diff --git a/src/hsp2/__init__.py b/src/hsp2/__init__.py index 6f12cf93..d3ce71cd 100644 --- a/src/hsp2/__init__.py +++ b/src/hsp2/__init__.py @@ -1,16 +1,16 @@ -"""The Hydrologic Simulation Program - Python (HSP2) watershed model is is a - port of the well-established Hydrological Simulation Program - FORTRAN (HSPF), - re-coded with modern scientific Python and data formats. +"""The Hydrologic Simulation Program - Python (HSP2) watershed model is is a +port of the well-established Hydrological Simulation Program - FORTRAN (HSPF), +re-coded with modern scientific Python and data formats. - Modules: - - HSP2 contains the hydrology and water quality code modules converted from - HSPF, along with the main programs to run HSP2. - - HSP2tools contains supporting software modules such as the code to convert - legacy WDM and UCI files to HDF5 files for HSP2, and to provide additional - new and legacy capabilities. - - HSP2IO is new in v0.10 and contains an abstracted approach to getting data - in and out of HSP2 for flexibility and performance and also to support future - automation and model coupling. +Modules: + - HSP2 contains the hydrology and water quality code modules converted from + HSPF, along with the main programs to run HSP2. + - HSP2tools contains supporting software modules such as the code to convert + legacy WDM and UCI files to HDF5 files for HSP2, and to provide additional + new and legacy capabilities. + - HSP2IO is new in v0.10 and contains an abstracted approach to getting data + in and out of HSP2 for flexibility and performance and also to support future + automation and model coupling. """ from importlib.metadata import version, PackageNotFoundError @@ -19,5 +19,8 @@ __version__ = version("hsp2") except PackageNotFoundError: import os - with open(os.path.join(os.path.dirname(__file__),"../..", "VERSION"), encoding="ascii") as version_file: + + with open( + os.path.join(os.path.dirname(__file__), "../..", "VERSION"), encoding="ascii" + ) as version_file: __version__ = version_file.read().strip() diff --git a/src/hsp2/hsp2/ADCALC.py b/src/hsp2/hsp2/ADCALC.py index 396c6c0c..72f36c5e 100644 --- a/src/hsp2/hsp2/ADCALC.py +++ b/src/hsp2/hsp2/ADCALC.py @@ -8,7 +8,7 @@ """ from numba import njit -from numpy import array, zeros +from numpy import zeros from hsp2.hsp2.utilities import make_numba_dict @@ -18,14 +18,14 @@ ERRMSG = [] -def adcalc(io_manager, siminfo, uci, ts): +def adcalc(io_manager, siminfo, parameter, ts): """Prepare to simulate advection of fully entrained constituents""" errorsV = zeros(len(ERRMSG), dtype=int) simlen = siminfo["steps"] - ui = make_numba_dict(uci) + ui = make_numba_dict(parameter) nexits = int(ui["NEXITS"]) # table type GEN-INFO ui["simlen"] = siminfo["steps"] ui["delts"] = siminfo["delt"] * 60.0 # delts is the simulation interval in seconds @@ -55,7 +55,7 @@ def adcalc(io_manager, siminfo, uci, ts): SOVOL[:, i] = ts["SOVOL" + str(i + 1)] EOVOL[:, i] = ts["EOVOL" + str(i + 1)] - uci["adcalcData"] = (nexits, vol, VOL, SROVOL, EROVOL, SOVOL, EOVOL) + parameter["adcalcData"] = (nexits, vol, VOL, SROVOL, EROVOL, SOVOL, EOVOL) return errorsV, ERRMSG diff --git a/src/hsp2/hsp2/ATEMP.py b/src/hsp2/hsp2/ATEMP.py index fc385463..98bf5411 100644 --- a/src/hsp2/hsp2/ATEMP.py +++ b/src/hsp2/hsp2/ATEMP.py @@ -7,17 +7,17 @@ from numpy import empty, int64, zeros from hsp2.hsp2.utilities import LAPSE, hoursval, make_numba_dict -from hsp2.hsp2io.protocols import Category, SupportsReadTS +from hsp2.hsp2io.protocols import SupportsReadTS ERRMSGS = () -def atemp(io_manager: SupportsReadTS, siminfo, uci, ts): +def atemp(io_manager: SupportsReadTS, siminfo, parameters, ts): """high level driver for air temperature module""" ts["LAPSE"] = hoursval(siminfo, LAPSE, lapselike=True) - ui = make_numba_dict(uci) # Note: all values coverted to float automatically + ui = make_numba_dict(parameters) # Note: all values coverted to float automatically ui["k"] = siminfo["delt"] * 0.000833 # convert to in/timestep ui["steps"] = siminfo["steps"] ui["errlen"] = len(ERRMSGS) diff --git a/src/hsp2/hsp2/CONS.py b/src/hsp2/hsp2/CONS.py index b1ea6163..5f26ad5f 100644 --- a/src/hsp2/hsp2/CONS.py +++ b/src/hsp2/hsp2/CONS.py @@ -26,7 +26,7 @@ ERRMSG = [] -def cons(io_manager, siminfo, uci, ts): +def cons(io_manager, siminfo, parameters, ts): """Simulate behavior of conservative constituents; calculate concentration of conservative constituents after advection""" @@ -40,7 +40,7 @@ def cons(io_manager, siminfo, uci, ts): # si units conversion constants, 1 hectare is 10000 sq m AFACT = 1000000.0 - advectData = uci["advectData"] + advectData = parameters["advectData"] (nexits, vol, VOL, SROVOL, EROVOL, SOVOL, EOVOL) = advectData svol = vol * AFACT @@ -51,7 +51,7 @@ def cons(io_manager, siminfo, uci, ts): ts["SOVOL" + str(i + 1)] = SOVOL[:, i] ts["EOVOL" + str(i + 1)] = EOVOL[:, i] - ui = make_numba_dict(uci) + ui = make_numba_dict(parameters) nexits = int(ui["NEXITS"]) ui["simlen"] = siminfo["steps"] @@ -63,13 +63,13 @@ def cons(io_manager, siminfo, uci, ts): # conactive = ui['CONACTIVE'] # dict ncons = 1 - if "PARAMETERS" in uci: - if "NCONS" in uci["PARAMETERS"]: - ncons = uci["PARAMETERS"]["NCONS"] + if "PARAMETERS" in parameters: + if "NCONS" in parameters["PARAMETERS"]: + ncons = parameters["PARAMETERS"]["NCONS"] for index in range(ncons): icon = str(index + 1) - parms = uci["CONS" + icon] + parms = parameters["CONS" + icon] conid = parms["CONID"] # string name of the conservative constituent con = parms["CON"] # initial concentration of the conservative concid = parms[ @@ -92,13 +92,17 @@ def cons(io_manager, siminfo, uci, ts): # COADFG2 = ui['COADFG2'] # table-type cons-ad-flags # COADCN = getit() # flag: COADFG; monthly COACNM; value COADCN - if "FLAGS" in uci: - u = uci["FLAGS"] + if "FLAGS" in parameters: + u = parameters["FLAGS"] # get atmos dep timeseries coadfg1 = u["COADFG" + str((index * 2) - 1)] if coadfg1 > 0: ts["COADFX"] = initm( - siminfo, uci, coadfg1, "CONS" + str(index) + "_MONTHLY/COADFX", 0.0 + siminfo, + parameters, + coadfg1, + "CONS" + str(index) + "_MONTHLY/COADFX", + 0.0, ) elif coadfg1 == -1: ts["COADFX"] = ts["COADFX" + str(index)] @@ -106,7 +110,11 @@ def cons(io_manager, siminfo, uci, ts): coadfg2 = u["COADFG" + str(index * 2)] if coadfg2 > 0: ts["COADCN"] = initm( - siminfo, uci, coadfg2, "CONS" + str(index) + "_MONTHLY/COADCN", 0.0 + siminfo, + parameters, + coadfg2, + "CONS" + str(index) + "_MONTHLY/COADCN", + 0.0, ) elif coadfg2 == -1: ts["COADCN"] = ts["COADCN" + str(index)] @@ -121,7 +129,7 @@ def cons(io_manager, siminfo, uci, ts): ############################################################################ if nexits > 1: - u = uci["SAVE"] + u = parameters["SAVE"] key1 = name + "_OCON" for i in range(nexits): u[f"{key1}{i + 1}"] = u["OCON"] @@ -226,12 +234,12 @@ def _cons_(ui, ts): return -def expand_CONS_masslinks(flags, uci, dat, recs): +def expand_CONS_masslinks(flags, parameters, dat, recs): if flags["CONS"]: ncons = 1 - if "PARAMETERS" in uci: - if "NCONS" in uci["PARAMETERS"]: - ncons = uci["PARAMETERS"]["NCONS"] + if "PARAMETERS" in parameters: + if "NCONS" in parameters["PARAMETERS"]: + ncons = parameters["PARAMETERS"]["NCONS"] for i in range(1, ncons + 1): # ICONS loop for each cons rec = {} diff --git a/src/hsp2/hsp2/GENER.py b/src/hsp2/hsp2/GENER.py index d20f0283..06bcd3ae 100644 --- a/src/hsp2/hsp2/GENER.py +++ b/src/hsp2/hsp2/GENER.py @@ -78,7 +78,7 @@ def __init__( self.ts_input_1 = tsin["ONE"] if "TWO" in tsin: self.ts_input_2 = tsin["TWO"] - if not "ONE" in tsin and not "TWO" in tsin: + if "ONE" not in tsin and "TWO" not in tsin: raise NotImplementedError(f"Invalid SVOL for '{link.SVOLNO}'") if link.SVOL == "COPY" or link.SVOL == "GENER": @@ -153,9 +153,17 @@ def _opcode7(self) -> pd.Series: def _opcode8(self) -> pd.Series: # K(1) + K(2) * A + K(3) * A ** 2 # The user supplies the number of terms and the values of coefficients (K) - return ((self.k1 + (self.k2 * self.ts_input_1) + (self.k3 * (self.ts_input_1 ** 2)) - + (self.k4 * (self.ts_input_1 ** 3))) + (self.k5 * (self.ts_input_1 ** 4)) - + (self.k6 * (self.ts_input_1 ** 7)) + (self.k7 * (self.ts_input_1 ** 8))) + return ( + ( + self.k1 + + (self.k2 * self.ts_input_1) + + (self.k3 * (self.ts_input_1**2)) + + (self.k4 * (self.ts_input_1**3)) + ) + + (self.k5 * (self.ts_input_1**4)) + + (self.k6 * (self.ts_input_1**7)) + + (self.k7 * (self.ts_input_1**8)) + ) def _opcode9(self) -> pd.Series: return np.power(self.k, self.ts_input_1) diff --git a/src/hsp2/hsp2/GQUAL.py b/src/hsp2/hsp2/GQUAL.py index 98faefa0..786dc335 100644 --- a/src/hsp2/hsp2/GQUAL.py +++ b/src/hsp2/hsp2/GQUAL.py @@ -27,7 +27,7 @@ ) # ERRMSG11 -def gqual(io_manager, siminfo, uci, ts): +def gqual(io_manager, siminfo, parameters, ts): """Simulate the behavior of a generalized quality constituent""" errors = zeros(len(ERRMSGS)).astype(int64) @@ -42,7 +42,7 @@ def gqual(io_manager, siminfo, uci, ts): # si units conversion AFACT = 1000000.0 - advectData = uci["advectData"] + advectData = parameters["advectData"] (nexits, vol, VOL, SROVOL, EROVOL, SOVOL, EOVOL) = advectData svol = vol * AFACT @@ -53,7 +53,7 @@ def gqual(io_manager, siminfo, uci, ts): ts["SOVOL" + str(i + 1)] = SOVOL[:, i] ts["EOVOL" + str(i + 1)] = EOVOL[:, i] - ui = make_numba_dict(uci) + ui = make_numba_dict(parameters) ui["simlen"] = siminfo["steps"] ui["uunits"] = siminfo["units"] ui["svol"] = svol @@ -71,7 +71,7 @@ def gqual(io_manager, siminfo, uci, ts): sdfg = 2 phytfg = 2 - # ui = uci['PARAMETERS'] + # ui = parameters['PARAMETERS'] if "NGQUAL" in ui: ngqual = int(ui["NGQUAL"]) tempfg = ui["TEMPFG"] @@ -90,21 +90,29 @@ def gqual(io_manager, siminfo, uci, ts): ui = ui_base ui["index"] = index # update UI values for this constituent here! - ui_parms = uci["GQUAL" + str(index)] + ui_parms = parameters["GQUAL" + str(index)] if "GQADFG" + str((index * 2) - 1) in ui_parms: # get atmos dep timeseries gqadfgf = ui_parms["GQADFG" + str((index * 2) - 1)] if gqadfgf > 0: ts["GQADFX"] = initm( - siminfo, uci, gqadfgf, "GQUAL" + str(index) + "_MONTHLY/GQADFX", 0.0 + siminfo, + parameters, + gqadfgf, + "GQUAL" + str(index) + "_MONTHLY/GQADFX", + 0.0, ) elif gqadfgf == -1: ts["GQADFX"] = ts["GQADFX" + str(index) + " 1"] gqadfgc = ui_parms["GQADFG" + str(index * 2)] if gqadfgc > 0: ts["GQADCN"] = initm( - siminfo, uci, gqadfgc, "GQUAL" + str(index) + "_MONTHLY/GQADCN", 0.0 + siminfo, + parameters, + gqadfgc, + "GQUAL" + str(index) + "_MONTHLY/GQADCN", + 0.0, ) elif gqadfgc == -1: ts["GQADCN"] = ts["GQADCN" + str(index) + " 1"] @@ -141,7 +149,7 @@ def gqual(io_manager, siminfo, uci, ts): # BIOM = # from ts, monthly, constant ts["BIO"] = initm( siminfo, - uci, + parameters, ui_parms["GQPM27"], "GQUAL" + str(index) + "_MONTHLY/BIO", ui_parms["BIO"], @@ -176,27 +184,47 @@ def gqual(io_manager, siminfo, uci, ts): # for the following, if the flag value is 1 the timeseries should already be available as input if tempfg == 2 or tempfg == 3: ts["TW_GQ"] = initm( - siminfo, uci, tempfg, "GQUAL" + str(index) + "_MONTHLY/WATEMP", twat + siminfo, + parameters, + tempfg, + "GQUAL" + str(index) + "_MONTHLY/WATEMP", + twat, ) if phflag == 2 or phflag == 3: ts["PHVAL_GQ"] = initm( - siminfo, uci, phflag, "GQUAL" + str(index) + "_MONTHLY/PHVAL", phval + siminfo, + parameters, + phflag, + "GQUAL" + str(index) + "_MONTHLY/PHVAL", + phval, ) if roxfg == 2 or roxfg == 3: ts["ROC_GQ"] = initm( - siminfo, uci, roxfg, "GQUAL" + str(index) + "_MONTHLY/ROXYGEN", roc + siminfo, + parameters, + roxfg, + "GQUAL" + str(index) + "_MONTHLY/ROXYGEN", + roc, ) if cldfg == 2 or cldfg == 3: ts["CLOUD_GQ"] = initm( - siminfo, uci, cldfg, "GQUAL" + str(index) + "_MONTHLY/CLOUD", cld + siminfo, parameters, cldfg, "GQUAL" + str(index) + "_MONTHLY/CLOUD", cld ) if sdfg == 2 or sdfg == 3: ts["SDCNC_GQ"] = initm( - siminfo, uci, sdfg, "GQUAL" + str(index) + "_MONTHLY/SEDCONC", sdcnc + siminfo, + parameters, + sdfg, + "GQUAL" + str(index) + "_MONTHLY/SEDCONC", + sdcnc, ) if phytfg == 2 or phytfg == 3: ts["PHYTO_GQ"] = initm( - siminfo, uci, phytfg, "GQUAL" + str(index) + "_MONTHLY/PHYTO", phy + siminfo, + parameters, + phytfg, + "GQUAL" + str(index) + "_MONTHLY/PHYTO", + phy, ) # if any of these flags are 1 and the timeseries does not exist, that's a problem -- trigger message @@ -205,28 +233,28 @@ def gqual(io_manager, siminfo, uci, ts): qalfg3 = ui_parms["QALFG3"] if qalfg3 == 1: # qual undergoes photolysis # PHOTPM(1,I) # table-type gq-photpm - if "EXTENDEDS_PHOTPM" in uci: - ttable = uci["EXTENDEDS_PHOTPM"] + if "EXTENDEDS_PHOTPM" in parameters: + ttable = parameters["EXTENDEDS_PHOTPM"] for i in range(1, 21): ui["photpm" + str(i)] = ttable["PHOTPM" + str(i - 1)] # table-type gq-alpha - if "EXTENDEDS_ALPH" in uci: - ttable = uci["EXTENDEDS_ALPH"] + if "EXTENDEDS_ALPH" in parameters: + ttable = parameters["EXTENDEDS_ALPH"] for i in range(1, 19): ui["alph" + str(i)] = ttable["ALPH" + str(i - 1)] # table-type gq-gamma - if "EXTENDEDS_GAMM" in uci: - ttable = uci["EXTENDEDS_GAMM"] + if "EXTENDEDS_GAMM" in parameters: + ttable = parameters["EXTENDEDS_GAMM"] for i in range(1, 19): ui["gamm" + str(i)] = ttable["GAMM" + str(i - 1)] # table-type gq-delta - if "EXTENDEDS_DEL" in uci: - ttable = uci["EXTENDEDS_DEL"] + if "EXTENDEDS_DEL" in parameters: + ttable = parameters["EXTENDEDS_DEL"] for i in range(1, 19): ui["delta" + str(i)] = ttable["DEL" + str(i - 1)] # table-type gq-cldfact - if "EXTENDEDS_KCLD" in uci: - ttable = uci["EXTENDEDS_KCLD"] + if "EXTENDEDS_KCLD" in parameters: + ttable = parameters["EXTENDEDS_KCLD"] for i in range(1, 19): ui["kcld" + str(i)] = ttable["KCLD" + str(i - 1)] @@ -241,7 +269,7 @@ def gqual(io_manager, siminfo, uci, ts): ############################################################################ if nexits > 1: - u = uci["SAVE"] + u = parameters["SAVE"] name = "GQUAL" + str(index) # arbitrary identification key1 = name + "_ODQAL" for i in range(nexits): @@ -789,9 +817,15 @@ def _gqual_(ui, ts): for timeindex in range(simlen): if nexits > 1: for xindex in range(nexits): - OSED1[timeindex, xindex] = ts["OSED" + str(xindex + 1) + "1"][timeindex] - OSED2[timeindex, xindex] = ts["OSED" + str(xindex + 1) + "2"][timeindex] - OSED3[timeindex, xindex] = ts["OSED" + str(xindex + 1) + "3"][timeindex] + OSED1[timeindex, xindex] = ts["OSED" + str(xindex + 1) + "1"][ + timeindex + ] + OSED2[timeindex, xindex] = ts["OSED" + str(xindex + 1) + "2"][ + timeindex + ] + OSED3[timeindex, xindex] = ts["OSED" + str(xindex + 1) + "3"][ + timeindex + ] else: OSED1[timeindex, 0] = ts["ROSED1"][timeindex] OSED2[timeindex, 0] = ts["ROSED2"][timeindex] @@ -930,11 +964,11 @@ def _gqual_(ui, ts): isqal2 = ISQAL2[loop] isqal3 = ISQAL3[loop] - if uunits == 2: # uci is in metric units + if uunits == 2: # parameters are in metric units avdepm = AVDEP[loop] avdepe = AVDEP[loop] * 3.28 avvele = AVVEL[loop] * 3.28 - else: # uci is in english units + else: # parameters is are english units avdepm = AVDEP[loop] * 0.3048 avdepe = AVDEP[loop] avvele = AVVEL[loop] @@ -2074,11 +2108,11 @@ def light_factor(l, lset, light): return vals[l - 1] -def expand_GQUAL_masslinks(flags, uci, dat, recs): +def expand_GQUAL_masslinks(flags, parameters, dat, recs): if flags["GQUAL"]: ngqual = 1 - if "PARAMETERS" in uci: - ui = uci["PARAMETERS"] + if "PARAMETERS" in parameters: + ui = parameters["PARAMETERS"] if "NGQUAL" in ui: ngqual = ui["NGQUAL"] for i in range(1, ngqual + 1): diff --git a/src/hsp2/hsp2/HTRCH.py b/src/hsp2/hsp2/HTRCH.py index e675dd03..12b417a8 100644 --- a/src/hsp2/hsp2/HTRCH.py +++ b/src/hsp2/hsp2/HTRCH.py @@ -61,10 +61,10 @@ ) # ERRMSG0 -def htrch(io_manager, siminfo, uci, ts): +def htrch(io_manager, siminfo, parameters, ts): """Simulate heat exchange and water temperature""" - advectData = uci["advectData"] + advectData = parameters["advectData"] (nexits, vol, VOL, SROVOL, EROVOL, SOVOL, EOVOL) = advectData ts["VOL"] = VOL @@ -78,7 +78,7 @@ def htrch(io_manager, siminfo, uci, ts): ts["DAYFG"] = hourflag(siminfo, 0, dofirst=True).astype(float64) - ui = make_numba_dict(uci) + ui = make_numba_dict(parameters) nexits = int(ui["NEXITS"]) ui["simlen"] = siminfo["steps"] ui["uunits"] = siminfo["units"] @@ -108,10 +108,10 @@ def htrch(io_manager, siminfo, uci, ts): deltt = zeros(int(tstop)) ts["DELTT"] = deltt - u = uci["PARAMETERS"] + u = parameters["PARAMETERS"] # process optional monthly arrays to return interpolated data or constant array if "TGFLG" in u: - ts["TGRND"] = initm(siminfo, uci, u["TGFLG"], "TGRND", tgrnd) + ts["TGRND"] = initm(siminfo, parameters, u["TGFLG"], "TGRND", tgrnd) else: ts["TGRND"] = full(simlen, tgrnd) @@ -122,7 +122,7 @@ def htrch(io_manager, siminfo, uci, ts): ############################################################################ if nexits > 1: - u = uci["SAVE"] + u = parameters["SAVE"] key = "OHEAT" for i in range(nexits): u[f"{key}{i + 1}"] = u[key] @@ -240,7 +240,7 @@ def _htrch_(ui, ts): TGRND = ts["TGRND"] - if not "IHEAT" in ts: + if "IHEAT" not in ts: ts["IHEAT"] = zeros(simlen) IHEAT = ts["IHEAT"] # kcal.vol/l.ivl; heat is relative to 0 degreees c if uunits == 1: @@ -551,7 +551,7 @@ def vapor(tmp): ) -def expand_HTRCH_masslinks(flags, uci, dat, recs): +def expand_HTRCH_masslinks(flags, parameters, dat, recs): if flags["HTRCH"]: # IHEAT rec = {} diff --git a/src/hsp2/hsp2/HYDR.py b/src/hsp2/hsp2/HYDR.py index 74ed251a..d65ad8cb 100644 --- a/src/hsp2/hsp2/HYDR.py +++ b/src/hsp2/hsp2/HYDR.py @@ -36,14 +36,14 @@ MAXLOOPS = 100 # newton method exit tolerance -def hydr(io_manager, siminfo, uci, ts, ftables, state): +def hydr(io_manager, siminfo, parameters, ts, ftables, state): """find the state of the reach/reservoir at the end of the time interval and the outflows during the interval CALL: hydr(store, general, ui, ts, state) store is the Pandas/PyTable open store general is a dictionary with simulation level infor (OP_SEQUENCE for example) - ui is a dictionary with RID specific HSPF UCI like data + ui is a dictionary with RID specific HSPF parameter data ts is a dictionary with RID specific timeseries state is a dictionary that contains all dynamic code dictionaries such as: - specactions is a dictionary with all special actions @@ -51,7 +51,7 @@ def hydr(io_manager, siminfo, uci, ts, ftables, state): steps = siminfo["steps"] # number of simulation points uunits = siminfo["units"] - nexits = int(uci["PARAMETERS"]["NEXITS"]) + nexits = int(parameters["PARAMETERS"]["NEXITS"]) # units conversion constants, 1 ACRE is 43560 sq ft. assumes input in acre-ft VFACT = 43560.0 @@ -61,7 +61,7 @@ def hydr(io_manager, siminfo, uci, ts, ftables, state): VFACT = 1.0e6 AFACT = 10000.0 - u = uci["PARAMETERS"] + u = parameters["PARAMETERS"] funct = array([u[name] for name in u.keys() if name.startswith("FUNCT")]).astype( int )[0:nexits] @@ -72,7 +72,7 @@ def hydr(io_manager, siminfo, uci, ts, ftables, state): int )[0:nexits] - u = uci["STATES"] + u = parameters["STATES"] colin = array([u[name] for name in u.keys() if name.startswith("COLIN")]).astype( float )[0:nexits] @@ -96,10 +96,10 @@ def hydr(io_manager, siminfo, uci, ts, ftables, state): # generic SAVE table doesn't know nexits for output flows and rates if nexits > 1: - u = uci["SAVE"] + u = parameters["SAVE"] for key in ("O", "OVOL"): for i in range(nexits): - u[f"{key}{i+1}"] = u[key] + u[f"{key}{i + 1}"] = u[key] del u[key] # optional - defined, but can't used accidently @@ -111,17 +111,17 @@ def hydr(io_manager, siminfo, uci, ts, ftables, state): for name in ("IVOL", "POTEV", "PREC"): if name not in ts: ts[name] = zeros(steps) - ts["CONVF"] = initm(siminfo, uci, "VCONFG", "MONTHLY_CONVF", 1.0) + ts["CONVF"] = initm(siminfo, parameters, "VCONFG", "MONTHLY_CONVF", 1.0) # extract key columns of specified FTable for faster access (1d vs. 2d) - rchtab = ftables[f"{uci['PARAMETERS']['FTBUCI']}"] - # rchtab = store[f"FTABLES/{uci['PARAMETERS']['FTBUCI']}"] + rchtab = ftables[f"{parameters['PARAMETERS']['FTBUCI']}"] + # rchtab = store[f"FTABLES/{parameters['PARAMETERS']['FTBUCI']}"] ts["volumeFT"] = rchtab["Volume"].to_numpy() * VFACT ts["depthFT"] = rchtab["Depth"].to_numpy() ts["sareaFT"] = rchtab["Area"].to_numpy() * AFACT rchtab = rchtab.to_numpy() - ui = make_numba_dict(uci) # Note: all values coverted to float automatically + ui = make_numba_dict(parameters) # Note: all values coverted to float automatically ui["steps"] = steps ui["delt"] = siminfo["delt"] ui["nexits"] = nexits @@ -134,8 +134,8 @@ def hydr(io_manager, siminfo, uci, ts, ftables, state): Olabels = List() OVOLlabels = List() for i in range(nexits): - Olabels.append(f"O{i+1}") - OVOLlabels.append(f"OVOL{i+1}") + Olabels.append(f"O{i + 1}") + OVOLlabels.append(f"OVOL{i + 1}") ####################################################################################### # the following section (1 of 3) added to HYDR by rb to handle dynamic code and special actions @@ -203,9 +203,9 @@ def hydr(io_manager, siminfo, uci, ts, ftables, state): del ts["OVOL"] # save initial outflow(s) from reach: - uci["PARAMETERS"]["ROS"] = ui["ROS"] + parameters["PARAMETERS"]["ROS"] = ui["ROS"] for i in range(nexits): - uci["PARAMETERS"]["OS" + str(i + 1)] = ui["OS" + str(i + 1)] + parameters["PARAMETERS"]["OS" + str(i + 1)] = ui["OS" + str(i + 1)] # copy back (modified) operational element data state["state_ix"], state["dict_ix"], state["ts_ix"] = state_ix, dict_ix, ts_ix return errors, ERRMSGS @@ -848,7 +848,7 @@ def auxil(volumeFT, depthFT, sareaFT, indx, vol, length, stcor, AUX1FG, errors): return dep, stage, sarea, avdep, twid, hrad -def expand_HYDR_masslinks(flags, uci, dat, recs): +def expand_HYDR_masslinks(flags, parameters, dat, recs): if flags["HYDR"]: # IVOL rec = {} diff --git a/src/hsp2/hsp2/IQUAL.py b/src/hsp2/hsp2/IQUAL.py index d98b718a..8629dda9 100644 --- a/src/hsp2/hsp2/IQUAL.py +++ b/src/hsp2/hsp2/IQUAL.py @@ -16,7 +16,7 @@ from math import exp from numba import njit -from numpy import float64, full, int64, where, zeros +from numpy import float64, full, int64, zeros from hsp2.hsp2.utilities import hourflag, initm, initmdiv, make_numba_dict @@ -26,37 +26,37 @@ ) # ERRMSG0 -def iqual(io_manager, siminfo, uci, ts): +def iqual(io_manager, siminfo, parameters, ts): """Simulate washoff of quality constituents (other than solids, Heat, dox, and co2) using simple relationships with solids And/or water yield""" simlen = siminfo["steps"] nquals = 1 - if "PARAMETERS" in uci: - if "NQUAL" in uci["PARAMETERS"]: - nquals = int(uci["PARAMETERS"]["NQUAL"]) + if "PARAMETERS" in parameters: + if "NQUAL" in parameters["PARAMETERS"]: + nquals = int(parameters["PARAMETERS"]["NQUAL"]) constituents = [] for index in range(nquals): iqual = str(index + 1) - flags = uci["IQUAL" + iqual + "_FLAGS"] + flags = parameters["IQUAL" + iqual + "_FLAGS"] constituents.append(flags["QUALID"]) - ui = make_numba_dict(uci) + ui = make_numba_dict(parameters) ui["simlen"] = siminfo["steps"] ui["delt60"] = siminfo["delt"] / 60 # delt60 - simulation time interval in hours ui["nquals"] = nquals ui["errlen"] = len(ERRMSGS) # constituents = ui['CONSTITUENTS'] # (short) names of constituents - if "FLAGS" in uci: - u = uci["FLAGS"] + if "FLAGS" in parameters: + u = parameters["FLAGS"] index = 0 for constituent in constituents: # simulate constituent index += 1 # update UI values for this constituent here! - ui_flags = uci["IQUAL" + str(index) + "_FLAGS"] - ui_parms = uci["IQUAL" + str(index) + "_PARAMETERS"] + ui_flags = parameters["IQUAL" + str(index) + "_FLAGS"] + ui_parms = parameters["IQUAL" + str(index) + "_PARAMETERS"] qualid = ui_flags["QUALID"] qtyid = ui_flags["QTYID"] QSDFG = ui_flags["QSDFG"] @@ -73,21 +73,21 @@ def iqual(io_manager, siminfo, uci, ts): # handle monthly tables ts["POTFW" + str(index)] = initm( siminfo, - uci, + parameters, ui_flags["VPFWFG"], "IQUAL" + str(index) + "_MONTHLY/POTFW", ui_parms["POTFW"], ) ts["ACQOP" + str(index)] = initm( siminfo, - uci, + parameters, ui_flags["VQOFG"], "IQUAL" + str(index) + "_MONTHLY/ACQOP", ui_parms["ACQOP"], ) ts["SQOLIM" + str(index)] = initm( siminfo, - uci, + parameters, ui_flags["VQOFG"], "IQUAL" + str(index) + "_MONTHLY/SQOLIM", ui_parms["SQOLIM"], @@ -95,7 +95,7 @@ def iqual(io_manager, siminfo, uci, ts): ts["REMQOP" + str(index)] = initmdiv( siminfo, - uci, + parameters, ui_flags["VQOFG"], "IQUAL" + str(index) + "_MONTHLY/ACQOP", "IQUAL" + str(index) + "_MONTHLY/SQOLIM", @@ -107,19 +107,27 @@ def iqual(io_manager, siminfo, uci, ts): iqadfgc = 0 ts["IQADFX" + str(index)] = zeros(simlen) ts["IQADCN" + str(index)] = zeros(simlen) - if "FLAGS" in uci: + if "FLAGS" in parameters: # get atmos dep timeseries iqadfgf = u["IQADFG" + str((index * 2) - 1)] if iqadfgf > 0: ts["IQADFX" + str(index)] = initm( - siminfo, uci, iqadfgf, "IQUAL" + str(index) + "_MONTHLY/IQADFX", 0.0 + siminfo, + parameters, + iqadfgf, + "IQUAL" + str(index) + "_MONTHLY/IQADFX", + 0.0, ) elif iqadfgf == -1: ts["IQADFX" + str(index)] = ts["IQADFX" + str(index) + " 1"] iqadfgc = u["IQADFG" + str(index * 2)] if iqadfgc > 0: ts["IQADCN" + str(index)] = initm( - siminfo, uci, iqadfgc, "IQUAL" + str(index) + "_MONTHLY/IQADCN", 0.0 + siminfo, + parameters, + iqadfgc, + "IQUAL" + str(index) + "_MONTHLY/IQADCN", + 0.0, ) elif iqadfgc == -1: ts["IQADCN" + str(index)] = ts["IQADCN" + str(index) + " 1"] diff --git a/src/hsp2/hsp2/IWATER.py b/src/hsp2/hsp2/IWATER.py index e6c3f69d..97c5479a 100644 --- a/src/hsp2/hsp2/IWATER.py +++ b/src/hsp2/hsp2/IWATER.py @@ -18,7 +18,7 @@ ) -def iwater(io_manager, siminfo, uci, ts): +def iwater(io_manager, siminfo, parameters, ts): """Driver for IMPLND IWATER code. CALL: iwater(store, general, ui, ts) store is the Pandas/PyTable open store general is a dictionary with simulation info (OP_SEQUENCE for example) @@ -44,13 +44,15 @@ def iwater(io_manager, siminfo, uci, ts): # Replace fixed parameters in HSPF with timeseries for name in ["PETMAX", "PETMIN"]: if name not in ts: - ts[name] = full(steps, uci["PARAMETERS"][name], dtype=float64) + ts[name] = full(steps, parameters["PARAMETERS"][name], dtype=float64) # process optional monthly arrays to return interpolated data or constant array - u = uci["PARAMETERS"] + u = parameters["PARAMETERS"] if "VRSFG" in u: - ts["RETSC"] = initm(siminfo, uci, u["VRSFG"], "MONTHLY_RETSC", u["RETSC"]) - ts["NSUR"] = initm(siminfo, uci, u["VNNFG"], "MONTHLY_NSUR", u["NSUR"]) + ts["RETSC"] = initm( + siminfo, parameters, u["VRSFG"], "MONTHLY_RETSC", u["RETSC"] + ) + ts["NSUR"] = initm(siminfo, parameters, u["VNNFG"], "MONTHLY_NSUR", u["NSUR"]) else: ts["RETSC"] = full(steps, u["RETSC"]) ts["NSUR"] = full(steps, u["NSUR"]) @@ -65,7 +67,7 @@ def iwater(io_manager, siminfo, uci, ts): float64 ) # numba Dict limitation - ui = make_numba_dict(uci) # Note: all values coverted to float automatically + ui = make_numba_dict(parameters) # Note: all values coverted to float automatically ui["steps"] = steps ui["delt"] = siminfo["delt"] ui["errlen"] = len(ERRMSGS) diff --git a/src/hsp2/hsp2/IWTGAS.py b/src/hsp2/hsp2/IWTGAS.py index 7316327b..4f00acb5 100644 --- a/src/hsp2/hsp2/IWTGAS.py +++ b/src/hsp2/hsp2/IWTGAS.py @@ -5,7 +5,7 @@ Conversion of HSPF HIMPGAS.FOR module into Python""" from numba import njit -from numpy import float64, full, int64, where, zeros +from numpy import float64, full, int64, zeros from hsp2.hsp2.utilities import hourflag, initm, make_numba_dict @@ -23,7 +23,7 @@ MFACTA = 0.2266 -def iwtgas(io_manager, siminfo, uci, ts): +def iwtgas(io_manager, siminfo, parameters, ts): """Estimate water temperature, dissolved oxygen, and carbon dioxide in the outflows from a impervious land segment. calculate associated fluxes through exit gate @@ -37,15 +37,15 @@ def iwtgas(io_manager, siminfo, uci, ts): simlen = siminfo["steps"] - ui = make_numba_dict(uci) + ui = make_numba_dict(parameters) ui["simlen"] = siminfo["steps"] ui["uunits"] = siminfo["units"] ui["errlen"] = len(ERRMSG) - u = uci["PARAMETERS"] + u = parameters["PARAMETERS"] if "WTFVFG" in u: - ts["AWTF"] = initm(siminfo, uci, u["WTFVFG"], "MONTHLY_AWTF", u["AWTF"]) - ts["BWTF"] = initm(siminfo, uci, u["WTFVFG"], "MONTHLY_BWTF", u["BWTF"]) + ts["AWTF"] = initm(siminfo, parameters, u["WTFVFG"], "MONTHLY_AWTF", u["AWTF"]) + ts["BWTF"] = initm(siminfo, parameters, u["WTFVFG"], "MONTHLY_BWTF", u["BWTF"]) else: ts["AWTF"] = full(simlen, u["AWTF"]) ts["BWTF"] = full(simlen, u["BWTF"]) diff --git a/src/hsp2/hsp2/NUTRX_Class.py b/src/hsp2/hsp2/NUTRX_Class.py index af7e04b2..dd7450f1 100644 --- a/src/hsp2/hsp2/NUTRX_Class.py +++ b/src/hsp2/hsp2/NUTRX_Class.py @@ -6,9 +6,7 @@ from numpy import array, zeros from hsp2.hsp2.ADCALC import advect -from hsp2.hsp2.OXRX_Class import OXRX_Class -from hsp2.hsp2.RQUTIL import benth, decbal, sink -from hsp2.hsp2.utilities import initm, make_numba_dict +from hsp2.hsp2.RQUTIL import benth, decbal spec = [ ("adnh4", nb.float64[:]), diff --git a/src/hsp2/hsp2/OXRX_Class.py b/src/hsp2/hsp2/OXRX_Class.py index 3106eb38..3e6c7c85 100644 --- a/src/hsp2/hsp2/OXRX_Class.py +++ b/src/hsp2/hsp2/OXRX_Class.py @@ -3,12 +3,10 @@ import numba as nb import numpy as np from numba.experimental import jitclass -from numba.typed import Dict -from numpy import array, zeros +from numpy import zeros from hsp2.hsp2.ADCALC import advect, oxrea from hsp2.hsp2.RQUTIL import sink -from hsp2.hsp2.utilities import make_numba_dict spec = [ ("AFACT", nb.float64), diff --git a/src/hsp2/hsp2/PHCARB_Class.py b/src/hsp2/hsp2/PHCARB_Class.py index 00262867..d7968ae2 100644 --- a/src/hsp2/hsp2/PHCARB_Class.py +++ b/src/hsp2/hsp2/PHCARB_Class.py @@ -3,8 +3,7 @@ import numba as nb import numpy as np from numba.experimental import jitclass -from numba.typed import Dict -from numpy import array, zeros +from numpy import zeros from hsp2.hsp2.ADCALC import advect from hsp2.hsp2.RQUTIL import benth diff --git a/src/hsp2/hsp2/PLANK_Class.py b/src/hsp2/hsp2/PLANK_Class.py index 42cd639e..d662c47f 100644 --- a/src/hsp2/hsp2/PLANK_Class.py +++ b/src/hsp2/hsp2/PLANK_Class.py @@ -4,13 +4,12 @@ import numba as nb import numpy as np from numba.experimental import jitclass -from numpy import array, zeros +from numpy import zeros from hsp2.hsp2.ADCALC import advect from hsp2.hsp2.NUTRX_Class import NUTRX_Class from hsp2.hsp2.OXRX_Class import OXRX_Class from hsp2.hsp2.RQUTIL import decbal, sink -from hsp2.hsp2.utilities import initm, make_numba_dict if os.environ.get("NUMBA_DISABLE_JIT", 0): # jit should be on by default. OXRX_Class_ = OXRX_Class diff --git a/src/hsp2/hsp2/PQUAL.py b/src/hsp2/hsp2/PQUAL.py index fd3afc0d..353fbe9a 100644 --- a/src/hsp2/hsp2/PQUAL.py +++ b/src/hsp2/hsp2/PQUAL.py @@ -14,7 +14,7 @@ from math import exp from numba import njit -from numpy import float64, full, int64, where, zeros +from numpy import float64, int64, zeros from hsp2.hsp2.utilities import hourflag, initm, initmdiv, make_numba_dict @@ -29,37 +29,37 @@ PFACTA = 1.0 -def pqual(io_manager, siminfo, uci, ts): +def pqual(io_manager, siminfo, parameters, ts): """Simulate quality constituents (other than sediment, heat, dox, and co2) using simple relationships with sediment and water yield""" simlen = siminfo["steps"] nquals = 1 - if "PARAMETERS" in uci: - if "NQUAL" in uci["PARAMETERS"]: - nquals = int(uci["PARAMETERS"]["NQUAL"]) + if "PARAMETERS" in parameters: + if "NQUAL" in parameters["PARAMETERS"]: + nquals = int(parameters["PARAMETERS"]["NQUAL"]) constituents = [] for index in range(nquals): pqual = str(index + 1) - flags = uci["PQUAL" + pqual + "_FLAGS"] + flags = parameters["PQUAL" + pqual + "_FLAGS"] constituents.append(flags["QUALID"]) - ui = make_numba_dict(uci) + ui = make_numba_dict(parameters) ui["simlen"] = siminfo["steps"] ui["delt60"] = siminfo["delt"] / 60 # delt60 - simulation time interval in hours ui["nquals"] = nquals ui["errlen"] = len(ERRMSGS) # constituents = ui['CONSTITUENTS'] # (short) names of constituents - if "FLAGS" in uci: - u = uci["FLAGS"] + if "FLAGS" in parameters: + u = parameters["FLAGS"] index = 0 for constituent in constituents: # simulate constituent index += 1 # update UI values for this constituent here! - ui_flags = uci["PQUAL" + str(index) + "_FLAGS"] - ui_parms = uci["PQUAL" + str(index) + "_PARAMETERS"] + ui_flags = parameters["PQUAL" + str(index) + "_FLAGS"] + ui_parms = parameters["PQUAL" + str(index) + "_PARAMETERS"] qualid = ui_flags["QUALID"] qtyid = ui_flags["QTYID"] @@ -81,42 +81,42 @@ def pqual(io_manager, siminfo, uci, ts): ts["POTFW" + str(index)] = initm( siminfo, - uci, + parameters, ui_flags["VPFWFG"], "PQUAL" + str(index) + "_MONTHLY/POTFW", ui_parms["POTFW"], ) ts["POTFS" + str(index)] = initm( siminfo, - uci, + parameters, ui_flags["VPFSFG"], "PQUAL" + str(index) + "_MONTHLY/POTFS", ui_parms["POTFS"], ) ts["ACQOP" + str(index)] = initm( siminfo, - uci, + parameters, ui_flags["VQOFG"], "PQUAL" + str(index) + "_MONTHLY/ACQOP", ui_parms["ACQOP"], ) ts["SQOLIM" + str(index)] = initm( siminfo, - uci, + parameters, ui_flags["VQOFG"], "PQUAL" + str(index) + "_MONTHLY/SQOLIM", ui_parms["SQOLIM"], ) ts["IOQCP" + str(index)] = initm( siminfo, - uci, + parameters, ui_flags["VIQCFG"], "PQUAL" + str(index) + "_MONTHLY/IOQC", ui_parms["IOQC"], ) ts["AOQCP" + str(index)] = initm( siminfo, - uci, + parameters, ui_flags["VAQCFG"], "PQUAL" + str(index) + "_MONTHLY/AOQC", ui_parms["AOQC"], @@ -124,7 +124,7 @@ def pqual(io_manager, siminfo, uci, ts): ts["REMQOP" + str(index)] = initmdiv( siminfo, - uci, + parameters, ui_flags["VQOFG"], "PQUAL" + str(index) + "_MONTHLY/ACQOP", "PQUAL" + str(index) + "_MONTHLY/SQOLIM", @@ -136,19 +136,27 @@ def pqual(io_manager, siminfo, uci, ts): pqadfgc = 0 ts["PQADFX" + str(index)] = zeros(simlen) ts["PQADCN" + str(index)] = zeros(simlen) - if "FLAGS" in uci: + if "FLAGS" in parameters: # get atmos dep timeseries pqadfgf = u["PQADFG" + str((index * 2) - 1)] if pqadfgf > 0: ts["PQADFX" + str(index)] = initm( - siminfo, uci, pqadfgf, "PQUAL" + str(index) + "_MONTHLY/PQADFX", 0.0 + siminfo, + parameters, + pqadfgf, + "PQUAL" + str(index) + "_MONTHLY/PQADFX", + 0.0, ) elif pqadfgf == -1: ts["PQADFX" + str(index)] = ts["PQADFX" + str(index) + " 1"] pqadfgc = u["PQADFG" + str(index * 2)] if pqadfgc > 0: ts["PQADCN" + str(index)] = initm( - siminfo, uci, pqadfgc, "PQUAL" + str(index) + "_MONTHLY/PQADCN", 0.0 + siminfo, + parameters, + pqadfgc, + "PQUAL" + str(index) + "_MONTHLY/PQADCN", + 0.0, ) elif pqadfgc == -1: ts["PQADCN" + str(index)] = ts["PQADCN" + str(index) + " 1"] @@ -201,8 +209,8 @@ def _pqual_(ui, ts): for i in range(nquals): # simulate constituent index = i + 1 # update UI values for this constituent here! - # ui_flags = uci['PQUAL' + str(index) + '_FLAGS'] - # ui_parms = uci['PQUAL' + str(index) + '_PARAMETERS'] + # ui_flags = parameters['PQUAL' + str(index) + '_FLAGS'] + # ui_parms = parameters['PQUAL' + str(index) + '_PARAMETERS'] name = "PQUAL" + str(index) # arbitrary identification QSDFG = ui["QSDFG" + str(index)] diff --git a/src/hsp2/hsp2/PSTEMP.py b/src/hsp2/hsp2/PSTEMP.py index bf003935..2e69659c 100644 --- a/src/hsp2/hsp2/PSTEMP.py +++ b/src/hsp2/hsp2/PSTEMP.py @@ -5,7 +5,7 @@ Conversion of HSPF HPERTMP.FOR module into Python""" from numba import njit -from numpy import float64, full, int64, ones, where, zeros +from numpy import float64, full, int64, ones, zeros from hsp2.hsp2.utilities import hoursval, initm, make_numba_dict @@ -22,32 +22,40 @@ MAXTMP = 100 -def pstemp(io_manager, siminfo, uci, ts): +def pstemp(io_manager, siminfo, parameters, ts): """Estimate soil temperatures in a pervious land segment""" simlen = siminfo["steps"] - ui = make_numba_dict(uci) + ui = make_numba_dict(parameters) ui["simlen"] = siminfo["steps"] ui["uunits"] = siminfo["units"] ui["delt"] = siminfo["delt"] ui["errlen"] = len(ERRMSG) - u = uci["PARAMETERS"] + u = parameters["PARAMETERS"] if "SLTVFG" in u: - ts["ASLT"] = initm(siminfo, uci, u["SLTVFG"], "MONTHLY_ASLT", u["ASLT"]) - ts["BSLT"] = initm(siminfo, uci, u["SLTVFG"], "MONTHLY_BSLT", u["BSLT"]) + ts["ASLT"] = initm(siminfo, parameters, u["SLTVFG"], "MONTHLY_ASLT", u["ASLT"]) + ts["BSLT"] = initm(siminfo, parameters, u["SLTVFG"], "MONTHLY_BSLT", u["BSLT"]) else: ts["ASLT"] = full(simlen, u["ASLT"]) ts["BSLT"] = full(simlen, u["BSLT"]) if "ULTVFG" in u: - ts["ULTP1"] = initm(siminfo, uci, u["ULTVFG"], "MONTHLY_ULTP1", u["ULTP1"]) - ts["ULTP2"] = initm(siminfo, uci, u["ULTVFG"], "MONTHLY_ULTP2", u["ULTP2"]) + ts["ULTP1"] = initm( + siminfo, parameters, u["ULTVFG"], "MONTHLY_ULTP1", u["ULTP1"] + ) + ts["ULTP2"] = initm( + siminfo, parameters, u["ULTVFG"], "MONTHLY_ULTP2", u["ULTP2"] + ) else: ts["ULTP1"] = full(simlen, u["ULTP1"]) ts["ULTP2"] = full(simlen, u["ULTP2"]) if "LGTVFG" in u: - ts["LGTP1"] = initm(siminfo, uci, u["LGTVFG"], "MONTHLY_LGTP1", u["LGTP1"]) - ts["LGTP2"] = initm(siminfo, uci, u["LGTVFG"], "MONTHLY_LGTP2", u["LGTP2"]) + ts["LGTP1"] = initm( + siminfo, parameters, u["LGTVFG"], "MONTHLY_LGTP1", u["LGTP1"] + ) + ts["LGTP2"] = initm( + siminfo, parameters, u["LGTVFG"], "MONTHLY_LGTP2", u["LGTP2"] + ) else: ts["LGTP1"] = full(simlen, u["LGTP1"]) ts["LGTP2"] = full(simlen, u["LGTP2"]) diff --git a/src/hsp2/hsp2/PWATER.py b/src/hsp2/hsp2/PWATER.py index 843010db..53570058 100644 --- a/src/hsp2/hsp2/PWATER.py +++ b/src/hsp2/hsp2/PWATER.py @@ -28,7 +28,7 @@ ) -def pwater(io_manager, siminfo, uci, ts): +def pwater(io_manager, siminfo, parameters, ts): """PERLND WATER module CALL: pwater(store, general, ui, ts) store is the Pandas/PyTable open store @@ -53,20 +53,24 @@ def pwater(io_manager, siminfo, uci, ts): # Replace fixed parameters with time series if not already present for name in ("AGWRC", "DEEPFR", "INFILT", "KVARY", "LZSN", "PETMIN", "PETMAX"): - if name not in ts and name in uci["PARAMETERS"]: - ts[name] = full(steps, uci["PARAMETERS"][name]) + if name not in ts and name in parameters["PARAMETERS"]: + ts[name] = full(steps, parameters["PARAMETERS"][name]) # process optional monthly arrays to return interpolated data or constant array - u = uci["PARAMETERS"] + u = parameters["PARAMETERS"] if "VLEFG" in u: flag = (u["VLEFG"] == 1) or (u["VLEFG"] == 3) - ts["LZETP"] = initm(siminfo, uci, flag, "MONTHLY_LZETP", u["LZETP"]) - ts["CEPSC"] = initm(siminfo, uci, u["VCSFG"], "MONTHLY_CEPSC", u["CEPSC"]) - ts["INTFW"] = initm(siminfo, uci, u["VIFWFG"], "MONTHLY_INTFW", u["INTFW"]) - ts["IRC"] = initm(siminfo, uci, u["VIRCFG"], "MONTHLY_IRC", u["IRC"]) - ts["NSUR"] = initm(siminfo, uci, u["VNNFG"], "MONTHLY_NSUR", u["NSUR"]) - ts["UZSN"] = initm(siminfo, uci, u["VUZFG"], "MONTHLY_UZSN", u["UZSN"]) + ts["LZETP"] = initm(siminfo, parameters, flag, "MONTHLY_LZETP", u["LZETP"]) + ts["CEPSC"] = initm( + siminfo, parameters, u["VCSFG"], "MONTHLY_CEPSC", u["CEPSC"] + ) + ts["INTFW"] = initm( + siminfo, parameters, u["VIFWFG"], "MONTHLY_INTFW", u["INTFW"] + ) + ts["IRC"] = initm(siminfo, parameters, u["VIRCFG"], "MONTHLY_IRC", u["IRC"]) + ts["NSUR"] = initm(siminfo, parameters, u["VNNFG"], "MONTHLY_NSUR", u["NSUR"]) + ts["UZSN"] = initm(siminfo, parameters, u["VUZFG"], "MONTHLY_UZSN", u["UZSN"]) else: ts["LZETP"] = full(steps, u["LZETP"]) ts["CEPSC"] = full(steps, u["CEPSC"]) @@ -81,7 +85,7 @@ def pwater(io_manager, siminfo, uci, ts): # true the first time and at every hour of simulation ts["HRFG"] = hoursval(siminfo, ones(24), dofirst=True).astype(float) - ui = make_numba_dict(uci) # Note: all values coverted to float automatically + ui = make_numba_dict(parameters) # Note: all values coverted to float automatically ui["steps"] = siminfo["steps"] ui["delt"] = siminfo["delt"] ui["errlen"] = len(ERRMSGS) diff --git a/src/hsp2/hsp2/PWTGAS.py b/src/hsp2/hsp2/PWTGAS.py index 7cf4fa26..073f8fc1 100644 --- a/src/hsp2/hsp2/PWTGAS.py +++ b/src/hsp2/hsp2/PWTGAS.py @@ -5,7 +5,7 @@ Conversion of HSPF HPERGAS.FOR module into Python""" from numba import njit -from numpy import float64, full, int64, where, zeros +from numpy import float64, full, int64, zeros from hsp2.hsp2.utilities import hourflag, initm, make_numba_dict @@ -25,31 +25,39 @@ MFACTB = 0.0 -def pwtgas(io_manager, siminfo, uci, ts): +def pwtgas(io_manager, siminfo, parameters, ts): """Estimate water temperature, dissolved oxygen, and carbon dioxide in the outflows from a pervious landsegment. calculate associated fluxes through exit gates""" simlen = siminfo["steps"] - ui = make_numba_dict(uci) + ui = make_numba_dict(parameters) ui["simlen"] = siminfo["steps"] ui["uunits"] = siminfo["units"] ui["errlen"] = len(ERRMSG) - u = uci["PARAMETERS"] + u = parameters["PARAMETERS"] if "IDVFG" in u: - ts["IDOXP"] = initm(siminfo, uci, u["IDVFG"], "MONTHLY_IDOXP", u["IDOXP"]) + ts["IDOXP"] = initm( + siminfo, parameters, u["IDVFG"], "MONTHLY_IDOXP", u["IDOXP"] + ) else: ts["IDOXP"] = full(simlen, u["IDOXP"]) if "ICVFG" in u: - ts["ICO2P"] = initm(siminfo, uci, u["ICVFG"], "MONTHLY_ICO2P", u["ICO2P"]) + ts["ICO2P"] = initm( + siminfo, parameters, u["ICVFG"], "MONTHLY_ICO2P", u["ICO2P"] + ) else: ts["ICO2P"] = full(simlen, u["ICO2P"]) if "GDVFG" in u: - ts["ADOXP"] = initm(siminfo, uci, u["GDVFG"], "MONTHLY_ADOXP", u["ADOXP"]) + ts["ADOXP"] = initm( + siminfo, parameters, u["GDVFG"], "MONTHLY_ADOXP", u["ADOXP"] + ) else: ts["ADOXP"] = full(simlen, u["ADOXP"]) if "GCVFG" in u: - ts["ACO2P"] = initm(siminfo, uci, u["GCVFG"], "MONTHLY_ACO2P", u["ACO2P"]) + ts["ACO2P"] = initm( + siminfo, parameters, u["GCVFG"], "MONTHLY_ACO2P", u["ACO2P"] + ) else: ts["ACO2P"] = full(simlen, u["ACO2P"]) diff --git a/src/hsp2/hsp2/RQUAL.py b/src/hsp2/hsp2/RQUAL.py index 3fc0183b..78e766c5 100644 --- a/src/hsp2/hsp2/RQUAL.py +++ b/src/hsp2/hsp2/RQUAL.py @@ -3,20 +3,17 @@ License: LGPL2 """ -import logging - import numpy as np from numba import njit, types from numba.typed import Dict -from numpy import array, float64, full, where, zeros, asarray +from numpy import full, zeros, asarray from hsp2.hsp2.RQUAL_Class import RQUAL_Class from hsp2.hsp2.utilities import initm, initmd, make_numba_dict # the following imports added to handle special actions -from hsp2.hsp2.state import rqual_get_ix, rqual_init_ix, rqual_state_vars -from hsp2.hsp2.om import pre_step_model, step_model, model_domain_dependencies -from numba.typed import Dict +from hsp2.hsp2.state import rqual_init_ix, rqual_state_vars +from hsp2.hsp2.om import model_domain_dependencies ERRMSGS_oxrx = ( "OXRX: Warning -- SATDO is less than zero. This usually occurs when water temperature is very high (above ~66 deg. C). This usually indicates an error in input GATMP (or TW, if HTRCH is not being simulated).", @@ -40,8 +37,16 @@ def rqual( - io_manager, siminfo, uci, uci_oxrx, uci_nutrx, uci_plank, uci_phcarb, ts, - monthdata, state + io_manager, + siminfo, + parameters, + parameters_oxrx, + parameters_nutrx, + parameters_plank, + parameters_phcarb, + ts, + monthdata, + state, ): """Simulate constituents involved in biochemical transformations""" @@ -59,33 +64,33 @@ def rqual( siminfo_[key] = float(value) # module flags: - ui = make_numba_dict(uci) + ui = make_numba_dict(parameters) NUTFG = int(ui["NUTFG"]) PLKFG = int(ui["PLKFG"]) PHFG = int(ui["PHFG"]) # create numba dictionaries (empty if not simulated): - ui_oxrx = make_numba_dict(uci_oxrx) + ui_oxrx = make_numba_dict(parameters_oxrx) ui_oxrx["errlen"] = len(ERRMSGS_oxrx) ui_nutrx = Dict.empty(key_type=types.unicode_type, value_type=types.float64) if NUTFG == 1: - ui_nutrx = make_numba_dict(uci_nutrx) + ui_nutrx = make_numba_dict(parameters_nutrx) ui_nutrx["errlen"] = len(ERRMSGS_nutrx) ui_plank = Dict.empty(key_type=types.unicode_type, value_type=types.float64) if PLKFG == 1: - ui_plank = make_numba_dict(uci_plank) + ui_plank = make_numba_dict(parameters_plank) ui_plank["errlen"] = len(ERRMSGS_plank) ui_phcarb = Dict.empty(key_type=types.unicode_type, value_type=types.float64) if PHFG == 1: - ui_phcarb = make_numba_dict(uci_phcarb) + ui_phcarb = make_numba_dict(parameters_phcarb) ui_phcarb["errlen"] = len(ERRMSGS_phcarb) # hydraulic results: - advectData = uci["advectData"] + advectData = parameters["advectData"] (nexits, vol, VOL, SROVOL, EROVOL, SOVOL, EOVOL) = advectData ui["nexits"] = nexits @@ -280,7 +285,13 @@ def rqual( # --------------------------------------------------------------------- (err_oxrx, err_nutrx, err_plank, err_phcarb) = _rqual_run( - siminfo_, ui, ui_oxrx, ui_nutrx, ui_plank, ui_phcarb, ts, + siminfo_, + ui, + ui_oxrx, + ui_nutrx, + ui_plank, + ui_phcarb, + ts, state_info, state_paths, state_ix, @@ -300,13 +311,13 @@ def rqual( # for multiple exits, modify save table as needed if nexits > 1: - u = uci_oxrx["SAVE"] + u = parameters_oxrx["SAVE"] for i in range(nexits): u[f"OXCF2_{i + 1}1"] = u["OXCF2_11"] u[f"OXCF2_{i + 1}2"] = u["OXCF2_12"] if NUTFG == 1: - u = uci_nutrx["SAVE"] + u = parameters_nutrx["SAVE"] for i in range(nexits): u[f"NUCF9_{i + 1}1"] = u["NUCF9_11"] u[f"NUCF9_{i + 1}2"] = u["NUCF9_12"] @@ -322,7 +333,7 @@ def rqual( u[f"OSPO4_{i + 1}4"] = u["OSPO4_14"] if PLKFG == 1: - u = uci_plank["SAVE"] + u = parameters_plank["SAVE"] for i in range(nexits): u[f"PKCF2_{i + 1}1"] = u["PKCF2_11"] u[f"PKCF2_{i + 1}2"] = u["PKCF2_12"] @@ -336,7 +347,7 @@ def rqual( u[f"TPKCF2_{i + 1}5"] = u["TPKCF2_15"] if PHFG == 1: - u = uci_phcarb["SAVE"] + u = parameters_phcarb["SAVE"] for i in range(nexits): u[f"OTIC{i + 1}"] = u["OTIC1"] u[f"OCO2{i + 1}"] = u["OCO21"] @@ -345,32 +356,40 @@ def rqual( @njit(cache=True) -def _rqual_run(siminfo_, ui, ui_oxrx, ui_nutrx, ui_plank, ui_phcarb, ts, - state_info, - state_paths, - state_ix, - dict_ix, - ts_ix, - op_tokens, - model_exec_list): +def _rqual_run( + siminfo_, + ui, + ui_oxrx, + ui_nutrx, + ui_plank, + ui_phcarb, + ts, + state_info, + state_paths, + state_ix, + dict_ix, + ts_ix, + op_tokens, + model_exec_list, +): nutrx_errors = zeros((0), dtype=np.int64) plank_errors = zeros((0), dtype=np.int64) phcarb_errors = zeros((0), dtype=np.int64) # initialize WQ simulation: - RQUAL = RQUAL_Class(siminfo_, ui, ui_oxrx, ui_nutrx, ui_plank, ui_phcarb, ts - ) + RQUAL = RQUAL_Class(siminfo_, ui, ui_oxrx, ui_nutrx, ui_plank, ui_phcarb, ts) # run WQ simulation: - RQUAL.simulate(ts, - state_info, - state_paths, - state_ix, - dict_ix, - ts_ix, - op_tokens, - model_exec_list - ) + RQUAL.simulate( + ts, + state_info, + state_paths, + state_ix, + dict_ix, + ts_ix, + op_tokens, + model_exec_list, + ) # return error data: oxrx_errors = RQUAL.OXRX.errors @@ -431,7 +450,7 @@ def _compile_errors(NUTFG, PLKFG, PHFG, err_oxrx, err_nutrx, err_plank, err_phca # ------------------------------------------------------------------- -def expand_OXRX_masslinks(flags, uci, dat, recs): +def expand_OXRX_masslinks(flags, parameters, dat, recs): if flags["OXRX"]: for i in range(1, 3): rec = {} @@ -457,7 +476,7 @@ def expand_OXRX_masslinks(flags, uci, dat, recs): return recs -def expand_NUTRX_masslinks(flags, uci, dat, recs): +def expand_NUTRX_masslinks(flags, parameters, dat, recs): if flags["NUTRX"]: # dissolved species: for i in range(1, 5): @@ -527,7 +546,7 @@ def expand_NUTRX_masslinks(flags, uci, dat, recs): return recs -def expand_PLANK_masslinks(flags, uci, dat, recs): +def expand_PLANK_masslinks(flags, parameters, dat, recs): if flags["PLANK"]: for i in range(1, 6): rec = {} @@ -552,7 +571,7 @@ def expand_PLANK_masslinks(flags, uci, dat, recs): return recs -def expand_PHCARB_masslinks(flags, uci, dat, recs): +def expand_PHCARB_masslinks(flags, parameters, dat, recs): if flags["PHCARB"]: for i in range(1, 3): rec = {} diff --git a/src/hsp2/hsp2/RQUAL_Class.py b/src/hsp2/hsp2/RQUAL_Class.py index f90155cf..22e0eb7a 100644 --- a/src/hsp2/hsp2/RQUAL_Class.py +++ b/src/hsp2/hsp2/RQUAL_Class.py @@ -1,16 +1,13 @@ import os -from math import log import numba as nb -import numpy as np from numba.experimental import jitclass -from numpy import array, where, zeros +from numpy import zeros from hsp2.hsp2.NUTRX_Class import NUTRX_Class from hsp2.hsp2.OXRX_Class import OXRX_Class from hsp2.hsp2.PHCARB_Class import PHCARB_Class from hsp2.hsp2.PLANK_Class import PLANK_Class -from hsp2.hsp2.utilities import initm, make_numba_dict # the following imports added to handle special actions from hsp2.hsp2.state import rqual_get_ix @@ -790,7 +787,7 @@ def __init__(self, siminfo, ui, ui_oxrx, ui_nutrx, ui_plank, ui_phcarb, ts): ts["PHIF2"] = zeros(simlen) ts["ICO2"] = ts["PHIF2"] - if not "ALKCON" in ts: + if "ALKCON" not in ts: ts["ALKCON"] = zeros(simlen) if "CONS" + str(int(self.PHCARB.alkcon)) + "_CON" in ts: self.ALK = ts["CONS" + str(int(self.PHCARB.alkcon)) + "_CON"] @@ -823,35 +820,36 @@ def __init__(self, siminfo, ui, ui_oxrx, ui_nutrx, ui_plank, ui_phcarb, ts): return - def simulate(self, ts, - state_info, - state_paths, - state_ix, - dict_ix, - ts_ix, - op_tokens, - model_exec_list): - + def simulate( + self, + ts, + state_info, + state_paths, + state_ix, + dict_ix, + ts_ix, + op_tokens, + model_exec_list, + ): ####################################################################################### # the following section (2 of 3) added by pbd to RQUAL, this one to prepare for special actions ####################################################################################### rqual_ix = rqual_get_ix(state_ix, state_paths, state_info["domain"]) # these are integer placeholders faster than calling the array look each timestep - dox_ix = (rqual_ix["DOX"]) - bod_ix = (rqual_ix["BOD"]) - no3_ix = (rqual_ix["NO3"]) - tam_ix = (rqual_ix["TAM"]) - no2_ix = (rqual_ix["NO2"]) - po4_ix = (rqual_ix["PO4"]) - brtam1_ix = (rqual_ix["BRTAM1"]) - brtam2_ix = (rqual_ix["BRTAM2"]) - brpo41_ix = (rqual_ix["BRPO41"]) - brpo42_ix = (rqual_ix["BRPO42"]) - cforea_ix = (rqual_ix["CFOREA"]) + dox_ix = rqual_ix["DOX"] + bod_ix = rqual_ix["BOD"] + no3_ix = rqual_ix["NO3"] + tam_ix = rqual_ix["TAM"] + no2_ix = rqual_ix["NO2"] + po4_ix = rqual_ix["PO4"] + brtam1_ix = rqual_ix["BRTAM1"] + brtam2_ix = rqual_ix["BRTAM2"] + brpo41_ix = rqual_ix["BRPO41"] + brpo42_ix = rqual_ix["BRPO42"] + cforea_ix = rqual_ix["CFOREA"] ####################################################################################### for loop in range(self.simlen): - ####################################################################################### # the following section (3 of 3) added by pbd to accommodate special actions ####################################################################################### @@ -862,10 +860,10 @@ def simulate(self, ts, state_ix[tam_ix] = self.NUTRX.tam state_ix[no2_ix] = self.NUTRX.no2 state_ix[po4_ix] = self.NUTRX.po4 - state_ix[brtam1_ix] = self.NUTRX.brtam[1] - state_ix[brtam2_ix] = self.NUTRX.brtam[2] - state_ix[brpo41_ix] = self.NUTRX.brpo4[1] - state_ix[brpo42_ix] = self.NUTRX.brpo4[2] + state_ix[brtam1_ix] = self.NUTRX.brtam[0] + state_ix[brtam2_ix] = self.NUTRX.brtam[1] + state_ix[brpo41_ix] = self.NUTRX.brpo4[0] + state_ix[brpo42_ix] = self.NUTRX.brpo4[1] state_ix[cforea_ix] = self.OXRX.cforea if state_info["state_step_om"] == "enabled": pre_step_model( @@ -885,10 +883,10 @@ def simulate(self, ts, self.NUTRX.tam = state_ix[tam_ix] self.NUTRX.no2 = state_ix[no2_ix] self.NUTRX.po4 = state_ix[po4_ix] - self.NUTRX.brtam[1] = state_ix[brtam1_ix] - self.NUTRX.brtam[2] = state_ix[brtam2_ix] - self.NUTRX.brpo4[1] = state_ix[brpo41_ix] - self.NUTRX.brpo4[2] = state_ix[brpo42_ix] + self.NUTRX.brtam[0] = state_ix[brtam1_ix] + self.NUTRX.brtam[1] = state_ix[brtam2_ix] + self.NUTRX.brpo4[0] = state_ix[brpo41_ix] + self.NUTRX.brpo4[1] = state_ix[brpo42_ix] self.OXRX.cforea = state_ix[cforea_ix] ####################################################################################### diff --git a/src/hsp2/hsp2/SEDMNT.py b/src/hsp2/hsp2/SEDMNT.py index 45406a39..3c8953a1 100644 --- a/src/hsp2/hsp2/SEDMNT.py +++ b/src/hsp2/hsp2/SEDMNT.py @@ -8,7 +8,7 @@ """ from numba import njit, types -from numpy import float64, full, int64, where, zeros, asarray +from numpy import float64, full, int64, zeros, asarray from hsp2.hsp2.utilities import hourflag, initm, make_numba_dict @@ -24,25 +24,29 @@ MFACTA = 1.0 -def sedmnt(io_manager, siminfo, uci, ts, state): +def sedmnt(io_manager, siminfo, parameters, ts, state): """Produce and remove sediment from the land surface""" simlen = siminfo["steps"] - ui = make_numba_dict(uci) # Note: all values converted to float automatically + ui = make_numba_dict( + parameters + ) # Note: all values converted to float automatically ui["simlen"] = siminfo["steps"] ui["uunits"] = siminfo["units"] ui["delt"] = siminfo["delt"] ui["errlen"] = len(ERRMSG) - u = uci["PARAMETERS"] + u = parameters["PARAMETERS"] if "CRVFG" in u: - ts["COVERI"] = initm(siminfo, uci, u["CRVFG"], "MONTHLY_COVER", u["COVER"]) + ts["COVERI"] = initm( + siminfo, parameters, u["CRVFG"], "MONTHLY_COVER", u["COVER"] + ) else: ts["COVERI"] = full(simlen, u["COVER"]) if "VSIVFG" in u: - ts["NVSI"] = initm(siminfo, uci, u["VSIVFG"], "MONTHLY_NVSI", u["NVSI"]) + ts["NVSI"] = initm(siminfo, parameters, u["VSIVFG"], "MONTHLY_NVSI", u["NVSI"]) else: ts["NVSI"] = full(simlen, u["NVSI"]) @@ -207,9 +211,7 @@ def _sedmnt_( ####################################################################################### sedmnt_ix = sedmnt_get_ix(state_ix, state_paths, state_info["domain"]) # these are integer placeholders faster than calling the array look each timestep - dets_ix = ( - sedmnt_ix["DETS"] - ) + dets_ix = sedmnt_ix["DETS"] ####################################################################################### for loop in range(simlen): diff --git a/src/hsp2/hsp2/SEDTRN.py b/src/hsp2/hsp2/SEDTRN.py index fd48ff7f..475fb31e 100644 --- a/src/hsp2/hsp2/SEDTRN.py +++ b/src/hsp2/hsp2/SEDTRN.py @@ -25,7 +25,7 @@ ) # ERRMSG6 -def sedtrn(io_manager, siminfo, uci, ts, state): +def sedtrn(io_manager, siminfo, parameters, ts, state): """Simulate behavior of inorganic sediment""" # simlen = siminfo['steps'] @@ -34,7 +34,7 @@ def sedtrn(io_manager, siminfo, uci, ts, state): delts = siminfo["delt"] * 60 uunits = siminfo["units"] - advectData = uci["advectData"] + advectData = parameters["advectData"] (nexits, vol, VOL, SROVOL, EROVOL, SOVOL, EOVOL) = advectData ts["VOL"] = VOL @@ -44,7 +44,7 @@ def sedtrn(io_manager, siminfo, uci, ts, state): ts["SOVOL" + str(i + 1)] = SOVOL[:, i] ts["EOVOL" + str(i + 1)] = EOVOL[:, i] - ui = make_numba_dict(uci) + ui = make_numba_dict(parameters) ui["simlen"] = siminfo["steps"] ui["uunits"] = siminfo["units"] ui["vol"] = vol @@ -52,7 +52,7 @@ def sedtrn(io_manager, siminfo, uci, ts, state): ui["delt60"] = siminfo["delt"] / 60 ui["errlen"] = len(ERRMSGS) - ui_silt = uci["SILT"] + ui_silt = parameters["SILT"] if uunits == 1: ui["silt_d"] = ui_silt["D"] * 0.0833 ui["silt_w"] = ( @@ -70,7 +70,7 @@ def sedtrn(io_manager, siminfo, uci, ts, state): ui_silt["M"] * delt60 / 24.0 * 4.880 ) # convert erodibility coeff from /day to /ivl - ui_clay = uci["CLAY"] + ui_clay = parameters["CLAY"] if uunits == 1: ui["clay_d"] = ui_clay["D"] * 0.0833 ui["clay_w"] = ( @@ -142,17 +142,17 @@ def sedtrn(io_manager, siminfo, uci, ts, state): ############################################################################ if nexits > 1: - u = uci["SAVE"] + u = parameters["SAVE"] key1 = "OSED1" key2 = "OSED2" key3 = "OSED3" key4 = "OSED4" keyx = "OSED" for i in range(nexits): - u[f"{keyx}{i + 1}"+"1"] = u[key1] - u[f"{keyx}{i + 1}"+"2"] = u[key2] - u[f"{keyx}{i + 1}"+"3"] = u[key3] - u[f"{keyx}{i + 1}"+"4"] = u[key4] + u[f"{keyx}{i + 1}" + "1"] = u[key1] + u[f"{keyx}{i + 1}" + "2"] = u[key2] + u[f"{keyx}{i + 1}" + "3"] = u[key3] + u[f"{keyx}{i + 1}" + "4"] = u[key4] del u[key1] del u[key2] del u[key3] @@ -438,7 +438,7 @@ def _sedtrn_( ####################################################################################### # perform any necessary unit conversions - if uunits == 2: # uci is in metric units + if uunits == 2: # parameters is in metric units avvele = AVVEL[loop] * 3.28 avdepm = AVDEP[loop] avdepe = AVDEP[loop] * 3.28 @@ -448,7 +448,7 @@ def _sedtrn_( ised1 = ISED1[loop] / 2.83e-08 ised2 = ISED2[loop] / 2.83e-08 ised3 = ISED3[loop] / 2.83e-08 - else: # uci is in english units + else: # parameters is in english units avvele = AVVEL[loop] avdepm = AVDEP[loop] * 0.3048 avdepe = AVDEP[loop] @@ -1162,7 +1162,7 @@ def toffaleti(v, fdiam, fhrad, slope, tempr, vset): ) # Total transport capacity of the rchres (tons/day/ft) -def expand_SEDTRN_masslinks(flags, uci, dat, recs): +def expand_SEDTRN_masslinks(flags, parameters, dat, recs): if flags["SEDTRN"]: # ISED1 rec = {} diff --git a/src/hsp2/hsp2/SNOW.py b/src/hsp2/hsp2/SNOW.py index 46dca5f1..0aae2a63 100644 --- a/src/hsp2/hsp2/SNOW.py +++ b/src/hsp2/hsp2/SNOW.py @@ -17,20 +17,19 @@ from hsp2.hsp2.utilities import ( SEASONS, SVP, - hourflag, hoursval, initm, make_numba_dict, monthval, ) -from hsp2.hsp2io.protocols import Category, SupportsReadTS +from hsp2.hsp2io.protocols import SupportsReadTS ERRMSGS = ( "Snow simulation cannot function properly with delt> 360", # ERRMSG0 ) -def snow(io_manager: SupportsReadTS, siminfo, uci, ts): +def snow(io_manager: SupportsReadTS, siminfo, parameters, ts): """high level driver for SNOW module CALL: snow(store, general, ui, ts) store is the Pandas/PyTable open store @@ -62,8 +61,8 @@ def snow(io_manager: SupportsReadTS, siminfo, uci, ts): "SNOWCF", "KMELT", ]: - if name not in ts and name in uci["PARAMETERS"]: - ts[name] = full(steps, uci["PARAMETERS"][name]) + if name not in ts and name in parameters["PARAMETERS"]: + ts[name] = full(steps, parameters["PARAMETERS"][name]) # true the first time and at 6am and earlier every day of simulation ts["HR6IND"] = hour6flag(siminfo, dofirst=True).astype(float) @@ -73,25 +72,25 @@ def snow(io_manager: SupportsReadTS, siminfo, uci, ts): # make ICEFG available to PWATER later. siminfo["ICEFG"] = 0 - if "FLAGS" in uci: - if "ICEFG" in uci["FLAGS"]: - siminfo["ICEFG"] = uci["FLAGS"]["ICEFG"] + if "FLAGS" in parameters: + if "ICEFG" in parameters["FLAGS"]: + siminfo["ICEFG"] = parameters["FLAGS"]["ICEFG"] - ui = make_numba_dict(uci) # Note: all values coverted to float automatically + ui = make_numba_dict(parameters) # Note: all values coverted to float automatically ui["steps"] = steps ui["uunits"] = UUNITS ui["delt"] = siminfo["delt"] ui["errlen"] = len(ERRMSGS) ui["cloudfg"] = cloudfg - u = uci["PARAMETERS"] + u = parameters["PARAMETERS"] vkmfg = 0 - if "FLAGS" in uci: - uf = uci["FLAGS"] + if "FLAGS" in parameters: + uf = parameters["FLAGS"] if "VKMFG" in uf: vkmfg = uf["VKMFG"] - ts["KMELT"] = initm(siminfo, uci, vkmfg, "MONTHLY_KMELT", u["KMELT"]) + ts["KMELT"] = initm(siminfo, parameters, vkmfg, "MONTHLY_KMELT", u["KMELT"]) ############################################################################ errors = _snow_(ui, ts) diff --git a/src/hsp2/hsp2/SOLIDS.py b/src/hsp2/hsp2/SOLIDS.py index fdc6ae01..95523dbd 100644 --- a/src/hsp2/hsp2/SOLIDS.py +++ b/src/hsp2/hsp2/SOLIDS.py @@ -5,7 +5,7 @@ Conversion of HSPF HIMPSLD.FOR module into Python""" from numba import njit -from numpy import float64, full, int64, where, zeros +from numpy import float64, full, int64, zeros from hsp2.hsp2.utilities import hourflag, initm, make_numba_dict @@ -14,7 +14,7 @@ ERRMSG = [] -def solids(io_manager, siminfo, uci, ts): +def solids(io_manager, siminfo, parameters, ts): """Accumulate and remove solids from the impervious land segment""" simlen = siminfo["steps"] @@ -23,18 +23,24 @@ def solids(io_manager, siminfo, uci, ts): if name not in ts: ts[name] = zeros(simlen) - u = uci["PARAMETERS"] + u = parameters["PARAMETERS"] # process optional monthly arrays to return interpolated data or constant array if "VASDFG" in u: - ts["ACCSDP"] = initm(siminfo, uci, u["VASDFG"], "MONTHLY_ACCSDP", u["ACCSDP"]) + ts["ACCSDP"] = initm( + siminfo, parameters, u["VASDFG"], "MONTHLY_ACCSDP", u["ACCSDP"] + ) else: ts["ACCSDP"] = full(simlen, u["ACCSDP"]) if "VRSDFG" in u: - ts["REMSDP"] = initm(siminfo, uci, u["VRSDFG"], "MONTHLY_REMSDP", u["REMSDP"]) + ts["REMSDP"] = initm( + siminfo, parameters, u["VRSDFG"], "MONTHLY_REMSDP", u["REMSDP"] + ) else: ts["REMSDP"] = full(simlen, u["REMSDP"]) - ui = make_numba_dict(uci) # Note: all values converted to float automatically + ui = make_numba_dict( + parameters + ) # Note: all values converted to float automatically ui["uunits"] = siminfo["units"] ui["simlen"] = siminfo["steps"] ui["delt60"] = siminfo["delt"] / 60 # delt60 - simulation time interval in hours diff --git a/src/hsp2/hsp2/__init__.py b/src/hsp2/hsp2/__init__.py index ddd1ac44..ff02c7cc 100644 --- a/src/hsp2/hsp2/__init__.py +++ b/src/hsp2/hsp2/__init__.py @@ -1,5 +1,5 @@ -"""The `hsp2` module contains the hydrology and water quality code modules - converted from HSPF, along with the main programs to run HSP2 +"""The `hsp2` module contains the hydrology and water quality code modules +converted from HSPF, along with the main programs to run HSP2 """ from hsp2.hsp2.main import main diff --git a/src/hsp2/hsp2/configuration.py b/src/hsp2/hsp2/configuration.py index 54aaa80a..7f0beaba 100644 --- a/src/hsp2/hsp2/configuration.py +++ b/src/hsp2/hsp2/configuration.py @@ -85,16 +85,16 @@ def noop(store, siminfo, ui, ts): } -def expand_masslinks(flags, uci, dat, recs): - recs = expand_HYDR_masslinks(flags, uci, dat, recs) - recs = expand_HTRCH_masslinks(flags, uci, dat, recs) - recs = expand_CONS_masslinks(flags, uci, dat, recs) - recs = expand_SEDTRN_masslinks(flags, uci, dat, recs) - recs = expand_GQUAL_masslinks(flags, uci, dat, recs) - recs = expand_OXRX_masslinks(flags, uci, dat, recs) - recs = expand_NUTRX_masslinks(flags, uci, dat, recs) - recs = expand_PLANK_masslinks(flags, uci, dat, recs) - recs = expand_PHCARB_masslinks(flags, uci, dat, recs) +def expand_masslinks(flags, parameters, dat, recs): + recs = expand_HYDR_masslinks(flags, parameters, dat, recs) + recs = expand_HTRCH_masslinks(flags, parameters, dat, recs) + recs = expand_CONS_masslinks(flags, parameters, dat, recs) + recs = expand_SEDTRN_masslinks(flags, parameters, dat, recs) + recs = expand_GQUAL_masslinks(flags, parameters, dat, recs) + recs = expand_OXRX_masslinks(flags, parameters, dat, recs) + recs = expand_NUTRX_masslinks(flags, parameters, dat, recs) + recs = expand_PLANK_masslinks(flags, parameters, dat, recs) + recs = expand_PHCARB_masslinks(flags, parameters, dat, recs) return recs diff --git a/src/hsp2/hsp2/main.py b/src/hsp2/hsp2/main.py index cf49aa6d..31886728 100644 --- a/src/hsp2/hsp2/main.py +++ b/src/hsp2/hsp2/main.py @@ -65,18 +65,18 @@ def main( msg = messages() msg(1, f"Processing started for file {hdfname}; saveall={saveall}") - # read user control, parameters, states, and flags uci and map to local variables - uci_obj = io_manager.read_uci() - opseq = uci_obj.opseq - ddlinks = uci_obj.ddlinks - ddmasslinks = uci_obj.ddmasslinks - ddext_sources = uci_obj.ddext_sources - ddgener = uci_obj.ddgener - uci = uci_obj.uci - siminfo = uci_obj.siminfo - ftables = uci_obj.ftables - specactions = uci_obj.specactions - monthdata = uci_obj.monthdata + # read user control, parameters, states, and flags parameters and map to local variables + parameter_obj = io_manager.read_parameters() + opseq = parameter_obj.opseq + ddlinks = parameter_obj.ddlinks + ddmasslinks = parameter_obj.ddmasslinks + ddext_sources = parameter_obj.ddext_sources + ddgener = parameter_obj.ddgener + model = parameter_obj.model + siminfo = parameter_obj.siminfo + ftables = parameter_obj.ftables + specactions = parameter_obj.specactions + monthdata = parameter_obj.monthdata start, stop = siminfo["start"], siminfo["stop"] @@ -88,7 +88,7 @@ def main( ####################################################################################### # Set up Things in state that will be used in all modular activities like SPECL state = init_state_dicts() - state_siminfo_hsp2(uci_obj, siminfo, io_manager, state) + state_siminfo_hsp2(parameter_obj, siminfo, io_manager, state) # Add support for dynamic functions to operate on STATE # - Load any dynamic components if present, and store variables on objects state_load_dynamics_hsp2(state, io_manager, siminfo) @@ -131,7 +131,7 @@ def main( io_manager, ts, {}, - uci, + model, segment, ddlinks, ddmasslinks, @@ -158,20 +158,20 @@ def main( ts = get_gener_timeseries( ts, gener_instances, ddlinks[segment], ddmasslinks ) - flags = uci[(operation, "GENERAL", segment)]["ACTIVITY"] + flags = model[(operation, "GENERAL", segment)]["ACTIVITY"] if operation == "RCHRES": # Add nutrient adsorption flags: if flags["NUTRX"] == 1: - flags["TAMFG"] = uci[(operation, "NUTRX", segment)]["FLAGS"][ + flags["TAMFG"] = model[(operation, "NUTRX", segment)]["FLAGS"][ "NH3FG" ] - flags["ADNHFG"] = uci[(operation, "NUTRX", segment)]["FLAGS"][ + flags["ADNHFG"] = model[(operation, "NUTRX", segment)]["FLAGS"][ "ADNHFG" ] - flags["PO4FG"] = uci[(operation, "NUTRX", segment)]["FLAGS"][ + flags["PO4FG"] = model[(operation, "NUTRX", segment)]["FLAGS"][ "PO4FG" ] - flags["ADPOFG"] = uci[(operation, "NUTRX", segment)]["FLAGS"][ + flags["ADPOFG"] = model[(operation, "NUTRX", segment)]["FLAGS"][ "ADPOFG" ] @@ -179,7 +179,7 @@ def main( io_manager, ts, flags, - uci, + model, segment, ddlinks, ddmasslinks, @@ -207,10 +207,10 @@ def main( # Set context for dynamic executables and special actions state_context_hsp2(state, operation, segment, activity) - ui = uci[(operation, activity, segment)] # ui is a dictionary + ui = model[(operation, activity, segment)] # ui is a dictionary if operation == "PERLND" and activity == "SEDMNT": # special exception here to make CSNOFG available - ui["PARAMETERS"]["CSNOFG"] = uci[(operation, "PWATER", segment)][ + ui["PARAMETERS"]["CSNOFG"] = model[(operation, "PWATER", segment)][ "PARAMETERS" ]["CSNOFG"] if operation == "PERLND" and activity == "PSTEMP": @@ -218,125 +218,125 @@ def main( ui["PARAMETERS"]["AIRTFG"] = flags["ATEMP"] if operation == "PERLND" and activity == "PWTGAS": # special exception here to make CSNOFG available - ui["PARAMETERS"]["CSNOFG"] = uci[(operation, "PWATER", segment)][ + ui["PARAMETERS"]["CSNOFG"] = model[(operation, "PWATER", segment)][ "PARAMETERS" ]["CSNOFG"] if operation == "RCHRES": if "PARAMETERS" not in ui: ui["PARAMETERS"] = {} - ui["PARAMETERS"]["NEXITS"] = uci[(operation, "HYDR", segment)][ + ui["PARAMETERS"]["NEXITS"] = model[(operation, "HYDR", segment)][ "PARAMETERS" ]["NEXITS"] if activity == "ADCALC": ui["PARAMETERS"]["ADFG"] = flags["ADCALC"] - ui["PARAMETERS"]["KS"] = uci[(operation, "HYDR", segment)][ + ui["PARAMETERS"]["KS"] = model[(operation, "HYDR", segment)][ "PARAMETERS" ]["KS"] - ui["PARAMETERS"]["VOL"] = uci[(operation, "HYDR", segment)][ + ui["PARAMETERS"]["VOL"] = model[(operation, "HYDR", segment)][ "STATES" ]["VOL"] - ui["PARAMETERS"]["ROS"] = uci[(operation, "HYDR", segment)][ + ui["PARAMETERS"]["ROS"] = model[(operation, "HYDR", segment)][ "PARAMETERS" ]["ROS"] - nexits = uci[(operation, "HYDR", segment)]["PARAMETERS"][ + nexits = model[(operation, "HYDR", segment)]["PARAMETERS"][ "NEXITS" ] for index in range(nexits): - ui["PARAMETERS"]["OS" + str(index + 1)] = uci[ + ui["PARAMETERS"]["OS" + str(index + 1)] = model[ (operation, "HYDR", segment) ]["PARAMETERS"]["OS" + str(index + 1)] if activity == "HTRCH": ui["PARAMETERS"]["ADFG"] = flags["ADCALC"] - ui["advectData"] = uci[(operation, "ADCALC", segment)][ + ui["advectData"] = model[(operation, "ADCALC", segment)][ "adcalcData" ] - # ui['STATES']['VOL'] = uci[(operation, 'HYDR', segment)]['STATES']['VOL'] + # ui['STATES']['VOL'] = parameters[(operation, 'HYDR', segment)]['STATES']['VOL'] if activity == "CONS": - ui["advectData"] = uci[(operation, "ADCALC", segment)][ + ui["advectData"] = model[(operation, "ADCALC", segment)][ "adcalcData" ] if activity == "SEDTRN": ui["PARAMETERS"]["ADFG"] = flags["ADCALC"] - ui["advectData"] = uci[(operation, "ADCALC", segment)][ + ui["advectData"] = model[(operation, "ADCALC", segment)][ "adcalcData" ] - # ui['STATES']['VOL'] = uci[(operation, 'HYDR', segment)]['STATES']['VOL'] + # ui['STATES']['VOL'] = parameters[(operation, 'HYDR', segment)]['STATES']['VOL'] ui["PARAMETERS"]["HTFG"] = flags["HTRCH"] ui["PARAMETERS"]["AUX3FG"] = 0 if flags["HYDR"]: - ui["PARAMETERS"]["LEN"] = uci[(operation, "HYDR", segment)][ - "PARAMETERS" - ]["LEN"] - ui["PARAMETERS"]["DELTH"] = uci[ + ui["PARAMETERS"]["LEN"] = model[ + (operation, "HYDR", segment) + ]["PARAMETERS"]["LEN"] + ui["PARAMETERS"]["DELTH"] = model[ (operation, "HYDR", segment) ]["PARAMETERS"]["DELTH"] - ui["PARAMETERS"]["DB50"] = uci[ + ui["PARAMETERS"]["DB50"] = model[ (operation, "HYDR", segment) ]["PARAMETERS"]["DB50"] - ui["PARAMETERS"]["AUX3FG"] = uci[ + ui["PARAMETERS"]["AUX3FG"] = model[ (operation, "HYDR", segment) ]["PARAMETERS"]["AUX3FG"] if activity == "GQUAL": - ui["advectData"] = uci[(operation, "ADCALC", segment)][ + ui["advectData"] = model[(operation, "ADCALC", segment)][ "adcalcData" ] ui["PARAMETERS"]["HTFG"] = flags["HTRCH"] ui["PARAMETERS"]["SEDFG"] = flags["SEDTRN"] - # ui['PARAMETERS']['REAMFG'] = uci[(operation, 'OXRX', segment)]['PARAMETERS']['REAMFG'] + # ui['PARAMETERS']['REAMFG'] = parameters[(operation, 'OXRX', segment)]['PARAMETERS']['REAMFG'] ui["PARAMETERS"]["HYDRFG"] = flags["HYDR"] if flags["HYDR"]: - ui["PARAMETERS"]["LKFG"] = uci[ + ui["PARAMETERS"]["LKFG"] = model[ (operation, "HYDR", segment) ]["PARAMETERS"]["LKFG"] - ui["PARAMETERS"]["AUX1FG"] = uci[ + ui["PARAMETERS"]["AUX1FG"] = model[ (operation, "HYDR", segment) ]["PARAMETERS"]["AUX1FG"] - ui["PARAMETERS"]["AUX2FG"] = uci[ + ui["PARAMETERS"]["AUX2FG"] = model[ (operation, "HYDR", segment) ]["PARAMETERS"]["AUX2FG"] - ui["PARAMETERS"]["LEN"] = uci[(operation, "HYDR", segment)][ - "PARAMETERS" - ]["LEN"] - ui["PARAMETERS"]["DELTH"] = uci[ + ui["PARAMETERS"]["LEN"] = model[ + (operation, "HYDR", segment) + ]["PARAMETERS"]["LEN"] + ui["PARAMETERS"]["DELTH"] = model[ (operation, "HYDR", segment) ]["PARAMETERS"]["DELTH"] if flags["OXRX"]: - ui["PARAMETERS"]["LKFG"] = uci[ + ui["PARAMETERS"]["LKFG"] = model[ (operation, "HYDR", segment) ]["PARAMETERS"]["LKFG"] - ui["PARAMETERS"]["CFOREA"] = uci[ + ui["PARAMETERS"]["CFOREA"] = model[ (operation, "OXRX", segment) ]["PARAMETERS"]["CFOREA"] if flags["SEDTRN"]: - ui["PARAMETERS"]["SSED1"] = uci[ + ui["PARAMETERS"]["SSED1"] = model[ (operation, "SEDTRN", segment) ]["STATES"]["SSED1"] - ui["PARAMETERS"]["SSED2"] = uci[ + ui["PARAMETERS"]["SSED2"] = model[ (operation, "SEDTRN", segment) ]["STATES"]["SSED2"] - ui["PARAMETERS"]["SSED3"] = uci[ + ui["PARAMETERS"]["SSED3"] = model[ (operation, "SEDTRN", segment) ]["STATES"]["SSED3"] if flags["HTRCH"]: - ui["PARAMETERS"]["CFSAEX"] = uci[ + ui["PARAMETERS"]["CFSAEX"] = model[ (operation, "HTRCH", segment) ]["PARAMETERS"]["CFSAEX"] elif flags["PLANK"]: if ( "CFSAEX" - in uci[(operation, "PLANK", segment)]["PARAMETERS"] + in model[(operation, "PLANK", segment)]["PARAMETERS"] ): - ui["PARAMETERS"]["CFSAEX"] = uci[ + ui["PARAMETERS"]["CFSAEX"] = model[ (operation, "PLANK", segment) ]["PARAMETERS"]["CFSAEX"] if activity == "RQUAL": # RQUAL inputs: - ui["advectData"] = uci[(operation, "ADCALC", segment)][ + ui["advectData"] = model[(operation, "ADCALC", segment)][ "adcalcData" ] if flags["HYDR"]: - ui["PARAMETERS"]["LKFG"] = uci[ + ui["PARAMETERS"]["LKFG"] = model[ (operation, "HYDR", segment) ]["PARAMETERS"]["LKFG"] @@ -348,52 +348,52 @@ def main( ui["FLAGS"]["PLKFG"] = flags["PLANK"] ui["FLAGS"]["PHFG"] = flags["PHCARB"] if flags["CONS"]: - if "PARAMETERS" in uci[(operation, "CONS", segment)]: + if "PARAMETERS" in model[(operation, "CONS", segment)]: if ( "NCONS" - in uci[(operation, "CONS", segment)]["PARAMETERS"] + in model[(operation, "CONS", segment)]["PARAMETERS"] ): - ui["PARAMETERS"]["NCONS"] = uci[ + ui["PARAMETERS"]["NCONS"] = model[ (operation, "CONS", segment) ]["PARAMETERS"]["NCONS"] # OXRX module inputs: - ui_oxrx = uci[(operation, "OXRX", segment)] + ui_oxrx = model[(operation, "OXRX", segment)] if flags["HYDR"]: - ui_oxrx["PARAMETERS"]["LEN"] = uci[ + ui_oxrx["PARAMETERS"]["LEN"] = model[ (operation, "HYDR", segment) ]["PARAMETERS"]["LEN"] - ui_oxrx["PARAMETERS"]["DELTH"] = uci[ + ui_oxrx["PARAMETERS"]["DELTH"] = model[ (operation, "HYDR", segment) ]["PARAMETERS"]["DELTH"] if flags["HTRCH"]: - ui_oxrx["PARAMETERS"]["ELEV"] = uci[ + ui_oxrx["PARAMETERS"]["ELEV"] = model[ (operation, "HTRCH", segment) ]["PARAMETERS"]["ELEV"] if flags["SEDTRN"]: - ui["PARAMETERS"]["SSED1"] = uci[ + ui["PARAMETERS"]["SSED1"] = model[ (operation, "SEDTRN", segment) ]["STATES"]["SSED1"] - ui["PARAMETERS"]["SSED2"] = uci[ + ui["PARAMETERS"]["SSED2"] = model[ (operation, "SEDTRN", segment) ]["STATES"]["SSED2"] - ui["PARAMETERS"]["SSED3"] = uci[ + ui["PARAMETERS"]["SSED3"] = model[ (operation, "SEDTRN", segment) ]["STATES"]["SSED3"] # PLANK module inputs: if flags["HTRCH"]: - ui["PARAMETERS"]["CFSAEX"] = uci[ + ui["PARAMETERS"]["CFSAEX"] = model[ (operation, "HTRCH", segment) ]["PARAMETERS"]["CFSAEX"] # NUTRX, PLANK, PHCARB module inputs: - ui_nutrx = uci[(operation, "NUTRX", segment)] - ui_plank = uci[(operation, "PLANK", segment)] - ui_phcarb = uci[(operation, "PHCARB", segment)] + ui_nutrx = model[(operation, "NUTRX", segment)] + ui_plank = model[(operation, "PLANK", segment)] + ui_phcarb = model[(operation, "PHCARB", segment)] ############ calls activity function like snow() ############## if operation not in ["COPY", "GENER"]: @@ -418,7 +418,7 @@ def main( ui_phcarb, ts, monthdata, - state + state, ) ############################################################### @@ -432,24 +432,24 @@ def main( outstep_nutrx = 2 outstep_plank = 2 outstep_phcarb = 2 - if "BINOUT" in uci[(operation, "GENERAL", segment)]: - if activity in uci[(operation, "GENERAL", segment)]["BINOUT"]: - outstep = uci[(operation, "GENERAL", segment)]["BINOUT"][ + if "BINOUT" in model[(operation, "GENERAL", segment)]: + if activity in model[(operation, "GENERAL", segment)]["BINOUT"]: + outstep = model[(operation, "GENERAL", segment)]["BINOUT"][ activity ] elif activity == "RQUAL": - outstep_oxrx = uci[(operation, "GENERAL", segment)]["BINOUT"][ + outstep_oxrx = model[(operation, "GENERAL", segment)]["BINOUT"][ "OXRX" ] - outstep_nutrx = uci[(operation, "GENERAL", segment)]["BINOUT"][ - "NUTRX" - ] - outstep_plank = uci[(operation, "GENERAL", segment)]["BINOUT"][ - "PLANK" - ] - outstep_phcarb = uci[(operation, "GENERAL", segment)]["BINOUT"][ - "PHCARB" - ] + outstep_nutrx = model[(operation, "GENERAL", segment)][ + "BINOUT" + ]["NUTRX"] + outstep_plank = model[(operation, "GENERAL", segment)][ + "BINOUT" + ]["PLANK"] + outstep_phcarb = model[(operation, "GENERAL", segment)][ + "BINOUT" + ]["PHCARB"] if "SAVE" in ui: save_timeseries( @@ -557,7 +557,7 @@ def get_flows( io_manager: SupportsReadTS, ts, flags, - uci, + parameters, segment, ddlinks, ddmasslinks, @@ -598,7 +598,7 @@ def get_flows( else: # this is the kind that needs to be expanded if dat.SGRPN == "ROFLOW" or dat.SGRPN == "OFLOW": - recs = expand_masslinks(flags, uci, dat, recs) + recs = expand_masslinks(flags, parameters, dat, recs) for rec in recs: mfactor = rec["MFACTOR"] diff --git a/src/hsp2/hsp2/mainDoE.py b/src/hsp2/hsp2/mainDoE.py index f00bd97b..4a3f103d 100644 --- a/src/hsp2/hsp2/mainDoE.py +++ b/src/hsp2/hsp2/mainDoE.py @@ -110,8 +110,8 @@ def main(hdfname, doe, doename="DOE_RESULTS", saveall=False): msg(1, f"Processing started for file {hdfname}; saveall={saveall}") # read user control, parameters, states, and flags from HDF5 file - opseq, ddlinks, ddmasslinks, ddext_sources, originaluci, siminfo = get_uci( - store + opseq, ddlinks, ddmasslinks, ddext_sources, originaluci, siminfo = ( + get_parameters(store) ) start, stop = siminfo["start"], siminfo["stop"] @@ -124,7 +124,7 @@ def main(hdfname, doe, doename="DOE_RESULTS", saveall=False): savepath = f"{doename}/RUN{run}" msg(2, f"Starting Run {run}; saving as {savepath}") - uci = deepcopy(originaluci) + parameters = deepcopy(originaluci) for _, operation, segment, delt in opseq.itertuples(): msg(3, f"{operation} {segment} DELT(minutes): {delt}") siminfo["delt"] = delt @@ -133,7 +133,7 @@ def main(hdfname, doe, doename="DOE_RESULTS", saveall=False): # now conditionally execute all activity modules for the op, segment ts = get_timeseries(store, ddext_sources[(operation, segment)], siminfo) - flags = uci[(operation, "GENERAL", segment)]["ACTIVITY"] + flags = parameters[(operation, "GENERAL", segment)]["ACTIVITY"] for activity, function in activities[operation].items(): if function == noop or not flags[activity]: continue @@ -151,7 +151,7 @@ def main(hdfname, doe, doename="DOE_RESULTS", saveall=False): msg, savepath, ) - ui = uci[operation, activity, segment] # ui is a dictionary + ui = parameters[operation, activity, segment] # ui is a dictionary # update deep copy of UCI dict with run dict ruci = rundict[run] @@ -209,9 +209,9 @@ def msg(indent, message, final=False): return msg -def get_uci(store): +def get_parameters(store): # read user control and user data from HDF5 file - uci = defaultdict(dict) + parameters = defaultdict(dict) siminfo = {} for path in store.keys(): # finds ALL data sets into HDF5 file op, module, *other = path[1:].split(sep="/", maxsplit=3) @@ -237,8 +237,8 @@ def get_uci(store): opseq = store[path] elif op in {"PERLND", "IMPLND", "RCHRES"}: for id, vdict in store[path].to_dict("index").items(): - uci[(op, module, id)][s] = vdict - return opseq, ddlinks, ddmasslinks, ddext_sources, uci, siminfo + parameters[(op, module, id)][s] = vdict + return opseq, ddlinks, ddmasslinks, ddext_sources, parameters, siminfo def make_runlist(store, doe, doename): diff --git a/src/hsp2/hsp2/model.py b/src/hsp2/hsp2/model.py new file mode 100644 index 00000000..6bb788fc --- /dev/null +++ b/src/hsp2/hsp2/model.py @@ -0,0 +1,17 @@ +from collections import defaultdict + +from pandas import DataFrame + + +class Model: + def __init__(self) -> None: + self.model = defaultdict(dict) + self.ddlinks = defaultdict(list) + self.ddmasslinks = defaultdict(list) + self.ddext_sources = defaultdict(list) + self.ddgener = defaultdict(dict) + self.siminfo = {} + self.opseq = DataFrame() + self.ftables = {} + self.specactions = {} + self.monthdata = None diff --git a/src/hsp2/hsp2/sedtrn_step.py b/src/hsp2/hsp2/sedtrn_step.py index 69bdb86b..0f9c6441 100644 --- a/src/hsp2/hsp2/sedtrn_step.py +++ b/src/hsp2/hsp2/sedtrn_step.py @@ -1,17 +1,11 @@ -from numpy import array, zeros, where, int64, asarray -from math import log10, exp -from numba import njit, types -from numba.types import List +from numba import njit # the following imports added to handle special actions from hsp2.hsp2.state import ( - sedtrn_get_ix, - sedtrn_init_ix, get_domain_state, set_domain_state, ) -from hsp2.hsp2.om import pre_step_model, step_model, model_domain_dependencies -from numba.typed import Dict +from hsp2.hsp2.om import pre_step_model, step_model @njit diff --git a/src/hsp2/hsp2/state.py b/src/hsp2/hsp2/state.py index 779d7dc1..d172a5b6 100644 --- a/src/hsp2/hsp2/state.py +++ b/src/hsp2/hsp2/state.py @@ -139,9 +139,9 @@ def state_context_hsp2(state, operation, segment, activity): state["domain"] = seg_path # + "/" + activity # may want to comment out activity? -def state_siminfo_hsp2(uci_obj, siminfo, io_manager, state): +def state_siminfo_hsp2(parameter_obj, siminfo, io_manager, state): # Add crucial simulation info for dynamic operation support - delt = uci_obj.opseq.INDELT_minutes[0] # get initial value for STATE objects + delt = parameter_obj.opseq.INDELT_minutes[0] # get initial value for STATE objects siminfo["delt"] = delt siminfo["tindex"] = date_range( siminfo["start"], siminfo["stop"], freq=Minute(delt) @@ -294,7 +294,19 @@ def sedmnt_init_ix(state, domain): def rqual_state_vars(): - rqual_state = ["DOX","BOD","NO3","TAM","NO2","PO4","BRTAM1","BRTAM2","BRPO41","BRPO42","CFOREA"] + rqual_state = [ + "DOX", + "BOD", + "NO3", + "TAM", + "NO2", + "PO4", + "BRTAM1", + "BRTAM2", + "BRPO41", + "BRPO42", + "CFOREA", + ] return rqual_state @@ -362,7 +374,19 @@ def sedmnt_get_ix(state_ix, state_paths, domain): @njit def rqual_get_ix(state_ix, state_paths, domain): # get a list of keys for all sedmnt state variables - rqual_state = ["DOX","BOD","NO3","TAM","NO2","PO4","BRTAM1","BRTAM2","BRPO41","BRPO42","CFOREA"] + rqual_state = [ + "DOX", + "BOD", + "NO3", + "TAM", + "NO2", + "PO4", + "BRTAM1", + "BRTAM2", + "BRPO41", + "BRPO42", + "CFOREA", + ] rqual_ix = Dict.empty(key_type=types.unicode_type, value_type=types.int64) for i in rqual_state: var_path = domain + "/" + i diff --git a/src/hsp2/hsp2/uci.py b/src/hsp2/hsp2/uci.py index 6c0b15c7..5b323b84 100644 --- a/src/hsp2/hsp2/uci.py +++ b/src/hsp2/hsp2/uci.py @@ -1,17 +1,19 @@ from collections import defaultdict +import warnings -from pandas import DataFrame +from .model import Model -class UCI: +class UCI(Model): def __init__(self) -> None: + warnings.warn( + """ +* +* UCI class is deprecated, use Model class in hsp2.model instead. +* The UCI class will be deleted sometime in the future. +* +""", + DeprecationWarning, + ) + super().__init__() self.uci = defaultdict(dict) - self.ddlinks = defaultdict(list) - self.ddmasslinks = defaultdict(list) - self.ddext_sources = defaultdict(list) - self.ddgener = defaultdict(dict) - self.siminfo = {} - self.opseq = DataFrame() - self.ftables = {} - self.specactions = {} - self.monthdata = None diff --git a/src/hsp2/hsp2/utilities.py b/src/hsp2/hsp2/utilities.py index 7ff1e3e3..4cd17dd2 100644 --- a/src/hsp2/hsp2/utilities.py +++ b/src/hsp2/hsp2/utilities.py @@ -181,25 +181,24 @@ ).to_numpy() -def make_numba_dict(uci): +def make_numba_dict(parameters): """ - Move UCI dictionary data to Numba dict for FLAGS, STATES, PARAMETERS. + Move dictionary data to Numba dict for FLAGS, STATES, PARAMETERS. Parameters ---------- - uci : Python dictionary - The uci dictionary contains xxxx.uci file data + parameters : Python dictionary + The dictionary contains the model parameters. Returns ------- ui : Numba dictionary - Same content as uci except for strings - + Same content as parameters except for strings """ ui = Dict.empty(key_type=types.unicode_type, value_type=types.float64) - for name in set(uci.keys()) & {"FLAGS", "PARAMETERS", "STATES"}: - for key, value in uci[name].items(): + for name in set(parameters.keys()) & {"FLAGS", "PARAMETERS", "STATES"}: + for key, value in parameters[name].items(): if type(value) in {int, float}: ui[key] = float(value) return ui @@ -258,15 +257,15 @@ def transform(ts, name, how, siminfo): elif how == "DIV": if "Y" in str(tsfreq) or "M" in str(tsfreq): mult = 1 - firstchar = str(tsfreq)[1:str(tsfreq).index(" ")] + firstchar = str(tsfreq)[1 : str(tsfreq).index(" ")] try: mult = int(firstchar) # like '<3 * MonthBegins>' except ValueError: pass if "M" in str(tsfreq): - ratio = 1.0 / (730.5*mult) # avg hrs in month + ratio = 1.0 / (730.5 * mult) # avg hrs in month elif "Y" in str(tsfreq): - ratio = 1.0 / (8766.0*mult) + ratio = 1.0 / (8766.0 * mult) else: ratio = freq / tsfreq ts = (ratio * ts).resample(freq).ffill() # HSP2 how = div diff --git a/src/hsp2/hsp2io/__init__.py b/src/hsp2/hsp2io/__init__.py index 8494fc4e..23dbedf1 100644 --- a/src/hsp2/hsp2io/__init__.py +++ b/src/hsp2/hsp2io/__init__.py @@ -1,6 +1,6 @@ -"""The `hsp2io` module contains an abstracted approach to getting data in and - out of HSP2 for flexibility and performance and also to support future - automation and model coupling. +"""The `hsp2io` module contains an abstracted approach to getting data in and +out of HSP2 for flexibility and performance and also to support future +automation and model coupling. """ -from hsp2 import __version__ +from .. import __version__ diff --git a/src/hsp2/hsp2io/hdf.py b/src/hsp2/hsp2io/hdf.py index 14ae058b..201552ee 100644 --- a/src/hsp2/hsp2io/hdf.py +++ b/src/hsp2/hsp2io/hdf.py @@ -1,8 +1,9 @@ from typing import Any, Union +import warnings import pandas as pd -from hsp2.hsp2.uci import UCI +from hsp2.hsp2.model import Model from hsp2.hsp2io.protocols import Category @@ -21,45 +22,56 @@ def __enter__(self): def __exit__(self, exc_type, exc_value, trace): self.__del__() - def read_uci(self) -> UCI: - """Read UCI related tables - - Parameters: None - - Returns: UCITuple + def read_uci(self) -> Model: + """ + DEPRECATED: use read_parameters instead + """ + warnings.warn( + """ +* +* DEPRECATED: use read_parameters instead +* read_uci will be removed in future releases +* +""", + DeprecationWarning, + ) + return self.read_parameters() + def read_parameters(self) -> Model: + """ + Read parameter tables from HDF5 and populate Model instance. """ - uci = UCI() + model = Model() for path in self._store.keys(): # finds ALL data sets into HDF5 file op, module, *other = path[1:].split(sep="/", maxsplit=3) s = "_".join(other) if op == "CONTROL": if module == "GLOBAL": temp = self._store[path].to_dict()["Info"] - uci.siminfo["start"] = pd.Timestamp(temp["Start"]) - uci.siminfo["stop"] = pd.Timestamp(temp["Stop"]) - uci.siminfo["units"] = 1 + model.siminfo["start"] = pd.Timestamp(temp["Start"]) + model.siminfo["stop"] = pd.Timestamp(temp["Stop"]) + model.siminfo["units"] = 1 if "Units" in temp: if int(temp["Units"]): - uci.siminfo["units"] = int(temp["Units"]) + model.siminfo["units"] = int(temp["Units"]) elif module == "LINKS": for row in self._store[path].fillna("").itertuples(): if row.TVOLNO != "": - uci.ddlinks[f"{row.TVOLNO}"].append(row) + model.ddlinks[f"{row.TVOLNO}"].append(row) else: - uci.ddlinks[f"{row.TOPFST}"].append(row) + model.ddlinks[f"{row.TOPFST}"].append(row) elif module == "MASS_LINKS": for row in self._store[path].replace("na", "").itertuples(): - uci.ddmasslinks[row.MLNO].append(row) + model.ddmasslinks[row.MLNO].append(row) elif module == "EXT_SOURCES": for row in self._store[path].replace("na", "").itertuples(): - uci.ddext_sources[(row.TVOL, row.TVOLNO)].append(row) + model.ddext_sources[(row.TVOL, row.TVOLNO)].append(row) elif module == "OP_SEQUENCE": - uci.opseq = self._store[path] + model.opseq = self._store[path] elif op in {"PERLND", "IMPLND", "RCHRES"}: for id, vdict in self._store[path].to_dict("index").items(): - uci.uci[(op, module, id)][s] = vdict + model.model[(op, module, id)][s] = vdict elif op == "GENER": for row in self._store[path].itertuples(): if len(row.OPNID.split()) == 1: @@ -69,19 +81,19 @@ def read_uci(self) -> UCI: start, stop = row.OPNID.split() for i in range(int(start), int(stop) + 1): if module != "COEFFS": - uci.ddgener[module][f"G{i:03d}"] = row[2] + model.ddgener[module][f"G{i:03d}"] = row[2] else: for it in range(1, 8): - uci.ddgener[f"K{it:01d}"][f"G{i:03d}"] = row[it+1] + model.ddgener[f"K{it:01d}"][f"G{i:03d}"] = row[it + 1] elif op == "FTABLES": - uci.ftables[module] = self._store[path] + model.ftables[module] = self._store[path] elif op == "SPEC_ACTIONS": - uci.specactions[module] = self._store[path] + model.specactions[module] = self._store[path] elif op == "MONTHDATA": - if not uci.monthdata: - uci.monthdata = {} - uci.monthdata[f"{op}/{module}"] = self._store[path] - return uci + if not model.monthdata: + model.monthdata = {} + model.monthdata[f"{op}/{module}"] = self._store[path] + return model def read_ts( self, diff --git a/src/hsp2/hsp2io/io.py b/src/hsp2/hsp2io/io.py index 5290a3d6..7a8e14f0 100644 --- a/src/hsp2/hsp2io/io.py +++ b/src/hsp2/hsp2io/io.py @@ -2,12 +2,12 @@ import pandas as pd -from hsp2.hsp2.uci import UCI +from hsp2.hsp2.model import Model from hsp2.hsp2.utilities import pandas_offset_by_version from hsp2.hsp2io.protocols import ( Category, SupportsReadTS, - SupportsReadUCI, + SupportsReadParameters, SupportsWriteLogging, SupportsWriteTS, ) @@ -19,41 +19,45 @@ class IOManager: def __init__( self, io_combined: Union[ - SupportsReadUCI, SupportsReadTS, SupportsWriteTS, None + SupportsReadParameters, SupportsReadTS, SupportsWriteTS, None ] = None, - uci: Union[SupportsReadUCI, None] = None, + parameters: Union[SupportsReadParameters, None] = None, input: Union[SupportsReadTS, None] = None, output: Union[SupportsReadTS, SupportsWriteTS, None] = None, log: Union[SupportsWriteLogging, None] = None, ) -> None: - """io_combined: SupportsReadUCI & SupportsReadTS & SupportsWriteTS & SupportsWriteLogging / None - Intended to allow users with a object that combines protocols for - UCI, Input, Output and Log a shortcut where only a - single argument needs to be provided. If UCI, Input, Output and/or - Log are not specified this argument will be used as the default. - uci: SupportsReadUCI/None (Default None) - A class instance implementing the SupportReadUCI protocol. - This class acts as the data source for UCI information. - The argument io_combined be used in place by default if this argument is not specified. - input: SupportsReadUCI/None (Default None) - A class instance implementing SupportReadTS protocol. - This class acts as the data source for any input timeseries. - The argument io_combined be used in place by default if this argument is not specified. - output: SupportsWriteTS & SupportsReadTS / None (Default None) - A class implementing SupportsWriteTS & SupportReadTS protocol - This class acts as the location for outputing result timeseries as - well as the data source should those result timeseries be needed for - inputs into a model modules. - The argument io_combined be used in place by default if this argument is not specified. - log: SupportsWriteLogging/None (Default None) - A class implementing SupportWriteLogging protocol. This class - This class acts as the location to output logging information. - The argument io_combined be used in place by default if this argument is not specified. + """ + Initialize the IOManager for HSP2 model IO operations. + + Parameters + ---------- + io_combined : SupportsReadParameters or SupportsReadTS or SupportsWriteTS or None, optional + Object that combines protocols for Parameters, Input, Output, and + Log. If `parameters`, `input`, `output`, or `log` are not + specified, this argument will be used as the default for those. + parameters : SupportsReadParameters or None, optional + Instance implementing the SupportReadParameters protocol. Acts as + the data source for parameter information. If not specified, + `io_combined` will be used by default. + input : SupportsReadTS or None, optional + Instance implementing the SupportReadTS protocol. Acts as the data + source for any input timeseries. If not specified, `io_combined` + will be used by default. + output : SupportsWriteTS or SupportsReadTS or None, optional + Instance implementing the SupportsWriteTS and/or SupportReadTS + protocol. Acts as the location for outputting result timeseries and + as the data source for result timeseries needed as inputs to model + modules. + If not specified, `io_combined` will be used by default. + log : SupportsWriteLogging or None, optional + Instance implementing the SupportWriteLogging protocol. Acts as the + location to output logging information. If not specified, + `io_combined` will be used by default. """ self._input = io_combined if input is None else input self._output = io_combined if output is None else output - self._uci = io_combined if uci is None else uci + self._parameters = io_combined if parameters is None else parameters self._log = io_combined if log is None else log self._in_memory = {} @@ -61,11 +65,11 @@ def __init__( def __del__(self): del self._input del self._output - del self._uci + del self._parameters del self._log - def read_uci(self, *args, **kwargs) -> UCI: - return self._uci.read_uci() + def read_parameters(self, *args, **kwargs) -> Model: + return self._parameters.read_parameters() def write_ts( self, diff --git a/src/hsp2/hsp2io/protocols.py b/src/hsp2/hsp2io/protocols.py index b64d74d5..acc74654 100644 --- a/src/hsp2/hsp2io/protocols.py +++ b/src/hsp2/hsp2io/protocols.py @@ -1,11 +1,10 @@ -from collections import defaultdict from enum import Enum -from typing import Any, Dict, List, Protocol, Union, runtime_checkable +from typing import Dict, Protocol, Union, runtime_checkable import numpy as np import pandas as pd -from hsp2.hsp2.uci import UCI +from hsp2.hsp2.model import Model TimeSeriesDict = Dict[str, np.float64] @@ -16,8 +15,8 @@ class Category(Enum): @runtime_checkable -class SupportsReadUCI(Protocol): - def read_uci(self) -> UCI: ... +class SupportsReadParameters(Protocol): + def read_parameters(self) -> Model: ... @runtime_checkable diff --git a/src/hsp2/hsp2tools/__init__.py b/src/hsp2/hsp2tools/__init__.py index 6dc4d429..78e1f6e4 100644 --- a/src/hsp2/hsp2tools/__init__.py +++ b/src/hsp2/hsp2tools/__init__.py @@ -1,6 +1,6 @@ """The `hsp2tools` module contains supporting software modules such as the code - to convert legacy WDM and UCI files to HDF5 files for HSP2, and to provide - additional new and legacy capabilities. +to convert legacy WDM and UCI files to HDF5 files for HSP2, and to provide +additional new and legacy capabilities. """ from .clone import clone, removeClone diff --git a/src/hsp2/hsp2tools/fetch.py b/src/hsp2/hsp2tools/fetch.py index 9e2c8c57..addd44f5 100644 --- a/src/hsp2/hsp2tools/fetch.py +++ b/src/hsp2/hsp2tools/fetch.py @@ -54,7 +54,7 @@ def fetchtable(hdfname, path, names=[], usercol=None, usercolvalue=None, CSV=Fal df = df.to_csv() def replace(dff): - nonlocal dforiginal + nonlocal dforiginal # noqa F824 if CSV: dff = read_csv(StringIO(dff), index_col=0) print(dff) diff --git a/src/hsp2/hsp2tools/readUCI.py b/src/hsp2/hsp2tools/readUCI.py index d194b264..8299cb1f 100644 --- a/src/hsp2/hsp2tools/readUCI.py +++ b/src/hsp2/hsp2tools/readUCI.py @@ -1019,9 +1019,9 @@ def monthdata(info, llines): try: vals.append(float(line[:6])) except: - if '-' in line[:6]: + if "-" in line[:6]: # assume this exception was caused by the E missing, as is allowed in HSPF negpos = line[:6].index("-") - vals.append(float(line[:negpos] + 'E' + line[negpos:6])) + vals.append(float(line[:negpos] + "E" + line[negpos:6])) line = line[6:] lst.append(vals)