18 #include "libmesh/fe_interface.h" 19 #include "libmesh/quadrature.h" 27 _restart_in_place(false),
41 if (stateful_prop_ids[i] < data.
size() && data.
hasValue(stateful_prop_ids[i]) &&
44 auto & prop = data[stateful_prop_ids[i]];
45 auto & prop_from = data_from[i];
56 if (stateful_prop_ids[i] < data_from.
size() && data.
hasValue(i) &&
57 data_from.
hasValue(stateful_prop_ids[i]))
59 auto & prop = data[i];
60 auto & prop_from = data_from[stateful_prop_ids[i]];
65 std::optional<std::string>
92 mooseAssert(prop_record_ptr,
"Not initialized");
93 return *prop_record_ptr;
100 if (!record.stateful())
101 mooseAssert(!record.restored,
"Stateful properties should not be restored");
108 const std::vector<QpMap> & p_refinement_map,
110 const QBase & qrule_face,
113 const int input_side)
115 unsigned int n_qpoints = 0;
118 unsigned int side = input_side == -1 ? 0 : input_side;
120 if (input_side == -1)
121 n_qpoints = qrule.n_points();
123 n_qpoints = qrule_face.n_points();
127 mooseAssert(elem.active(),
"We should be doing p-refinement on active elements only");
128 mooseAssert(elem.processor_id() == pid,
"Prolongation should be occurring locally");
129 mooseAssert(p_refinement_map.size() == n_qpoints,
"Refinement map not proper size");
131 auto current_p_level_props =
initProps(tid, &elem, side, n_qpoints);
136 auto & current_p_level_prop = (*current_p_level_props[state])[i];
139 auto previous_p_level_prop = current_p_level_prop.clone(current_p_level_prop.size());
143 previous_p_level_prop->swap(current_p_level_prop);
144 current_p_level_prop.resize(n_qpoints);
145 for (
const auto qp :
index_range(p_refinement_map))
146 current_p_level_prop.qpCopy(qp, *previous_p_level_prop, p_refinement_map[qp]._to);
153 const std::vector<std::vector<QpMap>> & refinement_map,
155 const QBase & qrule_face,
159 const int input_parent_side,
160 const int input_child,
161 const int input_child_side)
163 mooseAssert(input_child != -1 || input_parent_side == input_child_side,
"Invalid inputs!");
165 unsigned int n_qpoints = 0;
168 unsigned int parent_side = input_parent_side == -1 ? 0 : input_parent_side;
169 unsigned int child_side = input_child_side == -1 ? 0 : input_child_side;
171 if (input_child_side == -1)
172 n_qpoints = qrule.n_points();
174 n_qpoints = qrule_face.n_points();
178 unsigned int n_children = elem.n_children();
180 std::vector<unsigned int> children;
182 if (input_child != -1)
183 children.push_back(input_child);
186 children.resize(n_children);
187 for (
unsigned int child = 0; child < n_children; child++)
188 children[child] = child;
191 for (
const auto & child : children)
195 if (input_child == -1 && input_child_side != -1 && !elem.is_child_on_side(child, parent_side))
198 const Elem * child_elem = elem.child_ptr(child);
202 if (child_elem->processor_id() != pid)
205 mooseAssert(child < refinement_map.size(),
"Refinement_map vector not initialized");
206 const std::vector<QpMap> & child_map = refinement_map[child];
208 auto child_props =
initProps(tid, child_elem, child_side, n_qpoints);
212 const auto & parent_props = parent_material_props.
props(&elem, parent_side, state);
214 for (
const auto qp :
index_range(refinement_map[child]))
215 (*child_props[state])[i].qpCopy(qp, parent_props[i], child_map[qp]._to);
222 const std::vector<std::pair<unsigned int, QpMap>> & coarsening_map,
223 const std::vector<const Elem *> & coarsened_element_children,
225 const QBase & qrule_face,
232 bool doing_a_side = input_side != -1;
234 unsigned int n_qpoints = 0;
239 n_qpoints = qrule.n_points();
244 n_qpoints = qrule_face.n_points();
247 auto parent_props =
initProps(tid, &elem, side, n_qpoints);
252 const std::pair<unsigned int, QpMap> & qp_pair = coarsening_map[qp];
253 unsigned int child = qp_pair.first;
255 mooseAssert(child < coarsened_element_children.size(),
256 "Coarsened element children vector not initialized");
257 const Elem * child_elem = coarsened_element_children[child];
258 const QpMap & qp_map = qp_pair.second;
262 const auto & child_props =
props(child_elem, side, state);
264 (*parent_props[state])[i].qpCopy(qp, child_props[i], qp_map.
_to);
271 const std::vector<std::shared_ptr<MaterialBase>> & mats,
272 const unsigned int n_qpoints,
274 const unsigned int side )
280 std::vector<std::pair<unsigned int, std::vector<std::stringstream> *>>>
281 materials_to_restart;
284 RestartableMapType::mapped_type * restartable_entry =
nullptr;
287 restartable_entry = &it->second;
293 std::vector<MaterialBase *> stateful_mats;
295 std::vector<unsigned int> stateful_ids_to_copy;
300 std::set<unsigned int> stateful_ids;
305 for (
const auto & mat : mats)
308 bool stateful =
false;
311 for (
const auto id : mat->getSuppliedPropIDs())
314 if (record.stateful())
316 const auto stateful_id = record.stateful_id;
320 const auto it_inserted_pair = stateful_ids.insert(stateful_id);
321 mooseAssert(it_inserted_pair.second,
323 "' supplied by multiple materials at the same point");
326 bool restarting =
false;
328 if (restartable_entry)
330 if (
auto id_datum_pair_it = restartable_entry->find(stateful_id);
331 id_datum_pair_it != restartable_entry->end())
334 materials_to_restart[mat.get()].emplace_back(stateful_id, &id_datum_pair_it->second);
339 stateful_ids_to_copy.push_back(record.stateful_id);
343 if (stateful || mat->forceStatefulInit())
344 stateful_mats.push_back(mat.get());
355 bool swapped =
false;
358 for (
auto mat : stateful_mats)
360 const auto materials_to_restart_find = materials_to_restart.find(mat);
361 const bool restart = materials_to_restart_find != materials_to_restart.end();
363 if (!restart || mat->forceStatefulInit())
368 swap(tid, elem, side);
372 mat->initStatefulProperties(n_qpoints);
385 for (
auto & [stateful_id, datum_ptr] : materials_to_restart_find->second)
388 (*datum_ptr)[state].seekg(0, std::ios::beg);
389 dataLoad((*datum_ptr)[state], (*
props[state])[stateful_id],
nullptr);
399 for (
const auto stateful_id : stateful_ids_to_copy)
402 (*
props[state])[stateful_id].qpCopy(qp, (*
props[0])[stateful_id], qp);
416 for (
unsigned int state =
maxState(); state != 0; state--)
422 const Elem & elem_to,
423 const Elem & elem_from,
425 unsigned int n_qpoints)
427 copy(tid, &elem_to, &elem_from, side, n_qpoints);
432 const Elem * elem_to,
433 const Elem * elem_from,
435 unsigned int n_qpoints)
437 auto to_props =
initProps(tid, elem_to, side, n_qpoints);
441 const auto & from_props =
props(elem_from, side, state);
444 (*to_props[state])[i].qpCopy(qp, from_props[i], qp);
451 Threads::spin_mutex::scoped_lock lock(this->
_spin_mtx);
463 Threads::spin_mutex::scoped_lock lock(this->
_spin_mtx);
473 if (
props(&elem, side, state).empty())
479 const std::type_info & type,
480 const unsigned int state,
486 " is not supported. Max state supported: ",
504 record.type = type.name();
507 record.state =
std::max(state, record.state);
521 std::vector<MaterialProperties *>
525 unsigned int n_qpoints)
529 props[state] = &this->
initProps(tid, state, elem, side, n_qpoints);
535 const unsigned int state,
538 unsigned int n_qpoints)
541 material_data.resize(n_qpoints);
546 if (material_data.isOnlyResizeIfSmaller())
547 n_qpoints = material_data.nQPoints();
550 if (mat_props.size() < n_props)
551 mat_props.resize(n_props, {});
555 if (!mat_props.hasValue(i))
558 mat_props.setPointer(i, material_data.props(0)[prop_id].clone(n_qpoints), {});
559 mooseAssert(mat_props[i].
id() == prop_id,
"Inconsistent id");
570 std::vector<std::string> ids_to_names(registry.idsToNamesBegin(), registry.idsToNamesEnd());
571 dataStore(stream, ids_to_names,
nullptr);
589 for (
auto & elem_side_map_pair : storage.
setProps(state))
591 const Elem * elem = elem_side_map_pair.first;
592 mooseAssert(elem,
"Null element");
595 auto & side_map = elem_side_map_pair.second;
596 std::size_t num_sides = side_map.size();
599 for (
auto & [side, props] : side_map)
603 std::size_t num_props = props.size();
605 mooseAssert(num_props > 0,
"No properties");
607 std::size_t n_q_points = 0;
608 for (
const auto & entry : props)
609 if (entry.size() > n_q_points)
610 n_q_points = entry.size();
617 for (
auto & entry : props)
619 std::stringstream
out;
635 std::vector<std::string> from_prop_ids_to_names;
636 dataLoad(stream, from_prop_ids_to_names,
nullptr);
639 dataLoad(stream, from_stateful_prop_id_to_prop_id,
nullptr);
642 dataLoad(stream, from_prop_records,
nullptr);
644 decltype(storage.
numStates()) num_states;
645 dataLoad(stream, num_states,
nullptr);
649 const auto build_maps = [](
const auto & prop_records,
const auto & ids_to_names)
651 std::map<std::string, std::set<std::string>> object_to_props, prop_to_objects;
653 if (prop_records[i] && prop_records[i]->stateful())
655 const auto & prop = ids_to_names[i];
656 for (
const auto & declarer : (*prop_records[i]).declarers)
658 object_to_props[declarer].insert(prop);
659 prop_to_objects[prop].insert(declarer);
663 return std::make_pair(std::move(object_to_props), std::move(prop_to_objects));
666 const std::vector<std::string> prop_ids_to_names(registry.idsToNamesBegin(),
667 registry.idsToNamesEnd());
668 const auto [object_to_props, prop_to_objects] =
671 const auto [from_object_to_props, from_prop_to_objects] =
672 build_maps(from_prop_records, from_prop_ids_to_names);
675 for (
const auto & [
object, props] : object_to_props)
677 const auto find_from_object = from_object_to_props.find(
object);
683 if (find_from_object != from_object_to_props.end())
685 const auto & from_props = find_from_object->second;
686 if (props != from_props)
688 std::stringstream error;
689 error <<
"The stateful material properties in " <<
object 690 <<
" that are being restarted do not match the stored properties in the same " 691 "material object from the checkpoint.\n\n";
692 error <<
"Checkpointed stateful properties:\n";
693 for (
const auto & prop : from_props)
694 error <<
" - " << prop <<
"\n";
695 error <<
"\nCurrent stateful properties:\n";
696 for (
const auto & prop : props)
697 error <<
" - " << prop <<
"\n";
707 " was stored in restart but no longer exists. This is not supported when " 708 "recovering stateful material properties.");
717 for (
const auto & [from_prop, from_objects] : from_prop_to_objects)
718 if (
const auto find_objects = prop_to_objects.find(from_prop);
719 find_objects != prop_to_objects.end())
720 for (
const auto &
object : find_objects->second)
721 if (!from_objects.count(
object))
723 "The stateful material property '",
725 "' was declared in ",
727 " but was not declared in that object on checkpoint.\n\nThis is not currently " 728 "supported due to ambiguity.\n\nPlease contact the development team on " 729 "GitHub if you desire this capability.");
732 std::vector<std::optional<unsigned int>> to_stateful_ids(from_stateful_prop_id_to_prop_id.size());
737 for (
auto & record_ptr : to_prop_records)
739 record_ptr->restored =
false;
742 for (
const auto from_stateful_id :
index_range(from_stateful_prop_id_to_prop_id))
744 const auto from_prop_id = from_stateful_prop_id_to_prop_id[from_stateful_id];
746 mooseAssert(from_prop_id < from_prop_records.size(),
"Invalid record map");
747 mooseAssert(from_prop_records[from_prop_id],
"Not set");
748 const auto & from_record = *from_prop_records[from_prop_id];
749 mooseAssert(from_record.stateful(),
"Not stateful");
751 mooseAssert(from_prop_id < from_prop_ids_to_names.size(),
"Invalid ID map");
752 const auto &
name = from_prop_ids_to_names[from_prop_id];
754 if (
const auto query_to_prop_id = registry.queryID(
name))
756 const auto to_prop_id = *query_to_prop_id;
758 mooseAssert(to_prop_id < to_prop_records.size(),
"Invalid record map");
759 mooseAssert(to_prop_records[to_prop_id],
"Not set");
760 auto & to_record = *to_prop_records[to_prop_id];
762 if (to_record.stateful())
764 if (from_record.type != to_record.type)
766 "The type for the restarted stateful material property '",
name,
"' does not match");
771 if (from_record.state != to_record.state)
772 mooseError(
"The number of states for the restarted stateful material property '",
774 "' do not match.\n\n",
775 "Checkpointed states: ",
777 "\nCurrent states: ",
781 mooseAssert(to_stateful_id !=
invalid_uint,
"Not stateful");
783 to_stateful_ids[from_stateful_id] = to_stateful_id;
786 to_record.restored =
true;
790 mooseAssert(from_stateful_id == to_stateful_id,
"Does not have direct mapping");
796 for (
const auto state :
make_range(num_states))
798 std::size_t num_elems;
799 dataLoad(stream, num_elems,
nullptr);
801 for (std::size_t i_elem = 0; i_elem < num_elems; ++i_elem)
805 mooseAssert(elem,
"Null element");
807 std::size_t num_sides;
808 dataLoad(stream, num_sides,
nullptr);
810 for (std::size_t i_side = 0; i_side < num_sides; ++i_side)
815 std::size_t num_props;
816 dataLoad(stream, num_props,
nullptr);
817 mooseAssert(num_props <= to_stateful_ids.size(),
"Missized map");
819 std::size_t num_q_points;
820 dataLoad(stream, num_q_points,
nullptr);
823 MaterialPropertyStorage::RestartableMapType::mapped_type * restart_entry =
nullptr;
827 for (
const auto from_stateful_id :
make_range(num_props))
831 std::stringstream data;
833 data.seekg(0, std::ios::beg);
836 if (
const auto to_stateful_id_ptr = to_stateful_ids[from_stateful_id])
838 const auto to_stateful_id = *to_stateful_id_ptr;
844 in_place_entry = &storage.
setProps(elem, side, state);
846 dataLoad(data, (*in_place_entry)[to_stateful_id],
nullptr);
855 auto & mat_entry = (*restart_entry)[to_stateful_id];
856 if (state >= mat_entry.size())
857 mat_entry.resize(state + 1);
859 mat_entry[state] = std::move(data);
std::string name(const ElemQuality q)
MaterialProperties & setProps(const Elem *elem, unsigned int side, const unsigned int state=0)
void shift()
Shift the material properties in time.
std::vector< MaterialData > _material_data
The threaded material data.
const unsigned int invalid_uint
Registry class for material property IDs and names.
void mooseError(Args &&... args)
Emit an error message with the given stringified, concatenated args and terminate the application...
void eraseProperty(const Elem *elem)
Remove the property storage and element pointer from internal data structures Use this when elements ...
void swap(std::vector< T > &data, const std::size_t idx0, const std::size_t idx1, const libMesh::Parallel::Communicator &comm)
Swap function for serial or distributed vector of data.
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) ...
const MaterialPropertyRegistry & getMaterialPropertyRegistry() const
Helper object for holding qp mapping info.
libMesh::Threads::spin_mutex & _spin_mtx
std::vector< std::optional< PropRecord > > _prop_records
Property records indexed by property id (may be null)
The following methods are specializations for using the libMesh::Parallel::packed_range_* routines fo...
unsigned int maxState() const
bool restored
Whether or not this property was restored (stateful only)
static void shallowSwapData(const std::vector< unsigned int > &stateful_prop_ids, MaterialProperties &data, MaterialProperties &data_from)
Shallow copies of material properties.
static void shallowSwapDataBack(const std::vector< unsigned int > &stateful_prop_ids, MaterialProperties &data, MaterialProperties &data_from)
unsigned int _to
The qp to map to.
MaterialPropertyStorage(MaterialPropertyRegistry ®istry)
auto max(const L &left, const R &right)
uint8_t processor_id_type
void setRestartInPlace()
Sets the loading of stateful material properties in place.
void prolongStatefulProps(processor_id_type pid, const std::vector< std::vector< QpMap >> &refinement_map, const libMesh::QBase &qrule, const libMesh::QBase &qrule_face, MaterialPropertyStorage &parent_material_props, const THREAD_ID tid, 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.
libMesh::IntRange< unsigned int > stateIndexRange() const
void swapBack(const THREAD_ID tid, const Elem &elem, unsigned int side)
Swap (shallow copy) material properties in MaterialPropertyStorage and MaterialDat Thread safe...
std::optional< std::string > queryStatefulPropName(const unsigned int id) const
bool isRestoredProperty(const std::string &name) const
bool _recovering
Whether or not we're recovering; enforces a one-to-one mapping of stateful properties.
unsigned int numStates() const
unsigned int addProperty(const std::string &prop_name, const std::type_info &type, const unsigned int state, const MaterialBase *const declarer)
Adds a property with the name prop_name, type type, and state state (0 = current, 1 = old...
unsigned int addOrGetID(const std::string &name, const WriteKey)
unsigned int state
The max state requrested for this property (0 = current, 1 = old, ...)
std::string typeAndName() const
Get the class's combined type and name; useful in error handling.
static constexpr unsigned int max_state
The max time state supported (2 = older)
std::vector< MaterialProperties * > initProps(const THREAD_ID tid, const Elem *elem, unsigned int side, unsigned int n_qpoints)
Initializes hashmap entries for element and side to proper qpoint and property count sizes...
bool hasStatefulProperties() const
RestartableMapType _restartable_map
The restartable data to be loaded in initStatefulProps() later.
void updateStatefulPropsForPRefinement(const processor_id_type pid, const std::vector< QpMap > &p_refinement_map, const libMesh::QBase &qrule, const libMesh::QBase &qrule_face, const THREAD_ID tid, const Elem &elem, const int input_side)
Based on the p-refinement flag of elem, either prolong (for refinement) or restrict (for coarsening) ...
Basic structure for storing information about a property.
const PropsType & props(const unsigned int state=0) const
Access methods to the stored material property data with the given state state.
const std::string & getName(const unsigned int id) const
unsigned int getID(const std::string &name) const
IntRange< T > make_range(T beg, T end)
void dataStore(std::ostream &stream, MaterialPropertyStorage &storage, void *context)
MaterialData & getMaterialData(const THREAD_ID tid)
MaterialPropertyRegistry & _registry
Shared registry (across storage objects) for property names and IDs.
friend void dataLoad(std::istream &, MaterialPropertyStorage &, void *)
void restrictStatefulProps(const std::vector< std::pair< unsigned int, QpMap >> &coarsening_map, const std::vector< const Elem *> &coarsened_element_children, const libMesh::QBase &qrule, const libMesh::QBase &qrule_face, const THREAD_ID tid, const Elem &elem, int input_side=-1)
Creates storage for newly created elements from mesh Adaptivity.
void swap(const THREAD_ID tid, const Elem &elem, unsigned int side)
Swap (shallow copy) material properties in MaterialData and MaterialPropertyStorage Thread safe...
void dataLoad(std::istream &stream, MaterialPropertyStorage &storage, void *context)
void initStatefulProps(const THREAD_ID tid, const std::vector< std::shared_ptr< MaterialBase >> &mats, const unsigned int n_qpoints, const Elem &elem, const unsigned int side=0)
Initialize stateful material properties.
bool _restart_in_place
Whether or not we want to restart stateful properties in place.
void copy(const THREAD_ID tid, const Elem &elem_to, const Elem &elem_from, unsigned int side, unsigned int n_qpoints)
Copy material properties from elem_from to elem_to.
auto min(const L &left, const R &right)
const PropRecord & getPropRecord(const unsigned int id) const
Get the property record associated with the material with id id.
MaterialBases compute MaterialProperties.
bool hasValue(const std::size_t i) const
auto index_range(const T &sizable)
unsigned int _max_state
The maximum state (0 = current, 1 = old, 2 = older)
unsigned int stateful_id
The stateful id in _storage used for this property, if any.
void resize(unsigned int n_qpoints)
Resize the data to hold properties for n_qpoints quadrature points.
std::set< std::string > declarers
The material (type,name) that have declared this property.
MaterialProperties & initAndSetProps(const Elem *elem, const unsigned int side, const unsigned int state)
libMesh::IntRange< unsigned int > statefulIndexRange() const
std::string type
The type of this property.