Skip to content

Commit 79f40dd

Browse files
committed
update the rest of functions for linear analysis
to use the find/replace funcitonality
1 parent 0c919b9 commit 79f40dd

File tree

1 file changed

+126
-73
lines changed

1 file changed

+126
-73
lines changed

src/Blocks/analysis_points.jl

Lines changed: 126 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -171,27 +171,34 @@ Compute the sensitivity function in analysis point `ap`. The sensitivity functio
171171
See also [`get_comp_sensitivity`](@ref), [`get_looptransfer`](@ref).
172172
"""
173173
function get_sensitivity(sys, ap_name::Symbol; kwargs...)
174-
find = let ap_name = ap_name
175-
x -> x isa AnalysisPoint && nameof(x) === ap_name
174+
find = function (x, ns)
175+
x isa AnalysisPoint || return false
176+
if ns === nothing
177+
nameof(x) === ap_name
178+
else
179+
Symbol(ns, :_, nameof(x)) === ap_name
180+
end
176181
end
177182
t = get_iv(sys)
178-
@variables d(t) = 0 # Perturbation serving as input to sensivity transfer function
183+
@variables d(t) = 0 # Perturbation serving as input to sensitivity transfer function
179184
namespace = Ref{Union{Nothing, Symbol}}(nothing)
180-
this_ap = Ref{Union{Nothing, AnalysisPoint}}(nothing)
181-
replace = let d = d, namespace = namespace, this_ap = this_ap
182-
(ap, ns) -> begin
183-
namespace[] = ns
184-
this_ap[] = ap
185+
apr = Ref{Union{Nothing, AnalysisPoint}}(nothing)
186+
replace = let d = d, namespace = namespace, apr = apr
187+
function (ap, ns)
188+
namespace[] = ns # Save the namespace to make it available for renamespace below
189+
apr[] = ap
185190
(ap.out.u ~ ap.in.u + d), d
186191
end
187192
end
188193
sys = expand_connections(sys, find, replace)
189-
(ap = this_ap[]) === nothing && error("Did not find analysis point $ap")
194+
(ap = apr[]) === nothing && error("Did not find analysis point $ap")
190195
u = ap.out.u
191196
if (ns = namespace[]) !== nothing
192-
d = ModelingToolkit.renamespace(d, ns)
193-
u = ModelingToolkit.renamespace(u, ns)
197+
@show ns
198+
@show d = ModelingToolkit.renamespace(ns, d)
199+
@show u = ModelingToolkit.renamespace(ns, u)
194200
end
201+
@show u, d
195202
ModelingToolkit.linearize(sys, [d], [u]; kwargs...)
196203
end
197204

@@ -209,23 +216,34 @@ Compute the complementary sensitivity function in analysis point `ap`. The compl
209216
210217
See also [`get_sensitivity`](@ref), [`get_looptransfer`](@ref).
211218
"""
212-
function get_comp_sensitivity(sys, ap::AnalysisPoint; kwargs...)
213-
sys = ModelingToolkit.flatten(sys) # To get namespacing right
219+
function get_comp_sensitivity(sys, ap_name::Symbol; kwargs...)
220+
find = function (x, ns)
221+
x isa AnalysisPoint || return false
222+
if ns === nothing
223+
nameof(x) === ap_name
224+
else
225+
Symbol(ns, :_, nameof(x)) === ap_name
226+
end
227+
end
214228
t = get_iv(sys)
215-
@variables d(t) = 0 # Perturbation serving as input to sensivity transfer function
216-
found = false
217-
new_eqs = map(equations(sys)) do eq
218-
eq.rhs == ap || (return eq)
219-
found = true
220-
ap.out.u + d ~ ap.in.u # This assumes that the connector has an internal vaiable named u
229+
@variables d(t) = 0 # Perturbation serving as input to sensitivity transfer function
230+
namespace = Ref{Union{Nothing, Symbol}}(nothing)
231+
apr = Ref{Union{Nothing, AnalysisPoint}}(nothing)
232+
replace = let d = d, namespace = namespace, apr = apr
233+
function (ap, ns)
234+
namespace[] = ns # Save the namespace to make it available for renamespace below
235+
apr[] = ap
236+
(ap.out.u + d ~ ap.in.u), d
237+
end
221238
end
222-
found || error("Did not find analysis point $ap")
223-
@set! sys.eqs = new_eqs
224-
@set! sys.states = [states(sys); d]
225-
@set! sys.defaults = merge(ModelingToolkit.defaults(sys), Dict(d => 0))
226-
227-
sys = expand_analysis_points(sys) # Any remaining analysis points are removed by this
228-
ModelingToolkit.linearize(sys, [d], [ap.in.u]; kwargs...)
239+
sys = expand_connections(sys, find, replace)
240+
(ap = apr[]) === nothing && error("Did not find analysis point $ap")
241+
u = ap.in.u
242+
if (ns = namespace[]) !== nothing
243+
d = ModelingToolkit.renamespace(ns, d)
244+
u = ModelingToolkit.renamespace(ns, u)
245+
end
246+
ModelingToolkit.linearize(sys, [d], [u]; kwargs...)
229247
end
230248

231249
"""
@@ -242,19 +260,34 @@ Compute the (linearized) loop-transfer function in analysis point `ap`, from `ap
242260
243261
See also [`get_sensitivity`](@ref), [`get_comp_sensitivity`](@ref), [`open_loop`](@ref).
244262
"""
245-
function get_looptransfer(sys, ap::AnalysisPoint; kwargs...)
246-
sys = ModelingToolkit.flatten(sys) # To get namespacing right
263+
function get_looptransfer(sys, ap_name::Symbol; kwargs...)
264+
find = function (x, ns)
265+
x isa AnalysisPoint || return false
266+
if ns === nothing
267+
nameof(x) === ap_name
268+
else
269+
Symbol(ns, :_, nameof(x)) === ap_name
270+
end
271+
end
247272
t = get_iv(sys)
248-
found = false
249-
new_eqs = map(equations(sys)) do eq
250-
eq.rhs == ap || (return eq)
251-
found = true
252-
0 ~ 0 # This assumes that the connector has an internal vaiable named u
273+
namespace = Ref{Union{Nothing, Symbol}}(nothing)
274+
apr = Ref{Union{Nothing, AnalysisPoint}}(nothing)
275+
replace = let namespace = namespace, apr = apr
276+
function (ap, ns)
277+
namespace[] = ns # Save the namespace to make it available for renamespace below
278+
apr[] = ap
279+
(0 ~ 0), nothing
280+
end
253281
end
254-
found || error("Did not find analysis point $ap")
255-
@set! sys.eqs = new_eqs
256-
sys = expand_analysis_points(sys) # Any remaining analysis points are removed by this
257-
ModelingToolkit.linearize(sys, [ap.out.u], [ap.in.u]; kwargs...)
282+
sys = expand_connections(sys, find, replace)
283+
(ap = apr[]) === nothing && error("Did not find analysis point $ap")
284+
u = ap.out.u
285+
y = ap.in.u
286+
if (ns = namespace[]) !== nothing
287+
y = ModelingToolkit.renamespace(ns, y)
288+
u = ModelingToolkit.renamespace(ns, u)
289+
end
290+
ModelingToolkit.linearize(sys, [u], [y]; kwargs...)
258291
end
259292

260293
"""
@@ -273,54 +306,78 @@ Open the loop at analysis point `ap` by breaking the connection through `ap`.
273306
274307
See also [`get_sensitivity`](@ref), [`get_comp_sensitivity`](@ref), [`get_looptransfer`](@ref).
275308
"""
276-
function open_loop(sys, ap::AnalysisPoint; kwargs...)
277-
sys = ModelingToolkit.flatten(sys) # To get namespacing right
309+
function open_loop(sys, ap_name::Symbol; kwargs...)
310+
find = function (x, ns)
311+
x isa AnalysisPoint || return false
312+
if ns === nothing
313+
nameof(x) === ap_name
314+
else
315+
Symbol(ns, :_, nameof(x)) === ap_name
316+
end
317+
end
278318
t = get_iv(sys)
279319
@variables u(t)=0 [input = true]
280320
@variables y(t)=0 [output = true]
281-
found = false
282-
new_eqs = map(equations(sys)) do eq
283-
eq.rhs == ap || (return [eq])
284-
found = true
285-
[ap.out.u ~ u
286-
ap.in.u ~ y]
321+
namespace = Ref{Union{Nothing, Symbol}}(nothing)
322+
apr = Ref{Union{Nothing, AnalysisPoint}}(nothing)
323+
replace = let u = u, y = y, namespace = namespace, apr = apr
324+
function (ap, ns)
325+
namespace[] = ns # Save the namespace to make it available for renamespace below
326+
apr[] = ap
327+
[ap.out.u ~ u, ap.in.u ~ y], [u, y]
328+
end
287329
end
288-
found || error("Did not find analysis point $ap")
289-
new_eqs = reduce(vcat, new_eqs)
290-
@set! sys.eqs = new_eqs
291-
@set! sys.states = [states(sys); u; y]
292-
@set! sys.defaults = merge(ModelingToolkit.defaults(sys), Dict(u => 0, y => 0))
330+
if (ns = namespace[]) !== nothing
331+
y = ModelingToolkit.renamespace(ns, y)
332+
u = ModelingToolkit.renamespace(ns, u)
333+
end
334+
sys = expand_connections(sys, find, replace)
335+
(ap = apr[]) === nothing && error("Did not find analysis point $ap")
293336
sys
294337
end
295338

296339
"""
297-
ModelingToolkit.linearize(sys, input::AnalysisPoint, output::AnalysisPoint)
340+
ModelingToolkit.linearize(sys, input_name::Symbol, output_name::Symbol)
298341
299342
Linearize a system between two analysis points.
300343
All parts of the model that do not appear between `input` and `output` will be neglected.
301344
"""
302-
function ModelingToolkit.linearize(sys, input::AnalysisPoint, output::AnalysisPoint;
345+
function ModelingToolkit.linearize(sys, input_name::Symbol, output_name::Symbol;
303346
kwargs...)
304-
sys = ModelingToolkit.flatten(sys) # To get namespacing right
347+
find = function (x, ns)
348+
x isa AnalysisPoint || return false
349+
if ns === nothing
350+
nameof(x) (input_name, output_name)
351+
else
352+
Symbol(ns, :_, nameof(x)) (input_name, output_name)
353+
end
354+
end
305355
t = get_iv(sys)
306356
@variables u(t)=0 [input = true]
307357
@variables y(t)=0 [output = true]
308-
new_eqs = map(equations(sys)) do eq
309-
if eq.rhs == input
310-
[input.out.u ~ u]
311-
#input.in.u ~ 0] # We only need to ground one of the ends, hence not including this equation
312-
elseif eq.rhs == output
313-
[output.in.u ~ y
314-
output.out.u ~ 0]
315-
else
316-
return [eq]
358+
namespace = Ref{Union{Nothing, Symbol}}(nothing)
359+
apr = Ref{Union{Nothing, AnalysisPoint}}(nothing)
360+
replace = let u = u, y = y, namespace = namespace, apr = apr
361+
function (ap, ns)
362+
namespace[] = ns # Save the namespace to make it available for renamespace below
363+
apr[] = ap
364+
if nameof(ap) === input_name
365+
[ap.out.u ~ u], u
366+
#input.in.u ~ 0] # We only need to ground one of the ends, hence not including this equation
367+
elseif nameof(ap) === output_name
368+
[ap.in.u ~ y
369+
ap.out.u ~ 0], y
370+
else
371+
error("This should never happen")
372+
end
317373
end
318374
end
319-
new_eqs = reduce(vcat, new_eqs)
320-
@set! sys.eqs = new_eqs
321-
@set! sys.states = [states(sys); u; y]
322-
@set! sys.defaults = merge(ModelingToolkit.defaults(sys), Dict(u => 0, y => 0))
323-
sys = expand_analysis_points(sys)
375+
sys = expand_connections(sys, find, replace)
376+
(ap = apr[]) === nothing && error("Did not find analysis point $ap")
377+
if (ns = namespace[]) !== nothing
378+
y = ModelingToolkit.renamespace(ns, y)
379+
u = ModelingToolkit.renamespace(ns, u)
380+
end
324381
ModelingToolkit.linearize(sys, [u], [y]; kwargs...)
325382
end
326383

@@ -331,11 +388,7 @@ for f in [:get_sensitivity, :get_comp_sensitivity, :get_looptransfer, :open_loop
331388
end
332389
end
333390

334-
function ModelingToolkit.linearize(sys, input_name::Symbol, output_name::Symbol;
391+
function ModelingToolkit.linearize(sys, input::AnalysisPoint, output::AnalysisPoint;
335392
kwargs...)
336-
input = find_analysis_point(sys, input_name)
337-
input === nothing && error("Failed to find an analysis point named $input_name")
338-
output = find_analysis_point(sys, output_name)
339-
output === nothing && error("Failed to find an analysis point named $output_name")
340-
ModelingToolkit.linearize(sys, input, output; kwargs...)
393+
ModelingToolkit.linearize(sys, nameof(input), nameof(output); kwargs...)
341394
end

0 commit comments

Comments
 (0)