4 * This source code is part of
8 * GROningen MAchine for Chemical Simulations
11 * Copyright (c) 1991-2001, University of Groningen, The Netherlands
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * If you want to redistribute modifications, please consider that
18 * scientific software is very special. Version control is crucial -
19 * bugs must be traceable. We will be happy to consider code for
20 * inclusion in the official distribution, but derived work must not
21 * be called official GROMACS. Details are found in the README & COPYING
22 * files - if they are missing, get the official version at www.gromacs.org.
24 * To help us fund GROMACS development, we humbly ask that you cite
25 * the papers on the package - you can find them in the top README file.
27 * For more info, check our website at http://www.gromacs.org
30 * GROtesk MACabre and Sinister
32 static char *SRCID_g_relax_c
= "$Id$";
62 real tauc
,dtauc
,S2
,dS2
;
67 void read_shifts(FILE *fp
,int nx
,real shiftx
[],int ny
,real shifty
[])
72 for(i
=0; (i
<nx
); i
++) {
77 /*for(i=0; (i<ny); i++) {
84 complex c_sqr(complex c
)
88 cs
.re
= c
.re
*c
.re
-c
.im
*c
.im
;
89 cs
.im
= 2.0*c
.re
*c
.im
;
94 complex c_add(complex c
,complex d
)
104 complex calc_ylm(int m
,rvec rij
,real r2
,real r_3
,real r_6
)
106 static bool bFirst
=TRUE
;
107 static real y0
,y1
,y2
;
108 real x
,y
,z
,xsq
,ysq
,rxy
,r1
,cphi
,sphi
,cth
,sth
,fac
;
112 y0
= sqrt(5/(4*M_PI
));
113 y1
= sqrt(45/(24*M_PI
));
114 y2
= sqrt(45/(96*M_PI
));
132 /* Now calculate the spherical harmonics */
137 cs
.re
= fac
*(cphi
*cphi
-sphi
*sphi
);
138 /* Use the index as a prefactor... check your formulas */
139 cs
.im
= m
*fac
*cphi
*sphi
;
148 cs
.re
= y0
*(3*cth
*cth
-1);
158 void myfunc(real x
,real a
[],real
*y
,real dyda
[],int na
)
162 * y = a1 + (1-a1) exp(-a2 x)
164 * where in real life a1 is S^2 and a2 = 1/tauc
173 *y
= S2
+ (1-S2
)*eee
;
175 dyda
[2] = x
*tau1
*tau1
*(1-a
[1])*eee
;
178 void fit_one(bool bVerbose
,
179 int nframes
,real x
[],real y
[],real dy
[],real ftol
,
180 real
*S2
,real
*dS2
,real
*tauc
,real
*dtauc
)
182 void mrqmin(real x
[],real y
[],real sig
[],int ndata
,real a
[],
183 int ma
,int lista
[],int mfit
,real
**covar
,real
**alpha
,
185 void (*funcs
)(real x
,real a
[],real
*y
,real dyda
[],int na
),
188 real
*a
,**covar
,**alpha
;
189 real chisq
,ochisq
,alamda
;
191 int i
,j
,ma
,mfit
,*lista
;
198 for(i
=0; (i
<ma
+1); i
++) {
204 a
[1] = 0.99; /* S^2 */
205 a
[2] = 0.1; /* tauc */
206 alamda
= -1; /* Starting value */
211 mrqmin(x
-1,y
-1,dy
-1,nframes
,a
,ma
,lista
,mfit
,covar
,alpha
,
212 &chisq
,myfunc
,&alamda
);
214 fprintf(stderr
,"\rFitting %d chisq=%g, alamda=%g, tau=%g, S^2=%g\t\t\n",
215 j
,chisq
,alamda
,1.0/a
[2],a
[1]);
217 bCont
= (((ochisq
- chisq
) > ftol
*chisq
) ||
218 ((ochisq
== chisq
)));
219 } while (bCont
&& (alamda
!= 0.0) && (j
< 50));
221 fprintf(stderr
,"\n");
223 /* Now get the covariance matrix out */
225 mrqmin(x
-1,y
-1,dy
-1,nframes
,a
,ma
,lista
,mfit
,covar
,alpha
,
226 &chisq
,myfunc
,&alamda
);
229 *dS2
= sqrt(covar
[1][1]);
231 *dtauc
= sqrt(covar
[2][2]);
233 for(i
=0; (i
<ma
+1); i
++) {
243 void calc_tauc(bool bVerbose
,int npair
,t_pair pair
[],real dt
,
244 int nframes
,t_sij spec
[],real
**corr
)
249 real S2
,S22
,tauc
,fac
;
255 for(i
=0; (i
<nframes
); i
++)
258 fprintf(stderr
,"Fitting correlation function to Lipari&Szabo function\n");
259 fac
=1.0/((real
)nframes
);
260 for(i
=0; (i
<npair
); i
++) {
262 /* Use Levenberg-Marquardt method to fit */
263 for(j
=0; (j
<nframes
); j
++)
266 nframes
,x
,corr
[i
],dy
,ftol
,
267 &(spec
[i
].S2
),&(spec
[i
].dS2
),
268 &(spec
[i
].tauc
),&(spec
[i
].dtauc
));
270 sprintf(buf
,"test%d.xvg",i
);
271 fp
= ffopen(buf
,"w");
272 for(j
=0; (j
<nframes
); j
++) {
273 fprintf(fp
,"%10g %10g %10g\n",j
*dt
,corr
[i
][j
],
274 spec
[i
].S2
+ (1-spec
[i
].S2
)*exp(-j
*dt
/spec
[i
].tauc
));
282 void calc_aver(FILE *fp
,int nframes
,int npair
,t_pair pair
[],t_sij
*spec
,
289 md_6
= pow(maxdist
,-6.0);
292 for(i
=0; (i
<npair
); i
++) {
295 fprintf(fp
,"%5d %5d",pair
[i
].ai
,pair
[i
].aj
);
296 for(m
=0; (m
<5); m
++) {
297 c1
.re
= spec
[i
].Ylm
[m
].re
*nf_1
;
298 c1
.im
= spec
[i
].Ylm
[m
].im
*nf_1
;
303 fprintf(fp
," %8.3f+i%8.3f",c1
.re
,c1
.im
);
305 fprintf(fp
," %8.3f-i%8.3f",c1
.re
,-c1
.im
);
308 spec
[i
].rij_3
*= nf_1
;
309 spec
[i
].rij_6
*= nf_1
;
310 spec
[i
].y2
.re
= fac
*c2
.re
;
311 spec
[i
].y2
.im
= fac
*c2
.im
;
312 spec
[i
].bNOE
= (spec
[i
].rij_6
> md_6
);
316 void plot_spectrum(char *noefn
,int npair
,t_pair pair
[],t_sij
*spec
,real taum
)
320 t_rgb rlo
= { 1,0,0 },rhi
= {1,1,1};
321 real Sijmax
,Sijmin
,pow6
,pow3
,pp3
,pp6
,ppy
,tauc
;
328 fp
=xvgropen(noefn
,"Cross Relaxation","Pair Index","\\8s\\4\\sij\\N");
329 for(i
=0; (i
<npair
); i
++) {
331 sij
.re
= -0.4*((taum
-tauc
)*spec
[i
].y2
.re
+ tauc
*spec
[i
].rij_6
);
332 sij
.im
= -0.4* (taum
-tauc
)*spec
[i
].y2
.im
;
334 Sijmax
=max(Sijmax
,sij
.re
);
335 Sijmin
=min(Sijmin
,sij
.re
);
336 fprintf(fp
,"%5d %10g\n",i
,sij
.re
);
339 fprintf(stderr
,"Sijmin: %g, Sijmax: %g\n",Sijmin
,Sijmax
);
340 out
=ffopen("spec.out","w");
343 fprintf(out
,"%5s %5s %8s %8s %8s %8s %8s %8s %8s %8s %8s\n",
344 "at i","at j","S^2","Sig S^2","tauc","Sig tauc",
345 "<rij6>","<rij3>","<ylm>","rij3-6","ylm-rij6");
346 for(i
=0; (i
<npair
); i
++) {
348 pp6
= pow(spec
[i
].rij_6
,pow6
);
349 pp3
= pow(spec
[i
].rij_3
,pow3
);
350 if (spec
[i
].y2
.re
< 0)
351 ppy
= -pow(-spec
[i
].y2
.re
,pow6
);
353 ppy
= pow(spec
[i
].y2
.re
,pow6
);
354 fprintf(out
,"%5d %5d %8.4f %8.4f %8.4f %8.4f %8.4f %8.4f %8.4f %8.4f %8.4f\n",
355 pair
[i
].ai
,pair
[i
].aj
,
356 spec
[i
].S2
,spec
[i
].dS2
,spec
[i
].tauc
,spec
[i
].dtauc
,
357 pp6
,pp3
,ppy
,pp3
-pp6
,ppy
-pp6
);
367 void spectrum(bool bVerbose
,
368 char *trj
,char *shifts
,bool bAbInitio
,
369 char *corrfn
,char *noefn
,
370 int maxframes
,bool bFour
,bool bFit
,int nrestart
,
371 int npair
,t_pair pair
[],int nat
,real chem_shifts
[],
372 real taum
,real maxdist
,
373 real w_rls
[],rvec xp
[],t_idef
*idef
)
376 int i
,j
,m
,ii
,jj
,natoms
,status
,nframes
;
380 real r2
,r6
,r_3
,r_6
,tauc
;
387 fprintf(stderr
,"There is no kill like overkill! Going to malloc %d bytes\n",
388 npair
*maxframes
*sizeof(corr
[0][0]));
390 for(i
=0; (i
<npair
); i
++)
391 snew(corr
[i
],maxframes
);
393 natoms
= read_first_x(&status
,trj
,&t0
,&x
,box
);
395 fatal_error(0,"Not enough atoms in trajectory");
397 if (nframes
>= maxframes
) {
398 fprintf(stderr
,"\nThere are more than the %d frames you told me!",
404 fprintf(stderr
,"\rframe: %d",nframes
);
405 rm_pbc(idef
,natoms
,box
,x
,x
);
407 do_fit(natoms
,w_rls
,xp
,x
);
409 for(i
=0; (i
<npair
); i
++) {
412 rvec_sub(x
[ii
],x
[jj
],dx
);
413 copy_rvec(dx
,corr
[i
][nframes
]);
419 spec
[i
].rij_3
+= r_3
;
420 spec
[i
].rij_6
+= r_6
;
421 for(m
=0; (m
<5); m
++) {
422 spec
[i
].Ylm
[m
] = c_add(spec
[i
].Ylm
[m
],
423 calc_ylm(m
-2,dx
,r2
,r_3
,r_6
));
427 } while (read_next_x(status
,&t
,natoms
,x
,box
));
430 fprintf(stderr
,"\n");
432 fp
=ffopen("ylm.out","w");
433 calc_aver(fp
,nframes
,npair
,pair
,spec
,maxdist
);
436 /* Select out the pairs that have to be correlated */
438 for(i
=j
=0; (i
<npair
); i
++) {
440 Corr
[j
] = &(corr
[i
][0][0]);
444 fprintf(stderr
,"There are %d NOEs in your simulation\n",j
);
446 dt
= (t1
-t0
)/(nframes
-1);
449 do_autocorr(corrfn
,"Correlation Function for Interproton Vectors",
450 nframes
,j
,Corr
,dt
,eacP2
,nrestart
,FALSE
,FALSE
,bFour
,TRUE
);
452 calc_tauc(bVerbose
,npair
,pair
,dt
,nframes
/2,spec
,(real
**)corr
);
454 plot_spectrum(noefn
,npair
,pair
,spec
,taum
);
457 int main(int argc
,char *argv
[])
459 static char *desc
[] = {
460 "g_noe calculates a NOE spectrum"
465 int i
,j
,k
,natoms
,nprot
,*prot_ind
;
468 atom_id
*ind_fit
,*all_at
;
477 { efTRX
, "-f", NULL
, ffREAD
},
478 { efTPX
, "-s", NULL
, ffREAD
},
479 { efNDX
, NULL
, NULL
, ffREAD
},
480 { efDAT
, "-d", "shifts", ffREAD
},
481 { efOUT
, "-o","spec", ffWRITE
},
482 { efXVG
, "-corr", "rij-corr", ffWRITE
},
483 { efXVG
, "-noe", "noesy", ffWRITE
}
485 #define NFILE asize(fnm)
486 static real taum
= 0.0, maxdist
= 0.6;
487 static int nlevels
= 15;
488 static int nrestart
= 1;
489 static int maxframes
= 100;
490 static bool bFFT
= TRUE
,bFit
= TRUE
, bVerbose
= TRUE
;
492 { "-taum", FALSE
, etREAL
, &taum
,
493 "Rotational correlation time for your molecule. It is obligatory to pass this option" },
494 { "-maxdist", FALSE
, etREAL
, &maxdist
,
495 "Maximum distance to be plotted" },
496 { "-nlevels", FALSE
, etINT
, &nlevels
,
497 "Number of levels for plotting" },
498 { "-nframes", FALSE
, etINT
, &maxframes
,
499 "Number of frames in your trajectory. Will stop analysis after this" },
500 { "-fft", FALSE
, etBOOL
, &bFFT
,
501 "Use FFT for correlation function" },
502 { "-nrestart", FALSE
, etINT
, &nrestart
,
503 "Number of frames between starting point for computation of ACF without FFT" },
504 { "-fit", FALSE
, etBOOL
, &bFit
,
505 "Do an optimal superposition on reference structure in tpx file" },
506 { "-v", FALSE
, etBOOL
, &bVerbose
,
507 "Tell you what I am about to do" }
510 CopyRight(stderr
,argv
[0]);
511 parse_common_args(&argc
,argv
,PCA_CAN_VIEW
| PCA_CAN_TIME
| PCA_BE_NICE
,
512 NFILE
,fnm
,asize(pa
),pa
,asize(desc
),desc
,0,NULL
);
514 fatal_error(0,"Please give me a sensible taum!\n");
517 fprintf(stderr
,"Warning: too many levels, setting to %d\n",nlevels
);
520 top
= read_top(ftp2fn(efTPX
,NFILE
,fnm
));
521 natoms
= top
->atoms
.nr
;
523 read_tpx(ftp2fn(efTPX
,NFILE
,fnm
),&step
,&t
,&lambda
,NULL
,box
,
524 &natoms
,xp
,NULL
,NULL
,NULL
);
526 /* Determine the number of protons, and their index numbers
527 * by checking the mass
530 snew(prot_ind
,natoms
);
531 for(i
=0; (i
<natoms
); i
++)
532 if (top
->atoms
.atom
[i
].m
< 2) {
533 prot_ind
[nprot
++] = i
;
535 fprintf(stderr
,"There %d protons in your topology\n",nprot
);
536 snew(pair
,(nprot
*(nprot
-1)/2));
537 for(i
=k
=0; (i
<nprot
); i
++) {
538 for(j
=i
+1; (j
<nprot
); j
++,k
++) {
539 pair
[k
].ai
= prot_ind
[i
];
540 pair
[k
].aj
= prot_ind
[j
];
545 fprintf(stderr
,"Select group for root least squares fit\n");
546 rd_index(ftp2fn(efNDX
,NFILE
,fnm
),1,&ifit
,&ind_fit
,&gn_fit
);
549 fatal_error(0,"Need >= 3 points to fit!\n");
551 /* Make an array with weights for fitting */
553 for(i
=0; (i
<ifit
); i
++)
554 w_rls
[ind_fit
[i
]]=top
->atoms
.atom
[ind_fit
[i
]].m
;
556 /* Prepare reference frame */
558 for(j
=0; (j
<natoms
); j
++)
560 rm_pbc(&(top
->idef
),natoms
,box
,xp
,xp
);
561 reset_x(ifit
,ind_fit
,natoms
,all_at
,xp
,w_rls
);
565 ftp2fn(efTRX
,NFILE
,fnm
),ftp2fn(efDAT
,NFILE
,fnm
),
566 ftp2bSet(efDAT
,NFILE
,fnm
),opt2fn("-corr",NFILE
,fnm
),
567 opt2fn("-noe",NFILE
,fnm
),
568 maxframes
,bFFT
,bFit
,nrestart
,
569 k
,pair
,natoms
,shifts
,
570 taum
,maxdist
,w_rls
,xp
,&(top
->idef
));