using System.Text; namespace Yw.EPAnet { /// /// 管网计算拓展 /// public static class NetworkCalcuExtensions { /// /// 简单计算 /// public static CalcuResult CalcuSimple(this Network network) { var result = new CalcuResult(); //Null验证 if (network == null) { result.Succeed = false; return result; } var linkdict = network.GetAllLinks().ToDictionary(p => p.Id); var nodedict = network.GetAllNodes().ToDictionary(p => p.Id); //获取系统临时文件目录,创建inp临时文件 var inpFilePath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString("N") + ".inp"); //inp文本写入 var inpString = network.ToInpString(); File.WriteAllText(inpFilePath, inpString); //加载管网 var epanet = new HydraulicCore(true); var errOpen = epanet.open(inpFilePath, "", ""); if (errOpen != 0) { string errorMsg = epanet.geterrormsg(); result.Succeed = false; result.FailedList.Add(new CalcuFailed() { Code = errOpen, Message = $"{errorMsg}" }); return result; } //水力计算 var errCalcu = epanet.solveH(); if (errCalcu != 0) { string errorMsg = epanet.geterrormsg(); result.Succeed = false; result.FailedList.Add(new CalcuFailed() { Code = errCalcu, Message = $"{errorMsg}" }); return result; } int nodeCount = 0; int linkCount = 0; epanet.getcount((int)eCountType.Node, ref nodeCount); epanet.getcount((int)eCountType.Link, ref linkCount); const int MAXID = 31; var sb = new StringBuilder(MAXID); for (int i = 1; i <= nodeCount; i++) { epanet.getnodeid(i, sb); var arr = new string[] { "Head", "Press", "Demand" }; //System.Enum.GetValues(typeof(HydraulicModel.NodeValueType)); var arrnum = new int[] { 10, 11, 9 }; var calcuNode = new CalcuNode() { Id = sb.ToString(), }; for (var j = 0; j < arr.Length; j++) { float v = 0; //var t = (EPAcore.Core.NodeValueType)j; epanet.getnodevalue(i, arrnum[j], ref v); switch (arr[j]) { case "Head": calcuNode.Head = v; break; case "Press": calcuNode.Press = v; break; case "Demand": calcuNode.Demand = v; break; } } result.NodeList.Add(calcuNode); } var nodeResultDict = result.NodeList.ToDictionary(p => p.Id); for (int i = 1; i <= linkCount; i++) { epanet.getlinkid(i, sb); //var arr = System.Enum.GetValues(typeof(HydraulicModel.LinkValueType)); var arr = new string[] { "Flow", "Velocity", "Headloss" }; //System.Enum.GetValues(typeof(HydraulicModel.NodeValueType)); var arrnum = new int[] { 8, 9, 10 }; var calcuLink = new CalcuLink() { Id = sb.ToString(), }; for (var j = 0; j < arr.Length; j++) { float v = 0; //var t = (EPAcore.Core.NodeValueType)j; epanet.getlinkvalue(i, arrnum[j], ref v); switch (arr[j]) { case "Flow": calcuLink.Flow = v; break; case "Velocity": calcuLink.Velocity = v; break; case "Headloss": calcuLink.Headloss = v; break; } if (linkdict[calcuLink.Id] is Pipe p) { double minorloss1 = p.StartMinorloss * Math.Pow(calcuLink.Velocity, 2) / 2 / 9.81; double minorloss2 = p.EndMinorloss * Math.Pow(calcuLink.Velocity, 2) / 2 / 9.81; double minorloss = p.MinorLoss * Math.Pow(calcuLink.Velocity, 2) / 2 / 9.81; calcuLink.Headloss -= minorloss1 + minorloss2; calcuLink.MinorLoss = minorloss; calcuLink.FrictionLoss = calcuLink.Headloss - minorloss; //if (nodedict[p.StartNode.Id] is Elbow) { nodeResultDict[p.StartNode.Id].MinorLoss += minorloss1; } //if (nodedict[p.EndNode.Id] is Elbow) { nodeResultDict[p.EndNode.Id].MinorLoss += minorloss2; } } } result.LinkList.Add(calcuLink); } return result; } /// /// 计算局阻系数 /// network中的局部损失会被修改 /// public static CalcuResult CalcuMinorLoss(this Network network) { var calcuResult = network.CalcuSimple(); if (!calcuResult.Succeed) { return calcuResult; } var allCalcuLinks = calcuResult.LinkList; var allNodeList = network.GetAllNodes(); var allLinkList = network.GetAllLinks(); foreach (var link in allLinkList) { if (link is Pipe p) { p.StartMinorloss = 0; p.EndMinorloss = 0; } } foreach (var node in allNodeList) { var prevLinks = node.GetPrevLinks(allCalcuLinks); if (prevLinks == null || prevLinks.Count < 1) { continue; } var nextLinks = node.GetNextLinks(allCalcuLinks); if (nextLinks == null || nextLinks.Count < 1) { continue; } if (node is Elbow elbow) { //弯头 if (!elbow.MinorLoss.HasValue) { continue; } if (prevLinks.Count != 1) { continue; } var prevLink = prevLinks[0] as Pipe; if (prevLink != null) { prevLink.EndMinorloss = elbow.MinorLoss.Value / 2f; } if (nextLinks.Count != 1) { continue; } var nextLink = nextLinks[0] as Pipe; if (nextLink != null) { nextLink.StartMinorloss = elbow.MinorLoss.Value / 2f; } } else if (node is Threelink threelink) { //三通 var linkCount = prevLinks.Count + nextLinks.Count; if (linkCount != 3) { continue; } Link mainLink = null;//主管 List branchLinks = null;//支管列表 bool isNext = prevLinks.Count == 1; if (isNext)//1进2出 { mainLink = prevLinks[0]; branchLinks = nextLinks; } else//2进1出 { mainLink = nextLinks[0]; branchLinks = prevLinks; } var mainPipe = mainLink as Pipe; if (mainPipe == null) { continue; } foreach (var branchLink in branchLinks) { var branchPipe = branchLink as Pipe; if (branchPipe == null) { continue; } if (branchPipe.Diameter == mainPipe.Diameter) { var minorLoss = threelink.RunningThroughLoss; if (!minorLoss.HasValue) { minorLoss = threelink.MinorLoss; if (minorLoss.HasValue) { if (isNext) branchPipe.StartMinorloss = minorLoss.Value; else branchPipe.EndMinorloss = minorLoss.Value; } } } else { var minorLoss = threelink.BranchThroughLoss; if (!minorLoss.HasValue) { minorLoss = threelink.MinorLoss; if (minorLoss.HasValue) { if (isNext) branchPipe.StartMinorloss = minorLoss.Value; else branchPipe.EndMinorloss = minorLoss.Value; } } } } } else if (node is Fourlink fourlink) { //四通 if (!fourlink.MinorLoss.HasValue) { continue; } var linkCount = prevLinks.Count + nextLinks.Count; if (linkCount != 4) { continue; } bool isNext = prevLinks.Count < nextLinks.Count; var branchLinks = isNext ? nextLinks : prevLinks; foreach (var branchLink in branchLinks) { var pipe = branchLink as Pipe; if (pipe != null) { if (isNext) { pipe.StartMinorloss = fourlink.MinorLoss.Value; } else { pipe.EndMinorloss = fourlink.MinorLoss.Value; } } } } } calcuResult = network.CalcuSimple(); return calcuResult; } /// /// 计算 /// public static CalcuResult Calcu(this Network network, string calcuMode) { CalcuResult result = null; switch (calcuMode) { case CalcuMode.Simple: { result = network.CalcuSimple(); } break; case CalcuMode.MinorLoss: { result = network.CalcuMinorLoss(); } break; default: { result = network.CalcuSimple(); } break; } return result; } } }