This article shows how to implement an isotropic elliptic yield
criterion of the Green type in MFront
. Such an example
illustrates the usage of StandardElasticity
brick (see this page). This page is inspired by the
paper of Fritzen et al. (See [1]).
The whole implementation is available here.
The behaviour is described by a standard decomposition of the strain \(\underline{\varepsilon}^{\mathrm{to}}\) in an elastic and a plastic component, respectively denoted \(\underline{\varepsilon}^{\mathrm{el}}\) and \(\underline{\varepsilon}^{\mathrm{p}}\):
\[ \underline{\varepsilon}^{\mathrm{to}}=\underline{\varepsilon}^{\mathrm{el}}+\underline{\varepsilon}^{\mathrm{p}} \]
The stress \(\underline{\sigma}\) is related to the the elastic strain \(\underline{\varepsilon}^{\mathrm{el}}\) by a the standard Hooke law expressed using the Lamé coefficients: \[ \underline{\sigma}= \lambda\,{\mathrm{tr}{\left(\underline{\varepsilon}^{\mathrm{el}}\right)}}\underline{I}+2\,\mu\,\underline{\varepsilon}^{\mathrm{el}} \]
Cette relation est directement prise en charge par la brique
StandardElasticity
.
The behaviour is based on the definition of an equivalent stress \(\sigma_{\mathrm{eq}}\) defined as follows: \[ \sigma_{\mathrm{eq}}=\sqrt{{{\displaystyle \frac{\displaystyle 3}{\displaystyle 2}}}\,C\,\underline{s}\,\colon\,\underline{s}+F\,{\mathrm{tr}{\left(\underline{\sigma}\right)}}^{2}} \] where \(\underline{s}\) is the deviatoric stress tensor: \[ \underline{s}=\underline{\sigma}-{{\displaystyle \frac{\displaystyle 1}{\displaystyle 3}}}\,{\mathrm{tr}{\left(\underline{\sigma}\right)}}\,\underline{I} \] This equivalent stress is an homogeneous function of the stress of degree 1.
The plastic part of the behaviour is described by the following yield surface: \[ f{\left(\underline{\sigma}\right)} = \sigma_{\mathrm{eq}}-\sigma_{0} \] where \(\sigma_{0}\) is the yield stress.
Following the principle of maximum plastic dissipation, the plastic flow is assumed to be associated, so the flow direction \(\underline{n}\) is given by \({\displaystyle \frac{\displaystyle \partial f}{\displaystyle \partial \underline{\sigma}}}\):
\[ \underline{n} = {\displaystyle \frac{\displaystyle \partial f}{\displaystyle \partial \underline{\sigma}}} = {{\displaystyle \frac{\displaystyle 1}{\displaystyle \sigma_{\mathrm{eq}}}}}\,{\left({{\displaystyle \frac{\displaystyle 3}{\displaystyle 2}}}\,C\,\underline{s}+F\,{\mathrm{tr}{\left(\underline{\sigma}\right)}}\,\underline{I}\right)} \]
Since the equivalent stress is an homogeneous function of degree 1, the equivalent plastic strain \(p\) is well defined and the plastic strain rate can be written: \[ \underline{\dot{\varepsilon}}^{\mathrm{p}}=\dot{p}\,\underline{n} \]
The previous constitutive equations will be integrated using a standard implicit scheme.
The first thing that the integration will determine is whether a plastic flow occurs during the time step. To do this, a plastic prediction of the stress is made. If this prediction is inside the yield surface, the step is purely elastic and the integration is trivial. On the other hand, the material must lie on the yield surface at the end of the time step.
The state variable considered will be:
StandardElasticity
brick as eel
.Assuming a plastic loading, the system of equations to be solved is: \[ \left\{ \begin{aligned} \Delta\,\underline{\varepsilon}^{\mathrm{el}}-\Delta\,\underline{\varepsilon}^{\mathrm{to}}+\Delta\,p\,{\left.\underline{n}\right|_{t+\theta\,\Delta\,t}} &= 0 \\ f{\left({\left.\sigma_{\mathrm{eq}}\right|_{t+\theta\,\Delta\,t}}\right)} &= 0 \\ \end{aligned} \right. \]
where \({\left.X\right|_{t+\theta\,\Delta\,t}}\) is the value of \(X\) at \(t+\theta\,\Delta\,t\), \(\theta\) being a numerical parameter. In the following, the first (tensorial) equation is noted \(f_{\underline{\varepsilon}^{\mathrm{el}}}\) and the second (scalar) equation is noted \(f_{p}\).
In practice, it is physically sound to make satisfy exactly the yield condition at the end of the time step (otherwise, stress extrapolation can lead to stress state outside the yield surface and spurious oscillations can also be observed). This leads to the choice \(\theta=1\).
The jacobian \(J\) of the implicit system can be decomposed by blocks: \[ J= \begin{pmatrix} {\displaystyle \frac{\displaystyle \partial f_{\underline{\varepsilon}^{\mathrm{el}}}}{\displaystyle \partial \Delta\,\underline{\varepsilon}^{\mathrm{el}}}} & {\displaystyle \frac{\displaystyle \partial f_{\underline{\varepsilon}^{\mathrm{el}}}}{\displaystyle \partial \Delta\,p}} & \\\\ {\displaystyle \frac{\displaystyle \partial f_{p}}{\displaystyle \partial \Delta\,\underline{\varepsilon}^{\mathrm{el}}}} & {\displaystyle \frac{\displaystyle \partial f_{p}}{\displaystyle \partial \Delta\,p}} \\ \end{pmatrix} \]
The expression of the previous terms is given by:
\[ \left\{ \begin{aligned} {\displaystyle \frac{\displaystyle \partial f_{\underline{\varepsilon}^{\mathrm{el}}}}{\displaystyle \partial \Delta\,\underline{\varepsilon}^{\mathrm{el}}}} &= \underline{I} + dp\,{\displaystyle \frac{\displaystyle \partial {\left.\underline{n}\right|_{t+\theta\,\Delta\,t}}}{\displaystyle \partial \Delta\,\underline{\varepsilon}^{\mathrm{el}}}}\\ {\displaystyle \frac{\displaystyle \partial f_{\underline{\varepsilon}^{\mathrm{el}}}}{\displaystyle \partial \Delta\,p}} &= {\left.\underline{n}\right|_{t+\theta\,\Delta\,t}}\\ {\displaystyle \frac{\displaystyle \partial f_{p}}{\displaystyle \partial \Delta\,\underline{\varepsilon}^{\mathrm{el}}}} &= -\theta\,{\left.\underline{n}\right|_{t+\theta\,\Delta\,t}}\,\colon\,{\left.\underline{\underline{\mathbf{D}}}\right|_{t+\theta\,\Delta\,t}}\\ {\displaystyle \frac{\displaystyle \partial f_{p}}{\displaystyle \partial \Delta\,p}} &= 0 \end{aligned} \right. \]
\[ \begin{aligned} {\displaystyle \frac{\displaystyle \partial {\left.\underline{n}\right|_{t+\theta\,\Delta\,t}}}{\displaystyle \partial \Delta\,\underline{\varepsilon}^{\mathrm{el}}}} &={\displaystyle \frac{\displaystyle \partial {\left.\underline{n}\right|_{t+\theta\,\Delta\,t}}}{\displaystyle \partial {\left.\sigma\right|_{t+\theta\,\Delta\,t}}}}\,{\displaystyle \frac{\displaystyle \partial {\left.\sigma\right|_{t+\theta\,\Delta\,t}}}{\displaystyle \partial {\left.\underline{\varepsilon}^{\mathrm{el}}\right|_{t+\theta\,\Delta\,t}}}}\,{\displaystyle \frac{\displaystyle \partial {\left.\underline{\varepsilon}^{\mathrm{el}}\right|_{t+\theta\,\Delta\,t}}}{\displaystyle \partial \Delta\,\underline{\varepsilon}^{\mathrm{el}}}}\\ &={{\displaystyle \frac{\displaystyle \theta}{\displaystyle \sigma_{\mathrm{eq}}}}}\,{\left({{\displaystyle \frac{\displaystyle 3}{\displaystyle 2}}}\,C\,{\left(\underline{\underline{\mathbf{I}}}-{{\displaystyle \frac{\displaystyle 1}{\displaystyle 3}}}\,\underline{I}\,\otimes\,{\underline{I}}\right)}+F\,\underline{I}\,\otimes\,{\underline{I}}-{\left.\underline{n}\right|_{t+\theta\,\Delta\,t}}\,\otimes\,{\left.\underline{n}\right|_{t+\theta\,\Delta\,t}}\right)}\,\colon\,{\left.\underline{\underline{\mathbf{D}}}\right|_{t+\theta\,\Delta\,t}}\\ &={{\displaystyle \frac{\displaystyle \theta}{\displaystyle \sigma_{\mathrm{eq}}}}}\,{\left({{\displaystyle \frac{\displaystyle 3}{\displaystyle 2}}}\,C\,\,\underline{\underline{\mathbf{I}}}+{\left(F-{\left({{\displaystyle \frac{\displaystyle C}{\displaystyle 2}}}\right)}\right)}\,\underline{I}\,\otimes\,\underline{I}-{\left.\underline{n}\right|_{t+\theta\,\Delta\,t}}\,\otimes\,{\left.\underline{n}\right|_{t+\theta\,\Delta\,t}}\right)}\,\colon\,{\left.\underline{\underline{\mathbf{D}}}\right|_{t+\theta\,\Delta\,t}}\\ \end{aligned} \]
This expression could be further simplified.
Assuming an elastic loading, the system of equations to be solved is trivially: \[ \left\{ \begin{aligned} \Delta\,\underline{\varepsilon}^{\mathrm{el}}-\Delta\,\underline{\varepsilon}^{\mathrm{to}}&= 0 \\ \Delta\,p &= 0 \\ \end{aligned} \right. \]
The jacobian associated with this system is the identity matrix.
In the plastic loading case, the system of equations to be solved is
non-linear. We choose the Newton-Raphson algorithm with an
analytical jacobian. Compared to other algorithm available in
MFront
(Runge-Kutta, Broyden, Newton-Raphson with numerical
jacobian, etc..), this algorithm is generally the most
efficient in pratice.
The implementation begins with the choice of the
Implicit
domain specific language (dsl):
@DSL Implicit;
Note that this dsl automatically declares the elastic strain
eel
as a state variable.
As discussed before, we explicit state that a fully implicit integration will be used by default:
@Theta 1;
This value can be changed at runtime by modifying the
theta
parameter.
The stopping criterion is chosen low, to ensure the quality of the consistent tangent operator (the default value, \(10^{-8}\) is enough to ensure a good estimation of the state variable evolution, but is not enough to have a proper estimation of the consistent tangent operator):
@Epsilon 1e-14;
We then declare that we want to support all the modelling hypotheses:
@ModellingHypotheses {".+"};
The support of plane stress modelling hypotheses are handled by the
StandardElasticity
brick and will not be discussed
here.
StandardElasticity
brickTo implement this behaviour, we will use the
StandardElasticity
brick which provides:
This behaviour brick is fully described here.
The usage of the StandardElasticity
is declared as
follows:
@Brick StandardElasticity;
The elastic stiffness tensor \(D\)
is defined using @ComputeStiffnessTensor
keyword by giving
the elastic material properties as constants:
@ComputeStiffnessTensor<UnAltered> {150e9,0.3};
This computed stiffness is stored in a variable D
. A
second variable D_tdt
is also introduced. As the material
properties are constants, D_tdt
is an alias to
D
.
The elastic material properties can be changed at runtime time by
modifying the following parameters: YoungModulus
and
PoissonRatio
.
Rather than constants, one can also use correlations implemented in
seperate MFront
files. This allows to take into account the
dependency of the material properties with the temperature for example.
In this case, the variable D
contains the stiffness tensor
at \(t+\theta\,\Delta\,t\) and the
variable D_tdt
contains the stiffness tensor at \(t+\Delta\,t\).
Another possibility is to use the
@RequireStiffnessTensor
keyword. In this case, the elastic
material properties must be computed by the calling solver at the end of
the time step (and furnished to the mechanical behaviours through hidden
material properties).
As stated earlier, the state variable eel
is
automatically declared by the Implicit
dsl.
The equivalent plastic strain state variable p
is
declared as:
@StateVariable real p;
We then associate the appropriate glossary name to this variable:
.setGlossaryName("EquivalentPlasticStrain"); p
The definition of yield surface introduces three material coefficients \(C\), \(F\) and \(\sigma_{0}\) that we declare as a parameter:
@Parameter C = 0.8;
.setEntryName("GreenYieldCriterion_C");
C@Parameter F = 0.2;
.setEntryName("GreenYieldCriterion_F");
F@Parameter s0 = 150e6;
.setGlossaryName("YieldStress"); s0
The YieldStress
is an entry of the glossary (see here).
To select the implicit system associated either with the elastic or
plastic loading case, we introduce a boolean local variable
b
.
@LocalVariable bool b; // if true, plastic loading
Before solving the implicit system, the code block introduced by the
@InitLocalVariables
keyword is executed. For this
behaviour, this block will select either the elastic or plastic loading
case.
We first make an elastic prediction of the stress at the end
of the time step. We use the computeElasticPrediction
method introduced by the StandardElasticity
brick. This
method takes into account the modelling hypothesis, which is mandatory
for plane stress modelling hypotheses. We then make an elastic
prediction of the Hill equivalent stress and check whether or not this
elastic prediction is inside the elastic domain. The latter information
is stored in the boolean value b
which will be
false
(no plastic loading) if the loading is elastic.
@InitLocalVariables{
const auto sig_el = computeElasticPrediction();
const auto s_el = deviator(sig_el);
const auto tr_el = trace(sig_el);
const auto seq = sqrt(3*C*(s_el|s_el)/2+F*tr_el*tr_el);
= seq-s0 > 0;
b }
Finally, we describe how the implicit system and the computation of
the jacobian is written in a code block introduced by the
@Integrator
keyword.
We use the following facts:
feel
is initialized to
deel
).dfeel_ddeel
is initialized to the
identity tensor).feel
by the StandardElasticity
brick.Apart from those facts, the code is an almost direct translation of the mathematical expression described in previous sections and boils down to the following lines of code:
@Integrator{
constexpr const auto id = Stensor::Id();
constexpr const auto id4 = Stensor4::Id();
if(b){
const auto hC = C/2;
const auto s = deviator(sig);
const auto tr = trace(sig);
const auto seq = sqrt(3*hC*(s|s)+F*tr*tr);
const auto iseq = 1/(max(seq,real(1.e-10*young)));
const auto n = eval(iseq*(3*hC*s+F*tr*id));
// elasticity
+= dp*n;
feel += theta*dp*iseq*(3*hC*id4+(F-hC)*(id^id)-(n^n))*D;
dfeel_ddeel = n;
dfeel_ddp // plasticity
= (seq-s0)/young;
fp = strain(0);
dfp_ddp = theta*(n|D)/young;
dfp_ddeel }
}