Skip to content

Commit 1cb79cd

Browse files
Merge pull request #39 from devmotion/dde
Add DDETST problems and restructure existing DDE problems
2 parents c83079a + a788e51 commit 1cb79cd

File tree

6 files changed

+1596
-669
lines changed

6 files changed

+1596
-669
lines changed

src/DiffEqProblemLibrary.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ end # module
1919
module DDEProblemLibrary
2020
function importddeproblems()
2121
@isdefined(prob_dde_1delay) ||
22-
include(joinpath(@__DIR__, "dde_premade_problems.jl"));
22+
include(joinpath(@__DIR__, "dde/dde_premade_problems.jl"));
2323
nothing
2424
end
2525
end # module

src/dde/constant_delays.jl

Lines changed: 358 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,358 @@
1+
# Helper function for changing initial value and time type of the following DDEs
2+
3+
"""
4+
remake_dde_constant_u0_tType(prob::DDEProblem, u₀, tType)
5+
6+
Create a new delay differential problem by replacing the initial state of problem `prob`
7+
with `u0` and setting the type of time `t` to `tType`.
8+
9+
This function makes special assumptions about the structure of `prob` and is intended to be
10+
used for all problems of name `prob_dde_constant_*` in `DDEProblemLibrary`. The functions of
11+
these delay differential equation problems with constant delays are purposefully
12+
implemented such that they work for arbitrary types of state `u` and time `t`, and hence in
13+
particular for number types with units. The element type of `u` is saved as parameter `p` to
14+
ensure that the return type of the history functions is correct (which are functions of `p`
15+
but not of `u`).
16+
"""
17+
function remake_dde_constant_u0_tType(prob::DDEProblem, u₀, tType)
18+
remake(prob; u0 = u₀, tspan = tType.(prob.tspan), p = eltype(u₀),
19+
constant_lags = tType.(prob.constant_lags))
20+
end
21+
22+
# Single constant delay
23+
24+
## Short time span
25+
26+
### In-place function
27+
28+
@doc raw"""
29+
prob_dde_constant_1delay_ip
30+
31+
Delay differential equation
32+
33+
```math
34+
u'(t) = -u(t - 1)
35+
```
36+
37+
for ``t \in [0, 1]`` with history function ``\phi(t) = 0`` if ``t < 0`` and ``\phi(0) = 1``.
38+
39+
# Solution
40+
41+
The analytical solution for ``t \in [0, 10]`` can be obtained by the method of steps and
42+
is provided in this implementation.
43+
"""
44+
const prob_dde_constant_1delay_ip = let
45+
function f(du, u, h, p, t)
46+
e = oneunit(t)
47+
du[1] = - h(p, t - e; idxs = 1) * inv(e)
48+
49+
nothing
50+
end
51+
52+
# history function of the first component
53+
function h(p, t; idxs = 1)
54+
idxs == 1 || error("history function is only implemented for the first component")
55+
t zero(t) || error("history function is only implemented for t ≤ 0")
56+
57+
p === nothing ? zero(t) : zero(p)
58+
end
59+
60+
# only valid for specific history function
61+
function f_analytic(u₀, p, t)
62+
z = t * inv(oneunit(t))
63+
0 z 10 || error("analytical solution is only implemented for t ∈ [0, 10]")
64+
65+
if z < 1
66+
copy(u₀)
67+
else
68+
if z < 2
69+
c = @evalpoly(z, 2, -1)
70+
elseif z < 3
71+
c = @evalpoly(z, 4, -3, 1//2)
72+
elseif z < 4
73+
c = @evalpoly(z, 17//2, -15//2, 2, -1//6)
74+
elseif z < 5
75+
c = @evalpoly(z, 115//6, -109//6, 6, -5//6, 1//24)
76+
elseif z < 6
77+
c = @evalpoly(z, 1085//24, -1061//24, 197//12, -35//12, 1//4, -1//120)
78+
elseif z < 7
79+
c = @evalpoly(z, 13201//120, -13081//120, 521//12, -107//12, 1, -7//120, 1//720)
80+
elseif z < 8
81+
c = @evalpoly(z, 39371//144, -39227//144, 27227//240, -3685//144, 487//144,
82+
-21//80, 1//90, -1//5040)
83+
elseif z < 9
84+
c = @evalpoly(z, 1158379//1680, -1156699//1680, 212753//720, -51193//720,
85+
1511//144, -701//720, 1//18, -1//560, 1//40320)
86+
else
87+
c = @evalpoly(z, 23615939//13440, -23602499//13440, 7761511//10080,
88+
-279533//1440, 89269//2880, -1873//576, 323//1440, -11//1120,
89+
1//4032, -1//362880)
90+
end
91+
92+
c .* u₀
93+
end
94+
end
95+
96+
DDEProblem(DDEFunction(f, analytic=f_analytic), [1.0], h, (0.0, 10.0), typeof(1.0);
97+
constant_lags = [1])
98+
end
99+
100+
### Out-of-place function
101+
102+
"""
103+
prob_dde_constant_1delay_oop
104+
105+
Same delay differential equation as [`prob_dde_constant_1delay_ip`](@ref), but purposefully
106+
implemented with an out-of-place function.
107+
"""
108+
const prob_dde_constant_1delay_oop = let
109+
function f(u, h, p, t)
110+
e = oneunit(t)
111+
.- h(p, t - e) .* inv(e)
112+
end
113+
114+
# vectorized history function
115+
function h(p, t)
116+
t zero(t) || error("history function is only implemented for t ≤ 0")
117+
118+
p === nothing ? [zero(t)] : [zero(p)]
119+
end
120+
121+
DDEProblem(DDEFunction(f, analytic=prob_dde_constant_1delay_ip.f.analytic), [1.0], h,
122+
(0.0, 10.0), typeof(1.0); constant_lags = [1])
123+
end
124+
125+
### Scalar function
126+
127+
"""
128+
prob_dde_constant_1delay_scalar
129+
130+
Same delay differential equation as [`prob_dde_constant_1delay_ip`](@ref), but purposefully
131+
implemented with a scalar function.
132+
"""
133+
const prob_dde_constant_1delay_scalar = let
134+
# scalar history function
135+
function h(p, t)
136+
t zero(t) || error("history function is only implemented for t ≤ 0")
137+
138+
p === nothing ? zero(t) : zero(p)
139+
end
140+
141+
DDEProblem(prob_dde_constant_1delay_oop.f, 1.0, h, (0.0, 10.0), typeof(1.0);
142+
constant_lags = [1])
143+
end
144+
145+
## Long time span
146+
147+
### In-place function
148+
149+
@doc raw"""
150+
prob_dde_constant_1delay_long_ip
151+
152+
Delay differential equation
153+
154+
```math
155+
u'(t) = u(t) - u(t - 1/5)
156+
```
157+
158+
for ``t \in [0, 100]`` with history function ``\phi(t) = 0`` if ``t < 0`` and
159+
``\phi(0) = 1``.
160+
"""
161+
const prob_dde_constant_1delay_long_ip = let
162+
function f(du, u, h, p, t)
163+
T = typeof(t)
164+
du[1] = (u[1] - h(p, t - T(1/5); idxs = 1)) * inv(oneunit(t))
165+
166+
nothing
167+
end
168+
169+
DDEProblem(f, [1.0], prob_dde_constant_1delay_ip.h, (0.0, 100.0), typeof(1.0);
170+
constant_lags = [1/5])
171+
end
172+
173+
### Out-of-place function
174+
175+
"""
176+
prob_dde_constant_1delay_long_oop
177+
178+
Same delay differential equation as [`prob_dde_constant_1delay_long_ip`](@ref), but
179+
purposefully implemented with an out-of-place function.
180+
"""
181+
const prob_dde_constant_1delay_long_oop = let
182+
function f(u, h, p, t)
183+
T = typeof(t)
184+
(u .- h(p, t - T(1/5))) .* inv(oneunit(t))
185+
end
186+
187+
DDEProblem(f, [1.0], prob_dde_constant_1delay_oop.h, (0.0, 100.0), typeof(1.0);
188+
constant_lags = [1/5])
189+
end
190+
191+
### Scalar function
192+
193+
"""
194+
prob_dde_constant_1delay_long_scalar
195+
196+
Same delay differential equation as [`prob_dde_constant_1delay_long_ip`](@ref), but
197+
purposefully implemented with a scalar function.
198+
"""
199+
const prob_dde_constant_1delay_long_scalar =
200+
DDEProblem(prob_dde_constant_1delay_long_oop.f, 1.0, prob_dde_constant_1delay_scalar.h,
201+
(0.0, 100.0), typeof(1.0); constant_lags = [1/5])
202+
203+
# Two constant delays
204+
205+
## Short time span
206+
207+
### In-place function
208+
209+
@doc raw"""
210+
prob_dde_constant_2delays_ip
211+
212+
Delay differential equation
213+
214+
```math
215+
u'(t) = -u(t - 1/3) - u(t - 1/5)
216+
```
217+
218+
for ``t \in [0, 1]`` with history function ``\phi(t) = 0`` if ``t < 0`` and ``\phi(0) = 1``.
219+
220+
# Solution
221+
222+
The analytical solution for ``t \in [0, 10]`` can be obtained by the method of steps and
223+
is provided in this implementation.
224+
"""
225+
const prob_dde_constant_2delays_ip = let
226+
function f(du, u, h, p, t)
227+
T = typeof(t)
228+
du[1] = - (h(p, t - T(1/3); idxs = 1) + h(p, t - T(1/5); idxs = 1)) * inv(oneunit(t))
229+
230+
nothing
231+
end
232+
233+
# only valid for specific history function
234+
function f_analytic(u₀, p, t)
235+
z = t * inv(oneunit(t))
236+
0 z 1 || error("analytical solution is only implemented for t ∈ [0, 1]")
237+
238+
if z < 1/5
239+
copy(u₀)
240+
else
241+
if z < 1/3
242+
c = @evalpoly(z, 6//5, -1)
243+
elseif z < 2/5
244+
c = @evalpoly(z, 23//15, -2)
245+
elseif z < 8/15
246+
c = @evalpoly(z, 121//75, -12//5, 1//2)
247+
elseif z < 3/5
248+
c = @evalpoly(z, 427//225, -52//15, 3//2)
249+
elseif z < 2/3
250+
c = @evalpoly(z, 4351//2250, -547//150, 9//5, -1//6)
251+
elseif z < 11/15
252+
c = @evalpoly(z, 539//250, -647//150, 23//10, -1//6)
253+
elseif z < 4/5
254+
c = @evalpoly(z, 7942//3375, -128//25, 17//5, -2//3)
255+
elseif z < 13/15
256+
c = @evalpoly(z, 39998//16875, -1952//375, 89//25, -4//5, 1//24)
257+
elseif z < 14/15
258+
c = @evalpoly(z, 10109//3750, -1583//250, 243//50, -13//10, 1//24)
259+
else
260+
c = @evalpoly(z, 171449//60750, -139199//20250, 2579//450, -173//90, 5//24)
261+
end
262+
263+
c .* u₀
264+
end
265+
end
266+
267+
DDEProblem(DDEFunction(f, analytic = f_analytic), [1.0], prob_dde_constant_1delay_ip.h,
268+
(0.0, 1.0), typeof(1.0); constant_lags = [1/3, 1/5])
269+
end
270+
271+
### Out-of-place function
272+
273+
"""
274+
prob_dde_constant_2delays_oop
275+
276+
Same delay differential equation as [`prob_dde_constant_2delays_ip`](@ref), but purposefully
277+
implemented with an out-of-place function.
278+
"""
279+
const prob_dde_constant_2delays_oop = let
280+
function f(u, h, p, t)
281+
T = typeof(t)
282+
.- (h(p, t - T(1/3)) .+ h(p, t - T(1/5))) .* inv(oneunit(t))
283+
end
284+
285+
DDEProblem(DDEFunction(f, analytic = prob_dde_constant_2delays_ip.f.analytic), [1.0],
286+
prob_dde_constant_1delay_oop.h, (0.0, 1.0), typeof(1.0);
287+
constant_lags = [1/3, 1/5])
288+
end
289+
290+
### Scalar function
291+
292+
"""
293+
prob_dde_constant_2delays_scalar
294+
295+
Same delay differential equation as [`prob_dde_constant_2delays_ip`](@ref), but purposefully
296+
implemented with a scalar function.
297+
"""
298+
const prob_dde_constant_2delays_scalar =
299+
DDEProblem(prob_dde_constant_2delays_oop.f, 1.0, prob_dde_constant_1delay_scalar.h,
300+
(0.0, 1.0), typeof(1.0); constant_lags = [1/3, 1/5])
301+
302+
## Long time span
303+
304+
### In-place function
305+
306+
@doc raw"""
307+
prob_dde_constant_2delays_long_ip
308+
309+
Delay differential equation
310+
311+
```math
312+
u'(t) = - u(t - 1/3) - u(t - 1/5)
313+
```
314+
315+
for ``t \in [0, 100]`` with history function ``\phi(t) = 0`` if ``t < 0`` and
316+
``\phi(0) = 1``.
317+
"""
318+
const prob_dde_constant_2delays_long_ip = let
319+
function f(du, u, h, p, t)
320+
T = typeof(t)
321+
du[1] = - (h(p, t - T(1/3); idxs = 1) + h(p, t - T(1/5); idxs = 1)) * inv(oneunit(t))
322+
323+
nothing
324+
end
325+
326+
DDEProblem(f, [1.0], prob_dde_constant_1delay_ip.h, (0.0, 100.0), typeof(1.0);
327+
constant_lags = [1/3, 1/5])
328+
end
329+
330+
### Not in-place function
331+
332+
"""
333+
prob_dde_constant_2delays_long_oop
334+
335+
Same delay differential equation as [`prob_dde_constant_2delays_long_ip`](@ref), but
336+
purposefully implemented with an out-of-place function.
337+
"""
338+
const prob_dde_constant_2delays_long_oop = let
339+
function f(u, h, p, t)
340+
T = typeof(t)
341+
.- (h(p, t - T(1/3)) .+ h(p, t - T(1/5))) .* inv(oneunit(t))
342+
end
343+
344+
DDEProblem(f, [1.0], prob_dde_constant_1delay_oop.h, (0.0, 100.0), typeof(1.0);
345+
constant_lags = [1/3, 1/5])
346+
end
347+
348+
#### Scalar function
349+
350+
"""
351+
prob_dde_constant_2delays_long_scalar
352+
353+
Same delay differential equation as [`prob_dde_constant_2delays_long_ip`](@ref), but
354+
purposefully implemented with a scalar function.
355+
"""
356+
const prob_dde_constant_2delays_long_scalar =
357+
DDEProblem(prob_dde_constant_2delays_long_oop.f, 1.0, prob_dde_constant_1delay_scalar.h,
358+
(0.0, 100.0), typeof(1.0); constant_lags = [1/3, 1/5])

0 commit comments

Comments
 (0)