FMU Containers ?¶
A FMU Container is classical FMU which embeds other FMU's:

From API point of view, an FMUContainer can be seen as * an FMU which implement the FMI API (either version 2.0 or 3.0) * an fmi-importer which can load FMUs
FMU Manipulation Toolbox is shipped with fmucontainer command which makes easy to nest FMU's into FMU.
How to create an FMU Container ?¶
The fmucontainer command creates a FMU, named Container, from a description file. This file contains multiple parameters:
- time_step: a FMU Container acts as a fixed step time "solver" for its embedded FMU's.
- optional features
- multi-threading: each embedded FMU will use its own thread to parallelize
doStep()operation. - profiling: performance indicators can be calculated by the container to help to identify the bottlenecks among the embedded FMU's.
- routing table
- Input ports: the list of the Container's inputs. Each input is linked to one input (or more) of one of the embedded FMU's.
- Output ports: the list of the container's outputs. Each output is linked to one output of one of the embedded FMU's.
- Connexions between embedded FMU's
- Explicitly ignored ports (only port with
causality = "output"can be ignored) - Automation of routing table
- auto_input exposes automatically the (unconnected) ports of embedded FMU's with
causality = "input" - auto_output expose automatically the (unconnected) ports of embedded FMU's with
causality = "output" - auto_local expose automatically the ports of embedded FMU's with
causality = "local" - auto_parameter expose automatically the ports of embedded FMU's with
causality = "parameter" - auto_link links automatically ports of embedded FMU's which are left previously unconnected and have the same names and types
Some of these parameters can be defined by Command Line Interface or by the input files.
Several formats are supported as description files: - a CSV format: define only the routing table. Other options should be defined as command line options. - a JSON file: all parameters can be defined in the file. Command line can define default values if the parameter is not present in JSON file. - a SSP file. See ssp-standard.org. define only the routing table. Other options are defined with command line.
Command Line Options¶
The fmucontainer command supports the following options:
| Option | Default | Description |
|---|---|---|
-container filename[:step_size] | (required) | Description file for the container (.csv, .json, or .ssp). The optional :step_size suffix sets the internal time step (in seconds) when using .jsonor .ssp. Can be specified multiple times to build several containers. |
-fmu-directory path | . | Directory containing the source FMUs and used to generate the containers. |
-fmi {2\|3} | 2 | FMI version for the container interface. Only 2 or 3 is supported. |
-mt | off | Enable multi-threaded mode: each embedded FMU runs in its own thread. |
-sequential | off | Use sequential mode to schedule embedded FMUs. |
-profile | off | Enable profiling mode to monitor doStep() performance of each embedded FMU. |
-vr | off | Add a TS_MULTIPLIER input port to the container, allowing dynamic control of the step size. |
-datalog | off | Log input, output, and local variables of the container into a CSV file. |
-dump-json | off | Dump a JSON description file for each container. |
-no-auto-input | auto | Disable automatic exposure of unconnected input ports from embedded FMUs. |
-no-auto-output | auto | Disable automatic exposure of unconnected output ports from embedded FMUs. |
-no-auto-link | auto | Disable automatic linking of ports with matching names and types. |
-auto-local | off | Expose local variables of the embedded FMUs. |
-auto-parameter | off | Expose parameters of the embedded FMUs. |
-debug | off | Enable verbose logging during the build process. |
Example:
This command builds an FMI-3.0 container from assembly.csv with a 1 ms time step, multi-threading enabled, and profiling active. The source FMUs are located in the ./my_fmus directory.

CSV Input file¶
This is the historic input file format. It has been superseded by the Json input file format.
Example: * Two FMU's to be assembled: bb_position.fmu and bb_velocity.fmu * Container should expose position1 from bb_position.fmu as position * Container has no input * there's two links between embedded FMU's
the container.csv file content:
rule;from_fmu;from_port;to_fmu;to_port
FMU;bb_position.fmu;;;
FMU;bb_velocity.fmu;;;
OUTPUT;bb_position.fmu;position1;;position
LINK;bb_position.fmu;is_ground;bb_velocity.fmu;reset
LINK;bb_velocity.fmu;velocity;bb_position.fmu;velocity
OUTPUT;bb_velocity.fmu;velocity;;
Asserting the FMU's and the CSV files are located in current working directory, the following command will build the container:
Then container.fmu should be available. Note: the optional :0.1 suffix means the timestep should be 0.1 second.
Json Input file¶

SSP Input file¶
This feature is still alpha.
The following command
will 1. extact FMU's from the SSP file 2. build a container accordingly to the SSP
Note: the optional :0.1 suffix means the timestep should be 0.1 second.
Python API¶
FMU Containers can also be created programmatically using the Python API. This is the most flexible approach for automation and CI/CD pipelines.
Using a Description File¶
The Assembly class can load an existing description file (CSV, JSON, or SSP) and build the container:
from pathlib import Path
from fmu_manipulation_toolbox.assembly import Assembly
# Load a CSV description and build the container
assembly = Assembly("bouncing.json",
fmu_directory=Path("containers/bouncing_ball"),
mt=True)
assembly.make_fmu()
You can also export the assembly to a different format:
# Export the assembly as JSON (useful for review or version control)
assembly.write_json("bouncing.json")
# Export back to CSV
assembly.write_csv("bouncing-export.csv")
Building a Container Programmatically¶
For full control without any description file, use the FMUContainer class directly. The following example builds a bouncing ball container from scratch:
from pathlib import Path
from fmu_manipulation_toolbox.container import FMUContainer
fmu_directory = Path("containers/bouncing_ball")
# Create the container
container = FMUContainer("bouncing", fmu_directory, fmi_version=2)
# Load the embedded FMUs
container.get_fmu("bb_position.fmu")
container.get_fmu("bb_velocity.fmu")
# Expose outputs: (from_fmu, from_port, exposed_name)
container.add_output("bb_position.fmu", "position1", "position")
container.add_output("bb_velocity.fmu", "velocity", "velocity")
# Create links between embedded FMUs
container.add_link("bb_position.fmu", "is_ground", "bb_velocity.fmu", "reset")
container.add_link("bb_velocity.fmu", "velocity", "bb_position.fmu", "velocity")
# Automatically expose remaining unconnected inputs/outputs
container.add_implicit_rule(auto_input=True, auto_output=True, auto_link=True)
# Build the FMU container
container.make_fmu("bouncing.fmu", step_size=0.1, mt=True)
The resulting bouncing.fmu is generated in the fmu_directory.
FMUContainer Reference¶
The FMUContainer constructor takes the following parameters:
| Parameter | Default | Description |
|---|---|---|
identifier | (required) | used as modelIdentifier in modelDescription.xml |
fmu_directory | (required) | Directory containing the source FMUs |
fmi_version | 2 | FMI version for the container interface (2 or 3) |
The following methods define the container topology:
| Method | Description |
|---|---|
get_fmu(fmu_filename) | Load an embedded FMU from fmu_directory |
add_input(exposed_name, fmu_name, port_name) | Expose a port of an embedded FMU as a container input |
add_output(fmu_name, port_name, exposed_name) | Expose a port of an embedded FMU as a container output |
add_link(from_fmu, from_port, to_fmu, to_port) | Connect an output to an input between embedded FMUs |
drop_port(fmu_name, port_name) | Explicitly ignore an output port |
add_start_value(fmu_name, port_name, value) | Set a start value for a port of an embedded FMU |
add_implicit_rule(auto_input, auto_output, auto_link, auto_parameter, auto_local) | Automatically wire unconnected ports |
make_fmu(filename, step_size, mt, profiling, sequential, ts_multiplier, datalog) | Build the container FMU |
The make_fmu method accepts the following parameters:
| Parameter | Default | Description |
|---|---|---|
fmu_filename | (required) | Output filename for the container |
step_size | None | Internal time step in seconds (deduced from embedded FMUs if not set) |
mt | False | Enable multi-threading |
sequential | False | Use sequential scheduling |
profiling | False | Enable profiling |
ts_multiplier | False | Add TS_MULTIPLIER input for dynamic step size control |
datalog | False | Log variables into a CSV file |
FMI Support¶
FMI-3.0 current support is limited. Feel free to create a ticket to let us know your needs.
FMI-2.0 Containers¶
Without any additional option, fmucontainer will produce FMI-2.0 containers. These containers may embed - FMU 2.0 in cosimulation mode without any particular limitation. - FMU 3.0 in cosimulation mode with limitations: - Variables with FMI-3.0 specific types can be used for routing but cannot be exposed (as input, output, parameter or local). Note: boolean is redefined in FMI-3.0. So cannot be exposed from an FMU-3.0. - Early Return feature is not supported - Arrays are not supported
FMI-3.0 Containers¶
To produce FMI-3.0 compliant containers, use option -fmi 3 in fmucontainer command line. Those containers may embed
- FMU 2.0 in cosimulation mode with limitations:
-
booleanvariables can be used for routing but cannot be exposed (as input, output, parameter or local). -
FMU 3.0 in cosimulation mode with limitations:
- Early Return feature is not supported
- Arrays are not supported
Muti-Threading¶
If enabled through MT flag, each FMU will be run using its own thread which 1. fetch its inputs from container buffer which is shared with all FMUs. 2. process DoStep()
Synchronization uses a mutex.
Profiling¶
If enabled through profiling flag, each call to DoStep of each FMU is monitored. The elapsed time is compared with currentCommunicationPoint and a RT ratio is computed. A ratio greater than 1.0 means this particular FMU is faster than RT.