def calcFLS(iExp, qDif, clsEOS, dicSAM, clsEXP, clsIO): nCom = clsEOS.nComp nSam = clsEXP.nSamp nPrs = clsEXP.nRow iLiq = 1 iVap = -1 sNam = dicSAM[nSam].sNam #print("calcFLS: nCom,nSam,nRow ",nCom,nSam,nPrs) typIND = AP.classLIB().INDshrt.get("FLS") typOBS = AP.classLIB().OBSshrt.get("FLS") iPR = typIND.index("PRES") iTR = typIND.index("TEMP") iZF = typOBS.index("ZFAC") iDO = typOBS.index("DENO") iVF = typOBS.index("VFRC") #-- Load Feed Composition ------------------------------------------- Z = NP.zeros(nCom) for iC in range(nCom): Z[iC] = dicSAM[nSam].gZI(iC) #====================================================================== # Loop over user defined 'stages' #====================================================================== for iPrs in range(nPrs): pRes = clsEXP.dInd[iPR][iPrs] tRes = clsEXP.dInd[iTR][iPrs] #-- 2-Phase Flash --------------------------------------------------- vEst = 0.5 V, K, X, Y = CF.calcFlash(pRes, tRes, Z, vEst, clsEOS, clsIO) #-- Properties of the Liquid and Vapour Output of this stage -------- Moil, Vliq, Doil, Zoil, Uoil, dumS, dumS = CE.calcProps( iLiq, pRes, tRes, X, clsEOS) Mgas, Vvap, Dgas, Zgas, Ugas, dumS, dumS = CE.calcProps( iVap, pRes, tRes, Y, clsEOS) clsEXP.dCal[iZF][iPrs] = Zgas clsEXP.dCal[iDO][iPrs] = Doil clsEXP.dCal[iVF][iPrs] = V #====================================================================== # End of Module #====================================================================== return
def isLibComp(iC, cName, clsEOS, clsIO): #fLog = clsIO.fLog clsLIB = AP.classLIB() Pcrit = clsLIB.lPcrt[cName] Vcrit = clsLIB.lVcrt[cName] Tcrit = clsLIB.lTcrt[cName] + UT.dF2dR #-- Want this stored in degR Zcrit = Pcrit * Vcrit / (UT.gasCon * Tcrit) clsEOS.sNM(iC, cName) clsEOS.sPP("MW", iC, clsLIB.lMolW[cName]) clsEOS.sPP("TC", iC, Tcrit) clsEOS.sPP("PC", iC, Pcrit) clsEOS.sPP("VC", iC, Vcrit) clsEOS.sPP("ZC", iC, Zcrit) clsEOS.sPP("AF", iC, clsLIB.lAcnF[cName]) clsEOS.sPP("SG", iC, clsLIB.lSpcG[cName]) clsEOS.sPP("TB", iC, clsLIB.lTboi[cName] + UT.dF2dR) #-- Want this stored in degR clsEOS.sPP("PA", iC, clsLIB.lPara[cName]) clsEOS.sPP("MA", iC, 1.0) clsEOS.sPP("MB", iC, 1.0) if clsEOS.EOS == "SRK": clsEOS.sPP("SS", iC, clsLIB.lVSRK[cName]) else: clsEOS.sPP("SS", iC, clsLIB.lVSPR[cName]) clsEOS.sPP("CA", iC, clsLIB.lCpAI[cName]) clsEOS.sPP("CB", iC, clsLIB.lCpBI[cName]) clsEOS.sPP("CC", iC, clsLIB.lCpCI[cName]) clsEOS.sPP("CD", iC, clsLIB.lCpDI[cName]) sLog = "Component ({:2d}) = {:4s} is in Internal Library - Properties Assigned".format( iC + 1, cName) print(sLog) #====================================================================== # End of Routine #====================================================================== 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 assignBIPs(clsEOS): clsLIB = AP.classLIB() nComp = clsEOS.nComp #-- Initially, set all values to Zero ------------------------------- for iC in range(nComp): for jC in range(nComp): clsEOS.sIJ(iC, jC, 0.0) #-- Then set Library/Other Components ------------------------------- for iC in range(nComp): cINam = clsEOS.gNM(iC) #print("iC,cINam ",iC,cINam) if cINam.upper() == "N2": for jC in range(iC + 1, nComp): cJNam = clsEOS.gNM(jC) typJC = clsLIB.typeC.get(cJNam) #-- Other Lib Compor Not? if typJC == "L": if clsEOS.EOS == "SRK": KIJ = clsLIB.lKN2S[cJNam] else: KIJ = clsLIB.lKN2P[cJNam] else: if clsEOS.EOS == "SRK": KIJ = 0.080 else: KIJ = 0.115 #print("N2 :jC,cJNam,typJC,KIJ ",jC,cJNam,typJC,KIJ) clsEOS.sIJ(iC, jC, KIJ) clsEOS.sIJ(jC, iC, KIJ) elif cINam.upper() == "CO2": for jC in range(iC + 1, nComp): cJNam = clsEOS.gNM(jC) typJC = clsLIB.typeC.get(cJNam) #-- Other Lib Comp or Not? if typJC == "L": if clsEOS.EOS == "SRK": KIJ = clsLIB.lKCOS[cJNam] else: KIJ = clsLIB.lKCOP[cJNam] else: if clsEOS.EOS == "SRK": KIJ = 0.150 else: KIJ = 0.115 #print("CO2:jC,cJNam,typJC,KIJ ",jC,cJNam,typJC,KIJ) clsEOS.sIJ(iC, jC, KIJ) clsEOS.sIJ(jC, iC, KIJ) elif cINam.upper() == "H2S": for jC in range(iC + 1, nComp): cJNam = clsEOS.gNM(jC) typJC = clsLIB.typeC.get(cJNam) #-- Other Lib Comp or Not? if typJC == "L": if clsEOS.EOS == "SRK": KIJ = clsLIB.lKHSS[cJNam] else: KIJ = clsLIB.lKHSP[cJNam] else: if clsEOS.EOS == "SRK": KIJ = 0.030 else: KIJ = 0.055 #print("H2S:jC,cJNam,typJC,KIJ ",jC,cJNam,typJC,KIJ) clsEOS.sIJ(iC, jC, KIJ) clsEOS.sIJ(jC, iC, KIJ) elif cINam.upper() == "C1": for jC in range(iC + 1, nComp): cJNam = clsEOS.gNM(jC) typJC = clsLIB.typeC.get(cJNam) #-- Other Lib Comp or Not? if typJC == "L": if clsEOS.EOS == "SRK": KIJ = clsLIB.lKC1S[cJNam] else: KIJ = clsLIB.lKC1P[cJNam] else: if clsEOS.EOS == "SRK": KIJ = 0.000 else: mWJ = clsEOS.gPP("MW", jC) if mWJ > 90.0: KIJ = 0.14 * clsEOS.gPP("SG", jC) - 0.0668 else: KIJ = 0.000 #print("C1 :iC,jC,cJNam,typJC,KIJ ",iC,jC,cJNam,typJC,KIJ) clsEOS.sIJ(iC, jC, KIJ) clsEOS.sIJ(jC, iC, KIJ) else: pass #======================================================================= # End of Routine #======================================================================= return
def allProps(clsEOS, dicSAM, clsUNI, clsIO): iERR = 0 clsLIB = AP.classLIB() nComp = clsEOS.nComp nUser = clsEOS.nUser nSplt = clsEOS.nPseu nSamp = len(dicSAM) #print("allProps: nComp,nUser,nSplt,nSamp ",nComp,nUser,nSplt,nSamp) print("allProps: Attempting to assign Component Properties") #-- Find the type (Library or SCN) of first Nc-1 components --------- for iC in range(nUser - 1): cName = clsEOS.gNM(iC) typC = clsLIB.typeC.get(cName) if typC == None: print("allProps: Component " + str(iC + 1, cName) + " is not Library or SCN - Error") iERR = -1 return iERR #== Library Components ================================================ if typC == 'L': isLibComp(iC, cName, clsEOS, clsIO) #== SCN Components ==================================================== elif typC == 'S': #-- SCN Component molWt = clsLIB.scnMW[cName] heavyComp(molWt, -1.0, iC, clsEOS) sLog = "Component ({:2d}) = {:4s} is assumed to be a SCN - Properties Assigned/Calculated".format( iC + 1, cName) print(sLog) #== Not Library or SCN ================================================ else: print("Component Name " + cName + " Not Recognised - Error") iERR = -1 #======================================================================= # Process the Plus Fraction(s) # If more than one sample, split using Whitson Quadrature Method #======================================================================= #-- Mole Weight of Penultimate Component: 'Last' component = nComp-1 -- cPlus = clsEOS.gNM(nUser - 1) #-- Name of the User Plus Fraction if nSamp > 1 or nSplt > 1: sLog = "Component ({:2d}) = {:4s} is Plus Fraction to be Split into {:1d} Pseudos".format( nUser, cPlus, nSplt) print(sLog) iERR = splitPlus(dicSAM, clsEOS, clsIO) if iERR < 0: return iERR print("Plus Fraction Splitting Completed") else: molWt = dicSAM[0].mPlus specG = dicSAM[0].sPlus sLog = "Component ({:2d}) = {:4s} is Plus Fraction with No Split Requested - Properties Calculated".format( nUser + 1, cPlus) print(sLog) heavyComp(molWt, specG, nUser - 1, clsEOS) #======================================================================= # Sort the Binary Interaction Parameters #======================================================================= nComp = clsEOS.nComp #print("compProps: Set BICs, N = ",nComp) assignBIPs(clsEOS) print("Binary Interaction Parameters (BIPs) Assigned/Calculated") #======================================================================== # Do we need to sort the components? Most to Least Volatility #======================================================================== clsEOS, dicSAM = sortComponents(clsEOS, dicSAM) #======================================================================== # Output the data #======================================================================== sTit = "Initialisation" WO.outputProps(sTit, clsEOS, dicSAM, clsIO) #======================================================================== # Write Fluid Description to the SAV file #======================================================================== WO.outputSave(sTit, clsEOS, dicSAM, clsIO) #====================================================================== # Generate (Approximate) Phase Plots #====================================================================== #CP.allSamplesPhasePlot(clsEOS,dicSAM,clsIO) #====================================================================== # End of Routine #====================================================================== return iERR
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 calcCCE(iExp, qDif, clsEOS, dicSAM, clsEXP, clsIO): nCom = clsEOS.nComp nSam = clsEXP.nSamp nPrs = clsEXP.nRow clsSAM = dicSAM[nSam] sNam = clsSAM.sNam #== Independent & Calculated Data ===================================== typIND = AP.classLIB().INDshrt.get("CCE") typCAL = AP.classLIB().CALshrt.get("CCE") iPR = typIND.index("PRES") iRV = typCAL.index("RELV") iSL = typCAL.index("SLIQ") iZF = typCAL.index("ZFAC") iDO = typCAL.index("DENO") iUG = typCAL.index("VISG") iUO = typCAL.index("VISO") iMO = typCAL.index("MWO") iMG = typCAL.index("MWG") iDG = typCAL.index("DENG") iFT = typCAL.index("IFT") iHO = typCAL.index("HO") iHG = typCAL.index("HG") iCO = typCAL.index("CPO") iCG = typCAL.index("CPG") #-- Load Feed Composition ------------------------------------------- Z = NP.zeros(nCom) for iC in range(nCom): Z[iC] = clsSAM.gZI(iC) #-- Reservoir Temperature ------------------------------------------- tRes = clsEXP.Tres #-- Saturation Pressure --------------------------------------------- if clsEXP.PsatO > 0.0: pObs = clsEXP.PsatO else: pObs = -1.0 qBub, pSat, logK = clsEXP.getPsatInfo(qDif, nCom) qBub, pSat, Ksat = CS.calcPsat(pObs, tRes, qBub, pSat, logK, clsEOS, clsSAM, clsIO) if not qDif: clsEXP.setPsatInfo(qBub, pSat, NP.log(Ksat)) clsEXP.setPsatCal(pSat) iNeu = 0 iLiq = 1 iVap = -1 Msat, Vsat, Dsat, Zsat, Usat, dumS, dumS = CE.calcProps( iNeu, pSat, tRes, Z, clsEOS) #if qBub : vEst = 0.0 #else : vEst = 1.0 vEst = None #====================================================================== # Loop over user defined pressures #====================================================================== for iPrs in range(nPrs): pRes = clsEXP.dInd[iPR][iPrs] #== 1-Phase or 2-Phase? =============================================== if pRes > pSat: Moil, Vliq, Doil, Zoil, Uoil, dumS, dumS = CE.calcProps( iNeu, pRes, tRes, Z, clsEOS) #print("calcCCE[Z]: iP,pR,Mw,Vm,Ro,ZF,vS {:2d} {:8.2f} {:7.3f} {:8.4f} {:8.3f} {:8.4f} {:8.4f}".format(iPrs,pRes,M1P,V1P,D1P,Z1P,V1P)) relV = Vliq / Vsat if qBub: sLiq = 1.0 else: sLiq = 0.0 Mgas = Moil Vvap = Vliq Dgas = Doil Zgas = Zoil Ugas = Uoil IFT = 0.0 #-- Surface Tension [dyne/cm] HO,CPO,uJTO = \ CE.calcEnthSpecHeat(iNeu,pRes,tRes,Z,clsEOS) #-- Enthalpy & Spec Heat HG = HO CPG = CPO uJTG = uJTO #-- Gas = Oil = 1-Phase! #print("P,uJTO,uJTG,IFT {:8.2f} {:10.3e} {:10.3e} {:8.4f}".format(pRes,uJTO,uJTG,IFT)) else: #-- Two-Phase => Flash the Fluid V, K, X, Y = CF.calcFlash(pRes, tRes, Z, vEst, clsEOS, clsIO) vEst = V Moil, Vliq, Doil, Zoil, Uoil, dumS, dumS = CE.calcProps( iLiq, pRes, tRes, X, clsEOS) Mgas, Vvap, Dgas, Zgas, Ugas, dumS, dumS = CE.calcProps( iVap, pRes, tRes, Y, clsEOS) Voil = (1.0 - V) * Vliq Vgas = V * Vvap Vtot = Voil + Vgas relV = Vtot / Vsat if clsEXP.sLCCE == "TOT": sLiq = Voil / Vtot else: sLiq = Voil / Vsat if sLiq < 0.0: crash = 1.0 / 0.0 IFT = CE.calcIFT(Vliq, Vvap, X, Y, clsEOS) HO,CPO,uJTO = \ CE.calcEnthSpecHeat(iLiq,pRes,tRes,X,clsEOS) #-- Enthalpy & Spec Heat HG,CPG,uJTG = \ CE.calcEnthSpecHeat(iVap,pRes,tRes,Y,clsEOS) #-- Enthalpy & Spec Heat #print("P,uJTO,uJTg {:8.2f} {:10.3e} {:10.3e} {:8.4f}".format(pRes,uJTO,uJTG,IFT)) #== Store the data for this stage ===================================== clsEXP.dCal[iRV][iPrs] = relV clsEXP.dCal[iSL][iPrs] = sLiq clsEXP.dCal[iZF][iPrs] = Zgas clsEXP.dCal[iDO][iPrs] = Doil clsEXP.dCal[iUG][iPrs] = Ugas clsEXP.dCal[iUO][iPrs] = Uoil clsEXP.dCal[iMO][iPrs] = Moil clsEXP.dCal[iMG][iPrs] = Mgas clsEXP.dCal[iDG][iPrs] = Dgas clsEXP.dCal[iFT][iPrs] = IFT clsEXP.dCal[iHO][iPrs] = HO clsEXP.dCal[iHG][iPrs] = HG clsEXP.dCal[iCO][iPrs] = CPO clsEXP.dCal[iCG][iPrs] = CPG #====================================================================== # End of Module #====================================================================== return
def calcSAT(iExp, qDif, clsEOS, dicSAM, clsEXP, clsIO): nCom = clsEOS.nComp nSam = clsEXP.nSamp nTem = clsEXP.nRow clsSAM = dicSAM[nSam] sNam = clsSAM.sNam #print("calcSEP: nCom,nSam,nRow ",nCom,nSam,nPrs) typIND = AP.classLIB().INDshrt.get("SAT") typOBS = AP.classLIB().OBSshrt.get("SAT") iTR = typIND.index("TEMP") iPS = typOBS.index("PSAT") iZF = typOBS.index("ZFAC") iDO = typOBS.index("DENO") #-- Load Feed Composition ------------------------------------------- Z = NP.zeros(nCom) for iC in range(nCom): Z[iC] = dicSAM[nSam].gZI(iC) #====================================================================== # Loop over user defined 'stages' #====================================================================== for iTem in range(nTem): tRes = clsEXP.dInd[iTR][iTem] pSatO = clsEXP.dObs[iPS][iTem] 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,clsSAM,clsIO) iLiq = 0 MPs, VPs, DPs, ZPs, UPs, dmS, dmS = CE.calcProps( iLiq, pSat, tRes, Z, clsEOS) clsEXP.dCal[iPS][iTem] = pSat clsEXP.dCal[iZF][iTem] = ZPs clsEXP.dCal[iDO][iTem] = DPs #print("calcSAT: tRes,qBub,pSat ",tRes,qBub,pSat) #====================================================================== # End of Module #====================================================================== return
def calcDLE(iExp, qDif, clsEOS, dicSAM, clsEXP, clsIO): nCom = clsEOS.nComp nSam = clsEXP.nSamp nPrs = clsEXP.nRow clsSAM = dicSAM[nSam] sNam = clsSAM.sNam #print("calcCVD: nCom,nSam,nRow ",nCom,nSam,nPrs) typIND = AP.classLIB().INDshrt.get("DLE") typOBS = AP.classLIB().OBSshrt.get("DLE") iPR = typIND.index("PRES") iBO = typOBS.index("BO") iRS = typOBS.index("GOR") iDO = typOBS.index("DENO") iBT = typOBS.index("BT") iBG = typOBS.index("BG") iZF = typOBS.index("ZFAC") iGG = typOBS.index("GGRV") iUO = typOBS.index("VISO") #-- Load Feed Composition ------------------------------------------- Z = NP.zeros(nCom) for iC in range(nCom): Z[iC] = clsSAM.gZI(iC) #-- Reservoir Temperature ------------------------------------------- tRes = clsEXP.Tres #-- Saturation Pressure --------------------------------------------- if clsEXP.PsatO > 0.0: pObs = clsEXP.PsatO else: pObs = -1.0 qBub, pSat, logK = clsEXP.getPsatInfo(qDif, nCom) qBub, pSat, Ksat = CS.calcPsat(pObs, tRes, qBub, pSat, logK, clsEOS, clsSAM, clsIO) if not qDif: clsEXP.setPsatInfo(qBub, pSat, NP.log(Ksat)) clsEXP.setPsatCal(pSat) iLiq = 1 iVap = -1 Msat, Vsat, Dsat, Zsat, Usat, dumS, dumS = CE.calcProps( iLiq, pSat, tRes, Z, clsEOS) #if qBub : vEst = 0.0 #else : vEst = 1.0 vEst = None #====================================================================== # Loop over user defined pressures #====================================================================== zMol = 1.0 rTot = 0.0 psTs = UT.pStand / UT.tStand for iPrs in range(nPrs): pRes = clsEXP.dInd[iPR][iPrs] #== 1-Phase or 2-Phase? =============================================== if pRes > pSat: M1P, V1P, D1P, Z1P, U1P, dmS, dmS = CE.calcProps( iLiq, pRes, tRes, Z, clsEOS) if qBub: sLiq = 1.0 else: sLiq = 0.0 Voil = V1P Vrem = 0.0 Doil = D1P Vtot = V1P Bgas = 0.0 Zgas = 0.0 gGrv = 0.0 Uoil = U1P else: V, K, X, Y = CF.calcFlash(pRes, tRes, Z, vEst, clsEOS, clsIO) vEst = V Moil, Vliq, Doil, Zoil, Uoil, dumS, dumS = CE.calcProps( iLiq, pRes, tRes, X, clsEOS) Mgas, Vvap, Dgas, Zgas, Ugas, dumS, dumS = CE.calcProps( iVap, pRes, tRes, Y, clsEOS) Voil = zMol * (1.0 - V) * Vliq Vgas = zMol * V * Vvap zRem = pRes * Vgas / (Zgas * UT.gasCon * tRes) zMol = zMol - zRem Vrem = zRem * UT.volMol rTot = rTot + Vrem Z = NP.copy(X) Vtot = Voil + Vgas Bgas = psTs * Zgas * tRes / pRes gGrv = Mgas / UT.molAir #-- Temporary Storage Ahead of Stock Tank Corrections --------------- clsEXP.dCal[iBO][iPrs] = Voil clsEXP.dCal[iRS][iPrs] = Vrem clsEXP.dCal[iDO][iPrs] = Doil clsEXP.dCal[iBT][iPrs] = Vtot clsEXP.dCal[iBG][iPrs] = Bgas clsEXP.dCal[iZF][iPrs] = Zgas clsEXP.dCal[iGG][iPrs] = gGrv clsEXP.dCal[iUO][iPrs] = Uoil #== Stock Tank Volume ================================================= Mst, Vst, Dst, Zst, Ust, dmS, dmS = CE.calcProps(iLiq, UT.pStand, UT.tStand, Z, clsEOS) Vsto = zMol * Vst #== "Normalise" via Stock Tank Volume ================================= for iPrs in range(nPrs): rTot = rTot - clsEXP.dCal[iRS][iPrs] clsEXP.dCal[iBO][iPrs] = clsEXP.dCal[iBO][iPrs] / Vsto clsEXP.dCal[iRS][iPrs] = rTot / Vsto clsEXP.dCal[iBT][iPrs] = clsEXP.dCal[iBO][iPrs] + \ clsEXP.dCal[iBG][iPrs]*(clsEXP.dCal[iRS][0] - clsEXP.dCal[iRS][iPrs]) #====================================================================== # End of Module #====================================================================== return
def calcSEP(iExp, qDif, clsEOS, dicSAM, clsEXP, clsIO): if clsIO.Deb["SEP"] > 0: qDeb = True fDeb = clsIO.fDeb else: qDeb = False nCom = clsEOS.nComp nSam = clsEXP.nSamp nPrs = clsEXP.nRow clsSAM = dicSAM[nSam] sNam = clsSAM.sNam #print("calcSEP: nCom,nSam,nRow ",nCom,nSam,nPrs) typIND = AP.classLIB().INDshrt.get("SEP") typOBS = AP.classLIB().OBSshrt.get("SEP") iPR = typIND.index("PRES") iTR = typIND.index("TEMP") iBO = typOBS.index("BO") iRS = typOBS.index("GOR") iDO = typOBS.index("DENO") iGG = typOBS.index("GGRV") Lsep = clsEXP.Lsep Vsep = clsEXP.Vsep #print("calcSEP: Lsep ",Lsep) #print("calcSEP: Vsep ",Vsep) #-- Load Feed Composition ------------------------------------------- Z = NP.zeros(nCom) for iC in range(nCom): Z[iC] = clsSAM.gZI(iC) molZ = NP.zeros(nPrs) comZ = NP.zeros((nCom, nPrs)) xSTO = NP.zeros(nCom) ySTG = NP.zeros(nCom) molO = NP.zeros(nPrs) molG = NP.zeros(nPrs) mSTO = 0.0 mSTG = 0.0 #-- First Stage is (pSat,tRes) and all feed goes to Stage-2 --------- molZ[0] = 1.0 molZ[1] = 1.0 for iC in range(nCom): comZ[iC][0] = Z[iC] comZ[iC][1] = Z[iC] #-- 1st-Stage is Assumed to (Psat,tRes) ----------------------------- pObs = clsEXP.dInd[iPR][0] tRes = clsEXP.dInd[iTR][0] #print("calcSEP: pObs,tRes ",pObs,tRes) #-- Saturation Pressure --------------------------------------------- if clsEXP.PsatO > 0.0: pObs = clsEXP.PsatO else: pObs = -1.0 qBub, pSat, logK = clsEXP.getPsatInfo(qDif, nCom) qBub, pSat, Ksat = CS.calcPsat(pObs, tRes, qBub, pSat, logK, clsEOS, clsSAM, clsIO) #print("CalcSEP: Psat {:10.3f}".format(pSat)) if not qDif: clsEXP.setPsatInfo(qBub, pSat, NP.log(Ksat)) clsEXP.setPsatCal(pSat) iLiq = 1 iVap = -1 Msat, Vsat, Dsat, Zsat, Usat, dumS, dumS = CE.calcProps( iLiq, pSat, tRes, Z, clsEOS) #vEst = 0.5 vEst = None #====================================================================== # Loop over user defined pressures #====================================================================== zGas = 0.0 zOil = 0.0 zTot = 1.0 for iPrs in range(1, nPrs): pRes = clsEXP.dInd[iPR][iPrs] tRes = clsEXP.dInd[iTR][iPrs] #print("iPrs,pRes,tRes {:2d} {:10.3f} {:8.3f}".format(iPrs,pRes,tRes)) #-- 2-Phase Flash --------------------------------------------------- for iC in range(nCom): Z[iC] = comZ[iC][iPrs] #zSum = NP.sum(Z) #Z = NP.divide(Z,zSum) Z = UT.Norm(Z) #print("iSep,Z ",iPrs,Z) V, K, X, Y = CF.calcFlash(pRes, tRes, Z, vEst, clsEOS, clsIO) if V < 0.0: V = 0.0 #-- calcFlash sets X=Z & Y=Z if 1-Phase elif V > 1.0: V = 1.0 vEst = V zGas = molZ[iPrs] * V zOil = molZ[iPrs] * (1.0 - V) molG[iPrs] = zGas molO[iPrs] = zOil #print("iSep,molZ,molG,molO {:2d} {:10.5f} {:10.5f} {:10.5f}".format(iPrs,molZ[iPrs],molG[iPrs],molO[iPrs])) #-- Properties of the Liquid and Vapour Output of this stage -------- Moil, Vliq, Doil, Zoil, Uoil, dumS, dumS = CE.calcProps( iLiq, pRes, tRes, X, clsEOS) Mgas, Vvap, Dgas, Zgas, Ugas, dumS, dumS = CE.calcProps( iVap, pRes, tRes, Y, clsEOS) #-- Where is Liquid Output Going Next? ------------------------------ kSepL = Lsep[iPrs] if kSepL == 0: if mSTO + zOil > 0.0: for iC in range(nCom): xSTO[iC] = (xSTO[iC] * mSTO + zOil * X[iC]) / (mSTO + zOil) mSTO = mSTO + zOil else: xSTO = BP.copy(X) else: for iC in range(nCom): comZ[iC][kSepL] = (comZ[iC][kSepL] * molZ[kSepL] + X[iC] * zOil) / (molZ[kSepL] + zOil) molZ[kSepL] = molZ[kSepL] + zOil #-- Where is Vapour Output Going Next? ------------------------------ kSepV = Vsep[iPrs] if kSepV == 0: if mSTG + zGas > 0.0: for iC in range(nCom): ySTG[iC] = (ySTG[iC] * mSTG + zGas * Y[iC]) / (mSTG + zGas) mSTG = mSTG + zGas else: ySTG = NP.copy(Y) else: for iC in range(nCom): comZ[iC][kSepV] = (comZ[iC][kSepV] * molZ[kSepV] + Y[iC] * zGas) / (molZ[kSepV] + zGas) molZ[kSepV] = molZ[kSepV] + zGas Voil = zOil * Vliq Vgas = zGas * UT.volMol #-- Temporary storage for Bo & Rs ahead of divide by Vsto below ----- clsEXP.dCal[iBO][iPrs] = Voil clsEXP.dCal[iRS][iPrs] = Vgas clsEXP.dCal[iDO][iPrs] = Doil clsEXP.dCal[iGG][iPrs] = Mgas / UT.molAir #== Stock Tank Oil Volume ============================================= nTot = 0.0 rTot = 0.0 gTot = 0.0 Vsto = clsEXP.dCal[iBO][nPrs - 1] for iPrs in range(1, nPrs): clsEXP.dCal[iBO][iPrs] = clsEXP.dCal[iBO][iPrs] / Vsto #-- Bo clsEXP.dCal[iRS][iPrs] = clsEXP.dCal[iRS][iPrs] / Vsto #-- GOR nTot = nTot + molG[iPrs] rTot = rTot + molG[iPrs] * clsEXP.dCal[iRS][iPrs] gTot = gTot + molG[iPrs] * clsEXP.dCal[iGG][iPrs] #== Saturation Pressure Stage ========================================= if nTot > 0.0: gTot = gTot / nTot else: gTot = 0.0 #print("mSTG,mSTO {:10.5f} {:10.5f}".format(mSTG,mSTO)) clsEXP.dCal[iBO][0] = Vsat / Vsto clsEXP.dCal[iRS][0] = mSTG * UT.volMol / Vsto clsEXP.dCal[iDO][0] = Dsat clsEXP.dCal[iGG][0] = gTot #====================================================================== # End of Module #====================================================================== return
def calcCVD(iExp, qDif, clsEOS, dicSAM, clsEXP, clsIO): if clsIO.Deb["CVD"] > 0: qDeb = True fDeb = clsIO.fDeb else: qDeb = False nCom = clsEOS.nComp nSam = clsEXP.nSamp nPrs = clsEXP.nRow clsSAM = dicSAM[nSam] sNam = clsSAM.sNam if qDeb: sOut = "calcCVD: nCom,nSam,nRow {:2d} {:2d} {:2d}\n".format( nCom, nSam, nPrs) fDeb.write(sOut) #-- Independent & Calculated Data ----------------------------------- typIND = AP.classLIB().INDshrt.get("CVD") typCAL = AP.classLIB().CALshrt.get("CVD") iPR = typIND.index("PRES") iMR = typCAL.index("MREM") iSL = typCAL.index("SLIQ") iZF = typCAL.index("ZFAC") iMO = typCAL.index("MWO") iMG = typCAL.index("MWG") iDO = typCAL.index("DENO") iDG = typCAL.index("DENG") iUO = typCAL.index("VISO") iUG = typCAL.index("VISG") #-- Load Feed Composition ------------------------------------------- Z = NP.zeros(nCom) for iC in range(nCom): Z[iC] = clsSAM.gZI(iC) #-- Reservoir Temperature ------------------------------------------- tRes = clsEXP.Tres #-- Saturation Pressure --------------------------------------------- if clsEXP.PsatO > 0.0: pObs = clsEXP.PsatO else: pObs = -1.0 qBub, pSat, logK = clsEXP.getPsatInfo(qDif, nCom) qBub, pSat, Ksat = CS.calcPsat(pObs, tRes, qBub, pSat, logK, clsEOS, clsSAM, clsIO) if qDeb: sOut = "calcCVD: tRes,qBub,pSat {:8.2f} {:} {:10.3f}\n".format( tRes, qBub, pSat) fDeb.write(sOut) if not qDif: clsEXP.setPsatInfo(qBub, pSat, NP.log(Ksat)) clsEXP.setPsatCal(pSat) iNeu = 0 iLiq = 1 iVap = -1 Msat, Vsat, Dsat, Zsat, Usat, dumS, dumS = CE.calcProps( iNeu, pSat, tRes, Z, clsEOS) #if qBub : vEst = 0.0 #else : vEst = 1.0 vEst = None #====================================================================== # Loop over user defined pressures #====================================================================== zMol = 1.0 zTot = 0.0 for iPrs in range(nPrs): pRes = clsEXP.dInd[iPR][iPrs] #== 1-Phase or 2-Phase? =============================================== if pRes > pSat: Moil, Vliq, Doil, Zoil, Uoil, dumS, dumS = CE.calcProps( iNeu, pRes, tRes, Z, clsEOS) if qBub: sLiq = 1.0 else: sLiq = 0.0 zTot = 0.0 Mgas = Moil Dgas = Doil Zgas = Zoil Ugas = Uoil else: V, K, X, Y = CF.calcFlash(pRes, tRes, Z, vEst, clsEOS, clsIO) vEst = V Moil, Vliq, Doil, Zoil, Uoil, dumS, dumS = CE.calcProps( iLiq, pRes, tRes, X, clsEOS) Mgas, Vvap, Dgas, Zgas, Ugas, dumS, dumS = CE.calcProps( iVap, pRes, tRes, Y, clsEOS) Voil = zMol * (1.0 - V) * Vliq Vgas = zMol * V * Vvap sLiq = Voil / Vsat Vtot = Voil + Vgas Vrem = Vtot - Vsat zRem = pRes * Vrem / (Zgas * UT.gasCon * tRes) #-- Moles Removed for iC in range(nCom): Z[iC] = (zMol * Z[iC] - zRem * Y[iC]) / (zMol - zRem) zMol = zMol - zRem zTot = zTot + zRem if qDeb: sOut = "calcCVD: zRem {:10.3e}\n".format(zRem) fDeb.write(sOut) #-- Load Data ------------------------------------------------------- clsEXP.dCal[iMR][iPrs] = zTot clsEXP.dCal[iSL][iPrs] = sLiq clsEXP.dCal[iZF][iPrs] = Zgas clsEXP.dCal[iMO][iPrs] = Moil clsEXP.dCal[iMG][iPrs] = Mgas clsEXP.dCal[iDO][iPrs] = Doil clsEXP.dCal[iDG][iPrs] = Dgas clsEXP.dCal[iUO][iPrs] = Uoil clsEXP.dCal[iUG][iPrs] = Ugas #====================================================================== # End of Module #====================================================================== return
def genPlots(clsIO,dicEXP,dicSAM,clsUNI) : #return nExp = len(dicEXP) iInd = 0 #-------------------------------------------------------------------- # By default, write graphs to GraphOut sub-directory # If it doesn't already exist, create it! #-------------------------------------------------------------------- graphOut = "GraphOut" rootN = clsIO.rNam outRoot = graphOut + "/" + rootN + "_" if not os.path.exists(graphOut): os.makedirs(graphOut) print("Generating Plots in Sub-Directory ",graphOut) for iExp in range(nExp) : clsEXP = dicEXP[iExp] if clsEXP.IsAct : nObs = clsEXP.nObs nRow = clsEXP.nRow nSam = clsEXP.nSamp sNam = dicSAM[nSam].sNam xTyp = clsEXP.xName titLS = AP.classLIB().OBSlong.get(xTyp) for iObs in range(nObs) : if clsEXP.qObs[iObs] and clsEXP.qPlt[iObs] : xVec = NP.zeros(nRow) yObs = NP.zeros(nRow) yCal = NP.zeros(nRow) for iRow in range(nRow) : xVec[iRow] = clsUNI.I2X(clsEXP.dInd[iInd][iRow],clsEXP.uInd[iInd]) yObs[iRow] = clsUNI.I2X(clsEXP.dObs[iObs][iRow],clsEXP.uObs[iObs]) yCal[iRow] = clsUNI.I2X(clsEXP.dCal[iObs][iRow],clsEXP.uObs[iObs]) yObs = UT.zero_to_nan(yObs) yCal = UT.zero_to_nan(yCal) titL = xTyp + " " + titLS[iObs] + " of Sample " + sNam sLobs = clsEXP.hObs[iObs] + "-Obs" sLcal = clsEXP.hObs[iObs] + "-Cal" xLab = clsEXP.hInd[iInd] + "/[" + clsEXP.uInd[iInd] + "]" yLab = clsEXP.hObs[iObs] + "/[" + clsEXP.uObs[iObs] + "]" figN = outRoot + xTyp + "_" + str(iExp+1) + "_" + clsEXP.hObs[iObs] + ".png" PL.plot(xVec,yObs,label=sLobs,marker="s",linestyle='None',color='r') PL.plot(xVec,yCal,label=sLcal,color='r') PL.title(titL) PL.xlabel(xLab) PL.ylabel(yLab) PL.legend() PL.savefig(figN) PL.close() return
def regPlots(clsIO,dicEXP0,dicEXP1,dicSAM1,qReg,clsUNI) : #return nExp = len(dicEXP0) iInd = 0 if qReg : sReg = "Reg]" sExt = "_REG" else : sReg = "Grp]" sExt = "_GRP" #-------------------------------------------------------------------- # By default, write graphs to GraphOut sub-directory # If it doesn't already exist, create it! #-------------------------------------------------------------------- graphOut = "GraphOut" rootN = clsIO.rNam outRoot = graphOut + "/" + rootN + "_" if not os.path.exists(graphOut): os.makedirs(graphOut) print("Generating Plots in Sub-Directory ",graphOut) for iExp in range(nExp) : clsEXP0 = dicEXP0[iExp] clsEXP1 = dicEXP1[iExp] if clsEXP1.IsAct : nObs = clsEXP0.nObs nRow = clsEXP0.nRow nSam = clsEXP1.nSamp sNam = dicSAM1[nSam].sNam xTyp = clsEXP0.xName titLS = AP.classLIB().OBSlong.get(xTyp) for iObs in range(nObs) : if clsEXP0.qObs[iObs] : xVec = NP.zeros(nRow) yObs = NP.zeros(nRow) yBef = NP.zeros(nRow) yAft = NP.zeros(nRow) for iRow in range(nRow) : xVec[iRow] = clsUNI.I2X(clsEXP0.dInd[iInd][iRow],clsEXP0.uInd[iInd]) yObs[iRow] = clsUNI.I2X(clsEXP0.dObs[iObs][iRow],clsEXP0.uObs[iObs]) yBef[iRow] = clsUNI.I2X(clsEXP0.dCal[iObs][iRow],clsEXP0.uObs[iObs]) yAft[iRow] = clsUNI.I2X(clsEXP1.dCal[iObs][iRow],clsEXP0.uObs[iObs]) #-- Switch zeros to nan's to prevent plotting ----------------------- yObs = UT.zero_to_nan(yObs) yBef = UT.zero_to_nan(yBef) yAft = UT.zero_to_nan(yAft) sObs = clsEXP0.hObs[iObs] titL = xTyp + " " + titLS[iObs] + " of Sample " + sNam sLobs = clsEXP0.hObs[iObs] + "-Obs" sLcal0 = clsEXP0.hObs[iObs] + "-Cal[Bef-" + sReg sLcal1 = clsEXP0.hObs[iObs] + "-Cal[Aft-" + sReg xLab = clsEXP0.hInd[iInd] + "/[" + clsEXP0.uInd[iInd] + "]" yLab = clsEXP0.hObs[iObs] + "/[" + clsEXP0.uObs[iObs] + "]" figN = graphFileName(outRoot,xTyp,iExp,sObs,sExt) PL.plot(xVec,yObs,label=sLobs ,marker="s",linestyle='None',color='r') PL.plot(xVec,yBef,label=sLcal0,color='r') PL.plot(xVec,yAft,label=sLcal1,color='g') PL.title(titL) PL.xlabel(xLab) PL.ylabel(yLab) PL.legend() PL.savefig(figN) PL.close() return
def readGen(sTyp,clsIO,clsEOS,dicSAM,dicEXP,clsUNI) : nCom = clsEOS.nComp clsEXP = AD.classEXP(sTyp) #-- Create a New Exp Class nX = len(dicEXP) #-- Current Size of Exp Dictionary #print("readGen: sTyp,nX ",sTyp,nX) dicEXP.update({nX:clsEXP}) #-- Add New Exp to the Dictionary iERR = 0 iLine = 0 sName = None #-- Sample Name for Exp sNInj = None #-- Injection Sample Name (SWL only) Tres = None #-- Reservoir Temp sLCCE = None #-- SL-definition for CCE colH = [] #-- Column Headers colU = [] #-- Column Units dTab = [] #-- Data Table qData = False #-- Independent and Observed Data for this Experiment --------------- sIndA = AP.classLIB().INDshrt.get(sTyp) sObsA = AP.classLIB().OBSshrt.get(sTyp) sCalA = AP.classLIB().CALshrt.get(sTyp) nIndA = len(sIndA) #-- Num Allowed Independent Vars for this Exp nObsA = len(sObsA) #-- Num Allowed Observed Vars for this Exp nCalA = len(sCalA) #-- Num Allowed Calculated Vars for this Exp #print("sTyp,nIndA,nObsA,nCalA ",sTyp,nIndA,nObsA,nCalA) dWal = NP.ones(nObsA) ; dWps = 1.0 qPlt = NP.full(nObsA,True) #== Read lines until blank found ====================================== fInp = clsIO.fInp for curL in fInp : iLine += 1 if iLine > 100 : print("Too Many Lines of Data for Experiment ",sTyp) iERR = -1 break tokS = curL.split() nTok = len(tokS) if nTok == 0 : break else : #-- Must be reading Column Headers ---------------------------------- if tokS[0][:2].upper() == "PR" or \ tokS[0][:2].upper() == "TE" or \ tokS[0][:2].upper() == "MO" or \ tokS[0][:2].upper() == "HE" : for iTok in range(nTok) : colH.append(tokS[iTok]) nHed = nTok nexL = next(fInp) #-- Next line must define units tokS = nexL.split() nUni = len(tokS) if nHed != nUni : print("Must have same number of Headers and Units for experiment ",sTyp," - Error") return -1 for iTok in range(nUni) : colU.append(tokS[iTok]) qData = True #-- Comment? -------------------------------------------------------- elif tokS[0][:2] == "--" : pass #-- Weighting Factors ----------------------------------------------- elif tokS[0][:4].upper() == "WEIG" : if sTyp == "CCE" or sTyp == "CVD" or \ sTyp == "DLE" or sTyp == "SEP" : qTyp = True else : qTyp = False iTok = 1 #-- Ignore 1st Token [WEIG] while iTok < nTok : sTok = tokS[iTok].upper() if sTok == "PSAT" and qTyp : iTok += 1 dTok = tokS[iTok].upper() dWps = float(dTok) iTok += 1 else : for iObs in range(nObsA) : sObs = sObsA[iObs] if sTok == sObs : iTok += 1 dTok = tokS[iTok].upper() dWal[iObs] = float(dTok) iTok += 1 #-- Plot Oberseved Quantity ----------------------------------------- elif tokS[0][:4].upper() == "PLOT" : iTok = 1 #-- Ignore 1st Token [PLOT] while iTok < nTok : sTok = tokS[iTok].upper() if sTok == "NO" : qPlt[iTok-1] = False else : qPlt[iTok-1] = True iTok += 1 #-- Must now be read the numeric data ------------------------------- elif qData : dRow = NP.zeros(nHed) #-- Store data on this row if tokS[0][:1].upper() == "P" : #-- Found PSAT nLow = 1 isPD = 1 elif tokS[0][:1].upper() == "D" or \ tokS[0][:1].upper() == "H" : #-- Found DREF (GRD-Only) nLow = 1 #-- or HREF isPD = -1 else : nLow = 0 isPD = 0 for iTok in range(nLow,nTok) : dRow[iTok-nLow] = float(tokS[iTok]) dTab.append(dRow) #-- Append Row to Table if isPD == 1 : nRsat = len(dTab) clsEXP.setPsatRow(nRsat-1) elif isPD == -1 : nDref = len(dTab) clsEXP.setDrefRow(nDref-1) #-- Line following EXP type contains non-Table information ---------- else : iTok = 0 while iTok < nTok : if tokS[iTok].upper() == "SAMP" : iTok += 1 sName = tokS[iTok] #print("sName ",sName) elif tokS[iTok].upper() == "TRES" : iTok += 1 Tres = float(tokS[iTok]) iTok += 1 Tuni = tokS[iTok] #print("Tres,Tuni ",Tres,Tuni) elif tokS[iTok].upper() == "SINJ" : iTok += 1 sNInj = tokS[iTok] elif tokS[iTok].upper() == "SLIQ" : iTok += 1 sLCCE = tokS[iTok].upper() iTok += 1 #======================================================================== # Process the read data #======================================================================== #-- Fluid Sample ---------------------------------------------------- if sName == None : print("No sample defined (using SAMP=) for Experiment ",sTyp," - Error") return -1 else : nSamp = len(dicSAM) qFoun = False for iS in range(nSamp) : if sName == dicSAM[iS].sNam : qFoun = True clsEXP.setSamp(iS,sName) break if not qFoun : print("Sample ",sName," specified for Experiment ",sTyp," not found - Error") return -1 #-- Injection Sample (SWL only) ------------------------------------- if sTyp == 'SWL' : if sNInj == None : print("No Injection Sample defined (using SINJ) for Experiment SWL - Error") return -1 else: nSamp = len(dicSAM) qFoun = False for iS in range(nSamp) : if sNInj == dicSAM[iS].sNam : qFoun = True clsEXP.setSinj(iS) clsEXP.setSNin(sNInj) break if not qFoun : print("Injection Sample ",sNInj," specified for Experiment SWL not found - Error") return -1 else : if sNInj != None : print("Experiment ",sTyp," does not support SINJ= parameter [SWL only] - Error") return -1 #-- Reservoir Temperature ------------------------------------------- if sTyp == 'CCE' or sTyp == 'CVD' or sTyp == 'DLE' or \ sTyp == 'SWL' or sTyp == 'GRD' : if Tres == None : print("No Reservoir Temperature defined (using TRES=) for Experiment ",sTyp," - Error") return -1 else : Tint = clsUNI.X2I(Tres,Tuni) if Tint == -999.9 : return -1 else : clsEXP.setTres(Tint,Tuni) #-- CCE Liquid Saturation Definition (SL = VL/VTot or SL = VL/Vdew) - if sTyp == 'CCE' : if sLCCE == None : print("CCE Experiment has not set SLIQ-Type: SLiq = VLiq/Vdew assumed") clsEXP.setSLCCE("DEW") else: if sLCCE == "DEW" or sLCCE == "TOT" : clsEXP.setSLCCE(sLCCE) else : print("SLIQ= argument of CCE Experiment = ",sLCCE,": Should be DEW or TOT - Error") return -1 else : if sLCCE != None : print("Experiment ",sTyp," does not support SLIQ= parameter [CCE only] - Error") return -1 #== Process the Column Headers and Associated Units =================== nHead = len(colH) nUnit = len(colU) #print("colH ",colH) #print("colU ",colU) if nHead != nUnit : print("Number of Column Headers not equal to Column Units for Experiment ",sTyp," - Error") return -1 #-- Number of Rows of Data and Initialise Structures in classEXP ---- nRowS = len(dTab) nObsL = nHead - nIndA if sTyp == "GRD" : nRowD = nRowS + 1 else : nRowD = nRowS clsEXP.createExpArrays(nIndA,nObsA,nCalA,nRowD) if sTyp == "GRD" : clsEXP.createCompArray(nRowD,nCom,"Z","C") #-- zCal-Array #-- SEP experiment; create Lsep & Vsep Arrays ----------------------- if sTyp == "SEP" : #-- Create Lsep/Vsep arrays clsEXP.createSepStages(nRowS) qLsep = False ; qVsep = False for i in range(nHead) : #-- Test if they have been read if colH[i].upper() == "LSEP" : qLsep = True if colH[i].upper() == "VSEP" : qVsep = True if qLsep and qVsep : qSep = True elif qLsep and not qVsep : print("Lsep provided but not Vsep - Error") return -1 elif not qLsep and qVsep : print("Vsep provided but not Lsep - Error") return -1 else : qSep = False #-- Calculated Data [Store Full Array Regardless of User Entry] ----- nTemp = len(clsEXP.hCal) for i in range(nCalA) : clsEXP.hCal[i] = sCalA[i] clsEXP.uCal[i] = clsUNI.DUN(sCalA[i]) #-- Independent Data ------------------------------------------------ nFoun = 0 for i in range(nIndA) : sInd = sIndA[i].upper() for j in range(nHead) : sCol = colH[j].upper() sUni = colU[j].upper() if sInd == sCol : nFoun += 1 clsEXP.hInd[i] = sCol clsEXP.uInd[i] = sUni #print("i,sInd,j,sCol,sUni ",i,sInd,j,sCol,sUni) for k in range(nRowS) : clsEXP.dInd[i][k] = clsUNI.X2I(dTab[k][j],sUni) #print("k,dTab,cInd ",k,dTab[k][j],clsEXP.dInd[i][k]) if nIndA != nFoun : print("Experiment ",sTyp," expects ",nIndA," columns of Independent data: Only ",nFoun," found - Error") return -1 #-- Independent/Observed Psat for selected Experiments -------------- if sTyp == "CCE" or sTyp == "CVD" or sTyp == "DLE" or sTyp == "SEP" : nRsat = clsEXP.nRsat if nRsat < 0 : print("Experiment ",sTyp," must have one row starting with PSAT - Error") return -1 else : PsatO = clsEXP.dInd[0][nRsat] PsatU = clsEXP.uInd[0] clsEXP.setPsatObs(PsatO) clsEXP.setPsatWei(dWps) clsEXP.setPsatUni(PsatU) #-- Reference Depth and Pressure for GRD ---------------------------- if sTyp == "GRD" : nDref = clsEXP.nDref if nDref < 0 : print("Experiment GRD must have one row starting with DREF - Error") return -1 else : Dref = clsEXP.dInd[0][nDref] Pref = None for i in range(nHead) : sObs = colH[i].upper() sUni = colU[i].upper() if sObs[:2] == "PR" : Pref = clsUNI.X2I(dTab[nDref][i],sUni) break if Pref == None : print("Experiment GRD must a Pressure define on DREF row - Error") return -1 clsEXP.setDref(Dref) clsEXP.setPref(Pref) #-- Observed Data --------------------------------------------------- qObsA = [False for i in range(nObsA)] nFoun = 0 iPlt = 0 for i in range(nHead) : sObs = colH[i].upper() sUni = colU[i].upper() for j in range(nObsA) : sCol = sObsA[j].upper() if sObs == sCol : clsEXP.hObs[j] = sCol clsEXP.uObs[j] = sUni clsEXP.uCal[j] = sUni #-- Over-write default Cal-Unit with Obs-Unit clsEXP.qObs[j] = True clsEXP.qPlt[j] = qPlt[iPlt] iPlt += 1 for k in range(nRowS) : clsEXP.dObs[j][k] = clsUNI.X2I(dTab[k][i],sUni) clsEXP.dWei[j][k] = dWal[j] nFoun += 1 if sTyp == "SEP" and sObs == "LSEP" : for k in range(nRowS) : clsEXP.Lsep[k] = int(dTab[k][i]) if sTyp == "SEP" and sObs == "VSEP" : for k in range(nRowS) : clsEXP.Vsep[k] = int(dTab[k][i]) clsEXP.setUserObs(nFoun) #-- If SEP experiment, default the Lsep/Vsep arrays if not set ------ if sTyp == "SEP" and not qSep : for k in range(nRowS) : if k == 0 : clsEXP.Lsep[k] = 1 ; clsEXP.Vsep[k] = 1 elif k == nRowS - 1 : clsEXP.Lsep[k] = 0 ; clsEXP.Vsep[k] = 0 else : clsEXP.Lsep[k] = k+1 ; clsEXP.Vsep[k] = 0 #== End of Routine ====================================================== if iERR == 0 : clsEXP.isDef = True #-- Exp is Defined!! return iERR
def calcIntSamp(clsEOS, dicSAM, clsUNI, clsIO): nSamp = len(dicSAM) nComp = clsEOS.nComp #== Process Existing Samples ========================================== iPlus = 0 for iC in range(nComp): if clsEOS.gPP("MW", iC) > 90.0: iPlus = iC break for iS in range(nSamp - 1): clsSAM = dicSAM[iS] clsSAM.sCom[iPlus] = UT.moleFracC7P(clsSAM.sCom, clsEOS) for iC in range(iPlus + 1, nComp): clsSAM.sCom[iC] = 0.0 #== New Sample ======================================================== clsSAM = dicSAM[nSamp - 1] #-- Get Working Sample-Class #-- Extract eXact (full supplied) string or Part of string ---------- X = 'X' P = 'P' #-- Total Number of Components and Plus Fraction Properties --------- nCom = clsSAM.nCtot nPlus = clsSAM.uPlsCN mPlus = clsSAM.uPlsMW sPlus = clsSAM.uPlsSG #-- Inorganics and Neo-Pentane -------------------------------------- iH2 = findComp("H2", X, clsSAM) iHE = findComp("HE", X, clsSAM) iN2 = findComp("N2", X, clsSAM) iCO2 = findComp("CO2", X, clsSAM) iH2S = findComp("H2S", X, clsSAM) iNeo = findComp("Neo", P, clsSAM) #-- First Few Hydrocarbons ------------------------------------------ iC1 = findComp("C1", X, clsSAM) iC2 = findComp("C2", X, clsSAM) iC3 = findComp("C3", X, clsSAM) iIC4 = findComp("iC4", X, clsSAM) iNC4 = findComp("nC4", X, clsSAM) iIC5 = findComp("iC5", X, clsSAM) iNC5 = findComp("nC5", X, clsSAM) #-- SCN's C6 to C11 ------------------------------------------------- iC6 = findComp("C6", X, clsSAM) iC7 = findComp("C7", X, clsSAM) iC8 = findComp("C8", X, clsSAM) iC9 = findComp("C9", X, clsSAM) iC10 = findComp("C10", X, clsSAM) iC11 = findComp("C11", X, clsSAM) #== Process =========================================================== #-- N2 [Nitrogen]: Also H2 & HE (will be zero or trace) ------------- zN2 = 0.0 if iN2 >= 0: zN2 = zN2 + clsSAM.uCom[iN2] if iH2 >= 0: zN2 = zN2 + clsSAM.uCom[iH2] if iHE >= 0: zN2 = zN2 + clsSAM.uCom[iHE] if zN2 > 0.0: clsSAM.setInternal("N2", zN2) #-- CO2 and H2S ----------------------------------------------------- zCO2 = 0.0 zH2S = 0.0 if iCO2 >= 0: zCO2 = zCO2 + clsSAM.uCom[iCO2] if iH2S >= 0: zH2S = zH2S + clsSAM.uCom[iH2S] if zCO2 > 0.0: clsSAM.setInternal("CO2", zCO2) if zH2S > 0.0: clsSAM.setInternal("H2S", zH2S) #-- C1 -> nC5 ------------------------------------------------------- zC1 = 0.0 zC2 = 0.0 zC3 = 0.0 zIC4 = 0.0 zNC4 = 0.0 zIC5 = 0.0 zNC5 = 0.0 if iC1 >= 0: zC1 = zC1 + clsSAM.uCom[iC1] if iC2 >= 0: zC2 = zC2 + clsSAM.uCom[iC2] if iC3 >= 0: zC3 = zC3 + clsSAM.uCom[iC3] if iIC4 >= 0: zIC4 = zIC4 + clsSAM.uCom[iIC4] if iNC4 >= 0: zNC4 = zNC4 + clsSAM.uCom[iNC4] if iIC5 >= 0: zIC5 = zIC5 + clsSAM.uCom[iIC5] if iNC5 >= 0: zNC5 = zNC5 + clsSAM.uCom[iNC5] if iNeo >= 0: zIC5 = zIC5 + clsSAM.uCom[iNeo] if zC1 > 0.0: clsSAM.setInternal("C1", zC1) if zC2 > 0.0: clsSAM.setInternal("C2", zC2) if zC3 > 0.0: clsSAM.setInternal("C3", zC3) if zIC4 > 0.0: clsSAM.setInternal("IC4", zIC4) if zNC4 > 0.0: clsSAM.setInternal("NC4", zNC4) if zIC5 > 0.0: clsSAM.setInternal("IC5", zIC5) if zNC5 > 0.0: clsSAM.setInternal("NC5", zNC5) #-- SCN's C6 -> C10 ------------------------------------------------- uC7P = [] if iC6 >= 0: zC6 = clsSAM.uCom[iC6] if zC6 > 0.0: clsSAM.setInternal("C6", zC6) if nPlus > 7: uC7P = sumSCN(iC6, iC7, uC7P, clsSAM) if nPlus > 8: uC7P = sumSCN(iC7, iC8, uC7P, clsSAM) if nPlus > 9: uC7P = sumSCN(iC8, iC9, uC7P, clsSAM) if nPlus > 10: #-- C10 uC7P = sumSCN(iC9, iC10, uC7P, clsSAM) iCN = 11 for iC in range(iC10 + 1, nCom - 1): zNam = 'C' + str(iCN) uC7P.append(clsSAM.uCom[iC]) iCN = iCN + 1 nC7P = len(uC7P) #print("nC7P ",nC7P) #-- User Plus Fraction ---------------------------------------------- zPlus = "C" + str(nPlus) + "+" #== Internal [C7+] Plus Fraction Properties =========================== clsLIB = AP.classLIB() zC7P = 0.0 mC7P = 0.0 sC7P = 0.0 jC7P = 7 for iC7P in range(nC7P): zNam = 'C' + str(jC7P) zC7P = zC7P + uC7P[iC7P] mC7P = mC7P + uC7P[iC7P] * clsLIB.scnMW[zNam] sC7P = sC7P + uC7P[iC7P] * clsLIB.scnMW[zNam] / clsLIB.scnSG[zNam] jC7P = jC7P + 1 #print("zNam,z,Mw,SG ",zNam,uC7P[iC7P],clsLIB.scnMW[zNam],clsLIB.scnSG[zNam]) #-- Add User Plus Fraction ------------------------------------------ zPls = clsSAM.uCom[nCom - 1] #print("zPls,mPls,sPls ",zPls,clsSAM.uPlsMW,clsSAM.uPlsSG) zC7P = zC7P + zPls mC7P = mC7P + zPls * clsSAM.uPlsMW sC7P = sC7P + zPls * clsSAM.uPlsMW / clsSAM.uPlsSG #-- Renormalise the MW & SG ----------------------------------------- zInt = 'C7+' sC7P = mC7P / sC7P mC7P = mC7P / zC7P #print("zNam,zC7P,mC7P,sC7P {:s} {:7.5f} {:7.3f} {:7.5f}".format(zInt,zC7P,mC7P,sC7P)) #== Calculate Whitson-Alpha Parameter, if Appropriate ================= if nC7P > 5: #-- Minimum & Maximum Values ---------------------------------------- aMin = 0.5 fMin = fitAlpha(aMin, zC7P, mC7P, uC7P) aMax = 2.5 fMax = fitAlpha(aMax, zC7P, mC7P, uC7P) #== Brent's Method to minimise fSSQ and hence optimal-Alpha =========== fMid = 1.0E+6 #-- Mid-Value less than Min or Max? --------------------------------- while fMid > fMin or fMid > fMax: aMid = 0.5 * (aMin + aMax) fMid = fitAlpha(aMid, zC7P, mC7P, uC7P) if fMid > fMax: aMin = aMid fMin = fMid if fMid > fMin: aMax = aMid fMax = fMid #== Call Brent ======================================================== alfa = brentAlpha(aMin, aMid, aMax, zC7P, mC7P, uC7P) else: alfa = 1.0 #-- Default Value if Fit Not Possible #== Add Values to the Sample Class ==================================== clsSAM.setInternal(zInt, zC7P) clsSAM.setIntPlusMW(mC7P) clsSAM.setIntPlusSG(sC7P) clsSAM.setIntPlusAL(alfa) nUser = len(clsSAM.iCom) nPseu = clsEOS.NumPsu #-- #Pseudo's to split from C7+ nCint = nUser + nPseu - 1 clsSAM.setIntComp(nCint, nUser) clsEOS.setNComp(nCint) clsEOS.setNUser(nUser) clsEOS.setNPseu(nPseu) clsEOS.setNSamp(nSamp) #-- And define component names in EOS-class ------------------------- for iC in range(nUser): clsEOS.sNM(iC, clsSAM.iNam[iC]) #-- And copy 'internal' composition to 'working' -------------------- for iC in range(nUser): clsSAM.sZI(iC, clsSAM.iCom[iC]) #== Calculate Properties ============================================== iERR = CP.allProps(clsEOS, dicSAM, clsUNI, clsIO) #== Return ============================================================ return