rbmatlab  1.16.09
 All Classes Namespaces Files Functions Variables Modules Pages
lin_evol_detailed_simulation_primal_dual.m
Go to the documentation of this file.
1 function sim_data = lin_evol_detailed_simulation_primal_dual(model, model_data)
2 %sim_data = lin_evol_detailed_simulation_primal_dual(model, model_data)
3 %
4 % copy of lin_evol_detailed_simulation but extended to a primal/dual
5 % setting.
6 %
7 % function which performs a detailed simulation for the given mu, which has
8 % to be set in model via model.set_mu. Can either perform a pimal or a dual
9 % detailed simulation controlled via the field model.want_dual (= 1 or 0).
10 %
11 % see lin_ds_detailed_simulation for a description on the time indices
12 %
13 % required fields of model:
14 % T : final time
15 % nt : number of time-intervals until T, i.e. nt+1
16 % solution slices are computed
17 % init_values_algorithm: name of function for computing the
18 % initvalues-DOF with arguments (grid, params)
19 % example: init_values_cog
20 % operators_algorithm: name of function for computing the
21 % L_E,L_I,b-operators with arguments (grid, params)
22 % example operators_conv_diff
23 % data_const_in_time : if this optional field is 1, the time
24 % evolution is performed with constant operators,
25 % i.e. only the initial-time-operators are computed
26 % and used throughout the time simulation.
27 % compute_output_functional: flag indicating, whether output
28 % functional is to be computed
29 %
30 % return fields of sim_data:
31 % U : sequence of DOF vectors
32 % y : sequence of output functional values (if activated)
33 %
34 % optional fields of model:
35 % starting_time_step: starting time step for simulation (for example in
36 % t-partition). Default value is 0.
37 % stopping_tim_step: stopping time step for simulation
38 %
39 % special Note: in the european_option_pricing model a functional named
40 % 'theta' includes a partial timederivative and therefore produces a
41 % slightly different dual problem. Therefore the 'theta'-case is sometimes
42 % treated differently. Don't care about this case if you don't use the
43 % european_option_pricing model.
44 %
45 % Bernard Haasdonk 27.8.2009
46 %
47 % primal/dual formulation by Dominik Garmater 20.07 2012
48 
49 
50 
51 if ~isfield(model, 'want_dual')
52  model.want_dual = 0;
53 end
54 
55 if model.verbose >= 9
56  disp('entered detailed simulation ');
57 end
58 
59 if isempty(model_data)
60  model_data = gen_model_data(model);
61 end
62 
63 model.decomp_mode = 0; % == complete;
64 
65 model.dt = model.T/model.nt;
66 
67 %Fixing values for t-partition
68 if ~isfield(model,'starting_time_step')
69  model.t = 0;
70  t_ind_start =0;
71  t_ind_stop = model.nt;
72 else
73  t_ind_start = model.starting_time_step;
74  t_ind_stop = model.stopping_time_step;
75  model.t = (t_ind_start)*model.dt;
76 end
77 
78 % see lin_ds_detailed_simulation for a description on the time indices
79 if isfield(model,'save_time_indices')
80  valid_save_time_indices1 = model.save_time_indices>=t_ind_start;
81  valid_save_time_indices2 = model.save_time_indices<=t_ind_stop;
82  valid_save_time_indices = valid_save_time_indices1.*valid_save_time_indices2;
83  valid_save_time_indices = find(valid_save_time_indices);
84  save_time_index = zeros(1,model.nt+1);
85  save_time_index(model.save_time_indices(valid_save_time_indices)+1) = 1;
86  save_time_indices = find(save_time_index==1)-1;
87 else
88  save_time_index = ones(1,model.nt+1);
89  save_time_indices = 1:(model.nt+1);
90 end
91 
92 time_indices = zeros(1,length(save_time_indices));
93 time = zeros(1,length(save_time_indices));
94 t_column = 1; % next column index to be filled in output
95 t_ind = t_ind_start; % t_ind between 0 and nt
96 if model.want_dual % dual case
97  t = model.T-model.t; % backwards time between T and 0
98 else % primal case
99  t = model.t; % absolute time between 0 and T
100 end
101 
102 model.nt = t_ind_stop-t_ind_start+1;
103 
104 % initial values and preallocation
105 if model.want_dual
106  % in the dual case the riesz-representant of the functional is part of
107  % the initail values (this will be modified in the later first timestep)
108  [Ut, ~] = model.operators_output(model,model_data);
109  U = zeros(length(Ut),length(save_time_indices));
110 else % primal case
111  Ut = model.init_values_algorithm(model,model_data);
112  U = zeros(length(Ut),length(save_time_indices));
113 end
114 
115 operators_required = 1;
116 
117 % get operator components
118 if model.affinely_decomposed
119  old_decomp_mode = model.decomp_mode;
120  model.decomp_mode = 1;
121  if model.want_dual %dual
122  [~, ~, ~, L_I_comp, L_E_comp] = ...
123  model.operators_ptr(model, model_data);
124  else %primal
125  [L_I_comp, L_E_comp, b_comp] = model.operators_ptr(model, model_data);
126  end
127  model.decomp_mode = old_decomp_mode;
128 end
129 
130 % store init data
131 if save_time_index(t_ind+1)
132  time_indices(t_column) = t_ind;
133  time(t_column) = t;
134  % in the dual case it is Ut = -L_I^(-1)*v_l.
135  % this is performed later, when L_I is available
136  if model.want_dual == 0 %primal
137  U(:,t_column) = Ut;
138  t_column = t_column + 1;
139  end
140 end
141 
142 if ~isfield(model,'compute_output_functional')
143  model.compute_output_functional = 0;
144 end,
145 
146 
147 % loop over fv-steps
148 for t_ind = (t_ind_start):(t_ind_stop-1)
149 
150  % set the time - relevant if your operators are dependant on time.
151  if model.want_dual == 0
152  model.t = (t_ind)*model.dt; % forward time in primal case
153  else
154  model.t = model.T - (t_ind)*model.dt; % the backwards time in dual case
155  end
156 
157  if model.verbose >= 10
158  disp(['entered time-loop step ',num2str(t_ind)]);
159  end
160  if model.verbose == 9
161  fprintf('.');
162  end
163 
164  % get matrices and bias-vector
165  if operators_required
166 
167  model.t = t;
168 
169  % new assembly in every iteration
170  if ~model.affinely_decomposed
171  % model.decomp_mode is 0 here
172  if model.want_dual %dual
173  [~, ~, ~, L_I, L_E] = model.operators_ptr(model, model_data);
174  else %primal
175  [L_I, L_E, b] = model.operators_ptr(model, model_data);
176  end
177 
178  else
179  % or simple assembly based on affine parameter decomposition test affine decomposition
180  if model.debug
181  disp('test affine decomposition of operators')
182  test_affine_decomp(model.operators_ptr,3,1,model,model_data);
183  disp('OK')
184  end;
185 
186  model.decomp_mode = 2;
187  if model.want_dual %dual
188  [~, ~, ~, L_I_coeff, L_E_coeff] = ...
189  model.operators_ptr(model, model_data);
190  L_I = lincomb_sequence(L_I_comp, L_I_coeff);
191  L_E = lincomb_sequence(L_E_comp, L_E_coeff);
192  else %primal
193  [L_I_coeff, L_E_coeff, b_coeff] = ...
194  model.operators_ptr(model, model_data);
195  L_I = lincomb_sequence(L_I_comp, L_I_coeff);
196  L_E = lincomb_sequence(L_E_comp, L_E_coeff);
197  b = lincomb_sequence(b_comp, b_coeff);
198  end
199  model.decomp_mode = old_decomp_mode;
200  end
201 
202  if model.data_const_in_time
203  operators_required = 0;
204  end
205 
206  end % if operators required
207 
208 % in the dual case it is Ut = -L_I^(-1)*v_l in the first timestep
209 if t_ind == t_ind_start && model.want_dual
210  if strcmp(model.name_output_functional, 'theta') == 1
211  v_l = Ut; % save v_l the riesz-representant in the theta case because it is required in the next timestep
212  end
213  Ut = - L_I \ Ut;
214  U(:,t_column) = Ut;
215  t_column = t_column + 1;
216 end
217 
218 %computing the right-hand-side
219 if model.want_dual % dual
220  if strcmp(model.name_output_functional, 'theta') == 1 && t_ind == t_ind_start
221  rhs = L_E * Ut + v_l;
222  else
223  rhs = L_E * Ut;
224  end
225 else % primal
226  rhs = L_E * Ut + b;
227 end
228 %computing the solution
229 if isequal(L_I, speye(size(L_I))) || (model.want_dual && t_ind == t_ind_stop-1) %should fix the last timestep in the dual case
230  Ut = rhs;
231 else
232  Ut = L_I \ rhs;
233 end
234 
235 if save_time_index(t_ind+2)
236  U(:,t_column) = Ut;
237  time_indices(t_column) = t_ind;
238  time(t_column) = t;
239  t_column = t_column + 1;
240 end
241 
242 end %end of for-loop
243 
244 if model.verbose == 9
245  fprintf('\n');
246 end
247 
248 % output
249 sim_data.U = U;
250 sim_data.time = time;
251 sim_data.time_indices = time_indices;
252 
253 % only in the primal case an output does make sense
254 if isfield(model,'name_output_functional') && model.want_dual == 0
255 
256 % compute the riesz-representant of the functional
257  [v, ~] = model.operators_output(model, model_data);
258 
259 % the theta case is treated seperatly. See eop_theta_functional.
260  if strcmp(model.name_output_functional, 'theta') == 1
261  y = eop_theta_functional(sim_data.U, v);
262  sim_data.y = y(:);
263  else
264  sim_data.y = (v(:)') * U;
265  end
266 end
function r = verbose(level, message, messageId)
This function displays messages depending on a message-id and/or a level. Aditionally you can set/res...
Definition: verbose.m:17
function y = eop_theta_functional(U, v)
sim_data.y = eop_theta_functional(sim_data.U, v)
function sim_data = lin_evol_detailed_simulation_primal_dual(model, model_data)
sim_data = lin_evol_detailed_simulation_primal_dual(model, model_data)