From 0f18a856418cff345de0a14d1f07619558f47f5c Mon Sep 17 00:00:00 2001 From: DingZQ Date: Sat, 22 Feb 2025 17:19:47 +0800 Subject: [PATCH] Update online_anaylysis --- online_Analysis.py | 313 +++++++++++++++++++++++++++++---------------- 1 file changed, 201 insertions(+), 112 deletions(-) diff --git a/online_Analysis.py b/online_Analysis.py index 63910af..55a0feb 100644 --- a/online_Analysis.py +++ b/online_Analysis.py @@ -13,36 +13,41 @@ from psycopg import sql import pandas as pd import csv import chardet +import simulation ############################################################ # burst analysis 01 ############################################################ -def burst_analysis(prj_name, date_time, burst_ID: list | str, burst_size: list | float | int = None, duration=900, pump_control=None, valve_closed=None) -> str: - ''' - burst 分析 - :param prj_name: - :param date_time: - :param burst_ID: - :param burst_siz: - :param duration: - :param pump_control: - :param valve_closed: +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: - ''' - + """ print(datetime.now(pytz.timezone('Asia/Shanghai')).strftime("%Y-%m-%d %H:%M:%S") + " -- Start Analysis.") - new_name = f'burst_Anal_{prj_name}' + 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) - if is_project_open(prj_name): - close_project(prj_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()(prj_name, new_name, + CopyProjectEx()(name, new_name, ['operation', 'current_operation', 'restore_operation', 'batch_operation', 'operation_table']) print(datetime.now(pytz.timezone('Asia/Shanghai')).strftime("%Y-%m-%d %H:%M:%S") + " -- Start Opening Database.") open_project(new_name) @@ -108,43 +113,56 @@ def burst_analysis(prj_name, date_time, burst_ID: list | str, burst_size: list | cs_options.append(options) set_option(new_name, cs_options) - valve_control = None - if valve_closed is not None: - valve_control = {} - for valve in valve_closed: - valve_control[valve] = {'status': 'CLOSED'} - - result = run_simulation_ex(new_name,'realtime', date_time, - end_datetime=date_time, - duration=duration, - pump_control=pump_control, - valve_control=valve_control, - downloading_prohibition=True) + # 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(prj_name) #有疑惑 + # execute_undo(name) #有疑惑 if is_project_open(new_name): close_project(new_name) delete_project(new_name) - - return result + + # return result ############################################################ # valve closing analysis 02 ############################################################ -def valve_close_analysis(prj_name, date_time, valves, duration=None)->str: +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_{prj_name}' + 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) - if is_project_open(prj_name): - close_project(prj_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()(prj_name, new_name, + CopyProjectEx()(name, new_name, ['operation', 'current_operation', 'restore_operation', 'batch_operation', 'operation_table']) print(datetime.now(pytz.timezone('Asia/Shanghai')).strftime("%Y-%m-%d %H:%M:%S") + " -- Start Opening Database.") open_project(new_name) @@ -152,15 +170,15 @@ def valve_close_analysis(prj_name, date_time, valves, duration=None)->str: #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) + # 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 @@ -172,35 +190,51 @@ def valve_close_analysis(prj_name, date_time, valves, duration=None)->str: cs_options.append(options) set_option(new_name, cs_options) - result = run_simulation_ex(new_name,'realtime', date_time, date_time, duration, - downloading_prohibition=True) + # 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=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(prj_name) + # execute_undo(name) if is_project_open(new_name): close_project(new_name) delete_project(new_name) - return result + # 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(prj_name, date_time, valves, valves_k, drainage_node_ID, flushing_flow=0, duration=None)->str: +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: + """ print(datetime.now(pytz.timezone('Asia/Shanghai')).strftime("%Y-%m-%d %H:%M:%S") + " -- Start Analysis.") - new_name = f'flushing_Anal_{prj_name}' + 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(prj_name): - close_project(prj_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()(prj_name, new_name, + CopyProjectEx()(name, new_name, ['operation', 'current_operation', 'restore_operation', 'batch_operation', 'operation_table']) print(datetime.now(pytz.timezone('Asia/Shanghai')).strftime("%Y-%m-%d %H:%M:%S") + " -- Start Opening Database.") open_project(new_name) @@ -210,24 +244,27 @@ def flushing_analysis(prj_name, date_time, valves, valves_k, drainage_node_ID, f 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) - + # 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: + cs = ChangeSet() + if flushing_flow > 0: for r in emitter_demand['demands']: - r['demand']+=(flushing_flow/3.6) + 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: @@ -260,31 +297,47 @@ def flushing_analysis(prj_name, date_time, valves, valves_k, drainage_node_ID, f cs_options.append(options) set_option(new_name, cs_options) - result = run_simulation_ex(new_name,'realtime', date_time, date_time, duration, - downloading_prohibition=True) + # 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 + # return result ############################################################ # Contaminant simulation 04 # ############################################################ -def contaminant_simulation(prj_name:str,date_time:str, source:str,concentration:float,duration=900,pattern:str=None)->str: +def contaminant_simulation(name: str, modify_pattern_start_time: str, modify_total_duration: int = 900, + source: str = None, concentration: float = None, + source_pattern: str = 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 source: 污染源所在的节点ID + :param concentration: 污染源位置处的浓度,单位mg/L,即默认的污染模拟setting为concentration + :param source_pattern: 污染源的时间变化模式,若不传入则默认以恒定浓度持续模拟,时间长度等于duration; + 若传入,则格式为{1.0,0.5,1.1}等系数列表pattern_step模拟等于模型的hydraulic time step + :return: + """ print(datetime.now(pytz.timezone('Asia/Shanghai')).strftime("%Y-%m-%d %H:%M:%S") + " -- Start Analysis.") - new_name = f'contaminant_Sim_{prj_name}' + 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(prj_name): - close_project(prj_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()(prj_name, new_name, + CopyProjectEx()(name, new_name, ['operation', 'current_operation', 'restore_operation', 'batch_operation', 'operation_table']) print(datetime.now(pytz.timezone('Asia/Shanghai')).strftime("%Y-%m-%d %H:%M:%S") + " -- Start Opening Database.") open_project(new_name) @@ -301,19 +354,19 @@ def contaminant_simulation(prj_name:str,date_time:str, source:str,concentration: secs=from_clock_to_seconds_2(hydraulic_step) operation_step=0 #step 1. set duration - if duration==None: - duration=secs + if modify_total_duration==None: + modify_total_duration =secs #step 2. set pattern - if pattern!=None: - pt=get_pattern(new_name,pattern) + if source_pattern!=None: + pt=get_pattern(new_name,source_pattern) if pt==None: - str_response=str('cant find pattern') + str_response=str('cant find source_pattern') return str_response else: cs_pattern=ChangeSet() pt={} factors=[] - tmp_duration=duration + tmp_duration= modify_total_duration while tmp_duration>0: factors.append(1.0) tmp_duration=tmp_duration-secs @@ -360,33 +413,42 @@ def contaminant_simulation(prj_name:str,date_time:str, source:str,concentration: operation_step+=1 #step 5. run simulation - result = run_simulation_ex(new_name,'realtime', date_time, date_time, duration, - downloading_prohibition=True) + # 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(prj_name) + # execute_undo(name) if is_project_open(new_name): close_project(new_name) delete_project(new_name) - return result + # return result ############################################################ -# age analysis 05 +# age analysis 05 ***水龄模拟目前还没和实时模拟打通,不确定是否需要,先不要使用*** ############################################################ -def age_analysis(prj_name, start_time, end_time, duration) -> str: +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_{prj_name}' + 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(prj_name): - close_project(prj_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()(prj_name, new_name, + CopyProjectEx()(name, new_name, ['operation', 'current_operation', 'restore_operation', 'batch_operation', 'operation_table']) print(datetime.now(pytz.timezone('Asia/Shanghai')).strftime("%Y-%m-%d %H:%M:%S") + " -- Start Opening Database.") open_project(new_name) @@ -394,11 +456,11 @@ def age_analysis(prj_name, start_time, end_time, duration) -> str: # step 1. run simulation - result = run_simulation_ex(new_name, 'realtime', start_time, end_time, duration, + 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(prj_name) #有疑惑 + # execute_undo(name) #有疑惑 if is_project_open(new_name): close_project(new_name) delete_project(new_name) @@ -430,18 +492,31 @@ def age_analysis(prj_name, start_time, end_time, duration) -> str: ############################################################ -def pressure_regulation(prj_name, start_datetime, pump_control, tank_initial_level_control=None) -> str: +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_{prj_name}' + 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(prj_name): - close_project(prj_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()(prj_name, new_name, + CopyProjectEx()(name, new_name, ['operation', 'current_operation', 'restore_operation', 'batch_operation', 'operation_table']) print(datetime.now(pytz.timezone('Asia/Shanghai')).strftime("%Y-%m-%d %H:%M:%S") + " -- Start Opening Database.") open_project(new_name) @@ -455,23 +530,28 @@ def pressure_regulation(prj_name, start_datetime, pump_control, tank_initial_lev 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) + # 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 + # return result ############################################################ -# project management 07 +# project management 07 ***暂时不使用,与业务需求无关*** ############################################################ @@ -510,7 +590,7 @@ def project_management(prj_name, start_datetime, pump_control, ############################################################ -# scheduling analysis 08 +# scheduling analysis 08 ***暂时不使用,与业务需求无关*** ############################################################ @@ -633,6 +713,11 @@ def daily_scheduling_simulation(prj_name, start_time, pump_control, ############################################################ def network_update(file_path: str) -> None: + """ + 更新pg数据库中的inp文件 + :param file_path: inp文件 + :return: + """ read_inp('bb', file_path) csv_path = './history_pattern_flow.csv' @@ -783,5 +868,9 @@ if __name__ == '__main__': # str_dump=dump_output('h:\\OneDrive\\tjwaterserver\\temp\\beibeizone.db_busrtID(ZBBGXSZW000001).out') # with open("burst_out_dump.txt", "w") as f: # f.write(str_dump) -# network_update('model22_1223.inp') - submit_scada_info('bb', '4490') +# # network_update('model22_1223.inp') +# submit_scada_info('bb', '4490') + # 示例1:burst_analysis + burst_analysis(name='bb', modify_pattern_start_time='2025-02-14T10:30:00+08:00', + burst_ID='ZBBGXSZW000002', burst_size=50, modify_total_duration=1800, scheme_Name='burst_scheme') +