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 
130 {
131  libmesh_error_msg_if(!parameters_initialized, "Error: parameters not initialized in RBParametrized::set_parameters");
132 
133  // Terminate if params has the wrong number of parameters or samples.
134  // If the parameters are outside the min/max range, return false.
135  const bool valid_params = check_if_valid_params(params);
136 
137  // Make a copy of params (default assignment operator just does memberwise copy, which is sufficient here)
138  this->parameters = params;
139 
140  return valid_params;
141 }
142 
144 {
145  libmesh_error_msg_if(!parameters_initialized, "Error: parameters not initialized in RBParametrized::get_parameters");
146 
147  return parameters;
148 }
149 
151 {
152  libmesh_error_msg_if(!parameters_initialized, "Error: parameters not initialized in RBParametrized::get_parameters_min");
153 
154  return parameters_min;
155 }
156 
158 {
159  libmesh_error_msg_if(!parameters_initialized, "Error: parameters not initialized in RBParametrized::get_parameters_max");
160 
161  return parameters_max;
162 }
163 
164 Real RBParametrized::get_parameter_min(const std::string & param_name) const
165 {
166  libmesh_error_msg_if(!parameters_initialized, "Error: parameters not initialized in RBParametrized::get_parameter_min");
167 
168  return parameters_min.get_value(param_name);
169 }
170 
171 Real RBParametrized::get_parameter_max(const std::string & param_name) const
172 {
173  libmesh_error_msg_if(!parameters_initialized, "Error: parameters not initialized in RBParametrized::get_parameter_max");
174 
175  return parameters_max.get_value(param_name);
176 }
177 
179 {
180  libmesh_error_msg_if(!parameters_initialized, "Error: parameters not initialized in RBParametrized::print_current_parameters");
181 
182  get_parameters().print();
183 }
184 
185 void RBParametrized::write_parameter_data_to_files(const std::string & continuous_param_file_name,
186  const std::string & discrete_param_file_name,
187  const bool write_binary_data)
188 {
189  write_parameter_ranges_to_file(continuous_param_file_name, write_binary_data);
190  write_discrete_parameter_values_to_file(discrete_param_file_name, write_binary_data);
191 }
192 
193 void RBParametrized::write_parameter_ranges_to_file(const std::string & file_name,
194  const bool write_binary_data)
195 {
196  // The writing mode: ENCODE for binary, WRITE for ASCII
197  XdrMODE mode = write_binary_data ? ENCODE : WRITE;
198 
199  // Write out the parameter ranges
200  Xdr parameter_ranges_out(file_name, mode);
201  unsigned int n_continuous_params = get_n_continuous_params();
202  parameter_ranges_out << n_continuous_params;
203 
204  // Note: the following loops are not candidates for structured
205  // bindings syntax because the Xdr APIs which they call are not
206  // defined for const references. We must therefore make copies to
207  // call these functions.
208  for (const auto & pr : get_parameters_min())
209  {
210  std::string param_name = pr.first;
211  if (!is_discrete_parameter(param_name))
212  {
213  Real param_value = get_parameters_min().get_value(param_name);
214  parameter_ranges_out << param_name << param_value;
215  }
216  }
217  for (const auto & pr : get_parameters_max())
218  {
219  std::string param_name = pr.first;
220  if (!is_discrete_parameter(param_name))
221  {
222  Real param_value = get_parameters_max().get_value(param_name);
223  parameter_ranges_out << param_name << param_value;
224  }
225  }
226 
227  parameter_ranges_out.close();
228 }
229 
231  const bool write_binary_data)
232 {
233  // write out the discrete parameters, if we have any
234  if (get_n_discrete_params() > 0)
235  {
236  // The writing mode: ENCODE for binary, WRITE for ASCII
237  XdrMODE mode = write_binary_data ? ENCODE : WRITE;
238 
239  Xdr discrete_parameters_out(file_name, mode);
240  unsigned int n_discrete_params = get_n_discrete_params();
241  discrete_parameters_out << n_discrete_params;
242 
243  // Note: the following loops are not candidates for structured
244  // bindings syntax because the Xdr APIs which they call are not
245  // defined for const references. We must therefore make copies
246  // to call these functions.
247  for (const auto & pr : get_discrete_parameter_values())
248  {
249  std::string param_name = pr.first;
250  auto n_discrete_values = cast_int<unsigned int>(pr.second.size());
251  discrete_parameters_out << param_name << n_discrete_values;
252 
253  for (unsigned int i=0; i<n_discrete_values; i++)
254  {
255  Real discrete_value = pr.second[i];
256  discrete_parameters_out << discrete_value;
257  }
258  }
259  }
260 }
261 
262 void RBParametrized::read_parameter_data_from_files(const std::string & continuous_param_file_name,
263  const std::string & discrete_param_file_name,
264  const bool read_binary_data)
265 {
266  RBParameters param_min;
267  RBParameters param_max;
268  read_parameter_ranges_from_file(continuous_param_file_name,
269  read_binary_data,
270  param_min,
271  param_max);
272 
273  std::map<std::string, std::vector<Real>> discrete_parameter_values_in;
274  read_discrete_parameter_values_from_file(discrete_param_file_name,
275  read_binary_data,
276  discrete_parameter_values_in);
277 
278  initialize_parameters(param_min, param_max, discrete_parameter_values_in);
279 }
280 
281 void RBParametrized::read_parameter_ranges_from_file(const std::string & file_name,
282  const bool read_binary_data,
283  RBParameters & param_min,
284  RBParameters & param_max)
285 {
286  // The reading mode: DECODE for binary, READ for ASCII
287  XdrMODE mode = read_binary_data ? DECODE : READ;
288 
289  // Read in the parameter ranges
290  Xdr parameter_ranges_in(file_name, mode);
291  unsigned int n_continuous_params;
292  parameter_ranges_in >> n_continuous_params;
293 
294  for (unsigned int i=0; i<n_continuous_params; i++)
295  {
296  std::string param_name;
297  Real param_value;
298 
299  parameter_ranges_in >> param_name;
300  parameter_ranges_in >> param_value;
301 
302  param_min.set_value(param_name, param_value);
303  }
304  for (unsigned int i=0; i<n_continuous_params; i++)
305  {
306  std::string param_name;
307  Real param_value;
308 
309  parameter_ranges_in >> param_name;
310  parameter_ranges_in >> param_value;
311 
312  param_max.set_value(param_name, param_value);
313  }
314 
315  parameter_ranges_in.close();
316 }
317 
319  const bool read_binary_data,
320  std::map<std::string, std::vector<Real>> & discrete_parameter_values)
321 {
322  // read in the discrete parameters, if we have any
323  std::ifstream check_if_file_exists(file_name.c_str());
324  if (check_if_file_exists.good())
325  {
326  // The reading mode: DECODE for binary, READ for ASCII
327  XdrMODE mode = read_binary_data ? DECODE : READ;
328 
329  // Read in the parameter ranges
330  Xdr discrete_parameter_values_in(file_name, mode);
331  unsigned int n_discrete_params;
332  discrete_parameter_values_in >> n_discrete_params;
333 
334  for (unsigned int i=0; i<n_discrete_params; i++)
335  {
336  std::string param_name;
337  discrete_parameter_values_in >> param_name;
338 
339  unsigned int n_discrete_values;
340  discrete_parameter_values_in >> n_discrete_values;
341 
342  std::vector<Real> discrete_values(n_discrete_values);
343  for (auto & val : discrete_values)
344  discrete_parameter_values_in >> val;
345 
346  discrete_parameter_values[param_name] = discrete_values;
347  }
348  }
349 }
350 
351 bool RBParametrized::is_discrete_parameter(const std::string & mu_name) const
352 {
353  libmesh_error_msg_if(!parameters_initialized,
354  "Error: parameters not initialized in RBParametrized::is_discrete_parameter");
355 
356  return _discrete_parameter_values.count(mu_name);
357 }
358 
359 const std::map<std::string, std::vector<Real>> & RBParametrized::get_discrete_parameter_values() const
360 {
361  libmesh_error_msg_if(!parameters_initialized, "Error: parameters not initialized in RBParametrized::get_discrete_parameter_values");
362 
364 }
365 
367 {
368  for (const auto & [name, values] : get_discrete_parameter_values())
369  {
370  libMesh::out << "Discrete parameter " << name << ", values: ";
371 
372  for (const auto & value : values)
373  libMesh::out << value << " ";
374  libMesh::out << std::endl;
375  }
376 }
377 
379 {
380  // Check if number of parameters are correct.
381  libmesh_error_msg_if(params.n_parameters() != get_n_params(),
382  "Error: Number of parameters don't match; found "
383  << params.n_parameters() << ", expected "
384  << get_n_params());
385 
386  bool is_valid = true;
387  std::string prev_param_name = "";
388  for (const auto & [param_name, sample_vec] : params)
389  {
390  std::size_t sample_idx = 0;
391  const Real & min_value = get_parameter_min(param_name);
392  const Real & max_value = get_parameter_max(param_name);
393  for (const auto & value_vec : sample_vec)
394  {
395  for (const auto & value : value_vec)
396  {
397  // Check every parameter value (including across samples and vector-values)
398  // to ensure it's within the min/max range.
399  const bool outside_range = ((value < min_value) || (value > max_value));
400  is_valid = is_valid && !outside_range;
401  if (outside_range && verbose_mode)
402  {
403  libMesh::out << "Warning: parameter " << param_name << " value="
404  << value << " outside acceptable range: ("
405  << min_value << ", " << max_value << ")";
406  }
407 
408  // For discrete params, make sure params.get_value(param_name) is sufficiently
409  // close to one of the discrete parameter values.
410  // Note that vector-values not yet supported in discrete parameters,
411  // and the .get_sample_value() call will throw an error if the user
412  // tries to do it.
413  if (const auto it = get_discrete_parameter_values().find(param_name);
414  it != get_discrete_parameter_values().end())
415  {
416  const bool is_value_discrete =
417  is_value_in_list(params.get_sample_value(param_name, sample_idx),
418  it->second,
419  TOLERANCE);
420  is_valid = is_valid && is_value_discrete;
421  if (!is_value_discrete && verbose_mode)
422  libMesh::out << "Warning: parameter " << param_name << " value="
423  << value << " is not in discrete value list.";
424  }
425  }
426  ++sample_idx;
427  }
428  }
429  return is_valid;
430 }
431 
432 Real RBParametrized::get_closest_value(Real value, const std::vector<Real> & list_of_values)
433 {
434  libmesh_error_msg_if(list_of_values.empty(), "Error: list_of_values is empty.");
435 
436  Real min_distance = std::numeric_limits<Real>::max();
437  Real closest_val = 0.;
438  for (const auto & current_value : list_of_values)
439  {
440  Real distance = std::abs(value - current_value);
441  if (distance < min_distance)
442  {
443  min_distance = distance;
444  closest_val = current_value;
445  }
446  }
447 
448  return closest_val;
449 }
450 
451 bool RBParametrized::is_value_in_list(Real value, const std::vector<Real> & list_of_values, Real tol)
452 {
453  Real closest_value = get_closest_value(value, list_of_values);
454 
455  // Check if relative tolerance is satisfied
456  Real rel_error = std::abs(value - closest_value) / std::abs(value);
457  if (rel_error <= tol)
458  {
459  return true;
460  }
461 
462  // If relative tolerance isn't satisfied, we should still check an absolute
463  // error, since relative tolerance can be misleading if value is close to zero
464  Real abs_error = std::abs(value - closest_value);
465  return (abs_error <= tol);
466 }
467 
468 } // 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:278
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.
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:55
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.