Launching the FMI model in Engee
We run FMU models in the Julia environment to get the simulation results and use them in further calculations.
Task description
The FMI (Functional Mockup Interface) standard implies packing the model into an FMU (Functional Mockup Unit) file containing either a set of equations or code modeling the system (presumably, various programming languages that can be called in Engee are supported: Python, Java, Fortran, C++, etc. including Julia).
For example, consider a model of a spring and a pendulum assembled in Dymola. To run it, we need a library FMI.jl and a set of training models that are assembled in the package FMIZoo.jl.
Pkg.add( ["FMI", "FMIZoo"] )
Connecting the installed libraries:
using FMI
using FMIZoo
We are going to conduct a simulation of such a model.:
Library FMI.jl It allows you to run FMI/FMU models in several ways, and we will show two of them.:
- through the command
simulate - by creating your own simulation loop and command
fmi2DoStep.
Let's create a time vector (set the beginning tStart, ending Stop simulations and time step tStep):
tStart = 0.0
tStep = 0.1
tStop = 8.0
tSave = tStart:tStep:tStop
The simplest scenario for launching an FMU model
Loading the model SpringFrictionPendulum1D from the model package FMIZoo.jl.
fmu = loadFMU( "SpringFrictionPendulum1D", "Dymola", "2022x" )
info(fmu)
Let's run the calculation of this model, specifying the beginning and end of the simulation time and the variable to be saved. mass.s. Since there is friction in the model, fluctuations occur with decreasing amplitude, and after a while the load comes to rest.
simData = simulate(fmu, (tStart, tStop); recordValues=["mass.s"], saveat=tSave)
plot( simData )
After completing the calculation, you need to unload the FMU model from memory and delete all temporary data.
unloadFMU(fmu)
Creating your own simulation cycle
In a more complex case, for example, when you need to link the work of several models at once, you can organize a calculation cycle in which the model will perform steps in its phase space along a certain time vector.
Download the FMU model:
fmu = loadFMU("SpringFrictionPendulum1D", "Dymola", "2022x")
The step function expects a specially prepared model (a specific implementation), which we will create using fmi2Instantiate. In this way, many models can be initialized from a single FMU file at once.
instanceFMU = fmi2Instantiate!(fmu)
In the next cell, we set up the experiment (fmi2SetupExperiment), where we specify the beginning and end of the time interval for simulation, then the model must be switched to initialization mode (fmi2EnterInitializationMode) and get its initial state after initialization (fmi2ExitInitializationMode).
fmi2SetupExperiment(instanceFMU, tStart, tStop)
fmi2EnterInitializationMode(instanceFMU) # установить исходное состояние
fmi2ExitInitializationMode(instanceFMU) # прочитать исходное состояние
Now we can run the model in the calculation cycle. Function fmi2DoStep with a fixed pitch tStep allows you to perform the calculated steps of this model. If the model has input parameters or received data, they can be changed in a loop.
values = []
for t in tSave
# выставить входные параметры модели, если требуется
# ...
fmi2DoStep(instanceFMU, tStep)
# сохранить выходы модели
value = fmi2GetReal(instanceFMU, "mass.s")
push!(values, value)
end
plot(tSave, values)
At the end of the calculation, we must free up the memory and delete the intermediate files.
fmi2Terminate(instanceFMU)
fmi2FreeInstance!(instanceFMU)
unloadFMU(fmu)
Conclusion
We launched a simple FMU model with a single command, and also figured out how to organize a calculation cycle where we could update the input parameters of the model and make operational decisions based on the output data.