DFT

Description:

Density functional theory (DFT) is a computational quantum mechanical modelling method used in physics, chemistry and materials science to investigate the electronic structure (principally the ground state) of many-body systems, in particular atoms, molecules, and the condensed phases.


Next a Python snippet code that evaluates an uniformly distributed and weighed k-points grid to be used with `epsilon.x` package from  `Quantum Espresso`

#! pip install ase
from ase import Atoms
from ase.build import bulk
import ase.spacegroup as sg
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
def get_reciprocal_cell(atoms_list, positions_list, spacegroup, cell_parameters):
    system = sg.crystal(symbols=atoms_list, \
                        basis=positions_list, \
                        spacegroup=spacegroup,\
                        cellpar=cell_parameters)
    print(f'System cell:\n\t {system.cell}')
    system_BZ = system.get_reciprocal_cell()
    system_BZ.bravais = system_BZ.get_bravais_lattice()
    print(f'System reciprocal lattice symmetry:\n\t {system_BZ.bravais}')
    a_star, b_star, c_star = system_BZ.array
    a_star = a_star / np.linalg.norm(a_star)
    b_star = b_star / np.linalg.norm(b_star)
    c_star = c_star / np.linalg.norm(c_star)
    print(f'System reciprocal lattice vectors:\n \t a*={a_star}\n\t b*={b_star}\n\t c*={c_star}')
    return a_star, b_star, c_star
def generate_kpoints(nk, a_star, b_star, c_star, shift=0.0):
    """
    Generates a uniform K-point grid for a lattice given by a_star, b_star, c_star.
    Args:
        nk: The number of K-points along each reciprocal lattice vector.
        shift: A shift applied to the K-point grid.
    Returns:
        A list of K-point coordinates.
    """
    # Reciprocal lattice vectors for FCC
    a_star = np.array(a_star)
    b_star = np.array(b_star)
    c_star = np.array(c_star)
    # K-point grid
    kpoints = []
    for i in range(nk):
        for j in range(nk):
            for k in range(nk):
                kpoint = (i + 0.5) / nk * a_star + (j + 0.5) / nk * b_star + (k + 0.5) / nk * c_star
                kpoints.append(kpoint + shift)
    weigths = 1 / nk**3
    return kpoints, weigths
def plot_k_mesh(kpoints):
    # Extract the x, y, and z coordinates
    x = [point[0] for point in kpoints]
    y = [point[1] for point in kpoints]
    z = [point[2] for point in kpoints]
    # Create the 3D plot
    fig = plt.figure()
    ax = fig.add_subplot(111, projection='3d')
    # Plot the points
    ax.scatter(x, y, z)
    # Set labels and title
    ax.set_xlabel('kx')
    ax.set_ylabel('ky')
    ax.set_zlabel('kz')
    plt.title('K-points in 3D')
    # Show the plot
    plt.show()
# ZnO example
atoms_list=('Zn', 'O')
positions_list=[(2/3,1/3,0.5),(2/3,1/3,0.87)]
spacegroup=186
cell_parameters=[3.24,3.24,5.22,90,90,120]
a_star, b_star, c_star = get_reciprocal_cell(atoms_list=atoms_list, \
                                             positions_list=positions_list,\
                                             spacegroup=spacegroup, \

                                             cell_parameters=cell_parameters)

# GaAs example
atoms_list=('Ga', 'As')
positions_list=[(0,0,0),(1/4,1/4,3/4)]
spacegroup=216
cell_parameters=[5.75,5.75,5.75,90,90,90]
a_star, b_star, c_star = get_reciprocal_cell(atoms_list=atoms_list, \
                                             positions_list=positions_list,\
                                             spacegroup=spacegroup, \
                                             cell_parameters=cell_parameters)
nk = 10  # Number of K-points along each reciprocal lattice vector
kpoints, weigths = generate_kpoints(nk, a_star, b_star, c_star, shift=0.0)
printPoints = True
if printPoints:
    # Print the K-points
    for ik, kpoint in enumerate(kpoints):
        print(f"{kpoint[0]:.2f} {kpoint[1]:.2f} {kpoint[2]:.2f} {weigths:.3f}")
plot_k_mesh(kpoints)

 


We can find lots of tutorials, but this is a good one!


Modelling Materials with DFT

There some programs to do the task. A very good one is Quantum Espresso, which is free under GPL licence.

Here some hint of how to configure it.

Quantum espresso configuration

is an integrated suite of Open-Source computer codes for electronic-structure calculations and materials modeling at the nanoscale. It is based on density-functional theory, plane waves, and pseudopotentials.

(tested with 6.0.0 version)

http://www.hpcadvisorycouncil.com/pdf/ESPRESSO_Best_Practices.pdf

https://glennklockwood.blogspot.com/2014/02/quantum-espresso-compiling-and-choice.html

Some usefull links:

-> Link advisor to configure FFTW environment variables to run with intel’s mkl

-> Usefull discussions (1), (2)

-> Explicit offload for Quantum ESPRESSO

-> Installing Quantum Espresso with Intel Parallel Studio and OpenMPI

-> Quantum ESPRESSO* for Intel® Xeon Phi™ Coprocessor

-> Installation Guide

-> Intel® Parallel Studio XE 2017

-> Installation of OpenMPI

-> Using the ifortvars File to Specify Location of Components

-> Intel® Fortran Compiler 16.0 User and Reference Guide
________________________________________________________________

First things first!

Follow this up in order to compile QE using Intel’s compilers, mkl and mpi.

After installing Intel’s Parallel Studio, source compiler, mkl and mpi variables.

It could be included to the bashrc file:

#compilers source
source /opt/intel/compilers_and_libraries/linux/bin/compilervars.sh intel64
source /opt/intel/compilers_and_libraries/linux/mkl/bin/mklvars.sh intel64
source /opt/intel/compilers_and_libraries/linux/mpi/bin64/mpivars.sh

the paths point out to the installation folders.

compilervar.sh and mklvar.sh are sourced using <arch> intel64

This should give to QE’s configure the correct paths.

Configure QE explicitly indicating the intel’s compilers,

$ export FC=mpiifort
$ export F90=ifort
$ export F77=ifort
$ export MPIF90=mpiifort
$ export CC=mpicc

$ ./configure –enable-openmp –enable-parallel -with-scalapack=intel

or

$ ./configure –enable-parallel -with-scalapack=intel F90=ifort F77=ifort MPIF90=mpiifort CC=mpicc LIBDIRS=”/opt/intel/compilers_and_libraries/linux/mkl/lib/intel64″

It should produce a make.inc file like this (comments were removed)

======================================
.SUFFIXES :
.SUFFIXES : .o .c .f .f90

.f90.o:
$(MPIF90) $(F90FLAGS) -c $<

# .f.o and .c.o: do not modify

.f.o:
$(F77) $(FFLAGS) -c $<

.c.o:
$(CC) $(CFLAGS) -c $<

MANUAL_DFLAGS =
DFLAGS = -D__INTEL -D__DFTI -D__MPI
FDFLAGS = $(DFLAGS) $(MANUAL_DFLAGS)

IFLAGS = -I$(TOPDIR)/include -I../include/ -I/opt/intel/compilers_and_libraries_2018.3.222/linux/mkl/include

MOD_FLAG = -I

MPIF90 = mpiifort
#F90 = ifort
CC = icc
F77 = ifort

CPP = cpp
CPPFLAGS = -P -traditional $(DFLAGS) $(IFLAGS)

CFLAGS = -O3 $(DFLAGS) $(IFLAGS)
F90FLAGS = $(FFLAGS) -nomodule -fpp $(FDFLAGS) $(IFLAGS) $(MODFLAGS)
FFLAGS = -O2 -assume byterecl -g -traceback

FFLAGS_NOOPT = -O0 -assume byterecl -g -traceback

FFLAGS_NOMAIN = -nofor_main

LD = mpiifort
LDFLAGS = -static-intel
LD_LIBS =

BLAS_LIBS = -lmkl_intel_lp64 -lmkl_sequential -lmkl_core
BLAS_LIBS_SWITCH = external

LAPACK_LIBS = -mkl=parallel
LAPACK_LIBS_SWITCH = external

SCALAPACK_LIBS =

FFT_LIBS =

HDF5_LIB =

MPI_LIBS =

MASS_LIBS =

AR = ar
ARFLAGS = ruv

RANLIB = ranlib

FLIB_TARGETS = all

LIBOBJS = $(TOPDIR)/clib/clib.a $(TOPDIR)/iotk/src/libiotk.a
LIBS = $(SCALAPACK_LIBS) $(LAPACK_LIBS) $(FFT_LIBS) $(BLAS_LIBS) $(MPI_LIBS) $(MASS_LIBS) ${HDF5_LIB} $(LD_LIBS)

WGET = wget -O

PREFIX = /usr/local

================================

Note that FFT_LIBS path it was not recognized and should generate a crash during the make process. Using the Intel’s Link advisor we could get the correct links between mkl and FFT. It should produce something like (https://software.intel.com/en-us/articles/intel-mkl-link-line-advisor/)

-L${MKLROOT}/lib/intel64 -lmkl_intel_ilp64 -lmkl_intel_thread -lmkl_core -liomp5 -lpthread -lm -ldl

So, replace

FFT_LIBS =

with

FFT_LIBS = -L${MKLROOT}/lib/intel64 -lmkl_intel_ilp64 -lmkl_intel_thread -lmkl_core -liomp5 -lpthread -lm -ldl

If configure proceed without errors, make all executables (or the ones needed). Type

$ make all

Testing installation

Inside the software folders it is possible to find examples. For example,

$<qe_install_folder>/pw/examples

run all examples using the given script

$ ./run_all_examples

For newer versions of QE (>6, for instance) there is a test-suite script. Search for the folder /test-suite and type make. It should return the available options for making. Yelds something like

===================
To run Quantum ESPRESSO test-suite, type at the shell prompt:

make target

where <target> identifies an action
run-tests : run-tests-serial (default)
run-tests-serial : run all tests in SERIAL
run-tests-parallel : run all tests in PARALLEL (4 MPI)
compare : compare last output generated with reference
clean : clean output (our/err files) of all tests

For additional advanced commands and settings please manually inspect
ENVIRONMENT and Makefile files
=====================

Use, for example,

$make run-tests-parallel (takes a fairly long time to proceed)

Linking to QE executables

All executable files are withing the <intallation_folder>/bin. Export the path to the bashrc file allow for executing from a non-specific folder

export PATH=$PATH:/<installation_folder>/bin

Graphical User Interface – PWGUI

Within the QE it could be found the GUI folder. Inside of it there are some option for the GUI. For pw-like files PWGUI is a good one.

From README we have

The main purpose of the PWgui is to facilitate the creation and manipulation (editing) of input files for PWscf set of programs. It is possible to run the PWscf programs by using the GUI. This feature
requires to set the path of the PWscf executables via “File–>Settings” menu (tab: PWscf settings). The GUI can also use the XCRYSDEN program (http://www.xcrysden.org/) for the visualization of
atomic structures from the pw.x input/output files, or for the visualization of properties calculated via the sequence: pw.x–>pp.x (when the property was saved into an XSF file).

Currently, the following PWscf programs (modules) are supported:

* pw.x
* neb.x’s neb.dat
* ph.x
* pp.x
* projwfc.x
* bands.x
* dos.x
* d3.x
* ld1.x (atomic)

In order to use it, inside PWGUI folder, run the script pwgui. Type

$ ./pwgui

The path could also be exported and sourced to the bashrc file

export PATH=$PATH:/<intallation_folder>/GUI/PWgui

DONE!!!!