Line data Source code
1 : /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 : Copyright (c) 2017 of Haochuan Chen (excluding colvar_UIestimator.h)
3 : Copyright (c) 2017 of Haohao Fu (colvar_UIestimator.h)
4 :
5 : This program is free software: you can redistribute it and/or modify
6 : it under the terms of the GNU Lesser General Public License as published
7 : by the Free Software Foundation, either version 3 of the License, or
8 : (at your option) any later version.
9 :
10 : This program is distributed in the hope that it will be useful,
11 : but WITHOUT ANY WARRANTY; without even the implied warranty of
12 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 : GNU Lesser General Public License for more details.
14 :
15 : You should have received a copy of the GNU Lesser General Public License
16 : along with this program. If not, see <http://www.gnu.org/licenses/>.
17 : +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
18 : #ifndef __PLUMED_drr_colvar_UIestimator_h
19 : #define __PLUMED_drr_colvar_UIestimator_h
20 : // The original code(https://github.com/fhh2626/colvars/blob/master/src/colvar_UIestimator.h) has been modified by Haochuan Chen.
21 : // Modifications:
22 : // 1. Disable colvars related code.
23 : // 2. Change boltzmann constant.
24 : // 3. Change output precision.
25 : // I(Haochuan Chen) don't know how to maintain this code and how it runs. If you are interested in it, please contact Haohao Fu.
26 :
27 : #include <cmath>
28 : #include <vector>
29 : #include <fstream>
30 : #include <string>
31 : #include <iomanip>
32 : #include <limits>
33 :
34 : #include <typeinfo>
35 :
36 : // only for colvar module!
37 : // when integrated into other code, just remove this line and "...cvm::backup_file(...)"
38 : // #include "colvarmodule.h"
39 :
40 : namespace PLMD {
41 : namespace drr {
42 :
43 : namespace UIestimator
44 : {
45 : const int Y_SIZE = 21;
46 : const int HALF_Y_SIZE = 10;
47 : const double BOLTZMANN = 0.0083144621;
48 : const int EXTENDED_X_SIZE = HALF_Y_SIZE;
49 :
50 68 : class n_matrix // spare matrix, stores the distribution matrix of n(x,y)
51 : {
52 : public:
53 8 : n_matrix() {}
54 4 : n_matrix(const std::vector<double> & lowerboundary_p, // lowerboundary of x
55 : const std::vector<double> & upperboundary_p, // upperboundary of
56 : const std::vector<double> & width_p, // width of x
57 : const int y_size) // size of y, for example, ysize=7, then when x=1, the distribution of y in [-2,4] is considered
58 12 : : lowerboundary(lowerboundary_p), upperboundary(upperboundary_p), width(width_p)
59 : {
60 4 : this->dimension = lowerboundary.size();
61 4 : this->y_size = y_size; // keep in mind the internal (spare) matrix is stored in diagonal form
62 4 : this->y_total_size = int(pow(y_size, dimension) + 0.000001);
63 :
64 : // the range of the matrix is [lowerboundary, upperboundary]
65 4 : x_total_size = 1;
66 16 : for (int i = 0; i < dimension; i++)
67 : {
68 30 : x_size.push_back(int((upperboundary[i] - lowerboundary[i]) / width[i] + 0.000001));
69 6 : x_total_size *= x_size[i];
70 : }
71 :
72 : // initialize the internal matrix
73 4 : matrix.reserve(x_total_size);
74 68 : for (int i = 0; i < x_total_size; i++)
75 : {
76 64 : matrix.push_back(std::vector<int>(y_total_size, 0));
77 : }
78 :
79 4 : temp.resize(dimension);
80 4 : }
81 :
82 45034 : int inline get_value(const std::vector<double> & x, const std::vector<double> & y)
83 : {
84 : //if (matrix[convert_x(x)][convert_y(x, y)]!=0)
85 : //{
86 : //std::cout<<convert_x(x)<<" "<<convert_y(x, y)<<" "<<x[0]<<" "<<x[1]<<" "<<y[0]<<" "<<y[1]<<" ";
87 : //std::cout<<matrix[convert_x(x)][convert_y(x, y)]<<"sadasfdasaaaaaaaa"<<std::endl;
88 : //}
89 90068 : return matrix[convert_x(x)][convert_y(x, y)];
90 : }
91 :
92 : void inline set_value(const std::vector<double> & x, const std::vector<double> & y, const int value)
93 : {
94 : matrix[convert_x(x)][convert_y(x,y)] = value;
95 : }
96 :
97 34 : void inline increase_value(const std::vector<double> & x, const std::vector<double> & y, const int value)
98 : {
99 68 : matrix[convert_x(x)][convert_y(x,y)] += value;
100 34 : }
101 :
102 : private:
103 : std::vector<double> lowerboundary;
104 : std::vector<double> upperboundary;
105 : std::vector<double> width;
106 : int dimension;
107 : std::vector<int> x_size; // the size of x in each dimension
108 : int x_total_size; // the size of x of the internal matrix
109 : int y_size; // the size of y in each dimension
110 : int y_total_size; // the size of y of the internal matrix
111 :
112 : std::vector<std::vector<int> > matrix; // the internal matrix
113 :
114 : std::vector<int> temp; // this vector is used in convert_x and convert_y to save computational resource
115 :
116 45068 : int convert_x(const std::vector<double> & x) // convert real x value to its interal index
117 : {
118 221904 : for (int i = 0; i < dimension; i++)
119 : {
120 442090 : temp[i] = int((x[i] - lowerboundary[i]) / width[i] + 0.000001);
121 : }
122 :
123 : int index = 0;
124 133486 : for (int i = 0; i < dimension; i++)
125 : {
126 88418 : if (i + 1 < dimension)
127 : {
128 : int x_temp = 1;
129 130050 : for (int j = i + 1; j < dimension; j++)
130 86700 : x_temp *= x_size[j];
131 86700 : index += temp[i] * x_temp;
132 : }
133 : else
134 90136 : index += temp[i];
135 : }
136 45068 : return index;
137 : }
138 :
139 45068 : int convert_y(const std::vector<double> & x, const std::vector<double> & y) // convert real y value to its interal index
140 : {
141 221904 : for (int i = 0; i < dimension; i++)
142 : {
143 442090 : temp[i] = round((round(y[i] / width[i] + 0.000001) - round(x[i] / width[i] + 0.000001)) + (y_size - 1) / 2 + 0.000001);
144 : }
145 :
146 : int index = 0;
147 133486 : for (int i = 0; i < dimension; i++)
148 : {
149 88418 : if (i + 1 < dimension)
150 86700 : index += temp[i] * int(pow(y_size, dimension - i - 1) + 0.000001);
151 : else
152 90136 : index += temp[i];
153 : }
154 45068 : return index;
155 : }
156 :
157 265254 : double round(double r)
158 : {
159 265254 : return (r > 0.0) ? floor(r + 0.5) : ceil(r - 0.5);
160 : }
161 : };
162 :
163 : // vector, store the sum_x, sum_x_square, count_y
164 : template <typename T>
165 597 : class n_vector
166 : {
167 : public:
168 48 : n_vector() {}
169 40 : n_vector(const std::vector<double> & lowerboundary, // lowerboundary of x
170 : const std::vector<double> & upperboundary, // upperboundary of
171 : const std::vector<double> & width_p, // width of x
172 : const int y_size, // size of y, for example, ysize=7, then when x=1, the distribution of y in [-2,4] is considered
173 : const T & default_value) // the default value of T
174 200 : :width(width_p)
175 : {
176 40 : this->dimension = lowerboundary.size();
177 :
178 40 : x_total_size = 1;
179 168 : for (int i = 0; i < dimension; i++)
180 : {
181 256 : this->lowerboundary.push_back(lowerboundary[i] - (y_size - 1) / 2 * width[i] - 0.000001);
182 192 : this->upperboundary.push_back(upperboundary[i] + (y_size - 1) / 2 * width[i] + 0.000001);
183 :
184 256 : x_size.push_back(int((this->upperboundary[i] - this->lowerboundary[i]) / this->width[i] + 0.000001));
185 64 : x_total_size *= x_size[i];
186 : }
187 :
188 : // initialize the internal vector
189 40 : vector.resize(x_total_size, default_value);
190 :
191 40 : temp.resize(dimension);
192 40 : }
193 :
194 258 : const T inline get_value(const std::vector<double> & x)
195 : {
196 159900 : return vector[convert_x(x)];
197 : }
198 :
199 100 : void inline set_value(const std::vector<double> & x, const T & value)
200 : {
201 18142 : vector[convert_x(x)] = value;
202 100 : }
203 :
204 : void inline increase_value(const std::vector<double> & x, const T & value)
205 : {
206 308 : vector[convert_x(x)] += value;
207 : }
208 : private:
209 : std::vector<double> lowerboundary;
210 : std::vector<double> upperboundary;
211 : std::vector<double> width;
212 : int dimension;
213 : std::vector<int> x_size; // the size of x in each dimension
214 : int x_total_size; // the size of x of the internal matrix
215 :
216 : std::vector<T> vector; // the internal vector
217 :
218 : std::vector<int> temp; // this vector is used in convert_x and convert_y to save computational resource
219 :
220 89175 : int convert_x(const std::vector<double> & x) // convert real x value to its interal index
221 : {
222 439151 : for (int i = 0; i < dimension; i++)
223 : {
224 874940 : temp[i] = int((x[i] - lowerboundary[i]) / width[i] + 0.000001);
225 : }
226 :
227 : int index = 0;
228 264163 : for (int i = 0; i < dimension; i++)
229 : {
230 174988 : if (i + 1 < dimension)
231 : {
232 : int x_temp = 1;
233 257439 : for (int j = i + 1; j < dimension; j++)
234 171626 : x_temp *= x_size[j];
235 171626 : index += temp[i] * x_temp;
236 : }
237 : else
238 178350 : index += temp[i];
239 : }
240 89175 : return index;
241 : }
242 : };
243 :
244 8 : class UIestimator // the implemension of UI estimator
245 : {
246 : public:
247 8 : UIestimator() {}
248 :
249 : //called when (re)start an eabf simulation
250 4 : UIestimator(const std::vector<double>& lowerboundary_p,
251 : const std::vector<double>& upperboundary_p,
252 : const std::vector<double>& width_p,
253 : const std::vector<double>& krestr_p, // force constant in eABF
254 : const std::string& output_filename_p, // the prefix of output files
255 : const int output_freq_p,
256 : const bool restart_p, // whether restart from a .count and a .grad file
257 : const std::vector<std::string>& input_filename_p, // the prefixes of input files
258 : const double temperature_p)
259 4 : : lowerboundary(lowerboundary_p), upperboundary(upperboundary_p),
260 : width(width_p), krestr(krestr_p),
261 : output_filename(output_filename_p), output_freq(output_freq_p),
262 : restart(restart_p), input_filename(input_filename_p),
263 48 : temperature(temperature_p)
264 : {
265 :
266 4 : dimension = lowerboundary.size();
267 :
268 16 : for (int i = 0; i < dimension; i++)
269 : {
270 12 : sum_x.push_back(n_vector<double>(lowerboundary, upperboundary, width, Y_SIZE, 0.0));
271 12 : sum_x_square.push_back(n_vector<double>(lowerboundary, upperboundary, width, Y_SIZE, 0.0));
272 :
273 12 : x_av.push_back(n_vector<double>(lowerboundary, upperboundary, width, Y_SIZE, 0.0));
274 12 : sigma_square.push_back(n_vector<double>(lowerboundary, upperboundary, width, Y_SIZE, 0.0));
275 : }
276 :
277 4 : count_y = n_vector<int>(lowerboundary, upperboundary, width, Y_SIZE, 0);
278 4 : distribution_x_y = n_matrix(lowerboundary, upperboundary, width, Y_SIZE);
279 :
280 8 : grad = n_vector<std::vector<double> >(lowerboundary, upperboundary, width, 1, std::vector<double>(dimension, 0.0));
281 4 : count = n_vector<int>(lowerboundary, upperboundary, width, 1, 0);
282 :
283 4 : written = false;
284 4 : written_1D = false;
285 :
286 4 : if (dimension == 1)
287 : {
288 2 : std::vector<double> upperboundary_temp = upperboundary;
289 6 : upperboundary_temp[0] = upperboundary[0] + width[0];
290 2 : oneD_pmf = n_vector<double>(lowerboundary, upperboundary_temp, width, 1, 0.0);
291 : }
292 :
293 4 : if (restart == true)
294 : {
295 2 : input_grad = n_vector<std::vector<double> >(lowerboundary, upperboundary, width, 1, std::vector<double>(dimension, 0.0));
296 1 : input_count = n_vector<int>(lowerboundary, upperboundary, width, 1, 0);
297 :
298 : // initialize input_Grad and input_count
299 1 : std::vector<double> loop_flag(dimension, 0);
300 5 : for (int i = 0; i < dimension; i++)
301 : {
302 4 : loop_flag[i] = lowerboundary[i];
303 : }
304 : while (true)
305 : {
306 45 : for (int i = 0; i < dimension; i++)
307 : {
308 36 : input_grad.set_value(loop_flag, std::vector<double>(dimension,0));
309 : }
310 : input_count.set_value(loop_flag, 0);
311 :
312 : // iterate over any dimensions
313 9 : int i = dimension - 1;
314 : while (true)
315 : {
316 36 : loop_flag[i] += width[i];
317 36 : if (loop_flag[i] > upperboundary[i] - width[i] + 0.00001)
318 : {
319 4 : loop_flag[i] = lowerboundary[i];
320 4 : i--;
321 4 : if (i < 0)
322 : goto INITIAL_LOOPEND;
323 : }
324 : else
325 : break;
326 : }
327 : }
328 1 : INITIAL_LOOPEND:
329 1 : read_inputfiles(input_filename);
330 : }
331 4 : }
332 :
333 16 : ~UIestimator() {}
334 :
335 : // called from MD engine every step
336 34 : bool update(const int step, std::vector<double> x, std::vector<double> y)
337 : {
338 :
339 : //std::cout<<"weeeee: :"<<std::endl;
340 : //for (int i = 0; i < dimension; i++)
341 : //{
342 : // std::cout<<x[i]<<" "<<y[i]<<" ";
343 : //}
344 : //std::cout<<std::endl;
345 :
346 34 : if (step % output_freq == 0)
347 : {
348 10 : calc_pmf();
349 10 : write_files();
350 : //write_interal_data();
351 : }
352 :
353 150 : for (int i = 0; i < dimension; i++)
354 : {
355 : // for dihedral RC, it is possible that x = 179 and y = -179, should correct it
356 : // may have problem, need to fix
357 116 : if (x[i] > 150 && y[i] < -150)
358 : {
359 : //std::vector<double> x_temp(x);
360 : //x_temp[i] -= 360;
361 : //update(7, x_temp, y);
362 0 : y[i] += 360;
363 : }
364 58 : if (x[i] < -150 && y[i] > 150)
365 : {
366 : //std::vector<double> x_temp(x);
367 : //x_temp[i] += 360;
368 : //update(7, x_temp, y);
369 0 : y[i] -= 360;
370 : }
371 :
372 232 : if (x[i] < lowerboundary[i] - EXTENDED_X_SIZE * width[i] + 0.00001 || x[i] > upperboundary[i] + EXTENDED_X_SIZE * width[i] - 0.00001 \
373 58 : || y[i] - x[i] < -HALF_Y_SIZE * width[i] + 0.00001 || y[i] - x[i] > HALF_Y_SIZE * width[i] - 0.00001 \
374 116 : || y[i] - lowerboundary[i] < -HALF_Y_SIZE * width[i] + 0.00001 || y[i] - upperboundary[i] > HALF_Y_SIZE * width[i] - 0.00001)
375 : return false;
376 : }
377 :
378 : //for (int i = 0; i < dimension; i++)
379 : //{
380 : // std::cout<<x[i]<<" "<<y[i]<<" ";
381 : //}
382 : //std::cout<<std::endl;
383 :
384 150 : for (int i = 0; i < dimension; i++)
385 : {
386 58 : sum_x[i].increase_value(y, x[i]);
387 58 : sum_x_square[i].increase_value(y, x[i] * x[i]);
388 : }
389 34 : count_y.increase_value(y, 1);
390 :
391 150 : for (int i = 0; i < dimension; i++)
392 : {
393 : //if (x[i] < lowerboundary[i] + 0.000001 || x[i] > upperboundary[i] - 0.000001)
394 : // adapt colvars precision
395 232 : if (x[i] < lowerboundary[i] + 0.00001 || x[i] > upperboundary[i] - 0.00001)
396 : return false;
397 : }
398 34 : distribution_x_y.increase_value(x, y, 1);
399 :
400 34 : return true;
401 : }
402 :
403 : // update the output_filename
404 : void update_output_filename(const std::string& filename)
405 : {
406 34 : output_filename = filename;
407 : }
408 :
409 : private:
410 : std::vector<n_vector<double> > sum_x; // the sum of x in each y bin
411 : std::vector<n_vector<double> > sum_x_square; // the sum of x in each y bin
412 : n_vector<int> count_y; // the distribution of y
413 : n_matrix distribution_x_y; // the distribution of <x, y> pair
414 :
415 : int dimension;
416 :
417 : std::vector<double> lowerboundary;
418 : std::vector<double> upperboundary;
419 : std::vector<double> width;
420 : std::vector<double> krestr;
421 : std::string output_filename;
422 : int output_freq;
423 : bool restart;
424 : std::vector<std::string> input_filename;
425 : double temperature;
426 :
427 : n_vector<std::vector<double> > grad;
428 : n_vector<int> count;
429 :
430 : n_vector<double> oneD_pmf;
431 :
432 : n_vector<std::vector<double> > input_grad;
433 : n_vector<int> input_count;
434 :
435 : // used in double integration
436 : std::vector<n_vector<double> > x_av;
437 : std::vector<n_vector<double> > sigma_square;
438 :
439 : bool written;
440 : bool written_1D;
441 :
442 : // calculate gradients from the internal variables
443 10 : void calc_pmf()
444 : {
445 : int norm;
446 :
447 10 : std::vector<double> loop_flag(dimension, 0);
448 38 : for (int i = 0; i < dimension; i++)
449 : {
450 56 : loop_flag[i] = lowerboundary[i] - HALF_Y_SIZE * width[i];
451 : }
452 :
453 : while (true)
454 : {
455 4556 : norm = count_y.get_value(loop_flag) > 0 ? count_y.get_value(loop_flag) : 1;
456 11066 : for (int i = 0; i < dimension; i++)
457 : {
458 8788 : x_av[i].set_value(loop_flag, sum_x[i].get_value(loop_flag) / norm);
459 8788 : sigma_square[i].set_value(loop_flag, sum_x_square[i].get_value(loop_flag) / norm - x_av[i].get_value(loop_flag) * x_av[i].get_value(loop_flag));
460 : }
461 :
462 : // iterate over any dimensions
463 2278 : int i = dimension - 1;
464 : while (true)
465 : {
466 7110 : loop_flag[i] += width[i];
467 7110 : if (loop_flag[i] > upperboundary[i] + HALF_Y_SIZE * width[i] - width[i] + 0.00001)
468 : {
469 102 : loop_flag[i] = lowerboundary[i] - HALF_Y_SIZE * width[i];
470 102 : i--;
471 102 : if (i < 0)
472 : goto LOOPEND;
473 : }
474 : else
475 : break;
476 : }
477 : }
478 10 : LOOPEND:
479 :
480 : // double integration
481 10 : std::vector<double> av(dimension, 0);
482 10 : std::vector<double> diff_av(dimension, 0);
483 :
484 10 : std::vector<double> loop_flag_x(dimension, 0);
485 10 : std::vector<double> loop_flag_y(dimension, 0);
486 38 : for (int i = 0; i < dimension; i++)
487 : {
488 28 : loop_flag_x[i] = lowerboundary[i];
489 42 : loop_flag_y[i] = loop_flag_x[i] - HALF_Y_SIZE * width[i];
490 : }
491 :
492 : while (true)
493 : {
494 : norm = 0;
495 306 : for (int i = 0; i < dimension; i++)
496 : {
497 228 : av[i] = 0;
498 114 : diff_av[i] = 0;
499 342 : loop_flag_y[i] = loop_flag_x[i] - HALF_Y_SIZE * width[i];
500 : }
501 :
502 : while (true)
503 : {
504 : //std::cout<<"pppppppppppppppppppppp "<<loop_flag_x[0]<<" "<<loop_flag_x[1]<<" "<<loop_flag_y[0]<<" "<<loop_flag_y[1]<<std::endl;
505 15240 : norm += distribution_x_y.get_value(loop_flag_x, loop_flag_y);
506 74520 : for (int i = 0; i < dimension; i++)
507 : {
508 88766 : if (sigma_square[i].get_value(loop_flag_y) > 0.00001 || sigma_square[i].get_value(loop_flag_y) < -0.00001)
509 924 : av[i] += distribution_x_y.get_value(loop_flag_x, loop_flag_y) * ( (loop_flag_x[i] + 0.5 * width[i]) - x_av[i].get_value(loop_flag_y)) / sigma_square[i].get_value(loop_flag_y);
510 :
511 118560 : diff_av[i] += distribution_x_y.get_value(loop_flag_x, loop_flag_y) * (loop_flag_x[i] - loop_flag_y[i]);
512 : }
513 :
514 : // iterate over any dimensions
515 15240 : int i = dimension - 1;
516 : while (true)
517 : {
518 47880 : loop_flag_y[i] += width[i];
519 47880 : if (loop_flag_y[i] > loop_flag_x[i] + HALF_Y_SIZE * width[i] - width[i] + 0.00001)
520 : {
521 798 : loop_flag_y[i] = loop_flag_x[i] - HALF_Y_SIZE * width[i];
522 798 : i--;
523 798 : if (i < 0)
524 : goto LOOPEND2;
525 : }
526 : else
527 : break;
528 : }
529 : }
530 78 : LOOPEND2:
531 :
532 78 : std::vector<double> grad_temp(dimension, 0);
533 306 : for (int i = 0; i < dimension; i++)
534 : {
535 228 : diff_av[i] /= (norm > 0 ? norm : 1);
536 228 : av[i] = BOLTZMANN * temperature * av[i] / (norm > 0 ? norm : 1);
537 456 : grad_temp[i] = av[i] - krestr[i] * diff_av[i];
538 : }
539 78 : grad.set_value(loop_flag_x, grad_temp);
540 78 : count.set_value(loop_flag_x, norm);
541 :
542 : // iterate over any dimensions
543 78 : int i = dimension - 1;
544 : while (true)
545 : {
546 270 : loop_flag_x[i] += width[i];
547 270 : if (loop_flag_x[i] > upperboundary[i] - width[i] + 0.00001)
548 : {
549 22 : loop_flag_x[i] = lowerboundary[i];
550 22 : i--;
551 22 : if (i < 0)
552 : goto LOOPEND3;
553 : }
554 : else
555 : break;
556 : }
557 : }
558 : LOOPEND3:;
559 10 : }
560 :
561 :
562 : // calculate 1D pmf
563 6 : void calc_1D_pmf()
564 : {
565 6 : std::vector<double> last_position(1, 0);
566 6 : std::vector<double> position(1, 0);
567 :
568 : double min = 0;
569 : double dG = 0;
570 :
571 6 : oneD_pmf.set_value(lowerboundary, 0);
572 6 : last_position = lowerboundary;
573 102 : for (double i = lowerboundary[0] + width[0]; i < upperboundary[0] + 0.000001; i += width[0])
574 : {
575 42 : position[0] = i + 0.000001;
576 42 : if (restart == false || input_count.get_value(last_position) == 0)
577 : {
578 168 : dG = oneD_pmf.get_value(last_position) + grad.get_value(last_position)[0] * width[0];
579 : }
580 : else
581 : {
582 0 : dG = oneD_pmf.get_value(last_position) + ((grad.get_value(last_position)[0] * count.get_value(last_position) + input_grad.get_value(last_position)[0] * input_count.get_value(last_position)) / (count.get_value(last_position) + input_count.get_value(last_position))) * width[0];
583 : }
584 42 : if (dG < min)
585 : min = dG;
586 : oneD_pmf.set_value(position, dG);
587 42 : last_position[0] = i + 0.000001;
588 : }
589 :
590 108 : for (double i = lowerboundary[0]; i < upperboundary[0] + 0.000001; i += width[0])
591 : {
592 48 : position[0] = i + 0.000001;
593 48 : oneD_pmf.set_value(position, oneD_pmf.get_value(position) - min);
594 : }
595 6 : }
596 :
597 : // write 1D pmf
598 6 : void write_1D_pmf()
599 : {
600 6 : std::string pmf_filename = output_filename + ".UI.pmf";
601 :
602 : // only for colvars module!
603 : // if (written_1D) cvm::backup_file(pmf_filename.c_str());
604 :
605 12 : std::ofstream ofile_pmf(pmf_filename.c_str());
606 :
607 6 : std::vector<double> position(1, 0);
608 108 : for (double i = lowerboundary[0]; i < upperboundary[0] + 0.000001; i += width[0])
609 : {
610 48 : ofile_pmf << i << " ";
611 48 : position[0] = i + 0.000001;
612 48 : ofile_pmf << oneD_pmf.get_value(position) << std::endl;
613 : }
614 6 : ofile_pmf.close();
615 :
616 6 : written_1D = true;
617 6 : }
618 :
619 : // write heads of the output files
620 30 : void writehead(std::ofstream& os) const
621 : {
622 60 : os << "# " << dimension << std::endl;
623 114 : for (int i = 0; i < dimension; i++)
624 : {
625 42 : os.precision(std::numeric_limits<double>::max_digits10);
626 294 : os << "# " << std::fixed << lowerboundary[i] << " " << width[i] << " " << int((upperboundary[i] - lowerboundary[i]) / width[i] + 0.000001) << " " << 0 << std::endl;
627 : }
628 : os << std::endl;
629 30 : }
630 :
631 : // write interal data, used for testing
632 : // void write_interal_data()
633 : // {
634 : // std::string internal_filaname = output_filename + ".UI.internal";
635 : //
636 : // std::ofstream ofile_internal(internal_filaname.c_str());
637 : //
638 : // std::vector<double> loop_flag(dimension, 0);
639 : // for (int i = 0; i < dimension; i++)
640 : // {
641 : // loop_flag[i] = lowerboundary[i];
642 : // }
643 : // while (true)
644 : // {
645 : // for (int i = 0; i < dimension; i++)
646 : // {
647 : // ofile_internal << loop_flag[i] + 0.5 * width[i] << " ";
648 : // }
649 : //
650 : // for (int i = 0; i < dimension; i++)
651 : // {
652 : // ofile_internal << grad.get_value(loop_flag)[i] << " ";
653 : // }
654 : //
655 : // std::vector<double> ii(dimension,0);
656 : // for (double i = loop_flag[0] - 10; i < loop_flag[0] + 10 + 0.00001; i+= width[0])
657 : // {
658 : // for (double j = loop_flag[1] - 10; j< loop_flag[1] + 10 +0.00001; j+=width[1])
659 : // {
660 : // ii[0] = i;
661 : // ii[1] = j;
662 : // ofile_internal << i <<" "<<j<<" "<< distribution_x_y.get_value(loop_flag,ii)<< " ";
663 : // }
664 : // }
665 : // ofile_internal << std::endl;
666 : //
667 : // // iterate over any dimensions
668 : // int i = dimension - 1;
669 : // while (true)
670 : // {
671 : // loop_flag[i] += width[i];
672 : // if (loop_flag[i] > upperboundary[i] - width[i] + 0.00001)
673 : // {
674 : // loop_flag[i] = lowerboundary[i];
675 : // i--;
676 : // if (i < 0)
677 : // goto LOOPEND5;
678 : // }
679 : // else
680 : // break;
681 : // }
682 : // }
683 : // LOOPEND5:
684 : // ofile_internal.close();
685 : // }
686 :
687 : // write output files
688 10 : void write_files()
689 : {
690 10 : std::string grad_filename = output_filename + ".UI.grad";
691 10 : std::string hist_filename = output_filename + ".UI.hist.grad";
692 10 : std::string count_filename = output_filename + ".UI.count";
693 :
694 : // only for colvars module!
695 : // if (written) cvm::backup_file(grad_filename.c_str());
696 : //if (written) cvm::backup_file(hist_filename.c_str());
697 : // if (written) cvm::backup_file(count_filename.c_str());
698 :
699 20 : std::ofstream ofile(grad_filename.c_str());
700 20 : std::ofstream ofile_hist(hist_filename.c_str(), std::ios::app);
701 20 : std::ofstream ofile_count(count_filename.c_str());
702 :
703 10 : writehead(ofile);
704 10 : writehead(ofile_hist);
705 10 : writehead(ofile_count);
706 :
707 10 : if (dimension == 1)
708 : {
709 6 : calc_1D_pmf();
710 6 : write_1D_pmf();
711 : }
712 :
713 10 : std::vector<double> loop_flag(dimension, 0);
714 38 : for (int i = 0; i < dimension; i++)
715 : {
716 28 : loop_flag[i] = lowerboundary[i];
717 : }
718 : while (true)
719 : {
720 306 : for (int i = 0; i < dimension; i++)
721 : {
722 456 : ofile << std::fixed << std::setprecision(9) << loop_flag[i] + 0.5 * width[i] << " ";
723 342 : ofile_hist << std::fixed << std::setprecision(9) << loop_flag[i] + 0.5 * width[i] << " ";
724 342 : ofile_count << std::fixed << std::setprecision(9) << loop_flag[i] + 0.5 * width[i] << " ";
725 : }
726 :
727 78 : if (restart == false)
728 : {
729 216 : for (int i = 0; i < dimension; i++)
730 : {
731 312 : ofile << std::fixed << std::setprecision(9) << grad.get_value(loop_flag)[i] << " ";
732 312 : ofile_hist << std::fixed << std::setprecision(9) << grad.get_value(loop_flag)[i] << " ";
733 : }
734 : ofile << std::endl;
735 : ofile_hist << std::endl;
736 120 : ofile_count << count.get_value(loop_flag) << " " <<std::endl;
737 : }
738 : else
739 : {
740 : double final_grad = 0;
741 90 : for (int i = 0; i < dimension; i++)
742 : {
743 108 : int total_count_temp = (count.get_value(loop_flag) + input_count.get_value(loop_flag));
744 36 : if (input_count.get_value(loop_flag) == 0)
745 60 : final_grad = grad.get_value(loop_flag)[i];
746 : else
747 112 : final_grad = ((grad.get_value(loop_flag)[i] * count.get_value(loop_flag) + input_grad.get_value(loop_flag)[i] * input_count.get_value(loop_flag)) / total_count_temp);
748 36 : ofile << std::fixed << std::setprecision(9) << final_grad << " ";
749 36 : ofile_hist << std::fixed << std::setprecision(9) << final_grad << " ";
750 : }
751 : ofile << std::endl;
752 : ofile_hist << std::endl;
753 54 : ofile_count << (count.get_value(loop_flag) + input_count.get_value(loop_flag)) << " " <<std::endl;
754 : }
755 :
756 : // iterate over any dimensions
757 78 : int i = dimension - 1;
758 : while (true)
759 : {
760 270 : loop_flag[i] += width[i];
761 270 : if (loop_flag[i] > upperboundary[i] - width[i] + 0.00001)
762 : {
763 22 : loop_flag[i] = lowerboundary[i];
764 22 : i--;
765 : ofile << std::endl;
766 : ofile_hist << std::endl;
767 : ofile_count << std::endl;
768 22 : if (i < 0)
769 : goto LOOPEND4;
770 : }
771 : else
772 : break;
773 : }
774 : }
775 10 : LOOPEND4:
776 10 : ofile.close();
777 10 : ofile_count.close();
778 10 : ofile_hist.close();
779 :
780 10 : written = true;
781 10 : }
782 :
783 : // read input files
784 1 : void read_inputfiles(const std::vector<std::string>& input_filename)
785 : {
786 : char sharp;
787 : double nothing;
788 : int dimension_temp;
789 :
790 1 : std::vector<double> loop_bin_size(dimension, 0);
791 1 : std::vector<double> position_temp(dimension, 0);
792 1 : std::vector<double> grad_temp(dimension, 0);
793 1 : int count_temp = 0;
794 5 : for (unsigned int i = 0; i < input_filename.size(); i++)
795 : {
796 1 : int size = 1, size_temp = 0;
797 :
798 1 : std::string count_filename = input_filename[i] + ".UI.count";
799 1 : std::string grad_filename = input_filename[i] + ".UI.grad";
800 :
801 2 : std::ifstream count_file(count_filename.c_str(), std::ios::in);
802 2 : std::ifstream grad_file(grad_filename.c_str(), std::ios::in);
803 :
804 1 : count_file >> sharp >> dimension_temp;
805 1 : grad_file >> sharp >> dimension_temp;
806 :
807 5 : for (int j = 0; j < dimension; j++)
808 : {
809 4 : count_file >> sharp >> nothing >> nothing >> size_temp >> nothing;
810 2 : grad_file >> sharp >> nothing >> nothing >> nothing >> nothing;
811 2 : size *= size_temp;
812 : }
813 :
814 19 : for (int j = 0; j < size; j++)
815 : {
816 : do
817 : {
818 45 : for (int k = 0; k < dimension; k++)
819 : {
820 18 : count_file >> position_temp[k];
821 : grad_file >> nothing;
822 : }
823 :
824 45 : for (int l = 0; l < dimension; l++)
825 : {
826 18 : grad_file >> grad_temp[l];
827 : }
828 9 : count_file >> count_temp;
829 : }
830 27 : while (position_temp[i] < lowerboundary[i] - 0.000001 || position_temp[i] > upperboundary[i] + 0.000001);
831 :
832 9 : if (count_temp == 0)
833 : {
834 5 : continue;
835 : }
836 :
837 20 : for (int m = 0; m < dimension; m++)
838 : {
839 56 : grad_temp[m] = (grad_temp[m] * count_temp + input_grad.get_value(position_temp)[m] * input_count.get_value(position_temp)) / (count_temp + input_count.get_value(position_temp));
840 : }
841 4 : input_grad.set_value(position_temp, grad_temp);
842 4 : input_count.increase_value(position_temp, count_temp);
843 : }
844 :
845 1 : count_file.close();
846 1 : grad_file.close();
847 : }
848 1 : }
849 : };
850 : }
851 :
852 : }
853 : }
854 :
855 : #endif
|