cloudflight
2024-07-20 368869e50aa1bc741d4cc319dbd24e798e48b3a2
Hydraulic/Hydro.MapView/MapViewNetWork.cs
@@ -1,5 +1,5 @@
using Hydro.Core.Model;
using Hydro.Inp;
//using Hydro.Inp;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json;
using System;
@@ -33,9 +33,48 @@
        private NodeViewModelList _nodes = new NodeViewModelList();
        public NodeViewModelList Nodes { get { return _nodes; }set { base.Nodes = _nodes = value; } }
        private List<AreaViewModel> _areas = new List<AreaViewModel>();
        public List<AreaViewModel> Areas { get { return _areas; } set {  _areas = value; } }
        public NodeViewModel StartPoint { get; set; }
        public NodeViewModel EndPoint { get; set; }
        public double[] getMinMax(ColourType colourType)
        {
            //根据当前选中的ColourType,判断是否有对应的网络数据
            double max = 0;
            double min = 0;
            switch (colourType)
            {
                case ColourType.节点自由压力:
                    max = Nodes.Where(node => !(node is ReservoirViewModel || node is TankViewModel)).Max(node => node.EN_PRESSURE);
                    min = Nodes.Where(node => !(node is ReservoirViewModel || node is TankViewModel)).Min(node => node.EN_PRESSURE);
                    break;
                case ColourType.节点绝对压力:
                    max = Nodes.Where(node => !(node is ReservoirViewModel || node is TankViewModel)).Max(node => node.EN_PRESSURE);
                    min = Nodes.Where(node => !(node is ReservoirViewModel || node is TankViewModel)).Min(node => node.EN_PRESSURE);
                    break;
                case ColourType.节点需水量:
                    max = Nodes.Where(node => !(node is ReservoirViewModel || node is TankViewModel)).Max(node => node.EN_DEMAND);
                    min = Nodes.Where(node => !(node is ReservoirViewModel || node is TankViewModel)).Min(node => node.EN_DEMAND);
                    break;
                case ColourType.管线流量:
                    max = Links.Max(link => link.EN_FLOW);
                    min = Links.Min(link => link.EN_FLOW);
                    break;
                case ColourType.管线流速:
                    max = Links.Max(link => link.EN_VELOCITY);
                    min = Links.Min(link => link.EN_VELOCITY);
                    break;
                default:
                    break;
            }
            return new double[] { min, max };
        }
        /// <summary>
        /// 当量集合,当量模板ID,<器具ID,数量>
@@ -393,6 +432,7 @@
            pipe.Status = StatusType.DEFAULT;
            pipe.StartNode = node1;
            pipe.EndNode = node2;
            pipe.Length = -1;
@@ -618,7 +658,9 @@
            });
            if (ConnectNode!=null)
            {
                list.Add(AddPipe(ConnectNode, net.StartPoint));
                var l = AddPipe(ConnectNode, net.StartPoint);
                list.Add(l);
                Hash_ID.Add(l.ID);
            }
            //BuildRelation();
            return list;
@@ -814,10 +856,72 @@
        public List<TimePoint> Calc(string inpPath, string configPath = null)
        {
            bool CalcByConfig = false;
            List<TimePoint> list = new List<TimePoint>();
            if (CalcByConfig)
            {
                WdnmoParam wdnmoParam = new WdnmoParam();
                Nodes.ForEach(n =>
                {
                    //if (n is JunctionViewModel || n is MeterViewModel || n is NozzleViewModel)
                    {
                        wdnmoParam.ResultPoints.Add(new TimePoint { Key = $"Press_{n.ID}" });
                        wdnmoParam.ResultPoints.Add(new TimePoint { Key = $"Head_{n.ID}" });
                        wdnmoParam.ResultPoints.Add(new TimePoint { Key = $"Demand_{n.ID}" });
                    }
                });
                Links.ForEach(n =>
                {
                    //if (n is PipeViewModel || n is PumpViewModel || n is ValveViewModel)
                    {
                        wdnmoParam.ResultPoints.Add(new TimePoint { Key = $"Flow_{n.ID}" });
                        wdnmoParam.ResultPoints.Add(new TimePoint { Key = $"Velocity_{n.ID}" });
                        wdnmoParam.ResultPoints.Add(new TimePoint { Key = $"Headloss_{n.ID}" });
                    }
                });
                calc c = new calc();
                list = c.GetCalcResult(inpPath, wdnmoParam, configPath);
                if (list == null) return list;
            }
            else
            {
                list= base.Calc(inpPath);
            }
            list.Sort((a, b) => string.Compare(a.Key, b.Key));
            Nodes.Sort((a, b) => string.Compare(a.ID, b.ID));
            Links.Sort((a, b) => string.Compare(a.ID, b.ID));
            SetNodeFromWparam(this, list, "Press");
            SetNodeFromWparam(this, list, "Head");
            SetNodeFromWparam(this, list, "Demand");
            SetLinkFromWparam(this, list, "Flow");
            SetLinkFromWparam(this, list, "Velocity");
            SetLinkFromWparam(this, list, "Headloss");
            Links.ForEach(l=>
            {
                l.EN_HEADLOSS_MINOR = (float)Math.Round(l.MinorLoss * Math.Pow(l.EN_VELOCITY, 2) / 2 / 9.8, 4);
                l.EN_HEADLOSS_LINE = l.EN_HEADLOSS - l.EN_HEADLOSS_MINOR;
            });
            this._isCalculated = true;
            return list;
            //return new List<TimePoint>();
        }
        public List<TimePoint> WaterDistribution(string inpPath, string configPath = null,List<WaterEquivalentSettings> settings=null,double TotalDemand=-1,double InitPress=100)
        {
            if (TotalDemand < 0)
            {
                throw new Exception("TotalDemand must be set");
            }
            WdnmoParam wdnmoParam = new WdnmoParam();
            wdnmoParam.UpdateWParamByWaterEquivalentSettings(settings, TotalDemand);
            wdnmoParam.ScadaPoints.Add(new TimePoint { Key = "initPress", Value= InitPress });
            Nodes.ForEach(n =>
            {
                //if (n is JunctionViewModel || n is MeterViewModel || n is NozzleViewModel)
@@ -852,15 +956,18 @@
            SetLinkFromWparam(this, list, "Velocity");
            SetLinkFromWparam(this, list, "Headloss");
            Links.ForEach(l=>
            Links.ForEach(l =>
            {
                l.EN_HEADLOSS_MINOR = (float)Math.Round(l.MinorLoss * Math.Pow(l.EN_VELOCITY, 2) / 2 / 9.8, 4);
                l.EN_HEADLOSS_LINE = l.EN_HEADLOSS - l.EN_HEADLOSS_MINOR;
            });
            Nodes.ForEach(n => n.Demand = n.EN_DEMAND);
            this._isCalculated = true;
            return list;
            //return new List<TimePoint>();
        }
        public List<TimePoint> CalcByVal(WDNModelOptimizer wdo, Result val)
        {
@@ -912,6 +1019,171 @@
            return list;
            //return new List<TimePoint>();
        }
        public Dictionary<string, List<string>> CheckValidate()
        {
            BuildRelation();
            string result = null;
            Dictionary<string, List<string>> result_dict = new Dictionary<string, List<string>>();
            StringBuilder result_sb=new StringBuilder();
            //to-do
            var objs = Links.Select(o => o as LinkViewModel).ToList();//new List<LinkViewModel>() { Links[0] }; //Links.FindAll(o => o is LinkViewModel).Select(o => o as LinkViewModel).ToList();
            //objs去掉重复的元素
            objs = objs.Distinct().ToList();
            var visitedNodes = new HashSet<NodeViewModel>();
            FindObjs = new HashSet<IBaseViewModel>();
            objs.ForEach(o => TraversePipeNetworkALL(o, visitedNodes));
            List<string> list_孤立点 = new List<string>();
            for(int i=0;i<Nodes.Count;i++)
            {
                if (!FindObjs.Contains(Nodes[i]))
                {
                    result_sb.AppendLine($"节点{Nodes[i].ID}是孤立点");
                    list_孤立点.Add(Nodes[i].ID);
                }
            }
            if (list_孤立点.Count>0)result_dict.Add("孤立点", list_孤立点);
            //属性判断
            var list_管道连接关系异常 = new List<string>();
            var list_管道长度小于等于0 = new List<string>();
            var list_粗糙系数设置错误 = new List<string>();
            var list_管径设置错误 = new List<string>();
            pipes.ForEach(p =>
            {
                if (p.StartNode == null || p.EndNode == null)
                {
                    result_sb.AppendLine($"{p.ID}管道连接关系异常");
                    list_管道连接关系异常.Add(p.ID);
                }
                if (p.Length<=0)
                {
                    result_sb.AppendLine($"{p.ID}管道长度小于等于0");
                    list_管道长度小于等于0.Add(p.ID);
                }
                if (p.Roughness<=0.1 || p.Roughness>10000)
                {
                    result_sb.AppendLine($"{p.ID}粗糙系数设置错误");
                    list_粗糙系数设置错误.Add(p.ID);
                }
                if (p.Diameter<=0.1 || p.Diameter>10000)
                {
                    result_sb.AppendLine($"{p.ID}管径设置错误");
                    list_管径设置错误.Add(p.ID);
                }
            });
            if (list_管道连接关系异常.Count > 0) result_dict.Add("管道连接关系异常", list_管道连接关系异常);
            if (list_管道长度小于等于0.Count > 0) result_dict.Add("管道长度小于等于0", list_管道长度小于等于0);
            if (list_粗糙系数设置错误.Count > 0) result_dict.Add("粗糙系数设置错误", list_粗糙系数设置错误);
            if (list_管径设置错误.Count > 0) result_dict.Add("管径设置错误", list_管径设置错误);
            return result_dict;
        }
        HashSet<IBaseViewModel> FindObjs;
        private void TraversePipeNetworkALL(LinkViewModel startLink, HashSet<NodeViewModel> visitedNodes = null, int direction = 0)
        {
            Queue<LinkViewModel> queue = new Queue<LinkViewModel>();
            queue.Enqueue(startLink);
            if (visitedNodes == null)
                visitedNodes = new HashSet<NodeViewModel>();
            //visitedNodes.Add(startLink.StartNode);
            //visitedNodes.Add(startLink.EndNode);
            while (queue.Count > 0)
            {
                LinkViewModel currentLink = queue.Dequeue();
                //Console.WriteLine("Traversing Link: " + currentLink.ID);
                foreach (var node in new NodeViewModel[] { currentLink.StartNode, currentLink.EndNode })
                {
                    if (direction == 1 && currentLink.EN_FLOW >= 0 && node == currentLink.StartNode) continue;
                    if (direction == -1 && currentLink.EN_FLOW <= 0 && node == currentLink.EndNode) continue;
                    if (node != null && !visitedNodes.Contains(node))
                    {
                        visitedNodes.Add(node);
                        if (!FindObjs.Contains(node)) FindObjs.Add(node);
                        //Console.WriteLine("Visiting Node: " + node.ID);
                        foreach (var link in node.ViewLinks)
                        {
                            if (!visitedNodes.Contains(link.StartNode) || !visitedNodes.Contains(link.EndNode))
                            {
                                if (!FindObjs.Contains(link)) FindObjs.Add(link);
                                queue.Enqueue(link);
                            }
                        }
                    }
                }
            }
        }
        public List<TimePoint> CalcByValAndHead(WDNModelOptimizer wdo, Result val,double Head)
        {
            WdnmoParam wdnmoParam = new WdnmoParam();
            Nodes.ForEach(n =>
            {
                //if (n is JunctionViewModel || n is MeterViewModel || n is NozzleViewModel)
                {
                    wdnmoParam.ResultPoints.Add(new TimePoint { Key = $"Press_{n.ID}" });
                    wdnmoParam.ResultPoints.Add(new TimePoint { Key = $"Head_{n.ID}" });
                    wdnmoParam.ResultPoints.Add(new TimePoint { Key = $"Demand_{n.ID}" });
                }
            });
            Links.ForEach(n =>
            {
                //if (n is PipeViewModel || n is PumpViewModel || n is ValveViewModel)
                {
                    wdnmoParam.ResultPoints.Add(new TimePoint { Key = $"Flow_{n.ID}" });
                    wdnmoParam.ResultPoints.Add(new TimePoint { Key = $"Velocity_{n.ID}" });
                    wdnmoParam.ResultPoints.Add(new TimePoint { Key = $"Headloss_{n.ID}" });
                }
            });
            calcParam calcParam = new calcParam();
            calcParam.vars = val.arrayTryValue;
            calcParam.setVars = new List<SetVar>();
            reservoirs.ForEach(r =>
            {
                calcParam.setVars.Add(new SetVar(r.ID, true, (int)EpanetEnum.NodeValueType.水池水位, (float)Head));
            });
            wdnmoParam = wdo.CalcbyResult(calcParam, wdnmoParam);
            var list = wdnmoParam.ResultPoints;
            if (list == null) return list;
            list.Sort((a, b) => string.Compare(a.Key, b.Key));
            Nodes.Sort((a, b) => string.Compare(a.ID, b.ID));
            Links.Sort((a, b) => string.Compare(a.ID, b.ID));
            SetNodeFromWparam(this, list, "Press");
            SetNodeFromWparam(this, list, "Head");
            SetNodeFromWparam(this, list, "Demand");
            SetLinkFromWparam(this, list, "Flow");
            SetLinkFromWparam(this, list, "Velocity");
            SetLinkFromWparam(this, list, "Headloss");
            this._isCalculated = true;
            return list;
            //return new List<TimePoint>();
        }
        private void SetNodeFromWparam(MapViewNetWork net, List<TimePoint> list, string valueType)
        {
@@ -934,7 +1206,8 @@
                    }
                    if (k2 == list.Count)
                    {
                        throw new Exception($"未找到Node[{J.ID}]的{valueType}");
                        return;
                        //throw new Exception($"未找到Node[{J.ID}]的{valueType}");
                    }
                    switch (valueType)
                    {
@@ -975,7 +1248,8 @@
                    }
                    if (k2 == list.Count)
                    {
                        throw new Exception($"未找到Link[{J.ID}]的{valueType}");
                        return;
                        //throw new Exception($"未找到Link[{J.ID}]的{valueType}");
                    }
                    switch (valueType)
                    {