3 * This source code is part of
7 * GROningen MAchine for Chemical Simulations
10 * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
11 * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
12 * Copyright (c) 2001-2004, The GROMACS development team,
13 * check out http://www.gromacs.org for more information.
15 * This program is free software; you can redistribute it and/or
16 * modify it under the terms of the GNU General Public License
17 * as published by the Free Software Foundation; either version 2
18 * of the License, or (at your option) any later version.
20 * If you want to redistribute modifications, please consider that
21 * scientific software is very special. Version control is crucial -
22 * bugs must be traceable. We will be happy to consider code for
23 * inclusion in the official distribution, but derived work must not
24 * be called official GROMACS. Details are found in the README & COPYING
25 * files - if they are missing, get the official version at www.gromacs.org.
27 * To help us fund GROMACS development, we humbly ask that you cite
28 * the papers on the package - you can find them in the top README file.
30 * For more info, check our website at http://www.gromacs.org
33 * GROningen Mixture of Alchemy and Childrens' Stories
35 /* This file is completely threadsafe - keep it that way! */
43 #include "gmx_fatal.h"
48 static real dist2(t_pbc *pbc,rvec x,rvec y)
57 real distance_to_z(rvec x)
59 return (sqr(x[XX])+sqr(x[YY]));
62 static void low_rotate_conf(int natom,rvec *x,real alfa, real beta,real gamma)
67 for (i=0; i<natom; i++) {
68 copy_rvec(x[i],x_old);
69 /*calculate new x[i] by rotation alfa around the x-axis*/
71 x[i][YY]= cos(alfa)*x_old[YY] - sin(alfa)*x_old[ZZ];
72 x[i][ZZ]= sin(alfa)*x_old[YY] + cos(alfa)*x_old[ZZ];
73 copy_rvec(x[i],x_old);
74 /*calculate new x[i] by rotation beta around the y-axis*/
75 x[i][XX]= cos(beta)*x_old[XX] + sin(beta)*x_old[ZZ];
77 x[i][ZZ]= - sin(beta)*x_old[XX] + cos(beta)*x_old[ZZ];
78 copy_rvec(x[i],x_old);
79 /*calculate new x[i] by rotation gamma around the z-axis*/
80 x[i][XX]= x_old[XX]*cos(gamma) - x_old[YY]*sin(gamma);
81 x[i][YY]= x_old[XX]*sin(gamma) + x_old[YY]*cos(gamma);
86 static void low_rotate_conf_indexed(int nindex,atom_id *index,rvec *x,real alfa, real beta,real gamma)
91 for (i=0; i<nindex; i++) {
92 copy_rvec(x[index[i]],x_old);
93 /*calculate new x[index[i]] by rotation alfa around the x-axis*/
94 x[index[i]][XX]= x_old[XX];
95 x[index[i]][YY]= cos(alfa)*x_old[YY] - sin(alfa)*x_old[ZZ];
96 x[index[i]][ZZ]= sin(alfa)*x_old[YY] + cos(alfa)*x_old[ZZ];
97 copy_rvec(x[index[i]],x_old);
98 /*calculate new x[index[i]] by rotation beta around the y-axis*/
99 x[index[i]][XX]= cos(beta)*x_old[XX] + sin(beta)*x_old[ZZ];
100 x[index[i]][YY]= x_old[YY];
101 x[index[i]][ZZ]= - sin(beta)*x_old[XX] + cos(beta)*x_old[ZZ];
102 copy_rvec(x[index[i]],x_old);
103 /*calculate new x[index[i]] by rotation gamma around the z-axis*/
104 x[index[i]][XX]= x_old[XX]*cos(gamma) - x_old[YY]*sin(gamma);
105 x[index[i]][YY]= x_old[XX]*sin(gamma) + x_old[YY]*cos(gamma);
106 x[index[i]][ZZ]= x_old[ZZ];
110 void rotate_conf(int natom,rvec *x,rvec *v,real alfa, real beta,real gamma)
113 low_rotate_conf(natom,x,alfa,beta,gamma);
115 low_rotate_conf(natom,v,alfa,beta,gamma);
118 void rotate_conf_indexed(int nindex,atom_id *index,rvec *x,rvec *v,real alfa, real beta,real gamma)
121 low_rotate_conf_indexed(nindex,index,x,alfa,beta,gamma);
123 low_rotate_conf_indexed(nindex,index,v,alfa,beta,gamma);
126 void orient(int natom,rvec *x,rvec *v, rvec angle,matrix box)
128 real longest,rij,rzi;
129 int i,j,m,max_i=0,max_j=0;
132 real alfa=0,beta=0,gamma=0;
135 set_pbc(&pbc,-1,box);
137 /*first i am going to look for the longest atom-atom distance*/
138 longest=dist2(&pbc,x[0],x[1]);
141 for (i=0;(i<natom);i++) {
142 for (j=0;(j<natom);j++) {
143 rij=dist2(&pbc,x[i],x[j]);
151 /* first check if x[max_i]<x[max_j] else swap*/
152 if (x[max_i][2]>x[max_j][2]) {
158 /*set the origin to x[i]*/
160 origin[m]=x[max_i][m];
161 for(i=0;(i<natom);i++)
165 /* calculate the rotation angles alfa(x_axis) and beta(y_axis)
166 * the rotation angles must be calculated clockwise looking
167 * along the rotation axis to the origin*
170 alfa=atan(x[max_j][ZZ]/x[max_j][YY])-M_PI_2;
171 beta=M_PI_2-atan(x[max_j][ZZ]/x[max_j][XX]);
172 rotate_conf(natom,x,v,alfa,beta,gamma);
174 /* now search the longest distance for rotation along the z_axis */
175 longest=distance_to_z(x[0]);
177 for (i=1;(i<natom);i++) {
178 rzi=distance_to_z(x[i]);
184 gamma=atan(x[max_i][YY]/x[max_i][XX])-M_PI_2;
185 rotate_conf(natom,x,v,0,0,gamma);
192 void genconf(t_atoms *atoms,rvec *x,rvec *v,real *r,matrix box,ivec n_box)
194 int i,ix,iy,iz,m,j,imol,offset;
198 nmol=n_box[XX]*n_box[YY]*n_box[ZZ];
201 fprintf(stderr,"Generating configuration\n");
203 for(ix=0; (ix < n_box[XX]); ix++) {
204 delta[XX]=ix*box[XX][XX];
205 for(iy=0; (iy < n_box[YY]); iy++) {
206 delta[YY]=iy*box[YY][YY];
207 for(iz=0; (iz < n_box[ZZ]); iz++) {
208 delta[ZZ]=iz*box[ZZ][ZZ];
209 offset=imol*atoms->nr;
210 for (i=0;(i < atoms->nr);i++) {
211 for (m=0;(m < DIM);m++)
212 x[offset+i][m]=delta[m]+x[i][m];
214 for (m=0;(m < DIM);m++)
215 v[offset+i][m]=v[i][m];
222 for (i=1;(i<nmol);i++) {
223 int offs = i*atoms->nr;
224 int offsres = i*atoms->nres;
225 for (j=0;(j<atoms->nr);j++) {
226 atoms->atomname[offs+j] = atoms->atomname[j];
227 atoms->atom[offs+j].resind = atoms->atom[j].resind + offsres;
228 atoms->resinfo[atoms->atom[offs+j].resind] =
229 atoms->resinfo[atoms->atom[j].resind];
230 atoms->resinfo[atoms->atom[offs+j].resind].nr += offsres;
240 /*gen_box() generates a box around a configuration*/
241 void gen_box(int NTB,int natoms,rvec *x, matrix box,rvec box_space,
248 /*calculate minimum and maximum x[0..DIM-1]*/
249 for (m=0;(m<DIM);m++)
250 xmin[m]=xmax[m]=x[0][m];
251 for (i=1;(i < natoms); i++)
252 for (m=0;m<DIM;m++) {
253 xmin[m]=min(xmin[m],x[i][m]);
254 xmax[m]=max(xmax[m],x[i][m]);
257 /*calculate the new box sizes for cubic and octahedral ...*/
258 for (m=0; (m<DIM);m++)
259 box[m][m]=xmax[m]-xmin[m]+2*box_space[m];
261 /*calculate the box size if NTB=1 (truncated octahedron)*/
265 max_box=max(max_box,box[m][m]);
266 for (m=0;(m<DIM);m++)
270 /*move the molecule to the center of the box*/
272 for(i=0;(i<natoms);i++)
273 for (m=0;(m<DIM);m++) {
274 x[i][m]+=0.5*(box[m][m]-xmin[m]-xmax[m]);
279 /* print data to check this */
280 print_stat(x,natoms,box);