18 #include "libmesh/fe_interface.h" 19 #include "libmesh/quadrature.h" 29 _restart_in_place(false),
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];
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]];
67 std::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");
107 const std::set<const MooseObject *> &
110 static const std::set<const MooseObject *> empty;
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);
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);
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)
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)
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);
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);
536 std::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;
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(),
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);
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.
KOKKOS_INLINE_FUNCTION const T * find(const T &target, const T *const begin, const T *const end)
Find a value in an array.
std::vector< MaterialData > _material_data
The threaded material data.
const unsigned int invalid_uint
MaterialPropertyStorage(MaterialPropertyRegistry ®istry, FEProblemBase &problem)
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 ...
static Moose::ParameterRegistry & registry
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.
MaterialDataType
MaterialData types.
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.
Specialization of SubProblem for solving nonlinear equations plus auxiliary equations.
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)
const std::set< const MooseObject * > & getConsumers(Moose::MaterialDataType type) const
void dataStore(std::ostream &stream, MaterialPropertyStorage &storage, void *context)
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)
std::map< Moose::MaterialDataType, std::set< const MooseObject * > > _consumers
The consumers of this storage.
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
for(PetscInt i=0;i< nvars;++i)
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.
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.