def make_wateroilgas(dframe: pd.DataFrame, delta_s: float) -> pyscal.WaterOilGas: """Construct a pyscal WaterOilGas object from a dataframe of tabulated relperm and capillary pressure values Arguments: dframe: Containing tabulated values with pyscals column naming. The data must be restricted to only one SATNUM. """ dframe = dframe.copy() # Copy since we will modify it. wog = pyscal.WaterOilGas(swl=dframe["SW"].min(), h=delta_s) if "PCOW" not in dframe: dframe = dframe.assign(PCOW=0) if "PCOG" not in dframe: dframe = dframe.assign(PCOG=0) # If we have parsed family 2 input, KRO and KROW are not # on the same row. Merge the rows into family 1 style: if "KEYWORD" in dframe and "SOF3" in dframe["KEYWORD"].values: sof3_rows = dframe["KEYWORD"] == "SOF3" dframe.loc[sof3_rows, "SW"] = 1 - dframe[sof3_rows]["SO"] swl = dframe["SW"].min() dframe.loc[sof3_rows, "SG"] = 1 - swl - dframe[sof3_rows]["SO"] wo_dframe = (dframe[[ "SW", "KRW", "KROW", "PCOW" ]].set_index("SW").sort_index().dropna(how="all").interpolate( method="index").fillna( method="bfill").round(8).drop_duplicates().reset_index()) go_dframe = (dframe[[ "SG", "KRG", "KROG", "PCOG" ]].set_index("SG").sort_index().dropna(how="all").interpolate( method="index").fillna( method="bfill").round(8).drop_duplicates().reset_index()) else: wo_dframe = dframe[["SW", "KRW", "KROW", "PCOW"]].dropna().reset_index() go_dframe = dframe[["SG", "KRG", "KROG", "PCOG"]].dropna().reset_index() wog.wateroil.add_fromtable( wo_dframe, # For pyscal <= 0.7.7: swcolname="SW", krwcolname="KRW", krowcolname="KROW", pccolname="PCOW", ) wog.gasoil.add_fromtable( go_dframe, # For pyscal <= 0.7.7: sgcolname="SG", krgcolname="KRG", krogcolname="KROG", pccolname="PCOG", ) # If sgro > 0, it is a gas condensate object, which cannot be # mixed with non-gas condensate (during interpolation). Avoid pitfalls # in the estimated sgro by always setting it to zero: wog.gasoil.sgro = 0.0 return wog
def make_interpolant(base_df, low_df, high_df, interp_param, satnum, delta_s): """ Routine to define a pyscal.interpolant instance and perform interpolation. Parameters: base_df (pd.DataFrame): containing the base tables low_df (pd.DataFrame): containing the low tables high_df (pd.DataFrame): containing the high tables interp_param (dict): With keys ('param_w', 'param_g'), the interp parameter values satnum (int): the satuation number index delta_s (float): the saturation spacing to be used in out tables Returns: pyscal.WaterOilGas: Object holding tables for one satnum """ # Define base tables swlbase = base_df.loc["SWOF", satnum]["SW"].min() base = pyscal.WaterOilGas(swl=float(swlbase), h=delta_s) base.wateroil.add_fromtable( base_df.loc["SWOF", satnum].reset_index(), swcolname="SW", krwcolname="KRW", krowcolname="KROW", pccolname="PCOW", ) # Define low tables if "SWOF" in low_df.index.unique(): swllow = low_df.loc["SWOF", satnum]["SW"].min() low = pyscal.WaterOilGas(swl=float(swllow), h=delta_s) low.wateroil.add_fromtable( low_df.loc["SWOF", satnum].reset_index(), swcolname="SW", krwcolname="KRW", krowcolname="KROW", pccolname="PCOW", ) else: swllow = base_df.loc["SWOF", satnum]["SW"].min() low = pyscal.WaterOilGas(swl=float(swllow), h=delta_s) low.wateroil.add_fromtable( base_df.loc["SWOF", satnum].reset_index(), swcolname="SW", krwcolname="KRW", krowcolname="KROW", pccolname="PCOW", ) # Define high tables if "SWOF" in high_df.index.unique(): swlhigh = high_df.loc["SWOF", satnum]["SW"].min() high = pyscal.WaterOilGas(swl=float(swlhigh), h=delta_s) high.wateroil.add_fromtable( high_df.loc["SWOF", satnum].reset_index(), swcolname="SW", krwcolname="KRW", krowcolname="KROW", pccolname="PCOW", ) else: swlhigh = base_df.loc["SWOF", satnum]["SW"].min() high = pyscal.WaterOilGas(swl=float(swlhigh), h=delta_s) high.wateroil.add_fromtable( base_df.loc["SWOF", satnum].reset_index(), swcolname="SW", krwcolname="KRW", krowcolname="KROW", pccolname="PCOW", ) # Correct types for Sg (sometimes incorrecly set to str) base_df["SG"] = base_df["SG"].astype("float64") base.gasoil.add_fromtable( base_df.loc["SGOF", satnum].reset_index(), sgcolname="SG", krgcolname="KRG", krogcolname="KROG", pccolname="PCOG", ) if "SGOF" in low_df.index.unique(): low_df["SG"] = low_df["SG"].astype("float64") low.gasoil.add_fromtable( low_df.loc["SGOF", satnum].reset_index(), sgcolname="SG", krgcolname="KRG", krogcolname="KROG", pccolname="PCOG", ) else: low.gasoil.add_fromtable( base_df.loc["SGOF", satnum].reset_index(), sgcolname="SG", krgcolname="KRG", krogcolname="KROG", pccolname="PCOG", ) if "SGOF" in high_df.index.unique(): high_df["SG"] = high_df["SG"].astype("float64") high.gasoil.add_fromtable( high_df.loc["SGOF", satnum].reset_index(), sgcolname="SG", krgcolname="KRG", krogcolname="KROG", pccolname="PCOG", ) else: high.gasoil.add_fromtable( base_df.loc["SGOF", satnum].reset_index(), sgcolname="SG", krgcolname="KRG", krogcolname="KROG", pccolname="PCOG", ) rec = pyscal.SCALrecommendation(low, base, high, "SATNUM " + str(satnum), h=delta_s) if "SWOF" not in low_df.index.unique() and interp_param["param_w"] < 0: sys.exit("Error: interpolation parameter for SWOF, satnum:" + str(satnum) + " set to " + str(interp_param["param_w"]) + " but no low table is provided. Values cannot be negative") if "SWOF" not in high_df.index.unique() and interp_param["param_w"] > 0: sys.exit("Error: interpolation parameter for SWOF, satnum:" + str(satnum) + " set to " + str(interp_param["param_w"]) + " but no high table is provided. Values cannot be positive") if "SGOF" not in low_df.index.unique() and interp_param["param_g"] < 0: sys.exit("Error: interpolation parameter for SGOF, satnum:" + str(satnum) + " set to " + str(interp_param["param_g"]) + " but no low table is provided. Values cannot be negative") if "SGOF" not in high_df.index.unique() and interp_param["param_g"] > 0: sys.exit("Error: interpolation parameter for SGOF, satnum:" + str(satnum) + " set to " + str(interp_param["param_g"]) + " but no high table is provided. Values cannot be positive") return rec.interpolate(interp_param["param_w"], interp_param["param_g"], h=delta_s)