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/enumerationhelpers.h"
66 #include "gromacs/utility/fatalerror.h"
67 #include "gromacs/utility/gmxassert.h"
68 #include "gromacs/utility/smalloc.h"
69 #include "gromacs/utility/stringtoenumvalueconverter.h"
70 #include "gromacs/utility/stringutil.h"
72 void generate_nbparams(CombinationRule comb,
74 InteractionsOfType* interactions,
75 PreprocessingAtomTypes* atypes,
78 constexpr int c_nrfp2 = 2;
81 real c, bi, bj, ci, cj, ci0, ci1, ci2, cj0, cj1, cj2;
83 /* Lean mean shortcuts */
86 interactions->interactionTypes.clear();
88 std::array<real, MAXFORCEPARAM> forceParam = { NOTSET };
89 /* Fill the matrix with force parameters */
90 // Prefetch the parameters to improve cache hits and avoid dereference and call overhead
91 std::vector<std::pair<real, real>> cPrefetch;
92 cPrefetch.reserve(nr);
93 for (int i = 0; i < nr; i++)
95 cPrefetch.emplace_back(*atypes->atomNonBondedParamFromAtomType(i, 0),
96 *atypes->atomNonBondedParamFromAtomType(i, 1));
98 interactions->interactionTypes.reserve(nr * nr);
104 case CombinationRule::Geometric:
105 // Geometric combination rules, c6 and c12 are independent
106 GMX_RELEASE_ASSERT(nrfp == c_nrfp2, "nfrp should be 2");
107 for (int i = 0; (i < nr); i++)
109 for (int j = 0; (j < nr); j++)
111 for (int nf = 0; (nf < c_nrfp2); nf++)
113 ci = (nf == 0 ? cPrefetch[i].first : cPrefetch[i].second);
114 cj = (nf == 0 ? cPrefetch[j].first : cPrefetch[j].second);
115 c = std::sqrt(ci * cj);
118 interactions->interactionTypes.emplace_back(gmx::ArrayRef<const int>{},
124 case CombinationRule::Arithmetic:
125 /* c0 and c1 are sigma and epsilon */
126 for (int i = 0; (i < nr); i++)
128 for (int j = 0; (j < nr); j++)
130 ci0 = cPrefetch[i].first;
131 cj0 = cPrefetch[j].first;
132 ci1 = cPrefetch[i].second;
133 cj1 = cPrefetch[j].second;
134 forceParam[0] = (fabs(ci0) + fabs(cj0)) * 0.5;
135 /* Negative sigma signals that c6 should be set to zero later,
136 * so we need to propagate that through the combination rules.
138 if (ci0 < 0 || cj0 < 0)
142 forceParam[1] = std::sqrt(ci1 * cj1);
143 interactions->interactionTypes.emplace_back(gmx::ArrayRef<const int>{},
149 case CombinationRule::GeomSigEps:
150 /* c0 and c1 are sigma and epsilon */
151 for (int i = 0; (i < nr); i++)
153 for (int j = 0; (j < nr); j++)
155 ci0 = cPrefetch[i].first;
156 cj0 = cPrefetch[j].first;
157 ci1 = cPrefetch[i].second;
158 cj1 = cPrefetch[j].second;
159 forceParam[0] = std::sqrt(std::fabs(ci0 * cj0));
160 /* Negative sigma signals that c6 should be set to zero later,
161 * so we need to propagate that through the combination rules.
163 if (ci0 < 0 || cj0 < 0)
167 forceParam[1] = std::sqrt(ci1 * cj1);
168 interactions->interactionTypes.emplace_back(gmx::ArrayRef<const int>{},
176 gmx::formatString("No such combination rule %s", enumValueToString(comb));
177 warning_error_and_exit(wi, message, FARGS);
182 /* Buckingham rules */
183 for (int i = 0; (i < nr); i++)
185 for (int j = 0; (j < nr); j++)
187 ci0 = cPrefetch[i].first;
188 cj0 = cPrefetch[j].first;
189 ci2 = *atypes->atomNonBondedParamFromAtomType(i, 2);
190 cj2 = *atypes->atomNonBondedParamFromAtomType(j, 2);
191 bi = cPrefetch[i].second;
192 bj = cPrefetch[j].second;
193 forceParam[0] = std::sqrt(ci0 * cj0);
194 if ((bi == 0) || (bj == 0))
200 forceParam[1] = 2.0 / (1 / bi + 1 / bj);
202 forceParam[2] = std::sqrt(ci2 * cj2);
203 interactions->interactionTypes.emplace_back(gmx::ArrayRef<const int>{}, forceParam);
209 auto message = gmx::formatString("Invalid nonbonded type %s",
210 interaction_function[ftype].longname);
211 warning_error(wi, message);
215 /*! \brief Used to temporarily store the explicit non-bonded parameter
216 * combinations, which will be copied to InteractionsOfType. */
219 //! Has this combination been set.
221 //! The non-bonded parameters
225 static void realloc_nb_params(PreprocessingAtomTypes* atypes, t_nbparam*** nbparam, t_nbparam*** pair)
227 /* Add space in the non-bonded parameters matrix */
228 int atnr = atypes->size();
229 srenew(*nbparam, atnr);
230 snew((*nbparam)[atnr - 1], atnr);
234 snew((*pair)[atnr - 1], atnr);
238 int copy_nbparams(t_nbparam** param, int ftype, InteractionsOfType* interactions, int nr)
245 for (int i = 0; i < nr; i++)
247 for (int j = 0; j <= i; j++)
249 GMX_RELEASE_ASSERT(param, "Must have valid parameters");
250 if (param[i][j].bSet)
252 for (int f = 0; f < nrfp; f++)
254 interactions->interactionTypes[nr * i + j].setForceParameter(f, param[i][j].c[f]);
255 interactions->interactionTypes[nr * j + i].setForceParameter(f, param[i][j].c[f]);
265 void free_nbparam(t_nbparam** param, int nr)
269 GMX_RELEASE_ASSERT(param, "Must have valid parameters");
270 for (i = 0; i < nr; i++)
272 GMX_RELEASE_ASSERT(param[i], "Must have valid parameters");
278 static void copy_B_from_A(int ftype, double* c)
282 nrfpA = NRFPA(ftype);
283 nrfpB = NRFPB(ftype);
285 /* Copy the B parameters from the first nrfpB A parameters */
286 for (i = 0; (i < nrfpB); i++)
292 //! Local definition that supersedes the central one, as we only want the leading letter
293 static const char* enumValueToLetterAsString(ParticleType enumValue)
295 static constexpr gmx::EnumerationArray<ParticleType, const char*> particleTypeLetters = {
296 "A", "N", "S", "B", "V"
298 return particleTypeLetters[enumValue];
301 void push_at(t_symtab* symtab,
302 PreprocessingAtomTypes* at,
303 PreprocessingBondAtomType* bondAtomType,
306 t_nbparam*** nbparam,
310 int nfields, nfp0 = -1;
312 char type[STRLEN], btype[STRLEN], ptype[STRLEN];
314 double c[MAXFORCEPARAM];
315 char tmpfield[12][100]; /* Max 12 fields of width 100 */
318 bool have_atomic_number;
319 bool have_bonded_type;
323 /* First assign input line to temporary array */
324 nfields = sscanf(line,
325 "%s%s%s%s%s%s%s%s%s%s%s%s",
339 /* Comments on optional fields in the atomtypes section:
341 * The force field format is getting a bit old. For OPLS-AA we needed
342 * to add a special bonded atomtype, and for Gerrit Groenhofs QM/MM stuff
343 * we also needed the atomic numbers.
344 * To avoid making all old or user-generated force fields unusable we
345 * have introduced both these quantities as optional columns, and do some
346 * acrobatics to check whether they are present or not.
347 * This will all look much nicer when we switch to XML... sigh.
349 * Field 0 (mandatory) is the nonbonded type name. (string)
350 * Field 1 (optional) is the bonded type (string)
351 * Field 2 (optional) is the atomic number (int)
352 * Field 3 (mandatory) is the mass (numerical)
353 * Field 4 (mandatory) is the charge (numerical)
354 * Field 5 (mandatory) is the particle type (single character)
355 * This is followed by a number of nonbonded parameters.
357 * The safest way to identify the format is the particle type field.
359 * So, here is what we do:
361 * A. Read in the first six fields as strings
362 * B. If field 3 (starting from 0) is a single char, we have neither
363 * bonded_type or atomic numbers.
364 * C. If field 5 is a single char we have both.
365 * D. If field 4 is a single char we check field 1. If this begins with
366 * an alphabetical character we have bonded types, otherwise atomic numbers.
375 if ((strlen(tmpfield[5]) == 1) && isalpha(tmpfield[5][0]))
377 have_bonded_type = TRUE;
378 have_atomic_number = TRUE;
380 else if ((strlen(tmpfield[3]) == 1) && isalpha(tmpfield[3][0]))
382 have_bonded_type = FALSE;
383 have_atomic_number = FALSE;
387 have_bonded_type = (isalpha(tmpfield[1][0]) != 0);
388 have_atomic_number = !have_bonded_type;
391 /* optional fields */
400 if (have_atomic_number)
402 if (have_bonded_type)
405 line, "%s%s%d%lf%lf%s%lf%lf", type, btype, &atomnr, &m, &q, ptype, &c[0], &c[1]);
414 /* have_atomic_number && !have_bonded_type */
415 nread = sscanf(line, "%s%d%lf%lf%s%lf%lf", type, &atomnr, &m, &q, ptype, &c[0], &c[1]);
425 if (have_bonded_type)
427 /* !have_atomic_number && have_bonded_type */
428 nread = sscanf(line, "%s%s%lf%lf%s%lf%lf", type, btype, &m, &q, ptype, &c[0], &c[1]);
437 /* !have_atomic_number && !have_bonded_type */
438 nread = sscanf(line, "%s%lf%lf%s%lf%lf", type, &m, &q, ptype, &c[0], &c[1]);
447 if (!have_bonded_type)
452 if (!have_atomic_number)
462 if (have_atomic_number)
464 if (have_bonded_type)
467 line, "%s%s%d%lf%lf%s%lf%lf%lf", type, btype, &atomnr, &m, &q, ptype, &c[0], &c[1], &c[2]);
476 /* have_atomic_number && !have_bonded_type */
478 line, "%s%d%lf%lf%s%lf%lf%lf", type, &atomnr, &m, &q, ptype, &c[0], &c[1], &c[2]);
488 if (have_bonded_type)
490 /* !have_atomic_number && have_bonded_type */
492 line, "%s%s%lf%lf%s%lf%lf%lf", type, btype, &m, &q, ptype, &c[0], &c[1], &c[2]);
501 /* !have_atomic_number && !have_bonded_type */
502 nread = sscanf(line, "%s%lf%lf%s%lf%lf%lf", type, &m, &q, ptype, &c[0], &c[1], &c[2]);
511 if (!have_bonded_type)
516 if (!have_atomic_number)
524 auto message = gmx::formatString("Invalid function type %d in push_at", nb_funct);
525 warning_error_and_exit(wi, message, FARGS);
527 for (int j = nfp0; (j < MAXFORCEPARAM); j++)
531 std::array<real, MAXFORCEPARAM> forceParam;
533 if (strlen(type) == 1 && isdigit(type[0]))
535 warning_error_and_exit(wi, "Atom type names can't be single digits.", FARGS);
538 if (strlen(btype) == 1 && isdigit(btype[0]))
540 warning_error_and_exit(wi, "Bond atom type names can't be single digits.", FARGS);
543 /* Hack to read old topologies */
544 if (gmx_strcasecmp(ptype, "D") == 0)
548 static const gmx::StringToEnumValueConverter<ParticleType, enumValueToLetterAsString, gmx::StringCompareType::CaseInsensitive, gmx::StripStrings::No>
549 s_stringToParticleType;
550 std::optional<ParticleType> pt = s_stringToParticleType.valueFrom(ptype);
553 auto message = gmx::formatString("Invalid particle type %s", ptype);
554 warning_error_and_exit(wi, message, FARGS);
559 atom->ptype = pt.value();
560 for (int i = 0; i < MAXFORCEPARAM; i++)
562 forceParam[i] = c[i];
565 InteractionOfType interactionType({}, forceParam, "");
567 auto batype_nr = bondAtomType->addBondAtomType(symtab, btype);
569 auto atomType = at->atomTypeFromName(type);
570 if (atomType.has_value())
572 auto message = gmx::formatString(
573 "Atomtype %s was defined previously (e.g. in the forcefield files), "
574 "and has now been defined again. This could happen e.g. if you would "
575 "use a self-contained molecule .itp file that duplicates or replaces "
576 "the contents of the standard force-field files. You should check "
577 "the contents of your files and remove such repetition. If you know "
578 "you should override the previous definition, then you could choose "
579 "to suppress this warning with -maxwarn.",
581 warning(wi, message);
582 auto newAtomType = at->setType(*atomType, symtab, *atom, type, interactionType, batype_nr, atomnr);
583 if (!newAtomType.has_value())
585 auto message = gmx::formatString("Replacing atomtype %s failed", type);
586 warning_error_and_exit(wi, message, FARGS);
591 at->addType(symtab, *atom, type, interactionType, batype_nr, atomnr);
592 /* Add space in the non-bonded parameters matrix */
593 realloc_nb_params(at, nbparam, pair);
598 //! Return whether the contents of \c a and \c b are the same, considering also reversed order.
600 static bool equalEitherForwardOrBackward(gmx::ArrayRef<const T> a, gmx::ArrayRef<const T> b)
602 return (std::equal(a.begin(), a.end(), b.begin()) || std::equal(a.begin(), a.end(), b.rbegin()));
605 static void push_bondtype(InteractionsOfType* bt,
606 const InteractionOfType& b,
614 int nrfp = NRFP(ftype);
616 /* If bAllowRepeat is TRUE, we allow multiple entries as long as they
617 are on directly _adjacent_ lines.
620 /* First check if our atomtypes are _identical_ (not reversed) to the previous
621 entry. If they are not identical we search for earlier duplicates. If they are
622 we can skip it, since we already searched for the first line
626 bool isContinuationOfBlock = false;
627 if (bAllowRepeat && nr > 1)
629 isContinuationOfBlock = true;
630 gmx::ArrayRef<const int> newParAtom = b.atoms();
631 gmx::ArrayRef<const int> sysParAtom = bt->interactionTypes[nr - 2].atoms();
632 for (int j = 0; j < nral; j++)
634 if (newParAtom[j] != sysParAtom[j])
636 isContinuationOfBlock = false;
641 /* Search for earlier duplicates if this entry was not a continuation
642 from the previous line.
644 bool addBondType = true;
645 bool haveWarned = false;
646 bool haveErrored = false;
647 for (int i = 0; (i < nr); i++)
649 gmx::ArrayRef<const int> bParams = b.atoms();
650 gmx::ArrayRef<const int> testParams = bt->interactionTypes[i].atoms();
651 GMX_RELEASE_ASSERT(bParams.size() == testParams.size(),
652 "Number of atoms needs to be the same between parameters");
653 if (equalEitherForwardOrBackward(bParams, testParams))
655 GMX_ASSERT(nrfp <= MAXFORCEPARAM,
656 "This is ensured in other places, but we need this assert to keep the clang "
658 const bool identicalParameters = std::equal(bt->interactionTypes[i].forceParam().begin(),
659 bt->interactionTypes[i].forceParam().begin() + nrfp,
660 b.forceParam().begin());
662 if (!bAllowRepeat || identicalParameters)
667 if (!identicalParameters)
671 /* With dihedral type 9 we only allow for repeating
672 * of the same parameters with blocks with 1 entry.
673 * Allowing overriding is too complex to check.
675 if (!isContinuationOfBlock && !haveErrored)
678 "Encountered a second block of parameters for dihedral "
679 "type 9 for the same atoms, with either different parameters "
680 "and/or the first block has multiple lines. This is not "
685 else if (!haveWarned)
687 auto message = gmx::formatString(
688 "Bondtype %s was defined previously (e.g. in the forcefield files), "
689 "and has now been defined again. This could happen e.g. if you would "
690 "use a self-contained molecule .itp file that duplicates or replaces "
691 "the contents of the standard force-field files. You should check "
692 "the contents of your files and remove such repetition. If you know "
693 "you should override the previous definition, then you could choose "
694 "to suppress this warning with -maxwarn.%s",
695 interaction_function[ftype].longname,
696 (ftype == F_PDIHS) ? "\nUse dihedraltype 9 to allow several "
697 "multiplicity terms. Only consecutive "
698 "lines are combined. Non-consective lines "
699 "overwrite each other."
701 warning(wi, message);
703 fprintf(stderr, " old: ");
704 gmx::ArrayRef<const real> forceParam = bt->interactionTypes[i].forceParam();
705 for (int j = 0; j < nrfp; j++)
707 fprintf(stderr, " %g", forceParam[j]);
709 fprintf(stderr, " \n new: %s\n\n", line);
715 if (!identicalParameters && !bAllowRepeat)
717 /* Overwrite the parameters with the latest ones */
718 // TODO considering improving the following code by replacing with:
719 // std::copy(b->c, b->c + nrfp, bt->param[i].c);
720 gmx::ArrayRef<const real> forceParam = b.forceParam();
721 for (int j = 0; j < nrfp; j++)
723 bt->interactionTypes[i].setForceParameter(j, forceParam[j]);
731 /* fill the arrays up and down */
732 bt->interactionTypes.emplace_back(b.atoms(), b.forceParam(), b.interactionTypeName());
733 /* need to store force values because they might change below */
734 std::vector<real> forceParam(b.forceParam().begin(), b.forceParam().end());
736 /* The definitions of linear angles depend on the order of atoms,
737 * that means that for atoms i-j-k, with certain parameter a, the
738 * corresponding k-j-i angle will have parameter 1-a.
740 if (ftype == F_LINEAR_ANGLES)
742 forceParam[0] = 1 - forceParam[0];
743 forceParam[2] = 1 - forceParam[2];
745 std::vector<int> atoms;
746 gmx::ArrayRef<const int> oldAtoms = b.atoms();
747 for (auto oldAtom = oldAtoms.rbegin(); oldAtom != oldAtoms.rend(); oldAtom++)
749 atoms.emplace_back(*oldAtom);
751 bt->interactionTypes.emplace_back(atoms, forceParam, b.interactionTypeName());
755 static std::vector<int> atomTypesFromAtomNames(const PreprocessingAtomTypes* atomTypes,
756 const PreprocessingBondAtomType* bondAtomTypes,
757 gmx::ArrayRef<const char[20]> atomNames,
761 GMX_RELEASE_ASSERT(!(!atomNames.empty() && !atomTypes && !bondAtomTypes),
762 "Need to have either valid atomtypes or bondatomtypes object");
764 std::vector<int> atomTypesFromAtomNames;
765 for (const auto& name : atomNames)
767 if (atomTypes != nullptr)
769 auto atomType = atomTypes->atomTypeFromName(name);
770 if (!atomType.has_value())
772 auto message = gmx::formatString("Unknown atomtype %s\n", name);
773 warning_error_and_exit(wi, message, FARGS);
775 atomTypesFromAtomNames.emplace_back(*atomType);
777 else if (bondAtomTypes != nullptr)
779 auto bondAtomType = bondAtomTypes->bondAtomTypeFromName(name);
780 if (!bondAtomType.has_value())
782 auto message = gmx::formatString("Unknown bond_atomtype %s\n", name);
783 warning_error_and_exit(wi, message, FARGS);
785 atomTypesFromAtomNames.emplace_back(*bondAtomType);
788 return atomTypesFromAtomNames;
792 void push_bt(Directive d,
793 gmx::ArrayRef<InteractionsOfType> bt,
795 PreprocessingAtomTypes* at,
796 PreprocessingBondAtomType* bondAtomType,
800 const char* formal[MAXATOMLIST + 1] = {
801 "%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"
803 const char* formnl[MAXATOMLIST + 1] = { "%*s",
808 "%*s%*s%*s%*s%*s%*s",
809 "%*s%*s%*s%*s%*s%*s%*s" };
810 const char* formlf = "%lf%lf%lf%lf%lf%lf%lf%lf%lf%lf%lf%lf%lf";
811 int i, ft, ftype, nn, nrfp, nrfpA;
813 char alc[MAXATOMLIST + 1][20];
814 /* One force parameter more, so we can check if we read too many */
815 double c[MAXFORCEPARAM + 1];
817 if ((bondAtomType && at) || (!bondAtomType && !at))
819 gmx_incons("You should pass either bondAtomType or at to push_bt");
822 /* Make format string (nral ints+functype) */
823 if ((nn = sscanf(line, formal[nral], alc[0], alc[1], alc[2], alc[3], alc[4], alc[5])) != nral + 1)
825 auto message = gmx::formatString("Not enough atomtypes (%d instead of %d)", nn - 1, nral);
826 warning_error(wi, message);
830 ft = strtol(alc[nral], nullptr, 10);
831 ftype = ifunc_index(d, ft);
833 nrfpA = interaction_function[ftype].nrfpA;
834 strcpy(f1, formnl[nral]);
837 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]))
842 /* Copy the B-state from the A-state */
843 copy_B_from_A(ftype, c);
849 warning_error(wi, "Not enough parameters");
851 else if (nn > nrfpA && nn < nrfp)
853 warning_error(wi, "Too many parameters or not enough parameters for topology B");
857 warning_error(wi, "Too many parameters");
859 for (i = nn; (i < nrfp); i++)
865 std::vector<int> atomTypes =
866 atomTypesFromAtomNames(at, bondAtomType, gmx::arrayRefFromArray(alc, nral), wi);
867 std::array<real, MAXFORCEPARAM> forceParam;
868 for (int i = 0; (i < nrfp); i++)
870 forceParam[i] = c[i];
872 push_bondtype(&(bt[ftype]), InteractionOfType(atomTypes, forceParam), nral, ftype, FALSE, line, wi);
876 void push_dihedraltype(Directive d,
877 gmx::ArrayRef<InteractionsOfType> bt,
878 PreprocessingBondAtomType* bondAtomType,
882 const char* formal[MAXATOMLIST + 1] = {
883 "%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"
885 const char* formnl[MAXATOMLIST + 1] = { "%*s",
890 "%*s%*s%*s%*s%*s%*s",
891 "%*s%*s%*s%*s%*s%*s%*s" };
892 const char* formlf[MAXFORCEPARAM] = {
898 "%lf%lf%lf%lf%lf%lf",
899 "%lf%lf%lf%lf%lf%lf%lf",
900 "%lf%lf%lf%lf%lf%lf%lf%lf",
901 "%lf%lf%lf%lf%lf%lf%lf%lf%lf",
902 "%lf%lf%lf%lf%lf%lf%lf%lf%lf%lf",
903 "%lf%lf%lf%lf%lf%lf%lf%lf%lf%lf%lf",
904 "%lf%lf%lf%lf%lf%lf%lf%lf%lf%lf%lf%lf",
906 int i, ft, ftype, nn, nrfp, nrfpA, nral;
908 char alc[MAXATOMLIST + 1][20];
909 double c[MAXFORCEPARAM];
912 /* This routine accepts dihedraltypes defined from either 2 or 4 atoms.
914 * We first check for 2 atoms with the 3th column being an integer
915 * defining the type. If this isn't the case, we try it with 4 atoms
916 * and the 5th column defining the dihedral type.
918 nn = sscanf(line, formal[4], alc[0], alc[1], alc[2], alc[3], alc[4]);
919 if (nn >= 3 && strlen(alc[2]) == 1 && isdigit(alc[2][0]))
922 ft = strtol(alc[nral], nullptr, 10);
923 /* Move atom types around a bit and use 'X' for wildcard atoms
924 * to create a 4-atom dihedral definition with arbitrary atoms in
927 if (alc[2][0] == '2')
929 /* improper - the two atomtypes are 1,4. Use wildcards for 2,3 */
930 strcpy(alc[3], alc[1]);
931 sprintf(alc[2], "X");
932 sprintf(alc[1], "X");
933 /* alc[0] stays put */
937 /* proper - the two atomtypes are 2,3. Use wildcards for 1,4 */
938 sprintf(alc[3], "X");
939 strcpy(alc[2], alc[1]);
940 strcpy(alc[1], alc[0]);
941 sprintf(alc[0], "X");
944 else if (nn == 5 && strlen(alc[4]) == 1 && isdigit(alc[4][0]))
947 ft = strtol(alc[nral], nullptr, 10);
951 auto message = gmx::formatString(
952 "Incorrect number of atomtypes for dihedral (%d instead of 2 or 4)", nn - 1);
953 warning_error(wi, message);
959 /* Previously, we have always overwritten parameters if e.g. a torsion
960 with the same atomtypes occurs on multiple lines. However, CHARMM and
961 some other force fields specify multiple dihedrals over some bonds,
962 including cosines with multiplicity 6 and somethimes even higher.
963 Thus, they cannot be represented with Ryckaert-Bellemans terms.
964 To add support for these force fields, Dihedral type 9 is identical to
965 normal proper dihedrals, but repeated entries are allowed.
972 bAllowRepeat = FALSE;
976 ftype = ifunc_index(d, ft);
978 nrfpA = interaction_function[ftype].nrfpA;
980 strcpy(f1, formnl[nral]);
981 strcat(f1, formlf[nrfp - 1]);
983 /* Check number of parameters given */
985 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]))
990 /* Copy the B-state from the A-state */
991 copy_B_from_A(ftype, c);
997 warning_error(wi, "Not enough parameters");
999 else if (nn > nrfpA && nn < nrfp)
1001 warning_error(wi, "Too many parameters or not enough parameters for topology B");
1005 warning_error(wi, "Too many parameters");
1007 for (i = nn; (i < nrfp); i++)
1014 std::vector<int> atoms;
1015 std::array<real, MAXFORCEPARAM> forceParam;
1016 for (int i = 0; (i < 4); i++)
1018 if (!strcmp(alc[i], "X"))
1020 atoms.emplace_back(-1);
1024 auto atomNumber = bondAtomType->bondAtomTypeFromName(alc[i]);
1025 if (!atomNumber.has_value())
1027 auto message = gmx::formatString("Unknown bond_atomtype %s", alc[i]);
1028 warning_error_and_exit(wi, message, FARGS);
1030 atoms.emplace_back(*atomNumber);
1033 for (int i = 0; (i < nrfp); i++)
1035 forceParam[i] = c[i];
1037 /* Always use 4 atoms here, since we created two wildcard atoms
1038 * if there wasn't of them 4 already.
1040 push_bondtype(&(bt[ftype]), InteractionOfType(atoms, forceParam), 4, ftype, bAllowRepeat, line, wi);
1044 void push_nbt(Directive d, t_nbparam** nbt, PreprocessingAtomTypes* atypes, char* pline, int nb_funct, warninp* wi)
1046 /* swap the atoms */
1047 const char* form3 = "%*s%*s%*s%lf%lf%lf";
1048 const char* form4 = "%*s%*s%*s%lf%lf%lf%lf";
1049 const char* form5 = "%*s%*s%*s%lf%lf%lf%lf%lf";
1050 char a0[80], a1[80];
1051 int i, f, n, ftype, nrfp;
1057 if (sscanf(pline, "%s%s%d", a0, a1, &f) != 3)
1063 ftype = ifunc_index(d, f);
1065 if (ftype != nb_funct)
1067 auto message = gmx::formatString("Trying to add %s while the default nonbond type is %s",
1068 interaction_function[ftype].longname,
1069 interaction_function[nb_funct].longname);
1070 warning_error(wi, message);
1074 /* Get the force parameters */
1076 if (ftype == F_LJ14)
1078 n = sscanf(pline, form4, &c[0], &c[1], &c[2], &c[3]);
1084 /* When the B topology parameters are not set,
1085 * copy them from topology A
1087 GMX_ASSERT(nrfp <= 4, "LJ-14 cannot have more than 4 parameters");
1088 for (i = n; i < nrfp; i++)
1093 else if (ftype == F_LJC14_Q)
1095 n = sscanf(pline, form5, &c[0], &c[1], &c[2], &c[3], &dum);
1098 incorrect_n_param(wi);
1104 if (sscanf(pline, form3, &c[0], &c[1], &dum) != 2)
1106 incorrect_n_param(wi);
1112 if (sscanf(pline, form4, &c[0], &c[1], &c[2], &dum) != 3)
1114 incorrect_n_param(wi);
1121 gmx::formatString("Number of force parameters for nonbonded interactions is %d", nrfp);
1122 warning_error_and_exit(wi, message, FARGS);
1124 for (i = 0; (i < nrfp); i++)
1129 /* Put the parameters in the matrix */
1130 auto ai = atypes->atomTypeFromName(a0);
1131 if (!ai.has_value())
1133 auto message = gmx::formatString("Atomtype %s not found", a0);
1134 warning_error_and_exit(wi, message, FARGS);
1136 auto aj = atypes->atomTypeFromName(a1);
1137 if (!aj.has_value())
1139 auto message = gmx::formatString("Atomtype %s not found", a1);
1140 warning_error_and_exit(wi, message, FARGS);
1142 nbp = &(nbt[std::max(*ai, *aj)][std::min(*ai, *aj)]);
1147 for (i = 0; i < nrfp; i++)
1149 bId = bId && (nbp->c[i] == cr[i]);
1153 auto message = gmx::formatString(
1154 "Non-bonded parameters were defined previously (e.g. in the forcefield files), "
1155 "and have now been defined again. This could happen e.g. if you would "
1156 "use a self-contained molecule .itp file that duplicates or replaces "
1157 "the contents of the standard force-field files. You should check "
1158 "the contents of your files and remove such repetition. If you know "
1159 "you should override the previous definitions, then you could choose "
1160 "to suppress this warning with -maxwarn.");
1161 warning(wi, message);
1162 fprintf(stderr, " old:");
1163 for (i = 0; i < nrfp; i++)
1165 fprintf(stderr, " %g", nbp->c[i]);
1167 fprintf(stderr, " new\n%s\n", pline);
1171 for (i = 0; i < nrfp; i++)
1177 void push_cmaptype(Directive d,
1178 gmx::ArrayRef<InteractionsOfType> bt,
1180 PreprocessingAtomTypes* atomtypes,
1181 PreprocessingBondAtomType* bondAtomType,
1185 const char* formal = "%s%s%s%s%s%s%s%s%n";
1187 int ft, ftype, nn, nrfp, nrfpA, nrfpB;
1188 int start, nchar_consumed;
1189 int nxcmap, nycmap, ncmap, read_cmap, sl, nct;
1190 char s[20], alc[MAXATOMLIST + 2][20];
1192 /* Keep the compiler happy */
1196 GMX_ASSERT(nral == 5, "CMAP requires 5 atoms per interaction");
1198 /* Here we can only check for < 8 */
1199 if ((nn = sscanf(line, formal, alc[0], alc[1], alc[2], alc[3], alc[4], alc[5], alc[6], alc[7], &nchar_consumed))
1203 gmx::formatString("Incorrect number of atomtypes for cmap (%d instead of 5)", nn - 1);
1204 warning_error(wi, message);
1207 start += nchar_consumed;
1209 ft = strtol(alc[nral], nullptr, 10);
1210 nxcmap = strtol(alc[nral + 1], nullptr, 10);
1211 nycmap = strtol(alc[nral + 2], nullptr, 10);
1213 /* Check for equal grid spacing in x and y dims */
1214 if (nxcmap != nycmap)
1216 auto message = gmx::formatString(
1217 "Not the same grid spacing in x and y for cmap grid: x=%d, y=%d", nxcmap, nycmap);
1218 warning_error(wi, message);
1221 ncmap = nxcmap * nycmap;
1222 ftype = ifunc_index(d, ft);
1223 nrfpA = strtol(alc[6], nullptr, 10) * strtol(alc[6], nullptr, 10);
1224 nrfpB = strtol(alc[7], nullptr, 10) * strtol(alc[7], nullptr, 10);
1225 nrfp = nrfpA + nrfpB;
1227 /* Read in CMAP parameters */
1229 for (int i = 0; i < ncmap; i++)
1231 while (isspace(*(line + start + sl)))
1235 nn = sscanf(line + start + sl, " %s ", s);
1237 bt[F_CMAP].cmap.emplace_back(strtod(s, nullptr));
1246 gmx::formatString("Error in reading cmap parameter for angle %s %s %s %s %s",
1252 warning_error(wi, message);
1256 /* Check do that we got the number of parameters we expected */
1257 if (read_cmap == nrfpA)
1259 for (int i = 0; i < ncmap; i++)
1261 bt[F_CMAP].cmap.emplace_back(bt[F_CMAP].cmap[i]);
1266 if (read_cmap < nrfpA)
1268 warning_error(wi, "Not enough cmap parameters");
1270 else if (read_cmap > nrfpA && read_cmap < nrfp)
1272 warning_error(wi, "Too many cmap parameters or not enough parameters for topology B");
1274 else if (read_cmap > nrfp)
1276 warning_error(wi, "Too many cmap parameters");
1281 /* Set grid spacing and the number of grids (we assume these numbers to be the same for all
1282 * grids so we can safely assign them each time
1284 bt[F_CMAP].cmakeGridSpacing = nxcmap; /* Or nycmap, they need to be equal */
1285 bt[F_CMAP].cmapAngles++; /* Since we are incrementing here, we need to subtract later, see (*****) */
1286 nct = (nral + 1) * bt[F_CMAP].cmapAngles;
1288 for (int i = 0; (i < nral); i++)
1290 /* Assign a grid number to each cmap_type */
1291 GMX_RELEASE_ASSERT(bondAtomType != nullptr, "Need valid PreprocessingBondAtomType object");
1292 bt[F_CMAP].cmapAtomTypes.emplace_back(*bondAtomType->bondAtomTypeFromName(alc[i]));
1295 /* Assign a type number to this cmap */
1296 bt[F_CMAP].cmapAtomTypes.emplace_back(
1297 bt[F_CMAP].cmapAngles
1298 - 1); /* Since we inremented earlier, we need to subtrac here, to get the types right (****) */
1300 /* Check for the correct number of atoms (again) */
1301 if (bt[F_CMAP].nct() != nct)
1303 auto message = gmx::formatString(
1304 "Incorrect number of atom types (%d) in cmap type %d\n", nct, bt[F_CMAP].cmapAngles);
1305 warning_error(wi, message);
1307 std::vector<int> atomTypes =
1308 atomTypesFromAtomNames(atomtypes, bondAtomType, gmx::constArrayRefFromArray(alc, nral), wi);
1309 std::array<real, MAXFORCEPARAM> forceParam = { NOTSET };
1311 /* Push the bond to the bondlist */
1312 push_bondtype(&(bt[ftype]), InteractionOfType(atomTypes, forceParam), nral, ftype, FALSE, line, wi);
1316 static void push_atom_now(t_symtab* symtab,
1334 int j, resind = 0, resnr;
1338 if (((nr == 0) && (atomnr != 1)) || (nr && (atomnr != at->nr + 1)))
1340 auto message = gmx::formatString(
1341 "Atoms in the .top are not numbered consecutively from 1 (rather, "
1342 "atomnr = %d, while at->nr = %d)",
1345 warning_error_and_exit(wi, message, FARGS);
1348 j = strlen(resnumberic) - 1;
1349 if (isdigit(resnumberic[j]))
1355 ric = resnumberic[j];
1356 if (j == 0 || !isdigit(resnumberic[j - 1]))
1359 gmx::formatString("Invalid residue number '%s' for atom %d", resnumberic, atomnr);
1360 warning_error_and_exit(wi, message, FARGS);
1363 resnr = strtol(resnumberic, nullptr, 10);
1367 resind = at->atom[nr - 1].resind;
1369 if (nr == 0 || strcmp(resname, *at->resinfo[resind].name) != 0
1370 || resnr != at->resinfo[resind].nr || ric != at->resinfo[resind].ic)
1380 at->nres = resind + 1;
1381 srenew(at->resinfo, at->nres);
1382 at->resinfo[resind].name = put_symtab(symtab, resname);
1383 at->resinfo[resind].nr = resnr;
1384 at->resinfo[resind].ic = ric;
1388 resind = at->atom[at->nr - 1].resind;
1391 /* New atom instance
1392 * get new space for arrays
1394 srenew(at->atom, nr + 1);
1395 srenew(at->atomname, nr + 1);
1396 srenew(at->atomtype, nr + 1);
1397 srenew(at->atomtypeB, nr + 1);
1400 at->atom[nr].type = type;
1401 at->atom[nr].ptype = ptype;
1402 at->atom[nr].q = q0;
1403 at->atom[nr].m = m0;
1404 at->atom[nr].typeB = typeB;
1405 at->atom[nr].qB = qB;
1406 at->atom[nr].mB = mB;
1408 at->atom[nr].resind = resind;
1409 at->atom[nr].atomnumber = atomicnumber;
1410 at->atomname[nr] = put_symtab(symtab, name);
1411 at->atomtype[nr] = put_symtab(symtab, ctype);
1412 at->atomtypeB[nr] = put_symtab(symtab, ctypeB);
1416 void push_atom(t_symtab* symtab, t_atoms* at, PreprocessingAtomTypes* atypes, char* line, warninp* wi)
1418 int cgnumber, atomnr, nscan;
1419 char id[STRLEN], ctype[STRLEN], ctypeB[STRLEN], resnumberic[STRLEN], resname[STRLEN],
1420 name[STRLEN], check[STRLEN];
1421 double m, q, mb, qb;
1422 real m0, q0, mB, qB;
1424 /* Fixed parameters */
1425 if (sscanf(line, "%s%s%s%s%s%d", id, ctype, resnumberic, resname, name, &cgnumber) != 6)
1430 sscanf(id, "%d", &atomnr);
1431 auto type = atypes->atomTypeFromName(ctype);
1432 if (!type.has_value())
1434 auto message = gmx::formatString("Atomtype %s not found", ctype);
1435 warning_error_and_exit(wi, message, FARGS);
1437 ParticleType ptype = *atypes->atomParticleTypeFromAtomType(*type);
1439 /* Set default from type */
1440 q0 = *atypes->atomChargeFromAtomType(*type);
1441 m0 = *atypes->atomMassFromAtomType(*type);
1446 /* Optional parameters */
1447 nscan = sscanf(line, "%*s%*s%*s%*s%*s%*s%lf%lf%s%lf%lf%s", &q, &m, ctypeB, &qb, &mb, check);
1449 /* Nasty switch that falls thru all the way down! */
1458 typeB = atypes->atomTypeFromName(ctypeB);
1459 if (!typeB.has_value())
1461 auto message = gmx::formatString("Atomtype %s not found", ctypeB);
1462 warning_error_and_exit(wi, message, FARGS);
1464 qB = *atypes->atomChargeFromAtomType(*typeB);
1465 mB = *atypes->atomMassFromAtomType(*typeB);
1474 warning_error(wi, "Too many parameters");
1482 push_atom_now(symtab,
1485 *atypes->atomNumberFromAtomType(*type),
1495 typeB == type ? ctype : ctypeB,
1501 void push_molt(t_symtab* symtab, std::vector<MoleculeInformation>* mol, char* line, warninp* wi)
1506 if ((sscanf(line, "%s%d", type, &nrexcl)) != 2)
1508 warning_error(wi, "Expected a molecule type name and nrexcl");
1511 /* Test if this moleculetype overwrites another */
1512 const auto found = std::find_if(
1513 mol->begin(), mol->end(), [&type](const auto& m) { return strcmp(*(m.name), type) == 0; });
1514 if (found != mol->end())
1516 auto message = gmx::formatString("moleculetype %s is redefined", type);
1517 warning_error_and_exit(wi, message, FARGS);
1520 mol->emplace_back();
1521 mol->back().initMolInfo();
1523 /* Fill in the values */
1524 mol->back().name = put_symtab(symtab, type);
1525 mol->back().nrexcl = nrexcl;
1526 mol->back().excl_set = false;
1529 static bool findIfAllNBAtomsMatch(gmx::ArrayRef<const int> atomsFromParameterArray,
1530 gmx::ArrayRef<const int> atomsFromCurrentParameter,
1534 if (atomsFromParameterArray.size() != atomsFromCurrentParameter.size())
1540 for (gmx::index i = 0; i < atomsFromCurrentParameter.ssize(); i++)
1542 if (at->atom[atomsFromCurrentParameter[i]].typeB != atomsFromParameterArray[i])
1551 for (gmx::index i = 0; i < atomsFromCurrentParameter.ssize(); i++)
1553 if (at->atom[atomsFromCurrentParameter[i]].type != atomsFromParameterArray[i])
1562 static bool default_nb_params(int ftype,
1563 gmx::ArrayRef<InteractionsOfType> bt,
1565 InteractionOfType* p,
1572 InteractionOfType* pi = nullptr;
1573 int nr = bt[ftype].size();
1574 int nral = NRAL(ftype);
1575 int nrfp = interaction_function[ftype].nrfpA;
1576 int nrfpB = interaction_function[ftype].nrfpB;
1578 if ((!bB && nrfp == 0) || (bB && nrfpB == 0))
1586 /* First test the generated-pair position to save
1587 * time when we have 1000*1000 entries for e.g. OPLS...
1589 ntype = static_cast<int>(std::sqrt(static_cast<double>(nr)));
1590 GMX_ASSERT(ntype * ntype == nr,
1591 "Number of pairs of generated non-bonded parameters should be a perfect square");
1594 ti = at->atom[p->ai()].typeB;
1595 tj = at->atom[p->aj()].typeB;
1599 ti = at->atom[p->ai()].type;
1600 tj = at->atom[p->aj()].type;
1602 pi = &(bt[ftype].interactionTypes[ntype * ti + tj]);
1603 if (pi->atoms().ssize() < nral)
1605 /* not initialized yet with atom names */
1610 bFound = ((ti == pi->ai()) && (tj == pi->aj()));
1614 gmx::ArrayRef<const int> paramAtoms = p->atoms();
1615 /* Search explicitly if we didnt find it */
1618 auto foundParameter =
1619 std::find_if(bt[ftype].interactionTypes.begin(),
1620 bt[ftype].interactionTypes.end(),
1621 [¶mAtoms, &at, &bB](const auto& param) {
1622 return findIfAllNBAtomsMatch(param.atoms(), paramAtoms, at, bB);
1624 if (foundParameter != bt[ftype].interactionTypes.end())
1627 pi = &(*foundParameter);
1633 gmx::ArrayRef<const real> forceParam = pi->forceParam();
1636 if (nrfp + nrfpB > MAXFORCEPARAM)
1638 gmx_incons("Too many force parameters");
1640 for (int j = c_start; j < nrfpB; j++)
1642 p->setForceParameter(nrfp + j, forceParam[j]);
1647 for (int j = c_start; j < nrfp; j++)
1649 p->setForceParameter(j, forceParam[j]);
1655 for (int j = c_start; j < nrfp; j++)
1657 p->setForceParameter(j, 0.0);
1663 static bool default_cmap_params(gmx::ArrayRef<InteractionsOfType> bondtype,
1665 PreprocessingAtomTypes* atypes,
1666 InteractionOfType* p,
1674 bool bFound = false;
1679 /* Match the current cmap angle against the list of cmap_types */
1680 for (int i = 0; i < bondtype[F_CMAP].nct() && !bFound; i += 6)
1685 if ((atypes->bondAtomTypeFromAtomType(at->atom[p->ai()].type)
1686 == bondtype[F_CMAP].cmapAtomTypes[i])
1687 && (atypes->bondAtomTypeFromAtomType(at->atom[p->aj()].type)
1688 == bondtype[F_CMAP].cmapAtomTypes[i + 1])
1689 && (atypes->bondAtomTypeFromAtomType(at->atom[p->ak()].type)
1690 == bondtype[F_CMAP].cmapAtomTypes[i + 2])
1691 && (atypes->bondAtomTypeFromAtomType(at->atom[p->al()].type)
1692 == bondtype[F_CMAP].cmapAtomTypes[i + 3])
1693 && (atypes->bondAtomTypeFromAtomType(at->atom[p->am()].type)
1694 == bondtype[F_CMAP].cmapAtomTypes[i + 4]))
1696 /* Found cmap torsion */
1698 ct = bondtype[F_CMAP].cmapAtomTypes[i + 5];
1704 /* If we did not find a matching type for this cmap torsion */
1707 auto message = gmx::formatString("Unknown cmap torsion between atoms %d %d %d %d %d",
1713 warning_error_and_exit(wi, message, FARGS);
1716 *nparam_def = nparam_found;
1722 /* Returns the number of exact atom type matches, i.e. non wild-card matches,
1723 * returns -1 when there are no matches at all.
1725 static int natom_match(const InteractionOfType& pi,
1730 const PreprocessingAtomTypes* atypes)
1732 if ((pi.ai() == -1 || atypes->bondAtomTypeFromAtomType(type_i) == pi.ai())
1733 && (pi.aj() == -1 || atypes->bondAtomTypeFromAtomType(type_j) == pi.aj())
1734 && (pi.ak() == -1 || atypes->bondAtomTypeFromAtomType(type_k) == pi.ak())
1735 && (pi.al() == -1 || atypes->bondAtomTypeFromAtomType(type_l) == pi.al()))
1737 return (pi.ai() == -1 ? 0 : 1) + (pi.aj() == -1 ? 0 : 1) + (pi.ak() == -1 ? 0 : 1)
1738 + (pi.al() == -1 ? 0 : 1);
1746 static int findNumberOfDihedralAtomMatches(const InteractionOfType& currentParamFromParameterArray,
1747 const InteractionOfType& parameterToAdd,
1749 const PreprocessingAtomTypes* atypes,
1754 return natom_match(currentParamFromParameterArray,
1755 at->atom[parameterToAdd.ai()].typeB,
1756 at->atom[parameterToAdd.aj()].typeB,
1757 at->atom[parameterToAdd.ak()].typeB,
1758 at->atom[parameterToAdd.al()].typeB,
1763 return natom_match(currentParamFromParameterArray,
1764 at->atom[parameterToAdd.ai()].type,
1765 at->atom[parameterToAdd.aj()].type,
1766 at->atom[parameterToAdd.ak()].type,
1767 at->atom[parameterToAdd.al()].type,
1772 static bool findIfAllParameterAtomsMatch(gmx::ArrayRef<const int> atomsFromParameterArray,
1773 gmx::ArrayRef<const int> atomsFromCurrentParameter,
1775 const PreprocessingAtomTypes* atypes,
1778 if (atomsFromParameterArray.size() != atomsFromCurrentParameter.size())
1784 for (gmx::index i = 0; i < atomsFromCurrentParameter.ssize(); i++)
1786 if (atypes->bondAtomTypeFromAtomType(at->atom[atomsFromCurrentParameter[i]].typeB)
1787 != atomsFromParameterArray[i])
1796 for (gmx::index i = 0; i < atomsFromCurrentParameter.ssize(); i++)
1798 if (atypes->bondAtomTypeFromAtomType(at->atom[atomsFromCurrentParameter[i]].type)
1799 != atomsFromParameterArray[i])
1808 static std::vector<InteractionOfType>::iterator defaultInteractionsOfType(int ftype,
1809 gmx::ArrayRef<InteractionsOfType> bt,
1811 PreprocessingAtomTypes* atypes,
1812 const InteractionOfType& p,
1817 int nrfpA = interaction_function[ftype].nrfpA;
1818 int nrfpB = interaction_function[ftype].nrfpB;
1820 if ((!bB && nrfpA == 0) || (bB && nrfpB == 0))
1822 return bt[ftype].interactionTypes.end();
1827 if (ftype == F_PDIHS || ftype == F_RBDIHS || ftype == F_IDIHS || ftype == F_PIDIHS)
1829 int nmatch_max = -1;
1831 /* For dihedrals we allow wildcards. We choose the first type
1832 * that has the most real matches, i.e. non-wildcard matches.
1834 auto prevPos = bt[ftype].interactionTypes.end();
1835 auto pos = bt[ftype].interactionTypes.begin();
1836 while (pos != bt[ftype].interactionTypes.end() && nmatch_max < 4)
1838 pos = std::find_if(bt[ftype].interactionTypes.begin(),
1839 bt[ftype].interactionTypes.end(),
1840 [&p, &at, &atypes, &bB, &nmatch_max](const auto& param) {
1841 return (findNumberOfDihedralAtomMatches(param, p, at, atypes, bB)
1844 if (pos != bt[ftype].interactionTypes.end())
1847 nmatch_max = findNumberOfDihedralAtomMatches(*pos, p, at, atypes, bB);
1851 if (prevPos != bt[ftype].interactionTypes.end())
1855 /* Find additional matches for this dihedral - necessary
1857 * The rule in that case is that additional matches
1858 * HAVE to be on adjacent lines!
1861 // Advance iterator (like std::advance) without incrementing past end (UB)
1862 const auto safeAdvance = [](auto& it, auto n, auto end) {
1863 it = end - it > n ? it + n : end;
1865 /* Continue from current iterator position */
1866 auto nextPos = prevPos;
1867 const auto endIter = bt[ftype].interactionTypes.end();
1868 safeAdvance(nextPos, 2, endIter);
1869 for (; nextPos < endIter && bSame; safeAdvance(nextPos, 2, endIter))
1871 bSame = (prevPos->ai() == nextPos->ai() && prevPos->aj() == nextPos->aj()
1872 && prevPos->ak() == nextPos->ak() && prevPos->al() == nextPos->al());
1877 /* nparam_found will be increased as long as the numbers match */
1880 *nparam_def = nparam_found;
1883 else /* Not a dihedral */
1885 gmx::ArrayRef<const int> atomParam = p.atoms();
1886 auto found = std::find_if(bt[ftype].interactionTypes.begin(),
1887 bt[ftype].interactionTypes.end(),
1888 [&atomParam, &at, &atypes, &bB](const auto& param) {
1889 return findIfAllParameterAtomsMatch(
1890 param.atoms(), atomParam, at, atypes, bB);
1892 if (found != bt[ftype].interactionTypes.end())
1896 *nparam_def = nparam_found;
1902 void push_bond(Directive d,
1903 gmx::ArrayRef<InteractionsOfType> bondtype,
1904 gmx::ArrayRef<InteractionsOfType> bond,
1906 PreprocessingAtomTypes* atypes,
1912 bool* bWarn_copy_A_B,
1915 const char* aaformat[MAXATOMLIST] = { "%d%d", "%d%d%d", "%d%d%d%d",
1916 "%d%d%d%d%d", "%d%d%d%d%d%d", "%d%d%d%d%d%d%d" };
1917 const char* asformat[MAXATOMLIST] = {
1918 "%*s%*s", "%*s%*s%*s", "%*s%*s%*s%*s",
1919 "%*s%*s%*s%*s%*s", "%*s%*s%*s%*s%*s%*s", "%*s%*s%*s%*s%*s%*s%*s"
1921 const char* ccformat = "%lf%lf%lf%lf%lf%lf%lf%lf%lf%lf%lf%lf%lf";
1922 int nral, nral_fmt, nread, ftype;
1923 char format[STRLEN];
1924 /* One force parameter more, so we can check if we read too many */
1925 double cc[MAXFORCEPARAM + 1];
1926 int aa[MAXATOMLIST + 1];
1927 bool bFoundA = FALSE, bFoundB = FALSE, bDef, bSwapParity = FALSE;
1928 int nparam_defA, nparam_defB;
1930 nparam_defA = nparam_defB = 0;
1932 ftype = ifunc_index(d, 1);
1934 for (int j = 0; j < nral; j++)
1938 bDef = (NRFP(ftype) > 0);
1940 if (ftype == F_SETTLE)
1942 /* SETTLE acts on 3 atoms, but the topology format only specifies
1943 * the first atom (for historical reasons).
1952 nread = sscanf(line, aaformat[nral_fmt - 1], &aa[0], &aa[1], &aa[2], &aa[3], &aa[4], &aa[5]);
1954 if (ftype == F_SETTLE)
1961 if (nread < nral_fmt)
1966 else if (nread > nral_fmt)
1968 /* this is a hack to allow for virtual sites with swapped parity */
1969 bSwapParity = (aa[nral] < 0);
1972 aa[nral] = -aa[nral];
1974 ftype = ifunc_index(d, aa[nral]);
1980 case F_VSITE3OUT: break;
1983 gmx::formatString("Negative function types only allowed for %s and %s",
1984 interaction_function[F_VSITE3FAD].longname,
1985 interaction_function[F_VSITE3OUT].longname);
1986 warning_error_and_exit(wi, message, FARGS);
1992 /* Check for double atoms and atoms out of bounds */
1993 for (int i = 0; (i < nral); i++)
1995 if (aa[i] < 1 || aa[i] > at->nr)
1997 auto message = gmx::formatString(
1998 "Atom index (%d) in %s out of bounds (1-%d).\n"
1999 "This probably means that you have inserted topology section \"%s\"\n"
2000 "in a part belonging to a different molecule than you intended to.\n"
2001 "In that case move the \"%s\" section to the right molecule.",
2003 enumValueToString(d),
2005 enumValueToString(d),
2006 enumValueToString(d));
2007 warning_error_and_exit(wi, message, FARGS);
2009 for (int j = i + 1; (j < nral); j++)
2011 GMX_ASSERT(j < MAXATOMLIST + 1,
2012 "Values from nral=NRAL() will satisfy this, we assert to keep gcc 4 happy");
2015 auto message = gmx::formatString(
2016 "Duplicate atom index (%d) in %s", aa[i], enumValueToString(d));
2017 if (ftype == F_ANGRES)
2019 /* Since the angle restraints uses 2 pairs of atoms to
2020 * defines an angle between vectors, it can be useful
2021 * to use one atom twice, so we only issue a note here.
2023 warning_note(wi, message);
2027 warning_error(wi, message);
2033 /* default force parameters */
2034 std::vector<int> atoms;
2035 for (int j = 0; (j < nral); j++)
2037 atoms.emplace_back(aa[j] - 1);
2039 /* need to have an empty but initialized param array for some reason */
2040 std::array<real, MAXFORCEPARAM> forceParam = { 0.0 };
2042 /* Get force params for normal and free energy perturbation
2043 * studies, as determined by types!
2045 InteractionOfType param(atoms, forceParam, "");
2047 std::vector<InteractionOfType>::iterator foundAParameter = bondtype[ftype].interactionTypes.end();
2048 std::vector<InteractionOfType>::iterator foundBParameter = bondtype[ftype].interactionTypes.end();
2052 defaultInteractionsOfType(ftype, bondtype, at, atypes, param, FALSE, &nparam_defA);
2053 if (foundAParameter != bondtype[ftype].interactionTypes.end())
2055 /* Copy the A-state and B-state default parameters. */
2056 GMX_ASSERT(NRFPA(ftype) + NRFPB(ftype) <= MAXFORCEPARAM,
2057 "Bonded interactions may have at most 12 parameters");
2058 gmx::ArrayRef<const real> defaultParam = foundAParameter->forceParam();
2059 for (int j = 0; (j < NRFPA(ftype) + NRFPB(ftype)); j++)
2061 param.setForceParameter(j, defaultParam[j]);
2065 else if (NRFPA(ftype) == 0)
2070 defaultInteractionsOfType(ftype, bondtype, at, atypes, param, TRUE, &nparam_defB);
2071 if (foundBParameter != bondtype[ftype].interactionTypes.end())
2073 /* Copy only the B-state default parameters */
2074 gmx::ArrayRef<const real> defaultParam = foundBParameter->forceParam();
2075 for (int j = NRFPA(ftype); (j < NRFP(ftype)); j++)
2077 param.setForceParameter(j, defaultParam[j]);
2081 else if (NRFPB(ftype) == 0)
2086 else if (ftype == F_LJ14)
2088 bFoundA = default_nb_params(ftype, bondtype, at, ¶m, 0, FALSE, bGenPairs);
2089 bFoundB = default_nb_params(ftype, bondtype, at, ¶m, 0, TRUE, bGenPairs);
2091 else if (ftype == F_LJC14_Q)
2093 /* Fill in the A-state charges as default parameters */
2094 param.setForceParameter(0, fudgeQQ);
2095 param.setForceParameter(1, at->atom[param.ai()].q);
2096 param.setForceParameter(2, at->atom[param.aj()].q);
2097 /* The default LJ parameters are the standard 1-4 parameters */
2098 bFoundA = default_nb_params(F_LJ14, bondtype, at, ¶m, 3, FALSE, bGenPairs);
2101 else if (ftype == F_LJC_PAIRS_NB)
2103 /* Defaults are not supported here */
2109 gmx_incons("Unknown function type in push_bond");
2112 if (nread > nral_fmt)
2114 /* Manually specified parameters - in this case we discard multiple torsion info! */
2116 strcpy(format, asformat[nral_fmt - 1]);
2117 strcat(format, ccformat);
2119 nread = sscanf(line,
2135 if ((nread == NRFPA(ftype)) && (NRFPB(ftype) != 0))
2137 /* We only have to issue a warning if these atoms are perturbed! */
2139 gmx::ArrayRef<const int> paramAtoms = param.atoms();
2140 for (int j = 0; (j < nral); j++)
2142 bPert = bPert || PERTURBED(at->atom[paramAtoms[j]]);
2145 if (bPert && *bWarn_copy_A_B)
2147 auto message = gmx::formatString(
2148 "Some parameters for bonded interaction involving "
2149 "perturbed atoms are specified explicitly in "
2150 "state A, but not B - copying A to B");
2151 warning(wi, message);
2152 *bWarn_copy_A_B = FALSE;
2155 /* If only the A parameters were specified, copy them to the B state */
2156 /* The B-state parameters correspond to the first nrfpB
2157 * A-state parameters.
2159 for (int j = 0; (j < NRFPB(ftype)); j++)
2161 cc[nread++] = cc[j];
2165 /* If nread was 0 or EOF, no parameters were read => use defaults.
2166 * If nread was nrfpA we copied above so nread=nrfp.
2167 * If nread was nrfp we are cool.
2168 * For F_LJC14_Q we allow supplying fudgeQQ only.
2169 * Anything else is an error!
2171 if ((nread != 0) && (nread != EOF) && (nread != NRFP(ftype)) && !(ftype == F_LJC14_Q && nread == 1))
2173 auto message = gmx::formatString(
2174 "Incorrect number of parameters - found %d, expected %d "
2175 "or %d for %s (after the function type).",
2179 interaction_function[ftype].longname);
2180 warning_error_and_exit(wi, message, FARGS);
2183 for (int j = 0; (j < nread); j++)
2185 param.setForceParameter(j, cc[j]);
2187 /* Check whether we have to use the defaults */
2188 if (nread == NRFP(ftype))
2197 /* nread now holds the number of force parameters read! */
2202 /* When we have multiple terms it would be very dangerous to allow perturbations to a different atom type! */
2203 if (ftype == F_PDIHS)
2205 if ((nparam_defA != nparam_defB)
2206 || ((nparam_defA > 1 || nparam_defB > 1) && (foundAParameter != foundBParameter)))
2208 auto message = gmx::formatString(
2209 "Cannot automatically perturb a torsion with multiple terms to different "
2211 "Please specify perturbed parameters manually for this torsion in your "
2213 warning_error(wi, message);
2217 if (nread > 0 && nread < NRFPA(ftype))
2219 /* Issue an error, do not use defaults */
2220 auto message = gmx::formatString(
2221 "Not enough parameters, there should be at least %d (or 0 for defaults)", NRFPA(ftype));
2222 warning_error(wi, message);
2225 if (nread == 0 || nread == EOF)
2229 if (interaction_function[ftype].flags & IF_VSITE)
2231 for (int j = 0; j < MAXFORCEPARAM; j++)
2233 param.setForceParameter(j, NOTSET);
2237 /* flag to swap parity of vsi te construction */
2238 param.setForceParameter(1, -1);
2246 "NOTE: No default %s types, using zeroes\n",
2247 interaction_function[ftype].longname);
2251 auto message = gmx::formatString("No default %s types",
2252 interaction_function[ftype].longname);
2253 warning_error(wi, message);
2263 case F_VSITE3FAD: param.setForceParameter(0, 360 - param.c0()); break;
2264 case F_VSITE3OUT: param.setForceParameter(2, -param.c2()); break;
2270 /* We only have to issue a warning if these atoms are perturbed! */
2272 gmx::ArrayRef<const int> paramAtoms = param.atoms();
2273 for (int j = 0; (j < nral); j++)
2275 bPert = bPert || PERTURBED(at->atom[paramAtoms[j]]);
2280 auto message = gmx::formatString(
2281 "No default %s types for perturbed atoms, "
2282 "using normal values",
2283 interaction_function[ftype].longname);
2284 warning(wi, message);
2290 gmx::ArrayRef<const real> paramValue = param.forceParam();
2291 if ((ftype == F_PDIHS || ftype == F_ANGRES || ftype == F_ANGRESZ) && paramValue[5] != paramValue[2])
2293 auto message = gmx::formatString("%s multiplicity can not be perturbed %f!=%f",
2294 interaction_function[ftype].longname,
2297 warning_error_and_exit(wi, message, FARGS);
2300 if (IS_TABULATED(ftype) && param.c0() != param.c2())
2302 auto message = gmx::formatString("%s table number can not be perturbed %d!=%d",
2303 interaction_function[ftype].longname,
2304 gmx::roundToInt(param.c0()),
2305 gmx::roundToInt(param.c0()));
2306 warning_error_and_exit(wi, message, FARGS);
2309 /* Dont add R-B dihedrals where all parameters are zero (no interaction) */
2310 if (ftype == F_RBDIHS)
2314 for (int i = 0; i < NRFP(ftype); i++)
2316 if (paramValue[i] != 0.0)
2327 /* Put the values in the appropriate arrays */
2328 add_param_to_list(&bond[ftype], param);
2330 /* Push additional torsions from FF for ftype==9 if we have them.
2331 * We have already checked that the A/B states do not differ in this case,
2332 * so we do not have to double-check that again, or the vsite stuff.
2333 * In addition, those torsions cannot be automatically perturbed.
2335 if (bDef && ftype == F_PDIHS)
2337 for (int i = 1; i < nparam_defA; i++)
2339 /* Advance pointer! */
2340 foundAParameter += 2;
2341 gmx::ArrayRef<const real> forceParam = foundAParameter->forceParam();
2342 for (int j = 0; j < (NRFPA(ftype) + NRFPB(ftype)); j++)
2344 param.setForceParameter(j, forceParam[j]);
2346 /* And push the next term for this torsion */
2347 add_param_to_list(&bond[ftype], param);
2352 void push_cmap(Directive d,
2353 gmx::ArrayRef<InteractionsOfType> bondtype,
2354 gmx::ArrayRef<InteractionsOfType> bond,
2356 PreprocessingAtomTypes* atypes,
2360 const char* aaformat[MAXATOMLIST + 1] = {
2361 "%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"
2364 int ftype, nral, nread, ncmap_params;
2366 int aa[MAXATOMLIST + 1];
2369 ftype = ifunc_index(d, 1);
2373 nread = sscanf(line, aaformat[nral - 1], &aa[0], &aa[1], &aa[2], &aa[3], &aa[4], &aa[5]);
2380 else if (nread == nral)
2382 ftype = ifunc_index(d, 1);
2385 /* Check for double atoms and atoms out of bounds */
2386 for (int i = 0; i < nral; i++)
2388 if (aa[i] < 1 || aa[i] > at->nr)
2390 auto message = gmx::formatString(
2391 "Atom index (%d) in %s out of bounds (1-%d).\n"
2392 "This probably means that you have inserted topology section \"%s\"\n"
2393 "in a part belonging to a different molecule than you intended to.\n"
2394 "In that case move the \"%s\" section to the right molecule.",
2396 enumValueToString(d),
2398 enumValueToString(d),
2399 enumValueToString(d));
2400 warning_error_and_exit(wi, message, FARGS);
2403 for (int j = i + 1; (j < nral); j++)
2407 auto message = gmx::formatString(
2408 "Duplicate atom index (%d) in %s", aa[i], enumValueToString(d));
2409 warning_error(wi, message);
2414 /* default force parameters */
2415 std::vector<int> atoms;
2416 for (int j = 0; (j < nral); j++)
2418 atoms.emplace_back(aa[j] - 1);
2420 std::array<real, MAXFORCEPARAM> forceParam = { 0.0 };
2421 InteractionOfType param(atoms, forceParam, "");
2422 /* Get the cmap type for this cmap angle */
2423 bFound = default_cmap_params(bondtype, at, atypes, ¶m, FALSE, &cmap_type, &ncmap_params, wi);
2425 /* We want exactly one parameter (the cmap type in state A (currently no state B) back */
2426 if (bFound && ncmap_params == 1)
2428 /* Put the values in the appropriate arrays */
2429 param.setForceParameter(0, cmap_type);
2430 add_param_to_list(&bond[ftype], param);
2434 /* This is essentially the same check as in default_cmap_params() done one more time */
2436 gmx::formatString("Unable to assign a cmap type to torsion %d %d %d %d and %d\n",
2442 warning_error_and_exit(wi, message, FARGS);
2447 void push_vsitesn(Directive d, gmx::ArrayRef<InteractionsOfType> bond, t_atoms* at, char* line, warninp* wi)
2450 int type, ftype, n, ret, nj, a;
2452 double *weight = nullptr, weight_tot;
2454 std::array<real, MAXFORCEPARAM> forceParam = { 0.0 };
2456 ret = sscanf(ptr, "%d%n", &a, &n);
2461 gmx::formatString("Expected an atom index in section \"%s\"", enumValueToString(d));
2462 warning_error_and_exit(wi, message, FARGS);
2465 sscanf(ptr, "%d%n", &type, &n);
2467 ftype = ifunc_index(d, type);
2468 int firstAtom = a - 1;
2474 ret = sscanf(ptr, "%d%n", &a, &n);
2480 srenew(atc, nj + 20);
2481 srenew(weight, nj + 20);
2486 case 1: weight[nj] = 1; break;
2488 /* Here we use the A-state mass as a parameter.
2489 * Note that the B-state mass has no influence.
2491 weight[nj] = at->atom[atc[nj]].m;
2495 ret = sscanf(ptr, "%lf%n", &(weight[nj]), &n);
2499 auto message = gmx::formatString(
2500 "No weight or negative weight found for vsiten "
2501 "constructing atom %d (atom index %d)",
2504 warning_error_and_exit(wi, message, FARGS);
2508 auto message = gmx::formatString("Unknown vsiten type %d", type);
2509 warning_error_and_exit(wi, message, FARGS);
2511 weight_tot += weight[nj];
2518 auto message = gmx::formatString("Expected more than one atom index in section \"%s\"",
2519 enumValueToString(d));
2520 warning_error_and_exit(wi, message, FARGS);
2523 if (weight_tot == 0)
2525 warning_error_and_exit(wi, "The total mass of the construting atoms is zero", FARGS);
2528 for (int j = 0; j < nj; j++)
2530 std::vector<int> atoms = { firstAtom, atc[j] };
2532 forceParam[1] = weight[j] / weight_tot;
2533 /* Put the values in the appropriate arrays */
2534 add_param_to_list(&bond[ftype], InteractionOfType(atoms, forceParam));
2541 void push_mol(gmx::ArrayRef<MoleculeInformation> mols, char* pline, int* whichmol, int* nrcopies, warninp* wi)
2545 if (sscanf(pline, "%s%d", type, nrcopies) != 2)
2551 /* Search moleculename.
2552 * Here we originally only did case insensitive matching. But because
2553 * some PDB files can have many chains and use case to generate more
2554 * chain-identifiers, which in turn end up in our moleculetype name,
2555 * we added support for case-sensitivity.
2562 for (const auto& mol : mols)
2564 if (strcmp(type, *(mol.name)) == 0)
2569 if (gmx_strcasecmp(type, *(mol.name)) == 0)
2579 // select the case sensitive match
2580 *whichmol = matchcs;
2584 // avoid matching case-insensitive when we have multiple matches
2587 auto message = gmx::formatString(
2588 "For moleculetype '%s' in [ system ] %d case insensitive "
2589 "matches, but %d case sensitive matches were found. Check "
2590 "the case of the characters in the moleculetypes.",
2594 warning_error_and_exit(wi, message, FARGS);
2598 // select the unique case insensitive match
2599 *whichmol = matchci;
2603 auto message = gmx::formatString("No such moleculetype %s", type);
2604 warning_error_and_exit(wi, message, FARGS);
2609 void push_excl(char* line, gmx::ArrayRef<gmx::ExclusionBlock> b2, warninp* wi)
2613 char base[STRLEN], format[STRLEN];
2615 if (sscanf(line, "%d", &i) == 0)
2620 if ((1 <= i) && (i <= b2.ssize()))
2628 strcpy(base, "%*d");
2631 strcpy(format, base);
2632 strcat(format, "%d");
2633 n = sscanf(line, format, &j);
2636 if ((1 <= j) && (j <= b2.ssize()))
2639 b2[i].atomNumber.push_back(j);
2640 /* also add the reverse exclusion! */
2641 b2[j].atomNumber.push_back(i);
2642 strcat(base, "%*d");
2646 auto message = gmx::formatString("Invalid Atomnr j: %d, b2->nr: %zu\n", j, b2.size());
2647 warning_error_and_exit(wi, message, FARGS);
2653 int add_atomtype_decoupled(t_symtab* symtab, PreprocessingAtomTypes* at, t_nbparam*** nbparam, t_nbparam*** pair)
2658 /* Define an atom type with all parameters set to zero (no interactions) */
2661 /* Type for decoupled atoms could be anything,
2662 * this should be changed automatically later when required.
2664 atom.ptype = ParticleType::Atom;
2666 std::array<real, MAXFORCEPARAM> forceParam = { 0.0 };
2667 nr = at->addType(symtab, atom, "decoupled", InteractionOfType({}, forceParam, ""), -1, 0);
2669 /* Add space in the non-bonded parameters matrix */
2670 realloc_nb_params(at, nbparam, pair);
2675 static void convert_pairs_to_pairsQ(gmx::ArrayRef<InteractionsOfType> interactions, real fudgeQQ, t_atoms* atoms)
2677 /* Add the pair list to the pairQ list */
2678 std::vector<InteractionOfType> paramnew;
2680 gmx::ArrayRef<const InteractionOfType> paramp1 = interactions[F_LJ14].interactionTypes;
2681 gmx::ArrayRef<const InteractionOfType> paramp2 = interactions[F_LJC14_Q].interactionTypes;
2683 /* Fill in the new F_LJC14_Q array with the old one. NOTE:
2684 it may be possible to just ADD the converted F_LJ14 array
2685 to the old F_LJC14_Q array, but since we have to create
2686 a new sized memory structure, better just to deep copy it all.
2690 for (const auto& param : paramp2)
2692 paramnew.emplace_back(param);
2695 for (const auto& param : paramp1)
2697 std::vector<real> forceParam = {
2698 fudgeQQ, atoms->atom[param.ai()].q, atoms->atom[param.aj()].q, param.c0(), param.c1()
2700 paramnew.emplace_back(param.atoms(), forceParam, "");
2703 /* now assign the new data to the F_LJC14_Q structure */
2704 interactions[F_LJC14_Q].interactionTypes = paramnew;
2706 /* Empty the LJ14 pairlist */
2707 interactions[F_LJ14].interactionTypes.clear();
2710 static void generate_LJCpairsNB(MoleculeInformation* mol, int nb_funct, InteractionsOfType* nbp, warninp* wi)
2716 atom = mol->atoms.atom;
2718 ntype = static_cast<int>(std::sqrt(static_cast<double>(nbp->size())));
2719 GMX_ASSERT(ntype * ntype == gmx::ssize(*nbp),
2720 "Number of pairs of generated non-bonded parameters should be a perfect square");
2722 /* Add a pair interaction for all non-excluded atom pairs */
2723 const auto& excls = mol->excls;
2724 for (int i = 0; i < n; i++)
2726 for (int j = i + 1; j < n; j++)
2728 bool pairIsExcluded = false;
2729 for (const int atomK : excls[i])
2733 pairIsExcluded = true;
2736 if (!pairIsExcluded)
2738 if (nb_funct != F_LJ)
2740 auto message = gmx::formatString(
2741 "Can only generate non-bonded pair interactions "
2742 "for Van der Waals type Lennard-Jones");
2743 warning_error_and_exit(wi, message, FARGS);
2745 std::vector<int> atoms = { i, j };
2746 std::vector<real> forceParam = {
2749 nbp->interactionTypes[ntype * atom[i].type + atom[j].type].c0(),
2750 nbp->interactionTypes[ntype * atom[i].type + atom[j].type].c1()
2752 add_param_to_list(&mol->interactions[F_LJC_PAIRS_NB], InteractionOfType(atoms, forceParam));
2758 static void set_excl_all(gmx::ListOfLists<int>* excl)
2760 /* Get rid of the current exclusions and exclude all atom pairs */
2761 const int numAtoms = excl->ssize();
2762 std::vector<int> exclusionsForAtom(numAtoms);
2763 for (int i = 0; i < numAtoms; i++)
2765 exclusionsForAtom[i] = i;
2768 for (int i = 0; i < numAtoms; i++)
2770 excl->pushBack(exclusionsForAtom);
2774 static void decouple_atoms(t_atoms* atoms,
2775 int atomtype_decouple,
2778 const char* mol_name,
2783 for (i = 0; i < atoms->nr; i++)
2787 atom = &atoms->atom[i];
2789 if (atom->qB != atom->q || atom->typeB != atom->type)
2791 auto message = gmx::formatString(
2792 "Atom %d in molecule type '%s' has different A and B state "
2793 "charges and/or atom types set in the topology file as well "
2794 "as through the mdp option '%s'. You can not use both "
2795 "these methods simultaneously.",
2799 warning_error_and_exit(wi, message, FARGS);
2802 if (couple_lam0 == ecouplamNONE || couple_lam0 == ecouplamVDW)
2806 if (couple_lam0 == ecouplamNONE || couple_lam0 == ecouplamQ)
2808 atom->type = atomtype_decouple;
2810 if (couple_lam1 == ecouplamNONE || couple_lam1 == ecouplamVDW)
2814 if (couple_lam1 == ecouplamNONE || couple_lam1 == ecouplamQ)
2816 atom->typeB = atomtype_decouple;
2821 void convert_moltype_couple(MoleculeInformation* mol,
2822 int atomtype_decouple,
2828 InteractionsOfType* nbp,
2831 convert_pairs_to_pairsQ(mol->interactions, fudgeQQ, &mol->atoms);
2834 generate_LJCpairsNB(mol, nb_funct, nbp, wi);
2835 set_excl_all(&mol->excls);
2837 decouple_atoms(&mol->atoms, atomtype_decouple, couple_lam0, couple_lam1, *mol->name, wi);