Table of Contents
This tutorial shows how to perform the geometry optimization of a two-probe system, in our case a Li-H2-Li system very similar to the one presented in Li-H2-Li two-probe system, using the calculateOptimizedAtomicGeometry() function.
The optimization of a TwoProbeConfiguration in the current version of ATK is based on a procedure consisting of the following steps:
Extract the atomic configuration of the equivalent bulk system, which is the periodic atom configuration comprised of the two-probe electrodes and scattering region.
Relax this equivalent bulk system.
Transform the equivalent bulk configuration back to a two-probe configuration.
For a detailed description of the algorithm used to perform the geometry relaxation, see calculateOptimizedAtomicGeometry().
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 e.g. in Li-H2-Li two-probe system.
The initial configuration is created in the same way as in
Li-H2-Li two-probe system.
The main difference here concerns the positions of the atoms close to the center
of the scattering region. In order to have a configuration which is
not an equilibrium one, the two hydrogen atoms are brought
to a distance of 0.2 Å and their first-neighbor lithium atoms are pushed closer
to a distance of 3.0 Å. These values have been chosen in order to generate a
configuration which is obviously highly unstable, due to the
too short distance between the two hydrogen atoms.
# Setup the two-probe scattering region # Distances between Li-H and H-H # (dist_HH + 2*dist_LiH = 3.0 Angstrom) dist_HH = 0.2 dist_LiH = 1.5 - 0.5 * dist_HH
For the sake of clarity, the scattering region of the initial two-probe configuration we are going to create is shown in Figure 37.
Figure 37: A view of the scattering region of the two-probe system studied in this tutorial: Purple/dark corresponds to lithium atoms and white/light corresponds to hydrogen. The distance between the two hydrogen atoms is 0.2 Å.
The complete input file for generating the initial configuration is reported here:
from ATK.TwoProbe import * # Li chain lattice constant a = 2.90 # Construct the electrode unit cell unit_cell = [ [3*a, 0.0, 0.0 ], [0.0, 3*a, 0.0 ], [0.0, 0.0, 4*a ] ] * Angstrom # Define the electrode electrode_Li = PeriodicAtomConfiguration( super_cell_vectors = unit_cell, elements = 4*[Lithium], fractional_coordinates = [ (0.5, 0.5, float(i)/4.0) for i in range(0,4)] ) # Setup the two-probe scattering region # Distances between Li-H and H-H # (dist_HH + 2*dist_LiH = 3.0 Angstrom) dist_HH = 0.2 dist_LiH = 1.5 - 0.5 * dist_HH # The atoms in the central region elements = 3*[Lithium] + 2*[Hydrogen] + 3*[Lithium] positions = [ (0.0, 0.0, 0*a), (0.0, 0.0, 1*a), (0.0, 0.0, 2*a), (0.0, 0.0, 2*a + dist_LiH), (0.0, 0.0, 2*a + dist_LiH + dist_HH), (0.0, 0.0, 2*a + dist_LiH + dist_HH + dist_LiH + 0*a), (0.0, 0.0, 2*a + dist_LiH + dist_HH + dist_LiH + 1*a), (0.0, 0.0, 2*a + dist_LiH + dist_HH + dist_LiH + 2*a) ] * Angstrom # Combine electrode and scattering region # into a two-probe system two_probe_conf = TwoProbeConfiguration( electrodes = (electrode_Li,electrode_Li), scattering_region_elements = elements, scattering_region_cartesian_coordinates = positions ) # Export the two-probe configuration to a VNL file vnl_file = VNLFile("lih2li-ini.vnl") vnl_file.addToSample(two_probe_conf, "lih2li-ini")
After downloading the script, it can be processed with ATK by issuing the command
atk lih2li-ini-setup.py
At the end of the script we added the required lines to export
the TwoProbeConfiguration to a
VNLFile. The script will create
the file lih2li-ini.vnl that contains the atomic configuration
of our two-probe system.
As the first thing to do, one has to read the two-probe configuration created in the previous section:
# Restore old two-probe configuration vnl_file = VNLFile("lih2li-ini.vnl") configurations = vnl_file.readAtomicConfigurations() ini_two_probe_conf = configurations["lih2li-ini"]
We then set the relevant parameters for the self-consistent calculations and create an instance of a two-probe method using these parameters.
# Create parameters for electrodes electrode_bz = brillouinZoneIntegrationParameters( (1,1,80) ) electrode_occ = eigenstateOccupationParameters( temperature = 1300*Kelvin ) electrode_params = ElectrodeParameters( eigenstate_occupation_parameters = electrode_occ, brillouin_zone_integration_parameters = electrode_bz ) # Collect parameters into a two-probe calculation method two_probe_method=TwoProbeMethod( electrode_parameters = (electrode_params, electrode_params), exchange_correlation_type = LDA.PZ )
The next thing to do is to adjust the parameters required by the geometric relaxation. Here, we set the force tolerance to 0.05 Å/eV and allow the geometric optimization to take 200 iteration steps.
# Define parameters for geometry optimization opt_params = geometricOptimizationParameters( force_tolerance = 0.05*eV/Ang, max_steps = 200 )
In order to speed up the convergence of the example given in this tutorial,
we constrain all the lithium atoms in the scattering
region to be kept fixed to their initial position, allowing
only the two hydrogen atoms to relax. The indices of the atoms
to constrain could be set explicitly by setting the list
geo_constraints to [0,1,2,5,6,7], but here we add the
lithium atoms using a more general approach.
# Constraints: All Li atoms in the scattering region are kept fixed geo_constraints = [] elements = ini_two_probe_conf.elements() for i in range(len(elements)): if elements[i] == Lithium: geo_constraints.append(i)
Now we are ready to perform the geometric optimization for the two-probe using the calculateOptimizedAtomicGeometry() function:
# Optimize geometry for the two-probe opt_two_probe_conf = calculateOptimizedAtomicGeometry( atomic_configuration = ini_two_probe_conf, method = two_probe_method, optimization_parameters = opt_params, geometric_constraints = geo_constraints )
Finally, the optimized two-probe configuration is printed and then saved
to the VNLFile
lih2li-opt.vnl:
# Print and export two-probe configuration to a VNL file print '\n','='*50,'\n Two-probe optimized configuration:\n','='*50 nlPrint(opt_two_probe_conf) vnl_file = VNLFile("lih2li-opt.vnl") vnl_file.addToSample(opt_two_probe_conf, "lih2li-opt")
The complete input file for calculating the optimized configuration is:
from ATK.TwoProbe import * import ATK ATK.setVerbosityLevel(2) # Restore old two-probe configuration vnl_file = VNLFile("lih2li-ini.vnl") configurations = vnl_file.readAtomicConfigurations() ini_two_probe_conf = configurations["lih2li-ini"] # Create parameters for electrodes electrode_bz = brillouinZoneIntegrationParameters( (1,1,80) ) electrode_occ = eigenstateOccupationParameters( temperature = 1300*Kelvin ) electrode_params = ElectrodeParameters( eigenstate_occupation_parameters = electrode_occ, brillouin_zone_integration_parameters = electrode_bz ) # Collect parameters into a two-probe calculation method two_probe_method=TwoProbeMethod( electrode_parameters = (electrode_params, electrode_params), exchange_correlation_type = LDA.PZ ) # Define parameters for geometry optimization opt_params = geometricOptimizationParameters( force_tolerance = 0.05*eV/Ang, max_steps = 200 ) # Constraints: All Li atoms in the scattering region are kept fixed geo_constraints = [] elements = ini_two_probe_conf.elements() for i in range(len(elements)): if elements[i] == Lithium: geo_constraints.append(i) # Optimize geometry for the two-probe opt_two_probe_conf = calculateOptimizedAtomicGeometry( atomic_configuration = ini_two_probe_conf, method = two_probe_method, optimization_parameters = opt_params, geometric_constraints = geo_constraints ) # Print and export two-probe configuration to a VNL file print '\n','='*50,'\n Two-probe optimized configuration:\n','='*50 nlPrint(opt_two_probe_conf) vnl_file = VNLFile("lih2li-opt.vnl") vnl_file.addToSample(opt_two_probe_conf, "lih2li-opt")
After downloading the script, it can be processed with ATK by issuing the command
atk lih2li-opt.py
The optimized two-probe configuration from lih2li-opt.vnl
is shown in Figure 38. The fact that the
optimized chain is distorted indicates that, in order to preserve the one-dimensional
chain symmetry, the distance between the innermost lithium atoms should be increased
to about 4 to 5 Å.
Figure 38: A view of the optimized scattering region of two-probe system studied in this tutorial: Purple/dark corresponds to lithium atoms and white/light corresponds to hydrogen. The systems is so compressed in the region close to the hydrogen atoms that the initial one-dimensional linear chain symmetry is no longer preserved.
The optimized two-probe configuration can be used to perform self-consistent calculations and further analysis for the Li-H2-Li two-probe system. The next script compares the transmission eigenvalues and eigenstates for the initial and optimized two-probe systems from the previous example. For more details on how to calculate the transmission eigenvalues and eigenstates of a two-probe system, please have a look at the tutorial Transmission eigenchannels of doped Al wire.
from ATK.TwoProbe import * import ATK ATK.setVerbosityLevel(2) # Restore initial and optimized two-probe configurations ini_vnl_file = VNLFile("lih2li-ini.vnl") ini_configurations = ini_vnl_file.readAtomicConfigurations() ini_two_probe_conf = ini_configurations["lih2li-ini"] opt_vnl_file = VNLFile("lih2li-opt.vnl") opt_configurations = opt_vnl_file.readAtomicConfigurations() opt_two_probe_conf = opt_configurations["lih2li-opt"] # Create parameters for electrodes electrode_bz = brillouinZoneIntegrationParameters( (1,1,80) ) electrode_occ = eigenstateOccupationParameters( temperature = 1300*Kelvin ) electrode_params = ElectrodeParameters( eigenstate_occupation_parameters = electrode_occ, brillouin_zone_integration_parameters = electrode_bz ) # Collect parameters into a two-probe calculation method two_probe_method=TwoProbeMethod( electrode_parameters = (electrode_params, electrode_params), exchange_correlation_type = LDA.PZ, ) # Execute self-consistent calculations ini_scf = executeSelfConsistentCalculation( ini_two_probe_conf, two_probe_method, ) opt_scf = executeSelfConsistentCalculation( opt_two_probe_conf, two_probe_method, ) # Calculate the transmission eigenvalues at the Fermi level k_point_list = [(0.0,0.0)] ini_transmission_eigenvalues = calculateTransmissionEigenvalues( ini_scf, energy = 0*electronVolt, quantum_numbers = (k_point_list) ) opt_transmission_eigenvalues = calculateTransmissionEigenvalues( opt_scf, energy = 0*electronVolt, quantum_numbers = (k_point_list) ) # Write the transmission eigenvalues print "Initial transmission eigenvalue: %s" % (ini_transmission_eigenvalues[0]) print "Optimized transmission eigenvalue: %s" % (opt_transmission_eigenvalues[0]) # Calculate the corresponding transmission eigenstates ini_transmission_eigenstates = calculateTransmissionEigenstates( ini_scf, energy = 0*electronVolt, quantum_numbers = (0,k_point_list) ) opt_transmission_eigenstates = calculateTransmissionEigenstates( opt_scf, energy = 0*electronVolt, quantum_numbers = (0,k_point_list) ) # Save the results ini_vnl_file.addToSample(ini_transmission_eigenstates[0],"lih2li-ini") opt_vnl_file.addToSample(opt_transmission_eigenstates[0],"lih2li-opt")
After downloading the script, it can be processed with ATK by issuing the command
atk lih2li-opt-scf.py
The script writes the calculated transmission eigenvalues for the initial and
optimized two-probe system on standard output. The corresponding eigenstates
are then calculated and stored in the respective VNL files lih2li-ini.vnl and
lih2li-opt.vnl. The eigenstates can then be visualized in VNL.
In Figure 39 we shows the results of such a visualization.
Figure 39: A view of the eigenstates for the two-probe system studied in this tutorial. The eigenstate for the initial configuration is visualized as an isosurface in (a), while the same isosurface for the eigenstate of the optimized configuration is shown in (b).