2 * This file is part of the GROMACS molecular simulation package.
4 * Copyright (c) 2021, by the GROMACS development team, led by
5 * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
6 * and including many others, as listed in the AUTHORS file in the
7 * top-level source directory and at http://www.gromacs.org.
9 * GROMACS is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public License
11 * as published by the Free Software Foundation; either version 2.1
12 * of the License, or (at your option) any later version.
14 * GROMACS is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with GROMACS; if not, see
21 * http://www.gnu.org/licenses, or write to the Free Software Foundation,
22 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
24 * If you want to redistribute modifications to GROMACS, please
25 * consider that scientific software is very special. Version
26 * control is crucial - bugs must be traceable. We will be happy to
27 * consider code for inclusion in the official distribution, but
28 * derived work must not be called official GROMACS. Details are found
29 * in the README & COPYING files - if they are missing, get the
30 * official version at http://www.gromacs.org.
32 * To help us fund GROMACS development, we humbly ask that you cite
33 * the research papers on the package. Check out http://www.gromacs.org.
38 * \brief Defines a function that makes the list of links between
39 * atoms connected by bonded interactions.
41 * \author Berk Hess <hess@kth.se>
42 * \ingroup module_domdec
47 #include "gromacs/domdec/makebondedlinks.h"
49 #include "gromacs/domdec/domdec_internal.h"
50 #include "gromacs/domdec/options.h"
51 #include "gromacs/domdec/reversetopology.h"
52 #include "gromacs/mdtypes/atominfo.h"
53 #include "gromacs/utility/fatalerror.h"
54 #include "gromacs/utility/smalloc.h"
55 #include "gromacs/topology/block.h"
56 #include "gromacs/topology/mtop_util.h"
59 using gmx::DDBondedChecking;
61 /*! \brief Check if a link is stored in \p link between charge groups \p cg_gl and \p cg_gl_j and if not so, store a link */
62 static void check_link(t_blocka* link, int cg_gl, int cg_gl_j)
65 for (int k = link->index[cg_gl]; k < link->index[cg_gl + 1]; k++)
67 GMX_RELEASE_ASSERT(link->a, "Inconsistent NULL pointer while making charge-group links");
68 if (link->a[k] == cg_gl_j)
75 GMX_RELEASE_ASSERT(link->a || link->index[cg_gl + 1] + 1 > link->nalloc_a,
76 "Inconsistent allocation of link");
77 /* Add this charge group link */
78 if (link->index[cg_gl + 1] + 1 > link->nalloc_a)
80 link->nalloc_a = over_alloc_large(link->index[cg_gl + 1] + 1);
81 srenew(link->a, link->nalloc_a);
83 link->a[link->index[cg_gl + 1]] = cg_gl_j;
84 link->index[cg_gl + 1]++;
88 void makeBondedLinks(gmx_domdec_t* dd,
89 const gmx_mtop_t& mtop,
90 gmx::ArrayRef<gmx::AtomInfoWithinMoleculeBlock> atomInfoForEachMoleculeBlock)
93 if (!dd->comm->systemInfo.filterBondedCommunication)
95 /* Only communicate atoms based on cut-off */
96 dd->comm->bondedLinks = nullptr;
100 t_blocka* link = nullptr;
102 /* For each atom make a list of other atoms in the system
103 * that a linked to it via bonded interactions
104 * which are also stored in reverse_top.
107 reverse_ilist_t ril_intermol;
108 if (mtop.bIntermolecularInteractions)
112 atoms.nr = mtop.natoms;
113 atoms.atom = nullptr;
115 GMX_RELEASE_ASSERT(mtop.intermolecular_ilist,
116 "We should have an ilist when intermolecular interactions are on");
118 ReverseTopOptions rtOptions(DDBondedChecking::ExcludeZeroLimit);
120 *mtop.intermolecular_ilist, &atoms, rtOptions, AtomLinkRule::AllAtomsInBondeds, &ril_intermol);
124 snew(link->index, mtop.natoms + 1);
129 int indexOfFirstAtomInMolecule = 0;
130 int numLinkedAtoms = 0;
131 for (size_t mb = 0; mb < mtop.molblock.size(); mb++)
133 const gmx_molblock_t& molb = mtop.molblock[mb];
138 const gmx_moltype_t& molt = mtop.moltype[molb.type];
139 /* Make a reverse ilist in which the interactions are linked
140 * to all atoms, not only the first atom as in gmx_reverse_top.
141 * The constraints are discarded here.
143 ReverseTopOptions rtOptions(DDBondedChecking::ExcludeZeroLimit);
145 make_reverse_ilist(molt.ilist, &molt.atoms, rtOptions, AtomLinkRule::AllAtomsInBondeds, &ril);
147 gmx::AtomInfoWithinMoleculeBlock* atomInfoOfMoleculeBlock = &atomInfoForEachMoleculeBlock[mb];
150 for (mol = 0; mol < (mtop.bIntermolecularInteractions ? molb.nmol : 1); mol++)
152 for (int a = 0; a < molt.atoms.nr; a++)
154 int atomIndex = indexOfFirstAtomInMolecule + a;
155 link->index[atomIndex + 1] = link->index[atomIndex];
156 int i = ril.index[a];
157 while (i < ril.index[a + 1])
159 int ftype = ril.il[i++];
160 int nral = NRAL(ftype);
161 /* Skip the ifunc index */
163 for (int j = 0; j < nral; j++)
165 int aj = ril.il[i + j];
168 check_link(link, atomIndex, indexOfFirstAtomInMolecule + aj);
174 if (mtop.bIntermolecularInteractions)
176 int i = ril_intermol.index[atomIndex];
177 while (i < ril_intermol.index[atomIndex + 1])
179 int ftype = ril_intermol.il[i++];
180 int nral = NRAL(ftype);
181 /* Skip the ifunc index */
183 for (int j = 0; j < nral; j++)
185 /* Here we assume we have no charge groups;
186 * this has been checked above.
188 int aj = ril_intermol.il[i + j];
189 check_link(link, atomIndex, aj);
194 if (link->index[atomIndex + 1] - link->index[atomIndex] > 0)
196 atomInfoOfMoleculeBlock->atomInfo[a] |= gmx::sc_atomInfo_BondCommunication;
201 indexOfFirstAtomInMolecule += molt.atoms.nr;
203 int nlink_mol = link->index[indexOfFirstAtomInMolecule]
204 - link->index[indexOfFirstAtomInMolecule - molt.atoms.nr];
209 "molecule type '%s' %d atoms has %d atom links through bonded interac.\n",
217 /* Copy the data for the rest of the molecules in this block */
218 link->nalloc_a += (molb.nmol - mol) * nlink_mol;
219 srenew(link->a, link->nalloc_a);
220 for (; mol < molb.nmol; mol++)
222 for (int a = 0; a < molt.atoms.nr; a++)
224 int atomIndex = indexOfFirstAtomInMolecule + a;
225 link->index[atomIndex + 1] = link->index[atomIndex + 1 - molt.atoms.nr] + nlink_mol;
226 for (int j = link->index[atomIndex]; j < link->index[atomIndex + 1]; j++)
228 link->a[j] = link->a[j - nlink_mol] + molt.atoms.nr;
230 if (link->index[atomIndex + 1] - link->index[atomIndex] > 0
231 && atomIndex - atomInfoOfMoleculeBlock->indexOfFirstAtomInMoleculeBlock
232 < gmx::ssize(atomInfoOfMoleculeBlock->atomInfo))
234 atomInfoOfMoleculeBlock->atomInfo[atomIndex - atomInfoOfMoleculeBlock->indexOfFirstAtomInMoleculeBlock] |=
235 gmx::sc_atomInfo_BondCommunication;
239 indexOfFirstAtomInMolecule += molt.atoms.nr;
246 fprintf(debug, "Of the %d atoms %d are linked via bonded interactions\n", mtop.natoms, numLinkedAtoms);
249 dd->comm->bondedLinks = link;