Overview

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.

Mathematical Introduction

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.

Using TensorMechanics

Code

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.

Elasticity Tensor

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
  [../]

Strain

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'
  [../]

Stress

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.

Stress-Free Strains (Eigenstrains)

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

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];
}