The 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.

Principle of the versioned entities

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.

Naming convention

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.

Example

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.

Versioned language bindings

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.3144598

tfel.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.

Adding a new compatibility mode

A development which changes the results given by an entity of the TFEL libraries, without fixing an explicit bug, shall proceed as follows:

  1. 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.

  2. 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.

  3. Install the new header in include/CMakeLists.txt:

    install_header(TFEL <Name>-<X>.<Y>.<Z>.hxx)
  4. 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.

  5. 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.

  6. 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.

  7. 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.

Known limitations

See also