Beispiel #1
0
def  DDGnlpoisson_new (idata,xaxis,sinodes,Vin,nin,pin,toll,maxit,verbose,fi_e,fi_h,model,Vt,surface,fi_stat,iteration,ns):
    ## 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)
    #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
    EF = 0.0
    if iteration == 1:
        # Determination of the Fermi Level
        EF = 0.0
        V = np.zeros(n_max)
        n, p, V = equi_np_fi(
            iteration, idata.dop, idata.Ppz_Psp, n_max, idata.ni, model, Vt, surface
        )
        fi_stat = V
    else:
        if model.N_wells_virtual - 2 != 0:
            n, p, fi_non, EF = equi_np_fi3(
            V,
            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.ni*ns,
        )
        else:
            n = np.exp(V)
            p = np.exp(-V)       
        n=n*idata.ni
        p=p*idata.ni
    """
    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=idata.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 -idata.dop-idata.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 iteration == 1:
                n = np.exp(Vnew)*idata.ni
                p = np.exp(-Vnew)*idata.ni
            else:
                if model.N_wells_virtual - 2 != 0:
                    n, p, fi_non, EF = equi_np_fi3(
                    Vnew,
                    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.ni*ns,
                )
                else:
                    n = np.exp(Vnew)
                    p = np.exp(-Vnew)               
                n=n*idata.ni
                p=p*idata.ni            
            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 -idata.dop-idata.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,fi_stat]#,res,niter
Beispiel #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]