def create_water_oil_gas(params=None): """Create a WaterOilGas object from a dictionary of parameters Parameterization (Corey/LET) is inferred from presence of certain parameters in the dictionary. """ if not params: params = dict() if not isinstance(params, dict): raise TypeError( "Parameter to create_water_oil_gas must be a dictionary") # For case insensitiveness, all keys are converted to lower case: params = {key.lower(): value for (key, value) in params.items()} wateroil = PyscalFactory.create_water_oil(params) gasoil = PyscalFactory.create_gas_oil(params) wog_init_params = slicedict(params, WOG_INIT) wateroilgas = WaterOilGas(**wog_init_params) # The wateroilgas __init__ has already created WaterOil and GasOil objects # but we overwrite the references with newly created ones, this factory function # must then guarantee that they are compatible. wateroilgas.wateroil = wateroil wateroilgas.gasoil = gasoil if not wateroilgas.selfcheck(): raise ValueError(("Incomplete WaterOilGas object, " "some parameters missing to factory")) return wateroilgas
def multiplesatnums(): """Test of a case where there are multiple satnums""" satnums = [] satnums.append( WaterOilGas(swirr=0.01, swl=0.1, sgcr=0.05, sorg=0.1, tag="Good sand") ) satnums[0].wateroil.add_corey_oil(3) satnums[0].wateroil.add_corey_water(2.5) satnums[0].wateroil.add_simple_J() satnums[0].gasoil.add_corey_oil(4) satnums[0].gasoil.add_corey_gas(1) satnums.append( WaterOilGas(swirr=0.35, swl=0.4, sgcr=0.05, sorg=0.1, tag="Bad sand") ) satnums[1].wateroil.add_corey_oil(4) satnums[1].wateroil.add_corey_water(5) satnums[1].wateroil.add_simple_J() satnums[1].gasoil.add_corey_oil(4) satnums[1].gasoil.add_corey_gas(1) if satnums[0].selfcheck() and satnums[1].selfcheck(): print(satnums[0].wateroil.SWOF()) print(satnums[1].wateroil.SWOF(header=False)) print(satnums[0].gasoil.SGOF()) print(satnums[1].gasoil.SGOF(header=False))
def test_threephasecheck(): """Test three phase consistency checks""" wog = WaterOilGas() assert not wog.selfcheck() wog.wateroil.add_corey_water(nw=2) wog.wateroil.add_corey_oil(now=2, kroend=0.9) wog.gasoil.add_corey_gas(ng=2) wog.gasoil.add_corey_oil(nog=2, kroend=1) assert not wog.threephaseconsistency()
def test_not_threephase_consistency(): wog = WaterOilGas() # To trigger this, we need to hack the WaterOilGas object # by overriding the effect of its __init__ wog.wateroil = WaterOil(swl=0.4) wog.gasoil = GasOil(swl=0.2) wog.wateroil.add_corey_water(nw=2) wog.wateroil.add_corey_oil(now=2, kroend=0.9) wog.gasoil.add_corey_gas(ng=2) wog.gasoil.add_corey_oil(nog=2, kroend=1) assert not wog.threephaseconsistency()
def gen_wog(parameters: pd.DataFrame, fast_pyscal: bool = False) -> WaterOilGas: """ Creates a PyScal WaterOilGas object based on the input parameters supplied. Args: parameters: A dataframe consisting of all specified parameters. fast_pyscal: Run pyscal in fast-mode skipping checks. Useful for large models/ensemble. Returns: A PyScal WaterOilGas object """ wog_relperm = WaterOilGas( swirr=parameters["swirr"], swl=parameters["swl"], swcr=parameters["swcr"], sorw=parameters["sorw"], sorg=parameters["sorg"], sgcr=parameters["sgcr"], h=H_CONSTANT, fast=fast_pyscal, ) wog_relperm.wateroil.add_corey_water( nw=parameters["nw"], krwend=parameters["krwend"] ) wog_relperm.wateroil.add_corey_oil( now=parameters["now"], kroend=parameters["kroend"] ) wog_relperm.gasoil.add_corey_gas(ng=parameters["ng"], krgend=parameters["krgend"]) wog_relperm.gasoil.add_corey_oil(nog=parameters["nog"], kroend=parameters["kroend"]) return wog_relperm
def test_empty(): """Empty object should give empty strings (and logged errors)""" wog = WaterOilGas() assert wog.SWOF() == "" assert wog.SGOF() == "" assert wog.SOF3() == "" assert wog.SLGOF() == "" assert wog.SWFN() == "" assert wog.SGFN() == ""
def create_water_oil_gas(params=None): """Create a WaterOilGas object from a dictionary of parameters Parameterization (Corey/LET) is inferred from presence of certain parameters in the dictionary. Check create_water_oil() and create_gas_oil() for lists of supported parameters (case insensitive) """ if not params: params = dict() if not isinstance(params, dict): raise TypeError( "Parameter to create_water_oil_gas must be a dictionary") check_deprecated(params) # For case insensitiveness, all keys are converted to lower case: params = {key.lower(): value for (key, value) in params.items()} if sufficient_water_oil_params(params): wateroil = PyscalFactory.create_water_oil(params) else: logger.info( "No wateroil parameters. Assuming only gas-oil in wateroilgas") wateroil = None if sufficient_gas_oil_params(params): gasoil = PyscalFactory.create_gas_oil(params) else: logger.info("No gasoil parameters, assuming two-phase oilwatergas") gasoil = None wog_init_params = slicedict(params, WOG_INIT) wateroilgas = WaterOilGas(**wog_init_params) # The wateroilgas __init__ has already created WaterOil and GasOil objects # but we overwrite the references with newly created ones, this factory function # must then guarantee that they are compatible. wateroilgas.wateroil = wateroil # This might be None wateroilgas.gasoil = gasoil # This might be None if not wateroilgas.selfcheck(): raise ValueError(( "Incomplete WaterOilGas object, some parameters missing to factory" )) return wateroilgas
def test_slgof(swl, sorg, sgcr): wog = WaterOilGas(swl=swl, sorg=sorg, sgcr=sgcr, h=0.05) wog.wateroil.add_corey_water() wog.wateroil.add_corey_oil() wog.gasoil.add_corey_gas(krgmax=1) wog.gasoil.add_corey_oil() assert wog.selfcheck() slgof = wog.gasoil.slgof_df() assert "sl" in slgof assert "krg" in slgof assert "krog" in slgof assert len(slgof) check_table(slgof) # Requirements from E100 manual: assert np.isclose(slgof["sl"].values[0], wog.gasoil.swl + wog.gasoil.sorg) assert np.isclose(slgof["krg"].values[-1], 0) assert np.isclose(slgof["krog"].values[0], 0)
def test_wateroilgas_constructor(): """Test that constructor properties are available as aattributes""" wog = WaterOilGas(swirr=0.01, swl=0.02, sorg=0.03, sorw=0.04, tag="Foo") assert wog.swirr == 0.01 assert wog.swl == 0.02 assert wog.sorg == 0.03 assert wog.tag == "Foo" assert wog.sorw == 0.04 # Manipulate the tag in the underlying GasOil object: wog.gasoil.tag = "Bar" assert wog.tag == "Foo Bar" # Different tags are concatenated.
def test_slgof(swl, sorg, sgcr): """Test dumping SLGOF records""" wog = WaterOilGas(swl=swl, sorg=sorg, sgcr=sgcr, h=0.05) wog.wateroil.add_corey_water() wog.wateroil.add_corey_oil() wog.gasoil.add_corey_gas(krgmax=1) wog.gasoil.add_corey_oil() assert wog.selfcheck() slgof = wog.gasoil.slgof_df() assert "SL" in slgof assert "KRG" in slgof assert "KROG" in slgof assert not slgof.empty check_table(slgof) sat_table_str_ok(wog.SLGOF()) # Requirements from E100 manual: assert np.isclose(slgof["SL"].values[0], wog.gasoil.swl + wog.gasoil.sorg) assert np.isclose(slgof["KRG"].values[-1], 0) assert np.isclose(slgof["KROG"].values[0], 0)
def test_ieee_754(): """Test difficult values from experienced bugs related to IEE754 representation errors""" wateroilgas = WaterOilGas(swl=0.18) # For this particular swl value, we get: # wateroilgas.gasoil.table.sg.max() # Out[18]: 0.8200000000000001 # = (1 - 0.18) # Can we then interpolate from a table that goes up to 0.82? sgof = pd.DataFrame(columns=["Sg", "krg", "krog", "pcog"], data=[[0, 0, 1, 0], [0.82, 1, 0, 0]]) # Note, replacing 0.82 in the table above with 1-0.18 *is not the same* wateroilgas.gasoil.add_fromtable(sgof) assert wateroilgas.gasoil.table["krg"].max() == 1.0 assert wateroilgas.gasoil.table["krog"].min() == 0.0 assert wateroilgas.gasoil.table["pc"].min() == 0.0 assert wateroilgas.gasoil.table["pc"].max() == 0.0
def test_wateroilgas_simple(): """Test that default curves will give valid include strings""" wog = WaterOilGas() # Add default curves: wog.wateroil.add_corey_water() wog.wateroil.add_corey_oil() wog.gasoil.add_corey_gas() wog.gasoil.add_corey_oil() with pytest.raises(AssertionError): # Testing test code: sat_table_str_ok("") sat_table_str_ok(wog.SWOF()) sat_table_str_ok(wog.SGOF()) sat_table_str_ok(wog.SLGOF()) sat_table_str_ok(wog.SOF3()) sat_table_str_ok(wog.SGFN()) sat_table_str_ok(wog.SWFN())
def benchme(fast=False, doprint=False): """Test function for benchmarking the "fast"-feature Pipe the following code snip into "ipython" on the shell: > echo "import benchme %timeit benchme.benchme() %timeit benchme.benchme(fast=True) " | ipython or run this module directly """ wog = WaterOilGas(swl=0.1, h=0.1, fast=fast) wog.wateroil.add_corey_oil(now=3, kroend=0.9) wog.wateroil.add_corey_water(nw=2, krwend=0.2) wog.gasoil.add_corey_oil() wog.gasoil.add_corey_gas() if not doprint: len(wog.SWOF()) len(wog.SGOF()) else: print(wog.SWOF()) print(wog.SGOF())
def interpolate(self, parameter, parameter2=None, h=0.02): """Interpolate between low, base and high Endpoints are located for input curves, and interpolated individually. Interpolation for the nonlinear part is done on a normalized interval between the endpoints Interpolation is linear in relperm-direction, and will thus not be linear in log-relperm-direction This method returns an WaterOilGas object which can be realized into printed tables. No attempt is made to parametrize the interpolant in L,E,T parameter space, or Corey-space. Args: parameter (float): Between -1 and 1, inclusive. -1 reproduces low/ pessimistic curve, 0 gives base, 1 gives high/optimistic. parameter2 (float): If not None, used for the gas-oil interpolation, enables having interpolation uncorrelated for WaterOil and GasOil. Ignored for GasWater (no warning). h (float): Saturation step length in generated tables. Does not need to be the same as the tables interpolation is done from. """ if parameter2 is not None: gasparameter = parameter2 else: gasparameter = parameter # Either wateroil or gasoil can be None in the low, base, high # If they are None, it is a two-phase problem and we # should support this. do_gaswater = False do_wateroil = False do_gasoil = False if self.type == GasWater: do_gaswater = True elif self.type == WaterOilGas: do_wateroil = (self.base.wateroil is not None and self.low.wateroil is not None and self.high.wateroil is not None) do_gasoil = (self.base.gasoil is not None and self.low.gasoil is not None and self.high.gasoil is not None) if not do_gaswater: if not do_wateroil and not do_gasoil: raise ValueError( "Neither WaterOil or GasOil is complete in SCAL recommendation" ) if parameter2 is not None: if not do_gasoil: logger.warning("parameter2 is meaningless for water-oil only") if do_gaswater: logger.warning("parameter2 is meaningless for gas-water") # Initialize wateroil and gasoil curves to be filled with # interpolated curves: tags = set() if do_wateroil or do_gaswater: tags = tags.union( set([ self.base.wateroil.tag, self.low.wateroil.tag, self.high.wateroil.tag, ])) if do_gasoil: tags = tags.union( set([ self.base.gasoil.tag, self.low.gasoil.tag, self.high.gasoil.tag ])) tagstring = "\n".join(tags) if do_gaswater: interpolant = GasWater(h=h, tag=tagstring) if gasparameter != parameter: logger.warning( "Different interpolation parameters for Water and for " "gas in GasWater, this is maybe not what you want") else: interpolant = WaterOilGas(h=h, tag=tagstring) if do_wateroil or do_gaswater: tag = ( "SCAL recommendation interpolation to {}\n".format(parameter) + tagstring) if abs(parameter) > 1.0: logger.error("Interpolation parameter must be in [-1,1]") assert abs(parameter) <= 1.0 elif np.isclose(parameter, 0.0): interpolant.wateroil = copy.deepcopy(self.base.wateroil) interpolant.wateroil.tag = tag elif np.isclose(parameter, -1.0): interpolant.wateroil = copy.deepcopy(self.low.wateroil) interpolant.wateroil.tag = tag elif np.isclose(parameter, 1.0): interpolant.wateroil = copy.deepcopy(self.high.wateroil) interpolant.wateroil.tag = tag elif parameter < 0.0: interpolant.wateroil = interpolate_wo(self.base.wateroil, self.low.wateroil, -parameter, h=h, tag=tag) elif parameter > 0.0: interpolant.wateroil = interpolate_wo(self.base.wateroil, self.high.wateroil, parameter, h=h, tag=tag) else: interpolant.wateroil = None if do_gasoil or do_gaswater: tag = ("SCAL recommendation interpolation to {}\n".format( gasparameter) + tagstring) if abs(gasparameter) > 1.0: logger.error("Interpolation parameter must be in [-1,1]") assert abs(gasparameter) <= 1.0 elif np.isclose(gasparameter, 0.0): interpolant.gasoil = copy.deepcopy(self.base.gasoil) interpolant.gasoil.tag = tag elif np.isclose(gasparameter, -1.0): interpolant.gasoil = copy.deepcopy(self.low.gasoil) interpolant.gasoil.tag = tag elif np.isclose(gasparameter, 1.0): interpolant.gasoil = copy.deepcopy(self.high.gasoil) interpolant.gasoil.tag = tag elif gasparameter < 0.0: interpolant.gasoil = interpolate_go(self.base.gasoil, self.low.gasoil, -1 * gasparameter, h=h, tag=tag) elif gasparameter > 0.0: interpolant.gasoil = interpolate_go(self.base.gasoil, self.high.gasoil, gasparameter, h=h, tag=tag) else: interpolant.gasoil = None return interpolant
def test_parse_with_opm(tmpdir): """Test that the SWOF+SGOF output from pyscal can be injected into a valid Eclipse deck""" wog = WaterOilGas() wog.wateroil.add_corey_water(nw=2) wog.wateroil.add_corey_oil(now=2, kroend=0.9) wog.gasoil.add_corey_gas(ng=2) wog.gasoil.add_corey_oil(nog=2, kroend=1) ecldeck = ("""RUNSPEC DIMENS 1 1 1 / OIL WATER GAS START 1 'JAN' 2100 / TABDIMS 2* 10000 / EQLDIMS 1 / GRID DX 10 / DY 10 / DZ 50 / TOPS 1000 / PORO 0.3 / PERMX 100 / PERMY 100 / PERMZ 100 / PROPS """ + wog.SWOF() + wog.SGOF() + """ DENSITY 800 1000 1.2 / PVTW 1 1 0.0001 0.2 0.00001 / PVDO 100 1 1 150 0.9 1 / PVDG 100 1 1 150 0.9 1 / ROCK 100 0.0001 / SOLUTION EQUIL 1000 100 1040 0 1010 0 /""") tmpdir.chdir() Path("RELPERMTEST.DATA").write_text(ecldeck) deck = opm.io.Parser().parse("RELPERMTEST.DATA") assert "SWOF" in deck assert "SGOF" in deck
def __init__(self, low, base, high, tag=None, h=0.01): """Set up a SCAL recommendation curve set from WaterOilGas objects Arguments: low (WaterOilGas): low case base (WaterOilGas): base case high (WaterOilGas): high case tag (str): Describes the recommendation. This string will be used as tag strings for the interpolants. """ self.h = h self.tag = tag if isinstance(low, dict) and isinstance(base, dict) and isinstance( high, dict): logger.warning( ("Making SCALrecommendation from dicts is deprecated " "and will not be supported in future versions\n")) self.defaultshandling("swirr", 0.0, [low, base, high]) self.defaultshandling("swcr", 0.0, [low, base, high]) self.defaultshandling("sorg", 0.0, [low, base, high]) self.defaultshandling("sgcr", 0.0, [low, base, high]) # Special treatment for backwards compatibility: if "krowend" in low: logger.error("krowend is deprecated, use kroend") krowend = "krowend" else: krowend = "kroend" if "krogend" in low: logger.error("krogend is deprecated, use kroend") krogend = "krogend" else: krogend = "kroend" self.defaultshandling("kroend", 1.0, [low, base, high]) self.defaultshandling("krwmax", 1.0, [low, base, high]) self.defaultshandling("krgend", 1.0, [low, base, high]) self.defaultshandling("krgmax", 1.0, [low, base, high]) # Initialize saturation ranges for all curves self.low = WaterOilGas( swirr=low["swirr"], swl=low["swl"], sorw=low["sorw"], sorg=low["sorg"], sgcr=low["sgcr"], swcr=low["swcr"], h=h, tag=tag, ) self.base = WaterOilGas( swirr=base["swirr"], swl=base["swl"], sorw=base["sorw"], sorg=base["sorg"], sgcr=base["sgcr"], swcr=base["swcr"], h=h, tag=tag, ) self.high = WaterOilGas( swirr=high["swirr"], swl=high["swl"], sorw=high["sorw"], sorg=high["sorg"], sgcr=high["sgcr"], swcr=high["swcr"], h=h, tag=tag, ) # Add water and oil curves self.low.wateroil.add_LET_water( l=low["Lw"], e=low["Ew"], t=low["Tw"], krwend=low["krwend"], krwmax=low["krwmax"], ) self.base.wateroil.add_LET_water( l=base["Lw"], e=base["Ew"], t=base["Tw"], krwend=base["krwend"], krwmax=base["krwmax"], ) self.high.wateroil.add_LET_water( l=high["Lw"], e=high["Ew"], t=high["Tw"], krwend=high["krwend"], krwmax=high["krwmax"], ) self.low.wateroil.add_LET_oil(l=low["Lo"], e=low["Eo"], t=low["To"], kroend=low[krowend]) self.base.wateroil.add_LET_oil(l=base["Lo"], e=base["Eo"], t=base["To"], kroend=base[krowend]) self.high.wateroil.add_LET_oil(l=high["Lo"], e=high["Eo"], t=high["To"], kroend=high[krowend]) # Add gas and oil curves: self.low.gasoil.add_LET_gas( l=low["Lg"], e=low["Eg"], t=low["Tg"], krgend=low["krgend"], krgmax=low["krgmax"], ) self.base.gasoil.add_LET_gas( l=base["Lg"], e=base["Eg"], t=base["Tg"], krgend=base["krgend"], krgmax=base["krgmax"], ) self.high.gasoil.add_LET_gas( l=high["Lg"], e=high["Eg"], t=high["Tg"], krgend=high["krgend"], krgmax=high["krgmax"], ) self.low.gasoil.add_LET_oil(l=low["Log"], e=low["Eog"], t=low["Tog"], kroend=low[krogend]) self.base.gasoil.add_LET_oil(l=base["Log"], e=base["Eog"], t=base["Tog"], kroend=base[krogend]) self.high.gasoil.add_LET_oil(l=high["Log"], e=high["Eog"], t=high["Tog"], kroend=high[krogend]) self.type = WaterOilGas elif (isinstance(low, WaterOilGas) and isinstance(base, WaterOilGas) and isinstance(high, WaterOilGas)): self.low = low self.base = base self.high = high self.type = WaterOilGas elif (isinstance(low, GasWater) and isinstance(base, GasWater) and isinstance(high, GasWater)): self.low = low self.base = base self.high = high self.type = GasWater else: raise ValueError("Wrong arguments to SCALrecommendation")
def interpolate(self, parameter, parameter2=None, h=0.02): """Interpolate between low, base and high parameter = -1 reproduces low curve parameter = 0 reproduces base curve parameter = 1 reproduces high curve Endpoints are located for input curves, and interpolated individually. Interpolation for the nonlinear part is done on a normalized interval between the endpoints Interpolation is linear in relperm-direction, and will thus not be linear in log-relperm-direction This method returns an WaterOilGas object which can be realized into printed tables. No attempt is made to parametrize the interpolant in L,E,T parameter space, or Corey-space. If a second parameter is supplied ("parameter2") this is used for the gas-oil interpolation. This enables the gas-oil interpolant to be fully uncorrelated to the water-oil interpolant. CHECK how this affects endpoints and Eclipse consistency!! """ if parameter2 is not None: gasparameter = parameter2 else: gasparameter = parameter # Either wateroil or gasoil can be None in the low, base, high # If they are None, it is a two-phase problem and we # should support this. do_wateroil = (self.base.wateroil is not None and self.low.wateroil is not None and self.high.wateroil is not None) do_gasoil = (self.base.gasoil is not None and self.low.gasoil is not None and self.high.gasoil is not None) if not do_wateroil and not do_gasoil: raise ValueError( "Neither wateroil or gasoil is complete in SCAL recommendation" ) if parameter2 is not None and not do_gasoil: logger.warning("parameter2 is meaningless for water-oil only") # Initialize wateroil and gasoil curves to be filled with # interpolated curves: tags = set() if do_wateroil: tags = tags.union( set([ self.base.wateroil.tag, self.low.wateroil.tag, self.high.wateroil.tag, ])) if do_gasoil: tags = tags.union( set([ self.base.gasoil.tag, self.low.gasoil.tag, self.high.gasoil.tag ])) tagstring = "\n".join(tags) interpolant = WaterOilGas(h=h, tag=tagstring) if do_wateroil: tag = ( "SCAL recommendation interpolation to {}\n".format(parameter) + tagstring) if abs(parameter) > 1.0: logger.error("Interpolation parameter must be in [-1,1]") assert abs(parameter) <= 1.0 elif np.isclose(parameter, 0.0): interpolant.wateroil = self.base.wateroil interpolant.wateroil.tag = tag elif np.isclose(parameter, -1.0): interpolant.wateroil = self.low.wateroil interpolant.wateroil.tag = tag elif np.isclose(parameter, 1.0): interpolant.wateroil = self.high.wateroil interpolant.wateroil.tag = tag elif parameter < 0.0: interpolant.wateroil = utils.interpolate_wo(self.base.wateroil, self.low.wateroil, -parameter, h=h, tag=tag) elif parameter > 0.0: interpolant.wateroil = utils.interpolate_wo(self.base.wateroil, self.high.wateroil, parameter, h=h, tag=tag) else: interpolant.wateroil = None if do_gasoil: tag = ("SCAL recommendation interpolation to {}\n".format( gasparameter) + tagstring) if abs(gasparameter) > 1.0: logger.error("Interpolation parameter must be in [-1,1]") assert abs(gasparameter) <= 1.0 elif np.isclose(gasparameter, 0.0): interpolant.gasoil = self.base.gasoil interpolant.gasoil.tag = tag elif np.isclose(gasparameter, -1.0): interpolant.gasoil = self.low.gasoil interpolant.gasoil.tag = tag elif np.isclose(gasparameter, 1.0): interpolant.gasoil = self.high.gasoil interpolant.gasoil.tag = tag elif gasparameter < 0.0: interpolant.gasoil = utils.interpolate_go(self.base.gasoil, self.low.gasoil, -1 * gasparameter, h=h, tag=tag) elif gasparameter > 0.0: interpolant.gasoil = utils.interpolate_go(self.base.gasoil, self.high.gasoil, gasparameter, h=h, tag=tag) else: interpolant.gasoil = None return interpolant
def interpolate(self, parameter, parameter2=None, h=0.02): """Interpolate between low, base and high parameter = -1 reproduces low curve parameter = 0 reproduces base curve parameter = 1 reproduces high curve Interpolation is performed pointwise in the "relperm" direction for each saturation point. During interpolation, endpoints are hard to handle, and only swirr is attempted preserved. Interpolation is linear in relperm-direction, and will thus not be linear in log-relperm-direction This method returns an WaterOilGasTable object which can be realized into printed tables. No attempt is made to parametrize the interpolant in L,E,T parameter space. If a second parameter is supplied ("parameter2") this is used for the gas-oil interpolation. This enables the gas-oil interpolant to be fully uncorrelated to the water-oil interpolant. CHECK how this affects endpoints and Eclipse consistency!! """ if parameter2 is not None: gasparameter = parameter2 else: gasparameter = parameter # Initialize wateroil and gasoil curves to be filled with # interpolated curves: interpolant = WaterOilGas() if abs(parameter) > 1.0: logging.error("Interpolation parameter must be in [-1,1]") interpolant.wateroil = None raise AssertionError elif np.isclose(parameter, 0.0): interpolant.wateroil = self.base.wateroil elif np.isclose(parameter, -1.0): interpolant.wateroil = self.low.wateroil elif np.isclose(parameter, 1.0): interpolant.wateroil = self.high.wateroil elif parameter < 0.0: curve1 = copy.deepcopy(self.base.wateroil) curve2 = copy.deepcopy(self.low.wateroil) param_transf = -parameter # 0 gives base, 1 gives low. swl = (curve1.table["sw"][0] * (1 - param_transf) + curve2.table["sw"][0] * param_transf) interpolant.wateroil = WaterOil( swirr=swl, swl=swl, sorw=0.0, h=h, tag=self.tag + " interpolant at %g" % parameter, ) interpolator( interpolant.wateroil, curve1, curve2, param_transf, "sw", "krw", "krow", "pc", ) elif parameter > 0.0: curve1 = copy.deepcopy(self.base.wateroil) curve2 = copy.deepcopy(self.high.wateroil) param_transf = parameter # 0 gives base, 1 gives high swl = (curve1.table["sw"][0] * (1 - param_transf) + curve2.table["sw"][0] * param_transf) interpolant.wateroil = WaterOil( swirr=swl, swl=swl, sorw=0.0, h=h, tag=self.tag + " interpolant at %g" % parameter, ) interpolator( interpolant.wateroil, curve1, curve2, param_transf, "sw", "krw", "krow", "pc", ) # Gas-oil interpolation # We need swl from the interpolated WaterOil object. swl = interpolant.wateroil.swl if abs(gasparameter) > 1.0: logging.error("Interpolation parameter must be in [-1,1]") interpolant.gasoil = None raise AssertionError elif np.isclose(gasparameter, 0.0): interpolant.gasoil = self.base.gasoil elif np.isclose(gasparameter, -1.0): interpolant.gasoil = self.low.gasoil elif np.isclose(gasparameter, 1.0): interpolant.gasoil = self.high.gasoil elif gasparameter < 0.0: curve1 = copy.deepcopy(self.base.gasoil) curve2 = copy.deepcopy(self.low.gasoil) gas_param_transf = -1 * gasparameter # 0 gives base, 1 gives low. # We have to use the extreme, not interpolated sgcr. sgcr = min(curve1.sgcr, curve2.sgcr) interpolant.gasoil = GasOil( sgcr=sgcr, swl=swl, sorg=0.0, h=h, tag=self.tag + " interpolant at %g" % gasparameter, ) interpolator( interpolant.gasoil, curve1, curve2, gas_param_transf, "sg", "krg", "krog", "pc", ) interpolant.gasoil.resetsorg() elif gasparameter > 0.0: curve1 = copy.deepcopy(self.base.gasoil) curve2 = copy.deepcopy(self.high.gasoil) gas_param_transf = gasparameter # 0 gives base, 1 gives high # We have to use the extreme, not interpolated sgcr. sgcr = min(curve1.sgcr, curve2.sgcr) interpolant.gasoil = GasOil( sgcr=sgcr, swl=swl, sorg=0.0, h=h, tag=self.tag + " interpolant at %g" % gasparameter, ) interpolator( interpolant.gasoil, curve1, curve2, gas_param_transf, "sg", "krg", "krog", "pc", ) interpolant.gasoil.resetsorg() return interpolant
def __init__(self, low, base, high, tag, h=0.01): """Set up a SCAL recommendation curve set from WaterOilGas objects Arguments: low (WaterOilGas): low case base (WaterOilGas): base case high (WaterOilGas): high case """ self.h = h self.tag = tag if isinstance(low, dict) and isinstance(base, dict) and isinstance( high, dict): logging.warning( ("Making SCALrecommendation from dicts is deprecated " "and will not be supported in future versions\n" "Use WaterOilGas objects instead")) self.defaultshandling("swirr", 0.0, [low, base, high]) self.defaultshandling("swcr", 0.0, [low, base, high]) self.defaultshandling("sorg", 0.0, [low, base, high]) self.defaultshandling("sgcr", 0.0, [low, base, high]) self.defaultshandling("kroend", 1.0, [low, base, high]) self.defaultshandling("krwmax", 1.0, [low, base, high]) self.defaultshandling("krgend", 1.0, [low, base, high]) self.defaultshandling("krgmax", 1.0, [low, base, high]) # Initialize saturation ranges for all curves self.low = WaterOilGas( swirr=low["swirr"], swl=low["swl"], sorw=low["sorw"], sorg=low["sorg"], sgcr=low["sgcr"], swcr=low["swcr"], h=h, tag=tag, ) self.base = WaterOilGas( swirr=base["swirr"], swl=base["swl"], sorw=base["sorw"], sorg=base["sorg"], sgcr=base["sgcr"], swcr=base["swcr"], h=h, tag=tag, ) self.high = WaterOilGas( swirr=high["swirr"], swl=high["swl"], sorw=high["sorw"], sorg=high["sorg"], sgcr=high["sgcr"], swcr=high["swcr"], h=h, tag=tag, ) # Add water and oil curves self.low.wateroil.add_LET_water( l=low["Lw"], e=low["Ew"], t=low["Tw"], krwend=low["krwend"], krwmax=low["krwmax"], ) self.base.wateroil.add_LET_water( l=base["Lw"], e=base["Ew"], t=base["Tw"], krwend=base["krwend"], krwmax=base["krwmax"], ) self.high.wateroil.add_LET_water( l=high["Lw"], e=high["Ew"], t=high["Tw"], krwend=high["krwend"], krwmax=high["krwmax"], ) self.low.wateroil.add_LET_oil(l=low["Lo"], e=low["Eo"], t=low["To"], kroend=low["kroend"]) self.base.wateroil.add_LET_oil(l=base["Lo"], e=base["Eo"], t=base["To"], kroend=base["kroend"]) self.high.wateroil.add_LET_oil(l=high["Lo"], e=high["Eo"], t=high["To"], kroend=high["kroend"]) # Add gas and oil curves: self.low.gasoil.add_LET_gas( l=low["Lg"], e=low["Eg"], t=low["Tg"], krgend=low["krgend"], krgmax=low["krgmax"], ) self.base.gasoil.add_LET_gas( l=base["Lg"], e=base["Eg"], t=base["Tg"], krgend=base["krgend"], krgmax=base["krgmax"], ) self.high.gasoil.add_LET_gas( l=high["Lg"], e=high["Eg"], t=high["Tg"], krgend=high["krgend"], krgmax=high["krgmax"], ) self.low.gasoil.add_LET_oil(l=low["Log"], e=low["Eog"], t=low["Tog"], kroend=low["kroend"]) self.base.gasoil.add_LET_oil(l=base["Log"], e=base["Eog"], t=base["Tog"], kroend=base["kroend"]) self.high.gasoil.add_LET_oil(l=high["Log"], e=high["Eog"], t=high["Tog"], kroend=high["kroend"]) elif (isinstance(low, WaterOilGas) and isinstance(base, WaterOilGas) and isinstance(high, WaterOilGas)): self.low = low self.base = base self.high = high else: raise ValueError("Wrong arguments to SCALrecommendation")