Example #1
0
def  DDGnlpoisson (idata,xaxis,sinodes,Vin,nin,pin,Fnin,Fpin,dop,Ppz_Psp,l2,toll,maxit,verbose,ni,fi_e,fi_h,model,Vt):
    ## Set some useful constants
    dampit = 10
    dampcoeff	= 5
    
    ## Convert grid info to FEM form
    #Ndiricheletnodes= 2
    nodes 	= xaxis
    sielements=np.zeros(len(sinodes)-1) 
    sielements[:] = sinodes[1:len(sinodes)]
    n_max	= len(nodes)
    fi_n=np.zeros(n_max)
    fi_p=np.zeros(n_max)
    #totdofs = n_max - Ndiricheletnodes
    elements=np.zeros((n_max-1,2))
    elements[:,0]= np.arange(0,n_max-1)
    elements[:,1]=np.arange(1,n_max)
    Nelements=np.size(elements[:,0])
    BCnodes= n_max
    normr=np.zeros(maxit+1)
    """
    print("nodes=",nodes)
    print("sielements=",sielements)    
    print("n_max=",n_max)
    print("elements=",elements)
    print("Nelements=",Nelements)
    print("BCnodes=",BCnodes)
    check_point_8    
    """
    ## Initialization
    V = Vin
    Fn = Fnin
    Fp = Fpin
    if model.N_wells_virtual-2!=0 and config.quantum_effect:
        fi_n,fi_p =equi_np_fi222(ni,idata,fi_e,fi_h,V,Vt,idata.wfh_general,idata.wfe_general,model,idata.E_state_general,idata.E_statec_general,idata.meff_state_general,idata.meff_statec_general,n_max,idata.n,idata.p)

    n = DDGphin2n(V[sinodes]+fi_n[sinodes],Fn,idata.n)
    p = DDGphip2p(V[sinodes]+fi_p[sinodes],Fp,idata.p)
    """
    print("sinodes=",sinodes)
    print("n=",n)
    print("p=",p)
    check_point_9
    """
    if (sinodes[0]==0):
        n[1]=nin[0]
        p[1]=pin[0]
    if (sinodes[n_max-1]==n_max-1):
        n[n_max-1]=nin[n_max-1]
        p[n_max-1]=pin[n_max-1]
    
    ## Compute LHS matrices
    l22=l2*np.ones(Nelements)
    L      = Ucomplap (nodes,n_max,elements,Nelements,l22)
    
    ## Compute Mv =  ( n + p)
    Mv            =  np.zeros(n_max)
    Mv[sinodes]   =  (n + p)
    Cv            =  np.ones(Nelements)
    M             =  Ucompmass (nodes,n_max,elements,Nelements,Mv,Cv)
    
    ## Compute RHS vector
    Tv0            =  np.zeros(n_max)
    Tv0[sinodes]   = (n - p -dop-Ppz_Psp)
    Cv=  np.ones(Nelements)
    T0             =  Ucompconst (nodes,n_max,elements,Nelements,Tv0,Cv)
    
    """
    print('L=',L)
    print('M=',M)
    print('T0=',T0)
    check_point_10
    """
    ## Build LHS matrix and RHS of the linear system for 1st Newton step
    A=np.zeros((n_max,n_max))
    R=np.zeros(n_max)
    Anew=np.zeros((n_max,n_max))
    Rnew=np.zeros(n_max)
    
    A 		= L + M
    LV=np.dot(np.array(L) , V)
    R 		=  LV +T0
    
    ## Apply boundary conditions
    """
    print('A=',A)
    print('R=',R)
    check_point_11
    """
    
    A=np.delete(A, [0,BCnodes-1], 0)
    A=np.delete(A, [0,BCnodes-1], 1)
    R=np.delete(R, [0,BCnodes-1], 0)
    
    normr[0]		=  np.linalg.norm(R,np.inf)
    relresnorm 	= 1
    reldVnorm   = 1
    normrnew	= normr[0]
    
    ## Start of the newton cycle
    for newtit in range(1,maxit):
        if verbose:
            print("\n newton iteration: %d, reldVnorm = %f"%(newtit,reldVnorm))
        
        cc= np.linalg.solve(A, -R)#, rcond=None)[0]
        dV=np.zeros(n_max)
        dV[1:n_max-1] =cc
        ## Start of the damping procedure
        tk = 1
 
        for dit in range(1,dampit):
            if verbose:
                print("\n damping iteration: %d, residual norm = %f"%(dit,normrnew))
            Vnew   = V + tk * dV
            if model.N_wells_virtual-2!=0 and config.quantum_effect:
                fi_n,fi_p =equi_np_fi222(ni,idata,fi_e,fi_h,Vnew,Vt,idata.wfh_general,idata.wfe_general,model,idata.E_state_general,idata.E_statec_general,idata.meff_state_general,idata.meff_statec_general,n_max,n,p)             
            n = DDGphin2n(Vnew[sinodes]+fi_n[sinodes],Fn,idata.n)
            p = DDGphip2p(Vnew[sinodes]+fi_p[sinodes],Fp,idata.p)
            if (sinodes[0]==0):
                n[0]=nin[0]
                p[0]=pin[0]
            if (sinodes[n_max-1]==n_max-1):
                n[n_max-1]=nin[n_max-1]
                p[n_max-1]=pin[n_max-1]
            
            ## Compute LHS matrices
            Mv            =  np.zeros(n_max)
            Mv[sinodes]   =  (n + p)
            Cv            =  np.ones(Nelements)
            #Cv[sielements]=  1        
            M    = Ucompmass (nodes,n_max,elements,Nelements,Mv,Cv)
            
            ## Compute RHS vector (-residual)
            Tv0            =  np.zeros(n_max)
            Tv0[sinodes]   =  (n - p -dop-Ppz_Psp)
            Cv=  np.ones(Nelements)
            Cv            =  np.ones(Nelements)
            #Cv[sielements]=  1
            T0     = Ucompconst (nodes,n_max,elements,Nelements,Tv0,Cv)
            """ 
            print('L=',L)
            print('M=',M)
            print('T0=',T0)
            check_point_12
            """           
            ## Build LHS matrix and RHS of the linear system for 1st Newton step
            Anew 		= L + M
            LVnew=np.dot(np.array(L) , Vnew)
            Rnew 		=  LVnew +T0
            """
            print('Anew=',Anew)
            print('Rnew=',Rnew)
            check_point_13
            """
            ## Apply boundary conditions
            Anew=np.delete(Anew, [0,BCnodes-1], 0)
            Anew=np.delete(Anew, [0,BCnodes-1], 1)
            Rnew=np.delete(Rnew, [0,BCnodes-1], 0)
            
            if ((dit>1) and (np.linalg.norm(Rnew,np.inf) >= np.linalg.norm(R,np.inf))):
                if verbose:
                    print("\nexiting damping cycle \n")
                break
            else:
                A = Anew
                R = Rnew
        
            ## Compute | R_{k+1} | for the convergence test
            normrnew= np.linalg.norm(R,np.inf)
            
            ## Check if more damping is needed
            if (normrnew > normr[newtit]):
                tk = tk/dampcoeff
            else:
                if verbose:
                    print("\nexiting damping cycle because residual norm = %f \n"%normrnew)
                break
    
        V= Vnew	
        normr[newtit+1] = normrnew
        dVnorm= np.linalg.norm(tk*dV,np.inf)
    
        ## Check if convergence has been reached
        reldVnorm           = dVnorm / np.linalg.norm(V,np.inf)
        if (reldVnorm <= toll):
            if(verbose):
                print("\nexiting newton cycle because reldVnorm= %f \n"%reldVnorm)
            break
    
    res = normr
    niter = newtit
    
    return [V,n,p]#,res,niter
Example #2
0
def  DDNnewtonmap (ni,fi_e,fi_h,xaxis,idata,toll,maxit,verbose,model,Vt):
    odata     = idata
    n_max    = len(xaxis)
    fi_n=np.zeros(n_max)
    fi_p=np.zeros(n_max)
    Nelements=n_max-1
    elements=np.zeros((n_max-1,2))
    elements[:,0]= np.arange(0,n_max-1)
    elements[:,1]=np.arange(1,n_max)
    BCnodesp = [0,n_max-1]
    BCnodesp1 = [n_max,2*n_max-1]
    BCnodesp2 = [2*n_max,3*n_max-1]
    BCnodes_=np.zeros((3,2))
    BCnodes_[0,:]=BCnodesp
    BCnodes_[1,:]=BCnodesp1
    BCnodes_[2,:]=BCnodesp2
    BCnodes=BCnodes_.flatten()

    totaldofs= n_max-2
    dampcoef = 10
    maxdamp  = 2
    nrm_du_old=1.
    V = odata.V
    n = odata.n
    p = odata.p
    dop = idata.dop
    Ppz_Psp=idata.Ppz_Psp
    
    ## Create the complete unknown vector
    u = np.hstack(([V, n, p]))
    if model.N_wells_virtual-2!=0 and config.quantum_effect:
        fi_n,fi_p =equi_np_fi222(ni,idata,fi_e,fi_h,V,Vt,idata.wfh_general,idata.wfe_general,model,idata.E_state_general,idata.E_statec_general,idata.meff_state_general,idata.meff_statec_general,n_max,n,p)    
    ## Build fem matrices
    L = Ucomplap (xaxis,n_max,elements,Nelements,idata.l2*np.ones(Nelements))
    M = Ucompmass (xaxis,n_max,elements,Nelements,np.ones(n_max),np.ones(Nelements))
    DDn = Uscharfettergummel(xaxis,n_max,elements,Nelements,idata.mun,1,V+fi_n)
    DDp = Uscharfettergummel(xaxis,n_max,elements,Nelements,idata.mup,1,-V-fi_p)
    
    ## Initialise RHS
    denomsrh   = idata.TAUN0 * (p + idata.theta) + idata.TAUP0 * (n + idata.theta)
    factauger  = idata.Cn * n + idata.Cp * p
    fact       = (1 / denomsrh + factauger)
    r1  = np.dot(np.array(L) , V) + np.dot(np.array(M) , (n - p - dop-Ppz_Psp))
    r2  = np.dot(np.array(DDn) , n)+ np.dot(np.array(M) , (p * n - idata.theta** 2) * fact)
    r3  = np.dot(np.array(DDp) , p)+ np.dot(np.array(M) , (p * n - idata.theta** 2) * fact)
    RHS=-np.hstack(( r1, r2, r3))

    ##  Apply BCs
    RHS=np.delete(RHS, BCnodes, 0)
    nrm = np.linalg.norm(RHS,np.inf)
    res=np.zeros(maxit)
    res[0] = nrm
    ## Begin Newton Cycle
    for count in range (0, maxit):
        if verbose:
          print ("Newton Iteration Number:%d\n"%count)	
        Ln = Ucomplap (xaxis,n_max,elements,Nelements,Umediaarmonica(idata.mun*n))
        Lp = Ucomplap (xaxis,n_max,elements,Nelements,Umediaarmonica(idata.mup*p))
        Mn = Ucompmass (xaxis,n_max,elements,Nelements,np.ones(n_max),n[0:n_max-1]*fact[0:n_max-1])
        Mp = Ucompmass (xaxis,n_max,elements,Nelements,np.ones(n_max),p[0:n_max-1]*fact[0:n_max-1])
        Z  = np.zeros((n_max,n_max))   
        DDn = Uscharfettergummel(xaxis,n_max,elements,Nelements,idata.mun,1,V+fi_n)
        DDp = Uscharfettergummel(xaxis,n_max,elements,Nelements,idata.mup,1,-V-fi_p)
        A 	= L  #A11
        B	= M #A12
        C	=-M #A13
        DDD	=-Ln #A21
        E	= DDn+Mp#A22
        F	= Z+Mn  #A23
        G	= Lp #A31
        H	= Z+Mp #A32
        I	= DDp+Mn#A33
        ## Build LHS
        LHS= np.asarray(np.bmat([(A,	B, C),(DDD, E, F),(G, H, I)]))
        ## Apply BCs
        LHS=np.delete(LHS, BCnodes, 0)
        LHS=np.delete(LHS, BCnodes, 1)        
        ## Solve the linearised system
        dutmp= np.linalg.solve(LHS, RHS)#, rcond=None)[0]
        dv    = dutmp[0:totaldofs]
        dn    = dutmp[totaldofs:2*totaldofs]
        dp    = dutmp[2*totaldofs:3*totaldofs]
        du=np.hstack((0,dv,0,0,dn,0,0,dp,0))
        ## Check Convergence
        nrm_u = np.linalg.norm(u,np.inf)
        nrm_du = np.linalg.norm(du,np.inf)
    	
        ratio = nrm_du/nrm_u 
        if verbose:
          print ("ratio = %e\n"% ratio)		
        
        if (ratio <= toll):
            V 	 = u[0:n_max]
            n	    = u[n_max:2*n_max]
            p	    = u[2*n_max:len(u)]
            res[count]  = nrm
            break
        ## Begin damping cycle
        tj = 1
        if model.N_wells_virtual-2!=0 and config.quantum_effect:
            fi_n,fi_p =equi_np_fi222(ni,idata,fi_e,fi_h,V,Vt,idata.wfh_general,idata.wfe_general,model,idata.E_state_general,idata.E_statec_general,idata.meff_state_general,idata.meff_statec_general,n_max,n,p)
        for cc in range( 1,maxdamp):
          if verbose:
            print ("damping iteration number:%d\n"%cc)
            print ("reference residual norm:%f\n"%nrm)
          
          ## Update the unknown vector		
          utmp    = u + tj*du
          Vnew 	    = utmp[0:n_max]
          nnew	    = utmp[n_max:2*n_max]
          pnew	    = utmp[2*n_max:len(utmp)]
          ## Try a new RHS
          
          DDn = Uscharfettergummel(xaxis,n_max,elements,Nelements,idata.mun,1,Vnew+fi_n)
          DDp = Uscharfettergummel(xaxis,n_max,elements,Nelements,idata.mup,1,-Vnew-fi_p)
          
          r1  = np.dot(np.array(L) , V) + np.dot(np.array(M) , (nnew - pnew - dop-Ppz_Psp))
          r2  = np.dot(np.array(DDn) , nnew)+ np.dot(np.array(M) , (pnew * nnew - idata.theta** 2) * fact)
          r3  = np.dot(np.array(DDp) , pnew) + np.dot(np.array(M) , (pnew * nnew - idata.theta** 2) * fact)
          RHS=-np.hstack(( r1, r2, r3))

          ## Apply BCs
          RHS=np.delete(RHS, BCnodes, 0)
          nrmtmp=np.linalg.norm(RHS,np.inf)
          
          ## Update the damping coefficient
          if verbose:
              print("residual norm:%f\n\n"%nrmtmp)
            
          if (nrmtmp>nrm):
              tj = tj/(dampcoef*cc)
              if verbose:                  
                  print ("\ndamping coefficients = %f"%tj)
          else:
              break
        nrm_du = np.linalg.norm(tj*du,np.inf)
        u 	= utmp
        
        if (count>0):
            ratio = nrm_du/nrm_du_old
            if (ratio<.005):
                V 	    = u[0:n_max]
                n	    = u[n_max:2*n_max]
                p	    = u[2*n_max:len(u)]            
                res[count]  = nrm
                break           
        nrm = nrmtmp
        res[count]  = nrm
        ## Convert result vector into distinct output vectors 
        V 	    = u[0:n_max]
        n	    = u[n_max:2*n_max]
        p	    = u[2*n_max:len(u)]    
        nrm_du_old = nrm_du
    odata.V = V
    odata.n = n
    odata.p = p
    

    it   = count

    return [odata,it,res]
Example #3
0
def DDGelectron_driftdiffusion(psi, xaxis, ng, p, ni, TAUN0, TAUP0, mun, fi_e,
                               fi_h, model, Vt, idata):

    nodes = xaxis
    n_max = len(nodes)
    """
    n=np.zeros(n_max)
    p=np.zeros(n_max)
    """
    fi_n = np.zeros(n_max)
    fi_p = np.zeros(n_max)
    elements = np.zeros((n_max - 1, 2))
    elements[:, 0] = np.arange(0, n_max - 1)
    elements[:, 1] = np.arange(1, n_max)
    Nelements = np.size(elements[:, 0])

    BCnodes = [0, n_max - 1]

    nl = ng[0]
    nr = ng[n_max - 1]
    h = nodes[1:n_max] - nodes[0:n_max - 1]

    c = 1 / h
    """
    print("c=",c)
    print("h=",h)
    print("nr=",nr)
    print("nl=",nl)
    print("BCnodes=",BCnodes)
    print("Nelements=",Nelements)
    print("elements=",elements)
    print("n_max=",n_max)
    print("nodes=",nodes)
    check_point_15
    """
    if model.N_wells_virtual - 2 != 0 and config.quantum_effect:
        fi_n, fi_p = equi_np_fi222(
            ni, idata, fi_e, fi_h, psi, Vt, idata.wfh_general,
            idata.wfe_general, model, idata.E_state_general,
            idata.E_statec_general, idata.meff_state_general,
            idata.meff_statec_general, n_max, idata.n, p)
    Bneg = Ubernoulli(
        -(psi[1:n_max] - psi[0:n_max - 1]) -
        (fi_n[1:n_max] - fi_n[0:n_max - 1]), 1)
    Bpos = Ubernoulli((psi[1:n_max] - psi[0:n_max - 1]) +
                      (fi_p[1:n_max] - fi_p[0:n_max - 1]), 1)
    """
    print("Bneg=",Bneg)
    print("Bpos=",Bpos)
    check_point_16 
    """

    d0 = np.zeros(n_max)
    d0[0] = c[0] * Bneg[0]
    d0[n_max - 1] = c[len(c) - 1] * Bpos[len(Bpos) - 1]
    d0[1:n_max -
       1] = c[0:len(c) - 1] * Bpos[0:len(Bpos) -
                                   1] + c[1:len(c)] * Bneg[1:len(Bneg)]

    d1 = np.zeros(n_max)
    d1[0] = n_max
    d1[1:n_max] = -c * Bpos
    dm1 = np.zeros(n_max)
    dm1[n_max - 1] = n_max
    dm1[0:n_max - 1] = -c * Bneg
    """
    print("d0=",d0)
    print("d1=",d1)
    print("dm1=",dm1)
    check_point_17
    """
    A = sp.spdiags([dm1, d0, d1], np.array([-1, 0, 1]), n_max, n_max).todense()

    b = np.zeros(n_max)  #%- A * ng

    ## SRH Recombination term
    SRHD = TAUP0 * (ng + ni) + TAUN0 * (p + ni)
    SRHL = p / SRHD
    SRHR = ni**2 / SRHD

    ASRH = Ucompmass(nodes, n_max, elements, Nelements, SRHL,
                     np.ones(Nelements))
    bSRH = Ucompconst(nodes, n_max, elements, Nelements, SRHR,
                      np.ones(Nelements))
    """
    print("ASRH=",ASRH)
    print("bSRH=",bSRH)
    check_point_18
    """
    A = A + ASRH
    b = b + bSRH
    """ 
    print("A=",A)
    print("b=",b)
    check_point_19
    """
    ## Boundary conditions
    b = np.delete(b, BCnodes, 0)
    b[0] = -A[1, 0] * nl
    b[len(b) - 1] = -A[n_max - 2, n_max - 1] * nr
    A = np.delete(A, BCnodes, 0)
    A = np.delete(A, BCnodes, 1)

    nn = np.linalg.solve(A, b)
    n = np.zeros(n_max)
    n[1:n_max - 1] = nn
    n[0] = nl
    n[len(n) - 1] = nr
    """
    print("BCnodes=",BCnodes)
    print("A=",A)
    print("b=",b)
    print("n=",n)
    check_point_20    
    """
    return n
Example #4
0
def  DDGhole_driftdiffusion(psi,xaxis,pg,n,ni,TAUN0,TAUP0,mup,fi_e,fi_h,model,Vt,idata):
    
    nodes        = xaxis
    n_max     =len(nodes)
    """
    n=np.zeros(n_max)
    p=np.zeros(n_max)
    """
    fi_n=np.zeros(n_max)
    fi_p=np.zeros(n_max)
    elements=np.zeros((n_max-1,2))
    elements[:,0]= np.arange(0,n_max-1)
    elements[:,1]=np.arange(1,n_max)
    Nelements=np.size(elements[:,0])
    
    BCnodes= [0,n_max-1]
    
    pl = pg[0]
    pr = pg[n_max-1]
    h=nodes[1:len(nodes)]-nodes[0:len(nodes)-1]
    
    c=1/h
    if model.N_wells_virtual-2!=0 and config.quantum_effect:
        fi_n,fi_p =equi_np_fi222(ni,idata,fi_e,fi_h,psi,Vt,idata.wfh_general,idata.wfe_general,model,idata.E_state_general,idata.E_statec_general,idata.meff_state_general,idata.meff_statec_general,n_max,n,idata.p)
    Bneg=Ubernoulli(-(psi[1:n_max]-psi[0:n_max-1])-(fi_n[1:n_max]-fi_n[0:n_max-1]),1)
    Bpos=Ubernoulli( (psi[1:n_max]-psi[0:n_max-1])+(fi_p[1:n_max]-fi_p[0:n_max-1]),1)
    
    d0=np.zeros(n_max)
    d0[0]=c[0]*Bneg[0]
    d0[n_max-1]=c[len(c)-1]*Bpos[len(Bpos)-1]
    d0[1:n_max-1]=c[0:len(c)-1]*Bpos[0:len(Bpos)-1]+c[1:len(c)]*Bneg[1:len(Bneg)]    
    
    d1	= np.zeros(n_max)
    d1[0]=n_max
    d1[1:n_max]=-c* Bneg      
    dm1	= np.zeros(n_max)
    dm1[n_max-1]=n_max
    dm1[0:n_max-1]=-c* Bpos   
    A = sp.spdiags([dm1, d0, d1],np.array([-1,0,1]),n_max,n_max).todense() 
    b = np.zeros(n_max)#%- A * ng
    
    ## SRH Recombination term
        
    SRHD = TAUP0 * (n + ni) + TAUN0 * (pg + ni)
    SRHL = n / SRHD
    SRHR = ni**2 / SRHD
    
    ASRH = Ucompmass (nodes,n_max,elements,Nelements,SRHL,np.ones(Nelements))
    bSRH = Ucompconst (nodes,n_max,elements,Nelements,SRHR,np.ones(Nelements))
    
    A = A + ASRH
    b = b + bSRH
    
    ## Boundary conditions
    b=np.delete(b, BCnodes, 0)
    b[0]         = - A[1,0] * pl
    b[len(b)-1]       = - A[n_max-2,n_max-1] * pr
    A=np.delete(A, BCnodes, 0)
    A=np.delete(A, BCnodes, 1)
    
    pp= np.linalg.solve(A,b)
    p=np.zeros(n_max)
    p[1:n_max-1]=pp    
    p[0]=pl
    p[len(p)-1]=pr
    return p