rbmatlab  1.16.09
 All Classes Namespaces Files Functions Variables Modules Pages
lin_evol_rb_operators_primal_dual.m
Go to the documentation of this file.
1 function [LL_I, LL_E, bb, K_II, K_IE, K_EE, m_I, m_E, m, K_IdId, K_IdE, LL_I_correct, LL_E_correct, bb_correct, scm_offline_data] = ...
2  lin_evol_rb_operators_primal_dual(model, detailed_data)
3 %[LL_I, LL_E, bb, K_II, K_IE, K_EE, m_I, m_E, m, K_IdId, K_IdE, LL_I_correct, LL_E_correct, bb_correct, scm_offline_data] = ...
4 % lin_evol_rb_operators_primal_dual(model, detailed_data)
5 %
6 % function computing the time-dependent reduced basis operators and
7 % vectors.
8 %
9 % Function supports affine decomposition, i.e. different operation modes
10 % guided by optional field decomp_mode in params. See also the
11 % contents.txt for general explanation
12 %
13 % Required fields of model
14 % operators_algorithm: name of function for computing the
15 % L_E,L_I,b-operators with arguments (grid, params)
16 % example fv_operators_implicit
17 %
18 %
19 % Optional fields of model:
20 % mu_names : names of fields to be regarded as parameters in vector mu
21 % decomp_mode: operation mode of the function
22 % -0= 'complete' (default): no parameter dependence or decomposition is
23 % performed. output is as described above.
24 % -1= 'components': For each output argument a cell array of output
25 % arguments is returned representing the q-th component
26 % independent of the parameters given in mu_names
27 % -2= 'coefficients': For each output argument a cell array of output
28 % arguments is returned representing the q-th coefficient
29 % dependent of the parameters given in mu_names
30 %
31 % In 'coefficients' mode the detailed data is empty.
32 %
33 % Bernard Haasdonk 23.7.2006
34 %
35 % extended to primal/dual formulaton by Dominik Garmatter:
36 %
37 % see lin_evol_gen_reduced_data_primal_dual.m for the various cases that
38 % are included in this function. scm_offline_data are only generated if
39 % decomp_mode = 1, because you want to produce those data in your
40 % reduced_data and in gen_reduced_data the
41 % rb_operators are always called with decomp_mode = 1.
42 %
43 % special Note: in the european_option_pricing model a functional named
44 % 'theta' includes a partial timederivative and therefore produces a
45 % slightly different dual problem. Therefore the 'theta'-case is sometimes
46 % treated differently. Don't care about this case if you don't use the
47 % european_option_pricing model.
48 
49 
50 % Dominik Garmatter 20.07 2012
51 
52 bb = [];
53 m_I = [];
54 m_E = [];
55 m = [];
56 bb_correct = [];
57 LL_I_correct = [];
58 LL_E_correct = [];
59 K_IdId = [];
60 K_IdE = [];
61 
62 decomp_mode = model.decomp_mode;
63 
64 if decomp_mode == 0 % complete: simple projection on RB
65 
66 % if you want the improved output you need both detailed_data, which
67 % should be connected in the current 'detailed_data'. This function splits
68 % them, so the operators can work.
69 if model.want_improved_output && model.want_dual == 0
70  [detailed_data, detailed_data_dual] = lin_evol_split_detailed_data(detailed_data);
71 end
72 
73 if isfield(detailed_data, 'L_I_comp') && isfield(detailed_data, 'L_E_comp')
74 % use the components given in detailed_data to assemble the dual or primal
75 % components of the respective evolution scheme. The required coefficients
76 % are now computed.
77  old_mode = model.decomp_mode;
78  model.decomp_mode = 2;
79  if model.want_dual % dual
80  [~, ~, ~, L_I_coeff, L_E_coeff] = model.operators_ptr(model, detailed_data);
81  if strcmp(model.name_output_functional, 'theta') == 1
82  b_coeff = model.operators_output(model, detailed_data);
83  b = lincomb_sequence(detailed_data.b_comp, b_coeff);
84  end
85  else % primal
86  [L_I_coeff, L_E_coeff, b_coeff] = model.operators_ptr(model,detailed_data);
87  b = lincomb_sequence(detailed_data.b_comp, b_coeff);
88  end
89  model.decomp_mode = old_mode;
90  L_I = lincomb_sequence(detailed_data.L_I_comp, L_I_coeff);
91  L_E = lincomb_sequence(detailed_data.L_E_comp, L_E_coeff);
92 
93 else % there are no components in detailed_data compute the quantities (decomp_mode = 0)
94  if model.want_dual % dual
95  [~, ~, ~, L_I, L_E] = model.operators_ptr(model, detailed_data);
96  if strcmp(model.name_output_functional, 'theta') == 1
97  b = model.operators_output(model, detailed_data);
98  end
99  else % primal
100  [L_I, L_E, b] = model.operators_ptr(model,detailed_data);
101  end
102 end
103 
104 % First compute Quantities that are required in every case. But remember
105 % the included matrices are different (primal or dual)
106 
107  % apply all operator contributions to RB:
108  L_E_RB = L_E * detailed_data.RB;
109  L_I_RB = L_I * detailed_data.RB;
110 
111  % fill output quantities
112  % LL_I : matrix
113  A = detailed_data.W;
114 
115  LL_I = detailed_data.RB' * A * L_I_RB;
116 
117  % LL_E : matrix
118  LL_E = detailed_data.RB' * A * L_E_RB;
119 
120  % K_II : matrix
121  K_II = L_I_RB' * A * L_I_RB;
122 
123  % K_IE : matrix
124  K_IE = L_I_RB' * A * L_E_RB;
125 
126  % K_EE : matrix
127  K_EE = L_E_RB' * A * L_E_RB;
128 
129  if model.want_dual % additional requirements for the dual residual in the 0 -> 1 timestep
130  L_Id_RB = speye(size(L_I)) * detailed_data.RB;
131  K_IdId = L_Id_RB' * A * L_Id_RB;
132  K_IdE = L_Id_RB' * A * L_E_RB;
133  end
134 
135 % the Quantities that come into play when an inhomogeneity is involved (b
136 % in the primal case or v_l in the dual theta case in the second timestep)
137  if ~model.want_dual || strcmp(model.name_output_functional, 'theta') == 1
138  % bb : vector
139  bb = detailed_data.RB' * A * b;
140 
141  % m_I : vector
142  m_I = L_I_RB' * A * b;
143 
144  % m_E : vector
145  m_E = L_E_RB' * A * b;
146 
147  % m : scalar
148  m = b' * A * b;
149  if model.want_improved_output && model.want_dual == 0
150  % These Quantities are required for the correction term used in the
151  % improved output
152  bb_correct = b' * A * detailed_data_dual.RB;
153  LL_I_correct = L_I_RB' * A * detailed_data_dual.RB;
154  LL_E_correct = L_E_RB' * A * detailed_data_dual.RB;
155  end
156  end
157 
158 elseif decomp_mode == 1
159 
160 % if you want the improved output you need both detailed_data, which
161 % should be connected in the current 'detailed_data'. This function splits
162 % them, so the operators can work.
163 if model.want_improved_output && model.want_dual == 0
164  [detailed_data, detailed_data_dual] = lin_evol_split_detailed_data(detailed_data);
165 end
166 
167 if isfield(detailed_data, 'L_I_comp') && isfield(detailed_data, 'L_E_comp')
168 % simply extract the components out of the detailed_data
169  if model.want_dual
170  if strcmp(model.name_output_functional, 'theta') == 1
171  b = detailed_data.b_comp;
172  end
173  else
174  b = detailed_data.b_comp;
175  end
176  L_I = detailed_data.L_I_comp;
177  L_E = detailed_data.L_E_comp;
178 
179 else % there are no components in detailed_data compute them (decomp_mode = 1)
180  if model.want_dual % dual
181  [~, ~, ~, L_I, L_E] = model.operators_ptr(model, detailed_data);
182  if strcmp(model.name_output_functional, 'theta') == 1
183  b = model.operators_output(model, detailed_data);
184  end
185  else % primal
186  [L_I, L_E, b] = model.operators_ptr(model,detailed_data);
187  end
188 end
189 
190 % in gen_reduced_data the rb_operators are always called with
191 % decomp_mode = 1. Therefore only in this case the computation
192 % of scm_offline_data can be required. Generate them here if desired.
193 if ~isfield(model, 'use_scm')
194  model.use_scm = 0;
195 end
196 if model.use_scm
197  % these 2 fields are required in detailed_data for the scm to work!
198  if ~isfield(detailed_data, 'L_I_comp')
199  detailed_data.L_I_comp = L_I;
200  end
201  if ~isfield(detailed_data, 'L_E_comp')
202  detailed_data.L_E_comp = L_E;
203  end
204  scm_offline_data = scm_offline(model, detailed_data);
205 end
206 
207  Q_L_I = size(L_I,1);
208  Q_L_E = size(L_E,1);
209 
210  Nmax = size(detailed_data.RB,2);
211  H = size(detailed_data.RB,1);
212  A = detailed_data.W;
213 
214 % First compute Quantities that are required in every case. But remember
215 % the included matrices are different (primal or dual)
216 
217  % matrices:
218  K_II = cell(Q_L_I*Q_L_I,1);
219  K_II(:) = {zeros(Nmax,Nmax)};
220  K_IE = cell(Q_L_I*Q_L_E,1);
221  K_IE(:) = {zeros(Nmax,Nmax)};
222  K_EE = cell(Q_L_E*Q_L_E,1);
223  K_EE(:) = {zeros(Nmax,Nmax)};
224  LL_I = cell(Q_L_I,1);
225  LL_I(:) = {zeros(Nmax,Nmax)};
226  LL_E = cell(Q_L_E,1);
227  LL_E(:) = {zeros(Nmax,Nmax)};
228 
229  % apply all operator contributions to RB:
230  L_E_RB = cell(Q_L_E,1);
231  L_E_RB(:) = {zeros(H,Nmax)};
232  L_I_RB = cell(Q_L_I,1);
233  L_I_RB(:) = {zeros(H,Nmax)};
234  for q=1:Q_L_E
235  L_E_RB{q}(:,:)= L_E{q} * detailed_data.RB;
236  end;
237  for q=1:Q_L_I
238  L_I_RB{q}(:,:)= L_I{q} * detailed_data.RB;
239  end;
240 
241  if model.want_dual % additional requirements for the dual residual in the 0 -> 1 timestep
242  L_Id_RB = cell(1,1);
243  L_Id_RB(:) = {zeros(H,Nmax)};
244  K_IdId = cell(1,1);
245  K_IdId(:) = {zeros(Nmax,Nmax)};
246  K_IdE = cell(1*Q_L_E,1);
247  K_IdE(:) = {zeros(Nmax,Nmax)};
248 
249  L_Id_RB{1}(:,:) = speye(H) * detailed_data.RB;
250  K_IdId{1}(:,:) = L_Id_RB{1}' * A * L_Id_RB{1};
251  for q2 = 1:Q_L_E
252  K_IdE{q2} = L_Id_RB{1}' * A * L_E_RB{q2};
253  end
254  end
255 
256  % fill output quantities
257  % LL_I : matrices
258  for q = 1:Q_L_I;
259  LL_I{q} = detailed_data.RB' * A * L_I_RB{q};
260  end
261 
262  % LL_E : matrices
263  for q = 1:Q_L_E;
264  LL_E{q} = detailed_data.RB' * A * L_E_RB{q};
265  end
266 
267 
268  % K_II : matrices
269  for q1 = 1:Q_L_I;
270  for q2 = 1:Q_L_I;
271  K_II{ (q1-1)*Q_L_I + q2}(:,:) = ...
272  L_I_RB{q1}' * A * L_I_RB{q2};
273  end;
274  end;
275 
276  % K_IE : time sequence of matrices
277  % K_IE{1} = Gram matrix of L_I_RB{1} and L_E_RB{1}
278  % K_IE{2} = Gram matrix of L_I_RB{1} and L_E_RB{2}
279  % so L_E is "inner loop". This must fit to the sigma-ordering
280  for q1 = 1:Q_L_I;
281  for q2 = 1:Q_L_E;
282  K_IE{ (q1-1)*Q_L_E + q2} = ...
283  L_I_RB{q1}' * A * L_E_RB{q2};
284  end;
285  end;
286 
287  % K_EE : matrices
288  for q1 = 1:Q_L_E;
289  for q2 = 1:Q_L_E;
290  K_EE{ (q1-1)*Q_L_E + q2} = ...
291  L_E_RB{q1}' * A * L_E_RB{q2};
292  end;
293  end;
294 
295 % the Quantities that come into play when an inhomogeneity is involved (b
296 % in the primal case or v_l in the dual theta case in the second timestep)
297  if ~model.want_dual || strcmp(model.name_output_functional, 'theta') == 1
298  Q_b = length(b);
299  % init output quantities
300  % scalars:
301  m = cell(Q_b*Q_b,1);
302  m(:) = {zeros(1,1)};
303  % vectors:
304  m_I = cell(Q_L_I*Q_b,1);
305  m_I(:) = {zeros(Nmax,1)};
306  m_E = cell(Q_L_E*Q_b,1);
307  m_E(:) = {zeros(Nmax,1)};
308  bb = cell(Q_b,1);
309  bb(:) = {zeros(Nmax,1)};
310 
311  % bb : vectors
312  for q = 1:Q_b;
313  bb{q} = detailed_data.RB' * A * b{q};
314  end;
315 
316  % m_I : vectors
317  for q1 = 1:Q_L_I;
318  for q2 = 1:Q_b;
319  m_I{ (q1-1)*Q_b + q2} = ...
320  L_I_RB{q1}' * A * b{q2};
321  end;
322  end;
323 
324  % m_E : vectors
325  for q1 = 1:Q_L_E;
326  for q2 = 1:Q_b;
327  m_E{ (q1-1)*Q_b + q2} = ...
328  L_E_RB{q1}' * A * b{q2};
329  end;
330  end;
331 
332  % m : scalars
333  for q1 = 1:Q_b;
334  for q2 = 1:Q_b;
335  m{ (q1-1)*Q_b + q2} = ...
336  b{q1}' * A * b{q2};
337  end;
338  end
339  end
340 
341  if model.want_improved_output && model.want_dual == 0
342  % These Quantities are required for the correction term used in the
343  % improved output (only in the primal case available)
344  LL_I_correct = cell(Q_L_I,1);
345  LL_I_correct(:) = {zeros(Nmax,Nmax)};
346  LL_E_correct = cell(Q_L_E,1);
347  LL_E_correct(:) = {zeros(Nmax,Nmax)};
348  bb_correct = cell(Q_b,1);
349  bb_correct(:) = {zeros(Nmax,1)};
350 
351  for q = 1:Q_L_I;
352  LL_I_correct{q} = L_I_RB{q}' * A * detailed_data_dual.RB;
353  end
354 
355  for q = 1:Q_L_E;
356  LL_E_correct{q} = L_E_RB{q}' * A * detailed_data_dual.RB;
357  end
358 
359  for q = 1:Q_b;
360  bb_correct{q} = b{q}' * A * detailed_data_dual.RB;
361  end
362  end
363 
364 else % decomp_mode== 2 -> coefficients
365 
366 % computing the coeffs dependant on the controlfield 'model.want_dual'
367 % 1 = dual Operators are computet, 0 = primal ones are.
368  if model.want_dual
369  [~, ~, ~, L_I, L_E] = model.operators_ptr(model,[]);
370  if strcmp(model.name_output_functional, 'theta') == 1
371  b = model.operators_output(model, detailed_data);
372  end
373  else
374  [L_I, L_E, b] = model.operators_ptr(model,[]);
375  end
376 
377 % First compute Quantities that are required in every case. But remember
378 % the included coefficients can be different (primal or dual)
379 
380  Q_L_I = length(L_I(:));
381  Q_L_E = length(L_E(:));
382 
383  % rb-operator coefficients can simply be forwarded
384  LL_E = L_E;
385  LL_I = L_I;
386 
387  % pairs: products of sigmas:
388  K_II = repmatrows(L_I(:), Q_L_I) .* repmat(L_I(:), Q_L_I, 1);
389  K_IE = repmatrows(L_I(:), Q_L_E) .* repmat(L_E(:), Q_L_I, 1);
390  K_EE = repmatrows(L_E(:), Q_L_E) .* repmat(L_E(:), Q_L_E, 1);
391 
392  if model.want_dual % additional requirements for the dual residual in the 0 -> 1 timestep: (remember L_I ist simply the Identity there)
393  L_Id = 1;
394  Q_L_Id = length(L_Id(:));
395  K_IdId = repmatrows(L_Id(:), Q_L_Id) .* repmat(L_Id(:), Q_L_Id, 1);
396  K_IdE = repmatrows(L_Id(:), Q_L_E) .* repmat(L_E(:), Q_L_Id, 1);
397  end
398 
399 % the Quantities that come into play when an inhomogeneity is involved (b
400 % in the primal case or v_l in the dual theta case in the second timestep)
401  if ~model.want_dual || strcmp(model.name_output_functional, 'theta') == 1
402  Q_b = length(b(:));
403  bb = b;
404  m_I = repmatrows(L_I(:), Q_b) .* repmat(b(:) , Q_L_I, 1);
405  m_E = repmatrows(L_E(:), Q_b) .* repmat(b(:) , Q_L_E, 1);
406  m = repmatrows(b(:) , Q_b) .* repmat(b(:) , Q_b , 1);
407  if model.want_improved_output && model.want_dual == 0
408  % These Quantities are required for the correction term used in the
409  % improved output (only in the primal case available)
410  LL_I_correct = L_I;
411  LL_E_correct = L_E;
412  bb_correct = b;
413  end
414  end
415 
416 end %end if
function reduced_data = lin_evol_gen_reduced_data_primal_dual(model, detailed_data)
reduced_data = lin_evol_gen_reduced_data_primal_dual(model, detailed_data)
function [ LL_I , LL_E , bb , K_II , K_IE , K_EE , m_I , m_E , m , K_IdId , K_IdE , LL_I_correct , LL_E_correct , bb_correct , scm_offline_data ] = lin_evol_rb_operators_primal_dual(model, detailed_data)
[LL_I, LL_E, bb, K_II, K_IE, K_EE, m_I, m_E, m, K_IdId, K_IdE, LL_I_correct, LL_E_correct, bb_correct, scm_offline_data] = ... lin_evol_rb_operators_primal_dual(model, detailed_data)
function scm_offline_data = scm_offline(model, detailed_data, M_train, D_train)
scm_offline_data = scm_offline(model, detailed_data, M_train, D_train)
Definition: scm_offline.m:17
function [ detailed_data_primal , detailed_data_dual ] = lin_evol_split_detailed_data(detailed_data)
[detailed_data_primal, detailed_data_dual] = lin_evol_split_detailed_data(detailed_data) ...