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.
52 #include <unordered_set>
54 #include <sys/types.h>
56 #include "gromacs/fileio/gmxfio.h"
57 #include "gromacs/fileio/warninp.h"
58 #include "gromacs/gmxpreprocess/gmxcpp.h"
59 #include "gromacs/gmxpreprocess/gpp_atomtype.h"
60 #include "gromacs/gmxpreprocess/gpp_bond_atomtype.h"
61 #include "gromacs/gmxpreprocess/gpp_nextnb.h"
62 #include "gromacs/gmxpreprocess/grompp_impl.h"
63 #include "gromacs/gmxpreprocess/readir.h"
64 #include "gromacs/gmxpreprocess/topdirs.h"
65 #include "gromacs/gmxpreprocess/toppush.h"
66 #include "gromacs/gmxpreprocess/topshake.h"
67 #include "gromacs/gmxpreprocess/toputil.h"
68 #include "gromacs/gmxpreprocess/vsite_parm.h"
69 #include "gromacs/math/units.h"
70 #include "gromacs/math/utilities.h"
71 #include "gromacs/mdtypes/inputrec.h"
72 #include "gromacs/mdtypes/md_enums.h"
73 #include "gromacs/pbcutil/pbc.h"
74 #include "gromacs/topology/block.h"
75 #include "gromacs/topology/exclusionblocks.h"
76 #include "gromacs/topology/ifunc.h"
77 #include "gromacs/topology/symtab.h"
78 #include "gromacs/topology/topology.h"
79 #include "gromacs/utility/cstringutil.h"
80 #include "gromacs/utility/fatalerror.h"
81 #include "gromacs/utility/futil.h"
82 #include "gromacs/utility/gmxassert.h"
83 #include "gromacs/utility/logger.h"
84 #include "gromacs/utility/pleasecite.h"
85 #include "gromacs/utility/smalloc.h"
87 #define OPENDIR '[' /* starting sign for directive */
88 #define CLOSEDIR ']' /* ending sign for directive */
90 static void gen_pairs(const InteractionsOfType
& nbs
, InteractionsOfType
* pairs
, real fudge
, int comb
)
94 int nnn
= static_cast<int>(std::sqrt(static_cast<double>(ntp
)));
95 GMX_ASSERT(nnn
* nnn
== ntp
,
96 "Number of pairs of generated non-bonded parameters should be a perfect square");
97 int nrfp
= NRFP(F_LJ
);
98 int nrfpA
= interaction_function
[F_LJ14
].nrfpA
;
99 int nrfpB
= interaction_function
[F_LJ14
].nrfpB
;
101 if ((nrfp
!= nrfpA
) || (nrfpA
!= nrfpB
))
103 gmx_incons("Number of force parameters in gen_pairs wrong");
106 fprintf(stderr
, "Generating 1-4 interactions: fudge = %g\n", fudge
);
107 pairs
->interactionTypes
.clear();
109 std::array
<int, 2> atomNumbers
;
110 std::array
<real
, MAXFORCEPARAM
> forceParam
= { NOTSET
};
111 for (const auto& type
: nbs
.interactionTypes
)
113 /* Copy type.atoms */
114 atomNumbers
= { i
/ nnn
, i
% nnn
};
115 /* Copy normal and FEP parameters and multiply by fudge factor */
116 gmx::ArrayRef
<const real
> existingParam
= type
.forceParam();
117 GMX_RELEASE_ASSERT(2 * nrfp
<= MAXFORCEPARAM
,
118 "Can't have more parameters than half of maximum p arameter number");
119 for (int j
= 0; j
< nrfp
; j
++)
121 /* If we are using sigma/epsilon values, only the epsilon values
122 * should be scaled, but not sigma.
123 * The sigma values have even indices 0,2, etc.
125 if ((comb
== eCOMB_ARITHMETIC
|| comb
== eCOMB_GEOM_SIG_EPS
) && (j
% 2 == 0))
134 forceParam
[j
] = scaling
* existingParam
[j
];
135 forceParam
[nrfp
+ j
] = scaling
* existingParam
[j
];
137 pairs
->interactionTypes
.emplace_back(InteractionOfType(atomNumbers
, forceParam
));
142 double check_mol(const gmx_mtop_t
* mtop
, warninp
* wi
)
149 /* Check mass and charge */
152 for (const gmx_molblock_t
& molb
: mtop
->molblock
)
154 const t_atoms
* atoms
= &mtop
->moltype
[molb
.type
].atoms
;
155 for (i
= 0; (i
< atoms
->nr
); i
++)
157 q
+= molb
.nmol
* atoms
->atom
[i
].q
;
158 m
= atoms
->atom
[i
].m
;
159 mB
= atoms
->atom
[i
].mB
;
160 pt
= atoms
->atom
[i
].ptype
;
161 /* If the particle is an atom or a nucleus it must have a mass,
162 * else, if it is a shell, a vsite or a bondshell it can have mass zero
164 if (((m
<= 0.0) || (mB
<= 0.0)) && ((pt
== eptAtom
) || (pt
== eptNucleus
)))
166 ri
= atoms
->atom
[i
].resind
;
167 sprintf(buf
, "atom %s (Res %s-%d) has mass %g (state A) / %g (state B)\n",
168 *(atoms
->atomname
[i
]), *(atoms
->resinfo
[ri
].name
), atoms
->resinfo
[ri
].nr
, m
, mB
);
169 warning_error(wi
, buf
);
171 else if (((m
!= 0) || (mB
!= 0)) && (pt
== eptVSite
))
173 ri
= atoms
->atom
[i
].resind
;
175 "virtual site %s (Res %s-%d) has non-zero mass %g (state A) / %g (state "
177 " Check your topology.\n",
178 *(atoms
->atomname
[i
]), *(atoms
->resinfo
[ri
].name
), atoms
->resinfo
[ri
].nr
, m
, mB
);
179 warning_error(wi
, buf
);
180 /* The following statements make LINCS break! */
181 /* atoms->atom[i].m=0; */
188 /*! \brief Returns the rounded charge of a molecule, when close to integer, otherwise returns the original charge.
190 * The results of this routine are only used for checking and for
191 * printing warning messages. Thus we can assume that charges of molecules
192 * should be integer. If the user wanted non-integer molecular charge,
193 * an undesired warning is printed and the user should use grompp -maxwarn 1.
195 * \param qMol The total, unrounded, charge of the molecule
196 * \param sumAbsQ The sum of absolute values of the charges, used for determining the tolerance for the rounding.
198 static double roundedMoleculeCharge(double qMol
, double sumAbsQ
)
200 /* We use a tolerance of 1e-6 for inaccuracies beyond the 6th decimal
201 * of the charges for ascii float truncation in the topology files.
202 * Although the summation here uses double precision, the charges
203 * are read and stored in single precision when real=float. This can
204 * lead to rounding errors of half the least significant bit.
205 * Note that, unfortunately, we can not assume addition of random
206 * rounding errors. It is not entirely unlikely that many charges
207 * have a near half-bit rounding error with the same sign.
209 double tolAbs
= 1e-6;
210 double tol
= std::max(tolAbs
, 0.5 * GMX_REAL_EPS
* sumAbsQ
);
211 double qRound
= std::round(qMol
);
212 if (std::abs(qMol
- qRound
) <= tol
)
222 static void sum_q(const t_atoms
* atoms
, int numMols
, double* qTotA
, double* qTotB
)
229 for (int i
= 0; i
< atoms
->nr
; i
++)
231 qmolA
+= atoms
->atom
[i
].q
;
232 qmolB
+= atoms
->atom
[i
].qB
;
233 sumAbsQA
+= std::abs(atoms
->atom
[i
].q
);
234 sumAbsQB
+= std::abs(atoms
->atom
[i
].qB
);
237 *qTotA
+= numMols
* roundedMoleculeCharge(qmolA
, sumAbsQA
);
238 *qTotB
+= numMols
* roundedMoleculeCharge(qmolB
, sumAbsQB
);
241 static void get_nbparm(char* nb_str
, char* comb_str
, int* nb
, int* comb
, warninp
* wi
)
244 char warn_buf
[STRLEN
];
247 for (i
= 1; (i
< eNBF_NR
); i
++)
249 if (gmx_strcasecmp(nb_str
, enbf_names
[i
]) == 0)
256 *nb
= strtol(nb_str
, nullptr, 10);
258 if ((*nb
< 1) || (*nb
>= eNBF_NR
))
260 sprintf(warn_buf
, "Invalid nonbond function selector '%s' using %s", nb_str
, enbf_names
[1]);
261 warning_error(wi
, warn_buf
);
265 for (i
= 1; (i
< eCOMB_NR
); i
++)
267 if (gmx_strcasecmp(comb_str
, ecomb_names
[i
]) == 0)
274 *comb
= strtol(comb_str
, nullptr, 10);
276 if ((*comb
< 1) || (*comb
>= eCOMB_NR
))
278 sprintf(warn_buf
, "Invalid combination rule selector '%s' using %s", comb_str
, ecomb_names
[1]);
279 warning_error(wi
, warn_buf
);
284 static char** cpp_opts(const char* define
, const char* include
, warninp
* wi
)
288 const char* cppadds
[2];
289 char** cppopts
= nullptr;
290 const char* option
[2] = { "-D", "-I" };
291 const char* nopt
[2] = { "define", "include" };
295 char warn_buf
[STRLEN
];
298 cppadds
[1] = include
;
299 for (n
= 0; (n
< 2); n
++)
306 while ((*ptr
!= '\0') && isspace(*ptr
))
311 while ((*rptr
!= '\0') && !isspace(*rptr
))
318 snew(buf
, (len
+ 1));
319 strncpy(buf
, ptr
, len
);
320 if (strstr(ptr
, option
[n
]) != ptr
)
322 set_warning_line(wi
, "mdp file", -1);
323 sprintf(warn_buf
, "Malformed %s option %s", nopt
[n
], buf
);
324 warning(wi
, warn_buf
);
328 srenew(cppopts
, ++ncppopts
);
329 cppopts
[ncppopts
- 1] = gmx_strdup(buf
);
337 srenew(cppopts
, ++ncppopts
);
338 cppopts
[ncppopts
- 1] = nullptr;
344 static void make_atoms_sys(gmx::ArrayRef
<const gmx_molblock_t
> molblock
,
345 gmx::ArrayRef
<const MoleculeInformation
> molinfo
,
349 atoms
->atom
= nullptr;
351 for (const gmx_molblock_t
& molb
: molblock
)
353 const t_atoms
& mol_atoms
= molinfo
[molb
.type
].atoms
;
355 srenew(atoms
->atom
, atoms
->nr
+ molb
.nmol
* mol_atoms
.nr
);
357 for (int m
= 0; m
< molb
.nmol
; m
++)
359 for (int a
= 0; a
< mol_atoms
.nr
; a
++)
361 atoms
->atom
[atoms
->nr
++] = mol_atoms
.atom
[a
];
368 static char** read_topol(const char* infile
,
373 PreprocessingAtomTypes
* atypes
,
374 std::vector
<MoleculeInformation
>* molinfo
,
375 std::unique_ptr
<MoleculeInformation
>* intermolecular_interactions
,
376 gmx::ArrayRef
<InteractionsOfType
> interactions
,
377 int* combination_rule
,
381 std::vector
<gmx_molblock_t
>* molblock
,
382 bool* ffParametrizedWithHBondConstraints
,
385 bool usingFullRangeElectrostatics
,
387 const gmx::MDLogger
& logger
)
391 char * pline
= nullptr, **title
= nullptr;
392 char line
[STRLEN
], errbuf
[256], comb_str
[256], nb_str
[256];
394 char * dirstr
, *dummy2
;
395 int nrcopies
, nscan
, ncombs
, ncopy
;
396 double fLJ
, fQQ
, fPOW
;
397 MoleculeInformation
* mi0
= nullptr;
400 t_nbparam
** nbparam
, **pair
;
401 real fudgeLJ
= -1; /* Multiplication factor to generate 1-4 from LJ */
402 bool bReadDefaults
, bReadMolType
, bGenPairs
, bWarn_copy_A_B
;
403 double qt
= 0, qBt
= 0; /* total charge */
404 int dcatt
= -1, nmol_couple
;
405 /* File handling variables */
409 char* tmp_line
= nullptr;
410 char warn_buf
[STRLEN
];
411 const char* floating_point_arithmetic_tip
=
412 "Total charge should normally be an integer. See\n"
413 "http://www.gromacs.org/Documentation/Floating_Point_Arithmetic\n"
414 "for discussion on how close it should be to an integer.\n";
415 /* We need to open the output file before opening the input file,
416 * because cpp_open_file can change the current working directory.
420 out
= gmx_fio_fopen(outfile
, "w");
427 /* open input file */
428 auto cpp_opts_return
= cpp_opts(define
, include
, wi
);
429 status
= cpp_open_file(infile
, &handle
, cpp_opts_return
);
432 gmx_fatal(FARGS
, "%s", cpp_error(&handle
, status
));
435 /* some local variables */
436 DS_Init(&DS
); /* directive stack */
437 d
= Directive::d_invalid
; /* first thing should be a directive */
438 nbparam
= nullptr; /* The temporary non-bonded matrix */
439 pair
= nullptr; /* The temporary pair interaction matrix */
440 std::vector
<std::vector
<gmx::ExclusionBlock
>> exclusionBlocks
;
443 *reppow
= 12.0; /* Default value for repulsion power */
445 /* Init the number of CMAP torsion angles and grid spacing */
446 interactions
[F_CMAP
].cmakeGridSpacing
= 0;
447 interactions
[F_CMAP
].cmapAngles
= 0;
449 bWarn_copy_A_B
= bFEP
;
451 PreprocessingBondAtomType bondAtomType
;
452 /* parse the actual file */
453 bReadDefaults
= FALSE
;
455 bReadMolType
= FALSE
;
460 status
= cpp_read_line(&handle
, STRLEN
, line
);
461 done
= (status
== eCPP_EOF
);
464 if (status
!= eCPP_OK
)
466 gmx_fatal(FARGS
, "%s", cpp_error(&handle
, status
));
470 fprintf(out
, "%s\n", line
);
473 set_warning_line(wi
, cpp_cur_file(&handle
), cpp_cur_linenr(&handle
));
475 pline
= gmx_strdup(line
);
477 /* Strip trailing '\' from pline, if it exists */
479 if ((sl
> 0) && (pline
[sl
- 1] == CONTINUE
))
484 /* build one long line from several fragments - necessary for CMAP */
485 while (continuing(line
))
487 status
= cpp_read_line(&handle
, STRLEN
, line
);
488 set_warning_line(wi
, cpp_cur_file(&handle
), cpp_cur_linenr(&handle
));
490 /* Since we depend on the '\' being present to continue to read, we copy line
491 * to a tmp string, strip the '\' from that string, and cat it to pline
493 tmp_line
= gmx_strdup(line
);
495 sl
= strlen(tmp_line
);
496 if ((sl
> 0) && (tmp_line
[sl
- 1] == CONTINUE
))
498 tmp_line
[sl
- 1] = ' ';
501 done
= (status
== eCPP_EOF
);
504 if (status
!= eCPP_OK
)
506 gmx_fatal(FARGS
, "%s", cpp_error(&handle
, status
));
510 fprintf(out
, "%s\n", line
);
514 srenew(pline
, strlen(pline
) + strlen(tmp_line
) + 1);
515 strcat(pline
, tmp_line
);
519 /* skip trailing and leading spaces and comment text */
520 strip_comment(pline
);
523 /* if there is something left... */
524 if (static_cast<int>(strlen(pline
)) > 0)
526 if (pline
[0] == OPENDIR
)
528 /* A directive on this line: copy the directive
529 * without the brackets into dirstr, then
530 * skip spaces and tabs on either side of directive
532 dirstr
= gmx_strdup((pline
+ 1));
533 if ((dummy2
= strchr(dirstr
, CLOSEDIR
)) != nullptr)
539 if ((newd
= str2dir(dirstr
)) == Directive::d_invalid
)
541 sprintf(errbuf
, "Invalid directive %s", dirstr
);
542 warning_error(wi
, errbuf
);
546 /* Directive found */
547 if (DS_Check_Order(DS
, newd
))
554 /* we should print here which directives should have
555 been present, and which actually are */
556 gmx_fatal(FARGS
, "%s\nInvalid order for directive %s",
557 cpp_error(&handle
, eCPP_SYNTAX
), dir2str(newd
));
558 /* d = Directive::d_invalid; */
561 if (d
== Directive::d_intermolecular_interactions
)
563 if (*intermolecular_interactions
== nullptr)
565 /* We (mis)use the moleculetype processing
566 * to process the intermolecular interactions
567 * by making a "molecule" of the size of the system.
569 *intermolecular_interactions
= std::make_unique
<MoleculeInformation
>();
570 mi0
= intermolecular_interactions
->get();
572 make_atoms_sys(*molblock
, *molinfo
, &mi0
->atoms
);
578 else if (d
!= Directive::d_invalid
)
580 /* Not a directive, just a plain string
581 * use a gigantic switch to decode,
582 * if there is a valid directive!
586 case Directive::d_defaults
:
589 gmx_fatal(FARGS
, "%s\nFound a second defaults directive.\n",
590 cpp_error(&handle
, eCPP_SYNTAX
));
592 bReadDefaults
= TRUE
;
593 nscan
= sscanf(pline
, "%s%s%s%lf%lf%lf", nb_str
, comb_str
, genpairs
,
605 get_nbparm(nb_str
, comb_str
, &nb_funct
, combination_rule
, wi
);
608 bGenPairs
= (gmx::equalCaseInsensitive(genpairs
, "Y", 1));
609 if (nb_funct
!= eNBF_LJ
&& bGenPairs
)
612 "Generating pair parameters is only supported "
613 "with LJ non-bonded interactions");
629 nb_funct
= ifunc_index(Directive::d_nonbond_params
, nb_funct
);
632 case Directive::d_atomtypes
:
633 push_at(symtab
, atypes
, &bondAtomType
, pline
, nb_funct
, &nbparam
,
634 bGenPairs
? &pair
: nullptr, wi
);
637 case Directive::d_bondtypes
: // Intended to fall through
638 case Directive::d_constrainttypes
:
639 push_bt(d
, interactions
, 2, nullptr, &bondAtomType
, pline
, wi
);
641 case Directive::d_pairtypes
:
644 push_nbt(d
, pair
, atypes
, pline
, F_LJ14
, wi
);
648 push_bt(d
, interactions
, 2, atypes
, nullptr, pline
, wi
);
651 case Directive::d_angletypes
:
652 push_bt(d
, interactions
, 3, nullptr, &bondAtomType
, pline
, wi
);
654 case Directive::d_dihedraltypes
:
655 /* Special routine that can read both 2 and 4 atom dihedral definitions. */
656 push_dihedraltype(d
, interactions
, &bondAtomType
, pline
, wi
);
659 case Directive::d_nonbond_params
:
660 push_nbt(d
, nbparam
, atypes
, pline
, nb_funct
, wi
);
663 case Directive::d_implicit_genborn_params
: // NOLINT bugprone-branch-clone
664 // Skip this line, so old topologies with
665 // GB parameters can be read.
668 case Directive::d_implicit_surface_params
:
669 // Skip this line, so that any topologies
670 // with surface parameters can be read
671 // (even though these were never formally
675 case Directive::d_cmaptypes
:
676 push_cmaptype(d
, interactions
, 5, atypes
, &bondAtomType
, pline
, wi
);
679 case Directive::d_moleculetype
:
684 if (opts
->couple_moltype
!= nullptr
685 && (opts
->couple_lam0
== ecouplamNONE
|| opts
->couple_lam0
== ecouplamQ
686 || opts
->couple_lam1
== ecouplamNONE
687 || opts
->couple_lam1
== ecouplamQ
))
689 dcatt
= add_atomtype_decoupled(symtab
, atypes
, &nbparam
,
690 bGenPairs
? &pair
: nullptr);
692 ntype
= atypes
->size();
693 ncombs
= (ntype
* (ntype
+ 1)) / 2;
694 generate_nbparams(*combination_rule
, nb_funct
,
695 &(interactions
[nb_funct
]), atypes
, wi
);
696 ncopy
= copy_nbparams(nbparam
, nb_funct
, &(interactions
[nb_funct
]), ntype
);
699 .appendTextFormatted(
700 "Generated %d of the %d non-bonded parameter "
702 ncombs
- ncopy
, ncombs
);
703 free_nbparam(nbparam
, ntype
);
706 gen_pairs((interactions
[nb_funct
]), &(interactions
[F_LJ14
]),
707 fudgeLJ
, *combination_rule
);
708 ncopy
= copy_nbparams(pair
, nb_funct
, &(interactions
[F_LJ14
]), ntype
);
711 .appendTextFormatted(
712 "Generated %d of the %d 1-4 parameter "
714 ncombs
- ncopy
, ncombs
);
715 free_nbparam(pair
, ntype
);
717 /* Copy GBSA parameters to atomtype array? */
722 push_molt(symtab
, molinfo
, pline
, wi
);
723 exclusionBlocks
.emplace_back();
724 mi0
= &molinfo
->back();
725 mi0
->atoms
.haveMass
= TRUE
;
726 mi0
->atoms
.haveCharge
= TRUE
;
727 mi0
->atoms
.haveType
= TRUE
;
728 mi0
->atoms
.haveBState
= TRUE
;
729 mi0
->atoms
.havePdbInfo
= FALSE
;
732 case Directive::d_atoms
:
733 push_atom(symtab
, &(mi0
->atoms
), atypes
, pline
, wi
);
736 case Directive::d_pairs
:
739 "Need to have a valid MoleculeInformation object to work on");
740 push_bond(d
, interactions
, mi0
->interactions
, &(mi0
->atoms
), atypes
,
741 pline
, FALSE
, bGenPairs
, *fudgeQQ
, bZero
, &bWarn_copy_A_B
, wi
);
743 case Directive::d_pairs_nb
:
746 "Need to have a valid MoleculeInformation object to work on");
747 push_bond(d
, interactions
, mi0
->interactions
, &(mi0
->atoms
), atypes
,
748 pline
, FALSE
, FALSE
, 1.0, bZero
, &bWarn_copy_A_B
, wi
);
751 case Directive::d_vsites2
:
752 case Directive::d_vsites3
:
753 case Directive::d_vsites4
:
754 case Directive::d_bonds
:
755 case Directive::d_angles
:
756 case Directive::d_constraints
:
757 case Directive::d_settles
:
758 case Directive::d_position_restraints
:
759 case Directive::d_angle_restraints
:
760 case Directive::d_angle_restraints_z
:
761 case Directive::d_distance_restraints
:
762 case Directive::d_orientation_restraints
:
763 case Directive::d_dihedral_restraints
:
764 case Directive::d_dihedrals
:
765 case Directive::d_polarization
:
766 case Directive::d_water_polarization
:
767 case Directive::d_thole_polarization
:
770 "Need to have a valid MoleculeInformation object to work on");
771 push_bond(d
, interactions
, mi0
->interactions
, &(mi0
->atoms
), atypes
,
772 pline
, TRUE
, bGenPairs
, *fudgeQQ
, bZero
, &bWarn_copy_A_B
, wi
);
774 case Directive::d_cmap
:
777 "Need to have a valid MoleculeInformation object to work on");
778 push_cmap(d
, interactions
, mi0
->interactions
, &(mi0
->atoms
), atypes
, pline
, wi
);
781 case Directive::d_vsitesn
:
784 "Need to have a valid MoleculeInformation object to work on");
785 push_vsitesn(d
, mi0
->interactions
, &(mi0
->atoms
), pline
, wi
);
787 case Directive::d_exclusions
:
788 GMX_ASSERT(!exclusionBlocks
.empty(),
789 "exclusionBlocks must always be allocated so exclusions can "
791 if (exclusionBlocks
.back().empty())
793 GMX_RELEASE_ASSERT(mi0
,
794 "Need to have a valid MoleculeInformation "
795 "object to work on");
796 exclusionBlocks
.back().resize(mi0
->atoms
.nr
);
798 push_excl(pline
, exclusionBlocks
.back(), wi
);
800 case Directive::d_system
:
802 title
= put_symtab(symtab
, pline
);
804 case Directive::d_molecules
:
809 push_mol(*molinfo
, pline
, &whichmol
, &nrcopies
, wi
);
810 mi0
= &((*molinfo
)[whichmol
]);
811 molblock
->resize(molblock
->size() + 1);
812 molblock
->back().type
= whichmol
;
813 molblock
->back().nmol
= nrcopies
;
815 bCouple
= (opts
->couple_moltype
!= nullptr
816 && (gmx_strcasecmp("system", opts
->couple_moltype
) == 0
817 || strcmp(*(mi0
->name
), opts
->couple_moltype
) == 0));
820 nmol_couple
+= nrcopies
;
823 if (mi0
->atoms
.nr
== 0)
825 gmx_fatal(FARGS
, "Molecule type '%s' contains no atoms", *mi0
->name
);
829 .appendTextFormatted(
830 "Excluding %d bonded neighbours molecule type '%s'",
831 mi0
->nrexcl
, *mi0
->name
);
832 sum_q(&mi0
->atoms
, nrcopies
, &qt
, &qBt
);
833 if (!mi0
->bProcessed
)
835 generate_excl(mi0
->nrexcl
, mi0
->atoms
.nr
, mi0
->interactions
, &(mi0
->excls
));
836 gmx::mergeExclusions(&(mi0
->excls
), exclusionBlocks
[whichmol
]);
837 make_shake(mi0
->interactions
, &mi0
->atoms
, opts
->nshake
, logger
);
841 convert_moltype_couple(mi0
, dcatt
, *fudgeQQ
, opts
->couple_lam0
,
842 opts
->couple_lam1
, opts
->bCoupleIntra
,
843 nb_funct
, &(interactions
[nb_funct
]), wi
);
845 stupid_fill_block(&mi0
->mols
, mi0
->atoms
.nr
, TRUE
);
846 mi0
->bProcessed
= TRUE
;
851 GMX_LOG(logger
.warning
)
853 .appendTextFormatted("case: %d", static_cast<int>(d
));
854 gmx_incons("unknown directive");
863 // Check that all strings defined with -D were used when processing topology
864 std::string unusedDefineWarning
= checkAndWarnForUnusedDefines(*handle
);
865 if (!unusedDefineWarning
.empty())
867 warning(wi
, unusedDefineWarning
);
870 sfree(cpp_opts_return
);
877 /* List of GROMACS define names for force fields that have been
878 * parametrized using constraints involving hydrogens only.
880 * We should avoid hardcoded names, but this is hopefully only
881 * needed temparorily for discouraging use of constraints=all-bonds.
883 const std::array
<std::string
, 3> ffDefines
= { "_FF_AMBER", "_FF_CHARMM", "_FF_OPLSAA" };
884 *ffParametrizedWithHBondConstraints
= false;
885 for (const std::string
& ffDefine
: ffDefines
)
887 if (cpp_find_define(&handle
, ffDefine
))
889 *ffParametrizedWithHBondConstraints
= true;
893 if (cpp_find_define(&handle
, "_FF_GROMOS96") != nullptr)
896 "The GROMOS force fields have been parametrized with a physically incorrect "
897 "multiple-time-stepping scheme for a twin-range cut-off. When used with "
898 "a single-range cut-off (or a correct Trotter multiple-time-stepping scheme), "
899 "physical properties, such as the density, might differ from the intended values. "
900 "Since there are researchers actively working on validating GROMOS with modern "
901 "integrators we have not yet removed the GROMOS force fields, but you should be "
902 "aware of these issues and check if molecules in your system are affected before "
904 "Further information is available at https://redmine.gromacs.org/issues/2884 , "
905 "and a longer explanation of our decision to remove physically incorrect "
907 "can be found at https://doi.org/10.26434/chemrxiv.11474583.v1 .");
909 // TODO: Update URL for Issue #2884 in conjunction with updating grompp.warn in regressiontests.
913 if (opts
->couple_moltype
)
915 if (nmol_couple
== 0)
917 gmx_fatal(FARGS
, "Did not find any molecules of type '%s' for coupling", opts
->couple_moltype
);
921 .appendTextFormatted("Coupling %d copies of molecule type '%s'", nmol_couple
,
922 opts
->couple_moltype
);
925 /* this is not very clean, but fixes core dump on empty system name */
928 title
= put_symtab(symtab
, "");
933 sprintf(warn_buf
, "System has non-zero total charge: %.6f\n%s\n", qt
, floating_point_arithmetic_tip
);
934 warning_note(wi
, warn_buf
);
936 if (fabs(qBt
) > 1e-4 && !gmx_within_tol(qBt
, qt
, 1e-6))
938 sprintf(warn_buf
, "State B has non-zero total charge: %.6f\n%s\n", qBt
,
939 floating_point_arithmetic_tip
);
940 warning_note(wi
, warn_buf
);
942 if (usingFullRangeElectrostatics
&& (fabs(qt
) > 1e-4 || fabs(qBt
) > 1e-4))
945 "You are using Ewald electrostatics in a system with net charge. This can lead to "
946 "severe artifacts, such as ions moving into regions with low dielectric, due to "
947 "the uniform background charge. We suggest to neutralize your system with counter "
948 "ions, possibly in combination with a physiological salt concentration.");
949 please_cite(stdout
, "Hub2014a");
954 if (*intermolecular_interactions
!= nullptr)
956 sfree(intermolecular_interactions
->get()->atoms
.atom
);
962 char** do_top(bool bVerbose
,
964 const char* topppfile
,
968 gmx::ArrayRef
<InteractionsOfType
> interactions
,
969 int* combination_rule
,
970 double* repulsion_power
,
972 PreprocessingAtomTypes
* atypes
,
973 std::vector
<MoleculeInformation
>* molinfo
,
974 std::unique_ptr
<MoleculeInformation
>* intermolecular_interactions
,
975 const t_inputrec
* ir
,
976 std::vector
<gmx_molblock_t
>* molblock
,
977 bool* ffParametrizedWithHBondConstraints
,
979 const gmx::MDLogger
& logger
)
981 /* Tmpfile might contain a long path */
996 GMX_LOG(logger
.info
).asParagraph().appendTextFormatted("processing topology...");
998 title
= read_topol(topfile
, tmpfile
, opts
->define
, opts
->include
, symtab
, atypes
, molinfo
,
999 intermolecular_interactions
, interactions
, combination_rule
, repulsion_power
,
1000 opts
, fudgeQQ
, molblock
, ffParametrizedWithHBondConstraints
,
1001 ir
->efep
!= efepNO
, bZero
, EEL_FULL(ir
->coulombtype
), wi
, logger
);
1003 if ((*combination_rule
!= eCOMB_GEOMETRIC
) && (ir
->vdwtype
== evdwUSER
))
1006 "Using sigma/epsilon based combination rules with"
1007 " user supplied potential function may produce unwanted"
1015 * Exclude molecular interactions for QM atoms handled by MiMic.
1017 * Update the exclusion lists to include all QM atoms of this molecule,
1018 * replace bonds between QM atoms with CONNBOND and
1019 * set charges of QM atoms to 0.
1021 * \param[in,out] molt molecule type with QM atoms
1022 * \param[in] grpnr group informatio
1023 * \param[in,out] ir input record
1024 * \param[in] logger Handle to logging interface.
1026 static void generate_qmexcl_moltype(gmx_moltype_t
* molt
,
1027 const unsigned char* grpnr
,
1029 const gmx::MDLogger
& logger
)
1031 /* This routine expects molt->ilist to be of size F_NRE and ordered. */
1033 /* generates the exclusions between the individual QM atoms, as
1034 * these interactions should be handled by the QM subroutines and
1035 * not by the gromacs routines
1037 int qm_max
= 0, qm_nr
= 0, link_nr
= 0;
1038 int * qm_arr
= nullptr, *link_arr
= nullptr;
1041 /* First we search and select the QM atoms in an qm_arr array that
1042 * we use to create the exclusions.
1044 * we take the possibility into account that a user has defined more
1045 * than one QM group:
1047 * for that we also need to do this an ugly work-about just in case
1048 * the QM group contains the entire system...
1051 /* we first search for all the QM atoms and put them in an array
1053 for (int j
= 0; j
< ir
->opts
.ngQM
; j
++)
1055 for (int i
= 0; i
< molt
->atoms
.nr
; i
++)
1057 if (qm_nr
>= qm_max
)
1060 srenew(qm_arr
, qm_max
);
1062 if ((grpnr
? grpnr
[i
] : 0) == j
)
1064 qm_arr
[qm_nr
++] = i
;
1065 molt
->atoms
.atom
[i
].q
= 0.0;
1066 molt
->atoms
.atom
[i
].qB
= 0.0;
1070 /* bQMMM[..] is an array containin TRUE/FALSE for atoms that are
1071 * QM/not QM. We first set all elements to false. Afterwards we use
1072 * the qm_arr to change the elements corresponding to the QM atoms
1075 snew(bQMMM
, molt
->atoms
.nr
);
1076 for (int i
= 0; i
< molt
->atoms
.nr
; i
++)
1080 for (int i
= 0; i
< qm_nr
; i
++)
1082 bQMMM
[qm_arr
[i
]] = TRUE
;
1085 /* We remove all bonded interactions (i.e. bonds,
1086 * angles, dihedrals, 1-4's), involving the QM atoms. The way they
1087 * are removed is as follows: if the interaction invloves 2 atoms,
1088 * it is removed if both atoms are QMatoms. If it involves 3 atoms,
1089 * it is removed if at least two of the atoms are QM atoms, if the
1090 * interaction involves 4 atoms, it is removed if there are at least
1091 * 2 QM atoms. Since this routine is called once before any forces
1092 * are computed, the top->idef.il[N].iatom[] array (see idef.h) can
1093 * be rewritten at this poitn without any problem. 25-9-2002 */
1095 /* first check whether we already have CONNBONDS.
1096 * Note that if we don't, we don't add a param entry and set ftype=0,
1097 * which is ok, since CONNBONDS does not use parameters.
1099 int ftype_connbond
= 0;
1100 int ind_connbond
= 0;
1101 if (!molt
->ilist
[F_CONNBONDS
].empty())
1103 GMX_LOG(logger
.info
)
1105 .appendTextFormatted("nr. of CONNBONDS present already: %d",
1106 molt
->ilist
[F_CONNBONDS
].size() / 3);
1107 ftype_connbond
= molt
->ilist
[F_CONNBONDS
].iatoms
[0];
1108 ind_connbond
= molt
->ilist
[F_CONNBONDS
].size();
1110 /* now we delete all bonded interactions, except the ones describing
1111 * a chemical bond. These are converted to CONNBONDS
1113 for (int ftype
= 0; ftype
< F_NRE
; ftype
++)
1115 if (!(interaction_function
[ftype
].flags
& IF_BOND
) || ftype
== F_CONNBONDS
)
1119 int nratoms
= interaction_function
[ftype
].nratoms
;
1121 while (j
< molt
->ilist
[ftype
].size())
1127 /* Remove an interaction between two atoms when both are
1128 * in the QM region. Note that we don't have to worry about
1129 * link atoms here, as they won't have 2-atom interactions.
1131 int a1
= molt
->ilist
[ftype
].iatoms
[1 + j
+ 0];
1132 int a2
= molt
->ilist
[ftype
].iatoms
[1 + j
+ 1];
1133 bexcl
= (bQMMM
[a1
] && bQMMM
[a2
]);
1134 /* A chemical bond between two QM atoms will be copied to
1135 * the F_CONNBONDS list, for reasons mentioned above.
1137 if (bexcl
&& IS_CHEMBOND(ftype
))
1139 InteractionList
& ilist
= molt
->ilist
[F_CONNBONDS
];
1140 ilist
.iatoms
.resize(ind_connbond
+ 3);
1141 ilist
.iatoms
[ind_connbond
++] = ftype_connbond
;
1142 ilist
.iatoms
[ind_connbond
++] = a1
;
1143 ilist
.iatoms
[ind_connbond
++] = a2
;
1148 /* MM interactions have to be excluded if they are included
1149 * in the QM already. Because we use a link atom (H atom)
1150 * when the QM/MM boundary runs through a chemical bond, this
1151 * means that as long as one atom is MM, we still exclude,
1152 * as the interaction is included in the QM via:
1153 * QMatom1-QMatom2-QMatom-3-Linkatom.
1156 for (int jj
= j
+ 1; jj
< j
+ 1 + nratoms
; jj
++)
1158 if (bQMMM
[molt
->ilist
[ftype
].iatoms
[jj
]])
1164 /* MiMiC treats link atoms as quantum atoms - therefore
1165 * we do not need do additional exclusions here */
1166 bexcl
= numQmAtoms
== nratoms
;
1168 if (bexcl
&& ftype
== F_SETTLE
)
1171 "Can not apply QM to molecules with SETTLE, replace the moleculetype "
1172 "using QM and SETTLE by one without SETTLE");
1177 /* since the interaction involves QM atoms, these should be
1178 * removed from the MM ilist
1180 InteractionList
& ilist
= molt
->ilist
[ftype
];
1181 for (int k
= j
; k
< ilist
.size() - (nratoms
+ 1); k
++)
1183 ilist
.iatoms
[k
] = ilist
.iatoms
[k
+ (nratoms
+ 1)];
1185 ilist
.iatoms
.resize(ilist
.size() - (nratoms
+ 1));
1189 j
+= nratoms
+ 1; /* the +1 is for the functype */
1193 /* Now, we search for atoms bonded to a QM atom because we also want
1194 * to exclude their nonbonded interactions with the QM atoms. The
1195 * reason for this is that this interaction is accounted for in the
1196 * linkatoms interaction with the QMatoms and would be counted
1199 /* creating the exclusion block for the QM atoms. Each QM atom has
1200 * as excluded elements all the other QMatoms (and itself).
1203 qmexcl
.nr
= molt
->atoms
.nr
;
1204 qmexcl
.nra
= qm_nr
* (qm_nr
+ link_nr
) + link_nr
* qm_nr
;
1205 snew(qmexcl
.index
, qmexcl
.nr
+ 1);
1206 snew(qmexcl
.a
, qmexcl
.nra
);
1208 for (int i
= 0; i
< qmexcl
.nr
; i
++)
1210 qmexcl
.index
[i
] = j
;
1213 for (int k
= 0; k
< qm_nr
; k
++)
1215 qmexcl
.a
[k
+ j
] = qm_arr
[k
];
1217 for (int k
= 0; k
< link_nr
; k
++)
1219 qmexcl
.a
[qm_nr
+ k
+ j
] = link_arr
[k
];
1221 j
+= (qm_nr
+ link_nr
);
1224 qmexcl
.index
[qmexcl
.nr
] = j
;
1226 /* and merging with the exclusions already present in sys.
1229 std::vector
<gmx::ExclusionBlock
> qmexcl2(molt
->atoms
.nr
);
1230 gmx::blockaToExclusionBlocks(&qmexcl
, qmexcl2
);
1231 gmx::mergeExclusions(&(molt
->excls
), qmexcl2
);
1233 /* Finally, we also need to get rid of the pair interactions of the
1234 * classical atom bonded to the boundary QM atoms with the QMatoms,
1235 * as this interaction is already accounted for by the QM, so also
1236 * here we run the risk of double counting! We proceed in a similar
1237 * way as we did above for the other bonded interactions: */
1238 for (int i
= F_LJ14
; i
< F_COUL14
; i
++)
1240 int nratoms
= interaction_function
[i
].nratoms
;
1242 while (j
< molt
->ilist
[i
].size())
1244 int a1
= molt
->ilist
[i
].iatoms
[j
+ 1];
1245 int a2
= molt
->ilist
[i
].iatoms
[j
+ 2];
1246 bool bexcl
= (bQMMM
[a1
] && bQMMM
[a2
]);
1249 /* since the interaction involves QM atoms, these should be
1250 * removed from the MM ilist
1252 InteractionList
& ilist
= molt
->ilist
[i
];
1253 for (int k
= j
; k
< ilist
.size() - (nratoms
+ 1); k
++)
1255 ilist
.iatoms
[k
] = ilist
.iatoms
[k
+ (nratoms
+ 1)];
1257 ilist
.iatoms
.resize(ilist
.size() - (nratoms
+ 1));
1261 j
+= nratoms
+ 1; /* the +1 is for the functype */
1269 } /* generate_qmexcl */
1271 void generate_qmexcl(gmx_mtop_t
* sys
, t_inputrec
* ir
, const gmx::MDLogger
& logger
)
1273 /* This routine expects molt->molt[m].ilist to be of size F_NRE and ordered.
1276 unsigned char* grpnr
;
1277 int mol
, nat_mol
, nr_mol_with_qm_atoms
= 0;
1278 gmx_molblock_t
* molb
;
1280 int index_offset
= 0;
1283 grpnr
= sys
->groups
.groupNumbers
[SimulationAtomGroupType::QuantumMechanics
].data();
1285 for (size_t mb
= 0; mb
< sys
->molblock
.size(); mb
++)
1287 molb
= &sys
->molblock
[mb
];
1288 nat_mol
= sys
->moltype
[molb
->type
].atoms
.nr
;
1289 for (mol
= 0; mol
< molb
->nmol
; mol
++)
1292 for (int i
= 0; i
< nat_mol
; i
++)
1294 if ((grpnr
? grpnr
[i
] : 0) < (ir
->opts
.ngQM
))
1303 nr_mol_with_qm_atoms
++;
1306 /* We need to split this molblock */
1309 /* Split the molblock at this molecule */
1310 auto pos
= sys
->molblock
.begin() + mb
+ 1;
1311 sys
->molblock
.insert(pos
, sys
->molblock
[mb
]);
1312 sys
->molblock
[mb
].nmol
= mol
;
1313 sys
->molblock
[mb
+ 1].nmol
-= mol
;
1315 molb
= &sys
->molblock
[mb
];
1319 /* Split the molblock after this molecule */
1320 auto pos
= sys
->molblock
.begin() + mb
+ 1;
1321 sys
->molblock
.insert(pos
, sys
->molblock
[mb
]);
1322 molb
= &sys
->molblock
[mb
];
1323 sys
->molblock
[mb
].nmol
= 1;
1324 sys
->molblock
[mb
+ 1].nmol
-= 1;
1327 /* Create a copy of a moltype for a molecule
1328 * containing QM atoms and append it in the end of the list
1330 std::vector
<gmx_moltype_t
> temp(sys
->moltype
.size());
1331 for (size_t i
= 0; i
< sys
->moltype
.size(); ++i
)
1333 copy_moltype(&sys
->moltype
[i
], &temp
[i
]);
1335 sys
->moltype
.resize(sys
->moltype
.size() + 1);
1336 for (size_t i
= 0; i
< temp
.size(); ++i
)
1338 copy_moltype(&temp
[i
], &sys
->moltype
[i
]);
1340 copy_moltype(&sys
->moltype
[molb
->type
], &sys
->moltype
.back());
1341 /* Copy the exclusions to a new array, since this is the only
1342 * thing that needs to be modified for QMMM.
1344 sys
->moltype
.back().excls
= sys
->moltype
[molb
->type
].excls
;
1345 /* Set the molecule type for the QMMM molblock */
1346 molb
->type
= sys
->moltype
.size() - 1;
1348 generate_qmexcl_moltype(&sys
->moltype
[molb
->type
], grpnr
, ir
, logger
);
1354 index_offset
+= nat_mol
;