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 authored and oanaoana committed Oct 19, 2023
1 parent 2916b82 commit 8f89725
Show file tree
Hide file tree
Showing 11 changed files with 349 additions and 10 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
1 change: 1 addition & 0 deletions framework/include/postprocessors/ParsedPostprocessor.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,5 +44,6 @@ class ParsedPostprocessor : public GeneralPostprocessor, public FunctionParserUt
/// This post-processor value
Real _value;

using Moose::FunctorBase<Real>::evaluate;
usingFunctionParserUtilsMembers(false);
};
67 changes: 66 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 @@ -38,11 +40,74 @@ class Postprocessor : public OutputInterface, public NonADFunctorInterface
*/
virtual PostprocessorValue getValue() const;

/**
* Gets the current value stored in the ReporterData.
*
* In most (but not all) cases, this should return the same as \c getValue().
*/
PostprocessorValue getCurrentReporterValue() const;

/**
* Returns the name of the Postprocessor.
*/
std::string PPName() const { return _pp_name; }

protected:
/// MOOSE object
const MooseObject & _pp_moose_object;

/// Post-processor name
const std::string _pp_name;

/// FE problem
FEProblemBase & _pp_fe_problem;

/// Reporter data
ReporterData & _reporter_data;

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;

/**
* Gives a one-time warning for calling an \c evaluateDot() method.
*/
void evaluateDotWarning() const
{
mooseDoOnce(
mooseWarning("The time derivative functor operator was called on the post-processor '",
_pp_name,
"'. A zero value will always be returned, even if the post-processor value "
"changes with time."));
}
};
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
128 changes: 120 additions & 8 deletions framework/src/postprocessors/Postprocessor.C
Original file line number Diff line number Diff line change
Expand Up @@ -30,26 +30,28 @@ Postprocessor::validParams()
Postprocessor::Postprocessor(const MooseObject * moose_object)
: OutputInterface(moose_object->parameters()),
NonADFunctorInterface(moose_object),
_pp_name(moose_object->name())
Moose::FunctorBase<Real>(moose_object->name()),
_pp_moose_object(*moose_object),
_pp_name(moose_object->name()),
_pp_fe_problem(
*moose_object->parameters().getCheckedPointerParam<FEProblemBase *>("_fe_problem_base")),
_reporter_data(_pp_fe_problem.getReporterData(ReporterData::WriteKey()))
{
auto & fe_problem =
*moose_object->parameters().getCheckedPointerParam<FEProblemBase *>("_fe_problem_base");

const PostprocessorReporterName r_name(moose_object->name());
const PostprocessorReporterName r_name(_pp_name);

// Declare the Reporter value on thread 0 only; this lets us add error checking to
// make sure that it really is added only once
if (moose_object->parameters().get<THREAD_ID>("_tid") == 0)
{
mooseAssert(!fe_problem.getReporterData().hasReporterValue<PostprocessorValue>(r_name),
mooseAssert(!_reporter_data.hasReporterValue<PostprocessorValue>(r_name),
"Postprocessor Reporter value is already declared");

fe_problem.getReporterData(ReporterData::WriteKey())
_reporter_data
.declareReporterValue<PostprocessorValue, ReporterGeneralContext<PostprocessorValue>>(
r_name, REPORTER_MODE_UNSET, *moose_object);
}
else
mooseAssert(fe_problem.getReporterData().hasReporterValue<PostprocessorValue>(r_name),
mooseAssert(_reporter_data.hasReporterValue<PostprocessorValue>(r_name),
"Postprocessor Reporter value is not declared");
}

Expand All @@ -64,3 +66,113 @@ Postprocessor::getValue() const
{
mooseError("getValue() (const or non-const) must be implemented.");
}

PostprocessorValue
Postprocessor::getCurrentReporterValue() const
{
return _reporter_data.getReporterValue<PostprocessorValue>(
PostprocessorReporterName(_pp_name), _pp_moose_object, REPORTER_MODE_ROOT);
}

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

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

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

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

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

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
{
evaluateDotWarning();
return 0;
}

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

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

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

typename Postprocessor::DotType
Postprocessor::evaluateDot(const ElemPointArg & /*elem_point_arg*/,
const Moose::StateArg & /*state*/) const
{
evaluateDotWarning();
return 0;
}
39 changes: 39 additions & 0 deletions framework/src/problems/FEProblemBase.C
Original file line number Diff line number Diff line change
Expand Up @@ -3574,6 +3574,45 @@ 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);

UserObject * uo = nullptr;
if (uos.size() == 1)
uo = uos[0];
else
{
std::vector<UserObject *> uos_tid0;
theWarehouse()
.query()
.template condition<AttribName>(name)
.template condition<AttribSystem>("UserObject")
.template condition<AttribThread>(0)
.queryInto(uos_tid0);

if (uos_tid0.size() == 1)
uo = uos_tid0[0];
else
mooseError("This query should return exactly one object.");
}

if (auto * const functor = dynamic_cast<Moose::FunctorBase<Real> *>(uo))
{
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 @@ -31,6 +31,16 @@ be deformable. Additionally, the use of functors makes this model very flexible.
[NearestPointLayeredSideAverage.md] to accept any [functor](Functors/index.md),
not just variables.

### 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

0 comments on commit 8f89725

Please sign in to comment.