@@ -105,6 +105,9 @@ unless when developing new algorithm implementations that use dynamical systems.
105105"""
106106abstract type DynamicalSystem end
107107
108+ # Make it broadcastable:
109+ Base. broadcastable (ds:: DynamicalSystem ) = Ref (ds)
110+
108111# We utilize nature of time for dispatch; continuous time dispatches to `integ`
109112# and dispatches for `::DEIntegrator` are defined in `CoupledODEs` file.
110113"""
@@ -326,27 +329,35 @@ StateSpaceSets.dimension(ds::DynamicalSystem) = length(current_state(ds))
326329# API - altering status of the system
327330# ##########################################################################################
328331"""
329- set_state!(ds::DynamicalSystem, u::AbstractArray)
332+ set_state!(ds::DynamicalSystem, u::AbstractArray{Real} )
330333
331334Set the state of `ds` to `u`, which must match dimensionality with that of `ds`.
332335Also ensure that the change is notified to whatever integration protocol is used.
333336"""
334337set_state! (ds, u) = errormsg (ds)
335338
336339"""
337- set_state!(ds::DynamicalSystem, value::Real, index ) → u
340+ set_state!(ds::DynamicalSystem, value::Real, i ) → u
338341
339- Set the `i`th variable of `ds` to `value`. The ` index` can be an integer or
342+ Set the `i`th variable of `ds` to `value`. The index `i ` can be an integer or
340343a symbolic-like index for systems that reference a ModelingToolkit.jl model.
341-
342- Calling instead `set_state!(u, value, index, ds)` will modify the given
343- state `u` and return it, leaving `ds` unaltered.
344+ For example:
345+ ```julia
346+ i = :x # or `1` or `only(@variables(x))`
347+ set_state!(ds, 0.5, i)
348+ ```
344349
345350**Warning:** this function should not be used with derivative dynamical systems
346351such as Poincare/stroboscopic/projected dynamical systems.
352+ Use the method below to manipulate an array and give that to `set_state!`.
353+
354+
355+ set_state!(u::AbstractArray, value, index, ds::DynamicalSystem)
356+
357+ Modify the given state `u` and leave `ds` untouched.
347358"""
348359function set_state! (ds:: DynamicalSystem , value:: Real , i)
349- u = current_state (ds)
360+ u = Array ( current_state (ds)) # ensure it works for out of place as well!
350361 u = set_state! (u, value, i, ds)
351362 set_state! (ds, u)
352363end
@@ -365,6 +376,27 @@ function set_state!(u::AbstractArray, value::Real, i, ds::DynamicalSystem)
365376 return u
366377end
367378
379+ """
380+ set_state!(ds::DynamicalSystem, mapping::Dict)
381+
382+ Convenience version of `set_state!` that iteratively calls `set_state!(ds, val, i)`
383+ for all index-value pairs `(i, val)` in `mapping`. This allows you to
384+ partially set only some state variables.
385+ """
386+ function set_state! (ds:: DynamicalSystem , mapping:: Dict )
387+ # ensure we use a mutable vector, so same code works for in-place problems
388+ # (SymbolicIndexingInterface only works with mutable objects)
389+ um = Array (copy (current_state (ds)))
390+ set_state! (um, mapping, ds)
391+ set_state! (ds, um)
392+ end
393+ function set_state! (um:: Array{<:Real} , mapping:: Dict , ds:: DynamicalSystem )
394+ for (i, value) in pairs (mapping)
395+ set_state! (um, value, i, ds)
396+ end
397+ return um
398+ end
399+
368400"""
369401 set_parameter!(ds::DynamicalSystem, index, value [, p])
370402
@@ -403,14 +435,18 @@ end
403435"""
404436 set_parameters!(ds::DynamicalSystem, p = initial_parameters(ds))
405437
406- Set the parameter values in the [`current_parameters`](@ref)`(ds)` to match `p`.
407- This is done as an in-place overwrite by looping over the keys of `p`.
408- Hence the keys of `p` must be a subset of the keys of [`current_parameters`](@ref)`(ds)`.
438+ Set the parameter values in the [`current_parameters`](@ref)`(ds)` to match those in `p`.
439+ This is done as an in-place overwrite by looping over the keys of `p`
440+ hence `p` can be an arbitrary container mapping parameter indices to values
441+ (such as a `Vector{Real}`, `Vector{Pair}`, or `Dict`).
442+
443+ The keys of `p` must be valid keys that can be given to [`set_parameter!`](@ref).
409444"""
410445function set_parameters! (ds:: DynamicalSystem , p = initial_parameters (ds))
411446 cp = current_parameters (ds)
412447 p === cp && return
413- for (index, value) in pairs (p)
448+ iter = p isa Vector ? pairs (p) : p # allows using vector, dict, or vector{pair}.
449+ for (index, value) in iter
414450 _set_parameter! (ds, index, value, cp)
415451 end
416452 return
@@ -442,15 +478,28 @@ SciMLBase.step!(ds::DynamicalSystem, args...) = errormsg(ds)
442478
443479Reset the status of `ds`, so that it is as if it has be just initialized
444480with initial state `u`. Practically every function of the ecosystem that evolves
445- `ds` first calls this function on it. Besides the new initial state `u`, you
481+ `ds` first calls this function on it. Besides the new state `u`, you
446482can also configure the keywords `t0 = initial_time(ds)` and `p = current_parameters(ds)`.
447483
448- Note the default settings: the state and time are the initial,
449- but the parameters are the current.
484+ reinit!(ds::DynamicalSystem, u::Dict; kwargs...) → ds
450485
451- The special method `reinit!(ds, ::Nothing; kwargs...)` is also available,
452- which does nothing and leaves the system as is. This is so that downstream functions
486+ If `u` is a `Dict` (for partially setting specific state variables in [`set_state`](@ref)),
487+ then the alterations in `u` are still done in the state given by the keyword
488+ `reference_state = copy(initial_state(ds))`.
489+
490+ reinit!(ds, ::Nothing; kwargs...)
491+
492+ This method does nothing and leaves the system as is. This is so that downstream functions
453493that call `reinit!` can still be used without resetting the system but rather
454494continuing from its exact current state.
455495"""
456- SciMLBase. reinit! (ds:: DynamicalSystem , args... ; kwargs... ) = errormsg (ds)
496+ function SciMLBase. reinit! (ds:: DynamicalSystem , mapping:: Dict ;
497+ reference_state = copy (initial_state (ds)), kwargs... )
498+ um = Array (reference_state)
499+ set_state! (um, mapping, ds)
500+ reinit! (ds, um; kwargs... )
501+ end
502+
503+ SciMLBase. reinit! (ds:: DynamicalSystem , :: Nothing ; kw... ) = ds
504+ # all extensions of `reinit!` in concrete implementaitons
505+ # should only implement `reinit!(ds, ::AbstractArray)` method.
0 commit comments