KerMor  0.9
Model order reduction for nonlinear dynamical systems and nonlinear approximation
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
ModelAnalyzer.m
Go to the documentation of this file.
1 
2 
3 /* (Autoinserted by mtoc++)
4  * This source code has been filtered by the mtoc++ executable,
5  * which generates code that can be processed by the doxygen documentation tool.
6  *
7  * On the other hand, it can neither be interpreted by MATLAB, nor can it be compiled with a C++ compiler.
8  * Except for the comments, the function bodies of your M-file functions are untouched.
9  * Consequently, the FILTER_SOURCE_FILES doxygen switch (default in our Doxyfile.template) will produce
10  * attached source files that are highly readable by humans.
11  *
12  * Additionally, links in the doxygen generated documentation to the source code of functions and class members refer to
13  * the correct locations in the source code browser.
14  * However, the line numbers most likely do not correspond to the line numbers in the original MATLAB source files.
15  */
16 
18  :public handle {
37  public:
38 
39  SingleFigures = false;
40 
41 
42  UseOutput = true;
43 
44 
45  private:
46 
47  rm;
48 
49 
50  public:
51 
52 
54  if ~isa(rmodel," models.ReducedModel ")
55  error(" rmodel must be a models.ReducedModel subclass. ");
56  end
57  this.rm= rmodel;
58  }
59 
60 
61  function [matrix<double>params , errs , details ] = getRedErrForRandomParamSamples(integer num,integer seed,in) {
62  if nargin < 4
63  in = [];
64  if nargin < 3
65  seed = round(cputime*100);
66  if nargin < 2
67  num = 50;
68  end
69  end
70  end
71  params = this.rm.FullModel.getRandomParam(num, seed);
72  [errs, details] = getRedErrForParamSamples(this, params, in);
73  }
93  function [errs , details ] = getRedErrForParamSamples(integer params,integer in) {
94  fm = this.rm.FullModel;
95  if nargin < 3
96  in = [];
97  if nargin < 2
98  params = fm.Data.ParamSamples;
99  end
100  end
101  num = size(params,2);
102  details = struct;
103  details.params= params;
104  details.L2Errs= zeros(num,length(fm.Times));
105  details.L2Fullsol= details.L2Errs;
106  details.L2OutErrs= details.L2Errs;
107  details.L2OutFullsol= details.L2Errs;
108  details.Linferrs= details.L2Errs;
109  details.Linftruesolnorm= details.L2Errs;
110  details.Times= zeros(num,2); /* computation times full/reduced */
111 
112  haveerrest = ~isempty(this.rm.ErrorEstimator) && this.rm.ErrorEstimator.Enabled;
113  if haveerrest
114  details.Estimates= details.L2Errs;
115  details.OutEstimates= details.L2Errs;
116  errs = zeros(8,num);
117  else
118  errs = zeros(6,num);
119  end
120  pi = ProcessIndicator(" Computing reduction error details for %d param samples ",...
121  num,false,num);
122  for pidx = 1:num
123  mu = params(:,pidx);
124  [~, y, tf, x] = fm.simulate(mu, in);
125  [~, yr, tr, xr] = this.rm.simulate(mu, in);
126  details.Times(pidx,:) = [tf tr];
127  details.L2Errs(pidx,:) = Norm.L2(x-this.rm.V*xr);
128  details.L2Fullsol(pidx,:) = Norm.L2(x);
129  details.L2OutErrs(pidx,:) = Norm.L2(y-yr);
130  details.L2OutFullsol(pidx,:) = Norm.L2(y);
131  details.Linferrs(pidx,:) = Norm.Linf(x-this.rm.V*xr);
132  details.Linftruesolnorm(pidx,:) = Norm.Linf(x);
133  errs(1,pidx) = max(details.L2Errs(pidx,:)); /* linf l2 err */
134 
135  errs(2,pidx) = errs(1,pidx) ./ max(details.L2Fullsol(pidx,:)); /* rel */
136 
137  errs(3,pidx) = max(details.L2OutErrs(pidx,:)); /* linf l2 err - output */
138 
139  errs(4,pidx) = errs(3,pidx) ./ max(details.L2OutFullsol(pidx,:)); /* rel - output */
140 
141  errs(5,pidx) = max(details.Linferrs(pidx,:)); /* linf linf err */
142 
143  errs(6,pidx) = errs(5,pidx) ./ max(details.Linftruesolnorm(pidx,:)); /* rel */
144 
145  if haveerrest
146  /* Effectivity (w.r.t. L2 error)
147  * State space */
148  details.Estimates(pidx,:) = this.rm.ErrorEstimator.StateError;
149  errs(5,pidx) = details.Estimates(pidx,end)/details.L2Errs(pidx,end);
150  /* Output */
151  details.OutEstimates(pidx,:) = this.rm.ErrorEstimator.OutputError;
152  errs(6,pidx) = details.OutEstimates(pidx,end)/details.L2OutErrs(pidx,end);
153  end
154  pi.step;
155  end
156  pi.stop;
157  }
176  function plotRedErrForParamSamples(errs,pm) {
177  }
185  function [t , pm ] = compareRedFull(mu,inputidx) {
186  if nargin < 3
187  inputidx = [];
188  if nargin < 2
189  mu = [];
190  end
191  end
192  fm = this.rm.FullModel;
193  [~, y, ftime] = fm.simulate(mu,inputidx);
194  [ti,yr, rtime] = this.rm.simulate(mu,inputidx);
195  /* % Text output */
196  str = sprintf(" %s ",fm.Name);
197  if ~isempty(mu)
198  str = sprintf(" %s, mu=[%s] ",str,Utils.implode(mu," , "," %2.3f "));
199  end
200  if ~isempty(inputidx)
201  str = sprintf(" %s, u_%d ",str,inputidx);
202  end
203  t = PrintTable(" Computation times %s: ",str);
204  t.HasRowHeader= true;
205  t.addRow(" Full model ",ftime,[" %2.4fs "]);
206  t.addRow(" Reduced model ",rtime,[" %2.4fs "]);
207  t.addRow(" Speedup ",ftime/rtime,[" x%2.4f "]);
208  t.display;
209 
210  /* L^2 errors */
211  l2 = Norm.L2(yr-y);
212  lil2 = max(l2);
213  l2l2 = Norm.L2(l2^t);
214  meanl2 = mean(l2);
215  l2relyl2 = l2 ./ Norm.L2(y);
216  l2l2relyl2 = Norm.L2(l2relyl2^t);
217  lil2relyl2 = max(l2relyl2);
218  meanrell2 = mean(l2relyl2);
219  /* fprintf('||y(t_i)||_2: %s',Utils.implode(l2,', ','%2.3f')); */
220  t = PrintTable(" Error comparison for %s: ",str);
221  t.addRow(" L2 time and space error "," L^2(||y(t) - yr(t)||_2,[0,T]) ",l2l2);
222  t.addRow(" Linf time and L2 space error "," L^inf(||y(t) - yr(t)||_2,[0,T]) ",lil2);
223  t.addRow(" Relative L2 time and space error "," L^2(||(y(t) - yr(t)) / y(t)||_2,[0,T]) ",l2l2relyl2);
224  t.addRow(" Relative Linf time and L2 space error ", " L^inf(||(y(t) - yr(t)) / y(t)||_2,[0,T]) ",lil2relyl2);
225  t.addRow(" Mean L2 error "," Mean(||y(t) - yr(t)||_2,[0,T]) ",meanl2);
226  t.addRow(" Mean relative L2 error "," Mean(||(y(t) - yr(t)) / y(t)||_2,[0,T]) ",meanrell2);
227 
228  /* L^inf errors */
229  li = Norm.Linf(yr-y);
230  lili = max(li);
231  l2li = Norm.L2(li^t);
232  meanli = mean(li);
233  lirelyli = li ./ Norm.Linf(y);
234  l2lirelyli = Norm.L2(lirelyli^t);
235  lilirelyli = max(lirelyli);
236  meanrelli = mean(lirelyli);
237  t.addRow(" Linf time and space error "," L^inf(||y(t) - yr(t)||_inf,[0,T]) ",lili);
238  t.addRow(" L2 time and Linf space error "," L^2(||y(t) - yr(t)||_inf,[0,T]) ",l2li);
239  t.addRow(" Relative Linf time and space error "," L^inf(||(y(t) - yr(t)) / y(t)||_inf,[0,T]) ",lilirelyli);
240  t.addRow(" Relative L2 time and Linf space error "," L^2(||(y(t) - yr(t)) / y(t)||_inf,[0,T]) ",l2lirelyli);
241  t.addRow(" Mean Linf error "," Mean(||y(t) - yr(t)||_inf,[0,T]) ",meanli);
242  t.addRow(" Mean relative Linf error "," Mean(||(y(t) - yr(t)) / y(t)||_inf,[0,T]) ",meanrelli);
243  if nargout < 1
244  t.display;
245  end
246 
247  /* % Plotting */
248  pm = PlotManager(false, 2, 2);
249  fm.plot(ti, y, pm.nextPlot(" full_sim ",sprintf(" Full simulation\n%s ",str)));
250  fm.plot(ti, yr, pm.nextPlot(" red_sim ",sprintf(" Reduced simulation\n%s ",str)));
251  fm.plot(ti, log10(abs(y-yr)), pm.nextPlot(" abs_err ",sprintf(" Absolute error (log scale)\n%s ",str)));
252  hlp = abs(y);
253  fm.plot(ti, log10(abs(y-yr)./hlp), pm.nextPlot(" rel_err ",sprintf(" Relative error (log scale)\n%s ",str)));
254  pm.done;
255  if nargout < 2
256  pm.LeaveOpen= true;
257  end
258  }
276  function [el2 , elinf , doublet , colvec<double>x , fx , afx ] = getTrajApproxError(colvec<double> mu,integer inputidx) {
277  fm = this.rm.FullModel;
278  if ~isempty(fm.Approx)
279  if nargin == 2
280  inputidx = [];
281  end
282  /* Computes trajectory (including cache-lookup in
283  * BaseFullModel!) */
284  [t,x] = fm.computeTrajectory(mu, inputidx);
285  if ~isempty(this.rm.V)
286  x = this.rm.V*(this.rm.W^t*x);
287  end
288  mu = repmat(mu,1,numel(t));
289  fx = fm.Approx.evaluateMulti(x,t,mu);
290  afx = fm.System.f.evaluateMulti(x,t,mu);
291  el2 = Norm.L2(fx-afx);
292  elinf = Norm.Linf(fx-afx);
293  else
294  error(" The approximation error can only be computed for models with an approx.BaseApprox instance present. ");
295  end
296  }
308  function [el2 , elinf , pm ] = getATDError(pm) {
309 
310  rm = this.rm;
311  fm = rm.FullModel;
312 
313  if ~isempty(fm.Approx)
314  if nargin < 2
315  pm = PlotManager(false,2,2);
316  end
317  /* Full approx */
318  atd = fm.Data.ApproxTrainData;
319  afx = fm.Approx.evaluateMulti(atd.xi.toMemoryMatrix,atd.ti,atd.mui);
320  s = 1:size(atd.xi,2);
321  fx = atd.fxi.toMemoryMatrix;
322  nofx = Norm.L2(fx);
323  el2 = Norm.L2(fx-afx);
324  elinf = Norm.Linf(fx-afx);
325  h = pm.nextPlot(" abs_l2 "," Absolute L2 error "," x_i "," L2 ");
326  LogPlot.cleverPlot(h,s,el2);
327  h = pm.nextPlot(" rel_l2 "," Relative L2 error "," x_i "," L2 ");
328  LogPlot.cleverPlot(h,s,el2./nofx);
329 
330  if ~isempty(rm.V)
331  rd = size(rm.V);
332  /* Projected variant */
333  apfx = this.rm.System.f.evaluateMulti(rm.W^t*atd.xi,atd.ti,atd.mui);
334  nofx = Norm.L2(afx);
335  pel2 = Norm.L2(afx-rm.V*apfx);
336  h = pm.nextPlot(" abs_proj_l2 ",...
337  sprintf(" Absolute L2 error projected vs full approx, %d/%d dims ",rd(2),rd(1)),...
338  " x_i "," L2 ");
339  LogPlot.cleverPlot(h,s,pel2);
340  h = pm.nextPlot(" rel_proj_l2 ",...
341  sprintf(" Relative L2 error projected vs full approx, %d/%d dims ",rd(2),rd(1)),...
342  " x_i "," L2 ");
343  LogPlot.cleverPlot(h,s,pel2./nofx);
344  end
345 
346  pm.done;
347  if nargout < 3
348  pm.LeaveOpen= true;
349  end
350  else
351  error(" The approximation error can only be computed for models with an approx.BaseApprox instance present. ");
352  end
353 
354  }
368  function pm = analyzeError(colvec<double> mu,integer inputidx,pm) {
369  if isempty(this.rm.ErrorEstimator)
370  error(" Error analysis only available for models with error estimator ");
371  end
372  rmodel = this.rm;
373  if nargin < 4
374  pm = PlotManager(false, 2, 3);
375  if nargin < 3
376  inputidx = rmodel.DefaultInput;
377  if nargin < 2
378  mu = rmodel.DefaultMu;
379  end
380  end
381  end
382 
383 
384  /* % Initial computations */
385  [~, y, time, x] = rmodel.FullModel.simulate(mu, inputidx);
386  rmodel.ErrorEstimator.Enabled= false;
387  tic; rmodel.simulate(mu, inputidx); timer_noerr = toc;
388  rmodel.ErrorEstimator.Enabled= true;
389  [t, yr, timer, xr] = rmodel.simulate(mu, inputidx);
390 
391  if this.UseOutput
392  x = y;
393  xr = yr;
394  est = rmodel.ErrorEstimator.OutputError;
395  else
396  if ~isempty(rmodel.V)
397  xr = rmodel.V*xr;
398  end
399  est = rmodel.ErrorEstimator.StateError;
400  end
401  e = Norm.L2(x - xr);
402  xnorm = Norm.L2(x);
403  erel = e./xnorm;
404  estrel = est./xnorm;
405  xrnorm = Norm.L2(xr);
406  erelr = e./xrnorm;
407  estrelr = est./xrnorm;
408 
409  /* % System plot */
410  xrmin = xr-repmat(est,size(xr,1),1); xrplus = xr+repmat(est,size(xr,1),1);
411  ymax = max([max(x(:)) max(xr(:)) max(xrmin(:)) max(xrplus(:))]);
412  ymin = min([min(x(:)) min(xr(:)) min(xrmin(:)) min(xrplus(:))]);
413 
414  if this.UseOutput
415  ti = sprintf(" The full system "" s output (m=%d,time=%.3f) ",size(x,1),time);
416  else
417  ti = sprintf(" The full system (d=%d,time=%.3f) ",size(x,1),time);
418  end
419  h = pm.nextPlot(" fullsys ",ti," time "," error ");
420  plot(h,t,Utils.preparePlainPlot(x));
421  axis([t(1) t(end) ymin ymax]);
422 
423  if this.UseOutput
424  h = pm.nextPlot(" outputs ",...
425  sprintf(" Full+reduced system outputs with error bounds\n(r=%d,self time:%.3f, time with err est:%.3f) ",...
426  size(rmodel.V,2),timer_noerr,timer),...
427  " time "," y(t) / y^r(t) ");
428  plot(h, t,Utils.preparePlainPlot(x)," b ",...
429  t, Utils.preparePlainPlot(xr)," r ",...
430  t, Utils.preparePlainPlot(xrmin),...
431  " r-- ",t,Utils.preparePlainPlot(xrplus)," r-- ");
432  legend(" Full system "," Reduced system "," Lower bound "," Upper bound ");
433  else
434  h = pm.nextPlot(" redsys ",sprintf(" Reduced system (r=%d,self time:%.3f,\ntime with err est:%.3f) ",size(rmodel.V,2),timer_noerr,timer),...
435  " time "," x^r(t) ");
436  plot(h, t, Utils.preparePlainPlot(xr)," r ");
437  end
438  axis([t(1) t(end) ymin ymax]);
439 
440  /* % Absolute value plot */
441  h = pm.nextPlot(" norms "," The state variable norms "," time "," norms ");
442  plot(h, t, xnorm," b ",t,xrnorm," r ",t,xrnorm-est," r-- ",t,xrnorm+est," r-- ");
443  le = legend(" Full system "," Reduced system "," Lower bound "," Upper bound ");
444  set(le," Location "," NorthWest ");
445 
446  /* Error plots */
447  h = pm.nextPlot(" abserrors ",sprintf(" The state variable absolute errors.\nmean(e)=%g, mean(est)=%g ",mean(e),mean(est)),...
448  " time "," errors ");
449  semilogy(h,t,est," b ",t,e," r ");/* ,t,abs(e-est),'g'); */
450 
451  legend(" Estimated error "," True error ");/* ,'Location','Best'); */
452 
453 
454  /* Relative Error plots */
455  h = pm.nextPlot(" relerrors ",sprintf([" The state variable relative errors (comp. to "...
456  " full solution)\nmean(e_{rel})=%g, mean(est_{rel})=%g "],...
457  mean(erel),mean(estrel)),...
458  " time "," errors ");
459  semilogy(h,t,estrel," b ",t,erel," r ");
460  legend(" Estimated error "," True error ");/* ,'Location','Best'); */
461 
462 
463  h = pm.nextPlot(" relerrors_red ",sprintf([" The state variable relative errors (comp. to "...
464  " reduced solution)\nmean(ered_{rel})=%g, mean(estred_{rel})=%g "],...
465  mean(erelr),mean(estrelr)),...
466  " time "," errors ");
467  semilogy(h,t,erelr," r ",t,estrelr," b ");
468  legend(" True error "," Estimated error ");/* ,'Location','Best'); */
469 
470  if nargin < 4
471  pm.done;
472  end
473  }
474 
475 
476  function pm = plotReductionOverview(pm) {
477  if nargin < 2
478  pm = PlotManager(false,2,2);
479  pm.LeaveOpen= true;
480  end
481  [~,m,~,l] = FindInstance(this.rm.FullModel," IReductionSummaryPlotProvider ");
482  for k=1:length(m)
483  objs = m[k];
484  nobj = length(objs);
485  extra = ;
486  for i=1:nobj
487  if nobj > 0
488  extra = sprintf(" -%d ",i);
489  end
490  context = sprintf(" %s%s (%s) ",l[k],extra,class(objs(i)));
491  objs(i).plotSummary(pm,context);
492  end
493  end
494  pm.done;
495  }
509 };
510 
511 
512 
ModelAnalyzer: Analysis tools for reduced models and approximations.
Definition: ModelAnalyzer.m:17
Collection of generally useful functions.
Definition: Utils.m:17
function pm = analyzeError(colvec< double > mu,integer inputidx, pm)
LogPlot: Class with static functions for logarithmic plotting.
Definition: LogPlot.m:17
function [ el2 , elinf , pm ] = getATDError(pm)
Computes the approximation training error on the full system's trajectory for given mu and inputidx...
function [ PrintTable t , cell matches , parents , cell locations ] = FindInstance(handle obj,char type, varargin)
FindInstance: Locate instances of certain classes within a class or a struct.
Definition: FindInstance.m:17
An integer value.
The KerMor reduced model class.
Definition: ReducedModel.m:18
PlotManager: Small class that allows the same plots generated by some script to be either organized a...
Definition: PlotManager.m:17
Matlab's base handle class (documentation generation substitute)
static function handle p = cleverPlot(handle ax,rowvec< double > x,rowvec< double > y, varargin)
Calls corresponding plot routines depending on the scale of data.
Definition: LogPlot.m:158
function [ t , pm ] = compareRedFull(mu, inputidx)
Compares the solutions of the reduced model and the associated full model by calling the BaseModel...
static function rowvec< double > n = Linf(matrix< double > x)
Returns the discrete norm for each column vector in x.
Definition: Norm.m:73
ModelAnalyzer(models.ReducedModel rmodel)
Definition: ModelAnalyzer.m:53
function [ el2 , elinf , double t , colvec< double > x , fx , afx ] = getTrajApproxError(colvec< double > mu,integer inputidx)
Computes the approximation training error on the full system's trajectory for given mu and inputidx...
PrintTable: Class that allows table-like output spaced by tabs for multiple rows. ...
Definition: PrintTable.m:17
static function char str = implode(char|rowvec data,char glue,char format)
Implodes the elements of data using glue.
Definition: Utils.m:208
static function rowvec< double > n = L2(matrix< double > x)
Returns the discrete norm for each column vector in x.
Definition: Norm.m:39
function [ errs , details ] = getRedErrForParamSamples(integer params,integer in)
Computes the simulation errors (output) for the given model parameters.
Definition: ModelAnalyzer.m:93
Norm: Static class for commonly used norms on sets of vectors.
Definition: Norm.m:17
function pm = plotReductionOverview(pm)
function [ matrix< double > params , errs , details ] = getRedErrForRandomParamSamples(integer num,integer seed, in)
Computes the simulation errors (output) for num random model parameters.
Definition: ModelAnalyzer.m:61
ProcessIndicator: A simple class that indicates process either via waitbar or text output...
static function y = preparePlainPlot(y)
Memory-saving plotting for plain result plots.
Definition: Utils.m:297
function plotRedErrForParamSamples(errs, pm)
\todo implement, so far only plotting in DEIM testing with multiple DEIM m Orders.