Merge lp:~alesster/siesta/trunk_new_xc into lp:siesta
- trunk_new_xc
- Merge into trunk
Status: | Needs review |
---|---|
Proposed branch: | lp:~alesster/siesta/trunk_new_xc |
Merge into: | lp:siesta |
Diff against target: |
3150 lines (+2957/-16) 7 files modified
Docs/siesta.tex (+17/-0) Src/SiestaXC/ggaxc.f (+270/-5) Src/SiestaXC/vdwxc.F90 (+136/-6) Src/SiestaXC/vv_vdwxc.F90 (+2517/-0) Src/atom.F (+13/-2) Tests/Makefile (+3/-2) version.info (+1/-1) |
To merge this branch: | bzr merge lp:~alesster/siesta/trunk_new_xc |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Siesta Maintainers | Pending | ||
Review via email: mp+372423@code.launchpad.net |
Commit message
Description of the change
There were realized 4 new functionals:
SG4, GGA functional, keyword for XC.authors in fdf: SG4, sg4
Ref. L. A. Constantin et al, Phys. Rev. B 93, 045126 (2016)
SG4+VV10m, VDW functional, keyword for XC.authors in fdf: SG4VV, sg4vv
Ref. A. V. Terentjev et al, Computation 6, 7 (2018)
PBE+VV10, VDW functional, keyword for XC.authors in fdf: PBEVV, pbevv, PBEvv, pbeVV
Ref. H. Peng and J. P. Perdew, Phys. Rev. B 95, 0811105 (2017)
PBEsol+VV10s, VDW functional, keyword for XC.authors in fdf: PVESVVS, pbesvvs, PBESVVs, PBESvvs
Ref. A. V. Terentjev et al, Phys. Rev. B 98, 214108 (2018)
IMPORTANT NOTES:
During the testing two test examples were crashed with version 781:
h2o_filteret_basis and si001-diags
With new version 782 all tests were finished successfully exepting h2o_filteret_basis and si001-diags.
Check has shown the differences bwtween tested and refrenced output files. But it also gives the differences for the previous version 781.
Unmerged revisions
- 782. By Aleksandr V. Terentjev
-
-------------- This line and the following will be ignored --------------
modified:
Docs/siesta.tex
Src/SiestaXC/ggaxc.f
Src/SiestaXC/vdwxc.F90
Src/SiestaXC/vv_vdwxc. F90
Src/atom.F
Tests/Makefile
version.info
unknown:
Docs/branch- changes/ NOTES.trunk_ new_xc
Tests/ag_sg4/
Tests/graphite_ c6_sg4/
Tests/graphite_ vdw_pbesvvs/
Tests/graphite_ vdw_pbevv/
Tests/graphite_ vdw_sg4vv/
Tests/Reference/ ag_sg4. out
Tests/Reference/ graphite_ c6_sg4. out
Tests/Reference/ graphite_ vdw_pbesvvs. out
Tests/Reference/ graphite_ vdw_pbevv. out
Tests/Reference/ graphite_ vdw_sg4vv. out
Preview Diff
1 | === modified file 'Docs/siesta.tex' |
2 | --- Docs/siesta.tex 2019-08-22 09:05:46 +0000 |
3 | +++ Docs/siesta.tex 2019-09-06 14:47:07 +0000 |
4 | @@ -3723,6 +3723,10 @@ |
5 | implemented in \siesta) |
6 | |
7 | \item% |
8 | + \fdf*{SG4}: GGA functional based on semiclassical atom theory of Lucian A. Constantin, Aleksandrs Terentjevs, Fabio Della Sala, Pietro Cortona and Eduardo Fabiano, |
9 | + Phys. Rev. B \textbf{93}, 045126 (2016). |
10 | + |
11 | + \item% |
12 | \fdf*{DRSLL} (equivalent to \fdf*{DF1}): \xcidx{vdW-DF1} |
13 | \xcidx{DRSLL}% |
14 | van der Waals \xcidx{vdW} density functional (vdW-DF) \xcidx{vdW-DF} |
15 | @@ -3757,6 +3761,19 @@ |
16 | \fdf*{VV}: \xcidx{VV}% |
17 | vdW-DF functional of O. A. Vydrov and T. Van Voorhis, |
18 | J. Chem. Phys. \textbf{133}, 244103 (2010) |
19 | + |
20 | + \item% |
21 | + \fdf*{PBEVV}: vdW-DF functional (PBE+VV10L) with PBE exchange and correlation functionals and with non-local correlation term of O. A. Vydrov and T. Van Voorhis (VV). PBE+VV10L is the modification of PBE+rVV10L for \siesta\ of H. Peng and J. P. Perdew, Phys. Rev. B \textbf{95}, 0811105 (2017). |
22 | + |
23 | + \item% |
24 | + \fdf*{SG4VV}: vdW-DF functional (SG4+VV10m) with SG4 exchange and correlation functionals and with non-local correlation term of O. A. Vydrov and T. Van Voorhis (VV). |
25 | + SG4+VV10m is the modification of SG4+rVV10m functional for \siesta\ of Aleksandr V. Terentjev, Pietro Cortona, Lucian A. Constantin, José M. Pitarke |
26 | + Fabio Della Sala and Eduardo Fabiano, Computation \textbf{6}, 7 (2018). |
27 | + |
28 | + \item% |
29 | + \fdf*{PBESVVS}: vdW-DF functional (PBEsol+VV10s) with PBEsol exchange and correlation functionals and with non-local correlation term of O. A. Vydrov and |
30 | + T. Van Voorhis (VV). PBEsol+VV10s is the modification of PBEsol+rVV10s functional for \siesta\ of Aleksandr V. Terentjev, Lucian A. Constantin and J. M. Pitarke, |
31 | + Phys. Rev. B \textbf{98}, 214108 (2018). |
32 | |
33 | \end{itemize} |
34 | |
35 | |
36 | === modified file 'Src/SiestaXC/ggaxc.f' |
37 | --- Src/SiestaXC/ggaxc.f 2018-04-19 10:08:47 +0000 |
38 | +++ Src/SiestaXC/ggaxc.f 2019-09-06 14:47:07 +0000 |
39 | @@ -24,8 +24,9 @@ |
40 | ! b88x, ! Becke, PRA 38, 3098 (1988) (exchange only) |
41 | ! b88kbmx, ! Klimes et al, JPCM 22, 022201 (2009) (exchange only) |
42 | ! c09x, ! Cooper, PRB 81, 161104 (2010) (exchange only) |
43 | -! bhx ! Berland & Hyldgaard, PRB 89, 035412 (2014) (exchange only) |
44 | -! |
45 | +! bhx, ! Berland & Hyldgaard, PRB 89, 035412 (2014) (exchange only) |
46 | +! sg4xc ! GGA Constantin et al, PRB, 93, 045126 (2016) |
47 | +! |
48 | ! PUBLIC parameters, types, and variables available from this module: |
49 | ! none |
50 | ! |
51 | @@ -76,8 +77,9 @@ |
52 | . b88x, ! Becke, PRA 38, 3098 (1988) (exchange only) |
53 | . b88kbmx, ! Klimes et al, JPCM 22, 022201 (2009) (exchange only) |
54 | . c09x, ! Cooper, PRB 81, 161104 (2010) (exchange only) |
55 | - . bhx ! Berland & Hyldgaard, PRB 89, 035412 (2014) (exch. only) |
56 | - |
57 | + . bhx, ! Berland & Hyldgaard, PRB 89, 035412 (2014) (exch. only) |
58 | + . sg4xc ! GGA Constantin et al, PRB, 93, 045126 (2016) |
59 | + |
60 | PRIVATE ! Nothing is declared public beyond this point |
61 | |
62 | CONTAINS |
63 | @@ -255,6 +257,10 @@ |
64 | CALL PBESOLXC( IREL, NS, DD, GDD, |
65 | . EPSX, EPSC, dEXdDD, dECdDD, dEXdGDD, dECdGDD ) |
66 | |
67 | + ELSEIF (AUTHOR.EQ.'SG4'.OR.AUTHOR.EQ.'sg4') THEN |
68 | + CALL SG4XC( IREL, NS, DD, GDD, |
69 | + . EPSX, EPSC, dEXdDD, dECdDD, dEXdGDD, dECdGDD ) |
70 | + |
71 | ELSEIF (AUTHOR.EQ.'AM05' .OR. AUTHOR.EQ.'am05') THEN |
72 | CALL AM05XC( IREL, NS, DD, GDD, |
73 | . EPSX, EPSC, dEXdDD, dECdDD, dEXdGDD, dECdGDD ) |
74 | @@ -2756,4 +2762,263 @@ |
75 | |
76 | END SUBROUTINE C09X |
77 | |
78 | - END MODULE m_ggaxc |
79 | +! END MODULE m_ggaxc |
80 | + |
81 | +c |
82 | +c the SG4 subroutine |
83 | +c |
84 | + |
85 | + SUBROUTINE SG4XC( IREL, nspin, Dens, GDens, |
86 | + . EX, EC, DEXDD, DECDD, DEXDGD, DECDGD ) |
87 | + |
88 | +C ********************************************************************* |
89 | +C Implements GGA based on Semiclassical atom theory |
90 | +C Ref: L.A.Constantin et al, PRB, 93, 045126 (2016) |
91 | +C ******** INPUT ****************************************************** |
92 | +C INTEGER IREL : Relativistic-exchange switch (0=No, 1=Yes) |
93 | +C INTEGER nspin : Number of spin polarizations (1 or 2) |
94 | +C REAL*8 Dens(nspin) : Total electron density (if nspin=1) or |
95 | +C spin electron density (if nspin=2) |
96 | +C REAL*8 GDens(3,nspin) : Total or spin density gradient |
97 | +C ******** OUTPUT ***************************************************** |
98 | +C REAL*8 EX : Exchange energy density |
99 | +C REAL*8 EC : Correlation energy density |
100 | +C REAL*8 DEXDD(nspin) : Partial derivative |
101 | +C d(DensTot*Ex)/dDens(ispin), |
102 | +C where DensTot = Sum_ispin( Dens(ispin) ) |
103 | +C For a constant density, this is the |
104 | +C exchange potential |
105 | +C REAL*8 DECDD(nspin) : Partial derivative |
106 | +C d(DensTot*Ec)/dDens(ispin), |
107 | +C where DensTot = Sum_ispin( Dens(ispin) ) |
108 | +C For a constant density, this is the |
109 | +C correlation potential |
110 | +C REAL*8 DEXDGD(3,nspin): Partial derivative |
111 | +C d(DensTot*Ex)/d(GradDens(i,ispin)) |
112 | +C REAL*8 DECDGD(3,nspin): Partial derivative |
113 | +C d(DensTot*Ec)/d(GradDens(i,ispin)) |
114 | +C ********* UNITS **************************************************** |
115 | +C Lengths in Bohr |
116 | +C Densities in electrons per Bohr**3 |
117 | +C Energies in Hartrees |
118 | +C Gradient vectors in cartesian coordinates |
119 | +C ********* ROUTINES CALLED ****************************************** |
120 | +C EXCHNG, PW92C |
121 | +C ******************************************************************** |
122 | + |
123 | + use precision, only : dp |
124 | + |
125 | + implicit none |
126 | + INTEGER IREL, nspin |
127 | + real(dp) Dens(nspin), DECDD(nspin), DECDGD(3,nspin), |
128 | + . DEXDD(nspin), DEXDGD(3,nspin), GDens(3,nspin) |
129 | + |
130 | +C Internal variables |
131 | + INTEGER |
132 | + . IS, IX |
133 | + |
134 | + real(dp) |
135 | + . A, BETA, D(2), DADD, DECUDD, DENMIN, |
136 | + . DF1DD, DF2DD, DF3DD, DF4DD, DF1DGD, DF3DGD, DF4DGD, |
137 | + . DFCDD(2), DFCDGD(3,2), DFDD, DFDGD, DFXDD(2), DFXDGD(3,2), |
138 | + . DHDD, DHDGD, DKFDD, DKSDD, DPDD, DPDZ, DRSDD, |
139 | + . DS(2), DSDD, DSDGD, DT, DTDD, DTDGD, DZDD(2), |
140 | + . EC, ECUNIF, EX, EXUNIF, |
141 | + . F, F1, F2, F3, F4, FC, FX, FOUTHD, |
142 | + . GAMMA, GD(3,2), GDM(2), GDMIN, GDMS, GDMT, GDS, GDT(3), |
143 | + . H, HALF, KAPPA, KF, KFS, KS, MU, PHI, PI, RS, S, |
144 | + . T, THD, THRHLF, TWO, TWOTHD, VCUNIF(2), VXUNIF(2), ZETA, |
145 | +c Lucian: new variables |
146 | + . beta0, sigma, alpha, amu1, amu2, ak1, ak2, term1, dbetadd, |
147 | + . dterm1dd, dbetadgd, dadgd, dterm1dgd, xx1, xx2, dxx1ds, dxx2ds, |
148 | + . dfds |
149 | + |
150 | + |
151 | +C Lower bounds of density and its gradient to avoid divisions by zero |
152 | + PARAMETER ( DENMIN = 1.D-12 ) |
153 | + PARAMETER ( GDMIN = 1.D-12 ) |
154 | + |
155 | +C Fix some numerical parameters |
156 | + PARAMETER ( FOUTHD=4.D0/3.D0, HALF=0.5D0, |
157 | + . THD=1.D0/3.D0, THRHLF=1.5D0, |
158 | + . TWO=2.D0, TWOTHD=2.D0/3.D0 ) |
159 | + |
160 | +C Fix some more numerical constants |
161 | +c Lucian: constants for SG4 correlation and exchange |
162 | + PI = 4 * ATAN(1.D0) |
163 | + GAMMA = (1 - LOG(TWO)) / PI**2 |
164 | + BETA0=0.07903051884257d0 |
165 | + sigma=0.07d0 |
166 | + alpha=0.8d0 |
167 | +c |
168 | + amu1=0.042d0 |
169 | + amu2=0.218d0 |
170 | + ak1=0.56028717948717954d0 |
171 | + ak2=0.24371282051282048d0 |
172 | +C Translate density and its gradient to new variables |
173 | + IF (nspin .EQ. 1) THEN |
174 | + if(Dens(1).le.1.0d-12) Dens(1)=1.0d-12 |
175 | + D(1) = HALF * Dens(1) |
176 | + D(2) = D(1) |
177 | + DT = MAX( DENMIN, Dens(1) ) |
178 | + DO 10 IX = 1,3 |
179 | + GD(IX,1) = HALF * GDens(IX,1) |
180 | + GD(IX,2) = GD(IX,1) |
181 | + GDT(IX) = GDens(IX,1) |
182 | + 10 CONTINUE |
183 | + ELSE |
184 | + if(Dens(1).le.1.0d-12) Dens(1)=1.0d-12 |
185 | + if(Dens(2).le.1.0d-12) Dens(2)=1.0d-12 |
186 | + D(1) = Dens(1) |
187 | + D(2) = Dens(2) |
188 | + DT = MAX( DENMIN, Dens(1)+Dens(2) ) |
189 | + DO 20 IX = 1,3 |
190 | + GD(IX,1) = GDens(IX,1) |
191 | + GD(IX,2) = GDens(IX,2) |
192 | + GDT(IX) = GDens(IX,1) + GDens(IX,2) |
193 | + 20 CONTINUE |
194 | + ENDIF |
195 | + GDM(1) = SQRT( GD(1,1)**2 + GD(2,1)**2 + GD(3,1)**2 ) |
196 | + GDM(2) = SQRT( GD(1,2)**2 + GD(2,2)**2 + GD(3,2)**2 ) |
197 | + GDMT = SQRT( GDT(1)**2 + GDT(2)**2 + GDT(3)**2 ) |
198 | + GDMT = MAX( GDMIN, GDMT ) |
199 | + |
200 | +C Find local correlation energy and potential |
201 | + CALL PW92C( 2, D, ECUNIF, VCUNIF ) |
202 | + |
203 | +C Find total correlation energy |
204 | + RS = ( 3 / (4*PI*DT) )**THD |
205 | + KF = (3 * PI**2 * DT)**THD |
206 | + KS = SQRT( 4 * KF / PI ) |
207 | + ZETA = ( D(1) - D(2) ) / DT |
208 | + ZETA = MAX( -1.D0+DENMIN, ZETA ) |
209 | + ZETA = MIN( 1.D0-DENMIN, ZETA ) |
210 | + PHI = HALF * ( (1+ZETA)**TWOTHD + (1-ZETA)**TWOTHD ) |
211 | + T = GDMT / (2 * PHI * KS * DT) |
212 | +c Define beta |
213 | + if(t.ge.100.d0)t=100.d0 |
214 | + beta=beta0+sigma*t*(1.d0-dexp(-rs**2)) |
215 | +c |
216 | + F1 = ECUNIF / GAMMA / PHI**3 |
217 | + F2 = EXP(-F1) |
218 | + A = BETA / GAMMA / (F2-1) |
219 | + F3 = T**2 + A * T**4 |
220 | + F4 = BETA/GAMMA * F3 / (1 + A*F3) |
221 | +c Define phi**(alpha*t**3) term |
222 | + term1 = phi ** ( alpha * t **3 ) |
223 | + H = term1 * GAMMA * PHI**3 * LOG( 1 + F4 ) |
224 | +c |
225 | + FC = ECUNIF + H |
226 | + |
227 | +C Find correlation energy derivatives |
228 | + DRSDD = - (THD * RS / DT) |
229 | + DKFDD = THD * KF / DT |
230 | + DKSDD = HALF * KS * DKFDD / KF |
231 | + DZDD(1) = 1 / DT - ZETA / DT |
232 | + DZDD(2) = - (1 / DT) - ZETA / DT |
233 | + DPDZ = HALF * TWOTHD * ( 1/(1+ZETA)**THD - 1/(1-ZETA)**THD ) |
234 | + DO 40 IS = 1,2 |
235 | + DECUDD = ( VCUNIF(IS) - ECUNIF ) / DT |
236 | + DPDD = DPDZ * DZDD(IS) |
237 | + DTDD = (- T) * ( DPDD/PHI + DKSDD/KS + 1/DT ) |
238 | +c Derivative of beta |
239 | + dbetadd = sigma * DTDD * ( 1.d0 - dexp ( - rs ** 2 ) ) + |
240 | + . sigma * t * 2.d0 * rs * dexp ( - rs ** 2 ) * DRSDD |
241 | +c |
242 | + DF1DD = F1 * ( DECUDD/ECUNIF - 3*DPDD/PHI ) |
243 | + DF2DD = (- F2) * DF1DD |
244 | +c Derivative of A |
245 | + DADD = (- A) * DF2DD / (F2-1) + dbetadd / GAMMA / (F2-1) |
246 | +c |
247 | + DF3DD = (2*T + 4*A*T**3) * DTDD + DADD * T**4 |
248 | + DF4DD = F4 * ( DF3DD/F3 - (DADD*F3+A*DF3DD)/(1+A*F3) )+ |
249 | + . dbetadd/GAMMA * F3 / (1 + A*F3) |
250 | + |
251 | +c Derivative of term1 |
252 | + dterm1dd = term1 * ( alpha * 3.d0 * t * t * dtdd * dlog(phi) + |
253 | + . alpha * t * t * t / phi * dpdd ) |
254 | +c |
255 | +c Derivative of H |
256 | + DHDD= 3 * phi**2 * term1 * GAMMA * LOG( 1 + F4 ) * DPDD + |
257 | + . dterm1dd * GAMMA * PHI**3 * LOG( 1 + F4 ) + |
258 | + . term1 * GAMMA * PHI**3 * DF4DD / (1+F4) |
259 | +c |
260 | + DFCDD(IS) = VCUNIF(IS) + H + DT * DHDD |
261 | + DO 30 IX = 1,3 |
262 | + DTDGD = (T / GDMT) * GDT(IX) / GDMT |
263 | +c Derivative of beta with respect to gradient |
264 | + dbetadgd = sigma * DTDGD * ( 1.d0 - dexp ( - rs**2 ) ) |
265 | +c Derivative of A with respect to gradient |
266 | + dadgd = dbetadgd / GAMMA / (F2-1) |
267 | +c |
268 | + DF3DGD = DTDGD * ( 2 * T + 4 * A * T**3 ) + |
269 | + . dadgd * T**4 |
270 | +c |
271 | + DF4DGD = F4 * DF3DGD * ( 1/F3 - A/(1+A*F3) )+ |
272 | + . dbetadgd /GAMMA * F3 / (1 + A*F3) - |
273 | + . BETA /GAMMA * F3 / (1 + A*F3)**2 * dadgd *f3 |
274 | +c |
275 | + dterm1dgd = term1 * alpha * 3.d0 * t * t * dtdgd * dlog(phi) |
276 | +c |
277 | + DHDGD = term1 * GAMMA * PHI**3 * DF4DGD / (1+F4) + |
278 | + . dterm1dgd * GAMMA * PHI**3 * LOG( 1 + F4 ) |
279 | +c |
280 | + DFCDGD(IX,IS) = DT * DHDGD |
281 | + 30 CONTINUE |
282 | + 40 CONTINUE |
283 | + |
284 | +C Find exchange energy and potential |
285 | + FX = 0 |
286 | + DO 60 IS = 1,2 |
287 | + DS(IS) = MAX( DENMIN, 2 * D(IS) ) |
288 | + GDMS = MAX( GDMIN, 2 * GDM(IS) ) |
289 | + KFS = (3 * PI**2 * DS(IS))**THD |
290 | + S = GDMS / (2 * KFS * DS(IS)) |
291 | +c Exchange enhancement factor |
292 | + xx1=amu1*s*s/ak1 |
293 | + xx2=amu2*s*s/ak2 |
294 | + F=1+ak1+ak2-ak1/(1.d0+xx1+xx1**2+xx1**3+xx1**4)- |
295 | + . ak2/(1.d0+xx2) |
296 | +c |
297 | +c Note nspin=1 in call to exchng... |
298 | +c |
299 | + CALL EXCHNG( IREL, 1, DS(IS), EXUNIF, VXUNIF(IS) ) |
300 | + FX = FX + DS(IS) * EXUNIF * F |
301 | + |
302 | + DKFDD = THD * KFS / DS(IS) |
303 | + DSDD = S * ( -(DKFDD/KFS) - 1/DS(IS) ) |
304 | +c Derivative of exchange enhancement factor |
305 | + dxx1ds=amu1*2.d0*s/ak1 |
306 | + dxx2ds=amu2*2.d0*s/ak2 |
307 | + dfds=ak1/(1.d0+xx1+xx1**2+xx1**3+xx1**4)**2 * |
308 | + . dxx1ds*(1.d0+2.d0*xx1+3.d0*xx1**2+4.d0*xx1**3) + |
309 | + . ak2/(1.d0+xx2)**2 * dxx2ds |
310 | + dfdd=dfds*dsdd |
311 | + DFXDD(IS) = VXUNIF(IS) * F + DS(IS) * EXUNIF * DFDD |
312 | + |
313 | + DO 50 IX = 1,3 |
314 | + GDS = 2 * GD(IX,IS) |
315 | + DSDGD = (S / GDMS) * GDS / GDMS |
316 | +c |
317 | + DFDGD = dfds * DSDGD |
318 | +c |
319 | + DFXDGD(IX,IS) = DS(IS) * EXUNIF * DFDGD |
320 | + 50 CONTINUE |
321 | + 60 CONTINUE |
322 | + FX = HALF * FX / DT |
323 | + |
324 | +C Set output arguments |
325 | + EX = FX |
326 | + EC = FC |
327 | + DO 90 IS = 1,nspin |
328 | + DEXDD(IS) = DFXDD(IS) |
329 | + DECDD(IS) = DFCDD(IS) |
330 | + DO 80 IX = 1,3 |
331 | + DEXDGD(IX,IS) = DFXDGD(IX,IS) |
332 | + DECDGD(IX,IS) = DFCDGD(IX,IS) |
333 | + 80 CONTINUE |
334 | + 90 CONTINUE |
335 | + |
336 | + END SUBROUTINE SG4XC |
337 | + |
338 | + END MODULE m_ggaxc |
339 | |
340 | === modified file 'Src/SiestaXC/vdwxc.F90' |
341 | --- Src/SiestaXC/vdwxc.F90 2015-05-08 09:34:16 +0000 |
342 | +++ Src/SiestaXC/vdwxc.F90 2019-09-06 14:47:07 +0000 |
343 | @@ -257,12 +257,33 @@ |
344 | use m_vv_vdwxc, only: vv_vdw_get_kmesh ! Size and values of (kf,kg) mesh |
345 | use m_vv_vdwxc, only: vv_vdw_phi ! Interpolates rho1*rho2*phi(k1,k2,k) |
346 | use m_vv_vdwxc, only: vv_vdw_set_kcut ! Sets the planewave cutoff kc |
347 | - |
348 | +!! New vdw |
349 | + use m_sg4vv_vdwxc, only: sg4vv_vdw_beta ! Parameter beta of VV2010 functional |
350 | + use m_sg4vv_vdwxc, only: sg4vv_vdw_theta ! Func. theta of VV2010 functional |
351 | + use m_sg4vv_vdwxc, only: sg4vv_vdw_get_kmesh ! Size and values of (kf,kg) mesh |
352 | + use m_sg4vv_vdwxc, only: sg4vv_vdw_phi ! Interpolates rho1*rho2*phi(k1,k2,k) |
353 | + use m_sg4vv_vdwxc, only: sg4vv_vdw_set_kcut ! Sets the planewave cutoff kc |
354 | + |
355 | + use m_pbevv_vdwxc, only: pbevv_vdw_beta ! Parameter beta of VV2010 functional |
356 | + use m_pbevv_vdwxc, only: pbevv_vdw_theta ! Func. theta of VV2010 functional |
357 | + use m_pbevv_vdwxc, only: pbevv_vdw_get_kmesh ! Size and values of (kf,kg) mesh |
358 | + use m_pbevv_vdwxc, only: pbevv_vdw_phi ! Interpolates rho1*rho2*phi(k1,k2,k) |
359 | + use m_pbevv_vdwxc, only: pbevv_vdw_set_kcut ! Sets the planewave cutoff kc |
360 | + |
361 | + use m_pbesvvs_vdwxc, only: pbesvvs_vdw_beta ! Parameter beta of VV2010 functional |
362 | + use m_pbesvvs_vdwxc, only: pbesvvs_vdw_theta ! Func. theta of VV2010 functional |
363 | + use m_pbesvvs_vdwxc, only: pbesvvs_vdw_get_kmesh ! Size and values of (kf,kg) mesh |
364 | + use m_pbesvvs_vdwxc, only: pbesvvs_vdw_phi ! Interpolates rho1*rho2*phi(k1,k2,k) |
365 | + use m_pbesvvs_vdwxc, only: pbesvvs_vdw_set_kcut ! Sets the planewave cutoff kc |
366 | ! Used module parameters |
367 | use precision, only: dp ! Real double precision type |
368 | |
369 | #ifdef DEBUG_XC |
370 | use m_vv_vdwxc, only: vv_vdw_phiofr ! Interpolates rho1*rho2*phi(k1,k2,r) |
371 | +!! New use of vdw_phiofr |
372 | + use m_sg4vv_vdwxc, only: sg4vv_vdw_phiofr |
373 | + use m_pbevv_vdwxc, only: pbevv_vdw_phiofr |
374 | + use m_pbesvvs_vdwxc, only: pbesvvs_vdw_phiofr |
375 | use debugXC, only: udebug ! File unit for debug output |
376 | ! use plot_module, only: plot |
377 | #endif /* DEBUG_XC */ |
378 | @@ -348,7 +369,7 @@ |
379 | real(dp),parameter:: ytol = 1.e-15_dp ! Tol. for saturated q |
380 | |
381 | ! Private module variables and arrays |
382 | - character(len=5),save:: vdw_author='DRSLL' ! Functional 'flavour' name |
383 | + character(len=7),save:: vdw_author='PBESVVS' ! Functional 'flavour' name |
384 | real(dp),save:: dmesh(nd) ! Mesh points for phi(d1,d2) table |
385 | real(dp),save:: qmesh(mq) ! Mesh points for phi(q1,q2,r) |
386 | real(dp),save:: phi_table(0:3,0:3,nd,nd) ! Coefs. for bicubic interpolation |
387 | @@ -748,8 +769,18 @@ |
388 | ! Trap VV-version exception |
389 | #ifdef DEBUG_XC |
390 | if (vdw_author=='VV') then |
391 | - call vv_vdw_phiofr( r, phi ) |
392 | - return |
393 | + call vv_vdw_phiofr( r, phi ) |
394 | + return |
395 | +!! New vdw_phiofr |
396 | + elseif (vdw_author=='SG4VV') then |
397 | + call sg4vv_vdw_phiofr( r, phi ) |
398 | + return |
399 | + elseif (vdw_author=='PBEVV') then |
400 | + call pbevv_vdw_phiofr( r, phi ) |
401 | + return |
402 | + elseif (vdw_author=='PBESVVS') then |
403 | + call pbesvvs_vdw_phiofr( r, phi ) |
404 | + return |
405 | end if |
406 | #endif /* DEBUG_XC */ |
407 | |
408 | @@ -1362,6 +1393,22 @@ |
409 | dedrho = eps |
410 | dedgrho = 0 |
411 | return |
412 | +!! New vdw_beta |
413 | + elseif (vdw_author=='SG4VV') then |
414 | + eps = sg4vv_vdw_beta() |
415 | + dedrho = eps |
416 | + dedgrho = 0 |
417 | + return |
418 | + elseif (vdw_author=='PBEVV') then |
419 | + eps = pbevv_vdw_beta() |
420 | + dedrho = eps |
421 | + dedgrho = 0 |
422 | + return |
423 | + elseif (vdw_author=='PBESVVS') then |
424 | + eps = pbesvvs_vdw_beta() |
425 | + dedrho = eps |
426 | + dedgrho = 0 |
427 | + return |
428 | end if |
429 | |
430 | if (.not.initialized) then |
431 | @@ -1424,11 +1471,30 @@ |
432 | |
433 | ! Trap VV-version exception |
434 | if (vdw_author=='VV') then |
435 | - call vv_vdw_get_kmesh( nkf, nkg ) |
436 | + call vv_vdw_get_kmesh( nkf, nkg ) |
437 | n = nkf*nkg |
438 | if (present(q)) & |
439 | call die('vdw_get_qmesh: ERROR q-mesh not available for author=VV') |
440 | return |
441 | +!! New vdw_get_kmesh |
442 | + elseif (vdw_author=='SG4VV') then |
443 | + call sg4vv_vdw_get_kmesh( nkf, nkg ) |
444 | + n = nkf*nkg |
445 | + if (present(q)) & |
446 | + call die('vdw_get_qmesh: ERROR q-mesh not available for author=SG4VV') |
447 | + return |
448 | + elseif (vdw_author=='PBEVV') then |
449 | + call pbevv_vdw_get_kmesh( nkf, nkg ) |
450 | + n = nkf*nkg |
451 | + if (present(q)) & |
452 | + call die('vdw_get_qmesh: ERROR q-mesh not available for author=PBEVV') |
453 | + return |
454 | + elseif (vdw_author=='PBESVVS') then |
455 | + call pbesvvs_vdw_get_kmesh( nkf, nkg ) |
456 | + n = nkf*nkg |
457 | + if (present(q)) & |
458 | + call die('vdw_get_qmesh: ERROR q-mesh not available for author=PBESVVS') |
459 | + return |
460 | end if |
461 | |
462 | if (.not.qmesh_set) call set_qmesh() |
463 | @@ -1514,6 +1580,33 @@ |
464 | dEXdD, dEdDaux, dEXdGD, dEdGDaux ) |
465 | call GGAxc( 'PBE', iRel, nSpin, D, GD, epsAux, epsC, & |
466 | dEdDaux, dECdD, dEdGDaux, dECdGD ) |
467 | +!! New vdw functionals |
468 | + else if (vdw_author=='SG4VV' .or. vdw_author=='sg4vv') then |
469 | + ! A. V. Terentjev et al, Computation 6, 7 (2018) |
470 | + ! SG4 GGA for both exchange and correlation |
471 | + call GGAxc( 'SG4', iRel, nSpin, D, GD, epsX, epsAux, & |
472 | + dEXdD, dEdDaux, dEXdGD, dEdGDaux ) |
473 | + call GGAxc( 'SG4', iRel, nSpin, D, GD, epsAux, epsC, & |
474 | + dEdDaux, dECdD, dEdGDaux, dECdGD ) |
475 | + |
476 | + else if (vdw_author=='PBEVV' .or. vdw_author=='pbevv' .or. & |
477 | + vdw_author=='PBEvv' .or. vdw_author=='pbeVV' ) then |
478 | + ! H. Peng and J. P. Perdew, Phys. Rev. B 95, 0811105 (2017) |
479 | + ! PBE GGA for both exchange and correlation |
480 | + call GGAxc( 'PBE', iRel, nSpin, D, GD, epsX, epsAux, & |
481 | + dEXdD, dEdDaux, dEXdGD, dEdGDaux ) |
482 | + call GGAxc( 'PBE', iRel, nSpin, D, GD, epsAux, epsC, & |
483 | + dEdDaux, dECdD, dEdGDaux, dECdGD ) |
484 | + |
485 | + else if (vdw_author=='PBESVVS' .or. vdw_author=='pbesvvs' .or. & |
486 | + vdw_author=='PBESVVs' .or. vdw_author=='PBESvvs' ) then |
487 | + ! A. V. Terentjev et al, Phys. Rev. B 98, 214108 (2018) |
488 | + ! PBESOL GGA for both exchange and correlation |
489 | + call GGAxc( 'PBESOL', iRel, nSpin, D, GD, epsX, epsAux, & |
490 | + dEXdD, dEdDaux, dEXdGD, dEdGDaux ) |
491 | + call GGAxc( 'PBESOL', iRel, nSpin, D, GD, epsAux, epsC, & |
492 | + dEdDaux, dECdD, dEdGDaux, dECdGD ) |
493 | + |
494 | else |
495 | stop 'vdw_exchng ERROR: unknown author' |
496 | end if |
497 | @@ -1542,6 +1635,16 @@ |
498 | if (vdw_author=='VV') then |
499 | call vv_vdw_phi( k, phi, dphidk ) |
500 | return |
501 | +!! New vdw_phi |
502 | + elseif (vdw_author=='SG4VV') then |
503 | + call sg4vv_vdw_phi( k, phi, dphidk ) |
504 | + return |
505 | + elseif (vdw_author=='PBEVV') then |
506 | + call pbevv_vdw_phi( k, phi, dphidk ) |
507 | + return |
508 | + elseif (vdw_author=='PBESVVS') then |
509 | + call pbesvvs_vdw_phi( k, phi, dphidk ) |
510 | + return |
511 | end if |
512 | |
513 | if (.not.kcut_set) stop 'vdw_phi: ERROR: kcut must be previously set' |
514 | @@ -1605,6 +1708,13 @@ |
515 | zab = -0.8491_dp |
516 | else if (author=='VV') then |
517 | ! Vydrov and Van Voorhis, JCP 133, 244103 (2010) |
518 | +!! New vdw functionals |
519 | + else if (author=='SG4VV') then |
520 | + ! A. V. Terentjev et al, Computation 6, 7 (2018) |
521 | + else if (author=='PBEVV') then |
522 | + ! H. Peng and J. P. Perdew, Phys. Rev. B 95, 0811105 (2017) |
523 | + else if (author=='PBESVVS') then |
524 | + ! A. V. Terentjev et al, Phys. Rev. B 98, 214108 (2018) |
525 | else |
526 | stop 'vdw_set_author: ERROR: author not known' |
527 | end if |
528 | @@ -1630,8 +1740,18 @@ |
529 | |
530 | ! Trap VV-version exception |
531 | if (vdw_author=='VV') then |
532 | - call vv_vdw_set_kcut( kc ) |
533 | + call vv_vdw_set_kcut( kc ) |
534 | return |
535 | +!! New vdw_set_kcut |
536 | + elseif (vdw_author=='SG4VV') then |
537 | + call sg4vv_vdw_set_kcut( kc ) |
538 | + return |
539 | + elseif (vdw_author=='PBEVV') then |
540 | + call pbevv_vdw_set_kcut( kc ) |
541 | + return |
542 | + elseif (vdw_author=='PBESVVS') then |
543 | + call pbesvvs_vdw_set_kcut( kc ) |
544 | + return |
545 | end if |
546 | |
547 | if (kc == kcut) return ! Work alredy done |
548 | @@ -1780,6 +1900,16 @@ |
549 | if (vdw_author=='VV') then |
550 | call vv_vdw_theta( nspin, rhos, grhos, theta, dtdrho, dtdgrho ) |
551 | return |
552 | +!! New vdw_theta |
553 | + elseif (vdw_author=='SG4VV') then |
554 | + call sg4vv_vdw_theta( nspin, rhos, grhos, theta, dtdrho, dtdgrho ) |
555 | + return |
556 | + elseif (vdw_author=='PBEVV') then |
557 | + call pbevv_vdw_theta( nspin, rhos, grhos, theta, dtdrho, dtdgrho ) |
558 | + return |
559 | + elseif (vdw_author=='PBESVVS') then |
560 | + call pbesvvs_vdw_theta( nspin, rhos, grhos, theta, dtdrho, dtdgrho ) |
561 | + return |
562 | end if |
563 | |
564 | ns = min(nspin,2) |
565 | |
566 | === modified file 'Src/SiestaXC/vv_vdwxc.F90' |
567 | --- Src/SiestaXC/vv_vdwxc.F90 2016-05-10 10:45:36 +0000 |
568 | +++ Src/SiestaXC/vv_vdwxc.F90 2019-09-06 14:47:07 +0000 |
569 | @@ -993,3 +993,2520 @@ |
570 | end subroutine vv_vdw_theta |
571 | |
572 | END MODULE m_vv_vdwxc |
573 | + |
574 | +!!!==================SG4VV==================== |
575 | + |
576 | +MODULE m_sg4vv_vdwxc |
577 | + |
578 | +! Used module procedures |
579 | + use sys, only: die ! Termination routine |
580 | + use mesh1D, only: get_mesh ! Returns the mesh points |
581 | + use m_radfft, only: radfft ! Radial fast Fourier transform |
582 | + use alloc, only: re_alloc ! Re-allocation routine |
583 | + use mesh1D, only: set_mesh ! Sets a 1D mesh |
584 | + use interpolation,only: spline ! Sets spline interpolation |
585 | + use interpolation,only: splint ! Calculates spline interpolation |
586 | + |
587 | +! Used module parameters |
588 | + use precision, only: dp ! Real double precision type |
589 | + |
590 | +#ifdef DEBUG_XC |
591 | + use debugXC, only: udebug ! File unit for debug output |
592 | +! use plot_module, only: plot |
593 | +#endif /* DEBUG_XC */ |
594 | + |
595 | + implicit none |
596 | + |
597 | +! Called by m_vdwxc |
598 | +PUBLIC :: & |
599 | + sg4vv_vdw_beta, &! Returns parameter beta of the VV2010 functional |
600 | + sg4vv_vdw_theta, &! Finds function theta_ik(rho,grad_rho) |
601 | + sg4vv_vdw_get_kmesh, &! Returns size and values of (kf,kg) mesh |
602 | + sg4vv_vdw_phi, &! Finds and interpolates rho1*rho2*phi(k1,k2,k) |
603 | + sg4vv_vdw_set_kcut ! Sets the planewave cutoff kc of the integration grid |
604 | + |
605 | +#ifdef DEBUG_XC |
606 | +! Called by debugging test programs |
607 | +PUBLIC :: & |
608 | + sg4vv_vdw_phi_val, &! Kernel phi(kf1,kf2,kg1,kg2,r12) with no interpolation |
609 | + sg4vv_vdw_phiofr ! Kernel phi(k1,k2,r) at tabulated k1,k2-mesh values |
610 | +#endif /* DEBUG_XC */ |
611 | + |
612 | +PRIVATE ! Nothing is declared public beyond this point |
613 | + |
614 | +!! Set parameters of the SG4+rVV10m functional |
615 | +!! Ref. A. V. Terentjev et al, Computation 6, 7 (2018) |
616 | + real(dp),parameter:: vv_C = 0.0001 |
617 | + real(dp),parameter:: vv_b = 12.0 |
618 | +!! |
619 | + real(dp),parameter:: vv_beta = 0.00497 |
620 | + |
621 | + ! Mesh parameters for table of phi(k1,k2,r) and its Fourier transform |
622 | + character(len=*),parameter:: kernelPrefactor='rho' ! Prefactor of the |
623 | + ! nonlocal kernel for interpolation |
624 | + ! ('kf'|'kf2'|'sqr_rho'|'rho') |
625 | + integer, parameter:: nr = 2048 ! Radial mesh points (power of 2) |
626 | + real(dp),parameter:: rcut = 100._dp ! Radial cutoff: r>rcut => phi=0 |
627 | + real(dp),parameter:: rmin = 1.e-6_dp ! Min. radius as denominator |
628 | + integer, parameter:: nkf = 7 ! Number of Fermi wavevectors |
629 | + integer, parameter:: nkg = 5 ! Num. of grad(n)/n wavevectors |
630 | + integer, parameter:: nkfg = nkf*nkg ! Num. of (kf,kg) mesh points |
631 | + real(dp),parameter:: kfcut = 5.0_dp ! Max. Fermi wavevec. |
632 | + real(dp),parameter:: kgcut = 5.0_dp ! Max. grad(n)/n |
633 | + real(dp),parameter:: dkfmaxdkfmin = 20.0_dp ! Last/first kf mesh interval |
634 | + real(dp),parameter:: dkgmaxdkgmin = 2.0_dp ! Last/first kg mesh interval |
635 | + real(dp),parameter:: ktol = 1.e-12_dp ! 'out of range' tolerance |
636 | + real(dp),parameter:: amin = 1.e-12_dp ! tiny denominator to avoid /0 |
637 | + real(dp),parameter:: rhoMin = 1.e-10_dp ! Min. density for nonzero Vxc |
638 | + |
639 | + ! Parameters for cutoff function, used in radial Fourier transforms of phi |
640 | + integer, parameter:: ncut1 = 8 ! cutoff(x)=(1-x**ncut1)**ncut2 |
641 | + integer, parameter:: ncut2 = 4 |
642 | + |
643 | + ! Parameters for saturate function, used to enforce that q<qcut |
644 | + integer, parameter:: nsat = 15 ! h(x,xc)=1/(1/x**nsat+1/xc**nsat)**(1/nsat) |
645 | + ! nsat=15 approximately corresponds to |
646 | + ! nsat=12 for eq.(5) of Roman-Soler PRL |
647 | + |
648 | + ! Private module variables and arrays |
649 | + logical, save:: kcut_set=.false. ! Has kcut been set? |
650 | + logical, save:: kmesh_set=.false. ! Has (kf,kg) mesh been set? |
651 | + logical, save:: phi_table_set=.false. ! Has phi_table been set? |
652 | + integer, save:: nk ! Num. of radial mesh k-points |
653 | + real(dp),save:: dr ! r-mesh interval |
654 | + real(dp),save:: dk ! k-mesh interval |
655 | + real(dp),save:: kcut ! Planewave cutoff: k>kcut => phi=0 |
656 | + real(dp),save:: kmax ! Max. k vector in Fourier transforms |
657 | + real(dp),save:: kfmesh(nkf) ! Mesh points for Fermi wavevector |
658 | + real(dp),save:: kgmesh(nkg) ! Mesh points for grad(n)/n |
659 | + real(dp),pointer,save:: & |
660 | + phir(:,:,:)=>null(), &! Table of phi(r) |
661 | + phik(:,:,:)=>null(), &! Table of phi(k) |
662 | + d2phidr2(:,:,:)=>null(),&! Table of d^2(phi)/dr^2 |
663 | + d2phidk2(:,:,:)=>null() ! Table of d^2(phi)/dk^2 |
664 | + |
665 | +CONTAINS |
666 | + |
667 | +! ----------------------------------------------------------------------------- |
668 | + |
669 | +real(dp) function cutoff( x ) |
670 | + |
671 | +! Defines a smooth cutoff function that falls from y(0)=1 to y(1)=0 |
672 | + |
673 | + implicit none |
674 | + real(dp),intent(in):: x |
675 | + |
676 | + if (x<=0._dp) then |
677 | + cutoff = 1 |
678 | + else if (x>=1._dp) then |
679 | + cutoff = 0 |
680 | + else |
681 | + cutoff = (1-x**ncut1)**ncut2 |
682 | + end if |
683 | + |
684 | +end function cutoff |
685 | + |
686 | +!----------------------------------------------------------------------------- |
687 | + |
688 | +subroutine iofk( kf, kg, ikf, ikg ) |
689 | + |
690 | +! Finds indexes ikf and ikg such that kfmesh(ikf) <= kf < kfmesh(ikf+1) |
691 | +! and kgmesh(ikg) <= kg < kgmesh(ikg+1) in logarithmic meshes of the form |
692 | +! k(ik) = b*(exp((ik-1)*a)-1) |
693 | + |
694 | + implicit none |
695 | + real(dp), intent(in) :: kf, kg |
696 | + integer, intent(out):: ikf, ikg |
697 | + |
698 | + real(dp),save:: akf, akg, bkf, bkg |
699 | + logical, save:: first_call = .true. |
700 | + integer:: ik |
701 | + |
702 | + ! Mesh data initializations |
703 | + if (first_call) then |
704 | + ! Find logarithmic-mesh a & b parameters: x(j)=x(1)+b*(exp(a*(j-1))-1) |
705 | + akf = log( (kfmesh(nkf)-kfmesh(nkf-1)) / (kfmesh(2)-kfmesh(1)) ) / (nkf-2) |
706 | + akg = log( (kgmesh(nkg)-kgmesh(nkg-1)) / (kgmesh(2)-kgmesh(1)) ) / (nkg-2) |
707 | + akf = max( akf, amin ) |
708 | + akg = max( akg, amin ) |
709 | + bkf = (kfmesh(nkf) - kfmesh(1)) / (exp(akf*(nkf-1)) - 1) |
710 | + bkg = (kgmesh(nkg) - kgmesh(1)) / (exp(akg*(nkg-1)) - 1) |
711 | + ! Check that meshes are indeed logarithmic |
712 | + do ik = 1,nkf |
713 | + if (abs(kfmesh(ik)-kfmesh(1)-bkf*(exp(akf*(ik-1))-1))>ktol) & |
714 | + call die('sg4vv_vdw_iofk ERROR: kfmesh not logarithmic') |
715 | + end do |
716 | + do ik = 1,nkg |
717 | + if (abs(kgmesh(ik)-kgmesh(1)-bkg*(exp(akg*(ik-1))-1))>ktol) & |
718 | + call die('sg4vv_vdw_iofk ERROR: kgmesh not logarithmic') |
719 | + end do |
720 | + first_call = .false. |
721 | + end if |
722 | + |
723 | + ! Check that kf and kg are within interpolation range |
724 | + if (kf<kfmesh(1)-ktol .or. kf>kfmesh(nkf)+ktol .or. & |
725 | + kg<kgmesh(1)-ktol .or. kg>kgmesh(nkg)+ktol) then |
726 | + call die('sg4vv_vdw_iofk ERROR: (kf,kg) out of range') |
727 | + endif |
728 | + |
729 | + ! Find interpolation mesh intervals |
730 | + ikf = 1 + int( log( 1 + (kf-kfmesh(1))/bkf ) / akf ) |
731 | + ikg = 1 + int( log( 1 + (kg-kgmesh(1))/bkg ) / akg ) |
732 | + ikf = max( 1, ikf ) |
733 | + ikg = max( 1, ikg ) |
734 | + ikf = min( nkf-1, ikf ) |
735 | + ikg = min( nkg-1, ikg ) |
736 | + |
737 | +end subroutine iofk |
738 | + |
739 | +! ----------------------------------------------------------------------------- |
740 | + |
741 | +subroutine kofn( n, gn, kf, kg, dkfdn, dkgdn, dkfdgn, dkgdgn ) |
742 | + |
743 | +! Finds Fermi and gradient wavevectors from density and gradient |
744 | + |
745 | + implicit none |
746 | + real(dp), intent(in) :: n ! Electron density |
747 | + real(dp), intent(in) :: gn(3) ! Density gradient |
748 | + real(dp), intent(out):: kf ! Local Fermi wavevector |
749 | + real(dp), intent(out):: kg ! |grad(n)|/n |
750 | + real(dp), intent(out):: dkfdn ! dkf/dn |
751 | + real(dp), intent(out):: dkgdn ! dkg/dn |
752 | + real(dp), intent(out):: dkfdgn(3) ! dkf/dgn |
753 | + real(dp), intent(out):: dkgdgn(3) ! dkg/dgn |
754 | + |
755 | + real(dp):: gn2, pi |
756 | + |
757 | +! Trap exception for zero density |
758 | + if (n <= 1.e-30_dp) then |
759 | + kf = 0 |
760 | + kg = 0 |
761 | + dkfdn = 0 |
762 | + dkfdgn = 0 |
763 | + dkgdn = 0 |
764 | + dkgdgn = 0 |
765 | + return |
766 | + end if |
767 | + |
768 | +! Find kf and kg |
769 | + pi = acos(-1._dp) |
770 | + kf = (3*pi**2*n)**(1._dp/3) |
771 | + gn2 = sum(gn**2) |
772 | + kg = sqrt(gn2)/n |
773 | + |
774 | +! Find derivatives |
775 | + dkfdn = kf/n/3 |
776 | + dkfdgn = 0 |
777 | + dkgdn = -kg/n |
778 | + dkgdgn = kg*gn/gn2 |
779 | + |
780 | +end subroutine kofn |
781 | + |
782 | +!----------------------------------------------------------------------------- |
783 | + |
784 | +subroutine pofk( kf, kg, p, dpdkf, dpdkg ) |
785 | + |
786 | +! Finds the values and derivatives, at (kf,kg), of the bicubic polynomials |
787 | +! p_i(kf,kg) such that |
788 | +! y(kf,kg) = Sum_i p_i(kf,kg) * y_i |
789 | +! is the bicubic spline interpolation at (kf,kg) of (any) function y with |
790 | +! values y_i at mesh points (kfmesh,kgmesh)_i |
791 | + |
792 | + implicit none |
793 | + real(dp),intent(in) :: kf, kg ! point at which the polynomials are required |
794 | + real(dp),intent(out):: p(nkfg) ! polynomial values at (kf,kg) |
795 | + real(dp),intent(out):: dpdkf(nkfg) ! dp/dkf at (kf,kg) |
796 | + real(dp),intent(out):: dpdkg(nkfg) ! dp/dkg at (kf,kg) |
797 | + |
798 | + integer :: ikf, ikg, ikfg, ikf0, ikg0 |
799 | + real(dp):: a, b, dk, dkf0dkf, dkg0dkg, kf0, kg0 |
800 | + real(dp):: pkf0(nkf), dpkfdkf0(nkf), pkg0(nkg), dpkgdkg0(nkg) |
801 | + logical, save :: first_call=.true. |
802 | + real(dp),save :: pkf(nkf,nkf), d2pkfdkf2(nkf,nkf) |
803 | + real(dp),save :: pkg(nkg,nkg), d2pkgdkg2(nkg,nkg) |
804 | + |
805 | +! Set up spline polynomial basis |
806 | + if (first_call) then |
807 | + do ikf = 1,nkf |
808 | + pkf(:,ikf) = 0 ! ikf'th polynomial pkf(:,ikf) is one at kfmesh(ikf) |
809 | + pkf(ikf,ikf) = 1 ! and zero at all other points |
810 | + call spline( kfmesh, pkf(:,ikf), nkf, 1.e30_dp, 1.e30_dp, & |
811 | + d2pkfdkf2(:,ikf) ) |
812 | +! call spline( kfmesh, pkf(:,ikf), nkf, 0._dp, 0._dp, d2pkfdkf2(:,ikf) ) |
813 | + end do |
814 | + do ikg = 1,nkg |
815 | + pkg(:,ikg) = 0 |
816 | + pkg(ikg,ikg) = 1 |
817 | + call spline( kgmesh, pkg(:,ikg), nkg, 1.e30_dp, 1.e30_dp, & |
818 | + d2pkgdkg2(:,ikg) ) |
819 | +! call spline( kgmesh, pkg(:,ikg), nkg, 0._dp, 0._dp, d2pkgdkg2(:,ikg) ) |
820 | + end do |
821 | + |
822 | +! DEBUG |
823 | + open(22,file='pkf.dat') |
824 | + do ikf = 1,nkf |
825 | + write(22,'(20e15.6)') kfmesh(ikf), pkf(:,ikf), d2pkfdkf2(:,ikf) |
826 | + end do |
827 | + close(22) |
828 | + open(22,file='pkg.dat') |
829 | + do ikg = 1,nkg |
830 | + write(22,'(20e15.6)') kgmesh(ikg), pkg(:,ikg), d2pkgdkg2(:,ikg) |
831 | + end do |
832 | + close(22) |
833 | +! END DEBUG |
834 | + |
835 | + first_call = .false. |
836 | + end if |
837 | + |
838 | +! 'Saturate' (kf,kg) values to bring them to interpolation range |
839 | + call saturate( kf, kfcut, kf0, dkf0dkf ) |
840 | + call saturate( kg, kgcut, kg0, dkg0dkg ) |
841 | + |
842 | +! Find interval of k mesh in which (kf0,kg0) point is included |
843 | + call iofk( kf0, kg0, ikf0, ikg0 ) |
844 | + |
845 | +! Evaluate pkf polynomials of spline basis at kf0 |
846 | +! The splint code is in-lined here because it is a hot point |
847 | + dk = kfmesh(ikf0+1) - kfmesh(ikf0) |
848 | + a = (kfmesh(ikf0+1) - kf0) / dk ! dadkf0 = -1/dk |
849 | + b = (kf0 - kfmesh(ikf0)) / dk ! dbdkf0 = +1/dk |
850 | + do ikf = 1,nkf |
851 | + pkf0(ikf) = a*pkf(ikf0,ikf) + b*pkf(ikf0+1,ikf) & |
852 | + + ((a**3-a)*d2pkfdkf2(ikf0,ikf) + & |
853 | + (b**3-b)*d2pkfdkf2(ikf0+1,ikf)) * dk**2/6 |
854 | + dpkfdkf0(ikf) = - (pkf(ikf0,ikf) - pkf(ikf0+1,ikf)) / dk & |
855 | + - ((3*a**2-1)*d2pkfdkf2(ikf0,ikf) - & |
856 | + (3*b**2-1)*d2pkfdkf2(ikf0+1,ikf)) * dk/6 |
857 | + end do |
858 | + |
859 | +! Evaluate pkg polynomials of spline basis at kg0 |
860 | + dk = kgmesh(ikg0+1) - kgmesh(ikg0) |
861 | + a = (kgmesh(ikg0+1) - kg0) / dk ! dadkg0 = -1/dk |
862 | + b = (kg0 - kgmesh(ikg0)) / dk ! dbdkg0 = +1/dk |
863 | + do ikg = 1,nkg |
864 | + pkg0(ikg) = a*pkg(ikg0,ikg) + b*pkg(ikg0+1,ikg) & |
865 | + + ((a**3-a)*d2pkgdkg2(ikg0,ikg) + & |
866 | + (b**3-b)*d2pkgdkg2(ikg0+1,ikg)) * dk**2/6 |
867 | + dpkgdkg0(ikg) = - (pkg(ikg0,ikg) - pkg(ikg0+1,ikg)) / dk & |
868 | + - ((3*a**2-1)*d2pkgdkg2(ikg0,ikg) - & |
869 | + (3*b**2-1)*d2pkgdkg2(ikg0+1,ikg)) * dk/6 |
870 | + end do |
871 | + |
872 | +! Evaluate pkf*pkg polynomials at (kf0,kg0) |
873 | + ikfg = 0 |
874 | + do ikg = 1,nkg |
875 | + do ikf = 1,nkf |
876 | + ikfg = ikfg+1 |
877 | + p(ikfg) = pkf0(ikf) * pkg0(ikg) |
878 | + dpdkf(ikfg) = dpkfdkf0(ikf)*dkf0dkf * pkg0(ikg) |
879 | + dpdkg(ikfg) = pkf0(ikf) * dpkgdkg0(ikg)*dkg0dkg |
880 | + end do |
881 | + end do |
882 | + |
883 | +end subroutine pofk |
884 | + |
885 | +!----------------------------------------------------------------------------- |
886 | + |
887 | +subroutine saturate( x, xc, y, dydx ) |
888 | + |
889 | + ! Defines a function y(x,xc) = 1/(1/x^nsat+1/xc^nsat)^(1/nsat), where nsat |
890 | + ! is an integer set in the module header. This function is approximately |
891 | + ! equal to x for x<xc and it saturates to xc when x->infinity |
892 | + |
893 | + implicit none |
894 | + real(dp),intent(in) :: x ! Independent variable |
895 | + real(dp),intent(in) :: xc ! Saturation value |
896 | + real(dp),intent(out):: y ! Function value |
897 | + real(dp),intent(out):: dydx ! Derivative dy/dx |
898 | + |
899 | + real(dp):: z |
900 | + |
901 | + if (xc<=0._dp) then |
902 | + call die('sg4vv_vdwxc_saturate ERROR: xc<=0') |
903 | + else if (x<0._dp) then |
904 | + call die('sg4vv_vdwxc_saturate ERROR: x<0') |
905 | + else if (x==0._dp) then |
906 | + y = 0 |
907 | + dydx = 1 |
908 | + else |
909 | + z = 1/x**nsat + 1/xc**nsat |
910 | + y = 1/z**(1._dp/nsat) |
911 | + dydx = y/z/x**(nsat+1) |
912 | + end if |
913 | + |
914 | +end subroutine saturate |
915 | + |
916 | +!----------------------------------------------------------------------------- |
917 | + |
918 | +subroutine saturate_inverse( y, xc, x, dxdy ) |
919 | + |
920 | +! Finds the inverse of the function defined in saturate subroutine: |
921 | +! y=1/(1/x^n+1/xc^n)^(1/n) => x=1/(1/y^n-1/xc^n)^(1/n) |
922 | + |
923 | + implicit none |
924 | + real(dp),intent(in) :: y ! Independent variable |
925 | + real(dp),intent(in) :: xc ! Saturation value |
926 | + real(dp),intent(out):: x ! Inverse function value |
927 | + real(dp),intent(out):: dxdy ! Derivative dx/dy |
928 | + |
929 | + real(dp):: z |
930 | + |
931 | + if (xc<=0._dp) then |
932 | + call die('sg4vv_vdwxc_saturate_inverse ERROR: xc<=0') |
933 | + else if (y<0._dp .or. y>=xc) then |
934 | + call die('sg4vv_vdwxc_saturate_inverse ERROR: y out of range') |
935 | + else if (y==0._dp) then |
936 | + x = 0 |
937 | + dxdy = 1 |
938 | + else |
939 | + z = 1/y**nsat - 1/xc**nsat |
940 | + x = 1/z**(1._dp/nsat) |
941 | + dxdy = x/z/y**(nsat+1) |
942 | + end if |
943 | + |
944 | +end subroutine saturate_inverse |
945 | + |
946 | +!----------------------------------------------------------------------------- |
947 | + |
948 | +subroutine set_kmesh() |
949 | + |
950 | +! Sets mesh of q values |
951 | + |
952 | + implicit none |
953 | + integer :: mkf, mkg |
954 | + |
955 | + if (.not.kmesh_set) then |
956 | + call set_mesh( nkf, xmax=kfcut, dxndx1=dkfmaxdkfmin ) |
957 | + call get_mesh( nkf, mkf, kfmesh ) |
958 | + call set_mesh( nkg, xmax=kgcut, dxndx1=dkgmaxdkgmin ) |
959 | + call get_mesh( nkg, mkg, kgmesh ) |
960 | + kmesh_set = .true. |
961 | +#ifdef DEBUG_XC |
962 | + write(udebug,'(/,a,/,(10f8.4))') 'sg4vv_vdw_set_kmesh: kfmesh =', kfmesh |
963 | + write(udebug,'(/,a,/,(10f8.4))') 'sg4vv_vdw_set_kmesh: kgmesh =', kgmesh |
964 | +#endif /* DEBUG_XC */ |
965 | + end if |
966 | + |
967 | +end subroutine set_kmesh |
968 | + |
969 | +! ----------------------------------------------------------------------------- |
970 | + |
971 | +subroutine set_phi_table() |
972 | + |
973 | +! Finds and stores in memory the interpolation table (mesh points and |
974 | +! function values) for the kernel phi(k1,k2,k). |
975 | + |
976 | + implicit none |
977 | + character(len=*),parameter:: myName = 'sg4vv_vdwxc/set_phi_table ' |
978 | + integer :: ik, ikf1, ikf2, ikg1, ikg2, ik1, ik2, ir |
979 | + real(dp):: dkdk0, dphidk0, dphidkmax, dphidr0, dphidrmax, & |
980 | + k, kf1, kf2, kg1, kg2, pi, r(0:nr) |
981 | + |
982 | +! Check that table was not set yet |
983 | + if (phi_table_set) return |
984 | + |
985 | +! Check that kf, kg, r, and k meshes have been set |
986 | + if (.not.kmesh_set) call set_kmesh() |
987 | + if (.not.kcut_set) call die('sg4vv_vdw_set_phi_table ERROR: kcut not set') |
988 | + forall(ir=0:nr) r(ir) = ir*dr |
989 | + pi = acos(-1.0_dp) |
990 | + |
991 | +! Allocate arrays |
992 | + call re_alloc( phir, 0,nr, 1,nkfg, 1,nkfg, myName//'phir' ) |
993 | + call re_alloc( phik, 0,nr, 1,nkfg, 1,nkfg, myName//'phik' ) |
994 | + call re_alloc( d2phidr2, 0,nr, 1,nkfg, 1,nkfg, myName//'d2phidr2' ) |
995 | + call re_alloc( d2phidk2, 0,nr, 1,nkfg, 1,nkfg, myName//'d2phidk2' ) |
996 | + |
997 | +! Loop on (k1,k2) mesh points |
998 | + do ikg2 = 1,nkg ! loop on kg2 |
999 | + do ikf2 = 1,nkf ! loop on kf2 |
1000 | + ik2 = ikf2 + nkf*(ikg2-1) ! combined (ikf2,ikg2) index |
1001 | + do ikg1 = 1,nkg ! loop on kg1 |
1002 | + do ikf1 = 1,nkf ! loop on kf1 |
1003 | + ik1 = ikf1 + nkf*(ikg1-1) ! combined (ikf1,ikg1) index |
1004 | + if (ik1>ik2) cycle ! since we will symmetrize at the end |
1005 | + |
1006 | + ! Saturated (kf,kg) values |
1007 | + kf1 = kfmesh(ikf1) |
1008 | + kf2 = kfmesh(ikf2) |
1009 | + kg1 = kgmesh(ikg1) |
1010 | + kg2 = kgmesh(ikg2) |
1011 | + |
1012 | + ! Find original (unsaturated) kf anf kg values |
1013 | + ! call saturate_inverse( kfmesh(ikf1), kfcut, kf1, dkdk0 ) |
1014 | + ! call saturate_inverse( kfmesh(ikf2), kfcut, kf2, dkdk0 ) |
1015 | + ! call saturate_inverse( kgmesh(ikg1), kgcut, kg1, dkdk0 ) |
1016 | + ! call saturate_inverse( kgmesh(ikg2), kgcut, kg2, dkdk0 ) |
1017 | + |
1018 | + ! Find kernel as a function of r12 |
1019 | + do ir = 0,nr |
1020 | + phir(ir,ik1,ik2) = sg4vv_vdw_phi_val( kf1, kf2, kg1, kg2, r(ir) ) |
1021 | + end do |
1022 | + |
1023 | + ! Kill kernel smoothly at r=rcut |
1024 | + do ir = 0,nr |
1025 | + phir(ir,ik1,ik2) = phir(ir,ik1,ik2) * cutoff( r(ir)/rcut ) |
1026 | + end do |
1027 | + |
1028 | + ! Find kernel in reciprocal space |
1029 | + call radfft( 0, nr, rcut, phir(:,ik1,ik2), phik(:,ik1,ik2) ) |
1030 | + phik(:,ik1,ik2) = phik(:,ik1,ik2) * (2*pi)**1.5_dp |
1031 | + |
1032 | + ! Filter out above kcut |
1033 | + phik(nk:nr,ik1,ik2) = 0 |
1034 | + |
1035 | + ! Soft filter below kcut |
1036 | + do ik = 1,nk |
1037 | + k = ik * dk |
1038 | + phik(ik,ik1,ik2) = phik(ik,ik1,ik2) * cutoff(k/kcut) |
1039 | + end do |
1040 | + |
1041 | + ! Find filtered kernel in real space |
1042 | + call radfft( 0, nr, kmax, phik(:,ik1,ik2), phir(:,ik1,ik2) ) |
1043 | + phir(:,ik1,ik2) = phir(:,ik1,ik2) / (2*pi)**1.5_dp |
1044 | + |
1045 | + ! Set up spline interpolation tables |
1046 | + dphidr0 = 0 ! since phi(k1,k2,r) is even in r |
1047 | + dphidk0 = 0 ! and therefore phi(k1,k2,k) is also even in k |
1048 | + dphidrmax = 0 ! since phi->0 for r->infty |
1049 | + dphidkmax = 0 ! and also when k->infty |
1050 | + call spline( dr, phir(:,ik1,ik2), nr+1, dphidr0, dphidrmax, & |
1051 | + d2phidr2(:,ik1,ik2) ) |
1052 | + call spline( dk, phik(:,ik1,ik2), nk+1, dphidk0, dphidkmax, & |
1053 | + d2phidk2(:,ik1,ik2) ) |
1054 | + |
1055 | + ! Fill symmetric elements |
1056 | + phir(:,ik2,ik1) = phir(:,ik1,ik2) |
1057 | + phik(:,ik2,ik1) = phik(:,ik1,ik2) |
1058 | + d2phidr2(:,ik2,ik1) = d2phidr2(:,ik1,ik2) |
1059 | + d2phidk2(:,ik2,ik1) = d2phidk2(:,ik1,ik2) |
1060 | + |
1061 | +!#ifdef DEBUG_XC |
1062 | +! if (.false. .and. ik1==ik2) then |
1063 | +! print*, 'sg4vv_vdw_set_kcut: ik1,ik2=', ik1, ik2 |
1064 | +! call window( 0._dp, 5._dp, -1._dp, 4._dp, 0 ) |
1065 | +! call axes( 0._dp, 1._dp, 0._dp, 1._dp ) |
1066 | +! call plot( nr+1, r, phi, phir(:,ik1,ik2) ) |
1067 | +! call window( 0._dp, 10._dp, -0.05_dp, 0.15_dp, 0 ) |
1068 | +! call axes( 0._dp, 1._dp, 0._dp, 0.05_dp ) |
1069 | +! call plot( nr+1, r, r**2*phi, r**2*phir(:,ik1,ik2)) |
1070 | +! call show() |
1071 | +! end if |
1072 | +!#endif /* DEBUG_XC */ |
1073 | + |
1074 | + end do ! ikf1 |
1075 | + end do ! ikg1 |
1076 | + end do ! ikf2 |
1077 | + end do ! ikg2 |
1078 | + |
1079 | +!#ifdef DEBUG_XC |
1080 | +! open(17,file='vv_phi.table') |
1081 | +! write(17,'(3a6,2a12,/,(3i6,2f15.9))') & |
1082 | +! 'ik1', 'ik2', 'ir', 'phi', 'd2phi/dk2', & |
1083 | +!! (((ik1,ik2,ir,phir(ir,ik1,ik2),d2phidr2(ir,ik1,ik2), & |
1084 | +! (((ik1,ik2,ir,phik(ir,ik1,ik2),d2phidk2(ir,ik1,ik2), & |
1085 | +! ir=0,100),ik2=1,nkfg),ik1=1,nkfg) |
1086 | +! close(17) |
1087 | +!#endif /* DEBUG_XC */ |
1088 | + |
1089 | +! Mark table as set |
1090 | + phi_table_set = .true. |
1091 | + |
1092 | +end subroutine set_phi_table |
1093 | + |
1094 | +! ----------------------------------------------------------------------------- |
1095 | + |
1096 | +real(dp) function sg4vv_vdw_phi_val( kf1, kf2, kg1, kg2, r12 ) |
1097 | + |
1098 | +! vdW energy kernel of Vydrov-vanVoorhis, eq.(2) of JCP 133, 244103 (2010) |
1099 | +! This subroutine calculates the 'raw' kernel directly, without interpolarions |
1100 | +! In practice, it returns n1*n2*phi(k1,k2,r12), which is smooth for kf->0 |
1101 | +! Input: |
1102 | +! real(dp):: kf1, kf2 ! Fermi wavevectors at points 1 and 2 |
1103 | +! real(dp):: kg1, kg2 ! |grad(n)|/n at points 1 and 2 |
1104 | +! real(dp):: r12 ! distance between points 1 and 2 |
1105 | + |
1106 | +! Arguments |
1107 | + implicit none |
1108 | + real(dp),intent(in) :: kf1, kf2, kg1, kg2, r12 |
1109 | + |
1110 | +! Internal variables |
1111 | + real(dp):: g1, g2, kappa1, kappa2, kf1m, kf2m, n1, n2, & |
1112 | + phi, pi, w01, w02, wg1, wg2, wp1, wp2 |
1113 | + |
1114 | +! Avoid dividing by zero when kf=0 |
1115 | + kf1m = max(kf1,ktol) |
1116 | + kf2m = max(kf2,ktol) |
1117 | + |
1118 | +! Find kernel |
1119 | + pi = acos(-1.0_dp) |
1120 | + n1 = kf1m**3/(3*pi**2) ! electron density at point 1 |
1121 | + n2 = kf2m**3/(3*pi**2) ! electron density at point 2 |
1122 | + wp1 = sqrt(4*pi*n1) ! local plasma frequency at point 1 |
1123 | + wp2 = sqrt(4*pi*n2) ! local plasma frequency at point 2 |
1124 | + wg1 = sqrt(vv_C*kg1**4) ! local band gap at point 1 |
1125 | + wg2 = sqrt(vv_C*kg2**4) ! local band gap at point 2 |
1126 | + kappa1 = vv_b*kf1m**2/wp1 ! local VV kappa variable (eq.(9)) at point 1 |
1127 | + kappa2 = vv_b*kf2m**2/wp2 ! kappa variable at point 2 |
1128 | + w01 = sqrt(wg1**2+wp1**2/3) ! local w0 frequency (eq.(5)) at point 1 |
1129 | + w02 = sqrt(wg2**2+wp2**2/3) ! local w0 frequency at point 2 |
1130 | + g1 = w01*r12**2 + kappa1 ! local g variable (eq.(3)) at point 1 |
1131 | + g2 = w02*r12**2 + kappa2 ! local g variable at point 2 |
1132 | + phi = -1.5_dp/g1/g2/(g1+g2) ! VV kernel phi (eq.(2)) |
1133 | + |
1134 | + if (kernelPrefactor=='rho') then |
1135 | + ! Return whole integrand of eq.(1) |
1136 | + sg4vv_vdw_phi_val = n1*n2*phi |
1137 | + else if (kernelPrefactor=='kf') then |
1138 | + ! Return kf1*kf2*phi |
1139 | + sg4vv_vdw_phi_val = kf1*kf2*phi |
1140 | + else if (kernelPrefactor=='kf2') then |
1141 | + ! Return (kf1*kf2)**2*phi |
1142 | + sg4vv_vdw_phi_val = (kf1*kf2)**2*phi |
1143 | + else if (kernelPrefactor=='sqr_rho') then |
1144 | + ! Find and return sqrt(n1*n2)*phi |
1145 | + sg4vv_vdw_phi_val = sqrt(n1*n2)*phi |
1146 | + else |
1147 | + call die('sg4vv_vdw_phi_val ERROR: unknown kernelPrefactor') |
1148 | + end if |
1149 | + |
1150 | +end function sg4vv_vdw_phi_val |
1151 | + |
1152 | +! ----------------------------------------------------------------------------- |
1153 | + |
1154 | +real(dp) function sg4vv_vdw_beta() |
1155 | + |
1156 | +! Returns parameter beta of VV functional |
1157 | + |
1158 | + implicit none |
1159 | + sg4vv_vdw_beta = vv_beta |
1160 | + |
1161 | +end function sg4vv_vdw_beta |
1162 | + |
1163 | +!----------------------------------------------------------------------------- |
1164 | + |
1165 | +subroutine sg4vv_vdw_get_kmesh( mkf, mkg, kf, kg ) |
1166 | + |
1167 | +! Returns size and values of (kf,kg) mesh |
1168 | + |
1169 | + implicit none |
1170 | + integer, intent(out) :: mkf ! Number of kf mesh points |
1171 | + integer, intent(out) :: mkg ! Number of kg mesh points |
1172 | + real(dp),optional,intent(out) :: kf(:) ! Values of kf mesh points |
1173 | + real(dp),optional,intent(out) :: kg(:) ! Values of kg mesh points |
1174 | + integer:: nmax |
1175 | + if (.not.kmesh_set) call set_kmesh() |
1176 | + mkf = nkf |
1177 | + mkg = nkg |
1178 | + if (present(kf)) then |
1179 | + nmax = max( nkf, size(kf) ) |
1180 | + kf(1:nmax) = kfmesh(1:nmax) |
1181 | + end if |
1182 | + if (present(kg)) then |
1183 | + nmax = max( nkg, size(kg) ) |
1184 | + kg(1:nmax) = kgmesh(1:nmax) |
1185 | + end if |
1186 | +end subroutine sg4vv_vdw_get_kmesh |
1187 | + |
1188 | +! ----------------------------------------------------------------------------- |
1189 | + |
1190 | +subroutine sg4vv_vdw_phi( k, phi, dphidk ) |
1191 | + |
1192 | +! Finds by interpolation phi(k1,k2,k) (Fourier transform of phi(k1,k2,r)), |
1193 | +! with k1=(kf1,kg1), k2=(kf2,kg2) for all mesh values of kf (Fermi |
1194 | +! wavevector) and kg (grad(n)/n). If the interpolation table does not exist, |
1195 | +! it is calculated in the first call to sg4vv_vdw_phi. It requires a previous |
1196 | +! call to sg4vv_vdw_set_kc to set k mesh. |
1197 | + |
1198 | + implicit none |
1199 | + real(dp),intent(in) :: k ! Modulus of actual k vector |
1200 | + real(dp),intent(out):: phi(:,:) ! phi(k1,k2,k) at given k |
1201 | + ! for all k1,k2 in (kf,kg) mesh |
1202 | + real(dp),intent(out):: dphidk(:,:) ! dphi(k1,k2,k)/dk at given k |
1203 | + |
1204 | + integer :: ik, ik1, ik2 |
1205 | + real(dp):: a, a2, a3, b, b2, b3 |
1206 | + |
1207 | +! Set interpolation table |
1208 | + if (.not.phi_table_set) call set_phi_table() |
1209 | + |
1210 | +! Check argument sizes |
1211 | + if (size(phi,1)<nkfg .or. size(phi,2)<nkfg) & |
1212 | + call die('sg4vv_vdw_phi: ERROR: size(phi) too small') |
1213 | + |
1214 | +! Find phi values at point k |
1215 | + if (k >= kcut) then |
1216 | + phi(:,:) = 0 |
1217 | + dphidk(:,:) = 0 |
1218 | + else |
1219 | + ! Expand interpolation inline since this is the hottest point in VdW |
1220 | + ik = int(k/dk) |
1221 | + a = ((ik+1)*dk-k)/dk |
1222 | + b = 1 - a |
1223 | + a2 = (3*a**2 -1) * dk / 6 |
1224 | + b2 = (3*b**2 -1) * dk / 6 |
1225 | + a3 = (a**3 - a) * dk**2 / 6 |
1226 | + b3 = (b**3 - b) * dk**2 / 6 |
1227 | + do ik2 = 1,nkfg |
1228 | + do ik1 = 1,ik2 |
1229 | +! call splint( dk, phik(:,ik1,ik2), d2phidk2(:,ik1,ik2), & |
1230 | +! nk+1, k, phi(ik1,ik2), dphidk(ik1,ik2), pr ) |
1231 | + phi(ik1,ik2) = a*phik(ik,ik1,ik2) + b*phik(ik+1,ik1,ik2) & |
1232 | + + a3*d2phidk2(ik,ik1,ik2) + b3*d2phidk2(ik+1,ik1,ik2) |
1233 | + dphidk(ik1,ik2) = (-phik(ik,ik1,ik2) & |
1234 | + +phik(ik+1,ik1,ik2) )/dk & |
1235 | + - a2*d2phidk2(ik,ik1,ik2) + b2*d2phidk2(ik+1,ik1,ik2) |
1236 | + phi(ik2,ik1) = phi(ik1,ik2) |
1237 | + dphidk(ik2,ik1) = dphidk(ik1,ik2) |
1238 | + end do |
1239 | + end do |
1240 | + end if |
1241 | + |
1242 | +end subroutine sg4vv_vdw_phi |
1243 | + |
1244 | +!----------------------------------------------------------------------------- |
1245 | + |
1246 | +subroutine sg4vv_vdw_phiofr( r, phi ) |
1247 | + |
1248 | +! Finds phi(k1,k2,r) with k1=(kf1,kg1), k2=(kf2,kg2) for mesh values of |
1249 | +! kf's (Fermi wavevectors) and kg's (grad(n)/n) |
1250 | + |
1251 | + implicit none |
1252 | + real(dp),intent(in) :: r |
1253 | + real(dp),intent(out):: phi(:,:) |
1254 | + |
1255 | + integer :: ikf1, ikf2, ikg1, ikg2, ik1, ik2 |
1256 | + real(dp):: dphidr |
1257 | + |
1258 | + if (size(phi,1)<nkfg .or. size(phi,2)<nkfg) & |
1259 | + stop 'vv_phiofr: ERROR: size(phi) too small' |
1260 | + if (.not.phi_table_set) call set_phi_table() |
1261 | + |
1262 | + if (r >= rcut) then |
1263 | + phi(:,:) = 0 |
1264 | + else |
1265 | + do ik2 = 1,nkfg |
1266 | + do ik1 = 1,ik2 |
1267 | + call splint( dr, phir(:,ik1,ik2), d2phidr2(:,ik1,ik2), & |
1268 | + nr+1, r, phi(ik1,ik2), dphidr ) |
1269 | + phi(ik2,ik1) = phi(ik1,ik2) |
1270 | + end do ! ik1 |
1271 | + end do ! ik2 |
1272 | + end if ! (r>=rcut) |
1273 | + |
1274 | +end subroutine sg4vv_vdw_phiofr |
1275 | + |
1276 | +!----------------------------------------------------------------------------- |
1277 | + |
1278 | +subroutine sg4vv_vdw_set_kcut( kc ) |
1279 | + |
1280 | +! Sets the reciprocal planewave cutoff kc of the integration grid, and finds |
1281 | +! the interpolation table to be used by vdw_phi to obtain the vdW kernel phi |
1282 | +! at the reciprocal mesh wavevectors. |
1283 | + |
1284 | + implicit none |
1285 | + real(dp),intent(in):: kc ! Planewave cutoff: k>kcut => phi=0 |
1286 | + |
1287 | + real(dp):: pi |
1288 | + |
1289 | + ! Set kcut and radial mesh parameters, if not already set |
1290 | + if (.not. kc==kcut) then |
1291 | + kcut = kc |
1292 | + pi = acos(-1._dp) |
1293 | + dr = rcut / nr |
1294 | + dk = pi / rcut |
1295 | + kmax = pi / dr |
1296 | + nk = int(kcut/dk) + 1 |
1297 | + if (nk>nr) stop 'sg4vv_vdw_set_kcut: ERROR: nk>nr' |
1298 | + kcut_set = .true. |
1299 | +#ifdef DEBUG_XC |
1300 | + write(udebug,'(a,5f8.3)') 'sg4vv_vdw_set_kcut: kfcut,kgcut,rcut,kcut,kmax=', & |
1301 | + kfcut, kgcut, rcut, kc, kmax |
1302 | +#endif /* DEBUG_XC */ |
1303 | + end if |
1304 | + |
1305 | + ! Set (kf,kg) mesh and phi table |
1306 | + call set_kmesh() |
1307 | + call set_phi_table() |
1308 | + |
1309 | +end subroutine sg4vv_vdw_set_kcut |
1310 | + |
1311 | +!----------------------------------------------------------------------------- |
1312 | + |
1313 | +subroutine sg4vv_vdw_theta( nspin, rhos, grhos, theta, dtdrho, dtdgrho ) |
1314 | + |
1315 | +! Finds the value and derivatives of theta_i(rho,grad_rho) of eq.(8) |
1316 | +! of Roman-Soler PRL 2009. In practice, theta_i=p_i rather than rho*p_i, |
1317 | +! beacuse p_i is used here to expand rho1*rho2*phi rather than only phi. |
1318 | + |
1319 | + implicit none |
1320 | + integer, intent(in) :: nspin ! Number of spin components |
1321 | + real(dp),intent(in) :: rhos(nspin) ! Electron spin density |
1322 | + real(dp),intent(in) :: grhos(3,nspin) ! Spin density gradient |
1323 | + real(dp),intent(out):: theta(nkfg) ! Exp. polynomials at (kf,kg) |
1324 | + real(dp),intent(out):: dtdrho(nkfg,nspin) ! dtheta(ik)/drhos |
1325 | + real(dp),intent(out):: dtdgrho(3,nkfg,nspin) ! dtheta(ik)/dgrhos(ix) |
1326 | + |
1327 | + integer :: is, ix, ns |
1328 | + real(dp):: rho, grho(3), dpdkf(nkfg), dpdkg(nkfg), dkfdrho, dkfdgrho(3), & |
1329 | + dkgdrho, dkgdgrho(3), kf, kg, p(nkfg) |
1330 | + |
1331 | + ! Sum spin components of electron density |
1332 | + ns = min(nspin,2) ! num. of diagonal spin components (if noncollinear) |
1333 | + rho = sum(rhos(1:ns)) ! local electron density |
1334 | + grho = sum(grhos(:,1:ns),dim=2) ! local density gradient |
1335 | + |
1336 | + ! If density is between threshold, return zero |
1337 | + if (rho<rhoMin) then |
1338 | + theta = 0 |
1339 | + dtdrho = 0 |
1340 | + dtdgrho = 0 |
1341 | + return |
1342 | + end if |
1343 | + |
1344 | + ! Find local Fermi and gradient wavevectors, and their derivatives |
1345 | + call kofn( rho, grho, kf, kg, dkfdrho, dkgdrho, dkfdgrho, dkgdgrho ) |
1346 | + |
1347 | + ! Find expansion polynomials of integrand kernel of nonlocal vdW energy |
1348 | + call pofk( kf, kg, p, dpdkf, dpdkg ) |
1349 | + |
1350 | + ! Find theta functions and their derivatives with respect to rho and grho |
1351 | + if (kernelPrefactor=='rho') then |
1352 | + ! This is the right code if sg4vv_vdw_phi_val returns rho1*rho2*phi |
1353 | + theta(1:nkfg) = p(1:nkfg) |
1354 | + do is = 1,ns |
1355 | + dtdrho(1:nkfg,is) = dpdkf(1:nkfg)*dkfdrho + dpdkg(1:nkfg)*dkgdrho |
1356 | + do ix = 1,3 |
1357 | + dtdgrho(ix,1:nkfg,is) = dpdkf(1:nkfg)*dkfdgrho(ix) & |
1358 | + + dpdkg(1:nkfg)*dkgdgrho(ix) |
1359 | + end do |
1360 | + end do |
1361 | + else if (kernelPrefactor=='kf') then |
1362 | + ! This is the right code if sg4vv_vdw_phi_val returns kf1*kf2*phi |
1363 | + kf = max(kf,ktol) |
1364 | + theta(1:nkfg) = p(1:nkfg)*rho/kf |
1365 | + do is = 1,ns |
1366 | + dtdrho(1:nkfg,is) = (dpdkf(1:nkfg)*dkfdrho & |
1367 | + +dpdkg(1:nkfg)*dkgdrho)*rho/kf & |
1368 | + + p(1:nkfg)*(1/kf-rho/kf**2*dkfdrho) |
1369 | + do ix = 1,3 |
1370 | + dtdgrho(ix,1:nkfg,is) = (dpdkf(1:nkfg)*dkfdgrho(ix) & |
1371 | + +dpdkg(1:nkfg)*dkgdgrho(ix))*rho/kf |
1372 | + end do |
1373 | + end do |
1374 | + else if (kernelPrefactor=='kf2') then |
1375 | + ! This is the right code if sg4vv_vdw_phi_val returns (kf1*kf2)**2*phi |
1376 | + kf = max(kf,ktol) |
1377 | + theta(1:nkfg) = p(1:nkfg)*rho/kf**2 |
1378 | + do is = 1,ns |
1379 | + dtdrho(1:nkfg,is) = (dpdkf(1:nkfg)*dkfdrho & |
1380 | + +dpdkg(1:nkfg)*dkgdrho)*rho/kf**2 & |
1381 | + + p(1:nkfg)*(1/kf**2-2*rho/kf**3*dkfdrho) |
1382 | + do ix = 1,3 |
1383 | + dtdgrho(ix,1:nkfg,is) = (dpdkf(1:nkfg)*dkfdgrho(ix) & |
1384 | + +dpdkg(1:nkfg)*dkgdgrho(ix))*rho/kf**2 |
1385 | + end do |
1386 | + end do |
1387 | + else if (kernelPrefactor=='sqr_rho') then |
1388 | + ! This is the right code if sg4vv_vdw_phi_val returns sqrt(rho1*rho2)*phi |
1389 | + rho = max(rho,1.e-12_dp) ! to avoid division by zero |
1390 | + theta(1:nkfg) = p(1:nkfg) * sqrt(rho) |
1391 | + do is = 1,ns |
1392 | + dtdrho(1:nkfg,is) = ( dpdkf(1:nkfg)*dkfdrho & |
1393 | + + dpdkg(1:nkfg)*dkgdrho ) * sqrt(rho) & |
1394 | + + p(1:nkfg) * 0.5/sqrt(rho) |
1395 | + do ix = 1,3 |
1396 | + dtdgrho(ix,1:nkfg,is) = dpdkf(1:nkfg)*dkfdgrho(ix) * sqrt(rho) & |
1397 | + + dpdkg(1:nkfg)*dkgdgrho(ix) * sqrt(rho) |
1398 | + end do |
1399 | + end do |
1400 | + else |
1401 | + call die('sg4vv_vdw_theta ERROR: unknown kernelPrefactor') |
1402 | + end if ! (kernelPrefactor=='rho') |
1403 | + |
1404 | +end subroutine sg4vv_vdw_theta |
1405 | + |
1406 | +END MODULE m_sg4vv_vdwxc |
1407 | + |
1408 | +!!!=============== PBE+VV10 ======================== |
1409 | + |
1410 | +MODULE m_pbevv_vdwxc |
1411 | + |
1412 | +! Used module procedures |
1413 | + use sys, only: die ! Termination routine |
1414 | + use mesh1D, only: get_mesh ! Returns the mesh points |
1415 | + use m_radfft, only: radfft ! Radial fast Fourier transform |
1416 | + use alloc, only: re_alloc ! Re-allocation routine |
1417 | + use mesh1D, only: set_mesh ! Sets a 1D mesh |
1418 | + use interpolation,only: spline ! Sets spline interpolation |
1419 | + use interpolation,only: splint ! Calculates spline interpolation |
1420 | + |
1421 | +! Used module parameters |
1422 | + use precision, only: dp ! Real double precision type |
1423 | + |
1424 | +#ifdef DEBUG_XC |
1425 | + use debugXC, only: udebug ! File unit for debug output |
1426 | +! use plot_module, only: plot |
1427 | +#endif /* DEBUG_XC */ |
1428 | + |
1429 | + implicit none |
1430 | + |
1431 | +! Called by m_vdwxc |
1432 | +PUBLIC :: & |
1433 | + pbevv_vdw_beta, &! Returns parameter beta of the VV2010 functional |
1434 | + pbevv_vdw_theta, &! Finds function theta_ik(rho,grad_rho) |
1435 | + pbevv_vdw_get_kmesh, &! Returns size and values of (kf,kg) mesh |
1436 | + pbevv_vdw_phi, &! Finds and interpolates rho1*rho2*phi(k1,k2,k) |
1437 | + pbevv_vdw_set_kcut ! Sets the planewave cutoff kc of the integration grid |
1438 | + |
1439 | +#ifdef DEBUG_XC |
1440 | +! Called by debugging test programs |
1441 | +PUBLIC :: & |
1442 | + pbevv_vdw_phi_val, &! Kernel phi(kf1,kf2,kg1,kg2,r12) with no interpolation |
1443 | + pbevv_vdw_phiofr ! Kernel phi(k1,k2,r) at tabulated k1,k2-mesh values |
1444 | +#endif /* DEBUG_XC */ |
1445 | + |
1446 | +PRIVATE ! Nothing is declared public beyond this point |
1447 | + |
1448 | + ! Set parameters of the PBE+rVV10, |
1449 | + ! Ref. H. Peng and J. P. Perdew, Phys. Rev. B 95, 0811105 (2017) |
1450 | + real(dp),parameter:: vv_C = 0.0093 |
1451 | + real(dp),parameter:: vv_b = 10.0 |
1452 | + real(dp),parameter:: vv_beta = 0.00497 |
1453 | + |
1454 | + ! Mesh parameters for table of phi(k1,k2,r) and its Fourier transform |
1455 | + character(len=*),parameter:: kernelPrefactor='rho' ! Prefactor of the |
1456 | + ! nonlocal kernel for interpolation |
1457 | + ! ('kf'|'kf2'|'sqr_rho'|'rho') |
1458 | + integer, parameter:: nr = 2048 ! Radial mesh points (power of 2) |
1459 | + real(dp),parameter:: rcut = 100._dp ! Radial cutoff: r>rcut => phi=0 |
1460 | + real(dp),parameter:: rmin = 1.e-6_dp ! Min. radius as denominator |
1461 | + integer, parameter:: nkf = 7 ! Number of Fermi wavevectors |
1462 | + integer, parameter:: nkg = 5 ! Num. of grad(n)/n wavevectors |
1463 | + integer, parameter:: nkfg = nkf*nkg ! Num. of (kf,kg) mesh points |
1464 | + real(dp),parameter:: kfcut = 5.0_dp ! Max. Fermi wavevec. |
1465 | + real(dp),parameter:: kgcut = 5.0_dp ! Max. grad(n)/n |
1466 | + real(dp),parameter:: dkfmaxdkfmin = 20.0_dp ! Last/first kf mesh interval |
1467 | + real(dp),parameter:: dkgmaxdkgmin = 2.0_dp ! Last/first kg mesh interval |
1468 | + real(dp),parameter:: ktol = 1.e-12_dp ! 'out of range' tolerance |
1469 | + real(dp),parameter:: amin = 1.e-12_dp ! tiny denominator to avoid /0 |
1470 | + real(dp),parameter:: rhoMin = 1.e-10_dp ! Min. density for nonzero Vxc |
1471 | + |
1472 | + ! Parameters for cutoff function, used in radial Fourier transforms of phi |
1473 | + integer, parameter:: ncut1 = 8 ! cutoff(x)=(1-x**ncut1)**ncut2 |
1474 | + integer, parameter:: ncut2 = 4 |
1475 | + |
1476 | + ! Parameters for saturate function, used to enforce that q<qcut |
1477 | + integer, parameter:: nsat = 15 ! h(x,xc)=1/(1/x**nsat+1/xc**nsat)**(1/nsat) |
1478 | + ! nsat=15 approximately corresponds to |
1479 | + ! nsat=12 for eq.(5) of Roman-Soler PRL |
1480 | + |
1481 | + ! Private module variables and arrays |
1482 | + logical, save:: kcut_set=.false. ! Has kcut been set? |
1483 | + logical, save:: kmesh_set=.false. ! Has (kf,kg) mesh been set? |
1484 | + logical, save:: phi_table_set=.false. ! Has phi_table been set? |
1485 | + integer, save:: nk ! Num. of radial mesh k-points |
1486 | + real(dp),save:: dr ! r-mesh interval |
1487 | + real(dp),save:: dk ! k-mesh interval |
1488 | + real(dp),save:: kcut ! Planewave cutoff: k>kcut => phi=0 |
1489 | + real(dp),save:: kmax ! Max. k vector in Fourier transforms |
1490 | + real(dp),save:: kfmesh(nkf) ! Mesh points for Fermi wavevector |
1491 | + real(dp),save:: kgmesh(nkg) ! Mesh points for grad(n)/n |
1492 | + real(dp),pointer,save:: & |
1493 | + phir(:,:,:)=>null(), &! Table of phi(r) |
1494 | + phik(:,:,:)=>null(), &! Table of phi(k) |
1495 | + d2phidr2(:,:,:)=>null(),&! Table of d^2(phi)/dr^2 |
1496 | + d2phidk2(:,:,:)=>null() ! Table of d^2(phi)/dk^2 |
1497 | + |
1498 | +CONTAINS |
1499 | + |
1500 | +! ----------------------------------------------------------------------------- |
1501 | + |
1502 | +real(dp) function cutoff( x ) |
1503 | + |
1504 | +! Defines a smooth cutoff function that falls from y(0)=1 to y(1)=0 |
1505 | + |
1506 | + implicit none |
1507 | + real(dp),intent(in):: x |
1508 | + |
1509 | + if (x<=0._dp) then |
1510 | + cutoff = 1 |
1511 | + else if (x>=1._dp) then |
1512 | + cutoff = 0 |
1513 | + else |
1514 | + cutoff = (1-x**ncut1)**ncut2 |
1515 | + end if |
1516 | + |
1517 | +end function cutoff |
1518 | + |
1519 | +!----------------------------------------------------------------------------- |
1520 | + |
1521 | +subroutine iofk( kf, kg, ikf, ikg ) |
1522 | + |
1523 | +! Finds indexes ikf and ikg such that kfmesh(ikf) <= kf < kfmesh(ikf+1) |
1524 | +! and kgmesh(ikg) <= kg < kgmesh(ikg+1) in logarithmic meshes of the form |
1525 | +! k(ik) = b*(exp((ik-1)*a)-1) |
1526 | + |
1527 | + implicit none |
1528 | + real(dp), intent(in) :: kf, kg |
1529 | + integer, intent(out):: ikf, ikg |
1530 | + |
1531 | + real(dp),save:: akf, akg, bkf, bkg |
1532 | + logical, save:: first_call = .true. |
1533 | + integer:: ik |
1534 | + |
1535 | + ! Mesh data initializations |
1536 | + if (first_call) then |
1537 | + ! Find logarithmic-mesh a & b parameters: x(j)=x(1)+b*(exp(a*(j-1))-1) |
1538 | + akf = log( (kfmesh(nkf)-kfmesh(nkf-1)) / (kfmesh(2)-kfmesh(1)) ) / (nkf-2) |
1539 | + akg = log( (kgmesh(nkg)-kgmesh(nkg-1)) / (kgmesh(2)-kgmesh(1)) ) / (nkg-2) |
1540 | + akf = max( akf, amin ) |
1541 | + akg = max( akg, amin ) |
1542 | + bkf = (kfmesh(nkf) - kfmesh(1)) / (exp(akf*(nkf-1)) - 1) |
1543 | + bkg = (kgmesh(nkg) - kgmesh(1)) / (exp(akg*(nkg-1)) - 1) |
1544 | + ! Check that meshes are indeed logarithmic |
1545 | + do ik = 1,nkf |
1546 | + if (abs(kfmesh(ik)-kfmesh(1)-bkf*(exp(akf*(ik-1))-1))>ktol) & |
1547 | + call die('pbevv_vdw_iofk ERROR: kfmesh not logarithmic') |
1548 | + end do |
1549 | + do ik = 1,nkg |
1550 | + if (abs(kgmesh(ik)-kgmesh(1)-bkg*(exp(akg*(ik-1))-1))>ktol) & |
1551 | + call die('pbevv_vdw_iofk ERROR: kgmesh not logarithmic') |
1552 | + end do |
1553 | + first_call = .false. |
1554 | + end if |
1555 | + |
1556 | + ! Check that kf and kg are within interpolation range |
1557 | + if (kf<kfmesh(1)-ktol .or. kf>kfmesh(nkf)+ktol .or. & |
1558 | + kg<kgmesh(1)-ktol .or. kg>kgmesh(nkg)+ktol) then |
1559 | + call die('pbevv_vdw_iofk ERROR: (kf,kg) out of range') |
1560 | + endif |
1561 | + |
1562 | + ! Find interpolation mesh intervals |
1563 | + ikf = 1 + int( log( 1 + (kf-kfmesh(1))/bkf ) / akf ) |
1564 | + ikg = 1 + int( log( 1 + (kg-kgmesh(1))/bkg ) / akg ) |
1565 | + ikf = max( 1, ikf ) |
1566 | + ikg = max( 1, ikg ) |
1567 | + ikf = min( nkf-1, ikf ) |
1568 | + ikg = min( nkg-1, ikg ) |
1569 | + |
1570 | +end subroutine iofk |
1571 | + |
1572 | +! ----------------------------------------------------------------------------- |
1573 | + |
1574 | +subroutine kofn( n, gn, kf, kg, dkfdn, dkgdn, dkfdgn, dkgdgn ) |
1575 | + |
1576 | +! Finds Fermi and gradient wavevectors from density and gradient |
1577 | + |
1578 | + implicit none |
1579 | + real(dp), intent(in) :: n ! Electron density |
1580 | + real(dp), intent(in) :: gn(3) ! Density gradient |
1581 | + real(dp), intent(out):: kf ! Local Fermi wavevector |
1582 | + real(dp), intent(out):: kg ! |grad(n)|/n |
1583 | + real(dp), intent(out):: dkfdn ! dkf/dn |
1584 | + real(dp), intent(out):: dkgdn ! dkg/dn |
1585 | + real(dp), intent(out):: dkfdgn(3) ! dkf/dgn |
1586 | + real(dp), intent(out):: dkgdgn(3) ! dkg/dgn |
1587 | + |
1588 | + real(dp):: gn2, pi |
1589 | + |
1590 | +! Trap exception for zero density |
1591 | + if (n <= 1.e-30_dp) then |
1592 | + kf = 0 |
1593 | + kg = 0 |
1594 | + dkfdn = 0 |
1595 | + dkfdgn = 0 |
1596 | + dkgdn = 0 |
1597 | + dkgdgn = 0 |
1598 | + return |
1599 | + end if |
1600 | + |
1601 | +! Find kf and kg |
1602 | + pi = acos(-1._dp) |
1603 | + kf = (3*pi**2*n)**(1._dp/3) |
1604 | + gn2 = sum(gn**2) |
1605 | + kg = sqrt(gn2)/n |
1606 | + |
1607 | +! Find derivatives |
1608 | + dkfdn = kf/n/3 |
1609 | + dkfdgn = 0 |
1610 | + dkgdn = -kg/n |
1611 | + dkgdgn = kg*gn/gn2 |
1612 | + |
1613 | +end subroutine kofn |
1614 | + |
1615 | +!----------------------------------------------------------------------------- |
1616 | + |
1617 | +subroutine pofk( kf, kg, p, dpdkf, dpdkg ) |
1618 | + |
1619 | +! Finds the values and derivatives, at (kf,kg), of the bicubic polynomials |
1620 | +! p_i(kf,kg) such that |
1621 | +! y(kf,kg) = Sum_i p_i(kf,kg) * y_i |
1622 | +! is the bicubic spline interpolation at (kf,kg) of (any) function y with |
1623 | +! values y_i at mesh points (kfmesh,kgmesh)_i |
1624 | + |
1625 | + implicit none |
1626 | + real(dp),intent(in) :: kf, kg ! point at which the polynomials are required |
1627 | + real(dp),intent(out):: p(nkfg) ! polynomial values at (kf,kg) |
1628 | + real(dp),intent(out):: dpdkf(nkfg) ! dp/dkf at (kf,kg) |
1629 | + real(dp),intent(out):: dpdkg(nkfg) ! dp/dkg at (kf,kg) |
1630 | + |
1631 | + integer :: ikf, ikg, ikfg, ikf0, ikg0 |
1632 | + real(dp):: a, b, dk, dkf0dkf, dkg0dkg, kf0, kg0 |
1633 | + real(dp):: pkf0(nkf), dpkfdkf0(nkf), pkg0(nkg), dpkgdkg0(nkg) |
1634 | + logical, save :: first_call=.true. |
1635 | + real(dp),save :: pkf(nkf,nkf), d2pkfdkf2(nkf,nkf) |
1636 | + real(dp),save :: pkg(nkg,nkg), d2pkgdkg2(nkg,nkg) |
1637 | + |
1638 | +! Set up spline polynomial basis |
1639 | + if (first_call) then |
1640 | + do ikf = 1,nkf |
1641 | + pkf(:,ikf) = 0 ! ikf'th polynomial pkf(:,ikf) is one at kfmesh(ikf) |
1642 | + pkf(ikf,ikf) = 1 ! and zero at all other points |
1643 | + call spline( kfmesh, pkf(:,ikf), nkf, 1.e30_dp, 1.e30_dp, & |
1644 | + d2pkfdkf2(:,ikf) ) |
1645 | +! call spline( kfmesh, pkf(:,ikf), nkf, 0._dp, 0._dp, d2pkfdkf2(:,ikf) ) |
1646 | + end do |
1647 | + do ikg = 1,nkg |
1648 | + pkg(:,ikg) = 0 |
1649 | + pkg(ikg,ikg) = 1 |
1650 | + call spline( kgmesh, pkg(:,ikg), nkg, 1.e30_dp, 1.e30_dp, & |
1651 | + d2pkgdkg2(:,ikg) ) |
1652 | +! call spline( kgmesh, pkg(:,ikg), nkg, 0._dp, 0._dp, d2pkgdkg2(:,ikg) ) |
1653 | + end do |
1654 | + |
1655 | +! DEBUG |
1656 | + open(22,file='pkf.dat') |
1657 | + do ikf = 1,nkf |
1658 | + write(22,'(20e15.6)') kfmesh(ikf), pkf(:,ikf), d2pkfdkf2(:,ikf) |
1659 | + end do |
1660 | + close(22) |
1661 | + open(22,file='pkg.dat') |
1662 | + do ikg = 1,nkg |
1663 | + write(22,'(20e15.6)') kgmesh(ikg), pkg(:,ikg), d2pkgdkg2(:,ikg) |
1664 | + end do |
1665 | + close(22) |
1666 | +! END DEBUG |
1667 | + |
1668 | + first_call = .false. |
1669 | + end if |
1670 | + |
1671 | +! 'Saturate' (kf,kg) values to bring them to interpolation range |
1672 | + call saturate( kf, kfcut, kf0, dkf0dkf ) |
1673 | + call saturate( kg, kgcut, kg0, dkg0dkg ) |
1674 | + |
1675 | +! Find interval of k mesh in which (kf0,kg0) point is included |
1676 | + call iofk( kf0, kg0, ikf0, ikg0 ) |
1677 | + |
1678 | +! Evaluate pkf polynomials of spline basis at kf0 |
1679 | +! The splint code is in-lined here because it is a hot point |
1680 | + dk = kfmesh(ikf0+1) - kfmesh(ikf0) |
1681 | + a = (kfmesh(ikf0+1) - kf0) / dk ! dadkf0 = -1/dk |
1682 | + b = (kf0 - kfmesh(ikf0)) / dk ! dbdkf0 = +1/dk |
1683 | + do ikf = 1,nkf |
1684 | + pkf0(ikf) = a*pkf(ikf0,ikf) + b*pkf(ikf0+1,ikf) & |
1685 | + + ((a**3-a)*d2pkfdkf2(ikf0,ikf) + & |
1686 | + (b**3-b)*d2pkfdkf2(ikf0+1,ikf)) * dk**2/6 |
1687 | + dpkfdkf0(ikf) = - (pkf(ikf0,ikf) - pkf(ikf0+1,ikf)) / dk & |
1688 | + - ((3*a**2-1)*d2pkfdkf2(ikf0,ikf) - & |
1689 | + (3*b**2-1)*d2pkfdkf2(ikf0+1,ikf)) * dk/6 |
1690 | + end do |
1691 | + |
1692 | +! Evaluate pkg polynomials of spline basis at kg0 |
1693 | + dk = kgmesh(ikg0+1) - kgmesh(ikg0) |
1694 | + a = (kgmesh(ikg0+1) - kg0) / dk ! dadkg0 = -1/dk |
1695 | + b = (kg0 - kgmesh(ikg0)) / dk ! dbdkg0 = +1/dk |
1696 | + do ikg = 1,nkg |
1697 | + pkg0(ikg) = a*pkg(ikg0,ikg) + b*pkg(ikg0+1,ikg) & |
1698 | + + ((a**3-a)*d2pkgdkg2(ikg0,ikg) + & |
1699 | + (b**3-b)*d2pkgdkg2(ikg0+1,ikg)) * dk**2/6 |
1700 | + dpkgdkg0(ikg) = - (pkg(ikg0,ikg) - pkg(ikg0+1,ikg)) / dk & |
1701 | + - ((3*a**2-1)*d2pkgdkg2(ikg0,ikg) - & |
1702 | + (3*b**2-1)*d2pkgdkg2(ikg0+1,ikg)) * dk/6 |
1703 | + end do |
1704 | + |
1705 | +! Evaluate pkf*pkg polynomials at (kf0,kg0) |
1706 | + ikfg = 0 |
1707 | + do ikg = 1,nkg |
1708 | + do ikf = 1,nkf |
1709 | + ikfg = ikfg+1 |
1710 | + p(ikfg) = pkf0(ikf) * pkg0(ikg) |
1711 | + dpdkf(ikfg) = dpkfdkf0(ikf)*dkf0dkf * pkg0(ikg) |
1712 | + dpdkg(ikfg) = pkf0(ikf) * dpkgdkg0(ikg)*dkg0dkg |
1713 | + end do |
1714 | + end do |
1715 | + |
1716 | +end subroutine pofk |
1717 | + |
1718 | +!----------------------------------------------------------------------------- |
1719 | + |
1720 | +subroutine saturate( x, xc, y, dydx ) |
1721 | + |
1722 | + ! Defines a function y(x,xc) = 1/(1/x^nsat+1/xc^nsat)^(1/nsat), where nsat |
1723 | + ! is an integer set in the module header. This function is approximately |
1724 | + ! equal to x for x<xc and it saturates to xc when x->infinity |
1725 | + |
1726 | + implicit none |
1727 | + real(dp),intent(in) :: x ! Independent variable |
1728 | + real(dp),intent(in) :: xc ! Saturation value |
1729 | + real(dp),intent(out):: y ! Function value |
1730 | + real(dp),intent(out):: dydx ! Derivative dy/dx |
1731 | + |
1732 | + real(dp):: z |
1733 | + |
1734 | + if (xc<=0._dp) then |
1735 | + call die('pbevv_vdwxc_saturate ERROR: xc<=0') |
1736 | + else if (x<0._dp) then |
1737 | + call die('pbevv_vdwxc_saturate ERROR: x<0') |
1738 | + else if (x==0._dp) then |
1739 | + y = 0 |
1740 | + dydx = 1 |
1741 | + else |
1742 | + z = 1/x**nsat + 1/xc**nsat |
1743 | + y = 1/z**(1._dp/nsat) |
1744 | + dydx = y/z/x**(nsat+1) |
1745 | + end if |
1746 | + |
1747 | +end subroutine saturate |
1748 | + |
1749 | +!----------------------------------------------------------------------------- |
1750 | + |
1751 | +subroutine saturate_inverse( y, xc, x, dxdy ) |
1752 | + |
1753 | +! Finds the inverse of the function defined in saturate subroutine: |
1754 | +! y=1/(1/x^n+1/xc^n)^(1/n) => x=1/(1/y^n-1/xc^n)^(1/n) |
1755 | + |
1756 | + implicit none |
1757 | + real(dp),intent(in) :: y ! Independent variable |
1758 | + real(dp),intent(in) :: xc ! Saturation value |
1759 | + real(dp),intent(out):: x ! Inverse function value |
1760 | + real(dp),intent(out):: dxdy ! Derivative dx/dy |
1761 | + |
1762 | + real(dp):: z |
1763 | + |
1764 | + if (xc<=0._dp) then |
1765 | + call die('pbevv_vdwxc_saturate_inverse ERROR: xc<=0') |
1766 | + else if (y<0._dp .or. y>=xc) then |
1767 | + call die('pbevv_vdwxc_saturate_inverse ERROR: y out of range') |
1768 | + else if (y==0._dp) then |
1769 | + x = 0 |
1770 | + dxdy = 1 |
1771 | + else |
1772 | + z = 1/y**nsat - 1/xc**nsat |
1773 | + x = 1/z**(1._dp/nsat) |
1774 | + dxdy = x/z/y**(nsat+1) |
1775 | + end if |
1776 | + |
1777 | +end subroutine saturate_inverse |
1778 | + |
1779 | +!----------------------------------------------------------------------------- |
1780 | + |
1781 | +subroutine set_kmesh() |
1782 | + |
1783 | +! Sets mesh of q values |
1784 | + |
1785 | + implicit none |
1786 | + integer :: mkf, mkg |
1787 | + |
1788 | + if (.not.kmesh_set) then |
1789 | + call set_mesh( nkf, xmax=kfcut, dxndx1=dkfmaxdkfmin ) |
1790 | + call get_mesh( nkf, mkf, kfmesh ) |
1791 | + call set_mesh( nkg, xmax=kgcut, dxndx1=dkgmaxdkgmin ) |
1792 | + call get_mesh( nkg, mkg, kgmesh ) |
1793 | + kmesh_set = .true. |
1794 | +#ifdef DEBUG_XC |
1795 | + write(udebug,'(/,a,/,(10f8.4))') 'pbevv_vdw_set_kmesh: kfmesh =', kfmesh |
1796 | + write(udebug,'(/,a,/,(10f8.4))') 'pbevv_vdw_set_kmesh: kgmesh =', kgmesh |
1797 | +#endif /* DEBUG_XC */ |
1798 | + end if |
1799 | + |
1800 | +end subroutine set_kmesh |
1801 | + |
1802 | +! ----------------------------------------------------------------------------- |
1803 | + |
1804 | +subroutine set_phi_table() |
1805 | + |
1806 | +! Finds and stores in memory the interpolation table (mesh points and |
1807 | +! function values) for the kernel phi(k1,k2,k). |
1808 | + |
1809 | + implicit none |
1810 | + character(len=*),parameter:: myName = 'pbevv_vdwxc/set_phi_table ' |
1811 | + integer :: ik, ikf1, ikf2, ikg1, ikg2, ik1, ik2, ir |
1812 | + real(dp):: dkdk0, dphidk0, dphidkmax, dphidr0, dphidrmax, & |
1813 | + k, kf1, kf2, kg1, kg2, pi, r(0:nr) |
1814 | + |
1815 | +! Check that table was not set yet |
1816 | + if (phi_table_set) return |
1817 | + |
1818 | +! Check that kf, kg, r, and k meshes have been set |
1819 | + if (.not.kmesh_set) call set_kmesh() |
1820 | + if (.not.kcut_set) call die('pbevv_vdw_set_phi_table ERROR: kcut not set') |
1821 | + forall(ir=0:nr) r(ir) = ir*dr |
1822 | + pi = acos(-1.0_dp) |
1823 | + |
1824 | +! Allocate arrays |
1825 | + call re_alloc( phir, 0,nr, 1,nkfg, 1,nkfg, myName//'phir' ) |
1826 | + call re_alloc( phik, 0,nr, 1,nkfg, 1,nkfg, myName//'phik' ) |
1827 | + call re_alloc( d2phidr2, 0,nr, 1,nkfg, 1,nkfg, myName//'d2phidr2' ) |
1828 | + call re_alloc( d2phidk2, 0,nr, 1,nkfg, 1,nkfg, myName//'d2phidk2' ) |
1829 | + |
1830 | +! Loop on (k1,k2) mesh points |
1831 | + do ikg2 = 1,nkg ! loop on kg2 |
1832 | + do ikf2 = 1,nkf ! loop on kf2 |
1833 | + ik2 = ikf2 + nkf*(ikg2-1) ! combined (ikf2,ikg2) index |
1834 | + do ikg1 = 1,nkg ! loop on kg1 |
1835 | + do ikf1 = 1,nkf ! loop on kf1 |
1836 | + ik1 = ikf1 + nkf*(ikg1-1) ! combined (ikf1,ikg1) index |
1837 | + if (ik1>ik2) cycle ! since we will symmetrize at the end |
1838 | + |
1839 | + ! Saturated (kf,kg) values |
1840 | + kf1 = kfmesh(ikf1) |
1841 | + kf2 = kfmesh(ikf2) |
1842 | + kg1 = kgmesh(ikg1) |
1843 | + kg2 = kgmesh(ikg2) |
1844 | + |
1845 | + ! Find original (unsaturated) kf anf kg values |
1846 | + ! call saturate_inverse( kfmesh(ikf1), kfcut, kf1, dkdk0 ) |
1847 | + ! call saturate_inverse( kfmesh(ikf2), kfcut, kf2, dkdk0 ) |
1848 | + ! call saturate_inverse( kgmesh(ikg1), kgcut, kg1, dkdk0 ) |
1849 | + ! call saturate_inverse( kgmesh(ikg2), kgcut, kg2, dkdk0 ) |
1850 | + |
1851 | + ! Find kernel as a function of r12 |
1852 | + do ir = 0,nr |
1853 | + phir(ir,ik1,ik2) = pbevv_vdw_phi_val( kf1, kf2, kg1, kg2, r(ir) ) |
1854 | + end do |
1855 | + |
1856 | + ! Kill kernel smoothly at r=rcut |
1857 | + do ir = 0,nr |
1858 | + phir(ir,ik1,ik2) = phir(ir,ik1,ik2) * cutoff( r(ir)/rcut ) |
1859 | + end do |
1860 | + |
1861 | + ! Find kernel in reciprocal space |
1862 | + call radfft( 0, nr, rcut, phir(:,ik1,ik2), phik(:,ik1,ik2) ) |
1863 | + phik(:,ik1,ik2) = phik(:,ik1,ik2) * (2*pi)**1.5_dp |
1864 | + |
1865 | + ! Filter out above kcut |
1866 | + phik(nk:nr,ik1,ik2) = 0 |
1867 | + |
1868 | + ! Soft filter below kcut |
1869 | + do ik = 1,nk |
1870 | + k = ik * dk |
1871 | + phik(ik,ik1,ik2) = phik(ik,ik1,ik2) * cutoff(k/kcut) |
1872 | + end do |
1873 | + |
1874 | + ! Find filtered kernel in real space |
1875 | + call radfft( 0, nr, kmax, phik(:,ik1,ik2), phir(:,ik1,ik2) ) |
1876 | + phir(:,ik1,ik2) = phir(:,ik1,ik2) / (2*pi)**1.5_dp |
1877 | + |
1878 | + ! Set up spline interpolation tables |
1879 | + dphidr0 = 0 ! since phi(k1,k2,r) is even in r |
1880 | + dphidk0 = 0 ! and therefore phi(k1,k2,k) is also even in k |
1881 | + dphidrmax = 0 ! since phi->0 for r->infty |
1882 | + dphidkmax = 0 ! and also when k->infty |
1883 | + call spline( dr, phir(:,ik1,ik2), nr+1, dphidr0, dphidrmax, & |
1884 | + d2phidr2(:,ik1,ik2) ) |
1885 | + call spline( dk, phik(:,ik1,ik2), nk+1, dphidk0, dphidkmax, & |
1886 | + d2phidk2(:,ik1,ik2) ) |
1887 | + |
1888 | + ! Fill symmetric elements |
1889 | + phir(:,ik2,ik1) = phir(:,ik1,ik2) |
1890 | + phik(:,ik2,ik1) = phik(:,ik1,ik2) |
1891 | + d2phidr2(:,ik2,ik1) = d2phidr2(:,ik1,ik2) |
1892 | + d2phidk2(:,ik2,ik1) = d2phidk2(:,ik1,ik2) |
1893 | + |
1894 | +!#ifdef DEBUG_XC |
1895 | +! if (.false. .and. ik1==ik2) then |
1896 | +! print*, 'pbevv_vdw_set_kcut: ik1,ik2=', ik1, ik2 |
1897 | +! call window( 0._dp, 5._dp, -1._dp, 4._dp, 0 ) |
1898 | +! call axes( 0._dp, 1._dp, 0._dp, 1._dp ) |
1899 | +! call plot( nr+1, r, phi, phir(:,ik1,ik2) ) |
1900 | +! call window( 0._dp, 10._dp, -0.05_dp, 0.15_dp, 0 ) |
1901 | +! call axes( 0._dp, 1._dp, 0._dp, 0.05_dp ) |
1902 | +! call plot( nr+1, r, r**2*phi, r**2*phir(:,ik1,ik2)) |
1903 | +! call show() |
1904 | +! end if |
1905 | +!#endif /* DEBUG_XC */ |
1906 | + |
1907 | + end do ! ikf1 |
1908 | + end do ! ikg1 |
1909 | + end do ! ikf2 |
1910 | + end do ! ikg2 |
1911 | + |
1912 | +!#ifdef DEBUG_XC |
1913 | +! open(17,file='vv_phi.table') |
1914 | +! write(17,'(3a6,2a12,/,(3i6,2f15.9))') & |
1915 | +! 'ik1', 'ik2', 'ir', 'phi', 'd2phi/dk2', & |
1916 | +!! (((ik1,ik2,ir,phir(ir,ik1,ik2),d2phidr2(ir,ik1,ik2), & |
1917 | +! (((ik1,ik2,ir,phik(ir,ik1,ik2),d2phidk2(ir,ik1,ik2), & |
1918 | +! ir=0,100),ik2=1,nkfg),ik1=1,nkfg) |
1919 | +! close(17) |
1920 | +!#endif /* DEBUG_XC */ |
1921 | + |
1922 | +! Mark table as set |
1923 | + phi_table_set = .true. |
1924 | + |
1925 | +end subroutine set_phi_table |
1926 | + |
1927 | +! ----------------------------------------------------------------------------- |
1928 | + |
1929 | +real(dp) function pbevv_vdw_phi_val( kf1, kf2, kg1, kg2, r12 ) |
1930 | + |
1931 | +! vdW energy kernel of Vydrov-vanVoorhis, eq.(2) of JCP 133, 244103 (2010) |
1932 | +! This subroutine calculates the 'raw' kernel directly, without interpolarions |
1933 | +! In practice, it returns n1*n2*phi(k1,k2,r12), which is smooth for kf->0 |
1934 | +! Input: |
1935 | +! real(dp):: kf1, kf2 ! Fermi wavevectors at points 1 and 2 |
1936 | +! real(dp):: kg1, kg2 ! |grad(n)|/n at points 1 and 2 |
1937 | +! real(dp):: r12 ! distance between points 1 and 2 |
1938 | + |
1939 | +! Arguments |
1940 | + implicit none |
1941 | + real(dp),intent(in) :: kf1, kf2, kg1, kg2, r12 |
1942 | + |
1943 | +! Internal variables |
1944 | + real(dp):: g1, g2, kappa1, kappa2, kf1m, kf2m, n1, n2, & |
1945 | + phi, pi, w01, w02, wg1, wg2, wp1, wp2 |
1946 | + |
1947 | +! Avoid dividing by zero when kf=0 |
1948 | + kf1m = max(kf1,ktol) |
1949 | + kf2m = max(kf2,ktol) |
1950 | + |
1951 | +! Find kernel |
1952 | + pi = acos(-1.0_dp) |
1953 | + n1 = kf1m**3/(3*pi**2) ! electron density at point 1 |
1954 | + n2 = kf2m**3/(3*pi**2) ! electron density at point 2 |
1955 | + wp1 = sqrt(4*pi*n1) ! local plasma frequency at point 1 |
1956 | + wp2 = sqrt(4*pi*n2) ! local plasma frequency at point 2 |
1957 | + wg1 = sqrt(vv_C*kg1**4) ! local band gap at point 1 |
1958 | + wg2 = sqrt(vv_C*kg2**4) ! local band gap at point 2 |
1959 | + kappa1 = vv_b*kf1m**2/wp1 ! local VV kappa variable (eq.(9)) at point 1 |
1960 | + kappa2 = vv_b*kf2m**2/wp2 ! kappa variable at point 2 |
1961 | + w01 = sqrt(wg1**2+wp1**2/3) ! local w0 frequency (eq.(5)) at point 1 |
1962 | + w02 = sqrt(wg2**2+wp2**2/3) ! local w0 frequency at point 2 |
1963 | + g1 = w01*r12**2 + kappa1 ! local g variable (eq.(3)) at point 1 |
1964 | + g2 = w02*r12**2 + kappa2 ! local g variable at point 2 |
1965 | + phi = -1.5_dp/g1/g2/(g1+g2) ! VV kernel phi (eq.(2)) |
1966 | + |
1967 | + if (kernelPrefactor=='rho') then |
1968 | + ! Return whole integrand of eq.(1) |
1969 | + pbevv_vdw_phi_val = n1*n2*phi |
1970 | + else if (kernelPrefactor=='kf') then |
1971 | + ! Return kf1*kf2*phi |
1972 | + pbevv_vdw_phi_val = kf1*kf2*phi |
1973 | + else if (kernelPrefactor=='kf2') then |
1974 | + ! Return (kf1*kf2)**2*phi |
1975 | + pbevv_vdw_phi_val = (kf1*kf2)**2*phi |
1976 | + else if (kernelPrefactor=='sqr_rho') then |
1977 | + ! Find and return sqrt(n1*n2)*phi |
1978 | + pbevv_vdw_phi_val = sqrt(n1*n2)*phi |
1979 | + else |
1980 | + call die('pbevv_vdw_phi_val ERROR: unknown kernelPrefactor') |
1981 | + end if |
1982 | + |
1983 | +end function pbevv_vdw_phi_val |
1984 | + |
1985 | +! ----------------------------------------------------------------------------- |
1986 | + |
1987 | +real(dp) function pbevv_vdw_beta() |
1988 | + |
1989 | +! Returns parameter beta of VV functional |
1990 | + |
1991 | + implicit none |
1992 | + pbevv_vdw_beta = vv_beta |
1993 | + |
1994 | +end function pbevv_vdw_beta |
1995 | + |
1996 | +!----------------------------------------------------------------------------- |
1997 | + |
1998 | +subroutine pbevv_vdw_get_kmesh( mkf, mkg, kf, kg ) |
1999 | + |
2000 | +! Returns size and values of (kf,kg) mesh |
2001 | + |
2002 | + implicit none |
2003 | + integer, intent(out) :: mkf ! Number of kf mesh points |
2004 | + integer, intent(out) :: mkg ! Number of kg mesh points |
2005 | + real(dp),optional,intent(out) :: kf(:) ! Values of kf mesh points |
2006 | + real(dp),optional,intent(out) :: kg(:) ! Values of kg mesh points |
2007 | + integer:: nmax |
2008 | + if (.not.kmesh_set) call set_kmesh() |
2009 | + mkf = nkf |
2010 | + mkg = nkg |
2011 | + if (present(kf)) then |
2012 | + nmax = max( nkf, size(kf) ) |
2013 | + kf(1:nmax) = kfmesh(1:nmax) |
2014 | + end if |
2015 | + if (present(kg)) then |
2016 | + nmax = max( nkg, size(kg) ) |
2017 | + kg(1:nmax) = kgmesh(1:nmax) |
2018 | + end if |
2019 | +end subroutine pbevv_vdw_get_kmesh |
2020 | + |
2021 | +! ----------------------------------------------------------------------------- |
2022 | + |
2023 | +subroutine pbevv_vdw_phi( k, phi, dphidk ) |
2024 | + |
2025 | +! Finds by interpolation phi(k1,k2,k) (Fourier transform of phi(k1,k2,r)), |
2026 | +! with k1=(kf1,kg1), k2=(kf2,kg2) for all mesh values of kf (Fermi |
2027 | +! wavevector) and kg (grad(n)/n). If the interpolation table does not exist, |
2028 | +! it is calculated in the first call to pbevv_vdw_phi. It requires a previous |
2029 | +! call to pbevv_vdw_set_kc to set k mesh. |
2030 | + |
2031 | + implicit none |
2032 | + real(dp),intent(in) :: k ! Modulus of actual k vector |
2033 | + real(dp),intent(out):: phi(:,:) ! phi(k1,k2,k) at given k |
2034 | + ! for all k1,k2 in (kf,kg) mesh |
2035 | + real(dp),intent(out):: dphidk(:,:) ! dphi(k1,k2,k)/dk at given k |
2036 | + |
2037 | + integer :: ik, ik1, ik2 |
2038 | + real(dp):: a, a2, a3, b, b2, b3 |
2039 | + |
2040 | +! Set interpolation table |
2041 | + if (.not.phi_table_set) call set_phi_table() |
2042 | + |
2043 | +! Check argument sizes |
2044 | + if (size(phi,1)<nkfg .or. size(phi,2)<nkfg) & |
2045 | + call die('pbevv_vdw_phi: ERROR: size(phi) too small') |
2046 | + |
2047 | +! Find phi values at point k |
2048 | + if (k >= kcut) then |
2049 | + phi(:,:) = 0 |
2050 | + dphidk(:,:) = 0 |
2051 | + else |
2052 | + ! Expand interpolation inline since this is the hottest point in VdW |
2053 | + ik = int(k/dk) |
2054 | + a = ((ik+1)*dk-k)/dk |
2055 | + b = 1 - a |
2056 | + a2 = (3*a**2 -1) * dk / 6 |
2057 | + b2 = (3*b**2 -1) * dk / 6 |
2058 | + a3 = (a**3 - a) * dk**2 / 6 |
2059 | + b3 = (b**3 - b) * dk**2 / 6 |
2060 | + do ik2 = 1,nkfg |
2061 | + do ik1 = 1,ik2 |
2062 | +! call splint( dk, phik(:,ik1,ik2), d2phidk2(:,ik1,ik2), & |
2063 | +! nk+1, k, phi(ik1,ik2), dphidk(ik1,ik2), pr ) |
2064 | + phi(ik1,ik2) = a*phik(ik,ik1,ik2) + b*phik(ik+1,ik1,ik2) & |
2065 | + + a3*d2phidk2(ik,ik1,ik2) + b3*d2phidk2(ik+1,ik1,ik2) |
2066 | + dphidk(ik1,ik2) = (-phik(ik,ik1,ik2) & |
2067 | + +phik(ik+1,ik1,ik2) )/dk & |
2068 | + - a2*d2phidk2(ik,ik1,ik2) + b2*d2phidk2(ik+1,ik1,ik2) |
2069 | + phi(ik2,ik1) = phi(ik1,ik2) |
2070 | + dphidk(ik2,ik1) = dphidk(ik1,ik2) |
2071 | + end do |
2072 | + end do |
2073 | + end if |
2074 | + |
2075 | +end subroutine pbevv_vdw_phi |
2076 | + |
2077 | +!----------------------------------------------------------------------------- |
2078 | + |
2079 | +subroutine pbevv_vdw_phiofr( r, phi ) |
2080 | + |
2081 | +! Finds phi(k1,k2,r) with k1=(kf1,kg1), k2=(kf2,kg2) for mesh values of |
2082 | +! kf's (Fermi wavevectors) and kg's (grad(n)/n) |
2083 | + |
2084 | + implicit none |
2085 | + real(dp),intent(in) :: r |
2086 | + real(dp),intent(out):: phi(:,:) |
2087 | + |
2088 | + integer :: ikf1, ikf2, ikg1, ikg2, ik1, ik2 |
2089 | + real(dp):: dphidr |
2090 | + |
2091 | + if (size(phi,1)<nkfg .or. size(phi,2)<nkfg) & |
2092 | + stop 'vv_phiofr: ERROR: size(phi) too small' |
2093 | + if (.not.phi_table_set) call set_phi_table() |
2094 | + |
2095 | + if (r >= rcut) then |
2096 | + phi(:,:) = 0 |
2097 | + else |
2098 | + do ik2 = 1,nkfg |
2099 | + do ik1 = 1,ik2 |
2100 | + call splint( dr, phir(:,ik1,ik2), d2phidr2(:,ik1,ik2), & |
2101 | + nr+1, r, phi(ik1,ik2), dphidr ) |
2102 | + phi(ik2,ik1) = phi(ik1,ik2) |
2103 | + end do ! ik1 |
2104 | + end do ! ik2 |
2105 | + end if ! (r>=rcut) |
2106 | + |
2107 | +end subroutine pbevv_vdw_phiofr |
2108 | + |
2109 | +!----------------------------------------------------------------------------- |
2110 | + |
2111 | +subroutine pbevv_vdw_set_kcut( kc ) |
2112 | + |
2113 | +! Sets the reciprocal planewave cutoff kc of the integration grid, and finds |
2114 | +! the interpolation table to be used by vdw_phi to obtain the vdW kernel phi |
2115 | +! at the reciprocal mesh wavevectors. |
2116 | + |
2117 | + implicit none |
2118 | + real(dp),intent(in):: kc ! Planewave cutoff: k>kcut => phi=0 |
2119 | + |
2120 | + real(dp):: pi |
2121 | + |
2122 | + ! Set kcut and radial mesh parameters, if not already set |
2123 | + if (.not. kc==kcut) then |
2124 | + kcut = kc |
2125 | + pi = acos(-1._dp) |
2126 | + dr = rcut / nr |
2127 | + dk = pi / rcut |
2128 | + kmax = pi / dr |
2129 | + nk = int(kcut/dk) + 1 |
2130 | + if (nk>nr) stop 'pbevv_vdw_set_kcut: ERROR: nk>nr' |
2131 | + kcut_set = .true. |
2132 | +#ifdef DEBUG_XC |
2133 | + write(udebug,'(a,5f8.3)') 'pbevv_vdw_set_kcut: kfcut,kgcut,rcut,kcut,kmax=', & |
2134 | + kfcut, kgcut, rcut, kc, kmax |
2135 | +#endif /* DEBUG_XC */ |
2136 | + end if |
2137 | + |
2138 | + ! Set (kf,kg) mesh and phi table |
2139 | + call set_kmesh() |
2140 | + call set_phi_table() |
2141 | + |
2142 | +end subroutine pbevv_vdw_set_kcut |
2143 | + |
2144 | +!----------------------------------------------------------------------------- |
2145 | + |
2146 | +subroutine pbevv_vdw_theta( nspin, rhos, grhos, theta, dtdrho, dtdgrho ) |
2147 | + |
2148 | +! Finds the value and derivatives of theta_i(rho,grad_rho) of eq.(8) |
2149 | +! of Roman-Soler PRL 2009. In practice, theta_i=p_i rather than rho*p_i, |
2150 | +! beacuse p_i is used here to expand rho1*rho2*phi rather than only phi. |
2151 | + |
2152 | + implicit none |
2153 | + integer, intent(in) :: nspin ! Number of spin components |
2154 | + real(dp),intent(in) :: rhos(nspin) ! Electron spin density |
2155 | + real(dp),intent(in) :: grhos(3,nspin) ! Spin density gradient |
2156 | + real(dp),intent(out):: theta(nkfg) ! Exp. polynomials at (kf,kg) |
2157 | + real(dp),intent(out):: dtdrho(nkfg,nspin) ! dtheta(ik)/drhos |
2158 | + real(dp),intent(out):: dtdgrho(3,nkfg,nspin) ! dtheta(ik)/dgrhos(ix) |
2159 | + |
2160 | + integer :: is, ix, ns |
2161 | + real(dp):: rho, grho(3), dpdkf(nkfg), dpdkg(nkfg), dkfdrho, dkfdgrho(3), & |
2162 | + dkgdrho, dkgdgrho(3), kf, kg, p(nkfg) |
2163 | + |
2164 | + ! Sum spin components of electron density |
2165 | + ns = min(nspin,2) ! num. of diagonal spin components (if noncollinear) |
2166 | + rho = sum(rhos(1:ns)) ! local electron density |
2167 | + grho = sum(grhos(:,1:ns),dim=2) ! local density gradient |
2168 | + |
2169 | + ! If density is between threshold, return zero |
2170 | + if (rho<rhoMin) then |
2171 | + theta = 0 |
2172 | + dtdrho = 0 |
2173 | + dtdgrho = 0 |
2174 | + return |
2175 | + end if |
2176 | + |
2177 | + ! Find local Fermi and gradient wavevectors, and their derivatives |
2178 | + call kofn( rho, grho, kf, kg, dkfdrho, dkgdrho, dkfdgrho, dkgdgrho ) |
2179 | + |
2180 | + ! Find expansion polynomials of integrand kernel of nonlocal vdW energy |
2181 | + call pofk( kf, kg, p, dpdkf, dpdkg ) |
2182 | + |
2183 | + ! Find theta functions and their derivatives with respect to rho and grho |
2184 | + if (kernelPrefactor=='rho') then |
2185 | + ! This is the right code if pbevv_vdw_phi_val returns rho1*rho2*phi |
2186 | + theta(1:nkfg) = p(1:nkfg) |
2187 | + do is = 1,ns |
2188 | + dtdrho(1:nkfg,is) = dpdkf(1:nkfg)*dkfdrho + dpdkg(1:nkfg)*dkgdrho |
2189 | + do ix = 1,3 |
2190 | + dtdgrho(ix,1:nkfg,is) = dpdkf(1:nkfg)*dkfdgrho(ix) & |
2191 | + + dpdkg(1:nkfg)*dkgdgrho(ix) |
2192 | + end do |
2193 | + end do |
2194 | + else if (kernelPrefactor=='kf') then |
2195 | + ! This is the right code if pbevv_vdw_phi_val returns kf1*kf2*phi |
2196 | + kf = max(kf,ktol) |
2197 | + theta(1:nkfg) = p(1:nkfg)*rho/kf |
2198 | + do is = 1,ns |
2199 | + dtdrho(1:nkfg,is) = (dpdkf(1:nkfg)*dkfdrho & |
2200 | + +dpdkg(1:nkfg)*dkgdrho)*rho/kf & |
2201 | + + p(1:nkfg)*(1/kf-rho/kf**2*dkfdrho) |
2202 | + do ix = 1,3 |
2203 | + dtdgrho(ix,1:nkfg,is) = (dpdkf(1:nkfg)*dkfdgrho(ix) & |
2204 | + +dpdkg(1:nkfg)*dkgdgrho(ix))*rho/kf |
2205 | + end do |
2206 | + end do |
2207 | + else if (kernelPrefactor=='kf2') then |
2208 | + ! This is the right code if pbevv_vdw_phi_val returns (kf1*kf2)**2*phi |
2209 | + kf = max(kf,ktol) |
2210 | + theta(1:nkfg) = p(1:nkfg)*rho/kf**2 |
2211 | + do is = 1,ns |
2212 | + dtdrho(1:nkfg,is) = (dpdkf(1:nkfg)*dkfdrho & |
2213 | + +dpdkg(1:nkfg)*dkgdrho)*rho/kf**2 & |
2214 | + + p(1:nkfg)*(1/kf**2-2*rho/kf**3*dkfdrho) |
2215 | + do ix = 1,3 |
2216 | + dtdgrho(ix,1:nkfg,is) = (dpdkf(1:nkfg)*dkfdgrho(ix) & |
2217 | + +dpdkg(1:nkfg)*dkgdgrho(ix))*rho/kf**2 |
2218 | + end do |
2219 | + end do |
2220 | + else if (kernelPrefactor=='sqr_rho') then |
2221 | + ! This is the right code if pbevv_vdw_phi_val returns sqrt(rho1*rho2)*phi |
2222 | + rho = max(rho,1.e-12_dp) ! to avoid division by zero |
2223 | + theta(1:nkfg) = p(1:nkfg) * sqrt(rho) |
2224 | + do is = 1,ns |
2225 | + dtdrho(1:nkfg,is) = ( dpdkf(1:nkfg)*dkfdrho & |
2226 | + + dpdkg(1:nkfg)*dkgdrho ) * sqrt(rho) & |
2227 | + + p(1:nkfg) * 0.5/sqrt(rho) |
2228 | + do ix = 1,3 |
2229 | + dtdgrho(ix,1:nkfg,is) = dpdkf(1:nkfg)*dkfdgrho(ix) * sqrt(rho) & |
2230 | + + dpdkg(1:nkfg)*dkgdgrho(ix) * sqrt(rho) |
2231 | + end do |
2232 | + end do |
2233 | + else |
2234 | + call die('pbevv_vdw_theta ERROR: unknown kernelPrefactor') |
2235 | + end if ! (kernelPrefactor=='rho') |
2236 | + |
2237 | +end subroutine pbevv_vdw_theta |
2238 | + |
2239 | +END MODULE m_pbevv_vdwxc |
2240 | + |
2241 | +!!!=============== PBEsol+VV10s ========================= |
2242 | + |
2243 | +MODULE m_pbesvvs_vdwxc |
2244 | + |
2245 | +! Used module procedures |
2246 | + use sys, only: die ! Termination routine |
2247 | + use mesh1D, only: get_mesh ! Returns the mesh points |
2248 | + use m_radfft, only: radfft ! Radial fast Fourier transform |
2249 | + use alloc, only: re_alloc ! Re-allocation routine |
2250 | + use mesh1D, only: set_mesh ! Sets a 1D mesh |
2251 | + use interpolation,only: spline ! Sets spline interpolation |
2252 | + use interpolation,only: splint ! Calculates spline interpolation |
2253 | + |
2254 | +! Used module parameters |
2255 | + use precision, only: dp ! Real double precision type |
2256 | + |
2257 | +#ifdef DEBUG_XC |
2258 | + use debugXC, only: udebug ! File unit for debug output |
2259 | +! use plot_module, only: plot |
2260 | +#endif /* DEBUG_XC */ |
2261 | + |
2262 | + implicit none |
2263 | + |
2264 | +! Called by m_vdwxc |
2265 | +PUBLIC :: & |
2266 | + pbesvvs_vdw_beta, &! Returns parameter beta of the VV2010 functional |
2267 | + pbesvvs_vdw_theta, &! Finds function theta_ik(rho,grad_rho) |
2268 | + pbesvvs_vdw_get_kmesh, &! Returns size and values of (kf,kg) mesh |
2269 | + pbesvvs_vdw_phi, &! Finds and interpolates rho1*rho2*phi(k1,k2,k) |
2270 | + pbesvvs_vdw_set_kcut ! Sets the planewave cutoff kc of the integration grid |
2271 | + |
2272 | +#ifdef DEBUG_XC |
2273 | +! Called by debugging test programs |
2274 | +PUBLIC :: & |
2275 | + pbesvvs_vdw_phi_val, &! Kernel phi(kf1,kf2,kg1,kg2,r12) with no interpolation |
2276 | + pbesvvs_vdw_phiofr ! Kernel phi(k1,k2,r) at tabulated k1,k2-mesh values |
2277 | +#endif /* DEBUG_XC */ |
2278 | + |
2279 | +PRIVATE ! Nothing is declared public beyond this point |
2280 | + |
2281 | + ! Set parameters of the PBEsol+rVV10s, |
2282 | + ! Ref. A. V. Terentjev et al, Phys. Rev. B 98, 214108 (2018) |
2283 | + real(dp),parameter:: vv_C = 0.0093 |
2284 | + real(dp),parameter:: vv_b = 10.0 |
2285 | + real(dp),parameter:: vv_beta = 0.00497 |
2286 | + |
2287 | + ! Mesh parameters for table of phi(k1,k2,r) and its Fourier transform |
2288 | + character(len=*),parameter:: kernelPrefactor='rho' ! Prefactor of the |
2289 | + ! nonlocal kernel for interpolation |
2290 | + ! ('kf'|'kf2'|'sqr_rho'|'rho') |
2291 | + integer, parameter:: nr = 2048 ! Radial mesh points (power of 2) |
2292 | + real(dp),parameter:: rcut = 100._dp ! Radial cutoff: r>rcut => phi=0 |
2293 | + real(dp),parameter:: rmin = 1.e-6_dp ! Min. radius as denominator |
2294 | + integer, parameter:: nkf = 7 ! Number of Fermi wavevectors |
2295 | + integer, parameter:: nkg = 5 ! Num. of grad(n)/n wavevectors |
2296 | + integer, parameter:: nkfg = nkf*nkg ! Num. of (kf,kg) mesh points |
2297 | + real(dp),parameter:: kfcut = 5.0_dp ! Max. Fermi wavevec. |
2298 | + real(dp),parameter:: kgcut = 5.0_dp ! Max. grad(n)/n |
2299 | + real(dp),parameter:: dkfmaxdkfmin = 20.0_dp ! Last/first kf mesh interval |
2300 | + real(dp),parameter:: dkgmaxdkgmin = 2.0_dp ! Last/first kg mesh interval |
2301 | + real(dp),parameter:: ktol = 1.e-12_dp ! 'out of range' tolerance |
2302 | + real(dp),parameter:: amin = 1.e-12_dp ! tiny denominator to avoid /0 |
2303 | + real(dp),parameter:: rhoMin = 1.e-10_dp ! Min. density for nonzero Vxc |
2304 | + |
2305 | + ! Parameters for cutoff function, used in radial Fourier transforms of phi |
2306 | + integer, parameter:: ncut1 = 8 ! cutoff(x)=(1-x**ncut1)**ncut2 |
2307 | + integer, parameter:: ncut2 = 4 |
2308 | + |
2309 | + ! Parameters for saturate function, used to enforce that q<qcut |
2310 | + integer, parameter:: nsat = 15 ! h(x,xc)=1/(1/x**nsat+1/xc**nsat)**(1/nsat) |
2311 | + ! nsat=15 approximately corresponds to |
2312 | + ! nsat=12 for eq.(5) of Roman-Soler PRL |
2313 | + |
2314 | + ! Private module variables and arrays |
2315 | + logical, save:: kcut_set=.false. ! Has kcut been set? |
2316 | + logical, save:: kmesh_set=.false. ! Has (kf,kg) mesh been set? |
2317 | + logical, save:: phi_table_set=.false. ! Has phi_table been set? |
2318 | + integer, save:: nk ! Num. of radial mesh k-points |
2319 | + real(dp),save:: dr ! r-mesh interval |
2320 | + real(dp),save:: dk ! k-mesh interval |
2321 | + real(dp),save:: kcut ! Planewave cutoff: k>kcut => phi=0 |
2322 | + real(dp),save:: kmax ! Max. k vector in Fourier transforms |
2323 | + real(dp),save:: kfmesh(nkf) ! Mesh points for Fermi wavevector |
2324 | + real(dp),save:: kgmesh(nkg) ! Mesh points for grad(n)/n |
2325 | + real(dp),pointer,save:: & |
2326 | + phir(:,:,:)=>null(), &! Table of phi(r) |
2327 | + phik(:,:,:)=>null(), &! Table of phi(k) |
2328 | + d2phidr2(:,:,:)=>null(),&! Table of d^2(phi)/dr^2 |
2329 | + d2phidk2(:,:,:)=>null() ! Table of d^2(phi)/dk^2 |
2330 | + |
2331 | +CONTAINS |
2332 | + |
2333 | +! ----------------------------------------------------------------------------- |
2334 | + |
2335 | +real(dp) function cutoff( x ) |
2336 | + |
2337 | +! Defines a smooth cutoff function that falls from y(0)=1 to y(1)=0 |
2338 | + |
2339 | + implicit none |
2340 | + real(dp),intent(in):: x |
2341 | + |
2342 | + if (x<=0._dp) then |
2343 | + cutoff = 1 |
2344 | + else if (x>=1._dp) then |
2345 | + cutoff = 0 |
2346 | + else |
2347 | + cutoff = (1-x**ncut1)**ncut2 |
2348 | + end if |
2349 | + |
2350 | +end function cutoff |
2351 | + |
2352 | +!----------------------------------------------------------------------------- |
2353 | + |
2354 | +subroutine iofk( kf, kg, ikf, ikg ) |
2355 | + |
2356 | +! Finds indexes ikf and ikg such that kfmesh(ikf) <= kf < kfmesh(ikf+1) |
2357 | +! and kgmesh(ikg) <= kg < kgmesh(ikg+1) in logarithmic meshes of the form |
2358 | +! k(ik) = b*(exp((ik-1)*a)-1) |
2359 | + |
2360 | + implicit none |
2361 | + real(dp), intent(in) :: kf, kg |
2362 | + integer, intent(out):: ikf, ikg |
2363 | + |
2364 | + real(dp),save:: akf, akg, bkf, bkg |
2365 | + logical, save:: first_call = .true. |
2366 | + integer:: ik |
2367 | + |
2368 | + ! Mesh data initializations |
2369 | + if (first_call) then |
2370 | + ! Find logarithmic-mesh a & b parameters: x(j)=x(1)+b*(exp(a*(j-1))-1) |
2371 | + akf = log( (kfmesh(nkf)-kfmesh(nkf-1)) / (kfmesh(2)-kfmesh(1)) ) / (nkf-2) |
2372 | + akg = log( (kgmesh(nkg)-kgmesh(nkg-1)) / (kgmesh(2)-kgmesh(1)) ) / (nkg-2) |
2373 | + akf = max( akf, amin ) |
2374 | + akg = max( akg, amin ) |
2375 | + bkf = (kfmesh(nkf) - kfmesh(1)) / (exp(akf*(nkf-1)) - 1) |
2376 | + bkg = (kgmesh(nkg) - kgmesh(1)) / (exp(akg*(nkg-1)) - 1) |
2377 | + ! Check that meshes are indeed logarithmic |
2378 | + do ik = 1,nkf |
2379 | + if (abs(kfmesh(ik)-kfmesh(1)-bkf*(exp(akf*(ik-1))-1))>ktol) & |
2380 | + call die('pbesvvs_vdw_iofk ERROR: kfmesh not logarithmic') |
2381 | + end do |
2382 | + do ik = 1,nkg |
2383 | + if (abs(kgmesh(ik)-kgmesh(1)-bkg*(exp(akg*(ik-1))-1))>ktol) & |
2384 | + call die('pbesvvs_vdw_iofk ERROR: kgmesh not logarithmic') |
2385 | + end do |
2386 | + first_call = .false. |
2387 | + end if |
2388 | + |
2389 | + ! Check that kf and kg are within interpolation range |
2390 | + if (kf<kfmesh(1)-ktol .or. kf>kfmesh(nkf)+ktol .or. & |
2391 | + kg<kgmesh(1)-ktol .or. kg>kgmesh(nkg)+ktol) then |
2392 | + call die('pbesvvs_vdw_iofk ERROR: (kf,kg) out of range') |
2393 | + endif |
2394 | + |
2395 | + ! Find interpolation mesh intervals |
2396 | + ikf = 1 + int( log( 1 + (kf-kfmesh(1))/bkf ) / akf ) |
2397 | + ikg = 1 + int( log( 1 + (kg-kgmesh(1))/bkg ) / akg ) |
2398 | + ikf = max( 1, ikf ) |
2399 | + ikg = max( 1, ikg ) |
2400 | + ikf = min( nkf-1, ikf ) |
2401 | + ikg = min( nkg-1, ikg ) |
2402 | + |
2403 | +end subroutine iofk |
2404 | + |
2405 | +! ----------------------------------------------------------------------------- |
2406 | + |
2407 | +subroutine kofn( n, gn, kf, kg, dkfdn, dkgdn, dkfdgn, dkgdgn ) |
2408 | + |
2409 | +! Finds Fermi and gradient wavevectors from density and gradient |
2410 | + |
2411 | + implicit none |
2412 | + real(dp), intent(in) :: n ! Electron density |
2413 | + real(dp), intent(in) :: gn(3) ! Density gradient |
2414 | + real(dp), intent(out):: kf ! Local Fermi wavevector |
2415 | + real(dp), intent(out):: kg ! |grad(n)|/n |
2416 | + real(dp), intent(out):: dkfdn ! dkf/dn |
2417 | + real(dp), intent(out):: dkgdn ! dkg/dn |
2418 | + real(dp), intent(out):: dkfdgn(3) ! dkf/dgn |
2419 | + real(dp), intent(out):: dkgdgn(3) ! dkg/dgn |
2420 | + |
2421 | + real(dp):: gn2, pi |
2422 | + |
2423 | +! Trap exception for zero density |
2424 | + if (n <= 1.e-30_dp) then |
2425 | + kf = 0 |
2426 | + kg = 0 |
2427 | + dkfdn = 0 |
2428 | + dkfdgn = 0 |
2429 | + dkgdn = 0 |
2430 | + dkgdgn = 0 |
2431 | + return |
2432 | + end if |
2433 | + |
2434 | +! Find kf and kg |
2435 | + pi = acos(-1._dp) |
2436 | + kf = (3*pi**2*n)**(1._dp/3) |
2437 | + gn2 = sum(gn**2) |
2438 | + kg = sqrt(gn2)/n |
2439 | + |
2440 | +! Find derivatives |
2441 | + dkfdn = kf/n/3 |
2442 | + dkfdgn = 0 |
2443 | + dkgdn = -kg/n |
2444 | + dkgdgn = kg*gn/gn2 |
2445 | + |
2446 | +end subroutine kofn |
2447 | + |
2448 | +!----------------------------------------------------------------------------- |
2449 | + |
2450 | +subroutine pofk( kf, kg, p, dpdkf, dpdkg ) |
2451 | + |
2452 | +! Finds the values and derivatives, at (kf,kg), of the bicubic polynomials |
2453 | +! p_i(kf,kg) such that |
2454 | +! y(kf,kg) = Sum_i p_i(kf,kg) * y_i |
2455 | +! is the bicubic spline interpolation at (kf,kg) of (any) function y with |
2456 | +! values y_i at mesh points (kfmesh,kgmesh)_i |
2457 | + |
2458 | + implicit none |
2459 | + real(dp),intent(in) :: kf, kg ! point at which the polynomials are required |
2460 | + real(dp),intent(out):: p(nkfg) ! polynomial values at (kf,kg) |
2461 | + real(dp),intent(out):: dpdkf(nkfg) ! dp/dkf at (kf,kg) |
2462 | + real(dp),intent(out):: dpdkg(nkfg) ! dp/dkg at (kf,kg) |
2463 | + |
2464 | + integer :: ikf, ikg, ikfg, ikf0, ikg0 |
2465 | + real(dp):: a, b, dk, dkf0dkf, dkg0dkg, kf0, kg0 |
2466 | + real(dp):: pkf0(nkf), dpkfdkf0(nkf), pkg0(nkg), dpkgdkg0(nkg) |
2467 | + logical, save :: first_call=.true. |
2468 | + real(dp),save :: pkf(nkf,nkf), d2pkfdkf2(nkf,nkf) |
2469 | + real(dp),save :: pkg(nkg,nkg), d2pkgdkg2(nkg,nkg) |
2470 | + |
2471 | +! Set up spline polynomial basis |
2472 | + if (first_call) then |
2473 | + do ikf = 1,nkf |
2474 | + pkf(:,ikf) = 0 ! ikf'th polynomial pkf(:,ikf) is one at kfmesh(ikf) |
2475 | + pkf(ikf,ikf) = 1 ! and zero at all other points |
2476 | + call spline( kfmesh, pkf(:,ikf), nkf, 1.e30_dp, 1.e30_dp, & |
2477 | + d2pkfdkf2(:,ikf) ) |
2478 | +! call spline( kfmesh, pkf(:,ikf), nkf, 0._dp, 0._dp, d2pkfdkf2(:,ikf) ) |
2479 | + end do |
2480 | + do ikg = 1,nkg |
2481 | + pkg(:,ikg) = 0 |
2482 | + pkg(ikg,ikg) = 1 |
2483 | + call spline( kgmesh, pkg(:,ikg), nkg, 1.e30_dp, 1.e30_dp, & |
2484 | + d2pkgdkg2(:,ikg) ) |
2485 | +! call spline( kgmesh, pkg(:,ikg), nkg, 0._dp, 0._dp, d2pkgdkg2(:,ikg) ) |
2486 | + end do |
2487 | + |
2488 | +! DEBUG |
2489 | + open(22,file='pkf.dat') |
2490 | + do ikf = 1,nkf |
2491 | + write(22,'(20e15.6)') kfmesh(ikf), pkf(:,ikf), d2pkfdkf2(:,ikf) |
2492 | + end do |
2493 | + close(22) |
2494 | + open(22,file='pkg.dat') |
2495 | + do ikg = 1,nkg |
2496 | + write(22,'(20e15.6)') kgmesh(ikg), pkg(:,ikg), d2pkgdkg2(:,ikg) |
2497 | + end do |
2498 | + close(22) |
2499 | +! END DEBUG |
2500 | + |
2501 | + first_call = .false. |
2502 | + end if |
2503 | + |
2504 | +! 'Saturate' (kf,kg) values to bring them to interpolation range |
2505 | + call saturate( kf, kfcut, kf0, dkf0dkf ) |
2506 | + call saturate( kg, kgcut, kg0, dkg0dkg ) |
2507 | + |
2508 | +! Find interval of k mesh in which (kf0,kg0) point is included |
2509 | + call iofk( kf0, kg0, ikf0, ikg0 ) |
2510 | + |
2511 | +! Evaluate pkf polynomials of spline basis at kf0 |
2512 | +! The splint code is in-lined here because it is a hot point |
2513 | + dk = kfmesh(ikf0+1) - kfmesh(ikf0) |
2514 | + a = (kfmesh(ikf0+1) - kf0) / dk ! dadkf0 = -1/dk |
2515 | + b = (kf0 - kfmesh(ikf0)) / dk ! dbdkf0 = +1/dk |
2516 | + do ikf = 1,nkf |
2517 | + pkf0(ikf) = a*pkf(ikf0,ikf) + b*pkf(ikf0+1,ikf) & |
2518 | + + ((a**3-a)*d2pkfdkf2(ikf0,ikf) + & |
2519 | + (b**3-b)*d2pkfdkf2(ikf0+1,ikf)) * dk**2/6 |
2520 | + dpkfdkf0(ikf) = - (pkf(ikf0,ikf) - pkf(ikf0+1,ikf)) / dk & |
2521 | + - ((3*a**2-1)*d2pkfdkf2(ikf0,ikf) - & |
2522 | + (3*b**2-1)*d2pkfdkf2(ikf0+1,ikf)) * dk/6 |
2523 | + end do |
2524 | + |
2525 | +! Evaluate pkg polynomials of spline basis at kg0 |
2526 | + dk = kgmesh(ikg0+1) - kgmesh(ikg0) |
2527 | + a = (kgmesh(ikg0+1) - kg0) / dk ! dadkg0 = -1/dk |
2528 | + b = (kg0 - kgmesh(ikg0)) / dk ! dbdkg0 = +1/dk |
2529 | + do ikg = 1,nkg |
2530 | + pkg0(ikg) = a*pkg(ikg0,ikg) + b*pkg(ikg0+1,ikg) & |
2531 | + + ((a**3-a)*d2pkgdkg2(ikg0,ikg) + & |
2532 | + (b**3-b)*d2pkgdkg2(ikg0+1,ikg)) * dk**2/6 |
2533 | + dpkgdkg0(ikg) = - (pkg(ikg0,ikg) - pkg(ikg0+1,ikg)) / dk & |
2534 | + - ((3*a**2-1)*d2pkgdkg2(ikg0,ikg) - & |
2535 | + (3*b**2-1)*d2pkgdkg2(ikg0+1,ikg)) * dk/6 |
2536 | + end do |
2537 | + |
2538 | +! Evaluate pkf*pkg polynomials at (kf0,kg0) |
2539 | + ikfg = 0 |
2540 | + do ikg = 1,nkg |
2541 | + do ikf = 1,nkf |
2542 | + ikfg = ikfg+1 |
2543 | + p(ikfg) = pkf0(ikf) * pkg0(ikg) |
2544 | + dpdkf(ikfg) = dpkfdkf0(ikf)*dkf0dkf * pkg0(ikg) |
2545 | + dpdkg(ikfg) = pkf0(ikf) * dpkgdkg0(ikg)*dkg0dkg |
2546 | + end do |
2547 | + end do |
2548 | + |
2549 | +end subroutine pofk |
2550 | + |
2551 | +!----------------------------------------------------------------------------- |
2552 | + |
2553 | +subroutine saturate( x, xc, y, dydx ) |
2554 | + |
2555 | + ! Defines a function y(x,xc) = 1/(1/x^nsat+1/xc^nsat)^(1/nsat), where nsat |
2556 | + ! is an integer set in the module header. This function is approximately |
2557 | + ! equal to x for x<xc and it saturates to xc when x->infinity |
2558 | + |
2559 | + implicit none |
2560 | + real(dp),intent(in) :: x ! Independent variable |
2561 | + real(dp),intent(in) :: xc ! Saturation value |
2562 | + real(dp),intent(out):: y ! Function value |
2563 | + real(dp),intent(out):: dydx ! Derivative dy/dx |
2564 | + |
2565 | + real(dp):: z |
2566 | + |
2567 | + if (xc<=0._dp) then |
2568 | + call die('pbesvvs_vdwxc_saturate ERROR: xc<=0') |
2569 | + else if (x<0._dp) then |
2570 | + call die('pbesvvs_vdwxc_saturate ERROR: x<0') |
2571 | + else if (x==0._dp) then |
2572 | + y = 0 |
2573 | + dydx = 1 |
2574 | + else |
2575 | + z = 1/x**nsat + 1/xc**nsat |
2576 | + y = 1/z**(1._dp/nsat) |
2577 | + dydx = y/z/x**(nsat+1) |
2578 | + end if |
2579 | + |
2580 | +end subroutine saturate |
2581 | + |
2582 | +!----------------------------------------------------------------------------- |
2583 | + |
2584 | +subroutine saturate_inverse( y, xc, x, dxdy ) |
2585 | + |
2586 | +! Finds the inverse of the function defined in saturate subroutine: |
2587 | +! y=1/(1/x^n+1/xc^n)^(1/n) => x=1/(1/y^n-1/xc^n)^(1/n) |
2588 | + |
2589 | + implicit none |
2590 | + real(dp),intent(in) :: y ! Independent variable |
2591 | + real(dp),intent(in) :: xc ! Saturation value |
2592 | + real(dp),intent(out):: x ! Inverse function value |
2593 | + real(dp),intent(out):: dxdy ! Derivative dx/dy |
2594 | + |
2595 | + real(dp):: z |
2596 | + |
2597 | + if (xc<=0._dp) then |
2598 | + call die('pbesvvs_vdwxc_saturate_inverse ERROR: xc<=0') |
2599 | + else if (y<0._dp .or. y>=xc) then |
2600 | + call die('pbesvvs_vdwxc_saturate_inverse ERROR: y out of range') |
2601 | + else if (y==0._dp) then |
2602 | + x = 0 |
2603 | + dxdy = 1 |
2604 | + else |
2605 | + z = 1/y**nsat - 1/xc**nsat |
2606 | + x = 1/z**(1._dp/nsat) |
2607 | + dxdy = x/z/y**(nsat+1) |
2608 | + end if |
2609 | + |
2610 | +end subroutine saturate_inverse |
2611 | + |
2612 | +!----------------------------------------------------------------------------- |
2613 | + |
2614 | +subroutine set_kmesh() |
2615 | + |
2616 | +! Sets mesh of q values |
2617 | + |
2618 | + implicit none |
2619 | + integer :: mkf, mkg |
2620 | + |
2621 | + if (.not.kmesh_set) then |
2622 | + call set_mesh( nkf, xmax=kfcut, dxndx1=dkfmaxdkfmin ) |
2623 | + call get_mesh( nkf, mkf, kfmesh ) |
2624 | + call set_mesh( nkg, xmax=kgcut, dxndx1=dkgmaxdkgmin ) |
2625 | + call get_mesh( nkg, mkg, kgmesh ) |
2626 | + kmesh_set = .true. |
2627 | +#ifdef DEBUG_XC |
2628 | + write(udebug,'(/,a,/,(10f8.4))') 'pbesvvs_vdw_set_kmesh: kfmesh =', kfmesh |
2629 | + write(udebug,'(/,a,/,(10f8.4))') 'pbesvvs_vdw_set_kmesh: kgmesh =', kgmesh |
2630 | +#endif /* DEBUG_XC */ |
2631 | + end if |
2632 | + |
2633 | +end subroutine set_kmesh |
2634 | + |
2635 | +! ----------------------------------------------------------------------------- |
2636 | + |
2637 | +subroutine set_phi_table() |
2638 | + |
2639 | +! Finds and stores in memory the interpolation table (mesh points and |
2640 | +! function values) for the kernel phi(k1,k2,k). |
2641 | + |
2642 | + implicit none |
2643 | + character(len=*),parameter:: myName = 'pbesvvs_vdwxc/set_phi_table ' |
2644 | + integer :: ik, ikf1, ikf2, ikg1, ikg2, ik1, ik2, ir |
2645 | + real(dp):: dkdk0, dphidk0, dphidkmax, dphidr0, dphidrmax, & |
2646 | + k, kf1, kf2, kg1, kg2, pi, r(0:nr) |
2647 | + |
2648 | +! Check that table was not set yet |
2649 | + if (phi_table_set) return |
2650 | + |
2651 | +! Check that kf, kg, r, and k meshes have been set |
2652 | + if (.not.kmesh_set) call set_kmesh() |
2653 | + if (.not.kcut_set) call die('pbesvvs_vdw_set_phi_table ERROR: kcut not set') |
2654 | + forall(ir=0:nr) r(ir) = ir*dr |
2655 | + pi = acos(-1.0_dp) |
2656 | + |
2657 | +! Allocate arrays |
2658 | + call re_alloc( phir, 0,nr, 1,nkfg, 1,nkfg, myName//'phir' ) |
2659 | + call re_alloc( phik, 0,nr, 1,nkfg, 1,nkfg, myName//'phik' ) |
2660 | + call re_alloc( d2phidr2, 0,nr, 1,nkfg, 1,nkfg, myName//'d2phidr2' ) |
2661 | + call re_alloc( d2phidk2, 0,nr, 1,nkfg, 1,nkfg, myName//'d2phidk2' ) |
2662 | + |
2663 | +! Loop on (k1,k2) mesh points |
2664 | + do ikg2 = 1,nkg ! loop on kg2 |
2665 | + do ikf2 = 1,nkf ! loop on kf2 |
2666 | + ik2 = ikf2 + nkf*(ikg2-1) ! combined (ikf2,ikg2) index |
2667 | + do ikg1 = 1,nkg ! loop on kg1 |
2668 | + do ikf1 = 1,nkf ! loop on kf1 |
2669 | + ik1 = ikf1 + nkf*(ikg1-1) ! combined (ikf1,ikg1) index |
2670 | + if (ik1>ik2) cycle ! since we will symmetrize at the end |
2671 | + |
2672 | + ! Saturated (kf,kg) values |
2673 | + kf1 = kfmesh(ikf1) |
2674 | + kf2 = kfmesh(ikf2) |
2675 | + kg1 = kgmesh(ikg1) |
2676 | + kg2 = kgmesh(ikg2) |
2677 | + |
2678 | + ! Find original (unsaturated) kf anf kg values |
2679 | + ! call saturate_inverse( kfmesh(ikf1), kfcut, kf1, dkdk0 ) |
2680 | + ! call saturate_inverse( kfmesh(ikf2), kfcut, kf2, dkdk0 ) |
2681 | + ! call saturate_inverse( kgmesh(ikg1), kgcut, kg1, dkdk0 ) |
2682 | + ! call saturate_inverse( kgmesh(ikg2), kgcut, kg2, dkdk0 ) |
2683 | + |
2684 | + ! Find kernel as a function of r12 |
2685 | + do ir = 0,nr |
2686 | + phir(ir,ik1,ik2) = pbesvvs_vdw_phi_val( kf1, kf2, kg1, kg2, r(ir) ) |
2687 | + end do |
2688 | + |
2689 | + ! Kill kernel smoothly at r=rcut |
2690 | + do ir = 0,nr |
2691 | + phir(ir,ik1,ik2) = phir(ir,ik1,ik2) * cutoff( r(ir)/rcut ) |
2692 | + end do |
2693 | + |
2694 | + ! Find kernel in reciprocal space |
2695 | + call radfft( 0, nr, rcut, phir(:,ik1,ik2), phik(:,ik1,ik2) ) |
2696 | + phik(:,ik1,ik2) = phik(:,ik1,ik2) * (2*pi)**1.5_dp |
2697 | + |
2698 | + ! Filter out above kcut |
2699 | + phik(nk:nr,ik1,ik2) = 0 |
2700 | + |
2701 | + ! Soft filter below kcut |
2702 | + do ik = 1,nk |
2703 | + k = ik * dk |
2704 | + phik(ik,ik1,ik2) = phik(ik,ik1,ik2) * cutoff(k/kcut) |
2705 | + end do |
2706 | + |
2707 | + ! Find filtered kernel in real space |
2708 | + call radfft( 0, nr, kmax, phik(:,ik1,ik2), phir(:,ik1,ik2) ) |
2709 | + phir(:,ik1,ik2) = phir(:,ik1,ik2) / (2*pi)**1.5_dp |
2710 | + |
2711 | + ! Set up spline interpolation tables |
2712 | + dphidr0 = 0 ! since phi(k1,k2,r) is even in r |
2713 | + dphidk0 = 0 ! and therefore phi(k1,k2,k) is also even in k |
2714 | + dphidrmax = 0 ! since phi->0 for r->infty |
2715 | + dphidkmax = 0 ! and also when k->infty |
2716 | + call spline( dr, phir(:,ik1,ik2), nr+1, dphidr0, dphidrmax, & |
2717 | + d2phidr2(:,ik1,ik2) ) |
2718 | + call spline( dk, phik(:,ik1,ik2), nk+1, dphidk0, dphidkmax, & |
2719 | + d2phidk2(:,ik1,ik2) ) |
2720 | + |
2721 | + ! Fill symmetric elements |
2722 | + phir(:,ik2,ik1) = phir(:,ik1,ik2) |
2723 | + phik(:,ik2,ik1) = phik(:,ik1,ik2) |
2724 | + d2phidr2(:,ik2,ik1) = d2phidr2(:,ik1,ik2) |
2725 | + d2phidk2(:,ik2,ik1) = d2phidk2(:,ik1,ik2) |
2726 | + |
2727 | +!#ifdef DEBUG_XC |
2728 | +! if (.false. .and. ik1==ik2) then |
2729 | +! print*, 'pbesvvs_vdw_set_kcut: ik1,ik2=', ik1, ik2 |
2730 | +! call window( 0._dp, 5._dp, -1._dp, 4._dp, 0 ) |
2731 | +! call axes( 0._dp, 1._dp, 0._dp, 1._dp ) |
2732 | +! call plot( nr+1, r, phi, phir(:,ik1,ik2) ) |
2733 | +! call window( 0._dp, 10._dp, -0.05_dp, 0.15_dp, 0 ) |
2734 | +! call axes( 0._dp, 1._dp, 0._dp, 0.05_dp ) |
2735 | +! call plot( nr+1, r, r**2*phi, r**2*phir(:,ik1,ik2)) |
2736 | +! call show() |
2737 | +! end if |
2738 | +!#endif /* DEBUG_XC */ |
2739 | + |
2740 | + end do ! ikf1 |
2741 | + end do ! ikg1 |
2742 | + end do ! ikf2 |
2743 | + end do ! ikg2 |
2744 | + |
2745 | +!#ifdef DEBUG_XC |
2746 | +! open(17,file='vv_phi.table') |
2747 | +! write(17,'(3a6,2a12,/,(3i6,2f15.9))') & |
2748 | +! 'ik1', 'ik2', 'ir', 'phi', 'd2phi/dk2', & |
2749 | +!! (((ik1,ik2,ir,phir(ir,ik1,ik2),d2phidr2(ir,ik1,ik2), & |
2750 | +! (((ik1,ik2,ir,phik(ir,ik1,ik2),d2phidk2(ir,ik1,ik2), & |
2751 | +! ir=0,100),ik2=1,nkfg),ik1=1,nkfg) |
2752 | +! close(17) |
2753 | +!#endif /* DEBUG_XC */ |
2754 | + |
2755 | +! Mark table as set |
2756 | + phi_table_set = .true. |
2757 | + |
2758 | +end subroutine set_phi_table |
2759 | + |
2760 | +! ----------------------------------------------------------------------------- |
2761 | + |
2762 | +real(dp) function pbesvvs_vdw_phi_val( kf1, kf2, kg1, kg2, r12 ) |
2763 | + |
2764 | +! vdW energy kernel of Vydrov-vanVoorhis, eq.(2) of JCP 133, 244103 (2010) |
2765 | +! This subroutine calculates the 'raw' kernel directly, without interpolarions |
2766 | +! In practice, it returns n1*n2*phi(k1,k2,r12), which is smooth for kf->0 |
2767 | +! Input: |
2768 | +! real(dp):: kf1, kf2 ! Fermi wavevectors at points 1 and 2 |
2769 | +! real(dp):: kg1, kg2 ! |grad(n)|/n at points 1 and 2 |
2770 | +! real(dp):: r12 ! distance between points 1 and 2 |
2771 | + |
2772 | +! Arguments |
2773 | + implicit none |
2774 | + real(dp),intent(in) :: kf1, kf2, kg1, kg2, r12 |
2775 | + |
2776 | +! Internal variables |
2777 | + real(dp):: g1, g2, kappa1, kappa2, kf1m, kf2m, n1, n2, & |
2778 | + phi, pi, w01, w02, wg1, wg2, wp1, wp2, & |
2779 | + ss1, ss2, vv_C1, vv_C2, vv_Ct1, vv_Ct2 |
2780 | + |
2781 | +!! New parameters of the PBEsol+rVV10s, |
2782 | +!! Ref. A.V. Terentjev et al, Phys. Rev. B 98, 214108 (2018) |
2783 | + vv_C1 = 0.5_dp |
2784 | + vv_C2 = 300.0_dp |
2785 | + |
2786 | +! Avoid dividing by zero when kf=0 |
2787 | + kf1m = max(kf1,ktol) |
2788 | + kf2m = max(kf2,ktol) |
2789 | + |
2790 | +! Find kernel |
2791 | + pi = acos(-1.0_dp) |
2792 | + n1 = kf1m**3/(3*pi**2) ! electron density at point 1 |
2793 | + n2 = kf2m**3/(3*pi**2) ! electron density at point 2 |
2794 | +!! New formulas of the PBEsol+rVV10s, |
2795 | +!! Ref. A.V. Terentjev et al, Phys. Rev. B 98, 214108 (2018) |
2796 | + ss1 = 0.1616204568582_dp*kg1/(n1**(1/3)) |
2797 | + ss2 = 0.1616204568582_dp*kg2/(n2**(1/3)) |
2798 | + vv_Ct1 = vv_C+vv_C1/(1.0_dp + vv_C2*(ss1-0.5_dp)**2) |
2799 | + vv_Ct2 = vv_C+vv_C1/(1.0_dp + vv_C2*(ss2-0.5_dp)**2) |
2800 | +!! |
2801 | + wp1 = sqrt(4*pi*n1) ! local plasma frequency at point 1 |
2802 | + wp2 = sqrt(4*pi*n2) ! local plasma frequency at point 2 |
2803 | +!! |
2804 | + wg1 = sqrt(vv_Ct1*kg1**4) ! local band gap at point 1 |
2805 | + wg2 = sqrt(vv_Ct2*kg2**4) ! local band gap at point 2 |
2806 | +!! |
2807 | + kappa1 = vv_b*kf1m**2/wp1 ! local VV kappa variable (eq.(9)) at point 1 |
2808 | + kappa2 = vv_b*kf2m**2/wp2 ! kappa variable at point 2 |
2809 | + w01 = sqrt(wg1**2+wp1**2/3) ! local w0 frequency (eq.(5)) at point 1 |
2810 | + w02 = sqrt(wg2**2+wp2**2/3) ! local w0 frequency at point 2 |
2811 | + g1 = w01*r12**2 + kappa1 ! local g variable (eq.(3)) at point 1 |
2812 | + g2 = w02*r12**2 + kappa2 ! local g variable at point 2 |
2813 | + phi = -1.5_dp/g1/g2/(g1+g2) ! VV kernel phi (eq.(2)) |
2814 | + |
2815 | + if (kernelPrefactor=='rho') then |
2816 | + ! Return whole integrand of eq.(1) |
2817 | + pbesvvs_vdw_phi_val = n1*n2*phi |
2818 | + else if (kernelPrefactor=='kf') then |
2819 | + ! Return kf1*kf2*phi |
2820 | + pbesvvs_vdw_phi_val = kf1*kf2*phi |
2821 | + else if (kernelPrefactor=='kf2') then |
2822 | + ! Return (kf1*kf2)**2*phi |
2823 | + pbesvvs_vdw_phi_val = (kf1*kf2)**2*phi |
2824 | + else if (kernelPrefactor=='sqr_rho') then |
2825 | + ! Find and return sqrt(n1*n2)*phi |
2826 | + pbesvvs_vdw_phi_val = sqrt(n1*n2)*phi |
2827 | + else |
2828 | + call die('pbesvvs_vdw_phi_val ERROR: unknown kernelPrefactor') |
2829 | + end if |
2830 | + |
2831 | +end function pbesvvs_vdw_phi_val |
2832 | + |
2833 | +! ----------------------------------------------------------------------------- |
2834 | + |
2835 | +real(dp) function pbesvvs_vdw_beta() |
2836 | + |
2837 | +! Returns parameter beta of VV functional |
2838 | + |
2839 | + implicit none |
2840 | + pbesvvs_vdw_beta = vv_beta |
2841 | + |
2842 | +end function pbesvvs_vdw_beta |
2843 | + |
2844 | +!----------------------------------------------------------------------------- |
2845 | + |
2846 | +subroutine pbesvvs_vdw_get_kmesh( mkf, mkg, kf, kg ) |
2847 | + |
2848 | +! Returns size and values of (kf,kg) mesh |
2849 | + |
2850 | + implicit none |
2851 | + integer, intent(out) :: mkf ! Number of kf mesh points |
2852 | + integer, intent(out) :: mkg ! Number of kg mesh points |
2853 | + real(dp),optional,intent(out) :: kf(:) ! Values of kf mesh points |
2854 | + real(dp),optional,intent(out) :: kg(:) ! Values of kg mesh points |
2855 | + integer:: nmax |
2856 | + if (.not.kmesh_set) call set_kmesh() |
2857 | + mkf = nkf |
2858 | + mkg = nkg |
2859 | + if (present(kf)) then |
2860 | + nmax = max( nkf, size(kf) ) |
2861 | + kf(1:nmax) = kfmesh(1:nmax) |
2862 | + end if |
2863 | + if (present(kg)) then |
2864 | + nmax = max( nkg, size(kg) ) |
2865 | + kg(1:nmax) = kgmesh(1:nmax) |
2866 | + end if |
2867 | +end subroutine pbesvvs_vdw_get_kmesh |
2868 | + |
2869 | +! ----------------------------------------------------------------------------- |
2870 | + |
2871 | +subroutine pbesvvs_vdw_phi( k, phi, dphidk ) |
2872 | + |
2873 | +! Finds by interpolation phi(k1,k2,k) (Fourier transform of phi(k1,k2,r)), |
2874 | +! with k1=(kf1,kg1), k2=(kf2,kg2) for all mesh values of kf (Fermi |
2875 | +! wavevector) and kg (grad(n)/n). If the interpolation table does not exist, |
2876 | +! it is calculated in the first call to pbesvvs_vdw_phi. It requires a previous |
2877 | +! call to pbesvvs_vdw_set_kc to set k mesh. |
2878 | + |
2879 | + implicit none |
2880 | + real(dp),intent(in) :: k ! Modulus of actual k vector |
2881 | + real(dp),intent(out):: phi(:,:) ! phi(k1,k2,k) at given k |
2882 | + ! for all k1,k2 in (kf,kg) mesh |
2883 | + real(dp),intent(out):: dphidk(:,:) ! dphi(k1,k2,k)/dk at given k |
2884 | + |
2885 | + integer :: ik, ik1, ik2 |
2886 | + real(dp):: a, a2, a3, b, b2, b3 |
2887 | + |
2888 | +! Set interpolation table |
2889 | + if (.not.phi_table_set) call set_phi_table() |
2890 | + |
2891 | +! Check argument sizes |
2892 | + if (size(phi,1)<nkfg .or. size(phi,2)<nkfg) & |
2893 | + call die('pbesvvs_vdw_phi: ERROR: size(phi) too small') |
2894 | + |
2895 | +! Find phi values at point k |
2896 | + if (k >= kcut) then |
2897 | + phi(:,:) = 0 |
2898 | + dphidk(:,:) = 0 |
2899 | + else |
2900 | + ! Expand interpolation inline since this is the hottest point in VdW |
2901 | + ik = int(k/dk) |
2902 | + a = ((ik+1)*dk-k)/dk |
2903 | + b = 1 - a |
2904 | + a2 = (3*a**2 -1) * dk / 6 |
2905 | + b2 = (3*b**2 -1) * dk / 6 |
2906 | + a3 = (a**3 - a) * dk**2 / 6 |
2907 | + b3 = (b**3 - b) * dk**2 / 6 |
2908 | + do ik2 = 1,nkfg |
2909 | + do ik1 = 1,ik2 |
2910 | +! call splint( dk, phik(:,ik1,ik2), d2phidk2(:,ik1,ik2), & |
2911 | +! nk+1, k, phi(ik1,ik2), dphidk(ik1,ik2), pr ) |
2912 | + phi(ik1,ik2) = a*phik(ik,ik1,ik2) + b*phik(ik+1,ik1,ik2) & |
2913 | + + a3*d2phidk2(ik,ik1,ik2) + b3*d2phidk2(ik+1,ik1,ik2) |
2914 | + dphidk(ik1,ik2) = (-phik(ik,ik1,ik2) & |
2915 | + +phik(ik+1,ik1,ik2) )/dk & |
2916 | + - a2*d2phidk2(ik,ik1,ik2) + b2*d2phidk2(ik+1,ik1,ik2) |
2917 | + phi(ik2,ik1) = phi(ik1,ik2) |
2918 | + dphidk(ik2,ik1) = dphidk(ik1,ik2) |
2919 | + end do |
2920 | + end do |
2921 | + end if |
2922 | + |
2923 | +end subroutine pbesvvs_vdw_phi |
2924 | + |
2925 | +!----------------------------------------------------------------------------- |
2926 | + |
2927 | +subroutine pbesvvs_vdw_phiofr( r, phi ) |
2928 | + |
2929 | +! Finds phi(k1,k2,r) with k1=(kf1,kg1), k2=(kf2,kg2) for mesh values of |
2930 | +! kf's (Fermi wavevectors) and kg's (grad(n)/n) |
2931 | + |
2932 | + implicit none |
2933 | + real(dp),intent(in) :: r |
2934 | + real(dp),intent(out):: phi(:,:) |
2935 | + |
2936 | + integer :: ikf1, ikf2, ikg1, ikg2, ik1, ik2 |
2937 | + real(dp):: dphidr |
2938 | + |
2939 | + if (size(phi,1)<nkfg .or. size(phi,2)<nkfg) & |
2940 | + stop 'vv_phiofr: ERROR: size(phi) too small' |
2941 | + if (.not.phi_table_set) call set_phi_table() |
2942 | + |
2943 | + if (r >= rcut) then |
2944 | + phi(:,:) = 0 |
2945 | + else |
2946 | + do ik2 = 1,nkfg |
2947 | + do ik1 = 1,ik2 |
2948 | + call splint( dr, phir(:,ik1,ik2), d2phidr2(:,ik1,ik2), & |
2949 | + nr+1, r, phi(ik1,ik2), dphidr ) |
2950 | + phi(ik2,ik1) = phi(ik1,ik2) |
2951 | + end do ! ik1 |
2952 | + end do ! ik2 |
2953 | + end if ! (r>=rcut) |
2954 | + |
2955 | +end subroutine pbesvvs_vdw_phiofr |
2956 | + |
2957 | +!----------------------------------------------------------------------------- |
2958 | + |
2959 | +subroutine pbesvvs_vdw_set_kcut( kc ) |
2960 | + |
2961 | +! Sets the reciprocal planewave cutoff kc of the integration grid, and finds |
2962 | +! the interpolation table to be used by vdw_phi to obtain the vdW kernel phi |
2963 | +! at the reciprocal mesh wavevectors. |
2964 | + |
2965 | + implicit none |
2966 | + real(dp),intent(in):: kc ! Planewave cutoff: k>kcut => phi=0 |
2967 | + |
2968 | + real(dp):: pi |
2969 | + |
2970 | + ! Set kcut and radial mesh parameters, if not already set |
2971 | + if (.not. kc==kcut) then |
2972 | + kcut = kc |
2973 | + pi = acos(-1._dp) |
2974 | + dr = rcut / nr |
2975 | + dk = pi / rcut |
2976 | + kmax = pi / dr |
2977 | + nk = int(kcut/dk) + 1 |
2978 | + if (nk>nr) stop 'pbesvvs_vdw_set_kcut: ERROR: nk>nr' |
2979 | + kcut_set = .true. |
2980 | +#ifdef DEBUG_XC |
2981 | + write(udebug,'(a,5f8.3)') 'pbesvvs_vdw_set_kcut: kfcut,kgcut,rcut,kcut,kmax=', & |
2982 | + kfcut, kgcut, rcut, kc, kmax |
2983 | +#endif /* DEBUG_XC */ |
2984 | + end if |
2985 | + |
2986 | + ! Set (kf,kg) mesh and phi table |
2987 | + call set_kmesh() |
2988 | + call set_phi_table() |
2989 | + |
2990 | +end subroutine pbesvvs_vdw_set_kcut |
2991 | + |
2992 | +!----------------------------------------------------------------------------- |
2993 | + |
2994 | +subroutine pbesvvs_vdw_theta( nspin, rhos, grhos, theta, dtdrho, dtdgrho ) |
2995 | + |
2996 | +! Finds the value and derivatives of theta_i(rho,grad_rho) of eq.(8) |
2997 | +! of Roman-Soler PRL 2009. In practice, theta_i=p_i rather than rho*p_i, |
2998 | +! beacuse p_i is used here to expand rho1*rho2*phi rather than only phi. |
2999 | + |
3000 | + implicit none |
3001 | + integer, intent(in) :: nspin ! Number of spin components |
3002 | + real(dp),intent(in) :: rhos(nspin) ! Electron spin density |
3003 | + real(dp),intent(in) :: grhos(3,nspin) ! Spin density gradient |
3004 | + real(dp),intent(out):: theta(nkfg) ! Exp. polynomials at (kf,kg) |
3005 | + real(dp),intent(out):: dtdrho(nkfg,nspin) ! dtheta(ik)/drhos |
3006 | + real(dp),intent(out):: dtdgrho(3,nkfg,nspin) ! dtheta(ik)/dgrhos(ix) |
3007 | + |
3008 | + integer :: is, ix, ns |
3009 | + real(dp):: rho, grho(3), dpdkf(nkfg), dpdkg(nkfg), dkfdrho, dkfdgrho(3), & |
3010 | + dkgdrho, dkgdgrho(3), kf, kg, p(nkfg) |
3011 | + |
3012 | + ! Sum spin components of electron density |
3013 | + ns = min(nspin,2) ! num. of diagonal spin components (if noncollinear) |
3014 | + rho = sum(rhos(1:ns)) ! local electron density |
3015 | + grho = sum(grhos(:,1:ns),dim=2) ! local density gradient |
3016 | + |
3017 | + ! If density is between threshold, return zero |
3018 | + if (rho<rhoMin) then |
3019 | + theta = 0 |
3020 | + dtdrho = 0 |
3021 | + dtdgrho = 0 |
3022 | + return |
3023 | + end if |
3024 | + |
3025 | + ! Find local Fermi and gradient wavevectors, and their derivatives |
3026 | + call kofn( rho, grho, kf, kg, dkfdrho, dkgdrho, dkfdgrho, dkgdgrho ) |
3027 | + |
3028 | + ! Find expansion polynomials of integrand kernel of nonlocal vdW energy |
3029 | + call pofk( kf, kg, p, dpdkf, dpdkg ) |
3030 | + |
3031 | + ! Find theta functions and their derivatives with respect to rho and grho |
3032 | + if (kernelPrefactor=='rho') then |
3033 | + ! This is the right code if pbesvvs_vdw_phi_val returns rho1*rho2*phi |
3034 | + theta(1:nkfg) = p(1:nkfg) |
3035 | + do is = 1,ns |
3036 | + dtdrho(1:nkfg,is) = dpdkf(1:nkfg)*dkfdrho + dpdkg(1:nkfg)*dkgdrho |
3037 | + do ix = 1,3 |
3038 | + dtdgrho(ix,1:nkfg,is) = dpdkf(1:nkfg)*dkfdgrho(ix) & |
3039 | + + dpdkg(1:nkfg)*dkgdgrho(ix) |
3040 | + end do |
3041 | + end do |
3042 | + else if (kernelPrefactor=='kf') then |
3043 | + ! This is the right code if pbesvvs_vdw_phi_val returns kf1*kf2*phi |
3044 | + kf = max(kf,ktol) |
3045 | + theta(1:nkfg) = p(1:nkfg)*rho/kf |
3046 | + do is = 1,ns |
3047 | + dtdrho(1:nkfg,is) = (dpdkf(1:nkfg)*dkfdrho & |
3048 | + +dpdkg(1:nkfg)*dkgdrho)*rho/kf & |
3049 | + + p(1:nkfg)*(1/kf-rho/kf**2*dkfdrho) |
3050 | + do ix = 1,3 |
3051 | + dtdgrho(ix,1:nkfg,is) = (dpdkf(1:nkfg)*dkfdgrho(ix) & |
3052 | + +dpdkg(1:nkfg)*dkgdgrho(ix))*rho/kf |
3053 | + end do |
3054 | + end do |
3055 | + else if (kernelPrefactor=='kf2') then |
3056 | + ! This is the right code if pbesvvs_vdw_phi_val returns (kf1*kf2)**2*phi |
3057 | + kf = max(kf,ktol) |
3058 | + theta(1:nkfg) = p(1:nkfg)*rho/kf**2 |
3059 | + do is = 1,ns |
3060 | + dtdrho(1:nkfg,is) = (dpdkf(1:nkfg)*dkfdrho & |
3061 | + +dpdkg(1:nkfg)*dkgdrho)*rho/kf**2 & |
3062 | + + p(1:nkfg)*(1/kf**2-2*rho/kf**3*dkfdrho) |
3063 | + do ix = 1,3 |
3064 | + dtdgrho(ix,1:nkfg,is) = (dpdkf(1:nkfg)*dkfdgrho(ix) & |
3065 | + +dpdkg(1:nkfg)*dkgdgrho(ix))*rho/kf**2 |
3066 | + end do |
3067 | + end do |
3068 | + else if (kernelPrefactor=='sqr_rho') then |
3069 | + ! This is the right code if pbesvvs_vdw_phi_val returns sqrt(rho1*rho2)*phi |
3070 | + rho = max(rho,1.e-12_dp) ! to avoid division by zero |
3071 | + theta(1:nkfg) = p(1:nkfg) * sqrt(rho) |
3072 | + do is = 1,ns |
3073 | + dtdrho(1:nkfg,is) = ( dpdkf(1:nkfg)*dkfdrho & |
3074 | + + dpdkg(1:nkfg)*dkgdrho ) * sqrt(rho) & |
3075 | + + p(1:nkfg) * 0.5/sqrt(rho) |
3076 | + do ix = 1,3 |
3077 | + dtdgrho(ix,1:nkfg,is) = dpdkf(1:nkfg)*dkfdgrho(ix) * sqrt(rho) & |
3078 | + + dpdkg(1:nkfg)*dkgdgrho(ix) * sqrt(rho) |
3079 | + end do |
3080 | + end do |
3081 | + else |
3082 | + call die('pbesvvs_vdw_theta ERROR: unknown kernelPrefactor') |
3083 | + end if ! (kernelPrefactor=='rho') |
3084 | + |
3085 | +end subroutine pbesvvs_vdw_theta |
3086 | + |
3087 | +END MODULE m_pbesvvs_vdwxc |
3088 | + |
3089 | + |
3090 | |
3091 | === modified file 'Src/atom.F' |
3092 | --- Src/atom.F 2019-06-20 10:59:42 +0000 |
3093 | +++ Src/atom.F 2019-09-06 14:47:07 +0000 |
3094 | @@ -2038,6 +2038,8 @@ |
3095 | if (icorr .eq. "wc") ps_string ="GGA WC" |
3096 | if (icorr .eq. "bl") ps_string ="GGA BLYP" |
3097 | if (icorr .eq. "ps") ps_string ="GGA PBEsol" |
3098 | +! |
3099 | + if (icorr .eq. "sg") ps_string ="GGA SG4" |
3100 | |
3101 | if (icorr .eq. "jo") ps_string ="GGA PBEJsJrLO" |
3102 | if (icorr .eq. "jh") ps_string ="GGA PBEJsJrHEG" |
3103 | @@ -2131,8 +2133,17 @@ |
3104 | . write(6,'(a,1x,2a)') |
3105 | . 'xc_check: WARNING: Pseudopotential generated with', |
3106 | . trim(ps_string), " functional" |
3107 | - |
3108 | - |
3109 | +! |
3110 | + elseif((XCauth(nf).eq.'SG4').and.(XCfunc(nf).eq.'GGA')) |
3111 | + . then |
3112 | + |
3113 | + write(6,'(a)') |
3114 | + . 'xc_check: GGA SG4' |
3115 | + if (icorr.ne.'sg'.and.nXCfunc.eq.1) |
3116 | + . write(6,'(a,1x,2a)') |
3117 | + . 'xc_check: WARNING: Pseudopotential generated with', |
3118 | + . trim(ps_string), " functional" |
3119 | + |
3120 | elseif((XCauth(nf).eq.'PW91').and.(XCfunc(nf).eq.'GGA')) then |
3121 | |
3122 | write(6,'(a)') |
3123 | |
3124 | === modified file 'Tests/Makefile' |
3125 | --- Tests/Makefile 2019-01-30 15:22:16 +0000 |
3126 | +++ Tests/Makefile 2019-09-06 14:47:07 +0000 |
3127 | @@ -42,13 +42,14 @@ |
3128 | |
3129 | label = work |
3130 | |
3131 | -tests = 32_h2o ag anneal-cont ar2_vdw batio3 benzene bessel bessel-rich \ |
3132 | +tests = 32_h2o ag ag_sg4 anneal-cont ar2_vdw batio3 benzene bessel bessel-rich \ |
3133 | born born_spin carbon_nanoscroll ch4 chargeconf-h2o \ |
3134 | constant_volume dipole_correction fe fe_broyden \ |
3135 | fe_clust_noncollinear fe_clust_noncollinear-gga fe_cohp \ |
3136 | fen fe_noncol_kp fire_benzene floating \ |
3137 | force_2 force_constants gate_G_charge gate_G_hartree ge111 \ |
3138 | - ge_fatbands_so graphite_c6 graphite_c6_full graphite_vdw_df \ |
3139 | + ge_fatbands_so graphite_c6 graphite_c6_full graphite_c6_sg4 graphite_vdw_df \ |
3140 | + graphite_vdw_pbesvvs graphite_vdw_pbevv graphite_vdw_sg4vv \ |
3141 | h2_bessel h2o h2o_2 h2o_am05 h2o_bands h2o_bands_nc \ |
3142 | h2o_bands_polarized h2o_basis h2o_coop h2o_dipole h2o_dipole2 \ |
3143 | h2o_dos h2o_filteret_basis h2o_findp_bug h2o_netcdf h2o_op_broyden \ |
3144 | |
3145 | === modified file 'version.info' |
3146 | --- version.info 2019-09-04 13:09:45 +0000 |
3147 | +++ version.info 2019-09-06 14:47:07 +0000 |
3148 | @@ -1,1 +1,1 @@ |
3149 | -trunk-781 |
3150 | +trunk-782 |
Sorry about the delay in handling your merge request for new vdW options in SiestaXC.
The delay was motivated by two issues:
1. The Gitlab transition.
2. The development of a stand-alone library, ligGridXC, based on the code in SiestaXC.
LibGridXC is being developed at
https:/ /gitlab. com/siesta- project/ libraries/ libgridxc
and is "the future", in the sense that it will be required as a external library for Siesta very soon, once we merge in the next few weeks the PSML branch.
LibGridXC has the same functionality of SiestaXC, with some streamlining, and, in addition, offers an interface to LibXC. This interface is optional now, but very likely it will be made compulsory in the future.
As I understand it, your merge request:
* Adds a few more vdW flavors.
* Implements a new semilocal SG4 functional that is needed by some of the new vdW flavors.
I have no problem with the content of your merge request. I think it should definitely go into libGridXC, but I am not sure whether to integrate it also into the current code base (based on SiestaXC) which is "going away" soon.
In any case, I would request that you make new merge requests within Gitlab:
1. One for libgridXC.
2. (If you think it is worth it) Another one for the "master" branch of Siesta:
https:/ /gitlab. com/siesta- project/ siesta
Note that, as part of the Gitlab transition, the Launchpad branch that you proposed for merging is now available in git form in:
https:/ /gitlab. com/siesta- project/ siesta- legacy/ alesster_ trunk_new_ xc
As a further comment, note that the SG4 functional is already provided by libXC. However, the current way in which the semilocal pieces of the vdW functionals is handled in ligGridXC needs to be checked for compatibility with libXC. It is not as easy as passing the appropriate LIBXC-XXXX string to ggaxc, since the functional object needs to be initialized in advance. So I would keep the explicit implementation of SG4 for now.