Input and output formats

This section provides an overview of the input and output formats supported by DFTK, usually via integration with a third-party library.

Reading / writing files supported by AtomsIO

AtomsIO is a Julia package which supports reading / writing atomistic structures from / to a large range of file formats. Supported formats include Crystallographic Information Framework (CIF), XYZ and extxyz files, ASE / Gromacs / LAMMPS / Amber trajectory files or input files of various other codes (e.g. Quantum Espresso, VASP, ABINIT, CASTEP, …). The full list of formats is is available in the AtomsIO documentation.

The AtomsIO functionality is split into two packages. The main package, AtomsIO itself, only depends on packages, which are registered in the Julia General package registry. In contrast AtomsIOPython extends AtomsIO by parsers depending on python packages, which are automatically managed via PythonCall. While it thus provides the full set of supported IO formats, this also adds additional practical complications, so some users may choose not to use AtomsIOPython.

As an example we start the calculation of a simple antiferromagnetic iron crystal using a Quantum-Espresso input file, Fe_afm.pwi. For more details about calculations on magnetic systems using collinear spin, see Collinear spin and magnetic systems.

First we parse the Quantum Espresso input file using AtomsIO, which reads the lattice, atomic positions and initial magnetisation from the input file and returns it as an AtomsBase AbstractSystem, the JuliaMolSim community standard for representing atomic systems.

using AtomsIO        # Use Julia-only IO parsers
using AtomsIOPython  # Use python-based IO parsers (e.g. ASE)
system = load_system("Fe_afm.pwi")
FlexibleSystem(Fe₂, periodic = TTT):
    bounding_box      : [ 2.86814        0        0;
                                0  2.86814        0;
                                0        0  2.86814]u"Å"

    Atom(Fe, [       0,        0,        0]u"Å")
    Atom(Fe, [ 1.43407,  1.43407,        0]u"Å")

      .------.  
     /|      |  
    * |      |  
    | |      |  
    | .------.  
    |/  Fe  /   
    Fe-----*    

Next we attach pseudopotential information, since currently the parser is not yet capable to read this information from the file.

using DFTK
system = attach_psp(system, Fe="hgh/pbe/fe-q16.hgh")
FlexibleSystem(Fe₂, periodic = TTT):
    bounding_box      : [ 2.86814        0        0;
                                0  2.86814        0;
                                0        0  2.86814]u"Å"

    Atom(Fe, [       0,        0,        0]u"Å")
    Atom(Fe, [ 1.43407,  1.43407,        0]u"Å")

      .------.  
     /|      |  
    * |      |  
    | |      |  
    | .------.  
    |/  Fe  /   
    Fe-----*    

Finally we make use of DFTK's AtomsBase integration to run the calculation.

model = model_LDA(system; temperature=0.01)
basis = PlaneWaveBasis(model; Ecut=10, kgrid=(2, 2, 2))
ρ0 = guess_density(basis, system)
scfres = self_consistent_field(basis, ρ=ρ0);
n     Energy            log10(ΔE)   log10(Δρ)   Magnet   Diag   Δtime
---   ---------------   ---------   ---------   ------   ----   ------
  1   -223.7491440161                    0.22   -6.320    5.5    247ms
  2   -224.1614702037       -0.38       -0.21   -3.326    1.8    151ms
  3   -224.2176615381       -1.25       -1.06   -1.613    2.8    237ms
  4   -224.2198809189       -2.65       -1.46   -1.193    1.1    139ms
  5   -224.2207969796       -3.04       -1.73   -0.822    1.0    135ms
  6   -224.2212156304       -3.38       -2.00   -0.482    1.0    136ms
  7   -224.2213725153       -3.80       -2.35   -0.232    1.1    137ms
  8   -224.2214145498       -4.38       -2.85   -0.083    2.1    149ms
  9   -224.2214205115       -5.22       -3.52   -0.008    2.8    160ms
 10   -224.2214206820       -6.77       -3.76    0.001    2.4    165ms
 11   -224.2214207047       -7.65       -3.95   -0.002    1.0    130ms
 12   -224.2214207169       -7.91       -4.31   -0.000    1.2    132ms
 13   -224.2214207185       -8.81       -4.68    0.000    1.7    148ms
 14   -224.2214207187       -9.63       -5.23    0.000    1.5    139ms
 15   -224.2214207187      -10.55       -5.66   -0.000    2.1    147ms
 16   -224.2214207187      -11.46       -6.02   -0.000    2.4    159ms
DFTK data formats are not yet fully matured

The data format in which DFTK saves data as well as the general interface of the load_scfres and save_scfres pair of functions are not yet fully matured. If you use the functions or the produced files expect that you need to adapt your routines in the future even with patch version bumps.

Writing VTK files for visualization

For visualizing the density or the Kohn-Sham orbitals DFTK supports storing the result of an SCF calculations in the form of VTK files. These can afterwards be visualized using tools such as paraview. Using this feature requires the WriteVTK.jl Julia package.

using WriteVTK
save_scfres("iron_afm.vts", scfres; save_ψ=true);

This will save the iron calculation above into the file iron_afm.vts, using save_ψ=true to also include the KS orbitals.

Parsable data-export using json

Many structures in DFTK support the (unexported) todict function, which returns a simplified dictionary representation of the data.

DFTK.todict(scfres.energies)
Dict{String, Float64} with 9 entries:
  "AtomicNonlocal" => -4.34593
  "PspCorrection"  => 7.03001
  "Ewald"          => -161.527
  "total"          => -224.221
  "Entropy"        => -0.0306478
  "Kinetic"        => 75.6631
  "AtomicLocal"    => -161.128
  "Hartree"        => 41.397
  "Xc"             => -21.2803

This in turn can be easily written to disk using a JSON library. Currently we integrate most closely with JSON3, which is thus recommended.

using JSON3
open("iron_afm_energies.json", "w") do io
    JSON3.pretty(io, DFTK.todict(scfres.energies))
end
println(read("iron_afm_energies.json", String))
{
    "AtomicNonlocal": -4.345930969329029,
    "PspCorrection": 7.03000636467455,
    "Ewald": -161.52650757200072,
    "total": -224.2214207187343,
    "Entropy": -0.030647819189328584,
    "Kinetic": 75.66305111201358,
    "AtomicLocal": -161.1281114856379,
    "Hartree": 41.39700831685467,
    "Xc": -21.280288666120082
}

Once JSON3 is loaded, additionally a convenience function for saving a summary of scfres objects using save_scfres is available:

using JSON3
save_scfres("iron_afm.json", scfres)

Similarly a summary of the band data (occupations, eigenvalues, εF, etc.) for post-processing can be dumped using save_bands:

save_bands("iron_afm_scfres.json", scfres)

Notably this function works both for the results obtained by self_consistent_field as well as compute_bands:

bands = compute_bands(scfres, kline_density=10)
save_bands("iron_afm_bands.json", bands)
┌ Warning: The provided cell is a supercell: the returned k-path is the standard k-path of the associated primitive cell in the basis of the supercell reciprocal lattice.
  cell =
   Spglib.SpglibCell{Float64, Float64, Int64, Float64}
    lattice:
      5.41999997388764  0.0  0.0
      0.0  5.41999997388764  0.0
      0.0  0.0  5.41999997388764
    2 atomic positions:
      0.0  0.0  0.0
      0.5  0.5  0.0
    2 atoms:
      1  1
    2 magmoms:
      0.0  0.0

@ BrillouinSpglibExt ~/.julia/packages/Brillouin/gE7Kl/ext/BrillouinSpglibExt.jl:28

Writing and reading JLD2 files

The full state of a DFTK self-consistent field calculation can be stored on disk in form of an JLD2.jl file. This file can be read from other Julia scripts as well as other external codes supporting the HDF5 file format (since the JLD2 format is based on HDF5). This includes notably h5py to read DFTK output from python.

using JLD2
save_scfres("iron_afm.jld2", scfres)

Saving such JLD2 files supports some options, such as save_ψ=false, which avoids saving the Bloch waves (much faster and smaller files). Notice that JLD2 files can also be used with save_bands.

Since such JLD2 can also be read by DFTK to start or continue a calculation, these can also be used for checkpointing or for transferring results to a different computer. See Saving SCF results on disk and SCF checkpoints for details.

(Cleanup files generated by this notebook.)

rm.(["iron_afm.vts", "iron_afm.jld2",
     "iron_afm.json", "iron_afm_energies.json", "iron_afm_scfres.json",
     "iron_afm_bands.json"])
6-element Vector{Nothing}:
 nothing
 nothing
 nothing
 nothing
 nothing
 nothing