Skip to content

Commit

Permalink
V0.10.1 (#152)
Browse files Browse the repository at this point in the history
* modified test

* new backend y0.12.0

* fixed time-dependent test

* fixed test
  • Loading branch information
ThummeTo authored Oct 13, 2022
1 parent 6637cca commit aaec579
Show file tree
Hide file tree
Showing 5 changed files with 72 additions and 47 deletions.
4 changes: 2 additions & 2 deletions Project.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name = "FMI"
uuid = "14a09403-18e3-468f-ad8a-74f8dda2d9ac"
authors = ["TT <[email protected]>", "LM <[email protected]>", "JK <[email protected]>"]
version = "0.10.0"
version = "0.10.1"

[deps]
ChainRulesCore = "d360d2e6-b24c-11e9-a2a3-2a2ae2dbcce4"
Expand All @@ -20,7 +20,7 @@ ChainRulesCore = "1.15.0"
DiffEqCallbacks = "2.24.0"
DifferentialEquations = "7.5.0"
FMIExport = "0.1.0"
FMIImport = "0.11.0"
FMIImport = "0.12.0"
ForwardDiff = "0.10.0"
ProgressMeter = "1.7.0"
Requires = "1.3.0"
Expand Down
11 changes: 7 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
(@v1.6) pkg> add FMI
```

(3)\. If you want to check that everything works correctly, you can run the tests bundled with [*FMI.jl*](https://github.com/ThummeTo/FMI.jl):
3\. If you want to check that everything works correctly, you can run the tests bundled with [*FMI.jl*](https://github.com/ThummeTo/FMI.jl):
```julia-repl
(@v1.6) pkg> test FMI
```
Expand Down Expand Up @@ -97,12 +97,15 @@ To keep dependencies nice and clean, the original package [*FMI.jl*](https://git
- ...

## What Platforms are supported?
[*FMI.jl*](https://github.com/ThummeTo/FMI.jl) is tested (and testing) under Julia Versions *1.6.5 LTS* (64-bit) and *latest* (64-bit) on Windows *latest* (64-bit) and Ubuntu *latest* (64-bit). Mac and Julia (32-bit) should work, but untested.
[*FMI.jl*](https://github.com/ThummeTo/FMI.jl) is tested (and testing) under Julia Versions *1.6.6 LTS* (64-bit) and *latest* (64-bit) on Windows *latest* (64-bit) and Ubuntu *latest* (64-bit). Mac and Julia (32-bit) should work, but untested.

## How to cite? Related publications?
## How to cite?
Tobias Thummerer, Lars Mikelsons and Josef Kircher. 2021. **NeuralFMU: towards structural integration of FMUs into neural networks.** Martin Sjölund, Lena Buffoni, Adrian Pop and Lennart Ochel (Ed.). Proceedings of 14th Modelica Conference 2021, Linköping, Sweden, September 20-24, 2021. Linköping University Electronic Press, Linköping (Linköping Electronic Conference Proceedings ; 181), 297-306. [DOI: 10.3384/ecp21181297](https://doi.org/10.3384/ecp21181297)

Tobias Thummerer, Johannes Tintenherr, Lars Mikelsons 2021 **Hybrid modeling of the human cardiovascular system using NeuralFMUs** Journal of Physics: Conference Series 2090, 1, 012155. [DOI: 10.1088/1742-6596/2090/1/012155](https://doi.org/10.1088/1742-6596/2090/1/012155)
## Related publications?
Tobias Thummerer, Johannes Stoljar and Lars Mikelsons. 2022. **NeuralFMU: presenting a workflow for integrating hybrid NeuralODEs into real-world applications.** Electronics 11, 19, 3202. [DOI: 10.3390/electronics11193202](https://doi.org/10.3390/electronics11193202)

Tobias Thummerer, Johannes Tintenherr, Lars Mikelsons. 2021 **Hybrid modeling of the human cardiovascular system using NeuralFMUs** Journal of Physics: Conference Series 2090, 1, 012155. [DOI: 10.1088/1742-6596/2090/1/012155](https://doi.org/10.1088/1742-6596/2090/1/012155)

## Interested in Hybrid Modelling in Julia using FMUs?
See [*FMIFlux.jl*](https://github.com/ThummeTo/FMIFlux.jl).
80 changes: 48 additions & 32 deletions src/FMI2_sim.jl
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,7 @@ function affectFMU!(c::FMU2Component, integrator, idx, inputFunction, inputValue
u_modified!(integrator, true)
#set_proposed_dt!(integrator, 1e-10)
else
u_modified!(integrator, false)
@debug "affectFMU!(...): Handled event at t=$(integrator.t), no new state."
end

Expand All @@ -152,8 +153,12 @@ function stepCompleted(c::FMU2Component, x, t, integrator, inputFunction, inputV

@assert c.state == fmi2ComponentStateContinuousTimeMode "stepCompleted(...): Must be in continuous time mode."
#@info "Step completed"
if progressMeter !== nothing
ProgressMeter.update!(progressMeter, floor(Integer, 1000.0*(t-tStart)/(tStop-tStart)) )
if progressMeter !== nothing
stat = 1000.0*(t-tStart)/(tStop-tStart)
if !isnan(stat)
stat = floor(Integer, stat)
ProgressMeter.update!(progressMeter, stat)
end
end

(status, enterEventMode, terminateSimulation) = fmi2CompletedIntegratorStep(c, fmi2True)
Expand Down Expand Up @@ -197,34 +202,36 @@ function fx(c::FMU2Component,
p::AbstractArray,
t::Real)

if isa(t, ForwardDiff.Dual)
t = ForwardDiff.value(t)
end
# if isa(t, ForwardDiff.Dual)
# t = ForwardDiff.value(t)
# end

fmi2SetContinuousStates(c, x)
fmi2SetTime(c, t)
# fmi2SetContinuousStates(c, x)
# fmi2SetTime(c, t)

if all(isa.(dx, ForwardDiff.Dual))
dx_tmp = collect(ForwardDiff.value(e) for e in dx)
fmi2GetDerivatives!(c, dx_tmp)
T, V, N = fd_eltypes(dx)
dx[:] = collect(ForwardDiff.Dual{T, V, N}(dx_tmp[i], ForwardDiff.partials(dx[i]) ) for i in 1:length(dx))
else
fmi2GetDerivatives!(c, dx)
end
# if all(isa.(dx, ForwardDiff.Dual))
# dx_tmp = collect(ForwardDiff.value(e) for e in dx)
# fmi2GetDerivatives!(c, dx_tmp)
# T, V, N = fd_eltypes(dx)
# dx[:] = collect(ForwardDiff.Dual{T, V, N}(dx_tmp[i], ForwardDiff.partials(dx[i]) ) for i in 1:length(dx))
# else
# fmi2GetDerivatives!(c, dx)
# end

y, dx = FMIImport.eval!(c, dx, nothing, nothing, x, nothing, nothing, t)

return dx
end

# ForwardDiff-Dispatch for fx
function fx(comp::FMU2Component,
dx::AbstractArray{<:Real},
x::AbstractArray{<:ForwardDiff.Dual{Tx, Vx, Nx}},
p::AbstractArray,
t::Real) where {Tx, Vx, Nx}
# function fx(comp::FMU2Component,
# dx::AbstractArray{<:Real},
# x::AbstractArray{<:ForwardDiff.Dual{Tx, Vx, Nx}},
# p::AbstractArray,
# t::Real) where {Tx, Vx, Nx}

return _fx_fd(comp, dx, x, p, t)
end
# return _fx_fd(comp, dx, x, p, t)
# end

# function _fx_fd(TVNx, comp, dx, x, p, t)

Expand Down Expand Up @@ -758,6 +765,18 @@ function fmi2SimulateME(c::FMU2Component, t_start::Union{Real, Nothing} = nothin
fmi2SimulateME(c.fmu, c, t_start, t_stop; kwargs...)
end

# sets up the ODEProblem for simulating a ME-FMU
function setupODEProblem(c::FMU2Component, x0::AbstractArray{fmi2Real}, t_start::fmi2Real, t_stop::fmi2Real; p=[], customFx=nothing)
if customFx === nothing
customFx = (dx, x, p, t) -> fx(c, dx, x, p, t)
end

p = []
c.problem = ODEProblem(customFx, x0, (t_start, t_stop), p,)

return c.problem
end

"""
Simulates a FMU instance for the given simulation time interval.
State- and Time-Events are handled correctly.
Expand Down Expand Up @@ -869,7 +888,9 @@ function fmi2SimulateME(fmu::FMU2, c::Union{FMU2Component, Nothing}=nothing, t_s
dtmax = (t_stop-t_start)/100.0
end

c, x0 = prepareFMU(fmu, c, fmi2TypeModelExchange, instantiate, terminate, reset, setup, parameters, t_start, t_stop, tolerance; x0=x0, inputFunction=_inputFunction, inputValueReferences=inputValueReferences)
# argument `tolerance=nothing` here, because ME-FMUs doesn't support tolerance control (no solver included)
# tolerance for the solver is set-up later in this function
c, x0 = prepareFMU(fmu, c, fmi2TypeModelExchange, instantiate, terminate, reset, setup, parameters, t_start, t_stop, nothing; x0=x0, inputFunction=_inputFunction, inputValueReferences=inputValueReferences)

# from here on, we are in event mode, if `setup=false` this is the job of the user
#@assert c.state == fmi2ComponentStateEventMode "FMU needs to be in event mode after setup."
Expand All @@ -886,12 +907,7 @@ function fmi2SimulateME(fmu::FMU2, c::Union{FMU2Component, Nothing}=nothing, t_s
c.fmu.hasStateEvents = (c.fmu.modelDescription.numberOfEventIndicators > 0)
c.fmu.hasTimeEvents = (c.eventInfo.nextEventTimeDefined == fmi2True)

if customFx === nothing
customFx = (dx, x, p, t) -> fx(c, dx, x, p, t)
end

p = []
problem = ODEProblem(customFx, x0, (t_start, t_stop), p,)
setupODEProblem(c, x0, t_start, t_stop; customFx=customFx)

progressMeter = nothing
if showProgress
Expand Down Expand Up @@ -945,7 +961,7 @@ function fmi2SimulateME(fmu::FMU2, c::Union{FMU2Component, Nothing}=nothing, t_s

# if auto_dt == true
# @assert solver !== nothing "fmi2SimulateME(...): `auto_dt=true` but no solver specified, this is not allowed."
# tmpIntegrator = init(problem, solver)
# tmpIntegrator = init(c.problem, solver)
# dt = auto_dt_reset!(tmpIntegrator)
# end

Expand All @@ -964,9 +980,9 @@ function fmi2SimulateME(fmu::FMU2, c::Union{FMU2Component, Nothing}=nothing, t_s
end

if solver === nothing
fmusol.states = solve(problem; callback = CallbackSet(cbs...), dtmax=dtmax, solveKwargs..., kwargs...)
fmusol.states = solve(c.problem; callback = CallbackSet(cbs...), dtmax=dtmax, solveKwargs..., kwargs...)
else
fmusol.states = solve(problem, solver; callback = CallbackSet(cbs...), dtmax=dtmax, solveKwargs..., kwargs...)
fmusol.states = solve(c.problem, solver; callback = CallbackSet(cbs...), dtmax=dtmax, solveKwargs..., kwargs...)
end

fmusol.success = (fmusol.states.retcode == :Success)
Expand Down
6 changes: 6 additions & 0 deletions test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,12 @@ exportingToolsWindows = [("Dymola", "2022x")]
exportingToolsLinux = [("Dymola", "2022x")]
fmuStructs = ["FMU", "FMUCOMPONENT"]

# enable assertions for warnings/errors for all default execution configurations
for exec in [FMU2_EXECUTION_CONFIGURATION_NO_FREEING, FMU2_EXECUTION_CONFIGURATION_NO_RESET, FMU2_EXECUTION_CONFIGURATION_RESET]
exec.assertOnError = true
exec.assertOnWarning = true
end

function runtests(exportingTool)
ENV["EXPORTINGTOOL"] = exportingTool[1]
ENV["EXPORTINGVERSION"] = exportingTool[2]
Expand Down
18 changes: 9 additions & 9 deletions test/sim_ME.jl
Original file line number Diff line number Diff line change
Expand Up @@ -171,17 +171,17 @@ elseif envFMUSTRUCT == "FMUCOMPONENT"
end
@assert fmuStruct != nothing "Unknown fmuStruct, environment variable `FMUSTRUCT` = `$envFMUSTRUCT`"

# ToDo: autodiff=true not working currently!
# solution = fmiSimulateME(fmuStruct, t_start, t_stop; inputValueReferences=["extForce"], inputFunction=extForce, solver=Rosenbrock23(autodiff=true), dtmax=0.001) # dtmax to force resolution
# @test length(solution.states.u) > 0
# @test length(solution.states.t) > 0
# ToDo: test `autodiff=true`
solution = fmiSimulateME(fmuStruct, t_start, t_stop; solver=Rosenbrock23(autodiff=false), dtmax=0.001) # dtmax to force resolution
@test length(solution.states.u) > 0
@test length(solution.states.t) > 0

# @test solution.states.t[1] == t_start
# @test solution.states.t[end] == t_stop
@test solution.states.t[1] == t_start
@test solution.states.t[end] == t_stop

# # reference values from Simulation in Dymola2020x (Dassl)
# @test solution.states.u[1] == [0.5, 0.0]
# @test sum(abs.(solution.states.u[end] - [0.613371, 0.188633])) < 0.01
# reference values (no force) from Simulation in Dymola2020x (Dassl)
@test solution.states.u[1] == [0.5, 0.0]
@test sum(abs.(solution.states.u[end] - [0.509219, 0.314074])) < 0.01
fmiUnload(myFMU)

# case 3c: ME-FMU without events, but with input signal (implicit solver: Rosenbrock23, no autodiff)
Expand Down

3 comments on commit aaec579

@ThummeTo
Copy link
Owner Author

@ThummeTo ThummeTo commented on aaec579 Oct 13, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ThummeTo
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@JuliaRegistrator
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Registration pull request created: JuliaRegistries/General/70110

After the above pull request is merged, it is recommended that a tag is created on this repository for the registered package version.

This will be done automatically if the Julia TagBot GitHub Action is installed, or can be done manually through the github interface, or via:

git tag -a v0.10.1 -m "<description of version>" aaec579b7eef00ea4c693d2af6ce5ea22898fbcb
git push origin v0.10.1

Please sign in to comment.