Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Two more API functions for getting the integer of a symbolic parameter/state variable #195

Closed
wants to merge 6 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
# v3.6.0

Two new API functions for MTK integration: `integer_state_index` and `integer_parameter_index`.

# v3.5.0

Dynamical systems that have been constructed from `DEProblem`s that themselves
Expand Down
2 changes: 1 addition & 1 deletion Project.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name = "DynamicalSystemsBase"
uuid = "6e36e845-645a-534a-86f2-f5d4aa5a06b4"
repo = "https://github.com/JuliaDynamics/DynamicalSystemsBase.jl.git"
version = "3.5.2"
version = "3.6.0"

[deps]
ForwardDiff = "f6369f11-7733-5829-9624-2563aa707210"
Expand Down
21 changes: 20 additions & 1 deletion docs/src/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ DynamicalSystemsBase
DynamicalSystem
```

### API - Obtain information
```@docs
current_state
initial_state
Expand All @@ -27,46 +28,61 @@ current_time
initial_time
isinplace(::DynamicalSystem)
successful_step
referrenced_sciml_model
```

### API - Alter status

```@docs
reinit!(::DynamicalSystem, args...; kwargs...)
set_state!
set_parameter!
set_parameters!
```

### API - MTK integration

```@docs
referrenced_sciml_model
integer_state_index
integer_parameter_index
```

## Time evolution

```@docs
step!(::DynamicalSystem, args...; kwargs...)
trajectory
StateSpaceSet
```

## `DeterministicIteratedMap`

```@docs
DeterministicIteratedMap
```

## `CoupledODEs`

```@docs
CoupledODEs
```

## `StroboscopicMap`

```@docs
StroboscopicMap
```

## `PoincareMap`

```@docs
PoincareMap
current_crossing_time
poincaresos
```

## `TangentDynamicalSystem`

```@docs
CoreDynamicalSystem
TangentDynamicalSystem
Expand All @@ -76,18 +92,21 @@ orthonormal
```

## `ProjectedDynamicalSystem`

```@docs
ProjectedDynamicalSystem
```

## `ParallelDynamicalSystem`

```@docs
ParallelDynamicalSystem
initial_states
current_states
```

## `ArbitrarySteppable`

```@docs
ArbitrarySteppable
```
Expand Down
44 changes: 38 additions & 6 deletions src/core/dynamicalsystem_interface.jl
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,9 @@ model and all symbolic variables. Accessing a `DynamicalSystem` using symbolic v
is possible via the functions [`observe_state`](@ref), [`set_state!`](@ref),
[`current_parameter`](@ref) and [`set_parameter!`](@ref).
The referenced MTK model corresponding to the dynamical system can be obtained with
`model = referrenced_sciml_model(ds::DynamicalSystem)`.
`model = referrenced_sciml_model(ds::DynamicalSystem)` and the convenience functions
[`integer_state_index`](@ref), [`integer_parameter_index`](@ref) are useful for further
usage of the dynamical system.

See also the DynamicalSystems.jl tutorial online for an example.

Expand Down Expand Up @@ -116,10 +118,11 @@ errormsg(ds) = error("Not yet implemented for dynamical system of type $(nameof(

export current_state, initial_state, current_parameters, current_parameter, initial_parameters, isinplace,
current_time, initial_time, successful_step, isdeterministic, isdiscretetime, dynamic_rule,
reinit!, set_state!, set_parameter!, set_parameters!, step!, observe_state, referrenced_sciml_model
reinit!, set_state!, set_parameter!, set_parameters!, step!, observe_state,
referrenced_sciml_model, integer_state_index, integer_parameter_index

###########################################################################################
# Symbolic support
# Symbolic support (MTK integration)
###########################################################################################
# Simply extend the `referrenced_sciml_prob` and you have symbolic indexing support!
import SymbolicIndexingInterface
Expand All @@ -140,7 +143,36 @@ referrenced_sciml_model(::Nothing) = nothing
has_referrenced_model(prob::SciMLBase.DEProblem) = has_referrenced_model(referrenced_sciml_model(prob))
has_referrenced_model(::Nothing) = false
has_referrenced_model(::SymbolicIndexingInterface.SymbolCache{Nothing, Nothing, Nothing}) = false
has_referrenced_model(sys) = true
has_referrenced_model(model) = true

"""
integer_parameter_index(symbol, ds::DynamicalSystem) → i::Int

Convert the given symbolic variable representing a parameter to its integer
index in the parameter container ([`current_parameters`](@ref)).
Return `nothing` if `ds` doesn't reference a symbolic model
or the model does not have the given `symbol` as parameter.
"""
integer_parameter_index(s, ds::DynamicalSystem) = integer_parameter_index(s, referrenced_sciml_model(ds))
function integer_parameter_index(symbol, model)
isnothing(model) && return nothing
findfirst(isequal(symbol), parameters(model))
end

"""
integer_state_index(symbol, ds::DynamicalSystem) → i::Int

Convert the given symbolic variable representing a state (dynamic) variable to its integer
index in the state vector ([`current_state`](@ref)).
Return `nothing` if `ds` doesn't reference a symbolic model
or the model does not have the given `symbol` as a state variable.
"""
integer_state_index(s, ds::DynamicalSystem) = integer_state_index(s, referrenced_sciml_model(ds))
function integer_state_index(symbol, model)
isnothing(model) && return nothing
findfirst(isequal(symbol), states(model))
end


###########################################################################################
# API - obtaining information from the system
Expand All @@ -163,9 +195,9 @@ See also [`initial_state`](@ref), [`observe_state`](@ref).
current_state(ds::DynamicalSystem) = ds.u

"""
observe_state(ds::DynamicalSystem, i) → x::Real
observe_state(ds::DynamicalSystem, i [,u = current_state(ds)]) → x::Real

Return the current state of `ds` _observed_ at "index" `i`. Possibilities are:
Return the state `u` of `ds` _observed_ at "index" `i`. Possibilities are:

- `i::Int` returns the `i`-th dynamic variable.
- `i::Function` returns `f(current_state(ds))`, which is asserted to be a real number.
Expand Down
12 changes: 10 additions & 2 deletions test/mtk_integration.jl
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,12 @@ set_state!(ds, 1.5, 1)
set_state!(ds, -0.5, fol_1.x)
@test observe_state(ds, 1) == -0.5

# integer conversion
@test integer_state_index(fol_1.x, ds) == 1
@test isnothing(integer_state_index(fol_2.RHS, ds))
@test integer_parameter_index(fol_1.f, ds) == 1
@test isnothing(integer_parameter_index(fol_1.x, ds))

# test that derivative dynamical systems also work as execpted
u1 = current_state(ds)
pds = ParallelDynamicalSystem(ds, [u1, copy(u1)])
Expand Down Expand Up @@ -110,8 +116,10 @@ set_parameter!(ds, 1, 2.0)

@test_throws ArgumentError observe_state(ds, fol_1.f)

# Test that remake works also without anything initial
@test isnothing(integer_state_index(fol_2.RHS, ds))
@test isnothing(integer_parameter_index(fol_1.x, ds))

# Test that remake works also without anything initial
@variables t
D = Differential(t)
@mtkmodel Roessler begin
Expand All @@ -138,4 +146,4 @@ end
prob = ODEProblem(roessler_model)
roessler = CoupledODEs(prob)

@test roessler isa CoupledODEs
@test roessler isa CoupledODEs
Loading