18#include "libmesh/fe_interface.h"
19#include "libmesh/quadrature.h"
29 _restart_in_place(false),
42 for (
const auto i : make_range(std::min(stateful_prop_ids.size(), data_from.
size())))
43 if (stateful_prop_ids[i] < data.
size() && data.
hasValue(stateful_prop_ids[i]) &&
46 auto & prop = data[stateful_prop_ids[i]];
47 auto & prop_from = data_from[i];
57 for (
const auto i : make_range(std::min(stateful_prop_ids.size(), data.
size())))
58 if (stateful_prop_ids[i] < data_from.
size() && data.
hasValue(i) &&
59 data_from.
hasValue(stateful_prop_ids[i]))
61 auto & prop = data[i];
62 auto & prop_from = data_from[stateful_prop_ids[i]];
67std::optional<std::string>
94 mooseAssert(prop_record_ptr,
"Not initialized");
95 return *prop_record_ptr;
102 if (!record.stateful())
103 mooseAssert(!record.restored,
"Stateful properties should not be restored");
104 return record.restored;
107const std::set<const MooseObject *> &
110 static const std::set<const MooseObject *> empty;
122 const processor_id_type libmesh_dbg_var(pid),
123 const std::vector<QpMap> & p_refinement_map,
125 const QBase & qrule_face,
128 const int input_side)
130 unsigned int n_qpoints = 0;
133 unsigned int side = input_side == -1 ? 0 : input_side;
135 if (input_side == -1)
136 n_qpoints = qrule.n_points();
138 n_qpoints = qrule_face.n_points();
142 mooseAssert(elem.active(),
"We should be doing p-refinement on active elements only");
143 mooseAssert(elem.processor_id() == pid,
"Prolongation should be occurring locally");
144 mooseAssert(p_refinement_map.size() == n_qpoints,
"Refinement map not proper size");
146 auto current_p_level_props =
initProps(tid, &elem, side, n_qpoints);
151 auto & current_p_level_prop = (*current_p_level_props[state])[i];
154 auto previous_p_level_prop = current_p_level_prop.clone(current_p_level_prop.size());
158 previous_p_level_prop->swap(current_p_level_prop);
159 current_p_level_prop.resize(n_qpoints);
160 for (
const auto qp : index_range(p_refinement_map))
161 current_p_level_prop.qpCopy(qp, *previous_p_level_prop, p_refinement_map[qp]._to);
167 processor_id_type pid,
168 const std::vector<std::vector<QpMap>> & refinement_map,
170 const QBase & qrule_face,
174 const int input_parent_side,
175 const int input_child,
176 const int input_child_side)
178 mooseAssert(input_child != -1 || input_parent_side == input_child_side,
"Invalid inputs!");
180 unsigned int n_qpoints = 0;
183 unsigned int parent_side = input_parent_side == -1 ? 0 : input_parent_side;
184 unsigned int child_side = input_child_side == -1 ? 0 : input_child_side;
186 if (input_child_side == -1)
187 n_qpoints = qrule.n_points();
189 n_qpoints = qrule_face.n_points();
193 unsigned int n_children = elem.n_children();
195 std::vector<unsigned int> children;
197 if (input_child != -1)
198 children.push_back(input_child);
201 children.resize(n_children);
202 for (
unsigned int child = 0; child < n_children; child++)
203 children[child] = child;
206 for (
const auto & child : children)
210 if (input_child == -1 && input_child_side != -1 && !elem.is_child_on_side(child, parent_side))
213 const Elem * child_elem = elem.child_ptr(child);
217 if (child_elem->processor_id() != pid)
220 mooseAssert(child < refinement_map.size(),
"Refinement_map vector not initialized");
221 const std::vector<QpMap> & child_map = refinement_map[child];
223 auto child_props =
initProps(tid, child_elem, child_side, n_qpoints);
227 const auto & parent_props = parent_material_props.
props(&elem, parent_side, state);
229 for (
const auto qp : index_range(refinement_map[child]))
230 (*child_props[state])[i].qpCopy(qp, parent_props[i], child_map[qp]._to);
237 const std::vector<std::pair<unsigned int, QpMap>> & coarsening_map,
238 const std::vector<const Elem *> & coarsened_element_children,
240 const QBase & qrule_face,
247 bool doing_a_side = input_side != -1;
249 unsigned int n_qpoints = 0;
254 n_qpoints = qrule.n_points();
259 n_qpoints = qrule_face.n_points();
262 auto parent_props =
initProps(tid, &elem, side, n_qpoints);
265 for (
const auto qp : index_range(coarsening_map))
267 const std::pair<unsigned int, QpMap> & qp_pair = coarsening_map[qp];
268 unsigned int child = qp_pair.first;
270 mooseAssert(child < coarsened_element_children.size(),
271 "Coarsened element children vector not initialized");
272 const Elem * child_elem = coarsened_element_children[child];
273 const QpMap & qp_map = qp_pair.second;
277 const auto & child_props =
props(child_elem, side, state);
279 (*parent_props[state])[i].qpCopy(qp, child_props[i], qp_map.
_to);
286 const std::vector<std::shared_ptr<MaterialBase>> & mats,
287 const unsigned int n_qpoints,
289 const unsigned int side )
295 std::vector<std::pair<unsigned int, std::vector<std::stringstream> *>>>
296 materials_to_restart;
299 RestartableMapType::mapped_type * restartable_entry =
nullptr;
302 restartable_entry = &it->second;
308 std::vector<MaterialBase *> stateful_mats;
310 std::vector<unsigned int> stateful_ids_to_copy;
315 std::set<unsigned int> stateful_ids;
320 for (
const auto & mat : mats)
323 bool stateful =
false;
326 for (
const auto id : mat->getSuppliedPropIDs())
329 if (record.stateful())
331 const auto stateful_id = record.stateful_id;
335 const auto it_inserted_pair = stateful_ids.insert(stateful_id);
336 mooseAssert(it_inserted_pair.second,
338 "' supplied by multiple materials at the same point");
341 bool restarting =
false;
343 if (restartable_entry)
345 if (
auto id_datum_pair_it = restartable_entry->find(stateful_id);
346 id_datum_pair_it != restartable_entry->end())
349 materials_to_restart[mat.get()].emplace_back(stateful_id, &id_datum_pair_it->second);
354 stateful_ids_to_copy.push_back(record.stateful_id);
358 if (stateful || mat->forceStatefulInit())
359 stateful_mats.push_back(mat.get());
370 bool swapped =
false;
373 for (
auto mat : stateful_mats)
375 const auto materials_to_restart_find = materials_to_restart.find(mat);
376 const bool restart = materials_to_restart_find != materials_to_restart.end();
378 if (!restart || mat->forceStatefulInit())
383 swap(tid, elem, side);
387 mat->initStatefulProperties(n_qpoints);
400 for (
auto & [stateful_id, datum_ptr] : materials_to_restart_find->second)
401 for (
const auto state : index_range(*datum_ptr))
403 (*datum_ptr)[state].seekg(0, std::ios::beg);
404 dataLoad((*datum_ptr)[state], (*
props[state])[stateful_id],
nullptr);
414 for (
const auto stateful_id : stateful_ids_to_copy)
416 for (
const auto qp : make_range(n_qpoints))
417 (*
props[state])[stateful_id].qpCopy(qp, (*
props[0])[stateful_id], qp);
431 for (
unsigned int state =
maxState(); state != 0; state--)
437 const Elem & elem_to,
438 const Elem & elem_from,
440 unsigned int n_qpoints)
442 copy(tid, &elem_to, &elem_from, side, n_qpoints);
447 const Elem * elem_to,
448 const Elem * elem_from,
450 unsigned int n_qpoints)
452 auto to_props =
initProps(tid, elem_to, side, n_qpoints);
456 const auto & from_props =
props(elem_from, side, state);
458 for (
const auto qp : make_range(n_qpoints))
459 (*to_props[state])[i].qpCopy(qp, from_props[i], qp);
466 Threads::spin_mutex::scoped_lock lock(this->
_spin_mtx);
478 Threads::spin_mutex::scoped_lock lock(this->
_spin_mtx);
488 if (
props(&elem, side, state).empty())
494 const std::type_info & type,
495 const unsigned int state,
501 " is not supported. Max state supported: ",
519 record.type = type.name();
522 record.state = std::max(state, record.state);
536std::vector<MaterialProperties *>
540 unsigned int n_qpoints)
544 props[state] = &this->
initProps(tid, state, elem, side, n_qpoints);
550 const unsigned int state,
553 unsigned int n_qpoints)
556 material_data.
resize(n_qpoints);
561 if (material_data.isOnlyResizeIfSmaller())
562 n_qpoints = material_data.nQPoints();
565 if (mat_props.size() < n_props)
566 mat_props.resize(n_props, {});
570 if (!mat_props.hasValue(i))
573 mat_props.setPointer(i, material_data.props(0)[prop_id].clone(n_qpoints), {});
574 mooseAssert(mat_props[i].
id() == prop_id,
"Inconsistent id");
585 std::vector<std::string> ids_to_names(registry.idsToNamesBegin(), registry.idsToNamesEnd());
586 dataStore(stream, ids_to_names,
nullptr);
604 for (
auto & elem_side_map_pair : storage.
setProps(state))
606 const Elem * elem = elem_side_map_pair.first;
607 mooseAssert(elem,
"Null element");
610 auto & side_map = elem_side_map_pair.second;
611 std::size_t num_sides = side_map.size();
614 for (
auto & [side, props] : side_map)
618 std::size_t num_props = props.size();
620 mooseAssert(num_props > 0,
"No properties");
622 std::size_t n_q_points = 0;
623 for (
const auto & entry : props)
624 if (entry.size() > n_q_points)
625 n_q_points = entry.size();
632 for (
auto & entry : props)
634 std::stringstream out;
650 std::vector<std::string> from_prop_ids_to_names;
651 dataLoad(stream, from_prop_ids_to_names,
nullptr);
654 dataLoad(stream, from_stateful_prop_id_to_prop_id,
nullptr);
657 dataLoad(stream, from_prop_records,
nullptr);
659 decltype(storage.
numStates()) num_states;
660 dataLoad(stream, num_states,
nullptr);
664 const auto build_maps = [](
const auto & prop_records,
const auto & ids_to_names)
666 std::map<std::string, std::set<std::string>> object_to_props, prop_to_objects;
667 for (
const auto i : index_range(prop_records))
668 if (prop_records[i] && prop_records[i]->stateful())
670 const auto & prop = ids_to_names[i];
671 for (
const auto & declarer : (*prop_records[i]).declarers)
673 object_to_props[declarer].insert(prop);
674 prop_to_objects[prop].insert(declarer);
678 return std::make_pair(std::move(object_to_props), std::move(prop_to_objects));
681 const std::vector<std::string> prop_ids_to_names(registry.idsToNamesBegin(),
682 registry.idsToNamesEnd());
683 const auto [object_to_props, prop_to_objects] =
686 const auto [from_object_to_props, from_prop_to_objects] =
687 build_maps(from_prop_records, from_prop_ids_to_names);
690 for (
const auto & [
object, props] : object_to_props)
692 const auto find_from_object = from_object_to_props.find(
object);
698 if (find_from_object != from_object_to_props.end())
700 const auto & from_props = find_from_object->second;
701 if (props != from_props)
703 std::stringstream error;
704 error <<
"The stateful material properties in " <<
object
705 <<
" that are being restarted do not match the stored properties in the same "
706 "material object from the checkpoint.\n\n";
707 error <<
"Checkpointed stateful properties:\n";
708 for (
const auto & prop : from_props)
709 error <<
" - " << prop <<
"\n";
710 error <<
"\nCurrent stateful properties:\n";
711 for (
const auto & prop : props)
712 error <<
" - " << prop <<
"\n";
722 " was stored in restart but no longer exists. This is not supported when "
723 "recovering stateful material properties.");
732 for (
const auto & [from_prop, from_objects] : from_prop_to_objects)
733 if (
const auto find_objects = prop_to_objects.find(from_prop);
734 find_objects != prop_to_objects.end())
735 for (
const auto &
object : find_objects->second)
736 if (!from_objects.count(
object))
738 "The stateful material property '",
740 "' was declared in ",
742 " but was not declared in that object on checkpoint.\n\nThis is not currently "
743 "supported due to ambiguity.\n\nPlease contact the development team on "
744 "GitHub if you desire this capability.");
747 std::vector<std::optional<unsigned int>> to_stateful_ids(from_stateful_prop_id_to_prop_id.size());
752 for (
auto & record_ptr : to_prop_records)
754 record_ptr->restored =
false;
757 for (
const auto from_stateful_id : index_range(from_stateful_prop_id_to_prop_id))
759 const auto from_prop_id = from_stateful_prop_id_to_prop_id[from_stateful_id];
761 mooseAssert(from_prop_id < from_prop_records.size(),
"Invalid record map");
762 mooseAssert(from_prop_records[from_prop_id],
"Not set");
763 const auto & from_record = *from_prop_records[from_prop_id];
764 mooseAssert(from_record.stateful(),
"Not stateful");
766 mooseAssert(from_prop_id < from_prop_ids_to_names.size(),
"Invalid ID map");
767 const auto & name = from_prop_ids_to_names[from_prop_id];
769 if (
const auto query_to_prop_id = registry.queryID(name))
771 const auto to_prop_id = *query_to_prop_id;
773 mooseAssert(to_prop_id < to_prop_records.size(),
"Invalid record map");
774 mooseAssert(to_prop_records[to_prop_id],
"Not set");
775 auto & to_record = *to_prop_records[to_prop_id];
777 if (to_record.stateful())
779 if (from_record.type != to_record.type)
781 "The type for the restarted stateful material property '", name,
"' does not match");
786 if (from_record.state != to_record.state)
787 mooseError(
"The number of states for the restarted stateful material property '",
789 "' do not match.\n\n",
790 "Checkpointed states: ",
792 "\nCurrent states: ",
796 mooseAssert(to_stateful_id != invalid_uint,
"Not stateful");
798 to_stateful_ids[from_stateful_id] = to_stateful_id;
801 to_record.restored =
true;
805 mooseAssert(from_stateful_id == to_stateful_id,
"Does not have direct mapping");
811 for (
const auto state : make_range(num_states))
813 std::size_t num_elems;
814 dataLoad(stream, num_elems,
nullptr);
816 for (std::size_t i_elem = 0; i_elem < num_elems; ++i_elem)
820 mooseAssert(elem,
"Null element");
822 std::size_t num_sides;
823 dataLoad(stream, num_sides,
nullptr);
825 for (std::size_t i_side = 0; i_side < num_sides; ++i_side)
830 std::size_t num_props;
831 dataLoad(stream, num_props,
nullptr);
832 mooseAssert(num_props <= to_stateful_ids.size(),
"Missized map");
834 std::size_t num_q_points;
835 dataLoad(stream, num_q_points,
nullptr);
838 MaterialPropertyStorage::RestartableMapType::mapped_type * restart_entry =
nullptr;
842 for (
const auto from_stateful_id : make_range(num_props))
846 std::stringstream data;
848 data.seekg(0, std::ios::beg);
851 if (
const auto to_stateful_id_ptr = to_stateful_ids[from_stateful_id])
853 const auto to_stateful_id = *to_stateful_id_ptr;
859 in_place_entry = &storage.
setProps(elem, side, state);
861 dataLoad(data, (*in_place_entry)[to_stateful_id],
nullptr);
870 auto & mat_entry = (*restart_entry)[to_stateful_id];
871 if (state >= mat_entry.size())
872 mat_entry.resize(state + 1);
874 mat_entry[state] = std::move(data);
void dataLoad(std::istream &stream, MaterialPropertyStorage &storage, void *context)
void dataStore(std::ostream &stream, MaterialPropertyStorage &storage, void *context)
void mooseError(Args &&... args)
Emit an error message with the given stringified, concatenated args and terminate the application.
Specialization of SubProblem for solving nonlinear equations plus auxiliary equations.
MaterialBases compute MaterialProperties.
static constexpr unsigned int max_state
The max time state supported (2 = older)
void resize(const std::size_t size, const WriteKey)
Registry class for material property IDs and names.
unsigned int getID(const std::string &name) const
unsigned int addOrGetID(const std::string &name, const WriteKey)
const std::string & getName(const unsigned int id) const
Stores the stateful material properties computed by materials.
void setRestartInPlace()
Sets the loading of stateful material properties in place.
friend void dataLoad(std::istream &, MaterialPropertyStorage &, void *)
bool hasStatefulProperties() const
bool _recovering
Whether or not we're recovering; enforces a one-to-one mapping of stateful properties.
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.
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.
bool _restart_in_place
Whether or not we want to restart stateful properties in place.
MaterialPropertyRegistry & _registry
Shared registry (across storage objects) for property names and IDs.
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) ...
unsigned int maxState() const
const std::set< const MooseObject * > & getConsumers(Moose::MaterialDataType type) 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::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)
void swap(const THREAD_ID tid, const Elem &elem, unsigned int side)
Swap (shallow copy) material properties in MaterialData and MaterialPropertyStorage Thread safe.
std::map< Moose::MaterialDataType, std::set< const MooseObject * > > _consumers
The consumers of this storage.
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.
const PropsType & props(const unsigned int state=0) const
Access methods to the stored material property data with the given state state.
std::vector< std::optional< PropRecord > > _prop_records
Property records indexed by property id (may be null)
libMesh::Threads::spin_mutex & _spin_mtx
std::vector< MaterialData > _material_data
The threaded material data.
unsigned int numStates() const
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.
void eraseProperty(const Elem *elem)
Remove the property storage and element pointer from internal data structures Use this when elements ...
static void shallowSwapDataBack(const std::vector< unsigned int > &stateful_prop_ids, MaterialProperties &data, MaterialProperties &data_from)
void shift()
Shift the material properties in time.
libMesh::IntRange< unsigned int > statefulIndexRange() const
unsigned int _max_state
The maximum state (0 = current, 1 = old, 2 = older)
bool isRestoredProperty(const std::string &name) 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,...
MaterialProperties & setProps(const Elem *elem, unsigned int side, const unsigned int state=0)
MaterialPropertyStorage(MaterialPropertyRegistry ®istry, FEProblemBase &problem)
const MaterialPropertyRegistry & getMaterialPropertyRegistry() const
const PropRecord & getPropRecord(const unsigned int id) const
Get the property record associated with the material with id id.
RestartableMapType _restartable_map
The restartable data to be loaded in initStatefulProps() later.
std::optional< std::string > queryStatefulPropName(const unsigned int id) const
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
static void shallowSwapData(const std::vector< unsigned int > &stateful_prop_ids, MaterialProperties &data, MaterialProperties &data_from)
Shallow copies of material properties.
MaterialProperties & initAndSetProps(const Elem *elem, const unsigned int side, const unsigned int state)
std::string typeAndName() const
Get the class's combined type and name; useful in error handling.
Helper object for holding qp mapping info.
unsigned int _to
The qp to map to.
void clear()
Clears the underlying vector.
bool hasValue(const std::size_t i) const
MaterialDataType
MaterialData types.
The following methods are specializations for using the libMesh::Parallel::packed_range_* routines fo...
Basic structure for storing information about a property.
std::string type
The type of this property.
unsigned int stateful_id
The stateful id in _storage used for this property, if any.
std::set< std::string > declarers
The material (type,name) that have declared this property.
unsigned int state
The max state requrested for this property (0 = current, 1 = old, ...)