Minor modernization in gmx_dump
[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 #include "gmxpre.h"
38
39 #include "dump.h"
40
41 #include "config.h"
42
43 #include <cassert>
44 #include <cmath>
45 #include <cstdio>
46 #include <cstring>
47
48 #include "gromacs/commandline/pargs.h"
49 #include "gromacs/fileio/checkpoint.h"
50 #include "gromacs/fileio/enxio.h"
51 #include "gromacs/fileio/gmxfio.h"
52 #include "gromacs/fileio/mtxio.h"
53 #include "gromacs/fileio/tngio.h"
54 #include "gromacs/fileio/tpxio.h"
55 #include "gromacs/fileio/trrio.h"
56 #include "gromacs/fileio/xtcio.h"
57 #include "gromacs/gmxpreprocess/gmxcpp.h"
58 #include "gromacs/linearalgebra/sparsematrix.h"
59 #include "gromacs/math/vecdump.h"
60 #include "gromacs/mdrunutility/mdmodules.h"
61 #include "gromacs/mdtypes/forcerec.h"
62 #include "gromacs/mdtypes/inputrec.h"
63 #include "gromacs/mdtypes/md_enums.h"
64 #include "gromacs/mdtypes/state.h"
65 #include "gromacs/topology/mtop_util.h"
66 #include "gromacs/topology/topology.h"
67 #include "gromacs/trajectory/energyframe.h"
68 #include "gromacs/trajectory/trajectoryframe.h"
69 #include "gromacs/utility/arraysize.h"
70 #include "gromacs/utility/basedefinitions.h"
71 #include "gromacs/utility/fatalerror.h"
72 #include "gromacs/utility/futil.h"
73 #include "gromacs/utility/smalloc.h"
74 #include "gromacs/utility/txtdump.h"
75
76 namespace gmx
77 {
78
79 namespace
80 {
81
82 //! Dump a TPR file
83 void list_tpx(const char *fn,
84               gmx_bool    bShowNumbers,
85               gmx_bool    bShowParameters,
86               const char *mdpfn,
87               gmx_bool    bSysTop,
88               gmx_bool    bOriginalInputrec)
89 {
90     FILE         *gp;
91     int           indent, i, j, **gcount, atot;
92     t_state       state;
93     t_tpxheader   tpx;
94     gmx_mtop_t    mtop;
95     t_topology    top;
96
97     read_tpxheader(fn, &tpx, TRUE);
98     t_inputrec     ir;
99     read_tpx_state(fn,
100                    tpx.bIr ? &ir : nullptr,
101                    &state,
102                    tpx.bTop ? &mtop : nullptr);
103     if (tpx.bIr && !bOriginalInputrec)
104     {
105         MDModules().adjustInputrecBasedOnModules(&ir);
106     }
107
108     if (mdpfn && tpx.bIr)
109     {
110         gp = gmx_fio_fopen(mdpfn, "w");
111         pr_inputrec(gp, 0, nullptr, &ir, TRUE);
112         gmx_fio_fclose(gp);
113     }
114
115     if (!mdpfn)
116     {
117         if (bSysTop)
118         {
119             top = gmx_mtop_t_to_t_topology(&mtop, false);
120         }
121
122         if (available(stdout, &tpx, 0, fn))
123         {
124             indent = 0;
125             pr_title(stdout, indent, fn);
126             pr_inputrec(stdout, 0, "inputrec", tpx.bIr ? &ir : nullptr, FALSE);
127
128             pr_tpxheader(stdout, indent, "header", &(tpx));
129
130             if (!bSysTop)
131             {
132                 pr_mtop(stdout, indent, "topology", &(mtop), bShowNumbers, bShowParameters);
133             }
134             else
135             {
136                 pr_top(stdout, indent, "topology", &(top), bShowNumbers, bShowParameters);
137             }
138
139             pr_rvecs(stdout, indent, "box", tpx.bBox ? state.box : nullptr, DIM);
140             pr_rvecs(stdout, indent, "box_rel", tpx.bBox ? state.box_rel : nullptr, DIM);
141             pr_rvecs(stdout, indent, "boxv", tpx.bBox ? state.boxv : nullptr, DIM);
142             pr_rvecs(stdout, indent, "pres_prev", tpx.bBox ? state.pres_prev : nullptr, DIM);
143             pr_rvecs(stdout, indent, "svir_prev", tpx.bBox ? state.svir_prev : nullptr, DIM);
144             pr_rvecs(stdout, indent, "fvir_prev", tpx.bBox ? state.fvir_prev : nullptr, DIM);
145             /* leave nosehoover_xi in for now to match the tpr version */
146             pr_doubles(stdout, indent, "nosehoover_xi", state.nosehoover_xi.data(), state.ngtc);
147             /*pr_doubles(stdout,indent,"nosehoover_vxi",state.nosehoover_vxi,state.ngtc);*/
148             /*pr_doubles(stdout,indent,"therm_integral",state.therm_integral,state.ngtc);*/
149             pr_rvecs(stdout, indent, "x", tpx.bX ? state.x.rvec_array() : nullptr, state.natoms);
150             pr_rvecs(stdout, indent, "v", tpx.bV ? state.v.rvec_array() : nullptr, state.natoms);
151         }
152
153         const gmx_groups_t &groups = mtop.groups;
154
155         snew(gcount, egcNR);
156         for (i = 0; (i < egcNR); i++)
157         {
158             snew(gcount[i], groups.grps[i].nr);
159         }
160
161         for (i = 0; (i < mtop.natoms); i++)
162         {
163             for (j = 0; (j < egcNR); j++)
164             {
165                 gcount[j][getGroupType(groups, j, i)]++;
166             }
167         }
168         printf("Group statistics\n");
169         for (i = 0; (i < egcNR); i++)
170         {
171             atot = 0;
172             printf("%-12s: ", gtypes[i]);
173             for (j = 0; (j < groups.grps[i].nr); j++)
174             {
175                 printf("  %5d", gcount[i][j]);
176                 atot += gcount[i][j];
177             }
178             printf("  (total %d atoms)\n", atot);
179             sfree(gcount[i]);
180         }
181         sfree(gcount);
182     }
183 }
184
185 //! Dump a topology file
186 void list_top(const char *fn)
187 {
188     int       status, done;
189 #define BUFLEN 256
190     char      buf[BUFLEN];
191     gmx_cpp_t handle;
192     char     *cppopts[] = { nullptr };
193
194     status = cpp_open_file(fn, &handle, cppopts);
195     if (status != 0)
196     {
197         gmx_fatal(FARGS, "%s", cpp_error(&handle, status));
198     }
199     do
200     {
201         status = cpp_read_line(&handle, BUFLEN, buf);
202         done   = static_cast<int>(status == eCPP_EOF);
203         if (!done)
204         {
205             if (status != eCPP_OK)
206             {
207                 gmx_fatal(FARGS, "%s", cpp_error(&handle, status));
208             }
209             else
210             {
211                 printf("%s\n", buf);
212             }
213         }
214     }
215     while (done == 0);
216     status = cpp_close_file(&handle);
217     if (status != eCPP_OK)
218     {
219         gmx_fatal(FARGS, "%s", cpp_error(&handle, status));
220     }
221 }
222
223 //! Dump a TRR file
224 void list_trr(const char *fn)
225 {
226     t_fileio         *fpread;
227     int               nframe, indent;
228     char              buf[256];
229     rvec             *x, *v, *f;
230     matrix            box;
231     gmx_trr_header_t  trrheader;
232     gmx_bool          bOK;
233
234     fpread  = gmx_trr_open(fn, "r");
235
236     nframe = 0;
237     while (gmx_trr_read_frame_header(fpread, &trrheader, &bOK))
238     {
239         snew(x, trrheader.natoms);
240         snew(v, trrheader.natoms);
241         snew(f, trrheader.natoms);
242         if (gmx_trr_read_frame_data(fpread, &trrheader,
243                                     trrheader.box_size ? box : nullptr,
244                                     trrheader.x_size   ? x : nullptr,
245                                     trrheader.v_size   ? v : nullptr,
246                                     trrheader.f_size   ? f : nullptr))
247         {
248             sprintf(buf, "%s frame %d", fn, nframe);
249             indent = 0;
250             indent = pr_title(stdout, indent, buf);
251             pr_indent(stdout, indent);
252             fprintf(stdout, "natoms=%10d  step=%10" PRId64 "  time=%12.7e  lambda=%10g\n",
253                     trrheader.natoms, trrheader.step, trrheader.t, trrheader.lambda);
254             if (trrheader.box_size)
255             {
256                 pr_rvecs(stdout, indent, "box", box, DIM);
257             }
258             if (trrheader.x_size)
259             {
260                 pr_rvecs(stdout, indent, "x", x, trrheader.natoms);
261             }
262             if (trrheader.v_size)
263             {
264                 pr_rvecs(stdout, indent, "v", v, trrheader.natoms);
265             }
266             if (trrheader.f_size)
267             {
268                 pr_rvecs(stdout, indent, "f", f, trrheader.natoms);
269             }
270         }
271         else
272         {
273             fprintf(stderr, "\nWARNING: Incomplete frame: nr %d, t=%g\n",
274                     nframe, trrheader.t);
275         }
276
277         sfree(x);
278         sfree(v);
279         sfree(f);
280         nframe++;
281     }
282     if (!bOK)
283     {
284         fprintf(stderr, "\nWARNING: Incomplete frame header: nr %d, t=%g\n",
285                 nframe, trrheader.t);
286     }
287     gmx_trr_close(fpread);
288 }
289
290 //! Dump an xtc file
291 void list_xtc(const char *fn)
292 {
293     t_fileio   *xd;
294     int         indent;
295     char        buf[256];
296     rvec       *x;
297     matrix      box;
298     int         nframe, natoms;
299     int64_t     step;
300     real        prec, time;
301     gmx_bool    bOK;
302
303     xd = open_xtc(fn, "r");
304     read_first_xtc(xd, &natoms, &step, &time, box, &x, &prec, &bOK);
305
306     nframe = 0;
307     do
308     {
309         sprintf(buf, "%s frame %d", fn, nframe);
310         indent = 0;
311         indent = pr_title(stdout, indent, buf);
312         pr_indent(stdout, indent);
313         fprintf(stdout, "natoms=%10d  step=%10" PRId64 "  time=%12.7e  prec=%10g\n",
314                 natoms, step, time, prec);
315         pr_rvecs(stdout, indent, "box", box, DIM);
316         pr_rvecs(stdout, indent, "x", x, natoms);
317         nframe++;
318     }
319     while (read_next_xtc(xd, natoms, &step, &time, box, x, &prec, &bOK) != 0);
320     if (!bOK)
321     {
322         fprintf(stderr, "\nWARNING: Incomplete frame at time %g\n", time);
323     }
324     sfree(x);
325     close_xtc(xd);
326 }
327
328 #if GMX_USE_TNG
329
330 /*! \brief Callback used by list_tng_for_gmx_dump. */
331 void list_tng_inner(const char *fn,
332                     gmx_bool    bFirstFrame,
333                     real       *values,
334                     int64_t     step,
335                     double      frame_time,
336                     int64_t     n_values_per_frame,
337                     int64_t     n_atoms,
338                     real        prec,
339                     int64_t     nframe,
340                     char       *block_name)
341 {
342     char                 buf[256];
343     int                  indent = 0;
344
345     if (bFirstFrame)
346     {
347         sprintf(buf, "%s frame %" PRId64, fn, nframe);
348         indent = 0;
349         indent = pr_title(stdout, indent, buf);
350         pr_indent(stdout, indent);
351         fprintf(stdout, "natoms=%10" PRId64 "  step=%10" PRId64 "  time=%12.7e",
352                 n_atoms, step, frame_time);
353         if (prec > 0)
354         {
355             fprintf(stdout, "  prec=%10g", prec);
356         }
357         fprintf(stdout, "\n");
358     }
359     pr_reals_of_dim(stdout, indent, block_name, values, n_atoms, n_values_per_frame);
360 }
361
362 #endif
363
364 //! Dump a TNG file
365 void list_tng(const char *fn)
366 {
367 #if GMX_USE_TNG
368     gmx_tng_trajectory_t tng;
369     int64_t              nframe = 0;
370     int64_t              i, *block_ids = nullptr, step, ndatablocks;
371     gmx_bool             bOK;
372     real                *values = nullptr;
373
374     gmx_tng_open(fn, 'r', &tng);
375     gmx_print_tng_molecule_system(tng, stdout);
376
377     bOK    = gmx_get_tng_data_block_types_of_next_frame(tng, -1,
378                                                         0,
379                                                         nullptr,
380                                                         &step, &ndatablocks,
381                                                         &block_ids);
382     do
383     {
384         for (i = 0; i < ndatablocks; i++)
385         {
386             double               frame_time;
387             real                 prec;
388             int64_t              n_values_per_frame, n_atoms;
389             char                 block_name[STRLEN];
390
391             gmx_get_tng_data_next_frame_of_block_type(tng, block_ids[i], &values,
392                                                       &step, &frame_time,
393                                                       &n_values_per_frame, &n_atoms,
394                                                       &prec,
395                                                       block_name, STRLEN, &bOK);
396             if (!bOK)
397             {
398                 /* Can't write any output because we don't know what
399                    arrays are valid. */
400                 fprintf(stderr, "\nWARNING: Incomplete frame at time %g, will not write output\n", frame_time);
401             }
402             else
403             {
404                 list_tng_inner(fn, (0 == i), values, step, frame_time,
405                                n_values_per_frame, n_atoms, prec, nframe, block_name);
406             }
407         }
408         nframe++;
409     }
410     while (gmx_get_tng_data_block_types_of_next_frame(tng, step,
411                                                       0,
412                                                       nullptr,
413                                                       &step,
414                                                       &ndatablocks,
415                                                       &block_ids));
416
417     if (block_ids)
418     {
419         sfree(block_ids);
420     }
421     sfree(values);
422     gmx_tng_close(&tng);
423 #else
424     GMX_UNUSED_VALUE(fn);
425 #endif
426 }
427
428 //! Dump a trajectory file
429 void list_trx(const char *fn)
430 {
431     switch (fn2ftp(fn))
432     {
433         case efXTC:
434             list_xtc(fn);
435             break;
436         case efTRR:
437             list_trr(fn);
438             break;
439         case efTNG:
440             list_tng(fn);
441             break;
442         default:
443             fprintf(stderr, "File %s is of an unsupported type. Try using the command\n 'less %s'\n",
444                     fn, fn);
445     }
446 }
447
448 //! Dump an energy file
449 void list_ene(const char *fn)
450 {
451     ener_file_t    in;
452     gmx_bool       bCont;
453     gmx_enxnm_t   *enm = nullptr;
454     t_enxframe    *fr;
455     int            i, j, nre, b;
456     char           buf[22];
457
458     printf("gmx dump: %s\n", fn);
459     in = open_enx(fn, "r");
460     do_enxnms(in, &nre, &enm);
461     assert(enm);
462
463     printf("energy components:\n");
464     for (i = 0; (i < nre); i++)
465     {
466         printf("%5d  %-24s (%s)\n", i, enm[i].name, enm[i].unit);
467     }
468
469     snew(fr, 1);
470     do
471     {
472         bCont = do_enx(in, fr);
473
474         if (bCont)
475         {
476             printf("\n%24s  %12.5e  %12s  %12s\n", "time:",
477                    fr->t, "step:", gmx_step_str(fr->step, buf));
478             printf("%24s  %12s  %12s  %12s\n",
479                    "", "", "nsteps:", gmx_step_str(fr->nsteps, buf));
480             printf("%24s  %12.5e  %12s  %12s\n",
481                    "delta_t:", fr->dt, "sum steps:", gmx_step_str(fr->nsum, buf));
482             if (fr->nre == nre)
483             {
484                 printf("%24s  %12s  %12s  %12s\n",
485                        "Component", "Energy", "Av. Energy", "Sum Energy");
486                 if (fr->nsum > 0)
487                 {
488                     for (i = 0; (i < nre); i++)
489                     {
490                         printf("%24s  %12.5e  %12.5e  %12.5e\n",
491                                enm[i].name, fr->ener[i].e, fr->ener[i].eav,
492                                fr->ener[i].esum);
493                     }
494                 }
495                 else
496                 {
497                     for (i = 0; (i < nre); i++)
498                     {
499                         printf("%24s  %12.5e\n",
500                                enm[i].name, fr->ener[i].e);
501                     }
502                 }
503             }
504             for (b = 0; b < fr->nblock; b++)
505             {
506                 const char *typestr = "";
507
508                 t_enxblock *eb = &(fr->block[b]);
509                 printf("Block data %2d (%3d subblocks, id=%d)\n",
510                        b, eb->nsub, eb->id);
511
512                 if (eb->id < enxNR)
513                 {
514                     typestr = enx_block_id_name[eb->id];
515                 }
516                 printf("  id='%s'\n", typestr);
517                 for (i = 0; i < eb->nsub; i++)
518                 {
519                     t_enxsubblock *sb = &(eb->sub[i]);
520                     printf("  Sub block %3d (%5d elems, type=%s) values:\n",
521                            i, sb->nr, xdr_datatype_names[sb->type]);
522
523                     switch (sb->type)
524                     {
525                         case xdr_datatype_float:
526                             for (j = 0; j < sb->nr; j++)
527                             {
528                                 printf("%14d   %8.4f\n", j, sb->fval[j]);
529                             }
530                             break;
531                         case xdr_datatype_double:
532                             for (j = 0; j < sb->nr; j++)
533                             {
534                                 printf("%14d   %10.6f\n", j, sb->dval[j]);
535                             }
536                             break;
537                         case xdr_datatype_int:
538                             for (j = 0; j < sb->nr; j++)
539                             {
540                                 printf("%14d %10d\n", j, sb->ival[j]);
541                             }
542                             break;
543                         case xdr_datatype_int64:
544                             for (j = 0; j < sb->nr; j++)
545                             {
546                                 printf("%14d %s\n",
547                                        j, gmx_step_str(sb->lval[j], buf));
548                             }
549                             break;
550                         case xdr_datatype_char:
551                             for (j = 0; j < sb->nr; j++)
552                             {
553                                 printf("%14d %1c\n", j, sb->cval[j]);
554                             }
555                             break;
556                         case xdr_datatype_string:
557                             for (j = 0; j < sb->nr; j++)
558                             {
559                                 printf("%14d %80s\n", j, sb->sval[j]);
560                             }
561                             break;
562                         default:
563                             gmx_incons("Unknown subblock type");
564                     }
565                 }
566             }
567         }
568     }
569     while (bCont);
570
571     close_enx(in);
572
573     free_enxframe(fr);
574     sfree(fr);
575     sfree(enm);
576 }
577
578 //! Dump a (Hessian) matrix file
579 void list_mtx(const char *fn)
580 {
581     int                  nrow, ncol, i, j, k;
582     real                *full   = nullptr, value;
583     gmx_sparsematrix_t * sparse = nullptr;
584
585     gmx_mtxio_read(fn, &nrow, &ncol, &full, &sparse);
586
587     if (full == nullptr)
588     {
589         snew(full, nrow*ncol);
590         for (i = 0; i < nrow*ncol; i++)
591         {
592             full[i] = 0;
593         }
594
595         for (i = 0; i < sparse->nrow; i++)
596         {
597             for (j = 0; j < sparse->ndata[i]; j++)
598             {
599                 k              = sparse->data[i][j].col;
600                 value          = sparse->data[i][j].value;
601                 full[i*ncol+k] = value;
602                 full[k*ncol+i] = value;
603             }
604         }
605         gmx_sparsematrix_destroy(sparse);
606     }
607
608     printf("%d %d\n", nrow, ncol);
609     for (i = 0; i < nrow; i++)
610     {
611         for (j = 0; j < ncol; j++)
612         {
613             printf(" %g", full[i*ncol+j]);
614         }
615         printf("\n");
616     }
617
618     sfree(full);
619 }
620
621 }   // namespace
622
623 int gmx_dump(int argc, char *argv[])
624 {
625     const char *desc[] = {
626         "[THISMODULE] reads a run input file ([REF].tpr[ref]),",
627         "a trajectory ([REF].trr[ref]/[REF].xtc[ref]/[TT]/tng[tt]), an energy",
628         "file ([REF].edr[ref]) or a checkpoint file ([REF].cpt[ref])",
629         "and prints that to standard output in a readable format.",
630         "This program is essential for checking your run input file in case of",
631         "problems.[PAR]",
632         "The program can also preprocess a topology to help finding problems.",
633         "Note that currently setting [TT]GMXLIB[tt] is the only way to customize",
634         "directories used for searching include files.",
635     };
636     const char *bugs[] = {
637         "Position restraint output from -sys -s is broken"
638     };
639     t_filenm    fnm[] = {
640         { efTPR, "-s", nullptr, ffOPTRD },
641         { efTRX, "-f", nullptr, ffOPTRD },
642         { efEDR, "-e", nullptr, ffOPTRD },
643         { efCPT, nullptr, nullptr, ffOPTRD },
644         { efTOP, "-p", nullptr, ffOPTRD },
645         { efMTX, "-mtx", "hessian", ffOPTRD },
646         { efMDP, "-om", nullptr, ffOPTWR }
647     };
648 #define NFILE asize(fnm)
649
650     gmx_output_env_t *oenv;
651     /* Command line options */
652     gmx_bool          bShowNumbers      = TRUE;
653     gmx_bool          bShowParams       = FALSE;
654     gmx_bool          bSysTop           = FALSE;
655     gmx_bool          bOriginalInputrec = FALSE;
656     t_pargs           pa[]              = {
657         { "-nr", FALSE, etBOOL, {&bShowNumbers}, "Show index numbers in output (leaving them out makes comparison easier, but creates a useless topology)" },
658         { "-param", FALSE, etBOOL, {&bShowParams}, "Show parameters for each bonded interaction (for comparing dumps, it is useful to combine this with -nonr)" },
659         { "-sys", FALSE, etBOOL, {&bSysTop}, "List the atoms and bonded interactions for the whole system instead of for each molecule type" },
660         { "-orgir", FALSE, etBOOL, {&bOriginalInputrec}, "Show input parameters from tpr as they were written by the version that produced the file, instead of how the current version reads them" }
661     };
662
663     if (!parse_common_args(&argc, argv, 0, NFILE, fnm, asize(pa), pa,
664                            asize(desc), desc, asize(bugs), bugs, &oenv))
665     {
666         return 0;
667     }
668
669
670     if (ftp2bSet(efTPR, NFILE, fnm))
671     {
672         list_tpx(ftp2fn(efTPR, NFILE, fnm), bShowNumbers, bShowParams,
673                  ftp2fn_null(efMDP, NFILE, fnm), bSysTop, bOriginalInputrec);
674     }
675     else if (ftp2bSet(efTRX, NFILE, fnm))
676     {
677         list_trx(ftp2fn(efTRX, NFILE, fnm));
678     }
679     else if (ftp2bSet(efEDR, NFILE, fnm))
680     {
681         list_ene(ftp2fn(efEDR, NFILE, fnm));
682     }
683     else if (ftp2bSet(efCPT, NFILE, fnm))
684     {
685         list_checkpoint(ftp2fn(efCPT, NFILE, fnm), stdout);
686     }
687     else if (ftp2bSet(efTOP, NFILE, fnm))
688     {
689         list_top(ftp2fn(efTOP, NFILE, fnm));
690     }
691     else if (ftp2bSet(efMTX, NFILE, fnm))
692     {
693         list_mtx(ftp2fn(efMTX, NFILE, fnm));
694     }
695
696     return 0;
697 }
698
699 }   // namespace gmx