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 by the GROMACS development team.
7 * Copyright (c) 2018,2019,2020,2021, by the GROMACS development team, led by
8 * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
9 * and including many others, as listed in the AUTHORS file in the
10 * top-level source directory and at http://www.gromacs.org.
12 * GROMACS is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU Lesser General Public License
14 * as published by the Free Software Foundation; either version 2.1
15 * of the License, or (at your option) any later version.
17 * GROMACS is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * Lesser General Public License for more details.
22 * You should have received a copy of the GNU Lesser General Public
23 * License along with GROMACS; if not, see
24 * http://www.gnu.org/licenses, or write to the Free Software Foundation,
25 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
27 * If you want to redistribute modifications to GROMACS, please
28 * consider that scientific software is very special. Version
29 * control is crucial - bugs must be traceable. We will be happy to
30 * consider code for inclusion in the official distribution, but
31 * derived work must not be called official GROMACS. Details are found
32 * in the README & COPYING files - if they are missing, get the
33 * official version at http://www.gromacs.org.
35 * To help us fund GROMACS development, we humbly ask that you cite
36 * the research papers on the package. Check out http://www.gromacs.org.
50 #include "gromacs/fileio/warninp.h"
51 #include "gromacs/gmxpreprocess/gpp_atomtype.h"
52 #include "gromacs/gmxpreprocess/gpp_bond_atomtype.h"
53 #include "gromacs/gmxpreprocess/grompp_impl.h"
54 #include "gromacs/gmxpreprocess/notset.h"
55 #include "gromacs/gmxpreprocess/readir.h"
56 #include "gromacs/gmxpreprocess/topdirs.h"
57 #include "gromacs/gmxpreprocess/toputil.h"
58 #include "gromacs/math/functions.h"
59 #include "gromacs/mdtypes/md_enums.h"
60 #include "gromacs/topology/exclusionblocks.h"
61 #include "gromacs/topology/ifunc.h"
62 #include "gromacs/topology/symtab.h"
63 #include "gromacs/utility/arrayref.h"
64 #include "gromacs/utility/cstringutil.h"
65 #include "gromacs/utility/fatalerror.h"
66 #include "gromacs/utility/gmxassert.h"
67 #include "gromacs/utility/smalloc.h"
68 #include "gromacs/utility/stringutil.h"
70 void generate_nbparams(CombinationRule comb,
72 InteractionsOfType* interactions,
73 PreprocessingAtomTypes* atypes,
77 real c, bi, bj, ci, cj, ci0, ci1, ci2, cj0, cj1, cj2;
79 /* Lean mean shortcuts */
82 interactions->interactionTypes.clear();
84 std::array<real, MAXFORCEPARAM> forceParam = { NOTSET };
85 /* Fill the matrix with force parameters */
91 case CombinationRule::Geometric:
93 for (int i = 0; (i < nr); i++)
95 for (int j = 0; (j < nr); j++)
97 for (int nf = 0; (nf < nrfp); nf++)
99 ci = atypes->atomNonBondedParamFromAtomType(i, nf);
100 cj = atypes->atomNonBondedParamFromAtomType(j, nf);
101 c = std::sqrt(ci * cj);
104 interactions->interactionTypes.emplace_back(InteractionOfType({}, forceParam));
109 case CombinationRule::Arithmetic:
110 /* c0 and c1 are sigma and epsilon */
111 for (int i = 0; (i < nr); i++)
113 for (int j = 0; (j < nr); j++)
115 ci0 = atypes->atomNonBondedParamFromAtomType(i, 0);
116 cj0 = atypes->atomNonBondedParamFromAtomType(j, 0);
117 ci1 = atypes->atomNonBondedParamFromAtomType(i, 1);
118 cj1 = atypes->atomNonBondedParamFromAtomType(j, 1);
119 forceParam[0] = (fabs(ci0) + fabs(cj0)) * 0.5;
120 /* Negative sigma signals that c6 should be set to zero later,
121 * so we need to propagate that through the combination rules.
123 if (ci0 < 0 || cj0 < 0)
127 forceParam[1] = std::sqrt(ci1 * cj1);
128 interactions->interactionTypes.emplace_back(InteractionOfType({}, forceParam));
133 case CombinationRule::GeomSigEps:
134 /* c0 and c1 are sigma and epsilon */
135 for (int i = 0; (i < nr); i++)
137 for (int j = 0; (j < nr); j++)
139 ci0 = atypes->atomNonBondedParamFromAtomType(i, 0);
140 cj0 = atypes->atomNonBondedParamFromAtomType(j, 0);
141 ci1 = atypes->atomNonBondedParamFromAtomType(i, 1);
142 cj1 = atypes->atomNonBondedParamFromAtomType(j, 1);
143 forceParam[0] = std::sqrt(std::fabs(ci0 * cj0));
144 /* Negative sigma signals that c6 should be set to zero later,
145 * so we need to propagate that through the combination rules.
147 if (ci0 < 0 || cj0 < 0)
151 forceParam[1] = std::sqrt(ci1 * cj1);
152 interactions->interactionTypes.emplace_back(InteractionOfType({}, forceParam));
159 gmx::formatString("No such combination rule %s", enumValueToString(comb));
160 warning_error_and_exit(wi, message, FARGS);
165 /* Buckingham rules */
166 for (int i = 0; (i < nr); i++)
168 for (int j = 0; (j < nr); j++)
170 ci0 = atypes->atomNonBondedParamFromAtomType(i, 0);
171 cj0 = atypes->atomNonBondedParamFromAtomType(j, 0);
172 ci2 = atypes->atomNonBondedParamFromAtomType(i, 2);
173 cj2 = atypes->atomNonBondedParamFromAtomType(j, 2);
174 bi = atypes->atomNonBondedParamFromAtomType(i, 1);
175 bj = atypes->atomNonBondedParamFromAtomType(j, 1);
176 forceParam[0] = std::sqrt(ci0 * cj0);
177 if ((bi == 0) || (bj == 0))
183 forceParam[1] = 2.0 / (1 / bi + 1 / bj);
185 forceParam[2] = std::sqrt(ci2 * cj2);
186 interactions->interactionTypes.emplace_back(InteractionOfType({}, forceParam));
192 auto message = gmx::formatString("Invalid nonbonded type %s",
193 interaction_function[ftype].longname);
194 warning_error(wi, message);
198 /*! \brief Used to temporarily store the explicit non-bonded parameter
199 * combinations, which will be copied to InteractionsOfType. */
202 //! Has this combination been set.
204 //! The non-bonded parameters
208 static void realloc_nb_params(PreprocessingAtomTypes* atypes, t_nbparam*** nbparam, t_nbparam*** pair)
210 /* Add space in the non-bonded parameters matrix */
211 int atnr = atypes->size();
212 srenew(*nbparam, atnr);
213 snew((*nbparam)[atnr - 1], atnr);
217 snew((*pair)[atnr - 1], atnr);
221 int copy_nbparams(t_nbparam** param, int ftype, InteractionsOfType* interactions, int nr)
228 for (int i = 0; i < nr; i++)
230 for (int j = 0; j <= i; j++)
232 GMX_RELEASE_ASSERT(param, "Must have valid parameters");
233 if (param[i][j].bSet)
235 for (int f = 0; f < nrfp; f++)
237 interactions->interactionTypes[nr * i + j].setForceParameter(f, param[i][j].c[f]);
238 interactions->interactionTypes[nr * j + i].setForceParameter(f, param[i][j].c[f]);
248 void free_nbparam(t_nbparam** param, int nr)
252 GMX_RELEASE_ASSERT(param, "Must have valid parameters");
253 for (i = 0; i < nr; i++)
255 GMX_RELEASE_ASSERT(param[i], "Must have valid parameters");
261 static void copy_B_from_A(int ftype, double* c)
265 nrfpA = NRFPA(ftype);
266 nrfpB = NRFPB(ftype);
268 /* Copy the B parameters from the first nrfpB A parameters */
269 for (i = 0; (i < nrfpB); i++)
275 void push_at(t_symtab* symtab,
276 PreprocessingAtomTypes* at,
277 PreprocessingBondAtomType* bondAtomType,
280 t_nbparam*** nbparam,
289 t_xlate xl[eptNR] = {
290 { "A", eptAtom }, { "N", eptNucleus }, { "S", eptShell },
291 { "B", eptBond }, { "V", eptVSite },
294 int nr, nfields, j, pt, nfp0 = -1;
295 int batype_nr, nread;
296 char type[STRLEN], btype[STRLEN], ptype[STRLEN];
298 double c[MAXFORCEPARAM];
299 char tmpfield[12][100]; /* Max 12 fields of width 100 */
302 bool have_atomic_number;
303 bool have_bonded_type;
307 /* First assign input line to temporary array */
308 nfields = sscanf(line,
309 "%s%s%s%s%s%s%s%s%s%s%s%s",
323 /* Comments on optional fields in the atomtypes section:
325 * The force field format is getting a bit old. For OPLS-AA we needed
326 * to add a special bonded atomtype, and for Gerrit Groenhofs QM/MM stuff
327 * we also needed the atomic numbers.
328 * To avoid making all old or user-generated force fields unusable we
329 * have introduced both these quantities as optional columns, and do some
330 * acrobatics to check whether they are present or not.
331 * This will all look much nicer when we switch to XML... sigh.
333 * Field 0 (mandatory) is the nonbonded type name. (string)
334 * Field 1 (optional) is the bonded type (string)
335 * Field 2 (optional) is the atomic number (int)
336 * Field 3 (mandatory) is the mass (numerical)
337 * Field 4 (mandatory) is the charge (numerical)
338 * Field 5 (mandatory) is the particle type (single character)
339 * This is followed by a number of nonbonded parameters.
341 * The safest way to identify the format is the particle type field.
343 * So, here is what we do:
345 * A. Read in the first six fields as strings
346 * B. If field 3 (starting from 0) is a single char, we have neither
347 * bonded_type or atomic numbers.
348 * C. If field 5 is a single char we have both.
349 * D. If field 4 is a single char we check field 1. If this begins with
350 * an alphabetical character we have bonded types, otherwise atomic numbers.
359 if ((strlen(tmpfield[5]) == 1) && isalpha(tmpfield[5][0]))
361 have_bonded_type = TRUE;
362 have_atomic_number = TRUE;
364 else if ((strlen(tmpfield[3]) == 1) && isalpha(tmpfield[3][0]))
366 have_bonded_type = FALSE;
367 have_atomic_number = FALSE;
371 have_bonded_type = (isalpha(tmpfield[1][0]) != 0);
372 have_atomic_number = !have_bonded_type;
375 /* optional fields */
384 if (have_atomic_number)
386 if (have_bonded_type)
389 line, "%s%s%d%lf%lf%s%lf%lf", type, btype, &atomnr, &m, &q, ptype, &c[0], &c[1]);
398 /* have_atomic_number && !have_bonded_type */
399 nread = sscanf(line, "%s%d%lf%lf%s%lf%lf", type, &atomnr, &m, &q, ptype, &c[0], &c[1]);
409 if (have_bonded_type)
411 /* !have_atomic_number && have_bonded_type */
412 nread = sscanf(line, "%s%s%lf%lf%s%lf%lf", type, btype, &m, &q, ptype, &c[0], &c[1]);
421 /* !have_atomic_number && !have_bonded_type */
422 nread = sscanf(line, "%s%lf%lf%s%lf%lf", type, &m, &q, ptype, &c[0], &c[1]);
431 if (!have_bonded_type)
436 if (!have_atomic_number)
446 if (have_atomic_number)
448 if (have_bonded_type)
451 line, "%s%s%d%lf%lf%s%lf%lf%lf", type, btype, &atomnr, &m, &q, ptype, &c[0], &c[1], &c[2]);
460 /* have_atomic_number && !have_bonded_type */
462 line, "%s%d%lf%lf%s%lf%lf%lf", type, &atomnr, &m, &q, ptype, &c[0], &c[1], &c[2]);
472 if (have_bonded_type)
474 /* !have_atomic_number && have_bonded_type */
476 line, "%s%s%lf%lf%s%lf%lf%lf", type, btype, &m, &q, ptype, &c[0], &c[1], &c[2]);
485 /* !have_atomic_number && !have_bonded_type */
486 nread = sscanf(line, "%s%lf%lf%s%lf%lf%lf", type, &m, &q, ptype, &c[0], &c[1], &c[2]);
495 if (!have_bonded_type)
500 if (!have_atomic_number)
508 auto message = gmx::formatString("Invalid function type %d in push_at", nb_funct);
509 warning_error_and_exit(wi, message, FARGS);
511 for (int j = nfp0; (j < MAXFORCEPARAM); j++)
515 std::array<real, MAXFORCEPARAM> forceParam;
517 if (strlen(type) == 1 && isdigit(type[0]))
519 warning_error_and_exit(wi, "Atom type names can't be single digits.", FARGS);
522 if (strlen(btype) == 1 && isdigit(btype[0]))
524 warning_error_and_exit(wi, "Bond atom type names can't be single digits.", FARGS);
527 /* Hack to read old topologies */
528 if (gmx_strcasecmp(ptype, "D") == 0)
532 for (j = 0; (j < eptNR); j++)
534 if (gmx_strcasecmp(ptype, xl[j].entry) == 0)
541 auto message = gmx::formatString("Invalid particle type %s", ptype);
542 warning_error_and_exit(wi, message, FARGS);
549 for (int i = 0; i < MAXFORCEPARAM; i++)
551 forceParam[i] = c[i];
554 InteractionOfType interactionType({}, forceParam, "");
556 batype_nr = bondAtomType->addBondAtomType(symtab, btype);
558 if ((nr = at->atomTypeFromName(type)) != NOTSET)
560 auto message = gmx::formatString(
561 "Atomtype %s was defined previously (e.g. in the forcefield files), "
562 "and has now been defined again. This could happen e.g. if you would "
563 "use a self-contained molecule .itp file that duplicates or replaces "
564 "the contents of the standard force-field files. You should check "
565 "the contents of your files and remove such repetition. If you know "
566 "you should override the previous definition, then you could choose "
567 "to suppress this warning with -maxwarn.",
569 warning(wi, message);
570 if ((at->setType(nr, symtab, *atom, type, interactionType, batype_nr, atomnr)) == NOTSET)
572 auto message = gmx::formatString("Replacing atomtype %s failed", type);
573 warning_error_and_exit(wi, message, FARGS);
576 else if ((at->addType(symtab, *atom, type, interactionType, batype_nr, atomnr)) == NOTSET)
578 auto message = gmx::formatString("Adding atomtype %s failed", type);
579 warning_error_and_exit(wi, message, FARGS);
583 /* Add space in the non-bonded parameters matrix */
584 realloc_nb_params(at, nbparam, pair);
589 //! Return whether the contents of \c a and \c b are the same, considering also reversed order.
591 static bool equalEitherForwardOrBackward(gmx::ArrayRef<const T> a, gmx::ArrayRef<const T> b)
593 return (std::equal(a.begin(), a.end(), b.begin()) || std::equal(a.begin(), a.end(), b.rbegin()));
596 static void push_bondtype(InteractionsOfType* bt,
597 const InteractionOfType& b,
605 int nrfp = NRFP(ftype);
607 /* If bAllowRepeat is TRUE, we allow multiple entries as long as they
608 are on directly _adjacent_ lines.
611 /* First check if our atomtypes are _identical_ (not reversed) to the previous
612 entry. If they are not identical we search for earlier duplicates. If they are
613 we can skip it, since we already searched for the first line
617 bool isContinuationOfBlock = false;
618 if (bAllowRepeat && nr > 1)
620 isContinuationOfBlock = true;
621 gmx::ArrayRef<const int> newParAtom = b.atoms();
622 gmx::ArrayRef<const int> sysParAtom = bt->interactionTypes[nr - 2].atoms();
623 for (int j = 0; j < nral; j++)
625 if (newParAtom[j] != sysParAtom[j])
627 isContinuationOfBlock = false;
632 /* Search for earlier duplicates if this entry was not a continuation
633 from the previous line.
635 bool addBondType = true;
636 bool haveWarned = false;
637 bool haveErrored = false;
638 for (int i = 0; (i < nr); i++)
640 gmx::ArrayRef<const int> bParams = b.atoms();
641 gmx::ArrayRef<const int> testParams = bt->interactionTypes[i].atoms();
642 GMX_RELEASE_ASSERT(bParams.size() == testParams.size(),
643 "Number of atoms needs to be the same between parameters");
644 if (equalEitherForwardOrBackward(bParams, testParams))
646 GMX_ASSERT(nrfp <= MAXFORCEPARAM,
647 "This is ensured in other places, but we need this assert to keep the clang "
649 const bool identicalParameters = std::equal(bt->interactionTypes[i].forceParam().begin(),
650 bt->interactionTypes[i].forceParam().begin() + nrfp,
651 b.forceParam().begin());
653 if (!bAllowRepeat || identicalParameters)
658 if (!identicalParameters)
662 /* With dihedral type 9 we only allow for repeating
663 * of the same parameters with blocks with 1 entry.
664 * Allowing overriding is too complex to check.
666 if (!isContinuationOfBlock && !haveErrored)
669 "Encountered a second block of parameters for dihedral "
670 "type 9 for the same atoms, with either different parameters "
671 "and/or the first block has multiple lines. This is not "
676 else if (!haveWarned)
678 auto message = gmx::formatString(
679 "Bondtype %s was defined previously (e.g. in the forcefield files), "
680 "and has now been defined again. This could happen e.g. if you would "
681 "use a self-contained molecule .itp file that duplicates or replaces "
682 "the contents of the standard force-field files. You should check "
683 "the contents of your files and remove such repetition. If you know "
684 "you should override the previous definition, then you could choose "
685 "to suppress this warning with -maxwarn.%s",
686 interaction_function[ftype].longname,
687 (ftype == F_PDIHS) ? "\nUse dihedraltype 9 to allow several "
688 "multiplicity terms. Only consecutive "
689 "lines are combined. Non-consective lines "
690 "overwrite each other."
692 warning(wi, message);
694 fprintf(stderr, " old: ");
695 gmx::ArrayRef<const real> forceParam = bt->interactionTypes[i].forceParam();
696 for (int j = 0; j < nrfp; j++)
698 fprintf(stderr, " %g", forceParam[j]);
700 fprintf(stderr, " \n new: %s\n\n", line);
706 if (!identicalParameters && !bAllowRepeat)
708 /* Overwrite the parameters with the latest ones */
709 // TODO considering improving the following code by replacing with:
710 // std::copy(b->c, b->c + nrfp, bt->param[i].c);
711 gmx::ArrayRef<const real> forceParam = b.forceParam();
712 for (int j = 0; j < nrfp; j++)
714 bt->interactionTypes[i].setForceParameter(j, forceParam[j]);
722 /* fill the arrays up and down */
723 bt->interactionTypes.emplace_back(
724 InteractionOfType(b.atoms(), b.forceParam(), b.interactionTypeName()));
725 /* need to store force values because they might change below */
726 std::vector<real> forceParam(b.forceParam().begin(), b.forceParam().end());
728 /* The definitions of linear angles depend on the order of atoms,
729 * that means that for atoms i-j-k, with certain parameter a, the
730 * corresponding k-j-i angle will have parameter 1-a.
732 if (ftype == F_LINEAR_ANGLES)
734 forceParam[0] = 1 - forceParam[0];
735 forceParam[2] = 1 - forceParam[2];
737 std::vector<int> atoms;
738 gmx::ArrayRef<const int> oldAtoms = b.atoms();
739 for (auto oldAtom = oldAtoms.rbegin(); oldAtom != oldAtoms.rend(); oldAtom++)
741 atoms.emplace_back(*oldAtom);
743 bt->interactionTypes.emplace_back(InteractionOfType(atoms, forceParam, b.interactionTypeName()));
747 static std::vector<int> atomTypesFromAtomNames(const PreprocessingAtomTypes* atomTypes,
748 const PreprocessingBondAtomType* bondAtomTypes,
749 gmx::ArrayRef<const char[20]> atomNames,
753 GMX_RELEASE_ASSERT(!(!atomNames.empty() && !atomTypes && !bondAtomTypes),
754 "Need to have either valid atomtypes or bondatomtypes object");
756 std::vector<int> atomTypesFromAtomNames;
757 for (const auto& name : atomNames)
759 if (atomTypes != nullptr)
761 int atomType = atomTypes->atomTypeFromName(name);
762 if (atomType == NOTSET)
764 auto message = gmx::formatString("Unknown atomtype %s\n", name);
765 warning_error_and_exit(wi, message, FARGS);
767 atomTypesFromAtomNames.emplace_back(atomType);
769 else if (bondAtomTypes != nullptr)
771 int atomType = bondAtomTypes->bondAtomTypeFromName(name);
772 if (atomType == NOTSET)
774 auto message = gmx::formatString("Unknown bond_atomtype %s\n", name);
775 warning_error_and_exit(wi, message, FARGS);
777 atomTypesFromAtomNames.emplace_back(atomType);
780 return atomTypesFromAtomNames;
784 void push_bt(Directive d,
785 gmx::ArrayRef<InteractionsOfType> bt,
787 PreprocessingAtomTypes* at,
788 PreprocessingBondAtomType* bondAtomType,
792 const char* formal[MAXATOMLIST + 1] = {
793 "%s", "%s%s", "%s%s%s", "%s%s%s%s", "%s%s%s%s%s", "%s%s%s%s%s%s", "%s%s%s%s%s%s%s"
795 const char* formnl[MAXATOMLIST + 1] = { "%*s",
800 "%*s%*s%*s%*s%*s%*s",
801 "%*s%*s%*s%*s%*s%*s%*s" };
802 const char* formlf = "%lf%lf%lf%lf%lf%lf%lf%lf%lf%lf%lf%lf%lf";
803 int i, ft, ftype, nn, nrfp, nrfpA;
805 char alc[MAXATOMLIST + 1][20];
806 /* One force parameter more, so we can check if we read too many */
807 double c[MAXFORCEPARAM + 1];
809 if ((bondAtomType && at) || (!bondAtomType && !at))
811 gmx_incons("You should pass either bondAtomType or at to push_bt");
814 /* Make format string (nral ints+functype) */
815 if ((nn = sscanf(line, formal[nral], alc[0], alc[1], alc[2], alc[3], alc[4], alc[5])) != nral + 1)
817 auto message = gmx::formatString("Not enough atomtypes (%d instead of %d)", nn - 1, nral);
818 warning_error(wi, message);
822 ft = strtol(alc[nral], nullptr, 10);
823 ftype = ifunc_index(d, ft);
825 nrfpA = interaction_function[ftype].nrfpA;
826 strcpy(f1, formnl[nral]);
829 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]))
834 /* Copy the B-state from the A-state */
835 copy_B_from_A(ftype, c);
841 warning_error(wi, "Not enough parameters");
843 else if (nn > nrfpA && nn < nrfp)
845 warning_error(wi, "Too many parameters or not enough parameters for topology B");
849 warning_error(wi, "Too many parameters");
851 for (i = nn; (i < nrfp); i++)
857 std::vector<int> atomTypes =
858 atomTypesFromAtomNames(at, bondAtomType, gmx::arrayRefFromArray(alc, nral), wi);
859 std::array<real, MAXFORCEPARAM> forceParam;
860 for (int i = 0; (i < nrfp); i++)
862 forceParam[i] = c[i];
864 push_bondtype(&(bt[ftype]), InteractionOfType(atomTypes, forceParam), nral, ftype, FALSE, line, wi);
868 void push_dihedraltype(Directive d,
869 gmx::ArrayRef<InteractionsOfType> bt,
870 PreprocessingBondAtomType* bondAtomType,
874 const char* formal[MAXATOMLIST + 1] = {
875 "%s", "%s%s", "%s%s%s", "%s%s%s%s", "%s%s%s%s%s", "%s%s%s%s%s%s", "%s%s%s%s%s%s%s"
877 const char* formnl[MAXATOMLIST + 1] = { "%*s",
882 "%*s%*s%*s%*s%*s%*s",
883 "%*s%*s%*s%*s%*s%*s%*s" };
884 const char* formlf[MAXFORCEPARAM] = {
890 "%lf%lf%lf%lf%lf%lf",
891 "%lf%lf%lf%lf%lf%lf%lf",
892 "%lf%lf%lf%lf%lf%lf%lf%lf",
893 "%lf%lf%lf%lf%lf%lf%lf%lf%lf",
894 "%lf%lf%lf%lf%lf%lf%lf%lf%lf%lf",
895 "%lf%lf%lf%lf%lf%lf%lf%lf%lf%lf%lf",
896 "%lf%lf%lf%lf%lf%lf%lf%lf%lf%lf%lf%lf",
898 int i, ft, ftype, nn, nrfp, nrfpA, nral;
900 char alc[MAXATOMLIST + 1][20];
901 double c[MAXFORCEPARAM];
904 /* This routine accepts dihedraltypes defined from either 2 or 4 atoms.
906 * We first check for 2 atoms with the 3th column being an integer
907 * defining the type. If this isn't the case, we try it with 4 atoms
908 * and the 5th column defining the dihedral type.
910 nn = sscanf(line, formal[4], alc[0], alc[1], alc[2], alc[3], alc[4]);
911 if (nn >= 3 && strlen(alc[2]) == 1 && isdigit(alc[2][0]))
914 ft = strtol(alc[nral], nullptr, 10);
915 /* Move atom types around a bit and use 'X' for wildcard atoms
916 * to create a 4-atom dihedral definition with arbitrary atoms in
919 if (alc[2][0] == '2')
921 /* improper - the two atomtypes are 1,4. Use wildcards for 2,3 */
922 strcpy(alc[3], alc[1]);
923 sprintf(alc[2], "X");
924 sprintf(alc[1], "X");
925 /* alc[0] stays put */
929 /* proper - the two atomtypes are 2,3. Use wildcards for 1,4 */
930 sprintf(alc[3], "X");
931 strcpy(alc[2], alc[1]);
932 strcpy(alc[1], alc[0]);
933 sprintf(alc[0], "X");
936 else if (nn == 5 && strlen(alc[4]) == 1 && isdigit(alc[4][0]))
939 ft = strtol(alc[nral], nullptr, 10);
943 auto message = gmx::formatString(
944 "Incorrect number of atomtypes for dihedral (%d instead of 2 or 4)", nn - 1);
945 warning_error(wi, message);
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.
964 bAllowRepeat = FALSE;
968 ftype = ifunc_index(d, ft);
970 nrfpA = interaction_function[ftype].nrfpA;
972 strcpy(f1, formnl[nral]);
973 strcat(f1, formlf[nrfp - 1]);
975 /* Check number of parameters given */
977 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]))
982 /* Copy the B-state from the A-state */
983 copy_B_from_A(ftype, c);
989 warning_error(wi, "Not enough parameters");
991 else if (nn > nrfpA && nn < nrfp)
993 warning_error(wi, "Too many parameters or not enough parameters for topology B");
997 warning_error(wi, "Too many parameters");
999 for (i = nn; (i < nrfp); i++)
1006 std::vector<int> atoms;
1007 std::array<real, MAXFORCEPARAM> forceParam;
1008 for (int i = 0; (i < 4); i++)
1010 if (!strcmp(alc[i], "X"))
1012 atoms.emplace_back(-1);
1017 if ((atomNumber = bondAtomType->bondAtomTypeFromName(alc[i])) == NOTSET)
1019 auto message = gmx::formatString("Unknown bond_atomtype %s", alc[i]);
1020 warning_error_and_exit(wi, message, FARGS);
1022 atoms.emplace_back(atomNumber);
1025 for (int i = 0; (i < nrfp); i++)
1027 forceParam[i] = c[i];
1029 /* Always use 4 atoms here, since we created two wildcard atoms
1030 * if there wasn't of them 4 already.
1032 push_bondtype(&(bt[ftype]), InteractionOfType(atoms, forceParam), 4, ftype, bAllowRepeat, line, wi);
1036 void push_nbt(Directive d, t_nbparam** nbt, PreprocessingAtomTypes* atypes, char* pline, int nb_funct, warninp* wi)
1038 /* swap the atoms */
1039 const char* form3 = "%*s%*s%*s%lf%lf%lf";
1040 const char* form4 = "%*s%*s%*s%lf%lf%lf%lf";
1041 const char* form5 = "%*s%*s%*s%lf%lf%lf%lf%lf";
1042 char a0[80], a1[80];
1043 int i, f, n, ftype, nrfp;
1050 if (sscanf(pline, "%s%s%d", a0, a1, &f) != 3)
1056 ftype = ifunc_index(d, f);
1058 if (ftype != nb_funct)
1060 auto message = gmx::formatString("Trying to add %s while the default nonbond type is %s",
1061 interaction_function[ftype].longname,
1062 interaction_function[nb_funct].longname);
1063 warning_error(wi, message);
1067 /* Get the force parameters */
1069 if (ftype == F_LJ14)
1071 n = sscanf(pline, form4, &c[0], &c[1], &c[2], &c[3]);
1077 /* When the B topology parameters are not set,
1078 * copy them from topology A
1080 GMX_ASSERT(nrfp <= 4, "LJ-14 cannot have more than 4 parameters");
1081 for (i = n; i < nrfp; i++)
1086 else if (ftype == F_LJC14_Q)
1088 n = sscanf(pline, form5, &c[0], &c[1], &c[2], &c[3], &dum);
1091 incorrect_n_param(wi);
1097 if (sscanf(pline, form3, &c[0], &c[1], &dum) != 2)
1099 incorrect_n_param(wi);
1105 if (sscanf(pline, form4, &c[0], &c[1], &c[2], &dum) != 3)
1107 incorrect_n_param(wi);
1114 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++)
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)]);
1138 for (i = 0; i < nrfp; i++)
1140 bId = bId && (nbp->c[i] == cr[i]);
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);
1162 for (i = 0; i < nrfp; i++)
1168 void push_cmaptype(Directive d,
1169 gmx::ArrayRef<InteractionsOfType> bt,
1171 PreprocessingAtomTypes* atomtypes,
1172 PreprocessingBondAtomType* bondAtomType,
1176 const char* formal = "%s%s%s%s%s%s%s%s%n";
1178 int ft, ftype, nn, nrfp, nrfpA, nrfpB;
1179 int start, nchar_consumed;
1180 int nxcmap, nycmap, ncmap, read_cmap, sl, nct;
1181 char s[20], alc[MAXATOMLIST + 2][20];
1183 /* Keep the compiler happy */
1187 GMX_ASSERT(nral == 5, "CMAP requires 5 atoms per interaction");
1189 /* Here we can only check for < 8 */
1190 if ((nn = sscanf(line, formal, alc[0], alc[1], alc[2], alc[3], alc[4], alc[5], alc[6], alc[7], &nchar_consumed))
1194 gmx::formatString("Incorrect number of atomtypes for cmap (%d instead of 5)", nn - 1);
1195 warning_error(wi, message);
1198 start += nchar_consumed;
1200 ft = strtol(alc[nral], nullptr, 10);
1201 nxcmap = strtol(alc[nral + 1], nullptr, 10);
1202 nycmap = strtol(alc[nral + 2], nullptr, 10);
1204 /* Check for equal grid spacing in x and y dims */
1205 if (nxcmap != nycmap)
1207 auto message = gmx::formatString(
1208 "Not the same grid spacing in x and y for cmap grid: x=%d, y=%d", nxcmap, nycmap);
1209 warning_error(wi, message);
1212 ncmap = nxcmap * nycmap;
1213 ftype = ifunc_index(d, ft);
1214 nrfpA = strtol(alc[6], nullptr, 10) * strtol(alc[6], nullptr, 10);
1215 nrfpB = strtol(alc[7], nullptr, 10) * strtol(alc[7], nullptr, 10);
1216 nrfp = nrfpA + nrfpB;
1218 /* Read in CMAP parameters */
1220 for (int i = 0; i < ncmap; i++)
1222 while (isspace(*(line + start + sl)))
1226 nn = sscanf(line + start + sl, " %s ", s);
1228 bt[F_CMAP].cmap.emplace_back(strtod(s, nullptr));
1237 gmx::formatString("Error in reading cmap parameter for angle %s %s %s %s %s",
1243 warning_error(wi, message);
1247 /* Check do that we got the number of parameters we expected */
1248 if (read_cmap == nrfpA)
1250 for (int i = 0; i < ncmap; i++)
1252 bt[F_CMAP].cmap.emplace_back(bt[F_CMAP].cmap[i]);
1257 if (read_cmap < nrfpA)
1259 warning_error(wi, "Not enough cmap parameters");
1261 else if (read_cmap > nrfpA && read_cmap < nrfp)
1263 warning_error(wi, "Too many cmap parameters or not enough parameters for topology B");
1265 else if (read_cmap > nrfp)
1267 warning_error(wi, "Too many cmap parameters");
1272 /* Set grid spacing and the number of grids (we assume these numbers to be the same for all
1273 * grids so we can safely assign them each time
1275 bt[F_CMAP].cmakeGridSpacing = nxcmap; /* Or nycmap, they need to be equal */
1276 bt[F_CMAP].cmapAngles++; /* Since we are incrementing here, we need to subtract later, see (*****) */
1277 nct = (nral + 1) * bt[F_CMAP].cmapAngles;
1279 for (int i = 0; (i < nral); i++)
1281 /* Assign a grid number to each cmap_type */
1282 GMX_RELEASE_ASSERT(bondAtomType != nullptr, "Need valid PreprocessingBondAtomType object");
1283 bt[F_CMAP].cmapAtomTypes.emplace_back(bondAtomType->bondAtomTypeFromName(alc[i]));
1286 /* Assign a type number to this cmap */
1287 bt[F_CMAP].cmapAtomTypes.emplace_back(
1288 bt[F_CMAP].cmapAngles
1289 - 1); /* Since we inremented earlier, we need to subtrac here, to get the types right (****) */
1291 /* Check for the correct number of atoms (again) */
1292 if (bt[F_CMAP].nct() != nct)
1294 auto message = gmx::formatString(
1295 "Incorrect number of atom types (%d) in cmap type %d\n", nct, bt[F_CMAP].cmapAngles);
1296 warning_error(wi, message);
1298 std::vector<int> atomTypes =
1299 atomTypesFromAtomNames(atomtypes, bondAtomType, gmx::constArrayRefFromArray(alc, nral), wi);
1300 std::array<real, MAXFORCEPARAM> forceParam = { NOTSET };
1302 /* Push the bond to the bondlist */
1303 push_bondtype(&(bt[ftype]), InteractionOfType(atomTypes, forceParam), nral, ftype, FALSE, line, wi);
1307 static void push_atom_now(t_symtab* symtab,
1325 int j, resind = 0, resnr;
1329 if (((nr == 0) && (atomnr != 1)) || (nr && (atomnr != at->nr + 1)))
1331 auto message = gmx::formatString(
1332 "Atoms in the .top are not numbered consecutively from 1 (rather, "
1333 "atomnr = %d, while at->nr = %d)",
1336 warning_error_and_exit(wi, message, FARGS);
1339 j = strlen(resnumberic) - 1;
1340 if (isdigit(resnumberic[j]))
1346 ric = resnumberic[j];
1347 if (j == 0 || !isdigit(resnumberic[j - 1]))
1350 gmx::formatString("Invalid residue number '%s' for atom %d", resnumberic, atomnr);
1351 warning_error_and_exit(wi, message, FARGS);
1354 resnr = strtol(resnumberic, nullptr, 10);
1358 resind = at->atom[nr - 1].resind;
1360 if (nr == 0 || strcmp(resname, *at->resinfo[resind].name) != 0
1361 || resnr != at->resinfo[resind].nr || ric != at->resinfo[resind].ic)
1371 at->nres = resind + 1;
1372 srenew(at->resinfo, at->nres);
1373 at->resinfo[resind].name = put_symtab(symtab, resname);
1374 at->resinfo[resind].nr = resnr;
1375 at->resinfo[resind].ic = ric;
1379 resind = at->atom[at->nr - 1].resind;
1382 /* New atom instance
1383 * get new space for arrays
1385 srenew(at->atom, nr + 1);
1386 srenew(at->atomname, nr + 1);
1387 srenew(at->atomtype, nr + 1);
1388 srenew(at->atomtypeB, nr + 1);
1391 at->atom[nr].type = type;
1392 at->atom[nr].ptype = ptype;
1393 at->atom[nr].q = q0;
1394 at->atom[nr].m = m0;
1395 at->atom[nr].typeB = typeB;
1396 at->atom[nr].qB = qB;
1397 at->atom[nr].mB = mB;
1399 at->atom[nr].resind = resind;
1400 at->atom[nr].atomnumber = atomicnumber;
1401 at->atomname[nr] = put_symtab(symtab, name);
1402 at->atomtype[nr] = put_symtab(symtab, ctype);
1403 at->atomtypeB[nr] = put_symtab(symtab, ctypeB);
1407 void push_atom(t_symtab* symtab, t_atoms* at, PreprocessingAtomTypes* atypes, char* line, warninp* wi)
1410 int cgnumber, atomnr, type, typeB, nscan;
1411 char id[STRLEN], ctype[STRLEN], ctypeB[STRLEN], resnumberic[STRLEN], resname[STRLEN],
1412 name[STRLEN], check[STRLEN];
1413 double m, q, mb, qb;
1414 real m0, q0, mB, qB;
1416 /* Fixed parameters */
1417 if (sscanf(line, "%s%s%s%s%s%d", id, ctype, resnumberic, resname, name, &cgnumber) != 6)
1422 sscanf(id, "%d", &atomnr);
1423 if ((type = atypes->atomTypeFromName(ctype)) == NOTSET)
1425 auto message = gmx::formatString("Atomtype %s not found", ctype);
1426 warning_error_and_exit(wi, message, FARGS);
1428 ptype = atypes->atomParticleTypeFromAtomType(type);
1430 /* Set default from type */
1431 q0 = atypes->atomChargeFromAtomType(type);
1432 m0 = atypes->atomMassFromAtomType(type);
1437 /* Optional parameters */
1438 nscan = sscanf(line, "%*s%*s%*s%*s%*s%*s%lf%lf%s%lf%lf%s", &q, &m, ctypeB, &qb, &mb, check);
1440 /* Nasty switch that falls thru all the way down! */
1449 if ((typeB = atypes->atomTypeFromName(ctypeB)) == NOTSET)
1451 auto message = gmx::formatString("Atomtype %s not found", ctypeB);
1452 warning_error_and_exit(wi, message, FARGS);
1454 qB = atypes->atomChargeFromAtomType(typeB);
1455 mB = atypes->atomMassFromAtomType(typeB);
1464 warning_error(wi, "Too many parameters");
1472 push_atom_now(symtab,
1475 atypes->atomNumberFromAtomType(type),
1485 typeB == type ? ctype : ctypeB,
1491 void push_molt(t_symtab* symtab, std::vector<MoleculeInformation>* mol, char* line, warninp* wi)
1496 if ((sscanf(line, "%s%d", type, &nrexcl)) != 2)
1498 warning_error(wi, "Expected a molecule type name and nrexcl");
1501 /* Test if this moleculetype overwrites another */
1502 const auto found = std::find_if(
1503 mol->begin(), mol->end(), [&type](const auto& m) { return strcmp(*(m.name), type) == 0; });
1504 if (found != mol->end())
1506 auto message = gmx::formatString("moleculetype %s is redefined", type);
1507 warning_error_and_exit(wi, message, FARGS);
1510 mol->emplace_back();
1511 mol->back().initMolInfo();
1513 /* Fill in the values */
1514 mol->back().name = put_symtab(symtab, type);
1515 mol->back().nrexcl = nrexcl;
1516 mol->back().excl_set = false;
1519 static bool findIfAllNBAtomsMatch(gmx::ArrayRef<const int> atomsFromParameterArray,
1520 gmx::ArrayRef<const int> atomsFromCurrentParameter,
1524 if (atomsFromParameterArray.size() != atomsFromCurrentParameter.size())
1530 for (gmx::index i = 0; i < atomsFromCurrentParameter.ssize(); i++)
1532 if (at->atom[atomsFromCurrentParameter[i]].typeB != atomsFromParameterArray[i])
1541 for (gmx::index i = 0; i < atomsFromCurrentParameter.ssize(); i++)
1543 if (at->atom[atomsFromCurrentParameter[i]].type != atomsFromParameterArray[i])
1552 static bool default_nb_params(int ftype,
1553 gmx::ArrayRef<InteractionsOfType> bt,
1555 InteractionOfType* p,
1562 InteractionOfType* pi = nullptr;
1563 int nr = bt[ftype].size();
1564 int nral = NRAL(ftype);
1565 int nrfp = interaction_function[ftype].nrfpA;
1566 int nrfpB = interaction_function[ftype].nrfpB;
1568 if ((!bB && nrfp == 0) || (bB && nrfpB == 0))
1576 /* First test the generated-pair position to save
1577 * time when we have 1000*1000 entries for e.g. OPLS...
1579 ntype = static_cast<int>(std::sqrt(static_cast<double>(nr)));
1580 GMX_ASSERT(ntype * ntype == nr,
1581 "Number of pairs of generated non-bonded parameters should be a perfect square");
1584 ti = at->atom[p->ai()].typeB;
1585 tj = at->atom[p->aj()].typeB;
1589 ti = at->atom[p->ai()].type;
1590 tj = at->atom[p->aj()].type;
1592 pi = &(bt[ftype].interactionTypes[ntype * ti + tj]);
1593 if (pi->atoms().ssize() < nral)
1595 /* not initialized yet with atom names */
1600 bFound = ((ti == pi->ai()) && (tj == pi->aj()));
1604 gmx::ArrayRef<const int> paramAtoms = p->atoms();
1605 /* Search explicitly if we didnt find it */
1608 auto foundParameter =
1609 std::find_if(bt[ftype].interactionTypes.begin(),
1610 bt[ftype].interactionTypes.end(),
1611 [¶mAtoms, &at, &bB](const auto& param) {
1612 return findIfAllNBAtomsMatch(param.atoms(), paramAtoms, at, bB);
1614 if (foundParameter != bt[ftype].interactionTypes.end())
1617 pi = &(*foundParameter);
1623 gmx::ArrayRef<const real> forceParam = pi->forceParam();
1626 if (nrfp + nrfpB > MAXFORCEPARAM)
1628 gmx_incons("Too many force parameters");
1630 for (int j = c_start; j < nrfpB; j++)
1632 p->setForceParameter(nrfp + j, forceParam[j]);
1637 for (int j = c_start; j < nrfp; j++)
1639 p->setForceParameter(j, forceParam[j]);
1645 for (int j = c_start; j < nrfp; j++)
1647 p->setForceParameter(j, 0.0);
1653 static bool default_cmap_params(gmx::ArrayRef<InteractionsOfType> bondtype,
1655 PreprocessingAtomTypes* atypes,
1656 InteractionOfType* p,
1664 bool bFound = false;
1669 /* Match the current cmap angle against the list of cmap_types */
1670 for (int i = 0; i < bondtype[F_CMAP].nct() && !bFound; i += 6)
1675 if ((atypes->bondAtomTypeFromAtomType(at->atom[p->ai()].type)
1676 == bondtype[F_CMAP].cmapAtomTypes[i])
1677 && (atypes->bondAtomTypeFromAtomType(at->atom[p->aj()].type)
1678 == bondtype[F_CMAP].cmapAtomTypes[i + 1])
1679 && (atypes->bondAtomTypeFromAtomType(at->atom[p->ak()].type)
1680 == bondtype[F_CMAP].cmapAtomTypes[i + 2])
1681 && (atypes->bondAtomTypeFromAtomType(at->atom[p->al()].type)
1682 == bondtype[F_CMAP].cmapAtomTypes[i + 3])
1683 && (atypes->bondAtomTypeFromAtomType(at->atom[p->am()].type)
1684 == bondtype[F_CMAP].cmapAtomTypes[i + 4]))
1686 /* Found cmap torsion */
1688 ct = bondtype[F_CMAP].cmapAtomTypes[i + 5];
1694 /* If we did not find a matching type for this cmap torsion */
1697 auto message = gmx::formatString("Unknown cmap torsion between atoms %d %d %d %d %d",
1703 warning_error_and_exit(wi, message, FARGS);
1706 *nparam_def = nparam_found;
1712 /* Returns the number of exact atom type matches, i.e. non wild-card matches,
1713 * returns -1 when there are no matches at all.
1715 static int natom_match(const InteractionOfType& pi,
1720 const PreprocessingAtomTypes* atypes)
1722 if ((pi.ai() == -1 || atypes->bondAtomTypeFromAtomType(type_i) == pi.ai())
1723 && (pi.aj() == -1 || atypes->bondAtomTypeFromAtomType(type_j) == pi.aj())
1724 && (pi.ak() == -1 || atypes->bondAtomTypeFromAtomType(type_k) == pi.ak())
1725 && (pi.al() == -1 || atypes->bondAtomTypeFromAtomType(type_l) == pi.al()))
1727 return (pi.ai() == -1 ? 0 : 1) + (pi.aj() == -1 ? 0 : 1) + (pi.ak() == -1 ? 0 : 1)
1728 + (pi.al() == -1 ? 0 : 1);
1736 static int findNumberOfDihedralAtomMatches(const InteractionOfType& currentParamFromParameterArray,
1737 const InteractionOfType& parameterToAdd,
1739 const PreprocessingAtomTypes* atypes,
1744 return natom_match(currentParamFromParameterArray,
1745 at->atom[parameterToAdd.ai()].typeB,
1746 at->atom[parameterToAdd.aj()].typeB,
1747 at->atom[parameterToAdd.ak()].typeB,
1748 at->atom[parameterToAdd.al()].typeB,
1753 return natom_match(currentParamFromParameterArray,
1754 at->atom[parameterToAdd.ai()].type,
1755 at->atom[parameterToAdd.aj()].type,
1756 at->atom[parameterToAdd.ak()].type,
1757 at->atom[parameterToAdd.al()].type,
1762 static bool findIfAllParameterAtomsMatch(gmx::ArrayRef<const int> atomsFromParameterArray,
1763 gmx::ArrayRef<const int> atomsFromCurrentParameter,
1765 const PreprocessingAtomTypes* atypes,
1768 if (atomsFromParameterArray.size() != atomsFromCurrentParameter.size())
1774 for (gmx::index i = 0; i < atomsFromCurrentParameter.ssize(); i++)
1776 if (atypes->bondAtomTypeFromAtomType(at->atom[atomsFromCurrentParameter[i]].typeB)
1777 != atomsFromParameterArray[i])
1786 for (gmx::index i = 0; i < atomsFromCurrentParameter.ssize(); i++)
1788 if (atypes->bondAtomTypeFromAtomType(at->atom[atomsFromCurrentParameter[i]].type)
1789 != atomsFromParameterArray[i])
1798 static std::vector<InteractionOfType>::iterator defaultInteractionsOfType(int ftype,
1799 gmx::ArrayRef<InteractionsOfType> bt,
1801 PreprocessingAtomTypes* atypes,
1802 const InteractionOfType& p,
1807 int nrfpA = interaction_function[ftype].nrfpA;
1808 int nrfpB = interaction_function[ftype].nrfpB;
1810 if ((!bB && nrfpA == 0) || (bB && nrfpB == 0))
1812 return bt[ftype].interactionTypes.end();
1817 if (ftype == F_PDIHS || ftype == F_RBDIHS || ftype == F_IDIHS || ftype == F_PIDIHS)
1819 int nmatch_max = -1;
1821 /* For dihedrals we allow wildcards. We choose the first type
1822 * that has the most real matches, i.e. non-wildcard matches.
1824 auto prevPos = bt[ftype].interactionTypes.end();
1825 auto pos = bt[ftype].interactionTypes.begin();
1826 while (pos != bt[ftype].interactionTypes.end() && nmatch_max < 4)
1828 pos = std::find_if(bt[ftype].interactionTypes.begin(),
1829 bt[ftype].interactionTypes.end(),
1830 [&p, &at, &atypes, &bB, &nmatch_max](const auto& param) {
1831 return (findNumberOfDihedralAtomMatches(param, p, at, atypes, bB)
1834 if (pos != bt[ftype].interactionTypes.end())
1837 nmatch_max = findNumberOfDihedralAtomMatches(*pos, p, at, atypes, bB);
1841 if (prevPos != bt[ftype].interactionTypes.end())
1845 /* Find additional matches for this dihedral - necessary
1847 * The rule in that case is that additional matches
1848 * HAVE to be on adjacent lines!
1851 // Advance iterator (like std::advance) without incrementing past end (UB)
1852 const auto safeAdvance = [](auto& it, auto n, auto end) {
1853 it = end - it > n ? it + n : end;
1855 /* Continue from current iterator position */
1856 auto nextPos = prevPos;
1857 const auto endIter = bt[ftype].interactionTypes.end();
1858 safeAdvance(nextPos, 2, endIter);
1859 for (; nextPos < endIter && bSame; safeAdvance(nextPos, 2, endIter))
1861 bSame = (prevPos->ai() == nextPos->ai() && prevPos->aj() == nextPos->aj()
1862 && prevPos->ak() == nextPos->ak() && prevPos->al() == nextPos->al());
1867 /* nparam_found will be increased as long as the numbers match */
1870 *nparam_def = nparam_found;
1873 else /* Not a dihedral */
1875 gmx::ArrayRef<const int> atomParam = p.atoms();
1876 auto found = std::find_if(bt[ftype].interactionTypes.begin(),
1877 bt[ftype].interactionTypes.end(),
1878 [&atomParam, &at, &atypes, &bB](const auto& param) {
1879 return findIfAllParameterAtomsMatch(
1880 param.atoms(), atomParam, at, atypes, bB);
1882 if (found != bt[ftype].interactionTypes.end())
1886 *nparam_def = nparam_found;
1892 void push_bond(Directive d,
1893 gmx::ArrayRef<InteractionsOfType> bondtype,
1894 gmx::ArrayRef<InteractionsOfType> bond,
1896 PreprocessingAtomTypes* atypes,
1902 bool* bWarn_copy_A_B,
1905 const char* aaformat[MAXATOMLIST] = { "%d%d", "%d%d%d", "%d%d%d%d",
1906 "%d%d%d%d%d", "%d%d%d%d%d%d", "%d%d%d%d%d%d%d" };
1907 const char* asformat[MAXATOMLIST] = {
1908 "%*s%*s", "%*s%*s%*s", "%*s%*s%*s%*s",
1909 "%*s%*s%*s%*s%*s", "%*s%*s%*s%*s%*s%*s", "%*s%*s%*s%*s%*s%*s%*s"
1911 const char* ccformat = "%lf%lf%lf%lf%lf%lf%lf%lf%lf%lf%lf%lf%lf";
1912 int nral, nral_fmt, nread, ftype;
1913 char format[STRLEN];
1914 /* One force parameter more, so we can check if we read too many */
1915 double cc[MAXFORCEPARAM + 1];
1916 int aa[MAXATOMLIST + 1];
1917 bool bFoundA = FALSE, bFoundB = FALSE, bDef, bSwapParity = FALSE;
1918 int nparam_defA, nparam_defB;
1920 nparam_defA = nparam_defB = 0;
1922 ftype = ifunc_index(d, 1);
1924 for (int j = 0; j < nral; j++)
1928 bDef = (NRFP(ftype) > 0);
1930 if (ftype == F_SETTLE)
1932 /* SETTLE acts on 3 atoms, but the topology format only specifies
1933 * the first atom (for historical reasons).
1942 nread = sscanf(line, aaformat[nral_fmt - 1], &aa[0], &aa[1], &aa[2], &aa[3], &aa[4], &aa[5]);
1944 if (ftype == F_SETTLE)
1951 if (nread < nral_fmt)
1956 else if (nread > nral_fmt)
1958 /* this is a hack to allow for virtual sites with swapped parity */
1959 bSwapParity = (aa[nral] < 0);
1962 aa[nral] = -aa[nral];
1964 ftype = ifunc_index(d, aa[nral]);
1970 case F_VSITE3OUT: break;
1973 gmx::formatString("Negative function types only allowed for %s and %s",
1974 interaction_function[F_VSITE3FAD].longname,
1975 interaction_function[F_VSITE3OUT].longname);
1976 warning_error_and_exit(wi, message, FARGS);
1982 /* Check for double atoms and atoms out of bounds */
1983 for (int i = 0; (i < nral); i++)
1985 if (aa[i] < 1 || aa[i] > at->nr)
1987 auto message = gmx::formatString(
1988 "Atom index (%d) in %s out of bounds (1-%d).\n"
1989 "This probably means that you have inserted topology section \"%s\"\n"
1990 "in a part belonging to a different molecule than you intended to.\n"
1991 "In that case move the \"%s\" section to the right molecule.",
1997 warning_error_and_exit(wi, message, FARGS);
1999 for (int j = i + 1; (j < nral); j++)
2001 GMX_ASSERT(j < MAXATOMLIST + 1,
2002 "Values from nral=NRAL() will satisfy this, we assert to keep gcc 4 happy");
2005 auto message = gmx::formatString("Duplicate atom index (%d) in %s", aa[i], dir2str(d));
2006 if (ftype == F_ANGRES)
2008 /* Since the angle restraints uses 2 pairs of atoms to
2009 * defines an angle between vectors, it can be useful
2010 * to use one atom twice, so we only issue a note here.
2012 warning_note(wi, message);
2016 warning_error(wi, message);
2022 /* default force parameters */
2023 std::vector<int> atoms;
2024 for (int j = 0; (j < nral); j++)
2026 atoms.emplace_back(aa[j] - 1);
2028 /* need to have an empty but initialized param array for some reason */
2029 std::array<real, MAXFORCEPARAM> forceParam = { 0.0 };
2031 /* Get force params for normal and free energy perturbation
2032 * studies, as determined by types!
2034 InteractionOfType param(atoms, forceParam, "");
2036 std::vector<InteractionOfType>::iterator foundAParameter = bondtype[ftype].interactionTypes.end();
2037 std::vector<InteractionOfType>::iterator foundBParameter = bondtype[ftype].interactionTypes.end();
2041 defaultInteractionsOfType(ftype, bondtype, at, atypes, param, FALSE, &nparam_defA);
2042 if (foundAParameter != bondtype[ftype].interactionTypes.end())
2044 /* Copy the A-state and B-state default parameters. */
2045 GMX_ASSERT(NRFPA(ftype) + NRFPB(ftype) <= MAXFORCEPARAM,
2046 "Bonded interactions may have at most 12 parameters");
2047 gmx::ArrayRef<const real> defaultParam = foundAParameter->forceParam();
2048 for (int j = 0; (j < NRFPA(ftype) + NRFPB(ftype)); j++)
2050 param.setForceParameter(j, defaultParam[j]);
2054 else if (NRFPA(ftype) == 0)
2059 defaultInteractionsOfType(ftype, bondtype, at, atypes, param, TRUE, &nparam_defB);
2060 if (foundBParameter != bondtype[ftype].interactionTypes.end())
2062 /* Copy only the B-state default parameters */
2063 gmx::ArrayRef<const real> defaultParam = foundBParameter->forceParam();
2064 for (int j = NRFPA(ftype); (j < NRFP(ftype)); j++)
2066 param.setForceParameter(j, defaultParam[j]);
2070 else if (NRFPB(ftype) == 0)
2075 else if (ftype == F_LJ14)
2077 bFoundA = default_nb_params(ftype, bondtype, at, ¶m, 0, FALSE, bGenPairs);
2078 bFoundB = default_nb_params(ftype, bondtype, at, ¶m, 0, TRUE, bGenPairs);
2080 else if (ftype == F_LJC14_Q)
2082 /* Fill in the A-state charges as default parameters */
2083 param.setForceParameter(0, fudgeQQ);
2084 param.setForceParameter(1, at->atom[param.ai()].q);
2085 param.setForceParameter(2, at->atom[param.aj()].q);
2086 /* The default LJ parameters are the standard 1-4 parameters */
2087 bFoundA = default_nb_params(F_LJ14, bondtype, at, ¶m, 3, FALSE, bGenPairs);
2090 else if (ftype == F_LJC_PAIRS_NB)
2092 /* Defaults are not supported here */
2098 gmx_incons("Unknown function type in push_bond");
2101 if (nread > nral_fmt)
2103 /* Manually specified parameters - in this case we discard multiple torsion info! */
2105 strcpy(format, asformat[nral_fmt - 1]);
2106 strcat(format, ccformat);
2108 nread = sscanf(line,
2124 if ((nread == NRFPA(ftype)) && (NRFPB(ftype) != 0))
2126 /* We only have to issue a warning if these atoms are perturbed! */
2128 gmx::ArrayRef<const int> paramAtoms = param.atoms();
2129 for (int j = 0; (j < nral); j++)
2131 bPert = bPert || PERTURBED(at->atom[paramAtoms[j]]);
2134 if (bPert && *bWarn_copy_A_B)
2136 auto message = gmx::formatString(
2137 "Some parameters for bonded interaction involving "
2138 "perturbed atoms are specified explicitly in "
2139 "state A, but not B - copying A to B");
2140 warning(wi, message);
2141 *bWarn_copy_A_B = FALSE;
2144 /* If only the A parameters were specified, copy them to the B state */
2145 /* The B-state parameters correspond to the first nrfpB
2146 * A-state parameters.
2148 for (int j = 0; (j < NRFPB(ftype)); j++)
2150 cc[nread++] = cc[j];
2154 /* If nread was 0 or EOF, no parameters were read => use defaults.
2155 * If nread was nrfpA we copied above so nread=nrfp.
2156 * If nread was nrfp we are cool.
2157 * For F_LJC14_Q we allow supplying fudgeQQ only.
2158 * Anything else is an error!
2160 if ((nread != 0) && (nread != EOF) && (nread != NRFP(ftype)) && !(ftype == F_LJC14_Q && nread == 1))
2162 auto message = gmx::formatString(
2163 "Incorrect number of parameters - found %d, expected %d "
2164 "or %d for %s (after the function type).",
2168 interaction_function[ftype].longname);
2169 warning_error_and_exit(wi, message, FARGS);
2172 for (int j = 0; (j < nread); j++)
2174 param.setForceParameter(j, cc[j]);
2176 /* Check whether we have to use the defaults */
2177 if (nread == NRFP(ftype))
2186 /* nread now holds the number of force parameters read! */
2191 /* When we have multiple terms it would be very dangerous to allow perturbations to a different atom type! */
2192 if (ftype == F_PDIHS)
2194 if ((nparam_defA != nparam_defB)
2195 || ((nparam_defA > 1 || nparam_defB > 1) && (foundAParameter != foundBParameter)))
2197 auto message = gmx::formatString(
2198 "Cannot automatically perturb a torsion with multiple terms to different "
2200 "Please specify perturbed parameters manually for this torsion in your "
2202 warning_error(wi, message);
2206 if (nread > 0 && nread < NRFPA(ftype))
2208 /* Issue an error, do not use defaults */
2209 auto message = gmx::formatString(
2210 "Not enough parameters, there should be at least %d (or 0 for defaults)", NRFPA(ftype));
2211 warning_error(wi, message);
2214 if (nread == 0 || nread == EOF)
2218 if (interaction_function[ftype].flags & IF_VSITE)
2220 for (int j = 0; j < MAXFORCEPARAM; j++)
2222 param.setForceParameter(j, NOTSET);
2226 /* flag to swap parity of vsi te construction */
2227 param.setForceParameter(1, -1);
2235 "NOTE: No default %s types, using zeroes\n",
2236 interaction_function[ftype].longname);
2240 auto message = gmx::formatString("No default %s types",
2241 interaction_function[ftype].longname);
2242 warning_error(wi, message);
2252 case F_VSITE3FAD: param.setForceParameter(0, 360 - param.c0()); break;
2253 case F_VSITE3OUT: param.setForceParameter(2, -param.c2()); break;
2259 /* We only have to issue a warning if these atoms are perturbed! */
2261 gmx::ArrayRef<const int> paramAtoms = param.atoms();
2262 for (int j = 0; (j < nral); j++)
2264 bPert = bPert || PERTURBED(at->atom[paramAtoms[j]]);
2269 auto message = gmx::formatString(
2270 "No default %s types for perturbed atoms, "
2271 "using normal values",
2272 interaction_function[ftype].longname);
2273 warning(wi, message);
2279 gmx::ArrayRef<const real> paramValue = param.forceParam();
2280 if ((ftype == F_PDIHS || ftype == F_ANGRES || ftype == F_ANGRESZ) && paramValue[5] != paramValue[2])
2282 auto message = gmx::formatString("%s multiplicity can not be perturbed %f!=%f",
2283 interaction_function[ftype].longname,
2286 warning_error_and_exit(wi, message, FARGS);
2289 if (IS_TABULATED(ftype) && param.c0() != param.c2())
2291 auto message = gmx::formatString("%s table number can not be perturbed %d!=%d",
2292 interaction_function[ftype].longname,
2293 gmx::roundToInt(param.c0()),
2294 gmx::roundToInt(param.c0()));
2295 warning_error_and_exit(wi, message, FARGS);
2298 /* Dont add R-B dihedrals where all parameters are zero (no interaction) */
2299 if (ftype == F_RBDIHS)
2303 for (int i = 0; i < NRFP(ftype); i++)
2305 if (paramValue[i] != 0.0)
2316 /* Put the values in the appropriate arrays */
2317 add_param_to_list(&bond[ftype], param);
2319 /* Push additional torsions from FF for ftype==9 if we have them.
2320 * We have already checked that the A/B states do not differ in this case,
2321 * so we do not have to double-check that again, or the vsite stuff.
2322 * In addition, those torsions cannot be automatically perturbed.
2324 if (bDef && ftype == F_PDIHS)
2326 for (int i = 1; i < nparam_defA; i++)
2328 /* Advance pointer! */
2329 foundAParameter += 2;
2330 gmx::ArrayRef<const real> forceParam = foundAParameter->forceParam();
2331 for (int j = 0; j < (NRFPA(ftype) + NRFPB(ftype)); j++)
2333 param.setForceParameter(j, forceParam[j]);
2335 /* And push the next term for this torsion */
2336 add_param_to_list(&bond[ftype], param);
2341 void push_cmap(Directive d,
2342 gmx::ArrayRef<InteractionsOfType> bondtype,
2343 gmx::ArrayRef<InteractionsOfType> bond,
2345 PreprocessingAtomTypes* atypes,
2349 const char* aaformat[MAXATOMLIST + 1] = {
2350 "%d", "%d%d", "%d%d%d", "%d%d%d%d", "%d%d%d%d%d", "%d%d%d%d%d%d", "%d%d%d%d%d%d%d"
2353 int ftype, nral, nread, ncmap_params;
2355 int aa[MAXATOMLIST + 1];
2358 ftype = ifunc_index(d, 1);
2362 nread = sscanf(line, aaformat[nral - 1], &aa[0], &aa[1], &aa[2], &aa[3], &aa[4], &aa[5]);
2369 else if (nread == nral)
2371 ftype = ifunc_index(d, 1);
2374 /* Check for double atoms and atoms out of bounds */
2375 for (int i = 0; i < nral; i++)
2377 if (aa[i] < 1 || aa[i] > at->nr)
2379 auto message = gmx::formatString(
2380 "Atom index (%d) in %s out of bounds (1-%d).\n"
2381 "This probably means that you have inserted topology section \"%s\"\n"
2382 "in a part belonging to a different molecule than you intended to.\n"
2383 "In that case move the \"%s\" section to the right molecule.",
2389 warning_error_and_exit(wi, message, FARGS);
2392 for (int j = i + 1; (j < nral); j++)
2396 auto message = gmx::formatString("Duplicate atom index (%d) in %s", aa[i], dir2str(d));
2397 warning_error(wi, message);
2402 /* default force parameters */
2403 std::vector<int> atoms;
2404 for (int j = 0; (j < nral); j++)
2406 atoms.emplace_back(aa[j] - 1);
2408 std::array<real, MAXFORCEPARAM> forceParam = { 0.0 };
2409 InteractionOfType param(atoms, forceParam, "");
2410 /* Get the cmap type for this cmap angle */
2411 bFound = default_cmap_params(bondtype, at, atypes, ¶m, FALSE, &cmap_type, &ncmap_params, wi);
2413 /* We want exactly one parameter (the cmap type in state A (currently no state B) back */
2414 if (bFound && ncmap_params == 1)
2416 /* Put the values in the appropriate arrays */
2417 param.setForceParameter(0, cmap_type);
2418 add_param_to_list(&bond[ftype], param);
2422 /* This is essentially the same check as in default_cmap_params() done one more time */
2424 gmx::formatString("Unable to assign a cmap type to torsion %d %d %d %d and %d\n",
2430 warning_error_and_exit(wi, message, FARGS);
2435 void push_vsitesn(Directive d, gmx::ArrayRef<InteractionsOfType> bond, t_atoms* at, char* line, warninp* wi)
2438 int type, ftype, n, ret, nj, a;
2440 double *weight = nullptr, weight_tot;
2442 std::array<real, MAXFORCEPARAM> forceParam = { 0.0 };
2444 ret = sscanf(ptr, "%d%n", &a, &n);
2448 auto message = gmx::formatString("Expected an atom index in section \"%s\"", dir2str(d));
2449 warning_error_and_exit(wi, message, FARGS);
2452 sscanf(ptr, "%d%n", &type, &n);
2454 ftype = ifunc_index(d, type);
2455 int firstAtom = a - 1;
2461 ret = sscanf(ptr, "%d%n", &a, &n);
2467 srenew(atc, nj + 20);
2468 srenew(weight, nj + 20);
2473 case 1: weight[nj] = 1; break;
2475 /* Here we use the A-state mass as a parameter.
2476 * Note that the B-state mass has no influence.
2478 weight[nj] = at->atom[atc[nj]].m;
2482 ret = sscanf(ptr, "%lf%n", &(weight[nj]), &n);
2486 auto message = gmx::formatString(
2487 "No weight or negative weight found for vsiten "
2488 "constructing atom %d (atom index %d)",
2491 warning_error_and_exit(wi, message, FARGS);
2495 auto message = gmx::formatString("Unknown vsiten type %d", type);
2496 warning_error_and_exit(wi, message, FARGS);
2498 weight_tot += weight[nj];
2506 gmx::formatString("Expected more than one atom index in section \"%s\"", dir2str(d));
2507 warning_error_and_exit(wi, message, FARGS);
2510 if (weight_tot == 0)
2512 warning_error_and_exit(wi, "The total mass of the construting atoms is zero", FARGS);
2515 for (int j = 0; j < nj; j++)
2517 std::vector<int> atoms = { firstAtom, atc[j] };
2519 forceParam[1] = weight[j] / weight_tot;
2520 /* Put the values in the appropriate arrays */
2521 add_param_to_list(&bond[ftype], InteractionOfType(atoms, forceParam));
2528 void push_mol(gmx::ArrayRef<MoleculeInformation> mols, char* pline, int* whichmol, int* nrcopies, warninp* wi)
2532 if (sscanf(pline, "%s%d", type, nrcopies) != 2)
2538 /* Search moleculename.
2539 * Here we originally only did case insensitive matching. But because
2540 * some PDB files can have many chains and use case to generate more
2541 * chain-identifiers, which in turn end up in our moleculetype name,
2542 * we added support for case-sensitivity.
2549 for (const auto& mol : mols)
2551 if (strcmp(type, *(mol.name)) == 0)
2556 if (gmx_strcasecmp(type, *(mol.name)) == 0)
2566 // select the case sensitive match
2567 *whichmol = matchcs;
2571 // avoid matching case-insensitive when we have multiple matches
2574 auto message = gmx::formatString(
2575 "For moleculetype '%s' in [ system ] %d case insensitive "
2576 "matches, but %d case sensitive matches were found. Check "
2577 "the case of the characters in the moleculetypes.",
2581 warning_error_and_exit(wi, message, FARGS);
2585 // select the unique case insensitive match
2586 *whichmol = matchci;
2590 auto message = gmx::formatString("No such moleculetype %s", type);
2591 warning_error_and_exit(wi, message, FARGS);
2596 void push_excl(char* line, gmx::ArrayRef<gmx::ExclusionBlock> b2, warninp* wi)
2600 char base[STRLEN], format[STRLEN];
2602 if (sscanf(line, "%d", &i) == 0)
2607 if ((1 <= i) && (i <= b2.ssize()))
2615 strcpy(base, "%*d");
2618 strcpy(format, base);
2619 strcat(format, "%d");
2620 n = sscanf(line, format, &j);
2623 if ((1 <= j) && (j <= b2.ssize()))
2626 b2[i].atomNumber.push_back(j);
2627 /* also add the reverse exclusion! */
2628 b2[j].atomNumber.push_back(i);
2629 strcat(base, "%*d");
2633 auto message = gmx::formatString("Invalid Atomnr j: %d, b2->nr: %zu\n", j, b2.size());
2634 warning_error_and_exit(wi, message, FARGS);
2640 int add_atomtype_decoupled(t_symtab* symtab, PreprocessingAtomTypes* at, t_nbparam*** nbparam, t_nbparam*** pair)
2645 /* Define an atom type with all parameters set to zero (no interactions) */
2648 /* Type for decoupled atoms could be anything,
2649 * this should be changed automatically later when required.
2651 atom.ptype = eptAtom;
2653 std::array<real, MAXFORCEPARAM> forceParam = { 0.0 };
2654 nr = at->addType(symtab, atom, "decoupled", InteractionOfType({}, forceParam, ""), -1, 0);
2656 /* Add space in the non-bonded parameters matrix */
2657 realloc_nb_params(at, nbparam, pair);
2662 static void convert_pairs_to_pairsQ(gmx::ArrayRef<InteractionsOfType> interactions, real fudgeQQ, t_atoms* atoms)
2664 /* Add the pair list to the pairQ list */
2665 std::vector<InteractionOfType> paramnew;
2667 gmx::ArrayRef<const InteractionOfType> paramp1 = interactions[F_LJ14].interactionTypes;
2668 gmx::ArrayRef<const InteractionOfType> paramp2 = interactions[F_LJC14_Q].interactionTypes;
2670 /* Fill in the new F_LJC14_Q array with the old one. NOTE:
2671 it may be possible to just ADD the converted F_LJ14 array
2672 to the old F_LJC14_Q array, but since we have to create
2673 a new sized memory structure, better just to deep copy it all.
2677 for (const auto& param : paramp2)
2679 paramnew.emplace_back(param);
2682 for (const auto& param : paramp1)
2684 std::vector<real> forceParam = {
2685 fudgeQQ, atoms->atom[param.ai()].q, atoms->atom[param.aj()].q, param.c0(), param.c1()
2687 paramnew.emplace_back(InteractionOfType(param.atoms(), forceParam, ""));
2690 /* now assign the new data to the F_LJC14_Q structure */
2691 interactions[F_LJC14_Q].interactionTypes = paramnew;
2693 /* Empty the LJ14 pairlist */
2694 interactions[F_LJ14].interactionTypes.clear();
2697 static void generate_LJCpairsNB(MoleculeInformation* mol, int nb_funct, InteractionsOfType* nbp, warninp* wi)
2703 atom = mol->atoms.atom;
2705 ntype = static_cast<int>(std::sqrt(static_cast<double>(nbp->size())));
2706 GMX_ASSERT(ntype * ntype == gmx::ssize(*nbp),
2707 "Number of pairs of generated non-bonded parameters should be a perfect square");
2709 /* Add a pair interaction for all non-excluded atom pairs */
2710 const auto& excls = mol->excls;
2711 for (int i = 0; i < n; i++)
2713 for (int j = i + 1; j < n; j++)
2715 bool pairIsExcluded = false;
2716 for (const int atomK : excls[i])
2720 pairIsExcluded = true;
2723 if (!pairIsExcluded)
2725 if (nb_funct != F_LJ)
2727 auto message = gmx::formatString(
2728 "Can only generate non-bonded pair interactions "
2729 "for Van der Waals type Lennard-Jones");
2730 warning_error_and_exit(wi, message, FARGS);
2732 std::vector<int> atoms = { i, j };
2733 std::vector<real> forceParam = {
2736 nbp->interactionTypes[ntype * atom[i].type + atom[j].type].c0(),
2737 nbp->interactionTypes[ntype * atom[i].type + atom[j].type].c1()
2739 add_param_to_list(&mol->interactions[F_LJC_PAIRS_NB], InteractionOfType(atoms, forceParam));
2745 static void set_excl_all(gmx::ListOfLists<int>* excl)
2747 /* Get rid of the current exclusions and exclude all atom pairs */
2748 const int numAtoms = excl->ssize();
2749 std::vector<int> exclusionsForAtom(numAtoms);
2750 for (int i = 0; i < numAtoms; i++)
2752 exclusionsForAtom[i] = i;
2755 for (int i = 0; i < numAtoms; i++)
2757 excl->pushBack(exclusionsForAtom);
2761 static void decouple_atoms(t_atoms* atoms,
2762 int atomtype_decouple,
2765 const char* mol_name,
2770 for (i = 0; i < atoms->nr; i++)
2774 atom = &atoms->atom[i];
2776 if (atom->qB != atom->q || atom->typeB != atom->type)
2778 auto message = gmx::formatString(
2779 "Atom %d in molecule type '%s' has different A and B state "
2780 "charges and/or atom types set in the topology file as well "
2781 "as through the mdp option '%s'. You can not use both "
2782 "these methods simultaneously.",
2786 warning_error_and_exit(wi, message, FARGS);
2789 if (couple_lam0 == ecouplamNONE || couple_lam0 == ecouplamVDW)
2793 if (couple_lam0 == ecouplamNONE || couple_lam0 == ecouplamQ)
2795 atom->type = atomtype_decouple;
2797 if (couple_lam1 == ecouplamNONE || couple_lam1 == ecouplamVDW)
2801 if (couple_lam1 == ecouplamNONE || couple_lam1 == ecouplamQ)
2803 atom->typeB = atomtype_decouple;
2808 void convert_moltype_couple(MoleculeInformation* mol,
2809 int atomtype_decouple,
2815 InteractionsOfType* nbp,
2818 convert_pairs_to_pairsQ(mol->interactions, fudgeQQ, &mol->atoms);
2821 generate_LJCpairsNB(mol, nb_funct, nbp, wi);
2822 set_excl_all(&mol->excls);
2824 decouple_atoms(&mol->atoms, atomtype_decouple, couple_lam0, couple_lam1, *mol->name, wi);