Table of Contents
This tutorial demonstrates the functionality of calculateTransmissionEigenvalues() and calculateTransmissionEigenstates(). The two functions make it possible to calculate transmission eigenvalues and eigenstates, respectively. In general, transmission eigenstates provide a direct picture of the electronic states that contribute to the conductance. For this reason they help in understanding the physics of the systems under study.
To illustrate the functionality of the calculateTransmissionEigenvalues() and calculateTransmissionEigenstates() functions, we consider how a doping atom affects the conductance of a perfect metallic nano-wire. We choose to study an aluminum wire doped with oxygen. This has already been described in the literature in Ref. [22].
The tutorial is organized as follows:
First we review some concepts and physical properties of a perfect infinite aluminum nano-wire.
Later we describe how a oxygen doping atom affects the transmission through an aluminum chain by using the two functions calculateTransmissionEigenvalues() and calculateTransmissionEigenstates().
The systems of interest are presented in Figure 29
a and b. Figure 29
a shows the perfect one dimensional aluminum nano-wire and
Figure 29 b shows the doped one
dimensional aluminum nano-wire, in which one oxygen atom is added in a bridge
position between two aluminum atoms.
|
Figure 29: (a) Undoped Al wire.(b) Oxygen doped Al wire. Aluminum atoms in gray and oxygen atom in red. The boxes display the unit cell of the electrodes. Each electrode consists of six Al atoms and the scattering region consists of 15 Al atoms.
We underline that we will use this tutorial also to review some general concepts about two-probe systems, which are presented in Li-H2-Li two-probe system and Further analysis of two-probe systems. After you have finished this tutorial, you should be familiar with the following:
construction and configuration of a two-probe system.
usage of calculateTransmissionEigenvalues() and calculateTransmissionEigenstates() functions to calculate the transmission eigenvalues and eigenstates.
Before you start on this tutorial, you should have a basic knowledge regarding methods and configuration options relevant for two-probe systems. It is also useful to be familiar with the basic elements of Python and how to use NanoLanguage functions to define the geometry of the system and the numerical parameters for the calculations. Many of these concepts are described in other tutorials like the Li-H2-Li two-probe system and Further analysis of two-probe systems.
As you have seen in the Li-H2-Li two-probe system tutorial, a two-probe system is created in three steps:
Constructing the electrodes.
Setting up the scattering region.
Combining the electrodes and scattering region into a single system.
These three steps will be followed, with the purpose of building the two-probe perfect aluminum chain. If you are comfortable with these steps, you can probably go directly to this section of the tutorial.
The two electrodes are treated as bulk systems and must therefore be constructed as such. The scattering region contains the molecules (or similar interface) located between the two electrodes. In the specific case of a perfect one dimensional aluminum chain, both the electrodes contain 6 aluminum atoms, and the scattering region contains 15 aluminum atoms (see Figure 29).
The ATK methods we need for constructing the two-probe system are located in the module ATK.TwoProbe. You gain access to these by including the following statement at the top of the ATK input file
from ATK.TwoProbe import *
instructing ATK to load all objects and functions from the ATK.TwoProbe module. Later in the tutorial, notice that every script will always start with this line.
To build a perfect one dimensional aluminum nano-wire, we first define two identical one-dimensional aluminum electrodes. However, because of periodic boundary conditions in the S1 and S2 directions, the wire will be repeated periodically in the S1S2 plane (see also Li-H2-Li two-probe system). For this reason, we need to ensure that the aluminum chain is not interacting with repeated images by making the unit cell sufficiently large in the S1 and S2 directions. The two directions S1 and S2 are illustrated in Figure 29.
As you have learned in the Li-H2-Li two-probe system tutorial, the interaction range between the aluminum chain and the repeated images depends on the basis set, and therefore the size of the electrode unit cells should be adjusted accordingly. A good procedure would be to study the separation between the repeated chains in a systematic way, by e.g. looking at the total energy of two aluminum atoms as a function of the aluminum-aluminum distance. This is beyond the scope of this tutorial. We will therefore settle with an estimate and use 10 Å electrodes unit cell along the S1 and S2 directions.
The last information we need to build the electrodes unit cell is the inter-atomic aluminum distance. We choose to use the value of 2.39 Å reported in the literature [22].
Having defined the geometrical parameters of the system, we can now construct the electrode unit cell as follows:
# The spacing between the wires should be # enough large for the wire not to interact. xy = 10.0 # The lattice distance in the wire. zs = 2.39 # The lattice vectors of the electode. unit_cell = [[ xy, 0.0, 0.0], [ 0.0, xy , 0.0], [ 0.0, 0.0, 6*zs]]*Angstrom
Notice how the use of the variables xy and
zs simplify the way we define the electrode unit cell
giving us the freedom to change the chain lattice parameters by only
modifying the script in one single place. It is always a good idea to create
structures in this way. It might be more cumbersome typing everything the
first time, but it will save time, should you want to modify the geometry of
the system later on.
With the definition of unit_cell above, we have defined
the S1 and S2 directions to
be along the x-axis and y-axis, respectively.
Having defined the electrode unit cell, we next define the positions of the aluminum atoms in the electrode unit cell. We perform this operation as follows:
# Setting up the position of the atoms in the electrode. positions = [(xy/2, xy/2, zs*0), (xy/2, xy/2, zs*1), (xy/2, xy/2, zs*2), (xy/2, xy/2, zs*3), (xy/2, xy/2, zs*4), (xy/2, xy/2, zs*5)]*Angstrom
We have chosen to position our aluminum chain in the center of the electrode unit cell.
The coordinates along the z direction, of the six aluminum atoms are integer
multiples of the zs variable.
The last thing we need to do, is to create a PeriodicAtomConfiguration for the electrode:
# Combining lattice vectors, positions and with elements. electrode = PeriodicAtomConfiguration(unit_cell,[Aluminium]*6,positions)
We use the predefined unit_cell variable, as the electrode unit
cell, and we specify the constituents (elements) of the electrodes as six aluminum atoms
positioned as defined in the positions list.
The geometry of the electrodes is now well-defined, and we turn to the definition of the central region, located between the two aluminum probes. In our case, this will consist of a chain of 15 aluminum atoms. For the time being, the central region is a perfect chain of aluminum atoms, but later we will introduce one doping atom with the idea of studying the effects of the doping on the conductance of the metallic wire. Having this in mind, we choose a central region sufficiently large that the presence of the scattering oxygen atom will not be felt inside the actual electrodes. We have previously seen that this is a fundamental assumption in the two-probe algorithm used in ATK, namely that the electronic structure of the electrodes is bulk-like (Li-H2-Li two-probe system).
As for the size of the electrode unit cells in the S1 and S2 directions, the exact amount of screening layers required in the calculation, can be hard to estimate up front. Often, one has to study it systematically, and increase the number of screening layers until the results no longer change. This is beyond the scope of this tutorial. and we simply note that 15 aluminum atoms are appropriate for our purpose.
The scattering region can be built as follows:
# Setting up the central region positions for the undoped system. scattering_positions = [(xy/2, xy/2, zs*0), (xy/2, xy/2, zs*1), (xy/2, xy/2, zs*2), (xy/2, xy/2, zs*3), (xy/2, xy/2, zs*4), (xy/2, xy/2, zs*5), (xy/2, xy/2, zs*6), (xy/2, xy/2, zs*7), (xy/2, xy/2, zs*8), (xy/2, xy/2, zs*9), (xy/2, xy/2, zs*10), (xy/2, xy/2, zs*11), (xy/2, xy/2, zs*12), (xy/2, xy/2, zs*13), (xy/2, xy/2, zs*14)]*Angstrom
Once again, notice how the coordinates of the atoms in the scattering region
are defined using the xy and zs variables.
One important thing is that the z coordinates of the atoms inside the central
region are integer multiple of zs variable, starting from
0.0. This is not a problem, because ATK automatically aligns the first and last
atom in the scattering region with the last and first atom in the electrodes,
respectively.
We are now ready to combine the three constituents needed to construct the
two-probe system: the two electrodes and the scattering region. We do this
using the TwoProbeConfiguration function.
Notice that we use the same object electrode to represent both
the electrodes because our electrodes are physically identical. ATK will
automatically position the right electrode relative to the central region.
# Creating the perfect Aluminium wire. aluminum_wire = TwoProbeConfiguration((electrode,electrode), [Aluminium]*15, scattering_positions)
The constructed TwoProbeConfiguration
object stored in the variable aluminum_wire can now be used to
perform a self-consistent calculation on the system.
We have now discussed the details of the different steps that are needed for setting up the two-probe system. Combining all the code snippets discussed above, we end up with the following script for completing the task
from ATK.TwoProbe import * # The spacing between the wires should be # enough large for the wire not to interact. xy = 10.0 # The lattice distance in the wire. zs = 2.39 # The lattice vectors of the electode. unit_cell = [[ xy, 0.0, 0.0], [ 0.0, xy , 0.0], [ 0.0, 0.0, 6*zs]]*Angstrom # Setting up the position of the atoms in the electrode. positions = [(xy/2, xy/2, zs*0), (xy/2, xy/2, zs*1), (xy/2, xy/2, zs*2), (xy/2, xy/2, zs*3), (xy/2, xy/2, zs*4), (xy/2, xy/2, zs*5)]*Angstrom # Combining lattice vectors, positions and with elements. electrode = PeriodicAtomConfiguration(unit_cell,[Aluminium]*6,positions) # Setting up the central region positions for the undoped system. scattering_positions = [(xy/2, xy/2, zs*0), (xy/2, xy/2, zs*1), (xy/2, xy/2, zs*2), (xy/2, xy/2, zs*3), (xy/2, xy/2, zs*4), (xy/2, xy/2, zs*5), (xy/2, xy/2, zs*6), (xy/2, xy/2, zs*7), (xy/2, xy/2, zs*8), (xy/2, xy/2, zs*9), (xy/2, xy/2, zs*10), (xy/2, xy/2, zs*11), (xy/2, xy/2, zs*12), (xy/2, xy/2, zs*13), (xy/2, xy/2, zs*14)]*Angstrom # Creating the perfect Aluminium wire. aluminum_wire = TwoProbeConfiguration((electrode,electrode), [Aluminium]*15, scattering_positions) vnl_file = VNLFile("perfect_alwire.vnl") vnl_file.addToSample(aluminum_wire,"perfect_alwire")
You can now download the script and process it with ATK by issuing the command
atk perfect_alwire-setup.py
At the and of the script we added the required lines to export
the TwoProbeConfiguration to a
VNLFile. Therefore the script will create
the file perfect_alwire.vnl that contains the atomic configuration
of our two-probe system.
Once you have processed the script perfect_alwire-setup.py
with ATK, a file perfect_alwire.vnl should be located on
your disk. This VNLFile can be used for
starting a self consistent calculation. The first thing we need to do is
reading the information stored into the VNLFile.
We can do this as follows:
# Read the atomic configuration from a VNL file vnl_file = VNLFile("perfect_alwire.vnl") configurations = vnl_file.readAtomicConfigurations() perfect_wire = configurations["perfect_alwire"]
In this way, we notice that the variable perfect_wire contains
the two-probe configuration.
The next step is to set up the parameters for performing the self consistent field calculation (SCF). We will almost use the default parameters in order not to remove focus from the essentials of the two-probe systems. However, we will set up some parameters, like the mesh cutoff, the Brillouin zone integration parameters and the basis set. In particular, we decide to use a mesh cut-off of 150 Rydberg, a (1x1x20) mesh of k-points for the integration of the Brillouin zone and a DoubleZetaPolarized basis set. Having this in mind, we can set the electrode parameters as follows :
# Setting the electrode parameters bz_int_param = brillouinZoneIntegrationParameters( (1,1,20) ) electrode_parameters = ElectrodeParameters( brillouin_zone_integration_parameters= bz_int_param )
Now that we have defined the electrode parameters, we can create a TwoProbeMethod in the following way:
# Creating the TwoProbeMethod ele_den_para = electronDensityParameters(mesh_cutoff=150*Units.Ry) twoprobe_method = TwoProbeMethod( (electrode_parameters,electrode_parameters), electron_density_parameters=ele_den_para, basis_set_parameters=basisSetParameters( type=DoubleZetaDoublePolarized) )
|
|
Note |
|---|---|
|
Notice that we are using the same |
Once we have defined the TwoProbeMethod we can finally call the executeSelfConsistentCalculation() function to perform a self consistent field calculation. This can be done as follows:
# Execute the Self Consistent Field scf = executeSelfConsistentCalculation( perfect_wire, twoprobe_method, runtime_parameters=runtimeParameters(verbosity_level=1, checkpoint_filename='perfect_chain.nc'))
Finally, the full script:
from ATK.TwoProbe import * # Read the atomic configuration from a VNL file vnl_file = VNLFile("perfect_alwire.vnl") configurations = vnl_file.readAtomicConfigurations() perfect_wire = configurations["perfect_alwire"] # Setting the electrode parameters bz_int_param = brillouinZoneIntegrationParameters( (1,1,20) ) electrode_parameters = ElectrodeParameters( brillouin_zone_integration_parameters= bz_int_param ) # Creating the TwoProbeMethod ele_den_para = electronDensityParameters(mesh_cutoff=150*Units.Ry) twoprobe_method = TwoProbeMethod( (electrode_parameters,electrode_parameters), electron_density_parameters=ele_den_para, basis_set_parameters=basisSetParameters( type=DoubleZetaDoublePolarized) ) # Execute the Self Consistent Field scf = executeSelfConsistentCalculation( perfect_wire, twoprobe_method, runtime_parameters=runtimeParameters(verbosity_level=1, checkpoint_filename='perfect_chain.nc'))
You can now download the script and process it with ATK by executing the command
atk perfect_alwire-scf.py
At the end of the self consistent field the
perfect_chain.nc file is created. This file contains
the results of the calculation stored in the
NetCDF data format. This
file is important for post-processing calculations. In fact, later in this
tutorial, we will use it in order to calculate some physical quantities
without having to perform again a new SCF calculation.
Before calculating the transmission eigenchannels, we can take a look at the
transmission spectrum of our perfect aluminum wire. We have seen the use of
the calculateTransmissionSpectrum() in the
Further analysis of two-probe systems tutorial.
With this purpose, we now load the perfect_chain.nc and
use the information we have stored in it in order to calculate the transmission
spectrum of the perfect Al wire.
The first thing we need to do is to load the stored results using the
restoreSelfConsistentCalculation() function.
# Restoring the SCF from the previous calculation scf = restoreSelfConsistentCalculation('perfect_chain.nc')
Once we have loaded the stored information in the perfect_chain.nc
file, we need to define a range of energies over which the spectrum should be calculated.
We therefore create a list of energies we want to scan. In this specific case
we choose to scan the region between -8 and 3 eV, as it is done in [22] .
This can be done as follows:
# Specify the range of energies energy_scan = [ i/200.0*Units.eV for i in range(-1601,601)]
We now pass this list of energies, energy_scan, to the
function calculateTransmissionSpectrum()
to perform the calculation :
# Calculate the transmission spectrum bz_int_parm = brillouinZoneIntegrationParameters( (1,1) ) spectrum = calculateTransmissionSpectrum( self_consistent_calculation=scf, energies = energy_scan,
We notice that since our system effectively is one-dimensional, we only require one k-point in the transverse direction. This is actually the default value for the k-point sampling, but it is instructive to include it explicitly. The final script for calculating the transmission spectrum of a perfect Al wire is then:
from ATK.TwoProbe import * # Restoring the SCF from the previous calculation scf = restoreSelfConsistentCalculation('perfect_chain.nc') # Specify the range of energies energy_scan = [ i/200.0*Units.eV for i in range(-1601,601)] # Calculate the transmission spectrum bz_int_parm = brillouinZoneIntegrationParameters( (1,1) ) spectrum = calculateTransmissionSpectrum( self_consistent_calculation=scf, energies = energy_scan, brillouin_zone_integration_parameters=bz_int_parm) # Save the transmission spectrum to VNL file vnlfile = VNLFile("perfect_alwire_trans.vnl") vnlfile.addToSample(spectrum,'perfec_alwire_trans') # Print at screen the Transmission Spectrum print 'Transmission Spectrum' print '-----------------------------------------------------------------------' print 'Energies(eV) Coefficients' for i in range(len(spectrum.energies())): print '%17.3f %17.6f' %( spectrum.energies()[i].inUnitsOf(Units.eV), spectrum.coefficients()[i])
perfect_alwire-transm-spectrum.py
Downloading and executing the script with the following command
atk perfect_alwire-transm-spectrum.py
you should get some output similar to this
Transmission Spectrum ----------------------------------------------------------------------- Energies(eV) Coefficients -8.005 0.000000 -8.000 0.000000 -7.995 0.000000 -7.990 0.000000 -7.985 0.000000 -7.980 0.000000 ..... ........ 0.000 1.998907 0.005 1.998914 0.010 1.998920 0.015 1.998927 0.020 1.998933 0.025 1.998939 ..... ........
The spectrum can now be studied and plotted by importing the file
perfect_alwire_trans.vnl into VNL. Alternatively, the
data points could be printed to the screen or a file and visualized using
your favorite visualization tool. The resulting plot is illustrated in
Figure 30
Notice that because we are studying a perfect aluminum wire, the
conductance is quantized in integer steps of
as expected from the Landauer formula
, where
denotes the number of bands existing at the energy
.
We finally come to the core of this tutorial. We just performed the self consistent calculation on our perfect aluminum one dimensional nano-wire. It's now time to calculate the transmission eigenvalues and eigenstates.
Let us start with the calculation of transmission eigenvalues in order to
see which eigenvectors contribute to the conductance of the perfect Al wire.
Having this in mind, we need to write a script in which
we first load the stored information into perfect_chain.nc
and later use the function calculateTransmissionEigenvalues()
to calculate the transmission eigenvalues. This can be done as follows :
from ATK.TwoProbe import * # Look for the Eigenvalues at the Fermi level energy = 0.00000*Units.eV # Restore the calculation scf = restoreSelfConsistentCalculation('perfect_chain.nc') # k-point list k_point_list = [(0.0,0.0)] # Calculate the Transmission eigenvalues eigenvalues = calculateTransmissionEigenvalues( scf, energy, quantum_numbers=(k_point_list))[0] # Print the transmission eigenvalues for i in range(len(eigenvalues)): print 'Eigenvalue %3i %10.5f' %(i, eigenvalues[i])
perfect_alwire-transm-eigenvalues.py
The energy variable defines the energy at which we want to
calculate the transmission eigenvalues. Because we are interested in the
transmission eigenvalues at the Fermi level, we set it to zero.
Moreover, because we are considering a one-dimensional aluminum wire,
we just specify one k-point, (0.0,0.0) in the plane perpendicular to the wire.
As specified in the reference manual for
calculateTransmissionEigenvalues() function,
the dimensionality of the returned array, in this case eigenvalues,
corresponds to the number of elements specified in the quantum_numbers
variable. Therefore if we want the list of eigenvalues, we need to ask for the first
column in the eigenvalues variable.
Downloading and executing the script with the following command
atk perfect_alwire-transm-eigenvalues.py
you should obtain a similar output
Eigenvalue 0 0.99943 Eigenvalue 1 0.99943
We notice that only the first two eigenvalues have a value different from zero and very close to 1. From a physical point of view, the transmission eigenvalues represent the probability that the incoming wave function is transmitted into the other side of the scattering region. Therefore a value close to one, means that the incoming wave function is not scattered and will contribute to the conductance. For this reason, we are now going to plot the transmission eigenvector associated to the first two eigenvalues.
As usual we restore a previous self consistent field calculation loading the file
perfect_chain.nc. Once we have restored the calculation we can use the
calculateTransmissionEigenstates() function, to
calculate the transmission eigenvectors. Notice that in the variable
quantum_numbers we specify the index of the eigenvector we are interested
in (0 and 1) and the k-point of interest.
The script is easy to build as follow:
from ATK.TwoProbe import * # Look for the eigenvector at the Fermi level energy = 0.0*Units.eV # Restore the SCF calculation scf = restoreSelfConsistentCalculation('perfect_chain.nc') # Define output on VNL file results = VNLFile('perfect_alwire.vnl') # Calculate the transmission eigenstates index_list = [0,1] kpoint_list = [(0.0,0.0)] for index in index_list: transmission_eigenstate = calculateTransmissionEigenstates( scf, energy, quantum_numbers=(index,kpoint_list) ) results.addToSample(transmission_eigenstate[0],"perfect_alwire")
perfect_alwire-transm-eigenvectors.py
Notice that after calculating the first two transmission eigenchannels, we save them into a VNLFile. In this way you can visualize them easily with VNL (see Figure 31).
|
Figure 31: Plot from VNL, of the transmission eigenchannels. (a) Isosurface plot of the first eigenvector, corresponding to the first eigenvalue. The value of the isosurface is equal to 0.01. Axial view. (b) Contour plot of the first eigenvector in the axial view. (c) Contour plot of the second eigenvector in the axial view.
From Figure 31 we can see that the
conductance of a perfect aluminum wire is through eigenstates originating from the
superimposition of aluminum p states. These eigenstates appear to have a
symmetry in the plane orthogonal to the transport direction.
The symmetry of these
orbitals can be altered by the presence
of a doping atom as we will see in the next paragraphs.
|
|
Note |
|---|---|
|
The transmission eigenchannels module depends on a new method for calculating the scattering states of the twoprobe system. The method can sometimes be sensitive to parameters such as the energy infinitesimal. For this reason, to check that the algorithm is performing correctly at a particular quantum number, you can verify that the total sum of the transmission eigenvalues is equal to the total sum of the transmission coefficients calculated using the default method in ATK.TwoProbe. |
We have just seen that the conductance of a perfect aluminum wire is trough eigenstates originating from the superimposition of p aluminum states. Now, we will introduce one oxygen doping atom and we will study how this will effect the conductance. We will essentially introduce some modifications in the scripts we have created so far.
To assemble a two-probe system for a doped aluminum wire, we first
copy the perfect_alwire-setup.py into
imperfect_alwire-setup.py
and modify the new script so that one oxygen atom is added to the central region.
We choose to add one oxygen atom in a bridge position between two
aluminum atoms in the chain as you can see in Figure 32.
Notice that for the purpose of this tutorial, the position of the oxygen atom
in the x-y plane is randomly chosen. A better strategy is
optimize the oxygen atom position by performing a geometry optimization.
Good examples of how to perform a geometry optimization can be found on
Optimizing a lithium chain and
Reaction path optimization using the Nudged Elastic Band method
The new script is now:
from ATK.TwoProbe import * # The spacing between the wires - the distance should be large # enough for the wire not to interact. xy = 10.0 # The lattice distance in the wire. zs = 2.39 # The lattice vectors of the electode. unit_cell = [[ xy, 0.0, 0.0], [ 0.0, xy , 0.0], [ 0.0, 0.0, 6*zs]]*Angstrom # Setting up the position of the atoms in the electrode. positions = [(xy/2, xy/2, zs*0), (xy/2, xy/2, zs*1), (xy/2, xy/2, zs*2), (xy/2, xy/2, zs*3), (xy/2, xy/2, zs*4), (xy/2, xy/2, zs*5)]*Angstrom # Combining the lattice vectors, and positions together with elements. electrode = PeriodicAtomConfiguration(unit_cell,[Aluminium]*6,positions) # Setting up the scattering positions for the doped system. # Doping is placed a small distance from the chain in the middle # of the scattering region. scattering_positions = [(xy/2, xy/2, zs*0), (xy/2, xy/2, zs*1), (xy/2, xy/2, zs*2), (xy/2, xy/2, zs*3), (xy/2, xy/2, zs*4), (xy/2, xy/2, zs*5), (xy/2, xy/2, zs*6), (xy/2, xy/2, zs*7), (xy/2, xy/2+1.2,zs*7.5), (xy/2, xy/2, zs*8), (xy/2, xy/2, zs*9), (xy/2, xy/2, zs*10), (xy/2, xy/2, zs*11), (xy/2, xy/2, zs*12), (xy/2, xy/2, zs*13), (xy/2, xy/2, zs*14)]*Angstrom # Creating the perfect Aluminium wire. aluminum_wire = TwoProbeConfiguration((electrode,electrode), [Aluminium]*8+[Oxygen]+[Aluminium]*7, scattering_positions) vnl_file = VNLFile("imperfect_alwire.vnl") vnl_file.addToSample(aluminum_wire,"imperfect_alwire")
In the perfect_alwire-setup.py script, we added a line
into the scattering_positions python list, to define the
oxygen atom x,y,z position. Moreover we modified the list of elements into the
TwoProbeConfiguration function.
In the new script the central region contains 15 aluminum atoms and one
oxygen atom.
|
Figure 32: Central region of the oxygen doped aluminum wire. Gray and red are aluminum and oxygen atoms respectively.
Downloading the script and processing it with ATK with the following command :
atk imperfect_alwire-setup.py
a VNLFile named
imperfect_alwire.vnl containing the setup of
the new two-probe system should be located on you disk.
The imperfect_alwire.vnl VNLFile
can be now used for starting a self consistent calculation. The script to
perform the SCF is similar to that one used for the perfect aluminum wire and
can be obtained copying perfect_alwire-scf.py into
imperfect_alwire-scf.py. After that, we need to modify
the new script in order to be able to load the right VNLFile.
Here the final script :
from ATK.TwoProbe import * # Read the Atomic configuration from a VNL file vnl_file = VNLFile("imperfect_alwire.vnl") configurations = vnl_file.readAtomicConfigurations() perfect_wire = configurations["imperfect_alwire"] # Setting the Electrode parameters bz_int_param = brillouinZoneIntegrationParameters( (1,1,20) ) electrode_parameters = ElectrodeParameters( brillouin_zone_integration_parameters= bz_int_param ) # Creating the TwoProbeMethod ele_den_para = electronDensityParameters(mesh_cutoff=150*Units.Ry) twoprobe_method = TwoProbeMethod( (electrode_parameters,electrode_parameters), electron_density_parameters=ele_den_para, basis_set_parameters=basisSetParameters( type=DoubleZetaDoublePolarized) ) # Execute the Self Consistent Field scf = executeSelfConsistentCalculation(perfect_wire, twoprobe_method, runtime_parameters=runtimeParameters(verbosity_level=1, checkpoint_filename='imperfect_chain.nc'))
Notice that in the new script, we read the atomic configuration from
imperfect_alwire.vnl and we store the self consistent
field information into the imperfect_chain.nc
Download the script and process it with ATK by issuing the command
atk perfect_alwire-scf.py
Once the self consistent field is finished, the imperfect_chain.nc
should be present on your disk. As we did in the previous part of this tutorial, we will
use this NetCDF file as starting point to
calculate the transmission spectrum and the transmission eigenchannels.
After the self consistent field (SCF) calculation is finished, we
can load the imperfect_chain.nc and use the information
we have stored in it in order to calculate the transmission spectrum of the perfect Al wire.
The presence of one adsorbate atom on the aluminum chain will cause the
scattering of the Bloch electrons and consequently we expect that the
sharp and quantized transmission spectrum for the perfect aluminum wire
(see Figure 30) will be destroyed.
We will use is the following script:
from ATK.TwoProbe import * # Restoring the SCF from the previous calculation scf = restoreSelfConsistentCalculation('imperfect_chain.nc') # Specify the range of energies energy_scan = [ i/200.0*Units.eV for i in range(-1601,601)] # Calculate the Transmission Spectrum bz_int_parm = brillouinZoneIntegrationParameters( (1,1) ) spectrum = calculateTransmissionSpectrum( self_consistent_calculation=scf, energies = energy_scan, brillouin_zone_integration_parameters=bz_int_parm) # Save the Transmission Spectrum to VNL file vnlfile = VNLFile("imperfect_alwire_trans.vnl") vnlfile.addToSample(spectrum,'imperfect_alwire_trans') # Print at screen the Transmission Spectrum print 'Transmission Spectrum' print '-----------------------------------------------------------------------' print 'Energies(eV) Coefficients' for i in range(len(spectrum.energies())): print '%17.3f %17.6f' %( spectrum.energies()[i].inUnitsOf(Units.eV), spectrum.coefficients()[i])
imperfect_alwire-transm-spectrum.py
Even for the case of doped aluminum wire, we will scan the region between -8.0 and 3.0 eV in a way that the transmission spectrum could be directly compared with the transmission spectrum of the perfect aluminum wire. Download and execute the script with the following command:
atk imperfect_alwire-transm-spectrum.py
The obtained spectrum can be studied and plotted by importing the file
imperfect_alwire_trans.vnl into VNL. Alternatively,
the data points could be printed to the screen or a file and visualized using
your favorite visualization tool. In Figure 33 we plot the
transmission spectra of both the perfect and doped wires.
|
Figure 33: Transmission spectrum of both the perfect and doped aluminum wires. Blue and read are perfect and doped wires respectively.
Notice that as expected the oxygen atom adsorbed in the bridge position lowers the conductance of the aluminum wire, Figure 33.
In order to be able to plot the transmission eigenchannels, we need to
find the eigenstates that contribute to the conductance of the doped
aluminum wire. We copy perfect_alwire-transm-eigenvalues.py
into imperfect_alwire-transm-eigenvalues.py and
we modify the new script to load the imperfect_chain.nc file.
Thus :
from ATK.TwoProbe import * # Look for the Eigenvalues at the Fermi level peak = 0.00000*Units.eV # Restore the calculation scf = restoreSelfConsistentCalculation('imperfect_chain.nc') # k-point list k_point_list = [(0.0,0.0)] # Calculate the Transmission eigenvalues eigenvalues = calculateTransmissionEigenvalues( scf, peak, quantum_numbers=(k_point_list))[0] # Print the transmission eigenvalues for i in range(len(eigenvalues)): print 'Eigenvalue %3i %10.5f' %(i, eigenvalues[i])
imperfect_alwire-transm-eigenvalues.py
By downloading and executing the script with the following command
atk imperfect_alwire-transm-eigenvalues.py
You should obtain a similar output to
Eigenvalue 0 0.17252 Eigenvalue 1 0.00267
As well as in the case of the perfect aluminum wire, we notice that only the first two eigenvalues have a value different from zero. However, we notice that in the case of the doped aluminum wire the first two transmission eigenvalues have much lower values. In particular, the first one has a value of about 0.17 and the second one is almost zero. From a physical point of view, this means that the incoming wave functions corresponding to both the first and second eigenvalue are strongly scattered. As a consequence of this, a lower conductance is observed for the doped aluminum wire compared to the perfect one. To visualize this behavior, we calculate the first two transmission eigenstates and plot them with VNL, just as we did for the perfect aluminum chain.
We copy perfect_alwire-transm-eigenvectors.py
into imperfect_alwire-transm-eigenvectors.py and
we modify the new one to load the imperfect_chain.nc.
The new script is:
from ATK.TwoProbe import * # Look for the eigenvector at the Fermi level energy = 0.0*Units.eV # Restore the SCF calculation scf = restoreSelfConsistentCalculation('imperfect_chain.nc') # Define output on VNL file results = VNLFile('imperfect_alwire.vnl') # Calculate the transmission eigenstates index_list = [0,1] kpoint_list = [(0.0,0.0)] for index in index_list: transmission_eigenstate = calculateTransmissionEigenstates( scf, energy, quantum_numbers=(index,kpoint_list) ) results.addToSample(transmission_eigenstate[0],"imperfect_alwire")
imperfect_alwire-transm-eigenvectors.py
Download the script and execute it with the following command
atk imperfect_alwire-transm-eigenvectors.py
The first two transmission eigenstates are saved into a
VNLFile imperfect_alwire.vnl
and plotted in Figure 34.
|
Figure 34: Isosurface plots from VNL. (a) and (b) are isosurface plots of the first and second transmission eigenstates of the oxygen doped aluminum chain, respectively. The values of the isosurfaces are 0.01.
From Figure 34, we notice that the first two transmission eigenstates are no longer symmetric and periodic as in the case of the perfect aluminum wire. Moreover, the first transmission eigenstate is scattered but still has a transmission probability which is different from zero. This can be easily noticed in the isosurface plot since the scattered wave function (blue isosurface) is still able to penetrate the central region and enter in the right electrode. At the contrary, the second transmission eigenstate has a transmission probability almost close to zero and this is also represented in the Figure 34. In fact, the second transmission eigenstate (pink isosurface) is decaying just after the oxygen atom and is not able to reach the right electrode. Its contribution to the conductance of the doped aluminum wire is negligible.
|
|
Note |
|---|---|
|
Once again, we notice that the transmission eigenchannels module depends on a new method for calculating the scattering states of the twoprobe system. The method can sometimes be sensitive to parameters such as the energy infinitesimal. For this reason, to check that the algorithm is performing correctly at a particular quantum number, you can verify that the total sum of the transmission eigenvalues is equal to the total sum of the transmission coefficients calculated using the default method in ATK.TwoProbe. |
In this tutorial, we have reviewed how a two-probe system is constructed, initialized, and how transmission eigenvalues and eigenstates can be calculated. Specifically, we have discussed the following key issues:
How to construct electrodes and scattering regions.
Combining electrodes and scattering regions into a two-probe configuration.
Performing a self-consistent calculation for a two-probe system.
How to use calculateTransmissionEigenvalues() and calculateTransmissionEigenstates().