Revised g_tune_pme
authorCarsten Kutzner <ckutzne@gwdg.de>
Tue, 22 May 2012 08:07:42 +0000 (10:07 +0200)
committerCarsten Kutzner <ckutzne@gwdg.de>
Wed, 23 May 2012 12:58:09 +0000 (14:58 +0200)
1. Now, g_tune_pme only duplicates mdrun options where necessary,
options not understood by g_tune_pme are simply passed over to mdrun.
2. Users can now set minimum and maximum Coulomb radius iso scaling
factors for rcoulomb and the Fourier grid.
3. As a result of 1 and 2, some cleanup of the code was possible and
unneeded code was removed.
4. For -npme auto, the tool now derives a reasonable number of PME-
only nodes from the .tpr file settings and tests values around this
number.
Change-Id: I88af5d38a61e0409613f5f3fd4272f7f43823f64

src/tools/gmx_tune_pme.c

index 24d321e23e65b40381d92174c65236a8388fb55b..b09f2f39ef39cc2bb0fe92e26f81f643294cef00 100644 (file)
 #include "checkpoint.h"
 #include "gmx_ana.h"
 #include "names.h"
 #include "checkpoint.h"
 #include "gmx_ana.h"
 #include "names.h"
+#include "perf_est.h"
 
 
 
 
 
 
-enum {
-  ddnoSEL, ddnoINTERLEAVE, ddnoPP_PME, ddnoCARTESIAN, ddnoNR
-};
-
 /* Enum for situations that can occur during log file parsing, the
  * corresponding string entries can be found in do_the_tests() in
  * const char* ParseLog[] */
 /* Enum for situations that can occur during log file parsing, the
  * corresponding string entries can be found in do_the_tests() in
  * const char* ParseLog[] */
@@ -123,7 +120,7 @@ static int gmx_system_call(char *command)
     return ( system(command) );
 #endif
 }
     return ( system(command) );
 #endif
 }
+
 
 /* Check if string starts with substring */
 static gmx_bool str_starts(const char *string, const char *substring)
 
 /* Check if string starts with substring */
 static gmx_bool str_starts(const char *string, const char *substring)
@@ -137,7 +134,7 @@ static void cleandata(t_perf *perfdata, int test_nr)
     perfdata->Gcycles[test_nr]    = 0.0;
     perfdata->ns_per_day[test_nr] = 0.0;
     perfdata->PME_f_load[test_nr] = 0.0;
     perfdata->Gcycles[test_nr]    = 0.0;
     perfdata->ns_per_day[test_nr] = 0.0;
     perfdata->PME_f_load[test_nr] = 0.0;
-    
+
     return;
 }
 
     return;
 }
 
@@ -173,7 +170,6 @@ static void finalize(const char *fn_out)
     }
     fclose(fp);
     fprintf(stdout,"\n\n");
     }
     fclose(fp);
     fprintf(stdout,"\n\n");
-    thanx(stderr);
 }
 
 
 }
 
 
@@ -209,7 +205,7 @@ static int parse_logfile(const char *logfile, const char *errfile,
     fp = fopen(logfile, "r");
     perfdata->PME_f_load[test_nr] = -1.0;
     perfdata->guessPME            = -1;
     fp = fopen(logfile, "r");
     perfdata->PME_f_load[test_nr] = -1.0;
     perfdata->guessPME            = -1;
-    
+
     iFound = eFoundNothing;
     if (1 == nnodes)
         iFound = eFoundDDStr; /* Skip some case statements */
     iFound = eFoundNothing;
     if (1 == nnodes)
         iFound = eFoundDDStr; /* Skip some case statements */
@@ -226,7 +222,7 @@ static int parse_logfile(const char *logfile, const char *errfile,
             cleandata(perfdata, test_nr);
             return eParselogTerm;
         }
             cleandata(perfdata, test_nr);
             return eParselogTerm;
         }
-        
+
         /* Check whether cycle resetting  worked */
         if (presteps > 0 && !bFoundResetStr)
         {
         /* Check whether cycle resetting  worked */
         if (presteps > 0 && !bFoundResetStr)
         {
@@ -244,7 +240,7 @@ static int parse_logfile(const char *logfile, const char *errfile,
                     sprintf(dumstring , gmx_large_int_pfmt, resetsteps);
                     sprintf(dumstring2, gmx_large_int_pfmt, presteps+cpt_steps);
                     fprintf(stderr, "WARNING: Time step counters were reset at step %s,\n"
                     sprintf(dumstring , gmx_large_int_pfmt, resetsteps);
                     sprintf(dumstring2, gmx_large_int_pfmt, presteps+cpt_steps);
                     fprintf(stderr, "WARNING: Time step counters were reset at step %s,\n"
-                                    "         though they were supposed to be reset at step %s!\n", 
+                                    "         though they were supposed to be reset at step %s!\n",
                             dumstring, dumstring2);
                 }
             }
                             dumstring, dumstring2);
                 }
             }
@@ -306,13 +302,13 @@ static int parse_logfile(const char *logfile, const char *errfile,
                     fclose(fp);
                     if (bResetChecked || presteps == 0)
                         return eParselogOK;
                     fclose(fp);
                     if (bResetChecked || presteps == 0)
                         return eParselogOK;
-                    else 
+                    else
                         return eParselogResetProblem;
                 }
                 break;
         }
     } /* while */
                         return eParselogResetProblem;
                 }
                 break;
         }
     } /* while */
-    
+
     /* Close the log file */
     fclose(fp);
 
     /* Close the log file */
     fclose(fp);
 
@@ -326,7 +322,7 @@ static int parse_logfile(const char *logfile, const char *errfile,
             if ( str_starts(line, "Fatal error:") )
             {
                 if (fgets(line, STRLEN, fp) != NULL)
             if ( str_starts(line, "Fatal error:") )
             {
                 if (fgets(line, STRLEN, fp) != NULL)
-                    fprintf(stderr, "\nWARNING: A fatal error has occured during this benchmark:\n"
+                    fprintf(stderr, "\nWARNING: An error occured during this benchmark:\n"
                                     "%s\n", line);
                 fclose(fp);
                 cleandata(perfdata, test_nr);
                                     "%s\n", line);
                 fclose(fp);
                 cleandata(perfdata, test_nr);
@@ -344,7 +340,7 @@ static int parse_logfile(const char *logfile, const char *errfile,
      * the log file. */
     fprintf(stdout, "No performance data in log file.\n");
     cleandata(perfdata, test_nr);
      * the log file. */
     fprintf(stdout, "No performance data in log file.\n");
     cleandata(perfdata, test_nr);
-    
+
     return eParselogNoPerfData;
 }
 
     return eParselogNoPerfData;
 }
 
@@ -421,7 +417,7 @@ static gmx_bool analyze_data(
                 }
             }
             pd->ns_per_day_Av /= nrepeats;
                 }
             }
             pd->ns_per_day_Av /= nrepeats;
-            
+
             /* Nicer output: */
             if (pd->PME_f_load_Av > 0.0)
                 sprintf(str_PME_f_load, "%12.3f", pd->PME_f_load_Av);
             /* Nicer output: */
             if (pd->PME_f_load_Av > 0.0)
                 sprintf(str_PME_f_load, "%12.3f", pd->PME_f_load_Av);
@@ -515,14 +511,14 @@ static gmx_bool analyze_data(
 
     if (bCanUseOrigTPR && ntprs > 1)
         fprintf(fp, "and original PME settings.\n");
 
     if (bCanUseOrigTPR && ntprs > 1)
         fprintf(fp, "and original PME settings.\n");
-    
+
     fflush(fp);
     fflush(fp);
-    
+
     /* Return the index of the mdp file that showed the highest performance
      * and the optimal number of PME nodes */
     /* Return the index of the mdp file that showed the highest performance
      * and the optimal number of PME nodes */
-    *index_tpr    = k_win; 
+    *index_tpr    = k_win;
     *npme_optimal = winPME;
     *npme_optimal = winPME;
-    
+
     return bCanUseOrigTPR;
 }
 
     return bCanUseOrigTPR;
 }
 
@@ -544,7 +540,7 @@ static void get_program_paths(gmx_bool bThreads, char *cmd_mpirun[], char cmd_np
     const char empty_mpirun[] = "";
     gmx_bool  bMdrun = FALSE;
     gmx_bool  bMPI   = FALSE;
     const char empty_mpirun[] = "";
     gmx_bool  bMdrun = FALSE;
     gmx_bool  bMPI   = FALSE;
-    
+
 
     /* Get the commands we need to set up the runs from environment variables */
     if (!bThreads)
 
     /* Get the commands we need to set up the runs from environment variables */
     if (!bThreads)
@@ -558,7 +554,7 @@ static void get_program_paths(gmx_bool bThreads, char *cmd_mpirun[], char cmd_np
     {
         *cmd_mpirun = strdup(empty_mpirun);
     }
     {
         *cmd_mpirun = strdup(empty_mpirun);
     }
-     
+
     if ( (cp = getenv("MDRUN" )) != NULL )
         *cmd_mdrun  = strdup(cp);
     else
     if ( (cp = getenv("MDRUN" )) != NULL )
         *cmd_mdrun  = strdup(cp);
     else
@@ -641,9 +637,9 @@ static void get_program_paths(gmx_bool bThreads, char *cmd_mpirun[], char cmd_np
 
 
 static void launch_simulation(
 
 
 static void launch_simulation(
-        gmx_bool bLaunch,           /* Should the simulation be launched? */
+        gmx_bool bLaunch,       /* Should the simulation be launched? */
         FILE *fp,               /* General log file */
         FILE *fp,               /* General log file */
-        gmx_bool bThreads,          /* whether to use threads */
+        gmx_bool bThreads,      /* whether to use threads */
         char *cmd_mpirun,       /* Command for mpirun */
         char *cmd_np,           /* Switch for -np or -nt or empty */
         char *cmd_mdrun,        /* Command for mdrun */
         char *cmd_mpirun,       /* Command for mpirun */
         char *cmd_np,           /* Switch for -np or -nt or empty */
         char *cmd_mdrun,        /* Command for mdrun */
@@ -653,12 +649,12 @@ static void launch_simulation(
         int  nPMEnodes)         /* Number of PME nodes to use */
 {
     char  *command;
         int  nPMEnodes)         /* Number of PME nodes to use */
 {
     char  *command;
-    
-    
-    /* Make enough space for the system call command, 
+
+
+    /* Make enough space for the system call command,
      * (100 extra chars for -npme ... etc. options should suffice): */
     snew(command, strlen(cmd_mpirun)+strlen(cmd_mdrun)+strlen(cmd_np)+strlen(args_for_mdrun)+strlen(simulation_tpr)+100);
      * (100 extra chars for -npme ... etc. options should suffice): */
     snew(command, strlen(cmd_mpirun)+strlen(cmd_mdrun)+strlen(cmd_np)+strlen(args_for_mdrun)+strlen(simulation_tpr)+100);
-   
+
     /* Note that the -passall options requires args_for_mdrun to be at the end
      * of the command line string */
     if (bThreads)
     /* Note that the -passall options requires args_for_mdrun to be at the end
      * of the command line string */
     if (bThreads)
@@ -666,12 +662,12 @@ static void launch_simulation(
         sprintf(command, "%s%s-npme %d -s %s %s",
                 cmd_mdrun, cmd_np, nPMEnodes, simulation_tpr, args_for_mdrun);
     }
         sprintf(command, "%s%s-npme %d -s %s %s",
                 cmd_mdrun, cmd_np, nPMEnodes, simulation_tpr, args_for_mdrun);
     }
-    else 
+    else
     {
         sprintf(command, "%s%s%s -npme %d -s %s %s",
                 cmd_mpirun, cmd_np, cmd_mdrun, nPMEnodes, simulation_tpr, args_for_mdrun);
     }
     {
         sprintf(command, "%s%s%s -npme %d -s %s %s",
                 cmd_mpirun, cmd_np, cmd_mdrun, nPMEnodes, simulation_tpr, args_for_mdrun);
     }
-        
+
     fprintf(fp, "%s this command line to launch the simulation:\n\n%s", bLaunch? "Using":"Please use", command);
     sep_line(fp);
     fflush(fp);
     fprintf(fp, "%s this command line to launch the simulation:\n\n%s", bLaunch? "Using":"Please use", command);
     sep_line(fp);
     fflush(fp);
@@ -683,7 +679,6 @@ static void launch_simulation(
         sep_line(stdout);
         fflush(stdout);
         gmx_system_call(command);
         sep_line(stdout);
         fflush(stdout);
         gmx_system_call(command);
-        thanx(fp);
     }
 }
 
     }
 }
 
@@ -697,229 +692,20 @@ static void modify_PMEsettings(
     t_state      state;
     gmx_mtop_t   mtop;
     char         buf[200];
     t_state      state;
     gmx_mtop_t   mtop;
     char         buf[200];
-    
+
     snew(ir,1);
     read_tpx_state(fn_best_tpr,ir,&state,NULL,&mtop);
     snew(ir,1);
     read_tpx_state(fn_best_tpr,ir,&state,NULL,&mtop);
-        
+
     /* Set nsteps to the right value */
     ir->nsteps = simsteps;
     /* Set nsteps to the right value */
     ir->nsteps = simsteps;
-    
+
     /* Write the tpr file which will be launched */
     sprintf(buf, "Writing optimized simulation file %s with nsteps=%s.\n", fn_sim_tpr, gmx_large_int_pfmt);
     fprintf(stdout,buf,ir->nsteps);
     fflush(stdout);
     write_tpx_state(fn_sim_tpr,ir,&state,&mtop);
     /* Write the tpr file which will be launched */
     sprintf(buf, "Writing optimized simulation file %s with nsteps=%s.\n", fn_sim_tpr, gmx_large_int_pfmt);
     fprintf(stdout,buf,ir->nsteps);
     fflush(stdout);
     write_tpx_state(fn_sim_tpr,ir,&state,&mtop);
-        
-    sfree(ir);
-}
-
-
-typedef struct
-{
-    int  nkx, nky, nkz;      /* Fourier grid                                  */
-    real fac;                /* actual scaling factor                         */
-    real fs;                 /* Fourierspacing                                */
-} t_pmegrid;
-
-
-static void copy_grid(t_pmegrid *ingrid, t_pmegrid *outgrid)
-{
-    outgrid->nkx = ingrid->nkx;
-    outgrid->nky = ingrid->nky;
-    outgrid->nkz = ingrid->nkz;
-    outgrid->fac = ingrid->fac;
-    outgrid->fs  = ingrid->fs;
-}
-
-/* Removes entry 'index' from the t_pmegrid list */
-static void remove_from_list(
-        t_pmegrid gridlist[],
-        int *nlist,           /* Length of the list                           */
-        int index)            /* Index to remove from the list                */
-{
-    int j;
-
-
-    for (j = index; j < (*nlist - 1); j++)
-    {
-        copy_grid(&gridlist[j+1], &gridlist[j]);
-    }
-    *nlist = *nlist - 1;
-}
-
-
-/* Returns the index of the least necessary grid in the list.
- *
- * This is the one where the following conditions hold for the scaling factor:
- * 1. this grid has the smallest distance to its neighboring grid (distance
- *    measured by fac) -> this condition is true for two grids at the same time
- * 2. this grid (of the two) has the smaller distance to the other neighboring
- *    grid
- *
- * The extreme grids (the ones with the smallest and largest
- * scaling factor) are never thrown away.
- */
-static int get_throwaway_index(
-        t_pmegrid gridlist[],
-        int nlist)           /* Length of the list                           */
-{
-    int i,index = -1;
-    real dist,mindist,d_left,d_right;
-
-
-    /* Find the two factors with the smallest mutual distance */
-    mindist = GMX_FLOAT_MAX;
-    for (i = 1; i < nlist; i++)
-    {
-        dist = fabs(gridlist[i].fac - gridlist[i-1].fac);
-        if (dist < mindist)
-        {
-            index = i;
-            mindist = dist;
-        }
-    }
-    /* index and index-1 have the smallest mutual distance */
-    if (index == 1)
-    {
-        /* Never return the first index, i.e. index == 0 */
-        ;
-    }
-    else
-    {
-        d_left  = fabs(gridlist[index-1].fac - gridlist[index-2].fac);
-        d_right = fabs(gridlist[index+1].fac - gridlist[index  ].fac);
-
-        /* Return the left index if its distance to its left neighbor is shorter
-         * than the distance of the right index to its right neighbor */
-        if (d_left < d_right)
-            index--;
-    }
-    /* Never return the last index */
-    if (index == nlist-1)
-        index--;
-
-    return index;
-}
-
-
-static void make_grid_list(
-        real fmin,            /* minimum scaling factor (downscaling fac)     */
-        real fmax,            /* maximum scaling factor (upscaling fac)       */
-        int *ntprs,           /* Number of tpr files to test                  */
-        matrix box,           /* The box                                      */
-        t_pmegrid *griduse[], /* List of grids that have to be tested         */
-        real fs)              /* Requested fourierspacing at a scaling factor
-                                 of unity                                     */
-{
-    real req_fac,act_fac=0,act_fs,eps;
-    rvec box_size;
-    int i,jmin=0,d,ngridall=0;
-    int nkx=0,nky=0,nkz=0;
-    int nkx_old=0,nky_old=0,nkz_old=0;
-    t_pmegrid *gridall;
-    int gridalloc,excess;
-
-
-    /* Determine length of triclinic box vectors */
-    for(d=0; d<DIM; d++)
-    {
-        box_size[d] = 0;
-        for(i=0;i<DIM;i++)
-            box_size[d] += box[d][i]*box[d][i];
-        box_size[d] = sqrt(box_size[d]);
-    }
-
-    gridalloc = 25;
-    snew(gridall, gridalloc);
-
-    fprintf(stdout, "Possible PME grid settings (apart from input file settings):\n");
-    fprintf(stdout, "  nkx  nky  nkz  max spacing  scaling factor\n");
-
-    /* eps should provide a fine enough spacing not to miss any grid */
-    if (fmax != fmin)
-        eps = (fmax-fmin)/(100.0*(*ntprs - 1));
-    else
-        eps = 1.0/max( (*griduse)[0].nkz, max( (*griduse)[0].nkx, (*griduse)[0].nky ) );
-
-    for (req_fac = fmin; act_fac < fmax; req_fac += eps)
-    {
-        nkx=0;
-        nky=0;
-        nkz=0;
-        calc_grid(NULL,box,fs*req_fac,&nkx,&nky,&nkz);
-        act_fs = max(box_size[XX]/nkx,max(box_size[YY]/nky,box_size[ZZ]/nkz));
-        act_fac = act_fs/fs;
-        if (    ! ( nkx==nkx_old           && nky==nky_old           && nkz==nkz_old           )    /* Exclude if grid is already in list */
-             && ! ( nkx==(*griduse)[0].nkx && nky==(*griduse)[0].nky && nkz==(*griduse)[0].nkz ) )  /* Exclude input file grid */
-        {
-            /* We found a new grid that will do */
-            nkx_old = nkx;
-            nky_old = nky;
-            nkz_old = nkz;
-            gridall[ngridall].nkx = nkx;
-            gridall[ngridall].nky = nky;
-            gridall[ngridall].nkz = nkz;
-            gridall[ngridall].fac = act_fac;
-            gridall[ngridall].fs  = act_fs;
-            fprintf(stdout, "%5d%5d%5d %12f %12f\n",nkx,nky,nkz,act_fs,act_fac);
-            ngridall++;
-            if (ngridall >= gridalloc)
-            {
-                gridalloc += 25;
-                srenew(gridall, gridalloc);
-            }
-        }
-    }
-
-    /* excess is the number of grids we have to get rid of */
-    excess = ngridall+1 - *ntprs;
-
-    /* If we found less grids than tpr files were requested, simply test all
-     * the grid there are ... */
-    if (excess < 0)
-    {
-        fprintf(stdout, "NOTE: You requested %d tpr files, but apart from the input file grid only the\n"
-                        "      above listed %d suitable PME grids were found. Will test all suitable settings.\n",
-                        *ntprs, ngridall);
-        *ntprs = ngridall+1;
-    }
-    else
-    {
-        if (2 == *ntprs)
-        {
-            /* We can only keep the input tpr file plus one extra tpr file.
-             * We make that choice depending on the values of -upfac and -downfac */
-            if (fmin < 1.0)
-            {
-                /* Keep the one with the -downfac as scaling factor. This is already
-                 * stored in gridall[0] */
-                ;
-            }
-            else
-            {
-                /* Keep the one with -upfac as scaling factor */
-                copy_grid(&(gridall[ngridall-1]), &(gridall[0]));
-            }
 
 
-        }
-        else
-        {
-            /* From the grid list throw away the unnecessary ones (keep the extremes) */
-            for (i = 0; i < excess; i++)
-            {
-                /* Get the index of the least necessary grid from the list ... */
-                jmin = get_throwaway_index(gridall, ngridall);
-                /* ... and remove the grid from the list */
-                remove_from_list(gridall, &ngridall, jmin);
-            }
-        }
-    }
-
-    /* The remaining list contains the grids we want to test */
-    for (i=1; i < *ntprs; i++)
-        copy_grid(&(gridall[i-1]), &((*griduse)[i]));
-
-    sfree(gridall);
+    sfree(ir);
 }
 
 
 }
 
 
@@ -932,12 +718,10 @@ static void make_benchmark_tprs(
         char *fn_bench_tprs[],      /* WRITE: Names of benchmark tpr files           */
         gmx_large_int_t benchsteps, /* Number of time steps for benchmark runs       */
         gmx_large_int_t statesteps, /* Step counter in checkpoint file               */
         char *fn_bench_tprs[],      /* WRITE: Names of benchmark tpr files           */
         gmx_large_int_t benchsteps, /* Number of time steps for benchmark runs       */
         gmx_large_int_t statesteps, /* Step counter in checkpoint file               */
-        real upfac,                 /* Scale rcoulomb inbetween downfac and upfac    */
-        real downfac,
+        real rmin,                  /* Minimal Coulomb radius                        */
+        real rmax,                  /* Maximal Coulomb radius                        */
         int *ntprs,                 /* No. of TPRs to write, each with a different
         int *ntprs,                 /* No. of TPRs to write, each with a different
-                                       rcoulomb and fourierspacing. If not enough
-                                       grids are found, ntprs is reduced accordingly */
-        real fourierspacing,        /* Basic fourierspacing from tpr input file      */
+                                       rcoulomb and fourierspacing                   */
         t_inputinfo *info,          /* Contains information about mdp file options   */
         FILE *fp)                   /* Write the output here                         */
 {
         t_inputinfo *info,          /* Contains information about mdp file options   */
         FILE *fp)                   /* Write the output here                         */
 {
@@ -945,12 +729,14 @@ static void make_benchmark_tprs(
     t_inputrec   *ir;
     t_state      state;
     gmx_mtop_t   mtop;
     t_inputrec   *ir;
     t_state      state;
     gmx_mtop_t   mtop;
-    real         nlist_buffer; /* Thickness of the buffer regions for PME-switch potentials: */
+    real         nlist_buffer;      /* Thickness of the buffer regions for PME-switch potentials */
     char         buf[200];
     rvec         box_size;
     char         buf[200];
     rvec         box_size;
-    gmx_bool         bNote = FALSE;
-    t_pmegrid    *pmegrid=NULL; /* Grid settings for the PME grids to test    */
-    
+    gmx_bool     bNote = FALSE;
+    real         add;               /* Add this to rcoul for the next test    */
+    real         fac = 1.0;         /* Scaling factor for Coulomb radius      */
+    real         fourierspacing;    /* Basic fourierspacing from tpr          */
+
 
     sprintf(buf, "Making benchmark tpr file%s with %s time step%s",
             *ntprs > 1? "s":"", gmx_large_int_pfmt, benchsteps>1?"s":"");
 
     sprintf(buf, "Making benchmark tpr file%s with %s time step%s",
             *ntprs > 1? "s":"", gmx_large_int_pfmt, benchsteps>1?"s":"");
@@ -962,8 +748,8 @@ static void make_benchmark_tprs(
         benchsteps += statesteps;
     }
     fprintf(stdout, ".\n");
         benchsteps += statesteps;
     }
     fprintf(stdout, ".\n");
-        
-    
+
+
     snew(ir,1);
     read_tpx_state(fn_sim_tpr,ir,&state,NULL,&mtop);
 
     snew(ir,1);
     read_tpx_state(fn_sim_tpr,ir,&state,NULL,&mtop);
 
@@ -971,7 +757,7 @@ static void make_benchmark_tprs(
     if (EEL_PME(ir->coulombtype) == FALSE)
         gmx_fatal(FARGS, "Can only do optimizations for simulations with %s electrostatics.",
                 EELTYPE(eelPME));
     if (EEL_PME(ir->coulombtype) == FALSE)
         gmx_fatal(FARGS, "Can only do optimizations for simulations with %s electrostatics.",
                 EELTYPE(eelPME));
-    
+
     /* Check if rcoulomb == rlist, which is necessary for plain PME. */
     if (  (eelPME == ir->coulombtype) && !(ir->rcoulomb == ir->rlist) )
     {
     /* Check if rcoulomb == rlist, which is necessary for plain PME. */
     if (  (eelPME == ir->coulombtype) && !(ir->rcoulomb == ir->rlist) )
     {
@@ -988,7 +774,7 @@ static void make_benchmark_tprs(
     /* Reduce the number of steps for the benchmarks */
     info->orig_sim_steps = ir->nsteps;
     ir->nsteps           = benchsteps;
     /* Reduce the number of steps for the benchmarks */
     info->orig_sim_steps = ir->nsteps;
     ir->nsteps           = benchsteps;
-    
+
     /* For PME-switch potentials, keep the radial distance of the buffer region */
     nlist_buffer   = ir->rlist - ir->rcoulomb;
 
     /* For PME-switch potentials, keep the radial distance of the buffer region */
     nlist_buffer   = ir->rlist - ir->rcoulomb;
 
@@ -1006,23 +792,14 @@ static void make_benchmark_tprs(
     info->fsy[0] = box_size[YY]/ir->nky;
     info->fsz[0] = box_size[ZZ]/ir->nkz;
 
     info->fsy[0] = box_size[YY]/ir->nky;
     info->fsz[0] = box_size[ZZ]/ir->nkz;
 
-    /* Put the input grid as first entry into the grid list */
-    snew(pmegrid, *ntprs);
-    pmegrid[0].fac = 1.00;
-    pmegrid[0].nkx = ir->nkx;
-    pmegrid[0].nky = ir->nky;
-    pmegrid[0].nkz = ir->nkz;
-    pmegrid[0].fs  = max(box_size[ZZ]/ir->nkz, max(box_size[XX]/ir->nkx, box_size[YY]/ir->nky));
-
-    /* If no value for the fourierspacing was provided on the command line, we
-     * use the reconstruction from the tpr file */
-    if (fourierspacing <= 0)
-    {
-        fourierspacing = pmegrid[0].fs;
-    }
+    /* Reconstruct the fourierspacing from the number of PME grid points found in the tpr */
+    fourierspacing = max(box_size[ZZ]/ir->nkz, max(box_size[XX]/ir->nkx, box_size[YY]/ir->nky));
 
     fprintf(stdout, "Calculating PME grid points on the basis of a fourierspacing of %f nm\n", fourierspacing);
 
 
     fprintf(stdout, "Calculating PME grid points on the basis of a fourierspacing of %f nm\n", fourierspacing);
 
+    /* For performance comparisons the number of particles is useful to have */
+    fprintf(fp, "   Number of particles  : %d\n", mtop.natoms);
+
     /* Print information about settings of which some are potentially modified: */
     fprintf(fp, "   Coulomb type         : %s\n", EELTYPE(ir->coulombtype));
     fprintf(fp, "   Grid spacing x y z   : %f %f %f\n",
     /* Print information about settings of which some are potentially modified: */
     fprintf(fp, "   Coulomb type         : %s\n", EELTYPE(ir->coulombtype));
     fprintf(fp, "   Grid spacing x y z   : %f %f %f\n",
@@ -1048,21 +825,36 @@ static void make_benchmark_tprs(
         fprintf(fp, " rlistlong");
     fprintf(fp, "  tpr file\n");
 
         fprintf(fp, " rlistlong");
     fprintf(fp, "  tpr file\n");
 
-
-    /* Get useful PME grids if requested, the actual number of entries is
-     * returned in npmegrid */
-    if (*ntprs > 1)
-        make_grid_list(downfac, upfac, ntprs, state.box, &pmegrid, fourierspacing);
-    
     /* Loop to create the requested number of tpr input files */
     for (j = 0; j < *ntprs; j++)
     {
     /* Loop to create the requested number of tpr input files */
     for (j = 0; j < *ntprs; j++)
     {
-        /* The first one is the provided tpr file, just need to modify the number
-         * of steps, so skip the following block */
-        if (j > 0)
+        /* The first .tpr is the provided one, just need to modify nsteps,
+         * so skip the following block */
+        if (j != 0)
         {
         {
-            /* Scale the Coulomb radius */
-            ir->rcoulomb = info->rcoulomb[0]*pmegrid[j].fac;
+            /* Determine which Coulomb radii rc to use in the benchmarks */
+            add = (rmax-rmin)/(*ntprs-1);
+            if (is_equal(rmin,info->rcoulomb[0]))
+            {
+                ir->rcoulomb = rmin + j*add;
+            }
+            else if (is_equal(rmax,info->rcoulomb[0]))
+            {
+                ir->rcoulomb = rmin + (j-1)*add;
+            }
+            else
+            {
+                /* rmin != rcoul != rmax, ergo test between rmin and rmax */
+                add = (rmax-rmin)/(*ntprs-2);
+                ir->rcoulomb = rmin + (j-1)*add;
+            }
+
+            /* Determine the scaling factor fac */
+            fac = ir->rcoulomb/info->rcoulomb[0];
+
+            /* Scale the Fourier grid spacing */
+            ir->nkx = ir->nky = ir->nkz = 0;
+            calc_grid(NULL,state.box,fourierspacing*fac,&ir->nkx,&ir->nky,&ir->nkz);
 
             /* Adjust other radii since various conditions neet to be fulfilled */
             if (eelPME == ir->coulombtype)
 
             /* Adjust other radii since various conditions neet to be fulfilled */
             if (eelPME == ir->coulombtype)
@@ -1084,15 +876,10 @@ static void make_benchmark_tprs(
 
             ir->rlistlong = max_cutoff(ir->rlist,max_cutoff(ir->rvdw,ir->rcoulomb));
 
 
             ir->rlistlong = max_cutoff(ir->rlist,max_cutoff(ir->rvdw,ir->rcoulomb));
 
-            /* Copy the optimal grid dimensions to ir */
-            ir->nkx = pmegrid[j].nkx;
-            ir->nky = pmegrid[j].nky;
-            ir->nkz = pmegrid[j].nkz;
-
         } /* end of "if (j != 0)" */
 
         /* for j==0: Save the original settings
         } /* end of "if (j != 0)" */
 
         /* for j==0: Save the original settings
-         * for j >0: Save modified radii and fourier grids */
+         * for j >0: Save modified radii and Fourier grids */
         info->rcoulomb[j]  = ir->rcoulomb;
         info->rvdw[j]      = ir->rvdw;
         info->nkx[j]       = ir->nkx;
         info->rcoulomb[j]  = ir->rcoulomb;
         info->rvdw[j]      = ir->rvdw;
         info->nkx[j]       = ir->nkx;
@@ -1100,9 +887,9 @@ static void make_benchmark_tprs(
         info->nkz[j]       = ir->nkz;
         info->rlist[j]     = ir->rlist;
         info->rlistlong[j] = ir->rlistlong;
         info->nkz[j]       = ir->nkz;
         info->rlist[j]     = ir->rlist;
         info->rlistlong[j] = ir->rlistlong;
-        info->fsx[j]       = pmegrid[j].fs;
-        info->fsy[j]       = pmegrid[j].fs;
-        info->fsz[j]       = pmegrid[j].fs;
+        info->fsx[j]       = fac*fourierspacing;
+        info->fsy[j]       = fac*fourierspacing;
+        info->fsz[j]       = fac*fourierspacing;
 
         /* Write the benchmark tpr file */
         strncpy(fn_bench_tprs[j],fn_sim_tpr,strlen(fn_sim_tpr)-strlen(".tpr"));
 
         /* Write the benchmark tpr file */
         strncpy(fn_bench_tprs[j],fn_sim_tpr,strlen(fn_sim_tpr)-strlen(".tpr"));
@@ -1111,17 +898,14 @@ static void make_benchmark_tprs(
         fprintf(stdout,"Writing benchmark tpr %s with nsteps=", fn_bench_tprs[j]);
         fprintf(stdout, gmx_large_int_pfmt, ir->nsteps);
         if (j > 0)
         fprintf(stdout,"Writing benchmark tpr %s with nsteps=", fn_bench_tprs[j]);
         fprintf(stdout, gmx_large_int_pfmt, ir->nsteps);
         if (j > 0)
-            fprintf(stdout,", scaling factor %f\n", pmegrid[j].fac);
+            fprintf(stdout,", scaling factor %f\n", fac);
         else
             fprintf(stdout,", unmodified settings\n");
 
         write_tpx_state(fn_bench_tprs[j],ir,&state,&mtop);
         else
             fprintf(stdout,", unmodified settings\n");
 
         write_tpx_state(fn_bench_tprs[j],ir,&state,&mtop);
-        
+
         /* Write information about modified tpr settings to log file */
         /* Write information about modified tpr settings to log file */
-        if (j==0)
-            fprintf(fp, "%4d%10s%10f", j, "-input-", ir->rcoulomb);
-        else
-            fprintf(fp, "%4d%10f%10f", j, pmegrid[j].fac, ir->rcoulomb);
+        fprintf(fp, "%4d%10f%10f", j, fac, ir->rcoulomb);
         fprintf(fp, "%5d%5d%5d", ir->nkx, ir->nky, ir->nkz);
         fprintf(fp, " %9f ", info->fsx[j]);
         if (evdwCUT == ir->vdwtype)
         fprintf(fp, "%5d%5d%5d", ir->nkx, ir->nky, ir->nkz);
         fprintf(fp, " %9f ", info->fsx[j]);
         if (evdwCUT == ir->vdwtype)
@@ -1140,8 +924,8 @@ static void make_benchmark_tprs(
         }
     }
     if (bNote)
         }
     }
     if (bNote)
-        fprintf(fp, "\nNote that in addition to rcoulomb and the fourier grid\n"
-                    "also other input settings were changed (see table above).\n"
+        fprintf(fp, "\nNote that in addition to the Coulomb radius and the Fourier grid\n"
+                    "other input settings were also changed (see table above).\n"
                     "Please check if the modified settings are appropriate.\n");
     fflush(stdout);
     fflush(fp);
                     "Please check if the modified settings are appropriate.\n");
     fflush(stdout);
     fflush(fp);
@@ -1151,7 +935,7 @@ static void make_benchmark_tprs(
 
 /* Rename the files we want to keep to some meaningful filename and
  * delete the rest */
 
 /* Rename the files we want to keep to some meaningful filename and
  * delete the rest */
-static void cleanup(const t_filenm *fnm, int nfile, int k, int nnodes, 
+static void cleanup(const t_filenm *fnm, int nfile, int k, int nnodes,
                     int nPMEnodes, int nr, gmx_bool bKeepStderr)
 {
     char numstring[STRLEN];
                     int nPMEnodes, int nr, gmx_bool bKeepStderr)
 {
     char numstring[STRLEN];
@@ -1269,7 +1053,7 @@ static void make_npme_list(
     {
         eNPME = eNpmeSubset;
     }
     {
         eNPME = eNpmeSubset;
     }
-    else if ( 0 == strcmp(npmevalues_opt, "auto") )
+    else /* "auto" or "range" */
     {
         if (nnodes <= 64)
             eNPME = eNpmeAll;
     {
         if (nnodes <= 64)
             eNPME = eNpmeAll;
@@ -1278,10 +1062,6 @@ static void make_npme_list(
         else
             eNPME = eNpmeSubset;
     }
         else
             eNPME = eNpmeSubset;
     }
-    else
-    {
-        gmx_fatal(FARGS, "Unknown option for -npme in make_npme_list");
-    }
 
     /* Calculate how many entries we could possibly have (in case of -npme all) */
     if (nnodes > 2)
 
     /* Calculate how many entries we could possibly have (in case of -npme all) */
     if (nnodes > 2)
@@ -1357,6 +1137,41 @@ static void init_perfdata(t_perf *perfdata[], int ntprs, int datasets, int repea
 }
 
 
 }
 
 
+/* Check for errors on mdrun -h */
+static void make_sure_it_runs(char *mdrun_cmd_line, int length, FILE *fp)
+{
+    char *command, *msg;
+    int  ret;
+
+
+    snew(command, length +  15);
+    snew(msg    , length + 500);
+
+    fprintf(stdout, "Making shure the benchmarks can be executed ...\n");
+    sprintf(command, "%s-h -quiet", mdrun_cmd_line);
+    ret = gmx_system_call(command);
+
+    if (0 != ret)
+    {
+        /* 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"
+                        "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"
+                        "\n%s\n\n", command);
+
+        fprintf(stderr, "%s", msg);
+        sep_line(fp);
+        fprintf(fp    , "%s", msg);
+
+        exit(ret);
+    }
+
+    sfree(command);
+    sfree(msg    );
+}
+
+
 static void do_the_tests(
         FILE *fp,                   /* General g_tune_pme output file         */
         char **tpr_names,           /* Filenames of the input files to test   */
 static void do_the_tests(
         FILE *fp,                   /* General g_tune_pme output file         */
         char **tpr_names,           /* Filenames of the input files to test   */
@@ -1387,7 +1202,8 @@ static void do_the_tests(
     int     cmdline_length;
     char    *command, *cmd_stub;
     char    buf[STRLEN];
     int     cmdline_length;
     char    *command, *cmd_stub;
     char    buf[STRLEN];
-    gmx_bool    bResetProblem=FALSE;
+    gmx_bool bResetProblem=FALSE;
+    gmx_bool bFirst=TRUE;
 
 
     /* This string array corresponds to the eParselog enum type at the start
 
 
     /* This string array corresponds to the eParselog enum type at the start
@@ -1400,16 +1216,16 @@ static void do_the_tests(
                               "No DD grid found for these settings.",
                               "TPX version conflict!",
                               "mdrun was not started in parallel!",
                               "No DD grid found for these settings.",
                               "TPX version conflict!",
                               "mdrun was not started in parallel!",
-                              "A fatal error occured!" };
+                              "An error occured." };
     char    str_PME_f_load[13];
 
 
     char    str_PME_f_load[13];
 
 
-    /* Allocate space for the mdrun command line. 100 extra characters should 
+    /* Allocate space for the mdrun command line. 100 extra characters should
        be more than enough for the -npme etcetera arguments */
        be more than enough for the -npme etcetera arguments */
-    cmdline_length =  strlen(cmd_mpirun) 
+    cmdline_length =  strlen(cmd_mpirun)
                     + strlen(cmd_np)
                     + strlen(cmd_np)
-                    + strlen(cmd_mdrun) 
-                    + strlen(cmd_args_bench) 
+                    + strlen(cmd_mdrun)
+                    + strlen(cmd_args_bench)
                     + strlen(tpr_names[0]) + 100;
     snew(command , cmdline_length);
     snew(cmd_stub, cmdline_length);
                     + strlen(tpr_names[0]) + 100;
     snew(command , cmdline_length);
     snew(cmd_stub, cmdline_length);
@@ -1466,7 +1282,7 @@ static void do_the_tests(
             for (nr = 0; nr < repeats; nr++)
             {
                 pd->nPMEnodes = nPMEnodes[i];
             for (nr = 0; nr < repeats; nr++)
             {
                 pd->nPMEnodes = nPMEnodes[i];
-                
+
                 /* Add -npme and -s to the command line and save it. Note that
                  * the -passall (if set) options requires cmd_args_bench to be
                  * at the end of the command line string */
                 /* Add -npme and -s to the command line and save it. Note that
                  * the -passall (if set) options requires cmd_args_bench to be
                  * at the end of the command line string */
@@ -1474,6 +1290,12 @@ static void do_the_tests(
                 sprintf(pd->mdrun_cmd_line, "%s-npme %d -s %s %s",
                         cmd_stub, pd->nPMEnodes, tpr_names[k], cmd_args_bench);
 
                 sprintf(pd->mdrun_cmd_line, "%s-npme %d -s %s %s",
                         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 with mdrun -h first */
+                if (bFirst)
+                    make_sure_it_runs(pd->mdrun_cmd_line, cmdline_length, fp);
+                bFirst = FALSE;
+
                 /* Do a benchmark simulation: */
                 if (repeats > 1)
                     sprintf(buf, ", pass %d/%d", nr+1, repeats);
                 /* Do a benchmark simulation: */
                 if (repeats > 1)
                     sprintf(buf, ", pass %d/%d", nr+1, repeats);
@@ -1504,7 +1326,7 @@ static void do_the_tests(
                     sprintf(str_PME_f_load, "%12.3f", pd->PME_f_load[nr]);
                 else
                     sprintf(str_PME_f_load, "%s", "         -  ");
                     sprintf(str_PME_f_load, "%12.3f", pd->PME_f_load[nr]);
                 else
                     sprintf(str_PME_f_load, "%s", "         -  ");
-                
+
                 /* Write the data we got to disk */
                 fprintf(fp, "%4d%s %12.3f %12.3f %s    %s", pd->nPMEnodes,
                         buf, pd->Gcycles[nr], pd->ns_per_day[nr], str_PME_f_load, ParseLog[ret]);
                 /* Write the data we got to disk */
                 fprintf(fp, "%4d%s %12.3f %12.3f %s    %s", pd->nPMEnodes,
                         buf, pd->Gcycles[nr], pd->ns_per_day[nr], str_PME_f_load, ParseLog[ret]);
@@ -1527,6 +1349,7 @@ static void do_the_tests(
             } /* end of repeats loop */
         } /* end of -npme loop */
     } /* end of tpr file loop */
             } /* end of repeats loop */
         } /* end of -npme loop */
     } /* end of tpr file loop */
+
     if (bResetProblem)
     {
         sep_line(fp);
     if (bResetProblem)
     {
         sep_line(fp);
@@ -1544,15 +1367,15 @@ static void do_the_tests(
 
 
 static void check_input(
 
 
 static void check_input(
-        int nnodes, 
-        int repeats, 
-        int *ntprs, 
-        real *upfac,
-        real *downfac,
+        int nnodes,
+        int repeats,
+        int *ntprs,
+        real *rmin,
+        real rcoulomb,
+        real *rmax,
         real maxPMEfraction,
         real minPMEfraction,
         int  npme_fixed,
         real maxPMEfraction,
         real minPMEfraction,
         int  npme_fixed,
-        real fourierspacing,
         gmx_large_int_t bench_nsteps,
         const t_filenm *fnm,
         int nfile,
         gmx_large_int_t bench_nsteps,
         const t_filenm *fnm,
         int nfile,
@@ -1561,10 +1384,13 @@ static void check_input(
         int npargs,
         t_pargs *pa)
 {
         int npargs,
         t_pargs *pa)
 {
+    int old;
+
+
     /* Make sure the input file exists */
     if (!gmx_fexist(opt2fn("-s",nfile,fnm)))
         gmx_fatal(FARGS, "File %s not found.", opt2fn("-s",nfile,fnm));
     /* Make sure the input file exists */
     if (!gmx_fexist(opt2fn("-s",nfile,fnm)))
         gmx_fatal(FARGS, "File %s not found.", opt2fn("-s",nfile,fnm));
-    
+
     /* Make sure that the checkpoint file is not overwritten during benchmarking */
     if ( (0 == strcmp(opt2fn("-cpi",nfile,fnm), opt2fn("-bcpo",nfile,fnm)) ) && (sim_part > 1) )
         gmx_fatal(FARGS, "Checkpoint input (-cpi) and benchmark checkpoint output (-bcpo) files must not be identical.\n"
     /* Make sure that the checkpoint file is not overwritten during benchmarking */
     if ( (0 == strcmp(opt2fn("-cpi",nfile,fnm), opt2fn("-bcpo",nfile,fnm)) ) && (sim_part > 1) )
         gmx_fatal(FARGS, "Checkpoint input (-cpi) and benchmark checkpoint output (-bcpo) files must not be identical.\n"
@@ -1583,8 +1409,13 @@ static void check_input(
     {
         if (nnodes < 16)
             *ntprs = 1;
     {
         if (nnodes < 16)
             *ntprs = 1;
-        else 
+        else
+        {
             *ntprs = 3;
             *ntprs = 3;
+            /* Set a reasonable scaling factor for rcoulomb */
+            if (*rmax <= 0)
+                *rmax = rcoulomb * 1.2;
+        }
         fprintf(stderr, "Will test %d tpr file%s.\n", *ntprs, *ntprs==1?"":"s");
     }
     else
         fprintf(stderr, "Will test %d tpr file%s.\n", *ntprs, *ntprs==1?"":"s");
     }
     else
@@ -1592,12 +1423,54 @@ static void check_input(
         if (1 == *ntprs)
             fprintf(stderr, "Note: Choose ntpr>1 to shift PME load between real and reciprocal space.\n");
     }
         if (1 == *ntprs)
             fprintf(stderr, "Note: Choose ntpr>1 to shift PME load between real and reciprocal space.\n");
     }
-    
-    if ( is_equal(*downfac,*upfac) && (*ntprs > 2) && !(fourierspacing > 0.0))
+
+    /* Make shure that rmin <= rcoulomb <= rmax */
+    if (*rmin <= 0) *rmin = rcoulomb;
+    if (*rmax <= 0) *rmax = rcoulomb;
+    if ( !(*rmin <= *rmax) )
+    {
+        gmx_fatal(FARGS, "Please choose the Coulomb radii such that rmin <= rmax.\n"
+                         "rmin = %g, rmax = %g, actual rcoul from .tpr file = %g\n", *rmin, *rmax, rcoulomb);
+    }
+    /* Add test scenarios if rmin or rmax were set */
+    if (*ntprs <= 2)
+    {
+        if ( !is_equal(*rmin, rcoulomb) && (*ntprs == 1) )
+        {
+            (*ntprs)++;
+            fprintf(stderr, "NOTE: Setting -rmin to %g changed -ntpr to %d\n",
+                    *rmin, *ntprs);
+        }
+        if (!is_equal(*rmax, rcoulomb) && (*ntprs == 1) )
+        {
+            (*ntprs)++;
+            fprintf(stderr, "NOTE: Setting -rmax to %g changed -ntpr to %d\n",
+                    *rmax, *ntprs);
+        }
+    }
+    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) )
+        *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) )
+        *ntprs = max(*ntprs, 3);
+
+    if (old != *ntprs)
+    {
+        fprintf(stderr, "NOTE: Your rmin, rmax setting changed -ntpr to %d\n", *ntprs);
+    }
+
+    if (*ntprs > 1)
     {
     {
-        fprintf(stderr, "WARNING: Resetting -ntpr to 2 since both scaling factors are the same.\n"
-                        "Please choose upfac unequal to downfac to test various PME grid settings\n");
-        *ntprs = 2;
+        if (is_equal(*rmin,rcoulomb) && is_equal(rcoulomb,*rmax)) /* 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"
+                            "with correspondingly adjusted PME grid settings\n");
+            *ntprs = 1;
+        }
     }
 
     /* Check whether max and min fraction are within required values */
     }
 
     /* Check whether max and min fraction are within required values */
@@ -1607,7 +1480,7 @@ static void check_input(
         gmx_fatal(FARGS, "-min must be between 0 and 0.5");
     if (maxPMEfraction < minPMEfraction)
         gmx_fatal(FARGS, "-max must be larger or equal to -min");
         gmx_fatal(FARGS, "-min must be between 0 and 0.5");
     if (maxPMEfraction < minPMEfraction)
         gmx_fatal(FARGS, "-max must be larger or equal to -min");
-    
+
     /* Check whether the number of steps - if it was set - has a reasonable value */
     if (bench_nsteps < 0)
         gmx_fatal(FARGS, "Number of steps must be positive.");
     /* Check whether the number of steps - if it was set - has a reasonable value */
     if (bench_nsteps < 0)
         gmx_fatal(FARGS, "Number of steps must be positive.");
@@ -1618,39 +1491,17 @@ static void check_input(
         fprintf(stderr, gmx_large_int_pfmt, bench_nsteps);
         fprintf(stderr, ". Are you sure you want to perform so %s steps for each benchmark?\n", (bench_nsteps < 100)? "few" : "many");
     }
         fprintf(stderr, gmx_large_int_pfmt, bench_nsteps);
         fprintf(stderr, ". Are you sure you want to perform so %s steps for each benchmark?\n", (bench_nsteps < 100)? "few" : "many");
     }
-    
+
     if (presteps < 0)
     {
         gmx_fatal(FARGS, "Cannot have a negative number of presteps.\n");
     }
     if (presteps < 0)
     {
         gmx_fatal(FARGS, "Cannot have a negative number of presteps.\n");
     }
-    
-    if (*upfac <= 0.0 || *downfac <= 0.0 || *downfac > *upfac)
-        gmx_fatal(FARGS, "Both scaling factors must be larger than zero and upper\n"
-                         "scaling limit (%f) must be larger than lower limit (%f).",
-                         *upfac, *downfac);
 
 
-    if (*downfac < 0.75 || *upfac > 1.25)
-        fprintf(stderr, "WARNING: Applying extreme scaling factor. I hope you know what you are doing.\n");
-    
-    if (fourierspacing < 0)
-        gmx_fatal(FARGS, "Please choose a positive value for fourierspacing.");
-
-    /* Make shure that the scaling factor options are compatible with the number of tprs */
-    if ( (*ntprs < 3) && ( opt2parg_bSet("-upfac",npargs,pa) || opt2parg_bSet("-downfac",npargs,pa) ) )
-    {
-        if (opt2parg_bSet("-upfac",npargs,pa) && opt2parg_bSet("-downfac",npargs,pa) && !is_equal(*upfac,*downfac))
-        {
-            fprintf(stderr, "NOTE: Specify -ntpr > 2 for both scaling factors to take effect.\n"
-                             "(upfac=%f, downfac=%f)\n", *upfac, *downfac);
-        }
-        if (opt2parg_bSet("-upfac",npargs,pa))
-            *downfac = *upfac;
-        if (opt2parg_bSet("-downfac",npargs,pa))
-            *upfac = *downfac;
-    }
-    if ( (2 == *ntprs) && (opt2parg_bSet("-downfac",npargs,pa)) && !is_equal(*downfac, 1.0))
+    /* Check for rcoulomb scaling if more than one .tpr file is tested */
+    if (*ntprs > 1)
     {
     {
-        *upfac = 1.0;
+        if (*rmin/rcoulomb < 0.75 || *rmax/rcoulomb > 1.25)
+            fprintf(stderr, "WARNING: Applying extreme scaling factor. I hope you know what you are doing.\n");
     }
 
     /* If a fixed number of PME nodes is set we do rcoulomb and PME gird tuning
     }
 
     /* If a fixed number of PME nodes is set we do rcoulomb and PME gird tuning
@@ -1678,49 +1529,12 @@ static void check_input(
 }
 
 
 }
 
 
-/* Returns TRUE when "opt" is a switch for g_tune_pme itself */
-static gmx_bool is_main_switch(char *opt)
-{
-    if ( (0 == strcmp(opt,"-s"        ))
-      || (0 == strcmp(opt,"-p"        ))
-      || (0 == strcmp(opt,"-launch"   ))
-      || (0 == strcmp(opt,"-r"        ))
-      || (0 == strcmp(opt,"-ntpr"     ))
-      || (0 == strcmp(opt,"-max"      ))
-      || (0 == strcmp(opt,"-min"      ))
-      || (0 == strcmp(opt,"-upfac"    ))
-      || (0 == strcmp(opt,"-downfac"  ))
-      || (0 == strcmp(opt,"-fix"      ))
-      || (0 == strcmp(opt,"-four"     ))
-      || (0 == strcmp(opt,"-steps"    ))
-      || (0 == strcmp(opt,"-simsteps" ))
-      || (0 == strcmp(opt,"-resetstep"))
-      || (0 == strcmp(opt,"-so"       ))
-      || (0 == strcmp(opt,"-npstring" ))
-      || (0 == strcmp(opt,"-npme"     ))
-      || (0 == strcmp(opt,"-passall"  )) )
-    return TRUE;
-    
-    return FALSE;
-}
-
-
-/* Returns TRUE when "opt" is needed at launch time */
-static gmx_bool is_launch_option(char *opt, gmx_bool bSet)
-{
-    if (bSet)
-        return TRUE;
-    else    
-        return FALSE;
-}
-
-
 /* Returns TRUE when "opt" is needed at launch time */
 static gmx_bool is_launch_file(char *opt, gmx_bool bSet)
 {
 /* Returns TRUE when "opt" is needed at launch time */
 static gmx_bool is_launch_file(char *opt, gmx_bool bSet)
 {
-    /* We need all options that were set on the command line 
-     * and that do not start with -b */
-    if (0 == strncmp(opt,"-b", 2))
+    /* Apart from the input .tpr we need all options that were set
+     * on the command line and that do not start with -b */
+    if (0 == strncmp(opt,"-b", 2) || 0 == strncmp(opt,"-s", 2))
         return FALSE;
 
     if (bSet)
         return FALSE;
 
     if (bSet)
@@ -1730,33 +1544,14 @@ static gmx_bool is_launch_file(char *opt, gmx_bool bSet)
 }
 
 
 }
 
 
-/* Returns TRUE when "opt" gives an option needed for the benchmarks runs */
-static gmx_bool is_bench_option(char *opt, gmx_bool bSet)
-{
-    /* If option is set, we might need it for the benchmarks.
-     * This includes -cpi */
-    if (bSet)
-    {
-        if ( (0 == strcmp(opt, "-append"   ))
-          || (0 == strcmp(opt, "-maxh"     ))
-          || (0 == strcmp(opt, "-deffnm"   ))
-          || (0 == strcmp(opt, "-resethway"))
-          || (0 == strcmp(opt, "-cpnum"    )) )
-            return FALSE;
-        else
-            return TRUE;
-    }
-    else
-        return FALSE;
-}
-
-
 /* Returns TRUE when "opt" defines a file which is needed for the benchmarks runs */
 static gmx_bool is_bench_file(char *opt, gmx_bool bSet, gmx_bool bOptional, gmx_bool bIsOutput)
 {
 /* Returns TRUE when "opt" defines a file which is needed for the benchmarks runs */
 static gmx_bool is_bench_file(char *opt, gmx_bool bSet, gmx_bool bOptional, gmx_bool bIsOutput)
 {
-    /* All options starting with "-b" are for _b_enchmark files exclusively */
-    if (0 == strncmp(opt,"-b", 2))
-    { 
+    /* Apart from the input .tpr, all files starting with "-b" are for
+     * _b_enchmark files exclusively */
+    if (0 == strncmp(opt,"-s", 2)) return FALSE;
+    if (0 == strncmp(opt,"-b", 2) || 0 == strncmp(opt,"-s", 2))
+    {
         if (!bOptional || bSet)
             return TRUE;
         else
         if (!bOptional || bSet)
             return TRUE;
         else
@@ -1769,7 +1564,7 @@ static gmx_bool is_bench_file(char *opt, gmx_bool bSet, gmx_bool bOptional, gmx_
         else
             if (bSet) /* These are additional input files like -cpi -ei */
                 return TRUE;
         else
             if (bSet) /* These are additional input files like -cpi -ei */
                 return TRUE;
-            else 
+            else
                 return FALSE;
     }
 }
                 return FALSE;
     }
 }
@@ -1779,8 +1574,8 @@ static gmx_bool is_bench_file(char *opt, gmx_bool bSet, gmx_bool bOptional, gmx_
 static void add_to_string(char **str, char *buf)
 {
     int len;
 static void add_to_string(char **str, char *buf)
 {
     int len;
-    
-    
+
+
     len = strlen(*str) + strlen(buf) + 1;
     srenew(*str, len);
     strcat(*str, buf);
     len = strlen(*str) + strlen(buf) + 1;
     srenew(*str, len);
     strcat(*str, buf);
@@ -1789,7 +1584,10 @@ static void add_to_string(char **str, char *buf)
 
 /* Create the command line for the benchmark as well as for the real run */
 static void create_command_line_snippets(
 
 /* Create the command line for the benchmark as well as for the real run */
 static void create_command_line_snippets(
-        gmx_bool     bThreads,
+        gmx_bool bThreads,
+        gmx_bool bAppendFiles,
+        gmx_bool bKeepAndNumCPT,
+        gmx_bool bResetHWay,
         int      presteps,
         int      nfile,
         t_filenm fnm[],
         int      presteps,
         int      nfile,
         t_filenm fnm[],
@@ -1804,81 +1602,39 @@ static void create_command_line_snippets(
     int        i;
     char       *opt;
     const char *name;
     int        i;
     char       *opt;
     const char *name;
-    char       *np_or_nt;
-#define BUFLENGTH 255
-    char       buf[BUFLENGTH];
-    char       strbuf[BUFLENGTH];
-    char       strbuf2[BUFLENGTH];
-    
+    char       strbuf[STRLEN];
+
 
 
-    if (bThreads)
-        np_or_nt=strdup("-nt");
-    else
-        np_or_nt=strdup("-np");
-    
     /* strlen needs at least '\0' as a string: */
     snew(*cmd_args_bench ,1);
     snew(*cmd_args_launch,1);
     *cmd_args_launch[0]='\0';
     *cmd_args_bench[0] ='\0';
     /* strlen needs at least '\0' as a string: */
     snew(*cmd_args_bench ,1);
     snew(*cmd_args_launch,1);
     *cmd_args_launch[0]='\0';
     *cmd_args_bench[0] ='\0';
-    
-        
+
+
     /*******************************************/
     /* 1. Process other command line arguments */
     /*******************************************/
     /*******************************************/
     /* 1. Process other command line arguments */
     /*******************************************/
-    for (i=0; i<npargs; i++)
-    {
-        /* What command line switch are we currently processing: */
-        opt = (char *)pa[i].option;
-        /* Skip options not meant for mdrun */        
-        if (!is_main_switch(opt))
-        {
-            /* Boolean arguments need to be generated in the -[no]argname format */
-            if (pa[i].type == etBOOL)
-            {
-                sprintf(strbuf,"-%s%s ",*pa[i].u.b ? "" : "no",opt+1);
-            }
-            else
-            {
-                /* Print it to a string buffer, strip away trailing whitespaces that pa_val also returns: */
-                sprintf(strbuf2, "%s", pa_val(&pa[i],buf,BUFLENGTH));
-                rtrim(strbuf2);
-                sprintf(strbuf, "%s %s ", opt, strbuf2);
-            }
-
-            /* We need the -np (or -nt) switch in a separate buffer - whether or not it was set! */
-            if (0 == strcmp(opt,np_or_nt))
-            {
-                if (strcmp(procstring, "none")==0 && !bThreads)
-                {
-                    /* Omit -np <N> entirely */
-                    snew(*cmd_np, 2);
-                    sprintf(*cmd_np, " ");
-                }
-                else
-                {
-                    /* This is the normal case with -np <N> */
-                    snew(*cmd_np, strlen(procstring)+strlen(strbuf2)+4);
-                    sprintf(*cmd_np, " %s %s ", bThreads? "-nt" : procstring, strbuf2);
-                }
-            }
-            else 
-            {
-                if (is_bench_option(opt,pa[i].bSet))
-                    add_to_string(cmd_args_bench, strbuf);
-
-                if (is_launch_option(opt,pa[i].bSet))
-                    add_to_string(cmd_args_launch, strbuf);
-            }
-        }
-    }
     if (presteps > 0)
     {
         /* Add equilibration steps to benchmark options */
         sprintf(strbuf, "-resetstep %d ", presteps);
         add_to_string(cmd_args_bench, strbuf);
     }
     if (presteps > 0)
     {
         /* Add equilibration steps to benchmark options */
         sprintf(strbuf, "-resetstep %d ", presteps);
         add_to_string(cmd_args_bench, strbuf);
     }
-    
+    /* These switches take effect only at launch time */
+    if (FALSE == bAppendFiles)
+    {
+        add_to_string(cmd_args_launch, "-noappend ");
+    }
+    if (bKeepAndNumCPT)
+    {
+        add_to_string(cmd_args_launch, "-cpnum ");
+    }
+    if (bResetHWay)
+    {
+        add_to_string(cmd_args_launch, "-resethway ");
+    }
+
     /********************/
     /* 2. Process files */
     /********************/
     /********************/
     /* 2. Process files */
     /********************/
@@ -1886,32 +1642,26 @@ static void create_command_line_snippets(
     {
         opt  = (char *)fnm[i].opt;
         name = opt2fn(opt,nfile,fnm);
     {
         opt  = (char *)fnm[i].opt;
         name = opt2fn(opt,nfile,fnm);
-        
+
         /* Strbuf contains the options, now let's sort out where we need that */
         sprintf(strbuf, "%s %s ", opt, name);
         /* Strbuf contains the options, now let's sort out where we need that */
         sprintf(strbuf, "%s %s ", opt, name);
-        
-        /* Skip options not meant for mdrun */        
-        if (!is_main_switch(opt))
+
+        if ( is_bench_file(opt, opt2bSet(opt,nfile,fnm), is_optional(&fnm[i]), is_output(&fnm[i])) )
         {
         {
-            
-            if ( is_bench_file(opt, opt2bSet(opt,nfile,fnm), is_optional(&fnm[i]), is_output(&fnm[i])) )
-            {
-                /* All options starting with -b* need the 'b' removed,
-                 * therefore overwrite strbuf */
-                if (0 == strncmp(opt, "-b", 2))     
-                    sprintf(strbuf, "-%s %s ", &opt[2], name);
-                
-                add_to_string(cmd_args_bench, strbuf);
-            }
-            
-            if ( is_launch_file(opt,opt2bSet(opt,nfile,fnm)) )
-                add_to_string(cmd_args_launch, strbuf);
+            /* All options starting with -b* need the 'b' removed,
+             * therefore overwrite strbuf */
+            if (0 == strncmp(opt, "-b", 2))
+                sprintf(strbuf, "-%s %s ", &opt[2], name);
+
+            add_to_string(cmd_args_bench, strbuf);
         }
         }
+
+        if ( is_launch_file(opt,opt2bSet(opt,nfile,fnm)) )
+            add_to_string(cmd_args_launch, strbuf);
     }
 
     add_to_string(cmd_args_bench , extra_args);
     add_to_string(cmd_args_launch, extra_args);
     }
 
     add_to_string(cmd_args_bench , extra_args);
     add_to_string(cmd_args_launch, extra_args);
-#undef BUFLENGTH
 }
 
 
 }
 
 
@@ -1919,17 +1669,20 @@ static void create_command_line_snippets(
 static void setopt(const char *opt,int nfile,t_filenm fnm[])
 {
   int i;
 static void setopt(const char *opt,int nfile,t_filenm fnm[])
 {
   int i;
-  
+
   for(i=0; (i<nfile); i++)
     if (strcmp(opt,fnm[i].opt)==0)
       fnm[i].flag |= ffSET;
 }
 
 
   for(i=0; (i<nfile); i++)
     if (strcmp(opt,fnm[i].opt)==0)
       fnm[i].flag |= ffSET;
 }
 
 
-/* This routine checks for output files that get triggered by a tpr option.
- * These output files are marked as set to allow for proper cleanup after 
- * each tuning run. */
-static void get_tpr_outfiles(int nfile, t_filenm fnm[])
+/* This routine inspects the tpr file and ...
+ * 1. checks for output files that get triggered by a tpr option. These output
+ *    files are marked as 'set' to allow for a proper cleanup after each
+ *    tuning run.
+ * 2. returns the PME:PP load ratio
+ * 3. returns rcoulomb from the tpr */
+static float inspect_tpr(int nfile, t_filenm fnm[], real *rcoulomb)
 {
     gmx_bool     bPull;     /* Is pulling requested in .tpr file?             */
     gmx_bool     bTpi;      /* Is test particle insertion requested?          */
 {
     gmx_bool     bPull;     /* Is pulling requested in .tpr file?             */
     gmx_bool     bTpi;      /* Is test particle insertion requested?          */
@@ -1966,6 +1719,11 @@ static void get_tpr_outfiles(int nfile, t_filenm fnm[])
     {
         setopt("-mtx" , nfile, fnm);
     }
     {
         setopt("-mtx" , nfile, fnm);
     }
+
+    *rcoulomb = ir.rcoulomb;
+
+    /* Return the estimate for the number of PME nodes */
+    return pme_load_estimate(&mtop,&ir,state.box);
 }
 
 
 }
 
 
@@ -1975,8 +1733,8 @@ static void couple_files_options(int nfile, t_filenm fnm[])
     gmx_bool bSet,bBench;
     char *opt;
     char buf[20];
     gmx_bool bSet,bBench;
     char *opt;
     char buf[20];
-    
-    
+
+
     for (i=0; i<nfile; i++)
     {
         opt  = (char *)fnm[i].opt;
     for (i=0; i<nfile; i++)
     {
         opt  = (char *)fnm[i].opt;
@@ -2007,15 +1765,15 @@ static double gettime()
     double seconds;
 
     gettimeofday(&t,NULL);
     double seconds;
 
     gettimeofday(&t,NULL);
-    
+
     seconds = (double) t.tv_sec + 1e-6*(double)t.tv_usec;
     seconds = (double) t.tv_sec + 1e-6*(double)t.tv_usec;
-    
+
     return seconds;
 #else
     double  seconds;
     return seconds;
 #else
     double  seconds;
-    
+
     seconds = time(NULL);
     seconds = time(NULL);
-    
+
     return seconds;
 #endif
 }
     return seconds;
 #endif
 }
@@ -2045,19 +1803,20 @@ int gmx_tune_pme(int argc,char *argv[])
             "to repeat each test several times to get better statistics. [PAR]",
             "[TT]g_tune_pme[tt] can test various real space / reciprocal space workloads",
             "for you. With [TT]-ntpr[tt] you control how many extra [TT].tpr[tt] files will be",
             "to repeat each test several times to get better statistics. [PAR]",
             "[TT]g_tune_pme[tt] can test various real space / reciprocal space workloads",
             "for you. With [TT]-ntpr[tt] you control how many extra [TT].tpr[tt] files will be",
-            "written with enlarged cutoffs and smaller fourier grids respectively.",
+            "written with enlarged cutoffs and smaller Fourier grids respectively.",
             "Typically, the first test (number 0) will be with the settings from the input",
             "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 cutoffs multiplied",
-            "by (and at the same time fourier grid dimensions divided by) the scaling",
-            "factor [TT]-fac[tt] (default 1.2). The remaining [TT].tpr[tt] files will have about ",
-            "equally-spaced values in between these extremes. [BB]Note[bb] that you can set [TT]-ntpr[tt] to 1",
-            "if you just want to find the optimal number of PME-only nodes; in that case",
+            "[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. ",
+            "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",
+            "if you just seek the optimal number of PME-only nodes; in that case",
             "your input [TT].tpr[tt] file will remain unchanged.[PAR]",
             "For the benchmark runs, the default of 1000 time steps should suffice for most",
             "MD systems. The dynamic load balancing needs about 100 time steps",
             "to adapt to local load imbalances, therefore the time step counters",
             "your input [TT].tpr[tt] file will remain unchanged.[PAR]",
             "For the benchmark runs, the default of 1000 time steps should suffice for most",
             "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) you may have to set [TT]-resetstep[tt] to a higher value.",
+            "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.",
             "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]g_tune_pme -np 64 -s protein.tpr -launch[tt][PAR]",
             "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]g_tune_pme -np 64 -s protein.tpr -launch[tt][PAR]",
@@ -2075,24 +1834,26 @@ int gmx_tune_pme(int argc,char *argv[])
     real       maxPMEfraction=0.50;
     real       minPMEfraction=0.25;
     int        maxPMEnodes, minPMEnodes;
     real       maxPMEfraction=0.50;
     real       minPMEfraction=0.25;
     int        maxPMEnodes, minPMEnodes;
+    float      guessPMEratio;   /* guessed PME:PP ratio based on the tpr file */
+    float      guessPMEnodes;
     int        npme_fixed=-2;             /* If >= -1, use only this number
                                            * of PME-only nodes                */
     int        npme_fixed=-2;             /* If >= -1, use only this number
                                            * of PME-only nodes                */
-    real       downfac=1.0,upfac=1.2;
     int        ntprs=0;
     int        ntprs=0;
-    real       fs=0.0;                    /* 0 indicates: not set by the user */
+    real       rmin=0.0,rmax=0.0;  /* min and max value for rcoulomb if scaling is requested */
+    real       rcoulomb=-1.0;             /* Coulomb radius as set in .tpr file */
     gmx_large_int_t bench_nsteps=BENCHSTEPS;
     gmx_large_int_t new_sim_nsteps=-1;   /* -1 indicates: not set by the user */
     gmx_large_int_t cpt_steps=0;         /* Step counter in .cpt input file   */
     int        presteps=100;    /* Do a full cycle reset after presteps steps */
     gmx_large_int_t bench_nsteps=BENCHSTEPS;
     gmx_large_int_t new_sim_nsteps=-1;   /* -1 indicates: not set by the user */
     gmx_large_int_t cpt_steps=0;         /* Step counter in .cpt input file   */
     int        presteps=100;    /* Do a full cycle reset after presteps steps */
-    gmx_bool       bOverwrite=FALSE, bKeepTPR;
-    gmx_bool       bLaunch=FALSE;
-    gmx_bool       bPassAll=FALSE;
+    gmx_bool   bOverwrite=FALSE, bKeepTPR;
+    gmx_bool   bLaunch=FALSE;
     char       *ExtraArgs=NULL;
     char       **tpr_names=NULL;
     const char *simulation_tpr=NULL;
     int        best_npme, best_tpr;
     int        sim_part = 1;     /* For benchmarks with checkpoint files */
     char       *ExtraArgs=NULL;
     char       **tpr_names=NULL;
     const char *simulation_tpr=NULL;
     int        best_npme, best_tpr;
     int        sim_part = 1;     /* For benchmarks with checkpoint files */
-    
+    char       bbuf[STRLEN];
+
     /* Default program names if nothing else is found */
     char        *cmd_mpirun=NULL, *cmd_mdrun=NULL;
     char        *cmd_args_bench, *cmd_args_launch;
     /* Default program names if nothing else is found */
     char        *cmd_mpirun=NULL, *cmd_mdrun=NULL;
     char        *cmd_args_bench, *cmd_args_launch;
@@ -2106,11 +1867,11 @@ int gmx_tune_pme(int argc,char *argv[])
 
     /* Print out how long the tuning took */
     double      seconds;
 
     /* Print out how long the tuning took */
     double      seconds;
-    
+
     static t_filenm fnm[] = {
       /* g_tune_pme */
       { efOUT, "-p",      "perf",     ffWRITE },
     static t_filenm fnm[] = {
       /* g_tune_pme */
       { efOUT, "-p",      "perf",     ffWRITE },
-      { efLOG, "-err",    "errors",   ffWRITE },
+      { efLOG, "-err",    "bencherr", ffWRITE },
       { efTPX, "-so",     "tuned",    ffWRITE },
       /* mdrun: */
       { efTPX, NULL,      NULL,       ffREAD },
       { efTPX, "-so",     "tuned",    ffWRITE },
       /* mdrun: */
       { efTPX, NULL,      NULL,       ffREAD },
@@ -2171,41 +1932,20 @@ int gmx_tune_pme(int argc,char *argv[])
       { efNDX, "-bdn",    "bench",    ffOPTWR }
     };
 
       { efNDX, "-bdn",    "bench",    ffOPTWR }
     };
 
-    /* Command line options of mdrun */
-    gmx_bool bDDBondCheck = TRUE;
-    gmx_bool bDDBondComm  = TRUE;
-    gmx_bool bVerbose     = FALSE;
-    gmx_bool bCompact     = TRUE;
-    gmx_bool bSepPot      = FALSE;
-    gmx_bool bRerunVSite  = FALSE;
-    gmx_bool bIonize      = FALSE;
-    gmx_bool bConfout     = TRUE;
-    gmx_bool bReproducible = FALSE;
     gmx_bool bThreads     = FALSE;
 
     gmx_bool bThreads     = FALSE;
 
-    int  nmultisim=0;
-    int  nstglobalcomm=-1;
-    int  repl_ex_nst=0;
-    int  repl_ex_seed=-1;
-    int  nstepout=100;
     int  nthreads=1;
 
     int  nthreads=1;
 
-    const char *ddno_opt[ddnoNR+1] =
-      { NULL, "interleave", "pp_pme", "cartesian", NULL };
-    const char *dddlb_opt[] =
-      { NULL, "auto", "no", "yes", NULL };
     const char *procstring[] =
       { NULL, "-np", "-n", "none", NULL };
     const char *npmevalues_opt[] =
       { NULL, "auto", "all", "subset", NULL };
     const char *procstring[] =
       { NULL, "-np", "-n", "none", NULL };
     const char *npmevalues_opt[] =
       { NULL, "auto", "all", "subset", NULL };
-    real rdd=0.0,rconstr=0.0,dlb_scale=0.8,pforce=-1;
-    char *ddcsx=NULL,*ddcsy=NULL,*ddcsz=NULL;
-    char *deffnm=NULL;
-#define STD_CPT_PERIOD (15.0)
-    real cpt_period=STD_CPT_PERIOD,max_hours=-1;
+
     gmx_bool bAppendFiles=TRUE;
     gmx_bool bKeepAndNumCPT=FALSE;
     gmx_bool bResetCountersHalfWay=FALSE;
     gmx_bool bAppendFiles=TRUE;
     gmx_bool bKeepAndNumCPT=FALSE;
     gmx_bool bResetCountersHalfWay=FALSE;
+    gmx_bool bBenchmark=TRUE;
+
     output_env_t oenv=NULL;
 
     t_pargs pa[] = {
     output_env_t oenv=NULL;
 
     t_pargs pa[] = {
@@ -2216,8 +1956,6 @@ int gmx_tune_pme(int argc,char *argv[])
         "Number of nodes to run the tests on (must be > 2 for separate PME nodes)" },
       { "-npstring", FALSE, etENUM, {procstring},
         "Specify the number of processors to [TT]$MPIRUN[tt] using this string"},
         "Number of nodes to run the tests on (must be > 2 for separate PME nodes)" },
       { "-npstring", FALSE, etENUM, {procstring},
         "Specify the number of processors to [TT]$MPIRUN[tt] using this string"},
-      { "-passall",  FALSE, etBOOL, {&bPassAll},
-        "HIDDENPut arguments unknown to [TT]mdrun[tt] at the end of the command line. Can be used for debugging purposes. "},
       { "-nt",       FALSE, etINT,  {&nthreads},
         "Number of threads to run the tests on (turns MPI & mpirun off)"},
       { "-r",        FALSE, etINT,  {&repeats},
       { "-nt",       FALSE, etINT,  {&nthreads},
         "Number of threads to run the tests on (turns MPI & mpirun off)"},
       { "-r",        FALSE, etINT,  {&repeats},
@@ -2227,89 +1965,41 @@ int gmx_tune_pme(int argc,char *argv[])
       { "-min",      FALSE, etREAL, {&minPMEfraction},
         "Min fraction of PME nodes to test with" },
       { "-npme",     FALSE, etENUM, {npmevalues_opt},
       { "-min",      FALSE, etREAL, {&minPMEfraction},
         "Min fraction of PME nodes to test with" },
       { "-npme",     FALSE, etENUM, {npmevalues_opt},
-        "Benchmark all possible values for [TT]-npme[tt] or just the subset that is expected to perform well"},
-      { "-fix",      FALSE, etINT, {&npme_fixed},
+        "Within -min and -max, benchmark all possible values for [TT]-npme[tt], or just a reasonable subset. "
+        "Auto neglects -min and -max and chooses reasonable values around a guess for npme derived from the .tpr"},
+      { "-fix",      FALSE, etINT,  {&npme_fixed},
         "If >= -1, do not vary the number of PME-only nodes, instead use this fixed value and only vary rcoulomb and the PME grid spacing."},
         "If >= -1, do not vary the number of PME-only nodes, instead use this fixed value and only vary rcoulomb and the PME grid spacing."},
-      { "-upfac",    FALSE, etREAL, {&upfac},
-        "Upper limit for rcoulomb scaling factor (Note that rcoulomb upscaling results in fourier grid downscaling)" },
-      { "-downfac",  FALSE, etREAL, {&downfac},
-        "Lower limit for rcoulomb scaling factor" },
+      { "-rmax",     FALSE, etREAL, {&rmax},
+        "If >0, maximal rcoulomb for -ntpr>1 (rcoulomb upscaling results in fourier grid downscaling)" },
+      { "-rmin",     FALSE, etREAL, {&rmin},
+        "If >0, minimal rcoulomb for -ntpr>1" },
       { "-ntpr",     FALSE, etINT,  {&ntprs},
       { "-ntpr",     FALSE, etINT,  {&ntprs},
-        "Number of [TT].tpr[tt] files to benchmark. Create this many files with scaling factors ranging from 1.0 to fac. If < 1, automatically choose the number of [TT].tpr[tt] files to test" },
-      { "-four",     FALSE, etREAL, {&fs},
-        "Use this fourierspacing value instead of the grid found in the [TT].tpr[tt] input file. (Spacing applies to a scaling factor of 1.0 if multiple [TT].tpr[tt] files are written)" },
+        "Number of [TT].tpr[tt] files to benchmark. Create this many files with different rcoulomb scaling factors depending on -rmin and -rmax. "
+        "If < 1, automatically choose the number of [TT].tpr[tt] files to test" },
       { "-steps",    FALSE, etGMX_LARGE_INT, {&bench_nsteps},
       { "-steps",    FALSE, etGMX_LARGE_INT, {&bench_nsteps},
-        "Take timings for this many steps in the benchmark runs" }, 
+        "Take timings for this many steps in the benchmark runs" },
       { "-resetstep",FALSE, etINT,  {&presteps},
         "Let dlb equilibrate this many steps before timings are taken (reset cycle counters after this many steps)" },
       { "-simsteps", FALSE, etGMX_LARGE_INT, {&new_sim_nsteps},
       { "-resetstep",FALSE, etINT,  {&presteps},
         "Let dlb equilibrate this many steps before timings are taken (reset cycle counters after this many steps)" },
       { "-simsteps", FALSE, etGMX_LARGE_INT, {&new_sim_nsteps},
-        "If non-negative, perform this many steps in the real run (overwrites nsteps from [TT].tpr[tt], add [TT].cpt[tt] steps)" }, 
+        "If non-negative, perform this many steps in the real run (overwrites nsteps from [TT].tpr[tt], add [TT].cpt[tt] steps)" },
       { "-launch",   FALSE, etBOOL, {&bLaunch},
         "Launch the real simulation after optimization" },
       { "-launch",   FALSE, etBOOL, {&bLaunch},
         "Launch the real simulation after optimization" },
+      { "-bench",    FALSE, etBOOL, {&bBenchmark},
+        "Run the benchmarks or just create the input [TT].tpr[tt] files?" },
       /******************/
       /* mdrun options: */
       /******************/
       /******************/
       /* mdrun options: */
       /******************/
-      { "-deffnm",    FALSE, etSTR, {&deffnm},
-          "Set the default filename for all file options at launch time" },
-      { "-ddorder",   FALSE, etENUM, {ddno_opt},
-        "DD node order" },
-      { "-ddcheck",   FALSE, etBOOL, {&bDDBondCheck},
-        "Check for all bonded interactions with DD" },
-      { "-ddbondcomm",FALSE, etBOOL, {&bDDBondComm},
-        "HIDDENUse special bonded atom communication when [TT]-rdd[tt] > cut-off" },
-      { "-rdd",       FALSE, etREAL, {&rdd},
-        "The maximum distance for bonded interactions with DD (nm), 0 is determine from initial coordinates" },
-      { "-rcon",      FALSE, etREAL, {&rconstr},
-        "Maximum distance for P-LINCS (nm), 0 is estimate" },
-      { "-dlb",       FALSE, etENUM, {dddlb_opt},
-        "Dynamic load balancing (with DD)" },
-      { "-dds",       FALSE, etREAL, {&dlb_scale},
-        "Minimum allowed dlb scaling of the DD cell size" },
-      { "-ddcsx",     FALSE, etSTR,  {&ddcsx},
-        "HIDDENThe DD cell sizes in x" },
-      { "-ddcsy",     FALSE, etSTR,  {&ddcsy},
-        "HIDDENThe DD cell sizes in y" },
-      { "-ddcsz",     FALSE, etSTR,  {&ddcsz},
-        "HIDDENThe DD cell sizes in z" },
-      { "-gcom",      FALSE, etINT,  {&nstglobalcomm},
-        "Global communication frequency" },
-      { "-v",         FALSE, etBOOL, {&bVerbose},
-        "Be loud and noisy" },
-      { "-compact",   FALSE, etBOOL, {&bCompact},
-        "Write a compact log file" },
-      { "-seppot",    FALSE, etBOOL, {&bSepPot},
-        "Write separate V and dVdl terms for each interaction type and node to the log file(s)" },
-      { "-pforce",    FALSE, etREAL, {&pforce},
-        "Print all forces larger than this (kJ/mol nm)" },
-      { "-reprod",    FALSE, etBOOL, {&bReproducible},
-        "Try to avoid optimizations that affect binary reproducibility" },
-      { "-cpt",       FALSE, etREAL, {&cpt_period},
-        "Checkpoint interval (minutes)" },
-      { "-cpnum",   FALSE, etBOOL, {&bKeepAndNumCPT},
-        "Keep and number checkpoint files" },
-      { "-append",    FALSE, etBOOL, {&bAppendFiles},
+      /* We let g_tune_pme parse and understand these options, because we need to
+       * prevent that they appear on the mdrun command line for the benchmarks */
+      { "-append",   FALSE, etBOOL, {&bAppendFiles},
         "Append to previous output files when continuing from checkpoint instead of adding the simulation part number to all file names (for launch only)" },
         "Append to previous output files when continuing from checkpoint instead of adding the simulation part number to all file names (for launch only)" },
-      { "-maxh",      FALSE, etREAL, {&max_hours},
-        "Terminate after 0.99 times this time (hours)" },
-      { "-multi",     FALSE, etINT,  {&nmultisim},
-        "Do multiple simulations in parallel" },
-      { "-replex",    FALSE, etINT,  {&repl_ex_nst},
-        "Attempt replica exchange periodically with this period (steps)" },
-      { "-reseed",    FALSE, etINT,  {&repl_ex_seed},
-        "Seed for replica exchange, -1 is generate a seed" },
-      { "-rerunvsite", FALSE, etBOOL, {&bRerunVSite},
-        "HIDDENRecalculate virtual site coordinates with [TT]-rerun[tt]" },
-      { "-ionize",    FALSE, etBOOL, {&bIonize},
-        "Do a simulation including the effect of an X-ray bombardment on your system" },
-      { "-confout",   FALSE, etBOOL, {&bConfout},
-        "HIDDENWrite the last configuration with [TT]-c[tt] and force checkpointing at the last step" },
-      { "-stepout",   FALSE, etINT,  {&nstepout},
-        "HIDDENFrequency of writing the remaining runtime" },
+      { "-cpnum",    FALSE, etBOOL, {&bKeepAndNumCPT},
+        "Keep and number checkpoint files (launch only)" },
       { "-resethway", FALSE, etBOOL, {&bResetCountersHalfWay},
         "HIDDENReset the cycle counters after half the number of steps or halfway [TT]-maxh[tt] (launch only)" }
     };
 
       { "-resethway", FALSE, etBOOL, {&bResetCountersHalfWay},
         "HIDDENReset the cycle counters after half the number of steps or halfway [TT]-maxh[tt] (launch only)" }
     };
 
-    
+
 #define NFILE asize(fnm)
 
     CopyRight(stderr,argv[0]);
 #define NFILE asize(fnm)
 
     CopyRight(stderr,argv[0]);
@@ -2318,9 +2008,10 @@ int gmx_tune_pme(int argc,char *argv[])
 
     parse_common_args(&argc,argv,PCA_NOEXIT_ON_ARGS,
                       NFILE,fnm,asize(pa),pa,asize(desc),desc,
 
     parse_common_args(&argc,argv,PCA_NOEXIT_ON_ARGS,
                       NFILE,fnm,asize(pa),pa,asize(desc),desc,
-                      0,NULL,&oenv);        
+                      0,NULL,&oenv);
 
 
-    /* Store the remaining unparsed command line entries in a string */
+    /* Store the remaining unparsed command line entries in a string which
+     * is then attached to the mdrun command line */
     snew(ExtraArgs, 1);
     ExtraArgs[0] = '\0';
     for (i=1; i<argc; i++) /* argc will now be 1 if everything was understood */
     snew(ExtraArgs, 1);
     ExtraArgs[0] = '\0';
     for (i=1; i<argc; i++) /* argc will now be 1 if everything was understood */
@@ -2328,14 +2019,6 @@ int gmx_tune_pme(int argc,char *argv[])
         add_to_string(&ExtraArgs, argv[i]);
         add_to_string(&ExtraArgs, " ");
     }
         add_to_string(&ExtraArgs, argv[i]);
         add_to_string(&ExtraArgs, " ");
     }
-    if ( !bPassAll && (ExtraArgs[0] != '\0') )
-    {
-        fprintf(stderr, "\nWARNING: The following arguments you provided have no effect:\n"
-                        "%s\n"
-                        "Use the -passall option to force them to appear on the command lines\n"
-                        "for the benchmark simulations%s.\n\n",
-                        ExtraArgs, bLaunch? " and at launch time" : "");
-    }
 
     if (opt2parg_bSet("-nt",asize(pa),pa))
     {
 
     if (opt2parg_bSet("-nt",asize(pa),pa))
     {
@@ -2348,18 +2031,25 @@ int gmx_tune_pme(int argc,char *argv[])
         /* and now we just set this; a bit of an ugly hack*/
         nnodes=nthreads;
     }
         /* and now we just set this; a bit of an ugly hack*/
         nnodes=nthreads;
     }
-    /* tpr-triggered output files */
-    get_tpr_outfiles(NFILE,fnm);
+    /* Check for PME:PP ratio and whether tpr triggers additional output files */
+    guessPMEratio = inspect_tpr(NFILE,fnm,&rcoulomb);
 
     /* Automatically set -beo options if -eo is set etc. */
     couple_files_options(NFILE,fnm);
 
     /* Automatically set -beo options if -eo is set etc. */
     couple_files_options(NFILE,fnm);
-    
-    /* Construct the command line arguments for benchmark runs 
-     * as well as for the simulation run 
-     */
-    create_command_line_snippets(bThreads,presteps,NFILE,fnm,asize(pa),pa,procstring[0],
+
+    /* Construct the command line arguments for benchmark runs
+     * as well as for the simulation run */
+    if (bThreads)
+        sprintf(bbuf," -nt %d ", nthreads);
+    else
+        sprintf(bbuf," -np %d ", nnodes);
+
+    cmd_np = bbuf;
+
+    create_command_line_snippets(bThreads,bAppendFiles,bKeepAndNumCPT,bResetCountersHalfWay,presteps,
+                                 NFILE,fnm,asize(pa),pa,procstring[0],
                                  &cmd_np, &cmd_args_bench, &cmd_args_launch,
                                  &cmd_np, &cmd_args_bench, &cmd_args_launch,
-                                 bPassAll? ExtraArgs : (char *)"");
+                                 ExtraArgs);
 
     /* Read in checkpoint file if requested */
     sim_part = 1;
 
     /* Read in checkpoint file if requested */
     sim_part = 1;
@@ -2368,46 +2058,66 @@ int gmx_tune_pme(int argc,char *argv[])
         snew(cr,1);
         cr->duty=DUTY_PP; /* makes the following routine happy */
         read_checkpoint_simulation_part(opt2fn("-cpi",NFILE,fnm),
         snew(cr,1);
         cr->duty=DUTY_PP; /* makes the following routine happy */
         read_checkpoint_simulation_part(opt2fn("-cpi",NFILE,fnm),
-                                       &sim_part,&cpt_steps,cr,
-                                       FALSE,NFILE,fnm,NULL,NULL);
+                    &sim_part,&cpt_steps,cr,
+                    FALSE,NFILE,fnm,NULL,NULL);
         sfree(cr);
         sim_part++;
         /* sim_part will now be 1 if no checkpoint file was found */
         if (sim_part<=1)
         sfree(cr);
         sim_part++;
         /* sim_part will now be 1 if no checkpoint file was found */
         if (sim_part<=1)
-            gmx_fatal(FARGS, "Checkpoint file %s not found!", opt2fn("-cpi",
-                                                                     NFILE,
-                                                                     fnm));
+            gmx_fatal(FARGS, "Checkpoint file %s not found!", opt2fn("-cpi",NFILE,fnm));
     }
     }
-    
+
     /* Open performance output file and write header info */
     fp = ffopen(opt2fn("-p",NFILE,fnm),"w");
     /* Open performance output file and write header info */
     fp = ffopen(opt2fn("-p",NFILE,fnm),"w");
-    
+
     /* Make a quick consistency check of command line parameters */
     /* Make a quick consistency check of command line parameters */
-    check_input(nnodes, repeats, &ntprs, &upfac, &downfac,
+    check_input(nnodes, repeats, &ntprs, &rmin, rcoulomb, &rmax,
                 maxPMEfraction, minPMEfraction, npme_fixed,
                 maxPMEfraction, minPMEfraction, npme_fixed,
-                fs, bench_nsteps, fnm, NFILE, sim_part, presteps,
+                bench_nsteps, fnm, NFILE, sim_part, presteps,
                 asize(pa),pa);
                 asize(pa),pa);
-    
+
     /* Determine the maximum and minimum number of PME nodes to test,
      * the actual list of settings is build in do_the_tests(). */
     if ((nnodes > 2) && (npme_fixed < -1))
     {
     /* Determine the maximum and minimum number of PME nodes to test,
      * the actual list of settings is build in do_the_tests(). */
     if ((nnodes > 2) && (npme_fixed < -1))
     {
-        maxPMEnodes = floor(maxPMEfraction*nnodes);
-        minPMEnodes = max(floor(minPMEfraction*nnodes), 0);
-        fprintf(stdout, "Will try runs with %d ", minPMEnodes);
-        if (maxPMEnodes != minPMEnodes)
-            fprintf(stdout, "- %d ", maxPMEnodes);
-        fprintf(stdout, "PME-only nodes.\n  Note that the automatic number of PME-only nodes and no separate PME nodes are always tested.\n");
+        if (0 == strcmp(npmevalues_opt[0], "auto"))
+        {
+            /* Determine the npme range automatically based on the PME:PP load guess */
+            if (guessPMEratio > 1.0)
+            {
+                /* More PME than PP work, probably we do not need separate PME nodes at all! */
+                maxPMEnodes=nnodes/2;
+                minPMEnodes=nnodes/2;
+            }
+            else
+            {
+                /* PME : PP load is in the range 0..1, let's test around the guess */
+                guessPMEnodes = nnodes/(1.0 + 1.0/guessPMEratio);
+                minPMEnodes = floor(0.7*guessPMEnodes);
+                maxPMEnodes =  ceil(1.6*guessPMEnodes);
+                maxPMEnodes = min(maxPMEnodes, nnodes/2);
+            }
+        }
+        else
+        {
+            /* Determine the npme range based on user input */
+            maxPMEnodes = floor(maxPMEfraction*nnodes);
+            minPMEnodes = max(floor(minPMEfraction*nnodes), 0);
+            fprintf(stdout, "Will try runs with %d ", minPMEnodes);
+            if (maxPMEnodes != minPMEnodes)
+                fprintf(stdout, "- %d ", maxPMEnodes);
+            fprintf(stdout, "PME-only nodes.\n  Note that the automatic number of PME-only nodes and no separate PME nodes are always tested.\n");
+        }
     }
     else
     {
         maxPMEnodes = 0;
         minPMEnodes = 0;
     }
     else
     {
         maxPMEnodes = 0;
         minPMEnodes = 0;
-    }   
-    
+    }
+
     /* Get the commands we need to set up the runs from environment variables */
     get_program_paths(bThreads, &cmd_mpirun, cmd_np, &cmd_mdrun, repeats);
     /* Get the commands we need to set up the runs from environment variables */
     get_program_paths(bThreads, &cmd_mpirun, cmd_np, &cmd_mdrun, repeats);
-    
+
     /* Print some header info to file */
     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");
     /* Print some header info to file */
     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");
@@ -2437,10 +2147,8 @@ int gmx_tune_pme(int argc,char *argv[])
         fprintf(fp, gmx_large_int_pfmt, cpt_steps);
         fprintf(fp, "\n");
     }
         fprintf(fp, gmx_large_int_pfmt, cpt_steps);
         fprintf(fp, "\n");
     }
-    if (bLaunch)
-        fprintf(fp, "mdrun args at launchtime: %s\n", cmd_args_launch);
-    if (!bPassAll && ExtraArgs[0] != '\0')
-        fprintf(fp, "Unused arguments        : %s\n", ExtraArgs);
+    fprintf(fp, "mdrun args at launchtime: %s\n", cmd_args_launch);
+
     if (new_sim_nsteps >= 0)
     {
         bOverwrite = TRUE;
     if (new_sim_nsteps >= 0)
     {
         bOverwrite = TRUE;
@@ -2450,21 +2158,17 @@ int gmx_tune_pme(int argc,char *argv[])
         fprintf(fp, "Simulation steps        : ");
         fprintf(fp, gmx_large_int_pfmt, new_sim_nsteps);
         fprintf(fp, "\n");
         fprintf(fp, "Simulation steps        : ");
         fprintf(fp, gmx_large_int_pfmt, new_sim_nsteps);
         fprintf(fp, "\n");
-    }   
+    }
     if (repeats > 1)
         fprintf(fp, "Repeats for each test   : %d\n", repeats);
     if (repeats > 1)
         fprintf(fp, "Repeats for each test   : %d\n", repeats);
-    
-    if (fs > 0.0)
-    {
-        fprintf(fp, "Requested grid spacing  : %f (This will be the grid spacing at a scaling factor of 1.0)\n", fs);
-    }
-    
+
     if (npme_fixed >= -1)
     {
         fprintf(fp, "Fixing -npme at         : %d\n", npme_fixed);
     }
 
     fprintf(fp, "Input file              : %s\n", opt2fn("-s",NFILE,fnm));
     if (npme_fixed >= -1)
     {
         fprintf(fp, "Fixing -npme at         : %d\n", npme_fixed);
     }
 
     fprintf(fp, "Input file              : %s\n", opt2fn("-s",NFILE,fnm));
+    fprintf(fp, "   PME/PP load estimate : %g\n", guessPMEratio);
 
     /* Allocate memory for the inputinfo struct: */
     snew(info, 1);
 
     /* Allocate memory for the inputinfo struct: */
     snew(info, 1);
@@ -2490,44 +2194,53 @@ int gmx_tune_pme(int argc,char *argv[])
     /* It can be that ntprs is reduced by make_benchmark_tprs if not enough
      * different grids could be found. */
     make_benchmark_tprs(opt2fn("-s",NFILE,fnm), tpr_names, bench_nsteps+presteps,
     /* It can be that ntprs is reduced by make_benchmark_tprs if not enough
      * different grids could be found. */
     make_benchmark_tprs(opt2fn("-s",NFILE,fnm), tpr_names, bench_nsteps+presteps,
-            cpt_steps, upfac, downfac, &ntprs, fs, info, fp);
-
+            cpt_steps, rmin, rmax, &ntprs, info, fp);
 
     /********************************************************************************/
     /* Main loop over all scenarios we need to test: tpr files, PME nodes, repeats  */
     /********************************************************************************/
     snew(perfdata, ntprs);
 
     /********************************************************************************/
     /* Main loop over all scenarios we need to test: tpr files, PME nodes, repeats  */
     /********************************************************************************/
     snew(perfdata, ntprs);
-    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, sim_part, presteps, cpt_steps);
-    
-    fprintf(fp, "\nTuning took%8.1f minutes.\n", (gettime()-seconds)/60.0);
-
-    /* Analyse the results and give a suggestion for optimal settings: */
-    bKeepTPR = analyze_data(fp, opt2fn("-p", NFILE, fnm), perfdata, nnodes, ntprs, pmeentries,
-                            repeats, info, &best_tpr, &best_npme);
-    
-    /* Take the best-performing tpr file and enlarge nsteps to original value */
-    if ( bKeepTPR && !bOverwrite && !(fs > 0.0) )
+    if (bBenchmark)
     {
     {
-        simulation_tpr = opt2fn("-s",NFILE,fnm);
-    }
-    else
-    {
-        simulation_tpr = opt2fn("-so",NFILE,fnm);
-        modify_PMEsettings(bOverwrite? (new_sim_nsteps+cpt_steps) : 
-                           info->orig_sim_steps, tpr_names[best_tpr], 
-                           simulation_tpr);            
-    }
+        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, sim_part, presteps, cpt_steps);
 
 
-    /* Now start the real simulation if the user requested it ... */
-    launch_simulation(bLaunch, fp, bThreads, cmd_mpirun, cmd_np, cmd_mdrun,
-                      cmd_args_launch, simulation_tpr, nnodes, best_npme);
+        fprintf(fp, "\nTuning took%8.1f minutes.\n", (gettime()-seconds)/60.0);
+
+        /* Analyse the results and give a suggestion for optimal settings: */
+        bKeepTPR = analyze_data(fp, opt2fn("-p", NFILE, fnm), perfdata, nnodes, ntprs, pmeentries,
+                repeats, info, &best_tpr, &best_npme);
+
+        /* Take the best-performing tpr file and enlarge nsteps to original value */
+        if ( bKeepTPR && !bOverwrite )
+        {
+            simulation_tpr = opt2fn("-s",NFILE,fnm);
+        }
+        else
+        {
+            simulation_tpr = opt2fn("-so",NFILE,fnm);
+            modify_PMEsettings(bOverwrite? (new_sim_nsteps+cpt_steps) :
+                    info->orig_sim_steps, tpr_names[best_tpr],
+                    simulation_tpr);
+        }
+
+        /* Let's get rid of the temporary benchmark input files */
+        for (i=0; i<ntprs; i++)
+        {
+            fprintf(stdout, "Deleting temporary benchmark input file %s\n", tpr_names[i]);
+            remove(tpr_names[i]);
+        }
+
+        /* Now start the real simulation if the user requested it ... */
+        launch_simulation(bLaunch, fp, bThreads, cmd_mpirun, cmd_np, cmd_mdrun,
+                cmd_args_launch, simulation_tpr, nnodes, best_npme);
+    }
     ffclose(fp);
     ffclose(fp);
-        
+
     /* ... or simply print the performance results to screen: */
     if (!bLaunch)
         finalize(opt2fn("-p", NFILE, fnm));
     /* ... or simply print the performance results to screen: */
     if (!bLaunch)
         finalize(opt2fn("-p", NFILE, fnm));
-    
+
     return 0;
 }
     return 0;
 }