Skip to content

Commit

Permalink
Add functor material property shortcut output, closes #19382
Browse files Browse the repository at this point in the history
Fix up logic, add more comments to avoid confusion next time around
  • Loading branch information
GiudGiud committed Jan 11, 2024
1 parent 9b1fbca commit 99c5320
Show file tree
Hide file tree
Showing 3 changed files with 140 additions and 13 deletions.
44 changes: 44 additions & 0 deletions framework/include/actions/MaterialOutputAction.h
Expand Up @@ -12,6 +12,7 @@
// MOOSE includes
#include "Action.h"
#include "MaterialData.h"
#include "FEProblemBase.h"

class MooseObjectAction;
class MaterialBase;
Expand Down Expand Up @@ -48,6 +49,14 @@ class MaterialOutputAction : public Action
template <typename T>
bool hasADProperty(const std::string & property_name);

/**
* Helper method for testing if the functor material property exists
* @tparam T The functor property type (e.g., REAL)
* @param property_name The name of the property to test
*/
template <typename T>
bool hasFunctorProperty(const std::string & property_name);

/**
* A function to be overriden by derived actions to handle a set of material property types
*/
Expand Down Expand Up @@ -88,6 +97,25 @@ class MaterialOutputAction : public Action
const MaterialBase & material,
bool get_names_only);

/**
* Template method for creating the necessary objects for the various functor material property
* types
* @tparam T The type of material property that automatic output is being performed
* @param property_name The name of the functor material property to output
* @param material A pointer to the MaterialBase object containing the property of interest
* @param get_names_only A bool used to indicate that only the variable names should be returned
*
* @return A vector of names that can be used as AuxVariable names
*
* By default this function produces an mooseError, you must create a specialization for any type
* that you wish to have the automatic output capability. Also, you need to add a test for this
* type within the act() method.
*/
template <typename T>
std::vector<std::string> functorMaterialOutputHelper(const std::string & property_name,
const MaterialBase & material,
bool get_names_only);

/// Pointer the MaterialData object storing the block restricted materials
const MaterialData * _block_material_data;

Expand Down Expand Up @@ -119,6 +147,15 @@ MaterialOutputAction::materialOutputHelper(const std::string & /*property_name*/
mooseError("Unknown type, you must create a specialization of materialOutputHelper");
}

template <typename T>
std::vector<std::string>
MaterialOutputAction::functorMaterialOutputHelper(const std::string & /*property_name*/,
const MaterialBase & /*material*/,
bool /*get_names_only*/)
{
mooseError("Unknown type, you must create a specialization of functorMaterialOutputHelper");
}

template <typename T>
bool
MaterialOutputAction::hasProperty(const std::string & property_name)
Expand All @@ -140,3 +177,10 @@ MaterialOutputAction::hasADProperty(const std::string & property_name)
else
return false;
}

template <typename T>
bool
MaterialOutputAction::hasFunctorProperty(const std::string & property_name)
{
return _problem->hasFunctorWithType<T>(property_name, 0);
}
8 changes: 8 additions & 0 deletions framework/include/functormaterials/FunctorMaterial.h
Expand Up @@ -22,6 +22,8 @@ class FunctorMaterial : public Material
FunctorMaterial(const InputParameters & parameters);
void computeProperties() override final {}

const std::set<std::string> & getSuppliedFunctors() const { return _supplied_functor_props; }

protected:
void computeQpProperties() override final {}

Expand All @@ -43,6 +45,10 @@ class FunctorMaterial : public Material
PolymorphicLambda my_lammy,
const std::set<SubdomainID> & sub_ids,
const std::set<ExecFlagType> & clearance_schedule = {EXEC_ALWAYS});

private:
/// List of the properties supplied
std::set<std::string> _supplied_functor_props;
};

template <typename T, typename PolymorphicLambda>
Expand All @@ -51,6 +57,7 @@ FunctorMaterial::addFunctorProperty(const std::string & name,
PolymorphicLambda my_lammy,
const std::set<ExecFlagType> & clearance_schedule)
{
_supplied_functor_props.insert(name);
return addFunctorPropertyByBlocks<T>(name, my_lammy, blockIDs(), clearance_schedule);
}

Expand All @@ -71,6 +78,7 @@ FunctorMaterial::addFunctorPropertyByBlocks(const std::string & name,
prop_name = _pars.get<MooseFunctorName>(name);
}

_supplied_functor_props.insert(name);
return _subproblem.addPiecewiseByBlockLambdaFunctor<T>(
prop_name, my_lammy, clearance_schedule, _mesh, sub_ids, _tid);
}
101 changes: 88 additions & 13 deletions framework/src/actions/MaterialOutputAction.C
Expand Up @@ -10,13 +10,15 @@
// MOOSE includes
#include "MaterialOutputAction.h"
#include "FEProblem.h"
#include "FEProblemBase.h"
#include "MooseApp.h"
#include "AddOutputAction.h"
#include "MaterialBase.h"
#include "RankTwoTensor.h"
#include "RankFourTensor.h"
#include "MooseEnum.h"
#include "MooseVariableConstMonomial.h"
#include "FunctorMaterial.h"

#include "libmesh/utility.h"

Expand Down Expand Up @@ -53,6 +55,14 @@ template <>
std::vector<std::string> MaterialOutputAction::materialOutputHelper<RankFourTensor>(
const std::string & material_name, const MaterialBase & material, bool get_names_only);

template <>
std::vector<std::string> MaterialOutputAction::functorMaterialOutputHelper<Real>(
const std::string & material_name, const MaterialBase & material, bool get_names_only);

template <>
std::vector<std::string> MaterialOutputAction::functorMaterialOutputHelper<RealVectorValue>(
const std::string & material_name, const MaterialBase & material, bool get_names_only);

registerMooseAction("MooseApp", MaterialOutputAction, "add_output_aux_variables");

registerMooseAction("MooseApp", MaterialOutputAction, "add_aux_kernel");
Expand Down Expand Up @@ -152,30 +162,36 @@ MaterialOutputAction::act()
// (2) If the MaterialBase object itself has set the 'outputs' parameter
if (outputs_has_properties || outputs.find("none") == outputs.end())
{
// Add the material property for output if the name is contained in the 'output_properties'
// list
// or if the list is empty (all properties)
const std::set<std::string> names = mat->getSuppliedItems();
// Get all material properties supplied by this material as a starting point
std::set<std::string> names = mat->getSuppliedItems();
if (dynamic_cast<const FunctorMaterial *>(mat.get()))
{
const auto fmat_ptr = dynamic_cast<const FunctorMaterial *>(mat.get());
names.insert(fmat_ptr->getSuppliedFunctors().begin(),
fmat_ptr->getSuppliedFunctors().end());
}

for (const auto & name : names)
{
// Add the material property for output
// Output the property only if the name is contained in the 'output_properties'
// list or if the list is empty (all properties)
if (output_properties.empty() ||
std::find(output_properties.begin(), output_properties.end(), name) !=
output_properties.end())
{
// Add the material property for output
auto curr_material_names = materialOutput(name, *mat, get_names_only);
if (curr_material_names.size() == 0)
unsupported_names.insert(name);
material_names.insert(curr_material_names.begin(), curr_material_names.end());
}

// If the material object has limited outputs, store the variables associated with the
// output objects
if (!outputs.empty())
for (const auto & output_name : outputs)
_material_variable_names_map[output_name].insert(_material_variable_names.begin(),
_material_variable_names.end());
}
// If the material object has limited outputs, store the variables associated with the
// output objects
if (!outputs.empty())
for (const auto & output_name : outputs)
_material_variable_names_map[output_name].insert(_material_variable_names.begin(),
_material_variable_names.end());
}
}
if (unsupported_names.size() > 0 && get_names_only)
Expand Down Expand Up @@ -265,6 +281,18 @@ MaterialOutputAction::materialOutput(const std::string & property_name,
else if (hasProperty<RankFourTensor>(property_name))
names = materialOutputHelper<RankFourTensor>(property_name, material, get_names_only);

else if (hasFunctorProperty<Real>(property_name))
names = functorMaterialOutputHelper<Real>(property_name, material, get_names_only);

else if (hasFunctorProperty<ADReal>(property_name))
names = functorMaterialOutputHelper<Real>(property_name, material, get_names_only);

else if (hasFunctorProperty<RealVectorValue>(property_name))
names = functorMaterialOutputHelper<RealVectorValue>(property_name, material, get_names_only);

else if (hasFunctorProperty<ADRealVectorValue>(property_name))
names = functorMaterialOutputHelper<RealVectorValue>(property_name, material, get_names_only);

return names;
}

Expand All @@ -280,7 +308,12 @@ MaterialOutputAction::getParams(const std::string & type,
// Set the action parameters
InputParameters params = _factory.getValidParams(type);

params.set<MaterialPropertyName>("property") = property_name;
// Adapt for regular or functor materials
if (type.find("Material") != std::string::npos)
params.set<MaterialPropertyName>("property") = property_name;
else
params.set<MooseFunctorName>("functor") = property_name;

params.set<AuxVariableName>("variable") = variable_name;
if (_output_only_on_timestep_end)
params.set<ExecFlagEnum>("execute_on") = EXEC_TIMESTEP_END;
Expand Down Expand Up @@ -491,3 +524,45 @@ MaterialOutputAction::materialOutputHelper<RankFourTensor>(const std::string & p

return names;
}

template <>
std::vector<std::string>
MaterialOutputAction::functorMaterialOutputHelper<Real>(const std::string & property_name,
const MaterialBase & material,
bool get_names_only)
{
std::vector<std::string> names = {property_name + "_out"};
if (!get_names_only)
{
// add a '_out' suffix to avoid name conflicts between the functor property and aux-variable
auto params = getParams("FunctorAux", property_name, property_name + "_out", material);
_problem->addAuxKernel("FunctorAux", material.name() + property_name, params);
}

return names;
}

template <>
std::vector<std::string>
MaterialOutputAction::functorMaterialOutputHelper<RealVectorValue>(
const std::string & property_name, const MaterialBase & material, bool get_names_only)
{
std::array<char, 3> suffix = {{'x', 'y', 'z'}};
std::vector<std::string> names(3);
for (const auto i : make_range(Moose::dim))
{
std::ostringstream oss;
// add a '_out' suffix to avoid name conflicts between the functor property and aux-variable
oss << property_name << "_out_" << suffix[i];
names[i] = oss.str();

if (!get_names_only)
{
auto params = getParams("FunctorVectorElementalAux", property_name, oss.str(), material);
params.set<unsigned int>("component") = i;
_problem->addAuxKernel("FunctorVectorElementalAux", material.name() + oss.str(), params);
}
}

return names;
}

0 comments on commit 99c5320

Please sign in to comment.