1 function simulation_data = nonlin_evol_rb_simulation(model, reduced_data)
2 %
function simulation_data = nonlin_evol_rb_simulation(model, reduced_data)
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
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: ---
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
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
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
43 % generated fields of simulation_data:
44 % a(:,k) : coefficient vector of the reduced
45 % simulation at time t^{k-1}
47 % see the rb_***_online_prep() routine for specifications of the
48 % fields of reduced_data
50 % Bernard Haasdonk 15.5.2007
53 error('wrong number of arguments: should be 2');
56 %% compute a posteriori error estimator (c.f. diploma thesis Martin Drohmann
58 if ~isfield(model,'enable_error_estimator')
59 model.enable_error_estimator = 0;
64 disp(['performing simulation for mu = ',mat2str(get_mu(model))]);
67 if ~isfield(model, 'Mstrich')
71 if model.enable_error_estimator && model.Mstrich == 0;
72 error('If error estimator is enabled, model.Mstrich must be > 0');
75 % possibly shrink reduced_data detected by this routine
79 model.decomp_mode = 2;
81 sa0 = model.rb_init_values(model,[]);
82 a0 = lincomb_sequence(reduced_data.a0,sa0);
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
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];
99 %disp('temporary true mass matrix is considered');
102 reduced_data.CE = {};
104 crbInd_imp = reduced_data.implicit_crb_index;
105 crbInd_exp = reduced_data.explicit_crb_index;
107 Mstrich = model.Mstrich;
112 if model.enable_error_estimator
113 % Lipschitz constants
114 if ~isfield(model,
'C_E')
119 if ~isfield(model, 'C_I')
124 % initialize error estimator
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);
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);
141 Mimpl = cellfun(@length, reduced_data.TM_local(crbInd_exp,:));
142 Mimpl = arrayfun(@(a,b) min(a,b), MM, Mimpl);
146 % model
for explicit part (has different affine decomposition)
148 emodel.decomp_mode = 0;
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);
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} / ...
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));
169 if ~isfield(reduced_data,
'time_split_map')
170 reduced_data.time_split_map = [(1:model.nt+1)', ones(model.nt+1,1)];
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;
180 disp(['entered time-loop step ',num2str(t)]);
183 ti = reduced_data.time_split_map(t,2);
184 tii = reduced_data.time_split_map(t+1,2);
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};
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});
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)) * ...
203 bb_I = reduced_data.CE{crbInd_imp,tii}(:,1:Mred_impl(tii)) * ...
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);
212 LL_I = sparse([],[],[],model.N,model.N);
214 if ~isempty(reduced_data.bb_I)
215 bb_I = lincomb_sequence(reduced_data.bb_I,sbb_I);
217 bb_I = sparse([],[],[],model.N,1);
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
227 if ~model.newton_solver
228 A = LL_I * model.dt + speye(size(LL_I));
234 % determine local values by reconstructing U values from reduced
236 U_local_ext = reduced_data.RB_local_ext{crbInd_exp,ti} * a(:,t);
238 % the following performs
239 % U_local = L_local(U_local_ext, TM_local, [], ...
240 % reduced_data.grid_local_ext);
242 % note the use of emodel
243 reduced_data.grid = reduced_data.grid_local_ext{crbInd_exp,ti};
245 le_local_inc = emodel.L_E_local_ptr(emodel, reduced_data, ...
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;
250 if model.newton_solver
252 updelta_a = zeros(model.N, model.newton_steps+1);
253 updelta_a(:,1) = a(:,t);
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: ']);
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!');
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, ...
274 reduced_data.TM_local{crbInd_imp,tii});
276 [gradL_I, gL_I_offset] = ...
277 model.implicit_gradient_operators_algorithm(model, reduced_data, ...
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!');
285 gradL_I = reduced_data.CE_red{crbInd_imp,tii} * gradL_I ...
286 * reduced_data.RB_local_ext{crbInd_imp,tii};
288 gradL_I = gradL_I * model.dt + speye(size(gradL_I));
293 theta_update_expl = linsolve(reduced_data.BM{crbInd_exp,ti}(1:MM(ti),1:MM(ti)), ...
294 le_local_inc(1:MM(ti)), ...
296 theta_update_impl = linsolve(reduced_data.BM{crbInd_imp,tii}(1:MM(tii),1:MM(tii)), ...
297 li_local_inc(1:MM(tii)), ...
300 % minlength = min(length(theta_update_impl), length(theta_update_expl));
301 % theta_update = theta_update_expl(1:minlength) + theta_update_impl(1:minlength);
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));
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)), ...
312 arhs = reduced_data.DE{crbInd_exp,ti}(:,1:Mred_expl(ti)) ...
313 * theta_update(1:Mred_expl(ti));
316 full_rhs = - updelta_a(:,n) + a(:,t) - model.dt * arhs;
318 delta_a = gradL_I \ full_rhs;
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
326 if nres < model.newton_epsilon
331 a(:,t+1) = updelta_a(:,n+1);
333 % compute coefficients of update in CRB Space `\W_{M+M'}`.
335 theta_update_expl = linsolve(reduced_data.BM{crbInd_exp,ti}(1:MM(ti),1:MM(ti)), ...
337 theta_update_impl = 0;
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));
343 % check
if an LES is to be solved, or problem is an
explicit problem
344 if isequal(A, speye(size(A)))
347 % solve linear system without Newton solver
348 % disp('check symmetry and choose solver accordingly!');
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)
364 if(t==1) % && model.
verbose > 10)
365 disp(['relres=', num2str(relres), ' iter=', num2str(iter)]);
370 disp(['error in system solution, solver return flag = ', ...
377 if model.enable_error_estimator
379 error('error estimator does not work with varying crbs for different time slices yet');
381 ainc = a(:,t) - a(:,t+1);
382 theta_update = theta_update_expl + theta_update_impl;
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;
388 lipschitzConst = C_E^(model.nt - t + 1);
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;
403 % compute the empirical interpolation error estimation
404 eilog(t) = model.dt*lipschitzConst ...
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)) ));
410 Delta = Delta + eilog(t) ...
411 + lipschitzConst*newtonlog(t) ...
412 + lipschitzConst*residuum;
414 warning('RBMatlab:rb_simulation:runtime',...
415 'error estimator returned complex result');
422 if model.newton_solver && model.
verbose > 0
423 disp(['computation ready: We needed at most ', num2str(nmax), ' Newton steps']);
426 if model.enable_error_estimator
427 simulation_data.Delta = [0, Deltalog];
428 simulation_data.reslog = [0, reslog];
429 simulation_data.eilog = [0, eilog];
432 % prepare return parameters
433 simulation_data.a = a;
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 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 ...
function clear_all_caches()
This function clears the caches generated for caching of gradient data in evolution schemes...