satfunc
satfunc will extract saturation functions from .DATA files or from
include files, these are the keywords SWOF
, SGOF
,
SGWFN
, SWFN
, SOF2
, SGFN
, SOF3
and SLGOF
.
The data obtained from one invocation of the satfunc module will be put in one
dataframe, where data from different keywords are separated by the KEYWORD
column.
from res2df import satfunc, ResdataFiles
resdatafiles = ResdataFiles('MYDATADECK.DATA')
dframe = satfunc.df(resdatafiles)
SW |
KRW |
KROW |
PCOW |
SATNUM |
KEYWORD |
SG |
KRG |
KROG |
PCOG |
---|---|---|---|---|---|---|---|---|---|
0.32 |
0.0 |
1.0 |
165.728151841 |
1 |
SWOF |
||||
0.3374 |
1.676119e-08 |
0.9680216 |
153.074777675 |
1 |
SWOF |
||||
0.3548 |
4.795631e-07 |
0.9119928 |
141.953412741 |
1 |
SWOF |
||||
0.3722 |
3.451875e-06 |
0.8430636 |
132.116390967 |
1 |
SWOF |
||||
0.3896 |
1.412955e-05 |
0.7672163 |
123.365246941 |
1 |
SWOF |
||||
0.98 |
0.92 |
0.0 |
30.9230370781 |
1 |
SWOF |
||||
1.0 |
1.0 |
0.0 |
30.0 |
1 |
SWOF |
||||
1 |
SGOF |
0.0 |
0.0 |
1.0 |
0.0 |
||||
1 |
SGOF |
0.0192 |
0.001220697 |
0.8731062 |
0.0 |
||||
1 |
SGOF |
0.0384 |
0.004073989 |
0.7505835 |
0.0 |
||||
1 |
SGOF |
0.6144 |
0.8307268 |
2.713968e-07 |
0.0 |
||||
1 |
SGOF |
0.64 |
0.87 |
0.0 |
0.0 |
||||
1 |
SGOF |
0.6533333 |
0.9133333 |
0.0 |
0.0 |
||||
1 |
SGOF |
0.6666667 |
0.9566667 |
0.0 |
0.0 |
||||
1 |
SGOF |
0.68 |
1.0 |
0.0 |
0.0 |
Alternatively, the same data can be produced as a CSV file using the command line
res2csv satfunc MYDATADECK.DATA --verbose --output satfunc.csv
It is possible to extract keywords one at a time using the --keywords
command
line option.
Instead of complete decks, individual include files may also be parsed, but only one at a time.
Generating include files from dataframes
When a dataframe of saturation function data is loaded into Python, any operation may be applied on the data. Simple operations would typically be scaling, perhaps individual pr. SATNUM. Still, read below on pyscal before embarking on too many Pandas operations on saturation functions.
An example operation could for example to scale all KRW data of the first SATNUM in the SWOF table, and if dframe holds all the data, this can be performed by the command
# Build boolean array of which rows in the big dataframe we want to touch:
rows_to_touch = (dframe["KEYWORD"] == "SWOF") & (dframe["SATNUM"] == 1)
# Multiplicate these rows by 0.5
dframe.loc[rows_to_touch, "KRW"] *= 0.5
For a dataframe or a CSV file in the format provided by this module, an
include file can be generated either with the Python API
res2df.satfunc.df2res()
function or the command
csv2res satfunc satfunc.csv --output relperm.inc --keywords SWOF SGOF --verbose
which should give a file relperm.inc
that can be parsed by reservoir simulators. The command
above will only pick the keywords SWOF
and SGOF
(in the case there are
data for more keywords in the dataframe).
There are no automated checks for validity of the dumped include file.
Extracting properties pr. SATNUM
If you have an include file prepared (from any source), you might need to determine certain properties like endpoint. If you need to determine for example “SOWCR” - the largest oil saturation for which oil is immobile, because you need to avoid SOWCR + SWCR overshooting 1, you can write a code
from res2df import satfunc
# Read an include file directly into a DataFrame
with open("relperm.inc") as f_handle:
sat_df = satfunc.df(f_handle.read())
# Write a function that is to operate on each SATNUM:
def sowcr(df):
"""Determine the largest oil saturation where
oil relperm is below 1e-7"""
return 1 - df[df["KROW"] > 1e-7]["SW"].max()
# Apply that function individually on each SATNUM:
sat_df.groupby("SATNUM").apply(sowcr)
for an example include file, this could result in
SATNUM
1 0.15492
2 0.21002
3 0.05442
dtype: float64
The pyscal library
Manipulation of curve shapes or potentially interpolation between curves is hard
to do directly on the dataframes. Before doing manipulations of dataframes in
res2df.satfunc
, consider if it is better to implement the manipulations
through the pyscal library.
Pyscal can create curves from parametrizations, and interpolate between curves.
Pyscal can initialize its relperm objects from include files through the parsing capabilities of res2df.satfunc.
The function pyscal.pyscallist.df()
is analogous to res2df.satfunc.df()
in
what it produces, and the res2df.satfunc.df2res()
can be used on both
(potentially with some filtering needed.).