From 462f9103358e805b3abc6934e8e81b163e6bd4ec Mon Sep 17 00:00:00 2001 From: Joshua Larsen Date: Fri, 6 Aug 2021 18:24:47 -0700 Subject: [PATCH 1/2] update(MF6Output): updates to access the list file using .output.list() --- autotest/t504_test.py | 10 ++++++- flopy/mf6/mfmodel.py | 42 ++++------------------------ flopy/mf6/utils/output_util.py | 50 ++++++++++++++++++++++++++++++++-- 3 files changed, 61 insertions(+), 41 deletions(-) diff --git a/autotest/t504_test.py b/autotest/t504_test.py index 9a0f5b17d4..57798d0e44 100644 --- a/autotest/t504_test.py +++ b/autotest/t504_test.py @@ -1171,6 +1171,7 @@ def test_mf6_output(): bud = ml.oc.output.budget() hds = ml.oc.output.head() + lst = ml.oc.output.list() idomain = np.ones(ml.modelgrid.shape, dtype=int) zonbud = ml.oc.output.zonebudget(idomain) @@ -1184,9 +1185,13 @@ def test_mf6_output(): if not isinstance(zonbud, flopy.utils.ZoneBudget6): raise AssertionError() + if not isinstance(lst, flopy.utils.MfListBudget): + raise AssertionError() + bud = ml.output.budget() hds = ml.output.head() zonbud = ml.output.zonebudget(idomain) + lst = ml.output.list() if not isinstance(bud, flopy.utils.CellBudgetFile): raise TypeError() @@ -1197,6 +1202,9 @@ def test_mf6_output(): if not isinstance(zonbud, flopy.utils.ZoneBudget6): raise TypeError() + if not isinstance(lst, flopy.utils.MfListBudget): + raise TypeError() + uzf = ml.uzf uzf_bud = uzf.output.budget() conv = uzf.output.package_convergence() @@ -1220,7 +1228,7 @@ def test_mf6_output(): print(uzf.output.__dict__) raise AssertionError(", ".join(uzf.output.methods())) - if len(ml.output.methods()) != 3: + if len(ml.output.methods()) != 4: raise AssertionError() if ml.dis.output.methods() is not None: diff --git a/flopy/mf6/mfmodel.py b/flopy/mf6/mfmodel.py index 563c8ac786..5979333754 100644 --- a/flopy/mf6/mfmodel.py +++ b/flopy/mf6/mfmodel.py @@ -20,6 +20,7 @@ from ..mbase import ModelInterface from .utils.mfenums import DiscretizationType from .data import mfstructure +from .utils.output_util import MF6Output from ..utils.check import mf6check @@ -606,7 +607,7 @@ def output(self): try: return self.oc.output except AttributeError: - return None + return MF6Output(self) def export(self, f, **kwargs): """Method to export a model to a shapefile or netcdf file @@ -799,14 +800,7 @@ def load_base( print(" loading package {}...".format(ftype)) # load package instance.load_package(ftype, fname, pname, strict, None) - sim_data = simulation.simulation_data - if ftype == "dis" and not sim_data.max_columns_user_set: - # set column wrap to ncol - dis = instance.get_package("dis") - if dis is not None and hasattr(dis, "ncol"): - sim_data.max_columns_of_data = dis.ncol.get_data() - sim_data.max_columns_user_set = False - sim_data.max_columns_auto_set = True + # load referenced packages if modelname in instance.simulation_data.referenced_files: for ref_file in instance.simulation_data.referenced_files[ @@ -987,9 +981,6 @@ def set_model_relative_path(self, model_ws): Model working folder relative to simulation working folder """ - # set all data internal - self.set_all_data_internal(False) - # update path in the file manager file_mgr = self.simulation_data.mfpath file_mgr.set_last_accessed_model_path() @@ -1001,10 +992,6 @@ def set_model_relative_path(self, model_ws): and model_ws != "." and self.simulation.name_file is not None ): - model_folder_path = file_mgr.get_model_path(self.name) - if not os.path.exists(model_folder_path): - # make new model folder - os.makedirs(model_folder_path) # update model name file location in simulation name file models = self.simulation.name_file.models models_data = models.get_data() @@ -1185,26 +1172,7 @@ def rename_all_packages(self, name): package.package_type, ) - def set_all_data_external( - self, check_data=True, external_data_folder=None - ): - """Sets the model's list and array data to be stored externally. - - Parameters - ---------- - check_data : bool - Determines if data error checking is enabled during this - process. - external_data_folder - Folder, relative to the simulation path or model relative path - (see use_model_relative_path parameter), where external data - will be stored - - """ - for package in self.packagelist: - package.set_all_data_external(check_data, external_data_folder) - - def set_all_data_internal(self, check_data=True): + def set_all_data_external(self, check_data=True): """Sets the model's list and array data to be stored externally. Parameters @@ -1215,7 +1183,7 @@ def set_all_data_internal(self, check_data=True): """ for package in self.packagelist: - package.set_all_data_internal(check_data) + package.set_all_data_external(check_data) def register_package( self, diff --git a/flopy/mf6/utils/output_util.py b/flopy/mf6/utils/output_util.py index 4b66b854ec..a73ce3e850 100644 --- a/flopy/mf6/utils/output_util.py +++ b/flopy/mf6/utils/output_util.py @@ -1,7 +1,16 @@ import os -from ...utils import HeadFile, CellBudgetFile, Mf6Obs, ZoneBudget6, ZoneFile6 +from ...utils import ( + HeadFile, + CellBudgetFile, + Mf6Obs, + ZoneBudget6, + ZoneFile6, + MfListBudget, + MtListBudget, +) from ...utils.observationfile import CsvFile from ...pakbase import PackageInterface +from ...mbase import ModelInterface class MF6Output: @@ -16,7 +25,7 @@ class MF6Output: """ def __init__(self, obj): - from ..modflow import ModflowUtlobs + from ..modflow import ModflowUtlobs, ModflowGwtoc, ModflowGwfoc # set initial observation definitions methods = { @@ -31,9 +40,25 @@ def __init__(self, obj): self._methods = [] self._sim_ws = obj.simulation_data.mfpath.get_sim_path() - if not isinstance(obj, PackageInterface): + if not isinstance(obj, (PackageInterface, ModelInterface)): raise TypeError("Only mf6 PackageInterface types can be used") + # capture the list file for Models and for OC packages + if isinstance(obj, (ModelInterface, ModflowGwfoc, ModflowGwtoc)): + if isinstance(obj, ModelInterface): + ml = obj + else: + ml = obj.parent + self._mtype = ml.model_type + nam_file = ml.model_nam_file[:-4] + self._lst = ml.name_file.blocks["options"].datasets["list"].array + if self._lst is None: + self._lst = "{}.lst".format(nam_file) + setattr(self, "list", self.__list) + self._methods.append("list()") + if isinstance(obj, ModelInterface): + return + obspkg = False if isinstance(obj, ModflowUtlobs): # this is a package @@ -267,6 +292,25 @@ def __csv(self, f=None): except (IOError, FileNotFoundError): return None + def __list(self): + """ + Method to read list files + + Returns + ------- + MfListBudget, MtListBudget object + """ + if self._lst is not None: + reader = MfListBudget + if self._mtype == "gwt": + reader = MtListBudget + + try: + list_file = os.path.join(self._sim_ws, self._lst) + return reader(list_file) + except (AssertionError, IOError, FileNotFoundError): + return None + def __mulitfile_handler(self, f, flist): """ From 7aaa79682f62850f1f9a24546b86aacc2ecaa2ce Mon Sep 17 00:00:00 2001 From: Joshua Larsen Date: Fri, 6 Aug 2021 18:28:44 -0700 Subject: [PATCH 2/2] revert unintended changes due to version conflict in mfmodel.py --- flopy/mf6/mfmodel.py | 39 ++++++++++++++++++++++++++++++++++++--- 1 file changed, 36 insertions(+), 3 deletions(-) diff --git a/flopy/mf6/mfmodel.py b/flopy/mf6/mfmodel.py index 5979333754..393179bd2e 100644 --- a/flopy/mf6/mfmodel.py +++ b/flopy/mf6/mfmodel.py @@ -800,7 +800,14 @@ def load_base( print(" loading package {}...".format(ftype)) # load package instance.load_package(ftype, fname, pname, strict, None) - + sim_data = simulation.simulation_data + if ftype == "dis" and not sim_data.max_columns_user_set: + # set column wrap to ncol + dis = instance.get_package("dis") + if dis is not None and hasattr(dis, "ncol"): + sim_data.max_columns_of_data = dis.ncol.get_data() + sim_data.max_columns_user_set = False + sim_data.max_columns_auto_set = True # load referenced packages if modelname in instance.simulation_data.referenced_files: for ref_file in instance.simulation_data.referenced_files[ @@ -981,6 +988,9 @@ def set_model_relative_path(self, model_ws): Model working folder relative to simulation working folder """ + # set all data internal + self.set_all_data_internal(False) + # update path in the file manager file_mgr = self.simulation_data.mfpath file_mgr.set_last_accessed_model_path() @@ -992,6 +1002,10 @@ def set_model_relative_path(self, model_ws): and model_ws != "." and self.simulation.name_file is not None ): + model_folder_path = file_mgr.get_model_path(self.name) + if not os.path.exists(model_folder_path): + # make new model folder + os.makedirs(model_folder_path) # update model name file location in simulation name file models = self.simulation.name_file.models models_data = models.get_data() @@ -1172,7 +1186,26 @@ def rename_all_packages(self, name): package.package_type, ) - def set_all_data_external(self, check_data=True): + def set_all_data_external( + self, check_data=True, external_data_folder=None + ): + """Sets the model's list and array data to be stored externally. + + Parameters + ---------- + check_data : bool + Determines if data error checking is enabled during this + process. + external_data_folder + Folder, relative to the simulation path or model relative path + (see use_model_relative_path parameter), where external data + will be stored + + """ + for package in self.packagelist: + package.set_all_data_external(check_data, external_data_folder) + + def set_all_data_internal(self, check_data=True): """Sets the model's list and array data to be stored externally. Parameters @@ -1183,7 +1216,7 @@ def set_all_data_external(self, check_data=True): """ for package in self.packagelist: - package.set_all_data_external(check_data) + package.set_all_data_internal(check_data) def register_package( self,