/*! \brief Sets up the relation between neighboring domains and zones */
static void setup_neighbor_relations(gmx_domdec_t *dd)
{
- int d, dim, i, j, m;
+ int d, dim, m;
ivec tmp, s;
gmx_domdec_zones_t *zones;
- gmx_domdec_ns_ranges_t *izone;
GMX_ASSERT((dd->ndim >= 0) && (dd->ndim <= DIM), "Must have valid number of dimensions for DD");
for (d = 0; d < dd->ndim; d++)
zones = &dd->comm->zones;
- for (i = 0; i < nzone; i++)
+ for (int i = 0; i < nzone; i++)
{
m = 0;
clear_ivec(zones->shift[i]);
}
zones->n = nzone;
- for (i = 0; i < nzone; i++)
+ for (int i = 0; i < nzone; i++)
{
for (d = 0; d < DIM; d++)
{
}
}
}
- zones->nizone = nizone;
- for (i = 0; i < zones->nizone; i++)
+ for (int iZoneIndex = 0; iZoneIndex < nizone; iZoneIndex++)
{
- assert(ddNonbondedZonePairRanges[i][0] == i);
+ GMX_RELEASE_ASSERT(ddNonbondedZonePairRanges[iZoneIndex][0] == iZoneIndex,
+ "The first element for each ddNonbondedZonePairRanges should match its index");
- izone = &zones->izone[i];
+ DDPairInteractionRanges iZone;
+ iZone.iZoneIndex = iZoneIndex;
/* dd_zp3 is for 3D decomposition, for fewer dimensions use only
* j-zones up to nzone.
*/
- izone->j0 = std::min(ddNonbondedZonePairRanges[i][1], nzone);
- izone->j1 = std::min(ddNonbondedZonePairRanges[i][2], nzone);
+ iZone.jZoneRange =
+ gmx::Range<int>(std::min(ddNonbondedZonePairRanges[iZoneIndex][1], nzone),
+ std::min(ddNonbondedZonePairRanges[iZoneIndex][2], nzone));
for (dim = 0; dim < DIM; dim++)
{
if (dd->nc[dim] == 1)
{
/* All shifts should be allowed */
- izone->shift0[dim] = -1;
- izone->shift1[dim] = 1;
+ iZone.shift0[dim] = -1;
+ iZone.shift1[dim] = 1;
}
else
{
/* Determine the min/max j-zone shift wrt the i-zone */
- izone->shift0[dim] = 1;
- izone->shift1[dim] = -1;
- for (j = izone->j0; j < izone->j1; j++)
+ iZone.shift0[dim] = 1;
+ iZone.shift1[dim] = -1;
+ for (int jZone : iZone.jZoneRange)
{
- int shift_diff = zones->shift[j][dim] - zones->shift[i][dim];
- if (shift_diff < izone->shift0[dim])
+ int shift_diff = zones->shift[jZone][dim] - zones->shift[iZoneIndex][dim];
+ if (shift_diff < iZone.shift0[dim])
{
- izone->shift0[dim] = shift_diff;
+ iZone.shift0[dim] = shift_diff;
}
- if (shift_diff > izone->shift1[dim])
+ if (shift_diff > iZone.shift1[dim])
{
- izone->shift1[dim] = shift_diff;
+ iZone.shift1[dim] = shift_diff;
}
}
}
}
+
+ zones->iZones.push_back(iZone);
}
if (!isDlbDisabled(dd->comm))
#include <cstddef>
+#include <array>
#include <memory>
#include <vector>
#include "gromacs/topology/block.h"
#include "gromacs/utility/basedefinitions.h"
#include "gromacs/utility/gmxmpi.h"
+#include "gromacs/utility/range.h"
#include "gromacs/utility/real.h"
//! Max number of zones in domain decomposition
class GpuHaloExchange;
}
-typedef struct {
- /* j-zone start */
- int j0 = 0;
- /* j-zone end */
- int j1 = 0;
- /* i-charge-group end */
- int cg1 = 0;
- /* j-charge-group start */
- int jcg0 = 0;
- /* j-charge-group end */
- int jcg1 = 0;
- /* Minimum shifts to consider */
- ivec shift0 = { };
- /* Maximum shifts to consider */
- ivec shift1 = { };
-} gmx_domdec_ns_ranges_t;
+/*! \internal
+ * \brief Pair interaction zone and atom range for an i-zone
+ */
+struct DDPairInteractionRanges
+{
+ //! The index of this i-zone in the i-zone list
+ int iZoneIndex = -1;
+ //! The range of j-zones
+ gmx::Range<int> jZoneRange;
+ //! The i-atom range
+ gmx::Range<int> iAtomRange;
+ //! The j-atom range
+ gmx::Range<int> jAtomRange;
+ //! Minimum shifts to consider
+ ivec shift0 = { };
+ //! Maximum shifts to consider
+ ivec shift1 = { };
+};
typedef struct {
/* Zone lower corner in triclinic coordinates */
struct gmx_domdec_zones_t {
/* The number of zones including the home zone */
- int n = 0;
+ int n = 0;
/* The shift of the zones with respect to the home zone */
- ivec shift[DD_MAXZONE] = { };
+ ivec shift[DD_MAXZONE] = { };
/* The charge group boundaries for the zones */
- int cg_range[DD_MAXZONE+1] = { };
- /* The number of neighbor search zones with i-particles */
- int nizone = 0;
- /* The neighbor search charge group ranges for each i-zone */
- gmx_domdec_ns_ranges_t izone[DD_MAXIZONE];
+ int cg_range[DD_MAXZONE+1] = { };
+ /* The pair interaction zone and atom ranges per each i-zone */
+ std::vector<DDPairInteractionRanges> iZones;
/* Boundaries of the zones */
- gmx_domdec_zone_size_t size[DD_MAXZONE];
+ gmx_domdec_zone_size_t size[DD_MAXZONE];
/* The cg density of the home zone */
- real dens_zone0 = 0;
+ real dens_zone0 = 0;
};
struct gmx_ddbox_t {
gmx_bool bBCheck,
int *nbonded_local)
{
- int j;
+ gmx::ArrayRef<const DDPairInteractionRanges> iZones = zones->iZones;
- j = ind_start;
+ int j = ind_start;
while (j < ind_end)
{
t_iatom tiatoms[1 + MAXATOMLIST];
kz -= zones->n;
}
/* Check zone interaction assignments */
- bUse = ((iz < zones->nizone &&
+ bUse = ((iz < iZones.ssize() &&
iz <= kz &&
- kz >= zones->izone[iz].j0 &&
- kz < zones->izone[iz].j1) ||
- (kz < zones->nizone &&
+ iZones[iz].jZoneRange.isInRange(kz)) ||
+ (kz < iZones.ssize() &&
iz > kz &&
- iz >= zones->izone[kz].j0 &&
- iz < zones->izone[kz].j1));
+ iZones[kz].jZoneRange.isInRange(iz)));
if (bUse)
{
GMX_ASSERT(ftype != F_CONSTR || (iz == 0 && kz == 0),
const gmx_ga2la_t &ga2la = *dd->ga2la;
- /* Extract the j-atom range */
- const gmx::Range<int> jRange(zones->izone[iz].jcg0,
- zones->izone[iz].jcg1);
+ const auto &jAtomRange = zones->iZones[iz].jAtomRange;
n_excl_at_max = dd->reverse_top->n_excl_at_max;
* the number of exclusions in the list, which in turn
* can speed up the pair list construction a bit.
*/
- if (jRange.isInRange(jEntry->la))
+ if (jAtomRange.isInRange(jEntry->la))
{
lexcls->a[n++] = jEntry->la;
}
}
/*! \brief Ensure that we have enough space for exclusion storate in \p lexcls */
-static void check_exclusions_alloc(gmx_domdec_t *dd, gmx_domdec_zones_t *zones,
- t_blocka *lexcls)
+static void check_exclusions_alloc(const gmx_domdec_t *dd,
+ const gmx_domdec_zones_t *zones,
+ t_blocka *lexcls)
{
- const int nr = zones->izone[zones->nizone - 1].cg1;
+ const int nr = zones->iZones.back().iAtomRange.end();
check_alloc_index(lexcls, nr);
static void finish_local_exclusions(gmx_domdec_t *dd, gmx_domdec_zones_t *zones,
t_blocka *lexcls)
{
- const gmx::Range<int> nonhomeIzonesAtomRange(zones->izone[0].cg1,
- zones->izone[zones->nizone - 1].cg1);
+ const gmx::Range<int> nonhomeIzonesAtomRange(zones->iZones[0].iAtomRange.end(),
+ zones->iZones.back().iAtomRange.end());
if (!dd->haveExclusions)
{
t_blocka *lexcls, int *excl_count)
{
int nzone_bondeds, nzone_excl;
- int izone, cg0, cg1;
+ int cg0, cg1;
real rc2;
int nbonded_local;
gmx_reverse_top_t *rt;
if (dd->haveExclusions)
{
/* We only use exclusions from i-zones to i- and j-zones */
- nzone_excl = zones->nizone;
+ nzone_excl = zones->iZones.size();
}
else
{
lexcls->nra = 0;
*excl_count = 0;
- for (izone = 0; izone < nzone_bondeds; izone++)
+ for (int izone = 0; izone < nzone_bondeds; izone++)
{
cg0 = zones->cg_range[izone];
cg1 = zones->cg_range[izone + 1];
/* Some zones might not have exclusions, but some code still needs to
* loop over the index, so we set the indices here.
*/
- for (izone = nzone_excl; izone < zones->nizone; izone++)
+ for (size_t iZone = nzone_excl; iZone < zones->iZones.size(); iZone++)
{
- set_no_exclusions_zone(zones, izone, lexcls);
+ set_no_exclusions_zone(zones, iZone, lexcls);
}
finish_local_exclusions(dd, zones, lexcls);
{
const gmx_domdec_comm_t *comm;
const gmx_domdec_zones_t *zones;
- int i, j;
comm = dd->comm;
if (dd->ndim >= 3)
{
dim2 = dd->dim[2];
- for (j = 0; j < 4; j++)
+ for (int j = 0; j < 4; j++)
{
c->c[2][j] = comm->cell_x0[dim2];
}
if (isDlbOn(dd->comm))
{
/* Use the maximum of the i-cells that see a j-cell */
- for (i = 0; i < zones->nizone; i++)
+ for (const auto &iZone : zones->iZones)
{
- for (j = zones->izone[i].j0; j < zones->izone[i].j1; j++)
+ const int iZoneIndex = iZone.iZoneIndex;
+ for (int jZone : iZone.jZoneRange)
{
- if (j >= 4)
+ if (jZone >= 4)
{
- c->c[2][j-4] =
- std::max(c->c[2][j-4],
- comm->zone_d2[zones->shift[i][dim0]][zones->shift[i][dim1]].mch0);
+ c->c[2][jZone - 4] =
+ std::max(c->c[2][jZone - 4],
+ comm->zone_d2[zones->shift[iZoneIndex][dim0]][zones->shift[iZoneIndex][dim1]].mch0);
}
}
}
{
/* For the multi-body distance we need the maximum */
c->bc[2] = comm->cell_x0[dim2];
- for (i = 0; i < 2; i++)
+ for (int i = 0; i < 2; i++)
{
- for (j = 0; j < 2; j++)
+ for (int j = 0; j < 2; j++)
{
c->bc[2] = std::max(c->bc[2], comm->zone_d2[i][j].p1_0);
}
//! Set boundaries for the charge group range.
static void set_cg_boundaries(gmx_domdec_zones_t *zones)
{
- int c;
-
- for (c = 0; c < zones->nizone; c++)
+ for (auto &iZone : zones->iZones)
{
- zones->izone[c].cg1 = zones->cg_range[c+1];
- zones->izone[c].jcg0 = zones->cg_range[zones->izone[c].j0];
- zones->izone[c].jcg1 = zones->cg_range[zones->izone[c].j1];
+ iZone.iAtomRange = gmx::Range<int>(0, zones->cg_range[iZone.iZoneIndex + 1]);
+ iZone.jAtomRange =
+ gmx::Range<int>(zones->cg_range[iZone.jZoneRange.begin()],
+ zones->cg_range[iZone.jZoneRange.end()]);
}
}
gmx_domdec_comm_t *comm;
gmx_domdec_zones_t *zones;
gmx_bool bDistMB;
- int z, zi, d, dim;
+ int z, d, dim;
real rcs, rcmbs;
int i, j;
real vol;
if (bDistMB)
{
- for (zi = 0; zi < zones->nizone; zi++)
+ for (size_t zi = 0; zi < zones->iZones.size(); zi++)
{
if (zones->shift[zi][dim] == 0)
{
/* Loop over the i-zones to set the upper limit of each
* j-zone they see.
*/
- for (zi = 0; zi < zones->nizone; zi++)
+ for (const auto &iZone : zones->iZones)
{
+ const int zi = iZone.iZoneIndex;
if (zones->shift[zi][dim] == 0)
{
/* We should only use zones up to zone_end */
- int jZoneEnd = std::min(zones->izone[zi].j1, zone_end);
- for (z = zones->izone[zi].j0; z < jZoneEnd; z++)
+ const auto &jZoneRangeFull = iZone.jZoneRange;
+ if (zone_end <= *jZoneRangeFull.begin())
+ {
+ continue;
+ }
+ const gmx::Range<int> jZoneRange(*jZoneRangeFull.begin(),
+ std::min(*jZoneRangeFull.end(), zone_end));
+ for (int jZone : jZoneRange)
{
- if (zones->shift[z][dim] > 0)
+ if (zones->shift[jZone][dim] > 0)
{
- zones->size[z].x1[dim] = std::max(zones->size[z].x1[dim],
- zones->size[zi].x1[dim]+rcs);
+ zones->size[jZone].x1[dim] = std::max(zones->size[jZone].x1[dim],
+ zones->size[zi].x1[dim]+rcs);
}
}
}
}
else
{
- nzi = gridSet.domainSetup().zones->nizone;
+ nzi = gridSet.domainSetup().zones->iZones.size();
}
if (!isCpuType_ && minimumIlistCountForGpuBalancing > 0)
}
const Grid &iGrid = gridSet.grids()[zi];
- int zj0;
- int zj1;
+ Range<int> jZoneRange;
if (locality_ == InteractionLocality::Local)
{
- zj0 = 0;
- zj1 = 1;
+ jZoneRange = Range<int>(0, 1);
}
else
{
- zj0 = ddZones->izone[zi].j0;
- zj1 = ddZones->izone[zi].j1;
- if (zi == 0)
- {
- zj0++;
- }
+ jZoneRange = Range<int>(ddZones->iZones[zi].jZoneRange.begin() + (zi == 0 ? 1 : 0),
+ ddZones->iZones[zi].jZoneRange.end());
}
- for (int zj = zj0; zj < zj1; zj++)
+ for (int jZone : jZoneRange)
{
- const Grid &jGrid = gridSet.grids()[zj];
+ const Grid &jGrid = gridSet.grids()[jZone];
if (debug)
{
- fprintf(debug, "ns search grid %d vs %d\n", zi, zj);
+ fprintf(debug, "ns search grid %d vs %d\n", zi, jZone);
}
searchCycleCounting->start(enbsCCsearch);
/* Re-init the thread-local work flag data before making
* the first list (not an elegant conditional).
*/
- if (nbat->bUseBufferFlags && ((zi == 0 && zj == 0)))
+ if (nbat->bUseBufferFlags && (zi == 0 && jZone == 0))
{
init_buffer_flags(&searchWork[th].buffer_flags, nbat->numAtoms());
}