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