From 2f5ddd90c32e61f4eb58becac64577870910d1cf Mon Sep 17 00:00:00 2001 From: Simon Exner <43469235+0815Creeper@users.noreply.github.com> Date: Wed, 18 Sep 2024 11:05:27 +0200 Subject: [PATCH] updates to match FMIFlux.jl structure --- .github/workflows/Example.yml | 14 +- .github/workflows/Formatter.yml | 2 + .github/workflows/TestLTS.yml | 2 +- .gitignore | 6 +- docs/.gitignore | 3 +- docs/make.jl | 2 +- docs/src/examples/simulate.md | 307 ++++++++++++++++++++++++++++++++ test/.gitignore | 3 + 8 files changed, 327 insertions(+), 12 deletions(-) create mode 100644 docs/src/examples/simulate.md diff --git a/.github/workflows/Example.yml b/.github/workflows/Example.yml index 3af8f803..de8b9790 100644 --- a/.github/workflows/Example.yml +++ b/.github/workflows/Example.yml @@ -39,8 +39,8 @@ jobs: - name: "Install packages" run: pip install jupyter nbconvert - - - name: "Execute and synchronize all files" + + - name: "Execute notebook" env: FILE: examples/jupyter-src/${{ matrix.file-name }}.ipynb run: | @@ -55,7 +55,7 @@ jobs: if: success() && github.event_name != 'pull_request' && github.ref_name == 'main' uses: nick-fields/retry@v3 env: - CI_COMMIT_MESSAGE: example-${{ matrix.file-name }}-${{ matrix.os }}-${{ matrix.julia-version }}-${{ matrix.julia-arch }}-${{ matrix.experimental }}[${{ github.ref_name }}] + CI_COMMIT_MESSAGE: jupyter-example-${{ matrix.file-name }}-${{ matrix.os }}-${{ matrix.julia-version }}-${{ matrix.julia-arch }}-${{ matrix.experimental }}[${{ github.ref_name }}] CI_COMMIT_AUTHOR: github-actions[bot] EXAMPLES_PATH: examples/jupyter-src # Fetch all and clear the stash list. Include all files from the examples folder to the stash and switch the branch. @@ -95,7 +95,7 @@ jobs: uses: julia-actions/setup-julia@v2 with: version: '1.10' - + - run: julia -e 'using Pkg; Pkg.add("PlutoSliderServer");' - run: julia -e 'using PlutoSliderServer; PlutoSliderServer.export_directory("examples/pluto-src")' @@ -103,7 +103,7 @@ jobs: if: success() && github.event_name != 'pull_request' && github.ref_name == 'main' uses: nick-fields/retry@v3 env: - CI_COMMIT_MESSAGE: examples-pluto[${{ github.ref_name }}] + CI_COMMIT_MESSAGE: pluto-examples[${{ github.ref_name }}] CI_COMMIT_AUTHOR: github-actions[bot] EXAMPLES_PATH: examples/pluto-src # Fetch all and clear the stash list. Include all files from the examples folder to the stash and switch the branch. @@ -131,8 +131,8 @@ jobs: git reset git add ${{ env.EXAMPLES_PATH }} git commit -m "${{ env.CI_COMMIT_MESSAGE }}" - git push origin examples || (git reset --soft HEAD~1 && (exit 1)) - + git push origin examples || (git reset --soft HEAD~1 && (exit 1)) + call-docu: needs: [jupyter, pluto] if: github.event_name != 'pull_request' && github.ref_name == 'main' diff --git a/.github/workflows/Formatter.yml b/.github/workflows/Formatter.yml index 0155d9b6..14659356 100644 --- a/.github/workflows/Formatter.yml +++ b/.github/workflows/Formatter.yml @@ -3,6 +3,8 @@ on: pull_request: # this argument is not required if you don't use the `suggestion-label` input types: [ opened, reopened, synchronize, labeled, unlabeled ] + workflow_dispatch: + jobs: code-style: runs-on: ubuntu-latest diff --git a/.github/workflows/TestLTS.yml b/.github/workflows/TestLTS.yml index 6ad1877b..ffd9d004 100644 --- a/.github/workflows/TestLTS.yml +++ b/.github/workflows/TestLTS.yml @@ -54,4 +54,4 @@ jobs: # Run the tests - name: "Run tests" - uses: julia-actions/julia-runtest@v1 \ No newline at end of file + uses: julia-actions/julia-runtest@v1 diff --git a/.gitignore b/.gitignore index 809f569c..59e681db 100644 --- a/.gitignore +++ b/.gitignore @@ -24,6 +24,8 @@ docs/site/ Manifest.toml LocalPreferences.toml -# Custom +# custom tmp/ -.vscode/ \ No newline at end of file +build/ +.vscode/ +examples/jupyter-src/.ipynb_checkpoints/ diff --git a/docs/.gitignore b/docs/.gitignore index d1638636..0496399d 100644 --- a/docs/.gitignore +++ b/docs/.gitignore @@ -1 +1,2 @@ -build/ \ No newline at end of file +build/ +Manifest.toml diff --git a/docs/make.jl b/docs/make.jl index 7329e5e6..f5550034 100644 --- a/docs/make.jl +++ b/docs/make.jl @@ -60,7 +60,7 @@ for (x, md) in deepcopy(example_pages) string( "::warning title=SVG-Warning::example-page \"", md, - "\" has svg-xml text in it. Most likely, linking of support-files generated by jupyter is broken\"\r\n", + "\" has svg-xml text in it. Most likely, linking of support-files generated by jupyter is broken. The svg-xml text has been removed for the doc-manual, but also no plot will be displayed\r\n", ), ) # regex replace exeeds stack limit: s = replace(s, r"\<\?xml(?!<\/svg>)(.|\n)*?<\/svg>" => "") diff --git a/docs/src/examples/simulate.md b/docs/src/examples/simulate.md new file mode 100644 index 00000000..cd1c65b6 --- /dev/null +++ b/docs/src/examples/simulate.md @@ -0,0 +1,307 @@ +# Simulate an FMU in different modes +Tutorial by Johannes Stoljar, Tobias Thummerer + +🚧 This tutorial is under revision and will be replaced by an up-to-date version soon 🚧 + +## License + + +```julia +# 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](https://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 +In this example we want to show how fast and easy the simulation for an FMU is. For this purpose, the FMU is simulated in co-simulation mode and in model-exchange mode. After the FMU has been simulated, the simulation results are displayed in a graph. The graphs of the different modes are compared with each other. The used model 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/examples/examples/src/simulate.ipynb) there is also a [Julia file](https://github.com/thummeto/FMI.jl/blob/examples/examples/src/simulate.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/examples/examples/src/simulate.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 Plots via | add Plots | | + +## Code section + +To run the example, the previously installed packages must be included. + + +```julia +# imports +using FMI +using FMIZoo +using Plots +using DifferentialEquations +``` + +### Simulation setup + +Next, the start time and end time of the simulation are set. Finally, a step size is specified to store the results of the simulation at these time steps. + + +```julia +tStart = 0.0 +tStep = 0.01 +tStop = 8.0 +tSave = tStart:tStep:tStop +``` + + + + + 0.0:0.01: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 = loadFMU(pathToFMU) +# loadFMU("path/to/myFMU.fmu"; unpackPath = "path/to/unpacked/fmu/") + +info(myFMU) +``` + + #################### 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 ##################### + + +### Simulate FMU + +In the following, the FMU is simulated in the two different simulation modes. + +#### Simulate as Co-Simulation + +In the next steps the recorded values are defined. The first state is the position of the mass and the second state is the velocity. In the function `simulateCS()` the FMU is simulated in co-simulation mode (CS) with an adaptive step size but with fixed save points `tSave`. In addition, the start and end time and the recorded variables are specified. + + +```julia +vrs = ["mass.s", "mass.v"] + +dataCS = simulateCS(myFMU, (tStart, tStop); recordValues=vrs, saveat=tSave) +``` + + + + + Model name: + SpringFrictionPendulum1D + Success: + true + f(x)-Evaluations: + In-place: 0 + Out-of-place: 0 + Jacobian-Evaluations: + ∂ẋ_∂p: 0 + ∂ẋ_∂x: 0 + ∂ẋ_∂u: 0 + ∂y_∂p: 0 + ∂y_∂x: 0 + ∂y_∂u: 0 + ∂e_∂p: 0 + ∂e_∂x: 0 + ∂e_∂u: 0 + ∂xr_∂xl: 0 + Gradient-Evaluations: + ∂ẋ_∂t: 0 + ∂y_∂t: 0 + ∂e_∂t: 0 + Callback-Evaluations: + Condition (event-indicators): 0 + Time-Choice (event-instances): 0 + Affect (event-handling): 0 + Save values: 0 + Steps completed: 0 + Values [801]: + 0.0 (0.5, 0.0) + 0.01 (0.5002235448486548, 0.042692491939260585) + 0.02 (0.5008715291319449, 0.08568000508550636) + 0.03 (0.5019478597521578, 0.12892136998736314) + 0.04 (0.5034570452098334, 0.17232325681284336) + 0.05 (0.5053993458877354, 0.2158440857658765) + 0.06 (0.5077764240578201, 0.259420181133082) + 0.07 (0.5105886522837868, 0.30295578207463486) + 0.08 (0.5138351439717114, 0.3464184707972189) + ... + 8.0 (1.0713672543616686, -1.0008145180651074e-10) + Events [0]: + + + + +#### Simulate as Model-Exchange + +In the function `simulateME()` the FMU is simulated in model-exchange mode (ME) with an adaptive step size but with fixed save points `tSave`. In addition, the start and end time are specified. In contrast to the co-simulation, the values to be stored are not specified here, since the states and events of the FMU are always output as well. The identifiers given above just correspond to the states of the FMU. + + +```julia +dataME = simulateME(myFMU, (tStart, tStop); saveat=tSave) +``` + + +Simulating ME-FMU ... 0%|█ | ETA: N/A + + +Simulating ME-FMU ... 100%|██████████████████████████████| Time: 0:00:15 + + + + + + Model name: + SpringFrictionPendulum1D + Success: + true + f(x)-Evaluations: + In-place: 687 + Out-of-place: 0 + Jacobian-Evaluations: + ∂ẋ_∂p: 0 + ∂ẋ_∂x: 0 + ∂ẋ_∂u: 0 + ∂y_∂p: 0 + ∂y_∂x: 0 + ∂y_∂u: 0 + ∂e_∂p: 0 + ∂e_∂x: 0 + ∂e_∂u: 0 + ∂xr_∂xl: 0 + Gradient-Evaluations: + ∂ẋ_∂t: 0 + ∂y_∂t: 0 + ∂e_∂t: 0 + Callback-Evaluations: + Condition (event-indicators): 1451 + Time-Choice (event-instances): 0 + Affect (event-handling): 6 + Save values: 0 + Steps completed: 108 + States [801]: + 0.0 [0.5, 0.0] + 0.01 [0.5002131418271644, 0.042689450728413444] + 0.02 [0.500854887495059, 0.08570846016824428] + 0.03 [0.5019281657516876, 0.1289839014807958] + 0.04 [0.5034351795370763, 0.17244393614729067] + 0.05 [0.50537742474533, 0.21601821086566914] + 0.06 [0.5077556992635467, 0.25963791323182245] + 0.07 [0.5105701152466664, 0.3032358520639911] + 0.08 [0.5138201143130452, 0.34674645493266393] + ... + 8.0 [1.0668392065868253, -1.0000121313794676e-10] + Events [6]: + State-Event #11 @ 2.352941176471972e-11s (state-change: false) + State-Event #11 @ 0.9940420391302653s (state-change: false) + State-Event #19 @ 1.9882755413358095s (state-change: false) + State-Event #11 @ 2.9830393009345677s (state-change: false) + State-Event #19 @ 3.978829658884447s (state-change: false) + State-Event #11 @ 4.976975955926236s (state-change: false) + + + + +### Plotting FMU + +After the simulation is finished the results of the FMU for the co-simulation and 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 +plot(dataCS) +``` + + + + + + + + + + +```julia +plot(dataME) +``` + + + + + + + + + +From both graphs it can be seen that the simulation calculates exactly the same results. + +### Unload FMU + +After plotting the data, the FMU is unloaded and all unpacked data on disc is removed. + + +```julia +unloadFMU(myFMU) +``` + +### Summary + +Based on this tutorial it can be seen that simulating in the different mode is very easy, and it only takes a few commands to simulate the FMU. diff --git a/test/.gitignore b/test/.gitignore index c0f3c698..f0a471af 100644 --- a/test/.gitignore +++ b/test/.gitignore @@ -1,3 +1,6 @@ +*.svg +*.pdf +*.gif *.jld2 *.csv *.mat \ No newline at end of file