unifmu
unifmu copied to clipboard
A universal mechanism for implementing Functional Mock-up Units (FMUs) in various languages
UniFMU - Universal Functional Mock-Up Units
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.
Getting the tool
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.
How to use the command line interface?
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
Language specific documentation
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.
Supported Features
FMI2
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 |
FMI3 (in progress)
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 and deployment
Building during development
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 foldertarget/release
.
Building for deployment
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, anddocker-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
. This should generate three folders in thetarget
directory on your local computer, one folder for each OS (windows, macos, linux).
Citing the tool
When citing the tool, please cite the following paper:
- Legaard, C. M., Tola, D., Schranz, T., Macedo, H. D., & Larsen, P. G. (2021). A Universal Mechanism for Implementing Functional Mock-up Units. In G. Wagner, F. Werner, T. I. Γren, & F. D. Rango (Eds.), Proceedings of the 11th International Conference on Simulation and Modeling Methodologies, Technologies and Applications, SIMULTECH 2021, Online Streaming, July 7-9, 2021 (pp. 121-129). SCITEPRESS Digital Library. https://doi.org/10.5220/0010577601210129
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}
}