コード例 #1
0
ファイル: calcSat.py プロジェクト: SteveFurnival/PVTfree
def boundTsat(pRes,Z,clsEOS,clsIO) :

    if clsIO.Deb["TSAT"] > 0 :
        qDeb = True
        fDeb = clsIO.fDeb
    else :
        qDeb = False

#== Limiting Values ===================================================

    qSat = True

    tMax = 2500.0
    tMin =  200.0

    iMax,trMx,Kmax = CS.twoSidedStabTest(qSat,pRes,tMax,Z,clsEOS,clsIO)
    iMin,trMn,Kmin = CS.twoSidedStabTest(qSat,pRes,tMin,Z,clsEOS,clsIO)

    n2SC = 2

    if qDeb :
        sOut = "boundTsat: iMax,iMin,trMn {:2d} {:2d} {:10.3e}\n".format(iMax,iMin,trMn)
        fDeb.write(sOut)

#-- Test limiting values --------------------------------------------

    if iMax > 0 :
        print("Fluid at (Pres,Tres) = ({:10.3f},{:8.3f}) is 2-Phase: No-Psat".format(pRes,tMax))
        iTyp = -1
        logK = NP.zeros(clsEOS.nComp)
        return tMin,tMax,logK
      
#----------------------------------------------------------------------
#  Interval Halving
#----------------------------------------------------------------------

    tInt = 0.5*(tMin + tMax)

    while abs(tMax - tMin) > 100.0 :

        iTyp,triV,K = CS.twoSidedStabTest(qSat,pRes,tInt,Z,clsEOS,clsIO)

        n2SC += 1

        if qDeb :
            sOut = "iTyp,pRes,tMin,tInt,triV,tMax {:2d} {:10.3f} {:10.3f} {:10.3f} {:10.3e}{:10.3f}\n".format(iTyp,pRes,tMin,tInt,triV,tMax)
            fDeb.write(sOut)

        if iTyp > 0 :
            tMin = tInt
            logK = NP.log(K)
        else        :
            tMax = tInt

        tInt = 0.5*(tMin + tMax)

#== Return values =====================================================

    return tMin,tMax,logK
コード例 #2
0
ファイル: calcSat.py プロジェクト: SteveFurnival/PVTfree
def rescuePsat(qBub,p2PH,p1PH,tRes,Z,clsEOS,clsIO) :

    if clsIO.Deb["PSAT"] > 0 :
        qDeb = True
        fDeb = clsIO.fDeb
    else :
        qDeb = False

#== Using interval halfing ============================================

    pSat = 0.5*(p2PH+p1PH)
    qSat = True

    while abs(p1PH-p2PH) > 0.001 :

        iTyp,triV,K = CS.twoSidedStabTest(qSat,pSat,tRes,Z,clsEOS,clsIO)

        if iTyp == 0 :
            p1PH = pSat
        else         :
            p2PH = pSat
            logK = NP.log(K)

        pSat = 0.5*(p2PH+p1PH)

#== Return arguments ==================================================    
        
    return p2PH,logK
コード例 #3
0
ファイル: calcGrad.py プロジェクト: SteveFurnival/PVTfree
def calcTopBottom(zTyp, dDep, pDep, tRes, zDep, fRef, clsEOS, clsIO):

    nCom = clsEOS.nComp
    qSat = True
    qBub = None
    pSat = None

    #-- Calculate a Pressure & Composition at Bottom Depth --------------

    pDep, zDep = calcStepGRD(dDep, pDep, tRes, zDep, fRef, clsEOS, clsIO)

    #-- Is the new Composition Stable? ----------------------------------

    iDep, depT, kDep = CT.twoSidedStabTest(qSat, pDep, tRes, zDep, clsEOS,
                                           clsIO)

    #-- Unstable?  Re-Initialise and Calculate New Bottom Composition & Pressure

    if iDep > 0:

        if iDep == 1:  #-- Liquid-Like Fluid Unstable
            zDep = kDep / zDep
        elif iDep == 2:  #-- Vapour-Like Fluid Unstable
            zDep = kDep * zDep
        else:
            print("Search at " & zTyp
                  & " Depth Returned Unstable Fluid with iStab = 3")
            crash = 1.0 / 0.0

        zDep = UT.Norm(zDep)

        pDep, zDep = calcStepGRD(dDep, pDep, tRes, zDep, fRef, clsEOS, clsIO)

        logK = NP.log(kDep)

    else:
        logK = NP.zeros(nCom)

#== Now Calculate the Saturation Pressure at this Depth ===============

    clsWRK = AD.classSample("GRDwrk")
    clsWRK.setIntComp(nCom, nCom)

    for iC in range(nCom):
        clsWRK.sZI(iC, zDep[iC])

    qSat, pSat, Ksat = CS.calcPsat(pDep, tRes, qBub, pSat, logK, clsEOS,
                                   clsWRK, clsIO)

    #print("calcTopBottom: dDep,pDep,iDep,qSat,pSat ",dDep,pDep,iDep,qSat,pSat)

    #== Return Values =====================================================

    return pDep, zDep, qSat, pSat
コード例 #4
0
ファイル: calcSat.py プロジェクト: SteveFurnival/PVTfree
def searchOnePhase(qBub,pInc,pRes,tRes,Z,clsEOS,clsIO) :

    q1PH = False
    qSat = True

#----------------------------------------------------------------------
#  Increment upward until we find 1-Phase state
#----------------------------------------------------------------------

    while not q1PH :

        iTyp,triV,K = CS.twoSidedStabTest(qSat,pRes,tRes,Z,clsEOS,clsIO)

        if iTyp == 0 : break
        else         : pRes = pRes + pInc

#== Return value ======================================================

    return pRes
コード例 #5
0
ファイル: calcSat.py プロジェクト: SteveFurnival/PVTfree
def searchTwoPhase(qBub,pInc,pRes,tRes,Z,clsEOS,clsIO) :

    iTyp = 0
    qSat = True

#----------------------------------------------------------------------
#  Increment downward (in pressure) until we find 2-Phase state
#----------------------------------------------------------------------

    while iTyp == 0 :

        iTyp,triV,K = CS.twoSidedStabTest(qSat,pRes,tRes,Z,clsEOS,clsIO)

        if iTyp > 0 : break
        else        : pRes = pRes - pInc

#== Return Information ================================================

    logK = NP.log(K)

    return iTyp,pRes,logK
コード例 #6
0
def calcFlash(pRes,tRes,Z,vEst,clsEOS,clsIO) :

    if clsIO.Deb['FLASH'] > 0 :
        qDeb = True
        fDeb = clsIO.fDeb
    else                      :
        qDeb = False

    nCom = clsEOS.nComp
    #mFLS = 101
    mFLS = 13           #-- SS/GDEM for max-13 steps, then BFGS
    qSat = False

    iLiq =  1 ; iVap = -1

#-- Work arrays to hold residuals/GDEM ------------------------------

    res0 = NP.zeros(nCom)
    res1 = NP.zeros(nCom)
    res2 = NP.zeros(nCom)

#-- Check if we have an unstable solution at (P,T): get K-Values ----

    iTyp,triV,K = CS.twoSidedStabTest(qSat,pRes,tRes,Z,clsEOS,clsIO)

    if qDeb :
        sOut = "calcFlash: tRes,pRes,iTyp {:10.3f} {:10.3f} {:2d}\n".format(tRes,pRes,iTyp)
        fDeb.write(sOut)
        WO.writeArrayDebug(fDeb,K,"Post-2SidedStab: K")

    if iTyp == 0 :
        #print("Fluid at (P,T) = ({:8.1f},{:8.2f}) is Single-Phase".format(pRes,tRes))
        V = -1.0 ; K = NP.ones(nCom) ; X = Z ; Y = Z
        return V,K,X,Y

#-- Will work with log(K) -------------------------------------------    

    logK = NP.log(K)

#======================================================================
#  Main Iterative Loop
#======================================================================

    iFLS =  0 ; iCut =  0 ; icSS = 0
    
    qPro = False ; qCon = False ; qTrv = False

    V = vEst

    while iFLS < mFLS :

        iFLS += 1 ; icSS += 1
    
#== Call the RR-Solver ================================================

        V,X,Y = solveRR(Z,K,V)

#== Calculate the 2-Phase Gibbs Free Energy (GFE) and dG/d(Liq Moles) =        

        gfe2,dGdL = calcGFE2(pRes,tRes,V,X,Y,clsEOS)

#== If last step was GDEM, ensure GFE has been reduced and V bounded ==

        qUPD = True

        if qPro :   #-- Last step was promoted, check required!

            if V >= 0.0 and V <= 1.0 :          #-- 0 < V < 1: Flash Physical
                if gfe2 > lstG : qCut = True    #-- but GFE has increased
                else           : qCut = False   #-- OK
            else : qCut = True                  #-- Negative Flash Teritory

            qPro = False

#----------------------------------------------------------------------
#  Cut Step [-ve Flash or GFE increased) or Just Take SS
#  In Newton (or Newton-Like) Scheme, Would Do Line Seach Here
#  but would need dG/dlnKi and we only have dG/dnLi
#  As SS+GDEM, Just Half the Proposed Step, But Only 3 Times (1/8th step)
#  Why 4?  Seems to Work!!
#----------------------------------------------------------------------

            if qCut :
                iCut += 1
                if iCut < 4 :
                    #print("Promotion Step Halved: iCut ",iCut)
                    iFLS -= 1 ; icSS -= 1
                    dlnK = 0.5*dlnK
                    logK = logK - dlnK
                    K    = NP.exp(logK)
                else :
                    logK = logK - dlnK  #-- Remove the last of the Update
                    logK = logK + res0  #-- And make conventional SS
                    K    = NP.exp(logK)
                    
                qUPD  = False

#== Updates, Tolerance, Triviality Test, if allowed ===================

        if qUPD :

            res2 = res1        #-- Store previous two steps for GDEM
            res1 = res0
            res0 = dGdL        #-- dG/dnLi = dlnKi
            
            tolR = NP.dot(res0,res0)    #-- W&B Eqn.(4.30)
            triV = NP.dot(logK,logK)    #-- W&B Eqn.(4.51)

            if tolR < 1.0E-11 :   #-- 1E-13 hard to achieve!
                qCon = True
                break

            if triV < 1.0E-04 :
                qTrv = True
                break

#-- GDEM or Regular-SS step? ----------------------------------------

            lstG = gfe2  #-- Store 'last' GFE in case GDEM makes increase

            if icSS % UT.mGDEM2 > 0 :
                qPro = False
                logK = logK + res0    #-- W&B Eqn.(4.48)
                K    = NP.exp(logK)
            else :
                qPro,logK,K,dlnK = GDEM2(tolR,triV,res0,res1,res2,logK,clsIO)
                icSS = 0
                iCut = 0

#== End of Main Loop ==================================================                

        if qDeb :
            sOut = "calcFlash: I,gfe2,tolR,triV,V {:2d},{:10.3e},{:10.3e},{:10.3e},{:10.3e}\n".format(iFLS,gfe2,tolR,triV,V)
            fDeb.write(sOut)

#== K-Values, Vapour Fraction and Liquid/Vapour Mole Fractions ========        

    K = NP.exp(logK)            #-- K-Values

    V,X,Y = solveRR(Z,K,V)      #-- Solve RR for V,X & Y
    
#======================================================================
#  Not Converged and not trivial, try to finish off with BFGS
#======================================================================

    if not qCon and not qTrv :
        V,K,X,Y = calcFlashBFGS(pRes,tRes,Z,V,X,Y,clsEOS)

#======================================================================
#  End of Routine: Return Values
#======================================================================

    return V,K,X,Y
コード例 #7
0
ファイル: calcSat.py プロジェクト: SteveFurnival/PVTfree
def sweepPsatNoData(qBub,tRes,Z,clsEOS,clsIO) :

    iTyp,p2PH,p1PH,logK = boundPsat(tRes,Z,clsEOS,clsIO)

    if clsIO.Deb["PSAT"] > 0 :
        qDeb = True
        fDeb = clsIO.fDeb
    else :
        qDeb = False

    logK = NP.zeros(clsEOS.nComp)

    if qBub : iFed =  1     #-- Feed is Likely a Liquid
    else    : iFed = -1     #             Else a Vapour
        
#== Pressure Limits and # Increments ==================================

    pMIN =    10.0
    pMAX = 15010.0
    nINC = 15

#== set pSat = pMIN and calculate Increment ===========================

    pSat =  pMIN
    pINC = (pMAX - pSat)/float(nINC)
    p1PH = -1.0

#======================================================================
#  Increment in pressure until we find 1-Phase State
#======================================================================

    qSat = True

    for iStep in range(nINC+1) :

#== Can we split of another composition at this pressure? =============
        
        iThs,tThs,Kths = CS.twoSidedStabTest(qSat,pSat,tRes,Z,clsEOS,clsIO)

        if iThs > 0 : i2PH = 2
        else        : i2PH = 1

        if qDeb :
            sOut = "pSat,tRes,i2PH {:10.3f} {:8.3f} {:1d}\n".format(pSat,tRes,i2PH)
            fDeb.write(sOut)
   
        if iThs > 0 :
            iTyp = iThs
            p2PH = pSat
            logK = NP.log(Kths)
        else        :
            p1PH = pSat
            break
            
#== Increment pSat estimator and repeat ===============================
                
        pSat = pSat + pINC

#== Return Information ================================================    

    return iTyp,p2PH,p1PH,logK
コード例 #8
0
ファイル: calcSat.py プロジェクト: SteveFurnival/PVTfree
def boundPsat(tRes,Z,clsEOS,clsIO) :

    if clsIO.Deb["PSAT"] > 0 :
        qDeb = True
        fDeb = clsIO.fDeb
    else :
        qDeb = False

#== Limiting Values ===================================================

    qSat = True

    pMax = 15010.0
    pMin =    10.0

    iMax,trMx,Kmax = CS.twoSidedStabTest(qSat,pMax,tRes,Z,clsEOS,clsIO)
    iMin,trMn,Kmin = CS.twoSidedStabTest(qSat,pMin,tRes,Z,clsEOS,clsIO)

    n2SC = 2

    #print("boundPsat: iMax,iMin,trMn {:2d} {:2d} {:10.3e}".format(iMax,iMin,trMn))

#-- Test limiting values --------------------------------------------

    if iMax > 0 :
        print("Fluid at (Pres,Tres) = ({:10.3f},{:8.3f}) is 2-Phase: No-Psat".format(pMax,tRes))
        iTyp = -1
        logK = NP.zeros(clsEOS.nComp)
        return iTyp,pMin,pMax,logK
      
#----------------------------------------------------------------------
#  Interval Halving
#----------------------------------------------------------------------

    pInt = 0.5*(pMin + pMax)
    qLog = False

    while abs(pMax - pMin) > 100.0 :

        iTyp,triV,K = CS.twoSidedStabTest(qSat,pInt,tRes,Z,clsEOS,clsIO)

        n2SC += 1

        #print("iTyp,pMin,pInt,triV,pMax {:2d} {:10.3f} {:10.3f} {:10.3e} {:10.3f}".format(iTyp,pMin,pInt,triV,pMax))

        if iTyp > 0 :
            pMin = pInt
            logK = NP.log(K)
            qLog = True
        else        :
            pMax = pInt

        pInt = 0.5*(pMin + pMax)

#-- Ensure logK array is defined ------------------------------------        

    if not qLog : logK = NP.zeros(clsEOS.nComp)

#== Return values =====================================================

    return iTyp,pMin,pMax,logK