diff --git a/docs/src/API/System.md b/docs/src/API/System.md index b12c08b6ce..7fe46792a0 100644 --- a/docs/src/API/System.md +++ b/docs/src/API/System.md @@ -52,6 +52,8 @@ ModelingToolkit.has_unknowns ModelingToolkit.get_unknowns unknowns ModelingToolkit.unknowns_toplevel +irreducibles +maybe_zeros ModelingToolkit.has_ps ModelingToolkit.get_ps parameters diff --git a/docs/src/API/dynamic_opt.md b/docs/src/API/dynamic_opt.md index 1d94bc2108..667790fdd9 100644 --- a/docs/src/API/dynamic_opt.md +++ b/docs/src/API/dynamic_opt.md @@ -24,11 +24,13 @@ InfiniteOptCollocation(Ipopt.Optimizer, OrthogonalCollocation(3)) ``` ```@docs; canonical = false +AbstractCollocation JuMPCollocation InfiniteOptCollocation CasADiCollocation PyomoCollocation CommonSolve.solve(::AbstractDynamicOptProblem) +DynamicOptSolution ``` ### Problem constructors diff --git a/docs/src/API/variables.md b/docs/src/API/variables.md index 3101adbadc..cb95ad33af 100644 --- a/docs/src/API/variables.md +++ b/docs/src/API/variables.md @@ -12,6 +12,7 @@ Symbolics.@variables @parameters @constants @brownians +@brownian ``` Symbolic variables can have metadata attached to them. The defaults and guesses assigned diff --git a/docs/src/internals/structural_transformation.md b/docs/src/internals/structural_transformation.md index e2a3a2a854..7da7352852 100644 --- a/docs/src/internals/structural_transformation.md +++ b/docs/src/internals/structural_transformation.md @@ -63,6 +63,7 @@ distribute_shift SystemStructure TearingState TransformationState +mtkcompile! isdiffvar isdervar isalgvar @@ -84,4 +85,4 @@ InducedCondensationGraph MatchedCondensationGraph Unassigned unassigned -``` \ No newline at end of file +``` diff --git a/lib/ModelingToolkitBase/src/ModelingToolkitBase.jl b/lib/ModelingToolkitBase/src/ModelingToolkitBase.jl index 34ff9ebf23..b98cd68b0b 100644 --- a/lib/ModelingToolkitBase/src/ModelingToolkitBase.jl +++ b/lib/ModelingToolkitBase/src/ModelingToolkitBase.jl @@ -150,6 +150,15 @@ abstract type AbstractSystem end # See `deprecations.jl`. abstract type IntermediateDeprecationSystem <: AbstractSystem end +""" + independent_variable + +Generic function for querying the primary independent variable of a system-like object. + +Most users should call [`independent_variables`](@ref), which returns the independent +variables as a vector. Packages that define custom system types may extend +`independent_variable` when a scalar independent-variable interface is required. +""" function independent_variable end # this has to be included early to deal with dependency issues @@ -237,9 +246,36 @@ include("inputoutput.jl") include("deprecations.jl") +""" + t_nounits + +Unitless default independent variable used by ModelingToolkit examples and constructors. + +# Examples + +```julia +using ModelingToolkitBase + +t = ModelingToolkitBase.t_nounits +``` +""" const t_nounits = let only(@independent_variables t) end + +""" + D_nounits + +Default unitless differential operator `Differential(t_nounits)`. + +# Examples + +```julia +using ModelingToolkitBase + +D = ModelingToolkitBase.D_nounits +``` +""" const D_nounits = Differential(t_nounits) export CompilerOptions diff --git a/lib/ModelingToolkitBase/src/deprecations.jl b/lib/ModelingToolkitBase/src/deprecations.jl index 7f6ae09915..0c40717d9e 100644 --- a/lib/ModelingToolkitBase/src/deprecations.jl +++ b/lib/ModelingToolkitBase/src/deprecations.jl @@ -1,8 +1,34 @@ -@deprecate structural_simplify(sys; kwargs...) mtkcompile(sys; kwargs...) -@deprecate structural_simplify(sys, io; kwargs...) mtkcompile( - sys; inputs = io[1], outputs = io[2], kwargs... -) +""" + structural_simplify(sys; kwargs...) + structural_simplify(sys, io; kwargs...) +Deprecated alias for [`mtkcompile`](@ref). + +Use `mtkcompile(sys; kwargs...)` in new code. +""" +function structural_simplify(sys; kwargs...) + Base.depwarn( + "`structural_simplify(sys; kwargs...)` is deprecated. Use `mtkcompile(sys; kwargs...)` instead.", + :structural_simplify + ) + return mtkcompile(sys; kwargs...) +end + +function structural_simplify(sys, io; kwargs...) + Base.depwarn( + "`structural_simplify(sys, io; kwargs...)` is deprecated. Use `mtkcompile(sys; inputs = io[1], outputs = io[2], kwargs...)` instead.", + :structural_simplify + ) + return mtkcompile(sys; inputs = io[1], outputs = io[2], kwargs...) +end + +""" + @mtkbuild expr + +Deprecated alias for [`@mtkcompile`](@ref). + +Use `@mtkcompile` in new code. +""" macro mtkbuild(exprs...) return quote Base.depwarn("`@mtkbuild` is deprecated. Use `@mtkcompile` instead.", :mtkbuild) @@ -15,6 +41,13 @@ macro mtkbuild(exprs...) end |> esc end +""" + ODESystem(args...; kwargs...) + +Deprecated alias for [`System`](@ref). + +Use `System(args...; kwargs...)` in new code. +""" const ODESystem = IntermediateDeprecationSystem function IntermediateDeprecationSystem(args...; kwargs...) @@ -202,6 +235,13 @@ for T in [ end end +""" + @brownian xs... + +Deprecated alias for [`@brownians`](@ref). + +Use `@brownians` in new code. +""" macro brownian(xs...) return quote Base.depwarn( diff --git a/lib/ModelingToolkitBase/src/systems/abstractsystem.jl b/lib/ModelingToolkitBase/src/systems/abstractsystem.jl index 9a66492f88..07932b6d4f 100644 --- a/lib/ModelingToolkitBase/src/systems/abstractsystem.jl +++ b/lib/ModelingToolkitBase/src/systems/abstractsystem.jl @@ -1829,6 +1829,34 @@ function state_priorities(sys::AbstractSystem) return sps end +""" + irreducibles(sys::AbstractSystem) + +Return the variables in `sys` and its subsystems that are marked as irreducible. + +Irreducible variables are preserved as unknowns during simplification instead of being +eliminated as observed variables when possible. + +# Arguments + +- `sys`: system to inspect recursively. + +# Returns + +An atomic set of symbolic variables, with subsystem variables namespaced into `sys`. + +# Examples + +```julia +using ModelingToolkitBase +using ModelingToolkitBase: t_nounits as t, D_nounits as D + +@variables x(t) [irreducible = true] +@named sys = System([D(x) ~ -x], t) + +irreducibles(sys) +``` +""" function irreducibles(sys::AbstractSystem) ircs = get_irreducibles(sys) systems = get_systems(sys) @@ -1840,6 +1868,22 @@ function irreducibles(sys::AbstractSystem) return ircs end +""" + maybe_zeros(sys::AbstractSystem) + +Return variables in `sys` and its subsystems that simplification may constrain to zero. + +This is primarily used by structural simplification to track variables introduced or +retained while handling alias equations. + +# Arguments + +- `sys`: system to inspect recursively. + +# Returns + +An atomic set of symbolic variables, with subsystem variables namespaced into `sys`. +""" function maybe_zeros(sys::AbstractSystem) dds = get_maybe_zeros(sys) systems = get_systems(sys) diff --git a/lib/ModelingToolkitBase/src/systems/optimal_control_interface.jl b/lib/ModelingToolkitBase/src/systems/optimal_control_interface.jl index 990487c0e1..b79cf3609c 100644 --- a/lib/ModelingToolkitBase/src/systems/optimal_control_interface.jl +++ b/lib/ModelingToolkitBase/src/systems/optimal_control_interface.jl @@ -1,5 +1,25 @@ +""" + AbstractCollocation + +Abstract supertype for dynamic-optimization collocation method descriptors. + +Concrete collocation types are provided by backend extensions such as JuMP, InfiniteOpt, +CasADi, and Pyomo. +""" abstract type AbstractCollocation end +""" + DynamicOptSolution(model, sol, input_sol) + +Solution wrapper returned by dynamic-optimization backends. + +# Fields + +- `model`: backend-specific optimization model. +- `sol`: state trajectory as an `ODESolution`. +- `input_sol`: controller/input trajectory as an `ODESolution`, or `nothing` when the + backend does not return one. +""" struct DynamicOptSolution model::Any sol::ODESolution diff --git a/lib/ModelingToolkitBase/src/utils.jl b/lib/ModelingToolkitBase/src/utils.jl index 7744d8ddf5..439c2c635a 100644 --- a/lib/ModelingToolkitBase/src/utils.jl +++ b/lib/ModelingToolkitBase/src/utils.jl @@ -536,6 +536,20 @@ function collect_guesses!(guesses::SymmapT, vars::Vector{SymbolicT}) return end +""" + collect_var_to_name!(vars::Dict{Symbol, SymbolicT}, xs::Vector{SymbolicT}) + +Populate `vars` with mappings from symbolic variable names to variables. + +# Arguments + +- `vars`: dictionary updated in place. +- `xs`: symbolic variables to inspect. + +# Returns + +`nothing`. Throws `ArgumentError` if two distinct variables have the same name. +""" function collect_var_to_name!(vars::Dict{Symbol, SymbolicT}, xs::Vector{SymbolicT}) for x in xs SU.isconst(x) && continue diff --git a/lib/ModelingToolkitBase/src/variables.jl b/lib/ModelingToolkitBase/src/variables.jl index edcd9dc8a2..6a53ceeed5 100644 --- a/lib/ModelingToolkitBase/src/variables.jl +++ b/lib/ModelingToolkitBase/src/variables.jl @@ -495,6 +495,32 @@ function hasnominal(x) return Symbolics.getmetadata_maybe_indexed(unwrap(x), VariableNominal, nothing) !== nothing end +""" + setnominal(x, val) + +Return `x` with nominal-value metadata set to `val`. + +# Arguments + +- `x`: symbolic variable to annotate. +- `val`: nominal value used for scaling and numerical conditioning. + +# Returns + +A symbolic variable equivalent to `x` with updated `VariableNominal` metadata. + +# Examples + +```julia +using ModelingToolkitBase + +@variables x +x = setnominal(x, 10.0) +getnominal(x) +``` + +See also [`getnominal`](@ref) and [`hasnominal`](@ref). +""" function setnominal(x::Num, val) return setmetadata(x, VariableNominal, val) end @@ -705,6 +731,14 @@ isbrownian(s) = getvariabletype(s) === BROWNIAN $(SIGNATURES) Define one or more Brownian variables. + +# Examples + +```julia +using ModelingToolkitBase + +@brownians B +``` """ macro brownians(xs...) all( diff --git a/src/ModelingToolkit.jl b/src/ModelingToolkit.jl index d13f850597..be80809ca0 100644 --- a/src/ModelingToolkit.jl +++ b/src/ModelingToolkit.jl @@ -167,6 +167,38 @@ export get_sensitivity_function, get_comp_sensitivity_function, get_looptransfer_function, get_sensitivity, get_comp_sensitivity, get_looptransfer export isolate_subsystem +""" + FMIComponent(version; fmu, type, name, kwargs...) + +Construct a ModelingToolkit component from a Functional Mock-up Unit (FMU). + +# Arguments + +- `version`: a `Val` selecting the FMI major version, for example `Val(2)`. + +# Keyword Arguments + +- `fmu`: the loaded FMU object. +- `type`: the FMI interface type, such as `:ME` for model exchange. +- `name`: the component name used by `@named`. +- `kwargs...`: additional FMI extension options. + +# Returns + +An `AbstractSystem` component representing the FMU interface. + +# Examples + +```julia +using ModelingToolkit + +@named model = ModelingToolkit.FMIComponent(Val(2); fmu, type = :ME) +``` + +!!! note + `FMIComponent` is implemented by the FMI extension. Load the FMI dependency before + constructing FMU-backed components. +""" function FMIComponent end @public linearize_symbolic, reorder_unknowns diff --git a/src/linearization.jl b/src/linearization.jl index 4cb69d53ce..f2ea43ae33 100644 --- a/src/linearization.jl +++ b/src/linearization.jl @@ -555,14 +555,42 @@ function CommonSolve.solve(prob::LinearizationProblem; allow_input_derivatives = end """ - (; A, B, C, D), simplified_sys = linearize_symbolic(sys::AbstractSystem, inputs, outputs; simplify = false, allow_input_derivatives = false, kwargs...) + matrices, simplified_sys = linearize_symbolic(sys::AbstractSystem, inputs, outputs; + simplify = false, + allow_input_derivatives = false, + eval_expression = false, + eval_module = @__MODULE__, + split = true, + kwargs...) -Similar to [`linearize`](@ref), but returns symbolic matrices `A,B,C,D` rather than numeric. While `linearize` uses ForwardDiff to perform the linearization, this function uses `Symbolics.jacobian`. +Symbolically linearize `sys` between `inputs` and `outputs`. -See [`linearize`](@ref) for a description of the arguments. +Unlike [`linearize`](@ref), this uses `Symbolics.jacobian` and returns symbolic +matrices instead of numerical matrices evaluated at an operating point. + +# Arguments + +- `sys`: the system to linearize. This function calls [`mtkcompile`](@ref) internally. +- `inputs`: input variables used as the columns of the `B` and `D` matrices. +- `outputs`: output variables used as the rows of the `C` and `D` matrices. + +# Keyword Arguments + +- `simplify`: whether to run additional symbolic simplification during compilation. +- `allow_input_derivatives`: whether differentiated inputs may appear in the + linearized equations. If `true`, `B` and `D` include extra columns for those derivatives. +- `eval_expression`: whether generated expressions are evaluated directly instead of + using runtime-generated functions. +- `eval_module`: the module used when `eval_expression = true`. +- `split`: whether generated functions use a tuple of parameters or splatted parameters. +- `kwargs...`: additional keyword arguments forwarded to [`mtkcompile`](@ref). + +# Returns + +A pair `(matrices, simplified_sys)`. `matrices` is a `NamedTuple` containing `A`, +`B`, `C`, and `D`, plus the symbolic Jacobian blocks `f_x`, `f_z`, `g_x`, `g_z`, +`f_u`, `g_u`, `h_x`, `h_z`, and `h_u` of -# Extended help -The named tuple returned as the first argument additionally contains the jacobians `f_x, f_z, g_x, g_z, f_u, g_u, h_x, h_z, h_u` of ```math \\begin{aligned} ẋ &= f(x, z, u) \\\\ @@ -570,7 +598,27 @@ ẋ &= f(x, z, u) \\\\ y &= h(x, z, u) \\end{aligned} ``` -where `x` are differential unknown variables, `z` algebraic variables, `u` inputs and `y` outputs. + +Here `x` are differential unknowns, `z` are algebraic unknowns, `u` are inputs, +and `y` are outputs. + +# Examples + +```julia +using ModelingToolkit +using ModelingToolkit: t_nounits as t, D_nounits as D + +@variables x(t) = 1.0 u(t) = 0.0 y(t) = 0.0 +eqs = [D(x) ~ -x + u, + y ~ x] +@named sys = System(eqs, t) + +matrices, simplified_sys = ModelingToolkit.linearize_symbolic(sys, [u], [y]) +matrices.A +``` + +See also [`linearize`](@ref), [`linearization_function`](@ref), and +[`reorder_unknowns`](@ref). """ function linearize_symbolic( sys::AbstractSystem, inputs, @@ -845,7 +893,21 @@ end """ (; Ã, B̃, C̃, D̃) = similarity_transform(sys, T; unitary=false) -Perform a similarity transform `T : Tx̃ = x` on linear system represented by matrices in NamedTuple `sys` such that +Transform the state coordinates of a linear state-space model. + +# Arguments + +- `sys`: a `NamedTuple` with matrices `A`, `B`, `C`, and `D`, as returned by + [`linearize`](@ref) or [`linearize_symbolic`](@ref). +- `T`: the coordinate transformation matrix where `T * x̃ = x`. + +# Keyword Arguments + +- `unitary`: if `true`, use the adjoint `T'` instead of factoring and solving with `T`. + +# Returns + +A `NamedTuple` `(; A, B, C, D)` containing ``` Ã = T⁻¹AT @@ -854,7 +916,15 @@ C̃ = CT D̃ = D ``` -If `unitary=true`, `T` is assumed unitary and the matrix adjoint is used instead of the inverse. +# Examples + +```julia +sys = (; A = [-1.0 0.0; 0.0 -2.0], B = [1.0; 0.0;;], + C = [0.0 1.0], D = zeros(1, 1)) +T = [0.0 1.0; 1.0 0.0] + +transformed = ModelingToolkit.similarity_transform(sys, T; unitary = true) +``` """ function similarity_transform(sys::NamedTuple, T; unitary = false) if unitary @@ -873,16 +943,28 @@ end """ reorder_unknowns(sys::NamedTuple, old, new) -Permute the state representation of `sys` obtained from [`linearize`](@ref) so that the state unknown is changed from `old` to `new` -Example: +Permute the state ordering of a linearized system. -``` +# Arguments + +- `sys`: a `NamedTuple` with matrices `A`, `B`, `C`, and `D`, as returned by + [`linearize`](@ref) or [`linearize_symbolic`](@ref). +- `old`: the current state order, typically `unknowns(simplified_sys)`. +- `new`: the desired state order. It must contain the same entries as `old`. + +# Returns + +A `NamedTuple` `(; A, B, C, D)` whose state-space matrices use the order `new`. + +# Examples + +```julia lsys, ssys = linearize(pid, [reference.u, measurement.u], [ctr_output.u]) desired_order = [int.x, der.x] # Unknowns that are present in unknowns(ssys) lsys = ModelingToolkit.reorder_unknowns(lsys, unknowns(ssys), desired_order) ``` -See also [`ModelingToolkit.similarity_transform`](@ref) +See also [`similarity_transform`](@ref). """ function reorder_unknowns(sys::NamedTuple, old, new) nx = length(old) diff --git a/src/structural_transformation/StructuralTransformations.jl b/src/structural_transformation/StructuralTransformations.jl index 737384749f..9d94ea4dfe 100644 --- a/src/structural_transformation/StructuralTransformations.jl +++ b/src/structural_transformation/StructuralTransformations.jl @@ -66,6 +66,23 @@ export but_ordered_incidence, lowest_order_variable_mask, highest_order_variable include("utils.jl") include("pantelides.jl") +""" + tearing_substitution(sys::AbstractSystem; kwargs...) + +Replace the equations of `sys` with its fully substituted equations. + +This is a structural-transformation helper used by simplification passes. End-user code +should usually call [`mtkcompile`](@ref). + +# Arguments + +- `sys`: system whose equations should be substituted. +- `kwargs...`: keyword arguments forwarded to [`full_equations`](@ref). + +# Returns + +A copy of `sys` with substituted equations and no cached schedule. +""" function tearing_substitution(sys::AbstractSystem; kwargs...) neweqs = full_equations(sys::AbstractSystem; kwargs...) @set! sys.eqs = neweqs diff --git a/src/structural_transformation/pantelides.jl b/src/structural_transformation/pantelides.jl index 88e9df1dd2..6b4fde49fe 100644 --- a/src/structural_transformation/pantelides.jl +++ b/src/structural_transformation/pantelides.jl @@ -4,6 +4,21 @@ const NOTHING_EQ = nothing ~ nothing +""" + pantelides_reassemble(state::TearingState, var_eq_matching) + +Reassemble a `System` after Pantelides index reduction. + +# Arguments + +- `state`: tearing state containing the original system and derivative graphs. +- `var_eq_matching`: variable-equation matching returned by the Pantelides pass. + +# Returns + +A system whose equations and unknowns include the differentiated equations selected by +the Pantelides algorithm. +""" function pantelides_reassemble(state::TearingState, var_eq_matching) fullvars = state.fullvars @unpack var_to_diff, eq_to_diff = state.structure diff --git a/src/structural_transformation/utils.jl b/src/structural_transformation/utils.jl index d978a61846..7037db16aa 100644 --- a/src/structural_transformation/utils.jl +++ b/src/structural_transformation/utils.jl @@ -26,18 +26,59 @@ end ### ### Structural and symbolic utilities ### +""" + highest_order_variable_mask(ts) + +Return a predicate selecting highest-order variables in a tearing state. + +# Arguments + +- `ts`: tearing state whose derivative graph should be inspected. + +# Returns + +A predicate `f(v)::Bool` over variable indices. +""" function highest_order_variable_mask(ts) return let v2d = ts.structure.var_to_diff v -> isempty(outneighbors(v2d, v)) end end +""" + lowest_order_variable_mask(ts) + +Return a predicate selecting lowest-order variables in a tearing state. + +# Arguments + +- `ts`: tearing state whose derivative graph should be inspected. + +# Returns + +A predicate `f(v)::Bool` over variable indices. +""" function lowest_order_variable_mask(ts) return let v2d = ts.structure.var_to_diff v -> isempty(inneighbors(v2d, v)) end end +""" + but_ordered_incidence(ts::TearingState, varmask = highest_order_variable_mask(ts)) + +Construct the block upper triangular ordered incidence matrix for `ts`. + +# Arguments + +- `ts`: tearing state to analyze. +- `varmask`: predicate selecting which variable indices participate in the ordering. + +# Returns + +A pair `(matrix, block_boundaries)` containing the ordered incidence matrix and the +starting row/column boundaries for each block. +""" function but_ordered_incidence(ts::TearingState, varmask = highest_order_variable_mask(ts)) graph = complete(ts.structure.graph) var_eq_matching = complete(maximal_matching(graph; srcfilter = _ -> true, dstfilter = varmask)) diff --git a/src/systems/alias_elimination.jl b/src/systems/alias_elimination.jl index 86e12e02ee..534de24279 100644 --- a/src/systems/alias_elimination.jl +++ b/src/systems/alias_elimination.jl @@ -1,6 +1,22 @@ using SymbolicUtils: Rewriters using Graphs.Experimental.Traversals +""" + alias_elimination(sys) + +Run the alias-elimination pass on `sys`. + +This is a lower-level structural simplification pass used by [`mtkcompile`](@ref). +End-user code should usually call `mtkcompile` instead. + +# Arguments + +- `sys`: system to transform. + +# Returns + +The alias-eliminated system. +""" alias_elimination(sys) = alias_elimination!(TearingState(sys))[1] """ diff --git a/src/systems/substitute_component.jl b/src/systems/substitute_component.jl index 122cd75a8a..0841875044 100644 --- a/src/systems/substitute_component.jl +++ b/src/systems/substitute_component.jl @@ -151,6 +151,14 @@ Given a hierarchical system `sys` and a rule `lhs => rhs`, replace the subsystem obtained via `sys.inner.component`). The `rhs` must be valid as per the following conditions: +# Arguments + +- `sys`: the system whose nested subsystem should be replaced. +- `rule`: a pair `lhs => rhs`, where `lhs` is the namespaced subsystem to replace and + `rhs` is the unnamespaced replacement system. + +# Replacement Rules + 1. `rhs` must not be namespaced. 2. The name of `rhs` must be the same as the unnamespaced name of `lhs`. 3. Neither one of `lhs` or `rhs` can be marked as complete. @@ -165,6 +173,29 @@ conditions: be a connector of the same type. `sys` also cannot be marked as complete. + +# Returns + +A new system with the selected subsystem replaced and connection equations rebuilt. + +# Examples + +```julia +using ModelingToolkit +using ModelingToolkit: t_nounits as t, D_nounits as D + +function Block(k; name) + @variables x(t) = 0 + @parameters p = k + System([D(x) ~ -p * x], t; name) +end + +@named old_block = Block(1) +@named new_block = Block(2) +@named sys = System(Equation[], t; systems = [old_block]) + +updated = substitute_component(sys, sys.old_block => new_block) +``` """ function substitute_component(sys::T, rule::Pair{T, T}) where {T <: AbstractSystem} iscomplete(sys) && diff --git a/src/systems/systems.jl b/src/systems/systems.jl index 306e93d1fc..59e3be513d 100644 --- a/src/systems/systems.jl +++ b/src/systems/systems.jl @@ -146,11 +146,37 @@ Given a system that has been simplified via `mtkcompile`, return a `Dict` mappin variables of the system to equations that are used to solve for them. This includes observed variables. +# Arguments + +- `sys`: a system returned by [`mtkcompile`](@ref) or another simplification path that + records a tearing state. + # Keyword Arguments - `rename_dummy_derivatives`: Whether to rename dummy derivative variable keys into their `Differential` forms. For example, this would turn the key `yˍt(t)` into `Differential(t)(y(t))`. + +# Returns + +A `Dict` mapping unknown or observed symbolic variables to the equations used to solve +for them. + +# Examples + +```julia +using ModelingToolkit +using ModelingToolkit: t_nounits as t, D_nounits as D + +@variables x(t) = 1 y(t) = 0 +eqs = [D(x) ~ -x, + y ~ x + 1] +@named sys = System(eqs, t) +simplified = mtkcompile(sys) + +mapping = map_variables_to_equations(simplified) +mapping[y] +``` """ function map_variables_to_equations(sys::AbstractSystem; rename_dummy_derivatives = true) if !has_tearing_state(sys) diff --git a/src/systems/systemstructure.jl b/src/systems/systemstructure.jl index 19bc4dd849..d1e64b6d97 100644 --- a/src/systems/systemstructure.jl +++ b/src/systems/systemstructure.jl @@ -97,6 +97,33 @@ function inputs_to_parameters!(state::TearingState, inputsyms::OrderedSet{Symbol return state end +""" + mtkcompile!(state::TearingState; kwargs...) + +Mutating structural simplification entry point for an existing tearing state. + +This is developer-facing API used by ModelingToolkit internals and extension packages that +already have a `TearingState`. User code should normally call [`mtkcompile`](@ref) on a +`System` instead. + +# Arguments + +- `state`: tearing state to simplify in place. + +# Keyword Arguments + +- `check_consistency`: whether to check the transformed system for structural consistency. +- `fully_determined`: whether the transformed system is expected to have a square + equation/unknown structure. +- `inputs`: variables to treat as external inputs. +- `outputs`: variables to treat as requested outputs. +- `disturbance_inputs`: input variables that should be treated as disturbances. +- `kwargs...`: additional simplification options forwarded to the internal compiler. + +# Returns + +The simplified `System`. +""" function mtkcompile!( state::TearingState; check_consistency = true, fully_determined = true,