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

FMI 3.0 Import

Running Functional Mock-up Units as FastSim blocks, in both interface types.

What is an FMU?

FMI is an open standard for exchanging simulation models between tools. An FMU is a ZIP archive holding compiled model code, a modelDescription.xml declaring its variables and capabilities, and optional resources.

FastSim implements FMI 3.0 natively in Rust — it loads the shared library, parses the description and drives the fmi3* entry points itself. There is no Python FMI library in the loop, so an FMU is as cheap to step as any other block.

ModelExchangeFMU and CoSimulationFMU wrap an FMU as an ordinary block: its outputs become block outputs, its inputs become block inputs, and it connects like anything else.

Model Exchange or Co-Simulation?

The two interface types split the work differently:

Model Exchange Co-Simulation
who integrates FastSim's solver the FMU's own solver
the FMU provides MATHINLINE0ENDMATH a step of size MATHINLINE1ENDMATH
step size chosen by FastSim, adaptive if the solver is the communication grid
events located by FastSim via the FMU's event indicators handled inside, reported back

Model Exchange puts the FMU under one consistent integrator with the rest of the model, which is what you want for a stiff or tightly coupled system. Co-Simulation is the choice when the FMU's internal solver is part of the model's identity.

Python
Loading...

The Reference FMUs

These examples use the Reference-FMUs published by the Modelica Association — the same archives every FMI tool is tested against. FastSim keeps them as test fixtures, so the paths below point into the repository.

Python
Loading...

Model Exchange: Dahlquist

The Dahlquist test equation is the standard scalar stiffness probe:

MATHDISPLAY0ENDMATH

The FMU supplies MATHINLINE1ENDMATH; FastSim's solver does the integrating.

Python
Loading...

Verification

The analytic solution is MATHINLINE0ENDMATH (the FMU's default MATHINLINE1ENDMATH). Nothing about this check involves the FMU or FastSim — it is the exact answer.

Python
Loading...

Overriding Start Values

Variables declared in modelDescription.xml can be set before instantiation. Here the decay rate MATHINLINE0ENDMATH goes from 1 to 3, so the solution must become MATHINLINE1ENDMATH.

Python
Loading...

An unknown name is rejected rather than silently ignored:

Python
Loading...

Events: the Bouncing Ball

The BouncingBall FMU exposes an event indicator for the floor contact. In Model Exchange, FastSim locates the crossing, lets the FMU resolve the event, and carries on — the same machinery its own ZeroCrossing events use.

Outputs are height MATHINLINE0ENDMATH and velocity MATHINLINE1ENDMATH.

Python
Loading...
Python
Loading...

Verification

Two properties the physics fixes, independent of either implementation:

  1. the ball never passes through the floor,
  2. each bounce scales the energy by MATHINLINE0ENDMATH, so successive apex heights satisfy MATHINLINE1ENDMATH with the same MATHINLINE2ENDMATH every time.

Apex heights are the robust quantity here: the samples immediately around a bounce straddle a discontinuity, so a velocity ratio taken from them depends on where the grid happens to fall. The apex does not.

Python
Loading...

Co-Simulation

The same FMU, now integrating itself. FastSim advances it on a communication grid and reads the outputs back; the FMU reports events it handled internally.

Python
Loading...

The two agree on the trajectory but not bit-for-bit, and they should not: Model Exchange puts the ball under FastSim's adaptive solver with the event located to tolerance, while Co-Simulation hands each step to the FMU's own integrator on a fixed grid. Before the first bounce both are integrating the same smooth free fall, and what separates them there is the reference FMU's own forward-Euler step: over a fall of duration MATHINLINE0ENDMATH that lags the exact parabola by $ frac{1}{2}g,\Delta t,t$, which is the number below. After the first bounce the bounce instants drift by a fraction of a communication step, and near a bounce a small shift in time is a large difference in height — so the whole-run figure is dominated by that, not by any disagreement about the physics.

Python
Loading...