Skip to content

Commit 68004e9

Browse files
Merge pull request #2803 from SciML/myb/tearing_cycle
Fix specialize overdetemined system in tearing
2 parents 7fe6c6f + 4e745a6 commit 68004e9

File tree

4 files changed

+40
-26
lines changed

4 files changed

+40
-26
lines changed

downstream/Project.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
[deps]
2+
ModelingToolkit = "961ee093-0014-501f-94e3-6117800e7a78"

src/structural_transformation/bipartite_tearing/modia_tearing.jl

Lines changed: 17 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -89,45 +89,36 @@ function tear_graph_modia(structure::SystemStructure, isder::F = nothing,
8989

9090
ieqs = Int[]
9191
filtered_vars = BitSet()
92-
seen_eqs = falses(nsrcs(graph))
92+
free_eqs = free_equations(graph, var_sccs, var_eq_matching, varfilter)
93+
is_overdetemined = !isempty(free_eqs)
9394
for vars in var_sccs
9495
for var in vars
9596
if varfilter(var)
9697
push!(filtered_vars, var)
9798
if var_eq_matching[var] !== unassigned
9899
ieq = var_eq_matching[var]
99-
seen_eqs[ieq] = true
100100
push!(ieqs, ieq)
101101
end
102102
end
103103
var_eq_matching[var] = unassigned
104104
end
105-
tear_block!(vargraph, vars,
106-
var_eq_matching, ict, solvable_graph,
107-
ieqs, filtered_vars, isder)
105+
tear_graph_block_modia!(var_eq_matching, ict, solvable_graph, ieqs,
106+
filtered_vars, isder)
107+
# If the systems is overdetemined, we cannot assume the free equations
108+
# will not form algebraic loops with equations in the sccs.
109+
if !is_overdetemined
110+
vargraph.ne = 0
111+
for var in vars
112+
vargraph.matching[var] = unassigned
113+
end
114+
end
115+
empty!(ieqs)
116+
empty!(filtered_vars)
108117
end
109-
free_eqs = findall(!, seen_eqs)
110-
if !isempty(free_eqs)
118+
if is_overdetemined
111119
free_vars = findall(x -> !(x isa Int), var_eq_matching)
112-
tear_block!(vargraph, (),
113-
var_eq_matching, ict, solvable_graph,
114-
free_eqs, BitSet(free_vars), isder)
120+
tear_graph_block_modia!(var_eq_matching, ict, solvable_graph, free_eqs,
121+
BitSet(free_vars), isder)
115122
end
116123
return var_eq_matching, full_var_eq_matching, var_sccs
117124
end
118-
119-
function tear_block!(vargraph, vars,
120-
var_eq_matching, ict, solvable_graph, ieqs,
121-
filtered_vars, isder)
122-
tear_graph_block_modia!(var_eq_matching, ict, solvable_graph, ieqs,
123-
filtered_vars,
124-
isder)
125-
126-
# clear cache
127-
vargraph.ne = 0
128-
for var in vars
129-
vargraph.matching[var] = unassigned
130-
end
131-
empty!(ieqs)
132-
empty!(filtered_vars)
133-
end

src/structural_transformation/tearing.jl

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,3 +68,16 @@ function algebraic_variables_scc(state::TearingState)
6868

6969
return var_eq_matching, var_sccs
7070
end
71+
72+
function free_equations(graph, vars_scc, var_eq_matching, varfilter::F) where {F}
73+
ne = nsrcs(graph)
74+
seen_eqs = falses(ne)
75+
for vars in vars_scc, var in vars
76+
varfilter(var) || continue
77+
ieq = var_eq_matching[var]
78+
if ieq isa Int
79+
seen_eqs[ieq] = true
80+
end
81+
end
82+
findall(!, seen_eqs)
83+
end

test/nonlinearsystem.jl

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -266,3 +266,11 @@ alg_eqs = [0 ~ p - d * X]
266266
sys = @test_nowarn NonlinearSystem(alg_eqs; name = :name)
267267
@test isequal(only(unknowns(sys)), X)
268268
@test all(isequal.(parameters(sys), [p, d]))
269+
270+
# Over-determined sys
271+
@variables u1 u2
272+
@parameters u3 u4
273+
eqs = [u3 ~ u1 + u2, u4 ~ 2 * (u1 + u2), u3 + u4 ~ 3 * (u1 + u2)]
274+
@named ns = NonlinearSystem(eqs, [u1, u2], [u3, u4])
275+
sys = structural_simplify(ns; fully_determined = false)
276+
@test length(unknowns(sys)) == 1

0 commit comments

Comments
 (0)