Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Eclipse relperm family 2 to df output #355

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
131 changes: 86 additions & 45 deletions pyscal/pyscallist.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,16 +89,19 @@ def df(self) -> pd.DataFrame:
will contain the strings 'pess', 'base' and 'opt' (independent of
any alias name potentially used in an input xlsx/csv)
"""
# Names of dataframe columns in wateroil/gasoil.table:
# Names of dataframe columns in wateroil/gasoil.table, SOF3 and SLGOF:
wateroil_pyscal_cols = {"SW", "KRW", "KROW", "PC"}
gasoil_pyscal_cols = {"SG", "KRG", "KROG", "PC"}
sof3_cols = {"SO", "KROW", "KROG"}
slgof_cols = {"SL", "KRG", "KROG", "PC"}

# Renamers applied to the returned dataframe:
gasoil_col_renamer = {"SG": "SG", "KRG": "KRG", "KROG": "KROG", "PC": "PCOG"}
wateroil_col_renamer = {"SW": "SW", "KRW": "KRW", "KROW": "KROW", "PC": "PCOW"}
slgof_col_renamer = {"SL": "SL", "KRG": "KRG", "KROG": "KROG", "PC": "PCOG"}

# Sort order for rows in returned dataframe:
sort_candidates = ["SATNUM", "CASE", "KEYWORD", "SW", "SG", "SL"]
sort_candidates = ["SATNUM", "CASE", "KEYWORD", "SW", "SG", "SL", "SO"]

df_list = []
if self.pyscaltype == WaterOilGas:
Expand All @@ -122,55 +125,93 @@ def df(self) -> pd.DataFrame:
.assign(SATNUM=satnum + 1)
.rename(wateroil_col_renamer, axis="columns")
)
df_list.append(
wateroilgas.sof3_df()[sof3_cols].assign(SATNUM=satnum + 1)
)
df_list.append(
wateroilgas.gasoil.slgof_df()[gasoil_cols]
.assign(SATNUM=satnum + 1)
.rename(gasoil_col_renamer, axis="columns")
)
elif self.pyscaltype == SCALrecommendation:
for (satnum, scalrec) in enumerate(self.pyscal_list):
assert isinstance(scalrec, SCALrecommendation)
assert scalrec.low is not None
assert scalrec.base is not None
assert scalrec.high is not None
assert scalrec.low.wateroil is not None
assert scalrec.low.gasoil is not None
assert scalrec.base.wateroil is not None
assert scalrec.base.gasoil is not None
assert scalrec.high.wateroil is not None
assert scalrec.high.gasoil is not None
gasoil_cols = set(scalrec.base.gasoil.table.columns).intersection(
gasoil_pyscal_cols
)
wateroil_cols = set(scalrec.base.wateroil.table.columns).intersection(
wateroil_pyscal_cols
)
df_list.append(
scalrec.low.gasoil.table[gasoil_cols]
.assign(SATNUM=satnum + 1, CASE="pess")
.rename(gasoil_col_renamer, axis="columns")
)
df_list.append(
scalrec.base.gasoil.table[gasoil_cols]
.assign(SATNUM=satnum + 1, CASE="base")
.rename(gasoil_col_renamer, axis="columns")
)
df_list.append(
scalrec.high.gasoil.table[gasoil_cols]
.assign(SATNUM=satnum + 1, CASE="opt")
.rename(gasoil_col_renamer, axis="columns")
)

df_list.append(
scalrec.low.wateroil.table[wateroil_cols]
.assign(SATNUM=satnum + 1, CASE="pess")
.rename(wateroil_col_renamer, axis="columns")
)
df_list.append(
scalrec.base.wateroil.table[wateroil_cols]
.assign(SATNUM=satnum + 1, CASE="base")
.rename(wateroil_col_renamer, axis="columns")
)
df_list.append(
scalrec.high.wateroil.table[wateroil_cols]
.assign(SATNUM=satnum + 1, CASE="opt")
.rename(wateroil_col_renamer, axis="columns")
)
if scalrec.type == WaterOilGas:
assert scalrec.low.wateroil is not None
assert scalrec.low.gasoil is not None
assert scalrec.base.wateroil is not None
assert scalrec.base.gasoil is not None
assert scalrec.high.wateroil is not None
assert scalrec.high.gasoil is not None
gasoil_cols = set(scalrec.base.gasoil.table.columns).intersection(
gasoil_pyscal_cols
)
wateroil_cols = set(
scalrec.base.wateroil.table.columns
).intersection(wateroil_pyscal_cols)
df_list.append(
scalrec.low.gasoil.table[gasoil_cols]
.assign(SATNUM=satnum + 1, CASE="pess")
.rename(gasoil_col_renamer, axis="columns")
)
df_list.append(
scalrec.base.gasoil.table[gasoil_cols]
.assign(SATNUM=satnum + 1, CASE="base")
.rename(gasoil_col_renamer, axis="columns")
)
df_list.append(
scalrec.high.gasoil.table[gasoil_cols]
.assign(SATNUM=satnum + 1, CASE="opt")
.rename(gasoil_col_renamer, axis="columns")
)
df_list.append(
scalrec.low.wateroil.table[wateroil_cols]
.assign(SATNUM=satnum + 1, CASE="pess")
.rename(wateroil_col_renamer, axis="columns")
)
df_list.append(
scalrec.base.wateroil.table[wateroil_cols]
.assign(SATNUM=satnum + 1, CASE="base")
.rename(wateroil_col_renamer, axis="columns")
)
df_list.append(
scalrec.high.wateroil.table[wateroil_cols]
.assign(SATNUM=satnum + 1, CASE="opt")
.rename(wateroil_col_renamer, axis="columns")
)
df_list.append(
scalrec.low.sof3_df()[sof3_cols].assign(
SATNUM=satnum + 1, CASE="pess"
)
)
df_list.append(
scalrec.base.sof3_df()[sof3_cols].assign(
SATNUM=satnum + 1, CASE="base"
)
)
df_list.append(
scalrec.low.sof3_df()[sof3_cols].assign(
SATNUM=satnum + 1, CASE="opt"
)
)
df_list.append(
scalrec.low.gasoil.slgof_df()[slgof_cols]
.assign(SATNUM=satnum + 1, CASE="pess")
.rename(slgof_col_renamer, axis="columns")
)
df_list.append(
scalrec.base.gasoil.slgof_df()[slgof_cols]
.assign(SATNUM=satnum + 1, CASE="base")
.rename(slgof_col_renamer, axis="columns")
)
df_list.append(
scalrec.high.gasoil.slgof_df()[slgof_cols]
.assign(SATNUM=satnum + 1, CASE="opt")
.rename(slgof_col_renamer, axis="columns")
)
elif self.pyscaltype == WaterOil:
for (satnum, wateroil) in enumerate(self.pyscal_list):
assert isinstance(wateroil, WaterOil)
Expand Down
2 changes: 1 addition & 1 deletion pyscal/scalrecommendation.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@


class SCALrecommendation(object):
"""A SCAL recommendation consists of three OilWaterGas objects,
"""A SCAL recommendation consists of three WaterOilGas objects,
tagged low, base and high.

This container exists in order to to interpolation from -1 (low),
Expand Down
77 changes: 46 additions & 31 deletions pyscal/wateroilgas.py
Original file line number Diff line number Diff line change
Expand Up @@ -144,37 +144,7 @@ def SOF3(self, header: bool = True, dataincommentrow: bool = True) -> str:
):
logger.error("Both WaterOil and GasOil krow/krog is needed for SOF3")
return ""
self.threephaseconsistency()

# Copy of the wateroil data:
table = pd.DataFrame(self.wateroil.table[["SW", "KROW"]])
table["SO"] = 1 - table["SW"]

# Copy of the gasoil data:
gastable = pd.DataFrame(self.gasoil.table[["SG", "KROG"]])
gastable["SO"] = 1 - gastable["SG"] - self.wateroil.swl

# Merge WaterOil and GasOil on oil saturation, interpolate for
# missing data (potentially different sg- and sw-grids)
sof3table = (
pd.concat([table, gastable], sort=True)
.set_index("SO")
.sort_index()
.interpolate(method="slinear")
.fillna(method="ffill")
.fillna(method="bfill")
.reset_index()
)
sof3table["soint"] = list(
map(int, list(map(round, sof3table["SO"] * SWINTEGERS)))
)
sof3table.drop_duplicates("soint", inplace=True)

# The 'so' column has been calculated from floating point numbers
# and the zero value easily becomes a negative zero, circumvent this:
zerorow = np.isclose(sof3table["SO"], 0.0)
sof3table.loc[zerorow, "SO"] = abs(sof3table.loc[zerorow, "SO"])

sof3table = self.sof3_df()
string = ""
if header:
string += "SOF3\n"
Expand Down Expand Up @@ -298,3 +268,48 @@ def threephaseconsistency(self) -> bool:
# swl=0.45, (1-swl) = 0.55

return wog_is_ok

def sof3_df(self) -> pd.DataFrame:
"""Return a SOF3 DataFrame, combining data from the wateroil and
gasoil objects.

So - the oil saturation ranges from 0 to 1-swl. The saturation points
from the WaterOil object is used to generate these
"""
if (self.wateroil is None or self.gasoil is None) or (
"KROW" not in self.wateroil.table or "KROG" not in self.gasoil.table
):
logger.error("Both WaterOil and GasOil krow/krog is needed for SOF3")
return pd.DataFrame()
self.threephaseconsistency()

# Copy of the wateroil data:
table = pd.DataFrame(self.wateroil.table[["SW", "KROW"]])
table["SO"] = 1 - table["SW"]

# Copy of the gasoil data:
gastable = pd.DataFrame(self.gasoil.table[["SG", "KROG"]])
gastable["SO"] = 1 - gastable["SG"] - self.wateroil.swl

# Merge WaterOil and GasOil on oil saturation, interpolate for
# missing data (potentially different sg- and sw-grids)
sof3table = (
pd.concat([table, gastable], sort=True)
.set_index("SO")
.sort_index()
.interpolate(method="slinear")
.fillna(method="ffill")
.fillna(method="bfill")
.reset_index()
)
sof3table["soint"] = list(
map(int, list(map(round, sof3table["SO"] * SWINTEGERS)))
)
sof3table.drop_duplicates("soint", inplace=True)

# The 'so' column has been calculated from floating point numbers
# and the zero value easily becomes a negative zero, circumvent this:
zerorow = np.isclose(sof3table["SO"], 0.0)
sof3table.loc[zerorow, "SO"] = abs(sof3table.loc[zerorow, "SO"])

return sof3table