This example requires external dependencies and cannot be run in the browser.

FMI 3.0 Export

Writing a model out as a Functional Mock-up Unit, for both interface types, and packaging a subsystem as a reusable component.

What gets written

FMI is an open standard for moving simulation models between tools. to_fmu writes an FMI 3.0 source FMU: the model is lowered to C, wrapped in the FMI C layer, and zipped with a generated modelDescription.xml and buildDescription.xml.

Source FMU means the archive carries C rather than binaries, so the importing tool compiles it for its own platform.

One archive offers both interfaces:

  • Model Exchange — the FMU hands out MATHINLINE0ENDMATH and the importer integrates it.
  • Co-Simulation — the FMU integrates itself, with the solver baked in at export time, and the importer just advances it.

Simulation.to_fmu() exports a whole model. A Subsystem has to_fmu too, which is how a component with input and output ports is packaged on its own.

The Model

A damped harmonic oscillator, which has a closed-form solution to check against:

MATHDISPLAY0ENDMATH

Python
Loading...

System Parameters

Python
Loading...

Block Diagram

Python
Loading...

Simulation

The reference run, before exporting anything.

Python
Loading...

Export

The keyword arguments become the default experiment in modelDescription.xml — what an importer uses when the user does not say otherwise.

Python
Loading...

What the Importer Sees

modelDescription.xml declares the interfaces on offer and the variables. Both <ModelExchange> and <CoSimulation> are there.

Python
Loading...

Running It Back

FMPy is an independent FMI implementation, so it is a good way to check that the FMU really is one. It builds the C for this platform first, since a source FMU ships none.

Python
Loading...

Model Exchange

FMPy integrates the FMU with its own solver — CVode here, which FastSim never runs.

Python
Loading...

Co-Simulation

The same archive, the other way round: the FMU steps itself and FMPy only advances the clock.

Python
Loading...

Results

Python
Loading...

Verification

Against the closed-form solution, which involves neither the FMU nor FastSim.

Python
Loading...

Exporting a Subsystem

A whole simulation is a closed model — no inputs, nothing to wire it to. A Subsystem is the other case: a component with ports, which becomes an FMU with real input and output variables that someone else can drop into their model.

The component here is a driven spring-mass-damper: force in, its state out.

MATHDISPLAY0ENDMATH

Python
Loading...

The exported component has an input variable — this FMU is not self-contained, it is meant to be connected. Its outputs are the plant's, position first.

Python
Loading...

Verification

Driven at its undamped natural frequency MATHINLINE1ENDMATH, the steady-state amplitude of such a component is known:

MATHDISPLAY0ENDMATH

Python
Loading...
Python
Loading...

Published FMUs

The two FMUs from this page are published in the repository under fmus/, each with a reference solution (_ref.csv / _ref.opt / _in.csv) so other tools can import and compare. scripts/export_reference_fmus.py regenerates them, and scripts/check_exported_fmus.py replays this page's comparison end to end.