@@ -706,3 +706,143 @@ function convert_system_indepvar(sys::System, t; name = nameof(sys))
706706    @set!  sys. var_to_name =  var_to_name
707707    return  sys
708708end 
709+ 
710+ """ 
711+     $(TYPEDSIGNATURES)  
712+ 
713+ Shorthand for `respecialize(sys, []; all = true)` 
714+ """ 
715+ respecialize (sys:: AbstractSystem ) =  respecialize (sys, []; all =  true )
716+ 
717+ """ 
718+     $(TYPEDSIGNATURES)  
719+ 
720+ Specialize nonnumeric parameters in `sys` by changing their symtype to a concrete type. 
721+ `mapping` is an iterable, where each element can be a parameter or a pair mapping a parameter 
722+ to a value. If the element is a parameter, it must have a default. Each specified parameter 
723+ is updated to have the symtype of the value associated with it (either in `mapping` or in 
724+ the defaults). This operation can only be performed on nonnumeric, non-array parameters. The 
725+ defaults of respecialized parameters are set to the associated values. 
726+ 
727+ This operation can only be performed on `complete`d systems. 
728+ 
729+ # Keyword arguments 
730+ 
731+ - `all`: Specialize all nonnumeric parameters in the system. This will error if any such 
732+   parameter does not have a default. 
733+ """ 
734+ function  respecialize (sys:: AbstractSystem , mapping; all =  false )
735+     if  ! iscomplete (sys)
736+         error (""" 
737+         This operation can only be performed on completed systems. Use `complete(sys)` or 
738+         `mtkcompile(sys)`. 
739+         """  )
740+     end 
741+     if  ! is_split (sys)
742+         error (""" 
743+         This operation can only be performed on split systems. Use `complete(sys)` or 
744+         `mtkcompile(sys)` with the `split = true` keyword argument. 
745+         """  )
746+     end 
747+ 
748+     new_ps =  copy (get_ps (sys))
749+     @set!  sys. ps =  new_ps
750+ 
751+     extras =  []
752+     if  all
753+         for  x in  filter (! is_variable_numeric, get_ps (sys))
754+             if  any (y ->  isequal (x, y) ||  y isa  Pair &&  isequal (x, y[1 ]), mapping) || 
755+                symbolic_type (x) ===  ArraySymbolic () || 
756+                iscall (x) &&  operation (x) ===  getindex
757+                 continue 
758+             end 
759+             push! (extras, x)
760+         end 
761+     end 
762+     ps_to_specialize =  Iterators. flatten ((extras, mapping))
763+ 
764+     defs =  copy (defaults (sys))
765+     @set!  sys. defaults =  defs
766+     final_defs =  copy (defs)
767+     evaluate_varmap! (final_defs, ps_to_specialize)
768+ 
769+     subrules =  Dict ()
770+ 
771+     for  element in  ps_to_specialize
772+         if  element isa  Pair
773+             k, v =  element
774+         else 
775+             k =  element
776+             v =  get (final_defs, k, nothing )
777+             @assert  v != =  nothing  """ 
778+             Parameter $k  needs an associated value to be respecialized. 
779+             """  
780+             @assert  symbolic_type (v) ==  NotSymbolic () &&  ! is_array_of_symbolics (v) """ 
781+             Parameter $k  needs an associated value to be respecialized. Found symbolic \ 
782+             default $v . 
783+             """  
784+         end 
785+ 
786+         k =  unwrap (k)
787+         T =  typeof (v)
788+ 
789+         @assert  ! is_variable_numeric (k) """ 
790+         Numeric types cannot be respecialized - tried to respecialize $k . 
791+         """  
792+         @assert  symbolic_type (k) != =  ArraySymbolic () """ 
793+         Cannot respecialize array symbolics - tried to respecialize $k . 
794+         """  
795+         @assert  ! iscall (k) ||  operation (k) != =  getindex """ 
796+         Cannot respecialized scalarized array variables - tried to respecialize $k . 
797+         """  
798+         idx =  findfirst (isequal (k), get_ps (sys))
799+         @assert  idx != =  nothing  """ 
800+         Parameter $k  does not exist in the system. 
801+         """  
802+ 
803+         if  iscall (k)
804+             op =  operation (k)
805+             args =  arguments (k)
806+             new_p =  SymbolicUtils. term (op, args... ; type =  T)
807+         else 
808+             new_p =  SymbolicUtils. Sym {T} (getname (k))
809+         end 
810+ 
811+         get_ps (sys)[idx] =  new_p
812+         defaults (sys)[new_p] =  v
813+         subrules[unwrap (k)] =  unwrap (new_p)
814+     end 
815+ 
816+     substituter =  Base. Fix2 (fast_substitute, subrules)
817+     @set!  sys. eqs =  map (substituter, get_eqs (sys))
818+     @set!  sys. observed =  map (substituter, get_observed (sys))
819+     @set!  sys. initialization_eqs =  map (substituter, get_initialization_eqs (sys))
820+     if  get_noise_eqs (sys) != =  nothing 
821+         @set!  sys. noise_eqs =  map (substituter, get_noise_eqs (sys))
822+     end 
823+     @set!  sys. assertions =  Dict ([substituter (k) =>  v for  (k, v) in  assertions (sys)])
824+     @set!  sys. parameter_dependencies =  map (substituter, get_parameter_dependencies (sys))
825+     @set!  sys. defaults =  Dict ([substituter (k) =>  substituter (v) for  (k, v) in  defaults (sys)])
826+     @set!  sys. guesses =  Dict ([k =>  substituter (v) for  (k, v) in  guesses (sys)])
827+     @set!  sys. continuous_events =  map (get_continuous_events (sys)) do  cev
828+         SymbolicContinuousCallback (
829+             map (substituter, cev. conditions), substituter (cev. affect),
830+             substituter (cev. affect_neg), substituter (cev. initialize),
831+             substituter (cev. finalize), cev. rootfind,
832+             cev. reinitializealg, cev. zero_crossing_id)
833+     end 
834+     @set!  sys. discrete_events =  map (get_discrete_events (sys)) do  dev
835+         SymbolicDiscreteCallback (map (substituter, dev. conditions), substituter (dev. affect),
836+             substituter (dev. initialize), substituter (dev. finalize), dev. reinitializealg)
837+     end 
838+     if  get_schedule (sys) != =  nothing 
839+         sched =  get_schedule (sys)
840+         @set!  sys. schedule =  Schedule (
841+             sched. var_sccs, AnyDict (k =>  substituter (v) for  (k, v) in  sched. dummy_sub))
842+     end 
843+     @set!  sys. constraints =  map (substituter, get_constraints (sys))
844+     @set!  sys. tstops =  map (substituter, get_tstops (sys))
845+     @set!  sys. costs =  Vector {Union{Real, BasicSymbolic}} (map (substituter, get_costs (sys)))
846+     sys =  complete (sys; split =  is_split (sys))
847+     return  sys
848+ end 
0 commit comments