Simpatico  v1.10
mcMd/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/Dimension.h>
11 
12 namespace McMd
13 {
14 
15  using namespace Util;
16 
17  /*
18  * Constructor.
19  */
21  {
22  for (int i = 0; i < Dimension; ++i) {
23  invCellWidths_[i] = 0.0;
24  numCells_[i] = 0;
25  minCells_[i] = 0;
26  maxCells_[i] = 0;
27  minDel_[i] = 0;
28  maxDel_[i] = 0;
29  }
30  YZCells_ = 0;
31  totCells_ = 0;
32  atomCapacity_ = 0;
33  }
34 
35  /*
36  * Destructor.
37  */
39  {}
40 
41  /*
42  * Resets all Cell and CellTag objects to empty state.
43  */
45  {
46  // Clear all Cell objects
47  int i;
48  if (cells_.capacity() > 0) {
49  for (i=0; i < cells_.capacity(); ++i) {
50  cells_[i].clear();
51  }
52  }
53 
54  // Clear all CellTag objects
55  if (cellTags_.capacity() > 0) {
56  for (i = 0; i < cellTags_.capacity(); ++i) {
57  cellTags_[i].clear();
58  }
59  }
60  }
61 
62  /*
63  * Set number of cells and width for one axis (x,y, or z)
64  */
65  void
66  CellList::setCellsAxis(int axis, double cutoff)
67  {
68  numCells_[axis] = (int)(lengths_[axis]/cutoff);
69  if (numCells_[axis] < 1) {
70  numCells_[axis] = 1;
71  }
72  invCellWidths_[axis] = (double)numCells_[axis];
73 
74  minCells_[axis] = 0;
75  maxCells_[axis] = numCells_[axis]-1;
76 
77  if (numCells_[axis] > 2) {
78  minDel_[axis] = -1;
79  maxDel_[axis] = 1;
80  } else if (numCells_[axis] == 2) {
81  minDel_[axis] = -1;
82  maxDel_[axis] = 0;
83  } else if (numCells_[axis] == 1) {
84  minDel_[axis] = 0;
85  maxDel_[axis] = 0;
86  }
87  }
88 
89  /*
90  * Set atomCapacity and, if necessary, allocate cellTags_.
91  */
92  void
93  CellList::setAtomCapacity(int atomCapacity)
94  {
95  // Precondition
96  if (atomCapacity <= 0) {
97  UTIL_THROW("atomCapacity must be > 0");
98  }
99  atomCapacity_ = atomCapacity;
100 
101  // If necessary, allocate/reallocate cellTags_ array.
102  if (cellTags_.capacity() == 0) {
103  cellTags_.allocate(atomCapacity_);
104  } else
105  if (atomCapacity_ > cellTags_.capacity()) {
106  cellTags_.deallocate();
107  cellTags_.allocate(atomCapacity_);
108  }
109  }
110 
111  /*
112  * Setup an empty cell list.
113  */
114  void CellList::setup(const Boundary &boundary, double cutoff)
115  {
116  if (cutoff <= 0) {
117  UTIL_THROW("cutoff must be > 0");
118  }
119 
120  lengths_ = boundary.lengths();
121  setCellsAxis(0, cutoff);
122  setCellsAxis(1, cutoff);
123  setCellsAxis(2, cutoff);
124  YZCells_ = numCells_[1]*numCells_[2];
125  totCells_ = YZCells_*numCells_[0];
126  if (totCells_ < 1) {
127  UTIL_THROW("totCells_ must be > 1");
128  }
129 
130  // If necessary, allocate or reallocate cells_ array
131  if (cells_.capacity() == 0) {
132  cells_.allocate(totCells_);
133  } else
134  if (totCells_ > cells_.capacity()) {
135  cells_.deallocate();
136  cells_.allocate(totCells_);
137  }
138  clear();
139 
140  boundaryPtr_ = &boundary;
141  }
142 
143  /*
144  * Fill an array with Ids of atoms in cell ic and all neighboring cells.
145  */
146  void
147  CellList::getCellNeighbors(int ic, NeighborArray &neighbors, int &nInCell)
148  const
149  {
150  const Cell *cellPtr;
151  Atom *atomPtr;
152  int icx, icy, icz;
153  int jc, jcx, jcy, jcz;
154  int dcx, dcy, dcz, jp;
155 
156  // Determine cell coordinates icx, icy, icz
157  cellCoordFromIndex(ic, icx, icy, icz);
158 
159  // Zero total number of neighbor atoms and number in cell
160  //nNeighbor = 0;
161  nInCell = 0;
162  neighbors.clear();
163 
164  // Loop over atoms in cell ic.
165  // By convention, these appear first in the list.
166  cellPtr = &(cells_[ic]);
167  for (jp=0; jp < cellPtr->firstClearPos(); ++jp) {
168  atomPtr = cellPtr->atomPtr(jp);
169  if (atomPtr != 0) {
170  neighbors.append(atomPtr);
171  ++nInCell;
172  }
173  }
174 
175  // Loop over neighboring cells (excluding cell ic)
176 
177  // Loop in x direction
178  for (dcx = minDel_[0]; dcx <= maxDel_[0]; ++dcx) {
179  jcx = shiftCellCoordAxis(0, icx + dcx);
180 
181  // Loop in y direction
182  for (dcy = minDel_[1]; dcy <= maxDel_[1]; ++dcy) {
183  jcy = shiftCellCoordAxis(1, icy + dcy);
184 
185  // Loop in z direction
186  for (dcz = minDel_[2]; dcz <= maxDel_[2]; ++dcz) {
187  jcz = shiftCellCoordAxis(2, icz + dcz);
188 
189  // Get cell index jc and Cell pointer cellPtr
190  jc = cellIndexFromCoord(jcx, jcy, jcz);
191 
192  if (jc != ic) {
193 
194  // Loop over atoms in neighboring cell jc
195  cellPtr = &cells_[jc];
196  for (jp=0; jp < cellPtr->firstClearPos(); ++jp) {
197  atomPtr = cellPtr->atomPtr(jp);
198  if (atomPtr != 0) {
199  neighbors.append(atomPtr);
200  }
201  }
202 
203  } // end if (jc != ic)
204 
205  } // end for dcz
206 
207  } // end for dcy
208 
209  } // end for dcx
210 
211  }
212 
213  /*
214  * Get the maximum allowed atom index + 1.
215  */
217  { return atomCapacity_; }
218 
219  /*
220  * Get total number of atoms in this CellList.
221  */
222  int CellList::nAtom() const
223  {
224  int nAtomSum = 0;
225  for (int icell = 0; icell < totCells_; ++icell) {
226  nAtomSum += cells_[icell].nAtomCell();
227  }
228  return nAtomSum;
229  }
230 
231  /*
232  * Check validity of CellList, throw an Exception if an error is found.
233  *
234  * This method checks consistency of the CellList and Atom data structures.
235  * Calls Cell::isValid internally for each cell.
236  */
237  bool CellList::isValid(int nAtom) const
238  {
239 
240  // Call Cell::isValid for each Cell. Let any Exceptions bubble up.
241  int nAtomSum = 0;
242  for (int icell = 0; icell < totCells_; ++icell) {
243  cells_[icell].isValid(cellTags_, nAtom, icell);
244  nAtomSum += cells_[icell].nAtomCell();
245  }
246 
247  // Check that total number of atoms in all cells equals nAtom.
248  if (nAtom >= 0) {
249  if (nAtomSum != nAtom) {
250  UTIL_THROW("Number of atoms in all cells != nAtom");
251  }
252  }
253 
254  return true;
255  }
256 
257 }
const int Dimension
Dimensionality of space.
Definition: Dimension.h:19
bool isValid(int nAtom=-1) const
Return true if valid, or throw Exception.
void clear()
Set logical size to zero.
Definition: FSArray.h:271
const Vector & lengths() const
Get Vector of unit cell lengths by const reference.
An orthorhombic periodic unit cell.
void append(const Data &data)
Append data to the end of the array.
Definition: FSArray.h:258
int atomCapacity() const
Get the maximum allowed atom index + 1.
void clear()
Sets all Cell objects to empty state (no Atoms).
#define UTIL_THROW(msg)
Macro for throwing an Exception, reporting function, file and line number.
Definition: global.h:51
void getCellNeighbors(int ic, NeighborArray &neighbors, int &nInCell) const
Fill an array with pointers to atoms in a cell and neighboring cells.
int nAtom() const
Get total number of atoms in this CellList.
A point particle within a Molecule.
Utility classes for scientific computation.
Definition: accumulators.mod:1
void setup(const Boundary &boundary, double cutoff)
Setup grid of empty cells.
Atom * atomPtr(int index) const
Get a pointer to Atom (may be null).
virtual ~CellList()
Destructor.
A set of Atoms in a small region.
int firstClearPos() const
Get index of first clear element of atoms_.
Single-processor Monte Carlo (MC) and molecular dynamics (MD).
void setAtomCapacity(int atomCapacity)
Set atom capacity.