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.
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
,
71 InteractionsOfType
*interactions
,
72 PreprocessingAtomTypes
*atypes
,
76 real c
, bi
, bj
, ci
, cj
, ci0
, ci1
, ci2
, cj0
, cj1
, cj2
;
78 /* Lean mean shortcuts */
81 interactions
->interactionTypes
.clear();
83 std::array
<real
, MAXFORCEPARAM
> forceParam
= {NOTSET
};
84 /* Fill the matrix with force parameters */
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
);
103 interactions
->interactionTypes
.emplace_back(InteractionOfType({}, forceParam
));
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)
126 forceParam
[1] = std::sqrt(ci1
*cj1
);
127 interactions
->interactionTypes
.emplace_back(InteractionOfType({}, forceParam
));
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)
150 forceParam
[1] = std::sqrt(ci1
*cj1
);
151 interactions
->interactionTypes
.emplace_back(InteractionOfType({}, forceParam
));
157 auto message
= gmx::formatString("No such combination rule %d", comb
);
158 warning_error_and_exit(wi
, message
, FARGS
);
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))
181 forceParam
[1] = 2.0/(1/bi
+1/bj
);
183 forceParam
[2] = std::sqrt(ci2
* cj2
);
184 interactions
->interactionTypes
.emplace_back(InteractionOfType({}, forceParam
));
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. */
200 //! Has this combination been set.
202 //! The non-bonded parameters
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
);
216 snew((*pair
)[atnr
-1], atnr
);
220 int copy_nbparams(t_nbparam
**param
, int ftype
, InteractionsOfType
*interactions
, int nr
)
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
]);
247 void free_nbparam(t_nbparam
**param
, int nr
)
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");
260 static void copy_B_from_A(int ftype
, double *c
)
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
++)
274 void push_at (t_symtab
*symtab
, PreprocessingAtomTypes
*at
, PreprocessingBondAtomType
*bondAtomType
,
275 char *line
, int nb_funct
,
276 t_nbparam
***nbparam
, t_nbparam
***pair
,
283 t_xlate xl
[eptNR
] = {
291 int nr
, nfields
, j
, pt
, nfp0
= -1;
292 int batype_nr
, nread
;
293 char type
[STRLEN
], btype
[STRLEN
], ptype
[STRLEN
];
295 double c
[MAXFORCEPARAM
];
296 char tmpfield
[12][100]; /* Max 12 fields of width 100 */
299 bool have_atomic_number
;
300 bool have_bonded_type
;
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.
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
;
357 have_bonded_type
= ( isalpha(tmpfield
[1][0]) != 0 );
358 have_atomic_number
= !have_bonded_type
;
361 /* optional fields */
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]);
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]);
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]);
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]);
420 if (!have_bonded_type
)
425 if (!have_atomic_number
)
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]);
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]);
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]);
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]);
485 if (!have_bonded_type
)
490 if (!have_atomic_number
)
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
++)
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)
522 for (j
= 0; (j
< eptNR
); j
++)
524 if (gmx_strcasecmp(ptype
, xl
[j
].entry
) == 0)
531 auto message
= gmx::formatString("Invalid particle type %s", ptype
);
532 warning_error_and_exit(wi
, message
, FARGS
);
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
,
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
);
574 /* Add space in the non-bonded parameters matrix */
575 realloc_nb_params(at
, nbparam
, pair
);
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
,
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
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
)
646 if (!identicalParameters
)
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.");
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
,
674 "\nUse dihedraltype 9 to allow several multiplicity terms. Only consecutive "
675 "lines are combined. Non-consective lines overwrite each other."
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
);
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
]);
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
,
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
,
772 PreprocessingAtomTypes
*at
,
773 PreprocessingBondAtomType
*bondAtomType
,
777 const char *formal
[MAXATOMLIST
+1] = {
786 const char *formnl
[MAXATOMLIST
+1] = {
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
;
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
);
816 ft
= strtol(alc
[nral
], nullptr, 10);
817 ftype
= ifunc_index(d
, ft
);
819 nrfpA
= interaction_function
[ftype
].nrfpA
;
820 strcpy(f1
, formnl
[nral
]);
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]))
827 /* Copy the B-state from the A-state */
828 copy_B_from_A(ftype
, c
);
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");
842 warning_error(wi
, "Too many parameters");
844 for (i
= nn
; (i
< nrfp
); i
++)
850 std::vector
<int> atomTypes
= atomTypesFromAtomNames(at
,
852 gmx::arrayRefFromArray(alc
, nral
),
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
,
867 const char *formal
[MAXATOMLIST
+1] = {
876 const char *formnl
[MAXATOMLIST
+1] = {
882 "%*s%*s%*s%*s%*s%*s",
883 "%*s%*s%*s%*s%*s%*s%*s"
885 const char *formlf
[MAXFORCEPARAM
] = {
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
;
901 char alc
[MAXATOMLIST
+1][20];
902 double c
[MAXFORCEPARAM
];
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]))
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
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 */
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]))
940 ft
= strtol(alc
[nral
], nullptr, 10);
944 auto message
= gmx::formatString("Incorrect number of atomtypes for dihedral (%d instead of 2 or 4)", nn
-1);
945 warning_error(wi
, message
);
951 /* Previously, we have always overwritten parameters if e.g. a torsion
952 with the same atomtypes occurs on multiple lines. However, CHARMM and
953 some other force fields specify multiple dihedrals over some bonds,
954 including cosines with multiplicity 6 and somethimes even higher.
955 Thus, they cannot be represented with Ryckaert-Bellemans terms.
956 To add support for these force fields, Dihedral type 9 is identical to
957 normal proper dihedrals, but repeated entries are allowed.
964 bAllowRepeat
= FALSE
;
968 ftype
= ifunc_index(d
, ft
);
970 nrfpA
= interaction_function
[ftype
].nrfpA
;
972 strcpy(f1
, formnl
[nral
]);
973 strcat(f1
, formlf
[nrfp
-1]);
975 /* Check number of parameters given */
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]))
981 /* Copy the B-state from the A-state */
982 copy_B_from_A(ftype
, c
);
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");
996 warning_error(wi
, "Too many parameters");
998 for (i
= nn
; (i
< nrfp
); i
++)
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);
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
,
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
;
1051 if (sscanf (pline
, "%s%s%d", a0
, a1
, &f
) != 3)
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
);
1068 /* Get the force parameters */
1070 if (ftype
== F_LJ14
)
1072 n
= sscanf(pline
, form4
, &c
[0], &c
[1], &c
[2], &c
[3]);
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
++)
1087 else if (ftype
== F_LJC14_Q
)
1089 n
= sscanf(pline
, form5
, &c
[0], &c
[1], &c
[2], &c
[3], &dum
);
1092 incorrect_n_param(wi
);
1098 if (sscanf(pline
, form3
, &c
[0], &c
[1], &dum
) != 2)
1100 incorrect_n_param(wi
);
1106 if (sscanf(pline
, form4
, &c
[0], &c
[1], &c
[2], &dum
) != 3)
1108 incorrect_n_param(wi
);
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
++)
1122 /* Put the parameters in the matrix */
1123 if ((ai
= atypes
->atomTypeFromName(a0
)) == NOTSET
)
1125 auto message
= gmx::formatString("Atomtype %s not found", a0
);
1126 warning_error_and_exit(wi
, message
, FARGS
);
1128 if ((aj
= atypes
->atomTypeFromName(a1
)) == NOTSET
)
1130 auto message
= gmx::formatString("Atomtype %s not found", a1
);
1131 warning_error_and_exit(wi
, message
, FARGS
);
1133 nbp
= &(nbt
[std::max(ai
, aj
)][std::min(ai
, aj
)]);
1138 for (i
= 0; i
< nrfp
; i
++)
1140 bId
= bId
&& (nbp
->c
[i
] == cr
[i
]);
1144 auto message
= gmx::formatString
1145 ("Non-bonded parameters were defined previously (e.g. in the forcefield files), "
1146 "and have now been defined again. This could happen e.g. if you would "
1147 "use a self-contained molecule .itp file that duplicates or replaces "
1148 "the contents of the standard force-field files. You should check "
1149 "the contents of your files and remove such repetition. If you know "
1150 "you should override the previous definitions, then you could choose "
1151 "to suppress this warning with -maxwarn.");
1152 warning(wi
, message
);
1153 fprintf(stderr
, " old:");
1154 for (i
= 0; i
< nrfp
; i
++)
1156 fprintf(stderr
, " %g", nbp
->c
[i
]);
1158 fprintf(stderr
, " new\n%s\n", pline
);
1162 for (i
= 0; i
< nrfp
; i
++)
1169 push_cmaptype(Directive d
,
1170 gmx::ArrayRef
<InteractionsOfType
> bt
,
1172 PreprocessingAtomTypes
*atomtypes
,
1173 PreprocessingBondAtomType
*bondAtomType
,
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 */
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
);
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);
1216 /* Read in CMAP parameters */
1218 for (int i
= 0; i
< ncmap
; i
++)
1220 while (isspace(*(line
+start
+sl
)))
1224 nn
= sscanf(line
+start
+sl
, " %s ", s
);
1226 bt
[F_CMAP
].cmap
.emplace_back(strtod(s
, nullptr));
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
]);
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
,
1290 gmx::constArrayRefFromArray(alc
, nral
),
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
,
1301 int type
, char *ctype
, int ptype
,
1303 char *resname
, char *name
, real m0
, real q0
,
1304 int typeB
, char *ctypeB
, real mB
, real qB
,
1307 int j
, resind
= 0, resnr
;
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
]))
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);
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
)
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
;
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);
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
);
1388 void push_atom(t_symtab
*symtab
,
1389 t_atoms
*at
, PreprocessingAtomTypes
*atypes
, char *line
,
1393 int cgnumber
, atomnr
, type
, typeB
, nscan
;
1394 char id
[STRLEN
], ctype
[STRLEN
], ctypeB
[STRLEN
],
1395 resnumberic
[STRLEN
], resname
[STRLEN
], name
[STRLEN
], check
[STRLEN
];
1396 double m
, q
, mb
, qb
;
1397 real m0
, q0
, mB
, qB
;
1399 /* Fixed parameters */
1400 if (sscanf(line
, "%s%s%s%s%s%d",
1401 id
, ctype
, resnumberic
, resname
, name
, &cgnumber
) != 6)
1406 sscanf(id
, "%d", &atomnr
);
1407 if ((type
= atypes
->atomTypeFromName(ctype
)) == NOTSET
)
1409 auto message
= gmx::formatString("Atomtype %s not found", ctype
);
1410 warning_error_and_exit(wi
, message
, FARGS
);
1412 ptype
= atypes
->atomParticleTypeFromAtomType(type
);
1414 /* Set default from type */
1415 q0
= atypes
->atomChargeFromAtomType(type
);
1416 m0
= atypes
->atomMassFromAtomType(type
);
1421 /* Optional parameters */
1422 nscan
= sscanf(line
, "%*s%*s%*s%*s%*s%*s%lf%lf%s%lf%lf%s",
1423 &q
, &m
, ctypeB
, &qb
, &mb
, check
);
1425 /* Nasty switch that falls thru all the way down! */
1434 if ((typeB
= atypes
->atomTypeFromName(ctypeB
)) == NOTSET
)
1436 auto message
= gmx::formatString("Atomtype %s not found", ctypeB
);
1437 warning_error_and_exit(wi
, message
, FARGS
);
1439 qB
= atypes
->atomChargeFromAtomType(typeB
);
1440 mB
= atypes
->atomMassFromAtomType(typeB
);
1449 warning_error(wi
, "Too many parameters");
1457 push_atom_now(symtab
, at
, atomnr
, atypes
->atomNumberFromAtomType(type
),
1458 type
, ctype
, ptype
, resnumberic
,
1459 resname
, name
, m0
, q0
, typeB
,
1460 typeB
== type
? ctype
: ctypeB
, mB
, qB
, wi
);
1463 void push_molt(t_symtab
*symtab
,
1464 std::vector
<MoleculeInformation
> *mol
,
1471 if ((sscanf(line
, "%s%d", type
, &nrexcl
)) != 2)
1473 warning_error(wi
, "Expected a molecule type name and nrexcl");
1476 /* Test if this moleculetype overwrites another */
1477 const auto found
= std::find_if(mol
->begin(), mol
->end(),
1478 [&type
](const auto &m
)
1479 { return strcmp(*(m
.name
), type
) == 0; });
1480 if (found
!= mol
->end())
1482 auto message
= gmx::formatString("moleculetype %s is redefined", type
);
1483 warning_error_and_exit(wi
, message
, FARGS
);
1486 mol
->emplace_back();
1487 mol
->back().initMolInfo();
1489 /* Fill in the values */
1490 mol
->back().name
= put_symtab(symtab
, type
);
1491 mol
->back().nrexcl
= nrexcl
;
1492 mol
->back().excl_set
= false;
1495 static bool findIfAllNBAtomsMatch(gmx::ArrayRef
<const int> atomsFromParameterArray
,
1496 gmx::ArrayRef
<const int> atomsFromCurrentParameter
,
1500 if (atomsFromParameterArray
.size() != atomsFromCurrentParameter
.size())
1506 for (gmx::index i
= 0; i
< atomsFromCurrentParameter
.ssize(); i
++)
1508 if (at
->atom
[atomsFromCurrentParameter
[i
]].typeB
!= atomsFromParameterArray
[i
])
1517 for (gmx::index i
= 0; i
< atomsFromCurrentParameter
.ssize(); i
++)
1519 if (at
->atom
[atomsFromCurrentParameter
[i
]].type
!= atomsFromParameterArray
[i
])
1528 static bool default_nb_params(int ftype
, gmx::ArrayRef
<InteractionsOfType
> bt
, t_atoms
*at
,
1529 InteractionOfType
*p
, int c_start
, bool bB
, bool bGenPairs
)
1533 InteractionOfType
*pi
= nullptr;
1534 int nr
= bt
[ftype
].size();
1535 int nral
= NRAL(ftype
);
1536 int nrfp
= interaction_function
[ftype
].nrfpA
;
1537 int nrfpB
= interaction_function
[ftype
].nrfpB
;
1539 if ((!bB
&& nrfp
== 0) || (bB
&& nrfpB
== 0))
1547 /* First test the generated-pair position to save
1548 * time when we have 1000*1000 entries for e.g. OPLS...
1550 ntype
= static_cast<int>(std::sqrt(static_cast<double>(nr
)));
1551 GMX_ASSERT(ntype
* ntype
== nr
, "Number of pairs of generated non-bonded parameters should be a perfect square");
1554 ti
= at
->atom
[p
->ai()].typeB
;
1555 tj
= at
->atom
[p
->aj()].typeB
;
1559 ti
= at
->atom
[p
->ai()].type
;
1560 tj
= at
->atom
[p
->aj()].type
;
1562 pi
= &(bt
[ftype
].interactionTypes
[ntype
*ti
+tj
]);
1563 if (pi
->atoms().ssize() < nral
)
1565 /* not initialized yet with atom names */
1570 bFound
= ((ti
== pi
->ai()) && (tj
== pi
->aj()));
1574 gmx::ArrayRef
<const int> paramAtoms
= p
->atoms();
1575 /* Search explicitly if we didnt find it */
1578 auto foundParameter
= std::find_if(bt
[ftype
].interactionTypes
.begin(),
1579 bt
[ftype
].interactionTypes
.end(),
1580 [¶mAtoms
, &at
, &bB
](const auto ¶m
)
1581 { return findIfAllNBAtomsMatch(param
.atoms(), paramAtoms
, at
, bB
); });
1582 if (foundParameter
!= bt
[ftype
].interactionTypes
.end())
1585 pi
= &(*foundParameter
);
1591 gmx::ArrayRef
<const real
> forceParam
= pi
->forceParam();
1594 if (nrfp
+nrfpB
> MAXFORCEPARAM
)
1596 gmx_incons("Too many force parameters");
1598 for (int j
= c_start
; j
< nrfpB
; j
++)
1600 p
->setForceParameter(nrfp
+j
, forceParam
[j
]);
1605 for (int j
= c_start
; j
< nrfp
; j
++)
1607 p
->setForceParameter(j
, forceParam
[j
]);
1613 for (int j
= c_start
; j
< nrfp
; j
++)
1615 p
->setForceParameter(j
, 0.0);
1621 static bool default_cmap_params(gmx::ArrayRef
<InteractionsOfType
> bondtype
,
1622 t_atoms
*at
, PreprocessingAtomTypes
*atypes
,
1623 InteractionOfType
*p
, bool bB
,
1624 int *cmap_type
, int *nparam_def
,
1629 bool bFound
= false;
1634 /* Match the current cmap angle against the list of cmap_types */
1635 for (int i
= 0; i
< bondtype
[F_CMAP
].nct() && !bFound
; i
+= 6)
1644 (atypes
->bondAtomTypeFromAtomType(at
->atom
[p
->ai()].type
) == bondtype
[F_CMAP
].cmapAtomTypes
[i
]) &&
1645 (atypes
->bondAtomTypeFromAtomType(at
->atom
[p
->aj()].type
) == bondtype
[F_CMAP
].cmapAtomTypes
[i
+1]) &&
1646 (atypes
->bondAtomTypeFromAtomType(at
->atom
[p
->ak()].type
) == bondtype
[F_CMAP
].cmapAtomTypes
[i
+2]) &&
1647 (atypes
->bondAtomTypeFromAtomType(at
->atom
[p
->al()].type
) == bondtype
[F_CMAP
].cmapAtomTypes
[i
+3]) &&
1648 (atypes
->bondAtomTypeFromAtomType(at
->atom
[p
->am()].type
) == bondtype
[F_CMAP
].cmapAtomTypes
[i
+4]))
1650 /* Found cmap torsion */
1652 ct
= bondtype
[F_CMAP
].cmapAtomTypes
[i
+5];
1658 /* If we did not find a matching type for this cmap torsion */
1661 auto message
= gmx::formatString("Unknown cmap torsion between atoms %d %d %d %d %d",
1662 p
->ai()+1, p
->aj()+1, p
->ak()+1, p
->al()+1, p
->am()+1);
1663 warning_error_and_exit(wi
, message
, FARGS
);
1666 *nparam_def
= nparam_found
;
1672 /* Returns the number of exact atom type matches, i.e. non wild-card matches,
1673 * returns -1 when there are no matches at all.
1675 static int natom_match(const InteractionOfType
&pi
,
1676 int type_i
, int type_j
, int type_k
, int type_l
,
1677 const PreprocessingAtomTypes
* atypes
)
1679 if ((pi
.ai() == -1 || atypes
->bondAtomTypeFromAtomType(type_i
) == pi
.ai()) &&
1680 (pi
.aj() == -1 || atypes
->bondAtomTypeFromAtomType(type_j
) == pi
.aj()) &&
1681 (pi
.ak() == -1 || atypes
->bondAtomTypeFromAtomType(type_k
) == pi
.ak()) &&
1682 (pi
.al() == -1 || atypes
->bondAtomTypeFromAtomType(type_l
) == pi
.al()))
1685 (pi
.ai() == -1 ? 0 : 1) +
1686 (pi
.aj() == -1 ? 0 : 1) +
1687 (pi
.ak() == -1 ? 0 : 1) +
1688 (pi
.al() == -1 ? 0 : 1);
1696 static int findNumberOfDihedralAtomMatches(const InteractionOfType
¤tParamFromParameterArray
,
1697 const InteractionOfType
¶meterToAdd
,
1699 const PreprocessingAtomTypes
*atypes
,
1704 return natom_match(currentParamFromParameterArray
,
1705 at
->atom
[parameterToAdd
.ai()].typeB
,
1706 at
->atom
[parameterToAdd
.aj()].typeB
,
1707 at
->atom
[parameterToAdd
.ak()].typeB
,
1708 at
->atom
[parameterToAdd
.al()].typeB
, atypes
);
1712 return natom_match(currentParamFromParameterArray
,
1713 at
->atom
[parameterToAdd
.ai()].type
,
1714 at
->atom
[parameterToAdd
.aj()].type
,
1715 at
->atom
[parameterToAdd
.ak()].type
,
1716 at
->atom
[parameterToAdd
.al()].type
, atypes
);
1720 static bool findIfAllParameterAtomsMatch(gmx::ArrayRef
<const int> atomsFromParameterArray
,
1721 gmx::ArrayRef
<const int> atomsFromCurrentParameter
,
1723 const PreprocessingAtomTypes
*atypes
,
1726 if (atomsFromParameterArray
.size() != atomsFromCurrentParameter
.size())
1732 for (gmx::index i
= 0; i
< atomsFromCurrentParameter
.ssize(); i
++)
1734 if (atypes
->bondAtomTypeFromAtomType(
1735 at
->atom
[atomsFromCurrentParameter
[i
]].typeB
) != atomsFromParameterArray
[i
])
1744 for (gmx::index i
= 0; i
< atomsFromCurrentParameter
.ssize(); i
++)
1746 if (atypes
->bondAtomTypeFromAtomType(
1747 at
->atom
[atomsFromCurrentParameter
[i
]].type
) != atomsFromParameterArray
[i
])
1756 static std::vector
<InteractionOfType
>::iterator
1757 defaultInteractionsOfType(int ftype
, gmx::ArrayRef
<InteractionsOfType
> bt
,
1758 t_atoms
*at
, PreprocessingAtomTypes
*atypes
,
1759 const InteractionOfType
&p
, bool bB
,
1763 int nrfpA
= interaction_function
[ftype
].nrfpA
;
1764 int nrfpB
= interaction_function
[ftype
].nrfpB
;
1766 if ((!bB
&& nrfpA
== 0) || (bB
&& nrfpB
== 0))
1768 return bt
[ftype
].interactionTypes
.end();
1773 if (ftype
== F_PDIHS
|| ftype
== F_RBDIHS
|| ftype
== F_IDIHS
|| ftype
== F_PIDIHS
)
1775 int nmatch_max
= -1;
1777 /* For dihedrals we allow wildcards. We choose the first type
1778 * that has the most real matches, i.e. non-wildcard matches.
1780 auto prevPos
= bt
[ftype
].interactionTypes
.end();
1781 auto pos
= bt
[ftype
].interactionTypes
.begin();
1782 while (pos
!= bt
[ftype
].interactionTypes
.end() && nmatch_max
< 4)
1784 pos
= std::find_if(bt
[ftype
].interactionTypes
.begin(), bt
[ftype
].interactionTypes
.end(),
1785 [&p
, &at
, &atypes
, &bB
, &nmatch_max
](const auto ¶m
)
1786 { return (findNumberOfDihedralAtomMatches(param
, p
, at
, atypes
, bB
) > nmatch_max
); });
1787 if (pos
!= bt
[ftype
].interactionTypes
.end())
1790 nmatch_max
= findNumberOfDihedralAtomMatches(*pos
, p
, at
, atypes
, bB
);
1794 if (prevPos
!= bt
[ftype
].interactionTypes
.end())
1798 /* Find additional matches for this dihedral - necessary
1800 * The rule in that case is that additional matches
1801 * HAVE to be on adjacent lines!
1804 //Advance iterator (like std::advance) without incrementing past end (UB)
1805 const auto safeAdvance
= [](auto &it
, auto n
, auto end
) {
1806 it
= end
-it
> n
? it
+n
: end
;
1808 /* Continue from current iterator position */
1809 auto nextPos
= prevPos
;
1810 const auto endIter
= bt
[ftype
].interactionTypes
.end();
1811 safeAdvance(nextPos
, 2, endIter
);
1812 for (; nextPos
< endIter
&& bSame
; safeAdvance(nextPos
, 2, endIter
))
1814 bSame
= (prevPos
->ai() == nextPos
->ai() && prevPos
->aj() == nextPos
->aj() && prevPos
->ak() == nextPos
->ak() && prevPos
->al() == nextPos
->al());
1819 /* nparam_found will be increased as long as the numbers match */
1822 *nparam_def
= nparam_found
;
1825 else /* Not a dihedral */
1827 gmx::ArrayRef
<const int> atomParam
= p
.atoms();
1828 auto found
= std::find_if(bt
[ftype
].interactionTypes
.begin(),
1829 bt
[ftype
].interactionTypes
.end(),
1830 [&atomParam
, &at
, &atypes
, &bB
](const auto ¶m
)
1831 { return findIfAllParameterAtomsMatch(param
.atoms(), atomParam
, at
, atypes
, bB
); });
1832 if (found
!= bt
[ftype
].interactionTypes
.end())
1836 *nparam_def
= nparam_found
;
1843 void push_bond(Directive d
, gmx::ArrayRef
<InteractionsOfType
> bondtype
,
1844 gmx::ArrayRef
<InteractionsOfType
> bond
,
1845 t_atoms
*at
, PreprocessingAtomTypes
*atypes
, char *line
,
1846 bool bBonded
, bool bGenPairs
, real fudgeQQ
,
1847 bool bZero
, bool *bWarn_copy_A_B
,
1850 const char *aaformat
[MAXATOMLIST
] = {
1858 const char *asformat
[MAXATOMLIST
] = {
1863 "%*s%*s%*s%*s%*s%*s",
1864 "%*s%*s%*s%*s%*s%*s%*s"
1866 const char *ccformat
= "%lf%lf%lf%lf%lf%lf%lf%lf%lf%lf%lf%lf%lf";
1867 int nral
, nral_fmt
, nread
, ftype
;
1868 char format
[STRLEN
];
1869 /* One force parameter more, so we can check if we read too many */
1870 double cc
[MAXFORCEPARAM
+1];
1871 int aa
[MAXATOMLIST
+1];
1872 bool bFoundA
= FALSE
, bFoundB
= FALSE
, bDef
, bSwapParity
= FALSE
;
1873 int nparam_defA
, nparam_defB
;
1875 nparam_defA
= nparam_defB
= 0;
1877 ftype
= ifunc_index(d
, 1);
1879 for (int j
= 0; j
< nral
; j
++)
1883 bDef
= (NRFP(ftype
) > 0);
1885 if (ftype
== F_SETTLE
)
1887 /* SETTLE acts on 3 atoms, but the topology format only specifies
1888 * the first atom (for historical reasons).
1897 nread
= sscanf(line
, aaformat
[nral_fmt
-1],
1898 &aa
[0], &aa
[1], &aa
[2], &aa
[3], &aa
[4], &aa
[5]);
1900 if (ftype
== F_SETTLE
)
1907 if (nread
< nral_fmt
)
1912 else if (nread
> nral_fmt
)
1914 /* this is a hack to allow for virtual sites with swapped parity */
1915 bSwapParity
= (aa
[nral
] < 0);
1918 aa
[nral
] = -aa
[nral
];
1920 ftype
= ifunc_index(d
, aa
[nral
]);
1929 auto message
= gmx::formatString("Negative function types only allowed for %s and %s",
1930 interaction_function
[F_VSITE3FAD
].longname
,
1931 interaction_function
[F_VSITE3OUT
].longname
);
1932 warning_error_and_exit(wi
, message
, FARGS
);
1938 /* Check for double atoms and atoms out of bounds */
1939 for (int i
= 0; (i
< nral
); i
++)
1941 if (aa
[i
] < 1 || aa
[i
] > at
->nr
)
1943 auto message
= gmx::formatString
1944 ("Atom index (%d) in %s out of bounds (1-%d).\n"
1945 "This probably means that you have inserted topology section \"%s\"\n"
1946 "in a part belonging to a different molecule than you intended to.\n"
1947 "In that case move the \"%s\" section to the right molecule.",
1948 aa
[i
], dir2str(d
), at
->nr
, dir2str(d
), dir2str(d
));
1949 warning_error_and_exit(wi
, message
, FARGS
);
1951 for (int j
= i
+1; (j
< nral
); j
++)
1953 GMX_ASSERT(j
< MAXATOMLIST
+ 1, "Values from nral=NRAL() will satisfy this, we assert to keep gcc 4 happy");
1956 auto message
= gmx::formatString("Duplicate atom index (%d) in %s", aa
[i
], dir2str(d
));
1957 if (ftype
== F_ANGRES
)
1959 /* Since the angle restraints uses 2 pairs of atoms to
1960 * defines an angle between vectors, it can be useful
1961 * to use one atom twice, so we only issue a note here.
1963 warning_note(wi
, message
);
1967 warning_error(wi
, message
);
1973 /* default force parameters */
1974 std::vector
<int> atoms
;
1975 for (int j
= 0; (j
< nral
); j
++)
1977 atoms
.emplace_back(aa
[j
]-1);
1979 /* need to have an empty but initialized param array for some reason */
1980 std::array
<real
, MAXFORCEPARAM
> forceParam
= {0.0};
1982 /* Get force params for normal and free energy perturbation
1983 * studies, as determined by types!
1985 InteractionOfType
param(atoms
, forceParam
, "");
1987 std::vector
<InteractionOfType
>::iterator foundAParameter
= bondtype
[ftype
].interactionTypes
.end();
1988 std::vector
<InteractionOfType
>::iterator foundBParameter
= bondtype
[ftype
].interactionTypes
.end();
1991 foundAParameter
= defaultInteractionsOfType(ftype
,
1998 if (foundAParameter
!= bondtype
[ftype
].interactionTypes
.end())
2000 /* Copy the A-state and B-state default parameters. */
2001 GMX_ASSERT(NRFPA(ftype
)+NRFPB(ftype
) <= MAXFORCEPARAM
, "Bonded interactions may have at most 12 parameters");
2002 gmx::ArrayRef
<const real
> defaultParam
= foundAParameter
->forceParam();
2003 for (int j
= 0; (j
< NRFPA(ftype
)+NRFPB(ftype
)); j
++)
2005 param
.setForceParameter(j
, defaultParam
[j
]);
2009 else if (NRFPA(ftype
) == 0)
2013 foundBParameter
= defaultInteractionsOfType(ftype
,
2020 if (foundBParameter
!= bondtype
[ftype
].interactionTypes
.end())
2022 /* Copy only the B-state default parameters */
2023 gmx::ArrayRef
<const real
> defaultParam
= foundBParameter
->forceParam();
2024 for (int j
= NRFPA(ftype
); (j
< NRFP(ftype
)); j
++)
2026 param
.setForceParameter(j
, defaultParam
[j
]);
2030 else if (NRFPB(ftype
) == 0)
2035 else if (ftype
== F_LJ14
)
2037 bFoundA
= default_nb_params(ftype
, bondtype
, at
, ¶m
, 0, FALSE
, bGenPairs
);
2038 bFoundB
= default_nb_params(ftype
, bondtype
, at
, ¶m
, 0, TRUE
, bGenPairs
);
2040 else if (ftype
== F_LJC14_Q
)
2042 /* Fill in the A-state charges as default parameters */
2043 param
.setForceParameter(0, fudgeQQ
);
2044 param
.setForceParameter(1, at
->atom
[param
.ai()].q
);
2045 param
.setForceParameter(2, at
->atom
[param
.aj()].q
);
2046 /* The default LJ parameters are the standard 1-4 parameters */
2047 bFoundA
= default_nb_params(F_LJ14
, bondtype
, at
, ¶m
, 3, FALSE
, bGenPairs
);
2050 else if (ftype
== F_LJC_PAIRS_NB
)
2052 /* Defaults are not supported here */
2058 gmx_incons("Unknown function type in push_bond");
2061 if (nread
> nral_fmt
)
2063 /* Manually specified parameters - in this case we discard multiple torsion info! */
2065 strcpy(format
, asformat
[nral_fmt
-1]);
2066 strcat(format
, ccformat
);
2068 nread
= sscanf(line
, format
, &cc
[0], &cc
[1], &cc
[2], &cc
[3], &cc
[4], &cc
[5],
2069 &cc
[6], &cc
[7], &cc
[8], &cc
[9], &cc
[10], &cc
[11], &cc
[12]);
2071 if ((nread
== NRFPA(ftype
)) && (NRFPB(ftype
) != 0))
2073 /* We only have to issue a warning if these atoms are perturbed! */
2075 gmx::ArrayRef
<const int> paramAtoms
= param
.atoms();
2076 for (int j
= 0; (j
< nral
); j
++)
2078 bPert
= bPert
|| PERTURBED(at
->atom
[paramAtoms
[j
]]);
2081 if (bPert
&& *bWarn_copy_A_B
)
2083 auto message
= gmx::formatString("Some parameters for bonded interaction involving "
2084 "perturbed atoms are specified explicitly in "
2085 "state A, but not B - copying A to B");
2086 warning(wi
, message
);
2087 *bWarn_copy_A_B
= FALSE
;
2090 /* If only the A parameters were specified, copy them to the B state */
2091 /* The B-state parameters correspond to the first nrfpB
2092 * A-state parameters.
2094 for (int j
= 0; (j
< NRFPB(ftype
)); j
++)
2096 cc
[nread
++] = cc
[j
];
2100 /* If nread was 0 or EOF, no parameters were read => use defaults.
2101 * If nread was nrfpA we copied above so nread=nrfp.
2102 * If nread was nrfp we are cool.
2103 * For F_LJC14_Q we allow supplying fudgeQQ only.
2104 * Anything else is an error!
2106 if ((nread
!= 0) && (nread
!= EOF
) && (nread
!= NRFP(ftype
)) &&
2107 !(ftype
== F_LJC14_Q
&& nread
== 1))
2109 auto message
= gmx::formatString
2110 ("Incorrect number of parameters - found %d, expected %d "
2111 "or %d for %s (after the function type).",
2112 nread
, NRFPA(ftype
), NRFP(ftype
), interaction_function
[ftype
].longname
);
2113 warning_error_and_exit(wi
, message
, FARGS
);
2116 for (int j
= 0; (j
< nread
); j
++)
2118 param
.setForceParameter(j
, cc
[j
]);
2120 /* Check whether we have to use the defaults */
2121 if (nread
== NRFP(ftype
))
2130 /* nread now holds the number of force parameters read! */
2135 /* When we have multiple terms it would be very dangerous to allow perturbations to a different atom type! */
2136 if (ftype
== F_PDIHS
)
2138 if ((nparam_defA
!= nparam_defB
) || ((nparam_defA
> 1 || nparam_defB
> 1) && (foundAParameter
!= foundBParameter
)))
2141 gmx::formatString("Cannot automatically perturb a torsion with multiple terms to different form.\n"
2142 "Please specify perturbed parameters manually for this torsion in your topology!");
2143 warning_error(wi
, message
);
2147 if (nread
> 0 && nread
< NRFPA(ftype
))
2149 /* Issue an error, do not use defaults */
2150 auto message
= gmx::formatString("Not enough parameters, there should be at least %d (or 0 for defaults)", NRFPA(ftype
));
2151 warning_error(wi
, message
);
2154 if (nread
== 0 || nread
== EOF
)
2158 if (interaction_function
[ftype
].flags
& IF_VSITE
)
2160 for (int j
= 0; j
< MAXFORCEPARAM
; j
++)
2162 param
.setForceParameter(j
, NOTSET
);
2166 /* flag to swap parity of vsi te construction */
2167 param
.setForceParameter(1, -1);
2174 fprintf(stderr
, "NOTE: No default %s types, using zeroes\n",
2175 interaction_function
[ftype
].longname
);
2179 auto message
= gmx::formatString("No default %s types", interaction_function
[ftype
].longname
);
2180 warning_error(wi
, message
);
2191 param
.setForceParameter(0, 360 - param
.c0());
2194 param
.setForceParameter(2, -param
.c2());
2201 /* We only have to issue a warning if these atoms are perturbed! */
2203 gmx::ArrayRef
<const int> paramAtoms
= param
.atoms();
2204 for (int j
= 0; (j
< nral
); j
++)
2206 bPert
= bPert
|| PERTURBED(at
->atom
[paramAtoms
[j
]]);
2211 auto message
= gmx::formatString("No default %s types for perturbed atoms, "
2212 "using normal values", interaction_function
[ftype
].longname
);
2213 warning(wi
, message
);
2219 gmx::ArrayRef
<const real
> paramValue
= param
.forceParam();
2220 if ((ftype
== F_PDIHS
|| ftype
== F_ANGRES
|| ftype
== F_ANGRESZ
)
2221 && paramValue
[5] != paramValue
[2])
2223 auto message
= gmx::formatString("%s multiplicity can not be perturbed %f!=%f",
2224 interaction_function
[ftype
].longname
,
2225 paramValue
[2], paramValue
[5]);
2226 warning_error_and_exit(wi
, message
, FARGS
);
2229 if (IS_TABULATED(ftype
) && param
.c0() != param
.c2())
2231 auto message
= gmx::formatString("%s table number can not be perturbed %d!=%d",
2232 interaction_function
[ftype
].longname
,
2233 gmx::roundToInt(param
.c0()), gmx::roundToInt(param
.c0()));
2234 warning_error_and_exit(wi
, message
, FARGS
);
2237 /* Dont add R-B dihedrals where all parameters are zero (no interaction) */
2238 if (ftype
== F_RBDIHS
)
2242 for (int i
= 0; i
< NRFP(ftype
); i
++)
2244 if (paramValue
[i
] != 0.0)
2255 /* Put the values in the appropriate arrays */
2256 add_param_to_list (&bond
[ftype
], param
);
2258 /* Push additional torsions from FF for ftype==9 if we have them.
2259 * We have already checked that the A/B states do not differ in this case,
2260 * so we do not have to double-check that again, or the vsite stuff.
2261 * In addition, those torsions cannot be automatically perturbed.
2263 if (bDef
&& ftype
== F_PDIHS
)
2265 for (int i
= 1; i
< nparam_defA
; i
++)
2267 /* Advance pointer! */
2268 foundAParameter
+= 2;
2269 gmx::ArrayRef
<const real
> forceParam
= foundAParameter
->forceParam();
2270 for (int j
= 0; j
< (NRFPA(ftype
)+NRFPB(ftype
)); j
++)
2272 param
.setForceParameter(j
, forceParam
[j
]);
2274 /* And push the next term for this torsion */
2275 add_param_to_list (&bond
[ftype
], param
);
2280 void push_cmap(Directive d
, gmx::ArrayRef
<InteractionsOfType
> bondtype
,
2281 gmx::ArrayRef
<InteractionsOfType
> bond
,
2282 t_atoms
*at
, PreprocessingAtomTypes
*atypes
, char *line
,
2285 const char *aaformat
[MAXATOMLIST
+1] =
2296 int ftype
, nral
, nread
, ncmap_params
;
2298 int aa
[MAXATOMLIST
+1];
2301 ftype
= ifunc_index(d
, 1);
2305 nread
= sscanf(line
, aaformat
[nral
-1],
2306 &aa
[0], &aa
[1], &aa
[2], &aa
[3], &aa
[4], &aa
[5]);
2313 else if (nread
== nral
)
2315 ftype
= ifunc_index(d
, 1);
2318 /* Check for double atoms and atoms out of bounds */
2319 for (int i
= 0; i
< nral
; i
++)
2321 if (aa
[i
] < 1 || aa
[i
] > at
->nr
)
2323 auto message
= gmx::formatString
2324 ("Atom index (%d) in %s out of bounds (1-%d).\n"
2325 "This probably means that you have inserted topology section \"%s\"\n"
2326 "in a part belonging to a different molecule than you intended to.\n"
2327 "In that case move the \"%s\" section to the right molecule.",
2328 aa
[i
], dir2str(d
), at
->nr
, dir2str(d
), dir2str(d
));
2329 warning_error_and_exit(wi
, message
, FARGS
);
2332 for (int j
= i
+1; (j
< nral
); j
++)
2336 auto message
= gmx::formatString("Duplicate atom index (%d) in %s", aa
[i
], dir2str(d
));
2337 warning_error(wi
, message
);
2342 /* default force parameters */
2343 std::vector
<int> atoms
;
2344 for (int j
= 0; (j
< nral
); j
++)
2346 atoms
.emplace_back(aa
[j
]-1);
2348 std::array
<real
, MAXFORCEPARAM
> forceParam
= {0.0};
2349 InteractionOfType
param(atoms
, forceParam
, "");
2350 /* Get the cmap type for this cmap angle */
2351 bFound
= default_cmap_params(bondtype
, at
, atypes
, ¶m
, FALSE
, &cmap_type
, &ncmap_params
, wi
);
2353 /* We want exactly one parameter (the cmap type in state A (currently no state B) back */
2354 if (bFound
&& ncmap_params
== 1)
2356 /* Put the values in the appropriate arrays */
2357 param
.setForceParameter(0, cmap_type
);
2358 add_param_to_list(&bond
[ftype
], param
);
2362 /* This is essentially the same check as in default_cmap_params() done one more time */
2363 auto message
= gmx::formatString("Unable to assign a cmap type to torsion %d %d %d %d and %d\n",
2364 param
.ai()+1, param
.aj()+1, param
.ak()+1, param
.al()+1, param
.am()+1);
2365 warning_error_and_exit(wi
, message
, FARGS
);
2371 void push_vsitesn(Directive d
, gmx::ArrayRef
<InteractionsOfType
> bond
,
2372 t_atoms
*at
, char *line
,
2376 int type
, ftype
, n
, ret
, nj
, a
;
2378 double *weight
= nullptr, weight_tot
;
2380 std::array
<real
, MAXFORCEPARAM
> forceParam
= {0.0};
2382 ret
= sscanf(ptr
, "%d%n", &a
, &n
);
2386 auto message
= gmx::formatString("Expected an atom index in section \"%s\"",
2388 warning_error_and_exit(wi
, message
, FARGS
);
2391 sscanf(ptr
, "%d%n", &type
, &n
);
2393 ftype
= ifunc_index(d
, type
);
2394 int firstAtom
= a
- 1;
2400 ret
= sscanf(ptr
, "%d%n", &a
, &n
);
2407 srenew(weight
, nj
+20);
2416 /* Here we use the A-state mass as a parameter.
2417 * Note that the B-state mass has no influence.
2419 weight
[nj
] = at
->atom
[atc
[nj
]].m
;
2423 ret
= sscanf(ptr
, "%lf%n", &(weight
[nj
]), &n
);
2427 auto message
= gmx::formatString
2428 ("No weight or negative weight found for vsiten "
2429 "constructing atom %d (atom index %d)",
2431 warning_error_and_exit(wi
, message
, FARGS
);
2435 auto message
= gmx::formatString("Unknown vsiten type %d", type
);
2436 warning_error_and_exit(wi
, message
, FARGS
);
2438 weight_tot
+= weight
[nj
];
2446 auto message
= gmx::formatString("Expected more than one atom index in section \"%s\"",
2448 warning_error_and_exit(wi
, message
, FARGS
);
2451 if (weight_tot
== 0)
2453 warning_error_and_exit(wi
, "The total mass of the construting atoms is zero", FARGS
);
2456 for (int j
= 0; j
< nj
; j
++)
2458 std::vector
<int> atoms
= {firstAtom
, atc
[j
]};
2460 forceParam
[1] = weight
[j
]/weight_tot
;
2461 /* Put the values in the appropriate arrays */
2462 add_param_to_list (&bond
[ftype
], InteractionOfType(atoms
, forceParam
));
2469 void push_mol(gmx::ArrayRef
<MoleculeInformation
> mols
, char *pline
, int *whichmol
,
2475 if (sscanf(pline
, "%s%d", type
, nrcopies
) != 2)
2481 /* Search moleculename.
2482 * Here we originally only did case insensitive matching. But because
2483 * some PDB files can have many chains and use case to generate more
2484 * chain-identifiers, which in turn end up in our moleculetype name,
2485 * we added support for case-sensitivity.
2492 for (const auto &mol
: mols
)
2494 if (strcmp(type
, *(mol
.name
)) == 0)
2499 if (gmx_strcasecmp(type
, *(mol
.name
)) == 0)
2509 // select the case sensitive match
2510 *whichmol
= matchcs
;
2514 // avoid matching case-insensitive when we have multiple matches
2517 auto message
= gmx::formatString
2518 ("For moleculetype '%s' in [ system ] %d case insensitive "
2519 "matches, but %d case sensitive matches were found. Check "
2520 "the case of the characters in the moleculetypes.",
2522 warning_error_and_exit(wi
, message
, FARGS
);
2526 // select the unique case insensitive match
2527 *whichmol
= matchci
;
2531 auto message
= gmx::formatString("No such moleculetype %s", type
);
2532 warning_error_and_exit(wi
, message
, FARGS
);
2537 void push_excl(char *line
, gmx::ArrayRef
<gmx::ExclusionBlock
> b2
, warninp
*wi
)
2541 char base
[STRLEN
], format
[STRLEN
];
2543 if (sscanf(line
, "%d", &i
) == 0)
2548 if ((1 <= i
) && (i
<= b2
.ssize()))
2556 strcpy(base
, "%*d");
2559 strcpy(format
, base
);
2560 strcat(format
, "%d");
2561 n
= sscanf(line
, format
, &j
);
2564 if ((1 <= j
) && (j
<= b2
.ssize()))
2567 b2
[i
].atomNumber
.push_back(j
);
2568 /* also add the reverse exclusion! */
2569 b2
[j
].atomNumber
.push_back(i
);
2570 strcat(base
, "%*d");
2574 auto message
= gmx::formatString("Invalid Atomnr j: %d, b2->nr: %zu\n", j
, b2
.size());
2575 warning_error_and_exit(wi
, message
, FARGS
);
2582 int add_atomtype_decoupled(t_symtab
*symtab
, PreprocessingAtomTypes
*at
,
2583 t_nbparam
***nbparam
, t_nbparam
***pair
)
2588 /* Define an atom type with all parameters set to zero (no interactions) */
2591 /* Type for decoupled atoms could be anything,
2592 * this should be changed automatically later when required.
2594 atom
.ptype
= eptAtom
;
2596 std::array
<real
, MAXFORCEPARAM
> forceParam
= {0.0};
2597 nr
= at
->addType(symtab
, atom
, "decoupled", InteractionOfType({}, forceParam
, ""), -1, 0);
2599 /* Add space in the non-bonded parameters matrix */
2600 realloc_nb_params(at
, nbparam
, pair
);
2605 static void convert_pairs_to_pairsQ(gmx::ArrayRef
<InteractionsOfType
> interactions
,
2606 real fudgeQQ
, t_atoms
*atoms
)
2608 /* Add the pair list to the pairQ list */
2609 std::vector
<InteractionOfType
> paramnew
;
2611 gmx::ArrayRef
<const InteractionOfType
> paramp1
= interactions
[F_LJ14
].interactionTypes
;
2612 gmx::ArrayRef
<const InteractionOfType
> paramp2
= interactions
[F_LJC14_Q
].interactionTypes
;
2614 /* Fill in the new F_LJC14_Q array with the old one. NOTE:
2615 it may be possible to just ADD the converted F_LJ14 array
2616 to the old F_LJC14_Q array, but since we have to create
2617 a new sized memory structure, better just to deep copy it all.
2621 for (const auto ¶m
: paramp2
)
2623 paramnew
.emplace_back(param
);
2626 for (const auto ¶m
: paramp1
)
2628 std::vector
<real
> forceParam
= {
2629 fudgeQQ
, atoms
->atom
[param
.ai()].q
, atoms
->atom
[param
.aj()].q
,
2630 param
.c0(), param
.c1()
2632 paramnew
.emplace_back(InteractionOfType(param
.atoms(), forceParam
, ""));
2635 /* now assign the new data to the F_LJC14_Q structure */
2636 interactions
[F_LJC14_Q
].interactionTypes
= paramnew
;
2638 /* Empty the LJ14 pairlist */
2639 interactions
[F_LJ14
].interactionTypes
.clear();
2642 static void generate_LJCpairsNB(MoleculeInformation
*mol
, int nb_funct
, InteractionsOfType
*nbp
, warninp
*wi
)
2650 atom
= mol
->atoms
.atom
;
2652 ntype
= static_cast<int>(std::sqrt(static_cast<double>(nbp
->size())));
2653 GMX_ASSERT(ntype
* ntype
== gmx::ssize(*nbp
), "Number of pairs of generated non-bonded parameters should be a perfect square");
2655 /* Add a pair interaction for all non-excluded atom pairs */
2657 for (int i
= 0; i
< n
; i
++)
2659 for (int j
= i
+1; j
< n
; j
++)
2662 for (int k
= excl
->index
[i
]; k
< excl
->index
[i
+1]; k
++)
2664 if (excl
->a
[k
] == j
)
2671 if (nb_funct
!= F_LJ
)
2673 auto message
= gmx::formatString
2674 ("Can only generate non-bonded pair interactions "
2675 "for Van der Waals type Lennard-Jones");
2676 warning_error_and_exit(wi
, message
, FARGS
);
2678 std::vector
<int> atoms
= {i
, j
};
2679 std::vector
<real
> forceParam
= {
2682 nbp
->interactionTypes
[ntype
*atom
[i
].type
+atom
[j
].type
].c0(),
2683 nbp
->interactionTypes
[ntype
*atom
[i
].type
+atom
[j
].type
].c1()
2685 add_param_to_list(&mol
->interactions
[F_LJC_PAIRS_NB
], InteractionOfType(atoms
, forceParam
));
2691 static void set_excl_all(t_blocka
*excl
)
2695 /* Get rid of the current exclusions and exclude all atom pairs */
2697 excl
->nra
= nat
*nat
;
2698 srenew(excl
->a
, excl
->nra
);
2700 for (i
= 0; i
< nat
; i
++)
2703 for (j
= 0; j
< nat
; j
++)
2708 excl
->index
[nat
] = k
;
2711 static void decouple_atoms(t_atoms
*atoms
, int atomtype_decouple
,
2712 int couple_lam0
, int couple_lam1
,
2713 const char *mol_name
, warninp
*wi
)
2717 for (i
= 0; i
< atoms
->nr
; i
++)
2721 atom
= &atoms
->atom
[i
];
2723 if (atom
->qB
!= atom
->q
|| atom
->typeB
!= atom
->type
)
2725 auto message
= gmx::formatString
2726 ("Atom %d in molecule type '%s' has different A and B state "
2727 "charges and/or atom types set in the topology file as well "
2728 "as through the mdp option '%s'. You can not use both "
2729 "these methods simultaneously.",
2730 i
+ 1, mol_name
, "couple-moltype");
2731 warning_error_and_exit(wi
, message
, FARGS
);
2734 if (couple_lam0
== ecouplamNONE
|| couple_lam0
== ecouplamVDW
)
2738 if (couple_lam0
== ecouplamNONE
|| couple_lam0
== ecouplamQ
)
2740 atom
->type
= atomtype_decouple
;
2742 if (couple_lam1
== ecouplamNONE
|| couple_lam1
== ecouplamVDW
)
2746 if (couple_lam1
== ecouplamNONE
|| couple_lam1
== ecouplamQ
)
2748 atom
->typeB
= atomtype_decouple
;
2753 void convert_moltype_couple(MoleculeInformation
*mol
, int atomtype_decouple
, real fudgeQQ
,
2754 int couple_lam0
, int couple_lam1
,
2755 bool bCoupleIntra
, int nb_funct
, InteractionsOfType
*nbp
,
2758 convert_pairs_to_pairsQ(mol
->interactions
, fudgeQQ
, &mol
->atoms
);
2761 generate_LJCpairsNB(mol
, nb_funct
, nbp
, wi
);
2762 set_excl_all(&mol
->excls
);
2764 decouple_atoms(&mol
->atoms
, atomtype_decouple
, couple_lam0
, couple_lam1
,