Source code for gemini_model.fluid.pvt_sim

"""Tabulated PVT (PVTsim .tab) loader and interpolator.

Reads PVT tables exported from PVTsim (KEY format) and provides 2D
interpolators over pressure and temperature for common properties.
"""

import numpy as np
from scipy import interpolate


[docs] class PVT: """PVT table model with interpolation over P and T.""" def __init__(self): """Initialize PVT simulation model.""" self.parameters = {} self.parameters["pressure_max"] = None self.parameters["pressure_min"] = None self.parameters["temperature_max"] = None self.parameters["temperature_min"] = None
[docs] def update_parameters(self, parameters): """Update model parameters. Parameters ---------- parameters: dict Parameters dict as defined by the model. """ for key, value in parameters.items(): self.parameters[key] = value
[docs] def load_pvt_tables(self, pvt_file): """Load a PVTsim .tab file generated using the table format KEY.""" f = open(pvt_file, "r") tlines = f.readlines() kk = 1 nP = int(tlines[kk].split()[0]) nT = int(tlines[kk].split()[1]) PT = [] while len(PT) < nP: kk += 1 PT.extend(tlines[kk].split()) PT = [float(x) for x in PT] self.PT = np.array(PT) TM = [] while len(TM) < nT: kk += 1 TM.extend(tlines[kk].split()) TM = [float(x) for x in TM] self.TM = np.array(TM) spare = [] while len(spare) < 2 * nT: kk += 1 spare.extend(tlines[kk].split()) # GAS DENSITY (KG/M3) kk += 1 # print(tlines[kk]) RHOG = [] while len(RHOG) < nP * nT: kk += 1 RHOG.extend(tlines[kk].split()) RHOG = [float(x) for x in RHOG] self.RHOG = np.array(RHOG) self.RHOG = self.RHOG.reshape(nP, nT) # LIQUID DENSITY (KG/M3) kk += 1 # print(tlines[kk]) RHOL = [] while len(RHOL) < nP * nT: kk += 1 RHOL.extend(tlines[kk].split()) RHOL = [float(x) for x in RHOL] self.RHOL = np.array(RHOL) self.RHOL = self.RHOL.reshape(nP, nT) # WATER DENSITY (KG/M3) kk += 1 # print(tlines[kk]) RHOW = [] while len(RHOW) < nP * nT: kk += 1 RHOW.extend(tlines[kk].split()) RHOW = [float(x) for x in RHOW] self.RHOW = np.array(RHOW) self.RHOW = self.RHOW.reshape(nP, nT) # PRES. DERIV. OF GAS DENS. kk += 1 # print(tlines[kk]) RHOGP = [] while len(RHOGP) < nP * nT: kk += 1 RHOGP.extend(tlines[kk].split()) RHOGP = [float(x) for x in RHOGP] self.RHOGP = np.array(RHOGP) self.RHOGP = self.RHOGP.reshape(nP, nT) # PRES. DERIV. OF LIQUID DENS. kk += 1 # print(tlines[kk]) RHOLP = [] while len(RHOLP) < nP * nT: kk += 1 RHOLP.extend(tlines[kk].split()) RHOLP = [float(x) for x in RHOLP] self.RHOLP = np.array(RHOLP) self.RHOLP = self.RHOLP.reshape(nP, nT) # PRES. DERIV. OF WATER DENS. kk += 1 # print(tlines[kk]) RHOWP = [] while len(RHOWP) < nP * nT: kk += 1 RHOWP.extend(tlines[kk].split()) RHOWP = [float(x) for x in RHOWP] self.RHOWP = np.array(RHOWP) self.RHOWP = self.RHOWP.reshape(nP, nT) # TEMP. DERIV. OF GAS DENS. kk += 1 # print(tlines[kk]) RHOGT = [] while len(RHOGT) < nP * nT: kk += 1 RHOGT.extend(tlines[kk].split()) RHOGT = [float(x) for x in RHOGT] self.RHOGT = np.array(RHOGT) self.RHOGT = self.RHOGT.reshape(nP, nT) # TEMP. DERIV. OF LIQUID DENS. kk += 1 # print(tlines[kk]) RHOLT = [] while len(RHOLT) < nP * nT: kk += 1 RHOLT.extend(tlines[kk].split()) RHOLT = [float(x) for x in RHOLT] self.RHOLT = np.array(RHOLT) self.RHOLT = self.RHOLT.reshape(nP, nT) # TEMP. DERIV. OF WATER DENS. kk += 1 # print(tlines[kk]) RHOWT = [] while len(RHOWT) < nP * nT: kk += 1 RHOWT.extend(tlines[kk].split()) RHOWT = [float(x) for x in RHOWT] self.RHOWT = np.array(RHOWT) self.RHOWT = self.RHOWT.reshape(nP, nT) # GAS MASS FRACTION OF GAS + OIL kk += 1 # print(tlines[kk]) GMF = [] while len(GMF) < nP * nT: kk += 1 GMF.extend(tlines[kk].split()) GMF = [float(x) for x in GMF] self.GMF = np.array(GMF) self.GMF = self.GMF.reshape(nP, nT) # WATER MASS FRACTION OF GAS + OIL kk += 1 # print(tlines[kk]) WMF = [] while len(WMF) < nP * nT: kk += 1 WMF.extend(tlines[kk].split()) WMF = [float(x) for x in WMF] self.WMF = np.array(WMF) self.WMF = self.WMF.reshape(nP, nT) # GAS VISCOSITY (N S/M2) kk += 1 # print(tlines[kk]) VISG = [] while len(VISG) < nP * nT: kk += 1 VISG.extend(tlines[kk].split()) VISG = [float(x) for x in VISG] self.VISG = np.array(VISG) self.VISG = self.VISG.reshape(nP, nT) # LIQUID VISCOSITY (N S/M2) kk += 1 # print(tlines[kk]) VISL = [] while len(VISL) < nP * nT: kk += 1 VISL.extend(tlines[kk].split()) VISL = [float(x) for x in VISL] self.VISL = np.array(VISL) self.VISL = self.VISL.reshape(nP, nT) # WATER VISCOSITY (N S/M2) kk += 1 # print(tlines[kk]) VISW = [] while len(VISW) < nP * nT: kk += 1 VISW.extend(tlines[kk].split()) VISW = [float(x) for x in VISW] self.VISW = np.array(VISW) self.VISW = self.VISW.reshape(nP, nT) # GAS SPECIFIC HEAT (J/KG K) kk += 1 # print(tlines[kk]) CPG = [] while len(CPG) < nP * nT: kk += 1 CPG.extend(tlines[kk].split()) CPG = [float(x) for x in CPG] self.CPG = np.array(CPG) self.CPG = self.CPG.reshape(nP, nT) # LIQUID SPECIFIC HEAT (J/KG K) kk += 1 # print(tlines[kk]) CPL = [] while len(CPL) < nP * nT: kk += 1 CPL.extend(tlines[kk].split()) CPL = [float(x) for x in CPL] self.CPL = np.array(CPL) self.CPL = self.CPL.reshape(nP, nT) # WATER SPECIFIC HEAT (J/KG K) kk += 1 # print(tlines[kk]) CPW = [] while len(CPW) < nP * nT: kk += 1 CPW.extend(tlines[kk].split()) CPW = [float(x) for x in CPW] self.CPW = np.array(CPW) self.CPW = self.CPW.reshape(nP, nT) # GAS ENTHALPY (J/KG) kk += 1 # print(tlines[kk]) HG = [] while len(HG) < nP * nT: kk += 1 HG.extend(tlines[kk].split()) HG = [float(x) for x in HG] self.HG = np.array(HG) self.HG = self.HG.reshape(nP, nT) # LIQUID ENTHALPY (J/KG) kk += 1 # print(tlines[kk]) HL = [] while len(HL) < nP * nT: kk += 1 HL.extend(tlines[kk].split()) HL = [float(x) for x in HL] self.HL = np.array(HL) self.HL = self.HL.reshape(nP, nT) # WATER ENTHALPY (J/KG) kk += 1 # print(tlines[kk]) HW = [] while len(HW) < nP * nT: kk += 1 HW.extend(tlines[kk].split()) HW = [float(x) for x in HW] self.HW = np.array(HW) self.HW = self.HW.reshape(nP, nT) # GAS THERMAL COND. (W/M K) kk += 1 # print(tlines[kk]) TCG = [] while len(TCG) < nP * nT: kk += 1 TCG.extend(tlines[kk].split()) TCG = [float(x) for x in TCG] self.TCG = np.array(TCG) self.TCG = self.TCG.reshape(nP, nT) # LIQUID THERMAL COND. (W/M K) kk += 1 # print(tlines[kk]) TCL = [] while len(TCL) < nP * nT: kk += 1 TCL.extend(tlines[kk].split()) TCL = [float(x) for x in TCL] self.TCL = np.array(TCL) self.TCL = self.TCL.reshape(nP, nT) # WATER THERMAL COND. (W/M K) kk += 1 # print(tlines[kk]) TCW = [] while len(TCW) < nP * nT: kk += 1 TCW.extend(tlines[kk].split()) TCW = [float(x) for x in TCW] self.TCW = np.array(TCW) self.TCW = self.TCW.reshape(nP, nT) # SURFACE TENSION GAS/OIL (N/M) kk += 1 # print(tlines[kk]) SIGMAGO = [] while len(SIGMAGO) < nP * nT: kk += 1 SIGMAGO.extend(tlines[kk].split()) SIGMAGO = [float(x) for x in SIGMAGO] self.SIGMAGO = np.array(SIGMAGO) self.SIGMAGO = self.SIGMAGO.reshape(nP, nT) # SURFACE TENSION GAS/WATER (N/M) kk += 1 # print(tlines[kk]) SIGMAGW = [] while len(SIGMAGW) < nP * nT: kk += 1 SIGMAGW.extend(tlines[kk].split()) SIGMAGW = [float(x) for x in SIGMAGW] self.SIGMAGW = np.array(SIGMAGW) self.SIGMAGW = self.SIGMAGW.reshape(nP, nT) # SURFACE TENSION WATER/OIL (N/M) kk += 1 # print(tlines[kk]) SIGMAWO = [] while len(SIGMAWO) < nP * nT: kk += 1 SIGMAWO.extend(tlines[kk].split()) SIGMAWO = [float(x) for x in SIGMAWO] self.SIGMAWO = np.array(SIGMAWO) self.SIGMAWO = self.SIGMAWO.reshape(nP, nT) # GAS ENTROPY (J/KG/C) kk += 1 # print(tlines[kk]) SG = [] while len(SG) < nP * nT: kk += 1 SG.extend(tlines[kk].split()) SG = [float(x) for x in SG] self.SG = np.array(SG) self.SG = self.SG.reshape(nP, nT) # LIQUID ENTROPY (J/KG/C) kk += 1 # print(tlines[kk]) SL = [] while len(SL) < nP * nT: kk += 1 SL.extend(tlines[kk].split()) SL = [float(x) for x in SL] self.SL = np.array(SL) self.SL = self.SL.reshape(nP, nT) # WATER ENTROPY (J/KG/C) kk += 1 # print(tlines[kk]) SW = [] while len(SW) < nP * nT: kk += 1 SW.extend(tlines[kk].split()) SW = [float(x) for x in SW] self.SW = np.array(SW) self.SW = self.SW.reshape(nP, nT) f.close() self.parameters["pressure_max"] = max(self.PT) self.parameters["pressure_min"] = min(self.PT) self.parameters["temperature_max"] = max(self.TM) self.parameters["temperature_min"] = min(self.TM) self.create_fit_fuction()
[docs] def create_fit_fuction(self): """Create 2D interpolants for each PVT property.""" self.f_RHOG = interpolate.interp2d(self.PT, self.TM, np.transpose(self.RHOG)) self.f_VISG = interpolate.interp2d(self.PT, self.TM, np.transpose(self.VISG)) self.f_RHOL = interpolate.interp2d(self.PT, self.TM, np.transpose(self.RHOL)) self.f_RHOW = interpolate.interp2d(self.PT, self.TM, np.transpose(self.RHOW)) self.f_SL = interpolate.interp2d(self.PT, self.TM, np.transpose(self.SL)) self.f_SW = interpolate.interp2d(self.PT, self.TM, np.transpose(self.SW)) self.f_VISL = interpolate.interp2d(self.PT, self.TM, np.transpose(self.VISL)) self.f_VISW = interpolate.interp2d(self.PT, self.TM, np.transpose(self.VISW)) self.f_GMF = interpolate.interp2d(self.PT, self.TM, np.transpose(self.GMF)) self.f_CPG = interpolate.interp2d(self.PT, self.TM, np.transpose(self.CPG)) self.f_CPL = interpolate.interp2d(self.PT, self.TM, np.transpose(self.CPL)) self.f_TCG = interpolate.interp2d(self.PT, self.TM, np.transpose(self.TCG)) self.f_TCL = interpolate.interp2d(self.PT, self.TM, np.transpose(self.TCL)) self.f_SIGMAGW = interpolate.interp2d(self.PT, self.TM, np.transpose(self.SIGMAGW))
[docs] def get_pvt(self, P, T): """Interpolate PVT properties at pressure P (Pa) and temperature T (K). Parameters ---------- P : float Pressure (Pa). T : float Temperature (K). Returns ------- rho_g : float Gas density (kg/m3). rho_l : float Liquid density (kg/m3). gmf : float Gas mass fraction (-). eta_g : float Viscosity gas (Pa.s). eta_l : float Viscosity liquid (Pa.s). cp_g : float Heat capacity gas (J/Kg/K). cp_l : float Heat capacity liquid (J/Kg/K). K_g : float Thermal conductivity gas (W/m/K). K_l : float Thermal conductivity liquid (W/m/K). sigma : float Surface tension (N/m). """ rho_g = self.f_RHOG(P, T) rho_l = self.f_RHOL(P, T) gmf = self.f_GMF(P, T) eta_g = self.f_VISG(P, T) eta_l = self.f_VISL(P, T) cp_g = self.f_CPG(P, T) cp_l = self.f_CPL(P, T) K_g = self.f_TCG(P, T) K_l = self.f_TCL(P, T) sigma = self.f_SIGMAGW(P, T) return rho_g, rho_l, gmf, eta_g, eta_l, cp_g, cp_l, K_g, K_l, sigma