Skip to content

Commit

Permalink
New release
Browse files Browse the repository at this point in the history
1- Bug fixed in result: These bugs were relaetd to new version of the pandas being used. More bug fixes to come. 2- Bug fix in damage and restoration. The bug was introduced with different behavior of teh newer WNTr. 3- Enhancing the isolated elements algorithm.
  • Loading branch information
snaeimi committed Jan 30, 2025
1 parent 5f54258 commit 735043b
Show file tree
Hide file tree
Showing 8 changed files with 230 additions and 74 deletions.
6 changes: 3 additions & 3 deletions rewet/EnhancedWNTR/morph/link.py
Original file line number Diff line number Diff line change
Expand Up @@ -202,17 +202,17 @@ def _split_or_break_pipe(wn, pipe_name_to_split, new_pipe_name,
# add new pipe and change original length
wn2.add_pipe(new_pipe_name, j1, end_node.name,
original_length*(1-split_at_point), pipe.diameter,
pipe.roughness, pipe.minor_loss, pipe.status, pipe.cv)
pipe.roughness, pipe.minor_loss, pipe.status, pipe.check_valve)
pipe.length = original_length*split_at_point
else: # add pipe at start
pipe.start_node = wn2.get_node(j0)
# add new pipe and change original length
wn2.add_pipe(new_pipe_name, start_node.name, j1,
original_length*split_at_point, pipe.diameter,
pipe.roughness, pipe.minor_loss, pipe.status, pipe.cv)
pipe.roughness, pipe.minor_loss, pipe.status, pipe.check_valve)
pipe.length = original_length*(1-split_at_point)

if pipe.cv:
if pipe.check_valve:
logger.warn('You are splitting a pipe with a check valve. The new \
pipe will not have a check valve.')

Expand Down
115 changes: 61 additions & 54 deletions rewet/EnhancedWNTR/network/model.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ def __init__(self, inp_file_name=None):
self.breakage_link = {}
self.expicit_leak = []


def updateWaterNetworkModelWithResult(self, result , registry, latest_simulation_time = None):
"""
Updates Water Netwrok Model consistent with result model. must be only
Expand All @@ -56,65 +56,65 @@ def updateWaterNetworkModelWithResult(self, result , registry, latest_simulation
Parameters
----------
result : Water Netwrok Result
latest_simulation_time : int
latest time of simulation(duration of the latest run), to be
checked with time in result. Defaylt None.
Raises
------
ValueError
When simulation object is not of type EpanetSimulator
When simulation object is not of type EpanetSimulator
When latest simulation time is provided and is not consistent with
latest time in result.
When Tank level gets less than zero
Returns
-------
None.
"""


max_time = result.node['head'].index.max()
if latest_simulation_time == None:
latest_simulation_time = max_time
else:
if latest_simulation_time != max_time:
raise ValueError('Provided LATEST SIMULATION TIME id not consistnt with teh latest time in RESULT')

avilable_tank_name_list = set(self.tank_name_list).intersection(result.node['head'].columns)
for tank_name in avilable_tank_name_list:
#if tank_name not in result.node['head'].columns:
#continue
tank_level = None
head = None

cur_node = self.get_node(tank_name)
if cur_node._is_isolated:
continue
head = result.node['head'].loc[max_time, tank_name]

tank_level = head - cur_node.elevation
if tank_level < 0:
tank_level=0

if tank_level < cur_node.min_level:
tank_level = cur_node.min_level

if tank_level - cur_node.max_level > 0:
tank_level = cur_node.max_level

cur_node.init_level = abs(tank_level)
cur_node._head = cur_node.elevation + tank_level

if tank_level < 0.0:
logger.error('head= '+ repr(head))
logger.error('elevation= '+ repr(cur_node.elevation))
logger.error('tank_level= '+ repr(tank_level))
raise ValueError('Tank Level for ' + tank_name + ' is less than zero')

for link_name in self.link_name_list:
link = self.get_link(link_name)
setting = None
Expand All @@ -126,26 +126,26 @@ def updateWaterNetworkModelWithResult(self, result , registry, latest_simulation
#logger.error(link_name + ' exist in WaterNetwork but does not exist in result')
#raise ValueError(link_name + ' exist in WaterNetwork but does not exist in result')
continue

if isinstance(link, Valve):
link.settings = float(setting)

elif isinstance(link, Pump):
link.setting.base_value = float(setting)

if status == 0:
link._user_status = LinkStatus.Closed

elif status == 1:
link._user_status = LinkStatus.Open

elif status == 2:
link._user_status = LinkStatus.Active

else:
logger.error('Element type is: '+repr(type(link)))
logger.error('Status is : ' + repr(status))

def read_inpfile(self, filename):
"""
Defines water network model components from an EPANET INP file
Expand Down Expand Up @@ -178,115 +178,122 @@ def write_inpfile(self, filename, units=None):
if units is None:
units = self._options.hydraulic.en2_units
self._inpfile.write(filename, self, units=units)

def implicitLeakToExplicitEMitter(self, registry):
if len(self.expicit_leak) > 0:
raise ValueError("Explicit leak is not reset")

registry.active_pipe_damages = OrderedDict()
for node_name in self.node_name_list:
node = self.get_node(node_name)

if node._leak:

if node_name in self.expicit_leak:
raise ValueError('The node name in already in leak memory: '+node_name)

new_node_name = node_name+'-nn'
new_coord = (node.coordinates[0]+1,node.coordinates[1]+1)
self.add_junction(new_node_name, elevation=node.elevation ,coordinates=new_coord)
new_node = self.get_node(new_node_name)
new_node = self.get_node(new_node_name)


new_pipe_name = node_name+'-elk'
self.add_pipe(new_pipe_name, node_name, new_node_name, diameter=100, length=1, roughness=1000000, check_valve=True)

cd = node.leak_area*(2)**0.5 #(m^3ps/(KPa^0.5))
cd = cd/(0.145038**0.5) #(gpm/(Psi^0.5))
# When writing to emitter, function from_si changes m^3ps to GPM

new_node._emitter_coefficient = cd

if node.demand_timeseries_list[0].base_value > 0.001:
raise ValueError('leak node has demand: '+node_name)
temp={'node_name':node_name, 'method':'emitter', 'element1':new_pipe_name, 'element2':new_node_name, 'attr1':cd}
self.expicit_leak.append(temp)
registry.explicit_leak_node[node_name] = new_node_name
registry.active_pipe_damages.update({new_node_name:node_name})

def implicitLeakToExplicitReservoir(self, registry):
if len(self.expicit_leak) > 0:
raise ValueError("Explicit leak is not reset")
registry.active_pipe_damages = OrderedDict()
for node_name in self.node_name_list:
node = self.get_node(node_name)

if node._leak:

if node_name in self.expicit_leak:
raise ValueError('The node name in already in leak memory: '+node_name)

new_node_name = node_name+'_nn'
new_coord = (node.coordinates[0]+1,node.coordinates[1]+1)
self.add_reservoir(new_node_name, base_head = node.elevation ,coordinates=new_coord)

new_pipe_name = node_name+'-rlk'
diameter = np.sqrt(node.leak_area*4/3.14)
self.add_pipe(new_pipe_name, node_name, new_node_name, diameter=diameter, length=1, roughness=1000000, minor_loss = 1, check_valve=True)

if node.demand_timeseries_list[0].base_value>0.001:
raise ValueError('leak node has demand: '+node_name)
temp={'node_name':node_name, 'method':'reservoir', 'element1':new_pipe_name, 'element2':new_node_name}
self.expicit_leak.append(temp)
registry.explicit_leak_node[node_name] = new_node_name
registry.active_pipe_damages.update({new_node_name:node_name})

node.add_demand(-0.00001, pattern_name=None)

def resetExplicitLeak(self):
for data in self.expicit_leak:

for data in self.expicit_leak:
new_pipe_name = data['element1']
new_node_name = data['element2']

node_name = data["node_name"]

self.get_node(node_name).demand_timeseries_list[0].base_value = 0

self.remove_link(new_pipe_name, force=True)
self.get_node(new_node_name)._emitter_coefficient=None
self.remove_node(new_node_name, force=True)


# if data['method'] == 'reservoir':
# self.remove_node(f"{node_name}_nn")

self.expicit_leak = []

def linkBreackage(self, registry):
if len(self.breakage_link) > 0:
raise ValueError("Breakckage is not unliked")

self.breakage_link = {}
pipe_damage_table = registry.getDamageData('PIPE')
broken_pipe_damage_table = pipe_damage_table[pipe_damage_table['damage_type']=='break']

for damage_node, row in broken_pipe_damage_table.iterrows():
if registry.getPipeDamageAttribute('repair',damage_node)==True:
continue
pipe_A, pipe_B, orginal_pipe, node_A, node_B = registry.getBreakData(damage_node)

pipe_name_list = self.pipe_name_list
junction_name_list = self.junction_name_list

iPipe_A_in = pipe_A in pipe_name_list
iPipe_B_in = pipe_B in pipe_name_list
iNode_A_in = node_A in junction_name_list
iNode_B_in = node_B in junction_name_list

if not iPipe_A_in or not iPipe_B_in or not iNode_A_in or not iNode_B_in:
if iPipe_A_in or iPipe_B_in or iNode_A_in or iNode_B_in:
raise ValueError('The damage is partially removed?: '+repr(iPipe_A_in)+', '+repr(iPipe_B_in)+', '+repr(iNode_A_in)+', '+repr(iNode_B_in)+', '+repr(damage_node))
else:
node1 = self.get_link(pipe_A).start_node
node2 = self.get_link(pipe_B).end_node

new_pipe_name = damage_node+'_BLP'
self.add_pipe(new_pipe_name, node1.name, node2.name, length=1, diameter=1*2.54/100, roughness=100)
self.breakage_link[damage_node] = new_pipe_name

def unlinkBreackage(self):
for damage_node, link_pipe_name in self.breakage_link.items():
self.remove_link(link_pipe_name, force=True)

self.breakage_link = {}
self.breakage_link = {}
Loading

0 comments on commit 735043b

Please sign in to comment.