Skip to content

Instantly share code, notes, and snippets.

@typon
Created February 27, 2019 15:33
Show Gist options
  • Save typon/09e84699a49e2e99f6d31757208405de to your computer and use it in GitHub Desktop.
Save typon/09e84699a49e2e99f6d31757208405de to your computer and use it in GitHub Desktop.
Atomistix 2014 transistor analysis script
#Si nanowire
#bulk
atkpython transistor_analysis_DOS.py --ifile=nanowires/Si/si_bulk.py --analysis=bulk --model=dft --dos_energy_range=-1,1,40 --calcs=Bands --k_points=5,5,5 --band_dims=3 >& logs/si_bulk_bands_0_VG_3d.log &
atkpython transistor_analysis_DOS.py --ifile=nanowires/Si/si_bulk.py --analysis=bulk --model=dft --dos_energy_range=-1,1,40 --calcs=Bands --k_points=5,5,5 --band_dims=2 >& logs/si_bulk_bands_0_VG_2d.log &
atkpython transistor_analysis_DOS.py --ifile=nanowires/Si/si_bulk.py --analysis=bulk --model=dft --dos_energy_range=-1,1,40 --calcs=Bands --k_points=5,5,5 --band_dims=2 --band_route=G,X,W,K,G >& logs/si_bulk_bands_0_VG_2d.log &
#100
atkpython transistor_analysis_DOS.py --ifile=nanowires/Si/si_100_5A_6.25Ax6.25A_gated.py --analysis=gate_sweep --gate_v=-1,-1,1,0 --model=dft --dos_energy_range=-1,1,40 --calcs=Bands >& logs/si_100_5A_6.25Ax6.25A_gated_bands_-4_0_VG.log &
atkpython transistor_analysis_DOS.py --ifile=nanowires/Si/si_100_5A_6.25Ax6.25A_gated.py --analysis=gate_sweep --gate_v=-4,0,4,0 --model=dft --dos_energy_range=-1,1,40 --calcs=Bands >& logs/si_100_5A_6.25Ax6.25A_gated_bands_-4_0_VG.log &
atkpython transistor_analysis_DOS.py --ifile=nanowires/Si/si_100_5A_6.25Ax6.25A_gated_new.py --analysis=bulk --gate_v=-10,-10,2,0 --model=dft --dos_energy_range=-1,1,40 --calcs=Bands >& logs/si_100_5A_6.25Ax6.25A_gated_new_bands_-4_0_VG.log &
atkpython transistor_analysis_DOS.py --ifile=nanowires/Si/si_100_5A_6.25Ax6.25A_gated_new.py --analysis=bulk --gate_v=-1,-1,1,0 --model=dft --dos_energy_range=-1,1,40 --calcs=Bands >& logs/si_100_5A_6.25Ax6.25A_gated_new_bands_-4_0_VG.log &
atkpython transistor_analysis_DOS.py --ifile=nanowires/Si/si_100_5A_6.25Ax6.25A_gated_tubular.py --analysis=gate_sweep --gate_v=-4,-4,1,0 --model=huckel --dos_energy_range=-1,1,40 --calcs=Bands >& logs/si_100_5A_6.25Ax6.25A_gated_bands_-4_0_VG.log &
/opt/QuantumWise/VNL-ATK-2014.2/bin/atkpython transistor_analysis_DOS.py --ifile=nanowires/Si/si_100_5A_6.25Ax6.25A_gated.py --analysis=gate_sweep --gate_v=-2,1,4,0 --model=dft --dos_energy_range=-1,1,40 --calcs=Bands >& logs/si_100_5A_6.25Ax6.25A_gated_Bands_-2_1_VG.log &
#asymmetric voltage on metals
atkpython transistor_analysis_DOS.py --ifile=nanowires/Si/si_100_5A_6.25Ax6.25A_gated_huckel.py --analysis=bulk --gate_v=-4,0,2,0 --model=huckel --dos_energy_range=-1,1,40 --calcs=Bands >& logs/si_100_5A_6.25Ax6.25A_gated_bands_-4_0_VG.log &
#Graphene
#bulk
atkpython transistor_analysis_DOS.py --ifile=nanowires/Graphene/builder__graphene_bulk_unit_unrelaxed.py --analysis=bulk --model=dft --dos_energy_range=-1,1,40 --calcs=Bands --k_points=9,9,1 --band_dims=2 >& logs/graphene_bulk_bands_0_VG_2d.log &
atkpython transistor_analysis_DOS.py --ifile=nanowires/Graphene/builder__graphene_bulk_unit_unrelaxed.py --analysis=bulk --model=dft --dos_energy_range=-1,1,40 --calcs=Bands --k_points=9,9,1 --band_dims=2 --band_route=G,M,K,G >& logs/graphene_bulk_bands_0_VG_2d.log &
#Gold
#bulk
atkpython transistor_analysis_DOS.py --ifile=nanowires/Au_DFT/au_bulk.py --analysis=bulk --model=dft --dos_energy_range=-1,1,40 --calcs=Bands --k_points=5,5,5 --band_dims=2 >& logs/au_bulk_bands_0_VG_2d.log &
#100 nanowire
atkpython transistor_analysis_DOS.py --ifile=nanowires/Au_DFT/au_100_4.07A_8.65Ax5.767A_gated_new.py --analysis=bulk --model=dft --gate_v=-2.5,2.5,2,0 --dos_energy_range=-1,1,40 --calcs=Bands --k_points=2,2,50 --band_dims=1 >& logs/au_100_4.07A_8.65Ax5.767A_gated_new_-2.5_VG_1d.log &
atkpython transistor_analysis_DOS.py --ifile=nanowires/Au_DFT/au_100_4.07A_8.65Ax5.767A_gated_multipole.py --analysis=gate_sweep --model=dft --gate_v=-2.5,2.5,2,0 --dos_energy_range=-1,1,40 --calcs=Bands --k_points=3,3,11 --band_dims=1 >& logs/au_100_4.07A_8.65Ax5.767A_gated_mp_-2.5_VG_1d.log &
#110 nanowire
atkpython transistor_analysis_DOS.py --ifile=nanowires/Au_DFT/au_110_2.88A_8.65Ax5.8A_gated.py --analysis=bulk --model=dft --gate_v=-2.5,2.5,2,0 --dos_energy_range=-1,1,40 --calcs=Bands --k_points=2,2,50 --band_dims=1 >& logs/au_110_2.88A_8.65Ax5.8A_gated_-2.5_VG_1d.log &
atkpython transistor_analysis_DOS.py --ifile=nanowires/Au_DFT/au_110_2.88A_8.65Ax5.8A_gated_multipole.py --analysis=gate_sweep --model=dft --gate_v=-2.5,2.5,2,0 --dos_energy_range=-1,1,40 --calcs=Bands --k_points=3,3,11 --band_dims=1 >& logs/au_110_2.88A_8.65Ax5.8A_gated_mp_-2.5_VG_1d.log &
#111 nanowire
mpiexec -n 4 atkpython transistor_analysis_DOS.py --ifile=nanowires/Au_DFT/au_111_7.0A_8.65Ax5.8A_gated.py --analysis=bulk --model=dft --gate_v=-2.5,2.5,2,0 --dos_energy_range=-1,1,40 --calcs=Bands --k_points=3,3,11 --band_dims=1 >& logs/au_111_7.0A_8.65Ax5.8A_gated.py_-2.5_VG_1d.log &
atkpython transistor_analysis_DOS.py --ifile=nanowires/Au_DFT/au_111_7.0A_8.65Ax5.8A_gated_multipole.py --analysis=gate_sweep --model=dft --gate_v=-2.5,2.5,2,0 --dos_energy_range=-1,1,40 --calcs=Bands --k_points=3,3,11 --band_dims=1 >& logs/au_111_7.0A_8.65Ax5.8A_gated_mp.py_-2.5_VG_1d.log &
#Copper
#100 nanowire
atkpython transistor_analysis_DOS.py --ifile=nanowires/Cu/cu_100_3p6A_7p67Ax5p11A_gated.py --analysis=bulk --model=dft --gate_v=-2.5,2.5,2,0 --dos_energy_range=-1,1,40 --calcs=Bands --k_points=2,2,50 --band_dims=1 >& logs/cu_100_3p6A_7p67Ax5p11A_gated.py_-2.5_VG_1d.log &
atkpython transistor_analysis_DOS.py --ifile=nanowires/Cu/cu_100_3p6A_7p67Ax5p11A_gated_multipole.py --analysis=gate_sweep --model=dft --gate_v=-2.5,2.5,2,0 --dos_energy_range=-1,1,40 --calcs=Bands --k_points=3,3,11 --band_dims=1 >& logs/cu_100_3p6A_7p67Ax5p11A_gated_mp.py_-2.5_VG_1d.log &
#Silver
#100 nanowire
atkpython transistor_analysis_DOS.py --ifile=nanowires/Ag/ag_100_4p08A_8p67A_5p78A_gated.py --analysis=bulk --model=dft --gate_v=-2.5,2.5,2,0 --dos_energy_range=-1,1,40 --calcs=Bands --k_points=5,5,11 --band_dims=1 >& logs/ag_100_4p08A_8p67A_5p78A_gated.py-2.5_VG_1d.log &
atkpython transistor_analysis_DOS.py --ifile=nanowires/Ag/ag_100_4p08A_8p67A_5p78A_gated_multipole.py --analysis=gate_sweep --model=dft --gate_v=-2.5,2.5,2,0 --dos_energy_range=-1,1,40 --calcs=Bands --k_points=3,3,11 --band_dims=1 >& logs/ag_100_4p08A_8p67A_5p78A_gated_mp.py-2.5_VG_1d.log &
#!/usr/bin/python
# -*- coding: UTF-8 -*-
import pylab
import collections
from datetime import datetime
import time
import multiprocessing
import socket
import os
import sys
import re
import csv
import StringIO
import numpy as np
import scipy
from operator import add
import getopt
import pdb
import shutil
from pprint import pprint
import ntpath
import itertools
from NL.IO.NLSaveUtilities import nlinspect
def enum (**enums):
return type ('Enum', (), enums)
class Semaphore:
def __init__(self, device_config_path):
processId = str(os.getpid())
self.fileName = device_config_path + '.sem.' + processId + '.lock'
def touch (self, fileName):
with open(fileName, 'a'):
os.utime(fileName, None)
def lock (self):
exists = True
while (exists):
exists = os.path.exists(self.fileName)
print 'waiting for ', self.fileName
self.touch(self.fileName)
def release (self):
exists = os.path.exists(self.fileName)
if (exists):
os.remove(self.fileName)
class DeviceAnalysis:
def __init__(self, argv):
self.exchange_correlation = GGA.PBE
self.k_point_sampling = (1, 1, 100)
self.default_gate_voltage = 0 * Volt
self.analysis_type = None
self.voltage_range_input = {'gv':False, 'vds':False,}
self.band_route = None
self.band_zero = "FermiLevel"
self.nprocessors = 4
self.dos_energy_range = []
self.calc_types = []
self.ang_momenta = []
self.band_dims = 1
# Define gate_voltages
self.ConfigTypes = enum (BULK = (1, DensityOfStates, BulkConfiguration) , DEVICE = (2, DeviceDensityOfStates, DeviceConfiguration))
self.objects_enum = {"Veff": EffectivePotential, "Vext": ExternalPotential, "DiffPot": ElectrostaticDifferencePotential, "Edens": ElectronDensity,
"Dos": DensityOfStates, "LDDOS": LocalDeviceDensityOfStates, "Ediffdens": ElectronDifferenceDensity, "VDrop": ElectrostaticDifferencePotential,
"ChemPot": ChemicalPotential, "Band": Bandstructure, "VDropEff": EffectivePotential, "EffMass": EffectiveMass}
try:
opts, args = getopt.getopt(argv,"hiagvmndckbzlq:",["ifile=","analysis=", "gate_v=", "vds=", "model=",
"nprocs=", "dos_energy_range=", "calcs=", "k_points=",
"band_route=", "band_zero=", "angular_momenta=", "band_dims="])
except getopt.GetoptError, exc:
print exc.msg
self.usage()
if not opts:
print 'No options supplied'
self.usage()
for opt, arg in opts:
if opt == '-h':
self.usage()
elif opt in ("-i", "--ifile"):
inputfile = arg
elif opt in ("-a", "--analysis"):
self.analysis_type = arg
elif opt in ("-g", "--gate_v"):
gate_voltage_params = arg.split(',')
if len(gate_voltage_params) is not 4:
self.usage()
self.gate_v_start = float(gate_voltage_params[0])
self.gate_v_end = float(gate_voltage_params[1])
self.gate_v_points = float(gate_voltage_params[2])
self.vds_bias = float(gate_voltage_params[3])
self.voltage_range_input['gv'] = True
elif opt in ("-v", "--vds"):
vds_params = arg.split(',')
if len(vds_params) is not 4:
self.usage()
self.vds_start = float(vds_params[0])
self.vds_end = float(vds_params[1])
self.vds_points = float(vds_params[2])
self.gate_v = float(vds_params[3])
self.voltage_range_input['vds'] = True
elif opt in ("-m", "--model"):
self.model_type = arg
elif opt in ("-n", "--nprocs"):
self.nprocessors = int(arg)
elif opt in ("-d", "--dos_energy_range"):
dos_energy_params = arg.split(',')
if len(dos_energy_params) is not 3:
self.usage()
start = float(dos_energy_params[0])
end = float(dos_energy_params[1])
pts = float(dos_energy_params[2])
self.dos_energy_range = np.linspace(start, end, num = pts)
elif opt in ("-c", "--calcs"):
self.calc_types = arg.split(',')
print self.calc_types
elif opt in ("-k", "--k_points"):
k_points = arg.split(',')
if len(k_points) is not 3:
self.usage()
k_points_list = [int(i) for i in k_points]
self.k_point_sampling = tuple(k_points_list)
elif opt in ("-b", "--band_route"):
self.band_route = arg.split(',')
elif opt in ("-b", "--band_zero"):
self.band_zero = arg
elif opt in ("-l", "--angular_momenta"):
self.ang_momenta = arg.split(',')
self.ang_momenta = [int(x) for x in self.ang_momenta]
elif opt in ("-q", "--band_dims"):
self.band_dims = int(arg)
if self.analysis_type is None:
print "Please specify analysis type..."
self.usage()
if self.analysis_type == 'vds_sweep' and self.voltage_range_input ['vds'] is False:
self.usage()
elif self.analysis_type == 'gate_sweep' and self.voltage_range_input ['gv'] is False:
self.usage()
elif len(self.dos_energy_range) == 0:
self.usage()
elif len(self.calc_types) == 0:
self.usage()
self.print_sim_info()
print 'Input geometry file is:', inputfile
#run self consistent device calculation for zero bias.
voltage = 0 * Volt
init_config_obj = []
#Get full file path
full_input_path = os.path.abspath (inputfile)
#Get input file name only
file_base_name = ntpath.basename(full_input_path)
print file_base_name
print full_input_path
#extract diretory path
dir_path = os.path.dirname(full_input_path )
#Create tmp folder insid ethe directory to hold the NetCDF file and
#output data files
#Temp file path
tmp_path = dir_path+'/tmp/'
analysis_tmp_path = dir_path+'/tmp/internals/'
if not os.path.exists(analysis_tmp_path):
os.makedirs(analysis_tmp_path)
if not os.path.exists(tmp_path):
os.makedirs(tmp_path)
self.analysis_config_path = analysis_tmp_path+file_base_name+".internals"
self.device_config_path = tmp_path+file_base_name+".analysis.nc"
print "Device config path = ", self.device_config_path
self.sem_device = Semaphore(self.device_config_path)
self.sem_int = Semaphore(self.analysis_config_path)
#try reading device config first
try:
with open(self.device_config_path):
print "Accessing initial configuration"
init_config_obj = self.find_zero_volt_config ()
#configuration empty, therefore device config
except IOError:
print 'Oh dear. No device config file exists.'
if not init_config_obj:
print "No initial configuration exists, running DFT calculation"
print "Extracting configuration from file"
init_config_obj, basis_set = self.create_device_config(inputfile)
#setting iether bulk or device config type
self.set_configuration_type(init_config_obj)
if (self.config_type == self.ConfigTypes.DEVICE):
print "device"
if (self.model_type == 'dft'):
self.calculator = self.create_device_calculator_dft (basis_set)
elif (self.model_type == 'huckel'):
self.calculator = self.create_device_calculator_huckel (basis_set)
elif (self.config_type == self.ConfigTypes.BULK):
print "bulk"
if (self.model_type == 'dft'):
self.calculator = self.create_bulk_calculator (basis_set)
elif (self.model_type == 'huckel'):
self.calculator = self.create_bulk_huckel_calculator (basis_set)
init_config_obj.setCalculator(self.calculator)
nlprint(init_config_obj)
init_config_obj.update()
self.sem_device.lock()
nlsave(self.device_config_path, init_config_obj, object_id="Config, GateV %f, Vds %f" % (0.0, 0.0))
self.sem_device.release()
if (self.config_type == self.ConfigTypes.DEVICE):
configuration_obj = nlread(self.device_config_path, DeviceConfiguration)
elif (self.config_type == self.ConfigTypes.BULK):
configuration_obj = nlread(self.device_config_path, BulkConfiguration)
self.configuration_obj = configuration_obj [0]
else:
print 'Found initial configuration'
init_config_obj = init_config_obj [0]
self.set_configuration_type(init_config_obj)
self.configuration_obj = init_config_obj
self.extract_dimensions()
def usage(self):
print 'python transistor_analysis_DOS.py \
--ifile=<inputfile> \
--model=<huckel|dft> \
--analysis=<gate_sweep|vds_sweep|bulk> \
(--gate_v=<start,end,steps,vds_value> | --vds=<start,end,steps>) \
--dos_energy_range=<start,end,num_pts> \
--calcs=<Veff|Vext|DiffPot|Edens|Dos|LDDOS|Ediffdens|VDrop|Efield|Trans|Bands|ChemPot|VDropEff|EffMass|MoveTrans|None> \
--k_points=<start,end,steps> \
--band_zero=FermiLevel|Absolute \
--band_route=<route seperated with zero> \
--angular_momenta=<comma separated list of angular momenta>'
sys.exit()
def print_sim_info(self):
print "Machine name: ", socket.gethostname()
print "Starting simulation on: ", datetime.now().strftime('%Y-%m-%d %H:%M:%S')
def gv_obj (self, configuration_obj):
metallic_regions = configuration_obj.metallicRegions()
if not metallic_regions:
print "There are no metallic regions, device is not gated..."
#return 0 volt value
return self.default_gate_voltage.inUnitsOf(Volt)
gate_bias = metallic_regions[0].value().inUnitsOf(Volt)
#print "Metallic region voltages: "
#for region in metallic_regions:
#print region.value().inUnitsOf(Volt),
return gate_bias
def vds_obj (self, configuration_obj):
if self.config_type == self.ConfigTypes.DEVICE:
electrode_voltages = configuration_obj.calculator().electrodeVoltages()
return electrode_voltages[0].inUnitsOf(Volt) * 2
elif self.config_type == self.ConfigTypes.BULK:
#VDS for bulk is always 0
return 0
def find_zero_volt_config(self):
print "Finding zero volt config..."
zero_volt_config = []
#there are some configs
zero_volt_config = nlread(self.device_config_path, DeviceConfiguration,
object_id="Config, GateV %f, Vds %f" % (0.0, 0.0), read_state = True)
if not zero_volt_config:
zero_volt_config = nlread(self.device_config_path, BulkConfiguration,
#there are no metallic regions, therefore device not gated
object_id="Config, GateV %f, Vds %f" % (0.0, 0.0), read_state = True)
if (not zero_volt_config):
print "---------------------------------------"
print "Warning...No zero volt config found..."
print "---------------------------------------"
return zero_volt_config
def set_configuration_type(self, configuration_obj):
if 'BulkConfiguration' in str(type(configuration_obj)):
self.config_type = self.ConfigTypes.BULK
elif 'DeviceConfiguration' in str(type(configuration_obj)):
self.config_type = self.ConfigTypes.DEVICE
else:
print str(type(configuration_obj))
print "Error: Not valid configuration type"
sys.exit()
def find_closest_state (self, gate_voltage, drain_voltage):
#holds all objects. need to extract transmissionspectrum objects
all_nc_keys = nlinspect(self.device_config_path)
config_objects_ids = []
for key in all_nc_keys:
if key[0] == ('DeviceConfiguration') or key[0] == ('BulkConfiguration'):
config_objects_ids.append (key)
#config_objects_ids: [0] = DeviceConfiguration
# [1] = object_id
# [2] = Fingerprint
#Sort the Trans objects by voltage first for printing
#tuple of (gate_v, vds)
sorted_voltages = []
for config_obj in config_objects_ids:
#extracting the vds and gate voltage
object_id = config_obj[1]
search_obj = re.search (r'Config, GateV ([-0-9.]+), Vds ([-0-9.]+)$', object_id, re.M)
if search_obj:
gate_v = float(search_obj.group(1))
vds = float(search_obj.group(2))
sorted_voltages.append ((gate_v, vds))
#sort by Vgs
sorted_voltages.sort(key=lambda tup: tup[0])
vds_list = [tup[1] for tup in sorted_voltages]
#find the closest vds tuple first
closest_vds = min(vds_list, key=lambda x:abs(x-drain_voltage.inUnitsOf(Volt)))
#get gate voltages with only closest vds
culled_vgs_list = [tup[0] for tup in sorted_voltages if tup[1] == closest_vds]
closest_vgs = min(culled_vgs_list, key=lambda x:abs(x-gate_voltage.inUnitsOf(Volt)))
#get the closest intial state
initial_state = nlread(self.device_config_path, self.config_type[2],
object_id="Config, GateV %f, Vds %f" % (closest_vgs, closest_vds), read_state = True)
initial_state = initial_state [0]
vgs_init_state = self.gv_obj (initial_state)
vds_init_state = self.vds_obj (initial_state)
print ("Using initial state with VGS = %f, VDS = %f") % (vgs_init_state, vds_init_state)
return initial_state
def gate_voltage_sweep (self, voltages, drain_voltage, asymmetric_voltage=False):
print "Sweeping Gate voltages: ", voltages
##Only perform DFT calculations for voltages that are incomplete
#if self.config_type == self.ConfigTypes.DEVICE:
#config_objs = nlread(self.device_config_path, DeviceConfiguration)
#elif self.config_type == self.ConfigTypes.BULK:
#config_objs = nlread(self.device_config_path, BulkConfiguration)
##TODO MAKE THIS INTO ASSERT
#if not config_objs:
#print "There must be at least 0 volt config!"
#sys.exit()
#
#
##find only configs with particular vds bias
#configs_vds_bias = []
#for config in config_objs:
#electrode_voltages = config.calculator().electrodeVoltages()
#if abs(electrode_voltages[0].inUnitsOf(Volt)) == abs((drain_voltage.inUnitsOf(Volt)/2)):
#configs_vds_bias.append(config)
#
#
#if not configs_vds_bias:
#print "There are no configs with vds = ", drain_voltage
#sys.exit(1)
##there are some configs
#voltages = [x.inUnitsOf(Volt) for x in voltages]
#find zero volt vds config first
configs = []
zero_volt_config = nlread(self.device_config_path, self.config_type[2],
object_id="Config, GateV %f, Vds %f" % (0.0, drain_voltage.inUnitsOf(Volt)), read_state = False)
if not zero_volt_config:
print "There are no configs with vds = ", drain_voltage
sys.exit(1)
#now remove any gv bias configs for drain_voltage
valid_voltages = []
for voltage in voltages:
config = nlread(self.device_config_path, self.config_type[2],
object_id="Config, GateV %f, Vds %f" % (voltage.inUnitsOf(Volt), drain_voltage.inUnitsOf(Volt)), read_state = False)
if not config:
valid_voltages.append(voltage)
#for config in configs_vds_bias:
#
#metallic_regions = config.metallicRegions()
#gate_bias = metallic_regions[0].value().inUnitsOf(Volt)
##this bias has already been compiled
#if gate_bias in voltages:
#voltages.remove (gate_bias)
print "Gate Voltages being swept: ", valid_voltages
# Read in the old configuration
#TODO get the most appropirate voltage
new_config = zero_volt_config[0]
calculator = new_config.calculator()
metallic_regions = new_config.metallicRegions()
# Perform loop over gate voltages
for gate_voltage in valid_voltages:
print ("Running self consistent calculation with VGS = %f, VDS = %f") % (gate_voltage, drain_voltage)
# Set the gate voltages to the new values
if (asymmetric_voltage):
new_regions = [metallic_regions[0](value = gate_voltage)]
new_regions.extend([m for m in metallic_regions[1:]])
else:
new_regions = [m(value = gate_voltage) for m in metallic_regions]
new_config.setMetallicRegions(new_regions)
# Make a copy of the calculator and attach it to the configuration
# Restart from the previous scf state
#find closest state
init_state = self.find_closest_state(gate_voltage, drain_voltage)
new_config.setCalculator(calculator(),
initial_state=init_state)
new_config.update()
self.sem_device.lock()
nlsave(self.device_config_path, new_config,
object_id="Config, GateV %f, Vds %f" % (self.gv_obj(new_config), self.vds_obj(new_config)))
self.sem_device.release()
def vds_sweep (self, gate_voltage, vds_voltages):
#Only perform DFT calculations for voltages that are incomplete
if self.config_type == self.ConfigTypes.DEVICE:
config_objs = nlread(self.device_config_path, DeviceConfiguration, read_state=False)
elif self.config_type == self.ConfigTypes.BULK:
config_objs = nlread(self.device_config_path, BulkConfiguration, read_state=False)
#TODO MAKE THIS INTO ASSERT
if not config_objs:
print "There must be at least 0 volt config!"
sys.exit()
#Figure out if this configuration with current gate voltage is already done
#now remove any gv bias configs for drain_voltage
valid_voltages = []
for voltage in vds_voltages:
obj_id = "Config, GateV %f, Vds %f" % (gate_voltage.inUnitsOf(Volt), voltage.inUnitsOf(Volt))
config = nlread(self.device_config_path, self.config_type[2],
object_id=obj_id, read_state=False)
if not config:
valid_voltages.append(voltage)
zero_volt_config = self.configuration_obj
calculator = zero_volt_config.calculator()
print "Gate Voltage: ", self.gv_obj (zero_volt_config)
print "VDS voltages being swept: ", valid_voltages
# Perform loop over gate voltages
for voltage in valid_voltages:
print ("Running self consistent calculation with VGS = %f, VDS = %f") % (gate_voltage, voltage)
init_state = self.find_closest_state(gate_voltage, voltage)
# Set the gate voltages to the new values
zero_volt_config.setCalculator(
calculator(electrode_voltages=(voltage/2, -voltage/2)),
initial_state=init_state)
# Make a copy of the calculator and attach it to the configuration
# Restart from the previous scf state
zero_volt_config.update()
self.sem_device.lock()
nlsave(self.device_config_path, zero_volt_config, object_id="Config, GateV %f, Vds %f" % (self.gv_obj(zero_volt_config), self.vds_obj(zero_volt_config)))
self.sem_device.release()
def frac_to_cart(self, length_real, frac):
result = length_real*frac;
return result
def create_device_config (self, geometry_path):
# create file-like string to capture output
codeOut = StringIO.StringIO()
codeErr = StringIO.StringIO()
geometry_code = ''
try:
with open(geometry_path, 'r') as f:
geometry_code = f.read()
#print geometry_code
except IOError:
print 'Oh dear. Specified geometry file [',geometry_path,'] does not exist.'
if (geometry_code == ''):
print 'Oh dear. No geometry pecified'
exit(1)
basis_set = []
device_configuration = None
bulk_configuration = None
# capture output and errors
sys.stdout = codeOut
sys.stderr = codeErr
#print geometry_code
exec geometry_code
# restore stdout and stderr
sys.stdout = sys.__stdout__
sys.stderr = sys.__stderr__
#print geometry_code
#print f(4)
s = codeErr.getvalue()
if s:
print "###########################"
print "error: %s\n" % s
print "###########################"
#s = codeOut.getvalue()
#print "output:\n%s" % s
codeOut.close()
codeErr.close()
if len(basis_set) == 0:
print "Error: No basis set specified"
sys.exit()
if device_configuration is None:
return bulk_configuration, basis_set
elif bulk_configuration is None:
return device_configuration, basis_set
else:
print "Error: No configuration specified"
sys.exit()
def create_bulk_huckel_calculator (self, basis_set):
print "Creating Bulk calculator..."
if (self.voltage_range_input['gv']):
print "...with Multipole boundary conditions on A/B"
poisson_solver = MultigridSolver(
#boundary_conditions=[[NeumannBoundaryCondition,NeumannBoundaryCondition],
#[NeumannBoundaryCondition,NeumannBoundaryCondition],
#[PeriodicBoundaryCondition,PeriodicBoundaryCondition]]
#boundary_conditions=[[DirichletBoundaryCondition,DirichletBoundaryCondition],
#[DirichletBoundaryCondition,DirichletBoundaryCondition],
#[PeriodicBoundaryCondition,PeriodicBoundaryCondition]]
boundary_conditions=[[MultipoleBoundaryCondition,MultipoleBoundaryCondition],
[MultipoleBoundaryCondition,MultipoleBoundaryCondition],
[PeriodicBoundaryCondition,PeriodicBoundaryCondition]]
)
else:
print "...with Periodic boundary conditions on A/B/C"
poisson_solver = MultigridSolver(
boundary_conditions=[[PeriodicBoundaryCondition,PeriodicBoundaryCondition],
[PeriodicBoundaryCondition,PeriodicBoundaryCondition],
[PeriodicBoundaryCondition,PeriodicBoundaryCondition]]
)
bulk_numerical_accuracy_parameters = NumericalAccuracyParameters(
density_mesh_cutoff = 150.0*Rydberg,
k_point_sampling=self.k_point_sampling
)
calculator = HuckelCalculator(
basis_set=basis_set,
poisson_solver=poisson_solver,
numerical_accuracy_parameters=bulk_numerical_accuracy_parameters,
)
return calculator
def create_bulk_calculator (self, basis_set):
print "Creating Bulk calculator..."
if (self.voltage_range_input['gv']):
print "...with Dirichlet boundary conditions on A/B"
poisson_solver = MultigridSolver(
#boundary_conditions=[[NeumannBoundaryCondition,NeumannBoundaryCondition],
#[NeumannBoundaryCondition,NeumannBoundaryCondition],
#[PeriodicBoundaryCondition,PeriodicBoundaryCondition]]
boundary_conditions=[[DirichletBoundaryCondition,DirichletBoundaryCondition],
[DirichletBoundaryCondition,DirichletBoundaryCondition],
[PeriodicBoundaryCondition,PeriodicBoundaryCondition]]
)
else:
print "...with Periodic boundary conditions on A/B/C"
poisson_solver = FastFourierSolver()
bulk_numerical_accuracy_parameters = NumericalAccuracyParameters(
density_mesh_cutoff = 150.0*Rydberg,
k_point_sampling=self.k_point_sampling
)
calculator = LCAOCalculator(
poisson_solver=poisson_solver,
basis_set=basis_set,
exchange_correlation=self.exchange_correlation,
numerical_accuracy_parameters=bulk_numerical_accuracy_parameters,
)
return calculator
def create_device_calculator_huckel (self, basis_set):
#----------------------------------------
# Numerical Accuracy Settings
#----------------------------------------
left_electrode_numerical_accuracy_parameters = NumericalAccuracyParameters(
k_point_sampling=self.k_point_sampling,
)
right_electrode_numerical_accuracy_parameters = NumericalAccuracyParameters(
k_point_sampling=self.k_point_sampling,
)
device_numerical_accuracy_parameters = NumericalAccuracyParameters(
k_point_sampling=self.k_point_sampling,
)
#----------------------------------------
# Iteration Control Settings
#----------------------------------------
left_electrode_iteration_control_parameters = IterationControlParameters()
right_electrode_iteration_control_parameters = IterationControlParameters()
#device_iteration_control_parameters = IterationControlParameters()
device_iteration_control_parameters = IterationControlParameters(
damping_factor=0.10,
preconditioner=Kerker(0.02*Hartree, 0.5*Hartree, 0.01),
mixing_variable=HamiltonianVariable,
number_of_history_steps=12,
)
# Poisson Solver Settings
#----------------------------------------
left_electrode_poisson_solver = MultigridSolver(
boundary_conditions=[[NeumannBoundaryCondition,NeumannBoundaryCondition],
[NeumannBoundaryCondition,NeumannBoundaryCondition],
[PeriodicBoundaryCondition,PeriodicBoundaryCondition]]
)
right_electrode_poisson_solver = MultigridSolver(
boundary_conditions=[[NeumannBoundaryCondition,NeumannBoundaryCondition],
[NeumannBoundaryCondition,NeumannBoundaryCondition],
[PeriodicBoundaryCondition,PeriodicBoundaryCondition]]
)
device_poisson_solver = MultigridSolver(
boundary_conditions=[[NeumannBoundaryCondition,NeumannBoundaryCondition],
[NeumannBoundaryCondition,NeumannBoundaryCondition],
[DirichletBoundaryCondition,DirichletBoundaryCondition]]
)
#----------------------------------------
# Electrode Calculators
#----------------------------------------
left_electrode_calculator = HuckelCalculator(
basis_set=basis_set,
numerical_accuracy_parameters=left_electrode_numerical_accuracy_parameters,
iteration_control_parameters=left_electrode_iteration_control_parameters,
poisson_solver=left_electrode_poisson_solver,
)
right_electrode_calculator = HuckelCalculator(
basis_set=basis_set,
numerical_accuracy_parameters=right_electrode_numerical_accuracy_parameters,
iteration_control_parameters=right_electrode_iteration_control_parameters,
poisson_solver=right_electrode_poisson_solver,
)
#----------------------------------------
# Device Calculator
#----------------------------------------
calculator = DeviceHuckelCalculator(
basis_set=basis_set,
numerical_accuracy_parameters=device_numerical_accuracy_parameters,
iteration_control_parameters=device_iteration_control_parameters,
poisson_solver=device_poisson_solver,
electrode_calculators=
[left_electrode_calculator, right_electrode_calculator],
)
return calculator
def create_device_calculator_dft (self, basis_set):
# -------------------------------------------------------------
# Calculator
# -------------------------------------------------------------
#----------------------------------------
# Exchange-Correlation
#----------------------------------------
#----------------------------------------
# Numerical Accuracy Settings
#----------------------------------------
left_electrode_numerical_accuracy_parameters = NumericalAccuracyParameters(
k_point_sampling=self.k_point_sampling,
density_mesh_cutoff = 150.0*Rydberg,
)
right_electrode_numerical_accuracy_parameters = NumericalAccuracyParameters(
k_point_sampling=self.k_point_sampling,
density_mesh_cutoff = 150.0*Rydberg,
)
device_numerical_accuracy_parameters = NumericalAccuracyParameters(
k_point_sampling=self.k_point_sampling,
density_mesh_cutoff = 150.0*Rydberg,
)
#----------------------------------------
# Poisson Solver Settings
#----------------------------------------
left_electrode_poisson_solver = MultigridSolver(
boundary_conditions=[[NeumannBoundaryCondition,NeumannBoundaryCondition],
[NeumannBoundaryCondition,NeumannBoundaryCondition],
[PeriodicBoundaryCondition,PeriodicBoundaryCondition]]
)
right_electrode_poisson_solver = MultigridSolver(
boundary_conditions=[[NeumannBoundaryCondition,NeumannBoundaryCondition],
[NeumannBoundaryCondition,NeumannBoundaryCondition],
[PeriodicBoundaryCondition,PeriodicBoundaryCondition]]
)
device_poisson_solver = MultigridSolver(
boundary_conditions=[[NeumannBoundaryCondition,NeumannBoundaryCondition],
[NeumannBoundaryCondition,NeumannBoundaryCondition],
[DirichletBoundaryCondition,DirichletBoundaryCondition]]
)
#----------------------------------------
# Electrode Calculators
#----------------------------------------
left_electrode_calculator = LCAOCalculator(
basis_set=basis_set,
exchange_correlation=self.exchange_correlation,
numerical_accuracy_parameters=left_electrode_numerical_accuracy_parameters,
poisson_solver=left_electrode_poisson_solver,
)
right_electrode_calculator = LCAOCalculator(
basis_set=basis_set,
exchange_correlation=self.exchange_correlation,
numerical_accuracy_parameters=right_electrode_numerical_accuracy_parameters,
poisson_solver=right_electrode_poisson_solver,
)
#----------------------------------------
# Device Calculator
#----------------------------------------
calculator = DeviceLCAOCalculator(
poisson_solver=device_poisson_solver,
basis_set=basis_set,
exchange_correlation=self.exchange_correlation,
numerical_accuracy_parameters=device_numerical_accuracy_parameters,
electrode_calculators=
[left_electrode_calculator, right_electrode_calculator],
)
return calculator
def symmetry_points (self):
lattice = self.configuration_obj.bravaisLattice()
points = []
for point in lattice.symmetryPoints().keys():
points.append(point)
return points
def extract_dimensions (self):
lattice = self.configuration_obj.bravaisLattice()
lattice_vectors = lattice.primitiveVectors()
self.x_length = lattice_vectors[0][0]
self.y_length = lattice_vectors[1][1]
self.z_length = lattice_vectors[2][2]
coords = self.configuration_obj.fractionalCoordinates()
#sort by the third axis, in this case z. f2= axis3, f1=axis2, f0=axis1
#need to copy the array to make it work
coords = coords.copy()
coords.view('f8,f8,f8').sort(order=['f2'], axis=0)
#figuring out the projection lines for 100
self.z_coord_first_atom = coords[0][2]
self.z_coord_last_atom = coords[-1][2]
x_coords_list = [x[0] for x in coords]
x_coords_list = sorted(set(x_coords_list))
self.x_coord_first_atom = self.frac_to_cart(self.x_length, x_coords_list[0])
self.x_coord_last_atom = self.frac_to_cart(self.x_length, x_coords_list[-1])
middle_x_index = int(len(x_coords_list)/2)
self.x_coord_middle_atom = self.frac_to_cart(self.x_length, x_coords_list[middle_x_index])
middle_z_index = int(len(coords)/2)
self.z_coord_middle_atom = self.frac_to_cart(self.z_length, coords [middle_z_index][2])
self.projection_point_x_1 = numpy.array([0, 0.5, self.z_coord_first_atom])
self.projection_point_y_1 = numpy.array([0.5, 0, self.z_coord_first_atom])
self.projection_point_x_0 = numpy.array([0, 0.5, self.z_coord_last_atom])
self.projection_point_y_0 = numpy.array([0.5, 0, self.z_coord_last_atom])
for coord in coords:
x_coord = coord[0]
#print coords
def nlread_object (self, obj_name, gv, vds, nrg=0*eV, ang_momenta=[], dimensions=1, route=None, k_pts=None):
result = (False, None)
if (obj_name == 'LDDOS'):
obj_id = "LDDOS %f, GateV %f, Vds %f" % (nrg, gv, vds)
elif (obj_name == 'EffMass'):
obj_id = "EffMass, GateV %f, Vds %f, k = %s%s%s" % (gv, vds, str(k_pts[0]), str(k_pts[1]),str(k_pts[2]))
elif (obj_name == 'Band'):
if not ang_momenta:
ang_momenta_str = 'all'
else:
ang_momenta_str = str(ang_momenta)
if (dimensions == 1):
dimensions_str = ''
elif (dimensions > 1):
dimensions_str = ', dim = %d' % dimensions
if (route):
route_str = ',route = '
for point in route:
route_str = route_str + ('%s ' % point)
else:
route_str = ''
obj_id = "Band, GateV %f, Vds %f, l = %s%s%s" % (gv, vds, ang_momenta_str, dimensions_str, route_str)
else:
obj_id = obj_name + ", GateV %f, Vds %f" % (gv, vds)
path = self.analysis_config_path + obj_id.replace(" ", "_") + ".nc"
obj_type = self.objects_enum[obj_name]
if (obj_name == "Dos"):
obj_type = self.config_type[1]
try:
#obj = nlread(path, obj_type, object_id=obj_id)
obj = nlread(path, object_id=obj_id)
obj = obj[0]
result = (True, obj)
except:
result = (False, None)
return result
def generate_transmission_spectrum (self):
print "Generating Transmission Spectrum "
transmission_spectrum = TransmissionSpectrum(
configuration=self.configuration_obj,
energies=numpy.linspace(-2,2,101)*eV,
self_energy_calculator=KrylovSelfEnergy(),
)
nlsave(self.device_config_path, transmission_spectrum, object_id="Trans, GateV %f, Vds %f" % (self.gv_obj(self.configuration_obj), self.vds_obj(self.configuration_obj)))
def generate_diff_pot (self):
print "Generating Difference Potential"
diff = ElectrostaticDifferencePotential (
configuration = self.configuration_obj,
)
self.sem_int.lock()
obj_id = "DiffPot, GateV %f, Vds %f" % (self.gv_obj(self.configuration_obj), self.vds_obj(self.configuration_obj))
obj_id = obj_id.replace(" ", "_")
path = self.analysis_config_path + obj_id + ".nc"
nlsave(path, diff, object_id=obj_id)
self.sem_int.release()
def generate_v_ext (self):
print "Generating V external"
v_ext = ExternalPotential (
configuration = self.configuration_obj,
)
self.sem_int.lock()
obj_id = "Vext, GateV %f, Vds %f" % (self.gv_obj(self.configuration_obj), self.vds_obj(self.configuration_obj))
obj_id = obj_id.replace(" ", "_")
path = self.analysis_config_path + obj_id + ".nc"
nlsave(path, v_ext, object_id=obj_id)
self.sem_int.release()
def generate_v_eff (self):
print "Generating Veff"
v_eff = EffectivePotential (
configuration = self.configuration_obj,
)
self.sem_int.lock()
obj_id = "Veff, GateV %f, Vds %f" % (self.gv_obj(self.configuration_obj), self.vds_obj(self.configuration_obj))
path = self.analysis_config_path + obj_id.replace(" ", "_") + ".nc"
nlsave(path, v_eff, object_id=obj_id)
self.sem_int.release()
def generate_e_diff_density (self):
print "Generating Electron Difference Density"
electron_diff_density = ElectronDifferenceDensity (
configuration = self.configuration_obj,
)
self.sem_int.lock()
obj_id = "Ediffdens, GateV %f, Vds %f" % (self.gv_obj(self.configuration_obj), self.vds_obj(self.configuration_obj))
path = self.analysis_config_path + obj_id.replace(" ", "_") + ".nc"
nlsave(path, electron_diff_density, object_id=obj_id)
self.sem_int.release()
def generate_e_density (self):
print "Generating Electron Density"
electron_density = ElectronDensity (
configuration = self.configuration_obj,
)
self.sem_int.lock()
obj_id = "Edens, GateV %f, Vds %f" % (self.gv_obj(self.configuration_obj), self.vds_obj(self.configuration_obj))
path = self.analysis_config_path + obj_id.replace(" ", "_") + ".nc"
nlsave(path, electron_density, object_id=obj_id)
self.sem_int.release()
def generate_chem_potential (self):
print "Generating Chemical Potential..."
chemical_potential = ChemicalPotential (
configuration = self.configuration_obj,
)
self.sem_int.lock()
obj_id = "ChemPot, GateV %f, Vds %f" % (self.gv_obj(self.configuration_obj), self.vds_obj(self.configuration_obj))
path = self.analysis_config_path + obj_id.replace(" ", "_") + ".nc"
nlsave(path, chemical_potential, object_id=obj_id)
self.sem_int.release()
def generate_dos_real_space (self):
print "Generate DOS real space"
gv = self.gv_obj(self.configuration_obj)
vds = self.vds_obj(self.configuration_obj)
energies = [round(x, 6) for x in self.dos_energy_range]
num_energies = len(energies)
done_nrg = []
lddos_list = []
#Try reading all the LDDOS objects at once, since reaidng individually takes a long time.
#if not (len(lddos_list) == num_energies):
for nrg in energies:
print "Reading LDDOS with energy: ", nrg, ", VGS = ", gv, " VDS = ", vds
result, lddos_obj = self.nlread_object("LDDOS", gv, vds, nrg=nrg)
#lddos_obj = nlread(path, LocalDeviceDensityOfStates, object_id=obj_id)
if lddos_obj:
rounded_nrg = round(lddos_obj.energy().inUnitsOf(eV)[0], 6)
done_nrg.append(rounded_nrg)
#only do energies which are not already done
energies = [x for x in energies if x not in done_nrg]
energies = [x*eV for x in energies]
for nrg in energies:
ldos = LocalDeviceDensityOfStates(
configuration=self.configuration_obj,
energy=nrg,
kpoints=MonkhorstPackGrid(2,2),
contributions=All,
energy_zero_parameter=AverageFermiLevel,
infinitesimal=1e-06*eV,
self_energy_calculator=KrylovSelfEnergy(),
)
#ldos = LocalDeviceDensityOfStates(configuration_obj , nrg, contributions=All)
self.sem_int.lock()
obj_id = "LDDOS %f, GateV %f, Vds %f" % (nrg.inUnitsOf(eV), self.gv_obj(self.configuration_obj), self.vds_obj(self.configuration_obj))
path = self.analysis_config_path + obj_id.replace(" ", "_") + ".nc"
nlsave(path, ldos, object_id=obj_id)
self.sem_int.release()
def generate_voltage_drop (self):
print "Generating Voltage Drop Object"
gv = self.gv_obj(self.configuration_obj)
vds = self.vds_obj(self.configuration_obj)
result, zero_volt_drop_obj = self.nlread_object("DiffPot", 0.0, 0.0)
if (not result):
self.set_default_voltages(gate_v=0*Volt, vds = 0*Volt)
self.generate_diff_pot()
result, zero_volt_drop_obj = self.nlread_object("DiffPot", 0.0, 0.0)
self.set_default_voltages(gate_v=gv*Volt, vds = vds*Volt)
result, volt_drop_obj = self.nlread_object("DiffPot", gv, vds)
if (not result):
self.generate_diff_pot()
result, volt_drop_obj = self.nlread_object("DiffPot", gv, vds)
vdrop_obj = zero_volt_drop_obj - volt_drop_obj
self.sem_int.lock()
obj_id = "VDrop, GateV %f, Vds %f" % (self.gv_obj(self.configuration_obj), self.vds_obj(self.configuration_obj))
obj_id = obj_id.replace(" ", "_")
path = self.analysis_config_path + obj_id + ".nc"
nlsave(path, vdrop_obj, object_id=obj_id)
self.sem_int.release()
def graph_voltage_drop (self):
print "Graphing Voltage drop..."
gv = self.gv_obj(self.configuration_obj)
vds = self.vds_obj(self.configuration_obj)
#try reading Vdrop object first
result, volt_drop_obj = self.nlread_object("VDrop", gv, vds)
if (not result):
self.generate_voltage_drop()
result, volt_drop_obj = self.nlread_object("VDrop", gv, vds)
outfile = open (self.device_config_path + "_VG_" + str(gv) + "V_VDS_"+ str(vds) + "_V_vdrop.plot", 'w')
outfile.write ('z, y, \g(d)V\-(H), x, y, \g(d)V\-(H)\n')
outfile.write ('Angstrom, Angstrom, V, Angstrom, Angstrom, V\n')
outfile.write ('x = %f, x = %f, x = %f, z = %f, z = %f, z = %f\n' % (self.x_coord_middle_atom, self.x_coord_middle_atom, self.x_coord_middle_atom,
self.z_coord_middle_atom, self.z_coord_middle_atom, self.z_coord_middle_atom))
#volt_drop_arr = volt_drop_obj.toArray()
#get array of y values in Angstrom
x_vol_elem = volt_drop_obj.volumeElement()[0][0]
y_vol_elem = volt_drop_obj.volumeElement()[1][1]
z_vol_elem = volt_drop_obj.volumeElement()[2][2]
num_x_elems = volt_drop_obj.shape()[0]
num_y_elems = volt_drop_obj.shape()[1]
num_z_elems = volt_drop_obj.shape()[2]
x_coord_list = []
y_coord_list_1 = []
z_coord_list = []
yz_voltage_list = []
xy_voltage_list = []
#draw picture for x = middle atom
x_coord = self.x_coord_middle_atom
for z in range(num_z_elems):
z_coord = z * z_vol_elem
for y in range(num_y_elems):
y_coord = y * y_vol_elem
yz_voltage = volt_drop_obj.evaluate (x_coord, y_coord, z_coord, Spin.Sum)
y_coord_list_1.append(str(y_coord.inUnitsOf(Angstrom)))
z_coord_list.append(str(z_coord.inUnitsOf(Angstrom)))
yz_voltage_list.append(str(yz_voltage.inUnitsOf(eV)))
y_coord_list_2 = []
z_coord = self.z_coord_middle_atom
for x in range(num_x_elems):
x_coord = x * x_vol_elem
for y in range(num_y_elems):
y_coord = y * y_vol_elem
xy_voltage = volt_drop_obj.evaluate (x_coord, y_coord, z_coord, Spin.Sum)
x_coord_list.append(str(x_coord.inUnitsOf(Angstrom)))
y_coord_list_2.append(str(y_coord.inUnitsOf(Angstrom)))
xy_voltage_list.append(str(xy_voltage.inUnitsOf(eV)))
final_zipped = itertools.izip_longest(z_coord_list, y_coord_list_1, yz_voltage_list,
x_coord_list, y_coord_list_2, xy_voltage_list)
final_list = [x for x in (map(lambda x: '-' if x == None else x, pair) for pair in final_zipped)]
writer = csv.writer (outfile, delimiter=',')
writer.writerows (final_list)
outfile.close()
def generate_voltage_drop_eff (self):
print "Generating Voltage Drop Effective Object"
gv = self.gv_obj(self.configuration_obj)
vds = self.vds_obj(self.configuration_obj)
result, zero_volt_drop_obj = self.nlread_object("Veff", 0.0, 0.0)
if (not result):
self.set_default_voltages(gate_v=0*Volt, vds = 0*Volt)
self.generate_v_eff()
result, zero_volt_drop_obj = self.nlread_object("Veff", 0.0, 0.0)
self.set_default_voltages(gate_v=gv*Volt, vds = vds*Volt)
result, volt_drop_obj = self.nlread_object("Veff", gv, vds)
if (not result):
self.generate_v_eff()
result, volt_drop_obj = self.nlread_object("Veff", gv, vds)
vdrop_obj = volt_drop_obj - zero_volt_drop_obj
self.sem_int.lock()
obj_id = "VDropEff, GateV %f, Vds %f" % (self.gv_obj(self.configuration_obj), self.vds_obj(self.configuration_obj))
obj_id = obj_id.replace(" ", "_")
path = self.analysis_config_path + obj_id + ".nc"
nlsave(path, vdrop_obj, object_id=obj_id)
self.sem_int.release()
def graph_voltage_drop_eff (self):
print "Graphing Voltage drop effective..."
gv = self.gv_obj(self.configuration_obj)
vds = self.vds_obj(self.configuration_obj)
#try reading Vdrop object first
result, volt_drop_obj = self.nlread_object("VDropEff", gv, vds)
if (not result):
self.generate_voltage_drop_eff()
result, volt_drop_obj = self.nlread_object("VDropEff", gv, vds)
outfile = open (self.device_config_path + "_VG_" + str(gv) + "V_VDS_"+ str(vds) + "_V_vdropeff.plot", 'w')
outfile.write ('z, y, \g(d)V\-(eff), x, y, \g(d)V\-(eff)\n')
outfile.write ('Angstrom, Angstrom, V, Angstrom, Angstrom, V\n')
outfile.write ('x = %f, x = %f, x = %f, z = %f, z = %f, z = %f\n' % (self.x_coord_middle_atom, self.x_coord_middle_atom, self.x_coord_middle_atom,
self.z_coord_middle_atom, self.z_coord_middle_atom, self.z_coord_middle_atom))
#volt_drop_arr = volt_drop_obj.toArray()
#get array of y values in Angstrom
x_vol_elem = volt_drop_obj.volumeElement()[0][0]
y_vol_elem = volt_drop_obj.volumeElement()[1][1]
z_vol_elem = volt_drop_obj.volumeElement()[2][2]
num_x_elems = volt_drop_obj.shape()[0]
num_y_elems = volt_drop_obj.shape()[1]
num_z_elems = volt_drop_obj.shape()[2]
vdrop_array = volt_drop_obj.toArray()
x_coord_list = []
y_coord_list_1 = []
z_coord_list = []
yz_voltage_list = []
xy_voltage_list = []
#draw picture for x = middle atom
x_coord = self.x_coord_middle_atom
x_index_frac = x_coord/self.x_length
#get the actual index of the x-coordinate
x_index = int(x_index_frac * np.shape(vdrop_array)[0])
for z in range(num_z_elems):
z_coord = z * z_vol_elem
for y in range(num_y_elems):
y_coord = y * y_vol_elem
yz_voltage = vdrop_array[x_index][y][z]
yz_voltage = yz_voltage * Hartree
y_coord_list_1.append(str(y_coord.inUnitsOf(Angstrom)))
z_coord_list.append(str(z_coord.inUnitsOf(Angstrom)))
yz_voltage_list.append(str(yz_voltage.inUnitsOf(eV)))
#print y
y_coord_list_2 = []
z_coord = self.z_coord_middle_atom
z_index_frac = z_coord/self.z_length
#get the actual index of the x-coordinate
z_index = int(z_index_frac * np.shape(vdrop_array)[2])
for x in range(num_x_elems):
x_coord = x * x_vol_elem
for y in range(num_y_elems):
y_coord = y * y_vol_elem
xy_voltage = vdrop_array[x][y][z_index]
xy_voltage = xy_voltage * Hartree
x_coord_list.append(str(x_coord.inUnitsOf(Angstrom)))
y_coord_list_2.append(str(y_coord.inUnitsOf(Angstrom)))
xy_voltage_list.append(str(xy_voltage.inUnitsOf(eV)))
final_zipped = itertools.izip_longest(z_coord_list, y_coord_list_1, yz_voltage_list,
x_coord_list, y_coord_list_2, xy_voltage_list)
final_list = [x for x in (map(lambda x: '-' if x == None else x, pair) for pair in final_zipped)]
writer = csv.writer (outfile, delimiter=',')
writer.writerows (final_list)
outfile.close()
def graph_efield (self):
print "Graphing Electric Field ..."
gv = self.gv_obj(self.configuration_obj)
vds = self.vds_obj(self.configuration_obj)
#try reading Vdrop object first
result, volt_drop_obj = self.nlread_object("VDrop", gv, vds)
if (not result):
self.generate_voltage_drop()
result, volt_drop_obj = self.nlread_object("VDrop", gv, vds)
outfile = open (self.device_config_path + "_VG_" + str(gv) + "V_VDS_"+ str(vds) + "_V_efield.plot", 'w')
outfile.write ('z, y, \\ab(E), x, y, \\ab(E)\n')
outfile.write ('Angstrom, Angstrom, V/cm, Angstrom, Angstrom, V/cm\n')
outfile.write ('x = %f, x = %f, x = %f, z = %f, z = %f, z = %f\n' % (self.x_coord_middle_atom, self.x_coord_middle_atom, self.x_coord_middle_atom,
self.z_coord_middle_atom, self.z_coord_middle_atom, self.z_coord_middle_atom))
#volt_drop_arr = volt_drop_obj.toArray()
#get array of y values in Angstrom
x_vol_elem = volt_drop_obj.volumeElement()[0][0]
y_vol_elem = volt_drop_obj.volumeElement()[1][1]
z_vol_elem = volt_drop_obj.volumeElement()[2][2]
num_x_elems = volt_drop_obj.shape()[0]
num_y_elems = volt_drop_obj.shape()[1]
num_z_elems = volt_drop_obj.shape()[2]
x_coord_list = []
y_coord_list_1 = []
z_coord_list = []
yz_field_list = []
xy_field_list = []
#draw picture for x = middle atom
x_coord = self.x_coord_middle_atom
for z in range(num_z_elems):
z_coord = z * z_vol_elem
for y in range(num_y_elems):
y_coord = y * y_vol_elem
yz_field = volt_drop_obj.derivatives (x_coord, y_coord, z_coord, Spin.Sum)[2].inUnitsOf(eV/(Meter))/100
y_coord_list_1.append(str(y_coord.inUnitsOf(Angstrom)))
z_coord_list.append(str(z_coord.inUnitsOf(Angstrom)))
yz_field_list.append(str(yz_field))
y_coord_list_2 = []
z_coord = self.z_coord_middle_atom
for x in range(num_x_elems):
x_coord = x * x_vol_elem
for y in range(num_y_elems):
y_coord = y * y_vol_elem
xy_field = volt_drop_obj.derivatives (x_coord, y_coord, z_coord, Spin.Sum)[2].inUnitsOf(eV/(Meter))/100
x_coord_list.append(str(x_coord.inUnitsOf(Angstrom)))
y_coord_list_2.append(str(y_coord.inUnitsOf(Angstrom)))
xy_field_list.append(str(xy_field))
final_zipped = itertools.izip_longest(z_coord_list, y_coord_list_1, yz_field_list,
x_coord_list, y_coord_list_2, xy_field_list)
final_list = [x for x in (map(lambda x: '-' if x == None else x, pair) for pair in final_zipped)]
writer = csv.writer (outfile, delimiter=',')
writer.writerows (final_list)
outfile.close()
def graph_diff_pot (self):
print "Graphing Difference Potential"
gv = self.gv_obj(self.configuration_obj)
vds = self.vds_obj(self.configuration_obj)
result, diff_potential_obj = self.nlread_object("DiffPot", gv, vds)
if (not result):
self.generate_diff_pot()
result, diff_potential_obj = self.nlread_object("DiffPot", gv, vds)
proj_x_arr = []
proj_y_arr = []
#proj_x = diff_potential_obj.axisProjection ('Line', 'A', Spin.Sum, projection_point_x)
#proj_y = diff_potential_obj.axisProjection ('Line', 'B', Spin.Sum, projection_point_y)
proj_x_arr.append(diff_potential_obj.axisProjection ('Line', 'A', Spin.Sum, self.projection_point_x_0))
proj_y_arr.append(diff_potential_obj.axisProjection ('Line', 'B', Spin.Sum, self.projection_point_y_0))
proj_x_arr.append(diff_potential_obj.axisProjection ('Line', 'A', Spin.Sum, self.projection_point_x_1))
proj_y_arr.append(diff_potential_obj.axisProjection ('Line', 'B', Spin.Sum, self.projection_point_y_1))
#proj_x = diff_potential_obj.axisProjection ('Average', 'A', Spin.Sum)
#proj_y = diff_potential_obj.axisProjection ('Average', 'B', Spin.Sum)
#proj_z = diff_potential_obj.axisProjection ('Average', 'C', Spin.Sum)
#proj [0] = fractional coords
#proj [1] = potential at the coordinate
outfile = open (self.device_config_path + "_VG_" + str(gv) + "V_VDS_"+ str(vds) + "_V_diffpot.plot", 'w')
outfile.write ('x, \g(d)V\-(H), \g(d)V\-(H), y, \g(d)V\-(H), \g(d)V\-(H)\n')
outfile.write ('Angstrom, eV, eV, Angstrom, eV, eV\n')
outfile.write ('x, \g(d)V\-(H)_X_2_atoms, \g(d)V\-(H)_X_3_atoms, y, \g(d)V\-(H)_Y_2_atoms, \g(d)V\-(H)_Y_2_atoms\n')
length_x_coords = len(proj_x_arr[0][0])
length_y_coords = len(proj_y_arr[0][0])
j = 0
i = 0
max_index = max(length_x_coords,length_x_coords)
k = 0
done_x = False
done_y = False
while (k < max_index):
if (not done_y):
y_angstrom_0 = str(self.frac_to_cart(self.y_length, proj_y_arr[0][0][j]).inUnitsOf(Angstrom))
y_angstrom_1 = str(self.frac_to_cart(self.y_length, proj_y_arr[1][0][j]).inUnitsOf(Angstrom))
y_energy_0 = str(proj_y_arr[0][1][j].inUnitsOf(eV))
y_energy_1 = str(proj_y_arr[1][1][j].inUnitsOf(eV))
if (not done_x):
x_angstrom_0 = str(self.frac_to_cart(self.x_length, proj_x_arr[0][0][i]).inUnitsOf(Angstrom))
x_angstrom_1 = str(self.frac_to_cart(self.x_length, proj_x_arr[1][0][i]).inUnitsOf(Angstrom))
x_energy_0 = str(proj_x_arr[0][1][i].inUnitsOf(eV))
x_energy_1 = str(proj_x_arr[1][1][i].inUnitsOf(eV))
j = j+1
i = i+1
k = k+1
if (i >= length_x_coords):
done_x = True
x_angstrom_0 = '-'
x_energy_0 = '-'
x_energy_1 = '-'
if (j >= length_y_coords):
done_y = True
y_angstrom_0 = '-'
y_energy_0 = '-'
y_energy_1 = '-'
outfile.write (x_angstrom_0 + ',')
outfile.write (x_energy_0 + ',')
outfile.write (x_energy_1 + ',')
outfile.write (y_angstrom_0 + ',')
outfile.write (y_energy_0 + ',')
outfile.write (y_energy_1)
outfile.write ('\n')
outfile.close()
def graph_v_ext (self):
print "Graphing Vext"
gv = self.gv_obj(self.configuration_obj)
vds = self.vds_obj(self.configuration_obj)
result, ext_pot_obj = self.nlread_object("Vext", gv, vds)
if (not result):
self.generate_v_ext ()
result, ext_pot_obj = self.nlread_object("Vext", gv, vds)
proj_x_arr = []
proj_y_arr = []
#proj_x = diff_potential_obj.axisProjection ('Line', 'A', Spin.Sum, projection_point_x)
#proj_y = diff_potential_obj.axisProjection ('Line', 'B', Spin.Sum, projection_point_y)
proj_x_arr.append(ext_pot_obj.axisProjection ('Line', 'A', Spin.Sum, self.projection_point_x_0))
proj_y_arr.append(ext_pot_obj.axisProjection ('Line', 'B', Spin.Sum, self.projection_point_y_0))
proj_x_arr.append(ext_pot_obj.axisProjection ('Line', 'A', Spin.Sum, self.projection_point_x_1))
proj_y_arr.append(ext_pot_obj.axisProjection ('Line', 'B', Spin.Sum, self.projection_point_y_1))
outfile = open (self.device_config_path + "_VG_" + str(gv) + "V_VDS_"+ str(vds) + "_V_vext.plot", 'w')
outfile.write ('x, V\-(ext), V\-(ext), y, V\-(ext), V\-(ext)\n')
outfile.write ('Angstrom, eV, eV, Angstrom, eV, eV\n')
outfile.write ('x, V\-(ext_X_2_atoms), V\-(ext_X_3_atoms), y, V\-(ext_Y_2_atoms), V\-(ext_Y_3_atoms)\n')
length_x_coords = len(proj_x_arr[0][0])
length_y_coords = len(proj_y_arr[0][0])
j = 0
i = 0
max_index = max(length_x_coords,length_x_coords)
k = 0
done_x = False
done_y = False
while (k < max_index):
if (not done_y):
y_angstrom_0 = str(self.frac_to_cart(self.y_length, proj_y_arr[0][0][j]).inUnitsOf(Angstrom))
y_angstrom_1 = str(self.frac_to_cart(self.y_length, proj_y_arr[1][0][j]).inUnitsOf(Angstrom))
y_energy_0 = str(proj_y_arr[0][1][j].inUnitsOf(eV))
y_energy_1 = str(proj_y_arr[1][1][j].inUnitsOf(eV))
if (not done_x):
x_angstrom_0 = str(self.frac_to_cart(self.x_length, proj_x_arr[0][0][i]).inUnitsOf(Angstrom))
x_angstrom_1 = str(self.frac_to_cart(self.x_length, proj_x_arr[1][0][i]).inUnitsOf(Angstrom))
x_energy_0 = str(proj_x_arr[0][1][i].inUnitsOf(eV))
x_energy_1 = str(proj_x_arr[1][1][i].inUnitsOf(eV))
j = j+1
i = i+1
k = k+1
if (i >= length_x_coords):
done_x = True
x_angstrom_0 = '-'
x_energy_0 = '-'
x_energy_1 = '-'
if (j >= length_y_coords):
done_y = True
y_angstrom_0 = '-'
y_energy_0 = '-'
y_energy_1 = '-'
#printing VEFF for x direction
outfile.write (x_angstrom_0 + ',')
outfile.write (x_energy_0 + ',')
outfile.write (x_energy_1 + ',')
outfile.write (y_angstrom_0 + ',')
outfile.write (y_energy_0 + ',')
outfile.write (y_energy_1)
outfile.write ('\n')
outfile.close()
def graph_v_eff (self):
print "Graphing Veff"
gv = self.gv_obj(self.configuration_obj)
vds = self.vds_obj(self.configuration_obj)
result, effective_potential_obj = self.nlread_object("Veff", gv, vds)
if (not result):
self.generate_v_eff ()
result, effective_potential_obj = self.nlread_object("Veff", gv, vds)
outfile = open (self.device_config_path + "_VG_" + str(gv) + "V_VDS_"+ str(vds) + "_V_veff.plot", 'w')
outfile.write ('z, y, V\-(eff), x, y, V\-(eff)\n')
outfile.write ('Angstrom, Angstrom, V, Angstrom, Angstrom, V\n')
outfile.write ('x = %f, x = %f, x = %f, z = %f, z = %f, z = %f\n' % (self.x_coord_middle_atom, self.x_coord_middle_atom, self.x_coord_middle_atom,
self.z_coord_middle_atom, self.z_coord_middle_atom, self.z_coord_middle_atom))
#get array of y values in Angstrom
x_vol_elem = effective_potential_obj.volumeElement()[0][0]
y_vol_elem = effective_potential_obj.volumeElement()[1][1]
z_vol_elem = effective_potential_obj.volumeElement()[2][2]
num_x_elems = effective_potential_obj.shape()[0]
num_y_elems = effective_potential_obj.shape()[1]
num_z_elems = effective_potential_obj.shape()[2]
eff_pot_array = effective_potential_obj.toArray()
x_coord_list = []
y_coord_list_1 = []
z_coord_list = []
yz_voltage_list = []
xy_voltage_list = []
#draw picture for x = middle atom
x_coord = self.x_coord_middle_atom
x_index_frac = x_coord/self.x_length
#get the actual index of the x-coordinate
x_index = int(x_index_frac * np.shape(eff_pot_array)[0])
for z in range(num_z_elems):
z_coord = z * z_vol_elem
for y in range(num_y_elems):
y_coord = y * y_vol_elem
yz_voltage = eff_pot_array[x_index][y][z]
yz_voltage = yz_voltage * Hartree
y_coord_list_1.append(str(y_coord.inUnitsOf(Angstrom)))
z_coord_list.append(str(z_coord.inUnitsOf(Angstrom)))
yz_voltage_list.append(str(yz_voltage.inUnitsOf(eV)))
#print y
y_coord_list_2 = []
z_coord = self.z_coord_middle_atom
z_index_frac = z_coord/self.z_length
#get the actual index of the x-coordinate
z_index = int(z_index_frac * np.shape(eff_pot_array)[2])
for x in range(num_x_elems):
x_coord = x * x_vol_elem
for y in range(num_y_elems):
y_coord = y * y_vol_elem
xy_voltage = eff_pot_array[x][y][z_index]
xy_voltage = xy_voltage * Hartree
x_coord_list.append(str(x_coord.inUnitsOf(Angstrom)))
y_coord_list_2.append(str(y_coord.inUnitsOf(Angstrom)))
xy_voltage_list.append(str(xy_voltage.inUnitsOf(eV)))
final_zipped = itertools.izip_longest(z_coord_list, y_coord_list_1, yz_voltage_list,
x_coord_list, y_coord_list_2, xy_voltage_list)
final_list = [x for x in (map(lambda x: '-' if x == None else x, pair) for pair in final_zipped)]
writer = csv.writer (outfile, delimiter=',')
writer.writerows (final_list)
outfile.close()
def graph_e_density (self):
print "Graphing E density"
gv = self.gv_obj(self.configuration_obj)
vds = self.vds_obj(self.configuration_obj)
#try reading Vdrop object first
result, e_dens_obj = self.nlread_object("Edens", gv, vds)
if (not result):
self.generate_e_density()
result, e_dens_obj = self.nlread_object("Edens", gv, vds)
outfile = open (self.device_config_path + "_VG_" + str(gv) + "V_VDS_"+ str(vds) + "_V_edens.plot", 'w')
outfile.write ('z, y, n, x, y, n\n')
outfile.write ('Angstrom, Angstrom, cm\+(-3), Angstrom, Angstrom, cm\+(-3)\n')
outfile.write ('x = %f, x = %f, x = %f, z = %f, z = %f, z = %f\n' % (self.x_coord_middle_atom, self.x_coord_middle_atom, self.x_coord_middle_atom,
self.z_coord_middle_atom, self.z_coord_middle_atom, self.z_coord_middle_atom))
#volt_drop_arr = volt_drop_obj.toArray()
#get array of y values in Angstrom
x_vol_elem = e_dens_obj.volumeElement()[0][0]
y_vol_elem = e_dens_obj.volumeElement()[1][1]
z_vol_elem = e_dens_obj.volumeElement()[2][2]
num_x_elems = e_dens_obj.shape()[0]
num_y_elems = e_dens_obj.shape()[1]
num_z_elems = e_dens_obj.shape()[2]
x_coord_list = []
y_coord_list_1 = []
z_coord_list = []
yz_e_dens_list = []
xy_e_dens_list = []
#draw picture for x = middle atom
x_coord = self.x_coord_middle_atom
for z in range(num_z_elems):
z_coord = z * z_vol_elem
for y in range(num_y_elems):
y_coord = y * y_vol_elem
yz_e_dens = e_dens_obj.evaluate (x_coord, y_coord, z_coord, Spin.Sum)
y_coord_list_1.append(str(y_coord.inUnitsOf(Angstrom)))
z_coord_list.append(str(z_coord.inUnitsOf(Angstrom)))
yz_e_dens_list.append(str(yz_e_dens.inUnitsOf(Meter**-3)/10**6))
y_coord_list_2 = []
z_coord = self.z_coord_middle_atom
for x in range(num_x_elems):
x_coord = x * x_vol_elem
for y in range(num_y_elems):
y_coord = y * y_vol_elem
xy_e_dens = e_dens_obj.evaluate (x_coord, y_coord, z_coord, Spin.Sum)
x_coord_list.append(str(x_coord.inUnitsOf(Angstrom)))
y_coord_list_2.append(str(y_coord.inUnitsOf(Angstrom)))
xy_e_dens_list.append(str(xy_e_dens.inUnitsOf(Meter**-3)/10**6))
final_zipped = itertools.izip_longest(z_coord_list, y_coord_list_1, yz_e_dens_list,
x_coord_list, y_coord_list_2, xy_e_dens_list)
final_list = [x for x in (map(lambda x: '-' if x == None else x, pair) for pair in final_zipped)]
writer = csv.writer (outfile, delimiter=',')
writer.writerows (final_list)
outfile.close()
def graph_e_diff_density (self):
print "Graphing E diff density"
gv = self.gv_obj(self.configuration_obj)
vds = self.vds_obj(self.configuration_obj)
result, edensity_obj = self.nlread_object("Ediffdens", gv, vds)
if (not result):
self.generate_e_diff_density()
result, edensity_obj = self.nlread_object("Ediffdens", gv, vds)
proj_x_arr = []
proj_y_arr = []
proj_x_arr.append(edensity_obj.axisProjection ('Line', 'A', Spin.Sum, self.projection_point_x_0))
proj_y_arr.append(edensity_obj.axisProjection ('Line', 'B', Spin.Sum, self.projection_point_y_0))
proj_x_arr.append(edensity_obj.axisProjection ('Line', 'A', Spin.Sum, self.projection_point_x_1))
proj_y_arr.append(edensity_obj.axisProjection ('Line', 'B', Spin.Sum, self.projection_point_y_1))
outfile = open (self.device_config_path + "_VG_" + str(gv) + "V_VDS_"+ str(vds) + "_V_ediffdensity.plot", 'w')
outfile.write ('x, \g(d)n, \g(d)n, y, \g(d)n, \g(d)n\n')
outfile.write ('Angstrom, cm\+(-3), cm\+(-3), Angstrom, cm\+(-3), cm\+(-3)\n')
outfile.write ('x, \g(d)n_x_2_atoms, \g(d)n_x_3_atoms, y, \g(d)n_y_2_atoms, \g(d)n_y_3_atoms\n')
length_x_coords = len(proj_x_arr[0][0])
length_y_coords = len(proj_y_arr[0][0])
j = 0
i = 0
max_index = max(length_x_coords,length_x_coords)
k = 0
done_x = False
done_y = False
while (k < max_index):
if (not done_y):
y_angstrom_0 = str(self.frac_to_cart(self.y_length, proj_y_arr[0][0][j]).inUnitsOf(Angstrom))
y_angstrom_1 = str(self.frac_to_cart(self.y_length, proj_y_arr[1][0][j]).inUnitsOf(Angstrom))
#y_density_0 = str(proj_y_arr[0][1][j].inUnitsOf(Angstrom**-3))
#y_density_1 = str(proj_y_arr[1][1][j].inUnitsOf(Angstrom**-3))
y_density_0 = str(proj_y_arr[0][1][j].inUnitsOf(Meter**-3)/10**6)
y_density_1 = str(proj_y_arr[1][1][j].inUnitsOf(Meter**-3)/10**6)
if (not done_x):
x_angstrom_0 = str(self.frac_to_cart(self.x_length, proj_x_arr[0][0][i]).inUnitsOf(Angstrom))
x_angstrom_1 = str(self.frac_to_cart(self.x_length, proj_x_arr[1][0][i]).inUnitsOf(Angstrom))
#x_density_0 = str(proj_x_arr[0][1][i].inUnitsOf(Angstrom**-3))
#x_density_1 = str(proj_x_arr[1][1][i].inUnitsOf(Angstrom**-3))
x_density_0 = str(proj_x_arr[0][1][i].inUnitsOf(Meter**-3)/10**6)
x_density_1 = str(proj_x_arr[1][1][i].inUnitsOf(Meter**-3)/10**6)
j = j+1
i = i+1
k = k+1
if (i >= length_x_coords):
done_x = True
x_angstrom_0 = '-'
x_density_0 = '-'
x_density_1 = '-'
if (j >= length_y_coords):
done_y = True
y_angstrom_0 = '-'
y_density_0 = '-'
y_density_1 = '-'
#printing VEFF for x direction
outfile.write (x_angstrom_0 + ',')
outfile.write (x_density_0 + ',')
outfile.write (x_density_1 + ',')
outfile.write (y_angstrom_0 + ',')
outfile.write (y_density_0 + ',')
outfile.write (y_density_1)
outfile.write ('\n')
outfile.close()
def lddos_worker (self, axis, obj, result_dict):
#print "Starting worker for axis: ", axis
start_time = time.time()
dd={}
st = time.time()
axisProj = obj.axisProjection ('Average', axis, Spin.Sum)
#print "Time taken for axisProj = ", str (time.time() - st)
st = time.time()
fracs = [float(x) for x in axisProj[0]]
#print "Time taken for fracs = ", str (time.time() - st)
st = time.time()
vals = [x.inUnitsOf(Hartree**-1 * Angstrom**-3) for x in axisProj[1]]
#print "Time taken for vals comprehension = ", str (time.time() - st)
#dd[axis] = axisProj
#print dd
#print dd
#result_dict.update(dd)
st = time.time()
result_dict[axis] = (fracs, vals)
#print "Time taken for appending to dict = ", str (time.time() - st)
end_time = time.time()
print "Time taken for LDDOS_WORKER = ", str (end_time - start_time)
#print "Ending worker for axis: ", axis
def lddos_multi_nrg_worker (self, obj, result_string_lst):
nprocs = 3
procs = []
manager = multiprocessing.Manager()
result_dict=manager.dict()
energy = obj.energy()[0]
#start
axis = ['A','B','C']
for i in range(nprocs):
p = multiprocessing.Process (target=self.lddos_worker,
args=(axis[i],obj, result_dict))
procs.append(p)
p.start()
for p in procs:
p.join()
start_time = time.time()
proj_x = []
proj_x.append(result_dict[axis[0]][0])
proj_x.append(result_dict[axis[0]][1])
proj_y = []
proj_y.append(result_dict[axis[1]][0])
proj_y.append(result_dict[axis[1]][1])
proj_z = []
proj_z.append(result_dict[axis[2]][0])
proj_z.append(result_dict[axis[2]][1])
#proj_x = obj.axisProjection ('Average', 'A', Spin.Sum)
#proj_y = obj.axisProjection ('Average', 'B', Spin.Sum)
#proj_z = obj.axisProjection ('Average', 'C', Spin.Sum)
print "Printing LDDOS for Energy = ", str(energy.inUnitsOf(eV)),
print "\n"
length_x_coords = len(proj_x[0])
length_y_coords = len(proj_y[0])
length_z_coords = len(proj_z[0])
j = 0
i = 0
k = 0
max_index = max(length_x_coords,length_x_coords, length_z_coords)
l = 0
done_x = False
done_y = False
done_z = False
#setting up the dictionary to store all the values in
energy_float = float(energy.inUnitsOf(eV))
final_str_list = []
while (l < max_index):
if (not done_x):
x_angstrom = str(self.frac_to_cart(self.x_length, proj_x[0][i]).inUnitsOf(Angstrom))
x_states = (str(proj_x[1][i]))
if (not done_y):
y_angstrom = str(self.frac_to_cart(self.y_length, proj_y[0][j]).inUnitsOf(Angstrom))
y_states = (str(proj_y[1][j]))
if (not done_z):
z_angstrom = str(self.frac_to_cart(self.z_length, proj_z[0][k]).inUnitsOf(Angstrom))
z_states = (str(proj_z[1][k]))
i = i + 1
j = j + 1
k = k + 1
l = l + 1
if (i >= length_x_coords):
done_x = True
x_angstrom = '-'
x_states = '-'
if (j >= length_y_coords):
done_y = True
y_angstrom = '-'
y_states = '-'
if (k >= length_z_coords):
done_z = True
z_angstrom = '-'
z_states = '-'
if (done_y and done_x and done_z):
continue
energy_str = str(energy.inUnitsOf(eV))
#For x coords
final_string = (x_angstrom + ',')
final_string = final_string + (energy_str + ',')
final_string = final_string + (x_states + ',')
# For y coords
final_string = final_string + (y_angstrom + ',')
final_string = final_string + (energy_str + ',')
final_string = final_string + (y_states + ',')
# For z coords
final_string = final_string + (z_angstrom + ',')
final_string = final_string + (energy_str + ',')
final_string = final_string + (z_states)
final_string = final_string + '\n'
final_str_list.append(final_string)
end_time = time.time()
#print "Time taken to print one energy point: ", str (end_time - start_time)
result_string_lst[energy_float] = final_str_list
def graph_dos_real_space (self):
print "Graphing LDDOS Real Space"
gv = self.gv_obj(self.configuration_obj)
vds = self.vds_obj(self.configuration_obj)
start = time.time()
#@TODO UNCOMMENT THIS
self.generate_dos_real_space()
energies = [round(x, 6) for x in self.dos_energy_range]
#print "NUMBER OF LDDSO BJECTS"
#print len(nlread(self.device_config_path, LocalDeviceDensityOfStates))
outfile = open (self.device_config_path + "_VG_" + str(gv) + "V_VDS_"+ str(vds) + '_V_lddos.plot', 'w')
outfile.write ('x, Energy, States, y, Energy, States, z, Energy, States\n')
outfile.write ('Angstrom, eV, arb. units, Angstrom, eV, arb. units, Angstrom, eV, arb. units\n')
outfile.write ('x, Energy, Number of States, y, Energy, Number of States, z, Energy, Number of States\n')
final_out_dict = {}
nprocs = self.nprocessors
#start
#endj
for nrg_idx in range(0, len(energies), nprocs):
lddos_list = []
for k in range(nprocs):
nrg = energies[nrg_idx + k]
print "Reading LDDOS with energy: ", nrg, ", VGS = ", gv, " VDS = ", vds
result, lddos_obj = self.nlread_object("LDDOS", gv, vds, nrg=nrg)
lddos_list.append(lddos_obj)
for k in range(0, len(lddos_list), nprocs):
procs = []
manager = multiprocessing.Manager()
result_string_lst=manager.dict()
start_loop_time = time.time()
for i in range(nprocs):
p = multiprocessing.Process (target=self.lddos_multi_nrg_worker,
args=(lddos_list[k+i], result_string_lst))
procs.append(p)
p.start()
for p in procs:
p.join()
#append result dictionary to total dict with all energies
final_out_dict.update(result_string_lst)
time_per_iter = time.time() - start_loop_time
print "Time Taken: ", time_per_iter
print "\n"
od = collections.OrderedDict(sorted(final_out_dict.items()))
for k, v in od.iteritems():
for line in v:
outfile.write (line)
#printing z fractional coords
#outfile.write ('START_DATA|X|z|2\n')
#for i in proj_z[0]:
#outfile.write (str(i) + '\n')
#outfile.write ('END_DATA\n')
##printing energies for y direction
#outfile.write ('START_DATA|Y|n_z|0|2|kv-\n')
#for i in proj_z[1]:
#outfile.write (str(i.inUnitsOf(Angstrom**-3)) + '\n')
#outfile.write ('END_DATA\n')
outfile.close()
end = time.time()
total = end -start
print "Total Time Passed for Graphing real Space DOS Function ", total
def graph_dos_real_space_atk (self):
#print "NUMBER OF LDDSO BJECTS"
#te = nlread(self.device_config_path, LocalDeviceDensityOfStates)
#self.generate_dos_real_space()
gv = self.gv_obj(self.configuration_obj)
vds = self.vds_obj(self.configuration_obj)
energies = np.linspace(-5, 5, num = 10)
energies = [round(x, 6) for x in energies]
lddos_list = []
for nrg in energies:
print "Reading LDDOS with energy: ", nrg, ", VGS = ", gv, " VDS = ", vds
obj_id = "LDDOS %f, GateV %f, Vds %f" % (nrg, gv, vds)
obj_id = obj_id.replace(" ", "_")
path = self.analysis_config_path + obj_id + ".nc"
lddos_obj = nlread(path, LocalDeviceDensityOfStates, object_id=obj_id)
lddos_list.append(lddos_obj[0])
#Find the z-spacing
dX, dY, dZ = lddos_list[0].volumeElement().convertTo(Ang)
dz = dZ.norm()
shape = lddos_list[0].shape()
z = dz * numpy.arange(shape[2])
# calculate average lddos along z for each spectrum
energies = []
lddos_z = []
for lddos in lddos_list:
energies = energies + [lddos.energy().inUnitsOf(eV)]
avg_z = numpy.apply_over_axes(numpy.mean,lddos[:,:,:],[0,1]).flatten()
lddos_z = lddos_z + [avg_z]
# plot as contour plot
# make variables
energies = numpy.array(energies)
X, Y = numpy.meshgrid(z, energies)
Z = numpy.array(lddos_z).reshape(numpy.shape(X))
#print "X = "
#print X
#print "Y = "
#print Y
#print "Z = "
#print Z
#print "X min, max"
#print numpy.amax(X)
#print numpy.amin(X)
#print "Y min, max"
#print numpy.amax(Y)
#print numpy.amin(Y)
#print "Z min, max"
#print numpy.amax(Z)
#print numpy.amin(Z)
outfile = open (self.device_config_path + "_VG_" + str(gv) + "V_VDS_"+ str(vds) + '_V_lddos.plot', 'w')
outfile.write ('z, Energy, States\n')
outfile.write ('Angstrom, eV, arb. units\n')
outfile.write ('z, Energy, Number of States\n')
for z_coord in Z:
print z_coord
#plot the LDDOS(E, z)
pylab.xlabel('z (Angstrom)',fontsize=12,family='sans-serif')
pylab.ylabel('Energy (eV)',fontsize=12,family='sans-serif')
contour_values = numpy.linspace(0 , numpy.amax(Z), 25)
pylab.contourf(X, Y, Z, contour_values)
pylab.colorbar()
pylab.axis([numpy.amin(X), numpy.amax(X), numpy.amin(Y), numpy.amax(Y)])
pylab.title(self.device_config_path + ": E vs. z")
pylab.savefig(self.device_config_path + "_VG_" + str(gv) + "V_VDS_"+ str(vds) + '_V_lddos.png',dpi=100)
#pylab.show()
def graph_density_of_states (self):
print "Graphing Density of States"
gv = self.gv_obj(self.configuration_obj)
vds = self.vds_obj(self.configuration_obj)
print "DOS, GateV %f, Vds %f" % (gv, vds)
result, dos_obj = self.nlread_object("Dos", gv, vds)
if (not result):
self.generate_density_of_states ()
result, dos_obj = self.nlread_object("Dos", gv, vds)
if not self.ang_momenta:
ang_momenta_str = 'all'
else:
ang_momenta_str = str(self.ang_momenta)
ang_momenta_str = ang_momenta_str.replace('[','')
ang_momenta_str = ang_momenta_str.replace(']','')
outfile = open (self.device_config_path +
"_VG_" + str(gv) +
"_VDS_"+ str(vds) +
"_l=" + ang_momenta_str +
"_dos.plot", 'w')
outfile.write ('Energy, Density of States\n')
outfile.write ('eV, 1/eV\n')
energies = dos_obj.energies()
num_atoms = len(dos_obj.elements())
#dos_obj.nlprint()
#sys.exit()
if self.ang_momenta:
final_dos = dos_obj.evaluate(projection_list = ProjectionList(angular_momenta = self.ang_momenta))
else:
final_dos = dos_obj.evaluate()
j = 0
for i in final_dos:
outfile.write (str(energies[j].inUnitsOf(eV))+',')
outfile.write (str(i.inUnitsOf(eV**-1)) + '\n')
j = j + 1
outfile.close()
def graph_transmission_spectrum (self):
print "Graphing Transmission spectrum"
gv = self.gv_obj(self.configuration_obj)
vds = self.vds_obj(self.configuration_obj)
print "Trans, GateV %f, Vds %f" % (gv, vds)
#get the DOS object for the gate voltage we're working wiht
trans_objects = nlread(self.device_config_path, TransmissionSpectrum, object_id="Trans, GateV %f, Vds %f" % (gv, vds))
if not trans_objects:
self.generate_transmission_spectrum ()
#trans_objects = nlread(self.device_config_path, TransmissionSpectrum, object_id="Trans, GateV %f, Vds %f" % (gv, vds))
else:
print "Using existing transmission spectrum"
self.print_currents_file ()
def graph_chem_potential (self):
print "Graphing chemical potential..."
gv = self.gv_obj(self.configuration_obj)
vds = self.vds_obj(self.configuration_obj)
result, chem_pot_obj = self.nlread_object("ChemPot", gv, vds)
if (not result):
self.generate_chem_potential ()
result, chem_pot_obj = self.nlread_object("ChemPot", gv, vds)
def print_currents_file (self, currents_plot_file=None):
if currents_plot_file is None:
currents_plot_file = self.device_config_path + 'currents.plot'
if os.path.isfile(currents_plot_file):
print "Currents file exists, moving file and creating new file..."
found = True
num = 1
while (found and num < 3):
bak_file_name = currents_plot_file + '.' + str(num)
if os.path.isfile(bak_file_name):
num = num + 1
else:
shutil.copy (currents_plot_file, bak_file_name)
found = False
outfile = open (currents_plot_file, 'w')
outfile.write ("V\-(GS), V\-(DS), Current\n")
outfile.write ("V, V, µA\n")
#holds all objects. need to extract transmissionspectrum objects
all_nc_keys = nlinspect(self.device_config_path)
trans_objects_ids = []
for key in all_nc_keys:
if key[0] == 'TransmissionSpectrum':
trans_objects_ids.append (key)
#trans_objects_ids: [0] = TransmissionSpectrum.
#[1] = object_id
#[2] = Fingerprint
#Sort the Trans objects by voltage first for printing
#tuple of (gate_v, vds)
sorted_voltages = []
for trans_obj in trans_objects_ids:
#extracting the vds and gate voltage
object_id = trans_obj[1]
search_obj = re.search (r'Trans, GateV ([-0-9.]+), Vds ([-0-9.]+)$', object_id, re.M)
if search_obj:
gate_v = float(search_obj.group(1))
vds = float(search_obj.group(2))
sorted_voltages.append ((gate_v, vds))
#sort by Vds
sorted_voltages.sort(key=lambda tup: tup[0])
for trans_obj in trans_objects_ids:
#extracting the vds and gate voltage
object_id = trans_obj[1]
search_obj = re.search (r'Trans, GateV ([-0-9.]+), Vds ([-0-9.]+)$', object_id, re.M)
if search_obj:
gate_v = float(search_obj.group(1))
vds = float(search_obj.group(2))
sorted_voltages.append ((gate_v, vds))
trans_objects = nlread(self.device_config_path, TransmissionSpectrum, object_id="Trans, GateV %f, Vds %f" % (gate_v, vds))
trans_object = trans_objects [0]
print trans_object.energyZero()
current_in_uA = trans_object.current().inUnitsOf(Ampere) * 10**6
outfile.write (str(gate_v) + "," + str (vds) + "," + str (current_in_uA) + "\n")
outfile.close()
def generate_density_of_states (self):
print "Generating DOS"
# -------------------------------------------------------------
# Device density of states
# -------------------------------------------------------------
if self.config_type == self.ConfigTypes.DEVICE:
dos = DeviceDensityOfStates(
configuration=self.configuration_obj,
energies=numpy.linspace(-5,5,300)*eV,
kpoints=MonkhorstPackGrid(4,4),
contributions=All,
energy_zero_parameter=AverageFermiLevel,
infinitesimal=5e-07*eV,
self_energy_calculator=KrylovSelfEnergy(),
)
elif self.config_type == self.ConfigTypes.BULK:
dos = DensityOfStates(
configuration=self.configuration_obj,
kpoints=MonkhorstPackGrid(4,4,100),
energy_zero_parameter=FermiLevel,
)
self.sem_int.lock()
obj_id = "Dos, GateV %f, Vds %f" % (self.gv_obj(self.configuration_obj), self.vds_obj(self.configuration_obj))
path = self.analysis_config_path + obj_id.replace(" ", "_") + ".nc"
nlsave(path, dos, object_id=obj_id)
self.sem_int.release()
def generate_bulk_bandstructure (self, route=None, k_points_list=[], ang_momenta=[], dimensions=1):
print "Generating BULK Bandstructure"
#ang_momenta list isn't empty, therefore specify projection list
if ang_momenta:
projection_list = ProjectionList(angular_momenta = ang_momenta)
else:
projection_list = ProjectionList()
if route:
bandstructure = Bandstructure (
configuration=self.configuration_obj,
route=route,
points_per_segment=100,
bands_above_fermi_level=10,
projection_list = projection_list
)
else:
bandstructure = Bandstructure (
configuration=self.configuration_obj,
kpoints = k_points_list,
bands_above_fermi_level=2,
projection_list = projection_list
)
if not ang_momenta:
ang_momenta_str = 'all'
else:
ang_momenta_str = str(ang_momenta)
self.sem_int.lock()
if (dimensions == 1):
dimensions_str = ''
elif (dimensions > 1):
dimensions_str = ', dim = %d' % dimensions
if (route):
route_str = ',route = '
for point in route:
route_str = route_str + ('%s ' % point)
else:
route_str = ''
obj_id = "Band, GateV %f, Vds %f, l = %s%s%s" % (self.gv_obj(self.configuration_obj), self.vds_obj(self.configuration_obj), ang_momenta_str, dimensions_str, route_str)
path = self.analysis_config_path + obj_id.replace(" ", "_") + ".nc"
nlsave(path, bandstructure, object_id=obj_id)
self.sem_int.release()
def graph_bulk_bandstructure (self):
print "Graphing bandstructure..."
gv = self.gv_obj(self.configuration_obj)
vds = self.vds_obj(self.configuration_obj)
surface = '100'
if (self.band_dims == 1):
n0 = 500
bands_k_points_list = [[0, 0, x] for x in numpy.linspace (-0.5,0.5,num=n0, endpoint = True)]
elif (self.band_dims == 2):
if (surface == '100'):
n0 = 150
n1 = 150
kx = list(numpy.linspace (-1,1,num=n0, endpoint = True))
ky = list(numpy.linspace (-1,1,num=n1, endpoint = True))
#bands_k_points_list = np.array(list(itertools.product(kx,ky,kz)))
bands_k_points_list = np.array(list(itertools.product(kx,ky)))
bands_k_points_list = [[i[0],i[1],0] for i in bands_k_points_list]
elif (surface == '110'):
n0 = 50
n1 = 50
elif (self.band_dims == 3):
n0 = 20
n1 = 20
n2 = 20
kx = list(numpy.linspace (-0.5,0.5,num=n0, endpoint = True))
ky = list(numpy.linspace (-0.5,0.5,num=n1, endpoint = True))
kz = list(numpy.linspace (-0.5,0.5,num=n2, endpoint = True))
bands_k_points_list = np.array(list(itertools.product(kx,ky,kz)))
result, bandstructure_obj = self.nlread_object("Band", gv, vds, ang_momenta=self.ang_momenta, dimensions=self.band_dims, route=self.band_route)
if (not result):
self.generate_bulk_bandstructure(route=self.band_route, k_points_list=bands_k_points_list, ang_momenta=self.ang_momenta, dimensions=self.band_dims)
result, bandstructure_obj = self.nlread_object("Band", gv, vds, ang_momenta=self.ang_momenta, dimensions=self.band_dims, route=self.band_route)
energies = bandstructure_obj.evaluate().inUnitsOf(eV)
energy_zero = bandstructure_obj.energyZero()
if not self.ang_momenta:
ang_momenta_str = 'all'
else:
ang_momenta_str = str(self.ang_momenta)
ang_momenta_str = ang_momenta_str.replace('[','')
ang_momenta_str = ang_momenta_str.replace(']','')
outfile = open (self.device_config_path +
'VG_' + str(gv) +
'_VDS_' + str(vds) +
'_zero_' + self.band_zero +
'_l=' + ang_momenta_str +
'_dims=' + str(self.band_dims) +
'_bands.plot', 'w')
if (self.band_dims == 1):
outfile.write ('k\-(z), Energy\n')
outfile.write ('2\g(p)/L, eV\n')
#get the number of bands
num_bands = np.shape(energies)[1]
bands = range(num_bands)
#bands = [3, 4]
energies = energies[:,bands].transpose()
for band in range(len(bands)):
outfile.write ("#Band %d\n" % band)
x_index = 0
xs = []
all_nrgs = energies[band]
#x resets every n0
for z in range(0, n0):
outfile.write ("%f,%f\n" % (bands_k_points_list[z][2], all_nrgs[z]))
outfile.close()
elif (self.band_dims == 2):
outfile.write ('k\-(x), k\-(y), Energy\n')
outfile.write ('2\g(p)/L\-(x), 2\g(p)/L\-(y), eV\n')
#if (surface == '110'):
#get the number of bands
num_bands = np.shape(energies)[1]
bands = range(num_bands)
#bands = [3, 4]
energies = energies[:,bands].transpose()
for band in range(len(bands)):
outfile.write ("#Band %d\n" % band)
x_index = 0
y_index = 0
xs = []
ys = []
all_nrgs = energies[band]
#x resets every n1*n2 points
for x in range(0,len(all_nrgs), n1):
#y resets every n2 points
for y in range(x, x + n1):
xIndex = x_index % n0
yIndex = y_index % n1
x_coord = kx[xIndex]
y_coord = ky[yIndex]
outfile.write ("%f,%f,%f\n" % (kx[xIndex], ky[yIndex], all_nrgs[y]))
y_index = y_index + 1
x_index = x_index + 1
outfile.close()
elif (self.band_dims == 3):
outfile.write ('k\-(x), k\-(y), k\-(z), Energy\n')
outfile.write ('2\g(p)/L\-(x), 2\g(p)/L\-(y), 2\g(p)/L\-(z), eV\n')
#get the number of bands
num_bands = np.shape(energies)[1]
bands = range(num_bands)
bands = [3]
energies = energies[:,bands].transpose()
for band in range(len(bands)):
outfile.write ("#Band %d\n" % band)
x_index = 0
y_index = 0
z_index = 0
xs = []
ys = []
zs = []
all_nrgs = energies[band]
#x resets every n1*n2 points
for x in range(0,len(all_nrgs), n1*n2):
#y resets every n2 points
for y in range(x, x + (n1 * n2), n2):
#z resets every 1 point
for z in range(y, y + n2):
#xs.append (all_nrgs[x])
#ys.append (all_nrgs[y])
#zs.append (all_nrgs[y])
xIndex = x_index % n0
yIndex = y_index % n1
zIndex = z_index % n2
outfile.write ("%f,%f,%f,%f\n" % (kx[xIndex], ky[yIndex], kz[zIndex], all_nrgs[z]))
z_index = z_index + 1
y_index = y_index + 1
x_index = x_index + 1
outfile.close()
def generate_effective_mass (self, k_pts=[0,0,0]):
effective_mass = EffectiveMass(
configuration=self.configuration_obj,
kpoint_fractional=k_pts,
bands_below_fermi_level=1,
bands_above_fermi_level=2,
stencil_order=5,
delta=0.001*Angstrom**-1,
)
obj_id = "EffMass, GateV %f, Vds %f, k = %s%s%s" % (self.gv_obj(self.configuration_obj), self.vds_obj(self.configuration_obj), str(k_pts[0]), str(k_pts[1]),str(k_pts[2]))
path = self.analysis_config_path + obj_id.replace(" ", "_") + ".nc"
nlsave(path, effective_mass, object_id=obj_id)
self.sem_int.release()
def graph_effective_mass (self):
print "Graphing Effective Mass"
gv = self.gv_obj(self.configuration_obj)
vds = self.vds_obj(self.configuration_obj)
k =[0.000000, 0.000000, 0.000000]
k_str = "%s_%s_%s" % (str(k[0]), str(k[1]), str(k[2]))
result, effmass_obj = self.nlread_object("EffMass", gv, vds, k_pts=k)
if (not result):
self.generate_effective_mass (k_pts = k)
result, effmass_obj = self.nlread_object("EffMass", gv, vds, k_pts=k)
outfile = open (self.device_config_path +
'VG_' + str(gv) +
'_VDS_' + str(vds) +
'_k=' + k_str +
'_effmass.plot', 'w')
outfile.write("Band Id, Effective Mass, Energy, k-point\n")
outfile.write(", me, eV,\n")
i = 0
for band in effmass_obj.evaluate():
effMass = band[0][1].inUnitsOf(electron_mass)
energy = effmass_obj.energies()[0][i].inUnitsOf(eV)
outfile.write("%d, %f, %f, %s\n" % (i, effMass, energy, k_str))
i = i + 1
def transfer_transmission_spectrums (self):
#holds all objects. need to extract transmissionspectrum objects
all_nc_keys = nlinspect(self.device_config_path)
trans_objects_ids = []
for key in all_nc_keys:
if key[0] == 'TransmissionSpectrum':
trans_objects_ids.append (key)
#trans_objects_ids: [0] = TransmissionSpectrum.
#[1] = object_id
#[2] = Fingerprint
#Sort the Trans objects by voltage first for printing
#tuple of (gate_v, vds)
sorted_voltages = []
for trans_obj in trans_objects_ids:
#extracting the vds and gate voltage
object_id = trans_obj[1]
search_obj = re.search (r'Trans, GateV ([-0-9.]+), Vds ([-0-9.]+)$', object_id, re.M)
if search_obj:
gate_v = float(search_obj.group(1))
vds = float(search_obj.group(2))
sorted_voltages.append ((gate_v, vds))
def set_default_voltages (self, gate_v = 0*Volt, vds = 0*Volt):
#config_objs = []
#if self.config_type == self.ConfigTypes.DEVICE:
#config_objs = nlread(self.device_config_path, DeviceConfiguration)
#elif self.config_type == self.ConfigTypes.BULK:
#config_objs = nlread(self.device_config_path, BulkConfiguration)
##TODO MAKE THIS INTO ASSERT
#if not config_objs:
#print "There must be some configs at all!"
#sys.exit()
default_config = None
obj_id = "Config, GateV %f, Vds %f" % (gate_v.inUnitsOf(Volt), vds.inUnitsOf(Volt))
default_config = nlread(self.device_config_path, self.config_type[2],
object_id=obj_id)
if (default_config is None) or (not default_config):
#TODO MAKE THIS INTO ASSERT
print "No config found with this voltage! Run the init first! Vds = ", vds, " GateV = ", gate_v
sys.exit()
default_config = default_config[0]
self.configuration_obj = default_config
def analyze(self):
print "Starting analysis..."
if ('None' in self.calc_types):
print "No calculations specified..."
return
else:
if ('Veff' in self.calc_types):
self.graph_v_eff ()
if ('Vext' in self.calc_types):
self.graph_v_ext ()
if ('DiffPot' in self.calc_types):
self.graph_diff_pot ()
if ('Edens' in self.calc_types):
self.graph_e_density ()
if ('Dos' in self.calc_types):
self.graph_density_of_states ()
if ('LDDOS' in self.calc_types):
self.graph_dos_real_space ()
if ('Ediffdens' in self.calc_types):
self.graph_e_diff_density ()
if ('VDrop' in self.calc_types):
self.graph_voltage_drop ()
if ('VDropEff' in self.calc_types):
self.graph_voltage_drop_eff ()
if ('Efield' in self.calc_types):
self.graph_efield ()
if ('Trans' in self.calc_types):
self.graph_transmission_spectrum()
if ('Bands' in self.calc_types):
self.graph_bulk_bandstructure()
if ('ChemPot' in self.calc_types):
self.graph_chem_potential()
if ('EffMass' in self.calc_types):
self.graph_effective_mass()
if ('MoveTrans' in self.calc_types):
self.transfer_transmission_spectrums()
if __name__ == "__main__":
#gate_voltage_list=[-3, -2.5, -2, -1.5, -1, -0.5, 0, 0.5, 1]*Volt
#gate_voltage_list
dev_anal_obj = DeviceAnalysis(sys.argv[1:])
analysis_type = dev_anal_obj.analysis_type
if analysis_type == "bulk":
vds = 0.0 * Volt
gate_voltage_list = [0.0] * Volt
#set the gate potential
if (dev_anal_obj.voltage_range_input['gv']):
gate_voltage_list= np.linspace(dev_anal_obj.gate_v_start, dev_anal_obj.gate_v_end, num = dev_anal_obj.gate_v_points, endpoint=True) * Volt
dev_anal_obj.gate_voltage_sweep (gate_voltage_list, vds, asymmetric_voltage=True)
for gv in gate_voltage_list:
dev_anal_obj.set_default_voltages(gate_v=gv, vds=vds)
dev_anal_obj.analyze()
elif analysis_type == "vds_sweep":
dev_anal_obj.analyze()
vds_voltage_list = np.linspace(dev_anal_obj.vds_start, dev_anal_obj.vds_end, num = dev_anal_obj.vds_points, endpoint=False) * Volt
#
print "Sweeping VDS voltages: ", vds_voltage_list
#Gate voltage for which VDS voltage sbeing swept
gate_voltage = dev_anal_obj.gate_v * Volt
dev_anal_obj.gate_voltage_sweep ([gate_voltage], 0.0*Volt)
dev_anal_obj.set_default_voltages(gate_v=gate_voltage, vds = 0.0*Volt)
dev_anal_obj.vds_sweep (gate_voltage, vds_voltage_list)
for vds in vds_voltage_list:
dev_anal_obj.set_default_voltages(gate_v=gate_voltage, vds = vds)
dev_anal_obj.analyze()
elif analysis_type == "gate_sweep":
#dev_anal_obj.analyze()
gate_voltage_list= np.linspace(dev_anal_obj.gate_v_start, dev_anal_obj.gate_v_end, num = dev_anal_obj.gate_v_points, endpoint=False) * Volt
vds_voltage_list=[dev_anal_obj.vds_bias]*Volt
dev_anal_obj.set_default_voltages(gate_v=0.0 * Volt, vds = 0.0*Volt)
gate_voltage = 0.0 * Volt
dev_anal_obj.vds_sweep (gate_voltage, vds_voltage_list)
print "#####"
print "Sweeping Gate Voltages: ", gate_voltage_list
print "VDS Voltage: ", vds_voltage_list
print "#####"
for vds in vds_voltage_list:
dev_anal_obj.gate_voltage_sweep (gate_voltage_list, vds)
for gv in gate_voltage_list:
dev_anal_obj.set_default_voltages(gate_v=gv, vds=vds_voltage_list[0])
dev_anal_obj.analyze()
#set gate voltage for which to sweep vds
#sweep over VDS's
#sweep over gate voltage with certain vds
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment