干度2的计算和多日期历史数据的选择的增加

This commit is contained in:
2025-11-27 18:09:57 +08:00
parent b9085c4a93
commit 231801ccc3
4 changed files with 262 additions and 42 deletions

View File

@@ -93,12 +93,19 @@ namespace CapMachine.Wpf.Services
{ {
LiqRefFlowTag = LiqRefFlowShortTag!; LiqRefFlowTag = LiqRefFlowShortTag!;
} }
//kg/h //kg/h
if (TagManager.TryGetShortTagByName("冷媒流量[kg/h]", out ShortValueTag? VRVShortTag)) if (TagManager.TryGetShortTagByName("冷媒流量[kg/h]", out ShortValueTag? VRVShortTag))
{ {
VRVTag = VRVShortTag!; VRVTag = VRVShortTag!;
} }
//润滑油流量
if (TagManager.TryGetShortTagByName("润滑油流量[kg/h]", out ShortValueTag? LubeFlowShortTag))
{
LubeFlowTag = LubeFlowShortTag!;
}
// 气路阀前 P/T用于质量流量加权混合焓的计算LabVIEW 流程) // 气路阀前 P/T用于质量流量加权混合焓的计算LabVIEW 流程)
if (TagManager.TryGetShortTagByName("气路阀前压力[BarA]", out ShortValueTag? gasPreP)) if (TagManager.TryGetShortTagByName("气路阀前压力[BarA]", out ShortValueTag? gasPreP))
{ {
@@ -185,6 +192,15 @@ namespace CapMachine.Wpf.Services
/// </summary> /// </summary>
public ShortValueTag DrynessTag { get; set; } public ShortValueTag DrynessTag { get; set; }
private double _DrynessTag2Value;
/// <summary>
/// 干度2无量纲 [-]
/// </summary>
public double DrynessTag2Value
{
get { return _DrynessTag2Value; }
set { _DrynessTag2Value = value; RaisePropertyChanged(); }
}
/// <summary> /// <summary>
/// 气路阀前压力BarA /// 气路阀前压力BarA
@@ -207,6 +223,10 @@ namespace CapMachine.Wpf.Services
/// </summary> /// </summary>
public ShortValueTag LiqRefFlowTag { get; set; } public ShortValueTag LiqRefFlowTag { get; set; }
/// <summary>
/// 润滑油流量kg/h
/// </summary>
public ShortValueTag LubeFlowTag { get; set; }
/// <summary> /// <summary>
/// 风量数据-乘以系数的后的最终结果 /// 风量数据-乘以系数的后的最终结果
@@ -373,6 +393,26 @@ namespace CapMachine.Wpf.Services
// 处理 err // 处理 err
} }
//计算干度2
// 气相焓 h_vap_kJkg由 TPRHO 气相 + THERM
// 液相焓 h_liq_kJkg由 TPRHO 液相 + THERM
// 饱和液 / 气焓 h_l / h_v由 SATP +THERM
//气/液质量流量 mg/ml
if (TryComputeDrynessByEnthalpy2(
Gas_kJkgK, Liquid_kJkg,//气相质量焓 h vap [k/kg] 液相质量焓 h liq [kJ/kg]
GasFlowKgPerH, LubeFlowTag.PVModel.EngValue, //气体质量流量 mg [kg/h] 润滑油流量
LiqRefFlowTag.PVModel.EngValue,// 液体质量流量 ml [kg/h]
Liquid_h_liq, Gas_h_vap, //饱和液质量焓 h liq [kJ/kg] 饱和气质量焓 h vap [kJ/kg]
out var GasValue2, out var hMix2, out var err2))
{
// x 为最终干度 [0..1]hMix 为混合后比焓
DrynessTag2Value = GasValue2 * 100.0;
}
else
{
// 处理 err2
}
} }
catch (Exception ex) catch (Exception ex)
{ {
@@ -902,5 +942,89 @@ namespace CapMachine.Wpf.Services
return true; return true;
} }
/// <summary>
/// 按图片的最终流程计算干度2
/// 干度2的计算临时用作为对比使用
/// 1) 质量流量加权混合焓 h_mix = (h_vap*mg + h_liq*ml) / (mg + ml)
/// 2) 干度 x = (h_mix - h_l) / (h_v - h_l),并限幅到 [0,1]
///
/// 入参单位:
/// - hVap_kJkg, hLiq_kJkg, hSatL_kJkg, hSatV_kJkg 均为 kJ/kg
/// - mGas_kg_h, mLiq_kg_h 均为 kg/h
/// 返回true 表示成功,输出 x∈[0,1] 与 h_mixfalse 返回 error
/// </summary>
/// <param name="hVap_kJkg">气相质量焓 h_vap [kJ/kg]</param>
/// <param name="hLiq_kJkg">液相质量焓 h_liq [kJ/kg]</param>
/// <param name="mGas_kg_h">气体质量流量 mg [kg/h]</param>
/// <param name="mLiq_kg_h">液体质量流量 ml [kg/h]</param>
/// <param name="hSatL_kJkg">饱和液质量焓 h_l [kJ/kg]</param>
/// <param name="hSatV_kJkg">饱和气质量焓 h_v [kJ/kg]</param>
/// <param name="dryness">输出干度 x ∈ [0,1]</param>
/// <param name="hMix_kJkg">输出混合后总比焓 h_mix [kJ/kg]</param>
/// <param name="error">Err</param>
/// <returns></returns>
public bool TryComputeDrynessByEnthalpy2(
double hVap_kJkg, // 气相质量焓 h_vap [kJ/kg]
double hLiq_kJkg, // 液相质量焓 h_liq [kJ/kg]
double mGas_kg_h, // 气体质量流量 mg [kg/h]
double lubeFlow_kg_h, // 润滑油流量 mg [kg/h]
double mLiq_kg_h, // 液体质量流量 ml [kg/h]
double hSatL_kJkg, // 饱和液质量焓 h_l [kJ/kg]
double hSatV_kJkg, // 饱和气质量焓 h_v [kJ/kg]
out double dryness, // 输出干度 x ∈ [0,1]
out double hMix_kJkg, // 输出混合后总比焓 h_mix [kJ/kg]
out string error)
{
dryness = double.NaN;
hMix_kJkg = double.NaN;
error = string.Empty;
// 1) 合法性校验
if (double.IsNaN(hVap_kJkg) || double.IsNaN(hLiq_kJkg) || double.IsNaN(hSatL_kJkg) || double.IsNaN(hSatV_kJkg))
{
error = "输入焓值存在 NaN";
return false;
}
if (double.IsNaN(mGas_kg_h) || double.IsNaN(mLiq_kg_h))
{
error = "输入质量流量存在 NaN";
return false;
}
// 负值处理:小于 0 视为 0避免传感器噪声或符号错误影响
//double mg1 = Math.Max(0.0, mGas_kg_h);
double mg = Math.Max(0.0, mGas_kg_h) + Math.Max(0.0, lubeFlow_kg_h); // 这个是改动 气体流量再加上润滑油流量
double ml = Math.Max(0.0, mLiq_kg_h);
double mSum = mg + ml;
if (mSum <= 0)
{
error = "气液质量流量之和为 0无法进行加权混合焓计算";
return false;
}
// 2) 质量流量加权混合焓(严格按图片:上、下两路相加后除以总流量)
hMix_kJkg = (hVap_kJkg * mg + hLiq_kJkg * ml) / mSum;
// 3) 干度计算x = (h_mix - h_l) / (h_v - h_l)
double denom = (hSatV_kJkg - hSatL_kJkg);
const double eps = 1e-9;
if (Math.Abs(denom) < eps)
{
error = "饱和气/液焓差过小,无法计算干度(可能接近临界点或输入异常)";
return false;
}
double x = (hMix_kJkg - hSatL_kJkg) / denom;
// 4) 限幅到 [0,1]
if (double.IsNaN(x) || double.IsInfinity(x))
{
error = "干度计算结果异常NaN/Inf";
return false;
}
dryness = Math.Min(1.0, Math.Max(0.0, x));
return true;
}
} }
} }

View File

@@ -132,6 +132,20 @@ namespace CapMachine.Wpf.ViewModels
set { _IsLeftDrawerOpen = value; RaisePropertyChanged(); } set { _IsLeftDrawerOpen = value; RaisePropertyChanged(); }
} }
private bool _IsBusy;
public bool IsBusy
{
get { return _IsBusy; }
set { _IsBusy = value; RaisePropertyChanged(); }
}
private string _BusyMessage = "正在加载,请稍候...";
public string BusyMessage
{
get { return _BusyMessage; }
set { _BusyMessage = value; RaisePropertyChanged(); }
}
/// <summary> /// <summary>
@@ -417,7 +431,7 @@ namespace CapMachine.Wpf.ViewModels
/// <summary> /// <summary>
/// 获取试验数据的命令的执行方法 /// 获取试验数据的命令的执行方法
/// </summary> /// </summary>
private void HistoryDataFileCmdMethod() private async void HistoryDataFileCmdMethod()
{ {
if (SelectedHistoryExp == null) if (SelectedHistoryExp == null)
{ {
@@ -449,14 +463,29 @@ namespace CapMachine.Wpf.ViewModels
return; return;
} }
CsvRecordModels = new List<CsvRecordModel>(); BusyMessage = "正在加载CSV数据请稍候...";
IsBusy = true;
var loaded = new List<CsvRecordModel>();
string errorText = string.Empty;
stopwatch.Start(); stopwatch.Start();
var errors = new StringBuilder();
foreach (var f in files)
{
try try
{ {
await Task.Run(() =>
{
var errors = new StringBuilder();
for (int i = 0; i < files.Count; i++)
{
var f = files[i];
try
{
Application.Current.Dispatcher.Invoke(() =>
{
BusyMessage = $"正在加载({i + 1}/{files.Count}){System.IO.Path.GetFileName(f?.FilePath)}";
});
if (f == null) continue; if (f == null) continue;
if (string.IsNullOrWhiteSpace(f.FilePath)) if (string.IsNullOrWhiteSpace(f.FilePath))
{ {
@@ -472,7 +501,7 @@ namespace CapMachine.Wpf.ViewModels
var rec = ReadCsvFile(f.FilePath); var rec = ReadCsvFile(f.FilePath);
if (rec != null && rec.Count > 0) if (rec != null && rec.Count > 0)
{ {
CsvRecordModels.AddRange(rec); loaded.AddRange(rec);
} }
} }
catch (Exception ex) catch (Exception ex)
@@ -480,26 +509,35 @@ namespace CapMachine.Wpf.ViewModels
errors.AppendLine($"读取CSV失败: {ex.Message}"); errors.AppendLine($"读取CSV失败: {ex.Message}");
} }
} }
errorText = errors.ToString();
});
if (errors.Length > 0) if (!string.IsNullOrWhiteSpace(errorText))
{ {
System.Windows.MessageBox.Show(errors.ToString(), "读取提示", MessageBoxButton.OK, MessageBoxImage.Warning); System.Windows.MessageBox.Show(errorText, "读取提示", MessageBoxButton.OK, MessageBoxImage.Warning);
} }
if (CsvRecordModels.Count > 0) CsvRecordModels = new List<CsvRecordModel>();
if (loaded != null && loaded.Count > 0)
{ {
CsvRecordModels = CsvRecordModels CsvRecordModels = loaded
.Where(r => r != null) .Where(r => r != null)
.OrderBy(r => r.CreateTime) .OrderBy(r => r.CreateTime)
.ToList(); .ToList();
Application.Current.Dispatcher.Invoke(() =>
{
EventAggregator.GetEvent<HistoryDataToChartEvent>().Publish(new HistoryDataToChartMsg() { Machine = "History", Data = CsvRecordModels }); EventAggregator.GetEvent<HistoryDataToChartEvent>().Publish(new HistoryDataToChartMsg() { Machine = "History", Data = CsvRecordModels });
});
} }
}
finally
{
stopwatch.Stop(); stopwatch.Stop();
Console.WriteLine("加载CSV数据耗时:{0}", stopwatch.Elapsed.TotalSeconds.ToString()); Console.WriteLine("加载CSV数据耗时:{0}", stopwatch.Elapsed.TotalSeconds.ToString());
stopwatch.Reset(); stopwatch.Reset();
IsBusy = false;
IsLeftDrawerOpen = false; IsLeftDrawerOpen = false;
}
} }

View File

@@ -26,6 +26,7 @@
<Setter Property="BorderThickness" Value="0" /> <Setter Property="BorderThickness" Value="0" />
<Setter Property="BorderBrush" Value="Transparent" /> <Setter Property="BorderBrush" Value="Transparent" />
</Style> </Style>
<BooleanToVisibilityConverter x:Key="BoolToVisibilityConverter" />
</UserControl.Resources> </UserControl.Resources>
<materialDesign:DrawerHost <materialDesign:DrawerHost
x:Name="HistoryDrawerHost" x:Name="HistoryDrawerHost"
@@ -320,8 +321,39 @@
</DataGrid.Columns> </DataGrid.Columns>
<!-- CommandParameter="{Binding ElementName=MainDatagrid, Path=SelectedItem}" --> <!-- CommandParameter="{Binding ElementName=MainDatagrid, Path=SelectedItem}" -->
</DataGrid> </DataGrid>
<!-- 忙碌遮罩 -->
<Grid
x:Name="BusyOverlay"
Grid.Row="1"
Panel.ZIndex="999"
Background="#66000000"
Visibility="{Binding IsBusy, Converter={StaticResource BoolToVisibilityConverter}}">
<Border
Padding="16"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Background="White"
CornerRadius="6">
<StackPanel>
<ProgressBar
Width="220"
Height="6"
IsIndeterminate="True" />
<TextBlock
Margin="0,10,0,0"
HorizontalAlignment="Center"
FontSize="14"
Foreground="Black"
Text="{Binding BusyMessage}" />
</StackPanel>
</Border>
</Grid> </Grid>
</Grid>
</Grid> </Grid>

View File

@@ -211,7 +211,7 @@
</Grid.ColumnDefinitions> </Grid.ColumnDefinitions>
<materialDesign:Card <materialDesign:Card
Grid.ColumnSpan="6" Grid.ColumnSpan="5"
Margin="3" Margin="3"
Background="{DynamicResource MaterialDesignLightBackground}" Background="{DynamicResource MaterialDesignLightBackground}"
Foreground="{DynamicResource PrimaryHueLightForegroundBrush}" Foreground="{DynamicResource PrimaryHueLightForegroundBrush}"
@@ -232,6 +232,32 @@
</StackPanel> </StackPanel>
</materialDesign:Card> </materialDesign:Card>
<materialDesign:Card
Grid.Column="5"
Margin="3"
Background="{DynamicResource MaterialDesignLightBackground}"
Foreground="{DynamicResource PrimaryHueLightForegroundBrush}"
UniformCornerRadius="5">
<StackPanel Orientation="Horizontal">
<TextBlock
Margin="10,0,0,0"
VerticalAlignment="Center"
FontFamily="/Assets/Fonts/#iconfont"
FontSize="26"
Foreground="Blue"
Text="&#xe9f8;" />
<TextBlock
Foreground="Blue"
Style="{StaticResource TitelStyle}"
Text="干度2:" />
<TextBlock
VerticalAlignment="Center"
FontSize="26"
FontWeight="Bold"
Text="{Binding PPCService.DrynessTag2Value}" />
</StackPanel>
</materialDesign:Card>
<!--<materialDesign:Card <!--<materialDesign:Card
Grid.Column="3" Grid.Column="3"
Grid.ColumnSpan="3" Grid.ColumnSpan="3"