# Small strain plasticity¶

A framework for the approximation of plasticity models in *GetFEM*. See in `src/getfem_plasticity.cc`

and `interface/src/gf_model_set.cc`

for the brick implementation and to extend the implementation to new plasticity models.

## Theoretical background¶

We present a short introduction to small strain plasticity. We refer mainly to [SI-HU1998] and [SO-PE-OW2008] for a more detailed presentation.

### Additive decomposition of the small strain tensor¶

Let \(\Omega \subset \rm I\hspace{-0.15em}R^3\) be the reference configuration of a deformable body and \(u : \Omega \rightarrow \rm I\hspace{-0.15em}R^3\) be the displacement field. Small strain plasticity is based on the additive decomposition of the small strain tensor \(\varepsilon(u) = \dfrac{\nabla u + \nabla u^T}{2}\) in

where \(\varepsilon^e\) is the elastic part of the strain tensor and \(\varepsilon^p\) the plastic one.

### Internal variables, free energy potential and elastic law¶

We consider

a vector field of \(d_{\alpha}\) strain type internal variables (\(d_{\alpha} = 0\) if no internal variables are considered). We consider also a free energy potential

such that corresponding stress type variables are determined by

where \(\sigma\) is the Cauchy stress tensor and \(A\) the stress type internal variables. The plastic dissipation is given by

In the standard cases, \(\psi(\varepsilon^e, \alpha)\) is decomposed into

In the case of linearized elasticity, one has \(\psi^e(\varepsilon^e) = \frac{1}{2} ({\cal A}\varepsilon^e) :\varepsilon^e\) where \({\cal A}\) is the fourth order elasticity tensor. For isotropic linearized elasticity this expression reduces to \(\psi^e(\varepsilon^e) = \mu \mbox{dev}(\varepsilon^e) : \mbox{dev}(\varepsilon^e) + \frac{1}{2} K (\mbox{tr}(\varepsilon^e))^2\) where \(\mu\) is the shear modulus and \(K = \lambda + 2\mu/3\) is the bulk modulus.

### Plastic potential, yield function and plastic flow rule¶

Plastic yielding is supposed to occur when the stress attains a critical value. This limit is determined by a yield function \(f(\sigma, A)\) and the condition

The surface \(f(\sigma, A) = 0\) is the yield surface where the plastic deformation may occur.

Let us also consider the plastic potential \(\Psi(\sigma, A)\), (convex with respect to its both variables) which determines the plastic flow direction in the sense that the flow rule is defined as

with the additional complementarity condition

The variable \(\gamma\) is called the plastic multiplier. Note that when \(\psi(\varepsilon^e, \alpha), f(\sigma, A) \mbox{ or } \Psi(\sigma, A)\) are not differentiable, subdifferentials have to be used. Associated plasticity corresponds to the choice \(\Psi(\sigma, A) = f(\sigma, A)\).

### Initial boundary value problem¶

The weak formulation of a dynamic elastoplastic problem can be written, for an arbitrary kinematically admissible test function \(v\), as follows:

for \(u_0, \mathrm{v}_0, \varepsilon^p_0, \alpha_0\) being initial values and \(f\) and \(g\) being prescribed forces in the interior of domain \(\Omega\) and on the part of the boundary \(\Gamma_N\).

Note that plasticity models are often applied on quasi-static problems which correspond to the term \(\rho \ddot{u}\) being neglected.

Given a time step \(\Delta t = t_{n+1} -t_n\), from time \(t_n\) to \(t_{n+1}\), we will denote in the sequel \(u_n, \varepsilon^p_n \mbox{ and } \alpha_n\) the approximations at time \(t_n\) of \(u(t_n), \varepsilon^p_n(t_n) \mbox{ and } \alpha(t_n)\) respectively. These approximations correspond to the chosen time integration scheme (for instance one of the proposed schemes in The model tools for the integration of transient problems) which can be different than the time integration scheme used for the integration of the flow rule (see below).

## Flow rule integration¶

The plastic flow rule has to be integrated with its own time integration scheme. Among standards schemes, the backward Euler scheme, the \(\theta\)-scheme (or generalized trapezoidal rule) and the generalized mid-point scheme are the most commonly used in that context. We make here the choice of the \(\theta\)-scheme (\(\theta = 1\) corresponds to the backward Euler scheme as a special case).

Let \(u_{n+1}\) be the displacement at the considered time step and \(u_{n}\) at the previous one.

The \(\theta\)-scheme for the integration of the plastic flow rules reads as

with the complementary condition

where \(0 < \theta \le 1\) is the parameter of the \(\theta\)-scheme. We exclude \(\theta = 0\) because we will not consider explicit integration of plasticity. Let us recall that \(\theta = 1\) corresponds to the backward Euler scheme and \(\theta = 1/2\) to the Crank-Nicolson scheme (or trapezoidal rule) which is a second order consistent scheme. Note that the complementarity condition for the quantities at time step \(n\) is prescribed at the previous time step (\(\sigma_{n}, \alpha_n, \mbox{and } \gamma_n\) are supposed to be already determined).

A solution would be to solve the whole problem with all the unknows, that is \(u_{n+1}, \gamma_{n+1}, \varepsilon^p_{n+1} \mbox{ and } A_{n+1}\). This is of course possible but would be a rather expensive strategy because of the resulting high number of degrees of freedom. A classical strategy (the return mapping one for instance, see [SO-PE-OW2008] or the closest point projection one) consist in integrating locally the plastic flow on each Gauss point of the considered integration method separately, or more precisely to consider on each Gauss point the maps

with \(\eta_n, \zeta_{n}\) the right hand side of equations (1), (2), i.e.

This means in particular that \((\varepsilon^p_{n+1}, \alpha_{n+1}) = ({\mathscr E}^p(u_{n+1}, \zeta_n, \eta_n), {\mathscr A}(u_{n+1}, \zeta_{n}, \eta_n))\) is the solution to equations (1) and (2). Both these maps and their tangent moduli (usually called consistent tangent moduli) are then used in the global solve of the problem with a Newton method and for \(u_{n+1}\) the unique remaining variable. The advantage of the return mapping strategy is that the unique variable of the global solve is the displacement \(u_{n+1}\). A nonlinear solve on each Gauss point is often necessary which is usualy performed with a local Newton method.

In *GetFEM* we propose both the return mapping strategy and also an alternative strategy developed below which is mainly inspired from [PO-NI2016], [SE-PO-WO2015] and [HA-WO2009] and allow more simple tangent moduli. It consists in keeping (a multiple of) \(\gamma_{n+1}\) as an additional unknown with respect to \(u_{n+1}\). As we will see, this will allow a more generic treatment of the yield functions, the price for the simplicity being this additional unknown scalar field.

First, we consider an additional (and optional) given function \(\alpha(\sigma_{n+1}, A_{n+1}) > 0\) whose interest will appear later on (it will allow simple local inverses) and the new unknown scalar field

so that our two main unknows are now \(u_{n+1} \mbox{ and } \xi_{n+1}\). The discretized plastic flow rule integration now reads:

For \(u_{n+1} \mbox{ and } \xi_{n+1}\) be given, we define the two maps

where the pair \((\varepsilon^p_{n+1}, \alpha_{n+1}) = (\tilde{\mathscr E}^p(u_{n+1}, \theta \xi_{n+1}, \zeta_{n}, \eta_n), \tilde{\mathscr A}(u_{n+1}, \theta \xi_{n+1}, \zeta_{n}, \eta_n))\) is the solution to equations (3), (4) (without the consideration of (5)). We will see later, that, at least for simple isotropic plastic flow rules, these maps have a simple expression, even sometimes a linear one with respect to \(u_{n+1}\).

Still \(u_{n+1} \mbox{ and } \xi_{n+1}\) be given the stress \(\sigma_{n+1}\) reads

The complementarity equation (5) is then prescribed with the use of a well chosen complementarity function, as in [HA-WO2009] for \(r > 0\) such as:

or

NOTE : The notation \(\Delta \xi_{n+1} = \Delta t \xi_{n+1}\) is often used in the litterature. The choice here is to preserve the distinction between the two quantities, mainly because ot the possible use of adaptative time step : when the time step is changing, the value \(\xi_n\) has to be multiplied by the new time step, so that it is preferable to store \(\xi_n\) instead of \(\Delta \xi_{n}\) when using the \(\theta\)-scheme.

### Plane strain approximation¶

A plane strain approximation is a 2D problem which corresponds to the deformation of a long cylindrical object where the strain in the length direction (assumed to be along the \(z\) axis) is considered small compared to the ones in the other directions and is neglected. It result in a plane strain tensor of the form

We denote

the non neglected components of the strain tensor. In the decomposition of plastic and elastic part of the strain tensor, we assume

and

The adaptation to the plane strain approximation to plastic model is most of the time an easy task. An isotropic linearized elastic response reads

and thus

The nonzero \(\sigma_{3,3}\) component of the stress tensor is given by

Note that in the common case where isochoric plastic strain is assumed, one has

### Plane stress approximation¶

The plane stress approximation describe generally the 2D membrane deformation of a thin plate. It consist in prescribing the stress tensor to have only in-plane nonzero components, i.e.

We will still denote

the in-plane components of the stress tensor. For elastoplasticity, it consists generally to apply the 2D plastic flow rule, prescribing the out-plane components of the stress tensor to be zero with the additionnal variables \(\varepsilon^e_{1,3}\), \(\varepsilon^e_{2,3}\), \(\varepsilon^e_{3,3}\) being unknown (see for instance [SO-PE-OW2008]).

For an isotropic linearized elastic response, one has \(\sigma = \lambda \mbox{tr}(\varepsilon^e) + 2\mu\varepsilon^e\) such that

with

so that

Moreover

Note that in the case where isochoric plastic strain is assumed, one still has

## Some classical laws¶

Tresca : \(\rho(\sigma) \le \sigma_y\) where \(\rho(\sigma)\) spectral radius of the Cauchy stress tensor and \(\sigma_y\) the uniaxial yield stress (which may depend on some hardening internal variables).

Von Mises : \(\|\mbox{Dev}(\sigma)\| \le \sqrt{\frac{2}{3}}\sigma_y\) where \(\mbox{Dev}(\sigma) = \sigma - \frac{1}{3}\mbox{tr}(\sigma)I\) the deviatoric part of \(\sigma\) and \(\|\sigma\| = \sqrt{\sigma:\sigma}\).

### Perfect isotropic associated elastoplasticity with Von-Mises criterion (Prandl-Reuss model)¶

There is no internal variables and we consider an isotropic elastic response. The flow rule reads

This corresponds to \(\Psi(\sigma) = f(\sigma) = \|\mbox{Dev}(\sigma)\| - \sqrt{\frac{2}{3}}\sigma_y\).

The \(\theta\)-scheme for the integration of the plastic flow rule reads:

Choosing the factor \(\alpha(\sigma_{n}) = \|\mbox{Dev}(\sigma_{n})\|\) and still with \(\xi_n = \dfrac{\gamma_n}{\alpha(\sigma_{n})}\) this gives the equation

Since \(\mbox{Dev}(\sigma_{n+1}) = 2\mu\mbox{Dev}(\varepsilon(u_{n+1})) - 2\mu\varepsilon^p_{n+1}\) this directly gives:

which is a linear expression with respect to \(u_{n+1}\) (but not with respect to \(\xi_{n+1}\)).

Moreover, \(\zeta_n\) is defined by

**Elimination of the multiplier (for the return mapping approach)**

One has

Thus, denoting \(B = \mbox{Dev}(\varepsilon(u_{n+1})) - \zeta_n\), either

and \(\xi_{n+1} = 0\), i.e. we are in the elastic case, or \(\|\mbox{Dev}(\sigma_{n+1})\| = \sqrt{\frac{2}{3}}\) and one obtains

and thus

The two options can be summarized by

The multiplier \(\xi_{n+1}\) (needed for the \(\theta\)-scheme for \(\theta \ne 1\)) is given by

**Plane strain approximation**

The plane strain approximation has the same expression replacing the 3D strain tensors by the in-plane ones \(\bar{\varepsilon}^p\) and \(\bar{\varepsilon}(u_{n+1})\).

where \(\overline{\mbox{Dev}}(\bar{\varepsilon}) = \bar{\varepsilon} - \dfrac{\mbox{tr}(\bar{\varepsilon})}{3} \bar{I}\) is the 2D restriction of the 3D deviator.

Moreover, for the yield condition,

And for the elimination of the multiplier,

with \(\bar{B} = \overline{\mbox{Dev}}(\bar{\varepsilon}(u_{n+1}))-\bar{\zeta}_{n}\) and \(\|B\|^2 = \|\overline{\mbox{Dev}}(\bar{\varepsilon}(u_{n+1})) - \bar{\zeta}_n\|^2 + \left(\dfrac{\mbox{tr}(\bar{\varepsilon}(u_{n+1}))}{3} -\mbox{tr}(\bar{\zeta}_n) \right)^2\).

**Plane stress approximation**

For plane stress approximation, using (6) we deduce from the expression of the 3D case

since \(\mbox{Dev}(\varepsilon(u)) = \varepsilon(u) - \dfrac{2\mu}{3(\lambda+2\mu)}(\mbox{tr}(\bar{\varepsilon}(u)) - \mbox{tr}(\bar{\varepsilon}^p))\). Of course, this relation still has to be inverted. Denoting \(\alpha = 1+2\mu\theta\Delta \xi\), \(\beta = \dfrac{4\mu^2\theta\Delta \xi}{3\lambda+6\mu}\) and \(C = \bar{\zeta}_{n} +2\mu\theta\Delta \xi\left(\bar{\varepsilon}(u_{n+1}) - \dfrac{2\mu}{3(\lambda+2\mu)}(\mbox{tr}(\bar{\varepsilon}(u_{n+1}))))\bar{I}\right)\) one obtains

Moreover, for the yield condition, expression (7) can be used.

### Isotropic elastoplasticity with linear isotropic and kinematic hardening and Von-Mises criterion¶

We consider an isotropic elastic reponse and the internal variable \(\alpha : \Omega \rightarrow \rm I\hspace{-0.15em}R\) being the accumulated plastic strain which satisfies

For \(H_i\) the isotropic hardening modulus, the linear hardening consists in

i.e. \(A = H_i\alpha\) and a uniaxial yield stress defined by

for \(\sigma_{y0}\) the initial uniaxial yield stress. The yield function (and plastic potential since this is an associated plastic model) can be defined by

where \(H_k\) is the kinematic hardening modulus. The same computation as in the previous section leads to

where \(\zeta_n\) and \(\eta_n\) are defined by

Note that the isotropic hardening modulus do not intervene in \(\tilde{\mathscr E}^p(u_{n+1}, \theta \Delta \xi, \varepsilon^p_{n})\) but only in \(f(\sigma, A)\).

**Elimination of the multiplier (for the return mapping approach)**

Denoting \(\delta = \dfrac{1}{1+2(\mu+H_k/3)\theta\Delta t\xi_{n+1}}\), \(\beta = \dfrac{1-\delta}{2(\mu+H_k/3)}\) and \(B = 2\mu\mbox{Dev}(\varepsilon(u_{n+1}))-2(\mu+H_k/3)\zeta_n\) the expression for \(\varepsilon^p_{n+1}\) and \(\alpha_{n+1}\) becomes

and the plastic constraint

Thus, either we are in the elastic case, i.e. \(\xi_{n+1} = 0, \delta = 1\) and

or we are in the plastic case and \(\xi_{n+1} > 0, \delta < 1\), \(\delta \|B\| = \sqrt{\dfrac{2}{3}}(\sigma_{y0}+H_i \alpha_{n+1})\) and \((1-\delta)\) solves the equation

which leads to

The two cases can be summarized by

which directly gives \({\mathscr E}^p(u_{n+1}, \zeta_n, \eta_n)\) and \({\mathscr A}(u_{n+1}, \zeta_n, \eta_n)\) thanks to (8). The multiplier \(\xi_{n+1}\) being given by

**Plane strain approximation**

Still denoting \(\delta = \dfrac{1}{1+2(\mu+H_k/3)\theta\Delta t\xi_{n+1}}\), \(\beta = \dfrac{1-\delta}{2(\mu+H_k/3)}\), \(B = 2\mu\mbox{Dev}(\varepsilon(u_{n+1}))-2(\mu+H_k/3)\zeta_n\) and \(\overline{B} = 2\mu\overline{Dev}(\bar{\varepsilon}(u_{n+1}))-2(\mu+H_k/3)\bar{\zeta}_n\) its in-plane part, one has

with

The yield condition still reads

and for the elimination of the multiplier, \(\beta\) has the same expression as in the previous section adapting the value of \(\|B\|\). The expressions of \(\bar{\zeta}_n\) and \(\eta_n\) have to be adapted accoringly.

### Souza-Auricchio elastoplasticity law (for shape memory alloys)¶

See for instance [GR-ST2015] for the justification of the construction of this flow rule. A Von-Mises stress criterion together with an isotropic elastic response, no internal variables and a special type of kinematic hardening is considered with a constraint \(\|\varepsilon^p\| \le c_3\). The plastic potential and yield function have the form

with the complementarity condition

where \(c_1, c_2 \mbox{ and } c_3\) are some physical parameters. Note that \(\dfrac{\varepsilon^p}{\|\varepsilon^p\|}\) has to be understood to be the whole unit ball for \(\varepsilon^p = 0\).

to be done …

## Elasto-plasticity bricks¶

See the test programs `tests/plasticity.cc`

, `interface/tests/matlab/demo_plasticity.m`

, `interface/tests/matlab/demo_plasticity.py`

and in `contrib/test_plasticity`

.

### Generic brick¶

There are two versions of the generic brick. A first one when the plastic multiplier is kept as a variable of the problem where the added term is of the form:

with \(r > 0\) having a specific value chosen by the brick (in terms of the elasticity coefficients), and when the return mapping strategy is selected (plastic multiplier is just a data), just the added term:

The function which adds the brick to a model md is

```
getfem::add_small_strain_elastoplasticity_brick
(md, mim, lawname, unknowns_type,
const std::vector<std::string> &varnames,
const std::vector<std::string> ¶ms, region = size_type(-1));
```

where lawname is the name of an implemented plastic law, unknowns_type indicates the choice between a discretization where the plastic multiplier is an unknown of the problem or (return mapping approach) just a data of the model stored for the next iteration. Remember that in both cases, a multiplier is stored anyway. varnames is a set of variable and data names with length which may depend on the plastic law (at least the displacement, the plastic multiplier and the plastic strain). params is a list of expressions for the parameters (at least elastic coefficients and the yield stress). These expressions can be some data names (or even variable names) of the model but can also be any scalar valid expression of GWFL, the generic weak form language (such as “1/2”, “2+sin(X[0])”, “1+Norm(v)” …). The last two parameters optionally provided in params are the theta parameter of the theta-scheme (generalized trapezoidal rule) used for the plastic strain integration and the time-step`dt`. The default value for theta if omitted is 1, which corresponds to the classical Backward Euler scheme which is first order consistent. theta=1/2 corresponds to the Crank-Nicolson scheme (trapezoidal rule) which is second order consistent. Any value between 1/2 and 1 should be a valid value. The default value of dt is ‘timestep’ which simply indicates the time step defined in the model (by md.set_time_step(dt)). Alternatively it can be any expression (data name, constant value …). The time step can be altered from one iteration to the next one. region is a mesh region.

The available plasticity laws are:

“Prandtl Reuss” (or “isotropic perfect plasticity”). Isotropic elasto-plasticity with no hardening. The variables are the displacement, the plastic multiplier and the plastic strain. The displacement should be a variable and have a corresponding data having the same name preceded by “Previous_” corresponding to the displacement at the previous time step (typically “u” and “Previous_u”). The plastic multiplier should also have two versions (typically “xi” and “Previous_xi”) the first one being defined as data if unknowns_type = DISPLACEMENT_ONLY or as a variable if unknowns_type = DISPLACEMENT_AND_PLASTIC_MULTIPLIER. The plastic strain should represent a n x n data tensor field stored on mesh_fem or (preferably) on an im_data (corresponding to mim). The data are the first Lame coefficient, the second one (shear modulus) and the uniaxial yield stress. IMPORTANT: Note that this law implements the 3D expressions. If it is used in 2D, the expressions are just transposed to the 2D. For the plane strain approximation, see below.

“plane strain Prandtl Reuss” (or “plane strain isotropic perfect plasticity”) The same law as the previous one but adapted to the plane strain approximation. Can only be used in 2D.

“Prandtl Reuss linear hardening” (or “isotropic plasticity linear hardening”). Isotropic elasto-plasticity with linear isotropic and kinematic hardening. An additional variable compared to “Prandtl Reuss” law: the accumulated plastic strain. Similarly to the plastic strain, it is only stored at the end of the time step, so a simple data is required (preferably on an im_data). Two additional parameters: the kinematic hardening modulus and the isotropic one. 3D expressions only.

“plane strain Prandtl Reuss linear hardening” (or “plane strain isotropic plasticity linear hardening”). The same law as the previous one but adapted to the plane strain approximation. Can only be used in 2D.

IMPORTANT : remember that small_strain_elastoplasticity_next_iter has to be called at the end of each time step, before the next one (and before any post-treatment : this sets the value of the plastic strain and plastic multiplier).

Additionaly, the following function allow to pass from a time step to another for the small strain plastic brick:

```
getfem::small_strain_elastoplasticity_next_iter
(md, mim, lawname, unknowns_type,
const std::vector<std::string> &varnames,
const std::vector<std::string> ¶ms, region = size_type(-1));
```

The parameters have to be exactly the same as the ones of the add_small_strain_elastoplasticity_brick, so see the documentation of this function for any explanations. Basically, this brick computes the plastic strain and the plastic multiplier and stores them for the next step. Additionaly, it copies the computed displacement to the data that stores the displacement of the previous time step (typically “u” to “Previous_u”). It has to be called before any use of compute_small_strain_elastoplasticity_Von_Mises.

The function

```
getfem::compute_small_strain_elastoplasticity_Von_Mises
(md, mim, lawname, unknowns_type,
const std::vector<std::string> &varnames,
const std::vector<std::string> ¶ms,
const mesh_fem &mf_vm, model_real_plain_vector &VM,
region = size_type(-1));
```

computes the Von Mises stress field with respect to a small strain elastoplasticity term, approximated on mf_vm, and stores the result into VM. All other parameters have to be exactly the same as for add_small_strain_elastoplasticity_brick. Remember that small_strain_elastoplasticity_next_iter has to be called before any call of this function.

### A specific brick based on the low-level generic assembly for perfect plasticity¶

This is an previous version of a elastoplasticity brick which is restricted to isotropic perfect plasticity and is based on the low-level generic assembly. Its specificity which could be interesting for testing is that the flow rule is integrated on finite element nodes (not on Gauss points).

The function adding this brick to a model is:

```
getfem::add_elastoplasticity_brick
(md, mim, ACP, varname, previous_varname, datalambda, datamu, datathreshold, datasigma, region);
```

- where:
`varname`

represents the main displacement unknown on which the brick is added (u).`previous_varname`

is the displacement at the previous time step.`datalambda`

and`datamu`

are the data corresponding to the Lame coefficients.`datathreshold`

represents the plastic threshold of the studied material.`datasigma`

represents the stress constraint values supported by the material. It should be composed of 2 iterates for the time scheme needed for the Newton algorithm used. Note that the finite element method on which`datasigma`

is defined should be able to represent the derivative of`varname`

.`ACP`

corresponds to the type of projection to be used. It has an abstract_constraints_projection type and for the moment, only exists the VM_projection corresponding to the Von Mises one.

Be careful: `datalambda`

, `datamu`

and `datathreshold`

could be constants or described on the same finite element method.

This function assembles the tangent matrix and the right hand side vector which will be solved using a Newton algorithm.

Additionaly, The function:

```
getfem::elastoplasticity_next_iter
(md, mim, varname, previous_varname, ACP, datalambda, datamu, datathreshold, datasigma);
```

computes the new stress constraint values supported by the material after a load or an unload (once a solve has been done earlier) and upload the variables `varname`

and `datasigma`

as follows:

Then, \(u^n\) and \(\sigma^n\) contains the new values computed and one can restart the process.

The function:

```
getfem::compute_elastoplasticity_Von_Mises_or_Tresca
(md, datasigma, mf_vm, VM, tresca=false);
```

computes the Von Mises (or Tresca if `tresca`

= true) criterion on the stress tensor stored in `datasigma`

. The stress is evaluated on the mesh_fem `mf_vm`

and stored into the vector `VM`

.
Of course, this function can be used if and only if the previous function `elastoplasticity_next_iter`

has been called earlier.

The function:

```
getfem::compute_plastic_part
(md, mim, mf_pl, varname, previous_varname, ACP, datalambda, datamu, datathreshold, datasigma, Plast);
```

computes on `mf_pl`

the plastic part of the material, that could appear after a load and an unload, into the vector `Plast`

.

Note that `datasigma`

should be the vector containing the new stress constraint values, i.e. after a load or an unload of the material.