Also print 1x1 pair-list setup to log
[alexxy/gromacs.git] / src / gromacs / mdlib / nbnxn_tuning.cpp
index 3f91b13e3bce25ecb3e80ac518cb62df21b0a420..fe17c5b9c02a99da0a52e1039a658ae434d9f9dd 100644 (file)
@@ -68,6 +68,8 @@
 #include "gromacs/utility/cstringutil.h"
 #include "gromacs/utility/fatalerror.h"
 #include "gromacs/utility/gmxassert.h"
+#include "gromacs/utility/logger.h"
+#include "gromacs/utility/stringutil.h"
 
 /*! \brief Returns if we can (heuristically) change nstlist and rlist
  *
@@ -127,9 +129,14 @@ void increaseNstlist(FILE *fp, t_commrec *cr,
                      bool useOrEmulateGpuForNonbondeds,
                      const gmx::CpuInfo &cpuinfo)
 {
+    if (!EI_DYNAMICS(ir->eI))
+    {
+        /* Can only increase nstlist with dynamics */
+        return;
+    }
+
     float                  listfac_ok, listfac_max;
     int                    nstlist_orig, nstlist_prev;
-    verletbuf_list_setup_t ls;
     real                   rlistWithReferenceNstlist, rlist_inc, rlist_ok, rlist_max;
     real                   rlist_new, rlist_prev;
     size_t                 nstlist_ind = 0;
@@ -151,10 +158,15 @@ void increaseNstlist(FILE *fp, t_commrec *cr,
             return;
         }
 
-        if (fp != nullptr && useOrEmulateGpuForNonbondeds && ir->nstlist < nstlist_try[0])
+        /* With a GPU and fixed nstlist suggest tuning nstlist */
+        if (fp != nullptr &&
+            useOrEmulateGpuForNonbondeds &&
+            ir->nstlist < nstlist_try[0] &&
+            !supportsDynamicPairlistGenerationInterval(*ir))
         {
             fprintf(fp, nstl_gpu, ir->nstlist);
         }
+
         nstlist_ind = 0;
         while (nstlist_ind < NNSTL && ir->nstlist >= nstlist_try[nstlist_ind])
         {
@@ -200,6 +212,8 @@ void increaseNstlist(FILE *fp, t_commrec *cr,
         return;
     }
 
+    GMX_RELEASE_ASSERT(supportsDynamicPairlistGenerationInterval(*ir), "In all cases that do not support dynamic nstlist, we should have returned with an appropriate message above");
+
     if (useOrEmulateGpuForNonbondeds)
     {
         listfac_ok  = c_nbnxnListSizeFactorGPU;
@@ -225,7 +239,8 @@ void increaseNstlist(FILE *fp, t_commrec *cr,
         ir->nstlist = nstlist_cmdline;
     }
 
-    verletbuf_get_list_setup(TRUE, useOrEmulateGpuForNonbondeds, &ls);
+    ListSetupType      listType  = (useOrEmulateGpuForNonbondeds ? ListSetupType::Gpu : ListSetupType::CpuSimdWhenSupported);
+    VerletbufListSetup listSetup = verletbufGetSafeListSetup(listType);
 
     /* Allow rlist to make the list a given factor larger than the list
      * would be with the reference value for nstlist (10).
@@ -233,11 +248,12 @@ void increaseNstlist(FILE *fp, t_commrec *cr,
     nstlist_prev = ir->nstlist;
     ir->nstlist  = nbnxnReferenceNstlist;
     calc_verlet_buffer_size(mtop, det(box), ir, ir->nstlist, ir->nstlist - 1,
-                            -1, &ls, nullptr, &rlistWithReferenceNstlist);
+                            -1, &listSetup,
+                            nullptr, &rlistWithReferenceNstlist);
     ir->nstlist  = nstlist_prev;
 
     /* Determine the pair list size increase due to zero interactions */
-    rlist_inc = nbnxn_get_rlist_effective_inc(ls.cluster_size_j,
+    rlist_inc = nbnxn_get_rlist_effective_inc(listSetup.cluster_size_j,
                                               mtop->natoms/det(box));
     rlist_ok  = (rlistWithReferenceNstlist + rlist_inc)*std::cbrt(listfac_ok) - rlist_inc;
     rlist_max = (rlistWithReferenceNstlist + rlist_inc)*std::cbrt(listfac_max) - rlist_inc;
@@ -257,7 +273,7 @@ void increaseNstlist(FILE *fp, t_commrec *cr,
         }
 
         /* Set the pair-list buffer size in ir */
-        calc_verlet_buffer_size(mtop, det(box), ir, ir->nstlist, ir->nstlist - 1, -1, &ls, nullptr, &rlist_new);
+        calc_verlet_buffer_size(mtop, det(box), ir, ir->nstlist, ir->nstlist - 1, -1, &listSetup, nullptr, &rlist_new);
 
         /* Does rlist fit in the box? */
         bBox = (gmx::square(rlist_new) < max_cutoff2(ir->ePBC, box));
@@ -367,7 +383,7 @@ setDynamicPairlistPruningParameters(const t_inputrec             *ir,
                                     const gmx_mtop_t             *mtop,
                                     matrix                        box,
                                     gmx_bool                      useGpu,
-                                    const verletbuf_list_setup_t &listSetup,
+                                    const VerletbufListSetup     &listSetup,
                                     bool                          userSetNstlistPrune,
                                     const interaction_const_t    *ic,
                                     NbnxnListParameters          *listParams)
@@ -434,11 +450,40 @@ setDynamicPairlistPruningParameters(const t_inputrec             *ir,
     }
 }
 
-void setupDynamicPairlistPruning(FILE                      *fplog,
+/*! \brief Returns a string describing the setup of a single pair-list
+ *
+ * \param[in] listName           Short name of the list, can be ""
+ * \param[in] nstList            The list update interval in steps
+ * \param[in] nstListForSpacing  Update interval for setting the number characters for printing \p nstList
+ * \param[in] rList              List cut-off radius
+ * \param[in] interactionCutoff  The interaction cut-off, use for printing the list buffer size
+ */
+static std::string formatListSetup(const std::string &listName,
+                                   int                nstList,
+                                   int                nstListForSpacing,
+                                   real               rList,
+                                   real               interactionCutoff)
+{
+    std::string listSetup = "  ";
+    if (!listName.empty())
+    {
+        listSetup += listName + " list: ";
+    }
+    listSetup += "updated every ";
+    // Make the shortest int format string that fits nstListForSpacing
+    std::string nstListFormat = "%" + gmx::formatString("%d", gmx::formatString("%zu", nstListForSpacing).size()) + "d";
+    listSetup += gmx::formatString(nstListFormat.c_str(), nstList);
+    listSetup += gmx::formatString(" steps, buffer %.3f nm, rlist %.3f nm\n",
+                                   rList - interactionCutoff, rList);
+
+    return listSetup;
+}
+
+void setupDynamicPairlistPruning(const gmx::MDLogger       &mdlog,
                                  const t_inputrec          *ir,
                                  const gmx_mtop_t          *mtop,
                                  matrix                     box,
-                                 bool                       useGpu,
+                                 int                        nbnxnKernelType,
                                  const interaction_const_t *ic,
                                  NbnxnListParameters       *listParams)
 {
@@ -447,12 +492,14 @@ void setupDynamicPairlistPruning(FILE                      *fplog,
     /* Initialize the parameters to no dynamic list pruning */
     listParams->useDynamicPruning = false;
 
+    const VerletbufListSetup ls   = verletbufGetListSetup(nbnxnKernelType);
+
+    /* Currently emulation mode does not support dual pair-lists */
+    const bool useGpu             = (nbnxnKernelType == nbnxnk8x8x8_GPU);
+
     if (supportsDynamicPairlistGenerationInterval(*ir) &&
         getenv("GMX_DISABLE_DYNAMICPRUNING") == NULL)
     {
-        verletbuf_list_setup_t ls;
-        verletbuf_get_list_setup(TRUE, TRUE, &ls);
-
         /* Note that nstlistPrune can have any value independently of nstlist.
          * Actually applying rolling pruning is only useful when
          * nstlistPrune < nstlist -1
@@ -499,17 +546,51 @@ void setupDynamicPairlistPruning(FILE                      *fplog,
         {
             listParams->numRollingParts = 1;
         }
+    }
+
+    std::string mesg;
 
-        if (fplog && listParams->useDynamicPruning)
+    const real  interactionCutoff = std::max(ic->rcoulomb, ic->rvdw);
+    if (listParams->useDynamicPruning)
+    {
+        mesg += gmx::formatString("Using a dual %dx%d pair-list setup updated with dynamic%s pruning:\n",
+                                  ls.cluster_size_i, ls.cluster_size_j,
+                                  listParams->numRollingParts > 1 ? ", rolling" : "");
+        mesg += formatListSetup("outer", ir->nstlist, ir->nstlist, listParams->rlistOuter, interactionCutoff);
+        mesg += formatListSetup("inner", listParams->nstlistPrune, ir->nstlist, listParams->rlistInner, interactionCutoff);
+    }
+    else
+    {
+        mesg += gmx::formatString("Using a %dx%d pair-list setup:\n",
+                                  ls.cluster_size_i, ls.cluster_size_j);
+        mesg += formatListSetup("", ir->nstlist, ir->nstlist, listParams->rlistOuter, interactionCutoff);
+    }
+    if (supportsDynamicPairlistGenerationInterval(*ir))
+    {
+        VerletbufListSetup listSetup1x1 = { 1, 1 };
+        real               rlistOuter;
+        real               rlistInner;
+        calc_verlet_buffer_size(mtop, det(box), ir, ir->nstlist, ir->nstlist - 1,
+                                -1, &listSetup1x1, nullptr, &rlistOuter);
+        if (listParams->useDynamicPruning)
         {
-            const real interactionCutoff = std::max(ic->rcoulomb, ic->rvdw);
-            fprintf(fplog,
-                    "Using a dual pair-list setup updated with dynamic%s pruning:\n"
-                    "  outer list: updated every %3d steps, buffer %.3f nm, rlist %.3f nm\n"
-                    "  inner list: updated every %3d steps, buffer %.3f nm, rlist %.3f nm\n",
-                    listParams->numRollingParts > 1 ? ", rolling" : "",
-                    ir->nstlist, listParams->rlistOuter - interactionCutoff, listParams->rlistOuter,
-                    listParams->nstlistPrune, listParams->rlistInner - interactionCutoff, listParams->rlistInner);
+            int listLifeTime = listParams->nstlistPrune - (useGpu ? 0 : 1);
+            calc_verlet_buffer_size(mtop, det(box), ir, listParams->nstlistPrune, listLifeTime,
+                                    -1, &listSetup1x1, nullptr, &rlistInner);
+        }
+
+        mesg += gmx::formatString("At tolerance %g kJ/mol/ps per atom, equivalent classical 1x1 list would be:\n",
+                                  ir->verletbuf_tol);
+        if (listParams->useDynamicPruning)
+        {
+            mesg += formatListSetup("outer", ir->nstlist, ir->nstlist, rlistOuter, interactionCutoff);
+            mesg += formatListSetup("inner", listParams->nstlistPrune, ir->nstlist, rlistInner, interactionCutoff);
+        }
+        else
+        {
+            mesg += formatListSetup("", ir->nstlist, ir->nstlist, rlistOuter, interactionCutoff);
         }
     }
+
+    GMX_LOG(mdlog.info).asParagraph().appendText(mesg);
 }