|
120 | 120 | atol=1e-7)
|
121 | 121 | end
|
122 | 122 | end
|
| 123 | + |
| 124 | +@testitem "Test solve_ΩplusK_split achieves promised accuracies" begin |
| 125 | + using DFTK |
| 126 | + using LinearAlgebra |
| 127 | + using PseudoPotentialData |
| 128 | + |
| 129 | + function test_solve_ΩplusK(scfres, δVext) |
| 130 | + # Compute a reference solution |
| 131 | + δHψ = DFTK.multiply_ψ_by_blochwave(scfres.basis, scfres.ψ, δVext) |
| 132 | + bandtolalg = DFTK.BandtolGuaranteed(scfres) |
| 133 | + ref = DFTK.solve_ΩplusK_split(scfres, -δHψ; tol=1e-12, verbose=false, bandtolalg) |
| 134 | + |
| 135 | + # Test agreement of non-interacting response |
| 136 | + δρ0 = apply_χ0(scfres, δVext, tol=1e-14).δρ |
| 137 | + @test maximum(abs, δρ0 - ref.δρ0) < 5e-11 |
| 138 | + @test norm(δρ0 - ref.δρ0) < 5e-11 |
| 139 | + |
| 140 | + # Check residual is small |
| 141 | + ε = DFTK.DielectricAdjoint(scfres; bandtolalg=DFTK.BandtolGuaranteed(scfres)) |
| 142 | + εδρ = reshape(DFTK.inexact_mul(ε, ref.δρ; tol=1e-14).Ax, size(δρ0)) |
| 143 | + @test norm(δρ0 - εδρ) < 1e-12 |
| 144 | + @test maximum(abs, δρ0 - εδρ) < 1e-12 |
| 145 | + |
| 146 | + # TODO δψ agreement not tested |
| 147 | + @assert length(scfres.basis.kpoints) == 1 |
| 148 | + |
| 149 | + for tol in (1e-2, 1e-4, 1e-6, 1e-8, 1e-10) |
| 150 | + res = DFTK.solve_ΩplusK_split(scfres, -δHψ; tol, verbose=false) |
| 151 | + @test norm(res.δρ - ref.δρ) < tol |
| 152 | + |
| 153 | + # This is probably a bit flaky ... orbitals could rotate |
| 154 | + @test maximum(abs, res.δψ[1] - ref.δψ[1]) < tol |
| 155 | + end |
| 156 | + |
| 157 | + for s in (1, 10, 100, 10^5) |
| 158 | + tol = 1e-8 |
| 159 | + res = DFTK.solve_ΩplusK_split(scfres, -δHψ; tol, s, verbose=false) |
| 160 | + @test norm(res.δρ - ref.δρ) < tol |
| 161 | + @test maximum(abs, res.δψ[1] - ref.δψ[1]) < tol |
| 162 | + end |
| 163 | + end |
| 164 | + |
| 165 | + @testset "Polarisability in Helium" begin |
| 166 | + # Helium at the centre of the box |
| 167 | + a = 10.0 |
| 168 | + lattice = a * I(3) # cube of ``a`` bohrs |
| 169 | + pseudopotentials = PseudoFamily("cp2k.nc.sr.lda.v0_1.largecore.gth") |
| 170 | + atoms = [ElementPsp(:He, pseudopotentials)] |
| 171 | + positions = [[1/2, 1/2, 1/2]] |
| 172 | + |
| 173 | + model = model_DFT(lattice, atoms, positions; |
| 174 | + functionals=PBE(), symmetries=false) |
| 175 | + basis = PlaneWaveBasis(model; Ecut=30, kgrid=(1, 1, 1)) |
| 176 | + scfres = self_consistent_field(basis; tol=1e-12) |
| 177 | + |
| 178 | + # δVext is the potential from a uniform field interacting with the dielectric dipole |
| 179 | + # of the density. Note, that this expression only makes sense for a molecule |
| 180 | + δVext = [-(r[1] - a/2) for r in r_vectors_cart(basis)] |
| 181 | + δVext = cat(δVext; dims=4) |
| 182 | + |
| 183 | + test_solve_ΩplusK(scfres, δVext) |
| 184 | + end |
| 185 | + |
| 186 | + @testset "Aluminium atomic displacements" begin |
| 187 | + |
| 188 | + |
| 189 | + # TODO displace some atoms and solve response |
| 190 | + |
| 191 | + |
| 192 | + end |
| 193 | +end |
0 commit comments