Skip to content

Commit 55a395e

Browse files
authored
Various small fixes and interface improvements (#1179)
1 parent d6ae833 commit 55a395e

File tree

13 files changed

+60
-49
lines changed

13 files changed

+60
-49
lines changed

docs/src/features.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,8 @@ and runs out of the box on Linux, windows and macOS, see [Installation](@ref).
3232
## Response and response properties
3333
- Density-functional perturbation theory (DFPT)
3434
- Integration of DFPT with **algorithmic differentiation**,
35-
e.g. [Polarizability using automatic differentiation](@ref)
35+
e.g. [Elastic constants](@ref),
36+
[Polarizability using automatic differentiation](@ref)
3637
- [Phonon computations](@ref) *(preliminary implementation)*
3738

3839
## Unique features

docs/src/guide/introductory_resources.md

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -67,21 +67,22 @@ see [Publications](@ref).
6767
Covers topics such as DFT, pseudos, SCF, response, ...
6868

6969
## Recordings
70+
- [Algorithmic differentiation (AD) for plane-wave DFT](https://www.youtube.com/watch?v=g6j1beYSWV4) by M. F. Herbst:
71+
45-min talk at the Institute for Pure and Applied Mathematics (IPAM)
72+
at UCLA discussing the algorithmic differentiation techniques in DFTK.
73+
7074
- [DFTK.jl: 5 years of a multidisciplinary electronic-structure code](https://www.youtube.com/watch?v=ox_j2zKOuIk) by M. F. Herbst:
7175
30-min talk at JuliaCon 2024 providing the state of DFTK 5 years after the project was started.
7276
[Slides](https://michael-herbst.com/talks/2024.07.12_5years_DFTK.pdf),
7377
[Pluto notebook](https://michael-herbst.com/talks/2024.07.12_5years_DFTK.html)
7478

75-
- [Julia for Materials Modelling](https://www.youtube.com/watch?v=dujepKxxxkg) by M. F. Herbst:
79+
- [Julia for Materials Modelling](https://www.youtube.com/watch?v=dujepKxxxkg)
80+
by M. F. Herbst (from 2023):
7681
One-hour talk providing an overview of materials modelling tools for Julia.
7782
Key features of DFTK are highlighted as part of the talk.
83+
Starts to become a little outdated
7884
[Pluto notebooks](https://mfherbst.github.io/julia-for-materials/)
7985

80-
- [DFTK: A Julian approach for simulating electrons in solids](https://www.youtube.com/watch?v=-RomkxjlIcQ) by M. F. Herbst:
81-
Pre-recorded talk for JuliaCon 2020.
82-
Assumes no knowledge about DFT and gives the broad picture of DFTK. Starts to become a little outdated.
83-
[Slides](https://michael-herbst.com/talks/2020.07.29_juliacon_dftk.pdf).
84-
8586
- [Juliacon 2021 DFT workshop](https://www.youtube.com/watch?v=HvpPMWVm8aw) by M. F. Herbst:
8687
Three-hour workshop session at the 2021 Juliacon providing a mathematical look on
8788
DFT, SCF solution algorithms as well as the integration of DFTK into the Julia

src/elements.jl

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,9 @@ pseudofamily(::Element) = nothing
3535
has_core_density(::Element) = false
3636
# The preceding functions are fallback implementations that should be altered as needed.
3737

38+
eval_psp_energy_correction(T, ::Element) = zero(T)
39+
eval_psp_energy_correction(psp::Element) = eval_psp_energy_correction(Float64, psp)
40+
3841
# Fall back to the Gaussian table for Elements without pseudopotentials
3942
function valence_charge_density_fourier(el::Element, p::T)::T where {T <: Real}
4043
gaussian_valence_charge_density_fourier(el, p)
@@ -152,6 +155,7 @@ AtomsBase.mass(el::ElementPsp) = el.mass
152155
AtomsBase.species(el::ElementPsp) = el.species
153156
charge_ionic(el::ElementPsp) = charge_ionic(el.psp)
154157
has_core_density(el::ElementPsp) = has_core_density(el.psp)
158+
eval_psp_energy_correction(T, el::ElementPsp) = eval_psp_energy_correction(T, el.psp)
155159

156160
function local_potential_fourier(el::ElementPsp, p::T) where {T <: Real}
157161
p == 0 && return zero(T) # Compensating charge background
@@ -237,6 +241,7 @@ function local_potential_fourier(el::ElementCohenBergstresser, p::T) where {T <:
237241
psq_pi = Int(round(p^2 / (2π / el.lattice_constant)^2, digits=2))
238242
T(get(el.V_sym, psq_pi, 0.0))
239243
end
244+
# TODO Strictly speaking needs a eval_psp_energy_correction
240245

241246

242247
#
@@ -269,3 +274,4 @@ end
269274
function local_potential_fourier(el::ElementGaussian, p::Real)
270275
-el.α * exp(- (p * el.L)^2 / 2) # = ∫_ℝ³ V(x) exp(-ix⋅p) dx
271276
end
277+
# TODO Strictly speaking needs a eval_psp_energy_correction

src/pseudo/NormConservingPsp.jl

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ abstract type NormConservingPsp end
1818
# eval_psp_projector_fourier(psp, i, l, p::Real)
1919
# eval_psp_local_real(psp, r::Real)
2020
# eval_psp_local_fourier(psp, p::Real)
21-
# eval_psp_energy_correction(T::Type, psp, n_electrons::Integer)
21+
# eval_psp_energy_correction(T::Type, psp)
2222

2323
#### Optional methods:
2424
# eval_psp_density_valence_real(psp, r::Real)
@@ -86,15 +86,15 @@ eval_psp_local_fourier(psp::NormConservingPsp, p::AbstractVector) =
8686
eval_psp_local_fourier(psp, norm(p))
8787

8888
@doc raw"""
89-
eval_psp_energy_correction([T=Float64,] psp, n_electrons)
89+
eval_psp_energy_correction([T=Float64,] psp::NormConservingPsp)
90+
eval_psp_energy_correction([T=Float64,] element::Element)
9091
91-
Evaluate the energy correction to the Ewald electrostatic interaction energy of one unit
92-
cell, which is required compared the Ewald expression for point-like nuclei. `n_electrons`
93-
is the number of electrons per unit cell. This defines the uniform compensating background
94-
charge, which is assumed here.
95-
96-
Notice: The returned result is the *energy per unit cell* and not the energy per volume.
97-
To obtain the latter, the caller needs to divide by the unit cell volume.
92+
Evaluate the energy correction to the Ewald electrostatic interaction energy per unit
93+
of uniform negative charge. This is the correction required to account for the fact that
94+
the Ewald expression assumes point-like nuclei and not nuclei of the shape induced by
95+
the pseudopotential. The compensating background charge assumed for this expression is
96+
scaled to ``1``. Therefore multiplying by the number of electrons and dividing by the unit
97+
cell volume yields the energy correction per volume for the DFT simulation.
9898
9999
The energy correction is defined as the limit of the Fourier-transform of the local
100100
potential as ``p \to 0``, using the same correction as in the Fourier-transform of the local
@@ -103,12 +103,14 @@ potential:
103103
\lim_{p \to 0} 4π N_{\rm elec} ∫_{ℝ_+} (V(r) - C(r)) \frac{\sin(p·r)}{p·r} r^2 dr + F[C(r)]
104104
= 4π N_{\rm elec} ∫_{ℝ_+} (V(r) + Z/r) r^2 dr.
105105
```
106+
where as discussed above the implementation is expected to return the result
107+
for ``N_{\rm elec} = 1``.
106108
"""
107109
function eval_psp_energy_correction end
108110
# by default, no correction, see PspHgh implementation and tests
109111
# for details on what to implement
110-
eval_psp_energy_correction(psp::NormConservingPsp, n_electrons) =
111-
eval_psp_energy_correction(Float64, psp, n_electrons)
112+
113+
eval_psp_energy_correction(psp::NormConservingPsp) = eval_psp_energy_correction(Float64, psp)
112114

113115
"""
114116
eval_psp_density_valence_real(psp, r)

src/pseudo/PspHgh.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -218,7 +218,7 @@ function eval_psp_projector_real(psp::PspHgh, i, l, r::T) where {T <: Real}
218218
sqrt(T(2)) * r^(l + 2(i - 1)) * exp(-r^2 / 2rp^2) / rp^(l + ired) / sqrt(gamma(l + ired))
219219
end
220220

221-
function eval_psp_energy_correction(T, psp::PspHgh, n_electrons)
221+
function eval_psp_energy_correction(T, psp::PspHgh)
222222
# By construction we need to compute the DC component of the difference
223223
# of the Coulomb potential (-Z/G^2 in Fourier space) and the pseudopotential
224224
# i.e. -4πZ/(ΔG)^2 - eval_psp_local_fourier(psp, ΔG) for ΔG → 0. This is:
@@ -228,5 +228,5 @@ function eval_psp_energy_correction(T, psp::PspHgh, n_electrons)
228228

229229
# Multiply by number of electrons and 4π (spherical Hankel prefactor)
230230
# to get energy per unit cell
231-
4T(π) * n_electrons * difference_DC
231+
4T(π) * difference_DC
232232
end

src/pseudo/PspUpf.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -232,10 +232,10 @@ function eval_psp_density_core_fourier(psp::PspUpf, p::T) where {T<:Real}
232232
return hankel(rgrid, r2_ρcore, 0, p)
233233
end
234234

235-
function eval_psp_energy_correction(T, psp::PspUpf, n_electrons)
235+
function eval_psp_energy_correction(T, psp::PspUpf)
236236
rgrid = @view psp.rgrid[1:psp.ircut]
237237
vloc = @view psp.vloc[1:psp.ircut]
238-
4T(π) * n_electrons * simpson(rgrid) do i, r
238+
4T(π) * simpson(rgrid) do i, r
239239
r * (r * vloc[i] - -psp.Zion)
240240
end
241241
end

src/response/chi0.jl

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -575,6 +575,7 @@ function construct_bandtol(Bandtol::Type, basis::PlaneWaveBasis, ψ, occupation:
575575
# Distributing the error equally across all k-points leads to (with w = sqrt(Ω / Ng))
576576
# ‖z_{nk}‖ ≤ sqrt(Ω / Ng) / (‖K v_i‖ sqrt(Nocck) ‖Re(F⁻¹ Φk)‖_{2,∞} * 2f_{nk} Nk wk)
577577
# If we bound ‖Re(F⁻¹ Φk)‖_{2,∞} from below this is sqrt(Nocc / Ω).
578+
# See also section SM6 and Table SM4 in 2505.02319.
578579
#
579580
# Note that the kernel term ||K v_i|| of 2505.02319 is dropped here as it purely arises
580581
# from the rescaling of the RHS performed in apply_χ0 above. Consequently the function
@@ -598,10 +599,13 @@ function construct_bandtol(Bandtol::Type, scfres::NamedTuple; kwargs...)
598599
end
599600

600601
function adaptive_bandtol_orbital_term_(::Type{BandtolGuaranteed}, basis, kpt, ψk, mask_k)
601-
# Orbital term ‖Re(F⁻¹ Φk)‖_{2,∞} for thik k-point
602+
# Orbital term ‖F⁻¹ Φk‖_{2,∞} for thik k-point
603+
# Note that compared to the paper we deliberately do not take the real part,
604+
# since taking the real part represents an additional approximation
605+
# (thus making the strategy less guaranteed)
602606
row_sums_squared = sum(mask_k) do n
603607
ψnk_real = @views ifft(basis, kpt, ψk[:, n])
604-
abs2.(real.(ψnk_real))
608+
abs2.(ψnk_real)
605609
end
606610
sqrt(maximum(row_sums_squared))
607611
end

src/scf/anderson.jl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,8 @@ and returns ``xₙ₊₁``.
103103
M = stack(Pfxs) .- vec(Pfxₙ) # Mᵢⱼ = (Pfxⱼ)ᵢ - (Pfxₙ)ᵢ
104104
# We need to solve 0 = M' Pfxₙ + M'M βs <=> βs = - (M'M)⁻¹ M' Pfxₙ
105105

106+
# TODO If memory pressure is high, automatically drop old iterates here
107+
# (Note: This quickly happens in GPU scenarios)
106108
# Ensure the condition number of M stays below maxcond, else prune the history
107109
Mfac = qr(M)
108110
while size(M, 2) > 1 && cond(Mfac.R) > anderson.maxcond

src/scf/mixing.jl

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -33,18 +33,20 @@ mix_density(::SimpleMixing, ::PlaneWaveBasis, δF; kwargs...) = δF
3333
@doc raw"""
3434
Kerker mixing: ``J^{-1} ≈ \frac{|G|^2}{k_{TF}^2 + |G|^2}``
3535
where ``k_{TF}`` is the Thomas-Fermi wave vector. For spin-polarized calculations
36-
by default the spin density is not preconditioned. Unless a non-default value
37-
for ``ΔDOS_Ω`` is specified. This value should roughly be the expected difference in density
38-
of states (per unit volume) between spin-up and spin-down.
36+
by default the spin density is not preconditioned unless a non-default value
37+
for `ΔDOS_Ω` is specified. This value should roughly be the expected difference in density
38+
of states (per unit volume) between spin-up and spin-down. Notably setting
39+
`ΔDOS_Ω = kTF^2 / 4π` disables acting on the ``β`` spin channel completely (as if the
40+
DOS on ``β`` spin was zero).
3941
4042
Notes:
4143
- Abinit calls ``1/k_{TF}`` the dielectric screening length (parameter *dielng*)
4244
"""
4345
@kwdef struct KerkerMixing <: Mixing
4446
# Default kTF parameter suggested by Kresse, Furthmüller 1996 (kTF=1.5Å⁻¹)
4547
# DOI 10.1103/PhysRevB.54.11169
46-
kTF::Real = 0.8 # == sqrt(4π (DOS_α + DOS_β)) / Ω
47-
ΔDOS_Ω::Real = 0.0 # == (DOS_α - DOS_β) / Ω
48+
kTF::Real = 0.8 # == sqrt(4π (DOS_α + DOS_β) / Ω)
49+
ΔDOS_Ω::Real = 0.0 # == (DOS_α - DOS_β) / Ω; set == kTF^2/4π to disable acting on β density
4850
end
4951

5052
@timing "KerkerMixing" function mix_density(mixing::KerkerMixing, basis::PlaneWaveBasis,

src/terms/operators.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,7 @@ function apply!(Hψ, op::DivAgradOperator, ψ;
153153
.fourier .-= im .* G_plus_k[α] .* A∇ψ ./ 2
154154
end
155155
end
156-
# TODO Implement Matrix(op::DivAgrad)
156+
# TODO Implement Matrix(op::DivAgradOperator)
157157

158158

159159
# Optimize RFOs by combining terms that can be combined

0 commit comments

Comments
 (0)