@@ -295,7 +295,7 @@ function has_parameter_dependency_with_lhs(sys, sym)
295295    if  has_index_cache (sys) &&  (ic =  get_index_cache (sys)) != =  nothing 
296296        return  haskey (ic. dependent_pars_to_timeseries, unwrap (sym))
297297    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)])
299299    end 
300300end 
301301
@@ -565,7 +565,7 @@ function add_initialization_parameters(sys::AbstractSystem; split = true)
565565        D =  Differential (get_iv (sys))
566566        union! (all_initialvars, [D (v) for  v in  all_initialvars if  iscall (v)])
567567    end 
568-     for  eq in  parameter_dependencies (sys)
568+     for  eq in  get_parameter_dependencies (sys)
569569        is_variable_floatingpoint (eq. lhs) ||  continue 
570570        push! (all_initialvars, eq. lhs)
571571    end 
@@ -596,6 +596,22 @@ function isinitial(p)
596596            operation (p) ===  getindex &&  isinitial (arguments (p)[1 ]))
597597end 
598598
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+ 
599615""" 
600616$(TYPEDSIGNATURES) 
601617
@@ -612,13 +628,7 @@ using [`toggle_namespacing`](@ref).
612628""" 
613629function  complete (
614630        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)
622632
623633    if  flatten
624634        eqs =  equations (sys)
@@ -632,6 +642,7 @@ function complete(
632642            @set!  newsys. parent =  complete (sys; split =  false , flatten =  false )
633643        end 
634644        sys =  newsys
645+         sys =  process_parameter_equations (sys)
635646        if  add_initial_parameters
636647            sys =  add_initialization_parameters (sys; split)
637648        end 
@@ -1263,6 +1274,12 @@ function parameters(sys::AbstractSystem; initial_parameters = false)
12631274end 
12641275
12651276function  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 
12661283    return  map (eq ->  eq. lhs, parameter_dependencies (sys))
12671284end 
12681285
@@ -1279,27 +1296,33 @@ function parameters_toplevel(sys::AbstractSystem)
12791296end 
12801297
12811298""" 
1282- $(TYPEDSIGNATURES) 
1283- Get the parameter dependencies of the system `sys` and its subsystems. 
1299+     $(TYPEDSIGNATURES)  
12841300
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. 
12861303""" 
12871304function  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 
12881311    if  ! has_parameter_dependencies (sys)
12891312        return  Equation[]
12901313    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)
12991315end 
13001316
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+ """ 
13011323function  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)
13031326end 
13041327
13051328""" 
@@ -2079,7 +2102,7 @@ function Base.show(
20792102    end 
20802103
20812104    #  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 
20832106    npdeps >  0  &&  printstyled (io, " \n Parameter dependencies ($npdeps ):" 
20842107    npdeps >  0  &&  hint &&  print (io, "  see parameter_dependencies($name )" 
20852108
@@ -2588,15 +2611,15 @@ function extend(sys::AbstractSystem, basesys::AbstractSystem;
25882611    eqs =  union (get_eqs (basesys), get_eqs (sys))
25892612    sts =  union (get_unknowns (basesys), get_unknowns (sys))
25902613    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))
25922615    obs =  union (get_observed (basesys), get_observed (sys))
25932616    cevs =  union (get_continuous_events (basesys), get_continuous_events (sys))
25942617    devs =  union (get_discrete_events (basesys), get_discrete_events (sys))
25952618    defs =  merge (get_defaults (basesys), get_defaults (sys)) #  prefer `sys`
25962619    meta =  merge (get_metadata (basesys), get_metadata (sys))
25972620    syss =  union (get_systems (basesys), get_systems (sys))
25982621    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,
26002623        discrete_events =  devs, defaults =  defs, systems =  syss, metadata =  meta,
26012624        name =  name, description =  description, gui_metadata =  gui_metadata)
26022625
@@ -2610,7 +2633,10 @@ function extend(sys::AbstractSystem, basesys::AbstractSystem;
26102633            kwargs, (; assertions =  merge (get_assertions (basesys), get_assertions (sys))))
26112634    end 
26122635
2613-     return  T (args... ; kwargs... )
2636+     newsys =  T (args... ; kwargs... )
2637+     @set!  newsys. parameter_dependencies =  dep_ps
2638+ 
2639+     return  newsys
26142640end 
26152641
26162642""" 
@@ -2752,60 +2778,62 @@ function Symbolics.substitute(sys::AbstractSystem, rules::Union{Vector{<:Pair},
27522778        initialization_eqs =  fast_substitute (get_initialization_eqs (sys), rules)
27532779        cstrs =  fast_substitute (get_constraints (sys), rules)
27542780        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,
27572783            observed, initialization_eqs, constraints =  cstrs)
2784+         @set!  newsys. parameter_dependencies =  pdeps
27582785    else 
27592786        error (" substituting symbols is not supported for $(typeof (sys)) " 
27602787    end 
27612788end 
27622789
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 " . got)
2772-     end 
2773- end 
2790+ """ 
2791+     $(TYPEDSIGNATURES)  
27742792
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" 
27912802    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)
28002824        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)
28072825    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
28092837end 
28102838
28112839""" 
@@ -2829,7 +2857,7 @@ See also: [`ModelingToolkit.dump_variable_metadata`](@ref), [`ModelingToolkit.du
28292857""" 
28302858function  dump_parameters (sys:: AbstractSystem )
28312859    defs =  defaults (sys)
2832-     pdeps =  parameter_dependencies (sys)
2860+     pdeps =  get_parameter_dependencies (sys)
28332861    metas =  map (dump_variable_metadata .(parameters (sys))) do  meta
28342862        if  haskey (defs, meta. var)
28352863            meta =  merge (meta, (; default =  defs[meta. var]))
0 commit comments