}
}
-//! Comparator for sorting charge groups.
-static bool comp_cgsort(const gmx_cgsort_t &a, const gmx_cgsort_t &b)
-{
-
- if (a.nsc == b.nsc)
- {
- return a.ind_gl < b.ind_gl;
- }
- return a.nsc < b.nsc;
-}
-
/*! \brief Order data in \p dataToSort according to \p sort
*
* Note: both buffers should have at least \p sort.size() elements.
}
}
-//! Returns whether a < b */
-static bool compareCgsort(const gmx_cgsort_t &a,
- const gmx_cgsort_t &b)
-{
- return (a.nsc < b.nsc ||
- (a.nsc == b.nsc && a.ind_gl < b.ind_gl));
-}
-
-//! Do sorting of charge groups.
-static void orderedSort(gmx::ArrayRef<const gmx_cgsort_t> stationary,
- gmx::ArrayRef<gmx_cgsort_t> moved,
- std::vector<gmx_cgsort_t> *sort1)
-{
- /* The new indices are not very ordered, so we qsort them */
- std::sort(moved.begin(), moved.end(), comp_cgsort);
-
- /* stationary is already ordered, so now we can merge the two arrays */
- sort1->resize(stationary.size() + moved.size());
- std::merge(stationary.begin(), stationary.end(),
- moved.begin(), moved.end(),
- sort1->begin(),
- compareCgsort);
-}
-
-/*! \brief Set the sorting order for systems with charge groups, returned in sort->sort.
- *
- * The order is according to the global charge group index.
- * This adds and removes charge groups that moved between domains.
- */
-static void dd_sort_order(const gmx_domdec_t *dd,
- const t_forcerec *fr,
- int ncg_home_old,
- gmx_domdec_sort_t *sort)
-{
- const int *a = fr->ns->grid->cell_index;
-
- const int movedValue = NSGRID_SIGNAL_MOVED_FAC*fr->ns->grid->ncells;
-
- if (ncg_home_old >= 0 && !sort->sorted.empty())
- {
- GMX_RELEASE_ASSERT(sort->sorted.size() == static_cast<size_t>(ncg_home_old),
- "The sorting buffer should contain the old home charge group indices");
-
- std::vector<gmx_cgsort_t> &stationary = sort->stationary;
- std::vector<gmx_cgsort_t> &moved = sort->moved;
-
- /* The charge groups that remained in the same ns grid cell
- * are completely ordered. So we can sort efficiently by sorting
- * the charge groups that did move into the stationary list.
- * Note: push_back() seems to be slightly slower than direct access.
- */
- stationary.clear();
- moved.clear();
- for (int i = 0; i < dd->ncg_home; i++)
- {
- /* Check if this cg did not move to another node */
- if (a[i] < movedValue)
- {
- gmx_cgsort_t entry;
- entry.nsc = a[i];
- entry.ind_gl = dd->globalAtomGroupIndices[i];
- entry.ind = i;
-
- if (i >= ncg_home_old || a[i] != sort->sorted[i].nsc)
- {
- /* This cg is new on this node or moved ns grid cell */
- moved.push_back(entry);
- }
- else
- {
- /* This cg did not move */
- stationary.push_back(entry);
- }
- }
- }
-
- if (debug)
- {
- fprintf(debug, "ordered sort cgs: stationary %zu moved %zu\n",
- stationary.size(), moved.size());
- }
- /* Sort efficiently */
- orderedSort(stationary, moved, &sort->sorted);
- }
- else
- {
- std::vector<gmx_cgsort_t> &cgsort = sort->sorted;
- cgsort.clear();
- cgsort.reserve(dd->ncg_home);
- int numCGNew = 0;
- for (int i = 0; i < dd->ncg_home; i++)
- {
- /* Sort on the ns grid cell indices
- * and the global topology index
- */
- gmx_cgsort_t entry;
- entry.nsc = a[i];
- entry.ind_gl = dd->globalAtomGroupIndices[i];
- entry.ind = i;
- cgsort.push_back(entry);
- if (cgsort[i].nsc < movedValue)
- {
- numCGNew++;
- }
- }
- if (debug)
- {
- fprintf(debug, "qsort cgs: %d new home %d\n", dd->ncg_home, numCGNew);
- }
- /* Determine the order of the charge groups using qsort */
- std::sort(cgsort.begin(), cgsort.end(), comp_cgsort);
-
- /* Remove the charge groups which are no longer at home here */
- cgsort.resize(numCGNew);
- }
-}
-
//! Returns the sorting order for atoms based on the nbnxn grid order in sort
static void dd_sort_order_nbnxn(const t_forcerec *fr,
std::vector<gmx_cgsort_t> *sort)
}
//! Returns the sorting state for DD.
-static void dd_sort_state(gmx_domdec_t *dd, rvec *cgcm, t_forcerec *fr, t_state *state,
- int ncg_home_old)
+static void dd_sort_state(gmx_domdec_t *dd, rvec *cgcm, t_forcerec *fr, t_state *state)
{
gmx_domdec_sort_t *sort = dd->comm->sort.get();
- switch (fr->cutoff_scheme)
- {
- case ecutsGROUP:
- dd_sort_order(dd, fr, ncg_home_old, sort);
- break;
- case ecutsVERLET:
- dd_sort_order_nbnxn(fr, &sort->sorted);
- break;
- default:
- gmx_incons("unimplemented");
- }
+ dd_sort_order_nbnxn(fr, &sort->sorted);
const gmx::RangePartitioning &atomGrouping = dd->atomGrouping();
/* Set the home atom number */
dd->comm->atomRanges.setEnd(DDAtomRanges::Type::Home, dd->atomGrouping().fullRange().end());
- if (fr->cutoff_scheme == ecutsVERLET)
- {
- /* The atoms are now exactly in grid order, update the grid order */
- fr->nbv->setLocalAtomOrder();
- }
- else
- {
- /* Copy the sorted ns cell indices back to the ns grid struct */
- for (gmx::index i = 0; i < cgsort.ssize(); i++)
- {
- fr->ns->grid->cell_index[i] = cgsort[i].nsc;
- }
- fr->ns->grid->nr = cgsort.size();
- }
+ /* The atoms are now exactly in grid order, update the grid order */
+ fr->nbv->setLocalAtomOrder();
}
//! Accumulates load statistics.
t_block *cgs_gl;
int64_t step_pcoupl;
rvec cell_ns_x0, cell_ns_x1;
- int ncgindex_set, ncg_home_old = -1, ncg_moved, nat_f_novirsum;
+ int ncgindex_set, ncg_moved, nat_f_novirsum;
gmx_bool bBoxChanged, bNStGlobalComm, bDoDLB, bCheckWhetherToTurnDlbOn, bLogLoad;
- gmx_bool bRedist, bResortAll;
- ivec ncells_old = {0, 0, 0}, ncells_new = {0, 0, 0}, np;
+ gmx_bool bRedist;
+ ivec np;
real grid_density;
char sbuf[22];
/* Check if we should sort the charge groups */
const bool bSortCG = (bMasterState || bRedist);
- ncg_home_old = dd->ncg_home;
-
/* When repartitioning we mark atom groups that will move to neighboring
* DD cells, but we do not move them right away for performance reasons.
* Thus we need to keep track of how many charge groups will move for
comm_dd_ns_cell_sizes(dd, &ddbox, cell_ns_x0, cell_ns_x1, step);
}
- switch (fr->cutoff_scheme)
- {
- case ecutsGROUP:
- copy_ivec(fr->ns->grid->n, ncells_old);
- grid_first(fplog, fr->ns->grid, dd, &ddbox,
- state_local->box, cell_ns_x0, cell_ns_x1,
- fr->rlist, grid_density);
- break;
- case ecutsVERLET:
- fr->nbv->getLocalNumCells(&ncells_old[XX], &ncells_old[YY]);
- break;
- default:
- gmx_incons("unimplemented");
- }
/* We need to store tric_dir for dd_get_ns_ranges called from ns.c */
copy_ivec(ddbox.tric_dir, comm->tric_dir);
*/
set_zones_ncg_home(dd);
- switch (fr->cutoff_scheme)
- {
- case ecutsVERLET:
- set_zones_size(dd, state_local->box, &ddbox, 0, 1, ncg_moved);
-
- nbnxn_put_on_grid(fr->nbv.get(), state_local->box,
- 0,
- comm->zones.size[0].bb_x0,
- comm->zones.size[0].bb_x1,
- comm->updateGroupsCog.get(),
- 0, dd->ncg_home,
- comm->zones.dens_zone0,
- fr->cginfo,
- state_local->x,
- ncg_moved, bRedist ? comm->movedBuffer.data() : nullptr);
-
- fr->nbv->getLocalNumCells(&ncells_new[XX], &ncells_new[YY]);
- break;
- case ecutsGROUP:
- fill_grid(&comm->zones, fr->ns->grid, dd->ncg_home,
- 0, dd->ncg_home, fr->cg_cm);
+ set_zones_size(dd, state_local->box, &ddbox, 0, 1, ncg_moved);
- copy_ivec(fr->ns->grid->n, ncells_new);
- break;
- default:
- gmx_incons("unimplemented");
- }
-
- bResortAll = bMasterState;
-
- /* Check if we can user the old order and ns grid cell indices
- * of the charge groups to sort the charge groups efficiently.
- */
- if (ncells_new[XX] != ncells_old[XX] ||
- ncells_new[YY] != ncells_old[YY] ||
- ncells_new[ZZ] != ncells_old[ZZ])
- {
- bResortAll = TRUE;
- }
+ nbnxn_put_on_grid(fr->nbv.get(), state_local->box,
+ 0,
+ comm->zones.size[0].bb_x0,
+ comm->zones.size[0].bb_x1,
+ comm->updateGroupsCog.get(),
+ 0, dd->ncg_home,
+ comm->zones.dens_zone0,
+ fr->cginfo,
+ state_local->x,
+ ncg_moved, bRedist ? comm->movedBuffer.data() : nullptr);
if (debug)
{
fprintf(debug, "Step %s, sorting the %d home charge groups\n",
gmx_step_str(step, sbuf), dd->ncg_home);
}
- dd_sort_state(dd, fr->cg_cm, fr, state_local,
- bResortAll ? -1 : ncg_home_old);
+ dd_sort_state(dd, fr->cg_cm, fr, state_local);
/* After sorting and compacting we set the correct size */
dd_resize_state(state_local, f, comm->atomRanges.numHomeAtoms());