The Functional Mock-Up Interface (FMI) defines an exchange format that allows models, referred to as Functional Mock-Up Unit (FMU), to be shared between tools supporting the standard. In general, an FMU must be implemented in a programming language that can produce binaries that can be called from C, such as C itself or C++. While this allows efficient execution of a simulation, it is a significant limitation when prototyping models.
UniFMU is a command line tool that facilitates the implementation of FMUs in other popular languages that would otherwise not be able to produce C-compatible binaries. It does this by providing a precompiled binary that is C-compatible, which then dispatches calls to the implementation of the model in the target language.
Specification Version | FMU Interface | Languages | Binaries |
---|---|---|---|
FMI3 (in progress) | (Co-Simulation) | (Python, C#, Java) | (win64, linux64, darwin64) |
FMI2 | Co-Simulation | Python, C#, Java | win64, linux64, darwin64 |
FMI1 | x | x | x |
Examples of generated FMUs can be found in the unifmu_examples repo.
The tool can be downloaded from releases tab of the repository. It is a single executable that bundles all assets used during FMU generation as part of the binary.
To display the synopsis use the --help
flag.
unifmu 0.0.8
Implement Functional Mock-up units (FMUs) in various source languages.
* Source: https://github.com/INTO-CPS-Association/unifmu
* Examples: https://github.com/INTO-CPS-Association/unifmu_examples
USAGE:
unifmu <SUBCOMMAND>
OPTIONS:
-h, --help Print help information
-V, --version Print version information
SUBCOMMANDS:
generate Create a new FMU using the specified source language
help Print this message or the help of the given subcommand(s)
The command uses git-style subcommands, an example being generate
.
Help for the individual commands can be inquired by appending the --help
after the name of the subcommand.
Create a new FMU using the specified source language
USAGE:
unifmu generate [OPTIONS] <LANGUAGE> <FMU_VERSION> <OUTPATH>
ARGS:
<LANGUAGE> Source language of the generated FMU [possible values: python, c-sharp, java]
<FMU_VERSION> Version of the FMI specification to target [possible values: fmi2, fmi3 (in progress)]
<OUTPATH> Output directory or name of the FMU archive if "--zipped" is passed
OPTIONS:
-h, --help Print help information
-z, --zipped Compress the generated FMU as a zip-archive and store with '.fmu' extension
The generate command can be used to create a new FMU:
unifmu generate python model
The command generates a placeholder FMU implemented in the specific language. For example the tree below shows the placeholder FMU generated when implementing an FMU in python using UniFMU:
π¦model
β£ πbinaries
β β£ πdarwin64
β β β πunifmu.dylib
β β£ πlinux64
β β β πunifmu.so
β β πwin64
β β β πunifmu.dll
β£ πresources
β β£ πschemas
β β β πfmi2_messages_pb2.py
β β£ πbackend.py
β β£ πlaunch.toml
β β£ πmodel.py
β β πREADME.md
β πmodelDescription.xml
Like the file structure, the workflow for modifying FMUs varies depending on the implementation language.
Depending on the language a README.md
is placed in the root of the generated FMU, which serves as documentation for the particular language.
For reference the README.md
copied into Python FMUs looks like README.md.
Name | Supported | Notes |
---|---|---|
fmi2GetTypesPlatform | β | |
fmi2GetVersion | β | |
fmi2SetDebugLogging | x | |
fmi2Instantiate | β | |
fmi2FreeInstance | β | |
fmi2SetupExperiment | β | |
fmi2EnterInitializationMode | β | |
fmi2ExitInitializationMode | β | |
fmi2Terminate | β | |
fmi2Reset | β | |
fmi2GetReal | β | |
fmi2GetInteger | β | |
fmi2GetBoolean | β | |
fmi2GetString | β | |
fmi2SetReal | β | |
fmi2SetInteger | β | |
fmi2SetBoolean | β | |
fmi2SetString | β | |
fmi2GetFMUstate | β | |
fmi2SetFMUstate | β | |
fmi2FreeFMUstate | β | |
fmi2SerializedFMUstateSize | β | |
fmi2SerializeFMUstate | β | |
fmi2DeSerializeFMUstate | β | |
fmi2GetDirectionalDerivative | x | |
fmi2EnterEventMode | x | |
fmi2NewDiscreteStates | x | |
fmi2EnterContinuousTimeMode | x | |
fmi2CompletedIntegratorStep | x | |
fmi2SetTime | x | |
fmi2SetContinuousStates | x | |
fmi2GetDerivatives | x | |
fmi2GetEventIndicators | x | |
fmi2GetContinuousStates | x | |
fmi2GetNominalsOfContinuousStates | x | |
fmi2SetRealInputDerivatives | x | |
fmi2GetRealOutputDerivatives | x | |
fmi2DoStep | β | |
fmi2CancelStep | x | |
fmi2GetStatus | x | |
fmi2GetRealStatus | x | |
fmi2GetIntegerStatus | x | |
fmi2GetBooleanStatus | x | |
fmi2GetStringStatus | x |
Name | Supported | Notes |
---|---|---|
fmi3GetVersion | β | |
fmi3SetDebugLogging | x | |
fmi3InstantiateModelExchange | x | |
fmi3InstantiateCoSimulation | β | |
fmi3InstantiateScheduledExecution | x | |
fmi3FreeInstance | β | |
fmi3EnterInitializationMode | β | |
fmi3ExitInitializationMode | β | |
fmi3EnterEventMode | x | |
fmi3Terminate | β | |
fmi3Reset | β | |
fmi3GetFloat32 | β | |
fmi3GetFloat64 | β | |
fmi3GetInt8 | β | |
fmi3GetUInt8 | β | |
fmi3GetInt16 | β | |
fmi3GetUInt16 | β | |
fmi3GetInt32 | β | |
fmi3GetUInt32 | β | |
fmi3GetInt64 | β | |
fmi3GetUInt64 | β | |
fmi3GetBoolean | β | |
fmi3GetString | β | |
fmi3GetBinary | β | |
fmi3GetClock | β | |
fmi3SetFloat32 | β | |
fmi3SetFloat64 | β | |
fmi3SetInt8 | β | |
fmi3SetUInt8 | β | |
fmi3SetInt16 | β | |
fmi3SetUInt16 | β | |
fmi3SetInt32 | β | |
fmi3SetUInt32 | β | |
fmi3SetInt64 | β | |
fmi3SetUInt64 | β | |
fmi3SetBoolean | β | |
fmi3SetString | β | |
fmi3SetBinary | β | |
fmi3SetClock | x | |
fmi3GetNumberOfVariableDependencies | x | |
fmi3GetVariableDependencies | x | |
fmi3GetFMUState | β | |
fmi3SetFMUState | β | |
fmi3FreeFMUState | β | |
fmi3SerializedFMUStateSize | β | |
fmi3SerializeFMUState | β | |
fmi3DeserializeFMUState | β | |
fmi3GetDirectionalDerivative | x | |
fmi3GetAdjointDerivative | x | |
fmi3EnterConfigurationMode | x | |
fmi3ExitConfigurationMode | x | |
fmi3GetIntervalDecimal | x | |
fmi3GetIntervalFraction | x | |
fmi3GetShiftDecimal | x | |
fmi3GetShiftFraction | x | |
fmi3SetIntervalDecimal | x | |
fmi3SetIntervalFraction | x | |
fmi3SetShiftDecimal | x | |
fmi3SetShiftFraction | x | |
fmi3EvaluateDiscreteStates | x | |
fmi3UpdateDiscreteStates | x | |
fmi3EnterContinuousTimeMode | x | |
fmi3CompletedIntegratorStep | x | |
fmi3SetTime | x | |
fmi3SetContinuousStates | x | |
fmi3GetContinuousStateDerivatives | x | |
fmi3GetEventIndicators | x | |
fmi3GetContinuousStates | x | |
fmi3GetNominalsOfContinuousStates | x | |
fmi3GetNumberOfEventIndicators | x | |
fmi3GetNumberOfContinuousStates | x | |
fmi3EnterStepMode | x | |
fmi3GetOutputDerivatives | x | |
fmi3DoStep | x | |
fmi3ActivateModelPartition | x |
Building for local machine (with Windows as the example). This is a good method to locally test if the program is running as it should, before cross-compiling to different OSs.
make sure you have the following installed on your computer:
o rust
git clone the unifmu
repository.
make the changes you want.
install the rust toolchain for your operating systems, e.g. rustup target add x86_64-pc-windows-msvc
(msvc is the microsoft C-compiler).
build the project using cargo build --target x86_64-pc-windows-msvc --release
. This should build the project for your operating system, and generate a unifmu.exe in the folder target/release.
This method should be followed when building the tool to be deployed for different OSs (windows, macos, linux).
you need to have gone through the steps in the previous instructions for the development build.
have docker installed on your computer.
build the docker image using docker build -t unifmu-docker docker-build
. unifmu-docker
is the name of the container, and docker-build
is the directory where the Dockerfile is (assuming you are running this command from the root of the unifmu repository).
build the unifmu project in docker using docker run --name builder -it -v <location_of_unifmu_repository_on_local_pc>:/workdir unifmu-docker
followed by ./docker-build/build_all.sh
. This should generate three folders in the target
directory on your local computer, one folder for each OS (windows, macos, linux).
When citing the tool, please cite the following paper:
Bibtex:
@inproceedings{Legaard2021,
title = {A Universal Mechanism for Implementing Functional Mock-up Units},
booktitle = {11th {{International}} Conference on Simulation and Modeling Methodologies, Technologies and Applications},
author = {Legaard, Christian M. and Tola, Daniella and Schranz, Thomas and Macedo, Hugo Daniel and Larsen, Peter Gorm},
year = {2021},
pages = {to appear},
address = {{Virtual Event}},
series = {{{SIMULTECH}} 2021}
}