From dc3c8b7f1bac46329d25dac499249d147f4856a1 Mon Sep 17 00:00:00 2001 From: w-bonelli Date: Wed, 5 Feb 2025 20:12:58 -0500 Subject: [PATCH 1/4] wip --- flopy/mf6/inspect.py | 31 +++++++++++++++++++++++++++++++ flopy/utils/inspect.py | 7 +++++++ 2 files changed, 38 insertions(+) create mode 100644 flopy/mf6/inspect.py create mode 100644 flopy/utils/inspect.py diff --git a/flopy/mf6/inspect.py b/flopy/mf6/inspect.py new file mode 100644 index 0000000000..d1cc965623 --- /dev/null +++ b/flopy/mf6/inspect.py @@ -0,0 +1,31 @@ +def get_classes(predicate=None): + import flopy.mf6.modflow as modflow + from flopy.utils.inspect import get_classes as _get_classes + + return _get_classes( + modflow, + lambda cls: hasattr(cls, "dfn") and (predicate(cls) if predicate else True), + ) + + +def get_multi_packages(): + def _filter(cls): + return ( + len(cls.dfn) > 0 + and len(cls.dfn[0]) >= 2 + and cls.dfn[0][1] == "multi-package" + ) + + return get_classes(_filter) + + +def get_solution_packages(): + def _filter(cls): + return ( + len(cls.dfn) > 0 + and len(cls.dfn[0]) >= 2 + and len(cls.dfn[0][1]) > 0 + and cls.dfn[0][1][0] == "solution_package" + ) + + return get_classes(_filter) diff --git a/flopy/utils/inspect.py b/flopy/utils/inspect.py new file mode 100644 index 0000000000..8fe707ca1e --- /dev/null +++ b/flopy/utils/inspect.py @@ -0,0 +1,7 @@ +import inspect + + +def get_classes(module, predicate=None): + """Find classes in a module which satisfy a predicate.""" + classes = inspect.getmembers(module, inspect.isclass) + return [cls for name, cls in classes if predicate(cls)] From 76d489d6ced62fcae74146a534992a820e46e99a Mon Sep 17 00:00:00 2001 From: wpbonelli Date: Wed, 5 Feb 2025 20:28:18 -0500 Subject: [PATCH 2/4] add subpackage support --- flopy/mf6/inspect.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/flopy/mf6/inspect.py b/flopy/mf6/inspect.py index d1cc965623..781fda246f 100644 --- a/flopy/mf6/inspect.py +++ b/flopy/mf6/inspect.py @@ -29,3 +29,15 @@ def _filter(cls): ) return get_classes(_filter) + + +def get_sub_packages(): + def _filter(cls): + return ( + len(cls.dfn) > 0 + and len(cls.dfn[0]) >= 2 + and len(cls.dfn[0][1]) > 0 + and cls.dfn[0][1][0] == "subpackage" + ) + + return get_classes(_filter) From 76a2630dfc4c06ab9dc69cf6002ec20808d2701c Mon Sep 17 00:00:00 2001 From: wpbonelli Date: Wed, 5 Feb 2025 20:39:18 -0500 Subject: [PATCH 3/4] wip --- flopy/mf6/data/mfstructure.py | 45 ++++++----------------------------- flopy/mf6/inspect.py | 11 +++++---- flopy/utils/inspect.py | 5 ++-- 3 files changed, 17 insertions(+), 44 deletions(-) diff --git a/flopy/mf6/data/mfstructure.py b/flopy/mf6/data/mfstructure.py index 34a78a780e..691bac35ad 100644 --- a/flopy/mf6/data/mfstructure.py +++ b/flopy/mf6/data/mfstructure.py @@ -13,6 +13,8 @@ import numpy as np +from flopy.mf6.inspect import get_solution_packages + from ..mfbase import PackageContainer, StructException numeric_index_text = ( @@ -2492,7 +2494,9 @@ def __new__(cls, internal_request=False, load_from_dfn_files=False): cls._instance.sim_struct = None cls._instance.dimension_dict = {} cls._instance.load_from_dfn_files = load_from_dfn_files - cls._instance.flopy_dict = {} + cls._instance.flopy_dict = { + "solution_packages": get_solution_packages() + } # Read metadata from file cls._instance.valid = cls._instance.__load_structure() @@ -2509,9 +2513,6 @@ def __load_structure(self): # set up structure classes self.sim_struct = MFSimulationStructure() - # initialize flopy dict keys - MFStructure().flopy_dict["solution_packages"] = {} - if self.load_from_dfn_files: mf_dfn = Dfn() dfn_files = mf_dfn.get_file_list() @@ -2542,44 +2543,12 @@ def __load_structure(self): "parameter_name": line_lst[6], } MFStructure().flopy_dict[line_lst[3]] = sp_dict - elif line_lst[2] == "solution_package": - MFStructure().flopy_dict["solution_packages"][ - line_lst[3] - ] = line_lst[4:] - if len(MFStructure().flopy_dict["solution_packages"]) == 0: - MFStructure().flopy_dict["solution_packages"]["ims"] = ["*"] - warnings.warn( - "Package definition files (dfn) do not define a solution " - "package. This can happen if your dfn files are out of " - "sync. Auto-loaded default IMS solution package metadata." - " In the future auto-loading default metadata will be " - "deprecated.", - DeprecationWarning, - ) - # process each file for file in dfn_files: self.sim_struct.process_dfn(DfnFile(file)) self.sim_struct.tag_read_as_arrays() else: - package_list = PackageContainer.package_list() - for package in package_list: - # process header - for entry in package.dfn[0][1:]: - if ( - isinstance(entry, list) - and entry[0] == "solution_package" - ): - MFStructure().flopy_dict["solution_packages"][ - package.package_abbr - ] = entry[1:] - # process each package + for package in PackageContainer.package_list(): self.sim_struct.process_dfn(DfnPackage(package)) self.sim_struct.tag_read_as_arrays() - return True - - @staticmethod - def __valid_line(line): - if len(line.strip()) > 1 and line[0] != "#": - return True - return False + return True \ No newline at end of file diff --git a/flopy/mf6/inspect.py b/flopy/mf6/inspect.py index 781fda246f..525fdff5ba 100644 --- a/flopy/mf6/inspect.py +++ b/flopy/mf6/inspect.py @@ -1,4 +1,7 @@ -def get_classes(predicate=None): +from collections.abc import Mapping + + +def get_classes(predicate=None) -> Mapping[str, type]: import flopy.mf6.modflow as modflow from flopy.utils.inspect import get_classes as _get_classes @@ -8,7 +11,7 @@ def get_classes(predicate=None): ) -def get_multi_packages(): +def get_multi_packages() -> Mapping[str, type]: def _filter(cls): return ( len(cls.dfn) > 0 @@ -19,7 +22,7 @@ def _filter(cls): return get_classes(_filter) -def get_solution_packages(): +def get_solution_packages() -> Mapping[str, type]: def _filter(cls): return ( len(cls.dfn) > 0 @@ -31,7 +34,7 @@ def _filter(cls): return get_classes(_filter) -def get_sub_packages(): +def get_sub_packages() -> Mapping[str, type]: def _filter(cls): return ( len(cls.dfn) > 0 diff --git a/flopy/utils/inspect.py b/flopy/utils/inspect.py index 8fe707ca1e..1ded3b83e9 100644 --- a/flopy/utils/inspect.py +++ b/flopy/utils/inspect.py @@ -1,7 +1,8 @@ import inspect +from collections.abc import Mapping -def get_classes(module, predicate=None): +def get_classes(module, predicate=None) -> Mapping[str, type]: """Find classes in a module which satisfy a predicate.""" classes = inspect.getmembers(module, inspect.isclass) - return [cls for name, cls in classes if predicate(cls)] + return {name: cls for name, cls in classes if predicate(cls)} From b75d77b6272ba4d604daca40296faa46cb3591ea Mon Sep 17 00:00:00 2001 From: wpbonelli Date: Wed, 5 Feb 2025 21:16:36 -0500 Subject: [PATCH 4/4] update mfstructure --- flopy/mf6/data/mfstructure.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/flopy/mf6/data/mfstructure.py b/flopy/mf6/data/mfstructure.py index 691bac35ad..047f2697f8 100644 --- a/flopy/mf6/data/mfstructure.py +++ b/flopy/mf6/data/mfstructure.py @@ -2463,6 +2463,11 @@ def tag_read_as_arrays(self): package_struct.read_as_arrays = True +def _get_solution_packages(): + pkgs = get_solution_packages() + return {k.lower().replace("modflow", ""): "*" for k in pkgs.keys()} + + class MFStructure: """ Singleton class for accessing the contents of the json structure file @@ -2495,7 +2500,7 @@ def __new__(cls, internal_request=False, load_from_dfn_files=False): cls._instance.dimension_dict = {} cls._instance.load_from_dfn_files = load_from_dfn_files cls._instance.flopy_dict = { - "solution_packages": get_solution_packages() + "solution_packages": _get_solution_packages() } # Read metadata from file