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-2004, 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 * Gallium Rubidium Oxygen Manganese Argon Carbon Silicon
55 const real tol = 1e-8;
65 real uhat(int porder,real k1,real k2,real k3,real h1,real h2,real h3)
71 fac1 = sinx_x(k1*h1*0.5);
72 fac2 = sinx_x(k2*h2*0.5);
73 fac3 = sinx_x(k3*h3*0.5);
76 f123 = fac1*fac2*fac3;
77 for(i=1; (i<=porder+1); i++)
86 real uhat1D(int porder,real k1,real h1)
92 fac1 = sinx_x(k1*h1*0.5);
95 for(i=1; (i<=porder+1); i++)
104 real shat(real acut,real kmag,real r1)
106 return gk(kmag,acut,r1);
109 real dhat(real alpha,real k,real h)
113 dh = alpha*(sin(k*h)/h) + (1.0-alpha)*(sin(2.0*k*h)/(2.0*h) );
121 real cufrth(int porder,real k1,real k2,real k3,
122 real h1,real h2,real h3,int nalias)
124 real kn1,kn2,kn3,tmp;
131 tmp = uhat(porder,k1,k2,k3,h1,h2,h3);
132 ufrth = tmp*tmp*tmp*tmp;
136 for( n1 = -nalias; (n1<= nalias); n1++) {
137 for( n2 = -nalias; (n2<= nalias); n2++) {
138 for( n3 = -nalias; (n3<= nalias); n3++) {
139 kn1 = k1 + n1*twopi/h1;
140 kn2 = k2 + n2*twopi/h2;
141 kn3 = k3 + n3*twopi/h3;
142 tmp = uhat(porder,kn1,kn2,kn3,h1,h2,h3);
143 ufrth += tmp*tmp*tmp*tmp;
148 if (fabs(ufrth) < tol)
154 real crsqal(real acut,real r1,real k1,real k2,real k3,
155 real h1,real h2,real h3,int nalias)
159 real ksq,kmag,tmp,Rsqal;
168 ksq = k1*k1 + k2*k2 + k3*k3;
170 tmp = shat(acut,kmag,r1);
171 Rsqal = tmp*tmp/(ksq);
175 for(n1 = -nalias; (n1<= nalias); n1++) {
176 for( n2 = -nalias; (n2<= nalias); n2++) {
177 for( n3 = -nalias; (n3<= nalias); n3++) {
181 ksq = kn1*kn1 + kn2*kn2 + kn3*kn3;
183 tmp = shat(acut,kmag,r1);
184 Rsqal = Rsqal + tmp*tmp/ksq;
193 real usqsq(int porder,real k1,real k2,real k3,real h1,real h2,real h3)
195 const real tt=2.0/3.0;
196 const real tx=2.0/15.0;
197 real t1,t2,t3,t12,t22,t32,tmp;
207 tmp = (1.0-tt*t12)*(1-tt*t22)*(1-tt*t32);
208 else if (porder == 2)
209 tmp = ( (1.0 - t12 + tx*t12*t12)*
210 (1.0 - t22 + tx*t22*t22)*
211 (1.0 - t32 + tx*t32*t32) );
213 gmx_fatal(FARGS,"porder = %d in usqsq",porder);
218 real usqsq1D(int porder,real k1,real h1)
220 const real tt=2.0/3.0;
221 const real tx=2.0/15.0;
229 else if (porder == 2)
230 tmp = ( (1.0 - t12 + tx*t12*t12));
232 gmx_fatal(FARGS,"porder = %d in usqsq",porder);
237 real ursum(int term,int porder,real acut,real r1,
238 real k1,real k2,real k3,real h1,real h2,real h3,int nalias)
242 real kn1,kn2,kn3,urs,tmp;
252 c for large enough values of k, the terms become negligable
253 c if shat(k) = exp(-k^2/4*acut) < eps
254 c kcutsq = 4*alpha* (-ln(eps))
255 c eps = 10^-6, -ln(eps) = 14
256 c eps = 10^-10, -ln(eps) = 23
257 c eps = 10^-20, -ln(eps) = 46
259 c kcutsq = 4.0*acut*115;
263 if (term==XX) kt = k1;
264 if (term==YY) kt = k2;
265 if (term==ZZ) kt = k3;
266 ksq = k1*k1 + k2*k2 + k3*k3;
268 tmp = uhat(porder,k1,k2,k3,h1,h2,h3);
269 urs = tmp*tmp*kt*shat(acut,kmag,r1)/(ksq);
273 for(n1 = -nalias; (n1<= nalias); n1++) {
274 for( n2 = -nalias; (n2<= nalias); n2++) {
275 for( n3 = -nalias; (n3<= nalias); n3++) {
279 ksq = kn1*kn1 + kn2*kn2 + kn3*kn3;
281 if (term==XX) kt = kn1;
282 if (term==YY) kt = kn2;
283 if (term==ZZ) kt = kn3;
286 tmp = uhat(porder,kn1,kn2,kn3,h1,h2,h3);
288 urs = urs + tmp*tmp*kt*shat(acut,kmag,r1)/ksq;
297 real ursum1D(int term,int porder,real acut,real r1,real k1,real h1,int nalias)
309 c for large enough values of k, the terms become negligable
310 c if shat(k) = exp(-k^2/4*acut) < eps
311 c kcutsq = 4*alpha* (-ln(eps))
312 c eps = 10^-6, -ln(eps) = 14
313 c eps = 10^-10, -ln(eps) = 23
314 c eps = 10^-20, -ln(eps) = 46
317 /* kcutsq = 4.0*acut*115; */
320 if (term==1) kt = k1;
323 tmp = uhat1D(porder,k1,h1);
324 urs = tmp*tmp*kt*shat(acut,kmag,r1)/(EPSILON0*ksq);
328 for(n1 = -nalias; (n1<= nalias); n1++) {
331 /*c if (ksq.lt.kcutsq) then*/
332 if (term==XX) kt = kn1;
335 tmp = uhat1D(porder,kn1,h1);
337 urs = urs + tmp*tmp*kt*shat(acut,kmag,r1)/(EPSILON0*ksq);
345 real sym(int indx,int maxind)
347 if ( (indx == 0 ) || (indx == maxind/2) )
353 void calc(bool bSym,bool bVerbose,
354 const int n1max,const int n2max,const int n3max,
355 const real h1,const real h2,const real h3,
356 int nalias,int porder,real acut,real r1,const real alpha,
358 real ***ghat,real *ppval,real *zzval,real *eeref,real *qqopt)
361 real k1,k2,k3,ksq,kmag;
362 real gnumer,dsq,gdenom,gsq;
363 real ufrth,rsqal,rsq;
367 real d1,d2,d3,u1,u2,u3,ss,gg;
368 real pval,zval,eref,qopt;
369 int N1MAX,N2MAX,N3MAX;
391 for(l1=0; (l1<N1MAX); l1++) {
393 fprintf(stderr,"\rl1=%5d qopt=%12.6e",l1,qopt);
396 d1 = dhat(alpha,k1,h1);
398 for(l2=0; (l2<N2MAX); l2++) {
400 d2 = dhat(alpha,k2,h2);
402 for(l3=0; (l3<N3MAX); l3++) {
403 if (((l1+l2+l3) == 0) /*|| (l1 == n1max/2) || (l2 == n2max/2) ||
408 ksq = k1*k1 + k2*k2 + k3*k3;
411 d3 = dhat(alpha,k3,h3);
412 u1 = ursum(XX,porder,acut,r1,k1,k2,k3,h1,h2,h3,nalias);
413 u2 = ursum(YY,porder,acut,r1,k1,k2,k3,h1,h2,h3,nalias);
414 u3 = ursum(ZZ,porder,acut,r1,k1,k2,k3,h1,h2,h3,nalias);
416 gnumer = d1*u1+d2*u2+d3*u3;
417 dsq = d1*d1+d2*d2+d3*d3;
418 gdenom = dsq*usqsq(porder,k1,k2,k3,h1,h2,h3);
420 symfac = sym(l1,n1max)*sym(l2,n2max)*sym(l3,n3max);
424 rsqal = crsqal(acut,r1,k1,k2,k3,h1,h2,h3,nalias);
427 qopt += (symfac*(rsqal - sqr(gnumer)/gdenom));
429 fprintf(debug,"rsqal: %10.3e, gnumer: %10.3e, gdenom: %10.3e, ratio: %10.3e\n",
430 rsqal,gnumer,gdenom,gnumer/gdenom);
433 if ((l1 == n1max/2) || (l2 == n2max/2) || (l3 == n3max/2))
434 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",
435 l1,l2,l3,d1,d2,d3,u1,u2,u3,gnumer,dsq,gdenom,
436 (gdenom == 0.0) ? 0 : gnumer/gdenom);
443 ghat[l1][l2][l3] = gg/EPSILON0;
446 ufrth = cufrth(porder,k1,k2,k3,h1,h2,h3,nalias);
447 pval = pval + symfac*
448 (dsq*gsq*(usqsq(porder,k1,k2,k3,h1,h2,h3)-ufrth));
450 zval = zval + symfac*
451 (dsq*gsq*ufrth - 2.0*gnumer*gnumer/gdenom + rsqal);
452 ss = shat(acut,kmag,r1);
454 eref = eref + symfac* (rsqal - rsq);
461 fprintf(stderr,"\n");
462 *ppval = pval/(box1*box2*box3);
463 *zzval = zval/(box1*box2*box3);
464 *eeref = eref/(box1*box2*box3);
465 *qqopt = qopt/(EPSILON0*box1*box2*box3);
468 void calc1D(bool bSym,bool bVerbose,
469 const int n1max,const int n2max,const int n3max,
470 const real h1,const real h2,const real h3,
471 int nalias,int porder,real acut,real r1,const real alpha,
473 real ***ghat,real *ppval,real *zzval,real *eeref,real *qqopt)
477 real gnumer,dsq,gdenom;
483 real pval,zval,eref,qopt;
485 /* int N2MAX,N3MAX; */
489 /* N2MAX = n2max/2+1; */
490 /* N3MAX = n3max/2+1; */
509 for(l1=0; (l1<N1MAX); l1++) {
511 fprintf(stderr,"\rl1=%5d qopt=%12.6e",l1,qopt);
514 d1 = dhat(alpha,k1,h1);
519 u1 = ursum1D(XX,porder,acut,r1,k1,h1,nalias);
523 gdenom = dsq*usqsq(porder,k1,k2,k3,h1,h2,h3);
525 symfac = sym(l1,n1max);
529 rsqal = crsqal(acut,r1,k1,k2,k3,h1,h2,h3,nalias);
532 qopt += symfac*(rsqal - (gnumer*gnumer)/gdenom);
536 fprintf(stderr,"\n");
537 *ppval = pval/(box1*box2*box3);
538 *zzval = zval/(box1*box2*box3);
539 *eeref = eref/(box1*box2*box3);
540 *qqopt = qopt/(box1*box2*box3);
543 void read_params(char *fn,t_inputrec *ir,rvec boxs)
549 /* Read topology and coordinates */
550 read_tpx(fn,&step,&t,&lambda,ir,box,&natoms,NULL,NULL,NULL,NULL);
551 for(m=0; (m<DIM); m++)
555 int main(int argc,char *argv[])
558 const real gold=0.38197;
560 int n1max,n2max,n3max;
567 /* bool bNL=FALSE; */
569 real pval,zval,eref,qopt,norm;
570 real alpha0,alpha1,alpha2,alpha3,alptol;
573 /* int ii,jj,kk,nn; */
576 { efTPX, NULL, NULL, ffREAD },
577 { efHAT, "-o", "ghat", ffWRITE }
579 #define NFILE asize(fnm)
580 static bool bVerbose=FALSE,bCubic=TRUE,bSym=TRUE;
581 static t_pargs pa[] = {
582 { "-v", FALSE, etBOOL, &bVerbose, "Verbose on"},
583 { "-cubic", FALSE, etBOOL, &bCubic, "Force beta to be the same in all directions" },
584 { "-sym", FALSE, etBOOL, &bSym, "HIDDENUse symmetry for the generation of ghat function (turn off for debugging only!)" }
587 CopyRight(stdout,argv[0]);
588 parse_common_args(&argc,argv,0,TRUE,NFILE,fnm,asize(pa),pa,0,NULL,0,NULL);
590 read_params(ftp2fn(efTPX,NFILE,fnm),&ir,box);
592 r1 = ir.rcoulomb_switch;
600 /* These are not parameters. They are fixed.
601 * Luty et al. determined their optimal values to be 2.
607 set_LRconsts(stdout,r1,acut,box,NULL);
609 printf("Grid cell size is %8.4f x %8.4f x %8.4f nm\n",h1,h2,h3);
611 ghat=mk_rgrid(n1max,n2max,n3max);
619 calc(bSym,bVerbose,n1max,n2max,n3max,h1,h2,h3,
620 nalias,porder,acut,r1,alpha,bSearch,
621 ghat,&pval,&zval,&eref,&qopt);
627 calc(bSym,bVerbose,n1max,n2max,n3max,h1,h2,h3,
628 nalias,porder,acut,r1,alpha0,bSearch,
629 ghat,&pval,&zval,&eref,&q0);
630 calc(bSym,bVerbose,n1max,n2max,n3max,h1,h2,h3,
631 nalias,porder,acut,r1,alpha1,bSearch,
632 ghat,&pval,&zval,&eref,&q1);
633 calc(bSym,bVerbose,n1max,n2max,n3max,h1,h2,h3,
634 nalias,porder,acut,r1,alpha3,bSearch,
635 ghat,&pval,&zval,&eref,&q3);
637 /* if ( (q1 > q0) || (q1 > q3) )
638 gmx_fatal(FARGS,"oops q1=%f,q0=%f,q3=%f",q1,q0,q3); */
639 alpha2 = alpha1 + gold*(alpha3-alpha1);
640 calc(bSym,bVerbose,n1max,n2max,n3max,h1,h2,h3,
641 nalias,porder,acut,r1,alpha2,bSearch,
642 ghat,&pval,&zval,&eref,&q2);
646 fprintf(stderr,"q0 = %10g, q1= %10g, q2 = %10g, q3 = %10g\n",
649 while ((!bConv) && (niter < mxiter)) {
650 fprintf(stderr,"%2d %10.4f %10.4f %10.4f %10.4f\n",
651 niter,alpha0,alpha1,alpha2,alpha3);
658 alpha2 = alpha1 + gold*(alpha3-alpha1);
659 calc(bSym,bVerbose,n1max,n2max,n3max,h1,h2,h3,
660 nalias,porder,acut,r1,alpha2,bSearch,
661 ghat,&pval,&zval,&eref,&q2);
668 alpha1 = alpha2 - gold*(alpha2-alpha0);
669 calc(bSym,bVerbose,n1max,n2max,n3max,h1,h2,h3,
670 nalias,porder,acut,r1,alpha1,bSearch,
671 ghat,&pval,&zval,&eref,&q1);
673 if ((alpha3-alpha0) < alptol)
679 calc(bSym,bVerbose,n1max,n2max,n3max,h1,h2,h3,
680 nalias,porder,acut,r1,alpha,bSearch,
681 ghat,&pval,&zval,&eref,&qopt);
685 calc(bSym,bVerbose,n1max,n2max,n3max,h1,h2,h3,
686 nalias,porder,acut,r1,alpha,bSearch,
687 ghat,&pval,&zval,&eref,&qopt);
690 fprintf(stderr,"%10g %10g %10g %10g %10g %10g\n",
691 acut,r1,pval,zval,eref,qopt);
692 norm = sqr(1.0/(4.0*M_PI*h1*h1))*(4.0/3.0*M_PI*h1*h1*h1);
694 pval = sqrt(fabs(pval)/norm)*100.0;
695 zval = sqrt(fabs(zval)/norm)*100.0;
696 eref = sqrt(fabs(eref)/norm)*100.0;
697 qopt = sqrt(fabs(qopt)/norm)*100.0;
699 beta[XX] = beta[YY] = beta[ZZ] = alpha;
700 wr_ghat(ftp2fn(efHAT,NFILE,fnm),n1max,n2max,n3max,h1,h2,h3,
701 ghat,nalias,porder,niter,bSym,beta,
702 r1,acut,pval,zval,eref,qopt);
704 /* fp=ftp2FILE(efHAT,NFILE,fnm,"w");
705 fprintf(fp,"%8d %8d %8d %15.10e %15.10e %15.10e\n",
706 n1max,n2max,n3max,h1,h2,h3);
707 fprintf(fp,"%8d %8d %8d %8d %15.10e %15.10e %15.10e\n",
708 nalias,porder,niter,bSym,alpha,alpha,alpha);
709 fprintf(fp,"%10g %10g %10g %10g %10g %10g\n",
710 acut,r1,pval,zval,eref,qopt);
712 int N1MAX,N2MAX,N3MAX;
724 for(ii=0; (ii<N1MAX); ii++) {
725 for(jj=0; (jj<N2MAX); jj++) {
726 for(kk=0,nn=1; (kk<N3MAX); kk++,nn++) {
728 fprintf(fp," %12.5e",ghat[ii][jj][kk]);
741 pr_scalar_gk("ghat.xvg",n1max,n2max,n3max,box,ghat);