@@ -485,7 +485,7 @@ function generate_system_equations!(state::TearingState, neweqs::Vector{Equation
485485 # algebraic variables.
486486 linsol_result = nothing
487487 if ! is_disc && inline_linear_sccs
488- linsol_result = get_linear_scc_linsol (state, escc, vscc, neweqs, var_eq_matching, total_sub, analytical_linear_scc_limit, simplify)
488+ linsol_result = get_linear_scc_linsol (state, escc, vscc, neweqs, var_eq_matching, full_var_eq_matching, total_sub, analytical_linear_scc_limit, simplify)
489489 end
490490 if linsol_result isa Tuple{SymbolicT, BitVector, BitVector}
491491 linsol, eqs_mask, vars_mask = linsol_result
@@ -536,9 +536,7 @@ function generate_system_equations!(state::TearingState, neweqs::Vector{Equation
536536 # can populate `total_sub` appropriately.
537537 for (i, ieq) in enumerate (escc)
538538 eqs_mask[i] && continue
539- # Currently, if an equation is filtered out it is matched to a variable.
540- # This needs to be changed if we update our heuristic.
541- var = eq_var_matching[ieq]:: Int
539+ var = eq_var_matching[ieq]
542540 codegen_equation! (eq_generator, neweqs[ieq], ieq, var; simplify)
543541 end
544542 else
@@ -607,6 +605,7 @@ All equations not used in the linear system must be solved as normal.
607605function get_linear_scc_linsol (state:: TearingState , alg_eqs:: Vector{Int} ,
608606 alg_vars:: Vector{Int} , neweqs:: Vector{Equation} ,
609607 var_eq_matching:: StateSelection.VarEqMatchingT ,
608+ full_var_eq_matching:: StateSelection.VarEqMatchingT ,
610609 total_sub:: MTKBase.ExpandDerivativeDict{SymbolicT, Dict{SymbolicT, SymbolicT}} ,
611610 analytical_linear_scc_limit:: Int ,
612611 simplify:: Bool ; allow_symbolic:: Bool = false ,
@@ -624,9 +623,27 @@ function get_linear_scc_linsol(state::TearingState, alg_eqs::Vector{Int},
624623 all_torn && return nothing
625624
626625 N = length (alg_eqs)
626+ eqs_mask = trues (N)
627+ vars_mask = trues (N)
628+
629+ eq_to_idx = Dict (Iterators. map (reverse, enumerate (alg_eqs)))
630+
631+ irreds = irreducibles (sys)
632+ eq_var_matching = invview (var_eq_matching)
633+ for (i, iv) in enumerate (alg_vars)
634+ MTKBase. contains_possibly_indexed_element (irreds, fullvars[iv]) || continue
635+ # Irreducible variables are excluded
636+ vars_mask[i] = false
637+ # Along with the equations used for them
638+ ieq = full_var_eq_matching[iv]
639+ eqs_mask[eq_to_idx[ieq]] = false
640+ @assert ! (eq_var_matching[ieq] isa Int)
641+ end
642+
627643 vars = fullvars[alg_vars]
628644
629645 for i in eachindex (vars)
646+ vars_mask[i] || continue
630647 ivar = alg_vars[i]
631648 ieq = var_eq_matching[ivar]
632649 ieq isa Int || continue
@@ -643,6 +660,7 @@ function get_linear_scc_linsol(state::TearingState, alg_eqs::Vector{Int},
643660 b = fill (Symbolics. COMMON_ZERO, N)
644661
645662 for (eqidx, ieq) in enumerate (alg_eqs)
663+ eqs_mask[eqidx] || continue
646664 eq = neweqs[ieq]
647665 resid = eq. rhs
648666 # If `ieq` is a differential equation
@@ -656,8 +674,10 @@ function get_linear_scc_linsol(state::TearingState, alg_eqs::Vector{Int},
656674 end
657675
658676 for (varidx, var) in enumerate (vars)
677+ vars_mask[varidx] || continue
659678 lex = MTKBase. get_linear_expander_for! (sys, var, true )
660679 for (eqidx, resid) in enumerate (b)
680+ eqs_mask[eqidx] || continue
661681 Graphs. has_edge (graph, BipartiteEdge (alg_eqs[eqidx], alg_vars[varidx])) || continue
662682 p, q, islinear = lex (resid)
663683 islinear || return nothing
@@ -672,10 +692,11 @@ function get_linear_scc_linsol(state::TearingState, alg_eqs::Vector{Int},
672692
673693 # `-` is important! `b` is on the other side of the equality.
674694 for i in eachindex (b)
695+ eqs_mask[i] || continue
675696 b[i] = - b[i]
676697 end
677698
678- A, b, eqs_mask, vars_mask = __reduce_linear_system! (A, b, var_eq_matching, alg_eqs, alg_vars)
699+ A, b = __reduce_linear_system! (A, b, var_eq_matching, alg_eqs, alg_vars, eqs_mask, vars_mask )
679700
680701 N = length (b)
681702 A = collect (A):: Matrix{Num}
@@ -770,22 +791,21 @@ function get_linear_scc_linsol(state::TearingState, alg_eqs::Vector{Int},
770791 return (INLINE_LINEAR_SCC_OP (A, b), eqs_mask, vars_mask)
771792end
772793
773- function __reduce_linear_system! (A:: StateSelection.CLIL.SparseMatrixCLIL{Num, Int} , b:: Vector{SymbolicT} , var_eq_matching:: StateSelection.VarEqMatchingT , alg_eqs:: Vector{Int} , alg_vars:: Vector{Int} )
794+ function __reduce_linear_system! (A:: StateSelection.CLIL.SparseMatrixCLIL{Num, Int} , b:: Vector{SymbolicT} , var_eq_matching:: StateSelection.VarEqMatchingT , alg_eqs:: Vector{Int} , alg_vars:: Vector{Int} , eqs_mask :: BitVector , vars_mask :: BitVector )
774795 N = length (b)
775796 # Identify rows (equations) not worth involving in the linear solve.
776797 #
777798 # The current heuristic is to find all rows with constant coefficients
778799 # which are matched to a variable in `var_eq_matching`.
779- eqs_mask = trues (N)
780- vars_mask = trues (N)
781- new_N = N
800+ new_N = count (eqs_mask)
782801 eq_var_matching = invview (var_eq_matching)
783802 var_to_idx = Dict {Int, Int} (Iterators. map (reverse, enumerate (alg_vars)))
784803 # The `i`th variable in the SCC is eliminated as
785804 # `∑_k aliases[i][k] * fullvars[alg_vars[k]] + constants[i]`
786805 constants = Dict {Int, SymbolicT} ()
787806 aliases = Dict {Int, SparseArrays.SparseVector{Num, Int}} ()
788807 for (i, coeffs) in enumerate (A. row_vals)
808+ eqs_mask[i] || continue
789809 eq_var_matching[alg_eqs[i]] isa Int || continue
790810
791811 eqs_mask[i] = false
@@ -880,7 +900,7 @@ function __reduce_linear_system!(A::StateSelection.CLIL.SparseMatrixCLIL{Num, In
880900 old_to_new_eq[.! eqs_mask] .= 0
881901 A = StateSelection. get_new_mm (aliases, old_to_new_eq, old_to_new_var, A)
882902
883- return A, b, eqs_mask, vars_mask
903+ return A, b
884904end
885905
886906"""
0 commit comments