Skip to content

Commit 1067cc0

Browse files
fix: handle edge cases in trivial observed identification in generate_initializesystem
1 parent 5f5d7f6 commit 1067cc0

File tree

1 file changed

+44
-1
lines changed

1 file changed

+44
-1
lines changed

src/problems/initializationproblem.jl

Lines changed: 44 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,17 +55,54 @@ All other keyword arguments are forwarded to the wrapped nonlinear problem const
5555
simplify_system = true
5656
end
5757

58+
# The trivial observed identification process may have substituted the equations
59+
# of the system until they are pure-parameter equations. To prevent `mtkcompile` from
60+
# ignoring them (since we still want them as constraints) remove them from the system
61+
# and add them back later.
62+
varsbuf = Set()
63+
pareq_idxs = Int[]
64+
eqs = equations(isys)
65+
for (i, eq) in enumerate(eqs)
66+
empty!(varsbuf)
67+
vars!(varsbuf, eq; op = Union{Initial, Pre})
68+
# singular equations
69+
isempty(varsbuf) && continue
70+
if all(varsbuf) do sym
71+
is_parameter(isys, sym) ||
72+
symbolic_type(sym) == ArraySymbolic() &&
73+
is_sized_array_symbolic(sym) &&
74+
all(Base.Fix1(is_parameter, isys), collect(sym))
75+
end
76+
push!(pareq_idxs, i)
77+
end
78+
end
79+
pareqs = flatten_equations(eqs[pareq_idxs])
80+
pareqs = map(pareqs) do eq
81+
0 ~ eq.rhs - eq.lhs
82+
end
83+
eqs = eqs[setdiff(eachindex(eqs), pareq_idxs)]
84+
@set! isys.eqs = eqs
85+
5886
# useful for `SteadyStateProblem` since `f` has to be autonomous and the
5987
# initialization should be too
6088
if !time_dependent_init
6189
idx = findfirst(isequal(get_iv(sys)), get_ps(isys))
6290
idx === nothing || deleteat!(get_ps(isys), idx)
6391
end
6492

93+
# some variables may be used in the explicitly torn observed equations
94+
# but not in the standard equations
95+
used_in_explicit_obs = Set()
96+
for eq in observed(isys)
97+
vars!(used_in_explicit_obs, eq.rhs)
98+
end
99+
65100
if simplify_system
66101
isys = mtkcompile(isys; fully_determined, split = is_split(sys))
67102
end
68103

104+
@set! isys.eqs = [get_eqs(isys); pareqs]
105+
69106
ts = get_tearing_state(isys)
70107
unassigned_vars = StructuralTransformations.singular_check(ts)
71108
if warn_initialize_determined && !isempty(unassigned_vars)
@@ -79,7 +116,13 @@ All other keyword arguments are forwarded to the wrapped nonlinear problem const
79116
@warn errmsg
80117
end
81118

82-
uninit = setdiff(unknowns(sys), [unknowns(isys); observables(isys)])
119+
uninit = setdiff(unknowns(sys), unknowns(isys), observables(isys))
120+
# get the variables not present in standard equations but present in explicit observed
121+
extra_vars = intersect!(used_in_explicit_obs, uninit)
122+
# remove them from the uninitialized variables
123+
setdiff!(uninit, extra_vars)
124+
# and add them to the unknowns
125+
@set! isys.unknowns = [get_unknowns(isys); collect(extra_vars)]
83126

84127
# TODO: throw on uninitialized arrays
85128
filter!(x -> !(x isa Symbolics.Arr), uninit)

0 commit comments

Comments
 (0)