系列文章目录
https://editor.csdn.net/md/?articleId=115612518
前文day4,利用wntr创建了一个新的经典配水管网例子
文章目录
前言
本文将探究wntr的Pressure dependent demand simulation,并且使用emitter来定义泄漏点,与wntr中的新添加功能leak model做对比,在管网中查看添加泄漏点的数据,探究定位泄漏点的思路。
一、压力驱动模型与泄漏点的基础知识
1.需求驱动和压力驱动
我们已经在day3的学习中了解到需求驱动和压力驱动模拟器的区别:
在需求驱动(DD)的的仿真中,系统中的压力取决于节点的需求。在已知并满足节点需求的情况下,求解上述质量平衡和头部损失方程。这一假设在正常运行条件下是合理的,也适用于网络设计。这两种模拟器都可以使用需求驱动模拟来运行液压。
在导致低压条件的情况下(例如,消防、停电、管道泄漏),用户并不总是收到他们所要求的需求,因此建议采用压力驱动模型模拟。在压力驱动的模拟中,交付的需求取决于压力。上述的质量平衡和水头损失方程是通过同时确定需求和网络压力和流量来求解的。根据以下压力-需求关系,这两个模拟器都可以使用压力相关的需求模拟来运行液压。
通过设置option.hydraulic.demand_model的参数来选择压力驱动和需求驱动。
wn.options.hydraulic.demand_model = 'DD'#需求驱动
wn.options.hydraulic.demand_model = 'PDD'#压力驱动
由于我们主要的问题是研究管道泄漏爆管,所以我们采用压力驱动模拟,该模拟下交付的水量取决于压力,实际需水量(交付水量),和设计水量如下图所示:
要满足设计水量所需要的的水压叫做设计需水压(required pressure),当低于最低压力时,用户将不会获得任何用水,这两个参数都可以设置:
wn.options.hydraulic.required_pressure = 21.097 # 30 psi = 21.097 m
wn.options.hydraulic.minimum_pressure = 3.516 # 5 psi = 3.516 m
当使用WNTRSimultor时,所需的压力和最小压力可以在整个网络中变化。默认情况下,每个节点的所需压力和最小压力设置为None和液压选项中的全局值。如果用户定义了连接点的必需压力或最小压力,则该值将覆盖全局值。下面的示例单独修改了连接点121所需的压力和最小压力。
junction = wn.get_node('121')
junction.required_pressure = 14.065 # 20 psi = 14.065 m
junction.minimum_pressure = 0.352 # 0.5 psi = 0.352 m
2.扩散器emitter与add_leak
EPANET中的扩散器EMITTER,扩散器是与连接节点相关的设备,通过喷嘴或者控制模拟流量排向大气,用于模拟消火栓系统和灌溉系统,也可以模拟与连接节点相连的管道的泄漏,或者计算连接节点的消防流量。其流量是节点压力水头的函数:
式中 q 表示节点流量; C 表示扩散器系数; p 表示节点压力; γ 表示扩散器指数。
在 EPANET 中,扩散器作为连接节点的属性,而不是作为独立的管网组件,即可以通过修改节点属性将节点变成扩散器。
WNTRSimulator包含使用泄漏模型向网络添加泄漏的功能.因此,WNTRSimulator没有使用在水网络模型选项中定义的发射器系数,WNTR中的泄漏模型公式如下图所示:
在节点处添加泄漏
node = wn.get_node('123')
node.add_leak(wn, area=0.05, start_time=2*3600, end_time=12*3600)
3.WNTRSimulator多次模拟功能:
重置初始值并使用相同的水网络模型重新模拟。初始值包括模拟时间、油罐压头、储液罐压头、管道状态、泵状态和阀门状态。
暂停水力模拟,改变网络操作,然后重新启动模拟
将水网络模型和结果保存到文件中,并重新加载,以便日后分析,以下代码就是进行了两次模拟,第一次模拟了10小时,然后重新开始模拟了24小时,前10小时和后14小时可以分开单独分析
wn.options.time.duration = 10*3600
sim = wntr.sim.WNTRSimulator(wn)
first_10_hours_results = sim.run_sim()
wn.options.time.duration = 24*3600
sim = wntr.sim.WNTRSimulator(wn)
last_14_hours_results = sim.run_sim()
要从零时重新开始模拟,用户有几个选项:
1.利用现有的水网模型,重置初始条件。初始条件包括模拟时间、油罐压头、储液罐压头、管道状态、泵状态和阀门状态。当在两次模拟之间只有初始条件发生变化时,此选项非常有用。
wn.reset_initial_values()
2.将水网络模型保存到一个文件中,并在每次运行模拟时重新加载该文件。pickle文件通常用于此目的。pickle文件是用于序列化和反序列化Python对象的二进制文件。当水网络模型包含不能使用选项1重置的自定义控件时,或者当用户想在模拟之间改变操作时,这个选项非常有用。
在模拟之前保存一下:
import pickle
f=open('wn.pickle','wb')
pickle.dump(wn,f)
f.close()
sim = wntr.sim.WNTRSimulator(wn)
results = sim.run_sim()
reload pickle文件模拟
f=open('wn.pickle','rb')
wn = pickle.load(f)
f.close()
sim = wntr.sim.WNTRSimulator(wn)
results = sim.run_sim()
二、开始模拟
利用需求驱动进行模拟是,管网一共要满足如下方程:
质量守恒(连续性方程):
能量守恒(结点能量方程 WNTR中采用海曾威廉公式计算水损):
需水量与结点压力方程(压力驱动模型PDD要求):
1.利用创建好的管网进行模拟
该管网模型是我们之前在day4已经创建好的管网
我们添加在结点4添加了一个漏损点,观察link4的流量
import wntr
import matplotlib.pyplot as plt
#导入该模型
wn = wntr.network.WaterNetworkModel(r'./stduymodel1.inp')
#选择建模为压力驱动类型
wn.options.hydraulic.demand_model = 'PDD'
#在结点4添加一个爆管点
node4 = wn.get_node("n4")
node4.add_leak(wn,area=0.01,discharge_coeff=0.75,start_time=6*3600,end_time=12*3600)
#使用WNTRSimulator模拟爆管
sim = wntr.sim.WNTRSimulator(wn)
results = sim.run_sim()
#画图
plt.figure(figsize=(20,10))
plt.xticks(range(0,172800,3600),range(0,49))
flowrate_at_link4 = results.link['flowrate'].loc[:,'4']
print(flowrate_at_link4)
ax = flowrate_at_link4.plot()
ax.set(ylim = (0,0.1))
text = ax.set_xlabel("Time (hours)")
text = ax.set_ylabel("Flowrate")
plt.show()
我们再看看没有添加爆管点影响下的link4:
sim = wntr.sim.WNTRSimulator(wn)
results = sim.run_sim()
plt.figure(figsize=(20,10))
plt.xticks(range(0,172800,3600),range(0,49))
flowrate_at_link4 = results.link['flowrate'].loc[:,'4']
print(flowrate_at_link4)
ax = flowrate_at_link4.plot()
ax.set(ylim = (0,0.1))
text = ax.set_xlabel("Time (hours)")
text = ax.set_ylabel("Flowrate")
plt.show()
结果很明显,我们结点产生漏损的时候是第6小时开始,一直到12小时,一开始我们的流量剧烈下降,之后慢慢回升,终于在12小时的时候恢复正常。
压力也是类似:
当有漏损时
import wntr
import matplotlib.pyplot as plt
wn = wntr.network.WaterNetworkModel(r'./stduymodel1.inp')
wn.options.hydraulic.demand_model = 'PDD'
node4 = wn.get_node("n4")
node4.add_leak(wn,area=0.01,discharge_coeff=0.75,start_time=6*3600,end_time=12*3600)
sim = wntr.sim.WNTRSimulator(wn)
results = sim.run_sim()
plt.figure(figsize=(20,10))
plt.xticks(range(0,172800,3600),range(0,49))
pressure_at_node4 = results.node['head'].loc[:,'n4']
print(pressure_at_node4)
ax = pressure_at_node4.plot()
ax.set(ylim = (20,50))
text = ax.set_xlabel("Time (hours)")
text = ax.set_ylabel("head(m)")
plt.show()
下图为产生漏损时的n4
无漏损时:
效果明显。看看n4点的泄漏对较远的点n7:
下图是产生漏损的n7的水头时间序列:
下图是没有漏损点的n7水头,影响直到22小时才逐渐消失:
漏损在12小时时就已经停止,但是从该事件序列来看,漏损结束以后仍然对节点和管段有影响。如何判断漏损,定位漏损,在之后文献的阅读中需要更加注意。
2.在管段link中添加泄漏点
WNTR包含函数split_pipe和break_pipe来分割或破坏管道。通过这种方法可以在任意位置添加漏损点:
对于管道分裂,通过向模型中添加新的连接和新管道,原始管道被分裂成两个管道。对于管道破裂,通过向模型中添加两个新的连接和一个新管道,原来的管道被分成两个断开的管道。需要注意的是:当管道破裂时,流体不再可能从破裂的一端流向另一端。与增加泄漏的管道破裂相比,这更有可能引入不可转换的液压系统。
新连接的base_demand为0,默认demand_pattern。新结点的高程和坐标是基于原始管道端点之间的线性插值。新管道与原管道直径相同,粗糙度相同,损失较小,基础状态相同。
在新管道上不增加止回阀。由于新管道可以连接在原管道的起点或终点,用户可以控制是在止回阀之前还是之后发生分裂。
没有向新管道添加控件;原始管道保留任何控件。
比如下面的例子是把link4拆成两段 分别为link4和link4_B,中建添加一个结点link4_node,并添加泄漏:
wn = wntr.morph.split_pipe(wn, '4', '4_B', '4_node')
leak_node = wn.get_node('4_node')
leak_node.add_leak(wn, area=0.05, start_time=2*3600, end_time=12*3600)
通过该操作,理论上可以在任何管段,任何结点添加泄漏点。