Skip to content

Commit 38077db

Browse files
committed
update DFTK integration for DFTK 0.5.0
1 parent e76d701 commit 38077db

File tree

4 files changed

+15
-72
lines changed

4 files changed

+15
-72
lines changed

Project.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
name = "Atomistic"
22
uuid = "3e762ff9-b8d8-45cf-a902-edcbc7124e71"
33
authors = ["Jeremiah DeGreeff <[email protected]>"]
4-
version = "0.3.4"
4+
version = "0.3.5"
55

66
[deps]
77
AtomsBase = "a963bdd2-2df7-4f54-a1ee-49d51e6be12a"
@@ -21,7 +21,7 @@ UnitfulRecipes = "42071c24-d89e-48dd-8a24-8a12d9b8861f"
2121

2222
[compat]
2323
AtomsBase = "0.2"
24-
DFTK = "0.4"
24+
DFTK = "0.5"
2525
Distances = "0.10"
2626
InteratomicPotentials = "0.1"
2727
Molly = "0.9"

src/Atomistic.jl

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ using NBodySimulator
1818
using PeriodicTable
1919
using Plots, UnitfulRecipes
2020

21-
import Base: @kwdef
2221
import DFTK: Mixing
2322
import NBodySimulator: Body, BoundaryConditions, NullThermostat, SimulationResult, Thermostat
2423
import Plots: Plot

src/integrations/dftk_integration.jl

Lines changed: 9 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -1,84 +1,28 @@
1-
# Integrations with DFTK.jl
2-
3-
# -----------------------------------------------------------------------------
4-
# Integration with AtomsBase
5-
# -----------------------------------------------------------------------------
6-
7-
# ! all functions in this section are copied directly from experimental DFTK code
8-
# ! this code will be deleted once it is live in DFTK
9-
10-
function parse_system(system::AbstractSystem{3})
11-
if !all(periodicity(system))
12-
error("DFTK only supports calculations with periodic boundary conditions.")
13-
end
14-
15-
# Parse abstract system and return data required to construct model
16-
lattice = austrip.(hcat(bounding_box(system)...))
17-
T = eltype(lattice)
18-
19-
# Cache for instantiated pseudopotentials
20-
# (such that the respective objects are indistinguishable)
21-
cached_pseudos = Dict{String,Any}()
22-
atoms = map(system) do atom
23-
if hasproperty(atom, :potential)
24-
potential = atom.potential
25-
elseif hasproperty(atom, :pseudopotential)
26-
pspkey = atom.pseudopotential
27-
potential = get!(cached_pseudos, pspkey) do
28-
ElementPsp(AtomsBase.atomic_symbol(atom); psp = load_psp(pspkey))
29-
end
30-
else
31-
potential = ElementCoulomb(AtomsBase.atomic_symbol(atom))
32-
end
33-
34-
potential => SVector{3,T}(lattice \ T.(austrip.(position(atom))))
35-
end
36-
37-
oldatoms = oldatoms_from_new(atoms)
38-
39-
(; lattice, atoms = oldatoms)
40-
end
41-
function oldatoms_from_new(atomic_potentials)
42-
potentials = first.(atomic_potentials)
43-
potential_groups = [findall(Ref(pot) .== potentials) for pot in Set(potentials)]
44-
[first(atomic_potentials[first(group)]) => last.(atomic_potentials[group]) for group in potential_groups]
45-
end
46-
function DFTK.model_LDA(system::AbstractSystem; kwargs...)
47-
parsed = parse_system(system)
48-
model_LDA(parsed.lattice, parsed.atoms; kwargs...)
49-
end
50-
511
# -----------------------------------------------------------------------------
522
# Integration with InteratomicPotentials
533
# -----------------------------------------------------------------------------
544

555
# ! This integration should ultimately move to the DFTK package itself
566

57-
@kwdef struct DFTKPotential <: ArbitraryPotential
7+
struct DFTKPotential <: ArbitraryPotential
588
Ecut::Real
599
kgrid::AbstractVector{<:Integer}
60-
n_bands::Union{Integer,Nothing} = nothing
61-
tol::Union{AbstractFloat,Nothing} = nothing
62-
damping::Union{AbstractFloat,Nothing} = nothing
63-
mixing::Union{Mixing,Nothing} = nothing
64-
previous_scfres::Ref{Any} = Ref{Any}()
65-
potential_energy_cache::Dict{Float64,Float64} = Dict{Float64,Float64}()
10+
scf_args::Dict{Symbol,Any}
11+
previous_scf::Ref{Any}
6612
end
6713
function DFTKPotential(Ecut::Real, kgrid::AbstractVector{<:Integer}; kwargs...)
68-
DFTKPotential(; Ecut = Ecut, kgrid = kgrid, kwargs...)
14+
DFTKPotential(Ecut, kgrid, Dict{Symbol,Any}(kwargs...), Ref{Any}())
6915
end
7016
function DFTKPotential(Ecut::Unitful.Energy, kgrid::AbstractVector{<:Integer}; kwargs...)
71-
DFTKPotential(; Ecut = austrip(Ecut), kgrid = kgrid, kwargs...)
17+
DFTKPotential(austrip(Ecut), kgrid, Dict{Symbol,Any}(kwargs...), Ref{Any}())
7218
end
7319

7420
function InteratomicPotentials.energy_and_force(system::AbstractSystem, potential::DFTKPotential)
7521
model = model_LDA(system)
7622
basis = PlaneWaveBasis(model; Ecut = potential.Ecut, kgrid = potential.kgrid)
7723

78-
args = (f => getfield(potential, f) for f (:n_bands, :tol, :damping, :mixing) if !isnothing(getfield(potential, f)))
79-
extra_args = isassigned(potential.previous_scfres) ?= potential.previous_scfres[].ψ, ρ = potential.previous_scfres[].ρ) : (;)
80-
scfres = self_consistent_field(basis; args..., extra_args...)
81-
potential.previous_scfres[] = scfres
82-
# TODO: support multiple species
83-
(; e = scfres.energies.total, f = compute_forces_cart(scfres)[1])
24+
extra_args = isassigned(potential.previous_scf) ?= potential.previous_scf[].ψ, ρ = potential.previous_scf[].ρ) : (;)
25+
scfres = self_consistent_field(basis; potential.scf_args..., extra_args...)
26+
potential.previous_scf[] = scfres # cache previous scf as starting point for next calculation
27+
(; e = scfres.energies.total, f = compute_forces_cart(scfres))
8428
end

test/integrations/dftk_integration.jl

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,15 +16,15 @@
1616
@test eandf1.e isa Float64
1717
@test eandf1.f isa AbstractVector{<:SVector{3,<:Float64}}
1818

19-
@test potential1.previous_scfres[].energies.total == eandf1.e
20-
@test compute_forces_cart(potential1.previous_scfres[])[1] == eandf1.f
19+
@test potential1.previous_scf[].energies.total == eandf1.e
20+
@test compute_forces_cart(potential1.previous_scf[]) == eandf1.f
2121

2222
system2 = System(system1)
2323
eandf2 = energy_and_force(system2, potential2)
2424

2525
@test eandf2.e isa Float64
2626
@test eandf2.f isa AbstractVector{<:SVector{3,<:Float64}}
2727

28-
@test potential2.previous_scfres[].energies.total == eandf2.e
29-
@test compute_forces_cart(potential2.previous_scfres[])[1] == eandf2.f
28+
@test potential2.previous_scf[].energies.total == eandf2.e
29+
@test compute_forces_cart(potential2.previous_scf[]) == eandf2.f
3030
end

0 commit comments

Comments
 (0)