Skip to content

Commit

Permalink
Allowed post-processors to be used in functor parameters
Browse files Browse the repository at this point in the history
  • Loading branch information
joshuahansel committed Aug 11, 2023
1 parent 5490ab9 commit 0a5f62a
Show file tree
Hide file tree
Showing 9 changed files with 276 additions and 2 deletions.
6 changes: 6 additions & 0 deletions framework/doc/content/syntax/Functors/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ Functors are an abstraction, existing as a base class, that is available to seve
- [Auxiliary variables](syntax/AuxVariables/index.md)
- [Functor material properties](syntax/FunctorMaterials/index.md)
- [Functions](syntax/Functions/index.md)
- [Post-processors](syntax/Postprocessors/index.md)

All functors can be called using the same interfaces. This enables considerable code re-use.
For example, instead of having a kernel for each type of coupled forcing term, like
Expand All @@ -17,6 +18,11 @@ but for `Functors`, the space arguments can be an element, a point in an element
a face of an element, and so on. The time arguments represent the state of the functor : current, previous value (whether in time or iteration),
or value before that previous one.

!alert warning title=Using post-processors
Note that when using post-processors, instead of being evaluated on-the-fly at
a point in space and time, the most recently computed value is used, in accordance
with the `execute_on` for the post-processor.

!alert note
If a Functor is reported as missing by the simulation, you may use the `Debug/`[!param](/Debug/SetupDebugAction/show_functors)
parameter to get more information about which functors were created and requested.
Expand Down
38 changes: 37 additions & 1 deletion framework/include/postprocessors/Postprocessor.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,9 @@
* virtual getValue() interface which must be overridden by derived
* classes.
*/
class Postprocessor : public OutputInterface, public NonADFunctorInterface
class Postprocessor : public OutputInterface,
public NonADFunctorInterface,
public Moose::FunctorBase<Real>
{
public:
static InputParameters validParams();
Expand All @@ -45,4 +47,38 @@ class Postprocessor : public OutputInterface, public NonADFunctorInterface

protected:
const std::string _pp_name;

private:
using ElemArg = Moose::ElemArg;
using ElemQpArg = Moose::ElemQpArg;
using ElemSideQpArg = Moose::ElemSideQpArg;
using FaceArg = Moose::FaceArg;
using ElemPointArg = Moose::ElemPointArg;

ValueType evaluate(const ElemArg & elem, const Moose::StateArg & state) const override final;
ValueType evaluate(const FaceArg & face, const Moose::StateArg & state) const override final;
ValueType evaluate(const ElemQpArg & qp, const Moose::StateArg & state) const override final;
ValueType evaluate(const ElemSideQpArg & elem_side_qp,
const Moose::StateArg & state) const override final;
ValueType evaluate(const ElemPointArg & elem_point,
const Moose::StateArg & state) const override final;

GradientType evaluateGradient(const ElemArg & elem,
const Moose::StateArg & state) const override final;
GradientType evaluateGradient(const FaceArg & face,
const Moose::StateArg & state) const override final;
GradientType evaluateGradient(const ElemQpArg & qp,
const Moose::StateArg & state) const override final;
GradientType evaluateGradient(const ElemSideQpArg & elem_side_qp,
const Moose::StateArg & state) const override final;
GradientType evaluateGradient(const ElemPointArg & elem_point,
const Moose::StateArg & state) const override final;

DotType evaluateDot(const ElemArg & elem, const Moose::StateArg & state) const override final;
DotType evaluateDot(const FaceArg & face, const Moose::StateArg & state) const override final;
DotType evaluateDot(const ElemQpArg & qp, const Moose::StateArg & state) const override final;
DotType evaluateDot(const ElemSideQpArg & elem_side_qp,
const Moose::StateArg & state) const override final;
DotType evaluateDot(const ElemPointArg & elem_point,
const Moose::StateArg & state) const override final;
};
4 changes: 3 additions & 1 deletion framework/src/interfaces/FunctorInterface.C
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ FunctorInterface::deduceFunctorName(const std::string & name, const InputParamet
{
if (params.have_parameter<MooseFunctorName>(name))
return params.get<MooseFunctorName>(name);
// variables, functor material properties, and functions are also functors
// variables, functor material properties, functions, and post-processors are also functors
else if (params.have_parameter<MaterialPropertyName>(name))
return params.get<MaterialPropertyName>(name);
else if (params.have_parameter<VariableName>(name))
Expand All @@ -47,6 +47,8 @@ FunctorInterface::deduceFunctorName(const std::string & name, const InputParamet
return params.get<NonlinearVariableName>(name);
else if (params.have_parameter<FunctionName>(name))
return params.get<FunctionName>(name);
else if (params.have_parameter<PostprocessorName>(name))
return params.get<PostprocessorName>(name);
else
mooseError("Invalid parameter type for retrieving a functor");
}
Expand Down
99 changes: 99 additions & 0 deletions framework/src/postprocessors/Postprocessor.C
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ Postprocessor::validParams()
Postprocessor::Postprocessor(const MooseObject * moose_object)
: OutputInterface(moose_object->parameters()),
NonADFunctorInterface(moose_object),
Moose::FunctorBase<Real>(moose_object->name()),
_pp_name(moose_object->name())
{
auto & fe_problem =
Expand Down Expand Up @@ -64,3 +65,101 @@ Postprocessor::getValue() const
{
mooseError("getValue() (const or non-const) must be implemented.");
}

typename Postprocessor::ValueType
Postprocessor::evaluate(const ElemArg & /*elem_arg*/, const Moose::StateArg & /*state*/) const
{
return getValue();
}

typename Postprocessor::ValueType
Postprocessor::evaluate(const FaceArg & /*face*/, const Moose::StateArg & /*state*/) const
{
return getValue();
}

typename Postprocessor::ValueType
Postprocessor::evaluate(const ElemQpArg & /*elem_qp*/, const Moose::StateArg & /*state*/) const
{
return getValue();
}

typename Postprocessor::ValueType
Postprocessor::evaluate(const ElemSideQpArg & /*elem_side_qp*/,
const Moose::StateArg & /*state*/) const
{
return getValue();
}

typename Postprocessor::ValueType
Postprocessor::evaluate(const ElemPointArg & /*elem_point_arg*/,
const Moose::StateArg & /*state*/) const
{
return getValue();
}

typename Postprocessor::GradientType
Postprocessor::evaluateGradient(const ElemArg & /*elem_arg*/,
const Moose::StateArg & /*state*/) const
{
return 0;
}

typename Postprocessor::GradientType
Postprocessor::evaluateGradient(const FaceArg & /*face*/, const Moose::StateArg & /*state*/) const
{
return 0;
}

typename Postprocessor::GradientType
Postprocessor::evaluateGradient(const ElemQpArg & /*elem_qp*/,
const Moose::StateArg & /*state*/) const
{
return 0;
}

typename Postprocessor::GradientType
Postprocessor::evaluateGradient(const ElemSideQpArg & /*elem_side_qp*/,
const Moose::StateArg & /*state*/) const
{
return 0;
}

typename Postprocessor::GradientType
Postprocessor::evaluateGradient(const ElemPointArg & /*elem_point_arg*/,
const Moose::StateArg & /*state*/) const
{
return 0;
}

typename Postprocessor::DotType
Postprocessor::evaluateDot(const ElemArg & /*elem_arg*/, const Moose::StateArg & /*state*/) const
{
return 0;
}

typename Postprocessor::DotType
Postprocessor::evaluateDot(const FaceArg & /*face*/, const Moose::StateArg & /*state*/) const
{
return 0;
}

typename Postprocessor::DotType
Postprocessor::evaluateDot(const ElemQpArg & /*elem_qp*/, const Moose::StateArg & /*state*/) const
{
return 0;
}

typename Postprocessor::DotType
Postprocessor::evaluateDot(const ElemSideQpArg & /*elem_side_qp*/,
const Moose::StateArg & /*state*/) const
{
return 0;
}

typename Postprocessor::DotType
Postprocessor::evaluateDot(const ElemPointArg & /*elem_point_arg*/,
const Moose::StateArg & /*state*/) const
{
return 0;
}
23 changes: 23 additions & 0 deletions framework/src/problems/FEProblemBase.C
Original file line number Diff line number Diff line change
Expand Up @@ -3574,6 +3574,29 @@ FEProblemBase::addPostprocessor(const std::string & pp_name,
"\" already exists. You may not add a Postprocessor by the same name.");

addUserObject(pp_name, name, parameters);

for (THREAD_ID tid = 0; tid < libMesh::n_threads(); tid++)
{
std::vector<UserObject *> uos;
theWarehouse()
.query()
.template condition<AttribName>(name)
.template condition<AttribSystem>("UserObject")
.template condition<AttribThread>(tid)
.queryInto(uos);

if (uos.size() != 1)
mooseError("This query should return exactly one object.");

if (auto * const functor = dynamic_cast<Moose::FunctorBase<Real> *>(uos[0]))
{
this->addFunctor(name, *functor, tid);
if (_displaced_problem)
_displaced_problem->addFunctor(name, *functor, tid);
}
else
mooseError("Post-processors should all cast to Moose::FunctorBase<Real>.");
}
}

void
Expand Down
10 changes: 10 additions & 0 deletions modules/doc/content/newsletter/2023/2023_08.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,16 @@ This makes it ideal for situations in which one of the surfaces is 2D, or if
thermal expansion is provided as a direct user model instead of having the mesh
be deformable. Additionally, the use of functors makes this model very flexible.

### Post-processors can now be used in functor parameters

Post-processors can now be used in [functor](Functors/index.md) parameters, so functor
parameters now support the following inputs, allowing for great flexibility:

- variables (both regular and aux)
- functions
- [functor material properties](FunctorMaterials/index.md)
- post-processors

## libMesh-level Changes

## PETSc-level Changes
Expand Down
85 changes: 85 additions & 0 deletions test/tests/functors/get_functor/get_functor.i
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
[GlobalParams]
execute_on = 'INITIAL'
[]

[Mesh]
type = GeneratedMesh
dim = 1
nx = 5
[]

[AuxVariables]
[testvar]
[]
[]

[AuxKernels]
[testvar_auxkern]
type = FunctionAux
variable = testvar
function = testvar_fn
execute_on = 'INITIAL'
[]
[]

[FunctorMaterials]
[testfmat]
type = GenericFunctorMaterial
prop_names = 'testfmprop'
prop_values = 'testfmat_fn'
[]
[]

[Functions]
[testvar_fn]
type = ParsedFunction
expression = '10*x'
[]
[testfmat_fn]
type = ParsedFunction
expression = '50*x'
[]
[testfn]
type = ParsedFunction
expression = '25*x'
[]
[]

[Postprocessors]
[testpp]
type = ConstantPostprocessor
value = 2
[]

[get_var]
type = ElementIntegralFunctorPostprocessor
functor = testvar
[]
[get_fn]
type = ElementExtremeFunctorValue
functor = testfn
value_type = max
[]
[get_fmprop]
type = ElementExtremeFunctorValue
functor = testfmprop
value_type = max
[]
[get_pp]
type = ElementExtremeFunctorValue
functor = testpp
value_type = max
[]
[]

[Problem]
solve = false
[]

[Executioner]
type = Steady
[]

[Outputs]
csv = true
[]
2 changes: 2 additions & 0 deletions test/tests/functors/get_functor/gold/get_functor_out.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
time,get_fmprop,get_fn,get_pp,get_var,testpp
0,45,22.5,2,5,2
11 changes: 11 additions & 0 deletions test/tests/functors/get_functor/tests
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
[Tests]
issues = '#25012'
design = 'Functors/index.md'

[test]
type = CSVDiff
input = get_functor.i
csvdiff = get_functor_out.csv
requirement = 'The system shall be able to use a variable, function, functor material property, and a post-processor in a functor parameter.'
[]
[]

0 comments on commit 0a5f62a

Please sign in to comment.