Skip to content

fix: fix handling of loop openings for systems that are nonlinear in the inputs #3774

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

Merged
merged 2 commits into from
Jul 4, 2025
Merged
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
34 changes: 24 additions & 10 deletions src/systems/analysis_points.jl
Original file line number Diff line number Diff line change
Expand Up @@ -491,14 +491,20 @@ struct Break <: AnalysisPointTransformation
applicable if `add_input == true`.
"""
default_outputs_to_input::Bool
"""
Whether the added input is a parameter. Only applicable if `add_input == true`.
"""
added_input_is_param::Bool
end

"""
$(TYPEDSIGNATURES)

`Break` the given analysis point `ap`.
"""
Break(ap::AnalysisPoint, add_input::Bool = false) = Break(ap, add_input, false)
function Break(ap::AnalysisPoint, add_input::Bool = false, default_outputs_to_input = false)
Break(ap, add_input, default_outputs_to_input, false)
end

function apply_transformation(tf::Break, sys::AbstractSystem)
modify_nested_subsystem(sys, tf.ap) do breaksys
Expand Down Expand Up @@ -528,9 +534,15 @@ function apply_transformation(tf::Break, sys::AbstractSystem)
new_def
end
@set! breaksys.defaults = defs
unks = copy(get_unknowns(breaksys))
push!(unks, new_var)
@set! breaksys.unknowns = unks
if tf.added_input_is_param
ps = copy(get_ps(breaksys))
push!(ps, new_var)
@set! breaksys.ps = ps
else
unks = copy(get_unknowns(breaksys))
push!(unks, new_var)
@set! breaksys.unknowns = unks
end

return breaksys, (new_var,)
end
Expand Down Expand Up @@ -812,12 +824,14 @@ Given a list of analysis points, break the connection for each and set the outpu
"""
function handle_loop_openings(sys::AbstractSystem, aps)
for ap in canonicalize_ap(sys, aps)
sys, (outvar,) = apply_transformation(Break(ap, true, true), sys)
if Symbolics.isarraysymbolic(outvar)
push!(get_eqs(sys), outvar ~ zeros(size(outvar)))
sys, (d_v,) = apply_transformation(Break(ap, true, true, true), sys)
guesses = copy(get_guesses(sys))
guesses[d_v] = if symbolic_type(d_v) == ArraySymbolic()
fill(NaN, size(d_v))
else
push!(get_eqs(sys), outvar ~ 0)
NaN
end
@set! sys.guesses = guesses
end
return sys
end
Expand Down Expand Up @@ -849,10 +863,10 @@ All other keyword arguments are forwarded to `linearization_function`.
"""
function get_linear_analysis_function(
sys::AbstractSystem, transform, aps; system_modifier = identity, loop_openings = [], kwargs...)
sys = handle_loop_openings(sys, loop_openings)
aps = canonicalize_ap(sys, aps)
dus = []
us = []
sys = handle_loop_openings(sys, loop_openings)
aps = canonicalize_ap(sys, aps)
for ap in aps
sys, (du, u) = apply_transformation(transform(ap), sys)
push!(dus, du)
Expand Down
Loading