Shuxia Ning
2024-11-25 d4898c5d7e1bbbbba384a0e29f29c066d6f502a7
Hydro/Yw.EPAnet.Calcu.Core/04-Inp/InpInteropHelper.cs
@@ -1,6 +1,5 @@
using System.Text;
using System.Text.RegularExpressions;
//using Hydro.CommonBase;
namespace Yw.EPAnet
{
@@ -12,25 +11,26 @@
        /// <summary>
        /// 转换至Inp字符串
        /// </summary>
        /// <returns></returns>
        public static string ToInpString(this Network net, CalcuResult minorResult=null)
        public static string ToInpString(this Network network, CalcuResult minorResult = null)
        {
            string tempString = "";
            var tempPath = Path.Combine(Directory.GetCurrentDirectory(), @"template\template.inp");
            if (!File.Exists(tempPath))
            //模板文件
            var templateFilePath = TemplateHelper.GetPath();
            if (!File.Exists(templateFilePath))
            {
                throw new Exception("模板文件不存在," + tempPath);
                throw new Exception("模板文件不存在," + templateFilePath);
            }
            var templateString = File.ReadAllText(templateFilePath);
            tempString = File.ReadAllText(tempPath);
            StringBuilder statusStringBuilder = new StringBuilder();
            statusStringBuilder.AppendLine(";ID              \tStatus/Setting\r\n");
            //状态
            var statusSb = new StringBuilder();
            statusSb.AppendLine(";ID              \tStatus/Setting\r\n");
            StringBuilder emitterStringBuilder = new StringBuilder();
            emitterStringBuilder.AppendLine(";Junction        \tCoefficient");
            //扩散器
            var emitterSb = new StringBuilder();
            emitterSb.AppendLine(";Junction        \tCoefficient");
            StringBuilder coorStringBuilder = new StringBuilder();
            //坐标
            var coorStringBuilder = new StringBuilder();
            coorStringBuilder.AppendLine(";Node               X-Coord              Y-Coord");
            Dictionary<string, string> dictExchange = new Dictionary<string, string>() {
@@ -45,123 +45,146 @@
                {"{curve}","{7}" },
                {"{emitters}","{8}" },
            };
            dictExchange.ToList().ForEach(m => tempString = tempString.Replace(m.Key, m.Value));
            dictExchange.ToList().ForEach(m => templateString = templateString.Replace(m.Key, m.Value));
            StringBuilder junctionStringBuilder = new StringBuilder();
            //连接节点
            var junctionStringBuilder = new StringBuilder();
            junctionStringBuilder.AppendLine(";ID                 Elev           Demand         Pattern         Type");
            net.Junctions.ForEach(o =>
            //连接节点处理
            network.Junctions?.ForEach(x =>
            {
                var pTemp = o.DemandPattern;
                if (string.IsNullOrEmpty(pTemp) || pTemp == ";" || pTemp == "_") pTemp = "";
                junctionStringBuilder.AppendLine($"{o.Id}\t{o.Elev}\t{o.Demand}\t{pTemp}\t;\t" + $"0\tJunction");
                coorStringBuilder.AppendLine(o.Id + "    " + o.Position.X + "    " + o.Position.Y);
            });
            net.Meters.ForEach(o =>
            {
                var pTemp = o.DemandPattern;
                if (string.IsNullOrEmpty(pTemp) || pTemp == ";" || pTemp == "_") pTemp = "";
                junctionStringBuilder.AppendLine($"{o.Id}\t{o.Elev}\t{o.Demand}\t{pTemp}\t;\t" + $"0\tMeters");
                coorStringBuilder.AppendLine(o.Id + "    " + o.Position.X + "    " + o.Position.Y);
            });
            net.Nozzles.ForEach(o =>
            {
                var pTemp = o.DemandPattern;
                if (string.IsNullOrEmpty(pTemp) || pTemp == ";" || pTemp == "_") pTemp = "";
                junctionStringBuilder.AppendLine($"{o.Id}\t{o.Elev}\t{o.Demand}\t{pTemp}\t;\t" + $"0\tNozzle\t{o.Coefficient}");
                double Coe = o.Coefficient * Math.Pow(10 / 101.972, 0.5) / 1000 * 60;
                emitterStringBuilder.AppendLine(o.Id + "    " + Coe);
                coorStringBuilder.AppendLine(o.Id + "    " + o.Position.X + "    " + o.Position.Y);
                var demandPattern = x.DemandPattern;
                if (string.IsNullOrEmpty(demandPattern) || demandPattern == ";" || demandPattern == "_")
                {
                    demandPattern = string.Empty;
                }
                junctionStringBuilder.AppendLine($"{x.Id}\t{x.Elev}\t{x.Demand}\t{demandPattern}\t;\t" + $"0\tJunction");
                coorStringBuilder.AppendLine(x.Id + "    " + x.Position.X + "    " + x.Position.Y);
            });
            string junctionString = junctionStringBuilder.ToString();
            StringBuilder reservoirStringBuilder = new StringBuilder();
            reservoirStringBuilder.AppendLine(";ID                 Head           Pattern ");
            net.Reservoirs.ForEach(o =>
            network.GetAllCouplings()?.ForEach(x =>
            {
                reservoirStringBuilder.AppendLine($"{o.Id}\t{o.Head}\t{o.HeadPattern}\t;\t" + $"0\t{o.PoolElev}");
                coorStringBuilder.AppendLine(o.Id + "    " + o.Position.X + "    " + o.Position.Y);
                var demandPattern = x.DemandPattern;
                if (string.IsNullOrEmpty(demandPattern) || demandPattern == ";" || demandPattern == "_")
                {
                    demandPattern = string.Empty;
                }
                junctionStringBuilder.AppendLine($"{x.Id}\t{x.Elev}\t{x.Demand}\t{demandPattern}\t;\t" + $"0\tCoupling");
                coorStringBuilder.AppendLine(x.Id + "    " + x.Position.X + "    " + x.Position.Y);
            });
            string reserverString = reservoirStringBuilder.ToString();
            StringBuilder tankStringBuilder = new StringBuilder();
            tankStringBuilder.AppendLine(";ID                 Elevation      InitLevel      MinLevel       MaxLevel       Diameter       MinVol         VolCurve           Overflow");
            net.Tanks.ForEach(o =>
            network.GetAllInstruments()?.ForEach(x =>
            {
                var demandPattern = x.DemandPattern;
                if (string.IsNullOrEmpty(demandPattern) || demandPattern == ";" || demandPattern == "_")
                {
                    demandPattern = string.Empty;
                }
                junctionStringBuilder.AppendLine($"{x.Id}\t{x.Elev}\t{x.Demand}\t{demandPattern}\t;\t" + $"0\tInstrument");
                coorStringBuilder.AppendLine(x.Id + "    " + x.Position.X + "    " + x.Position.Y);
            });
            //水表处理
            network.Meters?.ForEach(x =>
            {
                var demandPattern = x.DemandPattern;
                if (string.IsNullOrEmpty(demandPattern) || demandPattern == ";" || demandPattern == "_")
                {
                    demandPattern = "";
                }
                junctionStringBuilder.AppendLine($"{x.Id}\t{x.Elev}\t{x.Demand}\t{demandPattern}\t;\t" + $"0\tMeters");
                coorStringBuilder.AppendLine(x.Id + "    " + x.Position.X + "    " + x.Position.Y);
            });
            //喷头处理
            network.Nozzles?.ForEach(x =>
            {
                var demandPattern = x.DemandPattern;
                if (string.IsNullOrEmpty(demandPattern) || demandPattern == ";" || demandPattern == "_")
                {
                    demandPattern = "";
                }
                junctionStringBuilder.AppendLine($"{x.Id}\t{x.Elev}\t{x.Demand}\t{demandPattern}\t;\t" + $"0\tNozzle\t{x.Coefficient}");
                double coefficient = x.Coefficient * Math.Pow(10 / 101.972, 0.5) / 1000 * 60;
                emitterSb.AppendLine(x.Id + "    " + coefficient);
                coorStringBuilder.AppendLine(x.Id + "    " + x.Position.X + "    " + x.Position.Y);
            });
            var junctionString = junctionStringBuilder.ToString();
            //水库处理
            var reservoirSb = new StringBuilder();
            reservoirSb.AppendLine(";ID                 Head           Pattern ");
            network.Reservoirs?.ForEach(x =>
            {
                reservoirSb.AppendLine($"{x.Id}\t{x.Head}\t{x.HeadPattern}\t;\t" + $"0\t{x.PoolElev}");
                coorStringBuilder.AppendLine(x.Id + "    " + x.Position.X + "    " + x.Position.Y);
            });
            string reserverString = reservoirSb.ToString();
            //水池处理
            var tankSb = new StringBuilder();
            tankSb.AppendLine(";ID                 Elevation      InitLevel      MinLevel       MaxLevel       Diameter       MinVol         VolCurve           Overflow");
            network.GetTanks()?.ForEach(o =>
            {
                // tankStringBuilder.AppendLine($"{o.Id}\t{o.PoolElev}\t{o.InitLevel}\t{o.MinLevel}\t{o.MaxLevel}\t{o.Diameter}\t{o.MinVol}\t{o.VolCurve}\t{o.Overflow}\t;\t");// + $"0");
                tankStringBuilder.AppendLine($"{o.Id}\t{o.PoolElev}\t{o.InitLevel}\t{o.MinLevel}\t{o.MaxLevel}\t{o.Diameter}\t{o.MinVol}\t{o.VolCurve}\t;\t");// + $"0");
                tankSb.AppendLine($"{o.Id}\t{o.PoolElev}\t{o.InitLevel}\t{o.MinLevel}\t{o.MaxLevel}\t{o.Diameter}\t{o.MinVol}\t{o.VolCurve}\t;\t");// + $"0");
                coorStringBuilder.AppendLine(o.Id + "    " + o.Position.X + "    " + o.Position.Y);
            });
            string tankString = tankStringBuilder.ToString();
            string tankString = tankSb.ToString();
            StringBuilder pipeStringBuilder = new StringBuilder();
            pipeStringBuilder.AppendLine(";ID                 Node1              Node2              Length         Diameter       Roughness      MinorLoss      Status");
            net.Pipes.ForEach(o =>
            //管道处理
            var pipeSb = new StringBuilder();
            pipeSb.AppendLine(";ID                 Node1              Node2              Length         Diameter       Roughness      MinorLoss      Status");
            network.GetAllPipes()?.ForEach(x =>
            {
                if (o.Roughness == 0) o.Roughness = 110;
                string statusString = o.LinkStatus == PipeStatus.Closed ? "CLOSED" : "";
                double MinorLoss = o.MinorLoss;
                if (minorResult!=null && minorResult.LinkDict.TryGetValue(o.Id,out ICalcuLink minorlossCalc))
                if (x.Roughness == 0)
                {
                    MinorLoss += minorlossCalc.MinorlossCoff;
                    x.Roughness = 110;
                }
                pipeStringBuilder.AppendLine($"{o.Id}\t{o.StartNode.Id}\t{o.EndNode.Id}\t{o.Length}\t{o.Diameter}\t{o.Roughness}\t{MinorLoss}\t{statusString}\t;\t");// + $"{p.Level}");
                if (o.LinkStatus != PipeStatus.Open)
                string statusString = x.LinkStatus == PipeStatus.Closed ? "CLOSED" : "";
                pipeSb.AppendLine($"{x.Id}\t{x.StartNode.Id}\t{x.EndNode.Id}\t{x.Length}\t{x.Diameter}\t{x.Roughness}\t{x.MinorLoss}\t{statusString}\t;\t");// + $"{p.Level}");
                if (x.LinkStatus != PipeStatus.Open)
                {
                    statusStringBuilder.AppendLine(o.Id + "\t" + statusString);
                    statusSb.AppendLine(x.Id + "\t" + statusString);
                }
            });
            string pipeString = pipeSb.ToString();
            string pipeString = pipeStringBuilder.ToString();
            StringBuilder valveStringBuilder = new StringBuilder();
            valveStringBuilder.AppendLine(";ID                 Node1              Node2              Diameter       Type   Setting        MinorLoss  ");
            net.Valves.ForEach(o =>
            //阀门处理
            var valveSb = new StringBuilder();
            valveSb.AppendLine(";ID                 Node1              Node2              Diameter       Type   Setting        MinorLoss  ");
            network.Valves?.ForEach(x =>
            {
                valveStringBuilder.AppendLine($"{o.Id}\t{o.StartNode.Id}\t{o.EndNode.Id}\t{o.Diameter:F4}\t{o.ValveType}\t{o.ValveSetting}\t{o.MinorLoss:F4}\t;\t");// + $"0");
                if (!string.IsNullOrEmpty(o.LinkStatus))
                    statusStringBuilder.AppendLine(o.Id + "\t" + o.LinkStatus);
                valveSb.AppendLine($"{x.Id}\t{x.StartNode.Id}\t{x.EndNode.Id}\t{x.Diameter:F4}\t{x.ValveType}\t{x.ValveSetting}\t{x.MinorLoss:F4}\t;\t");// + $"0");
                if (!string.IsNullOrEmpty(x.LinkStatus))
                {
                    statusSb.AppendLine(x.Id + "\t" + x.LinkStatus);
                }
            });
            net.GetAllValveLikes().ForEach(o =>
            network.GetAllResistances()?.ForEach(x =>
            {
                string type= "";
                if (o is HeatExchanger) type = "HeatExchanger";
                if (o is AirCompressor) type = "AirCompressor";
                valveStringBuilder.AppendLine($"{o.Id}\t{o.StartNode.Id}\t{o.EndNode.Id}\t{o.Diameter:F4}\tGPV\t{o.FlowHeadLossCurve}\t{o.MinorLoss:F4}\t;\t{type}");// + $"0");
                if (!string.IsNullOrEmpty(o.LinkStatus))
                    statusStringBuilder.AppendLine(o.Id + "\t" + o.LinkStatus);
                string type = null;
                if (x is Exchanger)
                {
                    type = "Exchanger";
                }
                else if (x is Compressor)
                {
                    type = "Compressor";
                }
                valveSb.AppendLine($"{x.Id}\t{x.StartNode.Id}\t{x.EndNode.Id}\t{x.Diameter:F4}\tGPV\t{x.CurveQL}\t{x.MinorLoss:F4}\t;\t{type}");// + $"0");
                if (!string.IsNullOrEmpty(x.LinkStatus))
                {
                    statusSb.AppendLine(x.Id + "\t" + x.LinkStatus);
                }
            });
            string valveString = valveSb.ToString();
            string valveString = valveStringBuilder.ToString();
            StringBuilder pumpStringBuilder = new StringBuilder();
            pumpStringBuilder.AppendLine(";ID                 Node1              Node2              Parameters  ");
            net.Pumps.ForEach(o =>
            //水泵处理
            var pumpSb = new StringBuilder();
            pumpSb.AppendLine(";ID                 Node1              Node2              Parameters  ");
            network.Pumps?.ForEach(o =>
            {
                pumpStringBuilder.AppendLine($"{o.Id}\t{o.StartNode.Id}\t{o.EndNode.Id}\tHead\t{o.CurveQH}\t;\t");// + $"0");
                pumpSb.AppendLine($"{o.Id}\t{o.StartNode.Id}\t{o.EndNode.Id}\tHead\t{o.CurveQH}\t;\t");// + $"0");
                string statusString = null;
                if (o.LinkStatus == PipeStatus.Closed)
                {
@@ -169,17 +192,18 @@
                }
                else
                {
                    if (o.SpeedRatio == null)
                        statusString= "\tOPEN";
                    if (o.SpeedRatio == null)
                        statusString = "\tOPEN";
                    else
                        statusString = $"\t{o.SpeedRatio}";
                }
                statusStringBuilder.AppendLine(o.Id + statusString);
                statusSb.AppendLine(o.Id + statusString);
            });
            string pumpString = pumpStringBuilder.ToString();
            StringBuilder curveStringBuilder = new StringBuilder();
            curveStringBuilder.AppendLine(@";ID                 X-Value        Y-Value
            string pumpString = pumpSb.ToString();
            //曲线处理
            var curveSb = new StringBuilder();
            curveSb.AppendLine(@";ID                 X-Value        Y-Value
                                            ;HEADLOSS: 
                                             GPVDefault         0              0     
                                             GPVDefault         100            0           
@@ -212,22 +236,22 @@
                                             PumpDefault        750            31.44       
                                             PumpDefault        777.7777778    30.37       
                                             PumpDefault        805.5555556    29.27    ");
            net.Curves.ForEach(o =>
            network.Curves?.ForEach(o =>
            {
                var curvePtList = o.CurveData?.OrderBy(x => x.X).ToList();
                foreach (var curvePt in curvePtList)
                {
                    curveStringBuilder.AppendLine($"{o.Id}  {curvePt.X} {curvePt.Y}");
                    curveSb.AppendLine($"{o.Id}  {curvePt.X} {curvePt.Y}");
                }
                //curveStringBuilder.AppendLine(o.ToString());
            });
            string curveString = curveStringBuilder.ToString();
            string curveString = curveSb.ToString();
            string coorString = coorStringBuilder.ToString();
            string output = "";
            string emitterString = emitterStringBuilder.ToString();
            string statusString = statusStringBuilder.ToString();
            output = tempString;
            string emitterString = emitterSb.ToString();
            string statusString = statusSb.ToString();
            output = templateString;
            output = ReplaceContent(output, "JUNCTIONS", junctionString);
            output = ReplaceContent(output, "RESERVOIRS", reserverString);
            output = ReplaceContent(output, "TANKS", tankString);
@@ -279,18 +303,17 @@
            return replacedText;
        }
        /// <summary>
        /// 从Inp字符串中解析
        /// </summary>
        /// <param name="inpString">inp字符串</param>
        /// <returns></returns>
        public static Network FromInpString(string inpString)
        {
            string InpPath = inpString;
            var net = new Network();
            if (InpPath == null || !File.Exists(InpPath)) return null;
            List<InpCoor> points = new List<InpCoor>();
            StreamReader sr = new StreamReader(InpPath);
            //try
            {
@@ -432,10 +455,8 @@
                                break;
                            case "VALVES":
                                {
                                    if (parts[-2] == "HeatExchanger")
                                    if (parts[-2] == "Exchanger")
                                    {
                                        InpHeatExchanger valve = new InpHeatExchanger();
                                        valve.Id = parts[0];
@@ -447,14 +468,14 @@
                                        float diameter;
                                        if (float.TryParse(parts[3], out diameter))
                                            valve.Diameter = diameter;
                                        valve.FlowHeadLossCurve = parts[5];
                                        valve.CurveQL = parts[5];
                                        float minorLoss;
                                        if (float.TryParse(parts[6], out minorLoss))
                                            valve.MinorLoss = minorLoss;
                                        net.HeatExchangers.Add(valve);
                                        net.Exchangers.Add(valve);
                                    }
                                    else if (parts[-2] == "AirCompressor")
                                    else if (parts[-2] == "Compressor")
                                    {
                                        InpAirCompressor valve = new InpAirCompressor();
                                        valve.Id = parts[0];
@@ -466,12 +487,12 @@
                                        float diameter;
                                        if (float.TryParse(parts[3], out diameter))
                                            valve.Diameter = diameter;
                                        valve.FlowHeadLossCurve = parts[5];
                                        valve.CurveQL = parts[5];
                                        float minorLoss;
                                        if (float.TryParse(parts[6], out minorLoss))
                                            valve.MinorLoss = minorLoss;
                                        net.AirCompressors.Add(valve);
                                        net.Compressors.Add(valve);
                                    }
                                    else
                                    {
@@ -553,7 +574,7 @@
                    J.Position = new Position2d();
                    J.Position.X = coor.Position.X;
                    J.Position.Y = coor.Position.Y;
                    k1++;
                }
                #endregion
@@ -581,7 +602,7 @@
                        //throw new Exception($"未找到Link[{p.Id}]的起始节点[{((IInpParser)p).Node1}]");
                    }
                    p.StartNode = J;
                    if (J.Links == null) J.Links = new List<ILink>();
                    if (J.Links == null) J.Links = new List<Link>();
                    J.Links.Add(p);
                    k2++;
                }
@@ -606,7 +627,7 @@
                        //throw new Exception($"未找到Link[{p.Id}]的终止节点[{((IInpParser)p).Node2}]");
                    }
                    p.EndNode = J;
                    if (J.Links == null) J.Links = new List<ILink>();
                    if (J.Links == null) J.Links = new List<Link>();
                    J.Links.Add(p);
                    k2++;
                }