Collective Variables Module - Developer Documentation
Loading...
Searching...
No Matches
colvargrid.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
10#ifndef COLVARGRID_H
11#define COLVARGRID_H
12
13#include <iosfwd>
14#include <memory>
15
16#include "colvar.h"
17#include "colvarmodule.h"
18#include "colvarvalue.h"
19#include "colvarparse.h"
20
21
25
26public:
28 size_t nd = 0;
29
31 std::vector<int> nx;
32
34 std::vector<int> nxc;
35
37 std::vector<colvarvalue> lower_boundaries;
38
40 std::vector<colvarvalue> upper_boundaries;
41
43 std::vector<cvm::real> widths;
44};
45
46
52template <class T> class colvar_grid : public colvar_grid_params, public colvarparse {
53
54 //protected:
55public: // TODO create accessors for these after all instantiations work
56
59 size_t mult = 1;
60
62 size_t nt;
63
65 std::vector<T> data;
66
68 std::vector<size_t> new_data;
69
71 std::vector<colvar *> cv;
72
74 std::vector<bool> use_actual_value;
75
77 inline size_t address(std::vector<int> const &ix) const
78 {
79 size_t addr = 0;
80 for (size_t i = 0; i < nd; i++) {
81 addr += ix[i]*static_cast<size_t>(nxc[i]);
82 if (cvm::debug()) {
83 if (ix[i] >= nx[i] || ix[i] < 0) {
84 cvmodule->error("Error: index along dimension " + cvm::to_str(i) + " (" + cvm::to_str(ix[i])
85 + ") exceeds bounds in colvar_grid.\n", COLVARS_BUG_ERROR);
86 return 0;
87 }
88 }
89 }
90 return addr;
91 }
92
94 inline void index(size_t address, std::vector<int> &ix) {
95 for (int dim = nd - 1; dim >= 0; --dim) {
96 ix[dim] = address % nx[dim];
97 address /= nx[dim];
98 }
99 }
100
101public:
103 std::vector<bool> periodic;
104
106 std::vector<bool> hard_lower_boundaries;
107
109 std::vector<bool> hard_upper_boundaries;
110
113
116
118 inline size_t num_variables() const
119 {
120 return nd;
121 }
122
124 inline std::vector<int> const &number_of_points_vec() const
125 {
126 return nx;
127 }
128
131 inline size_t number_of_points(int const icv = -1) const
132 {
133 if (icv < 0) {
134 return nt;
135 } else {
136 return nx[icv];
137 }
138 }
139
141 inline std::vector<int> const & sizes() const
142 {
143 return nx;
144 }
145
147 inline void set_sizes(std::vector<int> const &new_sizes)
148 {
149 nx = new_sizes;
150 }
151
153 inline size_t multiplicity() const
154 {
155 return mult;
156 }
157
159 inline void request_actual_value(bool b = true)
160 {
161 size_t i;
162 for (i = 0; i < use_actual_value.size(); i++) {
163 use_actual_value[i] = b;
164 }
165 }
166
168 int setup(std::vector<int> const &nx_i,
169 T const &t = T(),
170 size_t const &mult_i = 1)
171 {
172 if (cvm::debug()) {
173 cvmodule->log("Allocating grid: multiplicity = "+cvm::to_str(mult_i)+
174 ", dimensions = "+cvm::to_str(nx_i)+".\n");
175 }
176
177 mult = mult_i;
178
179 data.clear();
180
181 nx = nx_i;
182 nd = nx.size();
183
184 nxc.resize(nd);
185
186 // setup dimensions
187 nt = mult;
188 for (int i = nd-1; i >= 0; i--) {
189 if (nx[i] <= 0) {
190 cvm::error_static("Error: providing an invalid number of grid points, "+
191 cvm::to_str(nx[i])+".\n", COLVARS_BUG_ERROR);
192 return COLVARS_ERROR;
193 }
194 nxc[i] = nt;
195 nt *= nx[i];
196 }
197
198 if (cvm::debug()) {
199 cvmodule->log("Total number of grid elements = "+cvm::to_str(nt)+".\n");
200 }
201
202 data.reserve(nt);
203 data.assign(nt, t);
204
205 return COLVARS_OK;
206 }
207
209 int setup()
210 {
211 return setup(this->nx, T(), this->mult);
212 }
213
215 void reset(T const &t = T())
216 {
217 data.assign(nt, t);
218 }
219
220
222 // This constructor depends on a static cvm pointer and is deprecated
223 colvar_grid() : colvarparse(cvm::main()), has_data(false)
224 {
225 nd = nt = 0;
226 mult = 1;
227 has_parent_data = false;
228 this->setup();
229 }
230
232 virtual ~colvar_grid()
233 {}
234
238 // This constructor depends on a static cvm pointer and is deprecated
240 colvarparse(cvm::main()),
241 mult(g.mult),
242 data(),
243 cv(g.cv),
248 has_parent_data(false),
249 has_data(false)
250 {}
251
256 colvar_grid(std::vector<int> const &nx_i,
257 T const &t = T(),
258 size_t mult_i = 1)
259 : colvarparse(cvm::main()), has_parent_data(false), has_data(false)
260 {
261 this->setup(nx_i, t, mult_i);
262 }
263
267 colvar_grid(std::vector<colvar *> const &colvars,
268 T const &t = T(),
269 size_t mult_i = 1,
270 bool add_extra_bin = false,
271 std::shared_ptr<const colvar_grid_params> params = nullptr,
272 std::string config = std::string())
273 : colvarparse(cvm::main()), has_parent_data(false), has_data(false)
274 {
275 (void) t;
276 this->init_from_colvars(colvars, mult_i, add_extra_bin, params, config);
277 }
278
282 colvar_grid(std::string const &filename, size_t mult_i = 1);
283
284 int init_from_colvars(std::vector<colvar *> const &colvars,
285 size_t mult_i = 1,
286 bool add_extra_bin = false,
287 std::shared_ptr<const colvar_grid_params> params = nullptr,
288 std::string config = std::string())
289 {
290 if (cvm::debug()) {
291 cvmodule->log("Reading grid configuration from collective variables.\n");
292 }
293
294 cv = colvars;
295 nd = colvars.size();
296 mult = mult_i;
297
298 size_t i;
299
300 if (cvm::debug()) {
301 cvmodule->log("Allocating a grid for "+cvm::to_str(colvars.size())+
302 " collective variables, multiplicity = "+cvm::to_str(mult_i)+".\n");
303 }
304
305 for (i = 0; i < nd; i++) {
306 if (cv[i]->value().type() != colvarvalue::type_scalar) {
307 cvm::error_static("Colvar grids can only be automatically "
308 "constructed for scalar variables. "
309 "ABF and histogram can not be used; metadynamics "
310 "can be used with useGrids disabled.\n", COLVARS_INPUT_ERROR);
311 return COLVARS_ERROR;
312 }
313
314 if (cv[i]->width <= 0.0) {
315 cvm::error_static("Tried to initialize a grid on a "
316 "variable with negative or zero width.\n", COLVARS_INPUT_ERROR);
317 return COLVARS_ERROR;
318 }
319
320 widths.push_back(cv[i]->width);
323
324 // By default, get reported colvar value (for extended Lagrangian colvars)
325 use_actual_value.push_back(false);
326
327 // except if a colvar is specified twice in a row
328 // then the first instance is the actual value
329 // For histograms of extended-system coordinates
330 if (i > 0 && cv[i-1] == cv[i]) {
331 use_actual_value[i-1] = true;
332 }
333
334 // This needs to work if the boundaries are undefined in the colvars
335 lower_boundaries.push_back(cv[i]->lower_boundary);
336 upper_boundaries.push_back(cv[i]->upper_boundary);
337 }
338
339 // Replace widths and boundaries with optional custom configuration
340 if (!config.empty()) {
341 this->parse_params(config);
342 this->check_keywords(config, "grid");
343
344 if (params) {
345 cvm::error_static("Error: init_from_colvars was passed both a grid config and a template grid.", COLVARS_BUG_ERROR);
346 return COLVARS_BUG_ERROR;
347 }
348 } else if (params) {
349 // Match grid sizes with template
350
351 if (params->nd != nd) {
352 cvm::error_static("Trying to initialize grid from template with wrong dimension (" +
353 cvm::to_str(params->nd) + " instead of " +
354 cvm::to_str(this->nd) + ").");
355 return COLVARS_ERROR;
356 }
357
358 widths =params->widths;
359 lower_boundaries =params->lower_boundaries;
360 upper_boundaries =params->upper_boundaries;
361 }
362
363 // Only now can we determine periodicity
364 for (i = 0; i < nd; i++) {
365 periodic.push_back(cv[i]->periodic_boundaries(lower_boundaries[i].real_value,
366 upper_boundaries[i].real_value));
367
368 if (add_extra_bin) {
369 // Shift the grid by half the bin width (values at edges instead of center of bins)
370 lower_boundaries[i] -= 0.5 * widths[i];
371
372 if (periodic[i]) {
373 // Just shift
374 upper_boundaries[i] -= 0.5 * widths[i];
375 } else {
376 // Widen grid by one bin width
377 upper_boundaries[i] += 0.5 * widths[i];
378 }
379 }
380 }
381
382 // Reset grid sizes based on widths and boundaries
383 this->init_from_boundaries();
384 return this->setup();
385 }
386
387 int init_from_boundaries()
388 {
389 if (cvm::debug()) {
390 cvmodule->log("Configuring grid dimensions from colvars boundaries.\n");
391 }
392
393 // these will have to be updated
394 nx.clear();
395 nxc.clear();
396 nt = 0;
397
398 for (size_t i = 0; i < lower_boundaries.size(); i++) {
399 // Re-compute periodicity using current grid boundaries
400 periodic[i] = cv[i]->periodic_boundaries(lower_boundaries[i].real_value,
401 upper_boundaries[i].real_value);
402
403 cvm::real nbins = ( upper_boundaries[i].real_value -
404 lower_boundaries[i].real_value ) / widths[i];
405 int nbins_round = (int)(nbins+0.5);
406
407 if (cvm::fabs(nbins - cvm::real(nbins_round)) > 1.0E-10) {
408 cvmodule->log("Warning: grid interval("+
409 cvm::to_str(lower_boundaries[i], cvmodule->cv_width, cvmodule->cv_prec)+" - "+
410 cvm::to_str(upper_boundaries[i], cvmodule->cv_width, cvmodule->cv_prec)+
411 ") is not commensurate to its bin width("+
412 cvm::to_str(widths[i], cvmodule->cv_width, cvmodule->cv_prec)+").\n");
413 upper_boundaries[i].real_value = lower_boundaries[i].real_value +
414 (nbins_round * widths[i]);
415 }
416
417 if (cvm::debug())
418 cvmodule->log("Number of points is "+cvm::to_str((int) nbins_round)+
419 " for the colvar no. "+cvm::to_str(i+1)+".\n");
420
421 nx.push_back(nbins_round);
422 }
423
424 return COLVARS_OK;
425 }
426
429 inline void wrap(std::vector<int> & ix) const
430 {
431 for (size_t i = 0; i < nd; i++) {
432 if (periodic[i]) {
433 ix[i] = (ix[i] + nx[i]) % nx[i]; // Avoid modulo with negative operands (implementation-defined)
434 } else {
435 if (ix[i] < 0 || ix[i] >= nx[i]) {
436 cvm::error_static("Trying to wrap illegal index vector (non-PBC) for a grid point: "
437 + cvm::to_str(ix), COLVARS_BUG_ERROR);
438 return;
439 }
440 }
441 }
442 }
443
446 inline bool wrap_detect_edge(std::vector<int> & ix) const
447 {
448 bool edge = false;
449 for (size_t i = 0; i < nd; i++) {
450 if (periodic[i]) {
451 ix[i] = (ix[i] + nx[i]) % nx[i]; // Avoid modulo with negative operands (implementation-defined)
452 } else if (ix[i] < 0 || ix[i] >= nx[i]) {
453 edge = true;
454 }
455 }
456 return edge;
457 }
458
461 inline bool wrap_to_edge(std::vector<int> & ix, std::vector<int> & edge_bin) const
462 {
463 bool edge = false;
464 edge_bin = ix;
465 for (size_t i = 0; i < nd; i++) {
466 if (periodic[i]) {
467 ix[i] = (ix[i] + nx[i]) % nx[i]; // Avoid modulo with negative operands (implementation-defined)
468 edge_bin[i] = ix[i];
469 } else if (ix[i] < 0) {
470 edge = true;
471 edge_bin[i] = 0;
472 } else if (ix[i] >= nx[i]) {
473 edge = true;
474 edge_bin[i] = nx[i] - 1;
475 }
476 }
477 return edge;
478 }
479
480
482 inline int current_bin_scalar(int const i) const
483 {
484 return value_to_bin_scalar(use_actual_value[i] ? cv[i]->actual_value() : cv[i]->value(), i);
485 }
486
489 inline int current_bin_flat_bound() const
490 {
491 std::vector<int> index = new_index();
492 for (size_t i = 0; i < nd; i++) {
493 index[i] = current_bin_scalar_bound(i);
494 }
495 return address(index);
496 }
497
500 inline int current_bin_scalar_bound(int const i) const
501 {
502 return value_to_bin_scalar_bound(use_actual_value[i] ? cv[i]->actual_value() : cv[i]->value(), i);
503 }
504
506 inline int current_bin_scalar(int const i, int const iv) const
507 {
509 cv[i]->actual_value().vector1d_value[iv] :
510 cv[i]->value().vector1d_value[iv], i);
511 }
512
515 inline int value_to_bin_scalar(colvarvalue const &value, const int i) const
516 {
517 return (int) cvm::floor( (value.real_value - lower_boundaries[i].real_value) / widths[i] );
518 }
519
521 inline cvm::real current_bin_scalar_fraction(int const i) const
522 {
523 return value_to_bin_scalar_fraction(use_actual_value[i] ? cv[i]->actual_value() : cv[i]->value(), i);
524 }
525
528 inline cvm::real value_to_bin_scalar_fraction(colvarvalue const &value, const int i) const
529 {
530 cvm::real x = (value.real_value - lower_boundaries[i].real_value) / widths[i];
531 return x - cvm::floor(x);
532 }
533
536 inline int value_to_bin_scalar_bound(colvarvalue const &value, const int i) const
537 {
538 int bin_index = cvm::floor( (value.real_value - lower_boundaries[i].real_value) / widths[i] );
539
540 // Wrap bins for periodic dimensions before truncating
541 if (periodic[i]) bin_index %= nx[i];
542 if (bin_index < 0) bin_index=0;
543 if (bin_index >=int(nx[i])) bin_index=int(nx[i])-1;
544 return (int) bin_index;
545 }
546
548 inline int value_to_bin_scalar(colvarvalue const &value,
549 colvarvalue const &new_offset,
550 cvm::real const &new_width) const
551 {
552 return (int) cvm::floor( (value.real_value - new_offset.real_value) / new_width );
553 }
554
557 inline colvarvalue bin_to_value_scalar(int const &i_bin, int const i) const
558 {
559 return lower_boundaries[i].real_value + widths[i] * (0.5 + i_bin);
560 }
561
563 inline colvarvalue bin_to_value_scalar(int const &i_bin,
564 colvarvalue const &new_offset,
565 cvm::real const &new_width) const
566 {
567 return new_offset.real_value + new_width * (0.5 + i_bin);
568 }
569
571 inline void set_value(std::vector<int> const &ix,
572 T const &t,
573 size_t const &imult = 0)
574 {
575 data[this->address(ix)+imult] = t;
576 has_data = true;
577 }
578
580 inline void set_value(size_t i, T const &t)
581 {
582 data[i] = t;
583 }
584
586 inline T get_value(size_t i) const
587 {
588 return data[i];
589 }
590
591
596 void delta_grid(colvar_grid<T> const &other_grid)
597 {
598
599 if (other_grid.multiplicity() != this->multiplicity()) {
600 cvm::error_static("Error: trying to subtract two grids with "
601 "different multiplicity.\n");
602 return;
603 }
604
605 if (other_grid.data.size() != this->data.size()) {
606 cvm::error_static("Error: trying to subtract two grids with "
607 "different size.\n");
608 return;
609 }
610
611 for (size_t i = 0; i < data.size(); i++) {
612 data[i] = other_grid.data[i] - data[i];
613 }
614 has_data = true;
615 }
616
617
621 void copy_grid(colvar_grid<T> const &other_grid)
622 {
623 if (other_grid.multiplicity() != this->multiplicity()) {
624 cvm::error_static("Error: trying to copy two grids with "
625 "different multiplicity.\n");
626 return;
627 }
628
629 if (other_grid.data.size() != this->data.size()) {
630 cvm::error_static("Error: trying to copy two grids with "
631 "different size.\n");
632 return;
633 }
634
635
636 for (size_t i = 0; i < data.size(); i++) {
637 data[i] = other_grid.data[i];
638 }
639 has_data = true;
640 }
641
644 void raw_data_out(T* out_data) const
645 {
646 for (size_t i = 0; i < data.size(); i++) out_data[i] = data[i];
647 }
648 void raw_data_out(std::vector<T>& out_data) const
649 {
650 out_data = data;
651 }
653 void raw_data_in(const T* in_data)
654 {
655 for (size_t i = 0; i < data.size(); i++) data[i] = in_data[i];
656 has_data = true;
657 }
658 void raw_data_in(const std::vector<T>& in_data)
659 {
660 data = in_data;
661 has_data = true;
662 }
664 size_t raw_data_num() const { return data.size(); }
665
666
669 inline T const & value(std::vector<int> const &ix,
670 size_t const &imult = 0) const
671 {
672 return data[this->address(ix) + imult];
673 }
674
676 inline T const & value(size_t i) const
677 {
678 return data[i];
679 }
680
682 inline void add_constant(T const &t)
683 {
684 for (size_t i = 0; i < nt; i++)
685 data[i] += t;
686 has_data = true;
687 }
688
690 inline void multiply_constant(cvm::real const &a)
691 {
692 for (size_t i = 0; i < nt; i++)
693 data[i] *= a;
694 }
695
697 inline void remove_small_values(cvm::real const &a)
698 {
699 for (size_t i = 0; i < nt; i++)
700 if(data[i]<a) data[i] = a;
701 }
702
703
706 inline std::vector<int> const get_colvars_index(std::vector<colvarvalue> const &values) const
707 {
708 std::vector<int> index = new_index();
709 for (size_t i = 0; i < nd; i++) {
710 index[i] = value_to_bin_scalar(values[i], i);
711 }
712 return index;
713 }
714
717 inline std::vector<int> const get_colvars_index() const
718 {
719 std::vector<int> index = new_index();
720 for (size_t i = 0; i < nd; i++) {
721 index[i] = current_bin_scalar(i);
722 }
723 return index;
724 }
725
728 inline std::vector<int> const get_colvars_index_bound() const
729 {
730 std::vector<int> index = new_index();
731 for (size_t i = 0; i < nd; i++) {
732 index[i] = current_bin_scalar_bound(i);
733 }
734 return index;
735 }
736
740 inline cvm::real bin_distance_from_boundaries(std::vector<colvarvalue> const &values,
741 bool skip_hard_boundaries = false)
742 {
743 cvm::real minimum = 1.0E+16;
744 for (size_t i = 0; i < nd; i++) {
745
746 if (periodic[i]) continue;
747
748 cvm::real dl = cvm::sqrt(cv[i]->dist2(values[i], lower_boundaries[i])) / widths[i];
749 cvm::real du = cvm::sqrt(cv[i]->dist2(values[i], upper_boundaries[i])) / widths[i];
750
751 if (values[i].real_value < lower_boundaries[i])
752 dl *= -1.0;
753 if (values[i].real_value > upper_boundaries[i])
754 du *= -1.0;
755
756 if ( ((!skip_hard_boundaries) || (!hard_lower_boundaries[i])) && (dl < minimum))
757 minimum = dl;
758 if ( ((!skip_hard_boundaries) || (!hard_upper_boundaries[i])) && (du < minimum))
759 minimum = du;
760 }
761
762 return minimum;
763 }
764
765
770 void map_grid(colvar_grid<T> const &other_grid)
771 {
772 if (other_grid.multiplicity() != this->multiplicity()) {
773 cvm::error_static("Error: trying to merge two grids with values of "
774 "different multiplicity.\n");
775 return;
776 }
777
778 std::vector<colvarvalue> const &gb = this->lower_boundaries;
779 std::vector<cvm::real> const &gw = this->widths;
780 std::vector<colvarvalue> const &ogb = other_grid.lower_boundaries;
781 std::vector<cvm::real> const &ogw = other_grid.widths;
782
783 std::vector<int> ix = this->new_index();
784 std::vector<int> oix = other_grid.new_index();
785
786 if (cvm::debug())
787 cvmodule->log("Remapping grid...\n");
788 for ( ; this->index_ok(ix); this->incr(ix)) {
789
790 for (size_t i = 0; i < nd; i++) {
791 oix[i] =
792 value_to_bin_scalar(bin_to_value_scalar(ix[i], gb[i], gw[i]),
793 ogb[i],
794 ogw[i]);
795 }
796
797 if (! other_grid.index_ok(oix)) {
798 continue;
799 }
800
801 for (size_t im = 0; im < mult; im++) {
802 this->set_value(ix, other_grid.value(oix, im), im);
803 }
804 }
805
806 has_data = true;
807 if (cvm::debug())
808 cvmodule->log("Remapping done.\n");
809 }
810
813 void add_grid(colvar_grid<T> const &other_grid,
814 cvm::real scale_factor = 1.0)
815 {
816 if (other_grid.multiplicity() != this->multiplicity()) {
817 cvm::error_static("Error: trying to sum togetehr two grids with values of "
818 "different multiplicity.\n");
819 return;
820 }
821 if (scale_factor != 1.0)
822 for (size_t i = 0; i < data.size(); i++) {
823 data[i] += static_cast<T>(scale_factor * other_grid.data[i]);
824 }
825 else
826 // skip multiplication if possible
827 for (size_t i = 0; i < data.size(); i++) {
828 data[i] += other_grid.data[i];
829 }
830 has_data = true;
831 }
832
835 virtual T value_output(std::vector<int> const &ix,
836 size_t const &imult = 0) const
837 {
838 return value(ix, imult);
839 }
840
844 virtual void value_input(std::vector<int> const &ix,
845 T const &t,
846 size_t const &imult = 0,
847 bool add = false)
848 {
849 if ( add )
850 data[address(ix) + imult] += t;
851 else
852 data[address(ix) + imult] = t;
853 has_data = true;
854 }
855
856
857 // /// Get the pointer to the binned value indexed by ix
858 // inline T const *value_p (std::vector<int> const &ix)
859 // {
860 // return &(data[address (ix)]);
861 // }
862
865 inline std::vector<int> const new_index() const
866 {
867 return std::vector<int> (nd, 0);
868 }
869
872 inline bool index_ok(std::vector<int> const &ix) const
873 {
874 for (size_t i = 0; i < nd; i++) {
875 if ( (ix[i] < 0) || (ix[i] >= int(nx[i])) )
876 return false;
877 }
878 return true;
879 }
880
883 inline void incr(std::vector<int> &ix) const
884 {
885 for (int i = ix.size()-1; i >= 0; i--) {
886
887 ix[i]++;
888
889 if (ix[i] >= nx[i]) {
890
891 if (i > 0) {
892 ix[i] = 0;
893 continue;
894 } else {
895 // this is the last iteration, a non-valid index is being
896 // set for the outer index, which will be caught by
897 // index_ok()
898 ix[0] = nx[0];
899 return;
900 }
901 } else {
902 return;
903 }
904 }
905 }
906
908 std::string get_state_params() const;
909
911 int parse_params(std::string const &conf,
913
918 {
919 for (size_t i = 0; i < nd; i++) {
920 if ( (cvm::sqrt(cv[i]->dist2(cv[i]->lower_boundary,
921 lower_boundaries[i])) > 1.0E-10) ||
922 (cvm::sqrt(cv[i]->dist2(cv[i]->upper_boundary,
923 upper_boundaries[i])) > 1.0E-10) ||
924 (cvm::sqrt(cv[i]->dist2(cv[i]->width,
925 widths[i])) > 1.0E-10) ) {
926 cvm::error_static("Error: restart information for a grid is "
927 "inconsistent with that of its colvars.\n");
928 return;
929 }
930 }
931 }
932
933
936 void check_consistency(colvar_grid<T> const &other_grid)
937 {
938 for (size_t i = 0; i < nd; i++) {
939 // we skip dist2(), because periodicities and the like should
940 // matter: boundaries should be EXACTLY the same (otherwise,
941 // map_grid() should be used)
942 if ( (cvm::fabs(other_grid.lower_boundaries[i] -
943 lower_boundaries[i]) > 1.0E-10) ||
944 (cvm::fabs(other_grid.upper_boundaries[i] -
945 upper_boundaries[i]) > 1.0E-10) ||
946 (cvm::fabs(other_grid.widths[i] -
947 widths[i]) > 1.0E-10) ||
948 (data.size() != other_grid.data.size()) ) {
949 cvm::error_static("Error: inconsistency between "
950 "two grids that are supposed to be equal, "
951 "aside from the data stored.\n");
952 return;
953 }
954 }
955 }
956
958 std::istream & read_restart(std::istream &is);
959
962
964 std::ostream & write_restart(std::ostream &os);
965
968
970 std::istream &read_raw(std::istream &is);
971
974
975private:
976
978 template <class IST> IST& read_restart_template_(IST& is);
979
981 template <class IST> IST& read_raw_template_(IST& is);
982
983public:
984
988 std::ostream &write_raw(std::ostream &os, size_t const buf_size = 3) const;
989
993 cvm::memory_stream &write_raw(cvm::memory_stream &os, size_t const buf_size = 3) const;
994
996 std::istream & read_multicol(std::istream &is, bool add = false);
997
999 int read_multicol(std::string const &filename,
1000 std::string description = "grid file",
1001 bool add = false);
1002
1004 std::ostream & write_multicol(std::ostream &os) const;
1005
1007 int write_multicol(std::string const &filename,
1008 std::string description = "grid file") const;
1009
1011 std::ostream & write_opendx(std::ostream &os) const;
1012
1014 int write_opendx(std::string const &filename,
1015 std::string description = "grid file") const;
1016};
1017
1018
1019
1022class colvar_grid_count : public colvar_grid<size_t>
1023{
1024public:
1025
1028
1031 {}
1032
1034 colvar_grid_count(std::vector<colvar *> &colvars,
1035 std::shared_ptr<const colvar_grid_params> params = nullptr);
1036
1037 colvar_grid_count(std::vector<colvar *> &colvars,
1038 std::string config);
1039
1042 colvar_grid_count(std::string &filename);
1043
1045 inline void incr_count(std::vector<int> const &ix)
1046 {
1047 ++(data[this->address(ix)]);
1048 }
1049
1051 inline size_t const & new_value(std::vector<int> const &ix)
1052 {
1053 return new_data[address(ix)];
1054 }
1055
1057 std::string get_state_params() const;
1058
1060 int parse_params(std::string const &conf,
1062
1064 std::istream & read_restart(std::istream &is);
1065
1068
1070 std::ostream & write_restart(std::ostream &os);
1071
1074
1076 std::istream &read_raw(std::istream &is);
1077
1080
1084 std::ostream &write_raw(std::ostream &os, size_t const buf_size = 3) const;
1085
1089 cvm::memory_stream &write_raw(cvm::memory_stream &os, size_t const buf_size = 3) const;
1090
1092 std::istream & read_multicol(std::istream &is, bool add = false);
1093
1095 int read_multicol(std::string const &filename,
1096 std::string description = "grid file",
1097 bool add = false);
1098
1100 std::ostream & write_multicol(std::ostream &os) const;
1101
1103 int write_multicol(std::string const &filename,
1104 std::string description = "grid file") const;
1105
1107 std::ostream & write_opendx(std::ostream &os) const;
1108
1110 int write_opendx(std::string const &filename,
1111 std::string description = "grid file") const;
1112
1114 virtual void value_input(std::vector<int> const &ix,
1115 size_t const &t,
1116 size_t const &imult = 0,
1117 bool add = false)
1118 {
1119 (void) imult;
1120 if (add) {
1121 data[address(ix)] += t;
1122 if (this->has_parent_data) {
1123 // save newly read data for inputting parent grid
1124 new_data[address(ix)] = t;
1125 }
1126 } else {
1127 data[address(ix)] = t;
1128 }
1129 has_data = true;
1130 }
1131
1134 inline int local_sample_count(int radius)
1135 {
1136 std::vector<int> ix0 = new_index();
1137 std::vector<int> ix = new_index();
1138
1139 for (size_t i = 0; i < nd; i++) {
1140 ix0[i] = current_bin_scalar_bound(i);
1141 }
1142 if (radius < 1) {
1143 // Simple case: no averaging
1144 if (index_ok(ix0))
1145 return value(ix0);
1146 else
1147 return 0;
1148 }
1149 size_t count = 0;
1150 size_t nbins = 0;
1151 int i, j, k;
1152 bool edge;
1153 ix = ix0;
1154 // Treat each dimension separately to simplify code
1155 switch (nd)
1156 {
1157 case 1:
1158 for (i = -radius; i <= radius; i++) {
1159 ix[0] = ix0[0] + i;
1160 edge = wrap_detect_edge(ix);
1161 if (!edge) {
1162 nbins++;
1163 count += value(ix);
1164 }
1165 }
1166 break;
1167 case 2:
1168 for (i = -radius; i <= radius; i++) {
1169 ix[0] = ix0[0] + i;
1170 for (j = -radius; j <= radius; j++) {
1171 ix[1] = ix0[1] + j;
1172 edge = wrap_detect_edge(ix);
1173 if (!edge) {
1174 nbins++;
1175 count += value(ix);
1176 }
1177 }
1178 }
1179 break;
1180 case 3:
1181 for (i = -radius; i <= radius; i++) {
1182 ix[0] = ix0[0] + i;
1183 for (j = -radius; j <= radius; j++) {
1184 ix[1] = ix0[1] + j;
1185 for (k = -radius; k <= radius; k++) {
1186 ix[2] = ix0[2] + k;
1187 edge = wrap_detect_edge(ix);
1188 if (!edge) {
1189 nbins++;
1190 count += value(ix);
1191 }
1192 }
1193 }
1194 }
1195 break;
1196 default:
1197 cvm::error_static("Error: local_sample_count is not implemented for grids of dimension > 3", COLVARS_NOT_IMPLEMENTED);
1198 break;
1199 }
1200
1201 if (nbins)
1202 // Integer division - an error on the order of 1 doesn't matter
1203 return count / nbins;
1204 else
1205 return 0.0;
1206 }
1207
1208
1212 inline cvm::real log_gradient_finite_diff(const std::vector<int> &ix0,
1213 int n = 0, int offset = 0)
1214 {
1215 cvm::real Am1, A0, A1, A2; // values at locations -1, 0, +1, +2
1216 std::vector<int> ix = ix0;
1217
1218 // TODO this can be rewritten more concisely with wrap_edge()
1219 if (periodic[n]) {
1220 ix[n]--; wrap(ix);
1221 Am1 = value(ix) + offset;
1222 ix = ix0; wrap(ix);
1223 A0 = value(ix) + offset; // Used just to detect gaps
1224 ix[n]++; wrap(ix);
1225 A1 = value(ix) + offset;
1226 if (Am1 * A0 * A1 == 0) {
1227 return 0.; // can't handle 0, and don't compute derivative over a gap
1228 } else {
1229 return (cvmodule->logn(A1) - cvmodule->logn(Am1))
1230 / (widths[n] * 2.);
1231 }
1232 } else if (ix[n] > 0 && ix[n] < nx[n]-1) { // not an edge
1233 ix[n]--;
1234 Am1 = value(ix) + offset;
1235 ix = ix0;
1236 A0 = value(ix) + offset;
1237 ix[n]++;
1238 A1 = value(ix) + offset;
1239 if (Am1 * A0 * A1 == 0) {
1240 return 0.; // can't handle 0, and don't compute derivative over a gap
1241 } else {
1242 return (cvmodule->logn(A1) - cvmodule->logn(Am1))
1243 / (widths[n] * 2.);
1244 }
1245 } else {
1246 // edge: use 2nd order derivative
1247 int increment = (ix[n] == 0 ? 1 : -1);
1248 // move right from left edge, or the other way around
1249 A0 = value(ix) + offset;
1250 ix[n] += increment; A1 = value(ix) + offset;
1251 ix[n] += increment; A2 = value(ix) + offset;
1252 if (A0 * A1 * A2 == 0) {
1253 return 0.; // can't handle 0
1254 } else {
1255 return (-1.5 * cvmodule->logn(A0) + 2. * cvmodule->logn(A1)
1256 - 0.5 * cvmodule->logn(A2)) * increment / widths[n];
1257 }
1258 }
1259 }
1260
1261
1265 inline cvm::real gradient_finite_diff(const std::vector<int> &ix0,
1266 int n = 0)
1267 {
1268 cvm::real Am1, A0, A1, A2;
1269 std::vector<int> ix = ix0;
1270
1271 // FIXME this can be rewritten more concisely with wrap_edge()
1272 if (periodic[n]) {
1273 ix[n]--; wrap(ix);
1274 Am1 = value(ix);
1275 ix = ix0; wrap(ix);
1276 A0 = value(ix); // Used just to detect gaps
1277 ix[n]++; wrap(ix);
1278 A1 = value(ix);
1279 if (Am1 * A0 * A1 == 0) {
1280 return 0.; // can't handle empty bins
1281 } else {
1282 return (A1 - Am1) / (widths[n] * 2.);
1283 }
1284 } else if (ix[n] > 0 && ix[n] < nx[n]-1) { // not an edge
1285 ix[n]--;
1286 Am1 = value(ix);
1287 ix = ix0;
1288 A0 = value(ix);
1289 ix[n]++;
1290 A1 = value(ix);
1291 if (Am1 * A0 * A1 == 0) {
1292 return 0.; // can't handle empty bins
1293 } else {
1294 return (A1 - Am1) / (widths[n] * 2.);
1295 }
1296 } else {
1297 // edge: use 2nd order derivative
1298 int increment = (ix[n] == 0 ? 1 : -1);
1299 // move right from left edge, or the other way around
1300 A0 = value(ix);
1301 ix[n] += increment; A1 = value(ix);
1302 ix[n] += increment; A2 = value(ix);
1303 return (-1.5 * A0 + 2. * A1
1304 - 0.5 * A2) * increment / widths[n];
1305 }
1306 }
1307};
1308
1309
1311class colvar_grid_scalar : public colvar_grid<cvm::real>
1312{
1313public:
1314
1317 std::shared_ptr<colvar_grid_count> samples;
1318
1321
1324
1326 virtual ~colvar_grid_scalar();
1327
1329 colvar_grid_scalar(std::vector<colvar *> &colvars,
1330 std::shared_ptr<const colvar_grid_params> params = nullptr,
1331 bool add_extra_bin = false,
1332 std::string config = std::string());
1333
1335 colvar_grid_scalar(std::string const &filename);
1336
1338 inline void acc_value(std::vector<int> const &ix,
1339 cvm::real const &new_value,
1340 size_t const &imult = 0)
1341 {
1342 (void) imult;
1343 // only legal value of imult here is 0
1344 data[address(ix)] += new_value;
1345 if (samples)
1346 samples->incr_count(ix);
1347 has_data = true;
1348 }
1349
1351 std::string get_state_params() const;
1352
1354 int parse_params(std::string const &conf,
1356
1358 std::istream & read_restart(std::istream &is);
1359
1362
1364 std::ostream & write_restart(std::ostream &os);
1365
1368
1370 std::istream &read_raw(std::istream &is);
1371
1374
1378 std::ostream &write_raw(std::ostream &os, size_t const buf_size = 3) const;
1379
1383 cvm::memory_stream &write_raw(cvm::memory_stream &os, size_t const buf_size = 3) const;
1384
1386 std::istream & read_multicol(std::istream &is, bool add = false);
1387
1389 int read_multicol(std::string const &filename,
1390 std::string description = "grid file",
1391 bool add = false);
1392
1394 std::ostream & write_multicol(std::ostream &os) const;
1395
1397 int write_multicol(std::string const &filename,
1398 std::string description = "grid file") const;
1399
1401 std::ostream & write_opendx(std::ostream &os) const;
1402
1404 int write_opendx(std::string const &filename,
1405 std::string description = "grid file") const;
1406
1411 inline void vector_gradient_finite_diff( const std::vector<int> &ix0, std::vector<cvm::real> &grad)
1412 {
1413 cvm::real A0, A1;
1414 std::vector<int> ix;
1415 size_t i, j, k, n;
1416
1417 if (nd == 2) {
1418 for (n = 0; n < 2; n++) {
1419 ix = ix0;
1420 A0 = value(ix);
1421 ix[n]++; wrap(ix);
1422 A1 = value(ix);
1423 ix[1-n]++; wrap(ix);
1424 A1 += value(ix);
1425 ix[n]--; wrap(ix);
1426 A0 += value(ix);
1427 grad[n] = 0.5 * (A1 - A0) / widths[n];
1428 }
1429 } else if (nd == 3) {
1430
1431 cvm::real p[8]; // potential values within cube, indexed in binary (4 i + 2 j + k)
1432 ix = ix0;
1433 int index = 0;
1434 for (i = 0; i<2; i++) {
1435 ix[1] = ix0[1];
1436 for (j = 0; j<2; j++) {
1437 ix[2] = ix0[2];
1438 for (k = 0; k<2; k++) {
1439 wrap(ix);
1440 p[index++] = value(ix);
1441 ix[2]++;
1442 }
1443 ix[1]++;
1444 }
1445 ix[0]++;
1446 }
1447
1448 // The following would be easier to read using binary literals
1449 // 100 101 110 111 000 001 010 011
1450 grad[0] = 0.25 * ((p[4] + p[5] + p[6] + p[7]) - (p[0] + p[1] + p[2] + p[3])) / widths[0];
1451 // 010 011 110 111 000 001 100 101
1452 grad[1] = 0.25 * ((p[2] + p[3] + p[6] + p[7]) - (p[0] + p[1] + p[4] + p[5])) / widths[1];
1453 // 001 011 101 111 000 010 100 110
1454 grad[2] = 0.25 * ((p[1] + p[3] + p[5] + p[7]) - (p[0] + p[2] + p[4] + p[6])) / widths[2];
1455 } else {
1456 cvm::error_static("Finite differences available in dimension 2 and 3 only.");
1457 }
1458 }
1459
1460
1464 inline cvm::real log_gradient_finite_diff(const std::vector<int> &ix0,
1465 int n = 0, int offset = 0)
1466 {
1467 cvm::real A0, A1, A2;
1468 std::vector<int> ix = ix0;
1469
1470 // TODO this can be rewritten more concisely with wrap_edge()
1471 if (periodic[n]) {
1472 ix[n]--; wrap(ix);
1473 A0 = value(ix) + offset;
1474 ix = ix0;
1475 ix[n]++; wrap(ix);
1476 A1 = value(ix) + offset;
1477 if (A0 * A1 == 0) {
1478 return 0.; // can't handle empty bins
1479 } else {
1480 return (cvmodule->logn(A1) - cvmodule->logn(A0))
1481 / (widths[n] * 2.);
1482 }
1483 } else if (ix[n] > 0 && ix[n] < nx[n]-1) { // not an edge
1484 ix[n]--;
1485 A0 = value(ix) + offset;
1486 ix = ix0;
1487 ix[n]++;
1488 A1 = value(ix) + offset;
1489 if (A0 * A1 == 0) {
1490 return 0.; // can't handle empty bins
1491 } else {
1492 return (cvmodule->logn(A1) - cvmodule->logn(A0))
1493 / (widths[n] * 2.);
1494 }
1495 } else {
1496 // edge: use 2nd order derivative
1497 int increment = (ix[n] == 0 ? 1 : -1);
1498 // move right from left edge, or the other way around
1499 A0 = value(ix) + offset;
1500 ix[n] += increment; A1 = value(ix) + offset;
1501 ix[n] += increment; A2 = value(ix) + offset;
1502 if (A0 * A1 * A2 == 0) {
1503 return 0.; // can't handle empty bins
1504 } else {
1505 return (-1.5 * cvmodule->logn(A0) + 2. * cvmodule->logn(A1)
1506 - 0.5 * cvmodule->logn(A2)) * increment / widths[n];
1507 }
1508 }
1509 }
1510
1511
1515 inline cvm::real gradient_finite_diff(const std::vector<int> &ix0,
1516 int n = 0)
1517 {
1518 cvm::real Am1, A0, A1, A2;
1519 std::vector<int> ix = ix0;
1520
1521 // FIXME this can be rewritten more concisely with wrap_edge()
1522 if (periodic[n]) {
1523 ix[n]--; wrap(ix);
1524 Am1 = value(ix);
1525 ix = ix0; wrap(ix);
1526 A0 = value(ix); // Used just to detect gaps
1527 ix[n]++; wrap(ix);
1528 A1 = value(ix);
1529 if (Am1 * A0 * A1 == 0) {
1530 return 0.; // can't handle empty bins
1531 } else {
1532 return (A1 - Am1) / (widths[n] * 2.);
1533 }
1534 } else if (ix[n] > 0 && ix[n] < nx[n]-1) { // not an edge
1535 ix[n]--;
1536 Am1 = value(ix);
1537 ix = ix0;
1538 A0 = value(ix);
1539 ix[n]++;
1540 A1 = value(ix);
1541 if (Am1 * A0 * A1 == 0) {
1542 return 0.; // can't handle empty bins
1543 } else {
1544 return (A1 - Am1) / (widths[n] * 2.);
1545 }
1546 } else {
1547 // edge: use 2nd order derivative
1548 int increment = (ix[n] == 0 ? 1 : -1);
1549 // move right from left edge, or the other way around
1550 A0 = value(ix);
1551 ix[n] += increment; A1 = value(ix);
1552 ix[n] += increment; A2 = value(ix);
1553 return (-1.5 * A0 + 2. * A1
1554 - 0.5 * A2) * increment / widths[n];
1555 }
1556 }
1557
1558
1561 virtual inline cvm::real value_output(std::vector<int> const &ix,
1562 size_t const &imult = 0) const override
1563 {
1564 int s;
1565 if (imult > 0) {
1566 cvm::error_static("Error: trying to access a component "
1567 "larger than 1 in a scalar data grid.\n");
1568 return 0.;
1569 }
1570 if (samples) {
1571 return ( (s = samples->value(ix)) > 0) ?
1572 (data[address(ix) + imult] / cvm::real(s)) :
1573 0.0;
1574 } else {
1575 return data[address(ix) + imult];
1576 }
1577 }
1578
1580 virtual void value_input(std::vector<int> const &ix,
1581 cvm::real const &new_value,
1582 size_t const &imult = 0,
1583 bool add = false) override
1584 {
1585 if (imult > 0) {
1586 cvm::error_static("Error: trying to access a component "
1587 "larger than 1 in a scalar data grid.\n");
1588 return;
1589 }
1590 if (add) {
1591 if (samples)
1592 // Special case if samples == 0 and value != 0
1593 data[address(ix)] += new_value * samples->new_value(ix);
1594 else
1595 data[address(ix)] += new_value;
1596 } else {
1597 if (samples)
1598 data[address(ix)] = new_value * samples->value(ix);
1599 else
1600 data[address(ix)] = new_value;
1601 }
1602 has_data = true;
1603 }
1604
1606 cvm::real maximum_value() const;
1607
1609 cvm::real minimum_value() const;
1610
1613
1615 cvm::real integral() const;
1616
1619 cvm::real entropy() const;
1620
1623 cvm::real grid_rmsd(colvar_grid_scalar const &other_grid) const;
1624};
1625
1626
1627
1629class colvar_grid_gradient : public colvar_grid<cvm::real>
1630{
1631public:
1632
1635 std::shared_ptr<colvar_grid_count> samples;
1636
1639
1642 {}
1643
1644 // /// Constructor from specific sizes arrays
1645 // colvar_grid_gradient(std::vector<int> const &nx_i);
1646
1647 // /// Constructor from a vector of colvars
1648 // colvar_grid_gradient(std::vector<colvar *> &colvars,
1649 // std::string config = std::string());
1650
1652 colvar_grid_gradient(std::string const &filename, std::shared_ptr<colvar_grid_count> samples_in = nullptr);
1653
1655 colvar_grid_gradient(std::vector<colvar *> &colvars,
1656 std::shared_ptr<colvar_grid_count> samples_in = nullptr,
1657 std::shared_ptr<const colvar_grid_params> params = nullptr,
1658 std::string config = std::string());
1659
1662 int min_samples;
1663
1665 std::string get_state_params() const;
1666
1668 int parse_params(std::string const &conf,
1670
1672 std::istream & read_restart(std::istream &is);
1673
1676
1678 std::ostream & write_restart(std::ostream &os);
1679
1682
1684 std::istream &read_raw(std::istream &is);
1685
1688
1692 std::ostream &write_raw(std::ostream &os, size_t const buf_size = 3) const;
1693
1697 cvm::memory_stream &write_raw(cvm::memory_stream &os, size_t const buf_size = 3) const;
1698
1700 std::istream & read_multicol(std::istream &is, bool add = false);
1701
1703 int read_multicol(std::string const &filename,
1704 std::string description = "grid file",
1705 bool add = false);
1706
1708 std::ostream & write_multicol(std::ostream &os) const;
1709
1711 int write_multicol(std::string const &filename,
1712 std::string description = "grid file") const;
1713
1715 std::ostream & write_opendx(std::ostream &os) const;
1716
1718 int write_opendx(std::string const &filename,
1719 std::string description = "grid file") const;
1720
1722 inline void vector_value(std::vector<int> const &ix, std::vector<cvm::real> &v) const
1723 {
1724 cvm::real const * p = &value(ix);
1725 if (samples) {
1726 int count = samples->value(ix);
1727 if (count) {
1728 cvm::real invcount = 1.0 / count;
1729 for (size_t i = 0; i < mult; i++) {
1730 v[i] = invcount * p[i];
1731 }
1732 } else {
1733 for (size_t i = 0; i < mult; i++) {
1734 v[i] = 0.0;
1735 }
1736 }
1737 } else {
1738 for (size_t i = 0; i < mult; i++) {
1739 v[i] = p[i];
1740 }
1741 }
1742 }
1743
1744
1746 inline void acc_value(std::vector<int> const &ix, std::vector<colvarvalue> const &values) {
1747 for (size_t imult = 0; imult < mult; imult++) {
1748 data[address(ix) + imult] += values[imult].real_value;
1749 }
1750 if (samples)
1751 samples->incr_count(ix);
1752 }
1753
1756 inline void acc_force(std::vector<int> const &ix, cvm::real const *forces) {
1757 for (size_t imult = 0; imult < mult; imult++) {
1758 data[address(ix) + imult] -= forces[imult];
1759 }
1760 if (samples)
1761 samples->incr_count(ix);
1762 }
1763
1766 virtual cvm::real value_output(std::vector<int> const &ix,
1767 size_t const &imult = 0) const override
1768 {
1769 int s;
1770 if (samples) {
1771 return ( (s = samples->value(ix)) > 0) ?
1772 (data[address(ix) + imult] / cvm::real(s)) :
1773 0.0;
1774 } else {
1775 return data[address(ix) + imult];
1776 }
1777 }
1778
1782 {
1783 cvm::real fact;
1784 if ( weight <= min_samples ) {
1785 fact = 0.0;
1786 } else if ( weight < full_samples ) {
1787 fact = (weight - min_samples) / (weight * cvm::real(full_samples - min_samples));
1788 } else {
1789 fact = 1.0 / weight;
1790 }
1791 return fact;
1792 }
1793
1794
1799 virtual inline cvm::real value_output_smoothed(std::vector<int> const &ix, bool smoothed = true)
1800 {
1801 cvm::real weight, fact;
1802
1803 if (samples) {
1804 weight = cvm::real(samples->value(ix));
1805 } else {
1806 weight = 1.;
1807 }
1808
1809 if (smoothed) {
1810 fact = smooth_inverse_weight(weight);
1811 } else {
1812 fact = weight > 0. ? 1. / weight : 0.;
1813 }
1814
1815 return fact * data[address(ix)];
1816 }
1817
1818
1822 inline void vector_value_smoothed(std::vector<int> const &ix, cvm::real *grad, bool smoothed = true)
1823 {
1824 cvm::real weight, fact;
1825
1826 if (samples) {
1827 weight = cvm::real(samples->value(ix));
1828 } else {
1829 weight = 1.;
1830 }
1831
1832 if (smoothed) {
1833 fact = smooth_inverse_weight(weight);
1834 } else {
1835 fact = weight > 0. ? 1. / weight : 0.;
1836 }
1837 cvm::real *p = &(data[address(ix)]);
1838
1839 for (size_t imult = 0; imult < mult; imult++) {
1840 grad[imult] = fact * p[imult];
1841 }
1842 }
1843
1847 virtual void value_input(std::vector<int> const &ix,
1848 cvm::real const &new_value,
1849 size_t const &imult = 0,
1850 bool add = false) override
1851 {
1852 if (add) {
1853 if (samples)
1854 data[address(ix) + imult] += new_value * samples->new_value(ix);
1855 else
1856 data[address(ix) + imult] += new_value;
1857 } else {
1858 if (samples)
1859 data[address(ix) + imult] = new_value * samples->value(ix);
1860 else
1861 data[address(ix) + imult] = new_value;
1862 }
1863 has_data = true;
1864 }
1865
1866
1868 inline cvm::real average(bool smoothed = false)
1869 {
1870 if (nd != 1 || nx[0] == 0) {
1871 return 0.0;
1872 }
1873
1874 cvm::real sum = 0.0;
1875 for (std::vector<int> ix = new_index(); index_ok(ix); incr(ix)) {
1876 sum += value_output_smoothed(ix, smoothed);
1877 }
1878
1879 return (sum / cvm::real(nx[0]));
1880 }
1881
1884 cvm::real grid_rmsd(colvar_grid_gradient const &other_grid) const;
1885
1888 void write_1D_integral(std::ostream &os);
1889
1890};
1891
1892 #endif
Colvar_grid derived class to hold counters in discrete n-dim colvar space.
Definition: colvargrid.h:1023
colvar_grid_count()
Default constructor.
int local_sample_count(int radius)
Return the average number of samples in a given "radius" around current bin Really a hypercube of len...
Definition: colvargrid.h:1134
std::istream & read_raw(std::istream &is)
Read all grid parameters and data from a formatted stream.
Definition: colvargrid.cpp:64
std::string get_state_params() const
Write the current grid parameters to a string.
Definition: colvargrid.cpp:33
cvm::real gradient_finite_diff(const std::vector< int > &ix0, int n=0)
Return the gradient of discrete count from finite differences on the same grid for dimension n (colva...
Definition: colvargrid.h:1265
std::ostream & write_restart(std::ostream &os)
Write all grid parameters and data to a formatted stream.
Definition: colvargrid.cpp:54
std::ostream & write_opendx(std::ostream &os) const
Write the grid data without labels, as they are represented in memory.
Definition: colvargrid.cpp:108
std::ostream & write_raw(std::ostream &os, size_t const buf_size=3) const
Definition: colvargrid.cpp:74
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.cpp:38
virtual void value_input(std::vector< int > const &ix, size_t const &t, size_t const &imult=0, bool add=false)
Enter or add a value, but also handle parent grid.
Definition: colvargrid.h:1114
std::istream & read_restart(std::istream &is)
Read all grid parameters and data from a formatted stream.
Definition: colvargrid.cpp:44
std::istream & read_multicol(std::istream &is, bool add=false)
Read a grid written by write_multicol(), incrementin if data is true.
Definition: colvargrid.cpp:85
std::ostream & write_multicol(std::ostream &os) const
Write grid in a format which is both human-readable and gnuplot-friendly.
Definition: colvargrid.cpp:97
cvm::real log_gradient_finite_diff(const std::vector< int > &ix0, int n=0, int offset=0)
Return the log-gradient from finite differences on the same grid for dimension n Order-1 centered dif...
Definition: colvargrid.h:1212
size_t const & new_value(std::vector< int > const &ix)
Get the binned count indexed by ix from the newly read data.
Definition: colvargrid.h:1051
virtual ~colvar_grid_count()
Destructor.
Definition: colvargrid.h:1030
void incr_count(std::vector< int > const &ix)
Increment the counter at given position.
Definition: colvargrid.h:1045
Class for accumulating the gradient of a scalar function on a grid.
Definition: colvargrid.h:1630
std::string get_state_params() const
Write the current grid parameters to a string.
Definition: colvargrid.cpp:361
cvm::real smooth_inverse_weight(cvm::real weight)
Definition: colvargrid.h:1781
void vector_value_smoothed(std::vector< int > const &ix, cvm::real *grad, bool smoothed=true)
Obtain the vector value of the function at ix divided by its number of samples (if the count grid is ...
Definition: colvargrid.h:1822
virtual cvm::real value_output_smoothed(std::vector< int > const &ix, bool smoothed=true)
Return the scalar value of the function at ix divided by its number of samples (if the count grid is ...
Definition: colvargrid.h:1799
void acc_value(std::vector< int > const &ix, std::vector< colvarvalue > const &values)
Accumulate the value.
Definition: colvargrid.h:1746
cvm::real average(bool smoothed=false)
Compute and return average value for a 1D gradient grid.
Definition: colvargrid.h:1868
std::shared_ptr< colvar_grid_count > samples
Provide the sample count by which each binned value should be divided.
Definition: colvargrid.h:1635
std::istream & read_multicol(std::istream &is, bool add=false)
Read a grid written by write_multicol(), incrementin if data is true.
Definition: colvargrid.cpp:413
colvar_grid_gradient()
Default constructor.
Definition: colvargrid.cpp:331
std::ostream & write_restart(std::ostream &os)
Write all grid parameters and data to a formatted stream.
Definition: colvargrid.cpp:382
void write_1D_integral(std::ostream &os)
If the grid is 1-dimensional, integrate it and write the integral to a file (DEPRECATED by the colvar...
Definition: colvargrid.cpp:448
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.cpp:366
virtual cvm::real value_output(std::vector< int > const &ix, size_t const &imult=0) const override
Return the value of the function at ix divided by its number of samples (if the count grid is defined...
Definition: colvargrid.h:1766
std::istream & read_raw(std::istream &is)
Read all grid parameters and data from a formatted stream.
Definition: colvargrid.cpp:392
virtual ~colvar_grid_gradient()
Destructor.
Definition: colvargrid.h:1641
virtual void value_input(std::vector< int > const &ix, cvm::real const &new_value, size_t const &imult=0, bool add=false) override
Get the value from a formatted output and transform it into the internal representation (it may have ...
Definition: colvargrid.h:1847
void acc_force(std::vector< int > const &ix, cvm::real const *forces)
Accumulate the gradient based on the force (i.e. sums the opposite of the force)
Definition: colvargrid.h:1756
int full_samples
Parameters for smoothing data with low sampling.
Definition: colvargrid.h:1661
std::ostream & write_raw(std::ostream &os, size_t const buf_size=3) const
Definition: colvargrid.cpp:402
std::ostream & write_multicol(std::ostream &os) const
Write grid in a format which is both human-readable and gnuplot-friendly.
Definition: colvargrid.cpp:425
std::istream & read_restart(std::istream &is)
Read all grid parameters and data from a formatted stream.
Definition: colvargrid.cpp:372
cvm::real grid_rmsd(colvar_grid_gradient const &other_grid) const
Return the RMSD between this grid's data and another one Grids must have the same dimensions.
Definition: colvargrid.cpp:502
void vector_value(std::vector< int > const &ix, std::vector< cvm::real > &v) const
Get a vector with the binned value(s) indexed by ix, normalized if applicable.
Definition: colvargrid.h:1722
std::ostream & write_opendx(std::ostream &os) const
Write the grid data without labels, as they are represented in memory.
Definition: colvargrid.cpp:436
Unified base class for grid of values of a function of several collective variables.
Definition: colvargrid.h:24
size_t nd
Number of dimensions.
Definition: colvargrid.h:28
std::vector< int > nxc
Cumulative number of points along each dimension.
Definition: colvargrid.h:34
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
std::vector< colvarvalue > upper_boundaries
Upper boundaries of the colvars in this grid.
Definition: colvargrid.h:40
std::vector< int > nx
Number of points along each dimension.
Definition: colvargrid.h:31
Class for accumulating a scalar function on a grid.
Definition: colvargrid.h:1312
void acc_value(std::vector< int > const &ix, cvm::real const &new_value, size_t const &imult=0)
Accumulate the value.
Definition: colvargrid.h:1338
cvm::real minimum_value() const
Return the lowest value.
Definition: colvargrid.cpp:245
cvm::real gradient_finite_diff(const std::vector< int > &ix0, int n=0)
Return the gradient of discrete count from finite differences on the same grid for dimension n (colva...
Definition: colvargrid.h:1515
std::istream & read_restart(std::istream &is)
Read all grid parameters and data from a formatted stream.
Definition: colvargrid.cpp:159
std::string get_state_params() const
Write the current grid parameters to a string.
Definition: colvargrid.cpp:148
virtual ~colvar_grid_scalar()
Destructor.
Definition: colvargrid.cpp:144
cvm::real minimum_pos_value() const
Return the lowest positive value.
Definition: colvargrid.cpp:254
virtual cvm::real value_output(std::vector< int > const &ix, size_t const &imult=0) const override
Return the value of the function at ix divided by its number of samples (if the count grid is defined...
Definition: colvargrid.h:1561
cvm::real grid_rmsd(colvar_grid_scalar const &other_grid) const
Return the RMSD between this grid's data and another one Grids must have the same dimensions.
Definition: colvargrid.cpp:301
std::ostream & write_opendx(std::ostream &os) const
Write the grid data without labels, as they are represented in memory.
Definition: colvargrid.cpp:223
std::ostream & write_restart(std::ostream &os)
Write all grid parameters and data to a formatted stream.
Definition: colvargrid.cpp:169
std::ostream & write_multicol(std::ostream &os) const
Write grid in a format which is both human-readable and gnuplot-friendly.
Definition: colvargrid.cpp:212
std::istream & read_multicol(std::istream &is, bool add=false)
Read a grid written by write_multicol(), incrementin if data is true.
Definition: colvargrid.cpp:200
cvm::real integral() const
Calculates the integral of the map (uses widths if they are defined)
Definition: colvargrid.cpp:270
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.cpp:153
std::shared_ptr< colvar_grid_count > samples
Provide the associated sample count by which each binned value should be divided.
Definition: colvargrid.h:1317
std::ostream & write_raw(std::ostream &os, size_t const buf_size=3) const
Definition: colvargrid.cpp:189
virtual void value_input(std::vector< int > const &ix, cvm::real const &new_value, size_t const &imult=0, bool add=false) override
Enter or add value but also deal with count grid.
Definition: colvargrid.h:1580
cvm::real entropy() const
Assuming that the map is a normalized probability density, calculates the entropy (uses widths if the...
Definition: colvargrid.cpp:284
colvar_grid_scalar()
Default constructor.
Definition: colvargrid.cpp:121
cvm::real maximum_value() const
Return the highest value.
Definition: colvargrid.cpp:235
cvm::real log_gradient_finite_diff(const std::vector< int > &ix0, int n=0, int offset=0)
Return the log-gradient from finite differences on the same grid for dimension n (colvar_grid_scalar)
Definition: colvargrid.h:1464
void vector_gradient_finite_diff(const std::vector< int > &ix0, std::vector< cvm::real > &grad)
Return the gradient of the scalar field from finite differences Input coordinates are those of gradie...
Definition: colvargrid.h:1411
std::istream & read_raw(std::istream &is)
Read all grid parameters and data from a formatted stream.
Definition: colvargrid.cpp:179
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:209
std::istream & read_restart(std::istream &is)
Read all grid parameters and data from a formatted stream.
Definition: colvargrid_def.h:102
void set_value(size_t i, T const &t)
Set the value at the point with linear address i (for speed)
Definition: colvargrid.h:580
void check_consistency()
Check that the grid information inside (boundaries, widths, ...) is consistent with the current setti...
Definition: colvargrid.h:917
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
int current_bin_scalar_bound(int const i) const
Report the bin corresponding to the current value of variable i and assign first or last bin if out o...
Definition: colvargrid.h:500
std::vector< int > const new_index() const
Get the index corresponding to the "first" bin, to be used as the initial value for an index in loopi...
Definition: colvargrid.h:865
void add_constant(T const &t)
Add a constant to all elements (fast loop)
Definition: colvargrid.h:682
std::vector< size_t > new_data
Newly read data (used for count grids, when adding several grids read from disk)
Definition: colvargrid.h:68
cvm::real value_to_bin_scalar_fraction(colvarvalue const &value, const int i) const
Use the lower boundary and the width to report the fraction of bin beyond value_to_bin_scalar() that ...
Definition: colvargrid.h:528
void incr(std::vector< int > &ix) const
Increment the index, in a way that will make it loop over the whole nd-dimensional array.
Definition: colvargrid.h:883
size_t number_of_points(int const icv=-1) const
Definition: colvargrid.h:131
std::vector< bool > hard_upper_boundaries
Whether some colvars have hard upper boundaries.
Definition: colvargrid.h:109
virtual void value_input(std::vector< int > const &ix, T const &t, size_t const &imult=0, bool add=false)
Get the value from a formatted output and transform it into the internal representation (the two may ...
Definition: colvargrid.h:844
T const & value(size_t i) const
Get the binned value indexed by linear address i.
Definition: colvargrid.h:676
std::vector< int > const get_colvars_index_bound() const
Get the bin indices corresponding to the provided values of the colvars and assign first or last bin ...
Definition: colvargrid.h:728
int current_bin_flat_bound() const
Report the flattened bin address corresponding to the current value of all variables and assign first...
Definition: colvargrid.h:489
size_t mult
Multiplicity of each datum (allow the binning of non-scalar types such as atomic gradients)
Definition: colvargrid.h:59
size_t multiplicity() const
Return the multiplicity of the type used.
Definition: colvargrid.h:153
std::vector< int > const & sizes() const
Get the sizes in each direction.
Definition: colvargrid.h:141
void set_value(std::vector< int > const &ix, T const &t, size_t const &imult=0)
Set the value at the point with index ix.
Definition: colvargrid.h:571
colvarvalue bin_to_value_scalar(int const &i_bin, int const i) const
Use the two boundaries and the width to report the central value corresponding to a bin index.
Definition: colvargrid.h:557
std::vector< T > data
Low-level array of values.
Definition: colvargrid.h:65
void multiply_constant(cvm::real const &a)
Multiply all elements by a scalar constant (fast loop)
Definition: colvargrid.h:690
std::vector< int > const & number_of_points_vec() const
Return the numbers of points in all dimensions.
Definition: colvargrid.h:124
bool index_ok(std::vector< int > const &ix) const
Check that the index is within range in each of the dimensions.
Definition: colvargrid.h:872
cvm::real current_bin_scalar_fraction(int const i) const
Report the fraction of bin beyond current_bin_scalar()
Definition: colvargrid.h:521
bool has_data
Whether this grid has been filled with data or is still empty.
Definition: colvargrid.h:115
void add_grid(colvar_grid< T > const &other_grid, cvm::real scale_factor=1.0)
Add data from another grid of the same type, AND identical definition (boundaries,...
Definition: colvargrid.h:813
std::vector< int > const get_colvars_index(std::vector< colvarvalue > const &values) const
Get the bin indices corresponding to the provided values of the colvars.
Definition: colvargrid.h:706
void check_consistency(colvar_grid< T > const &other_grid)
Check that the grid information inside (boundaries, widths, ...) is consistent with that of another g...
Definition: colvargrid.h:936
colvar_grid(std::vector< int > const &nx_i, T const &t=T(), size_t mult_i=1)
Constructor from explicit grid sizes.
Definition: colvargrid.h:256
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
size_t nt
Total number of grid points.
Definition: colvargrid.h:62
T get_value(size_t i) const
Get the value at the point with linear address i (for speed)
Definition: colvargrid.h:586
void reset(T const &t=T())
Reset data (in case the grid is being reused)
Definition: colvargrid.h:215
size_t num_variables() const
Return the number of colvar objects.
Definition: colvargrid.h:118
int setup(std::vector< int > const &nx_i, T const &t=T(), size_t const &mult_i=1)
Allocate data.
Definition: colvargrid.h:168
IST & read_restart_template_(IST &is)
Helper method for read_restart.
Definition: colvargrid_def.h:84
colvar_grid(std::vector< colvar * > const &colvars, T const &t=T(), size_t mult_i=1, bool add_extra_bin=false, std::shared_ptr< const colvar_grid_params > params=nullptr, std::string config=std::string())
Constructor from a vector of colvars or an optional grid config string.
Definition: colvargrid.h:267
colvar_grid(colvar_grid< T > const &g)
"Almost copy-constructor": only copies configuration parameters from another grid,...
Definition: colvargrid.h:239
bool has_parent_data
True if this is a count grid related to another grid of data.
Definition: colvargrid.h:112
std::ostream & write_opendx(std::ostream &os) const
Write the grid data without labels, as they are represented in memory.
Definition: colvargrid_def.h:498
bool wrap_to_edge(std::vector< int > &ix, std::vector< int > &edge_bin) const
Definition: colvargrid.h:461
std::vector< int > const get_colvars_index() const
Get the bin indices corresponding to the current values of the colvars.
Definition: colvargrid.h:717
int current_bin_scalar(int const i, int const iv) const
Report the bin corresponding to the current value of item iv in variable i.
Definition: colvargrid.h:506
void delta_grid(colvar_grid< T > const &other_grid)
Get the change from this to other_grid and store the result in this. this_grid := other_grid - this_g...
Definition: colvargrid.h:596
void request_actual_value(bool b=true)
Request grid to use actual values of extended coords.
Definition: colvargrid.h:159
cvm::real bin_distance_from_boundaries(std::vector< colvarvalue > const &values, bool skip_hard_boundaries=false)
Get the minimal distance (in number of bins) from the boundaries; a negative number is returned if th...
Definition: colvargrid.h:740
int value_to_bin_scalar_bound(colvarvalue const &value, const int i) const
Use the lower boundary and the width to report which bin the provided value is in and assign first or...
Definition: colvargrid.h:536
int current_bin_scalar(int const i) const
Report the bin corresponding to the current value of variable i.
Definition: colvargrid.h:482
std::istream & read_raw(std::istream &is)
Read all grid parameters and data from a formatted stream.
Definition: colvargrid_def.h:157
std::vector< bool > hard_lower_boundaries
Whether some colvars have hard lower boundaries.
Definition: colvargrid.h:106
T const & value(std::vector< int > const &ix, size_t const &imult=0) const
Get the binned value indexed by ix, or the first of them if the multiplicity is larger than 1.
Definition: colvargrid.h:669
std::vector< bool > use_actual_value
Do we request actual value (for extended-system colvars)?
Definition: colvargrid.h:74
size_t raw_data_num() const
Size of the data as they are represented in memory.
Definition: colvargrid.h:664
size_t address(std::vector< int > const &ix) const
Get the low-level (unrolled) address corresponding to an index.
Definition: colvargrid.h:77
void remove_small_values(cvm::real const &a)
Assign values that are smaller than scalar constant the latter value (fast loop)
Definition: colvargrid.h:697
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:434
virtual ~colvar_grid()
Destructor.
Definition: colvargrid.h:232
int value_to_bin_scalar(colvarvalue const &value, const int i) const
Use the lower boundary and the width to report which bin the provided value is in.
Definition: colvargrid.h:515
IST & read_raw_template_(IST &is)
Helper method for read_raw.
Definition: colvargrid_def.h:129
virtual T value_output(std::vector< int > const &ix, size_t const &imult=0) const
Return the value suitable for output purposes (so that it may be rescaled or manipulated without chan...
Definition: colvargrid.h:835
void set_sizes(std::vector< int > const &new_sizes)
Set the sizes in each direction.
Definition: colvargrid.h:147
void copy_grid(colvar_grid< T > const &other_grid)
Copy data from another grid of the same type, AND identical definition (boundaries,...
Definition: colvargrid.h:621
void index(size_t address, std::vector< int > &ix)
Inverse of address(): n-dim index from linear address.
Definition: colvargrid.h:94
bool wrap_detect_edge(std::vector< int > &ix) const
Definition: colvargrid.h:446
void raw_data_out(T *out_data) const
Extract the grid data as they are represented in memory. Put the results in "out_data".
Definition: colvargrid.h:644
void map_grid(colvar_grid< T > const &other_grid)
Add data from another grid of the same type.
Definition: colvargrid.h:770
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:103
int value_to_bin_scalar(colvarvalue const &value, colvarvalue const &new_offset, cvm::real const &new_width) const
Same as the standard version, but uses another grid definition.
Definition: colvargrid.h:548
void wrap(std::vector< int > &ix) const
Definition: colvargrid.h:429
colvarvalue bin_to_value_scalar(int const &i_bin, colvarvalue const &new_offset, cvm::real const &new_width) const
Same as the standard version, but uses different parameters.
Definition: colvargrid.h:563
colvar_grid()
Default constructor.
Definition: colvargrid.h:223
std::vector< colvar * > cv
Colvars collected in this grid.
Definition: colvargrid.h:71
std::ostream & write_restart(std::ostream &os)
Write all grid parameters and data to a formatted stream.
Definition: colvargrid_def.h:112
void raw_data_in(const T *in_data)
Input the data as they are represented in memory.
Definition: colvargrid.h:653
@ f_cv_hard_lower_boundary
The lower boundary is not defined from user's choice.
Definition: colvardeps.h:358
@ f_cv_hard_upper_boundary
The upper boundary is not defined from user's choice.
Definition: colvardeps.h:360
Collective variables module (main class)
Definition: colvarmodule.h:72
static real logn(real const &x)
Definition: colvarmodule.h:231
double real
Defining an abstract real number allows to switch precision.
Definition: colvarmodule.h:99
static bool constexpr debug()
Whether debug output should be enabled (compile-time option)
Definition: colvarmodule.h:388
static real floor(real const &x)
Reimplemented to work around MS compiler issues.
Definition: colvarmodule.h:136
static int error_static(std::string const &message, int code=-1)
Definition: colvarmodule.h:789
void log(std::string const &message, int min_log_level=10)
Definition: colvarmodule.cpp:2140
int error(std::string const &message, int code=-1)
Print a message to the main log and set global error code.
Definition: colvarmodule.cpp:2224
static constexpr size_t cv_prec
Number of digits to represent a collective variables value(s)
Definition: colvarmodule.h:743
static real sqrt(real const &x)
Reimplemented to work around MS compiler issues.
Definition: colvarmodule.h:154
static real fabs(real const &x)
Reimplemented to work around MS compiler issues.
Definition: colvarmodule.h:148
static constexpr size_t cv_width
Number of characters to represent a collective variables value(s)
Definition: colvarmodule.h:745
static std::string to_str(char const *s)
Convert to string for output purposes.
Definition: colvarmodule.cpp:2572
Base class containing parsing functions; all objects which need to parse input inherit from this.
Definition: colvarparse.h:27
int check_keywords(std::string &conf, char const *key)
Check that all the keywords within "conf" are in the list of allowed keywords; this will invoke strip...
Definition: colvarparse.cpp:598
Parse_Mode
How a keyword is parsed in a string.
Definition: colvarparse.h:63
@ parse_normal
Alias for old default behavior (should be phased out)
Definition: colvarparse.h:82
Value of a collective variable: this is a metatype which can be set at runtime. By default it is set ...
Definition: colvarvalue.h:43
@ type_scalar
Scalar number, implemented as colvarmodule::real (default)
Definition: colvarvalue.h:56
cvm::real real_value
Real data member.
Definition: colvarvalue.h:77
Definition: colvars_memstream.h:30
Collective variables main module.
Parsing functions for collective variables.