def test_norm_J_pc_random(swirr, swl, a, b, poro, perm, sigma_costau): """Test many possibilities of Pc-parameters. Outside of the tested range, there are many combination of parameters that can give infinite capillary pressure""" swl = swirr + swl # No point in getting too many AssertionErrors wo = WaterOil(swirr=swirr, swl=swl, h=0.01) try: wo.add_normalized_J(a=a, b=b, perm=perm, poro=poro, sigma_costau=sigma_costau) except (AssertionError, ValueError): # when poro is < 0 f.ex. return check_table(wo.table)
def test_normalized_j(): """Test the normalized J-function correlation for capillary pressure""" wateroil = WaterOil(swirr=0.1, h=0.1) with pytest.raises(ValueError): wateroil.add_normalized_J(a=0.5, b=-0.2, poro=0.2, perm=10, sigma_costau=30) wateroil = WaterOil(swirr=0, swl=0.1, h=0.1) wateroil.add_normalized_J(a=0.5, b=-0.2, poro=0.2, perm=10, sigma_costau=30) check_table(wateroil.table) # Sample numerical tests taken from a prior implementation # NB: Prior implementation created Pc in atm, we create in bar bar_to_atm = 1.0 / 1.01325 wateroil.add_normalized_J(a=0.22, b=-0.5, perm=100, poro=0.2, sigma_costau=30) float_df_checker(wateroil.table, "sw", 0.1, "pc", 2.039969 * bar_to_atm) float_df_checker(wateroil.table, "sw", 0.6, "pc", 0.056666 * bar_to_atm) float_df_checker(wateroil.table, "sw", 1.0, "pc", 0.02040 * bar_to_atm)
def test_normalized_J(): wo = WaterOil(swirr=0.1, h=0.1) with pytest.raises(ValueError): wo.add_normalized_J(a=0.5, b=-0.2, poro=0.2, perm=10, sigma_costau=30) wo = WaterOil(swirr=0, swl=0.1, h=0.1) wo.add_normalized_J(a=0.5, b=-0.2, poro=0.2, perm=10, sigma_costau=30) check_table(wo.table) # Sample numerical tests taken from a prior implementation # NB: Prior implementation created Pc in atm, we create in bar bar_to_atm = 1.0 / 1.01325 wo.add_normalized_J(a=0.22, b=-0.5, perm=100, poro=0.2, sigma_costau=30) float_df_checker(wo.table, "sw", 0.1, "pc", 2.039969 * bar_to_atm) float_df_checker(wo.table, "sw", 0.6, "pc", 0.056666 * bar_to_atm) float_df_checker(wo.table, "sw", 1.0, "pc", 0.02040 * bar_to_atm)
def create_water_oil(params=None): """Create a WaterOil object from a dictionary of parameters. Parameterization (Corey/LET) is inferred from presence of certain parameters in the dictionary. Don't rely on behaviour of you supply both Corey and LET at the same time. Parameter names in the dictionary are case insensitive. You can use Swirr, swirr, sWirR, swiRR etc. NB: the add_LET_* methods have the names 'l', 'e' and 't' in their signatures, which is not precise enough in this context, so we require e.g. 'Lw' and 'Low' (which both will be translated to 'l') Recognized parameters: swirr, swl, swcr, sorw, h, tag, nw, now, krwmax, krwend, lw, ew, tw, low, eow, tow, lo, eo, to, kromax, krowend, a, a_petro, b, b_petro, poro_ref, perm_ref, drho, a, b, poro, perm, sigma_costau Args: params (dict): Dictionary with parameters describing the WaterOil object. """ if not params: params = dict() if not isinstance(params, dict): raise TypeError( "Parameter to create_water_oil 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()} # Allowing sending in NaN values, delete those keys. params = filter_nan_from_dict(params) usedparams = set() # No requirements to the base objects, defaults are ok. wateroil = WaterOil(**slicedict(params, WO_INIT)) usedparams = usedparams.union(set(slicedict(params, WO_INIT).keys())) logger.info("Initialized WaterOil object from parameters %s", str(list(usedparams))) # Water curve params_corey_water = slicedict(params, WO_COREY_WATER + WO_WATER_ENDPOINTS) params_let_water = slicedict(params, WO_LET_WATER + WO_WATER_ENDPOINTS) if set(WO_COREY_WATER).issubset(set(params_corey_water)): wateroil.add_corey_water(**params_corey_water) usedparams = usedparams.union(set(params_corey_water.keys())) logger.info( "Added Corey water to WaterOil object from parameters %s", str(params_corey_water.keys()), ) elif set(WO_LET_WATER).issubset(set(params_let_water)): params_let_water["l"] = params_let_water.pop("lw") params_let_water["e"] = params_let_water.pop("ew") params_let_water["t"] = params_let_water.pop("tw") wateroil.add_LET_water(**params_let_water) usedparams = usedparams.union(set(params_let_water.keys())) logger.info( "Added LET water to WaterOil object from parameters %s", str(params_let_water.keys()), ) else: logger.warning( "Missing or ambiguous parameters for water curve in WaterOil object" ) # Oil curve: params_corey_oil = slicedict(params, WO_COREY_OIL + WO_OIL_ENDPOINTS) params_let_oil = slicedict( params, WO_LET_OIL + WO_LET_OIL_ALT + WO_OIL_ENDPOINTS) if set(WO_COREY_OIL).issubset(set(params_corey_oil)): if "krowend" in params_corey_oil: params_corey_oil["kroend"] = params_corey_oil.pop("krowend") wateroil.add_corey_oil(**params_corey_oil) logger.info( "Added Corey water to WaterOil object from parameters %s", str(params_corey_oil.keys()), ) elif set(WO_LET_OIL).issubset(set(params_let_oil)): params_let_oil["l"] = params_let_oil.pop("low") params_let_oil["e"] = params_let_oil.pop("eow") params_let_oil["t"] = params_let_oil.pop("tow") if "krowend" in params_let_oil: params_let_oil["kroend"] = params_let_oil.pop("krowend") wateroil.add_LET_oil(**params_let_oil) logger.info( "Added LET water to WaterOil object from parameters %s", str(params_let_oil.keys()), ) elif set(WO_LET_OIL_ALT).issubset(set(params_let_oil)): params_let_oil["l"] = params_let_oil.pop("lo") params_let_oil["e"] = params_let_oil.pop("eo") params_let_oil["t"] = params_let_oil.pop("to") if "krowend" in params_let_oil: params_let_oil["kroend"] = params_let_oil.pop("krowend") wateroil.add_LET_oil(**params_let_oil) logger.info( "Added LET water to WaterOil object from parameters %s", str(params_let_oil.keys()), ) else: logger.warning( "Missing or ambiguous parameters for oil curve in WaterOil object" ) # Capillary pressure: params_simple_j = slicedict(params, WO_SIMPLE_J + ["g"]) params_norm_j = slicedict(params, WO_NORM_J) params_simple_j_petro = slicedict(params, WO_SIMPLE_J_PETRO + ["g"]) if set(WO_SIMPLE_J).issubset(set(params_simple_j)): wateroil.add_simple_J(**params_simple_j) elif set(WO_SIMPLE_J_PETRO).issubset(set(params_simple_j_petro)): params_simple_j_petro["a"] = params_simple_j_petro.pop("a_petro") params_simple_j_petro["b"] = params_simple_j_petro.pop("b_petro") wateroil.add_simple_J_petro(**params_simple_j_petro) elif set(WO_NORM_J).issubset(set(params_norm_j)): wateroil.add_normalized_J(**params_norm_j) else: logger.warning( ("Missing or ambiguous parameters for capillary pressure in " "WaterOil object. Using zero.")) if not wateroil.selfcheck(): raise ValueError(( "Incomplete WaterOil object, some parameters missing to factory" )) return wateroil
def test_normalized_j(caplog): """Test the normalized J-function correlation for capillary pressure""" wateroil = WaterOil(swirr=0.1, h=0.1) with pytest.raises(ValueError): wateroil.add_normalized_J(a=0.5, b=-0.2, poro=0.2, perm=10, sigma_costau=30) wateroil = WaterOil(swirr=0, swl=0.1, h=0.1) wateroil.add_normalized_J(a=0.5, b=-0.2, poro=0.2, perm=10, sigma_costau=30) check_table(wateroil.table) # Sample numerical tests taken from a prior implementation # NB: Prior implementation created Pc in atm, we create in bar bar_to_atm = 1.0 / 1.01325 wateroil.add_normalized_J(a=0.22, b=-0.5, perm=100, poro=0.2, sigma_costau=30) float_df_checker(wateroil.table, "SW", 0.1, "PC", 2.039969 * bar_to_atm) float_df_checker(wateroil.table, "SW", 0.6, "PC", 0.056666 * bar_to_atm) float_df_checker(wateroil.table, "SW", 1.0, "PC", 0.02040 * bar_to_atm) wateroil = WaterOil(swirr=0.1, swl=0.11, h=0.1) wateroil.add_normalized_J(a=0.5, b=-0.001, poro=0.2, perm=10, sigma_costau=30) assert "b exponent is very small" in caplog.text wateroil = WaterOil(swirr=0.1, swl=0.11, h=0.1) wateroil.add_normalized_J(a=0.001, b=-2, poro=0.2, perm=10, sigma_costau=30) assert "a parameter is very small" in caplog.text wateroil = WaterOil(swirr=0.1, swl=0.11, h=0.1) wateroil.add_normalized_J(a=9, b=-2, poro=0.2, perm=10, sigma_costau=30) assert "a parameter is very high" in caplog.text
def create_water_oil(params=None): """Create a WaterOil object from a dictionary of parameters. Parameterization (Corey/LET) is inferred from presence of certain parameters in the dictionary. Don't rely on behaviour of you supply both Corey and LET at the same time. Parameter names in the dictionary are case insensitive. You can use Swirr, swirr, sWirR, swiRR etc. NB: the add_LET_* methods have the names 'l', 'e' and 't' in their signatures, which is not precise enough in this context, so we require e.g. 'Lw' and 'Low' (which both will be translated to 'l') """ if not params: params = dict() if not isinstance(params, dict): raise TypeError( "Parameter to create_water_oil must be a dictionary") # For case insensitiveness, all keys are converted to lower case: params = {key.lower(): value for (key, value) in params.items()} usedparams = set() # No requirements to the base objects, defaults are ok. wateroil = WaterOil(**slicedict(params, WO_INIT)) usedparams = usedparams.union(set(slicedict(params, WO_INIT).keys())) logging.info("Initialized WaterOil object from parameters %s", str(list(usedparams))) # Water curve params_corey_water = slicedict(params, WO_COREY_WATER + WO_WATER_ENDPOINTS) params_let_water = slicedict(params, WO_LET_WATER + WO_WATER_ENDPOINTS) if set(WO_COREY_WATER).issubset(set(params_corey_water)): wateroil.add_corey_water(**params_corey_water) usedparams = usedparams.union(set(params_corey_water.keys())) logging.info( "Added Corey water to WaterOil object from parameters %s", str(params_corey_water.keys()), ) elif set(WO_LET_WATER).issubset(set(params_let_water)): params_let_water["l"] = params_let_water.pop("lw") params_let_water["e"] = params_let_water.pop("ew") params_let_water["t"] = params_let_water.pop("tw") wateroil.add_LET_water(**params_let_water) usedparams = usedparams.union(set(params_let_water.keys())) logging.info( "Added LET water to WaterOil object from parameters %s", str(params_let_water.keys()), ) else: logging.warning( "Missing or ambiguous parameters for water curve in WaterOil object" ) # Oil curve: params_corey_oil = slicedict(params, WO_COREY_OIL + WO_OIL_ENDPOINTS) params_let_oil = slicedict( params, WO_LET_OIL + WO_LET_OIL_ALT + WO_OIL_ENDPOINTS) if set(WO_COREY_OIL).issubset(set(params_corey_oil)): wateroil.add_corey_oil(**params_corey_oil) logging.info( "Added Corey water to WaterOil object from parameters %s", str(params_corey_oil.keys()), ) elif set(WO_LET_OIL).issubset(set(params_let_oil)): params_let_oil["l"] = params_let_oil.pop("low") params_let_oil["e"] = params_let_oil.pop("eow") params_let_oil["t"] = params_let_oil.pop("tow") wateroil.add_LET_oil(**params_let_oil) logging.info( "Added LET water to WaterOil object from parameters %s", str(params_let_oil.keys()), ) elif set(WO_LET_OIL_ALT).issubset(set(params_let_oil)): params_let_oil["l"] = params_let_oil.pop("lo") params_let_oil["e"] = params_let_oil.pop("eo") params_let_oil["t"] = params_let_oil.pop("to") wateroil.add_LET_oil(**params_let_oil) logging.info( "Added LET water to WaterOil object from parameters %s", str(params_let_oil.keys()), ) else: logging.warning( "Missing or ambiguous parameters for oil curve in WaterOil object" ) # Capillary pressure: params_simple_j = slicedict(params, WO_SIMPLE_J + ["g"]) params_norm_j = slicedict(params, WO_NORM_J) if set(WO_SIMPLE_J).issubset(set(params_simple_j)): wateroil.add_simple_J(**params_simple_j) elif set(WO_NORM_J).issubset(set(params_norm_j)): wateroil.add_normalized_J(**params_norm_j) else: logging.warning( "Missing or ambiguous parameters for capillary pressure in WaterOil object. Using zero." ) if not wateroil.selfcheck(): raise ValueError(("Incomplete WaterOil object, some parameters " "missing to factory")) return wateroil