def test_interpolate_go( swl, sgcr, dsgcr, dswlhigh, sorg, dsorg, ng_l, ng_h, nog_l, nog_h, krgend_l, krgend_h, kroend_l, kroend_h, ): """Test many possible combinations of interpolation between two Corey gasoil curves, looking for numerical corner cases""" go_low = GasOil(swl=swl, sgcr=sgcr, sorg=sorg) go_high = GasOil(swl=swl + dswlhigh, sgcr=sgcr + dsgcr, sorg=max(sorg - dsorg, 0)) go_low.add_corey_gas(ng=ng_l, krgend=krgend_l) go_high.add_corey_gas(ng=ng_h, krgend=krgend_h) go_low.add_corey_oil(nog=nog_l, kroend=kroend_l) go_high.add_corey_oil(nog=nog_h, kroend=kroend_h) ips = [] ip_dist = 0.05 for t in np.arange(0, 1 + ip_dist, ip_dist): go_ip = utils.interpolate_go(go_low, go_high, t) check_table(go_ip.table) ips.append(go_ip) assert 0 < go_ip.crosspoint() < 1 # Distances between low and interpolants: dists = [(go_low.table - interp.table)[["krg", "krog"]].sum().sum() for interp in ips] print("Interpolation, mean: {}, min: {}, max: {}, std: {} ip-par-dist: {}". format(np.mean(dists), min(dists), max(dists), np.std(np.diff(dists[1:])), ip_dist)) assert np.isclose(dists[0], 0) # Reproducing go_low # All curves that are close in parameter t, should be close in sum().sum(). # That means that diff of the distances should be similar, # that is the std.dev of the distances is low: ip_dist_std = np.std(np.diff( dists[1:])) # This number depends on 'h' and 't' range, and # by how different the low and high is. # (avoiding the first which reproduces go_low if ip_dist_std > 1.0: # number found from trial and error. print("ip_dist_std: {}".format(ip_dist_std)) print(dists) from matplotlib import pyplot as plt _, mpl_ax = plt.subplots() go_low.plotkrgkrog(mpl_ax=mpl_ax, color="red") go_high.plotkrgkrog(mpl_ax=mpl_ax, color="blue") for interp in ips: interp.plotkrgkrog(mpl_ax=mpl_ax, color="green") plt.show() assert False
def test_interpolate_go(): """Interactive tests for gasoil""" swl_l = random.uniform(0, 0.1) sgcr_l = random.uniform(0, 0.1) swl_h = random.uniform(0, 0.1) sgcr_h = random.uniform(0, 0.1) sorg_l = random.uniform(0, 0.2) sorg_h = random.uniform(0, 0.2) if random.uniform(0, 1) > 0.5: krgendanchor_l = "sorg" else: krgendanchor_l = "" if random.uniform(0, 1) > 0.5: krgendanchor_h = "sorg" else: krgendanchor_h = "" go_low = GasOil(swl=swl_l, sgcr=sgcr_l, sorg=sorg_l, krgendanchor=krgendanchor_l, h=0.001) go_high = GasOil(swl=swl_h, sgcr=sgcr_h, sorg=sorg_h, krgendanchor=krgendanchor_h, h=0.001) go_low.add_corey_gas(ng=random.uniform(1, 3), krgend=random.uniform(0.5, 1)) go_high.add_corey_gas(ng=random.uniform(1, 3), krgend=random.uniform(0.5, 1)) go_low.add_corey_oil(nog=random.uniform(1, 3), kroend=random.uniform(0.5, 1)) go_high.add_corey_oil(nog=random.uniform(1, 3), kroend=random.uniform(0.5, 1)) print(" ** Low curve (red):\n" + go_low.sgcomment + go_low.krgcomment + go_low.krogcomment) print(" ** High curve (blue):\n" + go_high.sgcomment + go_high.krgcomment + go_high.krogcomment) from matplotlib import pyplot as plt _, mpl_ax = plt.subplots() go_low.plotkrgkrog(mpl_ax, color="red") go_high.plotkrgkrog(mpl_ax, color="blue") for tparam in np.arange(0, 1, 0.1): go_ip = utils.interpolate_go(go_low, go_high, tparam) go_ip.plotkrgkrog(mpl_ax, color="green") mpl_ax.set_title("GasOil, random Corey, linear y-scale") plt.show() _, mpl_ax = plt.subplots() go_low.plotkrgkrog(mpl_ax, color="red") go_high.plotkrgkrog(mpl_ax, color="blue") # Plot again with log yscale: for tparam in np.arange(0, 1, 0.1): go_ip = utils.interpolate_go(go_low, go_high, tparam) go_ip.plotkrgkrog(mpl_ax, color="green", logyscale=True) mpl_ax.set_title("GasOil, random Corey, log y-scale") plt.show() # Capillary pressure - This is barely supported for gasoil # so the plotpc() function is missing. Include calculations # here so we ensure we don't crash on the all zeros. # _, mpl_ax = plt.subplots() # go_low.plotpc(mpl_ax, color="red", logyscale=True) # go_high.plotpc(mpl_ax, color="blue", logyscale=True) for tparam in np.arange(0, 1, 0.1): go_ip = utils.interpolate_go(go_low, go_high, tparam, h=0.001)
def test_tag_preservation(): """Test that we can preserve tags/comments through interpolation""" wo_low = WaterOil(swl=0.1) wo_high = WaterOil(swl=0.2) wo_low.add_corey_water(nw=2) wo_high.add_corey_water(nw=3) wo_low.add_corey_oil(now=2) wo_high.add_corey_oil(now=3) interpolant1 = utils.interpolate_wo(wo_low, wo_high, parameter=0.1, h=0.2) assert "Interpolated to 0.1" in interpolant1.tag sat_table_str_ok(interpolant1.SWOF()) wo_high.tag = "FOOBAR" interpolant2 = utils.interpolate_wo(wo_low, wo_high, parameter=0.1, h=0.2) assert "Interpolated to 0.1" in interpolant2.tag assert "between" in interpolant2.tag assert wo_high.tag in interpolant2.tag sat_table_str_ok(interpolant2.SWOF()) # wo_low.tag was empty deliberately here. # When wo_log and wo_high has the same tag: wo_low.tag = "FOOBAR" interpolant3 = utils.interpolate_wo(wo_low, wo_high, parameter=0.1, h=0.2) assert "Interpolated to 0.1" in interpolant3.tag assert "between" not in interpolant3.tag assert wo_high.tag in interpolant3.tag sat_table_str_ok(interpolant3.SWOF()) # Explicit tag: interpolant4 = utils.interpolate_wo(wo_low, wo_high, parameter=0.1, h=0.2, tag="Explicit tag") assert interpolant4.tag == "Explicit tag" # Tag with newline interpolant6 = utils.interpolate_wo(wo_low, wo_high, parameter=0.1, h=0.2, tag="Explicit tag\non two lines") assert "Explicit tag" in interpolant6.tag print(interpolant6.SWOF()) sat_table_str_ok(interpolant6.SWOF()) # Empty tag: interpolant5 = utils.interpolate_wo(wo_low, wo_high, parameter=0.1, h=0.2, tag="") assert interpolant5.tag == "" # Also sample check for GasOil (calls the same code) go_low = GasOil() go_high = GasOil() go_low.add_corey_gas(ng=2) go_high.add_corey_gas(ng=3) go_low.add_corey_oil(nog=2) go_high.add_corey_oil(nog=3) interpolant1 = utils.interpolate_go(go_low, go_high, parameter=0.1, h=0.2) assert "Interpolated to 0.1" in interpolant1.tag sat_table_str_ok(interpolant1.SGOF())
def test_ip_krogmax(): """Test behaviour of kroend/kromax under interpolation""" go_low = GasOil(swl=0, sgcr=0.1, sorg=0.2) go_low.add_corey_gas(ng=2, krgend=0.5, krgmax=0.7) go_low.add_corey_oil(nog=2, kroend=0.6, kromax=0.9) go_high = GasOil(swl=0.02, sgcr=0.05, sorg=0.1) go_high.add_corey_gas(ng=2, krgend=0.5, krgmax=0.72) go_high.add_corey_oil(nog=2, kroend=0.6, kromax=0.8) # Interpolate to midpoint between the curves above go_ip = utils.interpolate_go(go_low, go_high, 0.5) # kromax at sg zero, should be kromax: assert float_df_checker(go_ip.table, "sg", 0.0, "krog", 0.85) # kroend is 0.6 in low and high, but sgcr has changed: assert float_df_checker(go_ip.table, "sg", 0.075, "krog", 0.6) assert np.isclose(go_ip.swl, 0.01) assert np.isclose(go_ip.sorg, 0.15) # krgmax at 1 - swl: assert float_df_checker(go_ip.table, "sg", 1 - go_ip.swl, "krg", 0.71) # krgend at 1 - swl - sorg assert float_df_checker(go_ip.table, "sg", 1 - go_ip.swl - go_ip.sorg, "krg", 0.5) # If krgendanchor is None, then krgmax should be irrelevant go_low = GasOil(swl=0, sgcr=0.1, sorg=0.2, krgendanchor="") go_low.add_corey_gas(ng=5, krgend=0.5, krgmax=0.7) # krgmax will trigger warning message, intended, as the 0.7 # value here will mean nothing. go_low.add_corey_oil(nog=2, kroend=0.6, kromax=0.9) go_high = GasOil(swl=0.02, sgcr=0.05, sorg=0.1, krgendanchor="") go_high.add_corey_gas(ng=4, krgend=0.5, krgmax=0.72) # krgmax will trigger warning message, intended. go_high.add_corey_oil(nog=2, kroend=0.6, kromax=0.8) # Interpolate to midpoint between the curves above go_ip = utils.interpolate_go(go_low, go_high, 0.5, h=0.1) assert float_df_checker(go_ip.table, "sg", 0.0, "krog", 0.85) # kroend is 0.6 in low and high, but swcr has changed: assert float_df_checker(go_ip.table, "sg", 0.075, "krog", 0.6) # Activate these line to see a bug, interpolation_go # does not honor krgendanchorA: # from matplotlib import pyplot as plt # _, mpl_ax = plt.subplots() # go_low.plotkrgkrog(mpl_ax=mpl_ax, color="red") # go_high.plotkrgkrog(mpl_ax=mpl_ax, color="blue") # go_ip.plotkrgkrog(mpl_ax=mpl_ax, color="green") # plt.show() # krgmax is irrelevant, krgend is used here: assert float_df_checker(go_ip.table, "sg", 1 - 0.01, "krg", 0.5) # Do we get into trouble if krgendanchor is different in low and high? go_low = GasOil(swl=0, sgcr=0.1, sorg=0.2, krgendanchor="sorg") go_low.add_corey_gas(ng=2, krgend=0.5, krgmax=0.7) go_low.add_corey_oil(nog=2, kroend=0.6, kromax=0.9) go_high = GasOil(swl=0.02, sgcr=0.05, sorg=0.1, krgendanchor="") go_high.add_corey_gas(ng=2, krgend=0.5) go_high.add_corey_oil(nog=2, kroend=0.6, kromax=0.8) # Interpolate to midpoint between the curves above go_ip = utils.interpolate_go(go_low, go_high, 0.5) assert float_df_checker(go_ip.table, "sg", 0.0, "krog", 0.85) # kroend is 0.6 in low and high, but swcr has changed: assert float_df_checker(go_ip.table, "sg", 0.075, "krog", 0.6) # max(krg) is here avg of krgmax and krgend from the differnt tables: assert float_df_checker(go_ip.table, "sg", 1 - 0.01, "krg", 0.6) # krgend at 1 - swl - sorg, non-trivial expression, so a numerical # value is used here in the test: assert float_df_checker(go_ip.table, "sg", 1 - 0.01 - 0.15, "krg", 0.4491271) # krog-zero at 1 - swl - sorg: assert float_df_checker(go_ip.table, "sg", 1 - 0.01 - 0.15, "krog", 0)
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