예제 #1
0
def test_interpolate_wo_pc(swl, dswcr, dswlhigh, sorw, a_l, a_h, b_l, b_h):
    """
    Generate two random WaterOil curves, interpolate pc between them
    and check that the difference between each interpolant is small,
    this essentially checks that we can go continously between the
    two functions.
    """
    # pylint: disable=too-many-locals
    wo_low = WaterOil(swl=swl, swcr=swl + dswcr, sorw=sorw)
    wo_high = WaterOil(swl=swl + dswlhigh,
                       swcr=swl + dswlhigh + dswcr,
                       sorw=max(sorw - 0.01, 0))
    wo_low.add_corey_water()
    wo_high.add_corey_water()
    wo_low.add_corey_oil()
    wo_high.add_corey_oil()
    wo_low.add_simple_J(a=a_l, b=b_l)
    wo_high.add_simple_J(a=a_h, b=b_h)
    ips = []
    ip_dist = 0.05
    for t in np.arange(0, 1 + ip_dist, ip_dist):
        wo_ip = interpolate_wo(wo_low, wo_high, t)
        check_table(wo_ip.table)
        ips.append(wo_ip)
        assert 0 < wo_ip.crosspoint() < 1

    # Distances between low and interpolants:
    dists = [(wo_low.table - interp.table)[["pc"]].sum().sum()
             for interp in ips]
    assert np.isclose(dists[0], 0)

    # Distance between high and the last interpolant
    assert (wo_high.table - ips[-1].table)[["pc"]].sum().sum() < 0.01

    # Distances between low and interpolants:
    dists = [(wo_low.table - interp.table)[["pc"]].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 wo_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
    # (avoiding the first which reproduces go_low
    if ip_dist_std > 1.0:  # Found by trial and error
        print("ip_dist_std: {}".format(ip_dist_std))
        print(dists)
        _, mpl_ax = plt.subplots()
        wo_low.plotpc(mpl_ax=mpl_ax, color="red", logyscale=True)
        wo_high.plotpc(mpl_ax=mpl_ax, color="blue", logyscale=True)
        for interp in ips:
            interp.plotpc(mpl_ax=mpl_ax, color="green", logyscale=True)
        plt.show()
        assert False
예제 #2
0
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 = 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 = 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 = 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 = interpolate_wo(
        wo_low, wo_high, parameter=0.1, h=0.2, tag="Explicit tag"
    )
    assert interpolant4.tag == "Explicit tag"

    # Tag with newline
    interpolant6 = 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 = 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 = 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())
예제 #3
0
def test_ip_wo_kroend():
    """Test behaviour of kroend under interpolation"""
    wo_low = WaterOil(swl=0, swcr=0.1, sorw=0.2)
    wo_low.add_corey_water(nw=2, krwend=0.5, krwmax=0.7)
    wo_low.add_corey_oil(now=2, kroend=0.6)

    wo_high = WaterOil(swl=0.02, swcr=0.05, sorw=0.1)
    wo_high.add_corey_water(nw=2, krwend=0.5, krwmax=0.72)
    wo_high.add_corey_oil(now=2, kroend=0.7)

    # Interpolate to midpoint between the curves above
    wo_ip = interpolate_wo(wo_low, wo_high, 0.5)

    # kroend at mean swl:
    assert float_df_checker(wo_ip.table, "sw", 0.01, "krow", (0.6 + 0.7) / 2.0)

    assert float_df_checker(wo_ip.table, "sw", 1, "krw", 0.71)
    assert float_df_checker(wo_ip.table, "sw", 1 - 0.15, "krw", 0.5)
예제 #4
0
def test_interpolations_wo_fromtable():
    """Analog test as test_interpolations_go_fromtable().

    Pyscal 0.6.1 and earlier fails this test sorw.
    """
    base = pd.DataFrame(
        columns=["Sw", "krw", "krow"],
        data=[
            [0.0, 0.0, 1.0],
            [0.1, 0.0, 1.0],
            [0.2, 0.0, 1.0],  # swcr
            [0.3, 0.1, 0.9],
            [0.8, 0.8, 0.0],  # sorw
            [0.9, 0.9, 0.0],
            [1.0, 1.0, 0.0],
        ],
    )
    opt = pd.DataFrame(
        columns=["Sw", "krw", "krow"],
        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],  # swcr
            [0.9, 0.9, 0.0],  # sorw
            [0.95, 0.95, 0.0],
            [1.0, 1.0, 0.0],
        ],
    )
    wo_base = WaterOil(h=0.01)
    wo_base.add_fromtable(base)
    assert np.isclose(wo_base.estimate_swcr(), 0.2)
    assert np.isclose(wo_base.estimate_sorw(), 0.2)
    wo_opt = WaterOil(h=0.01)
    wo_opt.add_fromtable(opt)
    assert np.isclose(wo_opt.estimate_swcr(), 0.3)
    assert np.isclose(wo_opt.estimate_sorw(), 0.1)

    wo_ip = interpolate_wo(wo_base, wo_opt, 0.5, h=0.01)
    assert np.isclose(wo_ip.estimate_swcr(), 0.25)
    assert np.isclose(wo_ip.estimate_sorw(), 0.15)
예제 #5
0
    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