-
Notifications
You must be signed in to change notification settings - Fork 1
/
step_RMIS_MIS.m
180 lines (158 loc) · 6.46 KB
/
step_RMIS_MIS.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
function [Y,Yerr,m,hf] = step_RMIS_MIS(fs,ff,Jf,t0,Y0,Bo,Bi,hs,hf,rtol,atol)
% usage: [Y,Yerr,m,hf] = step_RMIS_MIS(fs,ff,Jf,t0,Y0,Bo,Bi,hs,hf,rtol,atol)
%
% This routine performs a single step of the relaxed multirate
% infinitesimal step (RMIS) method for the vector-valued ODE problem
% y' = fs(t,Y) + ff(t,Y), t >= t0, y in R^n,
% Y0 = [y1(t0), y2(t0), ..., yn(t0)]'.
% We perform the solve using a variation of the approach used for
% MIS methods by Knoth & Wolke (1998), i.e., we do NOT consider the
% problem in full GARK form. We do this to compute both an MIS and
% an RMIS solution, with the difference constituting the temporal
% error estimate.
%
% Inputs:
% fs = function handle for (slow) ODE RHS
% ff = function handle for (fast) ODE RHS
% Jf = function handle for Jacobian of ff (only required if an
% implicit inner method is supplied)
% t0 = value of independent variable at start of step
% Y0 = solution vector at start of step (column vector of length n)
% Bo = ERK Butcher table for 'outer' (slow) method
% Bo = [co Ao;
% qo bo;
% po do ]
% Here, co is a vector of stage time fractions (so-by-1),
% Ao is a matrix of Butcher coefficients (so-by-so),
% qo is an integer denoting the method order of accuracy
% bo is a vector of solution weights (1-by-so),
% po is an integer denoting the embedding order of accuracy,
% do is a vector of embedding weights (1-by-so),
% The [po, do] row is optional, and is unused in this
% routine. Also, the qo value is unused here.
% Note: the MIS method assumes that the outer method stage
% times are sorted, i.e. co(i+1) > co(i) for all i.
% Bi = Butcher table for a single step of an 'inner' (fast) method
% (can be ERK, DIRK or IRK)
% Bi = [ci Ai;
% qi bi;
% pi di ]
% All components have the same role as with Bi; we
% assume that Bi encodes a method with si stages
% hs = step size to use for slow time scale
% hf = initial step size to use for fast time scale
% rtol = desired relative error of solution at the fast scale (scalar)
% atol = desired absolute error of solution at the fast scale (vector or scalar)
%
% Outputs:
% Y = updated RMIS solution, [y1(t0+hs), y2(t0+hs), ..., yn(t0+hs)].
% Yerr = multirate temporal error estimate.
% m = actual number of substeps used for inner method.
% hf = final step size used at fast time scale
%
% Daniel R. Reynolds
% Department of Mathematics
% Southern Methodist University
% July 2018
% All Rights Reserved
% dummy stability function, tolerances
estab = @(t,y) inf;
% extract ERK method information from Bo, and ensure that it is legal
[Brows, Bcols] = size(Bo);
so = Bcols - 1; % number of stages
co = Bo(1:so,1); % stage time fraction array
bo = (Bo(so+1,2:so+1))'; % solution weights (convert to column)
Ao = Bo(1:so,2:so+1); % ERK coefficients
if (max(max(abs(triu(Ao)))) > 0)
error('Error: Bo does not specify an explicit RK method table')
end
% extract RK method information from Bi
[Brows, Bcols] = size(Bi);
si = Bcols - 1; % number of stages
ci = Bi(1:si,1); % stage time fraction array
bi = (Bi(si+1,2:si+1))'; % solution weights (convert to column)
Ai = Bi(1:si,2:si+1); % RK coefficients
innerRK = 0;
if (max(max(abs(triu(Ai)))) > 0) % implicit components exist
innerRK = 1;
if (max(max(abs(triu(Ai,1)))) > 0) % method is IRK
innerRK = 2;
end
end
% initialize outputs
m = 0;
n = length(Y0);
Y = reshape(Y0,n,1);
% initialize temporary variables
Fs = zeros(n,so);
fscale = zeros(so,1);
Ys = Y;
% first outer stage
Fs(:,1) = fs(t0,Y);
tcur = t0;
% add contributions from first outer stage to overall solution.
% Note: since inner method has explicit first stage, then its
% contribution to overall solution may be obtained by evaluating
% fast RHS at the same time as the slow
Y = Y + hs*bo(1)*(Fs(:,1) + ff(t0,Y));
% iterate over remaining outer stages
for i=2:so
% determine 'inner' ODE for this stage
% RHS function
for j=1:i-1
fscale(j) = (Ao(i,j)-Ao(i-1,j))/(co(i)-co(i-1));
end
fi = @(t,y) ff(t,y) + Fs*fscale;
% time interval
tspan = [tcur, tcur + (co(i)-co(i-1))*hs];
% step size bounds for fast scale
hf_max = (co(i)-co(i-1))*hs;
hf_min = hf_max * 1e-5;
% call inner RK method solver to perform substepping
if (innerRK == 2) % IRK inner method
[tvals, V, mi, ~, hf] = solve_IRK(fi, Jf, tspan, Ys, Bi, rtol, atol, hf_min, hf_max, hf);
elseif (innerRK == 1) % DIRK inner method
[tvals, V, mi, ~, hf] = solve_DIRK(fi, Jf, tspan, Ys, Bi, rtol, atol, hf_min, hf_max, hf);
else % ERK inner method
[tvals, V, mi, hf] = solve_ERK(fi, estab, tspan, Ys, Bi, rtol, atol, hf_min, hf_max, hf);
end
m = m + mi;
% update slow 'solution' as result from fast solve
Ys = V(:,end);
tcur = t0 + co(i)*hs;
Fs(:,i) = fs(tcur,Ys);
% update overall solution; note that since inner method has
% explicit first stage, then its contribution to overall
% solution may be obtained by evaluating fast RHS at the same
% time as the slow
Y = Y + hs*bo(i)*(Fs(:,i) + ff(tcur,Ys));
end
% all slow stages completed, if any of the time interval remains,
% finish that off here
if (co(so) < 1)
% determine 'inner' ODE for this stage
% RHS function
for j=1:so
fscale(j) = (bo(j)-Ao(so,j))/(1-co(so));
end
fi = @(t,y) ff(t,y) + Fs*fscale;
% time interval
tspan = [tcur, t0+hs];
% num internal time steps
ni = ceil((1-co(so))*hs/hf);
% step size
hf = (1-co(so))*hs/ni;
% call inner RK method solver to perform substepping
if (innerRK == 2) % IRK inner method
[tvals, V, mi, ~, hf] = solve_IRK(fi, Jf, tspan, Ys, Bi, rtol, atol, hf_min, hf_max, hf);
elseif (innerRK == 1) % DIRK inner method
[tvals, V, mi, ~, hf] = solve_DIRK(fi, Jf, tspan, Ys, Bi, rtol, atol, hf_min, hf_max, hf);
else % ERK inner method
[tvals, V, mi, hf] = solve_ERK(fi, estab, tspan, Ys, Bi, rtol, atol, hf_min, hf_max, hf);
end
m = m + mi;
% update slow 'solution' as result from fast solve
Ys = V(:,end);
end
Yerr = Y-Ys;
% end of function