Linear Analysis

Linear analysis refers to the process of linearizing a nonlinear model and analysing the resulting linear dynamical system. To facilitate linear analysis, ModelingToolkit provides the concept of an AnalysisPoint, which can be inserted in-between two causal blocks (such as those from ModelingToolkitStandardLibrary.Blocks sub module). Once a model containing analysis points is built, several operations are available:

  • get_sensitivity get the sensitivity function (wiki), $S(s)$, as defined in the field of control theory.
  • get_comp_sensitivity get the complementary sensitivity function $T(s) : S(s)+T(s)=1$.
  • get_looptransfer get the (open) loop-transfer function where the loop starts and ends in the analysis point. For a typical simple feedback connection with a plant $P(s)$ and a controller $C(s)$, the loop-transfer function at the plant output is $P(s)C(s)$.
  • linearize can be called with two analysis points denoting the input and output of the linearized system.
  • open_loop return a new (nonlinear) system where the loop has been broken in the analysis point, i.e., the connection the analysis point usually implies has been removed.

An analysis point can be created explicitly using the constructor AnalysisPoint, or automatically when connecting two causal components using connect:

connect(comp1.output, :analysis_point_name, comp2.input)

A single output can also be connected to multiple inputs:

connect(comp1.output, :analysis_point_name, comp2.input, comp3.input, comp4.input)
Causality

Analysis points are causal, i.e., they imply a directionality for the flow of information. The order of the connections in the connect statement is thus important, i.e., connect(out, :name, in) is different from connect(in, :name, out).

The directionality of an analysis point can be thought of as an arrow in a block diagram, where the name of the analysis point applies to the arrow itself.

┌─────┐         ┌─────┐
│     │  name   │     │
│  out├────────►│in   │
│     │         │     │
└─────┘         └─────┘

This is signified by the name being the middle argument to connect.

An analysis point of a built model is referred to by property access on the system in which it was created, sys.analysis_point_name, and the functions above accept the AnalysisPoint this returns. A point belonging to a subsystem is reached through the hierarchy, sys.inner.analysis_point_name. The system must be the unsimplified and uncompleted model, since both mtkcompile and complete remove the analysis points.

Old style

Referring to an analysis point by its Symbol name, as in get_sensitivity(sys, :plant_input), is the old style and is retained only for backwards compatibility. It will be deprecated.

Of the above mentioned functions, all except for open_loop return the output of ModelingToolkit.linearize, which is

matrices, simplified_sys = linearize(_...)
# matrices = (; A, B, C, D)

i.e., matrices is a named tuple containing the matrices of a linear state-space system on the form

\[\begin{aligned} \dot x &= Ax + Bu\\ y &= Cx + Du \end{aligned}\]

Example

The following example builds a simple closed-loop system with a plant $P$ and a controller $C$. Two analysis points are inserted, one before and one after $P$. We then derive a number of sensitivity functions and show the corresponding code using the package ControlSystemBase.jl

using ModelingToolkitStandardLibrary.Blocks, ModelingToolkit
using ModelingToolkit: t_nounits as t

@named P = FirstOrder(k = 1, T = 1) # A first-order system with pole in -1
@named C = Gain(-1)             # A P controller

eqs = [connect(P.output, :plant_output, C.input)  # Connect with an automatically created analysis point called :plant_output
       connect(C.output, :plant_input, P.input)]
sys = System(eqs, t, systems = [P, C], name = :feedback_system)

matrices_S = get_sensitivity(sys, sys.plant_input)[1] # Compute the matrices of a state-space representation of the (input)sensitivity function.
matrices_T = get_comp_sensitivity(sys, sys.plant_input)[1]
(A = [-2.0;;], B = [-1.0;;], C = [-1.0;;], D = [0.0;;])

Continued linear analysis and design can be performed using ControlSystemsBase.jl. We create ControlSystemsBase.StateSpace objects using

using ControlSystemsBase, Plots
S = ss(matrices_S...)
T = ss(matrices_T...)
bodeplot([S, T], lab = ["S" "" "T" ""], plot_title = "Bode plot of sensitivity functions",
    margin = 5Plots.mm)
Example block output

The sensitivity functions obtained this way should be equivalent to the ones obtained with the code below

using ControlSystemsBase
P = tf(1.0, [1, 1]) |> ss
C = 1                      # Negative feedback assumed in ControlSystems
S = sensitivity(P, C)      # or feedback(1, P*C)
T = comp_sensitivity(P, C) # or feedback(P*C)
ControlSystemsBase.StateSpace{ControlSystemsBase.Continuous, Float64}
A = 
 -2.0
B = 
 1.0
C = 
 1.0
D = 
 0.0

Continuous-time state-space model

We may also derive the loop-transfer function $L(s) = P(s)C(s)$ using

matrices_L = get_looptransfer(sys, sys.plant_output)[1]
L = ss(matrices_L...)
ControlSystemsBase.StateSpace{ControlSystemsBase.Continuous, Float64}
A = 
 -1.0
B = 
 -1.0
C = 
 1.0
D = 
 0.0

Continuous-time state-space model

which is equivalent to the following with ControlSystems

L = P * (-C) # Add the minus sign to build the negative feedback into the controller
ControlSystemsBase.StateSpace{ControlSystemsBase.Continuous, Float64}
A = 
 -1.0
B = 
 -1.0
C = 
 1.0
D = 
 -0.0

Continuous-time state-space model

To obtain the transfer function between two analysis points, we call linearize

matrices_PS = linearize(sys, sys.plant_input, sys.plant_output)[1]
(A = [-2.0;;], B = [1.0;;], C = [1.0;;], D = [0.0;;])

this particular transfer function should be equivalent to the linear system P(s)S(s), i.e., equivalent to

feedback(P, C)
ControlSystemsBase.StateSpace{ControlSystemsBase.Continuous, Float64}
A = 
 -2.0
B = 
 1.0
C = 
 1.0
D = 
 0.0

Continuous-time state-space model

Obtaining transfer functions

A statespace system from ControlSystemsBase can be converted to a transfer function using the function tf:

tf(S)
ControlSystemsBase.TransferFunction{ControlSystemsBase.Continuous, ControlSystemsBase.SisoRational{Float64}}
1.0s + 1.0
----------
1.0s + 2.0

Continuous-time transfer function model

Gain and phase margins

Further linear analysis can be performed using the analysis methods from ControlSystemsBase. For example, calculating the gain and phase margins of a system can be done using

margin(P)
(wgm = [NaN;;], gm = [Inf;;], wpm = [-0.0;;], pm = [180.0;;])

(they are infinite for this system). A Nyquist plot can be produced using

nyquistplot(P)
Example block output

Operating Point of Signals Disconnected by Loop Openings

When a connection is broken via loop_openings, the input variables that were driven by the connection are disconnected. Their values are part of the operating point at which the linearization is computed, which is significant for systems that are nonlinear in these variables.

Semantics: A loop opening changes the input-output structure of the linearization, not the operating point. A disconnected variable becomes a parameter of the system, not an additional input of the linearization, so it does not appear as an extra column of the $B$ or $D$ matrices. Its value is determined by, in order of precedence,

  1. its entry in the operating point: a value, e.g., op = Dict(u => value); the value missing, which makes the initialization solve for the variable from additional conditions in the operating point, for example a steady-state condition D(x) => 0 for a differential state variable x; or an expression,
  2. its initial condition in the system, e.g., @variables u(t) = value, unless the linearization is performed around a solution with LinearizationOpPoint, which ignores the initial conditions of the system,
  3. otherwise, the value of the signal that drove it before the connection was broken, at the operating point of the loop-closed system. The initialization includes the equation u ~ driver in place of the broken connection, so it solves the same problem as the initialization of the loop-closed system. With a LinearizationOpPoint, this is the value the signal has in the solution at each time point.

A guess value of the variable does not determine its value. The same rules apply to the input that replaces the broken connection in get_looptransfer, and to an input analysis point that is also listed in loop_openings. The value of a disconnected signal is fixed when the linearization function is built, so it must be given in the operating point passed to linearization_function or to the analysis function that builds it; linearize(sys, lin_fun; op) rejects values for signals that the linearization function holds at the value of their driver.

Motivation:

  • Loop openings are mostly used to extract a part of a feedback system at the operating point of the closed loop, e.g., the plant, the controller, or a loop-transfer function for the computation of stability margins. The linearizations of the parts combine into the linearization of the closed loop only if all parts are linearized at the same operating point. Holding the disconnected signals at their loop-closed values ensures this without any entries in the operating point, both at a single operating point and along a solution.
  • Setting disconnected signals to zero changes the operating point of the components that are nonlinear in them, and can yield linearizations at points the system never attains.
  • A loop opening can also be used to disconnect a signal in order to linearize at a different operating point, for example to remove a reference step that saturates a controller at the initial time. The new value of the signal is then a choice of the user, and it is given in the operating point or as an initial condition of the disconnected variable.

Index

    ModelingToolkit.get_comp_sensitivity — Method
    get_comp_sensitivity(sys, ap; loop_openings = [], system_modifier = identity, op = Dict(), kwargs...)

    Compute the complementary-sensitivity transfer matrices at analysis point ap and return (matrices, simplified_system, extras). This introduces an infinitesimal perturbation at the output of ap, linearizes the system, and computes the transfer function from the perturbation to the input of ap.

    Arguments and keyword arguments match get_sensitivity, with kwargs... forwarded to get_comp_sensitivity_function.

    See also get_sensitivity and get_looptransfer.

    source
    ModelingToolkit.get_comp_sensitivity_function — Method
    get_comp_sensitivity_function(
        sys::ModelingToolkitBase.AbstractSystem,
        aps;
        kwargs...
    ) -> Tuple{ModelingToolkit.LinearizationFunction{_A, P, H, _B, J1, J2, J3, J4, IA, @NamedTuple{abstol::Float64, reltol::Float64, nlsolve_alg::Nothing}} where {_A, P<:ODEProblem, H<:FunctionWrappersWrappers.FunctionWrappersWrapper, _B, J1<:Union{Nothing, ModelingToolkit.PreparedJacobian{true, DifferentiationInterfaceForwardDiffExt.ForwardDiffTwoArgJacobianPrep{Nothing, C, Tuple{Nothing, Nothing}}, ModelingToolkit.UFFun{F}, _A, ADTypes.AutoForwardDiff{nothing, Nothing}} where {C<:(ForwardDiff.JacobianConfig{T, _A, _B, <:Tuple{Any, Any}} where {T<:(ForwardDiff.Tag{F} where F<:ModelingToolkit.UFFun), _A, _B}), F, _A}}, J2<:Union{Nothing, ModelingToolkit.PreparedJacobian{true, DifferentiationInterfaceForwardDiffExt.ForwardDiffTwoArgJacobianPrep{Nothing, C, Tuple{Nothing, Nothing}}, FunctionWrappersWrappers.FunctionWrappersWrapper{FW, P, CS}, _A, ADTypes.AutoForwardDiff{nothing, Nothing}} where {C<:(ForwardDiff.JacobianConfig{T, _A, _B, <:Tuple{Any, Any}} where {T<:(ForwardDiff.Tag{F} where F<:FunctionWrappersWrappers.FunctionWrappersWrapper), _A, _B}), FW, P, CS, _A}}, J3<:Union{Nothing, ModelingToolkit.PreparedJacobian{true, DifferentiationInterfaceForwardDiffExt.ForwardDiffTwoArgJacobianPrep{Nothing, C, Tuple{Nothing, Nothing, Nothing}}, ModelingToolkit.PFFun{_A, S}, _A1, ADTypes.AutoForwardDiff{nothing, Nothing}} where {C<:(ForwardDiff.JacobianConfig{T, _A, _B, <:Tuple{Any, Any}} where {T<:(ForwardDiff.Tag{F} where F<:(ModelingToolkit.PFFun{_A, S} where {_A, S<:(SymbolicIndexingInterface.OOPSetter{_A, System} where _A)})), _A, _B}), _A, S<:(SymbolicIndexingInterface.OOPSetter{_A, System} where _A), _A1}}, J4<:(ModelingToolkit.PreparedJacobian{true, DifferentiationInterfaceForwardDiffExt.ForwardDiffTwoArgJacobianPrep{Nothing, C, Tuple{Nothing, Nothing, Nothing}}, ModelingToolkit.HPFun{F, S}, _A, ADTypes.AutoForwardDiff{nothing, Nothing}} where {C<:(ForwardDiff.JacobianConfig{T, _A, _B, <:Tuple{Any, Any}} where {T<:(ForwardDiff.Tag{F} where F<:(ModelingToolkit.HPFun{F, S} where {F<:FunctionWrappersWrappers.FunctionWrappersWrapper, S<:(SymbolicIndexingInterface.OOPSetter{_A, System} where _A)})), _A, _B}), F<:FunctionWrappersWrappers.FunctionWrappersWrapper, S<:(SymbolicIndexingInterface.OOPSetter{_A, System} where _A), _A}), IA<:Union{SciMLBase.NoInit, SciMLBase.OverrideInit{Nothing, Nothing, Nothing}}}, System}
    

    Return the complementary sensitivity function for the analysis point(s) aps, and the modified system simplified with the appropriate inputs and outputs.

    Arguments

    • aps: An analysis point of the unsimplified, uncompleted system sys, obtained as sys.ap_name, or a vector of such points. A point belonging to a subsystem is reached through the hierarchy, sys.inner.ap_name. Passing the Symbol name of a point is the old style and will be deprecated.

    Keyword Arguments

    • loop_openings: A list of analysis points whose connections should be removed as a part of the linear analysis. Each entry is an analysis point of the unsimplified, uncompleted system, obtained as sys.ap_name. The disconnected signals keep the value of their drivers at the operating point of the loop-closed system, unless the operating point or an initial condition specifies their value, see the section "Operating Point of Signals Disconnected by Loop Openings" of the linear-analysis tutorial.

    • system_modifier: A function taking the transformed system and applying any additional transformations, returning the modified system. The modified system is passed to linearization_function.

    All other keyword arguments are forwarded to linearization_function.

    source
    ModelingToolkit.get_looptransfer — Method
    get_looptransfer(sys, ap; loop_openings = [], system_modifier = identity, op = Dict(), kwargs...)

    Compute the loop-transfer matrices at analysis point ap and return (matrices, simplified_system, extras). The transfer is from ap.out to ap.in.

    Arguments and keyword arguments match get_sensitivity, with kwargs... forwarded to get_looptransfer_function.

    Negative feedback

    The computed loop transfer includes negative feedback. Negate the result when using an analysis tool that expects a loop-transfer function without the negative gain.

    See also get_sensitivity, get_comp_sensitivity, and open_loop.

    source
    ModelingToolkit.get_looptransfer_function — Method
    get_looptransfer_function(
        sys::ModelingToolkitBase.AbstractSystem,
        aps;
        kwargs...
    ) -> Tuple{ModelingToolkit.LinearizationFunction{_A, P, H, _B, J1, J2, J3, J4, IA, @NamedTuple{abstol::Float64, reltol::Float64, nlsolve_alg::Nothing}} where {_A, P<:ODEProblem, H<:FunctionWrappersWrappers.FunctionWrappersWrapper, _B, J1<:Union{Nothing, ModelingToolkit.PreparedJacobian{true, DifferentiationInterfaceForwardDiffExt.ForwardDiffTwoArgJacobianPrep{Nothing, C, Tuple{Nothing, Nothing}}, ModelingToolkit.UFFun{F}, _A, ADTypes.AutoForwardDiff{nothing, Nothing}} where {C<:(ForwardDiff.JacobianConfig{T, _A, _B, <:Tuple{Any, Any}} where {T<:(ForwardDiff.Tag{F} where F<:ModelingToolkit.UFFun), _A, _B}), F, _A}}, J2<:Union{Nothing, ModelingToolkit.PreparedJacobian{true, DifferentiationInterfaceForwardDiffExt.ForwardDiffTwoArgJacobianPrep{Nothing, C, Tuple{Nothing, Nothing}}, FunctionWrappersWrappers.FunctionWrappersWrapper{FW, P, CS}, _A, ADTypes.AutoForwardDiff{nothing, Nothing}} where {C<:(ForwardDiff.JacobianConfig{T, _A, _B, <:Tuple{Any, Any}} where {T<:(ForwardDiff.Tag{F} where F<:FunctionWrappersWrappers.FunctionWrappersWrapper), _A, _B}), FW, P, CS, _A}}, J3<:Union{Nothing, ModelingToolkit.PreparedJacobian{true, DifferentiationInterfaceForwardDiffExt.ForwardDiffTwoArgJacobianPrep{Nothing, C, Tuple{Nothing, Nothing, Nothing}}, ModelingToolkit.PFFun{_A, S}, _A1, ADTypes.AutoForwardDiff{nothing, Nothing}} where {C<:(ForwardDiff.JacobianConfig{T, _A, _B, <:Tuple{Any, Any}} where {T<:(ForwardDiff.Tag{F} where F<:(ModelingToolkit.PFFun{_A, S} where {_A, S<:(SymbolicIndexingInterface.OOPSetter{_A, System} where _A)})), _A, _B}), _A, S<:(SymbolicIndexingInterface.OOPSetter{_A, System} where _A), _A1}}, J4<:(ModelingToolkit.PreparedJacobian{true, DifferentiationInterfaceForwardDiffExt.ForwardDiffTwoArgJacobianPrep{Nothing, C, Tuple{Nothing, Nothing, Nothing}}, ModelingToolkit.HPFun{F, S}, _A, ADTypes.AutoForwardDiff{nothing, Nothing}} where {C<:(ForwardDiff.JacobianConfig{T, _A, _B, <:Tuple{Any, Any}} where {T<:(ForwardDiff.Tag{F} where F<:(ModelingToolkit.HPFun{F, S} where {F<:FunctionWrappersWrappers.FunctionWrappersWrapper, S<:(SymbolicIndexingInterface.OOPSetter{_A, System} where _A)})), _A, _B}), F<:FunctionWrappersWrappers.FunctionWrappersWrapper, S<:(SymbolicIndexingInterface.OOPSetter{_A, System} where _A), _A}), IA<:Union{SciMLBase.NoInit, SciMLBase.OverrideInit{Nothing, Nothing, Nothing}}}, System}
    

    Return the loop-transfer function for the analysis point(s) aps, and the modified system simplified with the appropriate inputs and outputs.

    Arguments

    • aps: An analysis point of the unsimplified, uncompleted system sys, obtained as sys.ap_name, or a vector of such points. A point belonging to a subsystem is reached through the hierarchy, sys.inner.ap_name. Passing the Symbol name of a point is the old style and will be deprecated.

    Keyword Arguments

    • loop_openings: A list of analysis points whose connections should be removed as a part of the linear analysis. Each entry is an analysis point of the unsimplified, uncompleted system, obtained as sys.ap_name. The disconnected signals keep the value of their drivers at the operating point of the loop-closed system, unless the operating point or an initial condition specifies their value, see the section "Operating Point of Signals Disconnected by Loop Openings" of the linear-analysis tutorial.

    • system_modifier: A function taking the transformed system and applying any additional transformations, returning the modified system. The modified system is passed to linearization_function.

    All other keyword arguments are forwarded to linearization_function.

    source
    ModelingToolkit.get_sensitivity — Method
    get_sensitivity(sys, ap; loop_openings = [], system_modifier = identity, op = Dict(), kwargs...)

    Compute the sensitivity transfer matrices at analysis point ap and return (matrices, simplified_system, extras). This introduces an infinitesimal perturbation at the input of ap, linearizes the system, and computes the transfer function from the perturbation to the output of ap.

    Arguments

    • sys: The unsimplified, uncompleted system containing the analysis point. Both mtkcompile and complete remove the analysis points, so neither may have been applied to sys.
    • ap: An AnalysisPoint, obtained by property access on sys, as in get_sensitivity(sys, sys.plant_input). A point belonging to a subsystem is reached through the hierarchy, sys.inner.plant_input. Passing the Symbol name of the point, get_sensitivity(sys, :plant_input), is the old style and will be deprecated.

    Keyword Arguments

    • loop_openings: connections to open before linearization.
    • system_modifier: transformation applied before linearization.
    • op: operating-point values passed to linearize, a dictionary or a LinearizationOpPoint.
    • allow_input_derivatives: allow derivatives of input variables in the linearization.
    • t: time at which to evaluate the linearization.
    • kwargs...: forwarded to get_sensitivity_function.

    See also get_comp_sensitivity and get_looptransfer.

    source
    ModelingToolkit.get_sensitivity_function — Method
    get_sensitivity_function(
        sys::ModelingToolkitBase.AbstractSystem,
        aps;
        kwargs...
    ) -> Tuple{ModelingToolkit.LinearizationFunction{_A, P, H, _B, J1, J2, J3, J4, IA, @NamedTuple{abstol::Float64, reltol::Float64, nlsolve_alg::Nothing}} where {_A, P<:ODEProblem, H<:FunctionWrappersWrappers.FunctionWrappersWrapper, _B, J1<:Union{Nothing, ModelingToolkit.PreparedJacobian{true, DifferentiationInterfaceForwardDiffExt.ForwardDiffTwoArgJacobianPrep{Nothing, C, Tuple{Nothing, Nothing}}, ModelingToolkit.UFFun{F}, _A, ADTypes.AutoForwardDiff{nothing, Nothing}} where {C<:(ForwardDiff.JacobianConfig{T, _A, _B, <:Tuple{Any, Any}} where {T<:(ForwardDiff.Tag{F} where F<:ModelingToolkit.UFFun), _A, _B}), F, _A}}, J2<:Union{Nothing, ModelingToolkit.PreparedJacobian{true, DifferentiationInterfaceForwardDiffExt.ForwardDiffTwoArgJacobianPrep{Nothing, C, Tuple{Nothing, Nothing}}, FunctionWrappersWrappers.FunctionWrappersWrapper{FW, P, CS}, _A, ADTypes.AutoForwardDiff{nothing, Nothing}} where {C<:(ForwardDiff.JacobianConfig{T, _A, _B, <:Tuple{Any, Any}} where {T<:(ForwardDiff.Tag{F} where F<:FunctionWrappersWrappers.FunctionWrappersWrapper), _A, _B}), FW, P, CS, _A}}, J3<:Union{Nothing, ModelingToolkit.PreparedJacobian{true, DifferentiationInterfaceForwardDiffExt.ForwardDiffTwoArgJacobianPrep{Nothing, C, Tuple{Nothing, Nothing, Nothing}}, ModelingToolkit.PFFun{_A, S}, _A1, ADTypes.AutoForwardDiff{nothing, Nothing}} where {C<:(ForwardDiff.JacobianConfig{T, _A, _B, <:Tuple{Any, Any}} where {T<:(ForwardDiff.Tag{F} where F<:(ModelingToolkit.PFFun{_A, S} where {_A, S<:(SymbolicIndexingInterface.OOPSetter{_A, System} where _A)})), _A, _B}), _A, S<:(SymbolicIndexingInterface.OOPSetter{_A, System} where _A), _A1}}, J4<:(ModelingToolkit.PreparedJacobian{true, DifferentiationInterfaceForwardDiffExt.ForwardDiffTwoArgJacobianPrep{Nothing, C, Tuple{Nothing, Nothing, Nothing}}, ModelingToolkit.HPFun{F, S}, _A, ADTypes.AutoForwardDiff{nothing, Nothing}} where {C<:(ForwardDiff.JacobianConfig{T, _A, _B, <:Tuple{Any, Any}} where {T<:(ForwardDiff.Tag{F} where F<:(ModelingToolkit.HPFun{F, S} where {F<:FunctionWrappersWrappers.FunctionWrappersWrapper, S<:(SymbolicIndexingInterface.OOPSetter{_A, System} where _A)})), _A, _B}), F<:FunctionWrappersWrappers.FunctionWrappersWrapper, S<:(SymbolicIndexingInterface.OOPSetter{_A, System} where _A), _A}), IA<:Union{SciMLBase.NoInit, SciMLBase.OverrideInit{Nothing, Nothing, Nothing}}}, System}
    

    Return the sensitivity function for the analysis point(s) aps, and the modified system simplified with the appropriate inputs and outputs.

    Arguments

    • aps: An analysis point of the unsimplified, uncompleted system sys, obtained as sys.ap_name, or a vector of such points. A point belonging to a subsystem is reached through the hierarchy, sys.inner.ap_name. Passing the Symbol name of a point is the old style and will be deprecated.

    Keyword Arguments

    • loop_openings: A list of analysis points whose connections should be removed as a part of the linear analysis. Each entry is an analysis point of the unsimplified, uncompleted system, obtained as sys.ap_name. The disconnected signals keep the value of their drivers at the operating point of the loop-closed system, unless the operating point or an initial condition specifies their value, see the section "Operating Point of Signals Disconnected by Loop Openings" of the linear-analysis tutorial.

    • system_modifier: A function taking the transformed system and applying any additional transformations, returning the modified system. The modified system is passed to linearization_function.

    All other keyword arguments are forwarded to linearization_function.

    source
    ModelingToolkit.isolate_subsystem — Method
    sys, input_vars, output_vars = isolate_subsystem(sys, input_aps, output_aps)

    Isolate the part of the unsimplified, hierarchical system sys bounded by the input analysis points input_aps and the output analysis points output_aps. The returned sys contains only the subsystems between the boundary analysis points at every level of the hierarchy; all upstream and downstream components, and all equations involving them, are removed.

    The boundary points are obtained as sys.ap_name, or sys.inner.ap_name for a point belonging to a subsystem, and each argument accepts a single point or a vector of points. Passing the Symbol names of the points is the old style and will be deprecated. sys must not have been passed through mtkcompile or complete, both of which remove the analysis points.

    Boundary analysis points may reside at any level of the hierarchy and in different branches of the subsystem tree.

    Returns:

    • sys: The system with only the isolated subsystems and their internal connections.
    • input_vars: Variables at the inside face of each input analysis point.
    • output_vars: Variables at the inside face of each output analysis point.
    source
    ModelingToolkit.linearization_ap_transform — Method
    sys, input_vars, output_vars =
    linearization_ap_transform(
        sys,
        inputs::Union{Vector{Symbol}, Vector{AnalysisPoint}, Symbol, AnalysisPoint},
        outputs,
        loop_openings
    ) -> Tuple{Any, Vararg{Vector{SymbolicUtils.BasicSymbolicImpl.var"typeof(BasicSymbolicImpl)"{SymReal}}, 4}}
    

    Apply analysis-point transformations to prepare a system for linearization.

    inputs, outputs and loop_openings are analysis points of the unsimplified, uncompleted system sys, obtained as sys.ap_name, or vectors of such points. Passing the Symbol names of the points is the old style and will be deprecated.

    Returns

    • sys: The transformed system.
    • input_vars: A vector of input variables corresponding to the input analysis points.
    • output_vars: A vector of output variables corresponding to the output analysis points.
    • loop_opening_params: A vector of the signals disconnected by the loop_openings, including the input variables of input analysis points that are also loop openings.
    • loop_opening_drivers: A vector of the variables that drove the signals in loop_opening_params before the connections were broken, in the same order.
    source