Skip to content

Commit 8c714fc

Browse files
feat: add allow_algebraic, default allow_symbolic to false
1 parent e29a989 commit 8c714fc

File tree

5 files changed

+59
-24
lines changed

5 files changed

+59
-24
lines changed

src/structural_transformation/partial_state_selection.jl

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -170,11 +170,11 @@ function partial_state_selection_graph!(structure::SystemStructure, var_eq_match
170170
end
171171

172172
function dummy_derivative_graph!(state::TransformationState, jac = nothing;
173-
state_priority = nothing, log = Val(false), kwargs...)
174-
state.structure.solvable_graph === nothing && find_solvables!(state; kwargs...)
173+
state_priority = nothing, log = Val(false), allow_symbolic = false, kwargs...)
174+
state.structure.solvable_graph === nothing && find_solvables!(state; allow_symbolic, kwargs...)
175175
complete!(state.structure)
176-
var_eq_matching = complete(pantelides!(state; kwargs...))
177-
dummy_derivative_graph!(state.structure, var_eq_matching, jac, state_priority, log)
176+
var_eq_matching = complete(pantelides!(state; allow_symbolic, kwargs...))
177+
dummy_derivative_graph!(state.structure, var_eq_matching, jac, state_priority, log; allow_symbolic)
178178
end
179179

180180
struct DummyDerivativeSummary
@@ -184,7 +184,7 @@ end
184184

185185
function dummy_derivative_graph!(
186186
structure::SystemStructure, var_eq_matching, jac = nothing,
187-
state_priority = nothing, ::Val{log} = Val(false)) where {log}
187+
state_priority = nothing, ::Val{log} = Val(false); allow_symbolic = false) where {log}
188188
@unpack eq_to_diff, var_to_diff, graph = structure
189189
diff_to_eq = invview(eq_to_diff)
190190
diff_to_var = invview(var_to_diff)
@@ -342,7 +342,12 @@ function dummy_derivative_graph!(
342342
@warn "The number of dummy derivatives ($n_dummys) does not match the number of differentiated equations ($n_diff_eqs)."
343343
end
344344

345-
ret = tearing_with_dummy_derivatives(structure, BitSet(dummy_derivatives))
345+
dummy_derivatives_set = BitSet(dummy_derivatives)
346+
if !allow_symbolic
347+
make_differential_denominators_unsolvable!(structure, dummy_derivatives_set)
348+
end
349+
350+
ret = tearing_with_dummy_derivatives(structure, dummy_derivatives_set)
346351
if log
347352
(ret..., DummyDerivativeSummary(var_dummy_scc, var_state_priority))
348353
else

src/structural_transformation/symbolics_tearing.jl

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -988,8 +988,11 @@ end
988988
ndims = ndims(arr)
989989
end
990990

991-
function tearing(state::TearingState; kwargs...)
992-
state.structure.solvable_graph === nothing && find_solvables!(state; kwargs...)
991+
function tearing(state::TearingState; allow_symbolic = false, kwargs...)
992+
state.structure.solvable_graph === nothing && find_solvables!(state; allow_symbolic, kwargs...)
993+
if !allow_symbolic
994+
make_differential_denominators_unsolvable!(state.structure)
995+
end
993996
complete!(state.structure)
994997
tearing_with_dummy_derivatives(state.structure, ())
995998
end

src/structural_transformation/utils.jl

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -275,6 +275,21 @@ function find_eq_solvables!(state::TearingState, ieq::Int, to_rm = Int[], coeffs
275275
all_int_vars, term
276276
end
277277

278+
"""
279+
$(TYPEDSIGNATURES)
280+
281+
Remove edges in `structure.solvable_graph` that require differential variables in the
282+
denominator to solve. `additional_algevars` is a collection of integers corresponding to
283+
differential variables that should be considered as algebraic for the purpose of this
284+
transformation.
285+
"""
286+
function make_differential_denominators_unsolvable!(structure::SystemStructure, additional_algevars = ())
287+
for ((eqi, vari), denoms) in structure.denominators
288+
all(i -> isalgvar(structure, i) || i in additional_algevars, denoms) && continue
289+
rem_edge!(structure.solvable_graph, eqi, vari)
290+
end
291+
end
292+
278293
function find_solvables!(state::TearingState; kwargs...)
279294
@assert state.structure.solvable_graph === nothing
280295
eqs = equations(state)

src/systems/systems.jl

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -18,21 +18,30 @@ Structurally simplify algebraic equations in a system and compute the
1818
topological sort of the observed equations in `sys`.
1919
2020
### Optional Arguments:
21-
+ optional argument `io` may take a tuple `(inputs, outputs)`. This will convert all `inputs` to parameters and allow them to be unconnected, i.e., simplification will allow models where `n_unknowns = n_equations - n_inputs`.
21+
+ optional argument `io` may take a tuple `(inputs, outputs)`. This will convert all
22+
`inputs` to parameters and allow them to be unconnected, i.e., simplification will
23+
allow models where `n_unknowns = n_equations - n_inputs`.
2224
2325
### Optional Keyword Arguments:
24-
+ When `simplify=true`, the `simplify` function will be applied during the tearing process.
25-
+ `allow_symbolic=true`, `allow_parameter=true`, and `conservative=false` limit the coefficient types during tearing. In particular, `conservative=true` limits tearing to only solve for trivial linear systems where the coefficient has the absolute value of ``1``.
26-
+ `fully_determined=true` controls whether or not an error will be thrown if the number of equations don't match the number of inputs, outputs, and equations.
26+
+ When `simplify=true`, the `simplify` function will be applied during the tearing
27+
process.
28+
+ `allow_symbolic=false`, `allow_algebraic=true`, `allow_parameter=true`, and
29+
`conservative=false` limit the coefficient types during tearing. In particular,
30+
`conservative=true` limits tearing to only solve for trivial linear systems where
31+
the coefficient has the absolute value of ``1``. `allow_symbolic` allows arbitrary
32+
symbolic coefficients. If it is false, `allow_algebraic` allows symbolic coefficients
33+
involving only algebraic variables and parameters. Otherwise, `allow_parameter` only
34+
allows coefficients containing parameters.
35+
+ `fully_determined=true` controls whether or not an error will be thrown if the number
36+
of equations don't match the number of inputs, outputs, and equations.
2737
"""
2838
function structural_simplify(
2939
sys::AbstractSystem, io = nothing; additional_passes = [], simplify = false, split = true,
30-
allow_symbolic = true, allow_parameter = true, conservative = false, fully_determined = true,
31-
kwargs...)
40+
allow_symbolic = false, allow_algebraic = true, allow_parameter = true, conservative = false,
41+
fully_determined = true, kwargs...)
3242
isscheduled(sys) && throw(RepeatedStructuralSimplificationError())
33-
newsys′ = __structural_simplify(sys, io; simplify,
34-
allow_symbolic, allow_parameter, conservative, fully_determined,
35-
kwargs...)
43+
newsys′ = __structural_simplify(sys, io; simplify, allow_symbolic, allow_algebraic,
44+
allow_parameter, conservative, fully_determined, kwargs...)
3645
if newsys′ isa Tuple
3746
@assert length(newsys′) == 2
3847
newsys = newsys′[1]

src/systems/systemstructure.jl

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -694,7 +694,7 @@ end
694694

695695
function _structural_simplify!(state::TearingState, io; simplify = false,
696696
check_consistency = true, fully_determined = true, warn_initialize_determined = false,
697-
dummy_derivative = true,
697+
dummy_derivative = true, allow_symbolic = false,
698698
kwargs...)
699699
if fully_determined isa Bool
700700
check_consistency &= fully_determined
@@ -711,24 +711,27 @@ function _structural_simplify!(state::TearingState, io; simplify = false,
711711
else
712712
input_idxs = 0:-1 # Empty range
713713
end
714-
sys, mm = ModelingToolkit.alias_elimination!(state; kwargs...)
714+
sys, mm = ModelingToolkit.alias_elimination!(state; allow_symbolic, kwargs...)
715715
if check_consistency
716716
fully_determined = ModelingToolkit.check_consistency(
717717
state, orig_inputs; nothrow = fully_determined === nothing)
718718
end
719719
if fully_determined && dummy_derivative
720720
sys = ModelingToolkit.dummy_derivative(
721-
sys, state; simplify, mm, check_consistency, kwargs...)
721+
sys, state; simplify, mm, check_consistency, allow_symbolic, kwargs...)
722722
elseif fully_determined
723-
var_eq_matching = pantelides!(state; finalize = false, kwargs...)
723+
var_eq_matching = pantelides!(state; finalize = false, allow_symbolic, kwargs...)
724+
if !allow_symbolic
725+
StructuralTransformations.make_differential_denominators_unsolvable!(state.structure)
726+
end
724727
sys = pantelides_reassemble(state, var_eq_matching)
725728
state = TearingState(sys)
726-
sys, mm = ModelingToolkit.alias_elimination!(state; kwargs...)
729+
sys, mm = ModelingToolkit.alias_elimination!(state; allow_symbolic, kwargs...)
727730
sys = ModelingToolkit.dummy_derivative(
728-
sys, state; simplify, mm, check_consistency, kwargs...)
731+
sys, state; simplify, mm, check_consistency, allow_symbolic, kwargs...)
729732
else
730733
sys = ModelingToolkit.tearing(
731-
sys, state; simplify, mm, check_consistency, kwargs...)
734+
sys, state; simplify, mm, check_consistency, allow_symbolic, kwargs...)
732735
end
733736
fullunknowns = [map(eq -> eq.lhs, observed(sys)); unknowns(sys)]
734737
@set! sys.observed = ModelingToolkit.topsort_equations(observed(sys), fullunknowns)

0 commit comments

Comments
 (0)