Reimplement constant acceleration groups
[alexxy/gromacs.git] / src / gromacs / tools / dump.cpp
index b116ff6d0549985c59836ab9a41fd4a4b45c77ea..d6506af7f99dfc769768bcb6350bf89591de0a41 100644 (file)
@@ -3,7 +3,8 @@
  *
  * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
  * Copyright (c) 2001-2013, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * 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.
@@ -62,7 +63,7 @@
 #include "gromacs/fileio/xtcio.h"
 #include "gromacs/gmxpreprocess/gmxcpp.h"
 #include "gromacs/math/vecdump.h"
-#include "gromacs/mdrunutility/mdmodules.h"
+#include "gromacs/mdrun/mdmodules.h"
 #include "gromacs/mdtypes/forcerec.h"
 #include "gromacs/mdtypes/inputrec.h"
 #include "gromacs/mdtypes/md_enums.h"
@@ -88,26 +89,23 @@ namespace
 {
 
 //! Dump a TPR file
-void list_tpr(const char *fn,
+void list_tpr(const charfn,
               gmx_bool    bShowNumbers,
               gmx_bool    bShowParameters,
-              const char *mdpfn,
+              const charmdpfn,
               gmx_bool    bSysTop,
               gmx_bool    bOriginalInputrec)
 {
-    FILE         *gp;
-    int           indent, i, j, **gcount, atot;
-    t_state       state;
-    t_tpxheader   tpx;
-    gmx_mtop_t    mtop;
-    t_topology    top;
-
-    read_tpxheader(fn, &tpx, TRUE);
-    t_inputrec     ir;
-    read_tpx_state(fn,
-                   tpx.bIr ? &ir : nullptr,
-                   &state,
-                   tpx.bTop ? &mtop : nullptr);
+    FILE*      gp;
+    int        indent, atot;
+    t_state    state;
+    gmx_mtop_t mtop;
+    t_topology top;
+
+    TpxFileHeader tpx = readTpxHeader(fn, true);
+    t_inputrec    ir;
+
+    read_tpx_state(fn, tpx.bIr ? &ir : nullptr, &state, tpx.bTop ? &mtop : nullptr);
     if (tpx.bIr && !bOriginalInputrec)
     {
         MDModules().adjustInputrecBasedOnModules(&ir);
@@ -158,46 +156,44 @@ void list_tpr(const char *fn,
             pr_rvecs(stdout, indent, "v", tpx.bV ? state.v.rvec_array() : nullptr, state.natoms);
         }
 
-        const gmx_groups_t &groups = mtop.groups;
+        const SimulationGroups& groups = mtop.groups;
 
-        snew(gcount, egcNR);
-        for (i = 0; (i < egcNR); i++)
+        gmx::EnumerationArray<SimulationAtomGroupType, std::vector<int>> gcount;
+        for (auto group : keysOf(gcount))
         {
-            snew(gcount[i], groups.grps[i].nr);
+            gcount[group].resize(groups.groups[group].size());
         }
 
-        for (i = 0; (i < mtop.natoms); i++)
+        for (int i = 0; (i < mtop.natoms); i++)
         {
-            for (j = 0; (j < egcNR); j++)
+            for (auto group : keysOf(gcount))
             {
-                gcount[j][getGroupType(groups, j, i)]++;
+                gcount[group][getGroupType(groups, group, i)]++;
             }
         }
         printf("Group statistics\n");
-        for (i = 0; (i < egcNR); i++)
+        for (auto group : keysOf(gcount))
         {
             atot = 0;
-            printf("%-12s: ", gtypes[i]);
-            for (j = 0; (j < groups.grps[i].nr); j++)
+            printf("%-12s: ", shortName(group));
+            for (const auto& entry : gcount[group])
             {
-                printf("  %5d", gcount[i][j]);
-                atot += gcount[i][j];
+                printf("  %5d", entry);
+                atot += entry;
             }
             printf("  (total %d atoms)\n", atot);
-            sfree(gcount[i]);
         }
-        sfree(gcount);
     }
 }
 
 //! Dump a topology file
-void list_top(const char *fn)
+void list_top(const charfn)
 {
-    int       status, done;
+    int status, done;
     // Legacy string length macro
     char      buf[STRLEN];
     gmx_cpp_t handle;
-    char     *cppopts[] = { nullptr };
+    char*     cppopts[] = { nullptr };
 
     status = cpp_open_file(fn, &handle, cppopts);
     if (status != 0)
@@ -219,8 +215,7 @@ void list_top(const char *fn)
                 printf("%s\n", buf);
             }
         }
-    }
-    while (done == 0);
+    } while (done == 0);
     status = cpp_close_file(&handle);
     if (status != eCPP_OK)
     {
@@ -229,17 +224,17 @@ void list_top(const char *fn)
 }
 
 //! Dump a TRR file
-void list_trr(const char *fn)
+void list_trr(const charfn)
 {
-    t_fileio         *fpread;
-    int               nframe, indent;
-    char              buf[256];
-    rvec             *x, *v, *f;
-    matrix            box;
-    gmx_trr_header_t  trrheader;
-    gmx_bool          bOK;
+    t_fileio*        fpread;
+    int              nframe, indent;
+    char             buf[256];
+    rvec *           x, *v, *f;
+    matrix           box;
+    gmx_trr_header_t trrheader;
+    gmx_bool         bOK;
 
-    fpread  = gmx_trr_open(fn, "r");
+    fpread = gmx_trr_open(fn, "r");
 
     nframe = 0;
     while (gmx_trr_read_frame_header(fpread, &trrheader, &bOK))
@@ -247,18 +242,23 @@ void list_trr(const char *fn)
         snew(x, trrheader.natoms);
         snew(v, trrheader.natoms);
         snew(f, trrheader.natoms);
-        if (gmx_trr_read_frame_data(fpread, &trrheader,
+        if (gmx_trr_read_frame_data(fpread,
+                                    &trrheader,
                                     trrheader.box_size ? box : nullptr,
-                                    trrheader.x_size   ? x : nullptr,
-                                    trrheader.v_size   ? v : nullptr,
-                                    trrheader.f_size   ? f : nullptr))
+                                    trrheader.x_size ? x : nullptr,
+                                    trrheader.v_size ? v : nullptr,
+                                    trrheader.f_size ? f : nullptr))
         {
             sprintf(buf, "%s frame %d", fn, nframe);
             indent = 0;
             indent = pr_title(stdout, indent, buf);
             pr_indent(stdout, indent);
-            fprintf(stdout, "natoms=%10d  step=%10" PRId64 "  time=%12.7e  lambda=%10g\n",
-                    trrheader.natoms, trrheader.step, trrheader.t, trrheader.lambda);
+            fprintf(stdout,
+                    "natoms=%10d  step=%10" PRId64 "  time=%12.7e  lambda=%10g\n",
+                    trrheader.natoms,
+                    trrheader.step,
+                    trrheader.t,
+                    trrheader.lambda);
             if (trrheader.box_size)
             {
                 pr_rvecs(stdout, indent, "box", box, DIM);
@@ -278,8 +278,7 @@ void list_trr(const char *fn)
         }
         else
         {
-            fprintf(stderr, "\nWARNING: Incomplete frame: nr %d, t=%g\n",
-                    nframe, trrheader.t);
+            fprintf(stderr, "\nWARNING: Incomplete frame: nr %d, t=%g\n", nframe, trrheader.t);
         }
 
         sfree(x);
@@ -289,24 +288,23 @@ void list_trr(const char *fn)
     }
     if (!bOK)
     {
-        fprintf(stderr, "\nWARNING: Incomplete frame header: nr %d, t=%g\n",
-                nframe, trrheader.t);
+        fprintf(stderr, "\nWARNING: Incomplete frame header: nr %d, t=%g\n", nframe, trrheader.t);
     }
     gmx_trr_close(fpread);
 }
 
 //! Dump an xtc file
-void list_xtc(const char *fn)
+void list_xtc(const charfn)
 {
-    t_fileio   *xd;
-    int         indent;
-    char        buf[256];
-    rvec       *x;
-    matrix      box;
-    int         nframe, natoms;
-    int64_t     step;
-    real        prec, time;
-    gmx_bool    bOK;
+    t_fileioxd;
+    int       indent;
+    char      buf[256];
+    rvec*     x;
+    matrix    box;
+    int       nframe, natoms;
+    int64_t   step;
+    real      prec, time;
+    gmx_bool  bOK;
 
     xd = open_xtc(fn, "r");
     read_first_xtc(xd, &natoms, &step, &time, box, &x, &prec, &bOK);
@@ -318,13 +316,11 @@ void list_xtc(const char *fn)
         indent = 0;
         indent = pr_title(stdout, indent, buf);
         pr_indent(stdout, indent);
-        fprintf(stdout, "natoms=%10d  step=%10" PRId64 "  time=%12.7e  prec=%10g\n",
-                natoms, step, time, prec);
+        fprintf(stdout, "natoms=%10d  step=%10" PRId64 "  time=%12.7e  prec=%10g\n", natoms, step, time, prec);
         pr_rvecs(stdout, indent, "box", box, DIM);
         pr_rvecs(stdout, indent, "x", x, natoms);
         nframe++;
-    }
-    while (read_next_xtc(xd, natoms, &step, &time, box, x, &prec, &bOK) != 0);
+    } while (read_next_xtc(xd, natoms, &step, &time, box, x, &prec, &bOK) != 0);
     if (!bOK)
     {
         fprintf(stderr, "\nWARNING: Incomplete frame at time %g\n", time);
@@ -336,19 +332,19 @@ void list_xtc(const char *fn)
 #if GMX_USE_TNG
 
 /*! \brief Callback used by list_tng_for_gmx_dump. */
-void list_tng_inner(const char *fn,
+void list_tng_inner(const charfn,
                     gmx_bool    bFirstFrame,
-                    real       *values,
+                    real*       values,
                     int64_t     step,
                     double      frame_time,
                     int64_t     n_values_per_frame,
                     int64_t     n_atoms,
                     real        prec,
                     int64_t     nframe,
-                    char       *block_name)
+                    char*       block_name)
 {
-    char                 buf[256];
-    int                  indent = 0;
+    char buf[256];
+    int  indent = 0;
 
     if (bFirstFrame)
     {
@@ -356,8 +352,7 @@ void list_tng_inner(const char *fn,
         indent = 0;
         indent = pr_title(stdout, indent, buf);
         pr_indent(stdout, indent);
-        fprintf(stdout, "natoms=%10" PRId64 "  step=%10" PRId64 "  time=%12.7e",
-                n_atoms, step, frame_time);
+        fprintf(stdout, "natoms=%10" PRId64 "  step=%10" PRId64 "  time=%12.7e", n_atoms, step, frame_time);
         if (prec > 0)
         {
             fprintf(stdout, "  prec=%10g", prec);
@@ -370,37 +365,39 @@ void list_tng_inner(const char *fn,
 #endif
 
 //! Dump a TNG file
-void list_tng(const char *fn)
+void list_tng(const charfn)
 {
 #if GMX_USE_TNG
     gmx_tng_trajectory_t tng;
     int64_t              nframe = 0;
     int64_t              i, *block_ids = nullptr, step, ndatablocks;
     gmx_bool             bOK;
-    real                *values = nullptr;
+    real*                values = nullptr;
 
     gmx_tng_open(fn, 'r', &tng);
     gmx_print_tng_molecule_system(tng, stdout);
 
-    bOK    = gmx_get_tng_data_block_types_of_next_frame(tng, -1,
-                                                        0,
-                                                        nullptr,
-                                                        &step, &ndatablocks,
-                                                        &block_ids);
+    bOK = gmx_get_tng_data_block_types_of_next_frame(tng, -1, 0, nullptr, &step, &ndatablocks, &block_ids);
     do
     {
         for (i = 0; i < ndatablocks; i++)
         {
-            double               frame_time;
-            real                 prec;
-            int64_t              n_values_per_frame, n_atoms;
-            char                 block_name[STRLEN];
-
-            gmx_get_tng_data_next_frame_of_block_type(tng, block_ids[i], &values,
-                                                      &step, &frame_time,
-                                                      &n_values_per_frame, &n_atoms,
+            double  frame_time;
+            real    prec;
+            int64_t n_values_per_frame, n_atoms;
+            char    block_name[STRLEN];
+
+            gmx_get_tng_data_next_frame_of_block_type(tng,
+                                                      block_ids[i],
+                                                      &values,
+                                                      &step,
+                                                      &frame_time,
+                                                      &n_values_per_frame,
+                                                      &n_atoms,
                                                       &prec,
-                                                      block_name, STRLEN, &bOK);
+                                                      block_name,
+                                                      STRLEN,
+                                                      &bOK);
             if (!bOK)
             {
                 /* Can't write any output because we don't know what
@@ -409,18 +406,13 @@ void list_tng(const char *fn)
             }
             else
             {
-                list_tng_inner(fn, (0 == i), values, step, frame_time,
-                               n_values_per_frame, n_atoms, prec, nframe, block_name);
+                list_tng_inner(
+                        fn, (0 == i), values, step, frame_time, n_values_per_frame, n_atoms, prec, nframe, block_name);
             }
         }
         nframe++;
-    }
-    while (gmx_get_tng_data_block_types_of_next_frame(tng, step,
-                                                      0,
-                                                      nullptr,
-                                                      &step,
-                                                      &ndatablocks,
-                                                      &block_ids));
+    } while (gmx_get_tng_data_block_types_of_next_frame(
+            tng, step, 0, nullptr, &step, &ndatablocks, &block_ids));
 
     if (block_ids)
     {
@@ -434,34 +426,27 @@ void list_tng(const char *fn)
 }
 
 //! Dump a trajectory file
-void list_trx(const char *fn)
+void list_trx(const charfn)
 {
     switch (fn2ftp(fn))
     {
-        case efXTC:
-            list_xtc(fn);
-            break;
-        case efTRR:
-            list_trr(fn);
-            break;
-        case efTNG:
-            list_tng(fn);
-            break;
+        case efXTC: list_xtc(fn); break;
+        case efTRR: list_trr(fn); break;
+        case efTNG: list_tng(fn); break;
         default:
-            fprintf(stderr, "File %s is of an unsupported type. Try using the command\n 'less %s'\n",
-                    fn, fn);
+            fprintf(stderr, "File %s is of an unsupported type. Try using the command\n 'less %s'\n", fn, fn);
     }
 }
 
 //! Dump an energy file
-void list_ene(const char *fn)
+void list_ene(const charfn)
 {
-    ener_file_t    in;
-    gmx_bool       bCont;
-    gmx_enxnm_t   *enm = nullptr;
-    t_enxframe    *fr;
-    int            i, j, nre, b;
-    char           buf[22];
+    ener_file_t  in;
+    gmx_bool     bCont;
+    gmx_enxnm_tenm = nullptr;
+    t_enxframe*  fr;
+    int          i, j, nre, b;
+    char         buf[22];
 
     printf("gmx dump: %s\n", fn);
     in = open_enx(fn, "r");
@@ -481,22 +466,24 @@ void list_ene(const char *fn)
 
         if (bCont)
         {
-            printf("\n%24s  %12.5e  %12s  %12s\n", "time:",
-                   fr->t, "step:", gmx_step_str(fr->step, buf));
-            printf("%24s  %12s  %12s  %12s\n",
-                   "", "", "nsteps:", gmx_step_str(fr->nsteps, buf));
-            printf("%24s  %12.5e  %12s  %12s\n",
-                   "delta_t:", fr->dt, "sum steps:", gmx_step_str(fr->nsum, buf));
+            printf("\n%24s  %12.5e  %12s  %12s\n", "time:", fr->t, "step:", gmx_step_str(fr->step, buf));
+            printf("%24s  %12s  %12s  %12s\n", "", "", "nsteps:", gmx_step_str(fr->nsteps, buf));
+            printf("%24s  %12.5e  %12s  %12s\n", "delta_t:", fr->dt, "sum steps:", gmx_step_str(fr->nsum, buf));
             if (fr->nre == nre)
             {
                 printf("%24s  %12s  %12s  %12s\n",
-                       "Component", "Energy", "Av. Energy", "Sum Energy");
+                       "Component",
+                       "Energy",
+                       "Av. Energy",
+                       "Sum Energy");
                 if (fr->nsum > 0)
                 {
                     for (i = 0; (i < nre); i++)
                     {
                         printf("%24s  %12.5e  %12.5e  %12.5e\n",
-                               enm[i].name, fr->ener[i].e, fr->ener[i].eav,
+                               enm[i].name,
+                               fr->ener[i].e,
+                               fr->ener[i].eav,
                                fr->ener[i].esum);
                     }
                 }
@@ -504,18 +491,16 @@ void list_ene(const char *fn)
                 {
                     for (i = 0; (i < nre); i++)
                     {
-                        printf("%24s  %12.5e\n",
-                               enm[i].name, fr->ener[i].e);
+                        printf("%24s  %12.5e\n", enm[i].name, fr->ener[i].e);
                     }
                 }
             }
             for (b = 0; b < fr->nblock; b++)
             {
-                const char *typestr = "";
+                const chartypestr = "";
 
-                t_enxblock *eb = &(fr->block[b]);
-                printf("Block data %2d (%3d subblocks, id=%d)\n",
-                       b, eb->nsub, eb->id);
+                t_enxblock* eb = &(fr->block[b]);
+                printf("Block data %2d (%3d subblocks, id=%d)\n", b, eb->nsub, eb->id);
 
                 if (eb->id < enxNR)
                 {
@@ -524,57 +509,56 @@ void list_ene(const char *fn)
                 printf("  id='%s'\n", typestr);
                 for (i = 0; i < eb->nsub; i++)
                 {
-                    t_enxsubblock *sb = &(eb->sub[i]);
+                    t_enxsubblocksb = &(eb->sub[i]);
                     printf("  Sub block %3d (%5d elems, type=%s) values:\n",
-                           i, sb->nr, xdr_datatype_names[sb->type]);
+                           i,
+                           sb->nr,
+                           enumValueToString(sb->type));
 
                     switch (sb->type)
                     {
-                        case xdr_datatype_float:
+                        case XdrDataType::Float:
                             for (j = 0; j < sb->nr; j++)
                             {
                                 printf("%14d   %8.4f\n", j, sb->fval[j]);
                             }
                             break;
-                        case xdr_datatype_double:
+                        case XdrDataType::Double:
                             for (j = 0; j < sb->nr; j++)
                             {
                                 printf("%14d   %10.6f\n", j, sb->dval[j]);
                             }
                             break;
-                        case xdr_datatype_int:
+                        case XdrDataType::Int:
                             for (j = 0; j < sb->nr; j++)
                             {
                                 printf("%14d %10d\n", j, sb->ival[j]);
                             }
                             break;
-                        case xdr_datatype_int64:
+                        case XdrDataType::Int64:
                             for (j = 0; j < sb->nr; j++)
                             {
-                                printf("%14d %s\n",
-                                       j, gmx_step_str(sb->lval[j], buf));
+                                printf("%14d %s\n", j, gmx_step_str(sb->lval[j], buf));
                             }
                             break;
-                        case xdr_datatype_char:
+                        case XdrDataType::Char:
                             for (j = 0; j < sb->nr; j++)
                             {
                                 printf("%14d %1c\n", j, sb->cval[j]);
                             }
                             break;
-                        case xdr_datatype_string:
+                        case XdrDataType::String:
                             for (j = 0; j < sb->nr; j++)
                             {
                                 printf("%14d %80s\n", j, sb->sval[j]);
                             }
                             break;
-                        default:
-                            gmx_incons("Unknown subblock type");
+                        default: gmx_incons("Unknown subblock type");
                     }
                 }
             }
         }
-    }
-    while (bCont);
+    } while (bCont);
 
     close_enx(in);
 
@@ -584,18 +568,18 @@ void list_ene(const char *fn)
 }
 
 //! Dump a (Hessian) matrix file
-void list_mtx(const char *fn)
+void list_mtx(const charfn)
 {
-    int                  nrow, ncol, i, j, k;
-    real                *full   = nullptr, value;
-    gmx_sparsematrix_t * sparse = nullptr;
+    int                 nrow, ncol, i, j, k;
+    real *              full   = nullptr, value;
+    gmx_sparsematrix_t* sparse = nullptr;
 
     gmx_mtxio_read(fn, &nrow, &ncol, &full, &sparse);
 
     if (full == nullptr)
     {
-        snew(full, nrow*ncol);
-        for (i = 0; i < nrow*ncol; i++)
+        snew(full, nrow * ncol);
+        for (i = 0; i < nrow * ncol; i++)
         {
             full[i] = 0;
         }
@@ -604,10 +588,10 @@ void list_mtx(const char *fn)
         {
             for (j = 0; j < sparse->ndata[i]; j++)
             {
-                k              = sparse->data[i][j].col;
-                value          = sparse->data[i][j].value;
-                full[i*ncol+k] = value;
-                full[k*ncol+i] = value;
+                k                  = sparse->data[i][j].col;
+                value              = sparse->data[i][j].value;
+                full[i * ncol + k] = value;
+                full[k * ncol + i] = value;
             }
         }
         gmx_sparsematrix_destroy(sparse);
@@ -618,7 +602,7 @@ void list_mtx(const char *fn)
     {
         for (j = 0; j < ncol; j++)
         {
-            printf(" %g", full[i*ncol+j]);
+            printf(" %g", full[i * ncol + j]);
         }
         printf("\n");
     }
@@ -628,100 +612,92 @@ void list_mtx(const char *fn)
 
 class Dump : public ICommandLineOptionsModule
 {
-    public:
-        Dump()
-        {}
-
-        // From ICommandLineOptionsModule
-        void init(CommandLineModuleSettings * /*settings*/) override
-        {
-        }
-
-        void initOptions(IOptionsContainer                 *options,
-                         ICommandLineOptionsModuleSettings *settings) override;
-
-        void optionsFinished() override;
-
-        int run() override;
-
-    private:
-        //! Commandline options
-        //! \{
-        bool bShowNumbers_      = true;
-        bool bShowParams_       = false;
-        bool bSysTop_           = false;
-        bool bOriginalInputrec_ = false;
-        //! \}
-        //! Commandline file options
-        //! \{
-        std::string inputTprFilename_;
-        std::string inputTrajectoryFilename_;
-        std::string inputEnergyFilename_;
-        std::string inputCheckpointFilename_;
-        std::string inputTopologyFilename_;
-        std::string inputMatrixFilename_;
-        std::string outputMdpFilename_;
-        //! \}
+public:
+    Dump() {}
+
+    // From ICommandLineOptionsModule
+    void init(CommandLineModuleSettings* /*settings*/) override {}
+
+    void initOptions(IOptionsContainer* options, ICommandLineOptionsModuleSettings* settings) override;
+
+    void optionsFinished() override;
+
+    int run() override;
+
+private:
+    //! Commandline options
+    //! \{
+    bool bShowNumbers_      = true;
+    bool bShowParams_       = false;
+    bool bSysTop_           = false;
+    bool bOriginalInputrec_ = false;
+    //! \}
+    //! Commandline file options
+    //! \{
+    std::string inputTprFilename_;
+    std::string inputTrajectoryFilename_;
+    std::string inputEnergyFilename_;
+    std::string inputCheckpointFilename_;
+    std::string inputTopologyFilename_;
+    std::string inputMatrixFilename_;
+    std::string outputMdpFilename_;
+    //! \}
 };
 
-void Dump::initOptions(IOptionsContainer                 *options,
-                       ICommandLineOptionsModuleSettings *settings)
+void Dump::initOptions(IOptionsContainer* options, ICommandLineOptionsModuleSettings* settings)
 {
-    const char *desc[] = {
-        "[THISMODULE] reads a run input file ([REF].tpr[ref]),",
-        "a trajectory ([REF].trr[ref]/[REF].xtc[ref]/[TT]tng[tt]), an energy",
-        "file ([REF].edr[ref]), a checkpoint file ([REF].cpt[ref])",
-        "or topology file ([REF].top[ref])",
-        "and prints that to standard output in a readable format.",
-        "This program is essential for checking your run input file in case of",
-        "problems."
-    };
+    const char* desc[] = { "[THISMODULE] reads a run input file ([REF].tpr[ref]),",
+                           "a trajectory ([REF].trr[ref]/[REF].xtc[ref]/[TT]tng[tt]), an energy",
+                           "file ([REF].edr[ref]), a checkpoint file ([REF].cpt[ref])",
+                           "or topology file ([REF].top[ref])",
+                           "and prints that to standard output in a readable format.",
+                           "This program is essential for checking your run input file in case of",
+                           "problems." };
     settings->setHelpText(desc);
+
+    const char* bugs[] = {
+        "The [REF].mdp[ref] file produced by [TT]-om[tt] can not be read by grompp."
+    };
+    settings->setBugText(bugs);
     // TODO If this ancient note acknowledging a bug is still true,
     // fix it or block that run path:
     //   Position restraint output from -sys -s is broken
 
     options->addOption(FileNameOption("s")
-                           .filetype(eftRunInput).inputFile()
-                           .store(&inputTprFilename_)
-                           .description("Run input file to dump"));
+                               .filetype(OptionFileType::RunInput)
+                               .inputFile()
+                               .store(&inputTprFilename_)
+                               .description("Run input file to dump"));
     options->addOption(FileNameOption("f")
-                           .filetype(eftTrajectory).inputFile()
-                           .store(&inputTrajectoryFilename_)
-                           .description("Trajectory file to dump"));
+                               .filetype(OptionFileType::Trajectory)
+                               .inputFile()
+                               .store(&inputTrajectoryFilename_)
+                               .description("Trajectory file to dump"));
     options->addOption(FileNameOption("e")
-                           .filetype(eftEnergy).inputFile()
-                           .store(&inputEnergyFilename_)
-                           .description("Energy file to dump"));
-    options->addOption(FileNameOption("cp")
-                           .legacyType(efCPT).inputFile()
-                           .store(&inputCheckpointFilename_)
-                           .description("Checkpoint file to dump"));
-    options->addOption(FileNameOption("p")
-                           .legacyType(efTOP).inputFile()
-                           .store(&inputTopologyFilename_)
-                           .description("Topology file to dump"));
-    options->addOption(FileNameOption("mtx")
-                           .legacyType(efMTX).inputFile()
-                           .store(&inputMatrixFilename_)
-                           .description("Hessian matrix to dump"));
+                               .filetype(OptionFileType::Energy)
+                               .inputFile()
+                               .store(&inputEnergyFilename_)
+                               .description("Energy file to dump"));
+    options->addOption(
+            FileNameOption("cp").legacyType(efCPT).inputFile().store(&inputCheckpointFilename_).description("Checkpoint file to dump"));
+    options->addOption(
+            FileNameOption("p").legacyType(efTOP).inputFile().store(&inputTopologyFilename_).description("Topology file to dump"));
+    options->addOption(
+            FileNameOption("mtx").legacyType(efMTX).inputFile().store(&inputMatrixFilename_).description("Hessian matrix to dump"));
     options->addOption(FileNameOption("om")
-                           .legacyType(efMDP).outputFile()
-                           .store(&outputMdpFilename_)
-                           .description("grompp input file from run input file"));
-
-    options->addOption(BooleanOption("nr")
-                           .store(&bShowNumbers_).defaultValue(true)
-                           .description("Show index numbers in output (leaving them out makes comparison easier, but creates a useless topology)"));
-    options->addOption(BooleanOption("param")
-                           .store(&bShowParams_).defaultValue(false)
-                           .description("Show parameters for each bonded interaction (for comparing dumps, it is useful to combine this with -nonr)"));
-    options->addOption(BooleanOption("sys")
-                           .store(&bShowParams_).defaultValue(false)
-                           .description("List the atoms and bonded interactions for the whole system instead of for each molecule type"));
-    options->addOption(BooleanOption("orgir")
-                           .store(&bShowParams_).defaultValue(false)
-                           .description("Show input parameters from tpr as they were written by the version that produced the file, instead of how the current version reads them"));
+                               .legacyType(efMDP)
+                               .outputFile()
+                               .store(&outputMdpFilename_)
+                               .description("grompp input file from run input file"));
+
+    options->addOption(
+            BooleanOption("nr").store(&bShowNumbers_).defaultValue(true).description("Show index numbers in output (leaving them out makes comparison easier, but creates a useless topology)"));
+    options->addOption(
+            BooleanOption("param").store(&bShowParams_).defaultValue(false).description("Show parameters for each bonded interaction (for comparing dumps, it is useful to combine this with -nonr)"));
+    options->addOption(
+            BooleanOption("sys").store(&bShowParams_).defaultValue(false).description("List the atoms and bonded interactions for the whole system instead of for each molecule type"));
+    options->addOption(
+            BooleanOption("orgir").store(&bShowParams_).defaultValue(false).description("Show input parameters from tpr as they were written by the version that produced the file, instead of how the current version reads them"));
 }
 
 void Dump::optionsFinished()
@@ -735,8 +711,12 @@ int Dump::run()
 {
     if (!inputTprFilename_.empty())
     {
-        list_tpr(inputTprFilename_.c_str(), bShowNumbers_, bShowParams_,
-                 outputMdpFilename_.c_str(), bSysTop_, bOriginalInputrec_);
+        list_tpr(inputTprFilename_.c_str(),
+                 bShowNumbers_,
+                 bShowParams_,
+                 outputMdpFilename_.empty() ? nullptr : outputMdpFilename_.c_str(),
+                 bSysTop_,
+                 bOriginalInputrec_);
     }
     else if (!inputTrajectoryFilename_.empty())
     {
@@ -762,14 +742,13 @@ int Dump::run()
     return 0;
 }
 
-}   // namespace
+} // namespace
 
-const char DumpInfo::name[]             = "dump";
-const char DumpInfo::shortDescription[] =
-    "Make binary files human readable";
+const char                       DumpInfo::name[]             = "dump";
+const char                       DumpInfo::shortDescription[] = "Make binary files human readable";
 ICommandLineOptionsModulePointer DumpInfo::create()
 {
     return std::make_unique<Dump>();
 }
 
-}   // namespace gmx
+} // namespace gmx