SSAGES  0.9.3
Software Suite for Advanced General Ensemble Simulations
GridBase.h
1 
20 #pragma once
21 
22 #include <cmath>
23 #include <exception>
24 #include <vector>
25 
26 namespace SSAGES
27 {
28 
30 
37 template<typename T>
38 class GridBase
39 {
40 protected:
42  std::vector<T> data_;
43 
45  size_t dimension_;
46 
48  std::vector<int> numPoints_;
49 
51  std::pair< std::vector<double>,std::vector<double> > edges_;
52 
54  std::vector<bool> isPeriodic_;
55 
57 
62  std::vector<int> wrapIndices(const std::vector<int> &indices) const
63  {
64  std::vector<int> newIndices(indices);
65  for (size_t i = 0; i < dimension_; ++i) {
66  if (!GetPeriodic(i)) {
67  continue;
68  }
69 
70  int index = indices.at(i);
71  while (index < 0) { index += numPoints_[i]; }
72  while (index >= numPoints_[i]) { index -= numPoints_[i]; }
73  if(index == numPoints_[i]-1)
74  index = 0;
75  newIndices.at(i) = index;
76  }
77 
78  return newIndices;
79  }
80 
82 
90  virtual size_t mapTo1d(const std::vector<int> &indices) const = 0;
91 
92 protected:
94 
104  GridBase(std::vector<int> numPoints,
105  std::vector<double> lower,
106  std::vector<double> upper,
107  std::vector<bool> isPeriodic)
108  : dimension_(numPoints.size()),
109  numPoints_(numPoints),
110  edges_(std::pair< std::vector<double>, std::vector<double> >(lower, upper)),
111  isPeriodic_(isPeriodic)
112  {
113  // Check that vector sizes are correct
114  if (edges_.first.size() != dimension_ ||
115  edges_.second.size() != dimension_) {
116  throw std::invalid_argument("Size of vector containing upper or "
117  "lower edges, does not match size of vector containing "
118  "number of grid points.");
119  }
120  if (isPeriodic_.size() == 0) {
121  // Default: Non-periodic in all dimensions
122  isPeriodic.resize(dimension_, false);
123  } else if (isPeriodic_.size() != dimension_) {
124  throw std::invalid_argument("Size of vector isPeriodic does not "
125  "match size of vector containing number of grid points.");
126  }
127  for(size_t i=0 ; i < isPeriodic_.size() ; i++)
128  {
129  if(isPeriodic_[i])
130  {
131  if(numPoints_[i] <= 1)
132  {
133  throw std::invalid_argument("A periodic grid is incompatible with a grid size of 1.");
134  }
135  double spacing = (edges_.second[i] - edges_.first[i]) / (numPoints_[i]-1);
136  edges_.first[i] -= spacing/2;
137  edges_.second[i] += spacing/2;
138  }
139  }
140 
141  }
142 
143 public:
144 
146  void syncGrid()
147  {
148  //Convenience
149  size_t dim = this->GetDimension();
150 
151  //Preallocate
152  std::vector<int> navigate(dim);
153 
154  //Loop over all surfaces. Number of surfaces = dim.
155  for(size_t i = 0 ; i < dim ; i++)
156  {
157  //Check if periodic in this dimension.
158  if(isPeriodic_[i])
159  {
160 
161  //Calculate surface size. This is equal to number of points in each other dimension multiplied.
162  size_t surfsize = 1;
163  for(size_t j = 0 ; j < dim ; j++)
164  {
165  if(i != j)
166  surfsize*=numPoints_[j];
167  }
168 
169  //Loop over all points of this surface on the 0 side and copy to end.
170  for(size_t j = 0 ; j < surfsize ; j++)
171  {
172  int runningcount = j;
173  for(size_t k = 0 ; k < dim ; k++)
174  {
175  if(k == i)
176  navigate[k] = 0;
177  else
178  {
179  navigate[k] = runningcount%numPoints_[k];
180  runningcount = runningcount / numPoints_[k];
181  }
182  }
183  auto temp = this->at(navigate);
184  navigate[i] = numPoints_[i]-1;
185  this->at(navigate) = temp;
186  }
187  }
188  }
189  }
190 
192 
195  size_t GetDimension() const
196  {
197  return dimension_;
198  }
199 
201 
205  const std::vector<int> GetNumPoints() const
206  {
207  return numPoints_;
208  }
209 
211 
217  int GetNumPoints(size_t dim) const
218  {
219  if (dim >= GetDimension()) {
220  std::cerr << "Warning! Grid size requested for a dimension larger "
221  "than the grid dimensionality!\n";
222  return 0;
223  }
224  return numPoints_.at(dim);
225  }
226 
228 
231  const std::vector<double> GetLower() const
232  {
233  std::vector<double> lower(dimension_);
234  for(size_t i = 0; i<dimension_;++i)
235  if(GetPeriodic(i)) {lower[i] = edges_.first[i] - ((edges_.first[i] - edges_.second[i]) / (numPoints_[i]))/2;}
236  else {lower[i] = edges_.first[i];}
237  return lower;
238  }
239 
241 
247  double GetLower(size_t dim) const
248  {
249  if (dim >= GetDimension()) {
250  std::cerr << "Warning! Lower edge requested for a dimension larger "
251  "than the grid dimensionality!\n";
252  return 0.0;
253  }
254  if(GetPeriodic(dim)){return edges_.first[dim] - ((edges_.first[dim] - edges_.second[dim]) / (numPoints_[dim]))/2;}
255  else{return edges_.first[dim];}
256  }
257 
259 
262  const std::vector<double> GetUpper() const
263  {
264  std::vector<double> upper(dimension_);
265  for(size_t i = 0; i<dimension_;++i)
266  if(GetPeriodic(i)) {upper[i] = edges_.second[i] + ((edges_.first[i] - edges_.second[i]) / (numPoints_[i]))/2;}
267  else {upper[i] = edges_.second[i];}
268  return upper;
269  }
270 
271 
273 
279  double GetUpper(size_t dim) const
280  {
281  if (dim >= GetDimension()) {
282  std::cerr << "Warning! Upper edge requested for a dimension larger "
283  "than the grid dimensionality!\n";
284  return 0.0;
285  }
286  if(GetPeriodic(dim)){return edges_.second[dim] + ((edges_.first[dim] - edges_.second[dim]) / (numPoints_[dim]))/2;}
287  else{return edges_.second[dim];}
288  }
289 
291 
295  const std::vector<bool>& GetPeriodic() const
296  {
297  return isPeriodic_;
298  }
299 
301 
308  bool GetPeriodic(size_t dim) const
309  {
310  if (dim >= GetDimension()) {
311  std::cerr << "Warning! Periodicity requested for a dimension larger "
312  "than the grid dimensionality!\n";
313  return false;
314  }
315  return GetPeriodic().at(dim);
316  }
317 
319 
326  size_t size() const
327  {
328  return data_.size();
329  }
330 
332 
338  T *data()
339  {
340  return data_.data();
341  }
342 
344 
350  T const *data() const
351  {
352  return data_.data();
353  }
354 
356 
372  std::vector<int> GetIndices(const std::vector<double> &x) const
373  {
374  // Check that input vector has the correct dimensionality
375  if (x.size() != dimension_) {
376  throw std::invalid_argument("Specified point has a larger "
377  "dimensionality than the grid.");
378  }
379 
380  std::vector<int> indices(dimension_);
381  for (size_t i = 0; i < dimension_; ++i)
382  {
383  double xpos = x.at(i);
384  if (!GetPeriodic(i))
385  {
386  if (xpos < edges_.first[i])
387  {
388  indices.at(i) = -1;
389  continue;
390  }
391  else if (xpos > edges_.second[i])
392  {
393  indices.at(i) = numPoints_[i];
394  continue;
395  }
396 
397  }
398 
399  // To make sure, the value is rounded in the correct direction.
400  double spacing = (edges_.second[i] - edges_.first[i]) / (numPoints_[i]);
401  indices.at(i) = std::floor( (xpos - edges_.first[i]) / spacing);
402  }
403 
404  return wrapIndices(indices);
405  }
406 
408 
464 
472  int GetIndex(double x) const
473  {
474  if (dimension_ != 1) {
475  throw std::invalid_argument("1d Grid index can only be accessed for "
476  "1d-Grids can be accessed with a.");
477  }
478  return GetIndices({x}).at(0);
479  }
480 
481 
483  /*/!
484  *\param coords
485  *\param dim
486  * To be finalized.
487 
488  std::vector<double> GetDist(const std::vector<double> &coords)
489  {
490 
491  }*/
492 
493 
495 
503  std::vector<double> GetCoordinates(const std::vector<int> &indices)
504  {
505  if (indices.size() != dimension_) {
506  throw std::invalid_argument(
507  "Grid indices specified for GetCoordinates() do not have "
508  "the same dimensionality as the grid.");
509  }
510 
511  std::vector<double> v(dimension_);
512 
513  for (size_t i = 0; i < dimension_; ++i) {
514  double spacing = (edges_.second[i] - edges_.first[i]) / (numPoints_[i]);
515  v.at(i) = edges_.first[i] + (indices[i] + 0.5)*spacing;
516  }
517 
518  return v;
519  }
520 
522 
528  double GetCoordinate(int index)
529  {
530  return GetCoordinates({index}).at(0);
531  }
532 
534 
546  const T& at(const std::vector<int> &indices) const
547  {
548  // Check that indices are in bound.
549  if (indices.size() != GetDimension()) {
550  throw std::invalid_argument("Dimension of indices does not match "
551  "dimension of the grid.");
552  }
553 
554  return data_.at(mapTo1d(indices));
555  }
556 
558 
562  T& at(const std::vector<int> &indices)
563  {
564  return const_cast<T&>(static_cast<const GridBase<T>* >(this)->at(indices));
565  }
566 
568 
578  template<typename R>
579  const T& at(std::initializer_list<R>&& x) const
580  {
581  return at(static_cast<std::vector<R> >(x));
582  }
583 
585 
595  template<typename R>
596  T& at(std::initializer_list<R>&& x)
597  {
598  return at(static_cast<std::vector<R> >(x));
599  }
600 
602 
608  const T& at(int index) const
609  {
610  if (dimension_ != 1) {
611  throw std::invalid_argument("Only 1d-Grids can be accessed with a "
612  "single integer as the index.");
613  }
614  return at({index});
615  }
616 
618 
624  T& at(int index)
625  {
626  return const_cast<T&>(static_cast<const GridBase<T>* >(this)->at(index));
627  }
628 
630 
637  const T& at(const std::vector<double> &x) const
638  {
639  return at(GetIndices(x));
640  }
641 
643 
650  T& at(const std::vector<double> &x)
651  {
652  return at(GetIndices(x));
653  }
654 
656 
663  const T& at(double x) const
664  {
665  if (dimension_ != 1) {
666  throw std::invalid_argument("Only 1d-Grids can be accessed with a "
667  "single float as the specified point.");
668  }
669  return at({x});
670  }
671 
673 
679  T& at(double x)
680  {
681  return const_cast<T&>(static_cast<const GridBase<T>* >(this)->at(x));
682  }
683 
685 
689  const T& operator[](const std::vector<int> &indices) const
690  {
691  return at(indices);
692  }
693 
695 
699  T& operator[](const std::vector<int> &indices)
700  {
701  return at(indices);
702  }
703 
705 
715  template<typename R>
716  const T& operator[](std::initializer_list<R>&& x) const
717  {
718  return at(static_cast<std::vector<R> >(x));
719  }
720 
722 
732  template<typename R>
733  T& operator[](std::initializer_list<R>&& x)
734  {
735  return at(static_cast<std::vector<R> >(x));
736  }
737 
739 
745  const T& operator[](int index) const
746  {
747  return at(index);
748  }
749 
751 
757  T& operator[](int index)
758  {
759  return at(index);
760  }
761 
763 
767  const T& operator[](const std::vector<double> &x) const
768  {
769  return at(x);
770  }
771 
773 
777  T& operator[](const std::vector<double> &x)
778  {
779  return at(x);
780  }
781 
783 
789  const T& operator[](double x) const
790  {
791  return at(x);
792  }
793 
795 
801  T& operator[](double x)
802  {
803  return at(x);
804  }
805 
807  virtual ~GridBase() {}
808 };
809 
810 } // End namespace SSAGES
Base class for Grids.
Definition: GridBase.h:39
int GetNumPoints(size_t dim) const
Get the number of points for a specific dimension.
Definition: GridBase.h:217
T & at(const std::vector< double > &x)
Access Grid element pertaining to a specific point – read/write.
Definition: GridBase.h:650
const T & at(double x) const
Access 1d-Grid by point - read-only.
Definition: GridBase.h:663
std::vector< bool > isPeriodic_
Periodicity of the Grid.
Definition: GridBase.h:54
const T & operator[](const std::vector< double > &x) const
Access Grid element pertaining to a specific point per [] read-only.
Definition: GridBase.h:767
T & operator[](int index)
Access 1d-Grid per [] operator, read-write.
Definition: GridBase.h:757
T & operator[](const std::vector< int > &indices)
Access Grid element per [] read-write.
Definition: GridBase.h:699
virtual size_t mapTo1d(const std::vector< int > &indices) const =0
This function needs to be implemented by child classes.
const std::vector< double > GetLower() const
Return the lower edges of the Grid.
Definition: GridBase.h:231
std::pair< std::vector< double >, std::vector< double > > edges_
Edges of the Grid in each dimension.
Definition: GridBase.h:51
T & operator[](const std::vector< double > &x)
Access Grid element pertaining to a specific point per [] read-write.
Definition: GridBase.h:777
const T & at(int index) const
Access 1d Grid by index, read-only.
Definition: GridBase.h:608
const T & at(const std::vector< double > &x) const
Access Grid element pertaining to a specific point – read-only.
Definition: GridBase.h:637
double GetCoordinate(int index)
Return center point of 1d-grid.
Definition: GridBase.h:528
const T & at(std::initializer_list< R > &&x) const
Const access of Grid element via initializer list.
Definition: GridBase.h:579
const T & operator[](int index) const
Access 1d-Grid per [] operator, read-only.
Definition: GridBase.h:745
T & at(double x)
Access 1d-Grid by point - read-write.
Definition: GridBase.h:679
virtual ~GridBase()
Destructor.
Definition: GridBase.h:807
size_t size() const
Get the size of the internal storage vector.
Definition: GridBase.h:326
std::vector< int > GetIndices(const std::vector< double > &x) const
Return the Grid indices for a given point.
Definition: GridBase.h:372
T * data()
Get pointer to the internal data storage vector.
Definition: GridBase.h:338
bool GetPeriodic(size_t dim) const
Get the periodicity in a specific dimension.
Definition: GridBase.h:308
std::vector< double > GetCoordinates(const std::vector< int > &indices)
! Return the distance to adjacent grid center points from given coordinates
Definition: GridBase.h:503
std::vector< int > numPoints_
Number of points in each dimension.
Definition: GridBase.h:48
size_t dimension_
Dimension of the grid.
Definition: GridBase.h:45
const T & operator[](double x) const
Access 1d-Grid via specific point, read-only.
Definition: GridBase.h:789
size_t GetDimension() const
Get the dimension.
Definition: GridBase.h:195
T & at(int index)
Access 1d Grid by index, read-write.
Definition: GridBase.h:624
int GetIndex(double x) const
Return linear interpolation on a coordinate.
Definition: GridBase.h:472
const T & at(const std::vector< int > &indices) const
Access Grid element read-only.
Definition: GridBase.h:546
const std::vector< double > GetUpper() const
Return the upper edges of the Grid.
Definition: GridBase.h:262
T & operator[](std::initializer_list< R > &&x)
Access Grid element via initializer list.
Definition: GridBase.h:733
GridBase(std::vector< int > numPoints, std::vector< double > lower, std::vector< double > upper, std::vector< bool > isPeriodic)
Constructor.
Definition: GridBase.h:104
std::vector< T > data_
Internal storage of the data.
Definition: GridBase.h:42
const std::vector< bool > & GetPeriodic() const
Return the periodicity of the Grid.
Definition: GridBase.h:295
void syncGrid()
Sync the grid.
Definition: GridBase.h:146
const T & operator[](std::initializer_list< R > &&x) const
Const access of Grid element via initializer list.
Definition: GridBase.h:716
const std::vector< int > GetNumPoints() const
Get the number of points for all dimensions.
Definition: GridBase.h:205
const T & operator[](const std::vector< int > &indices) const
Access Grid element per [] read-only.
Definition: GridBase.h:689
double GetLower(size_t dim) const
Get the lower edge for a specific dimension.
Definition: GridBase.h:247
T & at(const std::vector< int > &indices)
Access Grid element read/write.
Definition: GridBase.h:562
T & operator[](double x)
Access 1d-Grid via specific point, read-write.
Definition: GridBase.h:801
T const * data() const
Get pointer to const of the internal data storage vector.
Definition: GridBase.h:350
std::vector< int > wrapIndices(const std::vector< int > &indices) const
Wrap the index around periodic boundaries.
Definition: GridBase.h:62
double GetUpper(size_t dim) const
Get the upper edge for a specific dimension.
Definition: GridBase.h:279
T & at(std::initializer_list< R > &&x)
Access Grid element via initializer list.
Definition: GridBase.h:596