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)
        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>() {
@@ -43,107 +43,167 @@
                {"{coor}","{6}" },
                {"{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}");
                emitterStringBuilder.Append(o.Id + "    " + o.Coefficient);
                coorStringBuilder.AppendLine(o.Id + "    " + o.Position.X + "    " + o.Position.Y);
            });
            string junctionString = junctionStringBuilder.ToString();
            StringBuilder reservoirStringBuilder = new StringBuilder();
            reservoirStringBuilder.AppendLine(";ID                 Head           Pattern ");
            net.Reservoirs.ForEach(o =>
            {
                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);
            });
            string reserverString = reservoirStringBuilder.ToString();
            StringBuilder tankStringBuilder = new StringBuilder();
            tankStringBuilder.AppendLine(";ID                 Elevation      InitLevel      MinLevel       MaxLevel       Diameter       MinVol         VolCurve           Overflow");
            net.Tanks.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");
                coorStringBuilder.AppendLine(o.Id + "    " + o.Position.X + "    " + o.Position.Y);
            });
            string tankString = tankStringBuilder.ToString();
            StringBuilder pipeStringBuilder = new StringBuilder();
            pipeStringBuilder.AppendLine(";ID                 Node1              Node2              Length         Diameter       Roughness      MinorLoss      Status");
            net.Pipes.ForEach(o =>
            {
                if (o.Roughness == 0) o.Roughness = 110;
                string statusString = o.LinkStatus == PipeStatus.Closed ? "CLOSED" : "";
                pipeStringBuilder.AppendLine($"{o.Id}\t{o.StartNode.Id}\t{o.EndNode.Id}\t{o.Length}\t{o.Diameter}\t{o.Roughness}\t{o.MinorLoss}\t{statusString}\t;\t");// + $"{p.Level}");
                if (o.LinkStatus != PipeStatus.Open)
                var demandPattern = x.DemandPattern;
                if (string.IsNullOrEmpty(demandPattern) || demandPattern == ";" || demandPattern == "_")
                {
                    statusStringBuilder.AppendLine(o.Id + "\t" + statusString);
                    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);
            });
            network.GetAllCouplings()?.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\tCoupling");
                coorStringBuilder.AppendLine(x.Id + "    " + x.Position.X + "    " + x.Position.Y);
            });
            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");
                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 = tankSb.ToString();
            //管道处理
            var pipeSb = new StringBuilder();
            pipeSb.AppendLine(";ID                 Node1              Node2              Length         Diameter       Roughness      MinorLoss      Status");
            network.GetAllPipes()?.ForEach(x =>
            {
                if (x.Roughness == 0)
                {
                    x.Roughness = 110;
                }
                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)
                {
                    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);
                }
            });
            string valveString = valveStringBuilder.ToString();
            StringBuilder pumpStringBuilder = new StringBuilder();
            pumpStringBuilder.AppendLine(";ID                 Node1              Node2              Diameter       Type   Setting        MinorLoss  ");
            net.Pumps.ForEach(o =>
            network.GetAllResistances()?.ForEach(x =>
            {
                pumpStringBuilder.AppendLine($"{o.Id}\t{o.StartNode.Id}\t{o.EndNode.Id}\tHead\t{o.CurveQH}\tSPEED\t{o.SpeedRatio}\t;\t");// + $"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 pumpString = pumpStringBuilder.ToString();
            StringBuilder curveStringBuilder = new StringBuilder();
            curveStringBuilder.AppendLine(@";ID                 X-Value        Y-Value
            string valveString = valveSb.ToString();
            //水泵处理
            var pumpSb = new StringBuilder();
            pumpSb.AppendLine(";ID                 Node1              Node2              Parameters  ");
            network.Pumps?.ForEach(o =>
            {
                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)
                {
                    statusString = "\tCLOSED";
                }
                else
                {
                    if (o.SpeedRatio == null)
                        statusString = "\tOPEN";
                    else
                        statusString = $"\t{o.SpeedRatio}";
                }
                statusSb.AppendLine(o.Id + statusString);
            });
            string pumpString = pumpSb.ToString();
            //曲线处理
            var curveSb = new StringBuilder();
            curveSb.AppendLine(@";ID                 X-Value        Y-Value
                                            ;HEADLOSS: 
                                             GPVDefault         0              0     
                                             GPVDefault         100            0           
@@ -176,17 +236,22 @@
                                             PumpDefault        750            31.44       
                                             PumpDefault        777.7777778    30.37       
                                             PumpDefault        805.5555556    29.27    ");
            net.Curves.ForEach(o =>
            network.Curves?.ForEach(o =>
            {
                curveStringBuilder.AppendLine(o.ToString());
                var curvePtList = o.CurveData?.OrderBy(x => x.X).ToList();
                foreach (var curvePt in curvePtList)
                {
                    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);
@@ -238,17 +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
            {
@@ -265,7 +330,7 @@
                        string s = line.Trim('\t').Trim(' ');
                        if (s.Length == 0 || s[0] == ';') continue;
                        line = line.Replace("\t\t", "\t_\t").Replace("\t \t", "\t_\t");
                        Parts parts = new Parts(line.Split(new char[] { '\t', ' ', ';' }, StringSplitOptions.RemoveEmptyEntries));
                        InpParts parts = new InpParts(line.Split(new char[] { '\t', ' ', ';' }, StringSplitOptions.RemoveEmptyEntries));
                        switch (section)
                        {
                            case "JUNCTIONS":
@@ -282,7 +347,7 @@
                                    int.TryParse(parts[6], out level);
                                    var Level = level;
                                    if (parts[5] == "Meter")
                                    if (parts[-2] == "Meter")
                                    {
                                        net.Meters.Add(new Meter()
                                        {
@@ -292,7 +357,7 @@
                                            DemandPattern = PatternID,
                                        });
                                    }
                                    else if (parts[5] == "Nozzle")
                                    else if (parts[-2] == "Nozzle")
                                    {
                                        net.Nozzles.Add(new Nozzle()
                                        {
@@ -390,23 +455,65 @@
                                break;
                            case "VALVES":
                                {
                                    InpValve valve = new InpValve();
                                    valve.Id = parts[0];
                                    // 取出Node1和Node2中的字母部分,例如“S201326593”被取出为“201326593”
                                    valve.Node1 = parts[1]; // Regex.Replace(parts[1], "[^0-9]", "");
                                    valve.Node2 = parts[2]; // Regex.Replace(parts[2], "[^0-9]", "");
                                    if (parts[-2] == "Exchanger")
                                    {
                                        InpHeatExchanger valve = new InpHeatExchanger();
                                        valve.Id = parts[0];
                                    float diameter;
                                    if (float.TryParse(parts[3], out diameter))
                                        valve.Diameter = diameter;
                                    valve.ValveType = parts[4];
                                    valve.ValveSetting = parts[5];
                                    float minorLoss;
                                    if (float.TryParse(parts[6], out minorLoss))
                                        valve.MinorLoss = minorLoss;
                                        // 取出Node1和Node2中的字母部分,例如“S201326593”被取出为“201326593”
                                        valve.Node1 = parts[1]; // Regex.Replace(parts[1], "[^0-9]", "");
                                        valve.Node2 = parts[2]; // Regex.Replace(parts[2], "[^0-9]", "");
                                    net.Valves.Add(valve);
                                        float diameter;
                                        if (float.TryParse(parts[3], out diameter))
                                            valve.Diameter = diameter;
                                        valve.CurveQL = parts[5];
                                        float minorLoss;
                                        if (float.TryParse(parts[6], out minorLoss))
                                            valve.MinorLoss = minorLoss;
                                        net.Exchangers.Add(valve);
                                    }
                                    else if (parts[-2] == "Compressor")
                                    {
                                        InpAirCompressor valve = new InpAirCompressor();
                                        valve.Id = parts[0];
                                        // 取出Node1和Node2中的字母部分,例如“S201326593”被取出为“201326593”
                                        valve.Node1 = parts[1]; // Regex.Replace(parts[1], "[^0-9]", "");
                                        valve.Node2 = parts[2]; // Regex.Replace(parts[2], "[^0-9]", "");
                                        float diameter;
                                        if (float.TryParse(parts[3], out diameter))
                                            valve.Diameter = diameter;
                                        valve.CurveQL = parts[5];
                                        float minorLoss;
                                        if (float.TryParse(parts[6], out minorLoss))
                                            valve.MinorLoss = minorLoss;
                                        net.Compressors.Add(valve);
                                    }
                                    else
                                    {
                                        InpValve valve = new InpValve();
                                        valve.Id = parts[0];
                                        // 取出Node1和Node2中的字母部分,例如“S201326593”被取出为“201326593”
                                        valve.Node1 = parts[1]; // Regex.Replace(parts[1], "[^0-9]", "");
                                        valve.Node2 = parts[2]; // Regex.Replace(parts[2], "[^0-9]", "");
                                        float diameter;
                                        if (float.TryParse(parts[3], out diameter))
                                            valve.Diameter = diameter;
                                        valve.ValveType = parts[4];
                                        valve.ValveSetting = parts[5];
                                        float minorLoss;
                                        if (float.TryParse(parts[6], out minorLoss))
                                            valve.MinorLoss = minorLoss;
                                        net.Valves.Add(valve);
                                    }
                                }
                                break;
@@ -418,6 +525,16 @@
                                    if (double.TryParse(parts[1], out x) && double.TryParse(parts[2], out y))
                                    {
                                        points.Add(new InpCoor(id, new Position2d(x, y)));
                                    }
                                }
                                break;
                            case "EMITTERS":
                                {
                                    string id = parts[0];
                                    if (double.TryParse(parts[1], out double x))
                                    {
                                        double Coefficient = x / Math.Pow(10 / 101.972, 0.5) * 1000 / 60;
                                        net.Nozzles.Find(o => o.Id == id).Coefficient = Coefficient;
                                    }
                                }
                                break;
@@ -457,7 +574,7 @@
                    J.Position = new Position2d();
                    J.Position.X = coor.Position.X;
                    J.Position.Y = coor.Position.Y;
                    k1++;
                }
                #endregion
@@ -485,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++;
                }
@@ -510,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++;
                }