Simpatico  v1.10
GridArray.h
1 #ifndef UTIL_GRID_ARRAY_H
2 #define UTIL_GRID_ARRAY_H
3 
4 /*
5 * Util Package - C++ Utilities for Scientific Computation
6 *
7 * Copyright 2010 - 2017, The Regents of the University of Minnesota
8 * Distributed under the terms of the GNU General Public License.
9 */
10 
11 #include <util/misc/Memory.h>
12 #include <util/global.h>
13 
14 namespace Util
15 {
16 
27  template <typename Data>
28  class GridArray
29  {
30 
31  public:
32 
36  GridArray();
37 
41  GridArray(const GridArray<Data>& other);
42 
48  ~GridArray();
49 
54 
55  // Initialization
56 
62  void allocate(const IntVector& dimensions);
63 
70  template <class Archive>
71  void serialize(Archive& ar, const unsigned int version);
72 
76  bool isAllocated() const;
77 
78  // Grid Interface
79 
85  const IntVector& dimensions();
86 
92  int dimension(int i) const;
93 
97  int size() const;
98 
105  IntVector position(int rank) const;
106 
113  int rank(const IntVector& position) const;
114 
122  bool isInGrid(int coordinate, int i) const;
123 
131  bool isInGrid(IntVector& position) const;
132 
145  int shift(int& coordinate, int i) const;
146 
158  IntVector shift(IntVector& position) const;
159 
160  // Array Interface
161 
167  const Data& operator[] (int rank) const;
168 
174  Data& operator[] (int rank);
175 
181  const Data& operator() (const IntVector& position) const;
182 
188  Data& operator() (const IntVector& position);
189 
190  /*
191  * Return pointer to underlying 1D C-array.
192  */
193  Data* data();
194 
195  private:
196 
198  Data* data_;
199 
201  IntVector offsets_;
202 
204  IntVector dimensions_;
205 
207  int size_;
208 
209  };
210 
211  // Method definitions
212 
216  template <typename Data>
218  : data_(0),
219  offsets_(),
220  dimensions_(),
221  size_(0)
222  {}
223 
224  /*
225  * Destructor.
226  *
227  * Delete dynamically allocated C array.
228  */
229  template <typename Data>
231  {
232  if (data_) {
233  Memory::deallocate<Data>(data_, size_);
234  size_ = 0;
235  }
236  }
237 
238  /*
239  * Copy constructor.
240  */
241  template <typename Data>
243  : data_(0),
244  offsets_(),
245  dimensions_(),
246  size_(0)
247  {
248  // Precondition
249  if (other.data_ == 0) {
250  UTIL_THROW("Other GridArray must be allocated");
251  }
252  if (isAllocated()) {
253  UTIL_THROW("GridArray already allocated in copy constructor");
254  }
255 
256  allocate(other.dimensions_);
257  if (offsets_ != other.offsets_ ) {
258  UTIL_THROW("Unequal offsets");
259  }
260  if (size_ != other.size_ ) {
261  UTIL_THROW("Unequal sizes");
262  }
263  for (int i = 0; i < size_; ++i) {
264  data_[i] = other.data_[i];
265  }
266  }
267 
268  /*
269  * Assignment.
270  */
271  template <typename Data>
273  {
274  // Check for self assignment.
275  if (this == &other) {
276  return *this;
277  }
278 
279  // Precondition
280  if (other.data_ == 0) {
281  UTIL_THROW("Other GridArray must be allocated before assignment");
282  }
283 
284  // If this GridArray if not allocated, allocate now.
285  // If it is allocated, check that dimensions are equal.
286  if (!isAllocated()) {
287  allocate(other.dimensions_);
288  } else {
289  if (dimensions_ != other.dimensions_ ) {
290  UTIL_THROW("Unequal dimensions");
291  }
292  }
293  if (offsets_ != other.offsets_ ) {
294  UTIL_THROW("Unequal offsets");
295  }
296  if (size_ != other.size_ ) {
297  UTIL_THROW("Unequal sizes");
298  }
299 
300  // Copy elements
301  for (int i = 0; i < size_; ++i) {
302  data_[i] = other.data_[i];
303  }
304 
305  return *this;
306  }
307 
308  /*
309  * Set dimensions and allocate memory.
310  */
311  template <typename Data>
313  {
314  if (isAllocated()) {
315  UTIL_THROW("Attempt to re-allocate a GridArray");
316  }
317  for (int i = 0; i < Dimension; ++i) {
318  if (dimensions[i] <= 0) {
319  UTIL_THROW("Dimension not positive");
320  }
321  }
322  dimensions_ = dimensions;
323  offsets_[Dimension -1] = 1;
324  for (int i = Dimension - 1; i > 0; --i) {
325  offsets_[i-1] = offsets_[i]*dimensions_[i];
326  }
327  size_ = offsets_[0]*dimensions_[0];
328  Memory::allocate<Data>(data_, size_);
329  }
330 
331  /*
332  * Serialize a GridArray to/from an Archive.
333  */
334  template <class Data>
335  template <class Archive>
336  void GridArray<Data>::serialize(Archive& ar, const unsigned int version)
337  {
339  if (Archive::is_saving()) {
340  dimensions = dimensions_;
341  }
342  ar & dimensions;
343  if (Archive::is_loading()) {
344  if (!isAllocated()) {
345  allocate(dimensions);
346  }
347  }
348  for (int i = 0; i < size_; ++i) {
349  ar & data_[i];
350  }
351  }
352 
353  /*
354  * Get IntVector of dimensions.
355  */
356  template <typename Data>
358  { return dimensions_; }
359 
360  /*
361  * Get dimension in direction i.
362  */
363  template <class Data>
364  inline int GridArray<Data>::dimension(int i) const
365  { return dimensions_[i]; }
366 
367  /*
368  * Get total number of grid points.
369  */
370  template <class Data>
371  inline int GridArray<Data>::size() const
372  { return size_; }
373 
374  /*
375  * Calculate 1D rank from grid coordinates.
376  */
377  template <typename Data>
378  #ifdef UTIL_DEBUG
379  int GridArray<Data>::rank(const IntVector& position) const
380  {
381  int result = 0;
382  int i;
383  for (i = 0; i < Dimension - 1; ++i) {
384  assert(position[i] >= 0);
385  assert(position[i] < dimensions_[i]);
386  result += position[i]*offsets_[i];
387  }
388  assert(position[i] >= 0);
389  assert(position[i] < dimensions_[i]);
390  result += position[i];
391  return result;
392  }
393  #else
394  inline int GridArray<Data>::rank(const IntVector& position) const
395  {
396  return (position[0]*offsets_[0] + position[1]*offsets_[1] + position[2]);
397  }
398  #endif
399 
400  /*
401  * Calculate coordinates from 1D rank.
402  */
403  template <typename Data>
405  {
407  int remainder = rank;
408 
409  int i;
410  for (i = 0; i < Dimension - 1; ++i) {
411  position[i] = remainder/offsets_[i];
412  remainder -= position[i]*offsets_[i];
413  }
414  position[i] = remainder;
415  return position;
416  }
417 
418  /*
419  * Test if a single coordinate is within range of grid.
420  */
421  template <typename Data>
422  bool GridArray<Data>::isInGrid(int coordinate, int i) const
423  {
424  bool result = true;
425  if (coordinate < 0)
426  result = false;
427  if (coordinate >= dimensions_[i])
428  result = false;
429  return result;
430  }
431 
432  /*
433  * Test if a IntVector position is within primary grid domain.
434  */
435  template <typename Data>
436  bool GridArray<Data>::isInGrid(IntVector& position) const
437  {
438  bool result = true;
439  for (int i = 0; i < Dimension; ++i) {
440  if (position[i] < 0)
441  result = false;
442  if (position[i] >= dimensions_[i])
443  result = false;
444  }
445  return result;
446  }
447 
448  /*
449  * Shift a 1D coordinate to primary domain.
450  */
451  template <typename Data>
452  int GridArray<Data>::shift(int& coordinate, int i) const
453  {
454  int shift;
455  if (coordinate >= 0) {
456  shift = coordinate/dimensions_[i];
457  } else {
458  shift = -1 + ((coordinate+1)/dimensions_[i]);
459  }
460  coordinate -= shift*dimensions_[i];
461  return shift;
462  }
463 
464  /*
465  * Shift a IntVector position to primary domain.
466  */
467  template <typename Data>
469  {
470  IntVector shifts;
471  for (int i = 0; i < Dimension; ++i) {
472  shifts[i] = shift(position[i], i);
473  }
474  return shifts;
475  }
476 
477  /*
478  * Return element by const reference, indexed by 1D rank.
479  */
480  template <typename Data>
481  inline const Data& GridArray<Data>::operator[] (int rank) const
482  { return *(data_ + rank); }
483 
484  /*
485  * Return element by reference, indexed by 1D rank.
486  */
487  template <typename Data>
489  { return *(data_ + rank); }
490 
491  /*
492  * Return element by const reference, indexed by IntVector of coordinates
493  */
494  template <typename Data>
495  inline
496  const Data& GridArray<Data>::operator() (const IntVector& position) const
497  { return *(data_ + rank(position)); }
498 
499  /*
500  * Return element by reference, indexed by IntVector of coordinates
501  */
502  template <typename Data>
503  inline Data& GridArray<Data>::operator() (const IntVector& position)
504  { return *(data_ + rank(position)); }
505 
506  /*
507  * Return pointer to underlying 1D C-array.
508  */
509  template <typename Data>
510  inline Data* GridArray<Data>::data()
511  { return data_;}
512 
513  /*
514  * Return true if the GridArray has been allocated, false otherwise.
515  */
516  template <class Data>
517  inline bool GridArray<Data>::isAllocated() const
518  { return (bool)(data_ != 0); }
519 
520 }
521 #endif
int size() const
Get total number of grid points.
Definition: GridArray.h:371
const int Dimension
Dimensionality of space.
Definition: Dimension.h:19
~GridArray()
Destructor.
Definition: GridArray.h:230
int shift(int &coordinate, int i) const
Shift a periodic 1D coordinate into primary range.
Definition: GridArray.h:452
int dimension(int i) const
Get number of grid points along direction i.
Definition: GridArray.h:364
IntVector position(int rank) const
Get the position IntVector of a grid point with a specified rank.
Definition: GridArray.h:404
int rank(const IntVector &position) const
Get the rank of a grid point with specified position.
Definition: GridArray.h:394
const Data & operator[](int rank) const
Return element by const reference, indexed by 1D rank.
Definition: GridArray.h:481
bool isAllocated() const
Return true if the GridArray has been allocated, false otherwise.
Definition: GridArray.h:517
GridArray< Data > & operator=(const GridArray< Data > &other)
Assignment.
Definition: GridArray.h:272
File containing preprocessor macros for error handling.
const Data & operator()(const IntVector &position) const
Return element by const reference, indexed by IntVector position.
Definition: GridArray.h:496
#define UTIL_THROW(msg)
Macro for throwing an Exception, reporting function, file and line number.
Definition: global.h:51
void serialize(Archive &ar, const unsigned int version)
Serialize a GridArray to/from an Archive.
Definition: GridArray.h:336
Utility classes for scientific computation.
Definition: accumulators.mod:1
void allocate(const IntVector &dimensions)
Allocate memory for a matrix.
Definition: GridArray.h:312
bool isInGrid(int coordinate, int i) const
Is this 1D coordinate in range?
Definition: GridArray.h:422
Multi-dimensional array with the dimensionality of space.
Definition: GridArray.h:28
const IntVector & dimensions()
Get all dimensions of array as an IntVector.
Definition: GridArray.h:357
An IntVector is an integer Cartesian vector.
Definition: IntVector.h:73
GridArray()
Constructor.
Definition: GridArray.h:217