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 nfields, j, pt, nfp0 = -1;
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 auto batype_nr = bondAtomType->addBondAtomType(symtab, btype);
558 auto atomType = at->atomTypeFromName(type);
559 if (atomType.has_value())
561 auto message = gmx::formatString(
562 "Atomtype %s was defined previously (e.g. in the forcefield files), "
563 "and has now been defined again. This could happen e.g. if you would "
564 "use a self-contained molecule .itp file that duplicates or replaces "
565 "the contents of the standard force-field files. You should check "
566 "the contents of your files and remove such repetition. If you know "
567 "you should override the previous definition, then you could choose "
568 "to suppress this warning with -maxwarn.",
570 warning(wi, message);
571 auto newAtomType = at->setType(*atomType, symtab, *atom, type, interactionType, batype_nr, atomnr);
572 if (!newAtomType.has_value())
574 auto message = gmx::formatString("Replacing atomtype %s failed", type);
575 warning_error_and_exit(wi, message, FARGS);
580 at->addType(symtab, *atom, type, interactionType, batype_nr, atomnr);
581 /* Add space in the non-bonded parameters matrix */
582 realloc_nb_params(at, nbparam, pair);
587 //! Return whether the contents of \c a and \c b are the same, considering also reversed order.
589 static bool equalEitherForwardOrBackward(gmx::ArrayRef<const T> a, gmx::ArrayRef<const T> b)
591 return (std::equal(a.begin(), a.end(), b.begin()) || std::equal(a.begin(), a.end(), b.rbegin()));
594 static void push_bondtype(InteractionsOfType* bt,
595 const InteractionOfType& b,
603 int nrfp = NRFP(ftype);
605 /* If bAllowRepeat is TRUE, we allow multiple entries as long as they
606 are on directly _adjacent_ lines.
609 /* First check if our atomtypes are _identical_ (not reversed) to the previous
610 entry. If they are not identical we search for earlier duplicates. If they are
611 we can skip it, since we already searched for the first line
615 bool isContinuationOfBlock = false;
616 if (bAllowRepeat && nr > 1)
618 isContinuationOfBlock = true;
619 gmx::ArrayRef<const int> newParAtom = b.atoms();
620 gmx::ArrayRef<const int> sysParAtom = bt->interactionTypes[nr - 2].atoms();
621 for (int j = 0; j < nral; j++)
623 if (newParAtom[j] != sysParAtom[j])
625 isContinuationOfBlock = false;
630 /* Search for earlier duplicates if this entry was not a continuation
631 from the previous line.
633 bool addBondType = true;
634 bool haveWarned = false;
635 bool haveErrored = false;
636 for (int i = 0; (i < nr); i++)
638 gmx::ArrayRef<const int> bParams = b.atoms();
639 gmx::ArrayRef<const int> testParams = bt->interactionTypes[i].atoms();
640 GMX_RELEASE_ASSERT(bParams.size() == testParams.size(),
641 "Number of atoms needs to be the same between parameters");
642 if (equalEitherForwardOrBackward(bParams, testParams))
644 GMX_ASSERT(nrfp <= MAXFORCEPARAM,
645 "This is ensured in other places, but we need this assert to keep the clang "
647 const bool identicalParameters = std::equal(bt->interactionTypes[i].forceParam().begin(),
648 bt->interactionTypes[i].forceParam().begin() + nrfp,
649 b.forceParam().begin());
651 if (!bAllowRepeat || identicalParameters)
656 if (!identicalParameters)
660 /* With dihedral type 9 we only allow for repeating
661 * of the same parameters with blocks with 1 entry.
662 * Allowing overriding is too complex to check.
664 if (!isContinuationOfBlock && !haveErrored)
667 "Encountered a second block of parameters for dihedral "
668 "type 9 for the same atoms, with either different parameters "
669 "and/or the first block has multiple lines. This is not "
674 else if (!haveWarned)
676 auto message = gmx::formatString(
677 "Bondtype %s was defined previously (e.g. in the forcefield files), "
678 "and has now been defined again. This could happen e.g. if you would "
679 "use a self-contained molecule .itp file that duplicates or replaces "
680 "the contents of the standard force-field files. You should check "
681 "the contents of your files and remove such repetition. If you know "
682 "you should override the previous definition, then you could choose "
683 "to suppress this warning with -maxwarn.%s",
684 interaction_function[ftype].longname,
685 (ftype == F_PDIHS) ? "\nUse dihedraltype 9 to allow several "
686 "multiplicity terms. Only consecutive "
687 "lines are combined. Non-consective lines "
688 "overwrite each other."
690 warning(wi, message);
692 fprintf(stderr, " old: ");
693 gmx::ArrayRef<const real> forceParam = bt->interactionTypes[i].forceParam();
694 for (int j = 0; j < nrfp; j++)
696 fprintf(stderr, " %g", forceParam[j]);
698 fprintf(stderr, " \n new: %s\n\n", line);
704 if (!identicalParameters && !bAllowRepeat)
706 /* Overwrite the parameters with the latest ones */
707 // TODO considering improving the following code by replacing with:
708 // std::copy(b->c, b->c + nrfp, bt->param[i].c);
709 gmx::ArrayRef<const real> forceParam = b.forceParam();
710 for (int j = 0; j < nrfp; j++)
712 bt->interactionTypes[i].setForceParameter(j, forceParam[j]);
720 /* fill the arrays up and down */
721 bt->interactionTypes.emplace_back(
722 InteractionOfType(b.atoms(), b.forceParam(), b.interactionTypeName()));
723 /* need to store force values because they might change below */
724 std::vector<real> forceParam(b.forceParam().begin(), b.forceParam().end());
726 /* The definitions of linear angles depend on the order of atoms,
727 * that means that for atoms i-j-k, with certain parameter a, the
728 * corresponding k-j-i angle will have parameter 1-a.
730 if (ftype == F_LINEAR_ANGLES)
732 forceParam[0] = 1 - forceParam[0];
733 forceParam[2] = 1 - forceParam[2];
735 std::vector<int> atoms;
736 gmx::ArrayRef<const int> oldAtoms = b.atoms();
737 for (auto oldAtom = oldAtoms.rbegin(); oldAtom != oldAtoms.rend(); oldAtom++)
739 atoms.emplace_back(*oldAtom);
741 bt->interactionTypes.emplace_back(InteractionOfType(atoms, forceParam, b.interactionTypeName()));
745 static std::vector<int> atomTypesFromAtomNames(const PreprocessingAtomTypes* atomTypes,
746 const PreprocessingBondAtomType* bondAtomTypes,
747 gmx::ArrayRef<const char[20]> atomNames,
751 GMX_RELEASE_ASSERT(!(!atomNames.empty() && !atomTypes && !bondAtomTypes),
752 "Need to have either valid atomtypes or bondatomtypes object");
754 std::vector<int> atomTypesFromAtomNames;
755 for (const auto& name : atomNames)
757 if (atomTypes != nullptr)
759 auto atomType = atomTypes->atomTypeFromName(name);
760 if (!atomType.has_value())
762 auto message = gmx::formatString("Unknown atomtype %s\n", name);
763 warning_error_and_exit(wi, message, FARGS);
765 atomTypesFromAtomNames.emplace_back(*atomType);
767 else if (bondAtomTypes != nullptr)
769 auto bondAtomType = bondAtomTypes->bondAtomTypeFromName(name);
770 if (!bondAtomType.has_value())
772 auto message = gmx::formatString("Unknown bond_atomtype %s\n", name);
773 warning_error_and_exit(wi, message, FARGS);
775 atomTypesFromAtomNames.emplace_back(*bondAtomType);
778 return atomTypesFromAtomNames;
782 void push_bt(Directive d,
783 gmx::ArrayRef<InteractionsOfType> bt,
785 PreprocessingAtomTypes* at,
786 PreprocessingBondAtomType* bondAtomType,
790 const char* formal[MAXATOMLIST + 1] = {
791 "%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"
793 const char* formnl[MAXATOMLIST + 1] = { "%*s",
798 "%*s%*s%*s%*s%*s%*s",
799 "%*s%*s%*s%*s%*s%*s%*s" };
800 const char* formlf = "%lf%lf%lf%lf%lf%lf%lf%lf%lf%lf%lf%lf%lf";
801 int i, ft, ftype, nn, nrfp, nrfpA;
803 char alc[MAXATOMLIST + 1][20];
804 /* One force parameter more, so we can check if we read too many */
805 double c[MAXFORCEPARAM + 1];
807 if ((bondAtomType && at) || (!bondAtomType && !at))
809 gmx_incons("You should pass either bondAtomType or at to push_bt");
812 /* Make format string (nral ints+functype) */
813 if ((nn = sscanf(line, formal[nral], alc[0], alc[1], alc[2], alc[3], alc[4], alc[5])) != nral + 1)
815 auto message = gmx::formatString("Not enough atomtypes (%d instead of %d)", nn - 1, nral);
816 warning_error(wi, message);
820 ft = strtol(alc[nral], nullptr, 10);
821 ftype = ifunc_index(d, ft);
823 nrfpA = interaction_function[ftype].nrfpA;
824 strcpy(f1, formnl[nral]);
827 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]))
832 /* Copy the B-state from the A-state */
833 copy_B_from_A(ftype, c);
839 warning_error(wi, "Not enough parameters");
841 else if (nn > nrfpA && nn < nrfp)
843 warning_error(wi, "Too many parameters or not enough parameters for topology B");
847 warning_error(wi, "Too many parameters");
849 for (i = nn; (i < nrfp); i++)
855 std::vector<int> atomTypes =
856 atomTypesFromAtomNames(at, bondAtomType, gmx::arrayRefFromArray(alc, nral), wi);
857 std::array<real, MAXFORCEPARAM> forceParam;
858 for (int i = 0; (i < nrfp); i++)
860 forceParam[i] = c[i];
862 push_bondtype(&(bt[ftype]), InteractionOfType(atomTypes, forceParam), nral, ftype, FALSE, line, wi);
866 void push_dihedraltype(Directive d,
867 gmx::ArrayRef<InteractionsOfType> bt,
868 PreprocessingBondAtomType* bondAtomType,
872 const char* formal[MAXATOMLIST + 1] = {
873 "%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"
875 const char* formnl[MAXATOMLIST + 1] = { "%*s",
880 "%*s%*s%*s%*s%*s%*s",
881 "%*s%*s%*s%*s%*s%*s%*s" };
882 const char* formlf[MAXFORCEPARAM] = {
888 "%lf%lf%lf%lf%lf%lf",
889 "%lf%lf%lf%lf%lf%lf%lf",
890 "%lf%lf%lf%lf%lf%lf%lf%lf",
891 "%lf%lf%lf%lf%lf%lf%lf%lf%lf",
892 "%lf%lf%lf%lf%lf%lf%lf%lf%lf%lf",
893 "%lf%lf%lf%lf%lf%lf%lf%lf%lf%lf%lf",
894 "%lf%lf%lf%lf%lf%lf%lf%lf%lf%lf%lf%lf",
896 int i, ft, ftype, nn, nrfp, nrfpA, nral;
898 char alc[MAXATOMLIST + 1][20];
899 double c[MAXFORCEPARAM];
902 /* This routine accepts dihedraltypes defined from either 2 or 4 atoms.
904 * We first check for 2 atoms with the 3th column being an integer
905 * defining the type. If this isn't the case, we try it with 4 atoms
906 * and the 5th column defining the dihedral type.
908 nn = sscanf(line, formal[4], alc[0], alc[1], alc[2], alc[3], alc[4]);
909 if (nn >= 3 && strlen(alc[2]) == 1 && isdigit(alc[2][0]))
912 ft = strtol(alc[nral], nullptr, 10);
913 /* Move atom types around a bit and use 'X' for wildcard atoms
914 * to create a 4-atom dihedral definition with arbitrary atoms in
917 if (alc[2][0] == '2')
919 /* improper - the two atomtypes are 1,4. Use wildcards for 2,3 */
920 strcpy(alc[3], alc[1]);
921 sprintf(alc[2], "X");
922 sprintf(alc[1], "X");
923 /* alc[0] stays put */
927 /* proper - the two atomtypes are 2,3. Use wildcards for 1,4 */
928 sprintf(alc[3], "X");
929 strcpy(alc[2], alc[1]);
930 strcpy(alc[1], alc[0]);
931 sprintf(alc[0], "X");
934 else if (nn == 5 && strlen(alc[4]) == 1 && isdigit(alc[4][0]))
937 ft = strtol(alc[nral], nullptr, 10);
941 auto message = gmx::formatString(
942 "Incorrect number of atomtypes for dihedral (%d instead of 2 or 4)", nn - 1);
943 warning_error(wi, message);
949 /* Previously, we have always overwritten parameters if e.g. a torsion
950 with the same atomtypes occurs on multiple lines. However, CHARMM and
951 some other force fields specify multiple dihedrals over some bonds,
952 including cosines with multiplicity 6 and somethimes even higher.
953 Thus, they cannot be represented with Ryckaert-Bellemans terms.
954 To add support for these force fields, Dihedral type 9 is identical to
955 normal proper dihedrals, but repeated entries are allowed.
962 bAllowRepeat = FALSE;
966 ftype = ifunc_index(d, ft);
968 nrfpA = interaction_function[ftype].nrfpA;
970 strcpy(f1, formnl[nral]);
971 strcat(f1, formlf[nrfp - 1]);
973 /* Check number of parameters given */
975 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]))
980 /* Copy the B-state from the A-state */
981 copy_B_from_A(ftype, c);
987 warning_error(wi, "Not enough parameters");
989 else if (nn > nrfpA && nn < nrfp)
991 warning_error(wi, "Too many parameters or not enough parameters for topology B");
995 warning_error(wi, "Too many parameters");
997 for (i = nn; (i < nrfp); i++)
1004 std::vector<int> atoms;
1005 std::array<real, MAXFORCEPARAM> forceParam;
1006 for (int i = 0; (i < 4); i++)
1008 if (!strcmp(alc[i], "X"))
1010 atoms.emplace_back(-1);
1014 auto atomNumber = bondAtomType->bondAtomTypeFromName(alc[i]);
1015 if (!atomNumber.has_value())
1017 auto message = gmx::formatString("Unknown bond_atomtype %s", alc[i]);
1018 warning_error_and_exit(wi, message, FARGS);
1020 atoms.emplace_back(*atomNumber);
1023 for (int i = 0; (i < nrfp); i++)
1025 forceParam[i] = c[i];
1027 /* Always use 4 atoms here, since we created two wildcard atoms
1028 * if there wasn't of them 4 already.
1030 push_bondtype(&(bt[ftype]), InteractionOfType(atoms, forceParam), 4, ftype, bAllowRepeat, line, wi);
1034 void push_nbt(Directive d, t_nbparam** nbt, PreprocessingAtomTypes* atypes, char* pline, int nb_funct, warninp* wi)
1036 /* swap the atoms */
1037 const char* form3 = "%*s%*s%*s%lf%lf%lf";
1038 const char* form4 = "%*s%*s%*s%lf%lf%lf%lf";
1039 const char* form5 = "%*s%*s%*s%lf%lf%lf%lf%lf";
1040 char a0[80], a1[80];
1041 int i, f, n, ftype, nrfp;
1047 if (sscanf(pline, "%s%s%d", a0, a1, &f) != 3)
1053 ftype = ifunc_index(d, f);
1055 if (ftype != nb_funct)
1057 auto message = gmx::formatString("Trying to add %s while the default nonbond type is %s",
1058 interaction_function[ftype].longname,
1059 interaction_function[nb_funct].longname);
1060 warning_error(wi, message);
1064 /* Get the force parameters */
1066 if (ftype == F_LJ14)
1068 n = sscanf(pline, form4, &c[0], &c[1], &c[2], &c[3]);
1074 /* When the B topology parameters are not set,
1075 * copy them from topology A
1077 GMX_ASSERT(nrfp <= 4, "LJ-14 cannot have more than 4 parameters");
1078 for (i = n; i < nrfp; i++)
1083 else if (ftype == F_LJC14_Q)
1085 n = sscanf(pline, form5, &c[0], &c[1], &c[2], &c[3], &dum);
1088 incorrect_n_param(wi);
1094 if (sscanf(pline, form3, &c[0], &c[1], &dum) != 2)
1096 incorrect_n_param(wi);
1102 if (sscanf(pline, form4, &c[0], &c[1], &c[2], &dum) != 3)
1104 incorrect_n_param(wi);
1111 gmx::formatString("Number of force parameters for nonbonded interactions is %d", nrfp);
1112 warning_error_and_exit(wi, message, FARGS);
1114 for (i = 0; (i < nrfp); i++)
1119 /* Put the parameters in the matrix */
1120 auto ai = atypes->atomTypeFromName(a0);
1121 if (!ai.has_value())
1123 auto message = gmx::formatString("Atomtype %s not found", a0);
1124 warning_error_and_exit(wi, message, FARGS);
1126 auto aj = atypes->atomTypeFromName(a1);
1127 if (!aj.has_value())
1129 auto message = gmx::formatString("Atomtype %s not found", a1);
1130 warning_error_and_exit(wi, message, FARGS);
1132 nbp = &(nbt[std::max(*ai, *aj)][std::min(*ai, *aj)]);
1137 for (i = 0; i < nrfp; i++)
1139 bId = bId && (nbp->c[i] == cr[i]);
1143 auto message = gmx::formatString(
1144 "Non-bonded parameters were defined previously (e.g. in the forcefield files), "
1145 "and have now been defined again. This could happen e.g. if you would "
1146 "use a self-contained molecule .itp file that duplicates or replaces "
1147 "the contents of the standard force-field files. You should check "
1148 "the contents of your files and remove such repetition. If you know "
1149 "you should override the previous definitions, then you could choose "
1150 "to suppress this warning with -maxwarn.");
1151 warning(wi, message);
1152 fprintf(stderr, " old:");
1153 for (i = 0; i < nrfp; i++)
1155 fprintf(stderr, " %g", nbp->c[i]);
1157 fprintf(stderr, " new\n%s\n", pline);
1161 for (i = 0; i < nrfp; i++)
1167 void push_cmaptype(Directive d,
1168 gmx::ArrayRef<InteractionsOfType> bt,
1170 PreprocessingAtomTypes* atomtypes,
1171 PreprocessingBondAtomType* bondAtomType,
1175 const char* formal = "%s%s%s%s%s%s%s%s%n";
1177 int ft, ftype, nn, nrfp, nrfpA, nrfpB;
1178 int start, nchar_consumed;
1179 int nxcmap, nycmap, ncmap, read_cmap, sl, nct;
1180 char s[20], alc[MAXATOMLIST + 2][20];
1182 /* Keep the compiler happy */
1186 GMX_ASSERT(nral == 5, "CMAP requires 5 atoms per interaction");
1188 /* Here we can only check for < 8 */
1189 if ((nn = sscanf(line, formal, alc[0], alc[1], alc[2], alc[3], alc[4], alc[5], alc[6], alc[7], &nchar_consumed))
1193 gmx::formatString("Incorrect number of atomtypes for cmap (%d instead of 5)", nn - 1);
1194 warning_error(wi, message);
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(
1207 "Not the same grid spacing in x and y for cmap grid: x=%d, y=%d", nxcmap, nycmap);
1208 warning_error(wi, message);
1211 ncmap = nxcmap * nycmap;
1212 ftype = ifunc_index(d, ft);
1213 nrfpA = strtol(alc[6], nullptr, 10) * strtol(alc[6], nullptr, 10);
1214 nrfpB = strtol(alc[7], nullptr, 10) * strtol(alc[7], nullptr, 10);
1215 nrfp = nrfpA + nrfpB;
1217 /* Read in CMAP parameters */
1219 for (int i = 0; i < ncmap; i++)
1221 while (isspace(*(line + start + sl)))
1225 nn = sscanf(line + start + sl, " %s ", s);
1227 bt[F_CMAP].cmap.emplace_back(strtod(s, nullptr));
1236 gmx::formatString("Error in reading cmap parameter for angle %s %s %s %s %s",
1242 warning_error(wi, message);
1246 /* Check do that we got the number of parameters we expected */
1247 if (read_cmap == nrfpA)
1249 for (int i = 0; i < ncmap; i++)
1251 bt[F_CMAP].cmap.emplace_back(bt[F_CMAP].cmap[i]);
1256 if (read_cmap < nrfpA)
1258 warning_error(wi, "Not enough cmap parameters");
1260 else if (read_cmap > nrfpA && read_cmap < nrfp)
1262 warning_error(wi, "Too many cmap parameters or not enough parameters for topology B");
1264 else if (read_cmap > nrfp)
1266 warning_error(wi, "Too many cmap parameters");
1271 /* Set grid spacing and the number of grids (we assume these numbers to be the same for all
1272 * grids so we can safely assign them each time
1274 bt[F_CMAP].cmakeGridSpacing = nxcmap; /* Or nycmap, they need to be equal */
1275 bt[F_CMAP].cmapAngles++; /* Since we are incrementing here, we need to subtract later, see (*****) */
1276 nct = (nral + 1) * bt[F_CMAP].cmapAngles;
1278 for (int i = 0; (i < nral); i++)
1280 /* Assign a grid number to each cmap_type */
1281 GMX_RELEASE_ASSERT(bondAtomType != nullptr, "Need valid PreprocessingBondAtomType object");
1282 bt[F_CMAP].cmapAtomTypes.emplace_back(*bondAtomType->bondAtomTypeFromName(alc[i]));
1285 /* Assign a type number to this cmap */
1286 bt[F_CMAP].cmapAtomTypes.emplace_back(
1287 bt[F_CMAP].cmapAngles
1288 - 1); /* Since we inremented earlier, we need to subtrac here, to get the types right (****) */
1290 /* Check for the correct number of atoms (again) */
1291 if (bt[F_CMAP].nct() != nct)
1293 auto message = gmx::formatString(
1294 "Incorrect number of atom types (%d) in cmap type %d\n", nct, bt[F_CMAP].cmapAngles);
1295 warning_error(wi, message);
1297 std::vector<int> atomTypes =
1298 atomTypesFromAtomNames(atomtypes, bondAtomType, gmx::constArrayRefFromArray(alc, nral), wi);
1299 std::array<real, MAXFORCEPARAM> forceParam = { NOTSET };
1301 /* Push the bond to the bondlist */
1302 push_bondtype(&(bt[ftype]), InteractionOfType(atomTypes, forceParam), nral, ftype, FALSE, line, wi);
1306 static void push_atom_now(t_symtab* symtab,
1324 int j, resind = 0, resnr;
1328 if (((nr == 0) && (atomnr != 1)) || (nr && (atomnr != at->nr + 1)))
1330 auto message = gmx::formatString(
1331 "Atoms in the .top are not numbered consecutively from 1 (rather, "
1332 "atomnr = %d, while at->nr = %d)",
1335 warning_error_and_exit(wi, message, FARGS);
1338 j = strlen(resnumberic) - 1;
1339 if (isdigit(resnumberic[j]))
1345 ric = resnumberic[j];
1346 if (j == 0 || !isdigit(resnumberic[j - 1]))
1349 gmx::formatString("Invalid residue number '%s' for atom %d", resnumberic, atomnr);
1350 warning_error_and_exit(wi, message, FARGS);
1353 resnr = strtol(resnumberic, nullptr, 10);
1357 resind = at->atom[nr - 1].resind;
1359 if (nr == 0 || strcmp(resname, *at->resinfo[resind].name) != 0
1360 || resnr != at->resinfo[resind].nr || ric != at->resinfo[resind].ic)
1370 at->nres = resind + 1;
1371 srenew(at->resinfo, at->nres);
1372 at->resinfo[resind].name = put_symtab(symtab, resname);
1373 at->resinfo[resind].nr = resnr;
1374 at->resinfo[resind].ic = ric;
1378 resind = at->atom[at->nr - 1].resind;
1381 /* New atom instance
1382 * get new space for arrays
1384 srenew(at->atom, nr + 1);
1385 srenew(at->atomname, nr + 1);
1386 srenew(at->atomtype, nr + 1);
1387 srenew(at->atomtypeB, nr + 1);
1390 at->atom[nr].type = type;
1391 at->atom[nr].ptype = ptype;
1392 at->atom[nr].q = q0;
1393 at->atom[nr].m = m0;
1394 at->atom[nr].typeB = typeB;
1395 at->atom[nr].qB = qB;
1396 at->atom[nr].mB = mB;
1398 at->atom[nr].resind = resind;
1399 at->atom[nr].atomnumber = atomicnumber;
1400 at->atomname[nr] = put_symtab(symtab, name);
1401 at->atomtype[nr] = put_symtab(symtab, ctype);
1402 at->atomtypeB[nr] = put_symtab(symtab, ctypeB);
1406 void push_atom(t_symtab* symtab, t_atoms* at, PreprocessingAtomTypes* atypes, char* line, warninp* wi)
1409 int cgnumber, atomnr, nscan;
1410 char id[STRLEN], ctype[STRLEN], ctypeB[STRLEN], resnumberic[STRLEN], resname[STRLEN],
1411 name[STRLEN], check[STRLEN];
1412 double m, q, mb, qb;
1413 real m0, q0, mB, qB;
1415 /* Fixed parameters */
1416 if (sscanf(line, "%s%s%s%s%s%d", id, ctype, resnumberic, resname, name, &cgnumber) != 6)
1421 sscanf(id, "%d", &atomnr);
1422 auto type = atypes->atomTypeFromName(ctype);
1423 if (!type.has_value())
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 typeB = atypes->atomTypeFromName(ctypeB);
1450 if (!typeB.has_value())
1452 auto message = gmx::formatString("Atomtype %s not found", ctypeB);
1453 warning_error_and_exit(wi, message, FARGS);
1455 qB = *atypes->atomChargeFromAtomType(*typeB);
1456 mB = *atypes->atomMassFromAtomType(*typeB);
1465 warning_error(wi, "Too many parameters");
1473 push_atom_now(symtab,
1476 *atypes->atomNumberFromAtomType(*type),
1486 typeB == type ? ctype : ctypeB,
1492 void push_molt(t_symtab* symtab, std::vector<MoleculeInformation>* mol, char* line, warninp* wi)
1497 if ((sscanf(line, "%s%d", type, &nrexcl)) != 2)
1499 warning_error(wi, "Expected a molecule type name and nrexcl");
1502 /* Test if this moleculetype overwrites another */
1503 const auto found = std::find_if(
1504 mol->begin(), mol->end(), [&type](const auto& m) { return strcmp(*(m.name), type) == 0; });
1505 if (found != mol->end())
1507 auto message = gmx::formatString("moleculetype %s is redefined", type);
1508 warning_error_and_exit(wi, message, FARGS);
1511 mol->emplace_back();
1512 mol->back().initMolInfo();
1514 /* Fill in the values */
1515 mol->back().name = put_symtab(symtab, type);
1516 mol->back().nrexcl = nrexcl;
1517 mol->back().excl_set = false;
1520 static bool findIfAllNBAtomsMatch(gmx::ArrayRef<const int> atomsFromParameterArray,
1521 gmx::ArrayRef<const int> atomsFromCurrentParameter,
1525 if (atomsFromParameterArray.size() != atomsFromCurrentParameter.size())
1531 for (gmx::index i = 0; i < atomsFromCurrentParameter.ssize(); i++)
1533 if (at->atom[atomsFromCurrentParameter[i]].typeB != atomsFromParameterArray[i])
1542 for (gmx::index i = 0; i < atomsFromCurrentParameter.ssize(); i++)
1544 if (at->atom[atomsFromCurrentParameter[i]].type != atomsFromParameterArray[i])
1553 static bool default_nb_params(int ftype,
1554 gmx::ArrayRef<InteractionsOfType> bt,
1556 InteractionOfType* p,
1563 InteractionOfType* pi = nullptr;
1564 int nr = bt[ftype].size();
1565 int nral = NRAL(ftype);
1566 int nrfp = interaction_function[ftype].nrfpA;
1567 int nrfpB = interaction_function[ftype].nrfpB;
1569 if ((!bB && nrfp == 0) || (bB && nrfpB == 0))
1577 /* First test the generated-pair position to save
1578 * time when we have 1000*1000 entries for e.g. OPLS...
1580 ntype = static_cast<int>(std::sqrt(static_cast<double>(nr)));
1581 GMX_ASSERT(ntype * ntype == nr,
1582 "Number of pairs of generated non-bonded parameters should be a perfect square");
1585 ti = at->atom[p->ai()].typeB;
1586 tj = at->atom[p->aj()].typeB;
1590 ti = at->atom[p->ai()].type;
1591 tj = at->atom[p->aj()].type;
1593 pi = &(bt[ftype].interactionTypes[ntype * ti + tj]);
1594 if (pi->atoms().ssize() < nral)
1596 /* not initialized yet with atom names */
1601 bFound = ((ti == pi->ai()) && (tj == pi->aj()));
1605 gmx::ArrayRef<const int> paramAtoms = p->atoms();
1606 /* Search explicitly if we didnt find it */
1609 auto foundParameter =
1610 std::find_if(bt[ftype].interactionTypes.begin(),
1611 bt[ftype].interactionTypes.end(),
1612 [¶mAtoms, &at, &bB](const auto& param) {
1613 return findIfAllNBAtomsMatch(param.atoms(), paramAtoms, at, bB);
1615 if (foundParameter != bt[ftype].interactionTypes.end())
1618 pi = &(*foundParameter);
1624 gmx::ArrayRef<const real> forceParam = pi->forceParam();
1627 if (nrfp + nrfpB > MAXFORCEPARAM)
1629 gmx_incons("Too many force parameters");
1631 for (int j = c_start; j < nrfpB; j++)
1633 p->setForceParameter(nrfp + j, forceParam[j]);
1638 for (int j = c_start; j < nrfp; j++)
1640 p->setForceParameter(j, forceParam[j]);
1646 for (int j = c_start; j < nrfp; j++)
1648 p->setForceParameter(j, 0.0);
1654 static bool default_cmap_params(gmx::ArrayRef<InteractionsOfType> bondtype,
1656 PreprocessingAtomTypes* atypes,
1657 InteractionOfType* p,
1665 bool bFound = false;
1670 /* Match the current cmap angle against the list of cmap_types */
1671 for (int i = 0; i < bondtype[F_CMAP].nct() && !bFound; i += 6)
1676 if ((atypes->bondAtomTypeFromAtomType(at->atom[p->ai()].type)
1677 == bondtype[F_CMAP].cmapAtomTypes[i])
1678 && (atypes->bondAtomTypeFromAtomType(at->atom[p->aj()].type)
1679 == bondtype[F_CMAP].cmapAtomTypes[i + 1])
1680 && (atypes->bondAtomTypeFromAtomType(at->atom[p->ak()].type)
1681 == bondtype[F_CMAP].cmapAtomTypes[i + 2])
1682 && (atypes->bondAtomTypeFromAtomType(at->atom[p->al()].type)
1683 == bondtype[F_CMAP].cmapAtomTypes[i + 3])
1684 && (atypes->bondAtomTypeFromAtomType(at->atom[p->am()].type)
1685 == bondtype[F_CMAP].cmapAtomTypes[i + 4]))
1687 /* Found cmap torsion */
1689 ct = bondtype[F_CMAP].cmapAtomTypes[i + 5];
1695 /* If we did not find a matching type for this cmap torsion */
1698 auto message = gmx::formatString("Unknown cmap torsion between atoms %d %d %d %d %d",
1704 warning_error_and_exit(wi, message, FARGS);
1707 *nparam_def = nparam_found;
1713 /* Returns the number of exact atom type matches, i.e. non wild-card matches,
1714 * returns -1 when there are no matches at all.
1716 static int natom_match(const InteractionOfType& pi,
1721 const PreprocessingAtomTypes* atypes)
1723 if ((pi.ai() == -1 || atypes->bondAtomTypeFromAtomType(type_i) == pi.ai())
1724 && (pi.aj() == -1 || atypes->bondAtomTypeFromAtomType(type_j) == pi.aj())
1725 && (pi.ak() == -1 || atypes->bondAtomTypeFromAtomType(type_k) == pi.ak())
1726 && (pi.al() == -1 || atypes->bondAtomTypeFromAtomType(type_l) == pi.al()))
1728 return (pi.ai() == -1 ? 0 : 1) + (pi.aj() == -1 ? 0 : 1) + (pi.ak() == -1 ? 0 : 1)
1729 + (pi.al() == -1 ? 0 : 1);
1737 static int findNumberOfDihedralAtomMatches(const InteractionOfType& currentParamFromParameterArray,
1738 const InteractionOfType& parameterToAdd,
1740 const PreprocessingAtomTypes* atypes,
1745 return natom_match(currentParamFromParameterArray,
1746 at->atom[parameterToAdd.ai()].typeB,
1747 at->atom[parameterToAdd.aj()].typeB,
1748 at->atom[parameterToAdd.ak()].typeB,
1749 at->atom[parameterToAdd.al()].typeB,
1754 return natom_match(currentParamFromParameterArray,
1755 at->atom[parameterToAdd.ai()].type,
1756 at->atom[parameterToAdd.aj()].type,
1757 at->atom[parameterToAdd.ak()].type,
1758 at->atom[parameterToAdd.al()].type,
1763 static bool findIfAllParameterAtomsMatch(gmx::ArrayRef<const int> atomsFromParameterArray,
1764 gmx::ArrayRef<const int> atomsFromCurrentParameter,
1766 const PreprocessingAtomTypes* atypes,
1769 if (atomsFromParameterArray.size() != atomsFromCurrentParameter.size())
1775 for (gmx::index i = 0; i < atomsFromCurrentParameter.ssize(); i++)
1777 if (atypes->bondAtomTypeFromAtomType(at->atom[atomsFromCurrentParameter[i]].typeB)
1778 != atomsFromParameterArray[i])
1787 for (gmx::index i = 0; i < atomsFromCurrentParameter.ssize(); i++)
1789 if (atypes->bondAtomTypeFromAtomType(at->atom[atomsFromCurrentParameter[i]].type)
1790 != atomsFromParameterArray[i])
1799 static std::vector<InteractionOfType>::iterator defaultInteractionsOfType(int ftype,
1800 gmx::ArrayRef<InteractionsOfType> bt,
1802 PreprocessingAtomTypes* atypes,
1803 const InteractionOfType& p,
1808 int nrfpA = interaction_function[ftype].nrfpA;
1809 int nrfpB = interaction_function[ftype].nrfpB;
1811 if ((!bB && nrfpA == 0) || (bB && nrfpB == 0))
1813 return bt[ftype].interactionTypes.end();
1818 if (ftype == F_PDIHS || ftype == F_RBDIHS || ftype == F_IDIHS || ftype == F_PIDIHS)
1820 int nmatch_max = -1;
1822 /* For dihedrals we allow wildcards. We choose the first type
1823 * that has the most real matches, i.e. non-wildcard matches.
1825 auto prevPos = bt[ftype].interactionTypes.end();
1826 auto pos = bt[ftype].interactionTypes.begin();
1827 while (pos != bt[ftype].interactionTypes.end() && nmatch_max < 4)
1829 pos = std::find_if(bt[ftype].interactionTypes.begin(),
1830 bt[ftype].interactionTypes.end(),
1831 [&p, &at, &atypes, &bB, &nmatch_max](const auto& param) {
1832 return (findNumberOfDihedralAtomMatches(param, p, at, atypes, bB)
1835 if (pos != bt[ftype].interactionTypes.end())
1838 nmatch_max = findNumberOfDihedralAtomMatches(*pos, p, at, atypes, bB);
1842 if (prevPos != bt[ftype].interactionTypes.end())
1846 /* Find additional matches for this dihedral - necessary
1848 * The rule in that case is that additional matches
1849 * HAVE to be on adjacent lines!
1852 // Advance iterator (like std::advance) without incrementing past end (UB)
1853 const auto safeAdvance = [](auto& it, auto n, auto end) {
1854 it = end - it > n ? it + n : end;
1856 /* Continue from current iterator position */
1857 auto nextPos = prevPos;
1858 const auto endIter = bt[ftype].interactionTypes.end();
1859 safeAdvance(nextPos, 2, endIter);
1860 for (; nextPos < endIter && bSame; safeAdvance(nextPos, 2, endIter))
1862 bSame = (prevPos->ai() == nextPos->ai() && prevPos->aj() == nextPos->aj()
1863 && prevPos->ak() == nextPos->ak() && prevPos->al() == nextPos->al());
1868 /* nparam_found will be increased as long as the numbers match */
1871 *nparam_def = nparam_found;
1874 else /* Not a dihedral */
1876 gmx::ArrayRef<const int> atomParam = p.atoms();
1877 auto found = std::find_if(bt[ftype].interactionTypes.begin(),
1878 bt[ftype].interactionTypes.end(),
1879 [&atomParam, &at, &atypes, &bB](const auto& param) {
1880 return findIfAllParameterAtomsMatch(
1881 param.atoms(), atomParam, at, atypes, bB);
1883 if (found != bt[ftype].interactionTypes.end())
1887 *nparam_def = nparam_found;
1893 void push_bond(Directive d,
1894 gmx::ArrayRef<InteractionsOfType> bondtype,
1895 gmx::ArrayRef<InteractionsOfType> bond,
1897 PreprocessingAtomTypes* atypes,
1903 bool* bWarn_copy_A_B,
1906 const char* aaformat[MAXATOMLIST] = { "%d%d", "%d%d%d", "%d%d%d%d",
1907 "%d%d%d%d%d", "%d%d%d%d%d%d", "%d%d%d%d%d%d%d" };
1908 const char* asformat[MAXATOMLIST] = {
1909 "%*s%*s", "%*s%*s%*s", "%*s%*s%*s%*s",
1910 "%*s%*s%*s%*s%*s", "%*s%*s%*s%*s%*s%*s", "%*s%*s%*s%*s%*s%*s%*s"
1912 const char* ccformat = "%lf%lf%lf%lf%lf%lf%lf%lf%lf%lf%lf%lf%lf";
1913 int nral, nral_fmt, nread, ftype;
1914 char format[STRLEN];
1915 /* One force parameter more, so we can check if we read too many */
1916 double cc[MAXFORCEPARAM + 1];
1917 int aa[MAXATOMLIST + 1];
1918 bool bFoundA = FALSE, bFoundB = FALSE, bDef, bSwapParity = FALSE;
1919 int nparam_defA, nparam_defB;
1921 nparam_defA = nparam_defB = 0;
1923 ftype = ifunc_index(d, 1);
1925 for (int j = 0; j < nral; j++)
1929 bDef = (NRFP(ftype) > 0);
1931 if (ftype == F_SETTLE)
1933 /* SETTLE acts on 3 atoms, but the topology format only specifies
1934 * the first atom (for historical reasons).
1943 nread = sscanf(line, aaformat[nral_fmt - 1], &aa[0], &aa[1], &aa[2], &aa[3], &aa[4], &aa[5]);
1945 if (ftype == F_SETTLE)
1952 if (nread < nral_fmt)
1957 else if (nread > nral_fmt)
1959 /* this is a hack to allow for virtual sites with swapped parity */
1960 bSwapParity = (aa[nral] < 0);
1963 aa[nral] = -aa[nral];
1965 ftype = ifunc_index(d, aa[nral]);
1971 case F_VSITE3OUT: break;
1974 gmx::formatString("Negative function types only allowed for %s and %s",
1975 interaction_function[F_VSITE3FAD].longname,
1976 interaction_function[F_VSITE3OUT].longname);
1977 warning_error_and_exit(wi, message, FARGS);
1983 /* Check for double atoms and atoms out of bounds */
1984 for (int i = 0; (i < nral); i++)
1986 if (aa[i] < 1 || aa[i] > at->nr)
1988 auto message = gmx::formatString(
1989 "Atom index (%d) in %s out of bounds (1-%d).\n"
1990 "This probably means that you have inserted topology section \"%s\"\n"
1991 "in a part belonging to a different molecule than you intended to.\n"
1992 "In that case move the \"%s\" section to the right molecule.",
1998 warning_error_and_exit(wi, message, FARGS);
2000 for (int j = i + 1; (j < nral); j++)
2002 GMX_ASSERT(j < MAXATOMLIST + 1,
2003 "Values from nral=NRAL() will satisfy this, we assert to keep gcc 4 happy");
2006 auto message = gmx::formatString("Duplicate atom index (%d) in %s", aa[i], dir2str(d));
2007 if (ftype == F_ANGRES)
2009 /* Since the angle restraints uses 2 pairs of atoms to
2010 * defines an angle between vectors, it can be useful
2011 * to use one atom twice, so we only issue a note here.
2013 warning_note(wi, message);
2017 warning_error(wi, message);
2023 /* default force parameters */
2024 std::vector<int> atoms;
2025 for (int j = 0; (j < nral); j++)
2027 atoms.emplace_back(aa[j] - 1);
2029 /* need to have an empty but initialized param array for some reason */
2030 std::array<real, MAXFORCEPARAM> forceParam = { 0.0 };
2032 /* Get force params for normal and free energy perturbation
2033 * studies, as determined by types!
2035 InteractionOfType param(atoms, forceParam, "");
2037 std::vector<InteractionOfType>::iterator foundAParameter = bondtype[ftype].interactionTypes.end();
2038 std::vector<InteractionOfType>::iterator foundBParameter = bondtype[ftype].interactionTypes.end();
2042 defaultInteractionsOfType(ftype, bondtype, at, atypes, param, FALSE, &nparam_defA);
2043 if (foundAParameter != bondtype[ftype].interactionTypes.end())
2045 /* Copy the A-state and B-state default parameters. */
2046 GMX_ASSERT(NRFPA(ftype) + NRFPB(ftype) <= MAXFORCEPARAM,
2047 "Bonded interactions may have at most 12 parameters");
2048 gmx::ArrayRef<const real> defaultParam = foundAParameter->forceParam();
2049 for (int j = 0; (j < NRFPA(ftype) + NRFPB(ftype)); j++)
2051 param.setForceParameter(j, defaultParam[j]);
2055 else if (NRFPA(ftype) == 0)
2060 defaultInteractionsOfType(ftype, bondtype, at, atypes, param, TRUE, &nparam_defB);
2061 if (foundBParameter != bondtype[ftype].interactionTypes.end())
2063 /* Copy only the B-state default parameters */
2064 gmx::ArrayRef<const real> defaultParam = foundBParameter->forceParam();
2065 for (int j = NRFPA(ftype); (j < NRFP(ftype)); j++)
2067 param.setForceParameter(j, defaultParam[j]);
2071 else if (NRFPB(ftype) == 0)
2076 else if (ftype == F_LJ14)
2078 bFoundA = default_nb_params(ftype, bondtype, at, ¶m, 0, FALSE, bGenPairs);
2079 bFoundB = default_nb_params(ftype, bondtype, at, ¶m, 0, TRUE, bGenPairs);
2081 else if (ftype == F_LJC14_Q)
2083 /* Fill in the A-state charges as default parameters */
2084 param.setForceParameter(0, fudgeQQ);
2085 param.setForceParameter(1, at->atom[param.ai()].q);
2086 param.setForceParameter(2, at->atom[param.aj()].q);
2087 /* The default LJ parameters are the standard 1-4 parameters */
2088 bFoundA = default_nb_params(F_LJ14, bondtype, at, ¶m, 3, FALSE, bGenPairs);
2091 else if (ftype == F_LJC_PAIRS_NB)
2093 /* Defaults are not supported here */
2099 gmx_incons("Unknown function type in push_bond");
2102 if (nread > nral_fmt)
2104 /* Manually specified parameters - in this case we discard multiple torsion info! */
2106 strcpy(format, asformat[nral_fmt - 1]);
2107 strcat(format, ccformat);
2109 nread = sscanf(line,
2125 if ((nread == NRFPA(ftype)) && (NRFPB(ftype) != 0))
2127 /* We only have to issue a warning if these atoms are perturbed! */
2129 gmx::ArrayRef<const int> paramAtoms = param.atoms();
2130 for (int j = 0; (j < nral); j++)
2132 bPert = bPert || PERTURBED(at->atom[paramAtoms[j]]);
2135 if (bPert && *bWarn_copy_A_B)
2137 auto message = gmx::formatString(
2138 "Some parameters for bonded interaction involving "
2139 "perturbed atoms are specified explicitly in "
2140 "state A, but not B - copying A to B");
2141 warning(wi, message);
2142 *bWarn_copy_A_B = FALSE;
2145 /* If only the A parameters were specified, copy them to the B state */
2146 /* The B-state parameters correspond to the first nrfpB
2147 * A-state parameters.
2149 for (int j = 0; (j < NRFPB(ftype)); j++)
2151 cc[nread++] = cc[j];
2155 /* If nread was 0 or EOF, no parameters were read => use defaults.
2156 * If nread was nrfpA we copied above so nread=nrfp.
2157 * If nread was nrfp we are cool.
2158 * For F_LJC14_Q we allow supplying fudgeQQ only.
2159 * Anything else is an error!
2161 if ((nread != 0) && (nread != EOF) && (nread != NRFP(ftype)) && !(ftype == F_LJC14_Q && nread == 1))
2163 auto message = gmx::formatString(
2164 "Incorrect number of parameters - found %d, expected %d "
2165 "or %d for %s (after the function type).",
2169 interaction_function[ftype].longname);
2170 warning_error_and_exit(wi, message, FARGS);
2173 for (int j = 0; (j < nread); j++)
2175 param.setForceParameter(j, cc[j]);
2177 /* Check whether we have to use the defaults */
2178 if (nread == NRFP(ftype))
2187 /* nread now holds the number of force parameters read! */
2192 /* When we have multiple terms it would be very dangerous to allow perturbations to a different atom type! */
2193 if (ftype == F_PDIHS)
2195 if ((nparam_defA != nparam_defB)
2196 || ((nparam_defA > 1 || nparam_defB > 1) && (foundAParameter != foundBParameter)))
2198 auto message = gmx::formatString(
2199 "Cannot automatically perturb a torsion with multiple terms to different "
2201 "Please specify perturbed parameters manually for this torsion in your "
2203 warning_error(wi, message);
2207 if (nread > 0 && nread < NRFPA(ftype))
2209 /* Issue an error, do not use defaults */
2210 auto message = gmx::formatString(
2211 "Not enough parameters, there should be at least %d (or 0 for defaults)", NRFPA(ftype));
2212 warning_error(wi, message);
2215 if (nread == 0 || nread == EOF)
2219 if (interaction_function[ftype].flags & IF_VSITE)
2221 for (int j = 0; j < MAXFORCEPARAM; j++)
2223 param.setForceParameter(j, NOTSET);
2227 /* flag to swap parity of vsi te construction */
2228 param.setForceParameter(1, -1);
2236 "NOTE: No default %s types, using zeroes\n",
2237 interaction_function[ftype].longname);
2241 auto message = gmx::formatString("No default %s types",
2242 interaction_function[ftype].longname);
2243 warning_error(wi, message);
2253 case F_VSITE3FAD: param.setForceParameter(0, 360 - param.c0()); break;
2254 case F_VSITE3OUT: param.setForceParameter(2, -param.c2()); break;
2260 /* We only have to issue a warning if these atoms are perturbed! */
2262 gmx::ArrayRef<const int> paramAtoms = param.atoms();
2263 for (int j = 0; (j < nral); j++)
2265 bPert = bPert || PERTURBED(at->atom[paramAtoms[j]]);
2270 auto message = gmx::formatString(
2271 "No default %s types for perturbed atoms, "
2272 "using normal values",
2273 interaction_function[ftype].longname);
2274 warning(wi, message);
2280 gmx::ArrayRef<const real> paramValue = param.forceParam();
2281 if ((ftype == F_PDIHS || ftype == F_ANGRES || ftype == F_ANGRESZ) && paramValue[5] != paramValue[2])
2283 auto message = gmx::formatString("%s multiplicity can not be perturbed %f!=%f",
2284 interaction_function[ftype].longname,
2287 warning_error_and_exit(wi, message, FARGS);
2290 if (IS_TABULATED(ftype) && param.c0() != param.c2())
2292 auto message = gmx::formatString("%s table number can not be perturbed %d!=%d",
2293 interaction_function[ftype].longname,
2294 gmx::roundToInt(param.c0()),
2295 gmx::roundToInt(param.c0()));
2296 warning_error_and_exit(wi, message, FARGS);
2299 /* Dont add R-B dihedrals where all parameters are zero (no interaction) */
2300 if (ftype == F_RBDIHS)
2304 for (int i = 0; i < NRFP(ftype); i++)
2306 if (paramValue[i] != 0.0)
2317 /* Put the values in the appropriate arrays */
2318 add_param_to_list(&bond[ftype], param);
2320 /* Push additional torsions from FF for ftype==9 if we have them.
2321 * We have already checked that the A/B states do not differ in this case,
2322 * so we do not have to double-check that again, or the vsite stuff.
2323 * In addition, those torsions cannot be automatically perturbed.
2325 if (bDef && ftype == F_PDIHS)
2327 for (int i = 1; i < nparam_defA; i++)
2329 /* Advance pointer! */
2330 foundAParameter += 2;
2331 gmx::ArrayRef<const real> forceParam = foundAParameter->forceParam();
2332 for (int j = 0; j < (NRFPA(ftype) + NRFPB(ftype)); j++)
2334 param.setForceParameter(j, forceParam[j]);
2336 /* And push the next term for this torsion */
2337 add_param_to_list(&bond[ftype], param);
2342 void push_cmap(Directive d,
2343 gmx::ArrayRef<InteractionsOfType> bondtype,
2344 gmx::ArrayRef<InteractionsOfType> bond,
2346 PreprocessingAtomTypes* atypes,
2350 const char* aaformat[MAXATOMLIST + 1] = {
2351 "%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"
2354 int ftype, nral, nread, ncmap_params;
2356 int aa[MAXATOMLIST + 1];
2359 ftype = ifunc_index(d, 1);
2363 nread = sscanf(line, aaformat[nral - 1], &aa[0], &aa[1], &aa[2], &aa[3], &aa[4], &aa[5]);
2370 else if (nread == nral)
2372 ftype = ifunc_index(d, 1);
2375 /* Check for double atoms and atoms out of bounds */
2376 for (int i = 0; i < nral; i++)
2378 if (aa[i] < 1 || aa[i] > at->nr)
2380 auto message = gmx::formatString(
2381 "Atom index (%d) in %s out of bounds (1-%d).\n"
2382 "This probably means that you have inserted topology section \"%s\"\n"
2383 "in a part belonging to a different molecule than you intended to.\n"
2384 "In that case move the \"%s\" section to the right molecule.",
2390 warning_error_and_exit(wi, message, FARGS);
2393 for (int j = i + 1; (j < nral); j++)
2397 auto message = gmx::formatString("Duplicate atom index (%d) in %s", aa[i], dir2str(d));
2398 warning_error(wi, message);
2403 /* default force parameters */
2404 std::vector<int> atoms;
2405 for (int j = 0; (j < nral); j++)
2407 atoms.emplace_back(aa[j] - 1);
2409 std::array<real, MAXFORCEPARAM> forceParam = { 0.0 };
2410 InteractionOfType param(atoms, forceParam, "");
2411 /* Get the cmap type for this cmap angle */
2412 bFound = default_cmap_params(bondtype, at, atypes, ¶m, FALSE, &cmap_type, &ncmap_params, wi);
2414 /* We want exactly one parameter (the cmap type in state A (currently no state B) back */
2415 if (bFound && ncmap_params == 1)
2417 /* Put the values in the appropriate arrays */
2418 param.setForceParameter(0, cmap_type);
2419 add_param_to_list(&bond[ftype], param);
2423 /* This is essentially the same check as in default_cmap_params() done one more time */
2425 gmx::formatString("Unable to assign a cmap type to torsion %d %d %d %d and %d\n",
2431 warning_error_and_exit(wi, message, FARGS);
2436 void push_vsitesn(Directive d, gmx::ArrayRef<InteractionsOfType> bond, t_atoms* at, char* line, warninp* wi)
2439 int type, ftype, n, ret, nj, a;
2441 double *weight = nullptr, weight_tot;
2443 std::array<real, MAXFORCEPARAM> forceParam = { 0.0 };
2445 ret = sscanf(ptr, "%d%n", &a, &n);
2449 auto message = gmx::formatString("Expected an atom index in section \"%s\"", dir2str(d));
2450 warning_error_and_exit(wi, message, FARGS);
2453 sscanf(ptr, "%d%n", &type, &n);
2455 ftype = ifunc_index(d, type);
2456 int firstAtom = a - 1;
2462 ret = sscanf(ptr, "%d%n", &a, &n);
2468 srenew(atc, nj + 20);
2469 srenew(weight, nj + 20);
2474 case 1: weight[nj] = 1; break;
2476 /* Here we use the A-state mass as a parameter.
2477 * Note that the B-state mass has no influence.
2479 weight[nj] = at->atom[atc[nj]].m;
2483 ret = sscanf(ptr, "%lf%n", &(weight[nj]), &n);
2487 auto message = gmx::formatString(
2488 "No weight or negative weight found for vsiten "
2489 "constructing atom %d (atom index %d)",
2492 warning_error_and_exit(wi, message, FARGS);
2496 auto message = gmx::formatString("Unknown vsiten type %d", type);
2497 warning_error_and_exit(wi, message, FARGS);
2499 weight_tot += weight[nj];
2507 gmx::formatString("Expected more than one atom index in section \"%s\"", dir2str(d));
2508 warning_error_and_exit(wi, message, FARGS);
2511 if (weight_tot == 0)
2513 warning_error_and_exit(wi, "The total mass of the construting atoms is zero", FARGS);
2516 for (int j = 0; j < nj; j++)
2518 std::vector<int> atoms = { firstAtom, atc[j] };
2520 forceParam[1] = weight[j] / weight_tot;
2521 /* Put the values in the appropriate arrays */
2522 add_param_to_list(&bond[ftype], InteractionOfType(atoms, forceParam));
2529 void push_mol(gmx::ArrayRef<MoleculeInformation> mols, char* pline, int* whichmol, int* nrcopies, warninp* wi)
2533 if (sscanf(pline, "%s%d", type, nrcopies) != 2)
2539 /* Search moleculename.
2540 * Here we originally only did case insensitive matching. But because
2541 * some PDB files can have many chains and use case to generate more
2542 * chain-identifiers, which in turn end up in our moleculetype name,
2543 * we added support for case-sensitivity.
2550 for (const auto& mol : mols)
2552 if (strcmp(type, *(mol.name)) == 0)
2557 if (gmx_strcasecmp(type, *(mol.name)) == 0)
2567 // select the case sensitive match
2568 *whichmol = matchcs;
2572 // avoid matching case-insensitive when we have multiple matches
2575 auto message = gmx::formatString(
2576 "For moleculetype '%s' in [ system ] %d case insensitive "
2577 "matches, but %d case sensitive matches were found. Check "
2578 "the case of the characters in the moleculetypes.",
2582 warning_error_and_exit(wi, message, FARGS);
2586 // select the unique case insensitive match
2587 *whichmol = matchci;
2591 auto message = gmx::formatString("No such moleculetype %s", type);
2592 warning_error_and_exit(wi, message, FARGS);
2597 void push_excl(char* line, gmx::ArrayRef<gmx::ExclusionBlock> b2, warninp* wi)
2601 char base[STRLEN], format[STRLEN];
2603 if (sscanf(line, "%d", &i) == 0)
2608 if ((1 <= i) && (i <= b2.ssize()))
2616 strcpy(base, "%*d");
2619 strcpy(format, base);
2620 strcat(format, "%d");
2621 n = sscanf(line, format, &j);
2624 if ((1 <= j) && (j <= b2.ssize()))
2627 b2[i].atomNumber.push_back(j);
2628 /* also add the reverse exclusion! */
2629 b2[j].atomNumber.push_back(i);
2630 strcat(base, "%*d");
2634 auto message = gmx::formatString("Invalid Atomnr j: %d, b2->nr: %zu\n", j, b2.size());
2635 warning_error_and_exit(wi, message, FARGS);
2641 int add_atomtype_decoupled(t_symtab* symtab, PreprocessingAtomTypes* at, t_nbparam*** nbparam, t_nbparam*** pair)
2646 /* Define an atom type with all parameters set to zero (no interactions) */
2649 /* Type for decoupled atoms could be anything,
2650 * this should be changed automatically later when required.
2652 atom.ptype = eptAtom;
2654 std::array<real, MAXFORCEPARAM> forceParam = { 0.0 };
2655 nr = at->addType(symtab, atom, "decoupled", InteractionOfType({}, forceParam, ""), -1, 0);
2657 /* Add space in the non-bonded parameters matrix */
2658 realloc_nb_params(at, nbparam, pair);
2663 static void convert_pairs_to_pairsQ(gmx::ArrayRef<InteractionsOfType> interactions, real fudgeQQ, t_atoms* atoms)
2665 /* Add the pair list to the pairQ list */
2666 std::vector<InteractionOfType> paramnew;
2668 gmx::ArrayRef<const InteractionOfType> paramp1 = interactions[F_LJ14].interactionTypes;
2669 gmx::ArrayRef<const InteractionOfType> paramp2 = interactions[F_LJC14_Q].interactionTypes;
2671 /* Fill in the new F_LJC14_Q array with the old one. NOTE:
2672 it may be possible to just ADD the converted F_LJ14 array
2673 to the old F_LJC14_Q array, but since we have to create
2674 a new sized memory structure, better just to deep copy it all.
2678 for (const auto& param : paramp2)
2680 paramnew.emplace_back(param);
2683 for (const auto& param : paramp1)
2685 std::vector<real> forceParam = {
2686 fudgeQQ, atoms->atom[param.ai()].q, atoms->atom[param.aj()].q, param.c0(), param.c1()
2688 paramnew.emplace_back(InteractionOfType(param.atoms(), forceParam, ""));
2691 /* now assign the new data to the F_LJC14_Q structure */
2692 interactions[F_LJC14_Q].interactionTypes = paramnew;
2694 /* Empty the LJ14 pairlist */
2695 interactions[F_LJ14].interactionTypes.clear();
2698 static void generate_LJCpairsNB(MoleculeInformation* mol, int nb_funct, InteractionsOfType* nbp, warninp* wi)
2704 atom = mol->atoms.atom;
2706 ntype = static_cast<int>(std::sqrt(static_cast<double>(nbp->size())));
2707 GMX_ASSERT(ntype * ntype == gmx::ssize(*nbp),
2708 "Number of pairs of generated non-bonded parameters should be a perfect square");
2710 /* Add a pair interaction for all non-excluded atom pairs */
2711 const auto& excls = mol->excls;
2712 for (int i = 0; i < n; i++)
2714 for (int j = i + 1; j < n; j++)
2716 bool pairIsExcluded = false;
2717 for (const int atomK : excls[i])
2721 pairIsExcluded = true;
2724 if (!pairIsExcluded)
2726 if (nb_funct != F_LJ)
2728 auto message = gmx::formatString(
2729 "Can only generate non-bonded pair interactions "
2730 "for Van der Waals type Lennard-Jones");
2731 warning_error_and_exit(wi, message, FARGS);
2733 std::vector<int> atoms = { i, j };
2734 std::vector<real> forceParam = {
2737 nbp->interactionTypes[ntype * atom[i].type + atom[j].type].c0(),
2738 nbp->interactionTypes[ntype * atom[i].type + atom[j].type].c1()
2740 add_param_to_list(&mol->interactions[F_LJC_PAIRS_NB], InteractionOfType(atoms, forceParam));
2746 static void set_excl_all(gmx::ListOfLists<int>* excl)
2748 /* Get rid of the current exclusions and exclude all atom pairs */
2749 const int numAtoms = excl->ssize();
2750 std::vector<int> exclusionsForAtom(numAtoms);
2751 for (int i = 0; i < numAtoms; i++)
2753 exclusionsForAtom[i] = i;
2756 for (int i = 0; i < numAtoms; i++)
2758 excl->pushBack(exclusionsForAtom);
2762 static void decouple_atoms(t_atoms* atoms,
2763 int atomtype_decouple,
2766 const char* mol_name,
2771 for (i = 0; i < atoms->nr; i++)
2775 atom = &atoms->atom[i];
2777 if (atom->qB != atom->q || atom->typeB != atom->type)
2779 auto message = gmx::formatString(
2780 "Atom %d in molecule type '%s' has different A and B state "
2781 "charges and/or atom types set in the topology file as well "
2782 "as through the mdp option '%s'. You can not use both "
2783 "these methods simultaneously.",
2787 warning_error_and_exit(wi, message, FARGS);
2790 if (couple_lam0 == ecouplamNONE || couple_lam0 == ecouplamVDW)
2794 if (couple_lam0 == ecouplamNONE || couple_lam0 == ecouplamQ)
2796 atom->type = atomtype_decouple;
2798 if (couple_lam1 == ecouplamNONE || couple_lam1 == ecouplamVDW)
2802 if (couple_lam1 == ecouplamNONE || couple_lam1 == ecouplamQ)
2804 atom->typeB = atomtype_decouple;
2809 void convert_moltype_couple(MoleculeInformation* mol,
2810 int atomtype_decouple,
2816 InteractionsOfType* nbp,
2819 convert_pairs_to_pairsQ(mol->interactions, fudgeQQ, &mol->atoms);
2822 generate_LJCpairsNB(mol, nb_funct, nbp, wi);
2823 set_excl_all(&mol->excls);
2825 decouple_atoms(&mol->atoms, atomtype_decouple, couple_lam0, couple_lam1, *mol->name, wi);