Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fmi3 refactor #155

Closed
wants to merge 61 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
61 commits
Select commit Hold shift + click to select a range
2c95b77
Jupyter nbconvert synch - modified, paired .ipynb files
JoKircher Jun 1, 2022
2ce429c
Merge branch 'ThummeTo:main' into main
JoKircher Jun 7, 2022
f974e57
Fmi3 beta (#114)
ThummeTo Jun 7, 2022
07cddfd
move additional functions to the end
Jun 7, 2022
8e97b31
refactor FMI3_additional.jl
Jun 7, 2022
b047c62
update readme
ThummeTo Jun 7, 2022
f321189
readme updated
ThummeTo Jun 7, 2022
f6906b1
...
ThummeTo Jun 7, 2022
8676273
Update README.md
ThummeTo Jun 7, 2022
06360e8
update docstrings for wrapper functions
Jun 7, 2022
4cee313
optimized simulation calling order
ThummeTo Jun 8, 2022
3a87347
Merge branch 'ThummeTo:main' into main
JoKircher Jun 18, 2022
b701ff0
Jupyter nbconvert synch - modified, paired .ipynb files
JoKircher Jun 18, 2022
84adb72
Merge branch 'main' into fmi3-refactor
Jun 18, 2022
69c3146
added FMI3_JLD2.jl
Jun 18, 2022
0e9a7f9
WIP: fmi3 refactor
Jun 18, 2022
1b2ac26
update tests for FMI3
Jun 18, 2022
4156285
WIP: added more fmi3 calls
Jun 20, 2022
cfb93fb
Merge branch 'main' into fmi3-merge
ThummeTo Jun 22, 2022
d85abcb
add help function for fmiLoad
Jun 23, 2022
184ddff
WIP: updated all fmi functions
Jun 23, 2022
18a223d
Merge branch 'ThummeTo:main' into main
JoKircher Jun 24, 2022
f0a4f9e
comment tests for fmi3 out for now
Jun 24, 2022
1d3d1ad
Merge branch 'main' into fmi3-refactor
Jun 24, 2022
d4e8212
WIP: Fmi3 refactor (#126)
JoKircher Jun 27, 2022
9618700
WIP: merge
Jun 28, 2022
808a2d6
Merge branch 'main' of https://github.com/ThummeTo/FMI.jl into Thumme…
Jun 28, 2022
46fb5eb
Merge branch 'ThummeTo-main' into main
Jun 28, 2022
2966c12
Merge branch 'main' into fmi3-refactor
Jun 28, 2022
f1bc7b3
fixed fmiLoad
Jun 28, 2022
f9bc8f1
removed files
ThummeTo Jun 28, 2022
5b9112a
Merge branch 'fmi3-merge' of https://github.com/ThummeTo/FMI.jl into …
ThummeTo Jun 28, 2022
385cfb2
Merge branch 'main' into fmi3-merge
ThummeTo Jun 28, 2022
62533ed
Merge branch 'fmi3-merge' into fmi3-refactor
ThummeTo Jun 28, 2022
2682ab6
tests for fmi2 passing (#134)
JoKircher Jun 28, 2022
8bb51dc
deleted files
ThummeTo Jun 28, 2022
67bd7fa
WIP: started tests
Jun 28, 2022
eb70724
Merge branch 'fmi3-refactor' of https://github.com/JoKircher/FMI.jl i…
Jun 28, 2022
778f4cd
WIP: change sim and comments
Jun 29, 2022
60b3ca0
WIP: working on tests
Jun 30, 2022
438c500
Merge branch 'main' into fmi3-refactor
Jun 30, 2022
140e18b
WIP: finished state.jl test
Jul 6, 2022
4cc5e91
WIP: finished CSsim
Jul 6, 2022
b5ae466
WIP: working on ME simulation
Jul 7, 2022
77d71f0
WIP: still no ME simulation
Jul 12, 2022
988df9b
Merge branch 'fmi3-merge' of https://github.com/ThummeTo/FMI.jl into …
Jul 12, 2022
68e2e57
Merge branch 'ThummeTo-fmi3-merge' into fmi3-refactor
Jul 12, 2022
553bcbc
WIP: fix ME simulation
Sep 30, 2022
4ffe2c9
Merge branch 'main' into fmi3-refactor
Sep 30, 2022
d124d17
Merge remote-tracking branch 'upstream/main' into fmi3-refactor
Oct 4, 2022
d97033c
added status tag for next meeting
Oct 10, 2022
0af0aca
FMI3additional up to fmi2 structure
Oct 10, 2022
f254edf
fmi3_comp_wraps.jl up to fmi2 standard
Oct 11, 2022
9204c24
delete replicate functions
Oct 11, 2022
f8641af
fmi3Plot.jl up to fmi2standard
Oct 11, 2022
0c430bc
WIP commit to update branch
Oct 17, 2022
d7ef913
Merge remote-tracking branch 'upstream/main' into fmi3-refactor
Oct 17, 2022
6163950
build simulation loops after fmi2 structure
Nov 6, 2022
cabee8e
delete unnecessary prints
Nov 8, 2022
1cd414d
Merge remote-tracking branch 'upstream/main' into fmi3-refactor
Nov 10, 2022
d49a7dd
Update runtests.jl
Nov 14, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
289 changes: 289 additions & 0 deletions docs/src/examples/manipulation.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,289 @@
# Manipulate a function
Tutorial by Johannes Stoljar, Tobias Thummerer

## License
Copyright (c) 2021 Tobias Thummerer, Lars Mikelsons, Josef Kircher, Johannes Stoljar

Licensed under the MIT license. See [LICENSE](https://github.com/thummeto/FMI.jl/blob/main/LICENSE) file in the project root for details.

## Motivation
This Julia Package *FMI.jl* is motivated by the use of simulation models in Julia. Here the FMI specification is implemented. FMI (*Functional Mock-up Interface*) is a free standard ([fmi-standard.org](http://fmi-standard.org/)) 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. The user can thus use simulation models in the form of an FMU (*Functional Mock-up Units*). Besides loading the FMU, the user can also set values for parameters and states and simulate the FMU both as co-simulation and model exchange simulation.

## Introduction to the example
This example shows how to overwrite a library function with an own function. For this the FMU model is simulated first without changes. Then the function `fmi2GetReal()` is overwritten and simulated again. Both simulations are displayed in a graph to show the change caused by overwriting the function. The model used is a one-dimensional spring pendulum with friction. The object-orientated structure of the *SpringFrictionPendulum1D* can be seen in the following graphic.

![svg](https://github.com/thummeto/FMI.jl/blob/main/docs/src/examples/pics/SpringFrictionPendulum1D.svg?raw=true)


## Target group
The example is primarily intended for users who work in the field of simulations. The example wants to show how simple it is to use FMUs in Julia.


## Other formats
Besides, this [Jupyter Notebook](https://github.com/thummeto/FMI.jl/blob/main/example/manipulation.ipynb) there is also a [Julia file](https://github.com/thummeto/FMI.jl/blob/main/example/manipulation.jl) with the same name, which contains only the code cells and for the documentation there is a [Markdown file](https://github.com/thummeto/FMI.jl/blob/main/docs/src/examples/manipulation.md) corresponding to the notebook.


## Getting started

### Installation prerequisites
| | Description | Command | Alternative |
|:----|:----------------------------------|:--------------------------|:-----------------------------------------------|
| 1. | Enter Package Manager via | ] | |
| 2. | Install FMI via | add FMI | add " https://github.com/ThummeTo/FMI.jl " |
| 3. | Install FMIZoo via | add FMIZoo | add " https://github.com/ThummeTo/FMIZoo.jl " |
| 4. | Install FMICore via | add FMICore | add " https://github.com/ThummeTo/FMICore.jl " |
| 5. | Install Plots via | add Plots | |

## Code section

To run the example, the previously installed packages must be included.


```julia
# imports
using FMI
using FMIZoo
using FMICore
using Plots
```

### Simulation setup

Next, the start time and end time of the simulation are set.


```julia
tStart = 0.0
tStop = 8.0
```




8.0



### Import FMU

In the next lines of code the FMU model from *FMIZoo.jl* is loaded and the information about the FMU is shown.


```julia
# we use an FMU from the FMIZoo.jl
pathToFMU = get_model_filename("SpringFrictionPendulum1D", "Dymola", "2022x")

myFMU = fmiLoad(pathToFMU)

fmiInfo(myFMU)
```

┌ Info: fmi2Unzip(...): Successfully unzipped 29 files at `/tmp/fmijl_HiWCsS/SpringFrictionPendulum1D`.
└ @ FMIImport /home/runner/.julia/packages/FMIImport/ns5Pd/src/FMI2_ext.jl:75
┌ Info: fmi2Load(...): FMU resources location is `file:////tmp/fmijl_HiWCsS/SpringFrictionPendulum1D/resources`
└ @ FMIImport /home/runner/.julia/packages/FMIImport/ns5Pd/src/FMI2_ext.jl:190
┌ Info: fmi2Load(...): FMU supports both CS and ME, using CS as default if nothing specified.
└ @ FMIImport /home/runner/.julia/packages/FMIImport/ns5Pd/src/FMI2_ext.jl:193


#################### Begin information for FMU ####################
Model name: SpringFrictionPendulum1D
FMI-Version: 2.0
GUID: {df491d8d-0598-4495-913e-5b025e54d7f2}
Generation tool: Dymola Version 2022x (64-bit), 2021-10-08
Generation time: 2022-03-03T15:09:18Z
Var. naming conv.: structured
Event indicators: 24
Inputs: 0
Outputs: 0
States: 2
33554432 ["mass.s"]
33554433 ["mass.v", "mass.v_relfric"]
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 #####################


### Simulate FMU

In the next steps the recorded value is defined. The recorded value is the position of the mass. In the function `fmiSimulateME()` the FMU is simulated in model-exchange mode (ME) with an adaptive step size. In addition, the start and end time and the recorded variables are specified.


```julia
vrs = ["mass.s"]

simData = fmiSimulateME(myFMU, tStart, tStop; recordValues=vrs)
```

Simulating ME-FMU ... 100%|██████████████████████████████| Time: 0:00:10





Model name:
SpringFrictionPendulum1D
Success:
true
States [110]:
0.0 [0.5, 0.0]
2.3529411764719727e-11 [0.5, 1.0e-10]
1.0000023529411766e-5 [0.5000000002125017, 4.250030186348503e-5]
0.00011000002352941177 [0.5000000257134062, 0.0004675245102952289]
0.0011100000235294118 [0.5000026191281834, 0.004719970360497647]
0.011110000023529413 [0.5002631686645611, 0.047449647283752144]
0.03982466736770743 [0.5034050123596227, 0.17168075110950387]
0.09972054285078226 [0.5215006197560228, 0.43204954153497455]
0.16481836271111422 [0.5585747156842935, 0.703758265932321]
...
8.0 [1.0668213438183276, -1.0000099359121942e-10]
Values [110]:
0.0 (0.5,)
2.3529411764719727e-11 (0.5,)
1.0000023529411766e-5 (0.5000000002125017,)
0.00011000002352941177 (0.5000000257134062,)
0.0011100000235294118 (0.5000026191281834,)
0.011110000023529413 (0.5002631686645611,)
0.03982466736770743 (0.5034050123596227,)
0.09972054285078226 (0.5215006197560228,)
0.16481836271111422 (0.5585747156842935,)
...
8.0 (1.0668213438183276,)
Events [6]:
State-Event #11 @ 0.0s
State-Event #11 @ 0.9939s
State-Event #19 @ 1.9881s
State-Event #11 @ 2.9829s
State-Event #19 @ 3.9787s
State-Event #11 @ 4.9768s




### Plotting FMU

After the simulation is finished, the result of the FMU for the model-exchange mode can be plotted. In the plot for the FMU it can be seen that the oscillation continues to decrease due to the effect of the friction. If you simulate long enough, the oscillation comes to a standstill in a certain time.


```julia
fig = fmiPlot(simData, states=false)
```





![svg](manipulation_files/manipulation_10_0.svg)




### Override Function

After overwriting a function, the previous one is no longer accessible. The original function `fmi2GetReal()` is cached by storing the address of the pointer. The addresses of the pointers are kept in the FMU and are thus accessible.


```julia
# save, where the original `fmi2GetReal` function was stored, so we can access it in our new function
originalGetReal = myFMU.cGetReal
```




Ptr{Nothing} @0x00007f52e9530faf



To overwrite the function `fmi2GetReal!()`, the function header of the new custom function must be identical to the previous one. The function header looks like `fmi2GetReal!(cfunc::Ptr{Nothing}, c::fmi2Component, vr::Union{Array{fmi2ValueReference}, Ptr{fmi2ValueReference}}, nvr::Csize_t, value::Union{Array{fmi2Real}, Ptr{fmi2Real}})::fmi2Status`. The information how the FMI2 function are structured can be seen from [FMICore.jl](https://github.com/ThummeTo/FMICore.jl/blob/main/src/FMI2_c.jl#L718) or the FMI2.0.3-specification.

In the new implementation the original function is called by the previously stored pointer. Next there is a special handling if `value` is a pointer to an array. In this case the pointer is treated as an array, so that the entries are accessible. Otherwise, each value in `value` is multiplied by two. Finally, the original state of the original function is output.


```julia
function myGetReal!(c::fmi2Component, vr::Union{Array{fmi2ValueReference}, Ptr{fmi2ValueReference}},
nvr::Csize_t, value::Union{Array{fmi2Real}, Ptr{fmi2Real}})
# first, we do what the original function does
status = fmi2GetReal!(originalGetReal, c, vr, nvr, value)

# if we have a pointer to an array, we must interprete it as array to access elements
if isa(value, Ptr{fmi2Real})
value = unsafe_wrap(Array{fmi2Real}, value, nvr, own=false)
end

# now, we multiply every value by two (just for fun!)
for i in 1:nvr
value[i] *= 2.0
end

# return the original status
return status
end
```




myGetReal! (generic function with 1 method)



In the next command the original function is overwritten with the new defined function, for which the command `fmiSetFctGetReal()` is called.


```julia
# no we overwrite the original function
fmiSetFctGetReal(myFMU, myGetReal!)
```




Ptr{Nothing} @0x00007f533e325fc0



### Simulate and Plot FMU with modified function

As before, the identical command is called here for simulation. This is also a model exchange simulation. Immediately afterwards, the results are added to the previous graph as a dashed line.


```julia
simData = fmiSimulateME(myFMU, tStart, tStop; recordValues=vrs)
fmiPlot!(fig, simData; states=false, style=:dash)
```





![svg](manipulation_files/manipulation_18_0.svg)




As expected by overwriting the function, all values are doubled.

### Unload FMU

After plotting the data, the FMU is unloaded and all unpacked data on disc is removed.


```julia
fmiUnload(myFMU)
```

### Summary

In this tutorial it is shown how an existing function of the library can be replaced by an own implementation. Through this possibility, there are almost no limits for the user, whereby the user can customize the function to his liking.
Loading