Skip to content

Commit 9ef55cf

Browse files
fix: handle nested clock operators in TearingState
1 parent 319675b commit 9ef55cf

1 file changed

Lines changed: 80 additions & 2 deletions

File tree

lib/ModelingToolkitTearing/src/tearingstate.jl

Lines changed: 80 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,8 @@ function TearingState(sys::System, source_info::Union{Nothing, MTKBase.EquationS
173173

174174
# build symbolic incidence
175175
symbolic_incidence = Vector{SymbolicT}[]
176-
varsbuf = Set{SymbolicT}()
176+
varsbuf = OrderedSet{SymbolicT}()
177+
auxiliary_vars = OrderedSet{SymbolicT}()
177178
eqs_to_retain = trues(length(eqs))
178179
for (i, eq) in enumerate(eqs)
179180
eq, is_statemachine_equation = canonicalize_eq!(param_derivative_map, no_deriv_params, eqs_to_retain, ps, iv, i, eq)
@@ -239,7 +240,7 @@ function TearingState(sys::System, source_info::Union{Nothing, MTKBase.EquationS
239240
for (i, td) in enumerate(it)
240241
v′ = args[i]
241242
SU.isconst(v′) && continue
242-
addvar!(setmetadata(v′, MTKBase.VariableTimeDomain, td), VARIABLE)
243+
SU.search_variables!(auxiliary_vars, v′; is_atomic = MTKBase.OperatorIsAtomic{SU.Operator}())
243244
end
244245
end
245246
_ => nothing
@@ -278,6 +279,83 @@ function TearingState(sys::System, source_info::Union{Nothing, MTKBase.EquationS
278279
push!(symbolic_incidence, collect(incidence))
279280
end
280281

282+
for v in auxiliary_vars
283+
if v in ps
284+
if iv isa SymbolicT && is_time_dependent_parameter(v, ps, iv) &&
285+
!haskey(param_derivative_map, Differential(iv)(v)) && !(Differential(iv)(v) in no_deriv_params)
286+
# Parameter derivatives default to zero - they stay constant
287+
# between callbacks
288+
param_derivative_map[Differential(iv)(v)] = Symbolics.COMMON_ZERO
289+
end
290+
continue
291+
end
292+
293+
iv isa SymbolicT && isequal(v, iv) && continue
294+
iv isa SymbolicT && MTKBase.isdelay(v, iv) && continue
295+
296+
if !in(v, dvs)
297+
isvalid = @match v begin
298+
BSImpl.Term(; f, args) => f isa Shift || isempty(args) || f isa SU.Operator && is_transparent_operator(f)::Bool
299+
_ => false
300+
end
301+
v′ = v
302+
while !isvalid
303+
@match v′ begin
304+
BSImpl.Term(; f, args) => begin
305+
if f isa Differential
306+
v′ = args[1]
307+
elseif f isa Shift
308+
v′ = args[1]
309+
else
310+
break
311+
end
312+
if v′ in dvs
313+
isvalid = true
314+
break
315+
end
316+
end
317+
_ => break
318+
end
319+
end
320+
if !isvalid
321+
throw(ArgumentError("$v is present in the system but $v′ is not an unknown."))
322+
end
323+
324+
addvar!(v, VARIABLE)
325+
@match v begin
326+
BSImpl.Term(; f, args) && if f isa SU.Operator &&
327+
!(f isa Differential)
328+
end => begin
329+
it = input_timedomain(f, args)::Vector{InputTimeDomainElT}
330+
for (i, td) in enumerate(it)
331+
v′ = args[i]
332+
SU.isconst(v′) && continue
333+
SU.search_variables!(auxiliary_vars, v′; is_atomic = MTKBase.OperatorIsAtomic{SU.Operator}())
334+
end
335+
end
336+
_ => nothing
337+
end
338+
end
339+
sh = SU.shape(v)::SU.ShapeVecT
340+
if isempty(sh)
341+
addvar!(v, VARIABLE)
342+
elseif length(sh) == 1
343+
vv = collect(v)::Vector{SymbolicT}
344+
for vi in vv
345+
addvar!(vi, VARIABLE)
346+
end
347+
elseif length(sh) == 2
348+
vv = collect(v)::Matrix{SymbolicT}
349+
for vi in vv
350+
addvar!(vi, VARIABLE)
351+
end
352+
else
353+
vv = vec(collect(v)::Array{SymbolicT})::Vector{SymbolicT}
354+
for vi in vv
355+
addvar!(vi, VARIABLE)
356+
end
357+
end
358+
end
281359
filter!(Base.Fix2(!==, MTKBase.COMMON_NOTHING) last, param_derivative_map)
282360

283361
eqs = eqs[eqs_to_retain]

0 commit comments

Comments
 (0)