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.IO; using System.Linq; using System.Text; namespace IStation.WinFrmUI.Monitor { public partial class ModelCorrectionCombinePage1 : DocumentPage { public ModelCorrectionCombinePage1() { InitializeComponent(); this.PageTitle.Caption = "模型修正组合"; this.gridView1.SetNormalView(); this.gridView2.SetNormalView(); this.repositoryItemDateEdit1.SetOnlyShowYearMonth(); this.repositoryItemDateEdit2.SetOnlyShowYearMonth(); this.barEditDateStart.EditValue = new DateTime(2024, 9, 1); this.barEditDateEnd.EditValue = new DateTime(2024, 9, 1); this.stationListCtrl1.FocusedChangedEvent += StationListCtrl1_FocusedChangedEvent; this.monitorDataSourcesTreeList1.FocusedChangedEvent += MonitorDataSourcesListCtrl1_FocusedChangedEvent; } #region ViewModel 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() { this.STDP = Math.Round(this.STDP, 5); this.STDPHead = Math.Round(this.STDPHead, 5); } } /// /// 模型组合偏差 /// public class ModelCombineDiffViewModel { [Display(Name = "运行组合")] public string RunFlags { get; set; } [Display(Name = "最小流量")] public double MinFlow { get; set; } [Display(Name = "最大流量")] public double MaxFlow { get; set; } [Display(Name = "模型偏差")] public string ModelDeviation { get; set; } [Display(Name = "数量")] public int Count { get; set; } } /// /// 模型组合偏差 /// public class ModelViewModel { public string Time { get; set; } public List RunFlags { get; set; } public string RunFlagsStr { get; set; } public int RunCount { get; set; } public double TotalFlow { get; set; } public double PumpTotalFlow { get; set; } public Dictionary ModelDeviation { get; set; } } #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 _model_vm_list = null; private string _model_file = System.IO.Path.Combine (Settings.File.RootDirectory, Settings.File.DataFolder, "ch2_v3_20240918(Clear).inp"); /// /// 清空数据 /// public void Clear() { _model_diff_vm_list = new List(); this.modelDiffViewModelBindingSource.DataSource = new List(); } /// /// 初始化数据 /// 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 + "\\" + station.Name + ".json"; if (File.Exists(fileName)) { var json = File.ReadAllText(fileName); ana_factor_list = JsonHelper.Json2Object>(json); } SetBindingData(_model_file, flag_pump_dict, record_list, ana_factor_list, this.barCekUseAnalysisFactor.Checked); } /// /// 绑定数据 /// public void SetBindingData ( string model_inp, Dictionary flag_pump_dict, List record_list, List ana_factor_list, bool use_ana_factor ) { if (!File.Exists(model_inp)) { throw new Exception($"model_inp:is null"); } 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 model_id_tuple = AnalysisFactorHelper.GetModelIdList(); var flow_id_list = model_id_tuple.Item1; var pressure_id_list = model_id_tuple.Item2; var pump_id_list = model_id_tuple.Item3; var pump_flag_dict = AnalysisFactorHelper.GetPumpIdFlagDict(); var flag_pump_id_dict = AnalysisFactorHelper.GetFlagPumpIdDict(); var pattern_id_list = AnalysisFactorHelper.GetPatternIdList(); var curve_id_dict = AnalysisFactorHelper.GetCurveIdDict(); var flow_pump_dict = AnalysisFactorHelper.GetFlowPumpDict(); var pressure_pump_dict = AnalysisFactorHelper.GetPressurePumpDict(); var model_flow_mapping_dict = AnalysisFactorHelper.GetModelFlowIdMappingDict(); var model_pressure_mapping_dict = AnalysisFactorHelper.GetModelPressureIdMappingDict(); var flow_id_dict = new Dictionary(); var pressure_id_dict = new Dictionary(); var pump_id_dict = new Dictionary(); var pattern_id_dict = new Dictionary(); var flag_curve_dict = new Dictionary>(); var curve_point_count = 100; foreach (var id in flow_id_list) { if (EpanetMethods.ENgetlinkindex(id, out int index) != ErrorCode.Ok) continue; flow_id_dict.Add(id, index); } foreach (var id in pressure_id_list) { if (EpanetMethods.ENgetnodeindex(id, out int index) != ErrorCode.Ok) continue; pressure_id_dict.Add(id, index); } foreach (var id in pump_id_list) { if (EpanetMethods.ENgetlinkindex(id, out int index) != ErrorCode.Ok) continue; pump_id_dict.Add(id, index); } foreach (var id in pattern_id_list) { if (EpanetMethods.ENgetpatternindex(id, out int index) != ErrorCode.Ok) continue; pattern_id_dict.Add(id, index); } var pump_curve_dict = GetPumpCurveDict(); foreach (var item in curve_id_dict) { var curve_id = item.Key; var flag = item.Value; var pump_id = flag_pump_id_dict[flag]; var qh = pump_curve_dict[flag]; qh = Model.FitCurveHelper.BuildCurveExpress(qh.DefinePoints, eCurveFitType.CubicCurve); if (EpanetMethods.ENgetcurveindex(curve_id, out int index) != ErrorCode.Ok) continue; 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 bol = CheckFitPointList(fit_point_list, curve_point_count); if (!bol) { throw new Exception($"CheckFitPointList: false"); } err = EpanetMethods.ENsetcurve(index, flow_list, head_list, curve_point_count); if (err != 0) { throw new Exception($"ENsetcurve:{err}"); } flag_curve_dict.Add(pump_id, new Tuple(curve_id, index)); } var vm_list = new List(); foreach (var record in record_list) { var time = record.Time.ToString("G"); var model_record_dict = record.ModelRecordDict; 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 (ana_factor_list != null && ana_factor_list.Any() && use_ana_factor) { foreach (var item in pump_id_dict) { var pump_id = item.Key; if (!model_record_dict.ContainsKey(pump_id)) continue; var flag = pump_flag_dict[pump_id]; var pump_ratio = model_record_dict[pump_id]; if (pump_ratio <= 0.3) continue; var hz = Math.Round(pump_ratio * 50); var ana_factor = ana_factor_list.Find(x => x.Hz == hz && x.Flag == flag); if (ana_factor == null) { throw new Exception($"ana_factor:is null"); } var qh = pump_curve_dict[flag]; var head_dev = (float)ana_factor.HeadDeviation; var fit_point_list = new List(curve_point_count); if (head_dev == 0) { fit_point_list = qh.GetFitPoints(curve_point_count); } else { var pt_list_ct = qh.DefinePoints.Select(x => new Model.CurvePoint(x.X, x.Y + head_dev)).ToList(); var qh_ct = Model.FitCurveHelper.BuildCurveExpress(pt_list_ct, Model.eCurveFitType.CubicCurve); fit_point_list = qh_ct.GetFitPoints(curve_point_count); } var x_list = fit_point_list.Select(x => (float)x.X).ToList(); var y_list = fit_point_list.Select(x => (float)x.Y).ToList(); //待判断 var curve_index = flag_curve_dict[pump_id].Item2; err = EpanetMethods.ENsetcurve(curve_index, x_list.ToArray(), y_list.ToArray(), curve_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}"); } var vm = new ModelViewModel(); vm.Time = time; vm.ModelDeviation = new Dictionary(); vm.RunCount = record.PumpRunCount; vm.RunFlags = record.PumpSignalRecords.Select(x => x.Flag).OrderBy(x => x).ToList(); vm.RunFlagsStr = IntListHelper.ToString(vm.RunFlags); foreach (var item in pump_id_dict) { var pump_id = item.Key; if (!model_record_dict.ContainsKey(pump_id)) continue; var flag = pump_flag_dict[pump_id]; var index = item.Value; err = EpanetMethods.ENgetlinkvalue(index, LinkValue.Flow, out float model_value); if ((int)err > 6) { throw new Exception($"ENgetnodevalue:{err}"); } vm.PumpTotalFlow += model_value; } foreach (var item in flow_id_dict) { var flow_id = item.Key; var scada_id = model_flow_mapping_dict[flow_id]; if (!model_record_dict.ContainsKey(scada_id)) continue; var scada_value = model_record_dict[scada_id]; if (flow_pump_dict.ContainsKey(flow_id)) continue; var index = item.Value; err = EpanetMethods.ENgetlinkvalue(index, LinkValue.Flow, out float model_value); if ((int)err > 6) { throw new Exception($"ENgetnodevalue:{err}"); } model_value = Math.Abs(model_value); vm.TotalFlow += model_value; } foreach (var item in pressure_id_dict) { var pressure_id = item.Key; var scada_id = model_pressure_mapping_dict[pressure_id]; if (!model_record_dict.ContainsKey(scada_id)) continue; var scada_value = model_record_dict[scada_id]; if (!pressure_pump_dict.ContainsKey(pressure_id)) continue; var pump = pressure_pump_dict[pressure_id]; var pump_ratio = model_record_dict[pump.Item1]; if (pump_ratio <= 0.3) continue; var flag = pump.Item2; var index = item.Value; err = EpanetMethods.ENgetnodevalue(index, NodeValue.Head, out float model_value); if ((int)err > 6) { throw new Exception($"ENgetnodevalue:{err}"); } var diff_vlaue = scada_value - model_value; if (Math.Abs(diff_vlaue)>10) { } vm.ModelDeviation.Add(flag, diff_vlaue); } vm_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()) { _model_diff_vm_list = new List(); var minQ = 20000; var maxQ = 140000; var spaceQ = 1000; for (int currentMinQ = minQ; currentMinQ <= maxQ; currentMinQ += spaceQ) { var currentMaxQ = currentMinQ + spaceQ; var list = vm_list .Where(x => x.TotalFlow >= currentMinQ && x.TotalFlow <= currentMaxQ) .ToList(); if (list == null || !list.Any()) continue; var group = list.GroupBy(x => x.RunFlagsStr); foreach (var item in group) { if (item.Count() < 5) continue; var run_flags = item.Key; var model_diff_vm = new ModelCombineDiffViewModel(); model_diff_vm.RunFlags = run_flags; model_diff_vm.Count = item.Count(); model_diff_vm.MinFlow = currentMinQ; model_diff_vm.MaxFlow = currentMaxQ; var model_deviation_dict = new Dictionary(); List> tuple_list = item.SelectMany(x => x.ModelDeviation.Select(d => new Tuple(d.Key, d.Value))).ToList(); var group_by_flag = tuple_list.GroupBy(x => x.Item1); foreach (var flag_item in group_by_flag) { var flag = flag_item.Key; var head_diff_array = flag_item.Select(x => x.Item2).ToArray(); var filter_std_dev_pop_tuple = AnalysisFactorHelper.GetFilterBySTDP(head_diff_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_head_avg = filter_std_dev_pop_array.Average(); var head_diff_avg = std_dev_pop_head_avg; head_diff_avg = Math.Round(head_diff_avg, 5); model_deviation_dict.Add(flag, head_diff_avg); } model_diff_vm.ModelDeviation = JsonHelper.Object2Json(model_deviation_dict); var error = false; foreach (var item_v in model_deviation_dict) { if (Math.Abs(item_v.Value) > 5) { error = true; break; } } if (error) { continue; } _model_diff_vm_list.Add(model_diff_vm); } } } this.modelDiffViewModelBindingSource.DataSource = _model_diff_vm_list; this.gridView1.BestFitColumns(); //this.pumpFactorViewModelBindingSource.DataSource = vm_pump_facotr_list; //this.pumpFactorViewModelBindingSource.ResetBindings(false); //this.gridView2.BestFitColumns(); } 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; } bool CheckYValues(float[] xValues, int nPoints) { for (int j = 1; j < nPoints; j++) { if (xValues[j - 1] <= xValues[j]) { return false; } } return true; } private Dictionary GetPumpCurveDict() { var dict = new Dictionary(); var bll_curve = new BLL.PumpCurve(); var station_list = new BLL.Station().GetAll(); foreach (var station in station_list) { var pumps = new BLL.Equipment().GetPumpListByBelongTypeAndBelongID(IStation.ObjectType.Station, station.ID); if (pumps == null || !pumps.Any()) { return default; } foreach (var pump in pumps) { Model.CurveExpress qh = null; var curve_info = bll_curve.GetDefaultWorkingByPumpID(pump.ID)?.CurveInfo; if (curve_info != null) { qh = curve_info.CurveQH; } dict.Add(pump.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(); } private void barBtnExportAnalysisFactor_ItemClick(object sender, DevExpress.XtraBars.ItemClickEventArgs e) { if (_monitorDataSources == null || _station == null) { return; } if (_pump_list == null || !_pump_list.Any()) { return; } if (_model_diff_vm_list == null || !_model_diff_vm_list.Any()) { return; } WaitFrmHelper.ShowWaitForm("正在导出"); //var flag_hz_head_diff_list = _model_diff_vm_list.Where(x => x.Type == "压力" && x.Flag.HasValue).Select(x => //{ // var flag = x.Flag.Value; // var hz0 = x.HzRound.Value; // var head_dev = x.DiffVlaue; // if (head_dev > 0) // { // head_dev = -head_dev; // } // else // { // head_dev = Math.Abs(head_dev); // } // return new Tuple(flag, hz0, head_dev); //}).ToList(); //var bol = AnalysisFactorHelper.SaveAnalysisFactorDtoListAdd(_station.Name, _pump_list, flag_hz_head_diff_list); //if (!bol) //{ // XtraMessageBox.Show("导出失败!"); // return; //} WaitFrmHelper.HideWaitForm(); AlertTool.ShowInfo(System.Windows.Forms.Application.OpenForms[0], "提示", "导出完成!"); } } }