Start making IMD and swap model IMDModule
[alexxy/gromacs.git] / src / gromacs / tools / dump.cpp
1 /*
2  * This file is part of the GROMACS molecular simulation package.
3  *
4  * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
5  * Copyright (c) 2001-2013, The GROMACS development team.
6  * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
7  * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
8  * and including many others, as listed in the AUTHORS file in the
9  * top-level source directory and at http://www.gromacs.org.
10  *
11  * GROMACS is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU Lesser General Public License
13  * as published by the Free Software Foundation; either version 2.1
14  * of the License, or (at your option) any later version.
15  *
16  * GROMACS is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
19  * Lesser General Public License for more details.
20  *
21  * You should have received a copy of the GNU Lesser General Public
22  * License along with GROMACS; if not, see
23  * http://www.gnu.org/licenses, or write to the Free Software Foundation,
24  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA.
25  *
26  * If you want to redistribute modifications to GROMACS, please
27  * consider that scientific software is very special. Version
28  * control is crucial - bugs must be traceable. We will be happy to
29  * consider code for inclusion in the official distribution, but
30  * derived work must not be called official GROMACS. Details are found
31  * in the README & COPYING files - if they are missing, get the
32  * official version at http://www.gromacs.org.
33  *
34  * To help us fund GROMACS development, we humbly ask that you cite
35  * the research papers on the package. Check out http://www.gromacs.org.
36  */
37 /*! \internal \file
38  * \brief Implements gmx dump utility.
39  *
40  * \ingroup module_tools
41  */
42 #include "gmxpre.h"
43
44 #include "dump.h"
45
46 #include "config.h"
47
48 #include <cassert>
49 #include <cmath>
50 #include <cstdio>
51 #include <cstring>
52
53 #include "gromacs/commandline/cmdlineoptionsmodule.h"
54 #include "gromacs/fileio/checkpoint.h"
55 #include "gromacs/fileio/enxio.h"
56 #include "gromacs/fileio/filetypes.h"
57 #include "gromacs/fileio/gmxfio.h"
58 #include "gromacs/fileio/mtxio.h"
59 #include "gromacs/fileio/tngio.h"
60 #include "gromacs/fileio/tpxio.h"
61 #include "gromacs/fileio/trrio.h"
62 #include "gromacs/fileio/xtcio.h"
63 #include "gromacs/gmxpreprocess/gmxcpp.h"
64 #include "gromacs/math/vecdump.h"
65 #include "gromacs/mdrun/mdmodules.h"
66 #include "gromacs/mdtypes/forcerec.h"
67 #include "gromacs/mdtypes/inputrec.h"
68 #include "gromacs/mdtypes/md_enums.h"
69 #include "gromacs/mdtypes/state.h"
70 #include "gromacs/options/basicoptions.h"
71 #include "gromacs/options/filenameoption.h"
72 #include "gromacs/options/ioptionscontainer.h"
73 #include "gromacs/topology/mtop_util.h"
74 #include "gromacs/topology/topology.h"
75 #include "gromacs/trajectory/energyframe.h"
76 #include "gromacs/trajectory/trajectoryframe.h"
77 #include "gromacs/utility/arraysize.h"
78 #include "gromacs/utility/basedefinitions.h"
79 #include "gromacs/utility/fatalerror.h"
80 #include "gromacs/utility/futil.h"
81 #include "gromacs/utility/smalloc.h"
82 #include "gromacs/utility/txtdump.h"
83
84 namespace gmx
85 {
86
87 namespace
88 {
89
90 //! Dump a TPR file
91 void list_tpr(const char *fn,
92               gmx_bool    bShowNumbers,
93               gmx_bool    bShowParameters,
94               const char *mdpfn,
95               gmx_bool    bSysTop,
96               gmx_bool    bOriginalInputrec)
97 {
98     FILE         *gp;
99     int           indent, atot;
100     t_state       state;
101     t_tpxheader   tpx;
102     gmx_mtop_t    mtop;
103     t_topology    top;
104
105     read_tpxheader(fn, &tpx, TRUE);
106     t_inputrec     ir;
107     read_tpx_state(fn,
108                    tpx.bIr ? &ir : nullptr,
109                    &state,
110                    tpx.bTop ? &mtop : nullptr);
111     if (tpx.bIr && !bOriginalInputrec)
112     {
113         MDModules().adjustInputrecBasedOnModules(&ir);
114     }
115
116     if (mdpfn && tpx.bIr)
117     {
118         gp = gmx_fio_fopen(mdpfn, "w");
119         pr_inputrec(gp, 0, nullptr, &ir, TRUE);
120         gmx_fio_fclose(gp);
121     }
122
123     if (!mdpfn)
124     {
125         if (bSysTop)
126         {
127             top = gmx_mtop_t_to_t_topology(&mtop, false);
128         }
129
130         if (available(stdout, &tpx, 0, fn))
131         {
132             indent = 0;
133             pr_title(stdout, indent, fn);
134             pr_inputrec(stdout, 0, "inputrec", tpx.bIr ? &ir : nullptr, FALSE);
135
136             pr_tpxheader(stdout, indent, "header", &(tpx));
137
138             if (!bSysTop)
139             {
140                 pr_mtop(stdout, indent, "topology", &(mtop), bShowNumbers, bShowParameters);
141             }
142             else
143             {
144                 pr_top(stdout, indent, "topology", &(top), bShowNumbers, bShowParameters);
145             }
146
147             pr_rvecs(stdout, indent, "box", tpx.bBox ? state.box : nullptr, DIM);
148             pr_rvecs(stdout, indent, "box_rel", tpx.bBox ? state.box_rel : nullptr, DIM);
149             pr_rvecs(stdout, indent, "boxv", tpx.bBox ? state.boxv : nullptr, DIM);
150             pr_rvecs(stdout, indent, "pres_prev", tpx.bBox ? state.pres_prev : nullptr, DIM);
151             pr_rvecs(stdout, indent, "svir_prev", tpx.bBox ? state.svir_prev : nullptr, DIM);
152             pr_rvecs(stdout, indent, "fvir_prev", tpx.bBox ? state.fvir_prev : nullptr, DIM);
153             /* leave nosehoover_xi in for now to match the tpr version */
154             pr_doubles(stdout, indent, "nosehoover_xi", state.nosehoover_xi.data(), state.ngtc);
155             /*pr_doubles(stdout,indent,"nosehoover_vxi",state.nosehoover_vxi,state.ngtc);*/
156             /*pr_doubles(stdout,indent,"therm_integral",state.therm_integral,state.ngtc);*/
157             pr_rvecs(stdout, indent, "x", tpx.bX ? state.x.rvec_array() : nullptr, state.natoms);
158             pr_rvecs(stdout, indent, "v", tpx.bV ? state.v.rvec_array() : nullptr, state.natoms);
159         }
160
161         const SimulationGroups &groups = mtop.groups;
162
163         gmx::EnumerationArray < SimulationAtomGroupType, std::vector < int>> gcount;
164         for (auto group : keysOf(gcount))
165         {
166             gcount[group].resize(groups.groups[group].nr);
167         }
168
169         for (int i = 0; (i < mtop.natoms); i++)
170         {
171             for (auto group : keysOf(gcount))
172             {
173                 gcount[group][getGroupType(groups, group, i)]++;
174             }
175         }
176         printf("Group statistics\n");
177         for (auto group : keysOf(gcount))
178         {
179             atot = 0;
180             printf("%-12s: ", shortName(group));
181             for (int j = 0; (j < groups.groups[group].nr); j++)
182             {
183                 printf("  %5d", gcount[group][j]);
184                 atot += gcount[group][j];
185             }
186             printf("  (total %d atoms)\n", atot);
187         }
188     }
189 }
190
191 //! Dump a topology file
192 void list_top(const char *fn)
193 {
194     int       status, done;
195     // Legacy string length macro
196     char      buf[STRLEN];
197     gmx_cpp_t handle;
198     char     *cppopts[] = { nullptr };
199
200     status = cpp_open_file(fn, &handle, cppopts);
201     if (status != 0)
202     {
203         gmx_fatal(FARGS, "%s", cpp_error(&handle, status));
204     }
205     do
206     {
207         status = cpp_read_line(&handle, STRLEN, buf);
208         done   = static_cast<int>(status == eCPP_EOF);
209         if (!done)
210         {
211             if (status != eCPP_OK)
212             {
213                 gmx_fatal(FARGS, "%s", cpp_error(&handle, status));
214             }
215             else
216             {
217                 printf("%s\n", buf);
218             }
219         }
220     }
221     while (done == 0);
222     status = cpp_close_file(&handle);
223     if (status != eCPP_OK)
224     {
225         gmx_fatal(FARGS, "%s", cpp_error(&handle, status));
226     }
227 }
228
229 //! Dump a TRR file
230 void list_trr(const char *fn)
231 {
232     t_fileio         *fpread;
233     int               nframe, indent;
234     char              buf[256];
235     rvec             *x, *v, *f;
236     matrix            box;
237     gmx_trr_header_t  trrheader;
238     gmx_bool          bOK;
239
240     fpread  = gmx_trr_open(fn, "r");
241
242     nframe = 0;
243     while (gmx_trr_read_frame_header(fpread, &trrheader, &bOK))
244     {
245         snew(x, trrheader.natoms);
246         snew(v, trrheader.natoms);
247         snew(f, trrheader.natoms);
248         if (gmx_trr_read_frame_data(fpread, &trrheader,
249                                     trrheader.box_size ? box : nullptr,
250                                     trrheader.x_size   ? x : nullptr,
251                                     trrheader.v_size   ? v : nullptr,
252                                     trrheader.f_size   ? f : nullptr))
253         {
254             sprintf(buf, "%s frame %d", fn, nframe);
255             indent = 0;
256             indent = pr_title(stdout, indent, buf);
257             pr_indent(stdout, indent);
258             fprintf(stdout, "natoms=%10d  step=%10" PRId64 "  time=%12.7e  lambda=%10g\n",
259                     trrheader.natoms, trrheader.step, trrheader.t, trrheader.lambda);
260             if (trrheader.box_size)
261             {
262                 pr_rvecs(stdout, indent, "box", box, DIM);
263             }
264             if (trrheader.x_size)
265             {
266                 pr_rvecs(stdout, indent, "x", x, trrheader.natoms);
267             }
268             if (trrheader.v_size)
269             {
270                 pr_rvecs(stdout, indent, "v", v, trrheader.natoms);
271             }
272             if (trrheader.f_size)
273             {
274                 pr_rvecs(stdout, indent, "f", f, trrheader.natoms);
275             }
276         }
277         else
278         {
279             fprintf(stderr, "\nWARNING: Incomplete frame: nr %d, t=%g\n",
280                     nframe, trrheader.t);
281         }
282
283         sfree(x);
284         sfree(v);
285         sfree(f);
286         nframe++;
287     }
288     if (!bOK)
289     {
290         fprintf(stderr, "\nWARNING: Incomplete frame header: nr %d, t=%g\n",
291                 nframe, trrheader.t);
292     }
293     gmx_trr_close(fpread);
294 }
295
296 //! Dump an xtc file
297 void list_xtc(const char *fn)
298 {
299     t_fileio   *xd;
300     int         indent;
301     char        buf[256];
302     rvec       *x;
303     matrix      box;
304     int         nframe, natoms;
305     int64_t     step;
306     real        prec, time;
307     gmx_bool    bOK;
308
309     xd = open_xtc(fn, "r");
310     read_first_xtc(xd, &natoms, &step, &time, box, &x, &prec, &bOK);
311
312     nframe = 0;
313     do
314     {
315         sprintf(buf, "%s frame %d", fn, nframe);
316         indent = 0;
317         indent = pr_title(stdout, indent, buf);
318         pr_indent(stdout, indent);
319         fprintf(stdout, "natoms=%10d  step=%10" PRId64 "  time=%12.7e  prec=%10g\n",
320                 natoms, step, time, prec);
321         pr_rvecs(stdout, indent, "box", box, DIM);
322         pr_rvecs(stdout, indent, "x", x, natoms);
323         nframe++;
324     }
325     while (read_next_xtc(xd, natoms, &step, &time, box, x, &prec, &bOK) != 0);
326     if (!bOK)
327     {
328         fprintf(stderr, "\nWARNING: Incomplete frame at time %g\n", time);
329     }
330     sfree(x);
331     close_xtc(xd);
332 }
333
334 #if GMX_USE_TNG
335
336 /*! \brief Callback used by list_tng_for_gmx_dump. */
337 void list_tng_inner(const char *fn,
338                     gmx_bool    bFirstFrame,
339                     real       *values,
340                     int64_t     step,
341                     double      frame_time,
342                     int64_t     n_values_per_frame,
343                     int64_t     n_atoms,
344                     real        prec,
345                     int64_t     nframe,
346                     char       *block_name)
347 {
348     char                 buf[256];
349     int                  indent = 0;
350
351     if (bFirstFrame)
352     {
353         sprintf(buf, "%s frame %" PRId64, fn, nframe);
354         indent = 0;
355         indent = pr_title(stdout, indent, buf);
356         pr_indent(stdout, indent);
357         fprintf(stdout, "natoms=%10" PRId64 "  step=%10" PRId64 "  time=%12.7e",
358                 n_atoms, step, frame_time);
359         if (prec > 0)
360         {
361             fprintf(stdout, "  prec=%10g", prec);
362         }
363         fprintf(stdout, "\n");
364     }
365     pr_reals_of_dim(stdout, indent, block_name, values, n_atoms, n_values_per_frame);
366 }
367
368 #endif
369
370 //! Dump a TNG file
371 void list_tng(const char *fn)
372 {
373 #if GMX_USE_TNG
374     gmx_tng_trajectory_t tng;
375     int64_t              nframe = 0;
376     int64_t              i, *block_ids = nullptr, step, ndatablocks;
377     gmx_bool             bOK;
378     real                *values = nullptr;
379
380     gmx_tng_open(fn, 'r', &tng);
381     gmx_print_tng_molecule_system(tng, stdout);
382
383     bOK    = gmx_get_tng_data_block_types_of_next_frame(tng, -1,
384                                                         0,
385                                                         nullptr,
386                                                         &step, &ndatablocks,
387                                                         &block_ids);
388     do
389     {
390         for (i = 0; i < ndatablocks; i++)
391         {
392             double               frame_time;
393             real                 prec;
394             int64_t              n_values_per_frame, n_atoms;
395             char                 block_name[STRLEN];
396
397             gmx_get_tng_data_next_frame_of_block_type(tng, block_ids[i], &values,
398                                                       &step, &frame_time,
399                                                       &n_values_per_frame, &n_atoms,
400                                                       &prec,
401                                                       block_name, STRLEN, &bOK);
402             if (!bOK)
403             {
404                 /* Can't write any output because we don't know what
405                    arrays are valid. */
406                 fprintf(stderr, "\nWARNING: Incomplete frame at time %g, will not write output\n", frame_time);
407             }
408             else
409             {
410                 list_tng_inner(fn, (0 == i), values, step, frame_time,
411                                n_values_per_frame, n_atoms, prec, nframe, block_name);
412             }
413         }
414         nframe++;
415     }
416     while (gmx_get_tng_data_block_types_of_next_frame(tng, step,
417                                                       0,
418                                                       nullptr,
419                                                       &step,
420                                                       &ndatablocks,
421                                                       &block_ids));
422
423     if (block_ids)
424     {
425         sfree(block_ids);
426     }
427     sfree(values);
428     gmx_tng_close(&tng);
429 #else
430     GMX_UNUSED_VALUE(fn);
431 #endif
432 }
433
434 //! Dump a trajectory file
435 void list_trx(const char *fn)
436 {
437     switch (fn2ftp(fn))
438     {
439         case efXTC:
440             list_xtc(fn);
441             break;
442         case efTRR:
443             list_trr(fn);
444             break;
445         case efTNG:
446             list_tng(fn);
447             break;
448         default:
449             fprintf(stderr, "File %s is of an unsupported type. Try using the command\n 'less %s'\n",
450                     fn, fn);
451     }
452 }
453
454 //! Dump an energy file
455 void list_ene(const char *fn)
456 {
457     ener_file_t    in;
458     gmx_bool       bCont;
459     gmx_enxnm_t   *enm = nullptr;
460     t_enxframe    *fr;
461     int            i, j, nre, b;
462     char           buf[22];
463
464     printf("gmx dump: %s\n", fn);
465     in = open_enx(fn, "r");
466     do_enxnms(in, &nre, &enm);
467     assert(enm);
468
469     printf("energy components:\n");
470     for (i = 0; (i < nre); i++)
471     {
472         printf("%5d  %-24s (%s)\n", i, enm[i].name, enm[i].unit);
473     }
474
475     snew(fr, 1);
476     do
477     {
478         bCont = do_enx(in, fr);
479
480         if (bCont)
481         {
482             printf("\n%24s  %12.5e  %12s  %12s\n", "time:",
483                    fr->t, "step:", gmx_step_str(fr->step, buf));
484             printf("%24s  %12s  %12s  %12s\n",
485                    "", "", "nsteps:", gmx_step_str(fr->nsteps, buf));
486             printf("%24s  %12.5e  %12s  %12s\n",
487                    "delta_t:", fr->dt, "sum steps:", gmx_step_str(fr->nsum, buf));
488             if (fr->nre == nre)
489             {
490                 printf("%24s  %12s  %12s  %12s\n",
491                        "Component", "Energy", "Av. Energy", "Sum Energy");
492                 if (fr->nsum > 0)
493                 {
494                     for (i = 0; (i < nre); i++)
495                     {
496                         printf("%24s  %12.5e  %12.5e  %12.5e\n",
497                                enm[i].name, fr->ener[i].e, fr->ener[i].eav,
498                                fr->ener[i].esum);
499                     }
500                 }
501                 else
502                 {
503                     for (i = 0; (i < nre); i++)
504                     {
505                         printf("%24s  %12.5e\n",
506                                enm[i].name, fr->ener[i].e);
507                     }
508                 }
509             }
510             for (b = 0; b < fr->nblock; b++)
511             {
512                 const char *typestr = "";
513
514                 t_enxblock *eb = &(fr->block[b]);
515                 printf("Block data %2d (%3d subblocks, id=%d)\n",
516                        b, eb->nsub, eb->id);
517
518                 if (eb->id < enxNR)
519                 {
520                     typestr = enx_block_id_name[eb->id];
521                 }
522                 printf("  id='%s'\n", typestr);
523                 for (i = 0; i < eb->nsub; i++)
524                 {
525                     t_enxsubblock *sb = &(eb->sub[i]);
526                     printf("  Sub block %3d (%5d elems, type=%s) values:\n",
527                            i, sb->nr, xdr_datatype_names[sb->type]);
528
529                     switch (sb->type)
530                     {
531                         case xdr_datatype_float:
532                             for (j = 0; j < sb->nr; j++)
533                             {
534                                 printf("%14d   %8.4f\n", j, sb->fval[j]);
535                             }
536                             break;
537                         case xdr_datatype_double:
538                             for (j = 0; j < sb->nr; j++)
539                             {
540                                 printf("%14d   %10.6f\n", j, sb->dval[j]);
541                             }
542                             break;
543                         case xdr_datatype_int:
544                             for (j = 0; j < sb->nr; j++)
545                             {
546                                 printf("%14d %10d\n", j, sb->ival[j]);
547                             }
548                             break;
549                         case xdr_datatype_int64:
550                             for (j = 0; j < sb->nr; j++)
551                             {
552                                 printf("%14d %s\n",
553                                        j, gmx_step_str(sb->lval[j], buf));
554                             }
555                             break;
556                         case xdr_datatype_char:
557                             for (j = 0; j < sb->nr; j++)
558                             {
559                                 printf("%14d %1c\n", j, sb->cval[j]);
560                             }
561                             break;
562                         case xdr_datatype_string:
563                             for (j = 0; j < sb->nr; j++)
564                             {
565                                 printf("%14d %80s\n", j, sb->sval[j]);
566                             }
567                             break;
568                         default:
569                             gmx_incons("Unknown subblock type");
570                     }
571                 }
572             }
573         }
574     }
575     while (bCont);
576
577     close_enx(in);
578
579     free_enxframe(fr);
580     sfree(fr);
581     sfree(enm);
582 }
583
584 //! Dump a (Hessian) matrix file
585 void list_mtx(const char *fn)
586 {
587     int                  nrow, ncol, i, j, k;
588     real                *full   = nullptr, value;
589     gmx_sparsematrix_t * sparse = nullptr;
590
591     gmx_mtxio_read(fn, &nrow, &ncol, &full, &sparse);
592
593     if (full == nullptr)
594     {
595         snew(full, nrow*ncol);
596         for (i = 0; i < nrow*ncol; i++)
597         {
598             full[i] = 0;
599         }
600
601         for (i = 0; i < sparse->nrow; i++)
602         {
603             for (j = 0; j < sparse->ndata[i]; j++)
604             {
605                 k              = sparse->data[i][j].col;
606                 value          = sparse->data[i][j].value;
607                 full[i*ncol+k] = value;
608                 full[k*ncol+i] = value;
609             }
610         }
611         gmx_sparsematrix_destroy(sparse);
612     }
613
614     printf("%d %d\n", nrow, ncol);
615     for (i = 0; i < nrow; i++)
616     {
617         for (j = 0; j < ncol; j++)
618         {
619             printf(" %g", full[i*ncol+j]);
620         }
621         printf("\n");
622     }
623
624     sfree(full);
625 }
626
627 class Dump : public ICommandLineOptionsModule
628 {
629     public:
630         Dump()
631         {}
632
633         // From ICommandLineOptionsModule
634         void init(CommandLineModuleSettings * /*settings*/) override
635         {
636         }
637
638         void initOptions(IOptionsContainer                 *options,
639                          ICommandLineOptionsModuleSettings *settings) override;
640
641         void optionsFinished() override;
642
643         int run() override;
644
645     private:
646         //! Commandline options
647         //! \{
648         bool bShowNumbers_      = true;
649         bool bShowParams_       = false;
650         bool bSysTop_           = false;
651         bool bOriginalInputrec_ = false;
652         //! \}
653         //! Commandline file options
654         //! \{
655         std::string inputTprFilename_;
656         std::string inputTrajectoryFilename_;
657         std::string inputEnergyFilename_;
658         std::string inputCheckpointFilename_;
659         std::string inputTopologyFilename_;
660         std::string inputMatrixFilename_;
661         std::string outputMdpFilename_;
662         //! \}
663 };
664
665 void Dump::initOptions(IOptionsContainer                 *options,
666                        ICommandLineOptionsModuleSettings *settings)
667 {
668     const char *desc[] = {
669         "[THISMODULE] reads a run input file ([REF].tpr[ref]),",
670         "a trajectory ([REF].trr[ref]/[REF].xtc[ref]/[TT]tng[tt]), an energy",
671         "file ([REF].edr[ref]), a checkpoint file ([REF].cpt[ref])",
672         "or topology file ([REF].top[ref])",
673         "and prints that to standard output in a readable format.",
674         "This program is essential for checking your run input file in case of",
675         "problems."
676     };
677     settings->setHelpText(desc);
678     // TODO If this ancient note acknowledging a bug is still true,
679     // fix it or block that run path:
680     //   Position restraint output from -sys -s is broken
681
682     options->addOption(FileNameOption("s")
683                            .filetype(eftRunInput).inputFile()
684                            .store(&inputTprFilename_)
685                            .description("Run input file to dump"));
686     options->addOption(FileNameOption("f")
687                            .filetype(eftTrajectory).inputFile()
688                            .store(&inputTrajectoryFilename_)
689                            .description("Trajectory file to dump"));
690     options->addOption(FileNameOption("e")
691                            .filetype(eftEnergy).inputFile()
692                            .store(&inputEnergyFilename_)
693                            .description("Energy file to dump"));
694     options->addOption(FileNameOption("cp")
695                            .legacyType(efCPT).inputFile()
696                            .store(&inputCheckpointFilename_)
697                            .description("Checkpoint file to dump"));
698     options->addOption(FileNameOption("p")
699                            .legacyType(efTOP).inputFile()
700                            .store(&inputTopologyFilename_)
701                            .description("Topology file to dump"));
702     options->addOption(FileNameOption("mtx")
703                            .legacyType(efMTX).inputFile()
704                            .store(&inputMatrixFilename_)
705                            .description("Hessian matrix to dump"));
706     options->addOption(FileNameOption("om")
707                            .legacyType(efMDP).outputFile()
708                            .store(&outputMdpFilename_)
709                            .description("grompp input file from run input file"));
710
711     options->addOption(BooleanOption("nr")
712                            .store(&bShowNumbers_).defaultValue(true)
713                            .description("Show index numbers in output (leaving them out makes comparison easier, but creates a useless topology)"));
714     options->addOption(BooleanOption("param")
715                            .store(&bShowParams_).defaultValue(false)
716                            .description("Show parameters for each bonded interaction (for comparing dumps, it is useful to combine this with -nonr)"));
717     options->addOption(BooleanOption("sys")
718                            .store(&bShowParams_).defaultValue(false)
719                            .description("List the atoms and bonded interactions for the whole system instead of for each molecule type"));
720     options->addOption(BooleanOption("orgir")
721                            .store(&bShowParams_).defaultValue(false)
722                            .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"));
723 }
724
725 void Dump::optionsFinished()
726 {
727     // TODO Currently gmx dump ignores user input that seeks to dump
728     // multiple files. Here, we could enforce that the user only asks
729     // to dump one file.
730 }
731
732 int Dump::run()
733 {
734     if (!inputTprFilename_.empty())
735     {
736         list_tpr(inputTprFilename_.c_str(), bShowNumbers_, bShowParams_,
737                  outputMdpFilename_.c_str(), bSysTop_, bOriginalInputrec_);
738     }
739     else if (!inputTrajectoryFilename_.empty())
740     {
741         list_trx(inputTrajectoryFilename_.c_str());
742     }
743     else if (!inputEnergyFilename_.empty())
744     {
745         list_ene(inputEnergyFilename_.c_str());
746     }
747     else if (!inputCheckpointFilename_.empty())
748     {
749         list_checkpoint(inputCheckpointFilename_.c_str(), stdout);
750     }
751     else if (!inputTopologyFilename_.empty())
752     {
753         list_top(inputTopologyFilename_.c_str());
754     }
755     else if (!inputMatrixFilename_.empty())
756     {
757         list_mtx(inputMatrixFilename_.c_str());
758     }
759
760     return 0;
761 }
762
763 }   // namespace
764
765 const char DumpInfo::name[]             = "dump";
766 const char DumpInfo::shortDescription[] =
767     "Make binary files human readable";
768 ICommandLineOptionsModulePointer DumpInfo::create()
769 {
770     return std::make_unique<Dump>();
771 }
772
773 }   // namespace gmx