1 function ei_detailed_data =
ei_detailed(model, model_data, LU_fnames, params)
2 %
function ei_detailed_data =
ei_detailed(model, model_data, LU_fnames, params)
3 % constructs a collateral reduced basis and interpolation points
for given
4 %
operator evaluations.
6 % This
function prepares the empirical interpolation
for an arbitrary
7 % sequence of DOF-vectors. The DOF-vectors are expected to be
8 % stored in the file(s) given in 'LU_fnames', which is a cell array of strings
9 % or a
string array. The files are expected to contain a single matrix 'LU',
10 % which is a set of columnwise DOF-vectors. Usually the DOF-vectors correspond
11 % to operator evaluations, which are e.g. computed by
14 % \attention Every field in the returned structure 'ei_detailed_data' is a
15 % cell array, and this function only manipulates entries indexed by
16 % '(params.index, params.time_index)', e.g.
17 % 'ei_detailed_data.QM{params.index, params.time_index}
' holds the basis
18 % functions for the empirical interpolation of the operator with the index
19 % 'params.index
' for arguments lying in the time slice indexed by
20 % 'params.time_index
'. As this function extends data given in 'model_data
',
21 % the empirical interpolation can such be computed for different operators
24 % optional fields of params:
25 % ei_Mmax : integer indicating, when stop is wanted after
26 % reaching the maximum number of collateral RB
27 % vectors (default = inf)
28 % ei_target_error : string which is one of
29 % - 'approx
' for L2-projection error,
30 % - 'interpol
' for L2-interpolation error or
31 % - 'linfty-interpol
' for `L^{\infty}` interpolation error
33 % (default = 'approx
')
34 % ei_stop_epsilon : interpolation error limit stopping the basis
35 % extension when reached. (Default: 0)
36 % time_index : index of time slice for which the empirical
37 % interpolation information is generated. See
38 % time splitting for details. (default = 1)
39 % index : an operator index that can be associated with
40 % the generated empirical interpolation data.
41 % compute_lebesgue : compute the Lebesgue constant for the
42 % interpolation (default = false)
43 % skip_search : boolean flag indicating whether the search for
44 % new basis vectors shall be skipped after a
45 % time domain split. If set to false, the basis
46 % vectors from the previous CRB step chosen for
47 % this time domain are used. (default = false)
49 % optional fields of model_data:
50 % time_split_map : a map between a time step index `t \in \{1,
51 % \ldots, model.nt+1\}` and a time slice index
52 % `s \in \{1, \ldots, S_{\max}\}`, where
53 % `S_{\max}` is the number of time slices.
54 % For more details look at documentation of
55 % 'params.LU_fnames
'. (default = `t\mapsto 1
59 % LU_fnames : a cell array of strings or an array of strings
60 % of file names relative to rbmatlabtemp(),
61 % where time series of DOF vectors are stored
62 % for which the collateral reduced basis space
63 % shall be trained. Usually, 'LU_fnames
' is
64 % generated by ei_operator_collect_files(). The
65 % files should contain an array named 'LU
' of
66 % dimension 'dofs x model.nt+1
' or
67 % 'dofs x model.nt+1+\#intermediate
newton steps
'
68 % In the first case, only the vectors 'LU(:,s)
'
69 % with 'model_data.time_split_map(s)==params.time_index
'
70 % are used for empirical interpolation.
71 % params : a struct containing control parameters for the
72 % empirical interpolation.
75 % ei_detailed_data : a struct containing the vectors and matrices
76 % storing all high dimensional data needed for
77 % empirical interpolation, plus some information
78 % on the basis generation. Note, that this might
79 % be an extension the parameter 'model_data
'.
81 % generated fields of ei_detailed_data:
82 % QM: a matrix of columnwise DOF-vectors `q_j` for interpolation
83 % to be used as the colateral basis
84 % TM: a vector for the set of 'magic points
' by containing the index
85 % numbers of the corresponding DOF-nodes (In case of piecewise constant
86 % or linear basis-functions, the maxima `x_i` always can be found in a
87 % cell centroid (deg=0) or a node (deg=1).
88 % BM: the corresponding interpolation-matrix of dimension 'Mmax x Mmax
',
89 % i.e. interpolation can be done by solving the equation system `B
90 % \sigma = \left(\zeta(x_1), \ldots, \zeta(x_M)\right)` then `Q
91 % \sigma` is the empirical interpolation. Note, that this
92 % reconstruction may not be done in the online phase!
93 % ei_info: structure giving special details on creation:
94 % - 'max_err_sequence
': a vector of errors, AFTER the
95 % corresponding new basis vector extension,
96 % - 'extension_filenum
': a vector with the filenumbers, from which
97 % the snapshots are selected
98 % - 'extension_filepos
': a vector with the relative position of the
99 % snapshot within its file extension_filenum. By the latter two
100 % fields, a unique identification of the selected snapshots is
101 % possible, i.e. a later translation into parameter vectors,
103 % - 'stopped_on_Mmax
': flag indicating, whether stop on maximum
104 % 'params.ei_Mmax
' is a reason for termination
105 % - 'stopped_on_monotonicity
': flag indicating, that there is no
106 % error decrease anymore, which incicates an accuracy problem,
107 % so termination is performed
108 % - 'stopped_on_duplicate_point
': flag indicating, that the
109 % empirical interpolation selected the same interpolation point
110 % twice for interpolation, which indicates an accuracy limit
111 % - 'stopped_on_epsilon
': flag indicating, that the empirical
112 % interpolation stopped because the interpolation error dropped
113 % below the given limit 'params.ei_stop_epsilon
'
117 % Bernard Haasdonk 15.8.2007
119 %ei_target_error = 'interpol
';
122 grid = model_data.grid;
124 if ~isfield(model_data, 'time_split_map
')
125 model_data.time_split_map = [1:model.nt+1; ones(size(1:model.nt+1)) ]';
128 if ~isfield(params,
'time_index')
129 params.time_index = 1;
132 if ~isfield(params,'ei_target_error')
133 params.ei_target_error = 'approx';
136 if ~isfield(params,'ei_stop_epsilon')
137 params.ei_stop_epsilon = 0;
140 if ~isfield(params,'skip_search')
141 params.skip_search = false;
144 %if ~isfield(params,'ei_rel_abs')
145 % params.ei_rel_abs = 'absolute';
148 if ~isfield(params,'ei_Mmax')
149 params.ei_Mmax = inf;
153 LU_fnames = {LU_fnames};
156 if ~isfield(params,
'index')
160 if ~isfield(params,'compute_lebesgue')
161 params.compute_lebesgue = false;
165 ti = params.time_index;
167 % get weight matrix for inner-product computation
168 W = model.get_inner_product_matrix(model_data);
170 % determine initial size of vectors:
171 Q = zeros(size(W,1),0);
175 % initialize RB_info data
177 extension_filenum = [];
178 extension_filepos = [];
181 % difference to ei from literature:
182 % instead of simply first vector and normalization => search worst l2-error
184 if isfield(model_data, 'QM') ...
185 && all( [pari,ti] <= size(model_data.QM) ) ...
186 && size(model_data.QM{pari,ti},2) > 0
187 m = size(model_data.QM{pari,ti},2);
188 if(model.verbose > 0)
189 disp([
'Extending collateral reduced basis space of size ', num2str(m),
'.']);
191 if params.skip_search
192 Q = model_data.QM{pari,ti};
193 T = model_data.TM{pari,ti};
194 B = model_data.BM{pari,ti};
196 tei_info = model_data.ei_info{pari,ti};
197 max_errs = [ Inf; tei_info.max_err_sequence ];
198 extension_filenum = tei_info.extension_filenum;
199 extension_filepos = tei_info.extension_filepos;
204 stopped_on_monotonicity = 0;
205 stopped_on_epsilon = 0;
206 stopped_on_duplicate_point = 0;
207 if params.ei_Mmax < 1
212 if ismember(params.ei_target_error,{
'approx',
'interpol'})
213 disp('using l2-error for ei offline')
216 disp('using linfty-error for ei offline')
223 disp(['determining ei-basis & magic point ',num2str(m),':']);
224 % for each discrete function in LU
225 % compute best-l2-approximation in current space spanned by Q
227 % if <u_H,v_H> = u' * W * v (u,v coefficient vectors)
228 % then min_p (u_H - sum p(i) q_i) is minimized by
230 % p = (Q' W Q)^(-1) Q^T W u
232 % So compute whole array of p-vectors and resulting approximation Q*p
234 if params.skip_search && m <= length(extension_filenum)
235 tmp = load(fullfile(rbmatlabtemp,LU_fnames{extension_filenum(m)}));
236 if size(tmp.LU, 2) == tmodel.nt+1
237 tslice = tmodel_data.time_split_map(:,2) == tparams.time_index;
238 tslice = tmodel_data.time_split_map(tslice,1);
239 LU = tmp.LU(:,tslice);
243 zeta_M = tmp.LU(:,extension_filepos(m));
245 if strcmp(params.ei_target_error,
'approx') == 1
246 A = (Q
' * W * Q)^(-1) * Q' * W;
251 tmp_max_is = zeros(length(LU_fnames),1);
252 tmp_max_errs = zeros(length(LU_fnames),1);
253 tmp_zeta_M = zeros(grid.nelements,length(LU_fnames));
254 parfor i=1:length(LU_fnames)
255 tmp = load(fullfile(rbmatlabtemp,LU_fnames{i}));
256 tmodel_data = model_data;
260 if size(tmp.LU, 2) == tmodel.nt+1
261 tslice = tmodel_data.time_split_map(:,2) == tparams.time_index;
262 tslice = tmodel_data.time_split_map(tslice,1);
263 LU = tmp.LU(:,tslice);
268 switch tparams.ei_target_error
269 case 'approx' % approximation, i.e. L2-projection error
272 % interpolation, i.e. empirical interpolation error
273 case {
'interpol',
'linfty-interpol'}
275 LUapprox = Q * coeff;
277 error(
'ei_target_error unknown!')
279 % search maximum l2-error
281 errors = tmodel.l2_error_sequence_algorithm(LU,LUapprox,model_data.W);
283 errors = tmodel.linfty_error_sequence_algorithm(LU,LUapprox,[]);
285 % choose maximum error-snapshot for CRB extension
286 [tmp_max_err, tmp_max_i] = max(errors);
287 tmp_max_is(i) = tmp_max_i(1);
288 tmp_max_errs(i) = tmp_max_err(1);
289 tmp_zeta_M(:,i) = LU(:,tmp_max_i(1));
293 % get largest from filewise extremes
294 [max_err, max_in] = max(tmp_max_errs);
295 disp(['detected maximum error for extension: ',num2str(max_err(1))]);
296 max_errs = [max_errs; max_err(1)];
297 zeta_M = tmp_zeta_M(:,max_in(1));
298 extension_filenum = [extension_filenum; max_in(1)];
299 extension_filepos = [extension_filepos; tmp_max_is(max_in(1))];
305 if (m > 1) % compute interpolant
306 zeta_M_part = zeta_M(T); % get target values in interpolation points
307 %sigma = bicgstab(B,zeta_M_part,[],1000); % get interpolation
309 sigma = B \ zeta_M_part;
310 r_M = zeta_M - Q * sigma; % compute residual
312 disp(['positive minus negative contributions of residual (should be zero:)', num2str(sum(r_M))]);
313 disp(['positive minus negative contributions of zeta_M (should be zero:)', num2str(sum(zeta_M))]);
319 [max_r, t_M] = max(abs(r_M));
320 t_M = find(abs(r_M) >= max_r - 1e-12,1);
321 if ~isempty(find(t_M(1)==T, 1))
322 disp('empirical interpolation selected magic point twice!!');
323 stopped_on_duplicate_point = 1;
326 elseif (length(max_errs)>1) && (max_errs(end)>max_errs(end-1)) ...
327 && isequal(params.ei_target_error,'approx')
328 % check that l2-error sequence is decreasing in case of
329 % approximation error (interpol-error can be
330 % non-monotonic...). If not: accuracy
331 % problem and interpolation should be stopped
332 % stop empirical interpolation due to accuracy limit
333 disp('ei detected accuracy limit, loop is stopped.')
335 stopped_on_monotonicity = 1;
336 elseif (length(max_errs) > 1) && (max_errs(end) < params.ei_stop_epsilon)
337 disp('ei detected accuracy limit, loop is stopped.')
339 stopped_on_epsilon = 1;
341 q_M = r_M/r_M(t_M(1)); % then sign is respected
short version
342 % (after verifying zero-1 structure...)
343 % B = [B, zeros(m-1,1) ; ...
344 % Q(t_M,:), 1 ]; % interpolation matrix mit B(i,j) = q_j(t_i)
345 % T = [T; t_M]; % new vector of interpolation DOFs
346 % Q = [Q, q_M]; % new matrix of basis functions
348 Q(t_M,:), q_M(t_M) ]; % interpolation matrix mit B(i,j) = q_j(t_i)
349 T = [T; t_M]; % new vector of interpolation DOFs
350 Q = [Q, q_M]; % new matrix of basis functions
352 disp(['positive minus negative contributions of new basis function (should be zero:)', num2str(sum(q_M))]);
356 if params.ei_Mmax <= length(T)
357 disp('ei reached prescribed number of CRB-vectors, loop is stopped')
363 A = (Q' * W * Q)^(-1) * Q' * W;
365 % determine final error
366 tmp_max_errs = zeros(1, length(LU_fnames));
367 parfor i=1:length(LU_fnames)
369 tmp = load(fullfile(rbmatlabtemp,LU_fnames{i}));
370 tmodel_data = model_data;
373 tslice = tmodel_data.time_split_map(:,2) == tparams.time_index;
374 tslice = tmodel_data.time_split_map(tslice,1);
375 LU = tmp.LU(:,tslice);
377 switch params.ei_target_error
378 case 'approx' % approximation, i.e. L2-projection error
381 case {
'interpol',
'linfty-interpol'} % L2-/Linfty-interpolation error
383 LUapprox = Q * coeff;
385 error(
'ei_target_error unknown!')
388 % search maximum l2- or linfty error
390 tmp_errors = tmodel.l2_error_sequence_algorithm(LU,LUapprox,model_data.W);
391 % choose maximum l2error-snapshot for CRB extension
392 else % use linfty_error
393 tmp_errors = tmodel.linfty_error_sequence_algorithm(LU,LUapprox,[]);
395 [tmp_max_err, tmp_max_i] = max(tmp_errors);
396 tmp_max_errs(i) = tmp_max_err;
399 max_err = max(tmp_max_errs);
401 %params.title = 'Interpolation basis functions q_m';
402 %plot_element_data_sequence(grid,Q,params);
403 %disp(['Interpolation matrix B should have lower-triangular structure,' ...
406 %u = zeros(grid.nelements,1);
408 %plot_element_data(grid,u,params);
409 %title('Interpolation points/DOFS');
413 ei_detailed_data = model_data;
414 if ~isfield(ei_detailed_data,'QM')
415 ei_detailed_data.QM = cell(1,1);
416 ei_detailed_data.TM = cell(1,1);
417 ei_detailed_data.BM = cell(1,1);
418 ei_detailed_data.ei_info = cell(1,1);
421 ei_detailed_data.QM{pari,ti} = Q;
422 ei_detailed_data.TM{pari,ti} = T;
423 ei_detailed_data.BM{pari,ti} = B;
424 ei_detailed_data.ei_info{pari,ti} = [];
425 ei_detailed_data.ei_info{pari,ti}.max_err_sequence = [max_errs(2:end); max_err];
426 ei_detailed_data.ei_info{pari,ti}.extension_filenum = extension_filenum;
427 ei_detailed_data.ei_info{pari,ti}.extension_filepos = extension_filepos;
428 ei_detailed_data.ei_info{pari,ti}.stopped_on_monotonicity = stopped_on_monotonicity;
429 ei_detailed_data.ei_info{pari,ti}.stopped_on_epsilon = stopped_on_epsilon;
430 ei_detailed_data.ei_info{pari,ti}.stopped_on_Mmax = stopped_on_Mmax;
431 ei_detailed_data.ei_info{pari,ti}.ei_stopped_on_duplicate_point = ...
432 stopped_on_duplicate_point;
433 if params.compute_lebesgue
435 ei_detailed_data.ei_info{pari,ti}.lebesgue = max(sum(abs(XI),2));
436 ei_detailed_data.ei_info{pari,ti}.max_lebesgue = 2^length(T) - 1;
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 ei_detailed_data = ei_detailed(model, model_data, LU_fnames, params)
constructs a collateral reduced basis and interpolation points for given operator evaluations...
function LU_fnames = ei_operator_collect_files(model, model_data, Mtrain, params)
collects operator evaluations on a sample of snapshots
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 ...