Skip to content

FMU Containers ?

A FMU Container is classical FMU which embeds other FMU's:

FMU Container

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:

fmucontainer -container assembly.csv:0.001 -fmu-directory ./my_fmus -fmi 3 -mt -profile

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.

Routing

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:

fmucontainer -container container.csv:0.1

Then container.fmu should be available. Note: the optional :0.1 suffix means the timestep should be 0.1 second.

Json Input file

Routing

fmucontainer -container container.json

SSP Input file

This feature is still alpha.

The following command

fmucontainer -container my_file.ssp:0.1

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:
  • boolean variables 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.