Structural Transformation
These APIs support ModelingToolkit's structural-transformation machinery and extension packages. They are version-controlled for ModelingToolkit developers; end-user applications should use the documented public simplification API instead.
These functions are used for structural analysis and transformation of equation systems, including index reduction, tearing, and other algebraic manipulations used in the simplification process.
The names below are versioned developer API. TearingState is mutable compiler state and its fields are intentionally opaque. find_solvables! is retained as a compatibility export; new code should call the documented transformation entry points instead.
Tearing and Algebraic Simplification
ModelingToolkit.StructuralTransformations.tearing — Function
tearing(sys)Tear the nonlinear equations in system. When simplify=true, we simplify the new residual equations after tearing. End users are encouraged to call ModelingToolkitBase.mtkcompile instead, which calls this function internally.
ModelingToolkit.StructuralTransformations.tearing_substitution — Function
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 ModelingToolkitBase.mtkcompile.
Arguments
sys: system whose equations should be substituted.kwargs...: keyword arguments forwarded tofull_equations.
Returns
A copy of sys with substituted equations and no cached schedule.
ModelingToolkit.StructuralTransformations.dummy_derivative — Function
dummy_derivative(sys)Perform index reduction and use the dummy derivative technique to ensure that the system is balanced.
StateSelection.find_solvables! — Function
find_solvables!(
state::StateSelection.TransformationState;
kwargs...
)
Populate state.structure.solvable_graph with information about the solvability of equations. The implementation should validate that state.structure.solvable_graph is nothing before modifying state. The default implementation relies on find_eq_solvables!, to which it forwards all keyword arguments.
Index Reduction
ModelingToolkit.StructuralTransformations.dae_index_lowering — Function
dae_index_lowering(sys::System; kwargs...) -> SystemPerform the Pantelides algorithm to transform a higher index DAE to an index 1 DAE. kwargs are forwarded to the internal Pantelides pass. End users are encouraged to call ModelingToolkitBase.mtkcompile instead, which calls this function internally.
ModelingToolkit.StructuralTransformations.pantelides_reassemble — Function
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.
Incidence Matrix Operations
ModelingToolkit.StructuralTransformations.sorted_incidence_matrix — Function
sorted_incidence_matrix(
sys::ModelingToolkitBase.AbstractSystem
) -> Any
Obtain the incidence matrix of the system sorted by the SCCs. Requires that the system is simplified and has a schedule.
ModelingToolkit.StructuralTransformations.but_ordered_incidence — Function
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.
Variable Ordering and Masks
ModelingToolkit.StructuralTransformations.lowest_order_variable_mask — Function
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.
ModelingToolkit.StructuralTransformations.highest_order_variable_mask — Function
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.
In-Place Compilation
ModelingToolkit.mtkcompile! — Function
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 ModelingToolkitBase.mtkcompile 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.
ModelingToolkitTearing.TearingState — Type
mutable struct TearingState <: StateSelection.TransformationState{System}An implementation of StateSelection.TransformationState for ModelingToolkitBase.System.
Fields
sys::System: The system of equations.fullvars::Vector{SymbolicUtils.BasicSymbolicImpl.var"typeof(BasicSymbolicImpl)"{SymReal}}: The set of variables of the system.structure::ModelingToolkitTearing.SystemStructureextra_eqs::Vector{Equation}param_derivative_map::Dict{SymbolicUtils.BasicSymbolicImpl.var"typeof(BasicSymbolicImpl)"{SymReal}, SymbolicUtils.BasicSymbolicImpl.var"typeof(BasicSymbolicImpl)"{SymReal}}no_deriv_params::Set{SymbolicUtils.BasicSymbolicImpl.var"typeof(BasicSymbolicImpl)"{SymReal}}original_eqs::Vector{Equation}additional_observed::Vector{Equation}: Additional user-provided observed equations. The variables calculated here are not used in the rest of the system.
always_present::BitVector: Corresponding tofullvars, marks variables which may not be structurally present in any equation according tostructure.graphbut should not be considered as unused. This is typically used by variables on the RHS of equations inadditional_observed, and is useful for ensuring the consistency check is valid. For example, a simplification pass prior toStateSelection.check_consistencymay process the equations
Intoa ~ b b ~ c c ~ aadditional_observed = [a ~ b, c ~ b], and thus end up in a state where there are no equations andfullvars = [b]. The consistency check would considerbas unused and the system as fully determined, but in realitybshould be considered as used and the system singular.
statemachines::Vector{System}eqs_source::Vector{Vector{Symbol}}: Source information for each equation in theTearingState.Vector{Symbol}for each equation representing the path of the subsystem to which it belongs. Empty entries indicate unknown source. If this field is empty, either the system has no equations or source information is unknown.
mm::Union{Nothing, StateSelection.CLIL.SparseMatrixCLIL{Int64, Int64}}: ASparseMatrixCLILidentifying equations which are integer-coefficient linear combinations of variables.
analytical_derivatives::Dict{SymbolicUtils.BasicSymbolicImpl.var"typeof(BasicSymbolicImpl)"{SymReal}, SymbolicUtils.BasicSymbolicImpl.var"typeof(BasicSymbolicImpl)"{SymReal}}: A mapping fromD(x)(not thetotermvariant) to its derivative expression for analytically eliminated differential variables. No integrated or differentiated form ofxshould be present in the equations if its derivative specified here. Effectively,xalong with all its integrated and differentiated forms must be eliminated as observed and put intoadditional_observed.
Structural Transformation Interfaces
These upstream interfaces are rendered here because the ModelingToolkit structural transformation developer API dispatches on them.
StateSelection.TransformationState — Type
abstract type TransformationState{T}Supertype for structs representing the state of a system of DAEs during structural transformations. Must have the following fields:
structure<:SystemStructure: ASystemStructuresubtype. Should ideally be concretely typed to a specific implementation.fullvars::AbstractVector{T}: A list of variables in the system, ordered identically to the destination vertices ofstructure.graph. Theeltypeof this buffer can be chosen by the implementor. If this field is not present,get_fullvarsmust be implemented for the type.
In addition to the structural information in structure, this struct typically contains information relevant to the symbolic structure of the system. This can be used to reconstruct the system for code-generation after structural transformations.
StateSelection.TearingAlgorithm — Type
abstract type TearingAlgorithmSupertype for all tearing algorithms. A tearing algorithm takes as input the SystemStructure along with any other necessary arguments.
The output of a tearing algorithm must be a TearingResult and a NamedTuple of any additional data computed in the process that may be useful for further processing.
StateSelection.TearingResult — Type
struct TearingResultA struct containing the results of tearing.
Fields
var_eq_matching::BipartiteGraphs.Matching{Union{BipartiteGraphs.Unassigned, SelectedState}, Vector{Union{BipartiteGraphs.Unassigned, SelectedState, Int64}}}: The variable-equation matching. Differential variables are matched toSelectedState. The derivative of a differential variable is matched to the corresponding differential equation. Solved variables are matched to the equation they are solved from. Algebraic variables are matched tounassigned.
full_var_eq_matching::BipartiteGraphs.Matching{Union{BipartiteGraphs.Unassigned, SelectedState}, Vector{Union{BipartiteGraphs.Unassigned, SelectedState, Int64}}}: The variable-equation matching prior to tearing. This is the maximal matching used to computevar_sccs(see below). For generating the torn system,var_eq_matchingis the source of truth. This should only be used to identify algebraic equations in each SCC.
var_sccs::Vector{Vector{Int64}}: The partitioning of variables into strongly connected components (SCCs). The SCCs are sorted in dependency order, so each SCC depends on variables in previous SCCs.
StateSelection.find_eq_solvables! — Function
find_eq_solvables!(state::TransformationState, ieq::Int; kwargs...)Identify which variables equation ieq can be rearranged to solve for, and populate state.structure.solvable_graph accordingly. Keyword arguments are left to the implementor, and can influence the criteria for solvability.
StateSelection.bareiss.bareiss! — Function
bareiss!(M, [swap_strategy])Perform Bareiss's fraction-free row-reduction algorithm on the matrix M. Optionally, a specific pivoting method may be specified.
swapstrategy is an optional argument that determines how the swapping of rows and columns is performed. bareisscolswap (the default) swaps the columns and rows normally. bareiss_virtcolswap pretends to swap the columns which can be faster for sparse matrices.
StateSelection.CLIL.SparseMatrixCLIL — Type
SparseMatrixCLIL{T, Ti}The SparseMatrixCLIL represents a sparse matrix in two distinct ways:
- As a sparse (in both row and column) n x m matrix
- As a row-dense, column-sparse k x m matrix
The data structure keeps a permutation between the row order of the two representations. Swapping the rows in one does not affect the other.
On construction, the second representation is equivalent to the first with fully-sparse rows removed, though this may cease being true as row permutations are being applied to the matrix.
The default structure of the SparseMatrixCLIL type is the second structure, while the first is available via the thin AsSubMatrix wrapper.
ModelingToolkitTearing.InlineLinearSystem — Type
struct InlineLinearSystemDescription of a single inline linear-solve block in a simplified system: a square linear system $A x = b$ that the generated code re-solves on every evaluation. The tearing/reassemble pass emits such a block when it solves a strongly-connected component of algebraic equations as one linear system, writing each solved variable as an assignment vᵢ ~ (A \ b)[i].
Fields
size::Int64: DimensionNof the squareN×Nlinear system.variables::Vector{SymbolicUtils.BasicSymbolicImpl.var"typeof(BasicSymbolicImpl)"{SymReal}}: The variables solved by the block, ordered by their index in the solution vector. An entry isnothingif that solution component is not assigned to a variable (it should not normally occur).
expression::SymbolicUtils.BasicSymbolicImpl.var"typeof(BasicSymbolicImpl)"{SymReal}: The symbolic solve expressionA \ b(itsargumentsare the coefficient matrixAand the right-hand sideb), retained so callers can inspect or numerically evaluateA, e.g. to check its conditioning.
ModelingToolkitTearing.inline_linear_systems — Function
inline_linear_systems(
sys::ModelingToolkitBase.AbstractSystem
) -> Vector{InlineLinearSystem}
Report the inline linear-solve blocks in the simplified system sys as a Vector{InlineLinearSystem}, sorted by decreasing size.
When tearing solves a strongly-connected component of algebraic equations as one linear system, it emits, into equations(sys) / observed(sys), a square system $A x = b$ that the generated code re-solves on every evaluation as A \ b. Each solution component i then appears as an assignment vᵢ ~ (A \ b)[i]. The reassemble pass records these blocks in the system metadata as it creates them, and this function simply reads them back.
For each block it reports its size N and the N variables it solves for. It is a diagnostic for understanding a compiled model's per-step cost and structure: large blocks are the dominant linear-algebra work each evaluation, and a singularity-prone block can be traced to the physical quantities it determines. Returns an empty vector when sys emits no inline linear solves.