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 shat(real acut,real kmag,real r1)
88 return gk(kmag,acut,r1);
91 real dhat(real alpha,real k,real h)
95 dh = alpha*(sin(k*h)/h) + (1.0-alpha)*(sin(2.0*k*h)/(2.0*h) );
103 real cufrth(int porder,real k1,real k2,real k3,
104 real h1,real h2,real h3,int nalias)
106 real kn1,kn2,kn3,tmp;
113 tmp = uhat(porder,k1,k2,k3,h1,h2,h3);
114 ufrth = tmp*tmp*tmp*tmp;
118 for( n1 = -nalias; (n1<= nalias); n1++) {
119 for( n2 = -nalias; (n2<= nalias); n2++) {
120 for( n3 = -nalias; (n3<= nalias); n3++) {
121 kn1 = k1 + n1*twopi/h1;
122 kn2 = k2 + n2*twopi/h2;
123 kn3 = k3 + n3*twopi/h3;
124 tmp = uhat(porder,kn1,kn2,kn3,h1,h2,h3);
125 ufrth += tmp*tmp*tmp*tmp;
130 if (fabs(ufrth) < tol)
136 real crsqal(real acut,real r1,real k1,real k2,real k3,
137 real h1,real h2,real h3,int nalias)
141 real ksq,kmag,tmp,Rsqal;
150 ksq = k1*k1 + k2*k2 + k3*k3;
152 tmp = shat(acut,kmag,r1);
153 Rsqal = tmp*tmp/(ksq);
157 for(n1 = -nalias; (n1<= nalias); n1++) {
158 for( n2 = -nalias; (n2<= nalias); n2++) {
159 for( n3 = -nalias; (n3<= nalias); n3++) {
163 ksq = kn1*kn1 + kn2*kn2 + kn3*kn3;
165 tmp = shat(acut,kmag,r1);
166 Rsqal = Rsqal + tmp*tmp/ksq;
175 real usqsq(int porder,real k1,real k2,real k3,real h1,real h2,real h3)
177 const real tt=2.0/3.0;
178 const real tx=2.0/15.0;
179 real t1,t2,t3,t12,t22,t32,tmp;
189 tmp = (1.0-tt*t12)*(1-tt*t22)*(1-tt*t32);
190 else if (porder == 2)
191 tmp = ( (1.0 - t12 + tx*t12*t12)*
192 (1.0 - t22 + tx*t22*t22)*
193 (1.0 - t32 + tx*t32*t32) );
195 gmx_fatal(FARGS,"porder = %d in usqsq",porder);
200 real ursum(int term,int porder,real acut,real r1,
201 real k1,real k2,real k3,real h1,real h2,real h3,int nalias)
205 real kn1,kn2,kn3,urs,tmp;
215 c for large enough values of k, the terms become negligable
216 c if shat(k) = exp(-k^2/4*acut) < eps
217 c kcutsq = 4*alpha* (-ln(eps))
218 c eps = 10^-6, -ln(eps) = 14
219 c eps = 10^-10, -ln(eps) = 23
220 c eps = 10^-20, -ln(eps) = 46
222 c kcutsq = 4.0*acut*115;
226 if (term==XX) kt = k1;
227 if (term==YY) kt = k2;
228 if (term==ZZ) kt = k3;
229 ksq = k1*k1 + k2*k2 + k3*k3;
231 tmp = uhat(porder,k1,k2,k3,h1,h2,h3);
232 urs = tmp*tmp*kt*shat(acut,kmag,r1)/(ksq);
236 for(n1 = -nalias; (n1<= nalias); n1++) {
237 for( n2 = -nalias; (n2<= nalias); n2++) {
238 for( n3 = -nalias; (n3<= nalias); n3++) {
242 ksq = kn1*kn1 + kn2*kn2 + kn3*kn3;
244 if (term==XX) kt = kn1;
245 if (term==YY) kt = kn2;
246 if (term==ZZ) kt = kn3;
249 tmp = uhat(porder,kn1,kn2,kn3,h1,h2,h3);
251 urs = urs + tmp*tmp*kt*shat(acut,kmag,r1)/ksq;
260 real sym(int indx,int maxind)
262 if ( (indx == 0 ) || (indx == maxind/2) )
268 void calc(gmx_bool bSym,gmx_bool bVerbose,
269 const int n1max,const int n2max,const int n3max,
270 const real h1,const real h2,const real h3,
271 int nalias,int porder,real acut,real r1,const real alpha,
272 const gmx_bool bSearch,
273 real ***ghat,real *ppval,real *zzval,real *eeref,real *qqopt)
276 real k1,k2,k3,ksq,kmag;
277 real gnumer,dsq,gdenom,gsq;
278 real ufrth,rsqal,rsq;
282 real d1,d2,d3,u1,u2,u3,ss,gg;
283 real pval,zval,eref,qopt;
284 int N1MAX,N2MAX,N3MAX;
306 for(l1=0; (l1<N1MAX); l1++) {
308 fprintf(stderr,"\rl1=%5d qopt=%12.6e",l1,qopt);
311 d1 = dhat(alpha,k1,h1);
313 for(l2=0; (l2<N2MAX); l2++) {
315 d2 = dhat(alpha,k2,h2);
317 for(l3=0; (l3<N3MAX); l3++) {
318 if (((l1+l2+l3) == 0) /*|| (l1 == n1max/2) || (l2 == n2max/2) ||
323 ksq = k1*k1 + k2*k2 + k3*k3;
326 d3 = dhat(alpha,k3,h3);
327 u1 = ursum(XX,porder,acut,r1,k1,k2,k3,h1,h2,h3,nalias);
328 u2 = ursum(YY,porder,acut,r1,k1,k2,k3,h1,h2,h3,nalias);
329 u3 = ursum(ZZ,porder,acut,r1,k1,k2,k3,h1,h2,h3,nalias);
331 gnumer = d1*u1+d2*u2+d3*u3;
332 dsq = d1*d1+d2*d2+d3*d3;
333 gdenom = dsq*usqsq(porder,k1,k2,k3,h1,h2,h3);
335 symfac = sym(l1,n1max)*sym(l2,n2max)*sym(l3,n3max);
339 rsqal = crsqal(acut,r1,k1,k2,k3,h1,h2,h3,nalias);
342 qopt += (symfac*(rsqal - sqr(gnumer)/gdenom));
344 fprintf(debug,"rsqal: %10.3e, gnumer: %10.3e, gdenom: %10.3e, ratio: %10.3e\n",
345 rsqal,gnumer,gdenom,gnumer/gdenom);
348 if ((l1 == n1max/2) || (l2 == n2max/2) || (l3 == n3max/2))
349 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",
350 l1,l2,l3,d1,d2,d3,u1,u2,u3,gnumer,dsq,gdenom,
351 (gdenom == 0.0) ? 0 : gnumer/gdenom);
358 ghat[l1][l2][l3] = gg/EPSILON0;
361 ufrth = cufrth(porder,k1,k2,k3,h1,h2,h3,nalias);
362 pval = pval + symfac*
363 (dsq*gsq*(usqsq(porder,k1,k2,k3,h1,h2,h3)-ufrth));
365 zval = zval + symfac*
366 (dsq*gsq*ufrth - 2.0*gnumer*gnumer/gdenom + rsqal);
367 ss = shat(acut,kmag,r1);
369 eref = eref + symfac* (rsqal - rsq);
376 fprintf(stderr,"\n");
377 *ppval = pval/(box1*box2*box3);
378 *zzval = zval/(box1*box2*box3);
379 *eeref = eref/(box1*box2*box3);
380 *qqopt = qopt/(EPSILON0*box1*box2*box3);
383 void read_params(char *fn,t_inputrec *ir,rvec boxs)
389 /* Read topology and coordinates */
390 read_tpx(fn,&step,&t,&lambda,ir,box,&natoms,NULL,NULL,NULL,NULL);
391 for(m=0; (m<DIM); m++)
395 int main(int argc,char *argv[])
398 const real gold=0.38197;
400 int n1max,n2max,n3max;
406 gmx_bool bSearch,bConv;
407 /* gmx_bool bNL=FALSE; */
409 real pval,zval,eref,qopt,norm;
410 real alpha0,alpha1,alpha2,alpha3,alptol;
413 /* int ii,jj,kk,nn; */
416 { efTPX, NULL, NULL, ffREAD },
417 { efHAT, "-o", "ghat", ffWRITE }
419 #define NFILE asize(fnm)
420 static gmx_bool bVerbose=FALSE,bCubic=TRUE,bSym=TRUE;
421 static t_pargs pa[] = {
422 { "-v", FALSE, etBOOL, &bVerbose, "Verbose on"},
423 { "-cubic", FALSE, etBOOL, &bCubic, "Force beta to be the same in all directions" },
424 { "-sym", FALSE, etBOOL, &bSym, "HIDDENUse symmetry for the generation of ghat function (turn off for debugging only!)" }
427 CopyRight(stdout,argv[0]);
428 parse_common_args(&argc,argv,0,TRUE,NFILE,fnm,asize(pa),pa,0,NULL,0,NULL);
430 read_params(ftp2fn(efTPX,NFILE,fnm),&ir,box);
432 r1 = ir.rcoulomb_switch;
440 /* These are not parameters. They are fixed.
441 * Luty et al. determined their optimal values to be 2.
447 set_LRconsts(stdout,r1,acut,box,NULL);
449 printf("Grid cell size is %8.4f x %8.4f x %8.4f nm\n",h1,h2,h3);
451 ghat=mk_rgrid(n1max,n2max,n3max);
459 calc(bSym,bVerbose,n1max,n2max,n3max,h1,h2,h3,
460 nalias,porder,acut,r1,alpha,bSearch,
461 ghat,&pval,&zval,&eref,&qopt);
467 calc(bSym,bVerbose,n1max,n2max,n3max,h1,h2,h3,
468 nalias,porder,acut,r1,alpha0,bSearch,
469 ghat,&pval,&zval,&eref,&q0);
470 calc(bSym,bVerbose,n1max,n2max,n3max,h1,h2,h3,
471 nalias,porder,acut,r1,alpha1,bSearch,
472 ghat,&pval,&zval,&eref,&q1);
473 calc(bSym,bVerbose,n1max,n2max,n3max,h1,h2,h3,
474 nalias,porder,acut,r1,alpha3,bSearch,
475 ghat,&pval,&zval,&eref,&q3);
477 /* if ( (q1 > q0) || (q1 > q3) )
478 gmx_fatal(FARGS,"oops q1=%f,q0=%f,q3=%f",q1,q0,q3); */
479 alpha2 = alpha1 + gold*(alpha3-alpha1);
480 calc(bSym,bVerbose,n1max,n2max,n3max,h1,h2,h3,
481 nalias,porder,acut,r1,alpha2,bSearch,
482 ghat,&pval,&zval,&eref,&q2);
486 fprintf(stderr,"q0 = %10g, q1= %10g, q2 = %10g, q3 = %10g\n",
489 while ((!bConv) && (niter < mxiter)) {
490 fprintf(stderr,"%2d %10.4f %10.4f %10.4f %10.4f\n",
491 niter,alpha0,alpha1,alpha2,alpha3);
498 alpha2 = alpha1 + gold*(alpha3-alpha1);
499 calc(bSym,bVerbose,n1max,n2max,n3max,h1,h2,h3,
500 nalias,porder,acut,r1,alpha2,bSearch,
501 ghat,&pval,&zval,&eref,&q2);
508 alpha1 = alpha2 - gold*(alpha2-alpha0);
509 calc(bSym,bVerbose,n1max,n2max,n3max,h1,h2,h3,
510 nalias,porder,acut,r1,alpha1,bSearch,
511 ghat,&pval,&zval,&eref,&q1);
513 if ((alpha3-alpha0) < alptol)
519 calc(bSym,bVerbose,n1max,n2max,n3max,h1,h2,h3,
520 nalias,porder,acut,r1,alpha,bSearch,
521 ghat,&pval,&zval,&eref,&qopt);
525 calc(bSym,bVerbose,n1max,n2max,n3max,h1,h2,h3,
526 nalias,porder,acut,r1,alpha,bSearch,
527 ghat,&pval,&zval,&eref,&qopt);
530 fprintf(stderr,"%10g %10g %10g %10g %10g %10g\n",
531 acut,r1,pval,zval,eref,qopt);
532 norm = sqr(1.0/(4.0*M_PI*h1*h1))*(4.0/3.0*M_PI*h1*h1*h1);
534 pval = sqrt(fabs(pval)/norm)*100.0;
535 zval = sqrt(fabs(zval)/norm)*100.0;
536 eref = sqrt(fabs(eref)/norm)*100.0;
537 qopt = sqrt(fabs(qopt)/norm)*100.0;
539 beta[XX] = beta[YY] = beta[ZZ] = alpha;
540 wr_ghat(ftp2fn(efHAT,NFILE,fnm),n1max,n2max,n3max,h1,h2,h3,
541 ghat,nalias,porder,niter,bSym,beta,
542 r1,acut,pval,zval,eref,qopt);
544 /* fp=ftp2FILE(efHAT,NFILE,fnm,"w");
545 fprintf(fp,"%8d %8d %8d %15.10e %15.10e %15.10e\n",
546 n1max,n2max,n3max,h1,h2,h3);
547 fprintf(fp,"%8d %8d %8d %8d %15.10e %15.10e %15.10e\n",
548 nalias,porder,niter,bSym,alpha,alpha,alpha);
549 fprintf(fp,"%10g %10g %10g %10g %10g %10g\n",
550 acut,r1,pval,zval,eref,qopt);
552 int N1MAX,N2MAX,N3MAX;
564 for(ii=0; (ii<N1MAX); ii++) {
565 for(jj=0; (jj<N2MAX); jj++) {
566 for(kk=0,nn=1; (kk<N3MAX); kk++,nn++) {
568 fprintf(fp," %12.5e",ghat[ii][jj][kk]);
581 pr_scalar_gk("ghat.xvg",n1max,n2max,n3max,box,ghat);