JDFTx  1.2.0
ExCorr_internal_LDA.h
Go to the documentation of this file.
1 /*-------------------------------------------------------------------
2 Copyright 2012 Ravishankar Sundararaman, Kendra Letchworth Weaver
3 
4 This file is part of JDFTx.
5 
6 JDFTx is free software: you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation, either version 3 of the License, or
9 (at your option) any later version.
10 
11 JDFTx is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15 
16 You should have received a copy of the GNU General Public License
17 along with JDFTx. If not, see <http://www.gnu.org/licenses/>.
18 -------------------------------------------------------------------*/
19 
20 #ifndef JDFTX_ELECTRONIC_EXCORR_INTERNAL_LDA_H
21 #define JDFTX_ELECTRONIC_EXCORR_INTERNAL_LDA_H
22 
24 
27 
37 };
38 
40 class FunctionalLDA : public Functional
41 {
42 public:
43  FunctionalLDA(LDA_Variant variant, double scaleFac=1.0);
44  bool needsSigma() const { return false; }
45  bool needsLap() const { return false; }
46  bool needsTau() const { return false; }
47  bool hasExchange() const
48  { switch(variant)
49  { case LDA_X_Slater:
50  case LDA_XC_Teter:
51  return true;
52  default:
53  return false;
54  }
55  }
56  bool hasCorrelation() const
57  { switch(variant)
58  { case LDA_C_PZ:
59  case LDA_C_PW:
60  case LDA_C_PW_prec:
61  case LDA_C_VWN:
62  case LDA_XC_Teter:
63  return true;
64  default:
65  return false;
66  }
67  }
68  bool hasKinetic() const
69  { switch(variant)
70  { case LDA_KE_TF:
71  return true;
72  default:
73  return false;
74  }
75  }
76  bool hasEnergy() const { return true; }
77 
81  void evaluate(int N, std::vector<const double*> n, std::vector<const double*> sigma,
82  std::vector<const double*> lap, std::vector<const double*> tau,
83  double* E, std::vector<double*> E_n, std::vector<double*> E_sigma,
84  std::vector<double*> E_lap, std::vector<double*> E_tau) const;
85 
86 private:
87  LDA_Variant variant;
88 };
89 
94 #define SwitchTemplate_LDA(variant,nCount, fTemplate,argList) \
95  switch(variant) \
96  { case LDA_X_Slater: fTemplate< LDA_X_Slater, nCount> argList; break; \
97  case LDA_C_PZ: fTemplate< LDA_C_PZ, nCount> argList; break; \
98  case LDA_C_PW: fTemplate< LDA_C_PW, nCount> argList; break; \
99  case LDA_C_PW_prec: fTemplate< LDA_C_PW_prec, nCount> argList; break; \
100  case LDA_C_VWN: fTemplate< LDA_C_VWN, nCount> argList; break; \
101  case LDA_XC_Teter: fTemplate< LDA_XC_Teter, nCount> argList; break; \
102  case LDA_KE_TF: fTemplate< LDA_KE_TF, nCount> argList; break; \
103  default: break; \
104  }
105 
108 template<LDA_Variant variant> __hostanddev__
109 double LDA_eval(double rs, double zeta, double& e_rs, double& e_zeta);
110 
114 template<LDA_Variant variant, int nCount> struct LDA_calc
115 { __hostanddev__ static
116  void compute(int i, array<const double*,nCount> n, double* E, array<double*,nCount> E_n, double scaleFac)
117  { //Compute nTot and rs, and ignore tiny densities:
118  double nTot = (nCount==1) ? n[0][i] : n[0][i]+n[1][i];
119  if(nTot<nCutoff) return;
120  double rs = pow((4.*M_PI/3.)*nTot, (-1./3));
121 
122  //Compute the per particle energy and its derivatives:
123  double zeta = (nCount==1) ? 0. : (n[0][i] - n[1][i])/nTot;
124  double e_rs, e_zeta, e = LDA_eval<variant>(rs, zeta, e_rs, e_zeta);
125 
126  //Compute and store final n derivatives if required
127  if(E_n[0]) //if this pointer is non-null, all the rest are assumed non-null as well
128  { double e_nTot = -e_rs * rs / (3. * nTot); //propagate rs derivative to nTot;
129  double E_nTot = e + nTot * e_nTot; //derivative of energy density per volume
130  E_n[0][i] += scaleFac*( E_nTot - e_zeta * (zeta-1) );
131  if(nCount>1) E_n[1][i] += scaleFac*( E_nTot - e_zeta * (zeta+1) );
132  }
133  E[i] += scaleFac*( nTot * e ); //energy density per volume
134  }
135 };
136 
138 template<int nCount> struct LDA_calc <LDA_KE_TF, nCount>
139 { __hostanddev__ static
140  void compute(int i, array<const double*,nCount> n, double* E, array<double*,nCount> E_n, double scaleFac)
141  { //Kinetic Energy is computed for each spin density, independently of the other
142  const double KEprefac = (0.3/nCount)*pow(3*M_PI*M_PI, 2./3.);
143  for(int s=0; s<nCount; s++)
144  { double ns = n[s][i] * nCount;
145  double nsTo23 = pow(ns, 2./3.);
146  E[i] += scaleFac*( KEprefac * nsTo23 * ns ); // KEprefac * ns^(5/3)
147  if(E_n[s])
148  E_n[s][i] += scaleFac*( (nCount * KEprefac * 5./3.) * nsTo23 );
149  }
150  }
151 };
152 
154 template<int nCount> struct LDA_calc <LDA_X_Slater, nCount>
155 { __hostanddev__ static
156  void compute(int i, array<const double*,nCount> n, double* E, array<double*,nCount> E_n, double scaleFac)
157  { //Exchange is computed for each spin density, independently of the other
158  const double Xprefac = (-0.75/nCount) * pow(3./M_PI, 1./3);
159  for(int s=0; s<nCount; s++)
160  { double ns = n[s][i] * nCount;
161  double nsCbrt = pow(ns, 1./3);
162  E[i] += scaleFac*( Xprefac * nsCbrt * ns ); // Xprefac * ns^(4/3)
163  if(E_n[s])
164  E_n[s][i] += scaleFac*( (nCount * Xprefac * 4./3) * nsCbrt );
165  }
166  }
167 };
168 
169 
170 
173 template<bool para> struct LDA_eval_C_PZ
174 { __hostanddev__ double operator()(double rs, double& e_rs) const
175  { if(rs<1.)
176  { const double a = para ? 0.0311 : 0.01555;
177  const double b = para ? -0.0480 : -0.0269;
178  const double c = para ? 0.0020 : 0.0007;
179  const double d = para ? -0.0116 : -0.0048;
180  e_rs = a/rs + c*(1+log(rs)) + d;
181  return (a + c*rs) * log(rs) + b + d*rs;
182  }
183  else
184  { const double gamma = para ? -0.1423 : -0.0843;
185  const double beta1 = para ? 1.0529 : 1.3981;
186  const double beta2 = para ? 0.3334 : 0.2611;
187  double denInv = 1./(1. + beta1*sqrt(rs) + beta2*rs);
188  double denPrime = beta1/(2.*sqrt(rs)) + beta2;
189  e_rs = gamma * (-denInv*denInv) * denPrime;
190  return gamma * denInv;
191  }
192  }
193 };
195 template<> __hostanddev__
196 double LDA_eval<LDA_C_PZ>(double rs, double zeta, double& e_rs, double& e_zeta)
197 { return spinInterpolate(rs, zeta, e_rs, e_zeta, LDA_eval_C_PZ<true>(), LDA_eval_C_PZ<false>());
198 }
199 
203 template<int spinID, bool prec=true> struct LDA_eval_C_PW
204 { __hostanddev__ double operator()(double rs, double& e_rs) const
205  { //PW fit parameters for paramagnetic ferromagnetic zeta-derivative
206  const double A = prec
207  ? ( (spinID==0) ? 0.0310907 : ((spinID==1) ? 0.01554535 : 0.0168869) )
208  : ( (spinID==0) ? 0.031091 : ((spinID==1) ? 0.015545 : 0.016887) );
209  const double alpha = (spinID==0) ? 0.21370 : ((spinID==1) ? 0.20548 : 0.11125);
210  const double beta1 = (spinID==0) ? 7.5957 : ((spinID==1) ? 14.1189 : 10.357);
211  const double beta2 = (spinID==0) ? 3.5876 : ((spinID==1) ? 6.1977 : 3.6231);
212  const double beta3 = (spinID==0) ? 1.6382 : ((spinID==1) ? 3.3662 : 0.88026);
213  const double beta4 = (spinID==0) ? 0.49294 : ((spinID==1) ? 0.62517 : 0.49671);
214  //Denominator of rational function inside the log of equation (10):
215  double x = sqrt(rs);
216  double den = (2*A)*x*(beta1 + x*(beta2 + x*(beta3 + x*(beta4))));
217  double den_x = (2*A)*(beta1 + x*(2*beta2 + x*(3*beta3 + x*(4*beta4))));
218  double den_rs = den_x * 0.5/x; //propagate x derivative to rs derivative
219  //The log term of equation (10):
220  double logTerm = log(1.+1./den);
221  double logTerm_rs = -den_rs/(den*(1.+den));
222  //Equation (10) and its derivative:
223  e_rs = -(2*A) * (alpha * logTerm + (1+alpha*rs) * logTerm_rs);
224  return -(2*A) * (1+alpha*rs) * logTerm;
225  }
226 };
228 template<> __hostanddev__
229 double LDA_eval<LDA_C_PW>(double rs, double zeta, double& e_rs, double& e_zeta)
230 { return spinInterpolate(rs, zeta, e_rs, e_zeta,
232  1.709921); //truncation of 4./(9*(2^(1./3) - 1)) at ~ single precision
233 }
235 template<> __hostanddev__
236 double LDA_eval<LDA_C_PW_prec>(double rs, double zeta, double& e_rs, double& e_zeta)
237 { return spinInterpolate(rs, zeta, e_rs, e_zeta,
238  LDA_eval_C_PW<0>(), LDA_eval_C_PW<1>(), LDA_eval_C_PW<2>()); //defaults are high-prec versions
239 }
240 
241 
244 template<int spinID> struct LDA_eval_C_VWN
245 { __hostanddev__ double operator()(double rs, double& e_rs) const
246  { //VWN fit parameters for paramagnetic ferromagnetic zeta-derivative
247  const double A = (spinID==0) ? 0.0310907 : ((spinID==1) ? 0.01554535 : 1./(6.*M_PI*M_PI));
248  const double b = (spinID==0) ? 3.72744 : ((spinID==1) ? 7.06042 : 1.13107);
249  const double c = (spinID==0) ? 12.9352 : ((spinID==1) ? 18.0578 : 13.0045);
250  const double x0 = (spinID==0) ? -0.10498 : ((spinID==1) ? -0.32500 : -0.0047584);
251  const double X0 = c + x0*(b + x0);
252  const double Q = sqrt(4.*c - b*b);
253  double x = sqrt(rs);
254  double X = c + x*(b + x);
255  double X_x = 2*x + b;
256  //Three transcendental terms and their derivatives w.r.t x:
257  double atanTerm = (2./Q) * atan(Q/X_x), atanTerm_x = -4./(Q*Q + X_x*X_x);
258  double logTerm1 = log(x*x/X), logTerm1_x = 2./x - X_x/X;
259  double logTerm2 = log((x-x0)*(x-x0)/X), logTerm2_x = 2./(x-x0) - X_x/X;
260  //Correlation energy density and its derivatives:
261  double e = A*(logTerm1 + b * (atanTerm - (x0/X0)*(logTerm2 + (b+2*x0) * atanTerm)));
262  double e_x = A*(logTerm1_x + b * (atanTerm_x - (x0/X0)*(logTerm2_x + (b+2*x0) * atanTerm_x)));
263  e_rs = e_x * 0.5/x; //propagate x derivative to rs derivative
264  return e;
265  }
266 };
268 template<> __hostanddev__
269 double LDA_eval<LDA_C_VWN>(double rs, double zeta, double& e_rs, double& e_zeta)
270 { return spinInterpolate(rs, zeta, e_rs, e_zeta,
272 }
273 
274 
276 template<> __hostanddev__
277 double LDA_eval<LDA_XC_Teter>(double rs, double zeta, double& e_rs, double& e_zeta)
278 { //Value of pade coefficients at para, change in going to ferro
279  const double pa0 = 0.4581652932831429 , da0 = 0.119086804055547;
280  const double pa1 = 2.217058676663745 , da1 = 0.6157402568883345;
281  const double pa2 = 0.7405551735357053 , da2 = 0.1574201515892867;
282  const double pa3 = 0.01968227878617998, da3 = 0.003532336663397157;
283  const double pb2 = 4.504130959426697 , db2 = 0.2673612973836267;
284  const double pb3 = 1.110667363742916 , db3 = 0.2052004607777787;
285  const double pb4 = 0.02359291751427506, db4 = 0.004200005045691381;
286  //spin-interpolate coefficients to current zeta:
287  double f_zeta, f = spinInterpolation(zeta, f_zeta);
288  double a0 = pa0 + f * da0;
289  double a1 = pa1 + f * da1;
290  double a2 = pa2 + f * da2;
291  double a3 = pa3 + f * da3;
292  double b2 = pb2 + f * db2;
293  double b3 = pb3 + f * db3;
294  double b4 = pb4 + f * db4;
295  //Pade approximant:
296  double num = a0 + rs*(a1 + rs*(a2 + rs*(a3))); //numerator
297  double den = rs*(1. + rs*(b2 + rs*(b3 + rs*(b4)))); //denominator
298  double num_rs = a1 + rs*(2*a2 + rs*(3*a3)); //derivative of numerator w.r.t rs
299  double den_rs = 1. + rs*(2*b2 + rs*(3*b3 + rs*(4*b4))); //derivative of denominator w.r.t rs
300  double num_f = da0 + rs*(da1 + rs*(da2 + rs*(da3))); //derivative of numerator w.r.t f(zeta)
301  double den_f = rs*rs*(db2 + rs*(db3 + rs*(db4))); //derivative of denominator w.r.t f(zeta)
302  e_rs = (num*den_rs - den*num_rs)/(den*den);
303  e_zeta = (num*den_f - den*num_f)*f_zeta/(den*den);
304  return -num/den;
305 };
306 
307 #endif // JDFTX_ELECTRONIC_EXCORR_INTERNAL_LDA_H
ScalarField pow(const ScalarField &, double alpha)
Elementwise power (preserve input)
ScalarField sqrt(const ScalarField &)
Elementwise square root (preserve input)
bool needsSigma() const
return true if density gradients are used
Definition: ExCorr_internal_LDA.h:44
Definition: ExCorr_internal_LDA.h:244
LDA_Variant
Available LDA functionals.
Definition: ExCorr_internal_LDA.h:29
__hostanddev__ double LDA_eval< LDA_XC_Teter >(double rs, double zeta, double &e_rs, double &e_zeta)
Teter LSD exchange & correlation [Phys. Rev. B 54, 1703 (1996)].
Definition: ExCorr_internal_LDA.h:277
double scaleFac
scale factor (to support mixing for hybrid functionals)
Definition: ExCorr_internal.h:45
bool hasEnergy() const
whether total energy is meaningful for this functional
Definition: ExCorr_internal_LDA.h:76
__hostanddev__ double spinInterpolation(double zeta, double &f_zeta)
LDA spin interpolation function f(zeta) and its derivative.
Definition: ExCorr_internal.h:128
Vosko-Wilk-Nusair LDA correlation.
Definition: ExCorr_internal_LDA.h:34
__hostanddev__ double LDA_eval(double rs, double zeta, double &e_rs, double &e_zeta)
Perdew-Wang LDA correlation.
Definition: ExCorr_internal_LDA.h:32
Definition: ExCorr_internal_LDA.h:114
LDA exchange (Slater functional)
Definition: ExCorr_internal_LDA.h:30
ScalarField log(const ScalarField &)
Elementwise logarithm (preserve input)
void evaluate(int N, std::vector< const double * > n, std::vector< const double * > sigma, std::vector< const double * > lap, std::vector< const double * > tau, double *E, std::vector< double * > E_n, std::vector< double * > E_sigma, std::vector< double * > E_lap, std::vector< double * > E_tau) const
Definition: operators_internal.h:37
bool needsLap() const
return true if laplacian of density is used (MGGA)
Definition: ExCorr_internal_LDA.h:45
Definition: ExCorr_internal_LDA.h:173
bool hasKinetic() const
whether this functional includes kinetic energy
Definition: ExCorr_internal_LDA.h:68
Abstract base class for functionals.
Definition: ExCorr_internal.h:42
__hostanddev__ double LDA_eval< LDA_C_PW >(double rs, double zeta, double &e_rs, double &e_zeta)
Perdew-Wang correlation (original version, for numerical compatibility with LibXC&#39;s PW91) ...
Definition: ExCorr_internal_LDA.h:229
Common interface to the compute kernels shared by all LDA functionals.
Definition: ExCorr_internal_LDA.h:40
Perdew-Wang LDA correlation (with higher precision constants used in PBE)
Definition: ExCorr_internal_LDA.h:33
bool hasCorrelation() const
whether this functional includes correlation
Definition: ExCorr_internal_LDA.h:56
__hostanddev__ double spinInterpolate(double rs, double zeta, double &e_rs, double &e_zeta, const Para &para, const Ferro &ferro)
Spin-interpolate an LDA functional given its paramagnetic and ferromagnetic functors.
Definition: ExCorr_internal.h:138
Perdew-Zunger LDA correlation.
Definition: ExCorr_internal_LDA.h:31
__hostanddev__ double LDA_eval< LDA_C_VWN >(double rs, double zeta, double &e_rs, double &e_zeta)
Vosko-Wilk-Nusair correlation.
Definition: ExCorr_internal_LDA.h:269
bool needsTau() const
return true if orbital kinetic energy density is used (MGGA)
Definition: ExCorr_internal_LDA.h:46
__hostanddev__ double LDA_eval< LDA_C_PW_prec >(double rs, double zeta, double &e_rs, double &e_zeta)
Perdew-Wang correlation (extended precision version, for numerical compatibility with LibXC&#39;s PBE) ...
Definition: ExCorr_internal_LDA.h:236
Definition: ExCorr_internal_LDA.h:203
Teter LDA exchange and correlation.
Definition: ExCorr_internal_LDA.h:35
Thomas-Fermi kinetic energy functional.
Definition: ExCorr_internal_LDA.h:36
__hostanddev__ double LDA_eval< LDA_C_PZ >(double rs, double zeta, double &e_rs, double &e_zeta)
Perdew-Zunger correlation.
Definition: ExCorr_internal_LDA.h:196
bool hasExchange() const
whether this functional includes exchange
Definition: ExCorr_internal_LDA.h:47