Lede
The Functional Mock-up Interface (FMI) standard solves a fundamental problem in digital twin engineering: how do you integrate a battery-pack model from MATLAB, a thermal-fluid subsystem from Dymola, a controls algorithm from Simulink, and a structural FEA component from OpenModelica into a single coherent simulation? The answer lies in the FMU—a standardized container format that decouples domain-specific simulation tools from the orchestration layer. But the path to integration bifurcates immediately: do you export each subsystem as a Model Exchange FMU (which outsources solving to a master algorithm) or a Co-Simulation FMU (which packages its own solver)? That choice cascades through your entire digital twin architecture—affecting numerical accuracy, computational performance, and your ability to compose heterogeneous physics at all.
This post decodes FMI 3.0, the Model Exchange vs Co-Simulation architectural divide, and the orchestration engines (like Maestro) that knit multi-vendor FMUs into production-grade digital twins. We’ll examine step-size negotiation, algebraic loops, the role of clocks in event synchronization, and when each mode dominates real-world deployments.
TL;DR
-
FMI defines two simulation modes: Model Exchange (ME) exports raw differential equations; the importing master solver integrates them. Co-Simulation (CS) bundles equations and solver inside the FMU; the master only coordinates communication steps.
-
Choose Model Exchange when: you have simple, non-stiff models; you want tight coupling via shared timestepping; or solver compatibility is assured. Preferred in tightly-integrated single-vendor pipelines (Simulink-to-Simulink).
-
Choose Co-Simulation when: models require specialized solvers (implicit stiff integrators, DAE methods); they originate from different vendors; or you need encapsulation and IP protection. Dominant in multi-vendor digital twins.
-
FMI 3.0 introduces clocks (event synchronization), terminals (semantic signal grouping), and binary variables (opaque data), enabling event-driven orchestration and efficient sensor data interchange.
-
Maestro and similar orchestration engines abstract step-size negotiation, algebraic loop detection, and ZeroMQ-based inter-FMU communication, turning multi-physics composition into a declarative problem.
-
Real-world implication: most industrial digital twins blend both modes—lightweight controls (ME) coupled with physics-heavy models (CS)—orchestrated by a tool that handles state rollback on step rejection and zero-crossing detection across domains.
I. Terminology Primer: Unpacking the FMU Ecosystem
Before diving into the architectural split, let’s ground the language.
Functional Mock-up Interface (FMI)
Think of FMI as an API specification, analogous to USB or HDMI for the simulation world. Just as a USB port defines a contract (voltage, protocol, connector shape) independent of what device you plug in, FMI defines how a simulation model exports its interface: what variables can you read/write, what differential equations does it expose, and how do you advance time? The latest stable version is FMI 3.0 (finalized in 2023; FMI 3.0.2 was released end of 2024 with clarifications and bugfixes).
Functional Mock-up Unit (FMU)
An FMU is the tangible artifact—a .zip archive containing:
– modelDescription.xml: metadata (variable names, types, causality, clocks, terminals)
– binaries/: compiled shared libraries (.dll, .so, .dylib)
– sources/: optional C source code
– documentation/: user guides, technical notes
An FMU is stateful: it maintains internal variables, state derivatives, and discrete event triggers across time steps. It’s not a mere lookup table; it’s an encapsulated simulator.
Model Exchange (ME) vs Co-Simulation (CS)
-
Model Exchange: The FMU exports the right-hand side of a system of differential-algebraic equations (DAEs):
ẋ = f(x, u, t)
y = g(x, u, t)
The master algorithm (importer) calls the FMU to evaluate f and g at each integration point and applies its own numerical solver (Runge-Kutta, BDF, implicit Euler). -
Co-Simulation: The FMU bundles both the equations and a stepping function. The master calls:
doStep(tcurrent, tstep) → returns (xnew, ynew, converged)
The FMU’s internal solver advances its own state over [tcurrent, tcurrent + tstep]; the master doesn’t see (or care about) the solver algorithm or internal substeps.
Analogy: Model Exchange is like a vector graphics file (.svg)—you import the raw equations and render (integrate) them however you want. Co-Simulation is like a raster image (.jpg)—the rendering is fixed; you consume the final output.
Orchestration Engine (Master Algorithm)
The component that coordinates FMU stepping, manages communication steps, detects algebraic loops, handles step rejection, and synchronizes events across a network of FMUs. Examples: Maestro (INTO-CPS), OpenModelica, MATLAB/Simulink (with FMI add-ons), or custom frameworks (e.g., PyFMI in Python).
Clocks (FMI 3.0 Feature)
Event-driven synchronization primitives. Unlike continuous time, clocks tick at specific instants and can be periodic (e.g., “activate every 10 ms”) or triggered by zero-crossings. They enable robust synchronization of discrete controllers, sample-and-hold operations, and asynchronous communication across FMUs.
Terminals (FMI 3.0 Feature)
A semantic grouping mechanism for variables—instead of flat lists of u[0], u[1], …, you can now declare:
Terminal electrical {
Pin_p: Real voltage [V]
Pin_n: Real current [A]
}
This eases graphical modeling, signal validation, and automated connection checking.
Binary Variables (FMI 3.0 Feature)
An opaque data type for non-numeric payloads (sensor arrays, images, serialized protobuf messages). Allows efficient interchange of complex data without type casting or compression overhead.
II. Top-Level Architecture: Model Exchange vs Co-Simulation
Diagram 1: The FMI Execution Paradigm

What this diagram shows:
The left side (Model Exchange) flows from top to bottom: the master algorithm sits at the apex. It queries the FMU for derivatives (f), applies its own integrator (Runge-Kutta or BDF), advances time, and calls the FMU again at the next step. Control is inverted—the master is the active orchestrator.
The right side (Co-Simulation) shows a different rhythm: the FMU’s internal solver is self-contained. The master calls doStep(), the FMU advances its own state (black box), and returns the result. The master is a passive sequencer, coordinating communication at fixed (or negotiated) intervals.
Key distinction: In Model Exchange, the master algorithm “owns” the integration; it can backtrack, reject a step, and retry with smaller time increments. In Co-Simulation, once doStep() returns, that communication step is committed—the FMU has already internally computed and potentially discarded intermediate states.
III. Model Exchange: Flexibility and Tightly-Coupled Domains
When Model Exchange Dominates
Model Exchange is preferred when:
-
Solver compatibility is assured (usually single-vendor pipelines). If all your FMUs come from MATLAB Simulink, Dymola, or OpenModelica, they’re all exporting equations designed for standard solvers. No exotic DAE structure surprises.
-
Models are “simple” (low to moderate stiffness) in the sense that standard explicit or moderate implicit methods (RK45, ode15s) can handle them without excessive computational cost. Electrohydraulic servo systems, mechanical linkages, electrical circuits without exotic damping.
-
You want tight temporal coupling—e.g., you have a control loop that reads sensed state at time t, computes control input u(t), and applies it; the mechanical subsystem must sample this u(t) immediately, not one communication step later. Model Exchange’s synchronous dataflow (single-step integration across all FMUs) guarantees this.
-
Accuracy over wall-clock speed. You’re willing to call the FMU’s derivative function many times per second to achieve tight integration tolerances. Scientific validation, small-scale prototyping.
Trade-Off Analysis: Model Exchange
| Dimension | Advantage | Drawback |
|---|---|---|
| Temporal Coupling | Synchronous—all FMUs integrated at same instant | Requires all FMUs to “handshake” on time step; slower if one FMU is slow |
| Accuracy | Fine-grained control over step size & integrator tolerance | More overhead if many models are stiff (implicit solve required at each step) |
| IP Encapsulation | Equations are exposed (reversible, source-level) | If model is proprietary, CO2 emissions math, or licensed IP, source leakage is a concern |
| Solver Specialization | Master can choose best-fit solver for the combined system | Incompatible or exotic FMU structures (e.g., implicit Euler with state event sensitivity) can break |
| Offline Analysis | Easier to linearize, perform frequency-domain analysis, optimize around nominal trajectory | Limited to what the master solver supports |
Real Example: Electromechanical Servo
A DC motor driving a geared load, with a simple proportional controller:
– Motor dynamics (Model Exchange FMU from Simulink): ω̇ = f(i, ω, Tm)
– Load inertia (Model Exchange FMU from OpenModelica): Tm = Jm(ωm − ωload)
– Controller (Model Exchange FMU from C code): u = Kp(ωref − ω)
All three FMUs export discrete-time algebraic outputs and continuous-time state derivatives. The master integrator (say, ode45) steps all three in lockstep, exchanging outputs→inputs at each integration step. Latency from sensor→control→actuation is one integration step (microseconds if ode45 uses small stepsizes).
IV. Co-Simulation: Encapsulation and Heterogeneous Solvers
When Co-Simulation Dominates
Co-Simulation prevails when:
-
Specialized solvers are non-negotiable. Thermo-fluid models (CFD, multi-phase flow) often ship with their own implicit integrators tuned to handle stiffness and algebraic constraints. Trying to extract just the DAE and feed it to a general-purpose master solver often fails or degrades convergence.
-
Multi-vendor composition. You’re pulling the battery model from Altair HyperWorks, the thermal subsystem from COMSOL, the controls from Simulink, and the structural FEA from ANSYS—each with their own preferred solver, numerical stability thresholds, and state management.
-
IP protection and licensing. The model vendor wants to hide the underlying equations. A Co-Simulation FMU is a black box; you can only call
doStep(). Model Exchange FMUs, especially those with source code, are more transparent. -
Wall-clock performance matters. Co-Simulation allows the FMU to internally microstep (e.g., the thermal model might use 1 ms substeps internally while communicating to the master every 10 ms). The master only pays the cost of coarse synchronization.
-
Decoupled time scales. Some subsystems evolve much faster (or slower) than others. A battery thermal model might be fast; a structural damping model might be slow. Co-Simulation lets each FMU negotiate its own internal step size while communicating at a master-level cadence.
Trade-Off Analysis: Co-Simulation
| Dimension | Advantage | Drawback |
|---|---|---|
| IP Encapsulation | Equations hidden; only I/O visible | Master has no insight into internal solver; harder to debug convergence issues |
| Solver Specialization | Each FMU uses its best-fit solver | Master must negotiate step sizes blind; risk of instability if FMU’s internal accuracy expectations don’t align |
| Decoupled Time Scales | FMU can internally microstep; efficient for stiff systems | Communication step size must be chosen conservatively to avoid stability loss |
| Multi-Vendor Integration | No solver compatibility issues | Master must handle diverse failure modes (step rejection, NaN propagation, silent failures) |
| Wall-Clock Speed | Less overhead per master step (if internal substeps are optimized) | Can be slower if communication cost dominates or if FMU is not well-tuned |
| Backwards Compatibility | FMU can change internal solver without affecting master (transparent to user) | Master cannot rollback and retry if FMU reports convergence failure |
Real Example: Multi-Physics Battery Pack Model
A digital twin of a battery management system (BMS):
– Cell electrochemistry (Co-Simulation FMU): Li-ion cell model from COMSOL, with implicit DAE solver for ion transport, solid-state diffusion. Exports: V(t), T(t), SoH(t) every 1 ms internally, communicates to master at 100 ms.
– Thermal network (Co-Simulation FMU): Distributed thermal network (CFD preprocessed into an RC-ladder model) with stiff exponential terms. Uses BDF internally, outputs Tcell(t), Tcase(t) every 10 ms internally.
– BMS controller (Model Exchange or Co-Simulation): Proportional-integral loop that reads V and T, computes charge/discharge current setpoint, and outputs PWM commands. If Model Exchange, integrated tightly; if Co-Simulation, updates every 10 ms.
The master (Maestro or OpenModelica) doesn’t ask “what’s the ionic current in the SEI layer?”—that’s inside the COMSOL FMU. It only reads:
V, I, T = doStep(t, Δt) // COMSOL FMU
This encapsulation is critical for multi-vendor digital twins.
V. The Communication Step-Size Problem
Diagram 2: Communication Step Negotiation and Algebraic Loops

This diagram illustrates the core orchestration challenge: balancing step-size reduction for stability against the computational cost of frequent FMU re-evaluation and algebraic loop iteration.
What this diagram shows:
A chain of three FMUs (A→B→C) where A’s output is C’s input, and C’s output feeds back to A (forming a loop). The diagram illustrates:
1. Forward pass: at time t, orchestrator calls A.doStep(t, Δt), gets y_A.
2. B consumes A’s output: B.doStep(t, Δt) reads y_A, produces y_B.
3. C consumes B’s output: C.doStep(t, Δt) reads y_B, produces y_C.
4. Loop closure: A must accept y_C as input retroactively for the same time interval [t, t+Δt].
This is the algebraic loop. If no loop exists, the orchestrator can proceed to time t+Δt. If a loop is detected, the orchestrator must either:
– Iterate: call A again with y_C as input, re-compute y_A, and check for convergence.
– Reject the step: declare Δt too large, backtrack to t, and retry with smaller Δt.
– Ignore it: document that the loop is weak (loose coupling) and proceed (risks instability).
Step-Size Selection
The master orchestrator must choose Δt (communication step size) to balance:
- Stability: Too large Δt → information between coupled FMUs lags; feedback loops oscillate or diverge.
- Accuracy: Small Δt → fine temporal resolution but high synchronization overhead and more FMU calls.
- FMU autonomy: Co-Simulation FMUs may report internal divergence and request step rejection; Model Exchange FMUs defer to master’s judgment.
Heuristic (used by Maestro and similar tools):
- Start with Δt = user-specified value (e.g., 1 ms for realtime, 10 ms for slower systems).
- After each step, check: did any FMU report NaN, infinite state, or explicit rejection?
- If yes: halve Δt, backtrack, retry. If convergence iterations (in algebraic loops) exceeded threshold: halve Δt.
- If no: accept step, attempt to increase Δt by 10–20% (to reduce total wall-clock time).
Example: Battery BMS scenario above. If the electrochemistry model diverges when fed a sudden step change in current (from the controller), the orchestrator detects failure, reduces Δt from 100 ms to 50 ms, rolls back, and retries the step from t−100 ms with Δt=50 ms.
VI. FMI 3.0 Enhancements: Clocks, Terminals, and Binary Variables
Diagram 5: FMI 2.0 Limitations vs FMI 3.0 Solutions

FMI 3.0 introduces first-class abstractions for events, semantic signal binding, and opaque data interchange—removing rough edges from multi-vendor composition.
Clocks: Event-Driven Synchronization
FMI 2.0 was purely continuous-time; events (like a relay flip or controller sample) had to be encoded as zero-crossing detection (finding when a variable crossed zero) and state resets. FMI 3.0 introduces clocks—first-class timing primitives.
Clock Types
-
Periodic clock: Activates at regular intervals.
xml
<Clock name="controller_tick" period="0.01" unit="s" description="10 Hz control loop" />
Tells the orchestrator: “I (the FMU) have internal state that updates only every 10 ms; don’t ask me to evaluate between ticks.” -
Triggered/Event-based clock: Activates when a condition is true (e.g., zero-crossing).
xml
<Clock name="fault_detection" interval="0" description="Rising edge of fault signal" />
Why Clocks Matter
In FMI 2.0, a sample-and-hold block had to emit a zero-crossing event (the derivative of an internal ramp crosses zero), which told the master “an event happened.” FMI 3.0 clocks are explicit:
Clock activation → FMU.update() is called synchronously
→ discrete outputs are updated
→ no need to search for zero-crossings numerically
Benefits:
– Efficiency: No false zero-crossing detections; master knows exactly when discrete logic updates.
– Robustness: Finite state machines, polling loops, and interrupt handlers map directly to clocks.
– Multi-rate control: A 100 Hz sensor bus, a 1 kHz control loop, and a 10 Hz logging task can coexist as separate clocks within one FMU.
Real-World Example
An electric vehicle (EV) powertrain digital twin:
– Motor controller FMU (Co-Simulation): PWM frequency = 20 kHz (internal, not visible to master).
– Has a clock: “sample_current_feedback” (period = 1 ms).
– Has a clock: “log_fault_codes” (period = 100 ms).
– Battery thermal FMU (Co-Simulation): thermal timestep = 0.1 s, but exposes a clock “battery_alert” triggered when T > 50°C.
– CAN bus interface FMU (Co-Simulation or Model Exchange): receives CAN messages every variable time; uses triggered clocks to sync decoding.
The orchestrator’s timeline becomes a union of all active clocks: {1 ms, 100 ms, 0.1 s, CAN-triggered}, rather than a single master timebase. This is a major simplification for event-heavy systems like automotive.
Terminals: Semantic Signal Binding
FMI 2.0 forces you to name variables manually and hope you don’t make mistakes:
FMU A output: u_motor_cmd (what is this?)
FMU B input: motor_control_cmd (is this the same thing?)
Master integrator: u_A → input of B (hope they're compatible)
FMI 3.0 Terminals group variables by semantic role:
<Terminal name="electrical_interface">
<Signal name="voltage_V" type="Real" unit="V" />
<Signal name="current_A" type="Real" unit="A" />
</Terminal>
<Terminal name="mechanical_output">
<Signal name="torque_Nm" type="Real" unit="N·m" />
<Signal name="speed_rpm" type="Real" unit="rev/min" />
</Terminal>
Connection Rule: Terminals of the same type can be connected automatically. An orchestrator UI (or graphical modeler) can:
– Show FMUs as boxes with typed terminals
– Disallow invalid connections (e.g., “electrical” terminal → “mechanical” terminal)
– Infer variable bindings and generate the connection code
Real-World Impact: A thermal engineer models a subsystem in Dymola and exports it with a Terminal named “ambient_conditions” (temperature, pressure, humidity). An orchestrator can match this to any other FMU’s “ambient_conditions” terminal, reducing manual wiring and errors.
Binary Variables: Opaque Data Interchange
FMI 2.0 and earlier restricted variables to scalar types (Real, Integer, Boolean, String). Complex data had to be serialized (e.g., flattened into arrays of 1000 Reals).
FMI 3.0 introduces Binary variables—opaque byte arrays:
<Variable name="camera_frame" type="Binary" unit="bytes" />
<Variable name="lidar_scan" type="Binary" unit="bytes" />
<Variable name="sensor_telemetry" type="Binary" unit="bytes" />
Use Cases:
– Sensor data fusion: A camera-frame FMU outputs 2 MB of raw image data; rather than unpacking it into 2,000,000 Real variables, it emits a Binary blob. A vision-processing FMU consumes it directly.
– Message passing: A CAN-bus FMU receives serialized CAN frames as Binary; a higher-level orchestrator passes them to decoding logic without type conversions.
– Efficient streaming: Real-time video, LiDAR point clouds, or IMU bursts can be exchanged without scalar unpacking overhead.
Trade-Off: Loss of automatic unit checking and type safety—it’s the FMU vendor’s responsibility to document the binary format (e.g., “OpenCV BGR image, 1920×1080, uint8”).
VII. Algebraic Loops and Step-Size Limits
Diagram 3: Algebraic Loop Detection and Convergence

What this diagram shows:
Three scenarios:
1. No loop: A → B → C is a purely causal chain. Orchestrator executes one pass: A.doStep() → B.doStep() → C.doStep().
2. Weak loop (lag compensation): C’s output feeds back to A, but with a one-step delay (common in digital controllers). Orchestrator detects loop, iterates A.doStep() and C.doStep() until convergence, or iterates once and accepts small error.
3. Algebraic (strong) loop: A’s input depends on C’s output within the same communication interval. Orchestrator must iterate or declare the system ill-posed.
Iteration Strategy (Gauss-Seidel)
For an algebraic loop over FMUs {F1, F2, F3} with loop f1_out → f2_inp, f2_out → f3_inp, f3_out → f1_inp:
for iter in 1..maxIter:
y1_old = y1
F1.doStep(t, Δt) with input=y3_prev → y1_new
F2.doStep(t, Δt) with input=y1_new → y2_new
F3.doStep(t, Δt) with input=y2_new → y3_new
if ||[y1_new, y2_new, y3_new] - [y1_old, y2_old, y3_old]||_∞ < tol:
converged = True; break
else:
y1_prev, y2_prev, y3_prev = y1_new, y2_new, y3_new
if not converged:
reject step, halve Δt, backtrack
When Loops Break Stability
Algebraic loops are destabilizing if loop gain > 1. Example:
– F1 computes: y1 = 2 * u1 (proportional gain 2)
– F3 feeds back: y3 = 0.6 * y1 (partial feedback)
– Loop gain = 2 * 0.6 = 1.2 > 1
Gauss-Seidel iteration will diverge: y1 → ∞. The orchestrator detects this (after maxIter = 10 iterations), rejects the step, halves Δt, and retries. If Δt is reduced enough, the numerical coupling weakens, and iteration converges.
Practical heuristic: Loop gain dominated by communication step size. Smaller Δt → weaker coupling → convergence. Modern orchestrators (Maestro) automatically adjust Δt based on loop iteration history.
VIII. Orchestration in Practice: Maestro
What Maestro Does
Maestro is an open-source co-simulation orchestration engine developed by the INTO-CPS Association. It:
- Parses FMU descriptions (modelDescription.xml) and extracts variable metadata, causality, clocks.
- Schedules FMU stepping based on a user-provided co-simulation script (Maestro Base Language, MaBL).
- Detects and iterates algebraic loops.
- Handles step rejection (backtracking if an FMU reports convergence failure).
- Communicates via ZeroMQ for distributed simulation (FMUs can run on different machines).
- Manages wall-clock time for realtime or faster-than-realtime execution.
Example MaBL Script
import "battery.fmu"
import "bms_controller.fmu"
import "thermal_model.fmu"
scenario BatteryTwin {
battery_fmu.current := bms_controller.setpoint
bms_controller.voltage := battery_fmu.voltage
bms_controller.temperature := thermal_model.cell_temp
thermal_model.dissipated_power := battery_fmu.power
simulate(
start_time = 0,
end_time = 3600, // 1 hour
step_size = 0.01 // 10 ms communication interval
)
}
This declarative script:
– Defines four variables (current, voltage, temperature, power) as connection points.
– Sets the communication interval to 10 ms.
– Maestro auto-detects the algebraic loop (thermal_model → battery_fmu → bms_controller → battery_fmu) and sets up Gauss-Seidel iteration.
Step-Size Negotiation (Maestro2)
Maestro2 (2024 release) supports adaptive step-size control:
- Try step with current Δt.
- If any FMU rejects or iteration > threshold: halve Δt, backtrack, retry.
- If success and iterations < 0.3 * maxIter (low coupling): try to increase Δt by 1.1x next step.
- Track statistics and log for post-simulation analysis.
Real-world effect: A co-simulation that naively uses fixed 10 ms steps might spend 40% of wall-clock time in failed step rejections. Maestro’s adaptive scheme reduces this to ~5% overhead.
IX. Diagram 4: Complete Digital Twin Architecture

What this diagram shows:
A complete digital twin loop for an industrial system (e.g., a pumped thermal storage system):
– Left side (Reality): Physical system with sensors feeding real-time data.
– Middle (Digital Representation): Multiple FMUs (pump model, thermal reservoir, controller, fault detector) orchestrated by Maestro.
– Right side (Feedback): Model predictions (state estimates, predictions, diagnostics) used to:
– Update the real system (closed-loop control).
– Alert on anomalies (sensor fusion with model-based expectations).
– Optimize operating parameters (model predictive control).
Key flows:
1. Sensor data → Maestro (e.g., flow rate, temperature, pressure).
2. Maestro advances all FMUs in lockstep (or coordinated, for Multi-rate systems).
3. FMU outputs → control logic → physical system actuators.
4. Closed-loop: sensors → FMUs → controller → actuators → sensors.
This architecture is typical for:
– Condition monitoring (predicting component wear before failure).
– Optimization (finding setpoints that minimize energy consumption).
– Fault diagnosis (comparing model predictions to real sensors to isolate faults).
X. Edge Cases and Failure Modes
Case 1: Numerical Divergence in Coupled Systems
Symptom: Simulation runs for 10 seconds, then produces NaN in a state variable.
Root causes:
1. Stiff coupling with large Δt: An algebraic loop with high gain, stepped over a large interval, causes iteration to diverge.
2. Model singularity: An FMU computes division by zero (e.g., fluid density → zero due to extrapolation).
3. Implicit solver timeout: An FMU’s internal solver (e.g., Newton-Raphson for DAE) fails to converge within maxIter.
Diagnosis:
– Reduce Δt (e.g., from 10 ms to 1 ms). If divergence disappears, loop coupling is the culprit.
– Check FMU models for singularities (review equations, test bounds).
– Enable debug logging in the orchestrator (Maestro with --verbose flag) to see which FMU first reported NaN.
Fix:
– Reformulate the algebraic loop as a weak coupling (add a one-step delay buffer).
– Add bounds checking inside the FMU (clamp density, current, etc.).
– Increase the FMU’s internal solver tolerance slightly (trade accuracy for stability).
Case 2: Mismatched Unit Systems
Symptom: One FMU outputs power in Watts; another consumes “power” but expects units of kW (off by 1000x). Simulation runs but predicts absurd temperatures.
Prevention (FMI 3.0):
– Use Terminals with explicit unit attributes:
xml
<Terminal name="thermal_interface">
<Signal name="power" type="Real" unit="W" />
</Terminal>
– Orchestrator can warn: “Power output [W] → power input [kW] unit mismatch!”
Without Terminals (FMI 2.0):
– Manual checking of modelDescription.xml and FMU documentation.
– Add a unit-conversion FMU in the connection path (multiply by 1/1000).
Case 3: Zero-Crossing Chattering
Symptom: A relay or hysteresis block oscillates around a threshold, generating thousands of events per second.
Cause:
– Event detection (zero-crossing detection) is numeric; floating-point rounding can cause a variable to creep back and forth across zero.
In FMI 2.0:
– Orchestrator detects many consecutive zero-crossings and enters an infinite loop (or timeout).
In FMI 3.0:
– Use clocks with hysteresis:
xml
<Clock name="relay_clock" interval="0" hysteresis="1e-6" />
Clock activates only when the crossing signal crosses zero and stays on the opposite side for hysteresis duration.
Case 4: Distributed Communication Latency
Scenario: FMUs run on different machines, connected via Ethernet. ZeroMQ serializes and transmits messages; network jitter adds 1–10 ms latency per communication step.
Effect:
– If communication latency > Δt, orchestrator can’t keep up; simulation lags wall-clock time.
– Feedback loops introduce additional phase lag.
Mitigation:
– Use larger Δt (if accuracy permits) to amortize network overhead.
– Co-locate FMUs on the same machine or high-speed interconnect (InfiniBand) for latency-sensitive systems.
– Buffer sensor data on edge nodes and sync to orchestrator asynchronously.
XI. When to Use Each Mode: Decision Matrix
Diagram 6: Decision Framework for Choosing Model Exchange vs Co-Simulation

A practical guide showing when each mode dominates, with emphasis on the hybrid approach used in production digital twins.
| Scenario | Model Exchange | Co-Simulation | Rationale |
|---|---|---|---|
| Single vendor (all MATLAB/Simulink) | Strongly Preferred | Possible but unnecessary | All models compatible with MATLAB ODE solver |
| Multi-vendor (Simulink + OpenModelica + COMSOL) | Only if simple | Strongly Preferred | Solver incompatibility; need encapsulation |
| Tightly-coupled control loop (e.g., inverter–motor–sensor feedback) | Preferred | Possible (high communication cost) | Requires synchronous sampling; ME achieves this naturally |
| Stiff physics (implicit DAE) | Not recommended | Strongly Preferred | ME requires master to solve stiff system; inefficient |
| Thermo-fluid (CFD-derived model) | Not possible | Required | CFD tools export Co-Simulation FMUs; equations too complex for ME |
| Intellectual property protection (black-box model) | Weak (source leakage risk) | Strongly Preferred | CS FMU is an opaque binary |
| Real-time simulation on embedded hardware | If lightweight | Preferred | Co-Sim allows internal microsteps; less overhead for master |
| Offline analysis (frequency response, linearization) | Strongly Preferred | Harder (requires step inversion) | ME exports symbolic DAE; easy to linearize around setpoint |
| Realtime hardware-in-the-loop (HIL) with multi-physics | Hybrid mix | Both | Often: control loop (ME), physics (Co-Sim) |
XII. Real-World Implication: The Hybrid Approach
Most production digital twins use both modes:
Example: Electric Bus Powertrain
-
Battery pack (Co-Simulation FMU from COMSOL/Simulink): electrochemistry + thermal coupling
– Stiff DAEs (ion transport, Nernst equation).
– Proprietary IP.
– Reason: Co-Simulation FMU. -
Motor & inverter (Model Exchange FMU, generated from Simulink)
– Standard 3-phase AC equations, non-stiff.
– No IP concerns (generic model).
– Reason: Model Exchange FMU (tight coupling with controller). -
Driver + route planner controller (Co-Simulation FMU, C++ custom code)
– Discrete event logic (gear shifts, regen braking logic).
– Time-varying setpoints (GPS-based route preview).
– Reason: Co-Simulation FMU (events, internal state machine). -
Vehicle dynamics (Model Exchange FMU, OpenModelica)
– Standard multibody mechanics.
– Needs synchronous coupling with motor (wheel slip detection).
– Reason: Model Exchange FMU.
Orchestrator’s job: Route battery data → motor → dynamics → controller feedback → battery input, with step-size adaptation and algebraic loop detection. This hybrid composition is standard in automotive, aerospace, and industrial controls.
XIII. FMI 3.0 Improvements in Practice
Clock-Enabled Event Handling
Before (FMI 2.0): A BMS cell balancing logic (sample-and-hold every 100 ms) had to be encoded as:
internal_timer += Δt
if internal_timer >= 0.1:
sample_voltage = V
internal_timer = 0
This works but is error-prone (timer overflow, floating-point accumulated error).
After (FMI 3.0):
<Clock name="balancing_tick" period="0.1" unit="s" />
<Output name="sampled_voltage" causality="output" clock="balancing_tick" />
Orchestrator knows: sample_voltage updates only when balancing_tick fires; no need to poll or compute delays.
Terminal-Based Graphical Composition
A control engineer opens a graphical IDE, sees two boxes (Battery FMU, BMS FMU), drags Battery.thermal_interface → BMS.thermal_sensor_interface, and the IDE warns:
Unit mismatch: Battery exports [K] (Kelvin), BMS expects [°C] (Celsius).
Auto-convert? [Yes] [No]
In FMI 2.0, this would require hand-inspection of 200-page FMU documentation.
Binary for Sensor Fusion
A computer vision FMU exports:
camera_frame (Binary, 2 MB/frame at 30 FPS)
Instead of flattening to 6 million Real variables, Maestro passes the blob directly to a downstream image-processing FMU. Wall-clock overhead: near-zero.
XIV. Further Reading and Resources
The definitive references:
- FMI Standard Official Repository — FMI 3.0 specification (PDF, HTML).
- FMI FAQ — Quick answers to common questions.
- INTO-CPS Maestro Documentation — Maestro2 manual, MaBL reference, tutorials.
- Claytex: FMI Basics — Clear comparison of ME vs CS with examples.
- Modelon: FMI Library — Open-source FMI implementation in C.
- PyFMI — Python FMI loader and simulator (great for scripting orchestration).
- Modelica Conference Proceedings — Annual presentations on FMI advances, case studies, and orchestration techniques.
- INTO-CPS Association — Academic consortium advancing FMI, digital twins, and co-simulation tooling.
Closing Remarks
The FMI standard democratizes digital twin engineering by abstracting away solver and vendor differences. But the choice between Model Exchange and Co-Simulation is not merely technical—it shapes your entire simulation pipeline, from how you test models to how you deploy them in production.
Model Exchange is the architect’s choice: fine-grained control, tight coupling, offline analysis. Co-Simulation is the systems integrator’s choice: heterogeneous tools, intellectual property hiding, real-world robustness.
FMI 3.0’s clocks, terminals, and binary variables remove friction from multi-vendor composition. But they don’t eliminate the fundamental trade-off: encapsulation vs. control. Recognize this trade-off in your digital twin’s architecture, choose the mode(s) that match your physics and constraints, and let the orchestration engine handle the rest.
The future of industrial simulation is not a single monolithic tool but an ecosystem of specialized FMUs, each solving its domain optimally, stitched together by robust orchestration. FMI is the connective tissue.
Revision and Attribution
- Date written: 2026-04-17
- FMI versions covered: FMI 2.0, FMI 3.0 (current; FMI 3.0.2 as of 2024)
- Tools referenced: Maestro (INTO-CPS), OpenModelica, MATLAB Simulink, Dymola, COMSOL, ANSYS
- Sources: FMI Standard, Maestro Documentation, Claytex FMI Basics, Modelon FMI Resources, academic literature on co-simulation orchestration.
