diff --git a/.github/workflows/Formatter.yml b/.github/workflows/Formatter.yml new file mode 100644 index 0000000..0155d9b --- /dev/null +++ b/.github/workflows/Formatter.yml @@ -0,0 +1,14 @@ +name: Format suggestions +on: + pull_request: + # this argument is not required if you don't use the `suggestion-label` input + types: [ opened, reopened, synchronize, labeled, unlabeled ] +jobs: + code-style: + runs-on: ubuntu-latest + steps: + - uses: julia-actions/julia-format@v3 + with: + version: '1' # Set `version` to '1.0.54' if you need to use JuliaFormatter.jl v1.0.54 (default: '1') + suggestion-label: 'format-suggest' # leave this unset or empty to show suggestions for all PRs + diff --git a/.github/workflows/TestLTS.yml b/.github/workflows/TestLTS.yml index 2e1c8e6..1534158 100644 --- a/.github/workflows/TestLTS.yml +++ b/.github/workflows/TestLTS.yml @@ -35,7 +35,11 @@ jobs: version: ${{ matrix.julia-version }} arch: ${{ matrix.julia-arch }} - # Set up cache + # Set up julia-cache + - name: Set up julia-cache + uses: julia-actions/cache@v2 + + # Set up cache - name: "Set up cache" uses: actions/cache@v4 env: diff --git a/.github/workflows/TestLatest.yml b/.github/workflows/TestLatest.yml index 78f7712..98575e6 100644 --- a/.github/workflows/TestLatest.yml +++ b/.github/workflows/TestLatest.yml @@ -35,7 +35,11 @@ jobs: version: ${{ matrix.julia-version }} arch: ${{ matrix.julia-arch }} - # Set up cache + # Set up julia-cache + - name: Set up julia-cache + uses: julia-actions/cache@v2 + + # Set up cache - name: "Set up cache" uses: actions/cache@v4 env: @@ -66,4 +70,4 @@ jobs: env: CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} with: - file: lcov.info + files: lcov.info diff --git a/src/FMISensitivity.jl b/src/FMISensitivity.jl index f9fe5a2..d7b4c29 100644 --- a/src/FMISensitivity.jl +++ b/src/FMISensitivity.jl @@ -10,7 +10,7 @@ import SciMLSensitivity import SciMLSensitivity: ForwardDiff import SciMLSensitivity: FiniteDiff import SciMLSensitivity: ReverseDiff -import SciMLSensitivity: Zygote +import SciMLSensitivity: Zygote import FMIBase.ChainRulesCore using FMIBase.ChainRulesCore: ZeroTangent, NoTangent, @thunk diff --git a/src/hotfixes.jl b/src/hotfixes.jl index d8df6f7..7ff57d5 100644 --- a/src/hotfixes.jl +++ b/src/hotfixes.jl @@ -8,5 +8,6 @@ import FMIBase: FMUEvaluationOutput #grad_mut(av::AbstractVector) = invoke(grad_mut, Tuple{Any}, av) grad_mut(av::FMUEvaluationOutput) = invoke(grad_mut, Tuple{Any}, av) #grad_mut(c::Zygote.Context, av::AbstractVector) = invoke(grad_mut, Tuple{Zygote.Context, Any}, c, av) -grad_mut(c::Zygote.Context, av::FMUEvaluationOutput) = invoke(grad_mut, Tuple{Zygote.Context, Any}, c, av) -#grad_mut(av::AbstractVector) = [] \ No newline at end of file +grad_mut(c::Zygote.Context, av::FMUEvaluationOutput) = + invoke(grad_mut, Tuple{Zygote.Context,Any}, c, av) +#grad_mut(av::AbstractVector) = [] diff --git a/src/sense.jl b/src/sense.jl index 3314161..0fa0498 100644 --- a/src/sense.jl +++ b/src/sense.jl @@ -5,10 +5,18 @@ import FMIBase: eval!, invalidate!, check_invalidate! using FMIBase: getDirectionalDerivative!, getAdjointDerivative! -using FMIBase: setContinuousStates, setInputs, setReal, setTime, setReal, getReal!, getEventIndicators!, getRealType +using FMIBase: + setContinuousStates, + setInputs, + setReal, + setTime, + setReal, + getReal!, + getEventIndicators!, + getRealType # in FMI2 and FMI3 we can use fmi2GetDirectionalDerivative for JVP-computations -function jvp!(c::FMUInstance, mtxCache::Symbol, ∂f_refs, ∂x_refs, x, seed; accu=nothing) +function jvp!(c::FMUInstance, mtxCache::Symbol, ∂f_refs, ∂x_refs, x, seed; accu = nothing) jac = getfield(c, mtxCache) if isnothing(jac) @@ -22,7 +30,10 @@ function jvp!(c::FMUInstance, mtxCache::Symbol, ∂f_refs, ∂x_refs, x, seed; a jac.f_refs = ∂f_refs jac.x_refs = ∂x_refs - if c.fmu.executionConfig.JVPBuiltInDerivatives && providesDirectionalDerivatives(c.fmu) && !isa(jac.f_refs, Tuple) && !isa(jac.x_refs, Symbol) + if c.fmu.executionConfig.JVPBuiltInDerivatives && + providesDirectionalDerivatives(c.fmu) && + !isa(jac.f_refs, Tuple) && + !isa(jac.x_refs, Symbol) getDirectionalDerivative!(c, ∂f_refs, ∂x_refs, seed, jac.jvp) else jvp!(jac, x, seed) @@ -33,7 +44,7 @@ function jvp!(c::FMUInstance, mtxCache::Symbol, ∂f_refs, ∂x_refs, x, seed; a return nothing end -function gvp!(c::FMUInstance, mtxCache::Symbol, ∂f_refs, ∂x_refs, x, seed; accu=nothing) +function gvp!(c::FMUInstance, mtxCache::Symbol, ∂f_refs, ∂x_refs, x, seed; accu = nothing) grad = getfield(c, mtxCache) if isnothing(grad) @@ -47,7 +58,10 @@ function gvp!(c::FMUInstance, mtxCache::Symbol, ∂f_refs, ∂x_refs, x, seed; a grad.f_refs = ∂f_refs grad.x_refs = ∂x_refs - if c.fmu.executionConfig.JVPBuiltInDerivatives && providesDirectionalDerivatives(c.fmu) && !isa(grad.f_refs, Tuple) && !isa(grad.x_refs, Symbol) + if c.fmu.executionConfig.JVPBuiltInDerivatives && + providesDirectionalDerivatives(c.fmu) && + !isa(grad.f_refs, Tuple) && + !isa(grad.x_refs, Symbol) getDirectionalDerivative!(c, ∂f_refs, ∂x_refs, [seed], grad.gvp) else gvp!(grad, x, seed) @@ -59,7 +73,7 @@ function gvp!(c::FMUInstance, mtxCache::Symbol, ∂f_refs, ∂x_refs, x, seed; a end # in FMI2 there is no helper for VJP-computations (but in FMI3) ... -function vjp!(c::FMUInstance, mtxCache::Symbol, ∂f_refs, ∂x_refs, x, seed; accu=nothing) +function vjp!(c::FMUInstance, mtxCache::Symbol, ∂f_refs, ∂x_refs, x, seed; accu = nothing) jac = getfield(c, mtxCache) if isnothing(jac) @@ -72,8 +86,11 @@ function vjp!(c::FMUInstance, mtxCache::Symbol, ∂f_refs, ∂x_refs, x, seed; a jac.f_refs = ∂f_refs jac.x_refs = ∂x_refs - - if c.fmu.executionConfig.VJPBuiltInDerivatives && providesAdjointDerivatives(c.fmu) && !isa(jac.f_refs, Tuple) && !isa(jac.x_refs, Symbol) + + if c.fmu.executionConfig.VJPBuiltInDerivatives && + providesAdjointDerivatives(c.fmu) && + !isa(jac.f_refs, Tuple) && + !isa(jac.x_refs, Symbol) getAdjointDerivative!(c, ∂f_refs, ∂x_refs, seed, jac.vjp) else vjp!(jac, x, seed) @@ -84,7 +101,7 @@ function vjp!(c::FMUInstance, mtxCache::Symbol, ∂f_refs, ∂x_refs, x, seed; a return nothing end -function vgp!(c::FMUInstance, mtxCache::Symbol, ∂f_refs, ∂x_refs, x, seed; accu=nothing) +function vgp!(c::FMUInstance, mtxCache::Symbol, ∂f_refs, ∂x_refs, x, seed; accu = nothing) grad = getfield(c, mtxCache) if isnothing(grad) @@ -97,8 +114,11 @@ function vgp!(c::FMUInstance, mtxCache::Symbol, ∂f_refs, ∂x_refs, x, seed; a grad.f_refs = ∂f_refs grad.x_refs = ∂x_refs - - if c.fmu.executionConfig.VJPBuiltInDerivatives && providesAdjointDerivatives(c.fmu) && !isa(grad.f_refs, Tuple) && !isa(grad.x_refs, Symbol) + + if c.fmu.executionConfig.VJPBuiltInDerivatives && + providesAdjointDerivatives(c.fmu) && + !isa(grad.f_refs, Tuple) && + !isa(grad.x_refs, Symbol) getAdjointDerivative!(c, ∂f_refs, ∂x_refs, [seed], grad.vgp) else vgp!(grad, x, seed) @@ -109,23 +129,38 @@ function vgp!(c::FMUInstance, mtxCache::Symbol, ∂f_refs, ∂x_refs, x, seed; a return nothing end -function ChainRulesCore.frule(Δtuple, - ::typeof(FMIBase.eval!), - cRef, +function ChainRulesCore.frule( + Δtuple, + ::typeof(FMIBase.eval!), + cRef, dx, dx_refs, y, - y_refs, + y_refs, x, u, u_refs, p, - p_refs, - ec, + p_refs, + ec, ec_idcs, - t) - - Δself, ΔcRef, Δdx, Δdx_refs, Δy, Δy_refs, Δx, Δu, Δu_refs, Δp, Δp_refs, Δec, Δec_idcs, Δt = Δtuple # undual ? + t, +) + + Δself, + ΔcRef, + Δdx, + Δdx_refs, + Δy, + Δy_refs, + Δx, + Δu, + Δu_refs, + Δp, + Δp_refs, + Δec, + Δec_idcs, + Δt = Δtuple # undual ? @debug "frule start" @@ -136,7 +171,7 @@ function ChainRulesCore.frule(Δtuple, cRef = UInt64(cRef) end c = unsafe_pointer_to_objref(Ptr{Nothing}(cRef)) - + # ToDo: is this necessary? # t = undual(t) # u = undual(u) @@ -145,10 +180,11 @@ function ChainRulesCore.frule(Δtuple, dx_refs = unsense(dx_refs) dx_refs = convert(Array{UInt32,1}, dx_refs) - if length(dx_refs) == 0 && length(dx) == length(c.fmu.modelDescription.derivativeValueReferences) # all derivatives, please! + if length(dx_refs) == 0 && + length(dx) == length(c.fmu.modelDescription.derivativeValueReferences) # all derivatives, please! dx_refs = c.fmu.modelDescription.derivativeValueReferences end - + # [Note] `unsense` is necessary for AD over AD y_refs = unsense(y_refs) u_refs = unsense(u_refs) @@ -158,8 +194,8 @@ function ChainRulesCore.frule(Δtuple, y_refs = convert(Array{UInt32,1}, y_refs) u_refs = convert(Array{UInt32,1}, u_refs) p_refs = convert(Array{UInt32,1}, p_refs) - ec_idcs = convert(Array{UInt32,1}, ec_idcs) - + ec_idcs = convert(Array{UInt32,1}, ec_idcs) + ### outputs = (length(y_refs) > 0) @@ -171,7 +207,7 @@ function ChainRulesCore.frule(Δtuple, eventIndicators = (length(ec_idcs) > 0) Ω = FMIBase.eval!(cRef, dx, dx_refs, y, y_refs, x, u, u_refs, p, p_refs, ec, ec_idcs, t) - + # time, states and inputs where already set in `eval!`, no need to repeat it here # if length(c.frule_output.y) != length(y) @@ -204,17 +240,41 @@ function ChainRulesCore.frule(Δtuple, if states if derivatives - jvp!(c, :∂ẋ_∂x, dx_refs, c.fmu.modelDescription.stateValueReferences, x, Δx; accu=∂dx) + jvp!( + c, + :∂ẋ_∂x, + dx_refs, + c.fmu.modelDescription.stateValueReferences, + x, + Δx; + accu = ∂dx, + ) c.solution.evals_∂ẋ_∂x += 1 end - if outputs - jvp!(c, :∂y_∂x, y_refs, c.fmu.modelDescription.stateValueReferences, x, Δx; accu=∂y) + if outputs + jvp!( + c, + :∂y_∂x, + y_refs, + c.fmu.modelDescription.stateValueReferences, + x, + Δx; + accu = ∂y, + ) c.solution.evals_∂y_∂x += 1 end if eventIndicators - jvp!(c, :∂e_∂x, (:indicators, ec_idcs), c.fmu.modelDescription.stateValueReferences, x, Δx; accu=∂e) + jvp!( + c, + :∂e_∂x, + (:indicators, ec_idcs), + c.fmu.modelDescription.stateValueReferences, + x, + Δx; + accu = ∂e, + ) c.solution.evals_∂e_∂x += 1 end end @@ -224,17 +284,17 @@ function ChainRulesCore.frule(Δtuple, if inputs if derivatives - jvp!(c, :∂ẋ_∂u, dx_refs, u_refs, u, Δu; accu=∂dx) + jvp!(c, :∂ẋ_∂u, dx_refs, u_refs, u, Δu; accu = ∂dx) c.solution.evals_∂ẋ_∂u += 1 end if outputs - jvp!(c, :∂y_∂u, y_refs, u_refs, u, Δu; accu=∂y) + jvp!(c, :∂y_∂u, y_refs, u_refs, u, Δu; accu = ∂y) c.solution.evals_∂y_∂u += 1 end if eventIndicators - jvp!(c, :∂e_∂u, (:indicators, ec_idcs), u_refs, u, Δu; accu=∂e) + jvp!(c, :∂e_∂u, (:indicators, ec_idcs), u_refs, u, Δu; accu = ∂e) c.solution.evals_∂e_∂u += 1 end end @@ -244,17 +304,17 @@ function ChainRulesCore.frule(Δtuple, if parameters if derivatives - jvp!(c, :∂ẋ_∂p, dx_refs, p_refs, p, Δp; accu=∂dx) + jvp!(c, :∂ẋ_∂p, dx_refs, p_refs, p, Δp; accu = ∂dx) c.solution.evals_∂ẋ_∂p += 1 end if outputs - jvp!(c, :∂y_∂p, y_refs, p_refs, p, Δp; accu=∂y) + jvp!(c, :∂y_∂p, y_refs, p_refs, p, Δp; accu = ∂y) c.solution.evals_∂y_∂p += 1 end if eventIndicators - jvp!(c, :∂e_∂p, (:indicators, ec_idcs), p_refs, p, Δp; accu=∂e) + jvp!(c, :∂e_∂p, (:indicators, ec_idcs), p_refs, p, Δp; accu = ∂e) c.solution.evals_∂e_∂p += 1 end end @@ -262,19 +322,19 @@ function ChainRulesCore.frule(Δtuple, if Δt != NoTangent() && c.fmu.executionConfig.eval_t_gradients - if times + if times if derivatives - gvp!(c, :∂ẋ_∂t, dx_refs, :time, t, Δt; accu=∂dx) + gvp!(c, :∂ẋ_∂t, dx_refs, :time, t, Δt; accu = ∂dx) c.solution.evals_∂ẋ_∂t += 1 end if outputs - gvp!(c, :∂y_∂t, y_refs, :time, t, Δt; accu=∂y) + gvp!(c, :∂y_∂t, y_refs, :time, t, Δt; accu = ∂y) c.solution.evals_∂y_∂t += 1 end if eventIndicators - gvp!(c, :∂e_∂t, (:indicators, ec_idcs), :time, t, Δt; accu=∂e) + gvp!(c, :∂e_∂t, (:indicators, ec_idcs), :time, t, Δt; accu = ∂e) c.solution.evals_∂e_∂t += 1 end end @@ -284,37 +344,39 @@ function ChainRulesCore.frule(Δtuple, # [Note] Type Real is required for AD over AD ∂Ω = FMUEvaluationOutput{Real}() # Float64 - ∂Ω.y = ∂y + ∂Ω.y = ∂y ∂Ω.dx = ∂dx ∂Ω.ec = ∂e - return Ω, ∂Ω + return Ω, ∂Ω end -function ChainRulesCore.rrule(::typeof(FMIBase.eval!), - cRef, +function ChainRulesCore.rrule( + ::typeof(FMIBase.eval!), + cRef, dx, - dx_refs, + dx_refs, y, - y_refs, + y_refs, x, u, u_refs, p, p_refs, - ec, - ec_idcs, - t) + ec, + ec_idcs, + t, +) @assert !isa(cRef, FMUInstance) "Wrong dispatched!" @debug "rrule start: $((cRef, dx, dx_refs, y, y_refs, x, u, u_refs, p, p_refs, ec, ec_idcs, t))" - + c = unsafe_pointer_to_objref(Ptr{Nothing}(cRef)) y_len = (isnothing(y_refs) ? 0 : length(y_refs)) dx_len = (isnothing(dx) ? 0 : length(dx)) - + outputs = (length(y_refs) > 0) inputs = (length(u_refs) > 0) derivatives = (length(dx) > 0) @@ -330,7 +392,7 @@ function ChainRulesCore.rrule(::typeof(FMIBase.eval!), # setting the corresponding snapshot (that holds all related quantities, including the discrete state) # from the snapshot cache. This needs to be done for Ω, as well as for the pullback separately, # because they are evaluated at different points in time during ODE solving. - if length(c.solution.snapshots) > 0 + if length(c.solution.snapshots) > 0 sn = getSnapshot(c.solution, t) if !isnothing(sn) # sometimes it is -Inf apply!(c, sn) @@ -368,7 +430,7 @@ function ChainRulesCore.rrule(::typeof(FMIBase.eval!), #println("$(t),") - # ȳ = nothing + # ȳ = nothing # d̄x = nothing # ēc = nothing @@ -388,9 +450,9 @@ function ChainRulesCore.rrule(::typeof(FMIBase.eval!), # r̄[i] = 0.0 # end # end - + d̄x = @view(r̄[y_len+1:y_len+dx_len]) # r̄[1:dx_len] - ȳ = @view(r̄[1:y_len]) # r̄[dx_len+1:dx_len+y_len] + ȳ = @view(r̄[1:y_len]) # r̄[dx_len+1:dx_len+y_len] ēc = @view(r̄[y_len+dx_len+1:end]) # r̄[y_len+dx_len+1:end] outputs = outputs && !isZeroTangent(ȳ) @@ -441,68 +503,68 @@ function ChainRulesCore.rrule(::typeof(FMIBase.eval!), ū = zeros(length(u)) #ZeroTangent() p̄ = zeros(length(p)) #eroTangent() - if derivatives + if derivatives if states - vjp!(c, :∂ẋ_∂x, dx_refs, x_refs, x, d̄x; accu=x̄) + vjp!(c, :∂ẋ_∂x, dx_refs, x_refs, x, d̄x; accu = x̄) c.solution.evals_∂ẋ_∂x += 1 end if inputs - vjp!(c, :∂ẋ_∂u, dx_refs, u_refs, u, d̄x; accu=ū) + vjp!(c, :∂ẋ_∂u, dx_refs, u_refs, u, d̄x; accu = ū) c.solution.evals_∂ẋ_∂u += 1 end if parameters - vjp!(c, :∂ẋ_∂p, dx_refs, p_refs, p, d̄x; accu=p̄) + vjp!(c, :∂ẋ_∂p, dx_refs, p_refs, p, d̄x; accu = p̄) c.solution.evals_∂ẋ_∂p += 1 end if times && c.fmu.executionConfig.eval_t_gradients - vgp!(c, :∂ẋ_∂t, dx_refs, :time, t, d̄x; accu=t̄) + vgp!(c, :∂ẋ_∂t, dx_refs, :time, t, d̄x; accu = t̄) c.solution.evals_∂ẋ_∂t += 1 end end - if outputs + if outputs if states - vjp!(c, :∂y_∂x, y_refs, x_refs, x, ȳ; accu=x̄) + vjp!(c, :∂y_∂x, y_refs, x_refs, x, ȳ; accu = x̄) c.solution.evals_∂y_∂x += 1 end - + if inputs - vjp!(c, :∂y_∂u, y_refs, u_refs, u, ȳ; accu=ū) + vjp!(c, :∂y_∂u, y_refs, u_refs, u, ȳ; accu = ū) c.solution.evals_∂y_∂u += 1 end if parameters - vjp!(c, :∂y_∂p, y_refs, p_refs, p, ȳ; accu=p̄) + vjp!(c, :∂y_∂p, y_refs, p_refs, p, ȳ; accu = p̄) c.solution.evals_∂y_∂p += 1 end if times && c.fmu.executionConfig.eval_t_gradients - vgp!(c, :∂y_∂t, y_refs, :time, t, ȳ; accu=t̄) + vgp!(c, :∂y_∂t, y_refs, :time, t, ȳ; accu = t̄) c.solution.evals_∂y_∂t += 1 end end if eventIndicators if states - vjp!(c, :∂e_∂x, (:indicators, ec_idcs), x_refs, x, ēc; accu=x̄) + vjp!(c, :∂e_∂x, (:indicators, ec_idcs), x_refs, x, ēc; accu = x̄) c.solution.evals_∂e_∂x += 1 end if inputs - vjp!(c, :∂e_∂u, (:indicators, ec_idcs), u_refs, u, ēc; accu=ū) + vjp!(c, :∂e_∂u, (:indicators, ec_idcs), u_refs, u, ēc; accu = ū) c.solution.evals_∂e_∂u += 1 end if parameters - vjp!(c, :∂e_∂p, (:indicators, ec_idcs), p_refs, p, ēc; accu=p̄) + vjp!(c, :∂e_∂p, (:indicators, ec_idcs), p_refs, p, ēc; accu = p̄) c.solution.evals_∂e_∂p += 1 end if times && c.fmu.executionConfig.eval_t_gradients - vgp!(c, :∂e_∂t, (:indicators, ec_idcs), :time, t, ēc; accu=t̄) + vgp!(c, :∂e_∂t, (:indicators, ec_idcs), :time, t, ēc; accu = t̄) c.solution.evals_∂e_∂t += 1 end end @@ -521,9 +583,24 @@ function ChainRulesCore.rrule(::typeof(FMIBase.eval!), ēc = zeros(length(ec)) # ZeroTangent() # copy(ec) # @debug "pullback on d̄x, ȳ, ēc = $(d̄x), $(ȳ), $(ēc)\nt= $(t)s\nx=$(x)\ndx=$(dx)\n$((x̄, ū, p̄, t̄))" - + # [ToDo] This needs to be a tuple... but this prevents pre-allocation... - return (f̄, c̄Ref, d̄x, d̄x_refs, ȳ, ȳ_refs, x̄, ū, ū_refs, p̄, p̄_refs, ēc, ēc_idcs, t̄) + return ( + f̄, + c̄Ref, + d̄x, + d̄x_refs, + ȳ, + ȳ_refs, + x̄, + ū, + ū_refs, + p̄, + p̄_refs, + ēc, + ēc_idcs, + t̄, + ) end @debug "rrule end: $((Ω, eval_pullback))" @@ -532,474 +609,538 @@ function ChainRulesCore.rrule(::typeof(FMIBase.eval!), end # dx, y, x, u, p, ec, t -@ForwardDiff_frule FMIBase.eval!(cRef::UInt64, - dx ::AbstractVector{<:ForwardDiff.Dual}, +@ForwardDiff_frule FMIBase.eval!( + cRef::UInt64, + dx::AbstractVector{<:ForwardDiff.Dual}, dx_refs::AbstractVector{<:fmiValueReference}, - y ::AbstractVector{<:ForwardDiff.Dual}, + y::AbstractVector{<:ForwardDiff.Dual}, y_refs::AbstractVector{<:fmiValueReference}, - x ::AbstractVector{<:ForwardDiff.Dual}, - u ::AbstractVector{<:ForwardDiff.Dual}, + x::AbstractVector{<:ForwardDiff.Dual}, + u::AbstractVector{<:ForwardDiff.Dual}, u_refs::AbstractVector{<:fmiValueReference}, - p ::AbstractVector{<:ForwardDiff.Dual}, + p::AbstractVector{<:ForwardDiff.Dual}, p_refs::AbstractVector{<:fmiValueReference}, - ec ::AbstractVector{<:ForwardDiff.Dual}, + ec::AbstractVector{<:ForwardDiff.Dual}, ec_idcs::AbstractVector{<:fmiValueReference}, - t ::ForwardDiff.Dual) + t::ForwardDiff.Dual, +) -@grad_from_chainrules FMIBase.eval!(cRef::UInt64, - dx ::AbstractVector{<:ReverseDiff.TrackedReal}, +@grad_from_chainrules FMIBase.eval!( + cRef::UInt64, + dx::AbstractVector{<:ReverseDiff.TrackedReal}, dx_refs::AbstractVector{<:fmiValueReference}, - y ::AbstractVector{<:ReverseDiff.TrackedReal}, + y::AbstractVector{<:ReverseDiff.TrackedReal}, y_refs::AbstractVector{<:UInt32}, - x ::AbstractVector{<:ReverseDiff.TrackedReal}, - u ::AbstractVector{<:ReverseDiff.TrackedReal}, + x::AbstractVector{<:ReverseDiff.TrackedReal}, + u::AbstractVector{<:ReverseDiff.TrackedReal}, u_refs::AbstractVector{<:UInt32}, - p ::AbstractVector{<:ReverseDiff.TrackedReal}, + p::AbstractVector{<:ReverseDiff.TrackedReal}, p_refs::AbstractVector{<:UInt32}, - ec ::AbstractVector{<:ReverseDiff.TrackedReal}, + ec::AbstractVector{<:ReverseDiff.TrackedReal}, ec_idcs::AbstractVector{<:fmiValueReference}, - t ::ReverseDiff.TrackedReal) + t::ReverseDiff.TrackedReal, +) # dx, y, x, u, t -@ForwardDiff_frule FMIBase.eval!(cRef::UInt64, - dx ::AbstractVector{<:ForwardDiff.Dual}, +@ForwardDiff_frule FMIBase.eval!( + cRef::UInt64, + dx::AbstractVector{<:ForwardDiff.Dual}, dx_refs::AbstractVector{<:fmiValueReference}, - y ::AbstractVector{<:ForwardDiff.Dual}, + y::AbstractVector{<:ForwardDiff.Dual}, y_refs::AbstractVector{<:fmiValueReference}, - x ::AbstractVector{<:ForwardDiff.Dual}, - u ::AbstractVector{<:ForwardDiff.Dual}, + x::AbstractVector{<:ForwardDiff.Dual}, + u::AbstractVector{<:ForwardDiff.Dual}, u_refs::AbstractVector{<:fmiValueReference}, - p ::AbstractVector{<:Real}, + p::AbstractVector{<:Real}, p_refs::AbstractVector{<:fmiValueReference}, - ec ::AbstractVector{<:Real}, + ec::AbstractVector{<:Real}, ec_idcs::AbstractVector{<:fmiValueReference}, - t ::ForwardDiff.Dual) + t::ForwardDiff.Dual, +) -@grad_from_chainrules FMIBase.eval!(cRef::UInt64, - dx ::AbstractVector{<:ReverseDiff.TrackedReal}, +@grad_from_chainrules FMIBase.eval!( + cRef::UInt64, + dx::AbstractVector{<:ReverseDiff.TrackedReal}, dx_refs::AbstractVector{<:fmiValueReference}, - y ::AbstractVector{<:ReverseDiff.TrackedReal}, + y::AbstractVector{<:ReverseDiff.TrackedReal}, y_refs::AbstractVector{<:UInt32}, - x ::AbstractVector{<:ReverseDiff.TrackedReal}, - u ::AbstractVector{<:ReverseDiff.TrackedReal}, + x::AbstractVector{<:ReverseDiff.TrackedReal}, + u::AbstractVector{<:ReverseDiff.TrackedReal}, u_refs::AbstractVector{<:UInt32}, - p ::AbstractVector{<:Real}, + p::AbstractVector{<:Real}, p_refs::AbstractVector{<:UInt32}, - ec ::AbstractVector{<:Real}, + ec::AbstractVector{<:Real}, ec_idcs::AbstractVector{<:fmiValueReference}, - t ::ReverseDiff.TrackedReal) + t::ReverseDiff.TrackedReal, +) # x, u -@ForwardDiff_frule FMIBase.eval!(cRef::UInt64, - dx ::AbstractVector{<:Real}, +@ForwardDiff_frule FMIBase.eval!( + cRef::UInt64, + dx::AbstractVector{<:Real}, dx_refs::AbstractVector{<:fmiValueReference}, - y ::AbstractVector{<:Real}, + y::AbstractVector{<:Real}, y_refs::AbstractVector{<:fmiValueReference}, - x ::AbstractVector{<:ForwardDiff.Dual}, - u ::AbstractVector{<:ForwardDiff.Dual}, + x::AbstractVector{<:ForwardDiff.Dual}, + u::AbstractVector{<:ForwardDiff.Dual}, u_refs::AbstractVector{<:fmiValueReference}, - p ::AbstractVector{<:Real}, + p::AbstractVector{<:Real}, p_refs::AbstractVector{<:fmiValueReference}, - ec ::AbstractVector{<:Real}, + ec::AbstractVector{<:Real}, ec_idcs::AbstractVector{<:fmiValueReference}, - t ::Real) + t::Real, +) -@grad_from_chainrules FMIBase.eval!(cRef::UInt64, - dx ::AbstractVector{<:Real}, +@grad_from_chainrules FMIBase.eval!( + cRef::UInt64, + dx::AbstractVector{<:Real}, dx_refs::AbstractVector{<:fmiValueReference}, - y ::AbstractVector{<:Real}, + y::AbstractVector{<:Real}, y_refs::AbstractVector{<:UInt32}, - x ::AbstractVector{<:ReverseDiff.TrackedReal}, - u ::AbstractVector{<:ReverseDiff.TrackedReal}, + x::AbstractVector{<:ReverseDiff.TrackedReal}, + u::AbstractVector{<:ReverseDiff.TrackedReal}, u_refs::AbstractVector{<:UInt32}, - p ::AbstractVector{<:Real}, + p::AbstractVector{<:Real}, p_refs::AbstractVector{<:UInt32}, - ec ::AbstractVector{<:Real}, + ec::AbstractVector{<:Real}, ec_idcs::AbstractVector{<:fmiValueReference}, - t ::Real) + t::Real, +) # x, p -@ForwardDiff_frule FMIBase.eval!(cRef::UInt64, - dx ::AbstractVector{<:Real}, +@ForwardDiff_frule FMIBase.eval!( + cRef::UInt64, + dx::AbstractVector{<:Real}, dx_refs::AbstractVector{<:fmiValueReference}, - y ::AbstractVector{<:Real}, + y::AbstractVector{<:Real}, y_refs::AbstractVector{<:fmiValueReference}, - x ::AbstractVector{<:ForwardDiff.Dual}, - u ::AbstractVector{<:Real}, + x::AbstractVector{<:ForwardDiff.Dual}, + u::AbstractVector{<:Real}, u_refs::AbstractVector{<:fmiValueReference}, - p ::AbstractVector{<:ForwardDiff.Dual}, + p::AbstractVector{<:ForwardDiff.Dual}, p_refs::AbstractVector{<:fmiValueReference}, - ec ::AbstractVector{<:Real}, + ec::AbstractVector{<:Real}, ec_idcs::AbstractVector{<:fmiValueReference}, - t ::Real) + t::Real, +) -@grad_from_chainrules FMIBase.eval!(cRef::UInt64, - dx ::AbstractVector{<:Real}, +@grad_from_chainrules FMIBase.eval!( + cRef::UInt64, + dx::AbstractVector{<:Real}, dx_refs::AbstractVector{<:fmiValueReference}, - y ::AbstractVector{<:Real}, + y::AbstractVector{<:Real}, y_refs::AbstractVector{<:UInt32}, - x ::AbstractVector{<:ReverseDiff.TrackedReal}, - u ::AbstractVector{<:Real}, + x::AbstractVector{<:ReverseDiff.TrackedReal}, + u::AbstractVector{<:Real}, u_refs::AbstractVector{<:UInt32}, - p ::AbstractVector{<:ReverseDiff.TrackedReal}, + p::AbstractVector{<:ReverseDiff.TrackedReal}, p_refs::AbstractVector{<:UInt32}, - ec ::AbstractVector{<:Real}, + ec::AbstractVector{<:Real}, ec_idcs::AbstractVector{<:fmiValueReference}, - t ::Real) + t::Real, +) # t -@ForwardDiff_frule FMIBase.eval!(cRef::UInt64, - dx ::AbstractVector{<:Real}, +@ForwardDiff_frule FMIBase.eval!( + cRef::UInt64, + dx::AbstractVector{<:Real}, dx_refs::AbstractVector{<:fmiValueReference}, - y ::AbstractVector{<:Real}, + y::AbstractVector{<:Real}, y_refs::AbstractVector{<:fmiValueReference}, - x ::AbstractVector{<:Real}, - u ::AbstractVector{<:Real}, + x::AbstractVector{<:Real}, + u::AbstractVector{<:Real}, u_refs::AbstractVector{<:fmiValueReference}, - p ::AbstractVector{<:Real}, + p::AbstractVector{<:Real}, p_refs::AbstractVector{<:fmiValueReference}, - ec ::AbstractVector{<:Real}, + ec::AbstractVector{<:Real}, ec_idcs::AbstractVector{<:fmiValueReference}, - t ::ForwardDiff.Dual) + t::ForwardDiff.Dual, +) -@grad_from_chainrules FMIBase.eval!(cRef::UInt64, - dx ::AbstractVector{<:Real}, +@grad_from_chainrules FMIBase.eval!( + cRef::UInt64, + dx::AbstractVector{<:Real}, dx_refs::AbstractVector{<:fmiValueReference}, - y ::AbstractVector{<:Real}, + y::AbstractVector{<:Real}, y_refs::AbstractVector{<:UInt32}, - x ::AbstractVector{<:Real}, - u ::AbstractVector{<:Real}, + x::AbstractVector{<:Real}, + u::AbstractVector{<:Real}, u_refs::AbstractVector{<:UInt32}, - p ::AbstractVector{<:Real}, + p::AbstractVector{<:Real}, p_refs::AbstractVector{<:UInt32}, - ec ::AbstractVector{<:Real}, + ec::AbstractVector{<:Real}, ec_idcs::AbstractVector{<:fmiValueReference}, - t ::ReverseDiff.TrackedReal) + t::ReverseDiff.TrackedReal, +) # x -@ForwardDiff_frule FMIBase.eval!(cRef::UInt64, - dx ::AbstractVector{<:Real}, +@ForwardDiff_frule FMIBase.eval!( + cRef::UInt64, + dx::AbstractVector{<:Real}, dx_refs::AbstractVector{<:fmiValueReference}, - y ::AbstractVector{<:Real}, + y::AbstractVector{<:Real}, y_refs::AbstractVector{<:fmiValueReference}, - x ::AbstractVector{<:ForwardDiff.Dual}, - u ::AbstractVector{<:Real}, + x::AbstractVector{<:ForwardDiff.Dual}, + u::AbstractVector{<:Real}, u_refs::AbstractVector{<:fmiValueReference}, - p ::AbstractVector{<:Real}, + p::AbstractVector{<:Real}, p_refs::AbstractVector{<:fmiValueReference}, - ec ::AbstractVector{<:Real}, + ec::AbstractVector{<:Real}, ec_idcs::AbstractVector{<:fmiValueReference}, - t ::Real) + t::Real, +) -@grad_from_chainrules FMIBase.eval!(cRef::UInt64, - dx ::AbstractVector{<:Real}, +@grad_from_chainrules FMIBase.eval!( + cRef::UInt64, + dx::AbstractVector{<:Real}, dx_refs::AbstractVector{<:fmiValueReference}, - y ::AbstractVector{<:Real}, + y::AbstractVector{<:Real}, y_refs::AbstractVector{<:UInt32}, - x ::AbstractVector{<:ReverseDiff.TrackedReal}, - u ::AbstractVector{<:Real}, + x::AbstractVector{<:ReverseDiff.TrackedReal}, + u::AbstractVector{<:Real}, u_refs::AbstractVector{<:UInt32}, - p ::AbstractVector{<:Real}, + p::AbstractVector{<:Real}, p_refs::AbstractVector{<:UInt32}, - ec ::AbstractVector{<:Real}, + ec::AbstractVector{<:Real}, ec_idcs::AbstractVector{<:fmiValueReference}, - t ::Real) + t::Real, +) # u -@ForwardDiff_frule FMIBase.eval!(cRef::UInt64, - dx ::AbstractVector{<:Real}, +@ForwardDiff_frule FMIBase.eval!( + cRef::UInt64, + dx::AbstractVector{<:Real}, dx_refs::AbstractVector{<:fmiValueReference}, - y ::AbstractVector{<:Real}, + y::AbstractVector{<:Real}, y_refs::AbstractVector{<:fmiValueReference}, - x ::AbstractVector{<:Real}, - u ::AbstractVector{<:ForwardDiff.Dual}, + x::AbstractVector{<:Real}, + u::AbstractVector{<:ForwardDiff.Dual}, u_refs::AbstractVector{<:fmiValueReference}, - p ::AbstractVector{<:Real}, + p::AbstractVector{<:Real}, p_refs::AbstractVector{<:fmiValueReference}, - ec ::AbstractVector{<:Real}, + ec::AbstractVector{<:Real}, ec_idcs::AbstractVector{<:fmiValueReference}, - t ::Real) + t::Real, +) -@grad_from_chainrules FMIBase.eval!(cRef::UInt64, - dx ::AbstractVector{<:Real}, +@grad_from_chainrules FMIBase.eval!( + cRef::UInt64, + dx::AbstractVector{<:Real}, dx_refs::AbstractVector{<:fmiValueReference}, - y ::AbstractVector{<:Real}, + y::AbstractVector{<:Real}, y_refs::AbstractVector{<:UInt32}, - x ::AbstractVector{<:Real}, - u ::AbstractVector{<:ReverseDiff.TrackedReal}, + x::AbstractVector{<:Real}, + u::AbstractVector{<:ReverseDiff.TrackedReal}, u_refs::AbstractVector{<:UInt32}, - p ::AbstractVector{<:Real}, + p::AbstractVector{<:Real}, p_refs::AbstractVector{<:UInt32}, - ec ::AbstractVector{<:Real}, + ec::AbstractVector{<:Real}, ec_idcs::AbstractVector{<:fmiValueReference}, - t ::Real) + t::Real, +) # p -@ForwardDiff_frule FMIBase.eval!(cRef::UInt64, - dx ::AbstractVector{<:Real}, +@ForwardDiff_frule FMIBase.eval!( + cRef::UInt64, + dx::AbstractVector{<:Real}, dx_refs::AbstractVector{<:fmiValueReference}, - y ::AbstractVector{<:Real}, + y::AbstractVector{<:Real}, y_refs::AbstractVector{<:fmiValueReference}, - x ::AbstractVector{<:Real}, - u ::AbstractVector{<:Real}, + x::AbstractVector{<:Real}, + u::AbstractVector{<:Real}, u_refs::AbstractVector{<:fmiValueReference}, - p ::AbstractVector{<:ForwardDiff.Dual}, + p::AbstractVector{<:ForwardDiff.Dual}, p_refs::AbstractVector{<:fmiValueReference}, - ec ::AbstractVector{<:Real}, + ec::AbstractVector{<:Real}, ec_idcs::AbstractVector{<:fmiValueReference}, - t ::Real) + t::Real, +) -@grad_from_chainrules FMIBase.eval!(cRef::UInt64, - dx ::AbstractVector{<:Real}, +@grad_from_chainrules FMIBase.eval!( + cRef::UInt64, + dx::AbstractVector{<:Real}, dx_refs::AbstractVector{<:fmiValueReference}, - y ::AbstractVector{<:Real}, + y::AbstractVector{<:Real}, y_refs::AbstractVector{<:UInt32}, - x ::AbstractVector{<:Real}, - u ::AbstractVector{<:Real}, + x::AbstractVector{<:Real}, + u::AbstractVector{<:Real}, u_refs::AbstractVector{<:UInt32}, - p ::AbstractVector{<:ReverseDiff.TrackedReal}, + p::AbstractVector{<:ReverseDiff.TrackedReal}, p_refs::AbstractVector{<:UInt32}, - ec ::AbstractVector{<:Real}, + ec::AbstractVector{<:Real}, ec_idcs::AbstractVector{<:fmiValueReference}, - t ::Real) + t::Real, +) # ec -@ForwardDiff_frule FMIBase.eval!(cRef::UInt64, - dx ::AbstractVector{<:Real}, +@ForwardDiff_frule FMIBase.eval!( + cRef::UInt64, + dx::AbstractVector{<:Real}, dx_refs::AbstractVector{<:fmiValueReference}, - y ::AbstractVector{<:Real}, + y::AbstractVector{<:Real}, y_refs::AbstractVector{<:fmiValueReference}, - x ::AbstractVector{<:Real}, - u ::AbstractVector{<:Real}, + x::AbstractVector{<:Real}, + u::AbstractVector{<:Real}, u_refs::AbstractVector{<:fmiValueReference}, - p ::AbstractVector{<:Real}, + p::AbstractVector{<:Real}, p_refs::AbstractVector{<:fmiValueReference}, - ec ::AbstractVector{<:ForwardDiff.Dual}, + ec::AbstractVector{<:ForwardDiff.Dual}, ec_idcs::AbstractVector{<:fmiValueReference}, - t ::Real) + t::Real, +) -@grad_from_chainrules FMIBase.eval!(cRef::UInt64, - dx ::AbstractVector{<:Real}, +@grad_from_chainrules FMIBase.eval!( + cRef::UInt64, + dx::AbstractVector{<:Real}, dx_refs::AbstractVector{<:fmiValueReference}, - y ::AbstractVector{<:Real}, + y::AbstractVector{<:Real}, y_refs::AbstractVector{<:UInt32}, - x ::AbstractVector{<:Real}, - u ::AbstractVector{<:Real}, + x::AbstractVector{<:Real}, + u::AbstractVector{<:Real}, u_refs::AbstractVector{<:UInt32}, - p ::AbstractVector{<:Real}, + p::AbstractVector{<:Real}, p_refs::AbstractVector{<:UInt32}, - ec ::AbstractVector{<:ReverseDiff.TrackedReal}, + ec::AbstractVector{<:ReverseDiff.TrackedReal}, ec_idcs::AbstractVector{<:fmiValueReference}, - t ::Real) + t::Real, +) # x, t -@ForwardDiff_frule FMIBase.eval!(cRef::UInt64, - dx ::AbstractVector{<:Real}, +@ForwardDiff_frule FMIBase.eval!( + cRef::UInt64, + dx::AbstractVector{<:Real}, dx_refs::AbstractVector{<:fmiValueReference}, - y ::AbstractVector{<:Real}, + y::AbstractVector{<:Real}, y_refs::AbstractVector{<:fmiValueReference}, - x ::AbstractVector{<:ForwardDiff.Dual}, - u ::AbstractVector{<:Real}, + x::AbstractVector{<:ForwardDiff.Dual}, + u::AbstractVector{<:Real}, u_refs::AbstractVector{<:fmiValueReference}, - p ::AbstractVector{<:Real}, + p::AbstractVector{<:Real}, p_refs::AbstractVector{<:fmiValueReference}, - ec ::AbstractVector{<:Real}, + ec::AbstractVector{<:Real}, ec_idcs::AbstractVector{<:fmiValueReference}, - t ::ForwardDiff.Dual) + t::ForwardDiff.Dual, +) -@grad_from_chainrules FMIBase.eval!(cRef::UInt64, - dx ::AbstractVector{<:Real}, +@grad_from_chainrules FMIBase.eval!( + cRef::UInt64, + dx::AbstractVector{<:Real}, dx_refs::AbstractVector{<:fmiValueReference}, - y ::AbstractVector{<:Real}, + y::AbstractVector{<:Real}, y_refs::AbstractVector{<:UInt32}, - x ::AbstractVector{<:ReverseDiff.TrackedReal}, - u ::AbstractVector{<:Real}, + x::AbstractVector{<:ReverseDiff.TrackedReal}, + u::AbstractVector{<:Real}, u_refs::AbstractVector{<:UInt32}, - p ::AbstractVector{<:Real}, + p::AbstractVector{<:Real}, p_refs::AbstractVector{<:UInt32}, - ec ::AbstractVector{<:Real}, + ec::AbstractVector{<:Real}, ec_idcs::AbstractVector{<:fmiValueReference}, - t ::ReverseDiff.TrackedReal) + t::ReverseDiff.TrackedReal, +) # x, ec, t -@ForwardDiff_frule FMIBase.eval!(cRef::UInt64, - dx ::AbstractVector{<:Real}, +@ForwardDiff_frule FMIBase.eval!( + cRef::UInt64, + dx::AbstractVector{<:Real}, dx_refs::AbstractVector{<:fmiValueReference}, - y ::AbstractVector{<:Real}, + y::AbstractVector{<:Real}, y_refs::AbstractVector{<:fmiValueReference}, - x ::AbstractVector{<:ForwardDiff.Dual}, - u ::AbstractVector{<:Real}, + x::AbstractVector{<:ForwardDiff.Dual}, + u::AbstractVector{<:Real}, u_refs::AbstractVector{<:fmiValueReference}, - p ::AbstractVector{<:Real}, + p::AbstractVector{<:Real}, p_refs::AbstractVector{<:fmiValueReference}, - ec ::AbstractVector{<:ForwardDiff.Dual}, + ec::AbstractVector{<:ForwardDiff.Dual}, ec_idcs::AbstractVector{<:fmiValueReference}, - t ::ForwardDiff.Dual) + t::ForwardDiff.Dual, +) -@grad_from_chainrules FMIBase.eval!(cRef::UInt64, - dx ::AbstractVector{<:Real}, +@grad_from_chainrules FMIBase.eval!( + cRef::UInt64, + dx::AbstractVector{<:Real}, dx_refs::AbstractVector{<:fmiValueReference}, - y ::AbstractVector{<:Real}, + y::AbstractVector{<:Real}, y_refs::AbstractVector{<:UInt32}, - x ::AbstractVector{<:ReverseDiff.TrackedReal}, - u ::AbstractVector{<:Real}, + x::AbstractVector{<:ReverseDiff.TrackedReal}, + u::AbstractVector{<:Real}, u_refs::AbstractVector{<:UInt32}, - p ::AbstractVector{<:Real}, + p::AbstractVector{<:Real}, p_refs::AbstractVector{<:UInt32}, - ec ::AbstractVector{<:ReverseDiff.TrackedReal}, + ec::AbstractVector{<:ReverseDiff.TrackedReal}, ec_idcs::AbstractVector{<:fmiValueReference}, - t ::ReverseDiff.TrackedReal) + t::ReverseDiff.TrackedReal, +) # ec, t -@ForwardDiff_frule FMIBase.eval!(cRef::UInt64, - dx ::AbstractVector{<:Real}, +@ForwardDiff_frule FMIBase.eval!( + cRef::UInt64, + dx::AbstractVector{<:Real}, dx_refs::AbstractVector{<:fmiValueReference}, - y ::AbstractVector{<:Real}, + y::AbstractVector{<:Real}, y_refs::AbstractVector{<:fmiValueReference}, - x ::AbstractVector{<:Real}, - u ::AbstractVector{<:Real}, + x::AbstractVector{<:Real}, + u::AbstractVector{<:Real}, u_refs::AbstractVector{<:fmiValueReference}, - p ::AbstractVector{<:Real}, + p::AbstractVector{<:Real}, p_refs::AbstractVector{<:fmiValueReference}, - ec ::AbstractVector{<:ForwardDiff.Dual}, + ec::AbstractVector{<:ForwardDiff.Dual}, ec_idcs::AbstractVector{<:fmiValueReference}, - t ::ForwardDiff.Dual) + t::ForwardDiff.Dual, +) -@grad_from_chainrules FMIBase.eval!(cRef::UInt64, - dx ::AbstractVector{<:Real}, +@grad_from_chainrules FMIBase.eval!( + cRef::UInt64, + dx::AbstractVector{<:Real}, dx_refs::AbstractVector{<:fmiValueReference}, - y ::AbstractVector{<:Real}, + y::AbstractVector{<:Real}, y_refs::AbstractVector{<:UInt32}, - x ::AbstractVector{<:Real}, - u ::AbstractVector{<:Real}, + x::AbstractVector{<:Real}, + u::AbstractVector{<:Real}, u_refs::AbstractVector{<:UInt32}, - p ::AbstractVector{<:Real}, + p::AbstractVector{<:Real}, p_refs::AbstractVector{<:UInt32}, - ec ::AbstractVector{<:ReverseDiff.TrackedReal}, + ec::AbstractVector{<:ReverseDiff.TrackedReal}, ec_idcs::AbstractVector{<:fmiValueReference}, - t ::ReverseDiff.TrackedReal) + t::ReverseDiff.TrackedReal, +) # x, ec -@ForwardDiff_frule FMIBase.eval!(cRef::UInt64, - dx ::AbstractVector{<:Real}, +@ForwardDiff_frule FMIBase.eval!( + cRef::UInt64, + dx::AbstractVector{<:Real}, dx_refs::AbstractVector{<:fmiValueReference}, - y ::AbstractVector{<:Real}, + y::AbstractVector{<:Real}, y_refs::AbstractVector{<:fmiValueReference}, - x ::AbstractVector{<:ForwardDiff.Dual}, - u ::AbstractVector{<:Real}, + x::AbstractVector{<:ForwardDiff.Dual}, + u::AbstractVector{<:Real}, u_refs::AbstractVector{<:fmiValueReference}, - p ::AbstractVector{<:Real}, + p::AbstractVector{<:Real}, p_refs::AbstractVector{<:fmiValueReference}, - ec ::AbstractVector{<:ForwardDiff.Dual}, + ec::AbstractVector{<:ForwardDiff.Dual}, ec_idcs::AbstractVector{<:fmiValueReference}, - t ::Real) + t::Real, +) -@grad_from_chainrules FMIBase.eval!(cRef::UInt64, - dx ::AbstractVector{<:Real}, +@grad_from_chainrules FMIBase.eval!( + cRef::UInt64, + dx::AbstractVector{<:Real}, dx_refs::AbstractVector{<:fmiValueReference}, - y ::AbstractVector{<:Real}, + y::AbstractVector{<:Real}, y_refs::AbstractVector{<:UInt32}, - x ::AbstractVector{<:ReverseDiff.TrackedReal}, - u ::AbstractVector{<:Real}, + x::AbstractVector{<:ReverseDiff.TrackedReal}, + u::AbstractVector{<:Real}, u_refs::AbstractVector{<:UInt32}, - p ::AbstractVector{<:Real}, + p::AbstractVector{<:Real}, p_refs::AbstractVector{<:UInt32}, - ec ::AbstractVector{<:ReverseDiff.TrackedReal}, + ec::AbstractVector{<:ReverseDiff.TrackedReal}, ec_idcs::AbstractVector{<:fmiValueReference}, - t ::Real) + t::Real, +) # x, p, t -@ForwardDiff_frule FMIBase.eval!(cRef::UInt64, - dx ::AbstractVector{<:Real}, +@ForwardDiff_frule FMIBase.eval!( + cRef::UInt64, + dx::AbstractVector{<:Real}, dx_refs::AbstractVector{<:fmiValueReference}, - y ::AbstractVector{<:Real}, + y::AbstractVector{<:Real}, y_refs::AbstractVector{<:fmiValueReference}, - x ::AbstractVector{<:ForwardDiff.Dual}, - u ::AbstractVector{<:Real}, + x::AbstractVector{<:ForwardDiff.Dual}, + u::AbstractVector{<:Real}, u_refs::AbstractVector{<:fmiValueReference}, - p ::AbstractVector{<:ForwardDiff.Dual}, + p::AbstractVector{<:ForwardDiff.Dual}, p_refs::AbstractVector{<:fmiValueReference}, - ec ::AbstractVector{<:Real}, + ec::AbstractVector{<:Real}, ec_idcs::AbstractVector{<:fmiValueReference}, - t ::ForwardDiff.Dual) + t::ForwardDiff.Dual, +) -@grad_from_chainrules FMIBase.eval!(cRef::UInt64, - dx ::AbstractVector{<:Real}, +@grad_from_chainrules FMIBase.eval!( + cRef::UInt64, + dx::AbstractVector{<:Real}, dx_refs::AbstractVector{<:fmiValueReference}, - y ::AbstractVector{<:Real}, + y::AbstractVector{<:Real}, y_refs::AbstractVector{<:UInt32}, - x ::AbstractVector{<:ReverseDiff.TrackedReal}, - u ::AbstractVector{<:Real}, + x::AbstractVector{<:ReverseDiff.TrackedReal}, + u::AbstractVector{<:Real}, u_refs::AbstractVector{<:UInt32}, - p ::AbstractVector{<:ReverseDiff.TrackedReal}, + p::AbstractVector{<:ReverseDiff.TrackedReal}, p_refs::AbstractVector{<:UInt32}, - ec ::AbstractVector{<:Real}, + ec::AbstractVector{<:Real}, ec_idcs::AbstractVector{<:fmiValueReference}, - t ::ReverseDiff.TrackedReal) + t::ReverseDiff.TrackedReal, +) # x, p, ec, t -@ForwardDiff_frule FMIBase.eval!(cRef::UInt64, - dx ::AbstractVector{<:Real}, +@ForwardDiff_frule FMIBase.eval!( + cRef::UInt64, + dx::AbstractVector{<:Real}, dx_refs::AbstractVector{<:fmiValueReference}, - y ::AbstractVector{<:Real}, + y::AbstractVector{<:Real}, y_refs::AbstractVector{<:fmiValueReference}, - x ::AbstractVector{<:ForwardDiff.Dual}, - u ::AbstractVector{<:Real}, + x::AbstractVector{<:ForwardDiff.Dual}, + u::AbstractVector{<:Real}, u_refs::AbstractVector{<:fmiValueReference}, - p ::AbstractVector{<:ForwardDiff.Dual}, + p::AbstractVector{<:ForwardDiff.Dual}, p_refs::AbstractVector{<:fmiValueReference}, - ec ::AbstractVector{<:ForwardDiff.Dual}, + ec::AbstractVector{<:ForwardDiff.Dual}, ec_idcs::AbstractVector{<:fmiValueReference}, - t ::ForwardDiff.Dual) + t::ForwardDiff.Dual, +) -@grad_from_chainrules FMIBase.eval!(cRef::UInt64, - dx ::AbstractVector{<:Real}, +@grad_from_chainrules FMIBase.eval!( + cRef::UInt64, + dx::AbstractVector{<:Real}, dx_refs::AbstractVector{<:fmiValueReference}, - y ::AbstractVector{<:Real}, + y::AbstractVector{<:Real}, y_refs::AbstractVector{<:UInt32}, - x ::AbstractVector{<:ReverseDiff.TrackedReal}, - u ::AbstractVector{<:Real}, + x::AbstractVector{<:ReverseDiff.TrackedReal}, + u::AbstractVector{<:Real}, u_refs::AbstractVector{<:UInt32}, - p ::AbstractVector{<:ReverseDiff.TrackedReal}, + p::AbstractVector{<:ReverseDiff.TrackedReal}, p_refs::AbstractVector{<:UInt32}, - ec ::AbstractVector{<:ReverseDiff.TrackedReal}, + ec::AbstractVector{<:ReverseDiff.TrackedReal}, ec_idcs::AbstractVector{<:fmiValueReference}, - t ::ReverseDiff.TrackedReal) + t::ReverseDiff.TrackedReal, +) # x, p, ec -@ForwardDiff_frule FMIBase.eval!(cRef::UInt64, - dx ::AbstractVector{<:Real}, +@ForwardDiff_frule FMIBase.eval!( + cRef::UInt64, + dx::AbstractVector{<:Real}, dx_refs::AbstractVector{<:fmiValueReference}, - y ::AbstractVector{<:Real}, + y::AbstractVector{<:Real}, y_refs::AbstractVector{<:fmiValueReference}, - x ::AbstractVector{<:ForwardDiff.Dual}, - u ::AbstractVector{<:Real}, + x::AbstractVector{<:ForwardDiff.Dual}, + u::AbstractVector{<:Real}, u_refs::AbstractVector{<:fmiValueReference}, - p ::AbstractVector{<:ForwardDiff.Dual}, + p::AbstractVector{<:ForwardDiff.Dual}, p_refs::AbstractVector{<:fmiValueReference}, - ec ::AbstractVector{<:ForwardDiff.Dual}, + ec::AbstractVector{<:ForwardDiff.Dual}, ec_idcs::AbstractVector{<:fmiValueReference}, - t ::Real) + t::Real, +) -@grad_from_chainrules FMIBase.eval!(cRef::UInt64, - dx ::AbstractVector{<:Real}, +@grad_from_chainrules FMIBase.eval!( + cRef::UInt64, + dx::AbstractVector{<:Real}, dx_refs::AbstractVector{<:fmiValueReference}, - y ::AbstractVector{<:Real}, + y::AbstractVector{<:Real}, y_refs::AbstractVector{<:UInt32}, - x ::AbstractVector{<:ReverseDiff.TrackedReal}, - u ::AbstractVector{<:Real}, + x::AbstractVector{<:ReverseDiff.TrackedReal}, + u::AbstractVector{<:Real}, u_refs::AbstractVector{<:UInt32}, - p ::AbstractVector{<:ReverseDiff.TrackedReal}, + p::AbstractVector{<:ReverseDiff.TrackedReal}, p_refs::AbstractVector{<:UInt32}, - ec ::AbstractVector{<:ReverseDiff.TrackedReal}, + ec::AbstractVector{<:ReverseDiff.TrackedReal}, ec_idcs::AbstractVector{<:fmiValueReference}, - t ::Real) + t::Real, +) # FiniteDiff Jacobians abstract type FMUSensitivities end -mutable struct FMUJacobian{C, T, F} <: FMUSensitivities +mutable struct FMUJacobian{C,T,F} <: FMUSensitivities valid::Bool colored::Bool instance::C @@ -1008,11 +1149,11 @@ mutable struct FMUJacobian{C, T, F} <: FMUSensitivities jvp::Vector{T} vjp::Vector{T} - f_refs::Union{Vector{UInt32}, Tuple{Symbol, Vector{UInt32}}} - x_refs::Union{Vector{UInt32}, Symbol} - f_refs_set::Union{Set, Nothing} + f_refs::Union{Vector{UInt32},Tuple{Symbol,Vector{UInt32}}} + x_refs::Union{Vector{UInt32},Symbol} + f_refs_set::Union{Set,Nothing} - f::F + f::F #cache::FiniteDiff.JacobianCache #colors:: @@ -1020,7 +1161,11 @@ mutable struct FMUJacobian{C, T, F} <: FMUSensitivities validations::Int colorings::Int - function FMUJacobian{T}(instance::C, f_refs::Union{Vector{UInt32}, Tuple{Symbol, Vector{UInt32}}}, x_refs::Union{Vector{UInt32}, Symbol}) where {C, T} + function FMUJacobian{T}( + instance::C, + f_refs::Union{Vector{UInt32},Tuple{Symbol,Vector{UInt32}}}, + x_refs::Union{Vector{UInt32},Symbol}, + ) where {C,T} @assert !isa(f_refs, Tuple) || f_refs[1] == :indicators "`f_refs` is Tuple, it must be `:indicators`" @assert !isa(x_refs, Symbol) || x_refs == :time "`x_refs` is Symbol, it must be `:time`" @@ -1043,28 +1188,28 @@ mutable struct FMUJacobian{C, T, F} <: FMUSensitivities F = typeof(f) - inst = new{C, T, F}() + inst = new{C,T,F}() inst.f = f inst.instance = instance inst.f_refs = f_refs inst.f_refs_set = f_refs_set inst.x_refs = x_refs - + inst.mtx = zeros(T, f_len, x_len) inst.jvp = zeros(T, f_len) inst.vjp = zeros(T, x_len) - + inst.valid = false inst.validations = 0 inst.colored = false inst.colorings = 0 - + return inst end -end +end -mutable struct FMUGradient{C, T, F} <: FMUSensitivities +mutable struct FMUGradient{C,T,F} <: FMUSensitivities valid::Bool colored::Bool instance::C @@ -1073,11 +1218,11 @@ mutable struct FMUGradient{C, T, F} <: FMUSensitivities gvp::Vector{T} vgp::Vector{T} - f_refs::Union{Vector{UInt32}, Tuple{Symbol, Vector{UInt32}}} - x_refs::Union{Vector{UInt32}, Symbol} - f_refs_set::Union{Set, Nothing} + f_refs::Union{Vector{UInt32},Tuple{Symbol,Vector{UInt32}}} + x_refs::Union{Vector{UInt32},Symbol} + f_refs_set::Union{Set,Nothing} - f::F + f::F #cache::FiniteDiff.GradientCache #colors:: @@ -1085,7 +1230,11 @@ mutable struct FMUGradient{C, T, F} <: FMUSensitivities validations::Int colorings::Int - function FMUGradient{T}(instance::C, f_refs::Union{Vector{UInt32}, Tuple{Symbol, Vector{UInt32}}}, x_refs::Union{UInt32, Symbol}) where {C, T} + function FMUGradient{T}( + instance::C, + f_refs::Union{Vector{UInt32},Tuple{Symbol,Vector{UInt32}}}, + x_refs::Union{UInt32,Symbol}, + ) where {C,T} @assert !isa(f_refs, Tuple) || f_refs[1] == :indicators "`f_refs` is Tuple, it must be `:indicators`" @assert !isa(x_refs, Symbol) || x_refs == :time "`x_refs` is Symbol, it must be `:time`" @@ -1106,13 +1255,13 @@ mutable struct FMUGradient{C, T, F} <: FMUSensitivities F = typeof(f) - inst = new{C, T, F}() + inst = new{C,T,F}() inst.f = f inst.instance = instance inst.f_refs = f_refs inst.f_refs_set = f_refs_set inst.x_refs = x_refs - + inst.vec = zeros(T, f_len) inst.gvp = zeros(T, f_len) inst.vgp = zeros(T, x_len) @@ -1121,62 +1270,62 @@ mutable struct FMUGradient{C, T, F} <: FMUSensitivities inst.validations = 0 inst.colored = false inst.colorings = 0 - + return inst end -end +end function f_∂v_∂v(jac::FMUJacobian, dx, x) - setReal(jac.instance, jac.x_refs, x; track=false) + setReal(jac.instance, jac.x_refs, x; track = false) getReal!(jac.instance, jac.f_refs, dx) return dx end function f_∂e_∂v(jac::FMUJacobian, dx, x) - setReal(jac.instance, jac.x_refs, x; track=false) + setReal(jac.instance, jac.x_refs, x; track = false) getEventIndicators!(jac.instance, dx, jac.f_refs[2]) return dx end function f_∂e_∂t(jac::FMUGradient, dx, x) - setTime(jac.instance, x; track=false) + setTime(jac.instance, x; track = false) getEventIndicators!(jac.instance, dx, jac.f_refs[2]) return dx end function f_∂v_∂t(jac::FMUGradient, dx, x) - setTime(jac.instance, x; track=false) + setTime(jac.instance, x; track = false) getReal!(jac.instance, jac.f_refs, dx) return dx end function FMIBase.invalidate!(sens::FMUSensitivities) - sens.valid = false - return nothing + sens.valid = false + return nothing end function FMIBase.check_invalidate!(vrs, sens::FMUSensitivities) if !sens.valid - return + return end if isnothing(sens.f_refs_set) - return + return end for vr ∈ vrs - if vr ∈ sens.f_refs_set + if vr ∈ sens.f_refs_set invalidate!(sens) end end - return nothing + return nothing end function uncolor!(jac::FMUSensitivities) - jac.colored = false - return nothing + jac.colored = false + return nothing end function onehot!(seed, i::Integer) # [ToDo] this could be solved without allocations @@ -1190,59 +1339,95 @@ function validate!(jac::FMUJacobian, x::AbstractVector) rows = length(jac.f_refs) cols = length(jac.x_refs) - if jac.instance.fmu.executionConfig.sensitivity_strategy == :FMIDirectionalDerivative && providesDirectionalDerivatives(jac.instance.fmu) && !isa(jac.f_refs, Tuple) && !isa(jac.x_refs, Symbol) + if jac.instance.fmu.executionConfig.sensitivity_strategy == :FMIDirectionalDerivative && + providesDirectionalDerivatives(jac.instance.fmu) && + !isa(jac.f_refs, Tuple) && + !isa(jac.x_refs, Symbol) # ToDo: use directional derivatives with sparsitiy information! # ToDo: Optimize allocation (onehot) # [Note] Jacobian is sampled column by column seed = zeros(getRealType(jac.instance), cols) - for i in 1:cols - getDirectionalDerivative!(jac.instance, jac.f_refs, jac.x_refs, onehot!(seed, i), view(jac.mtx, 1:rows, i)) + for i = 1:cols + getDirectionalDerivative!( + jac.instance, + jac.f_refs, + jac.x_refs, + onehot!(seed, i), + view(jac.mtx, 1:rows, i), + ) end - elseif jac.instance.fmu.executionConfig.sensitivity_strategy == :FMIAdjointDerivative && providesAdjointDerivatives(jac.instance.fmu) && !isa(jac.f_refs, Tuple) && !isa(jac.x_refs, Symbol) + elseif jac.instance.fmu.executionConfig.sensitivity_strategy == :FMIAdjointDerivative && + providesAdjointDerivatives(jac.instance.fmu) && + !isa(jac.f_refs, Tuple) && + !isa(jac.x_refs, Symbol) # ToDo: use directional derivatives with sparsitiy information! # ToDo: Optimize allocation (onehot) # [Note] Jacobian is sampled row by row seed = zeros(getRealType(jac.instance), rows) - for i in 1:rows - getAdjointDerivative!(jac.instance, jac.f_refs, jac.x_refs, onehot!(seed, i), view(jac.mtx, 1:cols, i)) + for i = 1:rows + getAdjointDerivative!( + jac.instance, + jac.f_refs, + jac.x_refs, + onehot!(seed, i), + view(jac.mtx, 1:cols, i), + ) end else #if jac.instance.fmu.executionConfig.sensitivity_strategy == :FiniteDiff # cache = FiniteDiff.JacobianCache(x) - FiniteDiff.finite_difference_jacobian!(jac.mtx, (_x, _dx) -> (jac.f(jac, _x, _dx)), x) # , cache) - # else - # @assert false "Unknown sensitivity strategy `$(jac.instance.fmu.executionConfig.sensitivity_strategy)`." + FiniteDiff.finite_difference_jacobian!( + jac.mtx, + (_x, _dx) -> (jac.f(jac, _x, _dx)), + x, + ) # , cache) + # else + # @assert false "Unknown sensitivity strategy `$(jac.instance.fmu.executionConfig.sensitivity_strategy)`." end jac.validations += 1 - jac.valid = true + jac.valid = true return nothing end function validate!(grad::FMUGradient, x::Real) - if grad.instance.fmu.executionConfig.sensitivity_strategy == :FMIDirectionalDerivative && providesDirectionalDerivatives(grad.instance.fmu) && !isa(grad.f_refs, Tuple) && !isa(grad.x_refs, Symbol) + if grad.instance.fmu.executionConfig.sensitivity_strategy == + :FMIDirectionalDerivative && + providesDirectionalDerivatives(grad.instance.fmu) && + !isa(grad.f_refs, Tuple) && + !isa(grad.x_refs, Symbol) # ToDo: use directional derivatives with sparsitiy information! - getDirectionalDerivative!(grad.instance, grad.f_refs, grad.x_refs, ones(length(jac.f_refs)), grad.vec) + getDirectionalDerivative!( + grad.instance, + grad.f_refs, + grad.x_refs, + ones(length(jac.f_refs)), + grad.vec, + ) else #if grad.instance.fmu.executionConfig.sensitivity_strategy == :FiniteDiff # cache = FiniteDiff.GradientCache(x) - FiniteDiff.finite_difference_gradient!(grad.vec, (_x, _dx) -> (grad.f(grad, _x, _dx)), x) # , cache) + FiniteDiff.finite_difference_gradient!( + grad.vec, + (_x, _dx) -> (grad.f(grad, _x, _dx)), + x, + ) # , cache) end grad.validations += 1 - grad.valid = true + grad.valid = true return nothing end - + function color!(sens::FMUSensitivities) # ToDo # colors = SparseDiffTools.matrix_colors(sparsejac) sens.colorings += 1 - sens.colored = true + sens.colored = true return nothing end @@ -1251,8 +1436,8 @@ function ref_length(ref::AbstractArray) end function ref_length(ref::Symbol) - if ref == :time - return 1 + if ref == :time + return 1 else @assert false "unknwon ref symbol: $(ref)" end @@ -1260,7 +1445,7 @@ end function ref_length(ref::Tuple) @assert length(ref) == 2 "tuple ref length is $(length(ref)) != 2" - if ref[1] == :indicators + if ref[1] == :indicators return length(ref[2]) else @assert false "unknwon tuple ref $(ref)" @@ -1270,11 +1455,11 @@ end function update!(jac::FMUJacobian, x) if size(jac.mtx) != (ref_length(jac.f_refs), ref_length(jac.x_refs)) - #if length(jac.mtx) != ref_length(jac.f_refs) * ref_length(jac.x_refs) # this is cheaper + #if length(jac.mtx) != ref_length(jac.f_refs) * ref_length(jac.x_refs) # this is cheaper jac.mtx = similar(jac.mtx, ref_length(jac.f_refs), ref_length(jac.x_refs)) jac.jvp = similar(jac.jvp, ref_length(jac.f_refs)) jac.vjp = similar(jac.vjp, ref_length(jac.x_refs)) - + jac.valid = false end @@ -1294,7 +1479,7 @@ function update!(gra::FMUGradient, x) gra.vec = similar(gra.vec, ref_length(jac.f_refs)) gra.gvp = similar(gra.gvp, ref_length(jac.f_refs)) gra.vgp = similar(gra.vgp, ref_length(jac.x_refs)) - + gra.valid = false end @@ -1308,29 +1493,29 @@ function update!(gra::FMUGradient, x) return nothing end -function jvp!(jac::FMUJacobian, x::AbstractVector, v::AbstractVector; jvp=jac.jvp) +function jvp!(jac::FMUJacobian, x::AbstractVector, v::AbstractVector; jvp = jac.jvp) FMISensitivity.update!(jac, x) #return jac.mtx * v mul!(jvp, jac.mtx, v) return nothing end -function vjp!(jac::FMUJacobian, x::AbstractVector, v::AbstractVector; vjp=jac.vjp) +function vjp!(jac::FMUJacobian, x::AbstractVector, v::AbstractVector; vjp = jac.vjp) FMISensitivity.update!(jac, x) #return jac.mtx' * v mul!(vjp, jac.mtx', v) return nothing end -function gvp!(grad::FMUGradient, x, v; gvp=grad.gvp) +function gvp!(grad::FMUGradient, x, v; gvp = grad.gvp) FMISensitivity.update!(grad, x) #return grad.vec * v mul!(gvp, grad.vec, v) return nothing end -function vgp!(grad::FMUGradient, x, v, vgp=grad.vgp) +function vgp!(grad::FMUGradient, x, v, vgp = grad.vgp) FMISensitivity.update!(grad, x) - mul!(vgp, grad.vec', v) + mul!(vgp, grad.vec', v) return nothing end diff --git a/src/utils.jl b/src/utils.jl index de5df04..70bb02b 100644 --- a/src/utils.jl +++ b/src/utils.jl @@ -11,4 +11,4 @@ function isZeroTangent(d::ZeroTangent) end function isZeroTangent(d::AbstractArray{<:ZeroTangent}) return true -end \ No newline at end of file +end diff --git a/test/jacobians_gradients.jl b/test/jacobians_gradients.jl index ba756a6..386a4c9 100644 --- a/test/jacobians_gradients.jl +++ b/test/jacobians_gradients.jl @@ -3,7 +3,7 @@ # Licensed under the MIT license. See LICENSE file in the project root for details. # -import FMISensitivity.ForwardDiff +import FMISensitivity.ForwardDiff import FMISensitivity.Zygote import FMISensitivity.ReverseDiff # import FMISensitivity.FiniteDiff @@ -11,7 +11,8 @@ import FMISensitivity.ReverseDiff using FMISensitivity.FMIBase using FMISensitivity.FMIBase.FMICore -using FMISensitivity.FMIBase: getContinuousStates, getReal, getRealType, getEventIndicators, getDirectionalDerivative +using FMISensitivity.FMIBase: + getContinuousStates, getReal, getRealType, getEventIndicators, getDirectionalDerivative CHECK_ZYGOTE = false @@ -22,7 +23,7 @@ c, fmu = getFMUStruct("SpringFrictionPendulumExtForce1D", :ME) fmu.executionConfig.eval_t_gradients = true x_refs = fmu.modelDescription.stateValueReferences -x = getContinuousStates(c) +x = getContinuousStates(c) dx_refs = c.fmu.modelDescription.derivativeValueReferences dx = getReal(c, dx_refs) u_refs = fmu.modelDescription.inputValueReferences @@ -34,7 +35,7 @@ p = getReal(c, p_refs) e = getEventIndicators(c) t = 0.0 -reset! = function(c::FMUInstance) +reset! = function (c::FMUInstance) c.solution.evals_∂ẋ_∂x = 0 c.solution.evals_∂ẋ_∂u = 0 c.solution.evals_∂ẋ_∂p = 0 @@ -56,78 +57,94 @@ reset! = function(c::FMUInstance) end # evaluation: set state -ydx = fmu(;x=x) +ydx = fmu(; x = x) @test length(ydx) == 0 # evaluation: set state, get state derivative -ydx = fmu(;x=x, dx_refs=:all) +ydx = fmu(; x = x, dx_refs = :all) @test length(ydx) == 2 # evaluation: set state and inputs -ydx = fmu(;x=x, u=u, u_refs=u_refs, dx_refs=:all) +ydx = fmu(; x = x, u = u, u_refs = u_refs, dx_refs = :all) @test length(ydx) == 2 # evaluation: set state and inputs, get outputs (in-place) -ydx = fmu(;x=x, u=u, u_refs=u_refs, y=y, y_refs=y_refs) +ydx = fmu(; x = x, u = u, u_refs = u_refs, y = y, y_refs = y_refs) @test length(ydx) == 2 # evaluation: set state and inputs, get state derivative and outputs (in-place) -ydx = fmu(;dx_refs=:all, x=x, u=u, u_refs=u_refs, y=y, y_refs=y_refs) +ydx = fmu(; dx_refs = :all, x = x, u = u, u_refs = u_refs, y = y, y_refs = y_refs) @test length(ydx) == 4 # evaluation: set state and inputs, parameters, get state derivative (in-place) and outputs (in-place) -ydx = fmu(;x=x, u=u, u_refs=u_refs, y=y, y_refs=y_refs, dx=dx, dx_refs=:all, p=p, p_refs=p_refs) +ydx = fmu(; + x = x, + u = u, + u_refs = u_refs, + y = y, + y_refs = y_refs, + dx = dx, + dx_refs = :all, + p = p, + p_refs = p_refs, +) @test length(ydx) == 4 # known results -atol= 1e-3 # 1e-7 +atol = 1e-3 # 1e-7 ∂ẋ_∂x = [0.0 1.0; -10.0 -0.05] ∂ẋ_∂u = [0.0; 1.0] -∂ẋ_∂p = [0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0; - 0.0375 0.0 0.0 10.0 0.6 10.0 0.0 0.0 0.0 5.0 -5.25 0.0] +∂ẋ_∂p = [ + 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 + 0.0375 0.0 0.0 10.0 0.6 10.0 0.0 0.0 0.0 5.0 -5.25 0.0 +] ∂y_∂x = [0.0 1.0; -10.0 -0.05] ∂y_∂u = [0.0; 1.0] -∂y_∂p = [0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0; - 0.0375 0.0 0.0 10.0 0.6 10.0 0.0 0.0 0.0 5.0 -5.25 0.0] +∂y_∂p = [ + 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 + 0.0375 0.0 0.0 10.0 0.6 10.0 0.0 0.0 0.0 5.0 -5.25 0.0 +] ∂ẋ_∂t = [0.0, 0.0] ∂y_∂t = [0.0, 0.0] -∂e_∂x = [0.0 0.0; - 0.0 0.0; - 1.0 0.0; - 1.0 0.0; - -10.0 -0.05; - -10.0 -0.05; - 0.0 0.0; - 0.0 0.0; - 0.0 0.0; - 0.0 0.0; - 0.0 1.0; - 0.0 1.0; - -10.0 -0.05; - -10.0 -0.05; - 0.0 0.0; - 0.0 0.0; - 0.0 0.0; - 0.0 0.0; - 0.0 0.0; - 0.0 0.0; - 0.0 0.0; - 0.0 0.0; - 0.0 0.0; - 0.0 0.0; - 0.0 0.0; - 0.0 0.0; - 0.0 0.0; - 0.0 0.0; - 1.0 0.0; - 1.0 0.0; - 1.0 0.0; - 1.0 0.0] +∂e_∂x = [ + 0.0 0.0 + 0.0 0.0 + 1.0 0.0 + 1.0 0.0 + -10.0 -0.05 + -10.0 -0.05 + 0.0 0.0 + 0.0 0.0 + 0.0 0.0 + 0.0 0.0 + 0.0 1.0 + 0.0 1.0 + -10.0 -0.05 + -10.0 -0.05 + 0.0 0.0 + 0.0 0.0 + 0.0 0.0 + 0.0 0.0 + 0.0 0.0 + 0.0 0.0 + 0.0 0.0 + 0.0 0.0 + 0.0 0.0 + 0.0 0.0 + 0.0 0.0 + 0.0 0.0 + 0.0 0.0 + 0.0 0.0 + 1.0 0.0 + 1.0 0.0 + 1.0 0.0 + 1.0 0.0 +] # Test build-in directional derivatives (slow) only for jacobian A fmu.executionConfig.JVPBuiltInDerivatives = true -_f = _x -> fmu(;x=_x, dx_refs=:all) +_f = _x -> fmu(; x = _x, dx_refs = :all) _f(x) j_fwd = ForwardDiff.jacobian(_f, x) j_rwd = ReverseDiff.jacobian(_f, x) @@ -135,9 +152,9 @@ j_zyg = CHECK_ZYGOTE ? Zygote.jacobian(_f, x)[1] : nothing # j_smp = sampleJacobian(c, fmu.modelDescription.derivativeValueReferences, fmu.modelDescription.stateValueReferences) # j_get = getJacobian(c, fmu.modelDescription.derivativeValueReferences, fmu.modelDescription.stateValueReferences) -@test isapprox(j_fwd, ∂ẋ_∂x; atol=atol) -@test isapprox(j_rwd, ∂ẋ_∂x; atol=atol) -@test CHECK_ZYGOTE ? isapprox(j_zyg, ∂ẋ_∂x; atol=atol) : true +@test isapprox(j_fwd, ∂ẋ_∂x; atol = atol) +@test isapprox(j_rwd, ∂ẋ_∂x; atol = atol) +@test CHECK_ZYGOTE ? isapprox(j_zyg, ∂ẋ_∂x; atol = atol) : true # @test isapprox(j_smp, ∂ẋ_∂x; atol=atol) # @test isapprox(j_get, ∂ẋ_∂x; atol=atol) @@ -147,15 +164,15 @@ fmu.executionConfig.JVPBuiltInDerivatives = false # Test build-in adjoint derivatives (slow) only for jacobian A fmu.executionConfig.VJPBuiltInDerivatives = true -_f = _x -> fmu(;x=_x, dx_refs=:all) +_f = _x -> fmu(; x = _x, dx_refs = :all) _f(x) j_fwd = ForwardDiff.jacobian(_f, x) j_rwd = ReverseDiff.jacobian(_f, x) j_zyg = CHECK_ZYGOTE ? Zygote.jacobian(_f, x)[1] : nothing -@test isapprox(j_fwd, ∂ẋ_∂x; atol=atol) -@test isapprox(j_rwd, ∂ẋ_∂x; atol=atol) -@test CHECK_ZYGOTE ? isapprox(j_zyg, ∂ẋ_∂x; atol=atol) : true +@test isapprox(j_fwd, ∂ẋ_∂x; atol = atol) +@test isapprox(j_rwd, ∂ẋ_∂x; atol = atol) +@test CHECK_ZYGOTE ? isapprox(j_zyg, ∂ẋ_∂x; atol = atol) : true # End: Test build-in derivatives (slow) only for jacobian A fmu.executionConfig.VJPBuiltInDerivatives = false @@ -177,7 +194,7 @@ fmu.executionConfig.VJPBuiltInDerivatives = false reset!(c) # Jacobian A=∂dx/∂x (out-of-plcae) -_f = _x -> fmu(;x=_x, dx_refs=:all) +_f = _x -> fmu(; x = _x, dx_refs = :all) _f(x) j_fwd = ForwardDiff.jacobian(_f, x) j_rwd = ReverseDiff.jacobian(_f, x) @@ -185,9 +202,9 @@ j_zyg = CHECK_ZYGOTE ? Zygote.jacobian(_f, x)[1] : nothing #j_smp = sampleJacobian(c, fmu.modelDescription.derivativeValueReferences, fmu.modelDescription.stateValueReferences) #j_get = getJacobian(c, fmu.modelDescription.derivativeValueReferences, fmu.modelDescription.stateValueReferences) -@test isapprox(j_fwd, ∂ẋ_∂x; atol=atol) -@test isapprox(j_rwd, ∂ẋ_∂x; atol=atol) -@test CHECK_ZYGOTE ? isapprox(j_zyg, ∂ẋ_∂x; atol=atol) : true +@test isapprox(j_fwd, ∂ẋ_∂x; atol = atol) +@test isapprox(j_rwd, ∂ẋ_∂x; atol = atol) +@test CHECK_ZYGOTE ? isapprox(j_zyg, ∂ẋ_∂x; atol = atol) : true #@test isapprox(j_smp, ∂ẋ_∂x; atol=atol) #@test isapprox(j_get, ∂ẋ_∂x; atol=atol) @@ -208,7 +225,7 @@ j_zyg = CHECK_ZYGOTE ? Zygote.jacobian(_f, x)[1] : nothing reset!(c) # Jacobian A=∂dx/∂x (in-plcae) -_f = _x -> fmu(;x=_x, dx=dx, dx_refs=:all) +_f = _x -> fmu(; x = _x, dx = dx, dx_refs = :all) _f(x) j_fwd = ForwardDiff.jacobian(_f, x) j_rwd = ReverseDiff.jacobian(_f, x) @@ -216,9 +233,9 @@ j_zyg = CHECK_ZYGOTE ? Zygote.jacobian(_f, x)[1] : nothing #j_smp = sampleJacobian(c, fmu.modelDescription.derivativeValueReferences, fmu.modelDescription.stateValueReferences) #j_get = getJacobian(c, fmu.modelDescription.derivativeValueReferences, fmu.modelDescription.stateValueReferences) -@test isapprox(j_fwd, ∂ẋ_∂x; atol=atol) -@test isapprox(j_rwd, ∂ẋ_∂x; atol=atol) -@test CHECK_ZYGOTE ? isapprox(j_zyg, ∂ẋ_∂x; atol=atol) : true +@test isapprox(j_fwd, ∂ẋ_∂x; atol = atol) +@test isapprox(j_rwd, ∂ẋ_∂x; atol = atol) +@test CHECK_ZYGOTE ? isapprox(j_zyg, ∂ẋ_∂x; atol = atol) : true #@test isapprox(j_smp, ∂ẋ_∂x; atol=atol) #@test isapprox(j_get, ∂ẋ_∂x; atol=atol) @@ -239,7 +256,7 @@ j_zyg = CHECK_ZYGOTE ? Zygote.jacobian(_f, x)[1] : nothing reset!(c) # Jacobian B=∂dx/∂u -_f = _u -> fmu(; u=_u, u_refs=u_refs, dx_refs=:all) +_f = _u -> fmu(; u = _u, u_refs = u_refs, dx_refs = :all) _f(u) j_fwd = ForwardDiff.jacobian(_f, u) j_rwd = ReverseDiff.jacobian(_f, u) @@ -247,9 +264,9 @@ j_zyg = CHECK_ZYGOTE ? Zygote.jacobian(_f, u)[1] : nothing #j_smp = fsampleJacobian(c, fmu.modelDescription.derivativeValueReferences, u_refs) #j_get = getJacobian(c, fmu.modelDescription.derivativeValueReferences, u_refs) -@test isapprox(j_fwd, ∂ẋ_∂u; atol=atol) -@test isapprox(j_rwd, ∂ẋ_∂u; atol=atol) -@test CHECK_ZYGOTE ? isapprox(j_zyg, ∂ẋ_∂u; atol=atol) : true +@test isapprox(j_fwd, ∂ẋ_∂u; atol = atol) +@test isapprox(j_rwd, ∂ẋ_∂u; atol = atol) +@test CHECK_ZYGOTE ? isapprox(j_zyg, ∂ẋ_∂u; atol = atol) : true #@test isapprox(j_smp, ∂ẋ_∂u; atol=atol) #@test isapprox(j_get, ∂ẋ_∂u; atol=atol) @@ -270,7 +287,7 @@ j_zyg = CHECK_ZYGOTE ? Zygote.jacobian(_f, u)[1] : nothing reset!(c) # Jacobian C=∂y/∂x (in-place) -_f = _x -> fmu(;x=_x, y_refs=y_refs) +_f = _x -> fmu(; x = _x, y_refs = y_refs) _f(x) j_fwd = ForwardDiff.jacobian(_f, x) j_rwd = ReverseDiff.jacobian(_f, x) @@ -278,9 +295,9 @@ j_zyg = CHECK_ZYGOTE ? Zygote.jacobian(_f, x)[1] : nothing #j_smp = sampleJacobian(c, y_refs, fmu.modelDescription.stateValueReferences) #j_get = getJacobian(c, y_refs, fmu.modelDescription.stateValueReferences) -@test isapprox(j_fwd, ∂y_∂x; atol=atol) -@test isapprox(j_rwd, ∂y_∂x; atol=atol) -@test CHECK_ZYGOTE ? isapprox(j_zyg, ∂y_∂x; atol=atol) : true +@test isapprox(j_fwd, ∂y_∂x; atol = atol) +@test isapprox(j_rwd, ∂y_∂x; atol = atol) +@test CHECK_ZYGOTE ? isapprox(j_zyg, ∂y_∂x; atol = atol) : true #@test isapprox(j_smp, ∂y_∂x; atol=atol) #@test isapprox(j_get, ∂y_∂x; atol=atol) @@ -301,7 +318,7 @@ j_zyg = CHECK_ZYGOTE ? Zygote.jacobian(_f, x)[1] : nothing reset!(c) # Jacobian D=∂y/∂u -_f = _u -> fmu(; u=_u, u_refs=u_refs, y_refs=y_refs) +_f = _u -> fmu(; u = _u, u_refs = u_refs, y_refs = y_refs) _f(u) j_fwd = ForwardDiff.jacobian(_f, u) j_rwd = ReverseDiff.jacobian(_f, u) @@ -309,9 +326,9 @@ j_zyg = CHECK_ZYGOTE ? Zygote.jacobian(_f, u)[1] : nothing #j_smp = sampleJacobian(c, y_refs, u_refs) #j_get = getJacobian(c, y_refs, u_refs) -@test isapprox(j_fwd, ∂y_∂u; atol=atol) -@test isapprox(j_rwd, ∂y_∂u; atol=atol) -@test CHECK_ZYGOTE ? isapprox(j_zyg, ∂y_∂u; atol=atol) : true +@test isapprox(j_fwd, ∂y_∂u; atol = atol) +@test isapprox(j_rwd, ∂y_∂u; atol = atol) +@test CHECK_ZYGOTE ? isapprox(j_zyg, ∂y_∂u; atol = atol) : true #@test isapprox(j_smp, ∂y_∂u; atol=atol) #@test isapprox(j_get, ∂y_∂u; atol=atol) @@ -332,12 +349,12 @@ j_zyg = CHECK_ZYGOTE ? Zygote.jacobian(_f, u)[1] : nothing reset!(c) # explicit time derivative ∂ẋ/∂t -_f = _t -> fmu(; t=_t, dx_refs=:all) +_f = _t -> fmu(; t = _t, dx_refs = :all) _f(t) j_fwd = ForwardDiff.derivative(_f, t) # ReverseDiff has no `derivative` function for scalars -_f = _t -> fmu(; t=_t[1], dx_refs=:all) +_f = _t -> fmu(; t = _t[1], dx_refs = :all) #j_rwd = ReverseDiff.jacobian(_f, [t]) @warn "ReverseDiff time gradient skipped." j_rwd = ∂ẋ_∂t @@ -345,9 +362,9 @@ c.solution.evals_∂ẋ_∂t += 2 j_zyg = CHECK_ZYGOTE ? Zygote.jacobian(_f, t)[1] : nothing -@test isapprox(j_fwd, ∂ẋ_∂t; atol=atol) -@test isapprox(j_rwd, ∂ẋ_∂t; atol=atol) -@test CHECK_ZYGOTE ? isapprox(j_zyg, ∂ẋ_∂t; atol=atol) : true +@test isapprox(j_fwd, ∂ẋ_∂t; atol = atol) +@test isapprox(j_rwd, ∂ẋ_∂t; atol = atol) +@test CHECK_ZYGOTE ? isapprox(j_zyg, ∂ẋ_∂t; atol = atol) : true @test c.solution.evals_∂ẋ_∂u == 0 @test c.solution.evals_∂ẋ_∂p == 0 @@ -366,12 +383,12 @@ j_zyg = CHECK_ZYGOTE ? Zygote.jacobian(_f, t)[1] : nothing reset!(c) # explicit time derivative ∂y/∂t -_f = _t -> fmu(; y_refs=y_refs, t=_t) +_f = _t -> fmu(; y_refs = y_refs, t = _t) _f(t) j_fwd = ForwardDiff.derivative(_f, t) # ReverseDiff has no `derivative` function for scalars -_f = _t -> fmu(; y_refs=y_refs, t=_t[1]) +_f = _t -> fmu(; y_refs = y_refs, t = _t[1]) #j_rwd = ReverseDiff.jacobian(_f, [t]) @warn "ReverseDiff time gradient skipped." j_rwd = ∂y_∂t @@ -379,9 +396,9 @@ c.solution.evals_∂y_∂t += 2 j_zyg = CHECK_ZYGOTE ? Zygote.jacobian(_f, t)[1] : nothing -@test isapprox(j_fwd, ∂y_∂t; atol=atol) -@test isapprox(j_rwd, ∂y_∂t; atol=atol) -@test CHECK_ZYGOTE ? isapprox(j_zyg, ∂y_∂t; atol=atol) : true +@test isapprox(j_fwd, ∂y_∂t; atol = atol) +@test isapprox(j_rwd, ∂y_∂t; atol = atol) +@test CHECK_ZYGOTE ? isapprox(j_zyg, ∂y_∂t; atol = atol) : true @test c.solution.evals_∂ẋ_∂x == 0 @test c.solution.evals_∂ẋ_∂u == 0 @@ -401,69 +418,69 @@ reset!(c) # Jacobian ∂ẋ/∂p #if FMU_SUPPORTS_PARAMETER_SAMPLING - _f = _p -> fmu(;p=_p, p_refs=p_refs, dx_refs=:all) - _f(p) - j_fwd = ForwardDiff.jacobian(_f, p) - j_rwd = ReverseDiff.jacobian(_f, p) - j_zyg = CHECK_ZYGOTE ? Zygote.jacobian(_f, p)[1] : nothing - - @test isapprox(j_fwd, ∂ẋ_∂p; atol=atol) - @test isapprox(j_rwd, ∂ẋ_∂p; atol=atol) - @test CHECK_ZYGOTE ? isapprox(j_zyg, ∂ẋ_∂p; atol=atol) : true - - @test c.solution.evals_∂ẋ_∂x == 0 - @test c.solution.evals_∂ẋ_∂u == 0 - @test c.solution.evals_∂ẋ_∂p == (CHECK_ZYGOTE ? 16 : 14) - @test c.solution.evals_∂ẋ_∂t == 0 - - @test c.solution.evals_∂y_∂u == 0 - @test c.solution.evals_∂y_∂p == 0 - @test c.solution.evals_∂y_∂x == 0 - @test c.solution.evals_∂y_∂t == 0 - - @test c.solution.evals_∂e_∂x == 0 - @test c.solution.evals_∂e_∂u == 0 - @test c.solution.evals_∂e_∂p == 0 - @test c.solution.evals_∂e_∂t == 0 - reset!(c) +_f = _p -> fmu(; p = _p, p_refs = p_refs, dx_refs = :all) +_f(p) +j_fwd = ForwardDiff.jacobian(_f, p) +j_rwd = ReverseDiff.jacobian(_f, p) +j_zyg = CHECK_ZYGOTE ? Zygote.jacobian(_f, p)[1] : nothing + +@test isapprox(j_fwd, ∂ẋ_∂p; atol = atol) +@test isapprox(j_rwd, ∂ẋ_∂p; atol = atol) +@test CHECK_ZYGOTE ? isapprox(j_zyg, ∂ẋ_∂p; atol = atol) : true + +@test c.solution.evals_∂ẋ_∂x == 0 +@test c.solution.evals_∂ẋ_∂u == 0 +@test c.solution.evals_∂ẋ_∂p == (CHECK_ZYGOTE ? 16 : 14) +@test c.solution.evals_∂ẋ_∂t == 0 + +@test c.solution.evals_∂y_∂u == 0 +@test c.solution.evals_∂y_∂p == 0 +@test c.solution.evals_∂y_∂x == 0 +@test c.solution.evals_∂y_∂t == 0 + +@test c.solution.evals_∂e_∂x == 0 +@test c.solution.evals_∂e_∂u == 0 +@test c.solution.evals_∂e_∂p == 0 +@test c.solution.evals_∂e_∂t == 0 +reset!(c) #end # Jacobian ∂y/∂p #if FMU_SUPPORTS_PARAMETER_SAMPLING - _f = _p -> fmu(;p=_p, p_refs=p_refs, y_refs=y_refs) - _f(p) - j_fwd = ForwardDiff.jacobian(_f, p) - j_rwd = ReverseDiff.jacobian(_f, p) - j_zyg = CHECK_ZYGOTE ? Zygote.jacobian(_f, p)[1] : nothing - - @test isapprox(j_fwd, ∂y_∂p; atol=atol) - @test isapprox(j_rwd, ∂y_∂p; atol=atol) - @test CHECK_ZYGOTE ? isapprox(j_zyg, ∂y_∂p; atol=atol) : true - - @test c.solution.evals_∂ẋ_∂x == 0 - @test c.solution.evals_∂ẋ_∂u == 0 - @test c.solution.evals_∂ẋ_∂p == 0 - @test c.solution.evals_∂ẋ_∂t == 0 - - @test c.solution.evals_∂y_∂u == 0 - @test c.solution.evals_∂y_∂p == (CHECK_ZYGOTE ? 16 : 14) - @test c.solution.evals_∂y_∂x == 0 - @test c.solution.evals_∂y_∂t == 0 - - @test c.solution.evals_∂e_∂x == 0 - @test c.solution.evals_∂e_∂u == 0 - @test c.solution.evals_∂e_∂p == 0 - @test c.solution.evals_∂e_∂t == 0 - reset!(c) +_f = _p -> fmu(; p = _p, p_refs = p_refs, y_refs = y_refs) +_f(p) +j_fwd = ForwardDiff.jacobian(_f, p) +j_rwd = ReverseDiff.jacobian(_f, p) +j_zyg = CHECK_ZYGOTE ? Zygote.jacobian(_f, p)[1] : nothing + +@test isapprox(j_fwd, ∂y_∂p; atol = atol) +@test isapprox(j_rwd, ∂y_∂p; atol = atol) +@test CHECK_ZYGOTE ? isapprox(j_zyg, ∂y_∂p; atol = atol) : true + +@test c.solution.evals_∂ẋ_∂x == 0 +@test c.solution.evals_∂ẋ_∂u == 0 +@test c.solution.evals_∂ẋ_∂p == 0 +@test c.solution.evals_∂ẋ_∂t == 0 + +@test c.solution.evals_∂y_∂u == 0 +@test c.solution.evals_∂y_∂p == (CHECK_ZYGOTE ? 16 : 14) +@test c.solution.evals_∂y_∂x == 0 +@test c.solution.evals_∂y_∂t == 0 + +@test c.solution.evals_∂e_∂x == 0 +@test c.solution.evals_∂e_∂u == 0 +@test c.solution.evals_∂e_∂p == 0 +@test c.solution.evals_∂e_∂t == 0 +reset!(c) #end # Jacobian ∂e/∂x -_f = function(_x) - ec_idcs = collect(UInt32(i) for i in 1:fmu.modelDescription.numberOfEventIndicators) - - ret = fmu(; ec_idcs=ec_idcs, x=_x) - - return ret.ec +_f = function (_x) + ec_idcs = collect(UInt32(i) for i = 1:fmu.modelDescription.numberOfEventIndicators) + + ret = fmu(; ec_idcs = ec_idcs, x = _x) + + return ret.ec end _f(x) j_fwd = ForwardDiff.jacobian(_f, x) @@ -473,9 +490,9 @@ j_zyg = CHECK_ZYGOTE ? Zygote.jacobian(_f, x)[1] : nothing # j_smp = sampleJacobian(c, :indicators, fmu.modelDescription.parameterValueReferences) # no option to get sensitivitities directly in FMI2/FMI3... -@test isapprox(j_fwd, ∂e_∂x; atol=atol) -@test isapprox(j_rwd, ∂e_∂x; atol=atol) -@test CHECK_ZYGOTE ? isapprox(j_zyg, j_rwd; atol=atol) : true +@test isapprox(j_fwd, ∂e_∂x; atol = atol) +@test isapprox(j_rwd, ∂e_∂x; atol = atol) +@test CHECK_ZYGOTE ? isapprox(j_zyg, j_rwd; atol = atol) : true @test c.solution.evals_∂ẋ_∂x == 0 @test c.solution.evals_∂ẋ_∂u == 0 @@ -494,4 +511,4 @@ j_zyg = CHECK_ZYGOTE ? Zygote.jacobian(_f, x)[1] : nothing reset!(c) # clean up -unloadFMU(fmu) \ No newline at end of file +unloadFMU(fmu) diff --git a/test/performance.jl b/test/performance.jl index ed56d91..09fb704 100644 --- a/test/performance.jl +++ b/test/performance.jl @@ -5,7 +5,7 @@ # this is temporary until it's implemented in native Julia, see: # https://discourse.julialang.org/t/debug-has-massive-performance-impact/103974/19 -using Logging +using Logging if Sys.iswindows() Logging.disable_logging(Logging.Debug) end @@ -18,9 +18,9 @@ c, fmu = getFMUStruct("BouncingBall1D", :ME, "Dymola", "2022x") function evalBenchmark(b) res = run(b) min_time = min(res.times...) - memory = res.memory + memory = res.memory allocs = res.allocs - return min_time, memory, allocs + return min_time, memory, allocs end ########## f(x) evaluation / right-hand side ########## @@ -44,12 +44,38 @@ ec = zeros(fmi2Real, 0) ec_idcs = zeros(fmi2ValueReference, 0) t = NO_fmi2Real -b = @benchmarkable FMI.eval!($cRef, $dx, $dx_refs, $y, $y_refs, $x, $u, $u_refs, $p, $p_refs, $ec, $ec_idcs, $t) +b = @benchmarkable FMI.eval!( + $cRef, + $dx, + $dx_refs, + $y, + $y_refs, + $x, + $u, + $u_refs, + $p, + $p_refs, + $ec, + $ec_idcs, + $t, +) min_time, memory, allocs = evalBenchmark(b) @test allocs <= 0 @test memory <= 0 -b = @benchmarkable $c(dx=$dx, y=$y, y_refs=$y_refs, x=$x, u=$u, u_refs=$u_refs, p=$p, p_refs=$p_refs, ec=$ec, ec_idcs=$ec_idcs, t=$t) +b = @benchmarkable $c( + dx = $dx, + y = $y, + y_refs = $y_refs, + x = $x, + u = $u, + u_refs = $u_refs, + p = $p, + p_refs = $p_refs, + ec = $ec, + ec_idcs = $ec_idcs, + t = $t, +) min_time, memory, allocs = evalBenchmark(b) @test allocs <= 9 # `ignore_derivatives` causes an extra 3 allocations (48 bytes) @test memory <= 224 # ToDo: What are the remaining allocations compared to `eval!`? @@ -72,4 +98,4 @@ b = @benchmarkable ReverseDiff.jacobian($fun, $x) min_time, memory, allocs = evalBenchmark(b) # ToDo: This is too much! @test allocs <= 180 -@test memory <= 11400 \ No newline at end of file +@test memory <= 11400 diff --git a/test/runtests.jl b/test/runtests.jl index 1b0c974..ac3b3c0 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -20,20 +20,28 @@ for exec in FMU_EXECUTION_CONFIGURATIONS exec.assertOnWarning = true end -function getFMUStruct(modelname, mode, tool=ENV["EXPORTINGTOOL"], version=ENV["EXPORTINGVERSION"], fmiversion=ENV["FMIVERSION"], fmustruct=ENV["FMUSTRUCT"]; kwargs...) - +function getFMUStruct( + modelname, + mode, + tool = ENV["EXPORTINGTOOL"], + version = ENV["EXPORTINGVERSION"], + fmiversion = ENV["FMIVERSION"], + fmustruct = ENV["FMUSTRUCT"]; + kwargs..., +) + # choose FMU or FMUComponent if endswith(modelname, ".fmu") fmu = loadFMU(modelname; kwargs...) else - fmu = loadFMU(modelname, tool, version, fmiversion; kwargs...) + fmu = loadFMU(modelname, tool, version, fmiversion; kwargs...) end if fmustruct == "FMU" return fmu, fmu elseif fmustruct == "FMUCOMPONENT" - inst, _ = FMIImport.prepareSolveFMU(fmu, nothing, mode; loggingOn=true) + inst, _ = FMIImport.prepareSolveFMU(fmu, nothing, mode; loggingOn = true) @test !isnothing(inst) return inst, fmu @@ -45,7 +53,7 @@ end @testset "FMIImport.jl" begin if Sys.iswindows() || Sys.islinux() @info "Automated testing is supported on Windows/Linux." - + ENV["EXPORTINGTOOL"] = "Dymola" ENV["EXPORTINGVERSION"] = "2023x" @@ -60,7 +68,7 @@ end @testset "Jacobians / Gradients" begin include("jacobians_gradients.jl") end - + @testset "Solution" begin include("solution.jl") end @@ -72,7 +80,7 @@ end # end end end - + elseif Sys.isapple() @warn "Test-sets are currrently using Windows- and Linux-FMUs, automated testing for macOS is currently not supported." end diff --git a/test/solution.jl b/test/solution.jl index 6bb4325..cf8cc89 100644 --- a/test/solution.jl +++ b/test/solution.jl @@ -3,4 +3,4 @@ # Licensed under the MIT license. See LICENSE file in the project root for details. # -# [TODO] Test if gradients over solutions are correct, too. \ No newline at end of file +# [TODO] Test if gradients over solutions are correct, too.