- rvec c0; /* The lower corner of the (local) grid */
- rvec c1; /* The upper corner of the (local) grid */
- rvec size; /* c1 - c0 */
- real atom_density; /* The atom number density for the local grid */
- real maxAtomGroupRadius; /* The maximum distance an atom can be outside
- * of a cell and outside of the grid
- */
-
- gmx_bool bSimple; /* Is this grid simple or super/sub */
- int na_c; /* Number of atoms per cluster */
- int na_cj; /* Number of atoms for list j-clusters */
- int na_sc; /* Number of atoms per super-cluster */
- int na_c_2log; /* 2log of na_c */
-
- int numCells[DIM - 1]; /* Number of cells along x/y */
- int nc; /* Total number of cells */
-
- real cellSize[DIM - 1]; /* size of a cell */
- real invCellSize[DIM - 1]; /* 1/cellSize */
-
- int cell0; /* Index in nbs->cell corresponding to cell 0 */
-
- /* Grid data */
- std::vector<int> cxy_na; /* The number of atoms for each column in x,y */
- std::vector<int> cxy_ind; /* Grid (super)cell index, offset from cell0 */
-
- std::vector<int> nsubc; /* The number of sub cells for each super cell */
-
- /* Bounding boxes */
- std::vector<float> bbcz; /* Bounding boxes in z for the cells */
- std::vector < nbnxn_bb_t, gmx::AlignedAllocator < nbnxn_bb_t>> bb; /* 3D bounding boxes for the sub cells */
- std::vector < nbnxn_bb_t, gmx::AlignedAllocator < nbnxn_bb_t>> bbjStorage; /* 3D j-bounding boxes for the case where
- * the i- and j-cluster sizes are different */
- gmx::ArrayRef<nbnxn_bb_t> bbj; /* 3D j-bounding boxes */
- std::vector < float, gmx::AlignedAllocator < float>> pbb; /* 3D b. boxes in xxxx format per super cell */
-
- /* Bit-flag information */
- std::vector<int> flags; /* Flags for properties of clusters in each cell */
- std::vector<unsigned int> fep; /* FEP signal bits for atoms in each cluster */
-
- /* Statistics */
- int nsubc_tot; /* Total number of subcell, used for printing */
+ public:
+ /*! \internal
+ * \brief The cluster and cell geometry of a grid
+ */
+ struct Geometry
+ {
+ //! Constructs the cluster/cell geometry given the type of pairlist
+ Geometry(PairlistType pairlistType);
+
+ bool isSimple; //!< Is this grid simple (CPU) or hierarchical (GPU)
+ int numAtomsICluster; //!< Number of atoms per cluster
+ int numAtomsJCluster; //!< Number of atoms for list j-clusters
+ int numAtomsPerCell; //!< Number of atoms per cell
+ int numAtomsICluster2Log; //!< 2log of na_c
+ };
+
+ // The physical dimensions of a grid
+ struct Dimensions
+ {
+ //! The lower corner of the (local) grid
+ rvec lowerCorner;
+ //! The upper corner of the (local) grid
+ rvec upperCorner;
+ //! The physical grid size: upperCorner - lowerCorner
+ rvec gridSize;
+ //! An estimate for the atom number density of the region targeted by the grid
+ real atomDensity;
+ //! The maximum distance an atom can be outside of a cell and outside of the grid
+ real maxAtomGroupRadius;
+ //! Size of cell along dimension x and y
+ real cellSize[DIM - 1];
+ //! 1/size of a cell along dimensions x and y
+ real invCellSize[DIM - 1];
+ //! The number of grid cells along dimensions x and y
+ int numCells[DIM - 1];
+ };
+
+ //! Constructs a grid given the type of pairlist
+ Grid(PairlistType pairlistType);
+
+ //! Returns the geometry of the grid cells
+ const Geometry &geometry() const
+ {
+ return geometry_;
+ }
+
+ //! Returns the dimensions of the grid
+ const Dimensions &dimensions() const
+ {
+ return dimensions_;
+ }
+
+ //! Returns the total number of grid columns
+ int numColumns() const
+ {
+ return dimensions_.numCells[XX]*dimensions_.numCells[YY];
+ }
+
+ //! Returns the total number of grid cells
+ int numCells() const
+ {
+ return numCellsTotal_;
+ }
+
+ //! Returns the cell offset of (the first cell of) this grid in the list of cells combined over all grids
+ int cellOffset() const
+ {
+ return cellOffset_;
+ }
+
+ //! Returns the first cell index in the grid, starting at 0 in this grid
+ int firstCellInColumn(int columnIndex) const
+ {
+ return cxy_ind_[columnIndex];
+ };
+
+ //! Returns the number of cells in the column
+ int numCellsInColumn(int columnIndex) const
+ {
+ return cxy_ind_[columnIndex + 1] - cxy_ind_[columnIndex];
+ };
+
+ //! Returns the index of the first atom in the column
+ int firstAtomInColumn(int columnIndex) const
+ {
+ return (cellOffset_ + cxy_ind_[columnIndex])*geometry_.numAtomsPerCell;
+ };
+
+ //! Returns the number of real atoms in the column
+ int numAtomsInColumn(int columnIndex) const
+ {
+ return cxy_na_[columnIndex];
+ };
+
+ //! Returns the number of atoms in the column including padding
+ int paddedNumAtomsInColumn(int columnIndex) const
+ {
+ return numCellsInColumn(columnIndex)*geometry_.numAtomsPerCell;
+ };
+
+ //! Returns the end of the atom index range on the grid, including padding
+ int atomIndexEnd() const
+ {
+ return (cellOffset_ + numCellsTotal_)*geometry_.numAtomsPerCell;
+ }
+
+ //! Returns whether any atom in the cluster is perturbed
+ bool clusterIsPerturbed(int clusterIndex) const
+ {
+ return fep_[clusterIndex] != 0u;
+ }
+
+ //! Returns whether the given atom in the cluster is perturbed
+ bool atomIsPerturbed(int clusterIndex,
+ int atomIndexInCluster) const
+ {
+ return (fep_[clusterIndex] & (1 << atomIndexInCluster)) != 0u;
+ }
+
+ //! Returns the free-energy perturbation bits for the cluster
+ unsigned int fepBits(int clusterIndex) const
+ {
+ return fep_[clusterIndex];
+ }
+
+ //! Returns the i-bounding boxes for all clusters on the grid
+ gmx::ArrayRef<const BoundingBox> iBoundingBoxes() const
+ {
+ return bb_;
+ }
+
+ //! Returns the j-bounding boxes for all clusters on the grid
+ gmx::ArrayRef<const BoundingBox> jBoundingBoxes() const
+ {
+ return bbj_;
+ }
+
+ //! Returns the packed bounding boxes for all clusters on the grid, empty with a CPU list
+ gmx::ArrayRef<const float> packedBoundingBoxes() const
+ {
+ return pbb_;
+ }
+
+ //! Returns the bounding boxes along z for all cells on the grid
+ gmx::ArrayRef<const float> zBoundingBoxes() const
+ {
+ return bbcz_;
+ }
+
+ //! Returns the flags for all clusters on the grid
+ gmx::ArrayRef<const int> clusterFlags() const
+ {
+ return flags_;
+ }
+
+ //! Returns the number of clusters for all cells on the grid, empty with a CPU geometry
+ gmx::ArrayRef<const int> numClustersPerCell() const
+ {
+ return numClusters_;
+ }
+
+ //! Returns the cluster index for an atom
+ int atomToCluster(int atomIndex) const
+ {
+ return (atomIndex >> geometry_.numAtomsICluster2Log);
+ }
+
+ //! Returns the total number of clusters on the grid
+ int numClusters() const
+ {
+ if (geometry_.isSimple)
+ {
+ return numCellsTotal_;
+ }
+ else
+ {
+ return numClustersTotal_;
+ }
+ }
+
+ //! Sets the grid dimensions
+ void setDimensions(const nbnxn_search *nbs,
+ int ddZone,
+ int numAtoms,
+ const rvec lowerCorner,
+ const rvec upperCorner,
+ real atomDensity,
+ real maxAtomGroupRadius);
+
+ //! Determine in which grid cells the atoms should go
+ void calcCellIndices(nbnxn_search *nbs,
+ int ddZone,
+ int cellOffset,
+ const gmx::UpdateGroupsCog *updateGroupsCog,
+ int atomStart,
+ int atomEnd,
+ const int *atinfo,
+ gmx::ArrayRef<const gmx::RVec> x,
+ int numAtomsMoved,
+ const int *move,
+ nbnxn_atomdata_t *nbat);
+
+ private:
+ /*! \brief Fill a pair search cell with atoms
+ *
+ * Potentially sorts atoms and sets the interaction flags.
+ */
+ void fillCell(nbnxn_search *nbs,
+ nbnxn_atomdata_t *nbat,
+ int atomStart,
+ int atomEnd,
+ const int *atinfo,
+ gmx::ArrayRef<const gmx::RVec> x,
+ BoundingBox gmx_unused *bb_work_aligned);
+
+ //! Spatially sort the atoms within one grid column
+ void sortColumnsCpuGeometry(nbnxn_search *nbs,
+ int dd_zone,
+ int atomStart, int atomEnd,
+ const int *atinfo,
+ gmx::ArrayRef<const gmx::RVec> x,
+ nbnxn_atomdata_t *nbat,
+ int cxy_start, int cxy_end,
+ gmx::ArrayRef<int> sort_work);
+
+ //! Spatially sort the atoms within one grid column
+ void sortColumnsGpuGeometry(nbnxn_search *nbs,
+ int dd_zone,
+ int atomStart, int atomEnd,
+ const int *atinfo,
+ gmx::ArrayRef<const gmx::RVec> x,
+ nbnxn_atomdata_t *nbat,
+ int cxy_start, int cxy_end,
+ gmx::ArrayRef<int> sort_work);
+
+ /* Data members */
+ //! The geometry of the grid clusters and cells
+ Geometry geometry_;
+ //! The physical dimensions of the grid
+ Dimensions dimensions_;
+
+ //! The total number of cells in this grid
+ int numCellsTotal_;
+ //! Index in nbs->cell corresponding to cell 0 */
+ int cellOffset_;
+
+ /* Grid data */
+ //! The number of, non-filler, atoms for each grid column
+ std::vector<int> cxy_na_;
+ //! The grid-local cell index for each grid column
+ std::vector<int> cxy_ind_;
+
+ //! The number of cluster for each cell
+ std::vector<int> numClusters_;
+
+ /* Bounding boxes */
+ //! Bounding boxes in z for the cells
+ std::vector<float> bbcz_;
+ //! 3D bounding boxes for the sub cells
+ std::vector < BoundingBox, gmx::AlignedAllocator < BoundingBox>> bb_;
+ //! 3D j-bounding boxes for the case where the i- and j-cluster sizes are different
+ std::vector < BoundingBox, gmx::AlignedAllocator < BoundingBox>> bbjStorage_;
+ //! 3D j-bounding boxes
+ gmx::ArrayRef<BoundingBox> bbj_;
+ //! 3D bounding boxes in packed xxxx format per cell
+ std::vector < float, gmx::AlignedAllocator < float>> pbb_;
+
+ /* Bit-flag information */
+ //! Flags for properties of clusters in each cell
+ std::vector<int> flags_;
+ //! Signal bits for atoms in each cell that tell whether an atom is perturbed
+ std::vector<unsigned int> fep_;
+
+ /* Statistics */
+ //! Total number of clusters, used for printing
+ int numClustersTotal_;