3 % prepares detailed_data structure with high dimensional like reduced basis
6 % method, which prepares
'detailed_data', which is meant as data, that may be
7 % dependent on `H`, and is not required during the online-simulation, but it
8 % may be used for reconstruction purposes or computation of online_quantities.
9 % i.e. reduced basis vectors, colateral reduced basis spaces, grid, etc. can be
12 % The grid, the collateral basis for the explicit nonlinearity and the reduced
13 % basis are generated in this order.
15 % \note The reduced basis generation is delegated to the function
18 % - allowed dependency of data: `H`
19 % - allowed dependency of computation: `H`
20 % - unknown at this stage: `\mu, N_{\max}, M_{\max}, N, M`
22 % Required fields of model:
23 % Nmax : maximum number of reduced basis vectors to generate
24 % Mmax : maximum number of collateral reduced basis vectors to
26 % Mstrich : number of collateral reduced basis
function used
for
27 % a posteriori error estimation.
28 % ei_numintervals : (only used in
'param-time-space-grid' mode) the finite
29 % parameter
set for which the empirical interpolation is trained, is given
30 % by through a uniform distribution of parameters in the bounds given by
31 %
'model.mu_ranges'. This field specifies the number of parameters in each
32 % component direction.
33 % ei_space_operators : a cell array of
function pointers to the localized
34 % operators
for which a collateral reduced basis space shall be created.
35 % CRB_generation_mode : a
string which is either
36 % -
'file_load' : simple loading of collateral reduced basis from a file
37 % -
'param-time-space-grid' : search
for CRB vectors in a discrete subspace
38 % of the space of all
operator evaluations on solutions
for parameters in
39 % the
'model.mu_range' boundaries and all timesteps.
40 % CRB_basis_filename : (only used in
'file_load' mode) name of file, that
41 % contains precomputed collateral reduced basis
'QM'.
42 % separate_CRBs :
boolean flag, indicating whether, the
operator
43 % evaluations shall be stored in different directories
for the later
44 % computation of separate collateral reduced basis spaces
for each
45 %
operator, or combined a single directory.
47 % Optional fields of model:
48 % adaptive_time_split_mode :
boolean flag indicating whether the time slices
49 % shall be computed adaptively. (
default ==
false)
50 % time_split_Mmax : when collateral reduced basis reaches
this
51 % size, the current time slice is split in
'adaptive_time_split_mode'
52 % (
default =
'model.ei_Mmax')
53 % minimum_time_slice : when time slice contains only
this many number of
54 % time steps, adaptation is stopped in
'adaptive_time_split_mode'.
56 % ei_stop_epsilon : interpolation error limit stopping the basis
57 % extension when reached. This needs to be strictly positive in
58 %
'adaptive_time_split_mode'. (
default = 0 respectively 1e-6 in
59 %
'adaptive_time_split_mode')
60 % ei_time_splits : number of time slices the discrete time
61 % interval shall (initially) be splitted into. (default = 1)
63 % generated fields of detailed_data:
64 % grid : grid to be used in the subsequent stages, copied from 'model_data'
65 % QM : a matrix of columnwise DOF-vectors `q_j` for interpolation
66 % to be used as the colateral basis
67 % TM : a vector for the set of 'magic points' by containing the index
68 % numbers of the corresponding DOF-nodes (In case of piecewise
69 % constant or linear basis-functions, the maxima `x_i` always can be
70 % found in a cell centroid (deg=0) or a node (deg=1).
71 % BM : the corresponding interpolation-matrix of dimension 'Mmax x Mmax',
72 % i.e. interpolation can be done by solving the equation system `B
73 % \sigma = \left(\zeta(x_1), \ldots, \zeta(x_M)\right)` then `Q
74 % \sigma` is the empirical interpolation. Note, that this
75 % reconstruction may not be done in the online phase!
76 % ei_info: details on the empirical interpolation procedure as produced
78 % ei_info.extension_mus: a matrix whose column vectors hold the parameter
79 % vectors corresponding to the solution trajectory serving as a basis
81 % RB : matrix with 'Nmax' columns holding the reduced basis vectors
84 % detailed_data : structure containing all the reduced basis data and
85 % information about the generation process.
87 % Bernard Haasdonk 15.5.2007
90 detailed_data =
structcpy(detailed_data, model_data);
93 if ~isfield(model, 'adaptive_time_split_mode')
94 model.adaptive_time_split_mode = false;
97 if ~isfield(model, 'ei_stop_epsilon')
98 if model.adaptive_time_split_mode
99 model.ei_stop_epsilon = 1e-6;
101 model.ei_stop_epsilon = 0;
105 if ~isfield(model, 'ei_time_splits')
106 model.ei_time_splits = 1;
109 if ~isfield(model, 'extend_crb')
110 model.extend_crb = false;
113 if ~isfield(model, 'minimum_time_slice')
114 model.minimum_time_slice = 1;
117 if ~isfield(model, 'time_split_Mmax')
118 model.time_split_Mmax = model.Mmax;
121 if isa(model.ei_space_operators, 'function_handle')
122 params.ei_space_operators = { model.ei_space_operators };
124 %
if ~isfield(model,
'ei_space_operators')
125 % params.ei_space_operators = { model.L_E_local_ptr };
126 % detailed_data.explicit_crb_index = 1;
127 % detailed_data.implicit_crb_index = -1;
130 params.ei_space_operators = model.ei_space_operators;
132 if model.separate_CRBs
133 detailed_data.implicit_crb_index = 2;
134 detailed_data.explicit_crb_index = 1;
136 detailed_data.implicit_crb_index = 1;
137 detailed_data.explicit_crb_index = 1;
141 if ~isfield(model,
'ei_time_splits')
142 model.ei_time_splits = 1;
145 % empirical interpolation of nonlinearity must be performed before
146 % basis-construction, as basis construction needs availability of
147 % reduced simulation.
149 par.range = model.mu_ranges;
151 switch model.CRB_generation_mode
153 % choose the following number of setting, that the time-snapshots
154 % for the parameter ranges fit into memory:
155 % 5x5x5 times 5 timesnapshots of size 8000 = 1250 x 8000 should be fine.
156 % single nonlin simulation of 99 sec extrapolates to 3.5 hours for
157 % 125 detailed simulations!
159 case 'param-time-space-grid'
161 disp('computing param-time-space-grid for empirical interpolation');
162 par.numintervals = model.ei_numintervals;
163 % if ei_operator_collect_tmp is used, set the following params!!
164 %par.numintervals = [1,1,1];
166 Mtrain = transpose(M.vertex);
168 % initially set-up model.ei_time_splits time slices.
169 detailed_data.time_split_map = [ (1:model.nt+1)', ...
170 (ceil((1:model.nt+1)' / (model.nt+1)* (model.ei_time_splits-0.01))) ];
172 % collect the operator evaluations
176 ei_detailed_data = detailed_data;
177 for lsi = 1:size(LU_fnames,1)
178 params.ei_Mmax = model.Mmax;
179 if model.separate_CRBs
180 disp(['computing CRB for local operator ', ...
181 func2str(params.ei_space_operators{lsi})]);
182 params.ei_Mmax = model.sMmax{lsi};
184 disp(cell2mat([
'computing CRB for local operators: ', ...
185 cellfun(@(X)([func2str(X),
' ']), params.ei_space_operators, ...
186 'UniformOutput',
false)]));
189 if model.adaptive_time_split_mode
190 max_time_splits = model.ei_time_splits;
192 while ti <= max_time_splits;
193 params.time_index = ti;
194 something_todo =
true;
195 params.ei_Mmax = model.time_split_Mmax;
196 params.ei_stop_epsilon = model.ei_stop_epsilon;
198 ei_detailed_data =
ei_detailed(model, ei_detailed_data, ...
199 LU_fnames(lsi,:), params);
201 tei_info = ei_detailed_data.ei_info{lsi,ti};
202 if tei_info.stopped_on_epsilon %
goto next time slice
203 ti = ti + 1; something_todo =
false;
204 if model.verbose > 11
205 slice_size = sum(ei_detailed_data.time_split_map(:,2) == ti);
206 disp([
'Reached epsilon for time slice ', num2str(ti), ...
207 ' consisting of ' slice_size
' time steps.']);
209 elseif tei_info.stopped_on_Mmax % Have we reached Mmax?
210 % yes, we reached the time_split_Mmax
211 tmap = ei_detailed_data.time_split_map(:,2);
212 slice_size = sum(tmap == ti);
213 %
do we have minimum slice size reached?
214 if floor(slice_size/2) <= model.minimum_time_slice ...
215 || tei_info.max_err_sequence(end) < model.ei_stop_epsilon_first % or first epsilon is reached
216 if model.verbose > 11
217 disp([
'Reached minimum size for time slice ', num2str(ti), ...
218 ' consisting of ', num2str(slice_size),
' time steps.']);
220 % add further basis vectors,
if requested...
221 if model.time_split_Mmax ~= model.Mmax
222 params.ei_Mmax = model.Mmax;
223 ei_detailed_data =
ei_detailed(model, ei_detailed_data, ...
224 LU_fnames(lsi,:), params);
226 % go to next time slice
227 ti = ti + 1; something_todo =
false;
230 % split the time slice!
231 old_ti_indices = find(tmap == ti);
232 minold = min(old_ti_indices);
233 maxold = max(old_ti_indices);
236 slmiddle = max(floor(median(tei_info.extension_filepos)), model.minimum_time_slice);
237 slmiddle = min(slmiddle, slice_size-model.minimum_time_slice);
238 %slmiddle = floor(slice_size/2);
240 if model.verbose > 11
241 disp([
'Split time slice no. ', num2str(ti),
' at midpoint = ', ...
242 num2str(slmiddle) ,
'/', num2str(slice_size) ]);
246 new_tmap(minold:minold+slmiddle-1) = ti;
247 new_tmap(minold+slmiddle:maxold) = ti+1;
248 new_tmap(maxold+1:end) = tmap(maxold+1:end)+1;
250 ei_detailed_data.time_split_map = [ (1:model.nt+1)', new_tmap ];
252 disp([
'new time split map: ', num2str(ei_detailed_data.time_split_map(:,2)
')]);
254 % find basis functions in first half and second half
255 fh = tei_info.extension_filepos <= slmiddle;
258 splitdd.QM = { ei_detailed_data.QM{lsi, ti}(:,fh), ...
259 ei_detailed_data.QM{lsi, ti}(:,sh) };
260 splitdd.TM = { ei_detailed_data.TM{lsi, ti}(fh), ...
261 ei_detailed_data.TM{lsi, ti}(sh) };
262 splitdd.BM = { ei_detailed_data.BM{lsi, ti}(fh,fh), ...
263 ei_detailed_data.BM{lsi, ti}(sh,sh) };
264 splitdd.ei_info = cell(1,2);
265 splitdd.ei_info{1,1}.max_err_sequence = [tei_info.max_err_sequence(fh);Inf];
266 splitdd.ei_info{1,2}.max_err_sequence = [tei_info.max_err_sequence(sh);Inf];
267 splitdd.ei_info{1,1}.extension_filenum = tei_info.extension_filenum(fh);
268 splitdd.ei_info{1,2}.extension_filenum = tei_info.extension_filenum(sh);
269 splitdd.ei_info{1,1}.extension_filepos = tei_info.extension_filepos(fh);
270 splitdd.ei_info{1,2}.extension_filepos = tei_info.extension_filepos(sh)-slmiddle;
271 params.skip_search = true;
273 splitdd.QM = cell(1,2);
274 splitdd.TM = cell(1,2);
275 splitdd.BM = cell(1,2);
276 splitdd.ei_info = cell(1,2);
277 splitdd.ei_info{1,1}.max_err_sequence = [];
278 splitdd.ei_info{1,2}.max_err_sequence = [];
279 splitdd.ei_info{1,1}.extension_filenum = [];
280 splitdd.ei_info{1,2}.extension_filenum = [];
281 splitdd.ei_info{1,1}.extension_filepos = [];
282 splitdd.ei_info{1,2}.extension_filepos = [];
285 newQMsize = size(ei_detailed_data.QM,2) + 1;
286 ei_detailed_data.QM{lsi, newQMsize} = [];
287 ei_detailed_data.BM{lsi, newQMsize} = [];
288 ei_detailed_data.TM{lsi, newQMsize} = [];
289 ei_detailed_data.ei_info{lsi, newQMsize} = [];
291 ei_detailed_data.QM(lsi, ti:end) = ...
292 {splitdd.QM{:}, ei_detailed_data.QM{lsi,ti+1:end-1}};
293 ei_detailed_data.BM(lsi, ti:end) = ...
294 {splitdd.BM{:}, ei_detailed_data.BM{lsi,ti+1:end-1}};
295 ei_detailed_data.TM(lsi, ti:end) = ...
296 {splitdd.TM{:}, ei_detailed_data.TM{lsi,ti+1:end-1}};
297 ei_detailed_data.ei_info(lsi, ti:end) = ...
298 {splitdd.ei_info{:}, ei_detailed_data.ei_info{lsi,ti+1:end-1}};
300 max_time_splits = max_time_splits + 1;
304 error('Generation of collateral reduced space stopped after not converging in a time slice
');
308 % translate file-indices of snapshots into parameter vectors:
309 ei_detailed_data.ei_info{lsi,ti-1}.extension_mus = ...
311 mod(ei_detailed_data.ei_info{lsi,ti-1}.extension_filenum-1, ...
316 params.ei_stop_epsilon = model.ei_stop_epsilon;
317 for ti = 1:model.ei_time_splits
318 params.time_index = ti;
319 ei_detailed_data = ei_detailed(model, ei_detailed_data, ...
320 LU_fnames(lsi,:), params);
321 % translate file-indices of snapshots into parameter vectors:
322 ei_detailed_data.ei_info{lsi,ti}.extension_mus = ...
324 mod(ei_detailed_data.ei_info{lsi,ti}.extension_filenum-1, ...
334 disp('loading CRB from file
for empirical interpolation
');
335 tmp = load(model.CRB_basis_filename);
336 ei_detailed_data.QM = tmp.detailed_data.QM(:,1:model.Mmax);
337 ei_detailed_data.BM = tmp.detailed_data.BM(:,1:model.Mmax);
338 ei_detailed_data.TM = tmp.detailed_data.TM(1:model.Mmax);
339 ei_detailed_data.ei_info = tmp.detailed_data.ei_info;
340 if (model.Mmax~=size(tmp.detailed_data.QM,2))
341 disp(['Only extracted
',num2str(model.Mmax),' CRB-vectors from'...
342 num2str(size(tmp.detailed_data.QM,2))]);
347 error(
'ei-generation mode unknown');
350 detailed_data.BM = ei_detailed_data.BM;
351 detailed_data.TM = ei_detailed_data.TM;
352 detailed_data.QM = ei_detailed_data.QM;
353 detailed_data.ei_info = ei_detailed_data.ei_info;
354 detailed_data.time_split_map = ei_detailed_data.time_split_map;
356 % test Mmax on consistency, otherwise there may be problems afterwards
357 if ~isequal(model.Mmax, size(detailed_data.BM{1},2))
358 disp(['warning: Mmax in params is not the current number of generated', ...
359 ' basis vectors. Please adjust model.Mmax!']);
363 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
364 % simply generate reduced basis as in lin-evol case
367 model.M = cellfun(@(x)(size(x,2) - model.Mstrich), detailed_data.BM, 'UniformOutput', true);