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 /// 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 } }