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.
51 #include "gromacs/fileio/warninp.h"
52 #include "gromacs/gmxpreprocess/gpp_atomtype.h"
53 #include "gromacs/gmxpreprocess/gpp_bond_atomtype.h"
54 #include "gromacs/gmxpreprocess/grompp_impl.h"
55 #include "gromacs/gmxpreprocess/notset.h"
56 #include "gromacs/gmxpreprocess/readir.h"
57 #include "gromacs/gmxpreprocess/topdirs.h"
58 #include "gromacs/gmxpreprocess/toputil.h"
59 #include "gromacs/math/functions.h"
60 #include "gromacs/mdtypes/md_enums.h"
61 #include "gromacs/topology/exclusionblocks.h"
62 #include "gromacs/topology/ifunc.h"
63 #include "gromacs/topology/symtab.h"
64 #include "gromacs/utility/arrayref.h"
65 #include "gromacs/utility/cstringutil.h"
66 #include "gromacs/utility/enumerationhelpers.h"
67 #include "gromacs/utility/fatalerror.h"
68 #include "gromacs/utility/gmxassert.h"
69 #include "gromacs/utility/smalloc.h"
70 #include "gromacs/utility/stringtoenumvalueconverter.h"
71 #include "gromacs/utility/stringutil.h"
73 void generate_nbparams(CombinationRule comb,
75 InteractionsOfType* interactions,
76 PreprocessingAtomTypes* atypes,
79 constexpr int c_nrfp2 = 2;
82 real c, bi, bj, ci, cj, ci0, ci1, ci2, cj0, cj1, cj2;
84 /* Lean mean shortcuts */
87 interactions->interactionTypes.clear();
89 std::array<real, MAXFORCEPARAM> forceParam = { NOTSET };
90 /* Fill the matrix with force parameters */
91 // Prefetch the parameters to improve cache hits and avoid dereference and call overhead
92 std::vector<std::pair<real, real>> cPrefetch;
93 cPrefetch.reserve(nr);
94 for (int i = 0; i < nr; i++)
96 cPrefetch.emplace_back(*atypes->atomNonBondedParamFromAtomType(i, 0),
97 *atypes->atomNonBondedParamFromAtomType(i, 1));
99 interactions->interactionTypes.reserve(nr * nr);
105 case CombinationRule::Geometric:
106 // Geometric combination rules, c6 and c12 are independent
107 GMX_RELEASE_ASSERT(nrfp == c_nrfp2, "nfrp should be 2");
108 for (int i = 0; (i < nr); i++)
110 for (int j = 0; (j < nr); j++)
112 for (int nf = 0; (nf < c_nrfp2); nf++)
114 ci = (nf == 0 ? cPrefetch[i].first : cPrefetch[i].second);
115 cj = (nf == 0 ? cPrefetch[j].first : cPrefetch[j].second);
116 c = std::sqrt(ci * cj);
119 interactions->interactionTypes.emplace_back(gmx::ArrayRef<const int>{},
125 case CombinationRule::Arithmetic:
126 /* c0 and c1 are sigma and epsilon */
127 for (int i = 0; (i < nr); i++)
129 for (int j = 0; (j < nr); j++)
131 ci0 = cPrefetch[i].first;
132 cj0 = cPrefetch[j].first;
133 ci1 = cPrefetch[i].second;
134 cj1 = cPrefetch[j].second;
135 forceParam[0] = (fabs(ci0) + fabs(cj0)) * 0.5;
136 /* Negative sigma signals that c6 should be set to zero later,
137 * so we need to propagate that through the combination rules.
139 if (ci0 < 0 || cj0 < 0)
143 forceParam[1] = std::sqrt(ci1 * cj1);
144 interactions->interactionTypes.emplace_back(gmx::ArrayRef<const int>{},
150 case CombinationRule::GeomSigEps:
151 /* c0 and c1 are sigma and epsilon */
152 for (int i = 0; (i < nr); i++)
154 for (int j = 0; (j < nr); j++)
156 ci0 = cPrefetch[i].first;
157 cj0 = cPrefetch[j].first;
158 ci1 = cPrefetch[i].second;
159 cj1 = cPrefetch[j].second;
160 forceParam[0] = std::sqrt(std::fabs(ci0 * cj0));
161 /* Negative sigma signals that c6 should be set to zero later,
162 * so we need to propagate that through the combination rules.
164 if (ci0 < 0 || cj0 < 0)
168 forceParam[1] = std::sqrt(ci1 * cj1);
169 interactions->interactionTypes.emplace_back(gmx::ArrayRef<const int>{},
177 gmx::formatString("No such combination rule %s", enumValueToString(comb));
178 warning_error_and_exit(wi, message, FARGS);
183 /* Buckingham rules */
184 for (int i = 0; (i < nr); i++)
186 for (int j = 0; (j < nr); j++)
188 ci0 = cPrefetch[i].first;
189 cj0 = cPrefetch[j].first;
190 ci2 = *atypes->atomNonBondedParamFromAtomType(i, 2);
191 cj2 = *atypes->atomNonBondedParamFromAtomType(j, 2);
192 bi = cPrefetch[i].second;
193 bj = cPrefetch[j].second;
194 forceParam[0] = std::sqrt(ci0 * cj0);
195 if ((bi == 0) || (bj == 0))
201 forceParam[1] = 2.0 / (1 / bi + 1 / bj);
203 forceParam[2] = std::sqrt(ci2 * cj2);
204 interactions->interactionTypes.emplace_back(gmx::ArrayRef<const int>{}, forceParam);
210 auto message = gmx::formatString("Invalid nonbonded type %s",
211 interaction_function[ftype].longname);
212 warning_error(wi, message);
216 /*! \brief Used to temporarily store the explicit non-bonded parameter
217 * combinations, which will be copied to InteractionsOfType. */
220 //! Has this combination been set.
222 //! The non-bonded parameters
226 static void realloc_nb_params(PreprocessingAtomTypes* atypes, t_nbparam*** nbparam, t_nbparam*** pair)
228 /* Add space in the non-bonded parameters matrix */
229 int atnr = atypes->size();
230 srenew(*nbparam, atnr);
231 snew((*nbparam)[atnr - 1], atnr);
235 snew((*pair)[atnr - 1], atnr);
239 int copy_nbparams(t_nbparam** param, int ftype, InteractionsOfType* interactions, int nr)
246 for (int i = 0; i < nr; i++)
248 for (int j = 0; j <= i; j++)
250 GMX_RELEASE_ASSERT(param, "Must have valid parameters");
251 if (param[i][j].bSet)
253 for (int f = 0; f < nrfp; f++)
255 interactions->interactionTypes[nr * i + j].setForceParameter(f, param[i][j].c[f]);
256 interactions->interactionTypes[nr * j + i].setForceParameter(f, param[i][j].c[f]);
266 void free_nbparam(t_nbparam** param, int nr)
270 GMX_RELEASE_ASSERT(param, "Must have valid parameters");
271 for (i = 0; i < nr; i++)
273 GMX_RELEASE_ASSERT(param[i], "Must have valid parameters");
279 static void copy_B_from_A(int ftype, double* c)
283 nrfpA = NRFPA(ftype);
284 nrfpB = NRFPB(ftype);
286 /* Copy the B parameters from the first nrfpB A parameters */
287 for (i = 0; (i < nrfpB); i++)
293 //! Local definition that supersedes the central one, as we only want the leading letter
294 static const char* enumValueToLetterAsString(ParticleType enumValue)
296 static constexpr gmx::EnumerationArray<ParticleType, const char*> particleTypeLetters = {
297 "A", "N", "S", "B", "V"
299 return particleTypeLetters[enumValue];
302 void push_at(t_symtab* symtab,
303 PreprocessingAtomTypes* at,
304 PreprocessingBondAtomType* bondAtomType,
307 t_nbparam*** nbparam,
311 int nfields, nfp0 = -1;
313 char type[STRLEN], btype[STRLEN], ptype[STRLEN];
315 double c[MAXFORCEPARAM];
316 char tmpfield[12][100]; /* Max 12 fields of width 100 */
319 bool have_atomic_number;
320 bool have_bonded_type;
324 /* First assign input line to temporary array */
325 nfields = sscanf(line,
326 "%s%s%s%s%s%s%s%s%s%s%s%s",
340 /* Comments on optional fields in the atomtypes section:
342 * The force field format is getting a bit old. For OPLS-AA we needed
343 * to add a special bonded atomtype, and for Gerrit Groenhofs QM/MM stuff
344 * we also needed the atomic numbers.
345 * To avoid making all old or user-generated force fields unusable we
346 * have introduced both these quantities as optional columns, and do some
347 * acrobatics to check whether they are present or not.
348 * This will all look much nicer when we switch to XML... sigh.
350 * Field 0 (mandatory) is the nonbonded type name. (string)
351 * Field 1 (optional) is the bonded type (string)
352 * Field 2 (optional) is the atomic number (int)
353 * Field 3 (mandatory) is the mass (numerical)
354 * Field 4 (mandatory) is the charge (numerical)
355 * Field 5 (mandatory) is the particle type (single character)
356 * This is followed by a number of nonbonded parameters.
358 * The safest way to identify the format is the particle type field.
360 * So, here is what we do:
362 * A. Read in the first six fields as strings
363 * B. If field 3 (starting from 0) is a single char, we have neither
364 * bonded_type or atomic numbers.
365 * C. If field 5 is a single char we have both.
366 * D. If field 4 is a single char we check field 1. If this begins with
367 * an alphabetical character we have bonded types, otherwise atomic numbers.
376 if ((strlen(tmpfield[5]) == 1) && isalpha(tmpfield[5][0]))
378 have_bonded_type = TRUE;
379 have_atomic_number = TRUE;
381 else if ((strlen(tmpfield[3]) == 1) && isalpha(tmpfield[3][0]))
383 have_bonded_type = FALSE;
384 have_atomic_number = FALSE;
388 // Attempt parsing field 1 to integer. If successful, *end == '\0'
390 strtol(tmpfield[1], &end, 10);
392 // If conversion fails, we do not have an atomic number but a bonded type
393 have_bonded_type = (*end != 0);
394 have_atomic_number = !have_bonded_type;
397 /* optional fields */
406 if (have_atomic_number)
408 if (have_bonded_type)
411 line, "%s%s%d%lf%lf%s%lf%lf", type, btype, &atomnr, &m, &q, ptype, &c[0], &c[1]);
420 /* have_atomic_number && !have_bonded_type */
421 nread = sscanf(line, "%s%d%lf%lf%s%lf%lf", type, &atomnr, &m, &q, ptype, &c[0], &c[1]);
431 if (have_bonded_type)
433 /* !have_atomic_number && have_bonded_type */
434 nread = sscanf(line, "%s%s%lf%lf%s%lf%lf", type, btype, &m, &q, ptype, &c[0], &c[1]);
443 /* !have_atomic_number && !have_bonded_type */
444 nread = sscanf(line, "%s%lf%lf%s%lf%lf", type, &m, &q, ptype, &c[0], &c[1]);
453 if (!have_bonded_type)
458 if (!have_atomic_number)
468 if (have_atomic_number)
470 if (have_bonded_type)
473 line, "%s%s%d%lf%lf%s%lf%lf%lf", type, btype, &atomnr, &m, &q, ptype, &c[0], &c[1], &c[2]);
482 /* have_atomic_number && !have_bonded_type */
484 line, "%s%d%lf%lf%s%lf%lf%lf", type, &atomnr, &m, &q, ptype, &c[0], &c[1], &c[2]);
494 if (have_bonded_type)
496 /* !have_atomic_number && have_bonded_type */
498 line, "%s%s%lf%lf%s%lf%lf%lf", type, btype, &m, &q, ptype, &c[0], &c[1], &c[2]);
507 /* !have_atomic_number && !have_bonded_type */
508 nread = sscanf(line, "%s%lf%lf%s%lf%lf%lf", type, &m, &q, ptype, &c[0], &c[1], &c[2]);
517 if (!have_bonded_type)
522 if (!have_atomic_number)
530 auto message = gmx::formatString("Invalid function type %d in push_at", nb_funct);
531 warning_error_and_exit(wi, message, FARGS);
533 for (int j = nfp0; (j < MAXFORCEPARAM); j++)
537 std::array<real, MAXFORCEPARAM> forceParam;
539 if (strlen(type) == 1 && isdigit(type[0]))
541 warning_error_and_exit(wi, "Atom type names can't be single digits.", FARGS);
544 if (strlen(btype) == 1 && isdigit(btype[0]))
546 warning_error_and_exit(wi, "Bond atom type names can't be single digits.", FARGS);
549 /* Hack to read old topologies */
550 if (gmx_strcasecmp(ptype, "D") == 0)
554 static const gmx::StringToEnumValueConverter<ParticleType, enumValueToLetterAsString, gmx::StringCompareType::CaseInsensitive, gmx::StripStrings::No>
555 s_stringToParticleType;
556 std::optional<ParticleType> pt = s_stringToParticleType.valueFrom(ptype);
559 auto message = gmx::formatString("Invalid particle type %s", ptype);
560 warning_error_and_exit(wi, message, FARGS);
565 atom->ptype = pt.value();
566 for (int i = 0; i < MAXFORCEPARAM; i++)
568 forceParam[i] = c[i];
571 InteractionOfType interactionType({}, forceParam, "");
573 auto batype_nr = bondAtomType->addBondAtomType(symtab, btype);
575 auto atomType = at->atomTypeFromName(type);
576 if (atomType.has_value())
578 auto message = gmx::formatString(
579 "Atomtype %s was defined previously (e.g. in the forcefield files), "
580 "and has now been defined again. This could happen e.g. if you would "
581 "use a self-contained molecule .itp file that duplicates or replaces "
582 "the contents of the standard force-field files. You should check "
583 "the contents of your files and remove such repetition. If you know "
584 "you should override the previous definition, then you could choose "
585 "to suppress this warning with -maxwarn.",
587 warning(wi, message);
588 auto newAtomType = at->setType(*atomType, symtab, *atom, type, interactionType, batype_nr, atomnr);
589 if (!newAtomType.has_value())
591 auto message = gmx::formatString("Replacing atomtype %s failed", type);
592 warning_error_and_exit(wi, message, FARGS);
597 at->addType(symtab, *atom, type, interactionType, batype_nr, atomnr);
598 /* Add space in the non-bonded parameters matrix */
599 realloc_nb_params(at, nbparam, pair);
604 //! Return whether the contents of \c a and \c b are the same, considering also reversed order.
606 static bool equalEitherForwardOrBackward(gmx::ArrayRef<const T> a, gmx::ArrayRef<const T> b)
608 return (std::equal(a.begin(), a.end(), b.begin()) || std::equal(a.begin(), a.end(), b.rbegin()));
611 static void push_bondtype(InteractionsOfType* bt,
612 const InteractionOfType& b,
620 int nrfp = NRFP(ftype);
622 /* If bAllowRepeat is TRUE, we allow multiple entries as long as they
623 are on directly _adjacent_ lines.
626 /* First check if our atomtypes are _identical_ (not reversed) to the previous
627 entry. If they are not identical we search for earlier duplicates. If they are
628 we can skip it, since we already searched for the first line
632 bool isContinuationOfBlock = false;
633 if (bAllowRepeat && nr > 1)
635 isContinuationOfBlock = true;
636 gmx::ArrayRef<const int> newParAtom = b.atoms();
637 gmx::ArrayRef<const int> sysParAtom = bt->interactionTypes[nr - 2].atoms();
638 for (int j = 0; j < nral; j++)
640 if (newParAtom[j] != sysParAtom[j])
642 isContinuationOfBlock = false;
647 /* Search for earlier duplicates if this entry was not a continuation
648 from the previous line.
650 bool addBondType = true;
651 bool haveWarned = false;
652 bool haveErrored = false;
653 for (int i = 0; (i < nr); i++)
655 gmx::ArrayRef<const int> bParams = b.atoms();
656 gmx::ArrayRef<const int> testParams = bt->interactionTypes[i].atoms();
657 GMX_RELEASE_ASSERT(bParams.size() == testParams.size(),
658 "Number of atoms needs to be the same between parameters");
659 if (equalEitherForwardOrBackward(bParams, testParams))
661 GMX_ASSERT(nrfp <= MAXFORCEPARAM,
662 "This is ensured in other places, but we need this assert to keep the clang "
664 const bool identicalParameters = std::equal(bt->interactionTypes[i].forceParam().begin(),
665 bt->interactionTypes[i].forceParam().begin() + nrfp,
666 b.forceParam().begin());
668 if (!bAllowRepeat || identicalParameters)
673 if (!identicalParameters)
677 /* With dihedral type 9 we only allow for repeating
678 * of the same parameters with blocks with 1 entry.
679 * Allowing overriding is too complex to check.
681 if (!isContinuationOfBlock && !haveErrored)
684 "Encountered a second block of parameters for dihedral "
685 "type 9 for the same atoms, with either different parameters "
686 "and/or the first block has multiple lines. This is not "
691 else if (!haveWarned)
693 auto message = gmx::formatString(
694 "Bondtype %s was defined previously (e.g. in the forcefield files), "
695 "and has now been defined again. This could happen e.g. if you would "
696 "use a self-contained molecule .itp file that duplicates or replaces "
697 "the contents of the standard force-field files. You should check "
698 "the contents of your files and remove such repetition. If you know "
699 "you should override the previous definition, then you could choose "
700 "to suppress this warning with -maxwarn.%s",
701 interaction_function[ftype].longname,
702 (ftype == F_PDIHS) ? "\nUse dihedraltype 9 to allow several "
703 "multiplicity terms. Only consecutive "
704 "lines are combined. Non-consective lines "
705 "overwrite each other."
707 warning(wi, message);
709 fprintf(stderr, " old: ");
710 gmx::ArrayRef<const real> forceParam = bt->interactionTypes[i].forceParam();
711 for (int j = 0; j < nrfp; j++)
713 fprintf(stderr, " %g", forceParam[j]);
715 fprintf(stderr, " \n new: %s\n\n", line);
721 if (!identicalParameters && !bAllowRepeat)
723 /* Overwrite the parameters with the latest ones */
724 // TODO considering improving the following code by replacing with:
725 // std::copy(b->c, b->c + nrfp, bt->param[i].c);
726 gmx::ArrayRef<const real> forceParam = b.forceParam();
727 for (int j = 0; j < nrfp; j++)
729 bt->interactionTypes[i].setForceParameter(j, forceParam[j]);
737 /* fill the arrays up and down */
738 bt->interactionTypes.emplace_back(b.atoms(), b.forceParam(), b.interactionTypeName());
739 /* need to store force values because they might change below */
740 std::vector<real> forceParam(b.forceParam().begin(), b.forceParam().end());
742 /* The definitions of linear angles depend on the order of atoms,
743 * that means that for atoms i-j-k, with certain parameter a, the
744 * corresponding k-j-i angle will have parameter 1-a.
746 if (ftype == F_LINEAR_ANGLES)
748 forceParam[0] = 1 - forceParam[0];
749 forceParam[2] = 1 - forceParam[2];
751 std::vector<int> atoms;
752 gmx::ArrayRef<const int> oldAtoms = b.atoms();
753 for (auto oldAtom = oldAtoms.rbegin(); oldAtom != oldAtoms.rend(); oldAtom++)
755 atoms.emplace_back(*oldAtom);
757 bt->interactionTypes.emplace_back(atoms, forceParam, b.interactionTypeName());
761 static std::vector<int> atomTypesFromAtomNames(const PreprocessingAtomTypes* atomTypes,
762 const PreprocessingBondAtomType* bondAtomTypes,
763 gmx::ArrayRef<const char[20]> atomNames,
767 GMX_RELEASE_ASSERT(!(!atomNames.empty() && !atomTypes && !bondAtomTypes),
768 "Need to have either valid atomtypes or bondatomtypes object");
770 std::vector<int> atomTypesFromAtomNames;
771 for (const auto& name : atomNames)
773 if (atomTypes != nullptr)
775 auto atomType = atomTypes->atomTypeFromName(name);
776 if (!atomType.has_value())
778 auto message = gmx::formatString("Unknown atomtype %s\n", name);
779 warning_error_and_exit(wi, message, FARGS);
781 atomTypesFromAtomNames.emplace_back(*atomType);
783 else if (bondAtomTypes != nullptr)
785 auto bondAtomType = bondAtomTypes->bondAtomTypeFromName(name);
786 if (!bondAtomType.has_value())
788 auto message = gmx::formatString("Unknown bond_atomtype %s\n", name);
789 warning_error_and_exit(wi, message, FARGS);
791 atomTypesFromAtomNames.emplace_back(*bondAtomType);
794 return atomTypesFromAtomNames;
798 void push_bt(Directive d,
799 gmx::ArrayRef<InteractionsOfType> bt,
801 PreprocessingAtomTypes* at,
802 PreprocessingBondAtomType* bondAtomType,
806 const char* formal[MAXATOMLIST + 1] = {
807 "%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"
809 const char* formnl[MAXATOMLIST + 1] = { "%*s",
814 "%*s%*s%*s%*s%*s%*s",
815 "%*s%*s%*s%*s%*s%*s%*s" };
816 const char* formlf = "%lf%lf%lf%lf%lf%lf%lf%lf%lf%lf%lf%lf%lf";
817 int i, ft, ftype, nn, nrfp, nrfpA;
819 char alc[MAXATOMLIST + 1][20];
820 /* One force parameter more, so we can check if we read too many */
821 double c[MAXFORCEPARAM + 1];
823 if ((bondAtomType && at) || (!bondAtomType && !at))
825 gmx_incons("You should pass either bondAtomType or at to push_bt");
828 /* Make format string (nral ints+functype) */
829 if ((nn = sscanf(line, formal[nral], alc[0], alc[1], alc[2], alc[3], alc[4], alc[5])) != nral + 1)
831 auto message = gmx::formatString("Not enough atomtypes (%d instead of %d)", nn - 1, nral);
832 warning_error(wi, message);
836 ft = strtol(alc[nral], nullptr, 10);
837 ftype = ifunc_index(d, ft);
839 nrfpA = interaction_function[ftype].nrfpA;
840 strcpy(f1, formnl[nral]);
843 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]))
848 /* Copy the B-state from the A-state */
849 copy_B_from_A(ftype, c);
855 warning_error(wi, "Not enough parameters");
857 else if (nn > nrfpA && nn < nrfp)
859 warning_error(wi, "Too many parameters or not enough parameters for topology B");
863 warning_error(wi, "Too many parameters");
865 for (i = nn; (i < nrfp); i++)
871 std::vector<int> atomTypes =
872 atomTypesFromAtomNames(at, bondAtomType, gmx::arrayRefFromArray(alc, nral), wi);
873 std::array<real, MAXFORCEPARAM> forceParam;
874 for (int i = 0; (i < nrfp); i++)
876 forceParam[i] = c[i];
878 push_bondtype(&(bt[ftype]), InteractionOfType(atomTypes, forceParam), nral, ftype, FALSE, line, wi);
882 void push_dihedraltype(Directive d,
883 gmx::ArrayRef<InteractionsOfType> bt,
884 PreprocessingBondAtomType* bondAtomType,
888 const char* formal[MAXATOMLIST + 1] = {
889 "%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"
891 const char* formnl[MAXATOMLIST + 1] = { "%*s",
896 "%*s%*s%*s%*s%*s%*s",
897 "%*s%*s%*s%*s%*s%*s%*s" };
898 const char* formlf[MAXFORCEPARAM] = {
904 "%lf%lf%lf%lf%lf%lf",
905 "%lf%lf%lf%lf%lf%lf%lf",
906 "%lf%lf%lf%lf%lf%lf%lf%lf",
907 "%lf%lf%lf%lf%lf%lf%lf%lf%lf",
908 "%lf%lf%lf%lf%lf%lf%lf%lf%lf%lf",
909 "%lf%lf%lf%lf%lf%lf%lf%lf%lf%lf%lf",
910 "%lf%lf%lf%lf%lf%lf%lf%lf%lf%lf%lf%lf",
912 int i, ft, ftype, nn, nrfp, nrfpA, nral;
914 char alc[MAXATOMLIST + 1][20];
915 double c[MAXFORCEPARAM];
918 /* This routine accepts dihedraltypes defined from either 2 or 4 atoms.
920 * We first check for 2 atoms with the 3th column being an integer
921 * defining the type. If this isn't the case, we try it with 4 atoms
922 * and the 5th column defining the dihedral type.
924 nn = sscanf(line, formal[4], alc[0], alc[1], alc[2], alc[3], alc[4]);
925 if (nn >= 3 && strlen(alc[2]) == 1 && isdigit(alc[2][0]))
928 ft = strtol(alc[nral], nullptr, 10);
929 /* Move atom types around a bit and use 'X' for wildcard atoms
930 * to create a 4-atom dihedral definition with arbitrary atoms in
933 if (alc[2][0] == '2')
935 /* improper - the two atomtypes are 1,4. Use wildcards for 2,3 */
936 strcpy(alc[3], alc[1]);
937 sprintf(alc[2], "X");
938 sprintf(alc[1], "X");
939 /* alc[0] stays put */
943 /* proper - the two atomtypes are 2,3. Use wildcards for 1,4 */
944 sprintf(alc[3], "X");
945 strcpy(alc[2], alc[1]);
946 strcpy(alc[1], alc[0]);
947 sprintf(alc[0], "X");
950 else if (nn == 5 && strlen(alc[4]) == 1 && isdigit(alc[4][0]))
953 ft = strtol(alc[nral], nullptr, 10);
957 auto message = gmx::formatString(
958 "Incorrect number of atomtypes for dihedral (%d instead of 2 or 4)", nn - 1);
959 warning_error(wi, message);
965 /* Previously, we have always overwritten parameters if e.g. a torsion
966 with the same atomtypes occurs on multiple lines. However, CHARMM and
967 some other force fields specify multiple dihedrals over some bonds,
968 including cosines with multiplicity 6 and somethimes even higher.
969 Thus, they cannot be represented with Ryckaert-Bellemans terms.
970 To add support for these force fields, Dihedral type 9 is identical to
971 normal proper dihedrals, but repeated entries are allowed.
978 bAllowRepeat = FALSE;
982 ftype = ifunc_index(d, ft);
984 nrfpA = interaction_function[ftype].nrfpA;
986 strcpy(f1, formnl[nral]);
987 strcat(f1, formlf[nrfp - 1]);
989 /* Check number of parameters given */
991 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]))
996 /* Copy the B-state from the A-state */
997 copy_B_from_A(ftype, c);
1003 warning_error(wi, "Not enough parameters");
1005 else if (nn > nrfpA && nn < nrfp)
1007 warning_error(wi, "Too many parameters or not enough parameters for topology B");
1011 warning_error(wi, "Too many parameters");
1013 for (i = nn; (i < nrfp); i++)
1020 std::vector<int> atoms;
1021 std::array<real, MAXFORCEPARAM> forceParam;
1022 for (int i = 0; (i < 4); i++)
1024 if (!strcmp(alc[i], "X"))
1026 atoms.emplace_back(-1);
1030 auto atomNumber = bondAtomType->bondAtomTypeFromName(alc[i]);
1031 if (!atomNumber.has_value())
1033 auto message = gmx::formatString("Unknown bond_atomtype %s", alc[i]);
1034 warning_error_and_exit(wi, message, FARGS);
1036 atoms.emplace_back(*atomNumber);
1039 for (int i = 0; (i < nrfp); i++)
1041 forceParam[i] = c[i];
1043 /* Always use 4 atoms here, since we created two wildcard atoms
1044 * if there wasn't of them 4 already.
1046 push_bondtype(&(bt[ftype]), InteractionOfType(atoms, forceParam), 4, ftype, bAllowRepeat, line, wi);
1050 void push_nbt(Directive d, t_nbparam** nbt, PreprocessingAtomTypes* atypes, char* pline, int nb_funct, warninp* wi)
1052 /* swap the atoms */
1053 const char* form3 = "%*s%*s%*s%lf%lf%lf";
1054 const char* form4 = "%*s%*s%*s%lf%lf%lf%lf";
1055 const char* form5 = "%*s%*s%*s%lf%lf%lf%lf%lf";
1056 char a0[80], a1[80];
1057 int i, f, n, ftype, nrfp;
1063 if (sscanf(pline, "%s%s%d", a0, a1, &f) != 3)
1069 ftype = ifunc_index(d, f);
1071 if (ftype != nb_funct)
1073 auto message = gmx::formatString("Trying to add %s while the default nonbond type is %s",
1074 interaction_function[ftype].longname,
1075 interaction_function[nb_funct].longname);
1076 warning_error(wi, message);
1080 /* Get the force parameters */
1082 if (ftype == F_LJ14)
1084 n = sscanf(pline, form4, &c[0], &c[1], &c[2], &c[3]);
1090 /* When the B topology parameters are not set,
1091 * copy them from topology A
1093 GMX_ASSERT(nrfp <= 4, "LJ-14 cannot have more than 4 parameters");
1094 for (i = n; i < nrfp; i++)
1099 else if (ftype == F_LJC14_Q)
1101 n = sscanf(pline, form5, &c[0], &c[1], &c[2], &c[3], &dum);
1104 incorrect_n_param(wi);
1110 if (sscanf(pline, form3, &c[0], &c[1], &dum) != 2)
1112 incorrect_n_param(wi);
1118 if (sscanf(pline, form4, &c[0], &c[1], &c[2], &dum) != 3)
1120 incorrect_n_param(wi);
1127 gmx::formatString("Number of force parameters for nonbonded interactions is %d", nrfp);
1128 warning_error_and_exit(wi, message, FARGS);
1130 for (i = 0; (i < nrfp); i++)
1135 /* Put the parameters in the matrix */
1136 auto ai = atypes->atomTypeFromName(a0);
1137 if (!ai.has_value())
1139 auto message = gmx::formatString("Atomtype %s not found", a0);
1140 warning_error_and_exit(wi, message, FARGS);
1142 auto aj = atypes->atomTypeFromName(a1);
1143 if (!aj.has_value())
1145 auto message = gmx::formatString("Atomtype %s not found", a1);
1146 warning_error_and_exit(wi, message, FARGS);
1148 nbp = &(nbt[std::max(*ai, *aj)][std::min(*ai, *aj)]);
1153 for (i = 0; i < nrfp; i++)
1155 bId = bId && (nbp->c[i] == cr[i]);
1159 auto message = gmx::formatString(
1160 "Non-bonded parameters were defined previously (e.g. in the forcefield files), "
1161 "and have now been defined again. This could happen e.g. if you would "
1162 "use a self-contained molecule .itp file that duplicates or replaces "
1163 "the contents of the standard force-field files. You should check "
1164 "the contents of your files and remove such repetition. If you know "
1165 "you should override the previous definitions, then you could choose "
1166 "to suppress this warning with -maxwarn.");
1167 warning(wi, message);
1168 fprintf(stderr, " old:");
1169 for (i = 0; i < nrfp; i++)
1171 fprintf(stderr, " %g", nbp->c[i]);
1173 fprintf(stderr, " new\n%s\n", pline);
1177 for (i = 0; i < nrfp; i++)
1183 void push_cmaptype(Directive d,
1184 gmx::ArrayRef<InteractionsOfType> bt,
1186 PreprocessingAtomTypes* atomtypes,
1187 PreprocessingBondAtomType* bondAtomType,
1191 const char* formal = "%s%s%s%s%s%s%s%s%n";
1193 int ft, ftype, nn, nrfp, nrfpA, nrfpB;
1194 int start, nchar_consumed;
1195 int nxcmap, nycmap, ncmap, read_cmap, sl, nct;
1196 char s[20], alc[MAXATOMLIST + 2][20];
1198 /* Keep the compiler happy */
1202 GMX_ASSERT(nral == 5, "CMAP requires 5 atoms per interaction");
1204 /* Here we can only check for < 8 */
1205 if ((nn = sscanf(line, formal, alc[0], alc[1], alc[2], alc[3], alc[4], alc[5], alc[6], alc[7], &nchar_consumed))
1209 gmx::formatString("Incorrect number of atomtypes for cmap (%d instead of 5)", nn - 1);
1210 warning_error(wi, message);
1213 start += nchar_consumed;
1215 ft = strtol(alc[nral], nullptr, 10);
1216 nxcmap = strtol(alc[nral + 1], nullptr, 10);
1217 nycmap = strtol(alc[nral + 2], nullptr, 10);
1219 /* Check for equal grid spacing in x and y dims */
1220 if (nxcmap != nycmap)
1222 auto message = gmx::formatString(
1223 "Not the same grid spacing in x and y for cmap grid: x=%d, y=%d", nxcmap, nycmap);
1224 warning_error(wi, message);
1227 ncmap = nxcmap * nycmap;
1228 ftype = ifunc_index(d, ft);
1229 nrfpA = strtol(alc[6], nullptr, 10) * strtol(alc[6], nullptr, 10);
1230 nrfpB = strtol(alc[7], nullptr, 10) * strtol(alc[7], nullptr, 10);
1231 nrfp = nrfpA + nrfpB;
1233 /* Read in CMAP parameters */
1235 for (int i = 0; i < ncmap; i++)
1237 while (isspace(*(line + start + sl)))
1241 nn = sscanf(line + start + sl, " %s ", s);
1243 bt[F_CMAP].cmap.emplace_back(strtod(s, nullptr));
1252 gmx::formatString("Error in reading cmap parameter for angle %s %s %s %s %s",
1258 warning_error(wi, message);
1262 /* Check do that we got the number of parameters we expected */
1263 if (read_cmap == nrfpA)
1265 for (int i = 0; i < ncmap; i++)
1267 bt[F_CMAP].cmap.emplace_back(bt[F_CMAP].cmap[i]);
1272 if (read_cmap < nrfpA)
1274 warning_error(wi, "Not enough cmap parameters");
1276 else if (read_cmap > nrfpA && read_cmap < nrfp)
1278 warning_error(wi, "Too many cmap parameters or not enough parameters for topology B");
1280 else if (read_cmap > nrfp)
1282 warning_error(wi, "Too many cmap parameters");
1287 /* Set grid spacing and the number of grids (we assume these numbers to be the same for all
1288 * grids so we can safely assign them each time
1290 bt[F_CMAP].cmakeGridSpacing = nxcmap; /* Or nycmap, they need to be equal */
1291 bt[F_CMAP].cmapAngles++; /* Since we are incrementing here, we need to subtract later, see (*****) */
1292 nct = (nral + 1) * bt[F_CMAP].cmapAngles;
1294 for (int i = 0; (i < nral); i++)
1296 /* Assign a grid number to each cmap_type */
1297 GMX_RELEASE_ASSERT(bondAtomType != nullptr, "Need valid PreprocessingBondAtomType object");
1298 bt[F_CMAP].cmapAtomTypes.emplace_back(*bondAtomType->bondAtomTypeFromName(alc[i]));
1301 /* Assign a type number to this cmap */
1302 bt[F_CMAP].cmapAtomTypes.emplace_back(
1303 bt[F_CMAP].cmapAngles
1304 - 1); /* Since we inremented earlier, we need to subtrac here, to get the types right (****) */
1306 /* Check for the correct number of atoms (again) */
1307 if (bt[F_CMAP].nct() != nct)
1309 auto message = gmx::formatString(
1310 "Incorrect number of atom types (%d) in cmap type %d\n", nct, bt[F_CMAP].cmapAngles);
1311 warning_error(wi, message);
1313 std::vector<int> atomTypes =
1314 atomTypesFromAtomNames(atomtypes, bondAtomType, gmx::constArrayRefFromArray(alc, nral), wi);
1315 std::array<real, MAXFORCEPARAM> forceParam = { NOTSET };
1317 /* Push the bond to the bondlist */
1318 push_bondtype(&(bt[ftype]), InteractionOfType(atomTypes, forceParam), nral, ftype, FALSE, line, wi);
1322 static void push_atom_now(t_symtab* symtab,
1340 int j, resind = 0, resnr;
1344 if (((nr == 0) && (atomnr != 1)) || (nr && (atomnr != at->nr + 1)))
1346 auto message = gmx::formatString(
1347 "Atoms in the .top are not numbered consecutively from 1 (rather, "
1348 "atomnr = %d, while at->nr = %d)",
1351 warning_error_and_exit(wi, message, FARGS);
1354 j = strlen(resnumberic) - 1;
1355 if (isdigit(resnumberic[j]))
1361 ric = resnumberic[j];
1362 if (j == 0 || !isdigit(resnumberic[j - 1]))
1365 gmx::formatString("Invalid residue number '%s' for atom %d", resnumberic, atomnr);
1366 warning_error_and_exit(wi, message, FARGS);
1369 resnr = strtol(resnumberic, nullptr, 10);
1373 resind = at->atom[nr - 1].resind;
1375 if (nr == 0 || strcmp(resname, *at->resinfo[resind].name) != 0
1376 || resnr != at->resinfo[resind].nr || ric != at->resinfo[resind].ic)
1386 at->nres = resind + 1;
1387 srenew(at->resinfo, at->nres);
1388 at->resinfo[resind].name = put_symtab(symtab, resname);
1389 at->resinfo[resind].nr = resnr;
1390 at->resinfo[resind].ic = ric;
1394 resind = at->atom[at->nr - 1].resind;
1397 /* New atom instance
1398 * get new space for arrays
1400 srenew(at->atom, nr + 1);
1401 srenew(at->atomname, nr + 1);
1402 srenew(at->atomtype, nr + 1);
1403 srenew(at->atomtypeB, nr + 1);
1406 at->atom[nr].type = type;
1407 at->atom[nr].ptype = ptype;
1408 at->atom[nr].q = q0;
1409 at->atom[nr].m = m0;
1410 at->atom[nr].typeB = typeB;
1411 at->atom[nr].qB = qB;
1412 at->atom[nr].mB = mB;
1414 at->atom[nr].resind = resind;
1415 at->atom[nr].atomnumber = atomicnumber;
1416 at->atomname[nr] = put_symtab(symtab, name);
1417 at->atomtype[nr] = put_symtab(symtab, ctype);
1418 at->atomtypeB[nr] = put_symtab(symtab, ctypeB);
1422 void push_atom(t_symtab* symtab, t_atoms* at, PreprocessingAtomTypes* atypes, char* line, warninp* wi)
1424 int cgnumber, atomnr, nscan;
1425 char id[STRLEN], ctype[STRLEN], ctypeB[STRLEN], resnumberic[STRLEN], resname[STRLEN],
1426 name[STRLEN], check[STRLEN];
1427 double m, q, mb, qb;
1428 real m0, q0, mB, qB;
1430 /* Fixed parameters */
1431 if (sscanf(line, "%s%s%s%s%s%d", id, ctype, resnumberic, resname, name, &cgnumber) != 6)
1436 sscanf(id, "%d", &atomnr);
1437 auto type = atypes->atomTypeFromName(ctype);
1438 if (!type.has_value())
1440 auto message = gmx::formatString("Atomtype %s not found", ctype);
1441 warning_error_and_exit(wi, message, FARGS);
1443 ParticleType ptype = *atypes->atomParticleTypeFromAtomType(*type);
1445 /* Set default from type */
1446 q0 = *atypes->atomChargeFromAtomType(*type);
1447 m0 = *atypes->atomMassFromAtomType(*type);
1452 /* Optional parameters */
1453 nscan = sscanf(line, "%*s%*s%*s%*s%*s%*s%lf%lf%s%lf%lf%s", &q, &m, ctypeB, &qb, &mb, check);
1455 /* Nasty switch that falls thru all the way down! */
1464 typeB = atypes->atomTypeFromName(ctypeB);
1465 if (!typeB.has_value())
1467 auto message = gmx::formatString("Atomtype %s not found", ctypeB);
1468 warning_error_and_exit(wi, message, FARGS);
1470 qB = *atypes->atomChargeFromAtomType(*typeB);
1471 mB = *atypes->atomMassFromAtomType(*typeB);
1480 warning_error(wi, "Too many parameters");
1488 push_atom_now(symtab,
1491 *atypes->atomNumberFromAtomType(*type),
1501 typeB == type ? ctype : ctypeB,
1507 void push_molt(t_symtab* symtab, std::vector<MoleculeInformation>* mol, char* line, warninp* wi)
1512 if ((sscanf(line, "%s%d", type, &nrexcl)) != 2)
1514 warning_error(wi, "Expected a molecule type name and nrexcl");
1517 /* Test if this moleculetype overwrites another */
1518 const auto found = std::find_if(
1519 mol->begin(), mol->end(), [&type](const auto& m) { return strcmp(*(m.name), type) == 0; });
1520 if (found != mol->end())
1522 auto message = gmx::formatString("moleculetype %s is redefined", type);
1523 warning_error_and_exit(wi, message, FARGS);
1526 mol->emplace_back();
1527 mol->back().initMolInfo();
1529 /* Fill in the values */
1530 mol->back().name = put_symtab(symtab, type);
1531 mol->back().nrexcl = nrexcl;
1532 mol->back().excl_set = false;
1535 static bool findIfAllNBAtomsMatch(gmx::ArrayRef<const int> atomsFromParameterArray,
1536 gmx::ArrayRef<const int> atomsFromCurrentParameter,
1540 if (atomsFromParameterArray.size() != atomsFromCurrentParameter.size())
1546 for (gmx::index i = 0; i < atomsFromCurrentParameter.ssize(); i++)
1548 if (at->atom[atomsFromCurrentParameter[i]].typeB != atomsFromParameterArray[i])
1557 for (gmx::index i = 0; i < atomsFromCurrentParameter.ssize(); i++)
1559 if (at->atom[atomsFromCurrentParameter[i]].type != atomsFromParameterArray[i])
1568 static bool default_nb_params(int ftype,
1569 gmx::ArrayRef<InteractionsOfType> bt,
1571 InteractionOfType* p,
1578 InteractionOfType* pi = nullptr;
1579 int nr = bt[ftype].size();
1580 int nral = NRAL(ftype);
1581 int nrfp = interaction_function[ftype].nrfpA;
1582 int nrfpB = interaction_function[ftype].nrfpB;
1584 if ((!bB && nrfp == 0) || (bB && nrfpB == 0))
1592 /* First test the generated-pair position to save
1593 * time when we have 1000*1000 entries for e.g. OPLS...
1595 ntype = static_cast<int>(std::sqrt(static_cast<double>(nr)));
1596 GMX_ASSERT(ntype * ntype == nr,
1597 "Number of pairs of generated non-bonded parameters should be a perfect square");
1600 ti = at->atom[p->ai()].typeB;
1601 tj = at->atom[p->aj()].typeB;
1605 ti = at->atom[p->ai()].type;
1606 tj = at->atom[p->aj()].type;
1608 pi = &(bt[ftype].interactionTypes[ntype * ti + tj]);
1609 if (pi->atoms().ssize() < nral)
1611 /* not initialized yet with atom names */
1616 bFound = ((ti == pi->ai()) && (tj == pi->aj()));
1620 gmx::ArrayRef<const int> paramAtoms = p->atoms();
1621 /* Search explicitly if we didnt find it */
1624 auto foundParameter =
1625 std::find_if(bt[ftype].interactionTypes.begin(),
1626 bt[ftype].interactionTypes.end(),
1627 [¶mAtoms, &at, &bB](const auto& param) {
1628 return findIfAllNBAtomsMatch(param.atoms(), paramAtoms, at, bB);
1630 if (foundParameter != bt[ftype].interactionTypes.end())
1633 pi = &(*foundParameter);
1639 gmx::ArrayRef<const real> forceParam = pi->forceParam();
1642 if (nrfp + nrfpB > MAXFORCEPARAM)
1644 gmx_incons("Too many force parameters");
1646 for (int j = c_start; j < nrfpB; j++)
1648 p->setForceParameter(nrfp + j, forceParam[j]);
1653 for (int j = c_start; j < nrfp; j++)
1655 p->setForceParameter(j, forceParam[j]);
1661 for (int j = c_start; j < nrfp; j++)
1663 p->setForceParameter(j, 0.0);
1669 static bool default_cmap_params(gmx::ArrayRef<InteractionsOfType> bondtype,
1671 PreprocessingAtomTypes* atypes,
1672 InteractionOfType* p,
1680 bool bFound = false;
1685 /* Match the current cmap angle against the list of cmap_types */
1686 for (int i = 0; i < bondtype[F_CMAP].nct() && !bFound; i += 6)
1691 if ((atypes->bondAtomTypeFromAtomType(at->atom[p->ai()].type)
1692 == bondtype[F_CMAP].cmapAtomTypes[i])
1693 && (atypes->bondAtomTypeFromAtomType(at->atom[p->aj()].type)
1694 == bondtype[F_CMAP].cmapAtomTypes[i + 1])
1695 && (atypes->bondAtomTypeFromAtomType(at->atom[p->ak()].type)
1696 == bondtype[F_CMAP].cmapAtomTypes[i + 2])
1697 && (atypes->bondAtomTypeFromAtomType(at->atom[p->al()].type)
1698 == bondtype[F_CMAP].cmapAtomTypes[i + 3])
1699 && (atypes->bondAtomTypeFromAtomType(at->atom[p->am()].type)
1700 == bondtype[F_CMAP].cmapAtomTypes[i + 4]))
1702 /* Found cmap torsion */
1704 ct = bondtype[F_CMAP].cmapAtomTypes[i + 5];
1710 /* If we did not find a matching type for this cmap torsion */
1713 auto message = gmx::formatString("Unknown cmap torsion between atoms %d %d %d %d %d",
1719 warning_error_and_exit(wi, message, FARGS);
1722 *nparam_def = nparam_found;
1728 /* Returns the number of exact atom type matches, i.e. non wild-card matches,
1729 * returns -1 when there are no matches at all.
1731 static int findNumberOfDihedralAtomMatches(const InteractionOfType& bondType,
1732 const gmx::ArrayRef<const int> atomTypes)
1734 GMX_RELEASE_ASSERT(atomTypes.size() == 4, "Dihedrals have 4 atom types");
1735 const gmx::ArrayRef<const int> bondTypeAtomTypes = bondType.atoms();
1736 GMX_RELEASE_ASSERT(bondTypeAtomTypes.size() == 4, "Dihedral types have 4 atom types");
1737 int numExactMatches = 0;
1738 if (std::equal(bondTypeAtomTypes.begin(),
1739 bondTypeAtomTypes.end(),
1741 [&numExactMatches](int bondTypeAtomType, int atomType) {
1742 if (bondTypeAtomType == atomType)
1744 // Found an exact atom type match
1748 else if (bondTypeAtomType == -1)
1750 // Found a wildcard atom type match
1753 // Atom types do not match
1757 return numExactMatches;
1762 static std::vector<InteractionOfType>::iterator
1763 defaultInteractionsOfType(int ftype,
1764 gmx::ArrayRef<InteractionsOfType> bondType,
1765 const gmx::ArrayRef<const int> atomTypes,
1768 int nparam_found = 0;
1770 if (ftype == F_PDIHS || ftype == F_RBDIHS || ftype == F_IDIHS || ftype == F_PIDIHS)
1772 int nmatch_max = -1;
1774 /* For dihedrals we allow wildcards. We choose the first type
1775 * that has the most exact matches, i.e. non-wildcard matches.
1777 auto prevPos = bondType[ftype].interactionTypes.end();
1778 auto pos = bondType[ftype].interactionTypes.begin();
1779 while (pos != bondType[ftype].interactionTypes.end() && nmatch_max < 4)
1781 pos = std::find_if(bondType[ftype].interactionTypes.begin(),
1782 bondType[ftype].interactionTypes.end(),
1783 [&atomTypes, &nmatch_max](const auto& bondType) {
1784 return (findNumberOfDihedralAtomMatches(bondType, atomTypes) > nmatch_max);
1786 if (pos != bondType[ftype].interactionTypes.end())
1789 nmatch_max = findNumberOfDihedralAtomMatches(*pos, atomTypes);
1793 if (prevPos != bondType[ftype].interactionTypes.end())
1797 /* Find additional matches for this dihedral - necessary
1799 * The rule in that case is that additional matches
1800 * HAVE to be on adjacent lines!
1803 // Advance iterator (like std::advance) without incrementing past end (UB)
1804 const auto safeAdvance = [](auto& it, auto n, auto end) {
1805 it = end - it > n ? it + n : end;
1807 /* Continue from current iterator position */
1808 auto nextPos = prevPos;
1809 const auto endIter = bondType[ftype].interactionTypes.end();
1810 safeAdvance(nextPos, 2, endIter);
1811 for (; nextPos < endIter && bSame; safeAdvance(nextPos, 2, endIter))
1813 bSame = (prevPos->ai() == nextPos->ai() && prevPos->aj() == nextPos->aj()
1814 && prevPos->ak() == nextPos->ak() && prevPos->al() == nextPos->al());
1819 /* nparam_found will be increased as long as the numbers match */
1822 *nparam_def = nparam_found;
1825 else /* Not a dihedral */
1827 auto found = std::find_if(
1828 bondType[ftype].interactionTypes.begin(),
1829 bondType[ftype].interactionTypes.end(),
1830 [&atomTypes](const auto& param) {
1831 return std::equal(param.atoms().begin(), param.atoms().end(), atomTypes.begin());
1833 if (found != bondType[ftype].interactionTypes.end())
1837 *nparam_def = nparam_found;
1843 void push_bond(Directive d,
1844 gmx::ArrayRef<InteractionsOfType> bondtype,
1845 gmx::ArrayRef<InteractionsOfType> bond,
1847 PreprocessingAtomTypes* atypes,
1853 bool* bWarn_copy_A_B,
1856 const char* aaformat[MAXATOMLIST] = { "%d%d", "%d%d%d", "%d%d%d%d",
1857 "%d%d%d%d%d", "%d%d%d%d%d%d", "%d%d%d%d%d%d%d" };
1858 const char* asformat[MAXATOMLIST] = {
1859 "%*s%*s", "%*s%*s%*s", "%*s%*s%*s%*s",
1860 "%*s%*s%*s%*s%*s", "%*s%*s%*s%*s%*s%*s", "%*s%*s%*s%*s%*s%*s%*s"
1862 const char* ccformat = "%lf%lf%lf%lf%lf%lf%lf%lf%lf%lf%lf%lf%lf";
1863 int nral, nral_fmt, nread, ftype;
1864 char format[STRLEN];
1865 /* One force parameter more, so we can check if we read too many */
1866 double cc[MAXFORCEPARAM + 1];
1867 std::array<int, MAXATOMLIST + 1> aa;
1868 bool bFoundA = FALSE, bFoundB = FALSE, bDef, bSwapParity = FALSE;
1869 int nparam_defA, nparam_defB;
1871 nparam_defA = nparam_defB = 0;
1873 ftype = ifunc_index(d, 1);
1875 for (int j = 0; j < nral; j++)
1879 bDef = (NRFP(ftype) > 0);
1881 if (ftype == F_SETTLE)
1883 /* SETTLE acts on 3 atoms, but the topology format only specifies
1884 * the first atom (for historical reasons).
1893 nread = sscanf(line, aaformat[nral_fmt - 1], &aa[0], &aa[1], &aa[2], &aa[3], &aa[4], &aa[5]);
1895 if (ftype == F_SETTLE)
1902 if (nread < nral_fmt)
1907 else if (nread > nral_fmt)
1909 /* this is a hack to allow for virtual sites with swapped parity */
1910 bSwapParity = (aa[nral] < 0);
1913 aa[nral] = -aa[nral];
1915 ftype = ifunc_index(d, aa[nral]);
1921 case F_VSITE3OUT: break;
1924 gmx::formatString("Negative function types only allowed for %s and %s",
1925 interaction_function[F_VSITE3FAD].longname,
1926 interaction_function[F_VSITE3OUT].longname);
1927 warning_error_and_exit(wi, message, FARGS);
1933 /* Check for double atoms and atoms out of bounds, then convert to 0-based indexing */
1934 for (int i = 0; (i < nral); i++)
1936 if (aa[i] < 1 || aa[i] > at->nr)
1938 auto message = gmx::formatString(
1939 "Atom index (%d) in %s out of bounds (1-%d).\n"
1940 "This probably means that you have inserted topology section \"%s\"\n"
1941 "in a part belonging to a different molecule than you intended to.\n"
1942 "In that case move the \"%s\" section to the right molecule.",
1944 enumValueToString(d),
1946 enumValueToString(d),
1947 enumValueToString(d));
1948 warning_error_and_exit(wi, message, FARGS);
1950 for (int j = i + 1; (j < nral); j++)
1952 GMX_ASSERT(j < MAXATOMLIST + 1,
1953 "Values from nral=NRAL() will satisfy this, we assert to keep gcc 4 happy");
1956 auto message = gmx::formatString(
1957 "Duplicate atom index (%d) in %s", aa[i], enumValueToString(d));
1958 if (ftype == F_ANGRES)
1960 /* Since the angle restraints uses 2 pairs of atoms to
1961 * defines an angle between vectors, it can be useful
1962 * to use one atom twice, so we only issue a note here.
1964 warning_note(wi, message);
1968 warning_error(wi, message);
1973 // Convert to 0-based indexing
1977 // These are the atom indices for this interaction
1978 auto atomIndices = gmx::ArrayRef<const int>(aa).subArray(0, nral);
1980 // Look up the A-state atom types for this interaction
1981 std::vector<int> atomTypes(atomIndices.size());
1982 std::transform(atomIndices.begin(), atomIndices.end(), atomTypes.begin(), [at, atypes](const int atomIndex) {
1983 return atypes->bondAtomTypeFromAtomType(at->atom[atomIndex].type).value();
1985 // Look up the B-state atom types for this interaction
1986 std::vector<int> atomTypesB(atomIndices.size());
1987 std::transform(atomIndices.begin(), atomIndices.end(), atomTypesB.begin(), [at, atypes](const int atomIndex) {
1988 return atypes->bondAtomTypeFromAtomType(at->atom[atomIndex].typeB).value();
1991 /* default force parameters */
1992 /* need to have an empty but initialized param array for some reason */
1993 std::array<real, MAXFORCEPARAM> forceParam = { 0.0 };
1995 /* Get force params for normal and free energy perturbation
1996 * studies, as determined by types!
1998 InteractionOfType param(atomIndices, forceParam, "");
2000 std::vector<InteractionOfType>::iterator foundAParameter = bondtype[ftype].interactionTypes.end();
2001 std::vector<InteractionOfType>::iterator foundBParameter = bondtype[ftype].interactionTypes.end();
2004 if (NRFPA(ftype) == 0)
2010 foundAParameter = defaultInteractionsOfType(ftype, bondtype, atomTypes, &nparam_defA);
2011 if (foundAParameter != bondtype[ftype].interactionTypes.end())
2013 /* Copy the A-state and B-state default parameters. */
2014 GMX_ASSERT(NRFPA(ftype) + NRFPB(ftype) <= MAXFORCEPARAM,
2015 "Bonded interactions may have at most 12 parameters");
2016 gmx::ArrayRef<const real> defaultParam = foundAParameter->forceParam();
2017 for (int j = 0; (j < NRFPA(ftype) + NRFPB(ftype)); j++)
2019 param.setForceParameter(j, defaultParam[j]);
2025 if (NRFPB(ftype) == 0)
2031 foundBParameter = defaultInteractionsOfType(ftype, bondtype, atomTypesB, &nparam_defB);
2032 if (foundBParameter != bondtype[ftype].interactionTypes.end())
2034 /* Copy only the B-state default parameters */
2035 gmx::ArrayRef<const real> defaultParam = foundBParameter->forceParam();
2036 for (int j = NRFPA(ftype); (j < NRFP(ftype)); j++)
2038 param.setForceParameter(j, defaultParam[j]);
2044 else if (ftype == F_LJ14)
2046 bFoundA = default_nb_params(ftype, bondtype, at, ¶m, 0, FALSE, bGenPairs);
2047 bFoundB = default_nb_params(ftype, bondtype, at, ¶m, 0, TRUE, bGenPairs);
2049 else if (ftype == F_LJC14_Q)
2051 /* Fill in the A-state charges as default parameters */
2052 param.setForceParameter(0, fudgeQQ);
2053 param.setForceParameter(1, at->atom[param.ai()].q);
2054 param.setForceParameter(2, at->atom[param.aj()].q);
2055 /* The default LJ parameters are the standard 1-4 parameters */
2056 bFoundA = default_nb_params(F_LJ14, bondtype, at, ¶m, 3, FALSE, bGenPairs);
2059 else if (ftype == F_LJC_PAIRS_NB)
2061 /* Defaults are not supported here */
2067 gmx_incons("Unknown function type in push_bond");
2070 if (nread > nral_fmt)
2072 /* Manually specified parameters - in this case we discard multiple torsion info! */
2074 strcpy(format, asformat[nral_fmt - 1]);
2075 strcat(format, ccformat);
2077 nread = sscanf(line,
2093 if ((nread == NRFPA(ftype)) && (NRFPB(ftype) != 0))
2095 /* We only have to issue a warning if these atoms are perturbed! */
2097 gmx::ArrayRef<const int> paramAtoms = param.atoms();
2098 for (int j = 0; (j < nral); j++)
2100 bPert = bPert || PERTURBED(at->atom[paramAtoms[j]]);
2103 if (bPert && *bWarn_copy_A_B)
2105 auto message = gmx::formatString(
2106 "Some parameters for bonded interaction involving "
2107 "perturbed atoms are specified explicitly in "
2108 "state A, but not B - copying A to B");
2109 warning(wi, message);
2110 *bWarn_copy_A_B = FALSE;
2113 /* If only the A parameters were specified, copy them to the B state */
2114 /* The B-state parameters correspond to the first nrfpB
2115 * A-state parameters.
2117 for (int j = 0; (j < NRFPB(ftype)); j++)
2119 cc[nread++] = cc[j];
2123 /* If nread was 0 or EOF, no parameters were read => use defaults.
2124 * If nread was nrfpA we copied above so nread=nrfp.
2125 * If nread was nrfp we are cool.
2126 * For F_LJC14_Q we allow supplying fudgeQQ only.
2127 * Anything else is an error!
2129 if ((nread != 0) && (nread != EOF) && (nread != NRFP(ftype)) && !(ftype == F_LJC14_Q && nread == 1))
2131 auto message = gmx::formatString(
2132 "Incorrect number of parameters - found %d, expected %d "
2133 "or %d for %s (after the function type).",
2137 interaction_function[ftype].longname);
2138 warning_error_and_exit(wi, message, FARGS);
2141 for (int j = 0; (j < nread); j++)
2143 param.setForceParameter(j, cc[j]);
2145 /* Check whether we have to use the defaults */
2146 if (nread == NRFP(ftype))
2155 /* nread now holds the number of force parameters read! */
2160 /* When we have multiple terms it would be very dangerous to allow perturbations to a different atom type! */
2161 if (ftype == F_PDIHS)
2163 if ((nparam_defA != nparam_defB)
2164 || ((nparam_defA > 1 || nparam_defB > 1) && (foundAParameter != foundBParameter)))
2166 auto message = gmx::formatString(
2167 "Cannot automatically perturb a torsion with multiple terms to different "
2169 "Please specify perturbed parameters manually for this torsion in your "
2171 warning_error(wi, message);
2175 if (nread > 0 && nread < NRFPA(ftype))
2177 /* Issue an error, do not use defaults */
2178 auto message = gmx::formatString(
2179 "Not enough parameters, there should be at least %d (or 0 for defaults)", NRFPA(ftype));
2180 warning_error(wi, message);
2183 if (nread == 0 || nread == EOF)
2187 if (interaction_function[ftype].flags & IF_VSITE)
2189 for (int j = 0; j < MAXFORCEPARAM; j++)
2191 param.setForceParameter(j, NOTSET);
2195 /* flag to swap parity of vsi te construction */
2196 param.setForceParameter(1, -1);
2204 "NOTE: No default %s types, using zeroes\n",
2205 interaction_function[ftype].longname);
2209 auto message = gmx::formatString("No default %s types",
2210 interaction_function[ftype].longname);
2211 warning_error(wi, message);
2221 case F_VSITE3FAD: param.setForceParameter(0, 360 - param.c0()); break;
2222 case F_VSITE3OUT: param.setForceParameter(2, -param.c2()); break;
2228 /* We only have to issue a warning if these atoms are perturbed! */
2230 gmx::ArrayRef<const int> paramAtoms = param.atoms();
2231 for (int j = 0; (j < nral); j++)
2233 bPert = bPert || PERTURBED(at->atom[paramAtoms[j]]);
2238 auto message = gmx::formatString(
2239 "No default %s types for perturbed atoms, "
2240 "using normal values",
2241 interaction_function[ftype].longname);
2242 warning(wi, message);
2248 gmx::ArrayRef<const real> paramValue = param.forceParam();
2249 if ((ftype == F_PDIHS || ftype == F_ANGRES || ftype == F_ANGRESZ) && paramValue[5] != paramValue[2])
2251 auto message = gmx::formatString("%s multiplicity can not be perturbed %f!=%f",
2252 interaction_function[ftype].longname,
2255 warning_error_and_exit(wi, message, FARGS);
2258 if (IS_TABULATED(ftype) && param.c0() != param.c2())
2260 auto message = gmx::formatString("%s table number can not be perturbed %d!=%d",
2261 interaction_function[ftype].longname,
2262 gmx::roundToInt(param.c0()),
2263 gmx::roundToInt(param.c0()));
2264 warning_error_and_exit(wi, message, FARGS);
2267 /* Dont add R-B dihedrals where all parameters are zero (no interaction) */
2268 if (ftype == F_RBDIHS)
2272 for (int i = 0; i < NRFP(ftype); i++)
2274 if (paramValue[i] != 0.0)
2285 /* Put the values in the appropriate arrays */
2286 add_param_to_list(&bond[ftype], param);
2288 /* Push additional torsions from FF for ftype==9 if we have them.
2289 * We have already checked that the A/B states do not differ in this case,
2290 * so we do not have to double-check that again, or the vsite stuff.
2291 * In addition, those torsions cannot be automatically perturbed.
2293 if (bDef && ftype == F_PDIHS)
2295 for (int i = 1; i < nparam_defA; i++)
2297 /* Advance pointer! */
2298 foundAParameter += 2;
2299 gmx::ArrayRef<const real> forceParam = foundAParameter->forceParam();
2300 for (int j = 0; j < (NRFPA(ftype) + NRFPB(ftype)); j++)
2302 param.setForceParameter(j, forceParam[j]);
2304 /* And push the next term for this torsion */
2305 add_param_to_list(&bond[ftype], param);
2310 void push_cmap(Directive d,
2311 gmx::ArrayRef<InteractionsOfType> bondtype,
2312 gmx::ArrayRef<InteractionsOfType> bond,
2314 PreprocessingAtomTypes* atypes,
2318 const char* aaformat[MAXATOMLIST + 1] = {
2319 "%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"
2322 int ftype, nral, nread, ncmap_params;
2324 int aa[MAXATOMLIST + 1];
2327 ftype = ifunc_index(d, 1);
2331 nread = sscanf(line, aaformat[nral - 1], &aa[0], &aa[1], &aa[2], &aa[3], &aa[4], &aa[5]);
2338 else if (nread == nral)
2340 ftype = ifunc_index(d, 1);
2343 /* Check for double atoms and atoms out of bounds */
2344 for (int i = 0; i < nral; i++)
2346 if (aa[i] < 1 || aa[i] > at->nr)
2348 auto message = gmx::formatString(
2349 "Atom index (%d) in %s out of bounds (1-%d).\n"
2350 "This probably means that you have inserted topology section \"%s\"\n"
2351 "in a part belonging to a different molecule than you intended to.\n"
2352 "In that case move the \"%s\" section to the right molecule.",
2354 enumValueToString(d),
2356 enumValueToString(d),
2357 enumValueToString(d));
2358 warning_error_and_exit(wi, message, FARGS);
2361 for (int j = i + 1; (j < nral); j++)
2365 auto message = gmx::formatString(
2366 "Duplicate atom index (%d) in %s", aa[i], enumValueToString(d));
2367 warning_error(wi, message);
2372 /* default force parameters */
2373 std::vector<int> atoms;
2374 for (int j = 0; (j < nral); j++)
2376 atoms.emplace_back(aa[j] - 1);
2378 std::array<real, MAXFORCEPARAM> forceParam = { 0.0 };
2379 InteractionOfType param(atoms, forceParam, "");
2380 /* Get the cmap type for this cmap angle */
2381 bFound = default_cmap_params(bondtype, at, atypes, ¶m, FALSE, &cmap_type, &ncmap_params, wi);
2383 /* We want exactly one parameter (the cmap type in state A (currently no state B) back */
2384 if (bFound && ncmap_params == 1)
2386 /* Put the values in the appropriate arrays */
2387 param.setForceParameter(0, cmap_type);
2388 add_param_to_list(&bond[ftype], param);
2392 /* This is essentially the same check as in default_cmap_params() done one more time */
2394 gmx::formatString("Unable to assign a cmap type to torsion %d %d %d %d and %d\n",
2400 warning_error_and_exit(wi, message, FARGS);
2405 void push_vsitesn(Directive d, gmx::ArrayRef<InteractionsOfType> bond, t_atoms* at, char* line, warninp* wi)
2408 int type, ftype, n, ret, nj, a;
2410 double *weight = nullptr, weight_tot;
2412 std::array<real, MAXFORCEPARAM> forceParam = { 0.0 };
2414 ret = sscanf(ptr, "%d%n", &a, &n);
2419 gmx::formatString("Expected an atom index in section \"%s\"", enumValueToString(d));
2420 warning_error_and_exit(wi, message, FARGS);
2423 sscanf(ptr, "%d%n", &type, &n);
2425 ftype = ifunc_index(d, type);
2426 int firstAtom = a - 1;
2432 ret = sscanf(ptr, "%d%n", &a, &n);
2438 srenew(atc, nj + 20);
2439 srenew(weight, nj + 20);
2444 case 1: weight[nj] = 1; break;
2446 /* Here we use the A-state mass as a parameter.
2447 * Note that the B-state mass has no influence.
2449 weight[nj] = at->atom[atc[nj]].m;
2453 ret = sscanf(ptr, "%lf%n", &(weight[nj]), &n);
2457 auto message = gmx::formatString(
2458 "No weight or negative weight found for vsiten "
2459 "constructing atom %d (atom index %d)",
2462 warning_error_and_exit(wi, message, FARGS);
2466 auto message = gmx::formatString("Unknown vsiten type %d", type);
2467 warning_error_and_exit(wi, message, FARGS);
2469 weight_tot += weight[nj];
2476 auto message = gmx::formatString("Expected more than one atom index in section \"%s\"",
2477 enumValueToString(d));
2478 warning_error_and_exit(wi, message, FARGS);
2481 if (weight_tot == 0)
2483 warning_error_and_exit(wi, "The total mass of the construting atoms is zero", FARGS);
2486 for (int j = 0; j < nj; j++)
2488 std::vector<int> atoms = { firstAtom, atc[j] };
2490 forceParam[1] = weight[j] / weight_tot;
2491 /* Put the values in the appropriate arrays */
2492 add_param_to_list(&bond[ftype], InteractionOfType(atoms, forceParam));
2499 void push_mol(gmx::ArrayRef<MoleculeInformation> mols, char* pline, int* whichmol, int* nrcopies, warninp* wi)
2503 if (sscanf(pline, "%s%d", type, nrcopies) != 2)
2509 /* Search moleculename.
2510 * Here we originally only did case insensitive matching. But because
2511 * some PDB files can have many chains and use case to generate more
2512 * chain-identifiers, which in turn end up in our moleculetype name,
2513 * we added support for case-sensitivity.
2520 for (const auto& mol : mols)
2522 if (strcmp(type, *(mol.name)) == 0)
2527 if (gmx_strcasecmp(type, *(mol.name)) == 0)
2537 // select the case sensitive match
2538 *whichmol = matchcs;
2542 // avoid matching case-insensitive when we have multiple matches
2545 auto message = gmx::formatString(
2546 "For moleculetype '%s' in [ system ] %d case insensitive "
2547 "matches, but %d case sensitive matches were found. Check "
2548 "the case of the characters in the moleculetypes.",
2552 warning_error_and_exit(wi, message, FARGS);
2556 // select the unique case insensitive match
2557 *whichmol = matchci;
2561 auto message = gmx::formatString("No such moleculetype %s", type);
2562 warning_error_and_exit(wi, message, FARGS);
2567 void push_excl(char* line, gmx::ArrayRef<gmx::ExclusionBlock> b2, warninp* wi)
2571 char base[STRLEN], format[STRLEN];
2573 if (sscanf(line, "%d", &i) == 0)
2578 if ((1 <= i) && (i <= b2.ssize()))
2586 strcpy(base, "%*d");
2589 strcpy(format, base);
2590 strcat(format, "%d");
2591 n = sscanf(line, format, &j);
2594 if ((1 <= j) && (j <= b2.ssize()))
2597 b2[i].atomNumber.push_back(j);
2598 /* also add the reverse exclusion! */
2599 b2[j].atomNumber.push_back(i);
2600 strcat(base, "%*d");
2604 auto message = gmx::formatString("Invalid Atomnr j: %d, b2->nr: %zu\n", j, b2.size());
2605 warning_error_and_exit(wi, message, FARGS);
2611 int add_atomtype_decoupled(t_symtab* symtab, PreprocessingAtomTypes* at, t_nbparam*** nbparam, t_nbparam*** pair)
2616 /* Define an atom type with all parameters set to zero (no interactions) */
2619 /* Type for decoupled atoms could be anything,
2620 * this should be changed automatically later when required.
2622 atom.ptype = ParticleType::Atom;
2624 std::array<real, MAXFORCEPARAM> forceParam = { 0.0 };
2625 nr = at->addType(symtab, atom, "decoupled", InteractionOfType({}, forceParam, ""), -1, 0);
2627 /* Add space in the non-bonded parameters matrix */
2628 realloc_nb_params(at, nbparam, pair);
2633 static void convert_pairs_to_pairsQ(gmx::ArrayRef<InteractionsOfType> interactions, real fudgeQQ, t_atoms* atoms)
2635 /* Add the pair list to the pairQ list */
2636 std::vector<InteractionOfType> paramnew;
2638 gmx::ArrayRef<const InteractionOfType> paramp1 = interactions[F_LJ14].interactionTypes;
2639 gmx::ArrayRef<const InteractionOfType> paramp2 = interactions[F_LJC14_Q].interactionTypes;
2641 /* Fill in the new F_LJC14_Q array with the old one. NOTE:
2642 it may be possible to just ADD the converted F_LJ14 array
2643 to the old F_LJC14_Q array, but since we have to create
2644 a new sized memory structure, better just to deep copy it all.
2648 for (const auto& param : paramp2)
2650 paramnew.emplace_back(param);
2653 for (const auto& param : paramp1)
2655 std::vector<real> forceParam = {
2656 fudgeQQ, atoms->atom[param.ai()].q, atoms->atom[param.aj()].q, param.c0(), param.c1()
2658 paramnew.emplace_back(param.atoms(), forceParam, "");
2661 /* now assign the new data to the F_LJC14_Q structure */
2662 interactions[F_LJC14_Q].interactionTypes = paramnew;
2664 /* Empty the LJ14 pairlist */
2665 interactions[F_LJ14].interactionTypes.clear();
2668 static void generate_LJCpairsNB(MoleculeInformation* mol, int nb_funct, InteractionsOfType* nbp, warninp* wi)
2674 atom = mol->atoms.atom;
2676 ntype = static_cast<int>(std::sqrt(static_cast<double>(nbp->size())));
2677 GMX_ASSERT(ntype * ntype == gmx::ssize(*nbp),
2678 "Number of pairs of generated non-bonded parameters should be a perfect square");
2680 /* Add a pair interaction for all non-excluded atom pairs */
2681 const auto& excls = mol->excls;
2682 for (int i = 0; i < n; i++)
2684 for (int j = i + 1; j < n; j++)
2686 bool pairIsExcluded = false;
2687 for (const int atomK : excls[i])
2691 pairIsExcluded = true;
2694 if (!pairIsExcluded)
2696 if (nb_funct != F_LJ)
2698 auto message = gmx::formatString(
2699 "Can only generate non-bonded pair interactions "
2700 "for Van der Waals type Lennard-Jones");
2701 warning_error_and_exit(wi, message, FARGS);
2703 std::vector<int> atoms = { i, j };
2704 std::vector<real> forceParam = {
2707 nbp->interactionTypes[ntype * atom[i].type + atom[j].type].c0(),
2708 nbp->interactionTypes[ntype * atom[i].type + atom[j].type].c1()
2710 add_param_to_list(&mol->interactions[F_LJC_PAIRS_NB], InteractionOfType(atoms, forceParam));
2716 static void set_excl_all(gmx::ListOfLists<int>* excl)
2718 /* Get rid of the current exclusions and exclude all atom pairs */
2719 const int numAtoms = excl->ssize();
2720 std::vector<int> exclusionsForAtom(numAtoms);
2721 for (int i = 0; i < numAtoms; i++)
2723 exclusionsForAtom[i] = i;
2726 for (int i = 0; i < numAtoms; i++)
2728 excl->pushBack(exclusionsForAtom);
2732 static void decouple_atoms(t_atoms* atoms,
2733 int atomtype_decouple,
2736 const char* mol_name,
2741 for (i = 0; i < atoms->nr; i++)
2745 atom = &atoms->atom[i];
2747 if (atom->qB != atom->q || atom->typeB != atom->type)
2749 auto message = gmx::formatString(
2750 "Atom %d in molecule type '%s' has different A and B state "
2751 "charges and/or atom types set in the topology file as well "
2752 "as through the mdp option '%s'. You can not use both "
2753 "these methods simultaneously.",
2757 warning_error_and_exit(wi, message, FARGS);
2760 if (couple_lam0 == ecouplamNONE || couple_lam0 == ecouplamVDW)
2764 if (couple_lam0 == ecouplamNONE || couple_lam0 == ecouplamQ)
2766 atom->type = atomtype_decouple;
2768 if (couple_lam1 == ecouplamNONE || couple_lam1 == ecouplamVDW)
2772 if (couple_lam1 == ecouplamNONE || couple_lam1 == ecouplamQ)
2774 atom->typeB = atomtype_decouple;
2779 void convert_moltype_couple(MoleculeInformation* mol,
2780 int atomtype_decouple,
2786 InteractionsOfType* nbp,
2789 convert_pairs_to_pairsQ(mol->interactions, fudgeQQ, &mol->atoms);
2792 generate_LJCpairsNB(mol, nb_funct, nbp, wi);
2793 set_excl_all(&mol->excls);
2795 decouple_atoms(&mol->atoms, atomtype_decouple, couple_lam0, couple_lam1, *mol->name, wi);