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
}
}