b116ff6d0549985c59836ab9a41fd4a4b45c77ea
[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/mdrunutility/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, i, j, **gcount, 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 gmx_groups_t &groups = mtop.groups;
162
163         snew(gcount, egcNR);
164         for (i = 0; (i < egcNR); i++)
165         {
166             snew(gcount[i], groups.grps[i].nr);
167         }
168
169         for (i = 0; (i < mtop.natoms); i++)
170         {
171             for (j = 0; (j < egcNR); j++)
172             {
173                 gcount[j][getGroupType(groups, j, i)]++;
174             }
175         }
176         printf("Group statistics\n");
177         for (i = 0; (i < egcNR); i++)
178         {
179             atot = 0;
180             printf("%-12s: ", gtypes[i]);
181             for (j = 0; (j < groups.grps[i].nr); j++)
182             {
183                 printf("  %5d", gcount[i][j]);
184                 atot += gcount[i][j];
185             }
186             printf("  (total %d atoms)\n", atot);
187             sfree(gcount[i]);
188         }
189         sfree(gcount);
190     }
191 }
192
193 //! Dump a topology file
194 void list_top(const char *fn)
195 {
196     int       status, done;
197     // Legacy string length macro
198     char      buf[STRLEN];
199     gmx_cpp_t handle;
200     char     *cppopts[] = { nullptr };
201
202     status = cpp_open_file(fn, &handle, cppopts);
203     if (status != 0)
204     {
205         gmx_fatal(FARGS, "%s", cpp_error(&handle, status));
206     }
207     do
208     {
209         status = cpp_read_line(&handle, STRLEN, buf);
210         done   = static_cast<int>(status == eCPP_EOF);
211         if (!done)
212         {
213             if (status != eCPP_OK)
214             {
215                 gmx_fatal(FARGS, "%s", cpp_error(&handle, status));
216             }
217             else
218             {
219                 printf("%s\n", buf);
220             }
221         }
222     }
223     while (done == 0);
224     status = cpp_close_file(&handle);
225     if (status != eCPP_OK)
226     {
227         gmx_fatal(FARGS, "%s", cpp_error(&handle, status));
228     }
229 }
230
231 //! Dump a TRR file
232 void list_trr(const char *fn)
233 {
234     t_fileio         *fpread;
235     int               nframe, indent;
236     char              buf[256];
237     rvec             *x, *v, *f;
238     matrix            box;
239     gmx_trr_header_t  trrheader;
240     gmx_bool          bOK;
241
242     fpread  = gmx_trr_open(fn, "r");
243
244     nframe = 0;
245     while (gmx_trr_read_frame_header(fpread, &trrheader, &bOK))
246     {
247         snew(x, trrheader.natoms);
248         snew(v, trrheader.natoms);
249         snew(f, trrheader.natoms);
250         if (gmx_trr_read_frame_data(fpread, &trrheader,
251                                     trrheader.box_size ? box : nullptr,
252                                     trrheader.x_size   ? x : nullptr,
253                                     trrheader.v_size   ? v : nullptr,
254                                     trrheader.f_size   ? f : nullptr))
255         {
256             sprintf(buf, "%s frame %d", fn, nframe);
257             indent = 0;
258             indent = pr_title(stdout, indent, buf);
259             pr_indent(stdout, indent);
260             fprintf(stdout, "natoms=%10d  step=%10" PRId64 "  time=%12.7e  lambda=%10g\n",
261                     trrheader.natoms, trrheader.step, trrheader.t, trrheader.lambda);
262             if (trrheader.box_size)
263             {
264                 pr_rvecs(stdout, indent, "box", box, DIM);
265             }
266             if (trrheader.x_size)
267             {
268                 pr_rvecs(stdout, indent, "x", x, trrheader.natoms);
269             }
270             if (trrheader.v_size)
271             {
272                 pr_rvecs(stdout, indent, "v", v, trrheader.natoms);
273             }
274             if (trrheader.f_size)
275             {
276                 pr_rvecs(stdout, indent, "f", f, trrheader.natoms);
277             }
278         }
279         else
280         {
281             fprintf(stderr, "\nWARNING: Incomplete frame: nr %d, t=%g\n",
282                     nframe, trrheader.t);
283         }
284
285         sfree(x);
286         sfree(v);
287         sfree(f);
288         nframe++;
289     }
290     if (!bOK)
291     {
292         fprintf(stderr, "\nWARNING: Incomplete frame header: nr %d, t=%g\n",
293                 nframe, trrheader.t);
294     }
295     gmx_trr_close(fpread);
296 }
297
298 //! Dump an xtc file
299 void list_xtc(const char *fn)
300 {
301     t_fileio   *xd;
302     int         indent;
303     char        buf[256];
304     rvec       *x;
305     matrix      box;
306     int         nframe, natoms;
307     int64_t     step;
308     real        prec, time;
309     gmx_bool    bOK;
310
311     xd = open_xtc(fn, "r");
312     read_first_xtc(xd, &natoms, &step, &time, box, &x, &prec, &bOK);
313
314     nframe = 0;
315     do
316     {
317         sprintf(buf, "%s frame %d", fn, nframe);
318         indent = 0;
319         indent = pr_title(stdout, indent, buf);
320         pr_indent(stdout, indent);
321         fprintf(stdout, "natoms=%10d  step=%10" PRId64 "  time=%12.7e  prec=%10g\n",
322                 natoms, step, time, prec);
323         pr_rvecs(stdout, indent, "box", box, DIM);
324         pr_rvecs(stdout, indent, "x", x, natoms);
325         nframe++;
326     }
327     while (read_next_xtc(xd, natoms, &step, &time, box, x, &prec, &bOK) != 0);
328     if (!bOK)
329     {
330         fprintf(stderr, "\nWARNING: Incomplete frame at time %g\n", time);
331     }
332     sfree(x);
333     close_xtc(xd);
334 }
335
336 #if GMX_USE_TNG
337
338 /*! \brief Callback used by list_tng_for_gmx_dump. */
339 void list_tng_inner(const char *fn,
340                     gmx_bool    bFirstFrame,
341                     real       *values,
342                     int64_t     step,
343                     double      frame_time,
344                     int64_t     n_values_per_frame,
345                     int64_t     n_atoms,
346                     real        prec,
347                     int64_t     nframe,
348                     char       *block_name)
349 {
350     char                 buf[256];
351     int                  indent = 0;
352
353     if (bFirstFrame)
354     {
355         sprintf(buf, "%s frame %" PRId64, fn, nframe);
356         indent = 0;
357         indent = pr_title(stdout, indent, buf);
358         pr_indent(stdout, indent);
359         fprintf(stdout, "natoms=%10" PRId64 "  step=%10" PRId64 "  time=%12.7e",
360                 n_atoms, step, frame_time);
361         if (prec > 0)
362         {
363             fprintf(stdout, "  prec=%10g", prec);
364         }
365         fprintf(stdout, "\n");
366     }
367     pr_reals_of_dim(stdout, indent, block_name, values, n_atoms, n_values_per_frame);
368 }
369
370 #endif
371
372 //! Dump a TNG file
373 void list_tng(const char *fn)
374 {
375 #if GMX_USE_TNG
376     gmx_tng_trajectory_t tng;
377     int64_t              nframe = 0;
378     int64_t              i, *block_ids = nullptr, step, ndatablocks;
379     gmx_bool             bOK;
380     real                *values = nullptr;
381
382     gmx_tng_open(fn, 'r', &tng);
383     gmx_print_tng_molecule_system(tng, stdout);
384
385     bOK    = gmx_get_tng_data_block_types_of_next_frame(tng, -1,
386                                                         0,
387                                                         nullptr,
388                                                         &step, &ndatablocks,
389                                                         &block_ids);
390     do
391     {
392         for (i = 0; i < ndatablocks; i++)
393         {
394             double               frame_time;
395             real                 prec;
396             int64_t              n_values_per_frame, n_atoms;
397             char                 block_name[STRLEN];
398
399             gmx_get_tng_data_next_frame_of_block_type(tng, block_ids[i], &values,
400                                                       &step, &frame_time,
401                                                       &n_values_per_frame, &n_atoms,
402                                                       &prec,
403                                                       block_name, STRLEN, &bOK);
404             if (!bOK)
405             {
406                 /* Can't write any output because we don't know what
407                    arrays are valid. */
408                 fprintf(stderr, "\nWARNING: Incomplete frame at time %g, will not write output\n", frame_time);
409             }
410             else
411             {
412                 list_tng_inner(fn, (0 == i), values, step, frame_time,
413                                n_values_per_frame, n_atoms, prec, nframe, block_name);
414             }
415         }
416         nframe++;
417     }
418     while (gmx_get_tng_data_block_types_of_next_frame(tng, step,
419                                                       0,
420                                                       nullptr,
421                                                       &step,
422                                                       &ndatablocks,
423                                                       &block_ids));
424
425     if (block_ids)
426     {
427         sfree(block_ids);
428     }
429     sfree(values);
430     gmx_tng_close(&tng);
431 #else
432     GMX_UNUSED_VALUE(fn);
433 #endif
434 }
435
436 //! Dump a trajectory file
437 void list_trx(const char *fn)
438 {
439     switch (fn2ftp(fn))
440     {
441         case efXTC:
442             list_xtc(fn);
443             break;
444         case efTRR:
445             list_trr(fn);
446             break;
447         case efTNG:
448             list_tng(fn);
449             break;
450         default:
451             fprintf(stderr, "File %s is of an unsupported type. Try using the command\n 'less %s'\n",
452                     fn, fn);
453     }
454 }
455
456 //! Dump an energy file
457 void list_ene(const char *fn)
458 {
459     ener_file_t    in;
460     gmx_bool       bCont;
461     gmx_enxnm_t   *enm = nullptr;
462     t_enxframe    *fr;
463     int            i, j, nre, b;
464     char           buf[22];
465
466     printf("gmx dump: %s\n", fn);
467     in = open_enx(fn, "r");
468     do_enxnms(in, &nre, &enm);
469     assert(enm);
470
471     printf("energy components:\n");
472     for (i = 0; (i < nre); i++)
473     {
474         printf("%5d  %-24s (%s)\n", i, enm[i].name, enm[i].unit);
475     }
476
477     snew(fr, 1);
478     do
479     {
480         bCont = do_enx(in, fr);
481
482         if (bCont)
483         {
484             printf("\n%24s  %12.5e  %12s  %12s\n", "time:",
485                    fr->t, "step:", gmx_step_str(fr->step, buf));
486             printf("%24s  %12s  %12s  %12s\n",
487                    "", "", "nsteps:", gmx_step_str(fr->nsteps, buf));
488             printf("%24s  %12.5e  %12s  %12s\n",
489                    "delta_t:", fr->dt, "sum steps:", gmx_step_str(fr->nsum, buf));
490             if (fr->nre == nre)
491             {
492                 printf("%24s  %12s  %12s  %12s\n",
493                        "Component", "Energy", "Av. Energy", "Sum Energy");
494                 if (fr->nsum > 0)
495                 {
496                     for (i = 0; (i < nre); i++)
497                     {
498                         printf("%24s  %12.5e  %12.5e  %12.5e\n",
499                                enm[i].name, fr->ener[i].e, fr->ener[i].eav,
500                                fr->ener[i].esum);
501                     }
502                 }
503                 else
504                 {
505                     for (i = 0; (i < nre); i++)
506                     {
507                         printf("%24s  %12.5e\n",
508                                enm[i].name, fr->ener[i].e);
509                     }
510                 }
511             }
512             for (b = 0; b < fr->nblock; b++)
513             {
514                 const char *typestr = "";
515
516                 t_enxblock *eb = &(fr->block[b]);
517                 printf("Block data %2d (%3d subblocks, id=%d)\n",
518                        b, eb->nsub, eb->id);
519
520                 if (eb->id < enxNR)
521                 {
522                     typestr = enx_block_id_name[eb->id];
523                 }
524                 printf("  id='%s'\n", typestr);
525                 for (i = 0; i < eb->nsub; i++)
526                 {
527                     t_enxsubblock *sb = &(eb->sub[i]);
528                     printf("  Sub block %3d (%5d elems, type=%s) values:\n",
529                            i, sb->nr, xdr_datatype_names[sb->type]);
530
531                     switch (sb->type)
532                     {
533                         case xdr_datatype_float:
534                             for (j = 0; j < sb->nr; j++)
535                             {
536                                 printf("%14d   %8.4f\n", j, sb->fval[j]);
537                             }
538                             break;
539                         case xdr_datatype_double:
540                             for (j = 0; j < sb->nr; j++)
541                             {
542                                 printf("%14d   %10.6f\n", j, sb->dval[j]);
543                             }
544                             break;
545                         case xdr_datatype_int:
546                             for (j = 0; j < sb->nr; j++)
547                             {
548                                 printf("%14d %10d\n", j, sb->ival[j]);
549                             }
550                             break;
551                         case xdr_datatype_int64:
552                             for (j = 0; j < sb->nr; j++)
553                             {
554                                 printf("%14d %s\n",
555                                        j, gmx_step_str(sb->lval[j], buf));
556                             }
557                             break;
558                         case xdr_datatype_char:
559                             for (j = 0; j < sb->nr; j++)
560                             {
561                                 printf("%14d %1c\n", j, sb->cval[j]);
562                             }
563                             break;
564                         case xdr_datatype_string:
565                             for (j = 0; j < sb->nr; j++)
566                             {
567                                 printf("%14d %80s\n", j, sb->sval[j]);
568                             }
569                             break;
570                         default:
571                             gmx_incons("Unknown subblock type");
572                     }
573                 }
574             }
575         }
576     }
577     while (bCont);
578
579     close_enx(in);
580
581     free_enxframe(fr);
582     sfree(fr);
583     sfree(enm);
584 }
585
586 //! Dump a (Hessian) matrix file
587 void list_mtx(const char *fn)
588 {
589     int                  nrow, ncol, i, j, k;
590     real                *full   = nullptr, value;
591     gmx_sparsematrix_t * sparse = nullptr;
592
593     gmx_mtxio_read(fn, &nrow, &ncol, &full, &sparse);
594
595     if (full == nullptr)
596     {
597         snew(full, nrow*ncol);
598         for (i = 0; i < nrow*ncol; i++)
599         {
600             full[i] = 0;
601         }
602
603         for (i = 0; i < sparse->nrow; i++)
604         {
605             for (j = 0; j < sparse->ndata[i]; j++)
606             {
607                 k              = sparse->data[i][j].col;
608                 value          = sparse->data[i][j].value;
609                 full[i*ncol+k] = value;
610                 full[k*ncol+i] = value;
611             }
612         }
613         gmx_sparsematrix_destroy(sparse);
614     }
615
616     printf("%d %d\n", nrow, ncol);
617     for (i = 0; i < nrow; i++)
618     {
619         for (j = 0; j < ncol; j++)
620         {
621             printf(" %g", full[i*ncol+j]);
622         }
623         printf("\n");
624     }
625
626     sfree(full);
627 }
628
629 class Dump : public ICommandLineOptionsModule
630 {
631     public:
632         Dump()
633         {}
634
635         // From ICommandLineOptionsModule
636         void init(CommandLineModuleSettings * /*settings*/) override
637         {
638         }
639
640         void initOptions(IOptionsContainer                 *options,
641                          ICommandLineOptionsModuleSettings *settings) override;
642
643         void optionsFinished() override;
644
645         int run() override;
646
647     private:
648         //! Commandline options
649         //! \{
650         bool bShowNumbers_      = true;
651         bool bShowParams_       = false;
652         bool bSysTop_           = false;
653         bool bOriginalInputrec_ = false;
654         //! \}
655         //! Commandline file options
656         //! \{
657         std::string inputTprFilename_;
658         std::string inputTrajectoryFilename_;
659         std::string inputEnergyFilename_;
660         std::string inputCheckpointFilename_;
661         std::string inputTopologyFilename_;
662         std::string inputMatrixFilename_;
663         std::string outputMdpFilename_;
664         //! \}
665 };
666
667 void Dump::initOptions(IOptionsContainer                 *options,
668                        ICommandLineOptionsModuleSettings *settings)
669 {
670     const char *desc[] = {
671         "[THISMODULE] reads a run input file ([REF].tpr[ref]),",
672         "a trajectory ([REF].trr[ref]/[REF].xtc[ref]/[TT]tng[tt]), an energy",
673         "file ([REF].edr[ref]), a checkpoint file ([REF].cpt[ref])",
674         "or topology file ([REF].top[ref])",
675         "and prints that to standard output in a readable format.",
676         "This program is essential for checking your run input file in case of",
677         "problems."
678     };
679     settings->setHelpText(desc);
680     // TODO If this ancient note acknowledging a bug is still true,
681     // fix it or block that run path:
682     //   Position restraint output from -sys -s is broken
683
684     options->addOption(FileNameOption("s")
685                            .filetype(eftRunInput).inputFile()
686                            .store(&inputTprFilename_)
687                            .description("Run input file to dump"));
688     options->addOption(FileNameOption("f")
689                            .filetype(eftTrajectory).inputFile()
690                            .store(&inputTrajectoryFilename_)
691                            .description("Trajectory file to dump"));
692     options->addOption(FileNameOption("e")
693                            .filetype(eftEnergy).inputFile()
694                            .store(&inputEnergyFilename_)
695                            .description("Energy file to dump"));
696     options->addOption(FileNameOption("cp")
697                            .legacyType(efCPT).inputFile()
698                            .store(&inputCheckpointFilename_)
699                            .description("Checkpoint file to dump"));
700     options->addOption(FileNameOption("p")
701                            .legacyType(efTOP).inputFile()
702                            .store(&inputTopologyFilename_)
703                            .description("Topology file to dump"));
704     options->addOption(FileNameOption("mtx")
705                            .legacyType(efMTX).inputFile()
706                            .store(&inputMatrixFilename_)
707                            .description("Hessian matrix to dump"));
708     options->addOption(FileNameOption("om")
709                            .legacyType(efMDP).outputFile()
710                            .store(&outputMdpFilename_)
711                            .description("grompp input file from run input file"));
712
713     options->addOption(BooleanOption("nr")
714                            .store(&bShowNumbers_).defaultValue(true)
715                            .description("Show index numbers in output (leaving them out makes comparison easier, but creates a useless topology)"));
716     options->addOption(BooleanOption("param")
717                            .store(&bShowParams_).defaultValue(false)
718                            .description("Show parameters for each bonded interaction (for comparing dumps, it is useful to combine this with -nonr)"));
719     options->addOption(BooleanOption("sys")
720                            .store(&bShowParams_).defaultValue(false)
721                            .description("List the atoms and bonded interactions for the whole system instead of for each molecule type"));
722     options->addOption(BooleanOption("orgir")
723                            .store(&bShowParams_).defaultValue(false)
724                            .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"));
725 }
726
727 void Dump::optionsFinished()
728 {
729     // TODO Currently gmx dump ignores user input that seeks to dump
730     // multiple files. Here, we could enforce that the user only asks
731     // to dump one file.
732 }
733
734 int Dump::run()
735 {
736     if (!inputTprFilename_.empty())
737     {
738         list_tpr(inputTprFilename_.c_str(), bShowNumbers_, bShowParams_,
739                  outputMdpFilename_.c_str(), bSysTop_, bOriginalInputrec_);
740     }
741     else if (!inputTrajectoryFilename_.empty())
742     {
743         list_trx(inputTrajectoryFilename_.c_str());
744     }
745     else if (!inputEnergyFilename_.empty())
746     {
747         list_ene(inputEnergyFilename_.c_str());
748     }
749     else if (!inputCheckpointFilename_.empty())
750     {
751         list_checkpoint(inputCheckpointFilename_.c_str(), stdout);
752     }
753     else if (!inputTopologyFilename_.empty())
754     {
755         list_top(inputTopologyFilename_.c_str());
756     }
757     else if (!inputMatrixFilename_.empty())
758     {
759         list_mtx(inputMatrixFilename_.c_str());
760     }
761
762     return 0;
763 }
764
765 }   // namespace
766
767 const char DumpInfo::name[]             = "dump";
768 const char DumpInfo::shortDescription[] =
769     "Make binary files human readable";
770 ICommandLineOptionsModulePointer DumpInfo::create()
771 {
772     return std::make_unique<Dump>();
773 }
774
775 }   // namespace gmx