2 * This file is part of the GROMACS molecular simulation package.
4 * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
5 * Copyright (c) 2001-2004, The GROMACS development team.
6 * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
7 * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
8 * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
9 * and including many others, as listed in the AUTHORS file in the
10 * top-level source directory and at http://www.gromacs.org.
12 * GROMACS is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU Lesser General Public License
14 * as published by the Free Software Foundation; either version 2.1
15 * of the License, or (at your option) any later version.
17 * GROMACS is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * Lesser General Public License for more details.
22 * You should have received a copy of the GNU Lesser General Public
23 * License along with GROMACS; if not, see
24 * http://www.gnu.org/licenses, or write to the Free Software Foundation,
25 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
27 * If you want to redistribute modifications to GROMACS, please
28 * consider that scientific software is very special. Version
29 * control is crucial - bugs must be traceable. We will be happy to
30 * consider code for inclusion in the official distribution, but
31 * derived work must not be called official GROMACS. Details are found
32 * in the README & COPYING files - if they are missing, get the
33 * official version at http://www.gromacs.org.
35 * To help us fund GROMACS development, we humbly ask that you cite
36 * the research papers on the package. Check out http://www.gromacs.org.
38 /* This file is completely threadsafe - keep it that way! */
49 #include "gromacs/gmxpreprocess/gpp_atomtype.h"
50 #include "gromacs/gmxpreprocess/grompp_impl.h"
51 #include "gromacs/gmxpreprocess/topio.h"
52 #include "gromacs/gmxpreprocess/toputil.h"
53 #include "gromacs/math/functions.h"
54 #include "gromacs/math/units.h"
55 #include "gromacs/math/utilities.h"
56 #include "gromacs/math/vec.h"
57 #include "gromacs/mdtypes/md_enums.h"
58 #include "gromacs/topology/ifunc.h"
59 #include "gromacs/topology/topology.h"
60 #include "gromacs/utility/fatalerror.h"
61 #include "gromacs/utility/smalloc.h"
63 static int round_check(real r
, int limit
, int ftype
, const char* name
)
65 const int i
= gmx::roundToInt(r
);
67 if (r
- i
> 0.01 || r
- i
< -0.01)
69 gmx_fatal(FARGS
, "A non-integer value (%f) was supplied for '%s' in %s", r
, name
,
70 interaction_function
[ftype
].longname
);
75 gmx_fatal(FARGS
, "Value of '%s' in %s is %d, which is smaller than the minimum of %d", name
,
76 interaction_function
[ftype
].longname
, i
, limit
);
82 static void set_ljparams(int comb
, double reppow
, double v
, double w
, real
* c6
, real
* c12
)
84 if (comb
== eCOMB_ARITHMETIC
|| comb
== eCOMB_GEOM_SIG_EPS
)
88 *c6
= 4 * w
* gmx::power6(v
);
89 *c12
= 4 * w
* std::pow(v
, reppow
);
93 /* Interpret negative sigma as c6=0 and c12 with -sigma */
95 *c12
= 4 * w
* std::pow(-v
, reppow
);
105 /* A return value of 0 means parameters were assigned successfully,
106 * returning -1 means this is an all-zero interaction that should not be added.
108 static int assign_param(t_functype ftype
, t_iparams
* newparam
, gmx::ArrayRef
<const real
> old
, int comb
, double reppow
)
110 bool all_param_zero
= true;
113 for (int j
= 0; (j
< MAXFORCEPARAM
); j
++)
115 newparam
->generic
.buf
[j
] = 0.0;
116 /* If all parameters are zero we might not add some interaction types (selected below).
117 * We cannot apply this to ALL interactions, since many have valid reasons for having
118 * zero parameters (e.g. an index to a Cmap interaction, or LJ parameters), but
119 * we use it for angles and torsions that are typically generated automatically.
121 all_param_zero
= all_param_zero
&& fabs(old
[j
]) < GMX_REAL_MIN
;
126 if (IS_ANGLE(ftype
) || IS_RESTRAINT_TYPE(ftype
) || ftype
== F_IDIHS
|| ftype
== F_PDIHS
127 || ftype
== F_PIDIHS
|| ftype
== F_RBDIHS
|| ftype
== F_FOURDIHS
)
136 /* Post processing of input data: store cosine iso angle itself */
137 newparam
->harmonic
.rA
= cos(old
[0] * DEG2RAD
);
138 newparam
->harmonic
.krA
= old
[1];
139 newparam
->harmonic
.rB
= cos(old
[2] * DEG2RAD
);
140 newparam
->harmonic
.krB
= old
[3];
143 /* Post processing of input data: store square of length itself */
144 newparam
->harmonic
.rA
= gmx::square(old
[0]);
145 newparam
->harmonic
.krA
= old
[1];
146 newparam
->harmonic
.rB
= gmx::square(old
[2]);
147 newparam
->harmonic
.krB
= old
[3];
150 newparam
->fene
.bm
= old
[0];
151 newparam
->fene
.kb
= old
[1];
154 newparam
->restraint
.lowA
= old
[0];
155 newparam
->restraint
.up1A
= old
[1];
156 newparam
->restraint
.up2A
= old
[2];
157 newparam
->restraint
.kA
= old
[3];
158 newparam
->restraint
.lowB
= old
[4];
159 newparam
->restraint
.up1B
= old
[5];
160 newparam
->restraint
.up2B
= old
[6];
161 newparam
->restraint
.kB
= old
[7];
167 newparam
->tab
.table
= round_check(old
[0], 0, ftype
, "table index");
168 newparam
->tab
.kA
= old
[1];
169 newparam
->tab
.kB
= old
[3];
171 case F_CROSS_BOND_BONDS
:
172 newparam
->cross_bb
.r1e
= old
[0];
173 newparam
->cross_bb
.r2e
= old
[1];
174 newparam
->cross_bb
.krr
= old
[2];
176 case F_CROSS_BOND_ANGLES
:
177 newparam
->cross_ba
.r1e
= old
[0];
178 newparam
->cross_ba
.r2e
= old
[1];
179 newparam
->cross_ba
.r3e
= old
[2];
180 newparam
->cross_ba
.krt
= old
[3];
183 newparam
->u_b
.thetaA
= old
[0];
184 newparam
->u_b
.kthetaA
= old
[1];
185 newparam
->u_b
.r13A
= old
[2];
186 newparam
->u_b
.kUBA
= old
[3];
187 newparam
->u_b
.thetaB
= old
[4];
188 newparam
->u_b
.kthetaB
= old
[5];
189 newparam
->u_b
.r13B
= old
[6];
190 newparam
->u_b
.kUBB
= old
[7];
192 case F_QUARTIC_ANGLES
:
193 newparam
->qangle
.theta
= old
[0];
194 for (int i
= 0; i
< 5; i
++)
196 newparam
->qangle
.c
[i
] = old
[i
+ 1];
199 case F_LINEAR_ANGLES
:
200 newparam
->linangle
.aA
= old
[0];
201 newparam
->linangle
.klinA
= old
[1];
202 newparam
->linangle
.aB
= old
[2];
203 newparam
->linangle
.klinB
= old
[3];
209 newparam
->harmonic
.rA
= old
[0];
210 newparam
->harmonic
.krA
= old
[1];
211 newparam
->harmonic
.rB
= old
[2];
212 newparam
->harmonic
.krB
= old
[3];
215 newparam
->harmonic
.rA
= old
[0];
216 newparam
->harmonic
.krA
= old
[1];
219 newparam
->morse
.b0A
= old
[0];
220 newparam
->morse
.cbA
= old
[1];
221 newparam
->morse
.betaA
= old
[2];
222 newparam
->morse
.b0B
= old
[3];
223 newparam
->morse
.cbB
= old
[4];
224 newparam
->morse
.betaB
= old
[5];
227 newparam
->cubic
.b0
= old
[0];
228 newparam
->cubic
.kb
= old
[1];
229 newparam
->cubic
.kcub
= old
[2];
231 case F_CONNBONDS
: break;
232 case F_POLARIZATION
: newparam
->polarize
.alpha
= old
[0]; break;
234 newparam
->anharm_polarize
.alpha
= old
[0];
235 newparam
->anharm_polarize
.drcut
= old
[1];
236 newparam
->anharm_polarize
.khyp
= old
[2];
239 newparam
->wpol
.al_x
= old
[0];
240 newparam
->wpol
.al_y
= old
[1];
241 newparam
->wpol
.al_z
= old
[2];
242 newparam
->wpol
.rOH
= old
[3];
243 newparam
->wpol
.rHH
= old
[4];
244 newparam
->wpol
.rOD
= old
[5];
247 newparam
->thole
.a
= old
[0];
248 newparam
->thole
.alpha1
= old
[1];
249 newparam
->thole
.alpha2
= old
[2];
250 if ((old
[1] > 0) && (old
[2] > 0))
252 newparam
->thole
.rfac
= old
[0] * gmx::invsixthroot(old
[1] * old
[2]);
256 newparam
->thole
.rfac
= 1;
260 newparam
->bham
.a
= old
[0];
261 newparam
->bham
.b
= old
[1];
262 newparam
->bham
.c
= old
[2];
265 set_ljparams(comb
, reppow
, old
[0], old
[1], &newparam
->lj14
.c6A
, &newparam
->lj14
.c12A
);
266 set_ljparams(comb
, reppow
, old
[2], old
[3], &newparam
->lj14
.c6B
, &newparam
->lj14
.c12B
);
269 newparam
->ljc14
.fqq
= old
[0];
270 newparam
->ljc14
.qi
= old
[1];
271 newparam
->ljc14
.qj
= old
[2];
272 set_ljparams(comb
, reppow
, old
[3], old
[4], &newparam
->ljc14
.c6
, &newparam
->ljc14
.c12
);
275 newparam
->ljcnb
.qi
= old
[0];
276 newparam
->ljcnb
.qj
= old
[1];
277 set_ljparams(comb
, reppow
, old
[2], old
[3], &newparam
->ljcnb
.c6
, &newparam
->ljcnb
.c12
);
280 set_ljparams(comb
, reppow
, old
[0], old
[1], &newparam
->lj
.c6
, &newparam
->lj
.c12
);
286 newparam
->pdihs
.phiA
= old
[0];
287 newparam
->pdihs
.cpA
= old
[1];
289 /* Change 20100720: Amber occasionally uses negative multiplicities (mathematically OK),
290 * so I have changed the lower limit to -99 /EL
292 newparam
->pdihs
.phiB
= old
[3];
293 newparam
->pdihs
.cpB
= old
[4];
294 /* If both force constants are zero there is no interaction. Return -1 to signal
295 * this entry should NOT be added.
297 if (fabs(newparam
->pdihs
.cpA
) < GMX_REAL_MIN
&& fabs(newparam
->pdihs
.cpB
) < GMX_REAL_MIN
)
302 newparam
->pdihs
.mult
= round_check(old
[2], -99, ftype
, "multiplicity");
306 newparam
->pdihs
.phiA
= old
[0];
307 newparam
->pdihs
.cpA
= old
[1];
310 newparam
->posres
.fcA
[XX
] = old
[0];
311 newparam
->posres
.fcA
[YY
] = old
[1];
312 newparam
->posres
.fcA
[ZZ
] = old
[2];
313 newparam
->posres
.fcB
[XX
] = old
[3];
314 newparam
->posres
.fcB
[YY
] = old
[4];
315 newparam
->posres
.fcB
[ZZ
] = old
[5];
316 newparam
->posres
.pos0A
[XX
] = old
[6];
317 newparam
->posres
.pos0A
[YY
] = old
[7];
318 newparam
->posres
.pos0A
[ZZ
] = old
[8];
319 newparam
->posres
.pos0B
[XX
] = old
[9];
320 newparam
->posres
.pos0B
[YY
] = old
[10];
321 newparam
->posres
.pos0B
[ZZ
] = old
[11];
324 newparam
->fbposres
.geom
= round_check(old
[0], 0, ftype
, "geometry");
325 if (!(newparam
->fbposres
.geom
> efbposresZERO
&& newparam
->fbposres
.geom
< efbposresNR
))
328 "Invalid geometry for flat-bottomed position restraint.\n"
329 "Expected number between 1 and %d. Found %d\n",
330 efbposresNR
- 1, newparam
->fbposres
.geom
);
332 newparam
->fbposres
.r
= old
[1];
333 newparam
->fbposres
.k
= old
[2];
334 newparam
->fbposres
.pos0
[XX
] = old
[3];
335 newparam
->fbposres
.pos0
[YY
] = old
[4];
336 newparam
->fbposres
.pos0
[ZZ
] = old
[5];
339 newparam
->disres
.label
= round_check(old
[0], 0, ftype
, "label");
340 newparam
->disres
.type
= round_check(old
[1], 1, ftype
, "type'");
341 newparam
->disres
.low
= old
[2];
342 newparam
->disres
.up1
= old
[3];
343 newparam
->disres
.up2
= old
[4];
344 newparam
->disres
.kfac
= old
[5];
347 newparam
->orires
.ex
= round_check(old
[0], 1, ftype
, "experiment") - 1;
348 newparam
->orires
.label
= round_check(old
[1], 1, ftype
, "label");
349 newparam
->orires
.power
= round_check(old
[2], 0, ftype
, "power");
350 newparam
->orires
.c
= old
[3];
351 newparam
->orires
.obs
= old
[4];
352 newparam
->orires
.kfac
= old
[5];
355 newparam
->dihres
.phiA
= old
[0];
356 newparam
->dihres
.dphiA
= old
[1];
357 newparam
->dihres
.kfacA
= old
[2];
358 newparam
->dihres
.phiB
= old
[3];
359 newparam
->dihres
.dphiB
= old
[4];
360 newparam
->dihres
.kfacB
= old
[5];
363 for (int i
= 0; (i
< NR_RBDIHS
); i
++)
365 newparam
->rbdihs
.rbcA
[i
] = old
[i
];
366 newparam
->rbdihs
.rbcB
[i
] = old
[NR_RBDIHS
+ i
];
370 for (int i
= 0; (i
< NR_CBTDIHS
); i
++)
372 newparam
->cbtdihs
.cbtcA
[i
] = old
[i
];
376 /* Read the dihedral parameters to temporary arrays,
377 * and convert them to the computationally faster
378 * Ryckaert-Bellemans form.
380 /* Use conversion formula for OPLS to Ryckaert-Bellemans: */
381 newparam
->rbdihs
.rbcA
[0] = old
[1] + 0.5 * (old
[0] + old
[2]);
382 newparam
->rbdihs
.rbcA
[1] = 0.5 * (3.0 * old
[2] - old
[0]);
383 newparam
->rbdihs
.rbcA
[2] = 4.0 * old
[3] - old
[1];
384 newparam
->rbdihs
.rbcA
[3] = -2.0 * old
[2];
385 newparam
->rbdihs
.rbcA
[4] = -4.0 * old
[3];
386 newparam
->rbdihs
.rbcA
[5] = 0.0;
388 newparam
->rbdihs
.rbcB
[0] =
389 old
[NR_FOURDIHS
+ 1] + 0.5 * (old
[NR_FOURDIHS
+ 0] + old
[NR_FOURDIHS
+ 2]);
390 newparam
->rbdihs
.rbcB
[1] = 0.5 * (3.0 * old
[NR_FOURDIHS
+ 2] - old
[NR_FOURDIHS
+ 0]);
391 newparam
->rbdihs
.rbcB
[2] = 4.0 * old
[NR_FOURDIHS
+ 3] - old
[NR_FOURDIHS
+ 1];
392 newparam
->rbdihs
.rbcB
[3] = -2.0 * old
[NR_FOURDIHS
+ 2];
393 newparam
->rbdihs
.rbcB
[4] = -4.0 * old
[NR_FOURDIHS
+ 3];
394 newparam
->rbdihs
.rbcB
[5] = 0.0;
398 newparam
->constr
.dA
= old
[0];
399 newparam
->constr
.dB
= old
[1];
402 newparam
->settle
.doh
= old
[0];
403 newparam
->settle
.dhh
= old
[1];
413 newparam
->vsite
.a
= old
[0];
414 newparam
->vsite
.b
= old
[1];
415 newparam
->vsite
.c
= old
[2];
416 newparam
->vsite
.d
= old
[3];
417 newparam
->vsite
.e
= old
[4];
418 newparam
->vsite
.f
= old
[5];
421 newparam
->vsite
.a
= old
[1] * cos(DEG2RAD
* old
[0]);
422 newparam
->vsite
.b
= old
[1] * sin(DEG2RAD
* old
[0]);
423 newparam
->vsite
.c
= old
[2];
424 newparam
->vsite
.d
= old
[3];
425 newparam
->vsite
.e
= old
[4];
426 newparam
->vsite
.f
= old
[5];
429 newparam
->vsiten
.n
= round_check(old
[0], 1, ftype
, "number of atoms");
430 newparam
->vsiten
.a
= old
[1];
433 newparam
->cmap
.cmapA
= static_cast<int>(old
[0]);
434 newparam
->cmap
.cmapB
= static_cast<int>(old
[1]);
436 case F_GB12_NOLONGERUSED
:
437 case F_GB13_NOLONGERUSED
:
438 case F_GB14_NOLONGERUSED
: break;
440 gmx_fatal(FARGS
, "unknown function type %d in %s line %d", ftype
, __FILE__
, __LINE__
);
445 static int enter_params(gmx_ffparams_t
* ffparams
,
447 gmx::ArrayRef
<const real
> forceparams
,
456 if ((rc
= assign_param(ftype
, &newparam
, forceparams
, comb
, reppow
)) < 0)
458 /* -1 means this interaction is all-zero and should not be added */
464 if (ftype
!= F_DISRES
)
466 for (int type
= start
; type
< ffparams
->numTypes(); type
++)
468 // Note that the first condition is always met by starting the loop at start
469 if (ffparams
->functype
[type
] == ftype
470 && memcmp(&newparam
, &ffparams
->iparams
[type
], static_cast<size_t>(sizeof(newparam
))) == 0)
478 // Distance restraints should have unique labels and pairs with the same label
479 // should be consecutive, so we here we only need to check the last type in the list.
480 // This changes the complexity from quadratic to linear in the number of restraints.
481 const int type
= ffparams
->numTypes() - 1;
482 if (type
>= 0 && ffparams
->functype
[type
] == ftype
483 && memcmp(&newparam
, &ffparams
->iparams
[type
], static_cast<size_t>(sizeof(newparam
))) == 0)
490 const int type
= ffparams
->numTypes();
492 ffparams
->iparams
.push_back(newparam
);
493 ffparams
->functype
.push_back(ftype
);
495 GMX_ASSERT(ffparams
->iparams
.size() == ffparams
->functype
.size(), "sizes should match");
500 static void append_interaction(InteractionList
* ilist
, int type
, gmx::ArrayRef
<const int> a
)
502 ilist
->iatoms
.push_back(type
);
503 for (const auto& atom
: a
)
505 ilist
->iatoms
.push_back(atom
);
509 static void enter_function(const InteractionsOfType
* p
,
513 gmx_ffparams_t
* ffparams
,
518 int start
= ffparams
->numTypes();
520 for (auto& parm
: p
->interactionTypes
)
522 int type
= enter_params(ffparams
, ftype
, parm
.forceParam(), comb
, reppow
, start
, bAppend
);
523 /* Type==-1 is used as a signal that this interaction is all-zero and should not be added. */
524 if (!bNB
&& type
>= 0)
526 GMX_RELEASE_ASSERT(il
, "Need valid interaction list");
527 GMX_RELEASE_ASSERT(parm
.atoms().ssize() == NRAL(ftype
),
528 "Need to have correct number of atoms for the parameter");
529 append_interaction(il
, type
, parm
.atoms());
534 void convertInteractionsOfType(int atnr
,
535 gmx::ArrayRef
<const InteractionsOfType
> nbtypes
,
536 gmx::ArrayRef
<const MoleculeInformation
> mi
,
537 const MoleculeInformation
* intermolecular_interactions
,
548 ffp
= &mtop
->ffparams
;
550 ffp
->functype
.clear();
551 ffp
->iparams
.clear();
552 ffp
->reppow
= reppow
;
554 enter_function(&(nbtypes
[F_LJ
]), static_cast<t_functype
>(F_LJ
), comb
, reppow
, ffp
, nullptr, TRUE
, TRUE
);
555 enter_function(&(nbtypes
[F_BHAM
]), static_cast<t_functype
>(F_BHAM
), comb
, reppow
, ffp
, nullptr,
558 for (size_t mt
= 0; mt
< mtop
->moltype
.size(); mt
++)
560 molt
= &mtop
->moltype
[mt
];
561 for (i
= 0; (i
< F_NRE
); i
++)
563 molt
->ilist
[i
].iatoms
.clear();
565 gmx::ArrayRef
<const InteractionsOfType
> interactions
= mi
[mt
].interactions
;
567 flags
= interaction_function
[i
].flags
;
568 if ((i
!= F_LJ
) && (i
!= F_BHAM
)
569 && ((flags
& IF_BOND
) || (flags
& IF_VSITE
) || (flags
& IF_CONSTRAINT
)))
571 enter_function(&(interactions
[i
]), static_cast<t_functype
>(i
), comb
, reppow
, ffp
,
572 &molt
->ilist
[i
], FALSE
, (i
== F_POSRES
|| i
== F_FBPOSRES
));
577 mtop
->bIntermolecularInteractions
= FALSE
;
578 if (intermolecular_interactions
!= nullptr)
580 /* Process the intermolecular interaction list */
581 mtop
->intermolecular_ilist
= std::make_unique
<InteractionLists
>();
583 for (i
= 0; (i
< F_NRE
); i
++)
585 (*mtop
->intermolecular_ilist
)[i
].iatoms
.clear();
587 gmx::ArrayRef
<const InteractionsOfType
> interactions
= intermolecular_interactions
->interactions
;
589 if (!interactions
[i
].interactionTypes
.empty())
591 flags
= interaction_function
[i
].flags
;
592 /* For intermolecular interactions we (currently)
593 * only support potentials.
594 * Constraints and virtual sites would be possible,
595 * but require a lot of extra (bug-prone) code.
597 if (!(flags
& IF_BOND
))
600 "The intermolecular_interaction section may only contain bonded "
603 else if (NRAL(i
) == 1) /* e.g. position restraints */
606 "Single atom interactions don't make sense in the "
607 "intermolecular_interaction section, you can put them in the "
608 "moleculetype section");
610 else if (flags
& IF_CHEMBOND
)
613 "The intermolecular_interaction can not contain chemically bonding "
618 enter_function(&(interactions
[i
]), static_cast<t_functype
>(i
), comb
, reppow
,
619 ffp
, &(*mtop
->intermolecular_ilist
)[i
], FALSE
, FALSE
);
621 mtop
->bIntermolecularInteractions
= TRUE
;
626 if (!mtop
->bIntermolecularInteractions
)
628 mtop
->intermolecular_ilist
.reset(nullptr);
632 ffp
->fudgeQQ
= fudgeQQ
;