1 function rb_sim_data = rb_simulation_impl(rmodel, reduced_data)
2 %
function rb_sim_data = rb_simulation_impl(rmodel, reduced_data)
3 %
function, which performs a reduced basis online simulation
for
4 % the parameter vector `\mu \in {\cal P} \subset \mathbb{R}^p`, which is
7 % - allowed dependency of data: Nmax, Mmax, N, M, mu
8 % - not allowed dependency of data: H
9 % - allowed dependency of computation: Nmax, Mmax, N, M, mu
10 % - not allowed dependency of computation: H
11 % - Unknown at
this stage: ---
13 % The behaviour of
this simulation is controlled by the
ModelDescr structure
19 % Required fields of descr:
20 % mu_names : the cell array of names of mu-components and
21 %
for each of these stringt, a corresponding
22 % field in model is expected.
23 % T : end-time of simulation
24 % nt : number of timesteps to compute
25 % L_E_local_name : name of the local space-discretization
operator
26 % evaluation with syntax
28 % INC_local = L_local(U_local_ext, ind_local,
29 % grid_local_ext, model)
@endcode
30 % where
'*_local' indicates results on a set of
31 % elements,
'*_local_ext' includes information including
32 % their neighbours, i.e. the grid must be known also
for the
33 % neighbours, the values of the previous timstep must be
34 % known on the neighbours. The subset of elements, which are
35 % to be computed are given in ind_local and the values
36 % produced are
'INC_local'.
37 % Subsequent time-step operator would be defined
38 % as 'NU_local = U(ind_local) - dt * INC_local'
39 % rb_operators : function pointer to a method assembling the decomposed
40 % discretization operators
42 % optional fields of model:
43 % data_const_in_time : if this flag is set, then only operators
44 % for first time instance are computed
46 % generated fields of rb_sim_data:
47 % a : 'a(:,k)' is the coefficient vector of the reduced simulation at time
51 % Bernard Haasdonk 15.5.2007
54 error(
'wrong number of arguments: should be 2');
57 if rmodel.compute_conditions
58 LIconds = zeros(1, rmodel.descr.nt);
62 %% compute a posteriori error estimator (c.f. diploma thesis Martin Drohmann
64 if ~rmodel.enable_error_estimator
68 if rmodel.verbose >= 10
69 disp([
'performing simulation for mu = ',mat2str(get_mu(rmodel))]);
72 if ~isfield(rmodel,
'filecache_velocity_matrixfile_extract')
73 filecache_velocity_matrixfile_extract = 0;
75 filecache_velocity_matrixfile_extract = rmodel.filecache_velocity_matrixfile_extract;
79 rmodel.decomp_mode = 2;
81 sa0 = rb_init_values(rmodel,[], 2);
83 a0 = lincomb_sequence(reduced_data.a0, sa0);
88 % perform simulation loop in time
89 model.dt = model.T/model.nt;
90 a = zeros(rmodel.N, model.nt+1); % matrix of RB-coefficients
93 % in case of velocity-file access, the correct filename must be set here
94 % the following is only relevant in case of use of a
95 % model.use_velocitymatrix_file and filecaching mode 2
96 if filecache_velocity_matrixfile_extract == 2;
97 % change global velocity file to MMax velocity file generated in offline
98 rmodel.descr.velocity_matrixfile = ...
99 ['M',num2str(model.M(1)),'_','gridpart_Mmax',num2str(model.Mmax),'_',...
100 model.velocity_matrixfile];
103 %disp('temporary true mass matrix is considered');
106 if rmodel.enable_error_estimator
107 % Lipschitz constants
108 if ~isfield(model, 'C_E')
113 if ~isfield(model, 'C_I')
118 % initialize error estimator
120 % initialize error estimator log (strictly increasing)
121 Deltalog = zeros(1, model.nt-1);
122 % initialize log of residuum for each time step
123 reslog = zeros(1, model.nt-1);
124 % initialize part for ei estimation for each time step
125 eilog = zeros(1, model.nt-1);
126 % initialize part for
newton error for each time step
127 newtonlog = zeros(1, model.nt);
131 datanode_mode = true;
133 datanode_mode = false;
136 Mstrich = rmodel.Mstrich;
137 M = get_current_M(rmodel);
144 % model for explicit part (has different affine decomposition)
146 emodel.decomp_mode = 0;
148 % loop over time steps: computation of a(t+1)==a^t
150 model.t = (t-1)*model.dt;
154 disp(['entered time-loop step ',num2str(t)]);
157 % update reduced data for operators if necessary.
160 rmodel.tstep = emodel.tstep;
161 [expl_reduced_data, expl_tstop, Mexpl, Mred_expl]...
162 = get_reduced_data_for_operator('explicit', rmodel, reduced_data, datanode_mode);
164 rmodel.tstep = model.tstep;
170 rmodel.tstep = imodel.tstep;
171 [impl_reduced_data, impl_tstop, Mimpl, Mred_impl]...
172 = get_reduced_data_for_operator('implicit', rmodel, reduced_data, datanode_mode);
174 rmodel.tstep = model.tstep;
177 % asssemble affine parameter compositions of implicit parts
178 % only once, if data is const in time
179 if ~model.newton_solver && ((t==1) || (~model.data_const_in_time))
180 if model.implicit_nonlinear
182 tmpmodel.decomp_mode = 0;
184 [L_I_red, b_I_red] = ...
185 model.implicit_operators_algorithm(tmpmodel, impl_reduced_data,...
186 impl_reduced_data.TM_local); % tii
189 LL_I_red = L_I_red * impl_reduced_data.RB_local_ext; % tii
190 LL_I = impl_reduced_data.CE(:,1:Mred_impl) * ... % tii
193 bb_I = impl_reduced_data.CE(:,1:Mred_impl) * ...
198 NonlinEvol.ReducedData.rb_operators(rmodel,[], 2); % detailed_data omitted
199 if ~isempty(reduced_data.LL_I)
200 LL_I = lincomb_sequence(reduced_data.LL_I,sLL_I);
202 LL_I = sparse([],[],[],rmodel.N,rmodel.N);
204 if ~isempty(reduced_data.bb_I)
205 bb_I = lincomb_sequence(reduced_data.bb_I, sbb_I);
207 bb_I = sparse([],[],[],rmodel.N,1);
212 % setup linear system A * a(:,t+1) = rhs
213 % with A = Id + dt * LL_I
214 % rhs = a(:,t) - dt * BB_I - dt * CE * ll_E(a(:,t))
215 % where ll_E is the local operator evaluation
217 if ~model.newton_solver
218 A = LL_I * model.dt + speye(size(LL_I));
219 if rmodel.compute_conditions
220 LIconds(t) = condest(A);
227 % determine local values by reconstructing U values from reduced
229 U_local_ext = expl_reduced_data.RB_local_ext * a(:,t); % ti
231 % the following performs
232 % U_local = L_local(U_local_ext, TM_local, [], ...
233 % reduced_data.grid_local_ext);
235 % note the use of emodel
237 le_local_inc = emodel.L_E_local_ptr(emodel, expl_reduced_data, ...
239 expl_reduced_data.TM_local); % ti
240 % le_local_inc(U_local_ext(reduced_data.TM_local{crbInd_exp,tii}) + le_local_inc > 1) = 0;
242 if model.newton_solver
244 updelta_a = zeros(rmodel.N, model.newton_steps+1);
245 updelta_a(:,1) = a(:,t);
248 for n=1:model.newton_steps
249 if rmodel.verbose > 10
250 disp([
'Computing time step no. ', num2str(t), ...
251 ', Newton step no. ', num2str(n), ...
252 '... Residual norm: ']);
254 model.decomp_mode = 0;
255 updelta_rec = impl_reduced_data.RB_local_ext * updelta_a(:,n); % tii
256 if rmodel.debug && any(updelta_rec < -10*eps)
257 disp(num2str(min(updelta_rec)));
258 warning('RBMatlab:rb_simulation:runtime', ...
259 'reconstructed solutions at interpolation points is negative!');
261 model.t = model.t + model.dt;
262 % updelta_rec(updelta_rec < 0) = 0.001;
263 li_local_inc = model.L_I_local_ptr(model, impl_reduced_data, ...
265 impl_reduced_data.TM_local); % tii
267 [gradL_I, gL_I_offset] = ...
268 model.implicit_gradient_operators_algorithm(model, impl_reduced_data, ...
270 impl_reduced_data.TM_local(1:Mred_impl)); % tii
271 model.t = model.t - model.dt;
272 if any(gL_I_offset ~= 0)
273 warning('offset has non-zero entries!');
276 gradL_I = impl_reduced_data.CE_red * gradL_I ...
277 * impl_reduced_data.RB_local_ext;
279 gradL_I = gradL_I * model.dt + speye(size(gradL_I));
283 if impl_reduced_data ~= expl_reduced_data
284 theta_update_expl = linsolve(expl_reduced_data.BM(1:MM,1:MM), ...
285 le_local_inc(1:MM), ...
287 theta_update_impl = linsolve(impl_reduced_data.BM(1:MM,1:MM), ...
288 li_local_inc(1:MM), ...
291 arhs = expl_reduced_data.DE(:,1:Mred_expl) ...
292 * theta_update_expl(1:Mred_expl) ...
293 + impl_reduced_data.DE(:,1:Mred_impl) ...
294 * theta_update_impl(1:Mred_impl);
296 theta_update = linsolve(expl_reduced_data.BM(1:MM,1:MM), ...
297 le_local_inc(1:MM) + li_local_inc(1:MM), ...
300 arhs = expl_reduced_data.DE(:,1:Mred_expl) ...
301 * theta_update(1:Mred_expl);
304 full_rhs = - updelta_a(:,n) + a(:,t) - model.dt * arhs;
306 delta_a = gradL_I \ full_rhs;
308 if rmodel.compute_conditions
309 gradLIconds = [gradLIconds, condest(gradL_I)];
312 updelta_a(:,n+1) = updelta_a(:,n) + delta_a;
313 nres_a = updelta_a(:,n+1) -a(:,t) + model.dt * arhs;
314 nres = sqrt(nres_a' * nres_a);
318 if nres < model.newton_epsilon
323 a(:,t+1) = updelta_a(:,n+1);
324 else % no
newton solver...
325 % compute coefficients of update in CRB Space `\W_{M+M'}`.
327 theta_update_expl = linsolve(expl_reduced_data.BM(1:MM,1:MM), ...
329 theta_update = theta_update_expl;
331 rhs = a(:,t) - model.dt * bb_I ...
332 - model.dt * expl_reduced_data.DE(:,1:Mred_expl) ...
333 * theta_update_expl(1:Mred_expl);
335 % check
if an LES is to be solved, or problem is an
explicit problem
336 if isequal(A, speye(size(A)))
339 % disp('check symmetry and choose solver accordingly!');
341 % nonsymmetric solvers:
342 [a(:,t+1), flag, relres, iter] = bicgstab(A,rhs,1e-10,1000);
343 % [a(:,t+1), flag] = cgs(Li,rhs,[],1000);
344 % symmetric solver, non pd:
345 % see bug_symmlq for a very strange bug: cannot solve identity system!
346 % [a(:,t+1), flag] = symmlq(Li,rhs,[],1000);
347 % [a(:,t+1), flag] = minres(Li,rhs,[],1000);
348 % symmetric solver, pd:
349 %[a(:,t+1), flag] = bicgstab(A,rhs,[],1000);
350 if(t==1 && model.debug)
355 if(t==1) % && model.
verbose > 10)
356 disp(['relres=', num2str(relres), ' iter=', num2str(iter)]);
361 disp(['error in system solution, solver return flag = ', ...
368 if rmodel.enable_error_estimator
369 if ~isinf(impl_tstop)
370 error('error estimator does not work with varying crbs for different time slices yet');
372 ainc = a(:,t) - a(:,t+1);
374 if model.newton_solver
375 lipschitzConst = C_I^(model.nt - t + 2)*C_E^(model.nt - t + 1);
376 newtonlog(t) = nres + model.newton_epsilon;
378 lipschitzConst = C_E^(model.nt - t + 1);
381 if impl_reduced_data == expl_reduced_data
382 % note that in case of one basis for both operators all values are the
383 % same for both operators, i.e. Mexpl == Mimpl, impl_tstop == expl_tstop,
384 % expl_reduced_data.Mmass === impl_reduced_data.Mmass
386 % compute the residuum `\delta t norm(R^k)`
387 % TODO revise the following
388 residuum = sqrt( abs( ainc' * ainc ...
389 - 2*model.dt * ainc' ...
390 * ( expl_reduced_data.DE(:,1:Mexpl) ...
391 * theta_update(1:Mexpl) ) ...
392 + model.dt^2 * theta_update(1:Mexpl)' ...
393 * expl_reduced_data.Mmass(1:Mexpl,1:Mexpl) ...
394 * theta_update(1:Mexpl)) );
396 % theta_update = theta_update_expl + theta_update_impl;
397 error('residuum can only be computed for the case when _one_ reduced basis space for both operators has been computed.');
399 reslog(t) = residuum;
401 % compute the empirical interpolation error estimation
402 eilog(t) = model.dt*lipschitzConst ...
404 theta_update(M+1:MM)' ...
405 * impl_reduced_data.Mmass(M+1:MM,M+1:MM) ...
406 * theta_update(M+1:MM) ));
408 Delta = Delta + eilog(t) ...
409 + lipschitzConst*newtonlog(t) ...
410 + lipschitzConst*residuum;
412 warning('RBMatlab:rb_simulation:runtime',...
413 'error estimator returned complex result');
420 if model.newton_solver && rmodel.
verbose > 11
421 disp(['computation ready: We needed at most ', num2str(nmax), ' Newton steps']);
424 if rmodel.enable_error_estimator
425 rb_sim_data.Delta = [0, Deltalog];
426 rb_sim_data.reslog = [0, reslog];
427 rb_sim_data.eilog = [0, eilog];
430 % prepare return parameters
433 if rmodel.compute_conditions
434 rb_sim_data.conds.LI = LIconds;
435 rb_sim_data.conds.gradLI = gradLIconds;
440 function [reduced_data_op, tstop, Mop, Mred] = get_reduced_data_for_operator(
id, rmodel, reduced_data, datanode_mode)
443 % Mind = get_index(rmodel.M,
id, model.t);
444 Mind = get_index(rmodel.M,
id, get_mu(rmodel), rmodel.t);
445 M = get(rmodel.M, [Mind,1]);
449 MM = M + rmodel.Mstrich;
451 %crbInd = get_index(reduced_data,
id, rmodel);
452 crbInd = get_index(reduced_data,
id, get_mu(rmodel), rmodel.t);
453 reduced_data_op = get(reduced_data, crbInd);
454 tstop = index_valid_till(reduced_data, crbInd);
456 assert(Mop <= length(reduced_data_op.TM_local));
460 if isempty(reduced_data_op.CE) ...
461 || any(size(reduced_data_op.CE) ~= size(reduced_data_op.DE))
462 reduced_data_op.CE = reduced_data_op.DE / reduced_data_op.BM;
463 reduced_data_op.CE_red = reduced_data_op.DE(:,1:Mred) ...
464 / reduced_data_op.BM(1:Mred, 1:Mred);
function r = verbose(level, message, messageId)
This function displays messages depending on a message-id and/or a level. Aditionally you can set/res...
Reduced basis implementation for non-linear evolution equations.
function IDetailedModel this = set_mu(mu)
sets the active parameter vector
Struct with control fields for the analytical PDE functions, the discretization and the parametrizati...
This is the interface for a detailed model providing methods to compute high dimensional simulation s...
Reduced data implementation for non-linear evolution problems with finite volume discretizations.
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 ...
function clear_all_caches()
This function clears the caches generated for caching of gradient data in evolution schemes...