def test_normalize_nonlinpart_go(): """Manual tests for normalize_nonlinpart_go""" gasoil = GasOil(swl=0.1, sgcr=0.12, sorg=0.05, h=0.05) gasoil.add_corey_gas(ng=2.1, krgend=0.9) gasoil.add_corey_oil(nog=3, kroend=0.8) krgn, kron = normalize_nonlinpart_go(gasoil) assert np.isclose(krgn(0), 0) assert np.isclose(krgn(1), 0.9) # kron is normalized on son assert np.isclose(kron(0), 0) assert np.isclose(kron(1), 0.8) # Test with tricky endpoints h = 0.01 gasoil = GasOil(swl=h, sgcr=h, sorg=h, h=h) gasoil.add_corey_gas(ng=2.1, krgend=0.9) gasoil.add_corey_oil(nog=3, kroend=0.8) krgn, kron = normalize_nonlinpart_go(gasoil) assert np.isclose(krgn(0), 0.0) assert np.isclose(krgn(1), 0.9) assert np.isclose(kron(0), 0) assert np.isclose(kron(1), 0.8) # Test again with zero endpoints: gasoil = GasOil(swl=0, sgcr=0, sorg=0, h=0.01) gasoil.add_corey_gas(ng=2.1, krgend=0.9) gasoil.add_corey_oil(nog=3, kroend=0.8) krgn, kron = normalize_nonlinpart_go(gasoil) assert np.isclose(krgn(0), 0.0) assert np.isclose(krgn(1), 0.9) assert np.isclose(kron(0), 0) assert np.isclose(kron(1), 0.8) # Test when endpoints are messed up (cleared) gasoil = GasOil(swl=0.1, sgcr=0.2, sorg=0.1, h=0.1) gasoil.add_corey_gas(ng=2.1, krgend=0.6) gasoil.add_corey_oil(nog=3, kroend=0.8) gasoil.swl = 0 gasoil.sgcr = 0 gasoil.sorg = 0 krgn, kron = normalize_nonlinpart_go(gasoil) # These go well still, since we are at zero assert np.isclose(krgn(0), 0.0) assert np.isclose(kron(0), 0) assert np.isclose(kron(1), 0.8) # These do not match when endpoints are wrong assert not np.isclose(krgn(1), 0.6) # So fix endpoints! gasoil.swl = 1 - gasoil.table["sg"].max() gasoil.sgcr = gasoil.estimate_sgcr() gasoil.sorg = gasoil.estimate_sorg() # Try again krgn, kron = normalize_nonlinpart_go(gasoil) assert np.isclose(krgn(0), 0.0) assert np.isclose(kron(0), 0) assert np.isclose(krgn(1), 0.6) assert np.isclose(kron(1), 0.8)
def test_interpolations_go_fromtable(): """Test based on bug exposed in pyscal 0.6.1, where sgcr was underestimated in interpolations following add_fromtable(). """ base = pd.DataFrame( columns=["Sg", "krg", "krog"], data=[ [0.0, 0.0, 1.0], [0.1, 0.0, 1.0], [0.2, 0.0, 1.0], # sgcr [0.3, 0.1, 0.9], [0.8, 0.8, 0.0], # sorg [0.9, 0.9, 0.0], [1.0, 1.0, 0.0], ], ) opt = pd.DataFrame( columns=["Sg", "krg", "krog"], data=[ [0.0, 0.0, 1.0], [0.1, 0.0, 1.0], [0.3, 0.0, 1.0], [0.4, 0.1, 0.2], # sgcr [0.9, 0.9, 0.0], # sorg [0.95, 0.95, 0.0], [1.0, 1.0, 0.0], ], ) go_base = GasOil(h=0.01) go_base.add_fromtable(base) assert np.isclose(go_base.estimate_sgcr(), 0.2) assert np.isclose(go_base.estimate_sorg(), 0.2) go_opt = GasOil(h=0.01) go_opt.add_fromtable(opt) assert np.isclose(go_opt.estimate_sgcr(), 0.3) assert np.isclose(go_opt.estimate_sorg(), 0.1) go_ip = interpolate_go(go_base, go_opt, 0.5, h=0.01) assert np.isclose(go_ip.estimate_sgcr(), 0.25) assert np.isclose(go_ip.estimate_sorg(), 0.15)
def test_sorg(): """Test estimate_sorg for some manually set up cases""" # sorg, sgcr, h, swl: testtuples = [ (0.3, 0.01, 0.1, 0.1), (0.2, 0, 0.05, 0.0), (0.1, 0.3, 0.01, 0.5), (0.0, 0, 0.1, 0.000001), (0.9, 0.000001, 0.1, 0), (0.4, 0, 0.1, 0.2), ] for testtuple in testtuples: real_sorg = testtuple[0] real_sgcr = testtuple[1] h = testtuple[2] swl = testtuple[3] go = GasOil(sgcr=0.03, sorg=real_sorg, h=h, swl=swl) go.add_corey_oil(nog=2) go.add_corey_gas(ng=2, krgend=0.9) print("Testing sorg={} on h={}, swl={}".format(real_sorg, h, swl)) est_sorg = go.estimate_sorg() mis = abs(est_sorg - real_sorg) if mis > 0.01: print("Missed, estimated was {}".format(est_sorg)) assert mis < h + epsilon # Can't guarantee better than h. # If krgendanchor is not sorg (default), then krg cannot be used # and the GasOil object will resort to using krog. Should work # when now=2 but might not always work for all kinds of LET parameters. go = GasOil(sorg=real_sorg, h=h, swl=swl, krgendanchor="") go.add_corey_oil(nog=2) go.add_corey_gas(ng=2, krgend=0.8) est_sorg = go.estimate_sorg() print("Estimated to {}".format(est_sorg)) mis = abs(est_sorg - real_sorg) assert mis < h + epsilon # Test sgcr: go = GasOil(sorg=real_sorg, sgcr=real_sgcr, h=h, swl=swl, krgendanchor="sorg") go.add_corey_oil(nog=2, kroend=0.8) go.add_corey_gas(ng=2, krgend=0.8) est_sgcr = go.estimate_sgcr() mis = abs(est_sgcr - real_sgcr) assert mis < h + epsilon
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, ): # pylint: disable=too-many-arguments,too-many-locals """Test many possible combinations of interpolation between two Corey gasoil curves, looking for numerical corner cases""" h = 0.01 go_low = GasOil(swl=swl, sgcr=sgcr, sorg=sorg, h=h) go_high = GasOil( swl=swl + dswlhigh, sgcr=sgcr + dsgcr, sorg=max(sorg - dsorg, 0), h=h ) 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 = interpolate_go(go_low, go_high, t) check_table(go_ip.table) ips.append(go_ip) assert 0 < go_ip.crosspoint() < 1 # sgcr is non-trivial, if exponents are high, an effective sgcr might # be larger than the value used to initialize the curve. Try to be # permissive enough here. This can even cause the interpolant to be # outside the low-high envelope, but it is the way it is supposed to # be when sgcr is interpolated separately. sgcr_low = min( go_low.sgcr, go_low.estimate_sgcr(), go_high.sgcr, go_high.estimate_sgcr() ) sgcr_high = max( go_low.sgcr, go_low.estimate_sgcr(), go_high.sgcr, go_high.estimate_sgcr() ) sgcr_ip = go_ip.estimate_sgcr() sgcr_lower_bound_ok = sgcr_low - h - epsilon < sgcr_ip sgcr_upper_bound_ok = sgcr_ip < sgcr_high + h + epsilon assert sgcr_lower_bound_ok assert sgcr_upper_bound_ok # 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) _, 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