def add_tank_get_score(num_junctions, avg_initial_pressure_at_each_junc): global tank_elev_array network = Network(inp_file) junc_elev_array = [] junc_x_y_array = [] junc_id_array = [] score_array = [] # this loop add a tank to Node 1, calculate the peak-demand average pressure, stores it, and deletes the tank # it then adds a tank to Node 2 and repeats until all nodal locations are scored for junction in range(num_junctions): junc_elev_array.append(network.ep.ENgetnodevalue(junction + 1, 0)) junc_x_y_array.append(network.ep.ENgetcoord(junction + 1)) junc_id_array.append(network.ep.ENgetnodeid(junction + 1)) optimum_elevation = junc_elev_array[ junction] + avg_initial_pressure_at_each_junc[junction] tank_elev_array.append(optimum_elevation) network.add_tank(uid='balancing_tank', x=junc_x_y_array[junction][0], y=junc_x_y_array[junction][1], elevation=optimum_elevation, diameter=100, maxlevel=1000, minlevel=0, tanklevel=0) network.add_pipe(uid='balancing_tank_pipe', from_node=junc_id_array[junction], to_node='balancing_tank', diameter=1000, length=10, roughness=1E9, check_valve=False) network.save_inputfile(inp_file) junction_score = score_pressure_array( solve_and_return_pressures(num_junctions)) score_array.append(junction_score) print("Junction index ", score_index_counter, " : ", junction_score) network.delete_link('balancing_tank_pipe') network.delete_node('balancing_tank') network.reset() network.save_inputfile(inp_file) return score_array
class NetworkAgent: def __init__(self, filename='anytown_master.inp'): # load network self.network = Network(filename) self.network.solve() # for control self.speed_limit = (0.7, 1.2) # danger zone self.junction_threshold = (15, 120) self.state = None # function to get the effeciency of the pump(s) self.eff = None # speed increase/decrease resolution self.stepsize = 0.1 self.network.solve() self._calc_effeciency('E1') def _calc_effeciency(self, curve_id): curve = None for x in self.network.curves: if curve_id in x.uid: flow = [ value[0] for value in x.values] y = [value[1] for value in x.values] curve = np.poly1d(np.polyfit(flow,y,4)) if not curve: logging.info('no curve found with id{}'.format(curve_id)) self.eff = curve def reset(self): # epynet has its own reset function # self._calc_effeciency('E1') #optimize from scipy.optimize import minimize # initial guess is 0.8 thats the speed self.res = minimize(self.find_opt,1.2, method='Nelder-Mead', options={'disp':True}, bounds = self.speed_limit) print(self.res.x) self.network.reset() def find_opt(self, x): """ x : pump's speed returns: effeciency """ # change speed self.network.pumps['78'].speed = x self.network.solve() eff = self.calc_eff() # - sign because we need the maximum value return - eff def step(self): x = self.network.solve() print('solve function returns: {}'.format(x)) def calc_eff(self): # get only one pump with id 78 # complicated networks will be harder than this flow = self.network.pumps['78'].flow print('flow is: {}'.format(flow)) speed = self.network.pumps['78'].speed true_flow = float(flow/speed) return self.eff(true_flow) def junction_head(self): return list(self.network.junctions.head) def junction_demand(self): return list(self.network.junctions.demand) def junction_pressure(self): return list(self.network.junctions.pressure) def _action_increase_speed(self): # check if it's within the limits if self.network.pumps['78'].speed + self.stepsize > self.speed_limit[1]: return self.network.pumps['78'].speed += self.stepsize def _action_decrease_speed(self): if self.network.pumps['78'].speed - self.stepsize < self.speed_limit[1]: return self.network.pumps['78'].speed -= self.stepsize