Skip to content

Commit 3ae7030

Browse files
authored
Merge pull request #298 from SciML/fb/ap_updates
Analysis point fixes
2 parents 200b13a + 00601f2 commit 3ae7030

File tree

2 files changed

+42
-3
lines changed

2 files changed

+42
-3
lines changed

src/Blocks/analysis_points.jl

Lines changed: 34 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,10 @@ function Base.hash(ap::AnalysisPoint, seed::UInt)
1818
h3 (0xd29cdc51aa6562d4 % UInt)
1919
end
2020

21+
function ModelingToolkit.get_unit(ap::AnalysisPoint)
22+
ModelingToolkit.unitless
23+
end
24+
2125
function ap_var(sys)
2226
if hasproperty(sys, :u)
2327
# collect to turn symbolic arrays into arrays of symbols
@@ -28,6 +32,23 @@ function ap_var(sys)
2832
error("Could not determine the analysis-point variable in system $(nameof(sys)). To use an analysis point, apply it to a connection between two causal blocks containing connectors of type `RealInput/RealOutput` from ModelingToolkitStandardLibrary.Blocks.")
2933
end
3034

35+
"""
36+
find_analysis_points(sys)
37+
38+
Return a list of all analysis points in `sys`. If none are found, the list is empty.
39+
"""
40+
function find_analysis_points(sys)
41+
sys = ModelingToolkit.flatten(sys)
42+
eqs = equations(sys)
43+
aps = []
44+
for eq in eqs
45+
if eq.rhs isa AnalysisPoint
46+
push!(aps, eq.rhs)
47+
end
48+
end
49+
aps
50+
end
51+
3152
"""
3253
AnalysisPoint(in, out, name::Symbol)
3354
AnalysisPoint(in, out; name::Symbol)
@@ -418,16 +439,26 @@ function ModelingToolkit.linearization_function(sys::ModelingToolkit.AbstractSys
418439
ui = get_perturbation_var(ap_var(ap.out), "u")
419440
push!(multiplicities_u, length(ui)) # one ap may yield several new vars
420441
append!(u, ui)
421-
[ap_var(ap.out) .~ ap_var(ap.in) + ui;], ui
442+
if loop_openings !== nothing && ap.name loop_openings
443+
# In thise case, we break the existing connection.
444+
[ap_var(ap.out) .~ ui;], ui
445+
else
446+
[ap_var(ap.out) .~ ap_var(ap.in) + ui;], ui
447+
end
422448
#input.in.u ~ 0] # We only need to ground one of the ends, hence not including this equation
423449
elseif output_name isa SymOrVec && namespaced_ap_match(ap, ns, output_name, nothing)
424450
push!(namespace_y, ns) # Save the namespace to make it available for renamespace below
425451
push!(aps_y, ap)
426452
yi = get_perturbation_var(ap_var(ap.in), "y")
427453
push!(multiplicities_y, length(yi))
428454
append!(y, yi)
429-
[ap_var(ap.in) .~ yi;
430-
ap_var(ap.out) .~ ap_var(ap.in)], yi
455+
if loop_openings !== nothing && ap.name loop_openings
456+
[ap_var(ap.in) .~ yi;
457+
ap_var(ap.out) .~ 0], yi # In thise case, we break the existing connection.
458+
else
459+
[ap_var(ap.in) .~ yi;
460+
ap_var(ap.out) .~ ap_var(ap.in)], yi
461+
end
431462
else # loop opening
432463
[ap_var(ap.out) .~ 0;], []
433464
end

test/Blocks/test_analysis_points.jl

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -242,6 +242,14 @@ Si = ss(matrices...)
242242
t,
243243
systems = [P_inner, feedback, ref])
244244

245+
@test_nowarn Blocks.find_analysis_points(sys_inner)
246+
P_not_broken, _ = linearize(sys_inner, :u, :y)
247+
@test P_not_broken.A[] == -2
248+
P_broken, _ = linearize(sys_inner, :u, :y, loop_openings = [:u])
249+
@test P_broken.A[] == -1
250+
P_broken, _ = linearize(sys_inner, :u, :y, loop_openings = [:y])
251+
@test P_broken.A[] == -1
252+
245253
Sinner = sminreal(ss(get_sensitivity(sys_inner, :u)[1]...))
246254

247255
@named sys_inner = ODESystem(

0 commit comments

Comments
 (0)