def constraint_checker(diameter_array, min_pre, min_vel, max_vel, file,
                       num_nodes, num_links, num_pipes):
    # reconstruct .inp file from diameter array and store it as a temp file
    for pipe in range(len(diameter_array)):
        if diameter_array[pipe] > 0:
            ep.ENsetlinkvalue(pipe + 1, 0, diameter_array[pipe])

    ep.ENsaveinpfile(file)

    ep.ENopenH()
    ep.ENinitH()
    ep.ENrunH()

    # initialize an array of nodal heads
    head_array = np.zeros(num_nodes)
    # initialize an array of pipe velocities
    velocity_array = np.zeros(num_links)

    fail_pressure_list = []
    fail_min_vel_list = []
    fail_max_vel_list = []
    negative_diameter_list = []

    fail_pressure = False
    fail_min_vel = False
    fail_max_vel = False
    negative_diameter = False

    for node in range(num_nodes):

        if ep.ENgetnodevalue(node + 1,
                             11) < min_pre and ep.ENgetnodetype(node + 1) == 0:
            fail_pressure_list.append(node)
            fail_pressure = True

    for pipe in range(num_pipes):

        if ep.ENgetlinkvalue(pipe + 1, 9) < min_vel:
            fail_min_vel_list.append(pipe)
            fail_min_vel = True
        elif ep.ENgetlinkvalue(pipe + 1, 9) > max_vel:
            fail_max_vel_list.append(pipe)
            fail_max_vel = True

    i = 0
    for diameter in diameter_array:
        i += 1
        if diameter <= 0:
            negative_diameter_list.append(i)
            negative_diameter = True

    print('Fail pressure list (nodes):', fail_pressure_list)
    print('Lower than min velocity list (links):', fail_min_vel_list)
    print('Higher than max velocity list (links):', fail_max_vel_list)

    if fail_pressure or fail_min_vel or fail_max_vel or negative_diameter:
        return False
    else:
        return True
Exemple #2
0
def HydrantRating(MyNode, Demands):
    #Open the EPANET toolkit & hydraulics solver
    em.ENopen("example2.inp", "example2.rpt")
    em.ENopenH()

    # Get the index of the node of interest
    nodeindex = em.ENgetnodeindex(MyNode)

    rating = []
    # Iterate over all demands
    for dem in Demands:
        em.ENsetnodevalue(nodeindex, em.EN_BASEDEMAND, dem)
        em.ENinitH(em.EN_NOSAVE)
        em.ENrunH()
        pressure = em.ENgetnodevalue(nodeindex, em.EN_PRESSURE)
        rating.append(pressure)

    # Close hydraulics solver & toolkit */
    em.ENcloseH()
    em.ENclose()
    return rating
def simulation_supply(year, weatherforecast_kind, weatherforecast_accumulationtime, penetration_rate, control_type, number_simulation, original_epanet_file, original_swmm_file, irrigation_start, irrigation_end):

    #created file names
    name = original_epanet_file[:-4] + '_{}_{}_{}_{}_{}_{}'.format(year, weatherforecast_kind, weatherforecast_accumulationtime, penetration_rate, control_type, number_simulation)
    epanet_file = name + '.inp'
    epanet_report_file = name + '.rpt'
    json_file_drainage = original_swmm_file[:-4] + '_{}_{}_{}_{}_{}_{}.json'.format(year, weatherforecast_kind, weatherforecast_accumulationtime, penetration_rate, control_type, number_simulation)
    json_file = name + '.json'

    #read in results from urban drainage simulation
    with open('results/{}'.format(json_file_drainage)) as myfile:
        data = json.load(myfile)
    water_demand_supply = data['water_demand_supply'][0]
    water_harvesting = data['water_harvesting'][0]

    #read in classifcation houses to junctions
    if os.name == 'nt':
        classification_path = 'water\\Classification_Houses_Junctions.csv'
    else:
        classification_path = 'water/Classification_Houses_Junctions.csv'
    classification = pd.read_csv(classification_path, sep=';', header=None, names=['PropertyID','JunctionID'])
    classification.set_index('PropertyID',inplace=True)

    #read in daily weather data
    if os.name == 'nt':
        daily_weather_path = 'weather\\weather_daily_2015.csv'
    else:
        daily_weather_path = 'weather/weather_daily_2015.csv'
    daily_weather = pd.read_csv(daily_weather_path, sep=';', header=0)
    daily_weather['Date'] = pd.to_datetime(daily_weather['Date'], format='%d.%m.%Y')
    daily_weather.set_index('Date', inplace=True)

    #set irrigation period
    start_irrigation = pd.to_datetime('{}.{}.{}'.format(irrigation_start[1], irrigation_start[0], year), format='%d.%m.%Y')
    end_irrigation = pd.to_datetime('{}.{}.{}'.format(irrigation_end[1], irrigation_end[0], year), format='%d.%m.%Y') + pd.Timedelta(hours = 23)

    duration = end_irrigation - start_irrigation
    hours = int(duration.days * 24 + (duration.seconds/3600))

    #set daily demand pattern
    patterns = {}
    patterns['March'] = [0.40, 0.30, 0.15, 0.10, 0.15, 0.50, 1.00, 1.50, 1.60, 1.50, 1.30, 1.20, 1.30, 1.20, 1.15, 1.20, 1.20, 1.40, 1.60, 1.50, 1.20, 1.05, 0.90, 0.60]
    patterns['April'] = [0.35, 0.20, 0.20, 0.20, 0.35, 0.70, 1.20, 1.40, 1.40, 1.30, 1.25, 1.20, 1.30, 1.20, 1.25, 1.25, 1.45, 1.70, 1.60, 1.30, 1.10, 0.95, 0.70, 0.45]
    patterns['May'] = [0.40, 0.30, 0.30, 0.30, 0.40, 0.85, 1.25, 1.35, 1.30, 1.25, 1.20, 1.15, 1.25, 1.20, 1.15, 1.25, 1.40, 1.65, 1.50, 1.30, 1.15, 0.95, 0.70, 0.45]
    patterns['June'] = [0.45, 0.45, 0.40, 0.40, 0.40, 0.80, 1.25, 1.40, 1.30, 1.25, 1.15, 1.15, 1.20, 1.20, 1.15, 1.15, 1.30, 1.60, 1.55, 1.30, 1.10, 0.90, 0.70, 0.45]
    patterns['July'] = [0.40, 0.40, 0.30, 0.30, 0.40, 0.80, 1.20, 1.45, 1.35, 1.25, 1.20, 1.25, 1.20, 1.15, 1.05, 1.15, 1.30, 1.60, 1.50, 1.30, 1.15, 1.05, 0.80, 0.45]
    patterns['August'] = [0.30, 0.20, 0.15, 0.20, 0.35, 0.70, 1.30, 1.50, 1.45, 1.40, 1.25, 1.25, 1.20, 1.15, 1.05, 1.15, 1.40, 1.70, 1.60, 1.35, 1.15, 1.00, 0.75, 0.45]
    patterns['September'] = [0.30, 0.20, 0.15, 0.15, 0.30, 0.75, 1.35, 1.55, 1.50, 1.35, 1.25, 1.20, 1.25, 1.25, 1.10, 1.15, 1.40, 1.65, 1.55, 1.30, 1.15, 1.00, 0.75, 0.40]

    #set monthly demand variation factor
    month_demand = {}
    month_demand['January'] = 0.85
    month_demand['February'] = 0.95
    month_demand['March'] = 1.00
    month_demand['April'] = 1.05
    month_demand['May'] = 1.20
    month_demand['June'] = 1.10
    month_demand['July'] = 1.05
    month_demand['August'] = 1.00
    month_demand['September'] = 1.00
    month_demand['October'] = 0.95
    month_demand['November'] = 0.95
    month_demand['December'] = 0.90

    #set monthly spring variation factor
    month_source = {}
    month_source['January'] = 0.80
    month_source['February'] = 0.75
    month_source['March'] = 0.70
    month_source['April'] = 0.90
    month_source['May'] = 1.15
    month_source['June'] = 1.20
    month_source['July'] = 1.15
    month_source['August'] = 1.15
    month_source['September'] = 1.20
    month_source['October'] = 1.10
    month_source['November'] = 1.00
    month_source['December'] = 0.90

    #add rainbarrels to epanet file and change year:
    f = open(original_epanet_file) #read in
    success, val = read_write_swmm.swmm_input_read(f)

    if not success:
        print(val)
        sys.exit(1)

    val, house_to_node = modify_epanet_input.implement_irrigation_to_node(val, water_demand_supply, classification, hours)

    f = open(epanet_file,'w')
    read_write_swmm.swmm_input_write(f,val)
    f.close()

    #set initial values
    node_with_rainbarrel = {} #for node with rainbarrels
    demand_pattern_name = 'Demand' #pattern for water demand
    water_source_name = 'spring' #node name for water source

    #open Epanet Toolkit
    en.ENopen(epanet_file, epanet_report_file) #, epanet_bin_file) #open Epanet Toolkit with files

    #initiate epanet simulation
    en.ENopenH() #open hydraulic solver
    en.ENinitH(en.EN_SAVE) #save hydraulic results to bin file
    t = start_irrigation #set start time

    #set rainbarrel patterns
    peak_demand_hour = 17

    #get rain barrel control parameters
    for key, (junction) in house_to_node.items():
        patternid_node = en.ENgetpatternindex('Demand_{}'.format(junction))
        node_id = en.ENgetnodeindex(junction)
        node_with_rainbarrel[key] = patternid_node, node_id

    #get water source index
    water_source = en.ENgetnodeindex(water_source_name) #node index
    water_source_abstraction = en.ENgetnodevalue(water_source, en.EN_BASEDEMAND) # get base demand

    #get Demand pattern index
    demand = en.ENgetpatternindex(demand_pattern_name)

    #create dictonaries for results
    number_nodes = en.ENgetcount(en.EN_NODECOUNT)
    water_age = {}

    for index in range(1, number_nodes+1):
        key = en.ENgetnodeid(index).decode('utf-8')
        water_age[key] = {}

    pressure_nodes = copy.deepcopy(water_age)
    pressure_nodes_peak = copy.deepcopy(water_age)

    day = 0
    total_demand = 0

    while t < end_irrigation: #important that t is as long as duration to read hydraulic results file
        en.ENrunH() #run time step
        timedelta = en.ENsimtime() #get current simulation time
        t = start_irrigation + pd.Timedelta(days = timedelta.days, seconds = timedelta.seconds) #combine it with real date

        if t.hour == 23 and t.minute == 0 and t < end_irrigation: #check if new day, 23 because changes will be updated next time step at 0:00
            date = t + pd.Timedelta(seconds = 3600) #to get beginning of day
            month_name = date.month_name() #get month name

            #get daily demand factors
            month_factor_demand = month_demand[month_name] #get monthly factor
            daily_factor_demand, daily_factor_irrigation = calculate_daily_demand_spring.calculate_demand(daily_weather.loc[date,'Tmean'], daily_weather.loc[date,'Rain']) #calculate daily demand factor based on temperature
            demand_factor = month_factor_demand * daily_factor_demand #calculate demand factor for changing pattern
            irrigation_factor = month_factor_demand * daily_factor_irrigation #calculate irrigation factor for changing pattern

            #get daily source factors
            month_factor_source = month_source[month_name] #get monthly factor
            daily_factor_source = calculate_daily_demand_spring.calculate_spring(daily_weather.loc[date,'Tmean'],daily_weather.loc[date,'Rain']) #calculate daily source factor based on temperature
            source_factor = month_factor_source * daily_factor_source #calculate month factor for changing base source

            #set daily demand pattern
            demand_pattern = patterns[t.month_name()] #get daily pattern depending on month
            daily_demand_pattern = [i * demand_factor for i in demand_pattern] #change pattern
            en.ENsetpattern(demand, daily_demand_pattern) #set pattern

            #set daily water source pouring
            daily_source_abstraction = source_factor * water_source_abstraction #change -demand
            en.ENsetnodevalue(water_source, 1, daily_source_abstraction) #set demand

            #reset demand patterns for node with rain barrel - necessary for multiple rain barrels at one node
            for key, (pattern_node_id, node_id) in node_with_rainbarrel.items():
                en.ENsetpattern(pattern_node_id, daily_demand_pattern)

            #set individual rain barrel pattern
            for key, (pattern_node_id, node_id) in node_with_rainbarrel.items():

                water_demand = water_demand_supply[key][str(date)] #get irrigation demand for rain barrels m3
                water_harvested = water_harvesting[key][str(date)] #get saved water m3

                #set filling time rain barrel
                pattern_time = 23
               
                #get base demand for node
                base_demand = en.ENgetnodevalue(node_id,en.EN_BASEDEMAND) 

                #get actual pattern for node with rain barrel
                actual_pattern_value_filling = en.ENgetpatternvalue(pattern_node_id, pattern_time)
                actual_pattern_value_peak = en.ENgetpatternvalue(pattern_node_id, peak_demand_hour+1)

                #set filling of rain barrel
                water_abstraction_filling = actual_pattern_value_filling * base_demand
                water_abstraction_filling_new = water_abstraction_filling + water_demand / (60*60) * 1000 #calculate l/s
                water_abstraction_filling_new_pattern = water_abstraction_filling_new / base_demand
                en.ENsetpatternvalue(pattern_node_id, pattern_time, water_abstraction_filling_new_pattern) #change pattern

                #set reduction at peak hour
                water_abstraction_peak = actual_pattern_value_peak * base_demand * 3600
                water_abstraction_peak_without = daily_demand_pattern[peak_demand_hour] * base_demand * 3600

                water_abstraction_irrigation_total = sum([i*base_demand for i in daily_demand_pattern]) * 3600 * irrigation_factor
                water_reduction_irrigation_poss = (water_demand + water_harvested) * 1000 #calculate l/s
                water_reduction_irrigation = min(water_reduction_irrigation_poss, 0.4*water_abstraction_irrigation_total)

                water_reduction_total = max(water_abstraction_peak - water_reduction_irrigation, water_abstraction_peak_without * 0.6) / 3600

                water_redcution_new_pattern = water_reduction_total / base_demand
                en.ENsetpatternvalue(pattern_node_id, peak_demand_hour+1, water_redcution_new_pattern) #change pattern

                if day == 0:
                    total_demand += base_demand
                    day += 1

        #get pressure results at peak demand (17h -> reducing irrigation demand)
        if t.hour == 17:
            for index in range(1, number_nodes+1):
                key = en.ENgetnodeid(index).decode('utf-8') #get key (nodeid)
                pressure_nodes_peak[key].update({str(t): en.ENgetnodevalue(index, en.EN_PRESSURE)}) #get pressure for node

        #get pressure results at filling time rainbarrels (22-23h -> because at 23 irrigation starts)
        if t.hour == 22:
            for index in range(1, number_nodes+1):
                key = en.ENgetnodeid(index).decode('utf-8') #get key (nodeid)
                pressure_nodes[key].update({str(t): en.ENgetnodevalue(index, en.EN_PRESSURE)}) #get pressure for node

        en.ENnextH() #next time step

    en.ENcloseH() #close hydraulic solver

    en.ENopenQ() #open quality solver

    en.ENinitQ(en.EN_SAVE) #save quality results to bin file
    t = start_irrigation #set start time

    while t < end_irrigation: #t should be lower than from hydraulic results (< instead of <=)
        en.ENrunQ() #run quality time step
        timedelta = en.ENsimtime() #get current simulation time
        t = start_irrigation + pd.Timedelta(days = timedelta.days, seconds = timedelta.seconds) #combine it with real date

        #get water age results at end of the day
        if t.hour == 23:
            for index in range(1, number_nodes+1):
                key = en.ENgetnodeid(index).decode('utf-8') #get key (nodeid)
                water_age[key].update({str(t): en.ENgetnodevalue(index, en.EN_QUALITY)}) #get pressure for node

        en.ENstepQ() #next quality time step

    en.ENcloseQ() #close quality solver
    en.ENclose() #close epanet toolkit and delete files

    total_water_results = {}
    total_water_results['pressure'] = [pressure_nodes]
    total_water_results['pressure_peak'] = [pressure_nodes_peak]
    total_water_results['water_age'] = [water_age]

    results_json = json.dumps(total_water_results)
    f = open('results/{}'.format(json_file),"w")
    f.write(results_json)
    f.close()

    os.remove(epanet_report_file) #delete report file
    os.remove(epanet_file) #delete epanet file
em.ENopen(inpName + '.inp', inpName + '.rpt')
#print(inpName)
demMult = em.ENgetoption(em.EN_DEMANDMULT)

### get avg pressure
nnodes = em.ENgetcount(em.EN_NODECOUNT)
junInds = []
for index in range(1, nnodes + 1):
    if em.ENgetnodetype(index) == em.EN_JUNCTION:
        junInds.append(index)

junPres = [[] for q in range(len(junInds))]

time = []
## RUN SIM
em.ENopenH()
em.ENinitH(0)
while True:
    em.ENrunH()

    t = em.ENsimtime()
    time.append(
        datetime.timedelta.total_seconds(t))  #convert time delta to seconds

    # Retrieve hydraulic results for time t

    #    #Tank heights
    #    for  i in range(0,len(tankInds)):
    #        p=em.ENgetnodevalue(tankInds[i], em.EN_PRESSURE )
    #        tankLvls[i].append(p)
    #