using DevExpress.Utils; using DevExpress.XtraCharts; using HStation.WinFrmUI; using PBS.WinFrmUI.Hydro.Dispatch; using PBS.WinFrmUI.Hydro.Dispatch.Model; using System.Data; using System.Text; using Yw.Pump; using Yw.WinFrmUI.Phart; namespace PBS.WinFrmUI.Hydro { public partial class SimulationSchedulePage : DocumentPage { public SimulationSchedulePage() { InitializeComponent(); InitialChart(); this.chartControl.CrosshairEnabled = DefaultBoolean.True; this.chartControl.RuntimeHitTesting = true; this.chartControl.MouseDown += this.chartControl_MouseDown; this.chartControl.AnimationStartMode = ChartAnimationMode.OnLoad; this.gridView1.SetNormalView(); this.gridView1.OptionsView.ShowIndicator = false; this.PageTitle.Caption = "模拟计算"; } #region Class public class SimuValueViewModel { /// /// 时刻 /// public DateTime Time { get; set; } /// /// 最小流量 /// public double MinQ { get; set; } /// /// 最大流量 /// public double MaxQ { get; set; } /// /// 用水趋势 /// public double UsageQ { get; set; } } /// /// 计算值 /// public class CalcValueViewModel { /// /// 时间 /// public DateTime Time { get; set; } /// /// 目标流量 /// public double TargetFlow { get; set; } /// /// 目标扬程 /// public double TargetHead { get; set; } /// /// 总流量 /// public double TotalFlow { get; set; } /// /// 总功率 /// public double TotalPower { get; set; } /// /// 比较总功率(目标压力为恒压) /// public double CompareTotalPower { get; set; } /// /// 总效率 /// public double TotalEff { get; set; } /// /// 总扬程 /// public double TotalHead { get; set; } /// /// 计算用户压力(计算压力-目标压力+末端压力) /// public double CalcHead { get; set; } /// /// 变压总能耗 /// public double TotalEnergyVP { get; set; } /// /// 恒压总能耗 /// public double TotalEnergyCP { get; set; } ///// ///// 碳排放 ///// //public double CarbonEmission { get; set; } /// /// 节能值 /// public double EnergyEfficient { get; set; } /// /// 节能比 % /// public double EnergyEfficiencyRatio { get; set; } public string ControlType { get; set; } /// /// 泵列表 /// public List Pumps { get; set; } public string RealDataJson { get; set; } /// /// 是否计算成功 /// public bool CalcSuccess { get; set; } public string Status { get => CalcSuccess ? "成功" : "失败"; } } /// /// 泵信息 /// public class PumpViewModel { ///// ///// 标识 ///// //public long ID { get; set; } /// /// /// public long DbID { get; set; } /// /// 名称 /// public string Name { get; set; } /// /// 频率 /// public double HZ { get; set; } /// /// 流量 /// public double Flow { get; set; } /// /// 功率 /// public double Power { get; set; } /// /// 扬程 /// public double Head { get; set; } /// /// 效率 /// public double Eff { get; set; } /// /// 流量扬程线 /// public Yw.Pump.CurveQH CurveQH { get; set; } /// /// 流量功率线 /// public Yw.Pump.CurveQP CurveQP { get; set; } public bool IsCalc { get; set; } } #endregion #region Chart Variable private XYDiagram _xyDiagram = null; private GanttDiagram _ganttDiagram = null; private XYDiagramPane _paneP, _panePE, _paneRun; private AxisX _axisX; private AxisY _axisYP; private SecondaryAxisY _axisYQ, _axisYPower, _axisYE, _axisYRun; private ConstantLine _lineTime, _lineP, _ganttLine; private Series _seriesUsageQ, _seriesRangeAreaQ, _seriesRangeArea, _seriesAvgP, _seriesCalcP, _seriesRealP, _seriesPower, _seriesE; #endregion private List> _pumpCombine = null;//泵调度组合 private Dictionary _simuPumps_dict = null;//调度泵列表 private Vmo.FacilityVmo _facility = null;//设施 private List _calcValues = null;//计算值 private double _maxWaterDemand, _constantPressure;//系统最大流量/恒压值 private List _curveWaterUsageTrend = null; private Yw.Ahart.CubicCurve _curveUpperPressure = null; private Yw.Ahart.CubicCurve _curveLowerPressure = null; private Yw.Ahart.CubicCurve _curveAveragePressure = null; private int _totalTime = 1440;// private int _timeStep = 30;//数据步长 private System.Windows.Forms.Timer _timer = null;//定时器 private DateTime _baseTime = DateTime.Parse("1900-01-01"); private bool _calcIng = false; #region Initial /// /// 初始化数据 /// public async void InitialData(FacilityVmo obj, Yw.Ahart.CubicCurve curveUpperPressure, Yw.Ahart.CubicCurve curveLowerPressure, Yw.Ahart.CubicCurve curveAveragePressure) { _facility = obj; _curveUpperPressure = curveUpperPressure; _curveLowerPressure = curveLowerPressure; _curveAveragePressure = curveAveragePressure; _maxWaterDemand = _facility.MaxWaterDemand.Value; _constantPressure = _facility.ConstantPressure ?? 110; this.txtConstantP.EditValue = _constantPressure; this.txtEndP.EditValue = _facility.TerminalPressure; _lineP.AxisValue = _constantPressure; _simuPumps_dict = new Dictionary(); List<(HStation.Vmo.AssetsPumpMainVmo Pump, Yw.Pump.CurveQH CurveQH, Yw.Pump.CurveQP CurveQP)> list = new(); var assetsPackageMain = await BLLFactory.Instance.GetByID(obj.PackageID); if (assetsPackageMain != null) { var mappingList = await BLLFactory.Instance.GetByKitID(assetsPackageMain.ID); if (mappingList != null && mappingList.Any()) { var pumpMainIds = mappingList.Select(x => x.PumpMainID).ToList(); var pumpMainList = await BLLFactory.Instance.GetByIds(pumpMainIds); if (pumpMainList != null && pumpMainList.Any()) { foreach (var pumpMain in pumpMainList) { var relation = await BLLFactory.Instance.GetDefaultExByObjectTypeAndObjectID(HStation.Assets.DataType.PumpMain, pumpMain.ID); var diagram = await BLLFactory.Instance.GetByID(relation.DiagramID); var pumpCurve = diagram.GetDefaultPumpCurveViewMdoel(); list.Add((pumpMain, pumpCurve.CurveQH, pumpCurve.CurveQP)); } } } } foreach (var item in list) { var pump = item.Pump; var simuPumpVm = new SimuPumpViewModel(); simuPumpVm.ID = pump.ID; simuPumpVm.Name = pump.Name; simuPumpVm.Qr = pump.RatedFlow; simuPumpVm.Hr = pump.RatedHead; simuPumpVm.Nr = pump.RatedSpeed; simuPumpVm.Pr = pump.RatedPower; simuPumpVm.Er = pump.RatedEfficiency??0; //simuPumpVm.Ic = pump.Ic; //simuPumpVm.Oc = pump.Oc; //simuPumpVm.IOd = pump.IOd; //simuPumpVm.Ie = pump.Ie; //simuPumpVm.Oe = pump.Oe; simuPumpVm.IsBp = true; simuPumpVm.IsSxp = false; simuPumpVm.CurveQH = item.CurveQH; simuPumpVm.CurveQP = item.CurveQP; _simuPumps_dict[pump.ID]=simuPumpVm; } if (!_simuPumps_dict.Any()) return; InitialPumpRunSeries(_simuPumps_dict); var pumps = _simuPumps_dict.Values.Select(x => x.Name + x.ID).ToList(); _pumpCombine = new List>() { pumps }; } /// /// 初始化图表 /// private void InitialChart() { this.multiCurveExpressChart1.QPVisble = false; this.multiCurveExpressChart1.QEVisible = false; this.chartControl.CrosshairOptions.ShowOnlyInFocusedPane = false; _xyDiagram = this.chartControl.Diagram as XYDiagram; _paneP = (XYDiagramPane)_xyDiagram.FindPaneByName("PaneP"); _panePE = (XYDiagramPane)_xyDiagram.FindPaneByName("PanePE"); _paneRun = (XYDiagramPane)_xyDiagram.FindPaneByName("PaneRun"); _paneRun.EnableAxisXScrolling = DefaultBoolean.False; _paneRun.EnableAxisYScrolling = DefaultBoolean.False; _paneRun.EnableAxisXZooming = DefaultBoolean.False; _paneRun.EnableAxisYZooming = DefaultBoolean.False; _axisX = _xyDiagram.AxisX; _axisX.DateTimeScaleOptions.MeasureUnit = DateTimeMeasureUnit.Minute; _axisX.DateTimeScaleOptions.ScaleMode = ScaleMode.Manual; _axisYP = _xyDiagram.AxisY; _axisYQ = _xyDiagram.SecondaryAxesY.GetAxisByName("AxisYQ"); _axisYPower = _xyDiagram.SecondaryAxesY.GetAxisByName("AxisYPower"); _axisYE = _xyDiagram.SecondaryAxesY.GetAxisByName("AxisYE"); _axisYRun = _xyDiagram.SecondaryAxesY.GetAxisByName("AxisYRun"); _lineP = (ConstantLine)_xyDiagram.AxisY.ConstantLines.GetElementByName("ConstantLineP"); _lineP.Visible = true; _lineTime = (ConstantLine)_xyDiagram.AxisX.ConstantLines.GetElementByName("ConstantLineTime"); _seriesUsageQ = this.chartControl.GetSeriesByName("SeriesUsageQ"); _seriesUsageQ.CrosshairLabelPattern = "用水趋势:{V:N1}"; _seriesRangeArea = this.chartControl.GetSeriesByName("SeriesRangeArea"); _seriesRangeArea.CrosshairLabelPattern = "恒定压力:{V2:N2}"; _seriesAvgP = this.chartControl.GetSeriesByName("SeriesAvgP"); _seriesAvgP.CrosshairLabelPattern = "计算泵后压力:{V:N2}"; _seriesCalcP = this.chartControl.GetSeriesByName("SeriesCalcP"); _seriesCalcP.CrosshairLabelPattern = "计算用户压力:{V:N2}"; _seriesRealP = this.chartControl.GetSeriesByName("SeriesRealP"); _seriesRealP.CrosshairLabelPattern = "真实用户压力:{V:N2}"; _seriesPower = this.chartControl.GetSeriesByName("SeriesPower"); _seriesPower.CrosshairLabelPattern = "功率:{V:N3}"; _seriesE = this.chartControl.GetSeriesByName("SeriesE"); _seriesE.CrosshairLabelPattern = "效率:{V:N1}"; _seriesE.Visible = false; _seriesRangeAreaQ = this.chartControl.GetSeriesByName("SeriesRangeAreaQ"); _seriesRangeAreaQ.CrosshairLabelPattern = "用水趋势 上限:{V2:N1} 下限:{V1:N1}"; } /// /// 初始化泵运行系列 /// private void InitialPumpRunSeries(Dictionary pumps) { if (pumps == null || pumps.Count < 1) return; this.chartControl.BeginInit(); var axisLabels = new List(); for (int i = 0; i < pumps.Count; i++) { var pump = pumps.ElementAt(i).Value; axisLabels.Add(new CustomAxisLabel(pump.Name, i + 1)); var series = new DevExpress.XtraCharts.Series(); series.ArgumentScaleType = DevExpress.XtraCharts.ScaleType.DateTime; series.LabelsVisibility = DevExpress.Utils.DefaultBoolean.False; series.Name = pump.ID.ToString(); series.ShowInLegend = false; series.CrosshairEnabled = DefaultBoolean.False; series.LegendTextPattern = pump.Name; // var seriesView = new DevExpress.XtraCharts.PointSeriesView(); var seriesView = new DevExpress.XtraCharts.LineSeriesView(); seriesView.Color = Color.RoyalBlue; seriesView.EnableAntialiasing = DefaultBoolean.True; seriesView.Pane = _paneRun; seriesView.AxisY = _axisYRun; //seriesView.PointMarkerOptions.Kind = MarkerKind.Circle; //seriesView.PointMarkerOptions.BorderVisible = false; //seriesView.PointMarkerOptions.BorderColor = Color.Gray; //seriesView.PointMarkerOptions.Size = 26; seriesView.LineStyle.Thickness = 15; var emptyPointOptions = seriesView.EmptyPointOptions; emptyPointOptions.ProcessPoints = ProcessEmptyPointsMode.Interpolate; emptyPointOptions.Color = Color.FromArgb(100, Color.Gray); if (emptyPointOptions is LineEmptyPointOptions lineOptions) { lineOptions = (LineEmptyPointOptions)emptyPointOptions; lineOptions.LineStyle.DashStyle = ((LineSeriesView)seriesView).LineStyle.DashStyle; lineOptions.LineStyle.Thickness = ((LineSeriesView)seriesView).LineStyle.Thickness; } series.SeriesPointsSorting = SortingMode.None; series.SeriesPointsSortingKey = SeriesPointKey.Value_1; series.View = seriesView; series.Visible = true; this.chartControl.Series.Add(series); }  _axisYRun.CustomLabels.Clear(); _axisYRun.CustomLabels.AddRange(axisLabels.ToArray()); _axisYRun.WholeRange.SetMinMaxValues(1, pumps.Count); _axisYRun.Visibility = DefaultBoolean.True; this.chartControl.EndInit(); } #endregion #region SetChart /// /// 设置图表缩放和平移 /// private void SetChartScrollingAndZooming(bool bol) { this.chartControl.BeginInit(); _xyDiagram.EnableAxisXScrolling = bol; _xyDiagram.EnableAxisYScrolling = bol; _xyDiagram.EnableAxisXZooming = bol; _xyDiagram.EnableAxisYZooming = bol; this.chartControl.EndInit(); } #endregion #region SetView /// /// 清空计算数据 /// private void ClearCalcData() { this.txtTotalEnergyCP.EditValue = null; this.txtTotalEnergyVP.EditValue = null; this.txtEnergyEfficient.EditValue = null; this.txtEnergyEfficiencyRatio.EditValue = null; this.multiCurveExpressChart1.Clear(); this.gridControl1.DataSource = null; this.gridControl1.RefreshDataSource(); this.txtTime.EditValue = null; this.txtPower.EditValue = null; this.txtPumpP.EditValue = null; this.txtTerminalP.EditValue = null; _calcValues = new List(); this.chartControl.BeginInit(); _seriesPower.Points.Clear(); _seriesE.Points.Clear(); _seriesCalcP.Points.Clear(); _seriesAvgP.Points.Clear(); _seriesRangeArea.Points.Clear(); if (_simuPumps_dict != null && _simuPumps_dict.Any()) { for (int i = 1; i <= _simuPumps_dict.Count; i++) { var pump = _simuPumps_dict.ElementAt(i - 1).Value; var series = this.chartControl.GetSeriesByName(pump.ID.ToString()); if (series == null) continue; series.Points.Clear(); } } this.chartControl.EndInit(); } /// /// 设置图表信息 /// public void SetCurveChart(double workQ, double workH, double workP, double workE, List currentPumps) { this.multiCurveExpressChart1.Clear(); if (currentPumps == null || !currentPumps.Any()) return; var calc_pump_list = currentPumps.ToList();//.Where(x => !x.IsCalc).ToList(); if (calc_pump_list.Count == 2) { var pump = currentPumps[0]; var pump2 = currentPumps[1]; var vm = new PumpRunViewViewModel(); vm.Id = Guid.NewGuid().ToString(); vm.Name = pump.Name; vm.CurveName = pump.Name; vm.Color = Color.Black; vm.RatedQ = pump.Flow; vm.RatedH = pump.Head; vm.RatedP = pump.Power; //vm.RatedN = pump.RatedN; vm.RatedHz = pump.HZ; vm.CurveQH = pump.CurveQH.FeatCurve.GetPointList(100); vm.CurveQP = pump.CurveQP.FeatCurve.GetPointList(100); vm.Items = new List() { //new PumpRunViewItemViewModel() // { // Id = Guid.NewGuid().ToString(), // Name = pump.Name, // CurveName = pump.Name, // Color = Color.Blue, // Q = pump.Flow, // H = pump.Head, // E = pump.Eff, // P = pump.Power, // Hz = pump.HZ, // CurveQH = pump.CurveQH.FeatCurve.GetPointList(100), // CurveQP = pump.CurveQP.FeatCurve.GetPointList(100) // }, new PumpRunViewItemViewModel() { Id = Guid.NewGuid().ToString(), Name = pump2.Name, CurveName = pump2.Name, Color = Color.Blue, Q = pump2.Flow, H = pump2.Head, E = pump2.Eff, P = pump2.Power, Hz = pump2.HZ, CurveQH = pump2.CurveQH.FeatCurve.GetPointList(100), CurveQP = pump2.CurveQP.FeatCurve.GetPointList(100) } }; this.multiCurveExpressChart1.SetBindingData(vm); return; }   }   /// /// 设置面板信息 /// private void SetPanelInfo(CalcValueViewModel calcValue) { this.gridControl1.DataSource = calcValue.Pumps; this.gridControl1.RefreshDataSource(); this.gridView1.BestFitColumns(); this.txtTime.EditValue = calcValue.Time.ToString("T"); this.txtPower.EditValue = Math.Round(calcValue.TotalPower, 3)+ " kW·h"; this.txtPumpP.EditValue = Math.Round(calcValue.TotalHead, 2)+" m"; this.txtTerminalP.EditValue = Math.Round(calcValue.CalcHead, 2) + " m"; } private void SetEnergyInfo(CalcValueViewModel calcValue) { this.txtTotalEnergyVP.EditValue = calcValue.TotalEnergyVP + " kW·h"; this.txtTotalEnergyCP.EditValue = calcValue.TotalEnergyCP + " kW·h"; this.txtEnergyEfficient.EditValue = calcValue.EnergyEfficient + " kW·h"; this.txtEnergyEfficiencyRatio.EditValue = calcValue.EnergyEfficiencyRatio + " %"; } #endregion #region SetCalcStatus /// /// 设置进行状态 /// private void SetCalcIngStatus() { _calcIng = true; this.barBtnCalc.Enabled = false; this.barBtnPause.Enabled = true; this.barBtnContinue.Enabled = false; this.barBtnOver.Enabled = false; this.txtConstantP.ReadOnly = true; } /// /// 设置暂停状态 /// private void SetCalcPauseStatus() { _calcIng = true; this.barBtnPause.Enabled = false; this.barBtnContinue.Enabled = true; this.barBtnOver.Enabled = true; } /// /// 设置停止状态 /// private void SetCalcOverStatus() { _timer?.Stop(); _timer?.Dispose(); _calcIng = false; this.barBtnCalc.Enabled = true; this.barBtnPause.Enabled = false; this.barBtnContinue.Enabled = false; this.barBtnOver.Enabled = false; this.txtConstantP.ReadOnly = false; } #endregion #region Event //水量导入 private void barBtnWaterImport_ItemClick(object sender, DevExpress.XtraBars.ItemClickEventArgs e) { #region Load var dlg = new OpenFileDialog(); dlg.Filter = "Excel文件(*.xls;*.xlsx;*.csv)|*.xls;*.xlsx;*.csv|所有文件|*.*"; dlg.ValidateNames = true; dlg.CheckPathExists = true; dlg.CheckFileExists = true; if (dlg.ShowDialog() != DialogResult.OK) return; var filePath = dlg.FileName; var extension = Path.GetExtension(filePath); var timeValues_csv = new List(); switch (extension) { case ".csv": { using (var fs = new FileStream(filePath, FileMode.Open, FileAccess.Read)) using (var sr = new StreamReader(fs, Encoding.UTF8)) { sr.ReadLine(); var strLine = string.Empty; while (!string.IsNullOrEmpty(strLine = sr.ReadLine())) { var strList = strLine.Split(','); if (strList.Length < 2) return; if (!DateTime.TryParse(strList[0], out DateTime time)) continue; if (!double.TryParse(strList[1], out double value)) continue; if (value <= 0) continue; var timeValue = new TimeValue(time, value); timeValues_csv.Add(timeValue); } } } break; default: { TipFormHelper.ShowError("暂不支持该格式"); XtraMessageBox.Show("!"); return; } } #endregion ClearCalcData(); if (timeValues_csv.Count < 1) { XtraMessageBox.Show("无数据!"); return; } var days_tvs = timeValues_csv.OrderBy(x => x.Time.Day).GroupBy(x => new { x.Time.Day }); var last_day_tvs = days_tvs.Last().ToList(); #region Build var list = new List(); var maxValues = new Dictionary(); var minValues = new Dictionary(); foreach (var tvs in last_day_tvs) { DateTime time = tvs.Time; double value = tvs.Value; DateTime t = _baseTime.AddHours(time.Hour).AddMinutes(time.Minute); if (value <= 0) continue; if (!maxValues.ContainsKey(t)) maxValues[t] = 0; if (!minValues.ContainsKey(t)) minValues[t] = 999999999; list.Add(new Yw.Geometry.Point2d(t.ToOADate(), value)); if (value < minValues[t]) minValues[t] = value; if (value > maxValues[t]) maxValues[t] = value; } var fitHelper = new CurveFitHelper(list); _curveWaterUsageTrend = fitHelper.GetConfidenceCurve(100)[2]; #endregion var timeValuesUsageQ = _curveWaterUsageTrend.Select(p => new TimeValue(DateTime.FromOADate(p.X), p.Y)).ToList(); var timeRangeQValues = new List(); foreach (var ct in last_day_tvs) { var tvs = timeValues_csv.Where(x => x.Time.Hour == ct.Time.Hour && x.Time.Minute == ct.Time.Minute).ToList(); if (tvs == null || !tvs.Any()) continue; tvs = tvs.OrderBy(x => x.Value).ToList(); var minTimeQ = tvs.First(); var maxTimeQ = tvs.Last(); var trv = new TimeRangeValue(); trv.Time = new DateTime(_baseTime.Year, _baseTime.Month, _baseTime.Day, ct.Time.Hour, ct.Time.Minute, ct.Time.Second); trv.MinValue = minTimeQ.Value; trv.MaxValue = maxTimeQ.Value; timeRangeQValues.Add(trv); } var minTime = timeValuesUsageQ.Min(p => p.Time); var maxTime = timeValuesUsageQ.Max(p => p.Time); this.chartControl.BeginInit(); _seriesUsageQ.BindToData(timeValuesUsageQ, "Time", "Value"); _seriesRangeAreaQ.BindToData(timeRangeQValues, "Time", new string[] { "MinValue", "MaxValue" }); _axisX.WholeRange.SideMarginsValue = 0; _axisX.VisualRange.SideMarginsValue = 0; _axisX.WholeRange.SetMinMaxValues(minTime, maxTime); _axisX.VisualRange.SetMinMaxValues(minTime, maxTime); this.chartControl.EndInit(); } //恒定压力 private void txtConstantP_EditValueChanged(object sender, EventArgs e) { if (!double.TryParse(this.txtConstantP.Text, out double constantP)) return; if (!double.TryParse(this.txtEndP.Text, out double endP) ) return; _constantPressure = constantP; _lineP.AxisValue = constantP; } private int _takeIndex = 0; //计算 private void barBtnCalc_ItemClick(object sender, DevExpress.XtraBars.ItemClickEventArgs e) { if (_seriesUsageQ.Points.Count < 1) { XtraMessageBox.Show("请导入水量!"); return; } double.TryParse(this.txtConstantP.Text, out double constantP); double.TryParse(this.txtEndP.Text, out double endP); _constantPressure = constantP; _lineP.AxisValue = _constantPressure; SetCalcIngStatus(); ClearCalcData(); WaitFormHelper.ShowWaitForm("计算中"); _lineTime.AxisValue = DateTime.MinValue; _calcValues = SimuCalc(_simuPumps_dict, _constantPressure, endP, _totalTime, _timeStep); WaitFormHelper.HideWaitForm(); _calcValues = _calcValues?.Where(x => x.CalcSuccess).ToList(); if (_calcValues == null || !_calcValues.Any()) { SetCalcOverStatus(); TipFormHelper.ShowError("无计算数据!"); return; } var firstCalcValue = _calcValues[0]; for (int i = 1; i < _simuPumps_dict.Count + 1; i++) { var pump = _simuPumps_dict.ElementAt(i-1).Value; var series = this.chartControl.GetSeriesByName(pump.ID.ToString()); if (series == null) continue; var seriesPoint = new SeriesPoint(firstCalcValue.Time, i); series.Points.Add(seriesPoint); } var pt_list = _curveAveragePressure.GetPointList(100); _axisYP.VisualRange.MaxValue = _constantPressure; _axisYP.VisualRange.MinValue = pt_list.Min(x => x.Y) * 0.98; _axisYP.WholeRange.MaxValue = _constantPressure; _axisYP.WholeRange.MinValue = pt_list.Min(x => x.Y) * 0.98; _takeIndex = 0; _timer = new System.Windows.Forms.Timer(); _timer.Interval = 1; _timer.Tick += (sender_calc, e_calc) => { if (_calcValues == null || !_calcValues.Any()) { SetCalcOverStatus(); } if (_takeIndex >= _calcValues.Count) { SetCalcOverStatus(); return; } var calcValue = _calcValues[_takeIndex]; if (calcValue.CalcSuccess) { CalcValueViewModel lastCalcValue = null; if (_takeIndex > 0) { lastCalcValue = _calcValues[_takeIndex - 1]; } var time = calcValue.Time; var power = calcValue.TotalPower; var eff = calcValue.TotalEff; var calcP = calcValue.CalcHead; var avgP = calcValue.TargetHead; this.chartControl.BeginInit(); _seriesRangeArea.Points.Add(new SeriesPoint(time, new double[] { avgP, constantP })); _seriesAvgP.Points.Add(new SeriesPoint(time, avgP)); _seriesCalcP.Points.Add(new SeriesPoint(time, calcP)); _seriesPower.Points.Add(new SeriesPoint(time, power)); _seriesE.Points.Add(new SeriesPoint(time, eff)); for (int i = 1; i < _simuPumps_dict.Count + 1; i++) { var pump = _simuPumps_dict.ElementAt(i-1).Value; var series = this.chartControl.GetSeriesByName(pump.ID.ToString()); if (series == null) continue; var run = calcValue.Pumps.Exists(x => x.DbID == pump.ID&&!x.IsCalc); if (!run && lastCalcValue != null && lastCalcValue.Pumps != null) { run = lastCalcValue.Pumps.Exists(x => x.DbID == pump.ID&& !x.IsCalc); } var seriesPoint = new SeriesPoint(time, i); seriesPoint.IsEmpty = !run; seriesPoint.Color = !run ? Color.Gray : Color.RoyalBlue; series.Points.Add(seriesPoint); } _lineTime.AxisValue = time; _lineTime.Title.Text = time.ToString("T"); this.chartControl.EndInit(); SetPanelInfo(calcValue); SetCurveChart(calcValue.TotalFlow, calcValue.TargetHead, calcValue.TotalPower, calcValue.TotalEff, calcValue.Pumps); SetEnergyInfo(calcValue); } else { } _takeIndex++; }; _timer.Start(); } //暂停计算 private void barBtnPause_ItemClick(object sender, DevExpress.XtraBars.ItemClickEventArgs e) { _timer?.Stop(); SetCalcPauseStatus(); } //继续计算 private void barBtnContinue_ItemClick(object sender, DevExpress.XtraBars.ItemClickEventArgs e) { _timer?.Start(); SetCalcIngStatus(); } //结束计算 private void barBtnOver_ItemClick(object sender, DevExpress.XtraBars.ItemClickEventArgs e) { SetCalcOverStatus(); } //图表 鼠标点击事件 private void chartControl_MouseDown(object sender, MouseEventArgs e) { if (_calcIng) return; if (_calcValues == null || !_calcValues.Any()) return; if (e.Button != MouseButtons.Left) return; var hitInfo = this.chartControl.CalcHitInfo(e.Location); if (hitInfo.InChart) { var diagramCoordinates = _xyDiagram.PointToDiagram(e.Location); var axisValue = diagramCoordinates.GetAxisValue(_axisX); if (axisValue == null) return; var dt = axisValue.DateTimeValue; if (dt > (DateTime)_lineTime.AxisValue) return; var cv = _calcValues?.Find(x => x.Time == dt); if (cv == null) { var bol = InterValueBuild( dt, out double targetFlow, out double targetHead); if (!bol) return; var pumps = _simuPumps_dict.Values.ToList(); cv = SimuCalc(dt, pumps, targetFlow, targetHead, _constantPressure); if (cv == null) return; } SetCurveChart(cv.TotalFlow, cv.TargetHead, cv.TotalPower, cv.TotalEff, cv.Pumps); SetPanelInfo(cv); } } #endregion #region Simu /// /// 线性插值 /// private bool InterValueBuild(DateTime dt, out double usageQ, out double avgP) { usageQ = avgP = 0; if (_curveWaterUsageTrend != null && _curveWaterUsageTrend.Any()) { var timeOA = DateTime.Parse("1900-1-1").Add(dt.TimeOfDay).ToOADate(); for (int i = 0; i < _curveWaterUsageTrend.Count - 1; i++) { if (_curveWaterUsageTrend[i].X <= timeOA && timeOA <= _curveWaterUsageTrend[i + 1].X)//找到 { usageQ = (float)(_curveWaterUsageTrend[i].Y + (_curveWaterUsageTrend[i + 1].Y - _curveWaterUsageTrend[i].Y) * (timeOA - _curveWaterUsageTrend[i].X) / (_curveWaterUsageTrend[i + 1].X - _curveWaterUsageTrend[i].X)); break; } } } if (usageQ <= 0) { return false; } avgP = _curveAveragePressure.GetPointY(usageQ); return true; } /// /// 调度(所有时间) /// private List SimuCalc (Dictionary simuPumps, double constantP, double endP, int totalTime, int timeStep) { if (simuPumps == null || !simuPumps.Any()) return default; var startTime = _baseTime; var timeScale = totalTime / timeStep; var calcValues = new List(); var complexRequestPras = new Dispatch.Model.RequestParasComplex() { StationID = 1, PressValueType = RequestParasComplex.ePressValueType.扬程, SchemeSortType = eAnaSchemeSortType.功率, InletPipePara = new List() { new Dispatch.Model.InletPipePara(0) } }; var calcHelper = new Calculator_OptAna_General(); var combinIndex = 0; double cp_total_power_kw_sum = 0; double vp_total_power_kw_sum = 0; double total_power_diff = 0; for (int i = 0; i < timeScale; i++) { var intervalMinute = i * timeStep; var currentTime = startTime.AddMinutes(intervalMinute); if (!InterValueBuild( currentTime, out double targetFlow, out double targetHead)) continue; complexRequestPras.OutletPipePara = new List(); complexRequestPras.OutletPipePara.Add(new OutletPipePara() { TargetFlow = targetFlow, TargetPress = targetHead }); var combin = _pumpCombine[combinIndex]; var combinRunStatus = new Dispatch.Model.MachineRunPara(); combinRunStatus.MachineRunFilter = new List(); for (int j = 0; j < simuPumps.Count; j++) { var pump = simuPumps.ElementAt(j).Value; var machineRunFilter = new Dispatch.Model.MachineRunFilter() { MachineID = pump.ID, RunStatus = 1, Percentage = 1, IsFrequency = true }; combinRunStatus.MachineRunFilter.Add(machineRunFilter); } var calcValue = new CalcValueViewModel(); calcValue.Time = currentTime; calcValue.TargetFlow = targetFlow; calcValue.TargetHead = targetHead; calcValues.Add(calcValue); var schemes = calcHelper.CalcSchemes(simuPumps.Values.ToList(), complexRequestPras, combinRunStatus, out string errorInfo); if (schemes == null || !schemes.Any()) { calcValue.CalcSuccess = false; continue; } var scheme = schemes[0]; calcValue.CalcSuccess = true; calcValue.TotalPower = scheme.TotalWrkP; calcValue.TotalEff = scheme.TotalWrkE; calcValue.TotalHead = scheme.TotalWrkH; calcValue.TotalFlow = scheme.TotalWrkQ; calcValue.CalcHead = scheme.TotalWrkH - targetHead + endP; var cp_total_power = 0d; if (scheme.Items != null && scheme.Items.Any()) { calcValue.Pumps = new List(); foreach (var item in scheme.Items) { calcValue.Pumps = GetPumpViewModelList(targetFlow, item, out double clac_power); cp_total_power += clac_power; } } // var vp_total_power_kw = calcValue.TotalPower * timeStep / 60; var cp_total_power_kw = cp_total_power * timeStep / 60; total_power_diff += cp_total_power_kw - vp_total_power_kw;//节能值 vp_total_power_kw_sum += vp_total_power_kw;//调度功率 cp_total_power_kw_sum += cp_total_power_kw;//调度功率 calcValue.TotalEnergyVP = Math.Round(vp_total_power_kw_sum, 2);//总能耗 calcValue.TotalEnergyCP = Math.Round(cp_total_power_kw_sum, 2);//总能耗 calcValue.EnergyEfficient = Math.Round(total_power_diff, 2);//节能值 calcValue.EnergyEfficiencyRatio = Math.Round(total_power_diff / cp_total_power_kw_sum * 100, 2);//节能比例 } return calcValues; } /// /// 调度(单时刻) /// private CalcValueViewModel SimuCalc(DateTime dateTime, List simuPumps, double targetFlow, double targetHead, double constantP) { if (simuPumps == null || !simuPumps.Any()) return default; var calcHelper = new Calculator_OptAna_General(); var combinIndex = 0; var complexRequestPras = new Dispatch.Model.RequestParasComplex() { StationID = 1, PressValueType = RequestParasComplex.ePressValueType.扬程, SchemeSortType = eAnaSchemeSortType.功率, InletPipePara = new List() { new Dispatch.Model.InletPipePara(0) } }; var simuTime = dateTime; complexRequestPras.OutletPipePara = new List(); complexRequestPras.OutletPipePara.Add(new OutletPipePara() { TargetFlow = targetFlow, TargetPress = targetHead }); var combin = _pumpCombine[combinIndex]; var combinRunStatus = new Dispatch.Model.MachineRunPara(); combinRunStatus.MachineRunFilter = new List(); for (int j = 0; j < simuPumps.Count; j++) { var pump = simuPumps[j]; //var runStatus = combin.Exists(x => x == pump.Name) ? 1 : 0; var machineRunFilter = new Dispatch.Model.MachineRunFilter() { MachineID = pump.ID, RunStatus = 1, Percentage = 1, IsFrequency = true }; combinRunStatus.MachineRunFilter.Add(machineRunFilter); combinRunStatus.RunPumpCount = 2; } double.TryParse(this.txtEndP.Text, out double endP); //计算 var schemes = calcHelper.CalcSchemes(simuPumps, complexRequestPras, combinRunStatus, out string errorInfo); if (schemes == null || !schemes.Any()) { return default; } var scheme = schemes[0]; var calcValue = new CalcValueViewModel(); calcValue.Time = simuTime; calcValue.TargetFlow = targetFlow; calcValue.TargetHead = targetHead; calcValue.TotalPower = scheme.TotalWrkP; calcValue.TotalEff = scheme.TotalWrkE; calcValue.TotalHead = scheme.TotalWrkH; calcValue.TotalFlow = scheme.TotalWrkQ; calcValue.CalcHead = scheme.TotalWrkH - targetHead + endP; calcValue.CalcSuccess = true; if (scheme.Items != null && scheme.Items.Any()) { calcValue.Pumps = new List(); foreach (var item in scheme.Items) { calcValue.Pumps = GetPumpViewModelList(targetFlow, item, out double clac_power); } } complexRequestPras.OutletPipePara[0].TargetPress = constantP; var compareSchemes = calcHelper.CalcSchemes(simuPumps, complexRequestPras, combinRunStatus, out errorInfo); if (compareSchemes != null && compareSchemes.Any()) { var compareScheme = compareSchemes[0]; calcValue.CompareTotalPower = compareScheme.TotalWrkP; } return calcValue; } private List GetPumpViewModelList(double targetFlow, AnaSchemeItem item, out double clac_power) { clac_power = 0; var calc_pump = new PumpViewModel(); calc_pump.DbID = item.PumpID; calc_pump.Name = item.MachineName + "-变压"; calc_pump.HZ = item.Frequence; calc_pump.Power = item.WorkPointP; calc_pump.Eff = item.WorkPointE; calc_pump.Head = item.WorkPointH; calc_pump.Flow = item.WorkPointQ; calc_pump.CurveQH = new Yw.Pump. CurveQH(Yw.Ahart.eFeatType.Cubic,item.CurveInfoQH); calc_pump.CurveQP = new Yw.Pump.CurveQP(Yw.Ahart.eFeatType.Cubic, item.CurveInfoQP) ; var pump = _simuPumps_dict[item.PumpID]; var pt = new Yw.Geometry.Point2d(targetFlow, _constantPressure); var sect_pt = Yw.Pump.PerformParabolaHelper.GetQHSectPoint(pump.CurveQH, pt); if (sect_pt == null || sect_pt.IsZeroPoint()) return default; var wrk_speed = sect_pt.Y.CalculateSimuByH(pump.Nr, pt.Y); var wrk_fre = Math.Round(wrk_speed / pump.Nr * 50, 1); var wrk_curve_qh = new Yw.Pump.CurveQH(Yw.Ahart.eFeatType.Cubic, pump.CurveQH.GetPointListByN(pump.Nr, wrk_speed)); var wrk_curve_qp = new Yw.Pump.CurveQP(Yw.Ahart.eFeatType.Cubic, pump.CurveQP.GetPointListByN(pump.Nr, wrk_speed)); var wrk_power = wrk_curve_qp.FeatCurve.GetPointY(targetFlow); var wrk_eff = Yw.Pump.CalculationHelper.CalcuE(targetFlow, _constantPressure, wrk_power); var calc_pump2 = new PumpViewModel(); calc_pump2.DbID = item.PumpID; calc_pump2.Name = item.MachineName + "-恒压"; calc_pump2.HZ = wrk_fre; calc_pump2.Power = Math.Round(wrk_power, 3); calc_pump2.Eff = Math.Round(wrk_eff, 1); calc_pump2.Head = _constantPressure; calc_pump2.Flow = Math.Round(targetFlow, 2); calc_pump2.CurveQH = wrk_curve_qh; calc_pump2.CurveQP = wrk_curve_qp; calc_pump2.IsCalc = true; clac_power = wrk_power; return new List() { calc_pump2, calc_pump }; } #endregion #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 }; /// /// 生成随机深色 /// Color GetRandomColor() { var r_first = new Random((int)DateTime.Now.Ticks); System.Threading.Thread.Sleep(r_first.Next(50)); var r_sencond = new Random((int)DateTime.Now.Ticks); int red = r_first.Next(256); int green = r_sencond.Next(256); int blue = (red + green > 400) ? 0 : 400 - red - green; blue = (blue > 255) ? 255 : blue; return Color.FromArgb(red, green, blue); } #endregion #region Dispose /// /// 释放资源 /// /// protected void Dispose(bool disposing) { if (disposing) { if (this.components != null) this.components.Dispose(); if (_timer != null) { _timer.Stop(); _timer.Dispose(); } } base.Dispose(disposing); } #endregion } }