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 The GROMACS development team.
7 * Copyright (c) 2018,2019,2020, 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.
45 #include <unordered_map>
47 #include "gromacs/commandline/pargs.h"
48 #include "gromacs/commandline/viewit.h"
49 #include "gromacs/fileio/confio.h"
50 #include "gromacs/fileio/matio.h"
51 #include "gromacs/fileio/pdbio.h"
52 #include "gromacs/fileio/tpxio.h"
53 #include "gromacs/fileio/trxio.h"
54 #include "gromacs/fileio/xvgr.h"
55 #include "gromacs/gmxana/gmx_ana.h"
56 #include "gromacs/gmxana/gstat.h"
57 #include "gromacs/listed_forces/disre.h"
58 #include "gromacs/math/do_fit.h"
59 #include "gromacs/math/functions.h"
60 #include "gromacs/math/vec.h"
61 #include "gromacs/mdlib/force.h"
62 #include "gromacs/mdlib/mdatoms.h"
63 #include "gromacs/mdtypes/commrec.h"
64 #include "gromacs/mdtypes/fcdata.h"
65 #include "gromacs/mdtypes/inputrec.h"
66 #include "gromacs/mdtypes/md_enums.h"
67 #include "gromacs/mdtypes/mdatom.h"
68 #include "gromacs/pbcutil/ishift.h"
69 #include "gromacs/pbcutil/pbc.h"
70 #include "gromacs/pbcutil/rmpbc.h"
71 #include "gromacs/topology/index.h"
72 #include "gromacs/topology/mtop_util.h"
73 #include "gromacs/topology/topology.h"
74 #include "gromacs/trajectoryanalysis/topologyinformation.h"
75 #include "gromacs/utility/arraysize.h"
76 #include "gromacs/utility/fatalerror.h"
77 #include "gromacs/utility/futil.h"
78 #include "gromacs/utility/smalloc.h"
86 static t_toppop* top = nullptr;
92 real sumv, averv, maxv;
93 real *aver1, *aver2, *aver_3, *aver_6;
96 static void init5(int n)
106 for (i = 0; (i < ntop); i++)
113 static void add5(int ndr, real viol)
118 for (i = 1; (i < ntop); i++)
120 if (top[i].v < top[mini].v)
125 if (viol > top[mini].v)
132 static void print5(FILE* fp)
136 std::sort(top, top + ntop, [](const t_toppop& a, const t_toppop& b) { return a.v > b.v; }); // reverse sort
137 fprintf(fp, "Index:");
138 for (i = 0; (i < ntop); i++)
140 fprintf(fp, " %6d", top[i].n);
142 fprintf(fp, "\nViol: ");
143 for (i = 0; (i < ntop); i++)
145 fprintf(fp, " %6.3f", top[i].v);
150 static void check_viol(FILE* log,
151 const InteractionList& disres,
152 gmx::ArrayRef<const t_iparams> forceparams,
161 t_disresdata* disresdata)
163 int i, j, nat, n, type, nviol, ndr, label;
164 real rt, mviol, tviol, viol, lam, dvdl, drt;
166 static gmx_bool bFirst = TRUE;
178 gmx::ArrayRef<const int> forceatoms = disres.iatoms;
179 for (j = 0; (j < isize); j++)
183 nat = interaction_function[F_DISRES].nratoms + 1;
184 // Check internal consistency of disres.label
185 // The label for a distance restraint should be at most one larger
186 // than the previous label.
187 int label_old = forceparams[forceatoms[0]].disres.label;
188 for (i = 0; (i < disres.size()); i += nat)
190 type = forceatoms[i];
191 label = forceparams[type].disres.label;
192 if ((label == label_old) || (label == label_old + 1))
199 "Label mismatch in distance restrains. Label for restraint %d is %d, "
200 "expected it to be either %d or %d",
208 // Set up t_fcdata, only needed for calling ta_disres()
210 fcd.disres = disresdata;
212 // Get offset for label index
213 label_old = forceparams[forceatoms[0]].disres.label;
214 for (i = 0; (i < disres.size());)
216 type = forceatoms[i];
218 label = forceparams[type].disres.label - label_old;
221 fprintf(debug, "DISRE: ndr = %d, label = %d i=%d, n =%d\n", ndr, label, i, n);
226 } while (((i + n) < disres.size())
227 && (forceparams[forceatoms[i + n]].disres.label == label + label_old));
229 calc_disres_R_6(nullptr, nullptr, n, &forceatoms[i], x, pbc, disresdata, nullptr);
231 if (disresdata->Rt_6[label] <= 0)
233 gmx_fatal(FARGS, "ndr = %d, rt_6 = %f", ndr, disresdata->Rt_6[label]);
236 rt = gmx::invsixthroot(disresdata->Rt_6[label]);
237 dr[clust_id].aver1[ndr] += rt;
238 dr[clust_id].aver2[ndr] += gmx::square(rt);
239 drt = 1.0 / gmx::power3(rt);
240 dr[clust_id].aver_3[ndr] += drt;
241 dr[clust_id].aver_6[ndr] += disresdata->Rt_6[label];
243 snew(fshift, SHIFTS);
244 ta_disres(n, &forceatoms[i], forceparams.data(), x, f, fshift, pbc, lam, &dvdl, nullptr, &fcd, nullptr);
246 viol = disresdata->sumviol;
253 add5(forceparams[type].disres.label, viol);
260 for (j = 0; (j < isize); j++)
262 if (index[j] == forceparams[type].disres.label)
264 vvindex[j] = gmx::invsixthroot(disresdata->Rt_6[label]);
271 dr[clust_id].nv = nviol;
272 dr[clust_id].maxv = mviol;
273 dr[clust_id].sumv = tviol;
274 dr[clust_id].averv = tviol / ndr;
275 dr[clust_id].nframes++;
279 fprintf(stderr, "\nThere are %d restraints and %d pairs\n", ndr, disres.size() / nat);
292 real up1, r, rT3, rT6, viol, violT3, violT6;
295 static void dump_dump(FILE* log, int ndr, t_dr_stats drs[])
297 static const char* core[] = { "All restraints", "Core restraints" };
298 static const char* tp[] = { "linear", "third power", "sixth power" };
299 real viol_tot, viol_max, viol = 0;
304 for (int iCore = 0; iCore < 2; iCore++)
306 bCore = (iCore == 1);
307 for (kkk = 0; (kkk < 3); kkk++)
313 for (i = 0; (i < ndr); i++)
315 if (!bCore || drs[i].bCore)
319 case 0: viol = drs[i].viol; break;
320 case 1: viol = drs[i].violT3; break;
321 case 2: viol = drs[i].violT6; break;
322 default: gmx_incons("Dumping violations");
324 viol_max = std::max(viol_max, viol);
333 if ((nrestr > 0) || (bCore && (nrestr < ndr)))
336 fprintf(log, "+++++++ %s ++++++++\n", core[bCore]);
337 fprintf(log, "+++++++ Using %s averaging: ++++++++\n", tp[kkk]);
338 fprintf(log, "Sum of violations: %8.3f nm\n", viol_tot);
341 fprintf(log, "Average violation: %8.3f nm\n", viol_tot / nrestr);
343 fprintf(log, "Largest violation: %8.3f nm\n", viol_max);
344 fprintf(log, "Number of violated restraints: %d/%d\n", nviol, nrestr);
350 static void dump_viol(FILE* log, int ndr, t_dr_stats* drs, gmx_bool bLinear)
354 fprintf(log, "Restr. Core Up1 <r> <rT3> <rT6> <viol><violT3><violT6>\n");
355 for (i = 0; (i < ndr); i++)
357 if (bLinear && (drs[i].viol == 0))
362 "%6d%5s%8.3f%8.3f%8.3f%8.3f%8.3f%8.3f%8.3f\n",
364 yesno_names[drs[i].bCore],
375 static gmx_bool is_core(int i, int isize, const int index[])
378 gmx_bool bIC = FALSE;
380 for (kk = 0; !bIC && (kk < isize); kk++)
382 bIC = (index[kk] == i);
388 static void dump_stats(FILE* log,
390 const t_disresdata& dd,
391 const InteractionList& disres,
392 gmx::ArrayRef<const t_iparams> ip,
401 fprintf(log, "++++++++++++++ STATISTICS ++++++++++++++++++++++++\n");
403 const int nra = interaction_function[F_DISRES].nratoms + 1;
404 for (int j = 0; j < disres.size(); j += nra)
406 // Note that the restraint i can be used by multiple pairs
407 const int i = disres.iatoms[j] - dd.type_min;
408 GMX_RELEASE_ASSERT(i >= 0 && i < dd.nres, "The restraint index should be in range");
410 drs[i].label = ip[disres.iatoms[j]].disres.label;
411 drs[i].bCore = is_core(drs[i].label, isize, index);
412 drs[i].up1 = ip[disres.iatoms[j]].disres.up1;
413 drs[i].r = dr->aver1[i] / nsteps;
414 drs[i].rT3 = gmx::invcbrt(dr->aver_3[i] / nsteps);
415 drs[i].rT6 = gmx::invsixthroot(dr->aver_6[i] / nsteps);
416 drs[i].viol = std::max(0.0, static_cast<double>(drs[i].r - drs[i].up1));
417 drs[i].violT3 = std::max(0.0, static_cast<double>(drs[i].rT3 - drs[i].up1));
418 drs[i].violT6 = std::max(0.0, static_cast<double>(drs[i].rT6 - drs[i].up1));
421 int j1 = disres.iatoms[j + 1];
422 int j2 = disres.iatoms[j + 2];
423 atoms->pdbinfo[j1].bfac += drs[i].violT3 * 5;
424 atoms->pdbinfo[j2].bfac += drs[i].violT3 * 5;
427 dump_viol(log, dd.nres, drs, FALSE);
429 fprintf(log, "+++ Sorted by linear averaged violations: +++\n");
430 std::sort(drs, drs + dd.nres, [](const t_dr_stats& a, const t_dr_stats& b) {
431 return a.viol > b.viol;
433 dump_viol(log, dd.nres, drs, TRUE);
435 dump_dump(log, dd.nres, drs);
440 static void dump_clust_stats(FILE* fp,
441 const t_disresdata& dd,
442 const InteractionList& disres,
443 gmx::ArrayRef<const t_iparams> ip,
451 double sumV, maxV, sumVT3, sumVT6, maxVT3, maxVT6;
455 fprintf(fp, "++++++++++++++ STATISTICS ++++++++++++++++++++++\n");
456 fprintf(fp, "Cluster NFrames SumV MaxV SumVT MaxVT SumVS MaxVS\n");
460 for (k = 0; (k < clust->nr); k++)
462 if (dr[k].nframes == 0)
466 if (dr[k].nframes != (clust->index[k + 1] - clust->index[k]))
469 "Inconsistency in cluster %s.\n"
470 "Found %d frames in trajectory rather than the expected %d\n",
473 clust->index[k + 1] - clust->index[k]);
477 gmx_fatal(FARGS, "Inconsistency with cluster %d. Invalid name", k);
479 nra = interaction_function[F_DISRES].nratoms + 1;
480 sumV = sumVT3 = sumVT6 = maxV = maxVT3 = maxVT6 = 0;
482 // Use a map to process each restraint only once while looping over all pairs
483 std::unordered_map<int, bool> restraintHasBeenProcessed;
484 for (int j = 0; j < dd.nres; j += nra)
486 // Note that the restraint i can be used by multiple pairs
487 const int i = disres.iatoms[j] - dd.type_min;
489 if (restraintHasBeenProcessed[i])
494 drs[i].label = ip[disres.iatoms[j]].disres.label;
495 drs[i].bCore = is_core(drs[i].label, isize, index);
496 drs[i].up1 = ip[disres.iatoms[j]].disres.up1;
497 drs[i].r = dr[k].aver1[i] / dr[k].nframes;
498 if ((dr[k].aver_3[i] <= 0) || !std::isfinite(dr[k].aver_3[i]))
500 gmx_fatal(FARGS, "dr[%d].aver_3[%d] = %f", k, i, dr[k].aver_3[i]);
502 drs[i].rT3 = gmx::invcbrt(dr[k].aver_3[i] / dr[k].nframes);
503 drs[i].rT6 = gmx::invsixthroot(dr[k].aver_6[i] / dr[k].nframes);
504 drs[i].viol = std::max(0.0, static_cast<double>(drs[i].r - drs[i].up1));
505 drs[i].violT3 = std::max(0.0, static_cast<double>(drs[i].rT3 - drs[i].up1));
506 drs[i].violT6 = std::max(0.0, static_cast<double>(drs[i].rT6 - drs[i].up1));
508 sumVT3 += drs[i].violT3;
509 sumVT6 += drs[i].violT6;
510 maxV = std::max(maxV, static_cast<double>(drs[i].viol));
511 maxVT3 = std::max(maxVT3, static_cast<double>(drs[i].violT3));
512 maxVT6 = std::max(maxVT6, static_cast<double>(drs[i].violT6));
514 // We have processed restraint i, mark it as such
515 restraintHasBeenProcessed[i] = true;
517 if (std::strcmp(clust_name[k], "1000") == 0)
522 "%-10s%6d%8.3f %8.3f %8.3f %8.3f %8.3f %8.3f\n",
536 static void init_dr_res(t_dr_result* dr, int ndr)
538 snew(dr->aver1, ndr + 1);
539 snew(dr->aver2, ndr + 1);
540 snew(dr->aver_3, ndr + 1);
541 snew(dr->aver_6, ndr + 1);
549 static void dump_disre_matrix(const char* fn,
553 const InteractionDefinitions& idef,
554 const gmx_mtop_t* mtop,
561 int n_res, a_offset, mol, a;
562 int i, j, nra, nratoms, tp, ri, rj, index, nlabel, label;
564 real **matrix, *t_res, hi, *w_dr, rav, rviol;
565 t_rgb rlo = { 1, 1, 1 };
566 t_rgb rhi = { 0, 0, 0 };
572 snew(resnr, mtop->natoms);
575 for (const gmx_molblock_t& molb : mtop->molblock)
577 const t_atoms& atoms = mtop->moltype[molb.type].atoms;
578 for (mol = 0; mol < molb.nmol; mol++)
580 for (a = 0; a < atoms.nr; a++)
582 resnr[a_offset + a] = n_res + atoms.atom[a].resind;
585 a_offset += atoms.nr;
590 for (i = 0; (i < n_res); i++)
595 for (i = 0; (i < n_res); i++)
597 snew(matrix[i], n_res);
599 nratoms = interaction_function[F_DISRES].nratoms;
600 nra = (idef.il[F_DISRES].size() / (nratoms + 1));
606 for (i = 0; (i < idef.il[F_DISRES].size()); i += nratoms + 1)
608 tp = idef.il[F_DISRES].iatoms[i];
609 label = idef.iparams[tp].disres.label;
613 /* Set index pointer */
617 gmx_fatal(FARGS, "nlabel is %d, label = %d", nlabel, label);
621 gmx_fatal(FARGS, "ndr = %d, index = %d", ndr, index);
623 /* Update the weight */
624 w_dr[index] = 1.0 / nlabel;
633 printf("nlabel = %d, index = %d, ndr = %d\n", nlabel, index, ndr);
635 for (i = 0; (i < ndr); i++)
637 for (j = ptr[i]; (j < ptr[i + 1]); j += nratoms + 1)
639 tp = idef.il[F_DISRES].iatoms[j];
640 ai = idef.il[F_DISRES].iatoms[j + 1];
641 aj = idef.il[F_DISRES].iatoms[j + 2];
647 rav = gmx::invcbrt(dr->aver_3[i] / nsteps);
651 rav = dr->aver1[i] / nsteps;
655 fprintf(debug, "DR %d, atoms %d, %d, distance %g\n", i, ai, aj, rav);
657 rviol = std::max(0.0_real, rav - idef.iparams[tp].disres.up1);
658 matrix[ri][rj] += w_dr[i] * rviol;
659 matrix[rj][ri] += w_dr[i] * rviol;
660 hi = std::max(hi, matrix[ri][rj]);
661 hi = std::max(hi, matrix[rj][ri]);
671 printf("Warning: the maxdr that you have specified (%g) is smaller than\nthe largest "
672 "value in your simulation (%g)\n",
678 printf("Highest level in the matrix will be %g\n", hi);
679 fp = gmx_ffopen(fn, "w");
682 "Distance Violations",
699 int gmx_disre(int argc, char* argv[])
701 const char* desc[] = {
702 "[THISMODULE] computes violations of distance restraints.",
703 "The program always",
704 "computes the instantaneous violations rather than time-averaged,",
705 "because this analysis is done from a trajectory file afterwards",
706 "it does not make sense to use time averaging. However,",
707 "the time averaged values per restraint are given in the log file.[PAR]",
708 "An index file may be used to select specific restraints by index group label for",
710 "When the optional [TT]-q[tt] flag is given a [REF].pdb[ref] file coloured by the",
711 "amount of average violations.[PAR]",
712 "When the [TT]-c[tt] option is given, an index file will be read",
713 "containing the frames in your trajectory corresponding to the clusters",
714 "(defined in another manner) that you want to analyze. For these clusters",
715 "the program will compute average violations using the third power",
716 "averaging algorithm and print them in the log file."
719 static int nlevels = 20;
720 static real max_dr = 0;
721 static gmx_bool bThird = TRUE;
727 "Number of large violations that are stored in the log file every step" },
732 "Maximum distance violation in matrix output. If less than or equal to 0 the "
733 "maximum will be determined by the data." },
734 { "-nlevels", FALSE, etINT, { &nlevels }, "Number of levels in the matrix output" },
739 "Use inverse third power averaging or linear for matrix output" }
742 FILE * out = nullptr, *aver = nullptr, *numv = nullptr, *maxxv = nullptr, *xvg = nullptr;
746 rvec * x, *xav = nullptr;
751 int * index = nullptr, *ind_fit = nullptr;
753 t_cluster_ndx* clust = nullptr;
754 t_dr_result dr, *dr_clust = nullptr;
756 real * vvindex = nullptr, *w_rls = nullptr;
757 t_pbc pbc, *pbc_null;
760 gmx_output_env_t* oenv;
761 gmx_rmpbc_t gpbc = nullptr;
763 t_filenm fnm[] = { { efTPR, nullptr, nullptr, ffREAD }, { efTRX, "-f", nullptr, ffREAD },
764 { efXVG, "-ds", "drsum", ffWRITE }, { efXVG, "-da", "draver", ffWRITE },
765 { efXVG, "-dn", "drnum", ffWRITE }, { efXVG, "-dm", "drmax", ffWRITE },
766 { efXVG, "-dr", "restr", ffWRITE }, { efLOG, "-l", "disres", ffWRITE },
767 { efNDX, nullptr, "viol", ffOPTRD }, { efPDB, "-q", "viol", ffOPTWR },
768 { efNDX, "-c", "clust", ffOPTRD }, { efXPM, "-x", "matrix", ffOPTWR } };
769 #define NFILE asize(fnm)
771 if (!parse_common_args(
772 &argc, argv, PCA_CAN_TIME | PCA_CAN_VIEW, NFILE, fnm, asize(pa), pa, asize(desc), desc, 0, nullptr, &oenv))
777 fplog = ftp2FILE(efLOG, NFILE, fnm, "w");
784 t_inputrec irInstance;
785 t_inputrec* ir = &irInstance;
787 gmx::TopologyInformation topInfo;
788 topInfo.fillFromInputFile(ftp2fn(efTPR, NFILE, fnm));
789 int ntopatoms = topInfo.mtop()->natoms;
791 bPDB = opt2bSet("-q", NFILE, fnm);
794 snew(xav, ntopatoms);
795 snew(ind_fit, ntopatoms);
796 snew(w_rls, ntopatoms);
797 for (kkk = 0; (kkk < ntopatoms); kkk++)
803 atoms = topInfo.copyAtoms();
805 if (atoms->pdbinfo == nullptr)
807 snew(atoms->pdbinfo, atoms->nr);
809 atoms->havePdbInfo = TRUE;
812 gmx_localtop_t top(topInfo.mtop()->ffparams);
813 gmx_mtop_generate_local_top(*topInfo.mtop(), &top, ir->efep != efepNO);
814 const InteractionDefinitions& idef = top.idef;
817 if (ir->pbcType != PbcType::No)
822 if (ftp2bSet(efNDX, NFILE, fnm))
824 /* TODO: Nothing is written to this file if -c is provided, but it is
826 rd_index(ftp2fn(efNDX, NFILE, fnm), 1, &isize, &index, &grpname);
827 xvg = xvgropen(opt2fn("-dr", NFILE, fnm), "Individual Restraints", "Time (ps)", "nm", oenv);
828 snew(vvindex, isize);
830 for (i = 0; (i < isize); i++)
834 sprintf(leg[i], "index %d", index[i]);
836 xvgr_legend(xvg, isize, leg, oenv);
844 t_disresdata disresdata;
848 DisResRunMode::AnalysisTool,
857 int natoms = read_first_x(oenv, &status, ftp2fn(efTRX, NFILE, fnm), &t, &x, box);
860 init_dr_res(&dr, disresdata.nres);
861 if (opt2bSet("-c", NFILE, fnm))
863 clust = cluster_index(fplog, opt2fn("-c", NFILE, fnm));
864 snew(dr_clust, clust->clust->nr + 1);
865 for (i = 0; (i <= clust->clust->nr); i++)
867 init_dr_res(&dr_clust[i], disresdata.nres);
872 out = xvgropen(opt2fn("-ds", NFILE, fnm), "Sum of Violations", "Time (ps)", "nm", oenv);
873 aver = xvgropen(opt2fn("-da", NFILE, fnm), "Average Violation", "Time (ps)", "nm", oenv);
874 numv = xvgropen(opt2fn("-dn", NFILE, fnm), "# Violations", "Time (ps)", "#", oenv);
875 maxxv = xvgropen(opt2fn("-dm", NFILE, fnm), "Largest Violation", "Time (ps)", "nm", oenv);
878 auto mdAtoms = gmx::makeMDAtoms(fplog, *topInfo.mtop(), *ir, false);
879 atoms2md(topInfo.mtop(), ir, -1, {}, ntopatoms, mdAtoms.get());
880 update_mdatoms(mdAtoms->mdatoms(), ir->fepvals->init_lambda);
881 if (ir->pbcType != PbcType::No)
883 gpbc = gmx_rmpbc_init(idef, ir->pbcType, natoms);
889 if (ir->pbcType != PbcType::No)
891 if (ir->bPeriodicMols)
893 set_pbc(&pbc, ir->pbcType, box);
897 gmx_rmpbc(gpbc, natoms, box, x);
903 if (j > clust->maxframe)
906 "There are more frames in the trajectory than in the cluster index file. "
910 my_clust = clust->inv_clust[j];
911 range_check(my_clust, 0, clust->clust->nr);
913 fplog, idef.il[F_DISRES], idef.iparams, x, f, pbc_null, dr_clust, my_clust, isize, index, vvindex, &disresdata);
917 check_viol(fplog, idef.il[F_DISRES], idef.iparams, x, f, pbc_null, &dr, 0, isize, index, vvindex, &disresdata);
921 reset_x(atoms->nr, ind_fit, atoms->nr, nullptr, x, w_rls);
922 do_fit(atoms->nr, w_rls, x, x);
925 /* Store the first frame of the trajectory as 'characteristic'
926 * for colouring with violations.
928 for (kkk = 0; (kkk < atoms->nr); kkk++)
930 copy_rvec(x[kkk], xav[kkk]);
938 fprintf(xvg, "%10g", t);
939 for (i = 0; (i < isize); i++)
941 fprintf(xvg, " %10g", vvindex[i]);
945 fprintf(out, "%10g %10g\n", t, dr.sumv);
946 fprintf(aver, "%10g %10g\n", t, dr.averv);
947 fprintf(maxxv, "%10g %10g\n", t, dr.maxv);
948 fprintf(numv, "%10g %10d\n", t, dr.nv);
951 } while (read_next_x(oenv, status, &t, x, box));
953 if (ir->pbcType != PbcType::No)
955 gmx_rmpbc_done(gpbc);
961 fplog, disresdata, idef.il[F_DISRES], idef.iparams, clust->clust, dr_clust, clust->grpname, isize, index);
965 dump_stats(fplog, j, disresdata, idef.il[F_DISRES], idef.iparams, &dr, isize, index, bPDB ? atoms.get() : nullptr);
968 write_sto_conf(opt2fn("-q", NFILE, fnm),
969 "Coloured by average violation in Angstrom",
977 opt2fn_null("-x", NFILE, fnm), &dr, disresdata.nres, j, idef, topInfo.mtop(), max_dr, nlevels, bThird);
982 do_view(oenv, opt2fn("-dn", NFILE, fnm), "-nxy");
983 do_view(oenv, opt2fn("-da", NFILE, fnm), "-nxy");
984 do_view(oenv, opt2fn("-ds", NFILE, fnm), "-nxy");
985 do_view(oenv, opt2fn("-dm", NFILE, fnm), "-nxy");
992 do_view(oenv, opt2fn("-dr", NFILE, fnm), "-nxy");