diff --git a/framework/include/interfaces/BlockRestrictable.h b/framework/include/interfaces/BlockRestrictable.h index b27386ee3b9e..60ab892f87ff 100644 --- a/framework/include/interfaces/BlockRestrictable.h +++ b/framework/include/interfaces/BlockRestrictable.h @@ -137,14 +137,14 @@ class BlockRestrictable /** * Test if the supplied vector block ids are valid for this object * @param ids A vector of SubdomainIDs ids to check - * @return True if the all of the given ids are found within the ids for this object + * @return True if all of the given ids are found within the ids for this object */ bool hasBlocks(const std::vector & ids) const; /** * Test if the supplied set of block ids are valid for this object * @param ids A std::set of SubdomainIDs to check - * @return True if the all of the given ids are found within the ids for this object + * @return True if all of the given ids are found within the ids for this object * \see isSubset */ bool hasBlocks(const std::set & ids) const; diff --git a/framework/include/interfaces/InterpolatedStatefulMaterialPropertyInterface.h b/framework/include/interfaces/InterpolatedStatefulMaterialPropertyInterface.h new file mode 100644 index 000000000000..88dfdcfcebd0 --- /dev/null +++ b/framework/include/interfaces/InterpolatedStatefulMaterialPropertyInterface.h @@ -0,0 +1,78 @@ +//* This file is part of the MOOSE framework +//* https://www.mooseframework.org +//* +//* All rights reserved, see COPYRIGHT for full restrictions +//* https://github.com/idaholab/moose/blob/master/COPYRIGHT +//* +//* Licensed under LGPL 2.1, please see LICENSE for details +//* https://www.gnu.org/licenses/lgpl-2.1.html + +#pragma once + +// Standard includes +#include + +// MOOSE includes +#include "MooseTypes.h" +#include "Material.h" + +// Forward Declarations +class FEProblemBase; +class InputParameters; +class PostprocessorName; +class MooseObject; + +/** + * Interface class for classes which interact with Postprocessors. + * Provides the getPostprocessorValueXYZ() and related interfaces. + */ +class InterpolatedStatefulMaterialPropertyInterface +{ +public: + InterpolatedStatefulMaterialPropertyInterface(MooseObject * moose_object); + + template + const MaterialProperty & getInterpolatedMaterialPropertyOld(const std::string & name); + template + const MaterialProperty & getInterpolatedMaterialPropertyOldByName(const std::string & name); + +protected: + const std::string _pomps_prefix; + + MooseObject * _moose_object; + MaterialPropertyInterface * _material_property_interface; + Material * _material; +}; + +InterpolatedStatefulMaterialPropertyInterface::InterpolatedStatefulMaterialPropertyInterface( + MooseObject * moose_object) + : _pomps_prefix("_pomps_"), + _moose_object(moose_object), + _material_property_interface(dynamic_cast(moose_object)), + _material(dynamic_cast(moose_object)) +{ + if (!_material_property_interface && !_material) + mooseError("InterpolatedStatefulMaterialPropertyInterface can only be used from a class that " + "either derives from Material or MaterialPropertyInterface"); +} + +template +const MaterialProperty & +InterpolatedStatefulMaterialPropertyInterface::getInterpolatedMaterialPropertyOld( + const std::string & name) +{ + return getInterpolatedMaterialPropertyOldByName( + _material->getParam(name)); +} + +template +const MaterialProperty & +InterpolatedStatefulMaterialPropertyInterface::getInterpolatedMaterialPropertyOldByName( + const std::string & name) +{ + if (_material) + return _material->getMaterialPropertyByName(_pomps_prefix + "mat_" + name); + else + return _material_property_interface->getMaterialPropertyOldByName(_pomps_prefix + "mat_" + + name); +} diff --git a/framework/include/materials/MaterialPropertyInterface.h b/framework/include/materials/MaterialPropertyInterface.h index 3c21740e69a7..f047bac58934 100644 --- a/framework/include/materials/MaterialPropertyInterface.h +++ b/framework/include/materials/MaterialPropertyInterface.h @@ -262,6 +262,9 @@ class MaterialPropertyInterface MaterialBase & getMaterialByName(const std::string & name, bool no_warn = false); ///@} + /// get a set of MaterialBase pointers for all material objects that this object depends on + std::set getSupplyerMaterials(); + ///@{ /** * Check if the material property exists diff --git a/framework/src/base/Moose.C b/framework/src/base/Moose.C index 5a1e930a9aa7..f79293e1e2d3 100644 --- a/framework/src/base/Moose.C +++ b/framework/src/base/Moose.C @@ -236,6 +236,7 @@ addActionTypes(Syntax & syntax) registerTask("add_mortar_interface", false); registerTask("coupling_functor_check", true); registerTask("add_master_action_material", false); + registerTask("setup_projected_properties", false); // Dummy Actions (useful for sync points in the dependencies) registerTask("setup_function_complete", false); @@ -336,6 +337,7 @@ addActionTypes(Syntax & syntax) "(add_material)" "(add_master_action_material)" "(add_functor_material)" + "(setup_projected_properties)" "(add_output_aux_variables)" "(add_output)" "(auto_checkpoint_action)" diff --git a/framework/src/materials/MaterialPropertyInterface.C b/framework/src/materials/MaterialPropertyInterface.C index 4761f9be5a39..23478bdb9d65 100644 --- a/framework/src/materials/MaterialPropertyInterface.C +++ b/framework/src/materials/MaterialPropertyInterface.C @@ -134,12 +134,6 @@ MaterialPropertyInterface::statefulPropertiesAllowed(bool stateful_allowed) _stateful_allowed = stateful_allowed; } -MaterialBase & -MaterialPropertyInterface::getMaterial(const std::string & name) -{ - return getMaterialByName(_mi_params.get(name)); -} - void MaterialPropertyInterface::checkBlockAndBoundaryCompatibility( std::shared_ptr discrete) @@ -182,6 +176,12 @@ MaterialPropertyInterface::checkBlockAndBoundaryCompatibility( } } +MaterialBase & +MaterialPropertyInterface::getMaterial(const std::string & name) +{ + return getMaterialByName(_mi_params.get(name)); +} + MaterialBase & MaterialPropertyInterface::getMaterialByName(const std::string & name, bool no_warn) { @@ -192,6 +192,30 @@ MaterialPropertyInterface::getMaterialByName(const std::string & name, bool no_w return *discrete; } +std::set +MaterialPropertyInterface::getSupplyerMaterials() +{ + std::set matches; + const auto & mwh = _mi_feproblem.getMaterialWarehouse(); + for (const auto id : _mi_block_ids) + { + const auto & active_objects = mwh[_material_data_type].getActiveBlockObjects(id, _mi_tid); + for (const auto & mat : active_objects) + { + const auto & supplied_prop_ids = mat->getSuppliedPropIDs(); + if (MooseUtils::setsIntersect(_material_property_dependencies.begin(), + _material_property_dependencies.end(), + supplied_prop_ids.begin(), + supplied_prop_ids.end())) + { + matches.insert(mat.get()); + break; + } + } + } + return matches; +} + void MaterialPropertyInterface::checkExecutionStage() { diff --git a/modules/tensor_mechanics/include/actions/ProjectedStatefulMaterialStorageAction.h b/modules/tensor_mechanics/include/actions/ProjectedStatefulMaterialStorageAction.h new file mode 100644 index 000000000000..904290e79457 --- /dev/null +++ b/modules/tensor_mechanics/include/actions/ProjectedStatefulMaterialStorageAction.h @@ -0,0 +1,66 @@ +//* This file is part of the MOOSE framework +//* https://www.mooseframework.org +//* +//* All rights reserved, see COPYRIGHT for full restrictions +//* https://github.com/idaholab/moose/blob/master/COPYRIGHT +//* +//* Licensed under LGPL 2.1, please see LICENSE for details +//* https://www.gnu.org/licenses/lgpl-2.1.html + +#pragma once + +#include "Action.h" +#include "libmesh/fe_type.h" + +/** + * Set up AuxKernels and AxVariables for projected material property storage (PoMPS). + */ +class ProjectedStatefulMaterialStorageAction : public Action +{ +public: + static InputParameters validParams(); + + ProjectedStatefulMaterialStorageAction(const InputParameters & parameters); + + virtual void act() override; + +protected: + /** + * Perform setup for a single scalar component of the material property prop_name, and gather the + * names of teh AuxVariables used to represent each component in `vars`. + */ + void processComponent(const std::string & prop_name, + std::vector idx, + std::vector & vars, + bool is_ad); + + /** + * Add the material object to obtain the interpolated old state (for use with + * InterpolatedStatefulMaterialPropertyInterface) + */ + void addMaterial(const std::string & prop_type, + const std::string & prop_name, + std::vector & vars); + + enum class PropertyType + { + REAL, + REALVECTORVALUE, + RANKTWOTENSOR, + RANKFOURTENSOR + }; + typedef std::pair PropertyInfo; + + /** + * Return the property type and whether to use AD or not. If no property with a supported type is + * found, throw an error. + */ + PropertyInfo checkProperty(const std::string & prop_name); + + const std::vector & _prop_names; + + const MooseEnum _order; + FEType _fe_type; + const std::string _var_type; + const std::string _pomps_prefix; +}; diff --git a/modules/tensor_mechanics/include/auxkernels/ProjectedStatefulMaterialAux.h b/modules/tensor_mechanics/include/auxkernels/ProjectedStatefulMaterialAux.h new file mode 100644 index 000000000000..2e66edffb826 --- /dev/null +++ b/modules/tensor_mechanics/include/auxkernels/ProjectedStatefulMaterialAux.h @@ -0,0 +1,37 @@ +//* This file is part of the MOOSE framework +//* https://www.mooseframework.org +//* +//* All rights reserved, see COPYRIGHT for full restrictions +//* https://github.com/idaholab/moose/blob/master/COPYRIGHT +//* +//* Licensed under LGPL 2.1, please see LICENSE for details +//* https://www.gnu.org/licenses/lgpl-2.1.html + +#pragma once + +#include "AuxKernel.h" +#include "IndexableProperty.h" + +template +class ProjectedStatefulMaterialAuxTempl : public AuxKernel +{ +public: + static InputParameters validParams(); + + ProjectedStatefulMaterialAuxTempl(const InputParameters & parameters); + + virtual void initialSetup() override; + virtual void subdomainSetup() override; + +protected: + virtual Real computeValue() override; + + const IndexableProperty _prop; + const SubdomainID & _current_subdomain_id; + + std::set _all_materials; + std::vector _active_materials; +}; + +typedef ProjectedStatefulMaterialAuxTempl ProjectedStatefulMaterialAux; +typedef ProjectedStatefulMaterialAuxTempl ADProjectedStatefulMaterialAux; diff --git a/modules/tensor_mechanics/include/materials/InterpolatedStatefulMaterial.h b/modules/tensor_mechanics/include/materials/InterpolatedStatefulMaterial.h new file mode 100644 index 000000000000..1285c1b9728d --- /dev/null +++ b/modules/tensor_mechanics/include/materials/InterpolatedStatefulMaterial.h @@ -0,0 +1,50 @@ +//* This file is part of the MOOSE framework +//* https://www.mooseframework.org +//* +//* All rights reserved, see COPYRIGHT for full restrictions +//* https://github.com/idaholab/moose/blob/master/COPYRIGHT +//* +//* Licensed under LGPL 2.1, please see LICENSE for details +//* https://www.gnu.org/licenses/lgpl-2.1.html + +#pragma once + +#include "Material.h" +#include "RankTwoTensorForward.h" +#include "RankFourTensorForward.h" + +/** + * PowerLawSoftening is a smeared crack softening model that + * uses a power law equation to soften the tensile response. + * It is for use with ComputeSmearedCrackingStress. + */ +class InterpolatedStatefulMaterial : public Material +{ +public: + static InputParameters validParams(); + + InterpolatedStatefulMaterial(const InputParameters & parameters); + + virtual void computeQpProperties() override; + +protected: + /// Old state + const std::vector _old_state; + + /// emitted property name + const MaterialPropertyName _prop_name; + + /// Property type + enum class PropType + { + REAL, + REALVECTORVALUE, + RANKTWOTENSOR, + RANKFOURTENSOR + } _prop_type; + + MaterialProperty * _prop_real; + MaterialProperty * _prop_realvectorvalue; + MaterialProperty * _prop_ranktwotensor; + MaterialProperty * _prop_rankfourtensor; +}; diff --git a/modules/tensor_mechanics/include/materials/PowerLawSoftening.h b/modules/tensor_mechanics/include/materials/PowerLawSoftening.h index 4fcc317505c3..2ce8d181794d 100644 --- a/modules/tensor_mechanics/include/materials/PowerLawSoftening.h +++ b/modules/tensor_mechanics/include/materials/PowerLawSoftening.h @@ -11,8 +11,6 @@ #include "SmearedCrackSofteningBase.h" -// Forward declaration - /** * PowerLawSoftening is a smeared crack softening model that * uses a power law equation to soften the tensile response. diff --git a/modules/tensor_mechanics/include/userobjects/ProjectedStatefulMaterialNodalPatchRecovery.h b/modules/tensor_mechanics/include/userobjects/ProjectedStatefulMaterialNodalPatchRecovery.h new file mode 100644 index 000000000000..11375001b063 --- /dev/null +++ b/modules/tensor_mechanics/include/userobjects/ProjectedStatefulMaterialNodalPatchRecovery.h @@ -0,0 +1,35 @@ +//* This file is part of the MOOSE framework +//* https://www.mooseframework.org +//* +//* All rights reserved, see COPYRIGHT for full restrictions +//* https://github.com/idaholab/moose/blob/master/COPYRIGHT +//* +//* Licensed under LGPL 2.1, please see LICENSE for details +//* https://www.gnu.org/licenses/lgpl-2.1.html + +#pragma once + +// MOOSE includes +#include "NodalPatchRecoveryMaterialProperty.h" + +/** + * Nodal patch recovery for material property components for projected stateful properties + */ +class ProjectedStatefulMaterialNodalPatchRecovery : public NodalPatchRecoveryMaterialProperty +{ +public: + static InputParameters validParams(); + + ProjectedStatefulMaterialNodalPatchRecovery(const InputParameters & parameters); + + virtual void initialSetup() override; + virtual void subdomainSetup() override; + +protected: + virtual Real computeValue() override; + + const SubdomainID & _current_subdomain_id; + + std::set _all_materials; + std::vector _active_materials; +}; diff --git a/modules/tensor_mechanics/src/actions/ProjectedStatefulMaterialStorageAction.C b/modules/tensor_mechanics/src/actions/ProjectedStatefulMaterialStorageAction.C new file mode 100644 index 000000000000..e4daff50bb76 --- /dev/null +++ b/modules/tensor_mechanics/src/actions/ProjectedStatefulMaterialStorageAction.C @@ -0,0 +1,228 @@ +//* This file is part of the MOOSE framework +//* https://www.mooseframework.org +//* +//* All rights reserved, see COPYRIGHT for full restrictions +//* https://github.com/idaholab/moose/blob/master/COPYRIGHT +//* +//* Licensed under LGPL 2.1, please see LICENSE for details +//* https://www.gnu.org/licenses/lgpl-2.1.html + +// MOOSE includes +#include "ProjectedStatefulMaterialStorageAction.h" +#include "RankFourTensorForward.h" +#include "RankTwoTensorForward.h" +#include "AddAuxVariableAction.h" +#include "AddVariableAction.h" +#include "Conversion.h" +#include "FEProblemBase.h" +#include "Factory.h" + +#include "libmesh/string_to_enum.h" + +// we need to add these variables after the material property types are known +registerMooseAction("MooseApp", + ProjectedStatefulMaterialStorageAction, + "setup_projected_properties"); + +registerMooseAction("MooseApp", ProjectedStatefulMaterialStorageAction, "add_aux_kernel"); + +InputParameters +ProjectedStatefulMaterialStorageAction::validParams() +{ + InputParameters params = Action::validParams(); + + params.addClassDescription("Mark material properties for projected stateful storage."); + + params.addParam( + "family", + MooseEnum("LAGRANGE MONOMIAL", "LAGRANGE"), + "Finite element variable family to project the material properties onto"); + params.addParam( + "order", + AddAuxVariableAction::getAuxVariableOrders(), + "Finite element variable order to project the material properties onto"); + + // block restrictions + params += BlockRestrictable::validParams(); + + params.addParam>( + "projected_props", {}, "Material properties to project for stateful storage"); + return params; +} + +ProjectedStatefulMaterialStorageAction::ProjectedStatefulMaterialStorageAction( + const InputParameters & params) + : Action(params), + _prop_names(getParam>("projected_props")), + _order(params.get("order")), + _fe_type({Utility::string_to_enum(_order), + Utility::string_to_enum(params.get("family"))}), + _var_type(AddVariableAction::variableType(_fe_type)), + _pomps_prefix("_pomps_") +{ +} + +void +ProjectedStatefulMaterialStorageAction::processComponent(const std::string & prop_name, + std::vector idx, + std::vector & vars, + bool is_ad) +{ + const std::string pomps_prefix = "_pomps_"; + auto name = [&](const std::string & type) + { + auto name = _pomps_prefix + type + "_" + prop_name; + if (idx.size()) + name += "_" + Moose::stringify(idx, "_"); + return name; + }; + + const auto var_name = name("var"); + vars.push_back(var_name); + + if (_current_task == "setup_projected_properties") + { + // add the AuxVars for storage + auto params = _factory.getValidParams(_var_type); + params.applyParameters(parameters()); + params.set>("outputs") = {"none"}; + _problem->addAuxVariable(_var_type, var_name, params); + } + + if (_current_task == "add_aux_kernel") + { + // use nodal patch recovery for lagrange + if (_fe_type.family == LAGRANGE) + { + // nodal variables require patch recovery + const auto uo_name = name("uo"); + + { + // add user object + const auto & type_name = is_ad ? "ADProjectedStatefulMaterialNodalPatchRecovery" + : "ProjectedStatefulMaterialNodalPatchRecovery"; + auto params = _factory.getValidParams(type_name); + params.applySpecificParameters(parameters(), {"block"}); + params.set>("component") = idx; + params.set("property") = prop_name; + params.set("patch_polynomial_order") = _order; + params.set("execute_on") = {EXEC_INITIAL, EXEC_TIMESTEP_END}; + _problem->addUserObject(type_name, uo_name, params); + } + + { + // add aux kernel + auto params = _factory.getValidParams("NodalPatchRecoveryAux"); + params.applySpecificParameters(parameters(), {"block"}); + params.set("variable") = var_name; + params.set("nodal_patch_recovery_uo") = uo_name; + params.set("execute_on") = {EXEC_INITIAL, EXEC_TIMESTEP_END}; + _problem->addAuxKernel("NodalPatchRecoveryAux", name("aux"), params); + } + } + else + { + // elemental variables + { + const auto & type_name = + is_ad ? "ADProjectedStatefulMaterialAux" : "ProjectedStatefulMaterialAux"; + auto params = _factory.getValidParams(type_name); + params.applySpecificParameters(parameters(), {"block"}); + params.set("variable") = var_name; + params.set>("component") = idx; + params.set("property") = prop_name; + params.set("execute_on") = {EXEC_INITIAL, EXEC_TIMESTEP_END}; + _problem->addAuxKernel(type_name, name("aux"), params); + } + } + } +} + +ProjectedStatefulMaterialStorageAction::PropertyInfo +ProjectedStatefulMaterialStorageAction::checkProperty(const std::string & prop_name) +{ + const auto & data = _problem->getMaterialData(Moose::BLOCK_MATERIAL_DATA); + + if (data.haveProperty(prop_name)) + return {PropertyType::REAL, false}; + if (data.haveADProperty(prop_name)) + return {PropertyType::REAL, true}; + + if (data.haveProperty(prop_name)) + return {PropertyType::REALVECTORVALUE, false}; + if (data.haveADProperty(prop_name)) + return {PropertyType::REALVECTORVALUE, true}; + + if (data.haveProperty(prop_name)) + return {PropertyType::RANKTWOTENSOR, false}; + if (data.haveADProperty(prop_name)) + return {PropertyType::RANKTWOTENSOR, true}; + + if (data.haveProperty(prop_name)) + return {PropertyType::RANKFOURTENSOR, false}; + if (data.haveADProperty(prop_name)) + return {PropertyType::RANKFOURTENSOR, true}; + + paramError("projected_props", + "Material property type of property '", + prop_name, + "' is not supported for projection."); +} + +void +ProjectedStatefulMaterialStorageAction::addMaterial(const std::string & prop_type, + const std::string & prop_name, + std::vector & vars) +{ + auto params = _factory.getValidParams("InterpolatedStatefulMaterial"); + const auto name = _pomps_prefix + "mat_" + prop_name; + params.applySpecificParameters(parameters(), {"block"}); + params.set>("old_state") = vars; + params.set("prop_type") = prop_type; + params.set("prop_name") = name; + _problem->addMaterial("InterpolatedStatefulMaterial", name, params); +} + +void +ProjectedStatefulMaterialStorageAction::act() +{ + for (const auto & prop_name : _prop_names) + { + const auto prop_info = checkProperty(prop_name); + std::vector vars; + + switch (prop_info.first) + { + case PropertyType::REAL: + processComponent(prop_name, {}, vars, prop_info.second); + if (_current_task == "setup_projected_properties") + addMaterial("REAL", prop_name, vars); + break; + + case PropertyType::REALVECTORVALUE: + for (unsigned int i = 0; i < Moose::dim; ++i) + processComponent(prop_name, {i}, vars, prop_info.second); + if (_current_task == "setup_projected_properties") + addMaterial("REALVECTORVALUE", prop_name, vars); + break; + + case PropertyType::RANKTWOTENSOR: + for (unsigned int i = 0; i < Moose::dim; ++i) + for (unsigned int j = 0; j < Moose::dim; ++j) + processComponent(prop_name, {i, j}, vars, prop_info.second); + if (_current_task == "setup_projected_properties") + addMaterial("RANKTWOTENSOR", prop_name, vars); + break; + + case PropertyType::RANKFOURTENSOR: + for (unsigned int i = 0; i < Moose::dim; ++i) + for (unsigned int j = 0; j < Moose::dim; ++j) + for (unsigned int k = 0; k < Moose::dim; ++k) + for (unsigned int l = 0; l < Moose::dim; ++l) + processComponent(prop_name, {i, j, k, l}, vars, prop_info.second); + if (_current_task == "setup_projected_properties") + addMaterial("RANKFOURTENSOR", prop_name, vars); + break; + } + } +} diff --git a/modules/tensor_mechanics/src/auxkernels/ProjectedStatefulMaterialAux.C b/modules/tensor_mechanics/src/auxkernels/ProjectedStatefulMaterialAux.C new file mode 100644 index 000000000000..8480785d4f56 --- /dev/null +++ b/modules/tensor_mechanics/src/auxkernels/ProjectedStatefulMaterialAux.C @@ -0,0 +1,68 @@ +//* This file is part of the MOOSE framework +//* https://www.mooseframework.org +//* +//* All rights reserved, see COPYRIGHT for full restrictions +//* https://github.com/idaholab/moose/blob/master/COPYRIGHT +//* +//* Licensed under LGPL 2.1, please see LICENSE for details +//* https://www.gnu.org/licenses/lgpl-2.1.html + +#include "ProjectedStatefulMaterialAux.h" +#include "NodalPatchRecoveryBase.h" +#include "MaterialBase.h" + +registerMooseObject("TensorMechanicsApp", ProjectedStatefulMaterialAux); +registerMooseObject("TensorMechanicsApp", ADProjectedStatefulMaterialAux); + +template +InputParameters +ProjectedStatefulMaterialAuxTempl::validParams() +{ + auto params = IndexableProperty::validParams(); + params.addClassDescription( + "Picks a component of an indexable material property to get projected on an elemental " + "Auxvariable. For use by ProjectedStatefulMaterialStorageAction."); + return params; +} + +template +ProjectedStatefulMaterialAuxTempl::ProjectedStatefulMaterialAuxTempl( + const InputParameters & parameters) + : AuxKernel(parameters), _prop(this), _current_subdomain_id(_assembly.currentSubdomainID()) +{ +} + +template +void +ProjectedStatefulMaterialAuxTempl::initialSetup() +{ + _prop.check(); + + // get all material classes that provide properties for this object + _all_materials = getSupplyerMaterials(); +} + +template +void +ProjectedStatefulMaterialAuxTempl::subdomainSetup() +{ + // get materials for the current subdomain + _active_materials.clear(); + for (const auto & mat : _all_materials) + if (mat->hasBlocks(_current_subdomain_id)) + _active_materials.push_back(mat); +} + +template +Real +ProjectedStatefulMaterialAuxTempl::computeValue() +{ + if (_t_step == 0) + for (const auto & mat : _active_materials) + mat->initStatefulProperties(_qrule->size()); + + return MetaPhysicL::raw_value(_prop[_qp]); +} + +template class ProjectedStatefulMaterialAuxTempl; +template class ProjectedStatefulMaterialAuxTempl; diff --git a/modules/tensor_mechanics/src/base/TensorMechanicsApp.C b/modules/tensor_mechanics/src/base/TensorMechanicsApp.C index 82fbf17782a6..fa2a65f384e3 100644 --- a/modules/tensor_mechanics/src/base/TensorMechanicsApp.C +++ b/modules/tensor_mechanics/src/base/TensorMechanicsApp.C @@ -63,6 +63,8 @@ associateSyntaxInner(Syntax & syntax, ActionFactory & /*action_factory*/) registerSyntax("CommonLineElementAction", "Modules/TensorMechanics/LineElementMaster"); registerSyntax("LineElementAction", "Modules/TensorMechanics/LineElementMaster/*"); + registerSyntax("ProjectedStatefulMaterialStorageAction", "ProjectedStatefulMaterialStorage/*"); + registerSyntaxTask("DomainIntegralAction", "DomainIntegral", "add_user_object"); registerSyntaxTask("DomainIntegralAction", "DomainIntegral", "add_aux_variable"); registerSyntaxTask("DomainIntegralAction", "DomainIntegral", "add_aux_kernel"); diff --git a/modules/tensor_mechanics/src/materials/InterpolatedStatefulMaterial.C b/modules/tensor_mechanics/src/materials/InterpolatedStatefulMaterial.C new file mode 100644 index 000000000000..46eef56da4a7 --- /dev/null +++ b/modules/tensor_mechanics/src/materials/InterpolatedStatefulMaterial.C @@ -0,0 +1,81 @@ +//* This file is part of the MOOSE framework +//* https://www.mooseframework.org +//* +//* All rights reserved, see COPYRIGHT for full restrictions +//* https://github.com/idaholab/moose/blob/master/COPYRIGHT +//* +//* Licensed under LGPL 2.1, please see LICENSE for details +//* https://www.gnu.org/licenses/lgpl-2.1.html + +#include "InterpolatedStatefulMaterial.h" + +registerMooseObject("TensorMechanicsApp", InterpolatedStatefulMaterial); + +InputParameters +InterpolatedStatefulMaterial::validParams() +{ + InputParameters params = Material::validParams(); + params.addClassDescription("Access old state from projected data."); + params.addRequiredCoupledVar("old_state", "The AuxVars for the coupled components"); + params.addParam( + "prop_type", MooseEnum("REAL REALVECTORVALUE RANKTWOTENSOR RANKFOURTENSOR"), "Property type"); + params.addRequiredParam("prop_name", "Name to emit"); + return params; +} + +InterpolatedStatefulMaterial::InterpolatedStatefulMaterial(const InputParameters & parameters) + : Material(parameters), + _old_state(coupledValuesOld("old_state")), + _prop_name(getParam("prop_name")), + _prop_type(getParam("prop_type").getEnum()), + _prop_real(_prop_type == PropType::REAL ? &declareProperty(_prop_name) : nullptr), + _prop_realvectorvalue(_prop_type == PropType::REALVECTORVALUE + ? &declareProperty(_prop_name) + : nullptr), + _prop_ranktwotensor(_prop_type == PropType::RANKTWOTENSOR + ? &declareProperty(_prop_name) + : nullptr), + _prop_rankfourtensor(_prop_type == PropType::RANKFOURTENSOR + ? &declareProperty(_prop_name) + : nullptr) +{ +} + +void +InterpolatedStatefulMaterial::computeQpProperties() +{ + switch (_prop_type) + { + case PropType::REAL: + (*_prop_real)[_qp] = (*_old_state[0])[_qp]; + return; + + case PropType::REALVECTORVALUE: + { + std::size_t index = 0; + for (const auto i : make_range(Moose::dim)) + (*_prop_realvectorvalue)[_qp](i) = (*_old_state[index++])[_qp]; + return; + } + + case PropType::RANKTWOTENSOR: + { + std::size_t index = 0; + for (const auto i : make_range(Moose::dim)) + for (const auto j : make_range(Moose::dim)) + (*_prop_ranktwotensor)[_qp](i, j) = (*_old_state[index++])[_qp]; + return; + } + + case PropType::RANKFOURTENSOR: + { + std::size_t index = 0; + for (const auto i : make_range(Moose::dim)) + for (const auto j : make_range(Moose::dim)) + for (const auto k : make_range(Moose::dim)) + for (const auto l : make_range(Moose::dim)) + (*_prop_rankfourtensor)[_qp](i, j, k, l) = (*_old_state[index++])[_qp]; + return; + } + } +} diff --git a/modules/tensor_mechanics/src/userobjects/ProjectedStatefulMaterialNodalPatchRecovery.C b/modules/tensor_mechanics/src/userobjects/ProjectedStatefulMaterialNodalPatchRecovery.C new file mode 100644 index 000000000000..e8d286bbab3d --- /dev/null +++ b/modules/tensor_mechanics/src/userobjects/ProjectedStatefulMaterialNodalPatchRecovery.C @@ -0,0 +1,55 @@ +//* This file is part of the MOOSE framework +//* https://www.mooseframework.org +//* +//* All rights reserved, see COPYRIGHT for full restrictions +//* https://github.com/idaholab/moose/blob/master/COPYRIGHT +//* +//* Licensed under LGPL 2.1, please see LICENSE for details +//* https://www.gnu.org/licenses/lgpl-2.1.html + +#include "ProjectedStatefulMaterialNodalPatchRecovery.h" + +registerMooseObject("TensorMechanicsApp", ProjectedStatefulMaterialNodalPatchRecovery); + +InputParameters +ProjectedStatefulMaterialNodalPatchRecovery::validParams() +{ + InputParameters params = NodalPatchRecoveryMaterialProperty::validParams(); + return params; +} + +ProjectedStatefulMaterialNodalPatchRecovery::ProjectedStatefulMaterialNodalPatchRecovery( + const InputParameters & parameters) + : NodalPatchRecoveryMaterialProperty(parameters), + _current_subdomain_id(_assembly.currentSubdomainID()) +{ +} + +void +ProjectedStatefulMaterialNodalPatchRecovery::initialSetup() +{ + NodalPatchRecoveryMaterialProperty::initialSetup(); + + // get all material classes that provide properties for this object + _all_materials = getSupplyerMaterials(); +} + +void +ProjectedStatefulMaterialNodalPatchRecovery::subdomainSetup() +{ + // get materials for the current subdomain + _active_materials.clear(); + for (const auto & mat : _all_materials) + if (mat->hasBlocks(_current_subdomain_id)) + _active_materials.push_back(mat); +} + +Real +ProjectedStatefulMaterialNodalPatchRecovery::computeValue() +{ + if (_t_step == 0) + for (const auto & mat : _active_materials) + mat->initStatefulProperties(_qrule->size()); + + return _prop[_qp]; +} diff --git a/modules/tensor_mechanics/test/include/materials/ProjectedStatefulPropertiesTestMaterial.h b/modules/tensor_mechanics/test/include/materials/ProjectedStatefulPropertiesTestMaterial.h new file mode 100644 index 000000000000..3b8232415f5c --- /dev/null +++ b/modules/tensor_mechanics/test/include/materials/ProjectedStatefulPropertiesTestMaterial.h @@ -0,0 +1,57 @@ +//* This file is part of the MOOSE framework +//* https://www.mooseframework.org +//* +//* All rights reserved, see COPYRIGHT for full restrictions +//* https://github.com/idaholab/moose/blob/master/COPYRIGHT +//* +//* Licensed under LGPL 2.1, please see LICENSE for details +//* https://www.gnu.org/licenses/lgpl-2.1.html + +#pragma once + +#include "Material.h" +#include "InterpolatedStatefulMaterialPropertyInterface.h" +#include "RankTwoTensor.h" +#include "RankFourTensor.h" + +/** + * Test the projected old state capability in ProjectedStatefulMaterialStorageAction + */ +template +class ProjectedStatefulPropertiesTestMaterialTempl + : public Material, + public InterpolatedStatefulMaterialPropertyInterface +{ +public: + static InputParameters validParams(); + + ProjectedStatefulPropertiesTestMaterialTempl(const InputParameters & parameters); + +protected: + virtual void computeQpProperties() override; + virtual void initQpStatefulProperties() override; + + /// Real + GenericMaterialProperty & _prop_real; + const MaterialProperty & _prop_real_old; + const MaterialProperty & _prop_real_old_interpolated; + /// RealVectorValue + GenericMaterialProperty & _prop_realvectorvalue; + const MaterialProperty & _prop_realvectorvalue_old; + const MaterialProperty & _prop_realvectorvalue_old_interpolated; + /// RankTwoTensor + GenericMaterialProperty & _prop_ranktwotensor; + const MaterialProperty & _prop_ranktwotensor_old; + const MaterialProperty & _prop_ranktwotensor_old_interpolated; + /// RankFourTensor + GenericMaterialProperty & _prop_rankfourtensor; + const MaterialProperty & _prop_rankfourtensor_old; + const MaterialProperty & _prop_rankfourtensor_old_interpolated; + + /// diagnostic outout + MaterialProperty & _diff_norm; +}; + +typedef ProjectedStatefulPropertiesTestMaterialTempl ProjectedStatefulPropertiesTestMaterial; +typedef ProjectedStatefulPropertiesTestMaterialTempl + ADProjectedStatefulPropertiesTestMaterial; diff --git a/modules/tensor_mechanics/test/src/materials/ProjectedStatefulPropertiesTestMaterial.C b/modules/tensor_mechanics/test/src/materials/ProjectedStatefulPropertiesTestMaterial.C new file mode 100644 index 000000000000..ae40e6e6c8e0 --- /dev/null +++ b/modules/tensor_mechanics/test/src/materials/ProjectedStatefulPropertiesTestMaterial.C @@ -0,0 +1,102 @@ +//* This file is part of the MOOSE framework +//* https://www.mooseframework.org +//* +//* All rights reserved, see COPYRIGHT for full restrictions +//* https://github.com/idaholab/moose/blob/master/COPYRIGHT +//* +//* Licensed under LGPL 2.1, please see LICENSE for details +//* https://www.gnu.org/licenses/lgpl-2.1.html + +#include "ProjectedStatefulPropertiesTestMaterial.h" + +registerMooseObject("TensorMechanicsTestApp", ProjectedStatefulPropertiesTestMaterial); + +template +InputParameters +ProjectedStatefulPropertiesTestMaterialTempl::validParams() +{ + InputParameters params = Material::validParams(); + params.addClassDescription(""); + return params; +} + +template +ProjectedStatefulPropertiesTestMaterialTempl::ProjectedStatefulPropertiesTestMaterialTempl( + const InputParameters & parameters) + : Material(parameters), + InterpolatedStatefulMaterialPropertyInterface(this), + // Real + _prop_real(declareGenericProperty("test_real")), + _prop_real_old(getMaterialPropertyOldByName("test_real")), + _prop_real_old_interpolated(getInterpolatedMaterialPropertyOldByName("test_real")), + // RealVectorValue + _prop_realvectorvalue(declareGenericProperty("test_realvectorvalue")), + _prop_realvectorvalue_old( + getMaterialPropertyOldByName("test_realvectorvalue")), + _prop_realvectorvalue_old_interpolated( + getInterpolatedMaterialPropertyOldByName("test_realvectorvalue")), + // RankTwoTensor + _prop_ranktwotensor(declareGenericProperty("test_ranktwotensor")), + _prop_ranktwotensor_old(getMaterialPropertyOldByName("test_ranktwotensor")), + _prop_ranktwotensor_old_interpolated( + getInterpolatedMaterialPropertyOldByName("test_ranktwotensor")), + // RankFourTensor + _prop_rankfourtensor(declareGenericProperty("test_rankfourtensor")), + _prop_rankfourtensor_old(getMaterialPropertyOldByName("test_rankfourtensor")), + _prop_rankfourtensor_old_interpolated( + getInterpolatedMaterialPropertyOldByName("test_rankfourtensor")), + // diagnostic outputs + _diff_norm(declareProperty("diff_norm")) +{ +} + +template +void +ProjectedStatefulPropertiesTestMaterialTempl::initQpStatefulProperties() +{ + _prop_real[_qp] = 77; + _prop_realvectorvalue[_qp] = {2.4, 5.6, 7.8}; + _prop_ranktwotensor[_qp] = {1.1, 1.2, 1.3, 2.1, 2.2, 2.3, 3.1, 3.2, 3.3}; +} + +template +void +ProjectedStatefulPropertiesTestMaterialTempl::computeQpProperties() +{ + const auto & p = _q_point[_qp]; + + // update current properties + _prop_real[_qp] = 1.23 + _t * p(0) - p(1) * p(1); + _prop_realvectorvalue[_qp] = _prop_realvectorvalue_old[_qp] + p; + _prop_ranktwotensor[_qp] = _prop_ranktwotensor_old[_qp]; + _prop_rankfourtensor[_qp] = _prop_rankfourtensor_old[_qp]; + + for (const auto i : make_range(Moose::dim)) + { + _prop_realvectorvalue[_qp](i) += MathUtils::pow(_t, i); + for (const auto j : make_range(Moose::dim)) + { + _prop_ranktwotensor[_qp](i, j) += MathUtils::pow(_t, i) + MathUtils::pow(p(0), j); + for (const auto k : make_range(Moose::dim)) + { + for (const auto l : make_range(Moose::dim)) + _prop_rankfourtensor[_qp](i, j, k, l) += MathUtils::pow(_t, i) + MathUtils::pow(p(2), j) + + MathUtils::pow(p(1), k) + + MathUtils::pow(p(0), l); + } + } + } + + // compute norm of old diffs + const auto d1 = _prop_real_old[_qp] - _prop_real_old_interpolated[_qp]; + const auto d2 = _prop_realvectorvalue_old[_qp] - _prop_realvectorvalue_old_interpolated[_qp]; + const auto d3 = _prop_ranktwotensor_old[_qp] - _prop_ranktwotensor_old_interpolated[_qp]; + const auto d4 = _prop_rankfourtensor_old[_qp] - _prop_rankfourtensor_old_interpolated[_qp]; + + Real diff = 0.0; + diff += std::sqrt(d1 * d1); + diff += d2.norm(); + diff += d3.L2norm(); + diff += d4.L2norm(); + _diff_norm[_qp] = diff; +} diff --git a/modules/tensor_mechanics/test/tests/projected_stateful_materials/test.i b/modules/tensor_mechanics/test/tests/projected_stateful_materials/test.i new file mode 100644 index 000000000000..8ad5d183e039 --- /dev/null +++ b/modules/tensor_mechanics/test/tests/projected_stateful_materials/test.i @@ -0,0 +1,55 @@ +[Mesh] + [gen] + type = GeneratedMeshGenerator + dim = 2 + nx = 4 + ny = 4 + [] +[] + +[Variables] + [u] + [] +[] + +[Kernels] + [diff] + type = Diffusion + variable = u + [] +[] + +[ProjectedStatefulMaterialStorage] + [all] + projected_props = 'test_real test_realvectorvalue test_ranktwotensor test_rankfourtensor' + family = MONOMIAL + order = FIRST + [] +[] + +[Materials] + [test] + type = ProjectedStatefulPropertiesTestMaterial + [] +[] + +[Postprocessors] + [average_diff] + type = ElementAverageMaterialProperty + mat_prop = diff_norm + [] +[] + +[Executioner] + type = Transient + num_steps = 3 +[] + +[Outputs] + csv = true + # in initial the freshly set up old state of the material properties differes + # from the interpolated state as the MAT->AUX->MAT dependency cannot be + # resolved (as bot the computation of the current state as well as the + # testing are done in the same material object) + execute_on = 'TIMESTEP_END' +[] diff --git a/modules/tensor_mechanics/test/tests/projected_stateful_materials/tests b/modules/tensor_mechanics/test/tests/projected_stateful_materials/tests new file mode 100644 index 000000000000..e69de29bb2d1