def func_energy(E, tt, U_bias, A, spB_s, spB_d):

    eta = globvars.eta
    Nx = globvars.Nx
    Vd = Vdc.value
    Temp = Te
    fermi_flag = fermiflag1.value

    ee = E
    ep = ee+eta
    ck = 1-((ep-U_bias[0])/(2.0*tt))

    con_s = -tt*np.exp(1j*np.arccos(ck))
    ck = 1-((ep-U_bias[Nx-1])/(2*tt))
    con_d = -tt*np.exp(1j*np.arccos(ck))
    U_eff = U_bias
    U_eff = U_eff + 0j
    U_eff[0] = U_bias[0]+con_s
    U_eff[Nx-1] = U_bias[Nx-1]+con_d
    G_inv = (ep*np.eye(Nx))-A-np.diag(U_eff)
    G_s = spsolve(sparse.csr_matrix(G_inv), spB_s)
    G_d = spsolve(sparse.csr_matrix(G_inv), spB_d)
    f_1 = fermi(((-Vs-ee)/(k_B*Temp/q)), fermi_flag, -1.0/2.0)
    f_2 = fermi(((-Vd-ee)/(k_B*Temp/q)), fermi_flag, -1.0/2.0)
    N_den = -abs(G_s)**2*np.imag(con_s)*2.0*f_1-abs(G_d)**2*np.imag(con_d)*2.0*f_2
    return N_den
def func_energy(E, tt, U_bias, A, spB_s, spB_d):

    eta = globvars.eta
    Nx = globvars.Nx
    Vd = Vdc.value
    Temp = Te
    fermi_flag = fermiflag1.value

    ee = E
    ep = ee + eta
    ck = 1 - ((ep - U_bias[0]) / (2.0 * tt))

    con_s = -tt * np.exp(1j * np.arccos(ck))
    ck = 1 - ((ep - U_bias[Nx - 1]) / (2 * tt))
    con_d = -tt * np.exp(1j * np.arccos(ck))
    U_eff = U_bias
    U_eff = U_eff + 0j
    U_eff[0] = U_bias[0] + con_s
    U_eff[Nx - 1] = U_bias[Nx - 1] + con_d
    G_inv = (ep * np.eye(Nx)) - A - np.diag(U_eff)
    G_s = spsolve(sparse.csr_matrix(G_inv), spB_s)
    G_d = spsolve(sparse.csr_matrix(G_inv), spB_d)
    f_1 = fermi(((-Vs - ee) / (k_B * Temp / q)), fermi_flag, -1.0 / 2.0)
    f_2 = fermi(((-Vd - ee) / (k_B * Temp / q)), fermi_flag, -1.0 / 2.0)
    N_den = -abs(G_s)**2 * np.imag(con_s) * 2.0 * f_1 - abs(G_d)**2 * np.imag(
        con_d) * 2.0 * f_2
    return N_den
Example #3
0
def dummy_prime(x, dummy_flag, fermi_flag):
    if dummy_flag == 0:
        if fermi_flag == 0:
            y = np.exp(x)
        elif fermi_flag == 1:
            y = 1 / (1 + np.exp(-x))
    elif dummy_flag == 1.0 / 2.0:
        y = fermi(x, fermi_flag, -1.0 / 2.0)

    return y
def dummy_prime(x, dummy_flag, fermi_flag):
    if dummy_flag == 0:
        if fermi_flag == 0:
            y = np.exp(x)
        elif fermi_flag == 1:
            y = 1/(1 + np.exp(-x))
    elif dummy_flag == 1.0/2.0:
        y = fermi(x, fermi_flag, -1.0/2.0)

    return y
Example #5
0
def dummy(x, dummy_flag, fermi_flag):
    if dummy_flag == 0:
        if fermi_flag == 0:
            y = np.exp(x)
        elif fermi_flag == 1:
            y = np.log(1+np.exp(x))

    elif dummy_flag == 1.0/2.0:
        y = fermi(x, fermi_flag, 1.0/2.0)

    return y
Example #6
0
def dummy(x, dummy_flag, fermi_flag):
    if dummy_flag == 0:
        if fermi_flag == 0:
            y = np.exp(x)
        elif fermi_flag == 1:
            y = np.log(1 + np.exp(x))

    elif dummy_flag == 1.0 / 2.0:
        y = fermi(x, fermi_flag, 1.0 / 2.0)

    return y
def integral(zeta_s, zeta_d, upper_lim, fermi_flag):
    E_tail = 12
    tem_lim = upper_lim**0.5
    if tem_lim > 0:
        dx = 1e-2
        # dx=1e-2 means dE=2xdx, so dE varies from 0eV to ~2meV@E=20KT/q
        # the error criterion then can be around 1e-4 eV.
        nx = round(tem_lim / dx) + 2
        x = np.linspace(0, tem_lim, nx)
        dx = x[1]
        dummy1 = fermi(zeta_s - x**2, fermi_flag, -1.0 / 2.0)
        y1 = (sum(dummy1) - dummy1[0] / 2.0 - dummy1[nx - 1] / 2.0) * dx
    else:
        y1 = 0

    tem_lim_l = upper_lim**0.5
    tem_lim_h = (max(upper_lim + E_tail, zeta_d + E_tail))**0.5
    dx = 1e-2
    # dx=1e-3 means dE=2xdx, so dE varies from ~0.2meV@E=20KT/q to ~0.3meV@E=40KT/q
    # the error criterion then can be around 1e-4 eV.
    nx = round((tem_lim_h - tem_lim_l) / dx) + 2
    x = np.linspace(tem_lim_l, tem_lim_h, nx)
    dx = x[1] - x[0]
    dummy2 = fermi(zeta_d - x**2, fermi_flag, -1.0 / 2.0)
    y2 = (sum(dummy2) - dummy2[0] / 2.0 - dummy2[nx - 1] / 2) * dx

    tem_lim_l = 0
    tem_lim_h = (max(upper_lim + E_tail, zeta_s + E_tail))**0.5
    dx = 1e-2
    nx = round((tem_lim_h - tem_lim_l) / dx) + 2
    x = np.linspace(tem_lim_l, tem_lim_h, nx)
    dx = x[1] - x[0]
    dummy3 = fermi(zeta_s - x**2, fermi_flag, -1.0 / 2.0)
    y3 = (sum(dummy3) - dummy3[1] / 2.0 - dummy3[nx - 1] / 2.0) * dx

    y = y1 + y2 + y3

    return y
Example #8
0
 def __init__(self,
              playerNumber,
              strategyType='random',
              currentAction='C',
              nextAction=None,
              fraction=0.5):
     ''' Create a strategy with different type'''
     self.__strategyType = strategyType
     self.__nextAction = nextAction
     self.__fraction = fraction
     self.__currentAction = currentAction
     self.__qlInstance = qlearningStrategy(playerNumber)
     self.__fermiInstance = fermi()
     self.__F = 5
     self.__cost = 1
     self.__M = 1
     self.__cooperatorCount = 0
     self.__groupSize = 0
def current_mat(mu_scatter_old, T_E, E):
    #**************************FUNDAMENTAL physical constants********************************
    fermi_flag = fermiflag1.value
    Nx = globvars.Nx
    Temp = Te
    nu_scatter = globvars.nu_scatter
    mx = globvars.mx
    my = globvars.my
    mz = globvars.mz

    #**********************************INITIALIZATION****************************************
    dmu = 1e-6
    I_criterion = 1e-2 #1E-8A/um

    Iin = np.zeros((nu_scatter, 1))
    mu_scatter_new = np.zeros((nu_scatter+2, 1))

    delta_mu = np.zeros((nu_scatter+2, 1))
    delta_mu = np.squeeze(delta_mu)
    I_tem = np.zeros(2)
    IMU = np.zeros((nu_scatter, nu_scatter))
    IMU_dummy = np.zeros((nu_scatter, nu_scatter))
    T_dummy = np.sum(T_E, 0)
    #print sparse.csr_matrix(T_dummy[:,0])
    #print mu_scatter_old

    #***************************************************************************************
    #*************************************EVALUATE Iin**************************************
    #***************************************************************************************
    for i_node in np.arange(0,nu_scatter):
        I_dummy1 = np.dot(fermi(((mu_scatter_old[i_node]-E)/(k_B*Temp/q)),fermi_flag,-1.0/2.0),T_dummy[:,i_node])
        #print fermi(((mu_scatter_old[i_node]-E)/(k_B*Temp/q)),fermi_flag,-1.0/2.0)
        #print I_dummy1
        #print T_dummy[:,i_node]
        I_dummy2 = 0
        #print np.shape(fermi(((mu_scatter_old[i_node]-E)/(k_B*Temp/q)),fermi_flag,-1.0/2.0))
        #print np.shape(T_dummy[:,i_node])
        #Idum = fermi(((mu_scatter_old[i_node]-E)/(k_B*Temp/q)),fermi_flag,-1.0/2.0) * np.reshape(T_dummy[:,i_node],(799,1))
        #print Idum
        #exit()
        for j_node in np.arange(0,nu_scatter+2):
            I_dummy2 = I_dummy2 + np.dot(fermi(((mu_scatter_old[j_node]-E)/(k_B*Temp/q)),fermi_flag,-1.0/2.0),T_E[j_node, :, i_node])
            #print I_dummy2
        Iin[i_node] = I_dummy1-I_dummy2
        #print I_dummy1
        #print 'idum2'
        #print I_dummy2
        #print Iin[i_node]
        #exit()
    Isc = np.max(abs(Iin))
    #print Iin

    #***************************************************************************************
    #*************************************EVALUATE IMU**************************************
    #***************************************************************************************

    if Isc>=I_criterion:
        for i_node in np.arange(0, nu_scatter):
            IMU_dummy[i_node,i_node]=np.dot(((fermi(((mu_scatter_old[i_node]+dmu-E)/(k_B*Temp/q)),fermi_flag,-1.0/2.0)-fermi(((mu_scatter_old[i_node]-dmu-E)/(k_B*Temp/q)),fermi_flag,-1.0/2.0))/(2.0*dmu)),T_dummy[:,i_node])
            for j_node in np.arange(0, nu_scatter):
                IMU[i_node,j_node]=np.dot(((fermi(((mu_scatter_old[j_node]+dmu-E)/(k_B*Temp/q)),fermi_flag,-1.0/2.0)-fermi(((mu_scatter_old[j_node]-dmu-E)/(k_B*Temp/q)),fermi_flag,-1.0/2.0))/(2.0*dmu)),T_E[j_node, :,i_node])
        IMU=IMU_dummy-IMU

    #***************************************************************************************
    #**********************************END OF EVALUATE IMU**********************************
    #***************************************************************************************

    mu_scatter_new = mu_scatter_old

    #*********************************Newton searching loop*********************************

    iiii = 0
    #print Isc
    #print I_criterion
    while(Isc>=I_criterion):
        print 'Entering Jacobian loop in Current_mat'
        delta_mu[0:nu_scatter] = -spsolve(sparse.csr_matrix(IMU),sparse.csr_matrix(Iin))

        # The following IF statement performs a check to insure that the correction does not
        # bring the fermi level in the device above the source fermi level or below the drain fermi level.
        # If it does, then we averaged the fermi level of the scatterer to make it fit within that physical range of fermi levels.
        # If we don't perform that check, in some cases we can get a scatterer fermi level well below the drain fermi level
        # which forces charges to flow from the drain to fill the available state.......as a result -> NO convergence.

        mu_scatter_new=mu_scatter_new+delta_mu

        for i_node in np.arange(0, nu_scatter):
            if mu_scatter_new[i_node]>mu_scatter_new[nu_scatter]:
                mu_scatter_new[i_node] = mu_scatter_new[nu_scatter]
            elif mu_scatter_new[i_node]<mu_scatter_new[nu_scatter+1]:
                mu_scatter_new[i_node]=mu_scatter_new[nu_scatter+1]
            else:
                mu_scatter_new[i_node]=mu_scatter_new[i_node]

        #if (max(mu_scatter_new(1:nu_scatter))>mu_scatter_new(nu_scatter+1) ...
        #| min(mu_scatter_new(1:nu_scatter))<mu_scatter_new(nu_scatter+2))

        #   mu_scatter_new(1:nu_scatter)=(mu_scatter_old(1:nu_scatter)+mu_scatter_new(1:nu_scatter))/2.0;
        #   fprintf(1,'#s#s#e\n','AVERAGED ','MAX CHANGE ',max(abs(mu_scatter_new(1:nu_scatter)-mu_scatter_old(1:nu_scatter))));

        #else
        #    fprintf(1,'#s#s#e\n','NOT AVERAGED ','MAX CHANGE ',max(abs(mu_scatter_new(1:nu_scatter)-mu_scatter_old(1:nu_scatter))));

        #end

        #for i nu_scatter

        #  for i_node=1:nu_scatter
        #    if(abs(delta_mu(i_node))<=1)
        #       delta_mu(i_node)=delta_mu(i_node);
        #    elseif(1<abs(delta_mu(i_node)) & abs(delta_mu(i_node)) <3.7)
        #       delta_mu(i_node)=sign(delta_mu(i_node))*power(abs(delta_mu(i_node)),1/5);
        #    elseif(abs(delta_mu(i_node))>=3.7)
        #       delta_mu(i_node)=sign(delta_mu(i_node))*log(abs(delta_mu(i_node)));
        #    end
        #  end

        #  mu_scatter_new=mu_scatter_new+delta_mu;

        #****************************************************************************************
        #************************************ EVALUATE Iin***************************************
        #****************************************************************************************
        for i_node in np.arange(0,nu_scatter):
            I_dummy1 = np.dot(fermi(((mu_scatter_new[i_node]-E)/(k_B*Temp/q)),fermi_flag,-1.0/2.0),T_dummy[:,i_node])
            I_dummy2=0
            for j_node in np.arange(0,nu_scatter+2):
                I_dummy2=I_dummy2+np.dot(fermi(((mu_scatter_new[j_node]-E)/(k_B*Temp/q)),fermi_flag,-1.0/2.0),T_E[j_node, :,i_node])
            Iin[i_node] = I_dummy1-I_dummy2
        Isc = max(abs(Iin))
        print 'Isc =', Isc

        #****************************************************************************************
        #***********************************END OF EVALUATE Iin**********************************
        #****************************************************************************************

        if Isc>=I_criterion:

        #****************************************************************************************
        #**************************************EVALUATE IMU**************************************
        #****************************************************************************************
            for i_node in np.arange(0,nu_scatter):
                IMU_dummy[i_node,i_node]=np.dot(((fermi(((mu_scatter_new[i_node]+dmu-E)/(k_B*Temp/q)),fermi_flag,-1.0/2.0)-fermi(((mu_scatter_new[i_node]-dmu-E)/(k_B*Temp/q)),fermi_flag,-1.0/2.0))/(2.0*dmu)),T_dummy[:,i_node])
                for j_node in np.arange(0,nu_scatter):
                    IMU[i_node,j_node]=np.dot(((fermi(((mu_scatter_new[j_node]+dmu-E)/(k_B*Temp/q)),fermi_flag,-1.0/2.0)-fermi(((mu_scatter_new[j_node]-dmu-E)/(k_B*Temp/q)),fermi_flag,-1.0/2.0))/(2.0*dmu)),T_E[j_node, :,i_node])
            IMU=IMU_dummy-IMU

            #****************************************************************************************
            #***********************************END OF EVALUATE IMU**********************************
            #****************************************************************************************
        iiii = iiii+1
        print 'iiii = ', iiii

        # Copy old vals
        mu_scatter_old=mu_scatter_new

    for i_node in np.arange(0, 2):
        I_dummy1 = np.dot(fermi(((mu_scatter_new[i_node+nu_scatter]-E)/(k_B*Temp/q)),fermi_flag,-1.0/2.0),T_dummy[:,i_node+nu_scatter])
        #print I_dummy1
        #exit()
        I_dummy2=0
        for j_node in np.arange(0, nu_scatter+2):
            I_dummy2 = I_dummy2+np.dot(fermi(((mu_scatter_new[j_node]-E)/(k_B*Temp/q)),fermi_flag,-1.0/2.0),T_E[j_node, :, i_node+nu_scatter])
        I_tem[i_node]=I_dummy1-I_dummy2

    Is=I_tem[0]
    print Is
    Id=I_tem[1]
    print Id



    return [Is, Id, Iin, mu_scatter_new]
Example #10
0
def current(Ne, Ec, Ne_sub, E_sub, Nx, Ny, Ntotal, mx, my ,mz ):
    Temp = Te
    transport_model = transportmodel.value
    Vd = Vdc.value
    fermi_flag = fermiflag1.value
    E = globvars.E
    nu_scatter = globvars.nu_scatter
    Info_scatter_old = globvars.Info_scatter_old

    #### MODEL 2 related parameters

    eta = 1e-6j
    Ef_tail_low = 0.01
    Ef_tail_up = 0.3
    E_step = criterion_outer/2.0  # 0.5 times criterion_outer

    ####MODEL 4 related parameters
    e_field_limit = 1.0  # in V/m
    ####MODEL 5 related parameters

    ###########################################################
    #	INPUT AND OUTPUT VARIABLES
    ###########################################################
    #Info_scatter_old contains all information of scatters
    #2-dim matrix, dim_2:current,index, and Fermi energy, low field mobility
    #Ne_old is the old electron density
    #1 column of Ntotal elements
    #Ec_old is the old potential energy profile in eV
    #1 column of Ntotal elements
    #Te_old is the old electron temperature along the channel
    #1 column of Nx elements, for charge-sheet-model
    #Ne_sub contains 2D electron density on each subband
    #E_sub contains the 1D subband energy for all subband
    #considered
    #Te_sub_old contains the 1D electron temperature for all subband
    #considered, for bulk model

    #Ne is the 3D electron density profile in the entire device
    #1 column matrix of Ntotal elements
    #Ec is the conduction band edge profile in the entire device
    #1 column matrix of Ntotal elements
    #Te_old is 1 column matrix of Nx elements for electron temperature
    #, for charge-sheet-model

    #Ie is 1 column matrix of Nx elements for current density
    #A/m
    #Ie_sub contains currents carried in all subbands.
    ###########################################################

    ###########################################################
    #	TEMPORARY VARIABLES
    ###########################################################
    #Ec_channel is the given potential energy profile
    #along the channel
    #Fn_channel is the given quasi Fermi level along the channel
    #Ne_channel is the given electron 2D density along the channel
    #max_subband is the number of subbands considered
    #t_vall is the number of valleyes considered

    #########################INITIALIZATION#######################################
    Ie = np.zeros((Nx,1))
    Ie_sub = np.zeros((t_vall, Nx,max_subband))
    Te_sub = np.zeros((t_vall, Nx,max_subband))
    Fn_sub = np.zeros((t_vall, Nx,max_subband))
    #E_sub = np.zeros((Nx,max_subband,t_vall))
    #Ne_sub = np.zeros((Nx,max_subband,t_vall))

    #Info_scatter_new = np.zeros((nu_scatter,4))
    #Info_scatter_new = Info_scatter_old
    Ec_channel = np.zeros((Nx,1))
    Fn_channel = np.zeros((Nx,1))
    Ne_channel = np.zeros((Nx,1))
    #Fn_new = np.zeros((Ntotal,1))
    #Ne_new = np.zeros((Ntotal,1))

    #temporarily used variables
    if ox_pnt_flag == 0:
       Np_v = round(t_si/dy)+1
    elif ox_pnt_flag == 1:
       Np_v = Ny

    Ns = np.zeros((Nx, 1))
    N_body = np.zeros((Np_v, Nx))
    N_body_sum = np.zeros((Np_v, Nx))
    U_sub = np.zeros((Nx, max_subband, t_vall))
    W_sub = np.zeros((Np_v, Nx, max_subband, t_vall))
    U_bias = np.zeros((Nx, 1))

    ##############################################################################
    #THE START OF TRANSPORT EQUATION PART#########################################
    ##############################################################################

    ##############################################################################
    if transport_model==1:  #TRANSPORT MODEL 1######################################
        print 'entered tm1'
    ##############################################################################

    #*****************************************************************************
    elif transport_model==2: #TRANSPORT MODEL 2 DD*******************************
    #*****************************************************************************
        U_bias = np.zeros((Nx,1))
        Ns = np.zeros((Nx,1))
        Ie_tem = np.zeros((Nx,1))
        mobility = np.zeros((nu_scatter-1,1))
        mobility = (np.diff(Info_scatter_old[:,3])+2*Info_scatter_old[0:Nx-1,3])/2.0

        for i_val in np.arange(0, t_vall):
            Nccc = 2*m_e*np.sqrt(mx[i_val]*my[i_val])*k_B*Temp/(np.pi*h_bar**2)

            for i_sub in np.arange(max_subband):
                U_bias = E_sub[i_val, :, i_sub]
                Ns = Ne_sub[i_val, :, i_sub]

                if fermi_flag == 0:
                    fac_deg= np.ones(Nx-1)
                elif fermi_flag == 1:
                    Fn_channel = U_bias+(k_B*Temp/q)*anti_dummy(Ns/Nccc,0,fermi_flag)
                    zeta_channel = (Fn_channel-U_bias)/(k_B*Temp/q)
                    fac_deg_tem = np.log(1+np.exp(zeta_channel))*(1+np.exp(-zeta_channel))
                    fac_deg=(np.diff(fac_deg_tem)+2*fac_deg_tem[0:Nx-1])/2
                V_channel = -U_bias
                E_channel = -np.diff(V_channel)/dx
                mu_channel = mobility/(1+(mobility/Vel_sat*abs(E_channel))**beta)**(1/beta)

                Coe_1 = np.zeros(Nx-1)
                Coe_2 = np.zeros(Nx-1)

                for j in np.arange(0,Nx-1):
                    if abs(E_channel[j])<=abs(e_field_limit*fac_deg[j]):
                        Coe_1[j] = -mu_channel[j]*(k_B*Temp/q)*fac_deg[j]/dx
                        Coe_2[j] = -Coe_1[j]
                    else:
                        Coe_1[j] = mu_channel[j]*E_channel[j]*1/(1-np.exp(E_channel[j]*dx/((k_B*Temp/q)*fac_deg[j])))
                        Coe_2[j] = mu_channel[j]*E_channel[j]*1/(1-np.exp(-E_channel[j]*dx/((k_B*Temp/q)*fac_deg[j])))
                    Ie_tem[j]=-q*(Ns[j]*Coe_1[j]+Ns[j+1]*Coe_2[j])

                Ie_tem[Nx-1] = Ie_tem[Nx-2]
                Ie_sub[i_val, :,i_sub] = np.squeeze(Ie_tem)
                Fn_sub[i_val, :,i_sub] = Fn_channel
                Ie = Ie+Ie_tem

    ###########################################################################
    elif transport_model==3:  #BALLISTIC TRANSPORT USING SEMICLASSICAL APPROACH
    ###########################################################################
        U_bias = np.zeros((Nx,1))

        for i_val in np.arange(0, t_vall):
            Ie_2d = 2.0*q/h_bar**2*np.sqrt(mx[i_val]*m_e/2.0)*((k_B*Temp/q)*q/np.pi)**(3.0/2.0)

            for i_sub in np.arange(0, max_subband):
                U_bias = E_sub[i_val, :,i_sub]
                Ec_peak = max(U_bias)

                Ie_tem = 0
                Ie_tem = Ie_2d*(fermi(((-Vs-Ec_peak)/(k_B*Temp/q)),fermi_flag,1.0/2.0)-fermi(((-Vd-Ec_peak)/(k_B*Temp/q)),fermi_flag,1.0/2.0))
                Ie_sub[i_val, :, i_sub] = Ie_tem*np.ones(Nx)
                Ie = Ie+Ie_tem*np.ones(Nx)


    ##################################################################################
    elif transport_model==4: #BALLISTIC TRANSPORT MODEL USING GREEN FUNCTION APPROACH#
    ##################################################################################

        U_bias = np.zeros((Nx,1))

        Ec_peak = np.max((-Vs, np.max(E_sub[t_vall-1, :, max_subband-1])))
        E_number = round((Ec_peak+Ef_tail_up - E_sub[0, Nx-1, 0] + Ef_tail_low)/E_step)+2
        E = np.linspace((E_sub[0, Nx-1, 0]-Ef_tail_low),(Ec_peak+Ef_tail_up),E_number)
        delta_E = ((Ec_peak+Ef_tail_up)-(E_sub[0, Nx-1, 0]-Ef_tail_low))/(E_number-1)

        N_dos_one = np.zeros((Nx,E_number))
        N_dos = np.zeros((Nx,E_number))

        #used to plot the transmission coefficient with several valleys
        Trans_sub = np.zeros((E_number,1))
        Trans = np.zeros((E_number,1))

        for i_val in np.arange(0,t_vall):
            Ne_2d = 2*np.sqrt(mx[i_val]*m_e*(k_B*Temp/q)*q/(2*np.pi**3))/(h_bar*dx)
            Ie_2d = 2*q**2/(np.pi**2*h_bar**2)*np.sqrt(mx[i_val]*m_e*(k_B*Temp/q)*q*np.pi/2)
            tt = (h_bar**2)/(2*my[i_val]*m_e*(dx**2)*q)
            tt = float(tt)
            A = tt*((2*np.eye(Nx))-(np.diag(np.ones(Nx-1), 1))-(np.diag(np.ones(Nx-1), -1)))

            for i_sub in np.arange(0,max_subband):
                U_bias = E_sub[i_val, :, i_sub]
                #Ec_peak = max(-Vs,max(U_bias))
                #E_number = round((Ec_peak+Ef_tail_up-U_bias(Nx)+Ef_tail_low)/E_step)+2
                #E = np.linspace((U_bias(Nx)-Ef_tail_low),(Ec_peak+Ef_tail_up),E_number)
                #delta_E = ((Ec_peak+Ef_tail_up)-(U_bias(Nx)-Ef_tail_low))/(E_number-1)

                B_d = np.zeros((Nx, 1))
                B_d[Nx-1] = 1
                spB_d = sparse.csr_matrix(B_d)
                B_s = np.zeros((Nx, 1))
                B_s[0] = 1
                spB_s = sparse.csr_matrix(B_s)

                Ie_tem = 0
                for k in np.arange(0,E_number):
                    ee = E[k]
                    ep = ee + eta
                    ck = 1-((ep-U_bias[0])/(2*tt))
                    con_s = -tt*np.exp(1j*np.arccos(ck))
                    ck = 1-((ep-U_bias[Nx-1])/(2*tt))
                    con_d = -tt*np.exp(1j*np.arccos(ck))
                    U_eff = U_bias
                    U_eff = U_eff + 0j
                    U_eff[0] = U_bias[0] + con_s
                    U_eff[Nx-1] = U_bias[Nx-1] + con_d
                    G_inv = sparse.csr_matrix((ep*np.eye(Nx))-A-np.diag(U_eff))
                    G_s = spsolve(G_inv, spB_s)
                    G_d = spsolve(G_inv, spB_d)
                    f_1 = fermi(((-Vs-ee)/(k_B*Temp/q)), fermi_flag, -1.0/2.0)
                    f_2 = fermi(((-Vd-ee)/(k_B*Temp/q)), fermi_flag, -1.0/2.0)
                    Ie_tem = Ie_tem+abs(G_d[0])**2*np.imag(con_s)*np.imag(con_d)*4*(f_1-f_2)
                    Trans[k] = abs(G_d[0])**2*np.imag(con_s)*np.imag(con_d)*4
                    N_dos_one[:, k] = -abs(G_s)**2*np.imag(con_s)-abs(G_d)**2*np.imag(con_d)

                N_dos = N_dos+Ne_2d*N_dos_one

                Ie_sub[i_val, :, i_sub] = Ie_2d*delta_E*Ie_tem * np.ones(Nx)
                Ie = Ie+Ie_2d*delta_E * Ie_tem*np.ones(Nx)
                Trans_sub = Trans_sub+Trans

        Trans = Trans_sub
        globvars.Trans = Trans
        globvars.N_dos = N_dos

    return [Ie, Ie_sub, Te_sub, Fn_sub]
def current_mat(mu_scatter_old, T_E, E):
    #**************************FUNDAMENTAL physical constants********************************
    fermi_flag = fermiflag1.value
    Nx = globvars.Nx
    Temp = Te
    nu_scatter = globvars.nu_scatter
    mx = globvars.mx
    my = globvars.my
    mz = globvars.mz

    #**********************************INITIALIZATION****************************************
    dmu = 1e-6
    I_criterion = 1e-2  #1E-8A/um

    Iin = np.zeros((nu_scatter, 1))
    mu_scatter_new = np.zeros((nu_scatter + 2, 1))

    delta_mu = np.zeros((nu_scatter + 2, 1))
    delta_mu = np.squeeze(delta_mu)
    I_tem = np.zeros(2)
    IMU = np.zeros((nu_scatter, nu_scatter))
    IMU_dummy = np.zeros((nu_scatter, nu_scatter))
    T_dummy = np.sum(T_E, 0)
    #print sparse.csr_matrix(T_dummy[:,0])
    #print mu_scatter_old

    #***************************************************************************************
    #*************************************EVALUATE Iin**************************************
    #***************************************************************************************
    for i_node in np.arange(0, nu_scatter):
        I_dummy1 = np.dot(
            fermi(((mu_scatter_old[i_node] - E) / (k_B * Temp / q)),
                  fermi_flag, -1.0 / 2.0), T_dummy[:, i_node])
        #print fermi(((mu_scatter_old[i_node]-E)/(k_B*Temp/q)),fermi_flag,-1.0/2.0)
        #print I_dummy1
        #print T_dummy[:,i_node]
        I_dummy2 = 0
        #print np.shape(fermi(((mu_scatter_old[i_node]-E)/(k_B*Temp/q)),fermi_flag,-1.0/2.0))
        #print np.shape(T_dummy[:,i_node])
        #Idum = fermi(((mu_scatter_old[i_node]-E)/(k_B*Temp/q)),fermi_flag,-1.0/2.0) * np.reshape(T_dummy[:,i_node],(799,1))
        #print Idum
        #exit()
        for j_node in np.arange(0, nu_scatter + 2):
            I_dummy2 = I_dummy2 + np.dot(
                fermi(((mu_scatter_old[j_node] - E) / (k_B * Temp / q)),
                      fermi_flag, -1.0 / 2.0), T_E[j_node, :, i_node])
            #print I_dummy2
        Iin[i_node] = I_dummy1 - I_dummy2
        #print I_dummy1
        #print 'idum2'
        #print I_dummy2
        #print Iin[i_node]
        #exit()
    Isc = np.max(abs(Iin))
    #print Iin

    #***************************************************************************************
    #*************************************EVALUATE IMU**************************************
    #***************************************************************************************

    if Isc >= I_criterion:
        for i_node in np.arange(0, nu_scatter):
            IMU_dummy[i_node, i_node] = np.dot(
                ((fermi(((mu_scatter_old[i_node] + dmu - E) /
                         (k_B * Temp / q)), fermi_flag, -1.0 / 2.0) - fermi(
                             ((mu_scatter_old[i_node] - dmu - E) /
                              (k_B * Temp / q)), fermi_flag, -1.0 / 2.0)) /
                 (2.0 * dmu)), T_dummy[:, i_node])
            for j_node in np.arange(0, nu_scatter):
                IMU[i_node, j_node] = np.dot(((fermi(
                    ((mu_scatter_old[j_node] + dmu - E) /
                     (k_B * Temp / q)), fermi_flag, -1.0 / 2.0) - fermi(
                         ((mu_scatter_old[j_node] - dmu - E) /
                          (k_B * Temp / q)), fermi_flag, -1.0 / 2.0)) /
                                              (2.0 * dmu)), T_E[j_node, :,
                                                                i_node])
        IMU = IMU_dummy - IMU

    #***************************************************************************************
    #**********************************END OF EVALUATE IMU**********************************
    #***************************************************************************************

    mu_scatter_new = mu_scatter_old

    #*********************************Newton searching loop*********************************

    iiii = 0
    #print Isc
    #print I_criterion
    while (Isc >= I_criterion):
        print 'Entering Jacobian loop in Current_mat'
        delta_mu[0:nu_scatter] = -spsolve(sparse.csr_matrix(IMU),
                                          sparse.csr_matrix(Iin))

        # The following IF statement performs a check to insure that the correction does not
        # bring the fermi level in the device above the source fermi level or below the drain fermi level.
        # If it does, then we averaged the fermi level of the scatterer to make it fit within that physical range of fermi levels.
        # If we don't perform that check, in some cases we can get a scatterer fermi level well below the drain fermi level
        # which forces charges to flow from the drain to fill the available state.......as a result -> NO convergence.

        mu_scatter_new = mu_scatter_new + delta_mu

        for i_node in np.arange(0, nu_scatter):
            if mu_scatter_new[i_node] > mu_scatter_new[nu_scatter]:
                mu_scatter_new[i_node] = mu_scatter_new[nu_scatter]
            elif mu_scatter_new[i_node] < mu_scatter_new[nu_scatter + 1]:
                mu_scatter_new[i_node] = mu_scatter_new[nu_scatter + 1]
            else:
                mu_scatter_new[i_node] = mu_scatter_new[i_node]

        #if (max(mu_scatter_new(1:nu_scatter))>mu_scatter_new(nu_scatter+1) ...
        #| min(mu_scatter_new(1:nu_scatter))<mu_scatter_new(nu_scatter+2))

        #   mu_scatter_new(1:nu_scatter)=(mu_scatter_old(1:nu_scatter)+mu_scatter_new(1:nu_scatter))/2.0;
        #   fprintf(1,'#s#s#e\n','AVERAGED ','MAX CHANGE ',max(abs(mu_scatter_new(1:nu_scatter)-mu_scatter_old(1:nu_scatter))));

        #else
        #    fprintf(1,'#s#s#e\n','NOT AVERAGED ','MAX CHANGE ',max(abs(mu_scatter_new(1:nu_scatter)-mu_scatter_old(1:nu_scatter))));

        #end

        #for i nu_scatter

        #  for i_node=1:nu_scatter
        #    if(abs(delta_mu(i_node))<=1)
        #       delta_mu(i_node)=delta_mu(i_node);
        #    elseif(1<abs(delta_mu(i_node)) & abs(delta_mu(i_node)) <3.7)
        #       delta_mu(i_node)=sign(delta_mu(i_node))*power(abs(delta_mu(i_node)),1/5);
        #    elseif(abs(delta_mu(i_node))>=3.7)
        #       delta_mu(i_node)=sign(delta_mu(i_node))*log(abs(delta_mu(i_node)));
        #    end
        #  end

        #  mu_scatter_new=mu_scatter_new+delta_mu;

        #****************************************************************************************
        #************************************ EVALUATE Iin***************************************
        #****************************************************************************************
        for i_node in np.arange(0, nu_scatter):
            I_dummy1 = np.dot(
                fermi(((mu_scatter_new[i_node] - E) / (k_B * Temp / q)),
                      fermi_flag, -1.0 / 2.0), T_dummy[:, i_node])
            I_dummy2 = 0
            for j_node in np.arange(0, nu_scatter + 2):
                I_dummy2 = I_dummy2 + np.dot(
                    fermi(((mu_scatter_new[j_node] - E) / (k_B * Temp / q)),
                          fermi_flag, -1.0 / 2.0), T_E[j_node, :, i_node])
            Iin[i_node] = I_dummy1 - I_dummy2
        Isc = max(abs(Iin))
        print 'Isc =', Isc

        #****************************************************************************************
        #***********************************END OF EVALUATE Iin**********************************
        #****************************************************************************************

        if Isc >= I_criterion:

            #****************************************************************************************
            #**************************************EVALUATE IMU**************************************
            #****************************************************************************************
            for i_node in np.arange(0, nu_scatter):
                IMU_dummy[i_node, i_node] = np.dot(((fermi(
                    ((mu_scatter_new[i_node] + dmu - E) /
                     (k_B * Temp / q)), fermi_flag, -1.0 / 2.0) - fermi(
                         ((mu_scatter_new[i_node] - dmu - E) /
                          (k_B * Temp / q)), fermi_flag, -1.0 / 2.0)) /
                                                    (2.0 * dmu)),
                                                   T_dummy[:, i_node])
                for j_node in np.arange(0, nu_scatter):
                    IMU[i_node, j_node] = np.dot(((fermi(
                        ((mu_scatter_new[j_node] + dmu - E) /
                         (k_B * Temp / q)), fermi_flag, -1.0 / 2.0) - fermi(
                             ((mu_scatter_new[j_node] - dmu - E) /
                              (k_B * Temp / q)), fermi_flag, -1.0 / 2.0)) /
                                                  (2.0 * dmu)), T_E[j_node, :,
                                                                    i_node])
            IMU = IMU_dummy - IMU

            #****************************************************************************************
            #***********************************END OF EVALUATE IMU**********************************
            #****************************************************************************************
        iiii = iiii + 1
        print 'iiii = ', iiii

        # Copy old vals
        mu_scatter_old = mu_scatter_new

    for i_node in np.arange(0, 2):
        I_dummy1 = np.dot(
            fermi(
                ((mu_scatter_new[i_node + nu_scatter] - E) / (k_B * Temp / q)),
                fermi_flag, -1.0 / 2.0), T_dummy[:, i_node + nu_scatter])
        #print I_dummy1
        #exit()
        I_dummy2 = 0
        for j_node in np.arange(0, nu_scatter + 2):
            I_dummy2 = I_dummy2 + np.dot(
                fermi(((mu_scatter_new[j_node] - E) /
                       (k_B * Temp / q)), fermi_flag, -1.0 / 2.0),
                T_E[j_node, :, i_node + nu_scatter])
        I_tem[i_node] = I_dummy1 - I_dummy2

    Is = I_tem[0]
    print Is
    Id = I_tem[1]
    print Id

    return [Is, Id, Iin, mu_scatter_new]
Example #12
0
def charge(Ne_old, Ec_old, Ne_sub_old, E_sub_old, Nx, Ny, Ntotal, mx, my, mz,
           junction_l, junction_r, div_avd):

    transport_model = transportmodel.value
    fermi_flag = fermiflag1.value
    Vd = Vdc.value
    N_dos = globvars.N_dos

    Lsda = round(Lsd / dx)
    Lg_topa = round(Lg_top / dx)
    Lg_bota = round(Lg_bot / dx)
    t_topa = round(t_top / dy)
    t_bota = round(t_bot / dy)
    t_sia = round(t_si / dy)
    Temp = Te

    #NEGF scattering method parameters

    nu_scatter = globvars.nu_scatter
    Info_scatter_new = globvars.Info_scatter_new
    Info_scatter_old = globvars.Info_scatter_old
    Is = globvars.Is
    Id = globvars.Id

    #######################MODEL 4 related parameters#############################
    eta = 1e-6j
    globvars.eta = 1e-6j
    Ef_tail_low = 0.01
    Ef_tail_up = 0.3
    E_step = criterion_outer / 2.0  #0.5 times criterion_outer
    zeta_self = -(25.0 * 120.0 / (mu_low * 1e4)) * 1.0e-3j  #eV
    decay_fac = 1  #dimensionless
    ########################MODEL 3 related parameters############################
    ########################MODEL 2 related parameters############################
    e_field_limit = 1.0  #in V/m
    ##############################################################################
    ###########################INPUT AND OUTPUT VARIABLES#########################
    ##############################################################################
    # Ne_old is the old electron density
    # 1 column of Ntotal elements
    # Ec_old is the old potential energy profile in eV
    # 1 column of Ntotal elements
    # Te_old is the old electron temperature along the channel
    # 1 column of Nx elements, for charge-sheet-model

    # Ne_sub_old contains 2D electron density on each subband
    # E_sub_old contains the 1D subband energy for all subband
    # considered
    # Te_sub_old contains temperture data of electron on each subband
    # Nx by m, for bulk model

    # Fn_new 1 column of Ntotal elements, dummy varible
    # for Poisson Equation solving
    # Ne_new is the new 3D density in m^-3
    # 1 column of Ntotal elements
    # Ne_sub contains 2D electron density on each subband
    # E_sub contains the 1D subband energy for all subband considered

    # Fn is dummy Fermi energy level used by models 1,4 and 5 for
    # current calculation
    # max_subband is the number of subbands considered
    # t_vall is the number of ladders considered
    #############################################################################

    #########################INITIALIZATION######################################
    Ec_old = np.real(Ec_old.todense())  #1 column of Ntotal elements
    Ec_old = sparse.csr_matrix(Ec_old)
    Ne_old = np.real(Ne_old.todense())  #1 column of Ntotal elements
    #Ne_old = sparse.csr_matrix(Ne_old)
    #Ne_sub_old = zeros(Nx,max_subband,t_vall)
    #E_sub_old = zeros(Nx,max_subband,t_vall)

    Fn_new = np.zeros((Ntotal, 1))  #1 column of Ntotal elements
    Ne_new = np.zeros((Ntotal, 1))  #1 column of Ntotal elements
    Ne_sub = np.zeros((t_vall, Nx, max_subband))
    E_sub = np.zeros((t_vall, Nx, max_subband))

    # MODIFIED BY RAMESH,  JAN 13th 03. Comment out as
    # already initialized in main.m
    # Info_scatter_new = np.zeros(nu_scatter, 4)
    # Info_scatter_new = Info_scatter_old

    # temporarily used variables
    if ox_pnt_flag == 0:
        Np_v = round(t_si / dy) + 1
    elif ox_pnt_flag == 1:
        Np_v = Ny

    Fn = np.zeros((Nx, 1))
    Ns = np.zeros((Nx, 1))
    N_body = np.zeros((Np_v, Nx))
    N_body_sum = np.zeros((Np_v, Nx))
    U_sub = np.zeros((t_vall, Nx, max_subband))
    W_sub = np.zeros((max_subband, t_vall, Np_v, Nx))
    U_bias = np.zeros((Nx, 1))

    ############################################################################
    #THE START OF TRANSPORT EQUATION PART#######################################
    ############################################################################

    ############################################################################
    if transport_model == 1:  # TRANSPORT MODEL 1####################################
        ############################################################################
        # INITIALIZE THE REAL FERMI ENERGY LEVEL AND COMPUTE
        N_row_mid = round((Ntotal - Nx * (t_topa + t_bota + 1)) / Nx / 2.0) - 1
        Nc_start = (Nx * (t_topa + 1)) + N_row_mid * Nx
        Nc_end = (Nx * (t_topa + 1)) + (N_row_mid + 1) * Nx
        U_bias = Ec_old[Nc_start:Nc_end]
        Ez = (h_bar * np.pi / t_si)**2.0 / (2.0 * mz[0] * m_e) / q

        channel_s = junction_l
        channel_e = junction_r
        Fn_slope = (-Vd - (-Vs)) / (channel_e - channel_s)

        for i_node in np.arange(0, Nx):
            if i_node < channel_s:
                Fn[i_node] = -Vs - Ez
            elif i_node >= channel_e - 1:
                Fn[i_node] = -Vd - Ez
            else:
                Fn[i_node] = -Vs - Ez + (i_node - channel_s + 1) * Fn_slope
            if fermi_flag == 1:
                Ns[i_node] = Ncc * np.log(1 + np.exp(
                    (Fn[i_node] - U_bias[i_node]) / (k_B * Temp / q)))
            elif fermi_flag == 0:
                Ns[i_node] = Ncc * np.exp(
                    (Fn[i_node] - U_bias[i_node]) / (k_B * Temp / q))

        for iii_row in np.arange((Nx * (t_topa + 1)) / Nx,
                                 (Ntotal - Nx * t_bota) / Nx - 1):
            for iii_col in np.arange(0, Nx):
                i_node = iii_row * Nx + iii_col
                Ne_new[i_node] = (np.sin(
                    (iii_row + 1 - (Nx * (t_topa + 1)) / Nx) * dy / t_si *
                    np.pi)**2) * Ns[iii_col] * 2.0 / t_si

    #############################################################################
    elif transport_model == 2:  # DRIFT DIFFUSION ********************************
        #############################################################################
        mobility = np.zeros((nu_scatter - 1, 1))
        mobility = (np.diff(Info_scatter_old[:, 3]) +
                    2.0 * Info_scatter_old[0:Nx - 1, 3]) / 2.0

        [U_sub, W_sub] = schred(Ec_old, Nx, Ny, Ntotal, mx, my, mz)

        E_sub = U_sub

        for i_val in np.arange(0, t_vall):
            Nccc = 2 * m_e * np.sqrt(
                mx[i_val] * my[i_val]) * k_B * Temp / (np.pi * h_bar**2)
            for i_sub in np.arange(0, max_subband):
                U_bias = U_sub[i_val, :, i_sub]
                Ns = Ne_sub_old[i_val, :, i_sub]
                if fermi_flag == 1:
                    Ns_con = Nccc * np.log(1 + np.exp((-Vs - U_bias[0]) /
                                                      (k_B * Temp / q)))
                    Nd_con = Nccc * np.log(1 + np.exp((-Vd - U_bias[Nx - 1]) /
                                                      (k_B * Temp / q)))
                elif fermi_flag == 0:
                    Ns_con = Nccc * np.exp(
                        (-Vs - U_bias[0]) / (k_B * Temp / q))
                    Nd_con = Nccc * np.exp(
                        (-Vd - U_bias[Nx - 1]) / (k_B * Temp / q))

                if fermi_flag == 0:
                    fac_deg = np.ones(Nx - 1, 1)
                elif fermi_flag == 1:
                    arg = anti_dummy(Ns / Nccc, 0, fermi_flag)
                    Fn = U_bias + (k_B * Temp / q) * arg
                    zeta_channel = (Fn - U_bias) / (k_B * Temp / q)
                    fac_deg_tem = np.log(1 + np.exp(zeta_channel)) * (
                        1 + np.exp(-zeta_channel))
                    fac_deg_tem[np.where(
                        arg < -5
                    )] = 1  # To ensure could scalability when subbands are empty
                    fac_deg = (np.diff(fac_deg_tem) +
                               2 * fac_deg_tem[0:Nx - 1]) / 2
                V_channel = -U_bias
                E_channel = -np.diff(V_channel) / dx

                #If you want constant mobility uncomment the following line
                #mu_channel=mu_low./(1+(mu_low/Vel_sat*abs(E_channel)).^beta).^(1/beta)

                #If you want doping dependent mobility uncomment the following line
                mu_channel = mobility / (
                    1 +
                    (mobility / Vel_sat * abs(E_channel))**beta)**(1 / beta)
                Coe_1 = np.zeros(Nx - 1)
                Coe_2 = np.zeros(Nx - 1)

                for j in np.arange(0, Nx - 1):
                    if abs(E_channel[j]) <= abs(e_field_limit * fac_deg[j]):
                        Coe_1[j] = -mu_channel[j] * (k_B * Temp /
                                                     q) * fac_deg[j] / dx
                        Coe_2[j] = -Coe_1[j]
                    else:
                        Coe_1[j] = mu_channel[j] * E_channel[j] * 1 / (
                            1 - np.exp(E_channel[j] * dx /
                                       ((k_B * Temp / q) * fac_deg[j])))
                        Coe_2[j] = mu_channel[j] * E_channel[j] * 1 / (
                            1 - np.exp(-E_channel[j] * dx /
                                       ((k_B * Temp / q) * fac_deg[j])))

                AAA = np.diag(-Coe_1[1:Nx - 1] + Coe_2[0:Nx - 2]) - np.diag(
                    Coe_2[1:Nx - 2], 1) + np.diag(Coe_1[1:Nx - 2], -1)
                CCC = np.zeros((Nx - 2, 1))
                CCC[0] = -Coe_1[0] * Ns_con / Ncc
                CCC[Nx - 3] = Coe_2[Nx - 2] * Nd_con / Ncc

                BBB = spsolve(sparse.csr_matrix(AAA), sparse.csr_matrix(CCC))
                #Ne_sub[i_val, :, i_sub] = np.reshape([Ns_con,BBB*Ncc,Nd_con],(Nx,1))
                Ne_sub[i_val, 0, i_sub] = Ns_con
                Ne_sub[i_val, 1:Nx - 1, i_sub] = BBB * Ncc
                Ne_sub[i_val, Nx - 1, i_sub] = Nd_con

                for i_node in np.arange(0, Nx):
                    N_body[:, i_node] = Ne_sub[i_val, i_node,
                                               i_sub] * W_sub[i_sub, i_val, :,
                                                              i_node] / dy

                N_body_sum = N_body_sum + N_body

        Info_scatter_new[:, 2] = Fn

        if ox_pnt_flag == 0:
            #Ne_new = [Ne_old(1:(Nx*(t_topa+1)));...
            #reshape((N_body_sum(2:Np_v-1,:))',...
            #Nx*(Np_v-2),1);...
            #Ne_old((Ntotal-Nx*(t_bota+1)+1):Ntotal)]
            Ne_new[0:Nx * (t_topa + 1)] = Ne_old[0:Nx * (t_topa + 1)]
            Ne_new[Nx * (t_topa + 1):Nx * (t_topa + t_sia)] = np.reshape(
                (N_body_sum[1:Np_v - 1, :]), (1, Nx * (Np_v - 2))).transpose()
            Ne_new[Nx *
                   (t_topa + t_sia):Ntotal] = Ne_old[(Ntotal - Nx *
                                                      (t_bota + 1)):Ntotal]
            Ne_new = np.reshape(Ne_new, (Ntotal, 1))
        elif ox_pnt_flag == 1:
            Ne_new = np.reshape(N_body_sum.transpose(),
                                (1, Ntotal)).transpose()

################################################################################
    elif transport_model == 3:  #BALLISTIC TRANSPORT USING SEMICLASSICAL APPROACH#####
        ################################################################################

        [U_sub, W_sub] = schred(Ec_old, Nx, Ny, Ntotal, mx, my, mz)
        E_sub = U_sub

        for i_val in np.arange(0, t_vall):
            Ne_2d_1 = 2 * (np.sqrt(mx[i_val] * my[i_val]) * m_e * k_B *
                           Temp) / (2.0 * np.pi * h_bar**2)
            Ne_2d_2 = Ne_2d_1 * 2.0 / np.pi**0.5

            for i_sub in np.arange(0, max_subband):
                U_bias = U_sub[i_val, :, i_sub]
                [Ec_peak, i_peak] = np.max(U_bias), np.argmax(U_bias)
                for i_node in np.arange(0, Nx):
                    MEc_peak = (Ec_peak - U_bias[i_node]) / (k_B * Temp / q)
                    zeta_s = (-Vs - U_bias[i_node]) / (k_B * Temp / q)
                    zeta_d = (-Vd - U_bias[i_node]) / (k_B * Temp / q)
                    if zeta_s == zeta_d + 10000:
                        Ne_sub[i_val, i_node, i_sub] = 2 * Ne_2d_1 * fermi(
                            zeta_s, fermi_flag, 0)
                    else:
                        if i_node <= i_peak:
                            Ne_sub[i_val, i_node, i_sub] = Ne_2d_2 * integral(
                                zeta_s, zeta_d, MEc_peak, fermi_flag)
                        elif i_node > i_peak:
                            Ne_sub[i_val, i_node, i_sub] = Ne_2d_2 * integral(
                                zeta_d, zeta_s, MEc_peak, fermi_flag)
                    N_body[:, i_node] = Ne_sub[i_val, i_node,
                                               i_sub] * W_sub[i_sub, i_val, :,
                                                              i_node] / dy
                N_body_sum = N_body_sum + N_body

        if ox_pnt_flag == 0:
            #Ne_new = np.array([Ne_old[0:(Nx*(t_topa+1))], [np.reshape((N_body_sum[1:Np_v-1,:]).transpose(),(1,Nx*(Np_v-2))).transpose()], [Ne_old[(Ntotal-Nx*(t_bota+1)):Ntotal]]])
            #Ne_old = Ne_old.toarray()
            Ne_new[0:Nx * (t_topa + 1)] = Ne_old[0:Nx * (t_topa + 1)]
            Ne_new[Nx * (t_topa + 1):Nx * (t_topa + t_sia)] = np.reshape(
                (N_body_sum[1:Np_v - 1, :]), (1, Nx * (Np_v - 2))).transpose()
            Ne_new[Nx *
                   (t_topa + t_sia):Ntotal] = Ne_old[(Ntotal - Nx *
                                                      (t_bota + 1)):Ntotal]
            Ne_new = np.reshape(Ne_new, (Ntotal, 1))
        elif ox_pnt_flag == 1:
            Ne_new = np.reshape(N_body_sum.transpose(),
                                (1, Ntotal)).transpose()
    ##########################################################################
    elif transport_model == 4:  #BALLISTIC TRANSPORT MODEL USING GREEN FUNCTION APPROACH
        ##########################################################################

        [U_sub, W_sub] = schred(Ec_old, Nx, Ny, Ntotal, mx, my, mz)

        E_sub = U_sub

        #E , E_number are defined outside the loop to remain constant
        # When simulating several valleys and subband so the size of the DOS matrix
        # Remain constant...This maybe more PCU intensive...

        [Ec_peak, i_peak
         ] = np.max(U_sub[t_vall - 1, :,
                          max_subband - 1]), np.argmax(U_sub[t_vall - 1, :,
                                                             max_subband - 1])
        Ec_peak = np.max((-Vs, Ec_peak))
        E_number = round(
            (Ec_peak + Ef_tail_up - U_sub[0, Nx - 1, 0] + Ef_tail_low) /
            E_step) + 2
        print 'E_number = ', E_number
        E = np.linspace((U_sub[0, Nx - 1, 0] - Ef_tail_low),
                        (Ec_peak + Ef_tail_up), E_number)
        delta_E = ((Ec_peak + Ef_tail_up) -
                   (U_sub[0, Nx - 1, 0] - Ef_tail_low)) / (E_number - 1)

        for i_val in np.arange(0, t_vall):
            Ne_2d = 2 * np.sqrt(mx[i_val] * m_e * (k_B * Temp / q) * q /
                                (2 * np.pi**3)) / (h_bar * dx)
            tt = (h_bar**2) / (2 * my[i_val] * m_e * (dx**2) * q)
            tt = float(tt)
            A = tt * ((2 * np.eye(Nx)) - (np.diag(np.ones(Nx - 1), 1)) -
                      (np.diag(np.ones(Nx - 1), -1)))

            for i_sub in np.arange(0, max_subband):
                U_bias = U_sub[i_val, :, i_sub]
                #[Ec_peak,i_peak]=max(U_bias)
                #Ec_peak=max(-Vs,max(U_bias))
                #E_number=round((Ec_peak+Ef_tail_up-U_bias(Nx)+Ef_tail_low)/E_step)+2
                #E=linspace((U_bias(Nx)-Ef_tail_low),(Ec_peak+Ef_tail_up),E_number)
                #delta_E=((Ec_peak+Ef_tail_up)-(U_bias(Nx)-Ef_tail_low))/(E_number-1)
                N_den = np.zeros((Nx, 1))
                B_s = np.zeros((Nx, 1))
                B_d = np.zeros((Nx, 1))
                B_s[0] = 1
                B_d[Nx - 1] = 1
                spB_s = sparse.csr_matrix(B_s)
                spB_d = sparse.csr_matrix(B_d)

                #for k=1:E_number,
                #ee=E(k);ep=ee+eta
                #ck=1-((ep-U_bias(1))/(2*tt));con_s=-tt*exp(i*acos(ck))
                #ck=1-((ep-U_bias(Nx))/(2*tt));con_d=-tt*exp(i*acos(ck))
                #U_eff=U_bias
                #U_eff(1)=U_bias(1)+con_s
                #U_eff(Nx)=U_bias(Nx)+con_d
                #G_inv=sparse((ep*eye(Nx))-A-diag(U_eff))
                #G_s=G_inv\spB_s
                #G_d=G_inv\spB_d
                #f_1=fermi(((-Vs-ee)/(k_B*Temp/q)),fermi_flag,-1/2)
                #f_2=fermi(((-Vd-ee)/(k_B*Temp/q)),fermi_flag,-1/2)
                #N_den=N_den-abs(G_s).^2*imag(con_s)*2*f_1...
                #      -abs(G_d).^2*imag(con_d)*2*f_2
                #N_dos_one(:,k)=-abs(G_s).^2*imag(con_s)-abs(G_d).^2*imag(con_d)
                #end

                [N_den1, Nquad] = myquad(func_energy, E[0], E[E_number - 1],
                                         1e-6, [], tt, U_bias, A, spB_s, spB_d)
                N_den = N_den1 / (E[1] - E[0])

                Ne_sub[i_val, :, i_sub] = (N_den) * Ne_2d * delta_E
                for i_node in np.arange(0, Nx):
                    N_body[:, i_node] = Ne_sub[i_val, i_node,
                                               i_sub] * W_sub[i_sub, i_val, :,
                                                              i_node] / dy

                N_body_sum = N_body_sum + N_body

        if ox_pnt_flag == 0:
            #Ne_new=[Ne_old[1:(Nx*(t_topa+1)));...
            #reshape((N_body_sum(2:Np_v-1,:))',...
            #Nx*(Np_v-2),1);...
            #Ne_old((Ntotal-Nx*(t_bota+1)+1):Ntotal)]
            Ne_new[0:Nx * (t_topa + 1)] = Ne_old[0:Nx * (t_topa + 1)]
            Ne_new[Nx * (t_topa + 1):Nx * (t_topa + t_sia)] = np.reshape(
                (N_body_sum[1:Np_v - 1, :]), (1, Nx * (Np_v - 2))).transpose()
            Ne_new[Nx *
                   (t_topa + t_sia):Ntotal] = Ne_old[(Ntotal - Nx *
                                                      (t_bota + 1)):Ntotal]
            Ne_new = np.reshape(Ne_new, (Ntotal, 1))
        elif ox_pnt_flag == 1:
            Ne_new = np.reshape(N_body_sum.transpose(),
                                (1, Ntotal)).transpose()

        globvars.E = E

    ################################################################################
    elif transport_model == 5:  #SCATTERING MODEL USING GREEN"S FUNCTION METHOD*******
        ################################################################################

        [U_sub, W_sub] = schred(Ec_old, Nx, Ny, Ntotal, mx, my, mz)
        E_sub = U_sub

        U_scatter = np.zeros((Nx, 1))
        mu_scatter_old = np.zeros((nu_scatter + 2, 1))
        mu_scatter_new = np.zeros((nu_scatter + 2, 1))
        delta_mu = np.zeros((nu_scatter + 2, 1))
        i_scatter = np.zeros((nu_scatter + 2, 1))
        BB_dummy = np.eye(Nx)
        Iin = np.zeros((nu_scatter, 1))

        #comment the two following line for constant mobility
        #zeta_self=zeros(nu_scatter,1);
        #decay_fac=1;%dimensionless

        for i_s in np.arange(0, nu_scatter):
            i_scatter[i_s] = (Info_scatter_old[i_s, 1])

            # CHANGED BY RAMESH TO TAKE OLD GUESS
            mu_scatter_old[i_s] = (Info_scatter_new[i_s, 2])

        mu_scatter_old[nu_scatter] = -Vs
        mu_scatter_old[nu_scatter + 1] = -Vd
        i_scatter[nu_scatter] = 0
        i_scatter[nu_scatter + 1] = Nx - 1
        BB = sparse.lil_matrix((int(Nx), int(nu_scatter + 2)), dtype=float)
        i_scatter = i_scatter.astype(int)
        i_scatter = np.squeeze(i_scatter)
        #mu_scatter_old = mu_scatter_old.astype(int)
        mu_scatter_old = np.squeeze(mu_scatter_old)

        BB[:, 0:int(nu_scatter)] = BB_dummy[:, i_scatter[0:nu_scatter]]
        BB[:, int(nu_scatter):int(nu_scatter) + 1] = BB_dummy[:, 0:1]
        for ind in np.arange(0, Nx):
            if BB_dummy[ind, Nx - 1]:
                BB[ind, int(nu_scatter) + 1] = BB_dummy[ind, Nx - 1]
        BB = BB.tocsr()

        Ec_peak = np.max((-Vs, np.max(U_sub[0, :, 0])))
        Ec_bottom = U_sub[0, Nx - 1, 0]
        E_number = round(
            (Ec_peak + Ef_tail_up - Ec_bottom + Ef_tail_low) / E_step) + 2
        E = np.linspace((Ec_bottom - Ef_tail_low), (Ec_peak + Ef_tail_up),
                        E_number)
        delta_E = ((Ec_peak + Ef_tail_up) -
                   (Ec_bottom - Ef_tail_low)) / (E_number - 1)

        GG = sparse.csr_matrix((Nx, nu_scatter + 2))
        T_E = np.zeros((nu_scatter + 2, E_number, nu_scatter + 2))

        # comment the next line and uncomment the previous line for constant mobility

        E_self = np.ones(
            (E_number,
             nu_scatter + 2))  #correction on March 14th to include mobility
        E_self = E_self + 0j
        U_tem = np.zeros((nu_scatter, 1))

        # end of initialization

        # ADDED BY RAMESH JAN 13th 03.
        # We need to compute a mean free path to set
        # zeta_self based on the Fermi-level of the
        # probe, subband energy and grid spacing.
        sum1 = np.zeros((nu_scatter, 1))
        sum2 = np.zeros((nu_scatter, 1))
        lambda1 = np.zeros((nu_scatter, 1))
        for i_val in np.arange(0, t_vall):
            for i_sub in np.arange(0, max_subband):
                for i_s in np.arange(0, nu_scatter):
                    factor = np.exp((Info_scatter_new[i_s, 2] -
                                     U_sub[i_val, i_scatter[i_s], i_sub]) /
                                    (k_B * Temp / q))
                    sum1[i_s] = sum1[i_s] + my[i_val] * m_e * np.log(1 +
                                                                     factor)
                    # Prevent divide by zero
                    factor1 = np.log(1 + factor)
                    if (factor1 <= 1e-20):
                        factor1 = factor
                    factor2 = factor / (factor1 * (1 + factor)) * fermi(
                        ((Info_scatter_new[i_s, 2] -
                          U_sub[i_val, i_scatter[i_s], i_sub]) /
                         (k_B * Temp / q)), fermi_flag, 1.0 / 2.0)
                    sum2[i_s] = sum2[i_s] + my[i_val] * m_e * np.sqrt(
                        2 * k_B * Temp / (np.pi * mx[i_val] * m_e)) * factor2

        for i_s in np.arange(0, nu_scatter):
            lambda1[i_s] = 2 * k_B * Temp / q * Info_scatter_old[
                i_s, 3] * sum1[i_s] / sum2[i_s]

        lambda1 = np.squeeze(lambda1)

        ttot = 0
        scattot = 0
        ktot = 0
        stot = 0
        k2tot = 0
        soltot = 0
        asstot = 0
        N_dos = np.zeros((Nx, E_number))

        for i_val in np.arange(0, t_vall):
            t1 = time.time()
            Ie_2d = 2 * q**2 / (np.pi**2 * h_bar**2) * np.sqrt(
                my[i_val] * m_e * (k_B * Temp / q) * q * np.pi / 2.0)
            tt = (h_bar**2) / (2 * mx[i_val] * m_e * (dx**2) * q)
            tt = float(tt)
            A = tt * ((2 * np.eye(Nx)) - (np.diag(np.ones(Nx - 1), 1)) -
                      (np.diag(np.ones(Nx - 1), -1)))
            t2 = time.time()
            ttot += (t2 - t1)
            for i_sub in np.arange(0, max_subband):
                s1 = time.time()
                U_bias = U_sub[i_val, :, i_sub]
                U_tem = U_bias[i_scatter[0:nu_scatter]]
                s2 = time.time()
                stot += (s2 - s1)
                for k in np.arange(0, E_number):
                    k1 = time.time()
                    ee = E[k]
                    ep = ee + eta
                    ck = 1 - ((ep - U_bias[0]) / (2 * tt))
                    con_s = -tt * np.exp(1j * np.arccos(ck))
                    ck = 1 - ((ep - U_bias[Nx - 1]) / (2 * tt))
                    con_d = -tt * np.exp(1j * np.arccos(ck))
                    k2 = time.time()
                    ktot += (k2 - k1)
                    # ADDED BY RAMESH JAN 13 03.
                    scat1 = time.time()
                    for i_s in np.arange(0, nu_scatter):
                        elutot = ee - (A[i_scatter[i_s], i_scatter[i_s]] +
                                       U_bias[i_scatter[i_s]])
                        g1 = (elutot + cmath.sqrt(elutot**2 - 4.0 * tt**2)) / (
                            2 * tt**2)
                        g2 = (elutot - cmath.sqrt(elutot**2 - 4.0 * tt**2)) / (
                            2 * tt**2)
                        g3 = (np.imag(g2) <= 0) * g2 + (np.imag(g1 <= 0)) * g1
                        E_self[k, i_s] = 1j * np.imag(
                            g3 * 2 * dx * tt**2 / lambda1[i_s])

                    scat2 = time.time()
                    scattot += (scat2 - scat1)
                    k3 = time.time()
                    E_self[k, nu_scatter] = con_s
                    E_self[k, nu_scatter + 1] = con_d
                    U_scatter = U_scatter + 0j
                    U_scatter = np.squeeze(U_scatter)
                    U_scatter[i_scatter] = (E_self[k, :])

                    U_eff = U_bias + U_scatter
                    #print U_eff
                    G_inv = sparse.csr_matrix((ep * np.eye(Nx)) - A -
                                              np.diag(U_eff))
                    GG = np.zeros((Nx, nu_scatter + 2))
                    GG = GG + 0j
                    k4 = time.time()
                    k2tot += (k4 - k3)
                    sol1 = time.time()
                    gin = np.linalg.inv(G_inv.todense())
                    gin = sparse.csr_matrix(gin)
                    GG = gin * BB
                    GG = GG.toarray()
                    sol2 = time.time()
                    soltot += (sol2 - sol1)
                    #print sparse.csr_matrix(np.diag(np.imag(E_self[k,:]).conj().T))
                    #print np.shape(GG[i_scatter,:])
                    #print delta_E
                    #print abs(GG[i_scatter,:])**2
                    #print sparse.csr_matrix(4*int(Ie_2d)*delta_E*np.dot(np.diag(np.imag(E_self[k,:]).conj().T),abs(GG[i_scatter,:])**2))
                    T_E[:, k, :] = 4 * int(Ie_2d) * delta_E * np.dot(
                        (np.dot(np.diag(np.imag(E_self[k, :]).conj().T),
                                abs(GG[i_scatter, :])**2)),
                        np.diag(np.imag(E_self[k, :]).conj().T)) + np.squeeze(
                            T_E[:, k, :])
                    #print sparse.csr_matrix(T_E[:,k,:])
                    #print E_self[k,:]
                    #print GG[i_scatter,:]
                    #print k
                    sol3 = time.time()
                    asstot += (sol3 - sol2)
        #print ttot, stot, ktot, scattot, k2tot, soltot, asstot

        #calculate current, and search for mu_scatter
        #based on current continuity

        [Is, Id, Iin, mu_scatter_new] = current_mat(mu_scatter_old, T_E, E)
        #print 'sad'
        #print Is
        #print Id

        #end of mu_scatter search

        #Calculate charge density
        for i_val in np.arange(0, t_vall):
            Ne_2d = 2.0 * np.sqrt(my[i_val] * m_e * (k_B * Temp / q) * q /
                                  (2.0 * np.pi**3)) / (h_bar * dx)
            tt = (h_bar**2) / (2.0 * mx[i_val] * m_e * (dx**2) * q)
            tt = float(tt)
            A = tt * ((2.0 * np.eye(Nx)) - (np.diag(np.ones(Nx - 1), 1)) -
                      (np.diag(np.ones(Nx - 1), -1)))

            for i_sub in np.arange(0, max_subband):
                U_bias = U_sub[i_val, :, i_sub]
                U_tem = U_bias[(i_scatter[0:nu_scatter])]

                for k in np.arange(0, E_number):

                    # All this needs to be recomputed for multiple bands
                    #--------------------------------------------------
                    ee = E[k]
                    ep = ee + eta
                    ck = 1 - ((ep - U_bias[0]) / (2 * tt))
                    con_s = -tt * np.exp(1j * np.arccos(ck))
                    ck = 1 - ((ep - U_bias[Nx - 1]) / (2 * tt))
                    con_d = -tt * np.exp(1j * np.arccos(ck))

                    # ADDED BY RAMESH JAN 13 03.
                    for i_s in np.arange(0, nu_scatter):
                        elutot = ee - (A[i_scatter[i_s], i_scatter[i_s]] +
                                       U_bias[i_scatter[i_s]])
                        g1 = (elutot +
                              cmath.sqrt(elutot**2 - 4 * tt**2)) / (2 * tt**2)
                        g2 = (elutot -
                              cmath.sqrt(elutot**2 - 4 * tt**2)) / (2 * tt**2)
                        g3 = (np.imag(g2) <= 0) * g2 + (np.imag(g1 <= 0)) * g1
                        E_self[k, i_s] = 1j * np.imag(
                            g3 * 2 * dx * tt**2 / lambda1[i_s])

                    E_self = E_self + 0j
                    E_self[k, nu_scatter] = con_s
                    E_self[k, nu_scatter + 1] = con_d
                    U_scatter[i_scatter] = (E_self[k, :]).transpose()

                    U_eff = U_bias + U_scatter
                    G_inv = sparse.csr_matrix((ep * np.eye(Nx)) - A -
                                              np.diag(U_eff))
                    gin = np.linalg.inv(G_inv.todense())
                    gin = sparse.csr_matrix(gin)
                    GG = gin * BB
                    GG = GG.toarray()
                    Ne_sub[i_val, :, i_sub] = Ne_sub[i_val, :, i_sub] - np.dot(
                        2 * Ne_2d * delta_E * abs(GG)**2,
                        (np.imag(E_self[k, :]).conj().T) * fermi(
                            ((mu_scatter_new - ee) /
                             (k_B * Temp / q)), fermi_flag, -1.0 / 2.0))

                    GGG = np.zeros((Nx, Nx))
                    GGG = GGG + 0j
                    GGG[:, 0] = GG[:, Nx - 2]
                    GGG[:, Nx - 1] = GG[:, Nx - 1]
                    GGG[0:Nx, 1:Nx - 1] = GG[0:Nx, 0:Nx - 2]
                    N_dos[:, k] = -2 * np.imag(np.diag(GGG))

                for i_node in np.arange(0, Nx):
                    N_body[:, i_node] = Ne_sub[i_val, i_node,
                                               i_sub] * W_sub[i_sub, i_val, :,
                                                              i_node] / dy

                N_body_sum = N_body_sum + N_body

        Info_scatter_new[:, 0] = np.squeeze(Iin)
        Info_scatter_new[0, 0] = Is
        Info_scatter_new[:, 2] = mu_scatter_new[0:nu_scatter]

        if ox_pnt_flag == 0:
            #Ne_new=[Ne_old(1:(Nx*(t_topa+1)));...
            #reshape((N_body_sum(2:Np_v-1,:))',...
            #Nx*(Np_v-2),1);...
            #Ne_old((Ntotal-Nx*(t_bota+1)+1):Ntotal)]
            Ne_new[0:Nx * (t_topa + 1)] = Ne_old[0:Nx * (t_topa + 1)]
            Ne_new[Nx * (t_topa + 1):Nx * (t_topa + t_sia)] = np.reshape(
                (N_body_sum[1:Np_v - 1, :]), (1, Nx * (Np_v - 2))).transpose()
            Ne_new[Nx *
                   (t_topa + t_sia):Ntotal] = Ne_old[(Ntotal - Nx *
                                                      (t_bota + 1)):Ntotal]
            Ne_new = np.reshape(Ne_new, (Ntotal, 1))
        elif ox_pnt_flag == 1:
            Ne_new = np.reshape(N_body_sum.transpose(),
                                (1, Ntotal)).transpose()

        globvars.E = E
        globvars.Info_scatter_new = Info_scatter_new
        globvars.Info_scatter_old = Info_scatter_old
        globvars.Is = Is
        globvars.Id = Id
        globvars.N_dos = N_dos

    ################################################################################
    ######################START OF VARIABLE CHANGE PART#############################
    ################################################################################

    if ox_pnt_flag == 0:  # No electron penetration into oxide
        for iii_row in np.arange((Nx * (t_topa + 1)) / Nx,
                                 (Ntotal - Nx * t_bota) / Nx - 1):
            for iii_col in np.arange(0, Nx):
                i_node = iii_row * Nx + iii_col
                Fn_new[i_node] = anti_dummy(
                    Ne_new[i_node] / Nc, dummy_flag,
                    fermi_flag) * (k_B * Temp / q) + Ec_old[i_node]
    elif ox_pnt_flag == 1:  # assuming electron penetration into oxide
        Fn_new = anti_dummy((Ne_new + div_avd) / Nc, dummy_flag,
                            fermi_flag) * (k_B * Temp / q) + Ec_old

    #############################################################################
    #######################END OF VARIABLE CHANGE PART###########################
    #############################################################################

    #############################################################################
    ########################END OF FUNCTION CHARGE.M#############################
    #############################################################################

    return [Fn_new, Ne_new, Ne_sub, E_sub]
Example #13
0
def current(Ne, Ec, Ne_sub, E_sub, Nx, Ny, Ntotal, mx, my, mz):
    Temp = Te
    transport_model = transportmodel.value
    Vd = Vdc.value
    fermi_flag = fermiflag1.value
    E = globvars.E
    nu_scatter = globvars.nu_scatter
    Info_scatter_old = globvars.Info_scatter_old

    #### MODEL 2 related parameters

    eta = 1e-6j
    Ef_tail_low = 0.01
    Ef_tail_up = 0.3
    E_step = criterion_outer / 2.0  # 0.5 times criterion_outer

    ####MODEL 4 related parameters
    e_field_limit = 1.0  # in V/m
    ####MODEL 5 related parameters

    ###########################################################
    #	INPUT AND OUTPUT VARIABLES
    ###########################################################
    #Info_scatter_old contains all information of scatters
    #2-dim matrix, dim_2:current,index, and Fermi energy, low field mobility
    #Ne_old is the old electron density
    #1 column of Ntotal elements
    #Ec_old is the old potential energy profile in eV
    #1 column of Ntotal elements
    #Te_old is the old electron temperature along the channel
    #1 column of Nx elements, for charge-sheet-model
    #Ne_sub contains 2D electron density on each subband
    #E_sub contains the 1D subband energy for all subband
    #considered
    #Te_sub_old contains the 1D electron temperature for all subband
    #considered, for bulk model

    #Ne is the 3D electron density profile in the entire device
    #1 column matrix of Ntotal elements
    #Ec is the conduction band edge profile in the entire device
    #1 column matrix of Ntotal elements
    #Te_old is 1 column matrix of Nx elements for electron temperature
    #, for charge-sheet-model

    #Ie is 1 column matrix of Nx elements for current density
    #A/m
    #Ie_sub contains currents carried in all subbands.
    ###########################################################

    ###########################################################
    #	TEMPORARY VARIABLES
    ###########################################################
    #Ec_channel is the given potential energy profile
    #along the channel
    #Fn_channel is the given quasi Fermi level along the channel
    #Ne_channel is the given electron 2D density along the channel
    #max_subband is the number of subbands considered
    #t_vall is the number of valleyes considered

    #########################INITIALIZATION#######################################
    Ie = np.zeros((Nx, 1))
    Ie_sub = np.zeros((t_vall, Nx, max_subband))
    Te_sub = np.zeros((t_vall, Nx, max_subband))
    Fn_sub = np.zeros((t_vall, Nx, max_subband))
    #E_sub = np.zeros((Nx,max_subband,t_vall))
    #Ne_sub = np.zeros((Nx,max_subband,t_vall))

    #Info_scatter_new = np.zeros((nu_scatter,4))
    #Info_scatter_new = Info_scatter_old
    Ec_channel = np.zeros((Nx, 1))
    Fn_channel = np.zeros((Nx, 1))
    Ne_channel = np.zeros((Nx, 1))
    #Fn_new = np.zeros((Ntotal,1))
    #Ne_new = np.zeros((Ntotal,1))

    #temporarily used variables
    if ox_pnt_flag == 0:
        Np_v = round(t_si / dy) + 1
    elif ox_pnt_flag == 1:
        Np_v = Ny

    Ns = np.zeros((Nx, 1))
    N_body = np.zeros((Np_v, Nx))
    N_body_sum = np.zeros((Np_v, Nx))
    U_sub = np.zeros((Nx, max_subband, t_vall))
    W_sub = np.zeros((Np_v, Nx, max_subband, t_vall))
    U_bias = np.zeros((Nx, 1))

    ##############################################################################
    #THE START OF TRANSPORT EQUATION PART#########################################
    ##############################################################################

    ##############################################################################
    if transport_model == 1:  #TRANSPORT MODEL 1######################################
        print 'entered tm1'
    ##############################################################################

    #*****************************************************************************
    elif transport_model == 2:  #TRANSPORT MODEL 2 DD*******************************
        #*****************************************************************************
        U_bias = np.zeros((Nx, 1))
        Ns = np.zeros((Nx, 1))
        Ie_tem = np.zeros((Nx, 1))
        mobility = np.zeros((nu_scatter - 1, 1))
        mobility = (np.diff(Info_scatter_old[:, 3]) +
                    2 * Info_scatter_old[0:Nx - 1, 3]) / 2.0

        for i_val in np.arange(0, t_vall):
            Nccc = 2 * m_e * np.sqrt(
                mx[i_val] * my[i_val]) * k_B * Temp / (np.pi * h_bar**2)

            for i_sub in np.arange(max_subband):
                U_bias = E_sub[i_val, :, i_sub]
                Ns = Ne_sub[i_val, :, i_sub]

                if fermi_flag == 0:
                    fac_deg = np.ones(Nx - 1)
                elif fermi_flag == 1:
                    Fn_channel = U_bias + (k_B * Temp / q) * anti_dummy(
                        Ns / Nccc, 0, fermi_flag)
                    zeta_channel = (Fn_channel - U_bias) / (k_B * Temp / q)
                    fac_deg_tem = np.log(1 + np.exp(zeta_channel)) * (
                        1 + np.exp(-zeta_channel))
                    fac_deg = (np.diff(fac_deg_tem) +
                               2 * fac_deg_tem[0:Nx - 1]) / 2
                V_channel = -U_bias
                E_channel = -np.diff(V_channel) / dx
                mu_channel = mobility / (
                    1 +
                    (mobility / Vel_sat * abs(E_channel))**beta)**(1 / beta)

                Coe_1 = np.zeros(Nx - 1)
                Coe_2 = np.zeros(Nx - 1)

                for j in np.arange(0, Nx - 1):
                    if abs(E_channel[j]) <= abs(e_field_limit * fac_deg[j]):
                        Coe_1[j] = -mu_channel[j] * (k_B * Temp /
                                                     q) * fac_deg[j] / dx
                        Coe_2[j] = -Coe_1[j]
                    else:
                        Coe_1[j] = mu_channel[j] * E_channel[j] * 1 / (
                            1 - np.exp(E_channel[j] * dx /
                                       ((k_B * Temp / q) * fac_deg[j])))
                        Coe_2[j] = mu_channel[j] * E_channel[j] * 1 / (
                            1 - np.exp(-E_channel[j] * dx /
                                       ((k_B * Temp / q) * fac_deg[j])))
                    Ie_tem[j] = -q * (Ns[j] * Coe_1[j] + Ns[j + 1] * Coe_2[j])

                Ie_tem[Nx - 1] = Ie_tem[Nx - 2]
                Ie_sub[i_val, :, i_sub] = np.squeeze(Ie_tem)
                Fn_sub[i_val, :, i_sub] = Fn_channel
                Ie = Ie + Ie_tem

    ###########################################################################
    elif transport_model == 3:  #BALLISTIC TRANSPORT USING SEMICLASSICAL APPROACH
        ###########################################################################
        U_bias = np.zeros((Nx, 1))

        for i_val in np.arange(0, t_vall):
            Ie_2d = 2.0 * q / h_bar**2 * np.sqrt(mx[i_val] * m_e / 2.0) * (
                (k_B * Temp / q) * q / np.pi)**(3.0 / 2.0)

            for i_sub in np.arange(0, max_subband):
                U_bias = E_sub[i_val, :, i_sub]
                Ec_peak = max(U_bias)

                Ie_tem = 0
                Ie_tem = Ie_2d * (fermi(
                    ((-Vs - Ec_peak) /
                     (k_B * Temp / q)), fermi_flag, 1.0 / 2.0) - fermi(
                         ((-Vd - Ec_peak) /
                          (k_B * Temp / q)), fermi_flag, 1.0 / 2.0))
                Ie_sub[i_val, :, i_sub] = Ie_tem * np.ones(Nx)
                Ie = Ie + Ie_tem * np.ones(Nx)

    ##################################################################################
    elif transport_model == 4:  #BALLISTIC TRANSPORT MODEL USING GREEN FUNCTION APPROACH#
        ##################################################################################

        U_bias = np.zeros((Nx, 1))

        Ec_peak = np.max((-Vs, np.max(E_sub[t_vall - 1, :, max_subband - 1])))
        E_number = round(
            (Ec_peak + Ef_tail_up - E_sub[0, Nx - 1, 0] + Ef_tail_low) /
            E_step) + 2
        E = np.linspace((E_sub[0, Nx - 1, 0] - Ef_tail_low),
                        (Ec_peak + Ef_tail_up), E_number)
        delta_E = ((Ec_peak + Ef_tail_up) -
                   (E_sub[0, Nx - 1, 0] - Ef_tail_low)) / (E_number - 1)

        N_dos_one = np.zeros((Nx, E_number))
        N_dos = np.zeros((Nx, E_number))

        #used to plot the transmission coefficient with several valleys
        Trans_sub = np.zeros((E_number, 1))
        Trans = np.zeros((E_number, 1))

        for i_val in np.arange(0, t_vall):
            Ne_2d = 2 * np.sqrt(mx[i_val] * m_e * (k_B * Temp / q) * q /
                                (2 * np.pi**3)) / (h_bar * dx)
            Ie_2d = 2 * q**2 / (np.pi**2 * h_bar**2) * np.sqrt(
                mx[i_val] * m_e * (k_B * Temp / q) * q * np.pi / 2)
            tt = (h_bar**2) / (2 * my[i_val] * m_e * (dx**2) * q)
            tt = float(tt)
            A = tt * ((2 * np.eye(Nx)) - (np.diag(np.ones(Nx - 1), 1)) -
                      (np.diag(np.ones(Nx - 1), -1)))

            for i_sub in np.arange(0, max_subband):
                U_bias = E_sub[i_val, :, i_sub]
                #Ec_peak = max(-Vs,max(U_bias))
                #E_number = round((Ec_peak+Ef_tail_up-U_bias(Nx)+Ef_tail_low)/E_step)+2
                #E = np.linspace((U_bias(Nx)-Ef_tail_low),(Ec_peak+Ef_tail_up),E_number)
                #delta_E = ((Ec_peak+Ef_tail_up)-(U_bias(Nx)-Ef_tail_low))/(E_number-1)

                B_d = np.zeros((Nx, 1))
                B_d[Nx - 1] = 1
                spB_d = sparse.csr_matrix(B_d)
                B_s = np.zeros((Nx, 1))
                B_s[0] = 1
                spB_s = sparse.csr_matrix(B_s)

                Ie_tem = 0
                for k in np.arange(0, E_number):
                    ee = E[k]
                    ep = ee + eta
                    ck = 1 - ((ep - U_bias[0]) / (2 * tt))
                    con_s = -tt * np.exp(1j * np.arccos(ck))
                    ck = 1 - ((ep - U_bias[Nx - 1]) / (2 * tt))
                    con_d = -tt * np.exp(1j * np.arccos(ck))
                    U_eff = U_bias
                    U_eff = U_eff + 0j
                    U_eff[0] = U_bias[0] + con_s
                    U_eff[Nx - 1] = U_bias[Nx - 1] + con_d
                    G_inv = sparse.csr_matrix((ep * np.eye(Nx)) - A -
                                              np.diag(U_eff))
                    G_s = spsolve(G_inv, spB_s)
                    G_d = spsolve(G_inv, spB_d)
                    f_1 = fermi(((-Vs - ee) / (k_B * Temp / q)), fermi_flag,
                                -1.0 / 2.0)
                    f_2 = fermi(((-Vd - ee) / (k_B * Temp / q)), fermi_flag,
                                -1.0 / 2.0)
                    Ie_tem = Ie_tem + abs(G_d[0])**2 * np.imag(
                        con_s) * np.imag(con_d) * 4 * (f_1 - f_2)
                    Trans[k] = abs(
                        G_d[0])**2 * np.imag(con_s) * np.imag(con_d) * 4
                    N_dos_one[:, k] = -abs(G_s)**2 * np.imag(con_s) - abs(
                        G_d)**2 * np.imag(con_d)

                N_dos = N_dos + Ne_2d * N_dos_one

                Ie_sub[i_val, :,
                       i_sub] = Ie_2d * delta_E * Ie_tem * np.ones(Nx)
                Ie = Ie + Ie_2d * delta_E * Ie_tem * np.ones(Nx)
                Trans_sub = Trans_sub + Trans

        Trans = Trans_sub
        globvars.Trans = Trans
        globvars.N_dos = N_dos

    return [Ie, Ie_sub, Te_sub, Fn_sub]
Example #14
0
def charge(Ne_old,Ec_old,Ne_sub_old,E_sub_old, Nx, Ny, Ntotal, mx, my, mz, junction_l, junction_r, div_avd):

    transport_model = transportmodel.value
    fermi_flag = fermiflag1.value
    Vd = Vdc.value
    N_dos = globvars.N_dos

    Lsda=round(Lsd/dx)
    Lg_topa=round(Lg_top/dx)
    Lg_bota=round(Lg_bot/dx)
    t_topa=round(t_top/dy)
    t_bota=round(t_bot/dy)
    t_sia=round(t_si/dy)
    Temp = Te

    #NEGF scattering method parameters

    nu_scatter = globvars.nu_scatter
    Info_scatter_new  = globvars.Info_scatter_new
    Info_scatter_old = globvars.Info_scatter_old
    Is = globvars.Is
    Id = globvars.Id

    #######################MODEL 4 related parameters#############################
    eta = 1e-6j
    globvars.eta = 1e-6j
    Ef_tail_low = 0.01
    Ef_tail_up = 0.3
    E_step = criterion_outer/2.0 #0.5 times criterion_outer
    zeta_self = -(25.0*120.0/(mu_low*1e4))*1.0e-3j #eV
    decay_fac = 1 #dimensionless
    ########################MODEL 3 related parameters############################
    ########################MODEL 2 related parameters############################
    e_field_limit = 1.0 #in V/m
    ##############################################################################
    ###########################INPUT AND OUTPUT VARIABLES#########################
    ##############################################################################
    # Ne_old is the old electron density
    # 1 column of Ntotal elements
    # Ec_old is the old potential energy profile in eV
    # 1 column of Ntotal elements
    # Te_old is the old electron temperature along the channel
    # 1 column of Nx elements, for charge-sheet-model

    # Ne_sub_old contains 2D electron density on each subband
    # E_sub_old contains the 1D subband energy for all subband
    # considered
    # Te_sub_old contains temperture data of electron on each subband
    # Nx by m, for bulk model

    # Fn_new 1 column of Ntotal elements, dummy varible
    # for Poisson Equation solving
    # Ne_new is the new 3D density in m^-3
    # 1 column of Ntotal elements
    # Ne_sub contains 2D electron density on each subband
    # E_sub contains the 1D subband energy for all subband considered

    # Fn is dummy Fermi energy level used by models 1,4 and 5 for
    # current calculation
    # max_subband is the number of subbands considered
    # t_vall is the number of ladders considered
    #############################################################################

    #########################INITIALIZATION######################################
    Ec_old = np.real(Ec_old.todense())#1 column of Ntotal elements
    Ec_old = sparse.csr_matrix(Ec_old)
    Ne_old = np.real(Ne_old.todense()) #1 column of Ntotal elements
    #Ne_old = sparse.csr_matrix(Ne_old)
    #Ne_sub_old = zeros(Nx,max_subband,t_vall)
    #E_sub_old = zeros(Nx,max_subband,t_vall)

    Fn_new = np.zeros((Ntotal, 1)) #1 column of Ntotal elements
    Ne_new = np.zeros((Ntotal, 1)) #1 column of Ntotal elements
    Ne_sub = np.zeros((t_vall, Nx, max_subband))
    E_sub = np.zeros((t_vall, Nx, max_subband))

    # MODIFIED BY RAMESH,  JAN 13th 03. Comment out as
    # already initialized in main.m
    # Info_scatter_new = np.zeros(nu_scatter, 4)
    # Info_scatter_new = Info_scatter_old

    # temporarily used variables
    if ox_pnt_flag == 0:
        Np_v = round(t_si/dy)+1
    elif ox_pnt_flag == 1:
        Np_v = Ny


    Fn = np.zeros((Nx, 1))
    Ns = np.zeros((Nx, 1))
    N_body = np.zeros((Np_v, Nx))
    N_body_sum = np.zeros((Np_v, Nx))
    U_sub = np.zeros((t_vall, Nx, max_subband))
    W_sub = np.zeros((max_subband, t_vall, Np_v, Nx))
    U_bias = np.zeros((Nx, 1))

    ############################################################################
    #THE START OF TRANSPORT EQUATION PART#######################################
    ############################################################################

    ############################################################################
    if transport_model == 1:  # TRANSPORT MODEL 1####################################
    ############################################################################
    # INITIALIZE THE REAL FERMI ENERGY LEVEL AND COMPUTE
        N_row_mid = round((Ntotal-Nx*(t_topa+t_bota+1))/Nx/2.0)-1
        Nc_start = (Nx*(t_topa+1))+N_row_mid*Nx
        Nc_end=(Nx*(t_topa+1))+(N_row_mid+1)*Nx
        U_bias = Ec_old[Nc_start:Nc_end]
        Ez = (h_bar*np.pi/t_si)**2.0/(2.0*mz[0]*m_e)/q



        channel_s = junction_l
        channel_e = junction_r
        Fn_slope = (-Vd-(-Vs))/(channel_e-channel_s)

        for i_node in np.arange(0,Nx):
            if i_node < channel_s:
                Fn[i_node] = -Vs-Ez
            elif i_node >= channel_e - 1:
                Fn[i_node] = -Vd-Ez
            else:
                Fn[i_node] = -Vs-Ez+(i_node-channel_s + 1)*Fn_slope
            if fermi_flag == 1:
                Ns[i_node] = Ncc*np.log(1+np.exp((Fn[i_node]-U_bias[i_node])/(k_B*Temp/q)))
            elif fermi_flag == 0:
                Ns[i_node] = Ncc*np.exp((Fn[i_node]-U_bias[i_node])/(k_B*Temp/q))




        for iii_row in np.arange((Nx*(t_topa+1))/Nx, (Ntotal-Nx*t_bota)/Nx-1):
            for iii_col in np.arange(0, Nx):
                i_node = iii_row*Nx+iii_col
                Ne_new[i_node] = (np.sin((iii_row+1-(Nx*(t_topa+1))/Nx) * dy/t_si*np.pi)**2) * Ns[iii_col]*2.0/t_si


    #############################################################################
    elif transport_model==2: # DRIFT DIFFUSION ********************************
    #############################################################################
        mobility = np.zeros((nu_scatter-1,1))
        mobility = (np.diff(Info_scatter_old[:, 3]) + 2.0*Info_scatter_old[0:Nx-1,3])/2.0

        [U_sub, W_sub]=schred(Ec_old, Nx, Ny, Ntotal, mx, my, mz)

        E_sub=U_sub

        for i_val in np.arange(0, t_vall):
            Nccc = 2*m_e*np.sqrt(mx[i_val]*my[i_val])*k_B*Temp/(np.pi*h_bar**2)
            for i_sub in np.arange(0, max_subband):
                U_bias = U_sub[i_val, :,i_sub]
                Ns = Ne_sub_old[i_val, :,i_sub]
                if fermi_flag == 1:
                    Ns_con = Nccc*np.log(1+np.exp((-Vs-U_bias[0])/(k_B*Temp/q)))
                    Nd_con = Nccc*np.log(1+np.exp((-Vd-U_bias[Nx-1])/(k_B*Temp/q)))
                elif fermi_flag == 0:
                    Ns_con = Nccc*np.exp((-Vs-U_bias[0])/(k_B*Temp/q))
                    Nd_con = Nccc*np.exp((-Vd-U_bias[Nx-1])/(k_B*Temp/q))

                if fermi_flag == 0:
                    fac_deg = np.ones(Nx-1,1)
                elif fermi_flag == 1:
                    arg = anti_dummy(Ns/Nccc,0,fermi_flag)
                    Fn = U_bias+(k_B*Temp/q)*arg
                    zeta_channel = (Fn-U_bias)/(k_B*Temp/q)
                    fac_deg_tem = np.log(1+np.exp(zeta_channel))*(1+np.exp(-zeta_channel))
                    fac_deg_tem[np.where(arg < -5)]=1 # To ensure could scalability when subbands are empty
                    fac_deg=(np.diff(fac_deg_tem)+2*fac_deg_tem[0:Nx-1])/2
                V_channel=-U_bias
                E_channel=-np.diff(V_channel)/dx

                #If you want constant mobility uncomment the following line
                #mu_channel=mu_low./(1+(mu_low/Vel_sat*abs(E_channel)).^beta).^(1/beta)

                #If you want doping dependent mobility uncomment the following line
                mu_channel=mobility/(1+(mobility/Vel_sat*abs(E_channel))**beta)**(1/beta)
                Coe_1 = np.zeros(Nx-1)
                Coe_2 = np.zeros(Nx-1)

                for j in np.arange(0,Nx-1):
                    if abs(E_channel[j]) <= abs(e_field_limit*fac_deg[j]):
                        Coe_1[j] = -mu_channel[j]*(k_B*Temp/q)*fac_deg[j]/dx
                        Coe_2[j] = -Coe_1[j]
                    else:
                        Coe_1[j] = mu_channel[j]*E_channel[j]*1/(1-np.exp(E_channel[j]*dx/((k_B*Temp/q)*fac_deg[j])))
                        Coe_2[j] = mu_channel[j]*E_channel[j]*1/(1-np.exp(-E_channel[j]*dx/((k_B*Temp/q)*fac_deg[j])))

                AAA = np.diag(-Coe_1[1:Nx-1]+Coe_2[0:Nx-2])-np.diag(Coe_2[1:Nx-2],1)+np.diag(Coe_1[1:Nx-2],-1)
                CCC = np.zeros((Nx-2,1))
                CCC[0] = -Coe_1[0]*Ns_con/Ncc
                CCC[Nx-3] = Coe_2[Nx-2]*Nd_con/Ncc

                BBB = spsolve(sparse.csr_matrix(AAA),sparse.csr_matrix(CCC))
                #Ne_sub[i_val, :, i_sub] = np.reshape([Ns_con,BBB*Ncc,Nd_con],(Nx,1))
                Ne_sub[i_val, 0, i_sub] = Ns_con
                Ne_sub[i_val, 1:Nx-1, i_sub] = BBB*Ncc
                Ne_sub[i_val, Nx-1, i_sub] = Nd_con

                for i_node in np.arange(0,Nx):
                    N_body[:,i_node] = Ne_sub[i_val, i_node, i_sub]*W_sub[i_sub, i_val, :, i_node]/dy

                N_body_sum = N_body_sum+N_body


        Info_scatter_new[:,2] = Fn

        if ox_pnt_flag == 0:
            #Ne_new = [Ne_old(1:(Nx*(t_topa+1)));...
            #reshape((N_body_sum(2:Np_v-1,:))',...
            #Nx*(Np_v-2),1);...
            #Ne_old((Ntotal-Nx*(t_bota+1)+1):Ntotal)]
            Ne_new[0:Nx*(t_topa+1)] = Ne_old[0:Nx*(t_topa+1)]
            Ne_new[Nx*(t_topa+1):Nx*(t_topa+t_sia)] = np.reshape((N_body_sum[1:Np_v-1,:]),(1,Nx*(Np_v-2))).transpose()
            Ne_new[Nx*(t_topa+t_sia):Ntotal] = Ne_old[(Ntotal-Nx*(t_bota+1)):Ntotal]
            Ne_new = np.reshape(Ne_new, (Ntotal, 1))
        elif ox_pnt_flag == 1:
            Ne_new = np.reshape(N_body_sum.transpose(),(1, Ntotal)).transpose()


   ################################################################################
    elif transport_model == 3: #BALLISTIC TRANSPORT USING SEMICLASSICAL APPROACH#####
    ################################################################################

        [U_sub, W_sub] = schred(Ec_old, Nx, Ny, Ntotal, mx, my, mz)
        E_sub = U_sub

        for i_val in np.arange(0, t_vall):
            Ne_2d_1 = 2*(np.sqrt(mx[i_val]*my[i_val])*m_e*k_B*Temp)/(2.0*np.pi*h_bar**2)
            Ne_2d_2 = Ne_2d_1*2.0/np.pi**0.5

            for i_sub in np.arange(0,max_subband):
                U_bias = U_sub[i_val, :, i_sub]
                [Ec_peak,i_peak] = np.max(U_bias), np.argmax(U_bias)
                for i_node in np.arange (0,Nx):
                    MEc_peak = (Ec_peak-U_bias[i_node])/(k_B*Temp/q)
                    zeta_s = (-Vs-U_bias[i_node])/(k_B*Temp/q)
                    zeta_d = (-Vd-U_bias[i_node])/(k_B*Temp/q)
                    if zeta_s == zeta_d+10000:
                        Ne_sub[i_val, i_node, i_sub]=2*Ne_2d_1 * fermi(zeta_s, fermi_flag, 0)
                    else:
                        if i_node <= i_peak:
                            Ne_sub[i_val, i_node, i_sub] = Ne_2d_2*integral(zeta_s, zeta_d, MEc_peak, fermi_flag)
                        elif i_node>i_peak:
                            Ne_sub[i_val, i_node, i_sub] = Ne_2d_2*integral(zeta_d,zeta_s,MEc_peak,fermi_flag)
                    N_body[:,i_node] = Ne_sub[i_val, i_node, i_sub]*W_sub [i_sub, i_val, :,i_node]/dy
                N_body_sum = N_body_sum+N_body

        if ox_pnt_flag == 0:
            #Ne_new = np.array([Ne_old[0:(Nx*(t_topa+1))], [np.reshape((N_body_sum[1:Np_v-1,:]).transpose(),(1,Nx*(Np_v-2))).transpose()], [Ne_old[(Ntotal-Nx*(t_bota+1)):Ntotal]]])
            #Ne_old = Ne_old.toarray()
            Ne_new[0:Nx*(t_topa+1)] = Ne_old[0:Nx*(t_topa+1)]
            Ne_new[Nx*(t_topa+1):Nx*(t_topa+t_sia)] = np.reshape((N_body_sum[1:Np_v-1,:]),(1,Nx*(Np_v-2))).transpose()
            Ne_new[Nx*(t_topa+t_sia):Ntotal] = Ne_old[(Ntotal-Nx*(t_bota+1)):Ntotal]
            Ne_new = np.reshape(Ne_new,(Ntotal,1))
        elif ox_pnt_flag == 1:
            Ne_new = np.reshape(N_body_sum.transpose(), (1, Ntotal)).transpose()
    ##########################################################################
    elif transport_model == 4: #BALLISTIC TRANSPORT MODEL USING GREEN FUNCTION APPROACH
    ##########################################################################

        [U_sub , W_sub] = schred(Ec_old, Nx, Ny, Ntotal, mx, my, mz)

        E_sub = U_sub

        #E , E_number are defined outside the loop to remain constant
        # When simulating several valleys and subband so the size of the DOS matrix
        # Remain constant...This maybe more PCU intensive...

        [Ec_peak, i_peak] = np.max(U_sub[t_vall-1, :, max_subband-1]), np.argmax(U_sub[t_vall-1, :, max_subband-1])
        Ec_peak = np.max((-Vs, Ec_peak))
        E_number = round((Ec_peak+Ef_tail_up-U_sub[0, Nx-1, 0]+Ef_tail_low)/E_step)+2
        print 'E_number = ', E_number
        E = np.linspace((U_sub[0, Nx-1, 0]-Ef_tail_low), (Ec_peak+Ef_tail_up), E_number)
        delta_E = ((Ec_peak+Ef_tail_up)-(U_sub[0, Nx-1, 0]-Ef_tail_low))/(E_number-1)

        for i_val in np.arange(0, t_vall):
            Ne_2d = 2*np.sqrt(mx[i_val]*m_e*(k_B*Temp/q)*q/(2*np.pi**3))/(h_bar*dx)
            tt = (h_bar**2)/(2*my[i_val]*m_e*(dx**2)*q)
            tt = float(tt)
            A = tt*((2*np.eye(Nx))-(np.diag(np.ones(Nx-1), 1))-(np.diag(np.ones(Nx-1), -1)))

            for i_sub in np.arange(0,max_subband):
                U_bias = U_sub[i_val, :, i_sub]
                #[Ec_peak,i_peak]=max(U_bias)
                #Ec_peak=max(-Vs,max(U_bias))
                #E_number=round((Ec_peak+Ef_tail_up-U_bias(Nx)+Ef_tail_low)/E_step)+2
                #E=linspace((U_bias(Nx)-Ef_tail_low),(Ec_peak+Ef_tail_up),E_number)
                #delta_E=((Ec_peak+Ef_tail_up)-(U_bias(Nx)-Ef_tail_low))/(E_number-1)
                N_den = np.zeros((Nx,1))
                B_s = np.zeros((Nx,1))
                B_d = np.zeros((Nx,1))
                B_s[0] = 1
                B_d[Nx-1] = 1
                spB_s = sparse.csr_matrix(B_s)
                spB_d = sparse.csr_matrix(B_d)

                #for k=1:E_number,
                    #ee=E(k);ep=ee+eta
                    #ck=1-((ep-U_bias(1))/(2*tt));con_s=-tt*exp(i*acos(ck))
                    #ck=1-((ep-U_bias(Nx))/(2*tt));con_d=-tt*exp(i*acos(ck))
                    #U_eff=U_bias
                    #U_eff(1)=U_bias(1)+con_s
                    #U_eff(Nx)=U_bias(Nx)+con_d
                    #G_inv=sparse((ep*eye(Nx))-A-diag(U_eff))
                    #G_s=G_inv\spB_s
                    #G_d=G_inv\spB_d
                    #f_1=fermi(((-Vs-ee)/(k_B*Temp/q)),fermi_flag,-1/2)
                    #f_2=fermi(((-Vd-ee)/(k_B*Temp/q)),fermi_flag,-1/2)
                    #N_den=N_den-abs(G_s).^2*imag(con_s)*2*f_1...
                    #      -abs(G_d).^2*imag(con_d)*2*f_2
                    #N_dos_one(:,k)=-abs(G_s).^2*imag(con_s)-abs(G_d).^2*imag(con_d)
                #end

                [N_den1, Nquad] = myquad(func_energy, E[0], E[E_number-1], 1e-6, [], tt, U_bias, A, spB_s, spB_d)
                N_den = N_den1/(E[1]-E[0])

                Ne_sub[i_val, :, i_sub] = (N_den)*Ne_2d*delta_E
                for i_node in np.arange(0,Nx):
                    N_body[:,i_node] = Ne_sub[i_val, i_node, i_sub]*W_sub[i_sub, i_val, :, i_node]/dy

                N_body_sum = N_body_sum+N_body

        if ox_pnt_flag == 0:
            #Ne_new=[Ne_old[1:(Nx*(t_topa+1)));...
            #reshape((N_body_sum(2:Np_v-1,:))',...
            #Nx*(Np_v-2),1);...
            #Ne_old((Ntotal-Nx*(t_bota+1)+1):Ntotal)]
            Ne_new[0:Nx*(t_topa+1)] = Ne_old[0:Nx*(t_topa+1)]
            Ne_new[Nx*(t_topa+1):Nx*(t_topa+t_sia)] = np.reshape((N_body_sum[1:Np_v-1,:]),(1,Nx*(Np_v-2))).transpose()
            Ne_new[Nx*(t_topa+t_sia):Ntotal] = Ne_old[(Ntotal-Nx*(t_bota+1)):Ntotal]
            Ne_new = np.reshape(Ne_new, (Ntotal, 1))
        elif ox_pnt_flag == 1:
           Ne_new = np.reshape(N_body_sum.transpose(), (1, Ntotal)).transpose()

        globvars.E = E

    ################################################################################
    elif transport_model == 5: #SCATTERING MODEL USING GREEN"S FUNCTION METHOD*******
    ################################################################################

        [U_sub, W_sub] = schred(Ec_old, Nx, Ny, Ntotal, mx, my, mz)
        E_sub = U_sub

        U_scatter = np.zeros((Nx, 1))
        mu_scatter_old = np.zeros((nu_scatter+2, 1))
        mu_scatter_new = np.zeros((nu_scatter+2, 1))
        delta_mu = np.zeros((nu_scatter+2, 1))
        i_scatter = np.zeros((nu_scatter+2, 1))
        BB_dummy = np.eye(Nx)
        Iin = np.zeros((nu_scatter,1))

        #comment the two following line for constant mobility
        #zeta_self=zeros(nu_scatter,1);
        #decay_fac=1;%dimensionless

        for i_s in np.arange(0, nu_scatter):
            i_scatter[i_s] = (Info_scatter_old[i_s, 1])

            # CHANGED BY RAMESH TO TAKE OLD GUESS
            mu_scatter_old[i_s] = (Info_scatter_new[i_s, 2])

        mu_scatter_old[nu_scatter] = -Vs
        mu_scatter_old[nu_scatter+1] = -Vd
        i_scatter[nu_scatter] = 0
        i_scatter[nu_scatter+1] = Nx-1
        BB = sparse.lil_matrix((int(Nx), int(nu_scatter+2)), dtype=float)
        i_scatter = i_scatter.astype(int)
        i_scatter = np.squeeze(i_scatter)
        #mu_scatter_old = mu_scatter_old.astype(int)
        mu_scatter_old = np.squeeze(mu_scatter_old)

        BB[:, 0:int(nu_scatter)] = BB_dummy[:,i_scatter[0:nu_scatter]]
        BB[:, int(nu_scatter):int(nu_scatter)+1] = BB_dummy[:, 0:1]
        for ind in np.arange(0,Nx):
            if BB_dummy[ind, Nx-1]:
                BB[ind, int(nu_scatter) + 1] = BB_dummy[ind, Nx-1]
        BB = BB.tocsr()

        Ec_peak = np.max((-Vs, np.max(U_sub[0, :, 0])))
        Ec_bottom = U_sub[0, Nx-1, 0]
        E_number = round((Ec_peak+Ef_tail_up-Ec_bottom+Ef_tail_low)/E_step)+2
        E = np.linspace((Ec_bottom-Ef_tail_low), (Ec_peak+Ef_tail_up), E_number)
        delta_E = ((Ec_peak+Ef_tail_up)-(Ec_bottom-Ef_tail_low))/(E_number-1)

        GG = sparse.csr_matrix((Nx,nu_scatter+2))
        T_E = np.zeros((nu_scatter+2, E_number, nu_scatter+2))

        # comment the next line and uncomment the previous line for constant mobility

        E_self = np.ones((E_number,nu_scatter+2)) #correction on March 14th to include mobility
        E_self = E_self + 0j
        U_tem = np.zeros((nu_scatter,1))

        # end of initialization

        # ADDED BY RAMESH JAN 13th 03.
        # We need to compute a mean free path to set
        # zeta_self based on the Fermi-level of the
        # probe, subband energy and grid spacing.
        sum1 = np.zeros((nu_scatter, 1))
        sum2 = np.zeros((nu_scatter, 1))
        lambda1 = np.zeros((nu_scatter, 1))
        for i_val in np.arange(0, t_vall):
            for i_sub in np.arange(0, max_subband):
                for i_s in np.arange(0, nu_scatter):
                    factor = np.exp((Info_scatter_new[i_s,2]-U_sub[i_val, i_scatter[i_s], i_sub])/(k_B*Temp/q))
                    sum1[i_s] = sum1[i_s]+my[i_val]*m_e*np.log(1+factor)
                        # Prevent divide by zero
                    factor1 = np.log(1+factor)
                    if(factor1<=1e-20):
                        factor1 = factor
                    factor2 = factor/(factor1*(1+factor))*fermi(((Info_scatter_new[i_s,2]-U_sub[i_val, i_scatter[i_s],i_sub])/(k_B*Temp/q)),fermi_flag,1.0/2.0)
                    sum2[i_s] = sum2[i_s]+my[i_val]*m_e*np.sqrt(2*k_B*Temp/(np.pi*mx[i_val]*m_e))*factor2

        for i_s in np.arange(0, nu_scatter):
            lambda1[i_s]=2*k_B*Temp/q*Info_scatter_old[i_s,3]*sum1[i_s]/sum2[i_s]

        lambda1 = np.squeeze(lambda1)

        ttot=0
        scattot=0
        ktot =0
        stot = 0
        k2tot =0
        soltot = 0
        asstot = 0
        N_dos = np.zeros((Nx, E_number))

        for i_val in np.arange(0,t_vall):
            t1 = time.time()
            Ie_2d = 2*q**2/(np.pi**2*h_bar**2)*np.sqrt(my[i_val]*m_e*(k_B*Temp/q)*q*np.pi/2.0)
            tt = (h_bar**2)/(2*mx[i_val]*m_e*(dx**2)*q)
            tt = float(tt)
            A = tt*((2*np.eye(Nx))-(np.diag(np.ones(Nx-1),1))-(np.diag(np.ones(Nx-1),-1)))
            t2 = time.time()
            ttot += (t2 - t1)
            for i_sub in np.arange(0, max_subband):
                s1 = time.time()
                U_bias = U_sub[i_val, :, i_sub]
                U_tem = U_bias[i_scatter[0:nu_scatter]]
                s2 = time.time()
                stot += (s2-s1)
                for k in np.arange(0, E_number):
                    k1=time.time()
                    ee = E[k]
                    ep = ee+eta
                    ck = 1-((ep-U_bias[0])/(2*tt))
                    con_s = -tt*np.exp(1j*np.arccos(ck))
                    ck = 1-((ep-U_bias[Nx-1])/(2*tt))
                    con_d = -tt*np.exp(1j*np.arccos(ck))
                    k2 = time.time()
                    ktot += (k2 -k1)
                # ADDED BY RAMESH JAN 13 03.
                    scat1 = time.time()
                    for i_s in np.arange(0, nu_scatter):
                        elutot = ee-(A[i_scatter[i_s], i_scatter[i_s]]+U_bias[i_scatter[i_s]])
                        g1 = (elutot+cmath.sqrt(elutot**2-4.0*tt**2))/(2*tt**2)
                        g2 = (elutot-cmath.sqrt(elutot**2-4.0*tt**2))/(2*tt**2)
                        g3 = (np.imag(g2)<=0)*g2+(np.imag(g1<=0))*g1
                        E_self[k,i_s] = 1j*np.imag(g3*2*dx*tt**2/lambda1[i_s])

                    scat2 = time.time()
                    scattot += (scat2-scat1)
                    k3 = time.time()
                    E_self[k, nu_scatter] = con_s
                    E_self[k, nu_scatter+1] = con_d
                    U_scatter = U_scatter + 0j
                    U_scatter = np.squeeze(U_scatter)
                    U_scatter[i_scatter] = (E_self[k, :])

                    U_eff = U_bias+U_scatter
                    #print U_eff
                    G_inv = sparse.csr_matrix((ep*np.eye(Nx))-A-np.diag(U_eff))
                    GG = np.zeros((Nx, nu_scatter+2))
                    GG = GG + 0j
                    k4 = time.time()
                    k2tot += (k4-k3)
                    sol1 = time.time()
                    gin = np.linalg.inv(G_inv.todense())
                    gin = sparse.csr_matrix(gin)
                    GG = gin*BB
                    GG = GG.toarray()
                    sol2 = time.time()
                    soltot += (sol2-sol1)
                    #print sparse.csr_matrix(np.diag(np.imag(E_self[k,:]).conj().T))
                    #print np.shape(GG[i_scatter,:])
                    #print delta_E
                    #print abs(GG[i_scatter,:])**2
                    #print sparse.csr_matrix(4*int(Ie_2d)*delta_E*np.dot(np.diag(np.imag(E_self[k,:]).conj().T),abs(GG[i_scatter,:])**2))
                    T_E[:,k,:] = 4*int(Ie_2d)*delta_E*np.dot((np.dot(np.diag(np.imag(E_self[k,:]).conj().T),abs(GG[i_scatter,:])**2)),np.diag(np.imag(E_self[k,:]).conj().T))+np.squeeze(T_E[:, k, :])
                    #print sparse.csr_matrix(T_E[:,k,:])
                    #print E_self[k,:]
                    #print GG[i_scatter,:]
                    #print k
                    sol3 = time.time()
                    asstot += (sol3-sol2)
        #print ttot, stot, ktot, scattot, k2tot, soltot, asstot

        #calculate current, and search for mu_scatter
        #based on current continuity

        [Is, Id, Iin, mu_scatter_new] = current_mat(mu_scatter_old, T_E, E)
        #print 'sad'
        #print Is
        #print Id

        #end of mu_scatter search

        #Calculate charge density
        for i_val in np.arange(0, t_vall):
            Ne_2d = 2.0*np.sqrt(my[i_val]*m_e*(k_B*Temp/q)*q/(2.0*np.pi**3))/(h_bar*dx)
            tt = (h_bar**2)/(2.0*mx[i_val]*m_e*(dx**2)*q)
            tt = float(tt)
            A = tt*((2.0*np.eye(Nx))-(np.diag(np.ones(Nx-1),1))-(np.diag(np.ones(Nx-1),-1)))

            for i_sub in np.arange(0,max_subband):
                U_bias = U_sub[i_val, :, i_sub]
                U_tem = U_bias[(i_scatter[0:nu_scatter])]

                for k in np.arange(0, E_number):

                    # All this needs to be recomputed for multiple bands
                    #--------------------------------------------------
                    ee=E[k]
                    ep=ee+eta
                    ck=1-((ep-U_bias[0])/(2*tt))
                    con_s=-tt*np.exp(1j*np.arccos(ck))
                    ck=1-((ep-U_bias[Nx-1])/(2*tt))
                    con_d=-tt*np.exp(1j*np.arccos(ck))

                 # ADDED BY RAMESH JAN 13 03.
                    for i_s in np.arange(0, nu_scatter):
                        elutot = ee-(A[i_scatter[i_s], i_scatter[i_s]]+U_bias[i_scatter[i_s]])
                        g1 = (elutot+cmath.sqrt(elutot**2-4*tt**2))/(2*tt**2)
                        g2 = (elutot-cmath.sqrt(elutot**2-4*tt**2))/(2*tt**2)
                        g3 = (np.imag(g2)<=0)*g2+(np.imag(g1<=0))*g1
                        E_self[k,i_s] = 1j*np.imag(g3*2*dx*tt**2/lambda1[i_s])

                    E_self = E_self + 0j
                    E_self[k, nu_scatter] = con_s
                    E_self[k, nu_scatter+1] = con_d
                    U_scatter[i_scatter] = (E_self[k,:]).transpose()

                    U_eff = U_bias+U_scatter
                    G_inv = sparse.csr_matrix((ep*np.eye(Nx))-A-np.diag(U_eff))
                    gin = np.linalg.inv(G_inv.todense())
                    gin = sparse.csr_matrix(gin)
                    GG = gin*BB
                    GG = GG.toarray()
                    Ne_sub[i_val, :, i_sub]=Ne_sub[i_val, :, i_sub]-np.dot(2*Ne_2d*delta_E*abs(GG)**2,(np.imag(E_self[k,:]).conj().T)*fermi(((mu_scatter_new-ee)/(k_B*Temp/q)),fermi_flag,-1.0/2.0))

                    GGG = np.zeros((Nx,Nx))
                    GGG = GGG +0j
                    GGG[:, 0] = GG[:, Nx-2]
                    GGG[:, Nx-1] = GG[:, Nx-1]
                    GGG[0:Nx, 1:Nx-1] = GG[0:Nx,0:Nx-2]
                    N_dos[:,k] = -2*np.imag(np.diag(GGG))


                for i_node in np.arange(0,Nx):
                    N_body[:, i_node] = Ne_sub[i_val, i_node, i_sub]*W_sub[i_sub, i_val, :,i_node]/dy

                N_body_sum = N_body_sum+N_body

        Info_scatter_new[:, 0] = np.squeeze(Iin)
        Info_scatter_new[0, 0] = Is
        Info_scatter_new[:, 2] = mu_scatter_new[0:nu_scatter]

        if ox_pnt_flag==0:
            #Ne_new=[Ne_old(1:(Nx*(t_topa+1)));...
            #reshape((N_body_sum(2:Np_v-1,:))',...
            #Nx*(Np_v-2),1);...
            #Ne_old((Ntotal-Nx*(t_bota+1)+1):Ntotal)]
            Ne_new[0:Nx*(t_topa+1)] = Ne_old[0:Nx*(t_topa+1)]
            Ne_new[Nx*(t_topa+1):Nx*(t_topa+t_sia)] = np.reshape((N_body_sum[1:Np_v-1,:]),(1,Nx*(Np_v-2))).transpose()
            Ne_new[Nx*(t_topa+t_sia):Ntotal] = Ne_old[(Ntotal-Nx*(t_bota+1)):Ntotal]
            Ne_new = np.reshape(Ne_new, (Ntotal, 1))
        elif ox_pnt_flag==1:
            Ne_new=np.reshape(N_body_sum.transpose(), (1, Ntotal)).transpose()

        globvars.E = E
        globvars.Info_scatter_new = Info_scatter_new
        globvars.Info_scatter_old = Info_scatter_old
        globvars.Is = Is
        globvars.Id = Id
        globvars.N_dos = N_dos


    ################################################################################
    ######################START OF VARIABLE CHANGE PART#############################
    ################################################################################

    if ox_pnt_flag == 0:  # No electron penetration into oxide
        for iii_row in np.arange((Nx*(t_topa+1))/Nx, (Ntotal-Nx*t_bota)/Nx-1):
            for iii_col in np.arange(0, Nx):
                i_node = iii_row*Nx+iii_col
                Fn_new[i_node] = anti_dummy(Ne_new[i_node]/Nc, dummy_flag, fermi_flag)*(k_B*Temp/q)+Ec_old[i_node]
    elif ox_pnt_flag == 1: # assuming electron penetration into oxide
        Fn_new = anti_dummy((Ne_new+div_avd)/Nc, dummy_flag, fermi_flag)*(k_B*Temp/q)+Ec_old

    #############################################################################
    #######################END OF VARIABLE CHANGE PART###########################
    #############################################################################

    #############################################################################
    ########################END OF FUNCTION CHARGE.M#############################
    #############################################################################

    return [Fn_new, Ne_new, Ne_sub, E_sub]