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 <cstdio>
29 : #include <cmath>
30 : #include <limits>
31 : #include <algorithm>
32 : #include <sstream>
33 :
34 : namespace PLMD {
35 :
36 : class IFile;
37 :
38 : /// \ingroup TOOLBOX
39 : /// Very small non-zero number
40 : const double epsilon(std::numeric_limits<double>::epsilon());
41 :
42 : /// \ingroup TOOLBOX
43 : /// Boltzman constant in kj/K
44 : const double kBoltzmann(0.0083144621);
45 :
46 : /// \ingroup TOOLBOX
47 : /// PI
48 : const double pi(3.141592653589793238462643383279502884197169399375105820974944592307);
49 :
50 : /// \ingroup TOOLBOX
51 : /// Empty class which just contains several (static) tools
52 : class Tools {
53 : /// class to convert a string to a generic type T
54 : template<class T>
55 : static bool convertToAny(const std::string & str,T &t);
56 : /// class to convert a string to a real type T.
57 : /// T should be either float, double, or long double
58 : template<class T>
59 : static bool convertToReal(const std::string & str,T &t);
60 : public:
61 : /// Split the line in words using separators.
62 : /// It also take into account parenthesis. Outer parenthesis found are removed from
63 : /// output, and the text between them is considered as a single word. Only the
64 : /// outer parenthesis are processed, to allow nesting them.
65 : /// parlevel, if not NULL, is increased or decreased according to the number of opened/closed parenthesis
66 : static std::vector<std::string> getWords(const std::string & line,const char* sep=NULL,int* parlevel=NULL,const char* parenthesis="{");
67 : /// Get a line from the file pointer ifile
68 : static bool getline(FILE*,std::string & line);
69 : /// Get a parsed line from the file pointer ifile
70 : /// This function already takes care of joining continued lines and splitting the
71 : /// resulting line into an array of words
72 : static bool getParsedLine(IFile&ifile,std::vector<std::string> & line);
73 : /// Convert a string to a double, reading it
74 : static bool convert(const std::string & str,double & t);
75 : /// Convert a string to a long double, reading it
76 : static bool convert(const std::string & str,long double & t);
77 : /// Convert a string to a float, reading it
78 : static bool convert(const std::string & str,float & t);
79 : /// Convert a string to a int, reading it
80 : static bool convert(const std::string & str,int & t);
81 : /// Convert a string to a long int, reading it
82 : static bool convert(const std::string & str,long int & t);
83 : /// Convert a string to an unsigned int, reading it
84 : static bool convert(const std::string & str,unsigned & t);
85 : /// Convert a string to a atom number, reading it
86 : static bool convert(const std::string & str,AtomNumber & t);
87 : /// Convert a string to a string (i.e. copy)
88 : static bool convert(const std::string & str,std::string & t);
89 : /// Convert anything into a string
90 : template<typename T>
91 : static void convert(T i,std::string & str);
92 : /// Remove trailing blanks
93 : static void trim(std::string & s);
94 : /// Remove trailing comments
95 : static void trimComments(std::string & s);
96 : /// Apply pbc for a unitary cell
97 : static double pbc(double);
98 : /// Retrieve a key from a vector of options.
99 : /// It finds a key starting with "key=" or equal to "key" and copy the
100 : /// part after the = on s. E.g.:
101 : /// line.push_back("aa=xx");
102 : /// getKey(line,"aa",s);
103 : /// will set s="xx"
104 : static bool getKey(std::vector<std::string>& line,const std::string & key,std::string & s,int rep=-1);
105 : /// Find a keyword on the input line, eventually deleting it, and saving its value to val
106 : template <class T>
107 : static bool parse(std::vector<std::string>&line,const std::string&key,T&val,int rep=-1);
108 : /// Find a keyword on the input line, eventually deleting it, and saving its value to a vector
109 : template <class T>
110 : static bool parseVector(std::vector<std::string>&line,const std::string&key,std::vector<T>&val,int rep=-1);
111 : /// Find a keyword without arguments on the input line
112 : static bool parseFlag(std::vector<std::string>&line,const std::string&key,bool&val);
113 : /// Find a keyword on the input line, just reporting if it exists or not
114 : static bool findKeyword(const std::vector<std::string>&line,const std::string&key);
115 : /// Interpret atom ranges
116 : static void interpretRanges(std::vector<std::string>&);
117 : /// Remove duplicates from a vector of type T
118 : template <typename T>
119 : static void removeDuplicates(std::vector<T>& vec);
120 : /// interpret ":" syntax for labels
121 : static void interpretLabel(std::vector<std::string>&s);
122 : /// list files in a directory
123 : static std::vector<std::string> ls(const std::string&);
124 : /// removes leading and trailing blanks from a string
125 : static void stripLeadingAndTrailingBlanks( std::string& str );
126 : /// Extract the extensions from a file name.
127 : /// E.g.: extension("pippo.xyz")="xyz".
128 : /// It only returns extensions with a length between 1 and 4
129 : /// E.g.: extension("pippo.12345")="" whereas extenion("pippo.1234")="1234";
130 : /// It is also smart enough to detect "/", so that
131 : /// extension("pippo/.t")="" whereas extension("pippo/a.t")="t"
132 : static std::string extension(const std::string&);
133 : /// Fast int power
134 : static double fastpow(double base,int exp);
135 : /// Check if a string full starts with string start.
136 : /// Same as full.find(start)==0
137 : static bool startWith(const std::string & full,const std::string &start);
138 : };
139 :
140 : template <class T>
141 37002 : bool Tools::parse(std::vector<std::string>&line,const std::string&key,T&val,int rep) {
142 : std::string s;
143 74004 : if(!getKey(line,key+"=",s,rep)) return false;
144 15880 : if(s.length()>0 && !convert(s,val))return false;
145 : return true;
146 : }
147 :
148 : template <class T>
149 15079 : bool Tools::parseVector(std::vector<std::string>&line,const std::string&key,std::vector<T>&val,int rep) {
150 : std::string s;
151 30158 : if(!getKey(line,key+"=",s,rep)) return false;
152 : // if(s.length()==0) return true;
153 7088 : val.clear();
154 18308 : std::vector<std::string> words=getWords(s,"\t\n ,");
155 72929 : for(unsigned i=0; i<words.size(); ++i) {
156 : T v;
157 : std::string s=words[i];
158 18207 : const std::string multi("@replicas:");
159 18207 : if(rep>=0 && startWith(s,multi)) {
160 12 : s=s.substr(multi.length(),s.length());
161 12 : std::vector<std::string> words=getWords(s,"\t\n ,");
162 6 : plumed_assert(rep<static_cast<int>(words.size()));
163 6 : s=words[rep];
164 : }
165 18207 : if(!convert(s,v))return false;
166 18207 : val.push_back(v);
167 : }
168 : return true;
169 : }
170 :
171 : template<typename T>
172 146 : void Tools::removeDuplicates(std::vector<T>& vec)
173 : {
174 : std::sort(vec.begin(), vec.end());
175 : vec.erase(std::unique(vec.begin(), vec.end()), vec.end());
176 146 : }
177 :
178 : inline
179 15509 : bool Tools::parseFlag(std::vector<std::string>&line,const std::string&key,bool&val) {
180 58636 : for(auto p=line.begin(); p!=line.end(); ++p) {
181 44106 : if(key==*p) {
182 979 : val=true;
183 : line.erase(p);
184 : return true;
185 : }
186 : }
187 : return false;
188 : }
189 :
190 : /// beware: this brings any number into a pbc that ranges from -0.5 to 0.5
191 : inline
192 : double Tools::pbc(double x) {
193 : #ifdef __PLUMED_PBC_WHILE
194 : while (x>0.5) x-=1.0;
195 : while (x<-0.5) x+=1.0;
196 : return x;
197 : #else
198 : if(std::numeric_limits<int>::round_style == std::round_toward_zero) {
199 : const double offset=100.0;
200 1669609349 : const double y=x+offset;
201 1669609349 : if(y>=0) return y-int(y+0.5);
202 2187 : else return y-int(y-0.5);
203 : } else if(std::numeric_limits<int>::round_style == std::round_to_nearest) {
204 : return x-int(x);
205 : } else return x-floor(x+0.5);
206 : #endif
207 : }
208 :
209 : template<typename T>
210 219372 : void Tools::convert(T i,std::string & str) {
211 438744 : std::ostringstream ostr;
212 160710 : ostr<<i;
213 438744 : str=ostr.str();
214 219372 : }
215 :
216 : inline
217 : double Tools::fastpow(double base, int exp)
218 : {
219 12074854 : if(exp<0) {
220 0 : exp=-exp;
221 0 : base=1.0/base;
222 : }
223 : double result = 1.0;
224 42205266 : while (exp)
225 : {
226 30130412 : if (exp & 1)
227 18104622 : result *= base;
228 30130412 : exp >>= 1;
229 30130412 : base *= base;
230 : }
231 :
232 : return result;
233 : }
234 :
235 : }
236 :
237 : #endif
238 :
|