Line data Source code
1 : //* This file is part of the MOOSE framework
2 : //* https://mooseframework.inl.gov
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 : #ifdef MOOSE_KOKKOS_ENABLED
13 : #include "KokkosMaterialPropertyStorage.h"
14 : #endif
15 :
16 : // MOOSE includes
17 : #include "MaterialProperty.h"
18 : #include "MooseTypes.h"
19 : #include "MaterialData.h"
20 : #include "MathUtils.h"
21 : #include "MooseObjectName.h"
22 : #include "InputParameters.h"
23 :
24 : #include <unordered_map>
25 :
26 : #define usingMaterialPropertyInterfaceMembers \
27 : using MaterialPropertyInterface::_material_data_type; \
28 : using MaterialPropertyInterface::_material_data
29 :
30 : // Forward declarations
31 : class MooseObject;
32 : class FEProblemBase;
33 : class SubProblem;
34 :
35 : /**
36 : * Helper class for deferred getting of material properties after the construction
37 : * phase for materials. This enables "optional material properties" in materials.
38 : * It works by returning a reference to a pointer to a material property (rather
39 : * than a reference to the property value). The pointer will be set to point to
40 : * either an existing material property or to nullptr if the requested property
41 : * does not exist.
42 : */
43 : template <class M>
44 : class OptionalMaterialPropertyProxyBase
45 : {
46 : public:
47 1566 : OptionalMaterialPropertyProxyBase(const std::string & name, const unsigned int state)
48 1566 : : _name(name), _state(state)
49 : {
50 1566 : }
51 1326 : virtual ~OptionalMaterialPropertyProxyBase() {}
52 : virtual void resolve(M & material) = 0;
53 :
54 : protected:
55 : const std::string _name;
56 : const unsigned int _state;
57 : };
58 :
59 : /**
60 : * \class MaterialPropertyInterface
61 : * \brief An interface for accessing Materials
62 : *
63 : * Any object that needs material properties should inherit this interface.
64 : * If your object is also restricted to blocks and/or boundaries via the
65 : * BlockRestrictable and/or BoundaryRestrictable class, then MaterialPropertyInterface
66 : * must be inherited following these two classes for the material property checks
67 : * to operate correctly.
68 : */
69 : class MaterialPropertyInterface
70 : {
71 : public:
72 : MaterialPropertyInterface(const MooseObject * moose_object,
73 : const std::set<SubdomainID> & block_ids,
74 : const std::set<BoundaryID> & boundary_ids);
75 :
76 : #ifdef MOOSE_KOKKOS_ENABLED
77 : /**
78 : * Special constructor used for Kokkos functor copy during parallel dispatch
79 : */
80 : MaterialPropertyInterface(const MaterialPropertyInterface & object,
81 : const Moose::Kokkos::FunctorCopy & key);
82 : #endif
83 :
84 : static InputParameters validParams();
85 :
86 : /// The material property ID for a default (parsed from input) property
87 : static constexpr PropertyValue::id_type default_property_id =
88 : PropertyValue::invalid_property_id - 1;
89 : /// The material property ID for a zero property
90 : static constexpr PropertyValue::id_type zero_property_id = PropertyValue::invalid_property_id - 2;
91 :
92 : ///@{
93 : /**
94 : * Retrieve reference to material property or one of it's old or older values.
95 : * The name required by this method is the name that is hard-coded into
96 : * your source code as the input parameter key. If no input parameter is found
97 : * this behaves like the getMaterialPropertyByName family as a fall back.
98 : * @param name The name of the parameter key of the material property to retrieve
99 : * @param state The state (current = 0, old = 1, older = 2)
100 : * @return Reference to the desired material property
101 : */
102 : template <typename T, bool is_ad>
103 46944 : const GenericMaterialProperty<T, is_ad> & getGenericMaterialProperty(const std::string & name,
104 : const unsigned int state = 0)
105 : {
106 46944 : return getGenericMaterialProperty<T, is_ad>(name, _material_data, state);
107 : }
108 : template <typename T>
109 5464 : const MaterialProperty<T> & getMaterialProperty(const std::string & name,
110 : const unsigned int state = 0)
111 : {
112 5464 : return getGenericMaterialProperty<T, false>(name, state);
113 : }
114 : template <typename T>
115 2501 : const ADMaterialProperty<T> & getADMaterialProperty(const std::string & name)
116 : {
117 2501 : return getGenericMaterialProperty<T, true>(name, 0);
118 : }
119 : template <typename T>
120 103 : const MaterialProperty<T> & getMaterialPropertyOld(const std::string & name)
121 : {
122 103 : return getMaterialProperty<T>(name, 1);
123 : }
124 : template <typename T>
125 29 : const MaterialProperty<T> & getMaterialPropertyOlder(const std::string & name)
126 : {
127 29 : return getMaterialProperty<T>(name, 2);
128 : }
129 : ///@}
130 :
131 : ///@{
132 : /**
133 : * Retrieve reference to material property or its old or older value
134 : * The name required by this method is the name defined in the input file.
135 : * @param name The name of the material property to retrieve
136 : * @param state The state (current = 0, old = 1, older = 2)
137 : * @return Reference to the material property with the name 'name'
138 : */
139 : template <typename T, bool is_ad>
140 : const GenericMaterialProperty<T, is_ad> &
141 9076 : getGenericMaterialPropertyByName(const MaterialPropertyName & name, const unsigned int state = 0)
142 : {
143 9076 : return getGenericMaterialPropertyByName<T, is_ad>(name, _material_data, state);
144 : }
145 : template <typename T>
146 191 : const MaterialProperty<T> & getMaterialPropertyByName(const MaterialPropertyName & name,
147 : const unsigned int state = 0)
148 : {
149 191 : return getGenericMaterialPropertyByName<T, false>(name, state);
150 : }
151 : template <typename T>
152 12 : const ADMaterialProperty<T> & getADMaterialPropertyByName(const MaterialPropertyName & name)
153 : {
154 12 : return getGenericMaterialPropertyByName<T, true>(name, 0);
155 : }
156 : template <typename T>
157 : const MaterialProperty<T> & getMaterialPropertyOldByName(const MaterialPropertyName & name)
158 : {
159 : return getMaterialPropertyByName<T>(name, 1);
160 : }
161 : template <typename T>
162 : const MaterialProperty<T> & getMaterialPropertyOlderByName(const MaterialPropertyName & name)
163 : {
164 : return getMaterialPropertyByName<T>(name, 2);
165 : }
166 : ///@}
167 :
168 : #ifdef MOOSE_KOKKOS_SCOPE
169 : /**
170 : * Get a Kokkos material property by property name for any state
171 : * @tparam T The property data type
172 : * @tparam dimension The property dimension
173 : * @tparam state The property state
174 : * @param prop_name_in The property name
175 : * @returns The Kokkos material property
176 : */
177 : template <typename T, unsigned int dimension = 0, unsigned int state = 0>
178 : Moose::Kokkos::MaterialProperty<T, dimension>
179 : getKokkosMaterialPropertyByName(const std::string & prop_name_in);
180 : /**
181 : * Get an old Kokkos material property by property name
182 : * @tparam T The property data type
183 : * @tparam dimension The property dimension
184 : * @param prop_name The property name
185 : * @returns The Kokkos material property
186 : */
187 : template <typename T, unsigned int dimension = 0>
188 : Moose::Kokkos::MaterialProperty<T, dimension>
189 : getKokkosMaterialPropertyOldByName(const std::string & prop_name)
190 : {
191 : return getKokkosMaterialPropertyByName<T, dimension, 1>(prop_name);
192 : }
193 : /**
194 : * Get an older Kokkos material property by property name
195 : * @tparam T The property data type
196 : * @tparam dimension The property dimension
197 : * @param prop_name The property name
198 : * @returns The Kokkos material property
199 : */
200 : template <typename T, unsigned int dimension = 0>
201 : Moose::Kokkos::MaterialProperty<T, dimension>
202 : getKokkosMaterialPropertyOlderByName(const std::string & prop_name)
203 : {
204 : return getKokkosMaterialPropertyByName<T, dimension, 2>(prop_name);
205 : }
206 : /**
207 : * Get a Kokkos material property for any state
208 : * @tparam T The property data type
209 : * @tparam dimension The property dimension
210 : * @tparam state The property state
211 : * @param name The property name or the parameter name containing the property name
212 : * @returns The Kokkos material property
213 : */
214 : template <typename T, unsigned int dimension = 0, unsigned int state = 0>
215 789 : Moose::Kokkos::MaterialProperty<T, dimension> getKokkosMaterialProperty(const std::string & name)
216 : {
217 789 : return getKokkosMaterialPropertyByName<T, dimension, state>(getMaterialPropertyName(name));
218 : }
219 : /**
220 : * Get an old Kokkos material property
221 : * @tparam T The property data type
222 : * @tparam dimension The property dimension
223 : * @param name The property name or the parameter name containing the property name
224 : * @returns The Kokkos material property
225 : */
226 : template <typename T, unsigned int dimension = 0>
227 : Moose::Kokkos::MaterialProperty<T, dimension>
228 709 : getKokkosMaterialPropertyOld(const std::string & name)
229 : {
230 709 : return getKokkosMaterialPropertyByName<T, dimension, 1>(getMaterialPropertyName(name));
231 : }
232 : /**
233 : * Get an older Kokkos material property
234 : * @tparam T The property data type
235 : * @tparam dimension The property dimension
236 : * @param name The property name or the parameter name containing the property name
237 : * @returns The Kokkos material property
238 : */
239 : template <typename T, unsigned int dimension = 0>
240 : Moose::Kokkos::MaterialProperty<T, dimension>
241 278 : getKokkosMaterialPropertyOlder(const std::string & name)
242 : {
243 278 : return getKokkosMaterialPropertyByName<T, dimension, 2>(getMaterialPropertyName(name));
244 : }
245 : #endif
246 :
247 : ///@{ Optional material property getters
248 : /// \p state is the property state; 0 = current, 1 = old, 2 = older, etc.
249 : template <typename T, bool is_ad>
250 : const GenericOptionalMaterialProperty<T, is_ad> &
251 : getGenericOptionalMaterialProperty(const std::string & name, const unsigned int state = 0);
252 :
253 : template <typename T>
254 52 : const OptionalMaterialProperty<T> & getOptionalMaterialProperty(const std::string & name,
255 : const unsigned int state = 0)
256 : {
257 52 : return getGenericOptionalMaterialProperty<T, false>(name, state);
258 : }
259 : template <typename T>
260 26 : const OptionalADMaterialProperty<T> & getOptionalADMaterialProperty(const std::string & name)
261 : {
262 26 : return getGenericOptionalMaterialProperty<T, true>(name);
263 : }
264 :
265 : template <typename T>
266 13 : const OptionalMaterialProperty<T> & getOptionalMaterialPropertyOld(const std::string & name)
267 : {
268 13 : return getOptionalMaterialProperty<T>(name, 1);
269 : }
270 : template <typename T>
271 13 : const OptionalMaterialProperty<T> & getOptionalMaterialPropertyOlder(const std::string & name)
272 : {
273 13 : return getOptionalMaterialProperty<T>(name, 2);
274 : }
275 : ///@}
276 :
277 : /**
278 : * Retrieve pointer to a material property with the mesh blocks where it is defined
279 : * The name required by this method is the name defined in the input file.
280 : * This function can be thought as the combination of getMaterialPropertyByName and
281 : * getMaterialPropertyBlocks.
282 : * It can be called after the action of all actions.
283 : * @param name The name of the material property to retrieve
284 : * @return Pointer to the material property with the name 'name' and the set of blocks where the
285 : * property is valid
286 : */
287 : template <typename T>
288 : std::pair<const MaterialProperty<T> *, std::set<SubdomainID>>
289 : getBlockMaterialProperty(const MaterialPropertyName & name);
290 :
291 : #ifdef MOOSE_KOKKOS_SCOPE
292 : /**
293 : * Retrieve a Kokkos material property with the mesh blocks where it is defined
294 : * NOTE: This is not a drop-in replacement of getBlockMaterialProperty(). Unlike the original API,
295 : * this function cannot be called after object construction
296 : * @tparam T The property data type
297 : * @tparam dimension The property dimension
298 : * @tparam state The property state
299 : * @param name The name of the material property to retrieve
300 : * @returns The Kokkos material property with the name 'name' and the set of blocks where the
301 : * property is valid
302 : */
303 : template <typename T, unsigned int dimension = 0, unsigned int state = 0>
304 : std::pair<Moose::Kokkos::MaterialProperty<T, dimension>, std::set<SubdomainID>>
305 : getKokkosBlockMaterialProperty(const MaterialPropertyName & name);
306 : #endif
307 :
308 : /**
309 : * Return a material property that is initialized to zero by default and does
310 : * not need to (but can) be declared by another material.
311 : */
312 : template <typename T, bool is_ad>
313 : const GenericMaterialProperty<T, is_ad> &
314 : getGenericZeroMaterialProperty(const std::string & name);
315 : template <typename T, bool is_ad>
316 : const GenericMaterialProperty<T, is_ad> &
317 : getGenericZeroMaterialPropertyByName(const std::string & prop_name);
318 :
319 : /**
320 : * Return a constant zero anonymous material property
321 : */
322 : template <typename T, bool is_ad>
323 : const GenericMaterialProperty<T, is_ad> & getGenericZeroMaterialProperty();
324 :
325 : /// for backwards compatibility
326 : template <typename T, typename... Ts>
327 : const MaterialProperty<T> & getZeroMaterialProperty(Ts... args)
328 : {
329 : return getGenericZeroMaterialProperty<T, false>(args...);
330 : }
331 :
332 : /**
333 : * Retrieve the block ids that the material property is defined
334 : * @param name The name of the material property
335 : * @return A vector the the block ids for the property
336 : */
337 : std::set<SubdomainID> getMaterialPropertyBlocks(const std::string & name);
338 :
339 : /**
340 : * Retrieve the block names that the material property is defined
341 : * @param name The name of the material property
342 : * @return A vector the the block names for the property
343 : */
344 : std::vector<SubdomainName> getMaterialPropertyBlockNames(const std::string & name);
345 :
346 : /**
347 : * Retrieve the boundary ids that the material property is defined
348 : * @param name The name of the material property
349 : * @return A vector the the boundary ids for the property
350 : */
351 : std::set<BoundaryID> getMaterialPropertyBoundaryIDs(const std::string & name);
352 :
353 : /**
354 : * Retrieve the boundary namess that the material property is defined
355 : * @param name The name of the material property
356 : * @return A vector the the boundary names for the property
357 : */
358 : std::vector<BoundaryName> getMaterialPropertyBoundaryNames(const std::string & name);
359 :
360 : /**
361 : * Check if block and boundary restrictions of a given material are compatible with the current
362 : * material. Error out otherwise.
363 : */
364 : void checkBlockAndBoundaryCompatibility(std::shared_ptr<MaterialBase> discrete);
365 :
366 : ///@{
367 : /**
368 : * Return a MaterialBase reference - usable for computing directly.
369 : *
370 : * @param name The name of the input parameter or explicit material name.
371 : * @param no_warn If true, suppress warning about retrieving the material
372 : * potentially during its calculation. If you don't know what this is/means,
373 : * then you don't need it.
374 : */
375 : MaterialBase & getMaterial(const std::string & name);
376 : MaterialBase & getMaterialByName(const std::string & name, bool no_warn = false);
377 : ///@}
378 :
379 : /// get a map of MaterialBase pointers for all material objects that this object depends on for each block
380 : std::unordered_map<SubdomainID, std::vector<MaterialBase *>>
381 : buildRequiredMaterials(bool allow_stateful = true);
382 :
383 : ///@{
384 : /**
385 : * Check if the material property exists
386 : * @param name the name of the property to query
387 : * @return true if the property exists, otherwise false
388 : */
389 : template <typename T>
390 : bool hasMaterialProperty(const std::string & name);
391 : template <typename T>
392 : bool hasMaterialPropertyByName(const std::string & name);
393 : template <typename T>
394 : bool hasADMaterialProperty(const std::string & name);
395 : template <typename T>
396 : bool hasADMaterialPropertyByName(const std::string & name);
397 : #ifdef MOOSE_KOKKOS_SCOPE
398 : template <typename T, unsigned int dimension = 0>
399 : bool hasKokkosMaterialProperty(const std::string & name);
400 : template <typename T, unsigned int dimension = 0>
401 : bool hasKokkosMaterialPropertyByName(const std::string & name);
402 : #endif
403 : ///@}
404 :
405 : ///@{ generic hasMaterialProperty helper
406 : template <typename T, bool is_ad>
407 4681 : bool hasGenericMaterialProperty(const std::string & name)
408 : {
409 : if constexpr (is_ad)
410 191 : return hasADMaterialProperty<T>(name);
411 : else
412 4490 : return hasMaterialProperty<T>(name);
413 : }
414 : template <typename T, bool is_ad>
415 1675 : bool hasGenericMaterialPropertyByName(const std::string & name)
416 : {
417 : if constexpr (is_ad)
418 52 : return hasADMaterialPropertyByName<T>(name);
419 : else
420 1623 : return hasMaterialPropertyByName<T>(name);
421 : }
422 : ///@}
423 :
424 : /**
425 : * Derived classes can declare whether or not they work with
426 : * stateful material properties. See, for example, DiracKernel. By
427 : * default, they are allowed.
428 : */
429 : void statefulPropertiesAllowed(bool);
430 :
431 : /**
432 : * Returns true if getMaterialProperty() has been called, false otherwise.
433 : */
434 325293 : virtual bool getMaterialPropertyCalled() const { return _get_material_property_called; }
435 :
436 : /**
437 : * Retrieve the set of material properties that _this_ object depends on.
438 : *
439 : * @return The IDs corresponding to the material properties that
440 : * MUST be reinited before evaluating this object
441 : */
442 14677891 : virtual const std::unordered_set<unsigned int> & getMatPropDependencies() const
443 : {
444 14677891 : return _material_property_dependencies;
445 : }
446 :
447 : /// resolve all optional properties
448 : virtual void resolveOptionalProperties();
449 :
450 : /**
451 : * Retrieve the generic property named "name" for the specified \p material_data at state \p state
452 : */
453 : template <typename T, bool is_ad>
454 : const GenericMaterialProperty<T, is_ad> & getGenericMaterialProperty(
455 : const std::string & name, MaterialData & material_data, const unsigned int state = 0);
456 :
457 : /**
458 : * Retrieve the property named "name" for the specified \p material_data
459 : *
460 : * \p state is the property state; 0 = current, 1 = old, 2 = older, etc.
461 : */
462 : template <typename T>
463 39 : const MaterialProperty<T> & getMaterialProperty(const std::string & name,
464 : MaterialData & material_data,
465 : const unsigned int state = 0)
466 : {
467 39 : return getGenericMaterialProperty<T, false>(name, material_data, state);
468 : }
469 :
470 : /**
471 : * Retrieve the AD property named "name" for the specified \p material_data
472 : *
473 : * \p state is the property state; 0 = current, 1 = old, 2 = older, etc.
474 : */
475 : template <typename T>
476 878 : const ADMaterialProperty<T> & getADMaterialProperty(const std::string & name,
477 : MaterialData & material_data)
478 : {
479 878 : return getGenericMaterialProperty<T, true>(name, material_data, 0);
480 : }
481 :
482 : /**
483 : * Retrieve the generic property named "name" without any deduction for the specified \p
484 : * material_data for state \p state
485 : */
486 : template <typename T, bool is_ad>
487 : const GenericMaterialProperty<T, is_ad> & getGenericMaterialPropertyByName(
488 : const MaterialPropertyName & name, MaterialData & material_data, const unsigned int state);
489 :
490 : /**
491 : * Retrieve the generic property named "prop_name" without any deduction for the specified \p
492 : * material_data for state \p state. This API allows the \p prop_name to be a constant, e.g. it
493 : * allows the possibility that \p prop_name is not a name at all
494 : */
495 : template <typename T, bool is_ad>
496 : const GenericMaterialProperty<T, is_ad> &
497 : getPossiblyConstantGenericMaterialPropertyByName(const MaterialPropertyName & prop_name,
498 : MaterialData & material_data,
499 : const unsigned int state);
500 :
501 : /**
502 : * Retrieve the property named "name" without any deduction for the specified \p material_data
503 : *
504 : * \p state is the property state; 0 = current, 1 = old, 2 = older, etc.
505 : */
506 : template <typename T>
507 13 : const MaterialProperty<T> & getMaterialPropertyByName(const MaterialPropertyName & name,
508 : MaterialData & material_data,
509 : const unsigned int state = 0)
510 : {
511 13 : return getGenericMaterialPropertyByName<T, false>(name, material_data, state);
512 : }
513 :
514 : /**
515 : * Retrieve the AD property named "name" without any deduction for the specified \q
516 : * material_data
517 : */
518 : template <typename T>
519 : const ADMaterialProperty<T> & getADMaterialPropertyByName(const MaterialPropertyName & name,
520 : MaterialData & material_data)
521 : {
522 : return getGenericMaterialPropertyByName<T, true>(name, material_data, 0);
523 : }
524 :
525 : /**
526 : * Retrieve the old property deduced from the name \p name for the specified \p material_data
527 : */
528 : template <typename T>
529 13 : const MaterialProperty<T> & getMaterialPropertyOld(const std::string & name,
530 : MaterialData & material_data)
531 : {
532 13 : return getMaterialProperty<T>(name, material_data, 1);
533 : }
534 :
535 : /**
536 : * Retrieve the older property deduced from the name \p name for the specified \p
537 : * material_data
538 : */
539 : template <typename T>
540 13 : const MaterialProperty<T> & getMaterialPropertyOlder(const std::string & name,
541 : MaterialData & material_data)
542 : {
543 13 : return getMaterialProperty<T>(name, material_data, 2);
544 : }
545 :
546 : /**
547 : * Retrieve the old property named \p name without any deduction for the specified \p
548 : * material_data
549 : */
550 : template <typename T>
551 : const MaterialProperty<T> & getMaterialPropertyOldByName(const MaterialPropertyName & name,
552 : MaterialData & material_data)
553 : {
554 : return getMaterialPropertyByName<T>(name, material_data, 1);
555 : }
556 :
557 : /**
558 : * Retrieve the older property named \p name without any deduction for the specified \p
559 : * material_data
560 : */
561 : template <typename T>
562 : const MaterialProperty<T> & getMaterialPropertyOlderByName(const MaterialPropertyName & name,
563 : MaterialData & material_data)
564 : {
565 : return getMaterialPropertyByName<T>(name, material_data, 2);
566 : }
567 :
568 : private:
569 : /// The MooseObject creating the MaterialPropertyInterface
570 : const MooseObject & _mi_moose_object;
571 :
572 : protected:
573 : /// Parameters of the object with this interface
574 : const InputParameters & _mi_params;
575 :
576 : /// The name of the object that this interface belongs to
577 : const std::string _mi_name;
578 :
579 : /// The "complete" name of the object that this interface belongs for material property output
580 : const MooseObjectName _mi_moose_object_name;
581 :
582 : /// Reference to the FEProblemBase class
583 : FEProblemBase & _mi_feproblem;
584 :
585 : /// Reference to the subproblem
586 : SubProblem & _mi_subproblem;
587 :
588 : /// Current threaded it
589 : const THREAD_ID _mi_tid;
590 :
591 : #ifdef MOOSE_KOKKOS_ENABLED
592 : /// Whether the MOOSE object is a Kokkos object
593 : const bool _is_kokkos_object;
594 : #endif
595 :
596 : /// The type of data
597 : const Moose::MaterialDataType _material_data_type;
598 :
599 : /// The material data class that stores properties
600 : MaterialData & _material_data;
601 :
602 : /**
603 : * A helper method for checking material properties
604 : * This method was required to avoid a compiler problem with the template
605 : * getMaterialProperty method
606 : */
607 : virtual void checkMaterialProperty(const std::string & name, const unsigned int state);
608 :
609 : #ifdef MOOSE_KOKKOS_ENABLED
610 : /**
611 : * A virtual method that can be overriden by Kokkos objects to insert additional operations in
612 : * getKokkosMaterialProperty
613 : * @param prop_name_in The property name
614 : * @param state The property state
615 : */
616 639 : virtual void getKokkosMaterialPropertyHook(const std::string & /* prop_name_in */,
617 : const unsigned int /* state */)
618 : {
619 639 : }
620 : #endif
621 :
622 : /**
623 : * A proxy method for _mi_feproblem.markMatPropRequested(name)
624 : */
625 : void markMatPropRequested(const std::string &);
626 :
627 : /**
628 : * @return The name of the material property associated with name \p name.
629 : *
630 : * If \p name is the name of a material property parameter and the parameter is
631 : * valid, this will return the value of said parameter. Otherwise, it will just
632 : * return the name.
633 : */
634 : MaterialPropertyName getMaterialPropertyName(const std::string & name) const;
635 :
636 : /**
637 : * @return The default material property with the name \p name, if any.
638 : *
639 : * "Default" properties are properties whose default values are set from within
640 : * the name. That is, if we can cast \p name to a Real, _and_ the prop type is
641 : * a Real or RealVectorValue, we'll return said value.
642 : */
643 : ///@{
644 : template <typename T, bool is_ad>
645 : const GenericMaterialProperty<T, is_ad> *
646 : defaultGenericMaterialProperty(const std::string & name);
647 : template <typename T>
648 49 : const MaterialProperty<T> * defaultMaterialProperty(const std::string & name)
649 : {
650 49 : return defaultGenericMaterialProperty<T, false>(name);
651 : }
652 : template <typename T>
653 49 : const ADMaterialProperty<T> * defaultADMaterialProperty(const std::string & name)
654 : {
655 49 : return defaultGenericMaterialProperty<T, true>(name);
656 : }
657 : ///@}
658 :
659 : /**
660 : * Check and throw an error if the execution has progressed past the construction stage
661 : */
662 : void checkExecutionStage();
663 :
664 : /**
665 : * True by default. If false, this class throws an error if any of
666 : * the stateful material properties interfaces are used.
667 : */
668 : bool _stateful_allowed;
669 :
670 : /**
671 : * Initialized to false. Gets set to true when getMaterialProperty()
672 : * is called. Clients of this class can inquire whether getMaterialProperty()
673 : * has been called by calling getMaterialPropertyCalled().
674 : */
675 : bool _get_material_property_called;
676 :
677 : /// Storage vector for default properties
678 : std::vector<std::unique_ptr<PropertyValue>> _default_properties;
679 :
680 : /// The set of material properties (as given by their IDs) that _this_ object depends on
681 : std::unordered_set<unsigned int> _material_property_dependencies;
682 :
683 : const MaterialPropertyName _get_suffix;
684 :
685 : /// Use the interpolated state set up through the ProjectedStatefulMaterialStorageAction
686 : const bool _use_interpolated_state;
687 :
688 : ///@{ name suffixes for interpolated old and older properties
689 : static const std::string _interpolated_old;
690 : static const std::string _interpolated_older;
691 : ///@}
692 :
693 : private:
694 : /**
695 : * @returns The MaterialDataType given the interface's parameters
696 : */
697 : Moose::MaterialDataType getMaterialDataType(const std::set<BoundaryID> & boundary_ids) const;
698 :
699 : /*
700 : * A proxy method for _mi_feproblem.getMaxQps()
701 : */
702 : unsigned int getMaxQps() const;
703 :
704 : /*
705 : * A proxy method for _mi_feproblem.addConsumedPropertyName()
706 : */
707 : void addConsumedPropertyName(const MooseObjectName & obj_name, const std::string & prop_name);
708 :
709 : /// BoundaryRestricted flag
710 : const bool _mi_boundary_restricted;
711 :
712 : /// Storage for the block ids created by BlockRestrictable
713 : const std::set<SubdomainID> & _mi_block_ids;
714 :
715 : /// Storage for the boundary ids created by BoundaryRestrictable
716 : const std::set<BoundaryID> & _mi_boundary_ids;
717 :
718 : /// optional material properties
719 : std::vector<std::unique_ptr<OptionalMaterialPropertyProxyBase<MaterialPropertyInterface>>>
720 : _optional_property_proxies;
721 : };
722 :
723 : template <class M, typename T, bool is_ad>
724 : class OptionalMaterialPropertyProxy : public OptionalMaterialPropertyProxyBase<M>
725 : {
726 : public:
727 1566 : OptionalMaterialPropertyProxy(const std::string & name, const unsigned int state)
728 1566 : : OptionalMaterialPropertyProxyBase<M>(name, state)
729 : {
730 1566 : }
731 1566 : const GenericOptionalMaterialProperty<T, is_ad> & value() const { return _value; }
732 1566 : void resolve(M & mpi) override
733 : {
734 1566 : if (mpi.template hasGenericMaterialProperty<T, is_ad>(this->_name))
735 : {
736 : if constexpr (is_ad)
737 140 : if (this->_state > 0)
738 0 : mooseError("Non-current (state > 0) material properties are not available as AD");
739 :
740 672 : _value.set(&mpi.template getGenericMaterialProperty<T, is_ad>(this->_name, this->_state));
741 : }
742 1566 : }
743 :
744 : private:
745 : GenericOptionalMaterialProperty<T, is_ad> _value;
746 : };
747 :
748 : template <typename T, bool is_ad>
749 : const GenericMaterialProperty<T, is_ad> *
750 64363 : MaterialPropertyInterface::defaultGenericMaterialProperty(const std::string & name)
751 : {
752 : if constexpr (std::is_same_v<T, Real> || std::is_same_v<T, RealVectorValue>)
753 : {
754 34353 : std::istringstream ss(name);
755 : Real real_value;
756 :
757 : // check if the string parsed cleanly into a Real number
758 34353 : if (ss >> real_value && ss.eof())
759 : {
760 : using prop_type = GenericMaterialProperty<T, is_ad>;
761 :
762 7716 : const auto nqp = Moose::constMaxQpsPerElem;
763 : auto & property =
764 7716 : _default_properties.emplace_back(std::make_unique<prop_type>(default_property_id));
765 7716 : auto & T_property = static_cast<prop_type &>(*property);
766 :
767 7716 : T_property.resize(nqp);
768 7723716 : for (const auto qp : make_range(nqp))
769 7716000 : T_property[qp] = real_value;
770 :
771 7716 : return &T_property;
772 : }
773 34353 : }
774 :
775 56647 : return nullptr;
776 : }
777 :
778 : template <typename T>
779 : std::pair<const MaterialProperty<T> *, std::set<SubdomainID>>
780 : MaterialPropertyInterface::getBlockMaterialProperty(const MaterialPropertyName & name_in)
781 : {
782 : if (_mi_block_ids.empty())
783 : mooseError("getBlockMaterialProperty must be called by a block restrictable object");
784 :
785 : const auto name = _get_suffix.empty()
786 : ? static_cast<const std::string &>(name_in)
787 : : MooseUtils::join(std::vector<std::string>({name_in, _get_suffix}), "_");
788 :
789 : using pair_type = std::pair<const MaterialProperty<T> *, std::set<SubdomainID>>;
790 :
791 : if (!hasMaterialPropertyByName<T>(name))
792 : return pair_type(nullptr, {});
793 :
794 : // Call first so that the ID gets registered
795 : const auto & prop = _material_data.getProperty<T, false>(name, 0, _mi_moose_object);
796 : auto blocks = getMaterialPropertyBlocks(name);
797 : auto prop_blocks_pair = pair_type(&prop, std::move(blocks));
798 :
799 : _material_property_dependencies.insert(_material_data.getPropertyId(name));
800 :
801 : // Update consumed properties in MaterialPropertyDebugOutput
802 : addConsumedPropertyName(_mi_moose_object_name, name);
803 :
804 : return prop_blocks_pair;
805 : }
806 :
807 : template <typename T>
808 : bool
809 10692 : MaterialPropertyInterface::hasMaterialProperty(const std::string & name)
810 : {
811 : // Check if the supplied parameter is a valid input parameter key
812 10692 : const auto prop_name = getMaterialPropertyName(name);
813 21384 : return hasMaterialPropertyByName<T>(prop_name);
814 10692 : }
815 :
816 : template <typename T>
817 : bool
818 12315 : MaterialPropertyInterface::hasMaterialPropertyByName(const std::string & name_in)
819 : {
820 36945 : const auto name = _get_suffix.empty()
821 12315 : ? name_in
822 12315 : : MooseUtils::join(std::vector<std::string>({name_in, _get_suffix}), "_");
823 24630 : return _material_data.haveProperty<T>(name);
824 12315 : }
825 :
826 : template <typename T, bool is_ad>
827 : const GenericMaterialProperty<T, is_ad> &
828 0 : MaterialPropertyInterface::getGenericZeroMaterialProperty(const std::string & name)
829 : {
830 0 : const auto prop_name = getMaterialPropertyName(name);
831 0 : return getGenericZeroMaterialPropertyByName<T, is_ad>(prop_name);
832 0 : }
833 :
834 : template <typename T, bool is_ad>
835 : const GenericMaterialProperty<T, is_ad> &
836 1675 : MaterialPropertyInterface::getGenericZeroMaterialPropertyByName(const std::string & prop_name)
837 : {
838 : // if found return the requested property
839 1675 : if (hasGenericMaterialPropertyByName<T, is_ad>(prop_name))
840 231 : return getGenericMaterialPropertyByName<T, is_ad>(prop_name);
841 :
842 1444 : return getGenericZeroMaterialProperty<T, is_ad>();
843 : }
844 :
845 : template <typename T, bool is_ad>
846 : const GenericMaterialProperty<T, is_ad> &
847 1951 : MaterialPropertyInterface::getGenericZeroMaterialProperty()
848 : {
849 : // static zero property storage
850 1951 : static GenericMaterialProperty<T, is_ad> zero(zero_property_id);
851 :
852 : // resize to accomodate maximum number of qpoints
853 : // (in multiapp scenarios getMaxQps can return different values in each app; we need the max)
854 1951 : unsigned int nqp = getMaxQps();
855 1951 : if (nqp > zero.size())
856 1207 : zero.resize(nqp);
857 :
858 : // set values for all qpoints to zero
859 12605 : for (unsigned int qp = 0; qp < nqp; ++qp)
860 10654 : MathUtils::mooseSetToZero(zero[qp]);
861 :
862 1951 : return zero;
863 : }
864 :
865 : template <typename T>
866 : bool
867 339 : MaterialPropertyInterface::hasADMaterialProperty(const std::string & name)
868 : {
869 : // Check if the supplied parameter is a valid input parameter key
870 339 : const auto prop_name = getMaterialPropertyName(name);
871 678 : return hasADMaterialPropertyByName<T>(prop_name);
872 339 : }
873 :
874 : template <typename T>
875 : bool
876 391 : MaterialPropertyInterface::hasADMaterialPropertyByName(const std::string & name_in)
877 : {
878 1173 : const auto name = _get_suffix.empty()
879 391 : ? name_in
880 391 : : MooseUtils::join(std::vector<std::string>({name_in, _get_suffix}), "_");
881 782 : return _material_data.haveADProperty<T>(name);
882 391 : }
883 :
884 : template <typename T, bool is_ad>
885 : const GenericOptionalMaterialProperty<T, is_ad> &
886 906 : MaterialPropertyInterface::getGenericOptionalMaterialProperty(const std::string & name,
887 : const unsigned int state)
888 : {
889 906 : auto proxy = std::make_unique<OptionalMaterialPropertyProxy<MaterialPropertyInterface, T, is_ad>>(
890 : name, state);
891 906 : auto & optional_property = proxy->value();
892 906 : _optional_property_proxies.push_back(std::move(proxy));
893 906 : return optional_property;
894 906 : }
895 :
896 : template <typename T, bool is_ad>
897 : const GenericMaterialProperty<T, is_ad> &
898 49608 : MaterialPropertyInterface::getPossiblyConstantGenericMaterialPropertyByName(
899 : const MaterialPropertyName & prop_name, MaterialData & material_data, const unsigned int state)
900 : {
901 : // Check if it's just a constant
902 49608 : if (const auto * default_property = defaultGenericMaterialProperty<T, is_ad>(prop_name))
903 : {
904 6349 : _get_material_property_called = true;
905 6349 : return *default_property;
906 : }
907 :
908 43259 : if (state > 0 && !_stateful_allowed)
909 6 : mooseError("Stateful material properties not allowed for this object."
910 : " State ",
911 : state,
912 : " property for \"",
913 : prop_name,
914 : "\" was requested.");
915 :
916 43253 : return this->getGenericMaterialPropertyByName<T, is_ad>(prop_name, material_data, state);
917 : }
918 :
919 : template <typename T, bool is_ad>
920 : const GenericMaterialProperty<T, is_ad> &
921 49608 : MaterialPropertyInterface::getGenericMaterialProperty(const std::string & name,
922 : MaterialData & material_data,
923 : const unsigned int state)
924 : {
925 : // Check if the supplied parameter is a valid input parameter key
926 49608 : const auto prop_name = getMaterialPropertyName(name);
927 :
928 49608 : return getPossiblyConstantGenericMaterialPropertyByName<T, is_ad>(
929 99204 : prop_name, material_data, state);
930 49602 : }
931 :
932 : template <typename T, bool is_ad>
933 : const GenericMaterialProperty<T, is_ad> &
934 52709 : MaterialPropertyInterface::getGenericMaterialPropertyByName(const MaterialPropertyName & name_in,
935 : MaterialData & material_data,
936 : const unsigned int state)
937 : {
938 : #ifdef MOOSE_KOKKOS_ENABLED
939 39791 : if (_is_kokkos_object)
940 0 : _mi_moose_object.mooseError(
941 : "Attempted to retrieve a standard MOOSE material property from a Kokkos object.");
942 : #endif
943 :
944 52709 : if (_use_interpolated_state)
945 : {
946 468 : if (state == 1)
947 0 : return getGenericMaterialPropertyByName<T, is_ad>(
948 0 : name_in + _interpolated_old, material_data, 0);
949 468 : if (state == 2)
950 0 : return getGenericMaterialPropertyByName<T, is_ad>(
951 0 : name_in + _interpolated_older, material_data, 0);
952 : }
953 :
954 158127 : const auto name = _get_suffix.empty()
955 52709 : ? static_cast<const std::string &>(name_in)
956 52709 : : MooseUtils::join(std::vector<std::string>({name_in, _get_suffix}), "_");
957 :
958 52709 : checkExecutionStage();
959 52709 : checkMaterialProperty(name, state);
960 :
961 : // mark property as requested
962 52709 : markMatPropRequested(name);
963 :
964 : // Update the boolean flag.
965 52709 : _get_material_property_called = true;
966 :
967 : // Call first so that the ID gets registered
968 52709 : auto & prop = material_data.getProperty<T, is_ad>(name, state, _mi_moose_object);
969 :
970 : // Does the material data used here matter?
971 52697 : _material_property_dependencies.insert(material_data.getPropertyId(name));
972 :
973 52697 : if (state == 0)
974 48417 : addConsumedPropertyName(_mi_moose_object_name, name);
975 :
976 52697 : return prop;
977 52697 : }
978 :
979 : #ifdef MOOSE_KOKKOS_SCOPE
980 : template <typename T, unsigned int dimension>
981 : bool
982 : MaterialPropertyInterface::hasKokkosMaterialProperty(const std::string & name)
983 : {
984 : // Check if the supplied parameter is a valid input parameter key
985 : const auto prop_name = getMaterialPropertyName(name);
986 : return hasKokkosMaterialPropertyByName<T, dimension>(prop_name);
987 : }
988 :
989 : template <typename T, unsigned int dimension>
990 : bool
991 17 : MaterialPropertyInterface::hasKokkosMaterialPropertyByName(const std::string & name_in)
992 : {
993 35 : const auto name = _get_suffix.empty()
994 9 : ? name_in
995 9 : : MooseUtils::join(std::vector<std::string>({name_in, _get_suffix}), "_");
996 34 : return _material_data.haveKokkosProperty<T, dimension>(name);
997 17 : }
998 :
999 : template <typename T, unsigned int dimension, unsigned int state>
1000 : Moose::Kokkos::MaterialProperty<T, dimension>
1001 1924 : MaterialPropertyInterface::getKokkosMaterialPropertyByName(const std::string & prop_name_in)
1002 : {
1003 1924 : if (!_is_kokkos_object)
1004 0 : _mi_moose_object.mooseError(
1005 : "Attempted to retrieve a Kokkos material property from a standard MOOSE object.");
1006 :
1007 : if constexpr (std::is_same_v<T, Real>)
1008 : {
1009 1924 : std::istringstream ss(prop_name_in);
1010 : Real value;
1011 :
1012 : // Check if the string parsed cleanly into a Real number
1013 1924 : if (ss >> value && ss.eof())
1014 0 : return Moose::Kokkos::MaterialProperty<T, dimension>(value);
1015 1924 : }
1016 :
1017 3002 : const auto prop_name =
1018 1078 : _get_suffix.empty()
1019 1078 : ? static_cast<const std::string &>(prop_name_in)
1020 1078 : : MooseUtils::join(std::vector<std::string>({prop_name_in, _get_suffix}), "_");
1021 :
1022 1924 : checkExecutionStage();
1023 1924 : checkMaterialProperty(prop_name, state);
1024 :
1025 : // Mark property as requested
1026 1924 : markMatPropRequested(prop_name);
1027 :
1028 : // Update the boolean flag
1029 1924 : _get_material_property_called = true;
1030 :
1031 : // Call first so that the ID gets registered
1032 1924 : auto prop = _material_data.getKokkosProperty<T, dimension, state>(prop_name);
1033 :
1034 : // Does the material data used here matter?
1035 1924 : _material_property_dependencies.insert(_material_data.getPropertyId(prop_name));
1036 :
1037 : if constexpr (state == 0)
1038 937 : addConsumedPropertyName(_mi_moose_object_name, prop_name);
1039 :
1040 1924 : getKokkosMaterialPropertyHook(prop_name_in, state);
1041 :
1042 1924 : return prop;
1043 1924 : }
1044 :
1045 : template <typename T, unsigned int dimension, unsigned int state>
1046 : std::pair<Moose::Kokkos::MaterialProperty<T, dimension>, std::set<SubdomainID>>
1047 17 : MaterialPropertyInterface::getKokkosBlockMaterialProperty(const MaterialPropertyName & name_in)
1048 : {
1049 17 : if (!_is_kokkos_object)
1050 0 : _mi_moose_object.mooseError(
1051 : "Attempted to retrieve a Kokkos material property from a standard MOOSE object.");
1052 :
1053 17 : if (_mi_block_ids.empty())
1054 0 : mooseError("getKokkosBlockMaterialProperty must be called by a block restrictable object");
1055 :
1056 35 : const auto name = _get_suffix.empty()
1057 9 : ? static_cast<const std::string &>(name_in)
1058 9 : : MooseUtils::join(std::vector<std::string>({name_in, _get_suffix}), "_");
1059 :
1060 : using pair_type = std::pair<Moose::Kokkos::MaterialProperty<T, dimension>, std::set<SubdomainID>>;
1061 :
1062 17 : if (!hasKokkosMaterialPropertyByName<T, dimension>(name))
1063 0 : return pair_type(Moose::Kokkos::MaterialProperty<T, dimension>(), {});
1064 :
1065 17 : checkExecutionStage();
1066 :
1067 : // Mark property as requested
1068 17 : markMatPropRequested(name);
1069 :
1070 : // Call first so that the ID gets registered
1071 17 : auto prop = _material_data.getKokkosProperty<T, dimension, state>(name);
1072 17 : auto blocks = getMaterialPropertyBlocks(name);
1073 17 : auto prop_blocks_pair = pair_type(prop, std::move(blocks));
1074 :
1075 17 : _material_property_dependencies.insert(_material_data.getPropertyId(name));
1076 :
1077 : // Update consumed properties in MaterialPropertyDebugOutput
1078 : if constexpr (state == 0)
1079 17 : addConsumedPropertyName(_mi_moose_object_name, name);
1080 :
1081 17 : getKokkosMaterialPropertyHook(name_in, state);
1082 :
1083 17 : return prop_blocks_pair;
1084 17 : }
1085 : #endif
|