NAMD
eabf2D.C
Go to the documentation of this file.
1 //
2 // The extended adaptive biasing force method has been contributed to NAMD by the following authors:
3 //
4 // Haohao Fu and Christophe Chipot
5 // Laboratoire International Associ\'e
6 // Centre National de la Recherche Scientifique et University of Illinois at Urbana--Champaign
7 // Unit\'e Mixte de Recherche No. 7565, Universit\'e de Lorraine
8 // B.P. 70239, 54506 Vand\oe uvre-lès-Nancy cedex, France
9 //
10 // Copyright 2016, Centre National de la Recherche Scientifique
11 //
12 
13 #ifndef EABF2D_CPP
14 #define EABF2D_CPP
15 
16 #include <cmath>
17 #include <fstream>
18 #include <string>
19 #include <memory>
20 #include <algorithm>
21 #include <iomanip>
22 #include "fstream_namd.h"
23 
24 #include "eabf2D.h"
25 #include "eabffunc.h"
26 
27 // constructor
28 eABF2D::eABF2D(const double _lowerboundary,
29  const double _upperboundary,
30  const double _width,
31  const double _krestr,
32  const double _lowerboundary2,
33  const double _upperboundary2,
34  const double _width2,
35  const double _krestr2,
36  const std::string& _outputfile,
37  const int _outputfreq,
38  const bool _restart,
39  const std::string& _inputfile,
40  const bool _outputgrad,
41  const int _gradfreq,
42  const double _temperature) :
43  eABF(_outputfile, _outputfreq, _restart, _inputfile, _outputgrad, _gradfreq, _temperature)
44 {
45  lowerboundary.push_back(_lowerboundary);
46  lowerboundary.push_back(_lowerboundary2);
47  upperboundary.push_back(_upperboundary);
48  upperboundary.push_back(_upperboundary2);
49  width.push_back(_width);
50  width.push_back(_width2);
51  krestr.push_back(_krestr);
52  krestr.push_back(_krestr2);
53  this->initialize();
54  this->restart = _restart;
55  if(restart == true)
56  this->readfile();
57 }
58 
59 bool eABF2D::initialize()
60 {
61  for (int i = 0; i < 2; i++)
62  {
63  min.push_back(eabffunc::doubletoint(lowerboundary[i] / width[i]) - 10);
64  max.push_back(eabffunc::doubletoint(upperboundary[i] / width[i]) + 10);
65  bins.push_back(max[i] - min[i]);
66  }
67 
68  // initialize the distribution of "countall"
69  // be very careful about it
70  countall = new int*[bins[0] * bins[0]];
71  for (int i = 0; i < bins[0] * bins[0]; i++)
72  {
73  countall[i] = new int[bins[1] * bins[1]];
74  for (int j = 0; j < bins[1] * bins[1]; j++)
75  countall[i][j] = 0;
76  }
77 
78  // initialize other variables
79  for (int i = 0; i < bins[0]; i++)
80  {
81  sumx1.push_back(std::vector<double>(bins[1], 0));
82  sumx21.push_back(std::vector<double>(bins[1], 0));
83  sumx2.push_back(std::vector<double>(bins[1], 0));
84  sumx22.push_back(std::vector<double>(bins[1], 0));
85  county.push_back(std::vector<int>(bins[1], 0));
86  }
87  line = 0;
88 
89  return true;
90 }
91 
92 bool eABF2D::update(const std::string& colvarstring)
93 {
94  // this is the string obtained from colvar each step
95  // the format of this string is the same as those in colvar.traj file
96 
97  std::vector<std::string> data;
98  eabffunc::split(colvarstring, data);
99 
100  int step;
101 
102  double abf_force;
103  double eabf_force;
104  double abf_force2;
105  double eabf_force2;
106 
107  step = eabffunc::chartoint(data[0]);
108  abf_force = eabffunc::chartodouble(data[col[0]]);
109  eabf_force = eabffunc::chartodouble(data[col[1]]);
110  abf_force2 = eabffunc::chartodouble(data[col[2]]);
111  eabf_force2 = eabffunc::chartodouble(data[col[3]]);
112 
113 
114  if (abf_force > 150 && eabf_force < -150)
115  eabf_force += 360;
116  else if (abf_force < -150 && eabf_force > 150)
117  eabf_force -= 360;
118 
119  if (abf_force2 > 150 && eabf_force2 < -150)
120  eabf_force2 += 360;
121  else if (abf_force2 < -150 && eabf_force2 > 150)
122  eabf_force2 -= 360;
123 
124  int binx = int(floor(abf_force / width[0])) - min[0];
125  int biny = int(floor(eabf_force / width[0])) - min[0];
126  int binx2 = int(floor(abf_force2 / width[1])) - min[1];
127  int biny2 = int(floor(eabf_force2 / width[1])) - min[1];
128 
129  if (step%outputfreq == 0)
130  {
131  writefile();
132  }
133 
134  if (outputgrad == true && (step%gradfreq) == 0)
135  {
136  calpmf();
137  }
138 
139 
140  if (binx < 0 || binx >= bins[0] || biny < 0 || biny >= bins[0] || binx2 < 0 || binx2 >= bins[1] || biny2 < 0 || biny2 >= bins[1])
141  return false;
142  else
143  {
144  // distribution
145  countall[binx*bins[0] + biny][binx2*bins[1] + biny2]++;
146 
147  // if this is the first time add "countall", then the line in outputfile will increase
148  if (countall[binx*bins[0] + biny][binx2*bins[1] + biny2] == 1)
149  line++;
150  county[biny][biny2]++;
151  }
152 
153  sumx1[biny][biny2] += abf_force;
154  sumx21[biny][biny2] += abf_force * abf_force;
155  sumx2[biny][biny2] += abf_force2;
156  sumx22[biny][biny2] += abf_force2 * abf_force2;
157 
158 
159  // TODO: add convergence judgement
160  return true;
161 }
162 
163 
164 // WARNGING: do not test whether this function works !!!
165 bool eABF2D::readfile()
166 {
167  std::ifstream file(inputfile.c_str(), std::ios::in);
168 
169  // output file format, the first line is "this->line"
170  int temp_line, temp_bins, temp_bins2;
171  double temp_lowerboundary, temp_width, temp_lowerboundary2, temp_width2;
172  file >> temp_line >> temp_lowerboundary >> temp_width >> temp_bins >> krestr[0] >> temp_lowerboundary2 >> temp_width2 >> temp_bins2 >> krestr[1] >> temperature;
173 
174 
175  temp_bins = temp_bins + 20;
176  temp_bins2 = temp_bins2 + 20;
177 
178  int x = 0, y = 0, m = 0, n = 0;
179  int pos0 = 0, pos1 = 0, temp_countall = 0;
180  for (int i = 0; i < temp_line; i++)
181  {
182  file >> x >> y >> m >> n;
183  //if (x > temp_bins - 10 || x < 10 || y > temp_bins2 - 10 || y < 10)
184  // continue;
185  file >> temp_countall;
186  ;
187  pos0 = convertscale(temp_lowerboundary, x, 1) * bins[0] + convertscale(temp_lowerboundary, y, 1);
188  pos1 = convertscale(temp_lowerboundary2, m, 2) * bins[1] + convertscale(temp_lowerboundary2, n, 2);
189  // find the correct place to increase countall
190  if (countall[pos0][pos1] == 0)
191  line++;
192  countall[pos0][pos1] += temp_countall;
193  }
194 
195  double temp_sumx1, temp_sumx21, temp_sumx2, temp_sumx22;
196  int temp_county;
197  for (int i = 0; i < temp_bins; i++)
198  {
199  for (int j = 0; j < temp_bins2; j++)
200  {
201  file >> x >> y >> temp_sumx1 >> temp_sumx21 >> temp_sumx2 >> temp_sumx22 >> temp_county;
202  //if (x > temp_bins - 10 || x < 10 || y > temp_bins2 - 10 || y < 10)
203  // continue;
204  ;
205  sumx1[convertscale(temp_lowerboundary, x, 1)][convertscale(temp_lowerboundary2, y, 2)] += temp_sumx1;
206  sumx21[convertscale(temp_lowerboundary, x, 1)][convertscale(temp_lowerboundary2, y, 2)] += temp_sumx21;
207  sumx2[convertscale(temp_lowerboundary, x, 1)][convertscale(temp_lowerboundary2, y, 2)] += temp_sumx2;
208  sumx22[convertscale(temp_lowerboundary, x, 1)][convertscale(temp_lowerboundary2, y, 2)] += temp_sumx22;
209  county[convertscale(temp_lowerboundary, x, 1)][convertscale(temp_lowerboundary2, y, 2)] += temp_county;
210  }
211  }
212 
213  file.close();
214  return true;
215 }
216 
217 bool eABF2D::writefile() const
218 {
219  ofstream_namd file(outputfile.c_str(),".old");
220  file<<std::setprecision(15);
221 
222  file << line << " " << lowerboundary[0] << " " << width[0] << " " << bins[0] - 20 << " " << krestr[0] << " ";
223  file << lowerboundary[1] << " " << width[1] << " " << bins[1] - 20 << " " << krestr[1] << " " << temperature << std::endl;
224 
225  for (int i = 0; i < bins[0]; i++)
226  for (int j = 0; j < bins[0]; j++)
227  for (int m = 0; m < bins[1]; m++)
228  for (int n = 0; n < bins[1]; n++)
229  if (countall[i*bins[0] + j][m*bins[1] + n] != 0)
230  // the number of line should be "this->line", I guess :)
231  file << i << " " << j << " " << m << " " << n << " " << countall[i*bins[0] + j][m*bins[1] + n] << std::endl;
232 
233  for (int i = 0; i < bins[0]; i++)
234  for (int j = 0; j < bins[1]; j++)
235  file << i << " " << j << " " << sumx1[i][j] << " " << sumx21[i][j] << " " << sumx2[i][j] << " " << sumx22[i][j] << " " << county[i][j] << " " << std::endl;
236 
237  file.close();
238  return true;
239 }
240 
241 
242 //bool eABF2D::writecount(ofstream_namd& os) const
243 //{
244 // double x1,x2;
245 // writehead(os);
246 // for(int binx=0; binx<bins; binx++)
247 // {
248 // x1 = (binx + _min + 0.5) * width;
249 // for(int binx2=0; binx2<bins2; binx2++)
250 // {
251 // x2 = (binx2 + _min2 + 0.5) * width2;
252 // if(x1>=lowerboundary && x1<upperboundary && x2>=lowerboundary2 && x2<upperboundary2)
253 // os<<x1<<" "<<x2<<" "<<county[binx][binx2]<<std::endl;
254 // }
255 // }
256 // return true;
257 //}
258 
259 bool eABF2D::writehead(ofstream_namd& os) const
260 {
261  os<<"# 2"<<std::endl;
262  // the "real" bin numbers is "bins - 20"
263  os << "# " << lowerboundary[0] << " " << width[0] << " " << (bins[0] - 20) << " " << 0 << std::endl;
264  os << "# " << lowerboundary[1] << " " << width[1] << " " << (bins[1] - 20) << " " << 0 << std::endl;
265  os<<std::endl;
266  return true;
267 }
268 
269 bool eABF2D::calpmf() const
270 {
271  // double integration
272  // this is just a conversion from Chipot's script
273  int norm;
274  std::vector<std::vector<double> > x_av(bins[0]);
275  std::vector<std::vector<double> > x_av2(bins[0]);
276  std::vector<std::vector<double> > sigma21(bins[0]);
277  std::vector<std::vector<double> > sigma22(bins[0]);
278  for (int i = 0; i < bins[0]; i++)
279  {
280  x_av[i] = (std::vector<double>(bins[1], 0));
281  x_av2[i] = (std::vector<double>(bins[1], 0));
282  sigma21[i] = (std::vector<double>(bins[1], 0));
283  sigma22[i] = (std::vector<double>(bins[1], 0));
284  }
285  for (int biny = 0; biny < bins[0]; biny++)
286  {
287  for (int biny2 = 0; biny2 < bins[1]; biny2++)
288  {
289  norm = county[biny][biny2] > 0 ? county[biny][biny2] : 1;
290  x_av[biny][biny2] = sumx1[biny][biny2] / norm;
291  x_av2[biny][biny2] = sumx2[biny][biny2] / norm;
292  sigma21[biny][biny2] = sumx21[biny][biny2] / norm - x_av[biny][biny2] * x_av[biny][biny2];
293  sigma22[biny][biny2] = sumx22[biny][biny2] / norm - x_av2[biny][biny2] * x_av2[biny][biny2];
294  }
295 
296  }
297 
298  static std::string gridfilename = outputfile + ".grad";
299  static std::string histfilename = outputfile + ".hist.grad";
300  static std::string countfilename = outputfile + ".count";
301  //static std::string pmffilename = outputfile + ".pmf";
302 
303  ofstream_namd ofile(gridfilename.c_str(),".old");
304  ofstream_namd ofile_hist(histfilename.c_str(), std::ios::app);
305  ofstream_namd ofile_count(countfilename.c_str(),".old");
306 
307  writehead(ofile);
308  writehead(ofile_hist);
309  writehead(ofile_count);
310  //writecount(ofile_count);
311  //ofstream_namd ofile_pmf(pmffilename.c_str(),".old");
312 
313  //ofile_pmf<<lowerboundary<<" 0.0"<<std::endl;
314 
315  //double pmf = 0, pmf_x = 0;
316  double x1, x2, y1, y2, av1, av2, diff_av1, diff_av2, grad1, grad2;
317  for (int binx = 0; binx < bins[0]; binx++)
318  {
319  x1 = (binx + min[0] + 0.5) * width[0];
320  for (int binx2 = 0; binx2 < bins[1]; binx2++)
321  {
322  x2 = (binx2 + min[1] + 0.5) * width[1];
323  norm = 0;
324  av1 = 0;
325  av2 = 0;
326  diff_av1 = 0;
327  diff_av2 = 0;
328 
329  for (int biny = 0; biny < bins[0]; biny++)
330  {
331  y1 = (biny + min[0] + 0.5) * width[0];
332  for (int biny2 = 0; biny2 < bins[1]; biny2++)
333  {
334  y2 = (biny2 + min[1] + 0.5) * width[1];
335  norm += countall[binx * bins[0] + biny][binx2 * bins[1] + biny2];
336 
337  if (sigma21[biny][biny2]>0.00001 || sigma21[biny][biny2] < -0.00001)
338  {
339  av1 += countall[binx * bins[0] + biny][binx2 * bins[1] + biny2] * (x1 - x_av[biny][biny2]) / sigma21[biny][biny2];
340  }
341  else if (countall[binx * bins[0] + biny][binx2 * bins[1] + biny2] > 1)
342  {
343  // TODOC:\Users\ChinaFu\eabf\eabf2d.cpp|165|error: passing 'const eABF2D' as 'this' argument of 'int eABF2D::position(int, int, int, int)' discards qualifiers [-fpermissive]|, print error
344  }
345  diff_av1 += countall[binx * bins[0] + biny][binx2 * bins[1] + biny2] * (x1 - y1);
346 
347  if (sigma22[biny][biny2]>0.00001 || sigma22[biny][biny2] < -0.00001)
348  {
349  av2 += countall[binx * bins[0] + biny][binx2 * bins[1] + biny2] * (x2 - x_av2[biny][biny2]) / sigma22[biny][biny2];
350  }
351  else if (countall[binx * bins[0] + biny][binx2 * bins[1] + biny2] > 1)
352  {
353  // TODO, print error
354  }
355 
356  diff_av2 += countall[binx * bins[0] + biny][binx2 * bins[1] + biny2] * (x2 - y2);
357  }
358  }
359 
360  diff_av1 /= (norm > 0 ? norm : 1);
361  diff_av2 /= (norm > 0 ? norm : 1);
362 
363  av1 = eabffunc::BOLTZMANN * temperature * av1 / (norm > 0 ? norm : 1);
364  av2 = eabffunc::BOLTZMANN * temperature * av2 / (norm > 0 ? norm : 1);
365 
366  grad1 = av1 - krestr[0] * diff_av1;
367  grad2 = av2 - krestr[1] * diff_av2;
368 
369  if (x1 >= lowerboundary[0] && x1 < upperboundary[0] && x2 >= lowerboundary[1] && x2 < upperboundary[1])
370  {
371  ofile << x1 << " " << x2 << " " << grad1 << " " << grad2 << std::endl;
372  ofile_hist << x1 << " " << x2 << " " << grad1 << " " << grad2 << std::endl;
373  ofile_count << x1 << " " << x2 << " " << norm << std::endl;
374  //pmf += grad * width;
375  //pmf_x = x + 0.5 * width;
376  //ofile_pmf<<pmf_x<<" "<<pmf<<std::endl;
377  // TODO, rescale the pmf file to prevent negetive free energy
378  }
379  }
380  if (x1 > lowerboundary[0] && x1 < upperboundary[0])
381  {
382  ofile << std::endl;
383  ofile_count << std::endl;
384  }
385  }
386  ofile.close();
387  ofile_hist.close();
388  ofile_count.close();
389  //ofile_pmf.close();
390  return true;
391 }
392 
393 #endif // EABF2D
std::string inputfile
Definition: eabf.h:76
std::vector< double > lowerboundary
Definition: eabf.h:61
std::vector< double > width
Definition: eabf.h:63
Definition: eabf.h:22
double temperature
Definition: eabf.h:85
int line
Definition: eabf.h:102
std::vector< double > krestr
Definition: eabf.h:93
int chartoint(const std::string &c)
Definition: eabffunc.C:48
int gradfreq
Definition: eabf.h:82
bool outputgrad
Definition: eabf.h:79
double chartodouble(const std::string &c)
Definition: eabffunc.C:57
eABF2D(const double _lowerboundary, const double _upperboundary, const double _width, const double _krestr, const double _lowerboundary2, const double _upperboundary2, const double _width2, const double _krestr2, const std::string &_outputfile, const int _outputfreq, const bool _restart, const std::string &_inputfile, const bool _outputgrad, const int _gradfreq, const double _temperature)
Definition: eabf2D.C:28
std::vector< int > bins
Definition: eabf.h:91
void split(const std::string &s, std::vector< std::string > &ret)
Definition: eabffunc.C:37
gridSize y
std::vector< int > max
Definition: eabf.h:89
std::string outputfile
Definition: eabf.h:67
int outputfreq
Definition: eabf.h:70
gridSize x
std::vector< int > min
Definition: eabf.h:90
std::vector< double > upperboundary
Definition: eabf.h:62
bool update(const std::string &)
Definition: eabf2D.C:92
bool restart
Definition: eabf.h:73
std::vector< int > col
Definition: eabf.h:104
int doubletoint(const double)
Definition: eabffunc.C:66
const double BOLTZMANN
Definition: eabffunc.h:23