Remove unused function generate_excls and make clean_excls static
[gromacs.git] / src / gromacs / gmxpreprocess / toppush.cpp
blob4f2a8d760dae569b942a55035312b2c2f6774805
1 /*
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.
37 #include "gmxpre.h"
39 #include "toppush.h"
41 #include <cctype>
42 #include <cmath>
43 #include <cstdlib>
44 #include <cstring>
46 #include <algorithm>
47 #include <string>
49 #include "gromacs/fileio/warninp.h"
50 #include "gromacs/gmxpreprocess/gpp_atomtype.h"
51 #include "gromacs/gmxpreprocess/gpp_bond_atomtype.h"
52 #include "gromacs/gmxpreprocess/grompp_impl.h"
53 #include "gromacs/gmxpreprocess/notset.h"
54 #include "gromacs/gmxpreprocess/readir.h"
55 #include "gromacs/gmxpreprocess/topdirs.h"
56 #include "gromacs/gmxpreprocess/toputil.h"
57 #include "gromacs/math/functions.h"
58 #include "gromacs/mdtypes/md_enums.h"
59 #include "gromacs/topology/exclusionblocks.h"
60 #include "gromacs/topology/ifunc.h"
61 #include "gromacs/topology/symtab.h"
62 #include "gromacs/utility/arrayref.h"
63 #include "gromacs/utility/cstringutil.h"
64 #include "gromacs/utility/fatalerror.h"
65 #include "gromacs/utility/gmxassert.h"
66 #include "gromacs/utility/smalloc.h"
67 #include "gromacs/utility/stringutil.h"
69 void generate_nbparams(int comb,
70 int ftype,
71 InteractionsOfType *interactions,
72 PreprocessingAtomTypes *atypes,
73 warninp *wi)
75 int nr, nrfp;
76 real c, bi, bj, ci, cj, ci0, ci1, ci2, cj0, cj1, cj2;
78 /* Lean mean shortcuts */
79 nr = atypes->size();
80 nrfp = NRFP(ftype);
81 interactions->interactionTypes.clear();
83 std::array<real, MAXFORCEPARAM> forceParam = {NOTSET};
84 /* Fill the matrix with force parameters */
85 switch (ftype)
87 case F_LJ:
88 switch (comb)
90 case eCOMB_GEOMETRIC:
91 /* Gromos rules */
92 for (int i = 0; (i < nr); i++)
94 for (int j = 0; (j < nr); j++)
96 for (int nf = 0; (nf < nrfp); nf++)
98 ci = atypes->atomNonBondedParamFromAtomType(i, nf);
99 cj = atypes->atomNonBondedParamFromAtomType(j, nf);
100 c = std::sqrt(ci * cj);
101 forceParam[nf] = c;
103 interactions->interactionTypes.emplace_back(InteractionOfType({}, forceParam));
106 break;
108 case eCOMB_ARITHMETIC:
109 /* c0 and c1 are sigma and epsilon */
110 for (int i = 0; (i < nr); i++)
112 for (int j = 0; (j < nr); j++)
114 ci0 = atypes->atomNonBondedParamFromAtomType(i, 0);
115 cj0 = atypes->atomNonBondedParamFromAtomType(j, 0);
116 ci1 = atypes->atomNonBondedParamFromAtomType(i, 1);
117 cj1 = atypes->atomNonBondedParamFromAtomType(j, 1);
118 forceParam[0] = (fabs(ci0) + fabs(cj0))*0.5;
119 /* Negative sigma signals that c6 should be set to zero later,
120 * so we need to propagate that through the combination rules.
122 if (ci0 < 0 || cj0 < 0)
124 forceParam[0] *= -1;
126 forceParam[1] = std::sqrt(ci1*cj1);
127 interactions->interactionTypes.emplace_back(InteractionOfType({}, forceParam));
131 break;
132 case eCOMB_GEOM_SIG_EPS:
133 /* c0 and c1 are sigma and epsilon */
134 for (int i = 0; (i < nr); i++)
136 for (int j = 0; (j < nr); j++)
138 ci0 = atypes->atomNonBondedParamFromAtomType(i, 0);
139 cj0 = atypes->atomNonBondedParamFromAtomType(j, 0);
140 ci1 = atypes->atomNonBondedParamFromAtomType(i, 1);
141 cj1 = atypes->atomNonBondedParamFromAtomType(j, 1);
142 forceParam[0] = std::sqrt(std::fabs(ci0*cj0));
143 /* Negative sigma signals that c6 should be set to zero later,
144 * so we need to propagate that through the combination rules.
146 if (ci0 < 0 || cj0 < 0)
148 forceParam[0] *= -1;
150 forceParam[1] = std::sqrt(ci1*cj1);
151 interactions->interactionTypes.emplace_back(InteractionOfType({}, forceParam));
155 break;
156 default:
157 auto message = gmx::formatString("No such combination rule %d", comb);
158 warning_error_and_exit(wi, message, FARGS);
160 break;
162 case F_BHAM:
163 /* Buckingham rules */
164 for (int i = 0; (i < nr); i++)
166 for (int j = 0; (j < nr); j++)
168 ci0 = atypes->atomNonBondedParamFromAtomType(i, 0);
169 cj0 = atypes->atomNonBondedParamFromAtomType(j, 0);
170 ci2 = atypes->atomNonBondedParamFromAtomType(i, 2);
171 cj2 = atypes->atomNonBondedParamFromAtomType(j, 2);
172 bi = atypes->atomNonBondedParamFromAtomType(i, 1);
173 bj = atypes->atomNonBondedParamFromAtomType(j, 1);
174 forceParam[0] = std::sqrt(ci0 * cj0);
175 if ((bi == 0) || (bj == 0))
177 forceParam[1] = 0;
179 else
181 forceParam[1] = 2.0/(1/bi+1/bj);
183 forceParam[2] = std::sqrt(ci2 * cj2);
184 interactions->interactionTypes.emplace_back(InteractionOfType({}, forceParam));
188 break;
189 default:
190 auto message = gmx::formatString("Invalid nonbonded type %s",
191 interaction_function[ftype].longname);
192 warning_error(wi, message);
196 /*! \brief Used to temporarily store the explicit non-bonded parameter
197 * combinations, which will be copied to InteractionsOfType. */
198 struct t_nbparam
200 //! Has this combination been set.
201 bool bSet;
202 //! The non-bonded parameters
203 real c[4];
206 static void realloc_nb_params(PreprocessingAtomTypes *atypes,
207 t_nbparam ***nbparam, t_nbparam ***pair)
209 /* Add space in the non-bonded parameters matrix */
210 int atnr = atypes->size();
211 srenew(*nbparam, atnr);
212 snew((*nbparam)[atnr-1], atnr);
213 if (pair)
215 srenew(*pair, atnr);
216 snew((*pair)[atnr-1], atnr);
220 int copy_nbparams(t_nbparam **param, int ftype, InteractionsOfType *interactions, int nr)
222 int nrfp, ncopy;
224 nrfp = NRFP(ftype);
226 ncopy = 0;
227 for (int i = 0; i < nr; i++)
229 for (int j = 0; j <= i; j++)
231 GMX_RELEASE_ASSERT(param, "Must have valid parameters");
232 if (param[i][j].bSet)
234 for (int f = 0; f < nrfp; f++)
236 interactions->interactionTypes[nr*i+j].setForceParameter(f, param[i][j].c[f]);
237 interactions->interactionTypes[nr*j+i].setForceParameter(f, param[i][j].c[f]);
239 ncopy++;
244 return ncopy;
247 void free_nbparam(t_nbparam **param, int nr)
249 int i;
251 GMX_RELEASE_ASSERT(param, "Must have valid parameters");
252 for (i = 0; i < nr; i++)
254 GMX_RELEASE_ASSERT(param[i], "Must have valid parameters");
255 sfree(param[i]);
257 sfree(param);
260 static void copy_B_from_A(int ftype, double *c)
262 int nrfpA, nrfpB, i;
264 nrfpA = NRFPA(ftype);
265 nrfpB = NRFPB(ftype);
267 /* Copy the B parameters from the first nrfpB A parameters */
268 for (i = 0; (i < nrfpB); i++)
270 c[nrfpA+i] = c[i];
274 void push_at (t_symtab *symtab, PreprocessingAtomTypes *at, PreprocessingBondAtomType *bondAtomType,
275 char *line, int nb_funct,
276 t_nbparam ***nbparam, t_nbparam ***pair,
277 warninp *wi)
279 typedef struct {
280 const char *entry;
281 int ptype;
282 } t_xlate;
283 t_xlate xl[eptNR] = {
284 { "A", eptAtom },
285 { "N", eptNucleus },
286 { "S", eptShell },
287 { "B", eptBond },
288 { "V", eptVSite },
291 int nr, nfields, j, pt, nfp0 = -1;
292 int batype_nr, nread;
293 char type[STRLEN], btype[STRLEN], ptype[STRLEN];
294 double m, q;
295 double c[MAXFORCEPARAM];
296 char tmpfield[12][100]; /* Max 12 fields of width 100 */
297 t_atom *atom;
298 int atomnr;
299 bool have_atomic_number;
300 bool have_bonded_type;
302 snew(atom, 1);
304 /* First assign input line to temporary array */
305 nfields = sscanf(line, "%s%s%s%s%s%s%s%s%s%s%s%s",
306 tmpfield[0], tmpfield[1], tmpfield[2], tmpfield[3], tmpfield[4], tmpfield[5],
307 tmpfield[6], tmpfield[7], tmpfield[8], tmpfield[9], tmpfield[10], tmpfield[11]);
309 /* Comments on optional fields in the atomtypes section:
311 * The force field format is getting a bit old. For OPLS-AA we needed
312 * to add a special bonded atomtype, and for Gerrit Groenhofs QM/MM stuff
313 * we also needed the atomic numbers.
314 * To avoid making all old or user-generated force fields unusable we
315 * have introduced both these quantities as optional columns, and do some
316 * acrobatics to check whether they are present or not.
317 * This will all look much nicer when we switch to XML... sigh.
319 * Field 0 (mandatory) is the nonbonded type name. (string)
320 * Field 1 (optional) is the bonded type (string)
321 * Field 2 (optional) is the atomic number (int)
322 * Field 3 (mandatory) is the mass (numerical)
323 * Field 4 (mandatory) is the charge (numerical)
324 * Field 5 (mandatory) is the particle type (single character)
325 * This is followed by a number of nonbonded parameters.
327 * The safest way to identify the format is the particle type field.
329 * So, here is what we do:
331 * A. Read in the first six fields as strings
332 * B. If field 3 (starting from 0) is a single char, we have neither
333 * bonded_type or atomic numbers.
334 * C. If field 5 is a single char we have both.
335 * D. If field 4 is a single char we check field 1. If this begins with
336 * an alphabetical character we have bonded types, otherwise atomic numbers.
339 if (nfields < 6)
341 too_few(wi);
342 return;
345 if ( (strlen(tmpfield[5]) == 1) && isalpha(tmpfield[5][0]) )
347 have_bonded_type = TRUE;
348 have_atomic_number = TRUE;
350 else if ( (strlen(tmpfield[3]) == 1) && isalpha(tmpfield[3][0]) )
352 have_bonded_type = FALSE;
353 have_atomic_number = FALSE;
355 else
357 have_bonded_type = ( isalpha(tmpfield[1][0]) != 0 );
358 have_atomic_number = !have_bonded_type;
361 /* optional fields */
362 atomnr = -1;
364 switch (nb_funct)
367 case F_LJ:
368 nfp0 = 2;
370 if (have_atomic_number)
372 if (have_bonded_type)
374 nread = sscanf(line, "%s%s%d%lf%lf%s%lf%lf",
375 type, btype, &atomnr, &m, &q, ptype, &c[0], &c[1]);
376 if (nread < 8)
378 too_few(wi);
379 return;
382 else
384 /* have_atomic_number && !have_bonded_type */
385 nread = sscanf(line, "%s%d%lf%lf%s%lf%lf",
386 type, &atomnr, &m, &q, ptype, &c[0], &c[1]);
387 if (nread < 7)
389 too_few(wi);
390 return;
394 else
396 if (have_bonded_type)
398 /* !have_atomic_number && have_bonded_type */
399 nread = sscanf(line, "%s%s%lf%lf%s%lf%lf",
400 type, btype, &m, &q, ptype, &c[0], &c[1]);
401 if (nread < 7)
403 too_few(wi);
404 return;
407 else
409 /* !have_atomic_number && !have_bonded_type */
410 nread = sscanf(line, "%s%lf%lf%s%lf%lf",
411 type, &m, &q, ptype, &c[0], &c[1]);
412 if (nread < 6)
414 too_few(wi);
415 return;
420 if (!have_bonded_type)
422 strcpy(btype, type);
425 if (!have_atomic_number)
427 atomnr = -1;
430 break;
432 case F_BHAM:
433 nfp0 = 3;
435 if (have_atomic_number)
437 if (have_bonded_type)
439 nread = sscanf(line, "%s%s%d%lf%lf%s%lf%lf%lf",
440 type, btype, &atomnr, &m, &q, ptype, &c[0], &c[1], &c[2]);
441 if (nread < 9)
443 too_few(wi);
444 return;
447 else
449 /* have_atomic_number && !have_bonded_type */
450 nread = sscanf(line, "%s%d%lf%lf%s%lf%lf%lf",
451 type, &atomnr, &m, &q, ptype, &c[0], &c[1], &c[2]);
452 if (nread < 8)
454 too_few(wi);
455 return;
459 else
461 if (have_bonded_type)
463 /* !have_atomic_number && have_bonded_type */
464 nread = sscanf(line, "%s%s%lf%lf%s%lf%lf%lf",
465 type, btype, &m, &q, ptype, &c[0], &c[1], &c[2]);
466 if (nread < 8)
468 too_few(wi);
469 return;
472 else
474 /* !have_atomic_number && !have_bonded_type */
475 nread = sscanf(line, "%s%lf%lf%s%lf%lf%lf",
476 type, &m, &q, ptype, &c[0], &c[1], &c[2]);
477 if (nread < 7)
479 too_few(wi);
480 return;
485 if (!have_bonded_type)
487 strcpy(btype, type);
490 if (!have_atomic_number)
492 atomnr = -1;
495 break;
497 default:
498 auto message = gmx::formatString("Invalid function type %d in push_at", nb_funct);
499 warning_error_and_exit(wi, message, FARGS);
501 for (int j = nfp0; (j < MAXFORCEPARAM); j++)
503 c[j] = 0.0;
505 std::array<real, MAXFORCEPARAM> forceParam;
507 if (strlen(type) == 1 && isdigit(type[0]))
509 warning_error_and_exit(wi, "Atom type names can't be single digits.", FARGS);
512 if (strlen(btype) == 1 && isdigit(btype[0]))
514 warning_error_and_exit(wi, "Bond atom type names can't be single digits.", FARGS);
517 /* Hack to read old topologies */
518 if (gmx_strcasecmp(ptype, "D") == 0)
520 sprintf(ptype, "V");
522 for (j = 0; (j < eptNR); j++)
524 if (gmx_strcasecmp(ptype, xl[j].entry) == 0)
526 break;
529 if (j == eptNR)
531 auto message = gmx::formatString("Invalid particle type %s", ptype);
532 warning_error_and_exit(wi, message, FARGS);
534 pt = xl[j].ptype;
536 atom->q = q;
537 atom->m = m;
538 atom->ptype = pt;
539 for (int i = 0; i < MAXFORCEPARAM; i++)
541 forceParam[i] = c[i];
544 InteractionOfType interactionType({}, forceParam, "");
546 batype_nr = bondAtomType->addBondAtomType(symtab, btype);
548 if ((nr = at->atomTypeFromName(type)) != NOTSET)
550 auto message = gmx::formatString
551 ("Atomtype %s was defined previously (e.g. in the forcefield files), "
552 "and has now been defined again. This could happen e.g. if you would "
553 "use a self-contained molecule .itp file that duplicates or replaces "
554 "the contents of the standard force-field files. You should check "
555 "the contents of your files and remove such repetition. If you know "
556 "you should override the previous definition, then you could choose "
557 "to suppress this warning with -maxwarn.", type);
558 warning(wi, message);
559 if ((nr = at->setType(nr, symtab, *atom, type, interactionType, batype_nr,
560 atomnr)) == NOTSET)
562 auto message = gmx::formatString("Replacing atomtype %s failed", type);
563 warning_error_and_exit(wi, message, FARGS);
566 else if ((at->addType(symtab, *atom, type, interactionType,
567 batype_nr, atomnr)) == NOTSET)
569 auto message = gmx::formatString("Adding atomtype %s failed", type);
570 warning_error_and_exit(wi, message, FARGS);
572 else
574 /* Add space in the non-bonded parameters matrix */
575 realloc_nb_params(at, nbparam, pair);
577 sfree(atom);
580 //! Return whether the contents of \c a and \c b are the same, considering also reversed order.
581 template <typename T>
582 static bool equalEitherForwardOrBackward(gmx::ArrayRef<const T> a, gmx::ArrayRef<const T> b)
584 return (std::equal(a.begin(), a.end(), b.begin()) ||
585 std::equal(a.begin(), a.end(), b.rbegin()));
588 static void push_bondtype(InteractionsOfType *bt,
589 const InteractionOfType &b,
590 int nral,
591 int ftype,
592 bool bAllowRepeat,
593 const char *line,
594 warninp *wi)
596 int nr = bt->size();
597 int nrfp = NRFP(ftype);
599 /* If bAllowRepeat is TRUE, we allow multiple entries as long as they
600 are on directly _adjacent_ lines.
603 /* First check if our atomtypes are _identical_ (not reversed) to the previous
604 entry. If they are not identical we search for earlier duplicates. If they are
605 we can skip it, since we already searched for the first line
606 in this group.
609 bool isContinuationOfBlock = false;
610 if (bAllowRepeat && nr > 1)
612 isContinuationOfBlock = true;
613 gmx::ArrayRef<const int> newParAtom = b.atoms();
614 gmx::ArrayRef<const int> sysParAtom = bt->interactionTypes[nr - 2].atoms();
615 for (int j = 0; j < nral; j++)
617 if (newParAtom[j] != sysParAtom[j])
619 isContinuationOfBlock = false;
624 /* Search for earlier duplicates if this entry was not a continuation
625 from the previous line.
627 bool addBondType = true;
628 bool haveWarned = false;
629 bool haveErrored = false;
630 for (int i = 0; (i < nr); i++)
632 gmx::ArrayRef<const int> bParams = b.atoms();
633 gmx::ArrayRef<const int> testParams = bt->interactionTypes[i].atoms();
634 GMX_RELEASE_ASSERT(bParams.size() == testParams.size(), "Number of atoms needs to be the same between parameters");
635 if (equalEitherForwardOrBackward(bParams, testParams))
637 GMX_ASSERT(nrfp <= MAXFORCEPARAM, "This is ensured in other places, but we need this assert to keep the clang analyzer happy");
638 const bool identicalParameters = std::equal(bt->interactionTypes[i].forceParam().begin(),
639 bt->interactionTypes[i].forceParam().begin() + nrfp, b.forceParam().begin());
641 if (!bAllowRepeat || identicalParameters)
643 addBondType = false;
646 if (!identicalParameters)
648 if (bAllowRepeat)
650 /* With dihedral type 9 we only allow for repeating
651 * of the same parameters with blocks with 1 entry.
652 * Allowing overriding is too complex to check.
654 if (!isContinuationOfBlock && !haveErrored)
656 warning_error(wi, "Encountered a second block of parameters for dihedral "
657 "type 9 for the same atoms, with either different parameters "
658 "and/or the first block has multiple lines. This is not supported.");
659 haveErrored = true;
662 else if (!haveWarned)
664 auto message = gmx::formatString
665 ("Bondtype %s was defined previously (e.g. in the forcefield files), "
666 "and has now been defined again. This could happen e.g. if you would "
667 "use a self-contained molecule .itp file that duplicates or replaces "
668 "the contents of the standard force-field files. You should check "
669 "the contents of your files and remove such repetition. If you know "
670 "you should override the previous definition, then you could choose "
671 "to suppress this warning with -maxwarn.%s",
672 interaction_function[ftype].longname,
673 (ftype == F_PDIHS) ?
674 "\nUse dihedraltype 9 to allow several multiplicity terms. Only consecutive "
675 "lines are combined. Non-consective lines overwrite each other."
676 : "");
677 warning(wi, message);
679 fprintf(stderr, " old: ");
680 gmx::ArrayRef<const real> forceParam = bt->interactionTypes[i].forceParam();
681 for (int j = 0; j < nrfp; j++)
683 fprintf(stderr, " %g", forceParam[j]);
685 fprintf(stderr, " \n new: %s\n\n", line);
687 haveWarned = true;
691 if (!identicalParameters && !bAllowRepeat)
693 /* Overwrite the parameters with the latest ones */
694 // TODO considering improving the following code by replacing with:
695 // std::copy(b->c, b->c + nrfp, bt->param[i].c);
696 gmx::ArrayRef<const real> forceParam = b.forceParam();
697 for (int j = 0; j < nrfp; j++)
699 bt->interactionTypes[i].setForceParameter(j, forceParam[j]);
705 if (addBondType)
707 /* fill the arrays up and down */
708 bt->interactionTypes.emplace_back(
709 InteractionOfType(b.atoms(), b.forceParam(), b.interactionTypeName()));
710 /* need to store force values because they might change below */
711 std::vector<real> forceParam(b.forceParam().begin(), b.forceParam().end());
713 /* The definitions of linear angles depend on the order of atoms,
714 * that means that for atoms i-j-k, with certain parameter a, the
715 * corresponding k-j-i angle will have parameter 1-a.
717 if (ftype == F_LINEAR_ANGLES)
719 forceParam[0] = 1- forceParam[0];
720 forceParam[2] = 1- forceParam[2];
722 std::vector<int> atoms;
723 gmx::ArrayRef<const int> oldAtoms = b.atoms();
724 for (auto oldAtom = oldAtoms.rbegin(); oldAtom != oldAtoms.rend(); oldAtom++)
726 atoms.emplace_back(*oldAtom);
728 bt->interactionTypes.emplace_back(InteractionOfType(atoms, forceParam, b.interactionTypeName()));
732 static std::vector<int> atomTypesFromAtomNames(const PreprocessingAtomTypes *atomTypes,
733 const PreprocessingBondAtomType *bondAtomTypes,
734 gmx::ArrayRef<const char[20]> atomNames,
735 warninp *wi)
738 GMX_RELEASE_ASSERT(!(!atomNames.empty() && !atomTypes && !bondAtomTypes),
739 "Need to have either valid atomtypes or bondatomtypes object");
741 std::vector<int> atomTypesFromAtomNames;
742 for (const auto &name : atomNames)
744 if (atomTypes != nullptr)
746 int atomType = atomTypes->atomTypeFromName(name);
747 if (atomType == NOTSET)
749 auto message = gmx::formatString("Unknown atomtype %s\n", name);
750 warning_error_and_exit(wi, message, FARGS);
752 atomTypesFromAtomNames.emplace_back(atomType);
754 else if (bondAtomTypes != nullptr)
756 int atomType = bondAtomTypes->bondAtomTypeFromName(name);
757 if (atomType == NOTSET)
759 auto message = gmx::formatString("Unknown bond_atomtype %s\n", name);
760 warning_error_and_exit(wi, message, FARGS);
762 atomTypesFromAtomNames.emplace_back(atomType);
765 return atomTypesFromAtomNames;
769 void push_bt(Directive d,
770 gmx::ArrayRef<InteractionsOfType> bt,
771 int nral,
772 PreprocessingAtomTypes *at,
773 PreprocessingBondAtomType *bondAtomType,
774 char *line,
775 warninp *wi)
777 const char *formal[MAXATOMLIST+1] = {
778 "%s",
779 "%s%s",
780 "%s%s%s",
781 "%s%s%s%s",
782 "%s%s%s%s%s",
783 "%s%s%s%s%s%s",
784 "%s%s%s%s%s%s%s"
786 const char *formnl[MAXATOMLIST+1] = {
787 "%*s",
788 "%*s%*s",
789 "%*s%*s%*s",
790 "%*s%*s%*s%*s",
791 "%*s%*s%*s%*s%*s",
792 "%*s%*s%*s%*s%*s%*s",
793 "%*s%*s%*s%*s%*s%*s%*s"
795 const char *formlf = "%lf%lf%lf%lf%lf%lf%lf%lf%lf%lf%lf%lf%lf";
796 int i, ft, ftype, nn, nrfp, nrfpA;
797 char f1[STRLEN];
798 char alc[MAXATOMLIST+1][20];
799 /* One force parameter more, so we can check if we read too many */
800 double c[MAXFORCEPARAM+1];
802 if ((bondAtomType && at) || (!bondAtomType && !at))
804 gmx_incons("You should pass either bondAtomType or at to push_bt");
807 /* Make format string (nral ints+functype) */
808 if ((nn = sscanf(line, formal[nral],
809 alc[0], alc[1], alc[2], alc[3], alc[4], alc[5])) != nral+1)
811 auto message = gmx::formatString("Not enough atomtypes (%d instead of %d)", nn-1, nral);
812 warning_error(wi, message);
813 return;
816 ft = strtol(alc[nral], nullptr, 10);
817 ftype = ifunc_index(d, ft);
818 nrfp = NRFP(ftype);
819 nrfpA = interaction_function[ftype].nrfpA;
820 strcpy(f1, formnl[nral]);
821 strcat(f1, formlf);
822 if ((nn = sscanf(line, f1, &c[0], &c[1], &c[2], &c[3], &c[4], &c[5], &c[6], &c[7], &c[8], &c[9], &c[10], &c[11], &c[12]))
823 != nrfp)
825 if (nn == nrfpA)
827 /* Copy the B-state from the A-state */
828 copy_B_from_A(ftype, c);
830 else
832 if (nn < nrfpA)
834 warning_error(wi, "Not enough parameters");
836 else if (nn > nrfpA && nn < nrfp)
838 warning_error(wi, "Too many parameters or not enough parameters for topology B");
840 else if (nn > nrfp)
842 warning_error(wi, "Too many parameters");
844 for (i = nn; (i < nrfp); i++)
846 c[i] = 0.0;
850 std::vector<int> atomTypes = atomTypesFromAtomNames(at,
851 bondAtomType,
852 gmx::arrayRefFromArray(alc, nral),
853 wi);
854 std::array<real, MAXFORCEPARAM> forceParam;
855 for (int i = 0; (i < nrfp); i++)
857 forceParam[i] = c[i];
859 push_bondtype (&(bt[ftype]), InteractionOfType(atomTypes, forceParam), nral, ftype, FALSE, line, wi);
863 void push_dihedraltype(Directive d, gmx::ArrayRef<InteractionsOfType> bt,
864 PreprocessingBondAtomType *bondAtomType, char *line,
865 warninp *wi)
867 const char *formal[MAXATOMLIST+1] = {
868 "%s",
869 "%s%s",
870 "%s%s%s",
871 "%s%s%s%s",
872 "%s%s%s%s%s",
873 "%s%s%s%s%s%s",
874 "%s%s%s%s%s%s%s"
876 const char *formnl[MAXATOMLIST+1] = {
877 "%*s",
878 "%*s%*s",
879 "%*s%*s%*s",
880 "%*s%*s%*s%*s",
881 "%*s%*s%*s%*s%*s",
882 "%*s%*s%*s%*s%*s%*s",
883 "%*s%*s%*s%*s%*s%*s%*s"
885 const char *formlf[MAXFORCEPARAM] = {
886 "%lf",
887 "%lf%lf",
888 "%lf%lf%lf",
889 "%lf%lf%lf%lf",
890 "%lf%lf%lf%lf%lf",
891 "%lf%lf%lf%lf%lf%lf",
892 "%lf%lf%lf%lf%lf%lf%lf",
893 "%lf%lf%lf%lf%lf%lf%lf%lf",
894 "%lf%lf%lf%lf%lf%lf%lf%lf%lf",
895 "%lf%lf%lf%lf%lf%lf%lf%lf%lf%lf",
896 "%lf%lf%lf%lf%lf%lf%lf%lf%lf%lf%lf",
897 "%lf%lf%lf%lf%lf%lf%lf%lf%lf%lf%lf%lf",
899 int i, ft, ftype, nn, nrfp, nrfpA, nral;
900 char f1[STRLEN];
901 char alc[MAXATOMLIST+1][20];
902 double c[MAXFORCEPARAM];
903 bool bAllowRepeat;
905 /* This routine accepts dihedraltypes defined from either 2 or 4 atoms.
907 * We first check for 2 atoms with the 3th column being an integer
908 * defining the type. If this isn't the case, we try it with 4 atoms
909 * and the 5th column defining the dihedral type.
911 nn = sscanf(line, formal[4], alc[0], alc[1], alc[2], alc[3], alc[4]);
912 if (nn >= 3 && strlen(alc[2]) == 1 && isdigit(alc[2][0]))
914 nral = 2;
915 ft = strtol(alc[nral], nullptr, 10);
916 /* Move atom types around a bit and use 'X' for wildcard atoms
917 * to create a 4-atom dihedral definition with arbitrary atoms in
918 * position 1 and 4.
920 if (alc[2][0] == '2')
922 /* improper - the two atomtypes are 1,4. Use wildcards for 2,3 */
923 strcpy(alc[3], alc[1]);
924 sprintf(alc[2], "X");
925 sprintf(alc[1], "X");
926 /* alc[0] stays put */
928 else
930 /* proper - the two atomtypes are 2,3. Use wildcards for 1,4 */
931 sprintf(alc[3], "X");
932 strcpy(alc[2], alc[1]);
933 strcpy(alc[1], alc[0]);
934 sprintf(alc[0], "X");
937 else if (nn == 5 && strlen(alc[4]) == 1 && isdigit(alc[4][0]))
939 nral = 4;
940 ft = strtol(alc[nral], nullptr, 10);
942 else
944 auto message = gmx::formatString("Incorrect number of atomtypes for dihedral (%d instead of 2 or 4)", nn-1);
945 warning_error(wi, message);
946 return;
949 if (ft == 9)
951 /* Previously, we have always overwritten parameters if e.g. a torsion
952 with the same atomtypes occurs on multiple lines. However, CHARMM and
953 some other force fields specify multiple dihedrals over some bonds,
954 including cosines with multiplicity 6 and somethimes even higher.
955 Thus, they cannot be represented with Ryckaert-Bellemans terms.
956 To add support for these force fields, Dihedral type 9 is identical to
957 normal proper dihedrals, but repeated entries are allowed.
959 bAllowRepeat = TRUE;
960 ft = 1;
962 else
964 bAllowRepeat = FALSE;
968 ftype = ifunc_index(d, ft);
969 nrfp = NRFP(ftype);
970 nrfpA = interaction_function[ftype].nrfpA;
972 strcpy(f1, formnl[nral]);
973 strcat(f1, formlf[nrfp-1]);
975 /* Check number of parameters given */
976 if ((nn = sscanf(line, f1, &c[0], &c[1], &c[2], &c[3], &c[4], &c[5], &c[6], &c[7], &c[8], &c[9], &c[10], &c[11]))
977 != nrfp)
979 if (nn == nrfpA)
981 /* Copy the B-state from the A-state */
982 copy_B_from_A(ftype, c);
984 else
986 if (nn < nrfpA)
988 warning_error(wi, "Not enough parameters");
990 else if (nn > nrfpA && nn < nrfp)
992 warning_error(wi, "Too many parameters or not enough parameters for topology B");
994 else if (nn > nrfp)
996 warning_error(wi, "Too many parameters");
998 for (i = nn; (i < nrfp); i++)
1000 c[i] = 0.0;
1005 std::vector<int> atoms;
1006 std::array<real, MAXFORCEPARAM> forceParam;
1007 for (int i = 0; (i < 4); i++)
1009 if (!strcmp(alc[i], "X"))
1011 atoms.emplace_back(-1);
1013 else
1015 int atomNumber;
1016 if ((atomNumber = bondAtomType->bondAtomTypeFromName(alc[i])) == NOTSET)
1018 auto message = gmx::formatString("Unknown bond_atomtype %s", alc[i]);
1019 warning_error_and_exit(wi, message, FARGS);
1021 atoms.emplace_back(atomNumber);
1024 for (int i = 0; (i < nrfp); i++)
1026 forceParam[i] = c[i];
1028 /* Always use 4 atoms here, since we created two wildcard atoms
1029 * if there wasn't of them 4 already.
1031 push_bondtype (&(bt[ftype]), InteractionOfType(atoms, forceParam), 4, ftype, bAllowRepeat, line, wi);
1035 void push_nbt(Directive d, t_nbparam **nbt, PreprocessingAtomTypes *atypes,
1036 char *pline, int nb_funct,
1037 warninp *wi)
1039 /* swap the atoms */
1040 const char *form3 = "%*s%*s%*s%lf%lf%lf";
1041 const char *form4 = "%*s%*s%*s%lf%lf%lf%lf";
1042 const char *form5 = "%*s%*s%*s%lf%lf%lf%lf%lf";
1043 char a0[80], a1[80];
1044 int i, f, n, ftype, nrfp;
1045 double c[4], dum;
1046 real cr[4];
1047 int ai, aj;
1048 t_nbparam *nbp;
1049 bool bId;
1051 if (sscanf (pline, "%s%s%d", a0, a1, &f) != 3)
1053 too_few(wi);
1054 return;
1057 ftype = ifunc_index(d, f);
1059 if (ftype != nb_funct)
1061 auto message = gmx::formatString("Trying to add %s while the default nonbond type is %s",
1062 interaction_function[ftype].longname,
1063 interaction_function[nb_funct].longname);
1064 warning_error(wi, message);
1065 return;
1068 /* Get the force parameters */
1069 nrfp = NRFP(ftype);
1070 if (ftype == F_LJ14)
1072 n = sscanf(pline, form4, &c[0], &c[1], &c[2], &c[3]);
1073 if (n < 2)
1075 too_few(wi);
1076 return;
1078 /* When the B topology parameters are not set,
1079 * copy them from topology A
1081 GMX_ASSERT(nrfp <= 4, "LJ-14 cannot have more than 4 parameters");
1082 for (i = n; i < nrfp; i++)
1084 c[i] = c[i-2];
1087 else if (ftype == F_LJC14_Q)
1089 n = sscanf(pline, form5, &c[0], &c[1], &c[2], &c[3], &dum);
1090 if (n != 4)
1092 incorrect_n_param(wi);
1093 return;
1096 else if (nrfp == 2)
1098 if (sscanf(pline, form3, &c[0], &c[1], &dum) != 2)
1100 incorrect_n_param(wi);
1101 return;
1104 else if (nrfp == 3)
1106 if (sscanf(pline, form4, &c[0], &c[1], &c[2], &dum) != 3)
1108 incorrect_n_param(wi);
1109 return;
1112 else
1114 auto message = gmx::formatString("Number of force parameters for nonbonded interactions is %d", nrfp);
1115 warning_error_and_exit(wi, message, FARGS);
1117 for (i = 0; (i < nrfp); i++)
1119 cr[i] = c[i];
1122 /* Put the parameters in the matrix */
1123 if ((ai = atypes->atomTypeFromName(a0)) == NOTSET)
1125 auto message = gmx::formatString("Atomtype %s not found", a0);
1126 warning_error_and_exit(wi, message, FARGS);
1128 if ((aj = atypes->atomTypeFromName(a1)) == NOTSET)
1130 auto message = gmx::formatString("Atomtype %s not found", a1);
1131 warning_error_and_exit(wi, message, FARGS);
1133 nbp = &(nbt[std::max(ai, aj)][std::min(ai, aj)]);
1135 if (nbp->bSet)
1137 bId = TRUE;
1138 for (i = 0; i < nrfp; i++)
1140 bId = bId && (nbp->c[i] == cr[i]);
1142 if (!bId)
1144 auto message = gmx::formatString
1145 ("Non-bonded parameters were defined previously (e.g. in the forcefield files), "
1146 "and have now been defined again. This could happen e.g. if you would "
1147 "use a self-contained molecule .itp file that duplicates or replaces "
1148 "the contents of the standard force-field files. You should check "
1149 "the contents of your files and remove such repetition. If you know "
1150 "you should override the previous definitions, then you could choose "
1151 "to suppress this warning with -maxwarn.");
1152 warning(wi, message);
1153 fprintf(stderr, " old:");
1154 for (i = 0; i < nrfp; i++)
1156 fprintf(stderr, " %g", nbp->c[i]);
1158 fprintf(stderr, " new\n%s\n", pline);
1161 nbp->bSet = TRUE;
1162 for (i = 0; i < nrfp; i++)
1164 nbp->c[i] = cr[i];
1168 void
1169 push_cmaptype(Directive d,
1170 gmx::ArrayRef<InteractionsOfType> bt,
1171 int nral,
1172 PreprocessingAtomTypes *atomtypes,
1173 PreprocessingBondAtomType *bondAtomType,
1174 char *line,
1175 warninp *wi)
1177 const char *formal = "%s%s%s%s%s%s%s%s%n";
1179 int ft, ftype, nn, nrfp, nrfpA, nrfpB;
1180 int start, nchar_consumed;
1181 int nxcmap, nycmap, ncmap, read_cmap, sl, nct;
1182 char s[20], alc[MAXATOMLIST+2][20];
1184 /* Keep the compiler happy */
1185 read_cmap = 0;
1186 start = 0;
1188 GMX_ASSERT(nral == 5, "CMAP requires 5 atoms per interaction");
1190 /* Here we can only check for < 8 */
1191 if ((nn = sscanf(line, formal, alc[0], alc[1], alc[2], alc[3], alc[4], alc[5], alc[6], alc[7], &nchar_consumed)) < nral+3)
1193 auto message = gmx::formatString("Incorrect number of atomtypes for cmap (%d instead of 5)", nn-1);
1194 warning_error(wi, message);
1195 return;
1197 start += nchar_consumed;
1199 ft = strtol(alc[nral], nullptr, 10);
1200 nxcmap = strtol(alc[nral+1], nullptr, 10);
1201 nycmap = strtol(alc[nral+2], nullptr, 10);
1203 /* Check for equal grid spacing in x and y dims */
1204 if (nxcmap != nycmap)
1206 auto message = gmx::formatString("Not the same grid spacing in x and y for cmap grid: x=%d, y=%d", nxcmap, nycmap);
1207 warning_error(wi, message);
1210 ncmap = nxcmap*nycmap;
1211 ftype = ifunc_index(d, ft);
1212 nrfpA = strtol(alc[6], nullptr, 10)*strtol(alc[6], nullptr, 10);
1213 nrfpB = strtol(alc[7], nullptr, 10)*strtol(alc[7], nullptr, 10);
1214 nrfp = nrfpA+nrfpB;
1216 /* Read in CMAP parameters */
1217 sl = 0;
1218 for (int i = 0; i < ncmap; i++)
1220 while (isspace(*(line+start+sl)))
1222 sl++;
1224 nn = sscanf(line+start+sl, " %s ", s);
1225 sl += strlen(s);
1226 bt[F_CMAP].cmap.emplace_back(strtod(s, nullptr));
1228 if (nn == 1)
1230 read_cmap++;
1232 else
1234 auto message = gmx::formatString("Error in reading cmap parameter for angle %s %s %s %s %s", alc[0], alc[1], alc[2], alc[3], alc[4]);
1235 warning_error(wi, message);
1240 /* Check do that we got the number of parameters we expected */
1241 if (read_cmap == nrfpA)
1243 for (int i = 0; i < ncmap; i++)
1245 bt[F_CMAP].cmap.emplace_back(bt[F_CMAP].cmap[i]);
1248 else
1250 if (read_cmap < nrfpA)
1252 warning_error(wi, "Not enough cmap parameters");
1254 else if (read_cmap > nrfpA && read_cmap < nrfp)
1256 warning_error(wi, "Too many cmap parameters or not enough parameters for topology B");
1258 else if (read_cmap > nrfp)
1260 warning_error(wi, "Too many cmap parameters");
1265 /* Set grid spacing and the number of grids (we assume these numbers to be the same for all grids
1266 * so we can safely assign them each time
1268 bt[F_CMAP].cmakeGridSpacing = nxcmap; /* Or nycmap, they need to be equal */
1269 bt[F_CMAP].cmapAngles++; /* Since we are incrementing here, we need to subtract later, see (*****) */
1270 nct = (nral+1) * bt[F_CMAP].cmapAngles;
1272 for (int i = 0; (i < nral); i++)
1274 /* Assign a grid number to each cmap_type */
1275 GMX_RELEASE_ASSERT(bondAtomType != nullptr, "Need valid PreprocessingBondAtomType object");
1276 bt[F_CMAP].cmapAtomTypes.emplace_back(bondAtomType->bondAtomTypeFromName(alc[i]));
1279 /* Assign a type number to this cmap */
1280 bt[F_CMAP].cmapAtomTypes.emplace_back(bt[F_CMAP].cmapAngles-1); /* Since we inremented earlier, we need to subtrac here, to get the types right (****) */
1282 /* Check for the correct number of atoms (again) */
1283 if (bt[F_CMAP].nct() != nct)
1285 auto message = gmx::formatString("Incorrect number of atom types (%d) in cmap type %d\n", nct, bt[F_CMAP].cmapAngles);
1286 warning_error(wi, message);
1288 std::vector<int> atomTypes = atomTypesFromAtomNames(atomtypes,
1289 bondAtomType,
1290 gmx::constArrayRefFromArray(alc, nral),
1291 wi);
1292 std::array<real, MAXFORCEPARAM> forceParam = {NOTSET};
1294 /* Push the bond to the bondlist */
1295 push_bondtype (&(bt[ftype]), InteractionOfType(atomTypes, forceParam), nral, ftype, FALSE, line, wi);
1299 static void push_atom_now(t_symtab *symtab, t_atoms *at, int atomnr,
1300 int atomicnumber,
1301 int type, char *ctype, int ptype,
1302 char *resnumberic,
1303 char *resname, char *name, real m0, real q0,
1304 int typeB, char *ctypeB, real mB, real qB,
1305 warninp *wi)
1307 int j, resind = 0, resnr;
1308 unsigned char ric;
1309 int nr = at->nr;
1311 if (((nr == 0) && (atomnr != 1)) || (nr && (atomnr != at->nr+1)))
1313 auto message = gmx::formatString
1314 ("Atoms in the .top are not numbered consecutively from 1 (rather, "
1315 "atomnr = %d, while at->nr = %d)", atomnr, at->nr);
1316 warning_error_and_exit(wi, message, FARGS);
1319 j = strlen(resnumberic) - 1;
1320 if (isdigit(resnumberic[j]))
1322 ric = ' ';
1324 else
1326 ric = resnumberic[j];
1327 if (j == 0 || !isdigit(resnumberic[j-1]))
1329 auto message = gmx::formatString("Invalid residue number '%s' for atom %d",
1330 resnumberic, atomnr);
1331 warning_error_and_exit(wi, message, FARGS);
1334 resnr = strtol(resnumberic, nullptr, 10);
1336 if (nr > 0)
1338 resind = at->atom[nr-1].resind;
1340 if (nr == 0 || strcmp(resname, *at->resinfo[resind].name) != 0 ||
1341 resnr != at->resinfo[resind].nr ||
1342 ric != at->resinfo[resind].ic)
1344 if (nr == 0)
1346 resind = 0;
1348 else
1350 resind++;
1352 at->nres = resind + 1;
1353 srenew(at->resinfo, at->nres);
1354 at->resinfo[resind].name = put_symtab(symtab, resname);
1355 at->resinfo[resind].nr = resnr;
1356 at->resinfo[resind].ic = ric;
1358 else
1360 resind = at->atom[at->nr-1].resind;
1363 /* New atom instance
1364 * get new space for arrays
1366 srenew(at->atom, nr+1);
1367 srenew(at->atomname, nr+1);
1368 srenew(at->atomtype, nr+1);
1369 srenew(at->atomtypeB, nr+1);
1371 /* fill the list */
1372 at->atom[nr].type = type;
1373 at->atom[nr].ptype = ptype;
1374 at->atom[nr].q = q0;
1375 at->atom[nr].m = m0;
1376 at->atom[nr].typeB = typeB;
1377 at->atom[nr].qB = qB;
1378 at->atom[nr].mB = mB;
1380 at->atom[nr].resind = resind;
1381 at->atom[nr].atomnumber = atomicnumber;
1382 at->atomname[nr] = put_symtab(symtab, name);
1383 at->atomtype[nr] = put_symtab(symtab, ctype);
1384 at->atomtypeB[nr] = put_symtab(symtab, ctypeB);
1385 at->nr++;
1388 void push_atom(t_symtab *symtab,
1389 t_atoms *at, PreprocessingAtomTypes *atypes, char *line,
1390 warninp *wi)
1392 int ptype;
1393 int cgnumber, atomnr, type, typeB, nscan;
1394 char id[STRLEN], ctype[STRLEN], ctypeB[STRLEN],
1395 resnumberic[STRLEN], resname[STRLEN], name[STRLEN], check[STRLEN];
1396 double m, q, mb, qb;
1397 real m0, q0, mB, qB;
1399 /* Fixed parameters */
1400 if (sscanf(line, "%s%s%s%s%s%d",
1401 id, ctype, resnumberic, resname, name, &cgnumber) != 6)
1403 too_few(wi);
1404 return;
1406 sscanf(id, "%d", &atomnr);
1407 if ((type = atypes->atomTypeFromName(ctype)) == NOTSET)
1409 auto message = gmx::formatString("Atomtype %s not found", ctype);
1410 warning_error_and_exit(wi, message, FARGS);
1412 ptype = atypes->atomParticleTypeFromAtomType(type);
1414 /* Set default from type */
1415 q0 = atypes->atomChargeFromAtomType(type);
1416 m0 = atypes->atomMassFromAtomType(type);
1417 typeB = type;
1418 qB = q0;
1419 mB = m0;
1421 /* Optional parameters */
1422 nscan = sscanf(line, "%*s%*s%*s%*s%*s%*s%lf%lf%s%lf%lf%s",
1423 &q, &m, ctypeB, &qb, &mb, check);
1425 /* Nasty switch that falls thru all the way down! */
1426 if (nscan > 0)
1428 q0 = qB = q;
1429 if (nscan > 1)
1431 m0 = mB = m;
1432 if (nscan > 2)
1434 if ((typeB = atypes->atomTypeFromName(ctypeB)) == NOTSET)
1436 auto message = gmx::formatString("Atomtype %s not found", ctypeB);
1437 warning_error_and_exit(wi, message, FARGS);
1439 qB = atypes->atomChargeFromAtomType(typeB);
1440 mB = atypes->atomMassFromAtomType(typeB);
1441 if (nscan > 3)
1443 qB = qb;
1444 if (nscan > 4)
1446 mB = mb;
1447 if (nscan > 5)
1449 warning_error(wi, "Too many parameters");
1457 push_atom_now(symtab, at, atomnr, atypes->atomNumberFromAtomType(type),
1458 type, ctype, ptype, resnumberic,
1459 resname, name, m0, q0, typeB,
1460 typeB == type ? ctype : ctypeB, mB, qB, wi);
1463 void push_molt(t_symtab *symtab,
1464 std::vector<MoleculeInformation> *mol,
1465 char *line,
1466 warninp *wi)
1468 char type[STRLEN];
1469 int nrexcl;
1471 if ((sscanf(line, "%s%d", type, &nrexcl)) != 2)
1473 warning_error(wi, "Expected a molecule type name and nrexcl");
1476 /* Test if this moleculetype overwrites another */
1477 const auto found = std::find_if(mol->begin(), mol->end(),
1478 [&type](const auto &m)
1479 { return strcmp(*(m.name), type) == 0; });
1480 if (found != mol->end())
1482 auto message = gmx::formatString("moleculetype %s is redefined", type);
1483 warning_error_and_exit(wi, message, FARGS);
1486 mol->emplace_back();
1487 mol->back().initMolInfo();
1489 /* Fill in the values */
1490 mol->back().name = put_symtab(symtab, type);
1491 mol->back().nrexcl = nrexcl;
1492 mol->back().excl_set = false;
1495 static bool findIfAllNBAtomsMatch(gmx::ArrayRef<const int> atomsFromParameterArray,
1496 gmx::ArrayRef<const int> atomsFromCurrentParameter,
1497 const t_atoms *at,
1498 bool bB)
1500 if (atomsFromParameterArray.size() != atomsFromCurrentParameter.size())
1502 return false;
1504 else if (bB)
1506 for (gmx::index i = 0; i < atomsFromCurrentParameter.ssize(); i++)
1508 if (at->atom[atomsFromCurrentParameter[i]].typeB != atomsFromParameterArray[i])
1510 return false;
1513 return true;
1515 else
1517 for (gmx::index i = 0; i < atomsFromCurrentParameter.ssize(); i++)
1519 if (at->atom[atomsFromCurrentParameter[i]].type != atomsFromParameterArray[i])
1521 return false;
1524 return true;
1528 static bool default_nb_params(int ftype, gmx::ArrayRef<InteractionsOfType> bt, t_atoms *at,
1529 InteractionOfType *p, int c_start, bool bB, bool bGenPairs)
1531 int ti, tj, ntype;
1532 bool bFound;
1533 InteractionOfType *pi = nullptr;
1534 int nr = bt[ftype].size();
1535 int nral = NRAL(ftype);
1536 int nrfp = interaction_function[ftype].nrfpA;
1537 int nrfpB = interaction_function[ftype].nrfpB;
1539 if ((!bB && nrfp == 0) || (bB && nrfpB == 0))
1541 return TRUE;
1544 bFound = FALSE;
1545 if (bGenPairs)
1547 /* First test the generated-pair position to save
1548 * time when we have 1000*1000 entries for e.g. OPLS...
1550 ntype = static_cast<int>(std::sqrt(static_cast<double>(nr)));
1551 GMX_ASSERT(ntype * ntype == nr, "Number of pairs of generated non-bonded parameters should be a perfect square");
1552 if (bB)
1554 ti = at->atom[p->ai()].typeB;
1555 tj = at->atom[p->aj()].typeB;
1557 else
1559 ti = at->atom[p->ai()].type;
1560 tj = at->atom[p->aj()].type;
1562 pi = &(bt[ftype].interactionTypes[ntype*ti+tj]);
1563 if (pi->atoms().ssize() < nral)
1565 /* not initialized yet with atom names */
1566 bFound = false;
1568 else
1570 bFound = ((ti == pi->ai()) && (tj == pi->aj()));
1574 gmx::ArrayRef<const int> paramAtoms = p->atoms();
1575 /* Search explicitly if we didnt find it */
1576 if (!bFound)
1578 auto foundParameter = std::find_if(bt[ftype].interactionTypes.begin(),
1579 bt[ftype].interactionTypes.end(),
1580 [&paramAtoms, &at, &bB](const auto &param)
1581 { return findIfAllNBAtomsMatch(param.atoms(), paramAtoms, at, bB); });
1582 if (foundParameter != bt[ftype].interactionTypes.end())
1584 bFound = true;
1585 pi = &(*foundParameter);
1589 if (bFound)
1591 gmx::ArrayRef<const real> forceParam = pi->forceParam();
1592 if (bB)
1594 if (nrfp+nrfpB > MAXFORCEPARAM)
1596 gmx_incons("Too many force parameters");
1598 for (int j = c_start; j < nrfpB; j++)
1600 p->setForceParameter(nrfp+j, forceParam[j]);
1603 else
1605 for (int j = c_start; j < nrfp; j++)
1607 p->setForceParameter(j, forceParam[j]);
1611 else
1613 for (int j = c_start; j < nrfp; j++)
1615 p->setForceParameter(j, 0.0);
1618 return bFound;
1621 static bool default_cmap_params(gmx::ArrayRef<InteractionsOfType> bondtype,
1622 t_atoms *at, PreprocessingAtomTypes *atypes,
1623 InteractionOfType *p, bool bB,
1624 int *cmap_type, int *nparam_def,
1625 warninp *wi)
1627 int nparam_found;
1628 int ct;
1629 bool bFound = false;
1631 nparam_found = 0;
1632 ct = 0;
1634 /* Match the current cmap angle against the list of cmap_types */
1635 for (int i = 0; i < bondtype[F_CMAP].nct() && !bFound; i += 6)
1637 if (bB)
1641 else
1643 if (
1644 (atypes->bondAtomTypeFromAtomType(at->atom[p->ai()].type) == bondtype[F_CMAP].cmapAtomTypes[i]) &&
1645 (atypes->bondAtomTypeFromAtomType(at->atom[p->aj()].type) == bondtype[F_CMAP].cmapAtomTypes[i+1]) &&
1646 (atypes->bondAtomTypeFromAtomType(at->atom[p->ak()].type) == bondtype[F_CMAP].cmapAtomTypes[i+2]) &&
1647 (atypes->bondAtomTypeFromAtomType(at->atom[p->al()].type) == bondtype[F_CMAP].cmapAtomTypes[i+3]) &&
1648 (atypes->bondAtomTypeFromAtomType(at->atom[p->am()].type) == bondtype[F_CMAP].cmapAtomTypes[i+4]))
1650 /* Found cmap torsion */
1651 bFound = true;
1652 ct = bondtype[F_CMAP].cmapAtomTypes[i+5];
1653 nparam_found = 1;
1658 /* If we did not find a matching type for this cmap torsion */
1659 if (!bFound)
1661 auto message = gmx::formatString("Unknown cmap torsion between atoms %d %d %d %d %d",
1662 p->ai()+1, p->aj()+1, p->ak()+1, p->al()+1, p->am()+1);
1663 warning_error_and_exit(wi, message, FARGS);
1666 *nparam_def = nparam_found;
1667 *cmap_type = ct;
1669 return bFound;
1672 /* Returns the number of exact atom type matches, i.e. non wild-card matches,
1673 * returns -1 when there are no matches at all.
1675 static int natom_match(const InteractionOfType &pi,
1676 int type_i, int type_j, int type_k, int type_l,
1677 const PreprocessingAtomTypes* atypes)
1679 if ((pi.ai() == -1 || atypes->bondAtomTypeFromAtomType(type_i) == pi.ai()) &&
1680 (pi.aj() == -1 || atypes->bondAtomTypeFromAtomType(type_j) == pi.aj()) &&
1681 (pi.ak() == -1 || atypes->bondAtomTypeFromAtomType(type_k) == pi.ak()) &&
1682 (pi.al() == -1 || atypes->bondAtomTypeFromAtomType(type_l) == pi.al()))
1684 return
1685 (pi.ai() == -1 ? 0 : 1) +
1686 (pi.aj() == -1 ? 0 : 1) +
1687 (pi.ak() == -1 ? 0 : 1) +
1688 (pi.al() == -1 ? 0 : 1);
1690 else
1692 return -1;
1696 static int findNumberOfDihedralAtomMatches(const InteractionOfType &currentParamFromParameterArray,
1697 const InteractionOfType &parameterToAdd,
1698 const t_atoms *at,
1699 const PreprocessingAtomTypes *atypes,
1700 bool bB)
1702 if (bB)
1704 return natom_match(currentParamFromParameterArray,
1705 at->atom[parameterToAdd.ai()].typeB,
1706 at->atom[parameterToAdd.aj()].typeB,
1707 at->atom[parameterToAdd.ak()].typeB,
1708 at->atom[parameterToAdd.al()].typeB, atypes);
1710 else
1712 return natom_match(currentParamFromParameterArray,
1713 at->atom[parameterToAdd.ai()].type,
1714 at->atom[parameterToAdd.aj()].type,
1715 at->atom[parameterToAdd.ak()].type,
1716 at->atom[parameterToAdd.al()].type, atypes);
1720 static bool findIfAllParameterAtomsMatch(gmx::ArrayRef<const int> atomsFromParameterArray,
1721 gmx::ArrayRef<const int> atomsFromCurrentParameter,
1722 const t_atoms *at,
1723 const PreprocessingAtomTypes *atypes,
1724 bool bB)
1726 if (atomsFromParameterArray.size() != atomsFromCurrentParameter.size())
1728 return false;
1730 else if (bB)
1732 for (gmx::index i = 0; i < atomsFromCurrentParameter.ssize(); i++)
1734 if (atypes->bondAtomTypeFromAtomType(
1735 at->atom[atomsFromCurrentParameter[i]].typeB) != atomsFromParameterArray[i])
1737 return false;
1740 return true;
1742 else
1744 for (gmx::index i = 0; i < atomsFromCurrentParameter.ssize(); i++)
1746 if (atypes->bondAtomTypeFromAtomType(
1747 at->atom[atomsFromCurrentParameter[i]].type) != atomsFromParameterArray[i])
1749 return false;
1752 return true;
1756 static std::vector<InteractionOfType>::iterator
1757 defaultInteractionsOfType(int ftype, gmx::ArrayRef<InteractionsOfType> bt,
1758 t_atoms *at, PreprocessingAtomTypes *atypes,
1759 const InteractionOfType &p, bool bB,
1760 int *nparam_def)
1762 int nparam_found;
1763 int nrfpA = interaction_function[ftype].nrfpA;
1764 int nrfpB = interaction_function[ftype].nrfpB;
1766 if ((!bB && nrfpA == 0) || (bB && nrfpB == 0))
1768 return bt[ftype].interactionTypes.end();
1772 nparam_found = 0;
1773 if (ftype == F_PDIHS || ftype == F_RBDIHS || ftype == F_IDIHS || ftype == F_PIDIHS)
1775 int nmatch_max = -1;
1777 /* For dihedrals we allow wildcards. We choose the first type
1778 * that has the most real matches, i.e. non-wildcard matches.
1780 auto prevPos = bt[ftype].interactionTypes.end();
1781 auto pos = bt[ftype].interactionTypes.begin();
1782 while (pos != bt[ftype].interactionTypes.end() && nmatch_max < 4)
1784 pos = std::find_if(bt[ftype].interactionTypes.begin(), bt[ftype].interactionTypes.end(),
1785 [&p, &at, &atypes, &bB, &nmatch_max](const auto &param)
1786 { return (findNumberOfDihedralAtomMatches(param, p, at, atypes, bB) > nmatch_max); });
1787 if (pos != bt[ftype].interactionTypes.end())
1789 prevPos = pos;
1790 nmatch_max = findNumberOfDihedralAtomMatches(*pos, p, at, atypes, bB);
1794 if (prevPos != bt[ftype].interactionTypes.end())
1796 nparam_found++;
1798 /* Find additional matches for this dihedral - necessary
1799 * for ftype==9.
1800 * The rule in that case is that additional matches
1801 * HAVE to be on adjacent lines!
1803 bool bSame = true;
1804 //Advance iterator (like std::advance) without incrementing past end (UB)
1805 const auto safeAdvance = [](auto &it, auto n, auto end) {
1806 it = end-it > n ? it+n : end;
1808 /* Continue from current iterator position */
1809 auto nextPos = prevPos;
1810 const auto endIter = bt[ftype].interactionTypes.end();
1811 safeAdvance(nextPos, 2, endIter);
1812 for (; nextPos < endIter && bSame; safeAdvance(nextPos, 2, endIter))
1814 bSame = (prevPos->ai() == nextPos->ai() && prevPos->aj() == nextPos->aj() && prevPos->ak() == nextPos->ak() && prevPos->al() == nextPos->al());
1815 if (bSame)
1817 nparam_found++;
1819 /* nparam_found will be increased as long as the numbers match */
1822 *nparam_def = nparam_found;
1823 return prevPos;
1825 else /* Not a dihedral */
1827 gmx::ArrayRef<const int> atomParam = p.atoms();
1828 auto found = std::find_if(bt[ftype].interactionTypes.begin(),
1829 bt[ftype].interactionTypes.end(),
1830 [&atomParam, &at, &atypes, &bB](const auto &param)
1831 { return findIfAllParameterAtomsMatch(param.atoms(), atomParam, at, atypes, bB); });
1832 if (found != bt[ftype].interactionTypes.end())
1834 nparam_found = 1;
1836 *nparam_def = nparam_found;
1837 return found;
1843 void push_bond(Directive d, gmx::ArrayRef<InteractionsOfType> bondtype,
1844 gmx::ArrayRef<InteractionsOfType> bond,
1845 t_atoms *at, PreprocessingAtomTypes *atypes, char *line,
1846 bool bBonded, bool bGenPairs, real fudgeQQ,
1847 bool bZero, bool *bWarn_copy_A_B,
1848 warninp *wi)
1850 const char *aaformat[MAXATOMLIST] = {
1851 "%d%d",
1852 "%d%d%d",
1853 "%d%d%d%d",
1854 "%d%d%d%d%d",
1855 "%d%d%d%d%d%d",
1856 "%d%d%d%d%d%d%d"
1858 const char *asformat[MAXATOMLIST] = {
1859 "%*s%*s",
1860 "%*s%*s%*s",
1861 "%*s%*s%*s%*s",
1862 "%*s%*s%*s%*s%*s",
1863 "%*s%*s%*s%*s%*s%*s",
1864 "%*s%*s%*s%*s%*s%*s%*s"
1866 const char *ccformat = "%lf%lf%lf%lf%lf%lf%lf%lf%lf%lf%lf%lf%lf";
1867 int nral, nral_fmt, nread, ftype;
1868 char format[STRLEN];
1869 /* One force parameter more, so we can check if we read too many */
1870 double cc[MAXFORCEPARAM+1];
1871 int aa[MAXATOMLIST+1];
1872 bool bFoundA = FALSE, bFoundB = FALSE, bDef, bSwapParity = FALSE;
1873 int nparam_defA, nparam_defB;
1875 nparam_defA = nparam_defB = 0;
1877 ftype = ifunc_index(d, 1);
1878 nral = NRAL(ftype);
1879 for (int j = 0; j < nral; j++)
1881 aa[j] = NOTSET;
1883 bDef = (NRFP(ftype) > 0);
1885 if (ftype == F_SETTLE)
1887 /* SETTLE acts on 3 atoms, but the topology format only specifies
1888 * the first atom (for historical reasons).
1890 nral_fmt = 1;
1892 else
1894 nral_fmt = nral;
1897 nread = sscanf(line, aaformat[nral_fmt-1],
1898 &aa[0], &aa[1], &aa[2], &aa[3], &aa[4], &aa[5]);
1900 if (ftype == F_SETTLE)
1902 aa[3] = aa[1];
1903 aa[1] = aa[0] + 1;
1904 aa[2] = aa[0] + 2;
1907 if (nread < nral_fmt)
1909 too_few(wi);
1910 return;
1912 else if (nread > nral_fmt)
1914 /* this is a hack to allow for virtual sites with swapped parity */
1915 bSwapParity = (aa[nral] < 0);
1916 if (bSwapParity)
1918 aa[nral] = -aa[nral];
1920 ftype = ifunc_index(d, aa[nral]);
1921 if (bSwapParity)
1923 switch (ftype)
1925 case F_VSITE3FAD:
1926 case F_VSITE3OUT:
1927 break;
1928 default:
1929 auto message = gmx::formatString("Negative function types only allowed for %s and %s",
1930 interaction_function[F_VSITE3FAD].longname,
1931 interaction_function[F_VSITE3OUT].longname);
1932 warning_error_and_exit(wi, message, FARGS);
1938 /* Check for double atoms and atoms out of bounds */
1939 for (int i = 0; (i < nral); i++)
1941 if (aa[i] < 1 || aa[i] > at->nr)
1943 auto message = gmx::formatString
1944 ("Atom index (%d) in %s out of bounds (1-%d).\n"
1945 "This probably means that you have inserted topology section \"%s\"\n"
1946 "in a part belonging to a different molecule than you intended to.\n"
1947 "In that case move the \"%s\" section to the right molecule.",
1948 aa[i], dir2str(d), at->nr, dir2str(d), dir2str(d));
1949 warning_error_and_exit(wi, message, FARGS);
1951 for (int j = i+1; (j < nral); j++)
1953 GMX_ASSERT(j < MAXATOMLIST + 1, "Values from nral=NRAL() will satisfy this, we assert to keep gcc 4 happy");
1954 if (aa[i] == aa[j])
1956 auto message = gmx::formatString("Duplicate atom index (%d) in %s", aa[i], dir2str(d));
1957 if (ftype == F_ANGRES)
1959 /* Since the angle restraints uses 2 pairs of atoms to
1960 * defines an angle between vectors, it can be useful
1961 * to use one atom twice, so we only issue a note here.
1963 warning_note(wi, message);
1965 else
1967 warning_error(wi, message);
1973 /* default force parameters */
1974 std::vector<int> atoms;
1975 for (int j = 0; (j < nral); j++)
1977 atoms.emplace_back(aa[j]-1);
1979 /* need to have an empty but initialized param array for some reason */
1980 std::array<real, MAXFORCEPARAM> forceParam = {0.0};
1982 /* Get force params for normal and free energy perturbation
1983 * studies, as determined by types!
1985 InteractionOfType param(atoms, forceParam, "");
1987 std::vector<InteractionOfType>::iterator foundAParameter = bondtype[ftype].interactionTypes.end();
1988 std::vector<InteractionOfType>::iterator foundBParameter = bondtype[ftype].interactionTypes.end();
1989 if (bBonded)
1991 foundAParameter = defaultInteractionsOfType(ftype,
1992 bondtype,
1994 atypes,
1995 param,
1996 FALSE,
1997 &nparam_defA);
1998 if (foundAParameter != bondtype[ftype].interactionTypes.end())
2000 /* Copy the A-state and B-state default parameters. */
2001 GMX_ASSERT(NRFPA(ftype)+NRFPB(ftype) <= MAXFORCEPARAM, "Bonded interactions may have at most 12 parameters");
2002 gmx::ArrayRef<const real> defaultParam = foundAParameter->forceParam();
2003 for (int j = 0; (j < NRFPA(ftype)+NRFPB(ftype)); j++)
2005 param.setForceParameter(j, defaultParam[j]);
2007 bFoundA = true;
2009 else if (NRFPA(ftype) == 0)
2011 bFoundA = true;
2013 foundBParameter = defaultInteractionsOfType(ftype,
2014 bondtype,
2016 atypes,
2017 param,
2018 TRUE,
2019 &nparam_defB);
2020 if (foundBParameter != bondtype[ftype].interactionTypes.end())
2022 /* Copy only the B-state default parameters */
2023 gmx::ArrayRef<const real> defaultParam = foundBParameter->forceParam();
2024 for (int j = NRFPA(ftype); (j < NRFP(ftype)); j++)
2026 param.setForceParameter(j, defaultParam[j]);
2028 bFoundB = true;
2030 else if (NRFPB(ftype) == 0)
2032 bFoundB = true;
2035 else if (ftype == F_LJ14)
2037 bFoundA = default_nb_params(ftype, bondtype, at, &param, 0, FALSE, bGenPairs);
2038 bFoundB = default_nb_params(ftype, bondtype, at, &param, 0, TRUE, bGenPairs);
2040 else if (ftype == F_LJC14_Q)
2042 /* Fill in the A-state charges as default parameters */
2043 param.setForceParameter(0, fudgeQQ);
2044 param.setForceParameter(1, at->atom[param.ai()].q);
2045 param.setForceParameter(2, at->atom[param.aj()].q);
2046 /* The default LJ parameters are the standard 1-4 parameters */
2047 bFoundA = default_nb_params(F_LJ14, bondtype, at, &param, 3, FALSE, bGenPairs);
2048 bFoundB = TRUE;
2050 else if (ftype == F_LJC_PAIRS_NB)
2052 /* Defaults are not supported here */
2053 bFoundA = FALSE;
2054 bFoundB = TRUE;
2056 else
2058 gmx_incons("Unknown function type in push_bond");
2061 if (nread > nral_fmt)
2063 /* Manually specified parameters - in this case we discard multiple torsion info! */
2065 strcpy(format, asformat[nral_fmt-1]);
2066 strcat(format, ccformat);
2068 nread = sscanf(line, format, &cc[0], &cc[1], &cc[2], &cc[3], &cc[4], &cc[5],
2069 &cc[6], &cc[7], &cc[8], &cc[9], &cc[10], &cc[11], &cc[12]);
2071 if ((nread == NRFPA(ftype)) && (NRFPB(ftype) != 0))
2073 /* We only have to issue a warning if these atoms are perturbed! */
2074 bool bPert = false;
2075 gmx::ArrayRef<const int> paramAtoms = param.atoms();
2076 for (int j = 0; (j < nral); j++)
2078 bPert = bPert || PERTURBED(at->atom[paramAtoms[j]]);
2081 if (bPert && *bWarn_copy_A_B)
2083 auto message = gmx::formatString("Some parameters for bonded interaction involving "
2084 "perturbed atoms are specified explicitly in "
2085 "state A, but not B - copying A to B");
2086 warning(wi, message);
2087 *bWarn_copy_A_B = FALSE;
2090 /* If only the A parameters were specified, copy them to the B state */
2091 /* The B-state parameters correspond to the first nrfpB
2092 * A-state parameters.
2094 for (int j = 0; (j < NRFPB(ftype)); j++)
2096 cc[nread++] = cc[j];
2100 /* If nread was 0 or EOF, no parameters were read => use defaults.
2101 * If nread was nrfpA we copied above so nread=nrfp.
2102 * If nread was nrfp we are cool.
2103 * For F_LJC14_Q we allow supplying fudgeQQ only.
2104 * Anything else is an error!
2106 if ((nread != 0) && (nread != EOF) && (nread != NRFP(ftype)) &&
2107 !(ftype == F_LJC14_Q && nread == 1))
2109 auto message = gmx::formatString
2110 ("Incorrect number of parameters - found %d, expected %d "
2111 "or %d for %s (after the function type).",
2112 nread, NRFPA(ftype), NRFP(ftype), interaction_function[ftype].longname);
2113 warning_error_and_exit(wi, message, FARGS);
2116 for (int j = 0; (j < nread); j++)
2118 param.setForceParameter(j, cc[j]);
2120 /* Check whether we have to use the defaults */
2121 if (nread == NRFP(ftype))
2123 bDef = FALSE;
2126 else
2128 nread = 0;
2130 /* nread now holds the number of force parameters read! */
2132 if (bDef)
2134 /* Use defaults */
2135 /* When we have multiple terms it would be very dangerous to allow perturbations to a different atom type! */
2136 if (ftype == F_PDIHS)
2138 if ((nparam_defA != nparam_defB) || ((nparam_defA > 1 || nparam_defB > 1) && (foundAParameter != foundBParameter)))
2140 auto message =
2141 gmx::formatString("Cannot automatically perturb a torsion with multiple terms to different form.\n"
2142 "Please specify perturbed parameters manually for this torsion in your topology!");
2143 warning_error(wi, message);
2147 if (nread > 0 && nread < NRFPA(ftype))
2149 /* Issue an error, do not use defaults */
2150 auto message = gmx::formatString("Not enough parameters, there should be at least %d (or 0 for defaults)", NRFPA(ftype));
2151 warning_error(wi, message);
2154 if (nread == 0 || nread == EOF)
2156 if (!bFoundA)
2158 if (interaction_function[ftype].flags & IF_VSITE)
2160 for (int j = 0; j < MAXFORCEPARAM; j++)
2162 param.setForceParameter(j, NOTSET);
2164 if (bSwapParity)
2166 /* flag to swap parity of vsi te construction */
2167 param.setForceParameter(1, -1);
2170 else
2172 if (bZero)
2174 fprintf(stderr, "NOTE: No default %s types, using zeroes\n",
2175 interaction_function[ftype].longname);
2177 else
2179 auto message = gmx::formatString("No default %s types", interaction_function[ftype].longname);
2180 warning_error(wi, message);
2184 else
2186 if (bSwapParity)
2188 switch (ftype)
2190 case F_VSITE3FAD:
2191 param.setForceParameter(0, 360 - param.c0());
2192 break;
2193 case F_VSITE3OUT:
2194 param.setForceParameter(2, -param.c2());
2195 break;
2199 if (!bFoundB)
2201 /* We only have to issue a warning if these atoms are perturbed! */
2202 bool bPert = false;
2203 gmx::ArrayRef<const int> paramAtoms = param.atoms();
2204 for (int j = 0; (j < nral); j++)
2206 bPert = bPert || PERTURBED(at->atom[paramAtoms[j]]);
2209 if (bPert)
2211 auto message = gmx::formatString("No default %s types for perturbed atoms, "
2212 "using normal values", interaction_function[ftype].longname);
2213 warning(wi, message);
2219 gmx::ArrayRef<const real> paramValue = param.forceParam();
2220 if ((ftype == F_PDIHS || ftype == F_ANGRES || ftype == F_ANGRESZ)
2221 && paramValue[5] != paramValue[2])
2223 auto message = gmx::formatString("%s multiplicity can not be perturbed %f!=%f",
2224 interaction_function[ftype].longname,
2225 paramValue[2], paramValue[5]);
2226 warning_error_and_exit(wi, message, FARGS);
2229 if (IS_TABULATED(ftype) && param.c0() != param.c2())
2231 auto message = gmx::formatString("%s table number can not be perturbed %d!=%d",
2232 interaction_function[ftype].longname,
2233 gmx::roundToInt(param.c0()), gmx::roundToInt(param.c0()));
2234 warning_error_and_exit(wi, message, FARGS);
2237 /* Dont add R-B dihedrals where all parameters are zero (no interaction) */
2238 if (ftype == F_RBDIHS)
2241 int nr = 0;
2242 for (int i = 0; i < NRFP(ftype); i++)
2244 if (paramValue[i] != 0.0)
2246 nr++;
2249 if (nr == 0)
2251 return;
2255 /* Put the values in the appropriate arrays */
2256 add_param_to_list (&bond[ftype], param);
2258 /* Push additional torsions from FF for ftype==9 if we have them.
2259 * We have already checked that the A/B states do not differ in this case,
2260 * so we do not have to double-check that again, or the vsite stuff.
2261 * In addition, those torsions cannot be automatically perturbed.
2263 if (bDef && ftype == F_PDIHS)
2265 for (int i = 1; i < nparam_defA; i++)
2267 /* Advance pointer! */
2268 foundAParameter += 2;
2269 gmx::ArrayRef<const real> forceParam = foundAParameter->forceParam();
2270 for (int j = 0; j < (NRFPA(ftype)+NRFPB(ftype)); j++)
2272 param.setForceParameter(j, forceParam[j]);
2274 /* And push the next term for this torsion */
2275 add_param_to_list (&bond[ftype], param);
2280 void push_cmap(Directive d, gmx::ArrayRef<InteractionsOfType> bondtype,
2281 gmx::ArrayRef<InteractionsOfType> bond,
2282 t_atoms *at, PreprocessingAtomTypes *atypes, char *line,
2283 warninp *wi)
2285 const char *aaformat[MAXATOMLIST+1] =
2287 "%d",
2288 "%d%d",
2289 "%d%d%d",
2290 "%d%d%d%d",
2291 "%d%d%d%d%d",
2292 "%d%d%d%d%d%d",
2293 "%d%d%d%d%d%d%d"
2296 int ftype, nral, nread, ncmap_params;
2297 int cmap_type;
2298 int aa[MAXATOMLIST+1];
2299 bool bFound;
2301 ftype = ifunc_index(d, 1);
2302 nral = NRAL(ftype);
2303 ncmap_params = 0;
2305 nread = sscanf(line, aaformat[nral-1],
2306 &aa[0], &aa[1], &aa[2], &aa[3], &aa[4], &aa[5]);
2308 if (nread < nral)
2310 too_few(wi);
2311 return;
2313 else if (nread == nral)
2315 ftype = ifunc_index(d, 1);
2318 /* Check for double atoms and atoms out of bounds */
2319 for (int i = 0; i < nral; i++)
2321 if (aa[i] < 1 || aa[i] > at->nr)
2323 auto message = gmx::formatString
2324 ("Atom index (%d) in %s out of bounds (1-%d).\n"
2325 "This probably means that you have inserted topology section \"%s\"\n"
2326 "in a part belonging to a different molecule than you intended to.\n"
2327 "In that case move the \"%s\" section to the right molecule.",
2328 aa[i], dir2str(d), at->nr, dir2str(d), dir2str(d));
2329 warning_error_and_exit(wi, message, FARGS);
2332 for (int j = i+1; (j < nral); j++)
2334 if (aa[i] == aa[j])
2336 auto message = gmx::formatString("Duplicate atom index (%d) in %s", aa[i], dir2str(d));
2337 warning_error(wi, message);
2342 /* default force parameters */
2343 std::vector<int> atoms;
2344 for (int j = 0; (j < nral); j++)
2346 atoms.emplace_back(aa[j]-1);
2348 std::array<real, MAXFORCEPARAM> forceParam = {0.0};
2349 InteractionOfType param(atoms, forceParam, "");
2350 /* Get the cmap type for this cmap angle */
2351 bFound = default_cmap_params(bondtype, at, atypes, &param, FALSE, &cmap_type, &ncmap_params, wi);
2353 /* We want exactly one parameter (the cmap type in state A (currently no state B) back */
2354 if (bFound && ncmap_params == 1)
2356 /* Put the values in the appropriate arrays */
2357 param.setForceParameter(0, cmap_type);
2358 add_param_to_list(&bond[ftype], param);
2360 else
2362 /* This is essentially the same check as in default_cmap_params() done one more time */
2363 auto message = gmx::formatString("Unable to assign a cmap type to torsion %d %d %d %d and %d\n",
2364 param.ai()+1, param.aj()+1, param.ak()+1, param.al()+1, param.am()+1);
2365 warning_error_and_exit(wi, message, FARGS);
2371 void push_vsitesn(Directive d, gmx::ArrayRef<InteractionsOfType> bond,
2372 t_atoms *at, char *line,
2373 warninp *wi)
2375 char *ptr;
2376 int type, ftype, n, ret, nj, a;
2377 int *atc = nullptr;
2378 double *weight = nullptr, weight_tot;
2380 std::array<real, MAXFORCEPARAM> forceParam = {0.0};
2381 ptr = line;
2382 ret = sscanf(ptr, "%d%n", &a, &n);
2383 ptr += n;
2384 if (ret == 0)
2386 auto message = gmx::formatString("Expected an atom index in section \"%s\"",
2387 dir2str(d));
2388 warning_error_and_exit(wi, message, FARGS);
2391 sscanf(ptr, "%d%n", &type, &n);
2392 ptr += n;
2393 ftype = ifunc_index(d, type);
2394 int firstAtom = a - 1;
2396 weight_tot = 0;
2397 nj = 0;
2400 ret = sscanf(ptr, "%d%n", &a, &n);
2401 ptr += n;
2402 if (ret > 0)
2404 if (nj % 20 == 0)
2406 srenew(atc, nj+20);
2407 srenew(weight, nj+20);
2409 atc[nj] = a - 1;
2410 switch (type)
2412 case 1:
2413 weight[nj] = 1;
2414 break;
2415 case 2:
2416 /* Here we use the A-state mass as a parameter.
2417 * Note that the B-state mass has no influence.
2419 weight[nj] = at->atom[atc[nj]].m;
2420 break;
2421 case 3:
2422 weight[nj] = -1;
2423 ret = sscanf(ptr, "%lf%n", &(weight[nj]), &n);
2424 ptr += n;
2425 if (weight[nj] < 0)
2427 auto message = gmx::formatString
2428 ("No weight or negative weight found for vsiten "
2429 "constructing atom %d (atom index %d)",
2430 nj+1, atc[nj]+1);
2431 warning_error_and_exit(wi, message, FARGS);
2433 break;
2434 default:
2435 auto message = gmx::formatString("Unknown vsiten type %d", type);
2436 warning_error_and_exit(wi, message, FARGS);
2438 weight_tot += weight[nj];
2439 nj++;
2442 while (ret > 0);
2444 if (nj == 0)
2446 auto message = gmx::formatString("Expected more than one atom index in section \"%s\"",
2447 dir2str(d));
2448 warning_error_and_exit(wi, message, FARGS);
2451 if (weight_tot == 0)
2453 warning_error_and_exit(wi, "The total mass of the construting atoms is zero", FARGS);
2456 for (int j = 0; j < nj; j++)
2458 std::vector<int> atoms = {firstAtom, atc[j]};
2459 forceParam[0] = nj;
2460 forceParam[1] = weight[j]/weight_tot;
2461 /* Put the values in the appropriate arrays */
2462 add_param_to_list (&bond[ftype], InteractionOfType(atoms, forceParam));
2465 sfree(atc);
2466 sfree(weight);
2469 void push_mol(gmx::ArrayRef<MoleculeInformation> mols, char *pline, int *whichmol,
2470 int *nrcopies,
2471 warninp *wi)
2473 char type[STRLEN];
2475 if (sscanf(pline, "%s%d", type, nrcopies) != 2)
2477 too_few(wi);
2478 return;
2481 /* Search moleculename.
2482 * Here we originally only did case insensitive matching. But because
2483 * some PDB files can have many chains and use case to generate more
2484 * chain-identifiers, which in turn end up in our moleculetype name,
2485 * we added support for case-sensitivity.
2487 int nrcs = 0;
2488 int nrci = 0;
2489 int matchci = -1;
2490 int matchcs = -1;
2491 int i = 0;
2492 for (const auto &mol : mols)
2494 if (strcmp(type, *(mol.name)) == 0)
2496 nrcs++;
2497 matchcs = i;
2499 if (gmx_strcasecmp(type, *(mol.name)) == 0)
2501 nrci++;
2502 matchci = i;
2504 i++;
2507 if (nrcs == 1)
2509 // select the case sensitive match
2510 *whichmol = matchcs;
2512 else
2514 // avoid matching case-insensitive when we have multiple matches
2515 if (nrci > 1)
2517 auto message = gmx::formatString
2518 ("For moleculetype '%s' in [ system ] %d case insensitive "
2519 "matches, but %d case sensitive matches were found. Check "
2520 "the case of the characters in the moleculetypes.",
2521 type, nrci, nrcs);
2522 warning_error_and_exit(wi, message, FARGS);
2524 if (nrci == 1)
2526 // select the unique case insensitive match
2527 *whichmol = matchci;
2529 else
2531 auto message = gmx::formatString("No such moleculetype %s", type);
2532 warning_error_and_exit(wi, message, FARGS);
2537 void push_excl(char *line, gmx::ArrayRef<gmx::ExclusionBlock> b2, warninp *wi)
2539 int i, j;
2540 int n;
2541 char base[STRLEN], format[STRLEN];
2543 if (sscanf(line, "%d", &i) == 0)
2545 return;
2548 if ((1 <= i) && (i <= b2.ssize()))
2550 i--;
2552 else
2554 return;
2556 strcpy(base, "%*d");
2559 strcpy(format, base);
2560 strcat(format, "%d");
2561 n = sscanf(line, format, &j);
2562 if (n == 1)
2564 if ((1 <= j) && (j <= b2.ssize()))
2566 j--;
2567 b2[i].atomNumber.push_back(j);
2568 /* also add the reverse exclusion! */
2569 b2[j].atomNumber.push_back(i);
2570 strcat(base, "%*d");
2572 else
2574 auto message = gmx::formatString("Invalid Atomnr j: %d, b2->nr: %zu\n", j, b2.size());
2575 warning_error_and_exit(wi, message, FARGS);
2579 while (n == 1);
2582 int add_atomtype_decoupled(t_symtab *symtab, PreprocessingAtomTypes *at,
2583 t_nbparam ***nbparam, t_nbparam ***pair)
2585 t_atom atom;
2586 int nr;
2588 /* Define an atom type with all parameters set to zero (no interactions) */
2589 atom.q = 0.0;
2590 atom.m = 0.0;
2591 /* Type for decoupled atoms could be anything,
2592 * this should be changed automatically later when required.
2594 atom.ptype = eptAtom;
2596 std::array<real, MAXFORCEPARAM> forceParam = {0.0};
2597 nr = at->addType(symtab, atom, "decoupled", InteractionOfType({}, forceParam, ""), -1, 0);
2599 /* Add space in the non-bonded parameters matrix */
2600 realloc_nb_params(at, nbparam, pair);
2602 return nr;
2605 static void convert_pairs_to_pairsQ(gmx::ArrayRef<InteractionsOfType> interactions,
2606 real fudgeQQ, t_atoms *atoms)
2608 /* Add the pair list to the pairQ list */
2609 std::vector<InteractionOfType> paramnew;
2611 gmx::ArrayRef<const InteractionOfType> paramp1 = interactions[F_LJ14].interactionTypes;
2612 gmx::ArrayRef<const InteractionOfType> paramp2 = interactions[F_LJC14_Q].interactionTypes;
2614 /* Fill in the new F_LJC14_Q array with the old one. NOTE:
2615 it may be possible to just ADD the converted F_LJ14 array
2616 to the old F_LJC14_Q array, but since we have to create
2617 a new sized memory structure, better just to deep copy it all.
2621 for (const auto &param : paramp2)
2623 paramnew.emplace_back(param);
2626 for (const auto &param : paramp1)
2628 std::vector<real> forceParam = {
2629 fudgeQQ, atoms->atom[param.ai()].q, atoms->atom[param.aj()].q,
2630 param.c0(), param.c1()
2632 paramnew.emplace_back(InteractionOfType(param.atoms(), forceParam, ""));
2635 /* now assign the new data to the F_LJC14_Q structure */
2636 interactions[F_LJC14_Q].interactionTypes = paramnew;
2638 /* Empty the LJ14 pairlist */
2639 interactions[F_LJ14].interactionTypes.clear();
2642 static void generate_LJCpairsNB(MoleculeInformation *mol, int nb_funct, InteractionsOfType *nbp, warninp *wi)
2644 int n, ntype;
2645 t_atom *atom;
2646 t_blocka *excl;
2647 bool bExcl;
2649 n = mol->atoms.nr;
2650 atom = mol->atoms.atom;
2652 ntype = static_cast<int>(std::sqrt(static_cast<double>(nbp->size())));
2653 GMX_ASSERT(ntype * ntype == gmx::ssize(*nbp), "Number of pairs of generated non-bonded parameters should be a perfect square");
2655 /* Add a pair interaction for all non-excluded atom pairs */
2656 excl = &mol->excls;
2657 for (int i = 0; i < n; i++)
2659 for (int j = i+1; j < n; j++)
2661 bExcl = FALSE;
2662 for (int k = excl->index[i]; k < excl->index[i+1]; k++)
2664 if (excl->a[k] == j)
2666 bExcl = TRUE;
2669 if (!bExcl)
2671 if (nb_funct != F_LJ)
2673 auto message = gmx::formatString
2674 ("Can only generate non-bonded pair interactions "
2675 "for Van der Waals type Lennard-Jones");
2676 warning_error_and_exit(wi, message, FARGS);
2678 std::vector<int> atoms = {i, j};
2679 std::vector<real> forceParam = {
2680 atom[i].q,
2681 atom[j].q,
2682 nbp->interactionTypes[ntype*atom[i].type+atom[j].type].c0(),
2683 nbp->interactionTypes[ntype*atom[i].type+atom[j].type].c1()
2685 add_param_to_list(&mol->interactions[F_LJC_PAIRS_NB], InteractionOfType(atoms, forceParam));
2691 static void set_excl_all(t_blocka *excl)
2693 int nat, i, j, k;
2695 /* Get rid of the current exclusions and exclude all atom pairs */
2696 nat = excl->nr;
2697 excl->nra = nat*nat;
2698 srenew(excl->a, excl->nra);
2699 k = 0;
2700 for (i = 0; i < nat; i++)
2702 excl->index[i] = k;
2703 for (j = 0; j < nat; j++)
2705 excl->a[k++] = j;
2708 excl->index[nat] = k;
2711 static void decouple_atoms(t_atoms *atoms, int atomtype_decouple,
2712 int couple_lam0, int couple_lam1,
2713 const char *mol_name, warninp *wi)
2715 int i;
2717 for (i = 0; i < atoms->nr; i++)
2719 t_atom *atom;
2721 atom = &atoms->atom[i];
2723 if (atom->qB != atom->q || atom->typeB != atom->type)
2725 auto message = gmx::formatString
2726 ("Atom %d in molecule type '%s' has different A and B state "
2727 "charges and/or atom types set in the topology file as well "
2728 "as through the mdp option '%s'. You can not use both "
2729 "these methods simultaneously.",
2730 i + 1, mol_name, "couple-moltype");
2731 warning_error_and_exit(wi, message, FARGS);
2734 if (couple_lam0 == ecouplamNONE || couple_lam0 == ecouplamVDW)
2736 atom->q = 0.0;
2738 if (couple_lam0 == ecouplamNONE || couple_lam0 == ecouplamQ)
2740 atom->type = atomtype_decouple;
2742 if (couple_lam1 == ecouplamNONE || couple_lam1 == ecouplamVDW)
2744 atom->qB = 0.0;
2746 if (couple_lam1 == ecouplamNONE || couple_lam1 == ecouplamQ)
2748 atom->typeB = atomtype_decouple;
2753 void convert_moltype_couple(MoleculeInformation *mol, int atomtype_decouple, real fudgeQQ,
2754 int couple_lam0, int couple_lam1,
2755 bool bCoupleIntra, int nb_funct, InteractionsOfType *nbp,
2756 warninp *wi)
2758 convert_pairs_to_pairsQ(mol->interactions, fudgeQQ, &mol->atoms);
2759 if (!bCoupleIntra)
2761 generate_LJCpairsNB(mol, nb_funct, nbp, wi);
2762 set_excl_all(&mol->excls);
2764 decouple_atoms(&mol->atoms, atomtype_decouple, couple_lam0, couple_lam1,
2765 *mol->name, wi);