Skip to content

Commit 0da9f41

Browse files
authored
Update to DiffEq5 (#78)
* update type parameters of ODEIntegrators * trajectory works for OrdinaryDiffEq * all tests pass on DiffEq5 * Switch default solver to SimpleATsit5 * use .alg instead * use [:alg] god damn it
1 parent c131dee commit 0da9f41

File tree

9 files changed

+89
-74
lines changed

9 files changed

+89
-74
lines changed

REQUIRE

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
julia 0.7.0-beta2
22
StaticArrays 0.8
3-
DiffEqBase 4.10
4-
OrdinaryDiffEq 4.8
3+
DiffEqBase 5.0
54
ForwardDiff 0.8
65
DelayEmbeddings
76
Reexport 0.1
7+
SimpleDiffEq 0.1

src/continuous.jl

Lines changed: 50 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
1-
using OrdinaryDiffEq, StaticArrays
2-
import OrdinaryDiffEq: ODEIntegrator, ODEProblem
3-
using DiffEqBase: __init, ODEFunction
1+
using DiffEqBase, StaticArrays
2+
using DiffEqBase: __init, ODEFunction, AbstractODEIntegrator
43

54
export CDS_KWARGS
65
#####################################################################################
76
# Defaults #
87
#####################################################################################
9-
const DEFAULT_SOLVER = Vern9()
10-
const DEFAULT_DIFFEQ_KWARGS = (abstol = 1e-9,
11-
reltol = 1e-9, maxiters = typemax(Int))
8+
using SimpleDiffEq: SimpleATsit5
9+
const DEFAULT_SOLVER = SimpleATsit5()
10+
const DEFAULT_DIFFEQ_KWARGS = (abstol = 1e-6,
11+
reltol = 1e-6, maxiters = typemax(Int))
1212

1313
const CDS_KWARGS = (alg = DEFAULT_SOLVER, DEFAULT_DIFFEQ_KWARGS...)
1414

@@ -22,26 +22,23 @@ function ContinuousDynamicalSystem(prob::ODEProblem, args...)
2222
t0 = prob.tspan[1])
2323
end
2424

25-
function ODEProblem(ds::CDS{IIP}, tspan, args...) where {IIP}
26-
# when stable, do ODEFunction(ds.f; jac = ds.jacobian)
27-
return ODEProblem{IIP}(ds.f, ds.u0, tspan, args...)
25+
function DiffEqBase.ODEProblem(ds::CDS{IIP}, tspan, args...) where {IIP}
26+
return ODEProblem{IIP}(ODEFunction(ds.f; jac = ds.jacobian), ds.u0, tspan, args...)
2827
end
2928

3029
#####################################################################################
3130
# Integrators #
3231
#####################################################################################
33-
stateeltype(::ODEIntegrator{Alg, S}) where {Alg, S} = eltype(S)
34-
stateeltype(::ODEIntegrator{Alg, S}) where {
35-
Alg, S<:Vector{<:AbstractArray{T}}} where {T} = T
32+
stateeltype(::AbstractODEIntegrator{A, IIP, S}) where {A, IIP, S} = eltype(S)
33+
stateeltype(::AbstractODEIntegrator{A, IIP, S}) where {
34+
A, IIP, S<:Vector{<:AbstractArray{T}}} where {T} = T
3635

3736
function integrator(ds::CDS{iip}, u0 = ds.u0;
3837
tfinal = Inf, diffeq...) where {iip}
3938

4039
u = safe_state_type(Val{iip}(), u0)
4140
prob = ODEProblem{iip}(ds.f, u, (ds.t0, typeof(ds.t0)(tfinal)), ds.p)
4241

43-
(haskey(diffeq, :saveat) && tfinal == Inf) && error("Infinite solving!")
44-
4542
solver = _get_solver(diffeq)
4643
integ = __init(prob, solver; DEFAULT_DIFFEQ_KWARGS...,
4744
save_everystep = false, diffeq...)
@@ -108,12 +105,12 @@ function create_parallel(ds::CDS{true}, states)
108105
return paralleleom, st
109106
end
110107

111-
const STIFFSOLVERS = (ImplicitEuler, ImplicitMidpoint, Trapezoid, TRBDF2,
112-
GenericImplicitEuler,
113-
GenericTrapezoid, SDIRK2, Kvaerno3, KenCarp3, Cash4, Hairer4, Hairer42, Kvaerno4,
114-
KenCarp4, Kvaerno5, KenCarp5, Rosenbrock23,
115-
Rosenbrock32, ROS3P, Rodas3, RosShamp4, Veldd4, Velds4, GRK4T,
116-
GRK4A, Ros4LStab, Rodas4, Rodas42, Rodas4P)
108+
# const STIFFSOLVERS = (ImplicitEuler, ImplicitMidpoint, Trapezoid, TRBDF2,
109+
# GenericImplicitEuler,
110+
# GenericTrapezoid, SDIRK2, Kvaerno3, KenCarp3, Cash4, Hairer4, Hairer42, Kvaerno4,
111+
# KenCarp4, Kvaerno5, KenCarp5, Rosenbrock23,
112+
# Rosenbrock32, ROS3P, Rodas3, RosShamp4, Veldd4, Velds4, GRK4T,
113+
# GRK4A, Ros4LStab, Rodas4, Rodas42, Rodas4P)
117114

118115
function parallel_integrator(ds::CDS, states; diffeq...)
119116
peom, st = create_parallel(ds, states)
@@ -134,61 +131,74 @@ function trajectory(ds::ContinuousDynamicalSystem, T, u = ds.u0;
134131

135132
t0 = ds.t0
136133
tvec = (t0+Ttr):dt:(T+t0+Ttr)
137-
integ = integrator(ds, u; tfinal = t0 + Ttr + T, diffeq..., saveat = tvec)
138-
solve!(integ)
139-
return Dataset(integ.sol.u)
134+
sol = Vector{SVector{dimension(ds), stateeltype(ds)}}(undef, length(tvec))
135+
integ = integrator(ds, u; dt = dt, tfinal = tvec[end]+2dt, diffeq...)
136+
step!(integ, Ttr)
137+
for (i, t) in enumerate(tvec)
138+
while t > integ.t
139+
step!(integ)
140+
end
141+
if integ.tprev t integ.t
142+
sol[i] = integ(t)
143+
else
144+
error("should be integ.tprev ≤ t ≤ integ.t")
145+
end
146+
end
147+
return Dataset(sol)
140148
end
141149

142150
#####################################################################################
143151
# Get States #
144152
#####################################################################################
145-
get_state(integ::ODEIntegrator{Alg, S}) where {Alg, S<:AbstractVector} = integ.u
146-
get_state(integ::ODEIntegrator{Alg, S}) where {Alg, S<:AbstractMatrix} =
147-
integ.u[:, 1]
148-
get_state(integ::ODEIntegrator{Alg, S}) where {Alg, S<:Vector{<:AbstractVector}} =
153+
get_state(integ::AbstractODEIntegrator{Alg, IIP, S}) where {Alg, IIP, S<:AbstractVector} =
154+
integ.u
155+
get_state(integ::AbstractODEIntegrator{Alg, IIP, S}) where {Alg, IIP, S<:AbstractMatrix} =
156+
integ.u[:, 1]
157+
get_state(integ::AbstractODEIntegrator{Alg, IIP, S}) where {Alg, IIP, S<:Vector{<:AbstractVector}} =
149158
integ.u[1]
150-
get_state(integ::ODEIntegrator{Alg, S}, k::Int) where {
151-
Alg, S<:Vector{<:AbstractVector}} = integ.u[k]
152-
get_state(integ::ODEIntegrator{Alg, S}, k::Int) where {Alg, S<:AbstractMatrix} =
159+
get_state(integ::AbstractODEIntegrator{Alg, IIP, S}, k::Int) where {Alg, IIP, S<:Vector{<:AbstractVector}} =
160+
integ.u[k]
161+
get_state(integ::AbstractODEIntegrator{Alg, IIP, S}, k::Int) where {Alg, IIP, S<:AbstractMatrix} =
153162
integ.u[:, k]
154163

155164
function set_state!(
156-
integ::ODEIntegrator{Alg, S}, u::AbstractVector, k::Int = 1
157-
) where {Alg, S<:Vector{<:AbstractVector}}
165+
integ::AbstractODEIntegrator{Alg, IIP, S}, u::AbstractVector, k::Int = 1
166+
) where {Alg, IIP, S<:Vector{<:AbstractVector}}
158167
integ.u[k] = u
159168
u_modified!(integ, true)
160169
end
161170
function set_state!(
162-
integ::ODEIntegrator{Alg, S}, u::AbstractVector) where {Alg, S<:Matrix}
171+
integ::AbstractODEIntegrator{Alg, IIP, S}, u::AbstractVector
172+
) where {Alg, IIP, S<:Matrix}
163173
integ.u[:, 1] .= u
164174
u_modified!(integ, true)
165175
end
166176
function set_state!(
167-
integ::ODEIntegrator{Alg, S}, u::AbstractVector
168-
) where {Alg, S<:SMatrix{D, K}} where {D, K}
177+
integ::AbstractODEIntegrator{Alg, IIP, S}, u::AbstractVector
178+
) where {Alg, IIP, S<:SMatrix{D, K}} where {D, K}
169179
integ.u = hcat(SVector{D}(u), integ.u[:, SVector{K-1}(2:K...)])
170180
u_modified!(integ, true)
171181
end
172182

173-
get_deviations(integ::ODEIntegrator{Alg, S}) where {Alg, S<:Matrix} =
183+
get_deviations(integ::AbstractODEIntegrator{Alg, IIP, S}) where {Alg, IIP, S<:Matrix} =
174184
@view integ.u[:, 2:end]
175185

176186

177187
@generated function get_deviations(
178-
integ::ODEIntegrator{Alg, S}) where {Alg, S<:SMatrix{D,K}} where {D,K}
188+
integ::AbstractODEIntegrator{Alg, IIP, S}) where {Alg, IIP, S<:SMatrix{D,K}} where {D,K}
179189
gens = [:($k) for k=2:K]
180190
quote
181191
sind = SVector{$(K-1)}($(gens...))
182192
integ.u[:, sind]
183193
end
184194
end
185195

186-
set_deviations!(integ::ODEIntegrator{Alg, S}, Q) where {Alg, S<:Matrix} =
196+
set_deviations!(integ::AbstractODEIntegrator{Alg, IIP, S}, Q) where {Alg, IIP, S<:Matrix} =
187197
(integ.u[:, 2:end] .= Q; u_modified!(integ, true))
188-
set_deviations!(integ::ODEIntegrator{Alg, S}, Q) where {Alg, S<:SMatrix} =
198+
set_deviations!(integ::AbstractODEIntegrator{Alg, IIP, S}, Q) where {Alg, IIP, S<:SMatrix} =
189199
(integ.u = hcat(integ.u[:,1], Q); u_modified!(integ, true))
190200

191-
function DiffEqBase.reinit!(integ::ODEIntegrator, u0::AbstractVector,
201+
function DiffEqBase.reinit!(integ::AbstractODEIntegrator, u0::AbstractVector,
192202
Q0::AbstractMatrix; kwargs...)
193203

194204
set_state!(integ, u0)

src/discrete.jl

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -176,7 +176,7 @@ end
176176
#####################################################################################
177177
# Creating Integrators #
178178
#####################################################################################
179-
function integrator(ds::DDS{IIP, S, D, F, P}, u0 = ds.u0) where {IIP, S, D, F, P}
179+
function integrator(ds::DDS{IIP, S, D, F, P}, u0 = ds.u0; kwargs...) where {IIP, S, D, F, P}
180180
return MinimalDiscreteIntegrator{IIP, S, D, F, P}(
181181
ds.f, S(u0), ds.t0, S(copy(u0)), ds.p, ds.t0)
182182
end
@@ -187,7 +187,7 @@ function tangent_integrator(ds::DDS, k::Int = dimension(ds); kwargs...)
187187
end
188188

189189
function tangent_integrator(ds::DDS{IIP, S, D, F, P, JAC, JM}, Q0::AbstractMatrix;
190-
u0 = ds.u0) where {IIP, S, D, F, P, JAC, JM}
190+
u0 = ds.u0, kwargs...) where {IIP, S, D, F, P, JAC, JM}
191191

192192
Q = safe_matrix_type(Val{IIP}(), Q0)
193193
s = safe_state_type(Val{IIP}(), u0)
@@ -204,7 +204,7 @@ end
204204
# Auto-diffed in-place version
205205
function tangent_integrator(ds::DDS{true, S, D, F, P, JAC, JM, true},
206206
Q0::AbstractMatrix;
207-
u0 = ds.u0) where {S, D, F, P, JAC, JM}
207+
u0 = ds.u0, kwargs...) where {S, D, F, P, JAC, JM}
208208

209209
t0 = ds.t0
210210
R = D + length(Q0)
@@ -226,7 +226,7 @@ function tangent_integrator(ds::DDS{true, S, D, F, P, JAC, JM, true},
226226
return MDI{true, SS, R, TF, P}(tangentf, s, t0, deepcopy(s), ds.p, t0)
227227
end
228228

229-
function parallel_integrator(ds::DDS{IIP, S, D}, states) where {IIP, S, D}
229+
function parallel_integrator(ds::DDS{IIP, S, D}, states; kwargs...) where {IIP, S, D}
230230
peom, st = create_parallel(ds, states)
231231
F = typeof(peom); X = typeof(st); P = typeof(ds.p)
232232
return MDI{true, X, D, F, P}(peom, st, ds.t0, deepcopy(st), ds.p, ds.t0)

src/dynamicalsystem.jl

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
using LinearAlgebra, DiffEqBase, ForwardDiff, StaticArrays
2-
import DiffEqBase: isinplace, reinit!
32
using SparseArrays
43

54
export dimension, get_state, DynamicalSystem
@@ -140,7 +139,7 @@ const DDS = DiscreteDynamicalSystem
140139
systemtype(::DDS) = "discrete"
141140

142141

143-
isinplace(::DS{IIP}) where {IIP} = IIP
142+
DiffEqBase.isinplace(::DS{IIP}) where {IIP} = IIP
144143
statetype(::DS{IIP, S}) where {IIP, S} = S
145144
stateeltype(::DS{IIP, S}) where {IIP, S} = eltype(S)
146145
isautodiff(::DS{IIP, S, D, F, P, JAC, JM, IAD}) where
@@ -289,7 +288,7 @@ end
289288
# Jacobians #
290289
#######################################################################################
291290
function create_jacobian(
292-
f::F, ::Val{IIP}, s::S, p::P, t::T, ::Val{D}) where {F, IIP, S, P, T, D}
291+
@nospecialize(f::F), ::Val{IIP}, s::S, p::P, t::T, ::Val{D}) where {F, IIP, S, P, T, D}
293292
if IIP
294293
dum = deepcopy(s)
295294
cfg = ForwardDiff.JacobianConfig(
@@ -339,8 +338,9 @@ ds.jacobian(u, ds.p, t)
339338
#######################################################################################
340339
# Tanget Dynamics #
341340
#######################################################################################
341+
342342
# IIP Tangent Space dynamics
343-
function create_tangent(f::F, jacobian::JAC, J::JM,
343+
function create_tangent(@nospecialize(f::F), @nospecialize(jacobian::JAC), J::JM,
344344
::Val{true}, ::Val{k}) where {F, JAC, JM, k}
345345
J = deepcopy(J)
346346
tangentf = (du, u, p, t) -> begin
@@ -352,7 +352,6 @@ function create_tangent(f::F, jacobian::JAC, J::JM,
352352
end
353353
return tangentf
354354
end
355-
356355
# for the case of autodiffed systems, a specialized version is created
357356
# so that f! is not called twice in ForwardDiff
358357
function create_tangent_iad(f::F, J::JM, u, p, t, ::Val{k}) where {F, JM, k}
@@ -374,7 +373,6 @@ function create_tangent_iad(f::F, J::JM, u, p, t, ::Val{k}) where {F, JM, k}
374373
end
375374

376375

377-
378376
# OOP Tangent Space dynamics
379377
function create_tangent(f::F, jacobian::JAC, J::JM,
380378
::Val{false}, ::Val{k}) where {F, JAC, JM, k}

test/REQUIRE

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
DiffEqCallbacks 2.1
2+
OrdinaryDiffEq 5.0

test/dynsys_tangent.jl

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,18 @@
11
using DynamicalSystemsBase
2-
using StaticArrays, LinearAlgebra
2+
using OrdinaryDiffEq, SimpleDiffEq, StaticArrays, LinearAlgebra
33
using Test
44

5+
algs = (Vern9(), Tsit5(), SimpleATsit5())
6+
57
using DynamicalSystemsBase: CDS, DDS, DS
68
using DynamicalSystemsBase.Systems: hoop, hoop_jac, hiip, hiip_jac
79
using DynamicalSystemsBase.Systems: loop, loop_jac, liip, liip_jac
810
using DiffEqBase
911

1012
println("\nTesting tangent dynamics...")
1113

12-
let
14+
for alg in algs
15+
1316
u0 = [0, 10.0, 0]
1417
p = [10, 28, 8/3]
1518
u0h = ones(2)
@@ -23,7 +26,7 @@ PARAMS = [p, ph]
2326
# minimalistic lyapunov
2427
function lyapunov_iip(ds::DS, k)
2528
D = dimension(ds)
26-
tode = tangent_integrator(ds, orthonormal(D,k))
29+
tode = tangent_integrator(ds, orthonormal(D,k); alg = alg)
2730
λ = zeros(k)
2831
for t in 1:1000
2932
while tode.t < t
@@ -41,7 +44,7 @@ function lyapunov_iip(ds::DS, k)
4144
end
4245
function lyapunov_oop(ds::DS, k)
4346
D = dimension(ds)
44-
tode = tangent_integrator(ds, orthonormal(D,k))
47+
tode = tangent_integrator(ds, orthonormal(D,k); alg = alg)
4548
λ = zeros(k)
4649
ws_idx = SVector{k, Int}(collect(2:k+1))
4750
for t in 1:1000
@@ -60,7 +63,7 @@ function lyapunov_oop(ds::DS, k)
6063
end
6164

6265
for i in 1:8
63-
@testset "combination $i" begin
66+
@testset "$alg combination $i" begin
6467
sysindx = i < 5 ? 1 : 2
6568
if i < 5
6669
if isodd(i)
@@ -84,7 +87,7 @@ for i in 1:8
8487
end
8588

8689
if i < 5
87-
@test 0.8 < λ[1] < 0.9
90+
@test 0.8 < λ[1] < 0.92
8891
else
8992
@test 0.4 < λ[1] < 0.45
9093
end

test/dynsys_types.jl

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
11
using DynamicalSystemsBase
2-
using Test, StaticArrays, LinearAlgebra
2+
using Test, StaticArrays, LinearAlgebra, OrdinaryDiffEq, SimpleDiffEq
33
using DynamicalSystemsBase: CDS, DDS
44
using DynamicalSystemsBase.Systems: hoop, hoop_jac, hiip, hiip_jac
55
using DynamicalSystemsBase.Systems: loop, loop_jac, liip, liip_jac
66

77
println("\nTesting dynamical systems...")
8-
let
8+
9+
algs = (Vern9(), Tsit5(), SimpleATsit5())
10+
11+
for alg in algs
912
u0 = [0, 10.0, 0]
1013
p = [10, 28, 8/3]
1114
u0h = ones(2)
@@ -16,7 +19,7 @@ INITCOD = [u0, u0h]
1619
PARAMS = [p, ph]
1720

1821
for i in 1:8
19-
@testset "combination $i" begin
22+
@testset "$alg combination $i" begin
2023
sysindx = i < 5 ? 1 : 2
2124
if i < 5
2225
if isodd(i)
@@ -39,12 +42,12 @@ for i in 1:8
3942
J = jacobian(ds)
4043
@test typeof(J) <: (iip ? Matrix : SMatrix)
4144

42-
tinteg = tangent_integrator(ds, orthonormal(dimension(ds), dimension(ds)))
45+
tinteg = tangent_integrator(ds, orthonormal(dimension(ds), dimension(ds)); alg = alg)
4346
tuprev = deepcopy(get_state(tinteg))
4447
step!(tinteg)
4548
@test tuprev != get_state(tinteg)
4649

47-
integ = integrator(ds)
50+
integ = integrator(ds; alg = alg)
4851
uprev = deepcopy(get_state(integ))
4952
step!(integ)
5053
@test uprev != get_state(integ)
@@ -56,14 +59,14 @@ for i in 1:8
5659
step!(integ)
5760
end
5861

59-
@test get_state(tinteg) integ(tt)
62+
@test get_state(tinteg) integ(tt) atol = 1e-2
6063
else
6164
@test get_state(tinteg) == get_state(integ)
6265
end
6366

6467
# Currently the in-place version does not work from DiffEq's side:
6568
if i > 2
66-
pinteg = parallel_integrator(ds, [INITCOD[sysindx], INITCOD[sysindx]])
69+
pinteg = parallel_integrator(ds, [INITCOD[sysindx], INITCOD[sysindx]]; alg = alg)
6770
puprev = deepcopy(get_state(pinteg))
6871
step!(pinteg)
6972
@test get_state(pinteg, 1) == get_state(pinteg, 2) == get_state(pinteg)
@@ -83,7 +86,7 @@ for i in 1:8
8386
@test get_state(pinteg) == get_state(integ)
8487
end
8588
else
86-
pinteg = parallel_integrator(ds, [INITCOD[sysindx], INITCOD[sysindx]])
89+
pinteg = parallel_integrator(ds, [INITCOD[sysindx], INITCOD[sysindx]]; alg = alg)
8790
puprev = deepcopy(get_state(pinteg))
8891
step!(pinteg)
8992
@test get_state(pinteg, 1) == get_state(pinteg, 2) == get_state(pinteg)
@@ -92,7 +95,7 @@ for i in 1:8
9295
while integ.t < tt
9396
step!(integ)
9497
end
95-
@test get_state(pinteg, 1) integ(tt)
98+
@test get_state(pinteg, 1) integ(tt) atol = 1e-2
9699
end
97100
end
98101
end

0 commit comments

Comments
 (0)