using DevExpress.XtraRichEdit.Model;
using IStation.Epanet.Enums;
using IStation.Epanet;
using IStation.Model;
using IStation.WinFrmUI;
using System.Runtime;
using System.Text;
using IStation.Untity;
namespace IStation.Test
{
public class CorrectedStationScheduleModelHelper
{
private static int _ratedFrequency = 50;
///
/// 数据预处理
///
public static void StationDataPreproc(
Dictionary pumpScheduleDict,
List allStationRunRecordList,
List stationModelMappingList,
List pumpModelMappingList,
string modelFile
)
{
// 先过滤一波数据再传进来
if (VerifyNull(pumpScheduleDict))
{
return;
}
if (VerifyNull(allStationRunRecordList))
{
return;
}
var temp_id_build = new StringBuilder(31);
var code = EpanetMethods.ENopen(modelFile, "", "");
CheckCode(code);
code = EpanetMethods.ENopenH();
if ((int)code > 6)
{
throw new Exception($"ENopenH:{code}");
}
var curvePointCount = 100;
foreach (var mapping in pumpModelMappingList)
{
var flag = mapping.Flag;
var pumpSchedule = pumpScheduleDict[flag];
code = EpanetMethods.ENgetlinkindex(mapping.PumpId, out int pumpIndex);
CheckCode(code);
if (!string.IsNullOrEmpty(mapping.FlowId))
{
code = EpanetMethods.ENgetlinkindex(mapping.FlowId, out int flowIndex);
CheckCode(code);
mapping.FlowIndex = flowIndex;
}
code = EpanetMethods.ENgetnodeindex(mapping.PressureId, out int pressureIndex);
CheckCode(code);
code = EpanetMethods.ENgetcurveindex(mapping.CurveId, out int curveIndex);
CheckCode(code);
mapping.PumpIndex = pumpIndex;
mapping.PressureIndex = pressureIndex;
mapping.CurveIndex = curveIndex;
var curveQH = pumpSchedule.CurveQH;
var fitPtList = curveQH.GetFitPoints(curvePointCount);
var xList = fitPtList.Select(x => (float)x.X).ToArray();
var yList = fitPtList.Select(x => (float)x.Y).ToArray();
if (!CheckFitPointList(xList, yList))
{
throw new Exception($"CheckFitPointList: false");
}
code = EpanetMethods.ENsetcurve(mapping.CurveIndex, xList, yList, xList.Length);
CheckCode(code);
}
foreach (var mapping in stationModelMappingList)
{
code = EpanetMethods.ENgetlinkindex(mapping.FlowId, out int flowIndex);
CheckCode(code);
code = EpanetMethods.ENgetnodeindex(mapping.PressureId, out int pressureIndex);
CheckCode(code);
mapping.PressureIndex = pressureIndex;
mapping.FlowIndex = flowIndex;
}
var pumpModelMappingDict = pumpModelMappingList.ToDictionary(x => x.Flag, y => y);
var pattern_id_list = AnalysisHelper.GetPatternIdList();
var pattern_id_dict = new Dictionary();
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();
var vm_diff_list = new List();
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 pipeFlowIdList)
{
if (model_record_dict[id] < 1)
{
pipe_flow_err = false;
break;
}
}
foreach (var id in pipePressureIdList)
{
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];
}
code = EpanetMethods.ENsetpattern(pattern_index, new float[] { pattern_value }, 1);
if ((int)code > 6)
{
throw new Exception($"ENsetpattern:{code}");
}
}
code = EpanetMethods.ENinitH(0);
if ((int)code > 6)
{
throw new Exception($"ENinitH:{code}");
}
code = EpanetMethods.ENrunH(out _);
if ((int)code > 6)
{
throw new Exception($"ENrunH:{code}");
}
foreach (var pump_record in pump_allStationRecordList)
{
var flag = pump_record.Flag;
var pump = flagPumpDict[flag];
var qh = flagQhCurveDict[flag];
var mapping = pumpModelMappingDict[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;
code = EpanetMethods.ENgetlinkvalue(mapping.PumpIndex, LinkValue.Flow, out float model_flow);
if ((int)code > 6)
{
throw new Exception($"ENgetnodevalue:{code}");
}
if (Math.Abs(model_flow) < 1)
{
break;
}
code = EpanetMethods.ENgetnodevalue(mapping.PressureIndex, NodeValue.Pressure, out float model_outlet_pressure);
if ((int)code > 6)
{
throw new Exception($"ENgetnodevalue:{code}");
}
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];
code = EpanetMethods.ENgetlinkvalue(mapping.FlowIndex, LinkValue.Flow, out float model_flow);
if ((int)code > 6)
{
throw new Exception($"ENgetnodevalue:{code}");
}
code = EpanetMethods.ENgetnodevalue(mapping.PressureIndex, NodeValue.Pressure, out float model_outlet_pressure);
if ((int)code > 6)
{
throw new Exception($"ENgetnodevalue:{code}");
}
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);
}
}
code = EpanetMethods.ENcloseH();
if ((int)code > 6)
{
throw new Exception($"ENcloseH:{code}");
}
code = EpanetMethods.ENclose();
if ((int)code > 6)
{
throw new Exception($"ENclose:{code}");
}
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>();
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();
}
///
/// 数据预处理
///
public static void PumpDataPreproc(
Dictionary pumpScheduleDict,
List allPumpRunRecordList
)
{
// 先过滤一波数据再传进来
if (VerifyNull(pumpScheduleDict))
{
return;
}
if (VerifyNull(allPumpRunRecordList))
{
return;
}
var pumpRunRecordGroupByFlag = allPumpRunRecordList.GroupBy(x => x.Flag);
foreach (var flagGroup in pumpRunRecordGroupByFlag)
{
var flag = flagGroup.Key;
var pump = pumpScheduleDict[flag];
var pumpRunRecordGroupByHz = new Dictionary>();
var tempPumpRunRecordList = flagGroup.ToList();
if (pump.IsVariableFrequency)
{
var validList = FilterHead(tempPumpRunRecordList);
pumpRunRecordGroupByHz.Add(50, validList);
}
else
{
var tempHzGroup = tempPumpRunRecordList.OrderBy(x => x.Rpm).GroupBy(x =>
{
return (int)Math.Round(x.Rpm / pump.RatedSpeed * _ratedFrequency, 0);
});
foreach (var hzGroup in tempHzGroup)
{
var hz = hzGroup.Key;
var tempFilterList = FilterHead(hzGroup);
pumpRunRecordGroupByHz.Add(hz, tempFilterList);
}
}
foreach (var hzGroup in pumpRunRecordGroupByHz)
{
var hz = hzGroup.Key;
var similarCurveQH = SimilarCalculateHelper.CalculateQH(pump.CurveQH, _ratedFrequency, hz);
var curveQHPtList = similarCurveQH.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.FlowRate, x.Head)), Path.Combine(fullPath, $"{flag}_{hz}.csv"));
}
}
}
public static List FilterHead(IEnumerable list)
{
var pressures = list.Select(p => p.Head).ToList();
// 计算统计量
var (mean, stdDev) = DynamicThresholdProcessorHelper.CalculateStats(pressures);
double skewness = DynamicThresholdProcessorHelper.CalculateSkewness(pressures);
// 动态调整σ倍数
double sigmaMultiplier = DynamicThresholdProcessorHelper.CalculateSigmaMultiplier(skewness);
// var sigmaMultiplier = 3;//目前默认 标准差
// 计算边界
double lower = mean - sigmaMultiplier * stdDev;
double upper = mean + sigmaMultiplier * stdDev;
return list.Where(p => p.Head >= lower && p.Head <= upper).ToList();
}
static bool CheckFitPointList(float[] x, float[] y)
{
bool is_x_increasing = CheckIncreasing(x);
bool is_y_decreasing = CheckDecreasing(y);
if (!is_x_increasing)
{
Console.WriteLine("x不满足递增趋势");
return false;
}
if (!is_y_decreasing)
{
Console.WriteLine("y不满足递减趋势");
return false;
}
return true;
}
static bool CheckIncreasing(float[] values)
{
for (int i = 1; i < values.Length; i++)
{
if (values[i] < values[i - 1])
{
return false;
}
}
return true;
}
static bool CheckDecreasing(float[] values)
{
for (int i = 1; i < values.Length; i++)
{
if (values[i] > values[i - 1])
{
return false;
}
}
return true;
}
private static bool VerifyNull(IEnumerable