PSCF v1.1
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
14namespace Util
15{
16
27 template <typename Data>
29 {
30
31 public:
32
36 GridArray();
37
41 GridArray(GridArray<Data> const & other);
42
48 ~GridArray();
49
54
55 // Initialization
56
62 void allocate(IntVector const & 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 IntVector const & dimensions();
86
92 int dimension(int i) const;
93
97 int size() const;
98
105 IntVector position(int rank) const;
106
113 int rank(IntVector const & 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
159
160 // Array Interface
161
167 Data const & operator[] (int rank) const;
168
174 Data& operator[] (int rank);
175
181 Data const & operator() (IntVector const & position) const;
182
188 Data& operator() (IntVector const & 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>
274 {
275 // Check for self assignment.
276 if (this == &other) {
277 return *this;
278 }
279
280 // Precondition
281 if (other.data_ == 0) {
282 UTIL_THROW("Other GridArray must be allocated before assignment");
283 }
284
285 // If this GridArray if not allocated, allocate now.
286 // If it is allocated, check that dimensions are equal.
287 if (!isAllocated()) {
288 allocate(other.dimensions_);
289 } else {
290 if (dimensions_ != other.dimensions_ ) {
291 UTIL_THROW("Unequal dimensions");
292 }
293 }
294 if (offsets_ != other.offsets_ ) {
295 UTIL_THROW("Unequal offsets");
296 }
297 if (size_ != other.size_ ) {
298 UTIL_THROW("Unequal sizes");
299 }
300
301 // Copy elements
302 for (int i = 0; i < size_; ++i) {
303 data_[i] = other.data_[i];
304 }
305
306 return *this;
307 }
308
309 /*
310 * Set dimensions and allocate memory.
311 */
312 template <typename Data>
313 void GridArray<Data>::allocate(IntVector const & dimensions)
314 {
315 if (isAllocated()) {
316 UTIL_THROW("Attempt to re-allocate a GridArray");
317 }
318 for (int i = 0; i < Dimension; ++i) {
319 if (dimensions[i] <= 0) {
320 UTIL_THROW("Dimension not positive");
321 }
322 }
323 dimensions_ = dimensions;
324 offsets_[Dimension -1] = 1;
325 for (int i = Dimension - 1; i > 0; --i) {
326 offsets_[i-1] = offsets_[i]*dimensions_[i];
327 }
328 size_ = offsets_[0]*dimensions_[0];
329 Memory::allocate<Data>(data_, size_);
330 }
331
332 /*
333 * Serialize a GridArray to/from an Archive.
334 */
335 template <class Data>
336 template <class Archive>
337 void GridArray<Data>::serialize(Archive& ar, const unsigned int version)
338 {
339 IntVector dimensions;
340 if (Archive::is_saving()) {
341 dimensions = dimensions_;
342 }
343 ar & dimensions;
344 if (Archive::is_loading()) {
345 if (!isAllocated()) {
346 allocate(dimensions);
347 }
348 }
349 for (int i = 0; i < size_; ++i) {
350 ar & data_[i];
351 }
352 }
353
354 /*
355 * Get IntVector of dimensions.
356 */
357 template <typename Data>
359 { return dimensions_; }
360
361 /*
362 * Get dimension in direction i.
363 */
364 template <class Data>
365 inline int GridArray<Data>::dimension(int i) const
366 { return dimensions_[i]; }
367
368 /*
369 * Get total number of grid points.
370 */
371 template <class Data>
372 inline int GridArray<Data>::size() const
373 { return size_; }
374
375 /*
376 * Calculate 1D rank from grid coordinates.
377 */
378 template <typename Data>
379 #ifdef UTIL_DEBUG
380 int GridArray<Data>::rank(IntVector const & position) const
381 {
382 int result = 0;
383 int i;
384 for (i = 0; i < Dimension - 1; ++i) {
385 assert(position[i] >= 0);
386 assert(position[i] < dimensions_[i]);
387 result += position[i]*offsets_[i];
388 }
389 assert(position[i] >= 0);
390 assert(position[i] < dimensions_[i]);
391 result += position[i];
392 return result;
393 }
394 #else
395 inline int GridArray<Data>::rank(IntVector const & position) const
396 {
397 return (position[0]*offsets_[0] + position[1]*offsets_[1] + position[2]);
398 }
399 #endif
400
401 /*
402 * Calculate coordinates from 1D rank.
403 */
404 template <typename Data>
406 {
407 IntVector position;
408 int remainder = rank;
409
410 int i;
411 for (i = 0; i < Dimension - 1; ++i) {
412 position[i] = remainder/offsets_[i];
413 remainder -= position[i]*offsets_[i];
414 }
415 position[i] = remainder;
416 return position;
417 }
418
419 /*
420 * Test if a single coordinate is within range of grid.
421 */
422 template <typename Data>
423 bool GridArray<Data>::isInGrid(int coordinate, int i) const
424 {
425 bool result = true;
426 if (coordinate < 0)
427 result = false;
428 if (coordinate >= dimensions_[i])
429 result = false;
430 return result;
431 }
432
433 /*
434 * Test if a IntVector position is within primary grid domain.
435 */
436 template <typename Data>
438 {
439 bool result = true;
440 for (int i = 0; i < Dimension; ++i) {
441 if (position[i] < 0)
442 result = false;
443 if (position[i] >= dimensions_[i])
444 result = false;
445 }
446 return result;
447 }
448
449 /*
450 * Shift a 1D coordinate to primary domain.
451 */
452 template <typename Data>
453 int GridArray<Data>::shift(int& coordinate, int i) const
454 {
455 int shift;
456 if (coordinate >= 0) {
457 shift = coordinate/dimensions_[i];
458 } else {
459 shift = -1 + ((coordinate+1)/dimensions_[i]);
460 }
461 coordinate -= shift*dimensions_[i];
462 return shift;
463 }
464
465 /*
466 * Shift a IntVector position to primary domain.
467 */
468 template <typename Data>
470 {
471 IntVector shifts;
472 for (int i = 0; i < Dimension; ++i) {
473 shifts[i] = shift(position[i], i);
474 }
475 return shifts;
476 }
477
478 /*
479 * Return element by const reference, indexed by 1D rank.
480 */
481 template <typename Data>
482 inline Data const & GridArray<Data>::operator[] (int rank) const
483 { return *(data_ + rank); }
484
485 /*
486 * Return element by reference, indexed by 1D rank.
487 */
488 template <typename Data>
489 inline Data& GridArray<Data>::operator[] (int rank)
490 { return *(data_ + rank); }
491
492 /*
493 * Return element by const reference, indexed by IntVector of coordinates
494 */
495 template <typename Data>
496 inline
497 Data const & GridArray<Data>::operator() (IntVector const & position)
498 const
499 { return *(data_ + rank(position)); }
500
501 /*
502 * Return element by reference, indexed by IntVector of coordinates
503 */
504 template <typename Data>
505 inline Data& GridArray<Data>::operator() (IntVector const & position)
506 { return *(data_ + rank(position)); }
507
508 /*
509 * Return pointer to underlying 1D C-array.
510 */
511 template <typename Data>
512 inline Data * GridArray<Data>::data()
513 { return data_;}
514
515 /*
516 * Return true if the GridArray has been allocated, false otherwise.
517 */
518 template <class Data>
520 { return (bool)(data_ != 0); }
521
522}
523#endif
Multi-dimensional array with the dimensionality of space.
Definition: GridArray.h:29
int rank(IntVector const &position) const
Get the rank of a grid point with specified position.
Definition: GridArray.h:395
~GridArray()
Destructor.
Definition: GridArray.h:230
GridArray()
Constructor.
Definition: GridArray.h:217
Data const & operator[](int rank) const
Return element by const reference, indexed by 1D rank.
Definition: GridArray.h:482
bool isAllocated() const
Return true if the GridArray has been allocated, false otherwise.
Definition: GridArray.h:519
Data const & operator()(IntVector const &position) const
Return element by const reference, indexed by IntVector position.
Definition: GridArray.h:497
IntVector position(int rank) const
Get the position IntVector of a grid point with a specified rank.
Definition: GridArray.h:405
bool isInGrid(int coordinate, int i) const
Is this 1D coordinate in range?
Definition: GridArray.h:423
GridArray< Data > & operator=(GridArray< Data > const &other)
Assignment.
Definition: GridArray.h:273
void serialize(Archive &ar, const unsigned int version)
Serialize a GridArray to/from an Archive.
Definition: GridArray.h:337
void allocate(IntVector const &dimensions)
Allocate memory for a matrix.
Definition: GridArray.h:313
int dimension(int i) const
Get number of grid points along direction i.
Definition: GridArray.h:365
int shift(int &coordinate, int i) const
Shift a periodic 1D coordinate into primary range.
Definition: GridArray.h:453
IntVector const & dimensions()
Get all dimensions of array as an IntVector.
Definition: GridArray.h:358
int size() const
Get total number of grid points.
Definition: GridArray.h:372
An IntVector is an integer Cartesian vector.
Definition: IntVector.h:74
File containing preprocessor macros for error handling.
#define UTIL_THROW(msg)
Macro for throwing an Exception, reporting function, file and line number.
Definition: global.h:51
const int Dimension
Dimensionality of space.
Definition: Dimension.h:19
Utility classes for scientific computation.
Definition: accumulators.mod:1