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 1728 : OptionalMaterialPropertyProxyBase(const std::string & name, const unsigned int state)
48 1728 : : _name(name), _state(state)
49 : {
50 1728 : }
51 1428 : 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 49636 : const GenericMaterialProperty<T, is_ad> & getGenericMaterialProperty(const std::string & name,
104 : const unsigned int state = 0)
105 : {
106 49636 : return getGenericMaterialProperty<T, is_ad>(name, _material_data, state);
107 : }
108 : template <typename T>
109 7958 : const MaterialProperty<T> & getMaterialProperty(const std::string & name,
110 : const unsigned int state = 0)
111 : {
112 7958 : return getGenericMaterialProperty<T, false>(name, state);
113 : }
114 : template <typename T>
115 3690 : const ADMaterialProperty<T> & getADMaterialProperty(const std::string & name)
116 : {
117 3690 : return getGenericMaterialProperty<T, true>(name, 0);
118 : }
119 : template <typename T>
120 114 : const MaterialProperty<T> & getMaterialPropertyOld(const std::string & name)
121 : {
122 114 : return getMaterialProperty<T>(name, 1);
123 : }
124 : template <typename T>
125 32 : const MaterialProperty<T> & getMaterialPropertyOlder(const std::string & name)
126 : {
127 32 : 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 9560 : getGenericMaterialPropertyByName(const MaterialPropertyName & name, const unsigned int state = 0)
142 : {
143 9560 : return getGenericMaterialPropertyByName<T, is_ad>(name, _material_data, state);
144 : }
145 : template <typename T>
146 217 : const MaterialProperty<T> & getMaterialPropertyByName(const MaterialPropertyName & name,
147 : const unsigned int state = 0)
148 : {
149 217 : return getGenericMaterialPropertyByName<T, false>(name, state);
150 : }
151 : template <typename T>
152 16 : const ADMaterialProperty<T> & getADMaterialPropertyByName(const MaterialPropertyName & name)
153 : {
154 16 : 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 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);
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 210 : Moose::Kokkos::MaterialProperty<T, dimension> getKokkosMaterialProperty(const std::string & name)
216 : {
217 210 : 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 12 : getKokkosMaterialPropertyOld(const std::string & name)
229 : {
230 12 : 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 12 : getKokkosMaterialPropertyOlder(const std::string & name)
242 : {
243 12 : 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 56 : const OptionalMaterialProperty<T> & getOptionalMaterialProperty(const std::string & name,
255 : const unsigned int state = 0)
256 : {
257 56 : return getGenericOptionalMaterialProperty<T, false>(name, state);
258 : }
259 : template <typename T>
260 28 : const OptionalADMaterialProperty<T> & getOptionalADMaterialProperty(const std::string & name)
261 : {
262 28 : return getGenericOptionalMaterialProperty<T, true>(name);
263 : }
264 :
265 : template <typename T>
266 14 : const OptionalMaterialProperty<T> & getOptionalMaterialPropertyOld(const std::string & name)
267 : {
268 14 : return getOptionalMaterialProperty<T>(name, 1);
269 : }
270 : template <typename T>
271 14 : const OptionalMaterialProperty<T> & getOptionalMaterialPropertyOlder(const std::string & name)
272 : {
273 14 : 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 : /**
292 : * Return a material property that is initialized to zero by default and does
293 : * not need to (but can) be declared by another material.
294 : */
295 : template <typename T, bool is_ad>
296 : const GenericMaterialProperty<T, is_ad> &
297 : getGenericZeroMaterialProperty(const std::string & name);
298 : template <typename T, bool is_ad>
299 : const GenericMaterialProperty<T, is_ad> &
300 : getGenericZeroMaterialPropertyByName(const std::string & prop_name);
301 :
302 : /**
303 : * Return a constant zero anonymous material property
304 : */
305 : template <typename T, bool is_ad>
306 : const GenericMaterialProperty<T, is_ad> & getGenericZeroMaterialProperty();
307 :
308 : /// for backwards compatibility
309 : template <typename T, typename... Ts>
310 : const MaterialProperty<T> & getZeroMaterialProperty(Ts... args)
311 : {
312 : return getGenericZeroMaterialProperty<T, false>(args...);
313 : }
314 :
315 : /**
316 : * Retrieve the block ids that the material property is defined
317 : * @param name The name of the material property
318 : * @return A vector the the block ids for the property
319 : */
320 : std::set<SubdomainID> getMaterialPropertyBlocks(const std::string & name);
321 :
322 : /**
323 : * Retrieve the block names that the material property is defined
324 : * @param name The name of the material property
325 : * @return A vector the the block names for the property
326 : */
327 : std::vector<SubdomainName> getMaterialPropertyBlockNames(const std::string & name);
328 :
329 : /**
330 : * Retrieve the boundary ids that the material property is defined
331 : * @param name The name of the material property
332 : * @return A vector the the boundary ids for the property
333 : */
334 : std::set<BoundaryID> getMaterialPropertyBoundaryIDs(const std::string & name);
335 :
336 : /**
337 : * Retrieve the boundary namess that the material property is defined
338 : * @param name The name of the material property
339 : * @return A vector the the boundary names for the property
340 : */
341 : std::vector<BoundaryName> getMaterialPropertyBoundaryNames(const std::string & name);
342 :
343 : /**
344 : * Check if block and boundary restrictions of a given material are compatible with the current
345 : * material. Error out otherwise.
346 : */
347 : void checkBlockAndBoundaryCompatibility(std::shared_ptr<MaterialBase> discrete);
348 :
349 : ///@{
350 : /**
351 : * Return a MaterialBase reference - usable for computing directly.
352 : *
353 : * @param name The name of the input parameter or explicit material name.
354 : * @param no_warn If true, suppress warning about retrieving the material
355 : * potentially during its calculation. If you don't know what this is/means,
356 : * then you don't need it.
357 : */
358 : MaterialBase & getMaterial(const std::string & name);
359 : MaterialBase & getMaterialByName(const std::string & name, bool no_warn = false);
360 : ///@}
361 :
362 : /// get a map of MaterialBase pointers for all material objects that this object depends on for each block
363 : std::unordered_map<SubdomainID, std::vector<MaterialBase *>>
364 : buildRequiredMaterials(bool allow_stateful = true);
365 :
366 : ///@{
367 : /**
368 : * Check if the material property exists
369 : * @param name the name of the property to query
370 : * @return true if the property exists, otherwise false
371 : */
372 : template <typename T>
373 : bool hasMaterialProperty(const std::string & name);
374 : template <typename T>
375 : bool hasMaterialPropertyByName(const std::string & name);
376 : template <typename T>
377 : bool hasADMaterialProperty(const std::string & name);
378 : template <typename T>
379 : bool hasADMaterialPropertyByName(const std::string & name);
380 : #ifdef MOOSE_KOKKOS_SCOPE
381 : template <typename T, unsigned int dimension = 0>
382 : bool hasKokkosMaterialProperty(const std::string & name);
383 : template <typename T, unsigned int dimension = 0>
384 : bool hasKokkosMaterialPropertyByName(const std::string & name);
385 : #endif
386 : ///@}
387 :
388 : ///@{ generic hasMaterialProperty helper
389 : template <typename T, bool is_ad>
390 4998 : bool hasGenericMaterialProperty(const std::string & name)
391 : {
392 : if constexpr (is_ad)
393 214 : return hasADMaterialProperty<T>(name);
394 : else
395 4784 : return hasMaterialProperty<T>(name);
396 : }
397 : template <typename T, bool is_ad>
398 1717 : bool hasGenericMaterialPropertyByName(const std::string & name)
399 : {
400 : if constexpr (is_ad)
401 56 : return hasADMaterialPropertyByName<T>(name);
402 : else
403 1661 : return hasMaterialPropertyByName<T>(name);
404 : }
405 : ///@}
406 :
407 : /**
408 : * Derived classes can declare whether or not they work with
409 : * stateful material properties. See, for example, DiracKernel. By
410 : * default, they are allowed.
411 : */
412 : void statefulPropertiesAllowed(bool);
413 :
414 : /**
415 : * Returns true if getMaterialProperty() has been called, false otherwise.
416 : */
417 367783 : virtual bool getMaterialPropertyCalled() const { return _get_material_property_called; }
418 :
419 : /**
420 : * Retrieve the set of material properties that _this_ object depends on.
421 : *
422 : * @return The IDs corresponding to the material properties that
423 : * MUST be reinited before evaluating this object
424 : */
425 16119265 : virtual const std::unordered_set<unsigned int> & getMatPropDependencies() const
426 : {
427 16119265 : return _material_property_dependencies;
428 : }
429 :
430 : /// resolve all optional properties
431 : virtual void resolveOptionalProperties();
432 :
433 : /**
434 : * Retrieve the generic property named "name" for the specified \p material_data at state \p state
435 : */
436 : template <typename T, bool is_ad>
437 : const GenericMaterialProperty<T, is_ad> & getGenericMaterialProperty(
438 : const std::string & name, MaterialData & material_data, const unsigned int state = 0);
439 :
440 : /**
441 : * Retrieve the property named "name" for the specified \p material_data
442 : *
443 : * \p state is the property state; 0 = current, 1 = old, 2 = older, etc.
444 : */
445 : template <typename T>
446 42 : const MaterialProperty<T> & getMaterialProperty(const std::string & name,
447 : MaterialData & material_data,
448 : const unsigned int state = 0)
449 : {
450 42 : return getGenericMaterialProperty<T, false>(name, material_data, state);
451 : }
452 :
453 : /**
454 : * Retrieve the AD property named "name" for the specified \p material_data
455 : *
456 : * \p state is the property state; 0 = current, 1 = old, 2 = older, etc.
457 : */
458 : template <typename T>
459 1474 : const ADMaterialProperty<T> & getADMaterialProperty(const std::string & name,
460 : MaterialData & material_data)
461 : {
462 1474 : return getGenericMaterialProperty<T, true>(name, material_data, 0);
463 : }
464 :
465 : /**
466 : * Retrieve the generic property named "name" without any deduction for the specified \p
467 : * material_data for state \p state
468 : */
469 : template <typename T, bool is_ad>
470 : const GenericMaterialProperty<T, is_ad> & getGenericMaterialPropertyByName(
471 : const MaterialPropertyName & name, MaterialData & material_data, const unsigned int state);
472 :
473 : /**
474 : * Retrieve the generic property named "prop_name" without any deduction for the specified \p
475 : * material_data for state \p state. This API allows the \p prop_name to be a constant, e.g. it
476 : * allows the possibility that \p prop_name is not a name at all
477 : */
478 : template <typename T, bool is_ad>
479 : const GenericMaterialProperty<T, is_ad> &
480 : getPossiblyConstantGenericMaterialPropertyByName(const MaterialPropertyName & prop_name,
481 : MaterialData & material_data,
482 : const unsigned int state);
483 :
484 : /**
485 : * Retrieve the property named "name" without any deduction for the specified \p material_data
486 : *
487 : * \p state is the property state; 0 = current, 1 = old, 2 = older, etc.
488 : */
489 : template <typename T>
490 14 : const MaterialProperty<T> & getMaterialPropertyByName(const MaterialPropertyName & name,
491 : MaterialData & material_data,
492 : const unsigned int state = 0)
493 : {
494 14 : return getGenericMaterialPropertyByName<T, false>(name, material_data, state);
495 : }
496 :
497 : /**
498 : * Retrieve the AD property named "name" without any deduction for the specified \q
499 : * material_data
500 : */
501 : template <typename T>
502 : const ADMaterialProperty<T> & getADMaterialPropertyByName(const MaterialPropertyName & name,
503 : MaterialData & material_data)
504 : {
505 : return getGenericMaterialPropertyByName<T, true>(name, material_data, 0);
506 : }
507 :
508 : /**
509 : * Retrieve the old property deduced from the name \p name for the specified \p material_data
510 : */
511 : template <typename T>
512 14 : const MaterialProperty<T> & getMaterialPropertyOld(const std::string & name,
513 : MaterialData & material_data)
514 : {
515 14 : return getMaterialProperty<T>(name, material_data, 1);
516 : }
517 :
518 : /**
519 : * Retrieve the older property deduced from the name \p name for the specified \p
520 : * material_data
521 : */
522 : template <typename T>
523 14 : const MaterialProperty<T> & getMaterialPropertyOlder(const std::string & name,
524 : MaterialData & material_data)
525 : {
526 14 : return getMaterialProperty<T>(name, material_data, 2);
527 : }
528 :
529 : /**
530 : * Retrieve the old property named \p name without any deduction for the specified \p
531 : * material_data
532 : */
533 : template <typename T>
534 : const MaterialProperty<T> & getMaterialPropertyOldByName(const MaterialPropertyName & name,
535 : MaterialData & material_data)
536 : {
537 : return getMaterialPropertyByName<T>(name, material_data, 1);
538 : }
539 :
540 : /**
541 : * Retrieve the older property named \p name without any deduction for the specified \p
542 : * material_data
543 : */
544 : template <typename T>
545 : const MaterialProperty<T> & getMaterialPropertyOlderByName(const MaterialPropertyName & name,
546 : MaterialData & material_data)
547 : {
548 : return getMaterialPropertyByName<T>(name, material_data, 2);
549 : }
550 :
551 : private:
552 : /// The MooseObject creating the MaterialPropertyInterface
553 : const MooseObject & _mi_moose_object;
554 :
555 : protected:
556 : /// Parameters of the object with this interface
557 : const InputParameters & _mi_params;
558 :
559 : /// The name of the object that this interface belongs to
560 : const std::string _mi_name;
561 :
562 : /// The "complete" name of the object that this interface belongs for material property output
563 : const MooseObjectName _mi_moose_object_name;
564 :
565 : /// Reference to the FEProblemBase class
566 : FEProblemBase & _mi_feproblem;
567 :
568 : /// Reference to the subproblem
569 : SubProblem & _mi_subproblem;
570 :
571 : /// Current threaded it
572 : const THREAD_ID _mi_tid;
573 :
574 : /// Whether the MOOSE object is a Kokkos object
575 : const bool _is_kokkos_object;
576 :
577 : /// The type of data
578 : const Moose::MaterialDataType _material_data_type;
579 :
580 : /// The material data class that stores properties
581 : MaterialData & _material_data;
582 :
583 : /**
584 : * A helper method for checking material properties
585 : * This method was required to avoid a compiler problem with the template
586 : * getMaterialProperty method
587 : */
588 : virtual void checkMaterialProperty(const std::string & name, const unsigned int state);
589 :
590 : /**
591 : * A proxy method for _mi_feproblem.markMatPropRequested(name)
592 : */
593 : void markMatPropRequested(const std::string &);
594 :
595 : /**
596 : * @return The name of the material property associated with name \p name.
597 : *
598 : * If \p name is the name of a material property parameter and the parameter is
599 : * valid, this will return the value of said parameter. Otherwise, it will just
600 : * return the name.
601 : */
602 : MaterialPropertyName getMaterialPropertyName(const std::string & name) const;
603 :
604 : /**
605 : * @return The default material property with the name \p name, if any.
606 : *
607 : * "Default" properties are properties whose default values are set from within
608 : * the name. That is, if we can cast \p name to a Real, _and_ the prop type is
609 : * a Real or RealVectorValue, we'll return said value.
610 : */
611 : ///@{
612 : template <typename T, bool is_ad>
613 : const GenericMaterialProperty<T, is_ad> *
614 : defaultGenericMaterialProperty(const std::string & name);
615 : template <typename T>
616 53 : const MaterialProperty<T> * defaultMaterialProperty(const std::string & name)
617 : {
618 53 : return defaultGenericMaterialProperty<T, false>(name);
619 : }
620 : template <typename T>
621 53 : const ADMaterialProperty<T> * defaultADMaterialProperty(const std::string & name)
622 : {
623 53 : return defaultGenericMaterialProperty<T, true>(name);
624 : }
625 : ///@}
626 :
627 : /**
628 : * Check and throw an error if the execution has progressed past the construction stage
629 : */
630 : void checkExecutionStage();
631 :
632 : /**
633 : * True by default. If false, this class throws an error if any of
634 : * the stateful material properties interfaces are used.
635 : */
636 : bool _stateful_allowed;
637 :
638 : /**
639 : * Initialized to false. Gets set to true when getMaterialProperty()
640 : * is called. Clients of this class can inquire whether getMaterialProperty()
641 : * has been called by calling getMaterialPropertyCalled().
642 : */
643 : bool _get_material_property_called;
644 :
645 : /// Storage vector for default properties
646 : std::vector<std::unique_ptr<PropertyValue>> _default_properties;
647 :
648 : /// The set of material properties (as given by their IDs) that _this_ object depends on
649 : std::unordered_set<unsigned int> _material_property_dependencies;
650 :
651 : const MaterialPropertyName _get_suffix;
652 :
653 : /// Use the interpolated state set up through the ProjectedStatefulMaterialStorageAction
654 : const bool _use_interpolated_state;
655 :
656 : ///@{ name suffixes for interpolated old and older properties
657 : static const std::string _interpolated_old;
658 : static const std::string _interpolated_older;
659 : ///@}
660 :
661 : private:
662 : /**
663 : * @returns The MaterialDataType given the interface's parameters
664 : */
665 : Moose::MaterialDataType getMaterialDataType(const std::set<BoundaryID> & boundary_ids) const;
666 :
667 : /*
668 : * A proxy method for _mi_feproblem.getMaxQps()
669 : */
670 : unsigned int getMaxQps() const;
671 :
672 : /*
673 : * A proxy method for _mi_feproblem.addConsumedPropertyName()
674 : */
675 : void addConsumedPropertyName(const MooseObjectName & obj_name, const std::string & prop_name);
676 :
677 : /// BoundaryRestricted flag
678 : const bool _mi_boundary_restricted;
679 :
680 : /// Storage for the block ids created by BlockRestrictable
681 : const std::set<SubdomainID> & _mi_block_ids;
682 :
683 : /// Storage for the boundary ids created by BoundaryRestrictable
684 : const std::set<BoundaryID> & _mi_boundary_ids;
685 :
686 : /// optional material properties
687 : std::vector<std::unique_ptr<OptionalMaterialPropertyProxyBase<MaterialPropertyInterface>>>
688 : _optional_property_proxies;
689 : };
690 :
691 : template <class M, typename T, bool is_ad>
692 : class OptionalMaterialPropertyProxy : public OptionalMaterialPropertyProxyBase<M>
693 : {
694 : public:
695 1728 : OptionalMaterialPropertyProxy(const std::string & name, const unsigned int state)
696 1728 : : OptionalMaterialPropertyProxyBase<M>(name, state)
697 : {
698 1728 : }
699 1728 : const GenericOptionalMaterialProperty<T, is_ad> & value() const { return _value; }
700 1728 : void resolve(M & mpi) override
701 : {
702 1728 : if (mpi.template hasGenericMaterialProperty<T, is_ad>(this->_name))
703 : {
704 : if constexpr (is_ad)
705 157 : if (this->_state > 0)
706 0 : mooseError("Non-current (state > 0) material properties are not available as AD");
707 :
708 750 : _value.set(&mpi.template getGenericMaterialProperty<T, is_ad>(this->_name, this->_state));
709 : }
710 1728 : }
711 :
712 : private:
713 : GenericOptionalMaterialProperty<T, is_ad> _value;
714 : };
715 :
716 : template <typename T, bool is_ad>
717 : const GenericMaterialProperty<T, is_ad> *
718 68973 : MaterialPropertyInterface::defaultGenericMaterialProperty(const std::string & name)
719 : {
720 : if constexpr (std::is_same_v<T, Real> || std::is_same_v<T, RealVectorValue>)
721 : {
722 37978 : std::istringstream ss(name);
723 : Real real_value;
724 :
725 : // check if the string parsed cleanly into a Real number
726 37978 : if (ss >> real_value && ss.eof())
727 : {
728 : using prop_type = GenericMaterialProperty<T, is_ad>;
729 :
730 9028 : const auto nqp = Moose::constMaxQpsPerElem;
731 : auto & property =
732 9028 : _default_properties.emplace_back(std::make_unique<prop_type>(default_property_id));
733 9028 : auto & T_property = static_cast<prop_type &>(*property);
734 :
735 9028 : T_property.resize(nqp);
736 9037028 : for (const auto qp : make_range(nqp))
737 9028000 : T_property[qp] = real_value;
738 :
739 9028 : return &T_property;
740 : }
741 37978 : }
742 :
743 59945 : return nullptr;
744 : }
745 :
746 : template <typename T>
747 : std::pair<const MaterialProperty<T> *, std::set<SubdomainID>>
748 : MaterialPropertyInterface::getBlockMaterialProperty(const MaterialPropertyName & name_in)
749 : {
750 : const auto name = _get_suffix.empty()
751 : ? static_cast<const std::string &>(name_in)
752 : : MooseUtils::join(std::vector<std::string>({name_in, _get_suffix}), "_");
753 :
754 : if (_mi_block_ids.empty())
755 : mooseError("getBlockMaterialProperty must be called by a block restrictable object");
756 :
757 : using pair_type = std::pair<const MaterialProperty<T> *, std::set<SubdomainID>>;
758 :
759 : if (!hasMaterialPropertyByName<T>(name))
760 : return pair_type(nullptr, {});
761 :
762 : // Call first so that the ID gets registered
763 : const auto & prop = _material_data.getProperty<T, false>(name, 0, _mi_moose_object);
764 : auto blocks = getMaterialPropertyBlocks(name);
765 : auto prop_blocks_pair = pair_type(&prop, std::move(blocks));
766 :
767 : _material_property_dependencies.insert(_material_data.getPropertyId(name));
768 :
769 : // Update consumed properties in MaterialPropertyDebugOutput
770 : addConsumedPropertyName(_mi_moose_object_name, name);
771 :
772 : return prop_blocks_pair;
773 : }
774 :
775 : template <typename T>
776 : bool
777 11457 : MaterialPropertyInterface::hasMaterialProperty(const std::string & name)
778 : {
779 : // Check if the supplied parameter is a valid input parameter key
780 11457 : const auto prop_name = getMaterialPropertyName(name);
781 22914 : return hasMaterialPropertyByName<T>(prop_name);
782 11457 : }
783 :
784 : template <typename T>
785 : bool
786 13118 : MaterialPropertyInterface::hasMaterialPropertyByName(const std::string & name_in)
787 : {
788 39354 : const auto name = _get_suffix.empty()
789 13118 : ? name_in
790 13118 : : MooseUtils::join(std::vector<std::string>({name_in, _get_suffix}), "_");
791 26236 : return _material_data.haveProperty<T>(name);
792 13118 : }
793 :
794 : template <typename T, bool is_ad>
795 : const GenericMaterialProperty<T, is_ad> &
796 0 : MaterialPropertyInterface::getGenericZeroMaterialProperty(const std::string & name)
797 : {
798 0 : const auto prop_name = getMaterialPropertyName(name);
799 0 : return getGenericZeroMaterialPropertyByName<T, is_ad>(prop_name);
800 0 : }
801 :
802 : template <typename T, bool is_ad>
803 : const GenericMaterialProperty<T, is_ad> &
804 1717 : MaterialPropertyInterface::getGenericZeroMaterialPropertyByName(const std::string & prop_name)
805 : {
806 : // if found return the requested property
807 1717 : if (hasGenericMaterialPropertyByName<T, is_ad>(prop_name))
808 188 : return getGenericMaterialPropertyByName<T, is_ad>(prop_name);
809 :
810 1529 : return getGenericZeroMaterialProperty<T, is_ad>();
811 : }
812 :
813 : template <typename T, bool is_ad>
814 : const GenericMaterialProperty<T, is_ad> &
815 2077 : MaterialPropertyInterface::getGenericZeroMaterialProperty()
816 : {
817 : // static zero property storage
818 2077 : static GenericMaterialProperty<T, is_ad> zero(zero_property_id);
819 :
820 : // resize to accomodate maximum number of qpoints
821 : // (in multiapp scenarios getMaxQps can return different values in each app; we need the max)
822 2077 : unsigned int nqp = getMaxQps();
823 2077 : if (nqp > zero.size())
824 1308 : zero.resize(nqp);
825 :
826 : // set values for all qpoints to zero
827 13410 : for (unsigned int qp = 0; qp < nqp; ++qp)
828 11333 : MathUtils::mooseSetToZero(zero[qp]);
829 :
830 2077 : return zero;
831 : }
832 :
833 : template <typename T>
834 : bool
835 300 : MaterialPropertyInterface::hasADMaterialProperty(const std::string & name)
836 : {
837 : // Check if the supplied parameter is a valid input parameter key
838 300 : const auto prop_name = getMaterialPropertyName(name);
839 600 : return hasADMaterialPropertyByName<T>(prop_name);
840 300 : }
841 :
842 : template <typename T>
843 : bool
844 356 : MaterialPropertyInterface::hasADMaterialPropertyByName(const std::string & name_in)
845 : {
846 1068 : const auto name = _get_suffix.empty()
847 356 : ? name_in
848 356 : : MooseUtils::join(std::vector<std::string>({name_in, _get_suffix}), "_");
849 712 : return _material_data.haveADProperty<T>(name);
850 356 : }
851 :
852 : template <typename T, bool is_ad>
853 : const GenericOptionalMaterialProperty<T, is_ad> &
854 984 : MaterialPropertyInterface::getGenericOptionalMaterialProperty(const std::string & name,
855 : const unsigned int state)
856 : {
857 984 : auto proxy = std::make_unique<OptionalMaterialPropertyProxy<MaterialPropertyInterface, T, is_ad>>(
858 : name, state);
859 984 : auto & optional_property = proxy->value();
860 984 : _optional_property_proxies.push_back(std::move(proxy));
861 984 : return optional_property;
862 984 : }
863 :
864 : template <typename T, bool is_ad>
865 : const GenericMaterialProperty<T, is_ad> &
866 53085 : MaterialPropertyInterface::getPossiblyConstantGenericMaterialPropertyByName(
867 : const MaterialPropertyName & prop_name, MaterialData & material_data, const unsigned int state)
868 : {
869 : // Check if it's just a constant
870 53085 : if (const auto * default_property = defaultGenericMaterialProperty<T, is_ad>(prop_name))
871 : {
872 7522 : _get_material_property_called = true;
873 7522 : return *default_property;
874 : }
875 :
876 45563 : if (state > 0 && !_stateful_allowed)
877 8 : mooseError("Stateful material properties not allowed for this object."
878 : " State ",
879 : state,
880 : " property for \"",
881 : prop_name,
882 : "\" was requested.");
883 :
884 45555 : return this->getGenericMaterialPropertyByName<T, is_ad>(prop_name, material_data, state);
885 : }
886 :
887 : template <typename T, bool is_ad>
888 : const GenericMaterialProperty<T, is_ad> &
889 53085 : MaterialPropertyInterface::getGenericMaterialProperty(const std::string & name,
890 : MaterialData & material_data,
891 : const unsigned int state)
892 : {
893 : // Check if the supplied parameter is a valid input parameter key
894 53085 : const auto prop_name = getMaterialPropertyName(name);
895 :
896 53085 : return getPossiblyConstantGenericMaterialPropertyByName<T, is_ad>(
897 106154 : prop_name, material_data, state);
898 53077 : }
899 :
900 : template <typename T, bool is_ad>
901 : const GenericMaterialProperty<T, is_ad> &
902 55491 : MaterialPropertyInterface::getGenericMaterialPropertyByName(const MaterialPropertyName & name_in,
903 : MaterialData & material_data,
904 : const unsigned int state)
905 : {
906 55491 : if (_is_kokkos_object)
907 0 : mooseError("Attempted to retrieve a standard MOOSE material property from a Kokkos object.");
908 :
909 55491 : if (_use_interpolated_state)
910 : {
911 504 : if (state == 1)
912 0 : return getGenericMaterialPropertyByName<T, is_ad>(
913 0 : name_in + _interpolated_old, material_data, 0);
914 504 : if (state == 2)
915 0 : return getGenericMaterialPropertyByName<T, is_ad>(
916 0 : name_in + _interpolated_older, material_data, 0);
917 : }
918 :
919 166473 : const auto name = _get_suffix.empty()
920 55491 : ? static_cast<const std::string &>(name_in)
921 55491 : : MooseUtils::join(std::vector<std::string>({name_in, _get_suffix}), "_");
922 :
923 55491 : checkExecutionStage();
924 55491 : checkMaterialProperty(name, state);
925 :
926 : // mark property as requested
927 55491 : markMatPropRequested(name);
928 :
929 : // Update the boolean flag.
930 55491 : _get_material_property_called = true;
931 :
932 : // Call first so that the ID gets registered
933 55491 : auto & prop = material_data.getProperty<T, is_ad>(name, state, _mi_moose_object);
934 :
935 : // Does the material data used here matter?
936 55475 : _material_property_dependencies.insert(material_data.getPropertyId(name));
937 :
938 55475 : if (state == 0)
939 50791 : addConsumedPropertyName(_mi_moose_object_name, name);
940 :
941 55475 : return prop;
942 55475 : }
943 :
944 : #ifdef MOOSE_KOKKOS_SCOPE
945 : template <typename T, unsigned int dimension>
946 : bool
947 : MaterialPropertyInterface::hasKokkosMaterialProperty(const std::string & name)
948 : {
949 : // Check if the supplied parameter is a valid input parameter key
950 : const auto prop_name = getMaterialPropertyName(name);
951 : return hasKokkosMaterialPropertyByName<T, dimension>(prop_name);
952 : }
953 :
954 : template <typename T, unsigned int dimension>
955 : bool
956 : MaterialPropertyInterface::hasKokkosMaterialPropertyByName(const std::string & name_in)
957 : {
958 : const auto name = _get_suffix.empty()
959 : ? name_in
960 : : MooseUtils::join(std::vector<std::string>({name_in, _get_suffix}), "_");
961 : return _material_data.haveKokkosProperty<T, dimension>(name);
962 : }
963 :
964 : template <typename T, unsigned int dimension, unsigned int state>
965 : Moose::Kokkos::MaterialProperty<T, dimension>
966 1129 : MaterialPropertyInterface::getKokkosMaterialPropertyByName(const std::string & prop_name)
967 : {
968 1129 : if (!_is_kokkos_object)
969 0 : mooseError("Attempted to retrieve a Kokkos material property from a standard MOOSE object.");
970 :
971 : if constexpr (std::is_same_v<T, Real>)
972 : {
973 1129 : std::istringstream ss(prop_name);
974 : Real value;
975 :
976 : // Check if the string parsed cleanly into a Real number
977 1129 : if (ss >> value && ss.eof())
978 0 : return Moose::Kokkos::MaterialProperty<T, dimension>(value);
979 1129 : }
980 :
981 1129 : checkExecutionStage();
982 1129 : checkMaterialProperty(prop_name, state);
983 :
984 : // Mark property as requested
985 1129 : markMatPropRequested(prop_name);
986 :
987 : // Update the boolean flag
988 1129 : _get_material_property_called = true;
989 :
990 : // Call first so that the ID gets registered
991 1129 : auto prop = _material_data.getKokkosProperty<T, dimension, state>(prop_name);
992 :
993 : // Does the material data used here matter?
994 1129 : _material_property_dependencies.insert(_material_data.getPropertyId(prop_name));
995 :
996 : if constexpr (state == 0)
997 357 : addConsumedPropertyName(_mi_moose_object_name, prop_name);
998 :
999 1129 : return prop;
1000 1129 : }
1001 : #endif
|