https://mooseframework.inl.gov
Loading...
Searching...
No Matches
Functions
MaterialPropertyStorage.C File Reference

Go to the source code of this file.

Functions

void dataStore (std::ostream &stream, MaterialPropertyStorage &storage, void *context)
 
void dataLoad (std::istream &stream, MaterialPropertyStorage &storage, void *context)
 
void dataStore (std::ostream &stream, MaterialPropertyStorage::PropRecord &record, void *)
 
void dataLoad (std::istream &stream, MaterialPropertyStorage::PropRecord &record, void *)
 

Function Documentation

◆ dataLoad() [1/2]

void dataLoad ( std::istream &  stream,
MaterialPropertyStorage storage,
void *  context 
)

Definition at line 644 of file MaterialPropertyStorage.C.

645{
646 storage._restartable_map.clear();
647
648 const auto & registry = storage.getMaterialPropertyRegistry();
649
650 std::vector<std::string> from_prop_ids_to_names;
651 dataLoad(stream, from_prop_ids_to_names, nullptr);
652
653 decltype(storage._stateful_prop_id_to_prop_id) from_stateful_prop_id_to_prop_id;
654 dataLoad(stream, from_stateful_prop_id_to_prop_id, nullptr);
655
656 decltype(storage._prop_records) from_prop_records;
657 dataLoad(stream, from_prop_records, nullptr);
658
659 decltype(storage.numStates()) num_states;
660 dataLoad(stream, num_states, nullptr);
661
662 {
663 // Build maps of material object -> properties and property -> material objects
664 const auto build_maps = [](const auto & prop_records, const auto & ids_to_names)
665 {
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())
669 {
670 const auto & prop = ids_to_names[i];
671 for (const auto & declarer : (*prop_records[i]).declarers)
672 {
673 object_to_props[declarer].insert(prop);
674 prop_to_objects[prop].insert(declarer);
675 }
676 }
677
678 return std::make_pair(std::move(object_to_props), std::move(prop_to_objects));
679 };
680 // Maps for the current stateful properties
681 const std::vector<std::string> prop_ids_to_names(registry.idsToNamesBegin(),
682 registry.idsToNamesEnd());
683 const auto [object_to_props, prop_to_objects] =
684 build_maps(storage._prop_records, prop_ids_to_names);
685 // Maps for the stored stateful properties
686 const auto [from_object_to_props, from_prop_to_objects] =
687 build_maps(from_prop_records, from_prop_ids_to_names);
688
689 // Enforce our stateful requirements
690 for (const auto & [object, props] : object_to_props)
691 {
692 const auto find_from_object = from_object_to_props.find(object);
693
694 // We have a material object that was stored with the same name that
695 // had stateful material properties. Here, we enforce that the stateful
696 // properties stored match exactly the ones that we have declared in
697 // the new run
698 if (find_from_object != from_object_to_props.end())
699 {
700 const auto & from_props = find_from_object->second;
701 if (props != from_props)
702 {
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";
713 mooseError(error.str());
714 }
715 }
716 // We're recovering and we haven't found a stateful material object. We require a
717 // one-to-one stateful mapping when recovering
718 else if (storage._recovering)
719 {
720 mooseError("The ",
721 object,
722 " was stored in restart but no longer exists. This is not supported when "
723 "recovering stateful material properties.");
724 }
725 }
726
727 // We can easily support this, but have chosen not to due to ambiguity and we
728 // don't yet know how to express this ambiguity. Just removing this error
729 // _should_ make it work without issue because to_stateful_ids below for this
730 // property will be an empty optional, which means simply don't load it. Or,
731 // we could load it into the new property.
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 '",
739 from_prop,
740 "' was declared in ",
741 object,
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.");
745 }
746
747 std::vector<std::optional<unsigned int>> to_stateful_ids(from_stateful_prop_id_to_prop_id.size());
748
749 auto & to_prop_records = storage._prop_records;
750
751 // Mark everything as not restored in the event that we call this again
752 for (auto & record_ptr : to_prop_records)
753 if (record_ptr)
754 record_ptr->restored = false;
755
756 // Fill the mapping from previous ID to current stateful ID
757 for (const auto from_stateful_id : index_range(from_stateful_prop_id_to_prop_id))
758 {
759 const auto from_prop_id = from_stateful_prop_id_to_prop_id[from_stateful_id];
760
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");
765
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];
768
769 if (const auto query_to_prop_id = registry.queryID(name))
770 {
771 const auto to_prop_id = *query_to_prop_id;
772
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];
776
777 if (to_record.stateful())
778 {
779 if (from_record.type != to_record.type)
781 "The type for the restarted stateful material property '", name, "' does not match");
782
783 // I'm not sure if we need to enforce this one, but I don't want to think
784 // about it deeply so we'll just make it an error until someone complains
785 // we have time to think
786 if (from_record.state != to_record.state)
787 mooseError("The number of states for the restarted stateful material property '",
788 name,
789 "' do not match.\n\n",
790 "Checkpointed states: ",
791 from_record.state,
792 "\nCurrent states: ",
793 to_record.state);
794
795 const auto to_stateful_id = storage.getPropRecord(to_prop_id).stateful_id;
796 mooseAssert(to_stateful_id != invalid_uint, "Not stateful");
797
798 to_stateful_ids[from_stateful_id] = to_stateful_id;
799
800 // Mark that we're going to restore this property
801 to_record.restored = true;
802 mooseAssert(storage.isRestoredProperty(name), "Restored mismatch");
803
804 if (storage._recovering)
805 mooseAssert(from_stateful_id == to_stateful_id, "Does not have direct mapping");
806 }
807 }
808 }
809
810 // Load the properties
811 for (const auto state : make_range(num_states))
812 {
813 std::size_t num_elems;
814 dataLoad(stream, num_elems, nullptr);
815
816 for (std::size_t i_elem = 0; i_elem < num_elems; ++i_elem)
817 {
818 const Elem * elem;
819 dataLoad(stream, elem, context);
820 mooseAssert(elem, "Null element");
821
822 std::size_t num_sides;
823 dataLoad(stream, num_sides, nullptr);
824
825 for (std::size_t i_side = 0; i_side < num_sides; ++i_side)
826 {
827 unsigned int side;
828 dataLoad(stream, side, nullptr);
829
830 std::size_t num_props;
831 dataLoad(stream, num_props, nullptr);
832 mooseAssert(num_props <= to_stateful_ids.size(), "Missized map");
833
834 std::size_t num_q_points;
835 dataLoad(stream, num_q_points, nullptr);
836
837 // Avoid multiple map lookups for entries pertaining to [elem, side]
838 MaterialPropertyStorage::RestartableMapType::mapped_type * restart_entry = nullptr;
839 MaterialProperties * in_place_entry = nullptr;
840
841 // Load each stateful property
842 for (const auto from_stateful_id : make_range(num_props))
843 {
844 // Load the binary data, which lets us choose in a moment whether
845 // or not to load it in place or to cache it to load later
846 std::stringstream data;
847 dataLoad(stream, data, nullptr);
848 data.seekg(0, std::ios::beg);
849
850 // We have a property to load into
851 if (const auto to_stateful_id_ptr = to_stateful_ids[from_stateful_id])
852 {
853 const auto to_stateful_id = *to_stateful_id_ptr;
854
855 // Load the data directly into _storage
856 if (storage._restart_in_place)
857 {
858 if (!in_place_entry)
859 in_place_entry = &storage.setProps(elem, side, state);
860
861 dataLoad(data, (*in_place_entry)[to_stateful_id], nullptr);
862 }
863 // Properties aren't initialized, so load the data into
864 // _restartable_map to be loaded later in initStatefulProps()
865 else
866 {
867 if (!restart_entry)
868 restart_entry = &storage._restartable_map[std::make_pair(elem, side)];
869
870 auto & mat_entry = (*restart_entry)[to_stateful_id];
871 if (state >= mat_entry.size())
872 mat_entry.resize(state + 1);
873
874 mat_entry[state] = std::move(data);
875 }
876 }
877 }
878 }
879 }
880 }
881}
void dataLoad(std::istream &stream, MaterialPropertyStorage &storage, void *context)
void mooseError(Args &&... args)
Emit an error message with the given stringified, concatenated args and terminate the application.
Definition MooseError.h:311
unsigned int count
Definition MortarUtils.C:53
if(!dmm->_nl) SETERRQ(PETSC_COMM_WORLD
bool _recovering
Whether or not we're recovering; enforces a one-to-one mapping of stateful properties.
bool _restart_in_place
Whether or not we want to restart stateful properties in place.
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)
std::vector< std::optional< PropRecord > > _prop_records
Property records indexed by property id (may be null)
bool isRestoredProperty(const std::string &name) const
MaterialProperties & setProps(const Elem *elem, unsigned int side, const unsigned int state=0)
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.
KOKKOS_INLINE_FUNCTION const T * find(const T &target, const T *const begin, const T *const end)
Find a value in an array.
Definition KokkosUtils.h:40
std::string name(const ElemQuality q)
auto index_range(const T &sizable)
IntRange< T > make_range(T beg, T end)
unsigned int stateful_id
The stateful id in _storage used for this property, if any.

Referenced by dataLoad().

◆ dataLoad() [2/2]

void dataLoad ( std::istream &  stream,
MaterialPropertyStorage::PropRecord record,
void *  context 
)

Definition at line 893 of file MaterialPropertyStorage.C.

894{
895 dataLoad(stream, record.declarers, nullptr);
896 dataLoad(stream, record.type, nullptr);
897 dataLoad(stream, record.stateful_id, nullptr);
898 dataLoad(stream, record.state, nullptr);
899}
std::string type
The type of this property.
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, ...)

◆ dataStore() [1/2]

void dataStore ( std::ostream &  stream,
MaterialPropertyStorage storage,
void *  context 
)

Definition at line 581 of file MaterialPropertyStorage.C.

582{
583 // Store the material property ID -> name map for mapping back
584 const auto & registry = storage.getMaterialPropertyRegistry();
585 std::vector<std::string> ids_to_names(registry.idsToNamesBegin(), registry.idsToNamesEnd());
586 dataStore(stream, ids_to_names, nullptr);
587
588 // Store the stateful ID -> property ID map for mapping back
589 dataStore(stream, storage._stateful_prop_id_to_prop_id, nullptr);
590
591 // Store the prop -> record map
592 dataStore(stream, storage._prop_records, nullptr);
593
594 // Store the number of states
595 auto num_states = storage.numStates();
596 dataStore(stream, num_states, nullptr);
597
598 // Store every property
599 for (const auto state : storage.stateIndexRange())
600 {
601 std::size_t num_elems = storage.setProps(state).size();
602 dataStore(stream, num_elems, nullptr);
603
604 for (auto & elem_side_map_pair : storage.setProps(state))
605 {
606 const Elem * elem = elem_side_map_pair.first;
607 mooseAssert(elem, "Null element");
608 dataStore(stream, elem, context);
609
610 auto & side_map = elem_side_map_pair.second;
611 std::size_t num_sides = side_map.size();
612 dataStore(stream, num_sides, nullptr);
613
614 for (auto & [side, props] : side_map)
615 {
616 dataStore(stream, side, nullptr);
617
618 std::size_t num_props = props.size();
619 dataStore(stream, num_props, nullptr);
620 mooseAssert(num_props > 0, "No properties");
621
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();
626 dataStore(stream, n_q_points, nullptr);
627
628 // Here we actually store a stringstream of the data instead of the data directly, because
629 // upon load we don't know if we can load it immediately into place or if we need to cache
630 // it to load later. We also store it as skippable so that we can support not loading a
631 // property if it no longer exists in restart
632 for (auto & entry : props)
633 {
634 std::stringstream out;
635 dataStore(out, entry, nullptr);
636 dataStore(stream, out, nullptr);
637 }
638 }
639 }
640 }
641}
void dataStore(std::ostream &stream, MaterialPropertyStorage &storage, void *context)
std::size_t size() const
OStreamProxy out(std::cout)

Referenced by dataStore().

◆ dataStore() [2/2]

void dataStore ( std::ostream &  stream,
MaterialPropertyStorage::PropRecord record,
void *  context 
)

Definition at line 884 of file MaterialPropertyStorage.C.

885{
886 dataStore(stream, record.declarers, nullptr);
887 dataStore(stream, record.type, nullptr);
888 dataStore(stream, record.stateful_id, nullptr);
889 dataStore(stream, record.state, nullptr);
890}