2 % Interface
for the storage and generation of detailed data that can be used to
3 % build reduced basis functions.
5 % Via the generate() method, detailed data for exactly one parameter can vector be
6 % generated and is returned. Usually, this data needs to be postprocessed
7 % afterwards. E.g. in case of reduced basis generation for evolution equations,
8 % a
Cached instance could produce a detailed solution trajectory for
9 % the specified parameter and by applying a POD algorithm on this trajectory a
10 % single basis vector is extracted for basis extension.
12 % The generate method uses caching facilities to prevent data generation twice.
14 % Furthermore, the class provides methods to prepare and store solutions
15 % before-hand. This can be used in to compare reduced and detailed
16 % approximations for the entire training or validation set 'M'.
19 % unique name created from the IDs as given to the constructor.
23 properties(GetAccess = public, SetAccess = private)
24 id; %
string identifier for this generator
26 enable_caching = true; %
boolean flag indicating whether caching is enabled.
28 model_name = 'default'; % name
id of DetailedModel
32 %
boolean value indicating whether the cached data shall be automatically
33 % deleted if its inconsistent with the given 'dmodel'.
36 % seconds to wait before cached data is deleted automatically in case of
37 % inconsistent models.
42 % checks whether the basis generator points to a valid directory
46 properties(Access = private)
48 % number of files read from cache (only needed for debugging)
53 properties(Access = private, Dependent)
54 % path to all the cached data for the model for which this generator is
58 % path where the cached functions shall be stored.
61 % full path to settingsfile where model data is stored for consistency
70 function modelpath = get.modelpath(this)
71 modelpath = fullfile(rbmatlabtemp, 'cache', this.model_name);
74 function filepath = get.filepath(this)
75 filepath = fullfile(this.modelpath, this.idname);
78 function settingsfile = get.settingsfile(this)
79 settingsfile = fullfile(this.filepath, 'settings.mat');
82 function ok = get.is_valid(this)
83 ok = exist(this.settingsfile, 'file');
86 function dg =
Cached(dmodel,
id, force_delete, enable_caching)
87 % function dg =
Cached(dmodel,
id, force_delete)
88 % constructor for the detailed generator
91 %
id: an identifier
string or a cell array of identifier
93 % force_delete:
boolean value indicating whether the cached data shall
94 % be automatically deleted if its inconsistent with the
95 % given 'dmodel'. (Default = 'true')
96 % enable_caching:
boolean value indicating whether the generated data
97 % shall be stored in a cache. (Default = 'true')
100 if nargin >= 3 && ~isempty(force_delete)
101 dg.force_delete = force_delete;
103 if nargin >= 4 && ~isempty(enable_caching)
104 dg.enable_caching = enable_caching;
106 dg.model_name = dmodel.descr.name;
108 % When NEWDIR exists, MKDIR returns SUCCESS = 1, but with WARNING!
109 if ~exist(fullfile(rbmatlabtemp, 'cache', dmodel.descr.name, dg.idname), 'dir')
110 success = mkdir(rbmatlabtemp, fullfile('cache', dmodel.descr.name, dg.idname));
116 error(['error in generating the caching savepath: ', dg.filepath]);
120 if exist(dg.settingsfile, 'file')
121 tmp = load(dg.settingsfile);
123 assert_model_is_consistent(dg, dmodel, tmp.dmodel);
125 if ~dmodel.debug && dg.force_delete
126 disp(exception.message);
127 disp('==================================================================');
128 disp('========================== WARNING: ==============================');
129 disp('dmodel.force_delete is set to true. The data in the savepath' );
130 disp(['will be deleted in ', num2str(dg.countdown), ' seconds. ']);
131 disp('Press Ctrl-C if you want to keep the precompute files.');
132 disp('==================================================================');
133 for i=dg.countdown:-1:1
134 disp(['Deleting in directory in ', num2str(i), ' seconds.']);
137 clear_cachedirectory(dg);
139 error(exception.message);
145 save(dg.settingsfile, 'dmodel');
148 function idname = get.idname(this)
150 idname = sprintf('%s_', this.
id{:});
156 function clear_cachedirectory(
this)
157 % clears the directory containing the cached mat-files
159 delete(fullfile(this.filepath,
'*.mat'));
160 if exist(this.settingsfile,
'file')
161 delete(this.settingsfile);
165 function assert_model_is_consistent(this, dmodel, comparemodel)
166 % function assert_model_is_consistent(this, dmodel, comparemodel)
167 % throws an inconsistency error if the the current
IDetailedModel object
168 % and the one stored on the harddrive differ.
171 iseq = (dmodel == comparemodel);
173 throw(MException('RBMatlab:Storage:InconsistentData', ...
174 ['parameters of precomputed data and current',...
175 ' simulation are inconsistent! Please delete files in path ', ...
176 this.filepath, ' and restart!']));
181 function [detailed_sample, tictoc, opt_fields] = generate(this, dmodel, detailed_data, fields)
182 % function detailed_sample = generate(this, model, detailed_data[, fields])
183 % generates a detailed data sample for a specific parameter using
186 % Internally this method calls the engine method generate_impl() if the
187 % result cannot be read from the harddrive cache.
190 % fields: cell array of structure field names which shall also be
191 % stored in the cache in the 'opt_fields' structure. If not
192 % given only the 'detailed_sample' is generated.
195 % detailed_sample: This is usually a matrix with DOF vector columns
196 % holding the generated snapshots.
197 % tictoc: time needed to compute the snapshots.
198 % opt_fields: optional fields to be cached.
206 if this.enable_caching
207 hash = this.hashcode(dmodel);
208 filename = fullfile(this.filepath, ['dsample', hash, '.mat']);
210 if exist(filename, 'file')
211 tmp = load(filename);
214 if ~isfield(tmp, 'opt_fields')
217 for i =1:length(fields)
218 if ~isfield(tmp.opt_fields, fields{i})
223 opt_fields = tmp.opt_fields;
226 detailed_sample = tmp.detailed_sample;
230 this.nocachereads = this.nocachereads+1;
231 if mod(this.nocachereads, 10) == 0
232 disp([
'This is the tenth cache read and we are in debug mode.', ...
233 'Comparing with real simulation...']);
234 comp = generate_impl(
this, dmodel, detailed_data);
235 if any(size(comp) ~= size(detailed_sample))...
236 || any(comp ~= detailed_sample)
237 disp('computations do not correspond with the cached result!!!');
238 disp('Please check the hash function of whether the data directory')
239 disp([' ', this.filepath]);
240 disp('needs to be deleted');
249 disp('cache file not found because opt_fields are missing...');
255 [detailed_sample, opt_fields] = generate_impl(this, dmodel, detailed_data, fields);
256 tictoc = toc(tstart);
258 if this.enable_caching
259 hash = this.hashcode(dmodel);
260 filename = fullfile(this.filepath, ['dsample', hash, '.mat']);
262 save(filename, 'detailed_sample', 'tictoc', 'opt_fields');
267 function prepare(this, dmodel, detailed_data, M)
268 % function prepare_data(this, dmodel, detailed_data)
269 % precompute detailed data for all parameters given by \a M.
272 % M: matrix storing the parameters for which the generation shall be
273 % prepared. The matrix size equal `dim(\cal M) \times M_p`, where `M_p`
274 % denotes the number of parameter vectors. (Default = [])
276 num_cpus = 2*dmodel.num_cpus;
278 tmp_fp = this.filepath;
280 for mout = 0:floor((npar-1)/num_cpus)
281 dsample_c = cell(1, npar);
282 tictoc_c = cell(1, npar);
284 %parfor muind = (mout*num_cpus+1):min(npar, (mout+1)*num_cpus)
285 for muind = (mout*num_cpus+1):min(npar, (mout+1)*num_cpus)
288 set_mu( tmp_dmodel, tmp_M(muind,:) );
291 hash = tmp_this.hashcode(tmp_dmodel);
292 filename = fullfile(tmp_fp, ['dsample', hash, '.mat']);
293 if ~exist(filename, 'file')
294 disp(['Processing parameter vector ', num2str(muind),'/',num2str(npar),...
295 ' in
Cached ', tmp_this.idname, '...']);
297 dsample_c{muind} = generate_impl(
this, tmp_dmodel, detailed_data);
298 tictoc_c{muind} = toc(tstart);
300 disp([
'File exists: Skipping parameter vector ', num2str(muind),
'/',num2str(npar),...
301 ' in Cached ', tmp_this.idname,
'...']);
304 if this.enable_caching
305 for muind = (mout*num_cpus+1):min(npar, (mout+1)*num_cpus)
306 detailed_sample = dsample_c{muind};
307 tictoc = tictoc_c{muind};
309 set_mu( dmodel, M(muind,:) );
310 hash = this.hashcode(dmodel);
311 filename = fullfile(tmp_fp, [
'dsample', hash,
'.mat']);
312 if ~exist(filename,
'file')
313 save(filename, 'detailed_sample', 'tictoc')
318 end % end of function prepare_data
320 function dmodel = get_underlying_model(this)
321 % function dmodel = get_underlying_model(this)
322 % returns the detailed model stored on the harddrive with which the
323 % snaphshots were generated.
324 if exist(this.settingsfile, 'file')
325 tmp = load(this.settingsfile);
328 dmodel = ['settingsfile for extension ', this.
id, ' does not exist!'];
335 methods (Abstract, Access=protected)
336 % generates a sample trajectory or detailed simulation item from which a
337 % new basis function can be generated.
340 % fields: cell array of structure field names which shall also be
341 % stored in the cache in the 'opt_fields' structure. If not
342 % given only the 'U' is generated.
345 % U: a matrix with DOF vector columns holding the generated
347 % opt_fields: optional fields to be cached.
348 [U, opt_fields] = generate_impl(this, dmodel, detailed_data, fields);
352 methods (Static, Access=protected)
353 % function hashcode = hashcode(basis_generation)
354 % this is a very simple hash code, generating an md5 hash out of the
355 % current parameter vector.
357 % The default implementation of this function simply computes an MD5 hash
358 % out of the parameter vector;
359 function hashcode = hashcode(dmodel)
362 hashcode = hash(mu, 'MD5');
Interface for the storage and generation of detailed data that can be used to build reduced basis fun...
debug
an integer defining the debugging level controlling error output and extra tests during basis generat...
This is the interface for a detailed model providing methods to compute high dimensional simulation s...