Name

DeviceDensityOfStates — Class for representing the Device Density of States for a given configuration and calculator.

Synopsis

Namespace: NanoLanguage
DeviceDensityOfStates(
configuration,
energies,
kpoints,
contributions,
self_energy_calculator,
energy_zero_parameter,
infinitesimal
)

Description

Constructor for the Device Density of States object.

DeviceDensityOfStates Arguments

configuration

The two-probe configuration with attached calculator for which the density of states. should be calculated.

Type: DeviceConfiguration

Default: None
energies

The energies for which the density of states should be calculated.

Type: List containing elements of the type PhysicalQuantity with energy unit.

Default: numpy.linspace(-2.,2.,200)*eV
kpoints

The k-points for which the density of states should be calculated.

Type: MonkhorstPackGrid

Default: MonkhorstPackGrid(nx,ny), where nx, ny is the sampling used for the self consistent calculation.
contributions

The density contributions to include in the density of states.

Type: Left | Right | All

Default: All
self_energy_calculator

The SelfEnergyCalculator to be used for the density of states.

Type: DirectSelfEnergy() | RecursionSelfEnergy() | KrylovSelfEnergy()

Default: DirectSelfEnergy()
energy_zero_parameter

Specifies the choice for the energy zero.

Type: AverageFermiLevel | AbsoluteEnergy.

Default: AverageFermiLevel
infinitesimal

Small energy, used to move the density of states calculation away from the real axis. This is only relevant for recursion-style self-energy calculators.

Type: PhysicalQuantity with energy unit.

Default: 1.0e-6*eV

DeviceDensityOfStates Methods

A DeviceDensityOfStates object provides the following methods:

  • bias(): Return the applied bias

  • electrodeFermiLevels(): Return the electrodes Fermi levels in absolute energies

  • electrodeFermiTemperatures(): Return the electrodes Fermi temperature used in this density of states

  • electrodeVoltages(): Return the electrode_voltages used in this density of states spectrum

  • elements(): Query for the elements in the configuration used for generating the dos

  • energies(): Return the energies used in this density of states

  • energyZero(): Return the energy zero used for the energy scale in this density of states

  • evaluate(spin, projection_list): Return the density of states.

    spin

    The spin to select.

    Type: Spin.Sum | Spin.Up | Spin.Down |

    Default: Spin.Sum
    projection_list

    ProjectionList with projections to include in the density of states.

    Type: ProjectionList

    Default: ProjectionList(range(n_left, n_central-n_right))
  • infinitesimal(): Return the infinitesimal used for calculating the density of states

  • nlprint(stream): Print a string containing an ASCII table useful for plotting the density of states

    stream

    The stream the density of states should be written to.

    Type: A stream that supports strings being written to using 'write'.

    Default: sys.stdout
  • numberOfElectrodeAtoms(): Query for the number of electrode atoms in the configuration used for generating the dos

  • spins(): Return the spins used in this density of states

Usage Examples

Calculate the device density of states (DDOS) of a Li-H2-Li system.

# setup Huckel calculation for Li-H2-Li device

electrode_lattice = UnitCell([8., 0., 0.]*Angstrom,
                             [0., 8., 0.]*Angstrom,
                             [0., 0., 8.7]*Angstrom)

electrode_elements = [Lithium, Lithium, Lithium]
electrode_coordinates = [ [ 4.,  4., 1.45+i*2.9] for i in range(3)]*Angstrom

electrode = BulkConfiguration(
    bravais_lattice=electrode_lattice,
    elements=electrode_elements,
    cartesian_coordinates=electrode_coordinates
    )

lattice = UnitCell([8., 0., 0.]*Angstrom,
                   [0., 8., 0.]*Angstrom,
                   [0., 0., 37.376]*Angstrom)

elements = [Lithium,]*6 +[Hydrogen,]*2+[Lithium,]*6

coordinates = [ [ 4.,  4., 1.45+i*2.9] for i in range(6)] + \
              [ [ 4.,  4., 18.286+i*0.8] for i in range(2)] + \
              [ [ 4.,  4., 21.426+i*2.9] for i in range(6)]

central_region = BulkConfiguration(
    bravais_lattice=lattice,
    elements=elements,
    cartesian_coordinates=coordinates*Angstrom
    )

device_configuration = DeviceConfiguration(
    central_region,
    [electrode, electrode]
    )

calculator = DeviceHuckelCalculator(
    iteration_control_parameters = NonSelfconsistent,
    )

device_configuration.setCalculator(calculator)

device_configuration.update()
nlsave('device.nc', device_configuration)

#setup energies, and calculate DOS
energies = numpy.linspace(-2,3,100) * eV
dos = DeviceDensityOfStates(device_configuration, energies=energies)
nlsave('device.nc', dos)

device.py

[Note] Note
The spectrum can be visualized by selecting the file device.nc in the Result Browser in VNL

Plot the projected density of states (PDOS) for the non-surface atoms of the central region.

# read the dos
dos = nlread('device.nc',DeviceDensityOfStates)[0]
conf = nlread('device.nc', DeviceConfiguration)[0]
energies = dos.energies()

# calculate projection on atoms in the central region
dos_projection = [dos.evaluate(projection_list = ProjectionList([i])) \
                  for i in range(3,11)]

# plot the projections
import pylab
pylab.figure()
for i in range(3,11):
    label = conf.elements()[i].symbol()+'('+str(i)+')'
    pylab.plot(energies.inUnitsOf(eV),dos_projection[i-3].inUnitsOf(eV**-1), \
               label = label)
pylab.legend()    
pylab.xlabel("Energy (eV)")
pylab.ylabel("dos (1/eV)")
pylab.show()

dos.py

The density of states of the Li-H2-Li systems projected onto the atoms in the central region. Note that half of the curves are not visible because they fall on top of the other curves, due to symmetry.

Figure 11: The density of states of the Li-H2-Li systems projected onto the atoms in the central region. Note that half of the curves are not visible because they fall on top of the other curves, due to symmetry.


Calculate the contribution to the density of states from scattering states originating in the left electrode

conf = nlread('device.nc',DeviceConfiguration)[0]

#setup energies
energies = numpy.linspace(-2,3,100) * eV

#calculate the dos from the Left electrode
dos = DeviceDensityOfStates(conf, energies=energies, contributions=Left)

#calculate the projections on the atoms in the central region
dos_projection = [
     dos.evaluate(projection_list = ProjectionList([i])) for i in range(3,11)
     ]

#plot the data
import pylab
pylab.figure()
for i in range(3,11):
    label = conf.elements()[i].symbol()+'('+str(i)+')'
    pylab.plot(
        energies.inUnitsOf(eV),
	dos_projection[i-3].inUnitsOf(eV**-1),
	label=label
	)
pylab.legend()
pylab.xlabel("Energy (eV)")
pylab.ylabel("dos (1/eV)")
pylab.show()

dos_left.py

The density of states from the left electrode of the Li-H2-Li systems projected onto the atoms in the central region. Note how the density of states in the right lithium atoms is reduced, due do damping of the propagation by the hydrogen molecule.

Figure 12: The density of states from the left electrode of the Li-H2-Li systems projected onto the atoms in the central region. Note how the density of states in the right lithium atoms is reduced, due do damping of the propagation by the hydrogen molecule.


k-point average of the DOS

     dos =  DeviceDensityOfStates(conf, kpoints = MonkhorstPackGrid(4,4),
     energies=energies, contributions=Left)
  

Notes

The routine utilizes the symmetries of the configuration to reduce the computational load for k-point averaging.

The device density of states (DDOS) D(E) is computed via the spectral density matrix \rho(E)=\rho^L(E)+\rho^R(E) (cf. the section called “The non-equilibrium Green's function (NEGF) method”) where L/R denotes the contribution from the left/right electrode (see the keyword contributions above).

The local density of states (LDOS) is now defined as

\displaystyle

        D(E,\mathbf{r}) = \sum_{ij} \rho_{ij}(E) \phi_i(\mathbf{r})\phi_j(\mathbf{r}),

where we note that the basis set orbitals \phi_i(\mathbf{r}) are real functions in ATK through the use of solid harmonics.

The device density of states is then obtained by integrating the LDOS over all space:

\displaystyle

        D(E) = \int d\mathbf{r} D(E,\mathbf{r}) = \sum_{ij} \rho_{ij}(E) S_{ij},

where S_{ij}=\int \phi_i(\mathbf{r})\phi_j(\mathbf{r})d\mathbf{r} is the overlap matrix. Introducing M_{i}(E)=\sum_j \rho_{ij}(E) S_{ij} we may write this as

\displaystyle

        D(E) = \sum_i M_i(E),

where thus M_i(E) can be seen as the contribution to the DDOS from orbital i. This can be summed over orbitals of a particular angular momentum, and/or over one or several atoms, to give the projected device density of states (PDDOS), which also can be plotted in VNL. The projection is specified via the projection_list keyword to the evaluate() method (see above).