@@ -942,3 +942,143 @@ function convert_system_indepvar(sys::System, t; name = nameof(sys))
942942    @set!  sys. var_to_name =  var_to_name
943943    return  sys
944944end 
945+ 
946+ """ 
947+     $(TYPEDSIGNATURES)  
948+ 
949+ Shorthand for `respecialize(sys, []; all = true)` 
950+ """ 
951+ respecialize (sys:: AbstractSystem ) =  respecialize (sys, []; all =  true )
952+ 
953+ """ 
954+     $(TYPEDSIGNATURES)  
955+ 
956+ Specialize nonnumeric parameters in `sys` by changing their symtype to a concrete type. 
957+ `mapping` is an iterable, where each element can be a parameter or a pair mapping a parameter 
958+ to a value. If the element is a parameter, it must have a default. Each specified parameter 
959+ is updated to have the symtype of the value associated with it (either in `mapping` or in 
960+ the defaults). This operation can only be performed on nonnumeric, non-array parameters. The 
961+ defaults of respecialized parameters are set to the associated values. 
962+ 
963+ This operation can only be performed on `complete`d systems. 
964+ 
965+ # Keyword arguments 
966+ 
967+ - `all`: Specialize all nonnumeric parameters in the system. This will error if any such 
968+   parameter does not have a default. 
969+ """ 
970+ function  respecialize (sys:: AbstractSystem , mapping; all =  false )
971+     if  ! iscomplete (sys)
972+         error (""" 
973+         This operation can only be performed on completed systems. Use `complete(sys)` or 
974+         `mtkcompile(sys)`. 
975+         """  )
976+     end 
977+     if  ! is_split (sys)
978+         error (""" 
979+         This operation can only be performed on split systems. Use `complete(sys)` or 
980+         `mtkcompile(sys)` with the `split = true` keyword argument. 
981+         """  )
982+     end 
983+ 
984+     new_ps =  copy (get_ps (sys))
985+     @set!  sys. ps =  new_ps
986+ 
987+     extras =  []
988+     if  all
989+         for  x in  filter (! is_variable_numeric, get_ps (sys))
990+             if  any (y ->  isequal (x, y) ||  y isa  Pair &&  isequal (x, y[1 ]), mapping) || 
991+                symbolic_type (x) ===  ArraySymbolic () || 
992+                iscall (x) &&  operation (x) ===  getindex
993+                 continue 
994+             end 
995+             push! (extras, x)
996+         end 
997+     end 
998+     ps_to_specialize =  Iterators. flatten ((extras, mapping))
999+ 
1000+     defs =  copy (defaults (sys))
1001+     @set!  sys. defaults =  defs
1002+     final_defs =  copy (defs)
1003+     evaluate_varmap! (final_defs, ps_to_specialize)
1004+ 
1005+     subrules =  Dict ()
1006+ 
1007+     for  element in  ps_to_specialize
1008+         if  element isa  Pair
1009+             k, v =  element
1010+         else 
1011+             k =  element
1012+             v =  get (final_defs, k, nothing )
1013+             @assert  v != =  nothing  """ 
1014+             Parameter $k  needs an associated value to be respecialized. 
1015+             """  
1016+             @assert  symbolic_type (v) ==  NotSymbolic () &&  ! is_array_of_symbolics (v) """ 
1017+             Parameter $k  needs an associated value to be respecialized. Found symbolic \ 
1018+             default $v . 
1019+             """  
1020+         end 
1021+ 
1022+         k =  unwrap (k)
1023+         T =  typeof (v)
1024+ 
1025+         @assert  ! is_variable_numeric (k) """ 
1026+         Numeric types cannot be respecialized - tried to respecialize $k . 
1027+         """  
1028+         @assert  symbolic_type (k) != =  ArraySymbolic () """ 
1029+         Cannot respecialize array symbolics - tried to respecialize $k . 
1030+         """  
1031+         @assert  ! iscall (k) ||  operation (k) != =  getindex """ 
1032+         Cannot respecialized scalarized array variables - tried to respecialize $k . 
1033+         """  
1034+         idx =  findfirst (isequal (k), get_ps (sys))
1035+         @assert  idx != =  nothing  """ 
1036+         Parameter $k  does not exist in the system. 
1037+         """  
1038+ 
1039+         if  iscall (k)
1040+             op =  operation (k)
1041+             args =  arguments (k)
1042+             new_p =  SymbolicUtils. term (op, args... ; type =  T)
1043+         else 
1044+             new_p =  SymbolicUtils. Sym {T} (getname (k))
1045+         end 
1046+ 
1047+         get_ps (sys)[idx] =  new_p
1048+         defaults (sys)[new_p] =  v
1049+         subrules[unwrap (k)] =  unwrap (new_p)
1050+     end 
1051+ 
1052+     substituter =  Base. Fix2 (fast_substitute, subrules)
1053+     @set!  sys. eqs =  map (substituter, get_eqs (sys))
1054+     @set!  sys. observed =  map (substituter, get_observed (sys))
1055+     @set!  sys. initialization_eqs =  map (substituter, get_initialization_eqs (sys))
1056+     if  get_noise_eqs (sys) != =  nothing 
1057+         @set!  sys. noise_eqs =  map (substituter, get_noise_eqs (sys))
1058+     end 
1059+     @set!  sys. assertions =  Dict ([substituter (k) =>  v for  (k, v) in  assertions (sys)])
1060+     @set!  sys. parameter_dependencies =  map (substituter, get_parameter_dependencies (sys))
1061+     @set!  sys. defaults =  Dict ([substituter (k) =>  substituter (v) for  (k, v) in  defaults (sys)])
1062+     @set!  sys. guesses =  Dict ([k =>  substituter (v) for  (k, v) in  guesses (sys)])
1063+     @set!  sys. continuous_events =  map (get_continuous_events (sys)) do  cev
1064+         SymbolicContinuousCallback (
1065+             map (substituter, cev. conditions), substituter (cev. affect),
1066+             substituter (cev. affect_neg), substituter (cev. initialize),
1067+             substituter (cev. finalize), cev. rootfind,
1068+             cev. reinitializealg, cev. zero_crossing_id)
1069+     end 
1070+     @set!  sys. discrete_events =  map (get_discrete_events (sys)) do  dev
1071+         SymbolicDiscreteCallback (map (substituter, dev. conditions), substituter (dev. affect),
1072+             substituter (dev. initialize), substituter (dev. finalize), dev. reinitializealg)
1073+     end 
1074+     if  get_schedule (sys) != =  nothing 
1075+         sched =  get_schedule (sys)
1076+         @set!  sys. schedule =  Schedule (
1077+             sched. var_sccs, AnyDict (k =>  substituter (v) for  (k, v) in  sched. dummy_sub))
1078+     end 
1079+     @set!  sys. constraints =  map (substituter, get_constraints (sys))
1080+     @set!  sys. tstops =  map (substituter, get_tstops (sys))
1081+     @set!  sys. costs =  Vector {Union{Real, BasicSymbolic}} (map (substituter, get_costs (sys)))
1082+     sys =  complete (sys; split =  is_split (sys))
1083+     return  sys
1084+ end 
0 commit comments