Running the FMI model in Engee¶
Run FMU models in Julia environment to get simulation results and use them in further calculations.
The FMI (Functional Mockup Interface) standard involves packaging the model in an FMU (Functional Mockup Unit) file containing either a set of equations or code modelling the system (presumably supporting various programming languages that can be called in Engee: Python, Java, Fortran, C++, etc. including Julia).
For an example, let's look at a spring and pendulum model built in Dymola. To run it we need the library FMI.jl
and a set of training models, which are collected in the package FMIZoo.jl
.
Let's connect the installed libraries:
We are going to run a simulation of such a model:
The FMI.jl
library allows you to run FMI/FMU models in several ways, and we will show two of them:
- through the command
simulate
- through creating your own simulation loop and the command
fmi2DoStep
.
Create a time vector (set the start tStart
, the end Stop
of the simulation and the time step tStep
):
The simplest scenario for running an FMU model¶
Let's load the model SpringFrictionPendulum1D
from the model package FMIZoo.jl
.
#################### Begin information for FMU ####################
Model name: SpringFrictionPendulum1D
FMI-Version: 2.0
GUID: {2e178ad3-5e9b-48ec-a7b2-baa5669efc0c}
Generation tool: Dymola Version 2022x (64-bit), 2021-10-08
Generation time: 2022-05-19T06:54:12Z
Var. naming conv.: structured
Event indicators: 24
Inputs: 0
Outputs: 0
States: 2
33554432 ["mass.s"]
33554433 ["mass.v", "mass.v_relfric"]
Parameters: 12
16777216 ["fricScale"]
16777217 ["s0"]
16777218 ["v0"]
16777219 ["fixed.s0"]
...
16777223 ["mass.smin"]
16777224 ["mass.v_small"]
16777225 ["mass.L"]
16777226 ["mass.m"]
16777227 ["mass.fexp"]
Supports Co-Simulation: true
Model identifier: SpringFrictionPendulum1D
Get/Set State: true
Serialize State: true
Dir. Derivatives: true
Var. com. steps: true
Input interpol.: true
Max order out. der.: 1
Supports Model-Exchange: true
Model identifier: SpringFrictionPendulum1D
Get/Set State: true
Serialize State: true
Dir. Derivatives: true
##################### End information for FMU #####################
Run the calculation of this model, specifying the start and end of the simulation time and the stored variable mass.s
. Since there is friction in the model, the oscillations occur with decreasing amplitude, and after some time the load comes to rest.
After the calculation is finished, the FMU model must be unloaded from the memory and all time data must be deleted.
Creating your own simulation cycle¶
In a more complex case, such as when you need to link the work of several models, you can organise a computational loop in which the model takes steps in its phase space along some time vector.
Let's load the FMU model:
Out[0]:
Model name: SpringFrictionPendulum1D
Type: 1
The step function expects a specially prepared model (concrete implementation), which we will create using fmi2Instantiate
. In this way many models can be initialised from one FMU file.
Out[0]:
FMU: SpringFrictionPendulum1D
InstanceName: SpringFrictionPendulum1D
Address: Ptr{Nothing} @0x000000001d62f8c0
State: 0
Logging: false
FMU time: -Inf
FMU states: nothing
In the next cell we perform the experiment setup (fmi2SetupExperiment
), where we specify the start and end of the time interval for the simulation, then the model should be put into initialisation mode (fmi2EnterInitializationMode
) and get its initial state after initialisation (fmi2ExitInitializationMode
).
Now we can run the model in the computational loop. The fixed step function fmi2DoStep
tStep
allows the computational steps of this model. If the model has input parameters or accepted data, they can be changed in the loop.
At the end of the calculation we must free the memory and delete the intermediate files.
[OK][CvodeStatistics][SpringFrictionPendulum1D]: Sundials CVode Statistics
Stop time : 8.00 s
Simulation time : 1.42 s
Number of external steps : 80
Number of internal steps : 191
Number of non-linear iterations : 263
Number of non-linear convergence failures: 0
Number of f function evaluations : 291
Number of g function evaluations : 339
Number of Jacobian-evaluations (direct) : 7
Maximum integration order : 5
Suggested tolerance scale factor : 1.0
Grouping used : no
We ran a simple FMU model using a single command, and figured out how to organise a computational loop where we could update the input parameters of the model and make operational decisions based on the output data.
{"id": "9917cf3a-d645-4757-a825-2b12163dd952", "data": [{"showlegend": true, "mode": "lines", "xaxis": "x", "colorbar": {"y": 0.5329861111111112, "title": {"text": ""}, "len": 0.914342738407699, "x": 0.9934383202099737}, "name": "mass.s (33554432)", "yaxis": "y", "legendgroup": "mass.s (33554432)", "line": {"color": "rgba(0, 154, 250, 1.000)", "shape": "linear", "dash": "solid", "width": 1}, "y": [0.5, 0.5216337712911777, 0.585699537535943, 0.6869267320660232, 0.8156462828870731, 0.9593696988008208, 1.1038235061481492, 1.2345035186244255, 1.3383449823708398, 1.4047175326826922, 1.4259767999327344, 1.4058424621115875, 1.350661399642862, 1.264785776387944, 1.1562376966065413, 1.035647893976571, 0.9149490730690827, 0.8061436400267346, 0.7201658780009753, 0.6659782006197259, 0.6501284929655062, 0.6674924701309876, 0.7124002075443914, 0.7814278969372623, 0.868248508368866, 0.9644543123431987, 1.060623211645825, 1.1471304980815111, 1.2151148019617162, 1.2572804294599225, 1.268447227831807, 1.255176111341135, 1.2224415276083764, 1.1725647835518653, 1.1099163018610776, 1.0403857966275998, 0.9708094341895908, 0.9081585141814575, 0.858923759282897, 0.8285539819180577, 0.8209814422737365, 0.8285471613741592, 0.8466594580749613, 0.8742111147818488, 0.908928343023548, 0.9477135388442701, 0.9868159276361104, 1.0222939665425457, 1.050368613939233, 1.0677611528215483, 1.0722001103102978, 1.0722001103002896, 1.0722001102902814, 1.0722001102802734, 1.0722001102702652, 1.0722001102602572, 1.072200110250249, 1.072200110240241, 1.0722001102302328, 1.0722001102202245, 1.0722001102102166, 1.0722001102002083, 1.0722001101902003, 1.0722001101801921, 1.0722001101701841, 1.072200110160176, 1.072200110150168, 1.0722001101401597, 1.0722001101301515, 1.0722001101201435, 1.0722001101101353, 1.0722001101001273, 1.072200110090119, 1.072200110080111, 1.0722001100701029, 1.0722001100600949, 1.0722001100500866, 1.0722001100400784, 1.0722001100300704, 1.0722001100200622, 1.0722001100100542], "type": "scatter", "x": [0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.9, 2, 2.1, 2.2, 2.3, 2.4, 2.5, 2.6, 2.7, 2.8, 2.9, 3, 3.1, 3.2, 3.3, 3.4, 3.5, 3.6, 3.7, 3.8, 3.9, 4, 4.1, 4.2, 4.3, 4.4, 4.5, 4.6, 4.7, 4.8, 4.9, 5, 5.1, 5.2, 5.3, 5.4, 5.5, 5.6, 5.7, 5.8, 5.9, 6, 6.1, 6.2, 6.3, 6.4, 6.5, 6.6, 6.7, 6.8, 6.9, 7, 7.1, 7.2, 7.3, 7.4, 7.5, 7.6, 7.7, 7.8, 7.9, 8], "zaxis": null, "z": null, "metadata": {"shouldEnableSmartZoom": false, "smartZoomParams": {"minCount": 25000, "maxCount": 81, "currentCount": 81}}}], "config": {"showlegend": true, "xaxis": {"showticklabels": true, "gridwidth": 0.5, "tickvals": [0, 2, 4, 6, 8], "range": [-0.2400000000000002, 8.24], "domain": [0.05100612423447069, 0.9934383202099737], "mirror": false, "tickangle": 0, "showline": true, "ticktext": ["0", "2", "4", "6", "8"], "zeroline": false, "tickfont": {"color": "rgba(0, 0, 0, 1)", "family": "sans-serif", "size": 11}, "zerolinecolor": "rgba(0, 0, 0, 1)", "anchor": "y", "visible": true, "ticks": "inside", "tickmode": "array", "linecolor": "rgba(0, 0, 0, 1)", "showgrid": true, "title": {"text": "t [s]", "font": {"color": "rgba(0, 0, 0, 1)", "family": "sans-serif", "size": 15}}, "gridcolor": "rgba(0, 0, 0, 0.1)", "tickcolor": "rgb(0, 0, 0)", "type": "linear"}, "paper_bgcolor": "rgba(255, 255, 255, 1.000)", "annotations": [], "height": 400, "margin": {"l": 0, "b": 20, "r": 0, "t": 20}, "plot_bgcolor": "rgba(255, 255, 255, 1.000)", "yaxis": {"showticklabels": true, "gridwidth": 0.5, "tickvals": [0.6000000000000001, 0.8, 1, 1.2000000000000002, 1.4000000000000001], "range": [0.47222069600201794, 1.4537561039307165], "domain": [0.07581474190726165, 0.9901574803149606], "mirror": false, "tickangle": 0, "showline": true, "ticktext": ["0.6", "0.8", "1.0", "1.2", "1.4"], "zeroline": false, "tickfont": {"color": "rgba(0, 0, 0, 1)", "family": "sans-serif", "size": 11}, "zerolinecolor": "rgba(0, 0, 0, 1)", "anchor": "x", "visible": true, "ticks": "inside", "tickmode": "array", "linecolor": "rgba(0, 0, 0, 1)", "showgrid": true, "title": {"text": "", "font": {"color": "rgba(0, 0, 0, 1)", "family": "sans-serif", "size": 15}}, "gridcolor": "rgba(0, 0, 0, 0.1)", "tickcolor": "rgb(0, 0, 0)", "type": "linear"}, "legend": {"yanchor": "auto", "xanchor": "auto", "bordercolor": "rgba(0, 0, 0, 1)", "bgcolor": "rgba(255, 255, 255, 1.000)", "borderwidth": 1, "tracegroupgap": 0, "y": 1, "font": {"color": "rgba(0, 0, 0, 1)", "family": "sans-serif", "size": 11}, "title": {"font": {"color": "rgba(0, 0, 0, 1)", "family": "sans-serif", "size": 15}, "text": ""}, "traceorder": "normal", "x": 1}, "width": 1519.984375}}
{"id": "9feb99ee-c6e9-4fb1-a036-8848db92d9dc", "data": [{"showlegend": true, "mode": "lines", "xaxis": "x", "colorbar": {"y": 0.513888888888889, "title": {"text": ""}, "len": 0.9525371828521435, "x": 0.9934383202099737}, "name": "y1", "yaxis": "y", "legendgroup": "y1", "line": {"color": "rgba(0, 154, 250, 1.000)", "shape": "linear", "dash": "solid", "width": 1}, "y": [0.521617893337313, 0.5857403574487205, 0.6870806316419173, 0.8159118828873837, 0.9595494033091156, 1.1037259195636675, 1.2341352770315883, 1.3377773736721998, 1.4040715284592924, 1.4254203214015764, 1.4054151572683096, 1.3503197659321926, 1.2645501879051213, 1.156194440048218, 1.0358936843471542, 0.9155375100488806, 0.8071058211712159, 0.7214914488275355, 0.6675969594846171, 0.6518054894676271, 0.6690400876787104, 0.7137172559274544, 0.7824264966353125, 0.8688023224370243, 0.9644703694798775, 1.0599852848225226, 1.1458162549244963, 1.213249292866229, 1.2550887268873214, 1.2662249066932485, 1.253104708416079, 1.2206690257317532, 1.1712331039422006, 1.1091643750292035, 1.040395515011808, 0.9716854549857008, 0.9099221258877447, 0.8614911888975986, 0.831755052825566, 0.8244225626876394, 0.8317801640701884, 0.8493935612864197, 0.8761680200800709, 0.9099001972839909, 0.9475036225308328, 0.9853391533815364, 1.0195777074075896, 1.046563427330959, 1.063139013869552, 1.0672523633960693, 1.0672523633860627, 1.067252363376056, 1.0672523633660493, 1.0672523633560427, 1.067252363346036, 1.0672523633360294, 1.0672523633260227, 1.067252363316016, 1.0672523633060094, 1.0672523632960027, 1.067252363285996, 1.0672523632759894, 1.0672523632659827, 1.067252363255976, 1.0672523632459694, 1.0672523632359627, 1.067252363225956, 1.0672523632159494, 1.0672523632059427, 1.067252363195936, 1.0672523631859294, 1.0672523631759228, 1.067252363165916, 1.0672523631559094, 1.0672523631459028, 1.067252363135896, 1.0672523631258894, 1.0672523631158828, 1.0672523631058761, 1.0672523630958695, 1.0672523630958695], "type": "scatter", "x": [0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.9, 2, 2.1, 2.2, 2.3, 2.4, 2.5, 2.6, 2.7, 2.8, 2.9, 3, 3.1, 3.2, 3.3, 3.4, 3.5, 3.6, 3.7, 3.8, 3.9, 4, 4.1, 4.2, 4.3, 4.4, 4.5, 4.6, 4.7, 4.8, 4.9, 5, 5.1, 5.2, 5.3, 5.4, 5.5, 5.6, 5.7, 5.8, 5.9, 6, 6.1, 6.2, 6.3, 6.4, 6.5, 6.6, 6.7, 6.8, 6.9, 7, 7.1, 7.2, 7.3, 7.4, 7.5, 7.6, 7.7, 7.8, 7.9, 8], "zaxis": null, "z": null, "metadata": {"shouldEnableSmartZoom": false, "smartZoomParams": {"minCount": 25000, "maxCount": 81, "currentCount": 81}}}], "config": {"showlegend": true, "xaxis": {"showticklabels": true, "gridwidth": 0.5, "tickvals": [0, 2, 4, 6, 8], "range": [-0.2400000000000002, 8.24], "domain": [0.05100612423447069, 0.9934383202099737], "mirror": false, "tickangle": 0, "showline": true, "ticktext": ["0", "2", "4", "6", "8"], "zeroline": false, "tickfont": {"color": "rgba(0, 0, 0, 1)", "family": "sans-serif", "size": 11}, "zerolinecolor": "rgba(0, 0, 0, 1)", "anchor": "y", "visible": true, "ticks": "inside", "tickmode": "array", "linecolor": "rgba(0, 0, 0, 1)", "showgrid": true, "title": {"text": "", "font": {"color": "rgba(0, 0, 0, 1)", "family": "sans-serif", "size": 15}}, "gridcolor": "rgba(0, 0, 0, 0.1)", "tickcolor": "rgb(0, 0, 0)", "type": "linear"}, "paper_bgcolor": "rgba(255, 255, 255, 1.000)", "annotations": [], "height": 400, "margin": {"l": 0, "b": 20, "r": 0, "t": 20}, "plot_bgcolor": "rgba(255, 255, 255, 1.000)", "yaxis": {"showticklabels": true, "gridwidth": 0.5, "tickvals": [0.6000000000000001, 0.8, 1, 1.2000000000000002, 1.4000000000000001], "range": [0.4945038204953851, 1.4525343942435043], "domain": [0.03762029746281716, 0.9901574803149606], "mirror": false, "tickangle": 0, "showline": true, "ticktext": ["0.6", "0.8", "1.0", "1.2", "1.4"], "zeroline": false, "tickfont": {"color": "rgba(0, 0, 0, 1)", "family": "sans-serif", "size": 11}, "zerolinecolor": "rgba(0, 0, 0, 1)", "anchor": "x", "visible": true, "ticks": "inside", "tickmode": "array", "linecolor": "rgba(0, 0, 0, 1)", "showgrid": true, "title": {"text": "", "font": {"color": "rgba(0, 0, 0, 1)", "family": "sans-serif", "size": 15}}, "gridcolor": "rgba(0, 0, 0, 0.1)", "tickcolor": "rgb(0, 0, 0)", "type": "linear"}, "legend": {"yanchor": "auto", "xanchor": "auto", "bordercolor": "rgba(0, 0, 0, 1)", "bgcolor": "rgba(255, 255, 255, 1.000)", "borderwidth": 1, "tracegroupgap": 0, "y": 1, "font": {"color": "rgba(0, 0, 0, 1)", "family": "sans-serif", "size": 11}, "title": {"font": {"color": "rgba(0, 0, 0, 1)", "family": "sans-serif", "size": 15}, "text": ""}, "traceorder": "normal", "x": 1}, "width": 1509.984375}}