Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

v0.2.1 #13

Merged
merged 2 commits into from
Sep 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions Project.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name = "FMISensitivity"
uuid = "3e748fe5-cd7f-4615-8419-3159287187d2"
authors = ["TT <[email protected]>", "LM <[email protected]>"]
version = "0.2.0"
version = "0.2.1"

[deps]
FMIBase = "900ee838-d029-460e-b485-d98a826ceef2"
Expand All @@ -11,5 +11,5 @@ SciMLSensitivity = "1ed8b502-d754-442c-8d5d-10ac956f44a1"
[compat]
FMIBase = "1.0.0"
ForwardDiffChainRules = "0.2.0"
SciMLSensitivity = "7.0 - 7.59"
SciMLSensitivity = "7.0 - 7.66"
julia = "1.6"
50 changes: 26 additions & 24 deletions src/sense.jl
Original file line number Diff line number Diff line change
Expand Up @@ -331,7 +331,9 @@ function ChainRulesCore.rrule(::typeof(FMIBase.eval!),
# because they are evaluated at different points in time during ODE solving.
if length(c.solution.snapshots) > 0
sn = getSnapshot(c.solution, t)
apply!(c, sn)
if !isnothing(sn) # sometimes it is -Inf (whyever...)
apply!(c, sn)
end
end

Ω = FMIBase.eval!(cRef, dx, dx_refs, y, y_refs, x, u, u_refs, p, p_refs, ec, ec_idcs, t)
Expand Down Expand Up @@ -1003,7 +1005,7 @@ abstract type FMUSensitivities end
mutable struct FMUJacobian{C, T, F} <: FMUSensitivities
valid::Bool
colored::Bool
component::C
instance::C

mtx::Matrix{T}
jvp::Vector{T}
Expand All @@ -1021,7 +1023,7 @@ mutable struct FMUJacobian{C, T, F} <: FMUSensitivities
validations::Int
colorings::Int

function FMUJacobian{T}(component::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`"
Expand All @@ -1046,7 +1048,7 @@ mutable struct FMUJacobian{C, T, F} <: FMUSensitivities

inst = new{C, T, F}()
inst.f = f
inst.component = component
inst.instance = instance
inst.f_refs = f_refs
inst.f_refs_set = f_refs_set
inst.x_refs = x_refs
Expand All @@ -1068,7 +1070,7 @@ end
mutable struct FMUGradient{C, T, F} <: FMUSensitivities
valid::Bool
colored::Bool
component::C
instance::C

vec::Vector{T}
gvp::Vector{T}
Expand All @@ -1086,7 +1088,7 @@ mutable struct FMUGradient{C, T, F} <: FMUSensitivities
validations::Int
colorings::Int

function FMUGradient{T}(component::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`"
Expand All @@ -1109,7 +1111,7 @@ mutable struct FMUGradient{C, T, F} <: FMUSensitivities

inst = new{C, T, F}()
inst.f = f
inst.component = component
inst.instance = instance
inst.f_refs = f_refs
inst.f_refs_set = f_refs_set
inst.x_refs = x_refs
Expand All @@ -1129,26 +1131,26 @@ mutable struct FMUGradient{C, T, F} <: FMUSensitivities
end

function f_∂v_∂v(jac::FMUJacobian, dx, x)
setReal(jac.component, jac.x_refs, x; track=false)
getReal!(jac.component, jac.f_refs, dx)
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.component, jac.x_refs, x; track=false)
getEventIndicators!(jac.component, dx, jac.f_refs[2])
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.component, x; track=false)
getEventIndicators!(jac.component, dx, jac.f_refs[2])
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.component, x; track=false)
getReal!(jac.component, jac.f_refs, dx)
setTime(jac.instance, x; track=false)
getReal!(jac.instance, jac.f_refs, dx)
return dx
end

Expand Down Expand Up @@ -1191,25 +1193,25 @@ function validate!(jac::FMUJacobian, x::AbstractVector)
rows = length(jac.f_refs)
cols = length(jac.x_refs)

if jac.component.fmu.executionConfig.sensitivity_strategy == :FMIDirectionalDerivative && providesDirectionalDerivatives(jac.component.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
for i in 1:cols
getDirectionalDerivative!(jac.component, jac.f_refs, jac.x_refs, onehot(jac.component, cols, i), view(jac.mtx, 1:rows, i))
getDirectionalDerivative!(jac.instance, jac.f_refs, jac.x_refs, onehot(jac.instance, cols, i), view(jac.mtx, 1:rows, i))
end
elseif jac.component.fmu.executionConfig.sensitivity_strategy == :FMIAdjointDerivative && providesAdjointDerivatives(jac.component.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
for i in 1:rows
getAdjointDerivative!(jac.component, jac.f_refs, jac.x_refs, onehot(jac.component, rows, i), view(jac.mtx, 1:cols, i))
getAdjointDerivative!(jac.instance, jac.f_refs, jac.x_refs, onehot(jac.instance, rows, i), view(jac.mtx, 1:cols, i))
end
else #if jac.component.fmu.executionConfig.sensitivity_strategy == :FiniteDiff
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.component.fmu.executionConfig.sensitivity_strategy)`."
# @assert false "Unknown sensitivity strategy `$(jac.instance.fmu.executionConfig.sensitivity_strategy)`."
end

jac.validations += 1
Expand All @@ -1219,10 +1221,10 @@ end

function validate!(grad::FMUGradient, x::Real)

if grad.component.fmu.executionConfig.sensitivity_strategy == :FMIDirectionalDerivative && providesDirectionalDerivatives(grad.component.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.component, grad.f_refs, grad.x_refs, ones(length(jac.f_refs)), grad.vec)
else #if grad.component.fmu.executionConfig.sensitivity_strategy == :FiniteDiff
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)
end
Expand Down
Loading