rbmatlab  1.16.09
 All Classes Namespaces Files Functions Variables Modules Pages
nonlin_evol_rb_simulation.m
1 function simulation_data = nonlin_evol_rb_simulation(model, reduced_data)
2 %function simulation_data = nonlin_evol_rb_simulation(model, reduced_data)
3 %
4 % function, which performs a reduced basis online simulation for
5 % the parameter vector mu, which is assumed to be set in the model
6 % struct, i.e. a previous model = model.set_mu(model, [...]) is assumed
7 % to have taken place.
8 %
9 % allowed dependency of data: Nmax, Mmax, N, M, mu
10 % not allowed dependency of data: H
11 % allowed dependency of computation: Nmax, Mmax, N, M, mu
12 % not allowed dependency of computation: H
13 % Unknown at this stage: ---
14 %
15 % Required fields of model as required by the numerical operators and
16 % mu_names : the cell array of names of mu-components and
17 % for each of these stringt, a corresponding
18 % field in model is expected.
19 % T : end-time of simulation
20 % nt : number of timesteps to compute
21 % L_E_local_name : name of the local space-discretization operator
22 % evaluation with syntax
23 %
24 % INC_local = L_local(U_local_ext, ind_local,
25 % grid_local_ext, model)
26 % where *_local indicates results on a set of
27 % elements, *_local_ext includes information including
28 % their neighbours, i.e. the grid must be known
29 % also for the neighbours, the values of the
30 % previous timstep must be known on the
31 % neighbours. The subset of elements, which are
32 % to be computed are given in ind_local and the
33 % values produced are INC_local.
34 % Subsequent time-step operator would be defined
35 % as NU_local = U(ind_local) - dt * INC_local
36 % rb_operators : function pointer to a method assembling the decomposed
37 % discretization operators
38 %
39 % optional fields of model:
40 % data_const_in_time : if this flag is set, then only operators
41 % for first time instance are computed
42 %
43 % generated fields of simulation_data:
44 % a(:,k) : coefficient vector of the reduced
45 % simulation at time t^{k-1}
46 %
47 % see the rb_***_online_prep() routine for specifications of the
48 % fields of reduced_data
49 
50 % Bernard Haasdonk 15.5.2007
51 
52 if nargin ~= 2
53  error('wrong number of arguments: should be 2');
54 end
55 
56 %% compute a posteriori error estimator (c.f. diploma thesis Martin Drohmann
57 % p. 26ff.)
58 if ~isfield(model,'enable_error_estimator')
59  model.enable_error_estimator = 0;
60  model.Mstrich = 0;
61 end
62 
63 if model.verbose >= 10
64  disp(['performing simulation for mu = ',mat2str(get_mu(model))]);
65 end;
66 
67 if ~isfield(model, 'Mstrich')
68  model.Mstrich = 0;
69 end
70 
71 if model.enable_error_estimator && model.Mstrich == 0;
72  error('If error estimator is enabled, model.Mstrich must be > 0');
73 end
74 
75 % possibly shrink reduced_data detected by this routine
76 reduced_data = nonlin_evol_reduced_data_subset(model,reduced_data);
77 
78 % set init data
79 model.decomp_mode = 2;
80 
81 sa0 = model.rb_init_values(model,[]);
82 a0 = lincomb_sequence(reduced_data.a0,sa0);
83 
84 % perform simulation loop in time
85 model.dt = model.T/model.nt;
86 a = zeros(model.N,model.nt+1); % matrix of RB-coefficients
87 a(:,1) = a0;
88 
89 % in case of velocity-file access, the correct filename must be set here
90 % the following is only relevant in case of use of a
91 % model.use_velocitymatrix_file and filecaching mode 2
92 if model.filecache_velocity_matrixfile_extract == 2;
93  % change global velocity file to MMax velocity file generated in offline
94  model.velocity_matrixfile = ...
95  ['M',num2str(model.M(1)),'_','gridpart_Mmax',num2str(model.Mmax),'_',...
96  model.velocity_matrixfile];
97 end
98 
99 %disp('temporary true mass matrix is considered');
100 %M = reduced_data.M;
101 
102 reduced_data.CE = {};
103 
104 crbInd_imp = reduced_data.implicit_crb_index;
105 crbInd_exp = reduced_data.explicit_crb_index;
106 
107 Mstrich = model.Mstrich;
108 M = model.M;
109 % M plus Mstrich
110 MM = M + Mstrich;
111 
112 if model.enable_error_estimator
113  % Lipschitz constants
114  if ~isfield(model, 'C_E')
115  C_E = 1;
116  else
117  C_E = model.C_E;
118  end
119  if ~isfield(model, 'C_I')
120  C_I = 1;
121  else
122  C_I = model.C_I;
123  end
124  % initialize error estimator
125  Delta = 0;
126  % initialize error estimator log (strictly increasing)
127  Deltalog = zeros(1, model.nt-1);
128  % initialize log of residuum for each time step
129  reslog = zeros(1, model.nt-1);
130  % initialize part for ei estimation for each time step
131  eilog = zeros(1, model.nt-1);
132  % initialize part for newton error for each time step
133  newtonlog = zeros(1, model.nt);
134 end
135 
136 if model.separate_CRBs
137 % Mimpl = min([M+Mstrich, length(reduced_data.TM_local{crbInd_imp})]);
138  Mexpl = cellfun(@length, reduced_data.TM_local(crbInd_exp,:));
139  Mexpl = arrayfun(@(a,b) min(a,b), MM, Mexpl);
140 else
141  Mimpl = cellfun(@length, reduced_data.TM_local(crbInd_exp,:));
142  Mimpl = arrayfun(@(a,b) min(a,b), MM, Mimpl);
143  Mexpl = Mimpl;
144 end
145 
146 % model for explicit part (has different affine decomposition)
147 emodel = model;
148 emodel.decomp_mode = 0;
149 emodel.M = Mexpl;
150 
151 if strcmp(model.RB_error_indicator, 'estimator') || ...
152  strcmp(model.RB_error_indicator, 'ei_estimator_test')
153  Mred_expl = min(M, Mexpl);
154  Mred_impl = min(M, Mimpl);
155 else
156  Mred_expl = Mexpl;
157  Mred_impl = Mimpl;
158 end
159 
160 reduced_data.CE = cell(size(reduced_data.DE));
161 reduced_data.CE_red = cell(size(reduced_data.DE));
162 for i=1:length(reduced_data.DE(:))
163  reduced_data.CE{i} = reduced_data.DE{i} / ...
164  reduced_data.BM{i};
165  reduced_data.CE_red{i} = reduced_data.DE{i}(:,1:Mred_impl(i)) ...
166  / reduced_data.BM{i}(1:Mred_impl(i), 1:Mred_impl(i));
167 end
168 
169 if ~isfield(reduced_data, 'time_split_map')
170  reduced_data.time_split_map = [(1:model.nt+1)', ones(model.nt+1,1)];
171 end
172 
173 %ll_E = zeros(Mexpl, model.nt); % matrix of RB-coefficients
174 % loop over time steps: computation of a(t+1)==a^t
175 for t = 1:model.nt % either 1 or model.nt
176  model.t = (t-1)*model.dt;
177  emodel.t = model.t;
178  emodel.tstep = t;
179  if model.verbose >= 10
180  disp(['entered time-loop step ',num2str(t)]);
181  end;
182 
183  ti = reduced_data.time_split_map(t,2);
184  tii = reduced_data.time_split_map(t+1,2);
185 
186  % asssemble affine parameter compositions of implicit parts
187  % only once, if data is const in time
188  if ~model.newton_solver && ((t==1) || (~model.data_const_in_time))
189  if model.implicit_nonlinear
190  reduced_data.grid = reduced_data.grid_local_ext{crbInd_imp,tii};
191  tmpmodel = model;
192  tmpmodel.decomp_mode = 0;
194  [L_I_red, b_I_red] = ...
195  model.implicit_operators_algorithm(tmpmodel, reduced_data,...
196  reduced_data.TM_local{crbInd_imp,tii});
198 
199  LL_I_red = L_I_red * reduced_data.RB_local_ext{crbInd_imp,tii};
200  LL_I = reduced_data.CE{crbInd_imp,tii}(:,1:Mred_impl(tii)) * ...
201  LL_I_red;
202 
203  bb_I = reduced_data.CE{crbInd_imp,tii}(:,1:Mred_impl(tii)) * ...
204  b_I_red;
205 
206  else
207  [sLL_I, sbb_I] = ...
208  model.rb_operators(model,[]); % detailed_data omitted
209  if ~isempty(reduced_data.LL_I)
210  LL_I = lincomb_sequence(reduced_data.LL_I,sLL_I);
211  else
212  LL_I = sparse([],[],[],model.N,model.N);
213  end;
214  if ~isempty(reduced_data.bb_I)
215  bb_I = lincomb_sequence(reduced_data.bb_I,sbb_I);
216  else
217  bb_I = sparse([],[],[],model.N,1);
218  end;
219  end;
220  end;
221 
222  % setup linear system A * a(:,t+1) = rhs
223  % with A = Id + dt * LL_I
224  % rhs = a(:,t) - dt * BB_I - dt * CE * ll_E(a(:,t))
225  % where ll_E is the local operator evaluation
226 
227  if ~model.newton_solver
228  A = LL_I * model.dt + speye(size(LL_I));
229  else
230  A = 0;
231  bb_I = 0;
232  end
233 
234  % determine local values by reconstructing U values from reduced
235  % basis parts
236  U_local_ext = reduced_data.RB_local_ext{crbInd_exp,ti} * a(:,t);
237 
238  % the following performs
239  % U_local = L_local(U_local_ext, TM_local, [], ...
240  % reduced_data.grid_local_ext);
241  %
242  % note the use of emodel
243  reduced_data.grid = reduced_data.grid_local_ext{crbInd_exp,ti};
244 
245  le_local_inc = emodel.L_E_local_ptr(emodel, reduced_data, ...
246  U_local_ext, ...
247  reduced_data.TM_local{crbInd_exp,ti});
248 % le_local_inc(U_local_ext(reduced_data.TM_local{crbInd_exp,tii}) + le_local_inc > 1) = 0;
249 
250  if model.newton_solver
251  nmax = -1;
252  updelta_a = zeros(model.N, model.newton_steps+1);
253  updelta_a(:,1) = a(:,t);
254  n=0;
255 
256  for n=1:model.newton_steps
257  if model.verbose > 10
258  disp(['Computing time step no. ', num2str(t), ...
259  ', Newton step no. ', num2str(n), ...
260  '... Residual norm: ']);
261  end
262  model.decomp_mode = 0;
263  updelta_rec = reduced_data.RB_local_ext{crbInd_imp,tii} * updelta_a(:,n);
264  if model.debug && any(updelta_rec < -10*eps)
265  disp(num2str(min(updelta_rec)));
266  warning('RBMatlab:rb_simulation:runtime', ...
267  'reconstructed solutions at interpolation points is negative!');
268  end
269  model.t = model.t + model.dt;
270  % updelta_rec(updelta_rec < 0) = 0.001;
271  reduced_data.grid = reduced_data.grid_local_ext{crbInd_imp,tii};
272  li_local_inc = model.L_I_local_ptr(model, reduced_data, ...
273  updelta_rec, ...
274  reduced_data.TM_local{crbInd_imp,tii});
275 
276  [gradL_I, gL_I_offset] = ...
277  model.implicit_gradient_operators_algorithm(model, reduced_data, ...
278  updelta_rec,...
279  reduced_data.TM_local{crbInd_imp,tii}(1:Mred_impl(tii)));
280  model.t = model.t - model.dt;
281  if any(gL_I_offset ~= 0)
282  warning('offset has non-zero entries!');
283  end
284 
285  gradL_I = reduced_data.CE_red{crbInd_imp,tii} * gradL_I ...
286  * reduced_data.RB_local_ext{crbInd_imp,tii};
287 
288  gradL_I = gradL_I * model.dt + speye(size(gradL_I));
289 
290  opts.LT = true;
291 
292  if t==1 || ti ~= tii
293  theta_update_expl = linsolve(reduced_data.BM{crbInd_exp,ti}(1:MM(ti),1:MM(ti)), ...
294  le_local_inc(1:MM(ti)), ...
295  opts);
296  theta_update_impl = linsolve(reduced_data.BM{crbInd_imp,tii}(1:MM(tii),1:MM(tii)), ...
297  li_local_inc(1:MM(tii)), ...
298  opts);
299 
300 % minlength = min(length(theta_update_impl), length(theta_update_expl));
301 % theta_update = theta_update_expl(1:minlength) + theta_update_impl(1:minlength);
302 
303  arhs = reduced_data.DE{crbInd_exp,ti}(:,1:Mred_expl(ti)) ...
304  * theta_update_expl(1:Mred_expl(ti)) ...
305  + reduced_data.DE{crbInd_imp,tii}(:,1:Mred_impl(tii)) ...
306  * theta_update_impl(1:Mred_impl(tii));
307  else
308  theta_update = linsolve(reduced_data.BM{crbInd_exp,ti}(1:MM(ti),1:MM(ti)), ...
309  le_local_inc(1:MM(ti)) + li_local_inc(1:MM(ti)), ...
310  opts);
311 
312  arhs = reduced_data.DE{crbInd_exp,ti}(:,1:Mred_expl(ti)) ...
313  * theta_update(1:Mred_expl(ti));
314  end
315 
316  full_rhs = - updelta_a(:,n) + a(:,t) - model.dt * arhs;
317 
318  delta_a = gradL_I \ full_rhs;
319 
320  updelta_a(:,n+1) = updelta_a(:,n) + delta_a;
321  nres_a = updelta_a(:,n+1) -a(:,t) + model.dt * arhs;
322  nres = sqrt(nres_a' * nres_a);
323  if model.verbose > 10
324  disp(num2str(nres));
325  end
326  if nres < model.newton_epsilon
327  nmax = max(nmax, n);
328  break;
329  end
330  end
331  a(:,t+1) = updelta_a(:,n+1);
332  else
333  % compute coefficients of update in CRB Space `\W_{M+M'}`.
334  opts.LT = true;
335  theta_update_expl = linsolve(reduced_data.BM{crbInd_exp,ti}(1:MM(ti),1:MM(ti)), ...
336  le_local_inc, opts);
337  theta_update_impl = 0;
338 
339  rhs = a(:,t) - model.dt * bb_I ...
340  - model.dt * reduced_data.DE{crbInd_exp,ti}(:,1:Mred_expl(ti)) ...
341  * theta_update_expl(1:Mred_expl(ti));
342 
343  % check if an LES is to be solved, or problem is an explicit problem
344  if isequal(A, speye(size(A)))
345  a(:,t+1) = rhs;
346  else
347  % solve linear system without Newton solver
348 % disp('check symmetry and choose solver accordingly!');
349 % keyboard;
350  % nonsymmetric solvers:
351  [a(:,t+1), flag, relres, iter] = bicgstab(A,rhs,1e-10,1000);
352  % [a(:,t+1), flag] = cgs(Li,rhs,[],1000);
353  % symmetric solver, non pd:
354  % see bug_symmlq for a very strange bug: cannot solve identity system!
355  % [a(:,t+1), flag] = symmlq(Li,rhs,[],1000);
356  % [a(:,t+1), flag] = minres(Li,rhs,[],1000);
357  % symmetric solver, pd:
358  %[a(:,t+1), flag] = bicgstab(A,rhs,[],1000);
359  if(t==1 && model.debug)
360  disp(cond(A));
361  disp(all(A'==A));
362  disp(eig(full(A)));
363  end
364  if(t==1) % && model.verbose > 10)
365  disp(['relres=', num2str(relres), ' iter=', num2str(iter)]);
366  end
367  % exact solver:
368  % a(:,t+1)=A \ rhs;
369  if flag>0
370  disp(['error in system solution, solver return flag = ', ...
371  num2str(flag)]);
372  keyboard;
373  end
374  end
375  end
376 
377  if model.enable_error_estimator
378  if tii > 2
379  error('error estimator does not work with varying crbs for different time slices yet');
380  end
381  ainc = a(:,t) - a(:,t+1);
382  theta_update = theta_update_expl + theta_update_impl;
383 
384  if model.newton_solver
385  lipschitzConst = C_I^(model.nt - t + 2)*C_E^(model.nt - t + 1);
386  newtonlog(t) = nres + model.newton_epsilon;
387  else
388  lipschitzConst = C_E^(model.nt - t + 1);
389  end
390  % compute the residuum `\delta t norm(R^k)`
391  % TODO revise the following
392  residuum = sqrt( abs( ainc' * ainc ...
393  - 2*model.dt * ainc' ...
394  * ( reduced_data.DE{crbInd_exp,ti}(:,1:M(ti)) ...
395  * theta_update(1:M(ti)) ...
396  + reduced_data.DE{crbInd_imp,ti}(:,1:M(ti)) ...
397  * theta_update(1:M(ti)) ) ...
398  + model.dt^2 * theta_update(1:M(ti))' ...
399  * reduced_data.Mmass{1,ti}(1:M(ti),1:M(ti)) ...
400  * theta_update(1:M(ti))) );
401  reslog(t) = residuum;
402 
403  % compute the empirical interpolation error estimation
404  eilog(t) = model.dt*lipschitzConst ...
405  * sqrt(abs( ...
406  theta_update(M(tii)+1:MM(tii))' ...
407  * reduced_data.Mmass{1,tii}(M(tii)+1:MM(tii),M(tii)+1:MM(tii)) ...
408  * theta_update(M(tii)+1:MM(tii)) ));
409 
410  Delta = Delta + eilog(t) ...
411  + lipschitzConst*newtonlog(t) ...
412  + lipschitzConst*residuum;
413  if ~isreal(Delta)
414  warning('RBMatlab:rb_simulation:runtime',...
415  'error estimator returned complex result');
416  Delta = real(Delta);
417  end
418  Deltalog(t) = Delta;
419  end
420 end; % timeloop
421 
422 if model.newton_solver && model.verbose > 0
423  disp(['computation ready: We needed at most ', num2str(nmax), ' Newton steps']);
424 end
425 
426 if model.enable_error_estimator
427  simulation_data.Delta = [0, Deltalog];
428  simulation_data.reslog = [0, reslog];
429  simulation_data.eilog = [0, eilog];
430 end
431 
432 % prepare return parameters
433 simulation_data.a = a;
434 %| \docupdate
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 reduced_data_subset = nonlin_evol_reduced_data_subset(model, reduced_data)
method which modifies reduced_data, which is the data, that will be passed to the online-simulation a...
function [ descr , rdescr , dmodel , rmodel ] = newton(steps, combined, M_by_N_ratio, noof_ei_extensions, use_laplacian, model_size, random, num_cpus, Mstrich)
small script demonstrating a buckley leverett problem discretization and RB model reduction ...
Definition: newton.m:17
function clear_all_caches()
This function clears the caches generated for caching of gradient data in evolution schemes...