From 0f5eaa62a6ce8c24c056e2d690bc2e6a9958637e Mon Sep 17 00:00:00 2001 From: ningshuxia <ningshuxia0927@outlook.com> Date: 星期四, 27 三月 2025 11:51:17 +0800 Subject: [PATCH] 供水分析 --- WinFrmUI/PBS.WinFrmUI.Hydro/05-system-curve/00-core/SystemCurvePage.cs | 394 +++++++++---------------------------------------------- 1 files changed, 68 insertions(+), 326 deletions(-) diff --git a/WinFrmUI/PBS.WinFrmUI.Hydro/05-system-curve/00-core/SystemCurvePage.cs b/WinFrmUI/PBS.WinFrmUI.Hydro/05-system-curve/00-core/SystemCurvePage.cs index cf4b184..a00c6e4 100644 --- a/WinFrmUI/PBS.WinFrmUI.Hydro/05-system-curve/00-core/SystemCurvePage.cs +++ b/WinFrmUI/PBS.WinFrmUI.Hydro/05-system-curve/00-core/SystemCurvePage.cs @@ -1,150 +1,26 @@ -锘縰sing DevExpress.Mvvm.Native; -using DevExpress.XtraCharts; - -namespace PBS.WinFrmUI.Hydro +锘縩amespace PBS.WinFrmUI.Hydro { public partial class SystemCurvePage : DocumentPage { public SystemCurvePage() { InitializeComponent(); - this.facilityTreeListCtrl1.SelectFacilityEvent += FacilityTreeListCtrl1_SelectFacilityEvent; + this.facilityTreeListCtrl1.SelectFacilityEvent += FacilityTreeListCtrl1_SelectFacilityEvent; this.facilityTreeListCtrl1.RefreshDataEvent += () => { RefreshData(); }; - } - - - - private class ChartPressurePointViewModel - { - public ChartPressurePointViewModel() - { - } - public ChartPressurePointViewModel(double totalFlow, double upperPressure, double lowerPressure, double averagePressure) - { - this.TotalFlow = totalFlow; - this.UpperPressure = upperPressure; - this.LowerPressure = lowerPressure; - this.AveragePressure = averagePressure; - } - - public double TotalFlow { get; set; } - public double UpperPressure { get; set; } - public double LowerPressure { get; set; } - public double AveragePressure { get; set; } - } - - private class PointViewModel - { - public PointViewModel() - { - - } - public PointViewModel(double x, double y) - { - this.X = x; - this.Y = y; - } - - public double X { get; set; } - public double Y { get; set; } - } - - public class CalcResultViewModel - { - public double TotalFlow { get; set; } - public double EndPressure { get; set; } - public List<CalcNodeViewModel> CalcNodeList { get; set; } - - } - - public class CalcNodeViewModel - { - public int NodeIndex { get; set; } - public double Elevation { get; set; } - public double Flow { get; set; } - public double Pressure { get; set; } - } - - - private XYDiagram _xyDiagram; - private XYDiagramDefaultPane _xyDiagramPane; - - private Series _seriesWaterPoint; - private Series _seriesUpperPressure; - private Series _seriesLowerPressure; - private Series _seriesAveragePressure; - - private ConstantLine _constantLineDynamicPressure; - private ConstantLine _constantLineStaticPressure; - - - private Yw.Ahart.CubicCurve _curveUpperPressure = null; - private Yw.Ahart.CubicCurve _curveLowerPressure = null; - private Yw.Ahart.CubicCurve _curveAveragePressure = null; - private List<PointViewModel> _waterPointList = null; - - - private FacilityVmo _facility = null; - - - public override async void InitialDataSource() - { - var overlay = this.ShowOverlay(); - - this.chartControl1.Legend.Direction = LegendDirection.LeftToRight; - //this.chartControl1.AnimationStartMode = ChartAnimationMode.OnDataChanged; - this.chartControl1.RuntimeHitTesting = true; - //this.chartControl1.CrosshairEnabled = DevExpress.Utils.DefaultBoolean.False; - - _xyDiagram = this.chartControl1.Diagram as XYDiagram; - _xyDiagramPane = _xyDiagram.DefaultPane; - - _seriesWaterPoint = this.chartControl1.GetSeriesByName("SeriesWaterPoint"); - _seriesUpperPressure = this.chartControl1.GetSeriesByName("SeriesUpperPressure"); - _seriesLowerPressure = this.chartControl1.GetSeriesByName("SeriesLowerPressure"); - _seriesAveragePressure = this.chartControl1.GetSeriesByName("SeriesAveragePressure"); - - _constantLineDynamicPressure = _xyDiagram.AxisY.ConstantLines.GetElementByName("ConstantLineDynamicPressure") as ConstantLine; - _constantLineStaticPressure = _xyDiagram.AxisY.ConstantLines.GetElementByName("ConstantLineStaticPressure") as ConstantLine; - - _seriesWaterPoint.LegendTextPattern = "鐢ㄦ按鐐�"; - _seriesUpperPressure.LegendTextPattern = "鍘嬪姏-涓婇檺"; - _seriesLowerPressure.LegendTextPattern = "鍘嬪姏-涓嬮檺"; - _seriesAveragePressure.LegendTextPattern = "鍘嬪姏-骞冲潎"; - - _seriesWaterPoint.CrosshairEnabled = DevExpress.Utils.DefaultBoolean.False; - _seriesUpperPressure.CrosshairEnabled = DevExpress.Utils.DefaultBoolean.True; - _seriesLowerPressure.CrosshairEnabled = DevExpress.Utils.DefaultBoolean.True; - _seriesAveragePressure.CrosshairEnabled = DevExpress.Utils.DefaultBoolean.True; - - this.chartControl1.CrosshairOptions.ShowOnlyInFocusedPane = false; - this.chartControl1.CrosshairOptions.GroupHeaderPattern = "{A:N2}"; - this.chartControl1.CrosshairOptions.GroupHeaderTextOptions.EnableAntialiasing = DevExpress.Utils.DefaultBoolean.True; - _seriesUpperPressure.CrosshairLabelPattern = "{V:N2}"; - _seriesLowerPressure.CrosshairLabelPattern = "{V:N2}"; - _seriesAveragePressure.CrosshairLabelPattern = "{V:N2}"; - - _constantLineDynamicPressure.ShowInLegend = false; - _constantLineStaticPressure.ShowInLegend = false; - - _constantLineDynamicPressure.Title.Alignment = ConstantLineTitleAlignment.Far; - _constantLineStaticPressure.Title.Alignment = ConstantLineTitleAlignment.Far; - - _constantLineDynamicPressure.LineStyle.Thickness = 2; - _constantLineStaticPressure.LineStyle.Thickness = 2; - - _xyDiagram.EnableAxisXZooming = true; - _xyDiagram.EnableAxisYZooming = true; - _xyDiagram.EnableAxisXScrolling = true; - _xyDiagram.EnableAxisYScrolling = true; + } + private FacilityVmo _facility = null; + + /// <summary> + /// 鍒濆鍖栨暟鎹簮 + /// </summary> + public override async void InitialDataSource() + { base.InitialDataSource(); var allFacilityList = await BLLFactory<BLL.Facility>.Instance.GetAll(); - this.facilityTreeListCtrl1.SetBindingData(allFacilityList); - - overlay.Close(); + this.facilityTreeListCtrl1.SetBindingData(allFacilityList); } @@ -153,21 +29,15 @@ { InitialData(obj); } - - - + /// <summary> /// 鍒濆鍖栨暟鎹� /// </summary> public void InitialData(FacilityVmo obj) { - if (obj == null) - { - _facility = null; - return; - } - _facility = obj; + this.facilityPropertyCtrl1.SetBindingData(obj); + this.systemCurveChartCtrl1.Clear(); } @@ -179,52 +49,58 @@ TipFormHelper.ShowWarn("璇烽�夋嫨璁炬柦!"); return; } - - //鍢夊畾 - ////var file_path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "1843913603388936192.inp"); - //var minDemand = 0; // 鏈�灏忔�婚渶姘撮噺(m鲁/h) - //var maxDemand = 43; // 鏈�澶ф�婚渶姘撮噺(m鲁/h) - //var reservoirElevation = -4; //姘存睜鏍囬珮 - //var calcCount = 1000; // 璁$畻娆℃暟 - //var staticPressure = 22.5; //闈欏帇 - //var requiredEndPressure = 18; //闈欏帇 - + var file_path = _facility.ModelPath; var minDemand = 0; // 鏈�灏忔�婚渶姘撮噺(m鲁/h) - var maxDemand = _facility.MaxWaterDemand??45; // 鏈�澶ф�婚渶姘撮噺(m鲁/h) - var reservoirElevation = -4; //姘存睜鏍囬珮 - var calcCount = 10; // 璁$畻娆℃暟 - var staticPressure = 22.5; //闈欏帇 - var requiredEndPressure = _facility.TerminalPressure??15; //闈欏帇 - - CalcSystemCurve(file_path, minDemand, maxDemand, reservoirElevation, staticPressure, requiredEndPressure, calcCount); + var maxDemand = _facility.MaxWaterDemand??45; // 鏈�澶ф�婚渶姘撮噺(m鲁/h) + var calcCount = 20000; // 璁$畻娆℃暟 + var maxHeight = 22.5; //椤舵ゼ鏍囬珮 + var requiredEndPressure = _facility.TerminalPressure ?? 15; //闈欏帇 + CalcSystemCurve(file_path, minDemand, maxDemand, maxHeight, requiredEndPressure, calcCount); + } + /// <summary> + /// 璁$畻绯荤粺鏇茬嚎 + /// </summary> + /// <param name="inpFilePath"></param> + /// <param name="minDemand"></param> + /// <param name="maxDemand"></param> + /// <param name="reservoirElevation"></param> + /// <param name="maxHeight"></param> + /// <param name="requiredEndPressure"></param> + /// <param name="calcCount"></param> private void CalcSystemCurve( string inpFilePath, double minDemand, double maxDemand, - double reservoirElevation, - double staticPressure, + //double reservoirElevation, + double maxHeight, double requiredEndPressure, int calcCount) { var pressure = 0d; var nodeConfig = new List<WaterDistributionCalculator.NodeConfig>(); - var calcResultList = new List<CalcResultViewModel>(calcCount); + var waterPointCalcList = new List<WaterPointCalcViewModel>(calcCount); using (var helper = new Yw.Epanet.InteropXHelper()) { var code = helper.Open(inpFilePath, "", ""); + CheckCode(code); code = helper.GetCount(Yw.Epanet.eCountType.Node, out int totalNodeCount); - + CheckCode(code); var rand = new Random(); for (int nodeIndex = 1; nodeIndex <= totalNodeCount; nodeIndex++) { helper.GetNodeType(nodeIndex, out Yw.Epanet.eNodeType nodeType); if (nodeType == Yw.Epanet.eNodeType.Junction) { + code = helper.GetNodeId(nodeIndex, out string id); + if (!id.Contains("M")) + { + continue; + } helper.GetNodeValue(nodeIndex, Yw.Epanet.eNodeProperty.Elevation, out double elevation); nodeConfig.Add(new WaterDistributionCalculator.NodeConfig() { @@ -233,12 +109,7 @@ MinFlow = 0, MaxFlow = rand.NextDouble() * 5 }); - } - else if (nodeType == Yw.Epanet.eNodeType.Reservoir) - { - code = helper.SetNodeValue(nodeIndex, Yw.Epanet.eNodeProperty.Elevation, reservoirElevation); - CheckCode(code); - } + } } var userNodeCount = nodeConfig.Count; @@ -246,12 +117,14 @@ var allDemands = calculator.CalculateDistributions(); code = helper.OpenH(); + CheckCode(code); for (int count = 0; count < allDemands.Count; count++) { - var calcNodelDict = new Dictionary<int, CalcNodeViewModel>(userNodeCount); + var calcNodelDict = new Dictionary<int, WaterPointNodeViewModel>(userNodeCount); var calcEndPressure = double.MaxValue; code = helper.InitH(false); + CheckCode(code); var demands = allDemands[count]; foreach (var node in nodeConfig) { @@ -260,194 +133,63 @@ code = helper.SetNodeValue(userNodeIndex, Yw.Epanet.eNodeProperty.BaseDemand, demand); CheckCode(code); - calcNodelDict[userNodeIndex] = new CalcNodeViewModel() + calcNodelDict[userNodeIndex] = new WaterPointNodeViewModel() { - NodeIndex = userNodeIndex, + Index = userNodeIndex, Flow = demand }; } code = helper.RunH(out long t); - + CheckCode(code); foreach (var node in nodeConfig) { var userNodeIndex = node.NodeIndex; pressure = 0; - //code = helper.GetNodeValue(userNodeIndex, Yw.Epanet.eNodeProperty.Pressure, out pressure); - //CheckCode(code); - //var endPressure = pressure + node.Elevation; - - code = helper.GetNodeValue(userNodeIndex, Yw.Epanet.eNodeProperty.Pressure, out pressure); + //鑷敱鍘嬪姏=缁濆鍘嬪姏-鏍囬珮 + //榛樿璧峰鐐瑰帇鍔涗负鏈�浣庢按浣嶏紝鎵�浠ョ敤 缁濆鍘嬪姏 褰撹嚜鐢卞帇鍔� 锛堢粷瀵瑰帇鍔�=鑷敱鍘嬪姏+鏍囬珮锛� + code = helper.GetNodeValue(userNodeIndex, Yw.Epanet.eNodeProperty.Head, out double head); CheckCode(code); - var endPressure = pressure + node.Elevation; + var endPressure = head; calcNodelDict[userNodeIndex].Pressure = endPressure; - if (calcEndPressure > endPressure) { calcEndPressure = endPressure; - } - - if (Math.Abs(calcEndPressure) > 100) - { - code = helper.GetNodeId(userNodeIndex, out string id); - var b = id; } } code = helper.NextH(out long tstep); - - var result = new CalcResultViewModel(); - result.TotalFlow = demands.TotalDemand; - result.EndPressure = Math.Abs(calcEndPressure); - result.CalcNodeList = calcNodelDict.Values.ToList(); - calcResultList.Add(result); + CheckCode(code); + var waterPointCalc = new WaterPointCalcViewModel(); + waterPointCalc.TotalFlow = demands.TotalDemand; + waterPointCalc.EndPressure = Math.Abs(calcEndPressure) + maxHeight + requiredEndPressure; + waterPointCalc.NodeList = calcNodelDict.Values.ToList(); + waterPointCalcList.Add(waterPointCalc); } code = helper.Close(); + CheckCode(code); } - - - - this.chartControl1.BeginInit(); - - - _curveUpperPressure = null; - _curveLowerPressure = null; - _curveAveragePressure = null; - _waterPointList = null; - - - _seriesWaterPoint.Points.Clear(); - _seriesUpperPressure.Points.Clear(); - _seriesLowerPressure.Points.Clear(); - _seriesAveragePressure.Points.Clear(); - - _constantLineDynamicPressure.Visible = false; - _constantLineStaticPressure.Visible = false; - - if (calcResultList.Any()) - { - _waterPointList = calcResultList.Select(x => new PointViewModel(x.TotalFlow, x.EndPressure + staticPressure + requiredEndPressure)).ToList(); - //_waterPointList = calcResultList.Select(x => new PointViewModel(x.TotalFlow, x.EndPressure + staticPressure)).ToList(); - - var waterPointGroup = _waterPointList.GroupBy(x => Math.Round(x.X, 1)); - var upperPressurePtList = new List<Yw.Geometry.Point2d>(); - var lowerPressurePtList = new List<Yw.Geometry.Point2d>(); - var averagePressurePtList = new List<Yw.Geometry.Point2d>(); - - foreach (var item in waterPointGroup) - { - var x = item.Key; - var yList = item.Select(x => x.Y).OrderBy(x => x).ToList(); - - var yUpper = CalculatePercentile(yList, 0.95); - var yLower = CalculatePercentile(yList, 0.05); - var yNumList = yList.Where(x => x >= yLower && x <= yUpper); - if (yNumList==null||!yNumList.Any()) - { - continue; - } - var yAverage = yNumList.Where(x => x >= yLower && x <= yUpper).Average(); - - upperPressurePtList.Add(new Yw.Geometry.Point2d(x, yUpper)); - lowerPressurePtList.Add(new Yw.Geometry.Point2d(x, yLower)); - averagePressurePtList.Add(new Yw.Geometry.Point2d(x, yAverage)); - - } - - _curveUpperPressure = new Yw.Ahart.CubicCurve(upperPressurePtList); - _curveLowerPressure = new Yw.Ahart.CubicCurve(lowerPressurePtList); - _curveAveragePressure = new Yw.Ahart.CubicCurve(averagePressurePtList); - - var upperPressureCurvePtList = _curveUpperPressure.GetPointList(100); - var lowerPressureCurvePtList = _curveLowerPressure.GetPointList(100); - var averagePressureCurvePtList = _curveAveragePressure.GetPointList(100); - - - foreach (var item in _waterPointList) - { - _seriesWaterPoint.Points.Add(new SeriesPoint(item.X, item.Y)); - } - foreach (var item in upperPressureCurvePtList) - { - _seriesUpperPressure.Points.Add(new SeriesPoint(item.X, item.Y)); - } - foreach (var item in lowerPressureCurvePtList) - { - _seriesLowerPressure.Points.Add(new SeriesPoint(item.X, item.Y)); - } - foreach (var item in averagePressureCurvePtList) - { - _seriesAveragePressure.Points.Add(new SeriesPoint(item.X, item.Y)); - } - - var minX = _waterPointList.Min(x => x.X); - var maxX = _waterPointList.Max(x => x.X); - - var minY = _waterPointList.Min(x => x.Y); - var maxY = _waterPointList.Max(x => x.Y); - - - //var minDynamicPressure = minY; - //_constantLineDynamicPressure.AxisValue = minDynamicPressure; - //_constantLineDynamicPressure.Title.Text = $"鏈�浣庝緵姘村帇鍔�:{minDynamicPressure:N2}m"; - //_constantLineDynamicPressure.Visible = true; - - //var totalStaticPressure = staticPressure + Math.Abs(reservoirElevation); - //_constantLineStaticPressure.AxisValue = totalStaticPressure; - //_constantLineStaticPressure.Title.Text = $"鏈�楂樻ゼ灞傞珮搴�:{totalStaticPressure:N2}m"; - //_constantLineStaticPressure.Visible = true; - - //minY = Math.Min(staticPressure, minY); - //maxY = Math.Max(staticPressure, maxY); - - //minY = Math.Min(staticPressure, minY); - //maxY = Math.Max(staticPressure, maxY); - - //maxY = Math.Floor(maxY); - //maxX = Math.Floor(maxX); - - //_xyDiagram.AxisX.WholeRange.Auto = true; - //_xyDiagram.AxisX.VisualRange.Auto = true; - //_xyDiagram.AxisX.WholeRange.SideMarginsValue = 0; - //_xyDiagram.AxisX.VisualRange.SideMarginsValue = 0; - //_xyDiagram.AxisX.NumericScaleOptions.AutoGrid = true; - //_xyDiagram.AxisX.WholeRange.SetMinMaxValues(minX, 50); - //_xyDiagram.AxisX.VisualRange.SetMinMaxValues(minX, 50); - - //_xyDiagram.AxisY.WholeRange.Auto = true; - //_xyDiagram.AxisY.VisualRange.Auto = true; - //_xyDiagram.AxisY.NumericScaleOptions.AutoGrid = true; - //_xyDiagram.AxisY.WholeRange.SideMarginsValue = 0; - //_xyDiagram.AxisY.VisualRange.SideMarginsValue = 0; - //_xyDiagram.AxisY.WholeRange.SetMinMaxValues(minY, 70); - //_xyDiagram.AxisY.VisualRange.SetMinMaxValues(minY, 70); - - } - this.chartControl1.EndInit(); + + this.systemCurveChartCtrl1.SetBindingData(waterPointCalcList); } - - private double CalculatePercentile(List<double> sortedData, double percentile) - { - int n = sortedData.Count; - double index = (n - 1) * percentile; - int lower = (int)Math.Floor(index); - int upper = (int)Math.Ceiling(index); - double fraction = index - lower; - return sortedData[lower] * (1 - fraction) + sortedData[upper] * fraction; - } + private void CheckCode(Yw.Epanet.eErrorCode code) { if (code != Yw.Epanet.eErrorCode.OK) { - var msg = code.GetDisplayText(); - throw new Exception(msg); + if ((int)code>100) + { + var msg = code.GetDisplayText(); + throw new Exception(msg); + } + } } -- Gitblit v1.9.3