def RunModel(ConceptualModel, Paths, ParPath, p2, init_st, snow): """ ======================================================================= RunModel(PrecPath, Evap_Path, TempPath, DemPath, FlowAccPath, FlowDPath, ParPath, p2) ======================================================================= this function runs the conceptual distributed hydrological model Inputs: 1-Paths: 1-PrecPath: [String] path to the Folder contains precipitation rasters 2-Evap_Path: [String] path to the Folder contains Evapotranspiration rasters 3-TempPath: [String] path to the Folder contains Temperature rasters 4-FlowAccPath: [String] path to the Flow Accumulation raster of the catchment (it should include the raster name and extension) 5-FlowDPath: [String] path to the Flow Direction raster of the catchment (it should include the raster name and extension) 7-ParPath: [String] path to the Folder contains parameters rasters of the catchment 8-p2: [List] list of unoptimized parameters p2[0] = tfac, 1 for hourly, 0.25 for 15 min time step and 24 for daily time step p2[1] = catchment area in km2 Outputs: 1- st: [4D array] state variables 2- q_out: [1D array] calculated Discharge at the outlet of the catchment 3- q_uz: [3D array] Distributed discharge for each cell Example: PrecPath = prec_path="meteodata/4000/calib/prec" Evap_Path = evap_path="meteodata/4000/calib/evap" TempPath = temp_path="meteodata/4000/calib/temp" DemPath = "GIS/4000/dem4000.tif" FlowAccPath = "GIS/4000/acc4000.tif" FlowDPath = "GIS/4000/fd4000.tif" ParPath = "meteodata/4000/parameters" p2=[1, 227.31] st, q_out, q_uz_routed = RunModel(PrecPath,Evap_Path,TempPath,DemPath, FlowAccPath,FlowDPath,ParPath,p2) """ # input data validation assert len(Paths) == 5, "Paths should include 5 folder pathes " +str(len(Paths))+" paths are only provided" PrecPath=Paths[0] Evap_Path=Paths[1] TempPath=Paths[2] # DemPath=Paths[3] FlowAccPath=Paths[3] FlowDPath=Paths[4] # data type assert type(PrecPath)== str, "PrecPath input should be string type" assert type(Evap_Path)== str, "Evap_Path input should be string type" assert type(TempPath)== str, "TempPath input should be string type" # assert type(DemPath)== str, "DemPath input should be string type" assert type(FlowAccPath)== str, "FlowAccPath input should be string type" assert type(FlowDPath)== str, "FlowDPath input should be string type" assert type(ParPath)== str, "ParPath input should be string type" # input values # dem_ext=DemPath[-4:] # assert dem_ext == ".tif", "please add the extension at the end of the DEM raster path input" acc_ext=FlowAccPath[-4:] assert acc_ext == ".tif", "please add the extension at the end of the Flow accumulation raster path input" fd_ext=FlowDPath[-4:] assert fd_ext == ".tif", "please add the extension at the end of the Flow Direction path input" # check wether the path exists or not assert os.path.exists(PrecPath), PrecPath + " you have provided does not exist" assert os.path.exists(Evap_Path), Evap_Path+" path you have provided does not exist" assert os.path.exists(TempPath), TempPath+" path you have provided does not exist" # assert os.path.exists(DemPath), DemPath+ " you have provided does not exist" assert os.path.exists(FlowAccPath), FlowAccPath + " you have provided does not exist" assert os.path.exists(FlowDPath), FlowDPath+ " you have provided does not exist" # check wether the folder has the rasters or not assert len(os.listdir(PrecPath)) > 0, PrecPath+" folder you have provided is empty" assert len(os.listdir(Evap_Path)) > 0, Evap_Path+" folder you have provided is empty" assert len(os.listdir(TempPath)) > 0, TempPath+" folder you have provided is empty" # read data ### meteorological data prec=GIS.ReadRastersFolder(PrecPath) evap=GIS.ReadRastersFolder(Evap_Path) temp=GIS.ReadRastersFolder(TempPath) print("meteorological data are read successfully") #### GIS data # dem= gdal.Open(DemPath) acc=gdal.Open(FlowAccPath) fd=gdal.Open(FlowDPath) print("GIS data are read successfully") # parameters parameters=GIS.ReadRastersFolder(ParPath) print("Parameters are read successfully") #run the model st, q_out, q_uz, q_lz = Wrapper.Dist_model(ConceptualModel, acc, fd, prec, evap, temp, parameters, p2, snow, init_st) return st, q_out, q_uz, q_lz
def RunCalibration(ConceptualModel, Paths, Basic_inputs, SpatialVarFun, SpatialVarArgs, OF, OF_args, Q_obs, OptimizationArgs, printError=None): """ ======================================================================= RunCalibration(Paths, p2, Q_obs, UB, LB, SpatialVarFun, lumpedParNo, lumpedParPos, objective_function, printError=None, *args): ======================================================================= this function runs the conceptual distributed hydrological model Inputs: ---------- 1-Paths: 1-PrecPath: [String] path to the Folder contains precipitation rasters 2-Evap_Path: [String] path to the Folder contains Evapotranspiration rasters 3-TempPath: [String] path to the Folder contains Temperature rasters 4-FlowAccPath: [String] path to the Flow Accumulation raster of the catchment (it should include the raster name and extension) 5-FlowDPath: [String] path to the Flow Direction raster of the catchment (it should include the raster name and extension) 2-Basic_inputs: 1-p2: [List] list of unoptimized parameters p2[0] = tfac, 1 for hourly, 0.25 for 15 min time step and 24 for daily time step p2[1] = catchment area in km2 2-init_st: [list] initial values for the state variables [sp,sm,uz,lz,wc] in mm 3-UB: [Numeric] upper bound of the values of the parameters 4-LB: [Numeric] Lower bound of the values of the parameters 3-Q_obs: [Numeric] Observed values of discharge 6-lumpedParNo: [int] nomber of lumped parameters, you have to enter the value of the lumped parameter at the end of the list, default is 0 (no lumped parameters) 7-lumpedParPos: [List] list of order or position of the lumped parameter among all the parameters of the lumped model (order starts from 0 to the length of the model parameters), default is [] (empty), the following order of parameters is used for the lumped HBV model used [ltt, utt, rfcf, sfcf, ttm, cfmax, cwh, cfr, fc, beta, e_corr, etf, lp, c_flux, k, k1, alpha, perc, pcorr, Kmuskingum, Xmuskingum] 8-objective_function: [function] objective function to calculate the performance of the model and to be used in the calibration 9-*args: other arguments needed on the objective function Outputs: ---------- 1- st: [4D array] state variables 2- q_out: [1D array] calculated Discharge at the outlet of the catchment 3- q_uz: [3D array] Distributed discharge for each cell Example: ---------- PrecPath = prec_path="meteodata/4000/calib/prec" Evap_Path = evap_path="meteodata/4000/calib/evap" TempPath = temp_path="meteodata/4000/calib/temp" FlowAccPath = "GIS/4000/acc4000.tif" FlowDPath = "GIS/4000/fd4000.tif" ParPath = "meteodata/4000/"+"parameters.txt" p2=[1, 227.31] st, q_out, q_uz_routed = RunModel(PrecPath,Evap_Path,TempPath,DemPath, FlowAccPath,FlowDPath,ParPath,p2) """ ### inputs validation # data type assert len(Paths) == 5, "Paths should include 5 folder pathes " + str( len(Paths)) + " paths are only provided" PrecPath = Paths[0] Evap_Path = Paths[1] TempPath = Paths[2] # DemPath=Paths[3] FlowAccPath = Paths[3] FlowDPath = Paths[4] assert type(PrecPath) == str, "PrecPath input should be string type" assert type(Evap_Path) == str, "Evap_Path input should be string type" assert type(TempPath) == str, "TempPath input should be string type" # assert type(DemPath)== str, "DemPath input should be string type" assert type(FlowAccPath) == str, "FlowAccPath input should be string type" assert type(FlowDPath) == str, "FlowDPath input should be string type" # input values # dem_ext=DemPath[-4:] # assert dem_ext == ".tif", "please add the extension at the end of the DEM raster path input" acc_ext = FlowAccPath[-4:] assert acc_ext == ".tif", "please add the extension at the end of the Flow accumulation raster path input" fd_ext = FlowDPath[-4:] assert fd_ext == ".tif", "please add the extension at the end of the Flow Direction path input" # check wether the path exists or not assert os.path.exists( PrecPath), PrecPath + " you have provided does not exist" assert os.path.exists( Evap_Path), Evap_Path + " path you have provided does not exist" assert os.path.exists( TempPath), TempPath + " path you have provided does not exist" # assert os.path.exists(DemPath), DemPath+ " you have provided does not exist" assert os.path.exists( FlowAccPath), FlowAccPath + " you have provided does not exist" assert os.path.exists( FlowDPath), FlowDPath + " you have provided does not exist" # check wether the folder has the rasters or not assert len(os.listdir( PrecPath)) > 0, PrecPath + " folder you have provided is empty" assert len(os.listdir( Evap_Path)) > 0, Evap_Path + " folder you have provided is empty" assert len(os.listdir( TempPath)) > 0, TempPath + " folder you have provided is empty" # basic inputs # check if all inputs are included assert all( ["p2", "init_st", "UB", "LB", "snow "][i] in Basic_inputs.keys() for i in range( 4)), "Basic_inputs should contain ['p2','init_st','UB','LB'] " p2 = Basic_inputs['p2'] init_st = Basic_inputs["init_st"] UB = Basic_inputs['UB'] LB = Basic_inputs['LB'] snow = Basic_inputs['snow'] assert len(UB) == len(LB), "length of UB should be the same like LB" # check objective_function assert callable(OF), "second argument should be a function" if OF_args == None: OF_args = [] # read data ### meteorological data prec = GIS.ReadRastersFolder(PrecPath) evap = GIS.ReadRastersFolder(Evap_Path) temp = GIS.ReadRastersFolder(TempPath) print("meteorological data are read successfully") #### GIS data # dem= gdal.Open(DemPath) acc = gdal.Open(FlowAccPath) fd = gdal.Open(FlowDPath) print("GIS data are read successfully") ### optimization # get arguments store_history = OptimizationArgs[0] history_fname = OptimizationArgs[1] # check optimization arguement assert store_history != 0 or store_history != 1, "store_history should be 0 or 1" assert type( history_fname) == str, "history_fname should be of type string " assert history_fname[ -4:] == ".txt", "history_fname should be txt file please change extension or add .txt ad the end of the history_fname" print('Calibration starts') ### calculate the objective function def opt_fun(par): try: # parameters klb = float(par[-2]) kub = float(par[-1]) par = par[:-2] par_dist = SpatialVarFun(par, *SpatialVarArgs, kub=kub, klb=klb) #run the model _, q_out, q_uz_routed, q_lz_trans = Wrapper.Dist_model( ConceptualModel, acc, fd, prec, evap, temp, par_dist, p2, snow, init_st) # calculate performance of the model try: error = OF(Q_obs, q_out, q_uz_routed, q_lz_trans, *OF_args) except TypeError: # if no of inputs less than what the function needs assert 1 == 5, "the objective function you have entered needs more inputs please enter then in a list as *args" # print error if printError != 0: print(error) print(par) fail = 0 except: error = np.nan fail = 1 return error, [], fail ### define the optimization components opt_prob = Optimization('HBV Calibration', opt_fun) for i in range(len(LB)): opt_prob.addVar('x{0}'.format(i), type='c', lower=LB[i], upper=UB[i]) print(opt_prob) opt_engine = ALHSO(etol=0.0001, atol=0.0001, rtol=0.0001, stopiters=10, hmcr=0.5, par=0.5) #,filename='mostafa.out' Optimizer.__init__( opt_engine, def_options={ 'hms': [int, 9], # Memory Size [1,50] 'hmcr': [float, 0.95 ], # Probability rate of choosing from memory [0.7,0.99] 'par': [float, 0.99], # Pitch adjustment rate [0.1,0.99] 'dbw': [int, 2000], # Variable Bandwidth Quantization 'maxoutiter': [int, 2e3 ], # Maximum Number of Outer Loop Iterations (Major Iterations) 'maxinniter': [int, 2e2 ], # Maximum Number of Inner Loop Iterations (Minor Iterations) 'stopcriteria': [int, 1], # Stopping Criteria Flag 'stopiters': [ int, 20 ], # Consecutively Number of Outer Iterations for which the Stopping Criteria must be Satisfied 'etol': [float, 0.0001], # Absolute Tolerance for Equality constraints 'itol': [float, 0.0001], # Absolute Tolerance for Inequality constraints 'atol': [float, 0.0001], # Absolute Tolerance for Objective Function 1e-6 'rtol': [float, 0.0001], # Relative Tolerance for Objective Function 'prtoutiter': [int, 0], # Number of Iterations Before Print Outer Loop Information 'prtinniter': [int, 0], # Number of Iterations Before Print Inner Loop Information 'xinit': [int, 0], # Initial Position Flag (0 - no position, 1 - position given) 'rinit': [float, 1.0], # Initial Penalty Factor 'fileout': [int, store_history], # Flag to Turn On Output to filename 'filename': [ str, 'parameters.txt' ], # We could probably remove fileout flag if filename or fileinstance is given 'seed': [float, 0.5], # Random Number Seed (0 - Auto-Seed based on time clock) 'scaling': [ int, 1 ], # Design Variables Scaling Flag (0 - no scaling, 1 - scaling between [-1,1]) }) res = opt_engine(opt_prob) return res