Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Develop specact 1 #128

Merged
merged 8 commits into from
Jan 3, 2024
45 changes: 35 additions & 10 deletions HSP2/HYDR.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,14 @@
from HSP2.utilities import initm, make_numba_dict
from HSP2.state import *
from HSP2.SPECL import specl
from HSP2.om import *
from HSP2.om_model_object import *
from HSP2.om_sim_timer import *
from HSP2.om_special_action import *
#from HSP2.om_equation import *
from HSP2.om_model_linkage import *
#from HSP2.om_data_matrix import *
#from HSP2.om_model_broadcast import *


ERRMSGS =('HYDR: SOLVE equations are indeterminate', #ERRMSG0
Expand Down Expand Up @@ -123,10 +131,10 @@ def hydr(io_manager, siminfo, uci, ts, ftables, state):
Olabels.append(f'O{i+1}')
OVOLlabels.append(f'OVOL{i+1}')

# state_info is some generic things about the simulation
# state_info is some generic things about the simulation - must be numba safe, so we don't just pass the whole state which is not
state_info = Dict.empty(key_type=types.unicode_type, value_type=types.unicode_type)
state_info['operation'], state_info['segment'], state_info['activity'] = state['operation'], state['segment'], state['activity']
state_info['domain'], state_info['state_step_hydr'] = state['domain'], state['state_step_hydr']
state_info['domain'], state_info['state_step_hydr'], state_info['state_step_om'] = state['domain'], state['state_step_hydr'], state['state_step_om']
hsp2_local_py = state['hsp2_local_py']
# It appears necessary to load this here, instead of from main.py, otherwise,
# _hydr_() does not recognize the function state_step_hydr()?
Expand All @@ -140,15 +148,16 @@ def hydr(io_manager, siminfo, uci, ts, ftables, state):
# initialize the hydr paths in case they don't already reside here
hydr_init_ix(state_ix, state_paths, state['domain'])


###########################################################################
# specactions - special actions code TBD
# OM - load the tokens to pass in.
###########################################################################
specactions = make_numba_dict(state['specactions']) # Note: all values coverted to float automatically
op_tokens = state['op_tokens']

###########################################################################
# Do the simulation with _hydr_()
###########################################################################
errors = _hydr_(ui, ts, COLIND, OUTDGT, rchtab, funct, Olabels, OVOLlabels, state_info, state_paths, state_ix, dict_ix, ts_ix, specactions, state_step_hydr) # run reaches simulation code
errors = _hydr_(ui, ts, COLIND, OUTDGT, rchtab, funct, Olabels, OVOLlabels, state_info, state_paths, state_ix, dict_ix, ts_ix, state_step_hydr, op_tokens) # run reaches simulation code
###########################################################################

if 'O' in ts: del ts['O']
Expand All @@ -163,7 +172,7 @@ def hydr(io_manager, siminfo, uci, ts, ftables, state):


@njit(cache=True)
def _hydr_(ui, ts, COLIND, OUTDGT, rowsFT, funct, Olabels, OVOLlabels, state_info, state_paths, state_ix, dict_ix, ts_ix, specactions, state_step_hydr):
def _hydr_(ui, ts, COLIND, OUTDGT, rowsFT, funct, Olabels, OVOLlabels, state_info, state_paths, state_ix, dict_ix, ts_ix, state_step_hydr, op_tokens):
errors = zeros(int(ui['errlen'])).astype(int64)

steps = int(ui['steps']) # number of simulation steps
Expand Down Expand Up @@ -309,7 +318,6 @@ def _hydr_(ui, ts, COLIND, OUTDGT, rowsFT, funct, Olabels, OVOLlabels, state_inf
# HYDR (except where noted)
for step in range(steps):
# call specl
specl(ui, ts, step, state_info, state_paths, state_ix, specactions)
convf = CONVF[step]
outdgt[:] = OUTDGT[step, :]
colind[:] = COLIND[step, :]
Expand All @@ -323,17 +331,34 @@ def _hydr_(ui, ts, COLIND, OUTDGT, rowsFT, funct, Olabels, OVOLlabels, state_inf
state_ix[out_ix[oi]] = outdgt[oi]
state_ix[vol_ix], state_ix[ivol_ix] = vol, IVOL0[step]
state_ix[volev_ix] = volev
# *****************************************
# Execute dynamic code if enabled
# - these if statements may be irrelevant if default functions simply return
# when no objects are defined.
if (state_info['state_step_om'] == 'enabled'):
pre_step_model(op_tokens[0], op_tokens, state_ix, dict_ix, ts_ix, step)
if (state_info['state_step_hydr'] == 'enabled'):
state_step_hydr(state_info, state_paths, state_ix, dict_ix, ts_ix, hydr_ix, step)
# Execute dynamic code if enabled
if (state_info['state_step_om'] == 'enabled'):
#print("trying to execute state_step_om()")
# op_tokens[0] contains the model exec list. Later we may amend this
# perhaps even storing a domain specific exec list under domain/exec_list?
step_model(op_tokens[0], op_tokens, state_ix, dict_ix, ts_ix, step)
# Execute dynamic code if enabled
if ( (state_info['state_step_hydr'] == 'enabled')
or (state_info['state_step_om'] == 'enabled')
):
# Do write-backs for editable STATE variables
# OUTDGT is writeable
for oi in range(nexits):
outdgt[oi] = state_ix[out_ix[oi]]
# IVOL is writeable.
# Note: we must convert IVOL to the units expected in _hydr_
# IVOL is writeable.
# Note: we must convert IVOL to the units expected in _hydr_
# maybe routines should do this, and this is not needed (but pass VFACT in state)
IVOL[step] = state_ix[ivol_ix] * VFACT
# End dynamic code step()
# *****************************************
# vols, sas variables and their initializations not needed.
if irexit >= 0: # irrigation exit is set, zero based number
if rirwdl > 0.0: # equivalent to OVOL for the irrigation exit
Expand Down
47 changes: 44 additions & 3 deletions HSP2/SPECL.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,49 @@
''' process special actions in this domain
Notes:
- code for parsing UCI SPEC-ACTIONS is in HSP2tools/readUCI.py
- code for object classes that transform parsed data into OP codes for OM and STATE support
is in this directory tree as om_special_[action type].py,
- Ex: om_special_action.py contains object support and runtime functions for classic ACTIONS
'''

from numba import njit
from pandas import DataFrame, date_range
import h5py

def specl_load_actions(state, io_manager, siminfo):
dc = state['specactions']['ACTIONS']
#print(dc.index)
#print("speca entry 0:0", dc[0:0])
#print("speca entry 0:1", dc[0:1])
#print("speca entry 1:2", dc[1:2])
#print("speca entry 0:", dc[0:])
#print("speca entry 1:", dc[1:])
#print("speca entry 1:1", dc[1:1])
for ix in dc.index:
# add the items to the state['model_data'] dict
speca = dc[ix:(ix+1)]
# need to add a name attribute
opname = 'SPEC' + 'ACTION' + str(ix)
state['model_data'][opname] = {}
state['model_data'][opname]['name'] = opname
for ik in speca.keys():
#print("looking for speca key ", ik)
state['model_data'][opname][ik] = speca.to_dict()[ik][ix]
state['model_data'][opname]['object_class'] = 'SpecialAction'
#print("model_data", ix, " = ", state['model_data'][opname])
return

CALL: specl(io_manager, siminfo, uci, ts, state, specl_actions)
def state_load_dynamics_specl(state, io_manager, siminfo):
specl_load_actions(state, io_manager, siminfo)
# others defined below, like:
# specl_load_uvnames(state, io_manager, siminfo)
# ...
return

'''
# the code specl() is deprecated in favor of execution inside OM
# see om_special_action.py for example of object support and runtime functions for classic ACTIONS
CALL: specl(ui, ts, step, state_info, state_paths, state_ix, specactions)
store is the Pandas/PyTable open store
siminfo is a dictionary with simulation level infor (OP_SEQUENCE for example)
ui is a dictionary with RID specific HSPF UCI like data
Expand All @@ -9,8 +52,6 @@
specl_actions is a dictionary with all SPEC-ACTIONS entries
'''

from numba import njit

@njit
def specl(ui, ts, step, state_info, state_paths, state_ix, specactions):
# ther eis no need for _specl_ because this code must already be njit
Expand Down
6 changes: 6 additions & 0 deletions HSP2/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
from HSP2.utilities import versions, get_timeseries, expand_timeseries_names, save_timeseries, get_gener_timeseries
from HSP2.configuration import activities, noop, expand_masslinks
from HSP2.state import *
from HSP2.om import *
from HSP2.SPECL import *

from HSP2IO.io import IOManager, SupportsReadTS, Category

Expand Down Expand Up @@ -75,6 +77,10 @@ def main(io_manager:IOManager, saveall:bool=False, jupyterlab:bool=True) -> None
hydr_init_ix(state['state_ix'], state['state_paths'], state['domain'])
# - finally stash specactions in state, not domain (segment) dependent so do it once
state['specactions'] = specactions # stash the specaction dict in state
state_load_dynamics_specl(state, io_manager, siminfo)
state_load_dynamics_om(state, io_manager, siminfo)
# finalize all dynamically loaded components and prepare to run the model
state_om_model_run_prep(state, io_manager, siminfo)
#######################################################################################
# main processing loop
msg(1, f'Simulation Start: {start}, Stop: {stop}')
Expand Down
Loading