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, 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.
51 #include "gromacs/fileio/pdbio.h"
52 #include "gromacs/gmxpreprocess/add_par.h"
53 #include "gromacs/gmxpreprocess/fflibutil.h"
54 #include "gromacs/gmxpreprocess/gen_ad.h"
55 #include "gromacs/gmxpreprocess/gen_vsite.h"
56 #include "gromacs/gmxpreprocess/gpp_nextnb.h"
57 #include "gromacs/gmxpreprocess/h_db.h"
58 #include "gromacs/gmxpreprocess/notset.h"
59 #include "gromacs/gmxpreprocess/pgutil.h"
60 #include "gromacs/gmxpreprocess/resall.h"
61 #include "gromacs/gmxpreprocess/topdirs.h"
62 #include "gromacs/gmxpreprocess/topio.h"
63 #include "gromacs/gmxpreprocess/toputil.h"
64 #include "gromacs/math/functions.h"
65 #include "gromacs/math/vec.h"
66 #include "gromacs/topology/residuetypes.h"
67 #include "gromacs/topology/symtab.h"
68 #include "gromacs/utility/binaryinformation.h"
69 #include "gromacs/utility/cstringutil.h"
70 #include "gromacs/utility/dir_separator.h"
71 #include "gromacs/utility/exceptions.h"
72 #include "gromacs/utility/fatalerror.h"
73 #include "gromacs/utility/futil.h"
74 #include "gromacs/utility/niceheader.h"
75 #include "gromacs/utility/path.h"
76 #include "gromacs/utility/programcontext.h"
77 #include "gromacs/utility/smalloc.h"
78 #include "gromacs/utility/strdb.h"
79 #include "gromacs/utility/stringutil.h"
80 #include "gromacs/utility/textwriter.h"
82 /* this must correspond to enum in pdb2top.h */
83 const char *hh[ehisNR] = { "HISD", "HISE", "HISH", "HIS1" };
85 static int missing_atoms(t_restp *rp, int resind, t_atoms *at, int i0, int i)
92 for (j = 0; j < rp->natom; j++)
94 name = *(rp->atomname[j]);
96 for (k = i0; k < i; k++)
98 bFound = (bFound || !gmx_strcasecmp(*(at->atomname[k]), name));
103 fprintf(stderr, "\nWARNING: "
104 "atom %s is missing in residue %s %d in the pdb file\n",
105 name, *(at->resinfo[resind].name), at->resinfo[resind].nr);
106 if (name[0] == 'H' || name[0] == 'h')
108 fprintf(stderr, " You might need to add atom %s to the hydrogen database of building block %s\n"
109 " in the file %s.hdb (see the manual)\n",
110 name, *(at->resinfo[resind].rtp), rp->filebase);
112 fprintf(stderr, "\n");
119 gmx_bool is_int(double x)
121 const double tol = 1e-4;
130 return (fabs(x-ix) < tol);
134 choose_ff_impl(const char *ffsel,
135 char *forcefield, int ff_maxlen,
136 char *ffdir, int ffdir_maxlen)
138 std::vector<gmx::DataFileInfo> ffdirs = fflib_enumerate_forcefields();
139 const int nff = static_cast<int>(ffdirs.size());
141 /* Replace with unix path separators */
142 #if DIR_SEPARATOR != '/'
143 for (int i = 0; i < nff; ++i)
145 std::replace(ffdirs[i].dir.begin(), ffdirs[i].dir.end(), DIR_SEPARATOR, '/');
149 /* Store the force field names in ffs */
150 std::vector<std::string> ffs;
151 ffs.reserve(ffdirs.size());
152 for (int i = 0; i < nff; ++i)
154 ffs.push_back(gmx::stripSuffixIfPresent(ffdirs[i].name,
155 fflib_forcefield_dir_ext()));
159 if (ffsel != nullptr)
164 for (int i = 0; i < nff; ++i)
168 /* Matching ff name */
172 if (ffdirs[i].dir == ".")
189 "Force field '%s' occurs in %d places. pdb2gmx is using the one in the\n"
190 "current directory. Use interactive selection (not the -ff option) if\n"
191 "you would prefer a different one.\n", ffsel, nfound);
195 std::string message = gmx::formatString(
196 "Force field '%s' occurs in %d places, but not in "
197 "the current directory.\n"
198 "Run without the -ff switch and select the force "
199 "field interactively.", ffsel, nfound);
200 GMX_THROW(gmx::InconsistentInputError(message));
203 else if (nfound == 0)
205 std::string message = gmx::formatString(
206 "Could not find force field '%s' in current directory, "
207 "install tree or GMXLIB path.", ffsel);
208 GMX_THROW(gmx::InconsistentInputError(message));
213 std::vector<std::string> desc;
214 desc.reserve(ffdirs.size());
215 for (int i = 0; i < nff; ++i)
217 std::string docFileName(
218 gmx::Path::join(ffdirs[i].dir, ffdirs[i].name,
219 fflib_forcefield_doc()));
220 // TODO: Just try to open the file with a method that does not
221 // throw/bail out with a fatal error instead of multiple checks.
222 if (gmx::File::exists(docFileName, gmx::File::returnFalseOnError))
224 // TODO: Use a C++ API without such an intermediate/fixed-length buffer.
226 /* We don't use fflib_open, because we don't want printf's */
227 FILE *fp = gmx_ffopen(docFileName.c_str(), "r");
228 get_a_line(fp, buf, STRLEN);
230 desc.emplace_back(buf);
234 desc.push_back(ffs[i]);
237 /* Order force fields from the same dir alphabetically
238 * and put deprecated force fields at the end.
240 for (int i = 0; i < nff; ++i)
242 for (int j = i + 1; j < nff; ++j)
244 if (ffdirs[i].dir == ffdirs[j].dir &&
245 ((desc[i][0] == '[' && desc[j][0] != '[') ||
246 ((desc[i][0] == '[' || desc[j][0] != '[') &&
247 gmx_strcasecmp(desc[i].c_str(), desc[j].c_str()) > 0)))
249 std::swap(ffdirs[i].name, ffdirs[j].name);
250 std::swap(ffs[i], ffs[j]);
251 std::swap(desc[i], desc[j]);
256 printf("\nSelect the Force Field:\n");
257 for (int i = 0; i < nff; ++i)
259 if (i == 0 || ffdirs[i-1].dir != ffdirs[i].dir)
261 if (ffdirs[i].dir == ".")
263 printf("From current directory:\n");
267 printf("From '%s':\n", ffdirs[i].dir.c_str());
270 printf("%2d: %s\n", i+1, desc[i].c_str());
274 // TODO: Add a C++ API for this.
279 pret = fgets(buf, STRLEN, stdin);
283 sel = strtol(buf, nullptr, 10);
287 while (pret == nullptr || (sel < 0) || (sel >= nff));
289 /* Check for a current limitation of the fflib code.
290 * It will always read from the first ff directory in the list.
291 * This check assumes that the order of ffs matches the order
292 * in which fflib_open searches ff library files.
294 for (int i = 0; i < sel; i++)
296 if (ffs[i] == ffs[sel])
298 std::string message = gmx::formatString(
299 "Can only select the first of multiple force "
300 "field entries with directory name '%s%s' in "
301 "the list. If you want to use the next entry, "
302 "run pdb2gmx in a different directory, set GMXLIB "
303 "to point to the desired force field first, and/or "
304 "rename or move the force field directory present "
305 "in the current working directory.",
306 ffs[sel].c_str(), fflib_forcefield_dir_ext());
307 GMX_THROW(gmx::NotImplementedError(message));
316 if (ffs[sel].length() >= static_cast<size_t>(ff_maxlen))
318 std::string message = gmx::formatString(
319 "Length of force field name (%d) >= maxlen (%d)",
320 static_cast<int>(ffs[sel].length()), ff_maxlen);
321 GMX_THROW(gmx::InvalidInputError(message));
323 strcpy(forcefield, ffs[sel].c_str());
326 if (ffdirs[sel].bFromDefaultDir)
328 ffpath = ffdirs[sel].name;
332 ffpath = gmx::Path::join(ffdirs[sel].dir, ffdirs[sel].name);
334 if (ffpath.length() >= static_cast<size_t>(ffdir_maxlen))
336 std::string message = gmx::formatString(
337 "Length of force field dir (%d) >= maxlen (%d)",
338 static_cast<int>(ffpath.length()), ffdir_maxlen);
339 GMX_THROW(gmx::InvalidInputError(message));
341 strcpy(ffdir, ffpath.c_str());
345 choose_ff(const char *ffsel,
346 char *forcefield, int ff_maxlen,
347 char *ffdir, int ffdir_maxlen)
351 choose_ff_impl(ffsel, forcefield, ff_maxlen, ffdir, ffdir_maxlen);
353 GMX_CATCH_ALL_AND_EXIT_WITH_FATAL_ERROR;
356 void choose_watermodel(const char *wmsel, const char *ffdir,
359 const char *fn_watermodels = "watermodels.dat";
360 char fn_list[STRLEN];
367 if (strcmp(wmsel, "none") == 0)
369 *watermodel = nullptr;
373 else if (strcmp(wmsel, "select") != 0)
375 *watermodel = gmx_strdup(wmsel);
380 sprintf(fn_list, "%s%c%s", ffdir, DIR_SEPARATOR, fn_watermodels);
382 if (!fflib_fexist(fn_list))
384 fprintf(stderr, "No file '%s' found, will not include a water model\n",
386 *watermodel = nullptr;
391 fp = fflib_open(fn_list);
392 printf("\nSelect the Water Model:\n");
395 while (get_a_line(fp, buf, STRLEN))
397 srenew(model, nwm+1);
398 snew(model[nwm], STRLEN);
399 sscanf(buf, "%s%n", model[nwm], &i);
403 fprintf(stderr, "%2d: %s\n", nwm+1, buf+i);
412 fprintf(stderr, "%2d: %s\n", nwm+1, "None");
417 pret = fgets(buf, STRLEN, stdin);
421 sel = strtol(buf, nullptr, 10);
425 while (pret == nullptr || sel < 0 || sel > nwm);
429 *watermodel = nullptr;
433 *watermodel = gmx_strdup(model[sel]);
436 for (i = 0; i < nwm; i++)
443 static int name2type(t_atoms *at, int **cgnr,
444 t_restp restp[], gmx_residuetype_t *rt)
446 int i, j, prevresind, resind, i0, prevcg, cg, curcg;
464 for (i = 0; (i < at->nr); i++)
467 if (at->atom[i].resind != resind)
470 resind = at->atom[i].resind;
471 bProt = gmx_residuetype_is_protein(rt, *(at->resinfo[resind].name));
472 bNterm = bProt && (resind == 0);
475 nmissat += missing_atoms(&restp[prevresind], prevresind, at, i0, i);
479 if (at->atom[i].m == 0)
483 fprintf(debug, "atom %d%s: curcg=%d, prevcg=%d, cg=%d\n",
484 i+1, *(at->atomname[i]), curcg, prevcg,
485 j == NOTSET ? NOTSET : restp[resind].cgnr[j]);
489 name = *(at->atomname[i]);
490 j = search_jtype(&restp[resind], name, bNterm);
491 at->atom[i].type = restp[resind].atom[j].type;
492 at->atom[i].q = restp[resind].atom[j].q;
493 at->atom[i].m = restp[resind].atom[j].m;
494 cg = restp[resind].cgnr[j];
495 /* A charge group number -1 signals a separate charge group
498 if ( (cg == -1) || (cg != prevcg) || (resind != prevresind) )
507 fprintf(debug, "atom %d%s: curcg=%d, qt=%g, is_int=%d\n",
508 i+1, *(at->atomname[i]), curcg, qt, is_int(qt));
519 at->atom[i].typeB = at->atom[i].type;
520 at->atom[i].qB = at->atom[i].q;
521 at->atom[i].mB = at->atom[i].m;
523 nmissat += missing_atoms(&restp[resind], resind, at, i0, i);
528 static void print_top_heavy_H(FILE *out, real mHmult)
532 fprintf(out, "; Using deuterium instead of hydrogen\n\n");
534 else if (mHmult == 4.0)
536 fprintf(out, "#define HEAVY_H\n\n");
538 else if (mHmult != 1.0)
540 fprintf(stderr, "WARNING: unsupported proton mass multiplier (%g) "
541 "in pdb2top\n", mHmult);
545 void print_top_comment(FILE *out,
546 const char *filename,
550 char ffdir_parent[STRLEN];
555 gmx::TextWriter writer(out);
556 gmx::niceHeader(&writer, filename, ';');
557 writer.writeLine(gmx::formatString(";\tThis is a %s topology file", bITP ? "include" : "standalone"));
558 writer.writeLine(";");
560 gmx::BinaryInformationSettings settings;
561 settings.generatedByHeader(true);
562 settings.linePrefix(";\t");
563 gmx::printBinaryInformation(&writer, gmx::getProgramContext(), settings);
565 GMX_CATCH_ALL_AND_EXIT_WITH_FATAL_ERROR;
567 if (strchr(ffdir, '/') == nullptr)
569 fprintf(out, ";\tForce field was read from the standard GROMACS share directory.\n;\n\n");
571 else if (ffdir[0] == '.')
573 fprintf(out, ";\tForce field was read from current directory or a relative path - path added.\n;\n\n");
577 strncpy(ffdir_parent, ffdir, STRLEN-1);
578 ffdir_parent[STRLEN-1] = '\0'; /*make sure it is 0-terminated even for long string*/
579 p = strrchr(ffdir_parent, '/');
584 ";\tForce field data was read from:\n"
588 ";\tThis might be a non-standard force field location. When you use this topology, the\n"
589 ";\tforce field must either be present in the current directory, or the location\n"
590 ";\tspecified in the GMXLIB path variable or with the 'include' mdp file option.\n;\n\n",
595 void print_top_header(FILE *out, const char *filename,
596 gmx_bool bITP, const char *ffdir, real mHmult)
600 print_top_comment(out, filename, ffdir, bITP);
602 print_top_heavy_H(out, mHmult);
603 fprintf(out, "; Include forcefield parameters\n");
605 p = strrchr(ffdir, '/');
606 p = (ffdir[0] == '.' || p == nullptr) ? ffdir : p+1;
608 fprintf(out, "#include \"%s/%s\"\n\n", p, fflib_forcefield_itp());
611 static void print_top_posre(FILE *out, const char *pr)
613 fprintf(out, "; Include Position restraint file\n");
614 fprintf(out, "#ifdef POSRES\n");
615 fprintf(out, "#include \"%s\"\n", pr);
616 fprintf(out, "#endif\n\n");
619 static void print_top_water(FILE *out, const char *ffdir, const char *water)
624 fprintf(out, "; Include water topology\n");
626 p = strrchr(ffdir, '/');
627 p = (ffdir[0] == '.' || p == nullptr) ? ffdir : p+1;
628 fprintf(out, "#include \"%s/%s.itp\"\n", p, water);
631 fprintf(out, "#ifdef POSRES_WATER\n");
632 fprintf(out, "; Position restraint for each water oxygen\n");
633 fprintf(out, "[ position_restraints ]\n");
634 fprintf(out, ";%3s %5s %9s %10s %10s\n", "i", "funct", "fcx", "fcy", "fcz");
635 fprintf(out, "%4d %4d %10g %10g %10g\n", 1, 1, 1000.0, 1000.0, 1000.0);
636 fprintf(out, "#endif\n");
639 sprintf(buf, "%s/ions.itp", p);
641 if (fflib_fexist(buf))
643 fprintf(out, "; Include topology for ions\n");
644 fprintf(out, "#include \"%s\"\n", buf);
649 static void print_top_system(FILE *out, const char *title)
651 fprintf(out, "[ %s ]\n", dir2str(d_system));
652 fprintf(out, "; Name\n");
653 fprintf(out, "%s\n\n", title[0] ? title : "Protein");
656 void print_top_mols(FILE *out,
657 const char *title, const char *ffdir, const char *water,
658 int nincl, char **incls, int nmol, t_mols *mols)
665 fprintf(out, "; Include chain topologies\n");
666 for (i = 0; (i < nincl); i++)
668 incl = strrchr(incls[i], DIR_SEPARATOR);
675 /* Remove the path from the include name */
678 fprintf(out, "#include \"%s\"\n", incl);
685 print_top_water(out, ffdir, water);
687 print_top_system(out, title);
691 fprintf(out, "[ %s ]\n", dir2str(d_molecules));
692 fprintf(out, "; %-15s %5s\n", "Compound", "#mols");
693 for (i = 0; (i < nmol); i++)
695 fprintf(out, "%-15s %5d\n", mols[i].name, mols[i].nr);
700 void write_top(FILE *out, char *pr, const char *molname,
701 t_atoms *at, gmx_bool bRTPresname,
702 int bts[], t_params plist[], t_excls excls[],
703 gpp_atomtype_t atype, int *cgnr, int nrexcl)
704 /* NOTE: nrexcl is not the size of *excl! */
706 if (at && atype && cgnr)
708 fprintf(out, "[ %s ]\n", dir2str(d_moleculetype));
709 fprintf(out, "; %-15s %5s\n", "Name", "nrexcl");
710 fprintf(out, "%-15s %5d\n\n", molname ? molname : "Protein", nrexcl);
712 print_atoms(out, atype, at, cgnr, bRTPresname);
713 print_bondeds(out, at->nr, d_bonds, F_BONDS, bts[ebtsBONDS], plist);
714 print_bondeds(out, at->nr, d_constraints, F_CONSTR, 0, plist);
715 print_bondeds(out, at->nr, d_constraints, F_CONSTRNC, 0, plist);
716 print_bondeds(out, at->nr, d_pairs, F_LJ14, 0, plist);
717 print_excl(out, at->nr, excls);
718 print_bondeds(out, at->nr, d_angles, F_ANGLES, bts[ebtsANGLES], plist);
719 print_bondeds(out, at->nr, d_dihedrals, F_PDIHS, bts[ebtsPDIHS], plist);
720 print_bondeds(out, at->nr, d_dihedrals, F_IDIHS, bts[ebtsIDIHS], plist);
721 print_bondeds(out, at->nr, d_cmap, F_CMAP, bts[ebtsCMAP], plist);
722 print_bondeds(out, at->nr, d_polarization, F_POLARIZATION, 0, plist);
723 print_bondeds(out, at->nr, d_thole_polarization, F_THOLE_POL, 0, plist);
724 print_bondeds(out, at->nr, d_vsites2, F_VSITE2, 0, plist);
725 print_bondeds(out, at->nr, d_vsites3, F_VSITE3, 0, plist);
726 print_bondeds(out, at->nr, d_vsites3, F_VSITE3FD, 0, plist);
727 print_bondeds(out, at->nr, d_vsites3, F_VSITE3FAD, 0, plist);
728 print_bondeds(out, at->nr, d_vsites3, F_VSITE3OUT, 0, plist);
729 print_bondeds(out, at->nr, d_vsites4, F_VSITE4FD, 0, plist);
730 print_bondeds(out, at->nr, d_vsites4, F_VSITE4FDN, 0, plist);
734 print_top_posre(out, pr);
741 static void do_ssbonds(t_params *ps, t_atoms *atoms,
742 int nssbonds, t_ssbond *ssbonds, gmx_bool bAllowMissing)
747 for (i = 0; (i < nssbonds); i++)
749 ri = ssbonds[i].res1;
750 rj = ssbonds[i].res2;
751 ai = search_res_atom(ssbonds[i].a1, ri, atoms,
752 "special bond", bAllowMissing);
753 aj = search_res_atom(ssbonds[i].a2, rj, atoms,
754 "special bond", bAllowMissing);
755 if ((ai == -1) || (aj == -1))
757 gmx_fatal(FARGS, "Trying to make impossible special bond (%s-%s)!",
758 ssbonds[i].a1, ssbonds[i].a2);
760 add_param(ps, ai, aj, nullptr, nullptr);
764 static void at2bonds(t_params *psb, t_hackblock *hb,
767 real long_bond_dist, real short_bond_dist)
771 real dist2, long_bond_dist2, short_bond_dist2;
774 long_bond_dist2 = gmx::square(long_bond_dist);
775 short_bond_dist2 = gmx::square(short_bond_dist);
786 fprintf(stderr, "Making bonds...\n");
788 for (resind = 0; (resind < atoms->nres) && (i < atoms->nr); resind++)
790 /* add bonds from list of bonded interactions */
791 for (j = 0; j < hb[resind].rb[ebtsBONDS].nb; j++)
793 /* Unfortunately we can not issue errors or warnings
794 * for missing atoms in bonds, as the hydrogens and terminal atoms
795 * have not been added yet.
797 ai = search_atom(hb[resind].rb[ebtsBONDS].b[j].a[0], i, atoms,
799 aj = search_atom(hb[resind].rb[ebtsBONDS].b[j].a[1], i, atoms,
801 if (ai != -1 && aj != -1)
803 dist2 = distance2(x[ai], x[aj]);
804 if (dist2 > long_bond_dist2)
807 fprintf(stderr, "Warning: Long Bond (%d-%d = %g nm)\n",
808 ai+1, aj+1, std::sqrt(dist2));
810 else if (dist2 < short_bond_dist2)
812 fprintf(stderr, "Warning: Short Bond (%d-%d = %g nm)\n",
813 ai+1, aj+1, std::sqrt(dist2));
815 add_param(psb, ai, aj, nullptr, hb[resind].rb[ebtsBONDS].b[j].s);
818 /* add bonds from list of hacks (each added atom gets a bond) */
819 while ( (i < atoms->nr) && (atoms->atom[i].resind == resind) )
821 for (j = 0; j < hb[resind].nhack; j++)
823 if ( ( hb[resind].hack[j].tp > 0 ||
824 hb[resind].hack[j].oname == nullptr ) &&
825 strcmp(hb[resind].hack[j].a[0], *(atoms->atomname[i])) == 0)
827 switch (hb[resind].hack[j].tp)
829 case 9: /* COOH terminus */
830 add_param(psb, i, i+1, nullptr, nullptr); /* C-O */
831 add_param(psb, i, i+2, nullptr, nullptr); /* C-OA */
832 add_param(psb, i+2, i+3, nullptr, nullptr); /* OA-H */
835 for (k = 0; (k < hb[resind].hack[j].nr); k++)
837 add_param(psb, i, i+k+1, nullptr, nullptr);
844 /* we're now at the start of the next residue */
848 static int pcompar(const void *a, const void *b)
850 const t_param *pa, *pb;
852 pa = static_cast<const t_param *>(a);
853 pb = static_cast<const t_param *>(b);
855 d = pa->a[0] - pb->a[0];
858 d = pa->a[1] - pb->a[1];
862 return strlen(pb->s) - strlen(pa->s);
870 static void clean_bonds(t_params *ps)
877 /* swap atomnumbers in bond if first larger than second: */
878 for (i = 0; (i < ps->nr); i++)
880 if (ps->param[i].a[1] < ps->param[i].a[0])
882 a = ps->param[i].a[0];
883 ps->param[i].a[0] = ps->param[i].a[1];
884 ps->param[i].a[1] = a;
889 qsort(ps->param, ps->nr, (size_t)sizeof(ps->param[0]), pcompar);
891 /* remove doubles, keep the first one always. */
893 for (i = 1; (i < ps->nr); i++)
895 if ((ps->param[i].a[0] != ps->param[j-1].a[0]) ||
896 (ps->param[i].a[1] != ps->param[j-1].a[1]) )
900 cp_param(&(ps->param[j]), &(ps->param[i]));
905 fprintf(stderr, "Number of bonds was %d, now %d\n", ps->nr, j);
910 fprintf(stderr, "No bonds\n");
914 void print_sums(t_atoms *atoms, gmx_bool bSystem)
922 where = " in system";
931 for (i = 0; (i < atoms->nr); i++)
933 m += atoms->atom[i].m;
934 qtot += atoms->atom[i].q;
937 fprintf(stderr, "Total mass%s %.3f a.m.u.\n", where, m);
938 fprintf(stderr, "Total charge%s %.3f e\n", where, qtot);
941 static void check_restp_type(const char *name, int t1, int t2)
945 gmx_fatal(FARGS, "Residues in one molecule have a different '%s' type: %d and %d", name, t1, t2);
949 static void check_restp_types(t_restp *r0, t_restp *r1)
953 check_restp_type("all dihedrals", r0->bKeepAllGeneratedDihedrals, r1->bKeepAllGeneratedDihedrals);
954 check_restp_type("nrexcl", r0->nrexcl, r1->nrexcl);
955 check_restp_type("HH14", r0->bGenerateHH14Interactions, r1->bGenerateHH14Interactions);
956 check_restp_type("remove dihedrals", r0->bRemoveDihedralIfWithImproper, r1->bRemoveDihedralIfWithImproper);
958 for (i = 0; i < ebtsNR; i++)
960 check_restp_type(btsNames[i], r0->rb[i].type, r1->rb[i].type);
964 static void add_atom_to_restp(t_restp *restp, int at_start, const t_hack *hack)
968 const char *Hnum = "123456";
972 fprintf(debug,"adding atom(s) %s to atom %s in res %d%s in rtp\n",
974 * restp->atomname[at_start], resnr, restp->resname);
976 strcpy(buf, hack->nname);
977 buf[strlen(buf)+1] = '\0';
980 buf[strlen(buf)] = '-';
983 restp->natom += hack->nr;
984 srenew(restp->atom, restp->natom);
985 srenew(restp->atomname, restp->natom);
986 srenew(restp->cgnr, restp->natom);
988 for (k = restp->natom-1; k > at_start+hack->nr; k--)
991 restp->atom [k - hack->nr];
993 restp->atomname[k - hack->nr];
995 restp->cgnr [k - hack->nr];
998 for (k = 0; k < hack->nr; k++)
1000 /* set counter in atomname */
1003 buf[strlen(buf)-1] = Hnum[k];
1005 snew( restp->atomname[at_start+1+k], 1);
1006 restp->atom [at_start+1+k] = *hack->atom;
1007 *restp->atomname[at_start+1+k] = gmx_strdup(buf);
1008 if (hack->cgnr != NOTSET)
1010 restp->cgnr [at_start+1+k] = hack->cgnr;
1014 restp->cgnr [at_start+1+k] = restp->cgnr[at_start];
1019 void get_hackblocks_rtp(t_hackblock **hb, t_restp **restp,
1020 int nrtp, t_restp rtp[],
1021 int nres, t_resinfo *resinfo,
1023 t_hackblock **ntdb, t_hackblock **ctdb,
1024 const int *rn, const int *rc,
1025 gmx_bool bAllowMissing)
1035 /* first the termini */
1036 for (i = 0; i < nterpairs; i++)
1038 if (rn[i] >= 0 && ntdb[i] != nullptr)
1040 copy_t_hackblock(ntdb[i], &(*hb)[rn[i]]);
1042 if (rc[i] >= 0 && ctdb[i] != nullptr)
1044 merge_t_hackblock(ctdb[i], &(*hb)[rc[i]]);
1048 /* then the whole rtp */
1049 for (i = 0; i < nres; i++)
1051 /* Here we allow a mismatch of one character when looking for the rtp entry.
1052 * For such a mismatch there should be only one mismatching name.
1053 * This is mainly useful for small molecules such as ions.
1054 * Note that this will usually not work for protein, DNA and RNA,
1055 * since there the residue names should be listed in residuetypes.dat
1056 * and an error will have been generated earlier in the process.
1058 key = *resinfo[i].rtp;
1059 snew(resinfo[i].rtp, 1);
1060 *resinfo[i].rtp = search_rtp(key, nrtp, rtp);
1061 res = get_restp(*resinfo[i].rtp, nrtp, rtp);
1062 copy_t_restp(res, &(*restp)[i]);
1064 /* Check that we do not have different bonded types in one molecule */
1065 check_restp_types(&(*restp)[0], &(*restp)[i]);
1068 for (j = 0; j < nterpairs && tern == -1; j++)
1076 for (j = 0; j < nterpairs && terc == -1; j++)
1083 bRM = merge_t_bondeds(res->rb, (*hb)[i].rb, tern >= 0, terc >= 0);
1085 if (bRM && ((tern >= 0 && ntdb[tern] == nullptr) ||
1086 (terc >= 0 && ctdb[terc] == nullptr)))
1088 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).";
1091 fprintf(stderr, "%s\n", errString);
1095 gmx_fatal(FARGS, errString);
1098 else if (bRM && ((tern >= 0 && ntdb[tern]->nhack == 0) ||
1099 (terc >= 0 && ctdb[terc]->nhack == 0)))
1101 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.";
1104 fprintf(stderr, "%s\n", errString);
1108 gmx_fatal(FARGS, errString);
1113 /* now perform t_hack's on t_restp's,
1114 i.e. add's and deletes from termini database will be
1115 added to/removed from residue topology
1116 we'll do this on one big dirty loop, so it won't make easy reading! */
1117 for (i = 0; i < nres; i++)
1119 for (j = 0; j < (*hb)[i].nhack; j++)
1121 if ( (*hb)[i].hack[j].nr)
1123 /* find atom in restp */
1124 for (l = 0; l < (*restp)[i].natom; l++)
1126 if ( ( (*hb)[i].hack[j].oname == nullptr &&
1127 strcmp((*hb)[i].hack[j].a[0], *(*restp)[i].atomname[l]) == 0 ) ||
1128 ( (*hb)[i].hack[j].oname != nullptr &&
1129 strcmp((*hb)[i].hack[j].oname, *(*restp)[i].atomname[l]) == 0 ) )
1134 if (l == (*restp)[i].natom)
1136 /* If we are doing an atom rename only, we don't need
1137 * to generate a fatal error if the old name is not found
1140 /* Deleting can happen also only on the input atoms,
1141 * not necessarily always on the rtp entry.
1143 if (!((*hb)[i].hack[j].oname != nullptr &&
1144 (*hb)[i].hack[j].nname != nullptr) &&
1145 !((*hb)[i].hack[j].oname != nullptr &&
1146 (*hb)[i].hack[j].nname == nullptr))
1149 "atom %s not found in buiding block %d%s "
1150 "while combining tdb and rtp",
1151 (*hb)[i].hack[j].oname != nullptr ?
1152 (*hb)[i].hack[j].oname : (*hb)[i].hack[j].a[0],
1153 i+1, *resinfo[i].rtp);
1158 if ( (*hb)[i].hack[j].oname == nullptr)
1161 add_atom_to_restp(&(*restp)[i], l, &(*hb)[i].hack[j]);
1166 if ( (*hb)[i].hack[j].nname == nullptr)
1168 /* we're deleting */
1171 fprintf(debug, "deleting atom %s from res %d%s in rtp\n",
1172 *(*restp)[i].atomname[l],
1173 i+1, (*restp)[i].resname);
1175 /* shift the rest */
1176 (*restp)[i].natom--;
1177 for (k = l; k < (*restp)[i].natom; k++)
1179 (*restp)[i].atom [k] = (*restp)[i].atom [k+1];
1180 (*restp)[i].atomname[k] = (*restp)[i].atomname[k+1];
1181 (*restp)[i].cgnr [k] = (*restp)[i].cgnr [k+1];
1183 /* give back space */
1184 srenew((*restp)[i].atom, (*restp)[i].natom);
1185 srenew((*restp)[i].atomname, (*restp)[i].natom);
1186 srenew((*restp)[i].cgnr, (*restp)[i].natom);
1188 else /* nname != NULL */
1189 { /* we're replacing */
1192 fprintf(debug, "replacing atom %s by %s in res %d%s in rtp\n",
1193 *(*restp)[i].atomname[l], (*hb)[i].hack[j].nname,
1194 i+1, (*restp)[i].resname);
1196 snew( (*restp)[i].atomname[l], 1);
1197 (*restp)[i].atom[l] = *(*hb)[i].hack[j].atom;
1198 *(*restp)[i].atomname[l] = gmx_strdup((*hb)[i].hack[j].nname);
1199 if ( (*hb)[i].hack[j].cgnr != NOTSET)
1201 (*restp)[i].cgnr [l] = (*hb)[i].hack[j].cgnr;
1211 static gmx_bool atomname_cmp_nr(const char *anm, t_hack *hack, int *nr)
1218 return (gmx_strcasecmp(anm, hack->nname) == 0);
1222 if (isdigit(anm[strlen(anm)-1]))
1224 *nr = anm[strlen(anm)-1] - '0';
1230 if (*nr <= 0 || *nr > hack->nr)
1236 return (strlen(anm) == strlen(hack->nname) + 1 &&
1237 gmx_strncasecmp(anm, hack->nname, strlen(hack->nname)) == 0);
1242 static gmx_bool match_atomnames_with_rtp_atom(t_atoms *pdba, rvec *x, int atind,
1243 t_restp *rptr, t_hackblock *hbr,
1248 char *oldnm, *newnm;
1250 char *start_at, buf[STRLEN];
1252 gmx_bool bReplaceReplace, bFoundInAdd;
1255 oldnm = *pdba->atomname[atind];
1256 resnr = pdba->resinfo[pdba->atom[atind].resind].nr;
1259 for (j = 0; j < hbr->nhack; j++)
1261 if (hbr->hack[j].oname != nullptr && hbr->hack[j].nname != nullptr &&
1262 gmx_strcasecmp(oldnm, hbr->hack[j].oname) == 0)
1264 /* This is a replace entry. */
1265 /* Check if we are not replacing a replaced atom. */
1266 bReplaceReplace = FALSE;
1267 for (k = 0; k < hbr->nhack; k++)
1270 hbr->hack[k].oname != nullptr && hbr->hack[k].nname != nullptr &&
1271 gmx_strcasecmp(hbr->hack[k].nname, hbr->hack[j].oname) == 0)
1273 /* The replace in hack[j] replaces an atom that
1274 * was already replaced in hack[k], we do not want
1275 * second or higher level replaces at this stage.
1277 bReplaceReplace = TRUE;
1280 if (bReplaceReplace)
1282 /* Skip this replace. */
1286 /* This atom still has the old name, rename it */
1287 newnm = hbr->hack[j].nname;
1288 for (k = 0; k < rptr->natom; k++)
1290 if (gmx_strcasecmp(newnm, *rptr->atomname[k]) == 0)
1295 if (k == rptr->natom)
1297 /* The new name is not present in the rtp.
1298 * We need to apply the replace also to the rtp entry.
1301 /* We need to find the add hack that can add this atom
1302 * to find out after which atom it should be added.
1304 bFoundInAdd = FALSE;
1305 for (k = 0; k < hbr->nhack; k++)
1307 if (hbr->hack[k].oname == nullptr &&
1308 hbr->hack[k].nname != nullptr &&
1309 atomname_cmp_nr(newnm, &hbr->hack[k], &anmnr))
1313 start_at = hbr->hack[k].a[0];
1317 sprintf(buf, "%s%d", hbr->hack[k].nname, anmnr-1);
1320 for (start_nr = 0; start_nr < rptr->natom; start_nr++)
1322 if (gmx_strcasecmp(start_at, (*rptr->atomname[start_nr])) == 0)
1327 if (start_nr == rptr->natom)
1329 gmx_fatal(FARGS, "Could not find atom '%s' in residue building block '%s' to add atom '%s' to",
1330 start_at, rptr->resname, newnm);
1332 /* We can add the atom after atom start_nr */
1333 add_atom_to_restp(rptr, start_nr, &hbr->hack[j]);
1341 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'",
1343 hbr->hack[j].oname, hbr->hack[j].nname,
1350 printf("Renaming atom '%s' in residue '%s' %d to '%s'\n",
1351 oldnm, rptr->resname, resnr, newnm);
1353 /* Rename the atom in pdba */
1354 snew(pdba->atomname[atind], 1);
1355 *pdba->atomname[atind] = gmx_strdup(newnm);
1357 else if (hbr->hack[j].oname != nullptr && hbr->hack[j].nname == nullptr &&
1358 gmx_strcasecmp(oldnm, hbr->hack[j].oname) == 0)
1360 /* This is a delete entry, check if this atom is present
1361 * in the rtp entry of this residue.
1363 for (k = 0; k < rptr->natom; k++)
1365 if (gmx_strcasecmp(oldnm, *rptr->atomname[k]) == 0)
1370 if (k == rptr->natom)
1372 /* This atom is not present in the rtp entry,
1373 * delete is now from the input pdba.
1377 printf("Deleting atom '%s' in residue '%s' %d\n",
1378 oldnm, rptr->resname, resnr);
1380 /* We should free the atom name,
1381 * but it might be used multiple times in the symtab.
1382 * sfree(pdba->atomname[atind]);
1384 for (k = atind+1; k < pdba->nr; k++)
1386 pdba->atom[k-1] = pdba->atom[k];
1387 pdba->atomname[k-1] = pdba->atomname[k];
1388 copy_rvec(x[k], x[k-1]);
1399 void match_atomnames_with_rtp(t_restp restp[], t_hackblock hb[],
1400 t_atoms *pdba, rvec *x,
1407 for (i = 0; i < pdba->nr; i++)
1409 oldnm = *pdba->atomname[i];
1410 rptr = &restp[pdba->atom[i].resind];
1411 for (j = 0; (j < rptr->natom); j++)
1413 if (gmx_strcasecmp(oldnm, *(rptr->atomname[j])) == 0)
1418 if (j == rptr->natom)
1420 /* Not found yet, check if we have to rename this atom */
1421 if (match_atomnames_with_rtp_atom(pdba, x, i,
1422 rptr, &(hb[pdba->atom[i].resind]),
1425 /* We deleted this atom, decrease the atom counter by 1. */
1432 #define NUM_CMAP_ATOMS 5
1433 static void gen_cmap(t_params *psb, t_restp *restp, t_atoms *atoms)
1435 int residx, i, j, k;
1438 t_resinfo *resinfo = atoms->resinfo;
1439 int nres = atoms->nres;
1441 int cmap_atomid[NUM_CMAP_ATOMS];
1442 int cmap_chainnum = -1, this_residue_index;
1453 fprintf(stderr, "Making cmap torsions...\n");
1455 /* Most cmap entries use the N atom from the next residue, so the last
1456 * residue should not have its CMAP entry in that case, but for things like
1457 * dipeptides we sometimes define a complete CMAP entry inside a residue,
1458 * and in this case we need to process everything through the last residue.
1460 for (residx = 0; residx < nres; residx++)
1462 /* Add CMAP terms from the list of CMAP interactions */
1463 for (j = 0; j < restp[residx].rb[ebtsCMAP].nb; j++)
1466 /* Loop over atoms in a candidate CMAP interaction and
1467 * check that they exist, are from the same chain and are
1468 * from residues labelled as protein. */
1469 for (k = 0; k < NUM_CMAP_ATOMS && bAddCMAP; k++)
1471 /* Assign the pointer to the name of the next reference atom.
1472 * This can use -/+ labels to refer to previous/next residue.
1474 pname = restp[residx].rb[ebtsCMAP].b[j].a[k];
1475 /* Skip this CMAP entry if it refers to residues before the
1476 * first or after the last residue.
1478 if (((strchr(pname, '-') != nullptr) && (residx == 0)) ||
1479 ((strchr(pname, '+') != nullptr) && (residx == nres-1)))
1485 cmap_atomid[k] = search_atom(pname,
1486 i, atoms, ptr, TRUE);
1487 bAddCMAP = bAddCMAP && (cmap_atomid[k] != -1);
1490 /* This break is necessary, because cmap_atomid[k]
1491 * == -1 cannot be safely used as an index
1492 * into the atom array. */
1495 this_residue_index = atoms->atom[cmap_atomid[k]].resind;
1498 cmap_chainnum = resinfo[this_residue_index].chainnum;
1502 /* Does the residue for this atom have the same
1503 * chain number as the residues for previous
1505 bAddCMAP = bAddCMAP &&
1506 cmap_chainnum == resinfo[this_residue_index].chainnum;
1508 /* Here we used to check that the residuetype was protein and
1509 * disable bAddCMAP if that was not the case. However, some
1510 * special residues (say, alanine dipeptides) might not adhere
1511 * to standard naming, and if we start calling them normal
1512 * protein residues the user will be bugged to select termini.
1514 * Instead, I believe that the right course of action is to
1515 * keep the CMAP interaction if it is present in the RTP file
1516 * and we correctly identified all atoms (which is the case
1523 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);
1527 if (residx < nres-1)
1529 while (atoms->atom[i].resind < residx+1)
1535 /* Start the next residue */
1539 scrub_charge_groups(int *cgnr, int natoms)
1543 for (i = 0; i < natoms; i++)
1550 void pdb2top(FILE *top_file, char *posre_fn, char *molname,
1551 t_atoms *atoms, rvec **x, gpp_atomtype_t atype, t_symtab *tab,
1552 int nrtp, t_restp rtp[],
1553 t_restp *restp, t_hackblock *hb,
1554 gmx_bool bAllowMissing,
1555 gmx_bool bVsites, gmx_bool bVsiteAromatics,
1558 int nssbonds, t_ssbond *ssbonds,
1559 real long_bond_dist, real short_bond_dist,
1560 gmx_bool bDeuterate, gmx_bool bChargeGroups, gmx_bool bCmap,
1561 gmx_bool bRenumRes, gmx_bool bRTPresname)
1567 t_params plist[F_NRE];
1574 gmx_residuetype_t*rt;
1577 gmx_residuetype_init(&rt);
1581 print_resall(debug, atoms->nres, restp, atype);
1582 dump_hb(debug, atoms->nres, hb);
1586 at2bonds(&(plist[F_BONDS]), hb,
1588 long_bond_dist, short_bond_dist);
1590 /* specbonds: disulphide bonds & heme-his */
1591 do_ssbonds(&(plist[F_BONDS]),
1592 atoms, nssbonds, ssbonds,
1595 nmissat = name2type(atoms, &cgnr, restp, rt);
1600 fprintf(stderr, "There were %d missing atoms in molecule %s\n",
1605 gmx_fatal(FARGS, "There were %d missing atoms in molecule %s, if you want to use this incomplete topology anyhow, use the option -missing",
1610 /* Cleanup bonds (sort and rm doubles) */
1611 clean_bonds(&(plist[F_BONDS]));
1613 snew(vsite_type, atoms->nr);
1614 for (i = 0; i < atoms->nr; i++)
1616 vsite_type[i] = NOTSET;
1620 /* determine which atoms will be vsites and add dummy masses
1621 also renumber atom numbers in plist[0..F_NRE]! */
1622 do_vsites(nrtp, rtp, atype, atoms, tab, x, plist,
1623 &vsite_type, &cgnr, mHmult, bVsiteAromatics, ffdir);
1626 /* Make Angles and Dihedrals */
1627 fprintf(stderr, "Generating angles, dihedrals and pairs...\n");
1628 snew(excls, atoms->nr);
1629 init_nnb(&nnb, atoms->nr, 4);
1630 gen_nnb(&nnb, plist);
1631 print_nnb(&nnb, "NNB");
1632 gen_pad(&nnb, atoms, restp, plist, excls, hb, bAllowMissing);
1638 gen_cmap(&(plist[F_CMAP]), restp, atoms);
1639 if (plist[F_CMAP].nr > 0)
1641 fprintf(stderr, "There are %4d cmap torsion pairs\n",
1646 /* set mass of all remaining hydrogen atoms */
1649 do_h_mass(&(plist[F_BONDS]), vsite_type, atoms, mHmult, bDeuterate);
1653 /* Cleanup bonds (sort and rm doubles) */
1654 /* clean_bonds(&(plist[F_BONDS]));*/
1657 "There are %4d dihedrals, %4d impropers, %4d angles\n"
1658 " %4d pairs, %4d bonds and %4d virtual sites\n",
1659 plist[F_PDIHS].nr, plist[F_IDIHS].nr, plist[F_ANGLES].nr,
1660 plist[F_LJ14].nr, plist[F_BONDS].nr,
1661 plist[F_VSITE2].nr +
1662 plist[F_VSITE3].nr +
1663 plist[F_VSITE3FD].nr +
1664 plist[F_VSITE3FAD].nr +
1665 plist[F_VSITE3OUT].nr +
1666 plist[F_VSITE4FD].nr +
1667 plist[F_VSITE4FDN].nr );
1669 print_sums(atoms, FALSE);
1671 if (FALSE == bChargeGroups)
1673 scrub_charge_groups(cgnr, atoms->nr);
1678 for (i = 0; i < atoms->nres; i++)
1680 atoms->resinfo[i].nr = i + 1;
1681 atoms->resinfo[i].ic = ' ';
1687 fprintf(stderr, "Writing topology\n");
1688 /* We can copy the bonded types from the first restp,
1689 * since the types have to be identical for all residues in one molecule.
1691 for (i = 0; i < ebtsNR; i++)
1693 bts[i] = restp[0].rb[i].type;
1695 write_top(top_file, posre_fn, molname,
1697 bts, plist, excls, atype, cgnr, restp[0].nrexcl);
1701 free_t_hackblock(atoms->nres, &hb);
1702 free_t_restp(atoms->nres, &restp);
1703 gmx_residuetype_destroy(rt);
1705 /* we should clean up hb and restp here, but that is a *L*O*T* of work! */
1707 for (i = 0; i < F_NRE; i++)
1709 sfree(plist[i].param);
1711 for (i = 0; i < atoms->nr; i++)