Source code for darts.models.physics_sup.properties_black_oil

import numpy as np
from darts.engines import property_evaluator_iface
from .interpolation import TableInterpolation
from darts.tools.keyword_file_tools import *

[docs]class DensityGas:
[docs] def __init__(self, pvt): super().__init__() self.pvt = pvt self.dens_sc = get_table_keyword(self.pvt, 'DENSITY')[0][2] self.table = get_table_keyword(self.pvt, 'PVDG')
[docs] def evaluate(self, pres, pbub, xgo): pres_index = 0 # first column in the table - pressure Bg_index = 1 # second column in the table - volume factor Table = TableInterpolation() if (pres < self.table[0][0] or pres > self.table[len(self.table) - 1][0]): Bg = Table.LinearExtraP(self.table, pres, pres_index, Bg_index) else: Bg = Table.LinearInterP(self.table, pres, pres_index, Bg_index) return self.dens_sc / Bg
[docs]class DensityWat:
[docs] def __init__(self, pvt): super().__init__() self.pvt = pvt self.dens_sc = get_table_keyword(self.pvt, 'DENSITY')[0][1] self.table = get_table_keyword(self.pvt, 'PVTW')[0]
[docs] def evaluate(self, pres, pbub, xgo): X = self.table[2] * (pres - self.table[0]) Bw = self.table[1] / (1 + X + X * X / 2) return self.dens_sc / Bw
[docs]class ViscGas:
[docs] def __init__(self, pvt): super().__init__() self.pvt = pvt self.table = get_table_keyword(self.pvt, 'PVDG')
[docs] def evaluate(self, pres, pbub): pres_index = 0 # first column in the table - pressure vgas_index = 2 # third column in the table - viscosity Table = TableInterpolation() if (pres < self.table[0][0] or pres > self.table[len(self.table) - 1][0]): visco_gas = Table.LinearExtraP(self.table, pres, pres_index, vgas_index) else: visco_gas = Table.LinearInterP(self.table, pres, pres_index, vgas_index) return visco_gas
[docs]class ViscWat:
[docs] def __init__(self, pvt): super().__init__() self.pvt = pvt self.table = get_table_keyword(self.pvt, 'PVTW')[0]
[docs] def evaluate(self, pres, pbub): Y = -self.table[4] * (pres - self.table[0]) visco_wat = self.table[3] / (1 + Y + Y * Y / 2) return visco_wat
[docs]class flash_black_oil:
[docs] def __init__(self, pvt): super().__init__() self.pvt = pvt self.dens = get_table_keyword(self.pvt, 'DENSITY')[0] self.oil_dens = self.dens[0] self.gas_dens = self.dens[2] self.table = get_table_keyword(self.pvt, 'PVTO') self.len_table = len(self.table)
[docs] def bubble_point_pressure(self, pres, z): zg = z[0] zo = z[1] sat_rs = self.oil_dens / (self.gas_dens * (zo + zg) / zg - self.gas_dens) rs_index = 0 # first column in the table - rs pres_index = 1 # second column in the table - pressure Table = TableInterpolation() # find the index of saturated Rs for i in range(self.len_table - 1): if (self.table[i][0] == self.table[i+1][0]): num = i break if (sat_rs < self.table[0][0]): pbub = Table.LinearExtraP(self.table, sat_rs, rs_index, pres_index) elif (sat_rs > self.table[self.len_table-1][0]): pbub = Table.SatExtrapolation(self.table, sat_rs, rs_index, pres_index, num) else: pbub = Table.LinearInterP(self.table, sat_rs, rs_index, pres_index) if pres>pbub: pbub = pbub else: pbub = pres return pbub
[docs] def evaluate(self, pres, z): zg = z[0] zo = z[1] zw = 1 - zg - zo pbub = self.bubble_point_pressure(pres, z) rs_index = 0 # first column in the table - rs pres_index = 1 # second column in the table - pressure Table = TableInterpolation() # find the index of saturated Rs for i in range(self.len_table - 1): if (self.table[i][0] == self.table[i + 1][0]): num = i break # undersaturated condition if (pres > pbub): rs = self.oil_dens / (self.gas_dens * (zo+zg) / zg - self.gas_dens) # saturated condition else: if pres<self.table[0][1]: rs = Table.LinearExtraP(self.table, pres, pres_index, rs_index) elif pres>self.table[num][1]: rs = Table.SatExtrapolation(self.table, pres, pres_index, rs_index, num) else: rs = Table.LinearInterP(self.table, pres, pres_index, rs_index) xgo = self.gas_dens * rs / (self.oil_dens + self.gas_dens * rs) V = 1 - zw - zo / (1 - xgo) return xgo, V, pbub
[docs]class DensityOil:
[docs] def __init__(self, pvt): super().__init__() self.pvt = pvt self.dens_sc = get_table_keyword(self.pvt, 'DENSITY')[0][0] self.table = get_table_keyword(self.pvt, 'PVTO') self.len_table = len(self.table)
[docs] def evaluate(self, pres, pbub, xgo): pres_index = 1 Bo_index = 2 Table = TableInterpolation() # find the index of max Bo for i in range(self.len_table - 1): if (self.table[i][2] >= self.table[i + 1][2]): num = i break # calculate the saturated Bo if (pbub < self.table[0][1]): Bo_bub = Table.LinearExtraP(self.table, pbub, pres_index, Bo_index) elif (pbub > self.table[num][1]): Bo_bub = Table.SatExtrapolation(self.table, pbub, pres_index, Bo_index, num) else: Bo_bub = Table.LinearInterP(self.table, pbub, pres_index, Bo_index) # calculate Bo in current pressure # (1) saturated condition if pres < pbub: if (pres < self.table[0][1]): Bo = Table.LinearExtraP(self.table, pres, pres_index, Bo_index) elif (pres > self.table[num][1]): Bo = Table.SatExtrapolation(self.table, pres, pres_index, Bo_index, num) else: Bo = Table.LinearInterP(self.table, pres, pres_index, Bo_index) # (2) undersaturated condition else: pres_undersat = pres + self.table[num][1] - pbub Bo_undersat = Table.SatExtrapolation(self.table, pres_undersat, pres_index, Bo_index, num+1) if (pbub < self.table[num][1]): Bo = Bo_undersat * Bo_bub / self.table[num][2] else: Bo = Bo_undersat - (self.table[num][2] - Bo_bub) return self.dens_sc / Bo / (1 - xgo)
[docs]class ViscOil:
[docs] def __init__(self, pvt): super().__init__() self.pvt = pvt self.table = get_table_keyword(self.pvt, 'PVTO') self.len_table = len(self.table)
[docs] def evaluate(self, pres, pbub): pres_index = 1 visco_index = 3 Table = TableInterpolation() # find the index of min visco for i in range(self.len_table - 1): if (self.table[i][3] <= self.table[i + 1][3]): num = i break # calculate the saturated viscosity if (pbub < self.table[0][1]): visco_bub = Table.LinearExtraP(self.table, pbub, pres_index, visco_index) elif (pbub > self.table[num][1]): visco_bub = Table.SatExtrapolation(self.table, pbub, pres_index, visco_index, num) else: visco_bub = Table.LinearInterP(self.table, pbub, pres_index, visco_index) # calculate viscosity at current pressure # (1) saturated condition if pres < pbub: if (pres < self.table[0][1]): visco = Table.LinearExtraP(self.table, pres, pres_index, visco_index) elif (pres > self.table[num][1]): visco = Table.SatExtrapolation(self.table, pres, pres_index, visco_index, num) else: visco = Table.LinearInterP(self.table, pres, pres_index, visco_index) # (2) undersaturated condition else: pres_undersat = pres + self.table[num][1] - pbub visco_undersat = Table.SatExtrapolation(self.table, pres_undersat, pres_index, visco_index, num + 1) if (pbub < self.table[num][1]): visco = visco_undersat * visco_bub / self.table[num][3] else: visco = visco_undersat - (self.table[num][3] - visco_bub) return visco
[docs]class WatRelPerm:
[docs] def __init__(self, pvt): super().__init__() self.pvt = pvt self.SWOF = get_table_keyword(self.pvt, 'SWOF')
[docs] def evaluate(self, gas_sat, wat_sat): wat_index = 0 krw_index = 1 Table = TableInterpolation() if (wat_sat < self.SWOF[0][0] or wat_sat > self.SWOF[len(self.SWOF) - 1][0]): krw = Table.SCALExtraP(self.SWOF, wat_sat, wat_index, krw_index) else: krw = Table.LinearInterP(self.SWOF, wat_sat, wat_index, krw_index) return krw
[docs]class GasRelPerm:
[docs] def __init__(self, pvt): super().__init__() self.pvt = pvt self.SGOF = get_table_keyword(self.pvt, 'SGOF')
[docs] def evaluate(self, gas_sat, wat_sat): gas_index = 0 krg_index = 1 Table = TableInterpolation() if (gas_sat < self.SGOF[0][0] or gas_sat > self.SGOF[len(self.SGOF) - 1][0]): krg = Table.SCALExtraP(self.SGOF, gas_sat, gas_index, krg_index) else: krg = Table.LinearInterP(self.SGOF, gas_sat, gas_index, krg_index) return krg
# here we use Stone I model to calculate oil relperm
[docs]class OilRelPerm:
[docs] def __init__(self, pvt): super().__init__() self.pvt = pvt self.SGOF = get_table_keyword(self.pvt, 'SGOF') self.SWOF = get_table_keyword(self.pvt, 'SWOF')
[docs] def Krog(self, gas_sat): gas_index = 0 krog_index = 2 Table = TableInterpolation() if (gas_sat < self.SGOF[0][0] or gas_sat > self.SGOF[len(self.SGOF) - 1][0]): krog = Table.SCALExtraP(self.SGOF, gas_sat, gas_index, krog_index) else: krog = Table.LinearInterP(self.SGOF, gas_sat, gas_index, krog_index) return krog
[docs] def Krow(self, wat_sat): wat_index = 0 krow_index = 2 Table = TableInterpolation() if (wat_sat < self.SWOF[0][0] or wat_sat > self.SWOF[len(self.SWOF) - 1][0]): krow = Table.SCALExtraP(self.SWOF, wat_sat, wat_index, krow_index) else: krow = Table.LinearInterP(self.SWOF, wat_sat, wat_index, krow_index) return krow
[docs] def evaluate(self, gas_sat, wat_sat): len_SWOF = len(self.SWOF) len_SGOF = len(self.SGOF) Sorw = 1 - self.SWOF[len_SWOF - 1][0] Sorg = 1 - self.SGOF[len_SGOF - 1][0] Swc = self.SWOF[0][0] MINIMAL_FOR_COMPARE = 1e-12 Krocw = self.SWOF[0][2] SatLimit = 1 - 2 * MINIMAL_FOR_COMPARE oil_sat = 1 - wat_sat - gas_sat krow = self.Krow(wat_sat) krog = self.Krog(gas_sat) if (gas_sat < MINIMAL_FOR_COMPARE): kro = krow # water-oil two phases elif (wat_sat < Swc): kro = krog # water phase not mobile else: # Stone I model -> alpha alpha = 1 - gas_sat / (1 - min(Swc + Sorg, SatLimit)) # -> Som Som = alpha * Sorw + (1.0 - alpha) * Sorg # -> denom denom = 1.0 / (1.0 - min(Swc + Som, SatLimit)) # Normalized saturations if (oil_sat - Som) > 0: Ma = oil_sat - Som else: Ma = 0 SoStar = Ma * denom SwStar = min(wat_sat - Swc, SatLimit) * denom SgStar = min(gas_sat, SatLimit) * denom kro = (SoStar * krow * krog) / (Krocw * (1.0 - SwStar) * (1.0 - SgStar)) return kro
[docs]class RockCompactionEvaluator:
[docs] def __init__(self, pvt): super().__init__() self.pvt = pvt self.rock_table = get_table_keyword(self.pvt, 'ROCK')
[docs] def evaluate(self, state): pressure = state[0] pressure_ref = self.rock_table[0][0] compressibility = self.rock_table[0][1] return 1.0 + compressibility * (pressure - pressure_ref)
# capillary pressure based on table
[docs]class CapillaryPressurePcow(property_evaluator_iface):
[docs] def __init__(self, pvt): super().__init__() self.pvt = pvt self.SWOF = get_table_keyword(self.pvt, 'SWOF')
[docs] def evaluate(self, wat_sat): wat_index = 0 pc_index = 3 Table = TableInterpolation() if (wat_sat < self.SWOF[0][0] or wat_sat > self.SWOF[len(self.SWOF) - 1][0]): pcow = Table.SCALExtraP(self.SWOF, wat_sat, wat_index, pc_index) else: pcow = Table.LinearInterP(self.SWOF, wat_sat, wat_index, pc_index) return pcow
[docs]class CapillaryPressurePcgo(property_evaluator_iface):
[docs] def __init__(self, pvt): super().__init__() self.pvt = pvt self.SGOF = get_table_keyword(self.pvt, 'SGOF')
[docs] def evaluate(self, gas_sat): gas_index = 0 pc_index = 3 Table = TableInterpolation() if (gas_sat < self.SGOF[0][0] or gas_sat > self.SGOF[len(self.SGOF) - 1][0]): pcgo = Table.SCALExtraP(self.SGOF, gas_sat, gas_index, pc_index) else: pcgo = Table.LinearInterP(self.SGOF, gas_sat, gas_index, pc_index) return pcgo