Beispiel #1
0
real do_ewald(t_inputrec *ir,
              rvec x[],        rvec f[],
              real chargeA[],  real chargeB[],
              rvec box,
              t_commrec *cr,   int natoms,
              matrix lrvir,    real ewaldcoeff,
              real lambda,     real *dvdlambda,
              struct gmx_ewald_tab_t *et)
{
    real     factor     = -1.0/(4*ewaldcoeff*ewaldcoeff);
    real     scaleRecip = 4.0*M_PI/(box[XX]*box[YY]*box[ZZ])*ONE_4PI_EPS0/ir->epsilon_r; /* 1/(Vol*e0) */
    real    *charge, energy_AB[2], energy;
    rvec     lll;
    int      lowiy, lowiz, ix, iy, iz, n, q;
    real     tmp, cs, ss, ak, akv, mx, my, mz, m2, scale;
    gmx_bool bFreeEnergy;

    if (cr != NULL)
    {
        if (PAR(cr))
        {
            gmx_fatal(FARGS, "No parallel Ewald. Use PME instead.\n");
        }
    }


    if (!et->eir) /* allocate if we need to */
    {
        snew(et->eir, et->kmax);
        for (n = 0; n < et->kmax; n++)
        {
            snew(et->eir[n], natoms);
        }
        snew(et->tab_xy, natoms);
        snew(et->tab_qxyz, natoms);
    }

    bFreeEnergy = (ir->efep != efepNO);

    clear_mat(lrvir);

    calc_lll(box, lll);
    /* make tables for the structure factor parts */
    tabulate_eir(natoms, x, et->kmax, et->eir, lll);

    for (q = 0; q < (bFreeEnergy ? 2 : 1); q++)
    {
        if (!bFreeEnergy)
        {
            charge = chargeA;
            scale  = 1.0;
        }
        else if (q == 0)
        {
            charge = chargeA;
            scale  = 1.0 - lambda;
        }
        else
        {
            charge = chargeB;
            scale  = lambda;
        }
        lowiy        = 0;
        lowiz        = 1;
        energy_AB[q] = 0;
        for (ix = 0; ix < et->nx; ix++)
        {
            mx = ix*lll[XX];
            for (iy = lowiy; iy < et->ny; iy++)
            {
                my = iy*lll[YY];
                if (iy >= 0)
                {
                    for (n = 0; n < natoms; n++)
                    {
                        et->tab_xy[n] = cmul(et->eir[ix][n][XX], et->eir[iy][n][YY]);
                    }
                }
                else
                {
                    for (n = 0; n < natoms; n++)
                    {
                        et->tab_xy[n] = conjmul(et->eir[ix][n][XX], et->eir[-iy][n][YY]);
                    }
                }
                for (iz = lowiz; iz < et->nz; iz++)
                {
                    mz  = iz*lll[ZZ];
                    m2  = mx*mx+my*my+mz*mz;
                    ak  = exp(m2*factor)/m2;
                    akv = 2.0*ak*(1.0/m2-factor);
                    if (iz >= 0)
                    {
                        for (n = 0; n < natoms; n++)
                        {
                            et->tab_qxyz[n] = rcmul(charge[n], cmul(et->tab_xy[n],
                                                                    et->eir[iz][n][ZZ]));
                        }
                    }
                    else
                    {
                        for (n = 0; n < natoms; n++)
                        {
                            et->tab_qxyz[n] = rcmul(charge[n], conjmul(et->tab_xy[n],
                                                                       et->eir[-iz][n][ZZ]));
                        }
                    }

                    cs = ss = 0;
                    for (n = 0; n < natoms; n++)
                    {
                        cs += et->tab_qxyz[n].re;
                        ss += et->tab_qxyz[n].im;
                    }
                    energy_AB[q]  += ak*(cs*cs+ss*ss);
                    tmp            = scale*akv*(cs*cs+ss*ss);
                    lrvir[XX][XX] -= tmp*mx*mx;
                    lrvir[XX][YY] -= tmp*mx*my;
                    lrvir[XX][ZZ] -= tmp*mx*mz;
                    lrvir[YY][YY] -= tmp*my*my;
                    lrvir[YY][ZZ] -= tmp*my*mz;
                    lrvir[ZZ][ZZ] -= tmp*mz*mz;
                    for (n = 0; n < natoms; n++)
                    {
                        /*tmp=scale*ak*(cs*tab_qxyz[n].im-ss*tab_qxyz[n].re);*/
                        tmp       = scale*ak*(cs*et->tab_qxyz[n].im-ss*et->tab_qxyz[n].re);
                        f[n][XX] += tmp*mx*2*scaleRecip;
                        f[n][YY] += tmp*my*2*scaleRecip;
                        f[n][ZZ] += tmp*mz*2*scaleRecip;
#if 0
                        f[n][XX] += tmp*mx;
                        f[n][YY] += tmp*my;
                        f[n][ZZ] += tmp*mz;
#endif
                    }
                    lowiz = 1-et->nz;
                }
                lowiy = 1-et->ny;
            }
        }
    }

    if (!bFreeEnergy)
    {
        energy = energy_AB[0];
    }
    else
    {
        energy      = (1.0 - lambda)*energy_AB[0] + lambda*energy_AB[1];
        *dvdlambda += scaleRecip*(energy_AB[1] - energy_AB[0]);
    }

    lrvir[XX][XX] = -0.5*scaleRecip*(lrvir[XX][XX]+energy);
    lrvir[XX][YY] = -0.5*scaleRecip*(lrvir[XX][YY]);
    lrvir[XX][ZZ] = -0.5*scaleRecip*(lrvir[XX][ZZ]);
    lrvir[YY][YY] = -0.5*scaleRecip*(lrvir[YY][YY]+energy);
    lrvir[YY][ZZ] = -0.5*scaleRecip*(lrvir[YY][ZZ]);
    lrvir[ZZ][ZZ] = -0.5*scaleRecip*(lrvir[ZZ][ZZ]+energy);

    lrvir[YY][XX] = lrvir[XX][YY];
    lrvir[ZZ][XX] = lrvir[XX][ZZ];
    lrvir[ZZ][YY] = lrvir[YY][ZZ];

    energy *= scaleRecip;

    return energy;
}
Beispiel #2
0
real do_ewald(FILE *log,       bool bVerbose,
	      t_inputrec *ir,
	      rvec x[],        rvec f[],
		  real charge[],   rvec box,
	      t_commrec *cr,	      t_nsborder *nsb,
	      matrix lrvir, real ewaldcoeff)
{
  static    bool bFirst = TRUE;
  static    int       nx,ny,nz,kmax;
  static    cvec      **eir;
  static    t_complex  *tab_xy,*tab_qxyz;
  real factor=-1.0/(4*ewaldcoeff*ewaldcoeff);
  real energy;
  rvec lll;
  int  lowiy,lowiz,ix,iy,iz,n;
  real tmp,cs,ss,ak,akv,mx,my,mz,m2;
  
  if (bFirst) {
      if (bVerbose)
    fprintf(log,"Will do ordinary reciprocal space Ewald sum.\n");

    if (cr != NULL) {
      if (cr->nnodes > 1 || cr->nthreads>1)
	fatal_error(0,"No parallel Ewald. Use PME instead.\n");
    }
    
    nx = ir->nkx+1;
    ny = ir->nky+1;
    nz = ir->nkz+1;
    kmax = max(nx,max(ny,nz));
    snew(eir,kmax);
    for(n=0;n<kmax;n++)
      snew(eir[n],HOMENR(nsb));
    snew(tab_xy,HOMENR(nsb));
    snew(tab_qxyz,HOMENR(nsb));
    bFirst = FALSE;
  }
  clear_mat(lrvir);
  
  calc_lll(box,lll);
  /* make tables for the structure factor parts */
  tabulate_eir(HOMENR(nsb),x,kmax,eir,lll);
  
  lowiy=0;
  lowiz=1;
  energy=0;
  for(ix=0;ix<nx;ix++) {
    mx=ix*lll[XX];
    for(iy=lowiy;iy<ny;iy++) {
      my=iy*lll[YY];
      if(iy>=0) 
	for(n=0;n<HOMENR(nsb);n++) 
	  tab_xy[n]=cmul(eir[ix][n][XX],eir[iy][n][YY]);
      else 
	for(n=0;n<HOMENR(nsb);n++) 
	  tab_xy[n]=conjmul(eir[ix][n][XX],eir[-iy][n][YY]); 
      for(iz=lowiz;iz<nz;iz++) {
	mz=iz*lll[ZZ];	       
	m2=mx*mx+my*my+mz*mz;
	ak=exp(m2*factor)/m2;
	akv=2.0*ak*(1.0/m2-factor);  
	if(iz>=0) 
	  for(n=0;n<HOMENR(nsb);n++) 
	    tab_qxyz[n]=rcmul(charge[n],cmul(tab_xy[n],eir[iz][n][ZZ]));
	else 
	  for(n=0;n<HOMENR(nsb);n++) 
	    tab_qxyz[n]=rcmul(charge[n],conjmul(tab_xy[n],eir[-iz][n][ZZ]));
            
	cs=ss=0;
	for(n=0;n<HOMENR(nsb);n++) {
	  cs+=tab_qxyz[n].re;
	  ss+=tab_qxyz[n].im;
	}
	energy+=ak*(cs*cs+ss*ss);
	tmp=akv*(cs*cs+ss*ss);	       
	lrvir[XX][XX]-=tmp*mx*mx;
	lrvir[XX][YY]-=tmp*mx*my;
	lrvir[XX][ZZ]-=tmp*mx*mz;
	lrvir[YY][YY]-=tmp*my*my;
	lrvir[YY][ZZ]-=tmp*my*mz;
	lrvir[ZZ][ZZ]-=tmp*mz*mz;
	for(n=0;n<HOMENR(nsb);n++) {
	  tmp=ak*(cs*tab_qxyz[n].im-ss*tab_qxyz[n].re);
	  f[n][XX]+=tmp*mx;
	  f[n][YY]+=tmp*my;
	  f[n][ZZ]+=tmp*mz;
	}
	lowiz=1-nz;
      }
      lowiy=1-ny;
    }
  }   
  tmp=4.0*M_PI/(box[XX]*box[YY]*box[ZZ])*ONE_4PI_EPS0;
  for(n=0;n<HOMENR(nsb);n++) {
    f[n][XX]*=2*tmp;
    f[n][YY]*=2*tmp;
    f[n][ZZ]*=2*tmp;
  }
  lrvir[XX][XX]=-0.5*tmp*(lrvir[XX][XX]+energy);
  lrvir[XX][YY]=-0.5*tmp*(lrvir[XX][YY]);
  lrvir[XX][ZZ]=-0.5*tmp*(lrvir[XX][ZZ]);
  lrvir[YY][YY]=-0.5*tmp*(lrvir[YY][YY]+energy);
  lrvir[YY][ZZ]=-0.5*tmp*(lrvir[YY][ZZ]);
  lrvir[ZZ][ZZ]=-0.5*tmp*(lrvir[ZZ][ZZ]+energy);
  
  lrvir[YY][XX]=lrvir[XX][YY];
  lrvir[ZZ][XX]=lrvir[XX][ZZ];
  lrvir[ZZ][YY]=lrvir[YY][ZZ];
  
  energy*=tmp;
  
  return energy;
}
Beispiel #3
0
real do_ewald(FILE *log,       bool bVerbose,
	      t_inputrec *ir,
	      rvec x[],        rvec f[],
	      real chargeA[],  real chargeB[],
	      rvec box,
	      t_commrec *cr,   int natoms,
	      matrix lrvir,    real ewaldcoeff,
	      real lambda,     real *dvdlambda)
{
  static    bool bFirst = TRUE;
  static    int       nx,ny,nz,kmax;
  static    cvec      **eir;
  static    t_complex  *tab_xy,*tab_qxyz;
  real factor=-1.0/(4*ewaldcoeff*ewaldcoeff);
  real *charge,energy_AB[2],energy;
  rvec lll;
  int  lowiy,lowiz,ix,iy,iz,n,q;
  real tmp,cs,ss,ak,akv,mx,my,mz,m2,scale;
  bool bFreeEnergy;

  bFreeEnergy = (ir->efep != efepNO);

  if (bFirst) {
      if (bVerbose)
    fprintf(log,"Will do ordinary reciprocal space Ewald sum.\n");

    if (cr != NULL) {
      if (cr->nnodes > 1 || cr->nthreads>1)
	gmx_fatal(FARGS,"No parallel Ewald. Use PME instead.\n");
    }
    
    nx = ir->nkx+1;
    ny = ir->nky+1;
    nz = ir->nkz+1;
    kmax = max(nx,max(ny,nz));
    snew(eir,kmax);
    for(n=0;n<kmax;n++)
      snew(eir[n],natoms);
    snew(tab_xy,natoms);
    snew(tab_qxyz,natoms);
    bFirst = FALSE;
  }
  clear_mat(lrvir);
  
  calc_lll(box,lll);
  /* make tables for the structure factor parts */
  tabulate_eir(natoms,x,kmax,eir,lll);

  for(q=0; q<(bFreeEnergy ? 2 : 1); q++) {
    if (!bFreeEnergy) {
      charge = chargeA;
      scale = 1.0;
    } else if (q==0) {
      charge = chargeA;
      scale = 1.0 - lambda;
    } else {
      charge = chargeB;
      scale = lambda;
    }
    lowiy=0;
    lowiz=1;
    energy_AB[q]=0;
    for(ix=0;ix<nx;ix++) {
      mx=ix*lll[XX];
      for(iy=lowiy;iy<ny;iy++) {
	my=iy*lll[YY];
	if(iy>=0) 
	  for(n=0;n<natoms;n++) 
	    tab_xy[n]=cmul(eir[ix][n][XX],eir[iy][n][YY]);
	else 
	  for(n=0;n<natoms;n++) 
	    tab_xy[n]=conjmul(eir[ix][n][XX],eir[-iy][n][YY]); 
	for(iz=lowiz;iz<nz;iz++) {
	  mz=iz*lll[ZZ];	       
	  m2=mx*mx+my*my+mz*mz;
	  ak=exp(m2*factor)/m2;
	  akv=2.0*ak*(1.0/m2-factor);  
	  if(iz>=0) 
	    for(n=0;n<natoms;n++) 
	      tab_qxyz[n]=rcmul(charge[n],cmul(tab_xy[n],eir[iz][n][ZZ]));
	  else 
	    for(n=0;n<natoms;n++) 
	      tab_qxyz[n]=rcmul(charge[n],conjmul(tab_xy[n],eir[-iz][n][ZZ]));
	  
	  cs=ss=0;
	  for(n=0;n<natoms;n++) {
	    cs+=tab_qxyz[n].re;
	    ss+=tab_qxyz[n].im;
	  }
	  energy_AB[q]+=ak*(cs*cs+ss*ss);
	  tmp=scale*akv*(cs*cs+ss*ss);	       
	  lrvir[XX][XX]-=tmp*mx*mx;
	  lrvir[XX][YY]-=tmp*mx*my;
	  lrvir[XX][ZZ]-=tmp*mx*mz;
	  lrvir[YY][YY]-=tmp*my*my;
	  lrvir[YY][ZZ]-=tmp*my*mz;
	  lrvir[ZZ][ZZ]-=tmp*mz*mz;
	  for(n=0;n<natoms;n++) {
	    tmp=scale*ak*(cs*tab_qxyz[n].im-ss*tab_qxyz[n].re);
	    f[n][XX]+=tmp*mx;
	    f[n][YY]+=tmp*my;
	    f[n][ZZ]+=tmp*mz;
	  }
	  lowiz=1-nz;
	}
	lowiy=1-ny;
      }
    }
  }
  
  tmp=4.0*M_PI/(box[XX]*box[YY]*box[ZZ])*ONE_4PI_EPS0/ir->epsilon_r;

  if (!bFreeEnergy) {
    energy = energy_AB[0];
  } else {
    energy = (1.0 - lambda)*energy_AB[0] + lambda*energy_AB[1];
    *dvdlambda += tmp*(energy_AB[1] - energy_AB[0]);
  }
  for(n=0;n<natoms;n++) {
    f[n][XX]*=2*tmp;
    f[n][YY]*=2*tmp;
    f[n][ZZ]*=2*tmp;
  }
  lrvir[XX][XX]=-0.5*tmp*(lrvir[XX][XX]+energy);
  lrvir[XX][YY]=-0.5*tmp*(lrvir[XX][YY]);
  lrvir[XX][ZZ]=-0.5*tmp*(lrvir[XX][ZZ]);
  lrvir[YY][YY]=-0.5*tmp*(lrvir[YY][YY]+energy);
  lrvir[YY][ZZ]=-0.5*tmp*(lrvir[YY][ZZ]);
  lrvir[ZZ][ZZ]=-0.5*tmp*(lrvir[ZZ][ZZ]+energy);
  
  lrvir[YY][XX]=lrvir[XX][YY];
  lrvir[ZZ][XX]=lrvir[XX][ZZ];
  lrvir[ZZ][YY]=lrvir[YY][ZZ];
  
  energy*=tmp;
  
  return energy;
}