AtomsCalculators integration
AtomsCalculators.jl is an interface for doing standard computations (energies, forces, stresses, hessians) on atomistic structures. It is very much inspired by the calculator objects in the atomistic simulation environment.
DFTK by default ships a datastructure called a DFTKCalculator
, which implements the AtomsCalculators interface. A DFTKCalculator
can be constructed by passing three different named tuples, the model_kwargs
, the basis_kwargs
and the scf_kwargs
. The first two named tuples are passed as keyword arguments when constructing the DFT model using model_DFT
and its discretization using the PlaneWaveBasis
. The last one is used as keyword arguments when running the self_consistent_field
function on the resulting basis to solve the problem numerically. Thus when using the DFTKCalculator
the user is expected to pass these objects exactly the keyword argument one would pass when constructing a model
and basis
and when calling self_consistent_field
.
For example, to perform the calculation of the Tutorial using the AtomsCalculators interface we define the calculator as such:
using DFTK
using PseudoPotentialData
pd_lda_family = PseudoFamily("dojo.nc.sr.lda.v0_4_1.standard.upf")
model_kwargs = (; functionals=LDA(), pseudopotentials=pd_lda_family)
basis_kwargs = (; kgrid=[4, 4, 4], Ecut=7)
scf_kwargs = (; tol=1e-5)
calc = DFTKCalculator(; model_kwargs, basis_kwargs, scf_kwargs)
DFTKCalculator(functionals=Xc(lda_x, lda_c_pw), pseudopotentials=PseudoFamily("dojo.nc.sr.lda.v0_4_1.standard.upf"), Ecut=7, kgrid=[4, 4, 4])
Note, that the scf_kwargs
is optional and can be missing (then the defaults of self_consistent_field
are used).
Note that DFTK's kgrid_from_maximal_spacing
function can also be used with AbstractSystem
objects to determine an appropriate kgrid
paramter for the basis_kwargs
. E.g. kgrid_from_maximal_spacing(system, 0.25u"1/Å")
gives a k-point spacing of 0.25
per Angström for the passed system.
Based on this calc
object we can perform a DFT calculation on bulk silicon according to the AtomsCalculators
interface, e.g.
using AtomsBuilder
using AtomsCalculators
AC = AtomsCalculators
# Bulk silicon system of the Tutorial
silicon = bulk(:Si)
AC.potential_energy(silicon, calc) # Compute total energy
-8.508511644212128 Eₕ
or we can compute the energy and forces:
results = AC.calculate((AC.Energy(), AC.Forces()), silicon, calc)
results.energy
-8.508511644216611 Eₕ
results.forces
2-element Vector{StaticArraysCore.SVector{3, Unitful.Quantity{Float64, 𝐋 𝐌 𝐓^-2, Unitful.FreeUnits{(a₀^-1, Eₕ), 𝐋 𝐌 𝐓^-2, nothing}}}}:
[1.634858047537763e-14 Eₕ a₀^-1, 1.6439823618741613e-14 Eₕ a₀^-1, 1.733191985629924e-14 Eₕ a₀^-1]
[-1.6282857566859434e-14 Eₕ a₀^-1, -1.6444747532571478e-14 Eₕ a₀^-1, -1.6787312838403672e-14 Eₕ a₀^-1]
Note that the results
object returned by the call to AtomsCalculators.calculate
also contains a state
, which is a DFTK scfres
. This can be used to speed up subsequent computations:
# This is basically for free, since already computed:
results2 = @time AC.calculate((AC.Energy(), AC.Forces()), silicon, calc, nothing, results.state);
0.275893 seconds (744.81 k allocations: 76.962 MiB)
For an example using the DFTKCalculator
, see Geometry optimization.