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.
50 #include "gromacs/fileio/pdbio.h"
51 #include "gromacs/gmxpreprocess/add_par.h"
52 #include "gromacs/gmxpreprocess/fflibutil.h"
53 #include "gromacs/gmxpreprocess/gen_ad.h"
54 #include "gromacs/gmxpreprocess/gen_vsite.h"
55 #include "gromacs/gmxpreprocess/gpp_nextnb.h"
56 #include "gromacs/gmxpreprocess/grompp-impl.h"
57 #include "gromacs/gmxpreprocess/h_db.h"
58 #include "gromacs/gmxpreprocess/hackblock.h"
59 #include "gromacs/gmxpreprocess/notset.h"
60 #include "gromacs/gmxpreprocess/pgutil.h"
61 #include "gromacs/gmxpreprocess/resall.h"
62 #include "gromacs/gmxpreprocess/specbond.h"
63 #include "gromacs/gmxpreprocess/topdirs.h"
64 #include "gromacs/gmxpreprocess/topio.h"
65 #include "gromacs/gmxpreprocess/toputil.h"
66 #include "gromacs/math/functions.h"
67 #include "gromacs/math/vec.h"
68 #include "gromacs/topology/residuetypes.h"
69 #include "gromacs/topology/symtab.h"
70 #include "gromacs/utility/binaryinformation.h"
71 #include "gromacs/utility/cstringutil.h"
72 #include "gromacs/utility/dir_separator.h"
73 #include "gromacs/utility/exceptions.h"
74 #include "gromacs/utility/fatalerror.h"
75 #include "gromacs/utility/futil.h"
76 #include "gromacs/utility/niceheader.h"
77 #include "gromacs/utility/path.h"
78 #include "gromacs/utility/programcontext.h"
79 #include "gromacs/utility/smalloc.h"
80 #include "gromacs/utility/strconvert.h"
81 #include "gromacs/utility/strdb.h"
82 #include "gromacs/utility/stringutil.h"
83 #include "gromacs/utility/textwriter.h"
85 /* this must correspond to enum in pdb2top.h */
86 const char *hh[ehisNR] = { "HISD", "HISE", "HISH", "HIS1" };
88 static int missing_atoms(t_restp *rp, int resind, t_atoms *at, int i0, int i)
95 for (j = 0; j < rp->natom; j++)
97 name = *(rp->atomname[j]);
99 for (k = i0; k < i; k++)
101 bFound = (bFound || (gmx_strcasecmp(*(at->atomname[k]), name) == 0));
106 fprintf(stderr, "\nWARNING: "
107 "atom %s is missing in residue %s %d in the pdb file\n",
108 name, *(at->resinfo[resind].name), at->resinfo[resind].nr);
109 if (name[0] == 'H' || name[0] == 'h')
111 fprintf(stderr, " You might need to add atom %s to the hydrogen database of building block %s\n"
112 " in the file %s.hdb (see the manual)\n",
113 name, *(at->resinfo[resind].rtp), rp->filebase);
115 fprintf(stderr, "\n");
122 bool is_int(double x)
124 const double tol = 1e-4;
131 ix = gmx::roundToInt(x);
133 return (fabs(x-ix) < tol);
137 choose_ff_impl(const char *ffsel,
138 char *forcefield, int ff_maxlen,
139 char *ffdir, int ffdir_maxlen)
141 std::vector<gmx::DataFileInfo> ffdirs = fflib_enumerate_forcefields();
142 const int nff = static_cast<int>(ffdirs.size());
144 /* Replace with unix path separators */
145 #if DIR_SEPARATOR != '/'
146 for (int i = 0; i < nff; ++i)
148 std::replace(ffdirs[i].dir.begin(), ffdirs[i].dir.end(), DIR_SEPARATOR, '/');
152 /* Store the force field names in ffs */
153 std::vector<std::string> ffs;
154 ffs.reserve(ffdirs.size());
155 for (int i = 0; i < nff; ++i)
157 ffs.push_back(gmx::stripSuffixIfPresent(ffdirs[i].name,
158 fflib_forcefield_dir_ext()));
162 if (ffsel != nullptr)
167 for (int i = 0; i < nff; ++i)
171 /* Matching ff name */
175 if (ffdirs[i].dir == ".")
192 "Force field '%s' occurs in %d places. pdb2gmx is using the one in the\n"
193 "current directory. Use interactive selection (not the -ff option) if\n"
194 "you would prefer a different one.\n", ffsel, nfound);
198 std::string message = gmx::formatString(
199 "Force field '%s' occurs in %d places, but not in "
200 "the current directory.\n"
201 "Run without the -ff switch and select the force "
202 "field interactively.", ffsel, nfound);
203 GMX_THROW(gmx::InconsistentInputError(message));
206 else if (nfound == 0)
208 std::string message = gmx::formatString(
209 "Could not find force field '%s' in current directory, "
210 "install tree or GMXLIB path.", ffsel);
211 GMX_THROW(gmx::InconsistentInputError(message));
216 std::vector<std::string> desc;
217 desc.reserve(ffdirs.size());
218 for (int i = 0; i < nff; ++i)
220 std::string docFileName(
221 gmx::Path::join(ffdirs[i].dir, ffdirs[i].name,
222 fflib_forcefield_doc()));
223 // TODO: Just try to open the file with a method that does not
224 // throw/bail out with a fatal error instead of multiple checks.
225 if (gmx::File::exists(docFileName, gmx::File::returnFalseOnError))
227 // TODO: Use a C++ API without such an intermediate/fixed-length buffer.
229 /* We don't use fflib_open, because we don't want printf's */
230 FILE *fp = gmx_ffopen(docFileName, "r");
231 get_a_line(fp, buf, STRLEN);
233 desc.emplace_back(buf);
237 desc.push_back(ffs[i]);
240 /* Order force fields from the same dir alphabetically
241 * and put deprecated force fields at the end.
243 for (int i = 0; i < nff; ++i)
245 for (int j = i + 1; j < nff; ++j)
247 if (ffdirs[i].dir == ffdirs[j].dir &&
248 ((desc[i][0] == '[' && desc[j][0] != '[') ||
249 ((desc[i][0] == '[' || desc[j][0] != '[') &&
250 gmx_strcasecmp(desc[i].c_str(), desc[j].c_str()) > 0)))
252 std::swap(ffdirs[i].name, ffdirs[j].name);
253 std::swap(ffs[i], ffs[j]);
254 std::swap(desc[i], desc[j]);
259 printf("\nSelect the Force Field:\n");
260 for (int i = 0; i < nff; ++i)
262 if (i == 0 || ffdirs[i-1].dir != ffdirs[i].dir)
264 if (ffdirs[i].dir == ".")
266 printf("From current directory:\n");
270 printf("From '%s':\n", ffdirs[i].dir.c_str());
273 printf("%2d: %s\n", i+1, desc[i].c_str());
277 // TODO: Add a C++ API for this.
282 pret = fgets(buf, STRLEN, stdin);
286 sel = strtol(buf, nullptr, 10);
290 while (pret == nullptr || (sel < 0) || (sel >= nff));
292 /* Check for a current limitation of the fflib code.
293 * It will always read from the first ff directory in the list.
294 * This check assumes that the order of ffs matches the order
295 * in which fflib_open searches ff library files.
297 for (int i = 0; i < sel; i++)
299 if (ffs[i] == ffs[sel])
301 std::string message = gmx::formatString(
302 "Can only select the first of multiple force "
303 "field entries with directory name '%s%s' in "
304 "the list. If you want to use the next entry, "
305 "run pdb2gmx in a different directory, set GMXLIB "
306 "to point to the desired force field first, and/or "
307 "rename or move the force field directory present "
308 "in the current working directory.",
309 ffs[sel].c_str(), fflib_forcefield_dir_ext());
310 GMX_THROW(gmx::NotImplementedError(message));
319 if (ffs[sel].length() >= static_cast<size_t>(ff_maxlen))
321 std::string message = gmx::formatString(
322 "Length of force field name (%d) >= maxlen (%d)",
323 static_cast<int>(ffs[sel].length()), ff_maxlen);
324 GMX_THROW(gmx::InvalidInputError(message));
326 strcpy(forcefield, ffs[sel].c_str());
329 if (ffdirs[sel].bFromDefaultDir)
331 ffpath = ffdirs[sel].name;
335 ffpath = gmx::Path::join(ffdirs[sel].dir, ffdirs[sel].name);
337 if (ffpath.length() >= static_cast<size_t>(ffdir_maxlen))
339 std::string message = gmx::formatString(
340 "Length of force field dir (%d) >= maxlen (%d)",
341 static_cast<int>(ffpath.length()), ffdir_maxlen);
342 GMX_THROW(gmx::InvalidInputError(message));
344 strcpy(ffdir, ffpath.c_str());
348 choose_ff(const char *ffsel,
349 char *forcefield, int ff_maxlen,
350 char *ffdir, int ffdir_maxlen)
354 choose_ff_impl(ffsel, forcefield, ff_maxlen, ffdir, ffdir_maxlen);
356 GMX_CATCH_ALL_AND_EXIT_WITH_FATAL_ERROR;
359 void choose_watermodel(const char *wmsel, const char *ffdir,
362 const char *fn_watermodels = "watermodels.dat";
369 if (strcmp(wmsel, "none") == 0)
371 *watermodel = nullptr;
375 else if (strcmp(wmsel, "select") != 0)
377 *watermodel = gmx_strdup(wmsel);
382 std::string filename = gmx::Path::join(ffdir, fn_watermodels);
383 if (!fflib_fexist(filename))
385 fprintf(stderr, "No file '%s' found, will not include a water model\n",
387 *watermodel = nullptr;
392 fp = fflib_open(filename);
393 printf("\nSelect the Water Model:\n");
396 while (get_a_line(fp, buf, STRLEN))
398 srenew(model, nwm+1);
399 snew(model[nwm], STRLEN);
400 sscanf(buf, "%s%n", model[nwm], &i);
404 fprintf(stderr, "%2d: %s\n", nwm+1, buf+i);
413 fprintf(stderr, "%2d: %s\n", nwm+1, "None");
418 pret = fgets(buf, STRLEN, stdin);
422 sel = strtol(buf, nullptr, 10);
426 while (pret == nullptr || sel < 0 || sel > nwm);
430 *watermodel = nullptr;
434 *watermodel = gmx_strdup(model[sel]);
437 for (i = 0; i < nwm; i++)
444 static int name2type(t_atoms *at, int **cgnr,
445 t_restp restp[], gmx_residuetype_t *rt)
447 int i, j, prevresind, resind, i0, prevcg, cg, curcg;
463 for (i = 0; (i < at->nr); i++)
466 if (at->atom[i].resind != resind)
469 resind = at->atom[i].resind;
470 bProt = gmx_residuetype_is_protein(rt, *(at->resinfo[resind].name));
471 bNterm = bProt && (resind == 0);
474 nmissat += missing_atoms(&restp[prevresind], prevresind, at, i0, i);
478 if (at->atom[i].m == 0)
482 name = *(at->atomname[i]);
483 j = search_jtype(&restp[resind], name, bNterm);
484 at->atom[i].type = restp[resind].atom[j].type;
485 at->atom[i].q = restp[resind].atom[j].q;
486 at->atom[i].m = restp[resind].atom[j].m;
487 cg = restp[resind].cgnr[j];
488 /* A charge group number -1 signals a separate charge group
491 if ( (cg == -1) || (cg != prevcg) || (resind != prevresind) )
507 at->atom[i].typeB = at->atom[i].type;
508 at->atom[i].qB = at->atom[i].q;
509 at->atom[i].mB = at->atom[i].m;
511 nmissat += missing_atoms(&restp[resind], resind, at, i0, i);
516 static void print_top_heavy_H(FILE *out, real mHmult)
520 fprintf(out, "; Using deuterium instead of hydrogen\n\n");
522 else if (mHmult == 4.0)
524 fprintf(out, "#define HEAVY_H\n\n");
526 else if (mHmult != 1.0)
528 fprintf(stderr, "WARNING: unsupported proton mass multiplier (%g) "
529 "in pdb2top\n", mHmult);
533 void print_top_comment(FILE *out,
534 const char *filename,
538 char ffdir_parent[STRLEN];
543 gmx::TextWriter writer(out);
544 gmx::niceHeader(&writer, filename, ';');
545 writer.writeLine(gmx::formatString(";\tThis is a %s topology file", bITP ? "include" : "standalone"));
546 writer.writeLine(";");
548 gmx::BinaryInformationSettings settings;
549 settings.generatedByHeader(true);
550 settings.linePrefix(";\t");
551 gmx::printBinaryInformation(&writer, gmx::getProgramContext(), settings);
553 GMX_CATCH_ALL_AND_EXIT_WITH_FATAL_ERROR;
555 if (strchr(ffdir, '/') == nullptr)
557 fprintf(out, ";\tForce field was read from the standard GROMACS share directory.\n;\n\n");
559 else if (ffdir[0] == '.')
561 fprintf(out, ";\tForce field was read from current directory or a relative path - path added.\n;\n\n");
565 strncpy(ffdir_parent, ffdir, STRLEN-1);
566 ffdir_parent[STRLEN-1] = '\0'; /*make sure it is 0-terminated even for long string*/
567 p = strrchr(ffdir_parent, '/');
572 ";\tForce field data was read from:\n"
576 ";\tThis might be a non-standard force field location. When you use this topology, the\n"
577 ";\tforce field must either be present in the current directory, or the location\n"
578 ";\tspecified in the GMXLIB path variable or with the 'include' mdp file option.\n;\n\n",
583 void print_top_header(FILE *out, const char *filename,
584 bool bITP, const char *ffdir, real mHmult)
588 print_top_comment(out, filename, ffdir, bITP);
590 print_top_heavy_H(out, mHmult);
591 fprintf(out, "; Include forcefield parameters\n");
593 p = strrchr(ffdir, '/');
594 p = (ffdir[0] == '.' || p == nullptr) ? ffdir : p+1;
596 fprintf(out, "#include \"%s/%s\"\n\n", p, fflib_forcefield_itp());
599 static void print_top_posre(FILE *out, const char *pr)
601 fprintf(out, "; Include Position restraint file\n");
602 fprintf(out, "#ifdef POSRES\n");
603 fprintf(out, "#include \"%s\"\n", pr);
604 fprintf(out, "#endif\n\n");
607 static void print_top_water(FILE *out, const char *ffdir, const char *water)
612 fprintf(out, "; Include water topology\n");
614 p = strrchr(ffdir, '/');
615 p = (ffdir[0] == '.' || p == nullptr) ? ffdir : p+1;
616 fprintf(out, "#include \"%s/%s.itp\"\n", p, water);
619 fprintf(out, "#ifdef POSRES_WATER\n");
620 fprintf(out, "; Position restraint for each water oxygen\n");
621 fprintf(out, "[ position_restraints ]\n");
622 fprintf(out, ";%3s %5s %9s %10s %10s\n", "i", "funct", "fcx", "fcy", "fcz");
623 fprintf(out, "%4d %4d %10g %10g %10g\n", 1, 1, 1000.0, 1000.0, 1000.0);
624 fprintf(out, "#endif\n");
627 sprintf(buf, "%s/ions.itp", p);
629 if (fflib_fexist(buf))
631 fprintf(out, "; Include topology for ions\n");
632 fprintf(out, "#include \"%s\"\n", buf);
637 static void print_top_system(FILE *out, const char *title)
639 fprintf(out, "[ %s ]\n", dir2str(Directive::d_system));
640 fprintf(out, "; Name\n");
641 fprintf(out, "%s\n\n", title[0] ? title : "Protein");
644 void print_top_mols(FILE *out,
645 const char *title, const char *ffdir, const char *water,
646 int nincl, char **incls, int nmol, t_mols *mols)
651 fprintf(out, "; Include chain topologies\n");
652 for (int i = 0; i < nincl; i++)
654 fprintf(out, "#include \"%s\"\n", gmx::Path::getFilename(incls[i]).c_str());
661 print_top_water(out, ffdir, water);
663 print_top_system(out, title);
667 fprintf(out, "[ %s ]\n", dir2str(Directive::d_molecules));
668 fprintf(out, "; %-15s %5s\n", "Compound", "#mols");
669 for (int i = 0; i < nmol; i++)
671 fprintf(out, "%-15s %5d\n", mols[i].name, mols[i].nr);
676 void write_top(FILE *out, const char *pr, const char *molname,
677 t_atoms *at, bool bRTPresname,
678 int bts[], t_params plist[], t_excls excls[],
679 gpp_atomtype *atype, int *cgnr, int nrexcl)
680 /* NOTE: nrexcl is not the size of *excl! */
682 if (at && atype && cgnr)
684 fprintf(out, "[ %s ]\n", dir2str(Directive::d_moleculetype));
685 fprintf(out, "; %-15s %5s\n", "Name", "nrexcl");
686 fprintf(out, "%-15s %5d\n\n", molname ? molname : "Protein", nrexcl);
688 print_atoms(out, atype, at, cgnr, bRTPresname);
689 print_bondeds(out, at->nr, Directive::d_bonds, F_BONDS, bts[ebtsBONDS], plist);
690 print_bondeds(out, at->nr, Directive::d_constraints, F_CONSTR, 0, plist);
691 print_bondeds(out, at->nr, Directive::d_constraints, F_CONSTRNC, 0, plist);
692 print_bondeds(out, at->nr, Directive::d_pairs, F_LJ14, 0, plist);
693 print_excl(out, at->nr, excls);
694 print_bondeds(out, at->nr, Directive::d_angles, F_ANGLES, bts[ebtsANGLES], plist);
695 print_bondeds(out, at->nr, Directive::d_dihedrals, F_PDIHS, bts[ebtsPDIHS], plist);
696 print_bondeds(out, at->nr, Directive::d_dihedrals, F_IDIHS, bts[ebtsIDIHS], plist);
697 print_bondeds(out, at->nr, Directive::d_cmap, F_CMAP, bts[ebtsCMAP], plist);
698 print_bondeds(out, at->nr, Directive::d_polarization, F_POLARIZATION, 0, plist);
699 print_bondeds(out, at->nr, Directive::d_thole_polarization, F_THOLE_POL, 0, plist);
700 print_bondeds(out, at->nr, Directive::d_vsites2, F_VSITE2, 0, plist);
701 print_bondeds(out, at->nr, Directive::d_vsites3, F_VSITE3, 0, plist);
702 print_bondeds(out, at->nr, Directive::d_vsites3, F_VSITE3FD, 0, plist);
703 print_bondeds(out, at->nr, Directive::d_vsites3, F_VSITE3FAD, 0, plist);
704 print_bondeds(out, at->nr, Directive::d_vsites3, F_VSITE3OUT, 0, plist);
705 print_bondeds(out, at->nr, Directive::d_vsites4, F_VSITE4FD, 0, plist);
706 print_bondeds(out, at->nr, Directive::d_vsites4, F_VSITE4FDN, 0, plist);
710 print_top_posre(out, pr);
717 static void do_ssbonds(t_params *ps, t_atoms *atoms,
718 int nssbonds, t_ssbond *ssbonds, bool bAllowMissing)
723 for (i = 0; (i < nssbonds); i++)
725 ri = ssbonds[i].res1;
726 rj = ssbonds[i].res2;
727 ai = search_res_atom(ssbonds[i].a1, ri, atoms,
728 "special bond", bAllowMissing);
729 aj = search_res_atom(ssbonds[i].a2, rj, atoms,
730 "special bond", bAllowMissing);
731 if ((ai == -1) || (aj == -1))
733 gmx_fatal(FARGS, "Trying to make impossible special bond (%s-%s)!",
734 ssbonds[i].a1, ssbonds[i].a2);
736 add_param(ps, ai, aj, nullptr, nullptr);
740 static void at2bonds(t_params *psb, t_hackblock *hb,
743 real long_bond_dist, real short_bond_dist)
747 real dist2, long_bond_dist2, short_bond_dist2;
750 long_bond_dist2 = gmx::square(long_bond_dist);
751 short_bond_dist2 = gmx::square(short_bond_dist);
762 fprintf(stderr, "Making bonds...\n");
764 for (resind = 0; (resind < atoms->nres) && (i < atoms->nr); resind++)
766 /* add bonds from list of bonded interactions */
767 for (j = 0; j < hb[resind].rb[ebtsBONDS].nb; j++)
769 /* Unfortunately we can not issue errors or warnings
770 * for missing atoms in bonds, as the hydrogens and terminal atoms
771 * have not been added yet.
773 ai = search_atom(hb[resind].rb[ebtsBONDS].b[j].a[0], i, atoms,
775 aj = search_atom(hb[resind].rb[ebtsBONDS].b[j].a[1], i, atoms,
777 if (ai != -1 && aj != -1)
779 dist2 = distance2(x[ai], x[aj]);
780 if (dist2 > long_bond_dist2)
783 fprintf(stderr, "Warning: Long Bond (%d-%d = %g nm)\n",
784 ai+1, aj+1, std::sqrt(dist2));
786 else if (dist2 < short_bond_dist2)
788 fprintf(stderr, "Warning: Short Bond (%d-%d = %g nm)\n",
789 ai+1, aj+1, std::sqrt(dist2));
791 add_param(psb, ai, aj, nullptr, hb[resind].rb[ebtsBONDS].b[j].s);
794 /* add bonds from list of hacks (each added atom gets a bond) */
795 while ( (i < atoms->nr) && (atoms->atom[i].resind == resind) )
797 for (j = 0; j < hb[resind].nhack; j++)
799 if ( ( hb[resind].hack[j].tp > 0 ||
800 hb[resind].hack[j].oname == nullptr ) &&
801 strcmp(hb[resind].hack[j].a[0], *(atoms->atomname[i])) == 0)
803 switch (hb[resind].hack[j].tp)
805 case 9: /* COOH terminus */
806 add_param(psb, i, i+1, nullptr, nullptr); /* C-O */
807 add_param(psb, i, i+2, nullptr, nullptr); /* C-OA */
808 add_param(psb, i+2, i+3, nullptr, nullptr); /* OA-H */
811 for (k = 0; (k < hb[resind].hack[j].nr); k++)
813 add_param(psb, i, i+k+1, nullptr, nullptr);
820 /* we're now at the start of the next residue */
824 static int pcompar(const void *a, const void *b)
826 const t_param *pa, *pb;
828 pa = static_cast<const t_param *>(a);
829 pb = static_cast<const t_param *>(b);
831 d = pa->a[0] - pb->a[0];
834 d = pa->a[1] - pb->a[1];
838 return strlen(pb->s) - strlen(pa->s);
846 static void clean_bonds(t_params *ps)
853 /* swap atomnumbers in bond if first larger than second: */
854 for (i = 0; (i < ps->nr); i++)
856 if (ps->param[i].a[1] < ps->param[i].a[0])
858 a = ps->param[i].a[0];
859 ps->param[i].a[0] = ps->param[i].a[1];
860 ps->param[i].a[1] = a;
865 qsort(ps->param, ps->nr, static_cast<size_t>(sizeof(ps->param[0])), pcompar);
867 /* remove doubles, keep the first one always. */
869 for (i = 1; (i < ps->nr); i++)
871 if ((ps->param[i].a[0] != ps->param[j-1].a[0]) ||
872 (ps->param[i].a[1] != ps->param[j-1].a[1]) )
876 cp_param(&(ps->param[j]), &(ps->param[i]));
881 fprintf(stderr, "Number of bonds was %d, now %d\n", ps->nr, j);
886 fprintf(stderr, "No bonds\n");
890 void print_sums(t_atoms *atoms, bool bSystem)
898 where = " in system";
907 for (i = 0; (i < atoms->nr); i++)
909 m += atoms->atom[i].m;
910 qtot += atoms->atom[i].q;
913 fprintf(stderr, "Total mass%s %.3f a.m.u.\n", where, m);
914 fprintf(stderr, "Total charge%s %.3f e\n", where, qtot);
917 static void check_restp_type(const char *name, int t1, int t2)
921 gmx_fatal(FARGS, "Residues in one molecule have a different '%s' type: %d and %d", name, t1, t2);
925 static void check_restp_types(t_restp *r0, t_restp *r1)
929 check_restp_type("all dihedrals", static_cast<int>(r0->bKeepAllGeneratedDihedrals), static_cast<int>(r1->bKeepAllGeneratedDihedrals));
930 check_restp_type("nrexcl", r0->nrexcl, r1->nrexcl);
931 check_restp_type("HH14", static_cast<int>(r0->bGenerateHH14Interactions), static_cast<int>(r1->bGenerateHH14Interactions));
932 check_restp_type("remove dihedrals", static_cast<int>(r0->bRemoveDihedralIfWithImproper), static_cast<int>(r1->bRemoveDihedralIfWithImproper));
934 for (i = 0; i < ebtsNR; i++)
936 check_restp_type(btsNames[i], r0->rb[i].type, r1->rb[i].type);
940 static void add_atom_to_restp(t_restp *restp, int at_start, const t_hack *hack)
944 const char *Hnum = "123456";
946 strcpy(buf, hack->nname);
947 buf[strlen(buf)+1] = '\0';
950 buf[strlen(buf)] = '-';
953 restp->natom += hack->nr;
954 srenew(restp->atom, restp->natom);
955 srenew(restp->atomname, restp->natom);
956 srenew(restp->cgnr, restp->natom);
958 for (k = restp->natom-1; k > at_start+hack->nr; k--)
961 restp->atom [k - hack->nr];
963 restp->atomname[k - hack->nr];
965 restp->cgnr [k - hack->nr];
968 for (k = 0; k < hack->nr; k++)
970 /* set counter in atomname */
973 buf[strlen(buf)-1] = Hnum[k];
975 snew( restp->atomname[at_start+1+k], 1);
976 restp->atom [at_start+1+k] = *hack->atom;
977 *restp->atomname[at_start+1+k] = gmx_strdup(buf);
978 if (hack->cgnr != NOTSET)
980 restp->cgnr [at_start+1+k] = hack->cgnr;
984 restp->cgnr [at_start+1+k] = restp->cgnr[at_start];
989 void get_hackblocks_rtp(t_hackblock **hb, t_restp **restp,
990 int nrtp, t_restp rtp[],
991 int nres, t_resinfo *resinfo,
993 t_hackblock **ntdb, t_hackblock **ctdb,
994 const int *rn, const int *rc,
1005 /* first the termini */
1006 for (i = 0; i < nterpairs; i++)
1008 if (rn[i] >= 0 && ntdb[i] != nullptr)
1010 copy_t_hackblock(ntdb[i], &(*hb)[rn[i]]);
1012 if (rc[i] >= 0 && ctdb[i] != nullptr)
1014 merge_t_hackblock(ctdb[i], &(*hb)[rc[i]]);
1018 /* then the whole rtp */
1019 for (i = 0; i < nres; i++)
1021 /* Here we allow a mismatch of one character when looking for the rtp entry.
1022 * For such a mismatch there should be only one mismatching name.
1023 * This is mainly useful for small molecules such as ions.
1024 * Note that this will usually not work for protein, DNA and RNA,
1025 * since there the residue names should be listed in residuetypes.dat
1026 * and an error will have been generated earlier in the process.
1028 key = *resinfo[i].rtp;
1029 snew(resinfo[i].rtp, 1);
1030 *resinfo[i].rtp = search_rtp(key, nrtp, rtp);
1031 res = get_restp(*resinfo[i].rtp, nrtp, rtp);
1032 copy_t_restp(res, &(*restp)[i]);
1034 /* Check that we do not have different bonded types in one molecule */
1035 check_restp_types(&(*restp)[0], &(*restp)[i]);
1038 for (j = 0; j < nterpairs && tern == -1; j++)
1046 for (j = 0; j < nterpairs && terc == -1; j++)
1053 bRM = merge_t_bondeds(res->rb, (*hb)[i].rb, tern >= 0, terc >= 0);
1055 if (bRM && ((tern >= 0 && ntdb[tern] == nullptr) ||
1056 (terc >= 0 && ctdb[terc] == nullptr)))
1058 const char *errString = "There is a dangling bond at at least one of the terminal ends and the force field does not provide terminal entries or files. Fix your terminal residues so that they match the residue database (.rtp) entries, or provide terminal database entries (.tdb).";
1061 fprintf(stderr, "%s\n", errString);
1065 gmx_fatal(FARGS, "%s", errString);
1068 else if (bRM && ((tern >= 0 && ntdb[tern]->nhack == 0) ||
1069 (terc >= 0 && ctdb[terc]->nhack == 0)))
1071 const char *errString = "There is a dangling bond at at least one of the terminal ends. Fix your coordinate file, add a new terminal database entry (.tdb), or select the proper existing terminal entry.";
1074 fprintf(stderr, "%s\n", errString);
1078 gmx_fatal(FARGS, "%s", errString);
1083 /* now perform t_hack's on t_restp's,
1084 i.e. add's and deletes from termini database will be
1085 added to/removed from residue topology
1086 we'll do this on one big dirty loop, so it won't make easy reading! */
1087 for (i = 0; i < nres; i++)
1089 for (j = 0; j < (*hb)[i].nhack; j++)
1091 if ( (*hb)[i].hack[j].nr)
1093 /* find atom in restp */
1094 for (l = 0; l < (*restp)[i].natom; l++)
1096 if ( ( (*hb)[i].hack[j].oname == nullptr &&
1097 strcmp((*hb)[i].hack[j].a[0], *(*restp)[i].atomname[l]) == 0 ) ||
1098 ( (*hb)[i].hack[j].oname != nullptr &&
1099 strcmp((*hb)[i].hack[j].oname, *(*restp)[i].atomname[l]) == 0 ) )
1104 if (l == (*restp)[i].natom)
1106 /* If we are doing an atom rename only, we don't need
1107 * to generate a fatal error if the old name is not found
1110 /* Deleting can happen also only on the input atoms,
1111 * not necessarily always on the rtp entry.
1113 if (!((*hb)[i].hack[j].oname != nullptr &&
1114 (*hb)[i].hack[j].nname != nullptr) &&
1115 !((*hb)[i].hack[j].oname != nullptr &&
1116 (*hb)[i].hack[j].nname == nullptr))
1119 "atom %s not found in buiding block %d%s "
1120 "while combining tdb and rtp",
1121 (*hb)[i].hack[j].oname != nullptr ?
1122 (*hb)[i].hack[j].oname : (*hb)[i].hack[j].a[0],
1123 i+1, *resinfo[i].rtp);
1128 if ( (*hb)[i].hack[j].oname == nullptr)
1131 add_atom_to_restp(&(*restp)[i], l, &(*hb)[i].hack[j]);
1136 if ( (*hb)[i].hack[j].nname == nullptr)
1137 { /* we're deleting */
1138 /* shift the rest */
1139 (*restp)[i].natom--;
1140 for (k = l; k < (*restp)[i].natom; k++)
1142 (*restp)[i].atom [k] = (*restp)[i].atom [k+1];
1143 (*restp)[i].atomname[k] = (*restp)[i].atomname[k+1];
1144 (*restp)[i].cgnr [k] = (*restp)[i].cgnr [k+1];
1146 /* give back space */
1147 srenew((*restp)[i].atom, (*restp)[i].natom);
1148 srenew((*restp)[i].atomname, (*restp)[i].natom);
1149 srenew((*restp)[i].cgnr, (*restp)[i].natom);
1151 else /* nname != NULL */
1152 { /* we're replacing */
1153 snew( (*restp)[i].atomname[l], 1);
1154 (*restp)[i].atom[l] = *(*hb)[i].hack[j].atom;
1155 *(*restp)[i].atomname[l] = gmx_strdup((*hb)[i].hack[j].nname);
1156 if ( (*hb)[i].hack[j].cgnr != NOTSET)
1158 (*restp)[i].cgnr [l] = (*hb)[i].hack[j].cgnr;
1168 static bool atomname_cmp_nr(const char *anm, t_hack *hack, int *nr)
1175 return (gmx_strcasecmp(anm, hack->nname) == 0);
1179 if (isdigit(anm[strlen(anm)-1]))
1181 *nr = anm[strlen(anm)-1] - '0';
1187 if (*nr <= 0 || *nr > hack->nr)
1193 return (strlen(anm) == strlen(hack->nname) + 1 &&
1194 gmx_strncasecmp(anm, hack->nname, strlen(hack->nname)) == 0);
1199 static bool match_atomnames_with_rtp_atom(t_atoms *pdba, rvec *x, int atind,
1200 t_restp *rptr, t_hackblock *hbr,
1205 char *oldnm, *newnm;
1207 char *start_at, buf[STRLEN];
1209 bool bReplaceReplace, bFoundInAdd;
1212 oldnm = *pdba->atomname[atind];
1213 resnr = pdba->resinfo[pdba->atom[atind].resind].nr;
1216 for (j = 0; j < hbr->nhack; j++)
1218 if (hbr->hack[j].oname != nullptr && hbr->hack[j].nname != nullptr &&
1219 gmx_strcasecmp(oldnm, hbr->hack[j].oname) == 0)
1221 /* This is a replace entry. */
1222 /* Check if we are not replacing a replaced atom. */
1223 bReplaceReplace = FALSE;
1224 for (k = 0; k < hbr->nhack; k++)
1227 hbr->hack[k].oname != nullptr && hbr->hack[k].nname != nullptr &&
1228 gmx_strcasecmp(hbr->hack[k].nname, hbr->hack[j].oname) == 0)
1230 /* The replace in hack[j] replaces an atom that
1231 * was already replaced in hack[k], we do not want
1232 * second or higher level replaces at this stage.
1234 bReplaceReplace = TRUE;
1237 if (bReplaceReplace)
1239 /* Skip this replace. */
1243 /* This atom still has the old name, rename it */
1244 newnm = hbr->hack[j].nname;
1245 for (k = 0; k < rptr->natom; k++)
1247 if (gmx_strcasecmp(newnm, *rptr->atomname[k]) == 0)
1252 if (k == rptr->natom)
1254 /* The new name is not present in the rtp.
1255 * We need to apply the replace also to the rtp entry.
1258 /* We need to find the add hack that can add this atom
1259 * to find out after which atom it should be added.
1261 bFoundInAdd = FALSE;
1262 for (k = 0; k < hbr->nhack; k++)
1264 if (hbr->hack[k].oname == nullptr &&
1265 hbr->hack[k].nname != nullptr &&
1266 atomname_cmp_nr(newnm, &hbr->hack[k], &anmnr))
1270 start_at = hbr->hack[k].a[0];
1274 sprintf(buf, "%s%d", hbr->hack[k].nname, anmnr-1);
1277 for (start_nr = 0; start_nr < rptr->natom; start_nr++)
1279 if (gmx_strcasecmp(start_at, (*rptr->atomname[start_nr])) == 0)
1284 if (start_nr == rptr->natom)
1286 gmx_fatal(FARGS, "Could not find atom '%s' in residue building block '%s' to add atom '%s' to",
1287 start_at, rptr->resname, newnm);
1289 /* We can add the atom after atom start_nr */
1290 add_atom_to_restp(rptr, start_nr, &hbr->hack[j]);
1298 gmx_fatal(FARGS, "Could not find an 'add' entry for atom named '%s' corresponding to the 'replace' entry from atom name '%s' to '%s' for tdb or hdb database of residue type '%s'",
1300 hbr->hack[j].oname, hbr->hack[j].nname,
1307 printf("Renaming atom '%s' in residue '%s' %d to '%s'\n",
1308 oldnm, rptr->resname, resnr, newnm);
1310 /* Rename the atom in pdba */
1311 snew(pdba->atomname[atind], 1);
1312 *pdba->atomname[atind] = gmx_strdup(newnm);
1314 else if (hbr->hack[j].oname != nullptr && hbr->hack[j].nname == nullptr &&
1315 gmx_strcasecmp(oldnm, hbr->hack[j].oname) == 0)
1317 /* This is a delete entry, check if this atom is present
1318 * in the rtp entry of this residue.
1320 for (k = 0; k < rptr->natom; k++)
1322 if (gmx_strcasecmp(oldnm, *rptr->atomname[k]) == 0)
1327 if (k == rptr->natom)
1329 /* This atom is not present in the rtp entry,
1330 * delete is now from the input pdba.
1334 printf("Deleting atom '%s' in residue '%s' %d\n",
1335 oldnm, rptr->resname, resnr);
1337 /* We should free the atom name,
1338 * but it might be used multiple times in the symtab.
1339 * sfree(pdba->atomname[atind]);
1341 for (k = atind+1; k < pdba->nr; k++)
1343 pdba->atom[k-1] = pdba->atom[k];
1344 pdba->atomname[k-1] = pdba->atomname[k];
1345 copy_rvec(x[k], x[k-1]);
1356 void match_atomnames_with_rtp(t_restp restp[], t_hackblock hb[],
1357 t_atoms *pdba, rvec *x,
1364 for (i = 0; i < pdba->nr; i++)
1366 oldnm = *pdba->atomname[i];
1367 rptr = &restp[pdba->atom[i].resind];
1368 for (j = 0; (j < rptr->natom); j++)
1370 if (gmx_strcasecmp(oldnm, *(rptr->atomname[j])) == 0)
1375 if (j == rptr->natom)
1377 /* Not found yet, check if we have to rename this atom */
1378 if (match_atomnames_with_rtp_atom(pdba, x, i,
1379 rptr, &(hb[pdba->atom[i].resind]),
1382 /* We deleted this atom, decrease the atom counter by 1. */
1389 #define NUM_CMAP_ATOMS 5
1390 static void gen_cmap(t_params *psb, t_restp *restp, t_atoms *atoms)
1392 int residx, i, j, k;
1395 t_resinfo *resinfo = atoms->resinfo;
1396 int nres = atoms->nres;
1398 int cmap_atomid[NUM_CMAP_ATOMS];
1399 int cmap_chainnum = -1, this_residue_index;
1410 fprintf(stderr, "Making cmap torsions...\n");
1412 /* Most cmap entries use the N atom from the next residue, so the last
1413 * residue should not have its CMAP entry in that case, but for things like
1414 * dipeptides we sometimes define a complete CMAP entry inside a residue,
1415 * and in this case we need to process everything through the last residue.
1417 for (residx = 0; residx < nres; residx++)
1419 /* Add CMAP terms from the list of CMAP interactions */
1420 for (j = 0; j < restp[residx].rb[ebtsCMAP].nb; j++)
1423 /* Loop over atoms in a candidate CMAP interaction and
1424 * check that they exist, are from the same chain and are
1425 * from residues labelled as protein. */
1426 for (k = 0; k < NUM_CMAP_ATOMS && bAddCMAP; k++)
1428 /* Assign the pointer to the name of the next reference atom.
1429 * This can use -/+ labels to refer to previous/next residue.
1431 pname = restp[residx].rb[ebtsCMAP].b[j].a[k];
1432 /* Skip this CMAP entry if it refers to residues before the
1433 * first or after the last residue.
1435 if (((strchr(pname, '-') != nullptr) && (residx == 0)) ||
1436 ((strchr(pname, '+') != nullptr) && (residx == nres-1)))
1442 cmap_atomid[k] = search_atom(pname,
1443 i, atoms, ptr, TRUE);
1444 bAddCMAP = bAddCMAP && (cmap_atomid[k] != -1);
1447 /* This break is necessary, because cmap_atomid[k]
1448 * == -1 cannot be safely used as an index
1449 * into the atom array. */
1452 this_residue_index = atoms->atom[cmap_atomid[k]].resind;
1455 cmap_chainnum = resinfo[this_residue_index].chainnum;
1459 /* Does the residue for this atom have the same
1460 * chain number as the residues for previous
1462 bAddCMAP = bAddCMAP &&
1463 cmap_chainnum == resinfo[this_residue_index].chainnum;
1465 /* Here we used to check that the residuetype was protein and
1466 * disable bAddCMAP if that was not the case. However, some
1467 * special residues (say, alanine dipeptides) might not adhere
1468 * to standard naming, and if we start calling them normal
1469 * protein residues the user will be bugged to select termini.
1471 * Instead, I believe that the right course of action is to
1472 * keep the CMAP interaction if it is present in the RTP file
1473 * and we correctly identified all atoms (which is the case
1480 add_cmap_param(psb, cmap_atomid[0], cmap_atomid[1], cmap_atomid[2], cmap_atomid[3], cmap_atomid[4], restp[residx].rb[ebtsCMAP].b[j].s);
1484 if (residx < nres-1)
1486 while (atoms->atom[i].resind < residx+1)
1492 /* Start the next residue */
1496 scrub_charge_groups(int *cgnr, int natoms)
1500 for (i = 0; i < natoms; i++)
1507 void pdb2top(FILE *top_file, const char *posre_fn, const char *molname,
1508 t_atoms *atoms, rvec **x, gpp_atomtype *atype, t_symtab *tab,
1509 int nrtp, t_restp rtp[],
1510 t_restp *restp, t_hackblock *hb,
1512 bool bVsites, bool bVsiteAromatics,
1515 int nssbonds, t_ssbond *ssbonds,
1516 real long_bond_dist, real short_bond_dist,
1517 bool bDeuterate, bool bChargeGroups, bool bCmap,
1518 bool bRenumRes, bool bRTPresname)
1524 t_params plist[F_NRE];
1531 gmx_residuetype_t*rt;
1534 gmx_residuetype_init(&rt);
1537 at2bonds(&(plist[F_BONDS]), hb,
1539 long_bond_dist, short_bond_dist);
1541 /* specbonds: disulphide bonds & heme-his */
1542 do_ssbonds(&(plist[F_BONDS]),
1543 atoms, nssbonds, ssbonds,
1546 nmissat = name2type(atoms, &cgnr, restp, rt);
1551 fprintf(stderr, "There were %d missing atoms in molecule %s\n",
1556 gmx_fatal(FARGS, "There were %d missing atoms in molecule %s, if you want to use this incomplete topology anyhow, use the option -missing",
1561 /* Cleanup bonds (sort and rm doubles) */
1562 clean_bonds(&(plist[F_BONDS]));
1564 snew(vsite_type, atoms->nr);
1565 for (i = 0; i < atoms->nr; i++)
1567 vsite_type[i] = NOTSET;
1571 if (bVsiteAromatics)
1573 fprintf(stdout, "The conversion of aromatic rings into virtual sites is deprecated "
1574 "and may be removed in a future version of GROMACS");
1576 /* determine which atoms will be vsites and add dummy masses
1577 also renumber atom numbers in plist[0..F_NRE]! */
1578 do_vsites(nrtp, rtp, atype, atoms, tab, x, plist,
1579 &vsite_type, &cgnr, mHmult, bVsiteAromatics, ffdir);
1582 /* Make Angles and Dihedrals */
1583 fprintf(stderr, "Generating angles, dihedrals and pairs...\n");
1584 snew(excls, atoms->nr);
1585 init_nnb(&nnb, atoms->nr, 4);
1586 gen_nnb(&nnb, plist);
1587 print_nnb(&nnb, "NNB");
1588 gen_pad(&nnb, atoms, restp, plist, excls, hb, bAllowMissing);
1594 gen_cmap(&(plist[F_CMAP]), restp, atoms);
1595 if (plist[F_CMAP].nr > 0)
1597 fprintf(stderr, "There are %4d cmap torsion pairs\n",
1602 /* set mass of all remaining hydrogen atoms */
1605 do_h_mass(&(plist[F_BONDS]), vsite_type, atoms, mHmult, bDeuterate);
1609 /* Cleanup bonds (sort and rm doubles) */
1610 /* clean_bonds(&(plist[F_BONDS]));*/
1613 "There are %4d dihedrals, %4d impropers, %4d angles\n"
1614 " %4d pairs, %4d bonds and %4d virtual sites\n",
1615 plist[F_PDIHS].nr, plist[F_IDIHS].nr, plist[F_ANGLES].nr,
1616 plist[F_LJ14].nr, plist[F_BONDS].nr,
1617 plist[F_VSITE2].nr +
1618 plist[F_VSITE3].nr +
1619 plist[F_VSITE3FD].nr +
1620 plist[F_VSITE3FAD].nr +
1621 plist[F_VSITE3OUT].nr +
1622 plist[F_VSITE4FD].nr +
1623 plist[F_VSITE4FDN].nr );
1625 print_sums(atoms, FALSE);
1629 scrub_charge_groups(cgnr, atoms->nr);
1634 for (i = 0; i < atoms->nres; i++)
1636 atoms->resinfo[i].nr = i + 1;
1637 atoms->resinfo[i].ic = ' ';
1643 fprintf(stderr, "Writing topology\n");
1644 /* We can copy the bonded types from the first restp,
1645 * since the types have to be identical for all residues in one molecule.
1647 for (i = 0; i < ebtsNR; i++)
1649 bts[i] = restp[0].rb[i].type;
1651 write_top(top_file, posre_fn, molname,
1653 bts, plist, excls, atype, cgnr, restp[0].nrexcl);
1657 free_t_hackblock(atoms->nres, &hb);
1658 free_t_restp(atoms->nres, &restp);
1659 gmx_residuetype_destroy(rt);
1661 /* we should clean up hb and restp here, but that is a *L*O*T* of work! */
1663 for (i = 0; i < F_NRE; i++)
1665 sfree(plist[i].param);
1667 for (i = 0; i < atoms->nr; i++)