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 : #include "MaterialProperty.h"
13 : #include "Moose.h"
14 : #include "MooseUtils.h"
15 :
16 : // libMesh
17 : #include "libmesh/elem.h"
18 :
19 : #include <vector>
20 : #include <memory>
21 : #include <typeinfo>
22 :
23 : class MaterialPropertyStorage;
24 : class MooseObject;
25 : class Material;
26 : class XFEM;
27 : class MaterialBase;
28 :
29 : /**
30 : * Proxy for accessing MaterialPropertyStorage.
31 : * MaterialData stores the values associated with a particular material object
32 : */
33 : class MaterialData
34 : {
35 : public:
36 : MaterialData(MaterialPropertyStorage & storage, const THREAD_ID tid);
37 :
38 : /// The max time state supported (2 = older)
39 : static constexpr unsigned int max_state = 2;
40 :
41 : /**
42 : * Resize the data to hold properties for n_qpoints quadrature points.
43 : */
44 : void resize(unsigned int n_qpoints);
45 :
46 : /**
47 : * Returns the number of quadrature points the material properties
48 : * support/hold.
49 : */
50 68739570 : unsigned int nQPoints() const { return _n_qpoints; }
51 :
52 : /// copy material properties from one element to another
53 : void copy(const Elem & elem_to, const Elem & elem_from, unsigned int side);
54 :
55 : /// material properties for given element (and possible side)
56 : void swap(const Elem & elem, unsigned int side = 0);
57 :
58 : /**
59 : * Reinit material properties for given element (and possible side)
60 : * @param mats The material objects for which to compute properties
61 : * @param execute_stateful Whether to execute material objects that have stateful properties. This
62 : * should be \p false when for example executing material objects for mortar contexts in which
63 : * stateful properties don't make sense
64 : */
65 : template <typename MatContainer>
66 : void reinit(const MatContainer & mats);
67 :
68 : /// Calls the reset method of Materials to ensure that they are in a proper state.
69 : void reset(const std::vector<std::shared_ptr<MaterialBase>> & mats);
70 :
71 : /// material properties for given element (and possible side)
72 : void swapBack(const Elem & elem, unsigned int side = 0);
73 :
74 : /**
75 : * @returns The properties for the state \p state (defaults to zero).
76 : *
77 : * This should NEVER be used to modify the size of these objects.
78 : */
79 : ///{
80 : const MaterialProperties & props(const unsigned int state = 0) const;
81 : MaterialProperties & props(const unsigned int state = 0);
82 : ///@}
83 :
84 : template <typename T, bool is_ad>
85 : bool haveGenericProperty(const std::string & prop_name) const;
86 :
87 : /// Returns true if the regular material property exists - defined by any material.
88 : template <typename T>
89 41235 : bool haveProperty(const std::string & prop_name) const
90 : {
91 41235 : return haveGenericProperty<T, false>(prop_name);
92 : }
93 :
94 : /// Returns true if the AD material property exists - defined by any material.
95 : template <typename T>
96 20418 : bool haveADProperty(const std::string & prop_name) const
97 : {
98 20418 : return haveGenericProperty<T, true>(prop_name);
99 : }
100 :
101 : /**
102 : * Retrieves a material property
103 : * @tparam T The type of the property
104 : * @tparam is_ad Whether or not the property is AD
105 : * @param prop_name The name of the property
106 : * @param state The time state (0 = current, 1 = old, etc; defaults to 0)
107 : * @param requestor The MooseObject requesting the property
108 : * @return The property for the supplied type and name
109 : */
110 : template <typename T, bool is_ad = false>
111 60200 : GenericMaterialProperty<T, is_ad> & getProperty(const std::string & prop_name,
112 : const unsigned int state,
113 : const MooseObject & requestor)
114 : {
115 60200 : return getPropertyHelper<T, is_ad, false>(prop_name, state, requestor);
116 : }
117 : /**
118 : * Declares a material property
119 : * @tparam T The type of the property
120 : * @tparam is_ad Whether or not the property is AD
121 : * @param prop_name The name of the property
122 : * @param requestor The MooseObject declaring the property
123 : * @return The property for the supplied type and name
124 : */
125 : template <typename T, bool is_ad>
126 58673 : GenericMaterialProperty<T, is_ad> & declareProperty(const std::string & prop_name,
127 : const MooseObject & requestor)
128 : {
129 58673 : return getPropertyHelper<T, is_ad, true>(prop_name, 0, requestor);
130 : }
131 :
132 : /**
133 : * Returns true if the stateful material is in a swapped state.
134 : */
135 395102444 : bool isSwapped() const { return _swapped; }
136 :
137 : /**
138 : * Provide read-only access to the underlying MaterialPropertyStorage object.
139 : */
140 1365084 : const MaterialPropertyStorage & getMaterialPropertyStorage() const { return _storage; }
141 :
142 : /**
143 : * Key that provides access to only the XFEM class.
144 : */
145 : class XFEMKey
146 : {
147 : friend class XFEM;
148 : XFEMKey() {}
149 : XFEMKey(const XFEM &) {}
150 : };
151 :
152 : /**
153 : * Provide write-only access to the underlying MaterialPropertyStorage object JUST FOR XFEM.
154 : *
155 : * This should be removed. To be clear - you should not ever expect to have write access
156 : * to this data. It just turned out that XFEM got away with it when we were storing things
157 : * as pointers instead of smart pointers...
158 : *
159 : * These dirty reasons are why this method is named so egregiously.
160 : */
161 : MaterialPropertyStorage & getMaterialPropertyStorageForXFEM(const XFEMKey) { return _storage; }
162 :
163 : /**
164 : * @return Whether or not a property exists with the name \p name
165 : */
166 : bool hasProperty(const std::string & prop_name) const;
167 :
168 : /**
169 : * Wrapper for MaterialStorage::getPropertyId. Allows classes with a MaterialData object
170 : * (i.e. MaterialPropertyInterface) to access material property IDs.
171 : * @param prop_name The name of the material property
172 : *
173 : * @return An unsigned int corresponding to the property ID of the passed in prop_name
174 : */
175 : unsigned int getPropertyId(const std::string & prop_name) const;
176 :
177 : /**
178 : * Set _resize_only_if_smaller to perform a non-destructive resize. Setting this
179 : * flag to true means that resize(n) will not decrease the size of _props
180 : * if n is smaller than the size of the material data object.
181 : */
182 : void onlyResizeIfSmaller(bool flag) { _resize_only_if_smaller = flag; };
183 :
184 : /**
185 : * Check value of _resize_only_if_smaller
186 : */
187 570364 : bool isOnlyResizeIfSmaller() const { return _resize_only_if_smaller; };
188 :
189 : /**
190 : * Remove the property storage and element pointer from MaterialPropertyStorage data structures
191 : * Use this when elements are deleted so we don't end up with invalid elem pointers (for e.g.
192 : * stateful properties) hanging around in our data structures
193 : */
194 : void eraseProperty(const Elem * elem);
195 :
196 : private:
197 : /// Reference to the MaterialStorage class
198 : MaterialPropertyStorage & _storage;
199 :
200 : /// The thread id
201 : const THREAD_ID _tid;
202 :
203 : /// Number of quadrature points
204 : unsigned int _n_qpoints;
205 :
206 : /// The underlying property data
207 : std::array<MaterialProperties, max_state + 1> _props;
208 :
209 : unsigned int addPropertyHelper(const std::string & prop_name,
210 : const std::type_info & type,
211 : const unsigned int state,
212 : const MaterialBase * const declarer);
213 :
214 : template <typename T, bool is_ad, bool declare>
215 : GenericMaterialProperty<T, is_ad> & getPropertyHelper(const std::string & prop_name,
216 : const unsigned int state,
217 : const MooseObject & requestor);
218 :
219 : static void mooseErrorHelper(const MooseObject & object, const std::string_view & error);
220 :
221 : /**
222 : * Helper for casting \p requestor to a MaterialBase in addPropertyHelper() (templated)
223 : */
224 : const MaterialBase & castRequestorToDeclarer(const MooseObject & requestor) const;
225 :
226 : /// Status of storage swapping (calling swap sets this to true; swapBack sets it to false)
227 : bool _swapped;
228 :
229 : /// Use non-destructive resize of material data (calling resize() will not reduce size).
230 : /// Default is false (normal resize behaviour)
231 : bool _resize_only_if_smaller;
232 :
233 : /// maximum state id requested for a property
234 : unsigned int getMaxStateRequested(const unsigned int prop_id) const;
235 : };
236 :
237 : inline const MaterialProperties &
238 119126 : MaterialData::props(const unsigned int state) const
239 : {
240 : mooseAssert(_props.size() > state, "Invalid state");
241 119126 : return _props[state];
242 : }
243 :
244 : inline MaterialProperties &
245 38547581 : MaterialData::props(const unsigned int state)
246 : {
247 : mooseAssert(_props.size() > state, "Invalid state");
248 38547581 : return _props[state];
249 : }
250 :
251 : template <typename T, bool is_ad>
252 : inline bool
253 66670 : MaterialData::haveGenericProperty(const std::string & prop_name) const
254 : {
255 66670 : if (!hasProperty(prop_name))
256 6959 : return false;
257 :
258 59711 : const auto prop_id = getPropertyId(prop_name);
259 : // the property id exists, but the property was not created in this instance of the material type
260 59711 : if (prop_id >= props(0).size())
261 296 : return false;
262 :
263 59415 : const PropertyValue * const base_prop = props(0).queryValue(prop_id);
264 59415 : return dynamic_cast<const GenericMaterialProperty<T, is_ad> *>(base_prop) != nullptr;
265 : }
266 :
267 : template <typename T, bool is_ad, bool declare>
268 : GenericMaterialProperty<T, is_ad> &
269 118873 : MaterialData::getPropertyHelper(const std::string & prop_name,
270 : const unsigned int state,
271 : const MooseObject & requestor)
272 : {
273 : if constexpr (is_ad)
274 : mooseAssert(state == 0, "Cannot request/declare AD properties for states other than zero");
275 : if constexpr (declare)
276 : mooseAssert(state == 0, "Cannot declare properties for states other than zero");
277 :
278 : // Register/get the ID of the property
279 177546 : const auto prop_id = addPropertyHelper(
280 58673 : prop_name, typeid(T), state, declare ? &castRequestorToDeclarer(requestor) : nullptr);
281 118873 : const auto size = prop_id + 1;
282 :
283 : // Initialize the states that we need
284 245660 : for (const auto state_i : make_range(getMaxStateRequested(prop_id) + 1))
285 : {
286 126787 : auto & entry = props(state_i);
287 126787 : if (entry.size() < size)
288 58023 : entry.resize(size, {});
289 : // if we are not declaring the property we initialize only what we need (the requested state)
290 126787 : if (!entry.hasValue(prop_id) && (declare || state_i == state))
291 : {
292 57979 : if (state_i == 0)
293 108504 : entry.setPointer(
294 108504 : prop_id, std::move(std::make_unique<GenericMaterialProperty<T, is_ad>>(prop_id)), {});
295 : else
296 3727 : entry.setPointer(prop_id, std::move(std::make_unique<MaterialProperty<T>>(prop_id)), {});
297 : }
298 : }
299 :
300 : // Should be available now
301 118873 : auto & base_prop = props(state)[prop_id];
302 :
303 : // In the event that this property was already declared/requested, make sure
304 : // that the types are consistent
305 118873 : auto prop = dynamic_cast<GenericMaterialProperty<T, is_ad> *>(&base_prop);
306 118873 : if (!prop)
307 : {
308 16 : constexpr std::string_view action = declare ? "declared" : "requested";
309 16 : constexpr auto is_ad_to_str = [](const bool is_ad_bool)
310 16 : { return std::string_view(is_ad_bool ? "AD" : "non-AD"); };
311 16 : constexpr std::string_view ad_type = is_ad_to_str(is_ad);
312 :
313 16 : std::stringstream error;
314 : error << "The " << action << " " << ad_type << " "
315 : << "material property '" + prop_name + "' of type '" << MooseUtils::prettyCppType<T>()
316 32 : << "'\nis already retrieved or declared as a " << is_ad_to_str(base_prop.isAD())
317 16 : << " property of type '" << base_prop.type() << "'.";
318 16 : mooseErrorHelper(requestor, error.str());
319 0 : }
320 :
321 118857 : return *prop;
322 : }
323 :
324 : template <typename MatContainer>
325 : void
326 20527814 : MaterialData::reinit(const MatContainer & mats)
327 : {
328 49163406 : for (const auto & mat : mats)
329 28635659 : mat->computeProperties();
330 20527747 : }
|