SSAGES  0.1
A MetaDynamics Package
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Groups Pages
Grid.h
1 
20 #pragma once
21 
22 #include <exception>
23 #include <fstream>
24 #include <istream>
25 
26 #include "Drivers/DriverException.h"
27 #include "GridBase.h"
28 #include "schema.h"
29 #include "Validator/ObjectRequirement.h"
30 
31 namespace SSAGES
32 {
33 
35 
57 template<typename T>
58 class Grid : public GridBase<T>
59 {
60 private:
62 
70  size_t mapTo1d(const std::vector<int> &indices) const override
71  {
72  // Check if an index is out of bounds
73  for (size_t i=0; i < GridBase<T>::GetDimension(); ++i) {
74  int index = indices.at(i);
75  int numpoints = GridBase<T>::GetNumPoints(i);
76  if ( index < 0 || index >= numpoints )
77  {
78  throw std::out_of_range("Grid index out of range.");
79  }
80  }
81 
82  size_t idx = 0;
83  size_t fac = 1;
84  for (size_t i=0; i < GridBase<T>::GetDimension(); ++i) {
85  idx += indices.at(i) * fac;
86  fac *= GridBase<T>::GetNumPoints(i);
87  }
88  return idx;
89  }
90 
91 public:
93 
103  Grid(std::vector<int> numPoints,
104  std::vector<double> lower,
105  std::vector<double> upper,
106  std::vector<bool> isPeriodic)
107  : GridBase<T>(numPoints, lower, upper, isPeriodic)
108  {
109  size_t data_size = 1;
110  for (size_t d = 0; d < GridBase<T>::GetDimension(); ++d) {
111  size_t storage_size = GridBase<T>::GetNumPoints(d);
112  data_size *= storage_size;
113  }
114 
115  GridBase<T>::data_.resize(data_size);
116  }
117 
119 
127  static Grid<T>* BuildGrid(const Json::Value& json)
128  {
129  return BuildGrid(json, "#/Grid");
130  }
131 
133 
142  static Grid<T>* BuildGrid(const Json::Value& json, const std::string& path)
143  {
144  Json::ObjectRequirement validator;
145  Json::Value schema;
146  Json::Reader reader;
147 
148  reader.parse(JsonSchema::grid, schema);
149  validator.Parse(schema, path);
150 
151  // Validate inputs.
152  validator.Validate(json, path);
153  if (validator.HasErrors()) {
154  throw BuildException(validator.GetErrors());
155  }
156 
157  // Read in Lower Grid edges.
158  std::vector<double> lower;
159  for (auto &lv : json["lower"]) {
160  lower.push_back(lv.asDouble());
161  }
162 
163  size_t dimension = lower.size();
164 
165  // Read in upper grid edges.
166  std::vector<double> upper;
167  for (auto &uv : json["upper"]) {
168  upper.push_back(uv.asDouble());
169  }
170 
171  if (upper.size() != dimension) {
172  throw BuildException({"Number of upper values does not match "
173  "number of lower values!"});
174  }
175 
176  // Read in number of points.
177  std::vector<int> number_points;
178  for (auto &np : json["number_points"]) {
179  number_points.push_back(np.asInt());
180  }
181 
182  if (number_points.size() != dimension) {
183  throw BuildException({"Arrays \"lower\" and \"number_points\" do "
184  "not have the same size!"});
185  }
186 
187  // Read in periodicity.
188  std::vector<bool> isPeriodic;
189  for (auto &periodic : json["periodic"]) {
190  isPeriodic.push_back(periodic.asBool());
191  }
192 
193  if (isPeriodic.size() == 0) {
194  isPeriodic = std::vector<bool>(dimension, false);
195  } else if (isPeriodic.size() != dimension) {
196  throw BuildException({"Arrays \"lower\" and \"periodic\" do not "
197  "have the same size!"});
198  }
199 
200  // Construct the grid.
201  Grid<T>* grid = new Grid(number_points, lower, upper, isPeriodic);
202 
203  return grid;
204  }
205 
207 
243  template<typename R>
244  class GridIterator {
245  public:
248 
250  typedef int difference_type;
251 
253  typedef R value_type;
254 
256  typedef R* pointer;
257 
259  typedef R& reference;
260 
262  typedef std::bidirectional_iterator_tag iterator_category;
263 
265  GridIterator() = default;
266 
268 
273  GridIterator(const std::vector<int> &indices, Grid<T> *grid)
274  : indices_(indices), grid_(grid)
275  {
276  }
277 
279 
284  GridIterator(const std::vector<int> &indices, const Grid<T> *grid)
285  : indices_(indices), grid_(grid)
286  {
287  }
288 
290 
294  : indices_(other.indices_), grid_(other.grid_)
295  {
296  }
297 
299 
302  reference operator*() { return grid_->at(indices_); }
303 
305 
313  {
314  indices_.at(0) += 1;
315  for (size_t i = 0; i < grid_->GetDimension() - 1; ++i) {
316  if (indices_.at(i) >= grid_->GetNumPoints(i)) {
317  indices_.at(i) = 0;
318  indices_.at(i+1) += 1;
319  }
320  }
321 
322  return *this;
323  }
324 
326 
330  {
331  GridIterator it(*this);
332  ++(*this);
333  return it;
334  }
335 
337  /*
338  * \param shift Vector of shifts in each dimension.
339  * \return Reference to itself.
340  *
341  * This operator shifts the current position of the iterator by the
342  * given amount in each dimension.
343  *
344  * Example:
345  *
346  * \code{.cpp}
347  * if += {1,1,1};
348  * \endcode
349  *
350  * In this example the current position of the iterator is shifted
351  * diagonally.
352  */
353  self_type &operator+=(std::vector<int> shift)
354  {
355  if (shift.size() != grid_->GetDimension()) {
356  throw std::invalid_argument("Vector to shift iterator does not "
357  "match grid dimension.");
358  }
359 
360  for (size_t i = 0; i < grid_->GetDimension(); ++i) {
361  indices_.at(i) += shift.at(i);
362  }
363 
364  return *this;
365  }
366 
368 
374  const self_type operator+(std::vector<int> shift)
375  {
376  return GridIterator(*this) += shift;
377  }
378 
380 
387  {
388  indices_.at(0) -= 1;
389  for (size_t i = 0; i < grid_->GetDimension() - 1; ++i) {
390  if (indices_.at(i) < 0) {
391  indices_.at(i) = grid_->GetNumPoints(i)-1;
392  indices_.at(i+1) -= 1;
393  }
394  }
395 
396  return *this;
397  }
398 
400 
404  {
405  GridIterator it(*this);
406  --(*this);
407  return it;
408  }
409 
411 
415  self_type &operator-=(std::vector<int> shift)
416  {
417  if (shift.size() != grid_->GetDimension()) {
418  throw std::invalid_argument("Vector to shift iterator does not "
419  "match histogram dimension.");
420  }
421 
422  for (size_t i = 0; i < grid_->GetDimension(); ++i) {
423  indices_.at(i) -= shift.at(i);
424  }
425 
426  return *this;
427  }
428 
430 
434  const self_type operator-(std::vector<int> shift)
435  {
436  return GridIterator(*this) -= shift;
437  }
438 
440 
445  bool operator==(const self_type &rhs) const
446  {
447  return indices_ == rhs.indices_ && grid_ == rhs.grid_;
448  }
449 
451 
456  bool operator!=(const self_type &rhs) const
457  {
458  return !( (*this) == rhs );
459  }
460 
462 
468  std::vector<int> &indices()
469  {
470  return indices_;
471  }
472 
474 
479  int &index(size_t d)
480  {
481  return indices()[d];
482  }
483 
485 
488  std::vector<double> coordinates() const
489  {
490  return grid_->GetCoordinates(indices_);
491  }
492 
494 
498  double coordinate(size_t d) const
499  {
500  return coordinates()[d];
501  }
502 
503  private:
505  std::vector<int> indices_;
506 
509  };
510 
512  typedef GridIterator<T> iterator;
513 
515  typedef GridIterator<const T> const_iterator;
516 
518 
525  {
526  std::vector<int> indices(GridBase<T>::GetDimension(), 0);
527 
528  return iterator(indices, this);
529  }
530 
532 
538  {
539  std::vector<int> indices(GridBase<T>::GetDimension());
540  for (size_t i = 0; i < indices.size(); ++i) {
541  indices.at(i) = GridBase<T>::GetNumPoints(i) - 1;
542  }
543 
544  iterator it(indices, this);
545  return ++it;
546  }
547 
549 
556  {
557  std::vector<int> indices(GridBase<T>::GetDimension(), 0);
558 
559  return iterator(indices, this);
560  }
561 
563 
569  {
570  std::vector<int> indices(GridBase<T>::GetDimension());
571  for (size_t i = 0; i < indices.size(); ++i) {
572  indices.at(i) = GridBase<T>::GetNumPoints(i) - 1;
573  }
574 
575  iterator it(indices, this);
576  return ++it;
577  }
578 
580 
583  void WriteToFile(const std::string& file)
584  {
585  std::ofstream output(file.c_str(), std::ofstream::out);
586 
587  // Print out header.
588  output << "#! type grid\n";
589  output << "#! dim " << GridBase<T>::dimension_ << "\n";
590  output << "#! count ";
591  for(auto& c : GridBase<T>::numPoints_)
592  output << c << " ";
593  output << "\n";
594  output << "#! lower ";
595  for(auto& l : GridBase<T>::edges_.first)
596  output << l << " ";
597  output << "\n";
598  output << "#! upper ";
599  for(auto& u : GridBase<T>::edges_.second)
600  output << u << " ";
601  output << "\n";
602  output << "#! periodic ";
603  for(auto p : GridBase<T>::isPeriodic_)
604  output << p << " ";
605  output << "\n";
606 
607  for(auto it = this->begin(); it != this->end(); ++it)
608  {
609  auto coords = it.coordinates();
610  for(auto& c : coords)
611  output << std::setprecision(8) << std::fixed << c << " ";
612  output.unsetf(std::ios_base::fixed);
613  output << std::setprecision(16) << *it << "\n";
614  }
615 
616  output.close();
617  }
618 
620 
626  void LoadFromFile(const std::string& filename)
627  {
628  std::ifstream file(filename);
629  std::string line, buff;
630 
631  // Skip type for now.
632  std::getline(file, line);
633 
634  // Get dimension.
635  {
636  int dim = 0;
637  std::getline(file, line);
638  std::istringstream iss(line);
639  iss >> buff >> buff >> dim;
640  if(dim != GridBase<T>::dimension_)
641  throw std::invalid_argument(filename +
642  ": Expected dimension " + std::to_string(GridBase<T>::dimension_) +
643  " but got " + std::to_string(dim) + " instead.");
644  }
645 
646  // Get size.
647  {
648  std::getline(file, line);
649  std::istringstream iss(line);
650  int count = 0;
651  auto counts = GridBase<T>::numPoints_;
652  iss >> buff >> buff;
653  for(int i = 0; iss >> count; ++i)
654  {
655  if(count != counts[i])
656  throw std::invalid_argument(filename +
657  ": Expected count " + std::to_string(counts[i]) +
658  " on dimension " + std::to_string(i) + " but got " +
659  std::to_string(count) + " instead.");
660  }
661  }
662 
663  // Get lower bounds.
664  {
665  std::getline(file, line);
666  std::istringstream iss(line);
667  double lower = 0;
668  auto lowers = GridBase<T>::edges_.first;
669  iss >> buff >> buff;
670  for(int i = 0; iss >> lower; ++i)
671  {
672  if(std::abs(lower - lowers[i]) > 1e-8)
673  throw std::invalid_argument(filename +
674  ": Expected lower " + std::to_string(lowers[i]) +
675  " on dimension " + std::to_string(i) + " but got " +
676  std::to_string(lower) + " instead.");
677  }
678  }
679 
680  // Get upper bounds.
681  {
682  std::getline(file, line);
683  std::istringstream iss(line);
684  double upper = 0;
685  auto uppers = GridBase<T>::edges_.second;
686  iss >> buff >> buff;
687  for(int i = 0; iss >> upper; ++i)
688  {
689  if(std::abs(upper - uppers[i]) > 1e-8)
690  throw std::invalid_argument(filename +
691  ": Expected upper " + std::to_string(uppers[i]) +
692  " on dimension " + std::to_string(i) + " but got " +
693  std::to_string(upper) + " instead.");
694  }
695  }
696 
697  // Get periodic.
698  {
699  std::getline(file, line);
700  std::istringstream iss(line);
701  bool periodic;
702  auto periodics = GridBase<T>::isPeriodic_;
703  iss >> buff >> buff;
704  for(int i = 0; iss >> periodic; ++i)
705  {
706  if(periodic != periodics[i])
707  throw std::invalid_argument(filename +
708  ": Expected periodic " + std::to_string(periodics[i]) +
709  " on dimension " + std::to_string(i) + " but got " +
710  std::to_string(periodic) + " instead.");
711  }
712  }
713 
714  // Finally load data.
715  for(auto& d : GridBase<T>::data_)
716  {
717  std::getline(file, line);
718  std::istringstream iss(line);
719 
720  // Skip coordinates.
721  for(int i = 0; i < GridBase<T>::dimension_; ++i)
722  iss >> buff;
723 
724  iss >> d;
725  }
726  }
727 };
728 
729 } // End namespace SSAGES
bool HasErrors()
Check if errors have occured.
Definition: Requirement.h:86
GridIterator self_type
Type name of the iterator.
Definition: Grid.h:247
bool operator==(const self_type &rhs) const
Equality operator.
Definition: Grid.h:445
Basic Grid.
Definition: Grid.h:58
R & reference
Either T& or T const& for iterator and const_iterator, respectively.
Definition: Grid.h:259
bool operator!=(const self_type &rhs) const
Non-equality operator.
Definition: Grid.h:456
R * pointer
Either T* or T const* for iterator and const_iterator, respectively.
Definition: Grid.h:256
GridIterator()=default
Use default constructor.
Custom Iterator.
Definition: Grid.h:244
void WriteToFile(const std::string &file)
Write grid out to file.
Definition: Grid.h:583
GridIterator< T > iterator
Custom iterator over a grid.
Definition: Grid.h:512
self_type operator++(int)
Post-increment operator.
Definition: Grid.h:329
virtual void Parse(Value json, const std::string &path) override
Parse JSON value to generate Requirement(s).
self_type & operator++()
Pre-increment operator.
Definition: Grid.h:312
self_type & operator+=(std::vector< int > shift)
Addition assignment operator.
Definition: Grid.h:353
iterator begin()
Return iterator at first grid point.
Definition: Grid.h:524
Exception to be thrown when building the Driver fails.
self_type operator--(int)
Post-decrement operator.
Definition: Grid.h:403
std::vector< std::string > GetErrors()
Get list of error messages.
Definition: Requirement.h:92
const_iterator begin() const
Return const iterator at first grid point.
Definition: Grid.h:555
GridIterator(const GridIterator &other)
Copy constructor.
Definition: Grid.h:293
Requirements on an object.
Grid< T > * grid_
Pointer to grid to iterate over.
Definition: Grid.h:508
GridIterator(const std::vector< int > &indices, Grid< T > *grid)
Constructor.
Definition: Grid.h:273
GridIterator(const std::vector< int > &indices, const Grid< T > *grid)
Const constructor.
Definition: Grid.h:284
const std::vector< int > & GetNumPoints() const
Get the number of points for all dimensions.
Definition: GridBase.h:138
std::vector< int > indices_
Indices of current grid point.
Definition: Grid.h:505
const self_type operator-(std::vector< int > shift)
Subtraction iterator.
Definition: Grid.h:434
self_type & operator--()
Pre-decrement operator.
Definition: Grid.h:386
static Grid< T > * BuildGrid(const Json::Value &json, const std::string &path)
Set up the grid.
Definition: Grid.h:142
static Grid< T > * BuildGrid(const Json::Value &json)
Set up the grid.
Definition: Grid.h:127
std::vector< int > & indices()
Access indices.
Definition: Grid.h:468
const self_type operator+(std::vector< int > shift)
Addition operator.
Definition: Grid.h:374
std::vector< double > coordinates() const
Access coordinates.
Definition: Grid.h:488
double coordinate(size_t d) const
Access specific coordinate dimension.
Definition: Grid.h:498
std::bidirectional_iterator_tag iterator_category
HistIterator is a bidirectional iterator.
Definition: Grid.h:262
const_iterator end() const
Return const iterator after last valid grid point.
Definition: Grid.h:568
int & index(size_t d)
Access a specific index.
Definition: Grid.h:479
Grid(std::vector< int > numPoints, std::vector< double > lower, std::vector< double > upper, std::vector< bool > isPeriodic)
Constructor.
Definition: Grid.h:103
int difference_type
Difference type is an int.
Definition: Grid.h:250
void LoadFromFile(const std::string &filename)
Builds a grid from file.
Definition: Grid.h:626
reference operator*()
Dereference operator.
Definition: Grid.h:302
size_t mapTo1d(const std::vector< int > &indices) const override
Map d-dimensional indices to 1-d data vector.
Definition: Grid.h:70
GridIterator< const T > const_iterator
Custom constant iterator over a grid.
Definition: Grid.h:515
R value_type
Either T or const T for iterator and const_iterator, respectively.
Definition: Grid.h:253
virtual void Validate(const Value &json, const std::string &path) override
Validate JSON value.
iterator end()
Return iterator after last valid grid point.
Definition: Grid.h:537
self_type & operator-=(std::vector< int > shift)
Subtraction assignment operator.
Definition: Grid.h:415
Base class for Grids.
Definition: GridBase.h:38