Skip to content

Commit

Permalink
Initial work on advanced stateful properties
Browse files Browse the repository at this point in the history
This supports restarting and adding/removing stateful properties

refs idaholab#25840
  • Loading branch information
loganharbour committed Jan 29, 2024
1 parent c581c9a commit f11cdfd
Show file tree
Hide file tree
Showing 18 changed files with 540 additions and 119 deletions.
15 changes: 13 additions & 2 deletions framework/include/materials/MaterialData.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,13 @@

#include <vector>
#include <memory>
#include <typeinfo>

class MaterialPropertyStorage;
class MooseObject;
class Material;
class XFEM;
class MaterialBase;

/**
* Proxy for accessing MaterialPropertyStorage.
Expand Down Expand Up @@ -204,7 +206,10 @@ class MaterialData
/// The underlying property data
std::array<MaterialProperties, max_state + 1> _props;

unsigned int addPropertyHelper(const std::string & prop_name, const unsigned int state);
unsigned int addPropertyHelper(const std::string & prop_name,
const std::type_info & type,
const unsigned int state,
const MaterialBase * const declarer);

template <typename T, bool is_ad, bool declare>
GenericMaterialProperty<T, is_ad> & getPropertyHelper(const std::string & prop_name,
Expand All @@ -213,6 +218,11 @@ class MaterialData

static void mooseErrorHelper(const MooseObject & object, const std::string_view & error);

/**
* Helper for casting \p requestor to a MaterialBase in addPropertyHepler() (templated)
*/
const MaterialBase & castRequestorToDeclarer(const MooseObject & requestor) const;

/// Status of storage swapping (calling swap sets this to true; swapBack sets it to false)
bool _swapped;

Expand Down Expand Up @@ -263,7 +273,8 @@ MaterialData::getPropertyHelper(const std::string & prop_name,
mooseAssert(state == 0, "Cannot declare properties for states other than zero");

// Register/get the ID of the property
const auto prop_id = addPropertyHelper(prop_name, state);
const auto prop_id =
addPropertyHelper(prop_name, typeid(T), state, declare ? &castRequestorToDeclarer(requestor) : nullptr);

// Initialize the states that we need
const auto size = prop_id + 1;
Expand Down
5 changes: 5 additions & 0 deletions framework/include/materials/MaterialPropertyRegistry.h
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,11 @@ class MaterialPropertyRegistry
*/
auto idsToNamesRange() const { return libMesh::SimpleRange(idsToNamesBegin(), idsToNamesEnd()); }

/**
* @return The number of registered properties
*/
std::size_t size() const { return _id_to_name.size(); }

private:
/// Map of material property name -> material property id
std::unordered_map<std::string, unsigned int> _name_to_id;
Expand Down
59 changes: 47 additions & 12 deletions framework/include/materials/MaterialPropertyStorage.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
#include "MaterialPropertyRegistry.h"
#include "MaterialData.h"

#include <variant>

// Forward declarations
class MaterialBase;
class MaterialData;
Expand Down Expand Up @@ -42,6 +44,17 @@ class MaterialPropertyStorage
public:
MaterialPropertyStorage(MaterialPropertyRegistry & registry);

/**
* Basic structure for storing information about a property
*/
struct PropRecord
{
bool stateful() const { return state > 0; }
std::variant<const MaterialBase *, std::pair<std::string, std::string>> declarer;
std::string type;
unsigned int state = 0;
};

/**
* Creates storage for newly created elements from mesh Adaptivity. Also, copies values from the
* parent qps to the new children.
Expand Down Expand Up @@ -242,25 +255,32 @@ class MaterialPropertyStorage
bool hasProperty(const std::string & prop_name) const { return _registry.hasProperty(prop_name); }

/**
* Adds a property with the name \p prop_name and state \p state (0 = current, 1 = old, etc)
* Adds a property with the name \p prop_name, type \p type, and state \p state (0 = current, 1 =
* old, etc)
*
* This is idempotent - calling multiple times with the same name will provide the same id and
* works fine.
*
* \p declarer should be specified by the object declaring the property if it is being declared.
*/
unsigned int addProperty(const std::string & prop_name, const unsigned int state);
unsigned int addProperty(const std::string & prop_name,
const std::type_info & type,
const unsigned int state,
const MaterialBase * const declarer);

const std::vector<unsigned int> & statefulProps() const { return _stateful_prop_id_to_prop_id; }
const std::unordered_map<unsigned int, std::string> & statefulPropNames() const
{
return _stateful_prop_names;
}

const MaterialPropertyRegistry & getMaterialPropertyRegistry() const { return _registry; }

bool isStatefulProp(const std::string & prop_name) const
{
return _stateful_prop_names.count(_registry.getID(prop_name));
}
/**
* @return The name of the stateful property with id \p id, if any.
*/
std::optional<std::string> queryStatefulPropName(const unsigned int id) const;

/**
* @returns Whether or not the property \prop_name is stateful
*/
bool isStatefulProp(const std::string & prop_name) const;

/**
* Remove the property storage and element pointer from internal data structures
Expand Down Expand Up @@ -300,15 +320,27 @@ class MaterialPropertyStorage
*/
MaterialData & getMaterialData(const THREAD_ID tid) { return _material_data[tid]; }

/**
* Clears the materials that are marked as restored.
*
* Materials that have been restored do not have initStatefulProperties() called
* on them.
*/
void clearRestoredMaterials() { _restored_materials.clear(); }

protected:
/// The actual storage
std::array<PropsType, MaterialData::max_state + 1> _storage;

/// Mapping from stateful property ID to property name
std::unordered_map<unsigned int, std::string> _stateful_prop_names;
/// Property records indexed by property id (may be null)
std::vector<std::optional<PropRecord>> _prop_records;

/// the vector of stateful property ids (the vector index is the map to stateful prop_id)
std::vector<unsigned int> _stateful_prop_id_to_prop_id;

/// The materials that have been restored and should not have initStatefulProperties() called on
std::set<const MaterialBase *> _restored_materials;

void sizeProps(MaterialProperties & mp, unsigned int size);

private:
Expand Down Expand Up @@ -412,3 +444,6 @@ MaterialPropertyStorage::setProps(const unsigned int state)
{
return const_cast<MaterialPropertyStorage::PropsType &>(std::as_const(*this).props(state));
}

void dataStore(std::ostream & stream, MaterialPropertyStorage::PropRecord & record, void * context);
void dataLoad(std::istream & stream, MaterialPropertyStorage::PropRecord & record, void * context);
56 changes: 56 additions & 0 deletions framework/include/restart/DataIO.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
#include <map>
#include <unordered_map>
#include <memory>
#include <optional>

namespace libMesh
{
Expand Down Expand Up @@ -93,6 +94,12 @@ inline void storeHelper(std::ostream & stream, std::map<P, Q> & data, void * con
template <typename P, typename Q>
inline void storeHelper(std::ostream & stream, std::unordered_map<P, Q> & data, void * context);

/**
* Optional helper routine
*/
template <typename P>
inline void storeHelper(std::ostream & stream, std::optional<P> & data, void * context);

/**
* HashMap helper routine
*/
Expand Down Expand Up @@ -141,6 +148,12 @@ inline void loadHelper(std::istream & stream, std::map<P, Q> & data, void * cont
template <typename P, typename Q>
inline void loadHelper(std::istream & stream, std::unordered_map<P, Q> & data, void * context);

/**
* Optional helper routine
*/
template <typename P>
inline void loadHelper(std::istream & stream, std::optional<P> & data, void * context);

/**
* Hashmap helper routine
*/
Expand Down Expand Up @@ -316,6 +329,17 @@ dataStore(std::ostream & stream, std::unordered_map<T, U> & m, void * context)
}
}

template <typename T>
inline void
dataStore(std::ostream & stream, std::optional<T> & m, void * context)
{
bool has_value = m.has_value();
dataStore(stream, has_value, nullptr);

if (has_value)
storeHelper(stream, *m, context);
}

template <typename T, typename U>
inline void
dataStore(std::ostream & stream, HashMap<T, U> & m, void * context)
Expand Down Expand Up @@ -614,6 +638,22 @@ dataLoad(std::istream & stream, std::unordered_map<T, U> & m, void * context)
}
}

template <typename T>
inline void
dataLoad(std::istream & stream, std::optional<T> & m, void * context)
{
bool has_value;
dataLoad(stream, has_value, nullptr);

if (has_value)
{
m = T{};
loadHelper(stream, *m, context);
}
else
m.reset();
}

template <typename T, typename U>
inline void
dataLoad(std::istream & stream, HashMap<T, U> & m, void * context)
Expand Down Expand Up @@ -819,6 +859,14 @@ storeHelper(std::ostream & stream, std::unordered_map<P, Q> & data, void * conte
dataStore(stream, data, context);
}

// Optional Helper Function
template <typename P>
inline void
storeHelper(std::ostream & stream, std::optional<P> & data, void * context)
{
dataStore(stream, data, context);
}

// HashMap Helper Function
template <typename P, typename Q>
inline void
Expand Down Expand Up @@ -883,6 +931,14 @@ loadHelper(std::istream & stream, std::unordered_map<P, Q> & data, void * contex
dataLoad(stream, data, context);
}

// Optional Helper Function
template <typename P>
inline void
loadHelper(std::istream & stream, std::optional<P> & data, void * context)
{
dataLoad(stream, data, context);
}

// HashMap Helper Function
template <typename P, typename Q>
inline void
Expand Down
16 changes: 14 additions & 2 deletions framework/src/materials/MaterialData.C
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include "MaterialData.h"
#include "Material.h"
#include "MaterialPropertyStorage.h"
#include "MaterialBase.h"

MaterialData::MaterialData(MaterialPropertyStorage & storage, const THREAD_ID tid)
: _storage(storage), _tid(tid), _n_qpoints(0), _swapped(false), _resize_only_if_smaller(false)
Expand Down Expand Up @@ -88,7 +89,18 @@ MaterialData::eraseProperty(const Elem * elem)
}

unsigned int
MaterialData::addPropertyHelper(const std::string & prop_name, const unsigned int state)
MaterialData::addPropertyHelper(const std::string & prop_name,
const std::type_info & type,
const unsigned int state,
const MaterialBase * const declarer)
{
return _storage.addProperty(prop_name, state);
return _storage.addProperty(prop_name, type, state, declarer);
}

const MaterialBase &
MaterialData::castRequestorToDeclarer(const MooseObject & requestor) const
{
const auto declarer = dynamic_cast<const MaterialBase *>(&requestor);
mooseAssert(declarer, "Not a MaterialBase");
return *declarer;
}

0 comments on commit f11cdfd

Please sign in to comment.