www.mooseframework.org
MaterialPropertyStorage.C
Go to the documentation of this file.
1 //* This file is part of the MOOSE framework
2 //* https://www.mooseframework.org
3 //*
4 //* All rights reserved, see COPYRIGHT for full restrictions
5 //* https://github.com/idaholab/moose/blob/master/COPYRIGHT
6 //*
7 //* Licensed under LGPL 2.1, please see LICENSE for details
8 //* https://www.gnu.org/licenses/lgpl-2.1.html
9 
11 #include "MaterialProperty.h"
12 #include "Material.h"
13 #include "MaterialData.h"
14 #include "MooseMesh.h"
15 
16 #include "libmesh/fe_interface.h"
17 #include "libmesh/quadrature.h"
18 
19 std::map<std::string, unsigned int> MaterialPropertyStorage::_prop_ids;
20 
27 void
28 shallowCopyData(const std::vector<unsigned int> & stateful_prop_ids,
29  MaterialProperties & data,
30  MaterialProperties & data_from)
31 {
32  for (unsigned int i = 0; i < stateful_prop_ids.size(); ++i)
33  {
34  if (i >= data_from.size() || stateful_prop_ids[i] >= data.size())
35  continue;
36  PropertyValue * prop = data[stateful_prop_ids[i]]; // do the look-up just once (OPT)
37  PropertyValue * prop_from = data_from[i]; // do the look-up just once (OPT)
38  if (prop != nullptr && prop_from != nullptr)
39  prop->swap(prop_from);
40  }
41 }
42 
43 void
44 shallowCopyDataBack(const std::vector<unsigned int> & stateful_prop_ids,
45  MaterialProperties & data,
46  MaterialProperties & data_from)
47 {
48  for (unsigned int i = 0; i < stateful_prop_ids.size(); ++i)
49  {
50  if (i >= data.size() || stateful_prop_ids[i] >= data_from.size())
51  continue;
52  PropertyValue * prop = data[i]; // do the look-up just once (OPT)
53  PropertyValue * prop_from = data_from[stateful_prop_ids[i]]; // do the look-up just once (OPT)
54  if (prop != nullptr && prop_from != nullptr)
55  prop->swap(prop_from);
56  }
57 }
58 
60  : _has_stateful_props(false), _has_older_prop(false)
61 {
62  _props_elem =
63  libmesh_make_unique<HashMap<const Elem *, HashMap<unsigned int, MaterialProperties>>>();
65  libmesh_make_unique<HashMap<const Elem *, HashMap<unsigned int, MaterialProperties>>>();
67  libmesh_make_unique<HashMap<const Elem *, HashMap<unsigned int, MaterialProperties>>>();
68 }
69 
71 
72 void
74 {
75  for (auto & i : *_props_elem)
76  for (auto & j : i.second)
77  j.second.destroy();
78 
79  for (auto & i : *_props_elem_old)
80  for (auto & j : i.second)
81  j.second.destroy();
82 
83  for (auto & i : *_props_elem_older)
84  for (auto & j : i.second)
85  j.second.destroy();
86 }
87 
88 void
90  const std::vector<std::vector<QpMap>> & refinement_map,
91  const QBase & qrule,
92  const QBase & qrule_face,
93  MaterialPropertyStorage & parent_material_props,
94  MaterialData & child_material_data,
95  const Elem & elem,
96  const int input_parent_side,
97  const int input_child,
98  const int input_child_side)
99 {
100  mooseAssert(input_child != -1 || input_parent_side == input_child_side, "Invalid inputs!");
101 
102  unsigned int n_qpoints = 0;
103 
104  // If we passed in -1 for these then we really need to store properties at 0
105  unsigned int parent_side = input_parent_side == -1 ? 0 : input_parent_side;
106  unsigned int child_side = input_child_side == -1 ? 0 : input_child_side;
107 
108  if (input_child_side == -1) // Not doing side projection (ie, doing volume projection)
109  n_qpoints = qrule.n_points();
110  else
111  n_qpoints = qrule_face.n_points();
112 
113  child_material_data.resize(n_qpoints);
114 
115  unsigned int n_children = elem.n_children();
116 
117  std::vector<unsigned int> children;
118 
119  if (input_child != -1) // Passed in a child explicitly
120  children.push_back(input_child);
121  else
122  {
123  children.resize(n_children);
124  for (unsigned int child = 0; child < n_children; child++)
125  children[child] = child;
126  }
127 
128  for (const auto & child : children)
129  {
130  // If we're not projecting an internal child side, but we are projecting sides, see if this
131  // child is on that side
132  if (input_child == -1 && input_child_side != -1 && !elem.is_child_on_side(child, parent_side))
133  continue;
134 
135  const Elem * child_elem = elem.child_ptr(child);
136 
137  mooseAssert(child < refinement_map.size(), "Refinement_map vector not initialized");
138  const std::vector<QpMap> & child_map = refinement_map[child];
139 
140  initProps(child_material_data, *child_elem, child_side, n_qpoints);
141 
142  for (unsigned int i = 0; i < _stateful_prop_id_to_prop_id.size(); ++i)
143  {
144  // Copy from the parent stateful properties
145  for (unsigned int qp = 0; qp < refinement_map[child].size(); qp++)
146  {
147  PropertyValue * child_property = props(child_elem, child_side)[i];
148  mooseAssert(props().contains(&elem),
149  "Parent pointer is not in the MaterialProps data structure");
150  PropertyValue * parent_property = parent_material_props.props(&elem, parent_side)[i];
151 
152  child_property->qpCopy(qp, parent_property, child_map[qp]._to);
153  propsOld(child_elem, child_side)[i]->qpCopy(
154  qp, parent_material_props.propsOld(&elem, parent_side)[i], child_map[qp]._to);
155  if (hasOlderProperties())
156  propsOlder(child_elem, child_side)[i]->qpCopy(
157  qp, parent_material_props.propsOlder(&elem, parent_side)[i], child_map[qp]._to);
158  }
159  }
160  }
161 }
162 
163 void
165  const std::vector<std::pair<unsigned int, QpMap>> & coarsening_map,
166  const std::vector<const Elem *> & coarsened_element_children,
167  const QBase & qrule,
168  const QBase & qrule_face,
169  MaterialData & material_data,
170  const Elem & elem,
171  int input_side)
172 {
173  unsigned int side;
174 
175  bool doing_a_side = input_side != -1;
176 
177  unsigned int n_qpoints = 0;
178 
179  if (!doing_a_side)
180  {
181  side = 0; // Use 0 for the elem
182  n_qpoints = qrule.n_points();
183  }
184  else
185  {
186  side = input_side;
187  n_qpoints = qrule_face.n_points();
188  }
189 
190  initProps(material_data, elem, side, n_qpoints);
191 
192  // Copy from the child stateful properties
193  for (unsigned int qp = 0; qp < coarsening_map.size(); qp++)
194  {
195  const std::pair<unsigned int, QpMap> & qp_pair = coarsening_map[qp];
196  unsigned int child = qp_pair.first;
197 
198  mooseAssert(child < coarsened_element_children.size(),
199  "Coarsened element children vector not initialized");
200  const Elem * child_elem = coarsened_element_children[child];
201  const QpMap & qp_map = qp_pair.second;
202 
203  for (unsigned int i = 0; i < _stateful_prop_id_to_prop_id.size(); ++i)
204  {
205  mooseAssert(props().contains(child_elem),
206  "Child element pointer is not in the MaterialProps data structure");
207 
208  PropertyValue * child_property = props(child_elem, side)[i];
209  PropertyValue * parent_property = props(&elem, side)[i];
210 
211  parent_property->qpCopy(qp, child_property, qp_map._to);
212 
213  propsOld(&elem, side)[i]->qpCopy(qp, propsOld(child_elem, side)[i], qp_map._to);
214  if (hasOlderProperties())
215  propsOlder(&elem, side)[i]->qpCopy(qp, propsOlder(child_elem, side)[i], qp_map._to);
216  }
217  }
218 }
219 
220 void
222  const std::vector<std::shared_ptr<Material>> & mats,
223  unsigned int n_qpoints,
224  const Elem & elem,
225  unsigned int side /* = 0*/)
226 {
227  // NOTE: since materials are storing their computed properties in MaterialData class, we need to
228  // juggle the memory between MaterialData and MaterialProperyStorage classes
229 
230  initProps(material_data, elem, side, n_qpoints);
231 
232  // copy from storage to material data
233  swap(material_data, elem, side);
234  // run custom init on properties
235  for (const auto & mat : mats)
236  mat->initStatefulProperties(n_qpoints);
237 
238  swapBack(material_data, elem, side);
239 
240  if (!hasStatefulProperties())
241  return;
242 
243  // This second call to initProps covers cases where code in
244  // "init[Qp]StatefulProperties" may have called a get/declare for a stateful
245  // property affecting the _stateful_prop_id_to_prop_id vector among other
246  // things. This is necessary because a call to
247  // getMaterialProperty[Old/Older] can potentially trigger a material to
248  // become stateful that previously wasn't. This needs to go after the
249  // swapBack.
250  initProps(material_data, elem, side, n_qpoints);
251 
252  // Copy the properties to Old and Older as needed
253  for (unsigned int i = 0; i < _stateful_prop_id_to_prop_id.size(); ++i)
254  {
255  auto curr = props(&elem, side)[i];
256  auto old = propsOld(&elem, side)[i];
257  auto older = propsOlder(&elem, side)[i];
258  for (unsigned int qp = 0; qp < n_qpoints; ++qp)
259  {
260  old->qpCopy(qp, curr, qp);
261  if (hasOlderProperties())
262  older->qpCopy(qp, curr, qp);
263  }
264  }
265 }
266 
267 void
269 {
276  if (_has_older_prop)
278 
279  // Intentional fall through for case above and for handling just using old properties
281  if (fe_problem.usingADMatProps())
282  {
283  for (auto && elem_pair : (*_props_elem))
284  for (auto && side_pair : elem_pair.second)
285  for (auto && prop_value_ptr : side_pair.second)
286  prop_value_ptr->markAD(true);
287  for (auto && elem_pair : (*_props_elem_old))
288  for (auto && side_pair : elem_pair.second)
289  for (auto && prop_value_ptr : side_pair.second)
290  prop_value_ptr->markAD(false);
291  }
292 }
293 
294 void
296  const Elem & elem_to,
297  const Elem & elem_from,
298  unsigned int side,
299  unsigned int n_qpoints)
300 {
301  initProps(material_data, elem_to, side, n_qpoints);
302  for (unsigned int i = 0; i < _stateful_prop_id_to_prop_id.size(); ++i)
303  {
304  for (unsigned int qp = 0; qp < n_qpoints; ++qp)
305  {
306  props(&elem_to, side)[i]->qpCopy(qp, props(&elem_from, side)[i], qp);
307  propsOld(&elem_to, side)[i]->qpCopy(qp, propsOld(&elem_from, side)[i], qp);
308  if (hasOlderProperties())
309  propsOlder(&elem_to, side)[i]->qpCopy(qp, propsOlder(&elem_from, side)[i], qp);
310  }
311  }
312 }
313 
314 void
315 MaterialPropertyStorage::swap(MaterialData & material_data, const Elem & elem, unsigned int side)
316 {
317  Threads::spin_mutex::scoped_lock lock(Threads::spin_mtx);
318 
319  shallowCopyData(_stateful_prop_id_to_prop_id, material_data.props(), props(&elem, side));
320  shallowCopyData(_stateful_prop_id_to_prop_id, material_data.propsOld(), propsOld(&elem, side));
321  if (hasOlderProperties())
323  _stateful_prop_id_to_prop_id, material_data.propsOlder(), propsOlder(&elem, side));
324 }
325 
326 void
328  const Elem & elem,
329  unsigned int side)
330 {
331  Threads::spin_mutex::scoped_lock lock(Threads::spin_mtx);
332 
333  shallowCopyDataBack(_stateful_prop_id_to_prop_id, props(&elem, side), material_data.props());
335  _stateful_prop_id_to_prop_id, propsOld(&elem, side), material_data.propsOld());
336  if (hasOlderProperties())
338  _stateful_prop_id_to_prop_id, propsOlder(&elem, side), material_data.propsOlder());
339 }
340 
341 bool
342 MaterialPropertyStorage::hasProperty(const std::string & prop_name) const
343 {
344  return _prop_ids.count(prop_name) > 0;
345 }
346 
347 unsigned int
348 MaterialPropertyStorage::addProperty(const std::string & prop_name)
349 {
350  return getPropertyId(prop_name);
351 }
352 
353 unsigned int
354 MaterialPropertyStorage::addPropertyOld(const std::string & prop_name)
355 {
356  unsigned int prop_id = addProperty(prop_name);
357  _has_stateful_props = true;
358 
359  if (std::find(_stateful_prop_id_to_prop_id.begin(),
361  prop_id) == _stateful_prop_id_to_prop_id.end())
362  _stateful_prop_id_to_prop_id.push_back(prop_id);
363  _prop_names[prop_id] = prop_name;
364 
365  return prop_id;
366 }
367 
368 unsigned int
369 MaterialPropertyStorage::addPropertyOlder(const std::string & prop_name)
370 {
371  _has_older_prop = true;
372  return addPropertyOld(prop_name);
373 }
374 
375 unsigned int
376 MaterialPropertyStorage::getPropertyId(const std::string & prop_name)
377 {
378  auto it = _prop_ids.find(prop_name);
379  if (it != _prop_ids.end())
380  return it->second;
381 
382  auto id = _prop_ids.size();
383  _prop_ids[prop_name] = id;
384  return id;
385 }
386 
387 unsigned int
388 MaterialPropertyStorage::retrievePropertyId(const std::string & prop_name) const
389 {
390  auto it = _prop_ids.find(prop_name);
391  if (it == _prop_ids.end())
392  mooseError("MaterialPropertyStorage: property " + prop_name + " is not yet declared");
393  return it->second;
394 }
395 
396 void
398  const Elem & elem,
399  unsigned int side,
400  unsigned int n_qpoints)
401 {
402  material_data.resize(n_qpoints);
403  auto n = _stateful_prop_id_to_prop_id.size();
404 
405  if (props(&elem, side).size() < n)
406  props(&elem, side).resize(n, nullptr);
407  if (propsOld(&elem, side).size() < n)
408  propsOld(&elem, side).resize(n, nullptr);
409  if (propsOlder(&elem, side).size() < n)
410  propsOlder(&elem, side).resize(n, nullptr);
411 
412  // init properties (allocate memory. etc)
413  for (unsigned int i = 0; i < n; i++)
414  {
415  auto prop_id = _stateful_prop_id_to_prop_id[i];
416  // duplicate the stateful property in property storage (all three states - we will reuse the
417  // allocated memory there)
418  // also allocating the right amount of memory, so we do not have to resize, etc.
419  if (props(&elem, side)[i] == nullptr)
420  props(&elem, side)[i] = material_data.props()[prop_id]->init(n_qpoints);
421  if (propsOld(&elem, side)[i] == nullptr)
422  propsOld(&elem, side)[i] = material_data.propsOld()[prop_id]->init(n_qpoints);
423  if (hasOlderProperties() && propsOlder(&elem, side)[i] == nullptr)
424  propsOlder(&elem, side)[i] = material_data.propsOlder()[prop_id]->init(n_qpoints);
425  }
426 }
std::unique_ptr< HashMap< const Elem *, HashMap< unsigned int, MaterialProperties > > > _props_elem
void prolongStatefulProps(const std::vector< std::vector< QpMap >> &refinement_map, const QBase &qrule, const QBase &qrule_face, MaterialPropertyStorage &parent_material_props, MaterialData &child_material_data, const Elem &elem, const int input_parent_side, const int input_child, const int input_child_side)
Creates storage for newly created elements from mesh Adaptivity.
bool _has_stateful_props
Whether or not we have stateful properties.
virtual void swap(PropertyValue *rhs)=0
unsigned int addProperty(const std::string &prop_name)
The addProperty functions are idempotent - calling multiple times with the same name will provide the...
void initStatefulProps(MaterialData &material_data, const std::vector< std::shared_ptr< Material >> &mats, unsigned int n_qpoints, const Elem &elem, unsigned int side=0)
Initialize stateful material properties.
void mooseError(Args &&... args)
Emit an error message with the given stringified, concatenated args and terminate the application...
Definition: MooseError.h:207
Container for storing material properties.
unsigned int addPropertyOld(const std::string &prop_name)
void shallowCopyDataBack(const std::vector< unsigned int > &stateful_prop_ids, MaterialProperties &data, MaterialProperties &data_from)
HashMap< const Elem *, HashMap< unsigned int, MaterialProperties > > & propsOld()
Stores the stateful material properties computed by materials.
std::vector< unsigned int > _stateful_prop_id_to_prop_id
the vector of stateful property ids (the vector index is the map to stateful prop_id) ...
Helper object for holding qp mapping info.
Definition: MooseMesh.h:55
unsigned int addPropertyOlder(const std::string &prop_name)
unsigned int _to
The qp to map to.
Definition: MooseMesh.h:64
Specialization of SubProblem for solving nonlinear equations plus auxiliary equations.
virtual void qpCopy(const unsigned int to_qp, PropertyValue *rhs, const unsigned int from_qp)=0
Copy the value of a Property from one specific to a specific qp in this Property. ...
void copy(MaterialData &material_data, const Elem &elem_to, const Elem &elem_from, unsigned int side, unsigned int n_qpoints)
Copy material properties from elem_from to elem_to.
void usingADMatProps(bool using_ad_mat_props)
Set the global automatic differentiaion (AD) flag which indicates whether any consumer has requested ...
std::unique_ptr< HashMap< const Elem *, HashMap< unsigned int, MaterialProperties > > > _props_elem_old
void shift(const FEProblemBase &fe_problem)
Shift the material properties in time.
MaterialProperties & propsOld()
Definition: MaterialData.h:101
MaterialProperties & propsOlder()
Definition: MaterialData.h:102
void initProps(MaterialData &material_data, const Elem &elem, unsigned int side, unsigned int n_qpoints)
Initializes hashmap entries for element and side to proper qpoint and property count sizes...
unsigned int getPropertyId(const std::string &prop_name)
Returns the property ID for the given prop_name, adding the property and creating a new ID if it hasn...
HashMap< const Elem *, HashMap< unsigned int, MaterialProperties > > & propsOlder()
Abstract definition of a property value.
X_global swap(X_sys)
void swap(MaterialData &material_data, const Elem &elem, unsigned int side)
Swap (shallow copy) material properties in MaterialData and MaterialPropertyStorage Thread safe...
static std::map< std::string, unsigned int > _prop_ids
mapping from property name to property ID NOTE: this is static so the property numbering is global wi...
std::map< unsigned int, std::string > _prop_names
mapping from property ID to property name
void swapBack(MaterialData &material_data, const Elem &elem, unsigned int side)
Swap (shallow copy) material properties in MaterialPropertyStorage and MaterialDat Thread safe...
PetscInt n
unsigned int retrievePropertyId(const std::string &prop_name) const
HashMap< const Elem *, HashMap< unsigned int, MaterialProperties > > & props()
Access methods to the stored material property data.
bool hasProperty(const std::string &prop_name) const
bool _has_older_prop
True if any material requires older properties to be computed.
Proxy for accessing MaterialPropertyStorage.
Definition: MaterialData.h:27
void restrictStatefulProps(const std::vector< std::pair< unsigned int, QpMap >> &coarsening_map, const std::vector< const Elem *> &coarsened_element_children, const QBase &qrule, const QBase &qrule_face, MaterialData &material_data, const Elem &elem, int input_side=-1)
Creates storage for newly created elements from mesh Adaptivity.
std::unique_ptr< HashMap< const Elem *, HashMap< unsigned int, MaterialProperties > > > _props_elem_older
void shallowCopyData(const std::vector< unsigned int > &stateful_prop_ids, MaterialProperties &data, MaterialProperties &data_from)
Shallow copy the material properties.
MaterialProperties & props()
Methods for retrieving MaterialProperties object.
Definition: MaterialData.h:100
void resize(unsigned int n_qpoints)
Resize the data to hold properties for n_qpoints quadrature points.
Definition: MaterialData.C:29