libMesh
rb_parametrized.C
Go to the documentation of this file.
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 // libMesh includes
21 #include "libmesh/int_range.h"
22 #include "libmesh/simple_range.h"
23 #include "libmesh/xdr_cxx.h"
24 
25 // rbOOmit includes
26 #include "libmesh/rb_parametrized.h"
27 
28 // C++ includes
29 #include <sstream>
30 #include <fstream>
31 #include <algorithm> // std::min_element
32 
33 namespace libMesh
34 {
35 
37  :
38  verbose_mode(false),
39  parameters_initialized(false)
40 {
41 }
42 
44 
46 {
47  parameters.clear();
50  parameters_initialized = false;
51 }
52 
54  const RBParameters & mu_max_in,
55  const std::map<std::string, std::vector<Real>> & discrete_parameter_values)
56 {
57  // Check that the min/max vectors have the same size.
58  libmesh_error_msg_if(mu_min_in.n_parameters() != mu_max_in.n_parameters(),
59  "Error: Invalid mu_min/mu_max in initialize_parameters(), different number of parameters.");
60  libmesh_error_msg_if(mu_min_in.n_samples() != 1 ||
61  mu_max_in.n_samples() != 1,
62  "Error: Invalid mu_min/mu_max in initialize_parameters(), only 1 sample supported.");
63 
64  // Ensure all the values are valid for min and max.
65  auto pr_min = mu_min_in.begin_serialized();
66  auto pr_max = mu_max_in.begin_serialized();
67  for (; pr_min != mu_min_in.end_serialized(); ++pr_min, ++pr_max)
68  libmesh_error_msg_if((*pr_min).second > (*pr_max).second,
69  "Error: Invalid mu_min/mu_max in RBParameters constructor.");
70 
71  parameters_min = mu_min_in;
72  parameters_max = mu_max_in;
73 
74  // Add in min/max values due to the discrete parameters
75  for (const auto & [name, vals] : discrete_parameter_values)
76  {
77  libmesh_error_msg_if(vals.empty(), "Error: List of discrete parameters for " << name << " is empty.");
78 
79  Real min_val = *std::min_element(vals.begin(), vals.end());
80  Real max_val = *std::max_element(vals.begin(), vals.end());
81 
82  libmesh_assert_less_equal(min_val, max_val);
83 
84  parameters_min.set_value(name, min_val);
85  parameters_max.set_value(name, max_val);
86  }
87 
88  _discrete_parameter_values = discrete_parameter_values;
89 
91 
92  // Initialize the current parameters to parameters_min
94 }
95 
97 {
98  initialize_parameters(rb_parametrized.get_parameters_min(),
99  rb_parametrized.get_parameters_max(),
100  rb_parametrized.get_discrete_parameter_values());
101 }
102 
103 unsigned int RBParametrized::get_n_params() const
104 {
105  libmesh_error_msg_if(!parameters_initialized, "Error: parameters not initialized in RBParametrized::get_n_params");
106 
107  libmesh_assert_equal_to ( parameters_min.n_parameters(), parameters_max.n_parameters() );
108 
109  return parameters_min.n_parameters();
110 }
111 
113 {
114  libmesh_error_msg_if(!parameters_initialized, "Error: parameters not initialized in RBParametrized::get_n_continuous_params");
115 
117 
118  return static_cast<unsigned int>(get_n_params() - get_n_discrete_params());
119 }
120 
122 {
123  libmesh_error_msg_if(!parameters_initialized, "Error: parameters not initialized in RBParametrized::get_n_discrete_params");
124 
125  return cast_int<unsigned int>
127 }
128 
129 #ifdef LIBMESH_ENABLE_DEPRECATED
130 std::set<std::string> RBParametrized::get_parameter_names() const
131 {
132  libmesh_deprecated();
133  libmesh_error_msg_if(!parameters_initialized, "Error: parameters not initialized in RBParametrized::get_parameter_names");
134 
135  std::set<std::string> parameter_names;
136  for (const auto & pr : parameters_min)
137  parameter_names.insert(pr.first);
138 
139  return parameter_names;
140 }
141 #endif // LIBMESH_ENABLE_DEPRECATED
142 
144 {
145  libmesh_error_msg_if(!parameters_initialized, "Error: parameters not initialized in RBParametrized::set_parameters");
146 
147  // Terminate if params has the wrong number of parameters or samples.
148  // If the parameters are outside the min/max range, return false.
149  const bool valid_params = check_if_valid_params(params);
150 
151  // Make a copy of params (default assignment operator just does memberwise copy, which is sufficient here)
152  this->parameters = params;
153 
154  return valid_params;
155 }
156 
158 {
159  libmesh_error_msg_if(!parameters_initialized, "Error: parameters not initialized in RBParametrized::get_parameters");
160 
161  return parameters;
162 }
163 
165 {
166  libmesh_error_msg_if(!parameters_initialized, "Error: parameters not initialized in RBParametrized::get_parameters_min");
167 
168  return parameters_min;
169 }
170 
172 {
173  libmesh_error_msg_if(!parameters_initialized, "Error: parameters not initialized in RBParametrized::get_parameters_max");
174 
175  return parameters_max;
176 }
177 
178 Real RBParametrized::get_parameter_min(const std::string & param_name) const
179 {
180  libmesh_error_msg_if(!parameters_initialized, "Error: parameters not initialized in RBParametrized::get_parameter_min");
181 
182  return parameters_min.get_value(param_name);
183 }
184 
185 Real RBParametrized::get_parameter_max(const std::string & param_name) const
186 {
187  libmesh_error_msg_if(!parameters_initialized, "Error: parameters not initialized in RBParametrized::get_parameter_max");
188 
189  return parameters_max.get_value(param_name);
190 }
191 
193 {
194  libmesh_error_msg_if(!parameters_initialized, "Error: parameters not initialized in RBParametrized::print_current_parameters");
195 
196  get_parameters().print();
197 }
198 
199 void RBParametrized::write_parameter_data_to_files(const std::string & continuous_param_file_name,
200  const std::string & discrete_param_file_name,
201  const bool write_binary_data)
202 {
203  write_parameter_ranges_to_file(continuous_param_file_name, write_binary_data);
204  write_discrete_parameter_values_to_file(discrete_param_file_name, write_binary_data);
205 }
206 
207 void RBParametrized::write_parameter_ranges_to_file(const std::string & file_name,
208  const bool write_binary_data)
209 {
210  // The writing mode: ENCODE for binary, WRITE for ASCII
211  XdrMODE mode = write_binary_data ? ENCODE : WRITE;
212 
213  // Write out the parameter ranges
214  Xdr parameter_ranges_out(file_name, mode);
215  unsigned int n_continuous_params = get_n_continuous_params();
216  parameter_ranges_out << n_continuous_params;
217 
218  // Note: the following loops are not candidates for structured
219  // bindings syntax because the Xdr APIs which they call are not
220  // defined for const references. We must therefore make copies to
221  // call these functions.
222  for (const auto & pr : get_parameters_min())
223  {
224  std::string param_name = pr.first;
225  if (!is_discrete_parameter(param_name))
226  {
227  Real param_value = get_parameters_min().get_value(param_name);
228  parameter_ranges_out << param_name << param_value;
229  }
230  }
231  for (const auto & pr : get_parameters_max())
232  {
233  std::string param_name = pr.first;
234  if (!is_discrete_parameter(param_name))
235  {
236  Real param_value = get_parameters_max().get_value(param_name);
237  parameter_ranges_out << param_name << param_value;
238  }
239  }
240 
241  parameter_ranges_out.close();
242 }
243 
245  const bool write_binary_data)
246 {
247  // write out the discrete parameters, if we have any
248  if (get_n_discrete_params() > 0)
249  {
250  // The writing mode: ENCODE for binary, WRITE for ASCII
251  XdrMODE mode = write_binary_data ? ENCODE : WRITE;
252 
253  Xdr discrete_parameters_out(file_name, mode);
254  unsigned int n_discrete_params = get_n_discrete_params();
255  discrete_parameters_out << n_discrete_params;
256 
257  // Note: the following loops are not candidates for structured
258  // bindings syntax because the Xdr APIs which they call are not
259  // defined for const references. We must therefore make copies
260  // to call these functions.
261  for (const auto & pr : get_discrete_parameter_values())
262  {
263  std::string param_name = pr.first;
264  auto n_discrete_values = cast_int<unsigned int>(pr.second.size());
265  discrete_parameters_out << param_name << n_discrete_values;
266 
267  for (unsigned int i=0; i<n_discrete_values; i++)
268  {
269  Real discrete_value = pr.second[i];
270  discrete_parameters_out << discrete_value;
271  }
272  }
273  }
274 }
275 
276 void RBParametrized::read_parameter_data_from_files(const std::string & continuous_param_file_name,
277  const std::string & discrete_param_file_name,
278  const bool read_binary_data)
279 {
280  RBParameters param_min;
281  RBParameters param_max;
282  read_parameter_ranges_from_file(continuous_param_file_name,
283  read_binary_data,
284  param_min,
285  param_max);
286 
287  std::map<std::string, std::vector<Real>> discrete_parameter_values_in;
288  read_discrete_parameter_values_from_file(discrete_param_file_name,
289  read_binary_data,
290  discrete_parameter_values_in);
291 
292  initialize_parameters(param_min, param_max, discrete_parameter_values_in);
293 }
294 
295 void RBParametrized::read_parameter_ranges_from_file(const std::string & file_name,
296  const bool read_binary_data,
297  RBParameters & param_min,
298  RBParameters & param_max)
299 {
300  // The reading mode: DECODE for binary, READ for ASCII
301  XdrMODE mode = read_binary_data ? DECODE : READ;
302 
303  // Read in the parameter ranges
304  Xdr parameter_ranges_in(file_name, mode);
305  unsigned int n_continuous_params;
306  parameter_ranges_in >> n_continuous_params;
307 
308  for (unsigned int i=0; i<n_continuous_params; i++)
309  {
310  std::string param_name;
311  Real param_value;
312 
313  parameter_ranges_in >> param_name;
314  parameter_ranges_in >> param_value;
315 
316  param_min.set_value(param_name, param_value);
317  }
318  for (unsigned int i=0; i<n_continuous_params; i++)
319  {
320  std::string param_name;
321  Real param_value;
322 
323  parameter_ranges_in >> param_name;
324  parameter_ranges_in >> param_value;
325 
326  param_max.set_value(param_name, param_value);
327  }
328 
329  parameter_ranges_in.close();
330 }
331 
333  const bool read_binary_data,
334  std::map<std::string, std::vector<Real>> & discrete_parameter_values)
335 {
336  // read in the discrete parameters, if we have any
337  std::ifstream check_if_file_exists(file_name.c_str());
338  if (check_if_file_exists.good())
339  {
340  // The reading mode: DECODE for binary, READ for ASCII
341  XdrMODE mode = read_binary_data ? DECODE : READ;
342 
343  // Read in the parameter ranges
344  Xdr discrete_parameter_values_in(file_name, mode);
345  unsigned int n_discrete_params;
346  discrete_parameter_values_in >> n_discrete_params;
347 
348  for (unsigned int i=0; i<n_discrete_params; i++)
349  {
350  std::string param_name;
351  discrete_parameter_values_in >> param_name;
352 
353  unsigned int n_discrete_values;
354  discrete_parameter_values_in >> n_discrete_values;
355 
356  std::vector<Real> discrete_values(n_discrete_values);
357  for (auto & val : discrete_values)
358  discrete_parameter_values_in >> val;
359 
360  discrete_parameter_values[param_name] = discrete_values;
361  }
362  }
363 }
364 
365 bool RBParametrized::is_discrete_parameter(const std::string & mu_name) const
366 {
367  libmesh_error_msg_if(!parameters_initialized,
368  "Error: parameters not initialized in RBParametrized::is_discrete_parameter");
369 
370  return _discrete_parameter_values.count(mu_name);
371 }
372 
373 const std::map<std::string, std::vector<Real>> & RBParametrized::get_discrete_parameter_values() const
374 {
375  libmesh_error_msg_if(!parameters_initialized, "Error: parameters not initialized in RBParametrized::get_discrete_parameter_values");
376 
378 }
379 
381 {
382  for (const auto & [name, values] : get_discrete_parameter_values())
383  {
384  libMesh::out << "Discrete parameter " << name << ", values: ";
385 
386  for (const auto & value : values)
387  libMesh::out << value << " ";
388  libMesh::out << std::endl;
389  }
390 }
391 
393 {
394  // Check if number of parameters are correct.
395  libmesh_error_msg_if(params.n_parameters() != get_n_params(),
396  "Error: Number of parameters don't match; found "
397  << params.n_parameters() << ", expected "
398  << get_n_params());
399 
400  bool is_valid = true;
401  std::string prev_param_name = "";
402  for (const auto & [param_name, sample_vec] : params)
403  {
404  std::size_t sample_idx = 0;
405  const Real & min_value = get_parameter_min(param_name);
406  const Real & max_value = get_parameter_max(param_name);
407  for (const auto & value_vec : sample_vec)
408  {
409  for (const auto & value : value_vec)
410  {
411  // Check every parameter value (including across samples and vector-values)
412  // to ensure it's within the min/max range.
413  const bool outside_range = ((value < min_value) || (value > max_value));
414  is_valid = is_valid && !outside_range;
415  if (outside_range && verbose_mode)
416  {
417  libMesh::out << "Warning: parameter " << param_name << " value="
418  << value << " outside acceptable range: ("
419  << min_value << ", " << max_value << ")";
420  }
421 
422  // For discrete params, make sure params.get_value(param_name) is sufficiently
423  // close to one of the discrete parameter values.
424  // Note that vector-values not yet supported in discrete parameters,
425  // and the .get_sample_value() call will throw an error if the user
426  // tries to do it.
427  if (const auto it = get_discrete_parameter_values().find(param_name);
428  it != get_discrete_parameter_values().end())
429  {
430  const bool is_value_discrete =
431  is_value_in_list(params.get_sample_value(param_name, sample_idx),
432  it->second,
433  TOLERANCE);
434  is_valid = is_valid && is_value_discrete;
435  if (!is_value_discrete && verbose_mode)
436  libMesh::out << "Warning: parameter " << param_name << " value="
437  << value << " is not in discrete value list.";
438  }
439  }
440  ++sample_idx;
441  }
442  }
443  return is_valid;
444 }
445 
446 Real RBParametrized::get_closest_value(Real value, const std::vector<Real> & list_of_values)
447 {
448  libmesh_error_msg_if(list_of_values.empty(), "Error: list_of_values is empty.");
449 
450  Real min_distance = std::numeric_limits<Real>::max();
451  Real closest_val = 0.;
452  for (const auto & current_value : list_of_values)
453  {
454  Real distance = std::abs(value - current_value);
455  if (distance < min_distance)
456  {
457  min_distance = distance;
458  closest_val = current_value;
459  }
460  }
461 
462  return closest_val;
463 }
464 
465 bool RBParametrized::is_value_in_list(Real value, const std::vector<Real> & list_of_values, Real tol)
466 {
467  Real closest_value = get_closest_value(value, list_of_values);
468 
469  // Check if relative tolerance is satisfied
470  Real rel_error = std::abs(value - closest_value) / std::abs(value);
471  if (rel_error <= tol)
472  {
473  return true;
474  }
475 
476  // If relative tolerance isn't satisfied, we should still check an absolute
477  // error, since relative tolerance can be misleading if value is close to zero
478  Real abs_error = std::abs(value - closest_value);
479  return (abs_error <= tol);
480 }
481 
482 } // namespace libMesh
std::string name(const ElemQuality q)
This function returns a string containing some name for q.
Definition: elem_quality.C:42
Real get_value(const std::string &param_name) const
Get the value of the specified parameter, throw an error if it does not exist.
Definition: rb_parameters.C:65
virtual void clear()
Clear all the data structures associated with the system.
bool parameters_initialized
Flag indicating whether the parameters have been initialized.
void write_parameter_data_to_files(const std::string &continuous_param_file_name, const std::string &discrete_param_file_name, const bool write_binary_data)
Write out the parameter ranges to files.
void read_parameter_ranges_from_file(const std::string &file_name, const bool read_binary, RBParameters &param_min, RBParameters &param_max)
Read in the parameter ranges from file.
static constexpr Real TOLERANCE
const_iterator begin_serialized() const
Get const_iterator access to the parameters stored in this RBParameters object.
Real get_parameter_min(const std::string &param_name) const
Get minimum allowable value of parameter param_name.
Real get_parameter_max(const std::string &param_name) const
Get maximum allowable value of parameter param_name.
void write_discrete_parameter_values_to_file(const std::string &file_name, const bool write_binary_data)
Write out the discrete parameter values to file.
void close()
Closes the file if it is open.
Definition: xdr_cxx.C:277
const RBParameters & get_parameters_max() const
Get an RBParameters object that specifies the maximum allowable value for each parameter.
void read_discrete_parameter_values_from_file(const std::string &file_name, const bool read_binary_data, std::map< std::string, std::vector< Real >> &discrete_parameter_values_in)
Read in the discrete parameter values from file, if we have any.
void read_parameter_data_from_files(const std::string &continuous_param_file_name, const std::string &discrete_param_file_name, const bool read_binary_data)
Read in the parameter ranges from files.
The libMesh namespace provides an interface to certain functionality in the library.
static Real get_closest_value(Real value, const std::vector< Real > &list_of_values)
void print(unsigned precision=6, int max_values=5) const
Print the parameters.
Real distance(const Point &p)
static bool is_value_in_list(Real value, const std::vector< Real > &list_of_values, Real tol)
Helper function to check if the specified value is in the list of values (within a tolerance given by...
unsigned int get_n_discrete_params() const
Get the number of discrete parameters.
XdrMODE
Defines an enum for read/write mode in Xdr format.
Definition: enum_xdr_mode.h:35
RBParameters parameters_min
Vectors that define the ranges (min and max) for the parameters.
unsigned int n_parameters() const
Get the number of parameters that have been added.
const RBParameters & get_parameters_min() const
Get an RBParameters object that specifies the minimum allowable value for each parameter.
std::set< std::string > get_parameter_names() const
Get a set that stores the parameter names.
void write_parameter_ranges_to_file(const std::string &file_name, const bool write_binary)
Write out the parameter ranges to file.
RBParametrized()
Constructor.
const std::map< std::string, std::vector< Real > > & get_discrete_parameter_values() const
Get a const reference to the discrete parameter values.
libmesh_assert(ctx)
const RBParameters & get_parameters() const
Get the current parameters.
void print_parameters() const
Print the current parameters.
This class is part of the rbOOmit framework.
Definition: rb_parameters.h:52
std::map< std::string, std::vector< Real > > _discrete_parameter_values
Map that defines the allowable values of any discrete parameters.
unsigned int get_n_continuous_params() const
Get the number of continuous parameters.
bool verbose_mode
Public boolean to toggle verbose mode.
This class implements a C++ interface to the XDR (eXternal Data Representation) format.
Definition: xdr_cxx.h:67
bool set_parameters(const RBParameters &params)
Set the current parameters to params The parameters are checked for validity; an error is thrown if t...
unsigned int n_samples() const
Returns the number of samples stored for all parameters.
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
void set_value(const std::string &param_name, Real value)
Set the value of the specified parameter.
This class is part of the rbOOmit framework.
OStreamProxy out
void clear()
Clear this object.
Definition: rb_parameters.C:48
static const bool value
Definition: xdr_io.C:54
const_iterator end_serialized() const
bool check_if_valid_params(const RBParameters &params) const
Helper function to check that params is valid:
void initialize_parameters(const RBParameters &mu_min_in, const RBParameters &mu_max_in, const std::map< std::string, std::vector< Real >> &discrete_parameter_values)
Initialize the parameter ranges and set current_parameters.
unsigned int get_n_params() const
Get the number of parameters.
bool is_discrete_parameter(const std::string &mu_name) const
Is parameter mu_name discrete?
void print_discrete_parameter_values() const
Print out all the discrete parameter values.
RBParameters parameters
Vector storing the current parameters.