MFrontMFront generates assets which are used in studies that
must remain reproducible for many years. A development which does not
fix an explicit bug but changes the results of the generated code or the
behaviour of MFront itself, such as a new default value of
an option or a new default behaviour of a working keyword, is therefore
handled by a compatibility mode: the new behaviour is used by default
from a given version on, whereas users who need the previous one can
restore it by selecting an older compatibility mode. This policy is
stated in the coding
guidelines.
The two developments which motivated this mechanism are the use of
more accurate and up-to-date values of the physical constants and the
evolution of the PowellDogLeg algorithms to a more robust
and classical version. Those evolutions do not correct bugs: they change
the default behaviour of MFront and the results of the
generated code for the better.
Compatibility modes are 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 allows testing
them, or anticipating them, before they become the default.
The way the compatibility modes are implemented in the
TFEL libraries is described in this page.
| Compatibility mode | Description |
|---|---|
5.2.0 |
Values and behaviours of Version 5.2. First version supporting compatibility modes. |
future |
Values and behaviours of the next major version, which is still under development. |
A compatibility mode is a version: a mode will be added for each version introducing a change of the default behaviour.
By default, no compatibility mode is declared: the generated code
uses the greatest compatibility mode known by MFront, that
is to say the mode of the current version (5.2.0 in Version
5.2). A default mode can be declared globally, for all the files treated
by a run of the tool, using the
--default-compatibility-mode command line argument, as
explained below.
Declaring a compatibility mode makes the results of the generated
code independent of the version of the TFEL libraries used
to compile it (except for the future compatibility mode):
the generated code uses the entities of the mode it asks for, whatever
this version is, as described in
the next section. In Version 5.2, both approaches give the same
results since the current values of the physical constants are those of
the 5.2.0 mode.
--default-compatibility-mode argumentThe --default-compatibility-mode argument declares a
compatibility mode for all the files treated by a run of the tool. It is
supported by mfront, mfront-doc and
mfront-query, but only mfront generates
code:
$ mfront --obuild --interface=generic --default-compatibility-mode=5.2.0 *.mfrontThe accepted values are a version, such as 5.2.0 or
5.3.1, or the future mode. A version which is
not itself a known compatibility mode is associated with the greatest
known compatibility mode which does not exceed it, which is reported by
a warning: requesting 5.3.0 gives the 5.2.0
mode as long as no other mode has been introduced. A version strictly
lower than 5.2.0 is rejected.
compatibility_mode DSL optionThe compatibility mode of a single file is set by the
compatibility_mode option of the domain specific language,
which is available for all DSLs. This option has precedence
over the default compatibility mode.
It can be defined in the MFront file itself, using the
@DSL keyword, as in the following behaviour:
// Norton.mfront
@DSL Default{
compatibility_mode : "5.2.0"
};The name of the domain specific language follows the
@DSL keyword: Default for a behaviour,
DefaultModel for a model, MaterialProperty for
a material property, and so on.
It can also be defined on the command line, using the
--dsl-option argument, or one of its variants
--behaviour-dsl-option,
--material-property-dsl-option and
--model-dsl-option:
$ mfront --obuild --interface=generic --dsl-option=compatibility_mode:\"5.2.0\" Norton.mfrontAs for any option expecting a string value, special care must be taken with the quotes.
Finally, it can be defined in the configuration file passed with the
--configuration-file argument, in the
dsl_options section or in one of the sections dedicated to
a kind of material knowledge:
dsl_options : {
compatibility_mode : "5.2.0"
}As any DSL option, this option is listed by the
--list-dsl-options argument:
$ mfront --list-dsl-options=DefaultModel
- disable_runtime_checks : boolean stating if interfaces shall remove as much runtime checks as possible. ...
...
- compatibility_mode : string giving the version to which the MFront file shall comply.
...When a compatibility mode is declared, the generated code only refers
to the entities of this mode: those are duplicated, one copy per mode,
in the TFEL libraries, as described in this page. The results it gives
do not depend on the version of the TFEL libraries used to
compile it, except for bug fixes. When no compatibility mode is
declared, the generated code refers to the entities of the greatest
compatibility mode known by MFront, that is to say the mode
of the current version, and follows therefore the current behaviour of
that version.
For instance, the alias giving access to the physical constants in the generated code is:
// no compatibility mode declared, in Version 5.2
using PhysicalConstants [[maybe_unused]] =
tfel::v5_2_0::PhysicalConstants<NumericType, false>;// compatibility mode 5.2.0
using PhysicalConstants [[maybe_unused]] =
tfel::v5_2_0::PhysicalConstants<NumericType, false>;// future compatibility mode
using PhysicalConstants [[maybe_unused]] =
tfel::future::PhysicalConstants<NumericType, false>;For an asset which uses quantities (@UseQt), the second
template argument of the alias is use_qt instead of
false.
The physical constants are, at the time of writing, the only entities whose behaviour is subject to a compatibility mode. Any other entity, such as a brick or a non linear solver, shall be treated in the same way: the code generated for an asset which declares a compatibility mode uses the implementation designated by this mode.
When a compatibility mode is declared for an asset, it is recorded in
the generated code as an exported string symbol, whose name is the name
of the entry point suffixed by _compatibility_mode:
MFRONT_EXPORT_SYMBOL(const char*, Norton_compatibility_mode, "5.2.0");This symbol is generated whatever the way the mode has been declared,
by the compatibility_mode option of the DSL of
the file or by the --default-compatibility-mode argument:
it is not generated when no compatibility mode is declared. The
ExternalLibraryManager class of the
TFEL/System library returns it:
auto& elms =
tfel::system::ExternalLibraryManager::getExternalLibraryManager();
std::cout << elms.getCompatibilityMode("libBehaviour.so", "Norton")
<< '\n';>>> import tfel.system
>>> m = tfel.system.ExternalLibraryManager.getExternalLibraryManager()
>>> m.getCompatibilityMode("libBehaviour.so", "Norton")
'5.2.0'An empty string is returned when no compatibility mode is declared
for the asset: it then uses the greatest compatibility mode known by the
version of MFront which generated it.
The compatibility_mode attribute of a behaviour is
reported by the --attributes query of
mfront-query, which lists the names of the attributes of a
behaviour, when a compatibility mode is declared, by the file or by the
--default-compatibility-mode argument:
$ mfront-query --attributes Norton.mfront
automatic_declaration_of_the_temperature_as_first_external_state_variable
compatibility_mode use_stress_update_algorithm ...future
compatibility modeThe future compatibility mode introduces changes which
shall be the default of the next major version. It allows users to test
them in advance and to prepare their assets, whereas the values and the
behaviours of the current version are left unchanged.
An asset generated with the future mode is thus expected
to behave in the same way as the same asset generated with the version
which will make those changes the default. This is the reason why the
code generated in the future mode refers to the constants
of the next major version, tfel::future::PhysicalConstants,
and not to those of the current version.
The future mode is by nature unstable: new changes can
be added to it until the corresponding major version is released.
A development which changes the default behaviour of
MFront or the results of the code it generates, without
fixing an explicit bug, shall be gated by the compatibility mode of the
file it compiles. Such a development proceeds as follows:
Determine the version which shall make the new behaviour the
default. If this is not the next major version, the change is added to
the future mode only.
Declare the new mode in MFront, in
mfront/include/MFront/CompatibilityMode.hxx, by adding a
new version and inserting it in the
known_compatibility_modes array:
static inline constexpr auto v6_0_0 =
Version{.major = 6, .minor = 0, .patch = 0};The name of the version in this array is the name of the
C++ namespace used by the versioned entities of the
TFEL libraries, as described in the corresponding
section.
Use the compatibility mode in the code generator, using the
getEffectiveCompatibilityMode function, which returns the
mode declared by the material knowledge description or, if it declares
none, the greatest known compatibility mode, that is to say the mode of
the current version. An asset which declares no mode thus keeps the
behaviour of the current version. A change which becomes the default in
the next major version is gated as follows:
const auto v = getEffectiveCompatibilityMode(d);
if (v > CompatibilityMode::v5_2_0) {
// new behaviour: `future` mode, then default of Version 6.0
} else {
// previous behaviour: `5.2.0` mode, or no mode in Version 5.2
}Test both behaviours: a test behaviour, or model, or material
property, generated with each mode, and an MTest file
checking the results it gives, as the
PhysicalConstants_v5_2_0 and
PhysicalConstants_v6_0_0 test models do, the latter being
generated with the future mode.
If the change affects the TFEL libraries, follow the
checklist of the corresponding
section.
Describe the change in the release notes of the version which introduces it, in the section describing the compatibility modes.
The unit test CompatibilityModeTest checks the behaviour
of the CompatibilityMode structure: a new mode shall be
added to this test.