FunctorMaterials

Much like regular materials declare regular material properties, functor materials declare functor material properties. Functor material properties are properties that are evaluated on-the-fly. Along with multiple other classes of MOOSE objects, they are Functors. This allows for the creation of objects with considerable inter-operability between systems.

Using functor materials

Following a producer/consumer model, FunctorMaterials produce functor material properties, which kernels, boundary conditions, other functor materials, etc, may consume. Both regular and functor material properties support a wide array of data types (scalar, vector, tensors, automatic differentiation versions of all of these). Functor materials, because they are evaluated on-the-fly and call other functors on-the-fly as well, do not require dependency ordering.

All functor materials support caching in some capacity. This can avoid expensive material property computations, but is disabled by default due to the potential memory cost. The reader is referred to the Functors caching documentation.

warningwarning

Functor material properties and regular material properties are generally NOT compatible with each other. Functor material properties can only be used as regular material properties using a MaterialFunctorConverter to process them.

Functor materials are created within the [FunctorMaterials] block.

commentnote

If a Functor is reported as missing by the simulation, and it was supposed to be created by a FunctorMaterial, you may use the Debug/"show_functors" parameter to get more information about what functors were created and requested.

Developing with functor materials

Evaluating functors

See the Functor system documentation for information on how to retrieve a functor material property value in a kernel, boundary condition, ... even another functor material property.

Creating functor material properties

The functor material property system introduces APIs slightly different from the traditional material property system for declaring/adding and getting properties. To add a functor property:

  • addFunctorProperty<TYPE>

where TYPE can be anything such as Real, ADReal, RealVectorValue, ADRealVectorValue etc. To get a functor material property:

  • getFunctor<TYPE>

It's worth noting that whereas the traditional regular material property system has different methods to declare/get non-AD and AD properties, the new functor system has single APIs for both non-AD and AD property types.

Functor material property evaluations are defined using the API:


template <typename T, typename PolymorphicLambda>
const Moose::FunctorBase<T> &
FunctorMaterial::addFunctorProperty(const std::string & name,
                                    PolymorphicLambda my_lammy,
                                    const std::set<ExecFlagType> & clearance_schedule = {
                                        EXEC_ALWAYS});

where the first argument will be the functor name stored in the problem functor database (all functor names must be unique), the second argument is a lambda defining the property evaluation, and the third optional argument is a set defining at which execution stages the functor evaluation cache should be cleared. The lambda must be callable with two arguments, the first corresponding to space, and the second corresponding to time, and must return the type T of the FunctorMaterialProperty. An example of adding a constant functor material property that returns a Real looks like:


    addFunctorProperty<Real>(
        "foo", [](const auto &, const auto &) -> Real { return 1.; });

An example of a functor material property that depends on a fluid properties user object and pressure and temperature functors looks like


  addFunctorProperty<ADReal>(_density_name,
                             [this](const auto & r, const auto & t) -> ADReal
                             { return _fluid.rho_from_p_T(_pressure(r, t), _temperature(r, t)); });

In the above example, we simply forward the calling arguments along to the captured functors. _pressure and _temperature are captured in the lambda function because they are attributes to the local FunctorMaterial class, and [this] in the function definition captures all attributes from the class. Variable functor implementation is described in Variable functor evaluation. A test functor material class to setup a dummy Euler problem is shown in


#include "ADCoupledVelocityMaterial.h"

registerMooseObject("MooseTestApp", ADCoupledVelocityMaterial);

InputParameters
ADCoupledVelocityMaterial::validParams()
{
  InputParameters params = FunctorMaterial::validParams();
  params.addRequiredParam<MooseFunctorName>("vel_x", "the x velocity");
  params.addParam<MooseFunctorName>("vel_y", "the y velocity");
  params.addParam<MooseFunctorName>("vel_z", "the z velocity");
  params.addRequiredParam<MooseFunctorName>("rho", "The name of the density variable");
  params.addClassDescription("A material used to create a velocity from coupled variables");
  params.addParam<MaterialPropertyName>(
      "velocity", "velocity", "The name of the velocity material property to create");
  params.addParam<MaterialPropertyName>(
      "rho_u", "rho_u", "The product of the density and the x-velocity component");
  params.addParam<MaterialPropertyName>(
      "rho_v", "rho_v", "The product of the density and the y-velocity component");
  params.addParam<MaterialPropertyName>(
      "rho_w", "rho_w", "The product of the density and the z-velocity component");
  params.set<ExecFlagEnum>("execute_on") = {EXEC_ALWAYS};
  return params;
}

ADCoupledVelocityMaterial::ADCoupledVelocityMaterial(const InputParameters & parameters)
  : FunctorMaterial(parameters),
    _vel_x(getFunctor<ADReal>("vel_x")),
    _vel_y(isParamValid("vel_y") ? &getFunctor<ADReal>("vel_y") : nullptr),
    _vel_z(isParamValid("vel_z") ? &getFunctor<ADReal>("vel_z") : nullptr),
    _rho(getFunctor<ADReal>("rho"))
{
  const std::set<ExecFlagType> clearance_schedule(_execute_enum.begin(), _execute_enum.end());

  addFunctorProperty<ADRealVectorValue>(
      getParam<MaterialPropertyName>("velocity"),
      [this](const auto & r, const auto & t) -> ADRealVectorValue
      {
        ADRealVectorValue velocity(_vel_x(r, t));
        velocity(1) = _vel_y ? (*_vel_y)(r, t) : ADReal(0);
        velocity(2) = _vel_z ? (*_vel_z)(r, t) : ADReal(0);
        return velocity;
      },
      clearance_schedule);

  addFunctorProperty<ADReal>(
      getParam<MaterialPropertyName>("rho_u"),
      [this](const auto & r, const auto & t) -> ADReal { return _rho(r, t) * _vel_x(r, t); },
      clearance_schedule);

  addFunctorProperty<ADReal>(
      getParam<MaterialPropertyName>("rho_v"),
      [this](const auto & r, const auto & t) -> ADReal
      { return _vel_y ? _rho(r, t) * (*_vel_y)(r, t) : ADReal(0); },
      clearance_schedule);

  addFunctorProperty<ADReal>(
      getParam<MaterialPropertyName>("rho_w"),
      [this](const auto & r, const auto & t) -> ADReal
      { return _vel_z ? _rho(r, t) * (*_vel_z)(r, t) : ADReal(0); },
      clearance_schedule);
}
(moose/test/src/materials/ADCoupledVelocityMaterial.C)

Spatial arguments

See the general Functor documentation for an explanation about the spatial arguments that may be used for functor material properties.

Value Caching

See the general Functor documentation for an explanation about the caching capabilities that may be used with functor material properties.