`TFEL`

, `MFront`

and `MTest`

- Highlights
- TFEL
- New functionalities of the
`MFront`

code generator - New functionalities of
`MTest`

solver - New functionalities of the
`mfront-query`

tool - New functionalities of the
`tfel-config`

tool - Introduction of the
`mfm`

tool - Tickets fixed
- Ticket #37: Add the ability to compute part of the jacobian numerically
- Ticket #40:
`ImplicitDSL`

: Detect non finite values during resolution - Ticket #41:
`MTest`

: check if the residual is finite and not NaN - Ticket #42: Check for infinite and
`NaN`

values in material properties - Ticket #43: Add the list of parameters' names and types to generated library for the
`UMAT++`

interface - Ticket #45: Support for bounds on parameters
- Ticket #46: Improvements to the
`mfront`

`python`

module - Ticket #47: Add
`python`

bindings for the`mtest::Behaviour`

class - Ticket #46: Improved
`python`

bindings for the`mfront::BehaviourDescription`

class - Ticket #48: Add the ability to retrieve bounds for material properties and parameters from the
`mtest::Behaviour`

class - Ticket #49: Add the ability to retrieve the symmetry of the behaviour and the symmetry of the elastic behaviour from
`mfront-query`

- Ticket #50: Add the ability to retrieve bounds values from
`mfront-query`

- Ticket #65:
`@ElasticMaterialProperties`

does not work for DSL describing isotropics behaviours - Ticket 74
`mfront-query`

: handle static variables - Ticket 76: Add
`python`

bindings for the`SearchPathsHandler`

class in the`mfront`

module

- Know regressions
- References

The page declares the new functionalities of the 3.1 version of `TFEL`

, `MFront`

and `MTest`

.

`verrou`

`-ffast-math`

with GCC`TFELNUMODIS`

library`SlipSystemsDescription`

class in `TFEL/Material`

`starts_with`

string algorithmThe `starts_with`

string algorithm is an helper function used to determine if a given string starts with another.

`ends_with`

string algorithmThe `ends_with`

string algorithm is an helper function used to determine if a given string ends with another.

`LibraryInformation`

classThis release introduces the `LibraryInformation`

class that allow querying a library about exported symbols.

NoteThis class has been adapted from the`boost/dll`

library version 1.63 and has been originally written by Antony Polukhin, Renato Tegon Forti and Antony Polukhin.

`ExternalLibraryManager`

classIf a library is not found, the `ExternalLibraryManager`

class will try the following combinaisons:

- Append
`lib`

in front of the library name (except for`Microsoft`

`Windows`

platforms). - Append
`lib`

in front of the library name and the standard library suffix at the end (except for`Microsoft`

`Windows`

platforms). - Append the standard library suffix at the end of the library name.

The standard library suffix is:

`.dll`

for`Microsoft`

`Windows`

platforms.`.dylib`

for`Apple`

`MacOs`

plateforms.`.so`

on all other supported systems.

The `getLibraryPath`

method returns the path to a shared library:

- The method relies on the
`GetModuleFileNameA`

function on`Windows`

which is reliable. - On
`Unix`

, no portable way exists, so the method simply looks if the library can be loaded. If so, the method look if the file exists locally or in a directory listed in the`LD_LIBRARY_PATH`

variable.

The `ExternalLibraryManager`

class has several new methods for better handling of behaviours' parameters:

- The
`getUMATParametersNames`

returns the list of parameters. - The
`getUMATParametersTypes`

returns a list of integers which gives the type of the associated paramater: The integer values returned have the following meaning:- 0: floatting point value
- 1: integer value
- 2: unsigned short value

- The
`getRealParameterDefaultValue`

,`getIntegerParameterDefaultValue`

, and`getUnsignedShortParameterDefaultValue`

methods allow retrieving the default value of a parameter.

The `ExternalLibraryManager`

class has several new methods for better handling of a behaviour' variable bounds:

- The
`hasBounds`

,`hasLowerBound`

and`hasUpperBound`

allow querying about the existence of bounds for a given variable. - The
`getLowerBound`

method returns the lower bound a variable, if defined. - The
`getUpperBound`

method returns the upper bound a variable, if defined.

The `ExternalLibraryManager`

class has several new methods for better handling of a behaviour' variable bounds:

- The
`hasPhysicalBounds`

,`hasLowerPhysicalBound`

and`hasUpperPhysicalBound`

allow querying about the existence of bounds for a given variable. - The
`getLowerPhysicalBound`

method returns the physical lower bound a variable, if defined. - The
`getUpperPhysicalBound`

method returns the physical upper bound a variable, if defined.

The `getEntryPoints`

method returns a list containing all mfront generated entry points. Those can be functions or classes depending on the interface's needs.

The `getMaterialKnowledgeType`

allows retrieving the material knowledge type associated with and entry point. The returned value has the following meaning:

- 0: Material property.
- 1: Behaviour.
- 2: Model.

The `getInterface`

method allows retrieving the interface of used to generate an entry point. The value returned is defined by `MFront`

following Table @#tbl:MFrontInterfaceName.

Finite element solver | `MFront` interface name |
---|---|

`Cast3M` |
`Castem` |

`Code_Aster` |
`Aster` |

`Cyrano` |
`Cyrano` |

`Europlexus` |
`Europlexus` |

`Abaqus/Standard` |
`Abaqus` |

`Abaqus/Explicit` |
`AbaqusExplicit` |

`Ansys APDL` |
`Ansys` |

`CalculiX` |
`CalculiX` |

The following code retrieves all the behaviours generated with the `aster`

interface in the `libAsterBehaviour.so`

library:

```
auto ab = std::vector<std::string>{};
const auto l = "AsterBehaviour";
auto& elm = ExternalLibraryManager::getExternalLibraryManager();
for(const auto& e : elm.getEntryPoints(l)){
if((elm.getMaterialKnowledgeType(l,e)==1u)&&(elm.getInterface(l,e)=="Aster")){
ab.push_back(e);
}
}
```

Note that we did not mention the prefix and the suffix of the library. The library path is searched through the `getLibraryPath`

method.

The equivalent `python`

code is the following:

```
ab = []
l = 'AsterBehaviour';
elm = ExternalLibraryManager.getExternalLibraryManager();
for e in elm.getEntryPoints(l):
if ((elm.getMaterialKnowledgeType(l,e)==1) and
(elm.getInterface(l,e)=='Aster')):
ab.append(e)
```

The `getMaterial`

method allows retrieving the material to which an entry point is associated. If no material is defined, this method returns an empty string.

`ThreadPool`

classThe `ThreadPool`

class is used to handle a pool of threads that are given tasks. This class now has a `wait`

method which blocks the main thread up to tasks completion.

```
std::atomic<int> res(0);
auto task = [&res](const int i){
// update the res variable
return [&res,i]{
res+=i;
};
};
// create a pool of two threads
tfel::system::ThreadPool p(2);
// Create two tasks that can be executed
// using one or two threads.
p.addTask(task(-1));
p.addTask(task(2));
// Waiting for the tasks to end
p.wait();
// At this point, res is equal to 1.
// The 2 threads in the pool are *not* joined
// and are waiting for new tasks.
```

The computation of the eigen values and eigen vectors of a symmetric tensor has been improved in various ways:

- Various overloaded versions of the
`computeEigenValues`

,`computeEigenVectors`

and`computeEigenTensors`

methods have been introduced for more readable usage and compatibility with*structured bindings*construct introduced in C++17: the results of the computations are returned by value. There is also a new optional parameter allowing to sort the eigen values. - New eigen solvers have been introduced.

`computeEigenValues`

, `computeEigenVectors`

and `computeEigenTensors`

methodsVarious overloaded versions of the `computeEigenValues`

, `computeEigenVectors`

and `computeEigenTensors`

methods have been introduced for more readable usage and compatibility with *structured bindings* construct introduced in C++17: the results of the computations are returned by value.

For example:

```
tmatrix<3u,3u,real> m2;
tvector<3u,real> vp2;
std::tie(vp,m)=s.computeEigenVectors();
```

Thanks to C++17 *structured bindings* construct, the previous code will be equivalent to this much shorter and more readable code:

`auto [vp,m] = s.computeEigenVectors();`

Even better, we could write:

`const auto [vp,m] = s.computeEigenVectors();`

The `computeEigenValues`

and `computeEigenVectors`

methods now have an optional argument which specify if we want the eigen values to be sorted. Three options are available:

`ASCENDING`

: the eigen values are sorted from the lowest to the greatest.`DESCENDING`

: the eigen values are sorted from the greatest to the lowest.`UNSORTED`

: the eigen values are not sorted.

Here is how to use it:

```
tmatrix<3u,3u,real> m2;
tvector<3u,real> vp2;
std::tie(vp,m)=s.computeEigenVectors(Stensor::ASCENDING);
```

The default eigen solver for symmetric tensors used in `TFEL`

is based on analitical computations of the eigen values and eigen vectors. Such computations are more efficient but less accurate than the iterative Jacobi algorithm (see (Kopp 2008; Kopp 2017)).

With the courtesy of Joachim Kopp, we have created a `C++11`

compliant version of his routines that we gathered in header-only library called `FSES`

(Fast Symmetric Eigen Solver). This library is included with `TFEL`

and provides the following algorithms:

- Jacobi
- QL with implicit shifts
- Cuppen
- Analytical
- Hybrid
- Householder reduction

We have also introduced the Jacobi implementation of the `Geometric`

`Tools`

library (see (Eberly 2016; Eberly 2017)).

Those algorithms are available in 3D. For 2D symmetric tensors, we fall back to some default algorithm as described below.

Name | Algorithm in 3D | Algorithm in 2D |
---|---|---|

`TFELEIGENSOLVER` |
Analytical (TFEL) | Analytical (TFEL) |

`FSESJACOBIEIGENSOLVER` |
Jacobi | Analytical (FSES) |

`FSESQLEIGENSOLVER` |
QL with implicit shifts | Analytical (FSES) |

`FSESCUPPENEIGENSOLVER` |
Cuppen's Divide & Conquer | Analytical (FSES) |

`FSESANALYTICALEIGENSOLVER` |
Analytical | Analytical (FSES) |

`FSESHYBRIDEIGENSOLVER` |
Hybrid | Analytical (FSES) |

`GTESYMMETRICQREIGENSOLVER` |
Symmetric QR | Analytical (TFEL) |

The various eigen solvers available are enumerated in Table 2.

The eigen solver is passed as a template argument of the `computeEigenValues`

or the `computeEigenVectors`

methods as illustrated in the code below:

```
tmatrix<3u,3u,real> m2;
tvector<3u,real> vp2;
std::tie(vp,m)=s.computeEigenVectors<stensor::GTESYMMETRICQREIGENSOLVER>();
```

Algorithm | Failure ratio | \(\Delta_{\infty}\) | Times (ns) | Time ratio |
---|---|---|---|---|

`TFELEIGENSOLVER` |
0.000642 | 3.29e-05 | 250174564 | 1 |

`GTESYMMETRICQREIGENSOLVER` |
0 | 1.10e-06 | 359854550 | 1.44 |

`FSESJACOBIEIGENSOLVER` |
0 | 5.62e-07 | 473263841 | 1.89 |

`FSESQLEIGENSOLVER` |
0.000397 | 1.69e-06 | 259080052 | 1.04 |

`FSESCUPPENEIGENSOLVER` |
0.019469 | 3.49e-06 | 274547371 | 1.10 |

`FSESHYBRIDEIGENSOLVER` |
0.076451 | 5.56e-03 | 126689850 | 0.51 |

`FSESANALYTICALEIGENSOLVER` |
0.108877 | 1.58e-01 | 127236908 | 0.51 |

Algorithm | Failure ratio | \(\Delta_{\infty}\) | Times (ns) | Time ratio |
---|---|---|---|---|

`TFELEIGENSOLVER` |
0.000632 | 7.75e-14 | 252663338 | 1 |

`GTESYMMETRICQREIGENSOLVER` |
0 | 2.06e-15 | 525845499 | 2.08 |

`FSESJACOBIEIGENSOLVER` |
0 | 1.05e-15 | 489507133 | 1.94 |

`FSESQLEIGENSOLVER` |
0.000422 | 3.30e-15 | 367599140 | 1.45 |

`FSESCUPPENEIGENSOLVER` |
0.020174 | 5.79e-15 | 374190684 | 1.48 |

`FSESHYBRIDEIGENSOLVER` |
0.090065 | 3.53e-10 | 154911762 | 0.61 |

`FSESANALYTICALEIGENSOLVER` |
0.110399 | 1.09e-09 | 157613994 | 0.62 |

Algorithm | Failure ratio | \(\Delta_{\infty}\) | Times (ns) | Time ratio |
---|---|---|---|---|

`TFELEIGENSOLVER` |
0.000575 | 2.06e-17 | 428333721 | 1 |

`GTESYMMETRICQREIGENSOLVER` |
0 | 1.00e-18 | 814990447 | 1.90 |

`FSESJACOBIEIGENSOLVER` |
0 | 5.11e-19 | 748476926 | 1.75 |

`FSESQLEIGENSOLVER` |
0.00045 | 1.83e-18 | 548604588 | 1.28 |

`FSESCUPPENEIGENSOLVER` |
0.009134 | 3.23e-18 | 734707748 | 1.71 |

`FSESHYBRIDEIGENSOLVER` |
0.99959 | 4.01e-10 | 272701749 | 0.64 |

`FSESANALYTICALEIGENSOLVER` |
0.999669 | 1.36e-11 | 315243286 | 0.74 |

We have compared the available algorithm on \(10^{6}\) random symmetric tensors whose components are in \([-1:1]\).

For a given symmetric tensor, we consider that the computation of the eigenvalues and eigenvectors failed if: \[ \Delta_{\infty}=\max_{i\in[1,2,3]}\left\|{\underline{s}}\,\cdot\,\vec{v}_{i}-\lambda_{i}\,\vec{v}_{i}\right\|>10\,\varepsilon \] where \(\varepsilon\) is the accuracy of the floatting point considered.

The results of those tests are reported on Tables 3, 4 and 5:

- The standard eigen solver available in previous versions of
`TFEL`

offers a very interesting compromise between accuracy and numerical efficiency. - If very accurate results are required, the
`FSESJACOBIEIGENSOLVER`

eigen solver is a good choice.

Given a scalar valuated function \(f\), one can define an associated isotropic function for symmetric tensors as: \[ f{\left({\underline{s}}\right)}=\sum_{i=1}^{3}f{\left(\lambda_{i}\right)}{\underline{n}}_{i} \]

where \(\left.\lambda_{i}\right|_{i\in[1,2,3]}\) are the eigen values of the symmetric tensor \({\underline{s}}\) and \(\left.{\underline{n}}_{i}\right|_{i\in[1,2,3]}\) the associated eigen tensors.

If \(f\) is \(\mathcal{C}^{1}\), then \(f\) is a differentiable function of \({\underline{s}}\).

\(f\) can be computed with the `computeIsotropicFunction`

method of the stensor class. \({{\displaystyle\frac{\displaystyle \partial f}{\displaystyle \partial {\underline{s}}}}}\) can be computed with `computeIsotropicFunctionDerivative`

. One can also compute \(f\) and \({{\displaystyle\frac{\displaystyle \partial f}{\displaystyle \partial {\underline{s}}}}}\) all at once by the `computeIsotropicFunctionAndDerivative`

method. All those methods are templated by the name of the eigen solver (if no template parameter is given, the `TFELEIGENSOLVER`

is used).

Various new overloaded versions of those methods have been introduced in `TFEL-3.1`

. Those overloaded methods are meant to:

- allow the user to explicitly give the values of \(f\) or \(df\), rather than the functions to compute them. This allows to reduce the computational cost of the evaluation of the isotropic function when the values of the derivatives can directly be computed from the values of \(f\). See the example \(\exp\) example below.
- return the results by value. This allow a much more readable code if the
*structured bindings*feature of the`C++17`

standard is available.

To illustrate this new features, assuming that the *structured bindings* feature of the `C++17`

standard is available, one can now efficiently evaluate the exponential of a symmetric tensor and its derivative as follows:

```
const auto [vp,m] = s.computeEigenVectors();
const auto evp = map([](const auto x){return exp(x)},vp);
const auto [f,df] = Stensor::computeIsotropicFunctionAndDerivative(evp,evp,vp,m,1.e-12);
```

`fpclassify`

, `isnan`

, `isfinite`

functionsThe `C99`

standard defines the `fpclassify`

, `isnan`

, `isfinite`

functions to query some information about double precision floatting-point numbers (`double`

):

- Following the
`IEEE754`

standard, the`fpclassify`

categorizes a floating point number into one of the following categories: zero, subnormal, normal, infinite, NaN (Not a Number). The return value returned for each category is respectively`FP_ZERO`

,`FP_SUBNORMAL`

,`FP_NORMAL`

,`FP_INFINITE`

and`FP_NaN`

. - The
`isnan`

function returns a boolean stating if its argument has a not-a-number (NaN) value. - The
`isfinite`

function returns true if its argument falls into one of the following categories: zero, subnormal or normal.

The `C++11`

provides a set of overload for single precision (`float`

) and extended precision (`long double`

) floatting-point numbers.

Those functions are very handy to check the validity of a computation. However, those functions are not compatible with the use of the `-ffast-math`

option of the `GNU`

compiler which also implies the `-ffinite-math-only`

option. This latter option allows optimizations for floating-point arithmetic that assume that arguments and results are finite numbers. As a consequence, when this option is enabled, the previous functions does not behave as expected. For example, `isnan`

always returns false, whatever the value of its argument.

To overcome this issue, we have introduced in `TFEL/Math`

the implementation of these functions provided by the `musl`

library (see Musl development community (2017)). Those implementations are compatible with the `-ffast-math`

option of the `GNU`

compiler. Those implementations are defined in the `TFEL/Math/General/IEEE754.hxx`

header file in the `tfel::math::ieee754`

namespace.

`TFEL/Material`

`SlipSystemsDescription`

class`MFront`

code generatorThe `MFront`

gallery is meant to present well-written implementation of behaviours that will be updated to follow `MFront`

latest evolutions.

The implementation of various hyperelastic behaviours can be found here:

The following page describes how to implement standard hyperviscoelastic behaviours based on the development in Prony series:

http://tfel.sourceforge.net/hyperviscoelasticity.html

An example of a simple orthotropic behaviour is available here.

This following article shows how to implement an isotropic viscoplastic behaviour combining isotropic hardening and multiple kinematic hardenings following an Armstrong-Frederic evolution of the back stress:

http://tfel.sourceforge.net/isotropicplasticityamstrongfrederickinematichardening.html

`cmake`

GeneratorFor `Visual Studio`

users, who do not have access to the `GNU`

`make`

utility, a `cmake`

generator was introduced.

This generator is the default with `Visual Studio`

. In other development environment, the default generator is the `Makefile`

generator.

One can switch from a generator to another using the `--generator`

(`-G`

) option of `mfront`

, as follows:

`$ mfront -G cmake --obuild --interface=python YoungModulusTest.mfront`

In this case, `MFront`

will perform the following operations:

- Generate the sources of the python module.
- Generate a
`CMakeLists.txt`

file in the`src`

directory. - Configure the
`src`

directory using`cmake`

. - Build the python module using
`cmake`

.

The output of the previous command is, on `LinuX`

:

```
Treating target : all
-- The C compiler identification is GNU 4.9.2
-- The CXX compiler identification is GNU 4.9.2
-- Check for working C compiler: /usr/bin/cc
-- Check for working C compiler: /usr/bin/cc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/c++
-- Check for working CXX compiler: /usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- tfel-config : /home/th202608/codes/tfel/trunk/install/bin/tfel-config
-- tfel oflags : -fvisibility-inlines-hidden;-fvisibility=hidden;-fno-fast-math;-DNO_RUNTIME_CHECK_BOUNDS;-O2;-DNDEBUG;-ftree-vectorize;-march=native
-- Configuring done
-- Generating done
-- Build files have been written to: /tmp/src
Scanning dependencies of target materiallaw
[ 50%] Building CXX object CMakeFiles/materiallaw.dir/YoungModulusTest-python.o
[100%] Building CXX object CMakeFiles/materiallaw.dir/materiallawwrapper.o
Linking CXX shared library libmateriallaw.so
[100%] Built target materiallaw
The following library has been built :
- materiallaw.so : YoungModulusTest
```

`Implicit`

DSL`@NumericallyComputedJacobianBlocks`

Computing the jacobian of the implicit system is the most difficult part of implementing a behaviour. Computing the jacobian by finite difference is interesting but significantly decreases the performances of the behaviour and can be (very) sensitive to the choice of the numerical perturbation.

The `@NumericallyComputedJacobianBlocks`

keyword is used select a list of jacobian blocks that have to be computed numerically. This is more efficient than computing the whole jacobian numerically. Combined with the ability to compare the jacobian to a numerical approximation, the user now has the ability to build the jacobian incrementally, block by block and checks at each steps that their analytical expressions are correct.

This keyword can optionnaly be followed by a list of modelling hypotheses. The list of jacobian blocks is given as an array.

- This keyword can be used multiple times. The newly declared jacobian blocks are added to the existing ones.

`@NumericallyComputedJacobianBlocks {dfp_ddeel,dfeel_ddeel};`

`CalculiX`

interfaceA native interface for the `CalculiX`

solver has been added.

Calling external libraries from `CalculiX`

for the native interface requires a patch in version `2.12`

that can be downloaded here.

`Cast3M`

interface`MieheApelLambrechtLogarithmic`

finite strain strategyThe pre- and post-computations performed by the `MieheApelLambrechtLogarithmic`

finite strain strategy , which require the computation of the eigen values and eigen vectors of the right Cauchy strecth tensor, are now based the Jacobi algorithm from the `FSES`

library for improved accuracy.

`Code_Aster`

interface`GROT_GDEP`

finite strain formulation`GROT_GDEP`

is the name in `Code_Aster`

of a finite strain formulation based on the principle of virtual work in the reference configuration expressed in term of the Green-Lagrange strain and the second Piola-Kirchhoff stress. Such a formulation is also called `Total Lagrangian`

in the litterature (see Belytschko (2000)) and in other finite element solvers.

Prior to this version, `MFront`

behaviours were meant to be used with the `SIMO_MIEHE`

finite strain formulation and could not be used with the `GROT_GDEP`

finite strain formulation.

From the behaviour point of view, using `SIMO_MIEHE`

or `GROT_GDEP`

differs from the choice of the output stress and the definition of the consistent tangent operator.

`@AsterFiniteStrainFormulation`

keywordThe `@AsterFiniteStrainFormulation`

keyword can now be used to choose one of these finite strain formulation.

This keyword must be followed by one of the following choice:

`SIMO_MIEHE`

`GROT_GDEP`

or`TotalLagrangian`

The choice `SIMO_MIEHE`

remains the default for backward compatibility.

`Europlexus`

interface`MieheApelLambrechtLogarithmic`

finite strain strategyThe pre- and post-computations performed by the `MieheApelLambrechtLogarithmic`

finite strain strategy, which require the computation of the eigen values and eigen vectors of the right Cauchy strecth tensor, are now based the Jacobi algorithm from the `FSES`

library for improved accuracy.

`Abaqus-Explicit`

interface`MieheApelLambrechtLogarithmic`

finite strain strategyThe pre- and post-computations performed by the `MieheApelLambrechtLogarithmic`

finite strain strategy, which require the computation of the eigen values and eigen vectors of the right Cauchy strecth tensor, are now based the Jacobi algorithm from the `FSES`

library for improved accuracy.

`MTest`

solver\(4\) rounding mode are defined in the IEEE754 standard. Changing the rounding mode is a gross way to check the numerical stability of the computations performed with `MTest`

and `MFront`

.

The rounding mode can be set using the `--rounding-direction-mode`

option. Valid values for this option are:

`DownWard`

: Round downward.`ToNearest`

: Round to nearest (the default).`TowardZero`

: Round toward zero.`UpWard`

: Round upward.`Random`

: rounding mode is changed randomly a various stage of the computation to one of the four previous rounding modes.

Most unit-tests based on `MTest`

are now executed five times, one for each available choice of the rounding mode.

Abritrary non linear constraints on driving variables and thermodynamic forces can now be added using the `@NonLinearConstraint`

keyword.

NoteThis keyword can also be used to define linear constraints, although the numerical treatment of such a constraint will be sub-optimal. A special treatment of such a constraint is planned.

NoteThis development of this functionality highlighted the issue reported in Ticket #39. For more details, see: https://sourceforge.net/p/tfel/tickets/39/

This keyword must be followed by an option giving the normalisation policy. The normalisation policy can have one of the following values:

`DrivingVariable`

,`Strain`

,`DeformationGradient`

,`OpeningDisplacement`

stating that the constraint is of the order of magnitude of the driving variable.`ThermodynamicForce`

,`Stress`

,`CohesiveForce`

stating that the constraint is of the order of magnitude of the thermodynamic force.

```
// ensure that the loading is isochoric in 1D
@NonLinearConstraint<Strain> 'FRR*FTT*FZZ-1';
```

```
// impose the first piola kirchoff stress
// in an uniaxial compression test
@Real 'Pi0' -40e6
@NonLinearConstraint<Stress> 'SXX*FYY*FZZ-Pi0';
```

`@Print`

and `@Message`

keywordsThe `@Print`

keyword, or its alias named `@Message`

, is used to display some informative message on the standard output.

This keyword is followed by floatting point values and/or strings.

Strings are first interpreted as formula. If the interpretation is successfull, the result is printed. Otherwise, the string is display witout interpretation.

All the following tokens are appended to the message up to a final semi-colon.

`@Print "Complex computation result: " "12*5";`

In this example, the first string can't be interpreted as a formula, so its contents is printed. The second part can be interpreted, so its result (\(60\)) is displayed. The message printed is thus:

`Complex computation result: 60`

`@Import`

keywordDepending of the option used (given between '<' and '>'), the `@Import`

keyword is meant to have various meanings.

In this version, the only option available is the `castem`

option.

`castem`

optionThe `castem`

(or `Castem`

or `Cast3M`

) option let you import a function generated by `MFront`

with the `castem`

interface. This function can be used in every formula.

The keyword is followed by the library an function names.

```
@Import<castem> 'CastemW' 'W_ThermalExpansion';
// height at 20°C
@Real 'h0' 16e-3;
// height at 1500°C
@Real 'h' 'h0*(1+W_ThermalExpansion(1723.15)*(1723.25-293.15))';
```

`python`

bindings`Behaviour`

classThe `Behaviour`

class has been introduced in the `mtest`

modules. This class can be used to determine at runtime time the material properties, internal state variables, parameters and external state variables required by a specific implementation.

Contrary the `tfel.system.ExternalBehaviourDescription`

class, the information given by the `Behaviour`

class takes into account the variables that are implicitly declared by the interface to match its specific (internal) requirements. For example:

- The
`castem`

interface usually adds additional material properties describing the thermo-elastic properties. Such properties are may be unused by the behaviour. - The
`abaqus`

interface may declare additional state variables to describe the orthotropic axes (this is mandatory for finite strain ortotropic behaviours). - etc...

`MTest`

classIn the `python`

bindings, the `setNonLinearConstraint`

method has been added to the `MTest`

class.

This method takes two named arguments:

`constraint`

, the equation to be satified`normalisation_policy`

. The normalisation policy can have one of the following values:`DrivingVariable`

,`Strain`

,`DeformationGradient`

,`OpeningDisplacement`

stating that the constraint is of the order of magnitude of the driving variable`ThermodynamicForce`

,`Stress`

,`CohesiveForce`

stating that the constraint is of the order of magnitude of the thermodynamic force

`mfront-query`

tool`--static-variables`

: show the list of the behaviour static variables.`--parameter-default-value`

: display a parameter default value.`--static-variable-value`

: display the value of a static variable.`--has-bounds`

: return`true`

if a variable has bounds,`false`

otherwise.`--bounds-type`

: return the bounds type associated to a variable. The returned value has the follwing meaning:`None`

`Lower`

`Upper`

`LowerAndUpper`

`--bounds-value`

: show the bounds value associated as a range.`--has-physical-bounds`

: return`true`

if a variable has physical bounds,`false`

otherwise.`--physical-bounds-type`

: return the physical bounds type associated to a variable. The returned value has the follwing meaning:`None`

`Lower`

`Upper`

`LowerAndUpper`

`--physical-bounds-value`

: show the bounds value associated as a range.`--has-crystal-structure`

: return`true`

if a crystal structure has been defined.`--crystal-structure`

: return the crystal structure.`--slip-systems`

: list all the slip systems, sorted by family.`--slip-systems-by-index`

: list all the slip systems, sorted by index.`--orientation-tensors`

: list all the orientation tensors, sorted by family".`--orientation-tensors-by-index`

: list all the orientation tensors.`--orientation-tensors-by-slip-system`

: list all the orientation tensors.`--interaction-matrix`

: display the interaction matrix where the sliding systems' interaction are represented by their ranks.`--interaction-matrix-structure`

: return the number of independent coefficients and the sliding systems sorted by rank.

`tfel-config`

tool`tfel-config`

provides new options for better integration with build systems, such as `cmake`

:

`--major-version`

: returns the major version of`TFEL`

`--minor-version`

: returns the minor version of`TFEL`

`--revision-version`

: returns the revision version of`TFEL`

`--ldflags`

: returns appropriate flags for the linker to link against specified libraries (see`--math`

,`--system`

the options and others). This option is equivalent to the`--libs`

options but better reflects the intent of the option.`--include-path`

: returns the path the`TFEL`

headers.`--library-path`

: returns the path the`TFEL`

libraries.`--library-dependency`

: returns the list of dependencies of a`TFEL`

library. The given library is included in the list.`--python-version`

: returns the python version used to build the python bindings.

```
$ tfel-config --library-dependency --material
TFELMaterial TFELMath TFELUtilities TFELException TFELNUMODIS
```

`mfm`

tool`mfm`

is a tool that allow querying a library about the entry points defined by `MFront`

. Depending on the interface, an entry point can be a class name, a function, a name of an entity that will be registered in an abstract factory when the library is loaded, etc...

```
$ mfront --obuild --interface=aster ImplicitNorton.mfront
Treating target : all
The following library has been built :
- libAsterBehaviour.so : asterimplicitnorton
th202608@pleiades098:/tmp$ mfm src/libAsterBehaviour.so
- asterimplicitnorton
```

The entry points can be filtered. The following filters are available:

`--filter-by-interface`

.`--filter-by-material`

`--filter-by-name`

.`--filter-by-type`

. This option can be followed by`material-property`

,`behaviour`

or`model`

Filters are based on case-insensitive regular expressions.

Apart from filters, `mfm`

also have the following options:

`--verbose`

: set the verbosity level. The following values are accepted:`quiet`

,`level0`

,`level1`

,`level2`

,`debug`

,`full`

. If no value is given,`level1`

is selected.`--show-libs`

: show library name in front of entry points.

For example:

```
$ mfm --filter-by-material='M5' --filter-by-type=material_property --filter-by-name='.*YoungModulus.*' --filter-by-interface=castem --show-libs $(find . -type f)
- ./lib/libM5MaterialProperties-castem.so: M5_YoungModulus
- ./lib/libM5MaterialProperties-castem.so: M5_YoungModulus_Crocodile2015
- ./lib/libM5MaterialProperties-castem.so: M5_YoungModulus_MATPRO2001
```

The `@NumericallyComputedJacobianBlocks`

keyword can be used for that purpose.

For more details, see: https://sourceforge.net/p/tfel/tickets/37/

`ImplicitDSL`

: Detect non finite values during resolutionDuring the resolution of the implicit system, invalid results may occur. In previous versions, no check were made leading to a propagation of those values and finally the failure of integration.

A test to check that the residual of the implicit system is finite have been added. If this test is not satisfied after the first iteration, the last increment of the unknowns is divided by two and the resolution is restarted with this guess. If this test is not satisfied at the first iteration, the behaviour integration can not be performed.

`MTest`

: check if the residual is finite and not NaNIn previous versions, if the behaviour integration returned a not-a-number value (`NaN`

), this value propagated throughout the computation.

This situation can be detected by checking that the convergence criteria are finite as defined by the `IEEE754`

standard.

For more details, see: https://sourceforge.net/p/tfel/tickets/41/

`NaN`

values in material propertiesIn the previous versions of `MFront`

, generated sources for material properties checked that the `errno`

value to determine is something had gone wrong, but this check does not appear to portable nor reliable with the INTEL compiler or when the `-ffast-math`

option of the GNU compiler is activated.

The current version now check that the return value is finite.

For more details, see: https://sourceforge.net/p/tfel/tickets/42/

`UMAT++`

interfaceIn previous versions of `MFront`

, the list of parameters' names and types were not exported to the generated library for the `UMAT++`

interface, i.e. the additional symbols defined in the generated shared libraries that can be read through the `ExternalLibraryManager`

class.

For more details, see: https://sourceforge.net/p/tfel/tickets/43/

For more details, see: https://sourceforge.net/p/tfel/tickets/45/

`mfront`

`python`

moduleThe following improvements to the `mfront`

`python`

module have been made:

- Add missing metods in the
`BehaviourDescription`

class to retrieve information about the material symmetry - Add missing methods to retrieve information about standard and physical variables' bounds.

For more details, see: https://sourceforge.net/p/tfel/tickets/46/

`python`

bindings for the `mtest::Behaviour`

classThe `mtest`

module now contains bindings for the `mtest::Behaviour`

class. This class allow querying information about how to use a behaviour in a specific context (interface and modelling hypothesis): for example, if a behaviour has the `requireStiffnessTensor`

attribute, the list of material properties is updated appropriately if required by the interface for the considered modelling hypothesis. The `Behaviour`

class has the following useful methods:

`getBehaviourType`

: Return the behaviour type.`getBehaviourKinematic`

: Return the behaviour kinematic.`getDrivingVariablesSize`

: Return the size of a vector able to contain all the components of the driving variables.`getThermodynamicForcesSize`

: Return the size of a vector able to contain all the components of the thermodynamic forces.`getStensorComponentsSuffixes`

: Return the components suffixes of a symmetric tensor.`getVectorComponentsSuffixes`

: Return the components suffixes of a vector.`getTensorComponentsSuffixes`

: Return the components suffixes of a tensor.`getDrivingVariablesComponents`

: Return the components of the driving variables.`getThermodynamicForcesComponents`

: Return the components of the thermodynamic forces.`getDrivingVariableComponentPosition`

: Return the position of the component of a driving variable.`getThermodynamicForceComponentPosition`

: Return the position of the component of a thermodynamic force.`getSymmetryType`

: Return the symmetry of the behaviour: -- 0 means that the behaviour is isotropic. -- 1 means that the behaviour is orthotropic.`getMaterialPropertiesNames`

: return the names of the material properties.`getInternalStateVariablesNames`

: Return the names of the internal state variables.`expandInternalStateVariablesNames`

: Return the names of the internal state variables, taking into account the suffixes for vectors, symmetric tensors and tensors.`getInternalStateVariablesSize`

: Return the the size of the array of internal variables.`getInternalStateVariablesDescriptions`

: Return the descriptions the internal variables.`getInternalStateVariableType`

: Return the type of an internal variable:- 0 means that the internal state variable is a scalar.
- 1 means that the internal state variable is a symmetric tensor.
- 3 means that the internal state variable is a tensor.

`getInternalStateVariablePosition`

: Return the internal state variable position.`getExternalStateVariablesNames`

: Return the names of the external state variables.`getParametersNames`

: Return the names of the floating point parameters.`getIntegerParametersNames`

: Return the names of the integer parameters.`getUnsignedShortParametersNames`

: Return the names of the unsigned short parameters.- The
`getRealParameterDefaultValue`

,`getIntegerParameterDefaultValue`

and`getUnsignedShortParameterDefaultValue`

methods can be used to retrieve the default value of a parameter. - The
`hasBounds`

method returns true if the given variable has bounds. - The
`hasLowerBound`

method returns true if the given variable has a lower bound. - The
`hasUpperBound`

method hasUpperBound returns true if the given variable has an upper bound. - The
`getLowerBound`

method returns the lower bound of the given variable. - The
`getUpperBound`

method returns the uppert bound of the given variable. - The
`hasPhysicalBounds`

methodreturns true if the given variable has physical bounds. - The
`hasLowerPhysicalBound`

method returns true if the given variable has a physical lower bound. - The
`hasUpperPhysicalBound`

method returns true if the given variable has a physical upper bound. - The
`getLowerPhysicalBound`

method returns the lower bound of the given variable. - The
`getUpperPhysicalBound`

method returns the upper bound of the given variable.

For more details, see: https://sourceforge.net/p/tfel/tickets/47/

Here is an example of the usage of the `Behaviour`

class in `python`

:

```
import mtest
b= mtest.Behaviour('AsterBehaviour','asternorton','Tridimensional');
for p in b.getParametersNames():
print('- '+p+': '+str(b.getRealParameterDefaultValue(p)))
for p in b.getIntegerParametersNames():
print('- '+p+': '+str(b.getIntegerParameterDefaultValue(p)))
for p in b.getUnsignedShortParametersNames():
print('- '+p+': '+str(b.getUnsignedShortParameterDefaultValue(p)))
```

`python`

bindings for the `mfront::BehaviourDescription`

classThe `python`

bindings of the `mfront::BehaviourDescription`

now gives access to the parameters default values, and information about a variable standard or physical bounds (type, range).

Here is an example of its usage:

```
from tfel.material import ModellingHypothesis
import mfront
def printBounds(n,b):
print('Bounds of variable \''+n+'\':')
if((b.boundsType==mfront.VariableBoundsTypes.LOWER) or
(b.boundsType==mfront.VariableBoundsTypes.LOWERANDUPPER)):
print('- lower bound: '+str(b.lowerBound))
if((b.boundsType==mfront.VariableBoundsTypes.UPPER) or
(b.boundsType==mfront.VariableBoundsTypes.LOWERANDUPPER)):
print('- upper bound: '+str(b.upperBound))
print('')
dsl = mfront.getDSL('Norton.mfront')
dsl.analyseFile('Norton.mfront',[])
# behaviour description
bd = dsl.getBehaviourDescription()
if(bd.getSymmetryType()==mfront.BehaviourSymmetryType.ISOTROPIC):
print 'Isotropic behaviour\n'
else:
print 'Orthropic behaviour\n'
if(bd.getElasticSymmetryType()==mfront.BehaviourSymmetryType.ISOTROPIC):
print 'Isotropic elasticity\n'
else:
print 'Orthropic elasticity\n'
# a deeper look at the 3D case
d = bd.getBehaviourData(ModellingHypothesis.TRIDIMENSIONAL)
for p in d.getParameters():
if(p.arraySize==1):
if(p.hasBounds()):
printBounds(p.name,p.getBounds())
else:
for i in range(p.arraySize):
if(p.hasBounds(i)):
printBounds(p.name+'['+str(i)+']',p.getBounds(i))
```

`mtest::Behaviour`

classThe following methods were added to the `mtest.Behaviour`

class: - The `hasBounds`

method returns true if the given variable has bounds. - The `hasLowerBound`

method returns true if the given variable has a lower bound. - The `hasUpperBound`

method hasUpperBound returns true if the given variable has an upper bound. - The `getLowerBound`

method returns the lower bound of the given variable. - The `getUpperBound`

method returns the uppert bound of the given variable. - The `hasPhysicalBounds`

methodreturns true if the given variable has physical bounds. - The `hasLowerPhysicalBound`

method returns true if the given variable has a physical lower bound. - The `hasUpperPhysicalBound`

method returns true if the given variable has a physical upper bound. - The `getLowerPhysicalBound`

method returns the lower bound of the given variable. - The `getUpperPhysicalBound`

method returns the upper bound of the given variable.

Here is an example:

```
from mtest import Behaviour
b = Behaviour('AsterBehaviour','asternorton','Tridimensional')
for p in b.getParametersNames():
if b.hasLowerBound(p):
print(p+" lower bound: "+str(b.getLowerBound(p)))
if b.hasUpperBound(p):
print(p+" lower bound: "+str(b.getUpperBound(p)))
```

For more details, see: https://sourceforge.net/p/tfel/tickets/48/

`mfront-query`

The following queries are now available:

`--elastic-symmetry`

: return the symmetry of the elastic part of the behaviour. If the returned value is 0, this part of the behaviour is isotropic. If the returned value is 1, this part of the behaviour is orthotropic.the behaviour is orthotropic.`--symmetry`

: return the behaviour symmetry. If the returned value is 0, the behaviour is isotropic. If the returned value is 1, the behaviour is orthotropic.

For more details, see: https://sourceforge.net/p/tfel/tickets/49/

`mfront-query`

The following queries are now available:

`--has-bounds`

: return`true`

if a variable has bounds,`false`

otherwise.`--bounds-type`

: return the bounds type associated to a variable.`--bounds-value`

: show the bounds value associated as a range.`--has-physical-bounds`

: return`true`

if a variable has physical bounds,`false`

otherwise.`--physical-bounds-type`

: return the physical bounds type associated to a variable.`--physical-bounds-value`

: show the bounds value associated as a range.

For more details, see: https://sourceforge.net/p/tfel/tickets/50/

`@ElasticMaterialProperties`

does not work for DSL describing isotropics behavioursThe `@ElasticMaterialProperties`

is now available for domain specific languages (DSL) describing isotropics behaviours.

```
@DSL IsotropicStrainHardeningMisesCreep;
@Behaviour StrainHardeningCreep2;
@Author Helfer Thomas;
@Date 23/11/06;
@ElasticMaterialProperties {"Inconel600_YoungModulus.mfront",0.3};
@MaterialProperty real A;
@MaterialProperty real Ns;
@MaterialProperty real Np;
@FlowRule{
const real p0 = 1.e-6;
const real tmp = A*pow(seq,Ns-1.)*pow(p+p0,-Np-1);
f = tmp*seq*(p+p0);
df_dseq = Ns*tmp*(p+p0);
df_dp = -Np*tmp*seq;
}
```

For more details, see: https://sourceforge.net/p/tfel/tickets/65/

`mfront-query`

: handle static variables`mfront-query`

now has the following options:

`--static-variables`

: list all the static variables`--static-variable-value`

: return the value of a given static variable

For more details, see: https://sourceforge.net/p/tfel/tickets/74/

`python`

bindings for the `SearchPathsHandler`

class in the `mfront`

moduleThe `SearchPathsHandler`

class is used in `MFront`

to search additional files. Bindings for this class has been added to the `mfront`

module. The following methods are available:

`addSearchPaths`

: Add new search paths. Multiple paths are separated by commas under unices systems and by semicolons under Windows systems.`search`

: search a file and return the path to it if found.`getSearchPaths`

: return all the registred search paths.

For more details, see: https://sourceforge.net/p/tfel/tickets/76/

All variables, to the very exception of local variables, must be declared before the first user defined code block to allow appropriate analysis of those code blocks.

Some variables are automatically declared by keywords. For instance, the `@Epsilon`

keyword defines implicitly a parameter named `epsilon`

.

In previous versions of `MFront`

, those rules were only partially enforced: it may happen that some keywords or variable declaration shall now be moved before the first user defined code block.

Belytschko, Ted. 2000. *Nonlinear Finite Elements for Continua and Structures*. Chichester ; New York: Wiley-Blackwell.

Eberly, David. 2016. “A Robust Eigensolver for 3 × 3 Symmetric Matrices.” https://www.geometrictools.com/Documentation/RobustEigenSymmetric3x3.pdf.

———. 2017. “Geometric Tools.” http://www.geometrictools.com/.

Kopp, Joachim. 2008. “Efficient Numerical Diagonalization of Hermitian 3x3 Matrices.” *International Journal of Modern Physics C* 19 (3): 523–48. doi:10.1142/S0129183108012303.

———. 2017. “Numerical Diagonalization of 3x3 Matrices.” https://www.mpi-hd.mpg.de/personalhomes/globes/3x3/.

Musl development community. 2017. “Musl Libc.” https://www.musl-libc.org/.