using MembranePoreTester.Models; using System; using System.Collections.Generic; using System.IO; using System.Linq; namespace MembranePoreTester.Helpers { public static class PoreDistributionAnalysis { //public static double CalculateAveragePore( // IEnumerable points, // string unit, // TestLiquid liquid) //{ // var sorted = points.OrderBy(p => p.Pressure).ToList(); // if (sorted.Count < 2) return 0; // double[] pressures = sorted.Select(p => p.Pressure).ToArray(); // double[] dryFlows = sorted.Select(p => p.DryFlow).ToArray(); // double[] wetFlows = sorted.Select(p => p.WetFlow).ToArray(); // double halfDryFlow = dryFlows.Max() / 2.0; // // 找到湿膜流量等于 halfDryFlow 的压力(交点) // for (int i = 0; i < wetFlows.Length - 1; i++) // { // if ((wetFlows[i] <= halfDryFlow && wetFlows[i + 1] >= halfDryFlow) || // (wetFlows[i] >= halfDryFlow && wetFlows[i + 1] <= halfDryFlow)) // { // double p = Interpolation.Linear( // new[] { wetFlows[i], wetFlows[i + 1] }, // new[] { pressures[i], pressures[i + 1] }, // halfDryFlow); // return PoreCalculator.PressureToPore(p, unit, liquid); // } // } // return 0; //} //public static double CalculateAveragePore( // IEnumerable points, // string unit, // TestLiquid liquid) //{ // var sorted = points.OrderBy(p => p.Pressure).ToList(); // if (sorted.Count < 2) return 0; // double[] pressures = sorted.Select(p => p.Pressure).ToArray(); // double[] wetFlows = sorted.Select(p => p.WetFlow).ToArray(); // double[] dryFlows = sorted.Select(p => p.DryFlow).ToArray(); // // 日志文件路径(位于程序运行目录) // string logPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "PoreCalcLog.txt"); // void Log(string msg) // { // try // { // File.AppendAllText(logPath, $"{DateTime.Now:yyyy-MM-dd HH:mm:ss.fff} - {msg}{Environment.NewLine}"); // } // catch { /* 忽略日志写入错误,不影响主流程 */ } // } // Log($"开始计算平均孔径,数据点数={sorted.Count},单位={unit},液体={liquid.Name},表面张力={liquid.SurfaceTension}"); // for (int i = 0; i < pressures.Length - 1; i++) // { // double diff1 = wetFlows[i] - dryFlows[i]; // double diff2 = wetFlows[i + 1] - dryFlows[i + 1]; // Log($"区间{i}: 压力=[{pressures[i]}, {pressures[i + 1]}], 湿膜=[{wetFlows[i]}, {wetFlows[i + 1]}], 干膜=[{dryFlows[i]}, {dryFlows[i + 1]}], diff1={diff1}, diff2={diff2}"); // // 检查是否异号或其中之一为零 // if (diff1 * diff2 < 0 || Math.Abs(diff1) < 1e-8 || Math.Abs(diff2) < 1e-8) // { // double p; // if (Math.Abs(diff1) < 1e-8) // { // p = pressures[i]; // Log($"直接命中点i,压力={p}"); // } // else if (Math.Abs(diff2) < 1e-8) // { // p = pressures[i + 1]; // Log($"直接命中点i+1,压力={p}"); // } // else // { // double t = -diff1 / (diff2 - diff1); // t 在 0~1 之间 // p = pressures[i] + t * (pressures[i + 1] - pressures[i]); // Log($"线性插值: t={t}, 交点压力={p}"); // } // if (p > 0) // { // double pore = PoreCalculator.PressureToPore(p, unit, liquid); // Log($"平均孔径计算结果: 交点压力={p} {unit}, 孔径={pore} μm"); // return pore; // } // } // } // Log("未找到湿膜与干膜曲线的交点"); // return 0; //} public static double CalculateAveragePore( IEnumerable points, string unit, TestLiquid liquid) { var sorted = points.OrderBy(p => p.Pressure).ToList(); if (sorted.Count < 2) return 0; double[] pressures = sorted.Select(p => p.Pressure).ToArray(); double[] wetFlows = sorted.Select(p => p.WetFlow).ToArray(); double[] dryFlows = sorted.Select(p => p.DryFlow).ToArray(); // 日志记录 string logPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "PoreCalcLog.txt"); void Log(string msg) { try { File.AppendAllText(logPath, $"{DateTime.Now:yyyy-MM-dd HH:mm:ss.fff} - {msg}{Environment.NewLine}"); } catch { } } Log($"开始计算平均孔径,数据点数={sorted.Count}"); for (int i = 0; i < pressures.Length - 1; i++) { // 跳过干膜流量为0的点(避免虚假交点) if (dryFlows[i] == 0 || dryFlows[i + 1] == 0) continue; double diff1 = wetFlows[i] - dryFlows[i]; double diff2 = wetFlows[i + 1] - dryFlows[i + 1]; Log($"区间{i}: P=[{pressures[i]}, {pressures[i + 1]}], diff1={diff1}, diff2={diff2}"); if (diff1 * diff2 < 0 || Math.Abs(diff1) < 1e-8 || Math.Abs(diff2) < 1e-8) { double p; if (Math.Abs(diff1) < 1e-8) p = pressures[i]; else if (Math.Abs(diff2) < 1e-8) p = pressures[i + 1]; else { double t = -diff1 / (diff2 - diff1); p = pressures[i] + t * (pressures[i + 1] - pressures[i]); } Log($"找到交点: 压力={p} Pa"); double pore = PoreCalculator.PressureToPore(p, unit, liquid); Log($"平均孔径={pore} μm"); return pore; } } Log("未找到有效交点"); return 0; } private static void Log(string message) { try { string path = Path.Combine(Directory.GetCurrentDirectory(), "PoreDistributionAnalysis.log"); File.AppendAllText(path, DateTime.Now.ToString("o") + " " + message + Environment.NewLine); } catch { } } public static double CalculatePoreRangePercentage( IEnumerable points, string unit, TestLiquid liquid, double lowerPore, double upperPore) { var sorted = points.OrderBy(p => p.Pressure).ToList(); if (sorted.Count < 2) return 0; // 提取有效点(流量 > 0) var wetValid = sorted.Where(p => p.WetFlow > 0).Select(p => (Pressure: p.Pressure, Flow: p.WetFlow)).ToList(); var dryValid = sorted.Where(p => p.DryFlow > 0).Select(p => (Pressure: p.Pressure, Flow: p.DryFlow)).ToList(); if (wetValid.Count < 2 || dryValid.Count < 2) return 0; // 有效压力重叠区间 double minPressure = Math.Max(wetValid.First().Pressure, dryValid.First().Pressure); double maxPressure = Math.Min(wetValid.Last().Pressure, dryValid.Last().Pressure); if (minPressure >= maxPressure) return 0; // 孔径转压力 double pLower = PoreCalculator.PoreToPressure(upperPore, unit, liquid); double pUpper = PoreCalculator.PoreToPressure(lowerPore, unit, liquid); pLower = Math.Max(pLower, minPressure); pUpper = Math.Min(pUpper, maxPressure); if (pUpper <= pLower) return 0; // 在有效点集上插值 double qWetLower = InterpolateOnValid(wetValid, pLower); double qDryLower = InterpolateOnValid(dryValid, pLower); double qWetUpper = InterpolateOnValid(wetValid, pUpper); double qDryUpper = InterpolateOnValid(dryValid, pUpper); if (qDryLower <= 0 || qDryUpper <= 0) return 0; double ratioLow = qWetLower / qDryLower; double ratioHigh = qWetUpper / qDryUpper; double result = (ratioHigh - ratioLow) * 100; return result < 0 ? 0 : result; } // 辅助插值函数:基于有效点列表(已按压力升序) private static double InterpolateOnValid(List<(double Pressure, double Flow)> validPoints, double pressure) { if (validPoints.Count == 0) return 0; if (pressure <= validPoints[0].Pressure) return validPoints[0].Flow; if (pressure >= validPoints[^1].Pressure) return validPoints[^1].Flow; for (int i = 0; i < validPoints.Count - 1; i++) { if (pressure >= validPoints[i].Pressure && pressure <= validPoints[i + 1].Pressure) { double p1 = validPoints[i].Pressure; double f1 = validPoints[i].Flow; double p2 = validPoints[i + 1].Pressure; double f2 = validPoints[i + 1].Flow; return f1 + (f2 - f1) * (pressure - p1) / (p2 - p1); } } return 0; } } }