namespace IStation
{
///
///
///
public class HydraulicModelHelper
{
private readonly Service.Station _service_station = new();
private readonly Service.Scada _service_scada = new();
private readonly Service.ScheduleConfig _service_schedule_config = new();
private readonly Service.HydraulicModelValidationConfig _service_hydraulic_model_validation_config = new IStation.Service.HydraulicModelValidationConfig();
private static readonly Dictionary _pump_nr_dict = new() {
{ "Pump11",590},
{ "Pump12",590},
{ "Pump13",590},
{ "Pump14",590},
//{ "Pump15",590},
//{ "Pump16",590},
{ "Pump17",590},
{ "Pump18",590},
{ "Pump21",740},
{ "Pump22",495},
{ "Pump23",495},
{ "Pump24",495},
{ "Pump25",495},
{ "Pump26",495},
{ "Pump27",740}
};
private static readonly Dictionary _pump_flag_dict = new() {
{ 11,"Pump11"},
{ 12,"Pump12"},
{ 13,"Pump13"},
{ 14,"Pump14"},
{ 15,"Pump15"},
{ 16,"Pump16"},
{ 17,"Pump17"},
{ 18,"Pump18"},
{ 21,"Pump21"},
{ 22,"Pump22"},
{ 23,"Pump23"},
{ 24,"Pump24"},
{ 25,"Pump25"},
{ 26,"Pump26"},
{ 27,"Pump27"}
};
private static readonly string _hydraulic_model_file = Path.Combine(
Settings.ParasHelper.LocalFile.DataFolderDirectory,
Settings.ParasHelper.LocalFile.HydraulicModelFile);
///
/// 获取水力模型
///
public Dto.Epanet.HydraulicModelDto Get()
{
if (!File.Exists(_hydraulic_model_file))
{
throw Yw.Dto.YOops.Oh(Yw.Dto.eResultCode.Error, Yw.Dto.InternalErrorCodes.A001, $"水力模型文件缺失!文件路径:{_hydraulic_model_file}");
}
IStation.Epanet.NetworkHelper.Open(_hydraulic_model_file, out Epanet.Network.Network network);
if (network == null)
{
throw Yw.Dto.YOops.Oh(Yw.Dto.eResultCode.Error, Yw.Dto.InternalErrorCodes.A001, $"文件解析失败!文件路径:{_hydraulic_model_file}");
}
if (network == null)
return default;
var reservoirs = network.Reservoirs;
var tanks = network.Tanks;
var junctions = network.Junctions;
var pipes = network.Pipes;
var pumps = network.Pumps;
var valves = network.Valves;
var hydraulic_model_dto = new Dto.Epanet.HydraulicModelDto();
if (reservoirs != null && reservoirs.Any())
{
foreach (var item in reservoirs)
{
var dto = new Dto.Epanet.Reservoir
{
Id = item.Name,
Coordinate = new Dto.Epanet.EnPoint(item.Coordinate.X, item.Coordinate.Y)
};
hydraulic_model_dto.Reservoirs.Add(dto);
}
}
if (tanks != null && tanks.Any())
{
foreach (var item in tanks)
{
var dto = new Dto.Epanet.Tank
{
Id = item.Name,
Coordinate = new Dto.Epanet.EnPoint(item.Coordinate.X, item.Coordinate.Y),
};
hydraulic_model_dto.Tanks.Add(dto);
}
}
if (junctions != null && junctions.Any())
{
foreach (var item in junctions)
{
var dto = new Dto.Epanet.Junction
{
Id = item.Name,
Coordinate = new Dto.Epanet.EnPoint(item.Coordinate.X, item.Coordinate.Y),
};
hydraulic_model_dto.Junctions.Add(dto);
}
}
if (pipes != null && pipes.Any())
{
foreach (var item in pipes)
{
var dto = new Dto.Epanet.Pipe
{
Id = item.Name,
};
if (item.FirstNode != null)
{
var node = item.FirstNode;
dto.FirstNode = new Dto.Epanet.Node()
{
Id = node.Name,
Coordinate = new Dto.Epanet.EnPoint(node.Coordinate.X, node.Coordinate.Y),
};
}
if (item.SecondNode != null)
{
var node = item.SecondNode;
dto.SecondNode = new Dto.Epanet.Node()
{
Id = node.Name,
Coordinate = new Dto.Epanet.EnPoint(node.Coordinate.X, node.Coordinate.Y),
};
}
hydraulic_model_dto.Pipes.Add(dto);
}
}
if (pumps != null && pumps.Any())
{
foreach (var item in pumps)
{
var dto = new Dto.Epanet.Pump
{
Id = item.Name,
};
if (item.FirstNode != null)
{
var node = item.FirstNode;
dto.FirstNode = new Dto.Epanet.Node()
{
Id = node.Name,
Coordinate = new Dto.Epanet.EnPoint(node.Coordinate.X, node.Coordinate.Y),
};
}
if (item.SecondNode != null)
{
var node = item.SecondNode;
dto.SecondNode = new Dto.Epanet.Node()
{
Id = node.Name,
Coordinate = new Dto.Epanet.EnPoint(node.Coordinate.X, node.Coordinate.Y),
};
}
hydraulic_model_dto.Pumps.Add(dto);
}
}
if (valves != null && valves.Any())
{
foreach (var item in valves)
{
var dto = new Dto.Epanet.Valve
{
Id = item.Name,
};
if (item.FirstNode != null)
{
var node = item.FirstNode;
dto.FirstNode = new Dto.Epanet.Node()
{
Id = node.Name,
Coordinate = new Dto.Epanet.EnPoint(node.Coordinate.X, node.Coordinate.Y),
};
}
if (item.SecondNode != null)
{
var node = item.SecondNode;
dto.SecondNode = new Dto.Epanet.Node()
{
Id = node.Name,
Coordinate = new Dto.Epanet.EnPoint(node.Coordinate.X, node.Coordinate.Y),
};
}
hydraulic_model_dto.Valves.Add(dto);
}
}
return hydraulic_model_dto;
}
private List GetZyScadaList()
{
var scada_list = new List();
var scada_debug_file = Settings.ParasHelper.LocalFile.DataFolderDirectory + "\\" + "scada_debug.txt";
var scada_debug_json = File.ReadAllText(scada_debug_file);
var scada_output =Yw. JsonHelper.Json2Object(scada_debug_json);
foreach (var scada_dict in scada_output.data)
{
var vals = scada_dict.Value.ElementAt(0).Value;
var time = scada_dict.Value.ElementAt(1).Value;
var key = scada_dict.Value.ElementAt(2).Value;
var scada = new IStation.Dto.Epanet.ZyScada();
scada.Id = key;
if (DateTime.TryParse(time, out DateTime t))
scada.Time = t;
if (double.TryParse(vals, out double v))
scada.Value = v;
scada_list.Add(scada);
}
return scada_list;
}
///
/// 调度验证
///
public Dto.Epanet.HydraulicScheduleDto ScheduleValidation(double TotalFlow1, double TotalPressure1, double TotalFlow2, double TotalPressure2)
{
if (!File.Exists(_hydraulic_model_file))
{
throw Yw.Dto.YOops.Oh(Yw.Dto.eResultCode.Error, Yw.Dto.InternalErrorCodes.A001, $"水力模型文件缺失!文件路径:{_hydraulic_model_file}");
}
var receipt_time = DateTime.Now;
var request_id = Yw.YitIdHelper.NextId();
var log_title = string.Empty;
var log_msg = string.Empty;
log_title = "初始化基础信息文件";
var station_info = _service_station.Get();
var scada_info = _service_scada.Get();
var schedule_config1 = _service_schedule_config.GetStation1();
var schedule_config2 = _service_schedule_config.GetStation2();
if (station_info == null || scada_info == null)
{
log_msg = "文件缺失!";
throw Yw.Dto.YOops.Oh(Yw.Dto.eResultCode.Error, Yw.Dto.InternalErrorCodes.A001, log_msg);
}
var hydraulic_model_validation_config = _service_hydraulic_model_validation_config.Get();
if (hydraulic_model_validation_config == null)
{
log_msg = "水力模型验证文件不存在!";
throw Yw.Dto.YOops.Oh(Yw.Dto.eResultCode.Error, Yw.Dto.InternalErrorCodes.A001, log_msg);
}
var target_flow1 = TotalFlow1;
var target_pressure1 = TotalPressure1;
var target_flow2 = TotalFlow2;
var target_pressure2 = TotalPressure2;
var water_level1 = 0.0;
var water_level2 = 0.0;
var current_open_pump_flags1 = new List();
var current_open_pump_flags2 = new List();
var scada_list = GetZyScadaList();
if (!scada_list.Any())
{
log_msg = "Scada数据缺失!";
throw Yw.Dto.YOops.Oh(Yw.Dto.eResultCode.Error, Yw.Dto.InternalErrorCodes.A001, log_msg);
}
var water_level_tag_list_1 = scada_info.GetS1WaterLevelTagList();
var water_level_tag_list_2 = scada_info.GetS2WaterLevelTagList();
var water_level_valid_value_list1 = new List();
var water_level_valid_value_list2 = new List();
var run_status_tag_dict_1 = scada_info.GetS1RunStatusTagDict();
var run_status_tag_dict_2 = scada_info.GetS2RunStatusTagDict();
foreach (var scada in scada_list)
{
if (!scada.Value.HasValue)
continue;
var tag = scada.Id;
var value = scada.Value.Value;
if (water_level_tag_list_1.Contains(tag))
{
water_level_valid_value_list1.Add(value);
continue;
}
else if (water_level_tag_list_2.Contains(tag))
{
water_level_valid_value_list2.Add(value);
continue;
}
if (value != 1)
continue;
if (run_status_tag_dict_1.ContainsKey(tag))
{
current_open_pump_flags1.Add(run_status_tag_dict_1[tag]);
continue;
}
else if (run_status_tag_dict_2.ContainsKey(tag))
{
current_open_pump_flags2.Add(run_status_tag_dict_2[tag]);
continue;
}
}
if (water_level_valid_value_list1.Any())
water_level1 = water_level_valid_value_list1.Average(x => x);
if (water_level_valid_value_list2.Any())
water_level2 = water_level_valid_value_list2.Average(x => x);
log_title = "当前水位";
var target_head1 = Curve.PumpCalculateHelper.Mpa2M(target_pressure1) - water_level1;
var target_head2 = Curve.PumpCalculateHelper.Mpa2M(target_pressure2) - water_level2;
var helper = new Algorithm.ScheduleHelper();
helper.Initial(current_open_pump_flags1, schedule_config1);
var optimal_combine1 = helper.Calc(station_info.Station1, station_info.S1FlagsPart1, station_info.S1FlagsPart2, target_flow1, target_head1);
helper.Initial(current_open_pump_flags2, schedule_config2);
var optimal_combine2 = helper.Calc(station_info.Station2, station_info.S2FlagsPart1, station_info.S2FlagsPart2, target_flow2, target_head2);
log_title = "调度返回";
if (optimal_combine1 == null && optimal_combine2 == null)
{
log_msg = "厂内调度方案无法计算!";
throw Yw.Dto.YOops.Oh(Yw.Dto.eResultCode.Error, Yw.Dto.InternalErrorCodes.A001, log_msg);
}
var pump_schedule_value_list = new List();
foreach (var item in _pump_flag_dict)
{
var pump_schedule_value = new Dto.Epanet.ScheduleValue();
pump_schedule_value.ModelId = item.Value;
pump_schedule_value.Unit = "hz";
pump_schedule_value.ModelValue = 0;
pump_schedule_value_list.Add(pump_schedule_value);
}
if (optimal_combine1 != null)
{
foreach (var combine in optimal_combine1.Combines)
{
foreach (var fre_pump in combine.FrePumps)
{
var flag = fre_pump.Flag;
var pump_schedule_value = pump_schedule_value_list.Find(x => x.ModelId == _pump_flag_dict[flag]);
if (pump_schedule_value != null)
{
pump_schedule_value.ModelValue = fre_pump.Frequency / 50;
}
}
}
}
else
{
log_msg = $"\r\n1输水调度计算失败,无法满足目标流量:{target_flow1},目标压力:{target_pressure1}!";
}
if (optimal_combine2 != null)
{
foreach (var combine in optimal_combine2.Combines)
{
foreach (var fre_pump in combine.FrePumps)
{
var flag = fre_pump.Flag;
var pump_schedule_value = pump_schedule_value_list.Find(x => x.ModelId == _pump_flag_dict[flag]);
if (pump_schedule_value != null)
{
pump_schedule_value.ModelValue = fre_pump.Frequency / 50;
}
}
}
}
else
{
log_msg += $"\r\n2输水调度计算失败,无法满足目标流量:{target_flow2},目标压力:{target_pressure2}!";
}
var hydraulic_schedule_dto = new Dto.Epanet.HydraulicScheduleDto();
var flow_id_mapping_dict = hydraulic_model_validation_config.FlowIdMappingDict;
var pressure_id_mapping_dict = hydraulic_model_validation_config.PressureIdMappingDict;
var pattern_id_mapping_dict = hydraulic_model_validation_config.PatternIdMappingDict;
var pressure_id_kPa_list = hydraulic_model_validation_config.PressureIdkPaList;
var pattern_list = new List();
var time_value = new IStation.Hydraulic.TimeValue
{
Time = receipt_time,
Value = new Dictionary()
};
foreach (var scada in scada_list)
{
var tag = scada.Id;
var value = scada.Value;
foreach (var item in flow_id_mapping_dict)
{
if (item.Value != tag)
continue;
time_value.Value.Add(tag, value ?? 0);
}
foreach (var item in pressure_id_mapping_dict)
{
if (item.Value != tag)
continue;
var pressure_value = value ?? 0;
if (pressure_id_kPa_list.Contains(tag))
{
pressure_value /= 1000;
}
pressure_value = IStation.Curve.PumpCalculateHelper.Mpa2M(pressure_value);
time_value.Value.Add(tag, pressure_value);
}
foreach (var item in pattern_id_mapping_dict)
{
if (item.Value != tag)
continue;
var pattern_id = item.Key;
var factor = value ?? 0;
var pattern = new IStation.Hydraulic.Pattern
{
Id = pattern_id,
FactorList = new List()
};
var pump_schedule_value = pump_schedule_value_list.Find(x => x.ModelId == pattern_id);
if (pump_schedule_value != null)
{
double scada_value = -1;
if (_pump_nr_dict.ContainsKey(pattern_id))
{
scada_value = factor / _pump_nr_dict[pattern_id];
scada_value = scada_value < 0 ? 0 : scada_value;
}
pump_schedule_value.ScadaId = tag;
pump_schedule_value.ScadaValue = scada_value;
factor = pump_schedule_value.ModelValue.Value;
}
pattern.FactorList.Add((float)factor);
pattern_list.Add(pattern);
}
}
var p23 = pattern_list.Find(x => x.Id == "Pump23");
var hydraulic_model_record_list = IStation.Hydraulic.ModeVerifyHelper.Verify(request_id, _hydraulic_model_file, flow_id_mapping_dict, pressure_id_mapping_dict, pattern_list, time_value);
if (hydraulic_model_record_list == null || !hydraulic_model_record_list.Any())
{
log_msg = $"模型验证数据为空!";
}
hydraulic_schedule_dto.ScheduleValues.AddRange(pump_schedule_value_list);
foreach (var record in hydraulic_model_record_list)
{
var digits = 4;
var unit = "m";
if (record.ValueType == eValueType.Flow)
{
digits = 1;
unit = "m³/h";
}
var schedule_value = new Dto.Epanet.ScheduleValue();
schedule_value.ModelId = record.ModelId;
schedule_value.ScadaId = record.ScadaId;
schedule_value.Unit = unit;
if (record.ScadaValue.HasValue)
{
schedule_value.ScadaValue = Math.Round(record.ScadaValue.Value, digits);
}
if (record.ModeValue.HasValue)
{
schedule_value.ModelValue = Math.Round(record.ModeValue.Value, digits);
}
hydraulic_schedule_dto.ScheduleValues.Add(schedule_value);
}
return hydraulic_schedule_dto;
}
}
}