Skip to content

Commit

Permalink
fix(paths): Path code made more robust so that non-standard model fol…
Browse files Browse the repository at this point in the history
…der structures are supported (#1311) (#1316)

* fix(paths): Path code made more robust so that non-standard model folder structures are supported.  There are three basic path times, the path to the simulation, model relative paths to particular models in the simulation, and package/data relative paths to package or data files in a model or simulation. Model relative paths are relative to the simulation path.  Package/data relative paths are relative to the simulation path for packages/data not attached to a model and relative to model relative path for packages/data attached to a model. (#1311)

* test(paths): added more comprehensive testing of paths

Co-authored-by: Scott Paulinski <spaulinski@usgs.gov>
  • Loading branch information
scottrp and spaulins-usgs committed Dec 9, 2021
1 parent 8ab2e8d commit 0432ce9
Show file tree
Hide file tree
Showing 6 changed files with 187 additions and 41 deletions.
64 changes: 52 additions & 12 deletions autotest/t505_test.py
Expand Up @@ -811,6 +811,7 @@ def test_np001():
}
wel_package = ModflowGwfwel(
model,
filename=f"well_folder\\{model_name}.wel",
print_input=True,
print_flows=True,
save_flows=True,
Expand Down Expand Up @@ -841,7 +842,7 @@ def test_np001():

riv_spd = {
0: {
"filename": "riv.txt",
"filename": os.path.join("riv_folder", "riv.txt"),
"data": [((0, 0, 9), 110, 90.0, 100.0, 1.0, 2.0, 3.0)],
}
}
Expand Down Expand Up @@ -914,6 +915,12 @@ def test_np001():
assert (
sim.simulation_data.max_columns_of_data == dis_package.ncol.get_data()
)
# test package file with relative path to simulation path
wel_path = os.path.join(run_folder, "well_folder", f"{model_name}.wel")
assert os.path.exists(wel_path)
# test data file with relative path to simulation path
riv_path = os.path.join(run_folder, "riv_folder", "riv.txt")
assert os.path.exists(riv_path)

# run simulation
if run:
Expand Down Expand Up @@ -950,6 +957,17 @@ def test_np001():
sim.set_all_data_external(external_data_folder="data")
sim.write_simulation()

# test file with relative path to model relative path
wel_path = os.path.join(
run_folder, md_folder, "well_folder", f"{model_name}.wel"
)
assert os.path.exists(wel_path)
# test data file was recreated by set_all_data_external
riv_path = os.path.join(
run_folder, md_folder, "data", "np001_mod.riv_stress_period_data_1.txt"
)
assert os.path.exists(riv_path)

assert (
sim.simulation_data.max_columns_of_data == dis_package.ncol.get_data()
)
Expand All @@ -974,7 +992,6 @@ def test_np001():
outfile=outfile,
)

# budget_frf = sim.simulation_data.mfdata[(model_name, "CBC", "RIV")]
budget_frf = model.output.budget().get_data(text="RIV", full3D=False)
assert array_util.riv_array_comp(budget_frf_valid, budget_frf)

Expand Down Expand Up @@ -1090,14 +1107,15 @@ def test_np001():
well_spd = {0: [(-1, -1, -1, -2000.0), (0, 0, 7, -2.0)], 1: []}
wel_package = ModflowGwfwel(
model,
pname="wel_1",
filename="file_rename.wel",
print_input=True,
print_flows=True,
save_flows=True,
maxbound=2,
stress_period_data=well_spd,
)
wel_package.write()
sim.write_simulation()
found_begin = False
found_end = False
text_between_begin_and_end = False
Expand All @@ -1121,7 +1139,7 @@ def test_np001():
spath,
write_headers=False,
)
wel = test_sim.get_model().wel
wel = test_sim.get_model().get_package("wel_1")
wel._filename = "np001_spd_test.wel"
wel.write()
found_begin = False
Expand Down Expand Up @@ -1778,7 +1796,7 @@ def test005_advgw_tidal():
(31.0, 0.0, -600.0, -400.0),
]
ts_dict = {
"filename": "well-rates.ts",
"filename": os.path.join("well-rates", "well-rates.ts"),
"timeseries": timeseries,
"time_series_namerecord": [
("well_1_rate", "well_2_rate", "well_3_rate")
Expand Down Expand Up @@ -2160,6 +2178,10 @@ def test005_advgw_tidal():
sim.set_all_data_external()
sim.write_simulation()

# test time series data file with relative path to simulation path
ts_path = os.path.join(run_folder, "well-rates", "well-rates.ts")
assert os.path.exists(ts_path)

# run simulation
sim.run_simulation()

Expand All @@ -2180,22 +2202,24 @@ def test005_advgw_tidal():
package_type_dict = {}
for package in model.packagelist:
if not package.package_type in package_type_dict:
assert package.filename == f"new_name.{package.package_type}"
filename = os.path.split(package.filename)[1]
assert filename == f"new_name.{package.package_type}"
package_type_dict[package.package_type] = 1
sim.write_simulation()
name_file = os.path.join(run_folder, "new_name.nam")
assert os.path.exists(name_file)
dis_file = os.path.join(run_folder, "new_name.dis")
assert os.path.exists(dis_file)
# test time series data file with relative path to simulation path
ts_path = os.path.join(run_folder, "well-rates", "new_name.ts")
assert os.path.exists(ts_path)

sim.rename_all_packages("all_files_same_name")
package_type_dict = {}
for package in model.packagelist:
if not package.package_type in package_type_dict:
assert (
package.filename
== f"all_files_same_name.{package.package_type}"
)
filename = os.path.split(package.filename)[1]
assert filename == f"all_files_same_name.{package.package_type}"
package_type_dict[package.package_type] = 1
assert sim._tdis_file.filename == "all_files_same_name.tdis"
for ims_file in sim._ims_files.values():
Expand All @@ -2207,6 +2231,9 @@ def test005_advgw_tidal():
assert os.path.exists(dis_file)
tdis_file = os.path.join(run_folder, "all_files_same_name.tdis")
assert os.path.exists(tdis_file)
# test time series data file with relative path to simulation path
ts_path = os.path.join(run_folder, "well-rates", "all_files_same_name.ts")
assert os.path.exists(ts_path)

# load simulation
sim_load = MFSimulation.load(
Expand Down Expand Up @@ -3073,13 +3100,14 @@ def test006_2models_gnc():

# test exg delete
newexgrecarray = exgrecarray[10:]
gnc_path = os.path.join("gnc", "test006_2models_gnc.gnc")
exg_package = ModflowGwfgwf(
sim,
print_input=True,
print_flows=True,
save_flows=True,
auxiliary="testaux",
gnc_filerecord="test006_2models_gnc.gnc",
gnc_filerecord=gnc_path,
nexg=26,
exchangedata=newexgrecarray,
exgtype="gwf6-gwf6",
Expand All @@ -3094,7 +3122,7 @@ def test006_2models_gnc():
print_flows=True,
save_flows=True,
auxiliary="testaux",
gnc_filerecord="test006_2models_gnc.gnc",
gnc_filerecord=gnc_path,
nexg=36,
exchangedata=exgrecarray,
exgtype="gwf6-gwf6",
Expand All @@ -3108,6 +3136,7 @@ def test006_2models_gnc():
new_gncrecarray = gncrecarray[10:]
gnc_package = ModflowGwfgnc(
sim,
filename=gnc_path,
print_input=True,
print_flows=True,
numgnc=26,
Expand All @@ -3118,6 +3147,7 @@ def test006_2models_gnc():

gnc_package = ModflowGwfgnc(
sim,
filename=gnc_path,
print_input=True,
print_flows=True,
numgnc=36,
Expand All @@ -3131,6 +3161,10 @@ def test006_2models_gnc():
# write simulation to new location
sim.write_simulation()

# test gnc file was created in correct location
gnc_full_path = os.path.join(run_folder, gnc_path)
assert os.path.exists(gnc_full_path)

# run simulation
if run:
sim.run_simulation()
Expand Down Expand Up @@ -3172,6 +3206,9 @@ def test006_2models_gnc():
sim_path, "model2", "data", "model2.dis_botm.txt"
)
assert os.path.exists(ext_file_path_2)
# test gnc file was created in correct location
gnc_full_path = os.path.join(sim_path, gnc_path)
assert os.path.exists(gnc_full_path)
if run:
sim.run_simulation()

Expand All @@ -3183,6 +3220,9 @@ def test006_2models_gnc():
sim.rename_all_packages("file_rename")
sim.set_sim_path(rename_folder)
sim.write_simulation()
# test gnc file was created in correct location
gnc_full_path = os.path.join(rename_folder, "gnc", "file_rename.gnc")
assert os.path.exists(gnc_full_path)
if run:
sim.run_simulation()
sim.delete_output_files()
Expand Down
6 changes: 6 additions & 0 deletions flopy/mf6/data/mfdatastorage.py
Expand Up @@ -1552,6 +1552,12 @@ def store_external(
precision="double",
)
else:
# make sure folder exists
file_path = os.path.split(fp)[0]
if not os.path.exists(file_path):
os.makedirs(file_path)

# create file
try:
fd = open(fp, "w")
except:
Expand Down
24 changes: 15 additions & 9 deletions flopy/mf6/mfbase.py
Expand Up @@ -270,17 +270,23 @@ def _build_relative_path(self, model_name):
def strip_model_relative_path(self, model_name, path):
"""Strip out the model relative path part of `path`. For internal
FloPy use, not intended for end user."""
new_path = path
if model_name in self.model_relative_path:
model_rel_path = self.model_relative_path[model_name]
new_path = None
while path:
path, leaf = os.path.split(path)
if leaf != model_rel_path:
if new_path:
new_path = os.path.join(leaf, new_path)
else:
new_path = leaf
return new_path
if (
model_rel_path is not None
and len(model_rel_path) > 0
and model_rel_path != "."
):
model_rel_path_lst = model_rel_path.split(os.path.sep)
path_lst = path.split(os.path.sep)
new_path = ""
for i, mrp in enumerate(model_rel_path_lst):
if mrp != path_lst[i]:
new_path = os.path.join(new_path, path_lst[i])
for rp in path_lst[len(model_rel_path_lst) :]:
new_path = os.path.join(new_path, rp)
return new_path

@staticmethod
def unique_file_name(file_name, lookup):
Expand Down
40 changes: 32 additions & 8 deletions flopy/mf6/mfmodel.py
Expand Up @@ -1045,10 +1045,24 @@ def set_model_relative_path(self, model_ws):
packages_data = packages.get_data()
if packages_data is not None:
for index, entry in enumerate(packages_data):
old_package_name = os.path.split(entry[1])[1]
packages_data[index][1] = os.path.join(
path, old_package_name
)
# get package object associated with entry
package = None
if len(entry) >= 3:
package = self.get_package(entry[2])
if package is None:
package = self.get_package(entry[0])
if package is not None:
# combine model relative path with package path
packages_data[index][1] = os.path.join(
path, package.filename
)
else:
# package not found, create path based on
# information in name file
old_package_name = os.path.split(entry[1])[-1]
packages_data[index][1] = os.path.join(
path, old_package_name
)
packages.set_data(packages_data)
# update files referenced from within packages
for package in self.packagelist:
Expand Down Expand Up @@ -1186,12 +1200,15 @@ def update_package_filename(self, package, new_name):
message=message,
)
try:
file_mgr = self.simulation_data.mfpath
model_rel_path = file_mgr.model_relative_path[self.name]
# update namefile package data with new name
new_rec_array = None
old_leaf = os.path.split(package.filename)[1]
for item in package_data:
base, leaf = os.path.split(item[1])
if leaf == package.filename:
item[1] = os.path.join(base, new_name)
leaf = os.path.split(item[1])[1]
if leaf == old_leaf:
item[1] = os.path.join(model_rel_path, new_name)

if new_rec_array is None:
new_rec_array = np.rec.array(
Expand Down Expand Up @@ -1246,7 +1263,14 @@ def rename_all_packages(self, name):
package_type_count = {}
for package in self.packagelist:
if package.package_type not in package_type_count:
package.filename = f"{name}.{package.package_type}"
base_filename, leaf = os.path.split(package.filename)
new_fileleaf = f"{name}.{package.package_type}"
if base_filename != "":
package.filename = os.path.join(
base_filename, new_fileleaf
)
else:
package.filename = new_fileleaf
package_type_count[package.package_type] = 1
else:
package_type_count[package.package_type] += 1
Expand Down

0 comments on commit 0432ce9

Please sign in to comment.