1 function [L_I, L_E, b, L_I_adj, L_E_adj] =
eop_fd_operators(model, model_data)
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
9 % decomp_mode: operation mode of the
function
10 % - 0=
'complete' (
default): no parameter dependence or decomposition is
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
19 % the construction of L_I follows a 9-point-star described in my diploma
20 % thesis (chapter 4.2)
22 % Dominik Garmatter 02.04 2012
30 if ~isfield(model,
'decomp_mode')
31 model.decomp_mode = 0;
33 if ~isfield(model, 'want_dual')
37 decomp_mode = model.decomp_mode;
39 if decomp_mode == 0 % no affine decomposition
40 k = model_data.grid.nvertices; % k = number of grid points
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];
48 % L_I always has the form L_I = Id + \bar{L_I}. This also contains the
49 % dirichlet boundary values.
52 % NOTE:
this version
using spalloc is still sufficiently fast!
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
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
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
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
90 % simply transpose the components for the dual case
97 elseif decomp_mode == 1 % the parameterindependant components are generated
99 grid = model_data.grid;
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);
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
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.
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
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
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
135 L_I_XI_11 = sparse(diag(XI_11_center,0)+diag(XI_11_west,-1)+diag(XI_11_ost,1));
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
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.
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;
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;
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;
177 L_I_XI_22 = sparse(diag(XI_22_center,0)+diag(XI_22_sued,-model.N1)+diag(XI_22_nord,model.N1));
180 % The matrix
for the coefficient sigma1*sigma2*2*model.rho/(1+model.rho^2):
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
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;
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);
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);
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 -
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
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);
224 r_sued_build = zeros(1,model.N2-2);
225 r_sued = zeros(k-model.N1,1);
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;
232 r_nord_build = zeros(1,model.N2-1);
233 r_nord = zeros(k-model.N1,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;
240 r_west_build = zeros(model.N1,1);
241 r_west = zeros(k-1,1);
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);
246 r_ost_build = zeros(model.N1,1);
247 r_ost = zeros(k-1,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);
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));
254 % the dual components are simply the transposed
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)'};
264 L_I = {L_I_r; L_I_XI_11; L_I_XI_22; L_I_XI_12; L_I_basic};
270 elseif decomp_mode == 2 % parameterdependant coefficients are computed
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];
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];
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)