722 lines
28 KiB
Python
722 lines
28 KiB
Python
import json
|
||
from datetime import datetime
|
||
from math import pi, sqrt
|
||
|
||
import pytz
|
||
|
||
import app.services.simulation as simulation
|
||
from app.algorithms.api_ex.run_simulation import (
|
||
run_simulation_ex,
|
||
from_clock_to_seconds_2,
|
||
)
|
||
from app.native.api.project import copy_project
|
||
from app.services.epanet.epanet import Output
|
||
from app.services.scheme_management import store_scheme_info
|
||
from app.services.tjnetwork import *
|
||
|
||
|
||
############################################################
|
||
# burst analysis 01
|
||
############################################################
|
||
def convert_to_local_unit(proj: str, emitters: float) -> float:
|
||
open_project(proj)
|
||
proj_opt = get_option(proj)
|
||
str_unit = proj_opt.get("UNITS")
|
||
|
||
if str_unit == "CMH":
|
||
return emitters * 3.6
|
||
elif str_unit == "LPS":
|
||
return emitters
|
||
elif str_unit == "CMS":
|
||
return emitters / 1000.0
|
||
elif str_unit == "MGD":
|
||
return emitters * 0.0438126
|
||
|
||
# Unknown unit: log and return original value
|
||
print(str_unit)
|
||
return emitters
|
||
|
||
|
||
def burst_analysis(
|
||
name: str,
|
||
modify_pattern_start_time: str,
|
||
burst_ID: list | str = None,
|
||
burst_size: list | float | int = None,
|
||
modify_total_duration: int = 900,
|
||
modify_fixed_pump_pattern: dict[str, list] = None,
|
||
modify_variable_pump_pattern: dict[str, list] = None,
|
||
modify_valve_opening: dict[str, float] = None,
|
||
scheme_name: str = None,
|
||
) -> None:
|
||
"""
|
||
爆管模拟
|
||
:param name: 模型名称,数据库中对应的名字
|
||
:param modify_pattern_start_time: 模拟开始时间,格式为'2024-11-25T09:00:00+08:00'
|
||
:param burst_ID: 爆管管道的ID,选取的是管道,单独传入一个爆管管道,可以是str或list,传入多个爆管管道是用list
|
||
:param burst_size: 爆管管道破裂的孔口面积,和burst_ID列表各位置的ID对应,以cm*cm计算
|
||
:param modify_total_duration: 模拟总历时,秒
|
||
:param modify_fixed_pump_pattern: dict中包含多个水泵模式,str为工频水泵的id,list为修改后的pattern
|
||
:param modify_variable_pump_pattern: dict中包含多个水泵模式,str为变频水泵的id,list为修改后的pattern
|
||
:param modify_valve_opening: dict中包含多个阀门开启度,str为阀门的id,float为修改后的阀门开启度
|
||
:param scheme_name: 方案名称
|
||
:return:
|
||
"""
|
||
scheme_detail: dict = {
|
||
"burst_ID": burst_ID,
|
||
"burst_size": burst_size,
|
||
"modify_total_duration": modify_total_duration,
|
||
"modify_fixed_pump_pattern": modify_fixed_pump_pattern,
|
||
"modify_variable_pump_pattern": modify_variable_pump_pattern,
|
||
"modify_valve_opening": modify_valve_opening,
|
||
}
|
||
print(
|
||
datetime.now(pytz.timezone("Asia/Shanghai")).strftime("%Y-%m-%d %H:%M:%S")
|
||
+ " -- Start Analysis."
|
||
)
|
||
new_name = f"burst_Anal_{name}"
|
||
if have_project(new_name):
|
||
if is_project_open(new_name):
|
||
close_project(new_name)
|
||
delete_project(new_name)
|
||
print(
|
||
datetime.now(pytz.timezone("Asia/Shanghai")).strftime("%Y-%m-%d %H:%M:%S")
|
||
+ " -- Start Copying Database."
|
||
)
|
||
# CopyProjectEx()(name, new_name,
|
||
# ['operation', 'current_operation', 'restore_operation', 'batch_operation', 'operation_table'])
|
||
copy_project(name + "_template", new_name)
|
||
print(
|
||
datetime.now(pytz.timezone("Asia/Shanghai")).strftime("%Y-%m-%d %H:%M:%S")
|
||
+ " -- Start Opening Database."
|
||
)
|
||
open_project(new_name)
|
||
simulation.run_simulation(
|
||
name=new_name,
|
||
simulation_type="manually_temporary",
|
||
modify_pattern_start_time=modify_pattern_start_time,
|
||
)
|
||
print(
|
||
datetime.now(pytz.timezone("Asia/Shanghai")).strftime("%Y-%m-%d %H:%M:%S")
|
||
+ " -- Database Loading OK."
|
||
)
|
||
##step 1 set the emitter coefficient of end node of busrt pipe
|
||
if isinstance(burst_ID, list):
|
||
if (burst_size is not None) and (type(burst_size) is not list):
|
||
return json.dumps("Type mismatch.")
|
||
# 转化为列表形式
|
||
elif isinstance(burst_ID, str):
|
||
burst_ID = [burst_ID]
|
||
if burst_size is not None:
|
||
if isinstance(burst_size, float) or isinstance(burst_size, int):
|
||
burst_size = [burst_size]
|
||
else:
|
||
return json.dumps("Type mismatch.")
|
||
else:
|
||
return json.dumps("Type mismatch.")
|
||
if burst_size is None:
|
||
burst_size = [-1] * len(burst_ID)
|
||
elif len(burst_size) < len(burst_ID):
|
||
burst_size += [-1] * (len(burst_ID) - len(burst_size))
|
||
elif len(burst_size) > len(burst_ID):
|
||
# burst_size = burst_size[:len(burst_ID)]
|
||
return json.dumps("Length mismatch.")
|
||
for burst_ID_, burst_size_ in zip(burst_ID, burst_size):
|
||
pipe = get_pipe(new_name, burst_ID_)
|
||
str_start_node = pipe["node1"]
|
||
str_end_node = pipe["node2"]
|
||
d_pipe = pipe["diameter"] / 1000.0
|
||
if burst_size_ <= 0:
|
||
burst_size_ = 3.14 * d_pipe * d_pipe / 4 / 8
|
||
else:
|
||
burst_size_ = burst_size_ / 10000
|
||
emitter_coeff = (
|
||
0.65 * burst_size_ * sqrt(19.6) * 1000
|
||
) # 1/8开口面积作为coeff,单位 L/S
|
||
emitter_coeff = convert_to_local_unit(new_name, emitter_coeff)
|
||
emitter_node = ""
|
||
if is_junction(new_name, str_end_node):
|
||
emitter_node = str_end_node
|
||
elif is_junction(new_name, str_start_node):
|
||
emitter_node = str_start_node
|
||
old_emitter = get_emitter(new_name, emitter_node)
|
||
if old_emitter != None:
|
||
old_emitter["coefficient"] = emitter_coeff # 爆管的emitter coefficient设置
|
||
else:
|
||
old_emitter = {"junction": emitter_node, "coefficient": emitter_coeff}
|
||
new_emitter = ChangeSet()
|
||
new_emitter.append(old_emitter)
|
||
set_emitter(new_name, new_emitter)
|
||
# step 2. run simulation
|
||
# 涉及关阀计算,可能导致关阀后仍有流量,改为压力驱动PDA
|
||
options = get_option(new_name)
|
||
options["DEMAND MODEL"] = OPTION_DEMAND_MODEL_PDA
|
||
options["REQUIRED PRESSURE"] = "10.0000"
|
||
cs_options = ChangeSet()
|
||
cs_options.append(options)
|
||
set_option(new_name, cs_options)
|
||
# valve_control = None
|
||
# if modify_valve_opening is not None:
|
||
# valve_control = {}
|
||
# for valve in modify_valve_opening:
|
||
# valve_control[valve] = {'status': 'CLOSED'}
|
||
# result = run_simulation_ex(new_name,'realtime', modify_pattern_start_time,
|
||
# end_datetime=modify_pattern_start_time,
|
||
# modify_total_duration=modify_total_duration,
|
||
# modify_pump_pattern=modify_pump_pattern,
|
||
# valve_control=valve_control,
|
||
# downloading_prohibition=True)
|
||
simulation.run_simulation(
|
||
name=new_name,
|
||
simulation_type="extended",
|
||
modify_pattern_start_time=modify_pattern_start_time,
|
||
modify_total_duration=modify_total_duration,
|
||
modify_fixed_pump_pattern=modify_fixed_pump_pattern,
|
||
modify_variable_pump_pattern=modify_variable_pump_pattern,
|
||
modify_valve_opening=modify_valve_opening,
|
||
scheme_type="burst_analysis",
|
||
scheme_name=scheme_name,
|
||
)
|
||
# step 3. restore the base model status
|
||
# execute_undo(name) #有疑惑
|
||
if is_project_open(new_name):
|
||
close_project(new_name)
|
||
delete_project(new_name)
|
||
# 存储方案信息到 PG 数据库
|
||
store_scheme_info(
|
||
name=name,
|
||
scheme_name=scheme_name,
|
||
scheme_type="burst_analysis",
|
||
username="admin",
|
||
scheme_start_time=modify_pattern_start_time,
|
||
scheme_detail=scheme_detail,
|
||
)
|
||
|
||
|
||
############################################################
|
||
# valve closing analysis 02
|
||
############################################################
|
||
def valve_close_analysis(
|
||
name: str,
|
||
modify_pattern_start_time: str,
|
||
modify_total_duration: int = 900,
|
||
modify_valve_opening: dict[str, float] = None,
|
||
scheme_name: str = None,
|
||
) -> None:
|
||
"""
|
||
关阀模拟
|
||
:param name: 模型名称,数据库中对应的名字
|
||
:param modify_pattern_start_time: 模拟开始时间,格式为'2024-11-25T09:00:00+08:00'
|
||
:param modify_total_duration: 模拟总历时,秒
|
||
:param modify_valve_opening: dict中包含多个阀门开启度,str为阀门的id,float为修改后的阀门开启度
|
||
:param scheme_name: 方案名称
|
||
:return:
|
||
"""
|
||
print(
|
||
datetime.now(pytz.timezone("Asia/Shanghai")).strftime("%Y-%m-%d %H:%M:%S")
|
||
+ " -- Start Analysis."
|
||
)
|
||
new_name = f"valve_close_Anal_{name}"
|
||
if have_project(new_name):
|
||
if is_project_open(new_name):
|
||
close_project(new_name)
|
||
delete_project(new_name)
|
||
print(
|
||
datetime.now(pytz.timezone("Asia/Shanghai")).strftime("%Y-%m-%d %H:%M:%S")
|
||
+ " -- Start Copying Database."
|
||
)
|
||
# CopyProjectEx()(name, new_name,
|
||
# ['operation', 'current_operation', 'restore_operation', 'batch_operation', 'operation_table'])
|
||
copy_project(name + "_template", new_name)
|
||
print(
|
||
datetime.now(pytz.timezone("Asia/Shanghai")).strftime("%Y-%m-%d %H:%M:%S")
|
||
+ " -- Start Opening Database."
|
||
)
|
||
open_project(new_name)
|
||
print(
|
||
datetime.now(pytz.timezone("Asia/Shanghai")).strftime("%Y-%m-%d %H:%M:%S")
|
||
+ " -- Database Loading OK."
|
||
)
|
||
# step 1. change the valves status to 'closed'
|
||
# for valve in valves:
|
||
# if not is_valve(new_name,valve):
|
||
# result='ID:{}is not a valve type'.format(valve)
|
||
# return result
|
||
# cs=ChangeSet()
|
||
# status=get_status(new_name,valve)
|
||
# status['status']='CLOSED'
|
||
# cs.append(status)
|
||
# set_status(new_name,cs)
|
||
# step 2. run simulation
|
||
# 涉及关阀计算,可能导致关阀后仍有流量,改为压力驱动PDA
|
||
options = get_option(new_name)
|
||
options["DEMAND MODEL"] = OPTION_DEMAND_MODEL_PDA
|
||
options["REQUIRED PRESSURE"] = "20.0000"
|
||
cs_options = ChangeSet()
|
||
cs_options.append(options)
|
||
set_option(new_name, cs_options)
|
||
# result = run_simulation_ex(new_name,'realtime', modify_pattern_start_time, modify_pattern_start_time, modify_total_duration,
|
||
# downloading_prohibition=True)
|
||
simulation.run_simulation(
|
||
name=new_name,
|
||
simulation_type="extended",
|
||
modify_pattern_start_time=modify_pattern_start_time,
|
||
modify_total_duration=modify_total_duration,
|
||
modify_valve_opening=modify_valve_opening,
|
||
scheme_type="valve_close_Analysis",
|
||
scheme_name=scheme_name,
|
||
)
|
||
# step 3. restore the base model
|
||
# for valve in valves:
|
||
# execute_undo(name)
|
||
if is_project_open(new_name):
|
||
close_project(new_name)
|
||
delete_project(new_name)
|
||
# return result
|
||
|
||
|
||
############################################################
|
||
# flushing analysis 03
|
||
# Pipe_Flushing_Analysis(prj_name,date_time, Valve_id_list, Drainage_Node_Id, Flushing_flow[opt], Flushing_duration[opt])->out_file:string
|
||
############################################################
|
||
def flushing_analysis(
|
||
name: str,
|
||
modify_pattern_start_time: str,
|
||
modify_total_duration: int = 900,
|
||
modify_valve_opening: dict[str, float] = None,
|
||
drainage_node_ID: str = None,
|
||
flushing_flow: float = 0,
|
||
scheme_name: str = None,
|
||
) -> None:
|
||
"""
|
||
管道冲洗模拟
|
||
:param name: 模型名称,数据库中对应的名字
|
||
:param modify_pattern_start_time: 模拟开始时间,格式为'2024-11-25T09:00:00+08:00'
|
||
:param modify_total_duration: 模拟总历时,秒
|
||
:param modify_valve_opening: dict中包含多个阀门开启度,str为阀门的id,float为修改后的阀门开启度
|
||
:param drainage_node_ID: 冲洗排放口所在节点ID
|
||
:param flushing_flow: 冲洗水量,传入参数单位为m3/h
|
||
:param scheme_name: 方案名称
|
||
:return:
|
||
"""
|
||
scheme_detail: dict = {
|
||
"duration": modify_total_duration,
|
||
"valve_opening": modify_valve_opening,
|
||
"drainage_node_ID": drainage_node_ID,
|
||
"flushing_flow": flushing_flow,
|
||
}
|
||
print(
|
||
datetime.now(pytz.timezone("Asia/Shanghai")).strftime("%Y-%m-%d %H:%M:%S")
|
||
+ " -- Start Analysis."
|
||
)
|
||
new_name = f"flushing_Anal_{name}"
|
||
if have_project(new_name):
|
||
if is_project_open(new_name):
|
||
close_project(new_name)
|
||
delete_project(new_name)
|
||
# if is_project_open(name):
|
||
# close_project(name)
|
||
print(
|
||
datetime.now(pytz.timezone("Asia/Shanghai")).strftime("%Y-%m-%d %H:%M:%S")
|
||
+ " -- Start Copying Database."
|
||
)
|
||
# CopyProjectEx()(name, new_name,
|
||
# ['operation', 'current_operation', 'restore_operation', 'batch_operation', 'operation_table'])
|
||
copy_project(name + "_template", new_name)
|
||
print(
|
||
datetime.now(pytz.timezone("Asia/Shanghai")).strftime("%Y-%m-%d %H:%M:%S")
|
||
+ " -- Start Opening Database."
|
||
)
|
||
open_project(new_name)
|
||
print(
|
||
datetime.now(pytz.timezone("Asia/Shanghai")).strftime("%Y-%m-%d %H:%M:%S")
|
||
+ " -- Database Loading OK."
|
||
)
|
||
if not is_junction(new_name, drainage_node_ID):
|
||
return "Wrong Drainage node type"
|
||
# step 1. change the valves status to 'closed'
|
||
# for valve, valve_k in zip(valves, valves_k):
|
||
# cs=ChangeSet()
|
||
# status=get_status(new_name,valve)
|
||
# # status['status']='CLOSED'
|
||
# if valve_k == 0:
|
||
# status['status'] = 'CLOSED'
|
||
# elif valve_k < 1:
|
||
# status['status'] = 'OPEN'
|
||
# status['setting'] = 0.1036 * pow(valve_k, -3.105)
|
||
# cs.append(status)
|
||
# set_status(new_name,cs)
|
||
units = get_option(new_name)
|
||
# step 2. set the emitter coefficient of drainage node or add flush flow to the drainage node
|
||
emitter_demand = get_demand(new_name, drainage_node_ID)
|
||
cs = ChangeSet()
|
||
if flushing_flow > 0:
|
||
for r in emitter_demand["demands"]:
|
||
if units == "LPS":
|
||
r["demand"] += flushing_flow / 3.6
|
||
elif units == "CMH":
|
||
r["demand"] += flushing_flow
|
||
cs.append(emitter_demand)
|
||
set_demand(new_name, cs)
|
||
else:
|
||
pipes = get_node_links(new_name, drainage_node_ID)
|
||
flush_diameter = 50
|
||
for pipe in pipes:
|
||
d = get_pipe(new_name, pipe)["diameter"]
|
||
if flush_diameter < d:
|
||
flush_diameter = d
|
||
flush_diameter /= 1000
|
||
emitter_coeff = (
|
||
0.65 * 3.14 * (flush_diameter * flush_diameter / 4) * sqrt(19.6) * 1000
|
||
) # 全开口面积作为coeff
|
||
|
||
old_emitter = get_emitter(new_name, drainage_node_ID)
|
||
if old_emitter != None:
|
||
old_emitter["coefficient"] = emitter_coeff # 爆管的emitter coefficient设置
|
||
else:
|
||
old_emitter = {"junction": drainage_node_ID, "coefficient": emitter_coeff}
|
||
new_emitter = ChangeSet()
|
||
new_emitter.append(old_emitter)
|
||
set_emitter(new_name, new_emitter)
|
||
# step 3. run simulation
|
||
# 涉及关阀计算,可能导致关阀后仍有流量,改为压力驱动PDA
|
||
options = get_option(new_name)
|
||
options["DEMAND MODEL"] = OPTION_DEMAND_MODEL_PDA
|
||
options["REQUIRED PRESSURE"] = "20.0000"
|
||
cs_options = ChangeSet()
|
||
cs_options.append(options)
|
||
set_option(new_name, cs_options)
|
||
# result = run_simulation_ex(new_name,'realtime', modify_pattern_start_time, modify_pattern_start_time, modify_total_duration,
|
||
# downloading_prohibition=True)
|
||
simulation.run_simulation(
|
||
name=new_name,
|
||
simulation_type="extended",
|
||
modify_pattern_start_time=modify_pattern_start_time,
|
||
modify_total_duration=modify_total_duration,
|
||
modify_valve_opening=modify_valve_opening,
|
||
scheme_type="flushing_analysis",
|
||
scheme_name=scheme_name,
|
||
)
|
||
# step 4. restore the base model
|
||
if is_project_open(new_name):
|
||
close_project(new_name)
|
||
delete_project(new_name)
|
||
# return result
|
||
# 存储方案信息到 PG 数据库
|
||
store_scheme_info(
|
||
name=name,
|
||
scheme_name=scheme_name,
|
||
scheme_type="flushing_analysis",
|
||
username="admin",
|
||
scheme_start_time=modify_pattern_start_time,
|
||
scheme_detail=scheme_detail,
|
||
)
|
||
|
||
|
||
############################################################
|
||
# Contaminant simulation 04
|
||
#
|
||
############################################################
|
||
def contaminant_simulation(
|
||
name: str,
|
||
modify_pattern_start_time: str, # 模拟开始时间,格式为'2024-11-25T09:00:00+08:00'
|
||
modify_total_duration: int, # 模拟总历时,秒
|
||
source: str, # 污染源节点ID
|
||
concentration: float, # 污染源浓度,单位mg/L
|
||
scheme_name: str = None,
|
||
source_pattern: str = None, # 污染源时间变化模式名称
|
||
) -> None:
|
||
"""
|
||
污染模拟
|
||
:param name: 模型名称,数据库中对应的名字
|
||
:param modify_pattern_start_time: 模拟开始时间,格式为'2024-11-25T09:00:00+08:00'
|
||
:param modify_total_duration: 模拟总历时,秒
|
||
:param source: 污染源所在的节点ID
|
||
:param concentration: 污染源位置处的浓度,单位mg/L。默认的污染模拟setting为SOURCE_TYPE_CONCEN(改为SOURCE_TYPE_SETPOINT)
|
||
:param source_pattern: 污染源的时间变化模式,若不传入则默认以恒定浓度持续模拟,时间长度等于duration;
|
||
若传入,则格式为{1.0,0.5,1.1}等系数列表pattern_step模拟等于模型的hydraulic time step
|
||
:param scheme_name: 方案名称
|
||
:return:
|
||
"""
|
||
scheme_detail: dict = {
|
||
"source": source,
|
||
"concentration": concentration,
|
||
"duration": modify_total_duration,
|
||
"pattern": source_pattern,
|
||
}
|
||
print(
|
||
datetime.now(pytz.timezone("Asia/Shanghai")).strftime("%Y-%m-%d %H:%M:%S")
|
||
+ " -- Start Analysis."
|
||
)
|
||
new_name = f"contaminant_Sim_{name}"
|
||
if have_project(new_name):
|
||
if is_project_open(new_name):
|
||
close_project(new_name)
|
||
delete_project(new_name)
|
||
# if is_project_open(name):
|
||
# close_project(name)
|
||
print(
|
||
datetime.now(pytz.timezone("Asia/Shanghai")).strftime("%Y-%m-%d %H:%M:%S")
|
||
+ " -- Start Copying Database."
|
||
)
|
||
# CopyProjectEx()(name, new_name,
|
||
# ['operation', 'current_operation', 'restore_operation', 'batch_operation', 'operation_table'])
|
||
copy_project(name + "_template", new_name)
|
||
print(
|
||
datetime.now(pytz.timezone("Asia/Shanghai")).strftime("%Y-%m-%d %H:%M:%S")
|
||
+ " -- Start Opening Database."
|
||
)
|
||
open_project(new_name)
|
||
print(
|
||
datetime.now(pytz.timezone("Asia/Shanghai")).strftime("%Y-%m-%d %H:%M:%S")
|
||
+ " -- Database Loading OK."
|
||
)
|
||
dic_time = get_time(new_name)
|
||
dic_time["QUALITY TIMESTEP"] = "0:05:00"
|
||
cs = ChangeSet()
|
||
cs.operations.append(dic_time)
|
||
set_time(new_name, cs) # set QUALITY TIMESTEP
|
||
time_option = get_time(new_name)
|
||
hydraulic_step = time_option["HYDRAULIC TIMESTEP"]
|
||
secs = from_clock_to_seconds_2(hydraulic_step)
|
||
operation_step = 0
|
||
# step 1. set duration
|
||
if modify_total_duration == None:
|
||
modify_total_duration = secs
|
||
# step 2. set pattern
|
||
if source_pattern != None:
|
||
pt = get_pattern(new_name, source_pattern)
|
||
if pt == None:
|
||
str_response = str("cant find source_pattern")
|
||
return str_response
|
||
else:
|
||
cs_pattern = ChangeSet()
|
||
pt = {}
|
||
factors = []
|
||
tmp_duration = modify_total_duration
|
||
while tmp_duration > 0:
|
||
factors.append(1.0)
|
||
tmp_duration = tmp_duration - secs
|
||
pt["id"] = "contam_pt"
|
||
pt["factors"] = factors
|
||
cs_pattern.append(pt)
|
||
add_pattern(new_name, cs_pattern)
|
||
operation_step += 1
|
||
# step 3. set source/initial quality
|
||
# source quality
|
||
cs_source = ChangeSet()
|
||
source_schema = {
|
||
"node": source,
|
||
"s_type": SOURCE_TYPE_SETPOINT,
|
||
"strength": concentration,
|
||
"pattern": pt["id"],
|
||
}
|
||
cs_source.append(source_schema)
|
||
source_node = get_source(new_name, source)
|
||
if len(source_node) == 0:
|
||
add_source(new_name, cs_source)
|
||
else:
|
||
set_source(new_name, cs_source)
|
||
dict_demand = get_demand(new_name, source)
|
||
for demands in dict_demand["demands"]:
|
||
dict_demand["demands"][dict_demand["demands"].index(demands)]["demand"] = -1
|
||
dict_demand["demands"][dict_demand["demands"].index(demands)]["pattern"] = None
|
||
cs = ChangeSet()
|
||
cs.append(dict_demand)
|
||
set_demand(new_name, cs) # set inflow node
|
||
# # initial quality
|
||
# dict_quality = get_quality(new_name, source)
|
||
# dict_quality['quality'] = concentration
|
||
# cs = ChangeSet()
|
||
# cs.append(dict_quality)
|
||
# set_quality(new_name, cs)
|
||
operation_step += 1
|
||
# step 4 set option of quality to chemical
|
||
opt = get_option(new_name)
|
||
opt["QUALITY"] = OPTION_QUALITY_CHEMICAL
|
||
cs_option = ChangeSet()
|
||
cs_option.append(opt)
|
||
set_option(new_name, cs_option)
|
||
operation_step += 1
|
||
# step 5. run simulation
|
||
# result = run_simulation_ex(new_name,'realtime', modify_pattern_start_time, modify_pattern_start_time, modify_total_duration,
|
||
# downloading_prohibition=True)
|
||
simulation.run_simulation(
|
||
name=new_name,
|
||
simulation_type="extended",
|
||
modify_pattern_start_time=modify_pattern_start_time,
|
||
modify_total_duration=modify_total_duration,
|
||
scheme_type="contaminant_analysis",
|
||
scheme_name=scheme_name,
|
||
)
|
||
|
||
# for i in range(1,operation_step):
|
||
# execute_undo(name)
|
||
if is_project_open(new_name):
|
||
close_project(new_name)
|
||
delete_project(new_name)
|
||
# 存储方案信息到 PG 数据库
|
||
store_scheme_info(
|
||
name=name,
|
||
scheme_name=scheme_name,
|
||
scheme_type="contaminant_analysis",
|
||
username="admin",
|
||
scheme_start_time=modify_pattern_start_time,
|
||
scheme_detail=scheme_detail,
|
||
)
|
||
|
||
|
||
############################################################
|
||
# age analysis 05 ***水龄模拟目前还没和实时模拟打通,不确定是否需要,先不要使用***
|
||
############################################################
|
||
|
||
|
||
def age_analysis(
|
||
name: str, modify_pattern_start_time: str, modify_total_duration: int = 900
|
||
) -> None:
|
||
"""
|
||
水龄模拟
|
||
:param name: 模型名称,数据库中对应的名字
|
||
:param modify_pattern_start_time: 模拟开始时间,格式为'2024-11-25T09:00:00+08:00'
|
||
:param modify_total_duration: 模拟总历时,秒
|
||
:return:
|
||
"""
|
||
print(
|
||
datetime.now(pytz.timezone("Asia/Shanghai")).strftime("%Y-%m-%d %H:%M:%S")
|
||
+ " -- Start Analysis."
|
||
)
|
||
new_name = f"age_Anal_{name}"
|
||
if have_project(new_name):
|
||
if is_project_open(new_name):
|
||
close_project(new_name)
|
||
delete_project(new_name)
|
||
# if is_project_open(name):
|
||
# close_project(name)
|
||
print(
|
||
datetime.now(pytz.timezone("Asia/Shanghai")).strftime("%Y-%m-%d %H:%M:%S")
|
||
+ " -- Start Copying Database."
|
||
)
|
||
# CopyProjectEx()(name, new_name,
|
||
# ['operation', 'current_operation', 'restore_operation', 'batch_operation', 'operation_table'])
|
||
copy_project(name + "_template", new_name)
|
||
print(
|
||
datetime.now(pytz.timezone("Asia/Shanghai")).strftime("%Y-%m-%d %H:%M:%S")
|
||
+ " -- Start Opening Database."
|
||
)
|
||
open_project(new_name)
|
||
print(
|
||
datetime.now(pytz.timezone("Asia/Shanghai")).strftime("%Y-%m-%d %H:%M:%S")
|
||
+ " -- Database Loading OK."
|
||
)
|
||
# step 1. run simulation
|
||
|
||
result = run_simulation_ex(
|
||
new_name,
|
||
"realtime",
|
||
modify_pattern_start_time,
|
||
modify_total_duration,
|
||
downloading_prohibition=True,
|
||
)
|
||
# step 2. restore the base model status
|
||
# execute_undo(name) #有疑惑
|
||
if is_project_open(new_name):
|
||
close_project(new_name)
|
||
delete_project(new_name)
|
||
output = Output("./temp/{}.db.out".format(new_name))
|
||
# element_name = output.element_name()
|
||
# node_name = element_name['nodes']
|
||
# link_name = element_name['links']
|
||
nodes_age = []
|
||
node_result = output.node_results()
|
||
for node in node_result:
|
||
nodes_age.append(node["result"][-1]["quality"])
|
||
links_age = []
|
||
link_result = output.link_results()
|
||
for link in link_result:
|
||
links_age.append(link["result"][-1]["quality"])
|
||
age_result = {"nodes": nodes_age, "links": links_age}
|
||
# age_result = {'nodes': nodes_age, 'links': links_age, 'nodeIDs': node_name, 'linkIDs': link_name}
|
||
return json.dumps(age_result)
|
||
|
||
|
||
############################################################
|
||
# pressure regulation 06
|
||
############################################################
|
||
|
||
|
||
def pressure_regulation(
|
||
name: str,
|
||
modify_pattern_start_time: str,
|
||
modify_total_duration: int = 900,
|
||
modify_tank_initial_level: dict[str, float] = None,
|
||
modify_fixed_pump_pattern: dict[str, list] = None,
|
||
modify_variable_pump_pattern: dict[str, list] = None,
|
||
scheme_name: str = None,
|
||
) -> None:
|
||
"""
|
||
区域调压模拟,用来模拟未来15分钟内,开关水泵对区域压力的影响
|
||
:param name: 模型名称,数据库中对应的名字
|
||
:param modify_pattern_start_time: 模拟开始时间,格式为'2024-11-25T09:00:00+08:00'
|
||
:param modify_total_duration: 模拟总历时,秒
|
||
:param modify_tank_initial_level: dict中包含多个水塔,str为水塔的id,float为修改后的initial_level
|
||
:param modify_fixed_pump_pattern: dict中包含多个水泵模式,str为工频水泵的id,list为修改后的pattern
|
||
:param modify_variable_pump_pattern: dict中包含多个水泵模式,str为变频水泵的id,list为修改后的pattern
|
||
:param scheme_name: 模拟方案名称
|
||
:return:
|
||
"""
|
||
print(
|
||
datetime.now(pytz.timezone("Asia/Shanghai")).strftime("%Y-%m-%d %H:%M:%S")
|
||
+ " -- Start Analysis."
|
||
)
|
||
new_name = f"pressure_regulation_{name}"
|
||
if have_project(new_name):
|
||
if is_project_open(new_name):
|
||
close_project(new_name)
|
||
delete_project(new_name)
|
||
# if is_project_open(name):
|
||
# close_project(name)
|
||
print(
|
||
datetime.now(pytz.timezone("Asia/Shanghai")).strftime("%Y-%m-%d %H:%M:%S")
|
||
+ " -- Start Copying Database."
|
||
)
|
||
# CopyProjectEx()(name, new_name,
|
||
# ['operation', 'current_operation', 'restore_operation', 'batch_operation', 'operation_table'])
|
||
copy_project(name + "_template", new_name)
|
||
print(
|
||
datetime.now(pytz.timezone("Asia/Shanghai")).strftime("%Y-%m-%d %H:%M:%S")
|
||
+ " -- Start Opening Database."
|
||
)
|
||
open_project(new_name)
|
||
print(
|
||
datetime.now(pytz.timezone("Asia/Shanghai")).strftime("%Y-%m-%d %H:%M:%S")
|
||
+ " -- Database Loading OK."
|
||
)
|
||
# 全部关泵后,压力计算不合理,改为压力驱动PDA
|
||
options = get_option(new_name)
|
||
options["DEMAND MODEL"] = OPTION_DEMAND_MODEL_PDA
|
||
options["REQUIRED PRESSURE"] = "15.0000"
|
||
cs_options = ChangeSet()
|
||
cs_options.append(options)
|
||
set_option(new_name, cs_options)
|
||
# result = run_simulation_ex(name=new_name,
|
||
# simulation_type='realtime',
|
||
# start_datetime=start_datetime,
|
||
# duration=900,
|
||
# pump_control=pump_control,
|
||
# tank_initial_level_control=tank_initial_level_control,
|
||
# downloading_prohibition=True)
|
||
simulation.run_simulation(
|
||
name=new_name,
|
||
simulation_type="extended",
|
||
modify_pattern_start_time=modify_pattern_start_time,
|
||
modify_total_duration=modify_total_duration,
|
||
modify_tank_initial_level=modify_tank_initial_level,
|
||
modify_fixed_pump_pattern=modify_fixed_pump_pattern,
|
||
modify_variable_pump_pattern=modify_variable_pump_pattern,
|
||
scheme_type="pressure_regulation",
|
||
scheme_name=scheme_name,
|
||
)
|
||
if is_project_open(new_name):
|
||
close_project(new_name)
|
||
delete_project(new_name)
|
||
# return result
|