@@ -295,7 +295,7 @@ function has_parameter_dependency_with_lhs(sys, sym)
295
295
if has_index_cache (sys) && (ic = get_index_cache (sys)) != = nothing
296
296
return haskey (ic. dependent_pars_to_timeseries, unwrap (sym))
297
297
else
298
- return any (isequal (sym), [eq. lhs for eq in parameter_dependencies (sys)])
298
+ return any (isequal (sym), [eq. lhs for eq in get_parameter_dependencies (sys)])
299
299
end
300
300
end
301
301
@@ -565,7 +565,7 @@ function add_initialization_parameters(sys::AbstractSystem; split = true)
565
565
D = Differential (get_iv (sys))
566
566
union! (all_initialvars, [D (v) for v in all_initialvars if iscall (v)])
567
567
end
568
- for eq in parameter_dependencies (sys)
568
+ for eq in get_parameter_dependencies (sys)
569
569
is_variable_floatingpoint (eq. lhs) || continue
570
570
push! (all_initialvars, eq. lhs)
571
571
end
@@ -596,6 +596,22 @@ function isinitial(p)
596
596
operation (p) === getindex && isinitial (arguments (p)[1 ]))
597
597
end
598
598
599
+ """
600
+ $(TYPEDSIGNATURES)
601
+
602
+ Find [`GlobalScope`](@ref)d variables in `sys` and add them to the unknowns/parameters.
603
+ """
604
+ function discover_globalscoped (sys:: AbstractSystem )
605
+ newunknowns = OrderedSet ()
606
+ newparams = OrderedSet ()
607
+ iv = has_iv (sys) ? get_iv (sys) : nothing
608
+ collect_scoped_vars! (newunknowns, newparams, sys, iv; depth = - 1 )
609
+ setdiff! (newunknowns, observables (sys))
610
+ @set! sys. ps = unique! (vcat (get_ps (sys), collect (newparams)))
611
+ @set! sys. unknowns = unique! (vcat (get_unknowns (sys), collect (newunknowns)))
612
+ return sys
613
+ end
614
+
599
615
"""
600
616
$(TYPEDSIGNATURES)
601
617
@@ -612,13 +628,7 @@ using [`toggle_namespacing`](@ref).
612
628
"""
613
629
function complete (
614
630
sys:: AbstractSystem ; split = true , flatten = true , add_initial_parameters = true )
615
- newunknowns = OrderedSet ()
616
- newparams = OrderedSet ()
617
- iv = has_iv (sys) ? get_iv (sys) : nothing
618
- collect_scoped_vars! (newunknowns, newparams, sys, iv; depth = - 1 )
619
- # don't update unknowns to not disturb `mtkcompile` order
620
- # `GlobalScope`d unknowns will be picked up and added there
621
- @set! sys. ps = unique! (vcat (get_ps (sys), collect (newparams)))
631
+ sys = discover_globalscoped (sys)
622
632
623
633
if flatten
624
634
eqs = equations (sys)
@@ -632,6 +642,7 @@ function complete(
632
642
@set! newsys. parent = complete (sys; split = false , flatten = false )
633
643
end
634
644
sys = newsys
645
+ sys = process_parameter_equations (sys)
635
646
if add_initial_parameters
636
647
sys = add_initialization_parameters (sys; split)
637
648
end
@@ -1263,6 +1274,12 @@ function parameters(sys::AbstractSystem; initial_parameters = false)
1263
1274
end
1264
1275
1265
1276
function dependent_parameters (sys:: AbstractSystem )
1277
+ if ! iscomplete (sys)
1278
+ throw (ArgumentError ("""
1279
+ `dependent_parameters` requires that the system is marked as complete. Call
1280
+ `complete` or `mtkcompile` on the system.
1281
+ """ ))
1282
+ end
1266
1283
return map (eq -> eq. lhs, parameter_dependencies (sys))
1267
1284
end
1268
1285
@@ -1279,27 +1296,33 @@ function parameters_toplevel(sys::AbstractSystem)
1279
1296
end
1280
1297
1281
1298
"""
1282
- $(TYPEDSIGNATURES)
1283
- Get the parameter dependencies of the system `sys` and its subsystems.
1299
+ $(TYPEDSIGNATURES)
1284
1300
1285
- See also [`defaults`](@ref) and [`ModelingToolkit.get_parameter_dependencies`](@ref).
1301
+ Get the parameter dependencies of the system `sys` and its subsystems. Requires that the
1302
+ system is `complete`d.
1286
1303
"""
1287
1304
function parameter_dependencies (sys:: AbstractSystem )
1305
+ if ! iscomplete (sys)
1306
+ throw (ArgumentError ("""
1307
+ `parameter_dependencies` requires that the system is marked as complete. Call \
1308
+ `complete` or `mtkcompile` on the system.
1309
+ """ ))
1310
+ end
1288
1311
if ! has_parameter_dependencies (sys)
1289
1312
return Equation[]
1290
1313
end
1291
- pdeps = get_parameter_dependencies (sys)
1292
- systems = get_systems (sys)
1293
- # put pdeps after those of subsystems to maintain topological sorted order
1294
- namespaced_deps = mapreduce (
1295
- s -> map (eq -> namespace_equation (eq, s), parameter_dependencies (s)), vcat,
1296
- systems; init = Equation[])
1297
-
1298
- return vcat (namespaced_deps, pdeps)
1314
+ get_parameter_dependencies (sys)
1299
1315
end
1300
1316
1317
+ """
1318
+ $(TYPEDSIGNATURES)
1319
+
1320
+ Return all of the parameters of the system, including hidden initial parameters and ones
1321
+ eliminated via `parameter_dependencies`.
1322
+ """
1301
1323
function full_parameters (sys:: AbstractSystem )
1302
- vcat (parameters (sys; initial_parameters = true ), dependent_parameters (sys))
1324
+ dep_ps = [eq. lhs for eq in get_parameter_dependencies (sys)]
1325
+ vcat (parameters (sys; initial_parameters = true ), dep_ps)
1303
1326
end
1304
1327
1305
1328
"""
@@ -2079,7 +2102,7 @@ function Base.show(
2079
2102
end
2080
2103
2081
2104
# Print parameter dependencies
2082
- npdeps = has_parameter_dependencies (sys) ? length (parameter_dependencies (sys)) : 0
2105
+ npdeps = has_parameter_dependencies (sys) ? length (get_parameter_dependencies (sys)) : 0
2083
2106
npdeps > 0 && printstyled (io, " \n Parameter dependencies ($npdeps ):" ; bold)
2084
2107
npdeps > 0 && hint && print (io, " see parameter_dependencies($name )" )
2085
2108
@@ -2588,15 +2611,15 @@ function extend(sys::AbstractSystem, basesys::AbstractSystem;
2588
2611
eqs = union (get_eqs (basesys), get_eqs (sys))
2589
2612
sts = union (get_unknowns (basesys), get_unknowns (sys))
2590
2613
ps = union (get_ps (basesys), get_ps (sys))
2591
- dep_ps = union (parameter_dependencies (basesys), parameter_dependencies (sys))
2614
+ dep_ps = union (get_parameter_dependencies (basesys), get_parameter_dependencies (sys))
2592
2615
obs = union (get_observed (basesys), get_observed (sys))
2593
2616
cevs = union (get_continuous_events (basesys), get_continuous_events (sys))
2594
2617
devs = union (get_discrete_events (basesys), get_discrete_events (sys))
2595
2618
defs = merge (get_defaults (basesys), get_defaults (sys)) # prefer `sys`
2596
2619
meta = merge (get_metadata (basesys), get_metadata (sys))
2597
2620
syss = union (get_systems (basesys), get_systems (sys))
2598
2621
args = length (ivs) == 0 ? (eqs, sts, ps) : (eqs, ivs[1 ], sts, ps)
2599
- kwargs = (parameter_dependencies = dep_ps, observed = obs, continuous_events = cevs,
2622
+ kwargs = (observed = obs, continuous_events = cevs,
2600
2623
discrete_events = devs, defaults = defs, systems = syss, metadata = meta,
2601
2624
name = name, description = description, gui_metadata = gui_metadata)
2602
2625
@@ -2610,7 +2633,10 @@ function extend(sys::AbstractSystem, basesys::AbstractSystem;
2610
2633
kwargs, (; assertions = merge (get_assertions (basesys), get_assertions (sys))))
2611
2634
end
2612
2635
2613
- return T (args... ; kwargs... )
2636
+ newsys = T (args... ; kwargs... )
2637
+ @set! newsys. parameter_dependencies = dep_ps
2638
+
2639
+ return newsys
2614
2640
end
2615
2641
2616
2642
"""
@@ -2752,60 +2778,62 @@ function Symbolics.substitute(sys::AbstractSystem, rules::Union{Vector{<:Pair},
2752
2778
initialization_eqs = fast_substitute (get_initialization_eqs (sys), rules)
2753
2779
cstrs = fast_substitute (get_constraints (sys), rules)
2754
2780
subsys = map (s -> substitute (s, rules), get_systems (sys))
2755
- System (eqs, get_iv (sys); name = nameof (sys), defaults = defs,
2756
- guesses = guess, parameter_dependencies = pdeps, systems = subsys, noise_eqs,
2781
+ newsys = System (eqs, get_iv (sys); name = nameof (sys), defaults = defs,
2782
+ guesses = guess, systems = subsys, noise_eqs,
2757
2783
observed, initialization_eqs, constraints = cstrs)
2784
+ @set! newsys. parameter_dependencies = pdeps
2758
2785
else
2759
2786
error (" substituting symbols is not supported for $(typeof (sys)) " )
2760
2787
end
2761
2788
end
2762
2789
2763
- struct InvalidParameterDependenciesType
2764
- got:: Any
2765
- end
2766
-
2767
- function Base. showerror (io:: IO , err:: InvalidParameterDependenciesType )
2768
- print (
2769
- io, " Parameter dependencies must be a `Dict`, or an array of `Pair` or `Equation`." )
2770
- if err. got != = nothing
2771
- print (io, " Got " , err. got)
2772
- end
2773
- end
2790
+ """
2791
+ $(TYPEDSIGNATURES)
2774
2792
2775
- function process_parameter_dependencies (pdeps, ps)
2776
- if pdeps === nothing || isempty (pdeps)
2777
- return Equation[], ps
2778
- end
2779
- if pdeps isa Dict
2780
- pdeps = [k ~ v for (k, v) in pdeps]
2781
- else
2782
- pdeps isa AbstractArray || throw (InvalidParameterDependenciesType (pdeps))
2783
- pdeps = [if p isa Pair
2784
- p[1 ] ~ p[2 ]
2785
- elseif p isa Equation
2786
- p
2787
- else
2788
- error (" Parameter dependencies must be a `Dict`, `Vector{Pair}` or `Vector{Equation}`" )
2789
- end
2790
- for p in pdeps]
2793
+ Find equations of `sys` involving only parameters and separate them out into the
2794
+ `parameter_dependencies` field. Relative ordering of equations is maintained.
2795
+ Parameter-only equations are validated to be explicit and sorted topologically. All such
2796
+ explicitly determined parameters are removed from the parameters of `sys`. Return the new
2797
+ system.
2798
+ """
2799
+ function process_parameter_equations (sys:: AbstractSystem )
2800
+ if ! isempty (get_systems (sys))
2801
+ throw (ArgumentError (" Expected flattened system" ))
2791
2802
end
2792
- lhss = []
2793
- for p in pdeps
2794
- if ! isparameter (p. lhs)
2795
- error (" LHS of parameter dependency must be a single parameter. Found $(p. lhs) ." )
2796
- end
2797
- syms = vars (p. rhs)
2798
- if ! all (isparameter, syms)
2799
- error (" RHS of parameter dependency must only include parameters. Found $(p. rhs) " )
2803
+ varsbuf = Set ()
2804
+ pareq_idxs = Int[]
2805
+ eqs = equations (sys)
2806
+ for (i, eq) in enumerate (eqs)
2807
+ empty! (varsbuf)
2808
+ vars! (varsbuf, eq; op = Union{Differential, Initial, Pre})
2809
+ # singular equations
2810
+ isempty (varsbuf) && continue
2811
+ if all (varsbuf) do sym
2812
+ is_parameter (sys, sym) ||
2813
+ symbolic_type (sym) == ArraySymbolic () &&
2814
+ is_sized_array_symbolic (sym) &&
2815
+ all (Base. Fix1 (is_parameter, sys), collect (sym))
2816
+ end
2817
+ if ! isparameter (eq. lhs)
2818
+ throw (ArgumentError ("""
2819
+ LHS of parameter dependency equation must be a single parameter. Found \
2820
+ $(eq. lhs) .
2821
+ """ ))
2822
+ end
2823
+ push! (pareq_idxs, i)
2800
2824
end
2801
- push! (lhss, p. lhs)
2802
- end
2803
- lhss = map (identity, lhss)
2804
- pdeps = topsort_equations (pdeps, union (ps, lhss))
2805
- ps = filter (ps) do p
2806
- ! any (isequal (p), lhss)
2807
2825
end
2808
- return pdeps, ps
2826
+
2827
+ pareqs = [get_parameter_dependencies (sys); eqs[pareq_idxs]]
2828
+ explicitpars = [eq. lhs for eq in pareqs]
2829
+ pareqs = topsort_equations (pareqs, explicitpars)
2830
+
2831
+ eqs = eqs[setdiff (eachindex (eqs), pareq_idxs)]
2832
+
2833
+ @set! sys. eqs = eqs
2834
+ @set! sys. parameter_dependencies = pareqs
2835
+ @set! sys. ps = setdiff (get_ps (sys), explicitpars)
2836
+ return sys
2809
2837
end
2810
2838
2811
2839
"""
@@ -2829,7 +2857,7 @@ See also: [`ModelingToolkit.dump_variable_metadata`](@ref), [`ModelingToolkit.du
2829
2857
"""
2830
2858
function dump_parameters (sys:: AbstractSystem )
2831
2859
defs = defaults (sys)
2832
- pdeps = parameter_dependencies (sys)
2860
+ pdeps = get_parameter_dependencies (sys)
2833
2861
metas = map (dump_variable_metadata .(parameters (sys))) do meta
2834
2862
if haskey (defs, meta. var)
2835
2863
meta = merge (meta, (; default = defs[meta. var]))
0 commit comments