2 * This file is part of the GROMACS molecular simulation package.
4 * Copyright (c) 2008,2009,2010,2012,2013,2014,2015,2016,2017,2018, 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.
37 #include "mtop_util.h"
45 #include "gromacs/math/vectypes.h"
46 #include "gromacs/topology/atoms.h"
47 #include "gromacs/topology/block.h"
48 #include "gromacs/topology/idef.h"
49 #include "gromacs/topology/ifunc.h"
50 #include "gromacs/topology/topology.h"
51 #include "gromacs/topology/topsort.h"
52 #include "gromacs/utility/arrayref.h"
53 #include "gromacs/utility/fatalerror.h"
54 #include "gromacs/utility/real.h"
55 #include "gromacs/utility/smalloc.h"
57 static int gmx_mtop_maxresnr(const gmx_mtop_t *mtop, int maxres_renum)
61 for (const gmx_moltype_t &moltype : mtop->moltype)
63 const t_atoms &atoms = moltype.atoms;
64 if (atoms.nres > maxres_renum)
66 for (int r = 0; r < atoms.nres; r++)
68 if (atoms.resinfo[r].nr > maxresnr)
70 maxresnr = atoms.resinfo[r].nr;
79 static void buildMolblockIndices(gmx_mtop_t *mtop)
81 mtop->moleculeBlockIndices.resize(mtop->molblock.size());
85 int residueNumberStart = mtop->maxresnr + 1;
86 int moleculeIndexStart = 0;
87 for (size_t mb = 0; mb < mtop->molblock.size(); mb++)
89 const gmx_molblock_t &molb = mtop->molblock[mb];
90 MoleculeBlockIndices &indices = mtop->moleculeBlockIndices[mb];
91 const int numResPerMol = mtop->moltype[molb.type].atoms.nres;
93 indices.numAtomsPerMolecule = mtop->moltype[molb.type].atoms.nr;
94 indices.globalAtomStart = atomIndex;
95 indices.globalResidueStart = residueIndex;
96 atomIndex += molb.nmol*indices.numAtomsPerMolecule;
97 residueIndex += molb.nmol*numResPerMol;
98 indices.globalAtomEnd = atomIndex;
99 indices.residueNumberStart = residueNumberStart;
100 if (numResPerMol <= mtop->maxres_renum)
102 residueNumberStart += molb.nmol*numResPerMol;
104 indices.moleculeIndexStart = moleculeIndexStart;
105 moleculeIndexStart += molb.nmol;
109 void gmx_mtop_finalize(gmx_mtop_t *mtop)
113 if (mtop->molblock.size() == 1 && mtop->molblock[0].nmol == 1)
115 /* We have a single molecule only, no renumbering needed.
116 * This case also covers an mtop converted from pdb/gro/... input,
117 * so we retain the original residue numbering.
119 mtop->maxres_renum = 0;
123 /* We only renumber single residue molecules. Their intra-molecular
124 * residue numbering is anyhow irrelevant.
126 mtop->maxres_renum = 1;
129 env = getenv("GMX_MAXRESRENUM");
132 sscanf(env, "%d", &mtop->maxres_renum);
134 if (mtop->maxres_renum == -1)
136 /* -1 signals renumber residues in all molecules */
137 mtop->maxres_renum = INT_MAX;
140 mtop->maxresnr = gmx_mtop_maxresnr(mtop, mtop->maxres_renum);
142 buildMolblockIndices(mtop);
145 void gmx_mtop_count_atomtypes(const gmx_mtop_t *mtop, int state, int typecount[])
147 for (int i = 0; i < mtop->ffparams.atnr; ++i)
151 for (const gmx_molblock_t &molb : mtop->molblock)
153 const t_atoms &atoms = mtop->moltype[molb.type].atoms;
154 for (int i = 0; i < atoms.nr; ++i)
159 tpi = atoms.atom[i].type;
163 tpi = atoms.atom[i].typeB;
165 typecount[tpi] += molb.nmol;
170 int ncg_mtop(const gmx_mtop_t *mtop)
173 for (const gmx_molblock_t &molb : mtop->molblock)
175 ncg += molb.nmol*mtop->moltype[molb.type].cgs.nr;
181 int gmx_mtop_num_molecules(const gmx_mtop_t &mtop)
183 int numMolecules = 0;
184 for (const gmx_molblock_t &molb : mtop.molblock)
186 numMolecules += molb.nmol;
191 int gmx_mtop_nres(const gmx_mtop_t *mtop)
194 for (const gmx_molblock_t &molb : mtop->molblock)
196 nres += molb.nmol*mtop->moltype[molb.type].atoms.nres;
201 void gmx_mtop_remove_chargegroups(gmx_mtop_t *mtop)
203 for (gmx_moltype_t &molt : mtop->moltype)
205 t_block &cgs = molt.cgs;
206 if (cgs.nr < molt.atoms.nr)
208 cgs.nr = molt.atoms.nr;
209 srenew(cgs.index, cgs.nr + 1);
210 for (int i = 0; i < cgs.nr + 1; i++)
218 typedef struct gmx_mtop_atomloop_all
220 const gmx_mtop_t *mtop;
222 const t_atoms *atoms;
227 } t_gmx_mtop_atomloop_all;
229 gmx_mtop_atomloop_all_t
230 gmx_mtop_atomloop_all_init(const gmx_mtop_t *mtop)
232 struct gmx_mtop_atomloop_all *aloop;
239 &mtop->moltype[mtop->molblock[aloop->mblock].type].atoms;
241 aloop->maxresnr = mtop->maxresnr;
242 aloop->at_local = -1;
243 aloop->at_global = -1;
248 static void gmx_mtop_atomloop_all_destroy(gmx_mtop_atomloop_all_t aloop)
253 gmx_bool gmx_mtop_atomloop_all_next(gmx_mtop_atomloop_all_t aloop,
254 int *at_global, const t_atom **atom)
256 if (aloop == nullptr)
258 gmx_incons("gmx_mtop_atomloop_all_next called without calling gmx_mtop_atomloop_all_init");
264 if (aloop->at_local >= aloop->atoms->nr)
266 if (aloop->atoms->nres <= aloop->mtop->maxres_renum)
268 /* Single residue molecule, increase the count with one */
269 aloop->maxresnr += aloop->atoms->nres;
273 if (aloop->mol >= aloop->mtop->molblock[aloop->mblock].nmol)
276 if (aloop->mblock >= aloop->mtop->molblock.size())
278 gmx_mtop_atomloop_all_destroy(aloop);
281 aloop->atoms = &aloop->mtop->moltype[aloop->mtop->molblock[aloop->mblock].type].atoms;
286 *at_global = aloop->at_global;
287 *atom = &aloop->atoms->atom[aloop->at_local];
292 void gmx_mtop_atomloop_all_names(gmx_mtop_atomloop_all_t aloop,
293 char **atomname, int *resnr, char **resname)
297 *atomname = *(aloop->atoms->atomname[aloop->at_local]);
298 resind_mol = aloop->atoms->atom[aloop->at_local].resind;
299 *resnr = aloop->atoms->resinfo[resind_mol].nr;
300 if (aloop->atoms->nres <= aloop->mtop->maxres_renum)
302 *resnr = aloop->maxresnr + 1 + resind_mol;
304 *resname = *(aloop->atoms->resinfo[resind_mol].name);
307 void gmx_mtop_atomloop_all_moltype(gmx_mtop_atomloop_all_t aloop,
308 const gmx_moltype_t **moltype,
311 *moltype = &aloop->mtop->moltype[aloop->mtop->molblock[aloop->mblock].type];
312 *at_mol = aloop->at_local;
315 typedef struct gmx_mtop_atomloop_block
317 const gmx_mtop_t *mtop;
319 const t_atoms *atoms;
321 } t_gmx_mtop_atomloop_block;
323 gmx_mtop_atomloop_block_t
324 gmx_mtop_atomloop_block_init(const gmx_mtop_t *mtop)
326 struct gmx_mtop_atomloop_block *aloop;
332 aloop->atoms = &mtop->moltype[mtop->molblock[aloop->mblock].type].atoms;
333 aloop->at_local = -1;
338 static void gmx_mtop_atomloop_block_destroy(gmx_mtop_atomloop_block_t aloop)
343 gmx_bool gmx_mtop_atomloop_block_next(gmx_mtop_atomloop_block_t aloop,
344 const t_atom **atom, int *nmol)
346 if (aloop == nullptr)
348 gmx_incons("gmx_mtop_atomloop_all_next called without calling gmx_mtop_atomloop_all_init");
353 if (aloop->at_local >= aloop->atoms->nr)
356 if (aloop->mblock >= aloop->mtop->molblock.size())
358 gmx_mtop_atomloop_block_destroy(aloop);
361 aloop->atoms = &aloop->mtop->moltype[aloop->mtop->molblock[aloop->mblock].type].atoms;
365 *atom = &aloop->atoms->atom[aloop->at_local];
366 *nmol = aloop->mtop->molblock[aloop->mblock].nmol;
371 typedef struct gmx_mtop_ilistloop
373 const gmx_mtop_t *mtop;
378 gmx_mtop_ilistloop_init(const gmx_mtop_t *mtop)
380 struct gmx_mtop_ilistloop *iloop;
391 gmx_mtop_ilistloop_init(const gmx_mtop_t &mtop)
393 return gmx_mtop_ilistloop_init(&mtop);
396 static void gmx_mtop_ilistloop_destroy(gmx_mtop_ilistloop_t iloop)
401 gmx_bool gmx_mtop_ilistloop_next(gmx_mtop_ilistloop_t iloop,
402 const InteractionList **ilist_mol,
405 if (iloop == nullptr)
407 gmx_incons("gmx_mtop_ilistloop_next called without calling gmx_mtop_ilistloop_init");
411 if (iloop->mblock >= static_cast<int>(iloop->mtop->molblock.size()))
413 if (iloop->mblock == static_cast<int>(iloop->mtop->molblock.size()) &&
414 iloop->mtop->bIntermolecularInteractions)
416 *ilist_mol = iloop->mtop->intermolecular_ilist->data();
421 gmx_mtop_ilistloop_destroy(iloop);
426 iloop->mtop->moltype[iloop->mtop->molblock[iloop->mblock].type].ilist;
428 *nmol = iloop->mtop->molblock[iloop->mblock].nmol;
432 typedef struct gmx_mtop_ilistloop_all
434 const gmx_mtop_t *mtop;
438 } t_gmx_mtop_ilist_all;
440 gmx_mtop_ilistloop_all_t
441 gmx_mtop_ilistloop_all_init(const gmx_mtop_t *mtop)
443 struct gmx_mtop_ilistloop_all *iloop;
455 static void gmx_mtop_ilistloop_all_destroy(gmx_mtop_ilistloop_all_t iloop)
460 gmx_bool gmx_mtop_ilistloop_all_next(gmx_mtop_ilistloop_all_t iloop,
461 const InteractionList **ilist_mol,
465 if (iloop == nullptr)
467 gmx_incons("gmx_mtop_ilistloop_all_next called without calling gmx_mtop_ilistloop_all_init");
472 iloop->a_offset += iloop->mtop->moleculeBlockIndices[iloop->mblock].numAtomsPerMolecule;
477 /* Inter-molecular interactions, if present, are indexed with
478 * iloop->mblock == iloop->mtop->nmolblock, thus we should separately
479 * check for this value in this conditional.
481 if (iloop->mblock == iloop->mtop->molblock.size() ||
482 iloop->mol >= iloop->mtop->molblock[iloop->mblock].nmol)
486 if (iloop->mblock >= iloop->mtop->molblock.size())
488 if (iloop->mblock == iloop->mtop->molblock.size() &&
489 iloop->mtop->bIntermolecularInteractions)
491 *ilist_mol = iloop->mtop->intermolecular_ilist->data();
496 gmx_mtop_ilistloop_all_destroy(iloop);
502 iloop->mtop->moltype[iloop->mtop->molblock[iloop->mblock].type].ilist;
504 *atnr_offset = iloop->a_offset;
509 int gmx_mtop_ftype_count(const gmx_mtop_t *mtop, int ftype)
511 gmx_mtop_ilistloop_t iloop;
512 const InteractionList *il;
517 iloop = gmx_mtop_ilistloop_init(mtop);
518 while (gmx_mtop_ilistloop_next(iloop, &il, &nmol))
520 n += nmol*il[ftype].size()/(1+NRAL(ftype));
523 if (mtop->bIntermolecularInteractions)
525 n += (*mtop->intermolecular_ilist)[ftype].size()/(1+NRAL(ftype));
531 int gmx_mtop_ftype_count(const gmx_mtop_t &mtop, int ftype)
533 return gmx_mtop_ftype_count(&mtop, ftype);
536 t_block gmx_mtop_global_cgs(const gmx_mtop_t *mtop)
539 /* In most cases this is too much, but we realloc at the end */
540 snew(cgs_gl.index, mtop->natoms+1);
544 for (const gmx_molblock_t &molb : mtop->molblock)
546 const t_block &cgs_mol = mtop->moltype[molb.type].cgs;
547 for (int mol = 0; mol < molb.nmol; mol++)
549 for (int cg = 0; cg < cgs_mol.nr; cg++)
551 cgs_gl.index[cgs_gl.nr + 1] =
552 cgs_gl.index[cgs_gl.nr] +
553 cgs_mol.index[cg + 1] - cgs_mol.index[cg];
558 cgs_gl.nalloc_index = cgs_gl.nr + 1;
559 srenew(cgs_gl.index, cgs_gl.nalloc_index);
564 static void atomcat(t_atoms *dest, const t_atoms *src, int copies,
565 int maxres_renum, int *maxresnr)
569 int destnr = dest->nr;
573 dest->haveMass = src->haveMass;
574 dest->haveType = src->haveType;
575 dest->haveCharge = src->haveCharge;
576 dest->haveBState = src->haveBState;
577 dest->havePdbInfo = src->havePdbInfo;
581 dest->haveMass = dest->haveMass && src->haveMass;
582 dest->haveType = dest->haveType && src->haveType;
583 dest->haveCharge = dest->haveCharge && src->haveCharge;
584 dest->haveBState = dest->haveBState && src->haveBState;
585 dest->havePdbInfo = dest->havePdbInfo && src->havePdbInfo;
590 size = destnr+copies*srcnr;
591 srenew(dest->atom, size);
592 srenew(dest->atomname, size);
595 srenew(dest->atomtype, size);
596 if (dest->haveBState)
598 srenew(dest->atomtypeB, size);
601 if (dest->havePdbInfo)
603 srenew(dest->pdbinfo, size);
608 size = dest->nres+copies*src->nres;
609 srenew(dest->resinfo, size);
612 /* residue information */
613 for (l = dest->nres, j = 0; (j < copies); j++, l += src->nres)
615 memcpy(reinterpret_cast<char *>(&(dest->resinfo[l])), reinterpret_cast<char *>(&(src->resinfo[0])),
616 static_cast<size_t>(src->nres*sizeof(src->resinfo[0])));
619 for (l = destnr, j = 0; (j < copies); j++, l += srcnr)
621 memcpy(reinterpret_cast<char *>(&(dest->atom[l])), reinterpret_cast<char *>(&(src->atom[0])),
622 static_cast<size_t>(srcnr*sizeof(src->atom[0])));
623 memcpy(reinterpret_cast<char *>(&(dest->atomname[l])), reinterpret_cast<char *>(&(src->atomname[0])),
624 static_cast<size_t>(srcnr*sizeof(src->atomname[0])));
627 memcpy(reinterpret_cast<char *>(&(dest->atomtype[l])), reinterpret_cast<char *>(&(src->atomtype[0])),
628 static_cast<size_t>(srcnr*sizeof(src->atomtype[0])));
629 if (dest->haveBState)
631 memcpy(reinterpret_cast<char *>(&(dest->atomtypeB[l])), reinterpret_cast<char *>(&(src->atomtypeB[0])),
632 static_cast<size_t>(srcnr*sizeof(src->atomtypeB[0])));
635 if (dest->havePdbInfo)
637 memcpy(reinterpret_cast<char *>(&(dest->pdbinfo[l])), reinterpret_cast<char *>(&(src->pdbinfo[0])),
638 static_cast<size_t>(srcnr*sizeof(src->pdbinfo[0])));
642 /* Increment residue indices */
643 for (l = destnr, j = 0; (j < copies); j++)
645 for (i = 0; (i < srcnr); i++, l++)
647 dest->atom[l].resind = dest->nres+j*src->nres+src->atom[i].resind;
651 if (src->nres <= maxres_renum)
653 /* Single residue molecule, continue counting residues */
654 for (j = 0; (j < copies); j++)
656 for (l = 0; l < src->nres; l++)
659 dest->resinfo[dest->nres+j*src->nres+l].nr = *maxresnr;
664 dest->nres += copies*src->nres;
665 dest->nr += copies*src->nr;
668 t_atoms gmx_mtop_global_atoms(const gmx_mtop_t *mtop)
672 init_t_atoms(&atoms, 0, FALSE);
674 int maxresnr = mtop->maxresnr;
675 for (const gmx_molblock_t &molb : mtop->molblock)
677 atomcat(&atoms, &mtop->moltype[molb.type].atoms, molb.nmol,
678 mtop->maxres_renum, &maxresnr);
685 * The cat routines below are old code from src/kernel/topcat.c
688 static void blockcat(t_block *dest, const t_block *src, int copies)
690 int i, j, l, nra, size;
694 size = (dest->nr+copies*src->nr+1);
695 srenew(dest->index, size);
698 nra = dest->index[dest->nr];
699 for (l = dest->nr, j = 0; (j < copies); j++)
701 for (i = 0; (i < src->nr); i++)
703 dest->index[l++] = nra + src->index[i];
707 nra += src->index[src->nr];
710 dest->nr += copies*src->nr;
711 dest->index[dest->nr] = nra;
714 static void blockacat(t_blocka *dest, const t_blocka *src, int copies,
718 int destnr = dest->nr;
719 int destnra = dest->nra;
723 size = (dest->nr+copies*src->nr+1);
724 srenew(dest->index, size);
728 size = (dest->nra+copies*src->nra);
729 srenew(dest->a, size);
732 for (l = destnr, j = 0; (j < copies); j++)
734 for (i = 0; (i < src->nr); i++)
736 dest->index[l++] = dest->nra+src->index[i];
738 dest->nra += src->nra;
740 for (l = destnra, j = 0; (j < copies); j++)
742 for (i = 0; (i < src->nra); i++)
744 dest->a[l++] = dnum+src->a[i];
749 dest->index[dest->nr] = dest->nra;
752 static void ilistcat(int ftype,
754 const InteractionList &src,
763 dest->nalloc = dest->nr + copies*src.size();
764 srenew(dest->iatoms, dest->nalloc);
766 for (c = 0; c < copies; c++)
768 for (i = 0; i < src.size(); )
770 dest->iatoms[dest->nr++] = src.iatoms[i++];
771 for (a = 0; a < nral; a++)
773 dest->iatoms[dest->nr++] = dnum + src.iatoms[i++];
780 static void set_posres_params(t_idef *idef, const gmx_molblock_t *molb,
781 int i0, int a_offset)
787 il = &idef->il[F_POSRES];
789 idef->iparams_posres_nalloc = i1;
790 srenew(idef->iparams_posres, idef->iparams_posres_nalloc);
791 for (i = i0; i < i1; i++)
793 ip = &idef->iparams_posres[i];
794 /* Copy the force constants */
795 *ip = idef->iparams[il->iatoms[i*2]];
796 a_molb = il->iatoms[i*2+1] - a_offset;
797 if (molb->posres_xA.empty())
799 gmx_incons("Position restraint coordinates are missing");
801 ip->posres.pos0A[XX] = molb->posres_xA[a_molb][XX];
802 ip->posres.pos0A[YY] = molb->posres_xA[a_molb][YY];
803 ip->posres.pos0A[ZZ] = molb->posres_xA[a_molb][ZZ];
804 if (!molb->posres_xB.empty())
806 ip->posres.pos0B[XX] = molb->posres_xB[a_molb][XX];
807 ip->posres.pos0B[YY] = molb->posres_xB[a_molb][YY];
808 ip->posres.pos0B[ZZ] = molb->posres_xB[a_molb][ZZ];
812 ip->posres.pos0B[XX] = ip->posres.pos0A[XX];
813 ip->posres.pos0B[YY] = ip->posres.pos0A[YY];
814 ip->posres.pos0B[ZZ] = ip->posres.pos0A[ZZ];
816 /* Set the parameter index for idef->iparams_posre */
821 static void set_fbposres_params(t_idef *idef, const gmx_molblock_t *molb,
822 int i0, int a_offset)
828 il = &idef->il[F_FBPOSRES];
830 idef->iparams_fbposres_nalloc = i1;
831 srenew(idef->iparams_fbposres, idef->iparams_fbposres_nalloc);
832 for (i = i0; i < i1; i++)
834 ip = &idef->iparams_fbposres[i];
835 /* Copy the force constants */
836 *ip = idef->iparams[il->iatoms[i*2]];
837 a_molb = il->iatoms[i*2+1] - a_offset;
838 if (molb->posres_xA.empty())
840 gmx_incons("Position restraint coordinates are missing");
842 /* Take flat-bottom posres reference from normal position restraints */
843 ip->fbposres.pos0[XX] = molb->posres_xA[a_molb][XX];
844 ip->fbposres.pos0[YY] = molb->posres_xA[a_molb][YY];
845 ip->fbposres.pos0[ZZ] = molb->posres_xA[a_molb][ZZ];
846 /* Note: no B-type for flat-bottom posres */
848 /* Set the parameter index for idef->iparams_posre */
853 static void gen_local_top(const gmx_mtop_t *mtop,
854 bool freeEnergyInteractionsAtEnd,
858 int srcnr, destnr, ftype, natoms, nposre_old, nfbposre_old;
859 const gmx_ffparams_t *ffp;
862 gmx_mtop_atomloop_all_t aloop;
865 /* no copying of pointers possible now */
867 top->atomtypes.nr = mtop->atomtypes.nr;
868 if (mtop->atomtypes.atomnumber)
870 snew(top->atomtypes.atomnumber, top->atomtypes.nr);
871 std::copy(mtop->atomtypes.atomnumber, mtop->atomtypes.atomnumber + top->atomtypes.nr, top->atomtypes.atomnumber);
875 top->atomtypes.atomnumber = nullptr;
878 ffp = &mtop->ffparams;
881 idef->ntypes = ffp->ntypes;
882 idef->atnr = ffp->atnr;
883 /* we can no longer copy the pointers to the mtop members,
884 * because they will become invalid as soon as mtop gets free'd.
885 * We also need to make sure to only operate on valid data!
890 snew(idef->functype, ffp->ntypes);
891 std::copy(ffp->functype, ffp->functype + ffp->ntypes, idef->functype);
895 idef->functype = nullptr;
899 snew(idef->iparams, ffp->ntypes);
900 std::copy(ffp->iparams, ffp->iparams + ffp->ntypes, idef->iparams);
904 idef->iparams = nullptr;
906 idef->iparams_posres = nullptr;
907 idef->iparams_posres_nalloc = 0;
908 idef->iparams_fbposres = nullptr;
909 idef->iparams_fbposres_nalloc = 0;
910 idef->fudgeQQ = ffp->fudgeQQ;
911 idef->cmap_grid.ngrid = ffp->cmap_grid.ngrid;
912 idef->cmap_grid.grid_spacing = ffp->cmap_grid.grid_spacing;
913 if (ffp->cmap_grid.cmapdata)
915 snew(idef->cmap_grid.cmapdata, ffp->cmap_grid.ngrid);
916 std::copy(ffp->cmap_grid.cmapdata, ffp->cmap_grid.cmapdata + ffp->cmap_grid.ngrid, idef->cmap_grid.cmapdata);
920 idef->cmap_grid.cmapdata = nullptr;
922 idef->ilsort = ilsortUNKNOWN;
924 init_block(&top->cgs);
925 init_blocka(&top->excls);
926 for (ftype = 0; ftype < F_NRE; ftype++)
928 idef->il[ftype].nr = 0;
929 idef->il[ftype].nalloc = 0;
930 idef->il[ftype].iatoms = nullptr;
934 for (const gmx_molblock_t &molb : mtop->molblock)
936 const gmx_moltype_t &molt = mtop->moltype[molb.type];
938 srcnr = molt.atoms.nr;
941 blockcat(&top->cgs, &molt.cgs, molb.nmol);
943 blockacat(&top->excls, &molt.excls, molb.nmol, destnr, srcnr);
945 nposre_old = idef->il[F_POSRES].nr;
946 nfbposre_old = idef->il[F_FBPOSRES].nr;
947 for (ftype = 0; ftype < F_NRE; ftype++)
950 ftype == F_CONSTR && molt.ilist[F_CONSTRNC].size() > 0)
952 /* Merge all constrains into one ilist.
953 * This simplifies the constraint code.
955 for (int mol = 0; mol < molb.nmol; mol++)
957 ilistcat(ftype, &idef->il[F_CONSTR], molt.ilist[F_CONSTR],
958 1, destnr + mol*srcnr, srcnr);
959 ilistcat(ftype, &idef->il[F_CONSTR], molt.ilist[F_CONSTRNC],
960 1, destnr + mol*srcnr, srcnr);
963 else if (!(bMergeConstr && ftype == F_CONSTRNC))
965 ilistcat(ftype, &idef->il[ftype], molt.ilist[ftype],
966 molb.nmol, destnr, srcnr);
969 if (idef->il[F_POSRES].nr > nposre_old)
971 /* Executing this line line stops gmxdump -sys working
972 * correctly. I'm not aware there's an elegant fix. */
973 set_posres_params(idef, &molb, nposre_old/2, natoms);
975 if (idef->il[F_FBPOSRES].nr > nfbposre_old)
977 set_fbposres_params(idef, &molb, nfbposre_old/2, natoms);
980 natoms += molb.nmol*srcnr;
983 if (mtop->bIntermolecularInteractions)
985 for (ftype = 0; ftype < F_NRE; ftype++)
987 ilistcat(ftype, &idef->il[ftype], (*mtop->intermolecular_ilist)[ftype],
992 if (freeEnergyInteractionsAtEnd && gmx_mtop_bondeds_free_energy(mtop))
994 snew(qA, mtop->natoms);
995 snew(qB, mtop->natoms);
996 aloop = gmx_mtop_atomloop_all_init(mtop);
998 while (gmx_mtop_atomloop_all_next(aloop, &ag, &atom))
1003 gmx_sort_ilist_fe(&top->idef, qA, qB);
1009 top->idef.ilsort = ilsortNO_FE;
1014 gmx_mtop_generate_local_top(const gmx_mtop_t *mtop,
1015 bool freeEnergyInteractionsAtEnd)
1017 gmx_localtop_t *top;
1021 gen_local_top(mtop, freeEnergyInteractionsAtEnd, true, top);
1026 /*! \brief Fills an array with molecule begin/end atom indices
1028 * \param[in] mtop The global topology
1029 * \param[out] index Array of size nr. of molecules + 1 to be filled with molecule begin/end indices
1031 static void fillMoleculeIndices(const gmx_mtop_t &mtop,
1032 gmx::ArrayRef<int> index)
1034 int globalAtomIndex = 0;
1035 int globalMolIndex = 0;
1036 index[globalMolIndex] = globalAtomIndex;
1037 for (const gmx_molblock_t &molb : mtop.molblock)
1039 int numAtomsPerMolecule = mtop.moltype[molb.type].atoms.nr;
1040 for (int mol = 0; mol < molb.nmol; mol++)
1042 globalAtomIndex += numAtomsPerMolecule;
1043 globalMolIndex += 1;
1044 index[globalMolIndex] = globalAtomIndex;
1049 gmx::RangePartitioning gmx_mtop_molecules(const gmx_mtop_t &mtop)
1051 gmx::RangePartitioning mols;
1053 for (const gmx_molblock_t &molb : mtop.molblock)
1055 int numAtomsPerMolecule = mtop.moltype[molb.type].atoms.nr;
1056 for (int mol = 0; mol < molb.nmol; mol++)
1058 mols.appendBlock(numAtomsPerMolecule);
1065 /*! \brief Creates and returns a deprecated t_block struct with molecule indices
1067 * \param[in] mtop The global topology
1069 static t_block gmx_mtop_molecules_t_block(const gmx_mtop_t &mtop)
1073 mols.nr = gmx_mtop_num_molecules(mtop);
1074 mols.nalloc_index = mols.nr + 1;
1075 snew(mols.index, mols.nalloc_index);
1077 fillMoleculeIndices(mtop, gmx::arrayRefFromArray(mols.index, mols.nr + 1));
1082 t_topology gmx_mtop_t_to_t_topology(gmx_mtop_t *mtop, bool freeMTop)
1084 gmx_localtop_t ltop;
1087 gen_local_top(mtop, false, FALSE, <op);
1088 ltop.idef.ilsort = ilsortUNKNOWN;
1090 top.name = mtop->name;
1091 top.idef = ltop.idef;
1092 top.atomtypes = ltop.atomtypes;
1094 top.excls = ltop.excls;
1095 top.atoms = gmx_mtop_global_atoms(mtop);
1096 top.mols = gmx_mtop_molecules_t_block(*mtop);
1097 top.bIntermolecularInteractions = mtop->bIntermolecularInteractions;
1098 top.symtab = mtop->symtab;
1102 // Clear pointers and counts, such that the pointers copied to top
1103 // keep pointing to valid data after destroying mtop.
1104 mtop->symtab.symbuf = nullptr;
1105 mtop->symtab.nr = 0;
1111 std::vector<size_t> get_atom_index(const gmx_mtop_t *mtop)
1114 std::vector<size_t> atom_index;
1115 gmx_mtop_atomloop_block_t aloopb = gmx_mtop_atomloop_block_init(mtop);
1118 while (gmx_mtop_atomloop_block_next(aloopb, &atom, &nmol))
1120 if (atom->ptype == eptAtom)
1122 atom_index.push_back(j);
1129 void convertAtomsToMtop(t_symtab *symtab,
1134 mtop->symtab = *symtab;
1138 mtop->moltype.clear();
1139 mtop->moltype.resize(1);
1140 mtop->moltype.back().atoms = *atoms;
1142 mtop->molblock.resize(1);
1143 mtop->molblock[0].type = 0;
1144 mtop->molblock[0].nmol = 1;
1146 mtop->bIntermolecularInteractions = FALSE;
1148 mtop->natoms = atoms->nr;
1150 mtop->haveMoleculeIndices = false;
1152 gmx_mtop_finalize(mtop);