using IStation.Epanet;
|
using IStation.Epanet.Enums;
|
using IStation.Model;
|
using IStation.WinFrmUI;
|
using System.ComponentModel.DataAnnotations;
|
using System.Linq;
|
using System.Runtime;
|
using System.Runtime.Intrinsics.Arm;
|
using System.Text;
|
|
namespace IStation.Test
|
{
|
/// <summary>
|
/// 数据导入
|
/// 根据3倍标准差粗过滤异常数据
|
/// 再用数据用1hz分类,调用修正算法更新出最新的曲线
|
/// 缺失的频率向上取最近的hz相似换算下去
|
/// 现场调度用更新后的曲线调度
|
/// </summary>
|
public class Station1Helper
|
{
|
private static string _model_file = System.IO.Path.Combine
|
(SettingsD.File.RootDirectory, SettingsD.File.DataFolder, "ch2_v3_20240801(Clear).inp");
|
|
/// <summary>
|
/// 绑定数据
|
/// </summary>
|
public static void Start()
|
{
|
|
var projectId = 661070185922629;
|
IStation.SettingsD.Project.ID = projectId;
|
var monitorDataSourcesId = 663976941449285;//2024-202504
|
var stationIndex = 1;
|
var stationId = 462958406303813;
|
var dtStart = new DateTime(2024, 1, 1);
|
var dtEnd = new DateTime(2025, 5, 1);
|
|
var bll = new BLL.StationSignalRecordPacket();
|
var bllEquipment = new BLL.Equipment();
|
var bllCurve = new BLL.PumpCurve();
|
|
|
var pumpList = bllEquipment.GetPumpModelListByBelongTypeAndBelongID(IStation.ObjectType.Station, stationId);
|
var flagList = pumpList.Select(x => x.SortCode).OrderBy(x => x).ToList();
|
var flagPumpDict = pumpList.ToDictionary(x => x.SortCode, x => x.RatedParas);
|
|
var flagQhCurveDict = GetFlagCurveDict();
|
|
var pipe_flow_id_list = GlobalHelperW.GetPipeFlowIdList(stationIndex);
|
var pipe_pressure_id_list = GlobalHelperW.GetPipePressureIdList(stationIndex);
|
|
var packet_list = bll.Get(monitorDataSourcesId, stationId);
|
var allStationRecordList = packet_list.SelectMany(x => x.StationSignalRecords).ToList();
|
|
var temp_id_build = new StringBuilder(31);
|
var err = EpanetMethods.ENopen(_model_file, "", "");
|
if ((int)err > 6)
|
{
|
throw new Exception($"ENopen:{err}");
|
}
|
|
err = EpanetMethods.ENopenH();
|
if ((int)err > 6)
|
{
|
throw new Exception($"ENopenH:{err}");
|
}
|
|
var curve_point_count = 100;
|
var pump_model_mapping_list = AnalysisHelper.GetPumpModelMappingList();
|
var model_mapping_list = AnalysisHelper.GetStationMappingList();
|
|
foreach (var item in pump_model_mapping_list)
|
{
|
var flag = item.Flag;
|
|
|
if (EpanetMethods.ENgetlinkindex(item.PumpId, out int pump_index) != ErrorCode.Ok)
|
throw new Exception($"ENgetlinkindex:{err}");
|
|
if (!string.IsNullOrEmpty(item.FlowId))
|
{
|
if (EpanetMethods.ENgetlinkindex(item.FlowId, out int flow_index) != ErrorCode.Ok)
|
throw new Exception($"ENgetlinkindex:{err}");
|
item.FlowIndex = flow_index;
|
}
|
|
if (EpanetMethods.ENgetnodeindex(item.PressureId, out int pressure_index) != ErrorCode.Ok)
|
throw new Exception($"ENgetnodeindex:{err}");
|
|
if (EpanetMethods.ENgetcurveindex(item.CurveId, out int curve_index) != ErrorCode.Ok)
|
throw new Exception($"ENgetcurveindex:{err}");
|
|
item.PumpIndex = pump_index;
|
item.PressureIndex = pressure_index;
|
item.CurveIndex = curve_index;
|
|
|
var qh = flagQhCurveDict[flag];
|
var fit_point_list = qh.GetFitPoints(curve_point_count);
|
var flow_list = fit_point_list.Select(x => (float)x.X).ToArray();
|
var head_list = fit_point_list.Select(x => (float)x.Y).ToArray();
|
|
|
var cek = CheckFitPointList(fit_point_list, curve_point_count);
|
if (!cek)
|
{
|
throw new Exception($"CheckFitPointList: false");
|
}
|
err = EpanetMethods.ENsetcurve(item.CurveIndex, flow_list, head_list, curve_point_count);
|
if (err != 0)
|
{
|
throw new Exception($"ENsetcurve:{err}");
|
}
|
|
}
|
|
foreach (var item in model_mapping_list)
|
{
|
|
if (EpanetMethods.ENgetlinkindex(item.FlowId, out int flow_index) != ErrorCode.Ok)
|
throw new Exception($"ENgetlinkindex:{err}");
|
|
if (EpanetMethods.ENgetnodeindex(item.PressureId, out int pressure_index) != ErrorCode.Ok)
|
throw new Exception($"ENgetnodeindex:{err}");
|
|
item.PressureIndex = pressure_index;
|
item.FlowIndex = flow_index;
|
|
}
|
|
var pump_model_mapping_dict = pump_model_mapping_list.ToDictionary(x => x.Flag, y => y);
|
var pattern_id_list = AnalysisHelper.GetPatternIdList();
|
var pattern_id_dict = new Dictionary<string, int>();
|
foreach (var id in pattern_id_list)
|
{
|
if (EpanetMethods.ENgetpatternindex(id, out int index) != ErrorCode.Ok)
|
continue;
|
pattern_id_dict.Add(id, index);
|
}
|
|
var vm_list = new List<PumpViewModel>();
|
var vm_diff_list = new List<ModelDiffViewModel>();
|
foreach (var station_record in allStationRecordList)
|
{
|
var model_record_dict = station_record.ModelRecordDict;
|
var pipe_flow_err = true;
|
var pipe_pressure_err = true;
|
foreach (var id in pipe_flow_id_list)
|
{
|
if (model_record_dict[id] < 1)
|
{
|
pipe_flow_err = false;
|
break;
|
}
|
}
|
foreach (var id in pipe_pressure_id_list)
|
{
|
var value = model_record_dict[id];
|
if (value < 1 || value > 40)
|
{
|
pipe_pressure_err = false;
|
break;
|
}
|
}
|
if (!pipe_flow_err || !pipe_pressure_err)
|
{
|
continue;
|
}
|
var time = station_record.Time.ToString("G");
|
var pump_allStationRecordList = station_record.PumpSignalRecords;
|
var total_flow = station_record.TotalFlow;
|
var total_pressure = station_record.TotalPressure;
|
var pump_total_flow = pump_allStationRecordList.Sum(x => x.FlowRate);
|
var diff_flow = station_record.DiffFlow;
|
if (total_pressure < 0)
|
{
|
continue;
|
}
|
if (total_flow <= 0 && pump_total_flow <= 0)
|
{
|
continue;
|
}
|
if (pump_total_flow > 0 && Math.Abs(diff_flow) > 2000)
|
{
|
continue;
|
}
|
if (pump_allStationRecordList.Exists(x => x.Flag != 15 && x.Flag != 16 && x.Rpm < 1))
|
{
|
continue;
|
}
|
if (pump_allStationRecordList.Exists(x => x.OutletPressure > 50))
|
{
|
continue;
|
}
|
|
foreach (var pattern in pattern_id_dict)
|
{
|
var pattern_id = pattern.Key;
|
var pattern_index = pattern.Value;
|
var pattern_value = 0f;
|
if (model_record_dict.ContainsKey(pattern_id))
|
{
|
pattern_value = (float)model_record_dict[pattern_id];
|
}
|
err = EpanetMethods.ENsetpattern(pattern_index, new float[] { pattern_value }, 1);
|
if ((int)err > 6)
|
{
|
throw new Exception($"ENsetpattern:{err}");
|
}
|
}
|
|
err = EpanetMethods.ENinitH(0);
|
if ((int)err > 6)
|
{
|
throw new Exception($"ENinitH:{err}");
|
}
|
|
err = EpanetMethods.ENrunH(out _);
|
if ((int)err > 6)
|
{
|
throw new Exception($"ENrunH:{err}");
|
}
|
|
|
foreach (var pump_record in pump_allStationRecordList)
|
{
|
var flag = pump_record.Flag;
|
var pump = flagPumpDict[flag];
|
var qh = flagQhCurveDict[flag];
|
var mapping = pump_model_mapping_dict[flag];
|
var rpm = pump_record.Rpm;
|
if (!pump.IsBp)
|
rpm = pump.Nr;
|
if (rpm == 0)
|
break;
|
|
|
var hz = Math.Round(rpm / pump.Nr * 50, 2);
|
var hz0 = Math.Round(hz, 0);
|
var wl = pump_record.WaterLevel;
|
var inlet_pressure = Model.CurveCalcuHelper.Mpa2M(pump_record.InletPressure);
|
var outlet_pressure = Model.CurveCalcuHelper.Mpa2M(pump_record.OutletPressure);
|
var pressure_diff = outlet_pressure - inlet_pressure;
|
var flow = pump_record.FlowRate;
|
var curve_head = pump_record.Head;
|
|
|
err = EpanetMethods.ENgetlinkvalue(mapping.PumpIndex, LinkValue.Flow, out float model_flow);
|
if ((int)err > 6)
|
{
|
throw new Exception($"ENgetnodevalue:{err}");
|
}
|
if (Math.Abs(model_flow) < 1)
|
{
|
break;
|
}
|
|
err = EpanetMethods.ENgetnodevalue(mapping.PressureIndex, NodeValue.Pressure, out float model_outlet_pressure);
|
if ((int)err > 6)
|
{
|
throw new Exception($"ENgetnodevalue:{err}");
|
}
|
|
if (Math.Abs(model_outlet_pressure) > 45)
|
{
|
break;
|
}
|
|
model_flow = Math.Abs(model_flow);
|
model_outlet_pressure = Math.Abs(model_outlet_pressure);
|
var model_pressure_diff = model_outlet_pressure - inlet_pressure;
|
|
var flow_diff = flow - model_flow;
|
|
var vm = new PumpViewModel();
|
vm.Time = time;
|
vm.Rpm = rpm;
|
vm.Flag = flag;
|
vm.Hz = hz;
|
vm.Hz0 = hz0;
|
vm.WaterLevel = wl;
|
vm.InletPressure = Math.Round(inlet_pressure, 2);
|
vm.OutletPressure = Math.Round(outlet_pressure, 2);
|
vm.PressureDiff = Math.Round(pressure_diff, 2);
|
|
vm.Flow = Math.Round(flow, 1);
|
vm.ModelFlow = Math.Round(model_flow, 1);
|
vm.ModelOutletPressure = Math.Round(model_outlet_pressure, 2);
|
vm.CurvePressureDiff = Math.Round(model_pressure_diff, 2);
|
vm.PressureDiffDev = Math.Round(pressure_diff - model_pressure_diff, 3);
|
vm.FlowDiff = Math.Round(flow_diff, 1);
|
|
var other_press = 0d;
|
if (pump.IsBp)
|
{
|
other_press = Model.CurveCalcuHelper.CalculateOtherPress(model_flow, pump.Ic, pump.Oc, null, null);
|
}
|
|
var other_outlet = other_press + pressure_diff;
|
var mdoel_other_outlet = other_press + model_pressure_diff;
|
var diff = pressure_diff - model_pressure_diff;
|
|
if (diff>0.1)
|
{
|
|
}
|
var calcHead = other_outlet + vm.PressureDiffDev;
|
vm.CalcHead = Math.Round(mdoel_other_outlet, 2);
|
|
vm_list.Add(vm);
|
|
}
|
|
foreach (var mapping in model_mapping_list)
|
{
|
if (!model_record_dict.ContainsKey(mapping.ScadaPressureId))
|
{
|
continue;
|
}
|
if (!model_record_dict.ContainsKey(mapping.ScadaFlowId))
|
{
|
continue;
|
}
|
var flow = model_record_dict[mapping.ScadaFlowId];
|
var outlet_pressure = model_record_dict[mapping.ScadaPressureId];
|
|
err = EpanetMethods.ENgetlinkvalue(mapping.FlowIndex, LinkValue.Flow, out float model_flow);
|
if ((int)err > 6)
|
{
|
throw new Exception($"ENgetnodevalue:{err}");
|
}
|
|
err = EpanetMethods.ENgetnodevalue(mapping.PressureIndex, NodeValue.Pressure, out float model_outlet_pressure);
|
if ((int)err > 6)
|
{
|
throw new Exception($"ENgetnodevalue:{err}");
|
}
|
|
var flow_diff = flow - model_flow;
|
var pressure_diff = outlet_pressure - model_outlet_pressure;
|
|
var vm = new ModelDiffViewModel();
|
vm.Date = station_record.Time;
|
vm.Time = time;
|
vm.Name = mapping.Name;
|
vm.ScadaFlow = Math.Round(flow, 1);
|
vm.ScadaPressure = Math.Round(outlet_pressure, 3);
|
vm.MonitorFlow = Math.Round(model_flow, 1);
|
vm.MonitorPressure = Math.Round(model_outlet_pressure, 3);
|
vm.FlowDiff = Math.Round(flow_diff, 1);
|
vm.PressureDiff = Math.Round(pressure_diff, 3);
|
vm_diff_list.Add(vm);
|
}
|
}
|
|
err = EpanetMethods.ENcloseH();
|
if ((int)err > 6)
|
{
|
throw new Exception($"ENcloseH:{err}");
|
}
|
err = EpanetMethods.ENclose();
|
if ((int)err > 6)
|
{
|
throw new Exception($"ENclose:{err}");
|
}
|
|
if (!vm_list.Any())
|
{
|
return;
|
}
|
var fullPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "pumpcsv");
|
var allPumpRecordList2 = vm_list.Where(x =>
|
{
|
if (x.Rpm == IStation.Error.Default )
|
{
|
return false;
|
}
|
|
return true;
|
}).ToList();
|
var pumpFlagRecordGroup = allPumpRecordList2.OrderBy(x => x.Flag).GroupBy(x => x.Flag);
|
var pumpFlagHzRecordGroup = new Dictionary<(int Flag, int Hz), List<PumpViewModel>>();
|
foreach (var pumpFlag in pumpFlagRecordGroup)
|
{
|
var flag = pumpFlag.Key;
|
var pump = flagPumpDict[flag];
|
var pumpQh = flagQhCurveDict[flag];
|
if (!pump.IsBp)
|
{
|
var allFlagHzRecordList = pumpFlag.ToList();
|
if (allFlagHzRecordList.Count < 30)
|
{
|
Console.WriteLine($"{flag}泵-{50}hz 总数:{allFlagHzRecordList.Count},<5 跳过");
|
}
|
var flagHzRecordList = DynamicThresholdProcessorHelper.Filter(allFlagHzRecordList);
|
Console.WriteLine($"{flag}泵-{50}hz 总数:{allFlagHzRecordList.Count},过滤:{allFlagHzRecordList.Count - flagHzRecordList.Count}");
|
pumpFlagHzRecordGroup.Add((flag, 50), flagHzRecordList);
|
if (flagHzRecordList.Any())
|
{
|
var curvePtList = pumpQh.GetFitPoints(200).Select(x => new CurvePtViewModel(x)).ToList();
|
CsvHelper.ExportToCsv(curvePtList, Path.Combine(fullPath, $"{flag}_{50}_old_curve.csv"));
|
CsvHelper.ExportToCsv(flagHzRecordList.Select(x => new CurvePtViewModel(x.ModelFlow, x.CalcHead)).ToList(), Path.Combine(fullPath, $"{flag}_{50}.csv"));
|
}
|
}
|
else
|
{
|
var hzGroup = pumpFlag.OrderBy(x => x.Rpm).GroupBy(x =>
|
{
|
var hz = Math.Round(x.Rpm / pump.Nr * 50, 0);
|
return hz;
|
});
|
hzGroup = hzGroup.Where(x => x.Key > 10).ToList();
|
foreach (var pumpFlagHz in hzGroup)
|
{
|
var hz = pumpFlagHz.Key;
|
if (hz>50)
|
{
|
continue;
|
}
|
var allFlagHzRecordList = pumpFlagHz.ToList();
|
if (allFlagHzRecordList.Count < 30)
|
{
|
Console.WriteLine($"{flag}泵-{hz}hz 总数:{allFlagHzRecordList.Count},<5 跳过");
|
}
|
var flagHzRecordList = DynamicThresholdProcessorHelper.Filter(allFlagHzRecordList);
|
if (allFlagHzRecordList.Count < 30)
|
{
|
Console.WriteLine($"{flag}泵-{hz}hz 过滤后总数:{allFlagHzRecordList.Count},<5 跳过");
|
}
|
Console.WriteLine($"{flag}泵-{hz}hz 总数:{allFlagHzRecordList.Count},过滤:{allFlagHzRecordList.Count - flagHzRecordList.Count}");
|
pumpFlagHzRecordGroup.Add((flag, (int)hz), flagHzRecordList);
|
if (flagHzRecordList.Any())
|
{
|
var curvePtList = SimilarCalculateHelper.CalculateQH(pumpQh, 50, hz).GetFitPoints(100);
|
CsvHelper.ExportToCsv(curvePtList.Select(x => new CurvePtViewModel(x)).ToList(), Path.Combine(fullPath, $"{flag}_{hz}_old_curve.csv"));
|
CsvHelper.ExportToCsv(flagHzRecordList.Select(x => new CurvePtViewModel(x.ModelFlow,x.CalcHead)).ToList(), Path.Combine(fullPath, $"{flag}_{hz}.csv"));
|
}
|
}
|
|
}
|
|
}
|
|
|
|
|
GCSettings.LargeObjectHeapCompactionMode = GCLargeObjectHeapCompactionMode.CompactOnce;
|
GC.Collect(2, GCCollectionMode.Forced);
|
GC.WaitForFullGCComplete();
|
}
|
|
|
|
|
|
static bool CheckFitPointList(List<CurvePoint> fit_point_list, int nPoints)
|
{
|
var arr = fit_point_list.ToArray();
|
var max_y = fit_point_list[0].Y;
|
for (int j = 1; j < nPoints; j++)
|
{
|
if (arr[j].Y > max_y)
|
{
|
return false;
|
}
|
else
|
{
|
max_y = fit_point_list.Take(j).Max(x => x.Y);
|
}
|
}
|
return true;
|
}
|
|
|
private static Dictionary<int, Model.CurveExpress> GetFlagCurveDict()
|
{
|
var dict = new Dictionary<int, Model.CurveExpress>();
|
var bll_curve = new BLL.PumpCurve();
|
var station_list = new BLL.Station().GetAll();
|
foreach (var station in station_list)
|
{
|
var eq_list = new BLL.Equipment().GetPumpListByBelongTypeAndBelongID(IStation.ObjectType.Station, station.ID);
|
if (eq_list == null || !eq_list.Any())
|
{
|
return default;
|
}
|
|
foreach (var eq in eq_list)
|
{
|
Model.CurveExpress qh = null;
|
var curve_info = bll_curve.GetDefaultWorkingByPumpID(eq.ID)?.CurveInfo;
|
if (curve_info != null)
|
{
|
qh = curve_info.CurveQH;
|
}
|
dict.Add(eq.SortCode, qh);
|
}
|
}
|
|
return dict;
|
}
|
|
|
|
}
|
|
|
}
|
|
|
|
#region ViewModel
|
|
public class PumpViewModel
|
{
|
|
[Display(Name = "时间")]
|
public string Time { get; set; }
|
|
[Display(Name = "泵")]
|
public int Flag { get; set; }
|
|
[Display(Name = "转速")]
|
public double Rpm { get; set; }
|
|
[Display(Name = "频率")]
|
public double Hz { get; set; }
|
|
[Display(Name = "频率")]
|
public double Hz0 { get; set; }
|
|
[Display(Name = "水位")]
|
public double WaterLevel { get; set; }
|
|
[Display(Name = "进口压力")]
|
public double InletPressure { get; set; }
|
|
[Display(Name = "出口压力")]
|
public double OutletPressure { get; set; }
|
|
[Display(Name = "模型出口压力")]
|
public double ModelOutletPressure { get; set; }
|
|
[Display(Name = "瞬时流量")]
|
public double Flow { get; set; }
|
|
[Display(Name = "模型流量")]
|
public double ModelFlow { get; set; }
|
|
/// <summary>
|
/// 计算杨程
|
/// </summary>
|
public double CalcHead { get; set; }
|
|
[Display(Name = "流量差值")]
|
public double FlowDiff { get; set; }
|
|
|
[Display(Name = "压差")]
|
public double PressureDiff { get; set; }
|
|
[Display(Name = "曲线压差")]
|
public double CurvePressureDiff { get; set; }
|
|
[Display(Name = "压差差值")]
|
public double PressureDiffDev { get; set; }
|
|
}
|
|
public class ModelDiffViewModel
|
{
|
[Display(Name = "时间")]
|
public DateTime Date { get; set; }
|
|
[Display(Name = "时间")]
|
public string Time { get; set; }
|
|
[Display(Name = "名称")]
|
public string Name { get; set; }
|
|
[Display(Name = "监测压力")]
|
public double ScadaPressure { get; set; }
|
|
[Display(Name = "监测流量")]
|
public double ScadaFlow { get; set; }
|
|
[Display(Name = "模型压力")]
|
public double MonitorPressure { get; set; }
|
|
[Display(Name = "模型流量")]
|
public double MonitorFlow { get; set; }
|
|
[Display(Name = "压力偏差")]
|
public double PressureDiff { get; set; }
|
|
[Display(Name = "流量偏差")]
|
public double FlowDiff { get; set; }
|
|
}
|
|
|
public class CurveQhdPoint
|
{
|
public CurveQhdPoint(double q, double h, double pd)
|
{
|
|
Q = q;
|
H = h;
|
Pd = pd;
|
}
|
public CurveQhdPoint() { }
|
public double Q { get; set; }
|
public double H { get; set; }
|
public double Pd { get; set; }
|
}
|
|
|
#endregion
|