Remove obsolete mdp option ns-type
[gromacs.git] / src / gromacs / gmxpreprocess / toppush.cpp
blobff06eb8428b45cd14bc446d3020ea6c7d3bbea64
1 /*
2 * This file is part of the GROMACS molecular simulation package.
4 * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
5 * Copyright (c) 2001-2004, The GROMACS development team.
6 * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
7 * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
8 * and including many others, as listed in the AUTHORS file in the
9 * top-level source directory and at http://www.gromacs.org.
11 * GROMACS is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU Lesser General Public License
13 * as published by the Free Software Foundation; either version 2.1
14 * of the License, or (at your option) any later version.
16 * GROMACS is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * Lesser General Public License for more details.
21 * You should have received a copy of the GNU Lesser General Public
22 * License along with GROMACS; if not, see
23 * http://www.gnu.org/licenses, or write to the Free Software Foundation,
24 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
26 * If you want to redistribute modifications to GROMACS, please
27 * consider that scientific software is very special. Version
28 * control is crucial - bugs must be traceable. We will be happy to
29 * consider code for inclusion in the official distribution, but
30 * derived work must not be called official GROMACS. Details are found
31 * in the README & COPYING files - if they are missing, get the
32 * official version at http://www.gromacs.org.
34 * To help us fund GROMACS development, we humbly ask that you cite
35 * the research papers on the package. Check out http://www.gromacs.org.
37 #include "gmxpre.h"
39 #include "toppush.h"
41 #include <cctype>
42 #include <cmath>
43 #include <cstdlib>
44 #include <cstring>
46 #include <algorithm>
47 #include <string>
49 #include "gromacs/fileio/warninp.h"
50 #include "gromacs/gmxpreprocess/gpp_atomtype.h"
51 #include "gromacs/gmxpreprocess/gpp_bond_atomtype.h"
52 #include "gromacs/gmxpreprocess/grompp_impl.h"
53 #include "gromacs/gmxpreprocess/notset.h"
54 #include "gromacs/gmxpreprocess/readir.h"
55 #include "gromacs/gmxpreprocess/topdirs.h"
56 #include "gromacs/gmxpreprocess/toputil.h"
57 #include "gromacs/math/functions.h"
58 #include "gromacs/mdtypes/md_enums.h"
59 #include "gromacs/topology/exclusionblocks.h"
60 #include "gromacs/topology/ifunc.h"
61 #include "gromacs/topology/symtab.h"
62 #include "gromacs/utility/arrayref.h"
63 #include "gromacs/utility/cstringutil.h"
64 #include "gromacs/utility/fatalerror.h"
65 #include "gromacs/utility/gmxassert.h"
66 #include "gromacs/utility/smalloc.h"
67 #include "gromacs/utility/stringutil.h"
69 void generate_nbparams(int comb,
70 int ftype,
71 InteractionsOfType *interactions,
72 PreprocessingAtomTypes *atypes,
73 warninp *wi)
75 int nr, nrfp;
76 real c, bi, bj, ci, cj, ci0, ci1, ci2, cj0, cj1, cj2;
78 /* Lean mean shortcuts */
79 nr = atypes->size();
80 nrfp = NRFP(ftype);
81 interactions->interactionTypes.clear();
83 std::array<real, MAXFORCEPARAM> forceParam = {NOTSET};
84 /* Fill the matrix with force parameters */
85 switch (ftype)
87 case F_LJ:
88 switch (comb)
90 case eCOMB_GEOMETRIC:
91 /* Gromos rules */
92 for (int i = 0; (i < nr); i++)
94 for (int j = 0; (j < nr); j++)
96 for (int nf = 0; (nf < nrfp); nf++)
98 ci = atypes->atomNonBondedParamFromAtomType(i, nf);
99 cj = atypes->atomNonBondedParamFromAtomType(j, nf);
100 c = std::sqrt(ci * cj);
101 forceParam[nf] = c;
103 interactions->interactionTypes.emplace_back(InteractionOfType({}, forceParam));
106 break;
108 case eCOMB_ARITHMETIC:
109 /* c0 and c1 are sigma and epsilon */
110 for (int i = 0; (i < nr); i++)
112 for (int j = 0; (j < nr); j++)
114 ci0 = atypes->atomNonBondedParamFromAtomType(i, 0);
115 cj0 = atypes->atomNonBondedParamFromAtomType(j, 0);
116 ci1 = atypes->atomNonBondedParamFromAtomType(i, 1);
117 cj1 = atypes->atomNonBondedParamFromAtomType(j, 1);
118 forceParam[0] = (fabs(ci0) + fabs(cj0))*0.5;
119 /* Negative sigma signals that c6 should be set to zero later,
120 * so we need to propagate that through the combination rules.
122 if (ci0 < 0 || cj0 < 0)
124 forceParam[0] *= -1;
126 forceParam[1] = std::sqrt(ci1*cj1);
127 interactions->interactionTypes.emplace_back(InteractionOfType({}, forceParam));
131 break;
132 case eCOMB_GEOM_SIG_EPS:
133 /* c0 and c1 are sigma and epsilon */
134 for (int i = 0; (i < nr); i++)
136 for (int j = 0; (j < nr); j++)
138 ci0 = atypes->atomNonBondedParamFromAtomType(i, 0);
139 cj0 = atypes->atomNonBondedParamFromAtomType(j, 0);
140 ci1 = atypes->atomNonBondedParamFromAtomType(i, 1);
141 cj1 = atypes->atomNonBondedParamFromAtomType(j, 1);
142 forceParam[0] = std::sqrt(std::fabs(ci0*cj0));
143 /* Negative sigma signals that c6 should be set to zero later,
144 * so we need to propagate that through the combination rules.
146 if (ci0 < 0 || cj0 < 0)
148 forceParam[0] *= -1;
150 forceParam[1] = std::sqrt(ci1*cj1);
151 interactions->interactionTypes.emplace_back(InteractionOfType({}, forceParam));
155 break;
156 default:
157 auto message = gmx::formatString("No such combination rule %d", comb);
158 warning_error_and_exit(wi, message, FARGS);
160 break;
162 case F_BHAM:
163 /* Buckingham rules */
164 for (int i = 0; (i < nr); i++)
166 for (int j = 0; (j < nr); j++)
168 ci0 = atypes->atomNonBondedParamFromAtomType(i, 0);
169 cj0 = atypes->atomNonBondedParamFromAtomType(j, 0);
170 ci2 = atypes->atomNonBondedParamFromAtomType(i, 2);
171 cj2 = atypes->atomNonBondedParamFromAtomType(j, 2);
172 bi = atypes->atomNonBondedParamFromAtomType(i, 1);
173 bj = atypes->atomNonBondedParamFromAtomType(j, 1);
174 forceParam[0] = std::sqrt(ci0 * cj0);
175 if ((bi == 0) || (bj == 0))
177 forceParam[1] = 0;
179 else
181 forceParam[1] = 2.0/(1/bi+1/bj);
183 forceParam[2] = std::sqrt(ci2 * cj2);
184 interactions->interactionTypes.emplace_back(InteractionOfType({}, forceParam));
188 break;
189 default:
190 auto message = gmx::formatString("Invalid nonbonded type %s",
191 interaction_function[ftype].longname);
192 warning_error(wi, message);
196 /*! \brief Used to temporarily store the explicit non-bonded parameter
197 * combinations, which will be copied to InteractionsOfType. */
198 struct t_nbparam
200 //! Has this combination been set.
201 bool bSet;
202 //! The non-bonded parameters
203 real c[4];
206 static void realloc_nb_params(PreprocessingAtomTypes *atypes,
207 t_nbparam ***nbparam, t_nbparam ***pair)
209 /* Add space in the non-bonded parameters matrix */
210 int atnr = atypes->size();
211 srenew(*nbparam, atnr);
212 snew((*nbparam)[atnr-1], atnr);
213 if (pair)
215 srenew(*pair, atnr);
216 snew((*pair)[atnr-1], atnr);
220 int copy_nbparams(t_nbparam **param, int ftype, InteractionsOfType *interactions, int nr)
222 int nrfp, ncopy;
224 nrfp = NRFP(ftype);
226 ncopy = 0;
227 for (int i = 0; i < nr; i++)
229 for (int j = 0; j <= i; j++)
231 GMX_RELEASE_ASSERT(param, "Must have valid parameters");
232 if (param[i][j].bSet)
234 for (int f = 0; f < nrfp; f++)
236 interactions->interactionTypes[nr*i+j].setForceParameter(f, param[i][j].c[f]);
237 interactions->interactionTypes[nr*j+i].setForceParameter(f, param[i][j].c[f]);
239 ncopy++;
244 return ncopy;
247 void free_nbparam(t_nbparam **param, int nr)
249 int i;
251 GMX_RELEASE_ASSERT(param, "Must have valid parameters");
252 for (i = 0; i < nr; i++)
254 GMX_RELEASE_ASSERT(param[i], "Must have valid parameters");
255 sfree(param[i]);
257 sfree(param);
260 static void copy_B_from_A(int ftype, double *c)
262 int nrfpA, nrfpB, i;
264 nrfpA = NRFPA(ftype);
265 nrfpB = NRFPB(ftype);
267 /* Copy the B parameters from the first nrfpB A parameters */
268 for (i = 0; (i < nrfpB); i++)
270 c[nrfpA+i] = c[i];
274 void push_at (t_symtab *symtab, PreprocessingAtomTypes *at, PreprocessingBondAtomType *bondAtomType,
275 char *line, int nb_funct,
276 t_nbparam ***nbparam, t_nbparam ***pair,
277 warninp *wi)
279 typedef struct {
280 const char *entry;
281 int ptype;
282 } t_xlate;
283 t_xlate xl[eptNR] = {
284 { "A", eptAtom },
285 { "N", eptNucleus },
286 { "S", eptShell },
287 { "B", eptBond },
288 { "V", eptVSite },
291 int nr, nfields, j, pt, nfp0 = -1;
292 int batype_nr, nread;
293 char type[STRLEN], btype[STRLEN], ptype[STRLEN];
294 double m, q;
295 double c[MAXFORCEPARAM];
296 char tmpfield[12][100]; /* Max 12 fields of width 100 */
297 t_atom *atom;
298 int atomnr;
299 bool have_atomic_number;
300 bool have_bonded_type;
302 snew(atom, 1);
304 /* First assign input line to temporary array */
305 nfields = sscanf(line, "%s%s%s%s%s%s%s%s%s%s%s%s",
306 tmpfield[0], tmpfield[1], tmpfield[2], tmpfield[3], tmpfield[4], tmpfield[5],
307 tmpfield[6], tmpfield[7], tmpfield[8], tmpfield[9], tmpfield[10], tmpfield[11]);
309 /* Comments on optional fields in the atomtypes section:
311 * The force field format is getting a bit old. For OPLS-AA we needed
312 * to add a special bonded atomtype, and for Gerrit Groenhofs QM/MM stuff
313 * we also needed the atomic numbers.
314 * To avoid making all old or user-generated force fields unusable we
315 * have introduced both these quantities as optional columns, and do some
316 * acrobatics to check whether they are present or not.
317 * This will all look much nicer when we switch to XML... sigh.
319 * Field 0 (mandatory) is the nonbonded type name. (string)
320 * Field 1 (optional) is the bonded type (string)
321 * Field 2 (optional) is the atomic number (int)
322 * Field 3 (mandatory) is the mass (numerical)
323 * Field 4 (mandatory) is the charge (numerical)
324 * Field 5 (mandatory) is the particle type (single character)
325 * This is followed by a number of nonbonded parameters.
327 * The safest way to identify the format is the particle type field.
329 * So, here is what we do:
331 * A. Read in the first six fields as strings
332 * B. If field 3 (starting from 0) is a single char, we have neither
333 * bonded_type or atomic numbers.
334 * C. If field 5 is a single char we have both.
335 * D. If field 4 is a single char we check field 1. If this begins with
336 * an alphabetical character we have bonded types, otherwise atomic numbers.
339 if (nfields < 6)
341 too_few(wi);
342 return;
345 if ( (strlen(tmpfield[5]) == 1) && isalpha(tmpfield[5][0]) )
347 have_bonded_type = TRUE;
348 have_atomic_number = TRUE;
350 else if ( (strlen(tmpfield[3]) == 1) && isalpha(tmpfield[3][0]) )
352 have_bonded_type = FALSE;
353 have_atomic_number = FALSE;
355 else
357 have_bonded_type = ( isalpha(tmpfield[1][0]) != 0 );
358 have_atomic_number = !have_bonded_type;
361 /* optional fields */
362 atomnr = -1;
364 switch (nb_funct)
367 case F_LJ:
368 nfp0 = 2;
370 if (have_atomic_number)
372 if (have_bonded_type)
374 nread = sscanf(line, "%s%s%d%lf%lf%s%lf%lf",
375 type, btype, &atomnr, &m, &q, ptype, &c[0], &c[1]);
376 if (nread < 8)
378 too_few(wi);
379 return;
382 else
384 /* have_atomic_number && !have_bonded_type */
385 nread = sscanf(line, "%s%d%lf%lf%s%lf%lf",
386 type, &atomnr, &m, &q, ptype, &c[0], &c[1]);
387 if (nread < 7)
389 too_few(wi);
390 return;
394 else
396 if (have_bonded_type)
398 /* !have_atomic_number && have_bonded_type */
399 nread = sscanf(line, "%s%s%lf%lf%s%lf%lf",
400 type, btype, &m, &q, ptype, &c[0], &c[1]);
401 if (nread < 7)
403 too_few(wi);
404 return;
407 else
409 /* !have_atomic_number && !have_bonded_type */
410 nread = sscanf(line, "%s%lf%lf%s%lf%lf",
411 type, &m, &q, ptype, &c[0], &c[1]);
412 if (nread < 6)
414 too_few(wi);
415 return;
420 if (!have_bonded_type)
422 strcpy(btype, type);
425 if (!have_atomic_number)
427 atomnr = -1;
430 break;
432 case F_BHAM:
433 nfp0 = 3;
435 if (have_atomic_number)
437 if (have_bonded_type)
439 nread = sscanf(line, "%s%s%d%lf%lf%s%lf%lf%lf",
440 type, btype, &atomnr, &m, &q, ptype, &c[0], &c[1], &c[2]);
441 if (nread < 9)
443 too_few(wi);
444 return;
447 else
449 /* have_atomic_number && !have_bonded_type */
450 nread = sscanf(line, "%s%d%lf%lf%s%lf%lf%lf",
451 type, &atomnr, &m, &q, ptype, &c[0], &c[1], &c[2]);
452 if (nread < 8)
454 too_few(wi);
455 return;
459 else
461 if (have_bonded_type)
463 /* !have_atomic_number && have_bonded_type */
464 nread = sscanf(line, "%s%s%lf%lf%s%lf%lf%lf",
465 type, btype, &m, &q, ptype, &c[0], &c[1], &c[2]);
466 if (nread < 8)
468 too_few(wi);
469 return;
472 else
474 /* !have_atomic_number && !have_bonded_type */
475 nread = sscanf(line, "%s%lf%lf%s%lf%lf%lf",
476 type, &m, &q, ptype, &c[0], &c[1], &c[2]);
477 if (nread < 7)
479 too_few(wi);
480 return;
485 if (!have_bonded_type)
487 strcpy(btype, type);
490 if (!have_atomic_number)
492 atomnr = -1;
495 break;
497 default:
498 auto message = gmx::formatString("Invalid function type %d in push_at", nb_funct);
499 warning_error_and_exit(wi, message, FARGS);
501 for (int j = nfp0; (j < MAXFORCEPARAM); j++)
503 c[j] = 0.0;
505 std::array<real, MAXFORCEPARAM> forceParam;
507 if (strlen(type) == 1 && isdigit(type[0]))
509 warning_error_and_exit(wi, "Atom type names can't be single digits.", FARGS);
512 if (strlen(btype) == 1 && isdigit(btype[0]))
514 warning_error_and_exit(wi, "Bond atom type names can't be single digits.", FARGS);
517 /* Hack to read old topologies */
518 if (gmx_strcasecmp(ptype, "D") == 0)
520 sprintf(ptype, "V");
522 for (j = 0; (j < eptNR); j++)
524 if (gmx_strcasecmp(ptype, xl[j].entry) == 0)
526 break;
529 if (j == eptNR)
531 auto message = gmx::formatString("Invalid particle type %s", ptype);
532 warning_error_and_exit(wi, message, FARGS);
534 pt = xl[j].ptype;
536 atom->q = q;
537 atom->m = m;
538 atom->ptype = pt;
539 for (int i = 0; i < MAXFORCEPARAM; i++)
541 forceParam[i] = c[i];
544 InteractionOfType interactionType({}, forceParam, "");
546 batype_nr = bondAtomType->addBondAtomType(symtab, btype);
548 if ((nr = at->atomTypeFromName(type)) != NOTSET)
550 auto message = gmx::formatString
551 ("Atomtype %s was defined previously (e.g. in the forcefield files), "
552 "and has now been defined again. This could happen e.g. if you would "
553 "use a self-contained molecule .itp file that duplicates or replaces "
554 "the contents of the standard force-field files. You should check "
555 "the contents of your files and remove such repetition. If you know "
556 "you should override the previous definition, then you could choose "
557 "to suppress this warning with -maxwarn.", type);
558 warning(wi, message);
559 if ((nr = at->setType(nr, symtab, *atom, type, interactionType, batype_nr,
560 atomnr)) == NOTSET)
562 auto message = gmx::formatString("Replacing atomtype %s failed", type);
563 warning_error_and_exit(wi, message, FARGS);
566 else if ((at->addType(symtab, *atom, type, interactionType,
567 batype_nr, atomnr)) == NOTSET)
569 auto message = gmx::formatString("Adding atomtype %s failed", type);
570 warning_error_and_exit(wi, message, FARGS);
572 else
574 /* Add space in the non-bonded parameters matrix */
575 realloc_nb_params(at, nbparam, pair);
577 sfree(atom);
580 //! Return whether the contents of \c a and \c b are the same, considering also reversed order.
581 template <typename T>
582 static bool equalEitherForwardOrBackward(gmx::ArrayRef<const T> a, gmx::ArrayRef<const T> b)
584 return (std::equal(a.begin(), a.end(), b.begin()) ||
585 std::equal(a.begin(), a.end(), b.rbegin()));
588 static void push_bondtype(InteractionsOfType *bt,
589 const InteractionOfType &b,
590 int nral,
591 int ftype,
592 bool bAllowRepeat,
593 const char *line,
594 warninp *wi)
596 int nr = bt->size();
597 int nrfp = NRFP(ftype);
599 /* If bAllowRepeat is TRUE, we allow multiple entries as long as they
600 are on directly _adjacent_ lines.
603 /* First check if our atomtypes are _identical_ (not reversed) to the previous
604 entry. If they are not identical we search for earlier duplicates. If they are
605 we can skip it, since we already searched for the first line
606 in this group.
609 bool isContinuationOfBlock = false;
610 if (bAllowRepeat && nr > 1)
612 isContinuationOfBlock = true;
613 gmx::ArrayRef<const int> newParAtom = b.atoms();
614 gmx::ArrayRef<const int> sysParAtom = bt->interactionTypes[nr - 2].atoms();
615 for (int j = 0; j < nral; j++)
617 if (newParAtom[j] != sysParAtom[j])
619 isContinuationOfBlock = false;
624 /* Search for earlier duplicates if this entry was not a continuation
625 from the previous line.
627 bool addBondType = true;
628 bool haveWarned = false;
629 bool haveErrored = false;
630 for (int i = 0; (i < nr); i++)
632 gmx::ArrayRef<const int> bParams = b.atoms();
633 gmx::ArrayRef<const int> testParams = bt->interactionTypes[i].atoms();
634 GMX_RELEASE_ASSERT(bParams.size() == testParams.size(), "Number of atoms needs to be the same between parameters");
635 if (equalEitherForwardOrBackward(bParams, testParams))
637 GMX_ASSERT(nrfp <= MAXFORCEPARAM, "This is ensured in other places, but we need this assert to keep the clang analyzer happy");
638 const bool identicalParameters = std::equal(bt->interactionTypes[i].forceParam().begin(),
639 bt->interactionTypes[i].forceParam().begin() + nrfp, b.forceParam().begin());
641 if (!bAllowRepeat || identicalParameters)
643 addBondType = false;
646 if (!identicalParameters)
648 if (bAllowRepeat)
650 /* With dihedral type 9 we only allow for repeating
651 * of the same parameters with blocks with 1 entry.
652 * Allowing overriding is too complex to check.
654 if (!isContinuationOfBlock && !haveErrored)
656 warning_error(wi, "Encountered a second block of parameters for dihedral "
657 "type 9 for the same atoms, with either different parameters "
658 "and/or the first block has multiple lines. This is not supported.");
659 haveErrored = true;
662 else if (!haveWarned)
664 auto message = gmx::formatString
665 ("Bondtype %s was defined previously (e.g. in the forcefield files), "
666 "and has now been defined again. This could happen e.g. if you would "
667 "use a self-contained molecule .itp file that duplicates or replaces "
668 "the contents of the standard force-field files. You should check "
669 "the contents of your files and remove such repetition. If you know "
670 "you should override the previous definition, then you could choose "
671 "to suppress this warning with -maxwarn.%s",
672 interaction_function[ftype].longname,
673 (ftype == F_PDIHS) ?
674 "\nUse dihedraltype 9 to allow several multiplicity terms. Only consecutive "
675 "lines are combined. Non-consective lines overwrite each other."
676 : "");
677 warning(wi, message);
679 fprintf(stderr, " old: ");
680 gmx::ArrayRef<const real> forceParam = bt->interactionTypes[i].forceParam();
681 for (int j = 0; j < nrfp; j++)
683 fprintf(stderr, " %g", forceParam[j]);
685 fprintf(stderr, " \n new: %s\n\n", line);
687 haveWarned = true;
691 if (!identicalParameters && !bAllowRepeat)
693 /* Overwrite the parameters with the latest ones */
694 // TODO considering improving the following code by replacing with:
695 // std::copy(b->c, b->c + nrfp, bt->param[i].c);
696 gmx::ArrayRef<const real> forceParam = b.forceParam();
697 for (int j = 0; j < nrfp; j++)
699 bt->interactionTypes[i].setForceParameter(j, forceParam[j]);
705 if (addBondType)
707 /* fill the arrays up and down */
708 bt->interactionTypes.emplace_back(
709 InteractionOfType(b.atoms(), b.forceParam(), b.interactionTypeName()));
710 /* need to store force values because they might change below */
711 std::vector<real> forceParam(b.forceParam().begin(), b.forceParam().end());
713 /* The definitions of linear angles depend on the order of atoms,
714 * that means that for atoms i-j-k, with certain parameter a, the
715 * corresponding k-j-i angle will have parameter 1-a.
717 if (ftype == F_LINEAR_ANGLES)
719 forceParam[0] = 1- forceParam[0];
720 forceParam[2] = 1- forceParam[2];
722 std::vector<int> atoms;
723 gmx::ArrayRef<const int> oldAtoms = b.atoms();
724 for (auto oldAtom = oldAtoms.rbegin(); oldAtom != oldAtoms.rend(); oldAtom++)
726 atoms.emplace_back(*oldAtom);
728 bt->interactionTypes.emplace_back(InteractionOfType(atoms, forceParam, b.interactionTypeName()));
732 static std::vector<int> atomTypesFromAtomNames(const PreprocessingAtomTypes *atomTypes,
733 const PreprocessingBondAtomType *bondAtomTypes,
734 gmx::ArrayRef<const char[20]> atomNames,
735 warninp *wi)
738 GMX_RELEASE_ASSERT(!(!atomNames.empty() && !atomTypes && !bondAtomTypes),
739 "Need to have either valid atomtypes or bondatomtypes object");
741 std::vector<int> atomTypesFromAtomNames;
742 for (const auto &name : atomNames)
744 if (atomTypes != nullptr)
746 int atomType = atomTypes->atomTypeFromName(name);
747 if (atomType == NOTSET)
749 auto message = gmx::formatString("Unknown atomtype %s\n", name);
750 warning_error_and_exit(wi, message, FARGS);
752 atomTypesFromAtomNames.emplace_back(atomType);
754 else if (bondAtomTypes != nullptr)
756 int atomType = bondAtomTypes->bondAtomTypeFromName(name);
757 if (atomType == NOTSET)
759 auto message = gmx::formatString("Unknown bond_atomtype %s\n", name);
760 warning_error_and_exit(wi, message, FARGS);
762 atomTypesFromAtomNames.emplace_back(atomType);
765 return atomTypesFromAtomNames;
769 void push_bt(Directive d,
770 gmx::ArrayRef<InteractionsOfType> bt,
771 int nral,
772 PreprocessingAtomTypes *at,
773 PreprocessingBondAtomType *bondAtomType,
774 char *line,
775 warninp *wi)
777 const char *formal[MAXATOMLIST+1] = {
778 "%s",
779 "%s%s",
780 "%s%s%s",
781 "%s%s%s%s",
782 "%s%s%s%s%s",
783 "%s%s%s%s%s%s",
784 "%s%s%s%s%s%s%s"
786 const char *formnl[MAXATOMLIST+1] = {
787 "%*s",
788 "%*s%*s",
789 "%*s%*s%*s",
790 "%*s%*s%*s%*s",
791 "%*s%*s%*s%*s%*s",
792 "%*s%*s%*s%*s%*s%*s",
793 "%*s%*s%*s%*s%*s%*s%*s"
795 const char *formlf = "%lf%lf%lf%lf%lf%lf%lf%lf%lf%lf%lf%lf%lf";
796 int i, ft, ftype, nn, nrfp, nrfpA;
797 char f1[STRLEN];
798 char alc[MAXATOMLIST+1][20];
799 /* One force parameter more, so we can check if we read too many */
800 double c[MAXFORCEPARAM+1];
802 if ((bondAtomType && at) || (!bondAtomType && !at))
804 gmx_incons("You should pass either bondAtomType or at to push_bt");
807 /* Make format string (nral ints+functype) */
808 if ((nn = sscanf(line, formal[nral],
809 alc[0], alc[1], alc[2], alc[3], alc[4], alc[5])) != nral+1)
811 auto message = gmx::formatString("Not enough atomtypes (%d instead of %d)", nn-1, nral);
812 warning_error(wi, message);
813 return;
816 ft = strtol(alc[nral], nullptr, 10);
817 ftype = ifunc_index(d, ft);
818 nrfp = NRFP(ftype);
819 nrfpA = interaction_function[ftype].nrfpA;
820 strcpy(f1, formnl[nral]);
821 strcat(f1, formlf);
822 if ((nn = sscanf(line, f1, &c[0], &c[1], &c[2], &c[3], &c[4], &c[5], &c[6], &c[7], &c[8], &c[9], &c[10], &c[11], &c[12]))
823 != nrfp)
825 if (nn == nrfpA)
827 /* Copy the B-state from the A-state */
828 copy_B_from_A(ftype, c);
830 else
832 if (nn < nrfpA)
834 warning_error(wi, "Not enough parameters");
836 else if (nn > nrfpA && nn < nrfp)
838 warning_error(wi, "Too many parameters or not enough parameters for topology B");
840 else if (nn > nrfp)
842 warning_error(wi, "Too many parameters");
844 for (i = nn; (i < nrfp); i++)
846 c[i] = 0.0;
850 std::vector<int> atomTypes = atomTypesFromAtomNames(at,
851 bondAtomType,
852 gmx::arrayRefFromArray(alc, nral),
853 wi);
854 std::array<real, MAXFORCEPARAM> forceParam;
855 for (int i = 0; (i < nrfp); i++)
857 forceParam[i] = c[i];
859 push_bondtype (&(bt[ftype]), InteractionOfType(atomTypes, forceParam), nral, ftype, FALSE, line, wi);
863 void push_dihedraltype(Directive d, gmx::ArrayRef<InteractionsOfType> bt,
864 PreprocessingBondAtomType *bondAtomType, char *line,
865 warninp *wi)
867 const char *formal[MAXATOMLIST+1] = {
868 "%s",
869 "%s%s",
870 "%s%s%s",
871 "%s%s%s%s",
872 "%s%s%s%s%s",
873 "%s%s%s%s%s%s",
874 "%s%s%s%s%s%s%s"
876 const char *formnl[MAXATOMLIST+1] = {
877 "%*s",
878 "%*s%*s",
879 "%*s%*s%*s",
880 "%*s%*s%*s%*s",
881 "%*s%*s%*s%*s%*s",
882 "%*s%*s%*s%*s%*s%*s",
883 "%*s%*s%*s%*s%*s%*s%*s"
885 const char *formlf[MAXFORCEPARAM] = {
886 "%lf",
887 "%lf%lf",
888 "%lf%lf%lf",
889 "%lf%lf%lf%lf",
890 "%lf%lf%lf%lf%lf",
891 "%lf%lf%lf%lf%lf%lf",
892 "%lf%lf%lf%lf%lf%lf%lf",
893 "%lf%lf%lf%lf%lf%lf%lf%lf",
894 "%lf%lf%lf%lf%lf%lf%lf%lf%lf",
895 "%lf%lf%lf%lf%lf%lf%lf%lf%lf%lf",
896 "%lf%lf%lf%lf%lf%lf%lf%lf%lf%lf%lf",
897 "%lf%lf%lf%lf%lf%lf%lf%lf%lf%lf%lf%lf",
899 int i, ft, ftype, nn, nrfp, nrfpA, nral;
900 char f1[STRLEN];
901 char alc[MAXATOMLIST+1][20];
902 double c[MAXFORCEPARAM];
903 bool bAllowRepeat;
905 /* This routine accepts dihedraltypes defined from either 2 or 4 atoms.
907 * We first check for 2 atoms with the 3th column being an integer
908 * defining the type. If this isn't the case, we try it with 4 atoms
909 * and the 5th column defining the dihedral type.
911 nn = sscanf(line, formal[4], alc[0], alc[1], alc[2], alc[3], alc[4]);
912 if (nn >= 3 && strlen(alc[2]) == 1 && isdigit(alc[2][0]))
914 nral = 2;
915 ft = strtol(alc[nral], nullptr, 10);
916 /* Move atom types around a bit and use 'X' for wildcard atoms
917 * to create a 4-atom dihedral definition with arbitrary atoms in
918 * position 1 and 4.
920 if (alc[2][0] == '2')
922 /* improper - the two atomtypes are 1,4. Use wildcards for 2,3 */
923 strcpy(alc[3], alc[1]);
924 sprintf(alc[2], "X");
925 sprintf(alc[1], "X");
926 /* alc[0] stays put */
928 else
930 /* proper - the two atomtypes are 2,3. Use wildcards for 1,4 */
931 sprintf(alc[3], "X");
932 strcpy(alc[2], alc[1]);
933 strcpy(alc[1], alc[0]);
934 sprintf(alc[0], "X");
937 else if (nn == 5 && strlen(alc[4]) == 1 && isdigit(alc[4][0]))
939 nral = 4;
940 ft = strtol(alc[nral], nullptr, 10);
942 else
944 auto message = gmx::formatString("Incorrect number of atomtypes for dihedral (%d instead of 2 or 4)", nn-1);
945 warning_error(wi, message);
946 return;
949 if (ft == 9)
951 /* Previously, we have always overwritten parameters if e.g. a torsion
952 with the same atomtypes occurs on multiple lines. However, CHARMM and
953 some other force fields specify multiple dihedrals over some bonds,
954 including cosines with multiplicity 6 and somethimes even higher.
955 Thus, they cannot be represented with Ryckaert-Bellemans terms.
956 To add support for these force fields, Dihedral type 9 is identical to
957 normal proper dihedrals, but repeated entries are allowed.
959 bAllowRepeat = TRUE;
960 ft = 1;
962 else
964 bAllowRepeat = FALSE;
968 ftype = ifunc_index(d, ft);
969 nrfp = NRFP(ftype);
970 nrfpA = interaction_function[ftype].nrfpA;
972 strcpy(f1, formnl[nral]);
973 strcat(f1, formlf[nrfp-1]);
975 /* Check number of parameters given */
976 if ((nn = sscanf(line, f1, &c[0], &c[1], &c[2], &c[3], &c[4], &c[5], &c[6], &c[7], &c[8], &c[9], &c[10], &c[11]))
977 != nrfp)
979 if (nn == nrfpA)
981 /* Copy the B-state from the A-state */
982 copy_B_from_A(ftype, c);
984 else
986 if (nn < nrfpA)
988 warning_error(wi, "Not enough parameters");
990 else if (nn > nrfpA && nn < nrfp)
992 warning_error(wi, "Too many parameters or not enough parameters for topology B");
994 else if (nn > nrfp)
996 warning_error(wi, "Too many parameters");
998 for (i = nn; (i < nrfp); i++)
1000 c[i] = 0.0;
1005 std::vector<int> atoms;
1006 std::array<real, MAXFORCEPARAM> forceParam;
1007 for (int i = 0; (i < 4); i++)
1009 if (!strcmp(alc[i], "X"))
1011 atoms.emplace_back(-1);
1013 else
1015 int atomNumber;
1016 if ((atomNumber = bondAtomType->bondAtomTypeFromName(alc[i])) == NOTSET)
1018 auto message = gmx::formatString("Unknown bond_atomtype %s", alc[i]);
1019 warning_error_and_exit(wi, message, FARGS);
1021 atoms.emplace_back(atomNumber);
1024 for (int i = 0; (i < nrfp); i++)
1026 forceParam[i] = c[i];
1028 /* Always use 4 atoms here, since we created two wildcard atoms
1029 * if there wasn't of them 4 already.
1031 push_bondtype (&(bt[ftype]), InteractionOfType(atoms, forceParam), 4, ftype, bAllowRepeat, line, wi);
1035 void push_nbt(Directive d, t_nbparam **nbt, PreprocessingAtomTypes *atypes,
1036 char *pline, int nb_funct,
1037 warninp *wi)
1039 /* swap the atoms */
1040 const char *form3 = "%*s%*s%*s%lf%lf%lf";
1041 const char *form4 = "%*s%*s%*s%lf%lf%lf%lf";
1042 const char *form5 = "%*s%*s%*s%lf%lf%lf%lf%lf";
1043 char a0[80], a1[80];
1044 int i, f, n, ftype, nrfp;
1045 double c[4], dum;
1046 real cr[4];
1047 int ai, aj;
1048 t_nbparam *nbp;
1049 bool bId;
1051 if (sscanf (pline, "%s%s%d", a0, a1, &f) != 3)
1053 too_few(wi);
1054 return;
1057 ftype = ifunc_index(d, f);
1059 if (ftype != nb_funct)
1061 auto message = gmx::formatString("Trying to add %s while the default nonbond type is %s",
1062 interaction_function[ftype].longname,
1063 interaction_function[nb_funct].longname);
1064 warning_error(wi, message);
1065 return;
1068 /* Get the force parameters */
1069 nrfp = NRFP(ftype);
1070 if (ftype == F_LJ14)
1072 n = sscanf(pline, form4, &c[0], &c[1], &c[2], &c[3]);
1073 if (n < 2)
1075 too_few(wi);
1076 return;
1078 /* When the B topology parameters are not set,
1079 * copy them from topology A
1081 GMX_ASSERT(nrfp <= 4, "LJ-14 cannot have more than 4 parameters");
1082 for (i = n; i < nrfp; i++)
1084 c[i] = c[i-2];
1087 else if (ftype == F_LJC14_Q)
1089 n = sscanf(pline, form5, &c[0], &c[1], &c[2], &c[3], &dum);
1090 if (n != 4)
1092 incorrect_n_param(wi);
1093 return;
1096 else if (nrfp == 2)
1098 if (sscanf(pline, form3, &c[0], &c[1], &dum) != 2)
1100 incorrect_n_param(wi);
1101 return;
1104 else if (nrfp == 3)
1106 if (sscanf(pline, form4, &c[0], &c[1], &c[2], &dum) != 3)
1108 incorrect_n_param(wi);
1109 return;
1112 else
1114 auto message = gmx::formatString("Number of force parameters for nonbonded interactions is %d", nrfp);
1115 warning_error_and_exit(wi, message, FARGS);
1117 for (i = 0; (i < nrfp); i++)
1119 cr[i] = c[i];
1122 /* Put the parameters in the matrix */
1123 if ((ai = atypes->atomTypeFromName(a0)) == NOTSET)
1125 auto message = gmx::formatString("Atomtype %s not found", a0);
1126 warning_error_and_exit(wi, message, FARGS);
1128 if ((aj = atypes->atomTypeFromName(a1)) == NOTSET)
1130 auto message = gmx::formatString("Atomtype %s not found", a1);
1131 warning_error_and_exit(wi, message, FARGS);
1133 nbp = &(nbt[std::max(ai, aj)][std::min(ai, aj)]);
1135 if (nbp->bSet)
1137 bId = TRUE;
1138 for (i = 0; i < nrfp; i++)
1140 bId = bId && (nbp->c[i] == cr[i]);
1142 if (!bId)
1144 auto message = gmx::formatString
1145 ("Non-bonded parameters were defined previously (e.g. in the forcefield files), "
1146 "and have now been defined again. This could happen e.g. if you would "
1147 "use a self-contained molecule .itp file that duplicates or replaces "
1148 "the contents of the standard force-field files. You should check "
1149 "the contents of your files and remove such repetition. If you know "
1150 "you should override the previous definitions, then you could choose "
1151 "to suppress this warning with -maxwarn.");
1152 warning(wi, message);
1153 fprintf(stderr, " old:");
1154 for (i = 0; i < nrfp; i++)
1156 fprintf(stderr, " %g", nbp->c[i]);
1158 fprintf(stderr, " new\n%s\n", pline);
1161 nbp->bSet = TRUE;
1162 for (i = 0; i < nrfp; i++)
1164 nbp->c[i] = cr[i];
1168 void
1169 push_cmaptype(Directive d,
1170 gmx::ArrayRef<InteractionsOfType> bt,
1171 int nral,
1172 PreprocessingAtomTypes *atomtypes,
1173 PreprocessingBondAtomType *bondAtomType,
1174 char *line,
1175 warninp *wi)
1177 const char *formal = "%s%s%s%s%s%s%s%s%n";
1179 int ft, ftype, nn, nrfp, nrfpA, nrfpB;
1180 int start, nchar_consumed;
1181 int nxcmap, nycmap, ncmap, read_cmap, sl, nct;
1182 char s[20], alc[MAXATOMLIST+2][20];
1184 /* Keep the compiler happy */
1185 read_cmap = 0;
1186 start = 0;
1188 GMX_ASSERT(nral == 5, "CMAP requires 5 atoms per interaction");
1190 /* Here we can only check for < 8 */
1191 if ((nn = sscanf(line, formal, alc[0], alc[1], alc[2], alc[3], alc[4], alc[5], alc[6], alc[7], &nchar_consumed)) < nral+3)
1193 auto message = gmx::formatString("Incorrect number of atomtypes for cmap (%d instead of 5)", nn-1);
1194 warning_error(wi, message);
1195 return;
1197 start += nchar_consumed;
1199 ft = strtol(alc[nral], nullptr, 10);
1200 nxcmap = strtol(alc[nral+1], nullptr, 10);
1201 nycmap = strtol(alc[nral+2], nullptr, 10);
1203 /* Check for equal grid spacing in x and y dims */
1204 if (nxcmap != nycmap)
1206 auto message = gmx::formatString("Not the same grid spacing in x and y for cmap grid: x=%d, y=%d", nxcmap, nycmap);
1207 warning_error(wi, message);
1210 ncmap = nxcmap*nycmap;
1211 ftype = ifunc_index(d, ft);
1212 nrfpA = strtol(alc[6], nullptr, 10)*strtol(alc[6], nullptr, 10);
1213 nrfpB = strtol(alc[7], nullptr, 10)*strtol(alc[7], nullptr, 10);
1214 nrfp = nrfpA+nrfpB;
1216 /* Read in CMAP parameters */
1217 sl = 0;
1218 for (int i = 0; i < ncmap; i++)
1220 while (isspace(*(line+start+sl)))
1222 sl++;
1224 nn = sscanf(line+start+sl, " %s ", s);
1225 sl += strlen(s);
1226 bt[F_CMAP].cmap.emplace_back(strtod(s, nullptr));
1228 if (nn == 1)
1230 read_cmap++;
1232 else
1234 auto message = gmx::formatString("Error in reading cmap parameter for angle %s %s %s %s %s", alc[0], alc[1], alc[2], alc[3], alc[4]);
1235 warning_error(wi, message);
1240 /* Check do that we got the number of parameters we expected */
1241 if (read_cmap == nrfpA)
1243 for (int i = 0; i < ncmap; i++)
1245 bt[F_CMAP].cmap.emplace_back(bt[F_CMAP].cmap[i]);
1248 else
1250 if (read_cmap < nrfpA)
1252 warning_error(wi, "Not enough cmap parameters");
1254 else if (read_cmap > nrfpA && read_cmap < nrfp)
1256 warning_error(wi, "Too many cmap parameters or not enough parameters for topology B");
1258 else if (read_cmap > nrfp)
1260 warning_error(wi, "Too many cmap parameters");
1265 /* Set grid spacing and the number of grids (we assume these numbers to be the same for all grids
1266 * so we can safely assign them each time
1268 bt[F_CMAP].cmakeGridSpacing = nxcmap; /* Or nycmap, they need to be equal */
1269 bt[F_CMAP].cmapAngles++; /* Since we are incrementing here, we need to subtract later, see (*****) */
1270 nct = (nral+1) * bt[F_CMAP].cmapAngles;
1272 for (int i = 0; (i < nral); i++)
1274 /* Assign a grid number to each cmap_type */
1275 GMX_RELEASE_ASSERT(bondAtomType != nullptr, "Need valid PreprocessingBondAtomType object");
1276 bt[F_CMAP].cmapAtomTypes.emplace_back(bondAtomType->bondAtomTypeFromName(alc[i]));
1279 /* Assign a type number to this cmap */
1280 bt[F_CMAP].cmapAtomTypes.emplace_back(bt[F_CMAP].cmapAngles-1); /* Since we inremented earlier, we need to subtrac here, to get the types right (****) */
1282 /* Check for the correct number of atoms (again) */
1283 if (bt[F_CMAP].nct() != nct)
1285 auto message = gmx::formatString("Incorrect number of atom types (%d) in cmap type %d\n", nct, bt[F_CMAP].cmapAngles);
1286 warning_error(wi, message);
1288 std::vector<int> atomTypes = atomTypesFromAtomNames(atomtypes,
1289 bondAtomType,
1290 gmx::constArrayRefFromArray(alc, nral),
1291 wi);
1292 std::array<real, MAXFORCEPARAM> forceParam = {NOTSET};
1294 /* Push the bond to the bondlist */
1295 push_bondtype (&(bt[ftype]), InteractionOfType(atomTypes, forceParam), nral, ftype, FALSE, line, wi);
1299 static void push_atom_now(t_symtab *symtab, t_atoms *at, int atomnr,
1300 int atomicnumber,
1301 int type, char *ctype, int ptype,
1302 char *resnumberic,
1303 char *resname, char *name, real m0, real q0,
1304 int typeB, char *ctypeB, real mB, real qB,
1305 warninp *wi)
1307 int j, resind = 0, resnr;
1308 unsigned char ric;
1309 int nr = at->nr;
1311 if (((nr == 0) && (atomnr != 1)) || (nr && (atomnr != at->nr+1)))
1313 auto message = gmx::formatString
1314 ("Atoms in the .top are not numbered consecutively from 1 (rather, "
1315 "atomnr = %d, while at->nr = %d)", atomnr, at->nr);
1316 warning_error_and_exit(wi, message, FARGS);
1319 j = strlen(resnumberic) - 1;
1320 if (isdigit(resnumberic[j]))
1322 ric = ' ';
1324 else
1326 ric = resnumberic[j];
1327 if (j == 0 || !isdigit(resnumberic[j-1]))
1329 auto message = gmx::formatString("Invalid residue number '%s' for atom %d",
1330 resnumberic, atomnr);
1331 warning_error_and_exit(wi, message, FARGS);
1334 resnr = strtol(resnumberic, nullptr, 10);
1336 if (nr > 0)
1338 resind = at->atom[nr-1].resind;
1340 if (nr == 0 || strcmp(resname, *at->resinfo[resind].name) != 0 ||
1341 resnr != at->resinfo[resind].nr ||
1342 ric != at->resinfo[resind].ic)
1344 if (nr == 0)
1346 resind = 0;
1348 else
1350 resind++;
1352 at->nres = resind + 1;
1353 srenew(at->resinfo, at->nres);
1354 at->resinfo[resind].name = put_symtab(symtab, resname);
1355 at->resinfo[resind].nr = resnr;
1356 at->resinfo[resind].ic = ric;
1358 else
1360 resind = at->atom[at->nr-1].resind;
1363 /* New atom instance
1364 * get new space for arrays
1366 srenew(at->atom, nr+1);
1367 srenew(at->atomname, nr+1);
1368 srenew(at->atomtype, nr+1);
1369 srenew(at->atomtypeB, nr+1);
1371 /* fill the list */
1372 at->atom[nr].type = type;
1373 at->atom[nr].ptype = ptype;
1374 at->atom[nr].q = q0;
1375 at->atom[nr].m = m0;
1376 at->atom[nr].typeB = typeB;
1377 at->atom[nr].qB = qB;
1378 at->atom[nr].mB = mB;
1380 at->atom[nr].resind = resind;
1381 at->atom[nr].atomnumber = atomicnumber;
1382 at->atomname[nr] = put_symtab(symtab, name);
1383 at->atomtype[nr] = put_symtab(symtab, ctype);
1384 at->atomtypeB[nr] = put_symtab(symtab, ctypeB);
1385 at->nr++;
1388 static void push_cg(t_block *block, int *lastindex, int index, int a)
1390 if (((block->nr) && (*lastindex != index)) || (!block->nr))
1392 /* add a new block */
1393 block->nr++;
1394 srenew(block->index, block->nr+1);
1396 block->index[block->nr] = a + 1;
1397 *lastindex = index;
1400 void push_atom(t_symtab *symtab, t_block *cgs,
1401 t_atoms *at, PreprocessingAtomTypes *atypes, char *line, int *lastcg,
1402 warninp *wi)
1404 int nr, ptype;
1405 int cgnumber, atomnr, type, typeB, nscan;
1406 char id[STRLEN], ctype[STRLEN], ctypeB[STRLEN],
1407 resnumberic[STRLEN], resname[STRLEN], name[STRLEN], check[STRLEN];
1408 double m, q, mb, qb;
1409 real m0, q0, mB, qB;
1411 /* Make a shortcut for writing in this molecule */
1412 nr = at->nr;
1414 /* Fixed parameters */
1415 if (sscanf(line, "%s%s%s%s%s%d",
1416 id, ctype, resnumberic, resname, name, &cgnumber) != 6)
1418 too_few(wi);
1419 return;
1421 sscanf(id, "%d", &atomnr);
1422 if ((type = atypes->atomTypeFromName(ctype)) == NOTSET)
1424 auto message = gmx::formatString("Atomtype %s not found", ctype);
1425 warning_error_and_exit(wi, message, FARGS);
1427 ptype = atypes->atomParticleTypeFromAtomType(type);
1429 /* Set default from type */
1430 q0 = atypes->atomChargeFromAtomType(type);
1431 m0 = atypes->atomMassFromAtomType(type);
1432 typeB = type;
1433 qB = q0;
1434 mB = m0;
1436 /* Optional parameters */
1437 nscan = sscanf(line, "%*s%*s%*s%*s%*s%*s%lf%lf%s%lf%lf%s",
1438 &q, &m, ctypeB, &qb, &mb, check);
1440 /* Nasty switch that falls thru all the way down! */
1441 if (nscan > 0)
1443 q0 = qB = q;
1444 if (nscan > 1)
1446 m0 = mB = m;
1447 if (nscan > 2)
1449 if ((typeB = atypes->atomTypeFromName(ctypeB)) == NOTSET)
1451 auto message = gmx::formatString("Atomtype %s not found", ctypeB);
1452 warning_error_and_exit(wi, message, FARGS);
1454 qB = atypes->atomChargeFromAtomType(typeB);
1455 mB = atypes->atomMassFromAtomType(typeB);
1456 if (nscan > 3)
1458 qB = qb;
1459 if (nscan > 4)
1461 mB = mb;
1462 if (nscan > 5)
1464 warning_error(wi, "Too many parameters");
1472 push_cg(cgs, lastcg, cgnumber, nr);
1474 push_atom_now(symtab, at, atomnr, atypes->atomNumberFromAtomType(type),
1475 type, ctype, ptype, resnumberic,
1476 resname, name, m0, q0, typeB,
1477 typeB == type ? ctype : ctypeB, mB, qB, wi);
1480 void push_molt(t_symtab *symtab,
1481 std::vector<MoleculeInformation> *mol,
1482 char *line,
1483 warninp *wi)
1485 char type[STRLEN];
1486 int nrexcl;
1488 if ((sscanf(line, "%s%d", type, &nrexcl)) != 2)
1490 warning_error(wi, "Expected a molecule type name and nrexcl");
1493 /* Test if this moleculetype overwrites another */
1494 const auto found = std::find_if(mol->begin(), mol->end(),
1495 [&type](const auto &m)
1496 { return strcmp(*(m.name), type) == 0; });
1497 if (found != mol->end())
1499 auto message = gmx::formatString("moleculetype %s is redefined", type);
1500 warning_error_and_exit(wi, message, FARGS);
1503 mol->emplace_back();
1504 mol->back().initMolInfo();
1506 /* Fill in the values */
1507 mol->back().name = put_symtab(symtab, type);
1508 mol->back().nrexcl = nrexcl;
1509 mol->back().excl_set = false;
1512 static bool findIfAllNBAtomsMatch(gmx::ArrayRef<const int> atomsFromParameterArray,
1513 gmx::ArrayRef<const int> atomsFromCurrentParameter,
1514 const t_atoms *at,
1515 bool bB)
1517 if (atomsFromParameterArray.size() != atomsFromCurrentParameter.size())
1519 return false;
1521 else if (bB)
1523 for (gmx::index i = 0; i < atomsFromCurrentParameter.ssize(); i++)
1525 if (at->atom[atomsFromCurrentParameter[i]].typeB != atomsFromParameterArray[i])
1527 return false;
1530 return true;
1532 else
1534 for (gmx::index i = 0; i < atomsFromCurrentParameter.ssize(); i++)
1536 if (at->atom[atomsFromCurrentParameter[i]].type != atomsFromParameterArray[i])
1538 return false;
1541 return true;
1545 static bool default_nb_params(int ftype, gmx::ArrayRef<InteractionsOfType> bt, t_atoms *at,
1546 InteractionOfType *p, int c_start, bool bB, bool bGenPairs)
1548 int ti, tj, ntype;
1549 bool bFound;
1550 InteractionOfType *pi = nullptr;
1551 int nr = bt[ftype].size();
1552 int nral = NRAL(ftype);
1553 int nrfp = interaction_function[ftype].nrfpA;
1554 int nrfpB = interaction_function[ftype].nrfpB;
1556 if ((!bB && nrfp == 0) || (bB && nrfpB == 0))
1558 return TRUE;
1561 bFound = FALSE;
1562 if (bGenPairs)
1564 /* First test the generated-pair position to save
1565 * time when we have 1000*1000 entries for e.g. OPLS...
1567 ntype = static_cast<int>(std::sqrt(static_cast<double>(nr)));
1568 GMX_ASSERT(ntype * ntype == nr, "Number of pairs of generated non-bonded parameters should be a perfect square");
1569 if (bB)
1571 ti = at->atom[p->ai()].typeB;
1572 tj = at->atom[p->aj()].typeB;
1574 else
1576 ti = at->atom[p->ai()].type;
1577 tj = at->atom[p->aj()].type;
1579 pi = &(bt[ftype].interactionTypes[ntype*ti+tj]);
1580 if (pi->atoms().ssize() < nral)
1582 /* not initialized yet with atom names */
1583 bFound = false;
1585 else
1587 bFound = ((ti == pi->ai()) && (tj == pi->aj()));
1591 gmx::ArrayRef<const int> paramAtoms = p->atoms();
1592 /* Search explicitly if we didnt find it */
1593 if (!bFound)
1595 auto foundParameter = std::find_if(bt[ftype].interactionTypes.begin(),
1596 bt[ftype].interactionTypes.end(),
1597 [&paramAtoms, &at, &bB](const auto &param)
1598 { return findIfAllNBAtomsMatch(param.atoms(), paramAtoms, at, bB); });
1599 if (foundParameter != bt[ftype].interactionTypes.end())
1601 bFound = true;
1602 pi = &(*foundParameter);
1606 if (bFound)
1608 gmx::ArrayRef<const real> forceParam = pi->forceParam();
1609 if (bB)
1611 if (nrfp+nrfpB > MAXFORCEPARAM)
1613 gmx_incons("Too many force parameters");
1615 for (int j = c_start; j < nrfpB; j++)
1617 p->setForceParameter(nrfp+j, forceParam[j]);
1620 else
1622 for (int j = c_start; j < nrfp; j++)
1624 p->setForceParameter(j, forceParam[j]);
1628 else
1630 for (int j = c_start; j < nrfp; j++)
1632 p->setForceParameter(j, 0.0);
1635 return bFound;
1638 static bool default_cmap_params(gmx::ArrayRef<InteractionsOfType> bondtype,
1639 t_atoms *at, PreprocessingAtomTypes *atypes,
1640 InteractionOfType *p, bool bB,
1641 int *cmap_type, int *nparam_def,
1642 warninp *wi)
1644 int nparam_found;
1645 int ct;
1646 bool bFound = false;
1648 nparam_found = 0;
1649 ct = 0;
1651 /* Match the current cmap angle against the list of cmap_types */
1652 for (int i = 0; i < bondtype[F_CMAP].nct() && !bFound; i += 6)
1654 if (bB)
1658 else
1660 if (
1661 (atypes->bondAtomTypeFromAtomType(at->atom[p->ai()].type) == bondtype[F_CMAP].cmapAtomTypes[i]) &&
1662 (atypes->bondAtomTypeFromAtomType(at->atom[p->aj()].type) == bondtype[F_CMAP].cmapAtomTypes[i+1]) &&
1663 (atypes->bondAtomTypeFromAtomType(at->atom[p->ak()].type) == bondtype[F_CMAP].cmapAtomTypes[i+2]) &&
1664 (atypes->bondAtomTypeFromAtomType(at->atom[p->al()].type) == bondtype[F_CMAP].cmapAtomTypes[i+3]) &&
1665 (atypes->bondAtomTypeFromAtomType(at->atom[p->am()].type) == bondtype[F_CMAP].cmapAtomTypes[i+4]))
1667 /* Found cmap torsion */
1668 bFound = true;
1669 ct = bondtype[F_CMAP].cmapAtomTypes[i+5];
1670 nparam_found = 1;
1675 /* If we did not find a matching type for this cmap torsion */
1676 if (!bFound)
1678 auto message = gmx::formatString("Unknown cmap torsion between atoms %d %d %d %d %d",
1679 p->ai()+1, p->aj()+1, p->ak()+1, p->al()+1, p->am()+1);
1680 warning_error_and_exit(wi, message, FARGS);
1683 *nparam_def = nparam_found;
1684 *cmap_type = ct;
1686 return bFound;
1689 /* Returns the number of exact atom type matches, i.e. non wild-card matches,
1690 * returns -1 when there are no matches at all.
1692 static int natom_match(const InteractionOfType &pi,
1693 int type_i, int type_j, int type_k, int type_l,
1694 const PreprocessingAtomTypes* atypes)
1696 if ((pi.ai() == -1 || atypes->bondAtomTypeFromAtomType(type_i) == pi.ai()) &&
1697 (pi.aj() == -1 || atypes->bondAtomTypeFromAtomType(type_j) == pi.aj()) &&
1698 (pi.ak() == -1 || atypes->bondAtomTypeFromAtomType(type_k) == pi.ak()) &&
1699 (pi.al() == -1 || atypes->bondAtomTypeFromAtomType(type_l) == pi.al()))
1701 return
1702 (pi.ai() == -1 ? 0 : 1) +
1703 (pi.aj() == -1 ? 0 : 1) +
1704 (pi.ak() == -1 ? 0 : 1) +
1705 (pi.al() == -1 ? 0 : 1);
1707 else
1709 return -1;
1713 static int findNumberOfDihedralAtomMatches(const InteractionOfType &currentParamFromParameterArray,
1714 const InteractionOfType &parameterToAdd,
1715 const t_atoms *at,
1716 const PreprocessingAtomTypes *atypes,
1717 bool bB)
1719 if (bB)
1721 return natom_match(currentParamFromParameterArray,
1722 at->atom[parameterToAdd.ai()].typeB,
1723 at->atom[parameterToAdd.aj()].typeB,
1724 at->atom[parameterToAdd.ak()].typeB,
1725 at->atom[parameterToAdd.al()].typeB, atypes);
1727 else
1729 return natom_match(currentParamFromParameterArray,
1730 at->atom[parameterToAdd.ai()].type,
1731 at->atom[parameterToAdd.aj()].type,
1732 at->atom[parameterToAdd.ak()].type,
1733 at->atom[parameterToAdd.al()].type, atypes);
1737 static bool findIfAllParameterAtomsMatch(gmx::ArrayRef<const int> atomsFromParameterArray,
1738 gmx::ArrayRef<const int> atomsFromCurrentParameter,
1739 const t_atoms *at,
1740 const PreprocessingAtomTypes *atypes,
1741 bool bB)
1743 if (atomsFromParameterArray.size() != atomsFromCurrentParameter.size())
1745 return false;
1747 else if (bB)
1749 for (gmx::index i = 0; i < atomsFromCurrentParameter.ssize(); i++)
1751 if (atypes->bondAtomTypeFromAtomType(
1752 at->atom[atomsFromCurrentParameter[i]].typeB) != atomsFromParameterArray[i])
1754 return false;
1757 return true;
1759 else
1761 for (gmx::index i = 0; i < atomsFromCurrentParameter.ssize(); i++)
1763 if (atypes->bondAtomTypeFromAtomType(
1764 at->atom[atomsFromCurrentParameter[i]].type) != atomsFromParameterArray[i])
1766 return false;
1769 return true;
1773 static std::vector<InteractionOfType>::iterator
1774 defaultInteractionsOfType(int ftype, gmx::ArrayRef<InteractionsOfType> bt,
1775 t_atoms *at, PreprocessingAtomTypes *atypes,
1776 const InteractionOfType &p, bool bB,
1777 int *nparam_def)
1779 int nparam_found;
1780 int nrfpA = interaction_function[ftype].nrfpA;
1781 int nrfpB = interaction_function[ftype].nrfpB;
1783 if ((!bB && nrfpA == 0) || (bB && nrfpB == 0))
1785 return bt[ftype].interactionTypes.end();
1789 nparam_found = 0;
1790 if (ftype == F_PDIHS || ftype == F_RBDIHS || ftype == F_IDIHS || ftype == F_PIDIHS)
1792 int nmatch_max = -1;
1794 /* For dihedrals we allow wildcards. We choose the first type
1795 * that has the most real matches, i.e. non-wildcard matches.
1797 auto prevPos = bt[ftype].interactionTypes.end();
1798 auto pos = bt[ftype].interactionTypes.begin();
1799 while (pos != bt[ftype].interactionTypes.end() && nmatch_max < 4)
1801 pos = std::find_if(bt[ftype].interactionTypes.begin(), bt[ftype].interactionTypes.end(),
1802 [&p, &at, &atypes, &bB, &nmatch_max](const auto &param)
1803 { return (findNumberOfDihedralAtomMatches(param, p, at, atypes, bB) > nmatch_max); });
1804 if (pos != bt[ftype].interactionTypes.end())
1806 prevPos = pos;
1807 nmatch_max = findNumberOfDihedralAtomMatches(*pos, p, at, atypes, bB);
1811 if (prevPos != bt[ftype].interactionTypes.end())
1813 nparam_found++;
1815 /* Find additional matches for this dihedral - necessary
1816 * for ftype==9.
1817 * The rule in that case is that additional matches
1818 * HAVE to be on adjacent lines!
1820 bool bSame = true;
1821 //Advance iterator (like std::advance) without incrementing past end (UB)
1822 const auto safeAdvance = [](auto &it, auto n, auto end) {
1823 it = end-it > n ? it+n : end;
1825 /* Continue from current iterator position */
1826 auto nextPos = prevPos;
1827 const auto endIter = bt[ftype].interactionTypes.end();
1828 safeAdvance(nextPos, 2, endIter);
1829 for (; nextPos < endIter && bSame; safeAdvance(nextPos, 2, endIter))
1831 bSame = (prevPos->ai() == nextPos->ai() && prevPos->aj() == nextPos->aj() && prevPos->ak() == nextPos->ak() && prevPos->al() == nextPos->al());
1832 if (bSame)
1834 nparam_found++;
1836 /* nparam_found will be increased as long as the numbers match */
1839 *nparam_def = nparam_found;
1840 return prevPos;
1842 else /* Not a dihedral */
1844 gmx::ArrayRef<const int> atomParam = p.atoms();
1845 auto found = std::find_if(bt[ftype].interactionTypes.begin(),
1846 bt[ftype].interactionTypes.end(),
1847 [&atomParam, &at, &atypes, &bB](const auto &param)
1848 { return findIfAllParameterAtomsMatch(param.atoms(), atomParam, at, atypes, bB); });
1849 if (found != bt[ftype].interactionTypes.end())
1851 nparam_found = 1;
1853 *nparam_def = nparam_found;
1854 return found;
1860 void push_bond(Directive d, gmx::ArrayRef<InteractionsOfType> bondtype,
1861 gmx::ArrayRef<InteractionsOfType> bond,
1862 t_atoms *at, PreprocessingAtomTypes *atypes, char *line,
1863 bool bBonded, bool bGenPairs, real fudgeQQ,
1864 bool bZero, bool *bWarn_copy_A_B,
1865 warninp *wi)
1867 const char *aaformat[MAXATOMLIST] = {
1868 "%d%d",
1869 "%d%d%d",
1870 "%d%d%d%d",
1871 "%d%d%d%d%d",
1872 "%d%d%d%d%d%d",
1873 "%d%d%d%d%d%d%d"
1875 const char *asformat[MAXATOMLIST] = {
1876 "%*s%*s",
1877 "%*s%*s%*s",
1878 "%*s%*s%*s%*s",
1879 "%*s%*s%*s%*s%*s",
1880 "%*s%*s%*s%*s%*s%*s",
1881 "%*s%*s%*s%*s%*s%*s%*s"
1883 const char *ccformat = "%lf%lf%lf%lf%lf%lf%lf%lf%lf%lf%lf%lf%lf";
1884 int nral, nral_fmt, nread, ftype;
1885 char format[STRLEN];
1886 /* One force parameter more, so we can check if we read too many */
1887 double cc[MAXFORCEPARAM+1];
1888 int aa[MAXATOMLIST+1];
1889 bool bFoundA = FALSE, bFoundB = FALSE, bDef, bSwapParity = FALSE;
1890 int nparam_defA, nparam_defB;
1892 nparam_defA = nparam_defB = 0;
1894 ftype = ifunc_index(d, 1);
1895 nral = NRAL(ftype);
1896 for (int j = 0; j < nral; j++)
1898 aa[j] = NOTSET;
1900 bDef = (NRFP(ftype) > 0);
1902 if (ftype == F_SETTLE)
1904 /* SETTLE acts on 3 atoms, but the topology format only specifies
1905 * the first atom (for historical reasons).
1907 nral_fmt = 1;
1909 else
1911 nral_fmt = nral;
1914 nread = sscanf(line, aaformat[nral_fmt-1],
1915 &aa[0], &aa[1], &aa[2], &aa[3], &aa[4], &aa[5]);
1917 if (ftype == F_SETTLE)
1919 aa[3] = aa[1];
1920 aa[1] = aa[0] + 1;
1921 aa[2] = aa[0] + 2;
1924 if (nread < nral_fmt)
1926 too_few(wi);
1927 return;
1929 else if (nread > nral_fmt)
1931 /* this is a hack to allow for virtual sites with swapped parity */
1932 bSwapParity = (aa[nral] < 0);
1933 if (bSwapParity)
1935 aa[nral] = -aa[nral];
1937 ftype = ifunc_index(d, aa[nral]);
1938 if (bSwapParity)
1940 switch (ftype)
1942 case F_VSITE3FAD:
1943 case F_VSITE3OUT:
1944 break;
1945 default:
1946 auto message = gmx::formatString("Negative function types only allowed for %s and %s",
1947 interaction_function[F_VSITE3FAD].longname,
1948 interaction_function[F_VSITE3OUT].longname);
1949 warning_error_and_exit(wi, message, FARGS);
1955 /* Check for double atoms and atoms out of bounds */
1956 for (int i = 0; (i < nral); i++)
1958 if (aa[i] < 1 || aa[i] > at->nr)
1960 auto message = gmx::formatString
1961 ("Atom index (%d) in %s out of bounds (1-%d).\n"
1962 "This probably means that you have inserted topology section \"%s\"\n"
1963 "in a part belonging to a different molecule than you intended to.\n"
1964 "In that case move the \"%s\" section to the right molecule.",
1965 aa[i], dir2str(d), at->nr, dir2str(d), dir2str(d));
1966 warning_error_and_exit(wi, message, FARGS);
1968 for (int j = i+1; (j < nral); j++)
1970 GMX_ASSERT(j < MAXATOMLIST + 1, "Values from nral=NRAL() will satisfy this, we assert to keep gcc 4 happy");
1971 if (aa[i] == aa[j])
1973 auto message = gmx::formatString("Duplicate atom index (%d) in %s", aa[i], dir2str(d));
1974 if (ftype == F_ANGRES)
1976 /* Since the angle restraints uses 2 pairs of atoms to
1977 * defines an angle between vectors, it can be useful
1978 * to use one atom twice, so we only issue a note here.
1980 warning_note(wi, message);
1982 else
1984 warning_error(wi, message);
1990 /* default force parameters */
1991 std::vector<int> atoms;
1992 for (int j = 0; (j < nral); j++)
1994 atoms.emplace_back(aa[j]-1);
1996 /* need to have an empty but initialized param array for some reason */
1997 std::array<real, MAXFORCEPARAM> forceParam = {0.0};
1999 /* Get force params for normal and free energy perturbation
2000 * studies, as determined by types!
2002 InteractionOfType param(atoms, forceParam, "");
2004 std::vector<InteractionOfType>::iterator foundAParameter = bondtype[ftype].interactionTypes.end();
2005 std::vector<InteractionOfType>::iterator foundBParameter = bondtype[ftype].interactionTypes.end();
2006 if (bBonded)
2008 foundAParameter = defaultInteractionsOfType(ftype,
2009 bondtype,
2011 atypes,
2012 param,
2013 FALSE,
2014 &nparam_defA);
2015 if (foundAParameter != bondtype[ftype].interactionTypes.end())
2017 /* Copy the A-state and B-state default parameters. */
2018 GMX_ASSERT(NRFPA(ftype)+NRFPB(ftype) <= MAXFORCEPARAM, "Bonded interactions may have at most 12 parameters");
2019 gmx::ArrayRef<const real> defaultParam = foundAParameter->forceParam();
2020 for (int j = 0; (j < NRFPA(ftype)+NRFPB(ftype)); j++)
2022 param.setForceParameter(j, defaultParam[j]);
2024 bFoundA = true;
2026 else if (NRFPA(ftype) == 0)
2028 bFoundA = true;
2030 foundBParameter = defaultInteractionsOfType(ftype,
2031 bondtype,
2033 atypes,
2034 param,
2035 TRUE,
2036 &nparam_defB);
2037 if (foundBParameter != bondtype[ftype].interactionTypes.end())
2039 /* Copy only the B-state default parameters */
2040 gmx::ArrayRef<const real> defaultParam = foundBParameter->forceParam();
2041 for (int j = NRFPA(ftype); (j < NRFP(ftype)); j++)
2043 param.setForceParameter(j, defaultParam[j]);
2045 bFoundB = true;
2047 else if (NRFPB(ftype) == 0)
2049 bFoundB = true;
2052 else if (ftype == F_LJ14)
2054 bFoundA = default_nb_params(ftype, bondtype, at, &param, 0, FALSE, bGenPairs);
2055 bFoundB = default_nb_params(ftype, bondtype, at, &param, 0, TRUE, bGenPairs);
2057 else if (ftype == F_LJC14_Q)
2059 /* Fill in the A-state charges as default parameters */
2060 param.setForceParameter(0, fudgeQQ);
2061 param.setForceParameter(1, at->atom[param.ai()].q);
2062 param.setForceParameter(2, at->atom[param.aj()].q);
2063 /* The default LJ parameters are the standard 1-4 parameters */
2064 bFoundA = default_nb_params(F_LJ14, bondtype, at, &param, 3, FALSE, bGenPairs);
2065 bFoundB = TRUE;
2067 else if (ftype == F_LJC_PAIRS_NB)
2069 /* Defaults are not supported here */
2070 bFoundA = FALSE;
2071 bFoundB = TRUE;
2073 else
2075 gmx_incons("Unknown function type in push_bond");
2078 if (nread > nral_fmt)
2080 /* Manually specified parameters - in this case we discard multiple torsion info! */
2082 strcpy(format, asformat[nral_fmt-1]);
2083 strcat(format, ccformat);
2085 nread = sscanf(line, format, &cc[0], &cc[1], &cc[2], &cc[3], &cc[4], &cc[5],
2086 &cc[6], &cc[7], &cc[8], &cc[9], &cc[10], &cc[11], &cc[12]);
2088 if ((nread == NRFPA(ftype)) && (NRFPB(ftype) != 0))
2090 /* We only have to issue a warning if these atoms are perturbed! */
2091 bool bPert = false;
2092 gmx::ArrayRef<const int> paramAtoms = param.atoms();
2093 for (int j = 0; (j < nral); j++)
2095 bPert = bPert || PERTURBED(at->atom[paramAtoms[j]]);
2098 if (bPert && *bWarn_copy_A_B)
2100 auto message = gmx::formatString("Some parameters for bonded interaction involving "
2101 "perturbed atoms are specified explicitly in "
2102 "state A, but not B - copying A to B");
2103 warning(wi, message);
2104 *bWarn_copy_A_B = FALSE;
2107 /* If only the A parameters were specified, copy them to the B state */
2108 /* The B-state parameters correspond to the first nrfpB
2109 * A-state parameters.
2111 for (int j = 0; (j < NRFPB(ftype)); j++)
2113 cc[nread++] = cc[j];
2117 /* If nread was 0 or EOF, no parameters were read => use defaults.
2118 * If nread was nrfpA we copied above so nread=nrfp.
2119 * If nread was nrfp we are cool.
2120 * For F_LJC14_Q we allow supplying fudgeQQ only.
2121 * Anything else is an error!
2123 if ((nread != 0) && (nread != EOF) && (nread != NRFP(ftype)) &&
2124 !(ftype == F_LJC14_Q && nread == 1))
2126 auto message = gmx::formatString
2127 ("Incorrect number of parameters - found %d, expected %d "
2128 "or %d for %s (after the function type).",
2129 nread, NRFPA(ftype), NRFP(ftype), interaction_function[ftype].longname);
2130 warning_error_and_exit(wi, message, FARGS);
2133 for (int j = 0; (j < nread); j++)
2135 param.setForceParameter(j, cc[j]);
2137 /* Check whether we have to use the defaults */
2138 if (nread == NRFP(ftype))
2140 bDef = FALSE;
2143 else
2145 nread = 0;
2147 /* nread now holds the number of force parameters read! */
2149 if (bDef)
2151 /* Use defaults */
2152 /* When we have multiple terms it would be very dangerous to allow perturbations to a different atom type! */
2153 if (ftype == F_PDIHS)
2155 if ((nparam_defA != nparam_defB) || ((nparam_defA > 1 || nparam_defB > 1) && (foundAParameter != foundBParameter)))
2157 auto message =
2158 gmx::formatString("Cannot automatically perturb a torsion with multiple terms to different form.\n"
2159 "Please specify perturbed parameters manually for this torsion in your topology!");
2160 warning_error(wi, message);
2164 if (nread > 0 && nread < NRFPA(ftype))
2166 /* Issue an error, do not use defaults */
2167 auto message = gmx::formatString("Not enough parameters, there should be at least %d (or 0 for defaults)", NRFPA(ftype));
2168 warning_error(wi, message);
2171 if (nread == 0 || nread == EOF)
2173 if (!bFoundA)
2175 if (interaction_function[ftype].flags & IF_VSITE)
2177 for (int j = 0; j < MAXFORCEPARAM; j++)
2179 param.setForceParameter(j, NOTSET);
2181 if (bSwapParity)
2183 /* flag to swap parity of vsi te construction */
2184 param.setForceParameter(1, -1);
2187 else
2189 if (bZero)
2191 fprintf(stderr, "NOTE: No default %s types, using zeroes\n",
2192 interaction_function[ftype].longname);
2194 else
2196 auto message = gmx::formatString("No default %s types", interaction_function[ftype].longname);
2197 warning_error(wi, message);
2201 else
2203 if (bSwapParity)
2205 switch (ftype)
2207 case F_VSITE3FAD:
2208 param.setForceParameter(0, 360 - param.c0());
2209 break;
2210 case F_VSITE3OUT:
2211 param.setForceParameter(2, -param.c2());
2212 break;
2216 if (!bFoundB)
2218 /* We only have to issue a warning if these atoms are perturbed! */
2219 bool bPert = false;
2220 gmx::ArrayRef<const int> paramAtoms = param.atoms();
2221 for (int j = 0; (j < nral); j++)
2223 bPert = bPert || PERTURBED(at->atom[paramAtoms[j]]);
2226 if (bPert)
2228 auto message = gmx::formatString("No default %s types for perturbed atoms, "
2229 "using normal values", interaction_function[ftype].longname);
2230 warning(wi, message);
2236 gmx::ArrayRef<const real> paramValue = param.forceParam();
2237 if ((ftype == F_PDIHS || ftype == F_ANGRES || ftype == F_ANGRESZ)
2238 && paramValue[5] != paramValue[2])
2240 auto message = gmx::formatString("%s multiplicity can not be perturbed %f!=%f",
2241 interaction_function[ftype].longname,
2242 paramValue[2], paramValue[5]);
2243 warning_error_and_exit(wi, message, FARGS);
2246 if (IS_TABULATED(ftype) && param.c0() != param.c2())
2248 auto message = gmx::formatString("%s table number can not be perturbed %d!=%d",
2249 interaction_function[ftype].longname,
2250 gmx::roundToInt(param.c0()), gmx::roundToInt(param.c0()));
2251 warning_error_and_exit(wi, message, FARGS);
2254 /* Dont add R-B dihedrals where all parameters are zero (no interaction) */
2255 if (ftype == F_RBDIHS)
2258 int nr = 0;
2259 for (int i = 0; i < NRFP(ftype); i++)
2261 if (paramValue[i] != 0.0)
2263 nr++;
2266 if (nr == 0)
2268 return;
2272 /* Put the values in the appropriate arrays */
2273 add_param_to_list (&bond[ftype], param);
2275 /* Push additional torsions from FF for ftype==9 if we have them.
2276 * We have already checked that the A/B states do not differ in this case,
2277 * so we do not have to double-check that again, or the vsite stuff.
2278 * In addition, those torsions cannot be automatically perturbed.
2280 if (bDef && ftype == F_PDIHS)
2282 for (int i = 1; i < nparam_defA; i++)
2284 /* Advance pointer! */
2285 foundAParameter += 2;
2286 gmx::ArrayRef<const real> forceParam = foundAParameter->forceParam();
2287 for (int j = 0; j < (NRFPA(ftype)+NRFPB(ftype)); j++)
2289 param.setForceParameter(j, forceParam[j]);
2291 /* And push the next term for this torsion */
2292 add_param_to_list (&bond[ftype], param);
2297 void push_cmap(Directive d, gmx::ArrayRef<InteractionsOfType> bondtype,
2298 gmx::ArrayRef<InteractionsOfType> bond,
2299 t_atoms *at, PreprocessingAtomTypes *atypes, char *line,
2300 warninp *wi)
2302 const char *aaformat[MAXATOMLIST+1] =
2304 "%d",
2305 "%d%d",
2306 "%d%d%d",
2307 "%d%d%d%d",
2308 "%d%d%d%d%d",
2309 "%d%d%d%d%d%d",
2310 "%d%d%d%d%d%d%d"
2313 int ftype, nral, nread, ncmap_params;
2314 int cmap_type;
2315 int aa[MAXATOMLIST+1];
2316 bool bFound;
2318 ftype = ifunc_index(d, 1);
2319 nral = NRAL(ftype);
2320 ncmap_params = 0;
2322 nread = sscanf(line, aaformat[nral-1],
2323 &aa[0], &aa[1], &aa[2], &aa[3], &aa[4], &aa[5]);
2325 if (nread < nral)
2327 too_few(wi);
2328 return;
2330 else if (nread == nral)
2332 ftype = ifunc_index(d, 1);
2335 /* Check for double atoms and atoms out of bounds */
2336 for (int i = 0; i < nral; i++)
2338 if (aa[i] < 1 || aa[i] > at->nr)
2340 auto message = gmx::formatString
2341 ("Atom index (%d) in %s out of bounds (1-%d).\n"
2342 "This probably means that you have inserted topology section \"%s\"\n"
2343 "in a part belonging to a different molecule than you intended to.\n"
2344 "In that case move the \"%s\" section to the right molecule.",
2345 aa[i], dir2str(d), at->nr, dir2str(d), dir2str(d));
2346 warning_error_and_exit(wi, message, FARGS);
2349 for (int j = i+1; (j < nral); j++)
2351 if (aa[i] == aa[j])
2353 auto message = gmx::formatString("Duplicate atom index (%d) in %s", aa[i], dir2str(d));
2354 warning_error(wi, message);
2359 /* default force parameters */
2360 std::vector<int> atoms;
2361 for (int j = 0; (j < nral); j++)
2363 atoms.emplace_back(aa[j]-1);
2365 std::array<real, MAXFORCEPARAM> forceParam = {0.0};
2366 InteractionOfType param(atoms, forceParam, "");
2367 /* Get the cmap type for this cmap angle */
2368 bFound = default_cmap_params(bondtype, at, atypes, &param, FALSE, &cmap_type, &ncmap_params, wi);
2370 /* We want exactly one parameter (the cmap type in state A (currently no state B) back */
2371 if (bFound && ncmap_params == 1)
2373 /* Put the values in the appropriate arrays */
2374 param.setForceParameter(0, cmap_type);
2375 add_param_to_list(&bond[ftype], param);
2377 else
2379 /* This is essentially the same check as in default_cmap_params() done one more time */
2380 auto message = gmx::formatString("Unable to assign a cmap type to torsion %d %d %d %d and %d\n",
2381 param.ai()+1, param.aj()+1, param.ak()+1, param.al()+1, param.am()+1);
2382 warning_error_and_exit(wi, message, FARGS);
2388 void push_vsitesn(Directive d, gmx::ArrayRef<InteractionsOfType> bond,
2389 t_atoms *at, char *line,
2390 warninp *wi)
2392 char *ptr;
2393 int type, ftype, n, ret, nj, a;
2394 int *atc = nullptr;
2395 double *weight = nullptr, weight_tot;
2397 std::array<real, MAXFORCEPARAM> forceParam = {0.0};
2398 ptr = line;
2399 ret = sscanf(ptr, "%d%n", &a, &n);
2400 ptr += n;
2401 if (ret == 0)
2403 auto message = gmx::formatString("Expected an atom index in section \"%s\"",
2404 dir2str(d));
2405 warning_error_and_exit(wi, message, FARGS);
2408 sscanf(ptr, "%d%n", &type, &n);
2409 ptr += n;
2410 ftype = ifunc_index(d, type);
2411 int firstAtom = a - 1;
2413 weight_tot = 0;
2414 nj = 0;
2417 ret = sscanf(ptr, "%d%n", &a, &n);
2418 ptr += n;
2419 if (ret > 0)
2421 if (nj % 20 == 0)
2423 srenew(atc, nj+20);
2424 srenew(weight, nj+20);
2426 atc[nj] = a - 1;
2427 switch (type)
2429 case 1:
2430 weight[nj] = 1;
2431 break;
2432 case 2:
2433 /* Here we use the A-state mass as a parameter.
2434 * Note that the B-state mass has no influence.
2436 weight[nj] = at->atom[atc[nj]].m;
2437 break;
2438 case 3:
2439 weight[nj] = -1;
2440 ret = sscanf(ptr, "%lf%n", &(weight[nj]), &n);
2441 ptr += n;
2442 if (weight[nj] < 0)
2444 auto message = gmx::formatString
2445 ("No weight or negative weight found for vsiten "
2446 "constructing atom %d (atom index %d)",
2447 nj+1, atc[nj]+1);
2448 warning_error_and_exit(wi, message, FARGS);
2450 break;
2451 default:
2452 auto message = gmx::formatString("Unknown vsiten type %d", type);
2453 warning_error_and_exit(wi, message, FARGS);
2455 weight_tot += weight[nj];
2456 nj++;
2459 while (ret > 0);
2461 if (nj == 0)
2463 auto message = gmx::formatString("Expected more than one atom index in section \"%s\"",
2464 dir2str(d));
2465 warning_error_and_exit(wi, message, FARGS);
2468 if (weight_tot == 0)
2470 warning_error_and_exit(wi, "The total mass of the construting atoms is zero", FARGS);
2473 for (int j = 0; j < nj; j++)
2475 std::vector<int> atoms = {firstAtom, atc[j]};
2476 forceParam[0] = nj;
2477 forceParam[1] = weight[j]/weight_tot;
2478 /* Put the values in the appropriate arrays */
2479 add_param_to_list (&bond[ftype], InteractionOfType(atoms, forceParam));
2482 sfree(atc);
2483 sfree(weight);
2486 void push_mol(gmx::ArrayRef<MoleculeInformation> mols, char *pline, int *whichmol,
2487 int *nrcopies,
2488 warninp *wi)
2490 char type[STRLEN];
2492 if (sscanf(pline, "%s%d", type, nrcopies) != 2)
2494 too_few(wi);
2495 return;
2498 /* Search moleculename.
2499 * Here we originally only did case insensitive matching. But because
2500 * some PDB files can have many chains and use case to generate more
2501 * chain-identifiers, which in turn end up in our moleculetype name,
2502 * we added support for case-sensitivity.
2504 int nrcs = 0;
2505 int nrci = 0;
2506 int matchci = -1;
2507 int matchcs = -1;
2508 int i = 0;
2509 for (const auto &mol : mols)
2511 if (strcmp(type, *(mol.name)) == 0)
2513 nrcs++;
2514 matchcs = i;
2516 if (gmx_strcasecmp(type, *(mol.name)) == 0)
2518 nrci++;
2519 matchci = i;
2521 i++;
2524 if (nrcs == 1)
2526 // select the case sensitive match
2527 *whichmol = matchcs;
2529 else
2531 // avoid matching case-insensitive when we have multiple matches
2532 if (nrci > 1)
2534 auto message = gmx::formatString
2535 ("For moleculetype '%s' in [ system ] %d case insensitive "
2536 "matches, but %d case sensitive matches were found. Check "
2537 "the case of the characters in the moleculetypes.",
2538 type, nrci, nrcs);
2539 warning_error_and_exit(wi, message, FARGS);
2541 if (nrci == 1)
2543 // select the unique case insensitive match
2544 *whichmol = matchci;
2546 else
2548 auto message = gmx::formatString("No such moleculetype %s", type);
2549 warning_error_and_exit(wi, message, FARGS);
2554 void push_excl(char *line, gmx::ArrayRef<gmx::ExclusionBlock> b2, warninp *wi)
2556 int i, j;
2557 int n;
2558 char base[STRLEN], format[STRLEN];
2560 if (sscanf(line, "%d", &i) == 0)
2562 return;
2565 if ((1 <= i) && (i <= b2.ssize()))
2567 i--;
2569 else
2571 return;
2573 strcpy(base, "%*d");
2576 strcpy(format, base);
2577 strcat(format, "%d");
2578 n = sscanf(line, format, &j);
2579 if (n == 1)
2581 if ((1 <= j) && (j <= b2.ssize()))
2583 j--;
2584 b2[i].atomNumber.push_back(j);
2585 /* also add the reverse exclusion! */
2586 b2[j].atomNumber.push_back(i);
2587 strcat(base, "%*d");
2589 else
2591 auto message = gmx::formatString("Invalid Atomnr j: %d, b2->nr: %zu\n", j, b2.size());
2592 warning_error_and_exit(wi, message, FARGS);
2596 while (n == 1);
2599 int add_atomtype_decoupled(t_symtab *symtab, PreprocessingAtomTypes *at,
2600 t_nbparam ***nbparam, t_nbparam ***pair)
2602 t_atom atom;
2603 int nr;
2605 /* Define an atom type with all parameters set to zero (no interactions) */
2606 atom.q = 0.0;
2607 atom.m = 0.0;
2608 /* Type for decoupled atoms could be anything,
2609 * this should be changed automatically later when required.
2611 atom.ptype = eptAtom;
2613 std::array<real, MAXFORCEPARAM> forceParam = {0.0};
2614 nr = at->addType(symtab, atom, "decoupled", InteractionOfType({}, forceParam, ""), -1, 0);
2616 /* Add space in the non-bonded parameters matrix */
2617 realloc_nb_params(at, nbparam, pair);
2619 return nr;
2622 static void convert_pairs_to_pairsQ(gmx::ArrayRef<InteractionsOfType> interactions,
2623 real fudgeQQ, t_atoms *atoms)
2625 /* Add the pair list to the pairQ list */
2626 std::vector<InteractionOfType> paramnew;
2628 gmx::ArrayRef<const InteractionOfType> paramp1 = interactions[F_LJ14].interactionTypes;
2629 gmx::ArrayRef<const InteractionOfType> paramp2 = interactions[F_LJC14_Q].interactionTypes;
2631 /* Fill in the new F_LJC14_Q array with the old one. NOTE:
2632 it may be possible to just ADD the converted F_LJ14 array
2633 to the old F_LJC14_Q array, but since we have to create
2634 a new sized memory structure, better just to deep copy it all.
2638 for (const auto &param : paramp2)
2640 paramnew.emplace_back(param);
2643 for (const auto &param : paramp1)
2645 std::vector<real> forceParam = {
2646 fudgeQQ, atoms->atom[param.ai()].q, atoms->atom[param.aj()].q,
2647 param.c0(), param.c1()
2649 paramnew.emplace_back(InteractionOfType(param.atoms(), forceParam, ""));
2652 /* now assign the new data to the F_LJC14_Q structure */
2653 interactions[F_LJC14_Q].interactionTypes = paramnew;
2655 /* Empty the LJ14 pairlist */
2656 interactions[F_LJ14].interactionTypes.clear();
2659 static void generate_LJCpairsNB(MoleculeInformation *mol, int nb_funct, InteractionsOfType *nbp, warninp *wi)
2661 int n, ntype;
2662 t_atom *atom;
2663 t_blocka *excl;
2664 bool bExcl;
2666 n = mol->atoms.nr;
2667 atom = mol->atoms.atom;
2669 ntype = static_cast<int>(std::sqrt(static_cast<double>(nbp->size())));
2670 GMX_ASSERT(ntype * ntype == gmx::ssize(*nbp), "Number of pairs of generated non-bonded parameters should be a perfect square");
2672 /* Add a pair interaction for all non-excluded atom pairs */
2673 excl = &mol->excls;
2674 for (int i = 0; i < n; i++)
2676 for (int j = i+1; j < n; j++)
2678 bExcl = FALSE;
2679 for (int k = excl->index[i]; k < excl->index[i+1]; k++)
2681 if (excl->a[k] == j)
2683 bExcl = TRUE;
2686 if (!bExcl)
2688 if (nb_funct != F_LJ)
2690 auto message = gmx::formatString
2691 ("Can only generate non-bonded pair interactions "
2692 "for Van der Waals type Lennard-Jones");
2693 warning_error_and_exit(wi, message, FARGS);
2695 std::vector<int> atoms = {i, j};
2696 std::vector<real> forceParam = {
2697 atom[i].q,
2698 atom[j].q,
2699 nbp->interactionTypes[ntype*atom[i].type+atom[j].type].c0(),
2700 nbp->interactionTypes[ntype*atom[i].type+atom[j].type].c1()
2702 add_param_to_list(&mol->interactions[F_LJC_PAIRS_NB], InteractionOfType(atoms, forceParam));
2708 static void set_excl_all(t_blocka *excl)
2710 int nat, i, j, k;
2712 /* Get rid of the current exclusions and exclude all atom pairs */
2713 nat = excl->nr;
2714 excl->nra = nat*nat;
2715 srenew(excl->a, excl->nra);
2716 k = 0;
2717 for (i = 0; i < nat; i++)
2719 excl->index[i] = k;
2720 for (j = 0; j < nat; j++)
2722 excl->a[k++] = j;
2725 excl->index[nat] = k;
2728 static void decouple_atoms(t_atoms *atoms, int atomtype_decouple,
2729 int couple_lam0, int couple_lam1,
2730 const char *mol_name, warninp *wi)
2732 int i;
2734 for (i = 0; i < atoms->nr; i++)
2736 t_atom *atom;
2738 atom = &atoms->atom[i];
2740 if (atom->qB != atom->q || atom->typeB != atom->type)
2742 auto message = gmx::formatString
2743 ("Atom %d in molecule type '%s' has different A and B state "
2744 "charges and/or atom types set in the topology file as well "
2745 "as through the mdp option '%s'. You can not use both "
2746 "these methods simultaneously.",
2747 i + 1, mol_name, "couple-moltype");
2748 warning_error_and_exit(wi, message, FARGS);
2751 if (couple_lam0 == ecouplamNONE || couple_lam0 == ecouplamVDW)
2753 atom->q = 0.0;
2755 if (couple_lam0 == ecouplamNONE || couple_lam0 == ecouplamQ)
2757 atom->type = atomtype_decouple;
2759 if (couple_lam1 == ecouplamNONE || couple_lam1 == ecouplamVDW)
2761 atom->qB = 0.0;
2763 if (couple_lam1 == ecouplamNONE || couple_lam1 == ecouplamQ)
2765 atom->typeB = atomtype_decouple;
2770 void convert_moltype_couple(MoleculeInformation *mol, int atomtype_decouple, real fudgeQQ,
2771 int couple_lam0, int couple_lam1,
2772 bool bCoupleIntra, int nb_funct, InteractionsOfType *nbp,
2773 warninp *wi)
2775 convert_pairs_to_pairsQ(mol->interactions, fudgeQQ, &mol->atoms);
2776 if (!bCoupleIntra)
2778 generate_LJCpairsNB(mol, nb_funct, nbp, wi);
2779 set_excl_all(&mol->excls);
2781 decouple_atoms(&mol->atoms, atomtype_decouple, couple_lam0, couple_lam1,
2782 *mol->name, wi);