Files
VacuumPressureMembranePoreS…/Helpers/PoreDistributionAnalysis.cs
2026-04-11 20:47:41 +08:00

106 lines
4.2 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using MembranePoreTester.Models;
using System.Collections.Generic;
using System.Linq;
namespace MembranePoreTester.Helpers
{
public static class PoreDistributionAnalysis
{
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;
}
public static double CalculatePoreRangePercentage(
IEnumerable<DataPoint> 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;
}
}
}