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 : // initQpStatefulProperties() and computeQpProperties() are intentionally hidden
13 : // but some compilers generate ugly warnings
14 :
15 : #if defined(__clang__)
16 : #pragma clang diagnostic push
17 : #pragma clang diagnostic ignored "-Woverloaded-virtual"
18 : #elif defined(__GNUC__) || defined(__GNUG__)
19 : #pragma GCC diagnostic push
20 : #pragma GCC diagnostic ignored "-Woverloaded-virtual"
21 : #endif
22 :
23 : #include "KokkosMaterialBase.h"
24 : #include "KokkosDatum.h"
25 :
26 : #include "Coupleable.h"
27 : #include "MaterialPropertyInterface.h"
28 :
29 : namespace Moose
30 : {
31 : namespace Kokkos
32 : {
33 :
34 : /**
35 : * The base class for a user to derive their own Kokkos materials.
36 : *
37 : * The polymorphic design of the original MOOSE is reproduced statically by leveraging the Curiously
38 : * Recurring Template Pattern (CRTP), a programming idiom that involves a class template inheriting
39 : * from a template instantiation of itself. When the user derives their Kokkos object from this
40 : * class, the inheritance structure will look like:
41 : *
42 : * class UserMaterial final : public Moose::Kokkos::Material<UserMaterial>
43 : *
44 : * It is important to note that the template argument should point to the last derived class.
45 : * Therefore, if the user wants to define a derived class that can be further inherited, the derived
46 : * class should be a class template as well. Otherwise, it is recommended to mark the derived class
47 : * as final to prevent its inheritence by mistake.
48 : *
49 : * The user is expected to define initQpStatefulProperties() and computeQpProperties() as inlined
50 : * public methods in their derived class (not virtual override). The signature of
51 : * computeQpProperties() expected to be defined in the derived class is as follows:
52 : *
53 : * @param qp The local quadrature point index
54 : * @param datum The Datum object of the current thread
55 : *
56 : * KOKKOS_FUNCTION void computeQpProperties(const unsigned int qp, Datum & datum) const;
57 : *
58 : * The signature of initQpStatefulProperties() can be found in the code below, and its definition in
59 : * the derived class is optional. If it is defined in the derived class, it will hide the default
60 : * definition in the base class.
61 : */
62 : template <typename Derived>
63 : class Material : public MaterialBase, public Coupleable, public MaterialPropertyInterface
64 : {
65 : public:
66 : static InputParameters validParams();
67 :
68 : /**
69 : * Constructor
70 : */
71 : Material(const InputParameters & parameters);
72 :
73 : /**
74 : * Copy constructor for parallel dispatch
75 : */
76 : Material(const Material & object);
77 :
78 : /**
79 : * Dispatch stateful material property initialization
80 : */
81 : virtual void initStatefulProperties(unsigned int) override;
82 : /**
83 : * Dispatch material property evaluation
84 : */
85 : virtual void computeProperties() override;
86 :
87 : /**
88 : * Default methods to prevent compile errors even when these methods were not defined in the
89 : * derived class
90 : */
91 : ///@{
92 : /**
93 : * Initialize stateful material properties on a quadrature point
94 : * @param qp The local quadrature point index
95 : * @param datum The Datum object of the current thread
96 : */
97 0 : KOKKOS_FUNCTION void initQpStatefulProperties(const unsigned int /* qp */,
98 : Datum & /* datum */) const
99 : {
100 0 : }
101 : ///@}
102 :
103 : /**
104 : * The parallel computation entry functions called by Kokkos
105 : */
106 : ///@{
107 : KOKKOS_FUNCTION void operator()(ElementInit, const ThreadID tid) const;
108 : KOKKOS_FUNCTION void operator()(SideInit, const ThreadID tid) const;
109 : KOKKOS_FUNCTION void operator()(NeighborInit, const ThreadID tid) const;
110 : KOKKOS_FUNCTION void operator()(ElementCompute, const ThreadID tid) const;
111 : KOKKOS_FUNCTION void operator()(SideCompute, const ThreadID tid) const;
112 : KOKKOS_FUNCTION void operator()(NeighborCompute, const ThreadID tid) const;
113 : ///@}
114 :
115 : protected:
116 : /**
117 : * Get a material property by property name for any state
118 : * @tparam T The property data type
119 : * @tparam dimension The property dimension
120 : * @tparam state The property state
121 : * @param prop_name_in The property name
122 : * @returns The material property
123 : */
124 : template <typename T, unsigned int dimension = 0, unsigned int state = 0>
125 : MaterialProperty<T, dimension> getKokkosMaterialPropertyByName(const std::string & prop_name_in);
126 : /**
127 : * Get an old material property by property name
128 : * @tparam T The property data type
129 : * @tparam dimension The property dimension
130 : * @param prop_name The property name
131 : * @returns The material property
132 : */
133 : template <typename T, unsigned int dimension = 0>
134 : MaterialProperty<T, dimension> getKokkosMaterialPropertyOldByName(const std::string & prop_name)
135 : {
136 : return getKokkosMaterialPropertyByName<T, dimension, 1>(prop_name);
137 : }
138 : /**
139 : * Get an older material property by property name
140 : * @tparam T The property data type
141 : * @tparam dimension The property dimension
142 : * @param prop_name The property name
143 : * @returns The material property
144 : */
145 : template <typename T, unsigned int dimension = 0>
146 : MaterialProperty<T, dimension> getKokkosMaterialPropertyOlderByName(const std::string & prop_name)
147 : {
148 : return getKokkosMaterialPropertyByName<T, dimension, 2>(prop_name);
149 : }
150 : /**
151 : * Get a material property for any state
152 : * @tparam T The property data type
153 : * @tparam dimension The property dimension
154 : * @tparam state The property state
155 : * @param name The property name or the parameter name containing the property name
156 : * @returns The material property
157 : */
158 : template <typename T, unsigned int dimension = 0, unsigned int state = 0>
159 123 : MaterialProperty<T, dimension> getKokkosMaterialProperty(const std::string & name)
160 : {
161 123 : return getKokkosMaterialPropertyByName<T, dimension, state>(getMaterialPropertyName(name));
162 : }
163 : /**
164 : * Get an old material property
165 : * @tparam T The property data type
166 : * @tparam dimension The property dimension
167 : * @param name The property name or the parameter name containing the property name
168 : * @returns The material property
169 : */
170 : template <typename T, unsigned int dimension = 0>
171 544 : MaterialProperty<T, dimension> getKokkosMaterialPropertyOld(const std::string & name)
172 : {
173 544 : return getKokkosMaterialPropertyByName<T, dimension, 1>(getMaterialPropertyName(name));
174 : }
175 : /**
176 : * Get an older material property
177 : * @tparam T The property data type
178 : * @tparam dimension The property dimension
179 : * @param name The property name or the parameter name containing the property name
180 : * @returns The material property
181 : */
182 : template <typename T, unsigned int dimension = 0>
183 204 : MaterialProperty<T, dimension> getKokkosMaterialPropertyOlder(const std::string & name)
184 : {
185 204 : return getKokkosMaterialPropertyByName<T, dimension, 2>(getMaterialPropertyName(name));
186 : }
187 :
188 871 : virtual void checkMaterialProperty(const std::string & name, const unsigned int state) override
189 : {
190 : // Avoid performing duplicate checks for triple block/face/neighbor materials
191 871 : if (boundaryRestricted() || !_bnd)
192 299 : MaterialPropertyInterface::checkMaterialProperty(name, state);
193 871 : }
194 :
195 1027 : virtual bool isBoundaryMaterial() const override { return _bnd; }
196 :
197 13318 : virtual const std::unordered_set<unsigned int> & getMatPropDependencies() const override
198 : {
199 13318 : return MaterialPropertyInterface::getMatPropDependencies();
200 : }
201 :
202 1064 : virtual const MaterialData & materialData() const override { return _material_data; }
203 2048 : virtual MaterialData & materialData() override { return _material_data; }
204 838 : virtual MaterialDataType materialDataType() override { return _material_data_type; }
205 :
206 : /**
207 : * Flag whether the material is on faces
208 : */
209 : const bool _bnd;
210 : /**
211 : * Flag whether the material is on neighbor faces
212 : */
213 : const bool _neighbor;
214 :
215 : private:
216 : /**
217 : * Flag whether initQpStatefulProperties() was not defined in the derived class
218 : */
219 : const bool _default_init;
220 :
221 : /**
222 : * Dummy members unused for Kokkos materials
223 : */
224 : ///@{
225 : const QBase * const & _qrule;
226 0 : virtual const QBase & qRule() const override { return *_qrule; }
227 : ///@}
228 : };
229 :
230 : template <typename Derived>
231 : InputParameters
232 128754 : Material<Derived>::validParams()
233 : {
234 128754 : InputParameters params = MaterialBase::validParams();
235 128754 : params += MaterialPropertyInterface::validParams();
236 386262 : params.addParamNamesToGroup("use_displaced_mesh", "Advanced");
237 128754 : return params;
238 0 : }
239 :
240 : template <typename Derived>
241 952 : Material<Derived>::Material(const InputParameters & parameters)
242 : : MaterialBase(parameters),
243 : Coupleable(this, false),
244 : MaterialPropertyInterface(this, blockIDs(), boundaryIDs()),
245 766 : _bnd(_material_data_type != Moose::BLOCK_MATERIAL_DATA),
246 766 : _neighbor(_material_data_type == Moose::NEIGHBOR_MATERIAL_DATA),
247 766 : _default_init(&Derived::initQpStatefulProperties == &Material::initQpStatefulProperties),
248 770 : _qrule(_bnd ? (_neighbor ? _subproblem.assembly(_tid, 0).qRuleNeighbor()
249 260 : : _subproblem.assembly(_tid, 0).qRuleFace())
250 766 : : _subproblem.assembly(_tid, 0).qRule())
251 : {
252 1108 : for (auto coupled_var : getCoupledMooseVars())
253 156 : addMooseVariableDependency(coupled_var);
254 952 : }
255 :
256 : template <typename Derived>
257 36803 : Material<Derived>::Material(const Material & object)
258 : : MaterialBase(object),
259 : Coupleable(object, {}),
260 : MaterialPropertyInterface(object, {}),
261 29790 : _bnd(object._bnd),
262 29790 : _neighbor(object._neighbor),
263 29790 : _default_init(object._default_init),
264 29790 : _qrule(object._qrule)
265 : {
266 36803 : }
267 :
268 : template <typename Derived>
269 : void
270 656 : Material<Derived>::initStatefulProperties(unsigned int)
271 : {
272 656 : if (_default_init)
273 142 : return;
274 :
275 514 : if (!_bnd && !_neighbor)
276 168 : ::Kokkos::parallel_for(
277 264 : ::Kokkos::RangePolicy<ElementInit, ExecSpace, ::Kokkos::IndexType<ThreadID>>(
278 : 0, numKokkosElements()),
279 : *static_cast<Derived *>(this));
280 346 : else if (_bnd && !_neighbor)
281 178 : ::Kokkos::parallel_for(
282 280 : ::Kokkos::RangePolicy<SideInit, ExecSpace, ::Kokkos::IndexType<ThreadID>>(
283 : 0, numKokkosElementSides()),
284 : *static_cast<Derived *>(this));
285 : else
286 168 : ::Kokkos::parallel_for(
287 264 : ::Kokkos::RangePolicy<NeighborInit, ExecSpace, ::Kokkos::IndexType<ThreadID>>(
288 : 0, numKokkosElementSides()),
289 : *static_cast<Derived *>(this));
290 :
291 1028 : ::Kokkos::fence();
292 : }
293 :
294 : template <typename Derived>
295 : void
296 36289 : Material<Derived>::computeProperties()
297 : {
298 36289 : if (!_bnd && !_neighbor)
299 11806 : ::Kokkos::parallel_for(
300 19110 : ::Kokkos::RangePolicy<ElementCompute, ExecSpace, ::Kokkos::IndexType<ThreadID>>(
301 : 0, numKokkosElements()),
302 : *static_cast<Derived *>(this));
303 24483 : else if (_bnd && !_neighbor)
304 12677 : ::Kokkos::parallel_for(
305 20552 : ::Kokkos::RangePolicy<SideCompute, ExecSpace, ::Kokkos::IndexType<ThreadID>>(
306 : 0, numKokkosElementSides()),
307 : *static_cast<Derived *>(this));
308 : else
309 11806 : ::Kokkos::parallel_for(
310 19110 : ::Kokkos::RangePolicy<NeighborCompute, ExecSpace, ::Kokkos::IndexType<ThreadID>>(
311 : 0, numKokkosElementSides()),
312 : *static_cast<Derived *>(this));
313 :
314 36289 : ::Kokkos::fence();
315 36289 : }
316 :
317 : template <typename Derived>
318 : KOKKOS_FUNCTION void
319 9352 : Material<Derived>::operator()(ElementInit, const ThreadID tid) const
320 : {
321 9352 : auto material = static_cast<const Derived *>(this);
322 9352 : auto elem = kokkosElementID(tid);
323 :
324 9352 : Datum datum(elem, kokkosAssembly(), kokkosSystems());
325 :
326 51368 : for (unsigned int qp = 0; qp < datum.n_qps(); qp++)
327 : {
328 42016 : datum.reinit();
329 42016 : material->initQpStatefulProperties(qp, datum);
330 : }
331 9352 : }
332 :
333 : template <typename Derived>
334 : KOKKOS_FUNCTION void
335 230 : Material<Derived>::operator()(SideInit, const ThreadID tid) const
336 : {
337 230 : auto material = static_cast<const Derived *>(this);
338 230 : auto [elem, side] = kokkosElementSideID(tid);
339 :
340 230 : Datum datum(elem, side, kokkosAssembly(), kokkosSystems());
341 :
342 690 : for (unsigned int qp = 0; qp < datum.n_qps(); qp++)
343 : {
344 460 : datum.reinit();
345 460 : material->initQpStatefulProperties(qp, datum);
346 : }
347 230 : }
348 :
349 : template <typename Derived>
350 : KOKKOS_FUNCTION void
351 170 : Material<Derived>::operator()(NeighborInit, const ThreadID tid) const
352 : {
353 170 : auto material = static_cast<const Derived *>(this);
354 170 : auto [elem, side] = kokkosElementSideID(tid);
355 :
356 170 : Datum datum(elem, side, kokkosAssembly(), kokkosSystems());
357 :
358 510 : for (unsigned int qp = 0; qp < datum.n_qps(); qp++)
359 : {
360 340 : datum.reinit();
361 340 : material->initQpStatefulProperties(qp, datum);
362 : }
363 170 : }
364 :
365 : template <typename Derived>
366 : KOKKOS_FUNCTION void
367 653476 : Material<Derived>::operator()(ElementCompute, const ThreadID tid) const
368 : {
369 653476 : auto material = static_cast<const Derived *>(this);
370 653476 : auto elem = kokkosElementID(tid);
371 :
372 653476 : Datum datum(elem, kokkosAssembly(), kokkosSystems());
373 :
374 3576884 : for (unsigned int qp = 0; qp < datum.n_qps(); qp++)
375 : {
376 2923408 : datum.reinit();
377 2923408 : material->computeQpProperties(qp, datum);
378 : }
379 653476 : }
380 :
381 : template <typename Derived>
382 : KOKKOS_FUNCTION void
383 27110 : Material<Derived>::operator()(SideCompute, const ThreadID tid) const
384 : {
385 27110 : auto material = static_cast<const Derived *>(this);
386 27110 : auto [elem, side] = kokkosElementSideID(tid);
387 :
388 27110 : Datum datum(elem, side, kokkosAssembly(), kokkosSystems());
389 :
390 81330 : for (unsigned int qp = 0; qp < datum.n_qps(); qp++)
391 : {
392 54220 : datum.reinit();
393 54220 : material->computeQpProperties(qp, datum);
394 : }
395 27110 : }
396 :
397 : template <typename Derived>
398 : KOKKOS_FUNCTION void
399 21930 : Material<Derived>::operator()(NeighborCompute, const ThreadID tid) const
400 : {
401 21930 : auto material = static_cast<const Derived *>(this);
402 21930 : auto [elem, side] = kokkosElementSideID(tid);
403 :
404 21930 : Datum datum(elem, side, kokkosAssembly(), kokkosSystems());
405 :
406 65790 : for (unsigned int qp = 0; qp < datum.n_qps(); qp++)
407 : {
408 43860 : datum.reinit();
409 43860 : material->computeQpProperties(qp, datum);
410 : }
411 21930 : }
412 :
413 : template <typename Derived>
414 : template <typename T, unsigned int dimension, unsigned int state>
415 : MaterialProperty<T, dimension>
416 871 : Material<Derived>::getKokkosMaterialPropertyByName(const std::string & prop_name_in)
417 : {
418 871 : MaterialBase::checkExecutionStage();
419 :
420 1565 : const auto prop_name =
421 694 : _get_suffix.empty()
422 694 : ? prop_name_in
423 694 : : MooseUtils::join(std::vector<std::string>({prop_name_in, _get_suffix}), "_");
424 :
425 : if constexpr (state == 0)
426 123 : _requested_props.insert(prop_name);
427 :
428 871 : auto prop =
429 : MaterialPropertyInterface::getKokkosMaterialPropertyByName<T, dimension, state>(prop_name);
430 :
431 871 : registerPropName(prop_name, true, state);
432 :
433 1742 : return prop;
434 871 : }
435 :
436 : } // namespace Kokkos
437 : } // namespace Moose
|