The fmu_tools
library offers a set of utilities to import/export any existing model from/into an FMU.
For the FMU export, the library, mainly through its main class FmuComponentBase
, provides a higher C++ layer that:
- on the outer side: offers to the final user the standard FMU interface
- on the inner side: offers to the FMU developer an extensive set of utilities to bind its model to the FMU instance
The CMake infrastructure takes care of:
- building the source code;
- generating the modelDescription.xml;
- creating the standard FMU directory layout;
- packaging into a .fmu ZIP archive;
- runring compliance checks on the generated FMU.
For the FMU import, the library offers some auxiliary function to easily access internal variables by name, recognizes Modelica visualization shape structures by parsing the modelDescription.xml and to provide a dynamical link to any FMU.
A simple use of the library consists in just taking the project and modifying the myFmuComponent.h and myFmuComponent.cpp based on the user needs.
For those that would like to enable the feature of exporting FMUs into their projects, we suggest to refer to the template_project_fmu
of the Chrono library in which the CMakeLists takes care of fetching the content of this 'fmu_tools' library while linking to other libraries.
While this library offers some generic features and tools, users are asked to customize them for their specific problem. This is done by inheriting from FmuComponentBase
, plus some additional customization. One example is provided by the myFmuComponent
class. The impatient user could also just modify and use it straight away.
For those that want to develop their own indipendent class, they are required to:
- in CMake, set the
FMU_MODEL_IDENTIFIER
to any valid name (consider your operating system and C-function naming standards); a new target with same name will be created; - derive from
FmuComponentBase
your own class; please refer tomyFmuComponent
for an example; - the derived class should:
- in the constructor, remember to call
FmuComponentBase::instantiateType(_fmuType)
; - in the constructor, add all the relevant variables of the model to the FMU through
AddFmuVariable
; variable measurement units are supported and some default units are already declared; please also remember that the variables that are here binded to the FMU must be updated during_doStep
call; an auxiliary function (namelyupdateVars
) is automatically called after the call to_doStep
to run all the functions listed into theupdateVarsCallbacks
variable; it's up to the user to register the updating functions to this list; - a predefined
time
variable comes pre-binded to the FMU: remember to update it as well; - override
FmuComponentBase::_enterInitializationMode()
andFmuComponentBase::_exitInitializationMode()
: between these two calls the user should be able to set the parameters of the simulation; after the call to_exitInitializationMode
the model should be ready to run; - override
FmuComponentBase::is_cosimulation_available()
andFmuComponentBase::is_modelexchange_available()
so that they would return the proper answer; - override
_doStep
method of the base class with the problem-specific implementation.
- in the constructor, remember to call
- provide the implementation of
fmi2Instantiate_getPointer
similarly to:FmuComponentBase* fmi2Instantiate_getPointer( fmi2String instanceName, fmi2Type fmuType, fmi2String fmuGUID) { return new myFmuComponent(instanceName, fmuType, fmuGUID); }
Adding variables to the FMU is possible in two different flavours: by just passing the address of any given variable whose type is directly supported by the FMU interface or by providing a pair of getter/setter methods. Since the definition of these function pairs might not be immediate an helper macro MAKE_GETSET_PAIR
When everything is set up, build the PACK_FMU target to generate the FMU file.
- in the rare case that the user requires a different set of FMI variable types, it is required to modify fmi2_headers\fmi2TypesPlatform.h accordingly; in this case the TypesVariants.h file should be modified as well, so that the two variants declared do not contain any repeated type;
- while adding new FMU variables, the user can associate a measurement unit to them (otherwise the adimensional unit "1" will be set). However, units needs to be defined before any FMU variable could use them. Measurement units are defined through the
UnitDefinitionType
class, that stores the name of the unit (e.g. "rad/s2") together with the exponents of each SI base unit (e.g. rad=1, s=-2). The user should create its own object of typeUnitDefinitionType
and then pass it toFmuComponentBase
through its methodaddUnitDefinition
. After this step, the user can use the unit name in any following call toAddFmuVariable
; - the
RUN_TESTS
target will run the fmuChecker utility over the newly created fmu and makes sure no error is returned (only 'win64' and 'linux64' are available for now);
The target fmu_host
shows how to load and run FMUs. By default, it is set up to use the FMU generated by the FMU export target.
- basic import of FMUs
- basic export of FMUs
- associate Units to Variables
- keep C++14 compliance (filesystem and variant custom C++14 compliant implementation are offered)
- check compatibility of causality|variability|initial attributes for variables
- accept getter function instead of the usual pointer to variable (guarantee that this is allowed only for variables that can never be set)
- allow non-default 'fmi2TypesPlatform.h'
- register local variables as FMU variables
- automatic creation of modelDescription.xml based on registered variables
- automatic build, modelDescription.xml generation and zipping (through CMake post-build)
- GUID creation
- set of Resources folder
- unzip the FMUs (cross-platform, header-only)
- GUID checks (optional)
- test exported FMUs through the importer
- test exported FMUs with fmuChecker
- automatic testing with fmuChecker
- test on Win
- test on Linux (GCC8.5.0)
- test on MacOS
- importing
fmu_tools
into other project