(sec:extending:plugin-types:material-models)=
# Material models
The material model is responsible for describing the various coefficients in
the equations that ASPECT solves. To implement
a new material model, you need to overload the
[aspect::MaterialModel::Interface](https://aspect.geodynamics.org/doc/doxygen/namespaceaspect_1_1MaterialModel.html)
class and use the
`ASPECT_REGISTER_MATERIAL_MODEL` macro to register your new class. The
implementation of the new class should be in namespace
`aspect::MaterialModel`. An example of a material model implemented this way
is given in {ref}`sec:benchmarks:davies_et_al:case2.3`.
Specifically, your new class needs to implement the following interface:
```{code-block} c++
template
class aspect::MaterialModel::Interface
{
public:
// Physical parameters used in the basic equations
virtual void evaluate(const MaterialModelInputs &in, MaterialModelOutputs &out) const=0;
virtual bool is_compressible () const = 0;
// Reference quantities
virtual double reference_viscosity () const = 0;
// Functions used in dealing with run-time parameters
static void
declare_parameters (ParameterHandler &prm);
virtual void
parse_parameters (ParameterHandler &prm);
// Optional:
virtual void initialize ();
virtual void update ();
}
```
The main properties of the material are computed in the function evaluate()
that takes a struct of type MaterialModelInputs and is supposed to fill a
MaterialModelOutputs structure. For performance reasons this function is
handling lookups at an arbitrary number of positions, so for each variable
(for example viscosity), a std::vector is returned. The following members of
MaterialModelOutputs need to be filled:
```{code-block} c++
struct MaterialModelOutputs
{
std::vector viscosities;
std::vector densities;
std::vector thermal_expansion_coefficients;
std::vector specific_heat;
std::vector thermal_conductivities;
std::vector compressibilities;
}
```
The variables refer to the coefficients $\eta,C_p,k,\rho$ in equations
{math:numref}`eq:stokes-1`–{math:numref}`eq:temperature`, each as a function of
temperature, pressure, position, compositional fields and, in the case of the
viscosity, the strain rate (all handed in by MaterialModelInputs).
Implementations of evaluate() may of course choose to ignore dependencies on
any of these arguments. In writing a new material model, you should consider
coefficient self-consistency
({ref}`sec:coefficient_self_consistency`).
The remaining functions are used in postprocessing as well as handling
run-time parameters. The exact meaning of these member functions is documented
in the [aspect::MaterialModel::Interface](https://aspect.geodynamics.org/doc/doxygen/namespaceaspect_1_1MaterialModel.html)
class documentation. Note that some of the
functions listed above have a default implementation, as discussed on the
documentation page just mentioned.
The function `is_compressible` returns whether we should consider the material
as compressible or not, see {ref}`sec:methods:approximate-equations:ba` on the
Boussinesq model. As discussed there, incompressibility as described by this
function does not necessarily imply that the density is constant; rather, it
may still depend on temperature or pressure. In the current context,
compressibility simply means whether we should solve the continuity equation
as $\nabla \cdot (\rho \mathbf u)=0$ (compressible Stokes) or as
$\nabla \cdot \mathbf{u}=0$ (incompressible Stokes).
The purpose of the parameter handling functions has been discussed in the
general overview of plugins above.
The functions initialize() and update() can be implemented if desired (the
default implementation does nothing) and are useful if the material model has
internal state. The function initialize() is called once during the
initialization of ASPECT and can be used to
allocate memory, initialize state, or read information from an external file.
The function update() is called at the beginning of every time step.
Additionally, every material model has a member variable
"modeldependence," declared in the Interface class, which can be
accessed from the plugin as `this$\rightarrow$modeldependence`.
This structure describes the nonlinear dependence of the various coefficients
on pressure, temperature, composition or strain rate. This information will be
used in future versions of ASPECT to implement
a fully nonlinear solution scheme based on, for example, a Newton iteration.
The initialization of this variable is optional, but only plugins that declare
correct dependencies can benefit from these solver types. All packaged
material models declare their dependencies in the parseparameters() function
and can be used as a starting point for implementations of new material
models.
Older versions of ASPECT used to have
individual functions like `viscosity()` instead of the `evaluate()` function
discussed above. This old interface is no longer supported, restructure your
plugin to implement `evaluate()` instead (even if this function only calls the
old functions).