/
search_index.js
3 lines (3 loc) · 346 KB
/
search_index.js
1
2
3
var documenterSearchIndex = {"docs":
[{"location":"examples/gaas_surface/","page":"Modelling a gallium arsenide surface","title":"Modelling a gallium arsenide surface","text":"EditURL = \"https://github.com/JuliaMolSim/DFTK.jl/blob/master/examples/gaas_surface.jl\"","category":"page"},{"location":"examples/gaas_surface/#Modelling-a-gallium-arsenide-surface","page":"Modelling a gallium arsenide surface","title":"Modelling a gallium arsenide surface","text":"","category":"section"},{"location":"examples/gaas_surface/","page":"Modelling a gallium arsenide surface","title":"Modelling a gallium arsenide surface","text":"(Image: ) (Image: )","category":"page"},{"location":"examples/gaas_surface/","page":"Modelling a gallium arsenide surface","title":"Modelling a gallium arsenide surface","text":"This example shows how to use the atomistic simulation environment, or ASE for short, to set up and run a particular calculation of a gallium arsenide surface. ASE is a Python package to simplify the process of setting up, running and analysing results from atomistic simulations across different simulation codes. By means of ASEconvert it is seamlessly integrated with the AtomsBase ecosystem and thus available to DFTK via our own AtomsBase integration.","category":"page"},{"location":"examples/gaas_surface/","page":"Modelling a gallium arsenide surface","title":"Modelling a gallium arsenide surface","text":"In this example we will consider modelling the (1, 1, 0) GaAs surface separated by vacuum.","category":"page"},{"location":"examples/gaas_surface/","page":"Modelling a gallium arsenide surface","title":"Modelling a gallium arsenide surface","text":"Parameters of the calculation. Since this surface is far from easy to converge, we made the problem simpler by choosing a smaller Ecut and smaller values for n_GaAs and n_vacuum. More interesting settings are Ecut = 15 and n_GaAs = n_vacuum = 20.","category":"page"},{"location":"examples/gaas_surface/","page":"Modelling a gallium arsenide surface","title":"Modelling a gallium arsenide surface","text":"miller = (1, 1, 0) # Surface Miller indices\nn_GaAs = 2 # Number of GaAs layers\nn_vacuum = 4 # Number of vacuum layers\nEcut = 5 # Hartree\nkgrid = (4, 4, 1); # Monkhorst-Pack mesh\nnothing #hide","category":"page"},{"location":"examples/gaas_surface/","page":"Modelling a gallium arsenide surface","title":"Modelling a gallium arsenide surface","text":"Use ASE to build the structure:","category":"page"},{"location":"examples/gaas_surface/","page":"Modelling a gallium arsenide surface","title":"Modelling a gallium arsenide surface","text":"using ASEconvert\n\na = 5.6537 # GaAs lattice parameter in Ångström (because ASE uses Å as length unit)\ngaas = ase.build.bulk(\"GaAs\", \"zincblende\"; a)\nsurface = ase.build.surface(gaas, miller, n_GaAs, 0, periodic=true);\nnothing #hide","category":"page"},{"location":"examples/gaas_surface/","page":"Modelling a gallium arsenide surface","title":"Modelling a gallium arsenide surface","text":"Get the amount of vacuum in Ångström we need to add","category":"page"},{"location":"examples/gaas_surface/","page":"Modelling a gallium arsenide surface","title":"Modelling a gallium arsenide surface","text":"d_vacuum = maximum(maximum, surface.cell) / n_GaAs * n_vacuum\nsurface = ase.build.surface(gaas, miller, n_GaAs, d_vacuum, periodic=true);\nnothing #hide","category":"page"},{"location":"examples/gaas_surface/","page":"Modelling a gallium arsenide surface","title":"Modelling a gallium arsenide surface","text":"Write an image of the surface and embed it as a nice illustration:","category":"page"},{"location":"examples/gaas_surface/","page":"Modelling a gallium arsenide surface","title":"Modelling a gallium arsenide surface","text":"ase.io.write(\"surface.png\", surface * pytuple((3, 3, 1)), rotation=\"-90x, 30y, -75z\")","category":"page"},{"location":"examples/gaas_surface/","page":"Modelling a gallium arsenide surface","title":"Modelling a gallium arsenide surface","text":"<img src=\"../surface.png\" width=500 height=500 />","category":"page"},{"location":"examples/gaas_surface/","page":"Modelling a gallium arsenide surface","title":"Modelling a gallium arsenide surface","text":"Use the pyconvert function from PythonCall to convert to an AtomsBase-compatible system. These two functions not only support importing ASE atoms into DFTK, but a few more third-party data structures as well. Typically the imported atoms use a bare Coulomb potential, such that appropriate pseudopotentials need to be attached in a post-step:","category":"page"},{"location":"examples/gaas_surface/","page":"Modelling a gallium arsenide surface","title":"Modelling a gallium arsenide surface","text":"using DFTK\nsystem = attach_psp(pyconvert(AbstractSystem, surface);\n Ga=\"hgh/pbe/ga-q3.hgh\",\n As=\"hgh/pbe/as-q5.hgh\")","category":"page"},{"location":"examples/gaas_surface/","page":"Modelling a gallium arsenide surface","title":"Modelling a gallium arsenide surface","text":"We model this surface with (quite large a) temperature of 0.01 Hartree to ease convergence. Try lowering the SCF convergence tolerance (tol) or the temperature or try mixing=KerkerMixing() to see the full challenge of this system.","category":"page"},{"location":"examples/gaas_surface/","page":"Modelling a gallium arsenide surface","title":"Modelling a gallium arsenide surface","text":"model = model_DFT(system, [:gga_x_pbe, :gga_c_pbe],\n temperature=0.001, smearing=DFTK.Smearing.Gaussian())\nbasis = PlaneWaveBasis(model; Ecut, kgrid)\n\nscfres = self_consistent_field(basis, tol=1e-4, mixing=LdosMixing());\nnothing #hide","category":"page"},{"location":"examples/gaas_surface/","page":"Modelling a gallium arsenide surface","title":"Modelling a gallium arsenide surface","text":"scfres.energies","category":"page"},{"location":"examples/geometry_optimization/","page":"Geometry optimization","title":"Geometry optimization","text":"EditURL = \"https://github.com/JuliaMolSim/DFTK.jl/blob/master/examples/geometry_optimization.jl\"","category":"page"},{"location":"examples/geometry_optimization/#Geometry-optimization","page":"Geometry optimization","title":"Geometry optimization","text":"","category":"section"},{"location":"examples/geometry_optimization/","page":"Geometry optimization","title":"Geometry optimization","text":"(Image: ) (Image: )","category":"page"},{"location":"examples/geometry_optimization/","page":"Geometry optimization","title":"Geometry optimization","text":"We use the DFTK and Optim packages in this example to find the minimal-energy bond length of the H_2 molecule. We setup H_2 in an LDA model just like in the Tutorial for silicon.","category":"page"},{"location":"examples/geometry_optimization/","page":"Geometry optimization","title":"Geometry optimization","text":"using DFTK\nusing Optim\nusing LinearAlgebra\nusing Printf\n\nkgrid = [1, 1, 1] # k-point grid\nEcut = 5 # kinetic energy cutoff in Hartree\ntol = 1e-8 # tolerance for the optimization routine\na = 10 # lattice constant in Bohr\nlattice = a * I(3)\nH = ElementPsp(:H, psp=load_psp(\"hgh/lda/h-q1\"));\natoms = [H, H];\nnothing #hide","category":"page"},{"location":"examples/geometry_optimization/","page":"Geometry optimization","title":"Geometry optimization","text":"We define a Bloch wave and a density to be used as global variables so that we can transfer the solution from one iteration to another and therefore reduce the optimization time.","category":"page"},{"location":"examples/geometry_optimization/","page":"Geometry optimization","title":"Geometry optimization","text":"ψ = nothing\nρ = nothing","category":"page"},{"location":"examples/geometry_optimization/","page":"Geometry optimization","title":"Geometry optimization","text":"First, we create a function that computes the solution associated to the position x ℝ^6 of the atoms in reduced coordinates (cf. Reduced and cartesian coordinates for more details on the coordinates system). They are stored as a vector: x[1:3] represents the position of the first atom and x[4:6] the position of the second. We also update ψ and ρ for the next iteration.","category":"page"},{"location":"examples/geometry_optimization/","page":"Geometry optimization","title":"Geometry optimization","text":"function compute_scfres(x)\n model = model_LDA(lattice, atoms, [x[1:3], x[4:6]])\n basis = PlaneWaveBasis(model; Ecut, kgrid)\n global ψ, ρ\n if isnothing(ρ)\n ρ = guess_density(basis)\n end\n is_converged = DFTK.ScfConvergenceForce(tol / 10)\n scfres = self_consistent_field(basis; ψ, ρ, is_converged, callback=identity)\n ψ = scfres.ψ\n ρ = scfres.ρ\n scfres\nend;\nnothing #hide","category":"page"},{"location":"examples/geometry_optimization/","page":"Geometry optimization","title":"Geometry optimization","text":"Then, we create the function we want to optimize: fg! is used to update the value of the objective function F, namely the energy, and its gradient G, here computed with the forces (which are, by definition, the negative gradient of the energy).","category":"page"},{"location":"examples/geometry_optimization/","page":"Geometry optimization","title":"Geometry optimization","text":"function fg!(F, G, x)\n scfres = compute_scfres(x)\n if !isnothing(G)\n grad = compute_forces(scfres)\n G .= -[grad[1]; grad[2]]\n end\n scfres.energies.total\nend;\nnothing #hide","category":"page"},{"location":"examples/geometry_optimization/","page":"Geometry optimization","title":"Geometry optimization","text":"Now, we can optimize on the 6 parameters x = [x1, y1, z1, x2, y2, z2] in reduced coordinates, using LBFGS(), the default minimization algorithm in Optim. We start from x0, which is a first guess for the coordinates. By default, optimize traces the output of the optimization algorithm during the iterations. Once we have the minimizer xmin, we compute the bond length in Cartesian coordinates.","category":"page"},{"location":"examples/geometry_optimization/","page":"Geometry optimization","title":"Geometry optimization","text":"x0 = vcat(lattice \\ [0., 0., 0.], lattice \\ [1.4, 0., 0.])\nxres = optimize(Optim.only_fg!(fg!), x0, LBFGS(),\n Optim.Options(show_trace=true, f_tol=tol))\nxmin = Optim.minimizer(xres)\ndmin = norm(lattice*xmin[1:3] - lattice*xmin[4:6])\n@printf \"\\nOptimal bond length for Ecut=%.2f: %.3f Bohr\\n\" Ecut dmin","category":"page"},{"location":"examples/geometry_optimization/","page":"Geometry optimization","title":"Geometry optimization","text":"We used here very rough parameters to generate the example and setting Ecut to 10 Ha yields a bond length of 1.523 Bohr, which agrees with ABINIT.","category":"page"},{"location":"examples/geometry_optimization/","page":"Geometry optimization","title":"Geometry optimization","text":"note: Degrees of freedom\nWe used here a very general setting where we optimized on the 6 variables representing the position of the 2 atoms and it can be easily extended to molecules with more atoms (such as H_2O). In the particular case of H_2, we could use only the internal degree of freedom which, in this case, is just the bond length.","category":"page"},{"location":"examples/convergence_study/","page":"Performing a convergence study","title":"Performing a convergence study","text":"EditURL = \"https://github.com/JuliaMolSim/DFTK.jl/blob/master/examples/convergence_study.jl\"","category":"page"},{"location":"examples/convergence_study/#Performing-a-convergence-study","page":"Performing a convergence study","title":"Performing a convergence study","text":"","category":"section"},{"location":"examples/convergence_study/","page":"Performing a convergence study","title":"Performing a convergence study","text":"(Image: ) (Image: )","category":"page"},{"location":"examples/convergence_study/","page":"Performing a convergence study","title":"Performing a convergence study","text":"This example shows how to perform a convergence study to find an appropriate discretisation parameters for the Brillouin zone (kgrid) and kinetic energy cutoff (Ecut), such that the simulation results are converged to a desired accuracy tolerance.","category":"page"},{"location":"examples/convergence_study/","page":"Performing a convergence study","title":"Performing a convergence study","text":"Such a convergence study is generally performed by starting with a reasonable base line value for kgrid and Ecut and then increasing these parameters (i.e. using finer discretisations) until a desired property (such as the energy) changes less than the tolerance.","category":"page"},{"location":"examples/convergence_study/","page":"Performing a convergence study","title":"Performing a convergence study","text":"This procedure must be performed for each discretisation parameter. Beyond the Ecut and the kgrid also convergence in the smearing temperature or other numerical parameters should be checked. For simplicity we will neglect this aspect in this example and concentrate on Ecut and kgrid. Moreover we will restrict ourselves to using the same number of k-points in each dimension of the Brillouin zone.","category":"page"},{"location":"examples/convergence_study/","page":"Performing a convergence study","title":"Performing a convergence study","text":"As the objective of this study we consider bulk platinum. For running the SCF conveniently we define a function:","category":"page"},{"location":"examples/convergence_study/","page":"Performing a convergence study","title":"Performing a convergence study","text":"using DFTK\nusing LinearAlgebra\nusing Statistics\n\nfunction run_scf(; a=5.0, Ecut, nkpt, tol)\n atoms = [ElementPsp(:Pt, psp = load_psp(\"hgh/lda/Pt-q10\"))]\n position = [zeros(3)]\n lattice = a * Matrix(I, 3, 3)\n\n model = model_LDA(lattice, atoms, position; temperature=1e-2)\n basis = PlaneWaveBasis(model; Ecut, kgrid=(nkpt, nkpt, nkpt))\n println(\"nkpt = $nkpt Ecut = $Ecut\")\n self_consistent_field(basis; is_converged=DFTK.ScfConvergenceEnergy(tol))\nend;\nnothing #hide","category":"page"},{"location":"examples/convergence_study/","page":"Performing a convergence study","title":"Performing a convergence study","text":"Moreover we define some parameters. To make the calculations run fast for the automatic generation of this documentation we target only a convergence to 1e-2. In practice smaller tolerances (and thus larger upper bounds for nkpts and Ecuts are likely needed.","category":"page"},{"location":"examples/convergence_study/","page":"Performing a convergence study","title":"Performing a convergence study","text":"tol = 1e-2 # Tolerance to which we target to converge\nnkpts = 1:7 # K-point range checked for convergence\nEcuts = 10:2:24; # Energy cutoff range checked for convergence\nnothing #hide","category":"page"},{"location":"examples/convergence_study/","page":"Performing a convergence study","title":"Performing a convergence study","text":"As the first step we converge in the number of k-points employed in each dimension of the Brillouin zone …","category":"page"},{"location":"examples/convergence_study/","page":"Performing a convergence study","title":"Performing a convergence study","text":"function converge_kgrid(nkpts; Ecut, tol)\n energies = [run_scf(; nkpt, tol=tol/10, Ecut).energies.total for nkpt in nkpts]\n errors = abs.(energies[1:end-1] .- energies[end])\n iconv = findfirst(errors .< tol)\n (; nkpts=nkpts[1:end-1], errors, nkpt_conv=nkpts[iconv])\nend\nresult = converge_kgrid(nkpts; Ecut=mean(Ecuts), tol)\nnkpt_conv = result.nkpt_conv","category":"page"},{"location":"examples/convergence_study/","page":"Performing a convergence study","title":"Performing a convergence study","text":"… and plot the obtained convergence:","category":"page"},{"location":"examples/convergence_study/","page":"Performing a convergence study","title":"Performing a convergence study","text":"using Plots\nplot(result.nkpts, result.errors, dpi=300, lw=3, m=:o, yaxis=:log,\n xlabel=\"k-grid\", ylabel=\"energy absolute error\")","category":"page"},{"location":"examples/convergence_study/","page":"Performing a convergence study","title":"Performing a convergence study","text":"We continue to do the convergence in Ecut using the suggested k-point grid.","category":"page"},{"location":"examples/convergence_study/","page":"Performing a convergence study","title":"Performing a convergence study","text":"function converge_Ecut(Ecuts; nkpt, tol)\n energies = [run_scf(; nkpt, tol=tol/100, Ecut).energies.total for Ecut in Ecuts]\n errors = abs.(energies[1:end-1] .- energies[end])\n iconv = findfirst(errors .< tol)\n (; Ecuts=Ecuts[1:end-1], errors, Ecut_conv=Ecuts[iconv])\nend\nresult = converge_Ecut(Ecuts; nkpt=nkpt_conv, tol)\nEcut_conv = result.Ecut_conv","category":"page"},{"location":"examples/convergence_study/","page":"Performing a convergence study","title":"Performing a convergence study","text":"… and plot it:","category":"page"},{"location":"examples/convergence_study/","page":"Performing a convergence study","title":"Performing a convergence study","text":"plot(result.Ecuts, result.errors, dpi=300, lw=3, m=:o, yaxis=:log,\n xlabel=\"Ecut\", ylabel=\"energy absolute error\")","category":"page"},{"location":"examples/convergence_study/#A-more-realistic-example.","page":"Performing a convergence study","title":"A more realistic example.","text":"","category":"section"},{"location":"examples/convergence_study/","page":"Performing a convergence study","title":"Performing a convergence study","text":"Repeating the above exercise for more realistic settings, namely …","category":"page"},{"location":"examples/convergence_study/","page":"Performing a convergence study","title":"Performing a convergence study","text":"tol = 1e-4 # Tolerance to which we target to converge\nnkpts = 1:20 # K-point range checked for convergence\nEcuts = 20:1:50;\nnothing #hide","category":"page"},{"location":"examples/convergence_study/","page":"Performing a convergence study","title":"Performing a convergence study","text":"…one obtains the following two plots for the convergence in kpoints and Ecut.","category":"page"},{"location":"examples/convergence_study/","page":"Performing a convergence study","title":"Performing a convergence study","text":"<img src=\"../../assets/convergence_study_kgrid.png\" width=600 height=400 />\n<img src=\"../../assets/convergence_study_ecut.png\" width=600 height=400 />","category":"page"},{"location":"examples/energy_cutoff_smearing/","page":"Energy cutoff smearing","title":"Energy cutoff smearing","text":"EditURL = \"https://github.com/JuliaMolSim/DFTK.jl/blob/master/examples/energy_cutoff_smearing.jl\"","category":"page"},{"location":"examples/energy_cutoff_smearing/#Energy-cutoff-smearing","page":"Energy cutoff smearing","title":"Energy cutoff smearing","text":"","category":"section"},{"location":"examples/energy_cutoff_smearing/","page":"Energy cutoff smearing","title":"Energy cutoff smearing","text":"(Image: ) (Image: )","category":"page"},{"location":"examples/energy_cutoff_smearing/","page":"Energy cutoff smearing","title":"Energy cutoff smearing","text":"A technique that has been employed in the literature to ensure smooth energy bands for finite Ecut values is energy cutoff smearing.","category":"page"},{"location":"examples/energy_cutoff_smearing/","page":"Energy cutoff smearing","title":"Energy cutoff smearing","text":"As recalled in the Problems and plane-wave discretization section, the energy of periodic systems is computed by solving eigenvalue problems of the form","category":"page"},{"location":"examples/energy_cutoff_smearing/","page":"Energy cutoff smearing","title":"Energy cutoff smearing","text":"H_k u_k = ε_k u_k","category":"page"},{"location":"examples/energy_cutoff_smearing/","page":"Energy cutoff smearing","title":"Energy cutoff smearing","text":"for each k-point in the first Brillouin zone of the system. Each of these eigenvalue problem is discretized with a plane-wave basis mathcalB_k^E_c=x e^iG x G mathcalR^* k+G^2 2E_c whose size highly depends on the choice of k-point, cell size or cutoff energy rm E_c (the Ecut parameter of DFTK). As a result, energy bands computed along a k-path in the Brillouin zone or with respect to the system's unit cell volume - in the case of geometry optimization for example - display big irregularities when Ecut is taken too small.","category":"page"},{"location":"examples/energy_cutoff_smearing/","page":"Energy cutoff smearing","title":"Energy cutoff smearing","text":"Here is for example the variation of the ground state energy of face cubic centred (FCC) silicon with respect to its lattice parameter, around the experimental lattice constant.","category":"page"},{"location":"examples/energy_cutoff_smearing/","page":"Energy cutoff smearing","title":"Energy cutoff smearing","text":"using DFTK\nusing Statistics\n\na0 = 10.26 # Experimental lattice constant of silicon in bohr\na_list = range(a0 - 1/2, a0 + 1/2; length=20)\n\nfunction compute_ground_state_energy(a; Ecut, kgrid, kinetic_blowup, kwargs...)\n lattice = a / 2 * [[0 1 1.];\n [1 0 1.];\n [1 1 0.]]\n Si = ElementPsp(:Si, psp=load_psp(\"hgh/lda/Si-q4\"))\n atoms = [Si, Si]\n positions = [ones(3)/8, -ones(3)/8]\n model = model_PBE(lattice, atoms, positions; kinetic_blowup)\n basis = PlaneWaveBasis(model; Ecut, kgrid)\n self_consistent_field(basis; callback=identity, kwargs...).energies.total\nend\n\nEcut = 5 # Very low Ecut to display big irregularities\nkgrid = (2, 2, 2) # Very sparse k-grid to speed up convergence\nE0_naive = compute_ground_state_energy.(a_list; kinetic_blowup=BlowupIdentity(), Ecut, kgrid);\nnothing #hide","category":"page"},{"location":"examples/energy_cutoff_smearing/","page":"Energy cutoff smearing","title":"Energy cutoff smearing","text":"To be compared with the same computation for a high Ecut=100. The naive approximation of the energy is shifted for the legibility of the plot.","category":"page"},{"location":"examples/energy_cutoff_smearing/","page":"Energy cutoff smearing","title":"Energy cutoff smearing","text":"E0_ref = [-7.839775223322127, -7.843031658146996, -7.845961005280923,\n -7.848576991754026, -7.850892888614151, -7.852921532056932,\n -7.854675317792186, -7.85616622262217, -7.85740584131599,\n -7.858405359984107, -7.859175611288143, -7.859727053496513,\n -7.860069804791132, -7.860213631865354, -7.8601679947736915,\n -7.859942011410533, -7.859544518721661, -7.858984032385052,\n -7.858268793303855, -7.857406769423708]\n\nusing Plots\nshift = mean(abs.(E0_naive .- E0_ref))\np = plot(a_list, E0_naive .- shift, label=\"Ecut=5\", xlabel=\"lattice parameter a (bohr)\",\n ylabel=\"Ground state energy (Ha)\", color=1)\nplot!(p, a_list, E0_ref, label=\"Ecut=100\", color=2)","category":"page"},{"location":"examples/energy_cutoff_smearing/","page":"Energy cutoff smearing","title":"Energy cutoff smearing","text":"The problem of non-smoothness of the approximated energy is typically avoided by taking a large enough Ecut, at the cost of a high computation time. Another method consist in introducing a modified kinetic term defined through the data of a blow-up function, a method which is also referred to as \"energy cutoff smearing\". DFTK features energy cutoff smearing using the CHV blow-up function introduced in [CHV2022] that is mathematically ensured to provide C^2 regularity of the energy bands.","category":"page"},{"location":"examples/energy_cutoff_smearing/","page":"Energy cutoff smearing","title":"Energy cutoff smearing","text":"[CHV2022]: ","category":"page"},{"location":"examples/energy_cutoff_smearing/","page":"Energy cutoff smearing","title":"Energy cutoff smearing","text":"Éric Cancès, Muhammad Hassan and Laurent Vidal Modified-operator method for the calculation of band diagrams of crystalline materials, 2022. arXiv preprint.","category":"page"},{"location":"examples/energy_cutoff_smearing/","page":"Energy cutoff smearing","title":"Energy cutoff smearing","text":"Let us lauch the computation again with the modified kinetic term.","category":"page"},{"location":"examples/energy_cutoff_smearing/","page":"Energy cutoff smearing","title":"Energy cutoff smearing","text":"E0_modified = compute_ground_state_energy.(a_list; kinetic_blowup=BlowupCHV(), Ecut, kgrid);\nnothing #hide","category":"page"},{"location":"examples/energy_cutoff_smearing/","page":"Energy cutoff smearing","title":"Energy cutoff smearing","text":"note: Abinit energy cutoff smearing option\nFor the sake of completeness, DFTK also provides the blow-up function BlowupAbinit proposed in the Abinit quantum chemistry code. This function depends on a parameter Ecutsm fixed by the user (see Abinit user guide). For the right choice of Ecutsm, BlowupAbinit corresponds to the BlowupCHV approach with coefficients ensuring C^1 regularity. To choose BlowupAbinit, pass kinetic_blowup=BlowupAbinit(Ecutsm) to the model constructors.","category":"page"},{"location":"examples/energy_cutoff_smearing/","page":"Energy cutoff smearing","title":"Energy cutoff smearing","text":"We can know compare the approximation of the energy as well as the estimated lattice constant for each strategy.","category":"page"},{"location":"examples/energy_cutoff_smearing/","page":"Energy cutoff smearing","title":"Energy cutoff smearing","text":"estimate_a0(E0_values) = a_list[findmin(E0_values)[2]]\na0_naive, a0_ref, a0_modified = estimate_a0.([E0_naive, E0_ref, E0_modified])\n\nshift = mean(abs.(E0_modified .- E0_ref)) # Shift for legibility of the plot\nplot!(p, a_list, E0_modified .- shift, label=\"Ecut=5 + BlowupCHV\", color=3)\nvline!(p, [a0], label=\"experimental a0\", linestyle=:dash, linecolor=:black)\nvline!(p, [a0_naive], label=\"a0 Ecut=5\", linestyle=:dash, color=1)\nvline!(p, [a0_ref], label=\"a0 Ecut=100\", linestyle=:dash, color=2)\nvline!(p, [a0_modified], label=\"a0 Ecut=5 + BlowupCHV\", linestyle=:dash, color=3)","category":"page"},{"location":"examples/energy_cutoff_smearing/","page":"Energy cutoff smearing","title":"Energy cutoff smearing","text":"The smoothed curve obtained with the modified kinetic term allow to clearly designate a minimal value of the energy with respect to the lattice parameter a, even with the low Ecut=5 Ha.","category":"page"},{"location":"examples/energy_cutoff_smearing/","page":"Energy cutoff smearing","title":"Energy cutoff smearing","text":"println(\"Error of approximation of the reference a0 with modified kinetic term:\"*\n \" $(round((a0_modified - a0_ref)*100/a0_ref, digits=5))%\")","category":"page"},{"location":"publications/#Publications","page":"Publications","title":"Publications","text":"","category":"section"},{"location":"publications/","page":"Publications","title":"Publications","text":"Since DFTK is mostly developed as part of academic research, we would greatly appreciate if you cite our research papers as appropriate. See the CITATION.bib in the root of the DFTK repo and the publication list on this page for relevant citations. The current DFTK reference paper to cite is","category":"page"},{"location":"publications/","page":"Publications","title":"Publications","text":"@article{DFTKjcon,\n author = {Michael F. Herbst and Antoine Levitt and Eric Cancès},\n doi = {10.21105/jcon.00069},\n journal = {Proc. JuliaCon Conf.},\n title = {DFTK: A Julian approach for simulating electrons in solids},\n volume = {3},\n pages = {69},\n year = {2021},\n}","category":"page"},{"location":"publications/","page":"Publications","title":"Publications","text":"Additionally the following publications describe DFTK or one of its algorithms:","category":"page"},{"location":"publications/","page":"Publications","title":"Publications","text":"E. Cancès, M. F. Herbst, G. Kemlin, A. Levitt and B. Stamm. Numerical stability and efficiency of response property calculations in density functional theory (Submitted). ArXiv:2210.04512. (Supplementary material and computational scripts).\nE. Cancès, M. Hassan and L. Vidal. Modified-Operator Method for the Calculation of Band Diagrams of Crystalline Materials. (Submitted). ArXiv:2210.00442.\nM. F. Herbst and A. Levitt. A robust and efficient line search for self-consistent field iterations Journal of Computational Physics, 459, 111127 (2022). ArXiv:2109.14018. (Supplementary material and computational scripts).\nM. F. Herbst, A. Levitt and E. Cancès. DFTK: A Julian approach for simulating electrons in solids. JuliaCon Proceedings, 3, 69 (2021).\nM. F. Herbst and A. Levitt. Black-box inhomogeneous preconditioning for self-consistent field iterations in density functional theory. Journal of Physics: Condensed Matter, 33, 085503 (2021). ArXiv:2009.01665. (Supplementary material and computational scripts).","category":"page"},{"location":"publications/#Research-conducted-with-DFTK","page":"Publications","title":"Research conducted with DFTK","text":"","category":"section"},{"location":"publications/","page":"Publications","title":"Publications","text":"The following publications report research employing DFTK as a core component. Feel free to drop us a line if you want your work to be added here.","category":"page"},{"location":"publications/","page":"Publications","title":"Publications","text":"J. Cazalis. Dirac cones for a mean-field model of graphene (Submitted). ArXiv:2207.09893. (Computational script).\nE. Cancès, L. Garrigue, D. Gontier. A simple derivation of moiré-scale continuous models for twisted bilayer graphene (Submitted). ArXiv:2206.05685.\nE. Cancès, G. Dusson, G. Kemlin and A. Levitt. Practical error bounds for properties in plane-wave electronic structure calculations SIAM Journal on Scientific Computing, 44, B1312 (2022). ArXiv:2111.01470. (Supplementary material and computational scripts).\nG. Dusson, I. Sigal and B. Stamm. Analysis of the Feshbach-Schur method for the Fourier spectral discretizations of Schrödinger operators Mathematics of Computation, ?, ?? (2022). ArXiv:2008.10871.\nE. Cancès, G. Kemlin and A. Levitt. Convergence analysis of direct minimization and self-consistent iterations SIAM Journal on Matrix Analysis and Applications, 42, 243 (2021). ArXiv:2004.09088. (Computational script).\nM. F. Herbst, A. Levitt and E. Cancès. A posteriori error estimation for the non-self-consistent Kohn-Sham equations. Faraday Discussions, 224, 227 (2020). ArXiv:2004.13549. (Reference implementation).","category":"page"},{"location":"school2022/#DFTK-School-2022","page":"DFTK School 2022","title":"DFTK School 2022","text":"","category":"section"},{"location":"tricks/parallelization/#Timings-and-parallelization","page":"Timings and parallelization","title":"Timings and parallelization","text":"","category":"section"},{"location":"tricks/parallelization/","page":"Timings and parallelization","title":"Timings and parallelization","text":"This section summarizes the options DFTK offers to monitor and influence performance of the code.","category":"page"},{"location":"tricks/parallelization/","page":"Timings and parallelization","title":"Timings and parallelization","text":"using DFTK\na = 10.26 # Silicon lattice constant in Bohr\nlattice = a / 2 * [[0 1 1.];\n [1 0 1.];\n [1 1 0.]]\nSi = ElementPsp(:Si, psp=load_psp(\"hgh/lda/Si-q4\"))\natoms = [Si, Si]\npositions = [ones(3)/8, -ones(3)/8]\n\nmodel = model_LDA(lattice, atoms, positions)\nbasis = PlaneWaveBasis(model; Ecut=5, kgrid=[2, 2, 2])\n\nDFTK.reset_timer!(DFTK.timer)\nscfres = self_consistent_field(basis, tol=1e-5)","category":"page"},{"location":"tricks/parallelization/#Timing-measurements","page":"Timings and parallelization","title":"Timing measurements","text":"","category":"section"},{"location":"tricks/parallelization/","page":"Timings and parallelization","title":"Timings and parallelization","text":"By default DFTK uses TimerOutputs.jl to record timings, memory allocations and the number of calls for selected routines inside the code. These numbers are accessible in the object DFTK.timer. Since the timings are automatically accumulated inside this datastructure, any timing measurement should first reset this timer before running the calculation of interest.","category":"page"},{"location":"tricks/parallelization/","page":"Timings and parallelization","title":"Timings and parallelization","text":"For example to measure the timing of an SCF:","category":"page"},{"location":"tricks/parallelization/","page":"Timings and parallelization","title":"Timings and parallelization","text":"DFTK.reset_timer!(DFTK.timer)\nscfres = self_consistent_field(basis, tol=1e-5)\n\nDFTK.timer","category":"page"},{"location":"tricks/parallelization/","page":"Timings and parallelization","title":"Timings and parallelization","text":"The output produced when printing or displaying the DFTK.timer now shows a nice table summarising total time and allocations as well as a breakdown over individual routines.","category":"page"},{"location":"tricks/parallelization/","page":"Timings and parallelization","title":"Timings and parallelization","text":"note: Timing measurements and stack traces\nTiming measurements have the unfortunate disadvantage that they alter the way stack traces look making it sometimes harder to find errors when debugging. For this reason timing measurements can be disabled completely (i.e. not even compiled into the code) by setting the environment variable DFTK_TIMING to \"0\" or \"false\". For this to take effect recompiling all DFTK (including the precompile cache) is needed.","category":"page"},{"location":"tricks/parallelization/#Rough-timing-estimates","page":"Timings and parallelization","title":"Rough timing estimates","text":"","category":"section"},{"location":"tricks/parallelization/","page":"Timings and parallelization","title":"Timings and parallelization","text":"A very (very) rough estimate of the time per SCF step (in seconds) can be obtained with the following function. The function assumes that FFTs are the limiting operation and that no parallelisation is employed.","category":"page"},{"location":"tricks/parallelization/","page":"Timings and parallelization","title":"Timings and parallelization","text":"function estimate_time_per_scf_step(basis::PlaneWaveBasis)\n # Super rough figure from various tests on cluster, laptops, ... on a 128^3 FFT grid.\n time_per_FFT_per_grid_point = 30 #= ms =# / 1000 / 128^3\n\n (time_per_FFT_per_grid_point\n * prod(basis.fft_size)\n * length(basis.kpoints)\n * div(basis.model.n_electrons, DFTK.filled_occupation(basis.model), RoundUp)\n * 8 # mean number of FFT steps per state per k-point per iteration\n )\nend\n\n\"Time per SCF (s): $(estimate_time_per_scf_step(basis))\"","category":"page"},{"location":"tricks/parallelization/#Options-for-parallelization","page":"Timings and parallelization","title":"Options for parallelization","text":"","category":"section"},{"location":"tricks/parallelization/","page":"Timings and parallelization","title":"Timings and parallelization","text":"At the moment DFTK offers two ways to parallelize a calculation, firstly shared-memory parallelism using threading and secondly multiprocessing using MPI (via the MPI.jl Julia interface). MPI-based parallelism is currently only over k-points, such that it cannot be used for calculations with only a single k-point. Otherwise combining both forms of parallelism is possible as well.","category":"page"},{"location":"tricks/parallelization/","page":"Timings and parallelization","title":"Timings and parallelization","text":"The scaling of both forms of parallelism for a number of test cases is demonstrated in the following figure. These values were obtained using DFTK version 0.1.17 and Julia 1.6 and the precise scalings will likely be different depending on architecture, DFTK or Julia version. The rough trends should, however, be similar.","category":"page"},{"location":"tricks/parallelization/","page":"Timings and parallelization","title":"Timings and parallelization","text":"<img src=\"../scaling.png\" width=750 />","category":"page"},{"location":"tricks/parallelization/","page":"Timings and parallelization","title":"Timings and parallelization","text":"The MPI-based parallelization strategy clearly shows a superior scaling and should be preferred if available.","category":"page"},{"location":"tricks/parallelization/#MPI-based-parallelism","page":"Timings and parallelization","title":"MPI-based parallelism","text":"","category":"section"},{"location":"tricks/parallelization/","page":"Timings and parallelization","title":"Timings and parallelization","text":"Currently DFTK uses MPI to distribute on k-points only. This implies that calculations with only a single k-point cannot use make use of this. For details on setting up and configuring MPI with Julia see the MPI.jl documentation.","category":"page"},{"location":"tricks/parallelization/","page":"Timings and parallelization","title":"Timings and parallelization","text":"First disable all threading inside DFTK, by adding the following to your script running the DFTK calculation:\nusing DFTK\ndisable_threading()\nRun Julia in parallel using the mpiexecjl wrapper script from MPI.jl:\nmpiexecjl -np 16 julia myscript.jl\nIn this -np 16 tells MPI to use 16 processes and -t 1 tells Julia to use one thread only. Notice that we use mpiexecjl to automatically select the mpiexec compatible with the MPI version used by MPI.jl.","category":"page"},{"location":"tricks/parallelization/","page":"Timings and parallelization","title":"Timings and parallelization","text":"As usual with MPI printing will be garbled. You can use","category":"page"},{"location":"tricks/parallelization/","page":"Timings and parallelization","title":"Timings and parallelization","text":"DFTK.mpi_master() || (redirect_stdout(); redirect_stderr())","category":"page"},{"location":"tricks/parallelization/","page":"Timings and parallelization","title":"Timings and parallelization","text":"at the top of your script to disable printing on all processes but one.","category":"page"},{"location":"tricks/parallelization/","page":"Timings and parallelization","title":"Timings and parallelization","text":"info: MPI-based parallelism not fully supported\nWhile standard procedures (such as the SCF or band structure calculations) fully support MPI, not all routines of DFTK are compatible with MPI yet and will throw an error when being called in an MPI-parallel run. In most cases there is no intrinsic limitation it just has not yet been implemented. If you require MPI in one of our routines, where this is not yet supported, feel free to open an issue on github or otherwise get in touch.","category":"page"},{"location":"tricks/parallelization/#Thread-based-parallelism","page":"Timings and parallelization","title":"Thread-based parallelism","text":"","category":"section"},{"location":"tricks/parallelization/","page":"Timings and parallelization","title":"Timings and parallelization","text":"Threading in DFTK currently happens on multiple layers distributing the workload over different k-points, bands or within an FFT or BLAS call between threads. At its current stage our scaling for thread-based parallelism is worse compared MPI-based and therefore the parallelism described here should only be used if no other option exists. To use thread-based parallelism proceed as follows:","category":"page"},{"location":"tricks/parallelization/","page":"Timings and parallelization","title":"Timings and parallelization","text":"Ensure that threading is properly setup inside DFTK by adding to the script running the DFTK calculation:\nusing DFTK\nsetup_threading()\nThis disables FFT threading and sets the number of BLAS threads to the number of Julia threads.\nRun Julia passing the desired number of threads using the flag -t:\njulia -t 8 myscript.jl","category":"page"},{"location":"tricks/parallelization/","page":"Timings and parallelization","title":"Timings and parallelization","text":"For some cases (e.g. a single k-point, fewish bands and a large FFT grid) it can be advantageous to add threading inside the FFTs as well. One example is the Caffeine calculation in the above scaling plot. In order to do so just call setup_threading(n_fft=2), which will select two FFT threads. More than two FFT threads is rarely useful.","category":"page"},{"location":"tricks/parallelization/#Advanced-threading-tweaks","page":"Timings and parallelization","title":"Advanced threading tweaks","text":"","category":"section"},{"location":"tricks/parallelization/","page":"Timings and parallelization","title":"Timings and parallelization","text":"The default threading setup done by setup_threading is to select one FFT thread and the same number of BLAS and Julia threads. This section provides some info in case you want to change these defaults.","category":"page"},{"location":"tricks/parallelization/#BLAS-threads","page":"Timings and parallelization","title":"BLAS threads","text":"","category":"section"},{"location":"tricks/parallelization/","page":"Timings and parallelization","title":"Timings and parallelization","text":"All BLAS calls in Julia go through a parallelized OpenBlas or MKL (with MKL.jl. Generally threading in BLAS calls is far from optimal and the default settings can be pretty bad. For example for CPUs with hyper threading enabled, the default number of threads seems to equal the number of virtual cores. Still, BLAS calls typically take second place in terms of the share of runtime they make up (between 10% and 20%). Of note many of these do not take place on matrices of the size of the full FFT grid, but rather only in a subspace (e.g. orthogonalization, Rayleigh-Ritz, ...) such that parallelization is either anyway disabled by the BLAS library or not very effective. To set the number of BLAS threads use","category":"page"},{"location":"tricks/parallelization/","page":"Timings and parallelization","title":"Timings and parallelization","text":"using LinearAlgebra\nBLAS.set_num_threads(N)","category":"page"},{"location":"tricks/parallelization/","page":"Timings and parallelization","title":"Timings and parallelization","text":"where N is the number of threads you desire. To check the number of BLAS threads currently used, you can use","category":"page"},{"location":"tricks/parallelization/","page":"Timings and parallelization","title":"Timings and parallelization","text":"Int(ccall((BLAS.@blasfunc(openblas_get_num_threads), BLAS.libblas), Cint, ()))","category":"page"},{"location":"tricks/parallelization/","page":"Timings and parallelization","title":"Timings and parallelization","text":"or (from Julia 1.6) simply BLAS.get_num_threads().","category":"page"},{"location":"tricks/parallelization/#Julia-threads","page":"Timings and parallelization","title":"Julia threads","text":"","category":"section"},{"location":"tricks/parallelization/","page":"Timings and parallelization","title":"Timings and parallelization","text":"On top of BLAS threading DFTK uses Julia threads (Thread.@threads) in a couple of places to parallelize over k-points (density computation) or bands (Hamiltonian application). The number of threads used for these aspects is controlled by the flag -t passed to Julia or the environment variable JULIA_NUM_THREADS. To check the number of Julia threads use Threads.nthreads().","category":"page"},{"location":"tricks/parallelization/#FFT-threads","page":"Timings and parallelization","title":"FFT threads","text":"","category":"section"},{"location":"tricks/parallelization/","page":"Timings and parallelization","title":"Timings and parallelization","text":"Since FFT threading is only used in DFTK inside the regions already parallelized by Julia threads, setting FFT threads to something larger than 1 is rarely useful if a sensible number of Julia threads has been chosen. Still, to explicitly set the FFT threads use","category":"page"},{"location":"tricks/parallelization/","page":"Timings and parallelization","title":"Timings and parallelization","text":"using FFTW\nFFTW.set_num_threads(N)","category":"page"},{"location":"tricks/parallelization/","page":"Timings and parallelization","title":"Timings and parallelization","text":"where N is the number of threads you desire. By default no FFT threads are used, which is almost always the best choice.","category":"page"},{"location":"examples/error_estimates_forces/","page":"Practical error bounds for the forces","title":"Practical error bounds for the forces","text":"EditURL = \"https://github.com/JuliaMolSim/DFTK.jl/blob/master/examples/error_estimates_forces.jl\"","category":"page"},{"location":"examples/error_estimates_forces/#Practical-error-bounds-for-the-forces","page":"Practical error bounds for the forces","title":"Practical error bounds for the forces","text":"","category":"section"},{"location":"examples/error_estimates_forces/","page":"Practical error bounds for the forces","title":"Practical error bounds for the forces","text":"(Image: ) (Image: )","category":"page"},{"location":"examples/error_estimates_forces/","page":"Practical error bounds for the forces","title":"Practical error bounds for the forces","text":"This is a simple example showing how to compute error estimates for the forces on a rm TiO_2 molecule, from which we can either compute asymptotically valid error bounds or increase the precision on the computation of the forces.","category":"page"},{"location":"examples/error_estimates_forces/","page":"Practical error bounds for the forces","title":"Practical error bounds for the forces","text":"The strategy we follow is described with more details in [CDKL2021] and we will use in comments the density matrices framework. We will also needs operators and functions from src/scf/newton.jl.","category":"page"},{"location":"examples/error_estimates_forces/","page":"Practical error bounds for the forces","title":"Practical error bounds for the forces","text":"[CDKL2021]: E. Cancès, G. Dusson, G. Kemlin, and A. Levitt Practical error bounds for properties in plane-wave electronic structure calculations Preprint, 2021. arXiv","category":"page"},{"location":"examples/error_estimates_forces/","page":"Practical error bounds for the forces","title":"Practical error bounds for the forces","text":"using DFTK\nusing Printf\nusing LinearAlgebra\nusing ForwardDiff\nusing LinearMaps\nusing IterativeSolvers","category":"page"},{"location":"examples/error_estimates_forces/#Setup","page":"Practical error bounds for the forces","title":"Setup","text":"","category":"section"},{"location":"examples/error_estimates_forces/","page":"Practical error bounds for the forces","title":"Practical error bounds for the forces","text":"We setup manually the rm TiO_2 configuration from Materials Project.","category":"page"},{"location":"examples/error_estimates_forces/","page":"Practical error bounds for the forces","title":"Practical error bounds for the forces","text":"Ti = ElementPsp(:Ti, psp=load_psp(\"hgh/lda/ti-q4.hgh\"))\nO = ElementPsp(:O, psp=load_psp(\"hgh/lda/o-q6.hgh\"))\natoms = [Ti, Ti, O, O, O, O]\npositions = [[0.5, 0.5, 0.5], # Ti\n [0.0, 0.0, 0.0], # Ti\n [0.19542, 0.80458, 0.5], # O\n [0.80458, 0.19542, 0.5], # O\n [0.30458, 0.30458, 0.0], # O\n [0.69542, 0.69542, 0.0]] # O\nlattice = [[8.79341 0.0 0.0];\n [0.0 8.79341 0.0];\n [0.0 0.0 5.61098]];\nnothing #hide","category":"page"},{"location":"examples/error_estimates_forces/","page":"Practical error bounds for the forces","title":"Practical error bounds for the forces","text":"We apply a small displacement to one of the rm Ti atoms to get nonzero forces.","category":"page"},{"location":"examples/error_estimates_forces/","page":"Practical error bounds for the forces","title":"Practical error bounds for the forces","text":"positions[1] .+= [-0.022, 0.028, 0.035]","category":"page"},{"location":"examples/error_estimates_forces/","page":"Practical error bounds for the forces","title":"Practical error bounds for the forces","text":"We build a model with one k-point only, not too high Ecut_ref and small tolerance to limit computational time. These parameters can be increased for more precise results.","category":"page"},{"location":"examples/error_estimates_forces/","page":"Practical error bounds for the forces","title":"Practical error bounds for the forces","text":"model = model_LDA(lattice, atoms, positions)\nkgrid = [1, 1, 1]\nEcut_ref = 35\nbasis_ref = PlaneWaveBasis(model; Ecut=Ecut_ref, kgrid)\ntol = 1e-5;\nnothing #hide","category":"page"},{"location":"examples/error_estimates_forces/#Computations","page":"Practical error bounds for the forces","title":"Computations","text":"","category":"section"},{"location":"examples/error_estimates_forces/","page":"Practical error bounds for the forces","title":"Practical error bounds for the forces","text":"We compute the reference solution P_* from which we will compute the references forces.","category":"page"},{"location":"examples/error_estimates_forces/","page":"Practical error bounds for the forces","title":"Practical error bounds for the forces","text":"scfres_ref = self_consistent_field(basis_ref; tol, callback=identity)\nψ_ref, _ = DFTK.select_occupied_orbitals(basis_ref, scfres_ref.ψ,\n scfres_ref.occupation);\nnothing #hide","category":"page"},{"location":"examples/error_estimates_forces/","page":"Practical error bounds for the forces","title":"Practical error bounds for the forces","text":"We compute a variational approximation of the reference solution with smaller Ecut. ψr, ρr and Er are the quantities computed with Ecut and then extended to the reference grid.","category":"page"},{"location":"examples/error_estimates_forces/","page":"Practical error bounds for the forces","title":"Practical error bounds for the forces","text":"note: Choice of convergence parameters\nBe careful to choose Ecut not too close to Ecut_ref. Note also that the current choice Ecut_ref = 35 is such that the reference solution is not converged and Ecut = 15 is such that the asymptotic regime (crucial to validate the approach) is barely established.","category":"page"},{"location":"examples/error_estimates_forces/","page":"Practical error bounds for the forces","title":"Practical error bounds for the forces","text":"Ecut = 15\nbasis = PlaneWaveBasis(model; Ecut, kgrid)\nscfres = self_consistent_field(basis; tol, callback=identity)\nψr = DFTK.transfer_blochwave(scfres.ψ, basis, basis_ref)\nρr = compute_density(basis_ref, ψr, scfres.occupation)\nEr, hamr = energy_hamiltonian(basis_ref, ψr, scfres.occupation; ρ=ρr);\nnothing #hide","category":"page"},{"location":"examples/error_estimates_forces/","page":"Practical error bounds for the forces","title":"Practical error bounds for the forces","text":"We then compute several quantities that we need to evaluate the error bounds.","category":"page"},{"location":"examples/error_estimates_forces/","page":"Practical error bounds for the forces","title":"Practical error bounds for the forces","text":"Compute the residual R(P), and remove the virtual orbitals, as required in src/scf/newton.jl.","category":"page"},{"location":"examples/error_estimates_forces/","page":"Practical error bounds for the forces","title":"Practical error bounds for the forces","text":"res = DFTK.compute_projected_gradient(basis_ref, ψr, scfres.occupation)\nres, occ = DFTK.select_occupied_orbitals(basis_ref, res, scfres.occupation)\nψr, _ = DFTK.select_occupied_orbitals(basis_ref, ψr, scfres.occupation);\nnothing #hide","category":"page"},{"location":"examples/error_estimates_forces/","page":"Practical error bounds for the forces","title":"Practical error bounds for the forces","text":"Compute the error P-P_* on the associated orbitals ϕ-ψ after aligning them: this is done by solving min ϕ - ψU for U unitary matrix of size NN (N being the number of electrons) whose solution is U = S(S^*S)^-12 where S is the overlap matrix ψ^*ϕ.","category":"page"},{"location":"examples/error_estimates_forces/","page":"Practical error bounds for the forces","title":"Practical error bounds for the forces","text":"function compute_error(basis, ϕ, ψ)\n map(zip(ϕ, ψ)) do (ϕk, ψk)\n S = ψk'ϕk\n U = S*(S'S)^(-1/2)\n ϕk - ψk*U\n end\nend\nerr = compute_error(basis_ref, ψr, ψ_ref);\nnothing #hide","category":"page"},{"location":"examples/error_estimates_forces/","page":"Practical error bounds for the forces","title":"Practical error bounds for the forces","text":"Compute bm M^-1R(P) with bm M^-1 defined in [CDKL2021]:","category":"page"},{"location":"examples/error_estimates_forces/","page":"Practical error bounds for the forces","title":"Practical error bounds for the forces","text":"P = [PreconditionerTPA(basis_ref, kpt) for kpt in basis_ref.kpoints]\nmap(zip(P, ψr)) do (Pk, ψk)\n DFTK.precondprep!(Pk, ψk)\nend\nfunction apply_M(φk, Pk, δφnk, n)\n DFTK.proj_tangent_kpt!(δφnk, φk)\n δφnk = sqrt.(Pk.mean_kin[n] .+ Pk.kin) .* δφnk\n DFTK.proj_tangent_kpt!(δφnk, φk)\n δφnk = sqrt.(Pk.mean_kin[n] .+ Pk.kin) .* δφnk\n DFTK.proj_tangent_kpt!(δφnk, φk)\nend\nfunction apply_inv_M(φk, Pk, δφnk, n)\n DFTK.proj_tangent_kpt!(δφnk, φk)\n op(x) = apply_M(φk, Pk, x, n)\n function f_ldiv!(x, y)\n x .= DFTK.proj_tangent_kpt(y, φk)\n x ./= (Pk.mean_kin[n] .+ Pk.kin)\n DFTK.proj_tangent_kpt!(x, φk)\n end\n J = LinearMap{eltype(φk)}(op, size(δφnk, 1))\n δφnk = cg(J, δφnk, Pl=DFTK.FunctionPreconditioner(f_ldiv!),\n verbose=false, reltol=0, abstol=1e-15)\n DFTK.proj_tangent_kpt!(δφnk, φk)\nend\nfunction apply_metric(φ, P, δφ, A::Function)\n map(enumerate(δφ)) do (ik, δφk)\n Aδφk = similar(δφk)\n φk = φ[ik]\n for n = 1:size(δφk,2)\n Aδφk[:,n] = A(φk, P[ik], δφk[:,n], n)\n end\n Aδφk\n end\nend\nMres = apply_metric(ψr, P, res, apply_inv_M);\nnothing #hide","category":"page"},{"location":"examples/error_estimates_forces/","page":"Practical error bounds for the forces","title":"Practical error bounds for the forces","text":"We can now compute the modified residual R_rm Schur(P) using a Schur complement to approximate the error on low-frequencies[CDKL2021]:","category":"page"},{"location":"examples/error_estimates_forces/","page":"Practical error bounds for the forces","title":"Practical error bounds for the forces","text":"beginbmatrix\n(bm Ω + bm K)_11 (bm Ω + bm K)_12 \n0 bm M_22\nendbmatrix\nbeginbmatrix\nP_1 - P_*1 P_2-P_*2\nendbmatrix =\nbeginbmatrix\nR_1 R_2\nendbmatrix","category":"page"},{"location":"examples/error_estimates_forces/","page":"Practical error bounds for the forces","title":"Practical error bounds for the forces","text":"Compute the projection of the residual onto the high and low frequencies:","category":"page"},{"location":"examples/error_estimates_forces/","page":"Practical error bounds for the forces","title":"Practical error bounds for the forces","text":"resLF = DFTK.transfer_blochwave(res, basis_ref, basis)\nresHF = res - DFTK.transfer_blochwave(resLF, basis, basis_ref);\nnothing #hide","category":"page"},{"location":"examples/error_estimates_forces/","page":"Practical error bounds for the forces","title":"Practical error bounds for the forces","text":"Compute bm M^-1_22R_2(P):","category":"page"},{"location":"examples/error_estimates_forces/","page":"Practical error bounds for the forces","title":"Practical error bounds for the forces","text":"e2 = apply_metric(ψr, P, resHF, apply_inv_M);\nnothing #hide","category":"page"},{"location":"examples/error_estimates_forces/","page":"Practical error bounds for the forces","title":"Practical error bounds for the forces","text":"Compute the right hand side of the Schur system:","category":"page"},{"location":"examples/error_estimates_forces/","page":"Practical error bounds for the forces","title":"Practical error bounds for the forces","text":"# Rayleigh coefficients needed for `apply_Ω`\nΛ = map(enumerate(ψr)) do (ik, ψk)\n Hk = hamr.blocks[ik]\n Hψk = Hk * ψk\n ψk'Hψk\nend\nΩpKe2 = DFTK.apply_Ω(e2, ψr, hamr, Λ) .+ DFTK.apply_K(basis_ref, e2, ψr, ρr, occ)\nΩpKe2 = DFTK.transfer_blochwave(ΩpKe2, basis_ref, basis)\nrhs = resLF - ΩpKe2;\nnothing #hide","category":"page"},{"location":"examples/error_estimates_forces/","page":"Practical error bounds for the forces","title":"Practical error bounds for the forces","text":"Solve the Schur system to compute R_rm Schur(P): this is the most costly step, but inverting bmΩ + bmK on the small space has the same cost than the full SCF cycle on the small grid.","category":"page"},{"location":"examples/error_estimates_forces/","page":"Practical error bounds for the forces","title":"Practical error bounds for the forces","text":"ψ, _ = DFTK.select_occupied_orbitals(basis, scfres.ψ, scfres.occupation)\ne1 = DFTK.solve_ΩplusK(basis, ψ, rhs, occ; tol).δψ\ne1 = DFTK.transfer_blochwave(e1, basis, basis_ref)\nres_schur = e1 + Mres;\nnothing #hide","category":"page"},{"location":"examples/error_estimates_forces/#Error-estimates","page":"Practical error bounds for the forces","title":"Error estimates","text":"","category":"section"},{"location":"examples/error_estimates_forces/","page":"Practical error bounds for the forces","title":"Practical error bounds for the forces","text":"We start with different estimations of the forces:","category":"page"},{"location":"examples/error_estimates_forces/","page":"Practical error bounds for the forces","title":"Practical error bounds for the forces","text":"Force from the reference solution","category":"page"},{"location":"examples/error_estimates_forces/","page":"Practical error bounds for the forces","title":"Practical error bounds for the forces","text":"f_ref = compute_forces(scfres_ref)\nforces = Dict(\"F(P_*)\" => f_ref)\nrelerror = Dict(\"F(P_*)\" => 0.0)\ncompute_relerror(f) = norm(f - f_ref) / norm(f_ref);\nnothing #hide","category":"page"},{"location":"examples/error_estimates_forces/","page":"Practical error bounds for the forces","title":"Practical error bounds for the forces","text":"Force from the variational solution and relative error without any post-processing:","category":"page"},{"location":"examples/error_estimates_forces/","page":"Practical error bounds for the forces","title":"Practical error bounds for the forces","text":"f = compute_forces(scfres)\nforces[\"F(P)\"] = f\nrelerror[\"F(P)\"] = compute_relerror(f);\nnothing #hide","category":"page"},{"location":"examples/error_estimates_forces/","page":"Practical error bounds for the forces","title":"Practical error bounds for the forces","text":"We then try to improve F(P) using the first order linearization:","category":"page"},{"location":"examples/error_estimates_forces/","page":"Practical error bounds for the forces","title":"Practical error bounds for the forces","text":"F(P) = F(P_*) + rm dF(P)(P-P_*)","category":"page"},{"location":"examples/error_estimates_forces/","page":"Practical error bounds for the forces","title":"Practical error bounds for the forces","text":"To this end, we use the ForwardDiff.jl package to compute rm dF(P) using automatic differentiation.","category":"page"},{"location":"examples/error_estimates_forces/","page":"Practical error bounds for the forces","title":"Practical error bounds for the forces","text":"function df(basis, occupation, ψ, δψ, ρ)\n δρ = DFTK.compute_δρ(basis, ψ, δψ, occupation)\n ForwardDiff.derivative(ε -> compute_forces(basis, ψ.+ε.*δψ, occupation; ρ=ρ+ε.*δρ), 0)\nend;\nnothing #hide","category":"page"},{"location":"examples/error_estimates_forces/","page":"Practical error bounds for the forces","title":"Practical error bounds for the forces","text":"Computation of the forces by a linearization argument if we have access to the actual error P-P_*. Usually this is of course not the case, but this is the \"best\" improvement we can hope for with a linearisation, so we are aiming for this precision.","category":"page"},{"location":"examples/error_estimates_forces/","page":"Practical error bounds for the forces","title":"Practical error bounds for the forces","text":"df_err = df(basis_ref, occ, ψr, DFTK.proj_tangent(err, ψr), ρr)\nforces[\"F(P) - df(P)⋅(P-P_*)\"] = f - df_err\nrelerror[\"F(P) - df(P)⋅(P-P_*)\"] = compute_relerror(f - df_err);\nnothing #hide","category":"page"},{"location":"examples/error_estimates_forces/","page":"Practical error bounds for the forces","title":"Practical error bounds for the forces","text":"Computation of the forces by a linearization argument when replacing the error P-P_* by the modified residual R_rm Schur(P). The latter quantity is computable in practice.","category":"page"},{"location":"examples/error_estimates_forces/","page":"Practical error bounds for the forces","title":"Practical error bounds for the forces","text":"df_schur = df(basis_ref, occ, ψr, res_schur, ρr)\nforces[\"F(P) - df(P)⋅Rschur(P)\"] = f - df_schur\nrelerror[\"F(P) - df(P)⋅Rschur(P)\"] = compute_relerror(f - df_schur);\nnothing #hide","category":"page"},{"location":"examples/error_estimates_forces/","page":"Practical error bounds for the forces","title":"Practical error bounds for the forces","text":"Summary of all forces on the first atom (Ti)","category":"page"},{"location":"examples/error_estimates_forces/","page":"Practical error bounds for the forces","title":"Practical error bounds for the forces","text":"for (key, value) in pairs(forces)\n @printf(\"%30s = [%7.5f, %7.5f, %7.5f] (rel. error: %7.5f)\\n\",\n key, (value[1])..., relerror[key])\nend","category":"page"},{"location":"examples/error_estimates_forces/","page":"Practical error bounds for the forces","title":"Practical error bounds for the forces","text":"Notice how close the computable expression F(P) - rm dF(P)R_rm Schur(P) is to the best linearization ansatz F(P) - rm dF(P)(P-P_*).","category":"page"},{"location":"examples/collinear_magnetism/","page":"Collinear spin and magnetic systems","title":"Collinear spin and magnetic systems","text":"EditURL = \"https://github.com/JuliaMolSim/DFTK.jl/blob/master/examples/collinear_magnetism.jl\"","category":"page"},{"location":"examples/collinear_magnetism/#Collinear-spin-and-magnetic-systems","page":"Collinear spin and magnetic systems","title":"Collinear spin and magnetic systems","text":"","category":"section"},{"location":"examples/collinear_magnetism/","page":"Collinear spin and magnetic systems","title":"Collinear spin and magnetic systems","text":"(Image: ) (Image: )","category":"page"},{"location":"examples/collinear_magnetism/","page":"Collinear spin and magnetic systems","title":"Collinear spin and magnetic systems","text":"In this example we consider iron in the BCC phase. To show that this material is ferromagnetic we will model it once allowing collinear spin polarization and once without and compare the resulting SCF energies. In particular the ground state can only be found if collinear spins are allowed.","category":"page"},{"location":"examples/collinear_magnetism/","page":"Collinear spin and magnetic systems","title":"Collinear spin and magnetic systems","text":"First we setup BCC iron without spin polarization using a single iron atom inside the unit cell.","category":"page"},{"location":"examples/collinear_magnetism/","page":"Collinear spin and magnetic systems","title":"Collinear spin and magnetic systems","text":"using DFTK\n\na = 5.42352 # Bohr\nlattice = a / 2 * [[-1 1 1];\n [ 1 -1 1];\n [ 1 1 -1]]\natoms = [ElementPsp(:Fe, psp=load_psp(\"hgh/lda/Fe-q8.hgh\"))]\npositions = [zeros(3)];\nnothing #hide","category":"page"},{"location":"examples/collinear_magnetism/","page":"Collinear spin and magnetic systems","title":"Collinear spin and magnetic systems","text":"To get the ground-state energy we use an LDA model and rather moderate discretisation parameters.","category":"page"},{"location":"examples/collinear_magnetism/","page":"Collinear spin and magnetic systems","title":"Collinear spin and magnetic systems","text":"kgrid = [3, 3, 3] # k-point grid (Regular Monkhorst-Pack grid)\nEcut = 15 # kinetic energy cutoff in Hartree\nmodel_nospin = model_LDA(lattice, atoms, positions, temperature=0.01)\nbasis_nospin = PlaneWaveBasis(model_nospin; kgrid, Ecut)\n\nscfres_nospin = self_consistent_field(basis_nospin; tol=1e-4, mixing=KerkerDosMixing());\nnothing #hide","category":"page"},{"location":"examples/collinear_magnetism/","page":"Collinear spin and magnetic systems","title":"Collinear spin and magnetic systems","text":"scfres_nospin.energies","category":"page"},{"location":"examples/collinear_magnetism/","page":"Collinear spin and magnetic systems","title":"Collinear spin and magnetic systems","text":"Since we did not specify any initial magnetic moment on the iron atom, DFTK will automatically assume that a calculation with only spin-paired electrons should be performed. As a result the obtained ground state features no spin-polarization.","category":"page"},{"location":"examples/collinear_magnetism/","page":"Collinear spin and magnetic systems","title":"Collinear spin and magnetic systems","text":"Now we repeat the calculation, but give the iron atom an initial magnetic moment. For specifying the magnetic moment pass the desired excess of spin-up over spin-down electrons at each centre to the Model and the guess density functions. In this case we seek the state with as many spin-parallel d-electrons as possible. In our pseudopotential model the 8 valence electrons are 2 pair of s-electrons, 1 pair of d-electrons and 4 unpaired d-electrons giving a desired magnetic moment of 4 at the iron centre. The structure (i.e. pair mapping and order) of the magnetic_moments array needs to agree with the atoms array and 0 magnetic moments need to be specified as well.","category":"page"},{"location":"examples/collinear_magnetism/","page":"Collinear spin and magnetic systems","title":"Collinear spin and magnetic systems","text":"magnetic_moments = [4];\nnothing #hide","category":"page"},{"location":"examples/collinear_magnetism/","page":"Collinear spin and magnetic systems","title":"Collinear spin and magnetic systems","text":"tip: Units of the magnetisation and magnetic moments in DFTK\nUnlike all other quantities magnetisation and magnetic moments in DFTK are given in units of the Bohr magneton μ_B, which in atomic units has the value frac12. Since μ_B is (roughly) the magnetic moment of a single electron the advantage is that one can directly think of these quantities as the excess of spin-up electrons or spin-up electron density.","category":"page"},{"location":"examples/collinear_magnetism/","page":"Collinear spin and magnetic systems","title":"Collinear spin and magnetic systems","text":"We repeat the calculation using the same model as before. DFTK now detects the non-zero moment and switches to a collinear calculation.","category":"page"},{"location":"examples/collinear_magnetism/","page":"Collinear spin and magnetic systems","title":"Collinear spin and magnetic systems","text":"model = model_LDA(lattice, atoms, positions; magnetic_moments, temperature=0.01)\nbasis = PlaneWaveBasis(model; Ecut, kgrid)\nρ0 = guess_density(basis, magnetic_moments)\nscfres = self_consistent_field(basis, tol=1e-4; ρ=ρ0, mixing=KerkerDosMixing());\nnothing #hide","category":"page"},{"location":"examples/collinear_magnetism/","page":"Collinear spin and magnetic systems","title":"Collinear spin and magnetic systems","text":"scfres.energies","category":"page"},{"location":"examples/collinear_magnetism/","page":"Collinear spin and magnetic systems","title":"Collinear spin and magnetic systems","text":"note: Model and magnetic moments\nDFTK does not store the magnetic_moments inside the Model, but only uses them to determine the lattice symmetries. This step was taken to keep Model (which contains the physical model) independent of the details of the numerical details such as the initial guess for the spin density.","category":"page"},{"location":"examples/collinear_magnetism/","page":"Collinear spin and magnetic systems","title":"Collinear spin and magnetic systems","text":"In direct comparison we notice the first, spin-paired calculation to be a little higher in energy","category":"page"},{"location":"examples/collinear_magnetism/","page":"Collinear spin and magnetic systems","title":"Collinear spin and magnetic systems","text":"println(\"No magnetization: \", scfres_nospin.energies.total)\nprintln(\"Magnetic case: \", scfres.energies.total)\nprintln(\"Difference: \", scfres.energies.total - scfres_nospin.energies.total);\nnothing #hide","category":"page"},{"location":"examples/collinear_magnetism/","page":"Collinear spin and magnetic systems","title":"Collinear spin and magnetic systems","text":"Notice that with the small cutoffs we use to generate the online documentation the calculation is far from converged. With more realistic parameters a larger energy difference of about 0.1 Hartree is obtained.","category":"page"},{"location":"examples/collinear_magnetism/","page":"Collinear spin and magnetic systems","title":"Collinear spin and magnetic systems","text":"The spin polarization in the magnetic case is visible if we consider the occupation of the spin-up and spin-down Kohn-Sham orbitals. Especially for the d-orbitals these differ rather drastically. For example for the first k-point:","category":"page"},{"location":"examples/collinear_magnetism/","page":"Collinear spin and magnetic systems","title":"Collinear spin and magnetic systems","text":"iup = 1\nidown = iup + length(scfres.basis.kpoints) ÷ 2\n@show scfres.occupation[iup][1:7]\n@show scfres.occupation[idown][1:7];\nnothing #hide","category":"page"},{"location":"examples/collinear_magnetism/","page":"Collinear spin and magnetic systems","title":"Collinear spin and magnetic systems","text":"Similarly the eigenvalues differ","category":"page"},{"location":"examples/collinear_magnetism/","page":"Collinear spin and magnetic systems","title":"Collinear spin and magnetic systems","text":"@show scfres.eigenvalues[iup][1:7]\n@show scfres.eigenvalues[idown][1:7];\nnothing #hide","category":"page"},{"location":"examples/collinear_magnetism/","page":"Collinear spin and magnetic systems","title":"Collinear spin and magnetic systems","text":"note: ``k``-points in collinear calculations\nFor collinear calculations the kpoints field of the PlaneWaveBasis object contains each k-point coordinate twice, once associated with spin-up and once with down-down. The list first contains all spin-up k-points and then all spin-down k-points, such that iup and idown index the same k-point, but differing spins.","category":"page"},{"location":"examples/collinear_magnetism/","page":"Collinear spin and magnetic systems","title":"Collinear spin and magnetic systems","text":"We can observe the spin-polarization by looking at the density of states (DOS) around the Fermi level, where the spin-up and spin-down DOS differ.","category":"page"},{"location":"examples/collinear_magnetism/","page":"Collinear spin and magnetic systems","title":"Collinear spin and magnetic systems","text":"using Plots\nplot_dos(scfres)","category":"page"},{"location":"examples/collinear_magnetism/","page":"Collinear spin and magnetic systems","title":"Collinear spin and magnetic systems","text":"Similarly the band structure shows clear differences between both spin components.","category":"page"},{"location":"examples/collinear_magnetism/","page":"Collinear spin and magnetic systems","title":"Collinear spin and magnetic systems","text":"using Unitful\nusing UnitfulAtomic\nplot_bandstructure(scfres; kline_density=6)","category":"page"},{"location":"examples/wannier90/","page":"Wannierization using Wannier90","title":"Wannierization using Wannier90","text":"EditURL = \"https://github.com/JuliaMolSim/DFTK.jl/blob/master/examples/wannier90.jl\"","category":"page"},{"location":"examples/wannier90/#Wannierization-using-Wannier90","page":"Wannierization using Wannier90","title":"Wannierization using Wannier90","text":"","category":"section"},{"location":"examples/wannier90/","page":"Wannierization using Wannier90","title":"Wannierization using Wannier90","text":"(Image: ) (Image: )","category":"page"},{"location":"examples/wannier90/","page":"Wannierization using Wannier90","title":"Wannierization using Wannier90","text":"DFTK features an interface with the program Wannier90, in order to compute maximally-localized Wannier functions (MLWFs) from an initial self consistent field calculation. All processes are handled by calling the routine run_wannier90.","category":"page"},{"location":"examples/wannier90/","page":"Wannierization using Wannier90","title":"Wannierization using Wannier90","text":"warning: No guarantees on Wannier90 interface\nThis code is at an early stage and has so far not been fully tested. Bugs are likely and we welcome issues in case you find any!","category":"page"},{"location":"examples/wannier90/","page":"Wannierization using Wannier90","title":"Wannierization using Wannier90","text":"This example shows how to obtain the MLWFs corresponding to the first five bands of graphene. Since the bands 2 to 11 are entangled, 15 bands are first computed to obtain 5 MLWFs by a disantanglement procedure.","category":"page"},{"location":"examples/wannier90/","page":"Wannierization using Wannier90","title":"Wannierization using Wannier90","text":"using DFTK\nusing Unitful\nusing UnitfulAtomic\n\nd = 10u\"Å\"\na = 2.641u\"Å\" # Graphene Lattice constant\nlattice = [a -a/2 0;\n 0 √3*a/2 0;\n 0 0 d]\n\nC = ElementPsp(:C, psp=load_psp(\"hgh/pbe/c-q4\"))\natoms = [C, C]\npositions = [[0.0, 0.0, 0.0], [1//3, 2//3, 0.0]]\nmodel = model_PBE(lattice, atoms, positions)\nbasis = PlaneWaveBasis(model; Ecut=15, kgrid=[5, 5, 1])\nnbandsalg = AdaptiveBands(basis.model; n_bands_converge=15)\nscfres = self_consistent_field(basis; nbandsalg, tol=1e-5);\nnothing #hide","category":"page"},{"location":"examples/wannier90/","page":"Wannierization using Wannier90","title":"Wannierization using Wannier90","text":"Plot bandstructure of the system","category":"page"},{"location":"examples/wannier90/","page":"Wannierization using Wannier90","title":"Wannierization using Wannier90","text":"plot_bandstructure(scfres; kline_density=10)","category":"page"},{"location":"examples/wannier90/","page":"Wannierization using Wannier90","title":"Wannierization using Wannier90","text":"Now we use the run_wannier90 routine to generate all files needed by wannier90 and to perform the wannierization procedure. In Wannier90's convention, all files are named with the same prefix and only differ by their extensions. By default all generated input and output files are stored in the subfolder \"wannier90\" under the prefix \"wannier\" (i.e. \"wannier90/wannier.win\", \"wannier90/wannier.wout\", etc.). A different file prefix can be given with the keyword argument fileprefix as shown below.","category":"page"},{"location":"examples/wannier90/","page":"Wannierization using Wannier90","title":"Wannierization using Wannier90","text":"We now solve for 5 MLWF using wannier90:","category":"page"},{"location":"examples/wannier90/","page":"Wannierization using Wannier90","title":"Wannierization using Wannier90","text":"using wannier90_jll # Needed to make run_wannier90 available\nrun_wannier90(scfres;\n fileprefix=\"wannier/graphene\",\n n_wannier=5,\n num_print_cycles=25,\n num_iter=200,\n #\n dis_win_max=19.0,\n dis_froz_max=0.1,\n dis_num_iter=300,\n dis_mix_ratio=1.0,\n #\n wannier_plot=true,\n wannier_plot_format=\"cube\",\n wannier_plot_supercell=5,\n write_xyz=true,\n translate_home_cell=true,\n );\nnothing #hide","category":"page"},{"location":"examples/wannier90/","page":"Wannierization using Wannier90","title":"Wannierization using Wannier90","text":"As can be observed standard optional arguments for the disentanglement can be passed directly to run_wannier90 as keyword arguments.","category":"page"},{"location":"examples/wannier90/","page":"Wannierization using Wannier90","title":"Wannierization using Wannier90","text":"(Delete temporary files.)","category":"page"},{"location":"examples/wannier90/","page":"Wannierization using Wannier90","title":"Wannierization using Wannier90","text":"rm(\"wannier\", recursive=true)","category":"page"},{"location":"developer/data_structures/#Data-structures","page":"Data structures","title":"Data structures","text":"","category":"section"},{"location":"developer/data_structures/","page":"Data structures","title":"Data structures","text":"using DFTK\na = 10.26 # Silicon lattice constant in Bohr\nlattice = a / 2 * [[0 1 1.];\n [1 0 1.];\n [1 1 0.]]\nSi = ElementPsp(:Si, psp=load_psp(\"hgh/lda/Si-q4\"))\natoms = [Si, Si]\npositions = [ones(3)/8, -ones(3)/8]\n\nmodel = model_LDA(lattice, atoms, positions)\nkgrid = [4, 4, 4]\nEcut = 15\nbasis = PlaneWaveBasis(model; Ecut, kgrid)\nscfres = self_consistent_field(basis; tol=1e-4);","category":"page"},{"location":"developer/data_structures/","page":"Data structures","title":"Data structures","text":"In this section we assume a calculation of silicon LDA model in the setup described in Tutorial.","category":"page"},{"location":"developer/data_structures/#Model-datastructure","page":"Data structures","title":"Model datastructure","text":"","category":"section"},{"location":"developer/data_structures/","page":"Data structures","title":"Data structures","text":"The physical model to be solved is defined by the Model datastructure. It contains the unit cell, number of electrons, atoms, type of spin polarization and temperature. Each atom has an atomic type (Element) specifying the number of valence electrons and the potential (or pseudopotential) it creates with respect to the electrons. The Model structure also contains the list of energy terms defining the energy functional to be minimised during the SCF. For the silicon example above, we used an LDA model, which consists of the following terms[2]:","category":"page"},{"location":"developer/data_structures/","page":"Data structures","title":"Data structures","text":"[2]: If you are not familiar with Julia syntax, typeof.(model.term_types) is equivalent to [typeof(t) for t in model.term_types].","category":"page"},{"location":"developer/data_structures/","page":"Data structures","title":"Data structures","text":"typeof.(model.term_types)","category":"page"},{"location":"developer/data_structures/","page":"Data structures","title":"Data structures","text":"DFTK computes energies for all terms of the model individually, which are available in scfres.energies:","category":"page"},{"location":"developer/data_structures/","page":"Data structures","title":"Data structures","text":"scfres.energies","category":"page"},{"location":"developer/data_structures/","page":"Data structures","title":"Data structures","text":"For now the following energy terms are available in DFTK:","category":"page"},{"location":"developer/data_structures/","page":"Data structures","title":"Data structures","text":"Kinetic energy\nLocal potential energy, either given by analytic potentials or specified by the type of atoms.\nNonlocal potential energy, for norm-conserving pseudopotentials\nNuclei energies (Ewald or pseudopotential correction)\nHartree energy\nExchange-correlation energy\nPower nonlinearities (useful for Gross-Pitaevskii type models)\nMagnetic field energy\nEntropy term","category":"page"},{"location":"developer/data_structures/","page":"Data structures","title":"Data structures","text":"Custom types can be added if needed. For examples see the definition of the above terms in the src/terms directory.","category":"page"},{"location":"developer/data_structures/","page":"Data structures","title":"Data structures","text":"By mixing and matching these terms, the user can create custom models not limited to DFT. Convenience constructors are provided for common cases:","category":"page"},{"location":"developer/data_structures/","page":"Data structures","title":"Data structures","text":"model_LDA: LDA model using the Teter parametrisation\nmodel_DFT: Assemble a DFT model using any of the LDA or GGA functionals of the libxc library, for example: model_DFT(lattice, atoms, positions, [:gga_x_pbe, :gga_c_pbe]) model_DFT(lattice, atoms, positions, :lda_xc_teter93) where the latter is equivalent to model_LDA. Specifying no functional is the reduced Hartree-Fock model: model_DFT(lattice, atoms, positions, [])\nmodel_atomic: A linear model, which contains no electron-electron interaction (neither Hartree nor XC term).","category":"page"},{"location":"developer/data_structures/#PlaneWaveBasis-and-plane-wave-discretisations","page":"Data structures","title":"PlaneWaveBasis and plane-wave discretisations","text":"","category":"section"},{"location":"developer/data_structures/","page":"Data structures","title":"Data structures","text":"The PlaneWaveBasis datastructure handles the discretization of a given Model in a plane-wave basis. In plane-wave methods the discretization is twofold: Once the k-point grid, which determines the sampling inside the Brillouin zone and on top of that a finite plane-wave grid to discretise the lattice-periodic functions. The former aspect is controlled by the kgrid argument of PlaneWaveBasis, the latter is controlled by the cutoff energy parameter Ecut:","category":"page"},{"location":"developer/data_structures/","page":"Data structures","title":"Data structures","text":"PlaneWaveBasis(model; Ecut, kgrid)","category":"page"},{"location":"developer/data_structures/","page":"Data structures","title":"Data structures","text":"The PlaneWaveBasis by default uses symmetry to reduce the number of k-points explicitly treated. For details see Crystal symmetries.","category":"page"},{"location":"developer/data_structures/","page":"Data structures","title":"Data structures","text":"As mentioned, the periodic parts of Bloch waves are expanded in a set of normalized plane waves e_G:","category":"page"},{"location":"developer/data_structures/","page":"Data structures","title":"Data structures","text":"beginaligned\n psi_k(x) = e^i k cdot x u_k(x)\n = sum_G in mathcal R^* c_G e^i k cdot x e_G(x)\nendaligned","category":"page"},{"location":"developer/data_structures/","page":"Data structures","title":"Data structures","text":"where mathcal R^* is the set of reciprocal lattice vectors. The c_G are ell^2-normalized. The summation is truncated to a \"spherical\", k-dependent basis set","category":"page"},{"location":"developer/data_structures/","page":"Data structures","title":"Data structures","text":" S_k = leftG in mathcal R^* middle\n frac 1 2 k+ G^2 le E_textcutright","category":"page"},{"location":"developer/data_structures/","page":"Data structures","title":"Data structures","text":"where E_textcut is the cutoff energy.","category":"page"},{"location":"developer/data_structures/","page":"Data structures","title":"Data structures","text":"Densities involve terms like psi_k^2 = u_k^2 and therefore products e_-G e_G for G G in S_k. To represent these we use a \"cubic\", k-independent basis set large enough to contain the set G-G G G in S_k. We can obtain the coefficients of densities on the e_G basis by a convolution, which can be performed efficiently with FFTs (see ifft and fft functions). Potentials are discretized on this same set.","category":"page"},{"location":"developer/data_structures/","page":"Data structures","title":"Data structures","text":"The normalization conventions used in the code is that quantities stored in reciprocal space are coefficients in the e_G basis, and quantities stored in real space use real physical values. This means for instance that wavefunctions in the real space grid are normalized as fracOmegaN sum_r psi(r)^2 = 1 where N is the number of grid points.","category":"page"},{"location":"developer/data_structures/","page":"Data structures","title":"Data structures","text":"For example let us check the normalization of the first eigenfunction at the first k-point in reciprocal space:","category":"page"},{"location":"developer/data_structures/","page":"Data structures","title":"Data structures","text":"ψtest = scfres.ψ[1][:, 1]\nsum(abs2.(ψtest))","category":"page"},{"location":"developer/data_structures/","page":"Data structures","title":"Data structures","text":"We now perform an IFFT to get ψ in real space. The k-point has to be passed because ψ is expressed on the k-dependent basis. Again the function is normalised:","category":"page"},{"location":"developer/data_structures/","page":"Data structures","title":"Data structures","text":"ψreal = ifft(basis, basis.kpoints[1], ψtest)\nsum(abs2.(ψreal)) * basis.dvol","category":"page"},{"location":"developer/data_structures/","page":"Data structures","title":"Data structures","text":"The list of k points of the basis can be obtained with basis.kpoints.","category":"page"},{"location":"developer/data_structures/","page":"Data structures","title":"Data structures","text":"basis.kpoints","category":"page"},{"location":"developer/data_structures/","page":"Data structures","title":"Data structures","text":"The G vectors of the \"spherical\", k-dependent grid can be obtained with G_vectors:","category":"page"},{"location":"developer/data_structures/","page":"Data structures","title":"Data structures","text":"[length(G_vectors(basis, kpoint)) for kpoint in basis.kpoints]","category":"page"},{"location":"developer/data_structures/","page":"Data structures","title":"Data structures","text":"ik = 1\nG_vectors(basis, basis.kpoints[ik])[1:4]","category":"page"},{"location":"developer/data_structures/","page":"Data structures","title":"Data structures","text":"The list of G vectors (Fourier modes) of the \"cubic\", k-independent basis set can be obtained similarly with G_vectors(basis).","category":"page"},{"location":"developer/data_structures/","page":"Data structures","title":"Data structures","text":"length(G_vectors(basis)), prod(basis.fft_size)","category":"page"},{"location":"developer/data_structures/","page":"Data structures","title":"Data structures","text":"collect(G_vectors(basis))[1:4]","category":"page"},{"location":"developer/data_structures/","page":"Data structures","title":"Data structures","text":"Analogously the list of r vectors (real-space grid) can be obtained with r_vectors(basis):","category":"page"},{"location":"developer/data_structures/","page":"Data structures","title":"Data structures","text":"length(r_vectors(basis))","category":"page"},{"location":"developer/data_structures/","page":"Data structures","title":"Data structures","text":"collect(r_vectors(basis))[1:4]","category":"page"},{"location":"developer/data_structures/#Accessing-Bloch-waves-and-densities","page":"Data structures","title":"Accessing Bloch waves and densities","text":"","category":"section"},{"location":"developer/data_structures/","page":"Data structures","title":"Data structures","text":"Wavefunctions are stored in an array scfres.ψ as ψ[ik][iG, iband] where ik is the index of the k-point (in basis.kpoints), iG is the index of the plane wave (in G_vectors(basis, basis.kpoints[ik])) and iband is the index of the band. Densities are stored in real space, as a 4-dimensional array (the third being the spin component).","category":"page"},{"location":"developer/data_structures/","page":"Data structures","title":"Data structures","text":"using Plots # hide\nrvecs = collect(r_vectors(basis))[:, 1, 1] # slice along the x axis\nx = [r[1] for r in rvecs] # only keep the x coordinate\nplot(x, scfres.ρ[:, 1, 1, 1], label=\"\", xlabel=\"x\", ylabel=\"ρ\", marker=2)","category":"page"},{"location":"developer/data_structures/","page":"Data structures","title":"Data structures","text":"G_energies = [sum(abs2.(model.recip_lattice * G)) ./ 2 for G in G_vectors(basis)][:]\nscatter(G_energies, abs.(fft(basis, scfres.ρ)[:]);\n yscale=:log10, ylims=(1e-12, 1), label=\"\", xlabel=\"Energy\", ylabel=\"|ρ|\")","category":"page"},{"location":"developer/data_structures/","page":"Data structures","title":"Data structures","text":"Note that the density has no components on wavevectors above a certain energy, because the wavefunctions are limited to frac 1 2k+G^2 E_rm cut.","category":"page"},{"location":"examples/custom_solvers/","page":"Custom solvers","title":"Custom solvers","text":"EditURL = \"https://github.com/JuliaMolSim/DFTK.jl/blob/master/examples/custom_solvers.jl\"","category":"page"},{"location":"examples/custom_solvers/#Custom-solvers","page":"Custom solvers","title":"Custom solvers","text":"","category":"section"},{"location":"examples/custom_solvers/","page":"Custom solvers","title":"Custom solvers","text":"(Image: ) (Image: )","category":"page"},{"location":"examples/custom_solvers/","page":"Custom solvers","title":"Custom solvers","text":"In this example, we show how to define custom solvers. Our system will again be silicon, because we are not very imaginative","category":"page"},{"location":"examples/custom_solvers/","page":"Custom solvers","title":"Custom solvers","text":"using DFTK, LinearAlgebra\n\na = 10.26\nlattice = a / 2 * [[0 1 1.];\n [1 0 1.];\n [1 1 0.]]\nSi = ElementPsp(:Si, psp=load_psp(\"hgh/lda/Si-q4\"))\natoms = [Si, Si]\npositions = [ones(3)/8, -ones(3)/8]\n\n# We take very (very) crude parameters\nmodel = model_LDA(lattice, atoms, positions)\nbasis = PlaneWaveBasis(model; Ecut=5, kgrid=[1, 1, 1]);\nnothing #hide","category":"page"},{"location":"examples/custom_solvers/","page":"Custom solvers","title":"Custom solvers","text":"We define our custom fix-point solver: simply a damped fixed-point","category":"page"},{"location":"examples/custom_solvers/","page":"Custom solvers","title":"Custom solvers","text":"function my_fp_solver(f, x0, max_iter; tol)\n mixing_factor = .7\n x = x0\n fx = f(x)\n for n = 1:max_iter\n inc = fx - x\n if norm(inc) < tol\n break\n end\n x = x + mixing_factor * inc\n fx = f(x)\n end\n (fixpoint=x, converged=norm(fx-x) < tol)\nend;\nnothing #hide","category":"page"},{"location":"examples/custom_solvers/","page":"Custom solvers","title":"Custom solvers","text":"Our eigenvalue solver just forms the dense matrix and diagonalizes it explicitly (this only works for very small systems)","category":"page"},{"location":"examples/custom_solvers/","page":"Custom solvers","title":"Custom solvers","text":"function my_eig_solver(A, X0; maxiter, tol, kwargs...)\n n = size(X0, 2)\n A = Array(A)\n E = eigen(A)\n λ = E.values[1:n]\n X = E.vectors[:, 1:n]\n (; λ, X, residual_norms=[], iterations=0, converged=true, n_matvec=0)\nend;\nnothing #hide","category":"page"},{"location":"examples/custom_solvers/","page":"Custom solvers","title":"Custom solvers","text":"Finally we also define our custom mixing scheme. It will be a mixture of simple mixing (for the first 2 steps) and than default to Kerker mixing. In the mixing interface δF is (ρ_textout - ρ_textin), i.e. the difference in density between two subsequent SCF steps and the mix function returns δρ, which is added to ρ_textin to yield ρ_textnext, the density for the next SCF step.","category":"page"},{"location":"examples/custom_solvers/","page":"Custom solvers","title":"Custom solvers","text":"struct MyMixing\n n_simple # Number of iterations for simple mixing\nend\nMyMixing() = MyMixing(2)\n\nfunction DFTK.mix_density(mixing::MyMixing, basis, δF; n_iter, kwargs...)\n if n_iter <= mixing.n_simple\n return δF # Simple mixing -> Do not modify update at all\n else\n # Use the default KerkerMixing from DFTK\n DFTK.mix_density(KerkerMixing(), basis, δF; kwargs...)\n end\nend","category":"page"},{"location":"examples/custom_solvers/","page":"Custom solvers","title":"Custom solvers","text":"That's it! Now we just run the SCF with these solvers","category":"page"},{"location":"examples/custom_solvers/","page":"Custom solvers","title":"Custom solvers","text":"scfres = self_consistent_field(basis;\n tol=1e-8,\n solver=my_fp_solver,\n eigensolver=my_eig_solver,\n mixing=MyMixing());\nnothing #hide","category":"page"},{"location":"examples/custom_solvers/","page":"Custom solvers","title":"Custom solvers","text":"Note that the default convergence criterion is the difference in density. When this gets below tol, the \"driver\" self_consistent_field artificially makes the fixed-point solver think it's converged by forcing f(x) = x. You can customize this with the is_converged keyword argument to self_consistent_field.","category":"page"},{"location":"examples/metallic_systems/","page":"Temperature and metallic systems","title":"Temperature and metallic systems","text":"EditURL = \"https://github.com/JuliaMolSim/DFTK.jl/blob/master/examples/metallic_systems.jl\"","category":"page"},{"location":"examples/metallic_systems/#metallic-systems","page":"Temperature and metallic systems","title":"Temperature and metallic systems","text":"","category":"section"},{"location":"examples/metallic_systems/","page":"Temperature and metallic systems","title":"Temperature and metallic systems","text":"(Image: ) (Image: )","category":"page"},{"location":"examples/metallic_systems/","page":"Temperature and metallic systems","title":"Temperature and metallic systems","text":"In this example we consider the modeling of a magnesium lattice as a simple example for a metallic system. For our treatment we will use the PBE exchange-correlation functional. First we import required packages and setup the lattice. Again notice that DFTK uses the convention that lattice vectors are specified column by column.","category":"page"},{"location":"examples/metallic_systems/","page":"Temperature and metallic systems","title":"Temperature and metallic systems","text":"using DFTK\nusing Plots\nusing Unitful\nusing UnitfulAtomic\n\na = 3.01794 # bohr\nb = 5.22722 # bohr\nc = 9.77362 # bohr\nlattice = [[-a -a 0]; [-b b 0]; [0 0 -c]]\nMg = ElementPsp(:Mg, psp=load_psp(\"hgh/pbe/Mg-q2\"))\natoms = [Mg, Mg]\npositions = [[2/3, 1/3, 1/4], [1/3, 2/3, 3/4]];\nnothing #hide","category":"page"},{"location":"examples/metallic_systems/","page":"Temperature and metallic systems","title":"Temperature and metallic systems","text":"Next we build the PBE model and discretize it. Since magnesium is a metal we apply a small smearing temperature to ease convergence using the Fermi-Dirac smearing scheme. Note that both the Ecut is too small as well as the minimal k-point spacing kspacing far too large to give a converged result. These have been selected to obtain a fast execution time. By default PlaneWaveBasis chooses a kspacing of 2π * 0.022 inverse Bohrs, which is much more reasonable.","category":"page"},{"location":"examples/metallic_systems/","page":"Temperature and metallic systems","title":"Temperature and metallic systems","text":"kspacing = 0.945 / u\"angstrom\" # Minimal spacing of k-points,\n# in units of wavevectors (inverse Bohrs)\nEcut = 5 # Kinetic energy cutoff in Hartree\ntemperature = 0.01 # Smearing temperature in Hartree\nsmearing = DFTK.Smearing.FermiDirac() # Smearing method\n# also supported: Gaussian,\n# MarzariVanderbilt,\n# and MethfesselPaxton(order)\n\nmodel = model_DFT(lattice, atoms, positions, [:gga_x_pbe, :gga_c_pbe];\n temperature, smearing)\nkgrid = kgrid_from_minimal_spacing(lattice, kspacing)\nbasis = PlaneWaveBasis(model; Ecut, kgrid);\nnothing #hide","category":"page"},{"location":"examples/metallic_systems/","page":"Temperature and metallic systems","title":"Temperature and metallic systems","text":"Finally we run the SCF. Two magnesium atoms in our pseudopotential model result in four valence electrons being explicitly treated. Nevertheless this SCF will solve for eight bands by default in order to capture partial occupations beyond the Fermi level due to the employed smearing scheme. In this example we use a damping of 0.8. The default LdosMixing should be suitable to converge metallic systems like the one we model here. For the sake of demonstration we still switch to Kerker mixing here.","category":"page"},{"location":"examples/metallic_systems/","page":"Temperature and metallic systems","title":"Temperature and metallic systems","text":"scfres = self_consistent_field(basis, damping=0.8, mixing=KerkerMixing());\nnothing #hide","category":"page"},{"location":"examples/metallic_systems/","page":"Temperature and metallic systems","title":"Temperature and metallic systems","text":"scfres.occupation[1]","category":"page"},{"location":"examples/metallic_systems/","page":"Temperature and metallic systems","title":"Temperature and metallic systems","text":"scfres.energies","category":"page"},{"location":"examples/metallic_systems/","page":"Temperature and metallic systems","title":"Temperature and metallic systems","text":"The fact that magnesium is a metal is confirmed by plotting the density of states around the Fermi level.","category":"page"},{"location":"examples/metallic_systems/","page":"Temperature and metallic systems","title":"Temperature and metallic systems","text":"plot_dos(scfres)","category":"page"},{"location":"developer/gpu_computations/#GPU-computations","page":"GPU computations","title":"GPU computations","text":"","category":"section"},{"location":"developer/gpu_computations/","page":"GPU computations","title":"GPU computations","text":"Performing GPU computations in DFTK is still work in progress. The goal is to build on Julia's multiple dispatch to have the same code base for CPU and GPU. Our current approach is to aim at decent performance without writing any custom kernels at all, relying only on the high level functionalities implemented in the GPU packages.","category":"page"},{"location":"developer/gpu_computations/","page":"GPU computations","title":"GPU computations","text":"To go even further with this idea of unified code, we would also like to be able to support any type of GPU architecture: we do not want to hard-code the use of a specific architecture, say a NVIDIA CUDA GPU. DFTK does not realy on an architecture-specific package (CUDA, ROCm, OneAPI...) but rather uses GPUArrays, which is the counterpart of AbstractArray but for GPU arrays.","category":"page"},{"location":"developer/gpu_computations/#Current-implementation","page":"GPU computations","title":"Current implementation","text":"","category":"section"},{"location":"developer/gpu_computations/","page":"GPU computations","title":"GPU computations","text":"For now, GPU computations are done by specializing the architecture keyword argument when creating the basis. architecture should be an initialized instance of the (non-exported) CPU and GPU structures. CPU does not require any argument, but GPU requires the type of array which will be used for GPU computations.","category":"page"},{"location":"developer/gpu_computations/","page":"GPU computations","title":"GPU computations","text":"PlaneWaveBasis(model; Ecut, kgrid, architecture = DFTK.CPU())\nPlaneWaveBasis(model; Ecut, kgrid, architecture = DFTK.GPU(CuArray))","category":"page"},{"location":"developer/gpu_computations/","page":"GPU computations","title":"GPU computations","text":"note: GPU API is experimental\nIt is very likely that this API will change, based on the evolution of the Julia ecosystem concerning distributed architectures.","category":"page"},{"location":"developer/gpu_computations/","page":"GPU computations","title":"GPU computations","text":"Not all terms can be used when doing GPU computations. As of January 2023 this concerns Anyonic, Magnetic and TermPairwisePotential. Similarly GPU features are not yet exhaustively tested, and it is likely that some aspects of the code such as automatic differentiation or stresses will not work.","category":"page"},{"location":"developer/gpu_computations/#Pitfalls","page":"GPU computations","title":"Pitfalls","text":"","category":"section"},{"location":"developer/gpu_computations/","page":"GPU computations","title":"GPU computations","text":"There are a few things to keep in mind when doing GPU programming in DFTK.","category":"page"},{"location":"developer/gpu_computations/","page":"GPU computations","title":"GPU computations","text":"Transfers to and from a device can be done simply by converting an array to","category":"page"},{"location":"developer/gpu_computations/","page":"GPU computations","title":"GPU computations","text":"an other type. However, hard-coding the new array type (such as writing CuArray(A) to move A to a CUDA GPU) is not cross-architecture, and can be confusing for developers working only on the CPU code. These data transfers should be done using the helper functions to_device and to_cpu which provide a level of abstraction while also allowing multiple architectures to be used.","category":"page"},{"location":"developer/gpu_computations/","page":"GPU computations","title":"GPU computations","text":"cuda_gpu = DFTK.GPU(CuArray)\ncpu_architecture = DFTK.CPU()\nA = rand(10) # A is on the CPU\nB = DFTK.to_device(cuda_gpu, A) # B is a copy of A on the CUDA GPU\nB .+= 1.\nC = DFTK.to_cpu(B) # C is a copy of B on the CPU\nD = DFTK.to_device(cpu_architecture, B) # Equivalent to the previous line, but\n # should be avoided as it is less clear","category":"page"},{"location":"developer/gpu_computations/","page":"GPU computations","title":"GPU computations","text":"Note: similar could also be used, but then a reference array (one which already lives on the device) needs to be available at call time. This was done previously, with helper functions to easily build new arrays on a given architecture: see for example zeros_like.","category":"page"},{"location":"developer/gpu_computations/","page":"GPU computations","title":"GPU computations","text":"Functions which will get executed on the GPU should always have arguments","category":"page"},{"location":"developer/gpu_computations/","page":"GPU computations","title":"GPU computations","text":"which are isbits (immutable and contains no references to other values). When using map, also make sure that every structure used is also isbits. For example, the following map will fail, as model contains strings and arrays which are not isbits.","category":"page"},{"location":"developer/gpu_computations/","page":"GPU computations","title":"GPU computations","text":"function map_lattice(model::Model, Gs::AbstractArray{Vec3})\n # model is not isbits\n map(Gs) do Gi\n model.lattice * Gi\n end\nend","category":"page"},{"location":"developer/gpu_computations/","page":"GPU computations","title":"GPU computations","text":"However, the following map will run on a GPU, as the lattice is a static matrix.","category":"page"},{"location":"developer/gpu_computations/","page":"GPU computations","title":"GPU computations","text":"function map_lattice(model::Model, Gs::AbstractArray{Vec3})\n lattice = model.lattice # lattice is isbits\n map(Gs) do Gi\n model.lattice * Gi\n end\nend","category":"page"},{"location":"developer/gpu_computations/","page":"GPU computations","title":"GPU computations","text":"List comprehensions should be avoided, as they always return a CPU Array.","category":"page"},{"location":"developer/gpu_computations/","page":"GPU computations","title":"GPU computations","text":"Instead, we should use map which returns an array of the same type as the input one.","category":"page"},{"location":"developer/gpu_computations/","page":"GPU computations","title":"GPU computations","text":"Sometimes, creating a new array or making a copy can be necessary to achieve good","category":"page"},{"location":"developer/gpu_computations/","page":"GPU computations","title":"GPU computations","text":"performance. For example, iterating through the columns of a matrix to compute their norms is not efficient, as a new kernel is launched for every column. Instead, it is better to build the vector containing these norms, as it is a vectorized operation and will be much faster on the GPU.","category":"page"},{"location":"examples/scf_callbacks/","page":"Monitoring self-consistent field calculations","title":"Monitoring self-consistent field calculations","text":"EditURL = \"https://github.com/JuliaMolSim/DFTK.jl/blob/master/examples/scf_callbacks.jl\"","category":"page"},{"location":"examples/scf_callbacks/#Monitoring-self-consistent-field-calculations","page":"Monitoring self-consistent field calculations","title":"Monitoring self-consistent field calculations","text":"","category":"section"},{"location":"examples/scf_callbacks/","page":"Monitoring self-consistent field calculations","title":"Monitoring self-consistent field calculations","text":"(Image: ) (Image: )","category":"page"},{"location":"examples/scf_callbacks/","page":"Monitoring self-consistent field calculations","title":"Monitoring self-consistent field calculations","text":"The self_consistent_field function takes as the callback keyword argument one function to be called after each iteration. This function gets passed the complete internal state of the SCF solver and can thus be used both to monitor and debug the iterations as well as to quickly patch it with additional functionality.","category":"page"},{"location":"examples/scf_callbacks/","page":"Monitoring self-consistent field calculations","title":"Monitoring self-consistent field calculations","text":"This example discusses a few aspects of the callback function taking again our favourite silicon example.","category":"page"},{"location":"examples/scf_callbacks/","page":"Monitoring self-consistent field calculations","title":"Monitoring self-consistent field calculations","text":"We setup silicon in an LDA model using the ASE interface to build a bulk silicon lattice, see Input and output formats for more details.","category":"page"},{"location":"examples/scf_callbacks/","page":"Monitoring self-consistent field calculations","title":"Monitoring self-consistent field calculations","text":"using DFTK\nusing ASEconvert\n\nsystem = pyconvert(AbstractSystem, ase.build.bulk(\"Si\"))\nmodel = model_LDA(attach_psp(system; Si=\"hgh/pbe/si-q4.hgh\"))\nbasis = PlaneWaveBasis(model; Ecut=5, kgrid=[3, 3, 3]);\nnothing #hide","category":"page"},{"location":"examples/scf_callbacks/","page":"Monitoring self-consistent field calculations","title":"Monitoring self-consistent field calculations","text":"DFTK already defines a few callback functions for standard tasks. One example is the usual convergence table, which is defined in the callback ScfDefaultCallback. Another example is ScfPlotTrace, which records the total energy at each iteration and uses it to plot the convergence of the SCF graphically once it is converged. For details and other callbacks see src/scf/scf_callbacks.jl.","category":"page"},{"location":"examples/scf_callbacks/","page":"Monitoring self-consistent field calculations","title":"Monitoring self-consistent field calculations","text":"note: Callbacks are not exported\nCallbacks are not exported from the DFTK namespace as of now, so you will need to use them, e.g., as DFTK.ScfDefaultCallback and DFTK.ScfPlotTrace.","category":"page"},{"location":"examples/scf_callbacks/","page":"Monitoring self-consistent field calculations","title":"Monitoring self-consistent field calculations","text":"In this example we define a custom callback, which plots the change in density at each SCF iteration after the SCF has finished. For this we first define the empty plot canvas and an empty container for all the density differences:","category":"page"},{"location":"examples/scf_callbacks/","page":"Monitoring self-consistent field calculations","title":"Monitoring self-consistent field calculations","text":"using Plots\np = plot(yaxis=:log)\ndensity_differences = Float64[];\nnothing #hide","category":"page"},{"location":"examples/scf_callbacks/","page":"Monitoring self-consistent field calculations","title":"Monitoring self-consistent field calculations","text":"The callback function itself gets passed a named tuple similar to the one returned by self_consistent_field, which contains the input and output density of the SCF step as ρin and ρout. Since the callback gets called both during the SCF iterations as well as after convergence just before self_consistent_field finishes we can both collect the data and initiate the plotting in one function.","category":"page"},{"location":"examples/scf_callbacks/","page":"Monitoring self-consistent field calculations","title":"Monitoring self-consistent field calculations","text":"using LinearAlgebra\n\nfunction plot_callback(info)\n if info.stage == :finalize\n plot!(p, density_differences, label=\"|ρout - ρin|\", markershape=:x)\n else\n push!(density_differences, norm(info.ρout - info.ρin))\n end\n info\nend\ncallback = DFTK.ScfDefaultCallback() ∘ plot_callback;\nnothing #hide","category":"page"},{"location":"examples/scf_callbacks/","page":"Monitoring self-consistent field calculations","title":"Monitoring self-consistent field calculations","text":"Notice that for constructing the callback function we chained the plot_callback (which does the plotting) with the ScfDefaultCallback, such that when using the plot_callback function with self_consistent_field we still get the usual convergence table printed. We run the SCF with this callback …","category":"page"},{"location":"examples/scf_callbacks/","page":"Monitoring self-consistent field calculations","title":"Monitoring self-consistent field calculations","text":"scfres = self_consistent_field(basis; tol=1e-5, callback);\nnothing #hide","category":"page"},{"location":"examples/scf_callbacks/","page":"Monitoring self-consistent field calculations","title":"Monitoring self-consistent field calculations","text":"… and show the plot","category":"page"},{"location":"examples/scf_callbacks/","page":"Monitoring self-consistent field calculations","title":"Monitoring self-consistent field calculations","text":"p","category":"page"},{"location":"examples/scf_callbacks/","page":"Monitoring self-consistent field calculations","title":"Monitoring self-consistent field calculations","text":"The info object passed to the callback contains not just the densities but also the complete Bloch wave (in ψ), the occupation, band eigenvalues and so on. See src/scf/self_consistent_field.jl for all currently available keys.","category":"page"},{"location":"examples/scf_callbacks/","page":"Monitoring self-consistent field calculations","title":"Monitoring self-consistent field calculations","text":"tip: Debugging with callbacks\nVery handy for debugging SCF algorithms is to employ callbacks with an @infiltrate from Infiltrator.jl to interactively monitor what is happening each SCF step.","category":"page"},{"location":"features/#package-features","page":"DFTK features","title":"DFTK features","text":"","category":"section"},{"location":"features/","page":"DFTK features","title":"DFTK features","text":"Standard methods and models:\nStandard DFT models (LDA, GGA, meta-GGA): Any functional from the libxc library\nNorm-conserving pseudopotentials: Goedecker-type (GTH, HGH) or numerical (in UPF pseudopotential format), see Pseudopotentials for details.\nBrillouin zone symmetry for k-point sampling using spglib\nStandard smearing functions (including Methfessel-Paxton and Marzari-Vanderbilt cold smearing)\nCollinear spin polarization for magnetic systems\nSelf-consistent field approaches including Kerker mixing, LDOS mixing, adaptive damping\nDirect minimization, Newton solver\nMulti-level threading (k-points eigenvectors, FFTs, linear algebra)\nMPI-based distributed parallelism (distribution over k-points)\nTreat systems of 1000 electrons\nGround-state properties and post-processing:\nTotal energy\nForces, stresses\nDensity of states (DOS), local density of states (LDOS)\nBand structures\nEasy access to all intermediate quantities (e.g. density, Bloch waves)\nUnique features\nSupport for arbitrary floating point types, including Float32 (single precision) or Double64 (from DoubleFloats.jl).\nForward-mode algorithmic differentiation (see Polarizability using automatic differentiation)\nFlexibility to build your own Kohn-Sham model: Anything from analytic potentials, linear Cohen-Bergstresser model, the Gross-Pitaevskii equation, Anyonic models, etc.\nAnalytic potentials (see Tutorial on periodic problems)\n1D / 2D / 3D systems (see Tutorial on periodic problems)\nThird-party integrations:\nSeamless integration with many standard Input and output formats.\nIntegration with ASE and AtomsBase for passing atomic structures (see AtomsBase integration).\nWannierization using Wannier90","category":"page"},{"location":"features/","page":"DFTK features","title":"DFTK features","text":"Runs out of the box on Linux, macOS and Windows","category":"page"},{"location":"features/","page":"DFTK features","title":"DFTK features","text":"Missing a feature? Look for an open issue or create a new one. Want to contribute? See our contributing notes.","category":"page"},{"location":"examples/atomsbase/","page":"AtomsBase integration","title":"AtomsBase integration","text":"EditURL = \"https://github.com/JuliaMolSim/DFTK.jl/blob/master/examples/atomsbase.jl\"","category":"page"},{"location":"examples/atomsbase/#AtomsBase-integration","page":"AtomsBase integration","title":"AtomsBase integration","text":"","category":"section"},{"location":"examples/atomsbase/","page":"AtomsBase integration","title":"AtomsBase integration","text":"(Image: ) (Image: )","category":"page"},{"location":"examples/atomsbase/","page":"AtomsBase integration","title":"AtomsBase integration","text":"AtomsBase.jl is a common interface for representing atomic structures in Julia. DFTK directly supports using such structures to run a calculation as is demonstrated here.","category":"page"},{"location":"examples/atomsbase/","page":"AtomsBase integration","title":"AtomsBase integration","text":"using DFTK","category":"page"},{"location":"examples/atomsbase/#Feeding-an-AtomsBase-AbstractSystem-to-DFTK","page":"AtomsBase integration","title":"Feeding an AtomsBase AbstractSystem to DFTK","text":"","category":"section"},{"location":"examples/atomsbase/","page":"AtomsBase integration","title":"AtomsBase integration","text":"In this example we construct a silicon system using the ase.build.bulk routine from the atomistic simulation environment (ASE), which is exposed by ASEconvert as an AtomsBase AbstractSystem.","category":"page"},{"location":"examples/atomsbase/","page":"AtomsBase integration","title":"AtomsBase integration","text":"# Construct bulk system and convert to an AbstractSystem\nusing ASEconvert\nsystem_ase = ase.build.bulk(\"Si\")\nsystem = pyconvert(AbstractSystem, system_ase)","category":"page"},{"location":"examples/atomsbase/","page":"AtomsBase integration","title":"AtomsBase integration","text":"To use an AbstractSystem in DFTK, we attach pseudopotentials, construct a DFT model, discretise and solve:","category":"page"},{"location":"examples/atomsbase/","page":"AtomsBase integration","title":"AtomsBase integration","text":"system = attach_psp(system; Si=\"hgh/lda/si-q4\")\n\nmodel = model_LDA(system; temperature=1e-3)\nbasis = PlaneWaveBasis(model; Ecut=15, kgrid=[4, 4, 4])\nscfres = self_consistent_field(basis, tol=1e-8);\nnothing #hide","category":"page"},{"location":"examples/atomsbase/","page":"AtomsBase integration","title":"AtomsBase integration","text":"If we did not want to use ASE we could of course use any other package which yields an AbstractSystem object. This includes:","category":"page"},{"location":"examples/atomsbase/#Reading-a-system-using-AtomsIO","page":"AtomsBase integration","title":"Reading a system using AtomsIO","text":"","category":"section"},{"location":"examples/atomsbase/","page":"AtomsBase integration","title":"AtomsBase integration","text":"using AtomsIO\n\n# Read a file using [AtomsIO](https://github.com/mfherbst/AtomsIO.jl),\n# which directly yields an AbstractSystem.\nsystem = load_system(\"Si.extxyz\")\n\n# Now run the LDA calculation:\nsystem = attach_psp(system; Si=\"hgh/lda/si-q4\")\nmodel = model_LDA(system; temperature=1e-3)\nbasis = PlaneWaveBasis(model; Ecut=15, kgrid=[4, 4, 4])\nscfres = self_consistent_field(basis, tol=1e-8);\nnothing #hide","category":"page"},{"location":"examples/atomsbase/","page":"AtomsBase integration","title":"AtomsBase integration","text":"The same could be achieved using ExtXYZ by system = Atoms(read_frame(\"Si.extxyz\")), since the ExtXYZ.Atoms object is directly AtomsBase-compatible.","category":"page"},{"location":"examples/atomsbase/#Directly-setting-up-a-system-in-AtomsBase","page":"AtomsBase integration","title":"Directly setting up a system in AtomsBase","text":"","category":"section"},{"location":"examples/atomsbase/","page":"AtomsBase integration","title":"AtomsBase integration","text":"using AtomsBase\nusing Unitful\nusing UnitfulAtomic\n\n# Construct a system in the AtomsBase world\na = 10.26u\"bohr\" # Silicon lattice constant\nlattice = a / 2 * [[0, 1, 1.], # Lattice as vector of vectors\n [1, 0, 1.],\n [1, 1, 0.]]\natoms = [:Si => ones(3)/8, :Si => -ones(3)/8]\nsystem = periodic_system(atoms, lattice; fractional=true)\n\n# Now run the LDA calculation:\nsystem = attach_psp(system; Si=\"hgh/lda/si-q4\")\nmodel = model_LDA(system; temperature=1e-3)\nbasis = PlaneWaveBasis(model; Ecut=15, kgrid=[4, 4, 4])\nscfres = self_consistent_field(basis, tol=1e-4);\nnothing #hide","category":"page"},{"location":"examples/atomsbase/#Obtaining-an-AbstractSystem-from-DFTK-data","page":"AtomsBase integration","title":"Obtaining an AbstractSystem from DFTK data","text":"","category":"section"},{"location":"examples/atomsbase/","page":"AtomsBase integration","title":"AtomsBase integration","text":"At any point we can also get back the DFTK model as an AtomsBase-compatible AbstractSystem:","category":"page"},{"location":"examples/atomsbase/","page":"AtomsBase integration","title":"AtomsBase integration","text":"second_system = atomic_system(model)","category":"page"},{"location":"examples/atomsbase/","page":"AtomsBase integration","title":"AtomsBase integration","text":"Similarly DFTK offers a method to the atomic_system and periodic_system functions (from AtomsBase), which enable a seamless conversion of the usual data structures for setting up DFTK calculations into an AbstractSystem:","category":"page"},{"location":"examples/atomsbase/","page":"AtomsBase integration","title":"AtomsBase integration","text":"lattice = 5.431u\"Å\" / 2 * [[0 1 1.];\n [1 0 1.];\n [1 1 0.]];\nSi = ElementPsp(:Si, psp=load_psp(\"hgh/lda/Si-q4\"))\natoms = [Si, Si]\npositions = [ones(3)/8, -ones(3)/8]\n\nthird_system = atomic_system(lattice, atoms, positions)","category":"page"},{"location":"examples/dielectric/","page":"Eigenvalues of the dielectric matrix","title":"Eigenvalues of the dielectric matrix","text":"EditURL = \"https://github.com/JuliaMolSim/DFTK.jl/blob/master/examples/dielectric.jl\"","category":"page"},{"location":"examples/dielectric/#Eigenvalues-of-the-dielectric-matrix","page":"Eigenvalues of the dielectric matrix","title":"Eigenvalues of the dielectric matrix","text":"","category":"section"},{"location":"examples/dielectric/","page":"Eigenvalues of the dielectric matrix","title":"Eigenvalues of the dielectric matrix","text":"(Image: ) (Image: )","category":"page"},{"location":"examples/dielectric/","page":"Eigenvalues of the dielectric matrix","title":"Eigenvalues of the dielectric matrix","text":"We compute a few eigenvalues of the dielectric matrix (q=0, ω=0) iteratively.","category":"page"},{"location":"examples/dielectric/","page":"Eigenvalues of the dielectric matrix","title":"Eigenvalues of the dielectric matrix","text":"using DFTK\nusing Plots\nusing KrylovKit\nusing Printf\n\n# Calculation parameters\nkgrid = [1, 1, 1]\nEcut = 5\n\n# Silicon lattice\na = 10.26\nlattice = a / 2 .* [[0 1 1.]; [1 0 1.]; [1 1 0.]]\nSi = ElementPsp(:Si, psp=load_psp(\"hgh/lda/Si-q4\"))\natoms = [Si, Si]\npositions = [ones(3)/8, -ones(3)/8]\n\n# Compute the dielectric operator without symmetries\nmodel = model_LDA(lattice, atoms, positions, symmetries=false)\nbasis = PlaneWaveBasis(model; Ecut, kgrid)\nscfres = self_consistent_field(basis, tol=1e-8);\nnothing #hide","category":"page"},{"location":"examples/dielectric/","page":"Eigenvalues of the dielectric matrix","title":"Eigenvalues of the dielectric matrix","text":"Applying ε^ (1- χ_0 K) …","category":"page"},{"location":"examples/dielectric/","page":"Eigenvalues of the dielectric matrix","title":"Eigenvalues of the dielectric matrix","text":"function eps_fun(δρ)\n δV = apply_kernel(basis, δρ; ρ=scfres.ρ)\n χ0δV = apply_χ0(scfres, δV)\n δρ - χ0δV\nend;\nnothing #hide","category":"page"},{"location":"examples/dielectric/","page":"Eigenvalues of the dielectric matrix","title":"Eigenvalues of the dielectric matrix","text":"… eagerly diagonalizes the subspace matrix at each iteration","category":"page"},{"location":"examples/dielectric/","page":"Eigenvalues of the dielectric matrix","title":"Eigenvalues of the dielectric matrix","text":"eigsolve(eps_fun, randn(size(scfres.ρ)), 5, :LM; eager=true, verbosity=3);\nnothing #hide","category":"page"},{"location":"examples/graphene/","page":"Graphene band structure","title":"Graphene band structure","text":"EditURL = \"https://github.com/JuliaMolSim/DFTK.jl/blob/master/examples/graphene.jl\"","category":"page"},{"location":"examples/graphene/#Graphene-band-structure","page":"Graphene band structure","title":"Graphene band structure","text":"","category":"section"},{"location":"examples/graphene/","page":"Graphene band structure","title":"Graphene band structure","text":"(Image: ) (Image: )","category":"page"},{"location":"examples/graphene/","page":"Graphene band structure","title":"Graphene band structure","text":"This example plots the band structure of graphene, a 2D material. 2D band structures are not supported natively (yet), so we manually build a custom path in reciprocal space.","category":"page"},{"location":"examples/graphene/","page":"Graphene band structure","title":"Graphene band structure","text":"using DFTK\nusing Unitful\nusing UnitfulAtomic\nusing LinearAlgebra\n\n# Define the convergence parameters (these should be increased in production)\nL = 20 # height of the simulation box\nkgrid = [6, 6, 1]\nEcut = 15\ntemperature = 1e-3\n\n# Define the geometry and pseudopotential\na = 4.66 # lattice constant\na1 = a*[1/2,-sqrt(3)/2, 0]\na2 = a*[1/2, sqrt(3)/2, 0]\na3 = L*[0 , 0 , 1]\nlattice = [a1 a2 a3]\nC1 = [1/3,-1/3,0.0] # in reduced coordinates\nC2 = -C1\npositions = [C1, C2]\nC = ElementPsp(:C, psp=load_psp(\"hgh/pbe/c-q4\"))\natoms = [C, C]\n\n# Run SCF\nmodel = model_PBE(lattice, atoms, positions; temperature)\nbasis = PlaneWaveBasis(model; Ecut, kgrid)\nscfres = self_consistent_field(basis)\n\n# Construct 2D path through Brillouin zone\nsgnum = 13 # Graphene space group number\nkpath = irrfbz_path(model; dim=2, sgnum)\nplot_bandstructure(scfres, kpath; kline_density=20)","category":"page"},{"location":"examples/arbitrary_floattype/","page":"Arbitrary floating-point types","title":"Arbitrary floating-point types","text":"EditURL = \"https://github.com/JuliaMolSim/DFTK.jl/blob/master/examples/arbitrary_floattype.jl\"","category":"page"},{"location":"examples/arbitrary_floattype/#Arbitrary-floating-point-types","page":"Arbitrary floating-point types","title":"Arbitrary floating-point types","text":"","category":"section"},{"location":"examples/arbitrary_floattype/","page":"Arbitrary floating-point types","title":"Arbitrary floating-point types","text":"(Image: ) (Image: )","category":"page"},{"location":"examples/arbitrary_floattype/","page":"Arbitrary floating-point types","title":"Arbitrary floating-point types","text":"Since DFTK is completely generic in the floating-point type in its routines, there is no reason to perform the computation using double-precision arithmetic (i.e.Float64). Other floating-point types such as Float32 (single precision) are readily supported as well. On top of that we already reported[HLC2020] calculations in DFTK using elevated precision from DoubleFloats.jl or interval arithmetic using IntervalArithmetic.jl. In this example, however, we will concentrate on single-precision computations with Float32.","category":"page"},{"location":"examples/arbitrary_floattype/","page":"Arbitrary floating-point types","title":"Arbitrary floating-point types","text":"The setup of such a reduced-precision calculation is basically identical to the regular case, since Julia automatically compiles all routines of DFTK at the precision, which is used for the lattice vectors. Apart from setting up the model with an explicit cast of the lattice vectors to Float32, there is thus no change in user code required:","category":"page"},{"location":"examples/arbitrary_floattype/","page":"Arbitrary floating-point types","title":"Arbitrary floating-point types","text":"[HLC2020]: M. F. Herbst, A. Levitt, E. Cancès. A posteriori error estimation for the non-self-consistent Kohn-Sham equations ArXiv 2004.13549","category":"page"},{"location":"examples/arbitrary_floattype/","page":"Arbitrary floating-point types","title":"Arbitrary floating-point types","text":"using DFTK\n\n# Setup silicon lattice\na = 10.263141334305942 # lattice constant in Bohr\nlattice = a / 2 .* [[0 1 1.]; [1 0 1.]; [1 1 0.]]\nSi = ElementPsp(:Si, psp=load_psp(\"hgh/lda/Si-q4\"))\natoms = [Si, Si]\npositions = [ones(3)/8, -ones(3)/8]\n\n# Cast to Float32, setup model and basis\nmodel = model_DFT(Array{Float32}(lattice), atoms, positions, [:lda_x, :lda_c_vwn])\nbasis = PlaneWaveBasis(model, Ecut=7, kgrid=[4, 4, 4])\n\n# Run the SCF\nscfres = self_consistent_field(basis, tol=1e-3);\nnothing #hide","category":"page"},{"location":"examples/arbitrary_floattype/","page":"Arbitrary floating-point types","title":"Arbitrary floating-point types","text":"To check the calculation has really run in Float32, we check the energies and density are expressed in this floating-point type:","category":"page"},{"location":"examples/arbitrary_floattype/","page":"Arbitrary floating-point types","title":"Arbitrary floating-point types","text":"scfres.energies","category":"page"},{"location":"examples/arbitrary_floattype/","page":"Arbitrary floating-point types","title":"Arbitrary floating-point types","text":"eltype(scfres.energies.total)","category":"page"},{"location":"examples/arbitrary_floattype/","page":"Arbitrary floating-point types","title":"Arbitrary floating-point types","text":"eltype(scfres.ρ)","category":"page"},{"location":"examples/arbitrary_floattype/","page":"Arbitrary floating-point types","title":"Arbitrary floating-point types","text":"note: Generic linear algebra routines\nFor more unusual floating-point types (like IntervalArithmetic or DoubleFloats), which are not directly supported in the standard LinearAlgebra library of Julia one additional step is required: One needs to explicitly enable the generic versions of standard linear-algebra operations like cholesky or qr, which are needed inside DFTK by loading the GenericLinearAlgebra package in the user script (i.e. just add ad using GenericLinearAlgebra next to your using DFTK call).","category":"page"},{"location":"examples/gross_pitaevskii/","page":"Gross-Pitaevskii equation in one dimension","title":"Gross-Pitaevskii equation in one dimension","text":"EditURL = \"https://github.com/JuliaMolSim/DFTK.jl/blob/master/examples/gross_pitaevskii.jl\"","category":"page"},{"location":"examples/gross_pitaevskii/#gross-pitaevskii","page":"Gross-Pitaevskii equation in one dimension","title":"Gross-Pitaevskii equation in one dimension","text":"","category":"section"},{"location":"examples/gross_pitaevskii/","page":"Gross-Pitaevskii equation in one dimension","title":"Gross-Pitaevskii equation in one dimension","text":"(Image: ) (Image: )","category":"page"},{"location":"examples/gross_pitaevskii/","page":"Gross-Pitaevskii equation in one dimension","title":"Gross-Pitaevskii equation in one dimension","text":"In this example we will use DFTK to solve the Gross-Pitaevskii equation, and use this opportunity to explore a few internals.","category":"page"},{"location":"examples/gross_pitaevskii/#The-model","page":"Gross-Pitaevskii equation in one dimension","title":"The model","text":"","category":"section"},{"location":"examples/gross_pitaevskii/","page":"Gross-Pitaevskii equation in one dimension","title":"Gross-Pitaevskii equation in one dimension","text":"The Gross-Pitaevskii equation (GPE) is a simple non-linear equation used to model bosonic systems in a mean-field approach. Denoting by ψ the effective one-particle bosonic wave function, the time-independent GPE reads in atomic units:","category":"page"},{"location":"examples/gross_pitaevskii/","page":"Gross-Pitaevskii equation in one dimension","title":"Gross-Pitaevskii equation in one dimension","text":" H ψ = left(-frac12 Δ + V + 2 C ψ^2right) ψ = μ ψ qquad ψ_L^2 = 1","category":"page"},{"location":"examples/gross_pitaevskii/","page":"Gross-Pitaevskii equation in one dimension","title":"Gross-Pitaevskii equation in one dimension","text":"where C provides the strength of the boson-boson coupling. It's in particular a favorite model of applied mathematicians because it has a structure simpler than but similar to that of DFT, and displays interesting behavior (especially in higher dimensions with magnetic fields, see Gross-Pitaevskii equation with external magnetic field).","category":"page"},{"location":"examples/gross_pitaevskii/","page":"Gross-Pitaevskii equation in one dimension","title":"Gross-Pitaevskii equation in one dimension","text":"We wish to model this equation in 1D using DFTK. First we set up the lattice. For a 1D case we supply two zero lattice vectors,","category":"page"},{"location":"examples/gross_pitaevskii/","page":"Gross-Pitaevskii equation in one dimension","title":"Gross-Pitaevskii equation in one dimension","text":"a = 10\nlattice = a .* [[1 0 0.]; [0 0 0]; [0 0 0]];\nnothing #hide","category":"page"},{"location":"examples/gross_pitaevskii/","page":"Gross-Pitaevskii equation in one dimension","title":"Gross-Pitaevskii equation in one dimension","text":"which is special cased in DFTK to support 1D models.","category":"page"},{"location":"examples/gross_pitaevskii/","page":"Gross-Pitaevskii equation in one dimension","title":"Gross-Pitaevskii equation in one dimension","text":"For the potential term V we just pick a harmonic potential. The real-space grid is in 01) in fractional coordinates( see Lattices and lattice vectors), therefore:","category":"page"},{"location":"examples/gross_pitaevskii/","page":"Gross-Pitaevskii equation in one dimension","title":"Gross-Pitaevskii equation in one dimension","text":"pot(x) = (x - a/2)^2;\nnothing #hide","category":"page"},{"location":"examples/gross_pitaevskii/","page":"Gross-Pitaevskii equation in one dimension","title":"Gross-Pitaevskii equation in one dimension","text":"We setup each energy term in sequence: kinetic, potential and nonlinear term. For the non-linearity we use the LocalNonlinearity(f) term of DFTK, with f(ρ) = C ρ^α. This object introduces an energy term C ρ(r)^α dr to the total energy functional, thus a potential term α C ρ^α-1. In our case we thus need the parameters","category":"page"},{"location":"examples/gross_pitaevskii/","page":"Gross-Pitaevskii equation in one dimension","title":"Gross-Pitaevskii equation in one dimension","text":"C = 1.0\nα = 2;\nnothing #hide","category":"page"},{"location":"examples/gross_pitaevskii/","page":"Gross-Pitaevskii equation in one dimension","title":"Gross-Pitaevskii equation in one dimension","text":"… and with this build the model","category":"page"},{"location":"examples/gross_pitaevskii/","page":"Gross-Pitaevskii equation in one dimension","title":"Gross-Pitaevskii equation in one dimension","text":"using DFTK\nusing LinearAlgebra\n\nn_electrons = 1 # Increase this for fun\nterms = [Kinetic(),\n ExternalFromReal(r -> pot(r[1])),\n LocalNonlinearity(ρ -> C * ρ^α),\n]\nmodel = Model(lattice; n_electrons, terms, spin_polarization=:spinless); # spinless electrons\nnothing #hide","category":"page"},{"location":"examples/gross_pitaevskii/","page":"Gross-Pitaevskii equation in one dimension","title":"Gross-Pitaevskii equation in one dimension","text":"We discretize using a moderate Ecut (For 1D values up to 5000 are completely fine) and run a direct minimization algorithm:","category":"page"},{"location":"examples/gross_pitaevskii/","page":"Gross-Pitaevskii equation in one dimension","title":"Gross-Pitaevskii equation in one dimension","text":"basis = PlaneWaveBasis(model, Ecut=500, kgrid=(1, 1, 1))\nscfres = direct_minimization(basis, tol=1e-8) # This is a constrained preconditioned LBFGS\nscfres.energies","category":"page"},{"location":"examples/gross_pitaevskii/#Internals","page":"Gross-Pitaevskii equation in one dimension","title":"Internals","text":"","category":"section"},{"location":"examples/gross_pitaevskii/","page":"Gross-Pitaevskii equation in one dimension","title":"Gross-Pitaevskii equation in one dimension","text":"We use the opportunity to explore some of DFTK internals.","category":"page"},{"location":"examples/gross_pitaevskii/","page":"Gross-Pitaevskii equation in one dimension","title":"Gross-Pitaevskii equation in one dimension","text":"Extract the converged density and the obtained wave function:","category":"page"},{"location":"examples/gross_pitaevskii/","page":"Gross-Pitaevskii equation in one dimension","title":"Gross-Pitaevskii equation in one dimension","text":"ρ = real(scfres.ρ)[:, 1, 1, 1] # converged density, first spin component\nψ_fourier = scfres.ψ[1][:, 1]; # first k-point, all G components, first eigenvector\nnothing #hide","category":"page"},{"location":"examples/gross_pitaevskii/","page":"Gross-Pitaevskii equation in one dimension","title":"Gross-Pitaevskii equation in one dimension","text":"Transform the wave function to real space and fix the phase:","category":"page"},{"location":"examples/gross_pitaevskii/","page":"Gross-Pitaevskii equation in one dimension","title":"Gross-Pitaevskii equation in one dimension","text":"ψ = ifft(basis, basis.kpoints[1], ψ_fourier)[:, 1, 1]\nψ /= (ψ[div(end, 2)] / abs(ψ[div(end, 2)]));\nnothing #hide","category":"page"},{"location":"examples/gross_pitaevskii/","page":"Gross-Pitaevskii equation in one dimension","title":"Gross-Pitaevskii equation in one dimension","text":"Check whether ψ is normalised:","category":"page"},{"location":"examples/gross_pitaevskii/","page":"Gross-Pitaevskii equation in one dimension","title":"Gross-Pitaevskii equation in one dimension","text":"x = a * vec(first.(DFTK.r_vectors(basis)))\nN = length(x)\ndx = a / N # real-space grid spacing\n@assert sum(abs2.(ψ)) * dx ≈ 1.0","category":"page"},{"location":"examples/gross_pitaevskii/","page":"Gross-Pitaevskii equation in one dimension","title":"Gross-Pitaevskii equation in one dimension","text":"The density is simply built from ψ:","category":"page"},{"location":"examples/gross_pitaevskii/","page":"Gross-Pitaevskii equation in one dimension","title":"Gross-Pitaevskii equation in one dimension","text":"norm(scfres.ρ - abs2.(ψ))","category":"page"},{"location":"examples/gross_pitaevskii/","page":"Gross-Pitaevskii equation in one dimension","title":"Gross-Pitaevskii equation in one dimension","text":"We summarize the ground state in a nice plot:","category":"page"},{"location":"examples/gross_pitaevskii/","page":"Gross-Pitaevskii equation in one dimension","title":"Gross-Pitaevskii equation in one dimension","text":"using Plots\n\np = plot(x, real.(ψ), label=\"real(ψ)\")\nplot!(p, x, imag.(ψ), label=\"imag(ψ)\")\nplot!(p, x, ρ, label=\"ρ\")","category":"page"},{"location":"examples/gross_pitaevskii/","page":"Gross-Pitaevskii equation in one dimension","title":"Gross-Pitaevskii equation in one dimension","text":"The energy_hamiltonian function can be used to get the energy and effective Hamiltonian (derivative of the energy with respect to the density matrix) of a particular state (ψ, occupation). The density ρ associated to this state is precomputed and passed to the routine as an optimization.","category":"page"},{"location":"examples/gross_pitaevskii/","page":"Gross-Pitaevskii equation in one dimension","title":"Gross-Pitaevskii equation in one dimension","text":"E, ham = energy_hamiltonian(basis, scfres.ψ, scfres.occupation; ρ=scfres.ρ)\n@assert E.total == scfres.energies.total","category":"page"},{"location":"examples/gross_pitaevskii/","page":"Gross-Pitaevskii equation in one dimension","title":"Gross-Pitaevskii equation in one dimension","text":"Now the Hamiltonian contains all the blocks corresponding to k-points. Here, we just have one k-point:","category":"page"},{"location":"examples/gross_pitaevskii/","page":"Gross-Pitaevskii equation in one dimension","title":"Gross-Pitaevskii equation in one dimension","text":"H = ham.blocks[1];\nnothing #hide","category":"page"},{"location":"examples/gross_pitaevskii/","page":"Gross-Pitaevskii equation in one dimension","title":"Gross-Pitaevskii equation in one dimension","text":"H can be used as a linear operator (efficiently using FFTs), or converted to a dense matrix:","category":"page"},{"location":"examples/gross_pitaevskii/","page":"Gross-Pitaevskii equation in one dimension","title":"Gross-Pitaevskii equation in one dimension","text":"ψ11 = scfres.ψ[1][:, 1] # first k-point, first eigenvector\nHmat = Array(H) # This is now just a plain Julia matrix,\n# which we can compute and store in this simple 1D example\n@assert norm(Hmat * ψ11 - H * ψ11) < 1e-10","category":"page"},{"location":"examples/gross_pitaevskii/","page":"Gross-Pitaevskii equation in one dimension","title":"Gross-Pitaevskii equation in one dimension","text":"Let's check that ψ11 is indeed an eigenstate:","category":"page"},{"location":"examples/gross_pitaevskii/","page":"Gross-Pitaevskii equation in one dimension","title":"Gross-Pitaevskii equation in one dimension","text":"norm(H * ψ11 - dot(ψ11, H * ψ11) * ψ11)","category":"page"},{"location":"examples/gross_pitaevskii/","page":"Gross-Pitaevskii equation in one dimension","title":"Gross-Pitaevskii equation in one dimension","text":"Build a finite-differences version of the GPE operator H, as a sanity check:","category":"page"},{"location":"examples/gross_pitaevskii/","page":"Gross-Pitaevskii equation in one dimension","title":"Gross-Pitaevskii equation in one dimension","text":"A = Array(Tridiagonal(-ones(N - 1), 2ones(N), -ones(N - 1)))\nA[1, end] = A[end, 1] = -1\nK = A / dx^2 / 2\nV = Diagonal(pot.(x) + C .* α .* (ρ.^(α-1)))\nH_findiff = K + V;\nmaximum(abs.(H_findiff*ψ - (dot(ψ, H_findiff*ψ) / dot(ψ, ψ)) * ψ))","category":"page"},{"location":"examples/gross_pitaevskii_2D/","page":"Gross-Pitaevskii equation with external magnetic field","title":"Gross-Pitaevskii equation with external magnetic field","text":"EditURL = \"https://github.com/JuliaMolSim/DFTK.jl/blob/master/examples/gross_pitaevskii_2D.jl\"","category":"page"},{"location":"examples/gross_pitaevskii_2D/#Gross-Pitaevskii-equation-with-external-magnetic-field","page":"Gross-Pitaevskii equation with external magnetic field","title":"Gross-Pitaevskii equation with external magnetic field","text":"","category":"section"},{"location":"examples/gross_pitaevskii_2D/","page":"Gross-Pitaevskii equation with external magnetic field","title":"Gross-Pitaevskii equation with external magnetic field","text":"(Image: ) (Image: )","category":"page"},{"location":"examples/gross_pitaevskii_2D/","page":"Gross-Pitaevskii equation with external magnetic field","title":"Gross-Pitaevskii equation with external magnetic field","text":"We solve the 2D Gross-Pitaevskii equation with a magnetic field. This is similar to the previous example (Gross-Pitaevskii equation in one dimension), but with an extra term for the magnetic field. We reproduce here the results of https://arxiv.org/pdf/1611.02045.pdf Fig. 10","category":"page"},{"location":"examples/gross_pitaevskii_2D/","page":"Gross-Pitaevskii equation with external magnetic field","title":"Gross-Pitaevskii equation with external magnetic field","text":"using DFTK\nusing StaticArrays\nusing Plots\n\n# Unit cell. Having one of the lattice vectors as zero means a 2D system\na = 15\nlattice = a .* [[1 0 0.]; [0 1 0]; [0 0 0]];\n\n# Confining scalar potential, and magnetic vector potential\npot(x, y, z) = ((x - a/2)^2 + (y - a/2)^2)/2\nω = .6\nApot(x, y, z) = ω * @SVector [y - a/2, -(x - a/2), 0]\nApot(X) = Apot(X...);\n\n\n# Parameters\nEcut = 20 # Increase this for production\nη = 500\nC = η/2\nα = 2\nn_electrons = 1; # Increase this for fun\n\n# Collect all the terms, build and run the model\nterms = [Kinetic(),\n ExternalFromReal(X -> pot(X...)),\n LocalNonlinearity(ρ -> C * ρ^α),\n Magnetic(Apot),\n]\nmodel = Model(lattice; n_electrons, terms, spin_polarization=:spinless) # spinless electrons\nbasis = PlaneWaveBasis(model; Ecut, kgrid=(1, 1, 1))\nscfres = direct_minimization(basis, tol=1e-5) # Reduce tol for production\nheatmap(scfres.ρ[:, :, 1, 1], c=:blues)","category":"page"},{"location":"examples/pseudopotentials/","page":"Pseudopotentials","title":"Pseudopotentials","text":"EditURL = \"https://github.com/JuliaMolSim/DFTK.jl/blob/master/examples/pseudopotentials.jl\"","category":"page"},{"location":"examples/pseudopotentials/#Pseudopotentials","page":"Pseudopotentials","title":"Pseudopotentials","text":"","category":"section"},{"location":"examples/pseudopotentials/","page":"Pseudopotentials","title":"Pseudopotentials","text":"(Image: ) (Image: )","category":"page"},{"location":"examples/pseudopotentials/","page":"Pseudopotentials","title":"Pseudopotentials","text":"In this example, we'll look at how to use various pseudopotential (PSP) formats in DFTK and discuss briefly the utility and importance of pseudopotentials.","category":"page"},{"location":"examples/pseudopotentials/","page":"Pseudopotentials","title":"Pseudopotentials","text":"Currently, DFTK supports norm-conserving (NC) PSPs in separable (Kleinman-Bylander) form. Two file formats can currently be read and used: analytical Hartwigsen-Goedecker-Hutter (HGH) PSPs and numeric Unified Pseudopotential Format (UPF) PSPs.","category":"page"},{"location":"examples/pseudopotentials/","page":"Pseudopotentials","title":"Pseudopotentials","text":"In brief, the pseudopotential approach replaces the all-electron atomic potential with an effective atomic potential. In this pseudopotential, tightly-bound core electrons are completely eliminated (\"frozen\") and chemically-active valence electron wavefunctions are replaced with smooth pseudo-wavefunctions whose Fourier representations decay quickly. Both these transformations aim at reducing the number of Fourier modes required to accurately represent the wavefunction of the system, greatly increasing computational efficiency.","category":"page"},{"location":"examples/pseudopotentials/","page":"Pseudopotentials","title":"Pseudopotentials","text":"Different PSP generation codes produce various file formats which contain the same general quantities required for pesudopotential evaluation. HGH PSPs are constructed from a fixed functional form based on Gaussians, and the files simply tablulate various coefficients fitted for a given element. UPF PSPs take a more flexible approach where the functional form used to generate the PSP is arbitrary, and the resulting functions are tabulated on a radial grid in the file. The UPF file format is documented here: http://pseudopotentials.quantum-espresso.org/home/unified-pseudopotential-format.","category":"page"},{"location":"examples/pseudopotentials/","page":"Pseudopotentials","title":"Pseudopotentials","text":"In this example, we will compare the convergence of an analytical HGH PSP with a modern UPF PSP from PseudoDojo. Then, we will compare the bandstructure at the converged parameters calculated using the two PSPs.","category":"page"},{"location":"examples/pseudopotentials/","page":"Pseudopotentials","title":"Pseudopotentials","text":"using DFTK\nusing Downloads\nusing Unitful\nusing Plots","category":"page"},{"location":"examples/pseudopotentials/","page":"Pseudopotentials","title":"Pseudopotentials","text":"Here, we will use Perdew-Wang LDA PSP from PseudoDojo, which is available in the JuliaMolSim PseudoLibrary.","category":"page"},{"location":"examples/pseudopotentials/","page":"Pseudopotentials","title":"Pseudopotentials","text":"PSEUDOLIB = \"https://raw.githubusercontent.com/JuliaMolSim/PseudoLibrary\"\nCOMMIT = \"56d1774708e1adfff35d30a403004cb98de4224b\"\nURL_UPF = PSEUDOLIB * \"/$COMMIT/pseudos/pd_nc_sr_lda_standard_04_upf/Li.upf\";\nnothing #hide","category":"page"},{"location":"examples/pseudopotentials/","page":"Pseudopotentials","title":"Pseudopotentials","text":"We load the HGH and UPF PSPs using load_psp, which determines the file format using the file extension.","category":"page"},{"location":"examples/pseudopotentials/","page":"Pseudopotentials","title":"Pseudopotentials","text":"psp_hgh = load_psp(\"hgh/lda/li-q3.hgh\");\npath_upf = Downloads.download(URL_UPF, joinpath(tempdir(), \"Li.upf\"))\npsp_upf = load_psp(path_upf);\nnothing #hide","category":"page"},{"location":"examples/pseudopotentials/","page":"Pseudopotentials","title":"Pseudopotentials","text":"First, we'll take a look at the energy cutoff convergence of these two pseudopotentials. For both pseudos, a reference energy is calculated with a cutoff of 140 Hartree, and SCF calculations are run at increasing cutoffs until 1 meV / atom convergence is reached.","category":"page"},{"location":"examples/pseudopotentials/","page":"Pseudopotentials","title":"Pseudopotentials","text":"<img src=\"../../assets/li_pseudos_ecut_convergence.png\" width=600 height=400 />","category":"page"},{"location":"examples/pseudopotentials/","page":"Pseudopotentials","title":"Pseudopotentials","text":"The converged cutoffs are 128 Ha and 36 Ha for the HGH and UPF pseudos respectively. We see that the HGH pseudopotential is much harder, i.e. it requires a higher energy cutoff, than the UPF PSP. In general, numeric pseudopotentials tend to be softer than analytical pseudos because of the flexibility of sampling arbitrary functions on a grid.","category":"page"},{"location":"examples/pseudopotentials/","page":"Pseudopotentials","title":"Pseudopotentials","text":"Next, to see that the different pseudopotentials give reasonbly similar results, we'll look at the bandstructures calculated using the HGH and UPF PSPs. Even though the convered cutoffs are 128 and 36 Ha, we perform these calculations with a cutoff of 24 Ha for both PSPs.","category":"page"},{"location":"examples/pseudopotentials/","page":"Pseudopotentials","title":"Pseudopotentials","text":"function run_bands(psp)\n a = -1.53877u\"Å\"\n b = -2.66523u\"Å\"\n c = -4.92295u\"Å\"\n lattice = [ a a 0;\n -b b 0;\n 0 0 -c]\n Li = ElementPsp(:Li; psp)\n atoms = [Li, Li]\n positions = [[1/3, 2/3, 1/4],\n [2/3, 1/3, 3/4]]\n\n # These are (as you saw above) completely unconverged parameters\n model = model_LDA(lattice, atoms, positions; temperature=1e-2)\n basis = PlaneWaveBasis(model; Ecut=24, kgrid=(6, 6, 4))\n\n scfres = self_consistent_field(basis; tol=1e-4)\n bandplot = plot_bandstructure(scfres)\n (; scfres, bandplot)\nend;\nnothing #hide","category":"page"},{"location":"examples/pseudopotentials/","page":"Pseudopotentials","title":"Pseudopotentials","text":"The SCF and bandstructure calculations can then be performed using the two PSPs, where we notice in particular the difference in total energies.","category":"page"},{"location":"examples/pseudopotentials/","page":"Pseudopotentials","title":"Pseudopotentials","text":"result_hgh = run_bands(psp_hgh)\nresult_hgh.scfres.energies","category":"page"},{"location":"examples/pseudopotentials/","page":"Pseudopotentials","title":"Pseudopotentials","text":"result_upf = run_bands(psp_upf)\nresult_upf.scfres.energies","category":"page"},{"location":"examples/pseudopotentials/","page":"Pseudopotentials","title":"Pseudopotentials","text":"But while total energies are not physical and thus allowed to differ, the bands (as an example for a physical quantity) are very similar for both pseudos:","category":"page"},{"location":"examples/pseudopotentials/","page":"Pseudopotentials","title":"Pseudopotentials","text":"plot(result_hgh.bandplot, result_upf.bandplot, titles=[\"HGH\" \"UPF\"], size=(800, 400))","category":"page"},{"location":"guide/installation/#Installation","page":"Installation","title":"Installation","text":"","category":"section"},{"location":"guide/installation/","page":"Installation","title":"Installation","text":"In case you don't have a working Julia installation yet, first download the Julia binaries and follow the Julia installation instructions. At least Julia 1.6 is required for DFTK.","category":"page"},{"location":"guide/installation/","page":"Installation","title":"Installation","text":"Afterwards you can install DFTK like any other package in Julia. For example run in your Julia REPL terminal:","category":"page"},{"location":"guide/installation/","page":"Installation","title":"Installation","text":"import Pkg\nPkg.add(\"DFTK\")","category":"page"},{"location":"guide/installation/","page":"Installation","title":"Installation","text":"which will install the latest DFTK release. Alternatively (if you like to be fully up to date) install the master branch:","category":"page"},{"location":"guide/installation/","page":"Installation","title":"Installation","text":"import Pkg\nPkg.add(name=\"DFTK\", rev=\"master\")","category":"page"},{"location":"guide/installation/","page":"Installation","title":"Installation","text":"DFTK is continuously tested on Debian, Ubuntu, mac OS and Windows and should work on these operating systems out of the box.","category":"page"},{"location":"guide/installation/","page":"Installation","title":"Installation","text":"That's it. With this you are all set to run the code in the Tutorial or the examples directory.","category":"page"},{"location":"guide/installation/","page":"Installation","title":"Installation","text":"tip: DFTK version compatibility\nWe follow the usual semantic versioning conventions of Julia. Therefore all DFTK versions with the same minor (e.g. all 0.6.x) should be API compatible, while different minors (e.g. 0.7.y) might have breaking changes. These will also be announced in the release notes.","category":"page"},{"location":"guide/installation/#Recommended-optional-packages","page":"Installation","title":"Recommended optional packages","text":"","category":"section"},{"location":"guide/installation/","page":"Installation","title":"Installation","text":"While not strictly speaking required to use DFTK it is usually convenient to install a couple of standard packages from the AtomsBase ecosystem, such as AtomsIO.jl or ASEconvert.jl. You can install these two packages using","category":"page"},{"location":"guide/installation/","page":"Installation","title":"Installation","text":"import Pkg\nPkg.add([\"AtomsIO\", \"ASEconvert\"])","category":"page"},{"location":"guide/installation/","page":"Installation","title":"Installation","text":"While AtomsIO allows you to read (and write) a large range of standard file formats for atomistic structures, ASEconvert integrates DFTK with a number of convenience features of the ASE, the atomistic simulation environment. See Creating and modelling metallic supercells for an example where ASE is used within a DFTK workflow.","category":"page"},{"location":"guide/installation/","page":"Installation","title":"Installation","text":"note: Python dependencies in Julia\nThere are two main packages to use python dependencies from Julia, namely PythonCall and PyCall. These packages can be used side by side, but some care is needed. Since the AtomsBase ecosystem (thus AtomsIO and ASEconvert) is build based on PythonCall, be sure to follow these guidelines when using them in combination with PyCall-based packages (such as PyPlot).","category":"page"},{"location":"guide/installation/#Developer-setup","page":"Installation","title":"Developer setup","text":"","category":"section"},{"location":"guide/installation/","page":"Installation","title":"Installation","text":"If you want to start developing DFTK Julia has the option to automatically keep track of the changes of the sources during development. This means, for example, that Revise will automatically be aware of the changes you make to the DFTK sources and automatically reload your changes inside an active Julia session. To achieve such a setup you have two recommended options:","category":"page"},{"location":"guide/installation/","page":"Installation","title":"Installation","text":"Add a development version of DFTK to the global Julia environment:\nimport Pkg\nPkg.develop(\"DFTK\")\nThis clones DFTK to the path ~/.julia/dev/DFTK\" (on Linux). Note that with this method you cannot install both the stable and the development version of DFTK into your global environment.\nClone DFTK into a location of your choice\n$ git clone https://github.com/JuliaMolSim/DFTK.jl /some/path/\nWhenever you want to use exactly this development version of DFTK in a Julia environment (e.g. the global one) add it as a develop package:\nimport Pkg\nPkg.develop(\"/some/path/\")\nTo run a script or start a Julia REPL using exactly this source tree as the DFTK version, use the --project flag of Julia, see this documentation for details. For example to start a Julia REPL with this version of DFTK use\n$ julia --project=/some/path/\nThe advantage of this method is that you can easily have multiple clones of DFTK with potentially different modifications made.","category":"page"},{"location":"tricks/scf_checkpoints/","page":"Saving SCF results on disk and SCF checkpoints","title":"Saving SCF results on disk and SCF checkpoints","text":"EditURL = \"https://github.com/JuliaMolSim/DFTK.jl/blob/master/docs/src/tricks/scf_checkpoints.jl\"","category":"page"},{"location":"tricks/scf_checkpoints/#Saving-SCF-results-on-disk-and-SCF-checkpoints","page":"Saving SCF results on disk and SCF checkpoints","title":"Saving SCF results on disk and SCF checkpoints","text":"","category":"section"},{"location":"tricks/scf_checkpoints/","page":"Saving SCF results on disk and SCF checkpoints","title":"Saving SCF results on disk and SCF checkpoints","text":"For longer DFT calculations it is pretty standard to run them on a cluster in advance and to perform postprocessing (band structure calculation, plotting of density, etc.) at a later point and potentially on a different machine.","category":"page"},{"location":"tricks/scf_checkpoints/","page":"Saving SCF results on disk and SCF checkpoints","title":"Saving SCF results on disk and SCF checkpoints","text":"To support such workflows DFTK offers the two functions save_scfres and load_scfres, which allow to save the data structure returned by self_consistent_field on disk or retrieve it back into memory, respectively. For this purpose DFTK uses the JLD2.jl file format and Julia package. For the moment this process is considered an experimental feature and has a number of caveats, see the warnings below.","category":"page"},{"location":"tricks/scf_checkpoints/","page":"Saving SCF results on disk and SCF checkpoints","title":"Saving SCF results on disk and SCF checkpoints","text":"warning: Saving `scfres` is experimental\nThe load_scfres and save_scfres pair of functions are experimental features. This means:The interface of these functions as well as the format in which the data is stored on disk can change incompatibly in the future. At this point we make no promises ...\nJLD2 is not yet completely matured and it is recommended to only use it for short-term storage and not to archive scientific results.\nIf you are using the functions to transfer data between different machines ensure that you use the same version of Julia, JLD2 and DFTK for saving and loading data.","category":"page"},{"location":"tricks/scf_checkpoints/","page":"Saving SCF results on disk and SCF checkpoints","title":"Saving SCF results on disk and SCF checkpoints","text":"To illustrate the use of the functions in practice we will compute the total energy of the O₂ molecule at PBE level. To get the triplet ground state we use a collinear spin polarisation (see Collinear spin and magnetic systems for details) and a bit of temperature to ease convergence:","category":"page"},{"location":"tricks/scf_checkpoints/","page":"Saving SCF results on disk and SCF checkpoints","title":"Saving SCF results on disk and SCF checkpoints","text":"using DFTK\nusing LinearAlgebra\nusing JLD2\n\nd = 2.079 # oxygen-oxygen bondlength\na = 9.0 # size of the simulation box\nlattice = a * I(3)\nO = ElementPsp(:O, psp=load_psp(\"hgh/pbe/O-q6.hgh\"))\natoms = [O, O]\npositions = d / 2a * [[0, 0, 1], [0, 0, -1]]\nmagnetic_moments = [1., 1.]\n\nEcut = 10 # Far too small to be converged\nmodel = model_PBE(lattice, atoms, positions; temperature=0.02, smearing=Smearing.Gaussian(),\n magnetic_moments)\nbasis = PlaneWaveBasis(model; Ecut, kgrid=[1, 1, 1])\n\nscfres = self_consistent_field(basis, tol=1e-2, ρ=guess_density(basis, magnetic_moments))\nsave_scfres(\"scfres.jld2\", scfres);\nnothing #hide","category":"page"},{"location":"tricks/scf_checkpoints/","page":"Saving SCF results on disk and SCF checkpoints","title":"Saving SCF results on disk and SCF checkpoints","text":"scfres.energies","category":"page"},{"location":"tricks/scf_checkpoints/","page":"Saving SCF results on disk and SCF checkpoints","title":"Saving SCF results on disk and SCF checkpoints","text":"The scfres.jld2 file could now be transfered to a different computer, Where one could fire up a REPL to inspect the results of the above calculation:","category":"page"},{"location":"tricks/scf_checkpoints/","page":"Saving SCF results on disk and SCF checkpoints","title":"Saving SCF results on disk and SCF checkpoints","text":"using DFTK\nusing JLD2\nloaded = load_scfres(\"scfres.jld2\")\npropertynames(loaded)","category":"page"},{"location":"tricks/scf_checkpoints/","page":"Saving SCF results on disk and SCF checkpoints","title":"Saving SCF results on disk and SCF checkpoints","text":"loaded.energies","category":"page"},{"location":"tricks/scf_checkpoints/","page":"Saving SCF results on disk and SCF checkpoints","title":"Saving SCF results on disk and SCF checkpoints","text":"Since the loaded data contains exactly the same data as the scfres returned by the SCF calculation one could use it to plot a band structure, e.g. plot_bandstructure(load_scfres(\"scfres.jld2\")) directly from the stored data.","category":"page"},{"location":"tricks/scf_checkpoints/#Checkpointing-of-SCF-calculations","page":"Saving SCF results on disk and SCF checkpoints","title":"Checkpointing of SCF calculations","text":"","category":"section"},{"location":"tricks/scf_checkpoints/","page":"Saving SCF results on disk and SCF checkpoints","title":"Saving SCF results on disk and SCF checkpoints","text":"A related feature, which is very useful especially for longer calculations with DFTK is automatic checkpointing, where the state of the SCF is periodically written to disk. The advantage is that in case the calculation errors or gets aborted due to overrunning the walltime limit one does not need to start from scratch, but can continue the calculation from the last checkpoint.","category":"page"},{"location":"tricks/scf_checkpoints/","page":"Saving SCF results on disk and SCF checkpoints","title":"Saving SCF results on disk and SCF checkpoints","text":"To enable automatic checkpointing in DFTK one needs to pass the ScfSaveCheckpoints callback to self_consistent_field, for example:","category":"page"},{"location":"tricks/scf_checkpoints/","page":"Saving SCF results on disk and SCF checkpoints","title":"Saving SCF results on disk and SCF checkpoints","text":"callback = DFTK.ScfSaveCheckpoints()\nscfres = self_consistent_field(basis; ρ=guess_density(basis, magnetic_moments),\n tol=1e-2, callback);\nnothing #hide","category":"page"},{"location":"tricks/scf_checkpoints/","page":"Saving SCF results on disk and SCF checkpoints","title":"Saving SCF results on disk and SCF checkpoints","text":"Notice that using this callback makes the SCF go silent since the passed callback parameter overwrites the default value (namely DefaultScfCallback()) which exactly gives the familiar printing of the SCF convergence. If you want to have both (printing and checkpointing) you need to chain both callbacks:","category":"page"},{"location":"tricks/scf_checkpoints/","page":"Saving SCF results on disk and SCF checkpoints","title":"Saving SCF results on disk and SCF checkpoints","text":"callback = DFTK.ScfDefaultCallback() ∘ DFTK.ScfSaveCheckpoints(keep=true)\nscfres = self_consistent_field(basis; ρ=guess_density(basis, magnetic_moments),\n tol=1e-2, callback);\nnothing #hide","category":"page"},{"location":"tricks/scf_checkpoints/","page":"Saving SCF results on disk and SCF checkpoints","title":"Saving SCF results on disk and SCF checkpoints","text":"For more details on using callbacks with DFTK's self_consistent_field function see Monitoring self-consistent field calculations.","category":"page"},{"location":"tricks/scf_checkpoints/","page":"Saving SCF results on disk and SCF checkpoints","title":"Saving SCF results on disk and SCF checkpoints","text":"By default checkpoint is saved in the file dftk_scf_checkpoint.jld2, which is deleted automatically once the SCF completes successfully. If one wants to keep the file one needs to specify keep=true as has been done in the ultimate SCF for demonstration purposes: now we can continue the previous calculation from the last checkpoint as if the SCF had been aborted. For this one just loads the checkpoint with load_scfres:","category":"page"},{"location":"tricks/scf_checkpoints/","page":"Saving SCF results on disk and SCF checkpoints","title":"Saving SCF results on disk and SCF checkpoints","text":"oldstate = load_scfres(\"dftk_scf_checkpoint.jld2\")\nscfres = self_consistent_field(oldstate.basis, ρ=oldstate.ρ,\n ψ=oldstate.ψ, tol=1e-3);\nnothing #hide","category":"page"},{"location":"tricks/scf_checkpoints/","page":"Saving SCF results on disk and SCF checkpoints","title":"Saving SCF results on disk and SCF checkpoints","text":"note: Availability of `load_scfres`, `save_scfres` and `ScfSaveCheckpoints`\nAs JLD2 is an optional dependency of DFTK these three functions are only available once one has both imported DFTK and JLD2 (using DFTK and using JLD2).","category":"page"},{"location":"tricks/scf_checkpoints/","page":"Saving SCF results on disk and SCF checkpoints","title":"Saving SCF results on disk and SCF checkpoints","text":"(Cleanup files generated by this notebook)","category":"page"},{"location":"tricks/scf_checkpoints/","page":"Saving SCF results on disk and SCF checkpoints","title":"Saving SCF results on disk and SCF checkpoints","text":"rm(\"dftk_scf_checkpoint.jld2\")\nrm(\"scfres.jld2\")","category":"page"},{"location":"api/#API-reference","page":"API reference","title":"API reference","text":"","category":"section"},{"location":"api/","page":"API reference","title":"API reference","text":"This page provides a plain list of all documented functions, structs, modules and macros in DFTK. Note that this list is neither structured, complete nor particularly clean, so it only provides rough orientation at the moment. The best reference is the code itself.","category":"page"},{"location":"api/","page":"API reference","title":"API reference","text":"Modules = [DFTK, DFTK.Smearing]","category":"page"},{"location":"api/#DFTK.DFTK","page":"API reference","title":"DFTK.DFTK","text":"DFTK –- The density-functional toolkit. Provides functionality for experimenting with plane-wave density-functional theory algorithms.\n\n\n\n\n\n","category":"module"},{"location":"api/#DFTK.DFTK_DATADIR","page":"API reference","title":"DFTK.DFTK_DATADIR","text":"The default search location for Pseudopotential data files\n\n\n\n\n\n","category":"constant"},{"location":"api/#DFTK.timer","page":"API reference","title":"DFTK.timer","text":"TimerOutput object used to store DFTK timings.\n\n\n\n\n\n","category":"constant"},{"location":"api/#DFTK.AbstractArchitecture","page":"API reference","title":"DFTK.AbstractArchitecture","text":"Abstract supertype for architectures supported by DFTK.\n\n\n\n\n\n","category":"type"},{"location":"api/#DFTK.AdaptiveBands","page":"API reference","title":"DFTK.AdaptiveBands","text":"Dynamically adapt number of bands to be converged to ensure that the orbitals of lowest occupation are occupied to at most occupation_threshold. To obtain rapid convergence of the eigensolver a gap between the eigenvalues of the last occupied orbital and the last computed (but not converged) orbital of gap_min is ensured.\n\n\n\n\n\n","category":"type"},{"location":"api/#DFTK.Applyχ0Model","page":"API reference","title":"DFTK.Applyχ0Model","text":"Full χ0 application, optionally dropping terms or disabling Sternheimer. All keyword arguments passed to apply_χ0.\n\n\n\n\n\n","category":"type"},{"location":"api/#DFTK.AtomicLocal","page":"API reference","title":"DFTK.AtomicLocal","text":"Atomic local potential defined by model.atoms.\n\n\n\n\n\n","category":"type"},{"location":"api/#DFTK.AtomicNonlocal","page":"API reference","title":"DFTK.AtomicNonlocal","text":"Nonlocal term coming from norm-conserving pseudopotentials in Kleinmann-Bylander form. textEnergy = sum_a sum_ij sum_n f_n ψ_np_ai D_ij p_ajψ_n\n\n\n\n\n\n","category":"type"},{"location":"api/#DFTK.BlowupAbinit","page":"API reference","title":"DFTK.BlowupAbinit","text":"Blow-up function as used in Abinit.\n\n\n\n\n\n","category":"type"},{"location":"api/#DFTK.BlowupCHV","page":"API reference","title":"DFTK.BlowupCHV","text":"Blow-up function as proposed in https://arxiv.org/abs/2210.00442 The blow-up order of the function is fixed to ensure C^2 regularity of the energies bands away from crossings and Lipschitz continuity at crossings.\n\n\n\n\n\n","category":"type"},{"location":"api/#DFTK.BlowupIdentity","page":"API reference","title":"DFTK.BlowupIdentity","text":"Default blow-up corresponding to the standard kinetic energies.\n\n\n\n\n\n","category":"type"},{"location":"api/#DFTK.DielectricMixing","page":"API reference","title":"DFTK.DielectricMixing","text":"We use a simplification of the Resta model DOI 10.1103/physrevb.16.2717 and set χ_0(q) = fracC_0 G^24π (1 - C_0 G^2 k_TF^2) where C_0 = 1 - ε_r with ε_r being the macroscopic relative permittivity. We neglect K_textxc, such that J^-1 frack_TF^2 - C_0 G^2ε_r k_TF^2 - C_0 G^2\n\nBy default it assumes a relative permittivity of 10 (similar to Silicon). εr == 1 is equal to SimpleMixing and εr == Inf to KerkerMixing. The mixing is applied to ρ and ρ_textspin in the same way.\n\n\n\n\n\n","category":"type"},{"location":"api/#DFTK.DielectricModel","page":"API reference","title":"DFTK.DielectricModel","text":"A localised dielectric model for χ_0:\n\nsqrtL(x) textIFFT fracC_0 G^24π (1 - C_0 G^2 k_TF^2) textFFT sqrtL(x)\n\nwhere C_0 = 1 - ε_r, L(r) is a real-space localization function and otherwise the same conventions are used as in DielectricMixing.\n\n\n\n\n\n","category":"type"},{"location":"api/#DFTK.DivAgradOperator","page":"API reference","title":"DFTK.DivAgradOperator","text":"Nonlocal \"divAgrad\" operator -½ (A ) where A is a scalar field on the real-space grid. The -½ is included, such that this operator is a generalisation of the kinetic energy operator (which is obtained for A=1).\n\n\n\n\n\n","category":"type"},{"location":"api/#DFTK.ElementCohenBergstresser-Tuple{Any}","page":"API reference","title":"DFTK.ElementCohenBergstresser","text":"Element where the interaction with electrons is modelled as in CohenBergstresser1966. Only the homonuclear lattices of the diamond structure are implemented (i.e. Si, Ge, Sn).\n\nkey may be an element symbol (like :Si), an atomic number (e.g. 14) or an element name (e.g. \"silicon\")\n\n\n\n\n\n","category":"method"},{"location":"api/#DFTK.ElementCoulomb-Tuple{Any}","page":"API reference","title":"DFTK.ElementCoulomb","text":"Element interacting with electrons via a bare Coulomb potential (for all-electron calculations) key may be an element symbol (like :Si), an atomic number (e.g. 14) or an element name (e.g. \"silicon\")\n\n\n\n\n\n","category":"method"},{"location":"api/#DFTK.ElementGaussian-Tuple{Any, Any}","page":"API reference","title":"DFTK.ElementGaussian","text":"Element interacting with electrons via a Gaussian potential. Symbol is non-mandatory.\n\n\n\n\n\n","category":"method"},{"location":"api/#DFTK.ElementPsp-Tuple{Any}","page":"API reference","title":"DFTK.ElementPsp","text":"Element interacting with electrons via a pseudopotential model. key may be an element symbol (like :Si), an atomic number (e.g. 14) or an element name (e.g. \"silicon\")\n\n\n\n\n\n","category":"method"},{"location":"api/#DFTK.Energies","page":"API reference","title":"DFTK.Energies","text":"A simple struct to contain a vector of energies, and utilities to print them in a nice format.\n\n\n\n\n\n","category":"type"},{"location":"api/#DFTK.Entropy","page":"API reference","title":"DFTK.Entropy","text":"Entropy term -TS, where S is the electronic entropy. Turns the energy E into the free energy F=E-TS. This is in particular useful because the free energy, not the energy, is minimized at self-consistency.\n\n\n\n\n\n","category":"type"},{"location":"api/#DFTK.Ewald","page":"API reference","title":"DFTK.Ewald","text":"Ewald term: electrostatic energy per unit cell of the array of point charges defined by model.atoms in a uniform background of compensating charge yielding net neutrality.\n\n\n\n\n\n","category":"type"},{"location":"api/#DFTK.ExternalFromFourier","page":"API reference","title":"DFTK.ExternalFromFourier","text":"External potential from the (unnormalized) Fourier coefficients V(G) G is passed in cartesian coordinates\n\n\n\n\n\n","category":"type"},{"location":"api/#DFTK.ExternalFromReal","page":"API reference","title":"DFTK.ExternalFromReal","text":"External potential from an analytic function V (in cartesian coordinates). No low-pass filtering is performed.\n\n\n\n\n\n","category":"type"},{"location":"api/#DFTK.FermiTwoStage","page":"API reference","title":"DFTK.FermiTwoStage","text":"Two-stage Fermi level finding algorithm starting from a Gaussian-smearing guess.\n\n\n\n\n\n","category":"type"},{"location":"api/#DFTK.FixedBands","page":"API reference","title":"DFTK.FixedBands","text":"In each SCF step converge exactly n_bands_converge, computing along the way exactly n_bands_compute (usually a few more to ease convergence in systems with small gaps).\n\n\n\n\n\n","category":"type"},{"location":"api/#DFTK.FourierMultiplication","page":"API reference","title":"DFTK.FourierMultiplication","text":"Fourier space multiplication, like a kinetic energy term: (Hψ)(G) = multiplier(G) ψ(G)\n\n\n\n\n\n","category":"type"},{"location":"api/#DFTK.GPU-Union{Tuple{Type{T}}, Tuple{T}} where T<:AbstractArray","page":"API reference","title":"DFTK.GPU","text":"Construct a particular GPU architecture by passing the ArrayType\n\n\n\n\n\n","category":"method"},{"location":"api/#DFTK.Hartree","page":"API reference","title":"DFTK.Hartree","text":"Hartree term: for a decaying potential V the energy would be\n\n1/2 ∫ρ(x)ρ(y)V(x-y) dxdy\n\nwith the integral on x in the unit cell and of y in the whole space. For the Coulomb potential with periodic boundary conditions, this is rather\n\n1/2 ∫ρ(x)ρ(y) G(x-y) dx dy\n\nwhere G is the Green's function of the periodic Laplacian with zero mean (-Δ G = sum{R} 4π δR, integral of G zero on a unit cell).\n\n\n\n\n\n","category":"type"},{"location":"api/#DFTK.KerkerDosMixing","page":"API reference","title":"DFTK.KerkerDosMixing","text":"The same as KerkerMixing, but the Thomas-Fermi wavevector is computed from the current density of states at the Fermi level.\n\n\n\n\n\n","category":"type"},{"location":"api/#DFTK.KerkerMixing","page":"API reference","title":"DFTK.KerkerMixing","text":"Kerker mixing: J^-1 fracG^2k_TF^2 + G^2 where k_TF is the Thomas-Fermi wave vector. For spin-polarized calculations by default the spin density is not preconditioned. Unless a non-default value for ΔDOS_Ω is specified. This value should roughly be the expected difference in density of states (per unit volume) between spin-up and spin-down.\n\nNotes:\n\nAbinit calls 1k_TF the dielectric screening length (parameter dielng)\n\n\n\n\n\n","category":"type"},{"location":"api/#DFTK.Kinetic","page":"API reference","title":"DFTK.Kinetic","text":"Kinetic energy: 1/2 sumn fn ∫ |∇ψn|^2 * blowup(-i∇Ψ).\n\n\n\n\n\n","category":"type"},{"location":"api/#DFTK.Kpoint","page":"API reference","title":"DFTK.Kpoint","text":"Discretization information for k-point-dependent quantities such as orbitals. More generally, a k-point is a block of the Hamiltonian; eg collinear spin is treated by doubling the number of kpoints.\n\n\n\n\n\n","category":"type"},{"location":"api/#DFTK.LazyHcat","page":"API reference","title":"DFTK.LazyHcat","text":"Simple wrapper to represent a matrix formed by the concatenation of column blocks: it is mostly equivalent to hcat, but doesn't allocate the full matrix. LazyHcat only supports a few multiplication routines: furthermore, a multiplication involving this structure will always yield a plain array (and not a LazyHcat structure). LazyHcat is a lightweight subset of BlockArrays.jl's functionalities, but has the advantage to be able to store GPU Arrays (BlockArrays is heavily built on Julia's CPU Array).\n\n\n\n\n\n","category":"type"},{"location":"api/#DFTK.LdosModel","page":"API reference","title":"DFTK.LdosModel","text":"Represents the LDOS-based χ_0 model\n\nχ_0(r r) = (-D_textloc(r) δ(r r) + D_textloc(r) D_textloc(r) D)\n\nwhere D_textloc is the local density of states and D the density of states. For details see Herbst, Levitt 2020 arXiv:2009.01665\n\n\n\n\n\n","category":"type"},{"location":"api/#DFTK.LibxcDensities-Tuple{Any, Integer, Any, Any}","page":"API reference","title":"DFTK.LibxcDensities","text":"Compute density in real space and its derivatives starting from ρ\n\n\n\n\n\n","category":"method"},{"location":"api/#DFTK.LocalNonlinearity","page":"API reference","title":"DFTK.LocalNonlinearity","text":"Local nonlinearity, with energy ∫f(ρ) where ρ is the density\n\n\n\n\n\n","category":"type"},{"location":"api/#DFTK.Magnetic","page":"API reference","title":"DFTK.Magnetic","text":"Magnetic term A(-i). It is assumed (but not checked) that A = 0.\n\n\n\n\n\n","category":"type"},{"location":"api/#DFTK.MagneticFieldOperator","page":"API reference","title":"DFTK.MagneticFieldOperator","text":"Magnetic field operator A⋅(-i∇).\n\n\n\n\n\n","category":"type"},{"location":"api/#DFTK.Model-Tuple{AtomsBase.AbstractSystem}","page":"API reference","title":"DFTK.Model","text":"Model(system::AbstractSystem; kwargs...)\n\nAtomsBase-compatible Model constructor. Sets structural information (atoms, positions, lattice, n_electrons etc.) from the passed system.\n\n\n\n\n\n","category":"method"},{"location":"api/#DFTK.Model-Union{Tuple{AbstractMatrix{T}}, Tuple{T}, Tuple{AbstractMatrix{T}, Vector{<:DFTK.Element}}, Tuple{AbstractMatrix{T}, Vector{<:DFTK.Element}, Vector{<:AbstractVector}}} where T<:Real","page":"API reference","title":"DFTK.Model","text":"Model(lattice, atoms, positions; n_electrons, magnetic_moments, terms, temperature,\n smearing, spin_polarization, symmetries)\n\nCreates the physical specification of a model (without any discretization information).\n\nn_electrons is taken from atoms if not specified.\n\nspin_polarization is :none by default (paired electrons) unless any of the elements has a non-zero initial magnetic moment. In this case the spin_polarization will be :collinear.\n\nmagnetic_moments is only used to determine the symmetry and the spin_polarization; it is not stored inside the datastructure.\n\nsmearing is Fermi-Dirac if temperature is non-zero, none otherwise\n\nThe symmetries kwarg allows (a) to pass true / false to enable / disable the automatic determination of lattice symmetries or (b) to pass an explicit list of symmetry operations to use for lowering the computational effort. The default behaviour is equal to true, namely that the code checks the specified model in form of the Hamiltonian terms, lattice, atoms and magnetic_moments parameters and from these automatically determines a set of symmetries it can safely use. If you want to pass custom symmetry operations (e.g. a reduced or extended set) use the symmetry_operations function. Notice that this may lead to wrong results if e.g. the external potential breaks some of the passed symmetries. Use false to turn off symmetries completely.\n\n\n\n\n\n","category":"method"},{"location":"api/#DFTK.NbandsAlgorithm","page":"API reference","title":"DFTK.NbandsAlgorithm","text":"NbandsAlgorithm subtypes determine how many bands to compute and converge in each SCF step.\n\n\n\n\n\n","category":"type"},{"location":"api/#DFTK.NonlocalOperator","page":"API reference","title":"DFTK.NonlocalOperator","text":"Nonlocal operator in Fourier space in Kleinman-Bylander format, defined by its projectors P matrix and coupling terms D: Hψ = PDP' ψ\n\n\n\n\n\n","category":"type"},{"location":"api/#DFTK.NoopOperator","page":"API reference","title":"DFTK.NoopOperator","text":"Noop operation: don't do anything. Useful for energy terms that don't depend on the orbitals at all (eg nuclei-nuclei interaction).\n\n\n\n\n\n","category":"type"},{"location":"api/#DFTK.PairwisePotential-Tuple{Any, Any}","page":"API reference","title":"DFTK.PairwisePotential","text":"Pairwise terms: Pairwise potential between nuclei, e.g., Van der Waals potentials, such as Lennard—Jones terms. The potential is dependent on the distance between to atomic positions and the pairwise atomic types: For a distance d between to atoms A and B, the potential is V(d, params[(A, B)]). The parameters max_radius is of 100 by default, and gives the maximum distance (in Cartesian coordinates) between nuclei for which we consider interactions.\n\n\n\n\n\n","category":"method"},{"location":"api/#DFTK.PlaneWaveBasis","page":"API reference","title":"DFTK.PlaneWaveBasis","text":"A plane-wave discretized Model. Normalization conventions:\n\nThings that are expressed in the G basis are normalized so that if x is the vector, then the actual function is sum_G x_G e_G with e_G(x) = e^iG x sqrt(Omega), where Omega is the unit cell volume. This is so that, eg norm(ψ) = 1 gives the correct normalization. This also holds for the density and the potentials.\nQuantities expressed on the real-space grid are in actual values.\n\nifft and fft convert between these representations.\n\n\n\n\n\n","category":"type"},{"location":"api/#DFTK.PlaneWaveBasis-Tuple{Model}","page":"API reference","title":"DFTK.PlaneWaveBasis","text":"Creates a PlaneWaveBasis using the kinetic energy cutoff Ecut and a Monkhorst-Pack k-point grid. The MP grid can either be specified directly with kgrid providing the number of points in each dimension and kshift the shift (0 or 1/2 in each direction). If not specified a grid is generated using kgrid_from_minimal_spacing with a minimal spacing of 2π * 0.022 per Bohr.\n\n\n\n\n\n","category":"method"},{"location":"api/#DFTK.PlaneWaveBasis-Tuple{PlaneWaveBasis, AbstractVector, AbstractVector}","page":"API reference","title":"DFTK.PlaneWaveBasis","text":"Creates a new basis identical to basis, but with a custom set of kpoints\n\n\n\n\n\n","category":"method"},{"location":"api/#DFTK.PreconditionerNone","page":"API reference","title":"DFTK.PreconditionerNone","text":"No preconditioning\n\n\n\n\n\n","category":"type"},{"location":"api/#DFTK.PreconditionerTPA","page":"API reference","title":"DFTK.PreconditionerTPA","text":"(simplified version of) Tetter-Payne-Allan preconditioning ↑ M.P. Teter, M.C. Payne and D.C. Allan, Phys. Rev. B 40, 12255 (1989).\n\n\n\n\n\n","category":"type"},{"location":"api/#DFTK.PspCorrection","page":"API reference","title":"DFTK.PspCorrection","text":"Pseudopotential correction energy. TODO discuss the need for this.\n\n\n\n\n\n","category":"type"},{"location":"api/#DFTK.PspHgh-Tuple{Any}","page":"API reference","title":"DFTK.PspHgh","text":"PspHgh(path[, identifier, description])\n\nConstruct a Hartwigsen, Goedecker, Teter, Hutter separable dual-space Gaussian pseudopotential (1998) from file.\n\n\n\n\n\n","category":"method"},{"location":"api/#DFTK.PspUpf-Tuple{Any}","page":"API reference","title":"DFTK.PspUpf","text":"PspUpf(path[, identifier])\n\nConstruct a Unified Pseudopotential Format pseudopotential from file.\n\nDoes not support:\n\nNon-linear core correction\nFully-realtivistic / spin-orbit pseudos\nBare Coulomb / all-electron potentials\nSemilocal potentials\nUltrasoft potentials\nProjector-augmented wave potentials\nGIPAW reconstruction data\n\n\n\n\n\n","category":"method"},{"location":"api/#DFTK.RealFourierOperator","page":"API reference","title":"DFTK.RealFourierOperator","text":"Linear operators that act on tuples (real, fourier) The main entry point is apply!(out, op, in) which performs the operation out += op*in where out and in are named tuples (real, fourier) They also implement mul! and Matrix(op) for exploratory use.\n\n\n\n\n\n","category":"type"},{"location":"api/#DFTK.RealSpaceMultiplication","page":"API reference","title":"DFTK.RealSpaceMultiplication","text":"Real space multiplication by a potential: (Hψ)(r) = V(r) ψ(r)\n\n\n\n\n\n","category":"type"},{"location":"api/#DFTK.SimpleMixing","page":"API reference","title":"DFTK.SimpleMixing","text":"Simple mixing: J^-1 1\n\n\n\n\n\n","category":"type"},{"location":"api/#DFTK.TermNoop","page":"API reference","title":"DFTK.TermNoop","text":"A term with a constant zero energy.\n\n\n\n\n\n","category":"type"},{"location":"api/#DFTK.Xc","page":"API reference","title":"DFTK.Xc","text":"Exchange-correlation term, defined by a list of functionals and usually evaluated through libxc.\n\n\n\n\n\n","category":"type"},{"location":"api/#DFTK.χ0Mixing","page":"API reference","title":"DFTK.χ0Mixing","text":"Generic mixing function using a model for the susceptibility composed of the sum of the χ0terms. For valid χ0terms See the subtypes of χ0Model. The dielectric model is solved in real space using a GMRES. Either the full kernel (RPA=false) or only the Hartree kernel (RPA=true) are employed. verbose=true lets the GMRES run in verbose mode (useful for debugging).\n\n\n\n\n\n","category":"type"},{"location":"api/#AbstractFFTs.fft!-Tuple{AbstractArray{T, 3} where T, PlaneWaveBasis, AbstractArray{T, 3} where T}","page":"API reference","title":"AbstractFFTs.fft!","text":"In-place version of fft!. NOTE: If kpt is given, not only f_fourier but also f_real is overwritten.\n\n\n\n\n\n","category":"method"},{"location":"api/#AbstractFFTs.fft-Union{Tuple{U}, Tuple{T}, Tuple{PlaneWaveBasis{T, VT} where VT<:Real, AbstractArray{U}}} where {T, U}","page":"API reference","title":"AbstractFFTs.fft","text":"fft(basis::PlaneWaveBasis, [kpt::Kpoint, ] f_real)\n\nPerform an FFT to obtain the Fourier representation of f_real. If kpt is given, the coefficients are truncated to the k-dependent spherical basis set.\n\n\n\n\n\n","category":"method"},{"location":"api/#AbstractFFTs.ifft!-Tuple{AbstractArray{T, 3} where T, PlaneWaveBasis, AbstractArray{T, 3} where T}","page":"API reference","title":"AbstractFFTs.ifft!","text":"In-place version of ifft.\n\n\n\n\n\n","category":"method"},{"location":"api/#AbstractFFTs.ifft-Tuple{PlaneWaveBasis, AbstractArray}","page":"API reference","title":"AbstractFFTs.ifft","text":"ifft(basis::PlaneWaveBasis, [kpt::Kpoint, ] f_fourier)\n\nPerform an iFFT to obtain the quantity defined by f_fourier defined on the k-dependent spherical basis set (if kpt is given) or the k-independent cubic (if it is not) on the real-space grid.\n\n\n\n\n\n","category":"method"},{"location":"api/#AtomsBase.atomic_symbol-Tuple{DFTK.Element}","page":"API reference","title":"AtomsBase.atomic_symbol","text":"Chemical symbol corresponding to an element\n\n\n\n\n\n","category":"method"},{"location":"api/#AtomsBase.atomic_system","page":"API reference","title":"AtomsBase.atomic_system","text":"atomic_system(model::DFTK.Model, magnetic_moments=[])\natomic_system(lattice, atoms, positions, magnetic_moments=[])\n\nConstruct an AtomsBase atomic system from a DFTK model and associated magnetic moments or from the usual lattice, atoms and positions list used in DFTK plus magnetic moments.\n\n\n\n\n\n","category":"function"},{"location":"api/#AtomsBase.periodic_system","page":"API reference","title":"AtomsBase.periodic_system","text":"periodic_system(model::DFTK.Model, magnetic_moments=[])\nperiodic_system(lattice, atoms, positions, magnetic_moments=[])\n\nConstruct an AtomsBase atomic system from a DFTK model and associated magnetic moments or from the usual lattice, atoms and positions list used in DFTK plus magnetic moments.\n\n\n\n\n\n","category":"function"},{"location":"api/#Brillouin.KPaths.irrfbz_path-Tuple{Any}","page":"API reference","title":"Brillouin.KPaths.irrfbz_path","text":"Extract the high-symmetry k-point path corresponding to the passed model using Brillouin. Uses the conventions described in the reference work by Cracknell, Davies, Miller, and Love (CDML). Of note, this has minor differences to the k-path reference (Y. Himuma et. al. Comput. Mater. Sci. 128, 140 (2017)) underlying the path-choices of Brillouin.jl, specifically for oA and mC Bravais types.\n\nIf the cell is a supercell of a smaller primitive cell, the standard k-path of the associated primitive cell is returned. So, the high-symmetry k points are those of the primitive cell Brillouin zone, not those of the supercell Brillouin zone.\n\nThe dim argument allows to artificially truncate the dimension of the employed model, e.g. allowing to plot a 2D bandstructure of a 3D model (useful for example for plotting band structures of sheets with dim=2).\n\nDue to lacking support in Spglib.jl for two-dimensional lattices it is (a) assumed that model.lattice is a conventional lattice and (b) required to pass the space group number using the sgnum keyword argument.\n\n\n\n\n\n","category":"method"},{"location":"api/#DFTK.CROP","page":"API reference","title":"DFTK.CROP","text":"CROP-accelerated root-finding iteration for f, starting from x0 and keeping a history of m steps. Optionally warming specifies the number of non-accelerated steps to perform for warming up the history.\n\n\n\n\n\n","category":"function"},{"location":"api/#DFTK.G_vectors-Tuple{PlaneWaveBasis}","page":"API reference","title":"DFTK.G_vectors","text":"G_vectors(basis::PlaneWaveBasis)\nG_vectors(basis::PlaneWaveBasis, kpt::Kpoint)\n\nThe list of wave vectors G in reduced (integer) coordinates of a basis or a k-point kpt.\n\n\n\n\n\n","category":"method"},{"location":"api/#DFTK.G_vectors-Tuple{Union{Tuple, AbstractVector}}","page":"API reference","title":"DFTK.G_vectors","text":"G_vectors([architecture=AbstractArchitecture], fft_size::Tuple)\n\nThe wave vectors G in reduced (integer) coordinates for a cubic basis set of given sizes.\n\n\n\n\n\n","category":"method"},{"location":"api/#DFTK.G_vectors_cart-Tuple{PlaneWaveBasis}","page":"API reference","title":"DFTK.G_vectors_cart","text":"G_vectors_cart(basis::PlaneWaveBasis)\nG_vectors_cart(basis::PlaneWaveBasis, kpt::Kpoint)\n\nThe list of G vectors of a given basis or kpt, in cartesian coordinates.\n\n\n\n\n\n","category":"method"},{"location":"api/#DFTK.Gplusk_vectors-Tuple{PlaneWaveBasis, Kpoint}","page":"API reference","title":"DFTK.Gplusk_vectors","text":"Gplusk_vectors(basis::PlaneWaveBasis, kpt::Kpoint)\n\nThe list of G + k vectors, in reduced coordinates.\n\n\n\n\n\n","category":"method"},{"location":"api/#DFTK.Gplusk_vectors_cart-Tuple{PlaneWaveBasis, Kpoint}","page":"API reference","title":"DFTK.Gplusk_vectors_cart","text":"Gplusk_vectors_cart(basis::PlaneWaveBasis, kpt::Kpoint)\n\nThe list of G + k vectors, in cartesian coordinates.\n\n\n\n\n\n","category":"method"},{"location":"api/#DFTK.Gplusk_vectors_in_supercell-Tuple{PlaneWaveBasis, PlaneWaveBasis, Kpoint}","page":"API reference","title":"DFTK.Gplusk_vectors_in_supercell","text":"Maps all k+G vectors of an given basis as G vectors of the supercell basis, in reduced coordinates.\n\n\n\n\n\n","category":"method"},{"location":"api/#DFTK.HybridMixing-Tuple{}","page":"API reference","title":"DFTK.HybridMixing","text":"The model for the susceptibility is\n\nbeginaligned\n χ_0(r r) = (-D_textloc(r) δ(r r) + D_textloc(r) D_textloc(r) D) \n + sqrtL(x) textIFFT fracC_0 G^24π (1 - C_0 G^2 k_TF^2) textFFT sqrtL(x)\nendaligned\n\nwhere C_0 = 1 - ε_r, D_textloc is the local density of states, D is the density of states and the same convention for parameters are used as in DielectricMixing. Additionally there is the real-space localization function L(r). For details see Herbst, Levitt 2020 arXiv:2009.01665\n\nImportant kwargs passed on to χ0Mixing\n\nRPA: Is the random-phase approximation used for the kernel (i.e. only Hartree kernel is used and not XC kernel)\nverbose: Run the GMRES in verbose mode.\nreltol: Relative tolerance for GMRES\n\n\n\n\n\n","category":"method"},{"location":"api/#DFTK.IncreaseMixingTemperature-Tuple{}","page":"API reference","title":"DFTK.IncreaseMixingTemperature","text":"Increase the temperature used for computing the SCF preconditioners. Initially the temperature is increased by a factor, which is then smoothly lowered towards the temperature used within the model as the SCF converges. Once the density change is below above_ρdiff the mixing temperature is equal to the model temperature.\n\n\n\n\n\n","category":"method"},{"location":"api/#DFTK.LdosMixing-Tuple{}","page":"API reference","title":"DFTK.LdosMixing","text":"The model for the susceptibility is\n\nbeginaligned\n χ_0(r r) = (-D_textloc(r) δ(r r) + D_textloc(r) D_textloc(r) D)\nendaligned\n\nwhere D_textloc is the local density of states, D is the density of states. For details see Herbst, Levitt 2020 arXiv:2009.01665.\n\nImportant kwargs passed on to χ0Mixing\n\nRPA: Is the random-phase approximation used for the kernel (i.e. only Hartree kernel is used and not XC kernel)\nverbose: Run the GMRES in verbose mode.\nreltol: Relative tolerance for GMRES\n\n\n\n\n\n","category":"method"},{"location":"api/#DFTK.ScfAcceptImprovingStep-Tuple{}","page":"API reference","title":"DFTK.ScfAcceptImprovingStep","text":"Accept a step if the energy is at most increasing by max_energy and the residual is at most max_relative_residual times the residual in the previous step.\n\n\n\n\n\n","category":"method"},{"location":"api/#DFTK.ScfConvergenceDensity-Tuple{Any}","page":"API reference","title":"DFTK.ScfConvergenceDensity","text":"Flag convergence by using the L2Norm of the change between input density and unpreconditioned output density (ρout)\n\n\n\n\n\n","category":"method"},{"location":"api/#DFTK.ScfConvergenceEnergy-Tuple{Any}","page":"API reference","title":"DFTK.ScfConvergenceEnergy","text":"Flag convergence as soon as total energy change drops below tolerance\n\n\n\n\n\n","category":"method"},{"location":"api/#DFTK.ScfConvergenceForce-Tuple{Any}","page":"API reference","title":"DFTK.ScfConvergenceForce","text":"Flag convergence on the change in cartesian force between two iterations.\n\n\n\n\n\n","category":"method"},{"location":"api/#DFTK.ScfDefaultCallback-Tuple{}","page":"API reference","title":"DFTK.ScfDefaultCallback","text":"Default callback function for self_consistent_field and newton, which prints a convergence table.\n\n\n\n\n\n","category":"method"},{"location":"api/#DFTK.ScfDiagtol-Tuple{}","page":"API reference","title":"DFTK.ScfDiagtol","text":"Determine the tolerance used for the next diagonalization. This function takes ρnext - ρin and multiplies it with ratio_ρdiff to get the next diagtol, ensuring additionally that the returned value is between diagtol_min and diagtol_max and never increases.\n\n\n\n\n\n","category":"method"},{"location":"api/#DFTK.ScfPlotTrace","page":"API reference","title":"DFTK.ScfPlotTrace","text":"Plot the trace of an SCF, i.e. the absolute error of the total energy at each iteration versus the converged energy in a semilog plot. By default a new plot canvas is generated, but an existing one can be passed and reused along with kwargs for the call to plot!. Requires Plots to be loaded.\n\n\n\n\n\n","category":"function"},{"location":"api/#DFTK.ScfSaveCheckpoints","page":"API reference","title":"DFTK.ScfSaveCheckpoints","text":"Adds simplistic checkpointing to a DFTK self-consistent field calculation. Requires JLD2 to be loaded.\n\n\n\n\n\n","category":"function"},{"location":"api/#DFTK.apply_K-Tuple{PlaneWaveBasis, Any, Any, Any, Any}","page":"API reference","title":"DFTK.apply_K","text":"apply_K(basis::PlaneWaveBasis, δψ, ψ, ρ, occupation)\n\nCompute the application of K defined at ψ to δψ. ρ is the density issued from ψ. δψ also generates a δρ, computed with compute_δρ.\n\n\n\n\n\n","category":"method"},{"location":"api/#DFTK.apply_kernel-Tuple{PlaneWaveBasis, Any}","page":"API reference","title":"DFTK.apply_kernel","text":"apply_kernel(basis::PlaneWaveBasis, δρ; kwargs...)\n\nComputes the potential response to a perturbation δρ in real space, as a 4D (i,j,k,σ) array.\n\n\n\n\n\n","category":"method"},{"location":"api/#DFTK.apply_symop-Tuple{SymOp, Any, Any, AbstractVecOrMat}","page":"API reference","title":"DFTK.apply_symop","text":"Apply a symmetry operation to eigenvectors ψk at a given kpoint to obtain an equivalent point in [-0.5, 0.5)^3 and associated eigenvectors (expressed in the basis of the new k-point).\n\n\n\n\n\n","category":"method"},{"location":"api/#DFTK.apply_symop-Tuple{SymOp, Any, Any}","page":"API reference","title":"DFTK.apply_symop","text":"Apply a symmetry operation to a density.\n\n\n\n\n\n","category":"method"},{"location":"api/#DFTK.apply_Ω-Tuple{Any, Any, Hamiltonian, Any}","page":"API reference","title":"DFTK.apply_Ω","text":"apply_Ω(δψ, ψ, H::Hamiltonian, Λ)\n\nCompute the application of Ω defined at ψ to δψ. H is the Hamiltonian computed from ψ and Λ is the set of Rayleigh coefficients ψk' * Hk * ψk at each k-point.\n\n\n\n\n\n","category":"method"},{"location":"api/#DFTK.apply_χ0-NTuple{6, Any}","page":"API reference","title":"DFTK.apply_χ0","text":"Get the density variation δρ corresponding to a potential variation δV.\n\n\n\n\n\n","category":"method"},{"location":"api/#DFTK.atom_decay_length-Tuple{Any, Any}","page":"API reference","title":"DFTK.atom_decay_length","text":"Get the lengthscale of the valence density for an atom with n_elec_core core and n_elec_valence valence electrons.\n\n\n\n\n\n","category":"method"},{"location":"api/#DFTK.attach_psp-Tuple{AtomsBase.AbstractSystem, AbstractDict{Symbol, String}}","page":"API reference","title":"DFTK.attach_psp","text":"attach_psp(system::AbstractSystem, pspmap::AbstractDict{Symbol,String})\nattach_psp(system::AbstractSystem; psps::String...)\n\nReturn a new system with the pseudopotential property of all atoms set according to the passed pspmap, which maps from the atomic symbol to a pseudopotential identifier. Alternatively the mapping from atomic symbol to pseudopotential identifier can also be passed as keyword arguments. An empty string can be used to denote elements where the full Coulomb potential should be employed.\n\nExamples\n\nSelect pseudopotentials for all silicon and oxygen atoms in the system.\n\njulia> attach_psp(system, Dict(:Si => \"hgh/lda/si-q4\", :O => \"hgh/lda/o-q6\")\n\nSame thing but using the kwargs syntax:\n\njulia> attach_psp(system, Si=\"hgh/lda/si-q4\", O=\"hgh/lda/o-q6\")\n\n\n\n\n\n","category":"method"},{"location":"api/#DFTK.build_fft_plans!-Tuple{Array{ComplexF64}}","page":"API reference","title":"DFTK.build_fft_plans!","text":"Plan a FFT of type T and size fft_size, spending some time on finding an optimal algorithm. (Inplace, out-of-place) x (forward, backward) FFT plans are returned.\n\n\n\n\n\n","category":"method"},{"location":"api/#DFTK.build_form_factors-Tuple{Any, Array}","page":"API reference","title":"DFTK.build_form_factors","text":"Build form factors (Fourier transforms of projectors) for an atom centered at 0.\n\n\n\n\n\n","category":"method"},{"location":"api/#DFTK.build_projection_vectors_-Union{Tuple{T}, Tuple{PlaneWaveBasis{T, VT} where VT<:Real, Kpoint, Any, Any}} where T","page":"API reference","title":"DFTK.build_projection_vectors_","text":"Build projection vectors for a atoms array generated by term_nonlocal\n\nHat = sumij Cij |pi> <pj| Hper = sumR sumij Cij |pi(x-R)> <pj(x-R)| = sumR sum_ij Cij |pi(x-R)> <pj(x-R)|\n\n<ekG'|Hper|ekG> = ... = 1/Ω sumij Cij pihat(k+G') pjhat(k+G)^*\n\nwhere pihat(q) = ∫_R^3 pi(r) e^{-iqr} dr\n\nWe store 1/√Ω pihat(k+G) in proj_vectors.\n\n\n\n\n\n","category":"method"},{"location":"api/#DFTK.bzmesh_ir_wedge-Tuple{Any, Any}","page":"API reference","title":"DFTK.bzmesh_ir_wedge","text":" bzmesh_ir_wedge(kgrid_size, symmetries; kshift=[0, 0, 0])\n\nConstruct the irreducible wedge of a uniform Brillouin zone mesh for sampling k-points, given the crystal symmetries symmetries. Returns the list of irreducible k-point (fractional) coordinates, the associated weights and the new symmetries compatible with the grid.\n\n\n\n\n\n","category":"method"},{"location":"api/#DFTK.bzmesh_uniform-Tuple{Any}","page":"API reference","title":"DFTK.bzmesh_uniform","text":"bzmesh_uniform(kgrid_size; kshift=[0, 0, 0])\n\nConstruct a (shifted) uniform Brillouin zone mesh for sampling the k-points. Returns all k-point coordinates, appropriate weights and the identity SymOp.\n\n\n\n\n\n","category":"method"},{"location":"api/#DFTK.cell_to_supercell-Tuple{NamedTuple}","page":"API reference","title":"DFTK.cell_to_supercell","text":"Transpose all data from a given self-consistent-field result from unit cell to supercell conventions. The parameters to adapt are the following:\n\nbasis_supercell and ψ_supercell are computed by the routines above.\nThe supercell occupations vector is the concatenation of all input occupations vectors.\nThe supercell density is computed with supercell occupations and ψ_supercell.\nSupercell energies are the multiplication of input energies by the number of unit cells in the supercell.\n\nOther parameters stay untouched.\n\n\n\n\n\n","category":"method"},{"location":"api/#DFTK.cell_to_supercell-Tuple{PlaneWaveBasis}","page":"API reference","title":"DFTK.cell_to_supercell","text":"Construct a plane-wave basis whose unit cell is the supercell associated to an input basis kgrid. All other parameters are modified so that the respective physical systems associated to both basis are equivalent.\n\n\n\n\n\n","category":"method"},{"location":"api/#DFTK.cell_to_supercell-Union{Tuple{T}, Tuple{Any, PlaneWaveBasis{T, VT} where VT<:Real, PlaneWaveBasis{T, VT} where VT<:Real}} where T<:Real","page":"API reference","title":"DFTK.cell_to_supercell","text":"Re-organize Bloch waves computed in a given basis as Bloch waves of the associated supercell basis. The output ψ_supercell have a single component at Γ-point, such that ψ_supercellΓ k+n contains ψk n, within normalization on the supercell.\n\n\n\n\n\n","category":"method"},{"location":"api/#DFTK.cg!-Union{Tuple{T}, Tuple{AbstractVector{T}, LinearMaps.LinearMap{T}, AbstractVector{T}}} where T","page":"API reference","title":"DFTK.cg!","text":"Implementation of the conjugate gradient method which allows for preconditioning and projection operations along iterations.\n\n\n\n\n\n","category":"method"},{"location":"api/#DFTK.charge_ionic-Tuple{DFTK.Element}","page":"API reference","title":"DFTK.charge_ionic","text":"Return the total ionic charge of an atom type (nuclear charge - core electrons)\n\n\n\n\n\n","category":"method"},{"location":"api/#DFTK.charge_nuclear-Tuple{DFTK.Element}","page":"API reference","title":"DFTK.charge_nuclear","text":"Return the total nuclear charge of an atom type\n\n\n\n\n\n","category":"method"},{"location":"api/#DFTK.cis2pi-Tuple{Any}","page":"API reference","title":"DFTK.cis2pi","text":"Function to compute exp(2π i x)\n\n\n\n\n\n","category":"method"},{"location":"api/#DFTK.compute_Ak_gaussian_guess-Tuple{PlaneWaveBasis, Any, Any, Any, Any}","page":"API reference","title":"DFTK.compute_Ak_gaussian_guess","text":"Compute the matrix A_k_mn = langle ψ_m^k g^textper_n rangle\n\ng^per_n are periodized gaussians whose respective centers are given as an (num_bands,1) array [ [center 1], ... ].\n\nCenters are to be given in lattice coordinates and G_vectors in reduced coordinates. The dot product is computed in the Fourier space.\n\nGiven an orbital g_n, the periodized orbital is defined by : g^per_n = sumlimits_R in rm lattice g_n( cdot - R). The Fourier coefficient of g^per_n at any G is given by the value of the Fourier transform of g_n in G.\n\n\n\n\n\n","category":"method"},{"location":"api/#DFTK.compute_current-Tuple{PlaneWaveBasis, Any, Any}","page":"API reference","title":"DFTK.compute_current","text":"Computes the probability (not charge) current, ∑ fn Im(ψn* ∇ψn)\n\n\n\n\n\n","category":"method"},{"location":"api/#DFTK.compute_density-Union{Tuple{T}, Tuple{PlaneWaveBasis{T, VT} where VT<:Real, Any, Any}} where T","page":"API reference","title":"DFTK.compute_density","text":"compute_density(basis::PlaneWaveBasis, ψ::AbstractVector, occupation::AbstractVector)\n\nCompute the density for a wave function ψ discretized on the plane-wave grid basis, where the individual k-points are occupied according to occupation. ψ should be one coefficient matrix per k-point. It is possible to ask only for occupations higher than a certain level to be computed by using an optional occupation_threshold. By default all occupation numbers are considered.\n\n\n\n\n\n","category":"method"},{"location":"api/#DFTK.compute_dos-Tuple{Any, Any, Any}","page":"API reference","title":"DFTK.compute_dos","text":"Total density of states at energy ε\n\n\n\n\n\n","category":"method"},{"location":"api/#DFTK.compute_fft_size-Union{Tuple{T}, Tuple{Model{T}, Any}, Tuple{Model{T}, Any, Any}} where T","page":"API reference","title":"DFTK.compute_fft_size","text":"Determine the minimal grid size for the cubic basis set to be able to represent product of orbitals (with the default supersampling=2).\n\nOptionally optimize the grid afterwards for the FFT procedure by ensuring factorization into small primes.\n\nThe function will determine the smallest parallelepiped containing the wave vectors G^22 leq E_textcut textsupersampling^2. For an exact representation of the density resulting from wave functions represented in the spherical basis sets, supersampling should be at least 2.\n\nIf factors is not empty, ensure that the resulting fft_size contains all the factors\n\n\n\n\n\n","category":"method"},{"location":"api/#DFTK.compute_forces-Union{Tuple{T}, Tuple{PlaneWaveBasis{T, VT} where VT<:Real, Any, Any}} where T","page":"API reference","title":"DFTK.compute_forces","text":"Compute the forces of an obtained SCF solution. Returns the forces wrt. the fractional lattice vectors. To get cartesian forces use compute_forces_cart. Returns a list of lists of forces (as SVector{3}) in the same order as the atoms and positions in the underlying Model.\n\n\n\n\n\n","category":"method"},{"location":"api/#DFTK.compute_forces_cart-Tuple{PlaneWaveBasis, Any, Any}","page":"API reference","title":"DFTK.compute_forces_cart","text":"Compute the cartesian forces of an obtained SCF solution in Hartree / Bohr. Returns a list of lists of forces [[force for atom in positions] for (element, positions) in atoms] which has the same structure as the atoms object passed to the underlying Model.\n\n\n\n\n\n","category":"method"},{"location":"api/#DFTK.compute_inverse_lattice-Union{Tuple{AbstractMatrix{T}}, Tuple{T}} where T","page":"API reference","title":"DFTK.compute_inverse_lattice","text":"Compute the inverse of the lattice. Takes special care of 1D or 2D cases.\n\n\n\n\n\n","category":"method"},{"location":"api/#DFTK.compute_kernel-Union{Tuple{PlaneWaveBasis{T, VT} where VT<:Real}, Tuple{T}} where T","page":"API reference","title":"DFTK.compute_kernel","text":"compute_kernel(basis::PlaneWaveBasis; kwargs...)\n\nComputes a matrix representation of the full response kernel (derivative of potential with respect to density) in real space. For non-spin-polarized calculations the matrix dimension is prod(basis.fft_size) × prod(basis.fft_size) and for collinear spin-polarized cases it is 2prod(basis.fft_size) × 2prod(basis.fft_size). In this case the matrix has effectively 4 blocks\n\nleft(beginarraycc\n K_αα K_αβ\n K_βα K_ββ\nendarrayright)\n\n\n\n\n\n","category":"method"},{"location":"api/#DFTK.compute_ldos-Union{Tuple{T}, Tuple{Any, PlaneWaveBasis{T, VT} where VT<:Real, Any, Any}} where T","page":"API reference","title":"DFTK.compute_ldos","text":"Local density of states, in real space. weight_threshold is a threshold to screen away small contributions to the LDOS.\n\n\n\n\n\n","category":"method"},{"location":"api/#DFTK.compute_occupation-Union{Tuple{T}, Tuple{PlaneWaveBasis{T, VT} where VT<:Real, AbstractVector, Number}} where T","page":"API reference","title":"DFTK.compute_occupation","text":"Compute occupation given eigenvalues and Fermi level\n\n\n\n\n\n","category":"method"},{"location":"api/#DFTK.compute_occupation-Union{Tuple{T}, Tuple{PlaneWaveBasis{T, VT} where VT<:Real, AbstractVector}, Tuple{PlaneWaveBasis{T, VT} where VT<:Real, AbstractVector, AbstractFermiAlgorithm}} where T","page":"API reference","title":"DFTK.compute_occupation","text":"Compute occupation and Fermi level given eigenvalues and using fermialg. The tol_n_elec gives the accuracy on the electron count which should be at least achieved.\n\n\n\n\n\n","category":"method"},{"location":"api/#DFTK.compute_recip_lattice-Union{Tuple{AbstractMatrix{T}}, Tuple{T}} where T","page":"API reference","title":"DFTK.compute_recip_lattice","text":"Compute the reciprocal lattice. We use the convention that the reciprocal lattice is the set of G vectors such that G ⋅ R ∈ 2π ℤ for all R in the lattice.\n\n\n\n\n\n","category":"method"},{"location":"api/#DFTK.compute_stresses_cart-Tuple{Any}","page":"API reference","title":"DFTK.compute_stresses_cart","text":"Compute the stresses (= 1/Vol dE/d(M*lattice), taken at M=I) of an obtained SCF solution.\n\n\n\n\n\n","category":"method"},{"location":"api/#DFTK.compute_transfer_matrix-Union{Tuple{T}, Tuple{PlaneWaveBasis{T, VT} where VT<:Real, Kpoint, PlaneWaveBasis{T, VT} where VT<:Real, Kpoint}} where T","page":"API reference","title":"DFTK.compute_transfer_matrix","text":"Return a sparse matrix that maps quantities given on basis_in and kpt_in to quantities on basis_out and kpt_out.\n\n\n\n\n\n","category":"method"},{"location":"api/#DFTK.compute_transfer_matrix-Union{Tuple{T}, Tuple{PlaneWaveBasis{T, VT} where VT<:Real, PlaneWaveBasis{T, VT} where VT<:Real}} where T","page":"API reference","title":"DFTK.compute_transfer_matrix","text":"Return a list of sparse matrices (one per k-point) that map quantities given in the basis_in basis to quantities given in the basis_out basis.\n\n\n\n\n\n","category":"method"},{"location":"api/#DFTK.compute_unit_cell_volume-Tuple{Any}","page":"API reference","title":"DFTK.compute_unit_cell_volume","text":"Compute unit cell volume volume. In case of 1D or 2D case, the volume is the length/surface.\n\n\n\n\n\n","category":"method"},{"location":"api/#DFTK.compute_δocc!-Union{Tuple{T}, Tuple{Any, Any, Any, T, Any, Any}} where T","page":"API reference","title":"DFTK.compute_δocc!","text":"Compute the derivatives of the occupations (and of the Fermi level). The derivatives of the occupations are in-place stored in δocc. The tuple (; δocc, δεF) is returned. It is assumed the passed δocc are initialised to zero.\n\n\n\n\n\n","category":"method"},{"location":"api/#DFTK.compute_δψ!-NTuple{7, Any}","page":"API reference","title":"DFTK.compute_δψ!","text":"Perform in-place computations of the derivatives of the wave functions by solving a Sternheimer equation for each k-points. It is assumed the passed δψ are initialised to zero.\n\n\n\n\n\n","category":"method"},{"location":"api/#DFTK.compute_χ0-Tuple{Any}","page":"API reference","title":"DFTK.compute_χ0","text":"Compute the independent-particle susceptibility. Will blow up for large systems. For non-spin-polarized calculations the matrix dimension is prod(basis.fft_size) × prod(basis.fft_size) and for collinear spin-polarized cases it is 2prod(basis.fft_size) × 2prod(basis.fft_size). In this case the matrix has effectively 4 blocks, which are:\n\nleft(beginarraycc\n (χ_0)_αα (χ_0)_αβ \n (χ_0)_βα (χ_0)_ββ\nendarrayright)\n\n\n\n\n\n","category":"method"},{"location":"api/#DFTK.cos2pi-Tuple{Any}","page":"API reference","title":"DFTK.cos2pi","text":"Function to compute cos(2π x)\n\n\n\n\n\n","category":"method"},{"location":"api/#DFTK.count_n_proj-Tuple{Any, Any}","page":"API reference","title":"DFTK.count_n_proj","text":"count_n_proj(psps, psp_positions)\n\nNumber of projector functions for all angular momenta up to psp.lmax and for all atoms in the system, including angular parts from -m:m.\n\n\n\n\n\n","category":"method"},{"location":"api/#DFTK.count_n_proj-Tuple{DFTK.NormConservingPsp, Integer}","page":"API reference","title":"DFTK.count_n_proj","text":"count_n_proj(psp, l)\n\nNumber of projector functions for angular momentum l, including angular parts from -m:m.\n\n\n\n\n\n","category":"method"},{"location":"api/#DFTK.count_n_proj-Tuple{DFTK.NormConservingPsp}","page":"API reference","title":"DFTK.count_n_proj","text":"count_n_proj(psp)\n\nNumber of projector functions for all angular momenta up to psp.lmax, including angular parts from -m:m.\n\n\n\n\n\n","category":"method"},{"location":"api/#DFTK.count_n_proj_radial-Tuple{DFTK.NormConservingPsp, Integer}","page":"API reference","title":"DFTK.count_n_proj_radial","text":"count_n_proj_radial(psp, l)\n\nNumber of projector radial functions at angular momentum l.\n\n\n\n\n\n","category":"method"},{"location":"api/#DFTK.count_n_proj_radial-Tuple{DFTK.NormConservingPsp}","page":"API reference","title":"DFTK.count_n_proj_radial","text":"count_n_proj_radial(psp)\n\nNumber of projector radial functions at all angular momenta up to psp.lmax.\n\n\n\n\n\n","category":"method"},{"location":"api/#DFTK.create_supercell-NTuple{4, Any}","page":"API reference","title":"DFTK.create_supercell","text":"Construct a supercell of size supercell_size from a unit cell described by its lattice, atoms and their positions.\n\n\n\n\n\n","category":"method"},{"location":"api/#DFTK.datadir_psp-Tuple{}","page":"API reference","title":"DFTK.datadir_psp","text":"Return the data directory with pseudopotential files\n\n\n\n\n\n","category":"method"},{"location":"api/#DFTK.default_fermialg-Tuple{DFTK.Smearing.SmearingFunction}","page":"API reference","title":"DFTK.default_fermialg","text":"Default selection of a Fermi level determination algorithm\n\n\n\n\n\n","category":"method"},{"location":"api/#DFTK.default_spin_polarization-Tuple{Any}","page":"API reference","title":"DFTK.default_spin_polarization","text":":none if no element has a magnetic moment, else :collinear or :full.\n\n\n\n\n\n","category":"method"},{"location":"api/#DFTK.default_symmetries-NTuple{6, Any}","page":"API reference","title":"DFTK.default_symmetries","text":"Default logic to determine the symmetry operations to be used in the model.\n\n\n\n\n\n","category":"method"},{"location":"api/#DFTK.default_wannier_centres-Tuple{Any}","page":"API reference","title":"DFTK.default_wannier_centres","text":"Default random Gaussian guess for maximally-localised wannier functions generated in reduced coordinates.\n\n\n\n\n\n","category":"method"},{"location":"api/#DFTK.diagonalize_all_kblocks-Tuple{Any, Hamiltonian, Int64}","page":"API reference","title":"DFTK.diagonalize_all_kblocks","text":"Function for diagonalising each k-Point blow of ham one step at a time. Some logic for interpolating between k-points is used if interpolate_kpoints is true and if no guesses are given. eigensolver is the iterative eigensolver that really does the work, operating on a single k-Block. eigensolver should support the API eigensolver(A, X0; prec, tol, maxiter) prec_type should be a function that returns a preconditioner when called as prec(ham, kpt)\n\n\n\n\n\n","category":"method"},{"location":"api/#DFTK.diameter-Tuple{AbstractMatrix}","page":"API reference","title":"DFTK.diameter","text":"Compute the diameter of the unit cell\n\n\n\n\n\n","category":"method"},{"location":"api/#DFTK.direct_minimization-Tuple{PlaneWaveBasis}","page":"API reference","title":"DFTK.direct_minimization","text":"Computes the ground state by direct minimization. kwargs... are passed to Optim.Options(). Note that the resulting ψ are not necessarily eigenvectors of the Hamiltonian.\n\n\n\n\n\n","category":"method"},{"location":"api/#DFTK.disable_threading-Tuple{}","page":"API reference","title":"DFTK.disable_threading","text":"Convenience function to disable all threading in DFTK and assert that Julia threading is off as well.\n\n\n\n\n\n","category":"method"},{"location":"api/#DFTK.divergence_real-Tuple{Any, Any}","page":"API reference","title":"DFTK.divergence_real","text":"Compute divergence of an operand function, which returns the cartesian x,y,z components in real space when called with the arguments 1 to 3. The divergence is also returned as a real-space array.\n\n\n\n\n\n","category":"method"},{"location":"api/#DFTK.energy_ewald-Union{Tuple{T}, Tuple{AbstractArray{T}, Any, Any}} where T","page":"API reference","title":"DFTK.energy_ewald","text":"Compute the electrostatic interaction energy per unit cell between point charges in a uniform background of compensating charge to yield net neutrality.lattice should contain the lattice vectors as columns. charges and positions are the point charges and their positions (as an array of arrays) in fractional coordinates. If forces is not nothing, minus the derivatives of the energy with respect to positions is computed.\n\nFor now this function returns zero energy and force on non-3D systems. Use a pairwise potential term if you want to customise this treatment.\n\n\n\n\n\n","category":"method"},{"location":"api/#DFTK.energy_pairwise-Union{Tuple{T}, Tuple{Model{T}, Any, Any}} where T","page":"API reference","title":"DFTK.energy_pairwise","text":"Compute the pairwise interaction energy per unit cell between atomic sites. If forces is not nothing, minus the derivatives of the energy with respect to positions is computed. The potential is expected to decrease quickly at infinity.\n\n\n\n\n\n","category":"method"},{"location":"api/#DFTK.energy_psp_correction-Union{Tuple{T}, Tuple{AbstractMatrix{T}, Any, Any}} where T","page":"API reference","title":"DFTK.energy_psp_correction","text":"Compute the correction term for properly modelling the interaction of the pseudopotential core with the compensating background charge induced by the Ewald term.\n\n\n\n\n\n","category":"method"},{"location":"api/#DFTK.enforce_real!-Tuple{Any, Any}","page":"API reference","title":"DFTK.enforce_real!","text":"Ensure its real-space equivalent of passed Fourier-space representation is entirely real by removing wavevectors G that don't have a -G counterpart in the basis.\n\n\n\n\n\n","category":"method"},{"location":"api/#DFTK.estimate_integer_lattice_bounds-Union{Tuple{T}, Tuple{AbstractMatrix{T}, Any}, Tuple{AbstractMatrix{T}, Any, Any}} where T","page":"API reference","title":"DFTK.estimate_integer_lattice_bounds","text":"Estimate integer bounds for dense space loops from a given inequality ||Mx|| ≤ δ. For 1D and 2D systems the limit will be zero in the auxiliary dimensions.\n\n\n\n\n\n","category":"method"},{"location":"api/#DFTK.eval_psp_energy_correction","page":"API reference","title":"DFTK.eval_psp_energy_correction","text":"eval_psp_energy_correction([T=Float64,] psp, n_electrons)\n\nEvaluate the energy correction to the Ewald electrostatic interaction energy of one unit cell, which is required compared the Ewald expression for point-like nuclei. n_electrons is the number of electrons per unit cell. This defines the uniform compensating background charge, which is assumed here.\n\nNotice: The returned result is the energy per unit cell and not the energy per volume. To obtain the latter, the caller needs to divide by the unit cell volume.\n\nThe energy correction is defined as the limit of the Fourier-transform of the local potential as q -> 0, using the same correction as in the Fourier-transform of the local potential: lim{q->0} 4π Nelec ∫{R+} (V(r) - C(r)) sin(qr)/qr r^2 dr + F[C(r)] = 4π Nelec ∫{R+} (V(r) + Z/r) r^2 dr\n\n\n\n\n\n","category":"function"},{"location":"api/#DFTK.eval_psp_energy_correction-Tuple{Any, PspUpf, Any}","page":"API reference","title":"DFTK.eval_psp_energy_correction","text":"eval_psp_energy_correction(T::Type, psp::PspUpf, n_electrons::Number)\n\nFor UPFs, the integral is transformed to the following sum: 4π Nelec Σ{i} ri dr[i]\n\n\n\n\n\n","category":"method"},{"location":"api/#DFTK.eval_psp_local_fourier-Tuple{DFTK.NormConservingPsp, AbstractVector}","page":"API reference","title":"DFTK.eval_psp_local_fourier","text":"eval_psp_local_fourier(psp, q)\n\nEvaluate the local part of the pseudopotential in reciprocal space: Vloc(q) = ∫{R^3} Vloc(r) e^{-iqr} dr = 4π ∫{R+} Vloc(r) sin(qr)/q r dr In practice, the local potential should be corrected using a Coulomb-like term C(r) = -Z/r to remove the long-range tail of Vloc(r) from the integral: Vloc(q) = (∫_{R^3} (Vloc(r) - C(r)) e^{-iqr} dr) + F[C(r)] = 4π ∫{R+} (Vloc(r) + Z/r) sin(qr)/qr r^2 dr - Z/q^2\n\n\n\n\n\n","category":"method"},{"location":"api/#DFTK.eval_psp_local_fourier-Union{Tuple{T}, Tuple{PspUpf, T}} where T<:Real","page":"API reference","title":"DFTK.eval_psp_local_fourier","text":"eval_psp_local_fourier(psp::PspUpf, q<:Real)\n\nfor UPFs, the integral is transformed to the following sum: 4π/q (Σ{i} sin(q r[i]) (r[i] V(r[i]) + Z) dr[i] - Z/q)\n\n\n\n\n\n","category":"method"},{"location":"api/#DFTK.eval_psp_local_real-Tuple{DFTK.NormConservingPsp, AbstractVector}","page":"API reference","title":"DFTK.eval_psp_local_real","text":"eval_psp_local_real(psp, r)\n\nEvaluate the local part of the pseudopotential in real space.\n\n\n\n\n\n","category":"method"},{"location":"api/#DFTK.eval_psp_local_real-Union{Tuple{T}, Tuple{PspUpf, T}} where T<:Real","page":"API reference","title":"DFTK.eval_psp_local_real","text":" eval_psp_local_real(psp::PspUpf, r<:Real)\n\nEvaluate the local potential at real-space distance r via linear interpolation on the real-space mesh.\n\n\n\n\n\n","category":"method"},{"location":"api/#DFTK.eval_psp_projector_fourier-Tuple{DFTK.NormConservingPsp, AbstractVector}","page":"API reference","title":"DFTK.eval_psp_projector_fourier","text":"eval_psp_projector_fourier(psp, i, l, q)\n\nEvaluate the radial part of the i-th projector for angular momentum l at the reciprocal vector with modulus q: p(q) = ∫R^3 p{il}(r) e^{-iqr} dr = 4π ∫{R+} r^2 p{il}(r) j_l(q r) dr\n\n\n\n\n\n","category":"method"},{"location":"api/#DFTK.eval_psp_projector_fourier-Union{Tuple{T}, Tuple{PspUpf, Any, Any, T}} where T<:Real","page":"API reference","title":"DFTK.eval_psp_projector_fourier","text":"eval_psp_projector_fourier(psp::PspUPF, i::Number, l::Number, q<:Real)\n\nFor UPFs, the integral is transformed to the following sum: 4π Σ{k} jl(q r[k]) (r[k]^2 p{il}(r[k]) dr[k])\n\n\n\n\n\n","category":"method"},{"location":"api/#DFTK.eval_psp_projector_real-Tuple{DFTK.NormConservingPsp, Any, Any, AbstractVector}","page":"API reference","title":"DFTK.eval_psp_projector_real","text":"eval_psp_projector_real(psp, i, l, r)\n\nEvaluate the radial part of the i-th projector for angular momentum l in real-space at the vector with modulus r.\n\n\n\n\n\n","category":"method"},{"location":"api/#DFTK.eval_psp_projector_real-Union{Tuple{T}, Tuple{PspUpf, Any, Any, T}} where T<:Real","page":"API reference","title":"DFTK.eval_psp_projector_real","text":"eval_psp_projector_real(psp::PspUpf, i::Number, l::Number, r<:Real)\n\nEvaluate the ith Kleinman-Bylander β projector with angular momentum l at real-space distance r via linear interpolation on the real-space mesh.\n\nNote: UPFs store r[j] β_{li}(r[j]), so r=0 is undefined and will error.\n\n\n\n\n\n","category":"method"},{"location":"api/#DFTK.filled_occupation-Tuple{Any}","page":"API reference","title":"DFTK.filled_occupation","text":"Maximal occupation of a state (2 for non-spin-polarized electrons, 1 otherwise).\n\n\n\n\n\n","category":"method"},{"location":"api/#DFTK.find_equivalent_kpt-Union{Tuple{T}, Tuple{PlaneWaveBasis{T, VT} where VT<:Real, Any, Any}} where T","page":"API reference","title":"DFTK.find_equivalent_kpt","text":"Find the equivalent index of the coordinate kcoord ∈ ℝ³ in a list kcoords ∈ [-½, ½)³. ΔG is the vector of ℤ³ such that kcoords[index] = kcoord + ΔG.\n\n\n\n\n\n","category":"method"},{"location":"api/#DFTK.gather_kpts-Tuple{AbstractArray, PlaneWaveBasis}","page":"API reference","title":"DFTK.gather_kpts","text":"Gather the distributed data of a quantity depending on k-Points on the master process and return it. On the other (non-master) processes nothing is returned.\n\n\n\n\n\n","category":"method"},{"location":"api/#DFTK.gather_kpts-Tuple{PlaneWaveBasis}","page":"API reference","title":"DFTK.gather_kpts","text":"Gather the distributed k-point data on the master process and return it as a PlaneWaveBasis. On the other (non-master) processes nothing is returned. The returned object should not be used for computations and only to extract data for post-processing and serialisation to disk.\n\n\n\n\n\n","category":"method"},{"location":"api/#DFTK.gaussian_superposition-Union{Tuple{T}, Tuple{PlaneWaveBasis{T, VT} where VT<:Real, Any}} where T","page":"API reference","title":"DFTK.gaussian_superposition","text":"Build a superposition of Gaussians as a guess for the density and magnetisation. Expects a list of tuples (coefficient, length, position) for each of the Gaussian, which follow the functional form\n\nhatρ(G) = textcoefficient expleft(-(2π textlength G)^2right)\n\nand are placed at position (in fractional coordinates).\n\n\n\n\n\n","category":"method"},{"location":"api/#DFTK.guess_density","page":"API reference","title":"DFTK.guess_density","text":"guess_density(basis, magnetic_moments=[])\nguess_density(basis, system)\n\nBuild a superposition of atomic densities (SAD) guess density.\n\nWe take for the guess density a Gaussian centered around the atom, of length specified by atom_decay_length, normalized to get the right number of electrons\n\nhatρ(G) = Z expleft(-(2π textlength G)^2right)\n\nWhen magnetic moments are provided, construct a symmetry-broken density guess. The magnetic moments should be specified in units of μ_B.\n\n\n\n\n\n","category":"function"},{"location":"api/#DFTK.hamiltonian_with_total_potential-Tuple{Hamiltonian, Any}","page":"API reference","title":"DFTK.hamiltonian_with_total_potential","text":"Returns a new Hamiltonian with local potential replaced by the given one\n\n\n\n\n\n","category":"method"},{"location":"api/#DFTK.index_G_vectors-Tuple{Tuple, AbstractVector{<:Integer}}","page":"API reference","title":"DFTK.index_G_vectors","text":"Return the index tuple I such that G_vectors(basis)[I] == G or the index i such that G_vectors(basis, kpoint)[i] == G. Returns nothing if outside the range of valid wave vectors.\n\n\n\n\n\n","category":"method"},{"location":"api/#DFTK.interpolate_density-Tuple{Any, PlaneWaveBasis, PlaneWaveBasis}","page":"API reference","title":"DFTK.interpolate_density","text":"Interpolate a function expressed in a basis basis_in to a basis basis_out. This interpolation uses a very basic real-space algorithm, and makes a DWIM-y attempt to take into account the fact that basis_out can be a supercell of basis_in.\n\n\n\n\n\n","category":"method"},{"location":"api/#DFTK.interpolate_kpoint-Tuple{AbstractVecOrMat, PlaneWaveBasis, Kpoint, PlaneWaveBasis, Kpoint}","page":"API reference","title":"DFTK.interpolate_kpoint","text":"Interpolate some data from one k-point to another. The interpolation is fast, but not necessarily exact. Intended only to construct guesses for iterative solvers.\n\n\n\n\n\n","category":"method"},{"location":"api/#DFTK.irfft-Union{Tuple{T}, Tuple{PlaneWaveBasis{T, VT} where VT<:Real, AbstractArray}} where T","page":"API reference","title":"DFTK.irfft","text":"Perform a real valued iFFT; see ifft.\n\n\n\n\n\n","category":"method"},{"location":"api/#DFTK.is_metal-Tuple{Any, Any}","page":"API reference","title":"DFTK.is_metal","text":"is_metal(eigenvalues, εF; tol)\n\nDetermine whether the provided bands indicate the material is a metal, i.e. where bands are cut by the Fermi level.\n\n\n\n\n\n","category":"method"},{"location":"api/#DFTK.k_to_kpq_mapping-Tuple{PlaneWaveBasis, Any}","page":"API reference","title":"DFTK.k_to_kpq_mapping","text":"Return the indices of the kpoints shifted by q. That is for each kpoint of the basis: kpoints[ik].coordinate + q = kpoints[indices[ik]].coordinate.\n\n\n\n\n\n","category":"method"},{"location":"api/#DFTK.kgrid_from_minimal_n_kpoints-Tuple{Any, Integer}","page":"API reference","title":"DFTK.kgrid_from_minimal_n_kpoints","text":"Selects a kgrid size which ensures that at least a n_kpoints total number of k-points are used. The distribution of k-points amongst coordinate directions is as uniformly as possible, trying to achieve an identical minimal spacing in all directions.\n\n\n\n\n\n","category":"method"},{"location":"api/#DFTK.kgrid_from_minimal_spacing-Tuple{Any, Any}","page":"API reference","title":"DFTK.kgrid_from_minimal_spacing","text":"Selects a kgrid size to ensure a minimal spacing (in inverse Bohrs) between kpoints. A reasonable spacing is 0.13 inverse Bohrs (around 2π * 004 AA^-1).\n\n\n\n\n\n","category":"method"},{"location":"api/#DFTK.kgrid_monkhorst_pack-Tuple{Any}","page":"API reference","title":"DFTK.kgrid_monkhorst_pack","text":"Construct the coordinates of the k-points in a (shifted) Monkorst-Pack grid\n\n\n\n\n\n","category":"method"},{"location":"api/#DFTK.kpath_get_kcoords-Union{Tuple{Brillouin.KPaths.KPathInterpolant{D}}, Tuple{D}} where D","page":"API reference","title":"DFTK.kpath_get_kcoords","text":"Return kpoint coordinates in reduced coordinates\n\n\n\n\n\n","category":"method"},{"location":"api/#DFTK.krange_spin-Tuple{PlaneWaveBasis, Integer}","page":"API reference","title":"DFTK.krange_spin","text":"Return the index range of k-points that have a particular spin component.\n\n\n\n\n\n","category":"method"},{"location":"api/#DFTK.list_psp","page":"API reference","title":"DFTK.list_psp","text":"list_psp(element; functional, family, core, datadir_psp)\n\nList the pseudopotential files known to DFTK. Allows various ways to restrict the displayed files.\n\nExamples\n\njulia> list_psp(family=\"hgh\")\n\nwill list all HGH-type pseudopotentials and\n\njulia> list_psp(family=\"hgh\", functional=\"lda\")\n\nwill only list those for LDA (also known as Pade in this context) and\n\njulia> list_psp(:O, core=:semicore)\n\nwill list all oxygen semicore pseudopotentials known to DFTK.\n\n\n\n\n\n","category":"function"},{"location":"api/#DFTK.load_psp-Tuple{AbstractString}","page":"API reference","title":"DFTK.load_psp","text":"Load a pseudopotential file from the library of pseudopotentials. The file is searched in the directory datadir_psp() and by the key. If the key is a path to a valid file, the extension is used to determine the type of the pseudopotential file format and a respective class is returned.\n\n\n\n\n\n","category":"method"},{"location":"api/#DFTK.load_scfres","page":"API reference","title":"DFTK.load_scfres","text":"load_scfres(filename)\n\nLoad back an scfres, which has previously been stored with save_scfres. Note the warning in save_scfres.\n\n\n\n\n\n","category":"function"},{"location":"api/#DFTK.local_potential_fourier-Tuple{DFTK.Element, AbstractVector}","page":"API reference","title":"DFTK.local_potential_fourier","text":"Radial local potential, in Fourier space: V(q) = int_{R^3} V(x) e^{-iqx} dx.\n\n\n\n\n\n","category":"method"},{"location":"api/#DFTK.local_potential_real-Tuple{DFTK.Element, AbstractVector}","page":"API reference","title":"DFTK.local_potential_real","text":"Radial local potential, in real space.\n\n\n\n\n\n","category":"method"},{"location":"api/#DFTK.model_DFT-Tuple{AbstractMatrix, Vector{<:DFTK.Element}, Vector{<:AbstractVector}, Xc}","page":"API reference","title":"DFTK.model_DFT","text":"Build a DFT model from the specified atoms, with the specified functionals.\n\n\n\n\n\n","category":"method"},{"location":"api/#DFTK.model_LDA-Tuple{AbstractMatrix, Vector{<:DFTK.Element}, Vector{<:AbstractVector}}","page":"API reference","title":"DFTK.model_LDA","text":"Build an LDA model (Perdew & Wang parametrization) from the specified atoms. DOI:10.1103/PhysRevB.45.13244\n\n\n\n\n\n","category":"method"},{"location":"api/#DFTK.model_PBE-Tuple{AbstractMatrix, Vector{<:DFTK.Element}, Vector{<:AbstractVector}}","page":"API reference","title":"DFTK.model_PBE","text":"Build an PBE-GGA model from the specified atoms. DOI:10.1103/PhysRevLett.77.3865\n\n\n\n\n\n","category":"method"},{"location":"api/#DFTK.model_SCAN-Tuple{AbstractMatrix, Vector{<:DFTK.Element}, Vector{<:AbstractVector}}","page":"API reference","title":"DFTK.model_SCAN","text":"Build a SCAN meta-GGA model from the specified atoms. DOI:10.1103/PhysRevLett.115.036402\n\n\n\n\n\n","category":"method"},{"location":"api/#DFTK.model_atomic-Tuple{AbstractMatrix, Vector{<:DFTK.Element}, Vector{<:AbstractVector}}","page":"API reference","title":"DFTK.model_atomic","text":"Convenience constructor, which builds a standard atomic (kinetic + atomic potential) model. Use extra_terms to add additional terms.\n\n\n\n\n\n","category":"method"},{"location":"api/#DFTK.mpi_nprocs","page":"API reference","title":"DFTK.mpi_nprocs","text":"Number of processors used in MPI. Can be called without ensuring initialization.\n\n\n\n\n\n","category":"function"},{"location":"api/#DFTK.multiply_by_expiqr-NTuple{4, Any}","page":"API reference","title":"DFTK.multiply_by_expiqr","text":"Return the Fourier coefficients for ψk · e^{i q·r} in the basis of kpt_out, where ψk is defined on a basis kpt_in.\n\n\n\n\n\n","category":"method"},{"location":"api/#DFTK.n_elec_core-Tuple{DFTK.Element}","page":"API reference","title":"DFTK.n_elec_core","text":"Return the number of core electrons\n\n\n\n\n\n","category":"method"},{"location":"api/#DFTK.n_elec_valence-Tuple{DFTK.Element}","page":"API reference","title":"DFTK.n_elec_valence","text":"Return the number of valence electrons\n\n\n\n\n\n","category":"method"},{"location":"api/#DFTK.n_electrons_from_atoms-Tuple{Any}","page":"API reference","title":"DFTK.n_electrons_from_atoms","text":"Number of valence electrons.\n\n\n\n\n\n","category":"method"},{"location":"api/#DFTK.newton-Union{Tuple{T}, Tuple{PlaneWaveBasis{T, VT} where VT<:Real, Any}} where T","page":"API reference","title":"DFTK.newton","text":"newton(basis::PlaneWaveBasis{T}, ψ0;\n tol=1e-6, tol_cg=tol / 100, maxiter=20, callback=ScfDefaultCallback(),\n is_converged=ScfConvergenceDensity(tol))\n\nNewton algorithm. Be careful that the starting point needs to be not too far from the solution.\n\n\n\n\n\n","category":"method"},{"location":"api/#DFTK.next_compatible_fft_size-Tuple{Int64}","page":"API reference","title":"DFTK.next_compatible_fft_size","text":"Find the next compatible FFT size Sizes must (a) be a product of small primes only and (b) contain the factors. If smallprimes is empty (a) is skipped.\n\n\n\n\n\n","category":"method"},{"location":"api/#DFTK.next_density","page":"API reference","title":"DFTK.next_density","text":"Obtain new density ρ by diagonalizing ham. Follows the policy imposed by the bands data structure to determine and adjust the number of bands to be computed.\n\n\n\n\n\n","category":"function"},{"location":"api/#DFTK.norm2-Tuple{Any}","page":"API reference","title":"DFTK.norm2","text":"Square of the ℓ²-norm.\n\n\n\n\n\n","category":"method"},{"location":"api/#DFTK.norm_cplx-Tuple{Any}","page":"API reference","title":"DFTK.norm_cplx","text":"Complex-analytic extension of LinearAlgebra.norm(x) from real to complex inputs. Needed for phonons as we want to perform a matrix-vector product f'(x)·h, where f is a real-to-real function and h a complex vector. To do this using automatic differentiation, we can extend analytically f to accept complex inputs, then differentiate t -> f(x+t·h). This will fail if non-analytic functions like norm are used for complex inputs, and therefore we have to redefine it.\n\n\n\n\n\n","category":"method"},{"location":"api/#DFTK.normalize_kpoint_coordinate-Tuple{Real}","page":"API reference","title":"DFTK.normalize_kpoint_coordinate","text":"Bring k-point coordinates into the range [-0.5, 0.5)\n\n\n\n\n\n","category":"method"},{"location":"api/#DFTK.overlap_Mmn_k_kpb-Tuple{PlaneWaveBasis, Any, Any, Any, Any, Any}","page":"API reference","title":"DFTK.overlap_Mmn_k_kpb","text":"Computes the matrix M^kb_mn = langle u_mk u_nk+b rangle for given k, kpb = k+b.\n\nG_shift is the \"shifting\" vector, correction due to the periodicity conditions imposed on k -> ψk. It is non zero if kpb is taken in another unit cell of the reciprocal lattice. We use here that : ``u{n(k + Gshift)}(r) = e^{-i*\\langle Gshift,r \\rangle} u_{nk}``\n\n\n\n\n\n","category":"method"},{"location":"api/#DFTK.plot_bandstructure","page":"API reference","title":"DFTK.plot_bandstructure","text":"Compute and plot the band structure. n_bands selects the number of bands to compute. If this value is absent and an scfres is used to start the calculation a default of n_bands_scf + 5sqrt(n_bands_scf) is used. The unit used to plot the bands can be selected using the unit parameter. Like in the rest of DFTK Hartree is used by default. Another standard choices is unit=u\"eV\" (electron volts). The kline_density is given in number of k-points per inverse bohrs (i.e. overall in units of length).\n\n\n\n\n\n","category":"function"},{"location":"api/#DFTK.plot_dos","page":"API reference","title":"DFTK.plot_dos","text":"Plot the density of states over a reasonable range. Requires to load Plots.jl beforehand.\n\n\n\n\n\n","category":"function"},{"location":"api/#DFTK.psp_local_polynomial","page":"API reference","title":"DFTK.psp_local_polynomial","text":"The local potential of a HGH pseudopotentials in reciprocal space can be brought to the form Q(t) (t^2 exp(t^2 2)) where t = r_textloc q and Q is a polynomial of at most degree 8. This function returns Q.\n\n\n\n\n\n","category":"function"},{"location":"api/#DFTK.psp_projector_polynomial","page":"API reference","title":"DFTK.psp_projector_polynomial","text":"The nonlocal projectors of a HGH pseudopotentials in reciprocal space can be brought to the form Q(t) exp(-t^2 2) where t = r_l q and Q is a polynomial. This function returns Q.\n\n\n\n\n\n","category":"function"},{"location":"api/#DFTK.qcut_psp_local-Union{Tuple{PspHgh{T}}, Tuple{T}} where T","page":"API reference","title":"DFTK.qcut_psp_local","text":"Estimate an upper bound for the argument q after which abs(eval_psp_local_fourier(psp, q)) is a strictly decreasing function.\n\n\n\n\n\n","category":"method"},{"location":"api/#DFTK.qcut_psp_projector-Union{Tuple{T}, Tuple{PspHgh{T}, Any, Any}} where T","page":"API reference","title":"DFTK.qcut_psp_projector","text":"Estimate an upper bound for the argument q after which eval_psp_projector_fourier(psp, q) is a strictly decreasing function.\n\n\n\n\n\n","category":"method"},{"location":"api/#DFTK.r_vectors-Tuple{PlaneWaveBasis}","page":"API reference","title":"DFTK.r_vectors","text":"r_vectors(basis::PlaneWaveBasis)\n\nThe list of r vectors, in reduced coordinates. By convention, this is in [0,1)^3.\n\n\n\n\n\n","category":"method"},{"location":"api/#DFTK.r_vectors_cart-Tuple{PlaneWaveBasis}","page":"API reference","title":"DFTK.r_vectors_cart","text":"r_vectors_cart(basis::PlaneWaveBasis)\n\nThe list of r vectors, in cartesian coordinates.\n\n\n\n\n\n","category":"method"},{"location":"api/#DFTK.random_density-Tuple{PlaneWaveBasis}","page":"API reference","title":"DFTK.random_density","text":"Generate a physically valid random density integrating to the given number of electrons.\n\n\n\n\n\n","category":"method"},{"location":"api/#DFTK.read_w90_nnkp-Tuple{String}","page":"API reference","title":"DFTK.read_w90_nnkp","text":"Read the .nnkp file provided by the preprocessing routine of Wannier90 (i.e. \"wannier90.x -pp prefix\") Returns:\n\nthe array 'nnkpts' of k points, their respective nearest neighbors and associated shifing vectors (non zero if the neighbor is located in another cell).\nthe number 'nntot' of neighbors per k point.\n\nTODO: add the possibility to exclude bands\n\n\n\n\n\n","category":"method"},{"location":"api/#DFTK.run_wannier90","page":"API reference","title":"DFTK.run_wannier90","text":"Wannerize the obtained bands using wannier90. By default all converged bands from the scfres are employed (change with n_bands kwargs) and n_wannier = n_bands wannier functions are computed using random Gaussians as guesses. All keyword arguments supported by Wannier90 for the disentanglement may be added as keyword arguments. The function returns the fileprefix.\n\nwarning: Experimental feature\nCurrently this is an experimental feature, which has not yet been tested to full depth. The interface is considered unstable and may change incompatibly in the future. Use at your own risk and please report bugs in case you encounter any.\n\n\n\n\n\n","category":"function"},{"location":"api/#DFTK.save_scfres-Tuple{AbstractString, NamedTuple}","page":"API reference","title":"DFTK.save_scfres","text":"save_scfres(filename, scfres)\n\nSave an scfres obtained from self_consistent_field to a file. The format is determined from the file extension. Currently the following file extensions are recognized and supported:\n\njld2: A JLD2 file. Stores the complete state and can be used (with load_scfres) to restart an SCF from a checkpoint or post-process an SCF solution. See Saving SCF results on disk and SCF checkpoints for details.\nvts: A VTK file for visualisation e.g. in paraview. Stores the density, spin density and some metadata (energy, Fermi level, occupation etc.). Supports these keyword arguments:\nsave_ψ: Save the real-space representation of the orbitals as well (may lead to larger files).\nextra_data: Dict{String,Array} with additional data on the 3D real-space grid to store into the VTK file.\n\nwarning: No compatibility guarantees\nNo guarantees are made with respect to this function at this point. It may change incompatibly between DFTK versions or stop working / be removed in the future.\n\n\n\n\n\n","category":"method"},{"location":"api/#DFTK.scf_anderson_solver","page":"API reference","title":"DFTK.scf_anderson_solver","text":"Create a simple anderson-accelerated SCF solver. m specifies the number of steps to keep the history of.\n\n\n\n\n\n","category":"function"},{"location":"api/#DFTK.scf_damping_quadratic_model-Tuple{Any, Any}","page":"API reference","title":"DFTK.scf_damping_quadratic_model","text":"Use the two iteration states info and info_next to find a damping value from a quadratic model for the SCF energy. Returns nothing if the constructed model is not considered trustworthy, else returns the suggested damping.\n\n\n\n\n\n","category":"method"},{"location":"api/#DFTK.scf_damping_solver","page":"API reference","title":"DFTK.scf_damping_solver","text":"Create a damped SCF solver updating the density as x = β * x_new + (1 - β) * x\n\n\n\n\n\n","category":"function"},{"location":"api/#DFTK.select_eigenpairs_all_kblocks-Tuple{Any, Any}","page":"API reference","title":"DFTK.select_eigenpairs_all_kblocks","text":"Function to select a subset of eigenpairs on each k-Point. Works on the Tuple returned by diagonalize_all_kblocks.\n\n\n\n\n\n","category":"method"},{"location":"api/#DFTK.self_consistent_field-Union{Tuple{PlaneWaveBasis{T, VT} where VT<:Real}, Tuple{T}} where T","page":"API reference","title":"DFTK.self_consistent_field","text":"self_consistent_field(basis; [tol, mixing, damping, ρ, ψ])\n\nSolve the Kohn-Sham equations with a density-based SCF algorithm using damped, preconditioned iterations where ρ_textnext = α P^-1 (ρ_textout - ρ_textin).\n\nOverview of parameters:\n\nρ: Initial density\nψ: Initial orbitals\ntol: Tolerance for the density change (ρ_textout - ρ_textin) to flag convergence. Default is 1e-6.\nis_converged: Convergence control callback. Typical objects passed here are DFTK.ScfConvergenceDensity(tol) (the default), DFTK.ScfConvergenceEnergy(tol) or DFTK.ScfConvergenceForce(tol).\nmaxiter: Maximal number of SCF iterations\nmixing: Mixing method, which determines the preconditioner P^-1 in the above equation. Typical mixings are LdosMixing, KerkerMixing, SimpleMixing or DielectricMixing. Default is LdosMixing()\ndamping: Damping parameter α in the above equation. Default is 0.8.\nnbandsalg: By default DFTK uses nbandsalg=AdaptiveBands(model), which adaptively determines the number of bands to compute. If you want to influence this algorithm or use a predefined number of bands in each SCF step, pass a FixedBands or AdaptiveBands.\ncallback: Function called at each SCF iteration. Usually takes care of printing the intermediate state.\n\n\n\n\n\n","category":"method"},{"location":"api/#DFTK.sin2pi-Tuple{Any}","page":"API reference","title":"DFTK.sin2pi","text":"Function to compute sin(2π x)\n\n\n\n\n\n","category":"method"},{"location":"api/#DFTK.solve_ΩplusK-Union{Tuple{T}, Tuple{PlaneWaveBasis{T, VT} where VT<:Real, Any, Any, Any}} where T","page":"API reference","title":"DFTK.solve_ΩplusK","text":"solve_ΩplusK(basis::PlaneWaveBasis{T}, ψ, res, occupation;\n tol=1e-10, verbose=false) where {T}\n\nReturn δψ where (Ω+K) δψ = rhs\n\n\n\n\n\n","category":"method"},{"location":"api/#DFTK.solve_ΩplusK_split-Union{Tuple{T}, Tuple{Hamiltonian, AbstractArray{T}, Any, Any, Any, Any, Any}} where T","page":"API reference","title":"DFTK.solve_ΩplusK_split","text":"Solve the problem (Ω+K) δψ = rhs using a split algorithm, where rhs is typically -δHextψ (the negative matvec of an external perturbation with the SCF orbitals ψ) and δψ is the corresponding total variation in the orbitals ψ. Additionally returns: - δρ: Total variation in density) - δHψ: Total variation in Hamiltonian applied to orbitals - δeigenvalues: Total variation in eigenvalues - δVind: Change in potential induced by δρ (the term needed on top of δHextψ to get δHψ).\n\n\n\n\n\n","category":"method"},{"location":"api/#DFTK.spglib_atoms-Tuple{Any, AbstractVector{<:AbstractVector{<:AbstractFloat}}, Any}","page":"API reference","title":"DFTK.spglib_atoms","text":"Convert the DFTK atom groups and positions datastructure into a tuple of datastructures for use with spglib. Validity of the input data is assumed. The output positions contains positions per atom, numbers contains the mapping atom to a unique number for each group of indistinguishable atoms, spins contains the z-component of the initial magnetic moment on each atom, mapping contains the mapping of the numbers to the element objects in DFTK and collinear whether the atoms mark a case of collinear spin or not. Notice that if collinear is false then spins is garbage.\n\n\n\n\n\n","category":"method"},{"location":"api/#DFTK.spglib_standardize_cell-Union{Tuple{T}, Tuple{AbstractArray{T}, Any, Any}, Tuple{AbstractArray{T}, Any, Any, Any}} where T","page":"API reference","title":"DFTK.spglib_standardize_cell","text":"Returns crystallographic conventional cell according to the International Table of Crystallography Vol A (ITA) in case primitive=false. If primitive=true the primitive lattice is returned in the convention of the reference work of Cracknell, Davies, Miller, and Love (CDML). Of note this has minor differences to the primitive setting choice made in the ITA.\n\n\n\n\n\n","category":"method"},{"location":"api/#DFTK.sphericalbesselj_fast-Union{Tuple{T}, Tuple{Integer, T}} where T","page":"API reference","title":"DFTK.sphericalbesselj_fast","text":"sphericalbesselj_fast(l::Integer, x::Number)\n\nReturns the spherical Bessel function of the first kind jl(x). Consistent with https://en.wikipedia.org/wiki/Besselfunction#SphericalBesselfunctions and with SpecialFunctions.sphericalbesselj. Specialized for integer 0 <= l <= 5.\n\n\n\n\n\n","category":"method"},{"location":"api/#DFTK.spin_components-Tuple{Symbol}","page":"API reference","title":"DFTK.spin_components","text":"Explicit spin components of the KS orbitals and the density\n\n\n\n\n\n","category":"method"},{"location":"api/#DFTK.split_evenly-Tuple{Any, Any}","page":"API reference","title":"DFTK.split_evenly","text":"Split an iterable evenly into N chunks, which will be returned.\n\n\n\n\n\n","category":"method"},{"location":"api/#DFTK.standardize_atoms","page":"API reference","title":"DFTK.standardize_atoms","text":"Apply various standardisations to a lattice and a list of atoms. It uses spglib to detect symmetries (within tol_symmetry), then cleans up the lattice according to the symmetries (unless correct_symmetry is false) and returns the resulting standard lattice and atoms. If primitive is true (default) the primitive unit cell is returned, else the conventional unit cell is returned.\n\n\n\n\n\n","category":"function"},{"location":"api/#DFTK.symmetries_preserving_kgrid-Tuple{Any, Any}","page":"API reference","title":"DFTK.symmetries_preserving_kgrid","text":"Filter out the symmetry operations that don't respect the symmetries of the discrete BZ grid\n\n\n\n\n\n","category":"method"},{"location":"api/#DFTK.symmetries_preserving_rgrid-Tuple{Any, Any}","page":"API reference","title":"DFTK.symmetries_preserving_rgrid","text":"Filter out the symmetry operations that don't respect the symmetries of the discrete real-space grid\n\n\n\n\n\n","category":"method"},{"location":"api/#DFTK.symmetrize_forces-Tuple{Model, Any}","page":"API reference","title":"DFTK.symmetrize_forces","text":"Symmetrize the forces in reduced coordinates, forces given as an array forces[iel][α,i]\n\n\n\n\n\n","category":"method"},{"location":"api/#DFTK.symmetrize_stresses-Tuple{Model, Any}","page":"API reference","title":"DFTK.symmetrize_stresses","text":"Symmetrize the stress tensor, given as a Matrix in cartesian coordinates\n\n\n\n\n\n","category":"method"},{"location":"api/#DFTK.symmetrize_ρ-Tuple{Any, Any}","page":"API reference","title":"DFTK.symmetrize_ρ","text":"Symmetrize a density by applying all the basis (by default) symmetries and forming the average.\n\n\n\n\n\n","category":"method"},{"location":"api/#DFTK.symmetry_operations","page":"API reference","title":"DFTK.symmetry_operations","text":"Return the k-point symmetry operations associated to a lattice and atoms.\n\n\n\n\n\n","category":"function"},{"location":"api/#DFTK.synchronize_device-Tuple{DFTK.AbstractArchitecture}","page":"API reference","title":"DFTK.synchronize_device","text":"Synchronize data and finish all operations on the execution stream of the device. This needs to be called explicitly before a task finishes (e.g. in an @spawn block).\n\n\n\n\n\n","category":"method"},{"location":"api/#DFTK.to_cpu-Tuple{AbstractArray}","page":"API reference","title":"DFTK.to_cpu","text":"Transfer an array from a device (typically a GPU) to the CPU.\n\n\n\n\n\n","category":"method"},{"location":"api/#DFTK.to_device-Tuple{DFTK.CPU, Any}","page":"API reference","title":"DFTK.to_device","text":"Transfer an array to a particular device (typically a GPU)\n\n\n\n\n\n","category":"method"},{"location":"api/#DFTK.total_local_potential-Tuple{Hamiltonian}","page":"API reference","title":"DFTK.total_local_potential","text":"Get the total local potential of the given Hamiltonian, in real space in the spin components.\n\n\n\n\n\n","category":"method"},{"location":"api/#DFTK.transfer_blochwave-Union{Tuple{T}, Tuple{Any, PlaneWaveBasis{T, VT} where VT<:Real, PlaneWaveBasis{T, VT} where VT<:Real}} where T","page":"API reference","title":"DFTK.transfer_blochwave","text":"Transfer Bloch wave between two basis sets. Limited feature set.\n\n\n\n\n\n","category":"method"},{"location":"api/#DFTK.transfer_blochwave_kpt-Tuple{Any, PlaneWaveBasis, Any, Any, Any}","page":"API reference","title":"DFTK.transfer_blochwave_kpt","text":"Transfer an array ψk_in expanded on kpt_in, and produce ψ(r) e^i ΔGr expanded on kpt_out. It is mostly useful for phonons. Beware: ψk_out can lose information if the shift ΔG is large or if the G_vectors differ between k-points.\n\n\n\n\n\n","category":"method"},{"location":"api/#DFTK.transfer_blochwave_kpt-Union{Tuple{T}, Tuple{Any, PlaneWaveBasis{T, VT} where VT<:Real, Kpoint, PlaneWaveBasis{T, VT} where VT<:Real, Kpoint}} where T","page":"API reference","title":"DFTK.transfer_blochwave_kpt","text":"Transfer an array ψk defined on basisin k-point kptin to basisout k-point kptout.\n\n\n\n\n\n","category":"method"},{"location":"api/#DFTK.transfer_mapping-Union{Tuple{T}, Tuple{PlaneWaveBasis{T, VT} where VT<:Real, Kpoint, PlaneWaveBasis{T, VT} where VT<:Real, Kpoint}} where T","page":"API reference","title":"DFTK.transfer_mapping","text":"Compute the index mapping between two bases. Returns two arrays idcs_in and idcs_out such that ψkout[idcs_out] = ψkin[idcs_in] does the transfer from ψkin (defined on basis_in and kpt_in) to ψkout (defined on basis_out and kpt_out).\n\n\n\n\n\n","category":"method"},{"location":"api/#DFTK.unfold_bz-Tuple{PlaneWaveBasis}","page":"API reference","title":"DFTK.unfold_bz","text":"\" Convert a basis into one that doesn't use BZ symmetry. This is mainly useful for debug purposes (e.g. in cases we don't want to bother thinking about symmetries).\n\n\n\n\n\n","category":"method"},{"location":"api/#DFTK.weighted_ksum-Tuple{PlaneWaveBasis, Any}","page":"API reference","title":"DFTK.weighted_ksum","text":"Sum an array over kpoints, taking weights into account\n\n\n\n\n\n","category":"method"},{"location":"api/#DFTK.write_w90_eig-Tuple{String, Any}","page":"API reference","title":"DFTK.write_w90_eig","text":"Write the eigenvalues in a format readable by Wannier90.\n\n\n\n\n\n","category":"method"},{"location":"api/#DFTK.write_w90_win-Tuple{String, PlaneWaveBasis}","page":"API reference","title":"DFTK.write_w90_win","text":"Write a win file at the indicated prefix. Parameters to Wannier90 can be added as kwargs: e.g. num_iter=500.\n\n\n\n\n\n","category":"method"},{"location":"api/#DFTK.ylm_real-Union{Tuple{T}, Tuple{Integer, Integer, AbstractVector{T}}} where T","page":"API reference","title":"DFTK.ylm_real","text":"Returns the (l,m) real spherical harmonic Ylm(r). Consistent with https://en.wikipedia.org/wiki/Tableofsphericalharmonics#Realsphericalharmonics\n\n\n\n\n\n","category":"method"},{"location":"api/#DFTK.zeros_like","page":"API reference","title":"DFTK.zeros_like","text":"Create an array of same \"array type\" as X filled with zeros, minimizing the number of allocations. This unifies CPU and GPU code, as the output will always be on the same device as the input.\n\n\n\n\n\n","category":"function"},{"location":"api/#DFTK.@timing-Tuple","page":"API reference","title":"DFTK.@timing","text":"Shortened version of the @timeit macro from TimerOutputs, which writes to the DFTK timer.\n\n\n\n\n\n","category":"macro"},{"location":"api/#DFTK.Smearing.A-Tuple{Any, Any}","page":"API reference","title":"DFTK.Smearing.A","text":"A term in the Hermite delta expansion\n\n\n\n\n\n","category":"method"},{"location":"api/#DFTK.Smearing.H-Tuple{Any, Any}","page":"API reference","title":"DFTK.Smearing.H","text":"Standard Hermite function using physicist's convention.\n\n\n\n\n\n","category":"method"},{"location":"api/#DFTK.Smearing.entropy-Tuple{DFTK.Smearing.SmearingFunction, Any}","page":"API reference","title":"DFTK.Smearing.entropy","text":"Entropy. Note that this is a function of the energy x, not of occupation(x). This function satisfies s' = x f' (see https://www.vasp.at/vasp-workshop/k-points.pdf p. 12 and https://arxiv.org/pdf/1805.07144.pdf p. 18.\n\n\n\n\n\n","category":"method"},{"location":"api/#DFTK.Smearing.occupation","page":"API reference","title":"DFTK.Smearing.occupation","text":"occupation(S::SmearingFunction, x)\n\nOccupation at x, where in practice x = (ε - εF) / temperature. If temperature is zero, (ε-εF)/temperature = ±∞. The occupation function is required to give 1 and 0 respectively in these cases.\n\n\n\n\n\n","category":"function"},{"location":"api/#DFTK.Smearing.occupation_derivative-Tuple{DFTK.Smearing.SmearingFunction, Any}","page":"API reference","title":"DFTK.Smearing.occupation_derivative","text":"Derivative of the occupation function, approximation to minus the delta function.\n\n\n\n\n\n","category":"method"},{"location":"api/#DFTK.Smearing.occupation_divided_difference-Tuple{DFTK.Smearing.SmearingFunction, Any, Any, Any, Any}","page":"API reference","title":"DFTK.Smearing.occupation_divided_difference","text":"(f(x) - f(y))/(x - y), computed stably in the case where x and y are close\n\n\n\n\n\n","category":"method"},{"location":"examples/supercells/","page":"Creating and modelling metallic supercells","title":"Creating and modelling metallic supercells","text":"EditURL = \"https://github.com/JuliaMolSim/DFTK.jl/blob/master/examples/supercells.jl\"","category":"page"},{"location":"examples/supercells/#Creating-and-modelling-metallic-supercells","page":"Creating and modelling metallic supercells","title":"Creating and modelling metallic supercells","text":"","category":"section"},{"location":"examples/supercells/","page":"Creating and modelling metallic supercells","title":"Creating and modelling metallic supercells","text":"(Image: ) (Image: )","category":"page"},{"location":"examples/supercells/","page":"Creating and modelling metallic supercells","title":"Creating and modelling metallic supercells","text":"In this section we will be concerned with modelling supercells of aluminium. When dealing with periodic problems there is no unique definition of the lattice: Clearly any duplication of the lattice along an axis is also a valid repetitive unit to describe exactly the same system. This is exactly what a supercell is: An n-fold repetition along one of the axes of the original lattice.","category":"page"},{"location":"examples/supercells/","page":"Creating and modelling metallic supercells","title":"Creating and modelling metallic supercells","text":"The following code achieves this for aluminium:","category":"page"},{"location":"examples/supercells/","page":"Creating and modelling metallic supercells","title":"Creating and modelling metallic supercells","text":"using DFTK\nusing LinearAlgebra\nusing ASEconvert\n\nfunction aluminium_setup(repeat=1; Ecut=7.0, kgrid=[2, 2, 2])\n a = 7.65339\n lattice = a * Matrix(I, 3, 3)\n Al = ElementPsp(:Al, psp=load_psp(\"hgh/lda/al-q3\"))\n atoms = [Al, Al, Al, Al]\n positions = [[0.0, 0.0, 0.0], [0.0, 0.5, 0.5], [0.5, 0.0, 0.5], [0.5, 0.5, 0.0]]\n unit_cell = periodic_system(lattice, atoms, positions)\n\n # Make supercell in ASE:\n # We convert our lattice to the conventions used in ASE, make the supercell\n # and then convert back ...\n supercell_ase = convert_ase(unit_cell) * pytuple((repeat, 1, 1))\n supercell = pyconvert(AbstractSystem, supercell_ase)\n\n # Unfortunately right now the conversion to ASE drops the pseudopotential information,\n # so we need to reattach it:\n supercell = attach_psp(supercell, Al=\"hgh/lda/al-q3\")\n\n # Construct an LDA model and discretise\n # Note: We disable symmetries explicitly here. Otherwise the problem sizes\n # we are able to run on the CI are too simple to observe the numerical\n # instabilities we want to trigger here.\n model = model_LDA(supercell; temperature=1e-3, symmetries=false)\n PlaneWaveBasis(model; Ecut, kgrid)\nend;\nnothing #hide","category":"page"},{"location":"examples/supercells/","page":"Creating and modelling metallic supercells","title":"Creating and modelling metallic supercells","text":"As part of the code we are using a routine inside the ASE, the atomistic simulation environment for creating the supercell and make use of the two-way interoperability of DFTK and ASE. For more details on this aspect see the documentation on Input and output formats.","category":"page"},{"location":"examples/supercells/","page":"Creating and modelling metallic supercells","title":"Creating and modelling metallic supercells","text":"Write an example supercell structure to a file to plot it:","category":"page"},{"location":"examples/supercells/","page":"Creating and modelling metallic supercells","title":"Creating and modelling metallic supercells","text":"setup = aluminium_setup(5)\nconvert_ase(periodic_system(setup.model)).write(\"al_supercell.png\")","category":"page"},{"location":"examples/supercells/","page":"Creating and modelling metallic supercells","title":"Creating and modelling metallic supercells","text":"<img src=\"../al_supercell.png\" width=500 height=500 />","category":"page"},{"location":"examples/supercells/","page":"Creating and modelling metallic supercells","title":"Creating and modelling metallic supercells","text":"As we will see in this notebook the modelling of a system generally becomes harder if the system becomes larger.","category":"page"},{"location":"examples/supercells/","page":"Creating and modelling metallic supercells","title":"Creating and modelling metallic supercells","text":"This sounds like a trivial statement as per se the cost per SCF step increases as the system (and thus N) gets larger.\nBut there is more to it: If one is not careful also the number of SCF iterations increases as the system gets larger.\nThe aim of a proper computational treatment of such supercells is therefore to ensure that the number of SCF iterations remains constant when the system size increases.","category":"page"},{"location":"examples/supercells/","page":"Creating and modelling metallic supercells","title":"Creating and modelling metallic supercells","text":"For achieving the latter DFTK by default employs the LdosMixing preconditioner [HL2021] during the SCF iterations. This mixing approach is completely parameter free, but still automatically adapts to the treated system in order to efficiently prevent charge sloshing. As a result, modelling aluminium slabs indeed takes roughly the same number of SCF iterations irrespective of the supercell size:","category":"page"},{"location":"examples/supercells/","page":"Creating and modelling metallic supercells","title":"Creating and modelling metallic supercells","text":"[HL2021]: ","category":"page"},{"location":"examples/supercells/","page":"Creating and modelling metallic supercells","title":"Creating and modelling metallic supercells","text":"M. F. Herbst and A. Levitt. Black-box inhomogeneous preconditioning for self-consistent field iterations in density functional theory. J. Phys. Cond. Matt 33 085503 (2021). ArXiv:2009.01665","category":"page"},{"location":"examples/supercells/","page":"Creating and modelling metallic supercells","title":"Creating and modelling metallic supercells","text":"self_consistent_field(aluminium_setup(1); tol=1e-4);\nnothing #hide","category":"page"},{"location":"examples/supercells/","page":"Creating and modelling metallic supercells","title":"Creating and modelling metallic supercells","text":"self_consistent_field(aluminium_setup(2); tol=1e-4);\nnothing #hide","category":"page"},{"location":"examples/supercells/","page":"Creating and modelling metallic supercells","title":"Creating and modelling metallic supercells","text":"self_consistent_field(aluminium_setup(4); tol=1e-4);\nnothing #hide","category":"page"},{"location":"examples/supercells/","page":"Creating and modelling metallic supercells","title":"Creating and modelling metallic supercells","text":"When switching off explicitly the LdosMixing, by selecting mixing=SimpleMixing(), the performance of number of required SCF steps starts to increase as we increase the size of the modelled problem:","category":"page"},{"location":"examples/supercells/","page":"Creating and modelling metallic supercells","title":"Creating and modelling metallic supercells","text":"self_consistent_field(aluminium_setup(1); tol=1e-4, mixing=SimpleMixing());\nnothing #hide","category":"page"},{"location":"examples/supercells/","page":"Creating and modelling metallic supercells","title":"Creating and modelling metallic supercells","text":"self_consistent_field(aluminium_setup(4); tol=1e-4, mixing=SimpleMixing());\nnothing #hide","category":"page"},{"location":"examples/supercells/","page":"Creating and modelling metallic supercells","title":"Creating and modelling metallic supercells","text":"For completion let us note that the more traditional mixing=KerkerMixing() approach would also help in this particular setting to obtain a constant number of SCF iterations for an increasing system size (try it!). In contrast to LdosMixing, however, KerkerMixing is only suitable to model bulk metallic system (like the case we are considering here). When modelling metallic surfaces or mixtures of metals and insulators, KerkerMixing fails, while LdosMixing still works well. See the Modelling a gallium arsenide surface example or [HL2021] for details. Due to the general applicability of LdosMixing this method is the default mixing approach in DFTK.","category":"page"},{"location":"developer/symmetries/#Crystal-symmetries","page":"Crystal symmetries","title":"Crystal symmetries","text":"","category":"section"},{"location":"developer/symmetries/#Theory","page":"Crystal symmetries","title":"Theory","text":"","category":"section"},{"location":"developer/symmetries/","page":"Crystal symmetries","title":"Crystal symmetries","text":"In this discussion we will only describe the situation for a monoatomic crystal mathcal C subset mathbb R^3, the extension being easy. A symmetry of the crystal is an orthogonal matrix W and a real-space vector w such that","category":"page"},{"location":"developer/symmetries/","page":"Crystal symmetries","title":"Crystal symmetries","text":"W mathcalC + w = mathcalC","category":"page"},{"location":"developer/symmetries/","page":"Crystal symmetries","title":"Crystal symmetries","text":"The symmetries where W = 1 and w is a lattice vector are always assumed and ignored in the following.","category":"page"},{"location":"developer/symmetries/","page":"Crystal symmetries","title":"Crystal symmetries","text":"We can define a corresponding unitary operator U on L^2(mathbb R^3) with action","category":"page"},{"location":"developer/symmetries/","page":"Crystal symmetries","title":"Crystal symmetries","text":" (Uu)(x) = uleft( W x + w right)","category":"page"},{"location":"developer/symmetries/","page":"Crystal symmetries","title":"Crystal symmetries","text":"We assume that the atomic potentials are radial and that any self-consistent potential also respects this symmetry, so that U commutes with the Hamiltonian.","category":"page"},{"location":"developer/symmetries/","page":"Crystal symmetries","title":"Crystal symmetries","text":"This operator acts on a plane-wave as","category":"page"},{"location":"developer/symmetries/","page":"Crystal symmetries","title":"Crystal symmetries","text":"beginaligned\n(U e^iqcdot x) (x) = e^iq cdot w e^i (W^T q) x\n= e^- i(S q) cdot tau e^i (S q) cdot x\nendaligned","category":"page"},{"location":"developer/symmetries/","page":"Crystal symmetries","title":"Crystal symmetries","text":"where we set","category":"page"},{"location":"developer/symmetries/","page":"Crystal symmetries","title":"Crystal symmetries","text":"beginaligned\nS = W^T\ntau = -W^-1w\nendaligned","category":"page"},{"location":"developer/symmetries/","page":"Crystal symmetries","title":"Crystal symmetries","text":"It follows that the Fourier transform satisfies","category":"page"},{"location":"developer/symmetries/","page":"Crystal symmetries","title":"Crystal symmetries","text":"widehatUu(q) = e^- iq cdot tau widehat u(S^-1 q)","category":"page"},{"location":"developer/symmetries/","page":"Crystal symmetries","title":"Crystal symmetries","text":"(all of these equations being also valid in reduced coordinates). In particular, if e^ikcdot x u_k(x) is an eigenfunction, then by decomposing u_k over plane-waves e^i G cdot x one can see that e^i(S^T k) cdot x (U u_k)(x) is also an eigenfunction: we can choose","category":"page"},{"location":"developer/symmetries/","page":"Crystal symmetries","title":"Crystal symmetries","text":"u_Sk = U u_k","category":"page"},{"location":"developer/symmetries/","page":"Crystal symmetries","title":"Crystal symmetries","text":"This is used to reduce the computations needed. For a uniform sampling of the Brillouin zone (the reducible k-points), one can find a reduced set of k-points (the irreducible k-points) such that the eigenvectors at the reducible k-points can be deduced from those at the irreducible k-points.","category":"page"},{"location":"developer/symmetries/#Symmetrization","page":"Crystal symmetries","title":"Symmetrization","text":"","category":"section"},{"location":"developer/symmetries/","page":"Crystal symmetries","title":"Crystal symmetries","text":"Quantities that are calculated by summing over the reducible k points can be calculated by first summing over the irreducible k points and then symmetrizing. Let mathcalK_textreducible denote the reducible k-points sampling the Brillouin zone, mathcalS be the group of all crystal symmetries that leave this BZ mesh invariant (mathcalSmathcalK_textreducible = mathcalK_textreducible) and mathcalK be the irreducible k-points obtained from mathcalK_textreducible using the symmetries mathcalS. Clearly","category":"page"},{"location":"developer/symmetries/","page":"Crystal symmetries","title":"Crystal symmetries","text":"mathcalK_textred = Sk S in mathcalS k in mathcalK","category":"page"},{"location":"developer/symmetries/","page":"Crystal symmetries","title":"Crystal symmetries","text":"Let Q be a k-dependent quantity to sum (for instance, energies, densities, forces, etc). Q transforms in a particular way under symmetries: Q(Sk) = S(Q(k)) where the (linear) action of S on Q depends on the particular Q.","category":"page"},{"location":"developer/symmetries/","page":"Crystal symmetries","title":"Crystal symmetries","text":"beginaligned\nsum_k in mathcalK_textred Q(k)\n= sum_k in mathcalK sum_S text with Sk in mathcalK_textred S(Q(k)) \n= sum_k in mathcalK frac1N_mathcalSk sum_S in mathcalS S(Q(k))\n= frac1N_mathcalS sum_S in mathcalS\n left(sum_k in mathcalK fracN_mathcalSN_mathcalSk Q(k) right)\nendaligned","category":"page"},{"location":"developer/symmetries/","page":"Crystal symmetries","title":"Crystal symmetries","text":"Here, N_mathcalS = mathcalS is the total number of symmetry operations and N_mathcalSk denotes the number of operations such that leave k invariant. The latter operations form a subgroup of the group of all symmetry operations, sometimes called the small/little group of k. The factor fracN_mathcalSN_Sk, also equal to the ratio of number of reducible points encoded by this particular irreducible k to the total number of reducible points, determines the weight of each irreducible k point.","category":"page"},{"location":"developer/symmetries/#Example","page":"Crystal symmetries","title":"Example","text":"","category":"section"},{"location":"developer/symmetries/","page":"Crystal symmetries","title":"Crystal symmetries","text":"using DFTK\na = 10.26\nlattice = a / 2 * [[0 1 1.];\n [1 0 1.];\n [1 1 0.]]\nSi = ElementPsp(:Si, psp=load_psp(\"hgh/lda/Si-q4\"))\natoms = [Si, Si]\npositions = [ones(3)/8, -ones(3)/8]\nEcut = 5\nkgrid = [4, 4, 4]","category":"page"},{"location":"developer/symmetries/","page":"Crystal symmetries","title":"Crystal symmetries","text":"Let us demonstrate this in practice. We consider silicon, setup appropriately in the lattice, atoms and positions objects as in Tutorial and to reach a fast execution, we take a small Ecut of 5 and a [4, 4, 4] Monkhorst-Pack grid. First we perform the DFT calculation disabling symmetry handling","category":"page"},{"location":"developer/symmetries/","page":"Crystal symmetries","title":"Crystal symmetries","text":"model_nosym = model_LDA(lattice, atoms, positions; symmetries=false)\nbasis_nosym = PlaneWaveBasis(model_nosym; Ecut, kgrid)\nscfres_nosym = @time self_consistent_field(basis_nosym, tol=1e-6)\nnothing # hide","category":"page"},{"location":"developer/symmetries/","page":"Crystal symmetries","title":"Crystal symmetries","text":"and then redo it using symmetry (the default):","category":"page"},{"location":"developer/symmetries/","page":"Crystal symmetries","title":"Crystal symmetries","text":"model_sym = model_LDA(lattice, atoms, positions)\nbasis_sym = PlaneWaveBasis(model_sym; Ecut, kgrid)\nscfres_sym = @time self_consistent_field(basis_sym, tol=1e-6)\nnothing # hide","category":"page"},{"location":"developer/symmetries/","page":"Crystal symmetries","title":"Crystal symmetries","text":"Clearly both yield the same energy but the version employing symmetry is faster, since less k-points are explicitly treated:","category":"page"},{"location":"developer/symmetries/","page":"Crystal symmetries","title":"Crystal symmetries","text":"(length(basis_sym.kpoints), length(basis_nosym.kpoints))","category":"page"},{"location":"developer/symmetries/","page":"Crystal symmetries","title":"Crystal symmetries","text":"Both SCFs would even agree in the convergence history if exact diagonalization was used for the eigensolver in each step of both SCFs. But since DFTK adjusts this diagtol value adaptively during the SCF to increase performance, a slightly different history is obtained. Try adding the keyword argument determine_diagtol=(args...; kwargs...) -> 1e-8 in each SCF call to fix the diagonalization tolerance to be 1e-8 for all SCF steps, which will result in an almost identical convergence history.","category":"page"},{"location":"developer/symmetries/","page":"Crystal symmetries","title":"Crystal symmetries","text":"We can also explicitly verify both methods to yield the same density:","category":"page"},{"location":"developer/symmetries/","page":"Crystal symmetries","title":"Crystal symmetries","text":"using LinearAlgebra # hide\n(norm(scfres_sym.ρ - scfres_nosym.ρ),\n norm(values(scfres_sym.energies) .- values(scfres_nosym.energies)))","category":"page"},{"location":"developer/symmetries/","page":"Crystal symmetries","title":"Crystal symmetries","text":"The symmetries can be used to map reducible to irreducible points:","category":"page"},{"location":"developer/symmetries/","page":"Crystal symmetries","title":"Crystal symmetries","text":"ikpt_red = rand(1:length(basis_nosym.kpoints))\n# find a (non-unique) corresponding irreducible point in basis_nosym,\n# and the symmetry that relates them\nikpt_irred, symop = DFTK.unfold_mapping(basis_sym, basis_nosym.kpoints[ikpt_red])\n[basis_sym.kpoints[ikpt_irred].coordinate symop.S * basis_nosym.kpoints[ikpt_red].coordinate]","category":"page"},{"location":"developer/symmetries/","page":"Crystal symmetries","title":"Crystal symmetries","text":"The eigenvalues match also:","category":"page"},{"location":"developer/symmetries/","page":"Crystal symmetries","title":"Crystal symmetries","text":"[scfres_sym.eigenvalues[ikpt_irred] scfres_nosym.eigenvalues[ikpt_red]]","category":"page"},{"location":"examples/compare_solvers/","page":"Comparison of DFT solvers","title":"Comparison of DFT solvers","text":"EditURL = \"https://github.com/JuliaMolSim/DFTK.jl/blob/master/examples/compare_solvers.jl\"","category":"page"},{"location":"examples/compare_solvers/#Comparison-of-DFT-solvers","page":"Comparison of DFT solvers","title":"Comparison of DFT solvers","text":"","category":"section"},{"location":"examples/compare_solvers/","page":"Comparison of DFT solvers","title":"Comparison of DFT solvers","text":"(Image: ) (Image: )","category":"page"},{"location":"examples/compare_solvers/","page":"Comparison of DFT solvers","title":"Comparison of DFT solvers","text":"We compare four different approaches for solving the DFT minimisation problem, namely a density-based SCF, a potential-based SCF, direct minimisation and Newton.","category":"page"},{"location":"examples/compare_solvers/","page":"Comparison of DFT solvers","title":"Comparison of DFT solvers","text":"First we setup our problem","category":"page"},{"location":"examples/compare_solvers/","page":"Comparison of DFT solvers","title":"Comparison of DFT solvers","text":"using DFTK\nusing LinearAlgebra\n\na = 10.26 # Silicon lattice constant in Bohr\nlattice = a / 2 * [[0 1 1.];\n [1 0 1.];\n [1 1 0.]]\nSi = ElementPsp(:Si, psp=load_psp(\"hgh/lda/Si-q4\"))\natoms = [Si, Si]\npositions = [ones(3)/8, -ones(3)/8]\n\nmodel = model_LDA(lattice, atoms, positions)\nbasis = PlaneWaveBasis(model; Ecut=5, kgrid=[3, 3, 3])\n\n# Convergence we desire in the density\ntol = 1e-6","category":"page"},{"location":"examples/compare_solvers/#Density-based-self-consistent-field","page":"Comparison of DFT solvers","title":"Density-based self-consistent field","text":"","category":"section"},{"location":"examples/compare_solvers/","page":"Comparison of DFT solvers","title":"Comparison of DFT solvers","text":"scfres_scf = self_consistent_field(basis; tol);\nnothing #hide","category":"page"},{"location":"examples/compare_solvers/#Potential-based-SCF","page":"Comparison of DFT solvers","title":"Potential-based SCF","text":"","category":"section"},{"location":"examples/compare_solvers/","page":"Comparison of DFT solvers","title":"Comparison of DFT solvers","text":"scfres_scfv = DFTK.scf_potential_mixing(basis; tol);\nnothing #hide","category":"page"},{"location":"examples/compare_solvers/#Direct-minimization","page":"Comparison of DFT solvers","title":"Direct minimization","text":"","category":"section"},{"location":"examples/compare_solvers/","page":"Comparison of DFT solvers","title":"Comparison of DFT solvers","text":"Note: Unlike the other algorithms, tolerance for this one is in the energy, thus we square the density tolerance value to be roughly equivalent.","category":"page"},{"location":"examples/compare_solvers/","page":"Comparison of DFT solvers","title":"Comparison of DFT solvers","text":"scfres_dm = direct_minimization(basis; tol=tol^2);\nnothing #hide","category":"page"},{"location":"examples/compare_solvers/#Newton-algorithm","page":"Comparison of DFT solvers","title":"Newton algorithm","text":"","category":"section"},{"location":"examples/compare_solvers/","page":"Comparison of DFT solvers","title":"Comparison of DFT solvers","text":"Start not too far from the solution to ensure convergence: We run first a very crude SCF to get close and then switch to Newton.","category":"page"},{"location":"examples/compare_solvers/","page":"Comparison of DFT solvers","title":"Comparison of DFT solvers","text":"scfres_start = self_consistent_field(basis; tol=0.5);\nnothing #hide","category":"page"},{"location":"examples/compare_solvers/","page":"Comparison of DFT solvers","title":"Comparison of DFT solvers","text":"Remove the virtual orbitals (which Newton cannot treat yet)","category":"page"},{"location":"examples/compare_solvers/","page":"Comparison of DFT solvers","title":"Comparison of DFT solvers","text":"ψ = DFTK.select_occupied_orbitals(basis, scfres_start.ψ, scfres_start.occupation).ψ\nscfres_newton = newton(basis, ψ; tol);\nnothing #hide","category":"page"},{"location":"examples/compare_solvers/#Comparison-of-results","page":"Comparison of DFT solvers","title":"Comparison of results","text":"","category":"section"},{"location":"examples/compare_solvers/","page":"Comparison of DFT solvers","title":"Comparison of DFT solvers","text":"println(\"|ρ_newton - ρ_scf| = \", norm(scfres_newton.ρ - scfres_scf.ρ))\nprintln(\"|ρ_newton - ρ_scfv| = \", norm(scfres_newton.ρ - scfres_scfv.ρ))\nprintln(\"|ρ_newton - ρ_dm| = \", norm(scfres_newton.ρ - scfres_dm.ρ))","category":"page"},{"location":"examples/forwarddiff/","page":"Polarizability using automatic differentiation","title":"Polarizability using automatic differentiation","text":"EditURL = \"https://github.com/JuliaMolSim/DFTK.jl/blob/master/examples/forwarddiff.jl\"","category":"page"},{"location":"examples/forwarddiff/#Polarizability-using-automatic-differentiation","page":"Polarizability using automatic differentiation","title":"Polarizability using automatic differentiation","text":"","category":"section"},{"location":"examples/forwarddiff/","page":"Polarizability using automatic differentiation","title":"Polarizability using automatic differentiation","text":"(Image: ) (Image: )","category":"page"},{"location":"examples/forwarddiff/","page":"Polarizability using automatic differentiation","title":"Polarizability using automatic differentiation","text":"Simple example for computing properties using (forward-mode) automatic differentiation. For a more classical approach and more details about computing polarizabilities, see Polarizability by linear response.","category":"page"},{"location":"examples/forwarddiff/","page":"Polarizability using automatic differentiation","title":"Polarizability using automatic differentiation","text":"using DFTK\nusing LinearAlgebra\nusing ForwardDiff\n\n# Construct PlaneWaveBasis given a particular electric field strength\n# Again we take the example of a Helium atom.\nfunction make_basis(ε::T; a=10., Ecut=30) where {T}\n lattice=T(a) * I(3) # lattice is a cube of ``a`` Bohrs\n # Helium at the center of the box\n atoms = [ElementPsp(:He, psp=load_psp(\"hgh/lda/He-q2\"))]\n positions = [[1/2, 1/2, 1/2]]\n\n model = model_DFT(lattice, atoms, positions, [:lda_x, :lda_c_vwn];\n extra_terms=[ExternalFromReal(r -> -ε * (r[1] - a/2))],\n symmetries=false)\n PlaneWaveBasis(model; Ecut, kgrid=[1, 1, 1]) # No k-point sampling on isolated system\nend\n\n# dipole moment of a given density (assuming the current geometry)\nfunction dipole(basis, ρ)\n @assert isdiag(basis.model.lattice)\n a = basis.model.lattice[1, 1]\n rr = [a * (r[1] - 1/2) for r in r_vectors(basis)]\n sum(rr .* ρ) * basis.dvol\nend\n\n# Function to compute the dipole for a given field strength\nfunction compute_dipole(ε; tol=1e-8, kwargs...)\n scfres = self_consistent_field(make_basis(ε; kwargs...); tol)\n dipole(scfres.basis, scfres.ρ)\nend;\nnothing #hide","category":"page"},{"location":"examples/forwarddiff/","page":"Polarizability using automatic differentiation","title":"Polarizability using automatic differentiation","text":"With this in place we can compute the polarizability from finite differences (just like in the previous example):","category":"page"},{"location":"examples/forwarddiff/","page":"Polarizability using automatic differentiation","title":"Polarizability using automatic differentiation","text":"polarizability_fd = let\n ε = 0.01\n (compute_dipole(ε) - compute_dipole(0.0)) / ε\nend","category":"page"},{"location":"examples/forwarddiff/","page":"Polarizability using automatic differentiation","title":"Polarizability using automatic differentiation","text":"We do the same thing using automatic differentiation. Under the hood this uses custom rules to implicitly differentiate through the self-consistent field fixed-point problem.","category":"page"},{"location":"examples/forwarddiff/","page":"Polarizability using automatic differentiation","title":"Polarizability using automatic differentiation","text":"polarizability = ForwardDiff.derivative(compute_dipole, 0.0)\nprintln()\nprintln(\"Polarizability via ForwardDiff: $polarizability\")\nprintln(\"Polarizability via finite difference: $polarizability_fd\")","category":"page"},{"location":"guide/tutorial/","page":"Tutorial","title":"Tutorial","text":"EditURL = \"https://github.com/JuliaMolSim/DFTK.jl/blob/master/docs/src/guide/tutorial.jl\"","category":"page"},{"location":"guide/tutorial/#Tutorial","page":"Tutorial","title":"Tutorial","text":"","category":"section"},{"location":"guide/tutorial/","page":"Tutorial","title":"Tutorial","text":"(Image: ) (Image: )","category":"page"},{"location":"guide/tutorial/","page":"Tutorial","title":"Tutorial","text":"This document provides an overview of the structure of the code and how to access basic information about calculations. Basic familiarity with the concepts of plane-wave density functional theory is assumed throughout. Feel free to take a look at the Periodic problems or the Introductory resources chapters for some introductory material on the topic.","category":"page"},{"location":"guide/tutorial/","page":"Tutorial","title":"Tutorial","text":"note: Convergence parameters in the documentation\nWe use rough parameters in order to be able to automatically generate this documentation very quickly. Therefore results are far from converged. Tighter thresholds and larger grids should be used for more realistic results.","category":"page"},{"location":"guide/tutorial/","page":"Tutorial","title":"Tutorial","text":"For our discussion we will use the classic example of computing the LDA ground state of the silicon crystal. Performing such a calculation roughly proceeds in three steps.","category":"page"},{"location":"guide/tutorial/","page":"Tutorial","title":"Tutorial","text":"using DFTK\nusing Plots\nusing Unitful\nusing UnitfulAtomic\n\n# 1. Define lattice and atomic positions\na = 5.431u\"angstrom\" # Silicon lattice constant\nlattice = a / 2 * [[0 1 1.]; # Silicon lattice vectors\n [1 0 1.]; # specified column by column\n [1 1 0.]];\nnothing #hide","category":"page"},{"location":"guide/tutorial/","page":"Tutorial","title":"Tutorial","text":"By default, all numbers passed as arguments are assumed to be in atomic units. Quantities such as temperature, energy cutoffs, lattice vectors, and the k-point grid spacing can optionally be annotated with Unitful units, which are automatically converted to the atomic units used internally. For more details, see the Unitful package documentation and the UnitfulAtomic.jl package.","category":"page"},{"location":"guide/tutorial/","page":"Tutorial","title":"Tutorial","text":"# Load HGH pseudopotential for Silicon\nSi = ElementPsp(:Si, psp=load_psp(\"hgh/lda/Si-q4\"))\n\n# Specify type and positions of atoms\natoms = [Si, Si]\npositions = [ones(3)/8, -ones(3)/8]\n\n# 2. Select model and basis\nmodel = model_LDA(lattice, atoms, positions)\nkgrid = [4, 4, 4] # k-point grid (Regular Monkhorst-Pack grid)\nEcut = 7 # kinetic energy cutoff\n# Ecut = 190.5u\"eV\" # Could also use eV or other energy-compatible units\nbasis = PlaneWaveBasis(model; Ecut, kgrid)\n# Note the implicit passing of keyword arguments here:\n# this is equivalent to PlaneWaveBasis(model; Ecut=Ecut, kgrid=kgrid)\n\n# 3. Run the SCF procedure to obtain the ground state\nscfres = self_consistent_field(basis, tol=1e-5);\nnothing #hide","category":"page"},{"location":"guide/tutorial/","page":"Tutorial","title":"Tutorial","text":"That's it! Now you can get various quantities from the result of the SCF. For instance, the different components of the energy:","category":"page"},{"location":"guide/tutorial/","page":"Tutorial","title":"Tutorial","text":"scfres.energies","category":"page"},{"location":"guide/tutorial/","page":"Tutorial","title":"Tutorial","text":"Eigenvalues:","category":"page"},{"location":"guide/tutorial/","page":"Tutorial","title":"Tutorial","text":"hcat(scfres.eigenvalues...)","category":"page"},{"location":"guide/tutorial/","page":"Tutorial","title":"Tutorial","text":"eigenvalues is an array (indexed by k-points) of arrays (indexed by eigenvalue number). The \"splatting\" operation ... calls hcat with all the inner arrays as arguments, which collects them into a matrix.","category":"page"},{"location":"guide/tutorial/","page":"Tutorial","title":"Tutorial","text":"The resulting matrix is 7 (number of computed eigenvalues) by 8 (number of irreducible k-points). There are 7 eigenvalues per k-point because there are 4 occupied states in the system (4 valence electrons per silicon atom, two atoms per unit cell, and paired spins), and the eigensolver gives itself some breathing room by computing some extra states (see the bands argument to self_consistent_field as well as the AdaptiveBands documentation). There are only 8 k-points (instead of 4x4x4) because symmetry has been used to reduce the amount of computations to just the irreducible k-points (see Crystal symmetries for details).","category":"page"},{"location":"guide/tutorial/","page":"Tutorial","title":"Tutorial","text":"We can check the occupations ...","category":"page"},{"location":"guide/tutorial/","page":"Tutorial","title":"Tutorial","text":"hcat(scfres.occupation...)","category":"page"},{"location":"guide/tutorial/","page":"Tutorial","title":"Tutorial","text":"... and density, where we use that the density objects in DFTK are indexed as ρ[iσ, ix, iy, iz], i.e. first in the spin component and then in the 3-dimensional real-space grid.","category":"page"},{"location":"guide/tutorial/","page":"Tutorial","title":"Tutorial","text":"rvecs = collect(r_vectors(basis))[:, 1, 1] # slice along the x axis\nx = [r[1] for r in rvecs] # only keep the x coordinate\nplot(x, scfres.ρ[1, :, 1, 1], label=\"\", xlabel=\"x\", ylabel=\"ρ\", marker=2)","category":"page"},{"location":"guide/tutorial/","page":"Tutorial","title":"Tutorial","text":"We can also perform various postprocessing steps: for instance compute a band structure","category":"page"},{"location":"guide/tutorial/","page":"Tutorial","title":"Tutorial","text":"plot_bandstructure(scfres; kline_density=10)","category":"page"},{"location":"guide/tutorial/","page":"Tutorial","title":"Tutorial","text":"or get the cartesian forces (in Hartree / Bohr)","category":"page"},{"location":"guide/tutorial/","page":"Tutorial","title":"Tutorial","text":"compute_forces_cart(scfres)","category":"page"},{"location":"guide/tutorial/","page":"Tutorial","title":"Tutorial","text":"As expected, they are numerically zero in this highly symmetric configuration.","category":"page"},{"location":"examples/polarizability/","page":"Polarizability by linear response","title":"Polarizability by linear response","text":"EditURL = \"https://github.com/JuliaMolSim/DFTK.jl/blob/master/examples/polarizability.jl\"","category":"page"},{"location":"examples/polarizability/#Polarizability-by-linear-response","page":"Polarizability by linear response","title":"Polarizability by linear response","text":"","category":"section"},{"location":"examples/polarizability/","page":"Polarizability by linear response","title":"Polarizability by linear response","text":"(Image: ) (Image: )","category":"page"},{"location":"examples/polarizability/","page":"Polarizability by linear response","title":"Polarizability by linear response","text":"We compute the polarizability of a Helium atom. The polarizability is defined as the change in dipole moment","category":"page"},{"location":"examples/polarizability/","page":"Polarizability by linear response","title":"Polarizability by linear response","text":"μ = r ρ(r) dr","category":"page"},{"location":"examples/polarizability/","page":"Polarizability by linear response","title":"Polarizability by linear response","text":"with respect to a small uniform electric field E = -x.","category":"page"},{"location":"examples/polarizability/","page":"Polarizability by linear response","title":"Polarizability by linear response","text":"We compute this in two ways: first by finite differences (applying a finite electric field), then by linear response. Note that DFTK is not really adapted to isolated atoms because it uses periodic boundary conditions. Nevertheless we can simply embed the Helium atom in a large enough box (although this is computationally wasteful).","category":"page"},{"location":"examples/polarizability/","page":"Polarizability by linear response","title":"Polarizability by linear response","text":"As in other tests, this is not fully converged, convergence parameters were simply selected for fast execution on CI,","category":"page"},{"location":"examples/polarizability/","page":"Polarizability by linear response","title":"Polarizability by linear response","text":"using DFTK\nusing LinearAlgebra\n\na = 10.\nlattice = a * I(3) # cube of ``a`` bohrs\n# Helium at the center of the box\natoms = [ElementPsp(:He, psp=load_psp(\"hgh/lda/He-q2\"))]\npositions = [[1/2, 1/2, 1/2]]\n\n\nkgrid = [1, 1, 1] # no k-point sampling for an isolated system\nEcut = 30\ntol = 1e-8\n\n# dipole moment of a given density (assuming the current geometry)\nfunction dipole(basis, ρ)\n rr = [(r[1] - a/2) for r in r_vectors_cart(basis)]\n sum(rr .* ρ) * basis.dvol\nend;\nnothing #hide","category":"page"},{"location":"examples/polarizability/#Using-finite-differences","page":"Polarizability by linear response","title":"Using finite differences","text":"","category":"section"},{"location":"examples/polarizability/","page":"Polarizability by linear response","title":"Polarizability by linear response","text":"We first compute the polarizability by finite differences. First compute the dipole moment at rest:","category":"page"},{"location":"examples/polarizability/","page":"Polarizability by linear response","title":"Polarizability by linear response","text":"model = model_LDA(lattice, atoms, positions; symmetries=false)\nbasis = PlaneWaveBasis(model; Ecut, kgrid)\nres = self_consistent_field(basis; tol)\nμref = dipole(basis, res.ρ)","category":"page"},{"location":"examples/polarizability/","page":"Polarizability by linear response","title":"Polarizability by linear response","text":"Then in a small uniform field:","category":"page"},{"location":"examples/polarizability/","page":"Polarizability by linear response","title":"Polarizability by linear response","text":"ε = .01\nmodel_ε = model_LDA(lattice, atoms, positions;\n extra_terms=[ExternalFromReal(r -> -ε * (r[1] - a/2))],\n symmetries=false)\nbasis_ε = PlaneWaveBasis(model_ε; Ecut, kgrid)\nres_ε = self_consistent_field(basis_ε; tol)\nμε = dipole(basis_ε, res_ε.ρ)","category":"page"},{"location":"examples/polarizability/","page":"Polarizability by linear response","title":"Polarizability by linear response","text":"polarizability = (με - μref) / ε\n\nprintln(\"Reference dipole: $μref\")\nprintln(\"Displaced dipole: $με\")\nprintln(\"Polarizability : $polarizability\")","category":"page"},{"location":"examples/polarizability/","page":"Polarizability by linear response","title":"Polarizability by linear response","text":"The result on more converged grids is very close to published results. For example DOI 10.1039/C8CP03569E quotes 1.65 with LSDA and 1.38 with CCSD(T).","category":"page"},{"location":"examples/polarizability/#Using-linear-response","page":"Polarizability by linear response","title":"Using linear response","text":"","category":"section"},{"location":"examples/polarizability/","page":"Polarizability by linear response","title":"Polarizability by linear response","text":"Now we use linear response to compute this analytically; we refer to standard textbooks for the formalism. In the following, χ_0 is the independent-particle polarizability, and K the Hartree-exchange-correlation kernel. We denote with δV_rm ext an external perturbing potential (like in this case the uniform electric field). Then:","category":"page"},{"location":"examples/polarizability/","page":"Polarizability by linear response","title":"Polarizability by linear response","text":"δρ = χ_0 δV = χ_0 (δV_rm ext + K δρ)","category":"page"},{"location":"examples/polarizability/","page":"Polarizability by linear response","title":"Polarizability by linear response","text":"which implies","category":"page"},{"location":"examples/polarizability/","page":"Polarizability by linear response","title":"Polarizability by linear response","text":"δρ = (1-χ_0 K)^-1 χ_0 δV_rm ext","category":"page"},{"location":"examples/polarizability/","page":"Polarizability by linear response","title":"Polarizability by linear response","text":"From this we identify the polarizability operator to be χ = (1-χ_0 K)^-1 χ_0. Numerically, we apply χ to δV = -x by solving a linear equation (the Dyson equation) iteratively.","category":"page"},{"location":"examples/polarizability/","page":"Polarizability by linear response","title":"Polarizability by linear response","text":"using KrylovKit\n\n# Apply ``(1- χ_0 K)``\nfunction dielectric_operator(δρ)\n δV = apply_kernel(basis, δρ; res.ρ)\n χ0δV = apply_χ0(res, δV)\n δρ - χ0δV\nend\n\n# `δVext` is the potential from a uniform field interacting with the dielectric dipole\n# of the density.\nδVext = [-(r[1] - a/2) for r in r_vectors_cart(basis)]\nδVext = cat(δVext; dims=4)\n\n# Apply ``χ_0`` once to get non-interacting dipole\nδρ_nointeract = apply_χ0(res, δVext)\n\n# Solve Dyson equation to get interacting dipole\nδρ = linsolve(dielectric_operator, δρ_nointeract, verbosity=3)[1]\n\nprintln(\"Non-interacting polarizability: $(dipole(basis, δρ_nointeract))\")\nprintln(\"Interacting polarizability: $(dipole(basis, δρ))\")","category":"page"},{"location":"examples/polarizability/","page":"Polarizability by linear response","title":"Polarizability by linear response","text":"As expected, the interacting polarizability matches the finite difference result. The non-interacting polarizability is higher.","category":"page"},{"location":"examples/input_output/","page":"Input and output formats","title":"Input and output formats","text":"EditURL = \"https://github.com/JuliaMolSim/DFTK.jl/blob/master/examples/input_output.jl\"","category":"page"},{"location":"examples/input_output/#Input-and-output-formats","page":"Input and output formats","title":"Input and output formats","text":"","category":"section"},{"location":"examples/input_output/","page":"Input and output formats","title":"Input and output formats","text":"(Image: ) (Image: )","category":"page"},{"location":"examples/input_output/","page":"Input and output formats","title":"Input and output formats","text":"This section provides an overview of the input and output formats supported by DFTK, usually via integration with a third-party library.","category":"page"},{"location":"examples/input_output/#Reading-/-writing-files-supported-by-AtomsIO","page":"Input and output formats","title":"Reading / writing files supported by AtomsIO","text":"","category":"section"},{"location":"examples/input_output/","page":"Input and output formats","title":"Input and output formats","text":"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 formatis is available in the AtomsIO documentation.","category":"page"},{"location":"examples/input_output/","page":"Input and output formats","title":"Input and output formats","text":"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.","category":"page"},{"location":"examples/input_output/","page":"Input and output formats","title":"Input and output formats","text":"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.","category":"page"},{"location":"examples/input_output/","page":"Input and output formats","title":"Input and output formats","text":"using AtomsIO\nsystem = load_system(\"Fe_afm.pwi\")","category":"page"},{"location":"examples/input_output/","page":"Input and output formats","title":"Input and output formats","text":"Next we attach pseudopotential information, since currently the parser is not yet capable to read this information from the file.","category":"page"},{"location":"examples/input_output/","page":"Input and output formats","title":"Input and output formats","text":"using DFTK\nsystem = attach_psp(system, Fe=\"hgh/pbe/fe-q16.hgh\")","category":"page"},{"location":"examples/input_output/","page":"Input and output formats","title":"Input and output formats","text":"Finally we make use of DFTK's AtomsBase integration to run the calculation.","category":"page"},{"location":"examples/input_output/","page":"Input and output formats","title":"Input and output formats","text":"model = model_LDA(system; temperature=0.01)\nbasis = PlaneWaveBasis(model; Ecut=10, kgrid=(2, 2, 2))\nρ0 = guess_density(basis, system)\nscfres = self_consistent_field(basis, tol=1e-3, ρ=ρ0, mixing=KerkerMixing());\nnothing #hide","category":"page"},{"location":"examples/input_output/#Writing-VTK-files-for-visualization","page":"Input and output formats","title":"Writing VTK files for visualization","text":"","category":"section"},{"location":"examples/input_output/","page":"Input and output formats","title":"Input and output formats","text":"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.","category":"page"},{"location":"examples/input_output/","page":"Input and output formats","title":"Input and output formats","text":"using WriteVTK\nsave_scfres(\"iron_afm.vts\", scfres; save_ψ=true);\nnothing #hide","category":"page"},{"location":"examples/input_output/","page":"Input and output formats","title":"Input and output formats","text":"This will save the iron calculation above into the file iron_afm.vts, using save_ψ=true to also include the KS orbitals.","category":"page"},{"location":"examples/input_output/#Writing-and-reading-JLD2-files","page":"Input and output formats","title":"Writing and reading JLD2 files","text":"","category":"section"},{"location":"examples/input_output/","page":"Input and output formats","title":"Input and output formats","text":"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).","category":"page"},{"location":"examples/input_output/","page":"Input and output formats","title":"Input and output formats","text":"using JLD2\nsave_scfres(\"iron_afm.jld2\", scfres);\nnothing #hide","category":"page"},{"location":"examples/input_output/","page":"Input and output formats","title":"Input and output formats","text":"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.","category":"page"},{"location":"examples/input_output/","page":"Input and output formats","title":"Input and output formats","text":"(Cleanup files generated by this notebook.)","category":"page"},{"location":"examples/input_output/","page":"Input and output formats","title":"Input and output formats","text":"rm(\"iron_afm.vts\")\nrm(\"iron_afm.jld2\")","category":"page"},{"location":"guide/periodic_problems/","page":"Problems and plane-wave discretisations","title":"Problems and plane-wave discretisations","text":"EditURL = \"https://github.com/JuliaMolSim/DFTK.jl/blob/master/docs/src/guide/periodic_problems.jl\"","category":"page"},{"location":"guide/periodic_problems/#periodic-problems","page":"Problems and plane-wave discretisations","title":"Problems and plane-wave discretisations","text":"","category":"section"},{"location":"guide/periodic_problems/","page":"Problems and plane-wave discretisations","title":"Problems and plane-wave discretisations","text":"(Image: ) (Image: )","category":"page"},{"location":"guide/periodic_problems/","page":"Problems and plane-wave discretisations","title":"Problems and plane-wave discretisations","text":"In this example we want to show how DFTK can be used to solve simple one-dimensional periodic problems. Along the lines this notebook serves as a concise introduction into the underlying theory and jargon for solving periodic problems using plane-wave discretizations.","category":"page"},{"location":"guide/periodic_problems/#Periodicity-and-lattices","page":"Problems and plane-wave discretisations","title":"Periodicity and lattices","text":"","category":"section"},{"location":"guide/periodic_problems/","page":"Problems and plane-wave discretisations","title":"Problems and plane-wave discretisations","text":"A periodic problem is characterized by being invariant to certain translations. For example the sin function is periodic with periodicity 2π, i.e.","category":"page"},{"location":"guide/periodic_problems/","page":"Problems and plane-wave discretisations","title":"Problems and plane-wave discretisations","text":" sin(x) = sin(x + 2πm) quad m mathbbZ","category":"page"},{"location":"guide/periodic_problems/","page":"Problems and plane-wave discretisations","title":"Problems and plane-wave discretisations","text":"This is nothing else than saying that any translation by an integer multiple of 2π keeps the sin function invariant. More formally, one can use the translation operator T_2πm to write this as:","category":"page"},{"location":"guide/periodic_problems/","page":"Problems and plane-wave discretisations","title":"Problems and plane-wave discretisations","text":" T_2πm sin(x) = sin(x - 2πm) = sin(x)","category":"page"},{"location":"guide/periodic_problems/","page":"Problems and plane-wave discretisations","title":"Problems and plane-wave discretisations","text":"Whenever such periodicity exists one can exploit it to save computational work. Consider a problem in which we want to find a function f mathbbR mathbbR, but a priori the solution is known to be periodic with periodicity a. As a consequence of said periodicity it is sufficient to determine the values of f for all x from the interval -a2 a2) to uniquely define f on the full real axis. Naturally exploiting periodicity in a computational procedure thus greatly reduces the required amount of work.","category":"page"},{"location":"guide/periodic_problems/","page":"Problems and plane-wave discretisations","title":"Problems and plane-wave discretisations","text":"Let us introduce some jargon: The periodicity of our problem implies that we may define a lattice","category":"page"},{"location":"guide/periodic_problems/","page":"Problems and plane-wave discretisations","title":"Problems and plane-wave discretisations","text":" -3a/2 -a/2 +a/2 +3a/2\n ... |---------|---------|---------| ...\n a a a","category":"page"},{"location":"guide/periodic_problems/","page":"Problems and plane-wave discretisations","title":"Problems and plane-wave discretisations","text":"with lattice constant a. Each cell of the lattice is an identical periodic image of any of its neighbors. For finding f it is thus sufficient to consider only the problem inside a unit cell -a2 a2) (this is the convention used by DFTK, but this is arbitrary, and for instance 0a) would have worked just as well).","category":"page"},{"location":"guide/periodic_problems/#Periodic-operators-and-the-Bloch-transform","page":"Problems and plane-wave discretisations","title":"Periodic operators and the Bloch transform","text":"","category":"section"},{"location":"guide/periodic_problems/","page":"Problems and plane-wave discretisations","title":"Problems and plane-wave discretisations","text":"Not only functions, but also operators can feature periodicity. Consider for example the free-electron Hamiltonian","category":"page"},{"location":"guide/periodic_problems/","page":"Problems and plane-wave discretisations","title":"Problems and plane-wave discretisations","text":" H = -frac12 Δ","category":"page"},{"location":"guide/periodic_problems/","page":"Problems and plane-wave discretisations","title":"Problems and plane-wave discretisations","text":"In free-electron model (which gives rise to this Hamiltonian) electron motion is only by their own kinetic energy. As this model features no potential which could make one point in space more preferred than another, we would expect this model to be periodic. If an operator is periodic with respect to a lattice such as the one defined above, then it commutes with all lattice translations. For the free-electron case H one can easily show exactly that, i.e.","category":"page"},{"location":"guide/periodic_problems/","page":"Problems and plane-wave discretisations","title":"Problems and plane-wave discretisations","text":" T_ma H = H T_ma quad m mathbbZ","category":"page"},{"location":"guide/periodic_problems/","page":"Problems and plane-wave discretisations","title":"Problems and plane-wave discretisations","text":"We note in passing that the free-electron model is actually very special in the sense that the choice of a is completely arbitrary here. In other words H is periodic with respect to any translation. In general, however, periodicity is only attained with respect to a finite number of translations a and we will take this viewpoint here.","category":"page"},{"location":"guide/periodic_problems/","page":"Problems and plane-wave discretisations","title":"Problems and plane-wave discretisations","text":"Bloch's theorem now tells us that for periodic operators, the solutions to the eigenproblem","category":"page"},{"location":"guide/periodic_problems/","page":"Problems and plane-wave discretisations","title":"Problems and plane-wave discretisations","text":" H ψ_kn = ε_kn ψ_kn","category":"page"},{"location":"guide/periodic_problems/","page":"Problems and plane-wave discretisations","title":"Problems and plane-wave discretisations","text":"satisfy a factorization","category":"page"},{"location":"guide/periodic_problems/","page":"Problems and plane-wave discretisations","title":"Problems and plane-wave discretisations","text":" ψ_kn(x) = e^i kx u_kn(x)","category":"page"},{"location":"guide/periodic_problems/","page":"Problems and plane-wave discretisations","title":"Problems and plane-wave discretisations","text":"into a plane wave e^i kx and a lattice-periodic function","category":"page"},{"location":"guide/periodic_problems/","page":"Problems and plane-wave discretisations","title":"Problems and plane-wave discretisations","text":" T_ma u_kn(x) = u_kn(x - ma) = u_kn(x) quad m mathbbZ","category":"page"},{"location":"guide/periodic_problems/","page":"Problems and plane-wave discretisations","title":"Problems and plane-wave discretisations","text":"In this n is a labeling integer index and k is a real number, whose details will be clarified in the next section. The index n is sometimes also called the band index and functions ψ_kn satisfying this factorization are also known as Bloch functions or Bloch states.","category":"page"},{"location":"guide/periodic_problems/","page":"Problems and plane-wave discretisations","title":"Problems and plane-wave discretisations","text":"Consider the application of 2H = -Δ = - fracd^2d x^2 to such a Bloch wave. First we notice for any function f","category":"page"},{"location":"guide/periodic_problems/","page":"Problems and plane-wave discretisations","title":"Problems and plane-wave discretisations","text":" -i left( e^i kx f right)\n = -ifracddx left( e^i kx f right)\n = k e^i kx f + e^i kx (-i) f = e^i kx (-i + k) f","category":"page"},{"location":"guide/periodic_problems/","page":"Problems and plane-wave discretisations","title":"Problems and plane-wave discretisations","text":"Using this result twice one shows that applying -Δ yields","category":"page"},{"location":"guide/periodic_problems/","page":"Problems and plane-wave discretisations","title":"Problems and plane-wave discretisations","text":"beginaligned\n -Delta left(e^i kx u_kn(x)right)\n = -i left-i left(u_kn(x) e^i kx right) right \n = -i lefte^i kx (-i + k) u_kn(x) right \n = e^i kx (-i + k)^2 u_kn(x) \n = e^i kx 2H_k u_kn(x)\nendaligned","category":"page"},{"location":"guide/periodic_problems/","page":"Problems and plane-wave discretisations","title":"Problems and plane-wave discretisations","text":"where we defined","category":"page"},{"location":"guide/periodic_problems/","page":"Problems and plane-wave discretisations","title":"Problems and plane-wave discretisations","text":" H_k = frac12 (-i + k)^2","category":"page"},{"location":"guide/periodic_problems/","page":"Problems and plane-wave discretisations","title":"Problems and plane-wave discretisations","text":"The action of this operator on a function u_kn is given by","category":"page"},{"location":"guide/periodic_problems/","page":"Problems and plane-wave discretisations","title":"Problems and plane-wave discretisations","text":" H_k u_kn = e^-i kx H e^i kx u_kn","category":"page"},{"location":"guide/periodic_problems/","page":"Problems and plane-wave discretisations","title":"Problems and plane-wave discretisations","text":"which in particular implies that","category":"page"},{"location":"guide/periodic_problems/","page":"Problems and plane-wave discretisations","title":"Problems and plane-wave discretisations","text":" H_k u_kn = ε_kn u_kn quad quad H (e^i kx u_kn) = ε_kn (e^i kx u_kn)","category":"page"},{"location":"guide/periodic_problems/","page":"Problems and plane-wave discretisations","title":"Problems and plane-wave discretisations","text":"To seek the eigenpairs of H we may thus equivalently find the eigenpairs of all H_k. The point of this is that the eigenfunctions u_kn of H_k are periodic (unlike the eigenfunctions ψ_kn of H). In contrast to ψ_kn the functions u_kn can thus be fully represented considering the eigenproblem only on the unit cell.","category":"page"},{"location":"guide/periodic_problems/","page":"Problems and plane-wave discretisations","title":"Problems and plane-wave discretisations","text":"A detailed mathematical analysis shows that the transformation from H to the set of all H_k for a suitable set of values for k (details below) is actually a unitary transformation, the so-called Bloch transform. This transform brings the Hamiltonian into the symmetry-adapted basis for translational symmetry, which are exactly the Bloch functions. Similar to the case of choosing a symmetry-adapted basis for other kinds of symmetries (like the point group symmetry in molecules), the Bloch transform also makes the Hamiltonian H block-diagonal[1]:","category":"page"},{"location":"guide/periodic_problems/","page":"Problems and plane-wave discretisations","title":"Problems and plane-wave discretisations","text":" T_B H T_B^-1 left( beginarraycccc H_10 H_2H_30ddots endarray right)","category":"page"},{"location":"guide/periodic_problems/","page":"Problems and plane-wave discretisations","title":"Problems and plane-wave discretisations","text":"with each block H_k taking care of one value k. This block-diagonal structure under the basis of Bloch functions lets us completely describe the spectrum of H by looking only at the spectrum of all H_k blocks.","category":"page"},{"location":"guide/periodic_problems/","page":"Problems and plane-wave discretisations","title":"Problems and plane-wave discretisations","text":"[1]: Notice that block-diagonal is a bit an abuse of terms here, since the Hamiltonian is not a matrix but an operator and the number of blocks is infinite. The mathematically precise term is that the Bloch transform reveals the fibers of the Hamiltonian.","category":"page"},{"location":"guide/periodic_problems/#The-Brillouin-zone","page":"Problems and plane-wave discretisations","title":"The Brillouin zone","text":"","category":"section"},{"location":"guide/periodic_problems/","page":"Problems and plane-wave discretisations","title":"Problems and plane-wave discretisations","text":"We now consider the parameter k of the Hamiltonian blocks in detail.","category":"page"},{"location":"guide/periodic_problems/","page":"Problems and plane-wave discretisations","title":"Problems and plane-wave discretisations","text":"As discussed k is a real number. It turns out, however, that some of these kmathbbR give rise to operators related by unitary transformations (again due to translational symmetry).\nSince such operators have the same eigenspectrum, only one version needs to be considered.\nThe smallest subset from which k is chosen is the Brillouin zone (BZ).\nThe BZ is the unit cell of the reciprocal lattice, which may be constructed from the real-space lattice by a Fourier transform.\nIn our simple 1D case the reciprocal lattice is just\n ... |--------|--------|--------| ...\n 2π/a 2π/a 2π/a\ni.e. like the real-space lattice, but just with a different lattice constant b = 2π a.\nThe BZ in our example is thus B = -πa πa). The members of B are typically called k-points.","category":"page"},{"location":"guide/periodic_problems/#Discretization-and-plane-wave-basis-sets","page":"Problems and plane-wave discretisations","title":"Discretization and plane-wave basis sets","text":"","category":"section"},{"location":"guide/periodic_problems/","page":"Problems and plane-wave discretisations","title":"Problems and plane-wave discretisations","text":"With what we discussed so far the strategy to find all eigenpairs of a periodic Hamiltonian H thus reduces to finding the eigenpairs of all H_k with k B. This requires two discretisations:","category":"page"},{"location":"guide/periodic_problems/","page":"Problems and plane-wave discretisations","title":"Problems and plane-wave discretisations","text":"B is infinite (and not countable). To discretize we first only pick a finite number of k-points. Usually this k-point sampling is done by picking k-points along a regular grid inside the BZ, the k-grid.\nEach H_k is still an infinite-dimensional operator. Following a standard Ritz-Galerkin ansatz we project the operator into a finite basis and diagonalize the resulting matrix.","category":"page"},{"location":"guide/periodic_problems/","page":"Problems and plane-wave discretisations","title":"Problems and plane-wave discretisations","text":"For the second step multiple types of bases are used in practice (finite differences, finite elements, Gaussians, ...). In DFTK we currently support only plane-wave discretizations.","category":"page"},{"location":"guide/periodic_problems/","page":"Problems and plane-wave discretisations","title":"Problems and plane-wave discretisations","text":"For our 1D example normalized plane waves are defined as the functions","category":"page"},{"location":"guide/periodic_problems/","page":"Problems and plane-wave discretisations","title":"Problems and plane-wave discretisations","text":"e_G(x) = frace^i G xsqrta qquad G in bmathbbZ","category":"page"},{"location":"guide/periodic_problems/","page":"Problems and plane-wave discretisations","title":"Problems and plane-wave discretisations","text":"and typically one forms basis sets from these by specifying a kinetic energy cutoff E_textcut:","category":"page"},{"location":"guide/periodic_problems/","page":"Problems and plane-wave discretisations","title":"Problems and plane-wave discretisations","text":"left e_G big (G + k)^2 leq 2E_textcut right","category":"page"},{"location":"guide/periodic_problems/#Correspondence-of-theory-to-DFTK-code","page":"Problems and plane-wave discretisations","title":"Correspondence of theory to DFTK code","text":"","category":"section"},{"location":"guide/periodic_problems/","page":"Problems and plane-wave discretisations","title":"Problems and plane-wave discretisations","text":"Before solving a few example problems numerically in DFTK, a short overview of the correspondence of the introduced quantities to data structures inside DFTK.","category":"page"},{"location":"guide/periodic_problems/","page":"Problems and plane-wave discretisations","title":"Problems and plane-wave discretisations","text":"H is represented by a Hamiltonian object and variables for hamiltonians are usually called ham.\nH_k by a HamiltonianBlock and variables are hamk.\nψ_kn is usually just called ψ. u_kn is not stored (in favor of ψ_kn).\nε_kn is called eigenvalues.\nk-points are represented by Kpoint and respective variables called kpt.\nThe basis of plane waves is managed by PlaneWaveBasis and variables usually just called basis.","category":"page"},{"location":"guide/periodic_problems/#Solving-the-free-electron-Hamiltonian","page":"Problems and plane-wave discretisations","title":"Solving the free-electron Hamiltonian","text":"","category":"section"},{"location":"guide/periodic_problems/","page":"Problems and plane-wave discretisations","title":"Problems and plane-wave discretisations","text":"One typical approach to get physical insight into a Hamiltonian H is to plot a so-called band structure, that is the eigenvalues of H_k versus k. In DFTK we achieve this using the following steps:","category":"page"},{"location":"guide/periodic_problems/","page":"Problems and plane-wave discretisations","title":"Problems and plane-wave discretisations","text":"Step 1: Build the 1D lattice. DFTK is mostly tailored for 3D problems. Therefore quantities related to the problem space are have a fixed dimension 3. The convention is that for 1D / 2D problems the trailing entries are always zero and ignored in the computation. For the lattice we therefore construct a 3x3 matrix with only one entry.","category":"page"},{"location":"guide/periodic_problems/","page":"Problems and plane-wave discretisations","title":"Problems and plane-wave discretisations","text":"using DFTK\n\nlattice = zeros(3, 3)\nlattice[1, 1] = 20.;\nnothing #hide","category":"page"},{"location":"guide/periodic_problems/","page":"Problems and plane-wave discretisations","title":"Problems and plane-wave discretisations","text":"Step 2: Select a model. In this case we choose a free-electron model, which is the same as saying that there is only a Kinetic term (and no potential) in the model.","category":"page"},{"location":"guide/periodic_problems/","page":"Problems and plane-wave discretisations","title":"Problems and plane-wave discretisations","text":"model = Model(lattice; terms=[Kinetic()])","category":"page"},{"location":"guide/periodic_problems/","page":"Problems and plane-wave discretisations","title":"Problems and plane-wave discretisations","text":"Step 3: Define a plane-wave basis using this model and a cutoff E_textcut of 300 Hartree. The k-point grid is given as a regular grid in the BZ (a so-called Monkhorst-Pack grid). Here we select only one k-point (1x1x1), see the note below for some details on this choice.","category":"page"},{"location":"guide/periodic_problems/","page":"Problems and plane-wave discretisations","title":"Problems and plane-wave discretisations","text":"basis = PlaneWaveBasis(model; Ecut=300, kgrid=(1, 1, 1))","category":"page"},{"location":"guide/periodic_problems/","page":"Problems and plane-wave discretisations","title":"Problems and plane-wave discretisations","text":"Step 4: Plot the bands! Select a density of k-points for the k-grid to use for the bandstructure calculation, discretize the problem and diagonalize it. Afterwards plot the bands.","category":"page"},{"location":"guide/periodic_problems/","page":"Problems and plane-wave discretisations","title":"Problems and plane-wave discretisations","text":"using Unitful\nusing UnitfulAtomic\nusing Plots\n\nplot_bandstructure(basis; n_bands=6, kline_density=100)","category":"page"},{"location":"guide/periodic_problems/","page":"Problems and plane-wave discretisations","title":"Problems and plane-wave discretisations","text":"note: Selection of k-point grids in `PlaneWaveBasis` construction\nYou might wonder why we only selected a single k-point (clearly a very crude and inaccurate approximation). In this example the kgrid parameter specified in the construction of the PlaneWaveBasis is not actually used for plotting the bands. It is only used when solving more involved models like density-functional theory (DFT) where the Hamiltonian is non-linear. In these cases before plotting the bands the self-consistent field equations (SCF) need to be solved first. This is typically done on a different k-point grid than the grid used for the bands later on. In our case we don't need this extra step and therefore the kgrid value passed to PlaneWaveBasis is actually arbitrary.","category":"page"},{"location":"guide/periodic_problems/#Adding-potentials","page":"Problems and plane-wave discretisations","title":"Adding potentials","text":"","category":"section"},{"location":"guide/periodic_problems/","page":"Problems and plane-wave discretisations","title":"Problems and plane-wave discretisations","text":"So far so good. But free electrons are actually a little boring, so let's add a potential interacting with the electrons.","category":"page"},{"location":"guide/periodic_problems/","page":"Problems and plane-wave discretisations","title":"Problems and plane-wave discretisations","text":"The modified problem we will look at consists of diagonalizing\nH_k = frac12 (-i nabla + k)^2 + V\nfor all k in B with a periodic potential V interacting with the electrons.\nA number of \"standard\" potentials are readily implemented in DFTK and can be assembled using the terms kwarg of the model. This allows to seamlessly construct\ndensity-functial theory (DFT) models for treating electronic structures (see the Tutorial).\nGross-Pitaevskii models for bosonic systems (see Gross-Pitaevskii equation in one dimension)\neven some more unusual cases like anyonic models.","category":"page"},{"location":"guide/periodic_problems/","page":"Problems and plane-wave discretisations","title":"Problems and plane-wave discretisations","text":"We will use ElementGaussian, which is an analytic potential describing a Gaussian interaction with the electrons to DFTK. See Custom potential for how to create a custom potential.","category":"page"},{"location":"guide/periodic_problems/","page":"Problems and plane-wave discretisations","title":"Problems and plane-wave discretisations","text":"A single potential looks like:","category":"page"},{"location":"guide/periodic_problems/","page":"Problems and plane-wave discretisations","title":"Problems and plane-wave discretisations","text":"using Plots\nusing LinearAlgebra\nnucleus = ElementGaussian(0.3, 10.0)\nplot(r -> DFTK.local_potential_real(nucleus, norm(r)), xlims=(-50, 50))","category":"page"},{"location":"guide/periodic_problems/","page":"Problems and plane-wave discretisations","title":"Problems and plane-wave discretisations","text":"With this element at hand we can easily construct a setting where two potentials of this form are located at positions 20 and 80 inside the lattice 0 100:","category":"page"},{"location":"guide/periodic_problems/","page":"Problems and plane-wave discretisations","title":"Problems and plane-wave discretisations","text":"using LinearAlgebra\n\n# Define the 1D lattice [0, 100]\nlattice = diagm([100., 0, 0])\n\n# Place them at 20 and 80 in *fractional coordinates*,\n# that is 0.2 and 0.8, since the lattice is 100 wide.\nnucleus = ElementGaussian(0.3, 10.0)\natoms = [nucleus, nucleus]\npositions = [[0.2, 0, 0], [0.8, 0, 0]]\n\n# Assemble the model, discretize and build the Hamiltonian\nmodel = Model(lattice, atoms, positions; terms=[Kinetic(), AtomicLocal()])\nbasis = PlaneWaveBasis(model; Ecut=300, kgrid=(1, 1, 1));\nham = Hamiltonian(basis)\n\n# Extract the total potential term of the Hamiltonian and plot it\npotential = DFTK.total_local_potential(ham)[:, 1, 1]\nrvecs = collect(r_vectors_cart(basis))[:, 1, 1] # slice along the x axis\nx = [r[1] for r in rvecs] # only keep the x coordinate\nplot(x, potential, label=\"\", xlabel=\"x\", ylabel=\"V(x)\")","category":"page"},{"location":"guide/periodic_problems/","page":"Problems and plane-wave discretisations","title":"Problems and plane-wave discretisations","text":"This potential is the sum of two \"atomic\" potentials (the two \"Gaussian\" elements). Due to the periodic setting we are considering interactions naturally also occur across the unit cell boundary (i.e. wrapping from 100 over to 0). The required periodization of the atomic potential is automatically taken care, such that the potential is smooth across the cell boundary at 100/0.","category":"page"},{"location":"guide/periodic_problems/","page":"Problems and plane-wave discretisations","title":"Problems and plane-wave discretisations","text":"With this setup, let's look at the bands:","category":"page"},{"location":"guide/periodic_problems/","page":"Problems and plane-wave discretisations","title":"Problems and plane-wave discretisations","text":"using Unitful\nusing UnitfulAtomic\n\nplot_bandstructure(basis; n_bands=6, kline_density=500)","category":"page"},{"location":"guide/periodic_problems/","page":"Problems and plane-wave discretisations","title":"Problems and plane-wave discretisations","text":"The bands are noticeably different.","category":"page"},{"location":"guide/periodic_problems/","page":"Problems and plane-wave discretisations","title":"Problems and plane-wave discretisations","text":"The bands no longer overlap, meaning that the spectrum of H is no longer continuous but has gaps.\nThe two lowest bands are almost flat. This is because they represent two tightly bound and localized electrons inside the two Gaussians.\nThe higher the bands are in energy, the more free-electron-like they are. In other words the higher the kinetic energy of the electrons, the less they feel the effect of the two Gaussian potentials. As it turns out the curvature of the bands, (the degree to which they are free-electron-like) is highly related to the delocalization of electrons in these bands: The more curved the more delocalized. In some sense \"free electrons\" correspond to perfect delocalization.","category":"page"},{"location":"guide/introductory_resources/#introductory-resources","page":"Introductory resources","title":"Introductory resources","text":"","category":"section"},{"location":"guide/introductory_resources/","page":"Introductory resources","title":"Introductory resources","text":"This page collects a bunch of articles, lecture notes, textbooks and recordings related to density-functional theory (DFT) and DFTK. Since DFTK aims for an interdisciplinary audience the level and scope of the referenced works varies. They are roughly ordered from beginner to advanced. For a list of articles dealing with novel research aspects achieved using DFTK, see Publications.","category":"page"},{"location":"guide/introductory_resources/","page":"Introductory resources","title":"Introductory resources","text":"DFTK school 2022: Numerical methods for density-functional theory simulations: Summer school centred around the DFTK code and modern approaches to density-functional theory. Programme and lecture notes.\nDFTK: A Julian approach for simulating electrons in solids by M. F. Herbst: Pre-recorded talk for JuliaCon 2020. Assumes no knowledge about DFT and gives the broad picture of DFTK. Slides.\nDFT in a nutshell by Kieron Burke and Lucas Wagner: Short tutorial-style article introducing the basic DFT setting, basic equations and terminology. Great introduction from the physical / chemical perspective.\nJuliacon 2021 DFT workshop by M. F. Herbst: Three-hour workshop session at the 2021 Juliacon providing a mathematical look on DFT, SCF solution algorithms as well as the integration of DFTK into the Julia package ecosystem (arbitrary floating-point types, automatic differentiation, linear algebra and optimisation toolkits). Youtube recording.\nIntroduction to plane-wave DFT and DFTK by M. F. Herbst: Jupyter notebooks a two-hour lecture introducing plane-wave DFT and DFTK to an interdisciplinary audience of undergrads. You can also run the notebooks interactively on binder.\nElectronic Structure: Basic theory and practical methods by R. M. Martin (Cambridge University Press, 2004): Standard textbook introducing most common methods of the field (lattices, pseudopotentials, DFT, ...) from the perspective of a physicist.\nA Mathematical Introduction to Electronic Structure Theory by L. Lin and J. Lu (SIAM, 2019): Monograph attacking DFT from a mathematical angle. Covers topics such as DFT, pseudos, SCF, response, ...","category":"page"},{"location":"developer/useful_formulas/#Useful-formulas","page":"Useful formulas","title":"Useful formulas","text":"","category":"section"},{"location":"developer/useful_formulas/","page":"Useful formulas","title":"Useful formulas","text":"This section holds a collection of formulae, which are helpful when working with DFTK and plane-wave DFT in general. See also Notation and conventions for a description of the conventions used in the equations.","category":"page"},{"location":"developer/useful_formulas/#Fourier-transforms","page":"Useful formulas","title":"Fourier transforms","text":"","category":"section"},{"location":"developer/useful_formulas/","page":"Useful formulas","title":"Useful formulas","text":"The Fourier transform is\nwidehatf(q) = int_mathbb R^3 e^-i q cdot x f(x) dx\nFourier transforms of centered functions: If f(x) = R(x) Y_l^m(xx), then\nbeginaligned\n hat f( q)\n = int_mathbb R^3 R(x) Y_l^m(xx) e^-i q cdot x dx \n = sum_l = 0^infty 4 pi i^l\n sum_m = -l^l int_mathbb R^3\n R(x) j_l(q x)Y_l^m(-qq) Y_l^m(xx)\n Y_l^mast(xx)\n dx \n = 4 pi Y_l^m(-qq) i^l\n int_mathbb R^+ r^2 R(r) j_l(q r) dr\n endaligned\nThis also holds true for real spherical harmonics.","category":"page"},{"location":"developer/useful_formulas/#Spherical-harmonics","page":"Useful formulas","title":"Spherical harmonics","text":"","category":"section"},{"location":"developer/useful_formulas/","page":"Useful formulas","title":"Useful formulas","text":"Plane wave expansion formula\ne^i q cdot r =\n 4 pi sum_l = 0^infty sum_m = -l^l\n i^l j_l(q r) Y_l^m(qq) Y_l^mast(rr)\nSpherical harmonics orthogonality\nint_mathbbS^2 Y_l^m*(r)Y_l^m(r) dr\n = delta_ll delta_mm\nThis also holds true for real spherical harmonics.","category":"page"},{"location":"examples/cohen_bergstresser/","page":"Cohen-Bergstresser model","title":"Cohen-Bergstresser model","text":"EditURL = \"https://github.com/JuliaMolSim/DFTK.jl/blob/master/examples/cohen_bergstresser.jl\"","category":"page"},{"location":"examples/cohen_bergstresser/#Cohen-Bergstresser-model","page":"Cohen-Bergstresser model","title":"Cohen-Bergstresser model","text":"","category":"section"},{"location":"examples/cohen_bergstresser/","page":"Cohen-Bergstresser model","title":"Cohen-Bergstresser model","text":"(Image: ) (Image: )","category":"page"},{"location":"examples/cohen_bergstresser/","page":"Cohen-Bergstresser model","title":"Cohen-Bergstresser model","text":"This example considers the Cohen-Bergstresser model[CB1966], reproducing the results of the original paper. This model is particularly simple since its linear nature allows one to get away without any self-consistent field calculation.","category":"page"},{"location":"examples/cohen_bergstresser/","page":"Cohen-Bergstresser model","title":"Cohen-Bergstresser model","text":"[CB1966]: M. L. Cohen and T. K. Bergstresser Phys. Rev. 141, 789 (1966) DOI 10.1103/PhysRev.141.789","category":"page"},{"location":"examples/cohen_bergstresser/","page":"Cohen-Bergstresser model","title":"Cohen-Bergstresser model","text":"We build the lattice using the tabulated lattice constant from the original paper, stored in DFTK:","category":"page"},{"location":"examples/cohen_bergstresser/","page":"Cohen-Bergstresser model","title":"Cohen-Bergstresser model","text":"using DFTK\n\nSi = ElementCohenBergstresser(:Si)\natoms = [Si, Si]\npositions = [ones(3)/8, -ones(3)/8]\nlattice = Si.lattice_constant / 2 .* [[0 1 1.]; [1 0 1.]; [1 1 0.]];\nnothing #hide","category":"page"},{"location":"examples/cohen_bergstresser/","page":"Cohen-Bergstresser model","title":"Cohen-Bergstresser model","text":"Next we build the rather simple model and discretize it with moderate Ecut:","category":"page"},{"location":"examples/cohen_bergstresser/","page":"Cohen-Bergstresser model","title":"Cohen-Bergstresser model","text":"model = Model(lattice, atoms, positions; terms=[Kinetic(), AtomicLocal()])\nbasis = PlaneWaveBasis(model, Ecut=10.0, kgrid=(2, 2, 2));\nnothing #hide","category":"page"},{"location":"examples/cohen_bergstresser/","page":"Cohen-Bergstresser model","title":"Cohen-Bergstresser model","text":"We diagonalise at the Gamma point to find a Fermi level …","category":"page"},{"location":"examples/cohen_bergstresser/","page":"Cohen-Bergstresser model","title":"Cohen-Bergstresser model","text":"ham = Hamiltonian(basis)\neigres = diagonalize_all_kblocks(DFTK.lobpcg_hyper, ham, 6)\nεF = DFTK.compute_occupation(basis, eigres.λ).εF","category":"page"},{"location":"examples/cohen_bergstresser/","page":"Cohen-Bergstresser model","title":"Cohen-Bergstresser model","text":"… and compute and plot 8 bands:","category":"page"},{"location":"examples/cohen_bergstresser/","page":"Cohen-Bergstresser model","title":"Cohen-Bergstresser model","text":"using Plots\nusing Unitful\n\np = plot_bandstructure(basis; n_bands=8, εF, kline_density=10, unit=u\"eV\")\nylims!(p, (-5, 6))","category":"page"},{"location":"examples/custom_potential/","page":"Custom potential","title":"Custom potential","text":"EditURL = \"https://github.com/JuliaMolSim/DFTK.jl/blob/master/examples/custom_potential.jl\"","category":"page"},{"location":"examples/custom_potential/#custom-potential","page":"Custom potential","title":"Custom potential","text":"","category":"section"},{"location":"examples/custom_potential/","page":"Custom potential","title":"Custom potential","text":"(Image: ) (Image: )","category":"page"},{"location":"examples/custom_potential/","page":"Custom potential","title":"Custom potential","text":"We solve the 1D Gross-Pitaevskii equation with a custom potential. This is similar to Gross-Pitaevskii equation in 1D example and we show how to define local potentials attached to atoms, which allows for instance to compute forces. The custom potential is actually already defined as ElementGaussian in DFTK, and could be used as is.","category":"page"},{"location":"examples/custom_potential/","page":"Custom potential","title":"Custom potential","text":"using DFTK\nusing LinearAlgebra","category":"page"},{"location":"examples/custom_potential/","page":"Custom potential","title":"Custom potential","text":"First, we define a new element which represents a nucleus generating a Gaussian potential.","category":"page"},{"location":"examples/custom_potential/","page":"Custom potential","title":"Custom potential","text":"struct CustomPotential <: DFTK.Element\n α # Prefactor\n L # Width of the Gaussian nucleus\nend","category":"page"},{"location":"examples/custom_potential/","page":"Custom potential","title":"Custom potential","text":"Some default values","category":"page"},{"location":"examples/custom_potential/","page":"Custom potential","title":"Custom potential","text":"CustomPotential() = CustomPotential(1.0, 0.5);\nnothing #hide","category":"page"},{"location":"examples/custom_potential/","page":"Custom potential","title":"Custom potential","text":"We extend the two methods providing access to the real and Fourier representation of the potential to DFTK.","category":"page"},{"location":"examples/custom_potential/","page":"Custom potential","title":"Custom potential","text":"function DFTK.local_potential_real(el::CustomPotential, r::Real)\n -el.α / (√(2π) * el.L) * exp(- (r / el.L)^2 / 2)\nend\nfunction DFTK.local_potential_fourier(el::CustomPotential, q::Real)\n # = ∫ V(r) exp(-ix⋅q) dx\n -el.α * exp(- (q * el.L)^2 / 2)\nend","category":"page"},{"location":"examples/custom_potential/","page":"Custom potential","title":"Custom potential","text":"We set up the lattice. For a 1D case we supply two zero lattice vectors","category":"page"},{"location":"examples/custom_potential/","page":"Custom potential","title":"Custom potential","text":"a = 10\nlattice = a .* [[1 0 0.]; [0 0 0]; [0 0 0]];\nnothing #hide","category":"page"},{"location":"examples/custom_potential/","page":"Custom potential","title":"Custom potential","text":"In this example, we want to generate two Gaussian potentials generated by two \"nuclei\" localized at positions x_1 and x_2, that are expressed in 01) in fractional coordinates. x_1 - x_2 should be different from 05 to break symmetry and get nonzero forces.","category":"page"},{"location":"examples/custom_potential/","page":"Custom potential","title":"Custom potential","text":"x1 = 0.2\nx2 = 0.8\npositions = [[x1, 0, 0], [x2, 0, 0]]\ngauss = CustomPotential()\natoms = [gauss, gauss];\nnothing #hide","category":"page"},{"location":"examples/custom_potential/","page":"Custom potential","title":"Custom potential","text":"We setup a Gross-Pitaevskii model","category":"page"},{"location":"examples/custom_potential/","page":"Custom potential","title":"Custom potential","text":"C = 1.0\nα = 2;\nn_electrons = 1 # Increase this for fun\nterms = [Kinetic(),\n AtomicLocal(),\n LocalNonlinearity(ρ -> C * ρ^α)]\nmodel = Model(lattice, atoms, positions; n_electrons, terms,\n spin_polarization=:spinless); # use \"spinless electrons\"\nnothing #hide","category":"page"},{"location":"examples/custom_potential/","page":"Custom potential","title":"Custom potential","text":"We discretize using a moderate Ecut and run a SCF algorithm to compute forces afterwards. As there is no ionic charge associated to gauss we have to specify a starting density and we choose to start from a zero density.","category":"page"},{"location":"examples/custom_potential/","page":"Custom potential","title":"Custom potential","text":"basis = PlaneWaveBasis(model; Ecut=500, kgrid=(1, 1, 1))\nρ = zeros(eltype(basis), basis.fft_size..., 1)\nscfres = self_consistent_field(basis; tol=1e-5, ρ)\nscfres.energies","category":"page"},{"location":"examples/custom_potential/","page":"Custom potential","title":"Custom potential","text":"Computing the forces can then be done as usual:","category":"page"},{"location":"examples/custom_potential/","page":"Custom potential","title":"Custom potential","text":"compute_forces(scfres)","category":"page"},{"location":"examples/custom_potential/","page":"Custom potential","title":"Custom potential","text":"Extract the converged total local potential","category":"page"},{"location":"examples/custom_potential/","page":"Custom potential","title":"Custom potential","text":"tot_local_pot = DFTK.total_local_potential(scfres.ham)[:, 1, 1]; # use only dimension 1\nnothing #hide","category":"page"},{"location":"examples/custom_potential/","page":"Custom potential","title":"Custom potential","text":"Extract other quantities before plotting them","category":"page"},{"location":"examples/custom_potential/","page":"Custom potential","title":"Custom potential","text":"ρ = scfres.ρ[:, 1, 1, 1] # converged density, first spin component\nψ_fourier = scfres.ψ[1][:, 1] # first k-point, all G components, first eigenvector\nψ = ifft(basis, basis.kpoints[1], ψ_fourier)[:, 1, 1]\nψ /= (ψ[div(end, 2)] / abs(ψ[div(end, 2)]));\n\nusing Plots\nx = a * vec(first.(DFTK.r_vectors(basis)))\np = plot(x, real.(ψ), label=\"real(ψ)\")\nplot!(p, x, imag.(ψ), label=\"imag(ψ)\")\nplot!(p, x, ρ, label=\"ρ\")\nplot!(p, x, tot_local_pot, label=\"tot local pot\")","category":"page"},{"location":"#DFTK.jl:-The-density-functional-toolkit.","page":"Home","title":"DFTK.jl: The density-functional toolkit.","text":"","category":"section"},{"location":"","page":"Home","title":"Home","text":"The density-functional toolkit, DFTK for short, is a library of Julia routines for playing with plane-wave density-functional theory (DFT) algorithms. In its basic formulation it solves periodic Kohn-Sham equations. The unique feature of the code is its emphasis on simplicity and flexibility with the goal of facilitating methodological development and interdisciplinary collaboration. In about 7k lines of pure Julia code we support a sizeable set of features. Our performance is of the same order of magnitude as much larger production codes such as Abinit, Quantum Espresso and VASP. DFTK's source code is publicly available on github.","category":"page"},{"location":"","page":"Home","title":"Home","text":"If you are new to density-functional theory or plane-wave methods, see our notes on Periodic problems and our collection of Introductory resources.","category":"page"},{"location":"","page":"Home","title":"Home","text":"Found a bug, missing a feature? Look for an open issue or create a new one. Want to contribute? See our contributing notes.","category":"page"},{"location":"#getting-started","page":"Home","title":"Getting started","text":"","category":"section"},{"location":"","page":"Home","title":"Home","text":"First, new users should take a look at the Installation and Tutorial sections. Then, make your way through the various examples. An ideal starting point are the Examples on basic DFT calculations.","category":"page"},{"location":"","page":"Home","title":"Home","text":"note: Convergence parameters in the documentation\nIn the documentation we use very rough convergence parameters to be able to automatically generate this documentation very quickly. Therefore results are far from converged. Tighter thresholds and larger grids should be used for more realistic results.","category":"page"},{"location":"","page":"Home","title":"Home","text":"If you have an idea for an addition to the docs or see something wrong, please open an issue or pull request!","category":"page"},{"location":"developer/conventions/#Notation-and-conventions","page":"Notation and conventions","title":"Notation and conventions","text":"","category":"section"},{"location":"developer/conventions/#Usage-of-unicode-characters","page":"Notation and conventions","title":"Usage of unicode characters","text":"","category":"section"},{"location":"developer/conventions/","page":"Notation and conventions","title":"Notation and conventions","text":"DFTK liberally uses unicode characters to represent Greek characters (e.g. ψ, ρ, ε...). Make sure you use the proper Julia plugins to simplify typing them.","category":"page"},{"location":"developer/conventions/#symbol-conventions","page":"Notation and conventions","title":"Symbol conventions","text":"","category":"section"},{"location":"developer/conventions/","page":"Notation and conventions","title":"Notation and conventions","text":"Reciprocal-space vectors: k for vectors in the Brillouin zone, G for vectors of the reciprocal lattice, q for general vectors\nReal-space vectors: R for lattice vectors, r and x are usually used for unit for vectors in the unit cell or general real-space vectors, respectively. This convention is, however, less consistently applied.\nOmega is the unit cell, and Omega (or sometimes just Omega) is its volume.\nA are the real-space lattice vectors (model.lattice) and B the Brillouin zone lattice vectors (model.recip_lattice).\nThe Bloch waves are\npsi_nk(x) = e^ikcdot x u_nk(x)\nwhere n is the band index and k the k-point. In the code we sometimes use psi and u interchangeably.\nvarepsilon are the eigenvalues, varepsilon_F is the Fermi level.\nrho is the density.\nIn the code we use normalized plane waves:\ne_G(r) = frac 1 sqrtOmega e^i G cdot r\nY^l_m are the complex spherical harmonics, and Y_lm the real ones.\nj_l are the Bessel functions. In particular, j_0(x) = fracsin xx.","category":"page"},{"location":"developer/conventions/#Units","page":"Notation and conventions","title":"Units","text":"","category":"section"},{"location":"developer/conventions/","page":"Notation and conventions","title":"Notation and conventions","text":"In DFTK, atomic units are used throughout, most importantly lengths are in Bohr and energies in Hartree. See wikipedia for a list of conversion factors. Appropriate unit conversion can can be performed using the Unitful and UnitfulAtomic packages:","category":"page"},{"location":"developer/conventions/","page":"Notation and conventions","title":"Notation and conventions","text":"using Unitful\nusing UnitfulAtomic\naustrip(10u\"eV\") # 10eV in Hartree","category":"page"},{"location":"developer/conventions/","page":"Notation and conventions","title":"Notation and conventions","text":"using Unitful: Å\nusing UnitfulAtomic\nauconvert(Å, 1.2) # 1.2 Bohr in Ångström","category":"page"},{"location":"developer/conventions/","page":"Notation and conventions","title":"Notation and conventions","text":"warning: Differing unit conventions\nDifferent electronic-structure codes use different unit conventions. For example for lattice vectors the common length units are Bohr (used by DFTK) and Ångström (used e.g. by ASE, 1Å ≈ 1.80 Bohr). When setting up a calculation for DFTK one needs to ensure to convert to Bohr and atomic units. When structures are provided as AtomsBase.jl-compatible objects, this unit conversion is automatically performed behind the scenes. See AtomsBase integration for details.","category":"page"},{"location":"developer/conventions/#conventions-lattice","page":"Notation and conventions","title":"Lattices and lattice vectors","text":"","category":"section"},{"location":"developer/conventions/","page":"Notation and conventions","title":"Notation and conventions","text":"Both the real-space lattice (i.e. model.lattice) and reciprocal-space lattice (model.recip_lattice) contain the lattice vectors in columns. For example, model.lattice[:, 1] is the first real-space lattice vector. If 1D or 2D problems are to be treated these arrays are still 3 times 3 matrices, but contain two or one zero-columns, respectively. The real-space lattice vectors are sometimes referred to by A and the reciprocal-space lattice vectors by B = 2pi A^-T.","category":"page"},{"location":"developer/conventions/","page":"Notation and conventions","title":"Notation and conventions","text":"warning: Row-major versus column-major storage order\nJulia stores matrices as column-major, but other languages (notably Python and C) use row-major ordering. Care therefore needs to be taken to properly transpose the unit cell matrices A before using it with DFTK. For the supported third-party packages load_lattice, load_positions and load_atoms again handle such conversion automatically.","category":"page"},{"location":"developer/conventions/","page":"Notation and conventions","title":"Notation and conventions","text":"We use the convention that the unit cell in real space is 0 1)^3 in reduced coordinates and the unit cell in reciprocal space (the reducible Brillouin zone) is -12 12)^3.","category":"page"},{"location":"developer/conventions/#Reduced-and-cartesian-coordinates","page":"Notation and conventions","title":"Reduced and cartesian coordinates","text":"","category":"section"},{"location":"developer/conventions/","page":"Notation and conventions","title":"Notation and conventions","text":"Unless denoted otherwise the code uses reduced coordinates for reciprocal-space vectors such as k, G, q or real-space vectors like r and R (see Symbol conventions). One switches to Cartesian coordinates by","category":"page"},{"location":"developer/conventions/","page":"Notation and conventions","title":"Notation and conventions","text":"x_textcart = M x_textred","category":"page"},{"location":"developer/conventions/","page":"Notation and conventions","title":"Notation and conventions","text":"where M is either A / model.lattice (for real-space vectors) or B / model.recip_lattice (for reciprocal-space vectors). A useful relationship is","category":"page"},{"location":"developer/conventions/","page":"Notation and conventions","title":"Notation and conventions","text":"b_textcart cdot a_textcart=2pi b_textred cdot a_textred","category":"page"},{"location":"developer/conventions/","page":"Notation and conventions","title":"Notation and conventions","text":"if a and b are real-space and reciprocal-space vectors respectively. Other names for reduced coordinates are integer coordinates (usually for G-vectors) or fractional coordinates (usually for k-points).","category":"page"},{"location":"developer/conventions/#Normalization-conventions","page":"Notation and conventions","title":"Normalization conventions","text":"","category":"section"},{"location":"developer/conventions/","page":"Notation and conventions","title":"Notation and conventions","text":"The normalization conventions used in the code is that quantities stored in reciprocal space are coefficients in the e_G basis, and quantities stored in real space use real physical values. This means for instance that wavefunctions in the real space grid are normalized as fracOmegaN sum_r psi(r)^2 = 1 where N is the number of grid points and in reciprocal space its coefficients are ell^2-normalized, see the discussion in section PlaneWaveBasis and plane-wave discretisations where this is demonstrated.","category":"page"},{"location":"examples/anyons/","page":"Anyonic models","title":"Anyonic models","text":"EditURL = \"https://github.com/JuliaMolSim/DFTK.jl/blob/master/examples/anyons.jl\"","category":"page"},{"location":"examples/anyons/#Anyonic-models","page":"Anyonic models","title":"Anyonic models","text":"","category":"section"},{"location":"examples/anyons/","page":"Anyonic models","title":"Anyonic models","text":"(Image: ) (Image: )","category":"page"},{"location":"examples/anyons/","page":"Anyonic models","title":"Anyonic models","text":"We solve the almost-bosonic anyon model of https://arxiv.org/pdf/1901.10739.pdf","category":"page"},{"location":"examples/anyons/","page":"Anyonic models","title":"Anyonic models","text":"using DFTK\nusing StaticArrays\nusing Plots\n\n# Unit cell. Having one of the lattice vectors as zero means a 2D system\na = 14\nlattice = a .* [[1 0 0.]; [0 1 0]; [0 0 0]];\n\n# Confining scalar potential\npot(x, y, z) = ((x - a/2)^2 + (y - a/2)^2);\n\n# Parameters\nEcut = 50\nn_electrons = 1\nβ = 5;\n\n# Collect all the terms, build and run the model\nterms = [Kinetic(; scaling_factor=2),\n ExternalFromReal(X -> pot(X...)),\n Anyonic(1, β)\n]\nmodel = Model(lattice; n_electrons, terms, spin_polarization=:spinless) # \"spinless electrons\"\nbasis = PlaneWaveBasis(model; Ecut, kgrid=(1, 1, 1))\nscfres = direct_minimization(basis, tol=1e-14) # Reduce tol for production\nE = scfres.energies.total\ns = 2\nE11 = π/2 * (2(s+1)/s)^((s+2)/s) * (s/(s+2))^(2(s+1)/s) * E^((s+2)/s) / β\nprintln(\"e(1,1) / (2π)= \", E11 / (2π))\nheatmap(scfres.ρ[:, :, 1, 1], c=:blues)","category":"page"}]
}