2026-02-27 16:03:49 +08:00
|
|
|
|
using MembranePoreTester.Models;
|
2026-04-13 22:45:22 +08:00
|
|
|
|
using System;
|
2026-02-27 16:03:49 +08:00
|
|
|
|
using System.Collections.Generic;
|
2026-04-13 22:45:22 +08:00
|
|
|
|
using System.IO;
|
2026-02-27 16:03:49 +08:00
|
|
|
|
using System.Linq;
|
|
|
|
|
|
|
|
|
|
|
|
namespace MembranePoreTester.Helpers
|
|
|
|
|
|
{
|
|
|
|
|
|
public static class PoreDistributionAnalysis
|
|
|
|
|
|
{
|
2026-04-13 22:45:22 +08:00
|
|
|
|
//public static double CalculateAveragePore(
|
|
|
|
|
|
// IEnumerable<DataPoint> 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;
|
|
|
|
|
|
//}
|
2026-04-14 23:16:56 +08:00
|
|
|
|
//public static double CalculateAveragePore(
|
|
|
|
|
|
// IEnumerable<DataPoint> 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;
|
|
|
|
|
|
//}
|
2026-04-13 22:45:22 +08:00
|
|
|
|
|
2026-02-27 16:03:49 +08:00
|
|
|
|
public static double CalculateAveragePore(
|
2026-04-13 22:45:22 +08:00
|
|
|
|
IEnumerable<DataPoint> points,
|
|
|
|
|
|
string unit,
|
|
|
|
|
|
TestLiquid liquid)
|
2026-02-27 16:03:49 +08:00
|
|
|
|
{
|
|
|
|
|
|
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();
|
2026-04-13 22:45:22 +08:00
|
|
|
|
double[] dryFlows = sorted.Select(p => p.DryFlow).ToArray();
|
2026-02-27 16:03:49 +08:00
|
|
|
|
|
2026-04-14 23:16:56 +08:00
|
|
|
|
// 日志记录
|
|
|
|
|
|
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}");
|
2026-04-14 21:40:09 +08:00
|
|
|
|
|
2026-04-13 22:45:22 +08:00
|
|
|
|
for (int i = 0; i < pressures.Length - 1; i++)
|
2026-02-27 16:03:49 +08:00
|
|
|
|
{
|
2026-04-14 23:16:56 +08:00
|
|
|
|
// 跳过干膜流量为0的点(避免虚假交点)
|
|
|
|
|
|
if (dryFlows[i] == 0 || dryFlows[i + 1] == 0)
|
2026-04-14 21:40:09 +08:00
|
|
|
|
continue;
|
|
|
|
|
|
|
2026-04-13 22:45:22 +08:00
|
|
|
|
double diff1 = wetFlows[i] - dryFlows[i];
|
|
|
|
|
|
double diff2 = wetFlows[i + 1] - dryFlows[i + 1];
|
2026-04-14 23:16:56 +08:00
|
|
|
|
|
|
|
|
|
|
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)
|
2026-02-27 16:03:49 +08:00
|
|
|
|
{
|
2026-04-13 22:45:22 +08:00
|
|
|
|
double p;
|
2026-04-14 23:16:56 +08:00
|
|
|
|
if (Math.Abs(diff1) < 1e-8)
|
2026-04-13 22:45:22 +08:00
|
|
|
|
p = pressures[i];
|
2026-04-14 23:16:56 +08:00
|
|
|
|
else if (Math.Abs(diff2) < 1e-8)
|
2026-04-13 22:45:22 +08:00
|
|
|
|
p = pressures[i + 1];
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
2026-04-14 23:16:56 +08:00
|
|
|
|
double t = -diff1 / (diff2 - diff1);
|
|
|
|
|
|
p = pressures[i] + t * (pressures[i + 1] - pressures[i]);
|
2026-04-13 22:45:22 +08:00
|
|
|
|
}
|
2026-04-14 23:16:56 +08:00
|
|
|
|
Log($"找到交点: 压力={p} Pa");
|
|
|
|
|
|
double pore = PoreCalculator.PressureToPore(p, unit, liquid);
|
|
|
|
|
|
Log($"平均孔径={pore} μm");
|
|
|
|
|
|
return pore;
|
2026-02-27 16:03:49 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-04-14 23:16:56 +08:00
|
|
|
|
Log("未找到有效交点");
|
2026-04-14 21:40:09 +08:00
|
|
|
|
return 0;
|
2026-04-13 22:45:22 +08:00
|
|
|
|
}
|
|
|
|
|
|
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 { }
|
|
|
|
|
|
}
|
2026-04-11 20:47:41 +08:00
|
|
|
|
|
|
|
|
|
|
|
2026-02-27 16:03:49 +08:00
|
|
|
|
public static double CalculatePoreRangePercentage(
|
2026-04-11 20:47:41 +08:00
|
|
|
|
IEnumerable<DataPoint> points,
|
|
|
|
|
|
string unit,
|
|
|
|
|
|
TestLiquid liquid,
|
|
|
|
|
|
double lowerPore,
|
|
|
|
|
|
double upperPore)
|
2026-02-27 16:03:49 +08:00
|
|
|
|
{
|
|
|
|
|
|
var sorted = points.OrderBy(p => p.Pressure).ToList();
|
|
|
|
|
|
if (sorted.Count < 2) return 0;
|
|
|
|
|
|
|
2026-04-11 20:47:41 +08:00
|
|
|
|
// 提取有效点(流量 > 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;
|
2026-02-27 16:03:49 +08:00
|
|
|
|
|
2026-04-11 20:47:41 +08:00
|
|
|
|
// 孔径转压力
|
2026-02-27 16:03:49 +08:00
|
|
|
|
double pLower = PoreCalculator.PoreToPressure(upperPore, unit, liquid);
|
|
|
|
|
|
double pUpper = PoreCalculator.PoreToPressure(lowerPore, unit, liquid);
|
|
|
|
|
|
|
2026-04-11 20:47:41 +08:00
|
|
|
|
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;
|
2026-02-27 16:03:49 +08:00
|
|
|
|
|
|
|
|
|
|
double ratioLow = qWetLower / qDryLower;
|
|
|
|
|
|
double ratioHigh = qWetUpper / qDryUpper;
|
2026-04-11 20:47:41 +08:00
|
|
|
|
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;
|
2026-02-27 16:03:49 +08:00
|
|
|
|
|
2026-04-11 20:47:41 +08:00
|
|
|
|
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;
|
2026-02-27 16:03:49 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|