Effective masses with finite diff

This example shows how to use finite differences to compute effective masses and plot the data.

Initialize the EffMassAnalyzer from a GSR file with energies computed along segments passing through the k-points of interest.

Clearly the accuracy of the finite difference results strongly depends on the spacing between the points along the path. The GSR file used in this example is not accurate enough!

import abipy.data as abidata
from abipy.electrons.effmass_analyzer import EffMassAnalyzer

emana = EffMassAnalyzer.from_file(abidata.ref_file("si_nscf_GSR.nc"))
print(emana)
================================= Structure =================================
Full Formula (Si2)
Reduced Formula: Si
abc   :   3.866975   3.866975   3.866975
angles:  60.000000  60.000000  60.000000
pbc   :       True       True       True
Sites (2)
  #  SP       a     b     c
---  ----  ----  ----  ----
  0  Si    0     0     0
  1  Si    0.25  0.25  0.25

Abinit Spacegroup: spgid: 227, num_spatial_symmetries: 48, has_timerev: True, symmorphic: True

Number of electrons: 8.0, Fermi level: 5.598 (eV)
nsppol: 1, nkpt: 14, mband: 8, nspinor: 1, nspden: 1
smearing scheme: none (occopt 1), tsmear_eV: 0.272, tsmear Kelvin: 3157.7
Direct gap:
    Energy: 2.532 (eV)
    Initial state: spin: 0, kpt: $\Gamma$ [+0.000, +0.000, +0.000], band: 3, eig: 5.598, occ: 2.000
    Final state:   spin: 0, kpt: $\Gamma$ [+0.000, +0.000, +0.000], band: 4, eig: 8.130, occ: 0.000
Fundamental gap:
    Energy: 0.524 (eV)
    Initial state: spin: 0, kpt: $\Gamma$ [+0.000, +0.000, +0.000], band: 3, eig: 5.598, occ: 2.000
    Final state:   spin: 0, kpt: [+0.000, +0.429, +0.429], band: 4, eig: 6.123, occ: 0.000
Bandwidth: 11.856 (eV)
Valence maximum located at kpt index 6:
    spin: 0, kpt: $\Gamma$ [+0.000, +0.000, +0.000], band: 3, eig: 5.598, occ: 2.000
Conduction minimum located at kpt index 12:
    spin: 0, kpt: [+0.000, +0.429, +0.429], band: 4, eig: 6.123, occ: 0.000

TIP: Use `--verbose` to print k-point coordinates with more digits

Before computing the effective masses, we have to select the k-points.

emana.select_vbm()

# Alternatively, one can use:

#emana.select_cbm()
#emana.select_band_edges()

# or the most flexible API:

#emana.select_kpoint_band((0, 0, 0), band=3, spin=0, degtol_ev=0.1)

Compute effective masses with different accuracies and print results in tabular format. Useful to understand if results are sensitive to the number of points in the finite difference. Note however that numerical differentiation is performed with the same delta_k step.

Centeral diff weights for order: 2, and accuracy: 1 are missing!
Centeral diff weights for order: 2, and accuracy: 1 are missing!
Centeral diff weights for order: 2, and accuracy: 1 are missing!
Centeral diff weights for order: 2, and accuracy: 3 are missing!
Centeral diff weights for order: 2, and accuracy: 3 are missing!
Centeral diff weights for order: 2, and accuracy: 3 are missing!
Centeral diff weights for order: 2, and accuracy: 5 are missing!
Centeral diff weights for order: 2, and accuracy: 5 are missing!
Centeral diff weights for order: 2, and accuracy: 5 are missing!

        Don't have enough points for index: 6 in array of length: 7
        to compute backward finite difference with order: 2, and acc: 6 (num_weights: 8)
        Decrease acc or increase the number of sampling points.

        Don't have enough points for index: 6 in array of length: 7
        to compute backward finite difference with order: 2, and acc: 6 (num_weights: 8)
        Decrease acc or increase the number of sampling points.

        Don't have enough points for index: 6 in array of length: 7
        to compute backward finite difference with order: 2, and acc: 6 (num_weights: 8)
        Decrease acc or increase the number of sampling points.

Print the results to terminal with:

# extract segment.
segment = emana.segments[0]
#repr(segment); str(segment)
#assert segment.to_string(verbose=2)
df = segment.get_dataframe_with_accuracies(acc_list=(2, 4))
print(df)

#assert len(emana.segments) == 1
#for segment in emana.segments[0]:
#    segment.get_effmass_line(acc=2)
          npts   effm_b0   effm_b1   effm_b2
accuracy
2            4 -0.163343 -0.633128 -0.633128
4            6 -0.098950 -0.470343 -0.470343

Plot electronic dispersion and quadratic approximant based on the effective masses computed along each segment.

emana.plot_emass(acc=4)

#emana.plot_all_segments()
#emana.segments[0].plot_emass()
${\bf k}_0$: $\Gamma$ [+0.000, +0.000, +0.000], direction: [-1.000, 0.000, 0.000], (-0.943, 0.333, 0.000), step: 0.166 $\AA^{-1}$

Total running time of the script: (0 minutes 0.374 seconds)

Gallery generated by Sphinx-Gallery