Ejemplo n.º 1
0
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
Ejemplo n.º 2
0
def calcGOC(hAbv, hBel, tRes, hRef, pRef, zRef, fRef, clsEOS, clsIO):

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

    nCom = clsEOS.nComp
    iNeu = 0
    pObs = -1.0

    zDep = NP.zeros(nCom)  #-- Composition at this Depth
    zDew = NP.zeros(nCom)
    zBub = NP.zeros(nCom)

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

    qBub = None
    pSat = None
    logK = NP.empty(nCom)

    #--------------------------------------------------------------------
    #  Simple Interval Halving
    #--------------------------------------------------------------------

    iMid = 1
    zTyp = "GOC"
    zDep = zRef
    pDep = pRef

    while hBel - hAbv > 0.1:

        hMid = 0.5 * (hAbv + hBel)
        dDep = hMid - hRef

        pDep,zDep,qDep,sDep = \
            calcTopBottom(zTyp,dDep,pRef,tRes,zRef,fRef,clsEOS,clsIO)

        if qDeb:
            if qDep: iBub = 1
            else: iBub = -1
            sOut = "GOC search: iMid,hAbv,hMid,hBel,iBub,pSat {:2d} {:10.3f} {:10.3f} {:10.3f} {:2d} {:10.3f}\n" \
                   .format(iMid,hAbv,hMid,hBel,iBub,sDep)
            fDeb.write(sOut)

        if qDep:
            hBel = hMid
            zBub = zDep
        else:
            hAbv = hMid
            zDew = zDep

        iMid += 1

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

#print("GOC: hMid,pMid,sMid {:10.3f} {:10.3f} {:10.3f}".format(hMid,pDep,sDep))

    iNeu = 0

    mSat, vSat, dSat, zSat, uSat, dumS, dumS = CE.calcProps(
        iNeu, sDep, tRes, zDep, clsEOS)

    zC1, zC7 = calcMoleFracGRD(zDep, clsEOS)

    return hMid, pDep, sDep, dSat, zC1, zC7, zDew, zBub
Ejemplo n.º 3
0
def calcSWL(iExp, qDif, clsEOS, dicSAM, clsEXP, clsIO):

    nCom = clsEOS.nComp
    nSam = clsEXP.nSamp
    nInj = clsEXP.nSinj
    nAdd = clsEXP.nRow

    sNam = dicSAM[nSam].sNam

    #print("calcSEP: nCom,nSam,nRow ",nCom,nSam,nPrs)

    typIND = AP.classLIB().INDshrt.get("SWL")
    typOBS = AP.classLIB().OBSshrt.get("SWL")

    iMO = typIND.index("MOLE")

    iPS = typOBS.index("PSAT")
    iVS = typOBS.index("VSWL")

    #-- Reservoir Temperature -------------------------------------------

    tRes = clsEXP.Tres

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

    clsSAM = dicSAM[nSam]
    clsINJ = dicSAM[nInj]

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

    Z = NP.zeros(nCom)
    for iC in range(nCom):
        Z[iC] = clsSAM.gZI(iC)

    #-- Load Injection Composition --------------------------------------

    Y = NP.zeros(nCom)
    for iC in range(nCom):
        Y[iC] = clsINJ.gZI(iC)

    #-- Composition Array to be used ------------------------------------

    W = NP.zeros(nCom)

    mTot = 1.0
    mInj = 0.0

    #======================================================================
    #  Loop over user defined 'stages'
    #======================================================================

    for iAdd in range(nAdd):

        mInj = clsEXP.dInd[iMO][iAdd]

        mTot = mInj + 1.0

        #print("calcSWL: iAdd,mAdd,mInj,mTot ",iAdd,mThs,mInj,mTot)

        wDiv = 1.0 / mTot
        for iC in range(nCom):
            W[iC] = (Z[iC] + mInj * Y[iC]) * wDiv
            clsWRK.sZI(iC, W[iC])

        pSatO = clsEXP.dObs[iPS][iAdd]

        if pSatO > 0.0: pEst = 0.95 * pSatO
        else: pEst = -1.0

        qBub = None
        pSat = None
        logK = NP.empty(nCom)

        qBub,pSat,Ksat = \
            CS.calcPsat(pEst,tRes,qBub,pSat,logK,clsEOS,clsWRK,clsIO)

        iLiq = 0
        MPs, VPs, DPs, ZPs, UPs, dmS, dmS = CE.calcProps(
            iLiq, pSat, tRes, W, clsEOS)

        if iAdd == 0: Vref = VPs

        Vswl = mTot * VPs / Vref

        clsEXP.dCal[iPS][iAdd] = pSat
        clsEXP.dCal[iVS][iAdd] = Vswl

#======================================================================
#  End of Module
#======================================================================

    return
Ejemplo n.º 4
0
def calcGRD(iExp, qDif, clsEOS, dicSAM, clsEXP, clsIO):

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

    qSat = True

    #-- Various dimensions ----------------------------------------------

    nCom = clsEOS.nComp
    nSam = clsEXP.nSamp
    nDep = clsEXP.nRow - 1  #-- Extra Row for GOC, if present
    nRef = clsEXP.nDref

    nGOC = nDep

    #-- Pointers into the potential observed data (for calculated data) -

    typIND = AP.classLIB().INDshrt.get("GRD")
    typOBS = AP.classLIB().OBSshrt.get("GRD")

    iHG = typIND.index("HEIG")

    iPR = typOBS.index("PRES")
    iPS = typOBS.index("PSAT")
    iDN = typOBS.index("DENS")
    iC1 = typOBS.index("ZC1")
    iCP = typOBS.index("ZC7+")

    #-- Sample Name -----------------------------------------------------

    clsSAM = dicSAM[nSam]
    sNam = clsSAM.sNam

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

    #-- Load Reference Composition --------------------------------------

    zRef = NP.zeros(nCom)
    for iC in range(nCom):
        zRef[iC] = clsSAM.gZI(iC)

    #-- Reference Depth & Pressure --------------------------------------

    pRef = clsEXP.Pref
    hRef = clsEXP.Dref

    #-- Reservoir Temperature -------------------------------------------

    tRes = clsEXP.Tres

    #== Saturation Pressure at Reference Depth ============================

    pSatO = clsEXP.PsatO

    if pSatO > 0.0: pObs = 0.95 * pSatO
    else: pObs = -1.0

    qBub = None
    pSat = None
    logK = NP.empty(nCom)

    qBub, pSat, Ksat = CS.calcPsat(pObs, tRes, qBub, pSat, logK, clsEOS,
                                   clsSAM, clsIO)

    if qBub: iRef = 1  #-- Ref-State is BUB
    else: iRef = -1  #--              DEW

    iNeu = 0
    iLiq = 1
    iVap = -1

    mSat, vSat, dSat, zSat, uSat, dumS, dumS = CE.calcProps(
        iNeu, pSat, tRes, zRef, clsEOS)

    zC1, zC7 = calcMoleFracGRD(zRef, clsEOS)

    clsEXP.dCal[iPR][nRef] = pRef
    clsEXP.dCal[iPS][nRef] = pSat
    clsEXP.dCal[iDN][nRef] = dSat
    clsEXP.dCal[iC1][nRef] = zC1
    clsEXP.dCal[iCP][nRef] = zC7

    for iC in range(nCom):
        clsEXP.zCal[nRef][iC] = zRef[iC]

    #-- Get Reference (log) Fugacity Coeffs -----------------------------

    fRef, dumP = setupCalcGRDCoefsP(iNeu, pRef, tRes, zRef,
                                    clsEOS)  #-- Dont need Ref dlnPhi/dP

    #======================================================================
    #  GOC Search, if appropriate
    #======================================================================

    iTop = 0
    iBot = 0

    if nRef > 0:

        hTop = clsEXP.dInd[iHG][0]
        dTop = hTop - hRef
        zTyp = "Top"

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

        pTop,zTop,qTop,sTop = \
            calcTopBottom(zTyp,dTop,pRef,tRes,zRef,fRef,clsEOS,clsIO)

        if not qTop: iTop = -1  #-- Is DEW point

    else: hTop = None

    if nRef < nDep:

        hBot = clsEXP.dInd[iHG][nDep - 1]
        dBot = hBot - hRef
        zTyp = "Bot"

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

        pBot,zBot,qBot,sBot = \
            calcTopBottom(zTyp,dBot,pRef,tRes,zRef,fRef,clsEOS,clsIO)

        if qBot: iBot = 1  #-- Is BUB point

    else: hBot = None

    #--------------------------------------------------------------------
    #  Search for Gas-Oil-Contact?
    #--------------------------------------------------------------------

    if iTop * iBot < 0:

        if iRef == iTop: hTop = hRef
        else: hBot = hRef

        print("Gas-Oil-Contact Detected in Depth Interval")

        hGOC,pGOC,sGOC,dGOC,zC1,zC7,zDew,zBub = \
            calcGOC(hTop,hBot,tRes,hRef,pRef,zRef,fRef,clsEOS,clsIO)
    else:
        print("No Gas-Oil-Contact Detected in Depth Interval")
        hGOC = 0.0
        pGOC = 0.0
        sGOC = 0.0
        dGOC = 0.0
        zC1 = 0.0
        zC7 = 0.0
        zDew = NP.zeros(nCom)
        zBub = NP.zeros(nCom)

    clsEXP.dInd[iHG][nGOC] = hGOC

    clsEXP.dCal[iPR][nGOC] = pGOC
    clsEXP.dCal[iPS][nGOC] = sGOC
    clsEXP.dCal[iDN][nGOC] = dGOC
    clsEXP.dCal[iC1][nGOC] = zC1
    clsEXP.dCal[iCP][nGOC] = zC7

    for iC in range(nCom):
        clsEXP.zCal[nGOC][iC] = zDew[iC]

    #-- Above and Below any Possible GOC --------------------------------

    hAbv = None
    hBel = None

    #--------------------------------------------------------------------
    #  Above Reference Depth
    #--------------------------------------------------------------------

    zTyp = "Abv"

    for iDep in range(nRef - 1, -1, -1):

        hDep = clsEXP.dInd[iHG][iDep]
        dDep = hDep - hRef

        #print("Above: iDep,hDep ",iDep,hDep)

        pDep,zDep,qDep,sDep = \
            calcTopBottom(zTyp,dDep,pRef,tRes,zRef,fRef,clsEOS,clsIO)

        mDep, vDep, yDep, gDen, uDep, dumS, dumS = CE.calcProps(
            iNeu, pDep, tRes, zDep, clsEOS)
        zC1, zC7 = calcMoleFracGRD(zDep, clsEOS)

        clsEXP.dCal[iPR][iDep] = pDep
        clsEXP.dCal[iPS][iDep] = sDep
        clsEXP.dCal[iDN][iDep] = yDep
        clsEXP.dCal[iC1][iDep] = zC1
        clsEXP.dCal[iCP][iDep] = zC7

        for iC in range(nCom):
            clsEXP.zCal[iDep][iC] = zDep[iC]

        if qDeb:
            if qBub: isBub = 1
            else: isBub = -1
            sOut = "Above: iDep,hDep,pDep,pSat,Bub,zC1,zC7+,Dens {:2d} {:10.3f} {:10.3f} {:10.3f} {:2d} {:6.4f} {:6.4f} {:7.3f}\n".format(
                iDep, hDep, pDep, pSat, isBub, zC1, zC7, yDep)
            fDeb.write(sOut)
            WO.writeArrayDebug(fDeb, zDep, "zDep")

#--------------------------------------------------------------------
#  Below Reference Depth
#--------------------------------------------------------------------

    zTyp = "Bel"

    for iDep in range(nRef + 1, nDep):

        hDep = clsEXP.dInd[iHG][iDep]
        dDep = hDep - hRef

        #print("Below: iDep,hDep ",iDep,hDep)

        pDep,zDep,qDep,sDep = \
            calcTopBottom(zTyp,dDep,pRef,tRes,zRef,fRef,clsEOS,clsIO)

        mDep, vDep, yDep, gDen, uDep, dumS, dumS = CE.calcProps(
            iNeu, pDep, tRes, zDep, clsEOS)
        zC1, zC7 = calcMoleFracGRD(zDep, clsEOS)

        clsEXP.dCal[iPR][iDep] = pDep
        clsEXP.dCal[iPS][iDep] = sDep
        clsEXP.dCal[iDN][iDep] = yDep
        clsEXP.dCal[iC1][iDep] = zC1
        clsEXP.dCal[iCP][iDep] = zC7

        for iC in range(nCom):
            clsEXP.zCal[iDep][iC] = zDep[iC]

        if qDeb:
            if qBub: isBub = 1
            else: isBub = -1
            sOut = "Below: iDep,hDep,pDep,pSat,Bub,zC1,zC7+,Dens {:2d} {:10.3f} {:10.3f} {:10.3f} {:2d} {:6.4f} {:6.4f} {:7.3f}\n".format(
                iDep, hDep, pDep, pSat, isBub, zC1, zC7, yDep)
            fDeb.write(sOut)
            WO.writeArrayDebug(fDeb, zDep, "zDep")

#======================================================================
#  End of Routine
#======================================================================

    return
Ejemplo n.º 5
0
def calcGroup(sNumW, dicGRP, clsEOS0, dicSAM0):

    iERR = 0

    nOld = clsEOS0.nComp
    nNew = len(dicGRP)
    nSam = len(dicSAM0)

    tStd = UT.tStand  #-- Standard Temperature [519.67 degR = 60 degF]

    #print("calcGroup: nOld,nNew,nSam ",nOld,nNew,nSam)

    #== Create 'Group' Copies of EOS/Samples ==============================

    EOS = clsEOS0.EOS

    clsEOSG = AD.classEOS(EOS)
    dicSAMG = {}

    clsEOSG.setEOSparms(EOS)

    #----------------------------------------------------------------------
    #  Create New EOS-Class and Dictionary of Samples
    #----------------------------------------------------------------------

    clsEOSG.nComp = nNew
    clsEOSG.nSamp = nSam

    clsEOSG.setNComp(nNew)  #-- Dimensions the Arrays

    #== Samples ===========================================================

    for iSam in range(nSam):

        clsSAM0 = dicSAM0[iSam]

        sOld = clsSAM0.sNam
        clsSAMG = AD.classSample(sOld)

        dicSAMG[iSam] = clsSAMG
        dicSAMG[iSam].setIntComp(nNew, nNew)  #-- All "User" Components

        clsSAMG.iPlsMW = clsSAM0.iPlsMW
        clsSAMG.iPlsSG = clsSAM0.iPlsSG
        clsSAMG.iPlsAL = clsSAM0.iPlsAL

        sTot = 0.0

        for iNew in range(nNew):

            dZI = 0.0

            oldNum = dicGRP[iNew].oldNum
            nGrp = len(oldNum)

            for iGrp in range(nGrp):
                iC = oldNum[iGrp]
                dZI = dZI + dicSAM0[iSam].gZI(iC)

            dicSAMG[iSam].sZI(iNew, dZI)

            sTot = sTot + dZI

        #print("iSam,sTot ",iSam,sTot)

        if sTot - 1.0 > 1.0E-08:
            print("Composition of Sample " + sOld +
                  " > 1.0: One Old Component Counted Twice?")
            iERR = -1
            return iERR
        elif sTot - 1.0 < -1.0E-08:
            print("Composition of Sample " + sOld +
                  " < 1.0: One Old Component Missing?")
            iERR = -1
            return iERR

#== Work Array for Coats-A Calculation: Whitson Eqn.(5.93) ==========

    aSqr = NP.zeros(nOld)

    for iOld in range(nOld):

        MA = clsEOS0.gPP("MA", iOld)
        Tc = clsEOS0.gPP("TC", iOld)
        Pc = clsEOS0.gPP("PC", iOld)
        AF = clsEOS0.gPP("AF", iOld)

        tR = tStd / Tc
        aS = CE.sqrtAlpha(tR, AF, clsEOSG)

        aSqr[iOld] = sqrt(MA / Pc) * Tc * aS  #-- sqrt(OmgA*Tc^2*alfa/Pc]

        #print("iOld,aSqr {:2d} {:10.3e}".format(iOld,aSqr[iOld]))

#== Components ======================================================

    for iNew in range(nNew):

        clsGRP = dicGRP[iNew]

        newNam = clsGRP.newNam

        clsEOSG.sNM(iNew, newNam)

        oldNum = clsGRP.oldNum
        nGrp = len(oldNum)

        zNew = dicSAMG[sNumW].gZI(iNew)

        MwNew = 0.0
        TcNew = 0.0
        PcNew = 0.0
        VcNew = 0.0
        ZcNew = 0.0
        AFNew = 0.0
        TbNew = 0.0
        SGNew = 0.0
        PANew = 0.0
        SSNew = 0.0
        CANew = 0.0
        CBNew = 0.0
        CCNew = 0.0
        CDNew = 0.0

        aIGrp = 0.0
        bIGrp = 0.0

        for iGrp in range(nGrp):

            iOld = oldNum[iGrp]
            zOld = dicSAM0[sNumW].gZI(iOld)

            MwOld = clsEOS0.gPP("MW", iOld)
            TcOld = clsEOS0.gPP("TC", iOld)
            PcOld = clsEOS0.gPP("PC", iOld)
            VcOld = clsEOS0.gPP("VC", iOld)
            ZcOld = clsEOS0.gPP("ZC", iOld)
            AFOld = clsEOS0.gPP("AF", iOld)
            TbOld = clsEOS0.gPP("TB", iOld)
            SGOld = clsEOS0.gPP("SG", iOld)
            PAOld = clsEOS0.gPP("PA", iOld)
            SSOld = clsEOS0.gPP("SS", iOld)
            CAOld = clsEOS0.gPP("CA", iOld)
            CBOld = clsEOS0.gPP("CB", iOld)
            CCOld = clsEOS0.gPP("CC", iOld)
            CDOld = clsEOS0.gPP("CD", iOld)

            MwNew = MwNew + zOld * MwOld
            TcNew = TcNew + zOld * TcOld
            PcNew = PcNew + zOld * PcOld
            VcNew = VcNew + zOld * VcOld
            ZcNew = ZcNew + zOld * ZcOld
            AFNew = AFNew + zOld * AFOld
            TbNew = TbNew + zOld * TbOld
            PANew = PANew + zOld * PAOld
            SSNew = SSNew + zOld * SSOld
            CANew = CANew + zOld * CAOld
            CBNew = CBNew + zOld * CBOld
            CCNew = CCNew + zOld * CCOld
            CDNew = CDNew + zOld * CDOld

            SGNew = SGNew + zOld * MwOld / SGOld  #-- Specific Gravity special!

            tRed = tStd / TcOld
            sqAlf = CE.sqrtAlpha(tRed, AFOld, clsEOSG)
            MAOld = clsEOS0.gPP("MA", iOld)
            aIOld = sqrt(MAOld / PcOld) * TcOld * sqAlf

            MBOld = clsEOS0.gPP("MB", iOld)
            bIOld = MBOld * TcOld / PcOld

            aIGrp = aIGrp + zOld * aIOld
            bIGrp = bIGrp + zOld * bIOld

        SGNew = MwNew / SGNew  #-- Done as inverse

        MwNew = MwNew / zNew
        TcNew = TcNew / zNew
        PcNew = PcNew / zNew
        VcNew = VcNew / zNew
        ZcNew = ZcNew / zNew
        AFNew = AFNew / zNew
        TbNew = TbNew / zNew
        PANew = PANew / zNew
        SSNew = SSNew / zNew
        CANew = CANew / zNew
        CBNew = CBNew / zNew
        CCNew = CCNew / zNew
        CDNew = CDNew / zNew

        clsEOSG.sPP("MW", iNew, MwNew)
        clsEOSG.sPP("TC", iNew, TcNew)
        clsEOSG.sPP("PC", iNew, PcNew)
        clsEOSG.sPP("VC", iNew, VcNew)
        clsEOSG.sPP("ZC", iNew, ZcNew)
        clsEOSG.sPP("AF", iNew, AFNew)
        clsEOSG.sPP("TB", iNew, TbNew)
        clsEOSG.sPP("SG", iNew, SGNew)
        clsEOSG.sPP("PA", iNew, PANew)
        clsEOSG.sPP("SS", iNew, SSNew)
        clsEOSG.sPP("CA", iNew, CANew)
        clsEOSG.sPP("CB", iNew, CBNew)
        clsEOSG.sPP("CC", iNew, CCNew)
        clsEOSG.sPP("CD", iNew, CDNew)

        #-- Compute Coats OmegaB --------------------------------------------

        tRed = tStd / TcNew
        sqAlf = CE.sqrtAlpha(tRed, AFNew, clsEOSG)
        TcSqA = TcNew * sqAlf

        aI = TcSqA * TcSqA / PcNew
        bI = TcNew / PcNew

        aIGrp = aIGrp / zNew
        bIGrp = bIGrp / zNew

        OmgAI = aIGrp * aIGrp / aI
        OmgBI = bIGrp / bI  #-- Whitson Eqn.(5.93)

        clsEOSG.sPP("MA", iNew, OmgAI)
        clsEOSG.sPP("MB", iNew, OmgBI)

#== Binaries ==========================================================

    for iNew in range(nNew):

        iOldN = dicGRP[iNew].oldNum
        nIOld = len(iOldN)

        zINew = dicSAMG[sNumW].gZI(iNew)

        for jNew in range(iNew + 1, nNew):

            jOldN = dicGRP[jNew].oldNum
            nJOld = len(jOldN)

            zJNew = dicSAMG[sNumW].gZI(jNew)

            KIJ = 0.0
            ZIJ = 0.0

            for iGrp in range(nIOld):

                iOld = iOldN[iGrp]
                zIOld = dicSAM0[sNumW].gZI(iOld)

                for jGrp in range(nJOld):

                    jOld = jOldN[jGrp]
                    zJOld = dicSAM0[sNumW].gZI(jOld)
                    KIJOld = clsEOS0.gIJ(iOld, jOld)

                    ZIJ = ZIJ + zIOld * zJOld
                    KIJ = KIJ + zIOld * zJOld * KIJOld

            KIJ = KIJ / ZIJ

            clsEOSG.sIJ(iNew, jNew, KIJ)
            clsEOSG.sIJ(jNew, iNew, KIJ)

#== End of Routine ====================================================

    return iERR, clsEOSG, dicSAMG