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,
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",
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.size());)
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.size())
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.data(), x, f, fshift, pbc, lam, &dvdl, nullptr,
239 viol = fcd->disres.sumviol;
246 add5(forceparams[type].disres.label, viol);
253 for (j = 0; (j < isize); j++)
255 if (index[j] == forceparams[type].disres.label)
257 vvindex[j] = gmx::invsixthroot(fcd->disres.Rt_6[label]);
264 dr[clust_id].nv = nviol;
265 dr[clust_id].maxv = mviol;
266 dr[clust_id].sumv = tviol;
267 dr[clust_id].averv = tviol / ndr;
268 dr[clust_id].nframes++;
272 fprintf(stderr, "\nThere are %d restraints and %d pairs\n", ndr, disres.size() / nat);
285 real up1, r, rT3, rT6, viol, violT3, violT6;
288 static void dump_dump(FILE* log, int ndr, t_dr_stats drs[])
290 static const char* core[] = { "All restraints", "Core restraints" };
291 static const char* tp[] = { "linear", "third power", "sixth power" };
292 real viol_tot, viol_max, viol = 0;
297 for (int iCore = 0; iCore < 2; iCore++)
299 bCore = (iCore == 1);
300 for (kkk = 0; (kkk < 3); kkk++)
306 for (i = 0; (i < ndr); i++)
308 if (!bCore || drs[i].bCore)
312 case 0: viol = drs[i].viol; break;
313 case 1: viol = drs[i].violT3; break;
314 case 2: viol = drs[i].violT6; break;
315 default: gmx_incons("Dumping violations");
317 viol_max = std::max(viol_max, viol);
326 if ((nrestr > 0) || (bCore && (nrestr < ndr)))
329 fprintf(log, "+++++++ %s ++++++++\n", core[bCore]);
330 fprintf(log, "+++++++ Using %s averaging: ++++++++\n", tp[kkk]);
331 fprintf(log, "Sum of violations: %8.3f nm\n", viol_tot);
334 fprintf(log, "Average violation: %8.3f nm\n", viol_tot / nrestr);
336 fprintf(log, "Largest violation: %8.3f nm\n", viol_max);
337 fprintf(log, "Number of violated restraints: %d/%d\n", nviol, nrestr);
343 static void dump_viol(FILE* log, int ndr, t_dr_stats* drs, gmx_bool bLinear)
347 fprintf(log, "Restr. Core Up1 <r> <rT3> <rT6> <viol><violT3><violT6>\n");
348 for (i = 0; (i < ndr); i++)
350 if (bLinear && (drs[i].viol == 0))
354 fprintf(log, "%6d%5s%8.3f%8.3f%8.3f%8.3f%8.3f%8.3f%8.3f\n", drs[i].label,
355 yesno_names[drs[i].bCore], drs[i].up1, drs[i].r, drs[i].rT3, drs[i].rT6,
356 drs[i].viol, drs[i].violT3, drs[i].violT6);
360 static gmx_bool is_core(int i, int isize, const int index[])
363 gmx_bool bIC = FALSE;
365 for (kk = 0; !bIC && (kk < isize); kk++)
367 bIC = (index[kk] == i);
373 static void dump_stats(FILE* log,
375 const t_disresdata& dd,
376 const InteractionList& disres,
377 gmx::ArrayRef<const t_iparams> ip,
386 fprintf(log, "++++++++++++++ STATISTICS ++++++++++++++++++++++++\n");
388 const int nra = interaction_function[F_DISRES].nratoms + 1;
389 for (int j = 0; j < disres.size(); j += nra)
391 // Note that the restraint i can be used by multiple pairs
392 const int i = disres.iatoms[j] - dd.type_min;
393 GMX_RELEASE_ASSERT(i >= 0 && i < dd.nres, "The restraint index should be in range");
395 drs[i].label = ip[disres.iatoms[j]].disres.label;
396 drs[i].bCore = is_core(drs[i].label, isize, index);
397 drs[i].up1 = ip[disres.iatoms[j]].disres.up1;
398 drs[i].r = dr->aver1[i] / nsteps;
399 drs[i].rT3 = gmx::invcbrt(dr->aver_3[i] / nsteps);
400 drs[i].rT6 = gmx::invsixthroot(dr->aver_6[i] / nsteps);
401 drs[i].viol = std::max(0.0, static_cast<double>(drs[i].r - drs[i].up1));
402 drs[i].violT3 = std::max(0.0, static_cast<double>(drs[i].rT3 - drs[i].up1));
403 drs[i].violT6 = std::max(0.0, static_cast<double>(drs[i].rT6 - drs[i].up1));
406 int j1 = disres.iatoms[j + 1];
407 int j2 = disres.iatoms[j + 2];
408 atoms->pdbinfo[j1].bfac += drs[i].violT3 * 5;
409 atoms->pdbinfo[j2].bfac += drs[i].violT3 * 5;
412 dump_viol(log, dd.nres, drs, FALSE);
414 fprintf(log, "+++ Sorted by linear averaged violations: +++\n");
415 std::sort(drs, drs + dd.nres,
416 [](const t_dr_stats& a, const t_dr_stats& b) { return a.viol > b.viol; }); // Reverse sort
417 dump_viol(log, dd.nres, drs, TRUE);
419 dump_dump(log, dd.nres, drs);
424 static void dump_clust_stats(FILE* fp,
425 const t_disresdata& dd,
426 const InteractionList& disres,
427 gmx::ArrayRef<const t_iparams> ip,
435 double sumV, maxV, sumVT3, sumVT6, maxVT3, maxVT6;
439 fprintf(fp, "++++++++++++++ STATISTICS ++++++++++++++++++++++\n");
440 fprintf(fp, "Cluster NFrames SumV MaxV SumVT MaxVT SumVS MaxVS\n");
444 for (k = 0; (k < clust->nr); k++)
446 if (dr[k].nframes == 0)
450 if (dr[k].nframes != (clust->index[k + 1] - clust->index[k]))
453 "Inconsistency in cluster %s.\n"
454 "Found %d frames in trajectory rather than the expected %d\n",
455 clust_name[k], dr[k].nframes, clust->index[k + 1] - clust->index[k]);
459 gmx_fatal(FARGS, "Inconsistency with cluster %d. Invalid name", k);
461 nra = interaction_function[F_DISRES].nratoms + 1;
462 sumV = sumVT3 = sumVT6 = maxV = maxVT3 = maxVT6 = 0;
464 // Use a map to process each restraint only once while looping over all pairs
465 std::unordered_map<int, bool> restraintHasBeenProcessed;
466 for (int j = 0; j < dd.nres; j += nra)
468 // Note that the restraint i can be used by multiple pairs
469 const int i = disres.iatoms[j] - dd.type_min;
471 if (restraintHasBeenProcessed[i])
476 drs[i].label = ip[disres.iatoms[j]].disres.label;
477 drs[i].bCore = is_core(drs[i].label, isize, index);
478 drs[i].up1 = ip[disres.iatoms[j]].disres.up1;
479 drs[i].r = dr[k].aver1[i] / dr[k].nframes;
480 if ((dr[k].aver_3[i] <= 0) || !std::isfinite(dr[k].aver_3[i]))
482 gmx_fatal(FARGS, "dr[%d].aver_3[%d] = %f", k, i, dr[k].aver_3[i]);
484 drs[i].rT3 = gmx::invcbrt(dr[k].aver_3[i] / dr[k].nframes);
485 drs[i].rT6 = gmx::invsixthroot(dr[k].aver_6[i] / dr[k].nframes);
486 drs[i].viol = std::max(0.0, static_cast<double>(drs[i].r - drs[i].up1));
487 drs[i].violT3 = std::max(0.0, static_cast<double>(drs[i].rT3 - drs[i].up1));
488 drs[i].violT6 = std::max(0.0, static_cast<double>(drs[i].rT6 - drs[i].up1));
490 sumVT3 += drs[i].violT3;
491 sumVT6 += drs[i].violT6;
492 maxV = std::max(maxV, static_cast<double>(drs[i].viol));
493 maxVT3 = std::max(maxVT3, static_cast<double>(drs[i].violT3));
494 maxVT6 = std::max(maxVT6, static_cast<double>(drs[i].violT6));
496 // We have processed restraint i, mark it as such
497 restraintHasBeenProcessed[i] = true;
499 if (std::strcmp(clust_name[k], "1000") == 0)
503 fprintf(fp, "%-10s%6d%8.3f %8.3f %8.3f %8.3f %8.3f %8.3f\n", clust_name[k],
504 dr[k].nframes, sumV, maxV, sumVT3, maxVT3, sumVT6, maxVT6);
510 static void init_dr_res(t_dr_result* dr, int ndr)
512 snew(dr->aver1, ndr + 1);
513 snew(dr->aver2, ndr + 1);
514 snew(dr->aver_3, ndr + 1);
515 snew(dr->aver_6, ndr + 1);
523 static void dump_disre_matrix(const char* fn,
527 const InteractionDefinitions& idef,
528 const gmx_mtop_t* mtop,
535 int n_res, a_offset, mol, a;
536 int i, j, nra, nratoms, tp, ri, rj, index, nlabel, label;
538 real **matrix, *t_res, hi, *w_dr, rav, rviol;
539 t_rgb rlo = { 1, 1, 1 };
540 t_rgb rhi = { 0, 0, 0 };
546 snew(resnr, mtop->natoms);
549 for (const gmx_molblock_t& molb : mtop->molblock)
551 const t_atoms& atoms = mtop->moltype[molb.type].atoms;
552 for (mol = 0; mol < molb.nmol; mol++)
554 for (a = 0; a < atoms.nr; a++)
556 resnr[a_offset + a] = n_res + atoms.atom[a].resind;
559 a_offset += atoms.nr;
564 for (i = 0; (i < n_res); i++)
569 for (i = 0; (i < n_res); i++)
571 snew(matrix[i], n_res);
573 nratoms = interaction_function[F_DISRES].nratoms;
574 nra = (idef.il[F_DISRES].size() / (nratoms + 1));
580 for (i = 0; (i < idef.il[F_DISRES].size()); i += nratoms + 1)
582 tp = idef.il[F_DISRES].iatoms[i];
583 label = idef.iparams[tp].disres.label;
587 /* Set index pointer */
591 gmx_fatal(FARGS, "nlabel is %d, label = %d", nlabel, label);
595 gmx_fatal(FARGS, "ndr = %d, index = %d", ndr, index);
597 /* Update the weight */
598 w_dr[index] = 1.0 / nlabel;
607 printf("nlabel = %d, index = %d, ndr = %d\n", nlabel, index, ndr);
609 for (i = 0; (i < ndr); i++)
611 for (j = ptr[i]; (j < ptr[i + 1]); j += nratoms + 1)
613 tp = idef.il[F_DISRES].iatoms[j];
614 ai = idef.il[F_DISRES].iatoms[j + 1];
615 aj = idef.il[F_DISRES].iatoms[j + 2];
621 rav = gmx::invcbrt(dr->aver_3[i] / nsteps);
625 rav = dr->aver1[i] / nsteps;
629 fprintf(debug, "DR %d, atoms %d, %d, distance %g\n", i, ai, aj, rav);
631 rviol = std::max(0.0_real, rav - idef.iparams[tp].disres.up1);
632 matrix[ri][rj] += w_dr[i] * rviol;
633 matrix[rj][ri] += w_dr[i] * rviol;
634 hi = std::max(hi, matrix[ri][rj]);
635 hi = std::max(hi, matrix[rj][ri]);
645 printf("Warning: the maxdr that you have specified (%g) is smaller than\nthe largest "
646 "value in your simulation (%g)\n",
651 printf("Highest level in the matrix will be %g\n", hi);
652 fp = gmx_ffopen(fn, "w");
653 write_xpm(fp, 0, "Distance Violations", "<V> (nm)", "Residue", "Residue", n_res, n_res, t_res,
654 t_res, matrix, 0, hi, rlo, rhi, &nlevels);
658 int gmx_disre(int argc, char* argv[])
660 const char* desc[] = {
661 "[THISMODULE] computes violations of distance restraints.",
662 "The program always",
663 "computes the instantaneous violations rather than time-averaged,",
664 "because this analysis is done from a trajectory file afterwards",
665 "it does not make sense to use time averaging. However,",
666 "the time averaged values per restraint are given in the log file.[PAR]",
667 "An index file may be used to select specific restraints by index group label for",
669 "When the optional [TT]-q[tt] flag is given a [REF].pdb[ref] file coloured by the",
670 "amount of average violations.[PAR]",
671 "When the [TT]-c[tt] option is given, an index file will be read",
672 "containing the frames in your trajectory corresponding to the clusters",
673 "(defined in another manner) that you want to analyze. For these clusters",
674 "the program will compute average violations using the third power",
675 "averaging algorithm and print them in the log file."
678 static int nlevels = 20;
679 static real max_dr = 0;
680 static gmx_bool bThird = TRUE;
686 "Number of large violations that are stored in the log file every step" },
691 "Maximum distance violation in matrix output. If less than or equal to 0 the "
692 "maximum will be determined by the data." },
693 { "-nlevels", FALSE, etINT, { &nlevels }, "Number of levels in the matrix output" },
698 "Use inverse third power averaging or linear for matrix output" }
701 FILE * out = nullptr, *aver = nullptr, *numv = nullptr, *maxxv = nullptr, *xvg = nullptr;
706 rvec * x, *xav = nullptr;
711 int * index = nullptr, *ind_fit = nullptr;
713 t_cluster_ndx* clust = nullptr;
714 t_dr_result dr, *dr_clust = nullptr;
716 real * vvindex = nullptr, *w_rls = nullptr;
717 t_pbc pbc, *pbc_null;
720 gmx_output_env_t* oenv;
721 gmx_rmpbc_t gpbc = nullptr;
723 t_filenm fnm[] = { { efTPR, nullptr, nullptr, ffREAD }, { efTRX, "-f", nullptr, ffREAD },
724 { efXVG, "-ds", "drsum", ffWRITE }, { efXVG, "-da", "draver", ffWRITE },
725 { efXVG, "-dn", "drnum", ffWRITE }, { efXVG, "-dm", "drmax", ffWRITE },
726 { efXVG, "-dr", "restr", ffWRITE }, { efLOG, "-l", "disres", ffWRITE },
727 { efNDX, nullptr, "viol", ffOPTRD }, { efPDB, "-q", "viol", ffOPTWR },
728 { efNDX, "-c", "clust", ffOPTRD }, { efXPM, "-x", "matrix", ffOPTWR } };
729 #define NFILE asize(fnm)
731 if (!parse_common_args(&argc, argv, PCA_CAN_TIME | PCA_CAN_VIEW, NFILE, fnm, asize(pa), pa,
732 asize(desc), desc, 0, nullptr, &oenv))
737 fplog = ftp2FILE(efLOG, NFILE, fnm, "w");
744 t_inputrec irInstance;
745 t_inputrec* ir = &irInstance;
747 gmx::TopologyInformation topInfo;
748 topInfo.fillFromInputFile(ftp2fn(efTPR, NFILE, fnm));
749 int ntopatoms = topInfo.mtop()->natoms;
751 bPDB = opt2bSet("-q", NFILE, fnm);
754 snew(xav, ntopatoms);
755 snew(ind_fit, ntopatoms);
756 snew(w_rls, ntopatoms);
757 for (kkk = 0; (kkk < ntopatoms); kkk++)
763 atoms = topInfo.copyAtoms();
765 if (atoms->pdbinfo == nullptr)
767 snew(atoms->pdbinfo, atoms->nr);
769 atoms->havePdbInfo = TRUE;
772 gmx_localtop_t top(topInfo.mtop()->ffparams);
773 gmx_mtop_generate_local_top(*topInfo.mtop(), &top, ir->efep != efepNO);
776 if (ir->pbcType != PbcType::No)
781 if (ftp2bSet(efNDX, NFILE, fnm))
783 /* TODO: Nothing is written to this file if -c is provided, but it is
785 rd_index(ftp2fn(efNDX, NFILE, fnm), 1, &isize, &index, &grpname);
786 xvg = xvgropen(opt2fn("-dr", NFILE, fnm), "Individual Restraints", "Time (ps)", "nm", oenv);
787 snew(vvindex, isize);
789 for (i = 0; (i < isize); i++)
793 sprintf(leg[i], "index %d", index[i]);
795 xvgr_legend(xvg, isize, leg, oenv);
803 init_disres(fplog, topInfo.mtop(), ir, DisResRunMode::AnalysisTool, DDRole::Master,
804 NumRanks::Single, MPI_COMM_NULL, nullptr, &fcd, nullptr, FALSE);
806 int natoms = read_first_x(oenv, &status, ftp2fn(efTRX, NFILE, fnm), &t, &x, box);
809 init_dr_res(&dr, fcd.disres.nres);
810 if (opt2bSet("-c", NFILE, fnm))
812 clust = cluster_index(fplog, opt2fn("-c", NFILE, fnm));
813 snew(dr_clust, clust->clust->nr + 1);
814 for (i = 0; (i <= clust->clust->nr); i++)
816 init_dr_res(&dr_clust[i], fcd.disres.nres);
821 out = xvgropen(opt2fn("-ds", NFILE, fnm), "Sum of Violations", "Time (ps)", "nm", oenv);
822 aver = xvgropen(opt2fn("-da", NFILE, fnm), "Average Violation", "Time (ps)", "nm", oenv);
823 numv = xvgropen(opt2fn("-dn", NFILE, fnm), "# Violations", "Time (ps)", "#", oenv);
824 maxxv = xvgropen(opt2fn("-dm", NFILE, fnm), "Largest Violation", "Time (ps)", "nm", oenv);
827 auto mdAtoms = gmx::makeMDAtoms(fplog, *topInfo.mtop(), *ir, false);
828 atoms2md(topInfo.mtop(), ir, -1, nullptr, ntopatoms, mdAtoms.get());
829 update_mdatoms(mdAtoms->mdatoms(), ir->fepvals->init_lambda);
830 if (ir->pbcType != PbcType::No)
832 gpbc = gmx_rmpbc_init(top.idef, ir->pbcType, natoms);
838 if (ir->pbcType != PbcType::No)
840 if (ir->bPeriodicMols)
842 set_pbc(&pbc, ir->pbcType, box);
846 gmx_rmpbc(gpbc, natoms, box, x);
852 if (j > clust->maxframe)
855 "There are more frames in the trajectory than in the cluster index file. "
859 my_clust = clust->inv_clust[j];
860 range_check(my_clust, 0, clust->clust->nr);
861 check_viol(fplog, top.idef.il[F_DISRES], top.idef.iparams, x, f, pbc_null, dr_clust,
862 my_clust, isize, index, vvindex, &fcd);
866 check_viol(fplog, top.idef.il[F_DISRES], top.idef.iparams, x, f, pbc_null, &dr, 0,
867 isize, index, vvindex, &fcd);
871 reset_x(atoms->nr, ind_fit, atoms->nr, nullptr, x, w_rls);
872 do_fit(atoms->nr, w_rls, x, x);
875 /* Store the first frame of the trajectory as 'characteristic'
876 * for colouring with violations.
878 for (kkk = 0; (kkk < atoms->nr); kkk++)
880 copy_rvec(x[kkk], xav[kkk]);
888 fprintf(xvg, "%10g", t);
889 for (i = 0; (i < isize); i++)
891 fprintf(xvg, " %10g", vvindex[i]);
895 fprintf(out, "%10g %10g\n", t, dr.sumv);
896 fprintf(aver, "%10g %10g\n", t, dr.averv);
897 fprintf(maxxv, "%10g %10g\n", t, dr.maxv);
898 fprintf(numv, "%10g %10d\n", t, dr.nv);
901 } while (read_next_x(oenv, status, &t, x, box));
903 if (ir->pbcType != PbcType::No)
905 gmx_rmpbc_done(gpbc);
910 dump_clust_stats(fplog, fcd.disres, top.idef.il[F_DISRES], top.idef.iparams, clust->clust,
911 dr_clust, clust->grpname, isize, index);
915 dump_stats(fplog, j, fcd.disres, top.idef.il[F_DISRES], top.idef.iparams, &dr, isize, index,
916 bPDB ? atoms.get() : nullptr);
919 write_sto_conf(opt2fn("-q", NFILE, fnm), "Coloured by average violation in Angstrom",
920 atoms.get(), xav, nullptr, ir->pbcType, box);
922 dump_disre_matrix(opt2fn_null("-x", NFILE, fnm), &dr, fcd.disres.nres, j, top.idef,
923 topInfo.mtop(), max_dr, nlevels, bThird);
928 do_view(oenv, opt2fn("-dn", NFILE, fnm), "-nxy");
929 do_view(oenv, opt2fn("-da", NFILE, fnm), "-nxy");
930 do_view(oenv, opt2fn("-ds", NFILE, fnm), "-nxy");
931 do_view(oenv, opt2fn("-dm", NFILE, fnm), "-nxy");
938 do_view(oenv, opt2fn("-dr", NFILE, fnm), "-nxy");