3 * This source code is part of
7 * GROningen MAchine for Chemical Simulations
9 * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
10 * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
11 * Copyright (c) 2001-2009, The GROMACS development team,
12 * check out http://www.gromacs.org for more information.
14 * This program is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU General Public License
16 * as published by the Free Software Foundation; either version 2
17 * of the License, or (at your option) any later version.
19 * If you want to redistribute modifications, please consider that
20 * scientific software is very special. Version control is crucial -
21 * bugs must be traceable. We will be happy to consider code for
22 * inclusion in the official distribution, but derived work must not
23 * be called official GROMACS. Details are found in the README & COPYING
24 * files - if they are missing, get the official version at www.gromacs.org.
26 * To help us fund GROMACS development, we humbly ask that you cite
27 * the papers on the package - you can find them in the top README file.
29 * For more info, check our website at http://www.gromacs.org
32 * \brief Implementation of functions in centerofmass.h.
42 #include <centerofmass.h>
45 * \param[in] top Topology structure (unused, can be NULL).
46 * \param[in] x Position vectors of all atoms.
47 * \param[in] nrefat Number of atoms in the index.
48 * \param[in] index Indices of atoms.
49 * \param[out] xout COG position for the indexed atoms.
50 * \returns 0 on success.
53 gmx_calc_cog(t_topology
*top
, rvec x
[], int nrefat
, atom_id index
[], rvec xout
)
58 for (m
= 0; m
< nrefat
; ++m
)
61 rvec_inc(xout
, x
[ai
]);
63 svmul(1.0/nrefat
, xout
, xout
);
68 * \param[in] top Topology structure with masses.
69 * \param[in] x Position vectors of all atoms.
70 * \param[in] nrefat Number of atoms in the index.
71 * \param[in] index Indices of atoms.
72 * \param[out] xout COM position for the indexed atoms.
73 * \returns 0 on success, EINVAL if \p top is NULL.
75 * Works exactly as gmx_calc_cog() with the exception that a center of
76 * mass are calculated, and hence a topology with masses is required.
79 gmx_calc_com(t_topology
*top
, rvec x
[], int nrefat
, atom_id index
[], rvec xout
)
86 gmx_incons("no masses available while mass weighting was requested");
91 for (m
= 0; m
< nrefat
; ++m
)
94 mass
= top
->atoms
.atom
[ai
].m
;
95 for (j
= 0; j
< DIM
; ++j
)
97 xout
[j
] += mass
* x
[ai
][j
];
101 svmul(1.0/mtot
, xout
, xout
);
106 * \param[in] top Topology structure with masses
107 * (can be NULL if \p bMASS==FALSE).
108 * \param[in] x Position vectors of all atoms.
109 * \param[in] nrefat Number of atoms in the index.
110 * \param[in] index Indices of atoms.
111 * \param[in] bMass If TRUE, mass weighting is used.
112 * \param[out] xout COM/COG position for the indexed atoms.
113 * \returns 0 on success, EINVAL if \p top is NULL and \p bMass is TRUE.
115 * Calls either gmx_calc_com() or gmx_calc_cog() depending on the value of
117 * Other parameters are passed unmodified to these functions.
120 gmx_calc_comg(t_topology
*top
, rvec x
[], int nrefat
, atom_id index
[],
121 bool bMass
, rvec xout
)
125 return gmx_calc_com(top
, x
, nrefat
, index
, xout
);
129 return gmx_calc_cog(top
, x
, nrefat
, index
, xout
);
135 * \param[in] top Topology structure (unused, can be NULL).
136 * \param[in] x Position vectors of all atoms.
137 * \param[in] pbc Periodic boundary conditions structure.
138 * \param[in] nrefat Number of atoms in the index.
139 * \param[in] index Indices of atoms.
140 * \param[out] xout COG position for the indexed atoms.
141 * \returns 0 on success.
143 * Works exactly as gmx_calc_com_pbc(), but calculates the center of geometry.
146 gmx_calc_cog_pbc(t_topology
*top
, rvec x
[], t_pbc
*pbc
,
147 int nrefat
, atom_id index
[], rvec xout
)
149 const real tol
= 1e-4;
154 /* First simple calculation */
155 gmx_calc_cog(top
, x
, nrefat
, index
, xout
);
156 /* Now check if any atom is more than half the box from the COM */
163 for (m
= 0; m
< nrefat
; ++m
)
166 pbc_dx(pbc
, x
[ai
], xout
, dx
);
167 rvec_add(xout
, dx
, xtest
);
168 for (j
= 0; j
< DIM
; ++j
)
170 if (fabs(xtest
[j
] - x
[ai
][j
]) > tol
)
172 /* Here we have used the wrong image for contributing to the COM */
173 xout
[j
] += (xtest
[j
] - x
[ai
][j
]) / nrefat
;
187 * \param[in] top Topology structure with masses.
188 * \param[in] x Position vectors of all atoms.
189 * \param[in] pbc Periodic boundary conditions structure.
190 * \param[in] nrefat Number of atoms in the index.
191 * \param[in] index Indices of atoms.
192 * \param[out] xout COM position for the indexed atoms.
193 * \returns 0 on success, EINVAL if \p top is NULL.
195 * Works as gmx_calc_com(), but takes into account periodic boundary
196 * conditions: If any atom is more than half the box from the COM,
197 * it is wrapped around and a new COM is calculated. This is repeated
198 * until no atoms violate the condition.
200 * Modified from src/tools/gmx_sorient.c in Gromacs distribution.
203 gmx_calc_com_pbc(t_topology
*top
, rvec x
[], t_pbc
*pbc
,
204 int nrefat
, atom_id index
[], rvec xout
)
206 const real tol
= 1e-4;
214 gmx_incons("no masses available while mass weighting was requested");
217 /* First simple calculation */
220 for (m
= 0; m
< nrefat
; ++m
)
223 mass
= top
->atoms
.atom
[ai
].m
;
224 for (j
= 0; j
< DIM
; ++j
)
226 xout
[j
] += mass
* x
[ai
][j
];
230 svmul(1.0/mtot
, xout
, xout
);
231 /* Now check if any atom is more than half the box from the COM */
238 for (m
= 0; m
< nrefat
; ++m
)
241 mass
= top
->atoms
.atom
[ai
].m
/ mtot
;
242 pbc_dx(pbc
, x
[ai
], xout
, dx
);
243 rvec_add(xout
, dx
, xtest
);
244 for (j
= 0; j
< DIM
; ++j
)
246 if (fabs(xtest
[j
] - x
[ai
][j
]) > tol
)
248 /* Here we have used the wrong image for contributing to the COM */
249 xout
[j
] += mass
* (xtest
[j
] - x
[ai
][j
]);
263 * \param[in] top Topology structure with masses
264 * (can be NULL if \p bMASS==FALSE).
265 * \param[in] x Position vectors of all atoms.
266 * \param[in] pbc Periodic boundary conditions structure.
267 * \param[in] nrefat Number of atoms in the index.
268 * \param[in] index Indices of atoms.
269 * \param[in] bMass If TRUE, mass weighting is used.
270 * \param[out] xout COM/COG position for the indexed atoms.
271 * \returns 0 on success, EINVAL if \p top is NULL and \p bMass is TRUE.
273 * Calls either gmx_calc_com() or gmx_calc_cog() depending on the value of
275 * Other parameters are passed unmodified to these functions.
278 gmx_calc_comg_pbc(t_topology
*top
, rvec x
[], t_pbc
*pbc
,
279 int nrefat
, atom_id index
[], bool bMass
, rvec xout
)
283 return gmx_calc_com_pbc(top
, x
, pbc
, nrefat
, index
, xout
);
287 return gmx_calc_cog_pbc(top
, x
, pbc
, nrefat
, index
, xout
);
293 * \param[in] top Topology structure (unused, can be NULL).
294 * \param[in] x Position vectors of all atoms.
295 * \param[in] block t_block structure that divides \p index into blocks.
296 * \param[in] index Indices of atoms.
297 * \param[out] xout \p block->nr COG positions.
298 * \returns 0 on success.
301 gmx_calc_cog_block(t_topology
*top
, rvec x
[], t_block
*block
, atom_id index
[],
307 for (b
= 0; b
< block
->nr
; ++b
)
310 for (i
= block
->index
[b
]; i
< block
->index
[b
+1]; ++i
)
315 svmul(1.0/(block
->index
[b
+1] - block
->index
[b
]), xb
, xout
[b
]);
321 * \param[in] top Topology structure with masses.
322 * \param[in] x Position vectors of all atoms.
323 * \param[in] block t_block structure that divides \p index into blocks.
324 * \param[in] index Indices of atoms.
325 * \param[out] xout \p block->nr COM positions.
326 * \returns 0 on success, EINVAL if \p top is NULL.
328 * Works exactly as gmx_calc_cog_block() with the exception that centers of
329 * mass are calculated, and hence a topology with masses is required.
332 gmx_calc_com_block(t_topology
*top
, rvec x
[], t_block
*block
, atom_id index
[],
341 gmx_incons("no masses available while mass weighting was requested");
344 for (b
= 0; b
< block
->nr
; ++b
)
348 for (i
= block
->index
[b
]; i
< block
->index
[b
+1]; ++i
)
351 mass
= top
->atoms
.atom
[ai
].m
;
352 for (d
= 0; d
< DIM
; ++d
)
354 xb
[d
] += mass
* x
[ai
][d
];
358 svmul(1.0/mtot
, xb
, xout
[b
]);
364 * \param[in] top Topology structure with masses
365 * (can be NULL if \p bMASS==FALSE).
366 * \param[in] x Position vectors of all atoms.
367 * \param[in] block t_block structure that divides \p index into blocks.
368 * \param[in] index Indices of atoms.
369 * \param[in] bMass If TRUE, mass weighting is used.
370 * \param[out] xout \p block->nr COM/COG positions.
371 * \returns 0 on success, EINVAL if \p top is NULL and \p bMass is TRUE.
373 * Calls either gmx_calc_com_block() or gmx_calc_cog_block() depending on the
375 * Other parameters are passed unmodified to these functions.
378 gmx_calc_comg_block(t_topology
*top
, rvec x
[], t_block
*block
, atom_id index
[],
379 bool bMass
, rvec xout
[])
383 return gmx_calc_com_block(top
, x
, block
, index
, xout
);
387 return gmx_calc_cog_block(top
, x
, block
, index
, xout
);
392 * \param[in] top Topology structure with masses
393 * (can be NULL if \p bMASS==FALSE).
394 * \param[in] x Position vectors of all atoms.
395 * \param[in] block Blocks for calculation.
396 * \param[in] bMass If TRUE, mass weighting is used.
397 * \param[out] xout \p block->nr COM/COG positions.
398 * \returns 0 on success, EINVAL if \p top is NULL and \p bMass is TRUE.
400 * Calls gmx_calc_comg_block(), converting the \p t_blocka structure into
401 * a \p t_block and an index. Other parameters are passed unmodified.
404 * This function assumes that a pointer to \c t_blocka can be safely typecast
405 * into \c t_block such that the index fields can still be referenced.
406 * With the present Gromacs defitions of these types, this is the case,
407 * but if the layout of these structures is changed, this may lead to strange
411 gmx_calc_comg_blocka(t_topology
*top
, rvec x
[], t_blocka
*block
,
412 bool bMass
, rvec xout
[])
414 /* TODO: It would probably be better to do this without the type cast */
415 return gmx_calc_comg_block(top
, x
, (t_block
*)block
, block
->a
, bMass
, xout
);