# AuxKernels System

The AuxKernel system mimics the Kernels System but compute values that can be defined explicitly with a known function. There are two main use cases for AuxKerenel system: computing a quantity that varies with space and time for postprocessing purposes or for decoupling systems of equations. Examples for both of these use cases shall be discussed further in the following sections.

Creating a custom AuxKernel object is done by creating a new C++ object that inherits from AuxKernel or VectorAuxKernel and overriding the computeValue method, which returns a scalar (Real) or vector (RealVectorValue) for the two types respectively. A third type (AuxScalarKernel) also exists, but the syntax for these objects is different and detailed in the AuxScalarKernels System.

AuxKernel objects, like Kernel objects, must operate on a variable. Thus, there is a required parameter ("variable") that indicates the variable that the AuxKernel object is computing. These variables are defined in the AuxVariables block of the input file, for example the following input file snippet creates an auxiliary variable suitable for use with an VectorAuxKernel.

[AuxVariables]
[vec]
family = LAGRANGE_VEC
order = FIRST
[]
[]

(test/tests/auxkernels/vector_function_aux/vector_function_aux.i)

## Nodal vs Elemental AuxKernel Objects

There are two flavors of AuxKernel objects: nodal and elemental. The distinction is based on the type of variable that is being operated on by the object. If the variable family is LAGRANGE or LAGRANGE_VEC then the AuxKernel will behave as nodal. If the variable family is MONOMIAL then the AuxKernel will behave as an elemental.

The difference is based on how the computeValue method of the object is called when the kernel is executed. In the nodal case the computeValue method will be executed on each node within the finite element mesh and the value returned from the method will directly assign the value of the shape function at that node.

In the elemental case the computeValue method will be executed on each quadrature point of an element of the finite element mesh. The values computed at the quadrature points are used to perform the correct finite element interpolation automatically and set the values for the degrees of freedom. Typically, in the elemental case the order of the monomial finite element is set to constant so there is a single DOF per element, but higher monomials are also supported.

As is evident by the functionality detailed, the distinction between the two arises from the nature of the finite element shape functions. For Lagrange shape functions the DOF values correspond with the nodes, while for monomial shape functions the DOF values are not associated with nodes.

The same AuxKernel object can be designed work both as elemental or nodal, for example the computeValue method for the FunctionAux object properly handles using the correct spatial location based on if the object is nodal or elemental with the isNodal method.

Real
FunctionAux::computeValue()
{
if (isNodal())
return _func.value(_t, *_current_node);
else
return _func.value(_t, _q_point[_qp]);
}

(framework/src/auxkernels/FunctionAux.C)

Nodal AuxKernel objects abuse the notion of quadrature points, the _qp member variable is set to zero, but still must be used to access coupled variable values and material properties. This is done to allow the syntax to be consistent regardless of the AuxKernel flavor: nodal or elemental.

## Execute Flags

AuxKernel objects inherit from the SetupInterface (execute_on) so they include the "execute_on" variable. By default this parameter is set to EXEC_LINEAR and EXEC_TIMESTEP_END. The EXEC_LINEAR flag is set because it is possible to couple values compute by an AuxKernel object to other objects such as Kernel or Material objects that are used in the residual calculation. In order to ensure that the values from the auxiliary variable are correct during the iterative solve they are computed for each iteration.

However, if the auxiliary variable be computed is not being coupled to objects computing the residual evaluating the AuxKernel on each linear iteration is not necessary and can slow down the execution of a simulation. In this case, the EXEC_LINEAR flag should be removed. Likely the EXEC_INITIAL flag should be added to perform the auxiliary variable calculation during the initial setup phase as well.

## Example A: Post processing with AuxKernel

The following example is extracted from step 4 of the Darcy Flow and Thermomechanics Tutorial. Consider Darcy's Law for flow in porous media neglecting changes in time and gravity:

(1) where is the permeability tensor, is the fluid viscosity, and is the pressure and the velocity () may be computed as:

(2)

The left-hand side of Eq. (1) would be solved with a nonlinear variable and an appropriate Kernel object. The AuxKernel system can be used computing the velocity following Eq. (2). In the tutorial the exact calculation is performed using the DarcyVelocity object, the header and source files for this object are listed below.



#pragma once

#include "AuxKernel.h"

// Forward Declarations
class DarcyVelocity;

template <>
InputParameters validParams<DarcyVelocity>();

/**
* Auxiliary kernel responsible for computing the Darcy velocity given
* several fluid properties and the pressure gradient.
*/
class DarcyVelocity : public AuxKernel
{
public:
DarcyVelocity(const InputParameters & parameters);

protected:
/**
* AuxKernels MUST override computeValue.  computeValue() is called on
* points coincide with the nodes.
*/
virtual Real computeValue() override;

/// Will hold 0, 1, or 2 corresponding to x, y, or z.
int _component;

/// The gradient of a coupled variable

/// Holds the permeability and viscosity from the material system
const MaterialProperty<Real> & _permeability;
const MaterialProperty<Real> & _viscosity;
};

(tutorials/darcy_thermo_mech/step04_velocity_aux/include/auxkernels/DarcyVelocity.h)


#include "DarcyVelocity.h"

registerMooseObject("DarcyThermoMechApp", DarcyVelocity);

template <>
InputParameters
validParams<DarcyVelocity>()
{
InputParameters params = validParams<AuxKernel>();

// Declare the options for a MooseEnum.
// These options will be presented to the user in Peacock
// and if something other than these options is in the input file
// an error will be printed
MooseEnum component("x y z");

// Use the MooseEnum to add a parameter called "component"
params.addRequiredParam<MooseEnum>("component", component, "The desired component of velocity.");

// Add a "coupling paramater" to get a variable from the input file.

return params;
}

DarcyVelocity::DarcyVelocity(const InputParameters & parameters)
: AuxKernel(parameters),

// This will automatically convert the MooseEnum to an integer
_component(getParam<MooseEnum>("component")),

// Get the gradient of the variable

// Set reference to the permeability MaterialProperty.
// Only AuxKernels operating on Elemental Auxiliary Variables can do this
_permeability(getMaterialProperty<Real>("permeability")),

// Set reference to the viscosity MaterialProperty.
// Only AuxKernels operating on Elemental Auxiliary Variables can do this
_viscosity(getMaterialProperty<Real>("viscosity"))
{
}

Real
DarcyVelocity::computeValue()
{
// Then pull out the "component" of it we are looking for (x, y or z)
// Note that getting a particular component of a gradient is done using the
// parenthesis operator
return -(_permeability[_qp] / _viscosity[_qp]) * _pressure_gradient[_qp](_component);
}

(tutorials/darcy_thermo_mech/step04_velocity_aux/src/auxkernels/DarcyVelocity.C)

## Example B: Decoupling Equations

Auxiliary variables may be used interchangeably with nonlinear variables with respect to coupling allowing complicated systems of equations to be decoupled for solving individually. This is very useful for testing and validation.

Consider the heat equation with an advective term that is coupled to the pressure computed in Eq. (1) as in step 6 of the Darcy Flow and Thermomechanics Tutorial:

(3) where is temperature, is the heat capacity, is the thermal conductivity, and is the porosity. The advective term () is computed in a kernel object (DarcyConvection.C) and requires the pressure variable be provided as a variable:

  params.addRequiredCoupledVar("darcy_pressure", "The variable representing the pressure.");

(tutorials/darcy_thermo_mech/step06_coupled_darcy_heat_conduction/src/kernels/DarcyConvection.C)

For testing purposes is it not desirable to include the solve for the pressure variable when examining the correctness of the heat equation solve, so an auxiliary variable that is assigned an arbitrary function of space and time is used instead. The following input file snippet demonstrates the decoupling of the pressure variable by computing it using an AuxVariable the FunctionAux object.

[AuxVariables]
[pressure]
[]
[]

[AuxKernels]
[pressure]
type = FunctionAux
variable = pressure
function = 't*x*x*y'
execute_on = timestep_end
[]
[]

(tutorials/darcy_thermo_mech/step06_coupled_darcy_heat_conduction/problems/step6c_decoupled.i)