2 * This file is part of the GROMACS molecular simulation package.
4 * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
5 * Copyright (c) 2001-2004, The GROMACS development team.
6 * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
7 * Copyright (c) 2018,2019,2020,2021, by the GROMACS development team, led by
8 * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
9 * and including many others, as listed in the AUTHORS file in the
10 * top-level source directory and at http://www.gromacs.org.
12 * GROMACS is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU Lesser General Public License
14 * as published by the Free Software Foundation; either version 2.1
15 * of the License, or (at your option) any later version.
17 * GROMACS is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * Lesser General Public License for more details.
22 * You should have received a copy of the GNU Lesser General Public
23 * License along with GROMACS; if not, see
24 * http://www.gnu.org/licenses, or write to the Free Software Foundation,
25 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
27 * If you want to redistribute modifications to GROMACS, please
28 * consider that scientific software is very special. Version
29 * control is crucial - bugs must be traceable. We will be happy to
30 * consider code for inclusion in the official distribution, but
31 * derived work must not be called official GROMACS. Details are found
32 * in the README & COPYING files - if they are missing, get the
33 * official version at http://www.gromacs.org.
35 * To help us fund GROMACS development, we humbly ask that you cite
36 * the research papers on the package. Check out http://www.gromacs.org.
48 #include "gromacs/commandline/pargs.h"
49 #include "gromacs/commandline/viewit.h"
50 #include "gromacs/fileio/confio.h"
51 #include "gromacs/fileio/trxio.h"
52 #include "gromacs/fileio/xvgr.h"
53 #include "gromacs/gmxana/gmx_ana.h"
54 #include "gromacs/linearalgebra/nrjac.h"
55 #include "gromacs/math/functions.h"
56 #include "gromacs/math/units.h"
57 #include "gromacs/math/vec.h"
58 #include "gromacs/mdtypes/md_enums.h"
59 #include "gromacs/pbcutil/pbc.h"
60 #include "gromacs/pbcutil/rmpbc.h"
61 #include "gromacs/topology/index.h"
62 #include "gromacs/topology/topology.h"
63 #include "gromacs/trajectory/trajectoryframe.h"
64 #include "gromacs/utility/arraysize.h"
65 #include "gromacs/utility/cstringutil.h"
66 #include "gromacs/utility/fatalerror.h"
67 #include "gromacs/utility/futil.h"
68 #include "gromacs/utility/smalloc.h"
69 #include "gromacs/utility/stringutil.h"
72 low_print_data(FILE* fp, real time, rvec x[], int n, const int* index, const gmx_bool bDim[], const char* sffmt)
76 fprintf(fp, " %g", time);
77 for (i = 0; i < n; i++)
87 for (d = 0; d < DIM; d++)
91 fprintf(fp, sffmt, x[ii][d]);
96 fprintf(fp, sffmt, norm(x[ii]));
102 static void average_data(rvec x[], rvec xav[], const real* mass, int ngrps, const int isize[], int** index)
107 double sum[DIM], mtot;
109 for (g = 0; g < ngrps; g++)
114 for (i = 0; i < isize[g]; i++)
120 svmul(m, x[ind], tmp);
121 for (d = 0; d < DIM; d++)
129 for (d = 0; d < DIM; d++)
137 for (d = 0; d < DIM; d++)
139 xav[g][d] = sum[d] / mtot;
144 /* mass=NULL, so these are forces: sum only (do not average) */
145 for (d = 0; d < DIM; d++)
153 static void print_data(FILE* fp,
164 static std::vector<gmx::RVec> xav;
172 average_data(x, as_rvec_array(xav.data()), mass, ngrps, isize, index);
173 low_print_data(fp, time, as_rvec_array(xav.data()), ngrps, nullptr, bDim, sffmt);
177 low_print_data(fp, time, x, isize[0], index[0], bDim, sffmt);
181 static void write_trx_x(t_trxstatus* status,
182 const t_trxframe* fr,
189 static std::vector<gmx::RVec> xav;
190 // NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables)
191 static t_atoms* atoms = nullptr;
202 snew(atoms->atom, ngrps);
204 /* Note that atom and residue names will be the ones
205 * of the first atom in each group.
207 for (i = 0; i < ngrps; i++)
209 atoms->atom[i] = fr->atoms->atom[index[i][0]];
210 atoms->atomname[i] = fr->atoms->atomname[index[i][0]];
213 average_data(fr->x, as_rvec_array(xav.data()), mass, ngrps, isize, index);
215 fr_av.natoms = ngrps;
217 fr_av.x = as_rvec_array(xav.data());
218 write_trxframe(status, &fr_av, nullptr);
222 write_trxframe_indexed(status, fr, isize[0], index[0], nullptr);
226 static void make_legend(FILE* fp,
233 const gmx_bool bDim[],
234 const gmx_output_env_t* oenv)
237 const char* dimtxt[] = { " X", " Y", " Z", "" };
251 for (i = 0; i < n; i++)
253 for (d = 0; d <= DIM; d++)
257 snew(leg[j], STRLEN);
260 sprintf(leg[j], "mol %d%s", index[i] + 1, dimtxt[d]);
264 sprintf(leg[j], "%s%s", name[i], dimtxt[d]);
268 sprintf(leg[j], "atom %d%s", index[i] + 1, dimtxt[d]);
274 xvgr_legend(fp, j, leg, oenv);
276 for (i = 0; i < j; i++)
283 static real ekrot(rvec x[], rvec v[], const real mass[], int isize, const int index[])
285 real TCM[5][5], L[5][5];
286 double tm, m0, lxx, lxy, lxz, lyy, lyz, lzz, ekrot;
296 for (i = 0; i < isize; i++)
301 cprod(x[j], v[j], a0);
302 for (m = 0; (m < DIM); m++)
304 xcm[m] += m0 * x[j][m]; /* c.o.m. position */
305 vcm[m] += m0 * v[j][m]; /* c.o.m. velocity */
306 acm[m] += m0 * a0[m]; /* rotational velocity around c.o.m. */
309 dcprod(xcm, vcm, b0);
310 for (m = 0; (m < DIM); m++)
314 acm[m] -= b0[m] / tm;
317 lxx = lxy = lxz = lyy = lyz = lzz = 0.0;
318 for (i = 0; i < isize; i++)
322 for (m = 0; m < DIM; m++)
324 dx[m] = x[j][m] - xcm[m];
326 lxx += dx[XX] * dx[XX] * m0;
327 lxy += dx[XX] * dx[YY] * m0;
328 lxz += dx[XX] * dx[ZZ] * m0;
329 lyy += dx[YY] * dx[YY] * m0;
330 lyz += dx[YY] * dx[ZZ] * m0;
331 lzz += dx[ZZ] * dx[ZZ] * m0;
334 L[XX][XX] = lyy + lzz;
338 L[YY][YY] = lxx + lzz;
342 L[ZZ][ZZ] = lxx + lyy;
344 m_inv_gen(&L[0][0], DIM, &TCM[0][0]);
346 /* Compute omega (hoeksnelheid) */
349 for (m = 0; m < DIM; m++)
351 for (n = 0; n < DIM; n++)
353 ocm[m] += TCM[m][n] * acm[n];
355 ekrot += 0.5 * ocm[m] * acm[m];
361 static real ektrans(rvec v[], const real mass[], int isize, const int index[])
369 for (i = 0; i < isize; i++)
372 for (d = 0; d < DIM; d++)
374 mvcom[d] += mass[j] * v[j][d];
379 return dnorm2(mvcom) / (mtot * 2);
382 static real temp(rvec v[], const real mass[], int isize, const int index[])
388 for (i = 0; i < isize; i++)
391 ekin2 += mass[j] * norm2(v[j]);
394 return ekin2 / (3 * isize * gmx::c_boltz);
397 static void remove_jump(matrix box, int natoms, rvec xp[], rvec x[])
402 for (d = 0; d < DIM; d++)
404 hbox[d] = 0.5 * box[d][d];
406 for (i = 0; i < natoms; i++)
408 for (m = DIM - 1; m >= 0; m--)
410 while (x[i][m] - xp[i][m] <= -hbox[m])
412 for (d = 0; d <= m; d++)
414 x[i][d] += box[m][d];
417 while (x[i][m] - xp[i][m] > hbox[m])
419 for (d = 0; d <= m; d++)
421 x[i][d] -= box[m][d];
428 static void write_pdb_bfac(const char* fname,
440 const gmx_bool bDim[],
442 const gmx_output_env_t* oenv)
445 real max, len2, scale;
449 if ((nfr_x == 0) || (nfr_v == 0))
451 fprintf(stderr, "No frames found for %s, will not write %s\n", title, fname);
455 fprintf(stderr, "Used %d frames for %s\n", nfr_x, "coordinates");
456 fprintf(stderr, "Used %d frames for %s\n", nfr_v, title);
461 for (i = 0; i < DIM; i++)
475 for (i = 0; i < isize; i++)
477 svmul(scale, sum[index[i]], sum[index[i]]);
480 fp = xvgropen(xname, title, "Atom", "Spatial component", oenv);
481 for (i = 0; i < isize; i++)
484 "%-5d %10.3f %10.3f %10.3f\n",
493 for (i = 0; i < isize; i++)
496 for (m = 0; m < DIM; m++)
498 if (bDim[m] || bDim[DIM])
500 len2 += gmx::square(sum[index[i]][m]);
509 if (scale_factor != 0)
511 scale = scale_factor;
521 scale = 10.0 / std::sqrt(max);
525 printf("Maximum %s is %g on atom %d %s, res. %s %d\n",
529 *(atoms->atomname[maxi]),
530 *(atoms->resinfo[atoms->atom[maxi].resind].name),
531 atoms->resinfo[atoms->atom[maxi].resind].nr);
533 if (atoms->pdbinfo == nullptr)
535 snew(atoms->pdbinfo, atoms->nr);
537 atoms->havePdbInfo = TRUE;
541 for (i = 0; i < isize; i++)
544 for (m = 0; m < DIM; m++)
546 if (bDim[m] || bDim[DIM])
548 len2 += gmx::square(sum[index[i]][m]);
551 atoms->pdbinfo[index[i]].bfac = std::sqrt(len2) * scale;
556 for (i = 0; i < isize; i++)
558 atoms->pdbinfo[index[i]].bfac = sum[index[i]][onedim] * scale;
561 write_sto_conf_indexed(fname, title, atoms, x, nullptr, pbcType, box, isize, index);
565 static void update_histo(int gnx, const int index[], rvec v[], int* nhisto, int** histo, real binwidth)
570 if (*histo == nullptr)
573 for (i = 0; (i < gnx); i++)
575 vn = norm(v[index[i]]);
576 vnmax = std::max(vn, vnmax);
579 *nhisto = static_cast<int>(1 + (vnmax / binwidth));
580 snew(*histo, *nhisto);
582 for (i = 0; (i < gnx); i++)
584 vn = norm(v[index[i]]);
585 in = static_cast<int>(vn / binwidth);
589 fprintf(stderr, "Extending histogram from %d to %d\n", *nhisto, nnn);
592 for (m = *nhisto; (m < nnn); m++)
602 static void print_histo(const char* fn, int nhisto, int histo[], real binwidth, const gmx_output_env_t* oenv)
607 fp = xvgropen(fn, "Velocity distribution", "V (nm/ps)", "arbitrary units", oenv);
608 for (i = 0; (i < nhisto); i++)
610 fprintf(fp, "%10.3e %10d\n", i * binwidth, histo[i]);
615 int gmx_traj(int argc, char* argv[])
617 const char* desc[] = {
618 "[THISMODULE] plots coordinates, velocities, forces and/or the box.",
619 "With [TT]-com[tt] the coordinates, velocities and forces are",
620 "calculated for the center of mass of each group.",
621 "When [TT]-mol[tt] is set, the numbers in the index file are",
622 "interpreted as molecule numbers and the same procedure as with",
623 "[TT]-com[tt] is used for each molecule.[PAR]",
624 "Option [TT]-ot[tt] plots the temperature of each group,",
625 "provided velocities are present in the trajectory file.",
626 "No corrections are made for constrained degrees of freedom!",
627 "This implies [TT]-com[tt].[PAR]",
628 "Options [TT]-ekt[tt] and [TT]-ekr[tt] plot the translational and",
629 "rotational kinetic energy of each group,",
630 "provided velocities are present in the trajectory file.",
631 "This implies [TT]-com[tt].[PAR]",
632 "Options [TT]-cv[tt] and [TT]-cf[tt] write the average velocities",
633 "and average forces as temperature factors to a [REF].pdb[ref] file with",
634 "the average coordinates or the coordinates at [TT]-ctime[tt].",
635 "The temperature factors are scaled such that the maximum is 10.",
636 "The scaling can be changed with the option [TT]-scale[tt].",
637 "To get the velocities or forces of one",
638 "frame set both [TT]-b[tt] and [TT]-e[tt] to the time of",
639 "desired frame. When averaging over frames you might need to use",
640 "the [TT]-nojump[tt] option to obtain the correct average coordinates.",
641 "If you select either of these option the average force and velocity",
642 "for each atom are written to an [REF].xvg[ref] file as well",
643 "(specified with [TT]-av[tt] or [TT]-af[tt]).[PAR]",
644 "Option [TT]-vd[tt] computes a velocity distribution, i.e. the",
645 "norm of the vector is plotted. In addition in the same graph",
646 "the kinetic energy distribution is given.",
648 "See [gmx-trajectory] for plotting similar data for selections."
650 static gmx_bool bMol = FALSE, bCom = FALSE, bPBC = TRUE, bNoJump = FALSE;
651 static gmx_bool bX = TRUE, bY = TRUE, bZ = TRUE, bNorm = FALSE, bFP = FALSE;
652 static int ngroups = 1;
653 static real ctime = -1, scale = 0, binwidth = 1;
655 { "-com", FALSE, etBOOL, { &bCom }, "Plot data for the com of each group" },
656 { "-pbc", FALSE, etBOOL, { &bPBC }, "Make molecules whole for COM" },
661 "Index contains molecule numbers instead of atom numbers" },
662 { "-nojump", FALSE, etBOOL, { &bNoJump }, "Remove jumps of atoms across the box" },
663 { "-x", FALSE, etBOOL, { &bX }, "Plot X-component" },
664 { "-y", FALSE, etBOOL, { &bY }, "Plot Y-component" },
665 { "-z", FALSE, etBOOL, { &bZ }, "Plot Z-component" },
666 { "-ng", FALSE, etINT, { &ngroups }, "Number of groups to consider" },
667 { "-len", FALSE, etBOOL, { &bNorm }, "Plot vector length" },
668 { "-fp", FALSE, etBOOL, { &bFP }, "Full precision output" },
669 { "-bin", FALSE, etREAL, { &binwidth }, "Binwidth for velocity histogram (nm/ps)" },
674 "Use frame at this time for x in [TT]-cv[tt] and [TT]-cf[tt] instead of the average x" },
679 "Scale factor for [REF].pdb[ref] output, 0 is autoscale" }
681 FILE * outx = nullptr, *outv = nullptr, *outf = nullptr, *outb = nullptr, *outt = nullptr;
682 FILE * outekt = nullptr, *outekr = nullptr;
688 int flags, nvhisto = 0, *vhisto = nullptr;
689 rvec * xtop, *xp = nullptr;
690 rvec * sumx = nullptr, *sumv = nullptr, *sumf = nullptr;
693 t_trxstatus* status_out = nullptr;
694 gmx_rmpbc_t gpbc = nullptr;
696 int nr_xfr, nr_vfr, nr_ffr;
698 int * isize0, *isize;
699 int ** index0, **index;
702 gmx_bool bTop, bOX, bOXT, bOV, bOF, bOB, bOT, bEKT, bEKR, bCV, bCF;
703 gmx_bool bDim[4], bDum[4], bVD;
705 const char* box_leg[6] = { "XX", "YY", "ZZ", "YX", "ZX", "ZY" };
706 gmx_output_env_t* oenv;
709 { efTRX, "-f", nullptr, ffREAD }, { efTPS, nullptr, nullptr, ffREAD },
710 { efNDX, nullptr, nullptr, ffOPTRD }, { efXVG, "-ox", "coord", ffOPTWR },
711 { efTRX, "-oxt", "coord", ffOPTWR }, { efXVG, "-ov", "veloc", ffOPTWR },
712 { efXVG, "-of", "force", ffOPTWR }, { efXVG, "-ob", "box", ffOPTWR },
713 { efXVG, "-ot", "temp", ffOPTWR }, { efXVG, "-ekt", "ektrans", ffOPTWR },
714 { efXVG, "-ekr", "ekrot", ffOPTWR }, { efXVG, "-vd", "veldist", ffOPTWR },
715 { efPDB, "-cv", "veloc", ffOPTWR }, { efPDB, "-cf", "force", ffOPTWR },
716 { efXVG, "-av", "all_veloc", ffOPTWR }, { efXVG, "-af", "all_force", ffOPTWR }
718 #define NFILE asize(fnm)
720 if (!parse_common_args(&argc,
722 PCA_CAN_TIME | PCA_TIME_UNIT | PCA_CAN_VIEW,
739 "Interpreting indexfile entries as molecules.\n"
740 "Using center of mass.\n");
743 bOX = opt2bSet("-ox", NFILE, fnm);
744 bOXT = opt2bSet("-oxt", NFILE, fnm);
745 bOV = opt2bSet("-ov", NFILE, fnm);
746 bOF = opt2bSet("-of", NFILE, fnm);
747 bOB = opt2bSet("-ob", NFILE, fnm);
748 bOT = opt2bSet("-ot", NFILE, fnm);
749 bEKT = opt2bSet("-ekt", NFILE, fnm);
750 bEKR = opt2bSet("-ekr", NFILE, fnm);
751 bCV = opt2bSet("-cv", NFILE, fnm) || opt2bSet("-av", NFILE, fnm);
752 bCF = opt2bSet("-cf", NFILE, fnm) || opt2bSet("-af", NFILE, fnm);
753 bVD = opt2bSet("-vd", NFILE, fnm) || opt2parg_bSet("-bin", asize(pa), pa);
754 if (bMol || bOT || bEKT || bEKR)
766 sprintf(sffmt, "\t%s", gmx_real_fullprecision_pfmt);
770 sprintf(sffmt, "\t%%g");
772 std::string sffmt6 = gmx::formatString("%s%s%s%s%s%s", sffmt, sffmt, sffmt, sffmt, sffmt, sffmt);
774 bTop = read_tps_conf(ftp2fn(efTPS, NFILE, fnm),
780 bCom && (bOX || bOXT || bOV || bOT || bEKT || bEKR));
782 if ((bMol || bCV || bCF) && !bTop)
784 gmx_fatal(FARGS, "Need a run input file for option -mol, -cv or -cf");
789 indexfn = ftp2fn(efNDX, NFILE, fnm);
793 indexfn = ftp2fn_null(efNDX, NFILE, fnm);
796 if (!(bCom && !bMol))
800 snew(grpname, ngroups);
801 snew(isize0, ngroups);
802 snew(index0, ngroups);
803 get_index(&(top.atoms), indexfn, ngroups, isize0, index0, grpname);
810 snew(isize, ngroups);
811 snew(index, ngroups);
812 for (i = 0; i < ngroups; i++)
814 if (index0[0][i] < 0 || index0[0][i] >= mols->nr)
816 gmx_fatal(FARGS, "Molecule index (%d) is out of range (%d-%d)", index0[0][i] + 1, 1, mols->nr);
818 isize[i] = atndx[index0[0][i] + 1] - atndx[index0[0][i]];
819 snew(index[i], isize[i]);
820 for (j = 0; j < isize[i]; j++)
822 index[i][j] = atndx[index0[0][i]] + j;
833 snew(mass, top.atoms.nr);
834 for (i = 0; i < top.atoms.nr; i++)
836 mass[i] = top.atoms.atom[i].m;
845 std::string label(output_env_get_xvgr_tlabel(oenv));
848 flags = flags | TRX_READ_X;
849 outx = xvgropen(opt2fn("-ox", NFILE, fnm),
850 bCom ? "Center of mass" : "Coordinate",
854 make_legend(outx, ngroups, isize0[0], index0[0], grpname, bCom, bMol, bDim, oenv);
858 flags = flags | TRX_READ_X;
859 status_out = open_trx(opt2fn("-oxt", NFILE, fnm), "w");
863 flags = flags | TRX_READ_V;
864 outv = xvgropen(opt2fn("-ov", NFILE, fnm),
865 bCom ? "Center of mass velocity" : "Velocity",
869 make_legend(outv, ngroups, isize0[0], index0[0], grpname, bCom, bMol, bDim, oenv);
873 flags = flags | TRX_READ_F;
875 opt2fn("-of", NFILE, fnm), "Force", label, "Force (kJ mol\\S-1\\N nm\\S-1\\N)", oenv);
876 make_legend(outf, ngroups, isize0[0], index0[0], grpname, bCom, bMol, bDim, oenv);
880 outb = xvgropen(opt2fn("-ob", NFILE, fnm), "Box vector elements", label, "(nm)", oenv);
882 xvgr_legend(outb, 6, box_leg, oenv);
890 flags = flags | TRX_READ_V;
891 outt = xvgropen(opt2fn("-ot", NFILE, fnm), "Temperature", label, "(K)", oenv);
892 make_legend(outt, ngroups, isize[0], index[0], grpname, bCom, bMol, bDum, oenv);
900 flags = flags | TRX_READ_V;
901 outekt = xvgropen(opt2fn("-ekt", NFILE, fnm),
902 "Center of mass translation",
904 "Energy (kJ mol\\S-1\\N)",
906 make_legend(outekt, ngroups, isize[0], index[0], grpname, bCom, bMol, bDum, oenv);
914 flags = flags | TRX_READ_X | TRX_READ_V;
915 outekr = xvgropen(opt2fn("-ekr", NFILE, fnm),
916 "Center of mass rotation",
918 "Energy (kJ mol\\S-1\\N)",
920 make_legend(outekr, ngroups, isize[0], index[0], grpname, bCom, bMol, bDum, oenv);
924 flags = flags | TRX_READ_V;
928 flags = flags | TRX_READ_X | TRX_READ_V;
932 flags = flags | TRX_READ_X | TRX_READ_F;
934 if ((flags == 0) && !bOB)
936 fprintf(stderr, "Please select one or more output file options\n");
940 read_first_frame(oenv, &status, ftp2fn(efTRX, NFILE, fnm), &fr, flags);
943 if ((bOV || bOF) && fn2ftp(ftp2fn(efTRX, NFILE, fnm)) == efXTC)
946 "Cannot extract velocities or forces since your input XTC file does not contain "
952 snew(sumx, fr.natoms);
956 snew(sumv, fr.natoms);
960 snew(sumf, fr.natoms);
968 gpbc = gmx_rmpbc_init(&top.idef, pbcType, fr.natoms);
973 time = output_env_conv_time(oenv, fr.time);
975 if (fr.bX && bNoJump && fr.bBox)
979 remove_jump(fr.box, fr.natoms, xp, fr.x);
985 for (i = 0; i < fr.natoms; i++)
987 copy_rvec(fr.x[i], xp[i]);
991 if (fr.bX && bCom && bPBC)
993 gmx_rmpbc_trxfr(gpbc, &fr);
998 update_histo(isize[0], index[0], fr.v, &nvhisto, &vhisto, binwidth);
1003 print_data(outx, time, fr.x, mass, bCom, ngroups, isize, index, bDim, sffmt);
1007 t_trxframe frout = fr;
1010 frout.atoms = &top.atoms;
1011 frout.bAtoms = TRUE;
1015 write_trx_x(status_out, &frout, mass, bCom, ngroups, isize, index);
1019 print_data(outv, time, fr.v, mass, bCom, ngroups, isize, index, bDim, sffmt);
1023 print_data(outf, time, fr.f, nullptr, bCom, ngroups, isize, index, bDim, sffmt);
1027 fprintf(outb, "\t%g", fr.time);
1036 fprintf(outb, "\n");
1040 fprintf(outt, " %g", time);
1041 for (i = 0; i < ngroups; i++)
1043 fprintf(outt, sffmt, temp(fr.v, mass, isize[i], index[i]));
1045 fprintf(outt, "\n");
1049 fprintf(outekt, " %g", time);
1050 for (i = 0; i < ngroups; i++)
1052 fprintf(outekt, sffmt, ektrans(fr.v, mass, isize[i], index[i]));
1054 fprintf(outekt, "\n");
1056 if (bEKR && fr.bX && fr.bV)
1058 fprintf(outekr, " %g", time);
1059 for (i = 0; i < ngroups; i++)
1061 fprintf(outekr, sffmt, ekrot(fr.x, fr.v, mass, isize[i], index[i]));
1063 fprintf(outekr, "\n");
1065 if ((bCV || bCF) && fr.bX
1066 && (ctime < 0 || (fr.time >= ctime * 0.999999 && fr.time <= ctime * 1.000001)))
1068 for (i = 0; i < fr.natoms; i++)
1070 rvec_inc(sumx[i], fr.x[i]);
1076 for (i = 0; i < fr.natoms; i++)
1078 rvec_inc(sumv[i], fr.v[i]);
1084 for (i = 0; i < fr.natoms; i++)
1086 rvec_inc(sumf[i], fr.f[i]);
1091 } while (read_next_frame(oenv, status, &fr));
1093 if (gpbc != nullptr)
1095 gmx_rmpbc_done(gpbc);
1098 /* clean up a bit */
1107 close_trx(status_out);
1136 print_histo(opt2fn("-vd", NFILE, fnm), nvhisto, vhisto, binwidth, oenv);
1143 if (pbcType != PbcType::No && !bNoJump)
1146 "\nWARNING: More than one frame was used for option -cv or -cf\n"
1147 "If atoms jump across the box you should use the -nojump or -ctime "
1150 for (i = 0; i < isize[0]; i++)
1152 svmul(1.0 / nr_xfr, sumx[index[0][i]], sumx[index[0][i]]);
1155 else if (nr_xfr == 0)
1157 fprintf(stderr, "\nWARNING: No coordinate frames found for option -cv or -cf\n\n");
1162 write_pdb_bfac(opt2fn("-cv", NFILE, fnm),
1163 opt2fn("-av", NFILE, fnm),
1180 write_pdb_bfac(opt2fn("-cf", NFILE, fnm),
1181 opt2fn("-af", NFILE, fnm),
1198 view_all(oenv, NFILE, fnm);
1201 // Free index and isize only if they are distinct from index0 and isize0
1204 for (int i = 0; i < ngroups; i++)
1211 for (int i = 0; i < ngroups; i++)
1220 output_env_done(oenv);