1 /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 Copyright (c) 2011-2021 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
36 namespace PLMD {
37
38 class IFile;
39
40 /// \ingroup TOOLBOX
41 /// Very small non-zero number
42 const double epsilon(std::numeric_limits<double>::epsilon());
43
44 /// \ingroup TOOLBOX
45 /// Boltzman constant in kj/K
46 const double kBoltzmann(0.0083144621);
47
48 /// \ingroup TOOLBOX
49 /// PI
50 const double pi(3.141592653589793238462643383279502884197169399375105820974944592307);
51
52 /// \ingroup TOOLBOX
53 /// Empty class which just contains several (static) tools
54 class Tools {
55 /// class to convert a string to a generic type T
56 template<class T>
57 static bool convertToAny(const std::string & str,T &t);
58 /// class to convert a string to a real type T.
59 /// T should be either float, double, or long double
60 template<class T>
61 static bool convertToReal(const std::string & str,T &t);
62 /// class to convert a string to a int type T
63 template<class T>
64 static bool convertToInt(const std::string & str,T &t);
65 public:
66 /// Split the line in words using separators.
67 /// It also take into account parenthesis. Outer parenthesis found are removed from
68 /// output, and the text between them is considered as a single word. Only the
69 /// outer parenthesis are processed, to allow nesting them.
70 /// parlevel, if not NULL, is increased or decreased according to the number of opened/closed parenthesis
71 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);
72 /// Get a line from the file pointer ifile
73 static bool getline(FILE*,std::string & line);
74 /// Get a parsed line from the file pointer ifile
75 /// This function already takes care of joining continued lines and splitting the
76 /// resulting line into an array of words
77 static bool getParsedLine(IFile&ifile,std::vector<std::string> & line, const bool trimcomments=true);
78 /// compare two string in a case insensitive manner
79 static bool caseInSensStringCompare(const std::string & str1, const std::string &str2);
80 /// Convert a string to a double, reading it
81 static bool convert(const std::string & str,double & t);
82 /// Convert a string to a long double, reading it
83 static bool convert(const std::string & str,long double & t);
84 /// Convert a string to a float, reading it
85 static bool convert(const std::string & str,float & t);
86 /// Convert a string to a int, reading it
87 static bool convert(const std::string & str,int & t);
88 /// Convert a string to a long int, reading it
89 static bool convert(const std::string & str,long int & t);
90 /// Convert a string to an unsigned int, reading it
91 static bool convert(const std::string & str,unsigned & t);
92 /// Convert a string to a long unsigned int, reading it
93 static bool convert(const std::string & str,long unsigned & t);
94 /// Convert a string to a atom number, reading it
95 static bool convert(const std::string & str,AtomNumber & t);
96 /// Convert a string to a string (i.e. copy)
97 static bool convert(const std::string & str,std::string & t);
98 /// Convert anything into a string
99 template<typename T>
100 static void convert(T i,std::string & str);
101 /// Remove trailing blanks
102 static void trim(std::string & s);
103 /// Remove trailing comments
104 static void trimComments(std::string & s);
105 /// Apply pbc for a unitary cell
106 static double pbc(double);
107 /// Retrieve a key from a vector of options.
108 /// It finds a key starting with "key=" or equal to "key" and copy the
109 /// part after the = on s. E.g.:
110 /// line.push_back("aa=xx");
111 /// getKey(line,"aa",s);
112 /// will set s="xx"
113 static bool getKey(std::vector<std::string>& line,const std::string & key,std::string & s,int rep=-1);
114 /// Find a keyword on the input line, eventually deleting it, and saving its value to val
115 template <class T>
116 static bool parse(std::vector<std::string>&line,const std::string&key,T&val,int rep=-1);
117 /// Find a keyword on the input line, eventually deleting it, and saving its value to a vector
118 template <class T>
119 static bool parseVector(std::vector<std::string>&line,const std::string&key,std::vector<T>&val,int rep=-1);
120 /// Find a keyword without arguments on the input line
121 static bool parseFlag(std::vector<std::string>&line,const std::string&key,bool&val);
122 /// Find a keyword on the input line, just reporting if it exists or not
123 static bool findKeyword(const std::vector<std::string>&line,const std::string&key);
124 /// Interpret atom ranges
125 static void interpretRanges(std::vector<std::string>&);
126 /// Remove duplicates from a vector of type T
127 template <typename T>
128 static void removeDuplicates(std::vector<T>& vec);
129 /// interpret ":" syntax for labels
130 static void interpretLabel(std::vector<std::string>&s);
131 /// list files in a directory
132 static std::vector<std::string> ls(const std::string&);
133 /// removes leading and trailing blanks from a string
134 static void stripLeadingAndTrailingBlanks( std::string& str );
135 /// Extract the extensions from a file name.
136 /// E.g.: extension("pippo.xyz")="xyz".
137 /// It only returns extensions with a length between 1 and 4
138 /// E.g.: extension("pippo.12345")="" whereas extenion("pippo.1234")="1234";
139 /// It is also smart enough to detect "/", so that
140 /// extension("pippo/.t")="" whereas extension("pippo/a.t")="t"
141 static std::string extension(const std::string&);
142 /// Fast int power
143 static double fastpow(double base,int exp);
144 /// Modified 0th-order Bessel function of the first kind
145 static double bessel0(const double& val);
146 /// Check if a string full starts with string start.
147 /// Same as full.find(start)==0
148 static bool startWith(const std::string & full,const std::string &start);
149 /**
150 Tool to create a vector of raw pointers from a vector of unique_pointers (const version).
151 Returning a vector is fast in C++11. It can be used in order to feed a vector<unique_ptr<T>>
152 to a function that takes a vector<T*>.
153 \verbatim
154 // some function that takes a vec
155 void func(std::vector<Data*> & vec);
156 std::vector<std::unique_ptr<Data>> vec;
157 // func(vec); // does not compile
158 func(Tools::unique2raw(vec)); // compiles
159 \endverbatim
160 Notice that the conversion is fast but takes
161 some time to allocate the new vector and copy the pointers. In case the function
162 acting on the vector<T*> is very fast and we do not want to add significant overhead,
163 it might be convenient to store a separate set of raw pointers.
164 \verbatim
165 // some function that takes a vec
166 void func(std::vector<Data*> & vec);
167 std::vector<std::unique_ptr<Data>> vec;
168
169 // conversion done only once:
170 auto vec_ptr=Tools::unique2raw(vec);
171
172 for(int i=0;i<1000;i++){
173 func(vec_ptr);
174 }
175 \endverbatim
176 */
177 template <typename T>
178 static std::vector<T*> unique2raw(const std::vector<std::unique_ptr<T>>&);
179 /// Tool to create a vector of raw pointers from a vector of unique_pointers.
180 /// See the non const version.
181 template <typename T>
182 static std::vector<const T*> unique2raw(const std::vector<std::unique_ptr<const T>>&);
183 /// Tiny class that changes directory and comes back when going out of scope.
184 /// In case system calls to change dir are not available it throws an exception.
185 /// \warning By construction, changing directory breaks thread safety! Use with care.
186 class DirectoryChanger {
187 static const size_t buffersize=4096;
188 char cwd[buffersize]= {0};
189 public:
190 explicit DirectoryChanger(const char*path);
191 ~DirectoryChanger();
192 };
193 };
194
195 template <class T>
parse(std::vector<std::string> & line,const std::string & key,T & val,int rep)196 bool Tools::parse(std::vector<std::string>&line,const std::string&key,T&val,int rep) {
197 std::string s;
198 if(!getKey(line,key+"=",s,rep)) return false;
199 if(s.length()>0 && !convert(s,val))return false;
200 return true;
201 }
202
203 template <class T>
parseVector(std::vector<std::string> & line,const std::string & key,std::vector<T> & val,int rep)204 bool Tools::parseVector(std::vector<std::string>&line,const std::string&key,std::vector<T>&val,int rep) {
205 std::string s;
206 if(!getKey(line,key+"=",s,rep)) return false;
207 val.clear();
208 std::vector<std::string> words=getWords(s,"\t\n ,");
209 for(unsigned i=0; i<words.size(); ++i) {
210 T v;
211 std::string s=words[i];
212 const std::string multi("@replicas:");
213 if(rep>=0 && startWith(s,multi)) {
214 s=s.substr(multi.length(),s.length());
215 std::vector<std::string> words=getWords(s,"\t\n ,");
216 plumed_assert(rep<static_cast<int>(words.size()));
217 s=words[rep];
218 }
219 if(!convert(s,v))return false;
220 val.push_back(v);
221 }
222 return true;
223 }
224
225 template<typename T>
removeDuplicates(std::vector<T> & vec)226 void Tools::removeDuplicates(std::vector<T>& vec)
227 {
228 std::sort(vec.begin(), vec.end());
229 vec.erase(std::unique(vec.begin(), vec.end()), vec.end());
230 }
231
232 inline
parseFlag(std::vector<std::string> & line,const std::string & key,bool & val)233 bool Tools::parseFlag(std::vector<std::string>&line,const std::string&key,bool&val) {
234 for(auto p=line.begin(); p!=line.end(); ++p) {
235 if(key==*p) {
236 val=true;
237 line.erase(p);
238 return true;
239 }
240 }
241 return false;
242 }
243
244 /// beware: this brings any number into a pbc that ranges from -0.5 to 0.5
245 inline
pbc(double x)246 double Tools::pbc(double x) {
247 #ifdef __PLUMED_PBC_WHILE
248 while (x>0.5) x-=1.0;
249 while (x<-0.5) x+=1.0;
250 return x;
251 #else
252 if(std::numeric_limits<int>::round_style == std::round_toward_zero) {
253 const double offset=100.0;
254 const double y=x+offset;
255 if(y>=0) return y-int(y+0.5);
256 else return y-int(y-0.5);
257 } else if(std::numeric_limits<int>::round_style == std::round_to_nearest) {
258 return x-int(x);
259 } else return x-floor(x+0.5);
260 #endif
261 }
262
263 template<typename T>
convert(T i,std::string & str)264 void Tools::convert(T i,std::string & str) {
265 std::ostringstream ostr;
266 ostr<<i;
267 str=ostr.str();
268 }
269
270 inline
fastpow(double base,int exp)271 double Tools::fastpow(double base, int exp)
272 {
273 if(exp<0) {
274 exp=-exp;
275 base=1.0/base;
276 }
277 double result = 1.0;
278 while (exp)
279 {
280 if (exp & 1)
281 result *= base;
282 exp >>= 1;
283 base *= base;
284 }
285
286 return result;
287 }
288
289 template<typename T>
unique2raw(const std::vector<std::unique_ptr<T>> & x)290 std::vector<T*> Tools::unique2raw(const std::vector<std::unique_ptr<T>> & x) {
291 std::vector<T*> v(x.size());
292 for(unsigned i=0; i<x.size(); i++) v[i]=x[i].get();
293 return v;
294 }
295
296 template<typename T>
unique2raw(const std::vector<std::unique_ptr<const T>> & x)297 std::vector<const T*> Tools::unique2raw(const std::vector<std::unique_ptr<const T>> & x) {
298 std::vector<const T*> v(x.size());
299 for(unsigned i=0; i<x.size(); i++) v[i]=x[i].get();
300 return v;
301 }
302
303 }
304
305 #endif
306
307