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] = ...
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] = ...
6 %
function computing the time-dependent reduced basis operators and
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
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
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
31 % In
'coefficients' mode the detailed data is empty.
33 % Bernard Haasdonk 23.7.2006
35 % extended to primal/dual formulaton by Dominik Garmatter:
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.
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.
50 % Dominik Garmatter 20.07 2012
62 decomp_mode = model.decomp_mode;
64 if decomp_mode == 0 % complete: simple projection on RB
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
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
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);
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);
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);
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);
100 [L_I, L_E, b] = model.operators_ptr(model,detailed_data);
104 % First compute Quantities that are required in every case. But remember
105 % the included matrices are different (primal or dual)
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;
111 % fill output quantities
115 LL_I = detailed_data.RB' * A * L_I_RB;
118 LL_E = detailed_data.RB' * A * L_E_RB;
121 K_II = L_I_RB' * A * L_I_RB;
124 K_IE = L_I_RB' * A * L_E_RB;
127 K_EE = L_E_RB' * A * L_E_RB;
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;
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
139 bb = detailed_data.RB' * A * b;
142 m_I = L_I_RB' * A * b;
145 m_E = L_E_RB' * A * b;
149 if model.want_improved_output && model.want_dual == 0
150 % These Quantities are required for the correction term used in the
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;
158 elseif decomp_mode == 1
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
167 if isfield(detailed_data, 'L_I_comp') && isfield(detailed_data, 'L_E_comp')
168 % simply extract the components out of the detailed_data
170 if strcmp(model.name_output_functional, 'theta') == 1
171 b = detailed_data.b_comp;
174 b = detailed_data.b_comp;
176 L_I = detailed_data.L_I_comp;
177 L_E = detailed_data.L_E_comp;
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);
186 [L_I, L_E, b] = model.operators_ptr(model,detailed_data);
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')
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;
201 if ~isfield(detailed_data, 'L_E_comp')
202 detailed_data.L_E_comp = L_E;
204 scm_offline_data =
scm_offline(model, detailed_data);
210 Nmax = size(detailed_data.RB,2);
211 H = size(detailed_data.RB,1);
214 % First compute Quantities that are required in every case. But remember
215 % the included matrices are different (primal or dual)
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)};
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)};
235 L_E_RB{q}(:,:)= L_E{q} * detailed_data.RB;
238 L_I_RB{q}(:,:)= L_I{q} * detailed_data.RB;
241 if model.want_dual % additional requirements
for the dual residual in the 0 -> 1 timestep
243 L_Id_RB(:) = {zeros(H,Nmax)};
245 K_IdId(:) = {zeros(Nmax,Nmax)};
246 K_IdE = cell(1*Q_L_E,1);
247 K_IdE(:) = {zeros(Nmax,Nmax)};
249 L_Id_RB{1}(:,:) = speye(H) * detailed_data.RB;
250 K_IdId{1}(:,:) = L_Id_RB{1}
' * A * L_Id_RB{1};
252 K_IdE{q2} = L_Id_RB{1}' * A * L_E_RB{q2};
256 % fill output quantities
259 LL_I{q} = detailed_data.RB
' * A * L_I_RB{q};
264 LL_E{q} = detailed_data.RB' * A * L_E_RB{q};
271 K_II{ (q1-1)*Q_L_I + q2}(:,:) = ...
272 L_I_RB{q1}
' * A * L_I_RB{q2};
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
282 K_IE{ (q1-1)*Q_L_E + q2} = ...
283 L_I_RB{q1}' * A * L_E_RB{q2};
290 K_EE{ (q1-1)*Q_L_E + q2} = ...
291 L_E_RB{q1}
' * A * L_E_RB{q2};
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
299 % init output quantities
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)};
309 bb(:) = {zeros(Nmax,1)};
313 bb{q} = detailed_data.RB' * A * b{q};
319 m_I{ (q1-1)*Q_b + q2} = ...
320 L_I_RB{q1}
' * A * b{q2};
327 m_E{ (q1-1)*Q_b + q2} = ...
328 L_E_RB{q1}' * A * b{q2};
335 m{ (q1-1)*Q_b + q2} = ...
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)};
352 LL_I_correct{q} = L_I_RB{q}' * A * detailed_data_dual.RB;
356 LL_E_correct{q} = L_E_RB{q}
' * A * detailed_data_dual.RB;
360 bb_correct{q} = b{q}' * A * detailed_data_dual.RB;
364 else % decomp_mode== 2 -> coefficients
366 % computing the coeffs dependant on the controlfield
'model.want_dual'
367 % 1 = dual Operators are computet, 0 = primal ones are.
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);
374 [L_I, L_E, b] = model.operators_ptr(model,[]);
377 % First compute Quantities that are required in every
case. But remember
378 % the included coefficients can be different (primal or dual)
380 Q_L_I = length(L_I(:));
381 Q_L_E = length(L_E(:));
383 % rb-
operator coefficients can simply be forwarded
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);
392 if model.want_dual % additional requirements
for the dual residual in the 0 -> 1 timestep: (remember L_I ist simply the Identity there)
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);
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
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)
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)
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) ...