Changeset b70503 for pcp/src/excor.c


Ignore:
Timestamp:
Apr 21, 2008, 2:19:24 PM (17 years ago)
Author:
Frederik Heber <heber@…>
Children:
f7754e
Parents:
6c8ee7
git-author:
Frederik Heber <heber@…> (04/18/08 15:29:28)
git-committer:
Frederik Heber <heber@…> (04/21/08 14:19:24)
Message:

sinh_inverse(), CalcSE_GC() and DensityGradient() added for Gradient Correction XC

File:
1 edited

Legend:

Unmodified
Added
Removed
  • pcp/src/excor.c

    r6c8ee7 rb70503  
    787787  E->AllLocalDensityEnergy[CorrelationEnergy] = Factor*SumEc;
    788788  E->AllLocalDensityEnergy[ExchangeEnergy] = Factor*(SumEx); // - SumEx_GC);
     789}
     790
     791/** Returns \f$y = \sinh^{-1}(x)\f$.
     792 * Recall that \f$ x = sinh (y) =  \frac{\exp(y)-\exp(-y)}{2}\f$. Then, solve the in \f$\exp(y)\f$ quadratic
     793 * equation: \f$\exp(2y) - 1 - 2x\exp(y) = 0\f$ by pq-formula.
     794 * \param arg argument \f$x\f$
     795 * \return \f$\sinh^{-1}(x) = \ln(x+\sqrt{x^2+1})\f$
     796 */
     797inline static double sinh_inverse(double arg)
     798{
     799  return log(arg+sqrt(arg*arg+1));
     800}
     801
     802/** Gradient correction according to Becke '92.
     803 * \param EC ExCor structure
     804 * \param p \f$\rho\f$ local density
     805 * \param Dp \f$|\nabla \rho|\f$ local magnitude of density gradient
     806 * \return \f$b \rho^{4/3} \frac{x^2}{(1+6bx \sinh^-1 x}\f$ with \f$x = \frac{|\nabla \rho|}{\rho^{4/3}}\f$
     807 */
     808double CalcSE_GC(struct ExCor *EC, double p, double Dp)
     809{
     810  double res = 0.;
     811  double b = 0.0042;  // in atomic units, empirical constant fitted to noble gas atoms
     812  double x = Dp/pow(p, 4./3.);
     813  res = b * pow(p, 4./3.) * x/(1+6.*b*x*sinh_inverse(x));
     814 
     815  return res;
     816}
     817
     818/** Evaluates magnitude of gradient by simple 3-star.
     819 * \param *density density array
     820 * \param i current node
     821 * \param *Lev LatticeLevel structure for number of nodes per axis
     822 * \param *Lat Lattice structure for axis lengths
     823 * \return \f$|\nabla\rho|\f$
     824 */
     825double DensityGradient(fftw_real *density, int i, struct LatticeLevel *Lev, struct Lattice *Lat)
     826{
     827  double res=0., right_diff, left_diff;
     828  int neighbour[NDIM], nodes[NDIM];
     829  nodes[0] = Lev->Plan0.plan->local_nx;
     830  nodes[1] = Lev->Plan0.plan->N[1];
     831  nodes[2] = Lev->Plan0.plan->N[2]; 
     832  neighbour[0] = Lev->Plan0.plan->N[1] * Lev->Plan0.plan->N[2];
     833  neighbour[1] = Lev->Plan0.plan->N[2];
     834  neighbour[2] = 1.;
     835  int k, l, nr, i_check = i;
     836  double h;
     837
     838  //iS = n[2] + N[2]*(n[1] + N[1]*n0);  // howto access the array ...
     839
     840  for (k=NDIM-1;k>=0;k--) { // for each axis
     841    h = 0.;
     842    for (l=0;l<NDIM;l++)
     843      h += Lat->RealBasis[k*NDIM+l]/Lev->Plan0.plan->N[k];  // finite distance
     844    h = sqrt(h);
     845    // check which limit exists: right, left, both?
     846    right_diff = 0.;
     847    left_diff = 0.;
     848    nr = 0; // neighbour counter
     849    if (i_check % nodes[k] != nodes[k]-1) {// right neighbour?
     850      right_diff = density[i] - density[i+neighbour[k]];
     851      nr++;
     852    }
     853    if (i_check % nodes[k] != 0) { // left neighbour?
     854      left_diff = density[i] - density[i-neighbour[k]];
     855      nr++;
     856    }
     857    res += (left_diff + right_diff)/(h*nr) * (left_diff + right_diff)/(h*nr);
     858    i_check /= nodes[k];  // remove axis from i_check
     859  }
     860 
     861  return sqrt(res);
    789862}
    790863
Note: See TracChangeset for help on using the changeset viewer.