using DevExpress.Data.Linq.Helpers;
using DevExpress.Utils;
using DevExpress.XtraCharts;
using HStation.WinFrmUI;
using System.Data;
using System.Text;
using Yw.Pump;
using Yw.WinFrmUI.Phart;
using static PBS.WinFrmUI.Hydro.ScheduleHelper;
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;
}
#region Class
public class TimeValue
{
public TimeValue() { }
public TimeValue(DateTime time, double value)
{
this.Time = time;
this.Value = value;
}
public DateTime Time { get; set; }
public double Value { get; set; }
}
public class TimeRangeValue
{
public TimeRangeValue() { }
public TimeRangeValue(DateTime time, double min, double max)
{
this.Time = time;
this.MinValue = min;
this.MaxValue = max;
}
public DateTime Time { get; set; }
public double MinValue { get; set; }
public double MaxValue { get; set; }
}
public class SimuPumpViewModel
{
public long ID { get; set; }
public string Name { get; set; }
public string Code { get; set; }
public double Qr { get; set; }
public double Hr { get; set; }
public double Nr { get; set; }
public double Pr { get; set; }
public double Er { get; set; }
public double? Ic { get; set; }
public double? Oc { get; set; }
public double? IOd { get; set; }
public double? Ie { get; set; }
public double? Oe { get; set; }
public bool IsBp { get; set; }
public bool IsSxp { get; set; }
public Yw.Pump.CurveQH CurveQH { get; set; }
public Yw.Pump.CurveQP CurveQP { get; set; }
}
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 EnergyEfficient { get; set; }
///
/// 节能比 %
///
public double EnergyEfficiencyRatio { get; set; }
///
/// 泵列表
///
public List Pumps { get; set; }
///
/// 是否计算成功
///
public bool CalcSuccess { get; set; }
}
///
/// 泵信息
///
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 CurveInfoQH { get; set; }
///
/// 流量功率线
///
public Yw.Pump.CurveQP CurveInfoQP { 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 FacilityVmo _facility = null;
private List _pumpMainList = null;
private Dictionary _pumpCurveList = null;
private Yw.Ahart.CubicCurve _curveWaterUsageTrend = null;
private Yw.Ahart.CubicCurve _curveUpperPressure = null;
private Yw.Ahart.CubicCurve _curveLowerPressure = null;
private Yw.Ahart.CubicCurve _curveAveragePressure = null;
private List _calcValues = null;//计算值
private double _maxWaterDemand, _constantPressure;//系统最大流量/恒压值
private int _totalTime = 1440;//
private int _timeStep = 5;//数据步长
private System.Windows.Forms.Timer _timer = null;//定时器
private DateTime _baseTime = DateTime.Parse("1900-01-01");
private bool _calcIng = false;
#region Initial
///
/// 初始化数据源
///
public override void InitialDataSource()
{
base.InitialDataSource();
}
///
/// 初始化数据
///
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;
List<(HStation.Vmo.AssetsPumpMainVmo Pump, Yw.Pump.CurveQH CurveQH, Yw.Pump.CurveQP CurveQP)> list = new();
var assetsPackageMain = await BLLFactory.Instance.GetByID(_facility.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));
}
}
}
list = list.Take(1).ToList();
}
_pumpMainList = list?.Select(x => x.Pump).ToList();
_pumpCurveList = list.ToDictionary(x => x.Pump.ID, y => ((y.CurveQH, y.CurveQP)));
InitialPumpRunSeries(_pumpMainList);
}
///
/// 初始化图表
///
private void InitialChart()
{
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(List 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[i];
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.DeleteCurve();
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 (_pumpMainList != null && _pumpMainList.Any())
{
for (int i = 1; i <= _pumpMainList.Count; i++)
{
var pump = _pumpMainList.ElementAt(i - 1);
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.DeleteCurve();
if (currentPumps == null || !currentPumps.Any())
return;
var calc_pump_list = currentPumps.Where(x => !x.IsCalc).ToList();
if (calc_pump_list.Count == 1)
{
foreach (var item in currentPumps)
{
var currentPump = item;
ISupply.Curve.CurveExpress QH = currentPump.CurveInfoQH, QP = currentPump.CurveInfoQP;
var QE = Curve. Yw.Pump.CalculationHelper.CalculateE(QH, QP);
this.multiCurveExpressChart1.AddCurve(item.ID, currentPump.Name,
currentPump.Flow, currentPump.Head, currentPump.Power, currentPump.Eff, currentPump.HZ,
QH, QE, QP, System.Drawing.Color.Black);
}
this.multiCurveExpressChart1.CalcWorkPointByQ(workQ);
return;
}
var theConnectCurve = new Curve.ParallelConnectionHelper();
for (int i = 0; i < calc_pump_list.Count; i++)
{
var currentPump = calc_pump_list[i];
var QH = currentPump.CurveInfoQH;
var QP = currentPump.CurveInfoQP;
var QE = Curve. Yw.Pump.CalculationHelper.CalculateE(QH, QP);
theConnectCurve.AddCurve(QH, QP);
this.multiCurveExpressChart1.AddCurve(currentPump.ID,
currentPump.Name,
currentPump.Flow, currentPump.Head, currentPump.Power, currentPump.Eff,
currentPump.HZ,
QH,
QE,
QP,
ColorArray[i]);
}
var bol = theConnectCurve.CalculateParallel(out List ConnectCurveQH,
out List ConnectCurveQE,
out List ConnectCurveQP);
if (!bol)
{
return;
}
var curveExpressQH = ISupply.Curve.FitHelper.BuildCurveExpress(ConnectCurveQH);
var curveExpressQE = ISupply.Curve.FitHelper.BuildCurveExpress(ConnectCurveQE);
var curveExpressQP = ISupply.Curve.FitHelper.BuildCurveExpress(ConnectCurveQP);
this.multiCurveExpressChart1.AddCurve(-1, "并联曲线",
workQ, workH, workP, workE,
null,
curveExpressQH, curveExpressQE, curveExpressQP, System.Drawing.Color.Black);
// this.multiCurveExpressChart1.LineVisible = true;
this.multiCurveExpressChart1.CalcWorkPointByQ(workQ);*/
}
///
/// 设置面板信息
///
private void SetPanelInfo(CalcValueViewModel calcValue)
{
this.gridControl1.DataSource = calcValue.Pumps;
this.gridControl1.RefreshDataSource();
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:
{
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;
}
_curveWaterUsageTrend = new Yw.Ahart.CubicCurve(list);
#endregion
var timeValuesUsageQ = _curveWaterUsageTrend.GetPointList(100).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;
//this.multiCurveExpressChart1.InitialChartFixed(true, endP, constantP);
}
private int _takeIndex = 0;
//计算
private async 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();
_lineTime.AxisValue = DateTime.MinValue;
_calcValues = await SimuCalc( _constantPressure, endP, _totalTime, _timeStep);
_calcValues = _calcValues?.Where(x => x.CalcSuccess).ToList();
if (_calcValues == null || !_calcValues.Any())
{
SetCalcOverStatus();
XtraMessageBox.Show("无计算数据!");
return;
}
var firstCalcValue = _calcValues[0];
for (int i = 1; i < _pumpMainList.Count + 1; i++)
{
var pump = _pumpMainList.ElementAt(i - 1);
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 < _pumpMainList.Count + 1; i++)
{
var pump = _pumpMainList.ElementAt(i - 1);
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;
var timeOA = DateTime.Parse("1900-1-1").Add(dt.TimeOfDay).ToOADate();
usageQ = _curveWaterUsageTrend.GetPointY(timeOA);
if (usageQ <= 0)
{
return false;
}
//maxP = build.流量压降上限.Evaluate(usageQ);
//minP = build.流量压降下限.Evaluate(usageQ);
avgP = _curveAveragePressure.GetPointY(usageQ);
return true;
}
///
/// 调度(所有时间)
///
private async Task> SimuCalc
(
double constantP,
double endP,
int totalTime,
int timeStep)
{
if (_pumpMainList == null || !_pumpMainList.Any())
return default;
var startTime = _baseTime;
var timeScale = totalTime / timeStep;
var calcValues = new List();
var combinIndex = 0;
double cp_total_power_kw_sum = 0;
double vp_total_power_kw_sum = 0;
double total_power_diff = 0;
var helper = new ScheduleHelper();
helper.Initial(1,1);
for (int i = 0; i < timeScale; i++)
{
var intervalMinute = i * timeStep;
var currentTime = startTime.AddMinutes(intervalMinute);
if (!InterValueBuild(currentTime, out double targetFlow, out double targetPressure))
continue;
var calcValue = new CalcValueViewModel();
calcValue.Time = currentTime;
calcValue.TargetFlow = targetFlow;
calcValue.TargetHead = targetPressure;
calcValues.Add(calcValue);
var optCombine = await helper.GetOptAnaCombine(_facility.PackageID,_pumpMainList,targetFlow, targetPressure);
if (optCombine == null )
{
calcValue.CalcSuccess = false;
continue;
}
var scheme = optCombine;
calcValue.CalcSuccess = true;
calcValue.TotalPower = scheme.TotalPower;
calcValue.TotalEff = scheme.TotalEfficiency;
calcValue.TotalHead = scheme.TotalPressure;
calcValue.TotalFlow = scheme.TotalFlow;
calcValue.CalcHead = scheme.TotalPressure - targetPressure + endP;
var cp_total_power = 0d;
if (scheme.AnaFrePumps != null && scheme.AnaFrePumps.Any())
{
calcValue.Pumps = new List();
foreach (var item in scheme.AnaFrePumps)
{
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)
{
return default;
/* 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, null, 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, null, combinRunStatus, out errorInfo);
if (compareSchemes != null && compareSchemes.Any())
{
var compareScheme = compareSchemes[0];
calcValue.CompareTotalPower = compareScheme.TotalWrkP;
}
return calcValue;*/
}
private List GetPumpViewModelList(double targetFlow, AnaFrePump item, out double clac_power)
{
var pump = _pumpMainList.Find(x => x.ID == item.Flag);
var curve = _pumpCurveList[pump.ID];
clac_power = 0;
var calc_pump = new PumpViewModel();
calc_pump.DbID = item.Flag;
calc_pump.Name = pump.Name + "-变压";
calc_pump.HZ = item.Frequency;
calc_pump.Power = item.Power;
calc_pump.Eff = item.Eff;
calc_pump.Head = item.Head;
calc_pump.Flow = item.Flow;
//calc_pump.CurveInfoQH = item.GetDescription;
//calc_pump.CurveInfoQP = item.CurveInfoQP;
var pt = new Yw.Geometry.Point2d(targetFlow, _constantPressure);
var sect_pt = Yw.Pump.PerformParabolaHelper.GetQHSectPoint(curve.Item1, pt);
if (sect_pt == null || sect_pt.IsZeroPoint())
return null;
var wrk_speed = sect_pt.Y.CalculateSimuByH(pump.RatedSpeed, pt.Y);
var wrk_fre = Math.Round(wrk_speed / pump.RatedSpeed * 50, 1);
var wrk_curve_qh = new CurveQH(Yw.Ahart.eFeatType.Cubic, curve.Item1.GetPointListByN(pump.RatedSpeed, wrk_speed));
var wrk_curve_qp = new CurveQP(Yw.Ahart.eFeatType.Cubic, curve.Item2.GetPointListByN(pump.RatedSpeed, 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.Flag;
calc_pump2.Name = pump.Name + "-恒压";
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.CurveInfoQH = wrk_curve_qh;
calc_pump2.CurveInfoQP = 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
}
}