Reworked convert-tpr runtime extension
authorEliane Briand <eliane.briand@mpibpc.mpg.de>
Fri, 28 May 2021 07:11:10 +0000 (07:11 +0000)
committerAndrey Alekseenko <al42and@gmail.com>
Mon, 21 Jun 2021 20:42:22 +0000 (20:42 +0000)
Fixes extension of run using -until flag.

Fixes #4056

docs/release-notes/2021/2021.3.rst
src/gromacs/tools/convert_tpr.cpp
src/gromacs/tools/tests/refdata/HelpwritingTest_ConvertTprWritesHelp.xml

index 049bc1cddeacf260a15af789725fa050c69b641b..e2548d36177a614a416471fffa6b29508da500ec 100644 (file)
@@ -34,6 +34,14 @@ The tool now reports correct values.
 
 :issue:`4080`
 
+Make sure gmx convert-tpr -until works
+""""""""""""""""""""""""""""""""""""""
+
+This got broken during reworking the internals of the tool and didn't
+calculate the number of remaining steps correctly.
+
+:issue:`4056`
+
 Fixes that affect portability
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
index fe66b9f58814f5d3ad38b6a47dd3bb60284cfe75..eea593201549321aeb26b47dfd7ae8d80939c4c2 100644 (file)
@@ -4,7 +4,7 @@
  * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
  * Copyright (c) 2001-2004, The GROMACS development team.
  * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
- * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
+ * Copyright (c) 2018,2019,2020,2021, by the GROMACS development team, led by
  * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
  * and including many others, as listed in the AUTHORS file in the
  * top-level source directory and at http://www.gromacs.org.
@@ -271,6 +271,19 @@ static void zeroq(const int index[], gmx_mtop_t* mtop)
     }
 }
 
+static void print_runtime_info(t_inputrec* ir)
+{
+    char buf[STEPSTRSIZE];
+
+    printf("  Run start step                %22s     \n", gmx_step_str(ir->init_step, buf));
+    printf("  Run start time                %22g ps  \n", ir->init_step * ir->delta_t + ir->init_t);
+    printf("  Step to be made during run    %22s     \n", gmx_step_str(ir->nsteps, buf));
+    printf("  Runtime for the run           %22g ps  \n", ir->nsteps * ir->delta_t);
+    printf("  Run end step                  %22s     \n", gmx_step_str(ir->init_step + ir->nsteps, buf));
+    printf("  Run end time                  %22g ps  \n\n",
+           (ir->init_step + ir->nsteps) * ir->delta_t + ir->init_t);
+}
+
 namespace gmx
 {
 
@@ -364,8 +377,10 @@ void ConvertTpr::initOptions(IOptionsContainer* options, ICommandLineOptionsModu
                                .storeIsSet(&runToMaxTimeIsSet_)
                                .timeValue()
                                .description("Extend runtime until this ending time (ps)"));
-    options->addOption(
-            Int64Option("nsteps").store(&maxSteps_).storeIsSet(&maxStepsIsSet_).description("Change the number of steps"));
+    options->addOption(Int64Option("nsteps")
+                               .store(&maxSteps_)
+                               .storeIsSet(&maxStepsIsSet_)
+                               .description("Change the number of steps remaining to be made"));
     options->addOption(
             BooleanOption("zeroq").store(&zeroQIsSet_).description("Set the charges of a group (from the index) to zero"));
 }
@@ -377,107 +392,123 @@ int ConvertTpr::run()
     gmx_mtop_t mtop;
     t_atoms    atoms;
     t_state    state;
-    char       buf[200], buf2[200];
+    char       buf[STEPSTRSIZE];
+
+    if (static_cast<int>(extendTimeIsSet_) + static_cast<int>(maxStepsIsSet_) + static_cast<int>(runToMaxTimeIsSet_)
+        > 1)
+    {
+        printf("Multiple runtime modification operations cannot be done in a single call.\n");
+        return 1;
+    }
+
+    if ((extendTimeIsSet_ || maxStepsIsSet_ || runToMaxTimeIsSet_) && (zeroQIsSet_ || haveReadIndexFile_))
+    {
+        printf("Cannot do both runtime modification and charge-zeroing/index group extraction in a "
+               "single call.\n");
+        return 1;
+    }
+
+    if (zeroQIsSet_ && !haveReadIndexFile_)
+    {
+        printf("Charge zeroing need an index file.\n");
+        return 1;
+    }
 
-    fprintf(stderr, "Reading toplogy and stuff from %s\n", inputTprFileName_.c_str());
 
     t_inputrec  irInstance;
     t_inputrec* ir = &irInstance;
     read_tpx_state(inputTprFileName_.c_str(), ir, &state, &mtop);
-    int64_t currentMaxStep    = ir->init_step;
-    double  currentRunTime    = ir->init_step * ir->delta_t + ir->init_t;
-    real    currentMaxRunTime = 0.0;
 
-    if (maxStepsIsSet_)
-    {
-        fprintf(stderr, "Setting nsteps to %s\n", gmx_step_str(maxSteps_, buf));
-        ir->nsteps = maxSteps_;
-    }
-    else
+
+    if (extendTimeIsSet_ || maxStepsIsSet_ || runToMaxTimeIsSet_)
     {
-        /* Determine total number of steps remaining */
-        if (extendTimeIsSet_)
-        {
-            ir->nsteps = ir->nsteps - (currentMaxStep - ir->init_step)
-                         + gmx::roundToInt64(extendTime_ / ir->delta_t);
-            printf("Extending remaining runtime of by %g ps (now %s steps)\n", extendTime_,
-                   gmx_step_str(ir->nsteps, buf));
-        }
-        else if (runToMaxTimeIsSet_)
+        // Doing runtime modification
+
+        const double  inputTimeAtStartOfRun = ir->init_step * ir->delta_t + ir->init_t;
+        const int64_t inputStepAtEndOfRun   = ir->init_step + ir->nsteps;
+        const double  inputTimeAtEndOfRun   = inputStepAtEndOfRun * ir->delta_t + ir->init_t;
+
+        printf("Input file:\n");
+        print_runtime_info(ir);
+
+        if (maxStepsIsSet_)
         {
-            printf("nsteps = %s, run_step = %s, current_t = %g, until = %g\n",
-                   gmx_step_str(ir->nsteps, buf), gmx_step_str(currentMaxStep, buf2),
-                   currentRunTime, runToMaxTime_);
-            ir->nsteps = gmx::roundToInt64((currentMaxRunTime - currentRunTime) / ir->delta_t);
-            printf("Extending remaining runtime until %g ps (now %s steps)\n", currentMaxRunTime,
-                   gmx_step_str(ir->nsteps, buf));
+            fprintf(stderr, "Setting nsteps to %s\n", gmx_step_str(maxSteps_, buf));
+            ir->nsteps = maxSteps_;
         }
-        else
+        else if (extendTimeIsSet_)
         {
-            ir->nsteps -= currentMaxStep - ir->init_step;
-            /* Print message */
-            printf("%s steps (%g ps) remaining from first run.\n", gmx_step_str(ir->nsteps, buf),
-                   ir->nsteps * ir->delta_t);
+            printf("Extending remaining runtime by %g ps\n", extendTime_);
+            ir->nsteps += gmx::roundToInt64(extendTime_ / ir->delta_t);
         }
-    }
-
-    if (maxStepsIsSet_ || zeroQIsSet_ || (ir->nsteps > 0))
-    {
-        ir->init_step = currentMaxStep;
-
-        if (haveReadIndexFile_ || !(maxStepsIsSet_ || extendTimeIsSet_ || runToMaxTimeIsSet_))
+        else if (runToMaxTimeIsSet_)
         {
-            atoms         = gmx_mtop_global_atoms(&mtop);
-            int   gnx     = 0;
-            int*  index   = nullptr;
-            char* grpname = nullptr;
-            get_index(&atoms, inputIndexFileName_.c_str(), 1, &gnx, &index, &grpname);
-            bool bSel = false;
-            if (!zeroQIsSet_)
+            if (runToMaxTime_ <= inputTimeAtStartOfRun)
             {
-                bSel = (gnx != state.natoms);
-                for (int i = 0; ((i < gnx) && (!bSel)); i++)
-                {
-                    bSel = (i != index[i]);
-                }
+                printf("The requested run end time is at/before the run start time.\n");
+                return 1;
             }
-            else
+            if (runToMaxTime_ < inputTimeAtEndOfRun)
             {
-                bSel = false;
-            }
-            if (bSel)
-            {
-                fprintf(stderr,
-                        "Will write subset %s of original tpx containing %d "
-                        "atoms\n",
-                        grpname, gnx);
-                reduce_topology_x(gnx, index, &mtop, state.x.rvec_array(), state.v.rvec_array());
-                state.natoms = gnx;
-            }
-            else if (zeroQIsSet_)
-            {
-                zeroq(index, &mtop);
-                fprintf(stderr, "Zero-ing charges for group %s\n", grpname);
+                printf("The requested run end time is before the original run end time.\n");
+                printf("Reducing remaining runtime to %g ps\n", runToMaxTime_);
             }
             else
             {
-                fprintf(stderr, "Will write full tpx file (no selection)\n");
+                printf("Extending remaining runtime to %g ps\n", runToMaxTime_);
             }
+            ir->nsteps = gmx::roundToInt64((runToMaxTime_ - inputTimeAtStartOfRun) / ir->delta_t);
         }
 
-        double stateTime = ir->init_t + ir->init_step * ir->delta_t;
-        sprintf(buf, "Writing statusfile with starting step %s%s and length %s%s steps...\n", "%10",
-                PRId64, "%10", PRId64);
-        fprintf(stderr, buf, ir->init_step, ir->nsteps);
-        fprintf(stderr, "                                 time %10.3f and length %10.3f ps\n",
-                stateTime, ir->nsteps * ir->delta_t);
-        write_tpx_state(outputTprFileName_.c_str(), ir, &state, &mtop);
+        printf("\nOutput file:\n");
+        print_runtime_info(ir);
     }
     else
     {
-        printf("You've simulated long enough. Not writing tpr file\n");
+        // If zeroQIsSet_, then we are doing charge zero-ing; otherwise index group extraction
+        // In both cases an index filename has been provided
+
+        atoms         = gmx_mtop_global_atoms(&mtop);
+        int   gnx     = 0;
+        int*  index   = nullptr;
+        char* grpname = nullptr;
+        get_index(&atoms, inputIndexFileName_.c_str(), 1, &gnx, &index, &grpname);
+        bool bSel = false;
+        if (!zeroQIsSet_)
+        {
+            bSel = (gnx != state.natoms);
+            for (int i = 0; ((i < gnx) && (!bSel)); i++)
+            {
+                bSel = (i != index[i]);
+            }
+        }
+        else
+        {
+            bSel = false;
+        }
+        if (bSel)
+        {
+            fprintf(stderr,
+                    "Will write subset %s of original tpx containing %d "
+                    "atoms\n",
+                    grpname, gnx);
+            reduce_topology_x(gnx, index, &mtop, state.x.rvec_array(), state.v.rvec_array());
+            state.natoms = gnx;
+        }
+        else if (zeroQIsSet_)
+        {
+            zeroq(index, &mtop);
+            fprintf(stderr, "Zero-ing charges for group %s\n", grpname);
+        }
+        else
+        {
+            fprintf(stderr, "Will write full tpx file (no selection)\n");
+        }
     }
 
+    // Writing output tpx regardless of the operation performed
+    write_tpx_state(outputTprFileName_.c_str(), ir, &state, &mtop);
+
     return 0;
 }
 
index b0c890552b3dadd24fb46a505ee7c803a542fb07..25765ad1f390c6e36e6dad97822db73344b08e45 100644 (file)
@@ -44,7 +44,7 @@ Other options:
  -until  <time>             (0)
            Extend runtime until this ending time (ps)
  -nsteps <int>              (0)
-           Change the number of steps
+           Change the number of steps remaining to be made
  -[no]zeroq                 (no)
            Set the charges of a group (from the index) to zero
 ]]></String>