}
//! Restore atom groups for the charge groups.
-static void restoreAtomGroups(gmx_domdec_t *dd,
- const int *gcgs_index, const t_state *state)
+static void restoreAtomGroups(gmx_domdec_t *dd,
+ const t_state *state)
{
gmx::ArrayRef<const int> atomGroupsState = state->cg_gl;
std::vector<int> &globalAtomGroupIndices = dd->globalAtomGroupIndices;
- gmx::RangePartitioning &atomGrouping = dd->atomGrouping_;
globalAtomGroupIndices.resize(atomGroupsState.size());
- atomGrouping.clear();
/* Copy back the global charge group indices from state
* and rebuild the local charge group to atom index.
*/
for (gmx::index i = 0; i < atomGroupsState.ssize(); i++)
{
- const int atomGroupGlobal = atomGroupsState[i];
- const int groupSize = gcgs_index[atomGroupGlobal + 1] - gcgs_index[atomGroupGlobal];
- globalAtomGroupIndices[i] = atomGroupGlobal;
- atomGrouping.appendBlock(groupSize);
+ globalAtomGroupIndices[i] = atomGroupsState[i];
}
dd->ncg_home = atomGroupsState.size();
- dd->comm->atomRanges.setEnd(DDAtomRanges::Type::Home, atomGrouping.fullRange().end());
+ dd->comm->atomRanges.setEnd(DDAtomRanges::Type::Home, atomGroupsState.ssize());
set_zones_ncg_home(dd);
}
static void dd_set_cginfo(gmx::ArrayRef<const int> index_gl, int cg0, int cg1,
t_forcerec *fr, char *bLocalCG)
{
- cginfo_mb_t *cginfo_mb;
- int *cginfo;
- int cg;
-
if (fr != nullptr)
{
- cginfo_mb = fr->cginfo_mb;
- cginfo = fr->cginfo;
+ const cginfo_mb_t *cginfo_mb = fr->cginfo_mb;
+ gmx::ArrayRef<int> cginfo = fr->cginfo;
- for (cg = cg0; cg < cg1; cg++)
+ for (int cg = cg0; cg < cg1; cg++)
{
cginfo[cg] = ddcginfo(cginfo_mb, index_gl[cg]);
}
if (bLocalCG != nullptr)
{
- for (cg = cg0; cg < cg1; cg++)
+ for (int cg = cg0; cg < cg1; cg++)
{
bLocalCG[index_gl[cg]] = TRUE;
}
//! Makes the mappings between global and local atom indices during DD repartioning.
static void make_dd_indices(gmx_domdec_t *dd,
- const int *gcgs_index, int cg_start)
+ const int atomStart)
{
const int numZones = dd->comm->zones.n;
const int *zone2cg = dd->comm->zones.cg_range;
const int *zone_ncg1 = dd->comm->zone_ncg1;
gmx::ArrayRef<const int> globalAtomGroupIndices = dd->globalAtomGroupIndices;
- const gmx_bool bCGs = dd->comm->bCGs;
std::vector<int> &globalAtomIndices = dd->globalAtomIndices;
gmx_ga2la_t &ga2la = *dd->ga2la;
}
/* Make the local to global and global to local atom index */
- int a = dd->atomGrouping().subRange(cg_start, cg_start).begin();
+ int a = atomStart;
globalAtomIndices.resize(a);
for (int zone = 0; zone < numZones; zone++)
{
int cg0;
if (zone == 0)
{
- cg0 = cg_start;
+ cg0 = atomStart;
}
else
{
zone1 += numZones;
}
int cg_gl = globalAtomGroupIndices[cg];
- if (bCGs)
- {
- for (int a_gl = gcgs_index[cg_gl]; a_gl < gcgs_index[cg_gl+1]; a_gl++)
- {
- globalAtomIndices.push_back(a_gl);
- ga2la.insert(a_gl, {a, zone1});
- a++;
- }
- }
- else
- {
- globalAtomIndices.push_back(cg_gl);
- ga2la.insert(cg_gl, {a, zone1});
- a++;
- }
+ globalAtomIndices.push_back(cg_gl);
+ ga2la.insert(cg_gl, {a, zone1});
+ a++;
}
}
}
}
}
-//! Merges charge-group buffers.
+//! Merge atom buffers.
static void merge_cg_buffers(int ncell,
gmx_domdec_comm_dim_t *cd, int pulse,
int *ncg_cell,
gmx::ArrayRef<int> index_gl,
const int *recv_i,
- rvec *cg_cm, rvec *recv_vr,
- gmx::ArrayRef<int> cgindex,
- cginfo_mb_t *cginfo_mb, int *cginfo)
+ gmx::ArrayRef<gmx::RVec> x,
+ gmx::ArrayRef<const gmx::RVec> recv_vr,
+ cginfo_mb_t *cginfo_mb,
+ gmx::ArrayRef<int> cginfo)
{
gmx_domdec_ind_t *ind, *ind_p;
- int p, cell, c, cg, cg0, cg1, cg_gl, nat;
- int shift, shift_at;
+ int p, cell, c, cg, cg0, cg1, cg_gl;
+ int shift;
ind = &cd->ind[pulse];
/* Move the cg's present from previous grid pulses */
cg0 = ncg_cell[ncell+cell];
cg1 = ncg_cell[ncell+cell+1];
- cgindex[cg1+shift] = cgindex[cg1];
for (cg = cg1-1; cg >= cg0; cg--)
{
- index_gl[cg+shift] = index_gl[cg];
- copy_rvec(cg_cm[cg], cg_cm[cg+shift]);
- cgindex[cg+shift] = cgindex[cg];
- cginfo[cg+shift] = cginfo[cg];
+ index_gl[cg + shift] = index_gl[cg];
+ x[cg + shift] = x[cg];
+ cginfo[cg + shift] = cginfo[cg];
}
/* Correct the already stored send indices for the shift */
for (p = 1; p <= pulse; p++)
/* Merge in the communicated buffers */
shift = 0;
- shift_at = 0;
cg0 = 0;
for (cell = 0; cell < ncell; cell++)
{
cg1 = ncg_cell[ncell+cell+1] + shift;
- if (shift_at > 0)
- {
- /* Correct the old cg indices */
- for (cg = ncg_cell[ncell+cell]; cg < cg1; cg++)
- {
- cgindex[cg+1] += shift_at;
- }
- }
for (cg = 0; cg < ind->nrecv[cell]; cg++)
{
- /* Copy this charge group from the buffer */
+ /* Copy this atom from the buffer */
index_gl[cg1] = recv_i[cg0];
- copy_rvec(recv_vr[cg0], cg_cm[cg1]);
- /* Add it to the cgindex */
+ x[cg1] = recv_vr[cg0];
+ /* Copy information */
cg_gl = index_gl[cg1];
cginfo[cg1] = ddcginfo(cginfo_mb, cg_gl);
- nat = GET_CGINFO_NATOMS(cginfo[cg1]);
- cgindex[cg1+1] = cgindex[cg1] + nat;
cg0++;
cg1++;
- shift_at += nat;
}
shift += ind->nrecv[cell];
ncg_cell[ncell+cell+1] = cg1;
//! Makes a range partitioning for the atom groups wthin a cell
static void make_cell2at_index(gmx_domdec_comm_dim_t *cd,
int nzone,
- int atomGroupStart,
- const gmx::RangePartitioning &atomGroups)
+ int atomGroupStart)
{
/* Store the atom block boundaries for easy copying of communication buffers
*/
{
for (gmx_domdec_ind_t &ind : cd->ind)
{
- const auto range = atomGroups.subRange(g, g + ind.nrecv[zone]);
- ind.cell2at0[zone] = range.begin();
- ind.cell2at1[zone] = range.end();
+ ind.cell2at0[zone] = g;
g += ind.nrecv[zone];
+ ind.cell2at1[zone] = g;
}
}
}
int zonei, int zone,
int cg0, int cg1,
gmx::ArrayRef<const int> globalAtomGroupIndices,
- const gmx::RangePartitioning &atomGroups,
int dim, int dim_ind,
int dim0, int dim1, int dim2,
real r_comm2, real r_bcomm2,
gmx_bool bDist2B,
gmx_bool bDistMB,
rvec *cg_cm,
- const int *cginfo,
+ gmx::ArrayRef<const int> cginfo,
std::vector<int> *localAtomGroups,
dd_comm_setup_work_t *work)
{
}
vbuf.emplace_back(posPbc[XX], posPbc[YY], posPbc[ZZ]);
- nat += atomGroups.block(cg).size();
+ nat += 1;
}
}
{
int dim_ind, dim, dim0, dim1, dim2, dimd, nat_tot;
int nzone, nzone_send, zone, zonei, cg0, cg1;
- int c, i, cg, cg_gl, nrcg;
+ int c, i, cg, cg_gl;
int *zone_cg_range, pos_cg;
gmx_domdec_comm_t *comm;
gmx_domdec_zones_t *zones;
cginfo_mb_t *cginfo_mb;
gmx_bool bBondComm, bDist2B, bDistMB, bDistBonded;
dd_corners_t corners;
- rvec *cg_cm, *normal, *v_d, *v_0 = nullptr, *v_1 = nullptr;
+ rvec *normal, *v_d, *v_0 = nullptr, *v_1 = nullptr;
real skew_fac2_d, skew_fac_01;
rvec sf2_round;
comm->dth.resize(numThreads);
}
- switch (fr->cutoff_scheme)
- {
- case ecutsGROUP:
- cg_cm = fr->cg_cm;
- break;
- case ecutsVERLET:
- cg_cm = state->x.rvec_array();
- break;
- default:
- gmx_incons("unimplemented");
- }
-
bBondComm = comm->bBondComm;
/* Do we need to determine extra distances for multi-body bondeds? */
- bDistMB = (comm->bInterCGMultiBody && isDlbOn(dd->comm) && dd->ndim > 1);
+ bDistMB = (comm->haveInterDomainMultiBodyBondeds && isDlbOn(dd->comm) && dd->ndim > 1);
/* Do we need to determine extra distances for only two-body bondeds? */
bDist2B = (bBondComm && !bDistMB);
/* Get the cg's for this pulse in this zone */
get_zone_pulse_cgs(dd, zonei, zone, cg0_th, cg1_th,
dd->globalAtomGroupIndices,
- dd->atomGrouping(),
dim, dim_ind, dim0, dim1, dim2,
r_comm2, r_bcomm2,
box, distanceIsTriclinic,
v_d, v_0, v_1, &corners, sf2_round,
bDistBonded, bBondComm,
bDist2B, bDistMB,
- cg_cm, fr->cginfo,
+ state->x.rvec_array(),
+ fr->cginfo,
th == 0 ? &ind->index : &work.localAtomGroupBuffer,
&work);
}
/* Make space for cg_cm */
dd_check_alloc_ncg(fr, state, f, pos_cg + ind->nrecv[nzone]);
- if (fr->cutoff_scheme == ecutsGROUP)
- {
- cg_cm = fr->cg_cm;
- }
- else
- {
- cg_cm = state->x.rvec_array();
- }
- /* Communicate cg_cm */
+
+ /* Communicate the coordinates */
gmx::ArrayRef<gmx::RVec> rvecBufferRef;
if (cd->receiveInPlace)
{
- rvecBufferRef = gmx::arrayRefFromArray(reinterpret_cast<gmx::RVec *>(cg_cm + pos_cg), ind->nrecv[nzone]);
+ rvecBufferRef = gmx::makeArrayRef(state->x).subArray(pos_cg, ind->nrecv[nzone]);
}
else
{
{
cg_gl = dd->globalAtomGroupIndices[pos_cg];
fr->cginfo[pos_cg] = ddcginfo(cginfo_mb, cg_gl);
- nrcg = GET_CGINFO_NATOMS(fr->cginfo[pos_cg]);
- dd->atomGrouping_.appendBlock(nrcg);
if (bBondComm)
{
/* Update the charge group presence,
else
{
/* This part of the code is never executed with bBondComm. */
- std::vector<int> &atomGroupsIndex = dd->atomGrouping_.rawIndex();
- atomGroupsIndex.resize(numAtomGroupsNew + 1);
-
merge_cg_buffers(nzone, cd, p, zone_cg_range,
dd->globalAtomGroupIndices, integerBufferRef.data(),
- cg_cm, as_rvec_array(rvecBufferRef.data()),
- atomGroupsIndex,
+ state->x, rvecBufferRef,
fr->cginfo_mb, fr->cginfo);
pos_cg += ind->nrecv[nzone];
}
if (!cd->receiveInPlace)
{
/* Store the atom block for easy copying of communication buffers */
- make_cell2at_index(cd, nzone, zone_cg_range[nzone], dd->atomGrouping());
+ make_cell2at_index(cd, nzone, zone_cg_range[nzone]);
}
nzone += nzone;
}
zones = &comm->zones;
/* Do we need to determine extra distances for multi-body bondeds? */
- bDistMB = (comm->bInterCGMultiBody && isDlbOn(dd->comm) && dd->ndim > 1);
+ bDistMB = (comm->haveInterDomainMultiBodyBondeds && isDlbOn(dd->comm) && dd->ndim > 1);
for (z = zone_start; z < zone_end; z++)
{
orderVector<T>(sort, vectorToSort, *workVector);
}
-//! Order vectors of atoms.
-static void order_vec_atom(const gmx::RangePartitioning *atomGroups,
- gmx::ArrayRef<const gmx_cgsort_t> sort,
- gmx::ArrayRef<gmx::RVec> v,
- gmx::ArrayRef<gmx::RVec> buf)
-{
- if (atomGroups == nullptr)
- {
- /* Avoid the useless loop of the atoms within a cg */
- orderVector(sort, v, buf);
-
- return;
- }
-
- /* Order the data */
- int a = 0;
- for (const gmx_cgsort_t &entry : sort)
- {
- for (int i : atomGroups->block(entry.ind))
- {
- copy_rvec(v[i], buf[a]);
- a++;
- }
- }
- int atot = a;
-
- /* Copy back to the original array */
- for (int a = 0; a < atot; a++)
- {
- copy_rvec(buf[a], v[a]);
- }
-}
-
//! 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)
+static void dd_sort_state(gmx_domdec_t *dd, t_forcerec *fr, t_state *state)
{
gmx_domdec_sort_t *sort = dd->comm->sort.get();
dd_sort_order_nbnxn(fr, &sort->sorted);
- const gmx::RangePartitioning &atomGrouping = dd->atomGrouping();
-
/* We alloc with the old size, since cgindex is still old */
- GMX_ASSERT(atomGrouping.numBlocks() == dd->ncg_home, "atomGroups and dd should be consistent");
- DDBufferAccess<gmx::RVec> rvecBuffer(dd->comm->rvecBuffer, atomGrouping.fullRange().end());
-
- const gmx::RangePartitioning *atomGroupsPtr = (dd->comm->bCGs ? &atomGrouping : nullptr);
+ DDBufferAccess<gmx::RVec> rvecBuffer(dd->comm->rvecBuffer, dd->ncg_home);
/* Set the new home atom/charge group count */
dd->ncg_home = sort->sorted.size();
if (debug)
{
- fprintf(debug, "Set the new home %s count to %d\n",
- dd->comm->bCGs ? "charge group" : "atom",
+ fprintf(debug, "Set the new home atom count to %d\n",
dd->ncg_home);
}
if (state->flags & (1 << estX))
{
- order_vec_atom(atomGroupsPtr, cgsort, state->x, rvecBuffer.buffer);
+ orderVector(cgsort, makeArrayRef(state->x), rvecBuffer.buffer);
}
if (state->flags & (1 << estV))
{
- order_vec_atom(atomGroupsPtr, cgsort, state->v, rvecBuffer.buffer);
+ orderVector(cgsort, makeArrayRef(state->v), rvecBuffer.buffer);
}
if (state->flags & (1 << estCGP))
{
- order_vec_atom(atomGroupsPtr, cgsort, state->cg_p, rvecBuffer.buffer);
- }
-
- if (fr->cutoff_scheme == ecutsGROUP)
- {
- /* Reorder cgcm */
- gmx::ArrayRef<gmx::RVec> cgcmRef = gmx::arrayRefFromArray(reinterpret_cast<gmx::RVec *>(cgcm[0]), cgsort.size());
- orderVector(cgsort, cgcmRef, rvecBuffer.buffer);
+ orderVector(cgsort, makeArrayRef(state->cg_p), rvecBuffer.buffer);
}
/* Reorder the global cg index */
orderVector<int>(cgsort, dd->globalAtomGroupIndices, &sort->intBuffer);
/* Reorder the cginfo */
- orderVector<int>(cgsort, gmx::arrayRefFromArray(fr->cginfo, cgsort.size()), &sort->intBuffer);
- /* Rebuild the local cg index */
- if (dd->comm->bCGs)
- {
- /* We make a new, ordered atomGroups object and assign it to
- * the old one. This causes some allocation overhead, but saves
- * a copy back of the whole index.
- */
- gmx::RangePartitioning ordered;
- for (const gmx_cgsort_t &entry : cgsort)
- {
- ordered.appendBlock(atomGrouping.block(entry.ind).size());
- }
- dd->atomGrouping_ = ordered;
- }
- else
- {
- dd->atomGrouping_.setAllBlocksSizeOne(dd->ncg_home);
- }
+ orderVector<int>(cgsort, fr->cginfo, &sort->intBuffer);
/* Set the home atom number */
- dd->comm->atomRanges.setEnd(DDAtomRanges::Type::Home, dd->atomGrouping().fullRange().end());
+ dd->comm->atomRanges.setEnd(DDAtomRanges::Type::Home, dd->ncg_home);
/* The atoms are now exactly in grid order, update the grid order */
fr->nbv->setLocalAtomOrder();
gmx_domdec_t *dd;
gmx_domdec_comm_t *comm;
gmx_ddbox_t ddbox = {0};
- t_block *cgs_gl;
int64_t step_pcoupl;
rvec cell_ns_x0, cell_ns_x1;
int ncgindex_set, ncg_moved, nat_f_novirsum;
comm->n_load_have++;
}
- cgs_gl = &comm->cgs_gl;
-
bRedist = FALSE;
if (bMasterState)
{
distributeState(mdlog, dd, top_global, state_global, ddbox, state_local, f);
- dd_make_local_cgs(dd, &top_local->cgs);
-
/* Ensure that we have space for the new distribution */
dd_check_alloc_ncg(fr, state_local, f, dd->ncg_home);
- if (fr->cutoff_scheme == ecutsGROUP)
- {
- calc_cgcm(fplog, 0, dd->ncg_home,
- &top_local->cgs, state_local->x.rvec_array(), fr->cg_cm);
- }
-
inc_nrnb(nrnb, eNR_CGCM, comm->atomRanges.numHomeAtoms());
dd_set_cginfo(dd->globalAtomGroupIndices, 0, dd->ncg_home, fr, comm->bLocalCG);
clearDDStateIndices(dd, 0, 0);
/* Restore the atom group indices from state_local */
- restoreAtomGroups(dd, cgs_gl->index, state_local);
- make_dd_indices(dd, cgs_gl->index, 0);
+ restoreAtomGroups(dd, state_local);
+ make_dd_indices(dd, 0);
ncgindex_set = dd->ncg_home;
- if (fr->cutoff_scheme == ecutsGROUP)
- {
- /* Redetermine the cg COMs */
- calc_cgcm(fplog, 0, dd->ncg_home,
- &top_local->cgs, state_local->x.rvec_array(), fr->cg_cm);
- }
-
inc_nrnb(nrnb, eNR_CGCM, comm->atomRanges.numHomeAtoms());
dd_set_cginfo(dd->globalAtomGroupIndices, 0, dd->ncg_home, fr, comm->bLocalCG);
wallcycle_sub_stop(wcycle, ewcsDD_REDIST);
}
+ // TODO: Integrate this code in the nbnxm module
get_nsgrid_boundaries(ddbox.nboundeddim, state_local->box,
dd, &ddbox,
&comm->cell_x0, &comm->cell_x1,
- dd->ncg_home, fr->cg_cm,
+ dd->ncg_home, as_rvec_array(state_local->x.data()),
cell_ns_x0, cell_ns_x1, &grid_density);
if (bBoxChanged)
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);
+ dd_sort_state(dd, fr, state_local);
/* After sorting and compacting we set the correct size */
dd_resize_state(state_local, f, comm->atomRanges.numHomeAtoms());
setup_dd_communication(dd, state_local->box, &ddbox, fr, state_local, f);
/* Set the indices */
- make_dd_indices(dd, cgs_gl->index, ncgindex_set);
+ make_dd_indices(dd, ncgindex_set);
/* Set the charge group boundaries for neighbor searching */
set_cg_boundaries(&comm->zones);
dd_make_local_top(dd, &comm->zones, dd->npbcdim, state_local->box,
comm->cellsize_min, np,
fr,
- fr->cutoff_scheme == ecutsGROUP ? fr->cg_cm : state_local->x.rvec_array(),
+ state_local->x.rvec_array(),
top_global, top_local);
wallcycle_sub_stop(wcycle, ewcsDD_MAKETOP);
if (dd->splitConstraints || dd->splitSettles)
{
/* Only for inter-cg constraints we need special code */
- n = dd_make_local_constraints(dd, n, &top_global, fr->cginfo,
+ n = dd_make_local_constraints(dd, n, &top_global, fr->cginfo.data(),
constr, ir->nProjOrder,
top_local->idef.il);
}