Source code for openbandparams.iii_v_zinc_blende_alloy

#
#   Copyright (c) 2013-2015, Scott J Maddox
#
#   This file is part of openbandparams.
#
#   openbandparams is free software: you can redistribute it and/or modify
#   it under the terms of the GNU Affero General Public License as published
#   by the Free Software Foundation, either version 3 of the License, or
#   (at your option) any later version.
#
#   openbandparams is distributed in the hope that it will be useful,
#   but WITHOUT ANY WARRANTY; without even the implied warranty of
#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#   GNU Affero General Public License for more details.
#
#   You should have received a copy of the GNU Affero General Public License
#   along with openbandparams.  If not, see <http://www.gnu.org/licenses/>.
#
#############################################################################
from .alloy import Alloy
from .iii_v_alloy import IIIVAlloy
from .iii_v_zinc_blende_strained import IIIVZincBlendeStrained001
from .parameter import method_parameter
from .references import vurgaftman_2001, kane_1956
from .equations import varshni


[docs]class IIIVZincBlendeAlloy(IIIVAlloy): ''' The base class for all III-V zinc blende alloys. '''
[docs] def strained_001(self, target): ''' Returns an instance of ``IIIVZincBlendeStrained001``, which is a biaxial-strained III-V zinc blende binary alloy grown on a (001) surface. Parameters ---------- target : Alloy with ``a`` parameter or float Growth substrate, assumed to have a (001) surface, or out-of-plane strain, which is negative for tensile strain and positive for compressive strain. This is the strain measured by X-ray diffraction (XRD) symmetric omega-2theta scans. ''' if isinstance(target, Alloy): return IIIVZincBlendeStrained001(unstrained=self, substrate=target) else: return IIIVZincBlendeStrained001(unstrained=self, strain_out_of_plane=target)
@method_parameter(dependencies=['VBO', 'Eg'], units='eV')
[docs] def CBO(self, **kwargs): ''' Returns the conduction band offset (CBO), in eV at a given temperature, T, in K (default=300.). ''' return self.VBO(**kwargs) + self.Eg(**kwargs)
@method_parameter(dependencies=['VBO', 'Eg_Gamma'], units='eV')
[docs] def CBO_Gamma(self, **kwargs): ''' Returns the Gamma-valley conduction band offset (CBO), in eV at a given temperature, T, in K (default=300.). ''' return self.VBO(**kwargs) + self.Eg_Gamma(**kwargs)
@method_parameter(dependencies=['VBO', 'Eg_L'], units='eV')
[docs] def CBO_L(self, **kwargs): ''' Returns the L-valley conduction band offset (CBO), in eV at a given temperature, T, in K (default=300.). ''' return self.VBO(**kwargs) + self.Eg_L(**kwargs)
@method_parameter(dependencies=['VBO', 'Eg_X'], units='eV')
[docs] def CBO_X(self, **kwargs): ''' Returns the X-valley conduction band offset (CBO), in eV at a given temperature, T, in K (default=300.). ''' return self.VBO(**kwargs) + self.Eg_X(**kwargs)
@method_parameter(dependencies=['Eg_Gamma', 'Eg_L', 'Eg_X'], units='eV', aliases=['bandgap'])
[docs] def Eg(self, **kwargs): ''' Returns the bandgap, Eg, in eV at a given temperature, T, in K (default=300.). ''' return min(self.Eg_Gamma(**kwargs), self.Eg_L(**kwargs), self.Eg_X(**kwargs))
@method_parameter(dependencies=['Eg_Gamma_0', 'alpha_Gamma', 'beta_Gamma'], units='eV')
[docs] def Eg_Gamma(self, **kwargs): Eg_0 = self.Eg_Gamma_0(**kwargs) alpha = self.alpha_Gamma(**kwargs) beta = self.beta_Gamma(**kwargs) T = kwargs.get('T', 300.) return varshni(Eg_0, alpha, beta, T)
@method_parameter(dependencies=['Eg_L_0', 'alpha_L', 'beta_L'], units='eV')
[docs] def Eg_L(self, **kwargs): Eg_0 = self.Eg_L_0(**kwargs) alpha = self.alpha_L(**kwargs) beta = self.beta_L(**kwargs) T = kwargs.get('T', 300.) return varshni(Eg_0, alpha, beta, T)
@method_parameter(dependencies=['Eg_X_0', 'alpha_X', 'beta_X'], units='eV')
[docs] def Eg_X(self, **kwargs): Eg_0 = self.Eg_X_0(**kwargs) alpha = self.alpha_X(**kwargs) beta = self.beta_X(**kwargs) T = kwargs.get('T', 300.) return varshni(Eg_0, alpha, beta, T)
@method_parameter(dependencies=['Eg_Gamma_0', 'Delta_SO', 'Ep', 'meff_e_Gamma_0'], units='dimensionless', references=[vurgaftman_2001])
[docs] def F(self, **kwargs): ''' Returns the Kane remote-band parameter, `F`, calculated from `Eg_Gamma_0`, `Delta_SO`, `Ep`, and `meff_e_Gamma_0`. ''' Eg = self.Eg_Gamma_0(**kwargs) Delta_SO = self.Delta_SO(**kwargs) Ep = self.Ep(**kwargs) meff = self.meff_e_Gamma_0(**kwargs) return (1./meff-1-(Ep*(Eg+2.*Delta_SO/3.))/(Eg*(Eg+Delta_SO)))/2
@method_parameter(dependencies=['a_300K', 'thermal_expansion'], units='angstrom')
[docs] def a(self, **kwargs): ''' Returns the lattice parameter, a, in Angstroms at a given temperature, `T`, in Kelvin (default: 300 K). ''' T = kwargs.get('T', 300.) return (self.a_300K(**kwargs) + self.thermal_expansion(**kwargs) * (T - 300.))
@method_parameter(dependencies=['luttinger2', 'luttinger3'], units='dimensionless')
[docs] def luttinger32(self, **kwargs): ''' Returns the difference between the third and second Luttinger parameters, i.e. `luttinger3 - luttinger2`. Linear interpolation of luttinger32 is the recommended way to estimate the valance band warping in alloys. ''' return 1. / (self.luttinger1(**kwargs) - 2 * self.luttinger2(**kwargs))
@method_parameter(dependencies=['luttinger1', 'Eg_Gamma', 'Delta_SO', 'Ep'], units='m_e', references=[vurgaftman_2001])
[docs] def meff_SO(self, **kwargs): ''' Returns the electron effective mass in the Gamma-valley calculated from Eg_Gamma(T), Delta_SO, Ep and F. Interpolation of Eg_Gamma(T), Delta_SO, Ep and F, and then calculation of meff_e_Gamma is recommended for alloys. ''' Eg = self.Eg_Gamma(**kwargs) Delta_SO = self.Delta_SO(**kwargs) Ep = self.Ep(**kwargs) luttinger1 = self.luttinger1(**kwargs) return 1./(luttinger1 - (Ep*Delta_SO)/(3*Eg*(Eg+Delta_SO)))
@method_parameter(dependencies=['Eg_Gamma', 'Delta_SO', 'Ep', 'F'], units='m_e', references=[vurgaftman_2001])
[docs] def meff_e_Gamma(self, **kwargs): ''' Returns the electron effective mass in the Gamma-valley calculated from Eg_Gamma(T), Delta_SO, Ep and F. Interpolation of Eg_Gamma(T), Delta_SO, Ep and F, and then calculation of meff_e_Gamma is recommended for alloys. ''' Eg = self.Eg_Gamma(**kwargs) Delta_SO = self.Delta_SO(**kwargs) Ep = self.Ep(**kwargs) F = self.F(**kwargs) return 1./((1.+2.*F)+(Ep*(Eg+2.*Delta_SO/3.))/(Eg*(Eg+Delta_SO)))
@method_parameter(dependencies=['luttinger1', 'luttinger2'], units='m_e')
[docs] def meff_hh_100(self, **kwargs): ''' Returns the heavy-hole band effective mass in the [100] direction, meff_hh_100, in units of electron mass. ''' return 1. / (self.luttinger1(**kwargs) - 2 * self.luttinger2(**kwargs))
@method_parameter(dependencies=['luttinger1', 'luttinger2', 'luttinger3'], units='m_e')
[docs] def meff_hh_110(self, **kwargs): ''' Returns the heavy-hole band effective mass in the [110] direction, meff_hh_110, in units of electron mass. ''' return 2. / (2 * self.luttinger1(**kwargs) - self.luttinger2(**kwargs) - 3 * self.luttinger3(**kwargs))
@method_parameter(dependencies=['luttinger1', 'luttinger3'], units='m_e')
[docs] def meff_hh_111(self, **kwargs): ''' Returns the heavy-hole band effective mass in the [111] direction, meff_hh_111, in units of electron mass. ''' return 1. / (self.luttinger1(**kwargs) - 2 * self.luttinger3(**kwargs))
@method_parameter(dependencies=['luttinger1', 'luttinger2'], units='m_e')
[docs] def meff_lh_100(self, **kwargs): ''' Returns the light-hole band effective mass in the [100] direction, meff_lh_100, in units of electron mass. ''' return 1. / (self.luttinger1(**kwargs) + 2 * self.luttinger2(**kwargs))
@method_parameter(dependencies=['luttinger1', 'luttinger2', 'luttinger3'], units='m_e')
[docs] def meff_lh_110(self, **kwargs): ''' Returns the light-hole band effective mass in the [110] direction, meff_lh_110, in units of electron mass. ''' return 2. / (2 * self.luttinger1(**kwargs) + self.luttinger2(**kwargs) + 3 * self.luttinger3(**kwargs))
@method_parameter(dependencies=['luttinger1', 'luttinger3'], units='m_e')
[docs] def meff_lh_111(self, **kwargs): ''' Returns the light-hole band effective mass in the [111] direction, meff_lh_111, in units of electron mass. ''' return 1. / (self.luttinger1(**kwargs) + 2 * self.luttinger3(**kwargs))
@method_parameter(dependencies=['Eg_Gamma', 'meff_e_Gamma'], units='dimensionless', references=[kane_1956])
[docs] def nonparabolicity(self, **kwargs): ''' Returns the Kane band nonparabolicity parameter for the Gamma-valley. ''' Eg = self.Eg_Gamma(**kwargs) meff = self.meff_e_Gamma(**kwargs) return 1/Eg * (1 - meff)**2 # def _get_eps_xx(self, **kwargs): # if 'a0' in kwargs: # if self is not None: # self = self # else: # self = cls # return self.biaxial_strained_eps_xx(**kwargs) # elif 'eps_xx' in kwargs: # return kwargs['eps_xx'] # else: # raise ValueError('Missing required keyword argument' # ' `eps_xx` or `a0`') # # def biaxial_strained_eps_xx(self, **kwargs): # ''' # Returns the in-plane strain, `eps_xx`, induced by growing # on a substrate with the given lattice constant, `a0`, assuming no # lattice relaxation. # # This assumes growth in the [100] direction. # # Note: `eps_xx` should be negative for compressive in-plane strain, and # positive for tensile in-plane strain. # ''' # if 'a0' in kwargs: # return 1 - self.a(**kwargs) / kwargs['a0'] # else: # raise ValueError('Missing required keyword argument `a0`') # # def biaxial_strained_a0(self, **kwargs): # ''' # Returns the substrate lattice constant, `a0`, required to induce the # given in-plane strain, `eps_xx`, assuming no lattice relaxation. # # This assumes growth in the [100] direction. # # Note 1: Specifying `eps_xx` results in less overhead than # specifying `a0`. # # Note 2: `eps_xx` should be negative for compressive in-plane strain, and # positive for tensile in-plane strain. # ''' # eps_xx = self._get_eps_xx(**kwargs) # return self.a(**kwargs) / (1 - eps_xx) # # def biaxial_strained_eps_zz(self, **kwargs): # ''' # Returns the out-of-plane strain induced by the given in-plane # strain, `eps_xx`, or by growth on a substrate with the given lattice # constant, `a0`, assuming no lattice relaxation. # # This assumes growth in the [100] direction. # # Note 1: Specifying `eps_xx` results in less overhead than # specifying `a0`. # # Note 2: `eps_xx` should be negative for compressive in-plane strain, and # positive for tensile in-plane strain. # ''' # eps_xx = self._get_eps_xx(**kwargs) # return -2 * self.c_12(**kwargs) / self.c_11(**kwargs) * eps_xx # # def biaxial_strained_dE_c(self, **kwargs): # ''' # Returns the conduction band-edge shift, in eV, induced by the # given in-plane strain, `eps_xx`, or by growth on a substrate with # the given lattice constant, `a0`, assuming no lattice relaxation. # # This assumes growth in the [100] direction. # # Note 1: Specifying `eps_xx` results in less overhead than # specifying `a0`. # # Note 2: `eps_xx` should be negative for compressive in-plane strain, and # positive for tensile in-plane strain. # ''' # eps_xx = self._get_eps_xx(**kwargs) # return self.a_c(**kwargs) * (2 * eps_xx + # self.biaxial_strained_eps_zz(**kwargs)) # # def biaxial_strained_P_eps(self, **kwargs): # ''' # Returns the hydrostatic component of the valance band-edge shift, # in eV, induced by the given in-plane strain, `eps_xx`, or by growth # on a substrate with the given lattice constant, `a0`, assuming no # lattice relaxation. # # This assumes growth in the [100] direction. # # Note 1: Specifying `eps_xx` results in less overhead than # specifying `a0`. # # Note 2: `eps_xx` should be negative for compressive in-plane strain, and # positive for tensile in-plane strain. # ''' # eps_xx = self._get_eps_xx(**kwargs) # return self.a_v(**kwargs) * (2 * eps_xx + # self.biaxial_strained_eps_zz(**kwargs)) # # def biaxial_strained_Q_eps(self, **kwargs): # ''' # Returns the uniaxial component of the valance band-edge shift, # in eV, induced by the given in-plane strain, `eps_xx`, or by growth # on a substrate with the given lattice constant, `a0`, assuming no # lattice relaxation. # # This assumes growth in the [100] direction. # # Note 1: Specifying `eps_xx` results in less overhead than # specifying `a0`. # # Note 2: `eps_xx` should be negative for compressive in-plane strain, and # positive for tensile in-plane strain. # ''' # eps_xx = self._get_eps_xx(**kwargs) # return self.b(**kwargs) * (self.biaxial_strained_eps_zz(**kwargs) # - eps_xx) # # def biaxial_strained_dE_hh(self, **kwargs): # ''' # Returns the heavy-hole band-edge shift, in eV, induced by the given # in-plane strain, `eps_xx`, or by growth on a substrate with the given # lattice constant, `a0`, assuming no lattice relaxation. # # This assumes growth in the [100] direction. # # Note 1: Specifying `eps_xx` results in less overhead than # specifying `a0`. # # Note 2: `eps_xx` should be negative for compressive in-plane strain, and # positive for tensile in-plane strain. # ''' # return -(self.biaxial_strained_P_eps(**kwargs) # + self.biaxial_strained_Q_eps(**kwargs)) # # def biaxial_strained_dE_lh(self, **kwargs): # ''' # Returns the light-hole band-edge shift, in eV, induced by the given # in-plane strain, `eps_xx`, or by growth on a substrate with the given # lattice constant, `a0`, assuming no lattice relaxation. # # This assumes growth in the [100] direction. # # Note 1: Specifying `eps_xx` results in less overhead than # specifying `a0`. # # Note 2: `eps_xx` should be negative for compressive in-plane strain, and # positive for tensile in-plane strain. # ''' # return (-self.biaxial_strained_P_eps(**kwargs) # + self.biaxial_strained_Q_eps(**kwargs)) # # def biaxial_strained_E_c(self, **kwargs): # ''' # Returns the conduction band-edge offset, in eV, at the given # in-plane strain, `eps_xx`, or for growth on a substrate with the given # lattice constant, `a0`, assuming no lattice relaxation. # # This assumes growth in the [100] direction. # # Note 1: Specifying `eps_xx` results in less overhead than # specifying `a0`. # # Note 2: `eps_xx` should be negative for compressive in-plane strain, and # positive for tensile in-plane strain. # ''' # return (self.VBO(**kwargs) + self.Eg(**kwargs) # + self.biaxial_strained_dE_c(**kwargs)) # # def biaxial_strained_E_hh(self, **kwargs): # ''' # Returns the heavy-hole band-edge offset, in eV, at the given # in-plane strain, `eps_xx`, or for growth on a substrate with the given # lattice constant, `a0`, assuming no lattice relaxation. # # This assumes growth in the [100] direction. # # Note 1: Specifying `eps_xx` results in less overhead than # specifying `a0`. # # Note 2: `eps_xx` should be negative for compressive in-plane strain, and # positive for tensile in-plane strain. # ''' # return (self.VBO(**kwargs) # + self.biaxial_strained_dE_hh(**kwargs)) # # def biaxial_strained_E_lh(self, **kwargs): # ''' # Returns the light-hole band-edge offset, in eV, at the given # in-plane strain, `eps_xx`, or for growth on a substrate with the given # lattice constant, `a0`, assuming no lattice relaxation. # # This assumes growth in the [100] direction. # # Note 1: Specifying `eps_xx` results in less overhead than # specifying `a0`. # # Note 2: `eps_xx` should be negative for compressive in-plane strain, and # positive for tensile in-plane strain. # ''' # return (self.VBO(**kwargs) # + self.biaxial_strained_dE_lh(**kwargs)) # # def biaxial_strained_E_c_hh(self, **kwargs): # ''' # Returns the separation between the conduction band-edge and the # heavy-hole band-edge, in eV, at the given in-plane strain, `eps_xx`, # or for growth on a substrate with the given lattice constant, `a0`, # assuming no lattice relaxation, and at temperature, `T`, in # Kelvin (default: 300 K). # # This assumes growth in the [100] direction. # # Note 1: Specifying `eps_xx` results in less overhead than # specifying `a0`. # # Note 2: `eps_xx` should be negative for compressive in-plane strain, and # positive for tensile in-plane strain. # ''' # return (self.Eg(**kwargs) # + self.biaxial_strained_dE_c(**kwargs) # - self.biaxial_strained_dE_hh(**kwargs)) # # def biaxial_strained_E_c_lh(self, **kwargs): # ''' # Returns the separation between the conduction band-edge and the # light-hole band-edge, in eV, at the given in-plane strain, `eps_xx`, # or for growth on a substrate with the given lattice constant, `a0`, # assuming no lattice relaxation, and at temperature, `T`, in # Kelvin (default: 300 K). # # This assumes growth in the [100] direction. # # Note 1: Specifying `eps_xx` results in less overhead than # specifying `a0`. # # Note 2: `eps_xx` should be negative for compressive in-plane strain, and # positive for tensile in-plane strain. # ''' # return (self.Eg(**kwargs) # + self.biaxial_strained_dE_c(**kwargs) # - self.biaxial_strained_dE_lh(**kwargs)) # # def biaxial_strained_Eg(self, **kwargs): # ''' # Returns the minimum separation between the conduction band-edge and the # valance band-edge, in eV, at the given in-plane strain, `eps_xx`, # or for growth on a substrate with the given lattice constant, `a0`, # assuming no lattice relaxation, and at temperature, `T`, in # Kelvin (default: 300 K). # # This assumes growth in the [100] direction. # # Note 1: Specifying `eps_xx` results in less overhead than # specifying `a0`. # # Note 2: `eps_xx` should be negative for compressive in-plane strain, and # positive for tensile in-plane strain. # ''' # return min(self.biaxial_strained_E_c_hh(**kwargs), # self.biaxial_strained_E_c_lh(**kwargs))