The tensor mechanics module provides a powerful system for solving solid mechanics problems using a simple to use syntax based on tensor forms. This approach allows the tensor equations to be implemented clearly and concisely.

A material varies from its rest shape due to stress. This departure from the rest shape is called deformation or displacement, and the proportion of deformation to original size is called strain. To determine the deformed shape and the stress, a governing equation is solved to determine the displacement vector $$$\mathbf{u}$$$.

The strong form of the governing equation on the domain $$$\Omega$$$ and boundary $$$\Gamma=\Gamma_{\mathit{\iota _i}}\cup\Gamma_{\mathit{g_i}}$$$ can be stated as follows: $$$$\begin{eqnarray} \nabla \cdot (\boldsymbol{\sigma} + \boldsymbol{\sigma}_0) + \mathbf{b} &=& \mathbf{0} \;\mathrm{in}\;\Omega \\ \mathbf{u} &=& \mathbf{g}\;\mathrm{in}\;\Gamma_{ \mathbf{g}} \\ \boldsymbol{\sigma} \cdot \mathbf{n}&=&\boldsymbol{\iota}\;\mathrm{in}\;\Gamma_{ \boldsymbol{\iota}} \end{eqnarray}$$$$ where $$$\boldsymbol{\sigma}$$$ is the Cauchy stress tensor, $$$\boldsymbol{\sigma}_0$$$ is an additional source of stress (such as pore pressure), $$$\mathbf{u}$$$ is the displacement vector, $$$\mathbf{b}$$$ is the body force, $$$\mathbf{n}$$$ is the unit normal to the boundary, $$$\mathbf{g}$$$ is the prescribed displacement on the boundary and $$$\boldsymbol{\iota}$$$ is the prescribed traction on the boundary. The weak form of the residual equation is expressed as: \begin{eqnarray} \mathbb{R} = \left( \boldsymbol{\sigma} + \boldsymbol{\sigma}_0, \nabla \phi_m \right) - \left< \boldsymbol{\iota}, \phi_m \right> - \left( \mathbf{b}, \phi_m \right) = \mathbf{0}, \end{eqnarray} where $$$(\cdot)$$$ and $$$\left< \cdot \right>$$$ represent volume and boundary integrals, respectively. The solution of the residual equation with Newton's method requires the Jacobian of the residual equation, which can be expressed as (ignoring boundary terms) \begin{eqnarray} \mathbb{J} = \left( \frac{\partial \boldsymbol{\sigma}}{\partial \nabla \mathbf{u}} , \nabla \phi_m \right), \end{eqnarray} assuming $$$\boldsymbol{\sigma}_0$$$ is independent of the strain.

The material stress response is described by the constitutive model, where the stress is determined as a function of the strain, i.e. $$$\tilde{\boldsymbol{\sigma}}( \boldsymbol{\epsilon} - \boldsymbol{\epsilon}_0)$$$, where $$$\boldsymbol{\epsilon}$$$ is the strain and $$$\boldsymbol{\epsilon}_0$$$ is a stress free strain. For example, in linear elasticity (only valid for small strains), the material response is linear, i.e. $$$\boldsymbol{\sigma} = \boldsymbol{\mathcal{C}}(\boldsymbol{\epsilon} - \boldsymbol{\epsilon}_0)$$$. The tensor mechanics system can handle linear elasticity and finite strain mechanics, including both elasticity and plasticity.

The tensor mechanics module uses a modular system where the main tensors used in the residual equation are defined in individual material classes in MOOSE. The three tensors that must be defined for any mechanics problem are the elasticity tensor $$$\boldsymbol{\mathcal{C}}$$$, the strain $$$\boldsymbol{\epsilon}$$$ or strain increment, and the stress $$$\boldsymbol{\sigma}$$$. Optional tensors include additional stress $$$\boldsymbol{\sigma}_0$$$ and stress-free strain $$$\boldsymbol{\epsilon}_0$$$.

At times, a user may need to define multiple mechanics properties over a single block. For this reason, all material properties can be prepended by a name defined by the input parameter base_name.

The primary class for creating elasticity tensors ($$$\boldsymbol{\mathcal{C}}$$$) is `ComputeElasticityTensor`

(Doxygen). It defines the property

_elasticity_tensor(declareProperty<ElasticityTensorR4>(_base_name + "elasticity_tensor"))

It can also be used as a base class to create specialized code for more complicated elasticity tensors. Given the elastic constants required for the applicable symmetry, the material calculates the elasticity tensor. If you wish to rotate the elasticity tensor, constant Euler angles can be provided. The elasticity tensor can also be scaled with a function, if desired. The input file syntax to create an elasticity tensor is

[./elasticity_tensor] type = ComputeElasticityTensor block = 0 C_ijkl = '1 1' fill_method = symmetric_isotropic [../]

The base material class to create strains ($$$\boldsymbol{\epsilon}$$$) or strain increments is `ComputeStrainBase`

(Doxygen). For small strain it defines the property

_total_strain(declareProperty<RankTwoTensor>(_base_name + "total_strain"))

For incremental strains, both finite and small, the compute strain base class defines

_strain_rate(declareProperty<RankTwoTensor>(_base_name + "strain_rate")), _strain_increment(declareProperty<RankTwoTensor>(_base_name + "strain_increment")), _rotation_increment(declareProperty<RankTwoTensor>(_base_name + "rotation_increment")), _deformation_gradient(declareProperty<RankTwoTensor>(_base_name + "deformation gradient"))

It is a pure virtual class, requiring that all children override the `computeQpProperties()`

function. The strain is typically either small or finite strain. For small strains, use ComputeSmallStrain in which $$$\boldsymbol{\epsilon} = (\nabla \mathbf{u} + \nabla \mathbf{u}^T)/2$$$. For finite strains, use ComputeFiniteStrain in which an incremental form is employed such that the strain_increment and rotation_increment are calculated. For more information, see Finite Strain.

Thermal expansion is behavior common for all materials and has been implemented as a `stress_free_strain`

; Thermal strains are discussed in this category.

therefore it has been implemented in both `ComputeFiniteStrain`

(Doxygen) and `ComputeSmallStrain`

(Doxygen). For this reason, the base class `ComputeStrainBase`

has a coupled temperature that is only supplied when thermal expansion is to be considered.

The input file syntax for small strains and finite strains are

[./small_strain] type = ComputeSmallStrain displacements = 'disp_x disp_y disp_z' [../] [./finite_strain] type = ComputeFiniteStrain displacements = 'disp_x disp_y disp_z' [../]

The base class for constitutive equations to compute a stress ($$$\boldsymbol{\sigma}$$$) is `ComputeStressBase`

(Doxygen). It defines the property

_stress(declareProperty<RankTwoTensor>(_base_name + "stress")), _elastic_strain(declareProperty<RankTwoTensor>(_base_name + "elastic_strain"))

It is a pure virtual class, requiring all children to override `computeQpStress()`

. Two elastic constitutive models have been developed, one that assumes small strains (`ComputeLinearElasticStress`

(Doxygen) and the other finite strains (`ComputeFiniteStrainElasticStress`

(Doxygen)). The input file syntax for these materials are

[./linear_elastic_stress] type = ComputeLinearElasticStress block = 0 [../] [./finite_strain_elastic_stress] type = ComputeFiniteStrainElasticStress block = 0 [../]

There are a number of other constitutive models that have been implemented.

Thermal strains are a volumetric change resulting from a change in temperature of the material. The change in strains can be either a simple linear function of thermal change, e.g. ($$$\boldsymbol{\epsilon}_T = \alpha \Delta T$$$) or a more complex function of temperature. Besides thermal expansion, some models employ other stress-free strains ($$$\boldsymbol{\epsilon}_0$$$) to provide inherit strains in the material. This approach can also be used to include pressures that need to be included in a nonlinear constitutive model solve. The base class for stress-free strains is `ComputeStressFreeStrainBase`

(Doxygen). It defines the property

_stress_free_strain(declareProperty<RankTwoTensor>(_base_name + "stress_free_strain"))

For example, the stress_free_strain property is used in the `ComputeSmallStrain`

material as shown below:

//Remove the Eigen strain _total_strain[_qp] -= _stress_free_strain[_qp];

It is a pure virtual class, requiring all children to override `computeQpStressFreeStrain()`

.

The thermal expansion class, `ComputeThermalExpansionEigenStrains`

(Doxygen), inherits from `ComputeStressFreeStrainBase`

to compute the thermal strains for both small total strains and for incremental strains as a linear function of temperature. The input file syntax is

[./thermal_strains] type = ComputeThermalExpansionEigenStrains temperature = temp thermal_expansion_coefficient = 1.0e-4 stress_free_reference_temperature = 300 [../]

Other stress-free strains could be caused by defects such as over-sized or under-sized second phase particles. One stress-free strain material that has been implemented is `ComputeVariableEigenstrain`

(Doxygen). It computes a lattice mismatch due to a secondary phase, where the form of the tensor is defined by an input vector, and the scalar dependence on a phase variable is defined in another material. The input file syntax is

[./var_dependence] type = DerivativeParsedMaterial block = 0 function = 0.5*c^2 args = c outputs = exodus f_name = var_dep enable_jit = true third_derivatives = false [../] [./eigen_strain] type = ComputeVariableEigenstrain block = 0 eigen_base = '1 1 1 0 0 0' v = c variable_dependence = var_dep [../]

Note the `DerivativeParsedMaterial`

, which evaluates an expression given in the input file (and its automatically generated derivatives) at each quadrature point.

Extra stresses ($$$\boldsymbol{\sigma}_0$$$) can also be pulled into the residual calculation after the constitutive model calculation of the stress. Though no base class has been created for this, it would be straight forward to do so and it would need to define the property

_extra_stress(declareProperty<RankTwoTensor>(_base_name + "extra_stress"))

It is used in `ComputeStressBase`

as shown below:

void ComputeStressBase::computeQpProperties() { computeQpStress(); //Add in extra stress _stress[_qp] += _extra_stress[_qp]; }