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_mk_ghat_c
= "$Id$";
41 #include "shift_util.h"
48 const real tol
= 1e-8;
58 real
uhat(int porder
,real k1
,real k2
,real k3
,real h1
,real h2
,real h3
)
64 fac1
= sinx_x(k1
*h1
*0.5);
65 fac2
= sinx_x(k2
*h2
*0.5);
66 fac3
= sinx_x(k3
*h3
*0.5);
69 f123
= fac1
*fac2
*fac3
;
70 for(i
=1; (i
<=porder
+1); i
++)
79 real
uhat1D(int porder
,real k1
,real h1
)
85 fac1
= sinx_x(k1
*h1
*0.5);
88 for(i
=1; (i
<=porder
+1); i
++)
97 real
shat(real acut
,real kmag
,real r1
)
99 return gk(kmag
,acut
,r1
);
102 real
dhat(real alpha
,real k
,real h
)
106 dh
= alpha
*(sin(k
*h
)/h
) + (1.0-alpha
)*(sin(2.0*k
*h
)/(2.0*h
) );
114 real
cufrth(int porder
,real k1
,real k2
,real k3
,
115 real h1
,real h2
,real h3
,int nalias
)
117 real kn1
,kn2
,kn3
,tmp
;
124 tmp
= uhat(porder
,k1
,k2
,k3
,h1
,h2
,h3
);
125 ufrth
= tmp
*tmp
*tmp
*tmp
;
129 for( n1
= -nalias
; (n1
<= nalias
); n1
++) {
130 for( n2
= -nalias
; (n2
<= nalias
); n2
++) {
131 for( n3
= -nalias
; (n3
<= nalias
); n3
++) {
132 kn1
= k1
+ n1
*twopi
/h1
;
133 kn2
= k2
+ n2
*twopi
/h2
;
134 kn3
= k3
+ n3
*twopi
/h3
;
135 tmp
= uhat(porder
,kn1
,kn2
,kn3
,h1
,h2
,h3
);
136 ufrth
+= tmp
*tmp
*tmp
*tmp
;
141 if (fabs(ufrth
) < tol
)
147 real
crsqal(real acut
,real r1
,real k1
,real k2
,real k3
,
148 real h1
,real h2
,real h3
,int nalias
)
152 real ksq
,kmag
,tmp
,Rsqal
;
161 ksq
= k1
*k1
+ k2
*k2
+ k3
*k3
;
163 tmp
= shat(acut
,kmag
,r1
);
164 Rsqal
= tmp
*tmp
/(ksq
);
168 for(n1
= -nalias
; (n1
<= nalias
); n1
++) {
169 for( n2
= -nalias
; (n2
<= nalias
); n2
++) {
170 for( n3
= -nalias
; (n3
<= nalias
); n3
++) {
174 ksq
= kn1
*kn1
+ kn2
*kn2
+ kn3
*kn3
;
176 tmp
= shat(acut
,kmag
,r1
);
177 Rsqal
= Rsqal
+ tmp
*tmp
/ksq
;
186 real
usqsq(int porder
,real k1
,real k2
,real k3
,real h1
,real h2
,real h3
)
188 const real tt
=2.0/3.0;
189 const real tx
=2.0/15.0;
190 real t1
,t2
,t3
,t12
,t22
,t32
,tmp
;
200 tmp
= (1.0-tt
*t12
)*(1-tt
*t22
)*(1-tt
*t32
);
201 else if (porder
== 2)
202 tmp
= ( (1.0 - t12
+ tx
*t12
*t12
)*
203 (1.0 - t22
+ tx
*t22
*t22
)*
204 (1.0 - t32
+ tx
*t32
*t32
) );
206 fatal_error(0,"porder = %d in usqsq",porder
);
211 real
usqsq1D(int porder
,real k1
,real h1
)
213 const real tt
=2.0/3.0;
214 const real tx
=2.0/15.0;
222 else if (porder
== 2)
223 tmp
= ( (1.0 - t12
+ tx
*t12
*t12
));
225 fatal_error(0,"porder = %d in usqsq",porder
);
230 real
ursum(int term
,int porder
,real acut
,real r1
,
231 real k1
,real k2
,real k3
,real h1
,real h2
,real h3
,int nalias
)
235 real kn1
,kn2
,kn3
,urs
,tmp
;
245 c for large enough values of k, the terms become negligable
246 c if shat(k) = exp(-k^2/4*acut) < eps
247 c kcutsq = 4*alpha* (-ln(eps))
248 c eps = 10^-6, -ln(eps) = 14
249 c eps = 10^-10, -ln(eps) = 23
250 c eps = 10^-20, -ln(eps) = 46
252 c kcutsq = 4.0*acut*115;
256 if (term
==XX
) kt
= k1
;
257 if (term
==YY
) kt
= k2
;
258 if (term
==ZZ
) kt
= k3
;
259 ksq
= k1
*k1
+ k2
*k2
+ k3
*k3
;
261 tmp
= uhat(porder
,k1
,k2
,k3
,h1
,h2
,h3
);
262 urs
= tmp
*tmp
*kt
*shat(acut
,kmag
,r1
)/(ksq
);
266 for(n1
= -nalias
; (n1
<= nalias
); n1
++) {
267 for( n2
= -nalias
; (n2
<= nalias
); n2
++) {
268 for( n3
= -nalias
; (n3
<= nalias
); n3
++) {
272 ksq
= kn1
*kn1
+ kn2
*kn2
+ kn3
*kn3
;
274 if (term
==XX
) kt
= kn1
;
275 if (term
==YY
) kt
= kn2
;
276 if (term
==ZZ
) kt
= kn3
;
279 tmp
= uhat(porder
,kn1
,kn2
,kn3
,h1
,h2
,h3
);
281 urs
= urs
+ tmp
*tmp
*kt
*shat(acut
,kmag
,r1
)/ksq
;
290 real
ursum1D(int term
,int porder
,real acut
,real r1
,real k1
,real h1
,int nalias
)
302 c for large enough values of k, the terms become negligable
303 c if shat(k) = exp(-k^2/4*acut) < eps
304 c kcutsq = 4*alpha* (-ln(eps))
305 c eps = 10^-6, -ln(eps) = 14
306 c eps = 10^-10, -ln(eps) = 23
307 c eps = 10^-20, -ln(eps) = 46
310 /* kcutsq = 4.0*acut*115; */
313 if (term
==1) kt
= k1
;
316 tmp
= uhat1D(porder
,k1
,h1
);
317 urs
= tmp
*tmp
*kt
*shat(acut
,kmag
,r1
)/(EPSILON0
*ksq
);
321 for(n1
= -nalias
; (n1
<= nalias
); n1
++) {
324 /*c if (ksq.lt.kcutsq) then*/
325 if (term
==XX
) kt
= kn1
;
328 tmp
= uhat1D(porder
,kn1
,h1
);
330 urs
= urs
+ tmp
*tmp
*kt
*shat(acut
,kmag
,r1
)/(EPSILON0
*ksq
);
338 real
sym(int indx
,int maxind
)
340 if ( (indx
== 0 ) || (indx
== maxind
/2) )
346 void calc(bool bSym
,bool bVerbose
,
347 const int n1max
,const int n2max
,const int n3max
,
348 const real h1
,const real h2
,const real h3
,
349 int nalias
,int porder
,real acut
,real r1
,const real alpha
,
351 real
***ghat
,real
*ppval
,real
*zzval
,real
*eeref
,real
*qqopt
)
354 real k1
,k2
,k3
,ksq
,kmag
;
355 real gnumer
,dsq
,gdenom
,gsq
;
356 real ufrth
,rsqal
,rsq
;
360 real d1
,d2
,d3
,u1
,u2
,u3
,ss
,gg
;
361 real pval
,zval
,eref
,qopt
;
362 int N1MAX
,N2MAX
,N3MAX
;
384 for(l1
=0; (l1
<N1MAX
); l1
++) {
386 fprintf(stderr
,"\rl1=%5d qopt=%12.6e",l1
,qopt
);
389 d1
= dhat(alpha
,k1
,h1
);
391 for(l2
=0; (l2
<N2MAX
); l2
++) {
393 d2
= dhat(alpha
,k2
,h2
);
395 for(l3
=0; (l3
<N3MAX
); l3
++) {
396 if (((l1
+l2
+l3
) == 0) /*|| (l1 == n1max/2) || (l2 == n2max/2) ||
401 ksq
= k1
*k1
+ k2
*k2
+ k3
*k3
;
404 d3
= dhat(alpha
,k3
,h3
);
405 u1
= ursum(XX
,porder
,acut
,r1
,k1
,k2
,k3
,h1
,h2
,h3
,nalias
);
406 u2
= ursum(YY
,porder
,acut
,r1
,k1
,k2
,k3
,h1
,h2
,h3
,nalias
);
407 u3
= ursum(ZZ
,porder
,acut
,r1
,k1
,k2
,k3
,h1
,h2
,h3
,nalias
);
409 gnumer
= d1
*u1
+d2
*u2
+d3
*u3
;
410 dsq
= d1
*d1
+d2
*d2
+d3
*d3
;
411 gdenom
= dsq
*usqsq(porder
,k1
,k2
,k3
,h1
,h2
,h3
);
413 symfac
= sym(l1
,n1max
)*sym(l2
,n2max
)*sym(l3
,n3max
);
417 rsqal
= crsqal(acut
,r1
,k1
,k2
,k3
,h1
,h2
,h3
,nalias
);
420 qopt
+= (symfac
*(rsqal
- sqr(gnumer
)/gdenom
));
422 fprintf(debug
,"rsqal: %10.3e, gnumer: %10.3e, gdenom: %10.3e, ratio: %10.3e\n",
423 rsqal
,gnumer
,gdenom
,gnumer
/gdenom
);
426 if ((l1
== n1max
/2) || (l2
== n2max
/2) || (l3
== n3max
/2))
427 printf("L(%2d,%2d,%2d) D(%10.3e,%10.3e,%10.3e) U(%10.3e,%10.3e,%10.3e) gnumer=%10.3em dsq=%10.3e, gdenom=%10.3e, ghat=%10.3e\n",
428 l1
,l2
,l3
,d1
,d2
,d3
,u1
,u2
,u3
,gnumer
,dsq
,gdenom
,
429 (gdenom
== 0.0) ? 0 : gnumer
/gdenom
);
436 ghat
[l1
][l2
][l3
] = gg
/EPSILON0
;
439 ufrth
= cufrth(porder
,k1
,k2
,k3
,h1
,h2
,h3
,nalias
);
440 pval
= pval
+ symfac
*
441 (dsq
*gsq
*(usqsq(porder
,k1
,k2
,k3
,h1
,h2
,h3
)-ufrth
));
443 zval
= zval
+ symfac
*
444 (dsq
*gsq
*ufrth
- 2.0*gnumer
*gnumer
/gdenom
+ rsqal
);
445 ss
= shat(acut
,kmag
,r1
);
447 eref
= eref
+ symfac
* (rsqal
- rsq
);
454 fprintf(stderr
,"\n");
455 *ppval
= pval
/(box1
*box2
*box3
);
456 *zzval
= zval
/(box1
*box2
*box3
);
457 *eeref
= eref
/(box1
*box2
*box3
);
458 *qqopt
= qopt
/(EPSILON0
*box1
*box2
*box3
);
461 void calc1D(bool bSym
,bool bVerbose
,
462 const int n1max
,const int n2max
,const int n3max
,
463 const real h1
,const real h2
,const real h3
,
464 int nalias
,int porder
,real acut
,real r1
,const real alpha
,
466 real
***ghat
,real
*ppval
,real
*zzval
,real
*eeref
,real
*qqopt
)
470 real gnumer
,dsq
,gdenom
;
476 real pval
,zval
,eref
,qopt
;
478 /* int N2MAX,N3MAX; */
482 /* N2MAX = n2max/2+1; */
483 /* N3MAX = n3max/2+1; */
502 for(l1
=0; (l1
<N1MAX
); l1
++) {
504 fprintf(stderr
,"\rl1=%5d qopt=%12.6e",l1
,qopt
);
507 d1
= dhat(alpha
,k1
,h1
);
512 u1
= ursum1D(XX
,porder
,acut
,r1
,k1
,h1
,nalias
);
516 gdenom
= dsq
*usqsq(porder
,k1
,k2
,k3
,h1
,h2
,h3
);
518 symfac
= sym(l1
,n1max
);
522 rsqal
= crsqal(acut
,r1
,k1
,k2
,k3
,h1
,h2
,h3
,nalias
);
525 qopt
+= symfac
*(rsqal
- (gnumer
*gnumer
)/gdenom
);
529 fprintf(stderr
,"\n");
530 *ppval
= pval
/(box1
*box2
*box3
);
531 *zzval
= zval
/(box1
*box2
*box3
);
532 *eeref
= eref
/(box1
*box2
*box3
);
533 *qqopt
= qopt
/(box1
*box2
*box3
);
536 void read_params(char *fn
,t_inputrec
*ir
,rvec boxs
)
542 /* Read topology and coordinates */
543 read_tpx(fn
,&step
,&t
,&lambda
,ir
,box
,&natoms
,NULL
,NULL
,NULL
,NULL
);
544 for(m
=0; (m
<DIM
); m
++)
548 int main(int argc
,char *argv
[])
551 const real gold
=0.38197;
553 int n1max
,n2max
,n3max
;
560 /* bool bNL=FALSE; */
562 real pval
,zval
,eref
,qopt
,norm
;
563 real alpha0
,alpha1
,alpha2
,alpha3
,alptol
;
566 /* int ii,jj,kk,nn; */
569 { efTPX
, NULL
, NULL
, ffREAD
},
570 { efHAT
, "-o", "ghat", ffWRITE
}
572 #define NFILE asize(fnm)
573 static bool bVerbose
=FALSE
,bCubic
=TRUE
,bSym
=TRUE
;
574 static t_pargs pa
[] = {
575 { "-v", FALSE
, etBOOL
, &bVerbose
, "Verbose on"},
576 { "-cubic", FALSE
, etBOOL
, &bCubic
, "Force beta to be the same in all directions" },
577 { "-sym", FALSE
, etBOOL
, &bSym
, "HIDDENUse symmetry for the generation of ghat function (turn off for debugging only!)" }
580 CopyRight(stdout
,argv
[0]);
581 parse_common_args(&argc
,argv
,0,TRUE
,NFILE
,fnm
,asize(pa
),pa
,0,NULL
,0,NULL
);
583 read_params(ftp2fn(efTPX
,NFILE
,fnm
),&ir
,box
);
585 r1
= ir
.rcoulomb_switch
;
593 /* These are not parameters. They are fixed.
594 * Luty et al. determined their optimal values to be 2.
600 set_LRconsts(stdout
,r1
,acut
,box
,NULL
);
602 printf("Grid cell size is %8.4f x %8.4f x %8.4f nm\n",h1
,h2
,h3
);
604 ghat
=mk_rgrid(n1max
,n2max
,n3max
);
612 calc(bSym
,bVerbose
,n1max
,n2max
,n3max
,h1
,h2
,h3
,
613 nalias
,porder
,acut
,r1
,alpha
,bSearch
,
614 ghat
,&pval
,&zval
,&eref
,&qopt
);
620 calc(bSym
,bVerbose
,n1max
,n2max
,n3max
,h1
,h2
,h3
,
621 nalias
,porder
,acut
,r1
,alpha0
,bSearch
,
622 ghat
,&pval
,&zval
,&eref
,&q0
);
623 calc(bSym
,bVerbose
,n1max
,n2max
,n3max
,h1
,h2
,h3
,
624 nalias
,porder
,acut
,r1
,alpha1
,bSearch
,
625 ghat
,&pval
,&zval
,&eref
,&q1
);
626 calc(bSym
,bVerbose
,n1max
,n2max
,n3max
,h1
,h2
,h3
,
627 nalias
,porder
,acut
,r1
,alpha3
,bSearch
,
628 ghat
,&pval
,&zval
,&eref
,&q3
);
630 /* if ( (q1 > q0) || (q1 > q3) )
631 fatal_error(0,"oops q1=%f,q0=%f,q3=%f",q1,q0,q3); */
632 alpha2
= alpha1
+ gold
*(alpha3
-alpha1
);
633 calc(bSym
,bVerbose
,n1max
,n2max
,n3max
,h1
,h2
,h3
,
634 nalias
,porder
,acut
,r1
,alpha2
,bSearch
,
635 ghat
,&pval
,&zval
,&eref
,&q2
);
639 fprintf(stderr
,"q0 = %10g, q1= %10g, q2 = %10g, q3 = %10g\n",
642 while ((!bConv
) && (niter
< mxiter
)) {
643 fprintf(stderr
,"%2d %10.4f %10.4f %10.4f %10.4f\n",
644 niter
,alpha0
,alpha1
,alpha2
,alpha3
);
651 alpha2
= alpha1
+ gold
*(alpha3
-alpha1
);
652 calc(bSym
,bVerbose
,n1max
,n2max
,n3max
,h1
,h2
,h3
,
653 nalias
,porder
,acut
,r1
,alpha2
,bSearch
,
654 ghat
,&pval
,&zval
,&eref
,&q2
);
661 alpha1
= alpha2
- gold
*(alpha2
-alpha0
);
662 calc(bSym
,bVerbose
,n1max
,n2max
,n3max
,h1
,h2
,h3
,
663 nalias
,porder
,acut
,r1
,alpha1
,bSearch
,
664 ghat
,&pval
,&zval
,&eref
,&q1
);
666 if ((alpha3
-alpha0
) < alptol
)
672 calc(bSym
,bVerbose
,n1max
,n2max
,n3max
,h1
,h2
,h3
,
673 nalias
,porder
,acut
,r1
,alpha
,bSearch
,
674 ghat
,&pval
,&zval
,&eref
,&qopt
);
678 calc(bSym
,bVerbose
,n1max
,n2max
,n3max
,h1
,h2
,h3
,
679 nalias
,porder
,acut
,r1
,alpha
,bSearch
,
680 ghat
,&pval
,&zval
,&eref
,&qopt
);
683 fprintf(stderr
,"%10g %10g %10g %10g %10g %10g\n",
684 acut
,r1
,pval
,zval
,eref
,qopt
);
685 norm
= sqr(1.0/(4.0*M_PI
*h1
*h1
))*(4.0/3.0*M_PI
*h1
*h1
*h1
);
687 pval
= sqrt(fabs(pval
)/norm
)*100.0;
688 zval
= sqrt(fabs(zval
)/norm
)*100.0;
689 eref
= sqrt(fabs(eref
)/norm
)*100.0;
690 qopt
= sqrt(fabs(qopt
)/norm
)*100.0;
692 beta
[XX
] = beta
[YY
] = beta
[ZZ
] = alpha
;
693 wr_ghat(ftp2fn(efHAT
,NFILE
,fnm
),n1max
,n2max
,n3max
,h1
,h2
,h3
,
694 ghat
,nalias
,porder
,niter
,bSym
,beta
,
695 r1
,acut
,pval
,zval
,eref
,qopt
);
697 /* fp=ftp2FILE(efHAT,NFILE,fnm,"w");
698 fprintf(fp,"%8d %8d %8d %15.10e %15.10e %15.10e\n",
699 n1max,n2max,n3max,h1,h2,h3);
700 fprintf(fp,"%8d %8d %8d %8d %15.10e %15.10e %15.10e\n",
701 nalias,porder,niter,bSym,alpha,alpha,alpha);
702 fprintf(fp,"%10g %10g %10g %10g %10g %10g\n",
703 acut,r1,pval,zval,eref,qopt);
705 int N1MAX,N2MAX,N3MAX;
717 for(ii=0; (ii<N1MAX); ii++) {
718 for(jj=0; (jj<N2MAX); jj++) {
719 for(kk=0,nn=1; (kk<N3MAX); kk++,nn++) {
721 fprintf(fp," %12.5e",ghat[ii][jj][kk]);
734 pr_scalar_gk("ghat.xvg",n1max
,n2max
,n3max
,box
,ghat
);