@@ -207,6 +207,7 @@ mutable struct TearingState{T <: AbstractSystem} <: AbstractTearingState{T}
207
207
fullvars:: Vector
208
208
structure:: SystemStructure
209
209
extra_eqs:: Vector
210
+ param_derivative_map:: Dict{BasicSymbolic, Any}
210
211
end
211
212
212
213
TransformationState (sys:: AbstractSystem ) = TearingState (sys)
@@ -253,6 +254,12 @@ function Base.push!(ev::EquationsView, eq)
253
254
push! (ev. ts. extra_eqs, eq)
254
255
end
255
256
257
+ function is_time_dependent_parameter (p, iv)
258
+ return iv != = nothing && isparameter (p) && iscall (p) &&
259
+ (operation (p) === getindex && is_time_dependent_parameter (arguments (p)[1 ], iv) ||
260
+ (args = arguments (p); length (args)) == 1 && isequal (only (args), iv))
261
+ end
262
+
256
263
function TearingState (sys; quick_cancel = false , check = true )
257
264
sys = flatten (sys)
258
265
ivs = independent_variables (sys)
@@ -264,6 +271,7 @@ function TearingState(sys; quick_cancel = false, check = true)
264
271
var2idx = Dict {Any, Int} ()
265
272
symbolic_incidence = []
266
273
fullvars = []
274
+ param_derivative_map = Dict {BasicSymbolic, Any} ()
267
275
var_counter = Ref (0 )
268
276
var_types = VariableType[]
269
277
addvar! = let fullvars = fullvars, var_counter = var_counter, var_types = var_types
@@ -276,11 +284,23 @@ function TearingState(sys; quick_cancel = false, check = true)
276
284
277
285
vars = OrderedSet ()
278
286
varsvec = []
287
+ eqs_to_retain = trues (length (eqs))
279
288
for (i, eq′) in enumerate (eqs)
280
289
if eq′. lhs isa Connection
281
290
check ? error (" $(nameof (sys)) has unexpanded `connect` statements" ) :
282
291
return nothing
283
292
end
293
+ if iscall (eq′. lhs) && (op = operation (eq′. lhs)) isa Differential &&
294
+ isequal (op. x, iv) && is_time_dependent_parameter (only (arguments (eq′. lhs)), iv)
295
+ # parameter derivatives are opted out by specifying `D(p) ~ missing`, but
296
+ # we want to store `nothing` in the map because that means `fast_substitute`
297
+ # will ignore the rule. We will this identify the presence of `eq′.lhs` in
298
+ # the differentiated expression and error.
299
+ param_derivative_map[eq′. lhs] = coalesce (eq′. rhs, nothing )
300
+ eqs_to_retain[i] = false
301
+ # change the equation if the RHS is `missing` so the rest of this loop works
302
+ eq′ = eq′. lhs ~ coalesce (eq′. rhs, 0.0 )
303
+ end
284
304
if _iszero (eq′. lhs)
285
305
rhs = quick_cancel ? quick_cancel_expr (eq′. rhs) : eq′. rhs
286
306
eq = eq′
@@ -295,6 +315,12 @@ function TearingState(sys; quick_cancel = false, check = true)
295
315
any (isequal (_var), ivs) && continue
296
316
if isparameter (_var) ||
297
317
(iscall (_var) && isparameter (operation (_var)) || isconstant (_var))
318
+ if is_time_dependent_parameter (_var, iv) &&
319
+ ! haskey (param_derivative_map, Differential (iv)(_var))
320
+ # Parameter derivatives default to zero - they stay constant
321
+ # between callbacks
322
+ param_derivative_map[Differential (iv)(_var)] = 0.0
323
+ end
298
324
continue
299
325
end
300
326
v = scalarize (v)
@@ -351,6 +377,9 @@ function TearingState(sys; quick_cancel = false, check = true)
351
377
eqs[i] = eqs[i]. lhs ~ rhs
352
378
end
353
379
end
380
+ eqs = eqs[eqs_to_retain]
381
+ neqs = length (eqs)
382
+ symbolic_incidence = symbolic_incidence[eqs_to_retain]
354
383
355
384
# ## Handle discrete variables
356
385
lowest_shift = Dict ()
@@ -438,7 +467,7 @@ function TearingState(sys; quick_cancel = false, check = true)
438
467
ts = TearingState (sys, fullvars,
439
468
SystemStructure (complete (var_to_diff), complete (eq_to_diff),
440
469
complete (graph), nothing , var_types, sys isa AbstractDiscreteSystem),
441
- Any[])
470
+ Any[], param_derivative_map )
442
471
if sys isa DiscreteSystem
443
472
ts = shift_discrete_system (ts)
444
473
end
0 commit comments