From 73d1c712cf994883f46926a628341676080c3130 Mon Sep 17 00:00:00 2001 From: jbellino-usgs Date: Wed, 19 Jun 2019 16:24:46 -0400 Subject: [PATCH 01/15] feat(ModflowFlwob): Add various flow-obs types to model.mfnam_packages dictionary. --- flopy/modflow/mf.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/flopy/modflow/mf.py b/flopy/modflow/mf.py index 4b58e23fa6..a930539565 100644 --- a/flopy/modflow/mf.py +++ b/flopy/modflow/mf.py @@ -203,6 +203,10 @@ def __init__(self, modelname='modflowtest', namefile_ext='nam', "swt": flopy.modflow.ModflowSwt, "hyd": flopy.modflow.ModflowHyd, "hob": flopy.modflow.ModflowHob, + "chob": flopy.modflow.ModflowFlwob, + "gbob": flopy.modflow.ModflowFlwob, + "drob": flopy.modflow.ModflowFlwob, + "rvob": flopy.modflow.ModflowFlwob, "vdf": flopy.seawat.SeawatVdf, "vsc": flopy.seawat.SeawatVsc } From bec13eb4f31304f9c545ff4b9e542e3ee03d540c Mon Sep 17 00:00:00 2001 From: jbellino-usgs Date: Wed, 19 Jun 2019 16:25:09 -0400 Subject: [PATCH 02/15] feat(ModflowFlwob): Add method to load package from file. --- flopy/modflow/mfflwob.py | 181 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 181 insertions(+) diff --git a/flopy/modflow/mfflwob.py b/flopy/modflow/mfflwob.py index d47247d5ad..2a68b2dd3e 100755 --- a/flopy/modflow/mfflwob.py +++ b/flopy/modflow/mfflwob.py @@ -1,3 +1,4 @@ +import sys import numpy as np from ..pakbase import Package @@ -314,3 +315,183 @@ def write_file(self): # swm: END hack for writing standard file return + + @staticmethod + def load(f, model, flowtype=None, ext_unit_dict=None, check=True): + """ + Load an existing package. + + Parameters + ---------- + f : filename or file handle + File to load. + model : model object + The model object (of type :class:`flopy.modflow.mf.Modflow`) to + which this package will be added. + ext_unit_dict : dictionary, optional + If the arrays in the file are specified using EXTERNAL, + or older style array control records, then `f` should be a file + handle. In this case ext_unit_dict is required, which can be + constructed using the function + :class:`flopy.utils.mfreadnam.parsenamefile`. + check : boolean + Check package data for common errors. (default True) + + Returns + ------- + flwob : ModflowFlwob package object + ModflowFlwob package object. + + Examples + -------- + + >>> import flopy + >>> m = flopy.modflow.Modflow() + >>> hobs = flopy.modflow.ModflowFlwob.load('test.drob', m) + + """ + + if model.verbose: + sys.stdout.write('loading flwob package file...\n') + + if not hasattr(f, 'read'): + filename = f + f = open(filename, 'r') + + ext = None + if flowtype is None: + # attempt to infer flowtype + ext = f.name.split('.')[-1].lower() + if 'ch' in ext.lower(): + ext = 'chob' + flowtype = 'CHD' + elif 'gb' in ext.lower(): + ext = 'gbob' + flowtype = 'GHB' + elif 'dr' in ext.lower(): + ext = 'drob' + flowtype = 'DRN' + elif 'rv' in ext.lower(): + ext = 'rvob' + flowtype = 'RIV' + else: + msg = 'ModflowFlwob: flowtype cannot be inferred ' \ + 'from file name {}'.format(f.name) + raise KeyError(msg) + + # dataset 0 -- header + while True: + line = f.readline() + if line[0] != '#': + break + + # read dataset 1 -- NQFB NQCFB NQTFB IUFBOBSV Options + t = line.strip().split() + nqfb = int(t[0]) + nqcfb = int(t[1]) + nqtfb = int(t[2]) + iufbobsv = int(t[3]) + options = [] + if len(t) > 4: + options = t[4:] + + # read dataset 2 -- TOMULTFB + line = f.readline() + t = line.strip().split() + tomultfb = float(t[0]) + + nqobfb = np.zeros(nqfb, dtype=np.int32) + nqclfb = np.zeros(nqfb, dtype=np.int32) + obsnam = [] + irefsp = [] + toffset = [] + flwobs = [] + + layer = [] + row = [] + column = [] + factor = [] + + # read datasets 3, 4, and 5 for each of nqfb groups + # of cells + nobs = 0 + while True: + + # read dataset 3 -- NQOBFB NQCLFB + line = f.readline() + t = line.strip().split() + nqobfb[nobs] = int(t[0]) + nqclfb[nobs] = int(t[1]) + + # read dataset 4 -- OBSNAM IREFSP TOFFSET FLWOBS + ntimes = 0 + while True: + line = f.readline() + t = line.strip().split() + obsnam.append(t[0]) + irefsp.append(int(t[1])) + toffset.append(float(t[2])) + flwobs.append(float(t[3])) + ntimes += 1 + if ntimes == nqobfb[nobs]: + break + + # read dataset 5 -- Layer Row Column Factor + k = np.zeros(abs(nqclfb[nobs]), np.int32) + i = np.zeros(abs(nqclfb[nobs]), np.int32) + j = np.zeros(abs(nqclfb[nobs]), np.int32) + fac = np.zeros(abs(nqclfb[nobs]), np.float32) + + ncells = 0 + while True: + line = f.readline() + t = line.strip().split() + k[ncells] = int(t[0]) + i[ncells] = int(t[1]) + j[ncells] = int(t[2]) + fac[ncells] = float(t[3]) + + ncells += 1 + if ncells == abs(nqclfb[nobs]): + layer.append(k) + row.append(i) + column.append(j) + factor.append(fac) + break + + nobs += 1 + if nobs == nqfb: + break + + irefsp = np.array(irefsp) - 1 + layer = np.array(layer) - 1 + row = np.array(row) - 1 + column = np.array(column) - 1 + factor = np.array(factor) + + # close the file + f.close() + + # set package unit number + unitnumber = None + filenames = [None, None] + if ext_unit_dict is not None: + unitnumber, filenames[0] = \ + model.get_ext_dict_attr(ext_unit_dict, + filetype=ext.upper()) + if iufbobsv > 0: + iu, filenames[1] = \ + model.get_ext_dict_attr(ext_unit_dict, unit=iufbobsv) + model.add_pop_key_list(iufbobsv) + + # create ModflowFlwob object instance + flwob = ModflowFlwob(model, iufbobsv=iufbobsv, tomultfb=tomultfb, + nqfb=nqfb, nqcfb=nqcfb, + nqtfb=nqtfb, nqobfb=nqobfb, nqclfb=nqclfb, + obsnam=obsnam, irefsp=irefsp, toffset=toffset, + flwobs=flwobs, layer=layer, row=row, + column=column, factor=factor, options=options, + flowtype=flowtype, unitnumber=unitnumber, + filenames=filenames) + + return flwob From 964407868abc0dae5592e9c4d48791dd98ba9b81 Mon Sep 17 00:00:00 2001 From: jbellino-usgs Date: Wed, 19 Jun 2019 16:29:07 -0400 Subject: [PATCH 03/15] feat(ModflowFlwob): Use supplied unit number when loading package to avoid unit collisions. --- flopy/modflow/mfflwob.py | 42 ++++++++++++++++++++++++++++++---------- 1 file changed, 32 insertions(+), 10 deletions(-) diff --git a/flopy/modflow/mfflwob.py b/flopy/modflow/mfflwob.py index 2a68b2dd3e..02cc694f69 100755 --- a/flopy/modflow/mfflwob.py +++ b/flopy/modflow/mfflwob.py @@ -136,41 +136,63 @@ def __init__(self, model, nqfb=0, nqcfb=0, nqtfb=0, iufbobsv=0, if extension is None: extension = ['chob', 'obc', 'gbob', 'obg', 'drob', 'obd', 'rvob', 'obr'] - if unitnumber is None: - unitnumber = [40, 140, 41, 141, 42, 142, 43, 143] + pakunits = {'chob': 40, + 'gbob': 41, + 'drob': 42, + 'rvob': 43} + outunits = {'chob': 140, + 'gbob': 141, + 'drob': 142, + 'rvob': 143} + # if unitnumber is None: + # unitnumber = [40, 140, 41, 141, 42, 142, 43, 143] if flowtype.upper().strip() == 'CHD': name = ['CHOB', 'DATA'] extension = extension[0:2] - unitnumber = unitnumber[0:2] - iufbobsv = unitnumber[1] + # unitnumber = unitnumber[0:2] + # iufbobsv = unitnumber[1] self.url = 'chob.htm' self.heading = '# CHOB for MODFLOW, generated by Flopy.' elif flowtype.upper().strip() == 'GHB': name = ['GBOB', 'DATA'] extension = extension[2:4] - unitnumber = unitnumber[2:4] - iufbobsv = unitnumber[1] + # unitnumber = unitnumber[2:4] + # iufbobsv = unitnumber[1] self.url = 'gbob.htm' self.heading = '# GBOB for MODFLOW, generated by Flopy.' elif flowtype.upper().strip() == 'DRN': name = ['DROB', 'DATA'] extension = extension[4:6] - unitnumber = unitnumber[4:6] - iufbobsv = unitnumber[1] + # unitnumber = unitnumber[4:6] + # iufbobsv = unitnumber[1] self.url = 'drob.htm' self.heading = '# DROB for MODFLOW, generated by Flopy.' elif flowtype.upper().strip() == 'RIV': name = ['RVOB', 'DATA'] extension = extension[6:8] - unitnumber = unitnumber[6:8] - iufbobsv = unitnumber[1] + # unitnumber = unitnumber[6:8] + # iufbobsv = unitnumber[1] self.url = 'rvob.htm' self.heading = '# RVOB for MODFLOW, generated by Flopy.' else: msg = 'ModflowFlwob: flowtype must be CHD, GHB, DRN, or RIV' raise KeyError(msg) + if unitnumber is None: + unitnumber = [pakunits[name[0].lower()], + outunits[name[0].lower()]] + elif isinstance(unitnumber, int): + unitnumber = [unitnumber] + if len(unitnumber) == 1: + if unitnumber[0] in outunits.keys(): + unitnumber = [pakunits[name[0].lower()], + unitnumber[0]] + else: + unitnumber = [unitnumber[0], + outunits[name[0].lower()]] + iufbobsv = unitnumber[1] + # set filenames if filenames is None: filenames = [None, None] From 10563402aa509d47c22b696b710d6a1c681185b7 Mon Sep 17 00:00:00 2001 From: jbellino-usgs Date: Wed, 19 Jun 2019 16:30:13 -0400 Subject: [PATCH 04/15] feat(ModflowFlwob): Add additional width and precision for toffset to avoid string-conversions that result in numbers greater than total simulation time. --- flopy/modflow/mfflwob.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/flopy/modflow/mfflwob.py b/flopy/modflow/mfflwob.py index 02cc694f69..2ee053ebd1 100755 --- a/flopy/modflow/mfflwob.py +++ b/flopy/modflow/mfflwob.py @@ -298,10 +298,10 @@ def write_file(self): # Loop through observation times for the groups for j in range(self.nqobfb[i]): # write section 4 - line = '{}{:10d}{:10.4g} {:10.4g}\n'.format(self.obsnam[c], - self.irefsp[c] + 1, - self.toffset[c], - self.flwobs[c]) + line = '{:12}'.format(self.obsnam[c]) + line += '{:8d}'.format(self.irefsp[c]) + line += '{:16.10g}'.format(self.toffset[c]) + line += ' {:10.4g}\n'.format(self.flwobs[c]) f_fbob.write(line) c += 1 # index variable From d2bd9249a61178784d48933b9993d54f3b0b32d8 Mon Sep 17 00:00:00 2001 From: jbellino-usgs Date: Wed, 19 Jun 2019 16:38:44 -0400 Subject: [PATCH 05/15] feat(ModflowFlwob): Account for case where nqclfb is negative. --- flopy/modflow/mfflwob.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/flopy/modflow/mfflwob.py b/flopy/modflow/mfflwob.py index 2ee053ebd1..7498849143 100755 --- a/flopy/modflow/mfflwob.py +++ b/flopy/modflow/mfflwob.py @@ -224,10 +224,14 @@ def __init__(self, model, nqfb=0, nqcfb=0, nqtfb=0, iufbobsv=0, self.factor = factor # -create empty arrays of the correct size - self.layer = np.zeros((self.nqfb, max(self.nqclfb)), dtype='int32') - self.row = np.zeros((self.nqfb, max(self.nqclfb)), dtype='int32') - self.column = np.zeros((self.nqfb, max(self.nqclfb)), dtype='int32') - self.factor = np.zeros((self.nqfb, max(self.nqclfb)), dtype='float32') + self.layer = np.zeros((self.nqfb, max(np.abs(self.nqclfb))), + dtype='int32') + self.row = np.zeros((self.nqfb, max(np.abs(self.nqclfb))), + dtype='int32') + self.column = np.zeros((self.nqfb, max(np.abs(self.nqclfb))), + dtype='int32') + self.factor = np.zeros((self.nqfb, max(np.abs(self.nqclfb))), + dtype='float32') self.nqobfb = np.zeros((self.nqfb), dtype='int32') self.nqclfb = np.zeros((self.nqfb), dtype='int32') self.irefsp = np.zeros((self.nqtfb), dtype='int32') From 6f520064a5e7dc856b177cd567668f712866117e Mon Sep 17 00:00:00 2001 From: jbellino-usgs Date: Thu, 20 Jun 2019 09:34:31 -0400 Subject: [PATCH 06/15] feat(ModflowFlwob): Append filename using relative path with respect to the model working directory to ensure the correct filename is written to the namefile. --- flopy/modflow/mf.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/flopy/modflow/mf.py b/flopy/modflow/mf.py index a930539565..043a3387a2 100644 --- a/flopy/modflow/mf.py +++ b/flopy/modflow/mf.py @@ -825,7 +825,8 @@ def load(f, version='mf2005', exe_name='mf2005.exe', verbose=False, if key not in ml.pop_key_list: # do not add unit number (key) if it already exists if key not in ml.external_units: - ml.external_fnames.append(item.filename) + ml.external_fnames.append(os.path.relpath(item.filename, + ml.model_ws)) ml.external_units.append(key) ml.external_binflag.append("binary" in item.filetype.lower()) From 84a724d1ad6097ff5e52fed348f71c1e6355d689 Mon Sep 17 00:00:00 2001 From: jbellino-usgs Date: Thu, 20 Jun 2019 09:54:32 -0400 Subject: [PATCH 07/15] feat(ModflowFlwob): Add new autotest to check loading functionality. --- autotest/t041_test.py | 132 ++++++++++++++++++++++++++++-------------- 1 file changed, 89 insertions(+), 43 deletions(-) diff --git a/autotest/t041_test.py b/autotest/t041_test.py index 14a7366f2d..8a7b594739 100644 --- a/autotest/t041_test.py +++ b/autotest/t041_test.py @@ -217,7 +217,8 @@ def test_filenames(): pkglst = ['dis', 'bas6', 'pcg', 'lpf'] m = flopy.modflow.Modflow.load(modelname + '.nam', model_ws=pth, check=False, load_only=pkglst, - verbose=False, exe_name=exe_name) + verbose=False, exe_name=exe_name, + forgive=False) obs = flopy.modflow.HeadObservation(m, layer=0, row=5, column=5, time_series_data=[[1., 54.4], @@ -229,48 +230,6 @@ def test_filenames(): obs_data=[obs], options=['NOPRINT'], filenames=filenames) - - # add DRN package - spd = {0: [[0, 5, 5, .5, 8e6], - [0, 8, 8, .7, 8e6]]} - drn = flopy.modflow.ModflowDrn(m, 53, stress_period_data=spd) - - # flow observation - - # Lists of length nqfb - nqobfb = [1, 1] - nqclfb = [1, 1] - - # Lists of length nqtfb - obsnam = ['drob_1', 'drob_2'] - irefsp = [0, 0] - toffset = [0, 0] - flwobs = [0., 0.] - - # Lists of length (nqfb, nqclfb) - layer = [[0], [0]] - row = [[5], [8]] - column = [[5], [8]] - factor = [[1.], [1.]] - - drob = flopy.modflow.ModflowFlwob(m, - nqfb=len(nqclfb), - nqcfb=np.sum(nqclfb), - nqtfb=np.sum(nqobfb), - nqobfb=nqobfb, - nqclfb=nqclfb, - obsnam=obsnam, - irefsp=irefsp, - toffset=toffset, - flwobs=flwobs, - layer=layer, - row=row, - column=column, - factor=factor, - flowtype='drn', - options=['NOPRINT'], - filenames=['flwobs_simple.drob', - 'flwobs_simple.obd']) # Write the model input files m.write_input() @@ -315,8 +274,95 @@ def test_multilayerhob_prfail(): return +def test_flwob_load(): + """ + test041 create, write, and load ModflowFlwob package. + """ + # load the modflow model + opth = os.path.join(cpth, 'tc1-true', 'orig') + m = flopy.modflow.Modflow.load('tc1-true.nam', verbose=True, + model_ws=opth, exe_name=exe_name) + + npth = os.path.join(cpth, 'tc1-true', 'flwob') + m.change_model_ws(new_pth=npth, reset_external=True) + + # write the lgr model in to the new path + m.write_input() + + # add DRN package + spd = {0: [[0, 5, 5, .5, 8e6], + [0, 8, 8, .7, 8e6]]} + drn = flopy.modflow.ModflowDrn(m, 53, stress_period_data=spd) + + # flow observation + + # Lists of length nqfb + nqobfb = [1, 1] + nqclfb = [1, 1] + + # Lists of length nqtfb + obsnam = ['drob_1', 'drob_2'] + irefsp = [0, 0] + toffset = [0, 0] + flwobs = [-5.678, -6.874] + + # Lists of length (nqfb, nqclfb) + layer = [[0], [0]] + row = [[5], [8]] + column = [[5], [8]] + factor = [[1.], [1.]] + + drob = flopy.modflow.ModflowFlwob(m, + nqfb=len(nqclfb), + nqcfb=np.sum(nqclfb), + nqtfb=np.sum(nqobfb), + nqobfb=nqobfb, + nqclfb=nqclfb, + obsnam=obsnam, + irefsp=irefsp, + toffset=toffset, + flwobs=flwobs, + layer=layer, + row=row, + column=column, + factor=factor, + flowtype='drn', + options=['NOPRINT']) + # Write the model input files + m.write_input(check=False) + + # Load the DROB package and compare it to the original + pkglst = ['drob'] + m = flopy.modflow.Modflow.load('tc1-true.nam', model_ws=npth, + check=False, load_only=pkglst, + verbose=False, exe_name=exe_name, + forgive=False) + + # check variables were read properly + s = 'nqfb loaded from {} read incorrectly'.format(m.drob.fn_path) + assert(drob.nqfb == m.drob.nqfb), s + s = 'nqcfb loaded from {} read incorrectly'.format(m.drob.fn_path) + assert (drob.nqcfb == m.drob.nqcfb), s + s = 'nqtfb loaded from {} read incorrectly'.format(m.drob.fn_path) + assert (drob.nqtfb == m.drob.nqtfb), s + s = 'obsnam loaded from {} read incorrectly'.format(m.drob.fn_path) + assert (list([n for n in drob.obsnam]) == + list([n for n in m.drob.obsnam])), s + s = 'flwobs loaded from {} read incorrectly'.format(m.drob.fn_path) + assert np.array_equal(drob.flwobs, m.drob.flwobs), s + s = 'layer loaded from {} read incorrectly'.format(m.drob.fn_path) + assert np.array_equal(drob.layer, m.drob.layer), s + s = 'row loaded from {} read incorrectly'.format(m.drob.fn_path) + assert np.array_equal(drob.row, m.drob.row), s + s = 'column loaded from {} read incorrectly'.format(m.drob.fn_path) + assert np.array_equal(drob.column, m.drob.column), s + + return + + if __name__ == '__main__': test_hob_simple() test_obs_create_and_write() test_obs_load_and_write() test_filenames() + test_flwob_load() From bf8f0be70d437977697e5e65012ac0d8d068b3a2 Mon Sep 17 00:00:00 2001 From: jbellino-usgs Date: Thu, 20 Jun 2019 10:40:43 -0400 Subject: [PATCH 08/15] revert: "feat(ModflowFlwob): Append filename using relative path with respect to the model working directory to ensure the correct filename is written to the namefile." This reverts commit 6f520064a5e7dc856b177cd567668f712866117e. --- flopy/modflow/mf.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/flopy/modflow/mf.py b/flopy/modflow/mf.py index 043a3387a2..a930539565 100644 --- a/flopy/modflow/mf.py +++ b/flopy/modflow/mf.py @@ -825,8 +825,7 @@ def load(f, version='mf2005', exe_name='mf2005.exe', verbose=False, if key not in ml.pop_key_list: # do not add unit number (key) if it already exists if key not in ml.external_units: - ml.external_fnames.append(os.path.relpath(item.filename, - ml.model_ws)) + ml.external_fnames.append(item.filename) ml.external_units.append(key) ml.external_binflag.append("binary" in item.filetype.lower()) From 4adf51fbd95f54e91b83395f70aaa466d5af5a78 Mon Sep 17 00:00:00 2001 From: jbellino-usgs Date: Thu, 20 Jun 2019 11:55:08 -0400 Subject: [PATCH 09/15] feat(ModflowFlwob): Add 1 to zero-based "irefsp" when writing file. --- flopy/modflow/mfflwob.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/flopy/modflow/mfflwob.py b/flopy/modflow/mfflwob.py index 7498849143..acabff359e 100755 --- a/flopy/modflow/mfflwob.py +++ b/flopy/modflow/mfflwob.py @@ -303,7 +303,7 @@ def write_file(self): for j in range(self.nqobfb[i]): # write section 4 line = '{:12}'.format(self.obsnam[c]) - line += '{:8d}'.format(self.irefsp[c]) + line += '{:8d}'.format(self.irefsp[c] + 1) line += '{:16.10g}'.format(self.toffset[c]) line += ' {:10.4g}\n'.format(self.flwobs[c]) f_fbob.write(line) From eca305aba1e1b8b4731c6413476f061c8c393492 Mon Sep 17 00:00:00 2001 From: jbellino-usgs Date: Thu, 20 Jun 2019 12:41:24 -0400 Subject: [PATCH 10/15] feat(ModflowFlwob): Try to make Codacy happy. --- flopy/modflow/mfflwob.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/flopy/modflow/mfflwob.py b/flopy/modflow/mfflwob.py index acabff359e..3e10609fe5 100755 --- a/flopy/modflow/mfflwob.py +++ b/flopy/modflow/mfflwob.py @@ -506,7 +506,7 @@ def load(f, model, flowtype=None, ext_unit_dict=None, check=True): model.get_ext_dict_attr(ext_unit_dict, filetype=ext.upper()) if iufbobsv > 0: - iu, filenames[1] = \ + _, filenames[1] = \ model.get_ext_dict_attr(ext_unit_dict, unit=iufbobsv) model.add_pop_key_list(iufbobsv) From d11fbca72cb7437f23e9cb5166300f86762f6dc7 Mon Sep 17 00:00:00 2001 From: jbellino-usgs Date: Mon, 24 Jun 2019 12:06:56 -0400 Subject: [PATCH 11/15] feat(ModflowFlwob): Add "ftype" attribute and retrieval method. --- flopy/modflow/mfflwob.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/flopy/modflow/mfflwob.py b/flopy/modflow/mfflwob.py index 3e10609fe5..55ea5ec1f0 100755 --- a/flopy/modflow/mfflwob.py +++ b/flopy/modflow/mfflwob.py @@ -152,6 +152,7 @@ def __init__(self, model, nqfb=0, nqcfb=0, nqtfb=0, iufbobsv=0, extension = extension[0:2] # unitnumber = unitnumber[0:2] # iufbobsv = unitnumber[1] + self._ftype = 'CHOB' self.url = 'chob.htm' self.heading = '# CHOB for MODFLOW, generated by Flopy.' elif flowtype.upper().strip() == 'GHB': @@ -159,6 +160,7 @@ def __init__(self, model, nqfb=0, nqcfb=0, nqtfb=0, iufbobsv=0, extension = extension[2:4] # unitnumber = unitnumber[2:4] # iufbobsv = unitnumber[1] + self._ftype = 'GBOB' self.url = 'gbob.htm' self.heading = '# GBOB for MODFLOW, generated by Flopy.' elif flowtype.upper().strip() == 'DRN': @@ -166,6 +168,7 @@ def __init__(self, model, nqfb=0, nqcfb=0, nqtfb=0, iufbobsv=0, extension = extension[4:6] # unitnumber = unitnumber[4:6] # iufbobsv = unitnumber[1] + self._ftype = 'DROB' self.url = 'drob.htm' self.heading = '# DROB for MODFLOW, generated by Flopy.' elif flowtype.upper().strip() == 'RIV': @@ -173,6 +176,7 @@ def __init__(self, model, nqfb=0, nqcfb=0, nqtfb=0, iufbobsv=0, extension = extension[6:8] # unitnumber = unitnumber[6:8] # iufbobsv = unitnumber[1] + self._ftype = 'RVOB' self.url = 'rvob.htm' self.heading = '# RVOB for MODFLOW, generated by Flopy.' else: @@ -265,6 +269,9 @@ def __init__(self, model, nqfb=0, nqcfb=0, nqtfb=0, iufbobsv=0, # add checks for input compliance (obsnam length, etc.) self.parent.add_package(self) + def ftype(self): + return self._ftype + def write_file(self): """ Write the package file From d336b418e10908f6c8b479369169af7ab79a2dcd Mon Sep 17 00:00:00 2001 From: jbellino-usgs Date: Mon, 24 Jun 2019 13:47:43 -0400 Subject: [PATCH 12/15] feat(ModflowFlwob): Use ext_unit_dict to get proper flowtype and ftype from filename. --- flopy/modflow/mfflwob.py | 95 ++++++++++++++++++++++++++++++---------- 1 file changed, 72 insertions(+), 23 deletions(-) diff --git a/flopy/modflow/mfflwob.py b/flopy/modflow/mfflwob.py index 55ea5ec1f0..c0cdbc3f4a 100755 --- a/flopy/modflow/mfflwob.py +++ b/flopy/modflow/mfflwob.py @@ -1,6 +1,8 @@ +import os import sys import numpy as np from ..pakbase import Package +from ..utils import parsenamefile class ModflowFlwob(Package): @@ -350,7 +352,7 @@ def write_file(self): return @staticmethod - def load(f, model, flowtype=None, ext_unit_dict=None, check=True): + def load(f, model, ext_unit_dict=None, check=True): """ Load an existing package. @@ -391,27 +393,6 @@ def load(f, model, flowtype=None, ext_unit_dict=None, check=True): filename = f f = open(filename, 'r') - ext = None - if flowtype is None: - # attempt to infer flowtype - ext = f.name.split('.')[-1].lower() - if 'ch' in ext.lower(): - ext = 'chob' - flowtype = 'CHD' - elif 'gb' in ext.lower(): - ext = 'gbob' - flowtype = 'GHB' - elif 'dr' in ext.lower(): - ext = 'drob' - flowtype = 'DRN' - elif 'rv' in ext.lower(): - ext = 'rvob' - flowtype = 'RIV' - else: - msg = 'ModflowFlwob: flowtype cannot be inferred ' \ - 'from file name {}'.format(f.name) - raise KeyError(msg) - # dataset 0 -- header while True: line = f.readline() @@ -505,13 +486,20 @@ def load(f, model, flowtype=None, ext_unit_dict=None, check=True): # close the file f.close() + # get ext_unit_dict if none passed + if ext_unit_dict is None: + namefile = os.path.join(model.model_ws, model.namefile) + ext_unit_dict = parsenamefile(namefile, model.mfnam_packages) + + flowtype, ftype = _get_ftype_from_filename(f.name, ext_unit_dict) + # set package unit number unitnumber = None filenames = [None, None] if ext_unit_dict is not None: unitnumber, filenames[0] = \ model.get_ext_dict_attr(ext_unit_dict, - filetype=ext.upper()) + filetype=ftype.upper()) if iufbobsv > 0: _, filenames[1] = \ model.get_ext_dict_attr(ext_unit_dict, unit=iufbobsv) @@ -528,3 +516,64 @@ def load(f, model, flowtype=None, ext_unit_dict=None, check=True): filenames=filenames) return flwob + + +def _get_ftype_from_filename(fn, ext_unit_dict=None): + """ + Returns the boundary flowtype and filetype for a given ModflowFlwob + package filename. + + Parameters + ---------- + fn : str + The filename to be parsed. + ext_unit_dict : dictionary, optional + If the arrays in the file are specified using EXTERNAL, + or older style array control records, then `f` should be a file + handle. In this case ext_unit_dict is required, which can be + constructed using the function + :class:`flopy.utils.mfreadnam.parsenamefile`. + + Returns + ------- + flowtype : str + Corresponds to the type of the head-dependent boundary package for + which observations are desired (e.g. "CHD", "GHB", "DRN", or "RIV"). + ftype : str + Corresponds to the observation file type (e.g. "CHOB", "GBOB", + "DROB", or "RVOB"). + """ + + ftype = None + + # determine filetype from filename using ext_unit_dict + if ext_unit_dict is not None: + for k, v in ext_unit_dict.items(): + if v.filename == fn : + ftype = v.filetype + break + + # else, try to infer filetype from filename extension + else: + ext = fn.split('.')[-1].lower() + if 'ch' in ext.lower(): + ftype = 'CHOB' + elif 'gb' in ext.lower(): + ftype = 'GBOB' + elif 'dr' in ext.lower(): + ftype = 'DROB' + elif 'rv' in ext.lower(): + ftype = 'RVOB' + + msg = 'ModflowFlwob: filetype cannot be inferred ' \ + 'from file name {}'.format(fn) + if ftype is None: + raise AssertionError(msg) + + flowtype_dict = {'CHOB': 'CHD', + 'GOBO': 'GHB', + 'DROB': 'DRN', + 'RVOB': 'RIV'} + flowtype = flowtype_dict[ftype] + + return flowtype, ftype From 0934c121b994dacec55b7a1a93b7461e7a4a7069 Mon Sep 17 00:00:00 2001 From: jbellino-usgs Date: Mon, 24 Jun 2019 14:34:33 -0400 Subject: [PATCH 13/15] feat(ModflowFlwob): Remove unused variable and extra whitespace. --- flopy/modflow/mfflwob.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/flopy/modflow/mfflwob.py b/flopy/modflow/mfflwob.py index c0cdbc3f4a..191d6f0498 100755 --- a/flopy/modflow/mfflwob.py +++ b/flopy/modflow/mfflwob.py @@ -548,8 +548,8 @@ def _get_ftype_from_filename(fn, ext_unit_dict=None): # determine filetype from filename using ext_unit_dict if ext_unit_dict is not None: - for k, v in ext_unit_dict.items(): - if v.filename == fn : + for _, v in ext_unit_dict.items(): + if v.filename == fn: ftype = v.filetype break From 47514fa73b673ad43e04b5fc73c106aff1f32e80 Mon Sep 17 00:00:00 2001 From: jbellino-usgs Date: Mon, 24 Jun 2019 15:38:22 -0400 Subject: [PATCH 14/15] feat(ModflowFlwob): Catch dict items explicitly even if they are unused. --- flopy/modflow/mfflwob.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/flopy/modflow/mfflwob.py b/flopy/modflow/mfflwob.py index 191d6f0498..696554b920 100755 --- a/flopy/modflow/mfflwob.py +++ b/flopy/modflow/mfflwob.py @@ -548,9 +548,9 @@ def _get_ftype_from_filename(fn, ext_unit_dict=None): # determine filetype from filename using ext_unit_dict if ext_unit_dict is not None: - for _, v in ext_unit_dict.items(): - if v.filename == fn: - ftype = v.filetype + for key, value in ext_unit_dict.items(): + if value.filename == fn: + ftype = value.filetype break # else, try to infer filetype from filename extension From df3f5e276fe1c0dcbcff1b41df3dcc660842b791 Mon Sep 17 00:00:00 2001 From: jbellino-usgs Date: Mon, 24 Jun 2019 15:38:58 -0400 Subject: [PATCH 15/15] Revert "feat(ModflowFlwob): Try to make Codacy happy." This reverts commit eca305ab. --- flopy/modflow/mfflwob.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/flopy/modflow/mfflwob.py b/flopy/modflow/mfflwob.py index 696554b920..beeb08f28d 100755 --- a/flopy/modflow/mfflwob.py +++ b/flopy/modflow/mfflwob.py @@ -501,7 +501,7 @@ def load(f, model, ext_unit_dict=None, check=True): model.get_ext_dict_attr(ext_unit_dict, filetype=ftype.upper()) if iufbobsv > 0: - _, filenames[1] = \ + iu, filenames[1] = \ model.get_ext_dict_attr(ext_unit_dict, unit=iufbobsv) model.add_pop_key_list(iufbobsv)