Merge release-5-0 into master
[alexxy/gromacs.git] / src / gromacs / gmxana / gmx_tune_pme.c
index 112e87273262698a714f1c5bdcbe1413eefca659..c4a7e6e021b4769d6c1e6063fc8d48f38eb8c13f 100644 (file)
  * To help us fund GROMACS development, we humbly ask that you cite
  * the research papers on the package. Check out http://www.gromacs.org.
  */
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
+#include "gmxpre.h"
+
+#include "config.h"
 
+#include <stdlib.h>
 #include <time.h>
+
 #ifdef HAVE_SYS_TIME_H
 #include <sys/time.h>
 #endif
 
 #include "gromacs/commandline/pargs.h"
-#include "typedefs.h"
-#include "types/commrec.h"
-#include "gromacs/utility/smalloc.h"
-#include "vec.h"
-#include "copyrite.h"
 #include "gromacs/fileio/tpxio.h"
-#include "gromacs/utility/cstringutil.h"
-#include "readinp.h"
-#include "calcgrid.h"
-#include "checkpoint.h"
-#include "macros.h"
-#include "gmx_ana.h"
-#include "names.h"
-#include "perf_est.h"
-#include "inputrec.h"
-#include "gromacs/timing/walltime_accounting.h"
+#include "gromacs/gmxana/gmx_ana.h"
+#include "gromacs/legacyheaders/calcgrid.h"
+#include "gromacs/legacyheaders/checkpoint.h"
+#include "gromacs/legacyheaders/inputrec.h"
+#include "gromacs/legacyheaders/macros.h"
+#include "gromacs/legacyheaders/names.h"
+#include "gromacs/legacyheaders/perf_est.h"
+#include "gromacs/legacyheaders/readinp.h"
+#include "gromacs/legacyheaders/typedefs.h"
+#include "gromacs/legacyheaders/types/commrec.h"
 #include "gromacs/math/utilities.h"
-
-#include "gmx_fatal.h"
+#include "gromacs/math/vec.h"
+#include "gromacs/timing/walltime_accounting.h"
+#include "gromacs/utility/baseversion.h"
+#include "gromacs/utility/cstringutil.h"
+#include "gromacs/utility/fatalerror.h"
+#include "gromacs/utility/smalloc.h"
 
 /* Enum for situations that can occur during log file parsing, the
  * corresponding string entries can be found in do_the_tests() in
@@ -143,29 +144,6 @@ static void cleandata(t_perf *perfdata, int test_nr)
 }
 
 
-static gmx_bool is_equal(real a, real b)
-{
-    real diff, eps = 1.0e-7;
-
-
-    diff = a - b;
-
-    if (diff < 0.0)
-    {
-        diff = -diff;
-    }
-
-    if (diff < eps)
-    {
-        return TRUE;
-    }
-    else
-    {
-        return FALSE;
-    }
-}
-
-
 static void remove_if_exists(const char *fn)
 {
     if (gmx_fexist(fn))
@@ -553,8 +531,8 @@ static gmx_bool analyze_data(
     fprintf(fp, "\n");
 
     /* Only mention settings if they were modified: */
-    bRefinedCoul = !is_equal(info->rcoulomb[k_win], info->rcoulomb[0]);
-    bRefinedVdW  = !is_equal(info->rvdw[k_win], info->rvdw[0]    );
+    bRefinedCoul = !gmx_within_tol(info->rcoulomb[k_win], info->rcoulomb[0], GMX_REAL_EPS);
+    bRefinedVdW  = !gmx_within_tol(info->rvdw[k_win], info->rvdw[0], GMX_REAL_EPS);
     bRefinedGrid = !(info->nkx[k_win] == info->nkx[0] &&
                      info->nky[k_win] == info->nky[0] &&
                      info->nkz[k_win] == info->nkz[0]);
@@ -616,25 +594,25 @@ static void get_program_paths(gmx_bool bThreads, char *cmd_mpirun[], char *cmd_m
     {
         if ( (cp = getenv("MPIRUN")) != NULL)
         {
-            *cmd_mpirun = strdup(cp);
+            *cmd_mpirun = gmx_strdup(cp);
         }
         else
         {
-            *cmd_mpirun = strdup(def_mpirun);
+            *cmd_mpirun = gmx_strdup(def_mpirun);
         }
     }
     else
     {
-        *cmd_mpirun = strdup(empty_mpirun);
+        *cmd_mpirun = gmx_strdup(empty_mpirun);
     }
 
     if ( (cp = getenv("MDRUN" )) != NULL)
     {
-        *cmd_mdrun  = strdup(cp);
+        *cmd_mdrun  = gmx_strdup(cp);
     }
     else
     {
-        *cmd_mdrun  = strdup(def_mdrun);
+        *cmd_mdrun  = gmx_strdup(def_mdrun);
     }
 }
 
@@ -986,11 +964,11 @@ static void make_benchmark_tprs(
         {
             /* Determine which Coulomb radii rc to use in the benchmarks */
             add = (rmax-rmin)/(*ntprs-1);
-            if (is_equal(rmin, info->rcoulomb[0]))
+            if (gmx_within_tol(rmin, info->rcoulomb[0], GMX_REAL_EPS))
             {
                 ir->rcoulomb = rmin + j*add;
             }
-            else if (is_equal(rmax, info->rcoulomb[0]))
+            else if (gmx_within_tol(rmax, info->rcoulomb[0], GMX_REAL_EPS))
             {
                 ir->rcoulomb = rmin + (j-1)*add;
             }
@@ -1090,8 +1068,8 @@ static void make_benchmark_tprs(
         fprintf(fp, "  %-14s\n", fn_bench_tprs[j]);
 
         /* Make it clear to the user that some additional settings were modified */
-        if (!is_equal(ir->rvdw, info->rvdw[0])
-            || !is_equal(ir->rlistlong, info->rlistlong[0]) )
+        if (!gmx_within_tol(ir->rvdw, info->rvdw[0], GMX_REAL_EPS)
+            || !gmx_within_tol(ir->rlistlong, info->rlistlong[0], GMX_REAL_EPS) )
         {
             bNote = TRUE;
         }
@@ -1330,9 +1308,12 @@ static void make_sure_it_runs(char *mdrun_cmd_line, int length, FILE *fp,
     {
         /* To prevent confusion, do not again issue a gmx_fatal here since we already
          * get the error message from mdrun itself */
-        sprintf(msg,    "Cannot run the benchmark simulations! Please check the error message of\n"
+        sprintf(msg,
+                "Cannot run the first benchmark simulation! Please check the error message of\n"
                 "mdrun for the source of the problem. Did you provide a command line\n"
-                "argument that neither g_tune_pme nor mdrun understands? Offending command:\n"
+                "argument that neither gmx tune_pme nor mdrun understands? If you're\n"
+                "sure your command line should work, you can bypass this check with \n"
+                "gmx tune_pme -nocheck. The failing command was:\n"
                 "\n%s\n\n", command);
 
         fprintf(stderr, "%s", msg);
@@ -1363,7 +1344,7 @@ static void do_the_tests(
         int             npme_fixed,     /* If >= -1, test fixed number of PME
                                          * nodes only                             */
         const char     *npmevalues_opt, /* Which -npme values should be tested    */
-        t_perf        **perfdata,       /* Here the performace data is stored     */
+        t_perf        **perfdata,       /* Here the performance data is stored    */
         int            *pmeentries,     /* Entries in the nPMEnodes list          */
         int             repeats,        /* Repeat each test this often            */
         int             nnodes,         /* Total number of nodes = nPP + nPME     */
@@ -1376,7 +1357,8 @@ static void do_the_tests(
         const t_filenm *fnm,            /* List of filenames from command line    */
         int             nfile,          /* Number of files specified on the cmdl. */
         int             presteps,       /* DLB equilibration steps, is checked    */
-        gmx_int64_t     cpt_steps)      /* Time step counter in the checkpoint    */
+        gmx_int64_t     cpt_steps,      /* Time step counter in the checkpoint    */
+        gmx_bool        bCheck)         /* Check whether benchmark mdrun works    */
 {
     int      i, nr, k, ret, count = 0, totaltests;
     int     *nPMEnodes = NULL;
@@ -1476,8 +1458,11 @@ static void do_the_tests(
                         cmd_stub, pd->nPMEnodes, tpr_names[k], cmd_args_bench);
 
                 /* To prevent that all benchmarks fail due to a show-stopper argument
-                 * on the mdrun command line, we make a quick check first */
-                if (bFirst)
+                 * on the mdrun command line, we make a quick check first.
+                 * This check can be turned off in cases where the automatically chosen
+                 * number of PME-only ranks leads to a number of PP ranks for which no
+                 * decomposition can be found (e.g. for large prime numbers) */
+                if (bFirst && bCheck)
                 {
                     make_sure_it_runs(pd->mdrun_cmd_line, cmdline_length, fp, fnm, nfile);
                 }
@@ -1653,13 +1638,13 @@ static void check_input(
     /* Add test scenarios if rmin or rmax were set */
     if (*ntprs <= 2)
     {
-        if (!is_equal(*rmin, rcoulomb) && (*ntprs == 1) )
+        if (!gmx_within_tol(*rmin, rcoulomb, GMX_REAL_EPS) && (*ntprs == 1) )
         {
             (*ntprs)++;
             fprintf(stderr, "NOTE: Setting -rmin to %g changed -ntpr to %d\n",
                     *rmin, *ntprs);
         }
-        if (!is_equal(*rmax, rcoulomb) && (*ntprs == 1) )
+        if (!gmx_within_tol(*rmax, rcoulomb, GMX_REAL_EPS) && (*ntprs == 1) )
         {
             (*ntprs)++;
             fprintf(stderr, "NOTE: Setting -rmax to %g changed -ntpr to %d\n",
@@ -1668,13 +1653,13 @@ static void check_input(
     }
     old = *ntprs;
     /* If one of rmin, rmax is set, we need 2 tpr files at minimum */
-    if (!is_equal(*rmax, rcoulomb) || !is_equal(*rmin, rcoulomb) )
+    if (!gmx_within_tol(*rmax, rcoulomb, GMX_REAL_EPS) || !gmx_within_tol(*rmin, rcoulomb, GMX_REAL_EPS) )
     {
         *ntprs = max(*ntprs, 2);
     }
 
     /* If both rmin, rmax are set, we need 3 tpr files at minimum */
-    if (!is_equal(*rmax, rcoulomb) && !is_equal(*rmin, rcoulomb) )
+    if (!gmx_within_tol(*rmax, rcoulomb, GMX_REAL_EPS) && !gmx_within_tol(*rmin, rcoulomb, GMX_REAL_EPS) )
     {
         *ntprs = max(*ntprs, 3);
     }
@@ -1686,7 +1671,7 @@ static void check_input(
 
     if (*ntprs > 1)
     {
-        if (is_equal(*rmin, rcoulomb) && is_equal(rcoulomb, *rmax)) /* We have just a single rc */
+        if (gmx_within_tol(*rmin, rcoulomb, GMX_REAL_EPS) && gmx_within_tol(rcoulomb, *rmax, GMX_REAL_EPS)) /* We have just a single rc */
         {
             fprintf(stderr, "WARNING: Resetting -ntpr to 1 since no Coulomb radius scaling is requested.\n"
                     "Please set rmin < rmax to test Coulomb radii in the [rmin, rmax] interval\n"
@@ -2038,6 +2023,9 @@ int gmx_tune_pme(int argc, char *argv[])
         "need to provide a machine- or hostfile. This can also be passed",
         "via the MPIRUN variable, e.g.[PAR]",
         "[TT]export MPIRUN=\"/usr/local/mpirun -machinefile hosts\"[tt][PAR]",
+        "Before doing the actual benchmark runs, [THISMODULE] will do a quick",
+        "check whether mdrun works as expected with the provided parallel settings",
+        "if the [TT]-check[tt] option is activated (the default).",
         "Please call [THISMODULE] with the normal options you would pass to",
         "[gmx-mdrun] and add [TT]-np[tt] for the number of ranks to perform the",
         "tests on, or [TT]-ntmpi[tt] for the number of threads. You can also add [TT]-r[tt]",
@@ -2047,7 +2035,7 @@ int gmx_tune_pme(int argc, char *argv[])
         "written with enlarged cutoffs and smaller Fourier grids respectively.",
         "Typically, the first test (number 0) will be with the settings from the input",
         "[TT].tpr[tt] file; the last test (number [TT]ntpr[tt]) will have the Coulomb cutoff",
-        "specified by [TT]-rmax[tt] with a somwhat smaller PME grid at the same time. ",
+        "specified by [TT]-rmax[tt] with a somewhat smaller PME grid at the same time. ",
         "In this last test, the Fourier spacing is multiplied with [TT]rmax[tt]/rcoulomb. ",
         "The remaining [TT].tpr[tt] files will have equally-spaced Coulomb radii (and Fourier "
         "spacings) between these extremes. [BB]Note[bb] that you can set [TT]-ntpr[tt] to 1",
@@ -2057,7 +2045,7 @@ int gmx_tune_pme(int argc, char *argv[])
         "MD systems. The dynamic load balancing needs about 100 time steps",
         "to adapt to local load imbalances, therefore the time step counters",
         "are by default reset after 100 steps. For large systems (>1M atoms), as well as ",
-        "for a higher accuarcy of the measurements, you should set [TT]-resetstep[tt] to a higher value.",
+        "for a higher accuracy of the measurements, you should set [TT]-resetstep[tt] to a higher value.",
         "From the 'DD' load imbalance entries in the md.log output file you",
         "can tell after how many steps the load is sufficiently balanced. Example call:[PAR]"
         "[TT]gmx tune_pme -np 64 -s protein.tpr -launch[tt][PAR]",
@@ -2114,9 +2102,9 @@ int gmx_tune_pme(int argc, char *argv[])
         /* g_tune_pme */
         { efOUT, "-p",      "perf",     ffWRITE },
         { efLOG, "-err",    "bencherr", ffWRITE },
-        { efTPX, "-so",     "tuned",    ffWRITE },
+        { efTPR, "-so",     "tuned",    ffWRITE },
         /* mdrun: */
-        { efTPX, NULL,      NULL,       ffREAD },
+        { efTPR, NULL,      NULL,       ffREAD },
         { efTRN, "-o",      NULL,       ffWRITE },
         { efCOMPRESSED, "-x", NULL,     ffOPTWR },
         { efCPT, "-cpi",    NULL,       ffOPTRD },
@@ -2184,6 +2172,7 @@ int gmx_tune_pme(int argc, char *argv[])
     gmx_bool     bKeepAndNumCPT        = FALSE;
     gmx_bool     bResetCountersHalfWay = FALSE;
     gmx_bool     bBenchmark            = TRUE;
+    gmx_bool     bCheck                = TRUE;
 
     output_env_t oenv = NULL;
 
@@ -2227,6 +2216,8 @@ int gmx_tune_pme(int argc, char *argv[])
           "Launch the real simulation after optimization" },
         { "-bench",    FALSE, etBOOL, {&bBenchmark},
           "Run the benchmarks or just create the input [TT].tpr[tt] files?" },
+        { "-check",    FALSE, etBOOL, {&bCheck},
+          "Before the benchmark runs, check whether mdrun works in parallel" },
         /******************/
         /* mdrun options: */
         /******************/
@@ -2386,7 +2377,8 @@ int gmx_tune_pme(int argc, char *argv[])
     sep_line(fp);
     fprintf(fp, "\n      P E R F O R M A N C E   R E S U L T S\n");
     sep_line(fp);
-    fprintf(fp, "%s for Gromacs %s\n", ShortProgram(), GromacsVersion());
+    fprintf(fp, "%s for Gromacs %s\n", output_env_get_program_display_name(oenv),
+            gmx_version());
     if (!bThreads)
     {
         fprintf(fp, "Number of ranks         : %d\n", nnodes);
@@ -2478,7 +2470,7 @@ int gmx_tune_pme(int argc, char *argv[])
     {
         do_the_tests(fp, tpr_names, maxPMEnodes, minPMEnodes, npme_fixed, npmevalues_opt[0], perfdata, &pmeentries,
                      repeats, nnodes, ntprs, bThreads, cmd_mpirun, cmd_np, cmd_mdrun,
-                     cmd_args_bench, fnm, NFILE, presteps, cpt_steps);
+                     cmd_args_bench, fnm, NFILE, presteps, cpt_steps, bCheck);
 
         fprintf(fp, "\nTuning took%8.1f minutes.\n", (gmx_gettime()-seconds)/60.0);