Simpatico  v1.10
tools/neighbor/CellList.cpp
1 /*
2 * Simpatico - Simulation Package for Polymeric and Molecular Liquids
3 *
4 * Copyright 2010 - 2017, The Regents of the University of Minnesota
5 * Distributed under the terms of the GNU General Public License.
6 */
7 
8 #include "CellList.h"
9 #include <util/space/Vector.h>
10 #include <util/space/IntVector.h>
11 //#include <util/containers/FArray.h>
12 
13 namespace Tools
14 {
15 
16  using namespace Util;
17 
18  /*
19  * Constructor.
20  */
22  : begin_(0),
23  nAtom_(0),
24  nReject_(0),
25  #ifdef UTIL_DEBUG
26  maxNAtomCell_(0),
27  #endif
28  isBuilt_(false)
29  {
30  for (int i = 0; i < Dimension; ++i) {
31  cellLengths_[i] = 0.0;
32  }
33  }
34 
35  /*
36  * Destructor.
37  */
39  {}
40 
41  /*
42  * Allocate memory for this CellList (generalized coordinates).
43  */
44  void CellList::allocate(int atomCapacity, const Vector& lower,
45  const Vector& upper, const Vector& cutoffs)
46  {
47  // Allocate arrays of tag and handle objects
48  tags_.allocate(atomCapacity);
49  atoms_.allocate(atomCapacity);
50 
51  // Set grid dimensions and allocate an array of Cell objects
52  setGridDimensions(lower, upper, cutoffs);
53  }
54 
55  /*
56  * Calculate number of cells in each direction, resize cells_ array if needed.
57  */
58  void CellList::setGridDimensions(const Vector& lower, const Vector& upper,
59  const Vector& cutoffs)
60  {
61  upper_ = upper;
62  lower_ = lower;
63 
64  bool isNewGrid;
65  if (grid_.size() < 27) {
66  isNewGrid = true;
67  } else {
68  isNewGrid = false;
69  }
70 
71  // Calculate gridDimensions = number of cells in each direction
72  // If any differ from current grid dimension, isNewGrid = false.
73  Vector lengths;
74  IntVector gridDimensions;
75  for (int i = 0; i < Dimension; ++i) {
76  lengths[i] = upper_[i] - lower_[i];
77  if (lengths[i] < 0) {
78  UTIL_THROW("Error: length[i] < 0.0");
79  }
80  if (lengths[i] < cutoffs[i]) {
81  UTIL_THROW("Error: length[i] < cutoff[i]");
82  }
83  gridDimensions[i] = int(lengths[i]/cutoffs[i]);
84  cellLengths_[i] = lengths[i]/double(gridDimensions[i]);
85 
86  if (gridDimensions[i] != grid_.dimension(i)) {
87  isNewGrid = true;
88  }
89  }
90 
91  // Set new grid dimensions if necessary
92  if (isNewGrid) {
93  grid_.setDimensions(gridDimensions);
94 
95  gridOffsets_[Dimension - 1] = 1;
96  for (int i = Dimension - 1; i > 0; --i) {
97  gridOffsets_[i-1] = gridOffsets_[i]*gridDimensions[i];
98  }
99  }
100 
101  // Resize and initialize cells_ array, if necessary
102  int oldSize = cells_.size();
103  int newSize = grid_.size();
104  if (newSize != oldSize) {
105  cells_.resize(newSize);
106  if (newSize > oldSize) {
107  for (int i = 0; i < newSize; ++i) {
108  cells_[i].setId(i);
109  }
110  }
111  // Indicate that cell list must be rebuilt
112  isNewGrid = true;
113  }
114  assert(newSize >= 27);
115  assert(newSize == cells_.size());
116 
117  // Build linked cell list, if necessary
118  if (isNewGrid) {
119  // Loop over local cells, linking cells.
120  IntVector p;
121  Cell* prevPtr = 0;
122  Cell* cellPtr = 0;
123  int ic;
124  for (p[0] = 0; p[0] < grid_.dimension(0); ++p[0]) {
125  for (p[1] = 0; p[1] < grid_.dimension(1); ++p[1]) {
126  for (p[2] = 0; p[2] < grid_.dimension(2); ++p[2]) {
127  ic = grid_.rank(p);
128  cellPtr = &cells_[ic];
129  if (prevPtr) {
130  prevPtr->setNextCell(*cellPtr);
131  }
132  else {
133  begin_ = cellPtr;
134  }
135  prevPtr = cellPtr;
136  }
137  }
138  }
139  cellPtr->setLastCell();
140  }
141  }
142 
143  /*
144  * Construct grid of cells, build linked list and identify neighbors.
145  */
146  void CellList::makeGrid(const Vector& lower, const Vector& upper,
147  const Vector& cutoffs)
148  {
149  // Calculate required grid dimensions, reinitialize cells_ array if needed.
150  setGridDimensions(lower, upper, cutoffs);
151 
152  // Calculate offsets to move to neighboring cells
153  for (int cellId = 0; cellId < grid_.size(); cellId++) {
154  Cell::OffsetArray *offsets = new Cell::OffsetArray;
155 
156  for (int i = 0; i < Dimension; i++) {
157  std::pair<int, int> axisOffset;
158  axisOffset.first = calculateAxisOffset(cellId, i, 1);
159  axisOffset.second = calculateAxisOffset(cellId, i, -1);
160 
161  offsets->append(axisOffset);
162  }
163 
164  cells_[cellId].setOffsetArray(*offsets);
165  }
166  }
167 
168  /*
169  * Resets all cells to empty state.
170  */
172  {
173  // Clear all Cell objects
174  if (grid_.size() > 0) {
175  for (int i = 0; i < grid_.size(); ++i) {
176  cells_[i].clear();
177  }
178  }
179 
180  nAtom_ = 0;
181  nReject_ = 0;
182  #ifdef UTIL_DEBUG
183  maxNAtomCell_ = 0;
184  #endif
185 
186  isBuilt_ = false;
187  }
188 
189  /*
190  * Initialize all cells and fill them with atoms.
191  */
193  {
194  // Initialize all cells, by associating each with a
195  // block of the atoms_ array.
196 
197  CellAtom* cellAtomPtr = &atoms_[0];
198  for (int i = 0; i < grid_.size(); ++i) {
199  cellAtomPtr = cells_[i].initialize(cellAtomPtr);
200  }
201 
202  // Add all atoms to cells.
203  for (int i = 0; i < nAtom_; ++i) {
204  cells_[tags_[i].cellRank].append(tags_[i].ptr);
205  }
206 
207  #ifdef UTIL_DEBUG
208  // Calculate maxNAtomCell_
209  int nAtomCell;
210  maxNAtomCell_ = 0;
211  for (int i = 0; i < grid_.size(); ++i) {
212  nAtomCell = cells_[i].nAtom();
213  if (nAtomCell > maxNAtomCell_) {
214  maxNAtomCell_ = nAtomCell;
215  }
216  }
217  #endif
218 
219  isBuilt_ = true;
220  }
221 
222  /*
223  * Update position information in all CellAtom objects.
224  */
226  {
227  for (int i = 0; i < nAtom_; ++i) {
228  atoms_[i].update();
229  }
230  }
231 
232  /*
233  * Get total number of atoms in this CellList.
234  */
235  int CellList::nAtom() const
236  { return nAtom_; }
237 
238  /*
239  * Get number of atoms that were rejected (not added to cells).
240  */
241  int CellList::nReject() const
242  { return nReject_; }
243 
244  #ifdef UTIL_DEBUG
245  /*
246  * Get maximum number of atoms in any cell.
247  */
248  int CellList::maxNAtomCell() const
249  { return maxNAtomCell_; }
250  #endif
251 
252  /*
253  * Get the maximum number of atoms for which space is allocated.
254  */
256  { return tags_.capacity(); }
257 
258  /*
259  * Get the number of cells for which space has been allocated.
260  */
262  { return cells_.capacity(); }
263 
264  /*
265  * Is this CellList built (i.e., full of atoms)?
266  */
267  bool CellList::isBuilt() const
268  { return isBuilt_; }
269 
270  /*
271  * Check validity of CellList, throw an Exception if an error is found.
272  */
273  bool CellList::isValid() const
274  {
275 
276  if (isAllocated()) {
277  if (tags_.capacity() <= 0) {
278  UTIL_THROW("CellList is allocated but tags_.capacity() <= 0");
279  }
280  if (atoms_.capacity() <= 0) {
281  UTIL_THROW("CellList is allocated but atoms_.capacity() <= 0");
282  }
283  }
284 
285  if (isBuilt_) {
286 
287  if (!isAllocated()) {
288  UTIL_THROW("CellList is built but not allocated");
289  }
290 
291  // Check validity of all cells individually.
292  // const CellAtom* atomPtr;
293  const Cell* cellPtr;
294  int nAtomCell;
295  int nAtomSum = 0;
296  for (int icell = 0; icell < grid_.size(); ++icell) {
297  cellPtr = &cells_[icell];
298  nAtomCell = cellPtr->nAtom();
299  if (nAtomCell != cellPtr->atomCapacity()) {
300  UTIL_THROW("Cell nAtom != atomCapacity");
301  }
302  #if 0
303  if (nAtomCell > 0) {
304  for (int i = 0; i < nAtomCell; ++i) {
305  atomPtr = cellPtr->atomPtr(i);
306  if (icell != cellIndexFromPosition(atomPtr->position())) {
307  UTIL_THROW("Inconsistent position");
308  }
309  }
310  }
311  #endif
312  nAtomSum += nAtomCell;
313  }
314 
315  // Check that total number of atoms in all cells equals nAtom.
316  // Note: nAtom is incremented by the placeAtom() method.
317  if (nAtom_ >= 0) {
318  if (nAtomSum != nAtom_) {
319  UTIL_THROW("Number of atoms in all cells != nAtom");
320  }
321  }
322 
323  } else { // if not isBuilt_
324 
325  if (nAtom_ != 0) {
326  UTIL_THROW("CellList is not built, but nAtom_ != 0");
327  }
328 
329  }
330 
331  return true;
332  }
333 
334 }
virtual ~CellList()
Destructor.
const int Dimension
Dimensionality of space.
Definition: Dimension.h:19
A Vector is a Cartesian vector.
Definition: Vector.h:75
int atomCapacity() const
Capacity of array segment.
int nAtom() const
Number of atoms in cell.
void allocate(int atomCapacity, const Vector &lower, const Vector &upper, const Vector &cutoffs)
Allocate memory for this CellList (generalized coordinates).
bool isValid() const
Return true if valid, or throw Exception.
void append(const Data &data)
Append data to the end of the array.
Definition: FSArray.h:258
void update()
Update the cell list.
int dimension(int i) const
Get grid dimension along Cartesian direction i.
Definition: Grid.h:159
int size() const
Get total number of grid points.
Definition: Grid.h:166
int atomCapacity() const
Maximum number of atoms for which space is allocated.
A fixed capacity (static) contiguous array with a variable logical size.
Definition: FSArray.h:37
#define UTIL_THROW(msg)
Macro for throwing an Exception, reporting function, file and line number.
Definition: global.h:51
bool isAllocated() const
Has memory been allocated for this CellList?
Utility classes for scientific computation.
Definition: accumulators.mod:1
void setLastCell()
Set this to be the last cell in the list.
Single-processor classes for pre- and post-processing MD trajectories.
bool isBuilt() const
Has this CellList been built?
int nReject() const
Get number of atoms that were rejected (not placed in cells)
int rank(const IntVector &position) const
Get the rank of a grid point with specified position.
Definition: Grid.cpp:49
int cellCapacity() const
Number of cells for which space has been allocated.
void setNextCell(Cell &nextCell)
Set the pointer to the next cell in the list.
void makeGrid(const Vector &lower, const Vector &upper, const Vector &cutoffs)
Make the cell grid (using generalized coordinates).
int nAtom() const
Get total number of atoms (local and ghost) in this CellList.
An IntVector is an integer Cartesian vector.
Definition: IntVector.h:73
CellAtom * atomPtr(int i) const
Return a pointer to atom i.
FSArray< std::pair< int, int >, Dimension > OffsetArray
An array of offsets to the neighboring cells surrounding this cell.
int cellIndexFromPosition(const Vector &position) const
Return the index of the cell that contains a position Vector.
void clear()
Reset the cell list to its empty state (no atoms).
int capacity() const
Return allocated size.
Definition: Array.h:153
void allocate(int capacity)
Allocate the underlying C array.
Definition: DArray.h:191
void setDimensions(const IntVector &dimensions)
Set the grid dimensions in all directions.
Definition: Grid.cpp:32
Data for an atom in a CellList.
A single cell in a CellList.
void build()
Build the cell list.