2 * This file is part of the GROMACS molecular simulation package.
4 * Copyright (c) 2019, by the GROMACS development team, led by
5 * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
6 * and including many others, as listed in the AUTHORS file in the
7 * top-level source directory and at http://www.gromacs.org.
9 * GROMACS is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public License
11 * as published by the Free Software Foundation; either version 2.1
12 * of the License, or (at your option) any later version.
14 * GROMACS is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with GROMACS; if not, see
21 * http://www.gnu.org/licenses, or write to the Free Software Foundation,
22 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
24 * If you want to redistribute modifications to GROMACS, please
25 * consider that scientific software is very special. Version
26 * control is crucial - bugs must be traceable. We will be happy to
27 * consider code for inclusion in the official distribution, but
28 * derived work must not be called official GROMACS. Details are found
29 * in the README & COPYING files - if they are missing, get the
30 * official version at http://www.gromacs.org.
32 * To help us fund GROMACS development, we humbly ask that you cite
33 * the research papers on the package. Check out http://www.gromacs.org.
39 * Implements the GridSet class.
41 * \author Berk Hess <hess@kth.se>
42 * \ingroup module_nbnxm
49 #include "gromacs/domdec/domdec_struct.h"
50 #include "gromacs/mdlib/gmx_omp_nthreads.h"
51 #include "gromacs/mdlib/updategroupscog.h"
52 #include "gromacs/nbnxm/nbnxm.h"
53 #include "gromacs/utility/fatalerror.h"
60 //! Returns the number of DD zones
61 static int numDDZones(const std::array<bool, DIM> &haveDomDecPerDim)
64 for (auto haveDD : haveDomDecPerDim)
75 GridSet::GridSet(const std::array<bool, DIM> &haveDomDecPerDim,
76 const PairlistType pairlistType,
78 const int numThreads) :
79 grids_(numDDZones(haveDomDecPerDim), pairlistType),
81 numRealAtomsLocal_(0),
82 numRealAtomsTotal_(0),
88 void GridSet::setLocalAtomOrder()
90 /* Set the atom order for the home cell (index 0) */
91 const Nbnxm::Grid &grid = grids_[0];
94 for (int cxy = 0; cxy < grid.numColumns(); cxy++)
96 const int numAtoms = grid.numAtomsInColumn(cxy);
97 int cellIndex = grid.firstCellInColumn(cxy)*grid.geometry().numAtomsPerCell;
98 for (int i = 0; i < numAtoms; i++)
100 atomIndices_[cellIndex] = atomIndex;
101 cells_[atomIndex] = cellIndex;
108 // TODO: Move to gridset.cpp
109 void GridSet::putOnGrid(const matrix box,
111 const rvec lowerCorner,
112 const rvec upperCorner,
113 const gmx::UpdateGroupsCog *updateGroupsCog,
118 gmx::ArrayRef<const gmx::RVec> x,
119 const int numAtomsMoved,
121 nbnxn_atomdata_t *nbat)
123 Nbnxm::Grid &grid = grids_[ddZone];
132 const Nbnxm::Grid &previousGrid = grids_[ddZone - 1];
133 cellOffset = previousGrid.atomIndexEnd()/previousGrid.geometry().numAtomsPerCell;
136 const int n = atomEnd - atomStart;
138 real maxAtomGroupRadius;
143 numRealAtomsLocal_ = atomEnd - numAtomsMoved;
144 /* We assume that nbnxn_put_on_grid is called first
145 * for the local atoms (ddZone=0).
147 numRealAtomsTotal_ = atomEnd - numAtomsMoved;
149 maxAtomGroupRadius = (updateGroupsCog ? updateGroupsCog->maxUpdateGroupRadius() : 0);
153 fprintf(debug, "natoms_local = %5d atom_density = %5.1f\n",
154 numRealAtomsLocal_, atomDensity);
159 const Nbnxm::Grid::Dimensions &dimsGrid0 = grids_[0].dimensions();
160 atomDensity = dimsGrid0.atomDensity;
161 maxAtomGroupRadius = dimsGrid0.maxAtomGroupRadius;
163 numRealAtomsTotal_ = std::max(numRealAtomsTotal_, atomEnd);
166 /* We always use the home zone (grid[0]) for setting the cell size,
167 * since determining densities for non-local zones is difficult.
169 grid.setDimensions(ddZone, n - numAtomsMoved,
170 lowerCorner, upperCorner,
175 for (GridWork &work : gridWork_)
177 work.numAtomsPerColumn.resize(grid.numColumns() + 1);
180 /* Make space for the new cell indices */
181 cells_.resize(atomEnd);
183 const int nthread = gmx_omp_nthreads_get(emntPairsearch);
185 #pragma omp parallel for num_threads(nthread) schedule(static)
186 for (int thread = 0; thread < nthread; thread++)
190 Grid::calcColumnIndices(grid.dimensions(),
192 atomStart, atomEnd, x,
193 ddZone, move, thread, nthread,
194 cells_, gridWork_[thread].numAtomsPerColumn);
196 GMX_CATCH_ALL_AND_EXIT_WITH_FATAL_ERROR;
199 GridSetData gridSetData = getGridSetData();
201 /* Copy the already computed cell indices to the grid and sort, when needed */
202 grid.setCellIndices(ddZone, cellOffset, &gridSetData, gridWork_,
203 atomStart, atomEnd, atinfo, x, numAtomsMoved, nbat);
207 nbat->natoms_local = nbat->numAtoms();
209 if (ddZone == gmx::ssize(grids_) - 1)
211 /* We are done setting up all grids, we can resize the force buffers */
212 nbat->resizeForceBuffers();
218 // TODO: Move this function to a proper location after refactoring nbnxn_search
219 void nbnxn_put_on_grid(nonbonded_verlet_t *nb_verlet,
222 const rvec lowerCorner,
223 const rvec upperCorner,
224 const gmx::UpdateGroupsCog *updateGroupsCog,
229 gmx::ArrayRef<const gmx::RVec> x,
233 nbnxn_search &nbs = *nb_verlet->nbs;
235 nbs_cycle_start(&nbs.cc[enbsCCgrid]);
237 nbs.gridSet_.putOnGrid(box, ddZone, lowerCorner, upperCorner,
238 updateGroupsCog, atomStart, atomEnd, atomDensity,
239 atinfo, x, numAtomsMoved, move,
240 nb_verlet->nbat.get());
242 nbs_cycle_stop(&nbs.cc[enbsCCgrid]);
245 /* Calls nbnxn_put_on_grid for all non-local domains */
246 void nbnxn_put_on_grid_nonlocal(nonbonded_verlet_t *nbv,
247 const struct gmx_domdec_zones_t *zones,
249 gmx::ArrayRef<const gmx::RVec> x)
251 for (int zone = 1; zone < zones->n; zone++)
254 for (int d = 0; d < DIM; d++)
256 c0[d] = zones->size[zone].bb_x0[d];
257 c1[d] = zones->size[zone].bb_x1[d];
260 nbnxn_put_on_grid(nbv, nullptr,
263 zones->cg_range[zone],
264 zones->cg_range[zone+1],
272 gmx::ArrayRef<const int> nbnxn_get_atomorder(const nbnxn_search *nbs)
274 /* Return the atom order for the home cell (index 0) */
275 const Nbnxm::Grid &grid = nbs->gridSet().grids()[0];
277 const int numIndices = grid.atomIndexEnd() - grid.firstAtomInColumn(0);
279 return gmx::constArrayRefFromArray(nbs->gridSet().atomIndices().data(), numIndices);
282 void nonbonded_verlet_t::setLocalAtomOrder()
284 nbs->gridSet_.setLocalAtomOrder();
287 void nonbonded_verlet_t::getLocalNumCells(int *numCellsX,
288 int *numCellsY) const
290 nbs->gridSet().getLocalNumCells(numCellsX, numCellsY);
293 gmx::ArrayRef<const int> nbnxn_get_gridindices(const nbnxn_search* nbs)
295 return nbs->gridSet().cells();