rbmatlab 0.10.01
|
00001 classdef Assessment < handle 00002 % a class used to compute reduced several reduced simulations over a huge 00003 % parameter sample extracting useful information 00004 % 00005 % The class generates one or two dimensional cell arrays of these data fields 00006 % storing information for a variation of some attributes of the reduced 00007 % model, which can be freely chosen by specification of #plot_fields . 00008 00009 properties(Access=public) 00010 % is a vector of field names with at most 2 elements over which the error 00011 % landscape is computed or a cell with empty entries. 00012 % 00013 % A reasonable choice would be '{ \'N\', \'M\' }'. The error landscape is 00014 % plotted over a variation of these fields specified by samples. 00015 % In case of an empty cell entry, 'N' and 'M' are coupled by the fixed 00016 % ratio #M_by_N_ratio and samples should be a vector of coupling constant 00017 % between 0 and 1. See also: update_rmodel() 00018 % 00019 % @default = '{[]}' 00020 plot_fields = {[]}; 00021 00022 % is a cell array of scalar row vectors. The scalar values are 'plot_field' 00023 % values for which the error is computed and tested. 00024 % 00025 % @default = '{[0.1:0.1:1]}' 00026 samples = {(0.1:0.1:1)}; 00027 00028 % an parameter sampling object of type ParameterSampling.Interface 00029 % 00030 % @default is a random sampling with 10 elements and seed 654321; 00031 % 00032 % See also: init_random_sampling() 00033 M_test; 00034 00035 % is a cell array of description texts for the plot fields. If this field 00036 % is not set it is set to 'plot_fields'. 00037 plot_field_descr = {}; 00038 00039 00040 % character string specifying this test run. The string should be unique 00041 % for every parameter combination. 00042 % 00043 % @default rmodel.name + '_stoachastic_assessment'; 00044 run_name; 00045 00046 % boolean value determining whether error estimates shall be computed 00047 compute_estimates = false; 00048 00049 % boolean value determining whether the "true" error `\|u_h(\mu) - 00050 % u_{\text{red}}(\mu)\|_{{\cal W}_h}` shall be computed 00051 compute_errors = false; 00052 00053 % boolean value determining whether the condition numbers of the system 00054 % matrices shall be computed 00055 compute_conditions = false; 00056 00057 % boolean value indicating whether the refinement steps of the reduced 00058 % basis generation by Greedy.TrainingSetAdaptation shall be taken into account 00059 % 00060 % This option is only useful if 00061 % -# #M_test is set to the training sample of the parameter space 00062 % generation and 00063 % -# the #plot_fields include the basis dimensions 00064 % In this case the parameter sampling used during basis generation for the 00065 % given basis dimension is selected. 00066 follow_refinement_steps = false; 00067 00068 % if M and N are couple this value specifies the constant for the coupling. 00069 % 00070 % A value of zero means `M_{\max} / N_{\max}` 00071 M_by_N_ratio = 1; 00072 00073 % the underlying reduced model of type IReducedModel 00074 rmodel; 00075 00076 % an object of type CacheableObject storing the reduced model and the 00077 % detailed data 00078 cache_object; 00079 00080 end 00081 00082 properties(Dependent) 00083 % the "real" collection of vectors used for the #plot_fields variation 00084 % 00085 % See also: #samples 00086 rsamples; 00087 00088 % the underlying detailed data of type Greedy.DataTree.Detailed.INode 00089 % 00090 % @todo make this cached... 00091 detailed_data; 00092 end 00093 00094 methods 00095 00096 function dd = get.detailed_data(this) 00097 dd = this.cache_object.obj.detailed_data; 00098 end 00099 00100 function rsamples = get.rsamples(this) 00101 if length(this.samples) == 2 00102 rsamples = combvec(this.samples{1},this.samples{2}); 00103 else 00104 rsamples = this.samples{1}; 00105 end 00106 end 00107 00108 function sta = Assessment(matfile, rmodel, mu_set_size, seed) 00109 % function sta = Assessment(matfile, rmodel, mu_set_size, seed) 00110 % constructor 00111 % 00112 % Parameters: 00113 % matfile: name of result file where a IReducedModel object and a 00114 % Greedy.DataTree.Detailed.INode object must be stored. 00115 % mu_set_size: Optional argument determining the number of random 00116 % parameters in the validation sample. (Default = 10) 00117 % seed: a random seed used for initialization of 00118 % ParameterSampling.Random object for the #M_test parameter 00119 % sample set. (Default = 654321) 00120 00121 if nargin == 1 && isa(matfile, 'Postprocess.StochasticAssessment.Assessment') 00122 cp = matfile; 00123 m = metaclass(cp); 00124 fns = m.Properties(cellfun(@(x) ~isequal(x.SetAccess, 'none') && ~x.Dependent, m.Properties)); 00125 fns = cellfun(@(x) x.Name, fns, 'UniformOutput', false); 00126 fns = setdiff(fns, {'cache_object'}); 00127 for i = 1:length(fns); 00128 sta.(fns{i}) = cp.(fns{i}); 00129 end 00130 sta.cache_object = CacheableObject(cp.cache_object.matfile, 'detailed_data'); 00131 sta.rmodel = copy(cp.rmodel); 00132 else 00133 sta.rmodel = copy(rmodel); 00134 sta.cache_object = CacheableObject(matfile, 'detailed_data'); 00135 if nargin <= 2 00136 mu_set_size = 10; 00137 end 00138 if nargin <= 3 00139 seed = 654321; 00140 end 00141 init_random_sampling(sta, mu_set_size, seed); 00142 00143 if isempty(sta.plot_field_descr) 00144 sta.plot_field_descr = sta.plot_fields; 00145 else 00146 assert(length(sta.plot_field_descr) == length(sta.plot_fields)); 00147 end 00148 00149 sta.run_name = [rmodel.detailed_model.name, '_stochastic_assessment']; 00150 end 00151 end 00152 00153 function output=compute(this) 00154 % function compute(this) 00155 % stochastic estimation of error between reduced and detailed simulation over a 00156 % test sample of `\mu` vectors 00157 % 00158 % This function stochastically estimates the error between reduced and detailed 00159 % simulations for given `\mu`-vectors and various reduced and collateral basis 00160 % sizes. The results are visualized in a surface plot for problems with CRB. 00161 % 00162 % If required by the users, averaged time measurements for the reduced and the 00163 % detailed simulations are computed, too. 00164 % 00165 % Return values: 00166 % output: an Output object 00167 00168 %if isequal(params.mode, 'error_ei') 00169 % model.detailed_simulation = model.detailed_ei_simulation; 00170 %end 00171 00172 %if isequal(params.mode, 'error_ei_rb_proj') 00173 % model.detailed_simulation = model.detailed_ei_rb_proj_simulation; 00174 %end 00175 00176 reduced_data = gen_reduced_data(this.rmodel, this.detailed_data); 00177 00178 if this.compute_estimates 00179 assert(this.rmodel.Mstrich > 0); 00180 assert(this.rmodel.enable_error_estimator); 00181 else 00182 assert(~this.rmodel.enable_error_estimator); 00183 assert(this.rmodel.Mstrich == 0); 00184 end 00185 00186 basis_gen = this.detailed_data.bg_algorithm; 00187 while ~isa(basis_gen, 'Greedy.Algorithm') 00188 switch(class(basis_gen)) 00189 case 'Greedy.Combined' 00190 basis_gen = get_rb_basis_generator(basis_gen); 00191 case 'Greedy.TrainingSetAdaptation' 00192 basis_gen = basis_gen.child; 00193 otherwise 00194 error('nonono'); 00195 end 00196 end 00197 generator = basis_gen.detailed_gen; 00198 00199 if ~generator.is_valid 00200 generator = SnapshotsGenerator.Trajectories(this.rmodel.detailed_model); 00201 end 00202 00203 % default value (only need for mode == 'check' when no 'mu_set_size' is given) 00204 00205 savefile = [this.run_name]; 00206 tmpfile = [savefile,'_tmp.mat']; 00207 savefile = [savefile,'.mat']; 00208 00209 rps_size = length(this.rsamples); 00210 00211 complete_out = cell(1, rps_size); 00212 00213 if this.compute_conditions 00214 rd_conds = cell(1, rps_size); 00215 else 00216 rd_conds = {}; 00217 end 00218 00219 for comb = 1:rps_size 00220 00221 pf_val=this.rsamples(:,comb); 00222 00223 for i=1:length(pf_val) 00224 update_rmodel(this, this.plot_fields{i}, pf_val(i)); 00225 end 00226 temp_rd = extract_reduced_data_subset(this.rmodel, reduced_data); 00227 00228 if this.compute_conditions 00229 rd_conds{comb} = get_conds(temp_rd); 00230 end 00231 00232 disp(['Processing combination ', num2str(comb), '/', num2str(rps_size)]); 00233 00234 M = this.get_test_space_sample; 00235 generator.prepare(this.rmodel.detailed_model, this.detailed_data.model_data, M); 00236 mu_size = size(M,1); 00237 00238 part_out = struct('max_Delta' , cell(1, mu_size), ... 00239 'max_Delta_ind', cell(1, mu_size), ... 00240 'max_err' , cell(1, mu_size), ... 00241 'max_err_ind' , cell(1, mu_size), ... 00242 'rtime' , cell(1, mu_size), ... 00243 'rrtime' , cell(1, mu_size), ... 00244 'dtime' , cell(1, mu_size), ... 00245 'rconds' , cell(1, mu_size), ... 00246 'dconds' , cell(1, mu_size)); 00247 %for mu_ind = 1:mu_size 00248 parfor mu_ind = 1:mu_size 00249 tthis = this; 00250 trm = this.rmodel; 00251 tdm = trm.detailed_model; 00252 trd = temp_rd; 00253 tgen = generator; 00254 00255 disp(['processing parameter vector ',num2str(mu_ind),... 00256 '/',num2str(size(M,1))]); 00257 00258 set_mu(trm, M(mu_ind,:)); 00259 set_mu(tdm, M(mu_ind,:)); 00260 00261 compute_out = compute_impl(tthis, tgen, trm, trd); 00262 00263 part_out(mu_ind) = compute_out; 00264 end 00265 00266 complete_out{comb} = part_out; 00267 % disp(['saving temporary workspace in ', tmpfile]); 00268 % rmodel = this.rmodel; 00269 % detailed_data = this.detailed_data; 00270 % save(fullfile(rbmatlabtemp,tmpfile), 'complete_out', 'part_out', 'this', 'rmodel', 'detailed_data', 'reduced_data'); 00271 00272 end 00273 00274 if length(this.samples) == 2 00275 ns1 = length(this.samples{1}); 00276 ns2 = rps_size / ns1; 00277 complete_out = reshape(complete_out, ns1, ns2); 00278 if this.compute_conditions 00279 rd_conds = reshape(rd_conds, ns1, ns2); 00280 end 00281 end 00282 00283 output = Postprocess.StochasticAssessment.Output(complete_out, this); 00284 output.rd_conds = rd_conds; 00285 00286 save(fullfile(rbmatlabresult, savefile)); 00287 00288 end 00289 00290 function init_random_sampling(this, mu_set_size, seed) 00291 % function init_random_sampling(this, mu_set_size, seed) 00292 % generates the initial random sample set #M_test 00293 % 00294 % Parameters: 00295 % mu_set_size: @copydoc ParameterSampling.Random.nparameters 00296 % seed : @copydoc ParameterSampling.Random.seed 00297 00298 detailed_model = this.rmodel.detailed_model; 00299 this.M_test = ParameterSampling.Random(mu_set_size, seed); 00300 if this.M_test.init_required() 00301 init_sample(this.M_test, detailed_model); 00302 end 00303 end 00304 00305 function other = copy(this) 00306 % function other = copy(this) 00307 % deep copy of this object 00308 % 00309 % Return values: 00310 % other: copied Assessment object 00311 other = Postprocess.StochasticAssessment.Assessment(this); 00312 end 00313 00314 function equal_distribution_samples(this, min, max, sample_size) 00315 % function equal_distribution_samples(min, max, sample_size) 00316 % adapts the #samples attribute such that they are equally distributed in 00317 % a given range. 00318 % 00319 % Parameters: 00320 % min: is a vector of minimum values of 'plot_fields' variables. 00321 % max: is a vector for maximum values of 'plot_fields' 00322 % variables. 00323 % sample_size: specifies the number of sample values between 'min' and 00324 % 'max' for which the error is computed and plotted. The 00325 % default value is 'max-min'. 00326 00327 if nargin == 2 00328 sample_size = max-min; 00329 end 00330 00331 00332 assert(all(max > min)); 00333 00334 this.samples = cell(1,length(max)); 00335 for i = 1:length(max) 00336 this.samples{i} = min(i) + ... 00337 round((0:sample_size(i)-1) .* ... 00338 (max(i)-min(i))./(sample_size(i)-1)); 00339 end 00340 end 00341 00342 function update_rmodel(this, plot_field, new_value) 00343 % function update_rmodel(this, plot_field, new_value) 00344 % updates the reduced model, i.e. applies the changes defined by the 00345 % #plot_fields attribute 00346 % 00347 % Parameters: 00348 % plot_field: an entry in #plot_fields, if it is empty, a coupling of 00349 % 'N' and 'M' is assured. 00350 % new_value: the new value it should be set to. 00351 00352 if ~isempty(plot_field) 00353 this.rmodel.(plot_field) = new_value; 00354 else 00355 couple_N_and_M_by_c(this, new_value); 00356 end 00357 00358 rmodel = this.rmodel; 00359 disp(['N = ', num2str(rmodel.N), ' M = ', num2str(rmodel.M), ' Mstrich = ', num2str(rmodel.Mstrich)]); 00360 end 00361 00362 00363 end 00364 00365 00366 methods(Static) 00367 00368 function [rb_sim_data, tictoc] = rb_simulation_tictoc(varargin) 00369 % function [rb_sim_data, tictoc] = rb_simulation_tictoc(varargin) 00370 % a wrapper around the IReducedModel.rb_simulation() measuring the 00371 % execution time 00372 % 00373 % Return values: 00374 % rb_sim_data: the reduced simulation data 00375 % tictoc: execution time 00376 [rb_sim_data, tictoc] = tictoc_wrapper(@rb_simulation, varargin{:}); 00377 end 00378 00379 00380 end 00381 00382 methods(Access=private) 00383 00384 function output = compute_impl(this, generator, rmodel, reduced_data) 00385 00386 fprintf('['); 00387 00388 model_data = this.detailed_data.model_data; 00389 00390 max_Delta = NaN; 00391 max_Delta_ind = 0; 00392 max_err = NaN; 00393 max_err_ind = 0; 00394 dtime = NaN; 00395 rtime = NaN; 00396 rrtime = NaN; 00397 rconds = []; 00398 dconds = []; 00399 rmodel.compute_conditions = this.compute_conditions; 00400 try 00401 [rb_sim_data,tictoc] = this.rb_simulation_tictoc(rmodel, reduced_data); 00402 00403 fprintf('N'); 00404 if this.compute_estimates 00405 Delta = rb_sim_data.Delta; 00406 [max_Delta, max_Delta_ind] = max(Delta); 00407 else 00408 max_Delta = Inf; 00409 end 00410 00411 if this.compute_conditions 00412 rconds = rb_sim_data.conds; 00413 else 00414 % condition computations may make time measurements bogus. 00415 rtime = tictoc; 00416 end 00417 00418 if this.compute_errors 00419 dmodel = rmodel.detailed_model; 00420 if this.compute_conditions 00421 fields = {'conds'}; 00422 dmodel.compute_conditions = true; 00423 else 00424 fields = []; 00425 end 00426 [U_H, dtic_toc, opts] = generate(generator, dmodel, model_data, fields); 00427 fprintf('H'); 00428 if this.compute_conditions 00429 dconds = opts.conds; 00430 else 00431 % condition computations may make time measurements bogus. 00432 dtime = dtic_toc; 00433 end 00434 00435 tic; 00436 rb_sim_data = rb_reconstruction(rmodel, this.detailed_data, rb_sim_data); 00437 rrtime = toc; 00438 fprintf('R'); 00439 00440 errors = dmodel.l2_error_sequence_algorithm(U_H, rb_sim_data.U, ... 00441 model_data); 00442 [max_err,max_err_ind] = max(errors); 00443 else 00444 max_err = Inf; 00445 end 00446 00447 catch ME 00448 warning(['catched an error: ', ME.message]); 00449 disp('setting error to NaN'); 00450 end 00451 fprintf(']'); 00452 output.max_Delta = max_Delta; 00453 output.max_Delta_ind = max_Delta_ind; 00454 output.max_err = max_err; 00455 output.max_err_ind = max_err_ind; 00456 output.rtime = rtime; 00457 output.rrtime = rrtime; 00458 output.dtime = dtime; 00459 output.rconds = rconds; 00460 output.dconds = dconds; 00461 end 00462 00463 00464 function couple_N_and_M_by_c(this, c) 00465 % function model = couple_N_and_M_by_c(model, c) 00466 % modifies the reduced basis size fields of 'model' by a single variable. 00467 % 00468 % Parameters: 00469 % c: sets the reduced basis sizes to 00470 % `(N,M) = c (N_{\mbox{max}}, c_{MbyN} N_{\mbox{max}})`. For time-adaptive 00471 % schemes with several collateral reduced basis spaces, the following 00472 % formula is applied: `(N,M^k) = c (N_{\mbox{max}}), c_{MbyN} 00473 % \frac{M^k_{\mbox{max}}}{\mbox{max}_{k=0,...,K} M^k_{\mbox{max}}} 00474 % N_{\mbox{max}}.` 00475 00476 Nmax = get_rb_size(this.detailed_data, this.rmodel); 00477 Mmax = get_ei_size(this.detailed_data, this.rmodel); 00478 maxMmax = max(Mmax)-this.rmodel.Mstrich; 00479 this.rmodel.N = max(round(c*Nmax),1); 00480 if this.M_by_N_ratio == 0 00481 M_by_N_r = maxMmax / Nmax; 00482 elseif this.M_by_N_ratio == -1 00483 leaf_dd = get_active_leaf(this.detailed_data, this.rmodel); 00484 assert(isa(leaf_dd, 'Greedy.DataTree.Detailed.PODEI')); 00485 ext_ind = this.rmodel.N; 00486 ext_counts = get_field(leaf_dd, 'ei_ext_count'); 00487 ei_ext_steps = get_field(leaf_dd, 'ei_ext_steps'); 00488 rb_real_ext_steps = get_field(leaf_dd, 'rb_real_ext_steps'); 00489 if isempty(ext_counts) 00490 n_ei_exts = length(ei_ext_steps); 00491 ext_counts = ones(size(ei_ext_steps))*maxMmax/n_ei_exts; 00492 end 00493 Mcomp = round(sum((ei_ext_steps <= rb_real_ext_steps(ext_ind)).*ext_counts)); 00494 this.rmodel.M = min(maxMmax, max(Mcomp, 1)); 00495 return 00496 else 00497 M_by_N_r = this.M_by_N_ratio; 00498 end 00499 this.rmodel.M = arrayfun(@(x) min(x, max(round(c*x/maxMmax*M_by_N_r*Nmax),1)), maxMmax); 00500 end 00501 00502 function M = get_test_space_sample(this) 00503 if this.follow_refinement_steps 00504 info = active_info(this.detailed_data); 00505 ref_level = get_ref_level(info, this.rmodel); 00506 M = get_sample_at_ref_level(this.M_test, ref_level); 00507 else 00508 M = this.M_test.sample; 00509 end 00510 end 00511 00512 end 00513 end