FMI

The Functional Mock-up Interface (FMI) is a standard that defines a container and an interface to exchange dynamic models using a combination of XML files, binaries and C code zipped into a single file.

For further detail, please look at the official website: https://fmi-standard.org/

The goal of the standard is to allow the co-simulation of models from different tools. This notebook presents how to package a CoSApp model as a Functional Mock-up Unit (FMU).

System without iterative

Case description

Creating the elements

First, you need to export your CoSApp system code into a separate file.

[1]:
from exprampode_fmu import ExpRampOde

# Trick to display nicely the class code
from IPython.display import Markdown
import inspect
Markdown(f"```py\n{inspect.getsource(ExpRampOde)}```")
[1]:
class ExpRampOde(System):
    """
    System representing function f(t) = a * (1 - exp(-t / tau)),
    through ODE: tau * f' + f = a

    f is then apply on an input signal x to produce y.
    """
    def setup(self):
        self.add_inward('a', 1.0)
        self.add_inward('tau', 1.0)
        self.add_inward('x', 1.0)
        self.add_outward('y', 1.0)

        self.add_outward('df_dt', 0.0)
        self.add_transient('f', der='df_dt', max_time_step='tau / 5')

    def compute(self):
        self.df_dt = (self.a - self.f) / self.tau
        self.y = self.x * self.f

Export to FMU

Exporting a CoSApp system is done using function cosapp.tools.to_fmu.

When this function is called, actual system parameters will be used as default values in the FMU.

[2]:
import os
import tempfile
import shutil

from cosapp.tools import to_fmu

syst = ExpRampOde('fmu1')

# Customize parameters
syst.a = 5

if not os.path.exists('fmus'):
    os.mkdir('fmus')

# Export the FMU in a temporary directory
with tempfile.TemporaryDirectory() as tmp_dir:
    fmu_file = to_fmu(syst, dest=tmp_dir, locals=['f', 'df_dt'])
    shutil.copy2(fmu_file, 'fmus')

Use the FMU

[3]:
import pyfmi

fmu = pyfmi.load_fmu('fmus/ExpRampOde.fmu')
results = fmu.simulate(final_time=10.)
Simulation interval    : 0.0 - 10.0 seconds.
Elapsed simulation time: 0.1522242160026508 seconds.
[4]:
# Plot results
import plotly.graph_objs as go

layout = go.Layout(
    height = 450,
    xaxis = dict(title="time"),
    yaxis = dict(title = "f")
)

go.Figure(
    data=go.Scatter(
        x = results['time'],
        y = results['f'],
    ),
    layout=layout)