rbmatlab 0.10.01
|
00001 classdef Output < handle 00002 % result class for computations executed by an 00003 % Postprocess.StochasticAssessment.Assessment object. 00004 % 00005 % This class provides methods to transform and visualize the gathered data 00006 % for publication in LaTeX/Tikz documents. 00007 00008 properties 00009 00010 % values computed by Postprocess.StochasticAssessment.Assessment 00011 % 00012 % Usually this is a cell array of structure arrays. For cells correspond to 00013 % the @ref Assessment.rsamples "rsamples" and the structure array 00014 % corresponds to the test samples given by @ref Assessment.M_test "M_test". 00015 values; 00016 00017 % cell array of all condition numbers of reduced simulaton system matrices. 00018 rd_conds; 00019 00020 rtime_est = {}; % time for the computation of the error estimator. By default this is not set. 00021 00022 % the object of type Assessment with which the values are generated 00023 % 00024 % @todo Maybe we should cache this, too... 00025 assessment; 00026 00027 % maxmimum error values to be plotted. Above this values error display is 00028 % cropped. 00029 % 00030 % @default = 1; 00031 error_bound = 1; 00032 00033 % maxmimum estimator values to be plotted. Above this values error display 00034 % is cropped. 00035 % 00036 % @default = 100; 00037 estimator_bound = 100; 00038 00039 % define stability-region as error being smaller than sqrt(diffmax * area), 00040 % e.g. diffmax = 4, area = 2e-7 00041 00042 % stability region 00043 % 00044 % If the averaged error exceeds this value, the visualization is cropped 00045 % here. This happens especially for small reduced basis sizes. (Default = 00046 % '1e-2') 00047 stab_limit = 1e-2; 00048 00049 end 00050 00051 methods 00052 00053 function output = Output(values, assessment) 00054 % function output = Output(values, assessment) 00055 % Constructor 00056 % 00057 % Parameters: 00058 % values: the structure with the gathered data by the 00059 % Postprocess.StochasticAssessment.Assessment object 00060 % assessment: the generating object of type Postprocess.StochasticAssessment.Assessment 00061 00062 output.values = values; 00063 output.assessment = assessment; 00064 00065 end 00066 00067 function plot_landscape(this) 00068 %function plot_landscape(this) 00069 % plots a two dimensional error landscape in case of two dimensional 00070 % @ref Assessment.plot_fields "plot_fields" 00071 % 00072 % Used attributes: 00073 % - #error_bound and 00074 % - #stab_limit 00075 00076 errs = this.get_slice('max_err'); 00077 i = logical(errs>this.error_bound); 00078 errs(i) = this.error_bound; 00079 i = logical(isnan(errs)); 00080 errs(i) = this.error_bound; 00081 reshape(errs, size(this.values)); 00082 C = ones(size(errs)); 00083 i = logical(errs<this.stab_limit); 00084 C(i) = 2; 00085 00086 figure; 00087 if length(this.assessment.samples) == 2 00088 if isempty(find(C==1,1)); % i.e. all stable 00089 surf(this.assessment.samples{1},this.assessment.tsamples{2},errs'); 00090 else % some not stable 00091 surf(this.assessment.samples{1},this.assessment.tsamples{2},errs',C'); 00092 end; 00093 shading interp; 00094 % figure, pcolor(Ms, Ns,C); 00095 set(gca,'Zscale','log'); 00096 xlabel(this.assessment.pf_descr{1}); 00097 ylabel(this.assessment.pf_descr{2}); 00098 zlabel(this.assessment.error_label); 00099 else 00100 plot(this.assessment.rsamples, errs'); 00101 xlabel(this.assessment.pf_descr{1}); 00102 ylabel(this.assessment.error_label); 00103 set(gca,'Yscale','log'); 00104 end 00105 run_name = strrep(this.assessment.run_name,'_',' '); 00106 title([run_name,' L-infty([0,T],L2) error']); 00107 00108 figure; 00109 if length(this.assessment.samples) == 2 00110 surf(this.assessment.samples{1}, this.assessment.samples{2}, real(this.get_slice('max_err_inds'))); 00111 xlabel(this.assessment.pf_descr{1}); 00112 ylabel(this.assessment.pf_descr{2}); 00113 zlabel('time index'); 00114 else 00115 plot(this.assessment.samples, this.get_slice('max_err_inds')); 00116 xlabel(this.assessment.pf_descr{1}); 00117 zlabel('time index'); 00118 end 00119 00120 title('time index of maximum l2-error'); 00121 %set(gca,'Zscale','log'); 00122 end 00123 00124 function print_table(this, datafile) 00125 % function print_table(this, datafile) 00126 % prints out a CSV table with gathered data. 00127 % 00128 % An example for a pgfplotstable graphic that can interpret the table output 00129 % is shown in the following code snippet: 00130 % @code 00131 % \pgfplotstabletypeset[ 00132 % font={\footnotesize}, 00133 % columns={dim1,dim2,{time_avg},{err_max},{offtime_total}}, 00134 % columns/{dim1}/.style={ 00135 % column name={N}, 00136 % postproc cell content/.append code={% 00137 % \ifnum\pgfplotstablerow=0 00138 % \pgfkeyssetvalue{/pgfplots/table/@cell content}{$H={}$#2}% 00139 % \fi 00140 % }% 00141 % }, 00142 % columns/{dim2}/.style={ 00143 % column name={M}, 00144 % postproc cell content/.append code={% 00145 % \ifnum\pgfplotstablerow=0 00146 % \pgfkeyssetvalue{/pgfplots/table/@cell content}{\ensuremath{-}}% 00147 % \fi 00148 % }, 00149 % }, 00150 % columns/{time_avg}/.style={ 00151 % column name={\o-run--time[s]} 00152 % }, 00153 % columns/{err_max}/.style={ 00154 % column name={max. error} 00155 % }, 00156 % columns/{offtime_total}/.style={ 00157 % column name={offline time[h]}, 00158 % divide by=3600 00159 % }, 00160 % every even row/.style={ 00161 % before row={\rowcolor[gray]{0.9}}}, 00162 % every head row/.style={ 00163 % before row=\toprule,after row=\midrule}, 00164 % every last row/.style={ 00165 % after row=\bottomrule}, 00166 % display columns/2/.style={dec sep align}, 00167 % display columns/3/.style={zerofill,precision=2}, 00168 % empty cells with={\ensuremath{-}} 00169 % ]{table.dat}; 00170 % @endcode 00171 % 00172 % Parameters: 00173 % datafile: a string specifying the path and filename of the data table to be stored 00174 % 00175 % This function prints out a table with data for the average, min and max 00176 % values of 00177 % - reduced simulation time, 00178 % - reduced simulation reconstruction time, 00179 % - reduced simulation error estimator computation time, 00180 % - maximum error estimator and the 00181 % - maximum "true" error 00182 % Furthermore, the offline time is printed out split up into 00183 % - the total time spent in the offline phase, 00184 % - the time spent for (pre-)computation of detailed simulations 00185 % - the time spent in the EI-greedy algorithm 00186 % - the time spent in the reduced basis generation algorithm 00187 ratime = this.reduce_slice(@mean, 'rtime'); 00188 rmtime = this.reduce_slice(@min, 'rtime'); 00189 rMtime = this.reduce_slice(@max, 'rtime'); 00190 rratime = this.reduce_slice(@mean, 'rrtime'); 00191 rrmtime = this.reduce_slice(@min, 'rrtime'); 00192 rrMtime = this.reduce_slice(@max, 'rrtime'); 00193 restatime = this.reduce_slice(@mean, 'rtime_est'); 00194 restmtime = this.reduce_slice(@min, 'rtime_est'); 00195 restMtime = this.reduce_slice(@max, 'rtime_est'); 00196 etaa = this.reduce_slice(@mean, 'max_Delta'); 00197 etam = this.reduce_slice(@min, 'max_Delta'); 00198 etaM = this.reduce_slice(@max, 'max_Delta'); 00199 erra = this.reduce_slice(@mean, 'max_err'); 00200 errm = this.reduce_slice(@min, 'max_err'); 00201 errM = this.reduce_slice(@max, 'max_err'); 00202 00203 dimension = ones(length(ratime),2); 00204 ratio = ones(length(ratime),1); 00205 simulation = cell(length(ratime),1); 00206 offt = ones(length(ratime), 4); 00207 asm = this.assessment; 00208 rbdd = get_by_description(asm.detailed_data, 'rb'); 00209 00210 for comb = 1:length(asm.rsamples) 00211 pf_val = asm.rsamples(:,comb); 00212 for i = 1:length(pf_val) 00213 asm.update_rbmodel(asm.plot_fields{i}, asm.rsamples(i, comb)); 00214 end 00215 N = asm.rbmodel.N; 00216 M = asm.rbmodel.M; 00217 simulation{comb} = 'Reduced'; 00218 dimension(comb,1) = N; 00219 dimension(comb, 2) = M; 00220 if length(pf_val) == 1 00221 ratio(comb) = asm.rsamples(comb); 00222 else 00223 ratio(comb) = comb; 00224 end 00225 [offt(comb,1), offt(comb,2), offt(comb,3)] = offtime(asm.detailed_data, asm.rbmodel); 00226 end 00227 if offt(1,2) < 50 00228 offt(:,1) = 90; 00229 elseif offt(1,2) < 65 00230 offt(:,1) = 117; 00231 elseif offt(1,2) < 1300 00232 offt(:,1) = 887; 00233 else 00234 offt(:,1) = 1394; 00235 end 00236 offt(:,4) = sum(offt, 2); 00237 datime = this.reduce_slice(@mean, 'dtime', [], 1); 00238 dmtime = this.reduce_slice(@min, 'dtime', [], 1); 00239 dMtime = this.reduce_slice(@max, 'dtime', [], 1); 00240 Hsize = asm.detailed_data.model_data.grid.nelements; 00241 ddimension = Hsize; 00242 dratio = -1; 00243 print_datatable(datafile,... 00244 {... 00245 'ratio', 'dim1', 'dim2', ... 00246 'time_avg', 'time_max', 'time_min', 'rec_time_avg', 'rec_time_min', 'rec_time_max', ... 00247 'est_time_avg', 'est_time_min', 'est_time_max', 'eta_avg', 'eta_min', 'eta_max', ... 00248 'err_avg', 'err_min', 'err_max', ..., 00249 'offtime_dsims', 'offtime_ei', 'offtime_rb', 'offtime_total' ... 00250 }, ... 00251 [... 00252 dratio, 0, ddimension, ... 00253 datime, dmtime, dMtime, -1, -1 , -1, ... 00254 -1, -1, -1, 0, 0, 0, ... 00255 0, 0, 0, ... 00256 0, 0, 0, 0; ... 00257 ratio(:), dimension, ... 00258 ratime(:), rmtime(:), rMtime(:), rratime(:), rrmtime(:), rrMtime(:), ... 00259 restatime(:), restmtime(:), restMtime(:), etaa(:), etam(:), etaM(:), ... 00260 erra(:), errm(:), errM(:), ... 00261 offt... 00262 ]'); 00263 00264 end 00265 00266 function print_landscape(this, datafile, fieldname) 00267 % function print_landscape(this, datafile, fieldname) 00268 % equivalent to the plot_landscape() function put prints out a table 00269 % which can be interpreted e.g. by pgfplots/Tikz. 00270 % 00271 % An example for a pgfplots graphics that can interpret the table output 00272 % is shown in the following code snippet: 00273 % @code 00274 % \begin{axis}[zmode=log,log basis z=10,axis on top, 00275 % view={-50}{-30}, axis lines=box, 00276 % xlabel={$N$}, ylabel={$M$}, 00277 % zlabel={$\eta_{N,M,M'}$}] 00278 % \addplot3[surf] 00279 % table[x=N, y=M, z=error] {error_landscape.dat}; 00280 % @endcode 00281 % 00282 % Parameters: 00283 % datafile: a string specifying the path and filename of the data table to be stored 00284 % fieldname: the fieldname in the #values attribute that shall be 00285 % plotted @default 'max_err' 00286 if nargin <=2 00287 fieldname = 'max_err'; 00288 end 00289 errs = this.reduce_slice(@max, fieldname); 00290 i = logical(errs>this.error_bound); 00291 errs(i) = this.error_bound; 00292 i = logical(isnan(errs)); 00293 errs(i) = this.error_bound; 00294 00295 rsamples = this.assessment.rsamples; 00296 blocklength = length(this.assessment.samples{1}); 00297 00298 print_datatable(datafile, [this.assessment.plot_fields, {'error'}], ... 00299 [rsamples; errs(:)'], blocklength); 00300 % C = ones(size(errs)); 00301 % i = logical(errs<this.stab_limit); 00302 % C(i) = 2; 00303 end 00304 00305 function print_3d_curve(this, datafile, fieldname) 00306 % function print_landscape(this, datafile, fieldname) 00307 % equivalent to the print_landscape() function put prints out a table 00308 % which can be interpreted for a 3d-curve plot e.g. by pgfplots/Tikz. 00309 % 00310 % This function can be used to display certain curves on the error 00311 % landscape generated by print_landscape(). 00312 % 00313 % An example for a pgfplots graphics that can interpret the table output 00314 % is shown in the following code snippet: 00315 % @code 00316 % \begin{axis}[zmode=log,log basis z=10,axis on top, 00317 % view={-50}{-30}, axis lines=box, 00318 % xlabel={$N$}, ylabel={$M$}, 00319 % zlabel={$\eta_{N,M,M'}$}] 00320 % \addplot3[mark=0] 00321 % table[x=N, y=M, z=error] {error_curve.dat}; 00322 % @endcode 00323 % 00324 % Parameters: 00325 % datafile: a string specifying the path and filename of the data table to be stored 00326 % fieldname: the fieldname in the #values attribute that shall be 00327 % plotted @default 'max_err' 00328 if nargin <=2 00329 fieldname = 'max_err'; 00330 end 00331 errs = this.reduce_slice(@max, fieldname); 00332 i = logical(errs>this.error_bound); 00333 errs(i) = this.error_bound; 00334 i = logical(isnan(errs)); 00335 errs(i) = this.error_bound; 00336 00337 Ns = ones(length(errs), 1); 00338 Ms = ones(length(errs), 1); 00339 rsamples = this.assessment.rsamples; 00340 for i=1:length(Ns) 00341 c = rsamples(i); 00342 this.assessment.update_rbmodel([], c); 00343 Ns(i) = this.assessment.rbmodel.N; 00344 Ms(i) = this.assessment.rbmodel.M; 00345 end 00346 00347 print_datatable(datafile, {'c', 'N', 'M', 'error'}, ... 00348 [rsamples(:), Ns, Ms, errs(:)]'); 00349 end 00350 00351 function slic = get_slice(this, fieldname, cell_range, struct_range) 00352 % function slic = get_slice(this, fieldname, cell_range, out_range) 00353 % helper function slicing a field in the #values attribute 00354 % 00355 % Parameters: 00356 % fieldname: name of the field in the #values attributed to be sliced 00357 % cell_range: cell indices to be extracted from the field. 00358 % If empty all cell entries are returned 00359 % @default [] 00360 % struct_range: Usually the #values attribute is a cell of structure arrays. 00361 % arrays. This range defines a slice in the structure 00362 % array. If empty all array entries are returned. 00363 % @default [] 00364 % 00365 % Return values: 00366 % slic: the sliced #values attribute 00367 if nargin <= 2 || isempty(cell_range) 00368 cell_range = 1:length(this.values(:)); 00369 end 00370 if nargin <= 3 || isempty(struct_range) 00371 struct_range = 1:length(this.values{1}(:)); 00372 end 00373 if isequal(fieldname, 'rtime_est') 00374 slic = cellfun(@(x) x(struct_range), this.rtime_est(cell_range), 'UniformOutput', false); 00375 else 00376 slic = cellfun(@(x) [x(struct_range).(fieldname)], this.values(cell_range), 'UniformOutput', false); 00377 end 00378 slic = cell2mat(slic'); 00379 end 00380 00381 function rslice = reduce_slice(this, red_func, fieldname, cell_range, struct_range, direction) 00382 % function rslice = reduce_slice(this, red_func, fieldname, cell_range, struct_range, direction) 00383 % extends the get_slice() function by also applying a reduction function 00384 % on each matrix entry. 00385 % 00386 % Parameters: 00387 % fieldname: name of the field in the #values attributed to be sliced 00388 % red_func: function pointer who is applied to each matrix entry in 00389 % the slice, e.g. '@@max' or '@@mean' 00390 % cell_range: cell indices to be extracted from the field. If empty 00391 % all cell entries are returned. 00392 % @default [] 00393 % struct_range: Usually the #values attribute is a cell of structure arrays. 00394 % arrays. This range defines a slice in the structure 00395 % array. If empty all array entries are returned. 00396 % @default [] 00397 % direction: integer specifying in which direction a matrix shall be 00398 % reduced. In case it is equal to '2', the matrix is 00399 % transposed before 'red_func' is applied. 00400 % @default 1 00401 % 00402 % Return values: 00403 % rslice: the sliced and reduced #values attribute 00404 if nargin <=3 00405 cell_range = []; 00406 end 00407 if nargin <= 4 00408 struct_range = []; 00409 end 00410 if nargin <= 5 00411 direction = 1; 00412 end 00413 slic = get_slice(this, fieldname, cell_range, struct_range); 00414 if direction == 2 00415 slic = slic'; 00416 rslice = zeros(1,size(slic,1)); 00417 else 00418 rslice = zeros(size(slic,1),1); 00419 end 00420 for i = 1:size(slic,1) 00421 rslice(i) = red_func(slic(i,:)); 00422 end 00423 end 00424 00425 00426 function merge(this, other) 00427 % function merge(this, other) 00428 % helper function merging this Output object with another one. 00429 % 00430 % The following rules apply during merging: 00431 % -# If 'values.max_Delta' is all 'Inf', copy 'max_Delta' and 00432 % 'max_Delta_ind' from 'other'. 00433 % -# If 'values.max_err' is all 'Inf', copy 'max_err' and 00434 % 'max_err_ind' from 'other'. 00435 % -# If one of 'rconds', 'dconds' or 'rtime_est' is empty, copy it 00436 % from 'other' 00437 % -# If one of 'rtime', 'rrtime' or 'dtime' is set to all-'NaN', copy it 00438 % from 'other' 00439 % -# If 'this' and 'other' have valid 'rtime' (i.e. not-'Nan') and only 00440 % one of both has computed estimators, compute 'rtime_est' by 00441 % subtracting one from the other. 00442 % 00443 % Parameters: 00444 % other: another object of type Postprocess.StochasticAssessment.Output to be 00445 % merged into this one. 00446 cpfields = {}; 00447 rtime_exists = false; 00448 % check what we ar missing: 00449 if all([this.values{end}(:).max_Delta] == Inf) 00450 cpfields = [ cpfields, {'max_Delta', 'max_Delta_ind'}]; 00451 end 00452 if all([this.values{end}(:).max_err] == Inf) 00453 cpfields = [ cpfields, {'max_err', 'max_err_ind'}]; 00454 end 00455 if isempty([this.values{end}(:).rconds]) 00456 cpfields = [ cpfields, {'rconds'}]; 00457 end 00458 if isempty([this.values{end}(:).dconds]) 00459 cpfields = [ cpfields, {'dconds'}]; 00460 end 00461 if all(isnan([this.values{end}(:).rtime])) 00462 cpfields = [ cpfields, {'rtime'}]; 00463 else 00464 rtime_exists = true; 00465 end 00466 if all(isnan([this.values{end}(:).rrtime])) 00467 cpfields = [ cpfields, {'rrtime'}]; 00468 end 00469 if all(isnan([this.values{end}(:).dtime])) 00470 cpfields = [ cpfields, {'dtime'}]; 00471 end 00472 00473 for i = 1:length(cpfields) 00474 for j = 1:length(this.values(:)) 00475 [this.values{j}(:).(cpfields{i})] = other.values{j}(:).(cpfields{i}); 00476 end 00477 end 00478 00479 if rtime_exists && any(~isnan([other.values{end}(:).rtime])) 00480 if this.assessment.compute_estimates ~= other.assessment.compute_estimates 00481 this.rtime_est = cell(size(this.values)); 00482 for i = 1:length(this.values(:)) 00483 this.rtime_est{i} = abs([this.values{i}(:).rtime] - [other.values{i}(:).rtime]); 00484 end 00485 end 00486 end 00487 00488 if isempty(this.rtime_est) 00489 this.rtime_est = other.rtime_est; 00490 end 00491 00492 if isempty(this.rd_conds) 00493 this.rd_conds = other.rd_conds; 00494 end 00495 end 00496 end 00497 end