Line data Source code
1 : // rbOOmit: An implementation of the Certified Reduced Basis method.
2 : // Copyright (C) 2009, 2010 David J. Knezevic
3 :
4 : // This file is part of rbOOmit.
5 :
6 : // rbOOmit is free software; you can redistribute it and/or
7 : // modify it under the terms of the GNU Lesser General Public
8 : // License as published by the Free Software Foundation; either
9 : // version 2.1 of the License, or (at your option) any later version.
10 :
11 : // rbOOmit is distributed in the hope that it will be useful,
12 : // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 : // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 : // Lesser General Public License for more details.
15 :
16 : // You should have received a copy of the GNU Lesser General Public
17 : // License along with this library; if not, write to the Free Software
18 : // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 :
20 : #ifndef LIBMESH_RB_PARAMETERS_H
21 : #define LIBMESH_RB_PARAMETERS_H
22 :
23 : // libMesh includes
24 : #include "libmesh/libmesh_common.h"
25 :
26 : // C++ includes
27 : #include <string>
28 : #include <map>
29 : #include <set>
30 : #include <vector>
31 :
32 : namespace libMesh
33 : {
34 :
35 : /**
36 : * Typedef for an individual RB parameter. Each parameter is now stored
37 : * as a vector of values (different from the vector of samples).
38 : */
39 : using RBParameter = std::vector<Real>;
40 :
41 : /**
42 : * This class is part of the rbOOmit framework.
43 : *
44 : * This class defines a set of parameters indexed by strings.
45 : * Multiple samples can be defined, where a sample is a set of values for
46 : * each parameter. The parameters themselves can be multi-valued, e.g.
47 : * for storing a matrix-type parameter.
48 : *
49 : * \author David J. Knezevic
50 : * \date 2012
51 : */
52 136604 : class RBParameters
53 : {
54 : public:
55 :
56 : /**
57 : * Constructor. Initializes the _n_samples parameter to 1 for
58 : * backwards compatibility, but the set_n_samples() function can
59 : * always be called later to update this value.
60 : */
61 : RBParameters();
62 :
63 : /**
64 : * The special functions can be defaulted for this class, as it
65 : * does not manage any memory itself.
66 : */
67 6515 : RBParameters (RBParameters &&) = default;
68 62314 : RBParameters (const RBParameters &) = default;
69 698479 : RBParameters & operator= (const RBParameters &) = default;
70 0 : RBParameters & operator= (RBParameters &&) = default;
71 414999 : ~RBParameters() = default;
72 :
73 : /**
74 : * Constructor. Set parameters based on the std::map \p parameter_map.
75 : *
76 : * It sets the values as the 0th entry of the sample-vector
77 : * corresponding to each parameter name.
78 : */
79 : RBParameters(const std::map<std::string, Real> & parameter_map);
80 :
81 : /**
82 : * Return const_iterators to the internal parameter map, as a convenient
83 : * way to access the parameter names and values.
84 : * For example: for (const auto & [param_name, sample_vec] : my_parameters)
85 : */
86 : std::map<std::string,std::vector<RBParameter>>::const_iterator begin() const;
87 : std::map<std::string,std::vector<RBParameter>>::const_iterator end() const;
88 : std::map<std::string,std::vector<RBParameter>>::const_iterator extra_begin() const;
89 : std::map<std::string,std::vector<RBParameter>>::const_iterator extra_end() const;
90 :
91 : /**
92 : * Define a constant iterator for iterating over the map of parameters.
93 : * This will iterate over every individual value in the map, meaning all
94 : * three levels (param name, sample vector, value vector).
95 : * This custom iterator design is copied from the chunked_mapvector class.
96 : */
97 5607 : class const_iterator
98 : {
99 : public:
100 : // Typedefs needed for interoperating with other STL algorithms and containers.
101 : typedef std::forward_iterator_tag iterator_category;
102 : typedef std::pair<std::string, Real> value_type;
103 : typedef std::ptrdiff_t difference_type;
104 : typedef value_type* pointer;
105 : typedef value_type& reference;
106 :
107 : // Underlying iterator type, must match the container type of _parameters.
108 : typedef std::map<std::string, std::vector<RBParameter>>::const_iterator MapIter;
109 :
110 : // Constructor
111 202 : const_iterator(const MapIter & it,
112 : const std::size_t sample_vec_index,
113 : const std::size_t value_vec_index)
114 6990 : : _it(it),
115 6788 : _sample_vec_index(sample_vec_index),
116 7192 : _value_vec_index(value_vec_index)
117 202 : {}
118 :
119 : // Copy ctor
120 : const_iterator(const const_iterator & i) = default;
121 :
122 : // Prefix increment operator "++it"
123 7830 : const_iterator & operator++()
124 : {
125 : // First increment the value-vector index.
126 : // If _value_vec_index goes beyond the current value-vector, reset to the next one.
127 7830 : ++_value_vec_index;
128 8270 : if (_value_vec_index >= _it->second[_sample_vec_index].size())
129 : {
130 7830 : _value_vec_index = 0;
131 : // Now increment the sample-vector index, and do the same check.
132 : // If we go beyond the current sample-vector, reset to the next one.
133 7830 : ++_sample_vec_index;
134 8050 : if (_sample_vec_index >= _it->second.size())
135 : {
136 7830 : _sample_vec_index = 0;
137 216 : ++_it;
138 : }
139 : }
140 :
141 7830 : return *this;
142 : }
143 :
144 : // Postfix increment operator "it++". This is actually less
145 : // efficient than doing the prefix increment, so if nothing
146 : // requires it, let's skip defining it.
147 : // const_iterator operator++(int)
148 : // {
149 : // const_iterator i = *this;
150 : // ++(*this);
151 : // return i;
152 : // }
153 :
154 : // Dereference operator - returns a const reference to the value
155 : // indexed by it and _vec_index. Note: this is needed for backwards
156 : // compatibility but it is not the most efficient thing since we
157 : // need to construct a std::pair every time we dereference a
158 : // const_iterator.
159 7968 : const value_type & operator*() const
160 : {
161 8192 : _emulator = std::make_pair(_it->first, _it->second[_sample_vec_index][_value_vec_index]);
162 7968 : return _emulator;
163 : }
164 :
165 : // Equivalence comparison operator.
166 132 : bool operator==(const const_iterator & other) const
167 : {
168 4908 : return (_it == other._it && _sample_vec_index == other._sample_vec_index);
169 : }
170 :
171 : // Non-equvialence comparison operator
172 132 : bool operator!=(const const_iterator & other) const
173 : {
174 132 : return !(other == *this);
175 : }
176 :
177 : private:
178 : // Give RBParameters access to our private members. At the moment
179 : // this is not needed since the RBParameters class does not really
180 : // need to know anything about the const_iterator once it has been
181 : // created.
182 : // friend class RBParameters;
183 :
184 : // Iterator into real container
185 : MapIter _it;
186 :
187 : // Accompanying current sample-vector index into it->second
188 : std::size_t _sample_vec_index;
189 :
190 : // Accompanying current value-vector index into it->second[_sample_vec_index]
191 : std::size_t _value_vec_index;
192 :
193 : // Returned by the operator* function. Emulates dereferencing a
194 : // map<string, Real> iterator.
195 : mutable value_type _emulator;
196 : }; // end const_iterator
197 :
198 : /**
199 : * Get const_iterator access to the parameters stored in this RBParameters object.
200 : * This gives serialized access to all the individual Real values in the
201 : * nested vector<vector<Real>>.
202 : * Use this in a for loop with the following syntax, for example:
203 : * for (const auto &[key,val] : as_range(rb_parameters.begin_serialized(), rb_parameters.end_serialized())
204 : */
205 : const_iterator begin_serialized() const;
206 : const_iterator end_serialized() const;
207 :
208 : /**
209 : * Get const_iterator access to the extra parameters stored in this RBParameters object.
210 : * This gives serialized access to all the individual Real values in the
211 : * nested vector<vector<Real>>.
212 : * Use this in a for loop with the following syntax, for example:
213 : * for (const auto &[key,val] : as_range(rb_parameters.begin_serialized_extra(), rb_parameters.end_serialized_extra())
214 : */
215 : const_iterator begin_serialized_extra() const;
216 : const_iterator end_serialized_extra() const;
217 :
218 : /**
219 : * Clear this object.
220 : */
221 : void clear();
222 :
223 : /**
224 : * \returns true if there is a parameter named "param_name" present
225 : * in this class, false otherwise.
226 : */
227 : bool has_value(const std::string & param_name) const;
228 :
229 : /**
230 : * \returns true if there is an extra parameter named "param_name" present
231 : * in this class, false otherwise.
232 : */
233 : bool has_extra_value(const std::string & param_name) const;
234 :
235 : /**
236 : * Get the value of the specified parameter, throw an error if it does not exist.
237 : * Here we assume that there is only one sample, throw an error otherwise.
238 : * The Real-returning version also throws an error if the parameter exists
239 : * but contains multiple values.
240 : */
241 : Real get_value(const std::string & param_name) const;
242 : const RBParameter & get_vector_value(const std::string & param_name) const;
243 :
244 : /**
245 : * Get the value of the specified parameter, returning the provided
246 : * default value if it does not exist.
247 : * If the value does exist, we assume that there is only one sample,
248 : * and throw an error otherwise.
249 : * The Real-returning version also throws an error if the parameter exists
250 : * but contains multiple values.
251 : */
252 : Real get_value(const std::string & param_name, const Real & default_val) const;
253 : const RBParameter & get_vector_value(const std::string & param_name, const RBParameter & default_val) const;
254 :
255 : /**
256 : * Get the value of the specified parameter at the specified sample,
257 : * throwing an error if it does not exist.
258 : * The Real-returning version throws an error if the parameter exists
259 : * but contains multiple values.
260 : */
261 : Real get_sample_value(const std::string & param_name, std::size_t sample_idx) const;
262 : const RBParameter & get_sample_vector_value(const std::string & param_name, std::size_t sample_idx) const;
263 :
264 : /**
265 : * Get the value of the specified parameter at the specified sample,
266 : * returning the provided default value if either the parameter is
267 : * not defined or the sample is invalid.
268 : * The Real-returning version throws an error if the parameter exists
269 : * but contains multiple values.
270 : */
271 : Real get_sample_value(const std::string & param_name, std::size_t sample_idx, const Real & default_val) const;
272 : const RBParameter & get_sample_vector_value(const std::string & param_name, std::size_t sample_idx, const RBParameter & default_val) const;
273 :
274 : /**
275 : * Set the value of the specified parameter. If param_name
276 : * doesn't already exist, it is added to the RBParameters object.
277 : * For backwards compatibility, calling this function sets up
278 : * "param_name" to be a single-entry vector with "value" as the
279 : * only entry.
280 : */
281 : void set_value(const std::string & param_name, Real value);
282 : void set_value(const std::string & param_name, const RBParameter & value);
283 :
284 : /**
285 : * Set the value of the specified parameter at the specified sample
286 : * index. The sample index can refer to, e.g., load or time steps.
287 : */
288 : void set_value(const std::string & param_name, std::size_t index, Real value);
289 : void set_value(const std::string & param_name, std::size_t index, const RBParameter & value);
290 :
291 : /**
292 : * Similar to set_value(name, index, value) but instead of specifying a particular
293 : * index, just appends one more. Calling push_back_value() many times is more efficient
294 : * than calling set_value(name, index, value) many times because it takes advantage
295 : * of the std::vector's size-doubling t reduce allocations.
296 : */
297 : void push_back_value(const std::string & param_name, Real value);
298 : void push_back_value(const std::string & param_name, const RBParameter & value);
299 :
300 : /**
301 : * Same as push_back_value(), but for "extra" parameters.
302 : */
303 : void push_back_extra_value(const std::string & param_name, Real value);
304 : void push_back_extra_value(const std::string & param_name, const RBParameter & value);
305 :
306 : /**
307 : * Get the value of the specified extra parameter, throwing an error
308 : * if it does not exist.
309 : */
310 : Real get_extra_value(const std::string & param_name) const;
311 : const RBParameter & get_extra_vector_value(const std::string & param_name) const;
312 :
313 : /**
314 : * Get the value of the specified extra parameter, returning the
315 : * provided default value if it does not exist.
316 : */
317 : Real get_extra_value(const std::string & param_name, const Real & default_val) const;
318 : const RBParameter & get_extra_vector_value(const std::string & param_name, const RBParameter & default_val) const;
319 :
320 : /**
321 : * Get the value of the specified "extra" parameter at the specified sample index,
322 : * throwing an error if it does not exist.
323 : */
324 : Real get_extra_sample_value(const std::string & param_name, std::size_t sample_idx) const;
325 : const RBParameter & get_extra_sample_vector_value(const std::string & param_name, std::size_t sample_idx) const;
326 :
327 : /**
328 : * Get the value of the specified extra parameter at the specified sample index,
329 : * returning the provided default value if either the parameter is
330 : * not defined or the sample index is invalid.
331 : */
332 : Real get_extra_sample_value(const std::string & param_name, std::size_t sample_idx, const Real & default_val) const;
333 : const RBParameter & get_extra_sample_vector_value(const std::string & param_name, std::size_t sample_idx, const RBParameter & default_val) const;
334 :
335 : /**
336 : * Set the value of the specified extra parameter. If param_name
337 : * doesn't already exist, it is added to the extra parameters.
338 : */
339 : void set_extra_value(const std::string & param_name, Real value);
340 : void set_extra_value(const std::string & param_name, const RBParameter & value);
341 :
342 : /**
343 : * Set the value of the specified extra parameter at the specified sample
344 : * index. The sample index can refer to, e.g., load or time steps.
345 : */
346 : void set_extra_value(const std::string & param_name, std::size_t index, Real value);
347 : void set_extra_value(const std::string & param_name, std::size_t index, const RBParameter & value);
348 :
349 : /**
350 : * Get the number of parameters that have been added.
351 : */
352 : unsigned int n_parameters() const;
353 :
354 : /**
355 : * Set the number of samples this RBParameters object is intended to
356 : * represent, in the case that there are no actual parameters stored
357 : * on it. Note: this value will only be used in the no-parameters
358 : * case; if there are actual parameters specified in this class, the
359 : * number set via this API is ignored. All parameters stored within
360 : * the RBParameters object must have n_samples() samples.
361 : */
362 : void set_n_samples(unsigned int n_samples);
363 :
364 : /**
365 : * Returns the number of samples stored for all parameters. For
366 : * simplicity, we require all parameters to store the same number of
367 : * "samples" ("sample" here may refer to, e.g., time step or load step) and in
368 : * debug mode we actually verify that is the case.
369 : */
370 : unsigned int n_samples() const;
371 :
372 : /**
373 : * \return a set with the names of the parameters.
374 : *
375 : * Note that instead of creating a new set of strings here, it's
376 : * better to iterate over the RBParameters object directly, using
377 : * the iterators from the begin()/end() functions. The .first
378 : * will provide the parameter name, .second can be ignored as needed.
379 : */
380 : std::set<std::string> get_parameter_names() const;
381 :
382 : /**
383 : * \return a set with the names of the extra parameters.
384 : *
385 : * Note that instead of creating a new set of strings here, it's
386 : * better to iterate over the RBParameters extra object directly, using
387 : * the iterators from the extra_begin()/extra_end() functions. The .first
388 : * will provide the parameter name, .second can be ignored as needed.
389 : */
390 : std::set<std::string> get_extra_parameter_names() const;
391 :
392 : /**
393 : * Erase \p param_name from _parameters. If \p param_name is not present
394 : * in _parameters, then do nothing.
395 : */
396 : void erase_parameter(const std::string & param_name);
397 :
398 : /**
399 : * Erase \p param_name from _extra_parameters. If \p param_name is not present
400 : * in _extra_parameters, then do nothing.
401 : */
402 : void erase_extra_parameter(const std::string & param_name);
403 :
404 : /**
405 : * Two RBParameters are equal if they have the same _parameters map.
406 : */
407 : bool operator== (const RBParameters & rhs) const;
408 :
409 : /**
410 : * \returns !(*this == rhs).
411 : */
412 : bool operator!= (const RBParameters & rhs) const;
413 :
414 : /**
415 : * Append "rhs" to "*this". Both RBParameters objects must have the
416 : * same n_samples(), otherwise an error is thrown. If some of the
417 : * parameter names overlap, then the values from rhs overwrite
418 : * *this. Both parameters and "extra" parameters are appended.
419 : */
420 : RBParameters & operator+= (const RBParameters & rhs);
421 :
422 : /**
423 : * Get a string that specifies the contents of this RBParameters object.
424 : * \p precision specifies the number of digits of precision we use
425 : * in scientific notation in the string.
426 : * \p max_values is the max number of values to print out if the parameter
427 : * is vector-valued. Set to negative value to print all.
428 : */
429 : std::string get_string(unsigned precision=6, int max_values=5) const;
430 :
431 : /**
432 : * Print the parameters.
433 : */
434 : void print(unsigned precision=6, int max_values=5) const;
435 :
436 : private:
437 :
438 : /**
439 : * Helper function for the 3-parameter versions of set_value() and
440 : * set_extra_value().
441 : */
442 : void set_value_helper(std::map<std::string, std::vector<RBParameter>> & map,
443 : const std::string & param_name,
444 : const std::size_t index,
445 : RBParameter value);
446 :
447 : /**
448 : * The number of samples represented by this RBParameters object, in
449 : * the case where there are no parameters actually stored on it. If
450 : * there are parameters stored on this RBParameters object, then the
451 : * n_samples() API returns that number of samples instead.
452 : */
453 : unsigned int _n_samples;
454 :
455 : /**
456 : * Actual parameter values (in std::vector<RBParameter> form) across a vector of samples.
457 : * Each vector is indexed by a name.
458 : * Note that the number of samples in the outer vector should be the same
459 : * across all parameters, however, this is not necessary for the inner
460 : * "value-vector".
461 : */
462 : std::map<std::string, std::vector<RBParameter>> _parameters;
463 :
464 : /**
465 : * Extra parameter vectors not used for RB training.
466 : * Each vector is indexed by a name.
467 : */
468 : std::map<std::string, std::vector<RBParameter>> _extra_parameters;
469 : };
470 :
471 : } // namespace libMesh
472 :
473 :
474 : #endif // LIBMESH_RB_PARAMETERS_H
|