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/exclusionblocks.h"
49 #include "gromacs/topology/idef.h"
50 #include "gromacs/topology/ifunc.h"
51 #include "gromacs/topology/topology.h"
52 #include "gromacs/topology/topsort.h"
53 #include "gromacs/utility/arrayref.h"
54 #include "gromacs/utility/fatalerror.h"
55 #include "gromacs/utility/real.h"
56 #include "gromacs/utility/smalloc.h"
58 static int gmx_mtop_maxresnr(const gmx_mtop_t
*mtop
, int maxres_renum
)
62 for (const gmx_moltype_t
&moltype
: mtop
->moltype
)
64 const t_atoms
&atoms
= moltype
.atoms
;
65 if (atoms
.nres
> maxres_renum
)
67 for (int r
= 0; r
< atoms
.nres
; r
++)
69 if (atoms
.resinfo
[r
].nr
> maxresnr
)
71 maxresnr
= atoms
.resinfo
[r
].nr
;
80 static void buildMolblockIndices(gmx_mtop_t
*mtop
)
82 mtop
->moleculeBlockIndices
.resize(mtop
->molblock
.size());
86 int residueNumberStart
= mtop
->maxresnr
+ 1;
87 int moleculeIndexStart
= 0;
88 for (size_t mb
= 0; mb
< mtop
->molblock
.size(); mb
++)
90 const gmx_molblock_t
&molb
= mtop
->molblock
[mb
];
91 MoleculeBlockIndices
&indices
= mtop
->moleculeBlockIndices
[mb
];
92 const int numResPerMol
= mtop
->moltype
[molb
.type
].atoms
.nres
;
94 indices
.numAtomsPerMolecule
= mtop
->moltype
[molb
.type
].atoms
.nr
;
95 indices
.globalAtomStart
= atomIndex
;
96 indices
.globalResidueStart
= residueIndex
;
97 atomIndex
+= molb
.nmol
*indices
.numAtomsPerMolecule
;
98 residueIndex
+= molb
.nmol
*numResPerMol
;
99 indices
.globalAtomEnd
= atomIndex
;
100 indices
.residueNumberStart
= residueNumberStart
;
101 if (numResPerMol
<= mtop
->maxres_renum
)
103 residueNumberStart
+= molb
.nmol
*numResPerMol
;
105 indices
.moleculeIndexStart
= moleculeIndexStart
;
106 moleculeIndexStart
+= molb
.nmol
;
110 void gmx_mtop_finalize(gmx_mtop_t
*mtop
)
114 if (mtop
->molblock
.size() == 1 && mtop
->molblock
[0].nmol
== 1)
116 /* We have a single molecule only, no renumbering needed.
117 * This case also covers an mtop converted from pdb/gro/... input,
118 * so we retain the original residue numbering.
120 mtop
->maxres_renum
= 0;
124 /* We only renumber single residue molecules. Their intra-molecular
125 * residue numbering is anyhow irrelevant.
127 mtop
->maxres_renum
= 1;
130 env
= getenv("GMX_MAXRESRENUM");
133 sscanf(env
, "%d", &mtop
->maxres_renum
);
135 if (mtop
->maxres_renum
== -1)
137 /* -1 signals renumber residues in all molecules */
138 mtop
->maxres_renum
= INT_MAX
;
141 mtop
->maxresnr
= gmx_mtop_maxresnr(mtop
, mtop
->maxres_renum
);
143 buildMolblockIndices(mtop
);
146 void gmx_mtop_count_atomtypes(const gmx_mtop_t
*mtop
, int state
, int typecount
[])
148 for (int i
= 0; i
< mtop
->ffparams
.atnr
; ++i
)
152 for (const gmx_molblock_t
&molb
: mtop
->molblock
)
154 const t_atoms
&atoms
= mtop
->moltype
[molb
.type
].atoms
;
155 for (int i
= 0; i
< atoms
.nr
; ++i
)
160 tpi
= atoms
.atom
[i
].type
;
164 tpi
= atoms
.atom
[i
].typeB
;
166 typecount
[tpi
] += molb
.nmol
;
171 int ncg_mtop(const gmx_mtop_t
*mtop
)
174 for (const gmx_molblock_t
&molb
: mtop
->molblock
)
176 ncg
+= molb
.nmol
*mtop
->moltype
[molb
.type
].cgs
.nr
;
182 int gmx_mtop_num_molecules(const gmx_mtop_t
&mtop
)
184 int numMolecules
= 0;
185 for (const gmx_molblock_t
&molb
: mtop
.molblock
)
187 numMolecules
+= molb
.nmol
;
192 int gmx_mtop_nres(const gmx_mtop_t
*mtop
)
195 for (const gmx_molblock_t
&molb
: mtop
->molblock
)
197 nres
+= molb
.nmol
*mtop
->moltype
[molb
.type
].atoms
.nres
;
202 void gmx_mtop_remove_chargegroups(gmx_mtop_t
*mtop
)
204 for (gmx_moltype_t
&molt
: mtop
->moltype
)
206 t_block
&cgs
= molt
.cgs
;
207 if (cgs
.nr
< molt
.atoms
.nr
)
209 cgs
.nr
= molt
.atoms
.nr
;
210 srenew(cgs
.index
, cgs
.nr
+ 1);
211 for (int i
= 0; i
< cgs
.nr
+ 1; i
++)
219 typedef struct gmx_mtop_atomloop_all
221 const gmx_mtop_t
*mtop
;
223 const t_atoms
*atoms
;
228 } t_gmx_mtop_atomloop_all
;
230 gmx_mtop_atomloop_all_t
231 gmx_mtop_atomloop_all_init(const gmx_mtop_t
*mtop
)
233 struct gmx_mtop_atomloop_all
*aloop
;
240 &mtop
->moltype
[mtop
->molblock
[aloop
->mblock
].type
].atoms
;
242 aloop
->maxresnr
= mtop
->maxresnr
;
243 aloop
->at_local
= -1;
244 aloop
->at_global
= -1;
249 static void gmx_mtop_atomloop_all_destroy(gmx_mtop_atomloop_all_t aloop
)
254 gmx_bool
gmx_mtop_atomloop_all_next(gmx_mtop_atomloop_all_t aloop
,
255 int *at_global
, const t_atom
**atom
)
257 if (aloop
== nullptr)
259 gmx_incons("gmx_mtop_atomloop_all_next called without calling gmx_mtop_atomloop_all_init");
265 if (aloop
->at_local
>= aloop
->atoms
->nr
)
267 if (aloop
->atoms
->nres
<= aloop
->mtop
->maxres_renum
)
269 /* Single residue molecule, increase the count with one */
270 aloop
->maxresnr
+= aloop
->atoms
->nres
;
274 if (aloop
->mol
>= aloop
->mtop
->molblock
[aloop
->mblock
].nmol
)
277 if (aloop
->mblock
>= aloop
->mtop
->molblock
.size())
279 gmx_mtop_atomloop_all_destroy(aloop
);
282 aloop
->atoms
= &aloop
->mtop
->moltype
[aloop
->mtop
->molblock
[aloop
->mblock
].type
].atoms
;
287 *at_global
= aloop
->at_global
;
288 *atom
= &aloop
->atoms
->atom
[aloop
->at_local
];
293 void gmx_mtop_atomloop_all_names(gmx_mtop_atomloop_all_t aloop
,
294 char **atomname
, int *resnr
, char **resname
)
298 *atomname
= *(aloop
->atoms
->atomname
[aloop
->at_local
]);
299 resind_mol
= aloop
->atoms
->atom
[aloop
->at_local
].resind
;
300 *resnr
= aloop
->atoms
->resinfo
[resind_mol
].nr
;
301 if (aloop
->atoms
->nres
<= aloop
->mtop
->maxres_renum
)
303 *resnr
= aloop
->maxresnr
+ 1 + resind_mol
;
305 *resname
= *(aloop
->atoms
->resinfo
[resind_mol
].name
);
308 void gmx_mtop_atomloop_all_moltype(gmx_mtop_atomloop_all_t aloop
,
309 const gmx_moltype_t
**moltype
,
312 *moltype
= &aloop
->mtop
->moltype
[aloop
->mtop
->molblock
[aloop
->mblock
].type
];
313 *at_mol
= aloop
->at_local
;
316 typedef struct gmx_mtop_atomloop_block
318 const gmx_mtop_t
*mtop
;
320 const t_atoms
*atoms
;
322 } t_gmx_mtop_atomloop_block
;
324 gmx_mtop_atomloop_block_t
325 gmx_mtop_atomloop_block_init(const gmx_mtop_t
*mtop
)
327 struct gmx_mtop_atomloop_block
*aloop
;
333 aloop
->atoms
= &mtop
->moltype
[mtop
->molblock
[aloop
->mblock
].type
].atoms
;
334 aloop
->at_local
= -1;
339 static void gmx_mtop_atomloop_block_destroy(gmx_mtop_atomloop_block_t aloop
)
344 gmx_bool
gmx_mtop_atomloop_block_next(gmx_mtop_atomloop_block_t aloop
,
345 const t_atom
**atom
, int *nmol
)
347 if (aloop
== nullptr)
349 gmx_incons("gmx_mtop_atomloop_all_next called without calling gmx_mtop_atomloop_all_init");
354 if (aloop
->at_local
>= aloop
->atoms
->nr
)
357 if (aloop
->mblock
>= aloop
->mtop
->molblock
.size())
359 gmx_mtop_atomloop_block_destroy(aloop
);
362 aloop
->atoms
= &aloop
->mtop
->moltype
[aloop
->mtop
->molblock
[aloop
->mblock
].type
].atoms
;
366 *atom
= &aloop
->atoms
->atom
[aloop
->at_local
];
367 *nmol
= aloop
->mtop
->molblock
[aloop
->mblock
].nmol
;
372 typedef struct gmx_mtop_ilistloop
374 const gmx_mtop_t
*mtop
;
379 gmx_mtop_ilistloop_init(const gmx_mtop_t
*mtop
)
381 struct gmx_mtop_ilistloop
*iloop
;
392 gmx_mtop_ilistloop_init(const gmx_mtop_t
&mtop
)
394 return gmx_mtop_ilistloop_init(&mtop
);
397 static void gmx_mtop_ilistloop_destroy(gmx_mtop_ilistloop_t iloop
)
402 const InteractionLists
*
403 gmx_mtop_ilistloop_next(gmx_mtop_ilistloop_t iloop
,
406 if (iloop
== nullptr)
408 gmx_incons("gmx_mtop_ilistloop_next called without calling gmx_mtop_ilistloop_init");
412 if (iloop
->mblock
>= static_cast<int>(iloop
->mtop
->molblock
.size()))
414 if (iloop
->mblock
== static_cast<int>(iloop
->mtop
->molblock
.size()) &&
415 iloop
->mtop
->bIntermolecularInteractions
)
418 return iloop
->mtop
->intermolecular_ilist
.get();
421 gmx_mtop_ilistloop_destroy(iloop
);
425 *nmol
= iloop
->mtop
->molblock
[iloop
->mblock
].nmol
;
428 &iloop
->mtop
->moltype
[iloop
->mtop
->molblock
[iloop
->mblock
].type
].ilist
;
430 typedef struct gmx_mtop_ilistloop_all
432 const gmx_mtop_t
*mtop
;
436 } t_gmx_mtop_ilist_all
;
438 gmx_mtop_ilistloop_all_t
439 gmx_mtop_ilistloop_all_init(const gmx_mtop_t
*mtop
)
441 struct gmx_mtop_ilistloop_all
*iloop
;
453 static void gmx_mtop_ilistloop_all_destroy(gmx_mtop_ilistloop_all_t iloop
)
458 const InteractionLists
*
459 gmx_mtop_ilistloop_all_next(gmx_mtop_ilistloop_all_t iloop
,
463 if (iloop
== nullptr)
465 gmx_incons("gmx_mtop_ilistloop_all_next called without calling gmx_mtop_ilistloop_all_init");
470 iloop
->a_offset
+= iloop
->mtop
->moleculeBlockIndices
[iloop
->mblock
].numAtomsPerMolecule
;
475 /* Inter-molecular interactions, if present, are indexed with
476 * iloop->mblock == iloop->mtop->nmolblock, thus we should separately
477 * check for this value in this conditional.
479 if (iloop
->mblock
== iloop
->mtop
->molblock
.size() ||
480 iloop
->mol
>= iloop
->mtop
->molblock
[iloop
->mblock
].nmol
)
484 if (iloop
->mblock
>= iloop
->mtop
->molblock
.size())
486 if (iloop
->mblock
== iloop
->mtop
->molblock
.size() &&
487 iloop
->mtop
->bIntermolecularInteractions
)
490 return iloop
->mtop
->intermolecular_ilist
.get();
493 gmx_mtop_ilistloop_all_destroy(iloop
);
498 *atnr_offset
= iloop
->a_offset
;
501 &iloop
->mtop
->moltype
[iloop
->mtop
->molblock
[iloop
->mblock
].type
].ilist
;
504 int gmx_mtop_ftype_count(const gmx_mtop_t
*mtop
, int ftype
)
506 gmx_mtop_ilistloop_t iloop
;
511 iloop
= gmx_mtop_ilistloop_init(mtop
);
512 while (const InteractionLists
*il
= gmx_mtop_ilistloop_next(iloop
, &nmol
))
514 n
+= nmol
*(*il
)[ftype
].size()/(1+NRAL(ftype
));
517 if (mtop
->bIntermolecularInteractions
)
519 n
+= (*mtop
->intermolecular_ilist
)[ftype
].size()/(1+NRAL(ftype
));
525 int gmx_mtop_ftype_count(const gmx_mtop_t
&mtop
, int ftype
)
527 return gmx_mtop_ftype_count(&mtop
, ftype
);
530 t_block
gmx_mtop_global_cgs(const gmx_mtop_t
*mtop
)
533 /* In most cases this is too much, but we realloc at the end */
534 snew(cgs_gl
.index
, mtop
->natoms
+1);
538 for (const gmx_molblock_t
&molb
: mtop
->molblock
)
540 const t_block
&cgs_mol
= mtop
->moltype
[molb
.type
].cgs
;
541 for (int mol
= 0; mol
< molb
.nmol
; mol
++)
543 for (int cg
= 0; cg
< cgs_mol
.nr
; cg
++)
545 cgs_gl
.index
[cgs_gl
.nr
+ 1] =
546 cgs_gl
.index
[cgs_gl
.nr
] +
547 cgs_mol
.index
[cg
+ 1] - cgs_mol
.index
[cg
];
552 cgs_gl
.nalloc_index
= cgs_gl
.nr
+ 1;
553 srenew(cgs_gl
.index
, cgs_gl
.nalloc_index
);
558 static void atomcat(t_atoms
*dest
, const t_atoms
*src
, int copies
,
559 int maxres_renum
, int *maxresnr
)
563 int destnr
= dest
->nr
;
567 dest
->haveMass
= src
->haveMass
;
568 dest
->haveType
= src
->haveType
;
569 dest
->haveCharge
= src
->haveCharge
;
570 dest
->haveBState
= src
->haveBState
;
571 dest
->havePdbInfo
= src
->havePdbInfo
;
575 dest
->haveMass
= dest
->haveMass
&& src
->haveMass
;
576 dest
->haveType
= dest
->haveType
&& src
->haveType
;
577 dest
->haveCharge
= dest
->haveCharge
&& src
->haveCharge
;
578 dest
->haveBState
= dest
->haveBState
&& src
->haveBState
;
579 dest
->havePdbInfo
= dest
->havePdbInfo
&& src
->havePdbInfo
;
584 size
= destnr
+copies
*srcnr
;
585 srenew(dest
->atom
, size
);
586 srenew(dest
->atomname
, size
);
589 srenew(dest
->atomtype
, size
);
590 if (dest
->haveBState
)
592 srenew(dest
->atomtypeB
, size
);
595 if (dest
->havePdbInfo
)
597 srenew(dest
->pdbinfo
, size
);
602 size
= dest
->nres
+copies
*src
->nres
;
603 srenew(dest
->resinfo
, size
);
606 /* residue information */
607 for (l
= dest
->nres
, j
= 0; (j
< copies
); j
++, l
+= src
->nres
)
609 memcpy(reinterpret_cast<char *>(&(dest
->resinfo
[l
])), reinterpret_cast<char *>(&(src
->resinfo
[0])),
610 static_cast<size_t>(src
->nres
*sizeof(src
->resinfo
[0])));
613 for (l
= destnr
, j
= 0; (j
< copies
); j
++, l
+= srcnr
)
615 memcpy(reinterpret_cast<char *>(&(dest
->atom
[l
])), reinterpret_cast<char *>(&(src
->atom
[0])),
616 static_cast<size_t>(srcnr
*sizeof(src
->atom
[0])));
617 memcpy(reinterpret_cast<char *>(&(dest
->atomname
[l
])), reinterpret_cast<char *>(&(src
->atomname
[0])),
618 static_cast<size_t>(srcnr
*sizeof(src
->atomname
[0])));
621 memcpy(reinterpret_cast<char *>(&(dest
->atomtype
[l
])), reinterpret_cast<char *>(&(src
->atomtype
[0])),
622 static_cast<size_t>(srcnr
*sizeof(src
->atomtype
[0])));
623 if (dest
->haveBState
)
625 memcpy(reinterpret_cast<char *>(&(dest
->atomtypeB
[l
])), reinterpret_cast<char *>(&(src
->atomtypeB
[0])),
626 static_cast<size_t>(srcnr
*sizeof(src
->atomtypeB
[0])));
629 if (dest
->havePdbInfo
)
631 memcpy(reinterpret_cast<char *>(&(dest
->pdbinfo
[l
])), reinterpret_cast<char *>(&(src
->pdbinfo
[0])),
632 static_cast<size_t>(srcnr
*sizeof(src
->pdbinfo
[0])));
636 /* Increment residue indices */
637 for (l
= destnr
, j
= 0; (j
< copies
); j
++)
639 for (i
= 0; (i
< srcnr
); i
++, l
++)
641 dest
->atom
[l
].resind
= dest
->nres
+j
*src
->nres
+src
->atom
[i
].resind
;
645 if (src
->nres
<= maxres_renum
)
647 /* Single residue molecule, continue counting residues */
648 for (j
= 0; (j
< copies
); j
++)
650 for (l
= 0; l
< src
->nres
; l
++)
653 dest
->resinfo
[dest
->nres
+j
*src
->nres
+l
].nr
= *maxresnr
;
658 dest
->nres
+= copies
*src
->nres
;
659 dest
->nr
+= copies
*src
->nr
;
662 t_atoms
gmx_mtop_global_atoms(const gmx_mtop_t
*mtop
)
666 init_t_atoms(&atoms
, 0, FALSE
);
668 int maxresnr
= mtop
->maxresnr
;
669 for (const gmx_molblock_t
&molb
: mtop
->molblock
)
671 atomcat(&atoms
, &mtop
->moltype
[molb
.type
].atoms
, molb
.nmol
,
672 mtop
->maxres_renum
, &maxresnr
);
679 * The cat routines below are old code from src/kernel/topcat.c
682 static void blockcat(t_block
*dest
, const t_block
*src
, int copies
)
684 int i
, j
, l
, nra
, size
;
688 size
= (dest
->nr
+copies
*src
->nr
+1);
689 srenew(dest
->index
, size
);
692 nra
= dest
->index
[dest
->nr
];
693 for (l
= dest
->nr
, j
= 0; (j
< copies
); j
++)
695 for (i
= 0; (i
< src
->nr
); i
++)
697 dest
->index
[l
++] = nra
+ src
->index
[i
];
701 nra
+= src
->index
[src
->nr
];
704 dest
->nr
+= copies
*src
->nr
;
705 dest
->index
[dest
->nr
] = nra
;
708 static void blockacat(t_blocka
*dest
, const t_blocka
*src
, int copies
,
712 int destnr
= dest
->nr
;
713 int destnra
= dest
->nra
;
717 size
= (dest
->nr
+copies
*src
->nr
+1);
718 srenew(dest
->index
, size
);
722 size
= (dest
->nra
+copies
*src
->nra
);
723 srenew(dest
->a
, size
);
726 for (l
= destnr
, j
= 0; (j
< copies
); j
++)
728 for (i
= 0; (i
< src
->nr
); i
++)
730 dest
->index
[l
++] = dest
->nra
+src
->index
[i
];
732 dest
->nra
+= src
->nra
;
734 for (l
= destnra
, j
= 0; (j
< copies
); j
++)
736 for (i
= 0; (i
< src
->nra
); i
++)
738 dest
->a
[l
++] = dnum
+src
->a
[i
];
743 dest
->index
[dest
->nr
] = dest
->nra
;
744 dest
->nalloc_index
= dest
->nr
;
745 dest
->nalloc_a
= dest
->nra
;
748 static void ilistcat(int ftype
,
750 const InteractionList
&src
,
759 dest
->nalloc
= dest
->nr
+ copies
*src
.size();
760 srenew(dest
->iatoms
, dest
->nalloc
);
762 for (c
= 0; c
< copies
; c
++)
764 for (i
= 0; i
< src
.size(); )
766 dest
->iatoms
[dest
->nr
++] = src
.iatoms
[i
++];
767 for (a
= 0; a
< nral
; a
++)
769 dest
->iatoms
[dest
->nr
++] = dnum
+ src
.iatoms
[i
++];
776 static void set_posres_params(t_idef
*idef
, const gmx_molblock_t
*molb
,
777 int i0
, int a_offset
)
783 il
= &idef
->il
[F_POSRES
];
785 idef
->iparams_posres_nalloc
= i1
;
786 srenew(idef
->iparams_posres
, idef
->iparams_posres_nalloc
);
787 for (i
= i0
; i
< i1
; i
++)
789 ip
= &idef
->iparams_posres
[i
];
790 /* Copy the force constants */
791 *ip
= idef
->iparams
[il
->iatoms
[i
*2]];
792 a_molb
= il
->iatoms
[i
*2+1] - a_offset
;
793 if (molb
->posres_xA
.empty())
795 gmx_incons("Position restraint coordinates are missing");
797 ip
->posres
.pos0A
[XX
] = molb
->posres_xA
[a_molb
][XX
];
798 ip
->posres
.pos0A
[YY
] = molb
->posres_xA
[a_molb
][YY
];
799 ip
->posres
.pos0A
[ZZ
] = molb
->posres_xA
[a_molb
][ZZ
];
800 if (!molb
->posres_xB
.empty())
802 ip
->posres
.pos0B
[XX
] = molb
->posres_xB
[a_molb
][XX
];
803 ip
->posres
.pos0B
[YY
] = molb
->posres_xB
[a_molb
][YY
];
804 ip
->posres
.pos0B
[ZZ
] = molb
->posres_xB
[a_molb
][ZZ
];
808 ip
->posres
.pos0B
[XX
] = ip
->posres
.pos0A
[XX
];
809 ip
->posres
.pos0B
[YY
] = ip
->posres
.pos0A
[YY
];
810 ip
->posres
.pos0B
[ZZ
] = ip
->posres
.pos0A
[ZZ
];
812 /* Set the parameter index for idef->iparams_posre */
817 static void set_fbposres_params(t_idef
*idef
, const gmx_molblock_t
*molb
,
818 int i0
, int a_offset
)
824 il
= &idef
->il
[F_FBPOSRES
];
826 idef
->iparams_fbposres_nalloc
= i1
;
827 srenew(idef
->iparams_fbposres
, idef
->iparams_fbposres_nalloc
);
828 for (i
= i0
; i
< i1
; i
++)
830 ip
= &idef
->iparams_fbposres
[i
];
831 /* Copy the force constants */
832 *ip
= idef
->iparams
[il
->iatoms
[i
*2]];
833 a_molb
= il
->iatoms
[i
*2+1] - a_offset
;
834 if (molb
->posres_xA
.empty())
836 gmx_incons("Position restraint coordinates are missing");
838 /* Take flat-bottom posres reference from normal position restraints */
839 ip
->fbposres
.pos0
[XX
] = molb
->posres_xA
[a_molb
][XX
];
840 ip
->fbposres
.pos0
[YY
] = molb
->posres_xA
[a_molb
][YY
];
841 ip
->fbposres
.pos0
[ZZ
] = molb
->posres_xA
[a_molb
][ZZ
];
842 /* Note: no B-type for flat-bottom posres */
844 /* Set the parameter index for idef->iparams_posre */
849 /*! \brief Copy idef structure from mtop.
851 * Makes a deep copy of an idef data structure from a gmx_mtop_t.
852 * Used to initialize legacy topology types.
854 * \param[in] mtop Reference to input mtop.
855 * \param[in] idef Pointer to idef to populate.
856 * \param[in] mergeConstr Decide if constraints will be merged.
857 * \param[in] freeEnergyInteractionsAtEnd Decide if free energy stuff should
858 * be added at the end.
860 static void copyIdefFromMtop(const gmx_mtop_t
&mtop
,
862 bool freeEnergyInteractionsAtEnd
,
865 const gmx_ffparams_t
*ffp
= &mtop
.ffparams
;
867 idef
->ntypes
= ffp
->numTypes();
868 idef
->atnr
= ffp
->atnr
;
869 /* we can no longer copy the pointers to the mtop members,
870 * because they will become invalid as soon as mtop gets free'd.
871 * We also need to make sure to only operate on valid data!
874 if (!ffp
->functype
.empty())
876 snew(idef
->functype
, ffp
->functype
.size());
877 std::copy(ffp
->functype
.data(), ffp
->functype
.data() + ffp
->functype
.size(), idef
->functype
);
881 idef
->functype
= nullptr;
883 if (!ffp
->iparams
.empty())
885 snew(idef
->iparams
, ffp
->iparams
.size());
886 std::copy(ffp
->iparams
.data(), ffp
->iparams
.data() + ffp
->iparams
.size(), idef
->iparams
);
890 idef
->iparams
= nullptr;
892 idef
->iparams_posres
= nullptr;
893 idef
->iparams_posres_nalloc
= 0;
894 idef
->iparams_fbposres
= nullptr;
895 idef
->iparams_fbposres_nalloc
= 0;
896 idef
->fudgeQQ
= ffp
->fudgeQQ
;
897 idef
->cmap_grid
= new gmx_cmap_t
;
898 *idef
->cmap_grid
= ffp
->cmap_grid
;
899 idef
->ilsort
= ilsortUNKNOWN
;
901 for (int ftype
= 0; ftype
< F_NRE
; ftype
++)
903 idef
->il
[ftype
].nr
= 0;
904 idef
->il
[ftype
].nalloc
= 0;
905 idef
->il
[ftype
].iatoms
= nullptr;
909 for (const gmx_molblock_t
&molb
: mtop
.molblock
)
911 const gmx_moltype_t
&molt
= mtop
.moltype
[molb
.type
];
913 int srcnr
= molt
.atoms
.nr
;
916 int nposre_old
= idef
->il
[F_POSRES
].nr
;
917 int nfbposre_old
= idef
->il
[F_FBPOSRES
].nr
;
918 for (int ftype
= 0; ftype
< F_NRE
; ftype
++)
921 ftype
== F_CONSTR
&& molt
.ilist
[F_CONSTRNC
].size() > 0)
923 /* Merge all constrains into one ilist.
924 * This simplifies the constraint code.
926 for (int mol
= 0; mol
< molb
.nmol
; mol
++)
928 ilistcat(ftype
, &idef
->il
[F_CONSTR
], molt
.ilist
[F_CONSTR
],
929 1, destnr
+ mol
*srcnr
, srcnr
);
930 ilistcat(ftype
, &idef
->il
[F_CONSTR
], molt
.ilist
[F_CONSTRNC
],
931 1, destnr
+ mol
*srcnr
, srcnr
);
934 else if (!(mergeConstr
&& ftype
== F_CONSTRNC
))
936 ilistcat(ftype
, &idef
->il
[ftype
], molt
.ilist
[ftype
],
937 molb
.nmol
, destnr
, srcnr
);
940 if (idef
->il
[F_POSRES
].nr
> nposre_old
)
942 /* Executing this line line stops gmxdump -sys working
943 * correctly. I'm not aware there's an elegant fix. */
944 set_posres_params(idef
, &molb
, nposre_old
/2, natoms
);
946 if (idef
->il
[F_FBPOSRES
].nr
> nfbposre_old
)
948 set_fbposres_params(idef
, &molb
, nfbposre_old
/2, natoms
);
951 natoms
+= molb
.nmol
*srcnr
;
954 if (mtop
.bIntermolecularInteractions
)
956 for (int ftype
= 0; ftype
< F_NRE
; ftype
++)
958 ilistcat(ftype
, &idef
->il
[ftype
], (*mtop
.intermolecular_ilist
)[ftype
],
963 if (freeEnergyInteractionsAtEnd
&& gmx_mtop_bondeds_free_energy(&mtop
))
965 std::vector
<real
> qA(mtop
.natoms
);
966 std::vector
<real
> qB(mtop
.natoms
);
967 gmx_mtop_atomloop_all_t aloop
= gmx_mtop_atomloop_all_init(&mtop
);
970 while (gmx_mtop_atomloop_all_next(aloop
, &ag
, &atom
))
975 gmx_sort_ilist_fe(idef
, qA
.data(), qB
.data());
979 idef
->ilsort
= ilsortNO_FE
;
983 /*! \brief Copy atomtypes from mtop
985 * Makes a deep copy of t_atomtypes from gmx_mtop_t.
986 * Used to initialize legacy topology types.
988 * \param[in] mtop Reference to input mtop.
989 * \param[in] atomtypes Pointer to atomtypes to populate.
991 static void copyAtomtypesFromMtop(const gmx_mtop_t
&mtop
,
992 t_atomtypes
*atomtypes
)
994 atomtypes
->nr
= mtop
.atomtypes
.nr
;
995 if (mtop
.atomtypes
.atomnumber
)
997 snew(atomtypes
->atomnumber
, mtop
.atomtypes
.nr
);
998 std::copy(mtop
.atomtypes
.atomnumber
, mtop
.atomtypes
.atomnumber
+ mtop
.atomtypes
.nr
, atomtypes
->atomnumber
);
1002 atomtypes
->atomnumber
= nullptr;
1006 /*! \brief Copy cgs from mtop.
1008 * Makes a deep copy of cgs(t_block) from gmx_mtop_t.
1009 * Used to initialize legacy topology types.
1011 * \param[in] mtop Reference to input mtop.
1012 * \param[in] cgs Pointer to final cgs data structure.
1014 static void copyCgsFromMtop(const gmx_mtop_t
&mtop
,
1018 for (const gmx_molblock_t
&molb
: mtop
.molblock
)
1020 const gmx_moltype_t
&molt
= mtop
.moltype
[molb
.type
];
1021 blockcat(cgs
, &molt
.cgs
, molb
.nmol
);
1025 /*! \brief Copy excls from mtop.
1027 * Makes a deep copy of excls(t_blocka) from gmx_mtop_t.
1028 * Used to initialize legacy topology types.
1030 * \param[in] mtop Reference to input mtop.
1031 * \param[in] excls Pointer to final excls data structure.
1033 static void copyExclsFromMtop(const gmx_mtop_t
&mtop
,
1038 for (const gmx_molblock_t
&molb
: mtop
.molblock
)
1040 const gmx_moltype_t
&molt
= mtop
.moltype
[molb
.type
];
1042 int srcnr
= molt
.atoms
.nr
;
1043 int destnr
= natoms
;
1045 blockacat(excls
, &molt
.excls
, molb
.nmol
, destnr
, srcnr
);
1047 natoms
+= molb
.nmol
*srcnr
;
1051 /*! \brief Updates inter-molecular exclusion lists
1053 * This function updates inter-molecular exclusions to exclude all
1054 * non-bonded interactions between a given list of atoms
1056 * \param[inout] excls existing exclusions in local topology
1057 * \param[in] ids list of global IDs of atoms
1059 static void addMimicExclusions(t_blocka
*excls
,
1060 const gmx::ArrayRef
<const int> ids
)
1062 t_blocka inter_excl
{};
1063 init_blocka(&inter_excl
);
1064 size_t n_q
= ids
.size();
1066 inter_excl
.nr
= excls
->nr
;
1067 inter_excl
.nra
= n_q
* n_q
;
1069 size_t total_nra
= n_q
* n_q
;
1071 snew(inter_excl
.index
, excls
->nr
+ 1);
1072 snew(inter_excl
.a
, total_nra
);
1074 for (int i
= 0; i
< excls
->nr
; ++i
)
1076 inter_excl
.index
[i
] = 0;
1079 /* Here we loop over the list of QM atom ids
1080 * and create exclusions between all of them resulting in
1081 * n_q * n_q sized exclusion list
1084 for (int k
= 0; k
< inter_excl
.nr
; ++k
)
1086 inter_excl
.index
[k
] = prev_index
;
1087 for (long i
= 0; i
< ids
.size(); i
++)
1093 size_t index
= n_q
* i
;
1094 inter_excl
.index
[ids
[i
]] = index
;
1095 prev_index
= index
+ n_q
;
1096 for (size_t j
= 0; j
< n_q
; ++j
)
1098 inter_excl
.a
[n_q
* i
+ j
] = ids
[j
];
1102 inter_excl
.index
[ids
[n_q
- 1] + 1] = n_q
* n_q
;
1104 inter_excl
.index
[inter_excl
.nr
] = n_q
* n_q
;
1106 gmx::ExclusionBlocks qmexcl2
{};
1107 initExclusionBlocks(&qmexcl2
, excls
->nr
);
1108 gmx::blockaToExclusionBlocks(&inter_excl
, &qmexcl2
);
1110 // Merge the created exclusion list with the existing one
1111 gmx::mergeExclusions(excls
, &qmexcl2
);
1112 gmx::doneExclusionBlocks(&qmexcl2
);
1115 static void gen_local_top(const gmx_mtop_t
&mtop
,
1116 bool freeEnergyInteractionsAtEnd
,
1118 gmx_localtop_t
*top
)
1120 copyAtomtypesFromMtop(mtop
, &top
->atomtypes
);
1121 copyIdefFromMtop(mtop
, &top
->idef
, freeEnergyInteractionsAtEnd
, bMergeConstr
);
1122 copyCgsFromMtop(mtop
, &top
->cgs
);
1123 copyExclsFromMtop(mtop
, &top
->excls
);
1124 if (!mtop
.intermolecularExclusionGroup
.empty())
1126 addMimicExclusions(&top
->excls
,
1127 mtop
.intermolecularExclusionGroup
);
1132 gmx_mtop_generate_local_top(const gmx_mtop_t
*mtop
,
1133 bool freeEnergyInteractionsAtEnd
)
1135 gmx_localtop_t
*top
;
1139 gen_local_top(*mtop
, freeEnergyInteractionsAtEnd
, true, top
);
1144 /*! \brief Fills an array with molecule begin/end atom indices
1146 * \param[in] mtop The global topology
1147 * \param[out] index Array of size nr. of molecules + 1 to be filled with molecule begin/end indices
1149 static void fillMoleculeIndices(const gmx_mtop_t
&mtop
,
1150 gmx::ArrayRef
<int> index
)
1152 int globalAtomIndex
= 0;
1153 int globalMolIndex
= 0;
1154 index
[globalMolIndex
] = globalAtomIndex
;
1155 for (const gmx_molblock_t
&molb
: mtop
.molblock
)
1157 int numAtomsPerMolecule
= mtop
.moltype
[molb
.type
].atoms
.nr
;
1158 for (int mol
= 0; mol
< molb
.nmol
; mol
++)
1160 globalAtomIndex
+= numAtomsPerMolecule
;
1161 globalMolIndex
+= 1;
1162 index
[globalMolIndex
] = globalAtomIndex
;
1167 gmx::RangePartitioning
gmx_mtop_molecules(const gmx_mtop_t
&mtop
)
1169 gmx::RangePartitioning mols
;
1171 for (const gmx_molblock_t
&molb
: mtop
.molblock
)
1173 int numAtomsPerMolecule
= mtop
.moltype
[molb
.type
].atoms
.nr
;
1174 for (int mol
= 0; mol
< molb
.nmol
; mol
++)
1176 mols
.appendBlock(numAtomsPerMolecule
);
1183 /*! \brief Creates and returns a deprecated t_block struct with molecule indices
1185 * \param[in] mtop The global topology
1187 static t_block
gmx_mtop_molecules_t_block(const gmx_mtop_t
&mtop
)
1191 mols
.nr
= gmx_mtop_num_molecules(mtop
);
1192 mols
.nalloc_index
= mols
.nr
+ 1;
1193 snew(mols
.index
, mols
.nalloc_index
);
1195 fillMoleculeIndices(mtop
, gmx::arrayRefFromArray(mols
.index
, mols
.nr
+ 1));
1200 static void gen_t_topology(const gmx_mtop_t
&mtop
,
1201 bool freeEnergyInteractionsAtEnd
,
1205 copyAtomtypesFromMtop(mtop
, &top
->atomtypes
);
1206 copyIdefFromMtop(mtop
, &top
->idef
, freeEnergyInteractionsAtEnd
, bMergeConstr
);
1207 copyCgsFromMtop(mtop
, &top
->cgs
);
1208 copyExclsFromMtop(mtop
, &top
->excls
);
1210 top
->name
= mtop
.name
;
1211 top
->atoms
= gmx_mtop_global_atoms(&mtop
);
1212 top
->mols
= gmx_mtop_molecules_t_block(mtop
);
1213 top
->bIntermolecularInteractions
= mtop
.bIntermolecularInteractions
;
1214 top
->symtab
= mtop
.symtab
;
1217 t_topology
gmx_mtop_t_to_t_topology(gmx_mtop_t
*mtop
, bool freeMTop
)
1221 gen_t_topology(*mtop
, false, false, &top
);
1225 // Clear pointers and counts, such that the pointers copied to top
1226 // keep pointing to valid data after destroying mtop.
1227 mtop
->symtab
.symbuf
= nullptr;
1228 mtop
->symtab
.nr
= 0;
1233 std::vector
<int> get_atom_index(const gmx_mtop_t
*mtop
)
1236 std::vector
<int> atom_index
;
1237 gmx_mtop_atomloop_block_t aloopb
= gmx_mtop_atomloop_block_init(mtop
);
1240 while (gmx_mtop_atomloop_block_next(aloopb
, &atom
, &nmol
))
1242 if (atom
->ptype
== eptAtom
)
1244 atom_index
.push_back(j
);
1251 void convertAtomsToMtop(t_symtab
*symtab
,
1256 mtop
->symtab
= *symtab
;
1260 mtop
->moltype
.clear();
1261 mtop
->moltype
.resize(1);
1262 mtop
->moltype
.back().atoms
= *atoms
;
1264 mtop
->molblock
.resize(1);
1265 mtop
->molblock
[0].type
= 0;
1266 mtop
->molblock
[0].nmol
= 1;
1268 mtop
->bIntermolecularInteractions
= FALSE
;
1270 mtop
->natoms
= atoms
->nr
;
1272 mtop
->haveMoleculeIndices
= false;
1274 gmx_mtop_finalize(mtop
);