rbmatlab  1.13.10
 All Classes Namespaces Files Functions Variables Groups Pages
PODEI.m
1 classdef PODEI < Greedy.Plugin.Interface
2  % Greedy.Plugin.Interface implementation that extends in each basis extension step,
3  % the reduced basis space and/or the collateral reduced basis space(s).
4  %
5  % As an error indicator it uses the error indicator of the reduced numerical
6  % scheme, with the ambition to "optimize" all spaces for best output in the
7  % final solutions `u_{\text{red}}(\mu)`.
8 
9  properties(Constant, Hidden=true)
10 
11  % cell array of field names whose values shall be copied to the generated
12  % Greedy.DataTree.Detailed.PODEILeafNode instance.
13  info_fields = { ...
14  'Mmax_small', 'error_differences_for_extension', ...
15  'M_by_N_ratio', 'bad_extension_on_explosion', ...
16  'maximum_temporary_error_growth_factor', 'discard_last_rb_after_bad_extension', ...
17  'skip_rb_after_bad_extension', 'skip_ei_after_bad_extension' ...
18  };
19 
20  end
21 
22  properties(Dependent)
24  %
26  needs_preparation;
27 
29  %
31  use_l2_error;
32 
33  end
34 
35  properties
37  %
39  indicator_mode;
40 
42  %
44  relative_error = [];
45  end
46 
47  properties
48  % number of collateral reduced of the initial collateral reduced basis.
49  %
50  % In order to use the estimator of a nonlinear evolution equation for a
51  % basis extension with a greedy search in the parameter space, a collateral
52  % reduced basis space for all existing operators needs to be present. For
53  % this reason at the beginning of the basis generation algorithm, a
54  % collateral reduced bases of size at most 'Mmax_small' is generated
55  Mmax_small;
56 
57  % boolean flag indicating to use largest error difference over time steps
58  % in order to select snapshot for collateral reduced basis extension.
59  %
60  % In order to extend the collateral reduced basis spaces, we need to select
61  % one snapshot indexed by `k_{\max}` from the sequence of possible vectors
62  % `v_h(t^{k},\mu_{\max}) \in {\cal W}_h`. If this flag is set to 'true',
63  % `k_{\max} = \arg \max_{k=1,\ldots,K} \eta^k(\mu_{\max}) -
64  % \eta^{k-1}(\mu_{\max})`.
65  %
66  % Otherwise `k_{\max}` is determind as the time step of the maximum error
67  % returned by Greedy.Plugin.EI.compute_error()
68  error_differences_for_extension = false;
69 
70  % forced ratio between the sizes of the colletaral and the regular reduced
71  % basis space
72  %
73  % If the ratio is too low before a basis extension, only the collateral
74  % reduced basis space is extended.
75  %
76  % Its purpose is to make the collateral reduced basis space more refined
77  % than the reduced basis space. This is necessary as the best possible
78  % error for the basis generation of the reduced basis space @em depends on
79  % the quality of the collateral reduced basis space.
80  M_by_N_ratio = 0;
81 
82  % boolean flag indicating whether in an @em explosion is a bad extension.
83  %
84  % See also: indicate_bad_basis_extension() for details.
85  bad_extension_on_explosion = false;
86 
87  % maximum factor between the current maximum indicator and the smallest
88  % maximum error indicator during previous extensions
89  %
90  % See indicate_bad_basis_extension() for details.
91  maximum_temporary_error_growth_factor = 0;
92 
93  % boolean flag specifying whether the last generated reduced basis vector
94  % should be discarded after a bad extension is indicated by
95  % indicate_bad_basis_extension().
96  %
97  % See indicate_bad_basis_extension() and basis_extension() for details.
98  discard_last_rb_after_bad_extension = true;
99 
100  % boolean flag specifying whether the current reduced basis extension
101  % should be skipped after a bad extension is indicated by
102  % indicate_bad_basis_extension().
103  %
104  % See indicate_bad_basis_extension() and basis_extension() for details.
105  skip_rb_after_bad_extension = true;
106 
107  % boolean flag specifying whether the current collateral reduced basis
108  % extension should be skipped after a bad extension is indicated by
109  % indicate_bad_basis_extension().
110  %
111  % See indicate_bad_basis_extension() and basis_extension() for details.
112  skip_ei_after_bad_extension = false;
113  end
115  properties(Constant)
116  % @copybrief Greedy::Interfacegenerated_basis_type
117  %
118  % This is set to 'eirb'.
119  %
120  % @sa Greedy::Interfacegenerated_basis_type
121  generated_basis_type = 'eirb';
122  end
123 
124  properties(Access = public)
125  % object of type Greedy.Plugin::PODCommon used for extension of the reduced basis space.
126  rb_ext;
127 
128  % object of type Greedy.Plugin::EICommon used for extension of the collateral reduced
129  % basis space(s) and providing an error estimator
130  ei_ext;
131 
132  % object of type Greedy::Algorithm used for initial creation of
133  % collateral reduced basis space(s)
134  %
135  % See #Mmax_small for details
136  ei_init_greedy;
137  end
138 
139  methods
140  function crbeie = PODEI(rb_extension, ei_extension, ei_init_greedy, Mmax_small)
141  % function crbeie = PODEI(rb_extension, ei_extension, ei_init_greedy, Mmax_small)
142  % constructor for a combined extension algorithm for reduced and
143  % collateral reduced basis spaces.
144  %
145  % Parameters:
146  % rb_extension: an object of type Greedy.Plugin.PODCommon specifying how to
147  % extend the reduced basis space and providing an error
148  % indicator.
149  % ei_extension: an object of type Greedy.Plugin.EICommon specifying how to
150  % extend the collateral reduced basis space(s).
151  % ei_init_greedy: an object of type Greedy.Algorithm used for
152  % initial creation of collateral reduced basis space(s)
153 
154  assert(isa(rb_extension, 'Greedy.Plugin.PODCommon'));
155  assert(isa(ei_extension, 'Greedy.Plugin.EICommon'));
156  crbeie = crbeie@Greedy.Plugin.Interface(rb_extension.generator);
157  crbeie.rb_ext = rb_extension;
158  crbeie.ei_ext = ei_extension;
159  crbeie.ei_init_greedy = ei_init_greedy;
160  crbeie.Mmax_small = Mmax_small;
161  end
162 
163  function needs_prepare = get.needs_preparation(this)
164  needs_prepare = this.rb_ext.needs_preparation;
165  end
166 
167  function ret = get.indicator_mode(this)
168  ret = this.rb_ext.indicator_mode;
169  end
170 
171  function ret = get.use_l2_error(this)
172  ret = this.rb_ext.use_l2_error;
173  end
174 
175  function ret = get.relative_error(this)
176  ret = this.rb_ext.relative_error;
177  end
178 
179  function this=set.indicator_mode(this, value)
180  this.ei_ext.indicator_mode=value;
181  this.rb_ext.indicator_mode=value;
182  end
183 
184  function this=set.use_l2_error(this, value)
185  this.ei_ext.use_l2_error=value;
186  this.rb_ext.use_l2_error=value;
187  end
189  function this=set.relative_error(this, value)
190  this.ei_ext.relative_error=value;
191  this.rb_ext.relative_error=value;
192  end
193 
194  function detailed_data = init_basis(this, rmodel, model_data, M_train)
195  % function detailed_data = init_basis(this, rmodel, model_data, M_train)
196  % @copybrief Greedy.Plugin::Interfaceinit_basis()
197  %
198  % @copydetails Greedy.Plugin::Interfaceinit_basis()
199  %
200  % Parameters:
201  % rmodel: object of type IReducedModel
202  %
203  % Return values:
204  % detailed_data: object of type Greedy.DataTree.Detailed.PODEILeafNode
205  %
206  % This function
207  % -# starts Greedy.Algorithm.gen_detailed_data() on the
208  % #ei_init_greedy member in order to compute initial collateral
209  % reduced basis space(s)
210  % -# creates a history Greedy.DataTree.Detailed.INode.snapshot() afterwards
211  % -# calls Greedy.Plugin.PODCommon.init_basis() on the 'rb_ext' instance
212  detailed_data = Greedy.DataTree.Detailed.PODEILeafNode(model_data, true);
213  set_fields(detailed_data, this, Greedy.Plugin.PODEI.info_fields);
215  assert(rmodel.crb_enabled);
216 
217  if isfield(rmodel.bg_descr, 'stop_Mmax')
218  Mmax_backup = rmodel.bg_descr.stop_Mmax;
219  else
220  Mmax_backup = Inf;
221  end
222  this.ei_init_greedy.detailed_extension.stop_Mmax = this.Mmax_small;
223  detailed_data.ei = gen_detailed_data(this.ei_init_greedy, rmodel, model_data, []);
224  snapshot(detailed_data.ei, 'ei_init_basis', ...
225  sprintf(['Initialization of empirical interpolation basis on a coarse parameter grid\n',...
226  'and small epsilon tolerance or maximum basis size']),...
227  'EI initialized' );
228  % clear all stop flags, because they might lead to wrong behavior
229  % later
230  detailed_data.ei.stop_flags = {};
231 
232  if ~isempty(Mmax_backup)
233  rmodel.bg_descr.stop_Mmax = Mmax_backup;
234  detailed_data.ei.fields.stop_Mmax = Mmax_backup;
235  end
236 
237  % update the value for M! Now we need to subtract the Mstrich value
238  if isa(rmodel.M, 'DataTree.INode')
239  if isa(reduced_data.M, 'DataTree.INode')
240  rmodel.M = create_scalar_tree(reduced_data.M, @(x) get(x,1) - rmodel.Mstrich);
241  else
242  assert(rmodel.Mstrich == 0 || rmodel.M > rmodel.Mstrich);
243  rmodel.M = reduced_data.M - rmodel.Mstrich;
244  end
245  end
246 
247  tree_descr = get_leaf_description(detailed_data.ei);
248  for leaf_descr = tree_descr
249  leaf = get(detailed_data.ei, leaf_descr.basepath);
250  set_field(leaf, 'target_error_external', true);
251  end
253  detailed_data.rb = init_basis(this.rb_ext, rmodel, model_data, M_train);
254  end
255 
256  function prepare_reduced_data(this, rmodel, detailed_data)
257  % function prepare_reduced_data(this, rmodel, detailed_data)
258  % @copybrief Greedy.Plugin::Interfaceprepare_reduced_data()
259  %
260  % @copydetails Greedy.Plugin::Interfaceprepare_reduced_data()
262  prepare_reduced_data(this.rb_ext, rmodel, detailed_data);
263 % if this.ei_ext.needs_preparation
264 % prepare_reduced_data(this.ei_ext, rmodel, detailed_data);
265 % end
266  end
267 
268  function [max_errs, max_err_seq, max_mu_index] = error_indicators(this, rmodel, detailed_data, parameter_set, reuse_reduced_data)
269  % function [max_errs, max_err_seq, max_mu_index] = error_indicators(this, rmodel, detailed_data, parameter_set, reuse_reduced_data)
270  % @copybrief Greedy.Plugin::Interfaceerror_indicators()
271  %
272  % @copydetails Greedy.Plugin::Interfaceerror_indicators()
273  %
274  % Parameters:
275  % rmodel: an object of type IReducedModel
276  % detailed_data: an object of type Greedy.DataTree.Detailed.PODEILeafNode
277  %
278  % This function calls the Greedy.Plugin::Interfaceerror_indicators() method of the
279  % #rb_ext member.
280  if nargin < 5
281  reuse_reduced_data = [];
282  end
283  [max_errs, max_err_seq, max_mu_index] = error_indicators(this.rb_ext, rmodel, detailed_data, parameter_set, reuse_reduced_data);
284  end
285 
286  function errs = compute_error(this, rmodel, reduced_data, detailed_data)
287  % function errs = compute_error(this, rmodel, detailed_data)
289  %
291  %
292  % Parameters:
293  % rmodel: an object of type IReducedModel
294  % detailed_data: an object of type Greedy.DataTree.Detailed.PODEILeafNode
295  %
296  % This function calls the Greedy.Plugin.Interface.compute_error() method of
297  % the #rb_ext member.
298  errs = compute_error(this.rb_ext, rmodel, reduced_data, detailed_data);
299  end
300 
301  function Uapprox = generate_reduced(this, rmodel, reduced_data, detailed_data, U)
302  % function Uapprox = generate_reduced(this, rmodel, reduced_data, detailed_data, U)
304  %
306  %
307  % Parameters:
308  % rmodel: an object of type IReducedModel
309  % detailed_data: an object of type Greedy.DataTree.Detailed.PODEILeafNode
310  %
311  % This function calls the Greedy.Plugin.Interface.generate_reduced() method of the
312  % #rb_ext member.
313  Uapprox = generate_reduced(this.rb_ext, rmodel, reduced_data, detailed_data);
314  end
315 
316  function [breakloop, reason] = pre_check_for_end(this, rmodel, detailed_data)
317  % function [breakloop, reason] = pre_check_for_end(this, rmodel, detailed_data)
319  %
321  %
322  % Parameters:
323  % detailed_data: an object of type Greedy.DataTree.Detailed.PODEILeafNode
324  %
325  % This function only indicates a basis extension stop if both parts are
326  % ready.
327 
328  max_err_sequence = get_field(detailed_data, 'max_err_sequence');
329  ext_step = length(max_err_sequence);
330 
331  [breakloop_rb, reason_rb] = pre_check_for_end(this.rb_ext, rmodel, detailed_data.rb);
332  [breakloop_ei, reason_ei] = pre_check_for_end(this.ei_ext, rmodel, detailed_data.ei);
333 
334  breakloop = breakloop_rb & breakloop_ei;
335 
336  % special case: EI skipped for two small residual, and RB could not be
337  % extended => no strategy to get away...
338  ei_skip_small_residual = get_field(detailed_data.ei, 'ei_skipped_for_too_small_residual', 0);
339  if breakloop_rb && ~breakloop_ei ...
340  && ei_skip_small_residual(end) == ext_step-1
341  breakloop = true;
342  set_stop_flag(detailed_data.ei, 'stopping_on_too_small_residual');
343  reason_ei = 'EI extension skipped because of too small residual.';
344  end
345  reason = [reason_rb, ' ', reason_ei];
346  end
347 
348  function detailed_data = basis_extension(this, rmodel, detailed_data, max_err_seq, mu)
349  % function detailed_data = basis_extension(this, rmodel, detailed_data, max_err_seq, mu)
351  %
353  %
354  % This function first extends the collateral reduced basis space unless
355  % -# Greedy.Plugin.EI.pre_check_for_end() returned 'false'
356  % -# the last extension was "bad" as indicated by
357  % indicate_bad_basis_extension() and #skip_ei_after_bad_extension is
358  % enabled
359  % -# the extension fails (e.g. because of
360  % Greedy.Plugin::EIminimum_residual)
361  %
362  % Afterwards, this function extends the reduced basis space unless
363  % -# Greedy.Plugin.PODCommon.pre_check_for_end() returned 'false'
364  % -# the last extension was "bad" as indicated by
365  % indicate_bad_basis_extension() and #skip_rb_after_bad_extension of
366  % #discard_last_rb_after_bad_extension are enabled
367  % -# the 'M/N'-ratio condition as described in #M_by_N_ratio failed
368  % -# reduced simulations returned 'NaN' error indicators
369  %
370  % In the second case and with enabled
371  % #discard_last_rb_after_bad_extension option the last generated reduced
372  % basis is discarded if
373  % -# since the last discard at least two extensions have been
374  % processed.
375  %
376  % Parameters:
377  % rmodel: an object of type IReducedModel
378  % detailed_data: an object of type Greedy.DataTree.Detailed.PODEILeafNode
379  %
380  % Return values:
381  % detailed_data: an object of type Greedy.DataTree.Detailed.PODEILeafNode
382 
383 
384  max_extension_errs = get_field(detailed_data, 'max_extension_errs', 0);
385  last_extension_bad = indicate_bad_basis_extension(this, detailed_data);
386 
387  % extension step number
388  ext_step = length(max_extension_errs);
389 
390  % check whether the ei extension is ready
391  [ei_breakloop, ei_reason] = pre_check_for_end(this.ei_ext, rmodel, detailed_data.ei);
392 
393  Msize = get_ei_size(detailed_data.ei);
394 
395  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
396  % EI extension checks start %
397  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
398 
399  % only update basis spaces if end check is negative
400  ei_ext_steps = get_field(detailed_data, 'ei_ext_steps', 0);
401  if ei_breakloop
402  if rmodel.verbose > 1
403  disp('[1]> Skipping EI extension step, because pre_check_for_end() returned true');
404  end
405  if rmodel.verbose > 5
406  disp(['[5]> ', ei_reason]);
407  end
408  append_field(detailed_data.ei, 'ei_skipped_for_check_end', ext_step);
409 
410  % do not update basis space if last extension was bad and skipping is requested
411  elseif last_extension_bad && get_field(detailed_data, 'skip_ei_after_bad_extension') ...
412  && ei_ext_steps(end) == ext_step - 1
413 
414  if rmodel.verbose > 1
415  disp('[1]> Skipping EI extension step after bad extension');
416  end
417  append_field('ei_skipped_for_bad_extension', ext_step);
418  else
419 
420  % compute error indicator for snapshot selection
421  if get_field(detailed_data, 'error_differences_for_extension') && ~any(isnan(max_err_seq));
422  ei_errs = max_err_seq(2:end) - max_err_seq(1:end-1);
423  else
424  % recompute ei error
425  prepare_reduced_data(this.ei_ext, rmodel, detailed_data.ei);
426  set_mu(rmodel, mu);
427  ei_errs = compute_error(this.ei_ext, rmodel, [], detailed_data.ei);
428  end
430  %%%%%%%%%%%%%%%%%%%%%% extend EI basis %%%%%%%%%%%%%%%%%%%%%
431  append_field(detailed_data, 'ei_errs', ei_errs);
432  append_field(detailed_data, 'ei_max_err', max(ei_errs));
433 
434  this.ei_ext.target_error_external = 1;
435  detailed_data.ei = basis_extension(this.ei_ext, rmodel, detailed_data.ei, ei_errs, mu);
436  newMsize = get_ei_size(detailed_data.ei);
437 
438  % skip ei if residual is too small
439  if newMsize == Msize
440  append_field(detailed_data, 'ei_skipped_for_too_small_residual', ext_step);
441  ei_breakloop = true;
442  if rmodel.verbose > 1
443  disp('[1]> Skipping EI extension because of too small residual.');
444  end
445  else
446 
447  append_field(detailed_data, 'ei_ext_count', newMsize - Msize);
448  % update the info structure
449  Msize = newMsize;
450  append_field(detailed_data, 'ei_ext_steps', ext_step);
451  end
452  end
453 
454  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
455  % EI extension checks end %
456  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
457 
458 
459  % reduced basis extension
460  Nsize = get_rb_size(detailed_data);
461  M_by_N = Msize / Nsize;
463  [rb_breakloop, rb_reason] = pre_check_for_end(this.rb_ext, rmodel, detailed_data.rb);
464 
465 
466  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
467  % RB extension checks start %
468  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
469  rb_ext_steps = get_field(detailed_data, 'rb_ext_steps');
470  rb_discarded_for_bad_extension = get_field(detailed_data, 'rb_discarded_for_bad_extension', []);
471  if rb_breakloop
472  if rmodel.verbose > 1
473  disp('[1]> Skipping RB extension step, because pre_check_for_end() returned true');
474  end
475  if rmodel.verbose > 5
476  disp(['[5]> ',rb_reason]);
477  end
478  append_field(detailed_data, 'rb_skipped_for_check_end', ext_step);
479  else
480  % on error increase only update the rb space
481  if last_extension_bad
482  if get_field(detailed_data, 'discard_last_rb_after_bad_extension') ...
483  && rb_ext_steps(end) == ext_step -1 ...
484  && length(rb_ext_steps) > 2 ...
485  && (isempty(rb_discarded_for_bad_extension) ...
486  || rb_ext_steps(end-1) > rb_discarded_for_bad_extension(end))
487 
488  append_field(detailed_data, 'rb_discarded_for_bad_extension', ext_step);
489  delete_rb(detailed_data, Nsize);
490  if rmodel.verbose > 1
491  disp('[1]> Discarding last RB vector after bad extension step');
492  end
493  elseif this.skip_rb_after_bad_extension
494  append_field(detailed_data, 'rb_skipped_for_bad_extension', ext_step);
495  if rmodel.verbose > 1
496  disp('[1]> Skipping RB extension after bad extension step');
497  end
498  end
499  % only update rb basis space if the M_by_N_ratio is fulfilled
500  elseif ~ei_breakloop && M_by_N < get_field(detailed_data, 'M_by_N_ratio')
501  append_field(detailed_data, 'rb_skipped_for_M_by_N_ratio_restriction', ext_step);
502 
503  if rmodel.verbose > 1
504  disp('[1]> Skipping RB extension because of M_by_N_ratio');
505  end
506  % if reduced simulations failed we have a big problem! :(
507  elseif any(isnan(max_err_seq))
508  append_field(detailed_data, 'rb_skipped_for_failed_simulation', ext_step);
509  if ei_breakloop
510  error('Can''t extend either EI nor RB reduced basis space');
511  end
512 
513  % otherwise: Do a normal basis extension
514  else
515  detailed_data = basis_extension(this.rb_ext, rmodel, detailed_data, max_err_seq, mu);
516  append_field(detailed_data, 'rb_ext_steps', ext_step);
517  end
518  end
519  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
520  % RB extension checks end %
521  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
522 
523  end
524 
525  function detailed_data = finalize(this, rmodel, detailed_data)
526  % function detailed_data = finalize(this, rmodel, detailed_data)
527  % @copybrief Greedy.Plugin::Interfacefinalize()
528  %
529  % @copydetails Greedy.Plugin::Interfacefinalize()
530  %
531  % Parameters:
532  % rmodel: an object of type IReducedModel
533  % detailed_data: an object of type Greedy.DataTree.Detailed.PODEILeafNode
534  %
535  % Return values:
536  % detailed_data: an object of type Greedy.DataTree.Detailed.PODEILeafNode
537  %
538  % This method calls
539  % -# the finalize() method of the #ei_ext member and
540  % -# the finalize() method of the #rb_ext member
541 
542  detailed_data.ei = finalize(this.ei_ext, rmodel, detailed_data.ei);
543  detailed_data.rb = finalize(this.rb_ext, rmodel, detailed_data.rb);
544  end
545 
546  end
547 
548  methods(Access=public)
549 
550  function isbad = indicate_bad_basis_extension(this, detailed_data)
551  % function isbad = indicate_bad_basis_extension(this, detailed_data)
552  % indicates whether the last basis extension was bad
553  %
554  % The last basis extension is bad if the maximum error indicator is
555  % larger than in the step before.
556  %
557  % Furthermore, we test if the maximum error indicator is `f` times larger
558  % than the minimum error indicated at any extension step before. In this
559  % case we say, the event @em explosion has occured.
560  %
561  % If #maximum_temporary_error_growth_factor equals '0', the explosion
562  % test is disabled.
563  %
564  % The explosion test can affect the the assessment of a @em bad @em
565  % extension in the following way dependent on the option
566  % #bad_extension_on_explosion:
567  % - If #bad_extension_on_explosion is set to true, an @em explosion is
568  % also an indicator for a bad extension.
569  % - If #bad_extension_on_explosion is set to false, for an @em
570  % explosion true is returned.
571  %
572  % The latter option assumes that an explosion of the error indicates that
573  % lately introduced complexity by more accurate empirical interpolation
574  % operators is not captured by the current reduced basis yet.
575  %
576  % In the @em explosion test the factor `f` is defined by
577  % ``f = c_{\text{max\_temp\_err\_growth}} \cdot \frac{1}{n_{\text{no\_rb\_ext}}}``
578  % with a constant `c_{\text{max\_temp\_err\_growth}}` given by
579  % #maximum_temporary_error_growth_factor and a weighting factor
580  % determined by the number of extension steps withouth reduced
581  % basis extension `n_{\text{no\_rb\_ext}}`.
582  %
583  % Return values:
584  % isbad: a boolean value indicating whether the last extension was bad.
585 
586  max_extension_errs = get_field(detailed_data, 'max_err_sequence');
587 
588  ext_step = length(max_extension_errs);
589 
590  isbad = (length(max_extension_errs) > 1 && (max_extension_errs(end) > max_extension_errs(end-1)));
591 
592  max_temp_error_growth_factor = get_field(detailed_data, 'maximum_temporary_error_growth_factor');
593  rb_ext_steps = get_field(detailed_data, 'rb_ext_steps', 0);
594  if max_temp_error_growth_factor > 0
595  is_explosion = length(max_extension_errs) > 1 && max_extension_errs(end) < ...
596  max_temp_error_growth_factor/(ext_step - rb_ext_steps(end)) ...
597  * min(max_extension_errs);
598  if get_field(detailed_data, 'bad_extension_on_explosion')
599  isbad = isbad | is_explosion;
600  else
601  isbad = isbad & is_explosion;
602  end
603  end
604  end
605 
606  end
607 
608 end