LCOV - code coverage report
Current view: top level - tools - Tools.h (source / functions) Hit Total Coverage
Test: plumed test coverage Lines: 59 61 96.7 %
Date: 2024-10-11 08:09:47 Functions: 388 422 91.9 %

          Line data    Source code
       1             : /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
       2             :    Copyright (c) 2011-2023 The plumed team
       3             :    (see the PEOPLE file at the root of the distribution for a list of names)
       4             : 
       5             :    See http://www.plumed.org for more information.
       6             : 
       7             :    This file is part of plumed, version 2.
       8             : 
       9             :    plumed is free software: you can redistribute it and/or modify
      10             :    it under the terms of the GNU Lesser General Public License as published by
      11             :    the Free Software Foundation, either version 3 of the License, or
      12             :    (at your option) any later version.
      13             : 
      14             :    plumed is distributed in the hope that it will be useful,
      15             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      16             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      17             :    GNU Lesser General Public License for more details.
      18             : 
      19             :    You should have received a copy of the GNU Lesser General Public License
      20             :    along with plumed.  If not, see <http://www.gnu.org/licenses/>.
      21             : +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
      22             : #ifndef __PLUMED_tools_Tools_h
      23             : #define __PLUMED_tools_Tools_h
      24             : 
      25             : #include "AtomNumber.h"
      26             : #include <vector>
      27             : #include <string>
      28             : #include <cctype>
      29             : #include <cstdio>
      30             : #include <cmath>
      31             : #include <limits>
      32             : #include <algorithm>
      33             : #include <sstream>
      34             : #include <memory>
      35             : #include <cstddef>
      36             : 
      37             : namespace PLMD {
      38             : 
      39             : class IFile;
      40             : 
      41             : /// \ingroup TOOLBOX
      42             : /// Very small non-zero number
      43             : const double epsilon(std::numeric_limits<double>::epsilon());
      44             : 
      45             : /// \ingroup TOOLBOX
      46             : /// Boltzman constant in kj/K
      47             : const double kBoltzmann(0.0083144621);
      48             : 
      49             : /// \ingroup TOOLBOX
      50             : /// PI
      51             : const double pi(3.141592653589793238462643383279502884197169399375105820974944592307);
      52             : 
      53             : const double dp2cutoff(6.25);
      54             : 
      55             : const double dp2cutoffA=1.00193418799744762399; // 1.0/(1-std::exp(-dp2cutoff));
      56             : const double dp2cutoffB=-.00193418799744762399; // -std::exp(-dp2cutoff)/(1-std::exp(-dp2cutoff));
      57             : 
      58       30395 : inline static bool dp2cutoffNoStretch() {
      59       30395 :   static const auto* res=std::getenv("PLUMED_DP2CUTOFF_NOSTRETCH");
      60       30395 :   return res;
      61             : }
      62             : 
      63             : /// \ingroup TOOLBOX
      64             : /// Empty class which just contains several (static) tools
      65             : class Tools {
      66             : /// class to convert a string to a generic type T
      67             :   template<class T>
      68             :   static bool convertToAny(const std::string & str,T &t);
      69             : /// class to convert a string to a real type T.
      70             : /// T should be either float, double, or long double
      71             :   template<class T>
      72             :   static bool convertToReal(const std::string & str,T &t);
      73             : /// class to convert a string to a int type T
      74             :   template<class T>
      75             :   static bool convertToInt(const std::string & str,T &t);
      76             : public:
      77             : /// Split the line in words using separators.
      78             : /// It also take into account parenthesis. Outer parenthesis found are removed from
      79             : /// output, and the text between them is considered as a single word. Only the
      80             : /// outer parenthesis are processed, to allow nesting them.
      81             : /// parlevel, if not NULL, is increased or decreased according to the number of opened/closed parenthesis
      82             :   static std::vector<std::string> getWords(const std::string & line,const char* sep=NULL,int* parlevel=NULL,const char* parenthesis="{", const bool& delete_parenthesis=true);
      83             : /// Get a line from the file pointer ifile
      84             :   static bool getline(FILE*,std::string & line);
      85             : /// Get a parsed line from the file pointer ifile
      86             : /// This function already takes care of joining continued lines and splitting the
      87             : /// resulting line into an array of words
      88             :   static bool getParsedLine(IFile&ifile,std::vector<std::string> & line, const bool trimcomments=true);
      89             : /// compare two string in a case insensitive manner
      90             :   static bool caseInSensStringCompare(const std::string & str1, const std::string &str2);
      91             : /// Convert a string to a double, reading it
      92             :   static bool convertNoexcept(const std::string & str,double & t);
      93             : /// Convert a string to a long double, reading it
      94             :   static bool convertNoexcept(const std::string & str,long double & t);
      95             : /// Convert a string to a float, reading it
      96             :   static bool convertNoexcept(const std::string & str,float & t);
      97             : /// Convert a string to a int, reading it
      98             :   static bool convertNoexcept(const std::string & str,int & t);
      99             : /// Convert a string to a long int, reading it
     100             :   static bool convertNoexcept(const std::string & str,long int & t);
     101             : /// Convert a string to an unsigned int, reading it
     102             :   static bool convertNoexcept(const std::string & str,unsigned & t);
     103             : /// Convert a string to a long unsigned int, reading it
     104             :   static bool convertNoexcept(const std::string & str,long unsigned & t);
     105             : /// Convert a string to a atom number, reading it
     106             :   static bool convertNoexcept(const std::string & str,AtomNumber & t);
     107             : /// Convert a string to a string (i.e. copy)
     108             :   static bool convertNoexcept(const std::string & str,std::string & t);
     109             : /// Convert anything into a string
     110             :   template<typename T>
     111             :   static bool convertNoexcept(T i,std::string & str);
     112             : /// Convert anything into anything, throwing an exception in case there is an error
     113             : /// Remove trailing blanks
     114             :   static void trim(std::string & s);
     115             : /// Remove trailing comments
     116             :   static void trimComments(std::string & s);
     117             : /// Apply pbc for a unitary cell
     118             :   static double pbc(double);
     119             : /// Retrieve a key from a vector of options.
     120             : /// It finds a key starting with "key=" or equal to "key" and copy the
     121             : /// part after the = on s. E.g.:
     122             : /// line.push_back("aa=xx");
     123             : /// getKey(line,"aa",s);
     124             : /// will set s="xx"
     125             :   static bool getKey(std::vector<std::string>& line,const std::string & key,std::string & s,int rep=-1);
     126             : /// Find a keyword on the input line, eventually deleting it, and saving its value to val
     127             :   template <typename T,typename U>
     128    14244283 :   static void convert(const T & t,U & u) {
     129    14245070 :     plumed_assert(convertNoexcept(t,u)) <<"Error converting  "<<t;
     130    14244282 :   }
     131             :   template <typename T>
     132             :   static bool parse(std::vector<std::string>&line,const std::string&key,T&val,int rep=-1);
     133             : /// Find a keyword on the input line, eventually deleting it, and saving its value to a vector
     134             :   template <class T>
     135             :   static bool parseVector(std::vector<std::string>&line,const std::string&key,std::vector<T>&val,int rep=-1);
     136             : /// Find a keyword without arguments on the input line
     137             :   static bool parseFlag(std::vector<std::string>&line,const std::string&key,bool&val);
     138             : /// Find a keyword on the input line, just reporting if it exists or not
     139             :   static bool findKeyword(const std::vector<std::string>&line,const std::string&key);
     140             : /// Interpret atom ranges
     141             :   static void interpretRanges(std::vector<std::string>&);
     142             : /// Remove duplicates from a vector of type T
     143             :   template <typename T>
     144             :   static void removeDuplicates(std::vector<T>& vec);
     145             : /// interpret ":" syntax for labels
     146             :   static void interpretLabel(std::vector<std::string>&s);
     147             : /// list files in a directory
     148             :   static std::vector<std::string> ls(const std::string&);
     149             : /// removes leading and trailing blanks from a string
     150             :   static void stripLeadingAndTrailingBlanks( std::string& str );
     151             : /// Extract the extensions from a file name.
     152             : /// E.g.: extension("pippo.xyz")="xyz".
     153             : /// It only returns extensions with a length between 1 and 4
     154             : /// E.g.: extension("pippo.12345")="" whereas extenion("pippo.1234")="1234";
     155             : /// It is also smart enough to detect "/", so that
     156             : /// extension("pippo/.t")="" whereas extension("pippo/a.t")="t"
     157             :   static std::string extension(const std::string&);
     158             : /// Fast int power
     159             :   static double fastpow(double base,int exp);
     160             : /// Modified 0th-order Bessel function of the first kind
     161             :   static double bessel0(const double& val);
     162             : /// Check if a string full starts with string start.
     163             : /// Same as full.find(start)==0
     164             :   static bool startWith(const std::string & full,const std::string &start);
     165             :   /**
     166             :     Tool to create a vector of raw pointers from a vector of unique_pointers (const version).
     167             :   Returning a vector is fast in C++11. It can be used in order to feed a vector<unique_ptr<T>>
     168             :   to a function that takes a vector<T*>.
     169             :   \verbatim
     170             :   // some function that takes a vec
     171             :   void func(std::vector<Data*> & vec);
     172             :   std::vector<std::unique_ptr<Data>> vec;
     173             :   // func(vec); // does not compile
     174             :   func(Tools::unique2raw(vec)); // compiles
     175             :   \endverbatim
     176             :   Notice that the conversion is fast but takes
     177             :   some time to allocate the new vector and copy the pointers. In case the function
     178             :   acting on the vector<T*> is very fast and we do not want to add significant overhead,
     179             :   it might be convenient to store a separate set of raw pointers.
     180             :   \verbatim
     181             :   // some function that takes a vec
     182             :   void func(std::vector<Data*> & vec);
     183             :   std::vector<std::unique_ptr<Data>> vec;
     184             : 
     185             :   // conversion done only once:
     186             :   auto vec_ptr=Tools::unique2raw(vec);
     187             : 
     188             :   for(int i=0;i<1000;i++){
     189             :     func(vec_ptr);
     190             :   }
     191             :   \endverbatim
     192             :   */
     193             :   template <typename T>
     194             :   static std::vector<T*> unique2raw(const std::vector<std::unique_ptr<T>>&);
     195             : /// Tool to create a vector of raw pointers from a vector of unique_pointers.
     196             : /// See the non const version.
     197             :   template <typename T>
     198             :   static std::vector<const T*> unique2raw(const std::vector<std::unique_ptr<const T>>&);
     199             : /// Tiny class that changes directory and comes back when going out of scope.
     200             : /// In case system calls to change dir are not available it throws an exception.
     201             : /// \warning By construction, changing directory breaks thread safety! Use with care.
     202             :   class DirectoryChanger {
     203             :     static const std::size_t buffersize=4096;
     204             :     char cwd[buffersize]= {0};
     205             :   public:
     206             :     explicit DirectoryChanger(const char*path);
     207             :     ~DirectoryChanger();
     208             :   };
     209             : /// Mimic C++14 std::make_unique
     210             :   template<class T> struct _Unique_if {
     211             :     typedef std::unique_ptr<T> _Single_object;
     212             :   };
     213             :   template<class T> struct _Unique_if<T[]> {
     214             :     typedef std::unique_ptr<T[]> _Unknown_bound;
     215             :   };
     216             :   template<class T, std::size_t N> struct _Unique_if<T[N]> {
     217             :     typedef void _Known_bound;
     218             :   };
     219             :   template<class T, class... Args>
     220             :   static typename _Unique_if<T>::_Single_object
     221     4987385 :   make_unique(Args&&... args) {
     222     8581959 :     return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
     223             :   }
     224             :   template<class T>
     225             :   static typename _Unique_if<T>::_Unknown_bound
     226      853191 :   make_unique(std::size_t n) {
     227             :     typedef typename std::remove_extent<T>::type U;
     228   426515820 :     return std::unique_ptr<T>(new U[n]());
     229             :   }
     230             :   template<class T, class... Args>
     231             :   static typename _Unique_if<T>::_Known_bound
     232             :   make_unique(Args&&...) = delete;
     233             : };
     234             : 
     235             : template <class T>
     236       55575 : bool Tools::parse(std::vector<std::string>&line,const std::string&key,T&val,int rep) {
     237             :   std::string s;
     238      111150 :   if(!getKey(line,key+"=",s,rep)) return false;
     239       28048 :   if(s.length()>0 && !convertNoexcept(s,val))return false;
     240             :   return true;
     241             : }
     242             : 
     243             : template <class T>
     244       35005 : bool Tools::parseVector(std::vector<std::string>&line,const std::string&key,std::vector<T>&val,int rep) {
     245             :   std::string s;
     246       70010 :   if(!getKey(line,key+"=",s,rep)) return false;
     247       16271 :   val.clear();
     248       25939 :   std::vector<std::string> words=getWords(s,"\t\n ,");
     249      113132 :   for(unsigned i=0; i<words.size(); ++i) {
     250             :     T v;
     251       87193 :     std::string s=words[i];
     252       87193 :     const std::string multi("@replicas:");
     253       87193 :     if(rep>=0 && startWith(s,multi)) {
     254           6 :       s=s.substr(multi.length(),s.length());
     255           6 :       std::vector<std::string> words=getWords(s,"\t\n ,");
     256           6 :       plumed_assert(rep<static_cast<int>(words.size()));
     257           6 :       s=words[rep];
     258           6 :     }
     259       87193 :     if(!convertNoexcept(s,v))return false;
     260       87193 :     val.push_back(v);
     261             :   }
     262             :   return true;
     263       25939 : }
     264             : 
     265             : template<typename T>
     266        3186 : void Tools::removeDuplicates(std::vector<T>& vec)
     267             : {
     268        3186 :   std::sort(vec.begin(), vec.end());
     269        3186 :   vec.erase(std::unique(vec.begin(), vec.end()), vec.end());
     270        3186 : }
     271             : 
     272             : inline
     273       42714 : bool Tools::parseFlag(std::vector<std::string>&line,const std::string&key,bool&val) {
     274      103986 :   for(auto p=line.begin(); p!=line.end(); ++p) {
     275       62760 :     if(key==*p) {
     276        1488 :       val=true;
     277             :       line.erase(p);
     278             :       return true;
     279             :     }
     280             :   }
     281             :   return false;
     282             : }
     283             : 
     284             : /// beware: this brings any number into a pbc that ranges from -0.5 to 0.5
     285             : inline
     286  1820307219 : double Tools::pbc(double x) {
     287             : #ifdef __PLUMED_PBC_WHILE
     288             :   while (x>0.5) x-=1.0;
     289             :   while (x<-0.5) x+=1.0;
     290             :   return x;
     291             : #else
     292             :   if(std::numeric_limits<int>::round_style == std::round_toward_zero) {
     293             :     const double offset=100.0;
     294  1820307219 :     const double y=x+offset;
     295  1820307219 :     if(y>=0) return y-int(y+0.5);
     296        4577 :     else     return y-int(y-0.5);
     297             :   } else if(std::numeric_limits<int>::round_style == std::round_to_nearest) {
     298             :     return x-int(x);
     299             :   } else return x-floor(x+0.5);
     300             : #endif
     301             : }
     302             : 
     303             : template<typename T>
     304      323884 : bool Tools::convertNoexcept(T i,std::string & str) {
     305      323884 :   std::ostringstream ostr;
     306      210598 :   ostr<<i;
     307      323884 :   str=ostr.str();
     308      323884 :   return true;
     309      323884 : }
     310             : 
     311             : inline
     312    79175734 : double Tools::fastpow(double base, int exp)
     313             : {
     314    79175734 :   if(exp<0) {
     315           0 :     exp=-exp;
     316           0 :     base=1.0/base;
     317             :   }
     318             :   double result = 1.0;
     319   375014649 :   while (exp)
     320             :   {
     321   262238721 :     if (exp & 1)
     322   181137188 :       result *= base;
     323   262238721 :     exp >>= 1;
     324   262238721 :     base *= base;
     325             :   }
     326             : 
     327    79175734 :   return result;
     328             : }
     329             : 
     330             : template<typename T>
     331    13703470 : std::vector<T*> Tools::unique2raw(const std::vector<std::unique_ptr<T>> & x) {
     332    13703470 :   std::vector<T*> v(x.size());
     333    52721172 :   for(unsigned i=0; i<x.size(); i++) v[i]=x[i].get();
     334    13703470 :   return v;
     335             : }
     336             : 
     337             : template<typename T>
     338             : std::vector<const T*> Tools::unique2raw(const std::vector<std::unique_ptr<const T>> & x) {
     339             :   std::vector<const T*> v(x.size());
     340             :   for(unsigned i=0; i<x.size(); i++) v[i]=x[i].get();
     341             :   return v;
     342             : }
     343             : 
     344             : }
     345             : 
     346             : #endif
     347             : 

Generated by: LCOV version 1.15