LCOV - code coverage report
Current view: top level - include/utils - parameters.h (source / functions) Hit Total Coverage
Test: libMesh/libmesh: #4249 (f45222) with base 7cab9a Lines: 26 76 34.2 %
Date: 2025-09-10 12:25:45 Functions: 20 49 40.8 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : // The libMesh Finite Element Library.
       2             : // Copyright (C) 2002-2025 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner
       3             : 
       4             : // This library is free software; you can redistribute it and/or
       5             : // modify it under the terms of the GNU Lesser General Public
       6             : // License as published by the Free Software Foundation; either
       7             : // version 2.1 of the License, or (at your option) any later version.
       8             : 
       9             : // This library is distributed in the hope that it will be useful,
      10             : // but WITHOUT ANY WARRANTY; without even the implied warranty of
      11             : // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      12             : // Lesser General Public License for more details.
      13             : 
      14             : // You should have received a copy of the GNU Lesser General Public
      15             : // License along with this library; if not, write to the Free Software
      16             : // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
      17             : 
      18             : 
      19             : 
      20             : #ifndef LIBMESH_PARAMETERS_H
      21             : #define LIBMESH_PARAMETERS_H
      22             : 
      23             : // Local includes
      24             : #include "libmesh/libmesh_common.h"
      25             : #include "libmesh/reference_counted_object.h"
      26             : #include "libmesh/print_trace.h"
      27             : 
      28             : // C++ includes
      29             : #include <cstddef>
      30             : #include <map>
      31             : #include <sstream>
      32             : #include <string>
      33             : #include <typeinfo>
      34             : #include <vector>
      35             : #include <memory>
      36             : #include <set>
      37             : #ifdef LIBMESH_HAVE_RTTI
      38             : #include <typeinfo>
      39             : #endif
      40             : 
      41             : namespace libMesh
      42             : {
      43             : /**
      44             :  * Helper functions for printing scalar, vector, vector<vector> and vector<vector<vector>>
      45             :  * types.  Called from Parameters::Parameter<T>::print(...).
      46             :  */
      47             : template<typename P>
      48             : void print_helper(std::ostream & os, const P * param);
      49             : 
      50             : template<typename P>
      51             : void print_helper(std::ostream & os, const std::vector<P> * param);
      52             : 
      53             : template<typename P>
      54             : void print_helper(std::ostream & os, const std::vector<std::vector<P>> * param);
      55             : 
      56             : template<typename P>
      57             : void print_helper(std::ostream & os, const std::vector<std::vector<std::vector<P>>> * param);
      58             : 
      59             : template<typename P1, typename P2, typename C, typename A>
      60             : void print_helper(std::ostream & os, const std::map<P1, P2, C, A> * param);
      61             : 
      62             : template <typename P, typename C, typename A>
      63             : void print_helper(std::ostream & os, const std::set<P, C, A> * param);
      64             : 
      65             : /**
      66             :  * This class provides the ability to map between
      67             :  * arbitrary, user-defined strings and several data
      68             :  * types.  This can be used to provide arbitrary
      69             :  * user-specified options.
      70             :  *
      71             :  * \author Benjamin S. Kirk
      72             :  * \date 2004
      73             :  */
      74             : class Parameters
      75             : {
      76             : public:
      77             : 
      78             :   /**
      79             :    * Default constructor.
      80             :    */
      81      460691 :   Parameters () = default;
      82             : 
      83             :   /**
      84             :    * Copy constructor. Makes an independent copy by cloning the
      85             :    * contents of the passed-in Parameters object.
      86             :    */
      87             :   Parameters (const Parameters &);
      88             : 
      89             :   /**
      90             :    * Destructor.
      91             :    */
      92      459037 :   virtual ~Parameters () = default;
      93             : 
      94             :   /**
      95             :    * Assignment operator.  Removes all parameters in \p this
      96             :    * and inserts copies of all parameters from \p source
      97             :    */
      98             :   virtual Parameters & operator= (const Parameters & source);
      99             : 
     100             :   /**
     101             :    * Addition/Assignment operator.  Inserts copies of all parameters
     102             :    * from \p source.  Any parameters of the same name already in \p
     103             :    * this are replaced.
     104             :    */
     105             :   virtual Parameters & operator+= (const Parameters & source);
     106             : 
     107             :   /**
     108             :    * \returns \p true if a parameter of type \p T
     109             :    * with a specified name exists, \p false otherwise.
     110             :    *
     111             :    * If RTTI has been disabled then we return \p true
     112             :    * if a parameter of specified name exists regardless of its type.
     113             :    */
     114             :   template <typename T>
     115             :   bool have_parameter (std::string_view) const;
     116             : 
     117             :   /**
     118             :    * \returns A constant reference to the specified parameter
     119             :    * value.  Requires, of course, that the parameter exists.
     120             :    */
     121             :   template <typename T>
     122             :   const T & get (std::string_view) const;
     123             : 
     124             :   /**
     125             :    * Inserts a new Parameter into the object but does not return
     126             :    * a writable reference.  The value of the newly inserted
     127             :    * parameter may not be valid.
     128             :    */
     129             :   template <typename T>
     130             :   void insert (const std::string &);
     131             : 
     132             :   /**
     133             :    * \returns A writable reference to the specified parameter.
     134             :    * This method will create the parameter if it does not exist,
     135             :    * so it can be used to define parameters which will later be
     136             :    * accessed with the \p get() member.
     137             :    */
     138             :   template <typename T>
     139             :   T & set (const std::string &);
     140             : 
     141             :   /**
     142             :    * Overridable function to set any extended attributes for
     143             :    * classes inheriting from this class.
     144             :    */
     145      466902 :   virtual void set_attributes(const std::string &, bool /*inserted_only*/) {}
     146             : 
     147             :   /**
     148             :    * Removes the specified parameter from the list, if it exists.
     149             :    */
     150             :   void remove (std::string_view);
     151             : 
     152             :   /**
     153             :    * \returns The total number of parameters.
     154             :    */
     155             :   std::size_t n_parameters () const { return _values.size(); }
     156             : 
     157             : #ifdef LIBMESH_HAVE_RTTI
     158             :   /**
     159             :    * \returns The number of parameters of the requested type.
     160             :    */
     161             :   template <typename T>
     162             :   unsigned int n_parameters () const;
     163             : #endif // LIBMESH_HAVE_RTTI
     164             : 
     165             :   /**
     166             :    * Clears internal data structures & frees any allocated memory.
     167             :    */
     168             :   virtual void clear ();
     169             : 
     170             :   /**
     171             :    * Prints the contents, by default to libMesh::out.
     172             :    */
     173             :   void print (std::ostream & os=libMesh::out) const;
     174             : 
     175             :   /**
     176             :    * Abstract definition of a parameter value.
     177             :    */
     178             :   class Value : public ReferenceCountedObject<Value>
     179             :   {
     180             :   public:
     181             : 
     182             :     /**
     183             :      * Destructor.
     184             :      */
     185         792 :     virtual ~Value() = default;
     186             : 
     187             : #ifdef LIBMESH_HAVE_RTTI
     188             :     /**
     189             :      * std::type_info for type of parameter stored.
     190             :      * Must be reimplemented in derived classes.
     191             :      */
     192             :     virtual const std::type_info & type_info () const = 0;
     193             : 
     194             :     /**
     195             :      * String identifying the type of parameter stored.
     196             :      * Must be reimplemented in derived classes.
     197             :      */
     198             :     virtual std::string type () const = 0;
     199             : #endif // LIBMESH_HAVE_RTTI
     200             : 
     201             :     /**
     202             :      * Prints the parameter value to the specified stream.
     203             :      * Must be reimplemented in derived classes.
     204             :      */
     205             :     virtual void print(std::ostream &) const = 0;
     206             : 
     207             :     /**
     208             :      * Clone this value.  Useful in copy-construction.
     209             :      * Must be reimplemented in derived classes.
     210             :      */
     211             :     virtual std::unique_ptr<Value> clone () const = 0;
     212             :   };
     213             : 
     214             :   /**
     215             :    * Concrete definition of a parameter value
     216             :    * for a specified type.
     217             :    */
     218             :   template <typename T>
     219      465131 :   class Parameter : public Value
     220             :   {
     221             :   public:
     222             : 
     223             :     /**
     224             :      * \returns A read-only reference to the parameter value.
     225             :      */
     226      835935 :     const T & get () const { return _value; }
     227             : 
     228             :     /**
     229             :      * \returns A writable reference to the parameter value.
     230             :      */
     231      468142 :     T & set () { return _value; }
     232             : 
     233             : #ifdef LIBMESH_HAVE_RTTI
     234             :     /**
     235             :      * std::type_info for type of parameter stored.
     236             :      */
     237             :     virtual const std::type_info & type_info () const override;
     238             : 
     239             :     /**
     240             :      * String identifying the type of parameter stored.
     241             :      */
     242             :     virtual std::string type () const override;
     243             : #endif // LIBMESH_HAVE_RTTI
     244             : 
     245             :     /**
     246             :      * Prints the parameter value to the specified stream.
     247             :      */
     248             :     virtual void print(std::ostream &) const override;
     249             : 
     250             :     /**
     251             :      * Clone this value.  Useful in copy-construction.
     252             :      */
     253             :     virtual std::unique_ptr<Value> clone () const override;
     254             : 
     255             :   private:
     256             :     /**
     257             :      * Stored parameter value.
     258             :      */
     259             :     T _value;
     260             :   };
     261             : 
     262             :   /**
     263             :    * The type of the map that we store internally.
     264             :    */
     265             :   typedef std::map<std::string, std::unique_ptr<Value>, std::less<>> map_type;
     266             : 
     267             :   /**
     268             :    * Parameter map iterator.
     269             :    */
     270             :   typedef map_type::iterator iterator;
     271             : 
     272             :   /**
     273             :    * Constant parameter map iterator.
     274             :    */
     275             :   typedef map_type::const_iterator const_iterator;
     276             : 
     277             :   /**
     278             :    * Iterator pointing to the beginning of the set of parameters.
     279             :    */
     280             :   iterator begin();
     281             : 
     282             :   /**
     283             :    * Iterator pointing to the beginning of the set of parameters.
     284             :    */
     285             :   const_iterator begin() const;
     286             : 
     287             :   /**
     288             :    * Iterator pointing to the end of the set of parameters
     289             :    */
     290             :   iterator end();
     291             : 
     292             :   /**
     293             :    * Iterator pointing to the end of the set of parameters
     294             :    */
     295             :   const_iterator end() const;
     296             : 
     297             : protected:
     298             : 
     299             :   /**
     300             :    * Data structure to map names with values.
     301             :    */
     302             :   map_type _values;
     303             : };
     304             : 
     305             : // ------------------------------------------------------------
     306             : // Parameters::Parameter<> class inline methods
     307             : 
     308             : // These only work with Run-Time Type Information, even though
     309             : // typeid(T) *should* be determinable at compile time regardless...
     310             : #ifdef LIBMESH_HAVE_RTTI
     311             : template <typename T>
     312             : inline
     313           0 : const std::type_info & Parameters::Parameter<T>::type_info () const
     314             : {
     315           0 :   return typeid(T);
     316             : }
     317             : 
     318             : template <typename T>
     319             : inline
     320           0 : std::string Parameters::Parameter<T>::type () const
     321             : {
     322           0 :   return demangle(type_info().name());
     323             : }
     324             : #endif
     325             : 
     326             : template <typename T>
     327             : inline
     328           0 : void Parameters::Parameter<T>::print (std::ostream & os) const
     329             : {
     330             :   // Call helper function overloaded for basic scalar and vector types
     331           0 :   print_helper(os, static_cast<const T *>(&_value));
     332           0 : }
     333             : 
     334             : template <typename T>
     335             : inline
     336           0 : std::unique_ptr<Parameters::Value> Parameters::Parameter<T>::clone () const
     337             : {
     338           0 :   auto copy = std::make_unique<Parameter<T>>();
     339             : 
     340           0 :   copy->_value = this->_value; // assign value
     341             : 
     342           0 :   return copy; // as unique_ptr to base class
     343           0 : }
     344             : 
     345             : 
     346             : // ------------------------------------------------------------
     347             : // Parameters class inline methods
     348             : inline
     349           0 : void Parameters::clear ()
     350             : {
     351           0 :   _values.clear();
     352           0 : }
     353             : 
     354             : 
     355             : 
     356             : inline
     357           0 : Parameters & Parameters::operator= (const Parameters & source)
     358             : {
     359           0 :   this->Parameters::clear();
     360           0 :   *this += source;
     361             : 
     362           0 :   return *this;
     363             : }
     364             : 
     365             : inline
     366           0 : Parameters & Parameters::operator+= (const Parameters & source)
     367             : {
     368             :   // Overwrite each value (if it exists) or create a new entry
     369           0 :   for (const auto & [key, value] : source._values)
     370           0 :     _values[key] = value->clone();
     371             : 
     372           0 :   return *this;
     373             : }
     374             : 
     375             : inline
     376             : Parameters::Parameters (const Parameters & p)
     377             : {
     378             :   // calls assignment operator
     379             :   *this = p;
     380             : }
     381             : 
     382             : 
     383             : 
     384             : inline
     385           0 : void Parameters::print (std::ostream & os) const
     386             : {
     387           0 :   Parameters::const_iterator it = _values.begin();
     388             : 
     389             :   os << "Name\t Type\t Value\n"
     390           0 :      << "---------------------\n";
     391           0 :   while (it != _values.end())
     392             :     {
     393           0 :       os << " "   << it->first
     394             : #ifdef LIBMESH_HAVE_RTTI
     395           0 :          << "\t " << it->second->type()
     396             : #endif // LIBMESH_HAVE_RTTI
     397           0 :          << "\t ";   it->second->print(os);
     398           0 :       os << '\n';
     399             : 
     400           0 :       ++it;
     401             :     }
     402           0 : }
     403             : 
     404             : 
     405             : 
     406             : // Declare this now that Parameters::print() is defined.
     407             : // By declaring this early we can use it in subsequent
     408             : // methods.  Required for gcc-4.0.2 -- 11/30/2005, BSK
     409             : inline
     410           0 : std::ostream & operator << (std::ostream & os, const Parameters & p)
     411             : {
     412           0 :   p.print(os);
     413           0 :   return os;
     414             : }
     415             : 
     416             : 
     417             : 
     418             : template <typename T>
     419             : inline
     420     3195865 : bool Parameters::have_parameter (std::string_view name) const
     421             : {
     422      225128 :   Parameters::const_iterator it = _values.find(name);
     423             : 
     424     3195865 :   if (it != _values.end())
     425             :     {
     426             : #ifdef LIBMESH_HAVE_RTTI
     427             : 
     428      836446 :       if (dynamic_cast<const Parameter<T> *>(it->second.get()))
     429      836446 :         return true;
     430             : 
     431             : #else // !LIBMESH_HAVE_RTTI
     432             : 
     433             :       // cast_ptr will simply do a static_cast here when RTTI is not
     434             :       // enabled, and it will return a non-nullptr regardless of
     435             :       // whether or not the cast actually succeeds.
     436             :       libmesh_warning("Parameters::have_parameter() may return false positives when RTTI is not enabled.");
     437             : 
     438             :       if (cast_ptr<const Parameter<T> *>(it->second.get()))
     439             :         return true;
     440             : 
     441             : #endif
     442             :     }
     443             : 
     444      202558 :   return false;
     445             : }
     446             : 
     447             : 
     448             : 
     449             : template <typename T>
     450             : inline
     451      835935 : const T & Parameters::get (std::string_view name) const
     452             : {
     453      835935 :   if (!this->have_parameter<T>(name))
     454             :     {
     455           0 :       std::ostringstream oss;
     456             : 
     457           0 :       oss << "ERROR: no";
     458             : #ifdef LIBMESH_HAVE_RTTI
     459           0 :       oss << ' ' << demangle(typeid(T).name());
     460             : #endif
     461             :       oss << " parameter named \""
     462             :           << name << "\" found.\n\n"
     463           0 :           << "Known parameters:\n"
     464           0 :           << *this;
     465             : 
     466           0 :       libmesh_error_msg(oss.str());
     467           0 :     }
     468             : 
     469       23968 :   Parameters::const_iterator it = _values.find(name);
     470             : 
     471       23968 :   libmesh_assert(it != _values.end());
     472       23968 :   libmesh_assert(it->second);
     473             : 
     474             :   // Get pointer to derived type
     475       23968 :   auto ptr = cast_ptr<Parameter<T> *>(it->second.get());
     476             : 
     477             :   // Return const reference
     478      859903 :   return ptr->get();
     479             : }
     480             : 
     481             : template <typename T>
     482             : inline
     483             : void Parameters::insert (const std::string & name)
     484             : {
     485             :   if (!this->have_parameter<T>(name))
     486             :     _values[name] = std::make_unique<Parameter<T>>();
     487             : 
     488             :   set_attributes(name, true);
     489             : }
     490             : 
     491             : 
     492             : template <typename T>
     493             : inline
     494      468142 : T & Parameters::set (const std::string & name)
     495             : {
     496      468142 :   if (!this->have_parameter<T>(name))
     497      479997 :     _values[name] = std::make_unique<Parameter<T>>();
     498             : 
     499      468142 :   set_attributes(name, false);
     500             : 
     501             :   // Get pointer to existing or just-added entry
     502      468142 :   auto ptr = cast_ptr<Parameter<T> *>(_values[name].get());
     503             : 
     504             :   // Return writeable reference
     505      468142 :   return ptr->set();
     506             : }
     507             : 
     508             : inline
     509           0 : void Parameters::remove (std::string_view name)
     510             : {
     511             :   Parameters::iterator it = _values.find(name);
     512             : 
     513           0 :   if (it != _values.end())
     514           0 :     _values.erase(it);
     515           0 : }
     516             : 
     517             : 
     518             : 
     519             : #ifdef LIBMESH_HAVE_RTTI
     520             : template <typename T>
     521             : inline
     522             : unsigned int Parameters::n_parameters () const
     523             : {
     524             :   unsigned int cnt = 0;
     525             : 
     526             :   for (const auto & pr : _values)
     527             :     if (dynamic_cast<Parameter<T> *>(pr.second.get()))
     528             :       cnt++;
     529             : 
     530             :   return cnt;
     531             : }
     532             : #endif
     533             : 
     534             : inline
     535             : Parameters::iterator Parameters::begin()
     536             : {
     537             :   return _values.begin();
     538             : }
     539             : 
     540             : inline
     541             : Parameters::const_iterator Parameters::begin() const
     542             : {
     543             :   return _values.begin();
     544             : }
     545             : 
     546             : inline
     547             : Parameters::iterator Parameters::end()
     548             : {
     549             :   return _values.end();
     550             : }
     551             : 
     552             : inline
     553             : Parameters::const_iterator Parameters::end() const
     554             : {
     555             :   return _values.end();
     556             : }
     557             : 
     558             : //non-member scalar print function
     559             : template<typename P>
     560           0 : void print_helper(std::ostream & os, const P * param)
     561             : {
     562           0 :   os << *param;
     563           0 : }
     564             : 
     565             : template<>
     566             : inline
     567             : void print_helper(std::ostream & os, const char * param)
     568             : {
     569             :   // Specialization so that we don't print out unprintable characters
     570             :   os << static_cast<int>(*param);
     571             : }
     572             : 
     573             : template<>
     574             : inline
     575             : void print_helper(std::ostream & os, const unsigned char * param)
     576             : {
     577             :   // Specialization so that we don't print out unprintable characters
     578             :   os << static_cast<int>(*param);
     579             : }
     580             : 
     581             : //non-member vector print function
     582             : template<typename P>
     583             : void print_helper(std::ostream & os, const std::vector<P> * param)
     584             : {
     585             :   for (const auto & p : *param)
     586             :     os << p << " ";
     587             : }
     588             : 
     589             : //non-member vector<vector> print function
     590             : template<typename P>
     591             : void print_helper(std::ostream & os, const std::vector<std::vector<P>> * param)
     592             : {
     593             :   for (const auto & pv : *param)
     594             :     for (const auto & p : pv)
     595             :       os << p << " ";
     596             : }
     597             : 
     598             : //non-member vector<vector<vector>> print function
     599             : template<typename P>
     600             : void print_helper(std::ostream & os, const std::vector<std::vector<std::vector<P>>> * param)
     601             : {
     602             :   for (const auto & pvv : *param)
     603             :     for (const auto & pv : pvv)
     604             :       for (const auto & p : pv)
     605             :         os << p << " ";
     606             : }
     607             : 
     608             : //non-member map print function
     609             : template<typename P1, typename P2, typename C, typename A>
     610             : void print_helper(std::ostream & os, const std::map<P1, P2, C, A> * param)
     611             : {
     612             :   os << '{';
     613             :   std::size_t sz = param->size();
     614             :   for (auto KV : *param)
     615             :     {
     616             :       os << '\'' << KV.first << "\' => \'" << KV.second << '\'';
     617             :       if (--sz)
     618             :         os << ", ";
     619             :     }
     620             :   os << '}';
     621             : }
     622             : 
     623             : //non-member set print function
     624             : template<typename P, typename C, typename A>
     625             : void print_helper(std::ostream & os, const std::set<P, C, A> * param)
     626             : {
     627             :   for (const auto & p : *param)
     628             :     os << p << " ";
     629             : }
     630             : 
     631             : 
     632             : } // namespace libMesh
     633             : 
     634             : #endif // LIBMESH_PARAMETERS_H

Generated by: LCOV version 1.14