rbmatlab  1.16.09
 All Classes Namespaces Files Functions Variables Modules Pages
eop_fd_operators.m
Go to the documentation of this file.
1 function [L_I, L_E, b, L_I_adj, L_E_adj] = eop_fd_operators(model, model_data)
2 %[L_I, L_E, b, L_I_adj, L_E_adj] = eop_fd_operators(model, model_data)
3 %
4 % function which computes either L_I, L_E and b the components of the
5 % linear evolution scheme or L_I_adj and L_E_adj the components of the
6 % corresponding dual problem (controlled via model.want_dual).
7 % Supports affine decomposition via model.decomp_mode
8 %
9 % decomp_mode: operation mode of the function
10 % - 0='complete' (default): no parameter dependence or decomposition is
11 % performed.
12 % - 1='components': For each output argument a cell array of output
13 % arguments is returned representing the q-th component
14 % independent of the parameters given in mu_names
15 % - 2='coefficients': For each output argument a cell array of output
16 % arguments is returned representing the q-th coefficient
17 % dependent of the parameters given in mu_names
18 %
19 % the construction of L_I follows a 9-point-star described in my diploma
20 % thesis (chapter 4.2)
21 
22 % Dominik Garmatter 02.04 2012
23 
24 L_I = [];
25 L_E = [];
26 b = [];
27 L_I_adj = [];
28 L_E_adj = [];
29 
30 if ~isfield(model, 'decomp_mode')
31  model.decomp_mode = 0;
32 end
33 if ~isfield(model, 'want_dual')
34  model.want_dual = 0;
35 end
36 
37 decomp_mode = model.decomp_mode;
38 
39 if decomp_mode == 0 % no affine decomposition
40 k = model_data.grid.nvertices; % k = number of grid points
41 
42 % building the parametermatrix, which is used later for L_I and L_I_adj
43 XI = [model.sigma1*model.sigma1,...
44  2*model.rho/(1+model.rho*model.rho)*model.sigma1*model.sigma2;...
45  2*model.rho/(1+model.rho*model.rho)*model.sigma1*model.sigma2,...
46  model.sigma2*model.sigma2];
47 
48 % L_I always has the form L_I = Id + \bar{L_I}. This also contains the
49 % dirichlet boundary values.
50 L_I_basic = speye(k);
51 
52 % NOTE: this version using spalloc is still sufficiently fast!
53 
54 % build the entrys of the lower boundary (i.e. S2 = 0)
55 L_I_S1bound = spalloc(k,k,model.N1*9);
56  for m = 2 : model.N1-1
57  L_I_S1bound(m,m-1) = - model.deltaT*XI(1,1)*model_data.grid.X(m)*model_data.grid.X(m) / (2*model.h1*model.h1) + model.deltaT*model_data.grid.X(m)*model.r / (2*model.h1); % W of the '3-point-star' at the S2 = 0 boundary
58  L_I_S1bound(m,m) = model.deltaT*XI(1,1)*model_data.grid.X(m)*model_data.grid.X(m) / (model.h1*model.h1) + model.deltaT*model.r; % Z of the '3-point-star' at the S2 = 0 boundary
59  L_I_S1bound(m,m+1) = - model.deltaT*XI(1,1)*model_data.grid.X(m)*model_data.grid.X(m) / (2*model.h1*model.h1) - model.deltaT*model_data.grid.X(m)*model.r / (2*model.h1); % O of the '3-point-star' at the S2 = 0 boundary
60  end
61 
62 % build the entrys of the left boundary (i.e. S1 = 0)
63 L_I_S2bound = spalloc(k,k,model.N2*9);
64  for n = 1 : model.N2-2
65  L_I_S2bound(n*model.N1+1,(n-1)*model.N1+1) = - model.deltaT*XI(2,2)*model_data.grid.Y(n*model.N1+1)*model_data.grid.Y(n*model.N1+1) / (2*model.h2*model.h2) + model.deltaT*model_data.grid.Y(n*model.N1+1)*model.r / (2*model.h2); % S of the '3-point-star' at the S1 = 0 boundary
66  L_I_S2bound(n*model.N1+1, n*model.N1+1) = model.deltaT*XI(2,2)*model_data.grid.Y(n*model.N1+1)*model_data.grid.Y(n*model.N1+1) / (model.h2*model.h2) + model.deltaT*model.r; % Z of the '3-point-star' at the S1 = 0 boundary
67  L_I_S2bound(n*model.N1+1,(n+1)*model.N1+1) = - model.deltaT*XI(2,2)*model_data.grid.Y(n*model.N1+1)*model_data.grid.Y(n*model.N1+1) / (2*model.h2*model.h2) - model.deltaT*model_data.grid.Y(n*model.N1+1)*model.r / (2*model.h2); % N of the '3-point-star' at the S1 = 0 boundary
68  end
69 
70 % build the matrix entrys at the inner points
71 L_I_Inner = spalloc(k,k,model.N1*model.N2*9);
72  for j = 1 : model.N2-2
73  for i = j*model.N1+2 : (j+1)*model.N1-1
74  L_I_Inner(i,i-model.N1-1) = - model.deltaT*XI(1,2)*model_data.grid.X(i)*model_data.grid.Y(i) / (4*model.h1*model.h2); % SW of the 9-point-star
75  L_I_Inner(i,i-model.N1) = - model.deltaT*XI(2,2)*model_data.grid.Y(i)*model_data.grid.Y(i) / (2*model.h2*model.h2) + model.deltaT*model_data.grid.Y(i)*model.r / (2*model.h2); % S of the 9-point-star
76  L_I_Inner(i,i-model.N1+1) = model.deltaT*XI(1,2)*model_data.grid.X(i)*model_data.grid.Y(i) / (4*model.h1*model.h2); % SO of the 9-point-star
77  L_I_Inner(i,i-1) = - model.deltaT*XI(1,1)*model_data.grid.X(i)*model_data.grid.X(i) / (2*model.h1*model.h1) + model.deltaT*model_data.grid.X(i)*model.r / (2*model.h1); % W of the 9-point-star
78  L_I_Inner(i,i) = model.deltaT*XI(1,1)*model_data.grid.X(i)*model_data.grid.X(i) / (model.h1*model.h1) + model.deltaT*XI(2,2)*model_data.grid.Y(i)*model_data.grid.Y(i) / (model.h2*model.h2) + model.deltaT*model.r; % Z of the 9-point-star
79  L_I_Inner(i,i+1) = - model.deltaT*XI(1,1)*model_data.grid.X(i)*model_data.grid.X(i) / (2*model.h1*model.h1) - model.deltaT*model_data.grid.X(i)*model.r / (2*model.h1); % O of the 9-point-star
80  L_I_Inner(i,i+model.N1-1) = model.deltaT*XI(1,2)*model_data.grid.X(i)*model_data.grid.Y(i) / (4*model.h1*model.h2); % NW of the 9-point-star
81  L_I_Inner(i,i+model.N1) = - model.deltaT*XI(2,2)*model_data.grid.Y(i)*model_data.grid.Y(i) / (2*model.h2*model.h2) - model.deltaT*model_data.grid.Y(i)*model.r / (2*model.h2); % N of the 9-point-star
82  L_I_Inner(i,i+model.N1+1) = - model.deltaT*XI(1,2)*model_data.grid.X(i)*model_data.grid.Y(i) / (4*model.h1*model.h2); % NO of the 9-point-star
83  end
84  end
85 
86 L_I = L_I_basic + L_I_S1bound + L_I_S2bound + L_I_Inner; % build L_I
87 L_E = speye(k); % L_E = Id, because our discretization is completely implicit
88 b = zeros(k,1); % no inhomogeneity
89 
90 % simply transpose the components for the dual case
91 if model.want_dual
92  L_I_adj = L_I';
93  L_E_adj = L_E';
94 end
95 
96 
97 elseif decomp_mode == 1 % the parameterindependant components are generated
98 
99 grid = model_data.grid;
100 k = grid.nvertices;
101 
102 % L_I always has the form L_I = Id + \bar{L_I}. This also contains the
103 % dirichlet boundary values.
104 L_I_basic = speye(k);
105 
106 % build the matrix to the coefficient sigma1*sigma1. It is tridiagonal with
107 % diagonal position -1/0/1 and contains parts of the W/Z/O entry of the
108 % 9-point-star
109 
110 % approach:
111 % always build a vector containing the entrys of the corresponding diagonal
112 % and write those vector entrys on the diagonal. Therefore the vector
113 % contains the important information. The length of the vector always
114 % indicates the length of the corresponding diagonal.
115 
116 % Z entrys
117 XI_11_center_build = zeros(model.N1,1);
118 XI_11_center = zeros(k,1);
119 i = 1 : model.N1-1; % the index set specifies which vector entrys are non-zero
120 XI_11_center_build(i,1) = model.deltaT*grid.X(i).*grid.X(i)/(model.h1*model.h1);
121 XI_11_center(1:model.N1*(model.N2-1),1) = repmat(XI_11_center_build,model.N2-1,1); % build the vector
122 % W entrys
123 XI_11_west_build = zeros(model.N1,1);
124 XI_11_west = zeros(k-1,1);
125 i = 1 : model.N1-2; % the index set specifies which vector entrys are non-zero
126 XI_11_west_build(i,1) = -model.deltaT*grid.X(i+1).*grid.X(i+1)/(2*model.h1*model.h1);
127 XI_11_west(1:model.N1*(model.N2-1),1) = repmat(XI_11_west_build,model.N2-1,1); % build the vector
128 % O entrys
129 XI_11_ost_build = zeros(model.N1,1);
130 XI_11_ost = zeros(k-1,1);
131 i = 2 : model.N1-1; % the index set specifies which vector entrys are non-zero
132 XI_11_ost_build(i,1) = -model.deltaT*grid.X(i).*grid.X(i)/(2*model.h1*model.h1);
133 XI_11_ost(1:model.N1*(model.N2-1),1) = repmat(XI_11_ost_build,model.N2-1,1); % build the vector
134 %Matrix assembly
135 L_I_XI_11 = sparse(diag(XI_11_center,0)+diag(XI_11_west,-1)+diag(XI_11_ost,1));
136 
137 
138 % build the matrix to the coefficient sigma1*sigma1. It is tridiagonal with
139 % diagonal position -model.N1/0/model.N1 and contains parts of the S/Z/N
140 % entry of the 9-point-star
141 
142 % approach:
143 % again build a vector containing the entrys of the corresponding diagonal
144 % and write those vector entrys on the diagonal. Therefore the vector
145 % contains the important information. The length of the vector always
146 % indicates the length of the corresponding diagonal. The construction of
147 % the vector is a little more complex this time.
148 
149 % Z entrys
150 XI_22_center_build = zeros(1,model.N2-1);
151 XI_22_center = zeros(k,1);
152 i = 1 : model.N2-1; % the index set specifies which vector entrys are non-zero
153 % building the vector
154 XI_22_center_build(1,i) = model.deltaT*grid.Y(model.N1*(i-1)+1).*grid.Y(model.N1*(i-1)+1)/(model.h2*model.h2);
155 XI_22_center_build_2 = repmat(XI_22_center_build,model.N1,1);
156 XI_22_center(1:numel(XI_22_center_build_2),1) = XI_22_center_build_2(:);
157 XI_22_center(model.N1:model.N1:length(XI_22_center)) = 0;
158 % S entrys
159 XI_22_sued_build = zeros(1,model.N2-2);
160 XI_22_sued = zeros(k-model.N1,1);
161 i = 1 : model.N2-2; % the index set specifies which vector entrys are non-zero
162 % building the vector
163 XI_22_sued_build(1,i) = -model.deltaT*grid.Y(model.N1*i+1).*grid.Y(model.N1*i+1)/(2*model.h2*model.h2);
164 XI_22_sued_build_2 = repmat(XI_22_sued_build,model.N1,1);
165 XI_22_sued(1:numel(XI_22_sued_build_2),1) = XI_22_sued_build_2(:);
166 XI_22_sued(model.N1:model.N1:length(XI_22_sued)) = 0;
167 % N entrys
168 XI_22_nord_build = zeros(1,model.N2-1);
169 XI_22_nord = zeros(k-model.N1,1);
170 i = 2 : model.N2-1; % the index set specifies which vector entrys are non-zero
171 % building the vector
172 XI_22_nord_build(1,i) = -model.deltaT*grid.Y(model.N1*(i-1)+1).*grid.Y(model.N1*(i-1)+1)/(2*model.h2*model.h2);
173 XI_22_nord_build_2 = repmat(XI_22_nord_build,model.N1,1);
174 XI_22_nord(1:numel(XI_22_nord_build_2),1) = XI_22_nord_build_2(:);
175 XI_22_nord(model.N1:model.N1:length(XI_22_nord)) = 0;
176 %Matrix assembly
177 L_I_XI_22 = sparse(diag(XI_22_center,0)+diag(XI_22_sued,-model.N1)+diag(XI_22_nord,model.N1));
178 
179 
180 % The matrix for the coefficient sigma1*sigma2*2*model.rho/(1+model.rho^2):
181 %
182 %
183 % XI_12 = spalloc(k,k,4*k); %Maximal 4 Einträge pro Zeile (NW/NO/SW/SO)
184 % for j = 2 : model.N2-1 %Doppel-for-Schleife über alle inneren Punkte
185 % for i = (j-1)*model.N1+2 : j*model.N1-1
186 % XI_12(i,i+model.N1-1) = model.deltaT*grid.X(i+model.N1-1)*grid.Y(i+model.N1-1)/(4*model.h1*model.h2); %NW-Eintrag
187 % XI_12(i,i+model.N1+1) = -model.deltaT*grid.X(i+model.N1+1)*grid.Y(i+model.N1+1)/(4*model.h1*model.h2); %NO-Eintrag
188 % XI_12(i,i-model.N1-1) = -model.deltaT*grid.X(i-model.N1-1)*grid.Y(i-model.N1-1)/(4*model.h1*model.h2); %SW-Eintrag
189 % XI_12(i,i-model.N1+1) = model.deltaT*grid.X(i-model.N1+1)*grid.Y(i-model.N1+1)/(4*model.h1*model.h2); %SO-Eintrag
190 % end
191 % end
192 % new version:
193 i = zeros(model.N2-2,model.N1-2); % number of inner points
194 % the loop generates an indexmatrix with the indices of all inner points
195 for j = 1 : model.N2-2
196  i(j,:) = j*model.N1+2 : (j+1)*model.N1-1;
197 end
198 indices = reshape(i,1,size(i,1)*size(i,2)); % the inidces are reshaped as a rowvector
199 Zeilen_build = repmat(indices,4,1); % this vector is reproduced 4 times, since per point there are 4 (NO,NW,SO,SW) entrys
200 % with this rowvector we create indexvectors for the columns and rows in
201 % which the corresponding entrys are writeen
202 Zeilen = Zeilen_build(:);
203 Spalten = Zeilen + repmat([model.N1-1;model.N1+1;-model.N1-1;-model.N1+1],size(i,1)*size(i,2),1);
204 % build the matrix
205 L_I_XI_12 = sparse(Zeilen, Spalten, grid.X(Zeilen).*grid.Y(Zeilen).*repmat([model.deltaT;-model.deltaT;-model.deltaT;model.deltaT],size(i,1)*size(i,2),1)/(4*model.h1*model.h2) ,k ,k);
206 
207 
208 %Die Matrix zu model.r -> 5 Diagonalen an den Posiotionen
209 %-model.N1/-1/0/1/model.N1 mit den Resten der Süd/West/Z/Ost/Nord -
210 %Einträgen.
211 
212 % build the matrix to the coefficient model.r. It has 5 diagonals with
213 % diagonal position -model.N1/-1/0/1/model.N1 and contains parts of the
214 % S/W/Z/O/N entry of the 9-point-star
215 % the procedure is similar to the ones above
216 
217 % Z entrys
218 r_center_build = zeros(model.N1,1);
219 r_center = zeros(k,1);
220 r_center_build(1:model.N1-1,1) = model.deltaT;
221 r_center(1:model.N1*(model.N2-1)) = repmat(r_center_build,model.N2-1,1);
222 r_center(1,1) = 0;
223 % S entrys
224 r_sued_build = zeros(1,model.N2-2);
225 r_sued = zeros(k-model.N1,1);
226 i = 1 : model.N2-2;
227 r_sued_build(1,i) = model.deltaT*grid.Y(model.N1*i+1)/(2*model.h2);
228 r_sued_build_2 = repmat(r_sued_build,model.N1,1);
229 r_sued(1:numel(r_sued_build_2),1) = r_sued_build_2(:);
230 r_sued(model.N1:model.N1:length(r_sued)) = 0;
231 % N entrys
232 r_nord_build = zeros(1,model.N2-1);
233 r_nord = zeros(k-model.N1,1);
234 i = 2 : model.N2-1;
235 r_nord_build(1,i) = -model.deltaT*grid.Y(model.N1*(i-1)+1)/(2*model.h2);
236 r_nord_build_2 = repmat(r_nord_build,model.N1,1);
237 r_nord(1:numel(r_nord_build_2),1) = r_nord_build_2(:);
238 r_nord(model.N1:model.N1:length(r_nord)) = 0;
239 % W entrys
240 r_west_build = zeros(model.N1,1);
241 r_west = zeros(k-1,1);
242 i = 1 : model.N1-2;
243 r_west_build(i,1) = model.deltaT*grid.X(i+1)/(2*model.h1);
244 r_west(1:model.N1*(model.N2-1),1) = repmat(r_west_build,model.N2-1,1);
245 % O entrys
246 r_ost_build = zeros(model.N1,1);
247 r_ost = zeros(k-1,1);
248 i = 2 : model.N1-1;
249 r_ost_build(i,1) = -model.deltaT*grid.X(i)/(2*model.h1);
250 r_ost(1:model.N1*(model.N2-1),1) = repmat(r_ost_build,model.N2-1,1);
251 %Matrix assembly
252 L_I_r = sparse(diag(r_center,0)+diag(r_sued,-model.N1)+diag(r_nord,model.N1)+diag(r_west,-1)+diag(r_ost,1));
253 
254 % the dual components are simply the transposed
255 if model.want_dual
256  L_I_r_adj = L_I_r';
257  L_I_XI_11_adj = L_I_XI_11';
258  L_I_XI_22_adj = L_I_XI_22';
259  L_I_XI_12_adj = L_I_XI_12';
260  L_I_basic_adj = L_I_basic';
261  L_I_adj = {L_I_r_adj; L_I_XI_11_adj; L_I_XI_22_adj; L_I_XI_12_adj; L_I_basic_adj};
262  L_E_adj = {speye(k)'};
263 else
264  L_I = {L_I_r; L_I_XI_11; L_I_XI_22; L_I_XI_12; L_I_basic};
265  L_E = {speye(k)};
266  b = {zeros(k,1)};
267 end
268 
269 
270 elseif decomp_mode == 2 % parameterdependant coefficients are computed
271  if model.want_dual
272  L_I_adj = [model.r; model.sigma1*model.sigma1; model.sigma2*model.sigma2; 2*model.rho/(1+model.rho*model.rho)*model.sigma1*model.sigma2; 1];
273  L_E_adj = 1;
274  else
275  L_I = [model.r; model.sigma1*model.sigma1; model.sigma2*model.sigma2; 2*model.rho/(1+model.rho*model.rho)*model.sigma1*model.sigma2; 1];
276  L_E = 1;
277  b = 1;
278  end
279 
280 end
function [ L_I , L_E , b , L_I_adj , L_E_adj ] = eop_fd_operators(model, model_data)
[L_I, L_E, b, L_I_adj, L_E_adj] = eop_fd_operators(model, model_data)