Skip to content

Commit d55a4aa

Browse files
Merge pull request #4637 from SciML/as/fmi-fixes
refactor: avoid repeatedly instantiating FMUs during initialization
2 parents 70e3976 + d2559a2 commit d55a4aa

1 file changed

Lines changed: 36 additions & 8 deletions

File tree

ext/MTKFMIExt.jl

Lines changed: 36 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -93,13 +93,16 @@ with the name `namespace__variable`.
9393
FMU. For CoSimulation FMUs whose states/outputs are used in algebraic equations of the
9494
system, this needs to be an algorithm that will solve for the new algebraic variables.
9595
For example, `OrdinaryDiffEqCore.BrownFullBasicInit()`.
96+
- `stop_time`: The `stopTime` for the FMU, as defined in the FMI spec. By default, this will
97+
be set to `tspan[2]` when the `ODEProblem` is solved. An explicit value will overwrite this.
9698
- `type`: Either `:ME` or `:CS` depending on whether `fmu` is a Model Exchange or
9799
CoSimulation FMU respectively.
98100
- `name`: The name of the system.
99101
"""
100102
function MTK.FMIComponent(
101103
::Val{Ver}; fmu = nothing, tolerance = 1.0e-6,
102-
communication_step_size = nothing, reinitializealg = nothing, type, name
104+
communication_step_size = nothing, reinitializealg = nothing,
105+
stop_time = nothing, type, name
103106
) where {Ver}
104107
if Ver != 2 && Ver != 3
105108
throw(ArgumentError("FMI Version must be `2` or `3`"))
@@ -264,9 +267,9 @@ function MTK.FMIComponent(
264267
append!(observed, der_observed)
265268
elseif type == :CS
266269
_functor = if Ver == 2
267-
FMI2CSFunctor(state_value_references, output_value_references, Base.Ref{FMI.fmi2Real}(NaN))
270+
FMI2CSFunctor(state_value_references, output_value_references, Base.Ref{FMI.fmi2Real}(something(stop_time, NaN)))
268271
else
269-
FMI3CSFunctor(state_value_references, output_value_references, Base.Ref{FMI.fmi3Float64}(NaN))
272+
FMI3CSFunctor(state_value_references, output_value_references, Base.Ref{FMI.fmi3Float64}(something(stop_time, NaN)))
270273
end
271274
@parameters (functor::(typeof(_functor)))(..)[1:(length(__mtk_internal_u) + length(__mtk_internal_o))] = _functor
272275
# for co-simulation, we need to ensure the output buffer is solved for
@@ -567,6 +570,19 @@ function get_instance_CS!(wrapper::FMI2InstanceWrapper, states, inputs, params,
567570
)
568571
end
569572
@statuscheck FMI.fmi2ExitInitializationMode(wrapper.instance)
573+
else
574+
if !isempty(states)
575+
@statuscheck FMI.fmi2SetReal(
576+
wrapper.instance, wrapper.state_value_references,
577+
Csize_t(length(wrapper.state_value_references)), states
578+
)
579+
end
580+
if !isempty(inputs)
581+
@statuscheck FMI.fmi2SetReal(
582+
wrapper.instance, wrapper.input_value_references,
583+
Csize_t(length(inputs)), inputs
584+
)
585+
end
570586
end
571587
return wrapper.instance
572588
end
@@ -729,6 +745,17 @@ function get_instance_CS!(wrapper::FMI3InstanceWrapper, states, inputs, params,
729745
)
730746
end
731747
@statuscheck FMI.fmi3ExitInitializationMode(wrapper.instance)
748+
else
749+
if !isempty(inputs)
750+
@statuscheck FMI.fmi3SetFloat64(
751+
wrapper.instance, wrapper.input_value_references, inputs
752+
)
753+
end
754+
if !isempty(states)
755+
@statuscheck FMI.fmi3SetFloat64(
756+
wrapper.instance, wrapper.state_value_references, states
757+
)
758+
end
732759
end
733760
return wrapper.instance
734761
end
@@ -850,9 +877,6 @@ function (fn::FMI2CSFunctor)(wrapper::FMI2InstanceWrapper, states, inputs, param
850877
states = states isa SubArray ? copy(states) : states
851878
inputs = inputs isa SubArray ? copy(inputs) : inputs
852879
params = params isa SubArray ? copy(params) : params
853-
if wrapper.instance !== nothing
854-
reset_instance!(wrapper)
855-
end
856880
instance = get_instance_CS!(wrapper, states, inputs, params, t, fn.t_end[])
857881
if isempty(fn.output_value_references)
858882
return eltype(states)[]
@@ -887,7 +911,9 @@ function fmiCSInitialize!(m, o, ctx::FMI2CSFunctor, integrator)
887911
params = o.params
888912
t = o.t
889913
wrapper = o.wrapper
890-
ctx.t_end[] = integrator.sol.prob.tspan[2]
914+
if isnan(ctx.t_end[])
915+
ctx.t_end[] = integrator.sol.prob.tspan[2]
916+
end
891917
if wrapper.instance !== nothing
892918
reset_instance!(wrapper)
893919
end
@@ -993,7 +1019,9 @@ function fmiCSInitialize!(m, o, ctx::FMI3CSFunctor, integrator)
9931019
params = o.params
9941020
t = o.t
9951021
wrapper = o.wrapper
996-
ctx.t_end[] = integrator.sol.prob.tspan[2]
1022+
if isnan(ctx.t_end[])
1023+
ctx.t_end[] = integrator.sol.prob.tspan[2]
1024+
end
9971025
if wrapper.instance !== nothing
9981026
reset_instance!(wrapper)
9991027
end

0 commit comments

Comments
 (0)