This commit is contained in:
@@ -1,42 +1,134 @@
|
||||
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<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 CalculateAveragePore(
|
||||
IEnumerable<DataPoint> points,
|
||||
string unit,
|
||||
TestLiquid liquid)
|
||||
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[] dryFlows = sorted.Select(p => p.DryFlow).ToArray();
|
||||
|
||||
double halfDryFlow = dryFlows.Max() / 2.0;
|
||||
|
||||
// 找到湿膜流量等于 halfDryFlow 的压力(交点)
|
||||
for (int i = 0; i < wetFlows.Length - 1; i++)
|
||||
// 寻找湿膜流量曲线与干膜流量曲线的所有交点(直接相交),记录交点压力及对应的插值干膜流量
|
||||
var intersections = new List<(double Pressure, double DryFlowAtP)>();
|
||||
const double eps = 1e-12;
|
||||
for (int i = 0; i < pressures.Length - 1; i++)
|
||||
{
|
||||
if ((wetFlows[i] <= halfDryFlow && wetFlows[i + 1] >= halfDryFlow) ||
|
||||
(wetFlows[i] >= halfDryFlow && wetFlows[i + 1] <= halfDryFlow))
|
||||
double diff1 = wetFlows[i] - dryFlows[i];
|
||||
double diff2 = wetFlows[i + 1] - dryFlows[i + 1];
|
||||
// 检查差值是否异号或为零(表示相交)
|
||||
if (diff1 * diff2 <= 0 && diff1 != diff2)
|
||||
{
|
||||
double p = Interpolation.Linear(
|
||||
new[] { wetFlows[i], wetFlows[i + 1] },
|
||||
new[] { pressures[i], pressures[i + 1] },
|
||||
halfDryFlow);
|
||||
return PoreCalculator.PressureToPore(p, unit, liquid);
|
||||
double p;
|
||||
if (Math.Abs(diff1) < eps)
|
||||
{
|
||||
p = pressures[i];
|
||||
}
|
||||
else if (Math.Abs(diff2) < eps)
|
||||
{
|
||||
p = pressures[i + 1];
|
||||
}
|
||||
else
|
||||
{
|
||||
double p0 = pressures[i];
|
||||
double p1 = pressures[i + 1];
|
||||
if (Math.Abs(diff2 - diff1) < eps)
|
||||
continue;
|
||||
p = p0 + (p1 - p0) * (0 - diff1) / (diff2 - diff1);
|
||||
}
|
||||
|
||||
if (p <= 0) continue;
|
||||
|
||||
// 线性插值计算交点处的干膜流量
|
||||
double dryAtP;
|
||||
{
|
||||
double d0 = dryFlows[i];
|
||||
double d1 = dryFlows[i + 1];
|
||||
double p0 = pressures[i];
|
||||
double p1 = pressures[i + 1];
|
||||
if (Math.Abs(p1 - p0) < eps)
|
||||
dryAtP = d0;
|
||||
else
|
||||
dryAtP = d0 + (d1 - d0) * (p - p0) / (p1 - p0);
|
||||
}
|
||||
|
||||
intersections.Add((p, dryAtP));
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
|
||||
if (intersections.Count == 0)
|
||||
return 0;
|
||||
|
||||
// 如果存在多个交点,默认选择压力最小(靠近低压区的第一个交点)
|
||||
var chosen = intersections.OrderBy(x => x.Pressure).First();
|
||||
|
||||
// 将调试信息写入日志文件,便于在非 VS 环境下查看计算过程
|
||||
try
|
||||
{
|
||||
Log($"PoreDistributionAnalysis: unit={unit}, liquid.C_Pa={liquid?.C_Pa}");
|
||||
foreach (var it in intersections)
|
||||
Log($"intersection: P={it.Pressure}, dryAtP={it.DryFlowAtP}");
|
||||
Log($"chosen intersection: P={chosen.Pressure}");
|
||||
double pore = PoreCalculator.PressureToPore(chosen.Pressure, unit, liquid);
|
||||
Log($"calculated pore={pore}");
|
||||
return pore;
|
||||
}
|
||||
catch
|
||||
{
|
||||
try { return PoreCalculator.PressureToPore(chosen.Pressure, unit, liquid); } catch { 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(
|
||||
|
||||
@@ -44,7 +44,7 @@ namespace MembranePoreTester.ViewModels
|
||||
|
||||
public IReadOnlyList<TestLiquid> Liquids => TestLiquid.Predefined;
|
||||
public List<string> PressureUnits => new() { "Pa", "cmHg", "psi" };
|
||||
public List<string> MembraneTypes => new() { "平板膜", "中空纤维膜" };
|
||||
public List<string> MembraneTypes => new() { "中空纤维膜" };
|
||||
|
||||
public TestLiquid SelectedLiquid
|
||||
{
|
||||
|
||||
@@ -260,7 +260,7 @@ namespace MembranePoreTester.ViewModels
|
||||
|
||||
public IReadOnlyList<TestLiquid> Liquids => TestLiquid.Predefined;
|
||||
public List<string> PressureUnits => new() { "Pa", "cmHg", "psi" };
|
||||
public List<string> MembraneTypes => new() { "平板膜", "中空纤维膜" };
|
||||
public List<string> MembraneTypes => new() { "中空纤维膜" };
|
||||
|
||||
public TestLiquid SelectedLiquid
|
||||
{
|
||||
@@ -1208,7 +1208,7 @@ namespace MembranePoreTester.ViewModels
|
||||
model.Axes.Add(new LinearAxis
|
||||
{
|
||||
Position = AxisPosition.Bottom,
|
||||
Title = "压力 (kPa)",
|
||||
Title = "压力 (Pa)",
|
||||
TitleFontSize = 12
|
||||
});
|
||||
model.Axes.Add(new LinearAxis
|
||||
|
||||
@@ -293,7 +293,7 @@
|
||||
<TextBox Text="{Binding UpperPore}" Width="48" Margin="1"/>
|
||||
<TextBlock Text="μm" VerticalAlignment="Center" Margin="2,0,5,0"/>
|
||||
<Button Content="计算" Command="{Binding CalculateCommand}" Margin="2,0" Padding="8,5" Background="#2196F3" Click="Button_Click"/>
|
||||
<TextBlock Text="{Binding RangePercentage, StringFormat={}{0:F3}%}" FontSize="14" FontWeight="Bold" VerticalAlignment="Center" Margin="5,0" Foreground="#4CAF50"/>
|
||||
<TextBlock Text="{Binding RangePercentage, StringFormat={}{0:F2}%}" FontSize="14" FontWeight="Bold" VerticalAlignment="Center" Margin="5,0" Foreground="#4CAF50"/>
|
||||
</StackPanel>
|
||||
</GroupBox>
|
||||
<Separator Style="{StaticResource {x:Static ToolBar.SeparatorStyleKey}}" Margin="3,0"/>
|
||||
|
||||
Reference in New Issue
Block a user