Line data Source code
1 : //* This file is part of the MOOSE framework
2 : //* https://www.mooseframework.org
3 : //*
4 : //* All rights reserved, see COPYRIGHT for full restrictions
5 : //* https://github.com/idaholab/moose/blob/master/COPYRIGHT
6 : //*
7 : //* Licensed under LGPL 2.1, please see LICENSE for details
8 : //* https://www.gnu.org/licenses/lgpl-2.1.html
9 :
10 : #pragma once
11 :
12 : #include "KokkosArray.h"
13 :
14 : #include "MoosePassKey.h"
15 :
16 : #include <typeindex>
17 :
18 : class MaterialBase;
19 :
20 : namespace Moose::Kokkos
21 : {
22 :
23 : class MaterialPropertyStorage;
24 :
25 : using StorageKey = Moose::PassKey<MaterialPropertyStorage>;
26 :
27 : template <typename T, unsigned int dimension>
28 : class MaterialPropertyValueBase;
29 :
30 : template <typename T, unsigned int dimension>
31 : class MaterialPropertyValue;
32 :
33 : class Datum;
34 : class Assembly;
35 : class Mesh;
36 :
37 : /**
38 : * Property constant options
39 : */
40 : enum class PropertyConstantOption
41 : {
42 : NONE,
43 : ELEMENT,
44 : SUBDOMAIN
45 : };
46 :
47 : /**
48 : * A structure storing the metadata of Kokkos material properties
49 : */
50 : struct PropRecord
51 : {
52 : /**
53 : * List of declaring materials
54 : */
55 : std::set<const ::MaterialBase *> declarers;
56 : /**
57 : * Property name
58 : */
59 : std::string name;
60 : /**
61 : * Demangled data type name
62 : */
63 : std::string type;
64 : /**
65 : * Property ID
66 : */
67 : unsigned int id = libMesh::invalid_uint;
68 : /**
69 : * Size of each dimension of each subdomain
70 : */
71 : std::unordered_map<SubdomainID, std::vector<unsigned int>> dims;
72 : /**
73 : * Flag whether this property is a face property
74 : */
75 : bool bnd = false;
76 : /**
77 : * Flag whether this property is an on-demand property
78 : */
79 : bool on_demand = false;
80 : /**
81 : * Whether this property is constant over element or subdomain in each subdomain
82 : */
83 : std::unordered_map<SubdomainID, PropertyConstantOption> constant_option;
84 : };
85 :
86 : using PropertyStore = std::function<void(std::ostream &, void *)>;
87 : using PropertyLoad = std::function<void(std::istream &, void *)>;
88 :
89 : /**
90 : * The base class for Kokkos material properties
91 : */
92 : class MaterialPropertyBase
93 : {
94 : public:
95 : /**
96 : * Default constructor
97 : */
98 235279 : MaterialPropertyBase() = default;
99 : /**
100 : * Desturctor
101 : */
102 234961 : virtual ~MaterialPropertyBase() {}
103 :
104 : /**
105 : * Get the property ID
106 : * @returns The property ID assigned by the MOOSE registry
107 : */
108 : unsigned int id() const { return _id; }
109 : /**
110 : * Get the property name
111 : * @returns The property name
112 : */
113 : const std::string & name() const;
114 : /**
115 : * Get the data type
116 : * @returns The demangled data type name
117 : */
118 : const std::string & type() const;
119 : /**
120 : * Get the dimension
121 : * @returns The dimension
122 : */
123 : unsigned int dim() const;
124 : /**
125 : * Get the size of a dimension
126 : * @param subdomain The MOOSE subdomain ID
127 : * @param i The dimension index
128 : * @returns The size of the dimension
129 : */
130 : unsigned int dimSize(SubdomainID subdomain, unsigned int i) const;
131 :
132 : /**
133 : * Get the property type index for load/store functions
134 : * @returns The property type index for the load/store function pointer map lookup
135 : */
136 : virtual std::type_index propertyType() = 0;
137 :
138 : /**
139 : * Initialize this property
140 : * @param record The record of this property
141 : */
142 : virtual void init(const PropRecord & record, const StorageKey &);
143 :
144 : /**
145 : * Allocate the data storage
146 : * @param mesh The Kokkos mesh
147 : * @param assembly The Kokkos assembly
148 : * @param subdomains The MOOSE subdomain IDs
149 : * @param bnd Whether this property is a face property
150 : */
151 : virtual void allocate(const Mesh & mesh,
152 : const Assembly & assembly,
153 : const std::set<SubdomainID> & subdomains,
154 : const bool bnd,
155 : StorageKey) = 0;
156 : /**
157 : * Deep copy another property
158 : * @param prop The property to copy
159 : */
160 : virtual void copy(const MaterialPropertyBase & prop, StorageKey) = 0;
161 : /**
162 : * Swap with another property
163 : * @param prop The property to swap
164 : */
165 : virtual void swap(MaterialPropertyBase & prop, StorageKey) = 0;
166 :
167 : protected:
168 : /**
169 : * Pointer to the record of this property
170 : */
171 : const PropRecord * _record = nullptr;
172 : /**
173 : * Property ID
174 : */
175 : unsigned int _id = libMesh::invalid_uint;
176 : /**
177 : * Flag whether this property has a default value
178 : */
179 : bool _default = false;
180 : /**
181 : * Whether this property is constant over element or subdomain in each subdomain
182 : */
183 : Array<PropertyConstantOption> _constant_option;
184 : };
185 :
186 : inline const std::string &
187 : MaterialPropertyBase::name() const
188 : {
189 : if (!_record)
190 : mooseError("Cannot get the name of an uninitialized or default material property.");
191 : else
192 : return _record->name;
193 : }
194 :
195 : inline const std::string &
196 2 : MaterialPropertyBase::type() const
197 : {
198 2 : if (!_record)
199 0 : mooseError("Cannot get the type of an uninitialized or default material property.");
200 : else
201 2 : return _record->type;
202 : }
203 :
204 : inline unsigned int
205 2 : MaterialPropertyBase::dim() const
206 : {
207 2 : if (!_record || !_record->dims.size())
208 0 : mooseError("Cannot get the dimension of an uninitialized or default material property.");
209 : else
210 2 : return _record->dims.begin()->second.size();
211 : }
212 :
213 : inline unsigned int
214 : MaterialPropertyBase::dimSize(SubdomainID subdomain, unsigned int i) const
215 : {
216 : const unsigned int D = dim();
217 :
218 : if (i >= D)
219 : mooseError("Cannot get the size of ",
220 : i,
221 : "-th dimension for the ",
222 : D,
223 : "D material property '",
224 : name(),
225 : "'.");
226 :
227 : return libmesh_map_find(_record->dims, subdomain)[i];
228 : }
229 :
230 : template <typename T, unsigned int dimension>
231 : void propertyStore(std::ostream & stream, void * prop);
232 : template <typename T, unsigned int dimension>
233 : void propertyLoad(std::istream & stream, void * prop);
234 :
235 : /**
236 : * The Kokkos material property class
237 : */
238 : template <typename T, unsigned int dimension = 0>
239 : class MaterialProperty final : public MaterialPropertyBase
240 : {
241 : public:
242 : /**
243 : * Default constructor
244 : */
245 9604 : MaterialProperty() = default;
246 : /**
247 : * Constructor for default property
248 : * @param value The default value
249 : */
250 : MaterialProperty(const T & value);
251 : /**
252 : * Copy constructor
253 : * The reference material properties are held by the material property storage, and the user deals
254 : * with the clones of them. The reference material properties also hold the arrays for storing the
255 : * property values (_data), and the user accesses the arrays through their shallow copies in the
256 : * clones. As a result, if the reference material properties reallocate their arrays, the shallow
257 : * copies of arrays in the clones will lose synchronization. Thus, the clones also hold the
258 : * pointers to their reference material properties and shallow copy them in the copy constructor,
259 : * so that the arrays are always synchronized with those in the reference material properties
260 : * during parallel dispatch.
261 : */
262 : MaterialProperty(const MaterialProperty<T, dimension> & property);
263 : /**
264 : * Prevent initializing with properties of different rank
265 : */
266 : template <unsigned int D>
267 : MaterialProperty(const MaterialProperty<T, D> & other) = delete;
268 :
269 : /**
270 : * Shallow copy another property
271 : * @param property The property to be shallow copied
272 : */
273 : auto & operator=(const MaterialProperty<T, dimension> & property);
274 :
275 : #ifdef MOOSE_KOKKOS_SCOPE
276 : /**
277 : * Get whether this property is valid
278 : * @returns Whether this property is valid
279 : */
280 251648 : KOKKOS_FUNCTION operator bool() const { return _data.isAlloc() || _default; }
281 :
282 : /**
283 : * Get the property values of a quadrature point
284 : * @param datum The Datum object of the current thread
285 : * @param qp The local quadrature point index
286 : * @returns The MaterialPropertyValue object that provides access to the property values
287 : */
288 : KOKKOS_FUNCTION MaterialPropertyValue<T, dimension> operator()(const Datum & datum,
289 : const unsigned int qp) const;
290 : #endif
291 :
292 3038 : virtual std::type_index propertyType() override
293 : {
294 3038 : static const std::type_index type = typeid(*this);
295 :
296 3038 : return type;
297 : }
298 :
299 : virtual void init(const PropRecord & record, const StorageKey & key) override;
300 :
301 : #ifdef MOOSE_KOKKOS_SCOPE
302 : virtual void allocate(const Mesh & mesh,
303 : const Assembly & assembly,
304 : const std::set<SubdomainID> & subdomains,
305 : const bool bnd,
306 : StorageKey) override;
307 : virtual void copy(const MaterialPropertyBase & prop, StorageKey) override;
308 : virtual void swap(MaterialPropertyBase & prop, StorageKey) override;
309 : #endif
310 :
311 : private:
312 : /**
313 : * Shallow copy another property
314 : * @param property The property to be shallow copied
315 : */
316 : void shallowCopy(const MaterialProperty<T, dimension> & property);
317 :
318 : /**
319 : * Pointer to the reference property
320 : */
321 : const MaterialProperty<T, dimension> * _reference = nullptr;
322 : /**
323 : * Data storage
324 : */
325 : Array<Array<T, dimension + 1>> _data;
326 : /**
327 : * Default value
328 : */
329 : T _value;
330 :
331 : friend class MaterialPropertyValueBase<T, dimension>;
332 :
333 : friend void propertyStore<T, dimension>(std::ostream &, void *);
334 : friend void propertyLoad<T, dimension>(std::istream &, void *);
335 : };
336 :
337 : // The Kokkos array containing Kokkos material properties requires a deep copy because the copy
338 : // constructor of each Kokkos material property should be invoked
339 : template <typename T, unsigned int dimension>
340 : struct ArrayDeepCopy<MaterialProperty<T, dimension>>
341 : {
342 : static constexpr bool value = true;
343 : };
344 :
345 : } // namespace Moose::Kokkos
|