using DevExpress.XtraCharts; using IStation.Epanet; using IStation.Epanet.Enums; using IStation.Model; using IStation.Untity; using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.Drawing; using System.IO; using System.Linq; using System.Text; using static IStation.WinFrmUI.AnalysisHelper; namespace IStation.WinFrmUI.Monitor { public partial class ModelCorrectionComparePage : DocumentPage { public ModelCorrectionComparePage() { InitializeComponent(); this.PageTitle.Caption = "模型修正对比"; this.repositoryItemDateEdit1.SetOnlyShowYearMonth(); this.repositoryItemDateEdit2.SetOnlyShowYearMonth(); this.barEditDateStart.EditValue = new DateTime(2024, 9, 1); this.barEditDateEnd.EditValue = new DateTime(2024, 9, 1); this.barCekUseFlow.Checked = true; this.stationListCtrl1.FocusedChangedEvent += StationListCtrl1_FocusedChangedEvent; this.monitorDataSourcesTreeList1.FocusedChangedEvent += MonitorDataSourcesListCtrl1_FocusedChangedEvent; this.timeValueSwiftPlotChartView1.SetTimeAxisX(DevExpress.XtraCharts.DateTimeMeasureUnit.Minute); } #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; } [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 StationViewModel { [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 ModelCombineViewModel { public string Time { get; set; } public string RunFlags { get; set; } public double TotalFlow { get; set; } public Dictionary PressureDiffDevDict { get; set; } } public class PumpFactorViewModel { [Display(Name = "泵")] public int Flag { get; set; } [Display(Name = "频率")] public double Hz { get; set; } [Display(Name = "总体标准差")] public double? STDP { get; set; } [Display(Name = "扬程(STDP)")] public double? STDPHead { get; set; } [Display(Name = "备注")] public string Note { get; set; } public void Round() { if (this.STDP.HasValue) { this.STDP = Math.Round(this.STDP.Value, 5); } if (this.STDPHead.HasValue) { this.STDPHead = Math.Round(this.STDPHead.Value, 5); } } } #endregion private BLL.StationSignalRecordPacket _bll = new BLL.StationSignalRecordPacket(); private Model.Station _station = null; private Model.MonitorDataSources _monitorDataSources = null; private List> _pump_list = null; private List _model_diff_vm_list = null; private List _pump_vm_list = null; private string _model_file = System.IO.Path.Combine (Settings.File.RootDirectory, Settings.File.DataFolder, "ch2_v3_20240801(Clear).inp"); /// /// 清空数据 /// public void Clear() { _pump_vm_list = new List(); _model_diff_vm_list = new List(); this.timeValueSwiftPlotChartView1.ClearSeries(); } /// /// 初始化数据 /// public override void InitialDataSource() { this.stationListCtrl1.SetBindingData(); this.monitorDataSourcesTreeList1.SetBindingData(); } //泵站变换 private void StationListCtrl1_FocusedChangedEvent(Model.Station obj) { _station = obj; WaitFrmHelper.ShowWaitForm(); SetBindingData(_monitorDataSources, _station); WaitFrmHelper.HideWaitForm(); } //来源变换 private void MonitorDataSourcesListCtrl1_FocusedChangedEvent(Model.MonitorDataSources obj) { _monitorDataSources = obj; WaitFrmHelper.ShowWaitForm(); SetBindingData(_monitorDataSources, _station); WaitFrmHelper.HideWaitForm(); } /// /// 绑定数据 /// public void SetBindingData(Model.MonitorDataSources monitorDataSources, Model.Station station) { Clear(); if (monitorDataSources == null || station == null) { return; } if (this.barCekLoad.Checked) { return; } var station_index = station.SortCode; var dt_start = Convert.ToDateTime(this.barEditDateStart.EditValue); var dt_end = Convert.ToDateTime(this.barEditDateEnd.EditValue); var packets = _bll.Get(monitorDataSources.ID, station.ID); packets = packets?.Where(x => (x.Year >= dt_start.Year && x.Year <= dt_end.Year) && (x.Month >= dt_start.Month && x.Month <= dt_end.Month)).ToList(); if (packets == null || !packets.Any()) return; _pump_list = new BLL.Equipment().GetPumpListByBelongTypeAndBelongID(IStation.ObjectType.Station, station.ID); if (_pump_list == null || !_pump_list.Any()) { return; } var flag_pump_dict = _pump_list.ToDictionary(x => x.SortCode, x => x.RatedParas); var flag_list = _pump_list.Select(x => x.SortCode).OrderBy(x => x).ToList(); var record_list = packets.SelectMany(x => x.StationSignalRecords).ToList(); var root_folder = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "分析"); List ana_factor_list = null; var fileName = root_folder + "\\" + "AnalysisFactor.json"; if (File.Exists(fileName)) { var json = File.ReadAllText(fileName); ana_factor_list = JsonHelper.Json2Object>(json); } var pump_mapping_list = AnalysisHelper.GetPumpModelMappingList(); var station_mapping_list = AnalysisHelper.GetStationMappingList(); var pump_mapping_dict = pump_mapping_list.ToDictionary(x => x.Flag, x => x); var flag_qh_curve_dict = GetFlagCurveDict(); Set(_model_file, record_list, station_mapping_list, pump_mapping_dict, flag_pump_dict, flag_qh_curve_dict); } #region Color private List ColorArray = new List() { Color.Red, Color.Blue, Color.Green, Color.DodgerBlue, Color.Fuchsia, Color.MidnightBlue, Color.Maroon, Color.Aquamarine, Color.Bisque, Color.BurlyWood }; /// /// 获取随机颜色 /// /// private Color GetRandomColor(int count) { if (count < ColorArray.Count) { return ColorArray[count]; } return ColorHelper.GetRandomColor(); } #endregion private bool CheckFitPointList(List 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 Dictionary GetFlagCurveDict() { var dict = new Dictionary(); 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; } //加载 private void barCekLoad_CheckedChanged(object sender, DevExpress.XtraBars.ItemClickEventArgs e) { WaitFrmHelper.ShowWaitForm(); SetBindingData(_monitorDataSources, _station); WaitFrmHelper.HideWaitForm(); } // 刷新数据 private void barBtnRefresh_ItemClick(object sender, DevExpress.XtraBars.ItemClickEventArgs e) { InitialDataSource(); } /// ///模型验证得出分析系数 // 用分析系数分析模型组合偏差 // 再用分析系数和模型组合偏差分析得出对比 /// public void Set ( string model_inp, List station_record_list, List station_mapping_list, Dictionary pump_mapping_dict, Dictionary flag_pump_dict, Dictionary flag_qh_curve_dict ) { var first_tuple = ModelSet(model_inp, station_record_list, station_mapping_list, pump_mapping_dict, flag_pump_dict, flag_qh_curve_dict); if (first_tuple == null) { Clear(); return; } var first_vm_pump_list = first_tuple.Item1; var first_vm_station_list = first_tuple.Item2; if (first_vm_pump_list == null || !first_vm_pump_list.Any()) { Clear(); return; } var flag_hz_pressure_diff_dev_list = first_vm_pump_list.Select(x => new Tuple(x.Flag, x.Hz0, x.PressureDiffDev, x.ModelFlow)).ToList(); var ana_factor_list = AnalysisFactorSet(flag_pump_dict, flag_hz_pressure_diff_dev_list, this.barCekUseFlow.Checked); if (ana_factor_list == null || !ana_factor_list.Any()) { Clear(); return; } var flag_hz_head_dev_dict = ana_factor_list.GroupBy(x => x.Flag).ToDictionary(x => x.Key, y => y.ToDictionary(k => k.Hz, ky => ky.HeadDeviation ?? 0)); var second_tuple = ModelSet(model_inp, station_record_list, station_mapping_list, pump_mapping_dict, flag_pump_dict, flag_qh_curve_dict, flag_hz_head_dev_dict); if (second_tuple == null) { Clear(); return; } var second_vm_pump_list = second_tuple.Item1; var second_vm_station_list = second_tuple.Item2; var vm_combine_list = second_vm_pump_list .GroupBy(x => x.Time) .Select(group => { var time = group.Key; var run_flags = group.Select(x => x.Flag).OrderBy(x => x).ToList(); var total_flow = group.Sum(x => x.Flow); if (total_flow < 1) total_flow = group.Sum(x => x.ModelFlow); var dev_dict = group.ToDictionary(x => x.Flag, y => y.PressureDiffDev); var vm_combine = new ModelCombineViewModel(); vm_combine.Time = group.Key; vm_combine.RunFlags = IStation.Untity.IntListHelper.ToString(run_flags); vm_combine.TotalFlow = total_flow; vm_combine.PressureDiffDevDict = dev_dict; return vm_combine; }).ToList(); var run_flags_flow_pressure_diff_dev_dict = vm_combine_list .Select(x => new Tuple>(x.RunFlags, x.TotalFlow, x.PressureDiffDevDict)) .ToList(); var ana_deviation_list = AnalysisDeviationSet(flag_pump_dict, run_flags_flow_pressure_diff_dev_dict); if (ana_deviation_list == null || !ana_deviation_list.Any()) { Clear(); return; } var third_tuple = ModelSet(model_inp, station_record_list, station_mapping_list, pump_mapping_dict, flag_pump_dict, flag_qh_curve_dict, flag_hz_head_dev_dict, ana_deviation_list); if (third_tuple == null) { Clear(); return; } var third_vm_pump_list = third_tuple.Item1; var third_vm_station_list = third_tuple.Item2; int first_count = 0; int second_count = 0; //var first_group = first_vm_station_list.GroupBy(x => x.Name); //for (int i = 0; i < first_group.Count(); i++) //{ // var color = GetRandomColor(i); // var item = first_group.ElementAt(i); // var name = item.Key; // var list = item.ToList(); // var pressure_diff_list = list // .Where(x => !(Math.Abs(x.PressureDiff) > 2)) // .Select(x => new TimeValue(x.Date, x.PressureDiff)) // .ToList(); // this.timeValueSwiftPlotChartView1.AddSwiftPlotSeries(name, color, name + "(原始)", "压力", pressure_diff_list); //} //count = first_group.Count(); var second_group = second_vm_station_list.GroupBy(x => x.Name); for (int i = 0; i < second_group.Count(); i++) { var color = GetRandomColor(i + first_count); var item = second_group.ElementAt(i); var name = item.Key; var pressure_diff_list = item.Select(x => x.PressureDiff).ToList(); FilterOutliersHelper.STDEV(pressure_diff_list.ToArray(), out double std_dev, out double stdp); var list = item .Where(x => !(Math.Abs(x.PressureDiff) > stdp * 3)) .Select(x => new TimeValue(x.Date, x.PressureDiff)) .ToList(); var er_list = item .Where(x => Math.Abs(x.PressureDiff) > stdp * 3) .Select(x => new TimeValue(x.Date, x.PressureDiff)) .ToList(); this.timeValueSwiftPlotChartView1.AddSwiftPlotSeries(name, color, name + "(修正)", "压力", list); } second_count = second_group.Count(); var third_group = third_vm_station_list.GroupBy(x => x.Name); for (int i = 0; i < third_group.Count(); i++) { var color = GetRandomColor(i + first_count+second_count); var item = third_group.ElementAt(i); var name = item.Key; var pressure_diff_list = item.Select(x => x.PressureDiff).ToList(); FilterOutliersHelper.STDEV(pressure_diff_list.ToArray(), out double std_dev, out double stdp); var list = item .Where(x => !(Math.Abs(x.PressureDiff) > stdp * 3)) .Select(x => new TimeValue(x.Date, x.PressureDiff)) .ToList(); var er_list = item .Where(x => Math.Abs(x.PressureDiff) > stdp * 4) .Select(x => new TimeValue(x.Date, x.PressureDiff)) .ToList(); this.timeValueSwiftPlotChartView1.AddSwiftPlotSeries(name, color, name + "(二次修正)", "压力", list); } } private Tuple, List> ModelSet ( string model_inp, List station_record_list, List station_mapping_list, Dictionary pump_mapping_dict, Dictionary flag_pump_dict, Dictionary flag_qh_curve_dict, Dictionary> flag_hz_head_dev_dict = null, List ana_dev_list = null, int fit_point_count = 100 ) { var model_id_builder = new StringBuilder(31); var err = EpanetMethods.ENopen(model_inp, "", ""); if ((int)err > 6) { throw new Exception($"ENopen:{err}"); } err = EpanetMethods.ENopenH(); if ((int)err > 6) { throw new Exception($"ENopenH:{err}"); } foreach (var item in pump_mapping_dict) { var flag = item.Key; var mapping = item.Value; if (EpanetMethods.ENgetlinkindex(mapping.PumpId, out int pump_index) != ErrorCode.Ok) throw new Exception($"ENgetlinkindex:{err}"); if (!string.IsNullOrEmpty(mapping.FlowId)) { if (EpanetMethods.ENgetlinkindex(mapping.FlowId, out int flow_index) != ErrorCode.Ok) throw new Exception($"ENgetlinkindex:{err}"); mapping.FlowIndex = flow_index; } if (EpanetMethods.ENgetnodeindex(mapping.PressureId, out int pressure_index) != ErrorCode.Ok) throw new Exception($"ENgetnodeindex:{err}"); if (EpanetMethods.ENgetcurveindex(mapping.CurveId, out int curve_index) != ErrorCode.Ok) throw new Exception($"ENgetcurveindex:{err}"); mapping.PumpIndex = pump_index; mapping.PressureIndex = pressure_index; mapping.CurveIndex = curve_index; var qh = flag_qh_curve_dict[flag]; var fit_point_list = qh.GetFitPoints(fit_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, fit_point_count); if (!cek) { throw new Exception($"CheckFitPointList: false"); } err = EpanetMethods.ENsetcurve(mapping.CurveIndex, flow_list, head_list, fit_point_count); if (err != 0) { throw new Exception($"ENsetcurve:{err}"); } } foreach (var mapping in station_mapping_list) { if (EpanetMethods.ENgetlinkindex(mapping.FlowId, out int flow_index) != ErrorCode.Ok) throw new Exception($"ENgetlinkindex:{err}"); if (EpanetMethods.ENgetnodeindex(mapping.PressureId, out int pressure_index) != ErrorCode.Ok) throw new Exception($"ENgetnodeindex:{err}"); mapping.PressureIndex = pressure_index; mapping.FlowIndex = flow_index; } 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_pump_list = new List(); var vm_station_list = new List(); foreach (var station_record in station_record_list) { var time = station_record.Time.ToString("G"); var model_record_dict = station_record.ModelRecordDict; var pump_record_list = station_record.PumpSignalRecords; if (pump_record_list.Exists(x => x.Flag != 15 && x.Flag != 16 && x.Rpm < 1)) { continue; } if (pump_record_list.Exists(x => x.OutletPressure > 50)) { continue; } //if (ana_dev_list != null && ana_dev_list.Any()) //{ // var run_flags = pump_record_list.Select(x => x.Flag).OrderBy(x => x).ToList(); // var ana_dev = ana_dev_list.Find(x => x.RunFlags.SequenceEqual(run_flags)); // if (ana_dev != null) // { // var wl_dict = AnalysisHelper.GetWLDict(ana_dev.PressureDiff); // foreach (var item in wl_dict) // { // var code = item.Key; // var value=item.Value; // if (model_record_dict.ContainsKey(code)) // { // var wl = model_record_dict[code]- value; // model_record_dict[code] = wl; // } // } // } //} //设置模式 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}"); } } //是否使用修正系数更新曲线 if (flag_hz_head_dev_dict != null && flag_hz_head_dev_dict.Any()) { AnalysisDeviationDto ana_dev = null; if (ana_dev_list != null && ana_dev_list.Any()) { var run_flags = pump_record_list.Select(x => x.Flag).OrderBy(x => x).ToList(); ana_dev = ana_dev_list.Find(x => x.RunFlags.SequenceEqual(run_flags)); } foreach (var pump_record in pump_record_list) { var flag = pump_record.Flag; var pump = flag_pump_dict[flag]; var mapping = pump_mapping_dict[flag]; var rpm_ratio = pump_record.Rpm / pump.Nr; if (!pump.IsBp) rpm_ratio = 1; if (rpm_ratio <= 0.1) continue; var hz0 = Math.Round(rpm_ratio * 50, 0); if (hz0 > 50) hz0 = 50; if (!flag_hz_head_dev_dict.ContainsKey(flag)) throw new Exception($"!flag_hz_head_dev.ContainsKey(flag):{flag}"); if (!flag_hz_head_dev_dict[flag].ContainsKey(hz0)) throw new Exception($"!flag_hz_head_dev[flag].ContainsKey(hz0):{flag} {hz0}"); var qh = flag_qh_curve_dict[flag]; var fit_pt_list = qh.GetFitPoints(fit_point_count); var head_dev = (float)flag_hz_head_dev_dict[flag][hz0]; if (head_dev != 0) { var head_dev_v = head_dev; if (ana_dev != null) { head_dev_v -= (float)ana_dev.PressureDiff[flag]; } var pt_list = qh.DefinePoints.Select(x => new Model.CurvePoint(x.X, x.Y + head_dev_v)).ToList(); var qh_ct = Model.FitCurveHelper.BuildCurveExpress(pt_list, Model.eCurveFitType.CubicCurve); fit_pt_list = qh_ct.GetFitPoints(fit_point_count); } var x_array = fit_pt_list.Select(x => (float)x.X).ToArray(); var y_array = fit_pt_list.Select(x => (float)x.Y).ToArray(); err = EpanetMethods.ENsetcurve(mapping.CurveIndex, x_array, y_array, fit_point_count); if ((int)err > 6) { throw new Exception($"ENsetcurve:{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_record_list) { var flag = pump_record.Flag; var pump = flag_pump_dict[flag]; var qh = flag_qh_curve_dict[flag]; var mapping = pump_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); if (hz > 50) hz = 50; 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(model_pressure_diff - pressure_diff, 3); vm.FlowDiff = Math.Round(flow_diff, 1); vm_pump_list.Add(vm); } foreach (var mapping in station_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 StationViewModel(); 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_station_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}"); return new Tuple, List>(vm_pump_list, vm_station_list); } public List AnalysisFactorSet ( Dictionary flag_pump_dict, List> flag_hz_pressure_diff_list, bool use_flow = false ) { if (flag_pump_dict == null || !flag_pump_dict.Any()) return default; if (flag_hz_pressure_diff_list == null || !flag_hz_pressure_diff_list.Any()) return default; var opt_std_dev_pop = 0.3; var range_hz = 5; //分析范围内的系数 var flag_range_hz_pressure_diff_dict = new Dictionary>>(); var group_by_flag = flag_hz_pressure_diff_list.GroupBy(x => x.Item1); foreach (var item in group_by_flag) { var flag = item.Key; var pump = flag_pump_dict[flag]; if (!pump.IsBp) continue; for (double i = 20; i <= 50; i += range_hz) { var min_hz = i - range_hz; var max_hz = i; var list = item.Where(x => x.Item2 >= min_hz && x.Item2 <= max_hz).ToList(); if (list == null || list.Count() < 10) continue; var pressure_diff_list = list.Select(x => x.Item3).ToList(); var pressure_diff_filter_tuple = AnalysisHelper.GetFilterBySTDP(pressure_diff_list.ToArray(), opt_std_dev_pop, 0, 2); var pressure_diff_filter_array = pressure_diff_filter_tuple.Item1; var pressure_diff_std_dev_pop = pressure_diff_filter_tuple.Item2; var pressure_diff_std_dev_pop_head_avg = pressure_diff_filter_array.Average(); var std_dev_pop = pressure_diff_std_dev_pop; var diff_avg = pressure_diff_std_dev_pop_head_avg; var count = pressure_diff_filter_array.Count(); if (use_flow) { var flow_list = list.Select(x => x.Item4).ToList(); var flow_filter_tuple = AnalysisHelper.GetFilterBySTDP(flow_list.ToArray(), 50, 0, 2); var flow_filter_array = flow_filter_tuple.Item1; var flow_std_dev_pop = flow_filter_tuple.Item2; var flow_std_dev_pop_head_avg = flow_filter_array.Average(); var diff_V = Model.CurveCalcuHelper.CalculateOtherPress(flow_std_dev_pop_head_avg, pump.Ic, pump.Oc, null, null); var head_diff_avg = -(pressure_diff_std_dev_pop_head_avg + diff_V); diff_avg = head_diff_avg; } if (!flag_range_hz_pressure_diff_dict.ContainsKey(flag)) flag_range_hz_pressure_diff_dict.Add(flag, new Dictionary>()); flag_range_hz_pressure_diff_dict[flag].Add(max_hz, new Tuple(std_dev_pop, diff_avg, count)); } } if (!flag_range_hz_pressure_diff_dict.Any()) { return default; } //分析1hz范围内的系数 var exist_data_dto_list = new List(); var group_by_flag_hz = flag_hz_pressure_diff_list.GroupBy(x => new { x.Item1, x.Item2 }); foreach (var item in group_by_flag_hz) { var hz = item.Key.Item2; if (hz < 20) continue; var list = item.ToList(); if (list.Count() < 5) continue; var flag = item.Key.Item1; var pump = flag_pump_dict[flag]; var pressure_diff_list = list.Select(x => x.Item3).ToList(); var pressure_diff_filter_tuple = AnalysisHelper.GetFilterBySTDP(pressure_diff_list.ToArray(), opt_std_dev_pop); var pressure_diff_filter_array = pressure_diff_filter_tuple.Item1; var pressure_diff_std_dev_pop = pressure_diff_filter_tuple.Item2; var pressure_diff_std_dev_pop_head_avg = pressure_diff_filter_array.Average(); if (Math.Abs(pressure_diff_std_dev_pop) > 1) continue; if (Math.Abs(pressure_diff_std_dev_pop) > 0.5 && list.Count() < 10) continue; if (Math.Abs(pressure_diff_std_dev_pop_head_avg) > 5) continue; var std_dev_pop = pressure_diff_std_dev_pop; var diff_avg = pressure_diff_std_dev_pop_head_avg; var count = pressure_diff_filter_array.Count(); if (use_flow) { var flow_list = list.Select(x => x.Item4).ToList(); var flow_filter_tuple = AnalysisHelper.GetFilterBySTDP(flow_list.ToArray(), 50, 0, 2); var flow_filter_array = flow_filter_tuple.Item1; var flow_std_dev_pop = flow_filter_tuple.Item2; var flow_std_dev_pop_head_avg = flow_filter_array.Average(); var diff_V = Model.CurveCalcuHelper.CalculateOtherPress(flow_std_dev_pop_head_avg, pump.Ic, pump.Oc, null, null); var head_diff_avg = -(pressure_diff_std_dev_pop_head_avg + diff_V); diff_avg = head_diff_avg; } var dto = new AnalysisHelper.AnalysisFactorDto(); dto.Flag = flag; dto.Hz = hz; dto.HeadSTDP = std_dev_pop; dto.HeadDeviation = diff_avg; dto.Accuracy = 0; dto.Count = count; exist_data_dto_list.Add(dto); } exist_data_dto_list = exist_data_dto_list.OrderBy(x => x.Flag).ThenBy(x => x.Hz).ToList(); //相似换算修正系数(不存在监测数据的频率) var similar_dto_list = new List(); foreach (var item_pump in flag_pump_dict) { var flag = item_pump.Key; var pump = item_pump.Value; if (!pump.IsBp) continue; if (!flag_range_hz_pressure_diff_dict.ContainsKey(flag)) continue; var item_hz = flag_range_hz_pressure_diff_dict[flag]; for (int hz = 1; hz <= 50; hz++) { if (exist_data_dto_list.Exists(x => x.Flag == flag && x.Hz == hz)) continue; var hz0 = (hz / range_hz + 1) * range_hz; if (hz0 > 50) hz0 = 50; if (item_hz.ContainsKey(hz0)) { var tuple = item_hz[hz0]; var analysis_facotr = new AnalysisHelper.AnalysisFactorDto(); analysis_facotr.Flag = flag; analysis_facotr.Hz = hz; analysis_facotr.HeadSTDP = tuple.Item1; analysis_facotr.HeadDeviation = tuple.Item2; analysis_facotr.Accuracy = 0; similar_dto_list.Add(analysis_facotr); } else { var hz_list = item_hz.Select(x => x.Key).ToList(); var similar_hz = hz_list.Where(x => x >= hz0)?.OrderBy(x => x).FirstOrDefault(); if (similar_hz == null || similar_hz.Value == 0) similar_hz = hz_list.OrderByDescending(x => x).FirstOrDefault(); if (similar_hz == null) throw new Exception("similar_hz error"); var tuple = item_hz[similar_hz.Value]; var similar_ratio = hz / similar_hz.Value; var head_dev = tuple.Item2 * similar_ratio; var head_stdp = tuple.Item1 * similar_ratio; var analysis_facotr = new AnalysisHelper.AnalysisFactorDto(); analysis_facotr.Flag = flag; analysis_facotr.Hz = hz; analysis_facotr.HeadSTDP = head_stdp; analysis_facotr.HeadDeviation = head_dev; analysis_facotr.Accuracy = -1; similar_dto_list.Add(analysis_facotr); } } } var all_analysis_factor_list = new List(); all_analysis_factor_list.AddRange(exist_data_dto_list); all_analysis_factor_list.AddRange(similar_dto_list); all_analysis_factor_list = all_analysis_factor_list.OrderBy(x => x.Flag).ThenBy(x => x.Hz).ToList(); return all_analysis_factor_list; } public List AnalysisDeviationSet ( Dictionary flag_pump_dict, List>> run_flags_flow_pressure_diff_dev_dict, double minQ = 0, double maxQ = 100000, double spaceQ = 1000 ) { if (flag_pump_dict == null || !flag_pump_dict.Any()) return default; if (run_flags_flow_pressure_diff_dev_dict == null || !run_flags_flow_pressure_diff_dev_dict.Any()) return default; var list = new List(); var is_error_value = false; for (double current_minQ = minQ; current_minQ <= maxQ; current_minQ += spaceQ) { var current_maxQ = current_minQ + spaceQ; var combine_list = run_flags_flow_pressure_diff_dev_dict.Where(x => x.Item2 >= current_minQ && x.Item2 <= current_maxQ).ToList(); if (combine_list == null || !combine_list.Any()) continue; var group_by_run_flags = combine_list.GroupBy(x => x.Item1); foreach (var item_run_flags in group_by_run_flags) { if (item_run_flags.Count() < 5) continue; var flags = item_run_flags.Key; var dev_dict = new Dictionary(); var flag_dev_list = item_run_flags.SelectMany(x => x.Item3.Select(d => new Tuple(d.Key, d.Value))).ToList(); var group_by_flag = flag_dev_list.GroupBy(x => x.Item1); foreach (var flag_item in group_by_flag) { var flag = flag_item.Key; var dev_array = flag_item.Select(x => x.Item2).ToArray(); var filter_std_dev_pop_tuple = AnalysisHelper.GetFilterBySTDP(dev_array); var filter_std_dev_pop_array = filter_std_dev_pop_tuple.Item1; var std_dev_pop = filter_std_dev_pop_tuple.Item2; var std_dev_pop_pressure_diff_dev_avg = filter_std_dev_pop_array.Average(); var dev_avg = std_dev_pop_pressure_diff_dev_avg; dev_avg = Math.Round(dev_avg, 5); dev_dict.Add(flag, dev_avg); } is_error_value = false; foreach (var dev in dev_dict) { if (Math.Abs(dev.Value) > 3) { is_error_value = true; break; } } if (is_error_value) continue; var vm = new AnalysisDeviationDto(); vm.RunFlags = IStation.Untity.IntListHelper.ToList(flags); vm.MinFlow = current_minQ; vm.MaxFlow = current_maxQ; vm.Count = item_run_flags.Count(); vm.PressureDiff = dev_dict; list.Add(vm); } } return list; } } }