FMIExchange.jl

Dev Docs Build Docs Test

What is FMIExchange.jl?

FMIExchange.jl provides ways to easily load Model Exchange Functional Mock-up Units (FMUs) and simulate them using the DifferentialEquations.jl package. This package cannot run simulations on its own, but merely provides tools to construct ODEFunctions and callbacks from FMUs. The user retains full control over the simulation with the powerful and familiar interface of DifferentialEquations.jl.

FMIExchange.jl allows to simulate multiple FMUs at the same time and even combine them with native Julia ODEs; this is the main use-case of this package. FMIExchange.jl includes some functionality to automate the process of combining multiple models into one simulation: automatic addressing, human-readable address map generation and functions for connecting model inputs and outputs.

What is FMIExchange.jl not?

FMIExchange.jl is not a package for simulating or manipulating FMUs: it doesn't include a simulator but merely provides convenience functions to allow simulating FMUs with the DifferentialEquations.jl package. FMIImport.jl and FMICore.jl provide functionality for importing and manipulating FMUs. FMI.jl has built-in FMU simulation functionality, but this is limited to simulating a single FMU at a time and it is impossible to combine native ODEs with FMUs.

FMIExchange.jl is not a modelling package. While it has some basic simulation composition functionality it lacks some crucial features such as algebraic loop resolution. Some packages that support this are ModelingToolkit.jl and Causal.jl. Pull requests to make FMIExchange.jl compatible with these packages are welcome!

Usage

Below example walks you through simulating an FMU using FMIExchange.jl and DifferentialEquations.jl. The example FMU is a bouncing ball in a 2D space.

Import packages. Define FMU file location, and simulation start and stop times.

using FMIExchange
using DifferentialEquations

bbloc = joinpath("deps", "fmu", "BouncingBall2D.fmu") # fmu file location
bbstart = 0.0 # simulation start
bbstop = 60.0 # simulation stop

Define the FMU inputs, outputs, states. This step ensures that correct references to the model variables are made in the simulation. Optionally, the model parameters of the FMU can be changed.

bbins = String[] # FMU inputs (this FMU has none)
bbouts = String[] # FMU outputs (this FMU has none)
bbstates = ["dx", "dy", "x", "y"] # FMU states
bbparamters = Dict("eps"=>1e-2) # FMU parameters (optional)

Use the CachedFMU2 function to load the FMU (the name CachedFMU2 is to avoid naming conflicts with related packages). We then wrap it in a CachedModel struct which will automatically preallocate caches for faster calls to the FMU.

fmu = CachedFMU2(bbloc, bbstart, bbstop, bbins, bbouts, bbstates, bbparameters)
model = CachedModel(fmu)

FMU events are handled through callbacks. FMIExchange.jl can automatically generate the callbacks to handle these events using the get_callbacks function.

# For the bouncing ball, an event occurs whenever the ball hits a wall
cbs = get_callbacks(model, bbstart, bbstop)

Finally use the CachedModel and the callbacks as you would typically simulate a native Julia ODE.

# Solve using DifferentialEquations.jl
sol = solve(ODEProblem{true}(model, Float64[1.0, 0.0, 0.5, 1.0], (bbstart, bbstop), Float64[]), 
	    callback=CallbackSet(cbs...), saveat=bbstart:0.01:bbstop)

Installation

FMIExchange.jl can be installed through the Julia package manager as below

using Pkg
Pkg.add("https://github.com/Electa-Git/FMIExchange.jl")

Currently, FMIExchange.jl is not yet added to the general registry, but plans are to change that.

Generating Test FMUs

To run the tests you need to generate the FMUs. This requires OpenModelica to be installed and the compiler omc to be available in your PATH variable. The Modelica Standard Library, Buildings, IDEAS and MoPED libraries should be available in your Modelica path.

You can find your Modelica path by creating a mos script with the following contents

getModelicaPath()

and running it with omc. On Linux, the result is ~/.openmodelica/libraries.

Running Tests Without Generating FMUs

It is possible to download the compiled FMUs from the Github workflow runs of this repository if the artifacts are still available on Github. First extract all FMUs to deps/fmu/, then run tests as normal. It is possible that these FMUs do not work on your architecture / OS, in which case you will have to generate the FMUs manually.

License

The package is available under the BSD 3-clause license here. FMIExchange.jl was developed at KU Leuven - Electa by Lucas Bex.

A portion of this package reuses and modifies code from FMI.jl. The details, including a link to the copyright notice of FMI.jl, can be found in src/callbacks_fmijl.jl. The modifications include the following:

  • Compatibility with the interface of FMIExchange.jl
  • Rigorous caching for better performance