3D Fermi surface

PyProcar’s 3D Fermi surface utility is able to generate Fermi surface plots projected over spin, atoms and orbitals or a combination of one or many of each. This utility is also capable of projecting external properties that are provided on a mesh grid in momentum space. This feature is useful when one wants to project properties that are not provided in PROCAR file such as Fermi velocity, electron-phonon coupling and electron effective mass. We divide this section into three sub sections, plain Fermi surface, projection of properties from PROCAR and projection of properties from external file.

Note

When plotting 3D Fermi surfaces, it is important to use a Monkhorst-Pack k-grid while setting ISYM=-1 in the INCAR file (turn off symmetry).

3D surfaces

This section focuses on how the 3d image is created, if you are only interested in using this functionality, you can skip this part and move to the examples section. A surface is created by adding a collection of small polygons. By increasing the number of polygons, one can increase the smoothness of the surface. These polygons are defined by a collection of points on the surface also known as vertices and a recipe for their connections to create the polygons, which is defined by a list of points. This list is called faces. For example the following defines a cube:

vertices
 1   1.000000 -1.000000 -1.000000
 2   1.000000 -1.000000  1.000000
 3  -1.000000 -1.000000  1.000000
 4  -1.000000 -1.000000 -1.000000
 5   1.000000  1.000000 -0.999999
 6   0.999999  1.000000  1.000001
 7  -1.000000  1.000000  1.000000
 8  -1.000000  1.000000 -1.000000
faces
2 3 4
8 7 6
5 6 2
6 7 3
3 7 8
1 4 8
1 2 4
5 8 6
1 5 2
2 6 3
4 3 8
5 1 8

for example the first face defined by a triangle instructs to connect points 2,3 and 4. One can also assign colors to each face. pyprocar uses this feature to assign the projection colors to the surfaces. Another important aspect to this in definning the surface is the normals to the faces, however a tutorial about fermi surface is not a good place to get into details about surfaces.

To generate the fermi surface PyProcar uses different levels of generality to surfaces. The level is the definition of a surface which is handled by the class surface in pyprocar.core.Surface which only requires faces and vertices. The next level is an isosurface which is handeled by pyprocar.core.Isosurface, this class represents the equation \(f(x,y,z)=V\), where \(V\) is the isovalue and \(f(x,y,z)\) is the function. In a fermi surface \(f(x,y,z)\) will be the energy of each band at different points of the k space and \(V\) will be the fermi energy. To use this class one needs to provide the function in a 3 dimentional matrix and the isovalue. The next level is the fermi surface which is defined by an isosurfcace which is handled by the class pyprocar.fermisurface3d.FermiSurfcae3D. This function requires a list of kpoints and the eigen-values of the energy for a specific band. However one does not have to be concerned about the specifics of different layers and just use the pyprocar.fermi3D function to generate the fermi surface. The different arguments required by this function are explained in details at the bottom of this page. This work would not have been possible without the amazing packages, pyvista and trimesh. If you use pyprocar’s 3D fermi surface in your publication please cite trimesh and pyvista as well with the following citation information.

trimesh:

@software{trimesh,
      author = {{Dawson-Haggerty et al.}},
      title = {trimesh},
      url = {https://trimsh.org/},
      version = {3.2.0},
      date = {2019-12-8},
}

PyVista:

@article{sullivan2019pyvista,
doi = {10.21105/joss.01450},
url = {https://doi.org/10.21105/joss.01450},
year = {2019},
month = {may},
publisher = {The Open Journal},
volume = {4},
number = {37},
pages = {1450},
author = {C. Bane Sullivan and Alexander Kaszynski},
title = {{PyVista}: 3D plotting and mesh analysis through a streamlined interface for the Visualization Toolkit ({VTK})},
journal = {Journal of Open Source Software}
}

Examples

As a standard example for plotting fermi surfaces we use MgB2and SrFeO3.

1. Plain Fermi surface

This mode is activated by selecting the argument mode equal to 'plain'. This mode plots each band in fermi a different color, however there won’t be any color projection.

>>> surfaces = pyprocar.fermi3D(procar='colinear/PROCAR-MgB2-nonPol',
>>>                            outcar='colinear/OUTCAR-MgB2-nonPol',
>>>                            mode='plain',
>>>                            interpolation_factor=4,
>>>                            projection_accuracy='high',
>>>                            show=True,
>>>                            camera_pos=[0, 1, -1],
>>>                            save2d='MgB2-nonPol.png',
>>>                            save3d='MgB2-nonPol.glb')

The main arguments in this function are procar, outcar, bands, scale, mode and st, where procar and outcar are the names of the input PROCAR and OUTCAR files respectively, bands is an array of the bands that are desired to be plotted. Note if bands = -1, the function will try to plot all the bands provided in the PROCAR file. The kmesh will be interpolated by a factor of scale in each direction. The st tag controls the spin-texture plotting, and mode determines the type of projection of colors. There are additional keyword arguments that can be accessed in the help section of this function, such as face_color, cmap, atoms, orbitals, energy, transparent, nprocess etc.

2. Surface coloring based on properties from PROCAR

Similar to the bandsplot() section one can choose to project the contribution of different properties provided in the PROCAR file, such as atom, orbital and spin contributions. The projection can be represented by different color mapping schemes chosen by the user. The projection is not restricted to only one property at a time, so it can be chosen from all the provided properties. For example, one might want to see the contribution of the orbitals \(p_x\), \(p_y\), \(p_z\) from specific atoms, this function will parse the desired contributions and projects the sum of contributions on each face. To use this functionality one has to change the mode from plain to parametric and choose the atoms, orbitals, spin that are desired to be projected.

For noncolinear calculations, this function is able to plot arrows in the direction of the spinors provided in the PROCAR file. To turn this functionality on the one can set st=True to turn the spin-texture ON. The user can choose between coloring all the arrows originated from one band with a specific color, or project the contribution of that arrow in a specific Cartesian direction. To better represent the spin-texture we use the key argument transparent=True which changes the opacity of the Fermi-surface to zero.

3. Surface coloring based on properties obtained from an external file

Similar to the previous section, this function is able to read an external file, containing information about a scalar or a vector field in BZ and project the field on the Fermi surface. This file does not need to have the same mesh grid as the PROCAR file as long as the mesh sampling is fine enough. This function performs an interpolation on the provided data and evaluates functions at the center of each face on the Fermi surface. The external file should have the following format:

band = <band number>
   <kx1>  <ky1>  <kz1>  <color1>
   <kx2>  <ky2>  <kz2>  <color2>
   <kx3>  <ky3>  <kz3>  <color3>
   ...
band = <band number>

The function matches information about the first band present in the file to the first band requested to be plotted, second band present in the file to the second band requested to be plotted, and so on.

pyprocar.scriptFermi3D.fermi3D(procar='PROCAR', outcar='OUTCAR', infile='in.bxsf', abinit_output=None, fermi=None, bands=None, interpolation_factor=1, mode='plain', supercell=[1, 1, 1], extended_zone_directions=None, colors=None, background_color='white', save_colors=False, cmap='jet', atoms=None, orbitals=None, fermi_velocity=False, fermi_velocity_vector=False, effective_mass=False, spin=None, spin_texture=False, arrow_color=None, arrow_size=0.015, only_spin=False, fermi_shift=0, projection_accuracy='normal', code='vasp', vmin=0, vmax=1, savegif=None, savemp4=None, save3d=None, save_meshio=False, perspective=True, save2d=False, show_curvature=False, curvature_type='mean', show_slice=False, slice_normal=(1, 0, 0), slice_origin=(0, 0, 0), show_cross_section_area=False, iso_slider=False, iso_range=2, iso_surfaces=10, camera_pos=[1, 1, 1], widget=False, show=True, repair=True)[source]
Parameters
  • procar (str, optional (default 'PROCAR')) – Path to the PROCAR file of the simulation e.g. procar='~/MgB2/fermi/PROCAR'

  • outcar (str, optional (default 'OUTCAR')) – Path to the OUTCAR file of the simulation e.g. outcar='~/MgB2/fermi/OUTCAR'

  • abinit_output (str, optional (default None)) – Path to the Abinit output file e.g. outcar='~/MgB2/abinit.out'

  • infile (str, optional (default infile = in.bxsf')) – This is the path in the input bxsf file e.g. infile = ni_fs.bxsf'

  • fermi (float, optional (default None)) – Fermi energy at which the fermi surface is created. In other words fermi is the isovalue at which the fermi surface is created. If not defined it is read from the OUTCAR file. e.g. fermi=-5.49

  • bands (list int, optional) – Which bands are going to be plotted in the fermi surface. The numbering is based on vasp outputs. If nothing is selected, this function will iterate over all the bands and plots the ones that cross fermi. e.g. bands=[14, 15, 16, 17]

  • interpolation_factor (int, optional) – The kpoints grid will increase by this factor and interpolated at the new points using Fourier interpolation. e.g. If the kgrid is 5x5x5, interpolation_factor=4 will lead to a kgrid of 20x20x20

  • mode (str, optional (default mode='plain')) – Defines If the fermi surface will have any projection using colormaps or is a plotted with a uniform plain color. e.g. mode='plain', mode='parametric'

  • supercell (list int, optional (default [1, 1, 1])) – If one wants plot more than the 1st brillouin zone, this parameter can be used. e.g. supercell=[2, 2, 2]

  • extended_zone_directions (list of list of size 3, optional (default None)) – If one wants plot more than brillouin zones in a particular direection, this parameter can be used. e.g. extended_zone_directions=[[1,0,0],[0,1,0],[0,0,1]]

  • colors (list str, optional) – List of colors for each band. This argument does not work when a 3d file is saved. The colors for when save3d is used, we recomend using qualitative colormaps, as this function will automatically choose colors from the colormaps. e.g. colors=['red', 'blue', 'green']

  • background_color (str, optional (default white)) – Defines the background color. e.g. background_color='gray'

  • save_colors (bool, optional (default False)) – In case the plot is saved in 3D and some property of the material is projected on the fermi surface, this argument allows the projection to be stored in the 3D file. e.g. save_colors=True

  • cmap (str, optional (default jet)) – The color map used for color coding the projections. cmap is only relevant in mode='parametric'. A full list of color maps in matplotlib are provided in this web page. https://matplotlib.org/2.0.1/users/colormaps.html

  • atoms (list int, optional) –

    atoms define the projection of the atoms on the fermi surfcae . In other words it selects only the contribution of the atoms provided. Atoms has to be a python list(or numpy array) containing the atom indices. Atom indices has to be order of the input files of DFT package. atoms is only relevant in mode='parametric'. keep in mind that python counting starts from zero. e.g. for SrVO3 we are choosing only the oxygen atoms. atoms=[2, 3, 4], keep in mind that python counting starts from zero, for a POSCAR similar to following:

    Sr1 V1 O3
    1.0
    3.900891 0.000000 0.000000
    0.000000 3.900891 0.000000
    0.000000 0.000000 3.900891
    Sr V O
    1 1 3
    direct
    0.500000 0.500000 0.500000 Sr atom 0
    0.000000 0.000000 0.000000 V  atom 1
    0.000000 0.500000 0.000000 O  atom 2
    0.000000 0.000000 0.500000 O  atom 3
    0.500000 0.000000 0.000000 O  atom 4
    

    if nothing is specified this parameter will consider all the atoms present.

  • orbitals (list int, optional) –

    orbitals define the projection of orbitals on the fermi surface. In other words it selects only the contribution of the orbitals provided. Orbitals has to be a python list(or numpy array) containing the Orbital indices. Orbitals indices has to be order of the input files of DFT package. The following table represents the indecies for different orbitals in VASP.

    s

    py

    pz

    px

    dxy

    dyz

    dz2

    dxz

    x2-y2

    0

    1

    2

    3

    4

    5

    6

    7

    8

    orbitals is only relavent in mode='parametric' e.g. orbitals=[1,2,3] will only select the p orbitals while orbitals=[4,5,6,7,8] will select the d orbitals. If nothing is specified pyprocar will select all the present orbitals.

  • fermi_velocity_vector (bool, optional (default False)) – Boolean value to calculate fermi velocity vectors on the fermi surface. Must be used with mode= “property_projection”. e.g. fermi_velocity_vector=True

  • fermi_velocity (bool, optional (default False)) – Boolean value to calculate magnitude of the fermi velocity on the fermi surface. Must be used with mode= “property_projection”. e.g. fermi_velocity=True

  • effective_mass (bool, optional (default False)) – Boolean value to calculate the harmonic mean of the effective mass on the fermi surface. Must be used with mode= “property_projection”. e.g. effective_mass=True

  • spin (list int, optional) – e.g. spin=[0]

  • spin_texture (bool, optional (default False)) – In non collinear calculation one can choose to plot the spin texture on the fermi surface. e.g. spin_texture=True

  • arrow_color (str, optional) – Defines the color of the arrows when spin_texture=True. The default will select the colors based on the color map specified. If arrow_color is selected, all arrows will have the same color. e.g. arrow_color='red'

  • arrow_size (int, optional) – As the name suggests defines the size of the arrows, when spin texture is selected. e.g. arrow_size=3

  • only_spin (bool, optional) – If only_spin=True is selected, the fermi surface is not plotted and only the spins in the spin texture is plotted.

  • fermi_shift (float, optional) – This parameter is useful when one wants to plot the iso-surface above or belove the fermi level. e.g. fermi_shift=0.6

  • projection_accuracy (str, optional (default 'normal')) – Selected the accuracy of projected properties. 'normal' and 'high' are the only two options. 'normal' uses the fast but rather inaccurate nearest neighbor interpolation, while 'high' uses the more accurate linear interpolation for the projection of the properties. e.g. projection_accuracy='high'

  • code (str, optional (default 'vasp')) – The DFT code in which the calculation is performed with. Also, if you want to read a .bxsf file set code =”bxsf” e.g. code='vasp'

  • vmin (float, optional) – The maximum value in the color bar. cmap is only relevant in mode='parametric'. e.g. vmin=-1.0

  • vmax (float, optional) – The maximum value in the color bar. cmap is only relevant in mode='parametric'. e.g. vmax=1.0

  • savegif (str, optional) – pyprocar can save the fermi surface in a gif format. savegif is the path to which the gif is saved. e.g. savegif='fermi.gif' or savegif='~/MgB2/fermi.gif'

  • savemp4 (str, optional) – pyprocar can save the fermi surface in a mp4 video format. savemp4 is the path to which the video is saved. e.g. savegif='fermi.mp4' or savegif='~/MgB2/fermi.mp4'

  • save3d (str, optional) –

    pyprocar can save the fermi surface in a 3d file format. pyprocar uses the trimesh to save the 3d file. trimesh can export files with the following formats STL, binary PLY, ASCII OFF, OBJ, GLTF/GLB 2.0, COLLADA. save3d is the path to which the file is saved. e.g. save3d='fermi.glb'

  • save_meshio (bool, optional) – pyprocar can use meshio to save any 3d format supported by it.

  • perspective (bool, optional) – To create the illusion of depth, perspective is used in 2d graphics. One can turn this feature off by perspective=False e.g. perspective=False

  • save2d (str, optional) – The fermi surface can be saved as a 2D image. This parameter turns this feature on and selects the path at which the file is going to be saved. e.g. save2d='fermi.png'

  • show_slice (bool, optional) – Creates a widget which slices the fermi surface

  • slice_origin (tuple, optional) – Origin to put the plane widget

  • slice_normal (bool, optional) – Normal of the plane widget

  • show_cross_section_area (bool, optional) – Shows the largest cross sectional area

  • show_curvature (bool, optional) – plots the curvature of the fermi surface

  • curvature_type (str, optional) – If show_curvature is True, this option chooses the type of curvature availible in Pyvista. (‘mean’, ‘gaussian’, ‘maximum’, ‘minimum’)

  • iso_slider (bool, optional) – plots a slider widget which controls which iso_energy value viewed

  • iso_range (float, optional) – If iso_slider is True, this specifies the energy range around the fermi surface to view

  • iso_surfaces (int, optional) – If iso_slider is True, this specifies how many surfaces to generate in the range specified around the fermi surface

  • camera_pos (list float, optional (default [1, 1, 1])) – This parameter defines the position of the camera where it is looking at the fermi surface. This feature is important when one chooses to use the save2d, savegif or savemp4 option. e.g. camera_pos=[0.5, 1, -1]

  • widget (, optional) –

  • show (bool, optional (default True)) – If set to False it will not show the 3D plot.

Returns

  • s (pyprocar surface object) – The whole fermi surface added bands

  • surfaces (list pyprocar surface objects) – list of fermi surface of each band