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,2020, 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.
44 #include <unordered_map>
46 #include "gromacs/commandline/pargs.h"
47 #include "gromacs/commandline/viewit.h"
48 #include "gromacs/fileio/confio.h"
49 #include "gromacs/fileio/matio.h"
50 #include "gromacs/fileio/pdbio.h"
51 #include "gromacs/fileio/tpxio.h"
52 #include "gromacs/fileio/trxio.h"
53 #include "gromacs/fileio/xvgr.h"
54 #include "gromacs/gmxana/gmx_ana.h"
55 #include "gromacs/gmxana/gstat.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/mdtypes/fcdata.h"
63 #include "gromacs/mdtypes/inputrec.h"
64 #include "gromacs/mdtypes/md_enums.h"
65 #include "gromacs/pbcutil/ishift.h"
66 #include "gromacs/pbcutil/mshift.h"
67 #include "gromacs/pbcutil/pbc.h"
68 #include "gromacs/pbcutil/rmpbc.h"
69 #include "gromacs/topology/index.h"
70 #include "gromacs/topology/mtop_util.h"
71 #include "gromacs/topology/topology.h"
72 #include "gromacs/trajectoryanalysis/topologyinformation.h"
73 #include "gromacs/utility/arraysize.h"
74 #include "gromacs/utility/fatalerror.h"
75 #include "gromacs/utility/futil.h"
76 #include "gromacs/utility/smalloc.h"
84 static t_toppop* top = nullptr;
90 real sumv, averv, maxv;
91 real *aver1, *aver2, *aver_3, *aver_6;
94 static void init5(int n)
104 for (i = 0; (i < ntop); i++)
111 static void add5(int ndr, real viol)
116 for (i = 1; (i < ntop); i++)
118 if (top[i].v < top[mini].v)
123 if (viol > top[mini].v)
130 static void print5(FILE* fp)
134 std::sort(top, top + ntop, [](const t_toppop& a, const t_toppop& b) { return a.v > b.v; }); // reverse sort
135 fprintf(fp, "Index:");
136 for (i = 0; (i < ntop); i++)
138 fprintf(fp, " %6d", top[i].n);
140 fprintf(fp, "\nViol: ");
141 for (i = 0; (i < ntop); i++)
143 fprintf(fp, " %6.3f", top[i].v);
148 static void check_viol(FILE* log,
150 t_iparams forceparams[],
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 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->nr); 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",
201 i / nat, label, label_old, label_old + 1);
204 // Get offset for label index
205 label_old = forceparams[forceatoms[0]].disres.label;
206 for (i = 0; (i < disres->nr);)
208 type = forceatoms[i];
210 label = forceparams[type].disres.label - label_old;
213 fprintf(debug, "DISRE: ndr = %d, label = %d i=%d, n =%d\n", ndr, label, i, n);
218 } while (((i + n) < disres->nr)
219 && (forceparams[forceatoms[i + n]].disres.label == label + label_old));
221 calc_disres_R_6(nullptr, nullptr, n, &forceatoms[i], x, pbc, fcd, nullptr);
223 if (fcd->disres.Rt_6[label] <= 0)
225 gmx_fatal(FARGS, "ndr = %d, rt_6 = %f", ndr, fcd->disres.Rt_6[label]);
228 rt = gmx::invsixthroot(fcd->disres.Rt_6[label]);
229 dr[clust_id].aver1[ndr] += rt;
230 dr[clust_id].aver2[ndr] += gmx::square(rt);
231 drt = 1.0 / gmx::power3(rt);
232 dr[clust_id].aver_3[ndr] += drt;
233 dr[clust_id].aver_6[ndr] += fcd->disres.Rt_6[label];
235 snew(fshift, SHIFTS);
236 ta_disres(n, &forceatoms[i], forceparams, x, f, fshift, pbc, g, lam, &dvdl, nullptr, fcd, nullptr);
238 viol = fcd->disres.sumviol;
245 add5(forceparams[type].disres.label, viol);
252 for (j = 0; (j < isize); j++)
254 if (index[j] == forceparams[type].disres.label)
256 vvindex[j] = gmx::invsixthroot(fcd->disres.Rt_6[label]);
263 dr[clust_id].nv = nviol;
264 dr[clust_id].maxv = mviol;
265 dr[clust_id].sumv = tviol;
266 dr[clust_id].averv = tviol / ndr;
267 dr[clust_id].nframes++;
271 fprintf(stderr, "\nThere are %d restraints and %d pairs\n", ndr, disres->nr / nat);
284 real up1, r, rT3, rT6, viol, violT3, violT6;
287 static void dump_dump(FILE* log, int ndr, t_dr_stats drs[])
289 static const char* core[] = { "All restraints", "Core restraints" };
290 static const char* tp[] = { "linear", "third power", "sixth power" };
291 real viol_tot, viol_max, viol = 0;
296 for (int iCore = 0; iCore < 2; iCore++)
298 bCore = (iCore == 1);
299 for (kkk = 0; (kkk < 3); kkk++)
305 for (i = 0; (i < ndr); i++)
307 if (!bCore || drs[i].bCore)
311 case 0: viol = drs[i].viol; break;
312 case 1: viol = drs[i].violT3; break;
313 case 2: viol = drs[i].violT6; break;
314 default: gmx_incons("Dumping violations");
316 viol_max = std::max(viol_max, viol);
325 if ((nrestr > 0) || (bCore && (nrestr < ndr)))
328 fprintf(log, "+++++++ %s ++++++++\n", core[bCore]);
329 fprintf(log, "+++++++ Using %s averaging: ++++++++\n", tp[kkk]);
330 fprintf(log, "Sum of violations: %8.3f nm\n", viol_tot);
333 fprintf(log, "Average violation: %8.3f nm\n", viol_tot / nrestr);
335 fprintf(log, "Largest violation: %8.3f nm\n", viol_max);
336 fprintf(log, "Number of violated restraints: %d/%d\n", nviol, nrestr);
342 static void dump_viol(FILE* log, int ndr, t_dr_stats* drs, gmx_bool bLinear)
346 fprintf(log, "Restr. Core Up1 <r> <rT3> <rT6> <viol><violT3><violT6>\n");
347 for (i = 0; (i < ndr); i++)
349 if (bLinear && (drs[i].viol == 0))
353 fprintf(log, "%6d%5s%8.3f%8.3f%8.3f%8.3f%8.3f%8.3f%8.3f\n", drs[i].label,
354 yesno_names[drs[i].bCore], drs[i].up1, drs[i].r, drs[i].rT3, drs[i].rT6,
355 drs[i].viol, drs[i].violT3, drs[i].violT6);
359 static gmx_bool is_core(int i, int isize, const int index[])
362 gmx_bool bIC = FALSE;
364 for (kk = 0; !bIC && (kk < isize); kk++)
366 bIC = (index[kk] == i);
372 static void dump_stats(FILE* log,
374 const t_disresdata& dd,
375 const t_ilist* disres,
385 fprintf(log, "++++++++++++++ STATISTICS ++++++++++++++++++++++++\n");
387 const int nra = interaction_function[F_DISRES].nratoms + 1;
388 for (int j = 0; j < disres->nr; j += nra)
390 // Note that the restraint i can be used by multiple pairs
391 const int i = disres->iatoms[j] - dd.type_min;
392 GMX_RELEASE_ASSERT(i >= 0 && i < dd.nres, "The restraint index should be in range");
394 drs[i].label = ip[disres->iatoms[j]].disres.label;
395 drs[i].bCore = is_core(drs[i].label, isize, index);
396 drs[i].up1 = ip[disres->iatoms[j]].disres.up1;
397 drs[i].r = dr->aver1[i] / nsteps;
398 drs[i].rT3 = gmx::invcbrt(dr->aver_3[i] / nsteps);
399 drs[i].rT6 = gmx::invsixthroot(dr->aver_6[i] / nsteps);
400 drs[i].viol = std::max(0.0, static_cast<double>(drs[i].r - drs[i].up1));
401 drs[i].violT3 = std::max(0.0, static_cast<double>(drs[i].rT3 - drs[i].up1));
402 drs[i].violT6 = std::max(0.0, static_cast<double>(drs[i].rT6 - drs[i].up1));
405 int j1 = disres->iatoms[j + 1];
406 int j2 = disres->iatoms[j + 2];
407 atoms->pdbinfo[j1].bfac += drs[i].violT3 * 5;
408 atoms->pdbinfo[j2].bfac += drs[i].violT3 * 5;
411 dump_viol(log, dd.nres, drs, FALSE);
413 fprintf(log, "+++ Sorted by linear averaged violations: +++\n");
414 std::sort(drs, drs + dd.nres,
415 [](const t_dr_stats& a, const t_dr_stats& b) { return a.viol > b.viol; }); // Reverse sort
416 dump_viol(log, dd.nres, drs, TRUE);
418 dump_dump(log, dd.nres, drs);
423 static void dump_clust_stats(FILE* fp,
424 const t_disresdata& dd,
425 const t_ilist* disres,
434 double sumV, maxV, sumVT3, sumVT6, maxVT3, maxVT6;
438 fprintf(fp, "++++++++++++++ STATISTICS ++++++++++++++++++++++\n");
439 fprintf(fp, "Cluster NFrames SumV MaxV SumVT MaxVT SumVS MaxVS\n");
443 for (k = 0; (k < clust->nr); k++)
445 if (dr[k].nframes == 0)
449 if (dr[k].nframes != (clust->index[k + 1] - clust->index[k]))
452 "Inconsistency in cluster %s.\n"
453 "Found %d frames in trajectory rather than the expected %d\n",
454 clust_name[k], dr[k].nframes, clust->index[k + 1] - clust->index[k]);
458 gmx_fatal(FARGS, "Inconsistency with cluster %d. Invalid name", k);
460 nra = interaction_function[F_DISRES].nratoms + 1;
461 sumV = sumVT3 = sumVT6 = maxV = maxVT3 = maxVT6 = 0;
463 // Use a map to process each restraint only once while looping over all pairs
464 std::unordered_map<int, bool> restraintHasBeenProcessed;
465 for (int j = 0; j < dd.nres; j += nra)
467 // Note that the restraint i can be used by multiple pairs
468 const int i = disres->iatoms[j] - dd.type_min;
470 if (restraintHasBeenProcessed[i])
475 drs[i].label = ip[disres->iatoms[j]].disres.label;
476 drs[i].bCore = is_core(drs[i].label, isize, index);
477 drs[i].up1 = ip[disres->iatoms[j]].disres.up1;
478 drs[i].r = dr[k].aver1[i] / dr[k].nframes;
479 if ((dr[k].aver_3[i] <= 0) || !std::isfinite(dr[k].aver_3[i]))
481 gmx_fatal(FARGS, "dr[%d].aver_3[%d] = %f", k, i, dr[k].aver_3[i]);
483 drs[i].rT3 = gmx::invcbrt(dr[k].aver_3[i] / dr[k].nframes);
484 drs[i].rT6 = gmx::invsixthroot(dr[k].aver_6[i] / dr[k].nframes);
485 drs[i].viol = std::max(0.0, static_cast<double>(drs[i].r - drs[i].up1));
486 drs[i].violT3 = std::max(0.0, static_cast<double>(drs[i].rT3 - drs[i].up1));
487 drs[i].violT6 = std::max(0.0, static_cast<double>(drs[i].rT6 - drs[i].up1));
489 sumVT3 += drs[i].violT3;
490 sumVT6 += drs[i].violT6;
491 maxV = std::max(maxV, static_cast<double>(drs[i].viol));
492 maxVT3 = std::max(maxVT3, static_cast<double>(drs[i].violT3));
493 maxVT6 = std::max(maxVT6, static_cast<double>(drs[i].violT6));
495 // We have processed restraint i, mark it as such
496 restraintHasBeenProcessed[i] = true;
498 if (std::strcmp(clust_name[k], "1000") == 0)
502 fprintf(fp, "%-10s%6d%8.3f %8.3f %8.3f %8.3f %8.3f %8.3f\n", clust_name[k],
503 dr[k].nframes, sumV, maxV, sumVT3, maxVT3, sumVT6, maxVT6);
509 static void init_dr_res(t_dr_result* dr, int ndr)
511 snew(dr->aver1, ndr + 1);
512 snew(dr->aver2, ndr + 1);
513 snew(dr->aver_3, ndr + 1);
514 snew(dr->aver_6, ndr + 1);
522 static void dump_disre_matrix(const char* fn,
527 const gmx_mtop_t* mtop,
534 int n_res, a_offset, mol, a;
535 int i, j, nra, nratoms, tp, ri, rj, index, nlabel, label;
537 real **matrix, *t_res, hi, *w_dr, rav, rviol;
538 t_rgb rlo = { 1, 1, 1 };
539 t_rgb rhi = { 0, 0, 0 };
545 snew(resnr, mtop->natoms);
548 for (const gmx_molblock_t& molb : mtop->molblock)
550 const t_atoms& atoms = mtop->moltype[molb.type].atoms;
551 for (mol = 0; mol < molb.nmol; mol++)
553 for (a = 0; a < atoms.nr; a++)
555 resnr[a_offset + a] = n_res + atoms.atom[a].resind;
558 a_offset += atoms.nr;
563 for (i = 0; (i < n_res); i++)
568 for (i = 0; (i < n_res); i++)
570 snew(matrix[i], n_res);
572 nratoms = interaction_function[F_DISRES].nratoms;
573 nra = (idef->il[F_DISRES].nr / (nratoms + 1));
579 for (i = 0; (i < idef->il[F_DISRES].nr); i += nratoms + 1)
581 tp = idef->il[F_DISRES].iatoms[i];
582 label = idef->iparams[tp].disres.label;
586 /* Set index pointer */
590 gmx_fatal(FARGS, "nlabel is %d, label = %d", nlabel, label);
594 gmx_fatal(FARGS, "ndr = %d, index = %d", ndr, index);
596 /* Update the weight */
597 w_dr[index] = 1.0 / nlabel;
606 printf("nlabel = %d, index = %d, ndr = %d\n", nlabel, index, ndr);
608 for (i = 0; (i < ndr); i++)
610 for (j = ptr[i]; (j < ptr[i + 1]); j += nratoms + 1)
612 tp = idef->il[F_DISRES].iatoms[j];
613 ai = idef->il[F_DISRES].iatoms[j + 1];
614 aj = idef->il[F_DISRES].iatoms[j + 2];
620 rav = gmx::invcbrt(dr->aver_3[i] / nsteps);
624 rav = dr->aver1[i] / nsteps;
628 fprintf(debug, "DR %d, atoms %d, %d, distance %g\n", i, ai, aj, rav);
630 rviol = std::max(0.0_real, rav - idef->iparams[tp].disres.up1);
631 matrix[ri][rj] += w_dr[i] * rviol;
632 matrix[rj][ri] += w_dr[i] * rviol;
633 hi = std::max(hi, matrix[ri][rj]);
634 hi = std::max(hi, matrix[rj][ri]);
644 printf("Warning: the maxdr that you have specified (%g) is smaller than\nthe largest "
645 "value in your simulation (%g)\n",
650 printf("Highest level in the matrix will be %g\n", hi);
651 fp = gmx_ffopen(fn, "w");
652 write_xpm(fp, 0, "Distance Violations", "<V> (nm)", "Residue", "Residue", n_res, n_res, t_res,
653 t_res, matrix, 0, hi, rlo, rhi, &nlevels);
657 int gmx_disre(int argc, char* argv[])
659 const char* desc[] = {
660 "[THISMODULE] computes violations of distance restraints.",
661 "The program always",
662 "computes the instantaneous violations rather than time-averaged,",
663 "because this analysis is done from a trajectory file afterwards",
664 "it does not make sense to use time averaging. However,",
665 "the time averaged values per restraint are given in the log file.[PAR]",
666 "An index file may be used to select specific restraints by index group label for",
668 "When the optional [TT]-q[tt] flag is given a [REF].pdb[ref] file coloured by the",
669 "amount of average violations.[PAR]",
670 "When the [TT]-c[tt] option is given, an index file will be read",
671 "containing the frames in your trajectory corresponding to the clusters",
672 "(defined in another manner) that you want to analyze. For these clusters",
673 "the program will compute average violations using the third power",
674 "averaging algorithm and print them in the log file."
677 static int nlevels = 20;
678 static real max_dr = 0;
679 static gmx_bool bThird = TRUE;
685 "Number of large violations that are stored in the log file every step" },
690 "Maximum distance violation in matrix output. If less than or equal to 0 the "
691 "maximum will be determined by the data." },
692 { "-nlevels", FALSE, etINT, { &nlevels }, "Number of levels in the matrix output" },
697 "Use inverse third power averaging or linear for matrix output" }
700 FILE *out = nullptr, *aver = nullptr, *numv = nullptr, *maxxv = nullptr, *xvg = nullptr;
707 rvec * x, *xav = nullptr;
712 int * index = nullptr, *ind_fit = nullptr;
714 t_cluster_ndx* clust = nullptr;
715 t_dr_result dr, *dr_clust = nullptr;
717 real * vvindex = nullptr, *w_rls = nullptr;
718 t_pbc pbc, *pbc_null;
721 gmx_output_env_t* oenv;
722 gmx_rmpbc_t gpbc = nullptr;
724 t_filenm fnm[] = { { efTPR, nullptr, nullptr, ffREAD }, { efTRX, "-f", nullptr, ffREAD },
725 { efXVG, "-ds", "drsum", ffWRITE }, { efXVG, "-da", "draver", ffWRITE },
726 { efXVG, "-dn", "drnum", ffWRITE }, { efXVG, "-dm", "drmax", ffWRITE },
727 { efXVG, "-dr", "restr", ffWRITE }, { efLOG, "-l", "disres", ffWRITE },
728 { efNDX, nullptr, "viol", ffOPTRD }, { efPDB, "-q", "viol", ffOPTWR },
729 { efNDX, "-c", "clust", ffOPTRD }, { efXPM, "-x", "matrix", ffOPTWR } };
730 #define NFILE asize(fnm)
732 if (!parse_common_args(&argc, argv, PCA_CAN_TIME | PCA_CAN_VIEW, NFILE, fnm, asize(pa), pa,
733 asize(desc), desc, 0, nullptr, &oenv))
738 fplog = ftp2FILE(efLOG, NFILE, fnm, "w");
745 t_inputrec irInstance;
746 t_inputrec* ir = &irInstance;
748 gmx::TopologyInformation topInfo;
749 topInfo.fillFromInputFile(ftp2fn(efTPR, NFILE, fnm));
750 int ntopatoms = topInfo.mtop()->natoms;
752 bPDB = opt2bSet("-q", NFILE, fnm);
755 snew(xav, ntopatoms);
756 snew(ind_fit, ntopatoms);
757 snew(w_rls, ntopatoms);
758 for (kkk = 0; (kkk < ntopatoms); kkk++)
764 atoms = topInfo.copyAtoms();
766 if (atoms->pdbinfo == nullptr)
768 snew(atoms->pdbinfo, atoms->nr);
770 atoms->havePdbInfo = TRUE;
773 gmx_mtop_generate_local_top(*topInfo.mtop(), &top, ir->efep != efepNO);
777 if (ir->ePBC != epbcNONE)
779 if (ir->bPeriodicMols)
785 g = mk_graph(fplog, &top.idef, 0, ntopatoms, FALSE, FALSE);
789 if (ftp2bSet(efNDX, NFILE, fnm))
791 /* TODO: Nothing is written to this file if -c is provided, but it is
793 rd_index(ftp2fn(efNDX, NFILE, fnm), 1, &isize, &index, &grpname);
794 xvg = xvgropen(opt2fn("-dr", NFILE, fnm), "Individual Restraints", "Time (ps)", "nm", oenv);
795 snew(vvindex, isize);
797 for (i = 0; (i < isize); i++)
801 sprintf(leg[i], "index %d", index[i]);
803 xvgr_legend(xvg, isize, leg, oenv);
811 init_disres(fplog, topInfo.mtop(), ir, nullptr, nullptr, &fcd, nullptr, FALSE);
813 int natoms = read_first_x(oenv, &status, ftp2fn(efTRX, NFILE, fnm), &t, &x, box);
816 init_dr_res(&dr, fcd.disres.nres);
817 if (opt2bSet("-c", NFILE, fnm))
819 clust = cluster_index(fplog, opt2fn("-c", NFILE, fnm));
820 snew(dr_clust, clust->clust->nr + 1);
821 for (i = 0; (i <= clust->clust->nr); i++)
823 init_dr_res(&dr_clust[i], fcd.disres.nres);
828 out = xvgropen(opt2fn("-ds", NFILE, fnm), "Sum of Violations", "Time (ps)", "nm", oenv);
829 aver = xvgropen(opt2fn("-da", NFILE, fnm), "Average Violation", "Time (ps)", "nm", oenv);
830 numv = xvgropen(opt2fn("-dn", NFILE, fnm), "# Violations", "Time (ps)", "#", oenv);
831 maxxv = xvgropen(opt2fn("-dm", NFILE, fnm), "Largest Violation", "Time (ps)", "nm", oenv);
834 auto mdAtoms = gmx::makeMDAtoms(fplog, *topInfo.mtop(), *ir, false);
835 atoms2md(topInfo.mtop(), ir, -1, nullptr, ntopatoms, mdAtoms.get());
836 update_mdatoms(mdAtoms->mdatoms(), ir->fepvals->init_lambda);
837 if (ir->ePBC != epbcNONE)
839 gpbc = gmx_rmpbc_init(&top.idef, ir->ePBC, natoms);
845 if (ir->ePBC != epbcNONE)
847 if (ir->bPeriodicMols)
849 set_pbc(&pbc, ir->ePBC, box);
853 gmx_rmpbc(gpbc, natoms, box, x);
859 if (j > clust->maxframe)
862 "There are more frames in the trajectory than in the cluster index file. "
866 my_clust = clust->inv_clust[j];
867 range_check(my_clust, 0, clust->clust->nr);
868 check_viol(fplog, &(top.idef.il[F_DISRES]), top.idef.iparams, x, f, pbc_null, g,
869 dr_clust, my_clust, isize, index, vvindex, &fcd);
873 check_viol(fplog, &(top.idef.il[F_DISRES]), top.idef.iparams, x, f, pbc_null, g, &dr, 0,
874 isize, index, vvindex, &fcd);
878 reset_x(atoms->nr, ind_fit, atoms->nr, nullptr, x, w_rls);
879 do_fit(atoms->nr, w_rls, x, x);
882 /* Store the first frame of the trajectory as 'characteristic'
883 * for colouring with violations.
885 for (kkk = 0; (kkk < atoms->nr); kkk++)
887 copy_rvec(x[kkk], xav[kkk]);
895 fprintf(xvg, "%10g", t);
896 for (i = 0; (i < isize); i++)
898 fprintf(xvg, " %10g", vvindex[i]);
902 fprintf(out, "%10g %10g\n", t, dr.sumv);
903 fprintf(aver, "%10g %10g\n", t, dr.averv);
904 fprintf(maxxv, "%10g %10g\n", t, dr.maxv);
905 fprintf(numv, "%10g %10d\n", t, dr.nv);
908 } while (read_next_x(oenv, status, &t, x, box));
910 if (ir->ePBC != epbcNONE)
912 gmx_rmpbc_done(gpbc);
917 dump_clust_stats(fplog, fcd.disres, &(top.idef.il[F_DISRES]), top.idef.iparams,
918 clust->clust, dr_clust, clust->grpname, isize, index);
922 dump_stats(fplog, j, fcd.disres, &(top.idef.il[F_DISRES]), top.idef.iparams, &dr, isize,
923 index, bPDB ? atoms.get() : nullptr);
926 write_sto_conf(opt2fn("-q", NFILE, fnm), "Coloured by average violation in Angstrom",
927 atoms.get(), xav, nullptr, ir->ePBC, box);
929 dump_disre_matrix(opt2fn_null("-x", NFILE, fnm), &dr, fcd.disres.nres, j, &top.idef,
930 topInfo.mtop(), max_dr, nlevels, bThird);
935 do_view(oenv, opt2fn("-dn", NFILE, fnm), "-nxy");
936 do_view(oenv, opt2fn("-da", NFILE, fnm), "-nxy");
937 do_view(oenv, opt2fn("-ds", NFILE, fnm), "-nxy");
938 do_view(oenv, opt2fn("-dm", NFILE, fnm), "-nxy");
945 do_view(oenv, opt2fn("-dr", NFILE, fnm), "-nxy");