#!/usr/local/bin/python
# UTF-8

import numpy as np
import scipy.constants as Const


def none(*args, **kwargs):
    '''
    returns the band gap narrowing in eV
    '''
    return 0


def apparent_BGN(vals, doping, **kargs):
    '''
    It returns the 'apparent BGN'. This estimates the real band gap
    narrowing, but uses the accurate Boltzmann statistics. N is the
    net dopant concentration.
    This model incorporates degeneracy as well as band gap narrowing,
    which is why it determines an 'apparent BGN' and not an actual BGN.
    The apparent occurs as Boltzmann statistics are used rather than
    Fermi-Dirac statistic.

    returns the band gap narrowing in eV
    '''

    if type(doping).__module__ != np.__name__:
        doping = np.array(doping)

    BGN = np.zeros(np.array(doping).shape)

    index = doping > vals['n_onset']

    # making sure there are values to assign
    if np.sum(index) > 0:
        BGN[index] = (
            vals['de_slope'] * np.log(doping[index] / vals['n_onset']))

    return BGN


def not_implimented(vals, doping, **kargs):
    '''
    model not implemented, returning 0 values
    '''
    return np.zeros(doping.shape)


def BGN(vals, doping, **kargs):
    '''
    Returns the BGN when applied for carriers with Fermi distribution.
    This estimates the real band gap narrowing,
    but uses Boltzmann stats
    where N is the net dopant concentration.

    returns the band gap narrowing in eV
    '''
    # BGN = np.zeros(doping.shape)

    bgn = vals['de_slope']\
        * np.power(np.log(doping / vals['N_onset']), vals['b'])\
        + vals['de_offset']

    # ensures no negitive values
    if bgn.size > 1:
        bgn[bgn < 0] = 0

    return bgn


def Schenk(vals, Nd, Na, ne, nh, temp, **args):
    '''
    Based on the two principles:
    1. The rigid quasi-particle shifts of the conduction and
    valence band edges, which depend from the free-carrier concentrations
    2. the ionic quasi-particle shifts of the conduction and
    valence band edges resulting from ionised dopants concentrations

    returns the band gap narrowing in eV
    '''

    # makes the values unitless
    ne = (vals['aex']**3.) * ne
    nh = (vals['aex']**3.) * nh
    Na = (vals['aex']**3.) * Na
    Nd = (vals['aex']**3.) * Nd

    n_sum = ne + nh
    n_ionic = Na + Nd

    n_p = vals['alphae'] * ne + vals['alphah'] * nh

    # cacualtes curly T, to give linear dependence with temp
    vals['t'] = Const.k * temp / vals['ryex'] / Const.e

    delta_Ec = ridged_shift(vals, n_sum, n_p, ne, 'e')\
        + ionic_shift(vals, n_sum, n_p, n_ionic, 'e')
    delta_EV = ridged_shift(vals, n_sum, n_p, nh, 'h')\
        + ionic_shift(vals, n_sum, n_p, n_ionic, 'h')

    # print(delta_Ec, delta_EV)
    return delta_Ec + delta_EV


def ridged_shift(vals, n_sum, n_p, num_carrier, carrier):
    '''
    The rigid quasi-particle shift for a band
    the subscript a represents a carrier value (electron or hole)
    '''

    delta = -(
        (4. * Const.pi)**3. * n_sum**2. *
        (
            (48. * num_carrier / Const.pi / vals['g' + carrier])**(1. / 3.)
            + vals['c' + carrier] * np.log(1. + vals['d' + carrier] *
                                           n_p**vals['p' + carrier]))
        + (8. * Const.pi * vals['alpha' + carrier] / vals['g' + carrier])
        * num_carrier * vals['t']**2.
        + np.sqrt(8. * Const.pi * n_sum) * vals['t']**(5. / 2.)
    ) / (
        (4. * Const.pi)**3. * n_sum**2. + vals['t']**3. + vals['b' + carrier] *
        np.sqrt(n_sum) * vals['t']**2. + 40. * n_sum**1.5 * vals['t'])
    return -vals['ryex'] * delta


def ionic_shift(vals, n_sum, n_p, n_ionic, carrier):
    '''
    The ionic quasi-particle shift for a band
    '''

    U = n_sum**2. / vals['t']**3.

    delta = -n_ionic * (1. + U) / (
        np.sqrt(vals['t'] * n_sum / 2. / Const.pi) *
        (
            1. + vals['h' + carrier] * np.log(1. + np.sqrt(n_sum) / vals['t'])
        )
        + vals['j' + carrier] * U * n_p**.75 *
        (1. + vals['k' + carrier] * n_p**vals['q' + carrier])
    )

    return -vals['ryex'] * delta

31e4f70243452865e48a8bb0dfd90cf0e33bb30f
<mask token>


def none(*args, **kwargs):
    """
    returns the band gap narrowing in eV
    """
    return 0


def apparent_BGN(vals, doping, **kargs):
    """
    It returns the 'apparent BGN'. This estimates the real band gap
    narrowing, but uses the accurate Boltzmann statistics. N is the
    net dopant concentration.
    This model incorporates degeneracy as well as band gap narrowing,
    which is why it determines an 'apparent BGN' and not an actual BGN.
    The apparent occurs as Boltzmann statistics are used rather than
    Fermi-Dirac statistic.

    returns the band gap narrowing in eV
    """
    if type(doping).__module__ != np.__name__:
        doping = np.array(doping)
    BGN = np.zeros(np.array(doping).shape)
    index = doping > vals['n_onset']
    if np.sum(index) > 0:
        BGN[index] = vals['de_slope'] * np.log(doping[index] / vals['n_onset'])
    return BGN


def not_implimented(vals, doping, **kargs):
    """
    model not implemented, returning 0 values
    """
    return np.zeros(doping.shape)


<mask token>


def ridged_shift(vals, n_sum, n_p, num_carrier, carrier):
    """
    The rigid quasi-particle shift for a band
    the subscript a represents a carrier value (electron or hole)
    """
    delta = -((4.0 * Const.pi) ** 3.0 * n_sum ** 2.0 * ((48.0 * num_carrier /
        Const.pi / vals['g' + carrier]) ** (1.0 / 3.0) + vals['c' + carrier
        ] * np.log(1.0 + vals['d' + carrier] * n_p ** vals['p' + carrier])) +
        8.0 * Const.pi * vals['alpha' + carrier] / vals['g' + carrier] *
        num_carrier * vals['t'] ** 2.0 + np.sqrt(8.0 * Const.pi * n_sum) * 
        vals['t'] ** (5.0 / 2.0)) / ((4.0 * Const.pi) ** 3.0 * n_sum ** 2.0 +
        vals['t'] ** 3.0 + vals['b' + carrier] * np.sqrt(n_sum) * vals['t'] **
        2.0 + 40.0 * n_sum ** 1.5 * vals['t'])
    return -vals['ryex'] * delta


def ionic_shift(vals, n_sum, n_p, n_ionic, carrier):
    """
    The ionic quasi-particle shift for a band
    """
    U = n_sum ** 2.0 / vals['t'] ** 3.0
    delta = -n_ionic * (1.0 + U) / (np.sqrt(vals['t'] * n_sum / 2.0 / Const
        .pi) * (1.0 + vals['h' + carrier] * np.log(1.0 + np.sqrt(n_sum) /
        vals['t'])) + vals['j' + carrier] * U * n_p ** 0.75 * (1.0 + vals[
        'k' + carrier] * n_p ** vals['q' + carrier]))
    return -vals['ryex'] * delta

<mask token>


def none(*args, **kwargs):
    """
    returns the band gap narrowing in eV
    """
    return 0


def apparent_BGN(vals, doping, **kargs):
    """
    It returns the 'apparent BGN'. This estimates the real band gap
    narrowing, but uses the accurate Boltzmann statistics. N is the
    net dopant concentration.
    This model incorporates degeneracy as well as band gap narrowing,
    which is why it determines an 'apparent BGN' and not an actual BGN.
    The apparent occurs as Boltzmann statistics are used rather than
    Fermi-Dirac statistic.

    returns the band gap narrowing in eV
    """
    if type(doping).__module__ != np.__name__:
        doping = np.array(doping)
    BGN = np.zeros(np.array(doping).shape)
    index = doping > vals['n_onset']
    if np.sum(index) > 0:
        BGN[index] = vals['de_slope'] * np.log(doping[index] / vals['n_onset'])
    return BGN


def not_implimented(vals, doping, **kargs):
    """
    model not implemented, returning 0 values
    """
    return np.zeros(doping.shape)


<mask token>


def Schenk(vals, Nd, Na, ne, nh, temp, **args):
    """
    Based on the two principles:
    1. The rigid quasi-particle shifts of the conduction and
    valence band edges, which depend from the free-carrier concentrations
    2. the ionic quasi-particle shifts of the conduction and
    valence band edges resulting from ionised dopants concentrations

    returns the band gap narrowing in eV
    """
    ne = vals['aex'] ** 3.0 * ne
    nh = vals['aex'] ** 3.0 * nh
    Na = vals['aex'] ** 3.0 * Na
    Nd = vals['aex'] ** 3.0 * Nd
    n_sum = ne + nh
    n_ionic = Na + Nd
    n_p = vals['alphae'] * ne + vals['alphah'] * nh
    vals['t'] = Const.k * temp / vals['ryex'] / Const.e
    delta_Ec = ridged_shift(vals, n_sum, n_p, ne, 'e') + ionic_shift(vals,
        n_sum, n_p, n_ionic, 'e')
    delta_EV = ridged_shift(vals, n_sum, n_p, nh, 'h') + ionic_shift(vals,
        n_sum, n_p, n_ionic, 'h')
    return delta_Ec + delta_EV


def ridged_shift(vals, n_sum, n_p, num_carrier, carrier):
    """
    The rigid quasi-particle shift for a band
    the subscript a represents a carrier value (electron or hole)
    """
    delta = -((4.0 * Const.pi) ** 3.0 * n_sum ** 2.0 * ((48.0 * num_carrier /
        Const.pi / vals['g' + carrier]) ** (1.0 / 3.0) + vals['c' + carrier
        ] * np.log(1.0 + vals['d' + carrier] * n_p ** vals['p' + carrier])) +
        8.0 * Const.pi * vals['alpha' + carrier] / vals['g' + carrier] *
        num_carrier * vals['t'] ** 2.0 + np.sqrt(8.0 * Const.pi * n_sum) * 
        vals['t'] ** (5.0 / 2.0)) / ((4.0 * Const.pi) ** 3.0 * n_sum ** 2.0 +
        vals['t'] ** 3.0 + vals['b' + carrier] * np.sqrt(n_sum) * vals['t'] **
        2.0 + 40.0 * n_sum ** 1.5 * vals['t'])
    return -vals['ryex'] * delta


def ionic_shift(vals, n_sum, n_p, n_ionic, carrier):
    """
    The ionic quasi-particle shift for a band
    """
    U = n_sum ** 2.0 / vals['t'] ** 3.0
    delta = -n_ionic * (1.0 + U) / (np.sqrt(vals['t'] * n_sum / 2.0 / Const
        .pi) * (1.0 + vals['h' + carrier] * np.log(1.0 + np.sqrt(n_sum) /
        vals['t'])) + vals['j' + carrier] * U * n_p ** 0.75 * (1.0 + vals[
        'k' + carrier] * n_p ** vals['q' + carrier]))
    return -vals['ryex'] * delta

<mask token>


def none(*args, **kwargs):
    """
    returns the band gap narrowing in eV
    """
    return 0


def apparent_BGN(vals, doping, **kargs):
    """
    It returns the 'apparent BGN'. This estimates the real band gap
    narrowing, but uses the accurate Boltzmann statistics. N is the
    net dopant concentration.
    This model incorporates degeneracy as well as band gap narrowing,
    which is why it determines an 'apparent BGN' and not an actual BGN.
    The apparent occurs as Boltzmann statistics are used rather than
    Fermi-Dirac statistic.

    returns the band gap narrowing in eV
    """
    if type(doping).__module__ != np.__name__:
        doping = np.array(doping)
    BGN = np.zeros(np.array(doping).shape)
    index = doping > vals['n_onset']
    if np.sum(index) > 0:
        BGN[index] = vals['de_slope'] * np.log(doping[index] / vals['n_onset'])
    return BGN


def not_implimented(vals, doping, **kargs):
    """
    model not implemented, returning 0 values
    """
    return np.zeros(doping.shape)


def BGN(vals, doping, **kargs):
    """
    Returns the BGN when applied for carriers with Fermi distribution.
    This estimates the real band gap narrowing,
    but uses Boltzmann stats
    where N is the net dopant concentration.

    returns the band gap narrowing in eV
    """
    bgn = vals['de_slope'] * np.power(np.log(doping / vals['N_onset']),
        vals['b']) + vals['de_offset']
    if bgn.size > 1:
        bgn[bgn < 0] = 0
    return bgn


def Schenk(vals, Nd, Na, ne, nh, temp, **args):
    """
    Based on the two principles:
    1. The rigid quasi-particle shifts of the conduction and
    valence band edges, which depend from the free-carrier concentrations
    2. the ionic quasi-particle shifts of the conduction and
    valence band edges resulting from ionised dopants concentrations

    returns the band gap narrowing in eV
    """
    ne = vals['aex'] ** 3.0 * ne
    nh = vals['aex'] ** 3.0 * nh
    Na = vals['aex'] ** 3.0 * Na
    Nd = vals['aex'] ** 3.0 * Nd
    n_sum = ne + nh
    n_ionic = Na + Nd
    n_p = vals['alphae'] * ne + vals['alphah'] * nh
    vals['t'] = Const.k * temp / vals['ryex'] / Const.e
    delta_Ec = ridged_shift(vals, n_sum, n_p, ne, 'e') + ionic_shift(vals,
        n_sum, n_p, n_ionic, 'e')
    delta_EV = ridged_shift(vals, n_sum, n_p, nh, 'h') + ionic_shift(vals,
        n_sum, n_p, n_ionic, 'h')
    return delta_Ec + delta_EV


def ridged_shift(vals, n_sum, n_p, num_carrier, carrier):
    """
    The rigid quasi-particle shift for a band
    the subscript a represents a carrier value (electron or hole)
    """
    delta = -((4.0 * Const.pi) ** 3.0 * n_sum ** 2.0 * ((48.0 * num_carrier /
        Const.pi / vals['g' + carrier]) ** (1.0 / 3.0) + vals['c' + carrier
        ] * np.log(1.0 + vals['d' + carrier] * n_p ** vals['p' + carrier])) +
        8.0 * Const.pi * vals['alpha' + carrier] / vals['g' + carrier] *
        num_carrier * vals['t'] ** 2.0 + np.sqrt(8.0 * Const.pi * n_sum) * 
        vals['t'] ** (5.0 / 2.0)) / ((4.0 * Const.pi) ** 3.0 * n_sum ** 2.0 +
        vals['t'] ** 3.0 + vals['b' + carrier] * np.sqrt(n_sum) * vals['t'] **
        2.0 + 40.0 * n_sum ** 1.5 * vals['t'])
    return -vals['ryex'] * delta


def ionic_shift(vals, n_sum, n_p, n_ionic, carrier):
    """
    The ionic quasi-particle shift for a band
    """
    U = n_sum ** 2.0 / vals['t'] ** 3.0
    delta = -n_ionic * (1.0 + U) / (np.sqrt(vals['t'] * n_sum / 2.0 / Const
        .pi) * (1.0 + vals['h' + carrier] * np.log(1.0 + np.sqrt(n_sum) /
        vals['t'])) + vals['j' + carrier] * U * n_p ** 0.75 * (1.0 + vals[
        'k' + carrier] * n_p ** vals['q' + carrier]))
    return -vals['ryex'] * delta

import numpy as np
import scipy.constants as Const


def none(*args, **kwargs):
    """
    returns the band gap narrowing in eV
    """
    return 0


def apparent_BGN(vals, doping, **kargs):
    """
    It returns the 'apparent BGN'. This estimates the real band gap
    narrowing, but uses the accurate Boltzmann statistics. N is the
    net dopant concentration.
    This model incorporates degeneracy as well as band gap narrowing,
    which is why it determines an 'apparent BGN' and not an actual BGN.
    The apparent occurs as Boltzmann statistics are used rather than
    Fermi-Dirac statistic.

    returns the band gap narrowing in eV
    """
    if type(doping).__module__ != np.__name__:
        doping = np.array(doping)
    BGN = np.zeros(np.array(doping).shape)
    index = doping > vals['n_onset']
    if np.sum(index) > 0:
        BGN[index] = vals['de_slope'] * np.log(doping[index] / vals['n_onset'])
    return BGN


def not_implimented(vals, doping, **kargs):
    """
    model not implemented, returning 0 values
    """
    return np.zeros(doping.shape)


def BGN(vals, doping, **kargs):
    """
    Returns the BGN when applied for carriers with Fermi distribution.
    This estimates the real band gap narrowing,
    but uses Boltzmann stats
    where N is the net dopant concentration.

    returns the band gap narrowing in eV
    """
    bgn = vals['de_slope'] * np.power(np.log(doping / vals['N_onset']),
        vals['b']) + vals['de_offset']
    if bgn.size > 1:
        bgn[bgn < 0] = 0
    return bgn


def Schenk(vals, Nd, Na, ne, nh, temp, **args):
    """
    Based on the two principles:
    1. The rigid quasi-particle shifts of the conduction and
    valence band edges, which depend from the free-carrier concentrations
    2. the ionic quasi-particle shifts of the conduction and
    valence band edges resulting from ionised dopants concentrations

    returns the band gap narrowing in eV
    """
    ne = vals['aex'] ** 3.0 * ne
    nh = vals['aex'] ** 3.0 * nh
    Na = vals['aex'] ** 3.0 * Na
    Nd = vals['aex'] ** 3.0 * Nd
    n_sum = ne + nh
    n_ionic = Na + Nd
    n_p = vals['alphae'] * ne + vals['alphah'] * nh
    vals['t'] = Const.k * temp / vals['ryex'] / Const.e
    delta_Ec = ridged_shift(vals, n_sum, n_p, ne, 'e') + ionic_shift(vals,
        n_sum, n_p, n_ionic, 'e')
    delta_EV = ridged_shift(vals, n_sum, n_p, nh, 'h') + ionic_shift(vals,
        n_sum, n_p, n_ionic, 'h')
    return delta_Ec + delta_EV


def ridged_shift(vals, n_sum, n_p, num_carrier, carrier):
    """
    The rigid quasi-particle shift for a band
    the subscript a represents a carrier value (electron or hole)
    """
    delta = -((4.0 * Const.pi) ** 3.0 * n_sum ** 2.0 * ((48.0 * num_carrier /
        Const.pi / vals['g' + carrier]) ** (1.0 / 3.0) + vals['c' + carrier
        ] * np.log(1.0 + vals['d' + carrier] * n_p ** vals['p' + carrier])) +
        8.0 * Const.pi * vals['alpha' + carrier] / vals['g' + carrier] *
        num_carrier * vals['t'] ** 2.0 + np.sqrt(8.0 * Const.pi * n_sum) * 
        vals['t'] ** (5.0 / 2.0)) / ((4.0 * Const.pi) ** 3.0 * n_sum ** 2.0 +
        vals['t'] ** 3.0 + vals['b' + carrier] * np.sqrt(n_sum) * vals['t'] **
        2.0 + 40.0 * n_sum ** 1.5 * vals['t'])
    return -vals['ryex'] * delta


def ionic_shift(vals, n_sum, n_p, n_ionic, carrier):
    """
    The ionic quasi-particle shift for a band
    """
    U = n_sum ** 2.0 / vals['t'] ** 3.0
    delta = -n_ionic * (1.0 + U) / (np.sqrt(vals['t'] * n_sum / 2.0 / Const
        .pi) * (1.0 + vals['h' + carrier] * np.log(1.0 + np.sqrt(n_sum) /
        vals['t'])) + vals['j' + carrier] * U * n_p ** 0.75 * (1.0 + vals[
        'k' + carrier] * n_p ** vals['q' + carrier]))
    return -vals['ryex'] * delta

#!/usr/local/bin/python
# UTF-8

import numpy as np
import scipy.constants as Const


def none(*args, **kwargs):
    '''
    returns the band gap narrowing in eV
    '''
    return 0


def apparent_BGN(vals, doping, **kargs):
    '''
    It returns the 'apparent BGN'. This estimates the real band gap
    narrowing, but uses the accurate Boltzmann statistics. N is the
    net dopant concentration.
    This model incorporates degeneracy as well as band gap narrowing,
    which is why it determines an 'apparent BGN' and not an actual BGN.
    The apparent occurs as Boltzmann statistics are used rather than
    Fermi-Dirac statistic.

    returns the band gap narrowing in eV
    '''

    if type(doping).__module__ != np.__name__:
        doping = np.array(doping)

    BGN = np.zeros(np.array(doping).shape)

    index = doping > vals['n_onset']

    # making sure there are values to assign
    if np.sum(index) > 0:
        BGN[index] = (
            vals['de_slope'] * np.log(doping[index] / vals['n_onset']))

    return BGN


def not_implimented(vals, doping, **kargs):
    '''
    model not implemented, returning 0 values
    '''
    return np.zeros(doping.shape)


def BGN(vals, doping, **kargs):
    '''
    Returns the BGN when applied for carriers with Fermi distribution.
    This estimates the real band gap narrowing,
    but uses Boltzmann stats
    where N is the net dopant concentration.

    returns the band gap narrowing in eV
    '''
    # BGN = np.zeros(doping.shape)

    bgn = vals['de_slope']\
        * np.power(np.log(doping / vals['N_onset']), vals['b'])\
        + vals['de_offset']

    # ensures no negitive values
    if bgn.size > 1:
        bgn[bgn < 0] = 0

    return bgn


def Schenk(vals, Nd, Na, ne, nh, temp, **args):
    '''
    Based on the two principles:
    1. The rigid quasi-particle shifts of the conduction and
    valence band edges, which depend from the free-carrier concentrations
    2. the ionic quasi-particle shifts of the conduction and
    valence band edges resulting from ionised dopants concentrations

    returns the band gap narrowing in eV
    '''

    # makes the values unitless
    ne = (vals['aex']**3.) * ne
    nh = (vals['aex']**3.) * nh
    Na = (vals['aex']**3.) * Na
    Nd = (vals['aex']**3.) * Nd

    n_sum = ne + nh
    n_ionic = Na + Nd

    n_p = vals['alphae'] * ne + vals['alphah'] * nh

    # cacualtes curly T, to give linear dependence with temp
    vals['t'] = Const.k * temp / vals['ryex'] / Const.e

    delta_Ec = ridged_shift(vals, n_sum, n_p, ne, 'e')\
        + ionic_shift(vals, n_sum, n_p, n_ionic, 'e')
    delta_EV = ridged_shift(vals, n_sum, n_p, nh, 'h')\
        + ionic_shift(vals, n_sum, n_p, n_ionic, 'h')

    # print(delta_Ec, delta_EV)
    return delta_Ec + delta_EV


def ridged_shift(vals, n_sum, n_p, num_carrier, carrier):
    '''
    The rigid quasi-particle shift for a band
    the subscript a represents a carrier value (electron or hole)
    '''

    delta = -(
        (4. * Const.pi)**3. * n_sum**2. *
        (
            (48. * num_carrier / Const.pi / vals['g' + carrier])**(1. / 3.)
            + vals['c' + carrier] * np.log(1. + vals['d' + carrier] *
                                           n_p**vals['p' + carrier]))
        + (8. * Const.pi * vals['alpha' + carrier] / vals['g' + carrier])
        * num_carrier * vals['t']**2.
        + np.sqrt(8. * Const.pi * n_sum) * vals['t']**(5. / 2.)
    ) / (
        (4. * Const.pi)**3. * n_sum**2. + vals['t']**3. + vals['b' + carrier] *
        np.sqrt(n_sum) * vals['t']**2. + 40. * n_sum**1.5 * vals['t'])
    return -vals['ryex'] * delta


def ionic_shift(vals, n_sum, n_p, n_ionic, carrier):
    '''
    The ionic quasi-particle shift for a band
    '''

    U = n_sum**2. / vals['t']**3.

    delta = -n_ionic * (1. + U) / (
        np.sqrt(vals['t'] * n_sum / 2. / Const.pi) *
        (
            1. + vals['h' + carrier] * np.log(1. + np.sqrt(n_sum) / vals['t'])
        )
        + vals['j' + carrier] * U * n_p**.75 *
        (1. + vals['k' + carrier] * n_p**vals['q' + carrier])
    )

    return -vals['ryex'] * delta
