| | |
| | | /// </summary> |
| | | public static class NetworkPathAnalyseExtensions |
| | | { |
| | | internal class InnerLossNode |
| | | { |
| | | public string Id { get; set; } |
| | | /// <summary> |
| | | /// 起始水头 |
| | | /// </summary> |
| | | public double StartHead { get; set; } |
| | | |
| | | |
| | | public static List<ChartNode> GetChartNodeByPathLinks(this Network network, List<ILink> links) |
| | | /// <summary> |
| | | /// 结束水头 |
| | | /// </summary> |
| | | public double EndHead { get; set; } |
| | | |
| | | /// <summary> |
| | | /// 高程 |
| | | /// </summary> |
| | | public double Elev { get; set; } |
| | | |
| | | /// <summary> |
| | | /// 水头 |
| | | /// </summary> |
| | | public double Head { get; internal set; } |
| | | |
| | | /// <summary> |
| | | /// 局部水头损失 |
| | | /// </summary> |
| | | public double MinorHeadLoss |
| | | { |
| | | get |
| | | { |
| | | return StartHead - EndHead; |
| | | } |
| | | } |
| | | |
| | | public double Distance { get; set; } |
| | | } |
| | | |
| | | public static List<LossNode> GetChartNodeByPathLinks(this Network network, List<Link> links,CalcuResult calcuResult) |
| | | { |
| | | |
| | | |
| | | |
| | | var dictLinks = calcuResult.LinkList.ToDictionary(p => p.Id); |
| | | var dictNodes = calcuResult.NodeList.ToDictionary(p => p.Id); |
| | | |
| | | double length = 0; |
| | | ChartNode nodeEnd = new ChartNode(); |
| | | List<ChartNode> chartNodes = new List<ChartNode>(); |
| | | InnerLossNode nodeEnd = new InnerLossNode(); |
| | | List<InnerLossNode> chartNodes = new List<InnerLossNode>(); |
| | | for (int i = 0; i < links.Count; i++) |
| | | { |
| | | |
| | | var link = links[i]; |
| | | |
| | | var node = link.Flow > 0 ? link.StartNode : link.EndNode; |
| | | var node = dictLinks[link.Id].Flow > 0 ? link.StartNode : link.EndNode; |
| | | |
| | | double elev = getElev(node); |
| | | |
| | | |
| | | var Cnode = new ChartNode() |
| | | var Cnode = new InnerLossNode() |
| | | { |
| | | Id = node.Id, |
| | | StartHead = node.Head, |
| | | |
| | | EndHead = node.Head, |
| | | |
| | | Elev = node.Elev |
| | | StartHead = dictNodes[node.Id].Head, |
| | | EndHead = dictNodes[node.Id].Head, |
| | | Elev = elev, |
| | | Distance = length |
| | | }; |
| | | chartNodes.Add(Cnode); |
| | | |
| | | |
| | | var nodeEnd0 = link.Flow > 0 ? link.EndNode : link.StartNode; |
| | | |
| | | var nodeEnd0 = dictLinks[link.Id].Flow > 0 ? link.EndNode : link.StartNode; |
| | | nodeEnd.Id = nodeEnd0.Id; |
| | | nodeEnd.Head = nodeEnd.StartHead = nodeEnd.EndHead = nodeEnd0.Head; |
| | | nodeEnd.Elev = nodeEnd0.Elev; |
| | | nodeEnd.Head = nodeEnd.StartHead = nodeEnd.EndHead = dictNodes[nodeEnd0.Id].Head; |
| | | nodeEnd.Elev = getElev(nodeEnd0); |
| | | |
| | | if (link is Pipe p) |
| | | length += p.Length; |
| | | |
| | | } |
| | | |
| | | chartNodes.Add(nodeEnd); |
| | |
| | | if (p != null) |
| | | { |
| | | //根据p.diameter和p.flow计算流速 |
| | | double velocity = p.Flow / (Math.PI * Math.Pow(p.Diameter / 2, 2)); |
| | | double velocity = dictLinks[ p.Id].Flow/ (Math.PI * Math.Pow(p.Diameter / 2, 2)); |
| | | //根据流速计算局部水头损失 |
| | | double minorloss1 = p.StartNodeMinorlossCoff* Math.Pow(velocity, 2) / 2 / 9.81; |
| | | double minorloss2 = p.EndNodeMinorlossCoff * Math.Pow(velocity, 2) / 2 / 9.81; |
| | | double minorloss1 = p.StartMinorloss* Math.Pow(velocity, 2) / 2 / 9.81; |
| | | double minorloss2 = p.EndMinorloss * Math.Pow(velocity, 2) / 2 / 9.81; |
| | | |
| | | |
| | | if (i < links.Count - 1) |
| | |
| | | |
| | | |
| | | } |
| | | return chartNodes; |
| | | List<LossNode> lossNodes = new List<LossNode>(); |
| | | for (int i = 0; i < chartNodes.Count; i++) |
| | | { |
| | | var node = chartNodes[i]; |
| | | LossNode lossNode = new LossNode() |
| | | { |
| | | Id = node.Id, |
| | | Elev = node.Elev, |
| | | Head = node.StartHead, |
| | | MinorLoss = node.MinorHeadLoss, |
| | | Distance =node.Distance, |
| | | }; |
| | | lossNodes.Add(lossNode); |
| | | } |
| | | return lossNodes; |
| | | |
| | | } |
| | | |
| | | private static double getElev(Node node) |
| | | { |
| | | double elev = 0; |
| | | if (node is Tank tank) |
| | | { |
| | | elev = tank.PoolElev + tank.InitLevel; |
| | | } |
| | | else if (node is Reservoir reser) |
| | | { |
| | | elev = reser.Head; |
| | | } |
| | | else if (node is Junction junc) |
| | | { |
| | | elev = junc.Elev; |
| | | } |
| | | |
| | | return elev; |
| | | } |
| | | |
| | | |
| | | /// <summary> |
| | | /// 分析下游主要供水路径 |
| | | /// </summary> |
| | | public static List<ILink> AnalyzeDownstreamPath(this Network network, Junction startJunc) |
| | | public static List<Link> AnalyzeDownstreamPath(this Network network, Node startJunc,CalcuResult calcuResult) |
| | | { |
| | | var visitedNodes = new HashSet<INode>(); |
| | | var maxlink = startJunc.NextLinks.OrderByDescending(o => Math.Abs(o.Flow)).ToList()[0]; |
| | | var dictLinks = calcuResult.LinkList.ToDictionary(p => p.Id); |
| | | var dictNodes = calcuResult.NodeList.ToDictionary(p => p.Id); |
| | | var visitedNodes = new HashSet<Node>(); |
| | | var maxlink = startJunc.GetNextLinks(calcuResult.LinkList).OrderByDescending(o => Math.Abs(dictLinks[o.Id].Flow)).ToList()[0]; |
| | | return network.TraversePipeNetworkALL(maxlink, visitedNodes, 1, true); |
| | | } |
| | | |
| | |
| | | /// <param name="network"></param> |
| | | /// <param name="startJunc"></param> |
| | | /// <returns></returns> |
| | | public static List<ILink> AnalyzeUpstreamPath(this Network network, Junction startJunc) |
| | | public static List<Link> AnalyzeUpstreamPath(this Network network, Junction startJunc, CalcuResult calcuResult) |
| | | { |
| | | var visitedNodes = new HashSet<INode>(); |
| | | var maxlink = startJunc.NextLinks.OrderByDescending(o => Math.Abs(o.Flow)).ToList()[0]; |
| | | return network.TraversePipeNetworkALL(maxlink, visitedNodes, -1, true); |
| | | var dictLinks = calcuResult.LinkList.ToDictionary(p => p.Id); |
| | | var dictNodes = calcuResult.NodeList.ToDictionary(p => p.Id); |
| | | var visitedNodes = new HashSet<Node>(); |
| | | var maxlink = startJunc.GetPrevLinks(calcuResult.LinkList).OrderByDescending(o => Math.Abs(dictLinks[o.Id].Flow)).ToList()[0]; |
| | | return network.TraversePipeNetworkALL(maxlink, visitedNodes, -1, true, calcuResult); |
| | | } |
| | | /// <summary> |
| | | /// 宽度搜索遍历管网 |
| | |
| | | /// <param name="direction">遍历方向,0表示双向,1表示正向,-1表示反向</param> |
| | | /// <param name="isOnlyMax">是否只取最大流量的分支</param> |
| | | /// <returns></returns> |
| | | public static List<ILink> TraversePipeNetworkALL(this Network network,ILink startLink, HashSet<INode> visitedNodes = null, int direction = 0, bool isOnlyMax = false) |
| | | public static List<Link> TraversePipeNetworkALL(this Network network, Link startLink, HashSet<Node> visitedNodes = null, int direction = 0, bool isOnlyMax = false,CalcuResult calcuResult=null) |
| | | { |
| | | var _links主要路径=new List<ILink>(); |
| | | var dictLinks = calcuResult.LinkList.ToDictionary(p => p.Id); |
| | | var dictNodes = calcuResult.NodeList.ToDictionary(p => p.Id); |
| | | var _links主要路径=new List<Link>(); |
| | | if (isOnlyMax) _links主要路径.Add(startLink); |
| | | Queue<ILink> queue = new Queue<ILink>(); |
| | | Queue<Link> queue = new Queue<Link>(); |
| | | |
| | | queue.Enqueue(startLink); |
| | | if (visitedNodes == null) |
| | | visitedNodes = new HashSet<INode>(); |
| | | visitedNodes = new HashSet<Node>(); |
| | | |
| | | while (queue.Count > 0) |
| | | { |
| | | ILink currentLink = queue.Dequeue(); |
| | | Link currentLink = queue.Dequeue(); |
| | | if (isOnlyMax) _links主要路径.Add(currentLink); |
| | | |
| | | foreach (var node in new INode[] { currentLink.StartNode, currentLink.EndNode }) |
| | | foreach (var node in new Node[] { currentLink.StartNode, currentLink.EndNode }) |
| | | { |
| | | if (direction == 1 && currentLink.Flow >= 0 && node == currentLink.StartNode) continue; |
| | | if (direction == -1 && currentLink.Flow <= 0 && node == currentLink.EndNode) continue; |
| | | if (direction == 1 && dictLinks[currentLink.Id].Flow >= 0 && node == currentLink.StartNode) continue; |
| | | if (direction == -1 && dictLinks[currentLink.Id].Flow <= 0 && node == currentLink.EndNode) continue; |
| | | if (node != null && !visitedNodes.Contains(node)) |
| | | { |
| | | visitedNodes.Add(node); |
| | | List<ILink> list = new List<ILink>(); |
| | | List<Link> list = new List<Link>(); |
| | | |
| | | foreach (var link in node.Links) |
| | | { |
| | |
| | | { |
| | | if (list.Count >= 1) |
| | | { |
| | | var maxlist = list.OrderByDescending(p => Math.Abs(p.Flow)).ToList()[0]; |
| | | var maxlist = list.OrderByDescending(p => Math.Abs(dictLinks[p.Id].Flow)).ToList()[0]; |
| | | queue.Enqueue(maxlist); |
| | | } |
| | | |
| | |
| | | |
| | | } |
| | | |
| | | public class ChartNode |
| | | public class LossNode |
| | | { |
| | | public string Id { get; set; } |
| | | |
| | | /// <summary> |
| | | /// 起始水头 |
| | | /// </summary> |
| | | public double StartHead { get; set; } |
| | | |
| | | /// <summary> |
| | | /// 结束水头 |
| | | /// </summary> |
| | | public double EndHead { get; set; } |
| | | |
| | | /// <summary> |
| | | /// 高程 |
| | |
| | | /// <summary> |
| | | /// 水头 |
| | | /// </summary> |
| | | public double Head { get; internal set; } |
| | | public double Head { get; set; } |
| | | |
| | | /// <summary> |
| | | /// 局部水头损失 |
| | | /// </summary> |
| | | public double MinorHeadLoss |
| | | { |
| | | get |
| | | { |
| | | return StartHead - EndHead; |
| | | } |
| | | } |
| | | public double MinorLoss { get; set; } |
| | | |
| | | /// <summary> |
| | | /// 距离 |
| | | /// </summary> |
| | | public double Distance { get; set; } |
| | | } |
| | | } |