Skip to content

Commit

Permalink
Merge pull request #128 from HARPgroup/develop-specact-1
Browse files Browse the repository at this point in the history
Develop specact 1
  • Loading branch information
PaulDudaRESPEC authored Jan 3, 2024
2 parents 243b914 + 6f16851 commit bf62e28
Show file tree
Hide file tree
Showing 10 changed files with 1,304 additions and 14 deletions.
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

0 comments on commit bf62e28

Please sign in to comment.