-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathFDE_PI1_Im.m
410 lines (354 loc) · 14.6 KB
/
FDE_PI1_Im.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
function [t, y] = FDE_PI1_Im(alpha,f_fun,J_fun,t0,T,y0,h,param,tol,itmax)
% FDE_PI1_Im Solves on the interval [t0,T] an initial value problem for a
% for a system D^alpha y = f(t,y) of differential equations of
% fractional order alpha. Multi-order systems (MOS) are also
% possible, i.e. systems in which each equation has a different
% fractional order.
% The system or MOS of FDEs is solved by means of the implicit
% product-integration rule of rectangular type with convergence
% order equal to 1.
%
% Further information on this code are available in [1]; please, cite this
% code as [1] (see later on).
%
% -------------------------------------------------------------------------
% Description of input parameters
% -------------------------------------------------------------------------
% alpha : vector of the fractional orders alpha of each equation of the
% multi-order system of FDEs.
% f_fun : function handle that evaluates the right side f(t,y(t)) of
% the MOS of FDEs. f_fun(t,y) must return a vector function
% with the same number of entries as alpha. If necessary,
% f_fun(t,y,param) can have a vector of parameters.
% J_fun : function handle that evaluates the Jacobian of the right side
% f(t,y(t)) of the MOS of FDEs. J_fun must return a matrix
% function with the same number of rows and columns as alpha.
% If necessary, J_fun(t,y,param) can have a vector of
% parameters.
% t0, T : starting and final time of the interval of integration.
% y0 : vector (or matrix) of initial conditions with a number of
% rows equal to the size of the problem (hence to the number of
% entries of alpha or to the number of rows of the output of
% f_fun) and a number of columns equal to the smallest integer
% greater than max(alpha)
% h : step-size for integration. It must be real and positive
% param : vector of possible parameters for the evaluation of the
% right side f(t,y(t)) and of its Jacobian. This an optional
% parameter: it can be omitted or it is possible to use the an
% empty vector [] if the function f_fun(t,y) and its Jacobian
% do not have parameters.
% tol : tolerance for the solution of the internal nonlinear system
% of equations. This is an optional parameter and when not
% specified the defalut value 1.0e-6 is assumed.
% itmax : number of mximum iterations for the solution of the internal
% nonlinear system of equations. This is an optional parameter
% and when not specified the defalut value 100 is assumed.
%
% -------------------------------------------------------------------------
% Description of output parameters
% -------------------------------------------------------------------------
% t : vector of nodes on the interval [t0,T] in which the
% numerical solution is evaluated
% y : matrix with the values of the solution evaluated in t
%
% -------------------------------------------------------------------------
% Possible usages
% -------------------------------------------------------------------------
% [t, y] = FDE_PI1_Im(alpha,f_fun,J_fun,t0,T,y0,h)
% [t, y] = FDE_PI1_Im(alpha,f_fun,J_fun,t0,T,y0,h,param)
% [t, y] = FDE_PI1_Im(alpha,f_fun,J_fun,t0,T,y0,h,param,tol)
% [t, y] = FDE_PI1_Im(alpha,f_fun,J_fun,t0,T,y0,h,param,tol,itmax)
%
% -------------------------------------------------------------------------
% References and other information
% -------------------------------------------------------------------------
%
% [1] Garrappa R.: Numerical Solution of Fractional Differential
% Equations: a Survey and a Software Tutorial, Mathematics 2018, 6(2), 16
% doi: https://doi.org/10.3390/math6020016
% downloadable pdf: http://www.mdpi.com/2227-7390/6/2/16/pdf
%
% Revision: 1.1 - Date: November, 30 2017
%
% Please, report any problem or comment to :
% roberto dot garrappa at uniba dot it
%
% Copyright (c) 2017
%
% Author:
% Roberto Garrappa (University of Bari, Italy)
% roberto dot garrappa at uniba dot it
% Homepage: http://www.dm.uniba.it/Members/garrappa
%
% -------------------------------------------------------------------------
% Check inputs
if nargin < 10
itmax = 100 ;
if nargin < 9
tol = 1.0e-6 ;
if nargin < 8
param = [] ;
end
end
end
% Check order of the FDEs
alpha = alpha(:) ;
if any(alpha <= 0)
i_alpha_neg = find(alpha<=0) ;
error('MATLAB:NegativeOrder',...
['The order ALPHA of the FDE must be positive. The value ' ...
'ALPHA(%d) = %f can not be accepted.'], i_alpha_neg(1), alpha(i_alpha_neg(1)));
end
% Check the step--size of the method
if h <= 0
error('MATLAB:NegativeStepSize',...
['The step-size H for the method must be positive. The value ' ...
'H = %e can not be accepted.'], h);
end
% Check compatibility size of the problem with number of fractional orders
alpha_length = length(alpha) ;
problem_size = size(y0,1) ;
if alpha_length > 1
if problem_size ~= alpha_length
error('MATLAB:SizeNotCompatible', ...
['Size %d of the problem as obtained from initial conditions ' ...
'(i.e. the number of rows of Y0) not compatible with the ' ...
'number %d of fractional orders for multi-order systems. ' ...
], problem_size, alpha_length);
end
else
alpha = alpha*ones(problem_size,1) ;
alpha_length = problem_size ;
end
% Storage of initial conditions
ic.t0 = t0 ;
ic.y0 = y0 ;
ic.m_alpha = ceil(alpha) ;
for i = 1 : alpha_length
for j = 0 : ic.m_alpha(i)-1
ic.m_alpha_factorial(i,j+1) = factorial(j) ;
end
end
% Storage of information on the problem
Probl.ic = ic ;
Probl.f_fun = f_fun ;
Probl.J_fun = J_fun ;
Probl.problem_size = problem_size ;
Probl.param = param ;
Probl.alpha = alpha ;
Probl.alpha_length = alpha_length ;
% Check number of initial conditions
if size(y0,2) < max(ic.m_alpha)
error('MATLAB:NotEnoughInitialConditions', ...
['A not sufficient number of assigned initial conditions. ' ...
'Order ALPHA = %f requires %d initial conditions. '], ...
max(alpha),max(ic.m_alpha));
end
% Check compatibility size of the problem with size of the vector field
f_temp = f_vectorfield(t0,y0(:,1),Probl) ;
if Probl.problem_size ~= size(f_temp,1)
error('MATLAB:SizeNotCompatible', ...
['Size %d of the problem as obtained from initial conditions ' ...
'(i.e. the number of rows of Y0) not compatible with the ' ...
'size %d of the output of the vector field f_fun. ' ...
], Probl.problem_size,size(f_temp,1));
end
% Number of points in which to evaluate weights and solution
r = 16 ;
N = ceil((T-t0)/h) ;
Nr = ceil((N+1)/r)*r ;
Qr = ceil(log2(Nr/r)) - 1 ;
NNr = 2^(Qr+1)*r ;
% Preallocation of some variables
y = zeros(Probl.problem_size,N+1) ;
fy = zeros(Probl.problem_size,N+1) ;
zn = zeros(Probl.problem_size,NNr+1) ;
% Evaluation of coefficients of the PI rule
nvett = 0 : NNr+1 ;
bn = zeros(Probl.alpha_length,NNr+1) ;
for i_alpha = 1 : Probl.alpha_length
find_alpha = find(alpha(i_alpha)==alpha(1:i_alpha-1)) ;
if ~isempty(find_alpha)
bn(i_alpha,:) = bn(find_alpha(1),:) ;
%a0(i_alpha,:) = a0(find_alpha(1),:) ;
else
nalpha = nvett.^alpha(i_alpha) ;
%bn(i_alpha,:) = [ 1 , nalpha(2:end) - nalpha(1:end-1) ] ;
bn(i_alpha,:) = nalpha(2:end) - nalpha(1:end-1) ;
%a0(i_alpha,:) = [ 0 , nalpha1(1:end-2)-nalpha(2:end-1).*(nvett(2:end-1)-alpha(i_alpha)-1)] ;
end
end
PI.bn = bn ;
PI.halpha1 = h.^alpha./gamma(alpha+1) ;
PI.tol = tol ; PI.itmax = itmax ;
% Evaluation of FFT of coefficients of the PI rule
PI.r = r ;
if Qr >= 0
index_fft = zeros(2,Qr+1) ;
for l = 1 : Qr+1 % log2(NNr/r)
if l == 1
index_fft(1,l) = 1 ; index_fft(2,l) = r*2 ;
else
index_fft(1,l) = index_fft(2,l-1)+1 ; index_fft(2,l) = index_fft(2,l-1)+2^l*r;
end
end
bn_fft = zeros( Probl.alpha_length,index_fft(2,end)) ;
for l = 1 : Qr+1 % log2(NNr/r)
coef_end = 2^l*r ;
for i_alpha = 1 : Probl.alpha_length
find_alpha = find(alpha(i_alpha)==alpha(1:i_alpha-1)) ;
if ~isempty(find_alpha)
bn_fft(i_alpha,index_fft(1,l):index_fft(2,l)) = bn_fft(find_alpha(1),index_fft(1,l):index_fft(2,l)) ;
else
bn_fft(i_alpha,index_fft(1,l):index_fft(2,l)) = fft(PI.bn(i_alpha,1:coef_end),coef_end) ;
end
end
end
PI.bn_fft = bn_fft ; PI.index_fft = index_fft ;
end
% Initializing solution and process of computation
t = t0 + (0 : N)*h ;
y(:,1) = y0(:,1) ;
fy(:,1) = f_temp ;
[y, fy] = Triangolo(1, r-1, t, y, fy, zn, N, PI, Probl ) ;
% Main process of computation by means of the FFT algorithm
ff = zeros(1,2.^(Qr+2)) ; ff(1:2) = [0 2] ; card_ff = 2 ;
nx0 = 0 ; ny0 = 0 ;
for qr = 0 : Qr
L = 2^qr ;
[y, fy] = DisegnaBlocchi(L, ff, r, Nr, nx0+L*r, ny0, t, y, fy, ...
zn, N, PI, Probl ) ;
ff(1:2*card_ff) = [ff(1:card_ff) ff(1:card_ff)] ;
card_ff = 2*card_ff ;
ff(card_ff) = 4*L ;
end
% Evaluation solution in T when T is not in the mesh
if T < t(N+1)
c = (T - t(N))/h ;
t(N+1) = T ;
y(:,N+1) = (1-c)*y(:,N) + c*y(:,N+1) ;
end
t = t(1:N+1) ; y = y(:,1:N+1) ;
end
% =========================================================================
% =========================================================================
% r : dimension of the basic square or triangle
% L : factor of resizing of the squares
%%
function [y, fy] = DisegnaBlocchi(L, ff, r, Nr, nx0, ny0, t, y, fy, ...
zn, N , PI, Probl)
nxi = nx0 ; nxf = nx0 + L*r - 1 ;
nyi = ny0 ; nyf = ny0 + L*r - 1 ;
is = 1 ;
s_nxi(is) = nxi ; s_nxf(is) = nxf ; s_nyi(is) = nyi ; s_nyf(is) = nyf ;
i_triangolo = 0 ; stop = 0 ;
while ~stop
stop = nxi+r-1 == nx0+L*r-1 | (nxi+r-1>=Nr-1) ; % Ci si ferma quando il triangolo attuale finisce alla fine del quadrato
zn = Quadrato(nxi, nxf, nyi, nyf, fy, zn, N, PI, Probl) ;
[y, fy] = Triangolo(nxi, nxi+r-1, t, y, fy, zn, N, PI, Probl) ;
i_triangolo = i_triangolo + 1 ;
if ~stop
if nxi+r-1 == nxf % Il triangolo finisce dove finisce il quadrato -> si scende di livello
i_Delta = ff(i_triangolo) ;
Delta = i_Delta*r ;
nxi = s_nxf(is)+1 ; nxf = s_nxf(is) + Delta ;
nyi = s_nxf(is) - Delta +1; nyf = s_nxf(is) ;
s_nxi(is) = nxi ; s_nxf(is) = nxf ; s_nyi(is) = nyi ; s_nyf(is) = nyf ;
else % Il triangolo finisce prima del quadrato -> si fa un quadrato accanto
nxi = nxi + r ; nxf = nxi + r - 1 ; nyi = nyf + 1 ; nyf = nyf + r ;
is = is + 1 ;
s_nxi(is) = nxi ; s_nxf(is) = nxf ; s_nyi(is) = nyi ; s_nyf(is) = nyf ;
end
end
end
end
% =========================================================================
% =========================================================================
function zn = Quadrato(nxi, nxf, nyi, nyf, fy, zn, N, PI, Probl)
coef_end = nxf-nyi+1 ;
i_fft = log2(coef_end/PI.r) ;
funz_beg = nyi+1 ; funz_end = nyf+1 ;
Nnxf = min(N,nxf) ;
if nyi == 0 % Evaluation of the lowest square
vett_funz = [zeros(Probl.problem_size,1) , fy(:,funz_beg+1:funz_end) ] ;
else
vett_funz = fy(:,funz_beg:funz_end) ;
end
vett_funz_fft = fft(vett_funz,coef_end,2) ;
zzn = zeros(Probl.problem_size,coef_end) ;
for i = 1 : Probl.problem_size
i_alpha = min(Probl.alpha_length,i) ;
Z = PI.bn_fft(i_alpha,PI.index_fft(1,i_fft):PI.index_fft(2,i_fft)).*vett_funz_fft(i,:) ;
zzn(i,:) = real(ifft(Z,coef_end)) ;
end
zzn = zzn(:,nxf-nyf+1:end) ;
zn(:,nxi+1:Nnxf+1) = zn(:,nxi+1:Nnxf+1) + zzn(:,1:Nnxf-nxi+1) ;
end
% =========================================================================
% =========================================================================
function [y, fy] = Triangolo(nxi, nxf, t, y, fy, zn, N, PI, Probl)
for n = nxi : min(N,nxf)
St = StartingTerm(t(n+1),Probl.ic) ;
Phi = zeros(Probl.problem_size,1) ;
for j = nxi : n-1
Phi = Phi + PI.bn(1:Probl.alpha_length,n-j+1).*fy(:,j+1) ;
end
Phi_n = St + PI.halpha1.*(zn(:,n+1) + Phi) ;
yn0 = y(:,n) ; fn0 = f_vectorfield(t(n+1),yn0,Probl) ;
Jfn0 = Jf_vectorfield(t(n+1),yn0,Probl) ;
Gn0 = yn0 - PI.halpha1.*fn0 - Phi_n ;
stop = 0 ; it = 0 ;
while ~stop
JGn0 = eye(Probl.problem_size,Probl.problem_size) - diag(PI.halpha1)*Jfn0 ;
yn1 = yn0 - JGn0\Gn0 ;
fn1 = f_vectorfield(t(n+1),yn1,Probl) ;
Gn1 = yn1 - PI.halpha1.*fn1 - Phi_n ;
it = it + 1 ;
stop = norm(yn1-yn0,inf) < PI.tol | norm(Gn1,inf) < PI.tol;
if it > PI.itmax && ~stop
warning('MATLAB:NonConvegence',...
strcat('Internal iterations do not convergence to the ', ...
' tolerance %e in %d iterations. Try with a larger tolarence ',...
' or a bigger number of max iterations'),PI.tol,PI.itmax) ;
stop = 1 ;
end
yn0 = yn1 ; Gn0 = Gn1 ;
if ~stop
Jfn0 = Jf_vectorfield(t(n+1),yn0,Probl) ;
end
y(:,n+1) = yn1 ;
fy(:,n+1) = fn1 ;
end
end
end
% =========================================================================
% =========================================================================
function f = f_vectorfield(t,y,Probl)
if isempty(Probl.param)
f = feval(Probl.f_fun,t,y) ;
else
f = feval(Probl.f_fun,t,y,Probl.param) ;
end
end
% =========================================================================
% =========================================================================
function f = Jf_vectorfield(t,y,Probl)
if isempty(Probl.param)
f = feval(Probl.J_fun,t,y) ;
else
f = feval(Probl.J_fun,t,y,Probl.param) ;
end
end
% =========================================================================
% =========================================================================
function ys = StartingTerm(t,ic)
ys = zeros(size(ic.y0,1),1) ;
for k = 1 : max(ic.m_alpha)
if length(ic.m_alpha) == 1
ys = ys + (t-ic.t0)^(k-1)/ic.m_alpha_factorial(k)*ic.y0(:,k) ;
else
i_alpha = find(k<=ic.m_alpha) ;
ys(i_alpha,1) = ys(i_alpha,1) + (t-ic.t0)^(k-1)*ic.y0(i_alpha,k)./ic.m_alpha_factorial(i_alpha,k) ;
end
end
end