Reuse epbcXY logic
[gromacs/AngularHB.git] / src / contrib / ehanal.c
blob31c6870bb89b82c82ed7166fbca0e0869300698a
1 /*
2 *
3 * This source code is part of
4 *
5 * G R O M A C S
6 *
7 * GROningen MAchine for Chemical Simulations
8 *
9 * VERSION 3.3.3
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
32 * And Hey:
33 * Groningen Machine for Chemical Simulation
35 #ifdef HAVE_CONFIG_H
36 #include <config.h>
37 #endif
39 #include <stdlib.h>
40 #include <math.h>
41 #include <string.h>
42 #include "typedefs.h"
43 #include "gromacs/utility/smalloc.h"
44 #include "macros.h"
45 #include "gromacs/utility/fatalerror.h"
46 #include "random.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"
52 #include "names.h"
53 #include "ehdata.h"
54 #include "gromacs/fileio/pdbio.h"
56 t_histo *init_histo(int np,real minx,real maxx)
58 t_histo *h;
60 snew(h,1);
61 snew(h->y,np+1);
62 snew(h->nh,np+1);
63 h->np = np;
64 if (maxx <= minx)
65 gmx_fatal(FARGS,"minx (%f) should be less than maxx (%f) in init_histo",minx,maxx);
66 h->minx = minx;
67 h->maxx = maxx;
68 h->dx_1 = np/(maxx-minx);
69 h->dx = (maxx-minx)/np;
71 return h;
74 void done_histo(t_histo *h)
76 sfree(h->y);
77 sfree(h->nh);
78 h->np = 0;
81 void add_histo(t_histo *h,real x,real y)
83 int n;
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);
88 h->y[n] += y;
89 h->nh[n]++;
92 void dump_histo(t_histo *h,char *fn,char *title,char *xaxis,char *yaxis,
93 int enorm,real norm_fac)
95 FILE *fp;
96 int i,nn;
98 for(nn=h->np; (nn > 0); nn--)
99 if (h->nh[nn] != 0)
100 break;
101 for(i=0; (i<nn); i++)
102 if (h->nh[i] > 0)
103 break;
104 fp = xvgropen(fn,title,xaxis,yaxis);
105 for( ; (i<nn); i++) {
106 switch (enorm) {
107 case enormNO:
108 fprintf(fp,"%12f %12f %d\n",h->minx+h->dx*i,h->y[i],h->nh[i]);
109 break;
110 case enormFAC:
111 fprintf(fp,"%12f %12f %d\n",h->minx+h->dx*i,h->y[i]*norm_fac,h->nh[i]);
112 break;
113 case enormNP:
114 if (h->nh[i] > 0)
115 fprintf(fp,"%12f %12f %d\n",
116 h->minx+h->dx*i,h->y[i]*norm_fac/h->nh[i],h->nh[i]);
117 break;
118 default:
119 gmx_fatal(FARGS,"Wrong value for enorm (%d)",enorm);
122 gmx_ffclose(fp);
125 /*******************************************************************
127 * Functions to analyse and monitor scattering
129 *******************************************************************/
131 void add_scatter_event(t_ana_scat *scatter,rvec pos,gmx_bool bInel,
132 real t,real ekin)
134 int np = scatter->np;
136 if (np == scatter->maxp) {
137 scatter->maxp += 32;
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]);
147 scatter->np++;
150 void reset_ana_scat(t_ana_scat *scatter)
152 scatter->np = 0;
155 void done_scatter(t_ana_scat *scatter)
157 scatter->np = 0;
158 sfree(scatter->time);
159 sfree(scatter->ekin);
160 sfree(scatter->bInel);
161 sfree(scatter->pos);
164 void analyse_scatter(t_ana_scat *scatter,t_histo *hmfp)
166 int i,n;
167 rvec dx;
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,
184 int maxparticle)
186 t_ana_struct *anal;
188 snew(anal,1);
189 anal->nanal = 1.2*((nstep / nsave)+1);
190 anal->index = 0;
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);
197 anal->nstruct = 1;
198 anal->nparticle = 1;
199 anal->maxparticle = maxparticle;
200 snew(anal->q,1);
201 snew(anal->x,1);
202 snew(anal->x[0],maxparticle);
204 return anal;
207 void done_ana_struct(t_ana_struct *anal)
209 int i;
211 sfree(anal->t);
212 sfree(anal->maxdist);
213 sfree(anal->d2_com);
214 sfree(anal->d2_origin);
215 sfree(anal->nion);
216 sfree(anal->q);
217 for(i=0; (i<anal->nstruct); i++)
218 sfree(anal->x[i]);
219 sfree(anal->x);
222 void reset_ana_struct(t_ana_struct *anal)
224 int i;
226 for(i=0; (i<anal->nanal); i++) {
227 anal->t[i] = 0;
228 anal->maxdist[i] = 0;
229 clear_rvec(anal->d2_com[i]);
230 clear_rvec(anal->d2_origin[i]);
231 anal->nion[i] = 0;
233 anal->index = 0;
236 void add_ana_struct(t_ana_struct *total,t_ana_struct *add)
238 int i,m;
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[])
263 int i,j;
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]);
276 anal->nstruct++;
279 void analyse_structure(t_ana_struct *anal,real t,rvec center,
280 rvec x[],int nparticle,real charge[])
282 int i,j,m,nel,n=0;
283 rvec dx,com;
284 real dx2,dx1;
286 j = anal->index;
287 if (j >= anal->nanal)
288 gmx_fatal(FARGS,"Too many points in analyse_structure");
289 anal->t[j] = t;
290 anal->maxdist[j] = 0;
291 clear_rvec(com);
292 nel = 0;
293 for(i=0; (i<nparticle); i++) {
294 if (charge[i] < 0) {
295 rvec_inc(com,x[i]);
296 nel++;
299 if (nel > 0)
300 for(m=0; (m<3); m++)
301 com[m] /= nel;
302 for(i=0; (i<nparticle); i++) {
303 if (charge[i] < 0) {
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]);
310 dx1 = sqrt(dx2);
311 if (dx1 > anal->maxdist[j])
312 anal->maxdist[j] = dx1;
313 n++;
316 do_add_struct(anal,nparticle,x);
317 anal->nion[j] = n;
318 anal->index++;
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;
325 int i,j;
326 real t,d2;
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++) {
338 t = 1000*anal->t[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",
343 t,sqrt(d2/nsim),
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",
349 t,sqrt(d2/nsim),
350 sqrt(anal->d2_origin[i][XX]/nsim),
351 sqrt(anal->d2_origin[i][YY]/nsim),
352 sqrt(anal->d2_origin[i][ZZ]/nsim));
354 gmx_ffclose(hp);
355 gmx_ffclose(gp);
356 gmx_ffclose(fp);
357 gmx_ffclose(kp);
360 void dump_as_pdb(char *pdb,t_ana_struct *anal)
362 FILE *kp;
363 int i,j;
364 real t;
366 kp = gmx_ffopen(pdb,"w");
367 for(i=0; (i<anal->nstruct); i++) {
368 t = 1000*anal->t[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",
372 "PLS",' ',1,
373 anal->x[i][j][XX]/100,
374 anal->x[i][j][YY]/100,
375 anal->x[i][j][ZZ]/100);
376 fprintf(kp,"\n");
378 fprintf(kp,"ENDMDL\n");
380 gmx_ffclose(kp);
383 char *enms[eNR] = {
384 "Coulomb", "Repulsion", "Potential",
385 "EkHole", "EkElectron", "EkLattice", "Kinetic",
386 "Total"
389 void add_ana_ener(t_ana_ener *ae,int nn,real e[])
391 int i;
393 /* First time around we are constantly increasing the array size */
394 if (nn >= ae->nx) {
395 if (ae->nx == ae->maxx) {
396 ae->maxx += 1024;
397 srenew(ae->e,ae->maxx);
399 for(i=0; (i<eNR); i++)
400 ae->e[ae->nx][i] = e[i];
401 ae->nx++;
403 else {
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,
410 t_ana_struct *total)
412 FILE *fp;
413 int i,j;
414 real fac;
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]));
427 fprintf(fp,"&\n");
428 gmx_ffclose(fp);