-
Notifications
You must be signed in to change notification settings - Fork 1
/
step_RMIS.m
161 lines (143 loc) · 5.81 KB
/
step_RMIS.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
function [Y,m] = step_RMIS(fs,ff,Jf,t0,Y0,Bo,Bi,hs,hf)
% usage: [Y,m] = step_RMIS(fs,ff,Jf,t0,Y0,Bo,Bi,hs,hf)
%
% 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.
%
% 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 RMIS method assumes that the outer method stage
% times are sorted, i.e.
% 0 <= co(1) <= co(2) <= ... <= co(so) <= 1
% 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 = desired step size to use for fast time scale,
% hf <= hs*min_{i}(co(i+1)-co(i))
% Note: this is only a target step size; in fact we
% will determine each substepping interval and find
% hinner <= hi such that we take an integer number of
% steps to subcycle up to each outer stage time.
%
% Outputs:
% Y = [y1(t0+hs), y2(t0+hs), ..., yn(t0+hs)].
% m = actual number of substeps used for inner method.
%
% Daniel R. Reynolds
% Department of Mathematics
% Southern Methodist University
% July 2018
% All Rights Reserved
% dummy stability function, tolerances
estab = @(t,y) inf;
rtol = 1e20;
atol = 1e20;
% 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
Delta_co = co(2:so)-co(1:so-1);
if ( (co(1) < 0) || (min(Delta_co) < 0) || (co(so)>1))
error('Error: Bo does not satisfy sorted stage time reqirements')
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 whether this stage involves fast evolution
if (Delta_co(i-1) > 0)
% determine 'inner' ODE for this stage
% RHS function
for j=1:i-1
fscale(j) = (Ao(i,j)-Ao(i-1,j))/Delta_co(i-1);
end
fi = @(t,y) ff(t,y) + Fs*fscale;
% time interval
tspan = [tcur, tcur + Delta_co(i-1)*hs];
% num internal time steps
ni = ceil(Delta_co(i-1)*hs/hf);
% step size
hi = Delta_co(i-1)*hs/ni;
% call inner RK method solver to perform substepping
if (innerRK == 2) % IRK inner method
[tvals, V, mi, ~, ~] = solve_IRK(fi, Jf, tspan, Ys, Bi, rtol, atol, hi, hi, hi);
elseif (innerRK == 1) % DIRK inner method
[tvals, V, mi, ~, ~] = solve_DIRK(fi, Jf, tspan, Ys, Bi, rtol, atol, hi, hi, hi);
else % ERK inner method
[tvals, V, mi, ~] = solve_ERK(fi, estab, tspan, Ys, Bi, rtol, atol, hi, hi, hi);
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));
% or if this just requires a simple ERK update
else
%--- I'm not sure what goes here ---%
end
end
% end of function