TFEL
librariesThe assets generated by MFront are used in studies which
must remain reproducible for many years. A development which does not
fix an explicit bug but changes the results of the TFEL
libraries, such as the use of more accurate values of the physical
constants or the introduction of a more robust numerical algorithm, is
therefore handled by a compatibility mode: the new behaviour becomes the
default of a new version and the previous behaviour remains available
for the users who need it. This policy is stated in the coding
guidelines.
A compatibility mode is a version number: the mode associated with a
change is the version in which this change becomes the default. Such
evolutions of the default behaviour shall only be introduced on major
versions. The future compatibility mode gathers the changes
which are not the default yet but which shall be the default of the next
major version, so that they can be tested and anticipated.
The way MFront selects the compatibility mode of the
code it generates, and the way this mode is recorded in the generated
assets, are described in this
page.
Compatibility modes are a compile time mechanism in the
TFEL libraries: the entities which are subject to such an
evolution are duplicated, once per mode, in a header and in a namespace
named after the version which introduced them. Both behaviours are thus
compiled, once for each mode, and the user selects the one it needs by
naming the mode it contains.
This mechanism relies on names: the versioned entities are
constexpr entities or templates which are resolved when the
code using them is compiled, whatever the way this code has been
generated. Only the Python bindings use a preprocessor
definition, TFEL_VERSION_MAJOR, to select the values of the
current version.
The names which do not mention a mode, such as
tfel::PhysicalConstants, refer to the entity of the mode of
the current version of the library, whereas the entities of the previous
modes stay available, as those of the next major version.
The names which a versioned entity gives rise to are gathered in the
following table, where <X>.<Y>.<Z> is the
compatibility mode which introduced the entity,
<Name> is the name of the entity,
PhysicalConstants in the case of the physical constants,
and <NS> is the namespace which declares the
variables of the entity, tfel::constants in the case of the
physical constants:
| Role | Name |
|---|---|
| Header of the mode | TFEL/<Name>-<X>.<Y>.<Z>.hxx |
| Class of the mode | tfel::v<x>_<y>_<z>::<Name> |
| Variables of the mode | <NS>::v<x>_<y>_<z> |
| Header gathering all the modes | TFEL/<Name>.hxx, which includes all the previous
ones |
| Name of the current mode | tfel::<Name> and <NS>, which
refer to the entity of the mode of the current version |
| Name of the next major version | tfel::future::<Name> and
<NS>::future, which refer to the entity of the mode
of the next major version |
The suffix v<x>_<y>_<z> used in the
names above is the name of the version in which the mode was introduced,
with underscores instead of dots. It is also the name under which the
mode is declared in MFront, in the
known_compatibility_modes array of the
CompatibilityMode structure, as described in this
section.
The TFEL/PhysicalConstants library, which is at the time
of writing the only versioned library of TFEL, illustrates
this convention. The value of the molar gas constant is accessed in four
different ways:
#include "TFEL/PhysicalConstants.hxx"
// the value of the current version, 5.2.0 in Version 5.2
constexpr auto r1 = tfel::constants::R<double>;
// the value of a given mode
constexpr auto r2 = tfel::constants::v5_2_0::R<double>;
// the value of the next major version
constexpr auto r3 = tfel::constants::future::R<double>;
// so is the value of the mode of the next major version
constexpr auto r4 = tfel::constants::v6_0_0::R<double>;The same convention applies to the class which groups the constants
of a mode: tfel::PhysicalConstants,
tfel::v5_2_0::PhysicalConstants and
tfel::future::PhysicalConstants.
The page devoted to the values of
the physical constants describes in detail how this library handles
the compatibility modes, how those values are used in the
C++, Python and Fortran
interfaces and how a new set of values is introduced.
The language bindings follow the same convention: the entities which
do not mention a mode give the values of the current version of
TFEL, whereas the entities of the other modes are made
available in a scope named after the mode, which is a submodule in
Python:
>>> import tfel
>>> tfel.PhysicalConstants.R
8.31446
>>> tfel.v5_2_0.PhysicalConstants.R
8.31446
>>> tfel.future.PhysicalConstants.R
8.3144598tfel.PhysicalConstants gives the values of the current
version, tfel.v5_2_0.PhysicalConstants those of the
5.2.0 compatibility mode and
tfel.future.PhysicalConstants those of the next major
version.
A binding which is not versioned yet, such as the
Fortran one, exposes the values of the next major
version.
A development which changes the results given by an entity of the
TFEL libraries, without fixing an explicit bug, shall
proceed as follows:
Duplicate the entity, giving the version which introduces the change: the previous version keeps the names it has, whereas the new entity is defined in the header and in the namespace of the new mode, as described in the previous section. Both entities declare the same names, so that switching from a mode to another one does not require any other modification.
Keep the names which do not mention a mode pointing to the entity
of the mode of the current version of TFEL and those of the
tfel::future namespace pointing to the entity of the next
major version.
Install the new header in
include/CMakeLists.txt:
install_header(TFEL <Name>-<X>.<Y>.<Z>.hxx)Give access to the new entity in the language bindings which are versioned, following the convention of the language, as described in the corresponding section.
Declare the new mode in MFront, in the
CompatibilityMode structure, as described in this
section, so that MFront can generate code using the
entities of this mode.
Test both behaviours: a test behaviour, model or material
property, generated with each mode and an MTest file
checking the results it gives. The PhysicalConstants_v5_2_0
and PhysicalConstants_v6_0_0 test models, which return the
value of the Stefan-Boltzmann constant, and the MTest files
physical-constants-5.2.0.mtest and
physical-constants-6.0.0.mtest, which check the value they
give, are the reference tests of this mechanism.
Describe the change, and the compatibility mode which introduces it, in the release notes of the version which introduces them.
The values of the physical constants page describes how this checklist is applied to the physical constants, whose values are generated from a single data file.
Fortran bindings are not versioned yet: they expose
a single set of constants, which is that of the next major version.TFEL libraries raises
no fundamental difficulty, as long as the versioned entities are
constexpr entities or templates: the mechanism does not
rely on a preprocessor definition, since the values are resolved when
the generated code is compiled.