using NPOI.Util;
using Yw.Geometry;
namespace Yw.WinFrmUI.Phart
{
///
/// 性能计算辅助类
///
public static class PumpCalcHelper
{
#region 常规计算
#region 计算扬程
///
/// 计算扬程
///
/// 瞬时流量 m³/h
/// 进口压力 mpa
/// 出口压力 mpa
/// 进口口径 mm
/// 出口口径 mm
/// 进口标高 m
/// 出口标高 m
/// 扬程 m
public static double CalculateH(double q, double pr1, double pr2, double d1, double d2, double z1, double z2)
{
var qa = q / 3600;
var pr1a = pr1 * 1000000;
var pr2a = pr2 * 1000000;
var d1a = d1 / 1000;
var d2a = d2 / 1000;
var v1 = qa * 4 / (Math.PI * Math.Pow(d1a, 2));
var v2 = qa * 4 / (Math.PI * Math.Pow(d2a, 2));
var distance = z2 - z1;
var pg = Constant.WaterDensity * Constant.g;
var g2 = 2 * Constant.g;
var h = (pr2a / pg - pr1a / pg) + (Math.Pow(v2, 2) / g2 - Math.Pow(v1, 2) / g2) + distance;
return h;
}
///
/// 计算 OtherPress (测量扬程= 压差 + 表位差 + 流速)
///
/// 流量 m³/h
/// 进口管径 mm
/// 出口管径 mm
/// 进口标高 mm
/// 出口标高 mm
///
public static double CalculateOtherPress(double? q, double? inletPipeDia, double? outletPipeDia, double? inletElevation, double? outletElevation)
{
if (q == null || q.Value < 0.05)
{
if (outletElevation == null || inletElevation == null)
return 0;
return outletElevation.Value - inletElevation.Value;
}
double flow = q.Value;
double inPipeV = 0;
if (inletPipeDia != null && inletPipeDia.Value > 0.1)
{
// 流速计算 pipeD =mm,pumpFlow=m3/p
inPipeV = Constant.OtherPressCoeff * flow / inletPipeDia.Value / inletPipeDia.Value;
}
double outPipeV = 0;
if (outletPipeDia != null && outletPipeDia.Value > 0.1)
{
// 流速计算 rPipeD =mm,rPumpFlow=m3/p
outPipeV = Constant.OtherPressCoeff * flow / outletPipeDia.Value / outletPipeDia.Value;
}
double differV = (outPipeV * outPipeV - inPipeV * inPipeV) / Constant.g / 2.0;
if (outletElevation == null || inletElevation == null)
return differV;
return differV + outletElevation.Value - inletElevation.Value;
}
#endregion
#region 计算效率
///
/// 计算效率
///
/// 瞬时流量 m³/h
/// 扬程 m
/// 功率 kw
/// 密度 kg/m^3
/// 重力加速度 m/s^2
/// 百分数
public static double CalculateE(double q, double h, double p, double ρ, double g)
{
var qa = q / 3600;
var pa = p * 1000;
double e = 0;
if (pa < 0.1)
{
return e;
}
e = ρ * g * qa * h / pa;
return Math.Round(e * 100, 2);
}
///
/// 计算效率
///
/// 瞬时流量 m³/h
/// 扬程 m
/// 功率 kw
/// 百分数
public static double CalculateE(double q, double h, double p)
{
return CalculateE(q, h, p, Constant.WaterDensity, Constant.g);
}
///
/// 计算效率
///
/// 瞬时流量 m³/h
/// 扬程 m
/// 功率 kw
/// 密度 kg/m^3
/// 百分数
public static double CalculateE(double q, double h, double p, double ρ)
{
return CalculateE(q, h, p, ρ, Constant.g);
}
#endregion
#region 计算功率
///
/// 计算功率
///
/// 瞬时流量 m³/h
/// 扬程 m
/// 效率 百分数
/// 密度kg/m³
/// 重力加速度 m/s²
/// kw
public static double CalculateP(double q, double h, double e, double ρ, double g)
{
var qa = q / 3600;
var ea = e / 100;
double p = 0;
if (ea < 0.01)
{
return p;
}
p = ρ * g * qa * h / ea;
p = p / 1000;//换算成kw
if (p < 2)
{
return Math.Round(p, 4);
}
if (p < 30)
{
return Math.Round(p, 3);
}
if (p < 100)
{
return Math.Round(p, 2);
}
return Math.Round(p, 1);
}
///
/// 计算功率
///
/// 瞬时流量 m³/h
/// 扬程 m
/// 效率 百分数
/// 密度kg/m³
/// kw
public static double CalculateP(double q, double h, double e, double ρ)
{
return CalculateP(q, h, e, ρ, Constant.g);
}
///
/// 计算功率
///
/// 瞬时流量 m³/h
/// 扬程 m
/// 效率 百分数
/// kw
public static double CalculateP(double q, double h, double e)
{
return CalculateP(q, h, e, Constant.WaterDensity, Constant.g);
}
#endregion
#region Mpa<=>m
///
/// Mpa=>m
///
public static double Mpa2M(double mpa)
{
return mpa * Constant.WaterDensity / Constant.g;
}
///
/// m=>Mpa
///
public static double M2Mpa(double m)
{
return m * Constant.g / Constant.WaterDensity;
}
#endregion
#region 计算用电量
///
/// 计算用电量
///
/// 功率kw
/// 时间h
/// kw*h
public static double CalculateD(double p, double t)
{
return p * t;
}
#endregion
#region 计算累积流量
///
/// 计算累积流量
///
/// 瞬时流量m³/h
/// 时间h
/// m³
public static double CalculateQt(double q, double t)
{
return q * t;
}
#endregion
#region 计算能耗
///
/// 计算千吨能耗
///
/// 功率kW
/// 瞬时流量m³/h
/// kW·h/km³
public static double CalculateWP(double p, double q)
{
if (q < 0.1)
{
return default;
}
return p / q * 1000;
}
///
/// 计算单位能耗
///
/// 功率kW
/// 瞬时流量m³/h
/// 扬程m
/// kW·h/km³
public static double CalculateUWP(double p, double q, double h)
{
if (q < 0.1)
{
return default;
}
if (h < 0.1)
{
return default;
}
return p / q / h * 1000;
}
#endregion
#region 频率换算
///
/// 根据频率计算流量
///
/// 瞬时流量 m³/h
/// 频率
/// 额定频率
///
public static double CalculateQByHz(double q, double hz, double hzr = 50)
{
if (hzr < 0.1)
{
return q;
}
if (hz < 0.1)
{
return q;
}
/* if (hz > hzr)
{
return q;
}*/
double f_ratio = hzr / hz;
return q * f_ratio;
}
///
/// 根据频率计算扬程
///
/// 扬程 m
/// 频率
/// 额定频率
///
public static double CalculateHByHz(double h, double hz, double hzr = 50)
{
if (hzr < 0.1)
{
return h;
}
if (hz < 0.1)
{
return h;
}
/* if (hz > hzr)
{
return h;
}*/
double f_ratio = hzr / hz;
return h * f_ratio * f_ratio;
}
///
/// 根据频率计算 50hz功率
///
/// 功率 kw
/// 频率 kw
/// 额定频率
///
public static double CalculatePByHz(double p, double hz, double hzr = 50)
{
if (hzr < 0.1)
{
return p;
}
if (hz < 0.1)
{
return p;
}
/* if (hz > hzr)
{
return p;
}*/
double f_ratio = hzr / hz;
return p * f_ratio * f_ratio * f_ratio;
}
///
/// 根据转速计算流量
///
/// 瞬时流量 m³/h
/// 转速 r/min
/// 额定转速 r/min
///
public static double CalculateQByN(double q, double n, double nr)
{
if (nr < 0.1)
{
return q;
}
if (n < 0.1)
{
return q;
}
double f_ratio = nr / n;
return q * f_ratio;
}
///
/// 根据转速计算扬程
///
/// 扬程 m
/// 转速 r/min
/// 额定转速 r/min
///
public static double CalculateHByN(double h, double n, double nr)
{
if (nr < 0.1)
{
return h;
}
if (n < 0.1)
{
return h;
}
double f_ratio = nr / n;
return h * f_ratio * f_ratio;
}
///
/// 根据转速计算功率
///
/// 功率 kw
/// 转速 r/min
/// 额定转速 r/min
///
public static double CalculatePByN(double p, double n, double nr)
{
if (nr < 0.1)
{
return p;
}
if (n < 0.1)
{
return p;
}
double f_ratio = nr / n;
return p * f_ratio * f_ratio * f_ratio;
}
#endregion
#endregion
#region 复杂计算
#region Simu
///
/// 知道原始速度,以及原始的杨程H以及对应的变速后的杨程,求变速后的速度
///
///
///
///
///
public static double CalculateSimuByH(double origin_, double origin_h, double change_h)
{
double ratio = Math.Pow(origin_h / change_h, 1.0 / 2.0);
return origin_ / ratio;
}
///
/// 知道原始速度,以及原始的流量Q以及对应的变速后的杨程,求变速后的速度
///
///
///
///
///
public static double CalculateSimuByQ(double origin_, double origin_q, double change_q)
{
double ratio = origin_q / change_q;
return origin_ / ratio;
}
#endregion
#region 相似换算
///
/// 计算相似流量扬程曲线
///
/// 三次样条曲线
/// 原始频率
/// 换算频率
/// 拟合点数量
///
public static Yw.Geometry.CubicSpline2d CalculateSimilarQH(Yw.Geometry.CubicSpline2d cubic_spline, double origin_hz, double change_hz, int point_count = 12)
{
if (cubic_spline == null)
return null;
if (change_hz < 1)
return null;
var fit_points = cubic_spline.GetPointList(point_count);
var ratio = change_hz / origin_hz;
var similar_pt_list = new List();
foreach (Yw.Geometry.Point2d fit_point in fit_points)
{
var similar_point = new Yw.Geometry.Point2d();
similar_point.X = fit_point.X * ratio;
similar_point.Y = fit_point.Y * ratio * ratio;
similar_pt_list.Add(similar_point);
}
return new Yw.Geometry.CubicSpline2d(similar_pt_list);
}
///
/// 计算相似流量功率曲线
///
/// 三次样条曲线
/// 原始频率
/// 换算频率
/// 拟合点数量
///
public static Yw.Geometry.CubicSpline2d CalculateSimilarQP(Yw.Geometry.CubicSpline2d cubic_spline, double origin_hz, double change_hz, int point_count = 12)
{
if (cubic_spline == null)
return null;
if (change_hz < 1)
return null;
var fit_points = cubic_spline.GetPointList(point_count);
var ratio = change_hz / origin_hz;
var similar_pt_list = new List();
foreach (Yw.Geometry.Point2d fit_point in fit_points)
{
var similar_point = new Yw.Geometry.Point2d();
similar_point.X = fit_point.X * ratio;
similar_point.Y = fit_point.Y * ratio * ratio * ratio;
similar_pt_list.Add(similar_point);
}
return new Yw.Geometry.CubicSpline2d(similar_pt_list);
}
///
/// 计算相似流量效率曲线
///
/// 三次样条曲线
/// 原始频率
/// 换算频率
/// 拟合点数量
///
public static Yw.Geometry.CubicSpline2d CalculateSimilarQE(Yw.Geometry.CubicSpline2d cubic_spline, double origin_hz, double change_hz, int point_count = 12)
{
if (cubic_spline == null)
return null;
if (change_hz < 1)
return null;
var fit_points = cubic_spline.GetPointList(point_count);
var ratio = change_hz / origin_hz;
var similar_pt_list = new List();
foreach (Yw.Geometry.Point2d fit_point in fit_points)
{
var similar_point = new Yw.Geometry.Point2d();
similar_point.X = fit_point.X * ratio;
similar_point.Y = fit_point.Y;
similar_pt_list.Add(similar_point);
}
return new Yw.Geometry.CubicSpline2d(similar_pt_list);
}
///
/// 计算相似流量扬程曲线点
///
/// 曲线点
/// 原始频率
/// 换算频率
/// 拟合点数量
///
public static List CalculateSimilarQH(List fit_points, double origin_hz, double change_hz)
{
if (fit_points == null || !fit_points.Any())
return null;
if (change_hz < 1)
return null;
var ratio = change_hz / origin_hz;
var similar_pt_list = new List();
foreach (Yw.Geometry.Point2d fit_point in fit_points)
{
var similar_point = new Yw.Geometry.Point2d();
similar_point.X = fit_point.X * ratio;
similar_point.Y = fit_point.Y * ratio * ratio;
similar_pt_list.Add(similar_point);
}
return similar_pt_list;
}
///
/// 计算相似流量功率曲线点
///
/// 曲线点
/// 原始频率
/// 换算频率
/// 拟合点数量
///
public static List CalculateSimilarQP(List fit_points, double origin_hz, double change_hz)
{
if (fit_points == null || !fit_points.Any())
return null;
if (change_hz < 1)
return null;
var ratio = change_hz / origin_hz;
var similar_pt_list = new List();
foreach (Yw.Geometry.Point2d fit_point in fit_points)
{
var similar_point = new Yw.Geometry.Point2d();
similar_point.X = fit_point.X * ratio;
similar_point.Y = fit_point.Y * ratio * ratio * ratio;
similar_pt_list.Add(similar_point);
}
return similar_pt_list;
}
///
/// 计算相似流量效率曲线点
///
/// 曲线点
/// 原始频率
/// 换算频率
/// 拟合点数量
///
public static List CalculateSimilarQE(List fit_points, double origin_hz, double change_hz)
{
if (fit_points == null || !fit_points.Any())
return null;
if (change_hz < 1)
return null;
var ratio = change_hz / origin_hz;
var similar_pt_list = new List();
foreach (Yw.Geometry.Point2d fit_point in fit_points)
{
var similar_point = new Yw.Geometry.Point2d();
similar_point.X = fit_point.X * ratio;
similar_point.Y = fit_point.Y;
similar_pt_list.Add(similar_point);
}
return similar_pt_list;
}
///
/// 计算相似流量扬程点
///
/// 点
/// 原始频率
/// 换算频率
///
public static Yw.Geometry.Point2d CalculateSimilarQH(Yw.Geometry.Point2d fit_point, double origin_hz, double change_hz)
{
if (fit_point == null)
return null;
if (change_hz < 1)
return null;
var ratio = change_hz / origin_hz;
var similar_point = new Yw.Geometry.Point2d();
similar_point.X = fit_point.X * ratio;
similar_point.Y = fit_point.Y * ratio * ratio;
return similar_point;
}
///
/// 计算相似流量功率点
///
/// 点
/// 原始频率
/// 换算频率
///
public static Yw.Geometry.Point2d CalculateSimilarQP(Yw.Geometry.Point2d fit_point, double origin_hz, double change_hz)
{
if (fit_point == null)
return null;
if (change_hz < 1)
return null;
var ratio = change_hz / origin_hz;
var similar_point = new Yw.Geometry.Point2d();
similar_point.X = fit_point.X * ratio;
similar_point.Y = fit_point.Y * ratio * ratio * ratio;
return similar_point;
}
///
/// 计算相似流量效率点
///
/// 点
/// 原始频率
/// 换算频率
///
public static Yw.Geometry.Point2d CalculateSimilarQE(Yw.Geometry.Point2d fit_point, double origin_hz, double change_hz)
{
if (fit_point == null)
return null;
if (change_hz < 1)
return null;
var ratio = change_hz / origin_hz;
var similar_point = new Yw.Geometry.Point2d();
similar_point.X = fit_point.X * ratio;
similar_point.Y = fit_point.Y;
return similar_point;
}
#endregion
#region 计算推荐参数
public enum eCalculatePumpType
{
单级单吸离心泵 = 1,
多级离心泵 = 2,
双吸离心泵 = 3,
化工泵 = 4,
渣浆泵 = 5,
长轴泵 = 6
}
//capacity
static double[] effq = new double[33] { 5, 10, 15, 20, 25, 30, 40, 50, 60, 70, 80, 90, 100, 150, 200, 300, 400, 500, 600, 700, 800, 900, 1000, 1500, 2000, 3000, 4000, 5000, 6000, 7000, 8000, 9000, 10000 };
//1 single stage seriesEntity eff
static double[] singleeff = new double[33] { 58.0, 64.0, 67.2, 69.4, 70.9, 72.0, 73.8, 74.9, 75.8, 76.5, 77.0, 77.6, 78.0, 79.8, 80.8, 82.0, 83.0, 83.7, 84.2, 84.7, 85.0, 85.3, 85.7, 86.6, 87.2, 88.0, 88.6, 89.0, 89.2, 89.5, 89.7, 89.9, 90.0 };
//2 multi stage seriesEntity eff
static double[] multieff = new double[26] { 55.4, 59.4, 61.8, 63.5, 64.8, 65.9, 67.5, 68.9, 69.9, 70.9, 71.5, 72.3, 72.9, 75.3, 76.9, 79.2, 80.6, 81.5, 82.2, 82.8, 83.1, 83.5, 83.9, 84.8, 85.1, 85.5 };
//1 correct eff
static double[] effcorrect1 = new double[19] { 32, 25.5, 20.6, 17.3, 14.7, 12.5, 10.5, 9.0, 7.5, 6.0, 5.0, 4.0, 3.2, 2.5, 2.0, 1.5, 1.0, 0.5, 0 };
//2 correct eff
static double[] effcorrect2 = new double[10] { 0, 0.3, 0.7, 1.0, 1.3, 1.7, 1.9, 2.2, 2.7, 3.0 };
static double[] effns1 = new double[19] { 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80, 85, 90, 95, 100, 110, 120 };
static double[] effns2 = new double[10] { 210, 220, 230, 240, 250, 260, 270, 280, 290, 300 };
///
/// 根据泵类型计算推荐效率
///
/// 流量
/// 扬程
/// 转速
/// 泵类型
///
public static double CalculateEByPumpType(double q, double h, double n, int pumpType)
{
double ns = CalculateNs(q, h, n);
double eff, qjs1, qjs2, qjs3, effjs1, effjs2, effjs3, correct = 1;
int i = 0;
double dltE = 0.0;
double q0 = q;
double h0 = h;
//
double t = 1000;
if (pumpType == (int)eCalculatePumpType.单级单吸离心泵)
t = 10000;
if (pumpType == (int)eCalculatePumpType.多级离心泵)
t = 300000;
if (pumpType == (int)eCalculatePumpType.双吸离心泵)
t = 10000;
if (pumpType == (int)eCalculatePumpType.化工泵)
t = 10000;
if (pumpType == (int)eCalculatePumpType.渣浆泵)
t = 10000;
if (pumpType == (int)eCalculatePumpType.长轴泵)
t = 10000;
if (q0 > t)
{
i = effq.Length - 1;
}
else if (q0 >= 1.5 && q0 <= t)
{
i = 0;
for (i = 0; effq[i] <= q0; i++)
{
if (i + 1 == effq.Count())
{
break;
}
}
}
else
{
return -1;
}
if (i >= effq.Length)
i = effq.Length - 1;
if (q0 >= 10)
{
qjs1 = effq[i];
qjs2 = effq[i - 1];
qjs3 = effq[i - 2];
switch (pumpType)
{
case 1:
if (i >= singleeff.Length)
i = singleeff.Length - 1;
effjs1 = singleeff[i];
effjs2 = singleeff[i - 1];
effjs3 = singleeff[i - 2];
break;
case 2:
if (i >= multieff.Length)
i = multieff.Length - 1;
effjs1 = multieff[i];
effjs2 = multieff[i - 1];
effjs3 = multieff[i - 2];
break;
case 3:
if (i >= singleeff.Length)
i = singleeff.Length - 1;
effjs1 = singleeff[i];
effjs2 = singleeff[i - 1];
effjs3 = singleeff[i - 2];
dltE = -2;
break;
case 4:
if (i >= singleeff.Length)
i = singleeff.Length - 1;
effjs1 = singleeff[i];
effjs2 = singleeff[i - 1];
effjs3 = singleeff[i - 2];
dltE = 5;
break;
case 5:
effjs1 = singleeff[i];
effjs2 = singleeff[i - 1];
effjs3 = singleeff[i - 2];
dltE = 8;
break;
default:
effjs1 = singleeff[i];
effjs2 = singleeff[i - 1];
effjs3 = singleeff[i - 2];
dltE = 3.5;
break;
}
}
else
{
qjs1 = effq[2];
qjs2 = effq[1];
qjs3 = effq[0];
switch (pumpType)
{
case 1:
effjs1 = singleeff[2];
effjs2 = singleeff[1];
effjs3 = singleeff[0];
break;
case 2:
effjs1 = multieff[2];
effjs2 = multieff[1];
effjs3 = multieff[0];
break;
case 3:
effjs1 = singleeff[2];
effjs2 = singleeff[1];
effjs3 = singleeff[0];
dltE = -2;
break;
case 4:
effjs1 = singleeff[2];
effjs2 = singleeff[1];
effjs3 = singleeff[0];
dltE = 5;
break;
case 5:
effjs1 = singleeff[2];
effjs2 = singleeff[1];
effjs3 = singleeff[0];
dltE = 8;
break;
default:
effjs1 = singleeff[2];
effjs2 = singleeff[1];
effjs3 = singleeff[0];
dltE = 3.5;
break;
}
}
eff = (q0 - qjs2) * (q0 - qjs3) * effjs1 / ((qjs1 - qjs2) * (qjs1 - qjs3)) +
(q0 - qjs1) * (q0 - qjs3) * effjs2 / ((qjs2 - qjs1) * (qjs2 - qjs3)) +
(q0 - qjs1) * (q0 - qjs2) * effjs3 / ((qjs3 - qjs1) * (qjs3 - qjs2)) - dltE;
if ((ns < 120 && ns >= 20) || (ns < 300 && ns > 210))
{
if (ns < 120 && ns >= 20)
{
for (i = 0; effns1[i] <= ns; i++)
{
}
if (ns >= 25)
{
qjs1 = effns1[i];
qjs2 = effns1[i - 1];
qjs3 = effns1[i - 2];
effjs1 = effcorrect1[i];
effjs2 = effcorrect1[i - 1];
effjs3 = effcorrect1[i - 2];
}
else
{
qjs1 = effns1[i + 1];
qjs2 = effns1[i];
qjs3 = effns1[i - 1];
effjs1 = effcorrect1[i + 1];
effjs2 = effcorrect1[i];
effjs3 = effcorrect1[i - 1];
}
}
if (ns < 300 && ns > 210)
{
for (i = 0; effns2[i] <= ns; i++)
{
}
if (ns >= 220)
{
qjs1 = effns2[i];
qjs2 = effns2[i - 1];
qjs3 = effns2[i - 2];
effjs1 = effcorrect2[i];
effjs2 = effcorrect2[i - 1];
effjs3 = effcorrect2[i - 2];
}
else
{
qjs1 = effns2[i + 1];
qjs2 = effns2[i];
qjs3 = effns2[i - 1];
effjs1 = effcorrect2[i + 1];
effjs2 = effcorrect2[i];
effjs3 = effcorrect2[i - 1];
}
}
correct = (ns - qjs2) * (ns - qjs3) * effjs1 / ((qjs1 - qjs2) * (qjs1 - qjs3)) +
(ns - qjs1) * (ns - qjs3) * effjs2 / ((qjs2 - qjs1) * (qjs2 - qjs3)) +
(ns - qjs1) * (ns - qjs2) * effjs3 / ((qjs3 - qjs1) * (qjs3 - qjs2));
}
if (ns >= 300)
correct = 3.0;
if (ns < 20)
correct = 32.0;
if (ns >= 120 && ns <= 210)
correct = 0;
eff = eff - correct;
return eff;
}
//计算推荐NPSHr
public static double CalculateNPSHrByPumpType(double Q, double H, double n, int iPumpType)
{
double ns = CalculateNs(Q, H, n);
double S_Q = 10;
if (iPumpType == 3)
S_Q = Q / 2;
else
S_Q = Q;
double K = Math.Pow(ns, 1.3333) * 216 / 1000000;
return K * H;
}
#endregion
#region 计算比转速度
public static double CalculateNs(double Q, double H, double n)
{
return 3.65 * n * Math.Sqrt(Q / 3600) / Math.Pow(H, 0.75);
}
public static decimal CalculateNs(decimal Q, decimal H, decimal n)
{
return Convert.ToDecimal(3.65 * Convert.ToDouble(n) * Math.Sqrt(Convert.ToDouble(Q) / 3600) / Math.Pow(Convert.ToDouble(H), 0.75));
}
#endregion
#region 计算功率
///
/// 计算功率
///
/// 流量扬程点
/// 流量效率点
/// 流量功率点
public static List CalculateP(List qh_pt_list, List qe_pt_list)
{
if (qh_pt_list == null || qh_pt_list.Count() <= 2)
return null;
bool is_x_start_0 = qh_pt_list.First().X > 500 || qh_pt_list.First().X > qh_pt_list.Last().X * 0.2;
return CalculateP(qh_pt_list, qe_pt_list, Constant.WaterDensity, -1, is_x_start_0);
}
///
/// 计算功率
///
/// 流量扬程点
/// 流量效率点
/// 水的密度
/// 流量为0时的功率
/// 流量是否为0
///
public static List CalculateP(
List qh_pt_list,
List qe_pt_list,
double midu,
double zeroPower,
bool is_x_start_0)
{
if (qh_pt_list == null || qh_pt_list.Count < 3)
return null;
if (qe_pt_list == null || qe_pt_list.Count < 3)
return null;
var curve_qh = new Yw.Geometry.CubicSpline2d(qh_pt_list);
var curve_qe = new Yw.Geometry.CubicSpline2d(qe_pt_list);
var qp = CalculateP(curve_qh, curve_qe, midu, zeroPower, is_x_start_0);
return qp.GetPointList(qe_pt_list.Count());
}
///
/// 计算功率
///
/// 流量功率线拟合方式
/// 流量扬程线
/// 流量效率线
/// 水的密度
/// 流量为0时的功率
/// 流量是否为0
///
public static Yw.Geometry.CubicSpline2d CalculateP(Yw.Geometry.CubicSpline2d curve_qh, Yw.Geometry.CubicSpline2d curve_qe, double midu, double zeroPower, bool is_x_start_0)
{
if (curve_qh == null || curve_qe == null)
return null;
int point_count = 16;//点不能太多
var qh_pt_list = curve_qh.GetPointList(point_count);
if (qh_pt_list == null || qh_pt_list.Count < 3)
return null;
var qe_pt_list = curve_qe.GetPointList(point_count);
if (qe_pt_list == null || qe_pt_list.Count < 3)
return null;
List qp_pt_list = new List();
//间距
double min_flow = Math.Max(qh_pt_list.First().X, qe_pt_list.First().X);
double max_flow = Math.Min(qh_pt_list.Last().X, qe_pt_list.Last().X);
//
double Q, H, E, P;
double space = (max_flow - min_flow) / (point_count - 1);
//保证从0开始: 保证Q=0时,P不是计算出来的;
if (is_x_start_0)
{
for (int i = 5; i < point_count; i++)//前面几个点不要
{
Q = qe_pt_list.First().X + space * i;
E = curve_qe.GetPointY(Q);
H = curve_qh.GetPointY(Q);
if (H < 0.1 || E < 0.5)
continue;
P = CalculateP(Q, H, E, midu);
if (P < 2)
{
P = Math.Round(P, 3);
}
else if (P < 30)
{
P = Math.Round(P, 2);
}
else if (P < 100)
{
P = Math.Round(P, 1);
}
else
{
P = Math.Round(P, 0);
}
qp_pt_list.Add(new Yw.Geometry.Point2d(Q, P));
}
qp_pt_list = qp_pt_list.GetFitPointList(point_count);
if (qp_pt_list == null)
return null;
if (zeroPower > 0.1)
{
qp_pt_list.Insert(0, new Yw.Geometry.Point2d(0, zeroPower));
}
else
{
if (qp_pt_list[0].Y >= qp_pt_list[1].Y)
{
qp_pt_list[0].Y = qp_pt_list[1].Y * 0.95;
}
double startP = Yw.Geometry.LineHelper.GetYbyX(qp_pt_list[0].X, qp_pt_list[0].Y, qp_pt_list[1].X, qp_pt_list[1].Y, 0);
if (startP < 0.001)
startP = qp_pt_list[0].Y;
if (startP < 2)
{
startP = Math.Round(startP, 3);
}
else if (startP < 30)
{
startP = Math.Round(startP, 2);
}
else if (startP < 100)
{
startP = Math.Round(startP, 1);
}
else
{
startP = Math.Round(startP, 0);
}
qp_pt_list.Insert(0, new Yw.Geometry.Point2d(0, startP));
}
return new Yw.Geometry.CubicSpline2d(qp_pt_list);
}
else
{
for (int i = 0; i < point_count; i++)//前面几个点不要
{
Q = qe_pt_list.First().X + space * i;
E = curve_qe.GetPointY(Q);
H = curve_qh.GetPointY(Q);
if (H < 0.1 || E < 0.5)
continue;
P = CalculateP(Q, H, E, midu);
if (P < 2)
{
P = Math.Round(P, 3);
}
else if (P < 30)
{
P = Math.Round(P, 2);
}
else if (P < 100)
{
P = Math.Round(P, 1);
}
else
{
P = Math.Round(P, 0);
}
qp_pt_list.Add(new Yw.Geometry.Point2d(Q, P));
}
qp_pt_list = qp_pt_list.GetFitPointList(point_count);
if (qp_pt_list == null)
return null;
return new Yw.Geometry.CubicSpline2d(qp_pt_list);
}
}
#endregion
#region 计算效率
public static Yw.Geometry.CubicSpline2d CalculateE(Yw.Geometry.CubicSpline2d qh, Yw.Geometry.CubicSpline2d qp)
{
return CalculateE(qh, qp, Constant.WaterDensity);
}
public static Yw.Geometry.CubicSpline2d CalculateE(Yw.Geometry.CubicSpline2d qh, Yw.Geometry.CubicSpline2d qp, bool is_x_start_0)
{
return CalculateE(qh, qp, Constant.WaterDensity, is_x_start_0);
}
public static Yw.Geometry.CubicSpline2d CalculateE(Yw.Geometry.CubicSpline2d qh, Yw.Geometry.CubicSpline2d qp, double midu)
{
if (qh == null)
return null;
bool is_x_start_0 = true;
if (qh.MinX > 500 || qh.MinX > qh.MaxX * 0.1)
{
is_x_start_0 = false;
}
else
{
is_x_start_0 = true;
}
return CalculateE(qh, qp, midu, is_x_start_0);
}
public static Yw.Geometry.CubicSpline2d CalculateE(Yw.Geometry.CubicSpline2d qh, Yw.Geometry.CubicSpline2d qp, double midu, bool is_x_start_0)
{
if (qh == null)
return null;
if (qp == null)
return null;
int point_count = 12;
List qe_pt_list = new List();
List qp_pt_list = qp.GetPointList(point_count);
double Q, H, Eff, Power;
var fitCurve = new Yw.Geometry.CubicSpline2d(qh);
for (int i = 0; i < qp_pt_list.Count; i++)
{
Q = qp_pt_list[i].X;
Power = qp_pt_list[i].Y;
H = fitCurve.GetPointY(Q);
Eff = CalculateE(Q, H, Power, midu);
qe_pt_list.Add(new Yw.Geometry.Point2d(Q, Eff));
}
//保证Q=0时,Eff=0;
if (is_x_start_0)
{
qe_pt_list[0] = new Yw.Geometry.Point2d(0, 0);
qe_pt_list = qe_pt_list.GetFitPointList();
qe_pt_list = qe_pt_list.AmendByZeroPointY(qe_pt_list[3].X, 0);
return new Yw.Geometry.CubicSpline2d(qe_pt_list);
}
else
{
return new Yw.Geometry.CubicSpline2d(qe_pt_list);
}
}
public static List CalculateEpoint(
Yw.Geometry.CubicSpline2d qh,
Yw.Geometry.CubicSpline2d qp,
int point_count,
double midu)
{
if (qh == null)
return null;
if (qp == null)
return null;
List qe_pt_list = new List();
List qp_pt_list = qp.GetPointList(point_count);
double Q, H, Eff, Power;
var fitCurve = qh.Copy();
for (int i = 0; i < qp_pt_list.Count; i++)
{
Q = qp_pt_list[i].X;
Power = qp_pt_list[i].Y;
H = fitCurve.GetPointY(Q);
Eff = CalculateE(Q, H, Power, midu);
qe_pt_list.Add(new Yw.Geometry.Point2d(Q, Eff));
}
bool is_x_start_0 = true;
if (qe_pt_list.First().X > 500 || qe_pt_list.First().X > qe_pt_list.Last().X * 0.1)
{
is_x_start_0 = false;
}
else
{
is_x_start_0 = true;
}
//保证Q=0时,Eff=0;
if (is_x_start_0)
{
qe_pt_list[0] = new Yw.Geometry.Point2d(0, 0);
qe_pt_list = qe_pt_list.GetFitPointList();
return qe_pt_list.AmendByZeroPointY(qe_pt_list[3].X, 0);
}
else
{
return qe_pt_list.GetFitPointList();
}
}
///
/// 注意此方法 返回的点没有拟合
///
///
///
///
///
///
public static List CalculateE_AlignPointP(
List qh_pt_list,
List qp_pt_list,
double midu, bool is_x_start_0)
{
if (qh_pt_list == null || qh_pt_list.Count < 3)
return null;
if (qp_pt_list == null || qp_pt_list.Count < 3)
return null;
List qe_pt_list = new List();
if (qh_pt_list.IsEqualValueX(qp_pt_list))
{ //x都一致
for (int i = 0; i < qp_pt_list.Count; i++)
{
double Q, H, Eff, Power;
Q = qp_pt_list[i].X;
Power = qp_pt_list[i].Y;
H = qh_pt_list[i].Y;
Eff = CalculateE(Q, H, Power, midu);
qe_pt_list.Add(new Yw.Geometry.Point2d(Q, Eff));
}
}
else
{
var fitCurve_QP = new Yw.Geometry.CubicSpline2d(qp_pt_list);
var fitCurve_QH = new Yw.Geometry.CubicSpline2d(qh_pt_list);
for (int i = 0; i < qp_pt_list.Count; i++)
{
double Q, H, Eff, Power;
Q = qp_pt_list[i].X;
Power = fitCurve_QP.GetPointY(Q);
H = fitCurve_QH.GetPointY(Q);
Eff = CalculateE(Q, H, Power, midu);
qe_pt_list.Add(new Yw.Geometry.Point2d(Q, Eff));
}
}
//qe_pt_list = FitHelper.GetPointListByExtend(qe_pt_list);
//保证Q=0时,Eff=0;
if (is_x_start_0)
{
qe_pt_list[0] = new Yw.Geometry.Point2d(0, 0);
}
return qe_pt_list;
}
#endregion
#region 功率效率换算
///
/// 计算效率 对其功率
///
public static List CalculateELineByP(List qh_pt_list, List qp_pt_list, bool is_x_start_0)
{
if (qh_pt_list == null || qh_pt_list.Count < 3)
{
return null;
}
if (qp_pt_list == null || qp_pt_list.Count < 3)
{
return null;
}
List list = new List();
if (qh_pt_list.IsEqualValueX(qp_pt_list))
{
for (int i = 0; i < qp_pt_list.Count; i++)
{
double x = qp_pt_list[i].X;
double y = qp_pt_list[i].Y;
double y2 = qh_pt_list[i].Y;
double y3 = CalculateE(x, y2, y, Constant.WaterDensity);
list.Add(new Yw.Geometry.Point2d(x, y3));
}
}
else
{
var qp = new Yw.Geometry.CubicSpline2d(qp_pt_list);
var qh = new Yw.Geometry.CubicSpline2d(qh_pt_list);
for (int j = 0; j < qp_pt_list.Count; j++)
{
double x2 = qp_pt_list[j].X;
double fit_pointY = qp.GetPointY(x2);
double fit_pointY2 = qh.GetPointY(x2);
double y4 = CalculateE(x2, fit_pointY2, fit_pointY, Constant.WaterDensity);
list.Add(new Yw.Geometry.Point2d(x2, y4));
}
}
if (is_x_start_0)
{
list[0] = new Yw.Geometry.Point2d(0, 0);
}
return list;
}
///
/// 计算效率 对其效率
///
public static List CalculateP_AlignPointE(List qh_pt_list, List qe_pt_list, double midu, double ref_zero_power, bool is_x_start_0)
{
if (qh_pt_list == null || qh_pt_list.Count < 3)
{
return null;
}
if (qe_pt_list == null || qe_pt_list.Count < 3)
{
return null;
}
List list = new List();
if (qh_pt_list.IsEqualValueX(qe_pt_list))
{
for (int i = 0; i < qe_pt_list.Count(); i++)
{
double x = qe_pt_list[i].X;
double y = qe_pt_list[i].Y;
double y2 = qh_pt_list[i].Y;
if (!(y2 < 0.1) && !(y < 0.5))
{
double num = CalculateP(x, y2, y, midu);
num = ((num < 2.0) ? Math.Round(num, 3) : ((num < 30.0) ? Math.Round(num, 2) : ((!(num < 100.0)) ? Math.Round(num, 0) : Math.Round(num, 1))));
list.Add(new Yw.Geometry.Point2d(x, num));
}
}
}
else
{
var qe = new Yw.Geometry.CubicSpline2d(qe_pt_list);
var qh = new Yw.Geometry.CubicSpline2d(qh_pt_list);
for (int j = 0; j < qe_pt_list.Count(); j++)
{
double x2 = qe_pt_list[j].X;
double fit_pointY = qe.GetPointY(x2);
double fit_pointY2 = qh.GetPointY(x2);
if (!(fit_pointY2 < 0.09) && !(fit_pointY < 0.5))
{
double num2 = CalculateP(x2, fit_pointY2, fit_pointY, midu);
num2 = ((num2 < 2.0) ? Math.Round(num2, 3) : ((num2 < 30.0) ? Math.Round(num2, 2) : ((!(num2 < 100.0)) ? Math.Round(num2, 0) : Math.Round(num2, 1))));
list.Add(new Yw.Geometry.Point2d(x2, num2));
}
}
}
if (is_x_start_0)
{
if (list[0].X < 1.0)
{
if (ref_zero_power > 0.0)
{
list[0].X = 0.0;
list[0].Y = ref_zero_power;
}
else
{
list.RemoveAt(0);
var fit_points = list.GetFitPointList();
if (fit_points[0].Y >= fit_points[1].Y)
{
fit_points[0].Y = fit_points[1].Y * 0.95;
}
double num3 = Yw.Geometry.LineHelper.GetYbyX(fit_points[0].X, fit_points[0].Y, fit_points[1].X, fit_points[1].Y, 0.0);
if (num3 < 0.001)
{
num3 = fit_points[0].Y;
}
num3 = ((num3 < 2.0) ? Math.Round(num3, 3) : ((num3 < 30.0) ? Math.Round(num3, 2) : ((!(num3 < 100.0)) ? Math.Round(num3, 0) : Math.Round(num3, 1))));
list.Insert(0, new Yw.Geometry.Point2d(0.0, num3));
}
}
else if (ref_zero_power > 0.0)
{
list.Insert(0, new Yw.Geometry.Point2d(0.0, ref_zero_power));
}
else
{
var fit_points2 = list.GetFitPointList();
if (fit_points2[0].Y >= fit_points2[1].Y)
{
fit_points2[0].Y = fit_points2[1].Y * 0.95;
}
double num4 = Yw.Geometry.LineHelper.GetYbyX(fit_points2[0].X, fit_points2[0].Y, fit_points2[1].X, fit_points2[1].Y, 0.0);
if (num4 < 0.001)
{
num4 = fit_points2[0].Y;
}
num4 = ((num4 < 2.0) ? Math.Round(num4, 3) : ((num4 < 30.0) ? Math.Round(num4, 2) : ((!(num4 < 100.0)) ? Math.Round(num4, 0) : Math.Round(num4, 1))));
list.Insert(0, new Yw.Geometry.Point2d(0.0, num4));
}
}
return list;
}
#endregion
#endregion
#region 曲线与H=K*Q^i的交点
///
/// 根据相似点设置相似曲线,相似点(选择点)的x:流量y:杨程
///
public static double GetSimuValue(Yw.Geometry.CubicSpline2d cubic_spline, Yw.Geometry.Point2d simular_pt, double origin_value, double extend_ratio = 1)
{
if (cubic_spline == null)
return -3;
if (simular_pt.X < 0.1 || simular_pt.Y < 0.1)
return -2;
if (simular_pt.X > cubic_spline.MaxX * extend_ratio * 1.5)
return -4;
Yw.Geometry.Point2d sect_pt = GetSectPoint(cubic_spline, simular_pt, extend_ratio);
if (sect_pt == null || sect_pt.IsZeroPoint())
return -5;
//计算相似点的转速/直径
return CalculateSimuByH(origin_value, sect_pt.Y, simular_pt.Y);
}
//ratioIgnore:作用 当simularPoint超出曲线范围时,曲线扩大的倍数
public static Yw.Geometry.Point2d GetSectPoint(Yw.Geometry.CubicSpline2d cubic_spline, Yw.Geometry.Point2d simular_pt, double ratioIgnore)
{
return GetSectPointGeneral(cubic_spline, simular_pt, 2, ratioIgnore);
}
public static Yw.Geometry.Point2d GetSectPointParabola(Yw.Geometry.CubicSpline2d cubic_spline, Yw.Geometry.Point2d simular_pt)
{
var sect_pt = new Yw.Geometry.Point2d(0, 0);
if (cubic_spline == null)
return sect_pt;
var pt_list = cubic_spline.GetPointListByXRatioRange(1, 1.2, 50);
return GetSectPointParabola(pt_list, simular_pt);
}
//通过点simular_pt和点(0,0)的直线,与曲线Curve的交点(没有,返回Point(0,0))
public static Yw.Geometry.Point2d GetSectPointLine(List CurvePoints, Yw.Geometry.Point2d simular_pt)
{
Yw.Geometry.Point2d sect_pt = new Yw.Geometry.Point2d(0, 0);
if (CurvePoints == null || CurvePoints.Count < 2)
return sect_pt;
//计算直线的K
if (simular_pt.X < 1)
return sect_pt;
double a = simular_pt.Y / simular_pt.X;
if (a < 0.0001)
return sect_pt;
//与2点连成直线的交点,判断交点是否在2点之间,即可是曲线的交点
double b, c;
double x;
for (int i = 0; i < CurvePoints.Count - 1; i++)
{
LineHelper.GetKandB(CurvePoints[i], CurvePoints[i + 1], out b, out c);
/*解方程
* y=ax
* y=bx+c
*/
if (Math.Abs(a - b) < 0.001)
continue;
x = c / (a - b);
if (UtilsHelper.IsMiddle(CurvePoints[i].X, CurvePoints[i + 1].X, x))
{
sect_pt.X = x;
sect_pt.Y = a * x;
return sect_pt;
}
}
return sect_pt;
}
//通过点simular_pt和点(0,0)的抛物线,与曲线Curve的交点(没有,返回Point(0,0))
//曲线公式:H=K*Q^2
public static Yw.Geometry.Point2d GetSectPointParabola(List pt_list, Yw.Geometry.Point2d simular_pt)
{
return ParabolaCurveHelper.GetSectPoint(pt_list, simular_pt, 0);
}
public static Yw.Geometry.Point2d GetSectPointLine(this Yw.Geometry.CubicSpline2d cubic_spline, Yw.Geometry.Point2d simular_pt)
{
Yw.Geometry.Point2d sect_pt = new Yw.Geometry.Point2d(0, 0);
if (cubic_spline == null)
return sect_pt;
//计算直线的K
if (simular_pt.X < 1)
return sect_pt;
double a = simular_pt.Y / simular_pt.X;
if (a < 0.0001)
return sect_pt;
//点越多越精确
return GetSectPointLine(cubic_spline.GetPointList(100), simular_pt);
}
//曲线H=K*Q^i 与曲线Curve的交点(没有,返回Point(0,0))
public static Yw.Geometry.Point2d GetSectPointGeneral(List pt_list, Yw.Geometry.Point2d simular_pt, double index)
{
Yw.Geometry.Point2d sect_pt = new Yw.Geometry.Point2d(0, 0);
if (pt_list == null || pt_list.Count < 2)
return sect_pt;
if (simular_pt.X < 0.1)
return sect_pt;
if (Math.Abs(index - 1) < 0.01)
return GetSectPointLine(pt_list, simular_pt);
if (Math.Abs(index - 2) < 0.01)
return GetSectPointParabola(pt_list, simular_pt);
//计算系数K
double fixK = simular_pt.Y / Math.Pow(simular_pt.X, index);
if (fixK < 0.000001)
return sect_pt;
//思路是从simular_pt开始逐个增加0.1,直到k值最接近fixK
double space = (pt_list.Last().X - simular_pt.X) / 1200;
double x = simular_pt.X;
double y, k;
do
{
x = x + space;
y = 0;
var y_pt_list = pt_list.GetInterPointsY(x);
if (y_pt_list == null || !y_pt_list.Any())
{
break;
}
y = y_pt_list.Last();
k = y / Math.Pow(x, index);
} while (k > fixK);
sect_pt.X = x;
sect_pt.Y = y;
return sect_pt;
}
//ratioIgnore:作用 当simular_pt超出范围时,扩大的倍数
public static Yw.Geometry.Point2d GetSectPointGeneral(this Yw.Geometry.CubicSpline2d cubic_spline, Yw.Geometry.Point2d simular_pt, double index, double ratioIgnore)
{
Yw.Geometry.Point2d sect_pt = new Yw.Geometry.Point2d(0, 0);
if (cubic_spline == null)
return sect_pt;
if (simular_pt.X < 1)
return sect_pt;
var cubic_spline_ex = cubic_spline.Copy();
//检查是否在曲线的区域范围内
double max_flow = cubic_spline_ex.MaxX;
double max_head = cubic_spline_ex.GetPointY(max_flow);
double k1 = max_head / Math.Pow(max_flow, index);
double k2 = simular_pt.Y / Math.Pow(simular_pt.X, index);
if (k1 > k2)
{
cubic_spline_ex.MaxX = cubic_spline_ex.MaxX * ratioIgnore;//放大1.2倍
}
if (Math.Abs(index - 1) < 0.01)
return GetSectPointLine(cubic_spline_ex, simular_pt);
if (Math.Abs(index - 2) < 0.01)
return GetSectPointParabola(cubic_spline_ex, simular_pt);
//计算系数K
double fixK = simular_pt.Y / Math.Pow(simular_pt.X, index);
if (fixK < 0.000001)
return sect_pt;
//思路是从simular_pt开始逐个增加0.1,直到k值最接近fixK
double space = (cubic_spline_ex.MaxX - simular_pt.X) / 1000;
double x = simular_pt.X;
double y, k;
do
{
x = x + space;
y = cubic_spline_ex.GetPointY(x);
k = y / Math.Pow(x, index);
} while (k > fixK);
sect_pt.X = x;
sect_pt.Y = y;
return sect_pt;
}
#endregion 曲线与H=K*Q^i的交点 protect类型,给子类调用,怎么覆盖GetSectPoint
}
}