4 * This source code is part of
8 * GROningen MAchine for Chemical Simulations
12 * Copyright (c) 1991-1999
13 * BIOSON Research Institute, Dept. of Biophysical Chemistry
14 * University of Groningen, The Netherlands
17 * GROMACS: A message-passing parallel molecular dynamics implementation
18 * H.J.C. Berendsen, D. van der Spoel and R. van Drunen
19 * Comp. Phys. Comm. 91, 43-56 (1995)
21 * Also check out our WWW page:
22 * http://md.chem.rug.nl/~gmx
27 * GRowing Old MAkes el Chrono Sweat
29 static char *SRCID_g_diffuse_c
= "$Id$";
48 void prepare_data(int gnx
,atom_id index
[],rvec xcur
[],rvec xprev
[],
54 /* Remove periodicity */
55 for(m
=0; (m
<DIM
); m
++)
56 hbox
[m
]=0.5*box
[m
][m
];
57 for(i
=0; (i
<gnx
); i
++) {
59 for(m
=0; (m
<DIM
); m
++) {
60 while(xcur
[ind
][m
]-xprev
[ind
][m
] <= hbox
[m
])
61 xcur
[ind
][m
] += box
[m
][m
];
62 while(xcur
[ind
][m
]-xprev
[ind
][m
] > hbox
[m
])
63 xcur
[ind
][m
] -= box
[m
][m
];
68 static real
calc_msd(rvec xref
[],int nx
,atom_id index
[],rvec x
[])
75 for(i
=0; (i
<nx
); i
++) {
77 rvec_sub(xref
[ind
],x
[ind
],dx
);
83 static void analyse_msd(char *xvg
,char *grpname
,
84 int nframes
,int nstart
,real
**msd
,real xtime
[],
89 int i
,j
,nj
,minj
,legind
;
90 real
*D
,*Dsq
,t0
,msd0
,D2
,DeltaD
;
97 sprintf(buf
,"Diffusion constant for %s",grpname
);
98 fp
=xvgropen(xvg
,buf
,"Time (ps)","D (cm\\S2\\Ns\\S-1\\N)");
100 for(i
=0; (i
<nstart
); i
++) {
104 for(j
=0; (j
<nframes
); j
++) {
106 msd
[i
][j
] *= 1000.0/(6*(xtime
[j
] - xtime
[0]));
107 if (msd
[i
][j
] == 0.0)
110 if ((xtime
[j
] >= bfit
) && (xtime
[j
] <= efit
)) {
112 Dsq
[i
] += sqr(msd
[i
][j
]);
116 legind
= (nstart
> 1) ? i
+1 : 0;
119 sprintf(buf
,"D%d = %.2f, N=%d",i
+1,D
[i
],nj
);
120 leg
[legind
] = strdup(buf
);
123 leg
[legind
] = strdup("No data!");
127 /* Compute average D */
131 for(i
=0; (i
<nstart
); i
++) {
137 DeltaD
= sqrt(D2
- sqr(D
[nstart
]));
138 fprintf(stderr
,"Dav = %.2f, RMS = %.2f\n",D
[nstart
],DeltaD
);
139 fprintf(fp
,"# Dav = %.2f, RMS = %.2f nstart = %d\n",D
[nstart
],DeltaD
,nstart
);
141 sprintf(buf
,"D\\sav\\N = %.2f",D
[nstart
]);
142 leg
[0] = strdup(buf
);
144 xvgr_legend(fp
,((nstart
> 1) ? nstart
+1 : 1),leg
);
146 for(j
=0; (j
<minj
); j
++) {
147 fprintf(fp
,"%10g",xtime
[j
]-xtime
[0]);
150 for(i
=0; (i
<nstart
); i
++)
152 fprintf(fp
," %10g",msd0
/nstart
);
154 for(i
=0; (i
<nstart
); i
++)
155 fprintf(fp
," %10g",msd
[i
][j
]);
161 static void do_msd(char *trx
,char *xvg
,
162 int nframes
,int nstart
,real dt
,
163 int nx
,atom_id index
[],char *grpname
,
166 real
**msd
,*xtime
,t
,t0
,msdt
;
168 int i
,n
,status
,iframe
,istart
,natoms
;
170 rvec
*x
[2],**xref
=NULL
;
176 fatal_error(0,"nstart should be > 0 (iso %d)",nstart
);
178 fatal_error(0,"nframes should be > 0 (iso %d)",nframes
);
180 natoms
=read_first_x(&status
,trx
,&t0
,&(x
[cur
]),box
);
182 snew(x
[prev
],natoms
);
183 memcpy(x
[prev
],x
[cur
],natoms
*sizeof(x
[cur
][0]));
188 for(i
=0; (i
<nstart
); i
++) {
190 snew(msd
[i
],nframes
);
191 snew(xref
[i
],natoms
);
196 for(i
=0; (i
<nx
); i
++)
197 if (index
[i
] >= natoms
)
198 fatal_error(0,"Index[%d] = %d should be >=0 and < %d",i
,index
[i
],natoms
);
200 /* Index is OK if we got here */
205 /* Check for new starting point */
206 if (istart
< nstart
) {
207 if ((t
>= (t0
+istart
*dt
)) && (n_offs
[istart
] == -1)) {
208 fprintf(stderr
," New starting point\n");
209 memcpy(xref
[istart
],x
[cur
],natoms
*sizeof(x
[cur
][0]));
210 n_offs
[istart
]=iframe
;
214 for(n
=0; (n
<istart
); n
++) {
215 /* Compute the MSD for all starting points */
216 msdt
= calc_msd(xref
[n
],nx
,index
,x
[cur
]);
217 msd
[n
][iframe
-n_offs
[n
]] = msdt
;
220 /* Read new data into new array and remove PBC */
222 bEOF
= !read_next_x(status
,&t
,natoms
,x
[cur
],box
);
223 prepare_data(nx
,index
,x
[cur
],x
[prev
],box
);
226 } while ((iframe
< nframes
) && !bEOF
);
229 analyse_msd(xvg
,grpname
,iframe
,istart
,msd
,xtime
,bfit
,efit
);
231 for(i
=0; (i
<nstart
); i
++) {
241 int main(int argc
,char *argv
[])
243 static char *desc
[] = {
244 "g_diffuse computes the diffusion constant using the mean square",
245 "displacement of atoms from",
246 "their initial positions (using the Einstein relation).[PAR]",
248 static char *bugs
[] = {
249 "When the number of starting points is too high, average and standard deviation may be meaningless"
251 static int nrframes
= 10;
252 static int nstart
= 1;
253 static real dt
= 10.0;
254 static real bfit
=0,efit
=10000;
256 { "-nframes", FALSE
, etINT
, &nrframes
,
257 "Number of frames in your trajectory" },
258 { "-nstart", FALSE
, etINT
, &nstart
,
259 "Number of starting points" },
260 { "-dt", FALSE
, etREAL
, &dt
,
261 "Time between starting points" },
262 { "-beginfit",FALSE
, etREAL
, &bfit
,
263 "Begin fitting to a straight line at this time (ps)" },
264 { "-endfit", FALSE
, etREAL
, &efit
,
268 { efTRX
, "-f", NULL
, ffREAD
},
269 { efNDX
, NULL
, NULL
, ffREAD
},
270 { efXVG
, NULL
, "diff.xvg", ffWRITE
},
272 #define NFILE asize(fnm)
277 CopyRight(stdout
,argv
[0]);
279 parse_common_args(&argc
,argv
,PCA_CAN_VIEW
| PCA_CAN_TIME
,TRUE
,
280 NFILE
,fnm
,asize(pa
),pa
,asize(desc
),desc
,asize(bugs
),bugs
);
282 rd_index(ftp2fn(efNDX
,NFILE
,fnm
),1,&nx
,&index
,&grpname
);
284 do_msd(ftp2fn(efTRX
,NFILE
,fnm
),ftp2fn(efXVG
,NFILE
,fnm
),
285 nrframes
,nstart
,dt
,nx
,index
,grpname
,bfit
,efit
);
288 xvgr_file(ftp2fn(efXVG
,NFILE
,fnm
),"-nxy");