using Hydro.Core.Model;
|
//using Hydro.HydraulicModel;
|
using System;
|
using System.Collections.Generic;
|
using System.Data;
|
using System.Drawing;
|
using System.IO;
|
using System.IO.Ports;
|
using System.Linq;
|
using System.Text;
|
using System.Text.RegularExpressions;
|
using System.Threading;
|
using System.Threading.Tasks;
|
using System.Xml.Linq;
|
using static Hydro.Core.EpanetEnum;
|
using static Hydro.Core.ObjectEnum;
|
|
namespace Hydro.Inp
|
{
|
public class NetWork //: INetWork
|
{
|
public NetWork()
|
{
|
}
|
|
public List<JunctionModel> Junctions
|
{
|
get
|
{
|
var js = Nodes.Where(d => d is JunctionModel);
|
return js?.Select(d => d as JunctionModel).ToList();
|
}
|
|
}
|
public List<TankModel> Tanks
|
{
|
get
|
{
|
var js = Nodes.Where(d => d is TankModel);
|
return js?.Select(d => d as TankModel).ToList();
|
}
|
}
|
|
public List<PipeModel> Pipes
|
{
|
get
|
{
|
var js = Links.Where(d => d is PipeModel);
|
return js?.Select(d => d as PipeModel).ToList();
|
}
|
}
|
|
public List<PumpModel> Pumps
|
{
|
get
|
{
|
var js = Links.Where(d => d is PumpModel);
|
return js?.Select(d => d as PumpModel).ToList();
|
}
|
}
|
|
public List<ValveModel> Valves
|
{
|
get
|
{
|
var js = Links.Where(d => d is ValveModel);
|
return js?.Select(d => d as ValveModel).ToList();
|
}
|
}
|
|
public List<ReservoisModel> Reservos
|
{
|
get
|
{
|
var js = Nodes.Where(d => d is ReservoisModel);
|
return js?.Select(d => d as ReservoisModel).ToList();
|
}
|
}
|
|
public List<MeterModel> Meters
|
{
|
get
|
{
|
var js = Nodes.Where(d => d is MeterModel);
|
return js?.Select(d => d as MeterModel).ToList();
|
}
|
}
|
|
public List<NozzleModel> Nozzles
|
{
|
get
|
{
|
var js = Nodes.Where(d => d is NozzleModel);
|
return js?.Select(d => d as NozzleModel).ToList();
|
}
|
}
|
|
public virtual void AddJunction(JunctionModel junction)
|
{
|
CheckNodesExist(junction);
|
Nodes.Add(junction);
|
}
|
|
public virtual void AddJunctions(List<JunctionModel> junctions)
|
{
|
junctions.ForEach(junction => { AddJunction(junction); });
|
}
|
|
public virtual void AddTank(TankModel tank)
|
{
|
CheckNodesExist(tank);
|
Nodes.Add(tank);
|
}
|
|
public virtual void AddTanks(List<TankModel> tanks)
|
{
|
tanks.ForEach(tank => { AddTank(tank); });
|
}
|
|
public virtual void AddPipe(PipeModel pipe)
|
{
|
CheckLinksExist(pipe);
|
Links.Add(pipe);
|
}
|
|
public virtual void AddPipes(List<PipeModel> pipes)
|
{
|
pipes.ForEach(pipe => { AddPipe(pipe); });
|
}
|
public virtual void AddPump(PumpModel pump)
|
{
|
CheckLinksExist(pump);
|
Links.Add(pump);
|
}
|
|
public virtual void AddPumps(List<PumpModel> pumps)
|
{
|
pumps.ForEach(pump => { AddPump(pump); });
|
}
|
public virtual void AddValve(ValveModel valve)
|
{
|
CheckLinksExist(valve);
|
Links.Add(valve);
|
}
|
|
public virtual void AddValves(List<ValveModel> valves)
|
{
|
valves.ForEach(valve => { AddValve(valve); });
|
}
|
public virtual void AddReservos(ReservoisModel reservois)
|
{
|
CheckNodesExist(reservois);
|
Nodes.Add(reservois);
|
}
|
public virtual void AddReservoss(List<ReservoisModel> reservoiss)
|
{
|
reservoiss.ForEach(reservois => { AddReservos(reservois); });
|
}
|
public virtual void AddMeter(MeterModel meter)
|
{
|
CheckNodesExist(meter);
|
Nodes.Add(meter);
|
}
|
public virtual void AddMeters(List<MeterModel> meters)
|
{
|
meters.ForEach(meter => { AddMeter(meter); });
|
}
|
public virtual void AddNozzle(NozzleModel nozzle)
|
{
|
CheckNodesExist(nozzle);
|
Nodes.Add(nozzle);
|
}
|
public virtual void AddNozzles(List<NozzleModel> nozzles)
|
{
|
nozzles.ForEach(nozzle => { AddNozzle(nozzle); });
|
}
|
|
private void CheckNodesExist(NodeModel node)
|
{
|
if (Nodes.Any(d => d.ID == node.ID))
|
throw new Exception("已存在重复的对象");
|
}
|
|
private void CheckLinksExist(LinkModel link)
|
{
|
if (Links.Any(d => d.ID == link.ID))
|
throw new Exception("已存在重复的对象");
|
}
|
|
public List<NodeModel> Nodes { get; set; } = new List<NodeModel>();
|
public List<LinkModel> Links { get; set; } = new List<LinkModel>();
|
|
/// <summary>
|
/// 根据INP文件生成
|
/// </summary>
|
/// <param name="InpPath"></param>
|
/// <returns></returns>
|
public virtual bool BuildFromInp(string InpPath)
|
{
|
if (InpPath == null || !File.Exists(InpPath)) return false;
|
List<Coor> points = new List<Coor>();
|
StreamReader sr = new StreamReader(InpPath);
|
//try
|
{
|
string line;
|
string section = "";
|
while ((line = sr.ReadLine()) != null)
|
{
|
if (line.Trim().StartsWith("["))
|
{
|
section = line.TrimStart('[').TrimEnd(']');
|
}
|
else
|
{
|
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));
|
switch (section)
|
{
|
case "JUNCTIONS":
|
{
|
var ID = parts[0];
|
float elev;
|
float.TryParse(parts[1], out elev);
|
var Elev = elev;
|
float demand;
|
float.TryParse(parts[2], out demand);
|
var Demand = demand;
|
var PatternID = parts[3];
|
int level;
|
int.TryParse(parts[6], out level);
|
var Level = level;
|
|
if (parts[5] == "Meter")
|
{
|
AddMeter(new MeterModel()
|
{
|
ID = ID,
|
Elev = Elev,
|
Demand = Demand,
|
PatternID = PatternID,
|
});
|
}
|
else if (parts[5] == "Nozzle")
|
{
|
AddNozzle(new NozzleModel()
|
{
|
ID = ID,
|
Elev = Elev,
|
Demand = Demand,
|
PatternID = PatternID,
|
});
|
}
|
else
|
{
|
AddJunction(new JunctionModel()
|
{
|
ID = ID,
|
Elev = Elev,
|
Demand = Demand,
|
PatternID = PatternID,
|
});
|
}
|
|
}
|
break;
|
case "RESERVOIRS":
|
{
|
ReservoisModel r = new ReservoisModel();
|
r.ID = parts[0];
|
float head;
|
if (float.TryParse(parts[1], out head))
|
r.Head = head;
|
r.PatternID = parts.Length > 2 ? parts[2] : "";
|
int level;
|
//if (int.TryParse(parts[3], out level))
|
// r.Level = level;
|
AddReservos(r);
|
}
|
break;
|
case "TANKS":
|
{
|
//TankModel tank = new TankModel(parts[0], parts[1], parts[2], parts[3], parts[4], parts[5], parts[6], parts[7], parts[8]);
|
float initLevel = 0;
|
float.TryParse(parts[2], out initLevel);
|
|
float minLevel = 0;
|
float.TryParse(parts[3], out minLevel);
|
|
float maxLevel = 0;
|
float.TryParse(parts[4], out maxLevel);
|
|
float diamter = 0;
|
float.TryParse(parts[5], out diamter);
|
|
float minVol = 0;
|
float.TryParse(parts[6], out minVol);
|
var tank = new TankModel()
|
{
|
ID = parts[0],
|
Elev = float.Parse(parts[1]),
|
InitLevel = initLevel,
|
MinLevel = minLevel,
|
MaxLevel = maxLevel,
|
Diameter = diamter,
|
MinVol = minVol,
|
VolCurve = "",
|
IsOverFlow = true
|
};
|
//int level;
|
//if (int.TryParse(parts[9], out level))
|
// tank.Level = level;
|
AddTank(tank);
|
}
|
break;
|
case "PIPES":
|
{
|
PipeModel p = new PipeModel();
|
p.ID = parts[0];
|
p.Node1 = parts[1];
|
p.Node2 = parts[2];
|
float length;
|
if (float.TryParse(parts[3], out length))
|
p.Length = length;
|
float diameter;
|
if (float.TryParse(parts[4], out diameter))
|
p.Diameter = diameter;
|
float roughness;
|
if (float.TryParse(parts[5], out roughness))
|
p.Roughness = roughness;
|
float minorLoss;
|
if (float.TryParse(parts[6], out minorLoss))
|
p.MinorLoss = minorLoss;
|
p.Status = parts.Length > 7 ? StatusType.CLOSED : StatusType.DEFAULT;
|
//int level;
|
//if (int.TryParse(parts[8], out level))
|
// p.Level = level;
|
AddPipe(p);
|
}
|
break;
|
case "VALVES":
|
{
|
ValveModel valve = new ValveModel();
|
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.Type = parts[4];
|
valve.CurvSetting = parts[5];
|
float minorLoss;
|
if (float.TryParse(parts[6], out minorLoss))
|
valve.MinorLoss = minorLoss;
|
//int level;
|
//if (int.TryParse(parts[7], out level))
|
// valve.Level = level;
|
AddValve(valve);
|
}
|
break;
|
case "REPEATERS":
|
{
|
//Repeater repeater = new Repeater();
|
//repeater.ID = parts[0];
|
//repeater.Node1 = parts[1];
|
//repeater.Node2 = parts[2];
|
//// 取出Node1和Node2中的字母部分,例如“S201326593”被取出为“201326593”
|
//repeater.TemplateID = parts[3];
|
//int repeatTimes;
|
//if (int.TryParse(parts[4], out repeatTimes))
|
// repeater.RepeatTimes = repeatTimes;
|
//RepeatStatus status;
|
//if (Enum.TryParse(parts[5], out status))
|
// repeater.Status = status;
|
//repeater.NetworkPreName = parts[6];
|
//int networkPreStartNum;
|
//if (int.TryParse(parts[7], out networkPreStartNum))
|
// repeater.NetworkPreStartNum = networkPreStartNum;
|
//bool networkIsAscNum;
|
//if (bool.TryParse(parts[8], out networkIsAscNum))
|
// repeater.NetworkIsAscNum = networkIsAscNum;
|
//repeater.NetworkShowName = parts[9];
|
//int level;
|
//if (int.TryParse(parts[10], out level))
|
// repeater.Level = level;
|
//Links.Add(repeater);
|
}
|
break;
|
case "COORDINATES":
|
{
|
string id = parts[0];
|
float x;
|
float y;
|
if (float.TryParse(parts[1], out x) && float.TryParse(parts[2], out y))
|
{
|
points.Add(new Coor(id, new PointF(x, y)));
|
}
|
}
|
break;
|
}
|
}
|
}
|
sr.Close();
|
|
#region 坐标匹配方法
|
#endregion
|
|
#region 删除
|
//[Cloudflight修改]2023-11-27 二重循环匹配坐标速度太慢
|
////读取坐标
|
//Junctions.ForEach(o =>
|
//{
|
// var p = points.Where(d => d.ID == o.ID).FirstOrDefault();
|
// if (p != null)
|
// {
|
// o.X = p.Position.X;
|
// o.Y = p.Position.Y;
|
// }
|
//});
|
|
//Reservos.ForEach(o =>
|
//{
|
// var p = points.Where(d => d.ID == o.ID).FirstOrDefault();
|
// if (p != null)
|
// {
|
// o.X = p.Position.X;
|
// o.Y = p.Position.Y;
|
// }
|
//});
|
|
//Tanks.ForEach(o =>
|
//{
|
// var p = points.Where(d => d.ID == o.ID).FirstOrDefault();
|
// if (p != null)
|
// {
|
// o.X = p.Position.X;
|
// o.Y = p.Position.Y;
|
// }
|
//});
|
|
//Meters.ForEach(o =>
|
//{
|
// var p = points.Where(d => d.ID == o.ID).FirstOrDefault();
|
// if (p != null)
|
// {
|
// o.X = p.Position.X;
|
// o.Y = p.Position.Y;
|
// }
|
//});
|
|
//Nozzles.ForEach(o =>
|
//{
|
// var p = points.Where(d => d.ID == o.ID).FirstOrDefault();
|
// if (p != null)
|
// {
|
// o.X = p.Position.X;
|
// o.Y = p.Position.Y;
|
// }
|
//});
|
#endregion
|
|
#region 优化方案
|
int k1 = 0;
|
int k2 = 0;
|
|
|
Nodes.Sort((a, b) => string.Compare(a.ID, b.ID));
|
points.Sort((a, b) => string.Compare(a.ID, b.ID));
|
k1 = 0;
|
k2 = 0;
|
while (k1 < Nodes.Count)
|
{
|
var J = Nodes[k1];
|
var coor = points[k2];
|
|
while (J.ID != coor.ID && k2 < points.Count)
|
{
|
k2++;
|
if (k2 < points.Count) coor = points[k2];
|
|
}
|
if (k2 == points.Count)
|
{
|
throw new Exception($"未找到Node[{J.ID}]的坐标");
|
}
|
J.X = coor.Position.X;
|
J.Y = coor.Position.Y;
|
|
k1++;
|
}
|
#endregion
|
|
|
|
//建立点线关系链表StartNode,先将管线以Node1(节点1的ID)排序,再将Nodes按ID排序,建立两个游标k1、k2,正向一次循环,建立链表关系
|
//时间复杂度 O(n)
|
Links.Sort((a, b) => string.Compare(a.Node1, b.Node1));
|
k1 = 0;
|
k2 = 0;
|
while (k2 < Links.Count)
|
{
|
var p = Links[k2];
|
var J = Nodes[k1];
|
while (J.ID != p.Node1 && k1 < Nodes.Count)
|
{
|
k1++;
|
if (k1 < Nodes.Count) J = Nodes[k1];
|
|
}
|
if (k1 == Nodes.Count)
|
{
|
throw new Exception($"未找到Link[{p.ID}]的起始节点[{p.Node1}]");
|
}
|
//p.StartNode = J;
|
//if (J.MaxDiameter < p.Diameter) J.MaxDiameter = p.Diameter;
|
//J.Links.Add(p);
|
k2++;
|
}
|
|
//建立点线关系链表StartNode,先将管线以Node2(节点1的ID)排序,再将Nodes按ID排序,建立两个游标k1、k2,正向一次循环,建立链表关系
|
//时间复杂度 O(n)
|
Links.Sort((a, b) => string.Compare(a.Node2, b.Node2));
|
k1 = 0;
|
k2 = 0;
|
while (k2 < Links.Count)
|
{
|
var p = Links[k2];
|
var J = Nodes[k1];
|
while (J.ID != p.Node2 && k1 < Nodes.Count)
|
{
|
k1++;
|
if (k1 < Nodes.Count) J = Nodes[k1];
|
}
|
if (k1 == Nodes.Count)
|
{
|
throw new Exception($"未找到Link[{p.ID}]的终止节点[{p.Node2}]");
|
}
|
//p.EndNode = J;
|
//if (J.MaxDiameter < p.Diameter) J.MaxDiameter = p.Diameter;
|
//J.Links.Add(p);
|
k2++;
|
}
|
return true;
|
}
|
}
|
|
/// <summary>
|
/// 生成INP文件
|
/// </summary>
|
/// <param name="InpPath">Inp文件路径</param>
|
/// <param name="TemplateInpFullPath">Inp模板文件绝对路径,如果为空就用系统默认模板文件</param>
|
/// <exception cref="Exception"></exception>
|
public virtual void BuildToInp(string InpPath, string TemplateInpFullPath = "", string sourcePath = null, bool isReplace = false)
|
{
|
|
string tempString = "";
|
var tempPath = Path.Combine(Directory.GetCurrentDirectory(), @"template\inp\导出模板.inp");
|
if (!string.IsNullOrEmpty(TemplateInpFullPath))
|
{
|
tempPath = TemplateInpFullPath;
|
}
|
if (!File.Exists(tempPath))
|
{
|
throw new Exception("模板文件不存在," + tempPath);
|
}
|
if (!File.Exists(InpPath))
|
File.Create(InpPath).Close();
|
tempString = File.ReadAllText(tempPath);
|
StringBuilder statusStringBuilder = new StringBuilder();
|
statusStringBuilder.AppendLine(";ID \tStatus/Setting\r\n");
|
|
StringBuilder emitterStringBuilder = new StringBuilder();
|
emitterStringBuilder.AppendLine(";Junction \tCoefficient");
|
|
StringBuilder coorStringBuilder = new StringBuilder();
|
coorStringBuilder.AppendLine(";Node X-Coord Y-Coord");
|
|
Dictionary<string, string> dictExchange = new Dictionary<string, string>() {
|
{"{junctions}","{0}" },
|
{"{reservoirs}","{1}" },
|
{"{tanks}","{2}" },
|
{"{pipes}","{3}" },
|
{"{valves}","{4}" },
|
{"{pumps}","{5}" },
|
|
{"{coor}","{6}" },
|
{"{curve}","{7}" },
|
};
|
dictExchange.ToList().ForEach(m => tempString = tempString.Replace(m.Key, m.Value));
|
|
StringBuilder junctionStringBuilder = new StringBuilder();
|
|
junctionStringBuilder.AppendLine(";ID Elev Demand Pattern Type");
|
|
Junctions.ForEach(j =>
|
{
|
junctionStringBuilder.AppendLine(j.ToString() + $"0\tJunction");
|
coorStringBuilder.AppendLine(j.ToCoorString());
|
|
});
|
Meters.ForEach(m =>
|
{
|
junctionStringBuilder.AppendLine(m.ToString() + $"0\tMeters");
|
coorStringBuilder.AppendLine(m.ToCoorString());
|
});
|
Nozzles.ForEach(no =>
|
{
|
junctionStringBuilder.AppendLine(no.ToString() + $"0\tNozzle\t{no.FlowCoefficient}");
|
emitterStringBuilder.Append(no.ToEmitterString());
|
coorStringBuilder.AppendLine(no.ToCoorString());
|
});
|
|
string junctionString = junctionStringBuilder.ToString();
|
|
StringBuilder reservoirStringBuilder = new StringBuilder();
|
|
reservoirStringBuilder.AppendLine(";ID Head Pattern ");
|
|
Reservos.ForEach(o =>
|
{
|
reservoirStringBuilder.AppendLine(o.ToString() + $"0\t{o.Elev}");
|
coorStringBuilder.AppendLine(o.ToCoorString());
|
});
|
string reserverString = reservoirStringBuilder.ToString();
|
|
StringBuilder tankStringBuilder = new StringBuilder();
|
|
tankStringBuilder.AppendLine(";ID Elevation InitLevel MinLevel MaxLevel Diameter MinVol VolCurve Overflow");
|
|
Tanks.ForEach(o =>
|
{
|
tankStringBuilder.AppendLine(o.ToString());// + $"0");
|
coorStringBuilder.AppendLine(o.ToCoorString());
|
});
|
string tankString = tankStringBuilder.ToString();
|
|
StringBuilder pipeStringBuilder = new StringBuilder();
|
|
pipeStringBuilder.AppendLine(";ID Node1 Node2 Length Diameter Roughness MinorLoss Status");
|
|
Pipes.ForEach(p =>
|
{
|
pipeStringBuilder.AppendLine(p.ToString());// + $"{p.Level}");
|
statusStringBuilder.Append(p.ToStatusString());
|
});
|
|
string pipeString = pipeStringBuilder.ToString();
|
|
StringBuilder valveStringBuilder = new StringBuilder();
|
|
valveStringBuilder.AppendLine(";ID Node1 Node2 Diameter Type Setting MinorLoss ");
|
|
Valves.ForEach(o =>
|
{
|
valveStringBuilder.AppendLine(o.ToString());// + $"0");
|
statusStringBuilder.Append(o.ToStatusString());
|
});
|
string valveString = valveStringBuilder.ToString();
|
|
StringBuilder pumpStringBuilder = new StringBuilder();
|
|
pumpStringBuilder.AppendLine(";ID Node1 Node2 Diameter Type Setting MinorLoss ");
|
|
Pumps.ForEach(o =>
|
{
|
pumpStringBuilder.AppendLine(o.ToString());// + $"0");
|
statusStringBuilder.Append(o.ToStatusString());
|
});
|
string pumpString = pumpStringBuilder.ToString();
|
StringBuilder curveStringBuilder = new StringBuilder();
|
curveStringBuilder.AppendLine(@";ID X-Value Y-Value
|
;HEADLOSS:
|
GPVDefault 0 0
|
GPVDefault 100 0
|
;PUMP:
|
PumpDefault 0 45.38
|
PumpDefault 83.33333333 45.25
|
PumpDefault 111.1111111 45.12
|
PumpDefault 138.8888889 44.96
|
PumpDefault 166.6666667 44.76
|
PumpDefault 194.4444444 44.52
|
PumpDefault 222.2222222 44.24
|
PumpDefault 250 43.92
|
PumpDefault 277.7777778 43.56
|
PumpDefault 305.5555556 43.17
|
PumpDefault 333.3333333 42.73
|
PumpDefault 361.1111111 42.25
|
PumpDefault 388.8888889 41.74
|
PumpDefault 416.6666667 41.18
|
PumpDefault 444.4444444 40.58
|
PumpDefault 472.2222222 39.95
|
PumpDefault 500 39.28
|
PumpDefault 527.7777778 38.56
|
PumpDefault 555.5555556 37.81
|
PumpDefault 583.3333333 37.02
|
PumpDefault 611.1111111 36.19
|
PumpDefault 638.8888889 35.32
|
PumpDefault 666.6666667 34.41
|
PumpDefault 694.4444444 33.46
|
PumpDefault 722.2222222 32.47
|
PumpDefault 750 31.44
|
PumpDefault 777.7777778 30.37
|
PumpDefault 805.5555556 29.27 ");
|
|
Pumps.ForEach(o =>
|
{
|
curveStringBuilder.AppendLine(o.CreateFlowCurve());
|
});
|
string curveString = curveStringBuilder.ToString();
|
string coorString = coorStringBuilder.ToString();
|
string output = "";
|
string emitterString = emitterStringBuilder.ToString();
|
string statusString = statusStringBuilder.ToString();
|
output = tempString;
|
output = ReplaceContent(output, "JUNCTIONS", junctionString);
|
output = ReplaceContent(output, "RESERVOIRS", reserverString);
|
output = ReplaceContent(output, "TANKS", tankString);
|
output = ReplaceContent(output, "PIPES", pipeString);
|
output = ReplaceContent(output, "VALVES", valveString);
|
output = ReplaceContent(output, "PUMPS", pumpString);
|
output = ReplaceContent(output, "CURVES", curveString);
|
output = ReplaceContent(output, "COORDINATES", coorString);
|
output = ReplaceContent(output, "EMITTERS", emitterString);
|
output = ReplaceContent(output, "STATUS", statusString);
|
string backupFolderPath = Path.Combine(Path.GetDirectoryName(InpPath), "bk");
|
if (!Directory.Exists(backupFolderPath))
|
Directory.CreateDirectory(backupFolderPath);
|
|
string backupFileName = $"{Path.GetFileNameWithoutExtension(InpPath)}_{DateTime.Now:yyyyMMddHHmmss}{Path.GetExtension(InpPath)}";
|
string backupFilePath = Path.Combine(backupFolderPath, backupFileName);
|
if (File.Exists(InpPath)) File.Copy(InpPath, backupFilePath, true);
|
|
//Global.ClearFileReadOnly(InpPath);
|
File.WriteAllText(InpPath, output);
|
}
|
//public void BuildToInp(string filePath, string userCoorString = null, string sourcePath = null, bool isReplace = false)
|
//{
|
|
// if (sourcePath == null) sourcePath = filePath;
|
|
// string tempString = "";
|
// if (!isReplace)
|
// {
|
// var tempPath = Path.Combine(Directory.GetCurrentDirectory(), @"template\inp\导出模板.inp");
|
// if (!File.Exists(tempPath))
|
// {
|
// //MessageBox.Show($"模板文件不存在[{tempPath}]");
|
// return;
|
// }
|
// tempString = File.ReadAllText(tempPath);
|
// }
|
// else
|
// {
|
// tempString = File.ReadAllText(sourcePath);
|
// }
|
|
|
// Dictionary<string, string> dictExchange = new Dictionary<string, string>() {
|
// {"{junctions}","{0}" },
|
// {"{reservoirs}","{1}" },
|
// {"{tanks}","{2}" },
|
// {"{pipes}","{3}" },
|
// {"{valves}","{4}" },
|
// {"{pumps}","{5}" },
|
|
// {"{coor}","{6}" },
|
// {"{curve}","{7}" },
|
// };
|
// dictExchange.ToList().ForEach(m => tempString = tempString.Replace(m.Key, m.Value));
|
|
// StringBuilder junctionStringBuilder = new StringBuilder();
|
|
// junctionStringBuilder.AppendLine(";ID Elev Demand Pattern Type");
|
|
// Nodes.ForEach(o =>
|
// {
|
// //if (!o.Visible) return;
|
// if (o is JunctionModel j)
|
// junctionStringBuilder.AppendLine(j.ToString() + $"0\tJunction");
|
// else if (o is MeterModel m)
|
// junctionStringBuilder.AppendLine(m.ToString() + $"0\tMeter");
|
// else if (o is NozzleModel no)
|
// junctionStringBuilder.AppendLine(no.ToString() + $"0\tNozzle\t{no.FlowCoefficient}");
|
// });
|
// string junctionString = junctionStringBuilder.ToString();
|
|
// StringBuilder reservoirStringBuilder = new StringBuilder();
|
|
// reservoirStringBuilder.AppendLine(";ID Head Pattern ");
|
|
// Reservos.ForEach(o =>
|
// {
|
// //if (!o.Visible) return;
|
// reservoirStringBuilder.AppendLine(o.ToString() + $"0\t{o.Elev}");
|
// });
|
// string reserverString = reservoirStringBuilder.ToString();
|
|
// StringBuilder tankStringBuilder = new StringBuilder();
|
|
// tankStringBuilder.AppendLine(";ID Elevation InitLevel MinLevel MaxLevel Diameter MinVol VolCurve Overflow");
|
|
// Tanks.ForEach(o =>
|
// {
|
// //if (!o.Visible) return;
|
// tankStringBuilder.AppendLine(o.ToString() + $"0");
|
// });
|
// string tankString = tankStringBuilder.ToString();
|
|
// StringBuilder pipeStringBuilder = new StringBuilder();
|
|
// pipeStringBuilder.AppendLine(";ID Node1 Node2 Length Diameter Roughness MinorLoss Status");
|
|
// Links.ForEach(o =>
|
// {
|
// //if (!o.Visible) return;
|
// if (o is PipeModel p)
|
// pipeStringBuilder.AppendLine(p.ToString() + $"0");
|
// //else if (o is RepeaterViewModel r)
|
// // pipeStringBuilder.AppendLine(r.ToString());
|
// });
|
// string pipeString = pipeStringBuilder.ToString();
|
|
// StringBuilder valveStringBuilder = new StringBuilder();
|
|
// valveStringBuilder.AppendLine(";ID Node1 Node2 Diameter Type Setting MinorLoss ");
|
|
// Valves.ForEach(o =>
|
// {
|
// //if (!o.Visible) return;
|
// valveStringBuilder.AppendLine(o.ToString() + $"0");
|
// });
|
// string valveString = valveStringBuilder.ToString();
|
|
// StringBuilder pumpStringBuilder = new StringBuilder();
|
|
// pumpStringBuilder.AppendLine(";ID Node1 Node2 Diameter Type Setting MinorLoss ");
|
|
// Pumps.ForEach(o =>
|
// {
|
// //if (!o.Visible) return;
|
// pumpStringBuilder.AppendLine(o.ToString() + $"0");
|
// });
|
// string pumpString = pumpStringBuilder.ToString();
|
|
|
// StringBuilder curveStringBuilder = new StringBuilder();
|
|
|
|
// //pumps.ForEach(o =>
|
// //{
|
// // if (!o.Visible || !o.Datasets.ContainsKey("流量扬程曲线")) return;
|
// // curveStringBuilder.AppendLine(o.Datasets["流量扬程曲线"].ToString());
|
// //});
|
// if (dict_dataset != null)
|
// foreach (var kp in dict_dataset)
|
// {
|
// curveStringBuilder.AppendLine(kp.Value.ToString());
|
// }
|
// string curveString = curveStringBuilder.ToString();
|
|
|
// StringBuilder coorStringBuilder = new StringBuilder();
|
// if (userCoorString == null)
|
// {
|
|
// coorStringBuilder.AppendLine(";Node X-Coord Y-Coord");
|
// Nodes.ForEach(o => coorStringBuilder.AppendLine(o.ToCoorString()));
|
// }
|
// else
|
// {
|
// coorStringBuilder.Append(userCoorString);
|
// }
|
|
|
|
// string coorString = coorStringBuilder.ToString();
|
// string output = "";
|
|
|
|
|
|
// StringBuilder emitterStringBuilder = new StringBuilder();
|
// emitterStringBuilder.AppendLine(";Junction \tCoefficient");
|
// Nodes.ForEach(o => emitterStringBuilder.Append(o.ToEmitterString()));
|
|
|
|
// string emitterString = emitterStringBuilder.ToString();
|
|
|
|
|
|
// StringBuilder statusStringBuilder = new StringBuilder();
|
// statusStringBuilder.AppendLine(";ID \tStatus/Setting\r\n");
|
// Links.ForEach(o => statusStringBuilder.Append(o.ToStatusString()));
|
|
|
|
// string statusString = statusStringBuilder.ToString();
|
|
|
|
// output = tempString;
|
|
// output = ReplaceContent(output, "JUNCTIONS", junctionString);
|
// output = ReplaceContent(output, "RESERVOIRS", reserverString);
|
// output = ReplaceContent(output, "TANKS", tankString);
|
// output = ReplaceContent(output, "PIPES", pipeString);
|
// output = ReplaceContent(output, "VALVES", valveString);
|
// output = ReplaceContent(output, "PUMPS", pumpString);
|
// output = ReplaceContent(output, "CURVES", curveString);
|
|
|
// output = ReplaceContent(output, "COORDINATES", coorString);
|
// output = ReplaceContent(output, "EMITTERS", emitterString);
|
// output = ReplaceContent(output, "STATUS", statusString);
|
// string backupFolderPath = Path.Combine(Path.GetDirectoryName(filePath), "bk");
|
// if (!Directory.Exists(backupFolderPath))
|
// {
|
// Directory.CreateDirectory(backupFolderPath);
|
// }
|
|
// string backupFileName = $"{Path.GetFileNameWithoutExtension(filePath)}_{DateTime.Now:yyyyMMddHHmmss}{Path.GetExtension(filePath)}";
|
// string backupFilePath = Path.Combine(backupFolderPath, backupFileName);
|
// if (File.Exists(filePath)) File.Copy(filePath, backupFilePath, true);
|
|
|
// // 检查文件是否存在
|
// try
|
// {
|
// Global.ClearFileReadOnly(filePath);
|
|
// File.WriteAllText(filePath, output);
|
// }
|
// catch (Exception ex)
|
// {
|
// MessageBox.Show(ex.Message);
|
// }
|
|
// //MessageBox.Show($"保存成功!");
|
//}
|
/// <summary>
|
/// 根据Inp文件计算
|
/// </summary>
|
/// <returns></returns>
|
public virtual List<TimePoint> Calc(string InpPath)
|
{
|
HydraulicModel.Epanet epanet = new HydraulicModel.Epanet();
|
var result = new List<TimePoint>();
|
var err = epanet.open(InpPath, "d:\\5.log", "");
|
|
if (err != 0)
|
{
|
throw new Exception($"打开计算文件失败:{err}");
|
}
|
var errCal = epanet.solveH();
|
if (errCal != 0)
|
{
|
throw new Exception($"计算失败:{errCal}");
|
}
|
int nodeCount = 0, linkCount = 0;
|
epanet.getcount((int)CountType.Node, ref nodeCount);
|
epanet.getcount((int)CountType.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 = System.Enum.GetValues(typeof(HydraulicModel.NodeValueType));
|
for (var j = 0; j < arr.Length; j++)
|
{
|
float v = 0;
|
var t = (HydraulicModel.NodeValueType)j;
|
epanet.getnodevalue(i, (int)t, ref v);
|
result.Add(new TimePoint()
|
{
|
Key = sb.ToString() + "_" + t.ToString(),
|
Value = v,
|
});
|
}
|
}
|
|
for (int i = 1; i < linkCount; i++)
|
{
|
epanet.getlinkid(i, sb);
|
var arr = System.Enum.GetValues(typeof(HydraulicModel.LinkValueType));
|
for (var j = 0; j < arr.Length; j++)
|
{
|
float v = 0;
|
var t = (HydraulicModel.LinkValueType)j;
|
epanet.getlinkvalue(i, (int)t, ref v);
|
result.Add(new TimePoint()
|
{
|
Key = sb.ToString() + "_" + t.ToString(),
|
Value = v,
|
});
|
}
|
}
|
return result;
|
}
|
|
/// <summary>
|
/// 先生成Inp文件,再计算
|
/// </summary>
|
/// <returns></returns>
|
public virtual List<TimePoint> Calc()
|
{
|
var inpPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, @"data\inp\calc.inp");
|
BuildToInp(inpPath);
|
return Calc(inpPath);
|
}
|
|
/// <summary>
|
/// 数据有效性校验
|
/// </summary>
|
/// <returns></returns>
|
public virtual CheckModel Check()
|
{
|
var result = new CheckModel();
|
|
return result;
|
}
|
|
private string ReplaceContent(string text, string content, string replaceString)
|
{
|
|
|
string str = replaceString;
|
|
string replacedText = ReplaceCoordinatesSection(text, content, str);
|
|
return replacedText;
|
//Console.WriteLine(replacedText);
|
}
|
|
public static string ReplaceCoordinatesSection(string text, string content, string str)
|
{
|
string pattern = $@"(\[{content}\]).*?(\[|$)";
|
|
string replacedText = Regex.Replace(text, pattern, match =>
|
{
|
string section = match.Groups[2].Value.Trim();
|
|
if (!string.IsNullOrEmpty(section))
|
{
|
return $"{match.Groups[1].Value}\n{str}\n[";
|
}
|
else
|
{
|
return $"{match.Groups[1].Value}\n{str}\n[";
|
}
|
}, RegexOptions.Singleline);
|
|
return replacedText;
|
}
|
|
}
|
}
|