Djinious
Co-simulationEngineering methods

FMI co-simulation

Importing and co-simulating vendor models through the FMI standard — load a Dymola FMU and run it, cross-validate it against a native model, wrap your own controller around the black box through the FMI interface, couple it into a larger system, and quantify the co-simulation error.

DjiniousLab
A native PID controller tracking a setpoint on an imported vendor FMU plant through the FMI interface
closed-loop tracking error on a vendor FMU
2.9e-4 mclosed-loop tracking error on a vendor FMU
CS-vs-ME agreement (RMSE)
1.3e-3 mCS-vs-ME agreement (RMSE)
FMU-vs-native fidelity (RMSE)
4.7e-3 mFMU-vs-native fidelity (RMSE)
co-sim error cut by macro-step refinement
7.6×co-sim error cut by macro-step refinement
design notebooks
10design notebooks
requirements PASS
5 / 5requirements PASS

Run — and control — a model you didn't build.

No team models everything in one tool. The FMI standard exists so a model built in Dymola, Simulink or anywhere else can be packaged as an FMU and run somewhere else entirely. This program is the import side of that promise: load a vendor FMU into DjiniousLab's Julia worker, co-simulate it, cross-validate it against a native re-implementation, and — the part that matters — wrap your own controller around the black box and close the loop through the FMI interface. Interoperability isn't a checkbox; it's controlling someone else's model as if it were yours.

Drop in a vendor FMU and it just runs.

An FMU is a self-contained, compiled model behind a standard C interface. The first notebook loads a Dymola-exported reference FMU into the Julia worker and co-simulates it — states out, phase orbit closed, no source code, no re-derivation. That's the baseline interoperability claim: a model authored in another tool, running here, unchanged.

DjiniousLab
A vendor FMU's states co-simulated after being imported into the Julia worker
The import moment: a Dymola-exported FMU loaded and co-simulated in the worker — its states come straight out of the compiled model through the FMI interface. You're running a model you didn't write and can't see inside.

Co-simulation or model-exchange — and they agree.

FMI offers two modes. In co-simulation the FMU carries its own solver and you call doStep; in model-exchange your solver integrates the FMU's derivatives. The same FMU run both ways overlays to a 1.3×10⁻³ m RMSE — the choice is about who owns the solver, not about getting different answers. That equivalence is what lets you mix an FMU into a larger Julia-solved system with confidence.

DjiniousLab
The same FMU run in co-simulation and model-exchange modes, overlaying almost exactly
Co-simulation (FMU's own solver) vs model-exchange (the worker's solver integrating the FMU): the same FMU, two integration modes, overlapping to 1.3×10⁻³ m. The mode is a solver-ownership decision, not a fidelity one.
DjiniousLab
An imported FMU and a native Julia re-implementation of the same physics overlaying exactly
Cross-validation: a native Julia ODE built from the FMU's own parameters laid over the imported FMU — they track to 4.7×10⁻³ m. (Deliberately mismatch a parameter and they diverge, the negative control.) Interop fidelity you can measure, not assume.

Close a loop around the black box.

The strongest interoperability claim isn't running a vendor model — it's controlling one. The hero notebook makes the imported FMU the plant and wraps a native Julia PID around it through a manual co-simulation loop: read the FMU's output, compute the control, set the FMU's input, step. The controller never sees inside the FMU; it only talks to it through the FMI interface — and drives it to a setpoint with 2.9×10⁻⁴ m tracking error. That's a controller and a vendor plant from two different worlds, meeting at the standard.

DjiniousLab
A native PID driving an imported vendor FMU to a setpoint, with the control force shown
The hero: a native Julia PID controlling a black-box vendor FMU through the FMI interface (top — output tracking the setpoint; bottom — the control force it computes). The plant is someone else's compiled model; the controller is yours; the FMI interface is the contract between them.

Co-simulation has its own error budget.

Coupling models at discrete communication points introduces an error all its own: between steps, each model sees its inputs held constant, so a too-large macro step lags and distorts. The program quantifies it — halving the macro step roughly halves the error (first-order convergence), a 7.6× reduction across the sweep. Knowing that error is first-order in the step size is what lets you trade accuracy against speed deliberately instead of by accident.

DjiniousLab
A coarse macro step lagging the reference while a fine macro step tracks it — first-order co-sim convergence
The co-simulation error budget: a coarse macro step (red) lags and distorts because inputs are held constant between communication points, while a fine step (blue) tracks the reference. The error is first-order in the macro step — halve the step, halve the error.

Every number re-derived at sign-off.

The V&V notebook re-imports the FMU and re-derives each requirement from scratch, printing a PASS/FAIL board.

Result

  • Import & co-sim a vendor FMU: 101 samples
  • CS vs ME agreement: 1.3e-3 m RMSE
  • FMU vs native fidelity: 4.7e-3 m RMSE
  • Closed-loop tracking error: 2.9e-4 m
  • Co-sim error vs macro step: 7.6× reduction

Requirement

  • Import & co-sim a vendor FMU: R-01
  • CS vs ME agreement: R-02
  • FMU vs native fidelity: R-03
  • Closed-loop tracking error: R-04
  • Co-sim error vs macro step: R-05

The import side, on reference FMUs.

The deliverable is ten notebooks and the dossier — the models arrive as compiled FMUs behind the FMI C interface, not as acausal DjiniousLab components, so there's no custom block or canvas. The FMUs are Dymola-exported references rather than arbitrary third-party models; the co-simulation is single-rate with constant-input extrapolation between communication points and no algebraic-loop solver across coupled FMUs. And this is the import/co-simulate story specifically — FMU export is a separate Rust path in the platform. What the program proves is the interoperability core: load, co-simulate both ways, cross-validate, control, couple, and quantify the co-sim error — every number re-runnable, the strongest of them a native controller closing a loop around a vendor model it can't see inside.