LCOV - code coverage report
Current view: top level - src/reduced_basis - rb_parameters.C (source / functions) Hit Total Coverage
Test: libMesh/libmesh: #4481 (67a8c4) with base cc8438 Lines: 121 211 57.3 %
Date: 2026-06-12 15:24:28 Functions: 32 53 60.4 %
Legend: Lines: hit not hit

          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             : // libmesh includes
      21             : #include "libmesh/int_range.h"
      22             : #include "libmesh/libmesh_common.h"
      23             : #include "libmesh/rb_parameters.h"
      24             : #include "libmesh/utility.h"
      25             : 
      26             : // C++ includes
      27             : #include <algorithm>
      28             : #include <sstream>
      29             : 
      30             : namespace libMesh
      31             : {
      32             : 
      33      134817 : RBParameters::RBParameters() :
      34      134817 :   _n_samples(1)
      35             : {
      36      134817 : }
      37             : 
      38           7 : RBParameters::RBParameters(const std::map<std::string, Real> & parameter_map) :
      39           7 :   _n_samples(1)
      40             : {
      41             :   // Backwards compatible support for constructing an RBParameters
      42             :   // object from a map<string, Real>. We store a single entry in each
      43             :   // vector in the map.
      44          28 :   for (const auto & [key, val] : parameter_map)
      45          48 :     _parameters[key] = {{val}};
      46          25 : }
      47             : 
      48           0 : void RBParameters::clear()
      49             : {
      50           0 :   _n_samples = 1;
      51           0 :   _parameters.clear();
      52           0 :   _extra_parameters.clear();
      53           0 : }
      54             : 
      55          49 : bool RBParameters::has_value(const std::string & param_name) const
      56             : {
      57          49 :   return _parameters.count(param_name);
      58             : }
      59             : 
      60           7 : bool RBParameters::has_extra_value(const std::string & param_name) const
      61             : {
      62           7 :   return _extra_parameters.count(param_name);
      63             : }
      64             : 
      65    11164791 : Real RBParameters::get_value(const std::string & param_name) const
      66             : {
      67             :   // Simply return the [0]th entry of the vector if possible, otherwise error.
      68    11164811 :   libmesh_error_msg_if(this->n_samples() != 1,
      69             :     "Requesting value for parameter " << param_name << ", but parameter contains multiple samples.");
      70    11164777 :   return this->get_sample_value(param_name, /*sample_idx=*/0);
      71             : }
      72             : 
      73           0 : const RBParameter& RBParameters::get_vector_value(const std::string & param_name) const
      74             : {
      75             :   // Simply return the [0]th entry of the vector if possible, otherwise error.
      76           0 :   libmesh_error_msg_if(this->n_samples() != 1,
      77             :     "Requesting value for parameter " << param_name << ", but parameter contains multiple sample.");
      78           0 :   return this->get_sample_vector_value(param_name, /*sample_idx=*/0);
      79             : }
      80             : 
      81          14 : Real RBParameters::get_value(const std::string & param_name, const Real & default_val) const
      82             : {
      83             :   // Simply return the [0]th entry of the vector if possible, otherwise error.
      84          34 :   libmesh_error_msg_if(this->n_samples() != 1,
      85             :     "Requesting value for parameter " << param_name << ", but parameter contains multiple samples.");
      86           0 :   return this->get_sample_value(param_name, /*sample_idx=*/0, default_val);
      87             : }
      88             : 
      89           0 : const RBParameter & RBParameters::get_vector_value(const std::string & param_name, const RBParameter & default_val) const
      90             : {
      91             :   // Simply return the [0]th entry of the vector if possible, otherwise error.
      92           0 :   libmesh_error_msg_if(this->n_samples() != 1,
      93             :     "Requesting value for parameter " << param_name << ", but parameter contains multiple samples.");
      94           0 :   return this->get_sample_vector_value(param_name, /*sample_idx=*/0, default_val);
      95             : }
      96             : 
      97    11164854 : Real RBParameters::get_sample_value(const std::string & param_name, std::size_t sample_idx) const
      98             : {
      99    11164854 :   const auto & sample_vec = libmesh_map_find(_parameters, param_name);
     100    13975070 :   libmesh_error_msg_if(sample_idx >= sample_vec.size(), "Error getting value for parameter " << param_name);
     101    13975042 :   libmesh_error_msg_if(sample_vec[sample_idx].size() != 1,
     102             :     "Requesting Real value for parameter " << param_name << ", but parameter contains multiple values.");
     103    11164819 :   return sample_vec[sample_idx][0];
     104             : }
     105             : 
     106          28 : const RBParameter & RBParameters::get_sample_vector_value(const std::string & param_name, std::size_t sample_idx) const
     107             : {
     108          28 :   const auto & sample_vec = libmesh_map_find(_parameters, param_name);
     109          37 :   libmesh_error_msg_if(sample_idx >= sample_vec.size(), "Error getting value for parameter " << param_name);
     110          14 :   return sample_vec[sample_idx];
     111             : }
     112             : 
     113          21 : Real RBParameters::get_sample_value(const std::string & param_name, std::size_t sample_idx, const Real & default_val) const
     114             : {
     115           6 :   auto it = _parameters.find(param_name);
     116          21 :   if (it == _parameters.end() || sample_idx >= it->second.size())
     117          21 :     return default_val;
     118           0 :   libmesh_error_msg_if(it->second[sample_idx].size() != 1,
     119             :     "Requesting Real value for parameter " << param_name << ", but parameter contains multiple values.");
     120           0 :   return it->second[sample_idx][0];
     121             : }
     122             : 
     123           7 : const RBParameter & RBParameters::get_sample_vector_value(const std::string & param_name, std::size_t sample_idx, const RBParameter & default_val) const
     124             : {
     125           2 :   auto it = _parameters.find(param_name);
     126           7 :   if (it == _parameters.end() || sample_idx >= it->second.size())
     127           2 :     return default_val;
     128           0 :   return it->second[sample_idx];
     129             : }
     130             : 
     131         683 : void RBParameters::set_value(const std::string & param_name, Real value)
     132             : {
     133             :   // This version of set_value() does not take an index and is provided
     134             :   // for backwards compatibility. It creates a vector entry for the specified
     135             :   // param_name, overwriting any value(s) that were present.
     136        1851 :   _parameters[param_name] = {{value}};
     137         970 : }
     138             : 
     139      869120 : void RBParameters::set_value(const std::string & param_name, const RBParameter & value)
     140             : {
     141             :   // This version of set_value() does not take an index and is provided
     142             :   // for backwards compatibility. It creates a vector entry for the specified
     143             :   // param_name, overwriting any value(s) that were present.
     144     2389070 :   _parameters[param_name] = {value};
     145     1301660 : }
     146             : 
     147             : void
     148        2109 : RBParameters::set_value_helper(std::map<std::string, std::vector<RBParameter>> & map,
     149             :                                const std::string & param_name,
     150             :                                const std::size_t index,
     151             :                                RBParameter value)
     152             : {
     153             :   // Get reference to vector of values for this parameter, creating it
     154             :   // if it does not already exist.
     155        2109 :   auto & sample_vec = map[param_name];
     156             : 
     157             :   // If vec is already big enough, just set the value
     158        2723 :   if (sample_vec.size() > index)
     159         586 :     sample_vec[index] = std::move(value);
     160             : 
     161             :   // Otherwise push_back() if the vec is just barely not big enough
     162          98 :   else if (sample_vec.size() == index)
     163          49 :     sample_vec.emplace_back(std::move(value));
     164             : 
     165             :   // Otherwise, allocate more space (padding with 0s) if vector is not
     166             :   // big enough to fit the user's requested index.
     167             :   else
     168             :     {
     169          77 :       RBParameter zero_parameter(value.size(), 0.0);
     170          49 :       sample_vec.resize(index+1, zero_parameter);
     171          28 :       sample_vec[index] = std::move(value);
     172             :     }
     173        2109 : }
     174             : 
     175          91 : void RBParameters::set_value(const std::string & param_name, std::size_t index, Real value)
     176             : {
     177          91 :   this->set_value_helper(_parameters, param_name, index, {value});
     178          91 : }
     179             : 
     180        2018 : void RBParameters::set_value(const std::string & param_name, std::size_t index, const RBParameter & value)
     181             : {
     182        2018 :   this->set_value_helper(_parameters, param_name, index, value);
     183        2018 : }
     184             : 
     185           0 : void RBParameters::set_extra_value(const std::string & param_name, std::size_t index, Real value)
     186             : {
     187           0 :   this->set_value_helper(_extra_parameters, param_name, index, {value});
     188           0 : }
     189             : 
     190           0 : void RBParameters::set_extra_value(const std::string & param_name, std::size_t index, const RBParameter & value)
     191             : {
     192           0 :   this->set_value_helper(_extra_parameters, param_name, index, value);
     193           0 : }
     194             : 
     195          70 : void RBParameters::push_back_value(const std::string & param_name, Real value)
     196             : {
     197             :   // Get reference to vector of values for this parameter, creating it
     198             :   // if it does not already exist, and push back the specified value.
     199          70 :   _parameters[param_name].push_back({value});
     200          70 : }
     201             : 
     202          14 : void RBParameters::push_back_value(const std::string & param_name, const RBParameter & value)
     203             : {
     204             :   // Get reference to vector of values for this parameter, creating it
     205             :   // if it does not already exist, and push back the specified value.
     206          14 :   _parameters[param_name].push_back(value);
     207          14 : }
     208             : 
     209          21 : void RBParameters::push_back_extra_value(const std::string & param_name, Real value)
     210             : {
     211             :   // Get reference to vector of values for this extra parameter, creating it
     212             :   // if it does not already exist, and push back the specified value.
     213          21 :   _extra_parameters[param_name].push_back({value});
     214          21 : }
     215             : 
     216           0 : void RBParameters::push_back_extra_value(const std::string & param_name, const RBParameter & value)
     217             : {
     218             :   // Get reference to vector of values for this extra parameter, creating it
     219             :   // if it does not already exist, and push back the specified value.
     220           0 :   _extra_parameters[param_name].push_back(value);
     221           0 : }
     222             : 
     223           0 : Real RBParameters::get_extra_value(const std::string & param_name) const
     224             : {
     225             :   // Same as get_value(param_name) but for the map of extra parameters
     226           0 :   const auto & sample_vec = libmesh_map_find(_extra_parameters, param_name);
     227           0 :   libmesh_error_msg_if(sample_vec.size() != 1,
     228             :     "Requesting value for extra parameter " << param_name << ", but parameter contains multiple samples.");
     229           0 :   libmesh_error_msg_if(sample_vec[0].size() != 1,
     230             :     "Requesting Real value for extra parameter " << param_name << ", but parameter contains multiple values.");
     231           0 :   return sample_vec[0][0];
     232             : }
     233             : 
     234           0 : const RBParameter & RBParameters::get_extra_vector_value(const std::string & param_name) const
     235             : {
     236             :   // Same as get_value(param_name) but for the map of extra parameters
     237           0 :   const auto & sample_vec = libmesh_map_find(_extra_parameters, param_name);
     238           0 :   libmesh_error_msg_if(sample_vec.size() == 0, "Error getting value for extra parameter " << param_name);
     239           0 :   return sample_vec[0];
     240             : }
     241             : 
     242           0 : Real RBParameters::get_extra_value(const std::string & param_name, const Real & default_val) const
     243             : {
     244             :   // same as get_value(param_name, default_val) but for the map of extra parameters
     245           0 :   auto it = _extra_parameters.find(param_name);
     246           0 :   if (it == _extra_parameters.end())
     247           0 :     return default_val;
     248             : 
     249           0 :   libmesh_error_msg_if(it->second.size() != 1,
     250             :                        "Requesting value for extra parameter " << param_name << ", but parameter contains multiple samples.");
     251           0 :   libmesh_error_msg_if(it->second[0].size() != 1,
     252             :     "Requesting Real value for extra parameter " << param_name << ", but parameter contains multiple values.");
     253           0 :   return it->second[0][0];
     254             : }
     255             : 
     256          21 : Real RBParameters::get_extra_sample_value(const std::string & param_name, std::size_t sample_idx) const
     257             : {
     258          21 :   const auto & sample_vec = libmesh_map_find(_extra_parameters, param_name);
     259          27 :   libmesh_error_msg_if(sample_idx >= sample_vec.size(), "Error getting value for extra parameter " << param_name);
     260          27 :   libmesh_error_msg_if(sample_vec[sample_idx].size() != 1,
     261             :     "Requesting Real value for extra parameter " << param_name << ", but parameter contains multiple values.");
     262          21 :   return sample_vec[sample_idx][0];
     263             : }
     264             : 
     265           0 : const RBParameter & RBParameters::get_extra_sample_vector_value(const std::string & param_name, std::size_t sample_idx) const
     266             : {
     267           0 :   const auto & sample_vec = libmesh_map_find(_extra_parameters, param_name);
     268           0 :   libmesh_error_msg_if(sample_idx >= sample_vec.size(), "Error getting value for extra parameter " << param_name);
     269           0 :   return sample_vec[sample_idx];
     270             : }
     271             : 
     272           0 : Real RBParameters::get_extra_sample_value(const std::string & param_name, std::size_t sample_idx, const Real & default_val) const
     273             : {
     274             :   // same as get_sample_value(param_name, index, default_val) but for the map of extra parameters
     275           0 :   auto it = _extra_parameters.find(param_name);
     276           0 :   if (it==_extra_parameters.end() || sample_idx >= it->second.size())
     277           0 :     return default_val;
     278           0 :   libmesh_error_msg_if(it->second[sample_idx].size() != 1,
     279             :     "Requesting Real value for extra parameter " << param_name << ", but parameter contains multiple values.");
     280           0 :   return it->second[sample_idx][0];
     281             : }
     282             : 
     283           0 : const RBParameter & RBParameters::get_extra_sample_vector_value(
     284             :     const std::string &param_name,
     285             :     std::size_t sample_idx,
     286             :     const RBParameter &default_val) const
     287             : {
     288           0 :   auto it = _extra_parameters.find(param_name);
     289           0 :   if (it == _extra_parameters.end() || sample_idx >= it->second.size())
     290           0 :     return default_val;
     291           0 :   return it->second[sample_idx];
     292             : }
     293             : 
     294           0 : void RBParameters::set_extra_value(const std::string & param_name, Real value)
     295             : {
     296             :   // This version of set_extra_value() does not take an index and is provided
     297             :   // for backwards compatibility. It creates a vector entry for the specified
     298             :   // param_name, overwriting any value(s) that were present.
     299           0 :   _extra_parameters[param_name] = {{value}};
     300           0 : }
     301             : 
     302           0 : void RBParameters::set_extra_value(const std::string & param_name, const RBParameter & value)
     303             : {
     304             :   // This version of set_extra_value() does not take an index and is provided
     305             :   // for backwards compatibility. It creates a vector entry for the specified
     306             :   // param_name, overwriting any value(s) that were present.
     307           0 :   _extra_parameters[param_name] = {value};
     308           0 : }
     309             : 
     310      675804 : unsigned int RBParameters::n_parameters() const
     311             : {
     312      675804 :   return cast_int<unsigned int>(_parameters.size());
     313             : }
     314             : 
     315           7 : void RBParameters::set_n_samples(unsigned int n_samples)
     316             : {
     317           7 :   _n_samples = n_samples;
     318           7 : }
     319             : 
     320    18754658 : unsigned int RBParameters::n_samples() const
     321             : {
     322             :   // Quick return if there are no parameters
     323    18754658 :   if (_parameters.empty())
     324          14 :     return _n_samples;
     325             : 
     326             :   // If _parameters is not empty, we can check the number of samples in the first param
     327    10658796 :   auto size_first = _parameters.begin()->second.size();
     328             : 
     329             : #ifdef DEBUG
     330             :   // In debug mode, verify that all parameters have the same number of samples
     331    29536134 :   for (const auto & pr : _parameters)
     332    24206736 :     libmesh_assert_msg(pr.second.size() == size_first, "All parameters must have the same number of samples.");
     333             : #endif
     334             : 
     335             :   // If we made it here in DEBUG mode, then all parameters were
     336             :   // verified to have the same number of samples.
     337    18754644 :   return size_first;
     338             : }
     339             : 
     340           0 : std::set<std::string> RBParameters::get_parameter_names() const
     341             : {
     342           0 :   std::set<std::string> param_names;
     343           0 :   for (const auto & pr : _parameters)
     344           0 :     param_names.insert(pr.first);
     345           0 :   return param_names;
     346             : }
     347             : 
     348           0 : std::set<std::string> RBParameters::get_extra_parameter_names() const
     349             : {
     350           0 :   std::set<std::string> param_names;
     351           0 :   for (const auto & pr : _extra_parameters)
     352           0 :     param_names.insert(pr.first);
     353           0 :   return param_names;
     354             : }
     355             : 
     356           0 : void RBParameters::erase_parameter(const std::string & param_name)
     357             : {
     358           0 :   _parameters.erase(param_name);
     359           0 : }
     360             : 
     361           0 : void RBParameters::erase_extra_parameter(const std::string & param_name)
     362             : {
     363           0 :   _extra_parameters.erase(param_name);
     364           0 : }
     365             : 
     366      271975 : std::map<std::string,std::vector<RBParameter>>::const_iterator RBParameters::begin() const
     367             : {
     368      271975 :   return _parameters.cbegin();
     369             : }
     370             : 
     371      271975 : std::map<std::string,std::vector<RBParameter>>::const_iterator RBParameters::end() const
     372             : {
     373      271975 :   return _parameters.cend();
     374             : }
     375             : 
     376      134260 : std::map<std::string,std::vector<RBParameter>>::const_iterator RBParameters::extra_begin() const
     377             : {
     378      134260 :   return _extra_parameters.cbegin();
     379             : }
     380             : 
     381      134260 : std::map<std::string,std::vector<RBParameter>>::const_iterator RBParameters::extra_end() const
     382             : {
     383      134260 :   return _extra_parameters.cend();
     384             : }
     385             : 
     386         204 : RBParameters::const_iterator RBParameters::begin_serialized() const
     387             : {
     388         204 :   return {_parameters.cbegin(), 0, 0};
     389             : }
     390             : 
     391         488 : RBParameters::const_iterator RBParameters::end_serialized() const
     392             : {
     393             :   // Note: the index 0 is irrelevant here since _parameters.end() does
     394             :   // not refer to a valid vector entry in the map.
     395         488 :   return {_parameters.cend(), 0, 0};
     396             : }
     397             : 
     398           0 : RBParameters::const_iterator RBParameters::begin_serialized_extra() const
     399             : {
     400           0 :   return {_extra_parameters.cbegin(), 0, 0};
     401             : }
     402             : 
     403           0 : RBParameters::const_iterator RBParameters::end_serialized_extra() const
     404             : {
     405             :   // Note: the index 0 is irrelevant here since _parameters.end() does
     406             :   // not refer to a valid vector entry in the map.
     407           0 :   return {_extra_parameters.cend(), 0, 0};
     408             : }
     409             : 
     410        2800 : bool RBParameters::operator==(const RBParameters & rhs) const
     411             : {
     412        2800 :   return (this->_parameters == rhs._parameters &&
     413        2800 :           this->_extra_parameters == rhs._extra_parameters);
     414             : }
     415             : 
     416           0 : bool RBParameters::operator!=(const RBParameters & rhs) const
     417             : {
     418           0 :   return !(*this == rhs);
     419             : }
     420             : 
     421           7 : RBParameters & RBParameters::operator+= (const RBParameters & rhs)
     422             : {
     423           7 :   libmesh_error_msg_if(this->n_samples() != rhs.n_samples(),
     424             :                        "Can only append RBParameters objects with matching numbers of samples.");
     425             : 
     426             :   // Overwrite or add each (key, vec) pair in rhs to *this.
     427          14 :   for (const auto & [key, vec] : rhs._parameters)
     428           7 :     _parameters[key] = vec;
     429          14 :   for (const auto & [key, vec] : rhs._extra_parameters)
     430           7 :     _extra_parameters[key] = vec;
     431             : 
     432           7 :   return *this;
     433             : }
     434             : 
     435         497 : std::string RBParameters::get_string(unsigned precision, int max_values) const
     436             : {
     437         793 :   std::stringstream param_stringstream;
     438         497 :   param_stringstream << std::setprecision(static_cast<int>(precision)) << std::scientific;
     439             : 
     440        2611 :   for (const auto & [param_name, sample_vec] : _parameters)
     441             :     {
     442             :       // Write the param name, followed by a comma-separated list of the sample/vector values.
     443        2114 :       param_stringstream << param_name << ": ";
     444        2730 :       std::string separator = "";
     445        4228 :       for (const auto & value_vec : sample_vec)
     446             :         {
     447         616 :           param_stringstream << separator;
     448        2730 :           if (value_vec.size() == 1)
     449        2114 :             param_stringstream << value_vec[0];
     450             :           else
     451             :             {
     452           0 :               param_stringstream << "[ ";
     453           0 :               for (const auto val_idx : index_range(value_vec))
     454             :                 {
     455           0 :                   if (max_values < 0 || val_idx < static_cast<unsigned>(max_values))
     456           0 :                     param_stringstream << value_vec[val_idx] << " ";
     457             :                   else
     458             :                     {
     459           0 :                       param_stringstream << "... ";
     460           0 :                       break;
     461             :                     }
     462             :                 }
     463           0 :               param_stringstream << "]";
     464             :             }
     465         616 :           separator = ", ";
     466             :         }
     467         616 :       param_stringstream << std::endl;
     468             :     }
     469             : 
     470         645 :   return param_stringstream.str();
     471         201 : }
     472             : 
     473         497 : void RBParameters::print(unsigned precision, int max_values) const
     474             : {
     475         497 :   libMesh::out << get_string(precision, max_values);
     476         497 : }
     477             : 
     478             : }

Generated by: LCOV version 1.14