Use gmx::Range in domdec
authorBerk Hess <hess@kth.se>
Wed, 25 Sep 2019 09:42:29 +0000 (11:42 +0200)
committerMark Abraham <mark.j.abraham@gmail.com>
Tue, 1 Oct 2019 16:25:12 +0000 (18:25 +0200)
Renamed gmx_domdec_ns_ranges_t to DDPairInteractionRanges
and made it use gmx::Range. This is now used in an std::vector
in gmx_domdec_zones_t.

Note: more refactoring should be done in gmx_domdec_zones_t.

Change-Id: Iff61096ee8ce1e45a998a905fd56e0c2f43fa319

src/gromacs/domdec/domdec.cpp
src/gromacs/domdec/domdec_struct.h
src/gromacs/domdec/domdec_topology.cpp
src/gromacs/domdec/partition.cpp
src/gromacs/nbnxm/pairlist.cpp

index f3365e11a37900fbfe3cf8e79b62d2f310461bb4..84e3b898eb1798c7587470ff53990e67eda0dbd8 100644 (file)
@@ -1233,10 +1233,9 @@ static void make_load_communicators(gmx_domdec_t gmx_unused *dd)
 /*! \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++)
@@ -1263,7 +1262,7 @@ static void setup_neighbor_relations(gmx_domdec_t *dd)
 
     zones = &dd->comm->zones;
 
-    for (i = 0; i < nzone; i++)
+    for (int i = 0; i < nzone; i++)
     {
         m = 0;
         clear_ivec(zones->shift[i]);
@@ -1274,7 +1273,7 @@ static void setup_neighbor_relations(gmx_domdec_t *dd)
     }
 
     zones->n = nzone;
-    for (i = 0; i < nzone; i++)
+    for (int i = 0; i < nzone; i++)
     {
         for (d = 0; d < DIM; d++)
         {
@@ -1289,44 +1288,48 @@ static void setup_neighbor_relations(gmx_domdec_t *dd)
             }
         }
     }
-    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))
index c80e6687df66f70eab3891cd408edb90608e7841..c2be7bc66ecbd1df384ac5cae63978f40beb06e1 100644 (file)
@@ -47,6 +47,7 @@
 
 #include <cstddef>
 
+#include <array>
 #include <memory>
 #include <vector>
 
@@ -54,6 +55,7 @@
 #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
@@ -77,22 +79,24 @@ class LocalAtomSetManager;
 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         */
@@ -107,19 +111,17 @@ typedef struct {
 
 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 {
index d27b2033c81a4c645ce1c1abce555d2f45412f54..3df773af05afe22a3df201d6d75c068e9dc11ff9 100644 (file)
@@ -1126,9 +1126,9 @@ check_assign_interactions_atom(int i, int i_gl,
                                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];
@@ -1203,14 +1203,12 @@ check_assign_interactions_atom(int i, int i_gl,
                         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),
@@ -1425,9 +1423,7 @@ static void make_exclusions_zone(gmx_domdec_t *dd, gmx_domdec_zones_t *zones,
 
     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;
 
@@ -1470,7 +1466,7 @@ static void make_exclusions_zone(gmx_domdec_t *dd, gmx_domdec_zones_t *zones,
                      * 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;
                     }
@@ -1523,10 +1519,11 @@ static void check_alloc_index(t_blocka *ba, int nindex_max)
 }
 
 /*! \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);
 
@@ -1540,8 +1537,8 @@ static void check_exclusions_alloc(gmx_domdec_t *dd, gmx_domdec_zones_t *zones,
 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)
     {
@@ -1588,7 +1585,7 @@ static int make_local_bondeds_excls(gmx_domdec_t *dd,
                                     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;
@@ -1608,7 +1605,7 @@ static int make_local_bondeds_excls(gmx_domdec_t *dd,
     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
     {
@@ -1630,7 +1627,7 @@ static int make_local_bondeds_excls(gmx_domdec_t *dd,
     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];
@@ -1717,9 +1714,9 @@ static int make_local_bondeds_excls(gmx_domdec_t *dd,
     /* 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);
index f076b2e2a206e2c222184e0e3ef76c4e5be77e9e..918f57c9151edb994c822b5f56c0bea713926c26 100644 (file)
@@ -1460,7 +1460,6 @@ set_dd_corners(const gmx_domdec_t *dd,
 {
     const gmx_domdec_comm_t  *comm;
     const gmx_domdec_zones_t *zones;
-    int i, j;
 
     comm = dd->comm;
 
@@ -1498,22 +1497,23 @@ set_dd_corners(const gmx_domdec_t *dd,
         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);
                         }
                     }
                 }
@@ -1521,9 +1521,9 @@ set_dd_corners(const gmx_domdec_t *dd,
                 {
                     /* 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);
                         }
@@ -2187,13 +2187,12 @@ static void setup_dd_communication(gmx_domdec_t *dd,
 //! 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()]);
     }
 }
 
@@ -2221,7 +2220,7 @@ static void set_zones_size(gmx_domdec_t *dd,
     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;
@@ -2315,7 +2314,7 @@ static void set_zones_size(gmx_domdec_t *dd,
 
                     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)
                             {
@@ -2335,18 +2334,25 @@ static void set_zones_size(gmx_domdec_t *dd,
         /* 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);
                     }
                 }
             }
index 9474185f072e18ddb93e1a6b8670794ce8b21f34..ff60f433981dbad9d856eeffc1b3709ec7fe0c8a 100644 (file)
@@ -4005,7 +4005,7 @@ PairlistSet::constructPairlists(const Nbnxm::GridSet          &gridSet,
     }
     else
     {
-        nzi = gridSet.domainSetup().zones->nizone;
+        nzi = gridSet.domainSetup().zones->iZones.size();
     }
 
     if (!isCpuType_ && minimumIlistCountForGpuBalancing > 0)
@@ -4048,29 +4048,23 @@ PairlistSet::constructPairlists(const Nbnxm::GridSet          &gridSet,
         }
         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);
@@ -4090,7 +4084,7 @@ PairlistSet::constructPairlists(const Nbnxm::GridSet          &gridSet,
                     /* 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());
                     }