rbmatlab  1.13.10
 All Classes Namespaces Files Functions Variables Groups Pages
IReducedModel.m
1 classdef IReducedModel < IModel
2  % This is the interface for a reduced model providing methods to compute low
3  % dimensional reduced simulations based on a priori generated reduced basis
4  % spaces.
5  %
6  % An IReducedModel implementation is the final puzzle piece in the reduced
7  % basis framework as described the section on the @ref rbm_interface "main
8  % interfaces".
9  %
10  % Note, that this interface implements an IDetailedModel interface, by
11  % forwarding all methods to the underlying #detailed_model. By this, the
12  % reduced model is the only needed. This is again for historic reasons
13  % assuring compatibility with old codes which did not distinguish between
14  % reduced and detailed models.
15  %
16  % Usually a reduced model 'r_model' is used in the following way and order:
17  % -# Generate detailed data
18  % @code reduced_data = gen_detailed_data(r_model, model_data) @endcode
19  % -# Generate reduced data
20  % @code reduced_data = gen_reduced_data(r_model, detailed_data) @endcode
21  % -# (Optionally) extract a subset from this reduced_data
22  % @code reduced_data = extract_reduced_data_subset(r_model, reduced_data) @endcode
23  % -# Compute one or more reduced simulations by
24  % -# Setting the active parameter
25  % @code set_mu(r_model, mu) @endcode
26  % and
27  % -# executing the simulation
28  % @code rb_sim_data = rb_simulation(r_model, reduced_data) @endcode
29  % -# Optionally reconstruct the reduced simulation snapshots
30  % `u_{\text{red}}(\cdot; t^k, \mu) \in {\cal W}_{\text{red}}`
31  % @code rb_sim_data = rb_reconstruction(r_model, detailed_data, rb_sim_data) @endcode
32  %
33 
34  properties(Dependent, SetAccess = private)
35  % @copybrief IDetailedModel.descr
36  descr;
37  end
38 
39  properties (Dependent)
40  decomp_mode;
41  end
42 
43  properties (SetAccess = private, Dependent)
44  % cell array of strings describing the parameters of the model
45  mu_names;
46 
47  % cell array of vectors of size two defining the allowed interval range for
48  % the parameter components
49  mu_ranges;
50 
51  % an integer defining the verbosity level of information output during
52  % basis generation
53  verbose;
54 
55  % an integer defining the debugging level controlling error output and
56  % extra tests during basis generation
57  debug;
58  end
59 
60  properties
61  % flag indicating whether this model depends on collateral reduced basis
62  % spaces.
63  crb_enabled = false;
64 
65  % an object of type IDetailedModel which shall be reduced
66  detailed_model;
67 
68  % a structure of type BasisGenDescr defining the basis generation routines
69  % and data structures.
70  bg_descr;
71  end
72 
73  properties(Abstract)
74  % boolean flag indicating whether during an rb_simulation() an a posteriori
75  % error estimator shall be computed.
76  %
77  % This flag needs to be set to 'true' for certain Basis generation
78  % configurations.
79  enable_error_estimator;
80  end
81 
82  properties
83  % control variable for the size of the reduced basis used for reduced
84  % simulations. By default this is equal to the size of the generated
85  % reduced basis.
86  N = 0;
87 
88  % control variable for the size of the (collateral) reduced basis used for
89  % empirical interpolations. By default this is equal to the size of the
90  % generated reduced basis.
91  M = 0;
92 
93  % control variable for the number of (collateral) reduced basis vectors
94  % used for error estimation. By default this is equal to zero.
95  Mstrich = 0;
96  end
97 
98  methods
99  function rmif = IReducedModel(dmodel, bg_descr)
100  % Constructor of a reduced model
101  %
102  % Parameters:
103  % dmodel: the object of type IDetailedModel for which the reduced model
104  % shall be constructed.
105  if nargin == 1 || isempty(bg_descr)
106  copy = dmodel;
107  % check if the first argument is an IReducedModel -> copy constructor
108  if isa(copy, 'IReducedModel')
109  % dmodel constructor
110  m = metaclass(dmodel);
111  fns = m.Properties(cellfun(@(x) ~isequal(x.SetAccess, 'none') && ~x.Dependent, m.Properties));
112  fns = cellfun(@(x) x.Name, fns, 'UniformOutput', false);
113  for i=1:length(fns)
114  rmif.(fns{i}) = copy.(fns{i});
115  end
116  else
117  error('IReducedModel copy constructor needs to get only one argument');
118  end
119  elseif nargin == 2
120  rmif.detailed_model = dmodel;
121  rmif.bg_descr = bg_descr;
122  if ~IReducedModel.struct_check(bg_descr, ...
123  struct( ...
124  'reduced_data_constructor', {{@(x) isequal(class(x), 'function_handle')}}, ...
125  'detailed_data_constructor', {{@(x) isequal(class(x), 'function_handle')}}...
126  )...
127  );
128  error('Consistency check for IReducedModel failed');
129  end
130  else
131  error('IReducedModel constructor needs to get two arguments');
132  end
133  end
134 
135  function descr = get.descr(this)
136  descr = this.detailed_model.descr;
137  end
138 
139  function mu_ranges = get.mu_ranges(this)
140  mu_ranges = this.detailed_model.descr.mu_ranges;
141  end
142 
143  function mu_names = get.mu_names(this)
144  mu_names = this.detailed_model.descr.mu_names;
145  end
146 
147  function decomp_mode = get.decomp_mode(this)
148  decomp_mode = this.detailed_model.descr.decomp_mode;
149  end
150 
151  function set.decomp_mode(this, decomp_mode)
152  this.detailed_model.decomp_mode = decomp_mode;
153  end
154 
155  function debug = get.debug(this)
156  debug = this.detailed_model.descr.debug;
157  end
158 
159  function verbose = get.verbose(this)
160  verbose = this.detailed_model.descr.verbose;
161  end
162 
163  function iseq = eq(this, other)
164  % function iseq = eq(this, other)
165  % Comparison operator checking whether the underlying #detailed_model
166  % members of 'this' and 'other' are equal.
167  %
168  % Parameters:
169  % other: an object of type IReducedModel we want to compare with.
170  %
171  % Return values:
172  % iseq: a boolean value indicating whether 'this' and 'other' are
173  % equal.
174  iseq = (this.detailed_model == other.detailed_model);
175  end
177  function reduced_data = gen_reduced_data(this, detailed_data)
178  % function reduced_data = gen_reduced_data(this, detailed_data);
179  % Constructs the 'reduced_data' object holding low dimensional data needed
180  % for efficient reduced simulations with rb_simulation().
181  %
182  % Return values:
183  % reduced_data: reduced data object of type IReducedData.
184 
185  reduced_data = this.bg_descr.reduced_data_constructor(this, detailed_data);
186  end
188  function reduced_data_subset = extract_reduced_data_subset(this, reduced_data)
189  % function reduced_data = extract_reduced_data_subset(this, reduced_data);
190  % Extracts a subset of the 'reduced_data' generated by gen_reduced_data().
191  %
192  % Return values:
193  % reduced_data: object of type IReducedData holding a subset of the
194  % reduced data fields as they were generated by
195  % gen_reduced_data().
196 
197  if isa(reduced_data, 'IDetailedData')
198  reduced_data_subset = gen_reduced_data(this, reduced_data);
199  else
200  reduced_data_subset = extract_reduced_data_subset(reduced_data, this);
201  end
202  end
203  end
204 
205  methods(Abstract)
206 
207 
208  % function rb_sim_data = rb_simulation(this, reduced_data);
209  % Executes a reduced simulation and optionally an error estimation.
210  %
211  % Return values:
212  % rb_sim_data: structure holding the coefficient vectors of the reduced
213  % simulations and optional error estimators.
214  rb_sim_data = rb_simulation(this, reduced_data);
215 
216  % function rb_sim_data = rb_reconstruction(this, detailed_data, rb_sim_data);
217  % reconstructs the reduced simulation snapshots generated by
218  % rb_simulation() in the reduced space `{\cal W}_{\text{red}}`.
219  %
220  % Possible implementations are:
222  %
223  % Parameters:
224  % rb_sim_data: struct holding reduced simulation data returned by
225  % IReducedModel.rb_simulation() .
226  %
227  % Return values:
228  % rb_sim_data: struct holding the reduced simulation results and their
229  % reconstructions.
230  rb_sim_data = rb_reconstruction(this, detailed_data, rb_sim_data);
231 
232  % function c = copy(this);
233  % function that deep copies this handle class
234  %
235  % The suggested implementation in the implementation class should call a
236  % copy constructor which might look as follows:
237  %
238  % @code
239  % // this implements a copy constructor if necessary...
240  % rm = rm@IReducedModel(detailed_model, bg_descr);
241  % // are we NOT a copy constructor?
242  % if ~isa(detailed_model, 'Implementation.ReducedModel')
243  % // do some checks and further initializations here...
244  % end
245  % @endcode
246  %
247  % Return values:
248  % c: an object of type IReducedModel which is a deep copy of this object.
249  c = copy(this);
250  end
251 
252  methods(Static, Abstract)
253  % function Delta = get_estimators_from_sim_data(sim_data);
254  % Static helper method returning the vectors of error estimators for each
255  % reduced simulation snapshot `u_{\text{red}}(\cdot, t^k)` generated by
256  % rb_simulation().
257  %
258  % Parameters:
259  % rb_sim_data: struct holding reduced simulation data returned by
261  %
262  % Return values:
263  % Delta: This is a '(K+1) x 1' vector of estimates `\eta^k(\mu)`
264  Delta = get_estimators_from_sim_data(rb_sim_data);
265 
266  % function Delta = get_estimator_from_sim_data(sim_data);
267  % Static helper method returning an error estimator for the whole
268  % reduced trajectory `\{u_{\text{red}}(\cdot, t^k)\}_{k=0}^{K}` generated
269  % by rb_simulation().
270  %
271  % Parameters:
272  % rb_sim_data: struct holding reduced simulation data returned by
274  %
275  % Return values:
276  % Delta: This is a scalar computed from the estimates `\eta^k(\mu)`.
277  % Usually the maximum over `k=0,\ldots,K` is returned.
278  Delta = get_estimator_from_sim_data(rb_sim_data);
279 
280  end
281 
282  methods
283 
284  function U = get_dofs_from_sim_data(rmodel, sim_data)
285  % function U = get_dofs_from_sim_data(sim_data)
287  %
289  U = rmodel.detailed_model.get_dofs_from_sim_data(sim_data);
290  end
291 
292  end
293 
294  methods
295  function detailed_data = gen_detailed_data(this, model_data)
296  % function detailed_data = gen_detailed_data(this, model_data)
297  % initiates the reduced basis generation process
298  %
299  % This function calls the IDetailedData constructor specified by
300  % 'bg_descr.detailed_data_constructor' and returns the generated detailed
301  % data object..
302  %
303  % Return values:
304  % detailed_data: constructed detailed data object of type
305  % IDetailedData.
306 
307  detailed_data = this.bg_descr.detailed_data_constructor(this, model_data);
308  end
309 
310  function p = plot_sim_data(rmodel, model_data, sim_data, plot_params)
311  % function p = plot_sim_data(rmodel, model_data, sim_data, plot_params)
312  % @copybrief IDetailedModelplot_sim_data()
313  %
314  % This method actually calls the 'plot_sim_data()' method on the
315  % #detailed_model member.
316  % @copydetails IDetailedModel.plot_sim_data()
317  p = plot_sim_data(rmodel.detailed_model, model_data, sim_data, plot_params);
318  end
319 
320  function model_data = gen_model_data(this)
321  % @copybrief IDetailedModelgen_model_data()
322  %
323  % This function call is forwarded to the underlying #detailed_model.
324  %
325 
326  model_data = gen_model_data(this.detailed_model);
327  end
328 
329  function sim_data = detailed_simulation(this, model_data)
331  %
332  % This function call is forwarded to the underlying #detailed_model.
333  %
334  % Return values:
335  % sim_data: structure holding the detailed simulation result.
336  sim_data = detailed_simulation(this.detailed_model, model_data);
337  end
338 
339  function this = set_mu(this, mu)
340  % function this = set_mu(this, mu)
341  % Sets the active parameter vector `\mu \in {\cal M}` used for simulations
342  % on this model.
343  %
344  % The parameter set here, is also used by the rb_simulation() function.
345  % So, the #detailed_model and the reduced model's internal parameter
346  % vector in sync.
347  %
348  % Parameters:
349  % mu: The parameter vector `\mu`.
350  %
351  % Return values:
352  % this: handle to the changed IReducedModel
353 
354  this.detailed_model = set_mu(this.detailed_model, mu);
355 
356  end
357 
358  function mu = get_mu(this)
359  % function mu = get_mu(this)
360  % returns the active parameter vector `\mu \in { \cal M }`
361  %
362  % Return values:
363  % mu: The parameter vector `\mu`
364  mu = get_mu(this.detailed_model);
365  end
366 
367  function rb_size = get_rb_size(this, detailed_data)
368  % function rb_size = get_rb_size(this, detailed_data)
369  % returns the size of the generated reduced basis by the
370  % IDetailedData class.
371  %
372  % This method only forwards the call to the
373  % IDetailedData.get_rb_size() method. So, it is pretty useless, but
374  % necessary for compatibility with the old interface...
375  rb_size = get_rb_size(detailed_data);
376  end
377 
378  function couple_N_and_M(this, detailed_data, ratio, factor)
379  % function couple_N_and_M(this, detailed_data, ratio, factor)
380  % sets all the basis sizes for reduced simulations by a ratio with
381  % respect to the maximum possible basis size and a factor between RB and
382  % EI basis sizes.
383  %
384  % This method sets
385  % ``(N, M^{L_1}, \dots, M^{L_q})
386  % = \left(\lfloor r N_{\max} \rfloor, \lfloor r_M M_{\max}^{'L_1} \rfloor,
387  % \dots, \lfloor r_M M_{\max}^{'L_q} \rfloor\right),``
388  % where `r_M = \min\{ rf, 1 \}` and `M_{\max}^{'L} == M_{\max}^L - M'`.
389  %
390  % Parameters:
391  % ratio: an integer from the interval `[0, 1]` specifying the ratio `r`
392  % by which the number of collateral reduced basis functions
393  % shall be reduced with respect to the maximum possible.
394  % factor: an (optional) positive factor `f` between RB and EI basis
395  % sizes. (default = 1)
396 
397  assert(ratio >= 0 && ratio <= 1.0);
398 
399  if nargin == 3
400  factor = 1.0;
401  end
402  assert(factor >= 0);
403 
404  Nmax = get_rb_size(detailed_data);
405  this.N = floor(Nmax * ratio);
406  set_Mratio(this, detailed_data, min(ratio*factor,1));
407  end
408 
409  function this = set_Mratio(this, detailed_data, ratio)
410  % function set_Mratio(this, detailed_data, ratio)
411  % in case of multiple operators subject to empirical interpolation, this
412  % sets number of reduced basis functions used for reduced simulations by
413  % specifying a ratio.
414  %
415  % This method sets
416  % ``M^{L} = \lfloor M_{\max}^{'L} \cdot \text{ratio} \rfloor``
417  % for all operators/functions `L`, where `M_{\max}^{'L} == M_{\max}^L - M'`.
418  %
419  % Parameters:
420  % ratio: an integer from the interval `[0, 1]` specifying the ratio by
421  % which the number of collateral reduced basis functions shall
422  % be reduced with respect to the maximum possible.
423  assert(ratio <= 1 && ratio >= 0);
424  Mmax = get_ei_size(detailed_data.datatree);
425  if isa(Mmax, 'DataTree.IdMapNode')
426  for i = 1:length(Mmax)
427  set(this.M,i,floor((get(Mmax,i)-this.Mstrich) * ratio));
428  end
429  else
430  this.M = floor((Mmax-this.Mstrich) * ratio);
431  end
432  end
433 
434  function Mratio = get_Mratio(this, detailed_data)
435  % function Mratio = get_Mratio(this, detailed_data)
436  % in case of multiple operators subject to empirical interpolation, this
437  % gets the mean of ratio between the number of reduced basis functions
438  % used for reduced simulations and the maximum possible.
439  %
440  % This function gets the mean of
441  % `\frac{M^{L}}{M_{\max}^{L}}` over for all operators/functions `L`.
442  %
443  % Return values:
444  % Mratio: an integer from the interval `[0, 1]` specifying the ratio by
445  % which the number of collateral reduced basis functions is
446  % reduced with respect to the maximum possible.
447  M = this.M;
448  if isa(M, 'DataTree.IdMapNode')
449  M = scalar(M, @(x) mean([x{:}]));
450  end
451  Mmax = get_ei_size(detailed_data.datatree);
452  if isa(Mmax, 'DataTree.IdMapNode')
453  Mmax = scalar(Mmax, @(x) mean([x{:}]));
454  end
455  if ~isempty(Mmax)
456  Mratio = M/Mmax;
457  end
458 
459  end
460 
461  function ret = subsref(this, S)
462  % function ret = subsref(this, S)
463  % forwarding of fieldnames access to the underlying detailed_model description
464  %
465  % If the user calls 'r_model.parameter' and the field 'parameter' exists
466  % in the underlying model, the value of 'detailed_model.descr.parameter' is
467  % returned. This method is implemented for compatibility reasons, such that
468  % a basis generation object can be used like an old model. Try to prevent
469  % usage of this method in the future.
470  %
471  % @note that this method throws a 'RBmatlab:Compatibility' warning if a
472  % description field is accessed.
473 
474  ddescr = this.detailed_model.descr;
475  thissubs = [properties(this); methods(this)];
476  fns = setdiff(fieldnames(ddescr), thissubs);
477  if S(1).type(1) == '.' ...
478  && ~isempty(intersect(fns, S(1).subs))
479  warning('RBmatlab:Compatibility', ...
480  ['Requesting the reduced_model field ''', S(1).subs, ...
481  '''\nfrom a IReducedModel object! Maybe you should\n',...
482  'substitute the ''rmodel'' by a ''rmodel.detailed_model''']);
483  ret = this.descr.(S(1).subs);
484  else
485  if nargout == 1
486  ret = builtin('subsref', this, S);
487  else
488  builtin('subsref', this, S)
489  end
490  end
491  end
492  end
493 
494 end