using System.Net.Http.Headers;
|
|
namespace Yw.EPAnet
|
{
|
/// <summary>
|
/// 管网能耗分析拓展
|
/// </summary>
|
public static class NetworkEnergyAnalyseExtensions
|
{
|
|
/// <summary>
|
/// 分析整个管网的能量
|
/// </summary>
|
public static List<EnergyPoint> AnalyzeEnergy(this Network network,CalcuResult calcuResult)
|
{
|
var dictLinks = calcuResult.LinkList.ToDictionary(p => p.Id);
|
var dictNodes = calcuResult.NodeList.ToDictionary(p => p.Id);
|
var points=new List<EnergyPoint>();
|
var result = new EnergyResult();
|
//找到管网中需水量为负的节点
|
var negativeDemandNodes = network.GetAllNodes().Where(n =>
|
{
|
if (n is Node node)
|
{
|
return dictNodes[node.Id].Demand < 0;
|
}
|
return false;
|
}).ToList();
|
|
//找到管网中需水量为正的节点
|
var positiveDemandNodes = network.GetAllNodes().Where(n =>
|
{
|
if (n is Node node)
|
{
|
return dictNodes[node.Id].Demand > 0;
|
}
|
return false;
|
}).ToList();
|
|
double minElev = 99999999;
|
|
List<Node> DemandNodes=new List<Node>();
|
DemandNodes.AddRange(negativeDemandNodes);
|
DemandNodes.AddRange(positiveDemandNodes);
|
foreach (var node in DemandNodes)
|
{
|
if (node is Junction n)
|
{
|
if (n.Elev < minElev)
|
{
|
minElev = n.Elev;
|
}
|
}
|
else if (node is Tank t)
|
{
|
if (t.PoolElev < minElev)
|
{
|
minElev = t.PoolElev;
|
}
|
}
|
else if (node is Reservoir r)
|
{
|
var elev = r.PoolElev == null ? 0 : (double)r.PoolElev;
|
if (elev < minElev)
|
{
|
minElev = elev;
|
}
|
}
|
}
|
|
|
|
|
|
//计算这些节点的势能,势能计算公式为:势能=需水量*节点水头
|
|
foreach (var node in negativeDemandNodes)
|
{
|
if (node is Node n)
|
{
|
double energyInW = GetEnergyPowerByQH(Math.Abs(dictNodes[n.Id].Demand), dictNodes[n.Id].Head- minElev);
|
var energyPoint = new EnergyPoint
|
{
|
Id = n.Id,
|
EnergyType = eEnergyType.Input,
|
EnergyPower = energyInW,
|
|
};
|
points.Add(energyPoint);
|
result.InputEnergy.Add(n.Id, new List<EnergyPoint> { energyPoint });
|
result.InputTotalEnerge += energyInW;
|
}
|
}
|
|
|
foreach (var node in positiveDemandNodes)
|
{
|
if (node is Node n)
|
{
|
double energyInW = GetEnergyPowerByQH(Math.Abs(dictNodes[n.Id].Demand), dictNodes[n.Id].Head- minElev);
|
var energyPoint = new EnergyPoint
|
{
|
Id = n.Id,
|
EnergyType = eEnergyType.Output,
|
EnergyPower = energyInW,
|
|
};
|
points.Add(energyPoint);
|
result.OutputEnergy.Add(n.Id, new List<EnergyPoint> { energyPoint });
|
result.OutputTotalEnerge += energyInW;
|
}
|
}
|
|
foreach (var link in network.GetAllLinks())
|
{
|
if (link is Pipe p)
|
{
|
|
var cStartnode = (dictLinks[ link.Id].Flow > 0 ? link.StartNode : link.EndNode) as Node;
|
var cEndnode = (dictLinks[link.Id].Flow > 0 ? link.EndNode : link.StartNode) as Node;
|
var endNodeMinorlossCoff = p.EndMinorLossCoeff;
|
var startNodeMinorlossCoff = p.StartMinorLossCoeff;
|
//根据p.diameter和p.flow计算流速
|
double velocity = dictLinks[p.Id].Flow / (Math.PI * Math.Pow(p.Diameter / 2, 2));
|
var flow = Math.Abs(dictLinks[p.Id].Flow);
|
if (p.StartMinorLossCoeff!=0)
|
{
|
//根据流速计算局部水头损失
|
double headminorloss1 = p.StartMinorLossCoeff * Math.Pow(velocity, 2) / 2 / 9.81;
|
double energypower=GetEnergyPowerByQH(flow, headminorloss1);
|
var Id = cStartnode.Id;
|
if (!result.LossEnergy.ContainsKey(Id)) result.LossEnergy.Add(Id, new List<EnergyPoint>());
|
var energypoint=new EnergyPoint
|
{
|
Id = Id,
|
EnergyType = eEnergyType.MinorLoss,
|
EnergyPower = energypower,
|
|
};
|
|
result.MinorLossTotalEnerge += energypower;
|
//如果存在多个局部水头损失,需要累加合并
|
if (result.LossEnergy[Id].Any(e => e.EnergyType == eEnergyType.MinorLoss))
|
{
|
var exist = result.LossEnergy[Id].First(e => e.EnergyType == eEnergyType.MinorLoss);
|
exist.EnergyPower += energypower;
|
}
|
else
|
{
|
result.LossEnergy[Id].Add(energypoint);
|
}
|
var point = result.LossEnergy[Id].First(e => e.EnergyType == eEnergyType.MinorLoss);
|
points.Add(point);
|
}
|
|
if (p.EndMinorLossCoeff != 0)
|
{
|
//根据流速计算局部水头损失
|
double headminorloss2 = p.EndMinorLossCoeff * Math.Pow(velocity, 2) / 2 / 9.81;
|
double energypower = GetEnergyPowerByQH(flow, headminorloss2);
|
var Id = cEndnode.Id;
|
if (!result.LossEnergy.ContainsKey(Id)) result.LossEnergy.Add(Id, new List<EnergyPoint>());
|
var energypoint = new EnergyPoint
|
{
|
Id = Id,
|
EnergyType = eEnergyType.MinorLoss,
|
EnergyPower = energypower,
|
|
};
|
result.MinorLossTotalEnerge += energypower;
|
//如果存在多个局部水头损失,需要累加合并
|
if (result.LossEnergy[Id].Any(e => e.EnergyType == eEnergyType.MinorLoss))
|
{
|
var exist = result.LossEnergy[Id].First(e => e.EnergyType == eEnergyType.MinorLoss);
|
exist.EnergyPower += energypower;
|
}
|
else
|
{
|
result.LossEnergy[Id].Add(energypoint);
|
}
|
var point = result.LossEnergy[Id].First(e => e.EnergyType == eEnergyType.MinorLoss);
|
points.Add(point);
|
}
|
|
double pipeheadminorloss = 0;
|
if (p.MinorLossCoeff!=0)
|
{
|
//根据流速计算局部水头损失
|
pipeheadminorloss = p.MinorLossCoeff * Math.Pow(velocity, 2) / 2 / 9.81;
|
double energypower = GetEnergyPowerByQH(flow, pipeheadminorloss);
|
var Id = p.Id;
|
if (!result.LossEnergy.ContainsKey(Id)) result.LossEnergy.Add(Id, new List<EnergyPoint>());
|
var energypoint = new EnergyPoint
|
{
|
Id = Id,
|
EnergyType = eEnergyType.MinorLoss,
|
EnergyPower = energypower,
|
|
};
|
result.LossEnergy[Id].Add(energypoint);
|
result.MinorLossTotalEnerge += energypower;
|
points.Add(energypoint);
|
}
|
|
|
{
|
double headlossFriction =Math.Abs(dictLinks[p.Id].HeadLoss) - pipeheadminorloss;
|
double energypower = GetEnergyPowerByQH(flow, headlossFriction);
|
var Id = p.Id;
|
if (!result.LossEnergy.ContainsKey(Id)) result.LossEnergy.Add(Id, new List<EnergyPoint>());
|
var energypoint = new EnergyPoint
|
{
|
Id = Id,
|
EnergyType = eEnergyType.FrictionalLoss,
|
EnergyPower = energypower,
|
|
};
|
result.LossEnergy[Id].Add(energypoint);
|
result.FrictionalLossTotalEnerge += energypower;
|
points.Add(energypoint);
|
}
|
|
|
|
}
|
else if (link is Valve || link is Pump || link is Resistance)
|
{
|
//只计算阀门本身的局部水头损失
|
var flow = Math.Abs(dictLinks[link.Id].Flow);
|
//根据流速计算局部水头损失
|
double headminorloss1 =Math.Abs(dictNodes[link.StartNode.Id].Head - dictNodes[link.EndNode.Id].Head);
|
double energypower = GetEnergyPowerByQH(flow, headminorloss1);
|
var Id = link.Id;
|
|
if (link is Pump)
|
{
|
var Type = eEnergyType.Promote;
|
if (!result.InputEnergy.ContainsKey(Id)) result.InputEnergy.Add(Id, new List<EnergyPoint>());
|
var energypoint = new EnergyPoint
|
{
|
Id = Id,
|
EnergyType = Type,
|
EnergyPower = energypower,
|
|
};
|
result.InputEnergy[Id].Add(energypoint);
|
result.InputTotalEnerge += energypower;
|
points.Add(energypoint);
|
}
|
else
|
{
|
var Type = eEnergyType.MinorLoss;
|
if (!result.LossEnergy.ContainsKey(Id)) result.LossEnergy.Add(Id, new List<EnergyPoint>());
|
EnergyPoint energypoint = new EnergyPoint
|
{
|
Id = Id,
|
EnergyType = Type,
|
EnergyPower = energypower,
|
|
};
|
result.LossEnergy[Id].Add(energypoint);
|
result.MinorLossTotalEnerge += energypower;
|
points.Add(energypoint);
|
}
|
|
}
|
}
|
|
return points;
|
}
|
|
private static double GetEnergyPowerByQH(double flowQ,double head)
|
{
|
// 计算将 1 m³的水,提升 1 m 的高度所需要的能量
|
// 1 m³的水受到重力G=1m³ * 1000 kg/m³(密度) * 9.81 m/s² (重力加速度) = 9810 N
|
// 能量 = 力 * 距离 = 9810 N * 1 m = 9810 J
|
// 势能等效功率 = 能量 / 时间 = 9810 J / 1 h = 9810 J/h = 9810/3600 J/s= 9810/3600 W
|
double energyInM4PerH = flowQ * head;
|
double energyInW = energyInM4PerH * 1000 * 9.81 / 3600;
|
return energyInW;
|
}
|
|
|
}
|
|
public class EnergyPoint
|
{
|
public string Id { get; set; }
|
public eEnergyType EnergyType { get; set; }
|
/// <summary>
|
/// 单位时间内的能量,单位:瓦特W=焦耳J/秒s
|
/// </summary>
|
public double EnergyPower { get; set; }
|
|
}
|
|
public class EnergyResult
|
{
|
|
public Dictionary<string, List<EnergyPoint>> InputEnergy { get; set; }
|
public Dictionary<string, List<EnergyPoint>> LossEnergy { get; set; }
|
public Dictionary<string, List<EnergyPoint>> OutputEnergy { get; set; }
|
|
public double InitTotalEnerge { get; set; }
|
|
public double InputTotalEnerge { get; set; }
|
|
public double MinorLossTotalEnerge { get; set; }
|
|
public double FrictionalLossTotalEnerge { get; set; }
|
|
public double OutputTotalEnerge { get; set; }
|
|
public EnergyResult()
|
{
|
InputEnergy = new Dictionary<string, List<EnergyPoint>>();
|
LossEnergy = new Dictionary<string, List<EnergyPoint>>();
|
OutputEnergy = new Dictionary<string, List<EnergyPoint>>();
|
InputTotalEnerge = 0;
|
MinorLossTotalEnerge = 0;
|
FrictionalLossTotalEnerge = 0;
|
OutputTotalEnerge = 0;
|
}
|
|
|
}
|
|
public enum eEnergyType
|
{
|
/// <summary>
|
/// 重力势能输入:水池、水库
|
/// </summary>
|
Input,
|
|
/// <summary>
|
/// 重力势能输出:水池、水库、扩散器
|
/// </summary>
|
Output,
|
|
/// <summary>
|
/// 水泵提升能量(输入系统的有效功率),不考虑效率
|
/// </summary>
|
Promote,
|
|
/// <summary>
|
/// 局部摩擦阻力带来的能量损失:阀门、连接节点、管道、设备(换热器、空压机)
|
/// </summary>
|
MinorLoss,
|
|
/// <summary>
|
/// 沿程摩擦阻力带来的能量损失:管道
|
/// </summary>
|
FrictionalLoss,
|
}
|
|
|
}
|