www.mooseframework.org
Classes | Namespaces | Functions
MaterialPropertyStorage.h File Reference

Go to the source code of this file.

Classes

class  MaterialPropertyStorage
 Stores the stateful material properties computed by materials. More...
 
struct  MaterialPropertyStorage::PropRecord
 Basic structure for storing information about a property. More...
 

Namespaces

 libMesh
 The following methods are specializations for using the libMesh::Parallel::packed_range_* routines for std::strings.
 

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 *context)
 
void dataLoad (std::istream &stream, MaterialPropertyStorage::PropRecord &record, void *context)
 

Function Documentation

◆ dataLoad() [1/2]

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

Definition at line 629 of file MaterialPropertyStorage.C.

Referenced by dataLoad().

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

◆ dataLoad() [2/2]

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

Definition at line 878 of file MaterialPropertyStorage.C.

879 {
880  dataLoad(stream, record.declarers, nullptr);
881  dataLoad(stream, record.type, nullptr);
882  dataLoad(stream, record.stateful_id, nullptr);
883  dataLoad(stream, record.state, nullptr);
884 }
unsigned int state
The max state requrested for this property (0 = current, 1 = old, ...)
void dataLoad(std::istream &stream, MaterialPropertyStorage &storage, void *context)
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.
std::string type
The type of this property.

◆ dataStore() [1/2]

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

Definition at line 566 of file MaterialPropertyStorage.C.

Referenced by dataStore().

567 {
568  // Store the material property ID -> name map for mapping back
569  const auto & registry = storage.getMaterialPropertyRegistry();
570  std::vector<std::string> ids_to_names(registry.idsToNamesBegin(), registry.idsToNamesEnd());
571  dataStore(stream, ids_to_names, nullptr);
572 
573  // Store the stateful ID -> property ID map for mapping back
574  dataStore(stream, storage._stateful_prop_id_to_prop_id, nullptr);
575 
576  // Store the prop -> record map
577  dataStore(stream, storage._prop_records, nullptr);
578 
579  // Store the number of states
580  auto num_states = storage.numStates();
581  dataStore(stream, num_states, nullptr);
582 
583  // Store every property
584  for (const auto state : storage.stateIndexRange())
585  {
586  std::size_t num_elems = storage.setProps(state).size();
587  dataStore(stream, num_elems, nullptr);
588 
589  for (auto & elem_side_map_pair : storage.setProps(state))
590  {
591  const Elem * elem = elem_side_map_pair.first;
592  mooseAssert(elem, "Null element");
593  dataStore(stream, elem, context);
594 
595  auto & side_map = elem_side_map_pair.second;
596  std::size_t num_sides = side_map.size();
597  dataStore(stream, num_sides, nullptr);
598 
599  for (auto & [side, props] : side_map)
600  {
601  dataStore(stream, side, nullptr);
602 
603  std::size_t num_props = props.size();
604  dataStore(stream, num_props, nullptr);
605  mooseAssert(num_props > 0, "No properties");
606 
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();
611  dataStore(stream, n_q_points, nullptr);
612 
613  // Here we actually store a stringstream of the data instead of the data directly, because
614  // upon load we don't know if we can load it immediately into place or if we need to cache
615  // it to load later. We also store it as skippable so that we can support not loading a
616  // property if it no longer exists in restart
617  for (auto & entry : props)
618  {
619  std::stringstream out;
620  dataStore(out, entry, nullptr);
621  dataStore(stream, out, nullptr);
622  }
623  }
624  }
625  }
626 }
MaterialProperties & setProps(const Elem *elem, unsigned int side, const unsigned int state=0)
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
IntRange< unsigned int > stateIndexRange() const
std::vector< std::optional< PropRecord > > _prop_records
Property records indexed by property id (may be null)
std::size_t size() const
unsigned int numStates() const
OStreamProxy out
void dataStore(std::ostream &stream, MaterialPropertyStorage &storage, void *context)

◆ dataStore() [2/2]

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

Definition at line 869 of file MaterialPropertyStorage.C.

870 {
871  dataStore(stream, record.declarers, nullptr);
872  dataStore(stream, record.type, nullptr);
873  dataStore(stream, record.stateful_id, nullptr);
874  dataStore(stream, record.state, nullptr);
875 }
unsigned int state
The max state requrested for this property (0 = current, 1 = old, ...)
void dataStore(std::ostream &stream, MaterialPropertyStorage &storage, void *context)
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.
std::string type
The type of this property.