|
| 1 | +""" |
| 2 | +A simple test of multiple UZF objects within a cell. |
| 3 | +The fourth sub-test is designed to fail. An assert statement |
| 4 | +ensure this to be the case. |
| 5 | +""" |
| 6 | + |
| 7 | +import flopy |
| 8 | +import numpy as np |
| 9 | +import pytest |
| 10 | + |
| 11 | +from framework import TestFramework |
| 12 | + |
| 13 | +cases = ["uzauxmlt-1to1", "uzauxmlt-2to1", "uzauxmlt-3to1", "uzauxmlt-bad"] |
| 14 | +uzarea_correspondences = ("1to1", "2to1", "3to1", "bad") |
| 15 | +iuz_cell_dict = {} |
| 16 | +cell_iuz_dict = {} |
| 17 | + |
| 18 | +nouter, ninner = 100, 300 |
| 19 | +hclose, rclose, relax = 1e-9, 1e-3, 0.97 |
| 20 | + |
| 21 | +uzarea_data = { |
| 22 | + uzarea_correspondences[0]: { |
| 23 | + "uzf_pkdat": [ |
| 24 | + [0, (0, 0, 3), 1, -1, 1.0, 1e-5, 0.2, 0.3, 0.25, 3.5, "uzf01"], |
| 25 | + [1, (0, 0, 4), 1, -1, 1.0, 1e-5, 0.2, 0.3, 0.25, 3.5, "uzf02"], |
| 26 | + [2, (0, 0, 5), 1, -1, 1.0, 1e-5, 0.2, 0.3, 0.25, 3.5, "uzf03"], |
| 27 | + [3, (0, 0, 6), 1, -1, 1.0, 1e-5, 0.2, 0.3, 0.25, 3.5, "uzf04"], |
| 28 | + ], |
| 29 | + "auxmultval": 1.0, |
| 30 | + }, |
| 31 | + uzarea_correspondences[1]: { |
| 32 | + "uzf_pkdat": [ |
| 33 | + [0, (0, 0, 3), 1, -1, 1.0, 1e-5, 0.2, 0.3, 0.25, 3.5, "uzf01"], |
| 34 | + [1, (0, 0, 3), 1, -1, 1.0, 1e-5, 0.2, 0.3, 0.25, 3.5, "uzf01"], |
| 35 | + [2, (0, 0, 4), 1, -1, 1.0, 1e-5, 0.2, 0.3, 0.25, 3.5, "uzf02"], |
| 36 | + [3, (0, 0, 4), 1, -1, 1.0, 1e-5, 0.2, 0.3, 0.25, 3.5, "uzf02"], |
| 37 | + [4, (0, 0, 5), 1, -1, 1.0, 1e-5, 0.2, 0.3, 0.25, 3.5, "uzf03"], |
| 38 | + [5, (0, 0, 5), 1, -1, 1.0, 1e-5, 0.2, 0.3, 0.25, 3.5, "uzf03"], |
| 39 | + [6, (0, 0, 6), 1, -1, 1.0, 1e-5, 0.2, 0.3, 0.25, 3.5, "uzf04"], |
| 40 | + [7, (0, 0, 6), 1, -1, 1.0, 1e-5, 0.2, 0.3, 0.25, 3.5, "uzf04"], |
| 41 | + ], |
| 42 | + "auxmultval": 0.5, |
| 43 | + }, |
| 44 | + uzarea_correspondences[2]: { |
| 45 | + "uzf_pkdat": [ |
| 46 | + [0, (0, 0, 3), 1, -1, 1.0, 1e-5, 0.2, 0.3, 0.25, 3.5, "uzf01"], |
| 47 | + [1, (0, 0, 3), 1, -1, 1.0, 1e-5, 0.2, 0.3, 0.25, 3.5, "uzf01"], |
| 48 | + [2, (0, 0, 3), 1, -1, 1.0, 1e-5, 0.2, 0.3, 0.25, 3.5, "uzf01"], |
| 49 | + [3, (0, 0, 4), 1, -1, 1.0, 1e-5, 0.2, 0.3, 0.25, 3.5, "uzf02"], |
| 50 | + [4, (0, 0, 4), 1, -1, 1.0, 1e-5, 0.2, 0.3, 0.25, 3.5, "uzf02"], |
| 51 | + [5, (0, 0, 4), 1, -1, 1.0, 1e-5, 0.2, 0.3, 0.25, 3.5, "uzf02"], |
| 52 | + [6, (0, 0, 5), 1, -1, 1.0, 1e-5, 0.2, 0.3, 0.25, 3.5, "uzf03"], |
| 53 | + [7, (0, 0, 5), 1, -1, 1.0, 1e-5, 0.2, 0.3, 0.25, 3.5, "uzf03"], |
| 54 | + [8, (0, 0, 5), 1, -1, 1.0, 1e-5, 0.2, 0.3, 0.25, 3.5, "uzf03"], |
| 55 | + [9, (0, 0, 6), 1, -1, 1.0, 1e-5, 0.2, 0.3, 0.25, 3.5, "uzf04"], |
| 56 | + [10, (0, 0, 6), 1, -1, 1.0, 1e-5, 0.2, 0.3, 0.25, 3.5, "uzf04"], |
| 57 | + [11, (0, 0, 6), 1, -1, 1.0, 1e-5, 0.2, 0.3, 0.25, 3.5, "uzf04"], |
| 58 | + ], |
| 59 | + "auxmultval": 0.333, |
| 60 | + }, |
| 61 | + uzarea_correspondences[3]: { |
| 62 | + "uzf_pkdat": [ |
| 63 | + [0, (0, 0, 3), 1, -1, 1.0, 1e-5, 0.2, 0.3, 0.25, 3.5, "uzf01"], |
| 64 | + [1, (0, 0, 3), 1, -1, 1.0, 1e-5, 0.2, 0.3, 0.25, 3.5, "uzf01"], |
| 65 | + [2, (0, 0, 3), 1, -1, 1.0, 1e-5, 0.2, 0.3, 0.25, 3.5, "uzf01"], |
| 66 | + [3, (0, 0, 4), 1, -1, 1.0, 1e-5, 0.2, 0.3, 0.25, 3.5, "uzf02"], |
| 67 | + [4, (0, 0, 4), 1, -1, 1.0, 1e-5, 0.2, 0.3, 0.25, 3.5, "uzf02"], |
| 68 | + [5, (0, 0, 4), 1, -1, 1.0, 1e-5, 0.2, 0.3, 0.25, 3.5, "uzf02"], |
| 69 | + [6, (0, 0, 5), 1, -1, 1.0, 1e-5, 0.2, 0.3, 0.25, 3.5, "uzf03"], |
| 70 | + [7, (0, 0, 5), 1, -1, 1.0, 1e-5, 0.2, 0.3, 0.25, 3.5, "uzf03"], |
| 71 | + [8, (0, 0, 5), 1, -1, 1.0, 1e-5, 0.2, 0.3, 0.25, 3.5, "uzf03"], |
| 72 | + [9, (0, 0, 6), 1, -1, 1.0, 1e-5, 0.2, 0.3, 0.25, 3.5, "uzf04"], |
| 73 | + [10, (0, 0, 6), 1, -1, 1.0, 1e-5, 0.2, 0.3, 0.25, 3.5, "uzf04"], |
| 74 | + [11, (0, 0, 6), 1, -1, 1.0, 1e-5, 0.2, 0.3, 0.25, 3.5, "uzf04"], |
| 75 | + ], |
| 76 | + "auxmultval": 0.334, |
| 77 | + }, |
| 78 | +} |
| 79 | + |
| 80 | + |
| 81 | +def build_models(idx, test): |
| 82 | + name = cases[idx] |
| 83 | + uzarea_correspondence = uzarea_correspondences[idx] |
| 84 | + |
| 85 | + nlay, nrow, ncol = 3, 1, 10 |
| 86 | + nper = 1 |
| 87 | + perlen = [1.0] |
| 88 | + nstp = [1] |
| 89 | + tsmult = [1.0] |
| 90 | + |
| 91 | + delr = 100.0 |
| 92 | + delc = 100.0 |
| 93 | + strt = -9.0 |
| 94 | + |
| 95 | + tdis_rc = [] |
| 96 | + for i in range(nper): |
| 97 | + tdis_rc.append((perlen[i], nstp[i], tsmult[i])) |
| 98 | + |
| 99 | + # build MODFLOW 6 files |
| 100 | + ws = test.workspace |
| 101 | + sim = flopy.mf6.MFSimulation( |
| 102 | + sim_name=name, version="mf6", exe_name="mf6", sim_ws=ws |
| 103 | + ) |
| 104 | + |
| 105 | + # create tdis package |
| 106 | + flopy.mf6.ModflowTdis( |
| 107 | + sim, time_units="DAYS", nper=nper, perioddata=tdis_rc |
| 108 | + ) |
| 109 | + |
| 110 | + # create gwf model |
| 111 | + gwf = flopy.mf6.ModflowGwf( |
| 112 | + sim, modelname=name, newtonoptions="NEWTON", save_flows=True |
| 113 | + ) |
| 114 | + |
| 115 | + # create iterative model solution and register the gwf model with it |
| 116 | + ims = flopy.mf6.ModflowIms( |
| 117 | + sim, |
| 118 | + print_option="SUMMARY", |
| 119 | + complexity="MODERATE", |
| 120 | + outer_dvclose=hclose, |
| 121 | + outer_maximum=nouter, |
| 122 | + under_relaxation="DBD", |
| 123 | + inner_maximum=ninner, |
| 124 | + inner_dvclose=hclose, |
| 125 | + rcloserecord=rclose, |
| 126 | + linear_acceleration="BICGSTAB", |
| 127 | + scaling_method="NONE", |
| 128 | + reordering_method="NONE", |
| 129 | + relaxation_factor=relax, |
| 130 | + ) |
| 131 | + sim.register_ims_package(ims, [gwf.name]) |
| 132 | + |
| 133 | + flopy.mf6.ModflowGwfdis( |
| 134 | + gwf, |
| 135 | + nlay=nlay, |
| 136 | + nrow=nrow, |
| 137 | + ncol=ncol, |
| 138 | + delr=delr, |
| 139 | + delc=delc, |
| 140 | + top=0.0, |
| 141 | + botm=[-10.0, -20.0, -30.0], |
| 142 | + ) |
| 143 | + |
| 144 | + # initial conditions |
| 145 | + flopy.mf6.ModflowGwfic(gwf, strt=strt) |
| 146 | + |
| 147 | + # node property flow |
| 148 | + flopy.mf6.ModflowGwfnpf( |
| 149 | + gwf, |
| 150 | + save_flows=True, |
| 151 | + icelltype=1, |
| 152 | + k=1.0e-4, |
| 153 | + k22=1.0e-4, |
| 154 | + k33=1.0e-5, |
| 155 | + ) |
| 156 | + |
| 157 | + # aquifer storage |
| 158 | + flopy.mf6.ModflowGwfsto( |
| 159 | + gwf, |
| 160 | + save_flows=True, |
| 161 | + iconvert=1, |
| 162 | + ss=1e-5, |
| 163 | + sy=0.2, |
| 164 | + transient=True, |
| 165 | + ) |
| 166 | + |
| 167 | + # chd files |
| 168 | + chdval = -9.0 |
| 169 | + iface = 0 |
| 170 | + chdspd = { |
| 171 | + 0: [ |
| 172 | + [(0, 0, 0), chdval, iface, "object0"], |
| 173 | + [(0, 0, ncol - 1), chdval, iface, "object0"], |
| 174 | + ] |
| 175 | + } |
| 176 | + flopy.mf6.ModflowGwfchd( |
| 177 | + gwf, |
| 178 | + auxiliary="iface", |
| 179 | + boundnames=True, |
| 180 | + print_input=True, |
| 181 | + save_flows=True, |
| 182 | + stress_period_data=chdspd, |
| 183 | + ) |
| 184 | + |
| 185 | + # transient uzf info |
| 186 | + # ifno cellid landflg ivertcn surfdp vks thtr thts thti eps [bndnm] |
| 187 | + uz_pkdat = uzarea_data[uzarea_correspondence]["uzf_pkdat"] |
| 188 | + |
| 189 | + for itm in uz_pkdat: |
| 190 | + iuz_cell_dict.update({itm[0]: (itm[1][0], itm[1][1], itm[1][2])}) |
| 191 | + cell_iuz_dict.update({(itm[1][0], itm[1][1], itm[1][2]): itm[0]}) |
| 192 | + |
| 193 | + finf = 1.0 |
| 194 | + extdp = 0.0 |
| 195 | + extwc = 0.0 |
| 196 | + pet = 0.0 |
| 197 | + zero = 0.0 |
| 198 | + auxmultval = uzarea_data[uzarea_correspondence]["auxmultval"] |
| 199 | + uzf_spd = { |
| 200 | + 0: [ |
| 201 | + [i, finf, pet, extdp, extwc, zero, zero, zero, auxmultval] |
| 202 | + for i in np.arange(len(uz_pkdat)) |
| 203 | + ] |
| 204 | + } |
| 205 | + |
| 206 | + flopy.mf6.ModflowGwfuzf( |
| 207 | + gwf, |
| 208 | + print_input=True, |
| 209 | + print_flows=True, |
| 210 | + save_flows=True, |
| 211 | + boundnames=True, |
| 212 | + ntrailwaves=7, |
| 213 | + nwavesets=40, |
| 214 | + auxiliary="multiplier", |
| 215 | + auxmultname="multiplier", |
| 216 | + package_convergence_filerecord=f"{name}.UzfConvergence.csv", |
| 217 | + wc_filerecord=f"{name}.wc", |
| 218 | + nuzfcells=len(uz_pkdat), |
| 219 | + packagedata=uz_pkdat, |
| 220 | + perioddata=uzf_spd, |
| 221 | + budget_filerecord=f"{name}.uzf.bud", |
| 222 | + filename=f"{name}.uzf", |
| 223 | + ) |
| 224 | + |
| 225 | + # output control |
| 226 | + flopy.mf6.ModflowGwfoc( |
| 227 | + gwf, |
| 228 | + budget_filerecord=f"{name}.cbc", |
| 229 | + head_filerecord=f"{name}.hds", |
| 230 | + headprintrecord=[("COLUMNS", 10, "WIDTH", 15, "DIGITS", 6, "GENERAL")], |
| 231 | + saverecord=[("HEAD", "ALL"), ("BUDGET", "ALL")], |
| 232 | + printrecord=[("HEAD", "ALL"), ("BUDGET", "ALL")], |
| 233 | + filename=f"{name}.oc", |
| 234 | + ) |
| 235 | + |
| 236 | + return sim |
| 237 | + |
| 238 | + |
| 239 | +def check_output(idx, test): |
| 240 | + print("Running error check") |
| 241 | + name = cases[idx] |
| 242 | + |
| 243 | + errmsg0 = f"flow model should have run successfully but didn't\n" |
| 244 | + errmsg1 = ( |
| 245 | + f"flow model designed to fail, but seems to have run successfully\n" |
| 246 | + ) |
| 247 | + |
| 248 | + with open(test.workspace / "mfsim.lst", "r") as f: |
| 249 | + lines = f.readlines() |
| 250 | + error_count = 0 |
| 251 | + for line in lines: |
| 252 | + if "error report" in line.lower(): |
| 253 | + error_count += 1 |
| 254 | + |
| 255 | + if "bad" in name: |
| 256 | + assert error_count > 0, errmsg1 |
| 257 | + else: |
| 258 | + assert error_count == 0, errmsg0 |
| 259 | + |
| 260 | + |
| 261 | +@pytest.mark.parametrize("idx,name", enumerate(cases)) |
| 262 | +def test_mf6model(idx, name, function_tmpdir, targets): |
| 263 | + xfail = ["bad" in cases[ct] for ct in np.arange(len(cases))] |
| 264 | + test = TestFramework( |
| 265 | + name=name, |
| 266 | + workspace=function_tmpdir, |
| 267 | + build=lambda t: build_models(idx, t), |
| 268 | + check=lambda t: check_output(idx, t), |
| 269 | + targets=targets, |
| 270 | + xfail=xfail[idx], |
| 271 | + ) |
| 272 | + test.run() |
0 commit comments