Skip to content

Commit 32600e4

Browse files
committed
refined integrator syntax
1 parent d42cf78 commit 32600e4

File tree

2 files changed

+128
-57
lines changed

2 files changed

+128
-57
lines changed

Project.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
name = "Adapode"
22
uuid = "0750cfb5-909a-49d7-927e-29b6595444bf"
33
authors = ["Michael Reed"]
4-
version = "0.3.2"
4+
version = "0.3.3"
55

66
[deps]
77
Requires = "ae029012-a4dd-5104-9daa-d747884805df"

src/Adapode.jl

+127-56
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,51 @@ export ProductSpace, RealRegion, Interval, Rectangle, Hyperrectangle, ⧺, ⊕
3939
include("constants.jl")
4040
include("element.jl")
4141

42+
abstract type AbstractIntegrator end
43+
abstract type StepIntegrator <: AbstractIntegrator end
44+
abstract type AdaptiveIntegrator <: AbstractIntegrator end
45+
46+
struct EulerHeunIntegrator <: StepIntegrator
47+
tol::Float64
48+
end
49+
50+
struct ExplicitIntegrator{o} <: StepIntegrator
51+
tol::Float64
52+
end
53+
54+
struct ExplicitAdaptor{o} <: AdaptiveIntegrator
55+
tol::Float64
56+
end
57+
58+
struct MultistepIntegrator{o} <: StepIntegrator
59+
tol::Float64
60+
end
61+
62+
struct MultistepAdaptor{o} <: AdaptiveIntegrator
63+
tol::Float64
64+
end
65+
66+
AbstractIntegrator(tol=15,int::AbstractIntegrator=ExplicitIntegrator{4}) = int(tol)
67+
AbstractIntegrator(tol,m,o=4) = AbstractIntegrator(tol,Val(m),Val(o))
68+
function AbstractIntegrator(tol,M::Val{m},B::Val{o}=Val(4)) where {m,o}
69+
int = if m == 0
70+
EulerHeunIntegrator(tol)
71+
elseif m == 1
72+
ExplicitIntegrator{o}(tol)
73+
elseif m == 2
74+
ExplicitAdaptor{o}(tol)
75+
elseif m == 3
76+
MultistepIntegrator{o}(tol)
77+
elseif m == 4
78+
MultistepAdaptor{o}(tol)
79+
end
80+
end
81+
82+
EulerHeunIntegrator(tol::Int) = EulerHeunIntegrator(2.0^-tol)
83+
for fun (:ExplicitIntegrator,:ExplicitAdaptor,:MultistepIntegrator,:MultistepAdaptor)
84+
@eval $fun{o}(tol::Int) where o = $fun{o}(2.0^-tol)
85+
end
86+
4287
mutable struct TimeStep{T}
4388
h::T
4489
hmin::T
@@ -52,6 +97,8 @@ mutable struct TimeStep{T}
5297
checkstep!(new{typeof(h)}(h,hmin,hmax,emin,emax,(emin+emax)/2,1,0))
5398
end
5499
end
100+
TimeStep(I::AbstractIntegrator) = TimeStep(I.tol)
101+
55102
function checkstep!(t)
56103
abs(t.h) < t.hmin && (t.h = copysign(t.hmin,t.h))
57104
abs(t.h) > t.hmax && (t.h = copysign(t.hmax,t.h))
@@ -133,9 +180,9 @@ initsteps(x0,t,tmax,f,m,B) = initsteps(init(x0),t,tmax,f,m,B)
133180
function initsteps(x0::Section,t,tmax,::Val{m}) where m
134181
tmin,f0 = base(x0),fiber(x0)
135182
n = Int(round((tmax-tmin)/t.h))+1
136-
t = m (0,1,3) ? (tmin:t.h:tmax) : Vector{typeof(t.h)}(undef,n)
137-
m (0,1,3) && (t[1] = tmin)
138-
x = Array{fibertype(fibertype(x0)),ndims(f0)+1}(undef,size(f0)...,m (0,1,3) ? length(t) : n)
183+
t = m ? (tmin:t.h:tmax) : Vector{typeof(t.h)}(undef,n)
184+
(!m) && (t[1] = tmin)
185+
x = Array{fibertype(fibertype(x0)),ndims(f0)+1}(undef,size(f0)...,m ? length(t) : n)
139186
assign!(x,1,fiber(f0))
140187
return TensorField(ndims(f0) > 0 ? base(f0)×t : t,x)
141188
end
@@ -216,77 +263,99 @@ end
216263
init(x0) = 0.0 x0
217264
init(x0::Section) = x0
218265

219-
odesolve(f,x0,tmax,tol,m,o) = odesolve(f,x0,tmax,tol,Val(m),Val(o))
266+
struct InitialCondition{F,X}
267+
f::F
268+
x0::X
269+
tmax::Float64
270+
end
271+
272+
InitialCondition(f,x0) = InitialCondition(f,x0,2π)
273+
274+
struct InitialValueSetup{F,X,I<:AbstractIntegrator}
275+
ic::InitialCondition{F,X}
276+
i::I
277+
end
278+
279+
InitialValueSetup(f,x0,tmax,tol,m,o=4) = InitialValueSetup(f,x0,tmax,tol,Val(m),Val(o))
280+
function InitialValueSetup(f,x0,tmax=2π,tol=15,M::Val{m}=Val(1),B::Val{o}=Val(4)) where {m,o}
281+
InitialValueSetup(InitialCondition(f,x0,tmax),AbstractIntegrator(tol,M,B))
282+
end
283+
284+
odesolve(ode::InitialValueSetup) = odesolve(ode.ic,ode.i)
285+
odesolve(f,x0,tmax,tol,m,o=4) = odesolve(f,x0,tmax,tol,Val(m),Val(o))
220286
function odesolve(f,x0,tmax=2π,tol=15,M::Val{m}=Val(1),B::Val{o}=Val(4)) where {m,o}
221-
t = TimeStep(2.0^-tol)
222-
if m == 0 # Improved Euler, Heun's Method
223-
x = initsteps(x0,t,tmax,M)
224-
for i 2:size(x)[end]
225-
assign!(x,i,heun(extract(x,i-1),f,t.h))
226-
end
227-
elseif m == 1 # Singlestep
228-
x = initsteps(x0,t,tmax,M)
229-
for i 2:size(x)[end]
230-
assign!(x,i,explicit(extract(x,i-1),f,t.h,B))
231-
end
232-
elseif m == 2 # Adaptive Singlestep
233-
x = initsteps(x0,t,tmax,M)
234-
while timeloop!(x,t,tmax)
235-
explicit!(x,f,t,B)
236-
end
237-
elseif m == 3 # Multistep
238-
x,fx = initsteps(x0,t,tmax,f,M,B)
239-
for i o+1:size(x)[end] # o+1 changed to o
240-
assign!(x,i,predictcorrect(x,f,fx,t,B))
241-
end
242-
else # Adaptive Multistep
243-
x,fx = initsteps(x0,t,tmax,f,M,B)
244-
while timeloop!(x,t,tmax,B) # o+1 fix??
245-
predictcorrect!(x,f,fx,t,B)
246-
end
287+
odesolve(InitialCondition(f,x0,tmax),AbstractIntegrator(tol,M,B))
288+
end
289+
function odesolve(ic::InitialCondition,I::EulerHeunIntegrator)
290+
t = TimeStep(I)
291+
x = initsteps(ic.x0,t,ic.tmax,Val(true))
292+
for i 2:size(x)[end]
293+
assign!(x,i,heun(extract(x,i-1),ic.f,t.h))
294+
end
295+
return x
296+
end
297+
function odesolve(ic::InitialCondition,I::ExplicitIntegrator{o}) where o
298+
t,B = TimeStep(I),Val(o)
299+
x = initsteps(ic.x0,t,ic.tmax,Val(true))
300+
for i 2:size(x)[end]
301+
assign!(x,i,explicit(extract(x,i-1),ic.f,t.h,B))
302+
end
303+
return x
304+
end
305+
function odesolve(ic::InitialCondition,I::ExplicitAdaptor{o}) where o
306+
t,B = TimeStep(I),Val(o)
307+
x = initsteps(ic.x0,t,ic.tmax,Val(false))
308+
while timeloop!(x,t,ic.tmax)
309+
explicit!(x,ic.f,t,B)
310+
end
311+
return resize(x)
312+
end
313+
function odesolve(ic::InitialCondition,I::MultistepIntegrator{o}) where o
314+
t,B = TimeStep(I),Val(o)
315+
x,fx = initsteps(ic.x0,t,ic.tmax,ic.f,Val(true),B)
316+
for i o+1:size(x)[end] # o+1 changed to o
317+
assign!(x,i,predictcorrect(x,ic.f,fx,t,B))
318+
end
319+
return x
320+
end
321+
function odesolve(ic::InitialCondition,I::MultistepAdaptor{o}) where o
322+
t,B = TimeStep(I),Val(o)
323+
x,fx = initsteps(ic.x0,t,ic.tmax,ic.f,Val(false),B)
324+
while timeloop!(x,t,ic.tmax,B) # o+1 fix??
325+
predictcorrect!(x,ic.f,fx,t,B)
247326
end
248327
return resize(x)
249328
end
250329

251330
#integrange
252331
#integadapt
253332

254-
odesolve2(f,x0,tmax,tol,m,o) = odesolve2(f,x0,tmax,tol,Val(m),Val(o))
333+
odesolve2(ode::InitialValueSetup) = odesolve2(ode.ic,ode.i)
334+
odesolve2(f,x0,tmax,tol,m,o=4) = odesolve2(f,x0,tmax,tol,Val(m),Val(o))
255335
function odesolve2(f,x0,tmax=2π,tol=15,M::Val{m}=Val(1),B::Val{o}=Val(4)) where {m,o}
256-
t = TimeStep(2.0^-tol)
257-
if m == 1 # Singlestep
258-
x = initsteps(x0,t,tmax,M)
259-
for i 2:length(x)
260-
assign!(x,i,explicit(extract(x,i-1),f,t.h,B))
261-
end
262-
elseif m == 2 # Adaptive Singlestep
263-
x = initsteps(x0,t,tmax,M)
264-
while timeloop!(x,t,tmax)
265-
explicit!(x,f,t,B)
266-
end
267-
elseif m == 3 # Multistep
268-
x,fx = initsteps2(x0,t,tmax,f,M,B)
269-
for i (isone(o) ? 2 : o):length(x) # o+1 changed to o
270-
assign!(x,i,predictcorrect2(x,f,fx,t,B))
271-
end
272-
else # Adaptive Multistep
273-
x,fx = initsteps(x0,t,tmax,f,M,B) # o+1 fix?
274-
while timeloop!(x,t,tmax,B)
275-
predictcorrect!(x,f,fx,t,B)
276-
end
336+
odesolve2(InitialCondition(f,x0,tmax),AbstractIntegrator(tol,M,B))
337+
end
338+
odesolve2(ic::InitialCondition,I::ExplicitIntegrator) = odesolve(ic,I)
339+
odesolve2(ic::InitialCondition,I::ExplicitAdaptor) = odesolve(ic,I)
340+
odesolve2(ic::InitialCondition,I::MultistepAdaptor) = odesolve(ic,I)
341+
function odesolve2(ic::InitialCondition,I::MultistepIntegrator{o}) where o
342+
t,B = TimeStep(I),Val(o)
343+
x,fx = initsteps2(ic.x0,t,ic.tmax,ic.f,Val(true),B)
344+
for i (isone(o) ? 2 : o):size(x)[end] # o+1 changed to o
345+
assign!(x,i,predictcorrect2(x,ic.f,fx,t,B))
277346
end
278-
return resize(x)
347+
return x
279348
end
280349

281350
function integrate(f::TensorField,x,tmax=2π,tol=15,M::Val{m}=Val(1),B::Val{o}=Val(4)) where {m,o}
282351
x0,t = init(x),TimeStep(2.0^-tol)
283352
if m == 0 # Improved Euler, Heun's Method
284-
x = initsteps(x0,t,tmax,M)
353+
x = initsteps(x0,t,tmax,Val(true))
285354
for i 2:length(x)
286355
assign!(x,i,heun(extract(x,i-1),f,t.h))
287356
end
288357
elseif m == 3 # Multistep
289-
x,fx = initsteps(x0,t,tmax,f,M,B)
358+
x,fx = initsteps(x0,t,tmax,f,Val(true),B)
290359
for i o+1:length(x)
291360
assign!(x,i,predictcorrect(x,f,fx,t,B))
292361
end
@@ -296,7 +365,9 @@ end
296365

297366
export geosolve
298367

299-
geosolve(Γ,x0,v0,tmax,tol,m,o) = geosolve(Γ,x0,v0,tmax,tol,Val(m),Val(o))
368+
geosolve(ode::InitialValueSetup) = getindex.(odesolve(ode),1)
369+
geosolve(ic::InitialCondition,i::AbstractIntegrator) = getindex.(odesolve(ic,i),1)
370+
geosolve(Γ,x0,v0,tmax,tol,m,o=4) = geosolve(Γ,x0,v0,tmax,tol,Val(m),Val(o))
300371
function geosolve(Γ,x0,v0,tmax=2π,tol=15,M::Val{m}=Val(1),B::Val{o}=Val(4)) where {m,o}
301372
getindex.(odesolve(geodesic(Γ),Chain(x0,v0),tmax,tol,M,B),1)
302373
end

0 commit comments

Comments
 (0)