Beispiel #1
0
def test_factory_wateroilgas_deprecated_krowgend(caplog):
    """Some users will use deprecated  krowend krogend,
    these values should be translated to kroend"""
    wog = PyscalFactory.create_water_oil_gas(
        dict(nw=2, now=3, ng=1, nog=2.5, krowend=0.6, krogend=0.7))
    assert "deprecated" in caplog.text
    swof = wog.SWOF()
    assert "kroend=0.6" in swof
    sgof = wog.SGOF()
    assert "kroend=0.7" in sgof
    assert not wog.threephaseconsistency()
    sat_table_str_ok(swof)  # sgof code works for swof also currently
    sat_table_str_ok(sgof)
    assert "Corey krg" in sgof
    assert "Corey krog" in sgof
    assert "Corey krw" in swof
    assert "Corey krow" in swof
Beispiel #2
0
def test_fast_mode():
    """Test that the fast-flag is passed on to constructed objects

    Each object's own test code tests the actual effects of the fast flag"""
    wateroil = PyscalFactory.create_water_oil({"nw": 2, "now": 2})
    assert not wateroil.fast
    wateroil = PyscalFactory.create_water_oil({"nw": 2, "now": 2}, fast=True)
    assert wateroil.fast

    gasoil = PyscalFactory.create_gas_oil({"ng": 2, "nog": 2})
    assert not gasoil.fast
    gasoil = PyscalFactory.create_gas_oil({"ng": 2, "nog": 2}, fast=True)
    assert gasoil.fast

    gaswater = PyscalFactory.create_gas_water({"nw": 2, "ng": 2})
    assert not gaswater.gasoil.fast
    assert not gaswater.wateroil.fast
    gaswater = PyscalFactory.create_gas_water({"nw": 2, "ng": 2}, fast=True)
    assert gaswater.gasoil.fast
    assert gaswater.wateroil.fast
    assert gaswater.fast

    wateroilgas = PyscalFactory.create_water_oil_gas(
        {"nw": 2, "now": 2, "ng": 2, "nog": 2}, fast=True
    )
    assert wateroilgas.fast
    assert wateroilgas.wateroil.fast
    assert wateroilgas.gasoil.fast

    scalrec = PyscalFactory.create_scal_recommendation(
        {
            "low": {"nw": 2, "now": 2, "ng": 2, "nog": 2},
            "base": {"nw": 2, "now": 2, "ng": 2, "nog": 2},
            "high": {"nw": 2, "now": 2, "ng": 2, "nog": 2},
        },
        fast=True,
    )
    assert scalrec.low.fast
    assert scalrec.base.fast
    assert scalrec.high.fast

    interpolant = scalrec.interpolate(-0.5)
    assert interpolant.fast
Beispiel #3
0
def test_xls_scalrecommendation():
    """Test making SCAL recommendations from xls data"""

    if "__file__" in globals():
        # Easen up copying test code into interactive sessions
        testdir = os.path.dirname(os.path.abspath(__file__))
    else:
        testdir = os.path.abspath(".")

    xlsxfile = testdir + "/data/scal-pc-input-example.xlsx"
    scalinput = pd.read_excel(xlsxfile).set_index(["SATNUM", "CASE"])
    print(scalinput)
    for satnum in scalinput.index.levels[0].values:
        dictofdict = scalinput.loc[satnum, :].to_dict(orient="index")
        print(dictofdict)
        scalrec = PyscalFactory.create_scal_recommendation(dictofdict)
        print(scalrec.interpolate(-0.5).SWOF())
        scalrec.interpolate(+0.5)
Beispiel #4
0
def interpolatetest():
    """Test interpolation (sample test) in a scal recommentation"""
    rec = PyscalFactory.create_scal_recommendation(
        {
            "low": LOW_SAMPLE_LET,
            "base": BASE_SAMPLE_LET,
            "high": HIGH_SAMPLE_LET
        },
        "foo",
        h=0.001,
    )
    rec.add_simple_J()  # Add default pc curve
    #    print rec.low.wateroil.table
    interpolant = rec.interpolate(0.3, parameter2=-0.9, h=0.05)
    print(interpolant.wateroil.SWOF())
    print(interpolant.gasoil.SGOF())

    print("Consistency check: ", end=" ")
    print(interpolant.threephaseconsistency())
Beispiel #5
0
def test_comments_df():
    """Test that we support a tag column in the dataframe, and
    that we are able to handle UTF-8 stuff nicely in py2-3
    """
    dframe = pd.DataFrame(
        columns=["SATNUM", "tag", "Nw", "Now", "ng", "nOG"],
        data=[[1, "thisisacomment", 2, 2, 2, 2]],
    )
    relperm_data = PyscalFactory.load_relperm_df(dframe)
    p_list = PyscalFactory.create_pyscal_list(relperm_data, h=0.2)
    relperm_str = p_list.dump_family_1()
    assert "thisisacomment" in relperm_str

    # tag vs comment in dataframe should not matter.
    dframe = pd.DataFrame(
        columns=["SATNUM", "comment", "Nw", "Now", "ng", "nOG"],
        data=[[1, "thisisacomment", 2, 2, 2, 2]],
    )
    relperm_data = PyscalFactory.load_relperm_df(dframe)
    p_list = PyscalFactory.create_pyscal_list(relperm_data, h=0.2)
    relperm_str = p_list.dump_family_1()
    assert relperm_str.count("thisisacomment") == 2

    # Check case insensitiveness:
    dframe = pd.DataFrame(
        columns=["SAtnUM", "coMMent", "Nw", "Now", "ng", "nOG"],
        data=[[1, "thisisacomment", 2, 2, 2, 2]],
    )
    relperm_data = PyscalFactory.load_relperm_df(dframe)
    p_list = PyscalFactory.create_pyscal_list(relperm_data, h=0.2)
    assert p_list.dump_family_1().count("thisisacomment") == 2

    # UTF-8 stuff:
    dframe = pd.DataFrame(
        columns=["SATNUM", "TAG", "Nw", "Now", "Ng", "Nog"],
        data=[[1, "æøå", 2, 2, 2, 2]],
    )
    relperm_data = PyscalFactory.load_relperm_df(dframe)
    p_list = PyscalFactory.create_pyscal_list(relperm_data, h=0.2)
    assert p_list.dump_family_1().count("æøå") == 2
Beispiel #6
0
def test_scalrecommendation():
    """Testing making SCAL rec from dict of dict."""
    pyscal_factory = PyscalFactory()

    scal_input = {
        "low": {
            "nw": 2,
            "now": 4,
            "ng": 1,
            "nog": 2
        },
        "BASE": {
            "nw": 3,
            "NOW": 3,
            "ng": 1,
            "nog": 2
        },
        "high": {
            "nw": 4,
            "now": 2,
            "ng": 1,
            "nog": 3
        },
    }
    scal = pyscal_factory.create_scal_recommendation(scal_input)
    # (not supported yet to make WaterOil only..)
    interp = scal.interpolate(-0.5)
    sat_table_str_ok(interp.SWOF())
    sat_table_str_ok(interp.SGOF())
    sat_table_str_ok(interp.SLGOF())
    sat_table_str_ok(interp.SOF3())
    check_table(interp.wateroil.table)
    check_table(interp.gasoil.table)

    incomplete1 = scal_input.copy()
    del incomplete1["BASE"]
    with pytest.raises(ValueError):
        pyscal_factory.create_scal_recommendation(incomplete1)

    go_only = scal_input.copy()
    del go_only["low"]["now"]
    del go_only["low"]["nw"]
    gasoil = pyscal_factory.create_scal_recommendation(go_only)
    assert gasoil.low.wateroil is None
    assert gasoil.base.wateroil is not None
    assert gasoil.high.wateroil is not None
    # SCALrecommendation of gasoil only works as long as you
    # don't try to ask for water data:
    assert "SGFN" in gasoil.interpolate(-0.4).SGFN()
    assert "SWOF" not in gasoil.interpolate(-0.2).SWOF()
Beispiel #7
0
def test_factory_gaswater():
    """Test that we can create gas-water curves from dictionaries of parameters"""
    pyscal_factory = PyscalFactory()

    with pytest.raises(TypeError):
        # pylint: disable=unexpected-keyword-arg
        pyscal_factory.create_gas_water(swirr=0.01)  # noqa

    gaswater = pyscal_factory.create_gas_water(
        dict(swirr=0.01,
             swl=0.03,
             sgrw=0.1,
             sgcr=0.15,
             tag="gassy sand",
             ng=2,
             nw=2))

    assert isinstance(gaswater, GasWater)

    assert gaswater.swirr == 0.01
    assert gaswater.swl == 0.03
    assert gaswater.sgrw == 0.1
    assert gaswater.sgcr == 0.15
    assert gaswater.tag == "gassy sand"

    sgfn = gaswater.SGFN()
    swfn = gaswater.SWFN()
    sat_table_str_ok(sgfn)
    sat_table_str_ok(swfn)
    check_table(gaswater.wateroil.table)
    check_table(gaswater.gasoil.table)

    assert "sgrw=0.1" in swfn
    assert "swirr=0.01" in sgfn
    assert "swirr=0.01" in swfn
    assert "sgrw=0.1" in swfn
    assert "sgcr=0.15" in sgfn
    assert "nw=2" in swfn
    assert "ng=2" in sgfn
    assert "gassy sand" in sgfn

    gaswater = pyscal_factory.create_gas_water(dict(lg=1, eg=1, tg=1, nw=3))

    sgfn = gaswater.SGFN()
    swfn = gaswater.SWFN()
    sat_table_str_ok(sgfn)
    sat_table_str_ok(swfn)
    check_table(gaswater.wateroil.table)
    check_table(gaswater.gasoil.table)
Beispiel #8
0
def test_load_scalrec(tmpdir):
    """Load a SATNUM range from xlsx"""
    testdir = Path(__file__).absolute().parent

    scalrec_data = PyscalFactory.load_relperm_df(
        testdir / "data/scal-pc-input-example.xlsx")

    # Also check that we can read the old excel format
    scalrec_data_legacy_xls = PyscalFactory.load_relperm_df(
        testdir / "data/scal-pc-input-example.xls")
    pd.testing.assert_frame_equal(scalrec_data, scalrec_data_legacy_xls)

    scalrec_list = PyscalFactory.create_scal_recommendation_list(scalrec_data)
    wog_list = scalrec_list.interpolate(-0.3)

    with pytest.raises((AssertionError, ValueError)):
        scalrec_list.interpolate(-1.1)
    assert wog_list.pyscaltype == WaterOilGas

    with pytest.raises(TypeError):
        scalrec_list.dump_family_1()
    with pytest.raises(TypeError):
        scalrec_list.dump_family_2()
    with pytest.raises(TypeError):
        scalrec_list.SWOF()

    scalrec_list.interpolate([-1, 1, 0])
    with pytest.raises((AssertionError, ValueError)):
        scalrec_list.interpolate([-1, 0, 1.1])

    # Not enough interpolation parameters
    with pytest.raises(ValueError):
        scalrec_list.interpolate([-1, 1])
    with pytest.raises(ValueError):
        scalrec_list.interpolate([-1, 1, 0, 0])

    scalrec_list.interpolate(-1, 1)
    scalrec_list.interpolate(-1, [0, -1, 1])

    with pytest.raises(ValueError):
        scalrec_list.interpolate(1, [-1, 1, 0, 0])

    # Test slicing the scalrec to base, this is relevant for
    # API usage.
    base_data = scalrec_data[scalrec_data["CASE"] == "base"].drop("CASE",
                                                                  axis=1)
    PyscalFactory.load_relperm_df(base_data)  # Ensure no errors.
    pyscal_list = PyscalFactory.create_pyscal_list(base_data)
    assert "LET" in pyscal_list.dump_family_1()
Beispiel #9
0
def test_factory_gasoil():
    """Test that we can create curves from dictionaries of parameters"""

    logging.getLogger().setLevel("INFO")

    factory = PyscalFactory()

    with pytest.raises(TypeError):
        # (this must be a dictionary)
        factory.create_gas_oil(swirr=0.01)  # noqa

    go = factory.create_gas_oil(
        dict(swirr=0.01, swl=0.1, sgcr=0.05, tag="Good sand", ng=1, nog=2))
    assert isinstance(go, GasOil)
    assert go.sgcr == 0.05
    assert go.swl == 0.1
    assert go.swirr == 0.01
    assert go.tag == "Good sand"
    sgof = go.SGOF()
    assert "Corey krg" in sgof
    assert "Corey krog" in sgof
    assert "Zero capillary pressure" in sgof

    go = factory.create_gas_oil(
        dict(ng=1.2, nog=2, krgend=0.8, krgmax=0.9, kroend=0.6))
    sgof = go.SGOF()
    assert "kroend=0.6" in sgof
    assert "krgend=0.8" in sgof

    go = factory.create_gas_oil(dict(ng=1.3, Log=2, Eog=2, Tog=2))
    sgof = go.SGOF()
    assert "Corey krg" in sgof
    assert "LET krog" in sgof

    go = factory.create_gas_oil(dict(Lg=1, Eg=1, Tg=1, Log=2, Eog=2, Tog=2))
    sgof = go.SGOF()
    assert "LET krg" in sgof
    assert "LET krog" in sgof
Beispiel #10
0
def test_boundary_cases():
    """Test that interpolation is able to return the boundaries
    at +/- 1"""
    rec = PyscalFactory.create_scal_recommendation(
        {
            "low": LOW_SAMPLE_LET,
            "base": BASE_SAMPLE_LET,
            "high": HIGH_SAMPLE_LET
        },
        "foo",
        h=0.1,
    )
    # Object reference equivalence is a little bit strict,
    # because it would be perfectly fine if interpolate()
    # retured copied objects. But we don't have an equivalence operator
    # implemented.
    assert rec.interpolate(0).wateroil == rec.base.wateroil
    assert rec.interpolate(-1).wateroil == rec.low.wateroil
    assert rec.interpolate(1).wateroil == rec.high.wateroil
    assert rec.interpolate(0).gasoil == rec.base.gasoil
    assert rec.interpolate(-1).gasoil == rec.low.gasoil
    assert rec.interpolate(1).gasoil == rec.high.gasoil

    assert rec.interpolate(0, 1).wateroil == rec.base.wateroil
    assert rec.interpolate(-1, 1).wateroil == rec.low.wateroil
    assert rec.interpolate(1, 1).wateroil == rec.high.wateroil

    assert rec.interpolate(0, 1).gasoil == rec.high.gasoil
    assert rec.interpolate(-1, 1).gasoil == rec.high.gasoil
    assert rec.interpolate(1, 1).gasoil == rec.high.gasoil

    assert rec.interpolate(0, 0).gasoil == rec.base.gasoil
    assert rec.interpolate(-1, 0).gasoil == rec.base.gasoil
    assert rec.interpolate(1, 0).gasoil == rec.base.gasoil

    assert rec.interpolate(0, -1).gasoil == rec.low.gasoil
    assert rec.interpolate(-1, -1).gasoil == rec.low.gasoil
    assert rec.interpolate(1, -1).gasoil == rec.low.gasoil
Beispiel #11
0
def test_xls_factory():
    """Test/demonstrate how to go from data in an excel row to pyscal objects"""

    if "__file__" in globals():
        # Easen up copying test code into interactive sessions
        testdir = os.path.dirname(os.path.abspath(__file__))
    else:
        testdir = os.path.abspath(".")

    xlsxfile = testdir + "/data/scal-pc-input-example.xlsx"

    scalinput = pd.read_excel(xlsxfile).set_index(["SATNUM", "CASE"])

    for ((satnum, _), params) in scalinput.iterrows():
        assert satnum
        wog = PyscalFactory.create_water_oil_gas(params.to_dict())
        swof = wog.SWOF()
        assert "LET krw" in swof
        assert "LET krow" in swof
        assert "Simplified J" in swof
        sgof = wog.SGOF()
        assert "LET krg" in sgof
        assert "LET krog" in sgof
Beispiel #12
0
def test_xls_factory():
    """Test/demonstrate how to go from data in an excel row to pyscal objects

    This test function predates the load_relperm_df() function, but can
    still be in here.
    """
    testdir = Path(__file__).absolute().parent

    xlsxfile = testdir / "data/scal-pc-input-example.xlsx"

    scalinput = pd.read_excel(xlsxfile, engine="openpyxl").set_index(["SATNUM", "CASE"])

    for ((satnum, _), params) in scalinput.iterrows():
        assert satnum
        wog = PyscalFactory.create_water_oil_gas(params.to_dict())
        swof = wog.SWOF()
        assert "LET krw" in swof
        assert "LET krow" in swof
        assert "Simplified J" in swof
        sgof = wog.SGOF()
        sat_table_str_ok(sgof)
        assert "LET krg" in sgof
        assert "LET krog" in sgof
def test_interpolation(param_wo, param_go):
    """Test interpolation with random interpolation parameters,
    looking for numerical corner cases"""

    rec = PyscalFactory.create_scal_recommendation(
        {
            "low": LOW_SAMPLE_LET,
            "base": BASE_SAMPLE_LET,
            "high": HIGH_SAMPLE_LET
        },
        "foo",
        h=0.1,
    )
    rec.add_simple_J()  # Add default pc curve

    # Check that added pc curve is non-zero
    assert sum(rec.low.wateroil.table["PC"])
    assert sum(rec.base.wateroil.table["PC"])
    assert sum(rec.high.wateroil.table["PC"])

    try:
        interpolant = rec.interpolate(param_wo, param_go, h=0.1)
    except ValueError:
        return

    check_table(interpolant.wateroil.table)
    check_table(interpolant.gasoil.table)

    assert len(interpolant.gasoil.SGOF()) > 100
    assert len(interpolant.gasoil.SGFN()) > 100
    assert len(interpolant.wateroil.SWFN()) > 100
    assert len(interpolant.SOF3()) > 100
    assert len(interpolant.wateroil.SWOF()) > 100
    assert interpolant.threephaseconsistency()

    assert sum(interpolant.wateroil.table["PC"])
Beispiel #14
0
def test_scalrecommendation():
    """Testing making SCAL rec from dict of dict"""

    factory = PyscalFactory()

    scal_input = {
        "low": {
            "nw": 2,
            "now": 4,
            "ng": 1,
            "nog": 2
        },
        "BASE": {
            "nw": 3,
            "NOW": 3,
            "ng": 1,
            "nog": 2
        },
        "high": {
            "nw": 4,
            "now": 2,
            "ng": 1,
            "nog": 3
        },
    }
    scal = factory.create_scal_recommendation(scal_input)
    # (not supported yet to make WaterOil only..)
    scal.interpolate(-0.5).SWOF()

    incomplete1 = scal_input.copy()
    del incomplete1["BASE"]
    with pytest.raises(ValueError):
        factory.create_scal_recommendation(incomplete1)

    incomplete2 = scal_input.copy()
    del incomplete2["low"]["now"]
    with pytest.raises(ValueError):
        factory.create_scal_recommendation(incomplete2)
Beispiel #15
0
def test_load_relperm_df(tmpdir):
    """Test loading of dataframes with validation from excel or from csv"""
    testdir = Path(__file__).absolute().parent

    scalfile_xls = testdir / "data/scal-pc-input-example.xlsx"

    scaldata = PyscalFactory.load_relperm_df(scalfile_xls)
    with pytest.raises(IOError):
        PyscalFactory.load_relperm_df("not-existing-file")

    assert "SATNUM" in scaldata
    assert "CASE" in scaldata
    assert not scaldata.empty

    tmpdir.chdir()
    scaldata.to_csv("scal-input.csv")
    scaldata_fromcsv = PyscalFactory.load_relperm_df("scal-input.csv")
    assert "CASE" in scaldata_fromcsv
    assert not scaldata_fromcsv.empty
    scaldata_fromdf = PyscalFactory.load_relperm_df(scaldata_fromcsv)
    assert "CASE" in scaldata_fromdf
    assert "SATNUM" in scaldata_fromdf
    assert len(scaldata_fromdf) == len(scaldata_fromcsv) == len(scaldata)

    # Perturb the dataframe, this should trigger errors
    with pytest.raises(ValueError):
        PyscalFactory.load_relperm_df(scaldata.drop("SATNUM", axis="columns"))
    wrongsatnums = scaldata.copy()
    wrongsatnums["SATNUM"] = wrongsatnums["SATNUM"] * 2
    with pytest.raises(ValueError):
        PyscalFactory.load_relperm_df(wrongsatnums)
    wrongsatnums = scaldata.copy()
    wrongsatnums["SATNUM"] = wrongsatnums["SATNUM"].astype(int)
    wrongsatnums = wrongsatnums[wrongsatnums["SATNUM"] > 2]
    with pytest.raises(ValueError):
        PyscalFactory.load_relperm_df(wrongsatnums)
    wrongcases = scaldata.copy()
    wrongcases["CASE"] = wrongcases["CASE"] + "ffooo"
    with pytest.raises(ValueError):
        PyscalFactory.load_relperm_df(wrongcases)

    with pytest.raises(ValueError):
        PyscalFactory.load_relperm_df(scaldata.drop(["Lw", "Lg"], axis="columns"))

    # Insert a NaN, this replicates what happens if cells are merged
    mergedcase = scaldata.copy()
    mergedcase.loc[3, "SATNUM"] = np.nan
    with pytest.raises(ValueError):
        PyscalFactory.load_relperm_df(mergedcase)

    relpermfile_xls = testdir / "data/relperm-input-example.xlsx"
    relpermdata = PyscalFactory.load_relperm_df(relpermfile_xls)
    assert "TAG" in relpermdata
    assert "SATNUM" in relpermdata
    assert "satnum" not in relpermdata  # always converted to upper-case
    assert len(relpermdata) == 3
    swof_str = PyscalFactory.create_pyscal_list(relpermdata, h=0.2).SWOF()
    assert "Åre 1.8" in swof_str
    assert "SATNUM 2" in swof_str  # Autogenerated in SWOF, generated by factory
    assert "SATNUM 3" in swof_str
    assert "foobar" in swof_str  # Random string injected in xlsx.

    # Make a dummy text file
    with open("dummy.txt", "w") as fhandle:
        fhandle.write("foo\nbar, com")
    with pytest.raises(ValueError):
        PyscalFactory.load_relperm_df("dummy.txt")
Beispiel #16
0
def test_factory_wateroil():
    """Test that we can create curves from dictionaries of parameters"""
    pyscal_factory = PyscalFactory()

    # Factory refuses to create incomplete defaulted objects.
    with pytest.raises(ValueError):
        pyscal_factory.create_water_oil()

    with pytest.raises(TypeError):
        # (it must be a dictionary)
        # pylint: disable=unexpected-keyword-arg
        pyscal_factory.create_water_oil(swirr=0.01)  # noqa

    wateroil = pyscal_factory.create_water_oil(
        dict(
            swirr=0.01,
            swl=0.1,
            bogus="foobar",
            tag="Good sand",
            nw=3,
            now=2,
            krwend=0.2,
            krwmax=0.5,
        )
    )
    assert isinstance(wateroil, WaterOil)
    assert wateroil.swirr == 0.01
    assert wateroil.swl == 0.1
    assert wateroil.tag == "Good sand"
    assert "krw" in wateroil.table
    assert "Corey" in wateroil.krwcomment
    assert wateroil.table["krw"].max() == 0.2  # Because sorw==0 by default
    check_table(wateroil.table)
    sat_table_str_ok(wateroil.SWOF())
    sat_table_str_ok(wateroil.SWFN())

    wateroil = pyscal_factory.create_water_oil(
        dict(nw=3, now=2, sorw=0.1, krwend=0.2, krwmax=0.5)
    )
    assert isinstance(wateroil, WaterOil)
    assert "krw" in wateroil.table
    assert "Corey" in wateroil.krwcomment
    assert wateroil.table["krw"].max() == 0.5
    check_table(wateroil.table)
    sat_table_str_ok(wateroil.SWOF())
    sat_table_str_ok(wateroil.SWFN())

    # Ambiguous works, but we don't guarantee that this results
    # in LET or Corey.
    wateroil = pyscal_factory.create_water_oil(dict(nw=3, Lw=2, Ew=2, Tw=2, now=3))
    assert "krw" in wateroil.table
    assert "Corey" in wateroil.krwcomment or "LET" in wateroil.krwcomment
    check_table(wateroil.table)
    sat_table_str_ok(wateroil.SWOF())
    sat_table_str_ok(wateroil.SWFN())

    # Mixing Corey and LET
    wateroil = pyscal_factory.create_water_oil(dict(Lw=2, Ew=2, Tw=2, krwend=1, now=4))
    assert isinstance(wateroil, WaterOil)
    assert "krw" in wateroil.table
    assert wateroil.table["krw"].max() == 1.0
    assert "LET" in wateroil.krwcomment
    check_table(wateroil.table)
    sat_table_str_ok(wateroil.SWOF())
    sat_table_str_ok(wateroil.SWFN())

    wateroil = pyscal_factory.create_water_oil(
        dict(Lw=2, Ew=2, Tw=2, Low=3, Eow=3, Tow=3, krwend=0.5)
    )
    assert isinstance(wateroil, WaterOil)
    assert "krw" in wateroil.table
    assert "krow" in wateroil.table
    assert wateroil.table["krw"].max() == 0.5
    assert wateroil.table["krow"].max() == 1
    assert "LET" in wateroil.krwcomment
    assert "LET" in wateroil.krowcomment
    check_table(wateroil.table)
    sat_table_str_ok(wateroil.SWOF())
    sat_table_str_ok(wateroil.SWFN())

    # Add capillary pressure
    wateroil = pyscal_factory.create_water_oil(
        dict(swl=0.1, nw=1, now=1, a=2, b=-1, poro_ref=0.2, perm_ref=100, drho=200)
    )
    assert "pc" in wateroil.table
    assert wateroil.table["pc"].max() > 0.0
    assert "Simplified J" in wateroil.pccomment
    check_table(wateroil.table)
    sat_table_str_ok(wateroil.SWOF())
    sat_table_str_ok(wateroil.SWFN())

    # Test that the optional gravity g is picked up:
    wateroil = pyscal_factory.create_water_oil(
        dict(swl=0.1, nw=1, now=1, a=2, b=-1, poro_ref=0.2, perm_ref=100, drho=200, g=0)
    )
    assert "pc" in wateroil.table
    assert wateroil.table["pc"].max() == 0.0
    check_table(wateroil.table)
    sat_table_str_ok(wateroil.SWOF())
    sat_table_str_ok(wateroil.SWFN())

    # Test petrophysical simple J:
    wateroil = pyscal_factory.create_water_oil(
        dict(
            swl=0.1,
            nw=1,
            now=1,
            a_petro=2,
            b_petro=-1,
            poro_ref=0.2,
            perm_ref=100,
            drho=200,
        )
    )
    assert "pc" in wateroil.table
    assert wateroil.table["pc"].max() > 0.0
    assert "etrophysic" in wateroil.pccomment
    check_table(wateroil.table)
    sat_table_str_ok(wateroil.SWOF())
    sat_table_str_ok(wateroil.SWFN())

    # One pc param missing:
    wateroil = pyscal_factory.create_water_oil(
        dict(swl=0.1, nw=1, now=1, a=2, b=-1, perm_ref=100, drho=200, g=0)
    )
    assert "pc" not in wateroil.table
Beispiel #17
0
def test_init_with_swlheight():
    """With sufficient parameters, swl will be calculated on the fly
    when initializing the WaterOil object"""
    pyscal_factory = PyscalFactory()
    wateroil = pyscal_factory.create_water_oil(
        dict(
            swlheight=200,
            nw=1,
            now=1,
            swirr=0.01,
            a=1,
            b=-2,
            poro_ref=0.2,
            perm_ref=100,
            drho=200,
        )
    )
    assert np.isclose(wateroil.swl, 0.02480395)
    assert "swl=0.024" in wateroil.SWOF()

    with pytest.raises(
        ValueError,
        match="Can't initialize from SWLHEIGHT without sufficient simple-J parameters",
    ):
        # This should fail because capillary pressure parameters are not provided.
        pyscal_factory.create_water_oil(dict(swlheight=200, nw=1, now=1))

    # swcr must be larger than swl:
    with pytest.raises(ValueError, match="lower than computed swl"):
        pyscal_factory.create_water_oil(
            dict(
                swlheight=200,
                nw=1,
                now=1,
                swirr=0.01,
                swcr=0.0101,
                a=1,
                b=-2,
                poro_ref=0.2,
                perm_ref=100,
                drho=200,
            )
        )

    # If swcr is large enough, it will pass:
    wateroil = pyscal_factory.create_water_oil(
        dict(
            swlheight=200,
            nw=1,
            now=1,
            swirr=0.01,
            swcr=0.3,
            a=1,
            b=-2,
            poro_ref=0.2,
            perm_ref=100,
            drho=200,
        )
    )
    assert wateroil.swcr > wateroil.swl
    assert wateroil.swcr == 0.3
    assert "swcr=0.3" in wateroil.SWOF()

    # Test that GasWater also can be initialized with swlheight:
    gaswater = pyscal_factory.create_gas_water(
        dict(
            swlheight=200,
            nw=1,
            ng=1,
            swirr=0.01,
            swcr=0.3,
            a=1,
            b=-2,
            poro_ref=0.2,
            perm_ref=100,
            drho=200,
        )
    )
    assert "swl=0.024" in gaswater.SWFN()
    assert gaswater.swcr > gaswater.swl
    assert gaswater.swcr == 0.3
    assert "swcr=0.3" in gaswater.SWFN()
Beispiel #18
0
def pyscal_main(
    parametertable,
    verbose=False,
    output="relperm.inc",
    delta_s=None,
    int_param_wo=None,
    int_param_go=None,
    sheet_name=None,
    slgof=False,
    family2=False,
):
    """A "main()" method not relying on argparse. This can be used
    for testing, and also by an ERT forward model, e.g.
    in semeio (github.com/equinor/semeio)

    Args:
        parametertable (string): Filename (CSV or XLSX) to load
        verbose (bool): verbose or not
        output (string): Output filename
        delta_s (float): Saturation step-length
        int_param_wo (list): Interpolation params for wateroil
        int_param_go (list): Interpolation params for gasoil
        sheet_name (string): Which sheet in XLSX file
        slgof (bool): Use SLGOF
        family2 (bool): Dump family 2 keywords
    """
    if verbose:
        # Fixme: Logging level is not inherited in called modules.
        logger.setLevel(logging.INFO)

    if sheet_name:
        logger.info("Loading data from %s and sheetname %s", parametertable,
                    sheet_name)
    else:
        logger.info("Loading data from %s", parametertable)
    scalinput_df = PyscalFactory.load_relperm_df(parametertable,
                                                 sheet_name=sheet_name)

    logger.info("Input data:\n%s", scalinput_df.to_string(index=False))

    if int_param_go is not None and int_param_wo is None:
        logger.error("Don't use int_param_go alone, only int_param_wo")
        raise ValueError
    if "SATNUM" not in scalinput_df:
        logger.error("There is no column called SATNUM in the input data")
        raise ValueError
    if "CASE" in scalinput_df:
        # Then we should do interpolation
        if int_param_wo is None:
            logger.error("No interpolation parameters provided")
            raise ValueError
        scalrec_list = PyscalFactory.create_scal_recommendation_list(
            scalinput_df, h=delta_s)
        logger.info(
            "Interpolating, wateroil=%s, gasoil=%s",
            str(int_param_wo),
            str(int_param_go),
        )
        wog_list = scalrec_list.interpolate(int_param_wo,
                                            int_param_go,
                                            h=delta_s)
    else:
        wog_list = PyscalFactory.create_pyscal_list(
            scalinput_df,
            h=delta_s)  # can be both water-oil, water-oil-gas, or gas-water

    if (int_param_wo is not None
            or int_param_go is not None) and "CASE" not in scalinput_df:
        logger.error(
            "Interpolation parameter provided but no CASE column in input data"
        )
        raise ValueError
    if not family2:
        logger.info("Generating family 1 keywords.")
        if output == "-":
            print(wog_list.dump_family_1(slgof=slgof))
        else:
            wog_list.dump_family_1(filename=output, slgof=slgof)
            print("Written to " + output)
    else:
        logger.info("Generating family 2 keywords")
        if output == "-":
            print(wog_list.dump_family_2())
        else:
            wog_list.dump_family_2(filename=output)
            print("Written to " + output)
Beispiel #19
0
def test_error_messages_pr_satnum(caplog):
    """When errors are somewhere in a big dataframe, we should
    provide hints to the user for where to look"""

    # A string instead of a number in SATNUM 2
    dframe = pd.DataFrame(columns=["SATNUM", "nw", "now"],
                          data=[[1, 1, 1], [2, "foo", 1]])
    with pytest.raises(ValueError, match="SATNUM 2"):
        PyscalFactory.create_pyscal_list(dframe, h=0.2)

    dframe = pd.DataFrame(columns=["SATNUM", "nw", "now"],
                          data=[[1, 1, 1], [2, np.nan, 1]])
    with pytest.raises(ValueError, match="SATNUM 2"):
        PyscalFactory.create_pyscal_list(dframe, h=0.2)

    # Mixed up order:
    dframe = pd.DataFrame(columns=["SATNUM", "nw", "now"],
                          data=[[2, np.nan, 1], [1, 1, 1]])
    with pytest.raises(ValueError, match="SATNUM 2"):
        PyscalFactory.create_pyscal_list(dframe, h=0.2)

    # Gasoil list
    dframe = pd.DataFrame(columns=["SATNUM", "ng", "nog"],
                          data=[[1, 1, 1], [2, np.nan, 1]])
    with pytest.raises(ValueError, match="SATNUM 2"):
        PyscalFactory.create_pyscal_list(dframe, h=0.2)

    # Gaswater list:
    dframe = pd.DataFrame(columns=["SATNUM", "ng", "nw"],
                          data=[[1, 1, 1], [2, np.nan, 1]])
    with pytest.raises(ValueError, match="SATNUM 2"):
        PyscalFactory.create_pyscal_list(dframe, h=0.2)

    # Wateroilgas list:
    dframe = pd.DataFrame(
        columns=["SATNUM", "nw", "now", "ng", "nog"],
        data=[[1, 1, 1, 1, 1], [2, np.nan, 1, 2, 3]],
    )
    with pytest.raises(ValueError, match="SATNUM 2"):
        PyscalFactory.create_pyscal_list(dframe, h=0.2)

    # SCAL rec list:
    dframe = pd.DataFrame(
        columns=["SATNUM", "CASE", "nw", "now", "ng", "nog"],
        data=[
            [1, "low", 1, 1, 1, 1],
            [1, "base", 1, 1, 1, 1],
            [1, "high", 1, 1, 1, 1],
            [2, "low", np.nan, 1, 2, 3],
            [2, "base", 2, 1, 2, 3],
            [2, "high", 3, 1, 2, 3],
        ],
    )
    # The error should hint both to SATNUM and to low/base/high
    with pytest.raises(ValueError, match="SATNUM 2"):
        PyscalFactory.create_scal_recommendation_list(dframe, h=0.2)
    with pytest.raises(ValueError, match="Problem with low"):
        PyscalFactory.create_scal_recommendation_list(dframe, h=0.2)
Beispiel #20
0
def test_explicit_df():
    """Test some dataframes, check the error messages given"""

    dframe = pd.DataFrame(columns=["satnum"], data=[[1], [2]])
    with pytest.raises(ValueError):
        # SATNUM column must be upper case, or should we allow lowercase??
        relperm_data = PyscalFactory.load_relperm_df(dframe)

    dframe = pd.DataFrame(columns=["SATNUM"], data=[[0], [1]])
    with pytest.raises(ValueError):
        # SATNUM must start at 1.
        relperm_data = PyscalFactory.load_relperm_df(dframe)

    dframe = pd.DataFrame(columns=["SATNUM"], data=[[1], ["foo"]])
    with pytest.raises(ValueError):
        # SATNUM must contain only integers
        relperm_data = PyscalFactory.load_relperm_df(dframe)

    dframe = pd.DataFrame(columns=["SATNUM", "nw", "now"],
                          data=[[1.01, 1, 1], [2.01, 1, 1]])
    # This one will pass, as these can be converted to ints
    relperm_data = PyscalFactory.load_relperm_df(dframe)

    dframe = pd.DataFrame(columns=["SATNUM", "nw", "now"],
                          data=[[1.01, 1, 1], [1.3, 1, 1]])
    with pytest.raises(ValueError):
        # complains about non-uniqueness in SATNUM
        relperm_data = PyscalFactory.load_relperm_df(dframe)

    dframe = pd.DataFrame(columns=["SATNUM"], data=[[1], [2]])
    with pytest.raises(ValueError):
        # Not enough data
        relperm_data = PyscalFactory.load_relperm_df(dframe)

    # Minimal amount of data:
    dframe = pd.DataFrame(columns=["SATNUM", "Nw", "Now"], data=[[1, 2, 2]])
    relperm_data = PyscalFactory.load_relperm_df(dframe)
    p_list = PyscalFactory.create_pyscal_list(relperm_data, h=0.2)
    p_list.dump_family_1()
    with pytest.raises(ValueError):
        p_list.dump_family_2()

    # Case insensitive for parameters
    dframe = pd.DataFrame(columns=["SATNUM", "nw", "now"], data=[[1, 2, 2]])
    relperm_data = PyscalFactory.load_relperm_df(dframe)
    p_list = PyscalFactory.create_pyscal_list(relperm_data, h=0.2)
    p_list.dump_family_1()

    # Minimal wateroilgas
    dframe = pd.DataFrame(columns=["SATNUM", "Nw", "Now", "ng", "nOG"],
                          data=[[1, 2, 2, 2, 2]])
    relperm_data = PyscalFactory.load_relperm_df(dframe)
    p_list = PyscalFactory.create_pyscal_list(relperm_data, h=0.2)
    relperm_str = p_list.dump_family_1()
    assert "SWOF" in relperm_str
    assert "SGOF" in relperm_str
    assert "SLGOF" not in relperm_str
    assert "SOF3" not in relperm_str

    # Minimal wateroilgas with pc
    dframe = pd.DataFrame(
        columns=[
            "SATNUM",
            "swl",
            "Nw",
            "Now",
            "ng",
            "nOG",
            "a",
            "b",
            "poro_ref",
            "perm_ref",
            "drho",
        ],
        data=[[1, 0.1, 2, 2, 2, 2, 1.5, -0.5, 0.1, 100, 300]],
    )
    relperm_data = PyscalFactory.load_relperm_df(dframe)
    p_list = PyscalFactory.create_pyscal_list(relperm_data, h=0.2)
    relperm_str = p_list.dump_family_1()
    assert "SWOF" in relperm_str
    assert "Simplified" in relperm_str  # Bad practice, testing for stuff in comments
    assert "a=1.5" in relperm_str
Beispiel #21
0
def test_capillary_pressure():
    """Test that we recognize capillary pressure parametrizations"""
    dframe = pd.DataFrame(
        columns=[
            "SATNUM",
            "nw",
            "now",
            "swl",
            "a",
            "b",
            "PORO_reF",
            "PERM_ref",
            "drho",
        ],
        data=[[1, 1, 1, 0.05, 3.6, -3.5, 0.25, 15, 150]],
    )
    pyscal_list = PyscalFactory.create_pyscal_list(
        PyscalFactory.load_relperm_df(dframe))
    swof = pyscal_list.dump_family_1()
    assert "Simplified J-function" in swof
    assert "petrophysical" not in swof

    dframe = pd.DataFrame(
        columns=[
            "SATNUM",
            "nw",
            "now",
            "swl",
            "a_petro",
            "b_petro",
            "PORO_reF",
            "PERM_ref",
            "drho",
        ],
        data=[[1, 1, 1, 0.05, 3.6, -3.5, 0.25, 15, 150]],
    )
    pyscal_list = PyscalFactory.create_pyscal_list(
        PyscalFactory.load_relperm_df(dframe))
    swof = pyscal_list.dump_family_1()
    assert "Simplified J-function" in swof
    assert "petrophysical" in swof

    dframe = pd.DataFrame(
        columns=[
            "SATNUM",
            "nw",
            "now",
            "swl",
            "a",
            "b",
            "PORO",
            "PERM",
            "sigma_COStau",
        ],
        data=[[1, 1, 1, 0.05, 3.6, -3.5, 0.25, 15, 30]],
    )
    pyscal_list = PyscalFactory.create_pyscal_list(
        PyscalFactory.load_relperm_df(dframe))
    swof = pyscal_list.dump_family_1()
    assert "normalized J-function" in swof
    assert "sigma_costau" in swof
    assert "petrophysical" not in swof
def test_mock(tmpdir):
    """Mocked pyscal-generated input files.

    Note that this is using pyscal both for dumping to disk and
    parsing from disk, and is thus not representative for how flexible
    the code is for reading from include files not originating in pyscal.
    """
    tmpdir.chdir()
    columns = [
        "SATNUM",
        "Nw",
        "Now",
        "Ng",
        "Nog",
        "swl",
        "a",
        "b",
        "poro_ref",
        "perm_ref",
        "drho",
    ]
    dframe_pess = pd.DataFrame(
        columns=columns,
        data=[[1, 1, 1, 1, 1, 0.1, 2, -2, 0.25, 100, 150]],
    )
    dframe_base = pd.DataFrame(
        columns=columns,
        data=[[1, 2, 2, 2, 2, 0.1, 2, -2, 0.25, 200, 150]],
    )
    dframe_opt = pd.DataFrame(
        columns=columns,
        data=[[1, 3, 3, 3, 3, 0.1, 2, -2, 0.25, 300, 150]],
    )
    PyscalFactory.create_pyscal_list(dframe_pess).dump_family_1("pess.inc")
    PyscalFactory.create_pyscal_list(dframe_base).dump_family_1("base.inc")
    PyscalFactory.create_pyscal_list(dframe_opt).dump_family_1("opt.inc")

    config = {
        "base": ["base.inc"],
        "low": ["pess.inc"],
        "high": ["opt.inc"],
        "result_file": "outfile.inc",
        "interpolations": [{
            "param_w": -0.5,
            "param_g": 0.5
        }],
        "delta_s": 0.1,
    }

    interp_relperm.process_config(config)
    interp_relperm.process_config(config)

    outfile_df = satfunc.df(open("outfile.inc").read(), ntsfun=1)
    assert set(outfile_df["KEYWORD"].unique()) == {"SWOF", "SGOF"}
    assert outfile_df["SW"].sum() > 0
    assert outfile_df["SG"].sum() > 0
    assert outfile_df["KRW"].sum() > 0
    assert outfile_df["KROW"].sum() > 0
    assert outfile_df["KRG"].sum() > 0
    assert outfile_df["KROG"].sum() > 0
    assert outfile_df["PCOW"].sum() > 0
Beispiel #23
0
def test_fast():
    """Test fast mode for SCALrecommendation"""
    testdir = Path(__file__).absolute().parent

    scalrec_data = PyscalFactory.load_relperm_df(
        testdir / "data/scal-pc-input-example.xlsx")
    scalrec_list_fast = PyscalFactory.create_scal_recommendation_list(
        scalrec_data, fast=True)

    for item in scalrec_list_fast:
        assert item.fast
        assert item.low.fast
        assert item.base.fast
        assert item.high.fast

    wog_list_fast = scalrec_list_fast.interpolate(-0.5)
    for item in wog_list_fast:
        assert item.fast

    # WaterOilGas list
    dframe = pd.DataFrame(
        columns=["SATNUM", "nw", "now", "ng", "nog"],
        data=[
            [1, 2, 2, 2, 2],
            [2, 2, 2, 2, 2],
            [3, 2, 2, 2, 2],
        ],
    )
    relperm_data = PyscalFactory.load_relperm_df(dframe)
    p_list_fast = PyscalFactory.create_pyscal_list(relperm_data,
                                                   h=0.2,
                                                   fast=True)
    for item in p_list_fast:
        assert item.fast

    # GasOil list
    input_dframe = dframe[["SATNUM", "ng", "nog"]].copy()
    relperm_data = PyscalFactory.load_relperm_df(input_dframe)
    p_list_fast = PyscalFactory.create_pyscal_list(relperm_data,
                                                   h=0.2,
                                                   fast=True)
    for item in p_list_fast:
        assert item.fast

    # WaterOil list
    input_dframe = dframe[["SATNUM", "nw", "now"]].copy()
    relperm_data = PyscalFactory.load_relperm_df(input_dframe)
    p_list_fast = PyscalFactory.create_pyscal_list(relperm_data,
                                                   h=0.2,
                                                   fast=True)
    for item in p_list_fast:
        assert item.fast

    # GasWater list
    input_dframe = dframe[["SATNUM", "nw", "ng"]].copy()
    relperm_data = PyscalFactory.load_relperm_df(input_dframe)
    p_list_fast = PyscalFactory.create_pyscal_list(relperm_data,
                                                   h=0.2,
                                                   fast=True)
    for item in p_list_fast:
        assert item.fast

    # Testing with "fast" column in dataframe
    # Currently the choice is to only implement fast mode
    # as a global option. This column should do nothing now.
    # One could imagine it implemented
    # for individual SATNUM regions at a later stage
    dframe = pd.DataFrame(
        columns=["SATNUM", "nw", "now", "ng", "nog", "fast"],
        data=[
            [1, 2, 2, 2, 2, True],
            [2, 2, 2, 2, 2, False],
            [3, 2, 2, 2, 2, True],
        ],
    )
    relperm_data = PyscalFactory.load_relperm_df(dframe)
    assert "fast" in relperm_data
    p_list = PyscalFactory.create_pyscal_list(relperm_data, h=0.2)
    for item in p_list:
        assert not item.fast
def test_mock_two_satnums(tmpdir):
    """Mocked pyscal-generated input files.

    Note that this is using pyscal both for dumping to disk and
    parsing from disk, and is thus not representative for how flexible
    the code is for reading from include files not originating in pyscal.
    """
    # pylint: disable=no-value-for-parameter
    tmpdir.chdir()
    columns = [
        "SATNUM",
        "Nw",
        "Now",
        "Ng",
        "Nog",
        "swl",
        "a",
        "b",
        "poro_ref",
        "perm_ref",
        "drho",
    ]
    dframe_pess = pd.DataFrame(
        columns=columns,
        data=[
            [1, 1, 1, 1, 1, 0.1, 2, -2, 0.25, 100, 150],
            [1, 1, 1, 1, 1, 0.1, 2, -2, 0.25, 100, 150],
        ],
    )
    dframe_base = pd.DataFrame(
        columns=columns,
        data=[
            [1, 2, 2, 2, 2, 0.1, 2, -2, 0.25, 200, 150],
            [1, 2, 2, 2, 2, 0.1, 2, -2, 0.25, 200, 150],
        ],
    )
    dframe_opt = pd.DataFrame(
        columns=columns,
        data=[
            [1, 3, 3, 3, 3, 0.1, 2, -2, 0.25, 300, 150],
            [1, 3, 3, 3, 3, 0.1, 2, -2, 0.25, 300, 150],
        ],
    )
    PyscalFactory.create_pyscal_list(dframe_pess).dump_family_1("pess.inc")
    PyscalFactory.create_pyscal_list(dframe_base).dump_family_1("base.inc")
    PyscalFactory.create_pyscal_list(dframe_opt).dump_family_1("opt.inc")

    config = {
        "base": ["base.inc"],
        "low": ["pess.inc"],
        "high": ["opt.inc"],
        "result_file": "outfile.inc",
        "interpolations": [{
            "param_w": -0.5,
            "param_g": 0.5
        }],
        "delta_s": 0.1,
    }

    interp_relperm.process_config(config)
    outfile_str = open("outfile.inc").read()

    # Assert things about the comments emitted by pyscal when interpolating:
    # This is used as a proxy for asserting that interpolation parameters
    # are used for the correct satnums
    assert outfile_str.find("SCAL recommendation interpolation to 0.5")
    assert outfile_str.find("SCAL recommendation interpolation to -0.5")
    # SWOF comes before SGOF:
    assert outfile_str.find("to -0.5") < outfile_str.find("to 0.5")
    outfile_df = satfunc.df(outfile_str, ntsfun=2)
    assert set(outfile_df["KEYWORD"].unique()) == {"SWOF", "SGOF"}
    assert set(outfile_df["SATNUM"].unique()) == {1, 2}

    config = {
        "base": ["base.inc"],
        "low": ["pess.inc"],
        "high": ["opt.inc"],
        "result_file":
        "outfile.inc",
        "interpolations": [
            {
                "tables": [1],
                "param_w": -0.9,
                "param_g": -0.5
            },
            {
                "tables": [2],
                "param_w": 0.5,
                "param_g": 0.8
            },
        ],
        "delta_s":
        0.1,
    }
    interp_relperm.process_config(config)
    outfile_str = open("outfile.inc").read()
    assert outfile_str.find("to -0.9") < outfile_str.find("to 0.5")
    assert outfile_str.find("to 0.5") < outfile_str.find("to -0.5")
    assert outfile_str.find("to 0.5") < outfile_str.find("to 0.8")

    config = {
        "base": ["base.inc"],
        "low": ["pess.inc"],
        "high": ["opt.inc"],
        "result_file":
        "outfile.inc",
        "interpolations": [
            # This is a user error, the latter will override the first
            {
                "param_w": -0.9,
                "param_g": -0.5
            },
            {
                "param_w": 0.5,
                "param_g": 0.8
            },
        ],
        "delta_s":
        0.1,
    }
    interp_relperm.process_config(config)
    outfile_str = open("outfile.inc").read()
    assert "interpolation to -0.9" not in outfile_str
    assert "interpolation to 0.8" in outfile_str

    config = {
        "base": ["base.inc"],
        "low": ["pess.inc"],
        "high": ["opt.inc"],
        "result_file":
        "outfile.inc",
        "interpolations": [
            # Here the user intentionally overwrites the first:
            {
                "param_w": -0.9,
                "param_g": -0.5
            },
            {
                "tables": [],
                "param_w": 0.5,
                "param_g": 0.8
            },
        ],
        "delta_s":
        0.1,
    }
    interp_relperm.process_config(config)
    outfile_str = open("outfile.inc").read()
    assert "interpolation to -0.9" not in outfile_str
    assert "interpolation to 0.8" in outfile_str
Beispiel #25
0
def test_case_aliasing():
    """Test that we can use aliases for the CASE column
    in SCAL recommendations"""
    dframe = pd.DataFrame(
        columns=["SATNUM", "CASE", "Nw", "Now", "Ng", "Nog"],
        data=[
            [1, "pess", 2, 2, 1, 1],
            [1, "base", 3, 1, 1, 1],
            [1, "opt", 3, 1, 1, 1],
        ],
    )
    relperm_data = PyscalFactory.load_relperm_df(dframe)
    PyscalFactory.create_scal_recommendation_list(relperm_data, h=0.2).interpolate(-0.4)
    dframe = pd.DataFrame(
        columns=["SATNUM", "CASE", "Nw", "Now", "Ng", "Nog"],
        data=[
            [1, "pessimistic", 2, 2, 1, 1],
            [1, "base", 3, 1, 1, 1],
            [1, "optiMISTIc", 3, 1, 1, 1],
        ],
    )
    relperm_data = PyscalFactory.load_relperm_df(dframe)
    PyscalFactory.create_scal_recommendation_list(relperm_data, h=0.2).interpolate(-0.4)

    with pytest.raises(ValueError):
        PyscalFactory.load_relperm_df(
            pd.DataFrame(
                columns=["SATNUM", "CASE", "Nw", "Now", "Ng", "Nog"],
                data=[
                    [1, "FOOBAR", 2, 2, 1, 1],
                    [1, "base", 3, 1, 1, 1],
                    [1, "optIMIstiC", 3, 1, 1, 1],
                ],
            )
        )

    # Ambigous data:
    with pytest.raises(ValueError):
        amb = PyscalFactory.load_relperm_df(
            pd.DataFrame(
                columns=["SATNUM", "CASE", "Nw", "Now", "Ng", "Nog"],
                data=[
                    [1, "low", 2, 2, 1, 1],
                    [1, "pess", 5, 5, 5, 5],
                    [1, "base", 3, 1, 1, 1],
                    [1, "optIMIstiC", 3, 1, 1, 1],
                ],
            )
        )
        PyscalFactory.create_scal_recommendation_list(amb)

    # Missing a case
    with pytest.raises(ValueError):
        PyscalFactory.load_relperm_df(
            pd.DataFrame(
                columns=["SATNUM", "CASE", "Nw", "Now", "Ng", "Nog"],
                data=[[1, "base", 3, 1, 1, 1], [1, "optIMIstiC", 3, 1, 1, 1]],
            )
        )
    # Missing a case
    with pytest.raises(ValueError):
        PyscalFactory.load_relperm_df(
            pd.DataFrame(
                columns=["SATNUM", "CASE", "Nw", "Now", "Ng", "Nog"],
                data=[[1, "base", 3, 1, 1, 1]],
            )
        )
Beispiel #26
0
def test_load_scalrec_tags():
    """Test tag handling for a SCAL recommendation with SATNUM range"""
    if "__file__" in globals():
        # Easen up copying test code into interactive sessions
        testdir = os.path.dirname(os.path.abspath(__file__))
    else:
        testdir = os.path.abspath(".")

    scalrec_data = PyscalFactory.load_relperm_df(
        testdir + "/data/scal-pc-input-example.xlsx"
    )
    scalrec_list = PyscalFactory.create_scal_recommendation_list(scalrec_data)

    wog_list = scalrec_list.interpolate(-1)

    swof = wog_list.SWOF()
    assert swof.count("SCAL recommendation interpolation to -1") == 3
    assert swof.count("SATNUM 1") == 1
    assert swof.count("SATNUM") == 3

    sof3 = wog_list.SOF3()
    assert sof3.count("SCAL recommendation interpolation to -1") == 3
    assert sof3.count("SATNUM 1") == 1
    assert sof3.count("SATNUM") == 3

    assert (
        scalrec_list.interpolate(1)
        .SWOF()
        .count("SCAL recommendation interpolation to 1\n")
        == 3
    )
    assert (
        scalrec_list.interpolate(0)
        .SWOF()
        .count("SCAL recommendation interpolation to 0\n")
        == 3
    )
    assert (
        scalrec_list.interpolate(-0.444)
        .SWOF()
        .count("SCAL recommendation interpolation to -0.444\n")
        == 3
    )

    # Give each row in the SCAL recommendation its own tag (low, base, high
    # explicitly in each tag, someone will do that)
    scalrec_data["TAG"] = [
        "SAT1 low",
        "SAT1 base",
        "SAT1 high",
        "SAT2 pess",
        "SAT2 base",
        "SAT2 opt",
        "SAT3 pessimistic",
        "SAT3 base case",
        "SAT3 optimistic",
    ]
    scalrec_list2 = PyscalFactory.create_scal_recommendation_list(scalrec_data)
    swof = scalrec_list2.interpolate(-0.5, h=0.2).SWOF()
    assert swof.count("SCAL recommendation") == 3
    for tag in scalrec_data["TAG"]:
        assert swof.count(tag) == 1
Beispiel #27
0
def test_swl_from_height():
    """Test that can initialize swl from capillary pressure height"""
    df_columns = [
        "SATNUM",
        "nw",
        "now",
        "swl",
        "swlheight",
        "swirr",
        "a",
        "b",
        "PORO_reF",
        "PERM_ref",
        "drho",
    ]
    dframe = pd.DataFrame(
        columns=df_columns,
        data=[[1, 1, 1, np.nan, 300, 0.00, 3.6, -3.5, 0.25, 15, 150]],
    )
    pyscal_list = PyscalFactory.create_pyscal_list(
        PyscalFactory.load_relperm_df(dframe))

    # Mix swlheight init and direct swl-init:
    assert np.isclose(pyscal_list[1].swl, 0.157461)
    dframe = pd.DataFrame(
        columns=df_columns,
        data=[
            [1, 1, 1, np.nan, 300, 0.00, 3.6, -3.5, 0.25, 15, 150],
            [2, 1, 1, 0.3, np.nan, 0.00, 3.6, -3.5, 0.25, 15, 150],
        ],
    )
    pyscal_list = PyscalFactory.create_pyscal_list(
        PyscalFactory.load_relperm_df(dframe))
    assert np.isclose(pyscal_list[1].swl, 0.157461)
    assert np.isclose(pyscal_list[2].swl, 0.3)

    # Ambiguous, swl and swlheight both supplied:
    dframe = pd.DataFrame(
        columns=df_columns,
        data=[[1, 1, 1, 0.3, 300, 0.00, 3.6, -3.5, 0.25, 15, 150]],
    )
    with pytest.raises(ValueError):
        PyscalFactory.create_pyscal_list(PyscalFactory.load_relperm_df(dframe))

    # WaterOilGas (gasoil is also dependant on the computed swl)
    df_wog_columns = [
        "SATNUM",
        "nw",
        "now",
        "ng",
        "nog",
        "swlheight",
        "swirr",
        "a",
        "b",
        "PORO_reF",
        "PERM_ref",
        "drho",
    ]
    dframe = pd.DataFrame(
        columns=df_wog_columns,
        data=[[1, 1, 1, 2, 2, 300, 0.00, 3.6, -3.5, 0.25, 15, 150]],
    )
    pyscal_list = PyscalFactory.create_pyscal_list(
        PyscalFactory.load_relperm_df(dframe))
    assert np.isclose(pyscal_list[1].wateroil.swl, 0.157461)
    assert np.isclose(pyscal_list[1].gasoil.swl, 0.157461)

    # Test for GasWater:
    df_gw_columns = [
        "SATNUM",
        "nw",
        "ng",
        "swlheight",
        "swirr",
        "a",
        "b",
        "PORO_REF",
        "PERM_REF",
        "drho",
    ]
    dframe = pd.DataFrame(
        columns=df_gw_columns,
        data=[[1, 2, 3, 300, 0.00, 3.6, -3.5, 0.25, 15, 150]],
    )
    pyscal_list = PyscalFactory.create_pyscal_list(
        PyscalFactory.load_relperm_df(dframe))
    assert np.isclose(pyscal_list[1].wateroil.swl, 0.157461)
    assert np.isclose(pyscal_list[1].swl, 0.157461)
def test_SCAL_interpolation():
    """Demonstration of interpolation between LET curves, 2x2 subplot"""
    matplotlib.style.use("ggplot")

    rec = PyscalFactory.create_scal_recommendation(
        {
            "low": LOW_SAMPLE_LET,
            "base": BASE_SAMPLE_LET,
            "high": HIGH_SAMPLE_LET
        },
        "FOO",
        h=0.001,
    )
    _, ((ax1, ax2), (ax3, ax4)) = pyplot.subplots(2, 2)

    # Choosing logarithmic spaced interpolation parameters
    # is not the same as interpolating in log(kr)-space
    # check the effect by setting
    #  for t in -2 + np.logspace(1e-5,1e-1,15):
    # and
    #  for t in -1 + np.logspace(1e-5,1e-1,15)
    # in the loops below. Curves get clustered to the bottom
    # in both linear and log(kr) spaces, but there
    # still might be some other distribution for the interpolants
    # that yields something that spans nicely both the linear and the
    # logarithmic kr space (?)

    for tparam in np.arange(-1, 0, 0.2):
        interp = rec.interpolate(tparam, h=0.001)
        interp.wateroil.plotkrwkrow(ax1, "r")
        interp.wateroil.plotkrwkrow(ax2, "r")

    for tparam in np.arange(0, 1, 0.2):
        interp = rec.interpolate(tparam, h=0.001)
        interp.wateroil.plotkrwkrow(ax1, "g")
        interp.wateroil.plotkrwkrow(ax2, "g")

    rec.low.wateroil.plotkrwkrow(ax1, linewidth=2, linestyle=":")
    rec.base.wateroil.plotkrwkrow(ax1, linewidth=2)
    rec.high.wateroil.plotkrwkrow(ax1, linewidth=2, linestyle="--")
    rec.low.wateroil.plotkrwkrow(ax2, linewidth=2, linestyle=":")
    rec.base.wateroil.plotkrwkrow(ax2, linewidth=2)
    rec.high.wateroil.plotkrwkrow(ax2, linewidth=2, linestyle="--")
    ax2.set_yscale("log")
    ax2.set_ylim([1e-10, 1])
    ax1.set_xlabel("")
    ax2.set_xlabel("")
    ax1.set_title("Water-oil, low, base, high and interpolants", fontsize=10)
    ax2.set_title("Water-oil, low, base, high and interpolants", fontsize=10)

    for tparam in np.arange(-1, 0, 0.2):
        interp = rec.interpolate(tparam, h=0.001)
        interp.gasoil.plotkrgkrog(ax3, "r")
        interp.gasoil.plotkrgkrog(ax4, "r")

    for tparam in np.arange(0, 1, 0.2):
        interp = rec.interpolate(tparam, h=0.001)
        interp.gasoil.plotkrgkrog(ax3, "g")
        interp.gasoil.plotkrgkrog(ax4, "g")

    rec.low.gasoil.plotkrgkrog(ax3, linewidth=2, linestyle=":")
    rec.base.gasoil.plotkrgkrog(ax3, linewidth=2)
    rec.high.gasoil.plotkrgkrog(ax3, linewidth=2, linestyle="--")
    rec.low.gasoil.plotkrgkrog(ax4, linewidth=2, linestyle=":")
    rec.base.gasoil.plotkrgkrog(ax4, linewidth=2)
    rec.high.gasoil.plotkrgkrog(ax4, linewidth=2, linestyle="--")
    ax3.set_title("Gas-oil, low, base, high and interpolants", fontsize=10)
    ax4.set_title("Gas-oil, low, base, high and interpolants", fontsize=10)
    ax4.set_yscale("log")
    ax4.set_ylim([1e-05, 1])
    ax3.set_xlabel("")
    ax4.set_xlabel("")
    pyplot.subplots_adjust(hspace=0.3)
    print("--  Check:")
    print("--   * Red curves are between dotted and solid blue line")
    print("--   * Green curves are between solid blue and dashed")
    print("[Close windows to continue tests]")
    pyplot.show()
Beispiel #29
0
def test_df():
    """Test dataframe dumps"""
    testdir = Path(__file__).absolute().parent

    scalrec_data = PyscalFactory.load_relperm_df(
        testdir / "data/scal-pc-input-example.xlsx")
    scalrec_list = PyscalFactory.create_scal_recommendation_list(scalrec_data)
    wog_list = scalrec_list.interpolate(-0.3)

    # Test dataframe dumps:
    dframe = scalrec_list.df()
    assert "SG" in dframe
    assert "KRG" in dframe
    assert "KROG" in dframe
    assert "PCOW" in dframe
    if "PCOG" in dframe:
        # Allow PCOG to be included later.
        assert dframe["PCOG"].sum() == 0
    assert "KRW" in dframe
    assert "KROW" in dframe
    assert "SATNUM" in dframe
    assert dframe["SATNUM"].min() == 1
    assert len(dframe["SATNUM"].unique()) == len(scalrec_list)
    assert set(dframe["CASE"]) == set(["pess", "base", "opt"])
    assert dframe["SATNUM"].max() == len(scalrec_list)
    if HAVE_ECL2DF:
        # Test using ecl2df to do the include file printing. First we need to
        # massage the dataframe into what ecl2df can handle:
        base_df_swof = (dframe.set_index("CASE").loc["base"][[
            "SW", "KRW", "KROW", "PCOW", "SATNUM"
        ]].assign(KEYWORD="SWOF").dropna().reset_index(drop=True))
        ecl_inc = ecl2df.satfunc.df2ecl(base_df_swof)
        dframe_from_inc = ecl2df.satfunc.df(ecl_inc)
        pd.testing.assert_frame_equal(base_df_swof, dframe_from_inc)

        # Test also SGOF
        base_df_sgof = (dframe.set_index("CASE").loc["base"][[
            "SG", "KRG", "KROG", "SATNUM"
        ]].assign(KEYWORD="SGOF", PCOG=0.0).dropna().reset_index(drop=True))
        ecl_inc = ecl2df.satfunc.df2ecl(base_df_sgof)
        dframe_from_inc = ecl2df.satfunc.df(ecl_inc)
        pd.testing.assert_frame_equal(base_df_sgof,
                                      dframe_from_inc,
                                      check_like=True)

    # WaterOilGasList:
    dframe = wog_list.df()
    assert "SG" in dframe
    assert "KRG" in dframe
    assert "KROG" in dframe
    assert "PCOW" in dframe
    assert "PCOG" in dframe  # This gets included through interpolation
    assert "KRW" in dframe
    assert "KROW" in dframe
    assert "SATNUM" in dframe
    assert dframe["SATNUM"].min() == 1
    assert len(dframe["SATNUM"].unique()) == len(wog_list)
    assert "CASE" not in dframe
    assert dframe["SATNUM"].max() == len(wog_list)

    # WaterOil list
    input_dframe = pd.DataFrame(columns=["SATNUM", "Nw", "Now"],
                                data=[[1, 2, 2]])
    relperm_data = PyscalFactory.load_relperm_df(input_dframe)
    p_list = PyscalFactory.create_pyscal_list(relperm_data, h=0.2)
    dframe = p_list.df()
    assert "SW" in dframe
    assert "KRW" in dframe
    assert "KROW" in dframe
    assert "PCOW" not in dframe  # to be interpreted as zero
    assert "SATNUM" in dframe
    assert len(dframe.columns) == 4
    assert not dframe.empty

    # GasOil list
    input_dframe = pd.DataFrame(columns=["SATNUM", "Ng", "Nog"],
                                data=[[1, 2, 2]])
    relperm_data = PyscalFactory.load_relperm_df(input_dframe)
    p_list = PyscalFactory.create_pyscal_list(relperm_data, h=0.2)
    dframe = p_list.df()
    assert "SG" in dframe
    assert "KRG" in dframe
    assert "KROG" in dframe
    assert "PCOG" not in dframe  # to be interpreted as zero
    assert "SATNUM" in dframe
    assert len(dframe.columns) == 4
    assert not dframe.empty
Beispiel #30
0
def test_mock_two_satnums_via_files(tmpdir):
    """Mocked pyscal-generated input files.

    Note that this is using pyscal both for dumping to disk and
    parsing from disk, and is thus not representative for how flexible
    the code is for reading from include files not originating in pyscal.
    """
    # pylint: disable=no-value-for-parameter
    tmpdir.chdir()
    PyscalFactory.create_pyscal_list(
        TWO_SATNUM_PYSCAL_MOCK.loc["low"]).dump_family_1("pess.inc")
    PyscalFactory.create_pyscal_list(
        TWO_SATNUM_PYSCAL_MOCK.loc["base"]).dump_family_1("base.inc")
    PyscalFactory.create_pyscal_list(
        TWO_SATNUM_PYSCAL_MOCK.loc["high"]).dump_family_1("opt.inc")

    config = {
        "base": ["base.inc"],
        "low": ["pess.inc"],
        "high": ["opt.inc"],
        "result_file": "outfile.inc",
        "interpolations": [{
            "param_w": -0.5,
            "param_g": 0.5
        }],
        "delta_s": 0.1,
    }

    interp_relperm.process_config(config)
    outfile_str = Path("outfile.inc").read_text()

    # Assert things about the comments emitted by pyscal when interpolating:
    # This is used as a proxy for asserting that interpolation parameters
    # are used for the correct satnums
    assert outfile_str.find("SCAL recommendation interpolation to 0.5")
    assert outfile_str.find("SCAL recommendation interpolation to -0.5")
    # SWOF comes before SGOF:
    assert outfile_str.find("to -0.5") < outfile_str.find("to 0.5")
    outfile_df = satfunc.df(outfile_str, ntsfun=2)
    assert set(outfile_df["KEYWORD"].unique()) == {"SWOF", "SGOF"}
    assert set(outfile_df["SATNUM"].unique()) == {1, 2}

    config = {
        "base": ["base.inc"],
        "low": ["pess.inc"],
        "high": ["opt.inc"],
        "result_file":
        "outfile.inc",
        "interpolations": [
            {
                "tables": [1],
                "param_w": -0.9,
                "param_g": -0.5
            },
            {
                "tables": [2],
                "param_w": 0.5,
                "param_g": 0.8
            },
        ],
        "delta_s":
        0.1,
    }
    interp_relperm.process_config(config)
    outfile_str = open("outfile.inc").read()
    assert outfile_str.find("to -0.9") < outfile_str.find("to 0.5")
    assert outfile_str.find("to 0.5") < outfile_str.find("to -0.5")
    assert outfile_str.find("to 0.5") < outfile_str.find("to 0.8")

    config = {
        "base": ["base.inc"],
        "low": ["pess.inc"],
        "high": ["opt.inc"],
        "result_file":
        "outfile.inc",
        "interpolations": [
            # This is a user error, the latter will override the first
            {
                "param_w": -0.9,
                "param_g": -0.5
            },
            {
                "param_w": 0.5,
                "param_g": 0.8
            },
        ],
        "delta_s":
        0.1,
    }
    interp_relperm.process_config(config)
    outfile_str = open("outfile.inc").read()
    assert "interpolation to -0.9" not in outfile_str
    assert "interpolation to 0.8" in outfile_str

    config = {
        "base": ["base.inc"],
        "low": ["pess.inc"],
        "high": ["opt.inc"],
        "result_file":
        "outfile.inc",
        "interpolations": [
            # Here the user intentionally overwrites the first:
            {
                "param_w": -0.9,
                "param_g": -0.5
            },
            {
                "tables": [],
                "param_w": 0.5,
                "param_g": 0.8
            },
        ],
        "delta_s":
        0.1,
    }
    interp_relperm.process_config(config)
    outfile_str = open("outfile.inc").read()
    assert "interpolation to -0.9" not in outfile_str
    assert "interpolation to 0.8" in outfile_str