diff --git a/autotest/test_gwe_ssm01.py b/autotest/test_gwe_ssm01.py new file mode 100644 index 00000000000..2b1999662ae --- /dev/null +++ b/autotest/test_gwe_ssm01.py @@ -0,0 +1,281 @@ +""" +Test the SSM FILEINPUT option for specifying source and sink +temperatures. Similar to test_gwt_ssm03.py +""" + +import os + +import flopy +import numpy as np +import pytest +from framework import TestFramework + +cases = ["ssm01"] + +Cpw = 4184.0 +rhow = 1000.0 + + +def build_models(idx, test): + nlay, nrow, ncol = 3, 5, 5 + perlen = [5.0] + nstp = [5] + tsmult = [1.0] + nper = len(perlen) + delr = 1.0 + delc = 1.0 + top = 4.0 + botm = [3.0, 2.0, 1.0] + strt = 4.0 + hk = 1.0 + laytyp = 0 + Cps = 703.7 + rhos = 2700.0 + + nouter, ninner = 100, 300 + hclose, rclose, relax = 1e-6, 1e-6, 1.0 + + tdis_rc = [] + for i in range(nper): + tdis_rc.append((perlen[i], nstp[i], tsmult[i])) + + name = cases[idx] + + # build MODFLOW 6 files + ws = test.workspace + sim = flopy.mf6.MFSimulation( + sim_name=name, version="mf6", exe_name="mf6", sim_ws=ws + ) + # create tdis package + tdis = flopy.mf6.ModflowTdis( + sim, time_units="DAYS", nper=nper, perioddata=tdis_rc + ) + + # create gwf model + gwfname = "gwf_" + name + gwf = flopy.mf6.ModflowGwf( + sim, + modelname=gwfname, + save_flows=True, + ) + + # create iterative model solution and register the gwf model with it + imsgwf = flopy.mf6.ModflowIms( + sim, + print_option="SUMMARY", + outer_dvclose=hclose, + outer_maximum=nouter, + under_relaxation="NONE", + inner_maximum=ninner, + inner_dvclose=hclose, + rcloserecord=rclose, + linear_acceleration="CG", + scaling_method="NONE", + reordering_method="NONE", + relaxation_factor=relax, + filename=f"{gwfname}.ims", + ) + sim.register_ims_package(imsgwf, [gwf.name]) + + dis = flopy.mf6.ModflowGwfdis( + gwf, + nlay=nlay, + nrow=nrow, + ncol=ncol, + delr=delr, + delc=delc, + top=top, + botm=botm, + idomain=np.ones((nlay, nrow, ncol), dtype=int), + ) + + # initial conditions + ic = flopy.mf6.ModflowGwfic(gwf, strt=strt) + + # node property flow + npf = flopy.mf6.ModflowGwfnpf( + gwf, + icelltype=laytyp, + k=hk, + save_specific_discharge=True, + ) + + # chd files + spd = [[(0, 0, 0), 4.0]] + chd = flopy.mf6.modflow.mfgwfchd.ModflowGwfchd( + gwf, + print_flows=True, + maxbound=len(spd), + stress_period_data=spd, + pname="CHD-1", + ) + + # wel files + spd = [[(0, nrow - 1, ncol - 1), 1.0]] + wel = flopy.mf6.ModflowGwfwel( + gwf, + print_flows=True, + maxbound=len(spd), + stress_period_data=spd, + pname="WEL-1", + ) + + # output control + oc = flopy.mf6.ModflowGwfoc( + gwf, + budget_filerecord=f"{gwfname}.cbc", + head_filerecord=f"{gwfname}.hds", + headprintrecord=[("COLUMNS", 10, "WIDTH", 15, "DIGITS", 6, "GENERAL")], + saverecord=[("HEAD", "LAST"), ("BUDGET", "LAST")], + printrecord=[("HEAD", "LAST"), ("BUDGET", "LAST")], + ) + + # create gwt model + gwename = "gwe_" + name + gwe = flopy.mf6.MFModel( + sim, + model_type="gwe6", + modelname=gwename, + model_nam_file=f"{gwename}.nam", + ) + gwe.name_file.save_flows = True + + # create iterative model solution and register the gwt model with it + imsgwe = flopy.mf6.ModflowIms( + sim, + print_option="SUMMARY", + outer_dvclose=hclose, + outer_maximum=nouter, + under_relaxation="NONE", + inner_maximum=ninner, + inner_dvclose=hclose, + rcloserecord=rclose, + linear_acceleration="BICGSTAB", + scaling_method="NONE", + reordering_method="NONE", + relaxation_factor=relax, + filename=f"{gwename}.ims", + ) + sim.register_ims_package(imsgwe, [gwe.name]) + + dis = flopy.mf6.ModflowGwedis( + gwe, + nlay=nlay, + nrow=nrow, + ncol=ncol, + delr=delr, + delc=delc, + top=top, + botm=botm, + idomain=1, + ) + + # initial conditions + ic = flopy.mf6.ModflowGweic(gwe, strt=0.0) + + # advection + adv = flopy.mf6.ModflowGweadv(gwe) + + # mass storage and transfer + est = flopy.mf6.ModflowGweest( + gwe, + porosity=0.1, + heat_capacity_solid=Cps, + density_solid=rhos, + ) + + # sources + pd = [(0, "temperature", 100.0)] + spc = flopy.mf6.ModflowUtlspc( + gwe, perioddata=pd, maxbound=len(pd), filename=f"{gwename}.wel1.spc" + ) + sourcerecarray = [()] + fileinput = [ + ("WEL-1", f"{gwename}.wel1.spc"), + ] + ssm = flopy.mf6.ModflowGwessm( + gwe, print_flows=True, sources=sourcerecarray, fileinput=fileinput + ) + + # output control + oc = flopy.mf6.ModflowGweoc( + gwe, + budget_filerecord=f"{gwename}.cbc", + temperature_filerecord=f"{gwename}.ucn", + temperatureprintrecord=[ + ("COLUMNS", 10, "WIDTH", 15, "DIGITS", 6, "GENERAL") + ], + saverecord=[("TEMPERATURE", "ALL"), ("BUDGET", "ALL")], + printrecord=[("TEMPERATURE", "LAST"), ("BUDGET", "LAST")], + ) + + obs_data = { + f"{gwename}.obs.csv": [ + ("(1-1-1)", "TEMPERATURE", (0, 0, 0)), + ("(1-5-5)", "TEMPERATURE", (0, 4, 4)), + ], + } + + obs_package = flopy.mf6.ModflowUtlobs( + gwe, + pname=f"{gwename}.obs", + digits=10, + print_input=True, + continuous=obs_data, + ) + + # GWF GWE exchange + gwfgwe = flopy.mf6.ModflowGwfgwe( + sim, + exgtype="GWF6-GWE6", + exgmnamea=gwfname, + exgmnameb=gwename, + filename=f"{name}.gwfgwe", + ) + + return sim, None + + +def check_output(idx, test): + name = test.name + gwename = "gwe_" + name + + # load temperature file + fpth = os.path.join(test.workspace, f"{gwename}.ucn") + tobj = flopy.utils.HeadFile(fpth, precision="double", text="TEMPERATURE") + temp = tobj.get_data() + + # load transport budget file + fpth = os.path.join(test.workspace, f"{gwename}.cbc") + bobj = flopy.utils.CellBudgetFile( + fpth, + precision="double", + ) + + ssmbudall = bobj.get_data(text="SOURCE-SINK MIX") + for ssmbud in ssmbudall: + node, node2, q = ssmbud[0] + assert node == 25, "node location for well must be 25 (GWE cell 25)" + assert node2 == 1, "node2 location for well must be 1 (first well)" + msg0 = ( + "energy flux for well must the input temperature (100 deg C) " + "multiplied the heat capacity and density of water." + ) + assert q == 100.0 * Cpw * rhow, msg0 + + node, node2, q = ssmbud[1] + assert node == 1, "node location for chd must be 1 (first GWE cell)" + assert node2 == 1, "node2 location for chd must be 1 (first chd)" + assert q < 0.0, "energy flux for chd must be less than zero" + + +@pytest.mark.parametrize("idx, name", enumerate(cases)) +def test_mf6model(idx, name, function_tmpdir, targets): + test = TestFramework( + name=name, + workspace=function_tmpdir, + targets=targets, + build=lambda t: build_models(idx, t), + check=lambda t: check_output(idx, t), + ) + test.run() diff --git a/autotest/test_gwe_ssm02.py b/autotest/test_gwe_ssm02.py new file mode 100644 index 00000000000..9d8d0b870dc --- /dev/null +++ b/autotest/test_gwe_ssm02.py @@ -0,0 +1,522 @@ +""" +Test the SSM FILEINPUT option for specifying source and sink +temperatures. + +Four different recharge packages are tested with the SSM FILEINPUT +1. list-based recharge no time series +2. array-based recharge, no time array series +3. list-based recharge with time series +4. array-based recharge with time array series +""" + +import os + +import flopy +import numpy as np +import pytest +from framework import TestFramework + +cases = ["ssm02"] + +nlay, nrow, ncol = 3, 5, 5 +idomain_lay0 = [ + [1, 1, 1, 1, 1], + [1, 1, 1, 1, 1], + [1, 1, 0, 1, 1], + [1, 1, 0, 1, 1], + [1, 1, 1, 1, 1], +] +idomain = np.ones((nlay, nrow, ncol), dtype=int) +idomain[0, :, :] = np.array(idomain_lay0) + +Cpw = 4184.0 +rhow = 1000.0 + + +def build_models(idx, test): + perlen = [5.0, 5.0, 5.0] + nstp = [5, 5, 5] + tsmult = [1.0, 1.0, 1.0] + nper = len(perlen) + delr = 1.0 + delc = 1.0 + top = 4.0 + botm = [3.0, 2.0, 1.0] + strt = 4.0 + hk = 1.0 + laytyp = 0 + Cps = 703.7 + rhos = 2700.0 + + nouter, ninner = 100, 300 + hclose, rclose, relax = 1e-6, 1e-6, 1.0 + + tdis_rc = [] + for i in range(nper): + tdis_rc.append((perlen[i], nstp[i], tsmult[i])) + + name = cases[idx] + + # build MODFLOW 6 files + ws = test.workspace + sim = flopy.mf6.MFSimulation( + sim_name=name, version="mf6", exe_name="mf6", sim_ws=ws + ) + # create tdis package + tdis = flopy.mf6.ModflowTdis( + sim, time_units="DAYS", nper=nper, perioddata=tdis_rc + ) + + # create gwf model + gwfname = "gwf_" + name + gwf = flopy.mf6.ModflowGwf( + sim, + modelname=gwfname, + save_flows=True, + ) + + # create iterative model solution and register the gwf model with it + imsgwf = flopy.mf6.ModflowIms( + sim, + print_option="SUMMARY", + outer_dvclose=hclose, + outer_maximum=nouter, + under_relaxation="NONE", + inner_maximum=ninner, + inner_dvclose=hclose, + rcloserecord=rclose, + linear_acceleration="CG", + scaling_method="NONE", + reordering_method="NONE", + relaxation_factor=relax, + filename=f"{gwfname}.ims", + ) + sim.register_ims_package(imsgwf, [gwf.name]) + + dis = flopy.mf6.ModflowGwfdis( + gwf, + nlay=nlay, + nrow=nrow, + ncol=ncol, + delr=delr, + delc=delc, + top=top, + botm=botm, + idomain=idomain, + ) + + # initial conditions + ic = flopy.mf6.ModflowGwfic(gwf, strt=strt) + + # node property flow + npf = flopy.mf6.ModflowGwfnpf( + gwf, + icelltype=laytyp, + k=hk, + save_specific_discharge=True, + ) + + # chd files + spd = [[(nlay - 1, nrow - 1, ncol - 1), 4.0]] + chd = flopy.mf6.modflow.ModflowGwfchd( + gwf, + print_flows=True, + maxbound=len(spd), + stress_period_data=spd, + pname="CHD-1", + ) + + # list based recharge, recharge is equal to one-based user node number + idxrow, idxcol = np.where(idomain[0] == 1) + recharge_rate = np.arange(nrow * ncol).reshape((nrow, ncol)) + 1 + spd = {} + for kper in range(nper): + rlist = [] + for i, j in zip(idxrow, idxcol): + rlist.append([(0, i, j), recharge_rate[i, j]]) + spd[kper] = rlist + rch1 = flopy.mf6.modflow.ModflowGwfrch( + gwf, + print_flows=True, + maxbound=len(spd), + stress_period_data=spd, + pname="RCH-1", + filename=f"{gwfname}.rch1", + ) + + # array-based rch files + rspd = {} + for kper in range(nper): + rspd[kper] = recharge_rate + rch2 = flopy.mf6.ModflowGwfrcha( + gwf, + print_flows=True, + recharge=rspd, + pname="RCH-2", + filename=f"{gwfname}.rch2", + ) + + # list-based recharge with time series + idxrow, idxcol = np.where(idomain[0] == 1) + spd = [] + for i, j in zip(idxrow, idxcol): + nodeu = i * ncol + j + tsname = f"rch-{nodeu + 1}" + spd.append([(0, i, j), tsname]) + + tsnames = [] + for i in range(nrow): + for j in range(ncol): + nodeu = i * nrow + j + tsnames.append(f"rch-{nodeu + 1}") + ts_data = [] + totim = 0.0 + for kper in range(nper): + totim += perlen[kper] + for t in [0, totim]: + ts = tuple([float(t)] + list(range(1, nrow * ncol + 1))) + ts_data.append(ts) + ts_dict = { + "timeseries": ts_data, + "time_series_namerecord": tsnames, + "interpolation_methodrecord": [nrow * ncol * ("linear",)], + "filename": f"{gwfname}.rch3.ts", + } + + rch3 = flopy.mf6.modflow.ModflowGwfrch( + gwf, + print_flows=True, + maxbound=len(spd), + stress_period_data=spd, + pname="RCH-3", + filename=f"{gwfname}.rch3", + timeseries=ts_dict, + ) + + # array-based rch files + rch4 = flopy.mf6.ModflowGwfrcha( + gwf, + print_flows=True, + recharge="TIMEARRAYSERIES rcharray", + pname="RCH-4", + filename=f"{gwfname}.rch4", + ) + filename = f"{gwfname}.rch4.tas" + # for now write the recharge temperature to a dat file because there + # is a bug in flopy that will not correctly write this array as internal + tas_array = { + 0.0: f"{gwfname}.rch4.tas.dat", + 5.0: f"{gwfname}.rch4.tas.dat", + 10.0: f"{gwfname}.rch4.tas.dat", + 15.0: f"{gwfname}.rch4.tas.dat", + } + time_series_namerecord = "rcharray" + interpolation_methodrecord = "linear" + rch4.tas.initialize( + filename=filename, + tas_array=tas_array, + time_series_namerecord=time_series_namerecord, + interpolation_methodrecord=interpolation_methodrecord, + ) + np.savetxt( + os.path.join(ws, f"{gwfname}.rch4.tas.dat"), recharge_rate, fmt="%7.1f" + ) + + # output control + oc = flopy.mf6.ModflowGwfoc( + gwf, + budget_filerecord=f"{gwfname}.cbc", + head_filerecord=f"{gwfname}.hds", + headprintrecord=[("COLUMNS", 10, "WIDTH", 15, "DIGITS", 6, "GENERAL")], + saverecord=[("HEAD", "LAST"), ("BUDGET", "LAST")], + printrecord=[("HEAD", "LAST"), ("BUDGET", "LAST")], + ) + + # create gwt model + gwename = "gwe_" + name + gwe = flopy.mf6.MFModel( + sim, + model_type="gwe6", + modelname=gwename, + model_nam_file=f"{gwename}.nam", + ) + gwe.name_file.save_flows = True + + # create iterative model solution and register the gwt model with it + imsgwe = flopy.mf6.ModflowIms( + sim, + print_option="SUMMARY", + outer_dvclose=hclose, + outer_maximum=nouter, + under_relaxation="NONE", + inner_maximum=ninner, + inner_dvclose=hclose, + rcloserecord=rclose, + linear_acceleration="BICGSTAB", + scaling_method="NONE", + reordering_method="NONE", + relaxation_factor=relax, + filename=f"{gwename}.ims", + ) + sim.register_ims_package(imsgwe, [gwe.name]) + + dis = flopy.mf6.ModflowGwedis( + gwe, + nlay=nlay, + nrow=nrow, + ncol=ncol, + delr=delr, + delc=delc, + top=top, + botm=botm, + idomain=idomain, + ) + + # initial conditions + ic = flopy.mf6.ModflowGweic(gwe, strt=0.0) + + # advection + adv = flopy.mf6.ModflowGweadv(gwe) + + # mass storage and transfer + est = flopy.mf6.ModflowGweest( + gwe, + porosity=0.1, + heat_capacity_solid=Cps, + density_solid=rhos, + ) + + # ssm package + sourcerecarray = [()] + fileinput = [ + ("RCH-1", f"{gwename}.rch1.spc"), + ("RCH-2", f"{gwename}.rch2.spc"), + ("RCH-3", f"{gwename}.rch3.spc"), + ("RCH-4", f"{gwename}.rch4.spc"), + ] + ssm = flopy.mf6.ModflowGwessm( + gwe, print_flows=True, sources=sourcerecarray, fileinput=fileinput + ) + + # spc package for RCH-1 + idxrow, idxcol = np.where(idomain[0] == 1) + recharge_temperature = np.arange(nrow * ncol).reshape((nrow, ncol)) + 1 + pd = [] + for ipos, (i, j) in enumerate(zip(idxrow, idxcol)): + pd.append([ipos, "TEMPERATURE", recharge_temperature[i, j]]) + spc1 = flopy.mf6.ModflowUtlspc( + gwe, + perioddata=pd, + maxbound=len(pd), + filename=f"{gwename}.rch1.spc", + ) + + # spc package for RCH-2 + idxrow, idxcol = np.where(idomain[0] == 1) + recharge_temperature = np.arange(nrow * ncol).reshape((nrow, ncol)) + 1 + trchspd = {} + for kper in range(nper): + trchspd[kper] = recharge_temperature + spc2 = flopy.mf6.ModflowUtlspca( + gwe, + temperature=trchspd, + filename=f"{gwename}.rch2.spc", + ) + + # spc package for RCH-3 + idxrow, idxcol = np.where(idomain[0] == 1) + pd = [] + for ipos, (i, j) in enumerate(zip(idxrow, idxcol)): + nodeu = i * ncol + j + tsname = f"trch-{nodeu + 1}" + pd.append([ipos, "TEMPERATURE", tsname]) + + tsnames = [] + for i in range(nrow): + for j in range(ncol): + nodeu = i * ncol + j + tsnames.append(f"trch-{nodeu + 1}") + ts_data = [tuple([0.0] + list(range(1, nrow * ncol + 1)))] + for t in [5.0, 10.0, 15.0]: + ts = tuple([float(t)] + list(range(1, nrow * ncol + 1))) + ts_data.append(ts) + ts_dict = { + "timeseries": ts_data, + "time_series_namerecord": tsnames, + "interpolation_methodrecord": [nrow * ncol * ("linear",)], + "sfacrecord": [nrow * ncol * (1.0,)], + "filename": f"{gwename}.rch3.spc.ts", + } + spc3 = flopy.mf6.ModflowUtlspc( + gwe, + perioddata=pd, + maxbound=len(pd), + filename=f"{gwename}.rch3.spc", + timeseries=ts_dict, + print_input=True, + ) + + # spc package for RCH-4 + spc4 = flopy.mf6.ModflowUtlspca( + gwe, + temperature="TIMEARRAYSERIES tarray", + filename=f"{gwename}.rch4.spc", + print_input=True, + ) + filename = f"{gwename}.rch4.spc.tas" + # for now write the recharge temperature to a dat file because there + # is a bug in flopy that will not correctly write this array as internal + tas_array = { + 0.0: f"{gwename}.rch4.spc.tas.dat", + 5.0: f"{gwename}.rch4.spc.tas.dat", + 10.0: f"{gwename}.rch4.spc.tas.dat", + 15.0: f"{gwename}.rch4.spc.tas.dat", + } + time_series_namerecord = "tarray" + interpolation_methodrecord = "linear" + spc4.tas.initialize( + filename=filename, + tas_array=tas_array, + time_series_namerecord=time_series_namerecord, + interpolation_methodrecord=interpolation_methodrecord, + ) + recharge_temperature = np.arange(nrow * ncol).reshape((nrow, ncol)) + 1 + np.savetxt( + os.path.join(ws, f"{gwename}.rch4.spc.tas.dat"), + recharge_temperature, + fmt="%7.1f", + ) + + # output control + oc = flopy.mf6.ModflowGweoc( + gwe, + budget_filerecord=f"{gwename}.cbc", + temperature_filerecord=f"{gwename}.ucn", + temperatureprintrecord=[ + ("COLUMNS", 10, "WIDTH", 15, "DIGITS", 6, "GENERAL") + ], + saverecord=[("TEMPERATURE", "ALL"), ("BUDGET", "ALL")], + printrecord=[("TEMPERATURE", "LAST"), ("BUDGET", "LAST")], + ) + + obs_data = { + f"{gwename}.obs.csv": [ + ("(1-1-1)", "TEMPERATURE", (0, 0, 0)), + ("(1-5-5)", "TEMPERATURE", (nlay - 1, nrow - 1, ncol - 1)), + ], + } + + obs_package = flopy.mf6.ModflowUtlobs( + gwe, + pname=f"{gwename}.obs", + digits=10, + print_input=True, + continuous=obs_data, + ) + + # GWF GWE exchange + gwfgwe = flopy.mf6.ModflowGwfgwe( + sim, + exgtype="GWF6-gwe6", + exgmnamea=gwfname, + exgmnameb=gwename, + filename=f"{name}.gwfgwe", + ) + + return sim, None + + +def check_output(idx, test): + name = test.name + gwename = "gwe_" + name + + # load temperature file + fpth = os.path.join(test.workspace, f"{gwename}.ucn") + tobj = flopy.utils.HeadFile(fpth, precision="double", text="TEMPERATURE") + temp = tobj.get_data() + + # load transport budget file + fpth = os.path.join(test.workspace, f"{gwename}.cbc") + bobj = flopy.utils.CellBudgetFile( + fpth, + precision="double", + ) + + ssmbudall = bobj.get_data(text="SOURCE-SINK MIX") + times = tobj.get_times() + + print(times) + for itime, totim in enumerate(times): + print(f"Checking records for time {totim}") + + # Check records for each of the four recharge packages + ssmbud = ssmbudall[itime] + istart = 0 + for irchpak in [1, 2, 3, 4]: + print(f" Checking records for recharge package {irchpak}") + istop = istart + 23 + + print(ssmbud[istart:istop]) + + print(" Checking id1") + id1 = ssmbud[istart:istop]["node"] + id1a = [ + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 14, + 15, + 16, + 17, + 19, + 20, + 21, + 22, + 23, + 24, + 25, + ] + assert np.allclose(id1, id1a), f"{id1} /= {id1a}" + + print(" Checking id2") + id2 = ssmbud[istart:istop]["node2"] + if irchpak in [1, 3]: + # recharge packages 1 and 3 are list-based with 23 entries + id2a = np.arange(23) + 1 + elif irchpak in [2, 4]: + # recharge packages 2 and 4 are array-based with 25 entries + id2a = id1a + assert np.allclose(id2, id2a), f"q: {id2} /= {id2a}" + + print(f" Checking q for irchpak {irchpak}") + q = ssmbud[istart:istop]["q"] + if irchpak in [2, 3]: + qa = [float(a) ** 2 * rhow * Cpw for a in id1] + else: + qa = [float(a) ** 2 * rhow * Cpw for a in id1a] + for i in range(23): + print(f"{i + 1} {id1[i]} {id2[i]} {q[i]} {qa[i]}") + assert np.allclose(q, qa), f"q: {q} /=\n {qa}" + + istart = istop + + +@pytest.mark.parametrize("idx, name", enumerate(cases)) +def test_mf6model(idx, name, function_tmpdir, targets): + test = TestFramework( + name=name, + workspace=function_tmpdir, + targets=targets, + build=lambda t: build_models(idx, t), + check=lambda t: check_output(idx, t), + ) + test.run() diff --git a/doc/ReleaseNotes/develop.tex b/doc/ReleaseNotes/develop.tex index 5ffdd68834d..daa968dc50f 100644 --- a/doc/ReleaseNotes/develop.tex +++ b/doc/ReleaseNotes/develop.tex @@ -43,6 +43,7 @@ \item The PRT model's particle release point (PRP) package previously allowed two particles to be released at the same time from the same point. This could occur if an explicitly specified release time happened to coincide with a release time configured via period block settings. Each release point may now only release one particle at a time. Times falling within a configurable tolerance of one another (defaulting to $\sisetup{input-digits = 0123456789\epsilon} \num{\epsilon e+9}$, where $\epsilon$ is machine precision) are considered coincident and merged into a single release time. \item A new option RELEASE\_TIME\_FREQUENCY was added to the PRT model's particle release point (PRP) package. This option configures release times on a regular interval for the duration of the simulation, with the first release at the simulation start time. The PRP package's release schedule is the union of times configured via RELEASE\_TIME\_FREQUENCY, the RELEASETIMES block, and period block release settings, up to the tolerance mentioned in the previous item. If none of these are provided, a single release time is configured at the beginning of the first stress period's first time step. (A related bug has also been fixed which erroneously activated this default when user-specified release times were configured.) \item The PRT model's particle release point (PRP) package's FRACTION period-block release time setting has been removed. Period-block release settings can now be used only to release particles at the beginning of specified time steps, as is the case for period-block timing settings in the output control (OC) packages for all models. For fine control over release timing, specify times explicitly using the RELEASETIMES block. + \item The Stress Package Concentration (SPC) utility available with the SSM Package is now the referred to as the Stress Package Component utility in the MF6IO guide. Additionally, some relatively minor refactoring of the code facilitates use of the SPC utility with the GWE model type so that TEMPERATURE arrays may be read by the utility. The SPC acronym was maintained to preserve backward compatibility. \end{itemize} %\underline{INTERNAL FLOW PACKAGES} diff --git a/doc/mf6io/body.tex b/doc/mf6io/body.tex index 4933f668e7f..110dbbd49a0 100644 --- a/doc/mf6io/body.tex +++ b/doc/mf6io/body.tex @@ -80,6 +80,12 @@ \SECTION{Time-Variable Input} \input{gwf/tsi} +%Stress Package Component (SPC) Utility Input Instructions +\newpage +\SECTION{Stress Package Component (SPC) Utility} +\label{sec:spc} +\input{utl_spc.tex} + %Binary files \newpage \SECTION{Description of Binary Output Files} diff --git a/doc/mf6io/gwe/ssm.tex b/doc/mf6io/gwe/ssm.tex index ab8de50a564..c3a93c2be15 100644 --- a/doc/mf6io/gwe/ssm.tex +++ b/doc/mf6io/gwe/ssm.tex @@ -5,10 +5,10 @@ \begin{itemize} \item The default condition is that sources have a temperature of zero and sinks withdraw water at the calculated temperature of the cell. This default condition is assigned to any GWF stress package that is not included in a SOURCES block or FILEINPUT block. \item A second option is to assign auxiliary variables in the GWF model and include a temperature for each stress boundary. In this case, the user provides the name of the package and the name of the auxiliary variable containing temperature values for each boundary. As described below for srctype, there are multiple options for defining this behavior. -\item A third option is to prepare an SPT6 file for any desired GWF stress package. This SPT6 file allows users to change temperatures by stress period, or to use the time-series option to interpolate temperatures by time step. This third option was introduced in MODFLOW version 6.3.0. Information for this approach is entered in an optional FILEINPUT block below. The SPT6 input file supports list-based temperature input for most corresponding GWF stress packages, but also supports a READASARRAYS array-based input format if a corresponding GWF recharge or evapotranspiration package uses the READASARRAYS option. +\item A third option is to prepare an input file using the \hyperref[sec:spc]{Stress Package Component (SPC6) utility} for any desired GWF stress package. This SPC6 file allows users to change temperatures by stress period, or to use the time-series option to interpolate temperatures by time step. This third option was introduced in MODFLOW version 6.3.0. Information for this approach is entered in an optional FILEINPUT block below. The SPC6 input file supports list-based temperature input for most corresponding GWF stress packages, but also supports a READASARRAYS array-based input format if a corresponding GWF recharge or evapotranspiration package uses the READASARRAYS option. \end{itemize} -\noindent The auxiliary method and the SPT6 file input method can both be used for a GWE model, but only one approach can be assigned per GWF stress package. If a flow package specified in the SOURCES or FILEINPUT blocks is also represented using an advanced transport package (SFE, LKE, MWE, or UZE), then the advanced transport package will override SSM calculations for that package. +\noindent The auxiliary method and the SPC6 file input method can both be used for a GWE model, but only one approach can be assigned per GWF stress package. If a flow package specified in the SOURCES or FILEINPUT blocks is also represented using an advanced transport package (SFE, LKE, MWE, or UZE), then the advanced transport package will override SSM calculations for that package. \vspace{5mm} \subsubsection{Structure of Blocks} @@ -30,85 +30,4 @@ \subsubsection{Example Input File} % when obs are ready, they should go here -\newpage -\subsection{Stress Package Temperatures (SPT) -- List-Based Input} -As mentioned in the previous section on the SSM Package, temperatures can be specified for GWF stress packages using auxiliary variables, or they can be specified using input files dedicated to this purpose. The Stress Package Temperatures (SPT) input file can be used to provide temperatures that are assigned for GWF sources and sinks. An SPT input file can be list based or array based. List-based input files can be used for list-based GWF stress packages, such as wells, drains, and rivers. Array-based input files can be used for array-based GWF stress packages, such as recharge and evapotranspiration (provided the READASARRAYS options is used; these packages can also be provided in a list-based format). Array-based SPT input files are discussed in the next section. This section describes the list-based input format for the SPT input file. - -An SPT6 file can be prepared to provide user-specified temperatures for a GWF stress package, such a Well or General-Head Boundary Package, for example. One SPT6 file applies to one GWF stress package. Names for the SPT6 input files are provided in the FILEINPUT block of the SSM Package. SPT6 entries cannot be specified in the GWE name file. Use of the SPT6 input file is an alternative to specifying stress package temperatures as auxiliary variables in the flow model stress package. - -The boundary number in the PERIOD block corresponds to the boundary number in the GWF stress period package. Assignment of the boundary number is straightforward for the advanced packages (SFR, LAK, MAW, and UZF) because the features in these advanced packages are defined once at the beginning of the simulation and they do not change. For the other stress packages, however, the order of boundaries may change between stress periods. Consider the following Well Package input file, for example: - -\begin{verbatim} -# This is an example of a GWF Well Package -# in which the order of the wells changes from -# stress period 1 to 2. This must be explicitly -# handled by the user if using the SPT6 input -# for a GWE model. -BEGIN options - BOUNDNAMES -END options - -BEGIN dimensions - MAXBOUND 3 -END dimensions - -BEGIN period 1 - 1 77 65 -2200 SHALLOW_WELL - 2 77 65 -24.0 INTERMEDIATE_WELL - 3 77 65 -6.20 DEEP_WELL -END period - -BEGIN period 2 - 1 77 65 -1100 SHALLOW_WELL - 3 77 65 -3.10 DEEP_WELL - 2 77 65 -12.0 INTERMEDIATE_WELL -END period -\end{verbatim} - -\noindent In this Well input file, the order of the wells changed between periods 1 and 2. This reordering must be explicitly taken into account by the user when creating an SSMI6 file, because the boundary number in the SSMI file corresponds to the boundary number in the Well input file. In stress period 1, boundary number 2 is the INTERMEDIATE\_WELL, whereas in stress period 2, boundary number 2 is the DEEP\_WELL. When using this SSMI capability to specify boundary temperatures, it is recommended that users write the corresponding GWF stress packages using the same number, cell locations, and order of boundary conditions for each stress period. In addition, users can activate the PRINT\_FLOWS option in the SSM input file. When the SSM Package prints the individual solute flows to the transport list file, it includes a column containing the boundary temperature. Users can check the boundary temperatures in this output to verify that they are assigned as intended. - -\vspace{5mm} -\subsubsection{Structure of Blocks} -\vspace{5mm} - -\noindent \textit{FOR EACH SIMULATION} -\lstinputlisting[style=blockdefinition]{./mf6ivar/tex/utl-spt-options.dat} -\lstinputlisting[style=blockdefinition]{./mf6ivar/tex/utl-spt-dimensions.dat} -\vspace{5mm} -\noindent \textit{FOR ANY STRESS PERIOD} -\lstinputlisting[style=blockdefinition]{./mf6ivar/tex/utl-spt-period.dat} - -\vspace{5mm} -\subsubsection{Explanation of Variables} -\begin{description} -\input{./mf6ivar/tex/utl-spt-desc.tex} -\end{description} - -\subsubsection{Example Input File} -\lstinputlisting[style=inputfile]{./mf6ivar/examples/utl-spt-example.dat} - -% SPT array based -\newpage -\subsection{Stress Package Temperatures (SPT) -- Array-Based Input} - -This section describes array-based input for the SPT input file. If the READASARRAYS options is specified for either the GWF Recharge (RCH) or Evapotranspiration (EVT) Packages, then temperatures for these packages can be specified using array-based temperature input. This SPT array-based input is distinguished from the list-based input in the previous section through specification of the READASARRAYS option. When the READASARRAYS option is specified, then there is no DIMENSIONS block in the SPT input file. Instead, the shape of the array for temperatures is the number of rows by number of columns (NROW, NCOL), for a regular MODFLOW grid (DIS), and the number of cells in a layer (NCPL) for a discretization by vertices (DISV) grid. - -\vspace{5mm} -\subsubsection{Structure of Blocks} -\vspace{5mm} - -\noindent \textit{FOR EACH SIMULATION} -\lstinputlisting[style=blockdefinition]{./mf6ivar/tex/utl-spta-options.dat} -\vspace{5mm} -\noindent \textit{FOR ANY STRESS PERIOD} -\lstinputlisting[style=blockdefinition]{./mf6ivar/tex/utl-spta-period.dat} - -\vspace{5mm} -\subsubsection{Explanation of Variables} -\begin{description} -\input{./mf6ivar/tex/utl-spta-desc.tex} -\end{description} - -\subsubsection{Example Input File} -\lstinputlisting[style=inputfile]{./mf6ivar/examples/utl-spta-example.dat} diff --git a/doc/mf6io/gwt/ssm.tex b/doc/mf6io/gwt/ssm.tex index c79b0c35dbc..0a497ad6898 100644 --- a/doc/mf6io/gwt/ssm.tex +++ b/doc/mf6io/gwt/ssm.tex @@ -5,7 +5,7 @@ \begin{itemize} \item The default condition is that sources have a concentration of zero and sinks withdraw water at the calculated concentration of the cell. This default condition is assigned to any GWF stress package that is not included in a SOURCES block or FILEINPUT block. \item A second option is to assign auxiliary variables in the GWF model and include a concentration for each stress boundary. In this case, the user provides the name of the package and the name of the auxiliary variable containing concentration values for each boundary. As described below for srctype, there are multiple options for defining this behavior. -\item A third option is to prepare an SPC6 file for any desired GWF stress package. This SPC6 file allows users to change concentrations by stress period, or to use the time-series option to interpolate concentrations by time step. This third option was introduced in MODFLOW version 6.3.0. Information for this approach is entered in an optional FILEINPUT block below. The SPC6 input file supports list-based concentration input for most corresponding GWF stress packages, but also supports a READASARRAYS array-based input format if a corresponding GWF recharge or evapotranspiration package uses the READASARRAYS option. +\item A third option is to prepare an input file using the \hyperref[sec:spc]{Stress Package Component (SPC6) utility} for any desired GWF stress package. This SPC6 file allows users to change concentrations by stress period, or to use the time-series option to interpolate concentrations by time step. This third option was introduced in MODFLOW version 6.3.0. Information for this approach is entered in an optional FILEINPUT block below. The SPC6 input file supports list-based concentration input for most corresponding GWF stress packages, but also supports a READASARRAYS array-based input format if a corresponding GWF recharge or evapotranspiration package uses the READASARRAYS option. \end{itemize} \noindent The auxiliary method and the SPC6 file input method can both be used for a GWT model, but only one approach can be assigned per GWF stress package. If a flow package specified in the SOURCES or FILEINPUT blocks is also represented using an advanced transport package (SFT, LKT, MWT, or UZT), then the advanced transport package will override SSM calculations for that package. @@ -29,86 +29,3 @@ \subsubsection{Example Input File} \lstinputlisting[style=inputfile]{./mf6ivar/examples/gwt-ssm-example.dat} % when obs are ready, they should go here - -\newpage -\subsection{Stress Package Concentrations (SPC) -- List-Based Input} -As mentioned in the previous section on the SSM Package, concentrations can be specified for GWF stress packages using auxiliary variables, or they can be specified using input files dedicated to this purpose. The Stress Package Concentrations (SPC) input file can be used to provide concentrations that are assigned for GWF sources and sinks. An SPC input file can be list based or array based. List-based input files can be used for list-based GWF stress packages, such as wells, drains, and rivers. Array-based input files can be used for array-based GWF stress packages, such as recharge and evapotranspiration (provided the READASARRAYS options is used; these packages can also be provided in a list-based format). Array-based SPC input files are discussed in the next section. This section describes the list-based input format for the SPC input file. - -An SPC6 file can be prepared to provide user-specified concentrations for a GWF stress package, such a Well or General-Head Boundary Package, for example. One SPC6 file applies to one GWF stress package. Names for the SPC6 input files are provided in the FILEINPUT block of the SSM Package. SPC6 entries cannot be specified in the GWT name file. Use of the SPC6 input file is an alternative to specifying stress package concentrations as auxiliary variables in the flow model stress package. - -The boundary number in the PERIOD block corresponds to the boundary number in the GWF stress period package. Assignment of the boundary number is straightforward for the advanced packages (SFR, LAK, MAW, and UZF) because the features in these advanced packages are defined once at the beginning of the simulation and they do not change. For the other stress packages, however, the order of boundaries may change between stress periods. Consider the following Well Package input file, for example: - -\begin{verbatim} -# This is an example of a GWF Well Package -# in which the order of the wells changes from -# stress period 1 to 2. This must be explicitly -# handled by the user if using the SPC6 input -# for a GWT model. -BEGIN options - BOUNDNAMES -END options - -BEGIN dimensions - MAXBOUND 3 -END dimensions - -BEGIN period 1 - 1 77 65 -2200 SHALLOW_WELL - 2 77 65 -24.0 INTERMEDIATE_WELL - 3 77 65 -6.20 DEEP_WELL -END period - -BEGIN period 2 - 1 77 65 -1100 SHALLOW_WELL - 3 77 65 -3.10 DEEP_WELL - 2 77 65 -12.0 INTERMEDIATE_WELL -END period -\end{verbatim} - -\noindent In this Well input file, the order of the wells changed between periods 1 and 2. This reordering must be explicitly taken into account by the user when creating an SSMI6 file, because the boundary number in the SSMI file corresponds to the boundary number in the Well input file. In stress period 1, boundary number 2 is the INTERMEDIATE\_WELL, whereas in stress period 2, boundary number 2 is the DEEP\_WELL. When using this SSMI capability to specify boundary concentrations, it is recommended that users write the corresponding GWF stress packages using the same number, cell locations, and order of boundary conditions for each stress period. In addition, users can activate the PRINT\_FLOWS option in the SSM input file. When the SSM Package prints the individual solute flows to the transport list file, it includes a column containing the boundary concentration. Users can check the boundary concentrations in this output to verify that they are assigned as intended. - -\vspace{5mm} -\subsubsection{Structure of Blocks} -\vspace{5mm} - -\noindent \textit{FOR EACH SIMULATION} -\lstinputlisting[style=blockdefinition]{./mf6ivar/tex/utl-spc-options.dat} -\lstinputlisting[style=blockdefinition]{./mf6ivar/tex/utl-spc-dimensions.dat} -\vspace{5mm} -\noindent \textit{FOR ANY STRESS PERIOD} -\lstinputlisting[style=blockdefinition]{./mf6ivar/tex/utl-spc-period.dat} - -\vspace{5mm} -\subsubsection{Explanation of Variables} -\begin{description} -\input{./mf6ivar/tex/utl-spc-desc.tex} -\end{description} - -\subsubsection{Example Input File} -\lstinputlisting[style=inputfile]{./mf6ivar/examples/utl-spc-example.dat} - -% SPC array based -\newpage -\subsection{Stress Package Concentrations (SPC) -- Array-Based Input} - -This section describes array-based input for the SPC input file. If the READASARRAYS options is specified for either the GWF Recharge (RCH) or Evapotranspiration (EVT) Packages, then concentrations for these packages can be specified using array-based concentration input. This SPC array-based input is distinguished from the list-based input in the previous section through specification of the READASARRAYS option. When the READASARRAYS option is specified, then there is no DIMENSIONS block in the SPC input file. Instead, the shape of the array for concentrations is the number of rows by number of columns (NROW, NCOL), for a regular MODFLOW grid (DIS), and the number of cells in a layer (NCPL) for a discretization by vertices (DISV) grid. - -\vspace{5mm} -\subsubsection{Structure of Blocks} -\vspace{5mm} - -\noindent \textit{FOR EACH SIMULATION} -\lstinputlisting[style=blockdefinition]{./mf6ivar/tex/utl-spca-options.dat} -\vspace{5mm} -\noindent \textit{FOR ANY STRESS PERIOD} -\lstinputlisting[style=blockdefinition]{./mf6ivar/tex/utl-spca-period.dat} - -\vspace{5mm} -\subsubsection{Explanation of Variables} -\begin{description} -\input{./mf6ivar/tex/utl-spca-desc.tex} -\end{description} - -\subsubsection{Example Input File} -\lstinputlisting[style=inputfile]{./mf6ivar/examples/utl-spca-example.dat} - diff --git a/doc/mf6io/mf6ivar/dfn/gwe-ssm.dfn b/doc/mf6io/mf6ivar/dfn/gwe-ssm.dfn index 4cc3fc7982d..1e85ca53846 100644 --- a/doc/mf6io/mf6ivar/dfn/gwe-ssm.dfn +++ b/doc/mf6io/mf6ivar/dfn/gwe-ssm.dfn @@ -44,7 +44,7 @@ tagged false optional false reader urword longname source type -description keyword indicating how temperature will be assigned for sources and sinks. Keyword must be specified as either AUX or AUXMIXED. For both options the user must provide an auxiliary variable in the corresponding flow package. The auxiliary variable must have the same name as the AUXNAME value that follows. If the AUX keyword is specified, then the auxiliary variable specified by the user will be assigned as the concenration value for groundwater sources (flows with a positive sign). For negative flow rates (sinks), groundwater will be withdrawn from the cell at the simulated temperature of the cell. The AUXMIXED option provides an alternative method for how to determine the temperature of sinks. If the cell temperature is larger than the user-specified auxiliary temperature, then the temperature of groundwater withdrawn from the cell will be assigned as the user-specified temperature. Alternatively, if the user-specified auxiliary temperature is larger than the cell temperature, then groundwater will be withdrawn at the cell temperature. Thus, the AUXMIXED option is designed to work with the Evapotranspiration (EVT) and Recharge (RCH) Packages where water may be withdrawn at a temperature that is less than the cell temperature. +description keyword indicating how temperature will be assigned for sources and sinks. Keyword must be specified as either AUX or AUXMIXED. For both options the user must provide an auxiliary variable in the corresponding flow package. The auxiliary variable must have the same name as the AUXNAME value that follows. If the AUX keyword is specified, then the auxiliary variable specified by the user will be assigned as the temperature value for groundwater sources (flows with a positive sign). For negative flow rates (sinks), groundwater will be withdrawn from the cell at the simulated temperature of the cell. The AUXMIXED option provides an alternative method for how to determine the temperature of sinks. If the cell temperature is larger than the user-specified auxiliary temperature, then the temperature of groundwater withdrawn from the cell will be assigned as the user-specified temperature. Alternatively, if the user-specified auxiliary temperature is larger than the cell temperature, then groundwater will be withdrawn at the cell temperature. Thus, the AUXMIXED option is designed to work with the Evapotranspiration (EVT) and Recharge (RCH) Packages where water may be withdrawn at a temperature that is less than the cell temperature. block sources name auxname @@ -61,7 +61,7 @@ description name of the auxiliary variable in the package PNAME. This auxiliary block fileinput name fileinput -type recarray pname spt6 filein spt6_filename mixed +type recarray pname spc6 filein spc6_filename mixed reader urword longname description @@ -73,11 +73,11 @@ type string tagged false reader urword longname package name -description name of the flow package for which an SPT6 input file contains a source temperature. If this flow package is represented using an advanced transport package (SFE, LKE, MWE, or UZE), then the advanced transport package will override SSM terms specified here. +description name of the flow package for which an SPC6 input file contains a source temperature. If this flow package is represented using an advanced transport package (SFE, LKE, MWE, or UZE), then the advanced transport package will override SSM terms specified here. block fileinput -name spt6 +name spc6 type keyword shape in_record true @@ -99,15 +99,15 @@ longname file keyword description keyword to specify that an input filename is expected next. block fileinput -name spt6_filename +name spc6_filename type string preserve_case true in_record true reader urword optional false tagged false -longname spt file name -description character string that defines the path and filename for the file containing source and sink input data for the flow package. The SPT6\_FILENAME file is a flexible input file that allows temperatures to be specified by stress period and with time series. Instructions for creating the SPT6\_FILENAME input file are provided in the next section on file input for boundary temperatures. +longname spc file name +description character string that defines the path and filename for the file containing source and sink input data for the flow package. The SPC6\_FILENAME file is a flexible input file that allows temperatures to be specified by stress period and with time series. Instructions for creating the SPC6\_FILENAME input file are provided in the next section on file input for boundary temperatures. block fileinput name mixed diff --git a/doc/mf6io/mf6ivar/dfn/utl-spc.dfn b/doc/mf6io/mf6ivar/dfn/utl-spc.dfn index 6fabd0c0f6a..58aebbddd11 100644 --- a/doc/mf6io/mf6ivar/dfn/utl-spc.dfn +++ b/doc/mf6io/mf6ivar/dfn/utl-spc.dfn @@ -98,13 +98,13 @@ numeric_index true block period name spcsetting -type keystring concentration +type keystring concentration temperature shape tagged false in_record true reader urword longname -description line of information that is parsed into a keyword and values. Keyword values that can be used to start the SPCSETTING string include: CONCENTRATION. +description line of information that is parsed into a keyword and values. Keyword values that can be used to start the SPCSETTING string include: CONCENTRATION and TEMPERATURE. block period name concentration @@ -114,5 +114,16 @@ tagged true in_record true reader urword time_series true -longname well boundary concentration +longname boundary concentration description is the boundary concentration. If the Options block includes a TIMESERIESFILE entry (see the ``Time-Variable Input'' section), values can be obtained from a time series by entering the time-series name in place of a numeric value. By default, the CONCENTRATION for each boundary feature is zero. + +block period +name temperature +type double precision +shape +tagged true +in_record true +reader urword +time_series true +longname boundary temperature +description is the user-supplied boundary temperature. If the Options block includes a TIMESERIESFILE entry (see the ``Time-Variable Input'' section), values can be obtained from a time series by entering the time-series name in place of a numeric value. By default, the TEMPERATURE for each boundary feature is zero. \ No newline at end of file diff --git a/doc/mf6io/mf6ivar/dfn/utl-spca.dfn b/doc/mf6io/mf6ivar/dfn/utl-spca.dfn index 40bbe7067d8..92ac496e1ae 100644 --- a/doc/mf6io/mf6ivar/dfn/utl-spca.dfn +++ b/doc/mf6io/mf6ivar/dfn/utl-spca.dfn @@ -83,7 +83,16 @@ name concentration type double precision shape (ncol*nrow; ncpl) reader readarray +optional true longname concentration description is the concentration of the associated Recharge or Evapotranspiration stress package. The concentration array may be defined by a time-array series (see the "Using Time-Array Series in a Package" section). -default_value 0. + +block period +name temperature +type double precision +shape (ncol*nrow; ncpl) +reader readarray +optional true +longname temperature +description is the temperature of the associated Recharge or Evapotranspiration stress package. The temperature array may be defined by a time-array series (see the "Using Time-Array Series in a Package" section). diff --git a/doc/mf6io/mf6ivar/dfn/utl-spt.dfn b/doc/mf6io/mf6ivar/dfn/utl-spt.dfn deleted file mode 100644 index 4febf607234..00000000000 --- a/doc/mf6io/mf6ivar/dfn/utl-spt.dfn +++ /dev/null @@ -1,118 +0,0 @@ -# --------------------- ssm spt options --------------------- -# flopy multi-package - -block options -name print_input -type keyword -reader urword -optional true -longname print input to listing file -description REPLACE print_input {'{#1}': 'spt'} - -block options -name ts_filerecord -type record ts6 filein ts6_filename -shape -reader urword -tagged true -optional true -longname -description - -block options -name ts6 -type keyword -shape -in_record true -reader urword -tagged true -optional false -longname head keyword -description keyword to specify that record corresponds to a time-series file. - -block options -name filein -type keyword -shape -in_record true -reader urword -tagged true -optional false -longname file keyword -description keyword to specify that an input filename is expected next. - -block options -name ts6_filename -type string -preserve_case true -in_record true -reader urword -optional false -tagged false -longname file name of time series information -description REPLACE timeseriesfile {} - -# --------------------- ssm spt dimensions --------------------- - -block dimensions -name maxbound -type integer -reader urword -optional false -longname maximum number of ssm entries -description REPLACE maxbound {'{#1}': 'spt'} - -# --------------------- ssm spt period --------------------- - -block period -name iper -type integer -block_variable True -in_record true -tagged false -shape -valid -reader urword -optional false -longname stress period number -description REPLACE iper {} - -block period -name perioddata -type recarray bndno sptsetting -shape -reader urword -longname -description - -block period -name bndno -type integer -shape -tagged false -in_record true -reader urword -longname bound number for this entry -description integer value that defines the boundary package feature number associated with the specified PERIOD data on the line. BNDNO must be greater than zero and less than or equal to MAXBOUND. -numeric_index true - -block period -name sptsetting -type keystring temperature -shape -tagged false -in_record true -reader urword -longname -description line of information that is parsed into a keyword and values. Keyword values that can be used to start the SPTSETTING string include: TEMPERATURE. - -block period -name temperature -type double precision -shape -tagged true -in_record true -reader urword -time_series true -longname well boundary temperature -description is the boundary temperature. If the Options block includes a TIMESERIESFILE entry (see the ``Time-Variable Input'' section), values can be obtained from a time series by entering the time-series name in place of a numeric value. By default, the TEMPERATURE for each boundary feature is zero. diff --git a/doc/mf6io/mf6ivar/dfn/utl-spta.dfn b/doc/mf6io/mf6ivar/dfn/utl-spta.dfn deleted file mode 100644 index 13463e47a9b..00000000000 --- a/doc/mf6io/mf6ivar/dfn/utl-spta.dfn +++ /dev/null @@ -1,89 +0,0 @@ -# --------------------- ssm spta options --------------------- -# flopy multi-package - -block options -name readasarrays -type keyword -shape -reader urword -optional false -longname use array-based input -description indicates that array-based input will be used for the SPT Package. This keyword must be specified to use array-based input. When READASARRAYS is specified, values must be provided for every cell within a model layer, even those cells that have an IDOMAIN value less than one. Values assigned to cells with IDOMAIN values less than one are not used and have no effect on simulation results. -default_value True - -block options -name print_input -type keyword -reader urword -optional true -longname print input to listing file -description REPLACE print_input {'{#1}': 'spt'} - -block options -name tas_filerecord -type record tas6 filein tas6_filename -shape -reader urword -tagged true -optional true -longname -description - -block options -name tas6 -type keyword -shape -in_record true -reader urword -tagged true -optional false -longname head keyword -description keyword to specify that record corresponds to a time-array-series file. - -block options -name filein -type keyword -shape -in_record true -reader urword -tagged true -optional false -longname file keyword -description keyword to specify that an input filename is expected next. - -block options -name tas6_filename -type string -preserve_case true -in_record true -reader urword -optional false -tagged false -longname file name of time series information -description defines a time-array-series file defining a time-array series that can be used to assign time-varying values. See the Time-Variable Input section for instructions on using the time-array series capability. - - -# --------------------- ssm spta period --------------------- - -block period -name iper -type integer -block_variable True -in_record true -tagged false -shape -valid -reader urword -optional false -longname stress period number -description REPLACE iper {} - -block period -name temperature -type double precision -shape (ncol*nrow; ncpl) -reader readarray -longname temperature -description is the temperature of the associated Recharge or Evapotranspiration stress package. The temperature array may be defined by a time-array series (see the ``Using Time-Array Series in a Package'' section). -default_value 0. - diff --git a/doc/mf6io/mf6ivar/examples/utl-spc-example.dat b/doc/mf6io/mf6ivar/examples/utl-spc-example.dat index 75a8ebce066..622ef9d2958 100644 --- a/doc/mf6io/mf6ivar/examples/utl-spc-example.dat +++ b/doc/mf6io/mf6ivar/examples/utl-spc-example.dat @@ -8,21 +8,21 @@ BEGIN DIMENSIONS END DIMENSIONS BEGIN PERIOD 1 - 1 concentration myconc1ts - 2 concentration 100. - 3 concentration 100. - 4 concentration 100. - 5 concentration 100. - 6 concentration 100. - 7 concentration 100. - 8 concentration 100. - 9 concentration 100. - 10 concentration 100. + 1 concentration myconc1ts + 2 concentration 100.0 + 3 concentration 100.0 + 4 concentration 100.0 + 5 concentration 100.0 + 6 concentration 100.0 + 7 concentration 100.0 + 8 concentration 100.0 + 9 concentration 100.0 + 10 concentration 100.0 END period # Change boundary 1 and 2 concentrations to zero # and leave boundaries 3 through 10 at 100.0 BEGIN PERIOD 3 - 1 concentration 0. - 2 concentration 0. + 1 concentration 0.0 + 2 concentration 0.0 END period diff --git a/doc/mf6io/mf6ivar/examples/utl-spt-example.dat b/doc/mf6io/mf6ivar/examples/utl-spt-example.dat deleted file mode 100644 index 784a7fc87ff..00000000000 --- a/doc/mf6io/mf6ivar/examples/utl-spt-example.dat +++ /dev/null @@ -1,28 +0,0 @@ -BEGIN options - PRINT_INPUT - TS6 FILEIN heat_transport.wel1.ts -END options - -BEGIN DIMENSIONS - MAXBOUND 10 -END DIMENSIONS - -BEGIN PERIOD 1 - 1 temperature my_temperatures_ts - 2 temperature 20. - 3 temperature 20. - 4 temperature 20. - 5 temperature 20. - 6 temperature 20. - 7 temperature 20. - 8 temperature 20. - 9 temperature 20. - 10 temperature 20. -END period - -# Change boundary 1 and 2 temperatures to 10.0 -# and leave boundaries 3 through 10 at 20.0 -BEGIN PERIOD 3 - 1 temperature 10. - 2 temperature 10. -END period diff --git a/doc/mf6io/mf6ivar/examples/utl-spta-example.dat b/doc/mf6io/mf6ivar/examples/utl-spta-example.dat deleted file mode 100644 index 9f7869fc96e..00000000000 --- a/doc/mf6io/mf6ivar/examples/utl-spta-example.dat +++ /dev/null @@ -1,20 +0,0 @@ -BEGIN options - READASARRAYS - PRINT_INPUT -END options - -BEGIN PERIOD 1 - TEMPERATURE - INTERNAL FACTOR 1.0 - 0.00000000 1.00000000 2.00000000 3.00000000 4.00000000 - 5.00000000 6.00000000 7.00000000 8.00000000 9.00000000 - 10.00000000 11.00000000 12.00000000 13.00000000 14.00000000 - 15.00000000 16.00000000 17.00000000 18.00000000 19.00000000 - 20.00000000 21.00000000 22.00000000 23.00000000 24.00000000 -END PERIOD - -BEGIN PERIOD 3 - TEMPERATURE - CONSTANT 0.0 -END PERIOD - diff --git a/doc/mf6io/utl_spc.tex b/doc/mf6io/utl_spc.tex new file mode 100644 index 00000000000..14a9d818c1a --- /dev/null +++ b/doc/mf6io/utl_spc.tex @@ -0,0 +1,81 @@ +As mentioned in the sections describing the SSM Package for GWT and GWE, concentrations and temperatures, respectively, can be specified for GWF stress packages using auxiliary variables, or they can be specified using input files dedicated to this purpose. The Stress Package Component (SPC) input file can be used to provide concentrations or temperatures that are assigned for GWF sources and sinks. An SPC input file can be list based or array based. List-based input files can be used for list-based GWF stress packages, such as wells, drains, and rivers. Array-based input files can be used for array-based GWF stress packages, such as recharge and evapotranspiration (provided the READASARRAYS options is used; or, if preferred, a list-based format is supported for RCH and EVT as well). The next section describes the list-based input format for the SPC input file followed by a section that describes array-based SPC input files. + +\subsection{Stress Package Component (SPC) -- List-Based Input} + +An SPC6 file can be prepared to provide user-specified concentrations or temperatures for a GWF stress package, such a Well or General-Head Boundary Package, for example. One SPT6 file applies to one GWF stress package. Names for the SPC6 input files are provided in the FILEINPUT block of the SSM Package and therefore cannot be specified in either the GWT or GWE name files. Use of the SPC6 input file is an alternative to specifying stress package temperatures as auxiliary variables in the flow model stress package. + +The boundary number in the PERIOD block corresponds to the boundary number in the GWF stress period package. Assignment of the boundary number is straightforward for the advanced packages (SFR, LAK, MAW, and UZF) because the features in these advanced packages are defined once at the beginning of the simulation and they do not change. For the other stress packages, however, the order of boundaries may change between stress periods. Consider the following Well Package input file, for example: + +\begin{verbatim} +# This is an example of a GWF Well Package +# in which the order of the wells changes from +# stress period 1 to 2. This must be explicitly +# handled by the user if using the SPC6 input +# for a GWT or GWE model. +BEGIN options + BOUNDNAMES +END options + +BEGIN dimensions + MAXBOUND 3 +END dimensions + +BEGIN period 1 + 1 77 65 -2200 SHALLOW_WELL + 2 77 65 -24.0 INTERMEDIATE_WELL + 3 77 65 -6.20 DEEP_WELL +END period + +BEGIN period 2 + 1 77 65 -1100 SHALLOW_WELL + 3 77 65 -3.10 DEEP_WELL + 2 77 65 -12.0 INTERMEDIATE_WELL +END period +\end{verbatim} + +\noindent In this Well input file, the order of the wells changed between periods 1 and 2. This reordering must be explicitly taken into account by the user when creating an SPC6 file, because the boundary number in the SPC file corresponds to the boundary number in the Well input file. In stress period 1, boundary number 2 is the INTERMEDIATE\_WELL, whereas in stress period 2, boundary number 2 is the DEEP\_WELL. When using this SPC capability to specify boundary temperatures, it is recommended that users write the corresponding GWF stress packages using the same number, cell locations, and order of boundary conditions for each stress period. In addition, users can activate the PRINT\_FLOWS option in the SSM input file. When the SSM Package prints the individual solute flows to the transport list file, it includes a column containing the boundary concentration or temperature. Users can check the boundary concentrations (or temperatures) in this output to verify that they are assigned as intended. + +\vspace{5mm} +\subsubsection{Structure of Blocks} +\vspace{5mm} + +\noindent \textit{FOR EACH SIMULATION} +\lstinputlisting[style=blockdefinition]{./mf6ivar/tex/utl-spc-options.dat} +\lstinputlisting[style=blockdefinition]{./mf6ivar/tex/utl-spc-dimensions.dat} +\vspace{5mm} +\noindent \textit{FOR ANY STRESS PERIOD} +\lstinputlisting[style=blockdefinition]{./mf6ivar/tex/utl-spc-period.dat} + +\vspace{5mm} +\subsubsection{Explanation of Variables} +\begin{description} +\input{./mf6ivar/tex/utl-spc-desc.tex} +\end{description} + +\subsubsection{Example Input File} +\lstinputlisting[style=inputfile]{./mf6ivar/examples/utl-spc-example.dat} + +% SPT array based +\newpage +\subsection{Stress Package Component (SPC) -- Array-Based Input} + +This section describes array-based input for the SPC input file. If the READASARRAYS options is specified for either the GWF Recharge (RCH) or Evapotranspiration (EVT) Packages, then concentrations or temperatures for these packages can be specified using array-based input. This SPC array-based input is distinguished from the list-based input in the previous section through specification of the READASARRAYS option. When the READASARRAYS option is specified, then there is no DIMENSIONS block in the SPC input file. Instead, the shape of the array for concentrations or temperatures is the number of rows by number of columns (NROW, NCOL), for a regular MODFLOW grid (DIS), and the number of cells in a layer (NCPL) for a discretization by vertices (DISV) grid. + +\vspace{5mm} +\subsubsection{Structure of Blocks} +\vspace{5mm} + +\noindent \textit{FOR EACH SIMULATION} +\lstinputlisting[style=blockdefinition]{./mf6ivar/tex/utl-spca-options.dat} +\vspace{5mm} +\noindent \textit{FOR ANY STRESS PERIOD} +\lstinputlisting[style=blockdefinition]{./mf6ivar/tex/utl-spca-period.dat} + +\vspace{5mm} +\subsubsection{Explanation of Variables} +\begin{description} +\input{./mf6ivar/tex/utl-spca-desc.tex} +\end{description} + +\subsubsection{Example Input File} +\lstinputlisting[style=inputfile]{./mf6ivar/examples/utl-spca-example.dat} \ No newline at end of file diff --git a/make/makefile b/make/makefile index 71bc053718f..7aebe899061 100644 --- a/make/makefile +++ b/make/makefile @@ -1,51 +1,51 @@ -# makefile created by pymake (version 1.2.11.dev0) for the 'mf6' executable. +# makefile created by pymake (version 1.2.10.dev0) for the 'mf6' executable. include ./makedefaults # Define the source file directories SOURCEDIR1=../src -SOURCEDIR2=../src/Idm -SOURCEDIR3=../src/Idm/selector -SOURCEDIR4=../src/Exchange -SOURCEDIR5=../src/Distributed -SOURCEDIR6=../src/Solution -SOURCEDIR7=../src/Solution/LinearMethods -SOURCEDIR8=../src/Solution/ParticleTracker -SOURCEDIR9=../src/Solution/PETSc -SOURCEDIR10=../src/Timing -SOURCEDIR11=../src/Utilities -SOURCEDIR12=../src/Utilities/Idm -SOURCEDIR13=../src/Utilities/Idm/mf6blockfile -SOURCEDIR14=../src/Utilities/Idm/netcdf -SOURCEDIR15=../src/Utilities/TimeSeries -SOURCEDIR16=../src/Utilities/Memory -SOURCEDIR17=../src/Utilities/OutputControl -SOURCEDIR18=../src/Utilities/ArrayRead -SOURCEDIR19=../src/Utilities/Libraries -SOURCEDIR20=../src/Utilities/Libraries/rcm -SOURCEDIR21=../src/Utilities/Libraries/blas -SOURCEDIR22=../src/Utilities/Libraries/sparskit2 -SOURCEDIR23=../src/Utilities/Libraries/daglib -SOURCEDIR24=../src/Utilities/Libraries/sparsekit -SOURCEDIR25=../src/Utilities/Export -SOURCEDIR26=../src/Utilities/Vector -SOURCEDIR27=../src/Utilities/Matrix -SOURCEDIR28=../src/Utilities/Observation -SOURCEDIR29=../src/Model -SOURCEDIR30=../src/Model/Connection -SOURCEDIR31=../src/Model/ChannelFlow -SOURCEDIR32=../src/Model/OverlandFlow -SOURCEDIR33=../src/Model/ParticleTracking -SOURCEDIR34=../src/Model/SurfaceWaterFlow -SOURCEDIR35=../src/Model/GroundWaterTransport -SOURCEDIR36=../src/Model/ModelUtilities -SOURCEDIR37=../src/Model/GroundWaterFlow -SOURCEDIR38=../src/Model/GroundWaterFlow/submodules -SOURCEDIR39=../src/Model/Discretization -SOURCEDIR40=../src/Model/TransportModel -SOURCEDIR41=../src/Model/Geometry -SOURCEDIR42=../src/Model/GroundWaterEnergy +SOURCEDIR2=../src/Distributed +SOURCEDIR3=../src/Exchange +SOURCEDIR4=../src/Idm +SOURCEDIR5=../src/Idm/selector +SOURCEDIR6=../src/Model +SOURCEDIR7=../src/Model/ChannelFlow +SOURCEDIR8=../src/Model/Connection +SOURCEDIR9=../src/Model/Discretization +SOURCEDIR10=../src/Model/Geometry +SOURCEDIR11=../src/Model/GroundWaterEnergy +SOURCEDIR12=../src/Model/GroundWaterFlow +SOURCEDIR13=../src/Model/GroundWaterFlow/submodules +SOURCEDIR14=../src/Model/GroundWaterTransport +SOURCEDIR15=../src/Model/ModelUtilities +SOURCEDIR16=../src/Model/OverlandFlow +SOURCEDIR17=../src/Model/ParticleTracking +SOURCEDIR18=../src/Model/SurfaceWaterFlow +SOURCEDIR19=../src/Model/TransportModel +SOURCEDIR20=../src/Solution +SOURCEDIR21=../src/Solution/LinearMethods +SOURCEDIR22=../src/Solution/ParticleTracker +SOURCEDIR23=../src/Solution/PETSc +SOURCEDIR24=../src/Timing +SOURCEDIR25=../src/Utilities +SOURCEDIR26=../src/Utilities/ArrayRead +SOURCEDIR27=../src/Utilities/Export +SOURCEDIR28=../src/Utilities/Idm +SOURCEDIR29=../src/Utilities/Idm/mf6blockfile +SOURCEDIR30=../src/Utilities/Idm/netcdf +SOURCEDIR31=../src/Utilities/Libraries +SOURCEDIR32=../src/Utilities/Libraries/blas +SOURCEDIR33=../src/Utilities/Libraries/daglib +SOURCEDIR34=../src/Utilities/Libraries/rcm +SOURCEDIR35=../src/Utilities/Libraries/sparsekit +SOURCEDIR36=../src/Utilities/Libraries/sparskit2 +SOURCEDIR37=../src/Utilities/Matrix +SOURCEDIR38=../src/Utilities/Memory +SOURCEDIR39=../src/Utilities/Observation +SOURCEDIR40=../src/Utilities/OutputControl +SOURCEDIR41=../src/Utilities/TimeSeries +SOURCEDIR42=../src/Utilities/Vector VPATH = \ ${SOURCEDIR1} \ @@ -309,8 +309,8 @@ $(OBJDIR)/CellRectQuad.o \ $(OBJDIR)/CellRect.o \ $(OBJDIR)/VirtualModel.o \ $(OBJDIR)/BaseExchange.o \ +$(OBJDIR)/TspSpc.o \ $(OBJDIR)/tsp-fmi.o \ -$(OBJDIR)/GwtSpc.o \ $(OBJDIR)/GweInputData.o \ $(OBJDIR)/OutputControl.o \ $(OBJDIR)/tsp-ic.o \ diff --git a/msvs/mf6core.vfproj b/msvs/mf6core.vfproj index cc81f11cd98..2483ba98bdf 100644 --- a/msvs/mf6core.vfproj +++ b/msvs/mf6core.vfproj @@ -318,7 +318,7 @@ - + diff --git a/src/Model/GroundWaterEnergy/gwe-ctp.f90 b/src/Model/GroundWaterEnergy/gwe-ctp.f90 index e8963a50bd2..d66f5bc5bc0 100644 --- a/src/Model/GroundWaterEnergy/gwe-ctp.f90 +++ b/src/Model/GroundWaterEnergy/gwe-ctp.f90 @@ -11,7 +11,6 @@ module GweCtpModule use ObserveModule, only: ObserveType use TimeSeriesLinkModule, only: TimeSeriesLinkType, & GetTimeSeriesLinkFromList - use InputOutputModule, only: str_pad_left use MatrixBaseModule ! implicit none diff --git a/src/Model/GroundWaterTransport/gwt-cnc.f90 b/src/Model/GroundWaterTransport/gwt-cnc.f90 index 39b00d2abbd..fce07d1f731 100644 --- a/src/Model/GroundWaterTransport/gwt-cnc.f90 +++ b/src/Model/GroundWaterTransport/gwt-cnc.f90 @@ -11,7 +11,6 @@ module GwtCncModule use ObserveModule, only: ObserveType use TimeSeriesLinkModule, only: TimeSeriesLinkType, & GetTimeSeriesLinkFromList - use InputOutputModule, only: str_pad_left use MatrixBaseModule ! implicit none diff --git a/src/Model/ModelUtilities/GwtSpc.f90 b/src/Model/ModelUtilities/TspSpc.f90 similarity index 92% rename from src/Model/ModelUtilities/GwtSpc.f90 rename to src/Model/ModelUtilities/TspSpc.f90 index bcdb4a61ddc..81da6d621cc 100644 --- a/src/Model/ModelUtilities/GwtSpc.f90 +++ b/src/Model/ModelUtilities/TspSpc.f90 @@ -1,15 +1,16 @@ -!> @brief This module contains the GwtSpc Module +!> @brief This module contains the TspSpc Module !! !! This module contains the code for reading and storing a -!! generic input file of source and sink concentrations. -!! +!! generic input file of source and sink concentrations or +!! temperatures. !< -module GwtSpcModule +module TspSpcModule use KindModule, only: DP, LGP, I4B use ConstantsModule, only: LENPACKAGENAME, LENMODELNAME, & LENMEMPATH, DZERO, LENFTYPE, & - LINELENGTH, TABLEFT, TABCENTER + LINELENGTH, TABLEFT, TABCENTER, & + LENVARNAME use SimVariablesModule, only: errmsg use SimModule, only: store_error, count_errors use MemoryHelperModule, only: create_mem_path @@ -18,28 +19,29 @@ module GwtSpcModule use TimeSeriesManagerModule, only: TimeSeriesManagerType, tsmanager_cr use TimeArraySeriesManagerModule, only: TimeArraySeriesManagerType, & tasmanager_cr + use InputOutputModule, only: str_pad_left use TableModule, only: TableType, table_cr implicit none private - public :: GwtSpcType + public :: TspSpcType character(len=LENFTYPE) :: ftype = 'SPC' - character(len=LENPACKAGENAME) :: text = 'STRESS PACK CONC' + character(len=LENPACKAGENAME) :: text = 'STRESS PACK COMP' !> @brief Derived type for managing SPC input !! !! This derived type will read and process an SPC input file, - !! make time series interpolations, and provide concentrations to - !! the SSM package that correspond to an individual GWF stress - !! package. - !! + !! make time series interpolations, and provide concentrations or + !! temperatures to the SSM package that correspond to an individual + !! GWF stress package. !< - type :: GwtSpcType + type :: TspSpcType character(len=LENMODELNAME) :: name_model = '' !< the name of the model that contains this package character(len=LENPACKAGENAME) :: packName = '' !< name of the package character(len=LENPACKAGENAME) :: packNameFlow = '' !< name of the corresponding flow package + character(len=LENVARNAME) :: depvarname = '' !< name of the dependent variable (CONCENTRATION or TEMPERATURE) character(len=LENMEMPATH) :: memoryPath = '' !< the location in the memory manager where the variables are stored integer(I4B), pointer :: id => null() !< id number for this spc package integer(I4B), pointer :: inunit => null() !< unit number for input @@ -73,7 +75,7 @@ module GwtSpcModule procedure :: read_check_ionper procedure :: check_flow_package - end type GwtSpcType + end type TspSpcType contains @@ -84,15 +86,17 @@ module GwtSpcModule !! and allocating memory. !! !< - subroutine initialize(this, dis, id, inunit, iout, name_model, packNameFlow) + subroutine initialize(this, dis, id, inunit, iout, name_model, packNameFlow, & + dvn) ! -- dummy variables - class(GwtSpcType) :: this !< GwtSpcType + class(TspSpcType) :: this !< TspSpcType class(DisBaseType), pointer, intent(in) :: dis !< discretization package integer(I4B), intent(in) :: id !< id number for this spc package integer(I4B), intent(in) :: inunit !< unit number for input integer(I4B), intent(in) :: iout !< unit number for output character(len=*), intent(in) :: name_model !< character string containing model name character(len=*), intent(in) :: packNameflow !< character string containing name of corresponding flow package + character(len=*), intent(in) :: dvn !< dependent variable name (CONCENTRATION or TEMPERATURE) ! -- local ! ! -- construct the memory path @@ -108,6 +112,7 @@ subroutine initialize(this, dis, id, inunit, iout, name_model, packNameFlow) this%inunit = inunit this%iout = iout this%packNameFlow = packNameFlow + this%depvarname = dvn ! ! -- set pointers this%dis => dis @@ -149,7 +154,7 @@ subroutine allocate_scalars(this) ! -- modules use MemoryManagerModule, only: mem_allocate ! -- dummy variables - class(GwtSpcType) :: this !< GwtSpcType object + class(TspSpcType) :: this !< TspSpcType object ! ! -- allocate scalars in memory manager call mem_allocate(this%id, 'ID', this%memoryPath) @@ -187,7 +192,7 @@ end subroutine allocate_scalars subroutine read_options(this) ! -- modules ! -- dummy - class(GwtSpcType) :: this + class(TspSpcType) :: this ! -- local character(len=LINELENGTH) :: keyword, fname integer(I4B) :: ierr @@ -262,7 +267,7 @@ end subroutine read_options !< subroutine read_dimensions(this) ! -- dummy variables - class(GwtSpcType), intent(inout) :: this !< GwtSpcType object + class(TspSpcType), intent(inout) :: this !< TspSpcType object ! -- local variables character(len=LINELENGTH) :: keyword logical(LGP) :: isfound @@ -322,7 +327,7 @@ subroutine allocate_arrays(this) ! -- modules use MemoryManagerModule, only: mem_allocate ! -- dummy variables - class(GwtSpcType) :: this !< GwtSpcType object + class(TspSpcType) :: this !< TspSpcType object ! -- local integer(I4B) :: i ! @@ -344,7 +349,7 @@ end subroutine allocate_arrays !! !< function get_value(this, ientry, nbound_flow) result(value) - class(GwtSpcType) :: this !< GwtSpcType object + class(TspSpcType) :: this !< TspSpcType object integer(I4B), intent(in) :: ientry !< index of the data to return integer(I4B), intent(in) :: nbound_flow !< size of bound list in flow package real(DP) :: value @@ -392,7 +397,7 @@ subroutine spc_rp(this) ! -- modules use TdisModule, only: kper, nper ! -- dummy - class(GwtSpcType), intent(inout) :: this !< GwtSpcType object + class(TspSpcType), intent(inout) :: this !< TspSpcType object ! -- local character(len=LINELENGTH) :: line logical :: isfound @@ -471,7 +476,7 @@ subroutine spc_rp_list(this) ! -- modules use TdisModule, only: kper ! -- dummy - class(GwtSpcType), intent(inout) :: this !< GwtSpcType object + class(TspSpcType), intent(inout) :: this !< TspSpcType object ! -- local character(len=LINELENGTH) :: line character(len=LINELENGTH) :: title @@ -536,11 +541,11 @@ end subroutine spc_rp_list !! !< subroutine spc_rp_array(this, line) - use ConstantsModule, only: LENTIMESERIESNAME + use ConstantsModule, only: LENTIMESERIESNAME, LENANAME use SimModule, only: store_error use ArrayHandlersModule, only: ifind ! -- dummy - class(GwtSpcType), intent(inout) :: this !< GwtSpcType object + class(TspSpcType), intent(inout) :: this !< TspSpcType object character(len=LINELENGTH), intent(inout) :: line ! -- local integer(I4B) :: n @@ -548,7 +553,7 @@ subroutine spc_rp_array(this, line) integer(I4B) :: jauxcol, ivarsread integer(I4B), dimension(:), allocatable, target :: nodelist character(len=LENTIMESERIESNAME) :: tasName - character(len=24), dimension(1) :: aname + character(len=LENANAME) :: aname character(len=LINELENGTH) :: keyword logical :: endOfBlock logical :: convertFlux @@ -556,9 +561,8 @@ subroutine spc_rp_array(this, line) ! -- these time array series pointers need to be non-contiguous ! because a slice of bound is passed real(DP), dimension(:), pointer :: bndArrayPtr => null() - ! -- formats - ! -- data - data aname(1)/' CONCENTRATION'/ + ! + write (aname, '(a)') str_pad_left(this%depvarname, LENANAME) ! ! -- Initialize jauxcol = 0 @@ -577,7 +581,7 @@ subroutine spc_rp_array(this, line) ! ! -- Parse the keywords select case (keyword) - case ('CONCENTRATION') + case ('CONCENTRATION', 'TEMPERATURE') ! ! -- Look for keyword TIMEARRAYSERIES and time-array series ! name on line, following RECHARGE @@ -591,19 +595,20 @@ subroutine spc_rp_array(this, line) convertflux = .false. call this%TasManager%MakeTasLink(this%packName, bndArrayPtr, & this%iprpak, tasName, & - 'CONCENTRATION', & + this%depvarname, & convertFlux, nodelist, & this%parser%iuactive) else ! ! -- Read the concentration array call this%dis%read_layer_array(nodelist, this%dblvec, ncolbnd, & - this%maxbound, 1, aname(1), & + this%maxbound, 1, aname, & this%parser%iuactive, this%iout) end if ! case default - call store_error('Looking for CONCENTRATION. Found: '//trim(line)) + call store_error('Looking for component name, either CONCENTRATION & + &or TEMPERATURE. Found: '//trim(line)) call this%parser%StoreErrorUnit() end select @@ -621,7 +626,7 @@ end subroutine spc_rp_array subroutine spc_ad(this, nbound_flowpack, budtxt) ! -- modules ! -- dummy - class(GwtSpcType), intent(inout) :: this !< GwtSpcType object + class(TspSpcType), intent(inout) :: this !< TspSpcType object integer(I4B), intent(in) :: nbound_flowpack character(len=*), intent(in) :: budtxt ! -- local @@ -646,7 +651,7 @@ subroutine spc_da(this) ! -- modules use MemoryManagerModule, only: mem_deallocate ! -- dummy variables - class(GwtSpcType) :: this !< GwtSpcType object + class(TspSpcType) :: this !< TspSpcType object ! ! -- deallocate arrays in memory manager call mem_deallocate(this%dblvec) @@ -682,7 +687,7 @@ subroutine read_check_ionper(this) ! -- modules use TdisModule, only: kper ! -- dummy variables - class(GwtSpcType), intent(inout) :: this !< GwtSpcType object + class(TspSpcType), intent(inout) :: this !< TspSpcType object ! ! -- save last value and read period number this%lastonper = this%ionper @@ -712,7 +717,7 @@ subroutine set_value(this, ival) ! -- modules use TimeSeriesManagerModule, only: read_value_or_time_series_adv ! -- dummy - class(GwtSpcType), intent(inout) :: this !< GwtSpcType object + class(TspSpcType), intent(inout) :: this !< TspSpcType object integer(I4B), intent(in) :: ival ! -- local character(len=LINELENGTH) :: keyword @@ -722,13 +727,13 @@ subroutine set_value(this, ival) ! -- read remainder of variables on the line call this%parser%GetStringCaps(keyword) select case (keyword) - case ('CONCENTRATION') + case ('CONCENTRATION', 'TEMPERATURE') call this%parser%GetString(text) jj = 1 ! For CONCENTRATION bndElem => this%dblvec(ival) call read_value_or_time_series_adv(text, ival, jj, bndElem, this%packName, & 'BND', this%tsManager, this%iprpak, & - 'CONCENTRATION') + this%depvarname) end select return @@ -743,7 +748,7 @@ end subroutine set_value subroutine check_flow_package(this, nbound_flowpack, budtxt) ! -- modules ! -- dummy - class(GwtSpcType), intent(inout) :: this !< GwtSpcType object + class(TspSpcType), intent(inout) :: this !< TspSpcType object integer(I4B), intent(in) :: nbound_flowpack character(len=*), intent(in) :: budtxt ! -- local @@ -801,4 +806,4 @@ subroutine check_flow_package(this, nbound_flowpack, budtxt) return end subroutine check_flow_package -end module GwtSpcModule +end module TspSpcModule diff --git a/src/Model/TransportModel/tsp-ssm.f90 b/src/Model/TransportModel/tsp-ssm.f90 index 87dc2f62beb..830ff244b30 100644 --- a/src/Model/TransportModel/tsp-ssm.f90 +++ b/src/Model/TransportModel/tsp-ssm.f90 @@ -18,7 +18,7 @@ module TspSsmModule use TspFmiModule, only: TspFmiType use GweInputDataModule, only: GweInputDataType use TableModule, only: TableType, table_cr - use GwtSpcModule, only: GwtSpcType + use TspSpcModule, only: TspSpcType use MatrixBaseModule implicit none @@ -38,12 +38,12 @@ module TspSsmModule integer(I4B), pointer :: nbound !< total number of flow boundaries in this time step integer(I4B), dimension(:), pointer, contiguous :: isrctype => null() !< source type 0 is unspecified, 1 is aux, 2 is auxmixed, 3 is ssmi, 4 is ssmimixed - integer(I4B), dimension(:), pointer, contiguous :: iauxpak => null() !< aux col for concentration + integer(I4B), dimension(:), pointer, contiguous :: iauxpak => null() !< aux col for concentration/temperature integer(I4B), dimension(:), pointer, contiguous :: ibound => null() !< pointer to model ibound real(DP), dimension(:), pointer, contiguous :: cnew => null() !< pointer to gwt%x type(TspFmiType), pointer :: fmi => null() !< pointer to fmi object type(TableType), pointer :: outputtab => null() !< output table object - type(GwtSpcType), dimension(:), pointer :: ssmivec => null() !< array of stress package concentration objects + type(TspSpcType), dimension(:), pointer :: ssmivec => null() !< array of stress package concentration or temperature objects real(DP), pointer :: eqnsclfac => null() !< governing equation scale factor; =1. for solute; =rhow*cpw for energy character(len=LENVARNAME) :: depvartype = '' @@ -190,15 +190,15 @@ end subroutine ssm_ar !! !! This routine is called from gwt_rp(). It is called at the beginning of !! each stress period. If any SPC input files are used to provide source - !! and sink concentrations, then period blocks for the current stress period - !! are read. + !! and sink concentrations (or temperatures), then period blocks for the + !! current stress period are read. !< subroutine ssm_rp(this) ! -- dummy class(TspSsmType) :: this !< TspSsmType object ! -- local integer(I4B) :: ip - type(GwtSpcType), pointer :: ssmiptr + type(TspSpcType), pointer :: ssmiptr ! -- formats ! ! -- Call the rp method on any ssm input files @@ -219,15 +219,16 @@ end subroutine ssm_rp !! This routine is called from gwt_ad(). It is called at the beginning of !! each time step. The total number of flow boundaries is counted and stored !! in this%nbound. Also, if any SPC input files are used to provide source - !! and sink concentrations and time series are referenced in those files, - !! then ssm concenrations must be interpolated for the time step. + !! and sink concentrations (or temperatures) and time series are referenced + !! in those files, then ssm concenrations must be interpolated for the time + !! step. !< subroutine ssm_ad(this) ! -- dummy class(TspSsmType) :: this !< TspSsmType object ! -- local integer(I4B) :: ip - type(GwtSpcType), pointer :: ssmiptr + type(TspSpcType), pointer :: ssmiptr integer(I4B) :: i integer(I4B) :: node ! @@ -276,7 +277,7 @@ subroutine ssm_term(this, ipackage, ientry, rrate, rhsval, hcofval, & real(DP), intent(out), optional :: rrate !< calculated mass flow rate real(DP), intent(out), optional :: rhsval !< calculated rhs value real(DP), intent(out), optional :: hcofval !< calculated hcof value - real(DP), intent(out), optional :: cssm !< calculated source concentration depending on flow direction + real(DP), intent(out), optional :: cssm !< calculated source concentration/temperature depending on flow direction real(DP), intent(out), optional :: qssm !< water flow rate into model cell from boundary package ! -- local logical(LGP) :: lauxmixed @@ -307,10 +308,10 @@ subroutine ssm_term(this, ipackage, ientry, rrate, rhsval, hcofval, & ! of hcof, rhs, and rate if (.not. lauxmixed) then ! - ! -- If qbnd is positive, then concentration represents the inflow - ! concentration. If qbnd is negative, then the outflow concentration - ! (or temperature) is set equal to the simulated cell's concentration - ! (or temperature). + ! -- If qbnd is positive, then concentration (or temperature) represents + ! the inflow concentration (or temperature). If qbnd is negative, + ! then the outflow concentration (or temperature) is set equal to the + ! simulated cell's concentration (or temperature). if (qbnd >= DZERO) then omega = DZERO ! rhs else @@ -323,10 +324,11 @@ subroutine ssm_term(this, ipackage, ientry, rrate, rhsval, hcofval, & else ! ! -- lauxmixed value indicates that this is a mixed sink type where - ! the concentration value represents the injected concentration (or - ! temperature) if qbnd is positive. If qbnd is negative, then the - ! withdrawn water is equal to the minimum of the aux concentration - ! (or temperature) and the cell concentration (or temperature). + ! the concentration (or temperature) value represents the injected + ! concentration (or temperature) if qbnd is positive. If qbnd is + ! negative, then the withdrawn water is equal to the minimum of the + ! aux concentration (or temperature) and the cell concentration + ! (or temperature). if (qbnd >= DZERO) then omega = DZERO ! rhs (ctmp is aux value) else @@ -376,7 +378,7 @@ subroutine get_ssm_conc(this, ipackage, ientry, nbound_flow, conc, & integer(I4B), intent(in) :: ipackage !< package number integer(I4B), intent(in) :: ientry !< bound number integer(I4B), intent(in) :: nbound_flow !< size of flow package bound list - real(DP), intent(out) :: conc !< user-specified concentration for this bound + real(DP), intent(out) :: conc !< user-specified concentration/temperature for this bound logical(LGP), intent(out) :: lauxmixed !< user-specified flag for marking this as a mixed boundary ! -- local integer(I4B) :: isrctype @@ -681,7 +683,7 @@ subroutine ssm_da(this) class(TspSsmType) :: this !< TspSsmType object ! -- local integer(I4B) :: ip - type(GwtSpcType), pointer :: ssmiptr + type(TspSpcType), pointer :: ssmiptr ! ! -- Deallocate the ssmi objects if package was active if (this%inunit > 0) then @@ -1115,7 +1117,7 @@ subroutine set_ssmivec(this, ip, packname) character(len=*), intent(in) :: packname !< name of package ! -- local character(len=LINELENGTH) :: filename - type(GwtSpcType), pointer :: ssmiptr + type(TspSpcType), pointer :: ssmiptr integer(I4B) :: inunit ! ! -- read file name @@ -1126,7 +1128,7 @@ subroutine set_ssmivec(this, ip, packname) ! -- Create the SPC file object ssmiptr => this%ssmivec(ip) call ssmiptr%initialize(this%dis, ip, inunit, this%iout, this%name_model, & - trim(packname)) + trim(packname), this%depvartype) ! write (this%iout, '(4x, a, a, a, a, a)') 'USING SPC INPUT FILE ', & trim(filename), ' TO SET ', trim(this%depvartype), & diff --git a/src/Utilities/Constants.f90 b/src/Utilities/Constants.f90 index 933294d2a86..7b2423e6d96 100644 --- a/src/Utilities/Constants.f90 +++ b/src/Utilities/Constants.f90 @@ -17,6 +17,7 @@ module ConstantsModule integer(I4B), parameter :: LENVARNAME = 16 !< maximum length of a variable name integer(I4B), parameter :: LENCOMPONENTNAME = 16 !< maximum length of a component name integer(I4B), parameter :: LENCONTEXTNAME = 16 !< maximum length of a memory manager context + integer(I4B), parameter :: LENANAME = 24 !< maximum length of the header text for an array integer(I4B), parameter :: LENSOLUTIONNAME = LENCOMPONENTNAME !< maximum length of the solution name integer(I4B), parameter :: LENMODELNAME = LENCOMPONENTNAME !< maximum length of the model name integer(I4B), parameter :: LENPACKAGENAME = LENCOMPONENTNAME !< maximum length of the package name diff --git a/src/meson.build b/src/meson.build index 90e47691f2f..5e61da02a0f 100644 --- a/src/meson.build +++ b/src/meson.build @@ -239,7 +239,6 @@ modflow_sources = files( 'Model' / 'ModelUtilities' / 'GwfStorageUtils.f90', 'Model' / 'ModelUtilities' / 'GwfVscInputData.f90', 'Model' / 'ModelUtilities' / 'GwtDspOptions.f90', - 'Model' / 'ModelUtilities' / 'GwtSpc.f90', 'Model' / 'ModelUtilities' / 'ModelPackageInput.f90', 'Model' / 'ModelUtilities' / 'Mover.f90', 'Model' / 'ModelUtilities' / 'PackageMover.f90', @@ -248,6 +247,7 @@ modflow_sources = files( 'Model' / 'ModelUtilities' / 'SfrCrossSectionUtils.f90', 'Model' / 'ModelUtilities' / 'SwfCxsUtils.f90', 'Model' / 'ModelUtilities' / 'TspAdvOptions.f90', + 'Model' / 'ModelUtilities' / 'TspSpc.f90', 'Model' / 'ModelUtilities' / 'TimeSelect.f90', 'Model' / 'ModelUtilities' / 'TimeStepSelect.f90', 'Model' / 'ModelUtilities' / 'TrackData.f90',