diff --git a/lib/ModelingToolkitTearing/Project.toml b/lib/ModelingToolkitTearing/Project.toml index 8397003..8f54e43 100644 --- a/lib/ModelingToolkitTearing/Project.toml +++ b/lib/ModelingToolkitTearing/Project.toml @@ -36,7 +36,7 @@ OrderedCollections = "1.8.1" SciMLBase = "2.108" Setfield = "0.7, 0.8, 1" SparseArrays = "1" -StateSelection = "1.8" +StateSelection = "1.9" SymbolicIndexingInterface = "0.3" SymbolicUtils = "4.3" Symbolics = "7.15.1" diff --git a/lib/ModelingToolkitTearing/src/clock_inference/interface.jl b/lib/ModelingToolkitTearing/src/clock_inference/interface.jl index 6ab5e59..1ae4916 100644 --- a/lib/ModelingToolkitTearing/src/clock_inference/interface.jl +++ b/lib/ModelingToolkitTearing/src/clock_inference/interface.jl @@ -69,6 +69,7 @@ function system_subset(ts::TearingState, ieqs::Vector{Int}, iieqs::Vector{Int}, @set! ts.sys.initialization_eqs = initeqs[iieqs] @set! ts.original_eqs = ts.original_eqs[ieqs] @set! ts.structure = system_subset(ts.structure, ieqs, ivars) + @set! ts.always_present = ts.always_present[ivars] if !isempty(ts.eqs_source) @set! ts.eqs_source = ts.eqs_source[ieqs] end diff --git a/lib/ModelingToolkitTearing/src/stateselection_interface.jl b/lib/ModelingToolkitTearing/src/stateselection_interface.jl index b079e0f..f092d77 100644 --- a/lib/ModelingToolkitTearing/src/stateselection_interface.jl +++ b/lib/ModelingToolkitTearing/src/stateselection_interface.jl @@ -5,6 +5,7 @@ function StateSelection.var_derivative!(ts::TearingState, v::Int) D = Differential(MTKBase.get_iv(sys)) push!(ts.fullvars, D(ts.fullvars[v])) push!(ts.structure.state_priorities, ts.structure.state_priorities[v]) + push!(ts.always_present, ts.always_present[v]) return var_diff end @@ -348,6 +349,7 @@ function StateSelection.rm_eqs_vars!( structure, eqs_to_rm, vars_to_rm; eqs_sorted_and_uniqued, vars_sorted_and_uniqued ) deleteat!(state.fullvars, vars_to_rm) + deleteat!(state.always_present, vars_to_rm) eqs = copy(MTKBase.get_eqs(state.sys)) deleteat!(eqs, eqs_to_rm) deleteat!(state.original_eqs, eqs_to_rm) @@ -361,3 +363,6 @@ function StateSelection.rm_eqs_vars!( return old_to_new_eq, old_to_new_var end +function StateSelection.is_unused_var(state::TearingState, var::Integer) + return !state.always_present[var] && isempty(đť‘‘neighbors(state.structure.graph, var)) +end diff --git a/lib/ModelingToolkitTearing/src/tearingstate.jl b/lib/ModelingToolkitTearing/src/tearingstate.jl index 6088642..bc80f50 100644 --- a/lib/ModelingToolkitTearing/src/tearingstate.jl +++ b/lib/ModelingToolkitTearing/src/tearingstate.jl @@ -59,6 +59,23 @@ mutable struct TearingState <: StateSelection.TransformationState{System} are not used in the rest of the system. """ additional_observed::Vector{Equation} + """ + Corresponding to `fullvars`, marks variables which may not be structurally present in + any equation according to `structure.graph` but should not be considered as unused. + This is typically used by variables on the RHS of equations in `additional_observed`, + and is useful for ensuring the consistency check is valid. For example, a simplification + pass prior to `StateSelection.check_consistency` may process the equations + ```julia + a ~ b + b ~ c + c ~ a + ``` + Into `additional_observed = [a ~ b, c ~ b]`, and thus end up in a state where + there are no equations and `fullvars = [b]`. The consistency check would consider `b` as + unused and the system as fully determined, but in reality `b` should be considered + as used and the system singular. + """ + always_present::BitVector statemachines::Vector{System} """ Source information for each equation in the `TearingState`. `Vector{Symbol}` for each @@ -325,7 +342,8 @@ function TearingState(sys::System, source_info::Union{Nothing, MTKBase.EquationS structure = SystemStructure(complete(var_to_diff), complete(eq_to_diff), complete(graph), nothing, var_types, state_priorities, false) return TearingState(sys, fullvars, structure, Equation[], param_derivative_map, - no_deriv_params, original_eqs, Equation[], typeof(sys)[], sources) + no_deriv_params, original_eqs, Equation[], falses(length(fullvars)), + typeof(sys)[], sources) end function build_state_priorities(sys::System, fullvars::Vector{SymbolicT}, var_to_diff::StateSelection.DiffGraph)