8
8
p
9
9
y
10
10
yp
11
+ L
11
12
12
13
dt
13
14
kwargs
@@ -52,28 +53,18 @@ function SciMLBase.__init(prob::FDDEProblem, alg::DelayPECE; dt = 0.0, kwargs...
52
53
t0 = tspan[1 ]
53
54
tfinal = tspan[2 ]
54
55
T = eltype (u0)
55
- mesh = collect (Float64, t0 : dt : tfinal )
56
- size (mesh, 1 )
57
- yp = collect (Float64, t0 : dt : ( tfinal + dt ))
58
- N = length (t0 : dt : (tfinal + dt) )
59
- yp = _generate_similar_array (u0, N , u0)
60
- y = _generate_similar_array (u0, N - 1 , u0 )
61
- y[1 ] = ( length (u0) == 1 ) ? _generate_similar_array (u0, 1 , h (p, 0 )) : u0 # _generate_similar_array(u0, 1, h(p, 0))
62
-
63
- return DelayPECECache {iip, T} (prob, alg, mesh, u0, order[ 1 ] , τ, p, y, yp, dt, kwargs)
56
+ N = Int ( cld (tfinal - t0, dt) )
57
+ L = length ( collect ( - τ :dt : t0) )
58
+ mesh = collect (range (t0; stop = tfinal, length = N + 1 ))
59
+ yp = _generate_similar_array (u0, N + 1 , u0 )
60
+ y = _generate_similar_array (u0, L + N + 1 , u0)
61
+ y[L : - 1 : 1 ] . = ifelse (( length (u0) == 1 ), map (x -> [ h (p, x)], collect ( - τ :dt : t0)), map (x -> h (p, x), collect ( - τ :dt : (t0))) )
62
+ y[L + 1 ] = ifelse (( length (u0) == 1 ), [u0], u0) # _generate_similar_array(u0, 1, h(p, 0))
63
+
64
+ return DelayPECECache {iip, T} (prob, alg, mesh, u0, order, τ, p, y, yp, L , dt, kwargs)
64
65
end
65
66
66
- @inline function _generate_similar_array (u0, N, src)
67
- if N ≠ 1
68
- if length (u0) == 1
69
- return [similar ([src]) for i in 1 : N]
70
- else
71
- return [similar (src) for i in 1 : N]
72
- end
73
- else
74
- return [src]
75
- end
76
- end
67
+ @inline _generate_similar_array (u0, N, src) = ifelse (length (u0) == 1 , [[zero (u0)] for _ in 1 : N], [zero (src) for _ in 1 : N])
77
68
78
69
@inline function OrderWrapper (order, t)
79
70
if order isa Function
84
75
end
85
76
86
77
function SciMLBase. solve! (cache:: DelayPECECache{iip, T} ) where {iip, T}
87
- (; prob, alg, mesh, u0, order, p, dt) = cache
88
- maxn = length (mesh)
78
+ if length (cache. constant_lags) == 1
79
+ return solve_fdde_with_single_lag (cache)
80
+ else
81
+ return solve_fdde_with_multiple_lags (cache)
82
+ end
83
+ end
84
+
85
+ function solve_fdde_with_single_lag (cache:: DelayPECECache{iip, T} ) where {iip, T}
86
+ (; prob, alg, mesh, u0, order, L, p, dt) = cache
87
+ N = length (mesh)
89
88
l = length (u0)
90
- initial = (length (u0) == 1 ) ? _generate_similar_array (u0, 1 , prob. h (p, 0 )) : u0
91
- for n in 1 : (maxn - 1 )
92
- order = OrderWrapper (order, mesh[n + 1 ])
93
- cache. yp[n + 1 ] = zeros (T, l)
94
- for j in 1 : n
89
+ initial = ifelse (l == 1 , [u0], u0)
90
+ tmp = zeros (T, l)
91
+ for i in 0 : N- 2
92
+ order = OrderWrapper (order, mesh[i + 1 ])
93
+ # compute the yp part
94
+ for j in 0 : i
95
95
if iip
96
- tmp = zeros (length (cache. yp[1 ]))
97
- prob. f (tmp, cache. y[j], v (cache, j), p, mesh[j])
98
- cache. yp[n + 1 ] = cache. yp[n + 1 ] +
99
- generalized_binomials (j - 1 , n - 1 , order, dt) * tmp
96
+ prob. f (tmp, cache. y[L+ j+ 1 ], v (cache, j), p, mesh[j + 1 ])
97
+ cache. yp[i + 1 ] = cache. yp[i + 1 ] +
98
+ generalized_binomials (j, i, order, dt) * tmp
100
99
else
101
100
length (u0) == 1 ?
102
- (tmp = prob. f (cache. y[j ][1 ], v (cache, j)[1 ], p, mesh[j])) :
103
- (tmp = prob. f (cache. y[j ], v (cache, j), p, mesh[j]))
104
- @. cache. yp[n + 1 ] = cache. yp[n + 1 ] +
105
- generalized_binomials (j - 1 , n - 1 , order, dt) * tmp
101
+ (tmp = prob. f (cache. y[L + j + 1 ][1 ], v (cache, j)[1 ], p, mesh[j + 1 ])) :
102
+ (tmp = prob. f (cache. y[L + j + 1 ], v (cache, j), p, mesh[j+ 1 ]))
103
+ @. cache. yp[i + 1 ] = cache. yp[i + 1 ] +
104
+ generalized_binomials (j, i , order, dt) * tmp
106
105
end
107
106
end
108
- cache. yp[n + 1 ] = cache. yp[n + 1 ] / gamma (order) + initial
107
+ cache. yp[i + 1 ] = cache. yp[i + 1 ] / gamma (order) + initial
109
108
110
- cache. y[n + 1 ] = zeros (T, l)
111
-
112
- @fastmath @inbounds @simd for j in 1 : n
109
+ # compute the a part
110
+ for j in 0 : i
113
111
if iip
114
- tmp = zeros (T, length (cache. y[1 ]))
115
- prob. f (tmp, cache. y[j], v (cache, j), p, mesh[j])
116
- cache. y[n + 1 ] = cache. y[n + 1 ] + a (j - 1 , n - 1 , order, dt) * tmp
112
+ prob. f (tmp, cache. y[L + j + 1 ], v (cache, j), p, mesh[j+ 1 ])
113
+ cache. y[L + i + 2 ] += a (j, i, order, dt) * tmp
117
114
else
118
115
length (u0) == 1 ?
119
- (tmp = prob. f (cache. y[j ][1 ], v (cache, j)[1 ], p, mesh[j])) :
120
- (tmp = prob. f (cache. y[j ], v (cache, j), p, mesh[j]))
121
- @. cache. y[n + 1 ] = cache . y[n + 1 ] + a (j - 1 , n - 1 , order, dt) * tmp
116
+ (tmp = prob. f (cache. y[L + j + 1 ][1 ], v (cache, j)[1 ], p, mesh[j+ 1 ])) :
117
+ (tmp = prob. f (cache. y[L + j + 1 ], v (cache, j), p, mesh[j]))
118
+ @. cache. y[L + i + 2 ] += a (j, i , order, dt) * tmp
122
119
end
123
120
end
124
121
125
122
if iip
126
- tmp = zeros (T, l)
127
- prob. f (tmp, cache. yp[n + 1 ], v (cache, n + 1 ), p, mesh[n + 1 ])
128
- cache. y[n + 1 ] = cache. y[n + 1 ] / gamma (order) +
129
- dt^ order * tmp / gamma (order + 2 ) +
130
- initial
123
+ prob. f (tmp, cache. yp[i + 1 ], v (cache, i + 1 ), p, mesh[i + 2 ])
124
+ cache. y[L + i + 2 ] = cache. y[L + i + 2 ] / gamma (order) +
125
+ dt^ order * tmp / gamma (order + 2 ) + initial
131
126
else
132
127
length (u0) == 1 ?
133
- (tmp = prob. f (cache. yp[n + 1 ][1 ], v (cache, n + 1 )[1 ], p, mesh[n + 1 ])) :
134
- (tmp = prob. f (cache. yp[n + 1 ], v (cache, n + 1 ), p, mesh[n + 1 ]))
135
- @. cache. y[n + 1 ] = cache. y[n + 1 ] / gamma (order) +
136
- dt^ order * tmp / gamma (order + 2 ) +
137
- initial
128
+ (tmp = prob. f (cache. yp[i + 1 ][1 ], v (cache, i + 1 )[1 ], p, mesh[i + 2 ])) :
129
+ (tmp = prob. f (cache. yp[i + 1 ], v (cache, i + 1 ), p, mesh[i + 2 ]))
130
+ @. cache. y[L + i + 2 ] = cache. y[L + i + 2 ] / gamma (order) +
131
+ dt^ order * tmp / gamma (order + 2 ) + initial
138
132
end
139
133
end
140
134
141
- return DiffEqBase. build_solution (prob, alg, mesh, cache. y)
135
+ u = cache. y[L+ 1 : end ]
136
+
137
+ return DiffEqBase. build_solution (prob, alg, mesh, u)
142
138
end
143
139
144
140
function a (j:: I , n:: I , order, dt) where {I <: Integer }
145
- if j == n + 1
141
+ if j == n
146
142
result = 1
147
143
elseif j == 0
148
144
result = n^ (order + 1 ) - (n - order) * (n + 1 )^ order
@@ -153,11 +149,11 @@ function a(j::I, n::I, order, dt) where {I <: Integer}
153
149
end
154
150
155
151
function generalized_binomials (j, n, order, dt)
156
- @. dt^ order / order * ((n - j + 1 )^ order - (n - j)^ order)
152
+ @. dt^ order / order * ((n - j + 1 )^ order - (n - j )^ order)
157
153
end
158
154
159
155
function v (cache:: DelayPECECache{iip, T} , n) where {iip, T}
160
- (; prob, mesh, dt, constant_lags, p) = cache
156
+ (; prob, mesh, dt, constant_lags, L, p) = cache
161
157
τ = constant_lags
162
158
if typeof (τ) <: Function
163
159
m = floor .(Int, τ .(mesh) / dt)
@@ -172,26 +168,32 @@ function v(cache::DelayPECECache{iip, T}, n) where {iip, T}
172
168
end
173
169
end
174
170
else
175
- if τ >= (n - 1 ) * dt
176
- if length (prob. u0) == 1
177
- return [prob. h (p, (n - 1 ) * dt - τ)]
171
+ if isinteger (τ/ dt)# y-τ fall in grid point
172
+ # case when δ == 0
173
+ if τ/ dt < n
174
+ return cache. y[L + n - Int (τ/ dt) + 1 ]
178
175
else
179
- return prob. h (p, (n - 1 ) * dt - τ)
176
+ if length (prob. u0) == 1
177
+ return [prob. h (p, n * dt - τ)]
178
+ else
179
+ return prob. h (p, n * dt - τ)
180
+ end
180
181
end
181
182
else
182
183
m = floor (Int, τ / dt)
183
184
δ = m - τ / dt
185
+ # interpolate by the two nearest points
184
186
if m > 1
185
- return δ * cache. y[n - m + 2 ] + (1 - δ) * cache. y[n - m + 1 ]
186
- elseif m == 1
187
- return δ * cache. yp[n + 1 ] + (1 - δ) * cache. y[n ]
187
+ return δ * cache. y[n - m + L + 2 ] + (1 - δ) * cache. y[n - m + L + 1 ]
188
+ elseif m == 1 # h is larger than τ
189
+ return δ * cache. yp[n + 1 ] + (1 - δ) * cache. y[L + n + 1 ]
188
190
end
189
191
end
190
192
end
191
193
end
192
194
193
- function solve_fdde_with_multiple_lags (FDDE :: FDDEProblem , dt )
194
- (; f, h, order, constant_lags, p, tspan) = FDDE
195
+ function solve_fdde_with_multiple_lags (cache :: DelayPECECache )
196
+ (; f, h, order, constant_lags, p, tspan) = cache
195
197
τ = constant_lags[1 ]
196
198
mesh = collect (0 : dt: tspan[2 ])
197
199
maxn = length (mesh)
0 commit comments