def simulation_drainage(year, weatherforecast_kind, weatherforecast_accumulationtime, weatherforecast_updatesteps, penetration_rate, control_type, number_simulation, original_swmm_file, irrigation_start, irrigation_end, classification): startTime = dt.datetime.now() if control_type == 'smart': smart = True elif control_type == 'uncontrolled': smart = False else: print('usage control type: "uncontrolled" or "smart"') sys.exit(1) #input variable runoff coefficient runoff_coefficient = 0.95 #input variable max garden area max_garden = 25 #created variables analysetime = pd.to_datetime('{}.{}.{}'.format(irrigation_start[1], irrigation_start[0], year), format='%d.%m.%Y') endtime = pd.to_datetime('{}.{}.{}'.format(irrigation_end[1], irrigation_end[0], year), format='%d.%m.%Y') #created file names name = original_swmm_file[:-4] + '_{}_{}_{}_{}_{}_{}'.format( year, weatherforecast_kind, weatherforecast_accumulationtime, penetration_rate, control_type, number_simulation) swmm_file = name + '.inp' json_file = name + '.json' #create swmm input file f = open(original_swmm_file) #read in success, val = read_write_swmm.swmm_input_read(f) if not success: print(val) sys.exit(1) houses_implementation_RBs, val, rain_barrel_total_volume = implement_LIDs.implementation( val, penetration_rate, max_garden, '_H_', classification) #implementation of SRBs val = modify_swmm_input.change_parameters(val, analysetime, endtime, 'rain{}.dat'.format(year)) #print((houses_implementation_RBs)) f = open(swmm_file, 'w') read_write_swmm.swmm_input_write(f, val) f.close() #set initial values - needed for simulation newday = analysetime irrigation_time = analysetime + pd.Timedelta(seconds=84600) ct_old = analysetime - pd.Timedelta(seconds=60) irrigation = False number_rain_barrels = len(houses_implementation_RBs) houses_lid_parameters = {} rainbarrels_control_states = {} # set final results rainbarrels_results = {} water_demand_supply = {} water_harvesting = {} system_results = {} #read in temperature if os.name == 'nt': temperature_path = 'weather\\temperature_{}.csv'.format(year) else: temperature_path = 'weather/temperature_{}.csv'.format(year) Temperature_mean, Temperature_max, Temperature_min = calculate_irrigation_demand.read_in_temperature( temperature_path) #read in weather forecast if os.name == 'nt': forecast_path = 'weather\\rain_forecast_{}_{}.csv'.format( year, weatherforecast_kind) else: forecast_path = 'weather/rain_forecast_{}_{}.csv'.format( year, weatherforecast_kind) weatherforecast = weather_forecast.read_in_weather_forecast(forecast_path) with pyswmm.Simulation(swmm_file) as sim: system_stats = pyswmm.SystemStats(sim) #get system stats (rainfall) for n in range(number_rain_barrels): houses_lid_parameters[houses_implementation_RBs[n][ 0]] = houses_implementation_RBs[n][1:], pyswmm.LidGroups(sim)[ houses_implementation_RBs[n][0]][0], pyswmm.LidControls( sim)[houses_implementation_RBs[n][3]] rainbarrels_control_states[houses_implementation_RBs[n][0]] = [ 0, 0, False, False, False, 0, 0 ] rainbarrels_results[houses_implementation_RBs[n][0]] = [ 0, 0, 0, 0, 0 ] water_demand_supply[houses_implementation_RBs[n][0]] = {} water_harvesting[houses_implementation_RBs[n][0]] = {} for step in sim: ct = sim.current_time # current SWMM simulation time future_rainfall = False start_irrigation = False #print(ct) #daily control rules if ct >= newday: irrigation = irrigation_start <= ( newday.month, newday.day ) <= irrigation_end #check if actual day is in irrigation period newday_timestamp = newday #necessary for function irrigation_need and to find daily aggregated values in Temperature rain_day_beginning = system_stats.runoff_stats[ 'rainfall'] #get rainfall amount at beginning of the day [mm] newday += pd.Timedelta(days=1) #print(ct) #smart - get rain prediction for specific analysetime if smart and ct >= analysetime: weatherforecast_analysetime = weatherforecast.loc[ analysetime, '900':str(weatherforecast_accumulationtime )] #get weatherforecast specific analysetime weatherforecast_sum = sum( weatherforecast_analysetime ) #get rainsum of choosen analysetime if weatherforecast_sum > 0: future_rainfall = True future_rain_sum = weatherforecast_sum * runoff_coefficient #calculate effictive rainfall [mm] previous_rain_sum = system_stats.runoff_stats[ 'rainfall'] #get previous rainsum (rainsum is accumulated over simulation time) analysetime += pd.Timedelta( seconds=weatherforecast_updatesteps) #set new analysetime #calculate at irrigation demand at end of day - EN16941-1 (2018) EN 16941-1 On-site non-potable water systems. if ct > irrigation_time and irrigation: #set end of day for irrigation crop_evapotranspiration_ref = calculate_irrigation_demand.EH0( newday_timestamp, Temperature_max.loc[newday_timestamp, 'degC'], Temperature_min.loc[newday_timestamp, 'degC'], Temperature_mean.loc[newday_timestamp, 'degC'] ) #get necessary irrigation demand based on daily temperature rain_day = system_stats.runoff_stats[ 'rainfall'] - rain_day_beginning #get daily rainfall absolut_evapotranspiration = max( crop_evapotranspiration_ref - rain_day, 0) / 1000 #calculate irrigation demand [m3/m2] start_irrigation = True irrigation_time += pd.Timedelta(days=1) for subcatchment_name, ( (House_area, green_area, RB_name, RainBarrel_volume, RainBarrel_hight, RainBarrel_area, Rain_Barrel_DrainageCoefficient), RainBarrel, RainBarrel_control) in houses_lid_parameters.items(): RainBarrel_storage_old, RainBarrel_irrigation_goal, irrigation_on, rain_on, storm_on, closing_time, water_age_old = rainbarrels_control_states[ subcatchment_name] irrigation_demand_overall, water_saving, water_detention, number_operations, water_age = rainbarrels_results[ subcatchment_name] RainBarrel_storage = RainBarrel.storage.depth / 1000 * RainBarrel_area #[m3] get actual storage volume RainBarrel_available_storage = ( RainBarrel_volume - RainBarrel_storage ) #[m3] calclate available storage volume #smart and future_rainfall -> open rainbarrel if smart and future_rainfall: future_outflow_house = future_rain_sum / 1000 * House_area * 10000 if future_outflow_house > RainBarrel_available_storage and future_outflow_house < RainBarrel_volume and RainBarrel_storage > 0.001: #if predicted rainfall is higher than storage volume but less than rainbarrel volume RainBarrel_control.drain.coefficient = Rain_Barrel_DrainageCoefficient #open valve = set drainage coefficient rain_on = True #only open valve at analysetime number_operations += 1 #count opening operations if future_outflow_house > RainBarrel_volume: max_intensity_lead_time = weatherforecast_analysetime.idxmax( ) #get max intensity time temp_time = max_intensity_lead_time closing_time_RainBarrel = weatherforecast_analysetime.name + pd.Timedelta( seconds=int(temp_time)) - pd.Timedelta(seconds=900) if RainBarrel_storage > 0.001 and not storm_on: #or not rain_sum_to_max_intensity == 0: storm_on = True #only open valve at analysetime number_operations += 1 #count opening operations RainBarrel_control.drain.coefficient = Rain_Barrel_DrainageCoefficient #open valve = set drainage coefficient #irrigation time -> open rainbarrel if start_irrigation: irrigation_demand = absolut_evapotranspiration * green_area if irrigation_demand < RainBarrel_storage and irrigation_demand > 0: #calcluate usable water for irrigation inside storage layer water_usable = irrigation_demand water_needed = 0 irrigation_on = True #start irrigation elif irrigation_demand > RainBarrel_storage and irrigation_demand > 0 and RainBarrel_storage > 0.001: water_usable = RainBarrel_storage water_needed = irrigation_demand - water_usable irrigation_on = True #start irrigation else: water_usable = 0 water_needed = irrigation_demand if irrigation_on: #start irrigation RainBarrel.drain_node = 'Irrigation' #set outflow node RainBarrel_control.drain.coefficient = Rain_Barrel_DrainageCoefficient #open valve = set draiange coefficient RainBarrel_irrigation_goal = RainBarrel.water_balance.drain_flow + water_usable / RainBarrel_area * 1000 #calculate final outflow irrigation (RainBarrel_size is because of mm) water_saving += water_usable #calculate total water savings number_operations += 1 #count opening operations irrigation_demand_overall += irrigation_demand #calculate total irrigation demand water_demand_supply[subcatchment_name].update( {str(newday_timestamp): water_needed}) #get water demand for water supply water_harvesting[subcatchment_name].update( {str(newday_timestamp): water_usable}) #get amout of water harvesting #calculate detention_volume during irrigation period if irrigation: #only when irrigation time (21. March to 23. September) water_detention += max( RainBarrel_storage - RainBarrel_storage_old, 0) #calculate total detention volume #calculate water_age if RainBarrel_storage > 0.001: #only if storage > 1l time_delta = pd.Timedelta( ct - ct_old ).seconds / 3600 #get time difference between routing time steps water_age_actual = ( (water_age_old + time_delta) * (RainBarrel_storage_old - RainBarrel.new_drain_flow * time_delta * 3600 / 1000) ) / RainBarrel_storage #calculate actual water age else: water_age_actual = 0 water_age = max(water_age, water_age_actual) #set max water age #control rules every SWMM Step if irrigation_on: #control rules for irrigation if RainBarrel.water_balance.drain_flow >= RainBarrel_irrigation_goal or RainBarrel_storage < 0.001: #either irrigation demand or minimum water level reached irrigation_on = False #stop irrigation process RainBarrel_control.drain.coefficient = 0 #close valve - set drainage coefficient = 0 RainBarrel.drain_node = -1 #set outflow node if not irrigation_on and rain_on: #control rules for rainfall lower than rain barrel volume future_rain_storage = ( max( future_rain_sum - (system_stats.runoff_stats['rainfall'] - previous_rain_sum), 0) ) / 1000 * House_area * 10000 #calcute actuell rain storage volume if future_rain_storage < RainBarrel_available_storage: #if enough volume is available rain_on = False #stop emptying RainBarrel_control.drain.coefficient = 0 #close valve = set drainage coefficient = 0 if not irrigation_on and storm_on: if ct >= closing_time_RainBarrel: storm_on = False #close valve RainBarrel_control.drain.coefficient = 0 #close valve = set drainage coefficient = 0 #set new list values RainBarrel_storage_old = RainBarrel_storage rainbarrels_control_states[subcatchment_name] = [ RainBarrel_storage_old, RainBarrel_irrigation_goal, irrigation_on, rain_on, storm_on, closing_time, water_age_actual ] rainbarrels_results[subcatchment_name] = [ irrigation_demand_overall, water_saving, water_detention, number_operations, water_age ] #set old control step ct_old = ct #system states #flooding flooding_volume = 0 number_nodes = 0 flooding_nodes = {} for node in pyswmm.Nodes(sim): flooding_volume += node.statistics['flooding_volume'] number_nodes += 1 flooding_nodes.update( {node.nodeid: node.statistics['flooding_volume']}) #outflows outflow_irrigation = pyswmm.Nodes(sim)['Irrigation'].cumulative_inflow outflow_mixed_overflox = pyswmm.Nodes(sim)['CSO'].cumulative_inflow outflow_wastewater_treatmentplant = pyswmm.Nodes( sim)['treatment_plant'].cumulative_inflow system_results = [ number_nodes, flooding_volume, outflow_irrigation, outflow_mixed_overflox, outflow_wastewater_treatmentplant ] total_results = {} total_results['volume'] = [rain_barrel_total_volume] total_results['rainbarrels_results'] = [rainbarrels_results] total_results['water_demand_supply'] = [water_demand_supply] total_results['water_harvesting'] = [water_harvesting] total_results['system_results'] = [system_results] total_results['flooding_node'] = [flooding_nodes] results_json = json.dumps(total_results) f = open('results/{}'.format(json_file), "w") f.write(results_json) f.close() #print(dt.datetime.now()-startTime) os.remove(name + '.rpt') #delete report file os.remove(name + '.out') #delete out file os.remove(swmm_file) #delete swmm file
import sys import pyswmm try: pyswmm.Simulation('') except pyswmm.swmm5.SWMMException: pass
def swmm_simulate(inpFile, simulationStartTime, simulationEndTime, selected_nodes = list(), selected_links = list(), selected_subcatchments = list(), output_time_step = 300, add_and_remove_hotstart_period = False, hotstart_period_h = 5): import numpy as np import pyswmm import datetime from dateutil.relativedelta import relativedelta # import pdb # pdb.set_trace() # create time objects in Python simulationStartTime = datetime.datetime.strptime(simulationStartTime,"%Y-%m-%d %H:%M").replace(tzinfo=datetime.timezone.utc) simulationStartTime -= datetime.timedelta(seconds=output_time_step) # subtract one time step from the start time - otherwise the first time is a bit late simulationEndTime = datetime.datetime.strptime(simulationEndTime,"%Y-%m-%d %H:%M").replace(tzinfo=datetime.timezone.utc) ## Allocate space in arrays for storing the results later # we allocate a 10\% more of space just in case after the simulation it is freed... expected_timeseries_length = int(np.ceil(1.1*(simulationEndTime - simulationStartTime).total_seconds()/output_time_step)) # "ynode" is a dict with time series for the specified points of interest output_dict = {} output_dict["time"] = [datetime.datetime.now() for i in range(expected_timeseries_length)] for node in selected_nodes: output_dict[node] = np.zeros(expected_timeseries_length) for link in selected_links: output_dict[link] = np.zeros(expected_timeseries_length) for subcatchment in selected_subcatchments: output_dict[subcatchment] = np.zeros(expected_timeseries_length) # define which time steps to tell the user how far the simulation has come message_at_step = (np.linspace(0.25,0.75,num=3) * ((expected_timeseries_length/1.1) + hotstart_period_h*60/(output_time_step/60))).round() with pyswmm.Simulation(inpFile) as sim: # preparing the settings for the simulation like start and end time sim.start_time = simulationStartTime sim.end_time = simulationEndTime sim.step_advance(output_time_step) # if it has been selected that a "transient period" should be added in front the of the event that is simulated, then we add it here if add_and_remove_hotstart_period: sim.start_time = simulationStartTime - relativedelta(hours=hotstart_period_h) #Afterwards do not register the hotstart_period_h first hours!!! if len(selected_nodes)>0: l_node=[] allNodes = pyswmm.Nodes(sim) for node in selected_nodes: l_node.append(allNodes[node]) if len(selected_links)>0: allLinks = pyswmm.Links(sim) l_link=[] for link in selected_links: l_link.append(allLinks[link]) if len(selected_subcatchments)>0: allSubcatchments = pyswmm.Subcatchments(sim) l_subcatchment=[] for subcatchment in selected_subcatchments: l_subcatchment.append(allSubcatchments[subcatchment]) print("Simulation has started...") # run the model by moving one time step forward in time #nstep_hotstart = 0 # counter for number of time steps in the hotstart nstep = 0 # counter for the number of time steps in the model simulation message_step = 0 for step in sim: tt = sim.current_time.replace(tzinfo=datetime.timezone.utc) #nstep_hotstart += 1 message_step += 1 if (tt-simulationStartTime).total_seconds() >= 0: output_dict["time"][nstep] = tt.replace(tzinfo=datetime.timezone.utc) # save the time stamps for each time step for index, node in enumerate(selected_nodes): output_dict[node][nstep] = l_node[index].depth # save the values for all the variables of interest for index, link in enumerate(selected_links): output_dict[link][nstep] = l_link[index].flow for index, subcatchment in enumerate(selected_subcatchments): output_dict[subcatchment][nstep] = l_subcatchment[index].runoff nstep += 1 # increase the counter for the number of time steps if np.isin(message_step, message_at_step): print("Percent completed: " + str(round(sim.percent_complete*100))) # cut off the space that was intentionally allocated too much output_dict["time"] = output_dict["time"][:nstep] # there are only "nstep" number of time steps for i in output_dict: output_dict[i] = output_dict[i][:nstep] print("Simulation finished !!!!") return(output_dict)
#PySWMM test code import pyswmm as ps # import package sim = ps.Simulation( 'tutorial1.inp') # load & run simulation with no interaction sim.execute() with ps.Simulation('tutorial1.inp' ) as sim: # load and run simulation and print each timestep for step in sim: print(sim.current_time) sim.report()
def swmm_model_inventory(inpFile): import pandas as pd import pyswmm node_id_list = list() junction_list = list() outfall_list = list() storage_list = list() link_id_list = list() connections_list = list() conduit_list = list() orifice_list = list() outlet_list = list() pump_list = list() weir_list = list() raingauge_id_list = list() subcatchment_id_list = list() subcatchment_connection_list = list() with pyswmm.Simulation(inpFile) as sim: allNodes = pyswmm.Nodes(sim) for node in allNodes: node_id_list.append(node.nodeid) #temp_node = pyswmm.Nodes(sim)[node_list[i]] junction_list.append(node.is_junction()) outfall_list.append(node.is_outfall()) storage_list.append(node.is_storage()) allLinks = pyswmm.Links(sim) for link in allLinks: link_id_list.append(link.linkid) connections_list.append(link.connections) conduit_list.append(link.is_conduit()) orifice_list.append(link.is_orifice()) outlet_list.append(link.is_outlet()) pump_list.append(link.is_pump()) weir_list.append(link.is_weir()) allRainGauges = pyswmm.RainGages(sim) for rg in allRainGauges: raingauge_id_list.append(rg.raingageid) allSubcatchments = pyswmm.Subcatchments(sim) for subcatchment in allSubcatchments: subcatchment_id_list.append(subcatchment.subcatchmentid) subcatchment_connection_list.append(subcatchment.connection) #node_type = ["" for x in range(len(node_id_list))] nodes_overview = pd.DataFrame({ "id": node_id_list, "type": ["" for x in range(len(node_id_list))] }) nodes_overview.loc[junction_list, "type"] = "junction" nodes_overview.loc[outfall_list, "type"] = "outfall" nodes_overview.loc[storage_list, "type"] = "storage" #links_type = ["" for x in range(len(link_id_list))] links_overview = pd.DataFrame({ "id": link_id_list, "type": ["" for x in range(len(link_id_list))], "upstream_node": [connections_list[x][0] for x in range(len(connections_list))], "downstream_node": [connections_list[x][1] for x in range(len(connections_list))] }) links_overview.loc[conduit_list, "type"] = "conduit" links_overview.loc[orifice_list, "type"] = "orifice" links_overview.loc[outlet_list, "type"] = "outlet" links_overview.loc[pump_list, "type"] = "pump" links_overview.loc[weir_list, "type"] = "weir" subcatchments_overview = pd.DataFrame({ "id": subcatchment_id_list, "connection_node": [ subcatchment_connection_list[x][1] for x in range(len(subcatchment_connection_list)) ] }) return (nodes_overview, links_overview, subcatchments_overview, raingauge_id_list)