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/strconvert.h"
79 #include "gromacs/utility/strdb.h"
80 #include "gromacs/utility/stringutil.h"
81 #include "gromacs/utility/textwriter.h"
83 /* this must correspond to enum in pdb2top.h */
84 const char *hh[ehisNR] = { "HISD", "HISE", "HISH", "HIS1" };
86 static int missing_atoms(t_restp *rp, int resind, t_atoms *at, int i0, int i)
93 for (j = 0; j < rp->natom; j++)
95 name = *(rp->atomname[j]);
97 for (k = i0; k < i; k++)
99 bFound = (bFound || !gmx_strcasecmp(*(at->atomname[k]), name));
104 fprintf(stderr, "\nWARNING: "
105 "atom %s is missing in residue %s %d in the pdb file\n",
106 name, *(at->resinfo[resind].name), at->resinfo[resind].nr);
107 if (name[0] == 'H' || name[0] == 'h')
109 fprintf(stderr, " You might need to add atom %s to the hydrogen database of building block %s\n"
110 " in the file %s.hdb (see the manual)\n",
111 name, *(at->resinfo[resind].rtp), rp->filebase);
113 fprintf(stderr, "\n");
120 bool is_int(double x)
122 const double tol = 1e-4;
131 return (fabs(x-ix) < tol);
135 choose_ff_impl(const char *ffsel,
136 char *forcefield, int ff_maxlen,
137 char *ffdir, int ffdir_maxlen)
139 std::vector<gmx::DataFileInfo> ffdirs = fflib_enumerate_forcefields();
140 const int nff = static_cast<int>(ffdirs.size());
142 /* Replace with unix path separators */
143 #if DIR_SEPARATOR != '/'
144 for (int i = 0; i < nff; ++i)
146 std::replace(ffdirs[i].dir.begin(), ffdirs[i].dir.end(), DIR_SEPARATOR, '/');
150 /* Store the force field names in ffs */
151 std::vector<std::string> ffs;
152 ffs.reserve(ffdirs.size());
153 for (int i = 0; i < nff; ++i)
155 ffs.push_back(gmx::stripSuffixIfPresent(ffdirs[i].name,
156 fflib_forcefield_dir_ext()));
160 if (ffsel != nullptr)
165 for (int i = 0; i < nff; ++i)
169 /* Matching ff name */
173 if (ffdirs[i].dir == ".")
190 "Force field '%s' occurs in %d places. pdb2gmx is using the one in the\n"
191 "current directory. Use interactive selection (not the -ff option) if\n"
192 "you would prefer a different one.\n", ffsel, nfound);
196 std::string message = gmx::formatString(
197 "Force field '%s' occurs in %d places, but not in "
198 "the current directory.\n"
199 "Run without the -ff switch and select the force "
200 "field interactively.", ffsel, nfound);
201 GMX_THROW(gmx::InconsistentInputError(message));
204 else if (nfound == 0)
206 std::string message = gmx::formatString(
207 "Could not find force field '%s' in current directory, "
208 "install tree or GMXLIB path.", ffsel);
209 GMX_THROW(gmx::InconsistentInputError(message));
214 std::vector<std::string> desc;
215 desc.reserve(ffdirs.size());
216 for (int i = 0; i < nff; ++i)
218 std::string docFileName(
219 gmx::Path::join(ffdirs[i].dir, ffdirs[i].name,
220 fflib_forcefield_doc()));
221 // TODO: Just try to open the file with a method that does not
222 // throw/bail out with a fatal error instead of multiple checks.
223 if (gmx::File::exists(docFileName, gmx::File::returnFalseOnError))
225 // TODO: Use a C++ API without such an intermediate/fixed-length buffer.
227 /* We don't use fflib_open, because we don't want printf's */
228 FILE *fp = gmx_ffopen(docFileName.c_str(), "r");
229 get_a_line(fp, buf, STRLEN);
231 desc.emplace_back(buf);
235 desc.push_back(ffs[i]);
238 /* Order force fields from the same dir alphabetically
239 * and put deprecated force fields at the end.
241 for (int i = 0; i < nff; ++i)
243 for (int j = i + 1; j < nff; ++j)
245 if (ffdirs[i].dir == ffdirs[j].dir &&
246 ((desc[i][0] == '[' && desc[j][0] != '[') ||
247 ((desc[i][0] == '[' || desc[j][0] != '[') &&
248 gmx_strcasecmp(desc[i].c_str(), desc[j].c_str()) > 0)))
250 std::swap(ffdirs[i].name, ffdirs[j].name);
251 std::swap(ffs[i], ffs[j]);
252 std::swap(desc[i], desc[j]);
257 printf("\nSelect the Force Field:\n");
258 for (int i = 0; i < nff; ++i)
260 if (i == 0 || ffdirs[i-1].dir != ffdirs[i].dir)
262 if (ffdirs[i].dir == ".")
264 printf("From current directory:\n");
268 printf("From '%s':\n", ffdirs[i].dir.c_str());
271 printf("%2d: %s\n", i+1, desc[i].c_str());
275 // TODO: Add a C++ API for this.
280 pret = fgets(buf, STRLEN, stdin);
284 sel = strtol(buf, nullptr, 10);
288 while (pret == nullptr || (sel < 0) || (sel >= nff));
290 /* Check for a current limitation of the fflib code.
291 * It will always read from the first ff directory in the list.
292 * This check assumes that the order of ffs matches the order
293 * in which fflib_open searches ff library files.
295 for (int i = 0; i < sel; i++)
297 if (ffs[i] == ffs[sel])
299 std::string message = gmx::formatString(
300 "Can only select the first of multiple force "
301 "field entries with directory name '%s%s' in "
302 "the list. If you want to use the next entry, "
303 "run pdb2gmx in a different directory, set GMXLIB "
304 "to point to the desired force field first, and/or "
305 "rename or move the force field directory present "
306 "in the current working directory.",
307 ffs[sel].c_str(), fflib_forcefield_dir_ext());
308 GMX_THROW(gmx::NotImplementedError(message));
317 if (ffs[sel].length() >= static_cast<size_t>(ff_maxlen))
319 std::string message = gmx::formatString(
320 "Length of force field name (%d) >= maxlen (%d)",
321 static_cast<int>(ffs[sel].length()), ff_maxlen);
322 GMX_THROW(gmx::InvalidInputError(message));
324 strcpy(forcefield, ffs[sel].c_str());
327 if (ffdirs[sel].bFromDefaultDir)
329 ffpath = ffdirs[sel].name;
333 ffpath = gmx::Path::join(ffdirs[sel].dir, ffdirs[sel].name);
335 if (ffpath.length() >= static_cast<size_t>(ffdir_maxlen))
337 std::string message = gmx::formatString(
338 "Length of force field dir (%d) >= maxlen (%d)",
339 static_cast<int>(ffpath.length()), ffdir_maxlen);
340 GMX_THROW(gmx::InvalidInputError(message));
342 strcpy(ffdir, ffpath.c_str());
346 choose_ff(const char *ffsel,
347 char *forcefield, int ff_maxlen,
348 char *ffdir, int ffdir_maxlen)
352 choose_ff_impl(ffsel, forcefield, ff_maxlen, ffdir, ffdir_maxlen);
354 GMX_CATCH_ALL_AND_EXIT_WITH_FATAL_ERROR;
357 void choose_watermodel(const char *wmsel, const char *ffdir,
360 const char *fn_watermodels = "watermodels.dat";
361 char fn_list[STRLEN];
368 if (strcmp(wmsel, "none") == 0)
370 *watermodel = nullptr;
374 else if (strcmp(wmsel, "select") != 0)
376 *watermodel = gmx_strdup(wmsel);
381 sprintf(fn_list, "%s%c%s", ffdir, DIR_SEPARATOR, fn_watermodels);
383 if (!fflib_fexist(fn_list))
385 fprintf(stderr, "No file '%s' found, will not include a water model\n",
387 *watermodel = nullptr;
392 fp = fflib_open(fn_list);
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(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)
653 fprintf(out, "; Include chain topologies\n");
654 for (i = 0; (i < nincl); i++)
656 incl = strrchr(incls[i], DIR_SEPARATOR);
663 /* Remove the path from the include name */
666 fprintf(out, "#include \"%s\"\n", incl);
673 print_top_water(out, ffdir, water);
675 print_top_system(out, title);
679 fprintf(out, "[ %s ]\n", dir2str(d_molecules));
680 fprintf(out, "; %-15s %5s\n", "Compound", "#mols");
681 for (i = 0; (i < nmol); i++)
683 fprintf(out, "%-15s %5d\n", mols[i].name, mols[i].nr);
688 void write_top(FILE *out, char *pr, const char *molname,
689 t_atoms *at, bool bRTPresname,
690 int bts[], t_params plist[], t_excls excls[],
691 gpp_atomtype_t atype, int *cgnr, int nrexcl)
692 /* NOTE: nrexcl is not the size of *excl! */
694 if (at && atype && cgnr)
696 fprintf(out, "[ %s ]\n", dir2str(d_moleculetype));
697 fprintf(out, "; %-15s %5s\n", "Name", "nrexcl");
698 fprintf(out, "%-15s %5d\n\n", molname ? molname : "Protein", nrexcl);
700 print_atoms(out, atype, at, cgnr, bRTPresname);
701 print_bondeds(out, at->nr, d_bonds, F_BONDS, bts[ebtsBONDS], plist);
702 print_bondeds(out, at->nr, d_constraints, F_CONSTR, 0, plist);
703 print_bondeds(out, at->nr, d_constraints, F_CONSTRNC, 0, plist);
704 print_bondeds(out, at->nr, d_pairs, F_LJ14, 0, plist);
705 print_excl(out, at->nr, excls);
706 print_bondeds(out, at->nr, d_angles, F_ANGLES, bts[ebtsANGLES], plist);
707 print_bondeds(out, at->nr, d_dihedrals, F_PDIHS, bts[ebtsPDIHS], plist);
708 print_bondeds(out, at->nr, d_dihedrals, F_IDIHS, bts[ebtsIDIHS], plist);
709 print_bondeds(out, at->nr, d_cmap, F_CMAP, bts[ebtsCMAP], plist);
710 print_bondeds(out, at->nr, d_polarization, F_POLARIZATION, 0, plist);
711 print_bondeds(out, at->nr, d_thole_polarization, F_THOLE_POL, 0, plist);
712 print_bondeds(out, at->nr, d_vsites2, F_VSITE2, 0, plist);
713 print_bondeds(out, at->nr, d_vsites3, F_VSITE3, 0, plist);
714 print_bondeds(out, at->nr, d_vsites3, F_VSITE3FD, 0, plist);
715 print_bondeds(out, at->nr, d_vsites3, F_VSITE3FAD, 0, plist);
716 print_bondeds(out, at->nr, d_vsites3, F_VSITE3OUT, 0, plist);
717 print_bondeds(out, at->nr, d_vsites4, F_VSITE4FD, 0, plist);
718 print_bondeds(out, at->nr, d_vsites4, F_VSITE4FDN, 0, plist);
722 print_top_posre(out, pr);
729 static void do_ssbonds(t_params *ps, t_atoms *atoms,
730 int nssbonds, t_ssbond *ssbonds, bool bAllowMissing)
735 for (i = 0; (i < nssbonds); i++)
737 ri = ssbonds[i].res1;
738 rj = ssbonds[i].res2;
739 ai = search_res_atom(ssbonds[i].a1, ri, atoms,
740 "special bond", bAllowMissing);
741 aj = search_res_atom(ssbonds[i].a2, rj, atoms,
742 "special bond", bAllowMissing);
743 if ((ai == -1) || (aj == -1))
745 gmx_fatal(FARGS, "Trying to make impossible special bond (%s-%s)!",
746 ssbonds[i].a1, ssbonds[i].a2);
748 add_param(ps, ai, aj, nullptr, nullptr);
752 static void at2bonds(t_params *psb, t_hackblock *hb,
755 real long_bond_dist, real short_bond_dist)
759 real dist2, long_bond_dist2, short_bond_dist2;
762 long_bond_dist2 = gmx::square(long_bond_dist);
763 short_bond_dist2 = gmx::square(short_bond_dist);
774 fprintf(stderr, "Making bonds...\n");
776 for (resind = 0; (resind < atoms->nres) && (i < atoms->nr); resind++)
778 /* add bonds from list of bonded interactions */
779 for (j = 0; j < hb[resind].rb[ebtsBONDS].nb; j++)
781 /* Unfortunately we can not issue errors or warnings
782 * for missing atoms in bonds, as the hydrogens and terminal atoms
783 * have not been added yet.
785 ai = search_atom(hb[resind].rb[ebtsBONDS].b[j].a[0], i, atoms,
787 aj = search_atom(hb[resind].rb[ebtsBONDS].b[j].a[1], i, atoms,
789 if (ai != -1 && aj != -1)
791 dist2 = distance2(x[ai], x[aj]);
792 if (dist2 > long_bond_dist2)
795 fprintf(stderr, "Warning: Long Bond (%d-%d = %g nm)\n",
796 ai+1, aj+1, std::sqrt(dist2));
798 else if (dist2 < short_bond_dist2)
800 fprintf(stderr, "Warning: Short Bond (%d-%d = %g nm)\n",
801 ai+1, aj+1, std::sqrt(dist2));
803 add_param(psb, ai, aj, nullptr, hb[resind].rb[ebtsBONDS].b[j].s);
806 /* add bonds from list of hacks (each added atom gets a bond) */
807 while ( (i < atoms->nr) && (atoms->atom[i].resind == resind) )
809 for (j = 0; j < hb[resind].nhack; j++)
811 if ( ( hb[resind].hack[j].tp > 0 ||
812 hb[resind].hack[j].oname == nullptr ) &&
813 strcmp(hb[resind].hack[j].a[0], *(atoms->atomname[i])) == 0)
815 switch (hb[resind].hack[j].tp)
817 case 9: /* COOH terminus */
818 add_param(psb, i, i+1, nullptr, nullptr); /* C-O */
819 add_param(psb, i, i+2, nullptr, nullptr); /* C-OA */
820 add_param(psb, i+2, i+3, nullptr, nullptr); /* OA-H */
823 for (k = 0; (k < hb[resind].hack[j].nr); k++)
825 add_param(psb, i, i+k+1, nullptr, nullptr);
832 /* we're now at the start of the next residue */
836 static int pcompar(const void *a, const void *b)
838 const t_param *pa, *pb;
840 pa = static_cast<const t_param *>(a);
841 pb = static_cast<const t_param *>(b);
843 d = pa->a[0] - pb->a[0];
846 d = pa->a[1] - pb->a[1];
850 return strlen(pb->s) - strlen(pa->s);
858 static void clean_bonds(t_params *ps)
865 /* swap atomnumbers in bond if first larger than second: */
866 for (i = 0; (i < ps->nr); i++)
868 if (ps->param[i].a[1] < ps->param[i].a[0])
870 a = ps->param[i].a[0];
871 ps->param[i].a[0] = ps->param[i].a[1];
872 ps->param[i].a[1] = a;
877 qsort(ps->param, ps->nr, static_cast<size_t>(sizeof(ps->param[0])), pcompar);
879 /* remove doubles, keep the first one always. */
881 for (i = 1; (i < ps->nr); i++)
883 if ((ps->param[i].a[0] != ps->param[j-1].a[0]) ||
884 (ps->param[i].a[1] != ps->param[j-1].a[1]) )
888 cp_param(&(ps->param[j]), &(ps->param[i]));
893 fprintf(stderr, "Number of bonds was %d, now %d\n", ps->nr, j);
898 fprintf(stderr, "No bonds\n");
902 void print_sums(t_atoms *atoms, bool bSystem)
910 where = " in system";
919 for (i = 0; (i < atoms->nr); i++)
921 m += atoms->atom[i].m;
922 qtot += atoms->atom[i].q;
925 fprintf(stderr, "Total mass%s %.3f a.m.u.\n", where, m);
926 fprintf(stderr, "Total charge%s %.3f e\n", where, qtot);
929 static void check_restp_type(const char *name, int t1, int t2)
933 gmx_fatal(FARGS, "Residues in one molecule have a different '%s' type: %d and %d", name, t1, t2);
937 static void check_restp_types(t_restp *r0, t_restp *r1)
941 check_restp_type("all dihedrals", r0->bKeepAllGeneratedDihedrals, r1->bKeepAllGeneratedDihedrals);
942 check_restp_type("nrexcl", r0->nrexcl, r1->nrexcl);
943 check_restp_type("HH14", r0->bGenerateHH14Interactions, r1->bGenerateHH14Interactions);
944 check_restp_type("remove dihedrals", r0->bRemoveDihedralIfWithImproper, r1->bRemoveDihedralIfWithImproper);
946 for (i = 0; i < ebtsNR; i++)
948 check_restp_type(btsNames[i], r0->rb[i].type, r1->rb[i].type);
952 static void add_atom_to_restp(t_restp *restp, int at_start, const t_hack *hack)
956 const char *Hnum = "123456";
958 strcpy(buf, hack->nname);
959 buf[strlen(buf)+1] = '\0';
962 buf[strlen(buf)] = '-';
965 restp->natom += hack->nr;
966 srenew(restp->atom, restp->natom);
967 srenew(restp->atomname, restp->natom);
968 srenew(restp->cgnr, restp->natom);
970 for (k = restp->natom-1; k > at_start+hack->nr; k--)
973 restp->atom [k - hack->nr];
975 restp->atomname[k - hack->nr];
977 restp->cgnr [k - hack->nr];
980 for (k = 0; k < hack->nr; k++)
982 /* set counter in atomname */
985 buf[strlen(buf)-1] = Hnum[k];
987 snew( restp->atomname[at_start+1+k], 1);
988 restp->atom [at_start+1+k] = *hack->atom;
989 *restp->atomname[at_start+1+k] = gmx_strdup(buf);
990 if (hack->cgnr != NOTSET)
992 restp->cgnr [at_start+1+k] = hack->cgnr;
996 restp->cgnr [at_start+1+k] = restp->cgnr[at_start];
1001 void get_hackblocks_rtp(t_hackblock **hb, t_restp **restp,
1002 int nrtp, t_restp rtp[],
1003 int nres, t_resinfo *resinfo,
1005 t_hackblock **ntdb, t_hackblock **ctdb,
1006 const int *rn, const int *rc,
1017 /* first the termini */
1018 for (i = 0; i < nterpairs; i++)
1020 if (rn[i] >= 0 && ntdb[i] != nullptr)
1022 copy_t_hackblock(ntdb[i], &(*hb)[rn[i]]);
1024 if (rc[i] >= 0 && ctdb[i] != nullptr)
1026 merge_t_hackblock(ctdb[i], &(*hb)[rc[i]]);
1030 /* then the whole rtp */
1031 for (i = 0; i < nres; i++)
1033 /* Here we allow a mismatch of one character when looking for the rtp entry.
1034 * For such a mismatch there should be only one mismatching name.
1035 * This is mainly useful for small molecules such as ions.
1036 * Note that this will usually not work for protein, DNA and RNA,
1037 * since there the residue names should be listed in residuetypes.dat
1038 * and an error will have been generated earlier in the process.
1040 key = *resinfo[i].rtp;
1041 snew(resinfo[i].rtp, 1);
1042 *resinfo[i].rtp = search_rtp(key, nrtp, rtp);
1043 res = get_restp(*resinfo[i].rtp, nrtp, rtp);
1044 copy_t_restp(res, &(*restp)[i]);
1046 /* Check that we do not have different bonded types in one molecule */
1047 check_restp_types(&(*restp)[0], &(*restp)[i]);
1050 for (j = 0; j < nterpairs && tern == -1; j++)
1058 for (j = 0; j < nterpairs && terc == -1; j++)
1065 bRM = merge_t_bondeds(res->rb, (*hb)[i].rb, tern >= 0, terc >= 0);
1067 if (bRM && ((tern >= 0 && ntdb[tern] == nullptr) ||
1068 (terc >= 0 && ctdb[terc] == nullptr)))
1070 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).";
1073 fprintf(stderr, "%s\n", errString);
1077 gmx_fatal(FARGS, "%s", errString);
1080 else if (bRM && ((tern >= 0 && ntdb[tern]->nhack == 0) ||
1081 (terc >= 0 && ctdb[terc]->nhack == 0)))
1083 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.";
1086 fprintf(stderr, "%s\n", errString);
1090 gmx_fatal(FARGS, "%s", errString);
1095 /* now perform t_hack's on t_restp's,
1096 i.e. add's and deletes from termini database will be
1097 added to/removed from residue topology
1098 we'll do this on one big dirty loop, so it won't make easy reading! */
1099 for (i = 0; i < nres; i++)
1101 for (j = 0; j < (*hb)[i].nhack; j++)
1103 if ( (*hb)[i].hack[j].nr)
1105 /* find atom in restp */
1106 for (l = 0; l < (*restp)[i].natom; l++)
1108 if ( ( (*hb)[i].hack[j].oname == nullptr &&
1109 strcmp((*hb)[i].hack[j].a[0], *(*restp)[i].atomname[l]) == 0 ) ||
1110 ( (*hb)[i].hack[j].oname != nullptr &&
1111 strcmp((*hb)[i].hack[j].oname, *(*restp)[i].atomname[l]) == 0 ) )
1116 if (l == (*restp)[i].natom)
1118 /* If we are doing an atom rename only, we don't need
1119 * to generate a fatal error if the old name is not found
1122 /* Deleting can happen also only on the input atoms,
1123 * not necessarily always on the rtp entry.
1125 if (!((*hb)[i].hack[j].oname != nullptr &&
1126 (*hb)[i].hack[j].nname != nullptr) &&
1127 !((*hb)[i].hack[j].oname != nullptr &&
1128 (*hb)[i].hack[j].nname == nullptr))
1131 "atom %s not found in buiding block %d%s "
1132 "while combining tdb and rtp",
1133 (*hb)[i].hack[j].oname != nullptr ?
1134 (*hb)[i].hack[j].oname : (*hb)[i].hack[j].a[0],
1135 i+1, *resinfo[i].rtp);
1140 if ( (*hb)[i].hack[j].oname == nullptr)
1143 add_atom_to_restp(&(*restp)[i], l, &(*hb)[i].hack[j]);
1148 if ( (*hb)[i].hack[j].nname == nullptr)
1149 { /* we're deleting */
1150 /* shift the rest */
1151 (*restp)[i].natom--;
1152 for (k = l; k < (*restp)[i].natom; k++)
1154 (*restp)[i].atom [k] = (*restp)[i].atom [k+1];
1155 (*restp)[i].atomname[k] = (*restp)[i].atomname[k+1];
1156 (*restp)[i].cgnr [k] = (*restp)[i].cgnr [k+1];
1158 /* give back space */
1159 srenew((*restp)[i].atom, (*restp)[i].natom);
1160 srenew((*restp)[i].atomname, (*restp)[i].natom);
1161 srenew((*restp)[i].cgnr, (*restp)[i].natom);
1163 else /* nname != NULL */
1164 { /* we're replacing */
1165 snew( (*restp)[i].atomname[l], 1);
1166 (*restp)[i].atom[l] = *(*hb)[i].hack[j].atom;
1167 *(*restp)[i].atomname[l] = gmx_strdup((*hb)[i].hack[j].nname);
1168 if ( (*hb)[i].hack[j].cgnr != NOTSET)
1170 (*restp)[i].cgnr [l] = (*hb)[i].hack[j].cgnr;
1180 static bool atomname_cmp_nr(const char *anm, t_hack *hack, int *nr)
1187 return (gmx_strcasecmp(anm, hack->nname) == 0);
1191 if (isdigit(anm[strlen(anm)-1]))
1193 *nr = anm[strlen(anm)-1] - '0';
1199 if (*nr <= 0 || *nr > hack->nr)
1205 return (strlen(anm) == strlen(hack->nname) + 1 &&
1206 gmx_strncasecmp(anm, hack->nname, strlen(hack->nname)) == 0);
1211 static bool match_atomnames_with_rtp_atom(t_atoms *pdba, rvec *x, int atind,
1212 t_restp *rptr, t_hackblock *hbr,
1217 char *oldnm, *newnm;
1219 char *start_at, buf[STRLEN];
1221 bool bReplaceReplace, bFoundInAdd;
1224 oldnm = *pdba->atomname[atind];
1225 resnr = pdba->resinfo[pdba->atom[atind].resind].nr;
1228 for (j = 0; j < hbr->nhack; j++)
1230 if (hbr->hack[j].oname != nullptr && hbr->hack[j].nname != nullptr &&
1231 gmx_strcasecmp(oldnm, hbr->hack[j].oname) == 0)
1233 /* This is a replace entry. */
1234 /* Check if we are not replacing a replaced atom. */
1235 bReplaceReplace = FALSE;
1236 for (k = 0; k < hbr->nhack; k++)
1239 hbr->hack[k].oname != nullptr && hbr->hack[k].nname != nullptr &&
1240 gmx_strcasecmp(hbr->hack[k].nname, hbr->hack[j].oname) == 0)
1242 /* The replace in hack[j] replaces an atom that
1243 * was already replaced in hack[k], we do not want
1244 * second or higher level replaces at this stage.
1246 bReplaceReplace = TRUE;
1249 if (bReplaceReplace)
1251 /* Skip this replace. */
1255 /* This atom still has the old name, rename it */
1256 newnm = hbr->hack[j].nname;
1257 for (k = 0; k < rptr->natom; k++)
1259 if (gmx_strcasecmp(newnm, *rptr->atomname[k]) == 0)
1264 if (k == rptr->natom)
1266 /* The new name is not present in the rtp.
1267 * We need to apply the replace also to the rtp entry.
1270 /* We need to find the add hack that can add this atom
1271 * to find out after which atom it should be added.
1273 bFoundInAdd = FALSE;
1274 for (k = 0; k < hbr->nhack; k++)
1276 if (hbr->hack[k].oname == nullptr &&
1277 hbr->hack[k].nname != nullptr &&
1278 atomname_cmp_nr(newnm, &hbr->hack[k], &anmnr))
1282 start_at = hbr->hack[k].a[0];
1286 sprintf(buf, "%s%d", hbr->hack[k].nname, anmnr-1);
1289 for (start_nr = 0; start_nr < rptr->natom; start_nr++)
1291 if (gmx_strcasecmp(start_at, (*rptr->atomname[start_nr])) == 0)
1296 if (start_nr == rptr->natom)
1298 gmx_fatal(FARGS, "Could not find atom '%s' in residue building block '%s' to add atom '%s' to",
1299 start_at, rptr->resname, newnm);
1301 /* We can add the atom after atom start_nr */
1302 add_atom_to_restp(rptr, start_nr, &hbr->hack[j]);
1310 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'",
1312 hbr->hack[j].oname, hbr->hack[j].nname,
1319 printf("Renaming atom '%s' in residue '%s' %d to '%s'\n",
1320 oldnm, rptr->resname, resnr, newnm);
1322 /* Rename the atom in pdba */
1323 snew(pdba->atomname[atind], 1);
1324 *pdba->atomname[atind] = gmx_strdup(newnm);
1326 else if (hbr->hack[j].oname != nullptr && hbr->hack[j].nname == nullptr &&
1327 gmx_strcasecmp(oldnm, hbr->hack[j].oname) == 0)
1329 /* This is a delete entry, check if this atom is present
1330 * in the rtp entry of this residue.
1332 for (k = 0; k < rptr->natom; k++)
1334 if (gmx_strcasecmp(oldnm, *rptr->atomname[k]) == 0)
1339 if (k == rptr->natom)
1341 /* This atom is not present in the rtp entry,
1342 * delete is now from the input pdba.
1346 printf("Deleting atom '%s' in residue '%s' %d\n",
1347 oldnm, rptr->resname, resnr);
1349 /* We should free the atom name,
1350 * but it might be used multiple times in the symtab.
1351 * sfree(pdba->atomname[atind]);
1353 for (k = atind+1; k < pdba->nr; k++)
1355 pdba->atom[k-1] = pdba->atom[k];
1356 pdba->atomname[k-1] = pdba->atomname[k];
1357 copy_rvec(x[k], x[k-1]);
1368 void match_atomnames_with_rtp(t_restp restp[], t_hackblock hb[],
1369 t_atoms *pdba, rvec *x,
1376 for (i = 0; i < pdba->nr; i++)
1378 oldnm = *pdba->atomname[i];
1379 rptr = &restp[pdba->atom[i].resind];
1380 for (j = 0; (j < rptr->natom); j++)
1382 if (gmx_strcasecmp(oldnm, *(rptr->atomname[j])) == 0)
1387 if (j == rptr->natom)
1389 /* Not found yet, check if we have to rename this atom */
1390 if (match_atomnames_with_rtp_atom(pdba, x, i,
1391 rptr, &(hb[pdba->atom[i].resind]),
1394 /* We deleted this atom, decrease the atom counter by 1. */
1401 #define NUM_CMAP_ATOMS 5
1402 static void gen_cmap(t_params *psb, t_restp *restp, t_atoms *atoms)
1404 int residx, i, j, k;
1407 t_resinfo *resinfo = atoms->resinfo;
1408 int nres = atoms->nres;
1410 int cmap_atomid[NUM_CMAP_ATOMS];
1411 int cmap_chainnum = -1, this_residue_index;
1422 fprintf(stderr, "Making cmap torsions...\n");
1424 /* Most cmap entries use the N atom from the next residue, so the last
1425 * residue should not have its CMAP entry in that case, but for things like
1426 * dipeptides we sometimes define a complete CMAP entry inside a residue,
1427 * and in this case we need to process everything through the last residue.
1429 for (residx = 0; residx < nres; residx++)
1431 /* Add CMAP terms from the list of CMAP interactions */
1432 for (j = 0; j < restp[residx].rb[ebtsCMAP].nb; j++)
1435 /* Loop over atoms in a candidate CMAP interaction and
1436 * check that they exist, are from the same chain and are
1437 * from residues labelled as protein. */
1438 for (k = 0; k < NUM_CMAP_ATOMS && bAddCMAP; k++)
1440 /* Assign the pointer to the name of the next reference atom.
1441 * This can use -/+ labels to refer to previous/next residue.
1443 pname = restp[residx].rb[ebtsCMAP].b[j].a[k];
1444 /* Skip this CMAP entry if it refers to residues before the
1445 * first or after the last residue.
1447 if (((strchr(pname, '-') != nullptr) && (residx == 0)) ||
1448 ((strchr(pname, '+') != nullptr) && (residx == nres-1)))
1454 cmap_atomid[k] = search_atom(pname,
1455 i, atoms, ptr, TRUE);
1456 bAddCMAP = bAddCMAP && (cmap_atomid[k] != -1);
1459 /* This break is necessary, because cmap_atomid[k]
1460 * == -1 cannot be safely used as an index
1461 * into the atom array. */
1464 this_residue_index = atoms->atom[cmap_atomid[k]].resind;
1467 cmap_chainnum = resinfo[this_residue_index].chainnum;
1471 /* Does the residue for this atom have the same
1472 * chain number as the residues for previous
1474 bAddCMAP = bAddCMAP &&
1475 cmap_chainnum == resinfo[this_residue_index].chainnum;
1477 /* Here we used to check that the residuetype was protein and
1478 * disable bAddCMAP if that was not the case. However, some
1479 * special residues (say, alanine dipeptides) might not adhere
1480 * to standard naming, and if we start calling them normal
1481 * protein residues the user will be bugged to select termini.
1483 * Instead, I believe that the right course of action is to
1484 * keep the CMAP interaction if it is present in the RTP file
1485 * and we correctly identified all atoms (which is the case
1492 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);
1496 if (residx < nres-1)
1498 while (atoms->atom[i].resind < residx+1)
1504 /* Start the next residue */
1508 scrub_charge_groups(int *cgnr, int natoms)
1512 for (i = 0; i < natoms; i++)
1519 void pdb2top(FILE *top_file, char *posre_fn, char *molname,
1520 t_atoms *atoms, rvec **x, gpp_atomtype_t atype, t_symtab *tab,
1521 int nrtp, t_restp rtp[],
1522 t_restp *restp, t_hackblock *hb,
1524 bool bVsites, bool bVsiteAromatics,
1527 int nssbonds, t_ssbond *ssbonds,
1528 real long_bond_dist, real short_bond_dist,
1529 bool bDeuterate, bool bChargeGroups, bool bCmap,
1530 bool bRenumRes, bool bRTPresname)
1536 t_params plist[F_NRE];
1543 gmx_residuetype_t*rt;
1546 gmx_residuetype_init(&rt);
1549 at2bonds(&(plist[F_BONDS]), hb,
1551 long_bond_dist, short_bond_dist);
1553 /* specbonds: disulphide bonds & heme-his */
1554 do_ssbonds(&(plist[F_BONDS]),
1555 atoms, nssbonds, ssbonds,
1558 nmissat = name2type(atoms, &cgnr, restp, rt);
1563 fprintf(stderr, "There were %d missing atoms in molecule %s\n",
1568 gmx_fatal(FARGS, "There were %d missing atoms in molecule %s, if you want to use this incomplete topology anyhow, use the option -missing",
1573 /* Cleanup bonds (sort and rm doubles) */
1574 clean_bonds(&(plist[F_BONDS]));
1576 snew(vsite_type, atoms->nr);
1577 for (i = 0; i < atoms->nr; i++)
1579 vsite_type[i] = NOTSET;
1583 /* determine which atoms will be vsites and add dummy masses
1584 also renumber atom numbers in plist[0..F_NRE]! */
1585 do_vsites(nrtp, rtp, atype, atoms, tab, x, plist,
1586 &vsite_type, &cgnr, mHmult, bVsiteAromatics, ffdir);
1589 /* Make Angles and Dihedrals */
1590 fprintf(stderr, "Generating angles, dihedrals and pairs...\n");
1591 snew(excls, atoms->nr);
1592 init_nnb(&nnb, atoms->nr, 4);
1593 gen_nnb(&nnb, plist);
1594 print_nnb(&nnb, "NNB");
1595 gen_pad(&nnb, atoms, restp, plist, excls, hb, bAllowMissing);
1601 gen_cmap(&(plist[F_CMAP]), restp, atoms);
1602 if (plist[F_CMAP].nr > 0)
1604 fprintf(stderr, "There are %4d cmap torsion pairs\n",
1609 /* set mass of all remaining hydrogen atoms */
1612 do_h_mass(&(plist[F_BONDS]), vsite_type, atoms, mHmult, bDeuterate);
1616 /* Cleanup bonds (sort and rm doubles) */
1617 /* clean_bonds(&(plist[F_BONDS]));*/
1620 "There are %4d dihedrals, %4d impropers, %4d angles\n"
1621 " %4d pairs, %4d bonds and %4d virtual sites\n",
1622 plist[F_PDIHS].nr, plist[F_IDIHS].nr, plist[F_ANGLES].nr,
1623 plist[F_LJ14].nr, plist[F_BONDS].nr,
1624 plist[F_VSITE2].nr +
1625 plist[F_VSITE3].nr +
1626 plist[F_VSITE3FD].nr +
1627 plist[F_VSITE3FAD].nr +
1628 plist[F_VSITE3OUT].nr +
1629 plist[F_VSITE4FD].nr +
1630 plist[F_VSITE4FDN].nr );
1632 print_sums(atoms, FALSE);
1634 if (FALSE == bChargeGroups)
1636 scrub_charge_groups(cgnr, atoms->nr);
1641 for (i = 0; i < atoms->nres; i++)
1643 atoms->resinfo[i].nr = i + 1;
1644 atoms->resinfo[i].ic = ' ';
1650 fprintf(stderr, "Writing topology\n");
1651 /* We can copy the bonded types from the first restp,
1652 * since the types have to be identical for all residues in one molecule.
1654 for (i = 0; i < ebtsNR; i++)
1656 bts[i] = restp[0].rb[i].type;
1658 write_top(top_file, posre_fn, molname,
1660 bts, plist, excls, atype, cgnr, restp[0].nrexcl);
1664 free_t_hackblock(atoms->nres, &hb);
1665 free_t_restp(atoms->nres, &restp);
1666 gmx_residuetype_destroy(rt);
1668 /* we should clean up hb and restp here, but that is a *L*O*T* of work! */
1670 for (i = 0; i < F_NRE; i++)
1672 sfree(plist[i].param);
1674 for (i = 0; i < atoms->nr; i++)