diff --git a/pypvt/_cli.py b/pypvt/_cli.py index f02915e..e1372ba 100644 --- a/pypvt/_cli.py +++ b/pypvt/_cli.py @@ -14,7 +14,7 @@ def pvt_consistency_check(args: argparse.Namespace) -> None: Nothing """ - fluid_description = FieldFluidDescription(ecl_case=args.ecl_case) + fluid_description = FieldFluidDescription(ecl_case=args.ecl_case, kwfile_dict={}) print(fluid_description.validate_description()) for fluid in fluid_description.fluid_descriptions: @@ -24,6 +24,49 @@ def pvt_consistency_check(args: argparse.Namespace) -> None: fluid_description.create_consistency_report() +def pvt_consistency_adjustment(args: argparse.Namespace) -> None: + """ + Entrypoint for running pypvt consistency adjustment, + ie adjusting the xxvd tables to be consistent with + respect to contacts. + + Args: + args: input namespace from argparse + + Returns: + Nothing + """ + + print("Running adjustment algorithm, more to come :)") + kwfile_dict = {} + if args.equil_file: + kwfile_dict["EQUIL"] = args.equil_file + if args.rsvd_file: + kwfile_dict["RSVD"] = args.rsvd_file + if args.rvvd_file: + kwfile_dict["RVVD"] = args.rvvd_file + if args.pbvd_file: + kwfile_dict["PBVD"] = args.pbvd_file + if args.pdvd_file: + kwfile_dict["PDVD"] = args.pdvd_file + if args.pvt_file: + kwfile_dict["PVT"] = args.pvt_file + fluid_description = FieldFluidDescription( + ecl_case=args.ecl_case, kwfile_dict=kwfile_dict + ) + + print(fluid_description.validate_description()) + # fnr = 0 + # for fluid in fluid_description.fluid_descriptions: + # fluid.calc_fluid_prop_vs_depth(no_nodes=args.nodes) + # fluid.inplace_report() + # fluid.pvt_gradient_check() + # if fnr >0: + # break + # fnr +=1 + # fluid_description.create_consistency_report() + + def main() -> None: """ Main functionality run when the 'pypvt' command-line tool is called. @@ -57,6 +100,66 @@ def main() -> None: ) parser_checks.set_defaults(func=pvt_consistency_check) + + parser_adjust = subparsers.add_parser( + "adjust", + help="Adjustment of rsvd/pbvd tables to make model consistent with respect to pvt.", + ) + + parser_adjust.add_argument( + "--ecl_case", + required=True, + type=pathlib.Path, + help="""Path to eclipse deck that has been run, eg a refcase, + to read necessary kws from. Updated kws should be + added by use of the optional arguments.""", + ) + + parser_adjust.add_argument( + "--equil_file", + type=pathlib.Path, + help="File with updated equil kw to override the one from ecl_case", + ) + + parser_adjust.add_argument( + "--pvt_file", + type=pathlib.Path, + help="File with updated pvt kw to override the one from ecl_case", + ) + + parser_adjust.add_argument( + "--rsvd_file", + type=pathlib.Path, + help="File with rsvd kw to override the one from ecl_case", + ) + + parser_adjust.add_argument( + "--rvvd_file", + type=pathlib.Path, + help="File with rvvd kw to override the one from ecl_case", + ) + + parser_adjust.add_argument( + "--pbvd_file", + type=pathlib.Path, + help="File with PBVD kw to override the one from ecl_case", + ) + + parser_adjust.add_argument( + "--pdvd_file", + type=pathlib.Path, + help="File with PDVD kw to override the one from ecl_case", + ) + + parser_adjust.add_argument( + "--output", + required=True, + type=pathlib.Path, + help="Name of consistent output table", + ) + + parser_adjust.set_defaults(func=pvt_consistency_adjustment) + args = parser.parse_args() args.func(args) diff --git a/pypvt/field_fluid_description.py b/pypvt/field_fluid_description.py index ebf635b..c5fef04 100644 --- a/pypvt/field_fluid_description.py +++ b/pypvt/field_fluid_description.py @@ -37,69 +37,113 @@ class FieldFluidDescription: for a collection of fluid systems, ie a field. """ - def __init__(self, ecl_case=None): + @staticmethod + def _parse_ecl_case(case_name): + eclfiles = ecl2df.EclFiles(case_name) + df_dict = {} + try: + df_dict["GRID"] = ecl2df.grid.df(eclfiles) + except KeyError: + print("No grid found, exiting") + sys.exit() + + df_dict["PVT"] = ecl2df.pvt.df(eclfiles) + df_dict["EQUIL"] = ecl2df.equil.df(eclfiles, keywords="EQUIL") + df_dict["RSVD"] = ecl2df.equil.df(eclfiles, keywords="RSVD") + df_dict["RVVD"] = ecl2df.equil.df(eclfiles, keywords="RVVD") + df_dict["PBVD"] = ecl2df.equil.df(eclfiles, keywords="PBVD") + df_dict["PDVD"] = ecl2df.equil.df(eclfiles, keywords="PDVD") + + return df_dict + + @staticmethod + def _kw_from_files(case_name, kw_dict, ntequil): + kw_dict_from_file = {} + for key in kw_dict.keys(): + if key == "EQUIL": + eclfiles = ecl2df.EclFiles(case_name) + deck = eclfiles.get_ecldeck() + fake_data = "" + if "OIL" in deck: + fake_data += """ + OIL + """ + if "GAS" in deck: + fake_data += """ + GAS + """ + if "WATER" in deck: + fake_data += """ + WATER + """ + df = ecl2df.equil.df( + fake_data + open(kw_dict[key], "r").read(), + keywords="EQUIL", + ntequl=ntequil, + ) + assert "KEYWORD" in df, ( + "Unable to read " + key + " kw from file: " + str(kw_dict[key]) + ) + kw_dict_from_file[key] = df + + elif key in ["RSVD", "RVVD", "PBVD", "PDVD"]: + df = ecl2df.equil.df( + open(kw_dict[key], "r").read(), keywords=key, ntequl=ntequil + ) + assert "KEYWORD" in df, ( + "Unable to read " + key + " kw from file: " + str(kw_dict[key]) + ) + kw_dict_from_file[key] = df + elif key == "PVT": + df = ecl2df.pvt.df(eclfiles) + assert "KEYWORD" in df, ( + "Unable to read " + key + " kw from file: " + str(kw_dict[key]) + ) + kw_dict_from_file[key] = df + else: + raise KeyError("KW " + key + " not supported") + + return kw_dict_from_file + + def __init__(self, ecl_case, kwfile_dict): self.fluid_descriptions = list([]) self.inactive_fluid_descriptions = list([]) self.fluid_index = {} self.inacive_fluid_index = {} - self.max_depth = (10000,) - self.min_depth = (0,) self._records_list = [] self._pvt_logger = logging.getLogger(__name__) self._pvt_logger.addHandler(RecordsListHandler(self._records_list)) + eclkwdf_dict = {} if ecl_case: - self.init_from_ecl(ecl_case) - - @property - def logger(self): - return self._pvt_logger + eclkwdf_dict = self._parse_ecl_case(ecl_case) - def records_list(self): - return self._records_list - - @staticmethod - def _parse_case(case_name): - eclfiles = ecl2df.EclFiles(case_name) - dataframes = {} - - dataframes["GRID"] = ecl2df.grid.df(eclfiles) - dataframes["PVT"] = ecl2df.pvt.df(eclfiles) - dataframes["EQUIL"] = ecl2df.equil.df(eclfiles, keywords="EQUIL") - dataframes["RSVD"] = ecl2df.equil.df(eclfiles, keywords="RSVD") - dataframes["RVVD"] = ecl2df.equil.df(eclfiles, keywords="RVVD") - dataframes["PBVD"] = ecl2df.equil.df(eclfiles, keywords="PBVD") - dataframes["PDVD"] = ecl2df.equil.df(eclfiles, keywords="PDVD") - - return dataframes - - def init_from_ecl(self, case): - ecldf_dict = FieldFluidDescription._parse_case(case) - - grid = None - try: - grid = ecldf_dict["GRID"] - except KeyError: - print("No grid found, exiting") - sys.exit() + if kwfile_dict: + ntequl = len(eclkwdf_dict["EQUIL"]["EQLNUM"].unique()) + eclkwdf_dict = { + **eclkwdf_dict, + **self._kw_from_files(ecl_case, kwfile_dict, ntequl), + } top_struct = None bottom_struct = None - if ecldf_dict["GRID"] is not None: + grid = None + if eclkwdf_dict["GRID"] is not None: + grid = eclkwdf_dict["GRID"] top_struct = grid["Z"].min() bottom_struct = grid["Z"].max() pvt = None try: - pvt = ecldf_dict["PVT"] + pvt = eclkwdf_dict["PVT"] except KeyError: print("No pvt found, exiting") sys.exit() equil = None try: - equil = ecldf_dict["EQUIL"] + equil = eclkwdf_dict["EQUIL"] except KeyError: print("No equil found, exiting") sys.exit() @@ -121,7 +165,7 @@ def init_from_ecl(self, case): pvtnum=int(pvtnr), pvt_logger=self.logger, ) - fluid.init_from_ecl_df(ecldf_dict) + fluid.init_from_ecl_df(eclkwdf_dict) self.fluid_descriptions.append(fluid) self.fluid_index[int(equilnr)] = fluid_index fluid_index += 1 @@ -134,11 +178,18 @@ def init_from_ecl(self, case): fluid = ElementFluidDescription( eqlnum=int(equilnr), pvtnum=len(pvt["PVTNUM"].unique()) ) - fluid.init_from_ecl_df(ecldf_dict) + fluid.init_from_ecl_df(eclkwdf_dict) self.inactive_fluid_descriptions.append(fluid) self.inacive_fluid_index[int(equilnr)] = fluid_index fluid_index += 1 + @property + def logger(self): + return self._pvt_logger + + def records_list(self): + return self._records_list + def validate_description(self): """ Check if the minimum requirements of a fluid description is fulfilled: diff --git a/tests/data/adjust_config.yml b/tests/data/adjust_config.yml new file mode 100644 index 0000000..5dbd1ee --- /dev/null +++ b/tests/data/adjust_config.yml @@ -0,0 +1,13 @@ +rsvd_files: + -base: /path/to/base_rs.inc + -opt: /path/to/opt_rs.inc + -pes: /path/to/pes_rs.inc + +rvvd_files: + -base: /path/to/base_rv.inc + -opt: /path/to/opt_rv.inc + -pes: /path/to/pes_rv.inc + +eqil_file: /path/to/updated/equil.inc + +Output: updated_rsvd.inc \ No newline at end of file diff --git a/tests/data/interp_config.yml b/tests/data/interp_config.yml new file mode 100644 index 0000000..9c3ddad --- /dev/null +++ b/tests/data/interp_config.yml @@ -0,0 +1,20 @@ +rsvd_files: + -base: /path/to/base_rs.inc + -opt: /path/to/opt_rs.inc + -pes: /path/to/pes_rs.inc + +rvvd_files: + -base: /path/to/base_rv.inc + -opt: /path/to/opt_rv.inc + -pes: /path/to/pes_rv.inc + +eqil_file: /path/to/updated/equil.inc + +Output: updated_rsvd.inc + +interpolation: + -equilnums: [] + -param: 0.54 +interpolation: + -equilnums: [1,4,72] + -param: -0.2 \ No newline at end of file