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
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
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
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
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