@@ -717,6 +717,22 @@ function add_initialization_parameters(sys::AbstractSystem)
717717    return  sys
718718end 
719719
720+ """ 
721+ Returns true if the parameter `p` is of the form `Initial(x)`. 
722+ """ 
723+ function  isinitial (p)
724+     p =  unwrap (p)
725+     if  iscall (p)
726+         operation (p) isa  Initial &&  return  true 
727+         if  operation (p) ===  getindex
728+             operation (arguments (p)[1 ]) isa  Initial &&  return  true 
729+         end 
730+     else 
731+         return  false 
732+     end 
733+     return  false 
734+ end 
735+ 
720736""" 
721737$(TYPEDSIGNATURES) 
722738
@@ -757,38 +773,21 @@ function complete(sys::AbstractSystem; split = true, flatten = true)
757773        if  ! isempty (all_ps)
758774            #  reorder parameters by portions
759775            ps_split =  reorder_parameters (sys, all_ps)
776+             #  if there are tunables, they will all be in `ps_split[1]`
777+             #  and the arrays will have been scalarized
778+             ordered_ps =  eltype (all_ps)[]
760779            #  if there are no tunables, vcat them
761-             if  isempty (get_index_cache (sys). tunable_idx)
762-                 ordered_ps =  reduce (vcat, ps_split)
763-             else 
764-                 #  if there are tunables, they will all be in `ps_split[1]`
765-                 #  and the arrays will have been scalarized
766-                 ordered_ps =  eltype (all_ps)[]
767-                 i =  1 
768-                 #  go through all the tunables
769-                 while  i <=  length (ps_split[1 ])
770-                     sym =  ps_split[1 ][i]
771-                     #  if the sym is not a scalarized array symbolic OR it was already scalarized,
772-                     #  just push it as-is
773-                     if  ! iscall (sym) ||  operation (sym) !=  getindex || 
774-                        any (isequal (sym), all_ps)
775-                         push! (ordered_ps, sym)
776-                         i +=  1 
777-                         continue 
778-                     end 
779-                     #  the next `length(sym)` symbols should be scalarized versions of the same
780-                     #  array symbolic
781-                     if  ! allequal (first (arguments (x))
782-                     for  x in  view (ps_split[1 ], i: (i +  length (sym) -  1 )))
783-                         error (" This should not be possible. Please open an issue in ModelingToolkit.jl with an MWE and stacktrace." 
784-                     end 
785-                     arrsym =  first (arguments (sym))
786-                     push! (ordered_ps, arrsym)
787-                     i +=  length (arrsym)
788-                 end 
789-                 ordered_ps =  vcat (
790-                     ordered_ps, reduce (vcat, ps_split[2 : end ]; init =  eltype (ordered_ps)[]))
780+             if  ! isempty (get_index_cache (sys). tunable_idx)
781+                 unflatten_parameters! (ordered_ps, ps_split[1 ], all_ps)
782+                 ps_split =  Base. tail (ps_split)
783+             end 
784+             #  unflatten initial parameters
785+             if  ! isempty (get_index_cache (sys). initials_idx)
786+                 unflatten_parameters! (ordered_ps, ps_split[1 ], all_ps)
787+                 ps_split =  Base. tail (ps_split)
791788            end 
789+             ordered_ps =  vcat (
790+                 ordered_ps, reduce (vcat, ps_split; init =  eltype (ordered_ps)[]))
792791            @set!  sys. ps =  ordered_ps
793792        end 
794793    elseif  has_index_cache (sys)
@@ -800,6 +799,39 @@ function complete(sys::AbstractSystem; split = true, flatten = true)
800799    isdefined (sys, :complete ) ?  (@set!  sys. complete =  true ) :  sys
801800end 
802801
802+ """ 
803+     $(TYPEDSIGNATURES)  
804+ 
805+ Given a flattened array of parameters `params` and a collection of all (unscalarized) 
806+ parameters in the system `all_ps`, unscalarize the elements in `params` and append 
807+ to `buffer` in the same order as they are present in `params`. Effectively, if 
808+ `params = [p[1], p[2], p[3], q]` then this is equivalent to `push!(buffer, p, q)`. 
809+ """ 
810+ function  unflatten_parameters! (buffer, params, all_ps)
811+     i =  1 
812+     #  go through all the tunables
813+     while  i <=  length (params)
814+         sym =  params[i]
815+         #  if the sym is not a scalarized array symbolic OR it was already scalarized,
816+         #  just push it as-is
817+         if  ! iscall (sym) ||  operation (sym) !=  getindex || 
818+            any (isequal (sym), all_ps)
819+             push! (buffer, sym)
820+             i +=  1 
821+             continue 
822+         end 
823+         #  the next `length(sym)` symbols should be scalarized versions of the same
824+         #  array symbolic
825+         if  ! allequal (first (arguments (x))
826+         for  x in  view (params, i: (i +  length (sym) -  1 )))
827+             error (" This should not be possible. Please open an issue in ModelingToolkit.jl with an MWE and stacktrace." 
828+         end 
829+         arrsym =  first (arguments (sym))
830+         push! (buffer, arrsym)
831+         i +=  length (arrsym)
832+     end 
833+ end 
834+ 
803835for  prop in  [:eqs 
804836             :tag 
805837             :noiseeqs 
@@ -846,6 +878,7 @@ for prop in [:eqs
846878             :assertions 
847879             :solved_unknowns 
848880             :split_idxs 
881+              :ignored_connections 
849882             :parent 
850883             :is_dde 
851884             :tstops 
@@ -1362,6 +1395,75 @@ function assertions(sys::AbstractSystem)
13621395    return  merge (asserts, namespaced_asserts)
13631396end 
13641397
1398+ const  HierarchyVariableT =  Vector{Union{BasicSymbolic, Symbol}}
1399+ const  HierarchySystemT =  Vector{Union{AbstractSystem, Symbol}}
1400+ """ 
1401+ The type returned from `as_hierarchy`. 
1402+ """ 
1403+ const  HierarchyT =  Union{HierarchyVariableT, HierarchySystemT}
1404+ 
1405+ """ 
1406+     $(TYPEDSIGNATURES)  
1407+ 
1408+ The inverse operation of `as_hierarchy`. 
1409+ """ 
1410+ function  from_hierarchy (hierarchy:: HierarchyT )
1411+     namefn =  hierarchy[1 ] isa  AbstractSystem ?  nameof :  getname
1412+     foldl (@view  hierarchy[2 : end ]; init =  hierarchy[1 ]) do  sys, name
1413+         rename (sys, Symbol (name, NAMESPACE_SEPARATOR, namefn (sys)))
1414+     end 
1415+ end 
1416+ 
1417+ """ 
1418+     $(TYPEDSIGNATURES)  
1419+ 
1420+ Represent a namespaced system (or variable) `sys` as a hierarchy. Return a vector, where 
1421+ the first element is the unnamespaced system (variable) and subsequent elements are 
1422+ `Symbol`s representing the parents of the unnamespaced system (variable) in order from 
1423+ inner to outer. 
1424+ """ 
1425+ function  as_hierarchy (sys:: Union{AbstractSystem, BasicSymbolic} ):: HierarchyT 
1426+     namefn =  sys isa  AbstractSystem ?  nameof :  getname
1427+     #  get the hierarchy
1428+     hierarchy =  namespace_hierarchy (namefn (sys))
1429+     #  rename the system with unnamespaced name
1430+     newsys =  rename (sys, hierarchy[end ])
1431+     #  and remove it from the list
1432+     pop! (hierarchy)
1433+     #  reverse it to go from inner to outer
1434+     reverse! (hierarchy)
1435+     #  concatenate
1436+     T =  sys isa  AbstractSystem ?  AbstractSystem :  BasicSymbolic
1437+     return  Union{Symbol, T}[newsys; hierarchy]
1438+ end 
1439+ 
1440+ """ 
1441+     $(TYPEDSIGNATURES)  
1442+ 
1443+ Get the connections to ignore for `sys` and its subsystems. The returned value is a 
1444+ `Tuple` similar in structure to the `ignored_connections` field. Each system (variable) 
1445+ in the first (second) element of the tuple is also passed through `as_hierarchy`. 
1446+ """ 
1447+ function  ignored_connections (sys:: AbstractSystem )
1448+     has_ignored_connections (sys) ||  return  (HierarchySystemT[], HierarchyVariableT[])
1449+ 
1450+     ics =  get_ignored_connections (sys)
1451+     if  ics ===  nothing 
1452+         ics =  (HierarchySystemT[], HierarchyVariableT[])
1453+     end 
1454+     #  turn into hierarchies
1455+     ics =  (map (as_hierarchy, ics[1 ]), map (as_hierarchy, ics[2 ]))
1456+     systems =  get_systems (sys)
1457+     #  for each subsystem, get its ignored connections, add the name of the subsystem
1458+     #  to the hierarchy and concatenate corresponding buffers of the result
1459+     result =  mapreduce (Broadcast. BroadcastFunction (vcat), systems; init =  ics) do  subsys
1460+         sub_ics =  ignored_connections (subsys)
1461+         (map (Base. Fix2 (push!, nameof (subsys)), sub_ics[1 ]),
1462+             map (Base. Fix2 (push!, nameof (subsys)), sub_ics[2 ]))
1463+     end 
1464+     return  (Vector {HierarchySystemT} (result[1 ]), Vector {HierarchyVariableT} (result[2 ]))
1465+ end 
1466+ 
13651467""" 
13661468$(TYPEDSIGNATURES) 
13671469
0 commit comments