Updated selection documentation.
[gromacs/qmmm-gamess-us.git] / src / gmxlib / trajana / centerofmass.c
blobf05e4049af131db39965ff34c8e36cbd8cfcc649
1 /*
3 * This source code is part of
5 * G R O M A C S
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
31 /*! \internal \file
32 * \brief Implementation of functions in centerofmass.h.
34 #ifdef HAVE_CONFIG_H
35 #include <config.h>
36 #endif
38 #include <typedefs.h>
39 #include <pbc.h>
40 #include <vec.h>
42 #include <centerofmass.h>
44 /*!
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.
52 int
53 gmx_calc_cog(t_topology *top, rvec x[], int nrefat, atom_id index[], rvec xout)
55 int m, j, ai;
57 clear_rvec(xout);
58 for (m = 0; m < nrefat; ++m)
60 ai = index[m];
61 rvec_inc(xout, x[ai]);
63 svmul(1.0/nrefat, xout, xout);
64 return 0;
67 /*!
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.
78 int
79 gmx_calc_com(t_topology *top, rvec x[], int nrefat, atom_id index[], rvec xout)
81 int m, j, ai;
82 real mass, mtot;
84 if (!top)
86 gmx_incons("no masses available while mass weighting was requested");
87 return EINVAL;
89 clear_rvec(xout);
90 mtot = 0;
91 for (m = 0; m < nrefat; ++m)
93 ai = index[m];
94 mass = top->atoms.atom[ai].m;
95 for (j = 0; j < DIM; ++j)
97 xout[j] += mass * x[ai][j];
99 mtot += mass;
101 svmul(1.0/mtot, xout, xout);
102 return 0;
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
116 * \p bMass.
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)
123 if (bMass)
125 return gmx_calc_com(top, x, nrefat, index, xout);
127 else
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;
150 bool bChanged;
151 int m, j, ai, iter;
152 rvec dx, xtest;
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 */
157 if (pbc)
159 iter = 0;
162 bChanged = FALSE;
163 for (m = 0; m < nrefat; ++m)
165 ai = index[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;
174 x[ai][j] = xtest[j];
175 bChanged = TRUE;
179 iter++;
181 while (bChanged);
183 return 0;
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;
207 bool bChanged;
208 int m, j, ai, iter;
209 real mass, mtot;
210 rvec dx, xtest;
212 if (!top)
214 gmx_incons("no masses available while mass weighting was requested");
215 return EINVAL;
217 /* First simple calculation */
218 clear_rvec(xout);
219 mtot = 0;
220 for (m = 0; m < nrefat; ++m)
222 ai = index[m];
223 mass = top->atoms.atom[ai].m;
224 for (j = 0; j < DIM; ++j)
226 xout[j] += mass * x[ai][j];
228 mtot += mass;
230 svmul(1.0/mtot, xout, xout);
231 /* Now check if any atom is more than half the box from the COM */
232 if (pbc)
234 iter = 0;
237 bChanged = FALSE;
238 for (m = 0; m < nrefat; ++m)
240 ai = index[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]);
250 x[ai][j] = xtest[j];
251 bChanged = TRUE;
255 iter++;
257 while (bChanged);
259 return 0;
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
274 * \p bMass.
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)
281 if (bMass)
283 return gmx_calc_com_pbc(top, x, pbc, nrefat, index, xout);
285 else
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[],
302 rvec xout[])
304 int b, i, ai;
305 rvec xb;
307 for (b = 0; b < block->nr; ++b)
309 clear_rvec(xb);
310 for (i = block->index[b]; i < block->index[b+1]; ++i)
312 ai = index[i];
313 rvec_inc(xb, x[ai]);
315 svmul(1.0/(block->index[b+1] - block->index[b]), xb, xout[b]);
317 return 0;
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[],
333 rvec xout[])
335 int b, i, ai, d;
336 rvec xb;
337 real mass, mtot;
339 if (!top)
341 gmx_incons("no masses available while mass weighting was requested");
342 return EINVAL;
344 for (b = 0; b < block->nr; ++b)
346 clear_rvec(xb);
347 mtot = 0;
348 for (i = block->index[b]; i < block->index[b+1]; ++i)
350 ai = index[i];
351 mass = top->atoms.atom[ai].m;
352 for (d = 0; d < DIM; ++d)
354 xb[d] += mass * x[ai][d];
356 mtot += mass;
358 svmul(1.0/mtot, xb, xout[b]);
360 return 0;
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
374 * value of \p bMass.
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[])
381 if (bMass)
383 return gmx_calc_com_block(top, x, block, index, xout);
385 else
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.
403 * \attention
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
408 * crashes.
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);