LCOV - code coverage report
Current view: top level - src/reduced_basis - rb_parameters.C (source / functions) Hit Total Coverage
Test: libMesh/libmesh: #4229 (6a9aeb) with base 727f46 Lines: 121 211 57.3 %
Date: 2025-08-19 19:27:09 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      414081 : RBParameters::RBParameters() :
      34      414081 :   _n_samples(1)
      35             : {
      36      414081 : }
      37             : 
      38          71 : RBParameters::RBParameters(const std::map<std::string, Real> & parameter_map) :
      39          71 :   _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         284 :   for (const auto & [key, val] : parameter_map)
      45         432 :     _parameters[key] = {{val}};
      46         473 : }
      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         497 : bool RBParameters::has_value(const std::string & param_name) const
      56             : {
      57         497 :   return _parameters.count(param_name);
      58             : }
      59             : 
      60          71 : bool RBParameters::has_extra_value(const std::string & param_name) const
      61             : {
      62          71 :   return _extra_parameters.count(param_name);
      63             : }
      64             : 
      65    34318474 : 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    34318750 :   libmesh_error_msg_if(this->n_samples() != 1,
      69             :     "Requesting value for parameter " << param_name << ", but parameter contains multiple samples.");
      70    34318332 :   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         142 : 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         418 :   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    34319113 : Real RBParameters::get_sample_value(const std::string & param_name, std::size_t sample_idx) const
      98             : {
      99    34319113 :   const auto & sample_vec = libmesh_map_find(_parameters, param_name);
     100    37129457 :   libmesh_error_msg_if(sample_idx >= sample_vec.size(), "Error getting value for parameter " << param_name);
     101    37129173 :   libmesh_error_msg_if(sample_vec[sample_idx].size() != 1,
     102             :     "Requesting Real value for parameter " << param_name << ", but parameter contains multiple values.");
     103    34318758 :   return sample_vec[sample_idx][0];
     104             : }
     105             : 
     106         284 : const RBParameter & RBParameters::get_sample_vector_value(const std::string & param_name, std::size_t sample_idx) const
     107             : {
     108         284 :   const auto & sample_vec = libmesh_map_find(_parameters, param_name);
     109         357 :   libmesh_error_msg_if(sample_idx >= sample_vec.size(), "Error getting value for parameter " << param_name);
     110         142 :   return sample_vec[sample_idx];
     111             : }
     112             : 
     113         213 : 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         213 :   if (it == _parameters.end() || sample_idx >= it->second.size())
     117         213 :     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          71 : 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          71 :   if (it == _parameters.end() || sample_idx >= it->second.size())
     127           2 :     return default_val;
     128           0 :   return it->second[sample_idx];
     129             : }
     130             : 
     131        7067 : 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       21003 :   _parameters[param_name] = {{value}};
     137       13738 : }
     138             : 
     139     2619682 : 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     7640756 :   _parameters[param_name] = {value};
     145     4802784 : }
     146             : 
     147             : void
     148       21799 : 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       21799 :   auto & sample_vec = map[param_name];
     156             : 
     157             :   // If vec is already big enough, just set the value
     158       22413 :   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         994 :   else if (sample_vec.size() == index)
     163         497 :     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         525 :       RBParameter zero_parameter(value.size(), 0.0);
     170         497 :       sample_vec.resize(index+1, zero_parameter);
     171          28 :       sample_vec[index] = std::move(value);
     172             :     }
     173       21799 : }
     174             : 
     175         923 : void RBParameters::set_value(const std::string & param_name, std::size_t index, Real value)
     176             : {
     177         923 :   this->set_value_helper(_parameters, param_name, index, {value});
     178         923 : }
     179             : 
     180       20876 : void RBParameters::set_value(const std::string & param_name, std::size_t index, const RBParameter & value)
     181             : {
     182       20876 :   this->set_value_helper(_parameters, param_name, index, value);
     183       20876 : }
     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         710 : 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         710 :   _parameters[param_name].push_back({value});
     200         710 : }
     201             : 
     202         142 : 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         142 :   _parameters[param_name].push_back(value);
     207         142 : }
     208             : 
     209         213 : 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         213 :   _extra_parameters[param_name].push_back({value});
     214         213 : }
     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         213 : Real RBParameters::get_extra_sample_value(const std::string & param_name, std::size_t sample_idx) const
     257             : {
     258         213 :   const auto & sample_vec = libmesh_map_find(_extra_parameters, param_name);
     259         219 :   libmesh_error_msg_if(sample_idx >= sample_vec.size(), "Error getting value for extra parameter " << param_name);
     260         219 :   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         213 :   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     1813517 : unsigned int RBParameters::n_parameters() const
     311             : {
     312     1813517 :   return cast_int<unsigned int>(_parameters.size());
     313             : }
     314             : 
     315          71 : void RBParameters::set_n_samples(unsigned int n_samples)
     316             : {
     317          71 :   _n_samples = n_samples;
     318          71 : }
     319             : 
     320    62822219 : unsigned int RBParameters::n_samples() const
     321             : {
     322             :   // Quick return if there are no parameters
     323    62822219 :   if (_parameters.empty())
     324         142 :     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    62822077 :   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      862811 : std::map<std::string,std::vector<RBParameter>>::const_iterator RBParameters::begin() const
     367             : {
     368      862811 :   return _parameters.cbegin();
     369             : }
     370             : 
     371      862811 : std::map<std::string,std::vector<RBParameter>>::const_iterator RBParameters::end() const
     372             : {
     373      862811 :   return _parameters.cend();
     374             : }
     375             : 
     376      408234 : std::map<std::string,std::vector<RBParameter>>::const_iterator RBParameters::extra_begin() const
     377             : {
     378      408234 :   return _extra_parameters.cbegin();
     379             : }
     380             : 
     381      408234 : std::map<std::string,std::vector<RBParameter>>::const_iterator RBParameters::extra_end() const
     382             : {
     383      408234 :   return _extra_parameters.cend();
     384             : }
     385             : 
     386        2136 : RBParameters::const_iterator RBParameters::begin_serialized() const
     387             : {
     388        2136 :   return {_parameters.cbegin(), 0, 0};
     389             : }
     390             : 
     391        5056 : 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        5056 :   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       28415 : bool RBParameters::operator==(const RBParameters & rhs) const
     411             : {
     412       28415 :   return (this->_parameters == rhs._parameters &&
     413       28415 :           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          71 : RBParameters & RBParameters::operator+= (const RBParameters & rhs)
     422             : {
     423          71 :   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         142 :   for (const auto & [key, vec] : rhs._parameters)
     428          71 :     _parameters[key] = vec;
     429         142 :   for (const auto & [key, vec] : rhs._extra_parameters)
     430          71 :     _extra_parameters[key] = vec;
     431             : 
     432          71 :   return *this;
     433             : }
     434             : 
     435        5240 : std::string RBParameters::get_string(unsigned precision, int max_values) const
     436             : {
     437        5536 :   std::stringstream param_stringstream;
     438        5240 :   param_stringstream << std::setprecision(static_cast<int>(precision)) << std::scientific;
     439             : 
     440       27087 :   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       21847 :       param_stringstream << param_name << ": ";
     444       22463 :       std::string separator = "";
     445       43694 :       for (const auto & value_vec : sample_vec)
     446             :         {
     447         616 :           param_stringstream << separator;
     448       22463 :           if (value_vec.size() == 1)
     449       21847 :             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        5388 :   return param_stringstream.str();
     471        4944 : }
     472             : 
     473        5240 : void RBParameters::print(unsigned precision, int max_values) const
     474             : {
     475        5240 :   libMesh::out << get_string(precision, max_values);
     476        5240 : }
     477             : 
     478             : }

Generated by: LCOV version 1.14