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,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.
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.
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.
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.
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.
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.
45 #include "gromacs/commandline/pargs.h"
46 #include "gromacs/commandline/viewit.h"
47 #include "gromacs/fileio/confio.h"
48 #include "gromacs/fileio/matio.h"
49 #include "gromacs/fileio/pdbio.h"
50 #include "gromacs/fileio/tpxio.h"
51 #include "gromacs/fileio/trxio.h"
52 #include "gromacs/fileio/xvgr.h"
53 #include "gromacs/gmxana/gmx_ana.h"
54 #include "gromacs/gmxana/gstat.h"
55 #include "gromacs/gmxlib/nrnb.h"
56 #include "gromacs/listed_forces/disre.h"
57 #include "gromacs/math/do_fit.h"
58 #include "gromacs/math/functions.h"
59 #include "gromacs/math/vec.h"
60 #include "gromacs/mdlib/force.h"
61 #include "gromacs/mdlib/mdatoms.h"
62 #include "gromacs/mdlib/mdrun.h"
63 #include "gromacs/mdtypes/fcdata.h"
64 #include "gromacs/mdtypes/inputrec.h"
65 #include "gromacs/mdtypes/md_enums.h"
66 #include "gromacs/pbcutil/ishift.h"
67 #include "gromacs/pbcutil/mshift.h"
68 #include "gromacs/pbcutil/pbc.h"
69 #include "gromacs/pbcutil/rmpbc.h"
70 #include "gromacs/topology/index.h"
71 #include "gromacs/topology/mtop_util.h"
72 #include "gromacs/topology/topology.h"
73 #include "gromacs/trajectoryanalysis/topologyinformation.h"
74 #include "gromacs/utility/arraysize.h"
75 #include "gromacs/utility/fatalerror.h"
76 #include "gromacs/utility/futil.h"
77 #include "gromacs/utility/smalloc.h"
84 static t_toppop *top = nullptr;
89 real sumv, averv, maxv;
90 real *aver1, *aver2, *aver_3, *aver_6;
93 static void init5(int n)
103 for (i = 0; (i < ntop); i++)
110 static void add5(int ndr, real viol)
115 for (i = 1; (i < ntop); i++)
117 if (top[i].v < top[mini].v)
122 if (viol > top[mini].v)
129 static void print5(FILE *fp)
133 std::sort(top, top+ntop, [](const t_toppop &a, const t_toppop &b) {return a.v > b.v; }); //reverse sort
134 fprintf(fp, "Index:");
135 for (i = 0; (i < ntop); i++)
137 fprintf(fp, " %6d", top[i].n);
139 fprintf(fp, "\nViol: ");
140 for (i = 0; (i < ntop); i++)
142 fprintf(fp, " %6.3f", top[i].v);
147 static void check_viol(FILE *log,
148 t_ilist *disres, t_iparams forceparams[],
150 t_pbc *pbc, t_graph *g, t_dr_result dr[],
151 int clust_id, int isize, const int index[], real vvindex[],
155 int i, j, nat, n, type, nviol, ndr, label;
156 real rt, mviol, tviol, viol, lam, dvdl, drt;
158 static gmx_bool bFirst = TRUE;
170 forceatoms = disres->iatoms;
171 for (j = 0; (j < isize); j++)
175 nat = interaction_function[F_DISRES].nratoms+1;
176 for (i = 0; (i < disres->nr); )
178 type = forceatoms[i];
180 label = forceparams[type].disres.label;
183 fprintf(debug, "DISRE: ndr = %d, label = %d i=%d, n =%d\n",
188 gmx_fatal(FARGS, "tpr inconsistency. ndr = %d, label = %d\n", ndr, label);
194 while (((i+n) < disres->nr) &&
195 (forceparams[forceatoms[i+n]].disres.label == label));
197 calc_disres_R_6(nullptr, nullptr, n, &forceatoms[i],
198 x, pbc, fcd, nullptr);
200 if (fcd->disres.Rt_6[label] <= 0)
202 gmx_fatal(FARGS, "ndr = %d, rt_6 = %f", ndr, fcd->disres.Rt_6[label]);
205 rt = gmx::invsixthroot(fcd->disres.Rt_6[label]);
206 dr[clust_id].aver1[ndr] += rt;
207 dr[clust_id].aver2[ndr] += gmx::square(rt);
208 drt = 1.0/gmx::power3(rt);
209 dr[clust_id].aver_3[ndr] += drt;
210 dr[clust_id].aver_6[ndr] += fcd->disres.Rt_6[label];
212 snew(fshift, SHIFTS);
213 ta_disres(n, &forceatoms[i], forceparams,
215 pbc, g, lam, &dvdl, nullptr, fcd, nullptr);
217 viol = fcd->disres.sumviol;
224 add5(forceparams[type].disres.label, viol);
231 for (j = 0; (j < isize); j++)
233 if (index[j] == forceparams[type].disres.label)
235 vvindex[j] = gmx::invsixthroot(fcd->disres.Rt_6[label]);
242 dr[clust_id].nv = nviol;
243 dr[clust_id].maxv = mviol;
244 dr[clust_id].sumv = tviol;
245 dr[clust_id].averv = tviol/ndr;
246 dr[clust_id].nframes++;
250 fprintf(stderr, "\nThere are %d restraints and %d pairs\n",
251 ndr, disres->nr/nat);
263 real up1, r, rT3, rT6, viol, violT3, violT6;
266 static void dump_dump(FILE *log, int ndr, t_dr_stats drs[])
268 static const char *core[] = { "All restraints", "Core restraints" };
269 static const char *tp[] = { "linear", "third power", "sixth power" };
270 real viol_tot, viol_max, viol = 0;
275 for (int iCore = 0; iCore < 2; iCore++)
277 bCore = (iCore == 1);
278 for (kkk = 0; (kkk < 3); kkk++)
284 for (i = 0; (i < ndr); i++)
286 if (!bCore || drs[i].bCore)
294 viol = drs[i].violT3;
297 viol = drs[i].violT6;
300 gmx_incons("Dumping violations");
302 viol_max = std::max(viol_max, viol);
311 if ((nrestr > 0) || (bCore && (nrestr < ndr)))
314 fprintf(log, "+++++++ %s ++++++++\n", core[bCore]);
315 fprintf(log, "+++++++ Using %s averaging: ++++++++\n", tp[kkk]);
316 fprintf(log, "Sum of violations: %8.3f nm\n", viol_tot);
319 fprintf(log, "Average violation: %8.3f nm\n", viol_tot/nrestr);
321 fprintf(log, "Largest violation: %8.3f nm\n", viol_max);
322 fprintf(log, "Number of violated restraints: %d/%d\n", nviol, nrestr);
328 static void dump_viol(FILE *log, int ndr, t_dr_stats *drs, gmx_bool bLinear)
332 fprintf(log, "Restr. Core Up1 <r> <rT3> <rT6> <viol><violT3><violT6>\n");
333 for (i = 0; (i < ndr); i++)
335 if (bLinear && (drs[i].viol == 0))
339 fprintf(log, "%6d%5s%8.3f%8.3f%8.3f%8.3f%8.3f%8.3f%8.3f\n",
340 drs[i].index, yesno_names[drs[i].bCore],
341 drs[i].up1, drs[i].r, drs[i].rT3, drs[i].rT6,
342 drs[i].viol, drs[i].violT3, drs[i].violT6);
346 static gmx_bool is_core(int i, int isize, const int index[])
349 gmx_bool bIC = FALSE;
351 for (kk = 0; !bIC && (kk < isize); kk++)
353 bIC = (index[kk] == i);
359 static void dump_stats(FILE *log, int nsteps, int ndr, t_ilist *disres,
360 t_iparams ip[], t_dr_result *dr,
361 int isize, int index[], t_atoms *atoms)
367 fprintf(log, "++++++++++++++ STATISTICS ++++++++++++++++++++++++\n");
370 nra = interaction_function[F_DISRES].nratoms+1;
371 for (i = 0; (i < ndr); i++)
373 /* Search for the appropriate restraint */
374 for (; (j < disres->nr); j += nra)
376 if (ip[disres->iatoms[j]].disres.label == i)
382 drs[i].bCore = is_core(i, isize, index);
383 drs[i].up1 = ip[disres->iatoms[j]].disres.up1;
384 drs[i].r = dr->aver1[i]/nsteps;
385 drs[i].rT3 = gmx::invcbrt(dr->aver_3[i]/nsteps);
386 drs[i].rT6 = gmx::invsixthroot(dr->aver_6[i]/nsteps);
387 drs[i].viol = std::max(0.0, static_cast<double>(drs[i].r-drs[i].up1));
388 drs[i].violT3 = std::max(0.0, static_cast<double>(drs[i].rT3-drs[i].up1));
389 drs[i].violT6 = std::max(0.0, static_cast<double>(drs[i].rT6-drs[i].up1));
392 int j1 = disres->iatoms[j+1];
393 int j2 = disres->iatoms[j+2];
394 atoms->pdbinfo[j1].bfac += drs[i].violT3*5;
395 atoms->pdbinfo[j2].bfac += drs[i].violT3*5;
398 dump_viol(log, ndr, drs, FALSE);
400 fprintf(log, "+++ Sorted by linear averaged violations: +++\n");
401 std::sort(drs, drs+ndr, [](const t_dr_stats &a, const t_dr_stats &b)
402 {return a.viol > b.viol; }); //Reverse sort
403 dump_viol(log, ndr, drs, TRUE);
405 dump_dump(log, ndr, drs);
410 static void dump_clust_stats(FILE *fp, int ndr, t_ilist *disres,
411 t_iparams ip[], t_blocka *clust, t_dr_result dr[],
412 char *clust_name[], int isize, int index[])
414 int i, j, k, nra, mmm = 0;
415 double sumV, maxV, sumVT3, sumVT6, maxVT3, maxVT6;
419 fprintf(fp, "++++++++++++++ STATISTICS ++++++++++++++++++++++\n");
420 fprintf(fp, "Cluster NFrames SumV MaxV SumVT MaxVT SumVS MaxVS\n");
424 for (k = 0; (k < clust->nr); k++)
426 if (dr[k].nframes == 0)
430 if (dr[k].nframes != (clust->index[k+1]-clust->index[k]))
432 gmx_fatal(FARGS, "Inconsistency in cluster %s.\n"
433 "Found %d frames in trajectory rather than the expected %d\n",
434 clust_name[k], dr[k].nframes,
435 clust->index[k+1]-clust->index[k]);
439 gmx_fatal(FARGS, "Inconsistency with cluster %d. Invalid name", k);
442 nra = interaction_function[F_DISRES].nratoms+1;
443 sumV = sumVT3 = sumVT6 = maxV = maxVT3 = maxVT6 = 0;
444 for (i = 0; (i < ndr); i++)
446 /* Search for the appropriate restraint */
447 for (; (j < disres->nr); j += nra)
449 if (ip[disres->iatoms[j]].disres.label == i)
455 drs[i].bCore = is_core(i, isize, index);
456 drs[i].up1 = ip[disres->iatoms[j]].disres.up1;
457 drs[i].r = dr[k].aver1[i]/dr[k].nframes;
458 if ((dr[k].aver_3[i] <= 0) || !std::isfinite(dr[k].aver_3[i]))
460 gmx_fatal(FARGS, "dr[%d].aver_3[%d] = %f", k, i, dr[k].aver_3[i]);
462 drs[i].rT3 = gmx::invcbrt(dr[k].aver_3[i]/dr[k].nframes);
463 drs[i].rT6 = gmx::invsixthroot(dr[k].aver_6[i]/dr[k].nframes);
464 drs[i].viol = std::max(0.0, static_cast<double>(drs[i].r-drs[i].up1));
465 drs[i].violT3 = std::max(0.0, static_cast<double>(drs[i].rT3-drs[i].up1));
466 drs[i].violT6 = std::max(0.0, static_cast<double>(drs[i].rT6-drs[i].up1));
468 sumVT3 += drs[i].violT3;
469 sumVT6 += drs[i].violT6;
470 maxV = std::max(maxV, static_cast<double>(drs[i].viol));
471 maxVT3 = std::max(maxVT3, static_cast<double>(drs[i].violT3));
472 maxVT6 = std::max(maxVT6, static_cast<double>(drs[i].violT6));
474 if (std::strcmp(clust_name[k], "1000") == 0)
478 fprintf(fp, "%-10s%6d%8.3f %8.3f %8.3f %8.3f %8.3f %8.3f\n",
480 dr[k].nframes, sumV, maxV, sumVT3, maxVT3, sumVT6, maxVT6);
487 static void init_dr_res(t_dr_result *dr, int ndr)
489 snew(dr->aver1, ndr+1);
490 snew(dr->aver2, ndr+1);
491 snew(dr->aver_3, ndr+1);
492 snew(dr->aver_6, ndr+1);
500 static void dump_disre_matrix(const char *fn, t_dr_result *dr, int ndr,
501 int nsteps, t_idef *idef, const gmx_mtop_t *mtop,
502 real max_dr, int nlevels, gmx_bool bThird)
506 int n_res, a_offset, mol, a;
507 int i, j, nra, nratoms, tp, ri, rj, index, nlabel, label;
509 real **matrix, *t_res, hi, *w_dr, rav, rviol;
510 t_rgb rlo = { 1, 1, 1 };
511 t_rgb rhi = { 0, 0, 0 };
517 snew(resnr, mtop->natoms);
520 for (const gmx_molblock_t &molb : mtop->molblock)
522 const t_atoms &atoms = mtop->moltype[molb.type].atoms;
523 for (mol = 0; mol < molb.nmol; mol++)
525 for (a = 0; a < atoms.nr; a++)
527 resnr[a_offset + a] = n_res + atoms.atom[a].resind;
530 a_offset += atoms.nr;
535 for (i = 0; (i < n_res); i++)
540 for (i = 0; (i < n_res); i++)
542 snew(matrix[i], n_res);
544 nratoms = interaction_function[F_DISRES].nratoms;
545 nra = (idef->il[F_DISRES].nr/(nratoms+1));
551 for (i = 0; (i < idef->il[F_DISRES].nr); i += nratoms+1)
553 tp = idef->il[F_DISRES].iatoms[i];
554 label = idef->iparams[tp].disres.label;
558 /* Set index pointer */
562 gmx_fatal(FARGS, "nlabel is %d, label = %d", nlabel, label);
566 gmx_fatal(FARGS, "ndr = %d, index = %d", ndr, index);
568 /* Update the weight */
569 w_dr[index] = 1.0/nlabel;
578 printf("nlabel = %d, index = %d, ndr = %d\n", nlabel, index, ndr);
580 for (i = 0; (i < ndr); i++)
582 for (j = ptr[i]; (j < ptr[i+1]); j += nratoms+1)
584 tp = idef->il[F_DISRES].iatoms[j];
585 ai = idef->il[F_DISRES].iatoms[j+1];
586 aj = idef->il[F_DISRES].iatoms[j+2];
592 rav = gmx::invcbrt(dr->aver_3[i]/nsteps);
596 rav = dr->aver1[i]/nsteps;
600 fprintf(debug, "DR %d, atoms %d, %d, distance %g\n", i, ai, aj, rav);
602 rviol = std::max(0.0_real, rav-idef->iparams[tp].disres.up1);
603 matrix[ri][rj] += w_dr[i]*rviol;
604 matrix[rj][ri] += w_dr[i]*rviol;
605 hi = std::max(hi, matrix[ri][rj]);
606 hi = std::max(hi, matrix[rj][ri]);
616 printf("Warning: the maxdr that you have specified (%g) is smaller than\nthe largest value in your simulation (%g)\n", max_dr, hi);
620 printf("Highest level in the matrix will be %g\n", hi);
621 fp = gmx_ffopen(fn, "w");
622 write_xpm(fp, 0, "Distance Violations", "<V> (nm)", "Residue", "Residue",
623 n_res, n_res, t_res, t_res, matrix, 0, hi, rlo, rhi, &nlevels);
627 int gmx_disre(int argc, char *argv[])
629 const char *desc[] = {
630 "[THISMODULE] computes violations of distance restraints.",
631 "The program always",
632 "computes the instantaneous violations rather than time-averaged,",
633 "because this analysis is done from a trajectory file afterwards",
634 "it does not make sense to use time averaging. However,",
635 "the time averaged values per restraint are given in the log file.[PAR]",
636 "An index file may be used to select specific restraints for",
638 "When the optional [TT]-q[tt] flag is given a [REF].pdb[ref] file coloured by the",
639 "amount of average violations.[PAR]",
640 "When the [TT]-c[tt] option is given, an index file will be read",
641 "containing the frames in your trajectory corresponding to the clusters",
642 "(defined in another manner) that you want to analyze. For these clusters",
643 "the program will compute average violations using the third power",
644 "averaging algorithm and print them in the log file."
647 static int nlevels = 20;
648 static real max_dr = 0;
649 static gmx_bool bThird = TRUE;
651 { "-ntop", FALSE, etINT, {&ntop},
652 "Number of large violations that are stored in the log file every step" },
653 { "-maxdr", FALSE, etREAL, {&max_dr},
654 "Maximum distance violation in matrix output. If less than or equal to 0 the maximum will be determined by the data." },
655 { "-nlevels", FALSE, etINT, {&nlevels},
656 "Number of levels in the matrix output" },
657 { "-third", FALSE, etBOOL, {&bThird},
658 "Use inverse third power averaging or linear for matrix output" }
661 FILE *out = nullptr, *aver = nullptr, *numv = nullptr, *maxxv = nullptr, *xvg = nullptr;
669 rvec *x, *xav = nullptr;
674 int *index = nullptr, *ind_fit = nullptr;
676 t_cluster_ndx *clust = nullptr;
677 t_dr_result dr, *dr_clust = nullptr;
679 real *vvindex = nullptr, *w_rls = nullptr;
680 t_pbc pbc, *pbc_null;
683 gmx_output_env_t *oenv;
684 gmx_rmpbc_t gpbc = nullptr;
687 { efTPR, nullptr, nullptr, ffREAD },
688 { efTRX, "-f", nullptr, ffREAD },
689 { efXVG, "-ds", "drsum", ffWRITE },
690 { efXVG, "-da", "draver", ffWRITE },
691 { efXVG, "-dn", "drnum", ffWRITE },
692 { efXVG, "-dm", "drmax", ffWRITE },
693 { efXVG, "-dr", "restr", ffWRITE },
694 { efLOG, "-l", "disres", ffWRITE },
695 { efNDX, nullptr, "viol", ffOPTRD },
696 { efPDB, "-q", "viol", ffOPTWR },
697 { efNDX, "-c", "clust", ffOPTRD },
698 { efXPM, "-x", "matrix", ffOPTWR }
700 #define NFILE asize(fnm)
702 if (!parse_common_args(&argc, argv, PCA_CAN_TIME | PCA_CAN_VIEW,
703 NFILE, fnm, asize(pa), pa, asize(desc), desc, 0, nullptr, &oenv))
708 fplog = ftp2FILE(efLOG, NFILE, fnm, "w");
715 t_inputrec irInstance;
716 t_inputrec *ir = &irInstance;
718 gmx::TopologyInformation topInfo;
719 topInfo.fillFromInputFile(ftp2fn(efTPR, NFILE, fnm));
720 int ntopatoms = topInfo.mtop()->natoms;
722 bPDB = opt2bSet("-q", NFILE, fnm);
725 snew(xav, ntopatoms);
726 snew(ind_fit, ntopatoms);
727 snew(w_rls, ntopatoms);
728 for (kkk = 0; (kkk < ntopatoms); kkk++)
734 atoms = topInfo.copyAtoms();
736 if (atoms->pdbinfo == nullptr)
738 snew(atoms->pdbinfo, atoms->nr);
740 atoms->havePdbInfo = TRUE;
743 gmx_mtop_generate_local_top(*topInfo.mtop(), &top, ir->efep != efepNO);
747 if (ir->ePBC != epbcNONE)
749 if (ir->bPeriodicMols)
755 g = mk_graph(fplog, &top.idef, 0, ntopatoms, FALSE, FALSE);
759 if (ftp2bSet(efNDX, NFILE, fnm))
761 /* TODO: Nothing is written to this file if -c is provided, but it is
763 rd_index(ftp2fn(efNDX, NFILE, fnm), 1, &isize, &index, &grpname);
764 xvg = xvgropen(opt2fn("-dr", NFILE, fnm), "Individual Restraints", "Time (ps)",
766 snew(vvindex, isize);
768 for (i = 0; (i < isize); i++)
772 sprintf(leg[i], "index %d", index[i]);
774 xvgr_legend(xvg, isize, leg, oenv);
782 init_disres(fplog, topInfo.mtop(), ir, nullptr, nullptr, &fcd, nullptr, FALSE);
784 int natoms = read_first_x(oenv, &status, ftp2fn(efTRX, NFILE, fnm), &t, &x, box);
787 init_dr_res(&dr, fcd.disres.nres);
788 if (opt2bSet("-c", NFILE, fnm))
790 clust = cluster_index(fplog, opt2fn("-c", NFILE, fnm));
791 snew(dr_clust, clust->clust->nr+1);
792 for (i = 0; (i <= clust->clust->nr); i++)
794 init_dr_res(&dr_clust[i], fcd.disres.nres);
799 out = xvgropen(opt2fn("-ds", NFILE, fnm),
800 "Sum of Violations", "Time (ps)", "nm", oenv);
801 aver = xvgropen(opt2fn("-da", NFILE, fnm),
802 "Average Violation", "Time (ps)", "nm", oenv);
803 numv = xvgropen(opt2fn("-dn", NFILE, fnm),
804 "# Violations", "Time (ps)", "#", oenv);
805 maxxv = xvgropen(opt2fn("-dm", NFILE, fnm),
806 "Largest Violation", "Time (ps)", "nm", oenv);
809 auto mdAtoms = gmx::makeMDAtoms(fplog, *topInfo.mtop(), *ir, false);
810 atoms2md(topInfo.mtop(), ir, -1, nullptr, ntopatoms, mdAtoms.get());
811 update_mdatoms(mdAtoms->mdatoms(), ir->fepvals->init_lambda);
813 if (ir->ePBC != epbcNONE)
815 gpbc = gmx_rmpbc_init(&top.idef, ir->ePBC, natoms);
821 if (ir->ePBC != epbcNONE)
823 if (ir->bPeriodicMols)
825 set_pbc(&pbc, ir->ePBC, box);
829 gmx_rmpbc(gpbc, natoms, box, x);
835 if (j > clust->maxframe)
837 gmx_fatal(FARGS, "There are more frames in the trajectory than in the cluster index file. t = %8f\n", t);
839 my_clust = clust->inv_clust[j];
840 range_check(my_clust, 0, clust->clust->nr);
841 check_viol(fplog, &(top.idef.il[F_DISRES]),
843 x, f, pbc_null, g, dr_clust, my_clust, isize, index, vvindex, &fcd);
847 check_viol(fplog, &(top.idef.il[F_DISRES]),
849 x, f, pbc_null, g, &dr, 0, isize, index, vvindex, &fcd);
853 reset_x(atoms->nr, ind_fit, atoms->nr, nullptr, x, w_rls);
854 do_fit(atoms->nr, w_rls, x, x);
857 /* Store the first frame of the trajectory as 'characteristic'
858 * for colouring with violations.
860 for (kkk = 0; (kkk < atoms->nr); kkk++)
862 copy_rvec(x[kkk], xav[kkk]);
870 fprintf(xvg, "%10g", t);
871 for (i = 0; (i < isize); i++)
873 fprintf(xvg, " %10g", vvindex[i]);
877 fprintf(out, "%10g %10g\n", t, dr.sumv);
878 fprintf(aver, "%10g %10g\n", t, dr.averv);
879 fprintf(maxxv, "%10g %10g\n", t, dr.maxv);
880 fprintf(numv, "%10g %10d\n", t, dr.nv);
884 while (read_next_x(oenv, status, &t, x, box));
886 if (ir->ePBC != epbcNONE)
888 gmx_rmpbc_done(gpbc);
893 dump_clust_stats(fplog, fcd.disres.nres, &(top.idef.il[F_DISRES]),
894 top.idef.iparams, clust->clust, dr_clust,
895 clust->grpname, isize, index);
899 dump_stats(fplog, j, fcd.disres.nres, &(top.idef.il[F_DISRES]),
900 top.idef.iparams, &dr, isize, index,
901 bPDB ? atoms.get() : nullptr);
904 write_sto_conf(opt2fn("-q", NFILE, fnm),
905 "Coloured by average violation in Angstrom",
906 atoms.get(), xav, nullptr, ir->ePBC, box);
908 dump_disre_matrix(opt2fn_null("-x", NFILE, fnm), &dr, fcd.disres.nres,
909 j, &top.idef, topInfo.mtop(), max_dr, nlevels, bThird);
914 do_view(oenv, opt2fn("-dn", NFILE, fnm), "-nxy");
915 do_view(oenv, opt2fn("-da", NFILE, fnm), "-nxy");
916 do_view(oenv, opt2fn("-ds", NFILE, fnm), "-nxy");
917 do_view(oenv, opt2fn("-dm", NFILE, fnm), "-nxy");
924 do_view(oenv, opt2fn("-dr", NFILE, fnm), "-nxy");