@@ -247,8 +247,9 @@ function _check_and_sort!(ap_names, aps, namespaces, multiplicities)
247247 if ind === nothing
248248 @error " Could not find analysis point $apn "
249249 happy = false
250+ else
251+ push! (permutation, ind)
250252 end
251- push! (permutation, ind)
252253 end
253254 happy || error (" Failed to find all analysis points. I found these: $(nameof .(aps)) " )
254255 aps .= aps[permutation]
@@ -485,6 +486,48 @@ function ModelingToolkit.linearization_function(sys::ModelingToolkit.AbstractSys
485486 ModelingToolkit. linearization_function (system_modifier (sys), un, yn; kwargs... )
486487end
487488
489+
490+ function ModelingToolkit. generate_control_function (
491+ sys:: ModelingToolkit.AbstractODESystem , input_ap_name:: SymOrVec , dist_ap_name:: SymOrVec ; system_modifier = identity,
492+ kwargs... )
493+
494+ all_ap_names = [input_ap_name; dist_ap_name]
495+ find = namespaced_ap_match (all_ap_names, [])
496+ t = get_iv (sys)
497+ aps = []
498+ multiplicities = Int[]
499+ namespaces = []
500+ u = []
501+ d = []
502+ replace = function (ap, ns)
503+ if namespaced_ap_match (ap, ns, input_ap_name, nothing )
504+ push! (aps, ap)
505+ push! (multiplicities, length (ap_var (ap. in))) # ap may be vector-valued
506+ push! (namespaces, ns)
507+ push! (u, ap_var (ap. out))
508+ (0 ~ 0 ), nothing
509+ elseif namespaced_ap_match (ap, ns, dist_ap_name, nothing )
510+ push! (aps, ap)
511+ push! (multiplicities, length (ap_var (ap. in))) # ap may be vector-valued
512+ push! (namespaces, ns)
513+ push! (d, ap_var (ap. out))
514+ (0 ~ 0 ), nothing
515+ else
516+ error (" This should not have happened" )
517+ end
518+ end
519+ sys = expand_connections (sys, find, replace)
520+ permutation = _check_and_sort! (all_ap_names, aps, namespaces, multiplicities)
521+ uinds = 1 : length (u)
522+ dinds = length (u) .+ (1 : length (d))
523+ un = ModelingToolkit. renamespace .(namespaces[uinds], u[permutation[uinds]])
524+ dn = ModelingToolkit. renamespace .(namespaces[dinds], d[permutation[dinds] .- length (u)])
525+ sys = system_modifier (sys)
526+
527+ ModelingToolkit. generate_control_function (sys, un, dn; kwargs... )
528+ end
529+
530+
488531# Add a method to get_sensitivity that accepts the name of an AnalysisPoint
489532for f in [:get_sensitivity , :get_comp_sensitivity , :get_looptransfer , :open_loop ]
490533 @eval function $f (sys, ap:: AnalysisPoint , args... ; kwargs... )
0 commit comments