# coding: utf-8 #

Basic test of the wflow BMI interface + reservoir # In[10]: import numpy import os import os.path import shutil, glob import getopt import sys import getopt from wflow.wf_DynamicFramework import * import wflow.wflow_bmi as bmi import logging import wflow.wflow_adapt as adapter import datetime, calendar import os import numpy as np import ConfigParser #reload(bmi) ''' Todo: include error handling: - When WFlow_ids in the mapping section of config are not in the map - When RTC doesn't have data on the WFlow simulation period - When a RTC id in the id mapping section is not part of the model - ... Todo: add logging ''' def ConfigSectionMap(section): dict1 = {} options = Config.options(section) for option in options: try: dict1[option] = Config.get(section, option) if dict1[option] == -1: DebugPrint("skip: %s" % option) except: print("exception on %s!" % option) dict1[option] = None return dict1 def gettimestepfname(name,path,timestep): """ Get the pcraster filename fro this step :param name: :param path: :param timestep: :return: """ below_thousand = timestep % 1000 above_thousand = timestep / 1000 fname = str(name + '%0' + str(8-len(name)) + '.f.%03.f') % (above_thousand, below_thousand) fname = os.path.join(path,fname) return fname ######################################################################## ## Process command-line options # ######################################################################## argv = sys.argv try: opts, args = getopt.getopt(argv[1:], 'c:w:I:') print opts except getopt.error, msg: print 'cannot parse commandline' sys.exit for o, a in opts: if o == '-c': configfile = a if o == '-w' : cur_dir = os.path.abspath(a) if o == '-I' : IniFile = a Config = ConfigParser.ConfigParser() #inifile = Config.read('c:\FEWS\SI-WAMI\SI-WAMI\Modules\RTC\wflow_rtctools.ini') inifile = Config.read(configfile) ######################################################################## ## Parse ini-file # ######################################################################## #cur_dir = os.getcwd() Config.sections() os.chdir(cur_dir) dir_rtc = os.path.join(cur_dir,(ConfigSectionMap("model")['dir_rtc_model'])) dir_wflow = os.path.join(cur_dir,(ConfigSectionMap("model")['dir_wflow_model'])) Bin_RTC = os.path.join(cur_dir,(ConfigSectionMap("RTC wrapper engine")['bin_rtc'])) inflow_map=os.path.join(dir_wflow,(ConfigSectionMap("id_maps")['samplemap_in'])) outflow_map=os.path.join(dir_wflow,(ConfigSectionMap("id_maps")['samplemap_out'])) ldd_map=os.path.join(dir_wflow,(ConfigSectionMap("ldd")['ldd_res'])) # id's wflow and RTC reservoir inflow points id_in_rtc=[] id_in_wflow=list(ConfigSectionMap("id_mapping_inflow")) for index in range(len(id_in_wflow)): id_in_rtc.append(ConfigSectionMap("id_mapping_inflow")[id_in_wflow[index]]) # id's wflow and RTC reservoir outflow points id_out_rtc=[] id_out_wflow=list(ConfigSectionMap("id_mapping_outflow")) for index in range(len(id_out_wflow)): id_out_rtc.append(ConfigSectionMap("id_mapping_outflow")[id_out_wflow[index]]) ######################################################################## ## Initialize models # ######################################################################## # In[]: Initialize the RTC-Tools model os.chdir(Bin_RTC) from wflow.wrappers.rtc.wrapperExtended import BMIWrapperExtended #RTC_model = BMIWrapperExtended(engine=os.path.join(Bin_RTC,"RTCTools_BMI")) RTC_model = BMIWrapperExtended(engine=os.path.join(Bin_RTC,"RTCTools_BMI")) print 'RTCmodel', Bin_RTC,RTC_model RTC_model.initialize('..') # In[]: Initialize the WFlow model os.chdir(dir_wflow) LA_model = bmi.wflowbmi_csdms() LA_model.initialize((IniFile), loglevel=logging.WARN) # now get the forcings that wflow expects # The bmi is such that you can get the input variables and the output variables. However, the # input variable list also contains the in/out variables. So to # get the input only we subtract the two lists. invars = LA_model.get_input_var_names() outvars = LA_model.get_output_var_names() inputmstacks = list(set(invars) - set(outvars)) # In[]: Investigate start time, end time and time step of both models print 'WFlow:' LA_dt = LA_model.get_time_step() #LA_start = LA_model.get_start_time() timeutc = adapter.getStartTimefromRuninfo('inmaps/runinfo.xml') print timeutc LA_start = calendar.timegm(timeutc.timetuple()) timeutc = adapter.getEndTimefromRuninfo('inmaps/runinfo.xml') LA_end = calendar.timegm(timeutc.timetuple()) #LA_end = LA_model.get_end_time() print LA_dt print timeutc print LA_start print LA_end print 'RTC-Tools' RTC_dt = RTC_model.get_time_step() RTC_start = RTC_model.get_start_time() RTC_end = RTC_model.get_end_time() print RTC_dt print RTC_start print RTC_end if LA_start != RTC_start: print 'Error: start time of both model is not identical !!!' if LA_dt != RTC_dt: print 'Error: time step of both models is not identical !!!' # In[]: Read and map reservoir inflow and outflow locations Reservoir_inflow = pcr2numpy(scalar(pcraster.readmap(os.path.abspath(inflow_map))),np.NaN) Reservoir_outflow = pcr2numpy(scalar(pcraster.readmap(os.path.abspath(outflow_map))),np.NaN) inflow_list = list(np.unique(Reservoir_inflow[~np.isnan(Reservoir_inflow)])) outflow_list = list(np.unique(Reservoir_outflow[~np.isnan(Reservoir_outflow)])) # In[]: Overwrite TopoLdd with modified version ldd = pcraster.pcr2numpy(pcraster.readmap(os.path.join(dir_wflow,ldd_map)), np.NaN).astype(np.float32) LA_model.set_value("TopoLdd",flipud(ldd).copy()) ######################################################################## ## Run models # ######################################################################## t = LA_start timecounter = 0 while t < min(LA_end, RTC_end): #print "timestep = " + str(t) # run the WFlow model # first read forcing mapstacks (set in API section) and give to the model for thisstack in inputmstacks: toread = gettimestepfname(thisstack,os.path.join(dir_wflow,'inmaps'),timecounter+1) nptoset = flipud(pcr2numpy(scalar(pcraster.readmap(os.path.abspath(toread))),-999.0)).copy() LA_model.set_value(thisstack,nptoset) LA_model.update() print "calculation timestep = " + str(timecounter) # Get the inflow from the wflow model runoff map and map inflowQ = flipud(LA_model.get_value("SurfaceRunoff")).copy() # Map the sum of WFlow Inflow to RTC for idx, wflow_id in enumerate(id_in_wflow): value = np.ndarray(shape=(1,1), dtype=float, order='F') value[0][0] = np.sum(inflowQ[np.where(Reservoir_inflow==int(wflow_id))]) rtc_id = id_in_rtc[id_in_wflow.index(str(wflow_id))] print rtc_id + ' = ' + str(value[0][0]) RTC_model.set_value(rtc_id, value) # run the RTC-Tools model RTC_model.update(-1.0) # Extract RTC outflow and supply on WFlow 'inflowfield' inflowfield = zeros_like(inflowQ).copy() for idx, wflow_id in enumerate(id_out_wflow): rtc_id = id_out_rtc[id_out_wflow.index(str(wflow_id))] Qout = RTC_model.get_var(rtc_id) if isfinite(Qout): # no nan's into wflow inflowfield[Reservoir_outflow==int(wflow_id)] = Qout LA_model.set_value("IF",flipud(inflowfield).copy()) # This not not bmi but needed to update the kinematic wave reservoir LA_model.myModel.updateRunOff() #t = LA_model.get_current_time() t += LA_dt timecounter += 1 # In[]: Finalize.... LA_model.finalize() RTC_model.finalize()