Collective Variables Module - Developer Documentation
Loading...
Searching...
No Matches
colvargrid_def.h
1// -*- c++ -*-
2
3// This file is part of the Collective Variables module (Colvars).
4// The original version of Colvars and its updates are located at:
5// https://github.com/Colvars/colvars
6// Please update all Colvars source files before making any changes.
7// If you wish to distribute your changes, please submit them to the
8// Colvars repository at GitHub.
9
11
12#ifndef COLVARGRID_DEF_H
13#define COLVARGRID_DEF_H
14
15#include <iostream>
16#include <iomanip>
17
18#include "colvarmodule.h"
19#include "colvarproxy.h"
20#include "colvar.h"
21#include "colvargrid.h"
22#include "colvars_memstream.h"
23
24
25template <class T>
26colvar_grid<T>::colvar_grid(std::string const &filename, size_t mult_i)
27 : colvarparse(cvm::main())
28{
29std::istream &is = cvm::main()->proxy->input_stream(filename, "multicol grid file");
30if (!is) {
31 return;
32}
33
34// Data in the header: nColvars, then for each
35// xiMin, dXi, nPoints, periodic flag
36
37std::string hash;
38size_t i;
39
40if ( !(is >> hash) || (hash != "#") ) {
41 cvmodule->error("Error reading grid at position "+
42 cvm::to_str(static_cast<size_t>(is.tellg()))+
43 " in stream(read \"" + hash + "\")\n");
44 return;
45}
46
47is >> nd;
48mult = (mult_i == 0) ? nd : mult_i;
49
50std::vector<cvm::real> lower_in(nd), widths_in(nd);
51std::vector<int> nx_in(nd);
52std::vector<int> periodic_in(nd);
53
54for (i = 0; i < nd; i++ ) {
55 if ( !(is >> hash) || (hash != "#") ) {
56 cvmodule->error("Error reading grid at position "+
57 cvm::to_str(static_cast<size_t>(is.tellg()))+
58 " in stream(read \"" + hash + "\")\n");
59 return;
60 }
61
62 is >> lower_in[i] >> widths_in[i] >> nx_in[i] >> periodic_in[i];
63}
64
65this->setup(nx_in, 0., mult);
66
67widths = widths_in;
68
69for (i = 0; i < nd; i++ ) {
70 lower_boundaries.push_back(colvarvalue(lower_in[i]));
71 periodic.push_back(static_cast<bool>(periodic_in[i]));
72}
73
74// Reset the istream for read_multicol, which expects the whole file
75is.clear();
76is.seekg(0);
79}
80
81
82template <class T>
83template <class IST>
85 auto const start_pos = is.tellg();
86 std::string conf;
87 if ((is >> colvarparse::read_block("grid_parameters", &conf)) &&
88 (parse_params(conf, colvarparse::parse_restart) == COLVARS_OK) &&
89 read_raw(is)) {
90 return is;
91 }
92 auto const error_pos = is.tellg();
93 is.clear();
94 is.seekg(start_pos);
95 is.setstate(std::ios::failbit);
96 cvmodule->error("Error: in reading grid state from stream at position " +
97 cvm::to_str(error_pos) + "\n", COLVARS_INPUT_ERROR);
98 return is;
99}
100
101
102template <class T> std::istream &colvar_grid<T>::read_restart(std::istream &is) {
103 return read_restart_template_(is);
104}
105
106
108 return read_restart_template_(is);
109}
110
111
112template <class T> std::ostream &colvar_grid<T>::write_restart(std::ostream &os)
113{
114 os << "grid_parameters {\n" << get_state_params() << "}\n";
115 write_raw(os);
116 return os;
117}
118
119
121{
122 os << std::string("grid_parameters") << get_state_params();
123 write_raw(os);
124 return os;
125}
126
127template <class T>
128template <class IST>
130{
131 auto const start_pos = is.tellg();
132
133 for (std::vector<int> ix = new_index(); index_ok(ix); incr(ix)) {
134 for (size_t imult = 0; imult < mult; imult++) {
135 T new_value;
136 if (is >> new_value) {
137 value_input(ix, new_value, imult);
138 } else {
139 is.clear();
140 is.seekg(start_pos);
141 is.setstate(std::ios::failbit);
142 cvmodule->error(
143 "Error: failed to read all of the grid points from file. Possible explanations: grid "
144 "parameters in the configuration (lowerBoundary, upperBoundary, width) are different "
145 "from those in the file, or the file is corrupt/incomplete.\n",
146 COLVARS_INPUT_ERROR);
147 return is;
148 }
149 }
150 }
151
152 has_data = true;
153 return is;
154}
155
156
157template <class T> std::istream &colvar_grid<T>::read_raw(std::istream &is)
158{
159 return read_raw_template_(is);
160}
161
162
164{
165 return read_raw_template_(is);
166}
167
168
169template <class T>
170std::ostream &colvar_grid<T>::write_raw(std::ostream &os, size_t const buf_size) const
171{
172 auto const w = os.width();
173 auto const p = os.precision();
174
175 size_t count = 0;
176 for (auto ix = new_index(); index_ok(ix); incr(ix)) {
177 for (size_t imult = 0; imult < mult; imult++) {
178 os << " " << std::setw(w) << std::setprecision(p) << value_output(ix, imult);
179 if (((++count) % buf_size) == 0)
180 os << "\n";
181 }
182 }
183 // write a final newline only if buffer is not empty
184 if ((count % buf_size) != 0)
185 os << "\n";
186
187 return os;
188}
189
190
191template <class T>
193{
194 for (auto ix = new_index(); index_ok(ix); incr(ix)) {
195 for (size_t imult = 0; imult < mult; imult++) {
196 os << value_output(ix, imult);
197 }
198 }
199 return os;
200}
201
202
203template <class T> std::string colvar_grid<T>::get_state_params() const
204{
205 std::ostringstream os;
206 size_t i;
207 os << " n_colvars " << nd << "\n";
208
209 os << " lower_boundaries ";
210 for (i = 0; i < nd; i++)
211 os << " " << lower_boundaries[i];
212 os << "\n";
213
214 os << " upper_boundaries ";
215 for (i = 0; i < nd; i++)
216 os << " " << upper_boundaries[i];
217 os << "\n";
218
219 os << " widths ";
220 for (i = 0; i < nd; i++)
221 os << " " << widths[i];
222 os << "\n";
223
224 os << " sizes ";
225 for (i = 0; i < nd; i++)
226 os << " " << nx[i];
227 os << "\n";
228
229 return os.str();
230}
231
232
233template <class T> int colvar_grid<T>::parse_params(std::string const &conf,
234 colvarparse::Parse_Mode const parse_mode)
235{
236 if (cvm::debug())
237 cvmodule->log("Reading grid configuration from string.\n");
238
239 std::vector<int> old_nx = nx;
240 std::vector<colvarvalue> old_lb = lower_boundaries;
241 std::vector<colvarvalue> old_ub = upper_boundaries;
242 std::vector<cvm::real> old_w = widths;
243
244 {
245 size_t nd_in = 0;
246 // this is only used in state files
247 colvarparse::get_keyval(conf, "n_colvars", nd_in, nd, colvarparse::parse_silent);
248 if (nd_in != nd) {
249 cvmodule->error("Error: trying to read data for a grid "
250 "that contains a different number of colvars ("+
251 cvm::to_str(nd_in)+") than the grid defined "
252 "in the configuration file("+cvm::to_str(nd)+
253 ").\n");
254 return COLVARS_ERROR;
255 }
256 }
257
258 // underscore keywords are used in state file
259 colvarparse::get_keyval(conf, "lower_boundaries",
260 lower_boundaries, lower_boundaries, colvarparse::parse_silent);
261 colvarparse::get_keyval(conf, "upper_boundaries",
262 upper_boundaries, upper_boundaries, colvarparse::parse_silent);
263 // plural form is used in state file
264 colvarparse::get_keyval(conf, "widths", widths, widths, colvarparse::parse_silent);
265
266 // camel case keywords are used in config file
267 colvarparse::get_keyval(conf, "lowerBoundary",
268 lower_boundaries, lower_boundaries, parse_mode);
269 colvarparse::get_keyval(conf, "upperBoundary",
270 upper_boundaries, upper_boundaries, parse_mode);
271
272 colvarparse::get_keyval(conf, "width", widths, widths, parse_mode);
274 // only used in state file
275 colvarparse::get_keyval(conf, "sizes", nx, nx, colvarparse::parse_silent);
276
277 if (nd < lower_boundaries.size()) nd = lower_boundaries.size();
278
279 if (! use_actual_value.size()) use_actual_value.assign(nd, false);
280 if (! periodic.size()) periodic.assign(nd, false);
281 if (! widths.size()) widths.assign(nd, 1.0);
282
283 cvm::real eps = 1.e-10;
284
285 bool new_params = false;
286 if (old_nx.size()) {
287 for (size_t i = 0; i < nd; i++) {
288 if (old_nx[i] != nx[i] ||
289 cvm::sqrt(cv[i]->dist2(old_lb[i], lower_boundaries[i])) > eps ||
290 cvm::sqrt(cv[i]->dist2(old_ub[i], upper_boundaries[i])) > eps ||
291 cvm::fabs(old_w[i] - widths[i]) > eps) {
292 new_params = true;
293 }
294 }
295 } else {
296 new_params = true;
297 }
298
299 // reallocate the array in case the grid params have just changed
300 if (new_params) {
301 init_from_boundaries();
302 // data.clear(); // no longer needed: setup calls clear()
303 return this->setup(nx, T(), mult);
304 }
305
306 return COLVARS_OK;
307}
308
309
310template <class T>
311std::istream & colvar_grid<T>::read_multicol(std::istream &is, bool add)
312{
313 // Data in the header: nColvars, then for each
314 // xiMin, dXi, nPoints, periodic flag
315
316 std::string hash;
317 cvm::real lower, width, x;
318 size_t n, periodic_flag;
319 bool remap;
320 std::vector<T> new_value;
321 std::vector<int> nx_read;
322 std::vector<int> bin;
323
324 if ( cv.size() > 0 && cv.size() != nd ) {
325 cvmodule->error("Cannot read grid file: number of variables in file differs from number referenced by grid.\n");
326 return is;
327 }
328
329 if ( !(is >> hash) || (hash != "#") ) {
330 cvmodule->error("Error reading grid at position "+
331 cvm::to_str(static_cast<size_t>(is.tellg()))+
332 " in stream(read \"" + hash + "\")\n", COLVARS_INPUT_ERROR);
333 return is;
334 }
335
336 is >> n;
337 if ( n != nd ) {
338 cvmodule->error("Error reading grid: wrong number of collective variables.\n");
339 return is;
340 }
341
342 nx_read.resize(n);
343 bin.resize(n);
344 new_value.resize(mult);
345
346 if (this->has_parent_data && add) {
347 new_data.resize(data.size());
348 }
349
350 remap = false;
351 for (size_t i = 0; i < nd; i++ ) {
352 if ( !(is >> hash) || (hash != "#") ) {
353 cvmodule->error("Error reading grid at position "+
354 cvm::to_str(static_cast<size_t>(is.tellg()))+
355 " in stream(read \"" + hash + "\")\n");
356 return is;
357 }
358
359 is >> lower >> width >> nx_read[i] >> periodic_flag;
360
361
362 if ( (cvm::fabs(lower - lower_boundaries[i].real_value) > 1.0e-10) ||
363 (cvm::fabs(width - widths[i] ) > 1.0e-10) ||
364 (nx_read[i] != nx[i]) ) {
365 cvmodule->log("Warning: reading from different grid definition (colvar "
366 + cvm::to_str(i+1) + "); remapping data on new grid.\n");
367 remap = true;
368 }
369 }
370
371 if ( remap ) {
372 // re-grid data
373 while (is.good()) {
374 bool end_of_file = false;
375
376 for (size_t i = 0; i < nd; i++ ) {
377 if ( !(is >> x) ) end_of_file = true;
378 bin[i] = value_to_bin_scalar(x, i);
379 // if x is out of bounds and we are using PBC, wrap it
380 // Ignore out of bounds points in non-PBC
381 wrap_detect_edge(bin);
382 }
383 if (end_of_file) break;
384
385 for (size_t imult = 0; imult < mult; imult++) {
386 is >> new_value[imult];
387 }
388
389 if ( index_ok(bin) ) {
390 for (size_t imult = 0; imult < mult; imult++) {
391 value_input(bin, new_value[imult], imult, add);
392 }
393 }
394 }
395 } else {
396 // do not re-grid the data but assume the same grid is used
397 for (std::vector<int> ix = new_index(); index_ok(ix); incr(ix) ) {
398 for (size_t i = 0; i < nd; i++ ) {
399 is >> x;
400 }
401 for (size_t imult = 0; imult < mult; imult++) {
402 is >> new_value[imult];
403 value_input(ix, new_value[imult], imult, add);
404 }
405 }
406 }
407 has_data = true;
408 return is;
409}
410
411
412template <class T>
413int colvar_grid<T>::read_multicol(std::string const &filename,
414 std::string description,
415 bool add)
416{
417 std::istream &is = cvm::main()->proxy->input_stream(filename, description);
418 if (!is) {
419 return COLVARS_FILE_ERROR;
420 }
421 if (colvar_grid<T>::read_multicol(is, add)) {
422 cvm::main()->proxy->close_input_stream(filename);
423 return COLVARS_OK;
424 }
425 return COLVARS_FILE_ERROR;
426}
427
428
429template <class T>
430std::ostream & colvar_grid<T>::write_multicol(std::ostream &os) const
431{
432 // Save the output formats
433 std::ios_base::fmtflags prev_flags(os.flags());
434
435 // Data in the header: nColvars, then for each
436 // xiMin, dXi, nPoints, periodic
437
438 os << std::setw(2) << "# " << nd << "\n";
439 // Write the floating numbers in full precision
440 os.setf(std::ios::scientific, std::ios::floatfield);
441 for (size_t i = 0; i < nd; i++) {
442 os << "# "
443 << std::setw(cvmodule->cv_width) << std::setprecision(cvmodule->cv_prec) << lower_boundaries[i] << " "
444 << std::setw(cvmodule->cv_width) << std::setprecision(cvmodule->cv_prec) << widths[i] << " "
445 << std::setw(10) << nx[i] << " "
446 << periodic[i] << "\n";
447 }
448
449 for (std::vector<int> ix = new_index(); index_ok(ix); incr(ix) ) {
450
451 if (ix.back() == 0) {
452 // if the last index is 0, add a new line to mark the new record
453 os << "\n";
454 }
455
456 for (size_t i = 0; i < nd; i++) {
457 os << " "
458 << std::setw(cvmodule->cv_width) << std::setprecision(cvmodule->cv_prec)
459 << bin_to_value_scalar(ix[i], i);
460 }
461 os << " ";
462 for (size_t imult = 0; imult < mult; imult++) {
463 os << " "
464 << std::setw(cvmodule->cv_width) << std::setprecision(cvmodule->cv_prec)
465 << value_output(ix, imult);
466 }
467 os << "\n";
468 }
469
470 // Restore the output formats
471 os.flags(prev_flags);
472
473 return os;
474}
475
476
477template <class T>
478int colvar_grid<T>::write_multicol(std::string const &filename,
479 std::string description) const
480{
481 int error_code = COLVARS_OK;
482 std::ostream &os = cvm::main()->proxy->output_stream(filename, description);
483 if (!os) {
484 return COLVARS_FILE_ERROR;
485 }
486 error_code |= colvar_grid<T>::write_multicol(os) ? COLVARS_OK :
487 COLVARS_FILE_ERROR;
488 cvm::main()->proxy->close_output_stream(filename);
489 return error_code;
490}
491
492
493template <class T>
494std::ostream & colvar_grid<T>::write_opendx(std::ostream &os) const
495{
496 // write the header
497 os << "object 1 class gridpositions counts";
498 size_t icv;
499 for (icv = 0; icv < num_variables(); icv++) {
500 os << " " << number_of_points(icv);
501 }
502 os << "\n";
503
504 os << "origin";
505 for (icv = 0; icv < num_variables(); icv++) {
506 os << " " << (lower_boundaries[icv].real_value + 0.5 * widths[icv]);
507 }
508 os << "\n";
509
510 for (icv = 0; icv < num_variables(); icv++) {
511 os << "delta";
512 for (size_t icv2 = 0; icv2 < num_variables(); icv2++) {
513 if (icv == icv2) os << " " << widths[icv];
514 else os << " " << 0.0;
515 }
516 os << "\n";
517 }
518
519 os << "object 2 class gridconnections counts";
520 for (icv = 0; icv < num_variables(); icv++) {
521 os << " " << number_of_points(icv);
522 }
523 os << "\n";
524
525 os << "object 3 class array type double rank 0 items "
526 << number_of_points() << " data follows\n";
527
528 write_raw(os);
529
530 os << "object \"collective variables scalar field\" class field\n";
531 return os;
532}
533
534
535template <class T>
536int colvar_grid<T>::write_opendx(std::string const &filename,
537 std::string description) const
538{
539 int error_code = COLVARS_OK;
540 std::ostream &os = cvm::main()->proxy->output_stream(filename, description);
541 if (!os) {
542 return COLVARS_FILE_ERROR;
543 }
544 error_code |= colvar_grid<T>::write_opendx(os) ? COLVARS_OK :
545 COLVARS_FILE_ERROR;
546 cvm::main()->proxy->close_output_stream(filename);
547 return error_code;
548}
549
550#endif
size_t nd
Number of dimensions.
Definition: colvargrid.h:28
std::vector< colvarvalue > lower_boundaries
Lower boundaries of the colvars in this grid.
Definition: colvargrid.h:37
std::vector< cvm::real > widths
Widths of the colvars in this grid.
Definition: colvargrid.h:43
Grid of values of a function of several collective variables.
Definition: colvargrid.h:52
int setup()
Allocate data (allow initialization also after construction)
Definition: colvargrid.h:200
std::istream & read_restart(std::istream &is)
Read all grid parameters and data from a formatted stream.
Definition: colvargrid_def.h:102
std::string get_state_params() const
Write the current grid parameters to a string.
Definition: colvargrid_def.h:203
std::ostream & write_raw(std::ostream &os, size_t const buf_size=3) const
Definition: colvargrid_def.h:170
size_t mult
Multiplicity of each datum (allow the binning of non-scalar types such as atomic gradients)
Definition: colvargrid.h:59
int parse_params(std::string const &conf, colvarparse::Parse_Mode const parse_mode=colvarparse::parse_normal)
Read new grid parameters from a string.
Definition: colvargrid_def.h:233
IST & read_restart_template_(IST &is)
Helper method for read_restart.
Definition: colvargrid_def.h:84
std::ostream & write_opendx(std::ostream &os) const
Write the grid data without labels, as they are represented in memory.
Definition: colvargrid_def.h:494
std::istream & read_raw(std::istream &is)
Read all grid parameters and data from a formatted stream.
Definition: colvargrid_def.h:157
std::ostream & write_multicol(std::ostream &os) const
Write grid in a format which is both human-readable and gnuplot-friendly.
Definition: colvargrid_def.h:430
IST & read_raw_template_(IST &is)
Helper method for read_raw.
Definition: colvargrid_def.h:129
std::istream & read_multicol(std::istream &is, bool add=false)
Read a grid written by write_multicol(), incrementing if add is true.
Definition: colvargrid_def.h:311
std::vector< bool > periodic
Whether some colvars are periodic.
Definition: colvargrid.h:94
colvar_grid()
Default constructor.
Definition: colvargrid.h:214
std::ostream & write_restart(std::ostream &os)
Write all grid parameters and data to a formatted stream.
Definition: colvargrid_def.h:112
Collective variables module (main class)
Definition: colvarmodule.h:72
double real
Defining an abstract real number allows to switch precision.
Definition: colvarmodule.h:99
int error(std::string const &message, int code=-1)
Print a message to the main log and set global error code.
Definition: colvarmodule.cpp:2186
static colvarmodule * main()
Access the main instance of the Colvars module.
Definition: colvarmodule.cpp:205
static real sqrt(real const &x)
Reimplemented to work around MS compiler issues.
Definition: colvarmodule.h:143
static bool debug()
Whether debug output should be enabled (compile-time option)
Definition: colvarmodule.h:376
static real fabs(real const &x)
Reimplemented to work around MS compiler issues.
Definition: colvarmodule.h:137
static std::string to_str(char const *s)
Convert to string for output purposes.
Definition: colvarmodule.cpp:2541
colvarproxy * proxy
Pointer to the proxy object, used to retrieve atomic data from the hosting program.
Definition: colvarmodule.h:957
Definition: colvarparse.h:286
Base class containing parsing functions; all objects which need to parse input inherit from this.
Definition: colvarparse.h:27
Parse_Mode
How a keyword is parsed in a string.
Definition: colvarparse.h:63
@ parse_restart
The call is being executed from a read_restart() function.
Definition: colvarparse.h:80
@ parse_silent
Do not print the keyword.
Definition: colvarparse.h:73
virtual int close_output_stream(std::string const &output_name)
Closes the given output file/channel.
Definition: colvarproxy_io.cpp:474
std::istream & input_stream(std::string const &input_name, std::string const description="file/channel", bool error_on_fail=true)
Definition: colvarproxy_io.cpp:264
virtual std::ostream & output_stream(std::string const &output_name, std::string const description)
Definition: colvarproxy_io.cpp:407
int close_input_stream(std::string const &input_name)
Closes the given input stream.
Definition: colvarproxy_io.cpp:338
Value of a collective variable: this is a metatype which can be set at runtime. By default it is set ...
Definition: colvarvalue.h:43
Definition: colvars_memstream.h:30
Collective variables main module.
Colvars proxy classes.