Esempio n. 1
0
    def _conductivity(self, Na, Nd, nxc, **kwargs):

        Nid, Nia = get_carriers(Na, Nd, 0,
                                temp=self.cal_dts['temp'],
                                ni_author=self.cal_dts['nieff_author']
                                )

        if np.all(Nid > Nia):
            Nid = self.ion.update_dopant_ionisation(
                Nid, nxc, self.cal_dts['dopant'])
        elif np.all(Nia > Nid):
            Nia = self.ion.update_dopant_ionisation(
                Nia, nxc, self.cal_dts['dopant'])

        ne, nh = get_carriers(Nid, Nia, nxc,
                              temp=self.cal_dts['temp'],
                              ni_author=self.cal_dts['nieff_author']
                              )

        mob_e = self.Mob.electron_mobility(nxc, Na, Nd,
                                           temp=self.cal_dts['temp'])
        mob_h = self.Mob.hole_mobility(nxc, Na, Nd,
                                       temp=self.cal_dts['temp'])

        # print mob_h, mob_e, Na

        return const.e * (mob_e * ne + mob_h * nh)
Esempio n. 2
0
    def _conductivity(self, **kwargs):

        Nid, Nia = get_carriers(nxc=0,
                                Na=self.cal_dts['Na'],
                                Nd=self.cal_dts['Nd'],
                                temp=self.cal_dts['temp'],
                                ni_author=self.cal_dts['nieff_author']
                                )

        if np.all(Nid > Nia):
            Nid = self.ion.update_dopant_ionisation(
                Nid, nxc, impurity=self.cal_dts['dopant'])
        elif np.all(Nia > Nid):
            Nia = self.ion.update_dopant_ionisation(
                Nia,
                nxc=self.cal_dts['nxc'],
                impurity=self.cal_dts['dopant'])

        ne, nh = get_carriers(Nid, Nia,
                              nxc=self.cal_dts['nxc'],
                              temp=self.cal_dts['temp'],
                              ni_author=self.cal_dts['nieff_author']
                              )

        mob_e = self.Mob.electron_mobility(nxc=self.cal_dts['nxc'],
                                           Na=self.cal_dts['Na'],
                                           Nd=self.cal_dts['Nd'],
                                           temp=self.cal_dts['temp']
                                           )
        mob_h = self.Mob.hole_mobility(nxc=self.cal_dts['nxc'],
                                       Na=self.cal_dts['Na'],
                                       Nd=self.cal_dts['Nd'],
                                       temp=self.cal_dts['temp'])

        return const.e * (mob_e * ne + mob_h * nh)
Esempio n. 3
0
def generteCaldts(T,
                  Ndop,
                  doptypelist,
                  ionauthor='Altermatt_2006_table1',
                  vthauthor='Green_1990',
                  ni_author='Couderc_2014',
                  **kwarg):
    vth_e300, vth_h300 = Vel_th().update(temp=300, author=vthauthor)
    Caldts = []
    for i in range(len(T)):
        vth_e, vth_h = Vel_th().update(temp=T[i], author=vthauthor)
        Ni = ni().update(temp=T[i], author=ni_author)
        doptype = doptypelist[i]
        if doptype == 'n':
            Nidop = Ion(temp=T[i],
                        ni_author=ni_author).update_dopant_ionisation(
                            N_dop=Ndop[i],
                            nxc=0,
                            impurity='phosphorous',
                            author=ionauthor)
            n0, p0 = CF.get_carriers(1,
                                     Nidop,
                                     0,
                                     temp=T[i],
                                     ni_author=ni_author)
        elif doptype == 'p':
            Nidop = Ion(temp=T[i],
                        ni_author=ni_author).update_dopant_ionisation(
                            N_dop=Ndop[i],
                            nxc=0,
                            impurity='boron',
                            author=ionauthor)
            n0, p0 = CF.get_carriers(Nidop,
                                     0,
                                     0,
                                     temp=T[i],
                                     ni_author=ni_author)
        dts = {
            'ni': Ni,
            'vth_e': vth_e,
            'vth_h': vth_h,
            'n0': n0,
            'p0': p0,
            'T': T[i],
            'doptype': doptype,
            'vth_e300': vth_e300,
            'vth_h300': vth_h300
        }
        Caldts.append(dts.copy())
    return Caldts
Esempio n. 4
0
    def _tau(self, nxc, tau_e, tau_h, Et):
        """
        The Shockley Read Hall lifetime for a defect level
        in the band gap. This is calculated from the kinetics
        of repairing.
        """

        # the escape from defects
        nh1 = self.ni.ni * \
            np.exp(-Et * const.e / (const.k * self._cal_dts['temp']))

        ne1 = self.ni.ni * \
            np.exp(Et * const.e / (const.k * self._cal_dts['temp']))

        # get the number of carriers
        ne, nh = get_carriers(Na=self._cal_dts['Na'],
                              Nd=self._cal_dts['Nd'],
                              nxc=self._cal_dts['nxc'],
                              temp=self._cal_dts['temp'],
                              material=self._cal_dts['material'],
                              ni=self.ni.ni)

        # calculate the recombination rate
        U = (ne * nh - self.ni.ni**2) / \
            (tau_h * (ne + ne1) + tau_e * (nh + nh1))

        return self._cal_dts['nxc'] / U
Esempio n. 5
0
    def update(self, **kwargs):
        '''
        Calculates the band gap narrowing

        Inputs:
        Na, Nd, delta n, temp, ni

        output:
            band gap narrowing in eV
        '''

        self.calculationdetails = kwargs

        # a check to make sure the model hasn't changed
        if 'author' in kwargs.keys():
            self.change_model(self._cal_dts['author'])

        # this should be change an outside function alter
        ne, nh = GF.get_carriers(Na=self._cal_dts['Na'],
                                 Nd=self._cal_dts['Nd'],
                                 nxc=self._cal_dts['nxc'],
                                 temp=self._cal_dts['temp'])

        doping = np.array(np.abs(self._cal_dts['Na'] - self._cal_dts['Nd']))

        return getattr(Bgn, self.model)(
            self.vals,
            Na=np.copy(self._cal_dts['Na']),
            Nd=np.copy(self._cal_dts['Nd']),
            ne=ne,
            nh=nh,
            temp=self._cal_dts['temp'],
            doping=doping)
Esempio n. 6
0
    def ambipolar(self, ni_author=None, **kwargs):
        '''
        returns the ambipolar mobility

        inputs:
            ni_author: (optional, str)
                an author for the intrinsic carrier density
            kwargs: (optinal)
                any value with _cal_dts, for which the mobility depends on

        output:
            ambipolar mobility in cm^2 V^-1 s^-1
        '''

        if bool(kwargs):
            self.calculationdetails = kwargs

        # get the number of carriers
        ne, nh = get_carriers(
            Na=self._cal_dts['Na'],
            Nd=self._cal_dts['Nd'],
            nxc=self._cal_dts['nxc'],
            temp=self._cal_dts['temp'],
            material=self._cal_dts['material'],
            ni_author=ni_author,
            ni=9e9)

        mob_h = self.hole_mobility()
        mob_e = self.electron_mobility()

        # caculate the ambipolar mobility according to
        mob_ambi = (ne + nh) / (nh / mob_e + ne / mob_h)

        return mob_ambi
Esempio n. 7
0
    def ambipolar(self, ni_author=None, **kwargs):
        '''
        returns the ambipolar mobility

        inputs:
            ni_author: (optional, str)
                an author for the intrinsic carrier density
            kwargs: (optinal)
                any value with _cal_dts, for which the mobility depends on

        output:
            ambipolar mobility in cm^2 V^-1 s^-1
        '''

        if bool(kwargs):
            self.calculationdetails = kwargs

        # get the number of carriers
        ne, nh = get_carriers(Na=self._cal_dts['Na'],
                              Nd=self._cal_dts['Nd'],
                              nxc=self._cal_dts['nxc'],
                              temp=self._cal_dts['temp'],
                              material=self._cal_dts['material'],
                              ni_author=ni_author,
                              ni=9e9)

        mob_h = self.hole_mobility()
        mob_e = self.electron_mobility()

        # caculate the ambipolar mobility according to
        mob_ambi = (ne + nh) / (nh / mob_e + ne / mob_h)

        return mob_ambi
Esempio n. 8
0
    def _tau(self, nxc, tau_e, tau_h, Et):
        """
        The Shockley Read Hall lifetime for a defect level
        in the band gap. This is calculated from the kinetics
        of repairing.
        """

        # the escape from defects
        nh1 = self.ni.ni * \
            np.exp(-Et * const.e / (const.k * self._cal_dts['temp']))

        ne1 = self.ni.ni * \
            np.exp(Et * const.e / (const.k * self._cal_dts['temp']))

        # get the number of carriers
        ne, nh = get_carriers(Na=self._cal_dts['Na'],
                              Nd=self._cal_dts['Nd'],
                              nxc=self._cal_dts['nxc'],
                              temp=self._cal_dts['temp'],
                              material=self._cal_dts['material'],
                              ni=self.ni.ni
                              )

        # calculate the recombination rate
        U = (ne * nh - self.ni.ni**2) / \
            (tau_h * (ne + ne1) + tau_e * (nh + nh1))

        return self._cal_dts['nxc'] / U
Esempio n. 9
0
    def update(self, **kwargs):
        '''
        Calculates the band gap narrowing

        Inputs:
        Na, Nd, delta n, temp, ni

        output:
            band gap narrowing in eV
        '''

        self.calculationdetails = kwargs

        # a check to make sure the model hasn't changed
        if 'author' in kwargs.keys():
            self.change_model(self._cal_dts['author'])

        # this should be change an outside function alter
        ne, nh = GF.get_carriers(Na=self._cal_dts['Na'],
                                 Nd=self._cal_dts['Nd'],
                                 nxc=self._cal_dts['nxc'],
                                 temp=self._cal_dts['temp'])

        doping = np.array(np.abs(self._cal_dts['Na'] - self._cal_dts['Nd']))

        return getattr(Bgn, self.model)(
            self.vals,
            Na=np.copy(self._cal_dts['Na']),
            Nd=np.copy(self._cal_dts['Nd']),
            ne=ne,
            nh=nh,
            temp=self._cal_dts['temp'],
            doping=doping)
Esempio n. 10
0
    def update_dopant_ionisation(self, N_dop, nxc, impurity, **kwargs):
        '''
        This is a special function used to determine the number of
        ionised dopants given a number of excess carriers, and a
        single dopant type.

        inputs:
            N_dop: (float; cm^-3)
                The dopant density
            nxc: (float; cm^-3)
                The excess carrier density
            impurity: (str)
                The name of the dopant used e.g. boron, phosphorous. The
                dopants available depend on the model used

        output:
            N_idop: (float cm^-2)
                The number of ionised dopants
        '''

        self.calculationdetails = kwargs

        # a check to make sure the model hasn't changed
        if 'author' in kwargs.keys():
            self.change_model(self._cal_dts['author'])

        N_idop = N_dop

        if not isinstance(N_idop, np.ndarray):
            N_idop = np.asarray([N_idop])

        if not isinstance(N_dop, np.ndarray):
            N_dop = np.asarray([N_dop])

        if impurity in self.vals.keys():
            # TO DO, change this from just running 10 times to a proper check
            for i in range(10):
                if self.vals['tpe_' + self.vals[impurity]] == 'donor':
                    Nd = np.copy(N_idop)
                    Na = np.zeros(Nd.shape)
                elif self.vals['tpe_' + self.vals[impurity]] == 'acceptor':
                    Na = np.copy(N_idop)
                    Nd = np.zeros(Na.shape)
                else:
                    print('something went wrong in ionisation model')

                ne, nh = CF.get_carriers(Na,
                                         Nd,
                                         nxc,
                                         temp=self._cal_dts['temp'],
                                         material=self._cal_dts['material'],
                                         ni=self._cal_dts['ni_author'])

                N_idop = self.update(N_dop, ne, nh, impurity)

        else:
            print(r'Not a valid impurity, returning 100% ionisation')

        return N_idop
Esempio n. 11
0
    def update_dopant_ionisation(self, N_dop, nxc, impurity, **kwargs):
        '''
        This is a special function used to determine the number of
        ionised dopants given a number of excess carriers, and a
        single dopant type.

        inputs:
            N_dop: (float; cm^-3)
                The dopant density
            nxc: (float; cm^-3)
                The excess carrier density
            impurity: (str)
                The name of the dopant used e.g. boron, phosphorous. The
                dopants available depend on the model used

        output:
            N_idop: (float cm^-2)
                The number of ionised dopants
        '''

        self.calculationdetails = kwargs

        # a check to make sure the model hasn't changed
        if 'author' in kwargs.keys():
            self.change_model(self._cal_dts['author'])

        if not isinstance(N_dop, np.ndarray):
            N_dop = np.asarray([N_dop])

        N_idop = np.copy(N_dop)

        if impurity in self.vals.keys():
            # TO DO, change this from just running 10 times to a proper check
            for i in range(10):
                if self.vals['tpe_' + self.vals[impurity]] == 'donor':
                    Nd = np.copy(N_idop)
                    Na = np.zeros(Nd.shape)
                elif self.vals['tpe_' + self.vals[impurity]] == 'acceptor':
                    Na = np.copy(N_idop)
                    Nd = np.zeros(Na.shape)
                else:
                    print('something went wrong in ionisation model')

                ne, nh = CF.get_carriers(
                    Na,
                    Nd,
                    nxc,
                    temp=self._cal_dts['temp'],
                    material=self._cal_dts['material'],
                    ni=self._cal_dts['ni_author'])

                N_idop = self.update(
                    N_imp=N_dop, ne=ne, nh=nh, impurity=impurity)

        else:
            print(r'Not a valid impurity, returning 100% ionisation')

        return N_idop
Esempio n. 12
0
def uDCS_compensated(carrier, vals, nh, ne, Na, Nd, temp):
    '''
    A modifcation by Schindler that provides the mobility for compensated
    doped material.
    '''
    carrier_sum = nh + ne

    ne0, nh0 = GF.get_carriers(Na=Na, Nd=Nd, nxc=0, temp=300.)

    C_l = (Na + Nd) / (nh0 + ne0)

    if C_l < 1:
        C_l = 1

    nsc = Nsc(carrier, vals, nh, ne, Na, Nd)
    nsceff = Nsceff(carrier, vals, nh, ne, Na, Nd, temp)

    # determine e and h from which i majority
    def cal_maj():
        def beta2():
            tref = 37.9 * np.log(vals['cl_ref']**2 * (Na + Nd) / 1e19 + 3.6)
            return 1 + 60. / np.sqrt(vals['cl_ref']) * \
                np.exp(-(temp / tref + 1.18)**2)

        return un(carrier, vals, 300) * nsc / nsceff * (
            (nsc / vals['nref_' + carrier])**(vals['alpha_' + carrier]) /
            (temp / vals['temp_refc'])**(3 * vals['alpha_' + carrier] - 1.5) +
            (
                (C_l**beta2() - 1.) / vals['cl_ref'])**vals['beta1']
        )**(-1.) + \
            (uc(carrier, vals, 300) * carrier_sum / nsceff) *\
            (vals['temp_refc'] / temp)**(0.5)

    def cal_min():
        return un(carrier, vals, 300) * nsc / nsceff * (
            (nsc / vals['nref_' + carrier])**(vals['alpha_' + carrier]) /
            (temp / vals['temp_refc'])**(3. * vals['alpha_' + carrier] - 1.5) +
            (
                ((Na + Nd) / vals['n_ref3']) *
                (C_l - 1.) / vals['cl_ref'])**vals['beta1']
        )**(-1.) + \
            (uc(carrier, vals, 300) * carrier_sum / nsceff) * \
            (vals['temp_refc'] / temp)**(0.5)

    mob = 1

    # if the carriers are electrons change the following if statement
    if carrier == 'e':
        mob = -1

    # if the holes are larger at any point, assume
    # they are the majority carriers
    if np.any(nh * mob > ne * mob):
        mob = cal_min()
    else:
        mob = cal_maj()

    return mob
Esempio n. 13
0
def unified_mobility_compensated(vals, Na, Nd, nxc, temp, carrier, **kwargs):
    """
    Thaken from:

    [1] D. B. M. Klaassen,
    "A unified mobility model for device simulation-I. Model equations and
    concentration dependence"
     Solid. State. Electron., vol. 35, no. 7, pp. 953-959, Jul. 1992.

    [2] D. B. M. Klaassen,
    "A unified mobility model for device simulation-II. Temperature
    dependence of carrier mobility and lifetime,"
    Solid. State. Electron., vol. 35, no. 7, pp. 961-967, Jul. 1992.

    The model takes the sample inputs of ionised impurities and carrier
    concentrations

    This is the Klaassen's mobility model, for which the calculations
    with two exceptions:
        (i) r5 is set to -0.8552 rather than -0.01552 (see Table 2 of [1]),
        (ii) Eq. A3 of [1] is adjusted such that PCWe is determined with
        Ne,sc rather than (Z^3 Ni)
         and PCWh is determined with Nh,sc rather than (Z^3 Ni);

    these changes give a better fit to the solid calculated lines in
    Figures 6 and 7 of [1], which better fits the experimental data.
    These modifications are also contained in Sentaurus's version of
    Klaassen's model [5].
    Klaassen's mobility model fits reasonably with experimental data over
    an estimated temperature range of 100 - 450 K.
    Its accuracy is greatest at 300 K (see [1,2]).
    """
    # these are the values for phosphorous and boron respectively.

    # Original value
    # r5 = -0.01552, changing this means changing 2 equations as well

    # a switch used for different types
    # change to hle and electron for clarity

    type_dic = {'hole': 'h', 'electron': 'e'}

    if carrier in type_dic:
        carrier = type_dic[carrier]
    else:
        print('incorrect input for carrier input')

    # Things to fix up
    # ni = ni

    # the only thing ni is used for, this can be factored out so these values
    # are passed to this function

    ne, nh = GF.get_carriers(Na=Na, Nd=Nd, nxc=nxc, temp=temp)

    return 1. / (1. / uDCS(carrier, vals, nh, ne, Na, Nd, temp) +
                 1. / uLS(carrier, vals, temp))
Esempio n. 14
0
def unified_mobility_compensated(vals, Na, Nd, nxc, temp, carrier, **kwargs):
    """
    Thaken from:

    [1] D. B. M. Klaassen,
    "A unified mobility model for device simulation-I. Model equations and
    concentration dependence"
     Solid. State. Electron., vol. 35, no. 7, pp. 953-959, Jul. 1992.

    [2] D. B. M. Klaassen,
    "A unified mobility model for device simulation-II. Temperature
    dependence of carrier mobility and lifetime,"
    Solid. State. Electron., vol. 35, no. 7, pp. 961-967, Jul. 1992.

    The model takes the sample inputs of ionised impurities and carrier
    concentrations

    This is the Klaassen's mobility model, for which the calculations
    with two exceptions:
        (i) r5 is set to -0.8552 rather than -0.01552 (see Table 2 of [1]),
        (ii) Eq. A3 of [1] is adjusted such that PCWe is determined with
        Ne,sc rather than (Z^3 Ni)
         and PCWh is determined with Nh,sc rather than (Z^3 Ni);

    these changes give a better fit to the solid calculated lines in
    Figures 6 and 7 of [1], which better fits the experimental data.
    These modifications are also contained in Sentaurus's version of
    Klaassen's model [5].
    Klaassen's mobility model fits reasonably with experimental data over
    an estimated temperature range of 100 - 450 K.
    Its accuracy is greatest at 300 K (see [1,2]).
    """
    # these are the values for phosphorous and boron respectively.

    # Original value
    # r5 = -0.01552, changing this means changing 2 equations as well

    # a switch used for different types
    # change to hle and electron for clarity

    type_dic = {"hole": "h", "electron": "e"}

    if carrier in type_dic:
        carrier = type_dic[carrier]
    else:
        print("incorrect input for carrier input")

    # Things to fix up
    # ni = ni

    # the only thing ni is used for, this can be factored out so these values
    # are passed to this function

    ne, nh = GF.get_carriers(Na=Na, Nd=Nd, nxc=nxc, temp=temp)

    return 1.0 / (1.0 / uDCS(carrier, vals, nh, ne, Na, Nd, temp) + 1.0 / uLS(carrier, vals, temp))
Esempio n. 15
0
    def _conductivity(self, **kwargs):

        self.calculationdetails = kwargs
        self._update_links()

        Nid, Nia = get_carriers(nxc=0,
                                Na=self._cal_dts['Na'],
                                Nd=self._cal_dts['Nd'],
                                temp=self._cal_dts['temp'],
                                ni_author=self._cal_dts['nieff_author']
                                )

        if np.all(Nid > Nia):
            Nid = self.ion.update_dopant_ionisation(
                N_dop=Nid,
                nxc=self._cal_dts['nxc'],
                impurity=self._cal_dts['dopant'])
        elif np.all(Nia > Nid):
            Nia = self.ion.update_dopant_ionisation(
                N_dop=Nia,
                nxc=self._cal_dts['nxc'],
                impurity=self._cal_dts['dopant'])

        ne, nh = get_carriers(
            Na=Nia,
            Nd=Nid,
            nxc=self._cal_dts['nxc'],
            temp=self._cal_dts['temp'],
            ni_author=self._cal_dts['nieff_author']
        )

        mob_e = self.Mob.electron_mobility(nxc=self._cal_dts['nxc'],
                                           Na=self._cal_dts['Na'],
                                           Nd=self._cal_dts['Nd']
                                           )
        mob_h = self.Mob.hole_mobility(nxc=self._cal_dts['nxc'],
                                       Na=self._cal_dts['Na'],
                                       Nd=self._cal_dts['Nd'])

        return const.e * (mob_e * ne + mob_h * nh)
Esempio n. 16
0
def dorkel(vals, Na, Nd, nxc, temp, carrier, **kwargs):
    '''
    inputs:
        impurty: the number of impurities (cm^-3)
        min_carr_den: the number of minoirty carrier densities (cm^-3)
        maj_car_den: the number of majority carrier densities (cm^-3)
        temp: temperature (K)
    output:
         electron mobility (cm^2 V^-1 s^-1)
         hole mobility (cm^2 V^-1 s^-1)
    '''

    impurity = Na + Nd

    ne, nh = GF.get_carriers(Na,
                             Nd,
                             nxc,
                             temp=temp)
    # print Na, Nd, nxc, temp

    if np.all(nh < ne):
        nxc = nh
        maj_car_den = ne
    elif np.all(nh >= ne):
        maj_car_den = nh
        nxc = ne
    else:
        sys.exit("Mixed doping types not permitted")

    # this relates the carrier to the extension in the variable name
    if carrier == 'electron':
        carrier = 'e'
    elif carrier == 'hole':
        carrier = 'h'
    else:
        sys.exit("inappropriate values for carrier passed")

    # determine hole dependent carrier partial mobilities
    mu_L = lattice_mobility(vals, temp, carrier)
    mu_i = impurity_mobility(vals, impurity, temp, carrier)

    # determine both carrier scattering mobilities
    mu_css = carrier_scattering_mobility(
        vals, nxc, maj_car_den, temp)

    # determine sudo function
    X = np.sqrt(6. * mu_L * (mu_i + mu_css) / (mu_i * mu_css))

    # combine partial moblities into total
    mu = mu_L * (1.025 / (1. + (X / 1.68)**(1.43)) - 0.025)

    return mu
Esempio n. 17
0
def uDCS_compensated(carrier, vals, nh, ne, Na, Nd, temp):
    """
    A modifcation by Schindler that provides the mobility for compensated
    doped material.
    """
    carrier_sum = nh + ne

    ne0, nh0 = GF.get_carriers(Na=Na, Nd=Nd, nxc=0, temp=300.0)

    C_l = (Na + Nd) / (nh0 + ne0)

    if C_l < 1:
        C_l = 1

    nsc = Nsc(carrier, vals, nh, ne, Na, Nd)
    nsceff = Nsceff(carrier, vals, nh, ne, Na, Nd, temp)

    # determine e and h from which i majority
    def cal_maj():
        def beta2():
            tref = 37.9 * np.log(vals["cl_ref"] ** 2 * (Na + Nd) / 1e19 + 3.6)
            return 1 + 60.0 / np.sqrt(vals["cl_ref"]) * np.exp(-(temp / tref + 1.18) ** 2)

        return un(carrier, vals, 300) * nsc / nsceff * (
            (nsc / vals["nref_" + carrier]) ** (vals["alpha_" + carrier])
            / (temp / vals["temp_refc"]) ** (3 * vals["alpha_" + carrier] - 1.5)
            + ((C_l ** beta2() - 1.0) / vals["cl_ref"]) ** vals["beta1"]
        ) ** (-1.0) + (uc(carrier, vals, 300) * carrier_sum / nsceff) * (vals["temp_refc"] / temp) ** (0.5)

    def cal_min():
        return un(carrier, vals, 300) * nsc / nsceff * (
            (nsc / vals["nref_" + carrier]) ** (vals["alpha_" + carrier])
            / (temp / vals["temp_refc"]) ** (3.0 * vals["alpha_" + carrier] - 1.5)
            + (((Na + Nd) / vals["n_ref3"]) * (C_l - 1.0) / vals["cl_ref"]) ** vals["beta1"]
        ) ** (-1.0) + (uc(carrier, vals, 300) * carrier_sum / nsceff) * (vals["temp_refc"] / temp) ** (0.5)

    mob = 1

    # if the carriers are electrons change the following if statement
    if carrier == "e":
        mob = -1

    # if the holes are larger at any point, assume
    # they are the majority carriers
    if np.any(nh * mob > ne * mob):
        mob = cal_min()
    else:
        mob = cal_maj()

    return mob
def dorkel(vals, Na, Nd, nxc, temp, carrier, **kwargs):
    '''
    inputs:
        impurty: the number of impurities (cm^-3)
        min_carr_den: the number of minoirty carrier densities (cm^-3)
        maj_car_den: the number of majority carrier densities (cm^-3)
        temp: temperature (K)
    output:
         electron mobility (cm^2 V^-1 s^-1)
         hole mobility (cm^2 V^-1 s^-1)
    '''

    impurity = Na + Nd

    ne, nh = GF.get_carriers(Na, Nd, nxc, temp=temp)
    print Na, Nd, nxc, temp

    if np.all(nh < ne):
        nxc = nh
        maj_car_den = ne
    elif np.all(nh >= ne):
        maj_car_den = nh
        nxc = ne
    else:
        sys.exit("Mixed doping types not permitted")

    # this relates the carrier to the extension in the variable name
    if carrier == 'electron':
        carrier = 'e'
    elif carrier == 'hole':
        carrier = 'h'
    else:
        sys.exit("inappropriate values for carrier passed")

    # determine hole dependent carrier partial mobilities
    mu_L = lattice_mobility(vals, temp, carrier)
    mu_i = impurity_mobility(vals, impurity, temp, carrier)

    # determine both carrier scattering mobilities
    mu_css = carrier_scattering_mobility(vals, nxc, maj_car_den, temp)

    # determine sudo function
    X = np.sqrt(6. * mu_L * (mu_i + mu_css) / (mu_i * mu_css))

    # combine partial moblities into total
    mu = mu_L * (1.025 / (1. + (X / 1.68)**(1.43)) - 0.025)

    return mu
Esempio n. 19
0
    def update_dopant_ionisation(self, N_dop, nxc, impurity,
                                 temp=None, author=None):
        '''
        This is a special function used to determine the number of
        ionised dopants given a number of excess carriers, and a
        single dopant type.

        inputs:
            N_dop: (float; cm^-3)
                The dopant density
            nxc: (float; cm^-3)
                The excess carrier density
            impurity: (str)
                The name of the dopant used e.g. boron, phosphorous. The
                dopants available depend on the model used

        output:
            N_idop: (float cm^-2)
                The number of ionised dopants
        '''

        if temp is None:
            temp = self.temp

        if author is not None:
            self.change_model(author)

        N_idop = N_dop

        if impurity in self.vals.keys():
            # TO DO, change this from just running 10 times to a proper check
            for i in range(10):
                if self.vals['tpe_' + self.vals[impurity]] == 'donor':
                    Nd = N_idop
                    Na = 0
                elif self.vals['tpe_' + self.vals[impurity]] == 'acceptor':
                    Na = N_idop
                    Nd = 0

                ne, nh = CF.get_carriers(
                    Na, Nd, nxc, temp=temp, matterial='Si')

                N_idop = self.update(
                    N_dop, ne, nh, impurity, temp=temp, author=None)
        else:
            print r'Not a valid impurity, returning 100% ionisation'

        return N_idop
Esempio n. 20
0
    def update_dopant_ionisation(self, N_dop, nxc, impurity, **kwargs):
        '''
        This is a special function used to determine the number of
        ionised dopants given a number of excess carriers, and a
        single dopant type.

        inputs:
            N_dop: (float; cm^-3)
                The dopant density
            nxc: (float; cm^-3)
                The excess carrier density
            impurity: (str)
                The name of the dopant used e.g. boron, phosphorous. The
                dopants available depend on the model used

        output:
            N_idop: (float cm^-2)
                The number of ionised dopants
        '''

        self._update_dts(**kwargs)

        # a check to make sure the model hasn't changed
        if 'author' in kwargs.keys():
            self.change_model(self.cal_dts['author'])

        N_idop = N_dop

        if impurity in self.vals.keys():
            # TO DO, change this from just running 10 times to a proper check
            for i in range(10):
                if self.vals['tpe_' + self.vals[impurity]] == 'donor':
                    Nd = N_idop
                    Na = 0
                elif self.vals['tpe_' + self.vals[impurity]] == 'acceptor':
                    Na = N_idop
                    Nd = 0

                ne, nh = CF.get_carriers(
                    Na, Nd, nxc, temp=self.cal_dts['temp'],
                    material=self.cal_dts['material'])

                N_idop = self.update(
                    N_dop, ne, nh, impurity)
        else:
            print r'Not a valid impurity, returning 100% ionisation'

        return N_idop
Esempio n. 21
0
    def tau(self, nxc, **kwargs):
        self.calculationdetails = kwargs

        if 'author' in kwargs.keys():
            self.change_model(self._cal_dts['author'])

        ne0, nh0 = get_carriers(
            Na=self._cal_dts['Na'],
            Nd=self._cal_dts['Nd'],
            nxc=0,
            ni_author=self._cal_dts['ni_author'],
            temp=self._cal_dts['temp']
        )

        return getattr(augmdls, self.model)(
            self.vals, nxc, ne0, nh0, temp=self._cal_dts['temp'])
Esempio n. 22
0
    def tau(self, nxc, **kwargs):
        self.calculationdetails = kwargs
        self.change_model(self._cal_dts['author'])

        ne0, nh0 = get_carriers(
            Na=self._cal_dts['Na'],
            Nd=self._cal_dts['Nd'],
            nxc=self._cal_dts['nxc'],
            ni_author=self._cal_dts['ni_author'],
            temp=self._cal_dts['temp']
        )

        B = self._get_B()

        return getattr(radmdls, self.model)(
            self.vals, nxc, nh0, ne0, B, temp=self._cal_dts['temp']
        )
Esempio n. 23
0
    def tau(self, nxc, **kwargs):
        '''
        Returns the intrinsic carrier lifetime in seconds
        '''
        self.calculationdetails = kwargs
        self.change_model(self._cal_dts['author'])

        ne0, nh0 = get_carriers(Na=self._cal_dts['Na'],
                                Nd=self._cal_dts['Nd'],
                                nxc=0,
                                ni_author=self._cal_dts['ni_author'],
                                temp=self._cal_dts['temp'])

        Blow = self._get_Blow()

        return getattr(radmdls, self.model)(vals=self.vals,
                                            nxc=nxc,
                                            nh0=nh0,
                                            ne0=ne0,
                                            Blow=Blow,
                                            temp=self._cal_dts['temp'])
Esempio n. 24
0
    def tau(self, nxc, Na, Nd, temp=300):

        ne0, nh0 = get_carriers(
            Na, Nd, nxc=0, ni_author=None, temp=temp)

        return getattr(augmdls, self.model)(self.vals, nxc, ne0, nh0, temp)
Esempio n. 25
0
    def tau(self, nxc, Na, Nd, temp=300):

        ne0, nh0 = get_carriers(Na, Nd, nxc=0, ni_author=None, temp=temp)

        return getattr(augmdls, self.model)(self.vals, nxc, ne0, nh0, temp)