Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add functor material property shortcut output #26444

Merged
merged 4 commits into from Jan 24, 2024
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
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)
GiudGiud marked this conversation as resolved.
Show resolved Hide resolved
* @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
GiudGiud marked this conversation as resolved.
Show resolved Hide resolved
* 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());
}
GiudGiud marked this conversation as resolved.
Show resolved Hide resolved

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;
lindsayad marked this conversation as resolved.
Show resolved Hide resolved
}
4 changes: 4 additions & 0 deletions framework/src/functormaterials/FunctorMaterial.C
Expand Up @@ -25,6 +25,10 @@ FunctorMaterial::validParams()
// Do not allow functor materials in the regular Materials block
params.registerBase("FunctorMaterial");

// Remove MaterialBase parameters that are not used
params.suppressParameter<bool>("compute");
params.suppressParameter<MaterialPropertyName>("declare_suffix");

return params;
}

Expand Down
4 changes: 2 additions & 2 deletions framework/src/functormaterials/ParsedFunctorMaterial.C
Expand Up @@ -102,10 +102,10 @@ ParsedFunctorMaterialTempl<is_ad>::buildParsedFunction()
std::vector<std::string> symbols(_functor_symbols);
std::string symbols_str = Moose::stringify(symbols);
if (Moose::dim == 3)
symbols_str += ",x,y,z";
symbols_str += symbols_str.empty() ? "x,y,z" : ",x,y,z";
else
mooseError("ParsedFunctorMaterial assumes the dimension is always equal to 3.");
symbols_str += ",t";
symbols_str += symbols_str.empty() ? "t" : ",t";

// Parse the expression
if (_parsed_function->Parse(_expression, symbols_str) >= 0)
Expand Down
1 change: 1 addition & 0 deletions test/tests/functormaterials/output/gold/output_ad_out.e
Binary file not shown.
43 changes: 43 additions & 0 deletions test/tests/functormaterials/output/output.i
@@ -0,0 +1,43 @@
[Mesh]
type = GeneratedMesh
dim = 2
nx = 2
ny = 2
nz = 1
xmin = 0.0
xmax = 4.0
ymin = 0.0
ymax = 6.0
[]

[FunctorMaterials]
[parsed_fmat]
type = ParsedFunctorMaterial
expression = 't + x + y + z'
property_name = 'prop1'
outputs = 'exodus'
output_properties = 'prop1'
[]
[parsed_vector_fmat]
type = GenericVectorFunctorMaterial
prop_names = 'prop1_vec'
prop_values = '1 2 3'
outputs = 'exodus'
output_properties = 'prop1_vec'
[]
[]

[Problem]
solve = false
[]

[Executioner]
type = Steady
# Get the t to be equal to 4
time = 4.0
[]

[Outputs]
exodus = true
execute_on = 'INITIAL'
[]
43 changes: 43 additions & 0 deletions test/tests/functormaterials/output/output_ad.i
@@ -0,0 +1,43 @@
[Mesh]
type = GeneratedMesh
dim = 2
nx = 2
ny = 2
nz = 1
xmin = 0.0
xmax = 4.0
ymin = 0.0
ymax = 6.0
[]

[FunctorMaterials]
[parsed_fmat]
type = ADParsedFunctorMaterial
expression = 't + x + y + z'
property_name = 'prop1'
outputs = 'exodus'
output_properties = 'prop1'
[]
[parsed_vector_fmat]
type = ADGenericVectorFunctorMaterial
prop_names = 'prop1_vec'
prop_values = '1 2 3'
outputs = 'exodus'
output_properties = 'prop1_vec'
[]
[]

[Problem]
solve = false
[]

[Executioner]
type = Steady
# Get the t to be equal to 4
time = 4.0
[]

[Outputs]
exodus = true
execute_on = 'INITIAL'
[]