4 % copy of lin_evol_detailed_simulation but extended to a primal/dual
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).
11 % see lin_ds_detailed_simulation
for a description on the time indices
13 % required fields of model:
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
30 %
return fields of sim_data:
31 % U : sequence of DOF vectors
32 % y : sequence of output functional values (
if activated)
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
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.
45 % Bernard Haasdonk 27.8.2009
47 % primal/dual formulation by Dominik Garmater 20.07 2012
51 if ~isfield(model,
'want_dual')
56 disp('entered detailed simulation ');
59 if isempty(model_data)
60 model_data = gen_model_data(model);
63 model.decomp_mode = 0; % == complete;
65 model.dt = model.T/model.nt;
67 %Fixing values for t-partition
68 if ~isfield(model,'starting_time_step')
71 t_ind_stop = model.nt;
73 t_ind_start = model.starting_time_step;
74 t_ind_stop = model.stopping_time_step;
75 model.t = (t_ind_start)*model.dt;
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;
88 save_time_index = ones(1,model.nt+1);
89 save_time_indices = 1:(model.nt+1);
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
99 t = model.t; % absolute time between 0 and T
102 model.nt = t_ind_stop-t_ind_start+1;
104 % initial values and preallocation
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));
111 Ut = model.init_values_algorithm(model,model_data);
112 U = zeros(length(Ut),length(save_time_indices));
115 operators_required = 1;
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);
125 [L_I_comp, L_E_comp, b_comp] = model.operators_ptr(model, model_data);
127 model.decomp_mode = old_decomp_mode;
131 if save_time_index(t_ind+1)
132 time_indices(t_column) = t_ind;
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
138 t_column = t_column + 1;
142 if ~isfield(model,'compute_output_functional')
143 model.compute_output_functional = 0;
148 for t_ind = (t_ind_start):(t_ind_stop-1)
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
154 model.t = model.T - (t_ind)*model.dt; % the backwards time in dual case
158 disp(['entered time-loop step ',num2str(t_ind)]);
164 % get matrices and bias-vector
165 if operators_required
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);
175 [L_I, L_E, b] = model.operators_ptr(model, model_data);
179 % or simple assembly based on affine parameter decomposition test affine decomposition
181 disp('test affine decomposition of operators')
182 test_affine_decomp(model.operators_ptr,3,1,model,model_data);
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);
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);
199 model.decomp_mode = old_decomp_mode;
202 if model.data_const_in_time
203 operators_required = 0;
206 end % if operators required
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
215 t_column = t_column + 1;
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;
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
235 if save_time_index(t_ind+2)
237 time_indices(t_column) = t_ind;
239 t_column = t_column + 1;
250 sim_data.time = time;
251 sim_data.time_indices = time_indices;
253 % only in the primal case an output does make sense
254 if isfield(model,'name_output_functional') && model.want_dual == 0
256 % compute the riesz-representant of the functional
257 [v, ~] = model.operators_output(model, model_data);
260 if strcmp(model.name_output_functional, 'theta') == 1
264 sim_data.y = (v(:)') * U;
function r = verbose(level, message, messageId)
This function displays messages depending on a message-id and/or a level. Aditionally you can set/res...
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)