Skip to content

Commit 838b37c

Browse files
authored
fix(model_splitter.py): add trap for obs packages in bc packages (#2493)
* fix(model_splitter.py): add trap for obs packages in standard bc packages * fix indexing error in observation remapping routine * update testing syntax for ruff * change testing syntax for ruff * update test_package_observations
1 parent e546a2c commit 838b37c

File tree

2 files changed

+131
-3
lines changed

2 files changed

+131
-3
lines changed

autotest/test_model_splitter.py

+109
Original file line numberDiff line numberDiff line change
@@ -1489,3 +1489,112 @@ def test_timeseries(function_tmpdir):
14891489

14901490
if not success:
14911491
raise AssertionError("Timeseries split simulation did not properly run")
1492+
1493+
1494+
def test_package_observations():
1495+
XL = 10000
1496+
YL = 10500
1497+
dx = dy = 500
1498+
nlay = 3
1499+
nrow = int(YL / dy)
1500+
ncol = int(XL / dx)
1501+
1502+
delc = np.full((nrow,), dy)
1503+
delr = np.full((ncol,), dx)
1504+
1505+
top = np.full((nrow, ncol), 330)
1506+
1507+
botm = np.zeros((nlay, nrow, ncol))
1508+
botm[0] = 220
1509+
botm[1] = 200
1510+
botm[2] = 0
1511+
1512+
sim = flopy.mf6.MFSimulation()
1513+
ims = flopy.mf6.ModflowIms(sim, complexity="SIMPLE")
1514+
tdis = flopy.mf6.ModflowTdis(sim)
1515+
1516+
gwf = flopy.mf6.ModflowGwf(sim, modelname="ps1a_mod")
1517+
1518+
dis = flopy.mf6.ModflowGwfdis(
1519+
gwf,
1520+
nlay=nlay,
1521+
nrow=nrow,
1522+
ncol=ncol,
1523+
delr=delr,
1524+
delc=delc,
1525+
top=top,
1526+
botm=botm,
1527+
idomain=np.ones(botm.shape, dtype=int),
1528+
)
1529+
1530+
ic = flopy.mf6.ModflowGwfic(gwf, strt=330)
1531+
1532+
npf = flopy.mf6.ModflowGwfnpf(
1533+
gwf, k=[50, 0.01, 200], k33=[10, 0.01, 20], icelltype=[1, 0, 0]
1534+
)
1535+
1536+
# build the CHD stress period data
1537+
records = []
1538+
for row in range(nrow):
1539+
rec = ((0, row, 0), 330)
1540+
records.append(rec)
1541+
1542+
for row in range(nrow):
1543+
rec = ((0, row, ncol - 1), 320)
1544+
records.append(rec)
1545+
1546+
spd = {0: records}
1547+
1548+
chd = flopy.mf6.ModflowGwfchd(gwf, stress_period_data=spd)
1549+
1550+
observations = {
1551+
"chd_obs_out.csv": [
1552+
("C1", "chd", (0, 4, 0)), # 80 (end up as same)
1553+
("C2", "chd", (0, 16, 0)), # 320 (end up as m2 120)
1554+
("R1", "chd", (0, 3, 19)), # 79 (end up as same)
1555+
("R2", "chd", (0, 20, 19)), # 419 (end up as m2 219)
1556+
]
1557+
}
1558+
1559+
# do observations on the chd package!!!!
1560+
obs = flopy.mf6.ModflowUtlobs(
1561+
chd,
1562+
continuous=observations,
1563+
)
1564+
1565+
# now do model splitter???
1566+
array = np.ones((nrow, ncol), dtype=int)
1567+
split_loc = ncol // 2
1568+
array[split_loc:, :] = 2
1569+
1570+
mfs = flopy.mf6.utils.Mf6Splitter(sim)
1571+
new_sim = mfs.split_model(array)
1572+
1573+
gwf1 = new_sim.get_model("ps1a_mod_1")
1574+
gwf2 = new_sim.get_model("ps1a_mod_2")
1575+
1576+
obsdata1 = gwf1.obs.continuous.data["chd_obs_out_1.csv"]
1577+
obsdata2 = gwf2.obs.continuous.data["chd_obs_out_2.csv"]
1578+
1579+
vdict1 = {"C1": (0, 4, 0), "R1": (0, 3, 19)}
1580+
vdict2 = {"C2": (0, 6, 0), "R2": (0, 10, 19)}
1581+
1582+
for row in obsdata1:
1583+
obsname = row.obsname
1584+
cellid = row.id
1585+
if obsname not in vdict1:
1586+
raise AssertionError("Observations not correctly mapped to new model")
1587+
1588+
vcid = vdict1[obsname]
1589+
if vcid != cellid:
1590+
raise AssertionError("Observation cellid not correctly mapped to new model")
1591+
1592+
for row in obsdata2:
1593+
obsname = row.obsname
1594+
cellid = row.id
1595+
if obsname not in vdict2:
1596+
raise AssertionError("Observations not correctly mapped to new model")
1597+
1598+
vcid = vdict2[obsname]
1599+
if vcid != cellid:
1600+
raise AssertionError("Observation cellid not correctly mapped to new model")

flopy/mf6/utils/model_splitter.py

+22-3
Original file line numberDiff line numberDiff line change
@@ -2735,11 +2735,11 @@ def _remap_obs(self, package, mapped_data, remapper, pkg_type=None):
27352735
dtype=object,
27362736
)
27372737
for mkey, model in self._model_dict.items():
2738-
idx = np.asarray(new_model1 == mkey).nonzero()
2738+
idx = np.asarray(new_model1 == mkey).nonzero()[0]
27392739
idx = [
27402740
ix
2741-
for ix, i in enumerate(recarray.id[idx])
2742-
if not isinstance(i, str)
2741+
for ix in idx
2742+
if not isinstance(recarray.id[ix], str)
27432743
]
27442744
tmp_cellid = self._new_node_to_cellid(
27452745
model, new_node1, layers1, idx
@@ -3382,9 +3382,28 @@ def _remap_package(self, package, ismvr=False):
33823382
"interpolation_methodrecord": tspkg.interpolation_methodrecord.array["interpolation_method"][0]
33833383
}
33843384
mapped_data[mkey]["timeseries"] = tsdict
3385+
33853386
else:
33863387
pass
33873388

3389+
if hasattr(package, "obs"):
3390+
obs_map = {"cellid": self._node_map}
3391+
for mkey, mdict in mapped_data.items():
3392+
if "stress_period_data" in mdict:
3393+
for _, ra in mdict["stress_period_data"].items():
3394+
if isinstance(ra, dict):
3395+
continue
3396+
obs_map = self._set_boundname_remaps(
3397+
ra, obs_map, list(obs_map.keys()), mkey
3398+
)
3399+
for obspak in package.obs._packages:
3400+
mapped_data = self._remap_obs(
3401+
obspak,
3402+
mapped_data,
3403+
obs_map["cellid"],
3404+
pkg_type=package.package_type,
3405+
)
3406+
33883407
observations = mapped_data.pop("observations", None)
33893408

33903409
if "options" in package.blocks:

0 commit comments

Comments
 (0)