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-2008, 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 Machine for Chemical Simulation
43 #include "gromacs/utility/smalloc.h"
45 #include "gromacs/utility/fatalerror.h"
47 #include "gromacs/fileio/pdbio.h"
48 #include "gromacs/utility/futil.h"
49 #include "gromacs/math/units.h"
50 #include "gromacs/fileio/xvgr.h"
51 #include "gromacs/math/vec.h"
54 #include "gromacs/fileio/pdbio.h"
56 t_histo
*init_histo(int np
,real minx
,real maxx
)
65 gmx_fatal(FARGS
,"minx (%f) should be less than maxx (%f) in init_histo",minx
,maxx
);
68 h
->dx_1
= np
/(maxx
-minx
);
69 h
->dx
= (maxx
-minx
)/np
;
74 void done_histo(t_histo
*h
)
81 void add_histo(t_histo
*h
,real x
,real y
)
85 n
= (x
-h
->minx
)*h
->dx_1
;
86 if ((n
< 0) || (n
> h
->np
))
87 gmx_fatal(FARGS
,"Invalid x (%f) in add_histo. Should be in %f - %f",x
,h
->minx
,h
->maxx
);
92 void dump_histo(t_histo
*h
,char *fn
,char *title
,char *xaxis
,char *yaxis
,
93 int enorm
,real norm_fac
)
98 for(nn
=h
->np
; (nn
> 0); nn
--)
101 for(i
=0; (i
<nn
); i
++)
104 fp
= xvgropen(fn
,title
,xaxis
,yaxis
);
105 for( ; (i
<nn
); i
++) {
108 fprintf(fp
,"%12f %12f %d\n",h
->minx
+h
->dx
*i
,h
->y
[i
],h
->nh
[i
]);
111 fprintf(fp
,"%12f %12f %d\n",h
->minx
+h
->dx
*i
,h
->y
[i
]*norm_fac
,h
->nh
[i
]);
115 fprintf(fp
,"%12f %12f %d\n",
116 h
->minx
+h
->dx
*i
,h
->y
[i
]*norm_fac
/h
->nh
[i
],h
->nh
[i
]);
119 gmx_fatal(FARGS
,"Wrong value for enorm (%d)",enorm
);
125 /*******************************************************************
127 * Functions to analyse and monitor scattering
129 *******************************************************************/
131 void add_scatter_event(t_ana_scat
*scatter
,rvec pos
,gmx_bool bInel
,
134 int np
= scatter
->np
;
136 if (np
== scatter
->maxp
) {
138 srenew(scatter
->time
,scatter
->maxp
);
139 srenew(scatter
->ekin
,scatter
->maxp
);
140 srenew(scatter
->bInel
,scatter
->maxp
);
141 srenew(scatter
->pos
,scatter
->maxp
);
143 scatter
->time
[np
] = t
;
144 scatter
->bInel
[np
] = np
;
145 scatter
->ekin
[np
] = ekin
;
146 copy_rvec(pos
,scatter
->pos
[np
]);
150 void reset_ana_scat(t_ana_scat
*scatter
)
155 void done_scatter(t_ana_scat
*scatter
)
158 sfree(scatter
->time
);
159 sfree(scatter
->ekin
);
160 sfree(scatter
->bInel
);
164 void analyse_scatter(t_ana_scat
*scatter
,t_histo
*hmfp
)
169 if (scatter
->np
> 1) {
170 for(i
=1; (i
<scatter
->np
); i
++) {
171 rvec_sub(scatter
->pos
[i
],scatter
->pos
[i
-1],dx
);
172 add_histo(hmfp
,scatter
->ekin
[i
],norm(dx
));
177 /*******************************************************************
179 * Functions to analyse structural changes
181 *******************************************************************/
183 t_ana_struct
*init_ana_struct(int nstep
,int nsave
,real timestep
,
189 anal
->nanal
= 1.2*((nstep
/ nsave
)+1);
191 anal
->dt
= nsave
*timestep
;
192 snew(anal
->t
,anal
->nanal
);
193 snew(anal
->maxdist
,anal
->nanal
);
194 snew(anal
->d2_com
,anal
->nanal
);
195 snew(anal
->d2_origin
,anal
->nanal
);
196 snew(anal
->nion
,anal
->nanal
);
199 anal
->maxparticle
= maxparticle
;
202 snew(anal
->x
[0],maxparticle
);
207 void done_ana_struct(t_ana_struct
*anal
)
212 sfree(anal
->maxdist
);
214 sfree(anal
->d2_origin
);
217 for(i
=0; (i
<anal
->nstruct
); i
++)
222 void reset_ana_struct(t_ana_struct
*anal
)
226 for(i
=0; (i
<anal
->nanal
); i
++) {
228 anal
->maxdist
[i
] = 0;
229 clear_rvec(anal
->d2_com
[i
]);
230 clear_rvec(anal
->d2_origin
[i
]);
236 void add_ana_struct(t_ana_struct
*total
,t_ana_struct
*add
)
240 if (total
->index
== 0)
241 total
->index
= add
->index
;
242 else if (total
->index
!= add
->index
)
243 gmx_fatal(FARGS
,"Analysis incompatible (total: %d, add: %d) %s, %d",
244 total
->index
,add
->index
,__FILE__
,__LINE__
);
245 for(i
=0; (i
<total
->index
); i
++) {
246 if (total
->t
[i
] == 0)
247 total
->t
[i
] = add
->t
[i
];
248 else if (total
->t
[i
] != add
->t
[i
])
249 gmx_fatal(FARGS
,"Inconsistent times in analysis (%f-%f) %s, %d",
250 total
->t
[i
],add
->t
[i
],__FILE__
,__LINE__
);
251 if (add
->maxdist
[i
] > total
->maxdist
[i
])
252 total
->maxdist
[i
] = add
->maxdist
[i
];
253 for(m
=0; (m
<DIM
); m
++) {
254 total
->d2_com
[i
][m
] += add
->d2_com
[i
][m
]/add
->nion
[i
];
255 total
->d2_origin
[i
][m
] += add
->d2_origin
[i
][m
]/add
->nion
[i
];
257 total
->nion
[i
] += add
->nion
[i
];
261 static void do_add_struct(t_ana_struct
*anal
,int nparticle
,rvec x
[])
265 if (nparticle
> anal
->nparticle
) {
266 for(i
=0; (i
<anal
->nstruct
); i
++) {
267 for(j
=anal
->nparticle
; (j
<nparticle
); j
++)
268 copy_rvec(x
[j
],anal
->x
[i
][j
]);
271 anal
->nparticle
=nparticle
;
272 srenew(anal
->x
,anal
->nstruct
+1);
273 snew(anal
->x
[anal
->nstruct
],anal
->maxparticle
);
274 for(j
=0; (j
<nparticle
); j
++)
275 copy_rvec(x
[j
],anal
->x
[anal
->nstruct
][j
]);
279 void analyse_structure(t_ana_struct
*anal
,real t
,rvec center
,
280 rvec x
[],int nparticle
,real charge
[])
287 if (j
>= anal
->nanal
)
288 gmx_fatal(FARGS
,"Too many points in analyse_structure");
290 anal
->maxdist
[j
] = 0;
293 for(i
=0; (i
<nparticle
); i
++) {
302 for(i
=0; (i
<nparticle
); i
++) {
304 rvec_sub(x
[i
],com
,dx
);
305 for(m
=0; (m
<DIM
); m
++) {
306 anal
->d2_com
[j
][m
] += sqr(dx
[m
]);
307 anal
->d2_origin
[j
][m
] += sqr(x
[i
][m
]);
309 dx2
= iprod(x
[i
],x
[i
]);
311 if (dx1
> anal
->maxdist
[j
])
312 anal
->maxdist
[j
] = dx1
;
316 do_add_struct(anal
,nparticle
,x
);
321 void dump_ana_struct(char *rmax
,char *nion
,char *gyr_com
,char *gyr_origin
,
322 t_ana_struct
*anal
,int nsim
)
324 FILE *fp
,*gp
,*hp
,*kp
;
327 char *legend
[] = { "Rg", "RgX", "RgY", "RgZ" };
329 fp
= xvgropen(rmax
,"rmax","Time (fs)","r (nm)");
330 gp
= xvgropen(nion
,"N ion","Time (fs)","N ions");
331 hp
= xvgropen(gyr_com
,"Radius of gyration wrt. C.O.M.",
332 "Time (fs)","Rg (nm)");
333 xvgr_legend(hp
,asize(legend
),legend
);
334 kp
= xvgropen(gyr_origin
,"Radius of gyration wrt. Origin",
335 "Time (fs)","Rg (nm)");
336 xvgr_legend(kp
,asize(legend
),legend
);
337 for(i
=0; (i
<anal
->index
); i
++) {
339 fprintf(fp
,"%12g %10.3f\n",t
,anal
->maxdist
[i
]);
340 fprintf(gp
,"%12g %10.3f\n",t
,(1.0*anal
->nion
[i
])/nsim
-1);
341 d2
= anal
->d2_com
[i
][XX
] + anal
->d2_com
[i
][YY
] + anal
->d2_com
[i
][ZZ
];
342 fprintf(hp
,"%12g %10.3f %10.3f %10.3f %10.3f\n",
344 sqrt(anal
->d2_com
[i
][XX
]/nsim
),
345 sqrt(anal
->d2_com
[i
][YY
]/nsim
),
346 sqrt(anal
->d2_com
[i
][ZZ
]/nsim
));
347 d2
= anal
->d2_origin
[i
][XX
] + anal
->d2_origin
[i
][YY
] + anal
->d2_origin
[i
][ZZ
];
348 fprintf(kp
,"%12g %10.3f %10.3f %10.3f %10.3f\n",
350 sqrt(anal
->d2_origin
[i
][XX
]/nsim
),
351 sqrt(anal
->d2_origin
[i
][YY
]/nsim
),
352 sqrt(anal
->d2_origin
[i
][ZZ
]/nsim
));
360 void dump_as_pdb(char *pdb
,t_ana_struct
*anal
)
366 kp
= gmx_ffopen(pdb
,"w");
367 for(i
=0; (i
<anal
->nstruct
); i
++) {
369 fprintf(kp
,"MODEL %d time %g fs\n",i
+1,t
);
370 for(j
=0; (j
<anal
->nparticle
); j
++) {
371 fprintf(kp
,get_pdbformat(),"ATOM",i
+1,(j
< anal
->nion
[i
]) ? "O" : "N",
373 anal
->x
[i
][j
][XX
]/100,
374 anal
->x
[i
][j
][YY
]/100,
375 anal
->x
[i
][j
][ZZ
]/100);
378 fprintf(kp
,"ENDMDL\n");
384 "Coulomb", "Repulsion", "Potential",
385 "EkHole", "EkElectron", "EkLattice", "Kinetic",
389 void add_ana_ener(t_ana_ener
*ae
,int nn
,real e
[])
393 /* First time around we are constantly increasing the array size */
395 if (ae
->nx
== ae
->maxx
) {
397 srenew(ae
->e
,ae
->maxx
);
399 for(i
=0; (i
<eNR
); i
++)
400 ae
->e
[ae
->nx
][i
] = e
[i
];
404 for(i
=0; (i
<eNR
); i
++)
405 ae
->e
[nn
][i
] += e
[i
];
409 void dump_ana_ener(t_ana_ener
*ae
,int nsim
,real dt
,char *edump
,
416 fac
= 1.0/(nsim
*ELECTRONVOLT
);
417 fp
=xvgropen(edump
,"Energies","Time (fs)","E (eV)");
418 xvgr_legend(fp
,eNR
,enms
);
419 fprintf(fp
,"@ s%d legend \"Ek/Nelec\"\n",eNR
);
420 fprintf(fp
,"@ type nxy\n");
421 for(i
=0; (i
<ae
->nx
); i
++) {
422 fprintf(fp
,"%10f",1000.0*dt
*i
);
423 for(j
=0; (j
<eNR
); j
++)
424 fprintf(fp
," %8.3f",ae
->e
[i
][j
]*fac
);
425 fprintf(fp
," %8.3f\n",ae
->e
[i
][eELECTRON
]/(ELECTRONVOLT
*total
->nion
[i
]));