示例#1
0
def calcFugDerv(qBub,pSat,tRes,Z,logK,clsEOS) :

    iPhs = 0  #-- Force cubic solver to pick root with lowest GFE

    qP = True       #-- Don't Need Temp or Comp Derivatives, Just Pres
    qT = False
    qX = False
    
#-- Incipient Phase -------------------------------------------------        

    K    = NP.exp(logK)
    yMol = Z*K              #-- Vector!

#-- Get Fugacity Coeffs and their Pressure-Derivatives --------------

    yNor = UT.Norm(yMol)
        
    fugZ,dZdP,dumV,dumM = CE.calcPhaseFugPTX(iPhs,qP,qT,qX,pSat,tRes,Z   ,clsEOS)
    fugY,dYdP,dumV,dumM = CE.calcPhaseFugPTX(iPhs,qP,qT,qX,pSat,tRes,yNor,clsEOS)

#== Residual and Derivative Difference ================================

    res0 = fugZ - fugY - logK   #-- Vector!
    dFdP = dYdP - dZdP          #-- Vector!

#== Calculate tol2 =====================================================

    tol2 = calcTOL2(logK,res0)

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

    return tol2,yMol,res0,dFdP
示例#2
0
def flashFuncDervBFGS(AorB,qAlf,pRes,tRes,Z,clsEOS) :

    nCom = clsEOS.nComp

    qP = False      #-- Don't need P, T or X LogPhi Derivatives
    qT = False
    qX = False

    iLiq = 1 ; iVap = -1

#== Calculate Vapour Fraction, Liquid & Vapour Moles ==================

    if qAlf : sumV,niL,niV = calcLiqVapMoles(Z,AorB)
    else    : sumV,niL,niV = calcVapLiqMoles(Z,AorB)

#== Mole Fractions of Liquid and Vapour ===============================

    X,Y = molNumToMolFrac(sumV,niL,niV)

    Xmin = 1.0E-20
    
    X = NP.maximum(X,Xmin)
    Y = NP.maximum(Y,Xmin)

    logX = NP.log(X)
    logY = NP.log(Y)

#== Log Fugacity Coefficients =========================================    

    fugX,dumV,dumV,dumM = CE.calcPhaseFugPTX(iLiq,qP,qT,qX,pRes,tRes,X,clsEOS)
    fugY,dumV,dumV,dumM = CE.calcPhaseFugPTX(iVap,qP,qT,qX,pRes,tRes,Y,clsEOS)

#== Liquid and Vapour GFE =============================================

    logX = logX + fugX  #-- Vector!
    logY = logY + fugY  #-- Vector!

    gfeL = NP.dot(niL,logX)
    gfeV = NP.dot(niV,logY)

#== Total (2-Phase) GFE ===============================================

    gfeT = gfeL + gfeV

#== Gradient Vector (in alfa-space) ===================================

    grad = logX - logY  #-- Vector!

    aMul = NP.sqrt(niL*niV/Z)

    if qAlf : gMul =  1.0
    else    : gMul = -1.0

    Grad = gMul*NP.multiply(aMul,grad)  #-- Equation (3.197)

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

    return gfeT,Grad
示例#3
0
def calcF1F2(pRes, tRes, zRef, lnKref, alfa, iDer, clsEOS, clsIO):

    nCom = clsEOS.nComp
    iLiq = 0
    qXD = False

    #== Calculate the Incipient Phase Composition =========================

    yMol, yNor = incipientY(alfa, zRef, lnKref, clsEOS, clsIO)

    #== Fugacity and its Pressure-Derivatives (if required) ===============

    if iDer == 1:
        qPD = True
        qTD = False
    elif iDer == -1:
        qPD = False
        qTD = True
    else:
        qPD = False
        qTD = False

    fugZ, dZdP, dZdT, dumM = CE.calcPhaseFugPTX(iLiq, qPD, qTD, qXD, pRes,
                                                tRes, zRef, clsEOS)
    fugY, dYdP, dYdT, dumM = CE.calcPhaseFugPTX(iLiq, qPD, qTD, qXD, pRes,
                                                tRes, yNor, clsEOS)

    #== Calculate Functions ===============================================

    f1 = 0.0
    f2 = 0.0
    eD = 0.0

    fR = NP.log(yNor) + fugY - NP.log(zRef) - fugZ  #-- Vector

    f1 = NP.dot(yNor, fR)
    f2 = NP.dot(zRef, fR)

    fR = NP.multiply(fR, fR)
    eD = NP.dot(zRef, fR)

    df1dX = 0.0
    df2dX = 0.0

    if iDer == 1:
        pDiff = dYdP - dZdP  #-- Vector
        df1dX = NP.dot(yNor, pDiff)
        df2dX = NP.dot(zRef, pDiff)
    elif iDer == -1:
        tDiff = dYdT - dZdT  #-- Vector
        df1dX = NP.dot(yNor, tDiff)
        df2dX = NP.dot(zRef, tDiff)

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

    return f1, f2, eD, df1dX, df2dX
示例#4
0
def calcGFE2(pRes,tRes,V,X,Y,clsEOS) :

    iLiq =  1
    iVap = -1

    qP = False  #-- Don't need Pres, Temp or Comp LogPhi Derivatives
    qT = False
    qX = False

    xyMin = 1.0E-20

#-- Liquid Moles ----------------------------------------------------

    L = 1.0 - V

#-- Protect against zero (X,Y) --------------------------------------

    X = NP.maximum(X,xyMin)
    Y = NP.maximum(Y,xyMin)

#-- Log Mole Fractions ----------------------------------------------

    logX = NP.log(X)
    logY = NP.log(Y)

#-- Liquid and Vapour Log(Fugacity) Coefficients --------------------

    fugX,dumV,dumV,dumM = \
        CE.calcPhaseFugPTX(iLiq,qP,qT,qX,pRes,tRes,X,clsEOS)
    fugY,dumV,dumV,dumM = \
        CE.calcPhaseFugPTX(iVap,qP,qT,qX,pRes,tRes,Y,clsEOS)

#-- Log Mole Fractions now become 'Chemical Potential' --------------

    logX = logX + fugX  #-- Vector!
    logY = logY + fugY  #-- Vector!

#== 2-Phase GFE =======================================================

    gfeL = NP.dot(X,logX)
    gfeV = NP.dot(Y,logY)

    gfe2 = L*gfeL + V*gfeV

#== Gradient (wrt Liquid Moles) =======================================

    dGdL = logX - logY  #-- Vector!

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

    return gfe2,dGdL
示例#5
0
def setupCalcGRDCoefsP(iLiq, pRes, tRes, XY, clsEOS):

    nCom = clsEOS.NC
    iPhs = 0
    pByT = pRes / tRes

    qP = True  #-- Onlt want Pres-derivatives, not Temp or Comp
    qT = False
    qX = False

    #-- Calculate the log(Fugacity) Coefficients ------------------------

    FiC, FiP, dumV, dumX = CE.calcPhaseFugPTX(iPhs, qP, qT, qX, pRes, tRes, XY,
                                              clsEOS)

    #-- EoS B[i] Coefficients -------------------------------------------

    BiC = pByT * clsEOS.bI

    #== Augment with the Volume Shift Parameters ==========================

    for iC in range(nCom):

        cCor = BiC[iC] * clsEOS.gPP("SS", iC)  #-- bi*p/(RT)*si = Bi*si

        FiC[iC] = pRes * XY[iC] * exp(FiC[iC])  #-- log(phi) -> Fugacity
        FiP[iC] = FiC[iC] * (FiP[iC] + 1.0 / pRes)  #-- dFug/dP

        FiC[iC] = FiC[iC] * exp(-cCor)  #-- Volume Shift Corr
        FiP[iC] = FiP[iC] * exp(-cCor) * (1.0 - cCor / pRes
                                          )  #-- Volume Shift Corr

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

    return FiC, FiP
示例#6
0
    def stabMini(self, alfa, *args):

        iLiq = 0

        qP = False  #-- No Pres, Temp or Comp Derivatives Needed
        qT = False
        qX = False

        #== Unpack the arguments in *args =====================================

        pRes = args[0]
        tRes = args[1]
        Z = args[2]
        h = args[3]
        clsEOS = args[4]

        #== Un-Normalised & Normalised Mole Fractions =========================

        Y = 0.25 * alfa * alfa

        y, SY = UT.NormSum(Y)

        #-- log(fugacity) coefficients of Trial phase -----------------------

        fugY,dumV,dumV,dumM = \
            CE.calcPhaseFugPTX(iLiq,qP,qT,qX,pRes,tRes,y,clsEOS)

        #== Gstar and Gradient-Vector =========================================

        logY = NP.log(Y)  #-- Vector
        dGdY = logY + fugY - h  #-- Vector

        gStr = 1.0 - SY + NP.dot(Y, dGdY)  #-- Michelsen Eqn.(14)

        dGda = 0.5 * alfa * dGdY  #-- Michelsen Eqn.(25)

        #== Michelsen Approach to Triviality: Eqn.(23) & (24) =================

        YmZ = Y - Z
        beta = NP.dot(YmZ, dGdY)
        r = 2.0 * gStr / beta

        if gStr < 1.0E-3 and abs(r - 1.0) < 0.2: self.isTriv = True

        #print("gStr,r,Triv {:10.3e} {:10.3e} {:d}".format(gStr,r,self.isTriv))

        #== Return function and its derivative (as tuple) =====================

        return gStr, dGda
示例#7
0
def setupCalcGRDCoefsP(iLiq, pRes, tRes, XY, clsEOS):

    nCom = clsEOS.nComp
    iPhs = 0
    pByT = pRes / tRes
    recP = 1.0 / pRes

    qP = True  #-- Onlt want Pres-derivatives, not Temp or Comp
    qT = False
    qX = False

    #-- Calculate the log(Fugacity) Coefficients ------------------------

    f2, f2P, dumV, dumX = CE.calcPhaseFugPTX(iPhs, qP, qT, qX, pRes, tRes, XY,
                                             clsEOS)

    f2X = NP.exp(f2)  #-- Vec: exp(lnPhi)

    #-- EoS B[i] Coefficients -------------------------------------------

    BI = pByT * clsEOS.bI  #-- Vec: Bi*(p/RT)

    cI = BI * clsEOS.vS  #-- Vec: Ci = si*Bi
    XI = NP.exp(cI)  #-- Vec: exp(Ci)

    cIP = cI * recP  #-- Vec: Ci/p

    #== 3-Parameter Fugacity and its P-Derivative =========================

    f3 = pRes * XY * f2X * XI  #-- Vec: p*xi*exp(lnPhi)*exp(Ci)

    f3P = recP + f2P + cIP

    f3P = f3 * f3P

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

    return f3, f3P
示例#8
0
def twoSidedStabCheck(qSat, pRes, tRes, Z, clsEOS, clsIO):

    nCom = clsEOS.nComp

    qP = False  #-- No Pres, Temp or Comp Derivatives Needed
    qT = False
    qX = False

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

#-- Feed Log(Fugacity) Coefficients ---------------------------------

    iLiq = 0
    fugZ,dumV,dumV,dumM = \
        CE.calcPhaseFugPTX(iLiq,qP,qT,qX,pRes,tRes,Z,clsEOS)

    #-- Wilson K-Values -------------------------------------------------

    wilK = UT.wilsonK(pRes, tRes, clsEOS)

    #-- Trial Compositions ----------------------------------------------

    lnKV = NP.log(wilK)
    lnKL = -lnKV

    #-- Assume Feed is Liquid, Try to Split-Off Vapour ------------------

    iVap = -1
    iSTV,sumV,gVap,tolV,triV,lnKV = \
        oneSidedStabCheck(iVap,pRes,tRes,Z,fugZ,lnKV,clsEOS,clsIO)

    qVap = gVap < 0.0 and triV > 1.0E-04

    if qDeb:
        sOut = "Vap-Like Split: pRes,tRes,iSTV,gVap,tolV,triV {:10.3f} {:8.3f} {:3d} {:10.3e} {:10.3e} {:10.3e}\n".format(
            pRes, tRes, iSTV, gVap, tolV, triV)
        fDeb.write(sOut)
        #KV = NP.exp(lnKV)
        #WO.writeArrayDebug(fDeb,KV,"twoSidedStab: Wilson-KV")

#-- Assume Feed is Liquid, Try to Split-Off Vapour ------------------

    iLiq = 1
    iSTL,sumL,gLiq,tolL,triL,lnKL = \
        oneSidedStabCheck(iLiq,pRes,tRes,Z,fugZ,lnKL,clsEOS,clsIO)

    qLiq = gLiq < 0.0 and triL > 1.0E-04

    if qDeb:
        sOut = "Liq-Like Split: pRes,tRes,iSTL,gLiq,tolL,triL {:10.3f} {:8.3f} {:3d} {:10.3e} {:10.3e} {:10.3e}\n".format(
            pRes, tRes, iSTL, gLiq, tolL, triL)
        fDeb.write(sOut)
        #KL = NP.exp(lnKL)
        #WO.writeArrayDebug(fDeb,KL,"twoSidedStab: Wilson-KL")

#== Process the 1-Sided Tests =========================================

#print("2Stab: pRes,tRes,gLiq,triL,gVap,triV {:10.3f} {:8.3f} {:10.3e} {:10.3e} {:10.3e} {:10.3e}".format(pRes,tRes,gLiq,triL,gVap,triV))

    if qLiq and qVap:

        difK = lnKL - lnKV  #-- Vector
        triV = NP.dot(difK, difK)

        if triV > 1.0E-04:  #-- Are the solutions distinct?
            iTyp = -3
            if qSat:
                if gLiq < gVap:  #-- Called from Psat  - Liquid Lower-GFE
                    bstK = NP.exp(lnKL)
                    bstT = triL
                    iTyp = -1
                else:  #-- Called from Psat  - Vapour Lower-GFE
                    bstK = NP.exp(lnKV)
                    bstT = triV
                    iTyp = -2
            else:  #-- Called from Flash - Take Ratio
                bstK = NP.exp(difK)
                bstT = 0.0
        elif lnKV[nCom - 1] < 0.0:  #-- logK-Vap 'Right' Way-Up
            iTyp = -2
            bstK = NP.exp(lnKV)
            bstT = triV
        else:  #-- LogK-Liq must be 'Right' Way-Up
            iTyp = -1
            bstK = NP.exp(lnKL)
            bstT = triL

    elif qVap:  #-- Only Vapour-Like Unstable
        iTyp = 2
        bstK = NP.exp(lnKV)
        bstT = triV
    elif qLiq:  #-- Only Liquid-Like Unstable
        iTyp = 1
        bstK = NP.exp(lnKL)
        bstT = triL
    else:  #-- Is Stable 1-Phase at this (p,T)
        iTyp = 0
        bstK = NP.zeros(nCom)
        bstT = 0.0

#== Ensure the K-Values are the "Right" Way Up ========================

    if not qSat and bstK[nCom - 1] > 1.0:
        bstK = NP.divide(1.0, bstK)
        #print("Stab2S: Flipped K-values at iTyp,pRes,tRes {:2d} {:10.3f} {:8.3f}".format(iTyp,pRes,tRes))

    iTyp = abs(iTyp)

    return iTyp, bstT, bstK
示例#9
0
def stab2SidedBFGS(qSat, pRes, tRes, Z, clsEOS, clsIO):

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

    nCom = clsEOS.nComp

    qP = False  #-- No Pres, Temp or Comp Derivatives Needed
    qT = False
    qX = False

    iNeu = 0
    iLiq = 1
    iVap = -1

    #-- Feed Log(Fugacity) Coefficients ---------------------------------

    fugZ,dumV,dumV,dumM = \
        CE.calcPhaseFugPTX(iNeu,qP,qT,qX,pRes,tRes,Z,clsEOS)

    hVec = NP.log(Z) + fugZ  #-- Vector!

    #-- Wilson K-Values -------------------------------------------------

    wilK = UT.wilsonK(pRes, tRes, clsEOS)

    #-- Trial Compositions ----------------------------------------------

    yVap = Z * wilK  #-- Vector: Vapour-Like Trial
    yLiq = Z / wilK  #-- Vector: Liquid-Like Trial

    #== Create (lower,upper) bounds for the alpha's =====================

    bndA = []
    for iC in range(nCom):
        bndA.append((1.0E-20, None))

    #== Test SciPy Minimize Routine =====================================

    aVap = 2.0 * NP.sqrt(yVap)

    qConV, yVap = stabDriv(iVap, aVap, bndA, pRes, tRes, Z, hVec, clsEOS)

    aLiq = 2.0 * NP.sqrt(yLiq)

    qConL, yLiq = stabDriv(iLiq, aLiq, bndA, pRes, tRes, Z, hVec, clsEOS)

    #print("qConL,yLiq ",qConL,yLiq)
    #print("qConV,yVap ",qConL,yVap)

    #== Process the 1-Sided Tests =========================================

    if qConL and qConV:

        #-- If both trials unstable, take ratio unless they are the same ----

        iTyp = 3
        bstK = yVap / yLiq

        qSam = True
        for iC in range(nCom):
            if abs(bstK[iC] - 1.0) > 1.0E-03:
                qSam = False
                break

        if qSam:
            #print("iTyp=3 and All K = 1")
            if gStrV < gStrL: bstK = yVap / Z  #-- Vector
            else: bstK = Z / yLiq  #-- Vector

    elif qConV:
        iTyp = 2
        bstK = yVap / Z
    elif qConL:
        iTyp = 1
        bstK = Z / yLiq
    else:
        iTyp = 0
        bstK = NP.ones(nCom)

#== Ensure the K-Values are the "Right" Way Up ========================

    if bstK[nCom - 1] > 1.0: bstK = 1.0 / bstK  #-- Vector

    if qDeb: fDeb.write("Stab2: iTyp " + str(iTyp) + "\n")

    bstT = 0.0

    return iTyp, bstT, bstK
示例#10
0
def oneSidedStabCheck(iPhs, pRes, tRes, Z, fugZ, logK, clsEOS, clsIO):

    mSTB = 101
    nCom = clsEOS.nComp

    qP = False  #-- No Pres, Temp or Comp Derivatives Needed
    qT = False
    qX = False

    res0 = NP.zeros(nCom)

    iSTB = 0

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

    if qDeb > 0:
        sOut = "1-Sided SC at pRes,tRes {:10.3f} {:8.3f}\n".format(pRes, tRes)
        K = NP.exp(logK)
        WO.writeArrayDebug(fDeb, K, "1SidedStab: K")
        WO.writeArrayDebug(fDeb, Z, "1SidedStab: Z")
        fDeb.write(sOut)

#== Successive Substitution/GDEM Loop =================================

    while iSTB < mSTB:

        iSTB += 1

        #-- Mole Numbers ----------------------------------------------------

        K = NP.exp(logK)
        yMol = Z * K

        #-- Mole composition (normalised) -----------------------------------

        yNor, sumY = UT.NormSum(yMol)

        fugY,dumV,dumV,dumM = \
            CE.calcPhaseFugPTX(iPhs,qP,qT,qX,pRes,tRes,yNor,clsEOS)

        gStr = 1.0 - sumY

        #-- Residuals -------------------------------------------------------

        res1 = res0
        res0 = fugZ - fugY - logK

        tolR = NP.dot(res0, res0)
        gStr = gStr - NP.dot(yMol, res0)

        #-- GDEM Step? ------------------------------------------------------

        if iSTB % UT.mGDEM1 > 0: eigV = 1.0
        else: eigV = UT.GDEM1(res0, res1, clsIO)

        if eigV < 1.0: eigV = 1.0

        #-- Update logK with/without GDEM Acceleration ----------------------

        eVr0 = eigV * res0
        logK = logK + eVr0

        triV = NP.dot(logK, logK)

        if qDeb:
            sOut = "Stab1S: iSTB,sumY,gStr,tolR,triV,eigV {:3d} {:10.3e} {:10.3e} {:10.3e} {:10.3e} {:8.4f}\n" \
               .format(iSTB,sumY,gStr,tolR,triV,eigV)
            fDeb.write(sOut)
            #K = NP.exp(logK)
            #WO.writeArrayDebug(fDeb,K,"1SidedStab: K")

#-- Trivial or Converged? -------------------------------------------

        if triV < 1.0E-04:
            break
        elif tolR < 1.0E-12:
            break

#== Return the Gstar ==================================================

    if qDeb > 0:
        WO.writeArrayDebug(fDeb, K, "End 1S-SC: K")

    return iSTB, sumY, gStr, tolR, triV, logK
示例#11
0
def calcPsatBFGS(pEst,tRes,Z,clsEOS,clsIO) :

    nCom = clsEOS.nComp
    iNeu = 0

#-- Minimum and Maximum Pressure(in psia) to consider for Psat ------    

    p2PH =    10.0
    p1PH = 15010.0

#== The Sat-Type probably depends on the mol% of C7+ ==================

    mC7P = UT.moleFracC7P(Z,clsEOS)

    print("calcPsatBFGS: mC7P {:8.5f}".format(mC7P))

    if mC7P > 0.125 :   #-- Volatile oils have z(C7+) > 12.5%
        qBub = True
        iLiq =  1
        iVap = -1
    else :              #-- Else is Gas Condensate
        qBub = False
        iLiq = -1
        iVap =  1

    print("iLiq,iVap ",iLiq,iVap)

#== Initialise pSat and Liq/Vap Estimates =============================        

#----------------------------------------------------------------------
#  Pre-Sweep using trial Liquid using BFGS Stability Test
#----------------------------------------------------------------------

    qLOK = False
    qVOK = False
    nBel = 0

    pBel = []
    gBel = []

    if pEst == None : pSat = (2.0*p2PH + p1PH)/3.0  #-- Bias towards low-P
    else            : pSat =      pEst

    while (p1PH - p2PH) > 100.0 :

        print("p2PH,pSat,p1PH {:10.3f} {:10.3f} {:10.3f}".format(p2PH,pSat,p1PH))

#-- Wilson-K Values at current (p,T) --------------------------------

        wilK = UT.wilsonK(pSat,tRes,clsEOS)

        if qLOK : yLiq = NP.copy(yLOK)
        else    : yLiq = NP.divide(Z,wilK)
            
        if qVOK : yVap = NP.copy(yVOK)
        else    : yVap = NP.multiply(Z,wilK)
            
#-- Feed Log Fugacity Coefficients ----------------------------------

        fugZ,dumV,dumV,dumM = \
            CE.calcPhaseFugPTX(iNeu,qP,qT,qX,pSat,tRes,Z,clsEOS)

#-- Try to split a Liquid off what is assumed to be Vapour ----------        

        qConL,gStrL,yLiq = \
            stabCheckBFGS(iLiq,pSat,tRes,Z,fugZ,yLiq,clsEOS)

        if qConL :
            qLOK = True
            yLOK = NP.copy(yLiq)

#-- Try to split a Vapour off what is assumed to be Liquid ----------        

        qConV,gStrV,yVap = \
            stabCheckBFGS(iVap,pSat,tRes,Z,fugZ,yVap,clsEOS)

        if qConV :
            qVOK = True
            yVOK = NP.copy(yVap)

#-- Did either trial converge? --------------------------------------

        if qConL or qConV :
            p2PH = pSat
            pBel.append(pSat)
            if   qConL and qConV : gStr = min(gStrL,gStrV)
            elif qConL           : gStr =     gStrL
            elif qConV           : gStr =           gStrV
            gBel.append(gStr)
            nBel += 1
        else              :
            p1PH = pSat

#-- Two or more solutions below gStr = 0 => pSat --------------------

        if nBel >= 2 :
            dPrs = pBel[nBel-1] - pBel[nBel-2]
            dGst = gBel[nBel-1] - gBel[nBel-2]
            grad = dGst/dPrs
            intr = gBel[nBel-1] - pBel[nBel-1]*grad
            pSat = -intr/grad
        else :
            pSat = 0.5*(p2PH + p1PH)
        
    return qBub,pSat
示例#12
0
def refineInTempOnly(betO, pRes, tRes, Z, K, clsEOS):

    nCom = clsEOS.nComp

    iLiq = 1
    iVap = -1

    #-- c-Vector: c = 1/(1-K[i]) ----------------------------------------

    c = calcCvalues(K)
    logK = NP.log(K)

    #== Rachford-Rice Function G(beta) using required beta ================

    G = 0.0
    for iC in range(nCom):
        G = G + Z[iC] / (betO - c[iC])

    #-- Liquid and Vapour Mole Numbers and Mole Fractions ---------------

    X, Y = calcLiqVapMoleFrac(betO, Z, K, c)

    sumX = NP.sum(X)
    sumY = NP.sum(Y)
    recX = 1.0 / sumX
    recY = 1.0 / sumY
    xNor = NP.multiply(recX, X)
    yNor = NP.multiply(recY, Y)

    #-- Liquid and Vapour Fugacities and their P-Derivatives ------------

    qPD = False
    qTD = True
    qXD = False

    fugX, dumV, dXdT, dumM = CE.calcPhaseFugPTX(iLiq, qPD, qTD, qXD, pRes,
                                                tRes, xNor, clsEOS)
    fugY, dumV, dYdT, dumM = CE.calcPhaseFugPTX(iVap, qPD, qTD, qXD, pRes,
                                                tRes, yNor, clsEOS)

    #== Form residual and various sums ====================================

    GF = 0.0
    GFP = 0.0

    fRes = NP.zeros(nCom)
    dfdT = NP.zeros(nCom)

    for iC in range(nCom):

        fRes[iC] = logK[iC] + fugY[iC] - fugX[iC]
        dfdT[iC] = dYdT[iC] - dXdT[iC]

        xyz = xNor[iC] * yNor[iC] / Z[iC]

        GF = GF + xyz * fRes[iC]
        GFP = GFP + xyz * dfdT[iC]

#== Find delP =========================================================

    Grhs = G - GF

    if abs(GFP) > UT.macEPS: delT = Grhs / GFP
    else: delT = 0.0

    #-- If update takes us too far, cut-back ... ------------------------

    if tRes + delT < 0.0: delT = 0.5 * delT

    #print("tRes,Grhs,GFP,delT {:10.3f} {:10.3e} {:10.3e} {:10.3e}".format(tRes,Grhs,GFP,delT))

    tRes = tRes + delT

    #== Calculate d(lnK): Equation (14) ===================================

    for iC in range(nCom):
        dlnK = -fRes[iC] - delT * dfdT[iC]
        logK[iC] = logK[iC] + dlnK

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

    K = NP.exp(logK)
    c = calcCvalues(K)

    return tRes, K, c
示例#13
0
def findVapFracPT(alfa, betO, pRes, tRes, Z, lnKref, clsEOS):

    nCom = clsEOS.nComp

    iLiq = 1
    iVap = -1
    qPD = True
    qTD = True
    qXD = False

    #----------------------------------------------------------------------
    #  Iterate in (P,T)
    #----------------------------------------------------------------------

    fSSQ = 1.0

    while fSSQ > 1.0E-12:

        #== Solve Equation (20) to find theta =================================

        theta, K, c = findTheta(betO, alfa, Z, lnKref)

        #-- Liquid and Vapour Mole Fractions --------------------------------

        X, Y = calcLiqVapMoleFrac(betO, Z, K, c)

        #== Compute the Liquid & Vapour Fugacities and their (P,T)-Derivatives

        fugX, dXdP, dXdT, dumM = CE.calcPhaseFugPTX(iLiq, qPD, qTD, qXD, pRes,
                                                    tRes, X, clsEOS)
        fugY, dYdP, dYdT, dumM = CE.calcPhaseFugPTX(iVap, qPD, qTD, qXD, pRes,
                                                    tRes, Y, clsEOS)

        logX = NP.log(X)
        logY = NP.log(Y)

        #== Residuals and their (P,T)-Derivatives =============================

        dRes = logY + fugY - logX - fugX  #-- Vector
        dPrs = dYdP - dXdP  #-- Vector
        dTem = dYdT - dXdT  #-- Vector

        f1 = NP.dot(Y, dRes)
        f2 = NP.dot(X, dRes)
        df1dP = NP.dot(Y, dPrs)
        df2dP = NP.dot(X, dPrs)
        df1dT = NP.dot(Y, dTem)
        df2dT = NP.dot(X, dTem)

        #== Solve the 2x2 Matrix ==============================================

        dPrs, dTem = solve2x2(f1, f2, df1dP, df1dT, df2dP, df2dT)

        fSSQ = 0.5 * (dPrs * dPrs + dTem * dTem)

        pRes = pRes + dPrs
        tRes = tRes + dTem

        if pRes < 0.0 or tRes < 0.0: break

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

    return pRes, tRes
示例#14
0
def updatePTK(pRes, tRes, Z, Ze, logK, fcP2e, clsEOS, clsIO):

    nCom = clsEOS.nComp

    iNeu = 0
    qPD = True
    qTD = True
    qXD = False

    #-- Trial composition -----------------------------------------------

    K = NP.exp(logK)
    Y = Z * K

    #-- fc+1: Equation (11) ---------------------------------------------

    sumY = NP.sum(Y)
    fcP1 = sumY - 1.0

    #print("sumY {:10.5f}".format(sumY))

    #-- fc+2: Equation (13) ---------------------------------------------

    fcP2 = -fcP2e + NP.dot(Ze, logK)

    #-- Liquid and Vapour Fugacities and their P-Derivatives ------------

    yNor = Y / sumY  #-- Vector

    fugZ, dZdP, dZdT, dumM = CE.calcPhaseFugPTX(iNeu, qPD, qTD, qXD, pRes,
                                                tRes, Z, clsEOS)
    fugY, dYdP, dYdT, dumM = CE.calcPhaseFugPTX(iNeu, qPD, qTD, qXD, pRes,
                                                tRes, yNor, clsEOS)

    #== Construct Jacobian and RHS terms ==================================

    fRes = fugY - fugZ  #-- All Vector Operations
    dfdP = dYdP - dZdP
    dfdT = dYdT - dZdT
    fRes = logK + fRes

    sumf1 = NP.dot(Y, fRes)
    sumf2 = NP.dot(Ze, fRes)
    df1dP = NP.dot(Y, dfdP)
    df2dP = NP.dot(Ze, dfdP)
    df1dT = NP.dot(Y, dfdT)
    df2dT = NP.dot(Ze, dfdT)

    #== RHS-Terms =========================================================

    fcP1 = fcP1 - sumf1
    fcP2 = fcP2 - sumf2

    #== Invert (2x2) Matrix ===============================================

    dPrs, dTem = solve2x2(fcP1, fcP2, df1dP, df1dT, df2dP, df2dT)

    fSSQ = 0.5 * (dPrs * dPrs + dTem * dTem)

    fDeb = clsIO.fDeb

    sOut = "fcP1,fcP2,fSSQ,dPrs,dTem {:10.3e} {:10.3e} {:10.3e} {:10.3e} {:10.3e}\n".\
          format(fcP1,fcP2,fSSQ,dPrs,dTem)
    fDeb.write(sOut)

    #== P,T & logK-Updates ================================================

    pRes = pRes + dPrs
    tRes = tRes + dTem

    for iC in range(nCom):
        dlnK = -fRes[iC] - dPrs * dfdP[iC] - dTem * dfdT[iC]
        sOut = "iC,lnK,dlnK {:2d} {:10.3e} {:10.3e}\n".format(
            iC, logK[iC], dlnK)
        fDeb.write(sOut)
        logK[iC] = logK[iC] + dlnK

#== Return information ================================================

    return fSSQ, pRes, tRes, logK
示例#15
0
def calcTsat(pRes,clsEOS,clsSAM,clsIO) :

    nCom = clsEOS.NC
    mTSA = 101

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

#-- Load Feed Composition -------------------------------------------    

    Z = NP.zeros(nCom)
    
    for iC in range(nCom) : Z[iC] = clsSAM.gZI(iC)
    
#== Pre-Sweep; 2-Phase/1-Phase Temperature Bounds =====================

    t2PH,t1PH,logK = boundTsat(pRes,Z,clsEOS,clsIO)

    tRes = t2PH     #-- This will be our iteration parameter

    if qDeb :
        sOut = "calcTsat: pRes,t2PH,t1PH {:8.3f} {:10.3f} {:10.3f}\n".format(pRes,t2PH,t1PH)
        fDeb.write(sOut)
        K = NP.exp(logK)
        WO.writeArrayDebug(fDeb,K,"Post-boundTsat: K")

#----------------------------------------------------------------------
#  Main Iterative Loop
#----------------------------------------------------------------------

    iTSA = 0
    iPhs = 0
    qPD  = False
    qTD  = True
    qXD  = False

    K    = NP.exp(logK)
    yMol = Z*K

    while iTSA < mTSA :

        iTSA += 1

        if iTSA > 1 : res1 = res0  #-- Copy 'last' residual for GDEM

#== Log Fug Coefs and their T-derivatives for Feed and Trial Phase ====

        fugZ,dZdP,dZdT,dumM = CE.calcPhaseFugPTX(iPhs,qPD,qTD,qXD,pRes,tRes,Z,clsEOS)

#-- Get Normalised Trial Composition --------------------------------

        yNor = UT.Norm(yMol)

        fugY,dYdP,dYdT,dumM = CE.calcPhaseFugPTX(iPhs,qPD,qTD,qXD,pRes,tRes,yNor,clsEOS)

#== Residual and Derivative Difference ================================

        res0 = fugZ - fugY - logK   #-- Vector
        dFdT = dYdT - dZdT          #-- Vector

#== Calculate tol2 =====================================================

        tol2 = calcTOL2(logK,res0)

        resX = NP.exp(res0)

#== Is this a GDEM Step?  If so, calculate Single Eigenvalue ==========            

        if iTSA % CO.mGDEM1 > 0 : eigV = 1.0
        else                    : eigV = UT.GDEM1(res0,res1,clsIO)

#== Perform Update; Calculate Various Sums ============================

        yMol = yMol*resX                #-- W&B Eqn.(4.83) with lambda=1
        dQdT = NP.dot(yMol,dFdT)        #-- W&B Eqn.(4.86)
        qFun = NP.sum(yMol)             #-- W&B Eqn.(4.87a) 
        wrk0 = eigV*res0                #-- W&B Eqn.(4.83) with any lambda
        logK = logK + wrk0

#-- Test for Trivial Solution [all K's -> 1] ------------------------            

        triV = NP.dot(logK,logK)        #-- W&B Eqn.(4.88)

#== SS or GDEM step?  If GDEM, re-compute Yi afresh ===================        
        
        if eigV == 1.0 :
            sumY = qFun
        else :
            K    = NP.exp(logK)
            yMol = Z*K
            sumY = NP.sum(yMol)
            if qDeb :
                WO.writeArrayDebug(fDeb,K,"Post-GDEM: K")

        qFun =     1.0 - qFun
        tol1 = abs(1.0 - sumY)          #-- W&B Eqn.(4.87a)

#== Pressure Update (Newton) ==========================================

        dTem = - qFun/dQdT

        tOld = tRes
        tRes = tRes + dTem              #-- W&B Eqn.(4.85)

        if qDeb :
            sOut = "iTSA,qFun,dQdT,to11,tol2,triV,eigV,dTem,tRes {:3d} {:10.3e} {:10.3e} {:10.3e} {:10.3e} {:10.3e} {:10.3e} {:10.3e} {:10.4f}\n"\
                .format(iTSA,qFun,dQdT,tol1,tol2,triV,eigV,dTem,tRes)
            fDeb.write(sOut)

#== Converged? ========================================================

        if tol1 < 1.0E-12 and tol2 < 1.0E-08 :      #-- Hard to acheive 1E-13
            qCon = True
            break

#== Trivial Solution? =================================================

        if triV < 1.0E-04 :
            qTrv = True
            print("calcPsat: Trivial Solution?")
            break

#========================================================================
#  Converged: Calculate K-Values
#========================================================================

    Ksat = NP.exp(logK)

#== Ensure the K-Values are the 'Right-Way-Up' ========================

    if Ksat[nCom-1] > 1.0 :
        qBub = False
        #qBub = not qBub
        #Ksat = NP.divide(1.0,Ksat)
        if qDeb :
            sOut = "End-calcTsat: K-Values NOT Flipped\n"
            fDeb.write(sOut)
    else :
        qBub = True
        if qDeb :
            sOut = "End-calcTsat: K-Values OK\n"
            fDeb.write(sOut)

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

    return qBub,tRes,Ksat