Compare commits
4 Commits
a47ed5b817
...
HASCO_KR26
| Author | SHA1 | Date | |
|---|---|---|---|
| 802348a743 | |||
| 74bf47ee62 | |||
| 53ded58da3 | |||
| e3641ebe84 |
@@ -8,6 +8,7 @@
|
||||
<add key="PLCScan" value="600"/>
|
||||
<add key="PLCIP" value="127.0.0.1"/>
|
||||
<add key="CompressorDisplacementCc" value="35CC"/>
|
||||
<add key="Therdy_H3TempOffset_C" value="-10"/>
|
||||
<add key="FluidsPath" value="C:\Program Files (x86)\REFPROP\fluids"/>
|
||||
<add key="Cryogen" value="R134a"/>
|
||||
<add key="LocalDBPath" value="D:\MSDB\LocalDb\CapMachineDb"/>
|
||||
|
||||
@@ -210,6 +210,7 @@ namespace CapMachine.Wpf
|
||||
containerRegistry.RegisterDialog<DialogPIDConfigView, DialogPIDConfigViewModel>();
|
||||
containerRegistry.RegisterDialog<DialogLimitConfigView, DialogLimitConfigViewModel>();
|
||||
containerRegistry.RegisterDialog<DialogSuperHeatCoolConfigView, DialogSuperHeatCoolConfigViewModel>();
|
||||
containerRegistry.RegisterDialog<DialogTherdyConfigView, DialogTherdyConfigViewModel>();
|
||||
containerRegistry.RegisterDialog<DialogLogicRuleView, DialogLogicRuleViewModel>();
|
||||
containerRegistry.RegisterDialog<DialogCanLinConfigImExportView, DialogCanLinConfigImExportViewModel>();
|
||||
containerRegistry.RegisterDialog<DialogCANFdSchConfigView, DialogCANFdSchConfigViewModel>();
|
||||
@@ -308,8 +309,14 @@ namespace CapMachine.Wpf
|
||||
//给当前的全局异常捕捉服务使用
|
||||
LogService = ContainerLocator.Container.Resolve<ILogService>();
|
||||
LogService.Info("程序启动");
|
||||
|
||||
base.OnInitialized();
|
||||
|
||||
//#if DEBUG
|
||||
//var ppc = Prism.Ioc.ContainerLocator.Container.Resolve<CapMachine.Wpf.Services.PPCService>();
|
||||
//ppc.DebugRunThermoValidationCase_FromScreenshot_20260423();
|
||||
//#endif
|
||||
|
||||
//#endregion
|
||||
|
||||
//*******起始弹窗 * *******
|
||||
|
||||
@@ -55,23 +55,23 @@ namespace CapMachine.Wpf.Models
|
||||
[Name("吸气温度[℃]")]
|
||||
public double InhTemp { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// COND1温度[℃]
|
||||
/// </summary>
|
||||
[Name("COND1温度[℃]")]
|
||||
public double Cond1Temp { get; set; }
|
||||
///// <summary>
|
||||
///// COND1温度[℃]
|
||||
///// </summary>
|
||||
//[Name("COND1温度[℃]")]
|
||||
//public double Cond1Temp { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 润滑油压力[BarA]
|
||||
/// </summary>
|
||||
[Name("润滑油压力[BarA]")]
|
||||
public double LubePress { get; set; }
|
||||
///// <summary>
|
||||
///// 润滑油压力[BarA]
|
||||
///// </summary>
|
||||
//[Name("润滑油压力[BarA]")]
|
||||
//public double LubePress { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// COND2压力[BarA]
|
||||
/// </summary>
|
||||
[Name("COND2压力[BarA]")]
|
||||
public double Cond2Press { get; set; }
|
||||
///// <summary>
|
||||
///// COND2压力[BarA]
|
||||
///// </summary>
|
||||
//[Name("COND2压力[BarA]")]
|
||||
//public double Cond2Press { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// OCR[%]
|
||||
@@ -127,23 +127,23 @@ namespace CapMachine.Wpf.Models
|
||||
[Name("OS1温度[℃]")]
|
||||
public double OS1Temp { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// OS2温度[℃]
|
||||
/// </summary>
|
||||
[Name("OS2温度[℃]")]
|
||||
public double OS2Temp { get; set; }
|
||||
///// <summary>
|
||||
///// OS2温度[℃]
|
||||
///// </summary>
|
||||
//[Name("OS2温度[℃]")]
|
||||
//public double OS2Temp { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// COND2温度[℃]
|
||||
/// </summary>
|
||||
[Name("COND2温度[℃]")]
|
||||
public double Cond2Temp { get; set; }
|
||||
///// <summary>
|
||||
///// COND2温度[℃]
|
||||
///// </summary>
|
||||
//[Name("COND2温度[℃]")]
|
||||
//public double Cond2Temp { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// EVAP出口温度[℃]
|
||||
/// </summary>
|
||||
[Name("EVAP出口温度[℃]")]
|
||||
public double EVAPExpTemp { get; set; }
|
||||
///// <summary>
|
||||
///// EVAP出口温度[℃]
|
||||
///// </summary>
|
||||
//[Name("EVAP出口温度[℃]")]
|
||||
//public double EVAPExpTemp { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 冷媒流量[kg/h]
|
||||
@@ -169,17 +169,17 @@ namespace CapMachine.Wpf.Models
|
||||
[Name("膨胀阀前压力[BarA]")]
|
||||
public double TxvFrPress { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 膨胀阀前温度[℃]
|
||||
/// </summary>
|
||||
[Name("膨胀阀前温度[℃]")]
|
||||
public double TxvFrTemp { get; set; }
|
||||
///// <summary>
|
||||
///// 膨胀阀前温度[℃]
|
||||
///// </summary>
|
||||
//[Name("膨胀阀前温度[℃]")]
|
||||
//public double TxvFrTemp { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// EVAP出口压力[BarA]
|
||||
/// </summary>
|
||||
[Name("EVAP出口压力[BarA]")]
|
||||
public double EVAPExpPress { get; set; }
|
||||
///// <summary>
|
||||
///// EVAP出口压力[BarA]
|
||||
///// </summary>
|
||||
//[Name("EVAP出口压力[BarA]")]
|
||||
//public double EVAPExpPress { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 腔内压力[BarA]
|
||||
@@ -211,17 +211,17 @@ namespace CapMachine.Wpf.Models
|
||||
[Name("PTC出水温度[℃]")]
|
||||
public double PTCExpTemp { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// AT04_01[℃]
|
||||
/// </summary>
|
||||
[Name("AT04_01[℃]")]
|
||||
public double AT04_01Temp { get; set; }
|
||||
///// <summary>
|
||||
///// AT04_01[℃]
|
||||
///// </summary>
|
||||
//[Name("AT04_01[℃]")]
|
||||
//public double AT04_01Temp { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// AT04_02[℃]
|
||||
/// </summary>
|
||||
[Name("AT04_02[℃]")]
|
||||
public double AT04_02Temp { get; set; }
|
||||
///// <summary>
|
||||
///// AT04_02[℃]
|
||||
///// </summary>
|
||||
//[Name("AT04_02[℃]")]
|
||||
//public double AT04_02Temp { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 通讯Cmp母线电流[A]
|
||||
@@ -301,11 +301,11 @@ namespace CapMachine.Wpf.Models
|
||||
[Name("液冷媒流量[kg/h]")]
|
||||
public double LiqRefFlow { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 干度流量[kg/h]
|
||||
/// </summary>
|
||||
[Name("干度流量[kg/h]")]
|
||||
public double DryFlow { get; set; }
|
||||
///// <summary>
|
||||
///// 干度流量[kg/h]
|
||||
///// </summary>
|
||||
//[Name("干度流量[kg/h]")]
|
||||
//public double DryFlow { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// H5吸气混合器温度[℃]
|
||||
@@ -343,11 +343,11 @@ namespace CapMachine.Wpf.Models
|
||||
[Name("S.C循环水温[℃]")]
|
||||
public double SCCirWaterTemp { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// EVAP循环水温[℃]
|
||||
/// </summary>
|
||||
[Name("EVAP循环水温[℃]")]
|
||||
public double EvapCirWaterTemp { get; set; }
|
||||
///// <summary>
|
||||
///// EVAP循环水温[℃]
|
||||
///// </summary>
|
||||
//[Name("EVAP循环水温[℃]")]
|
||||
//public double EvapCirWaterTemp { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 吸气混合器出口压力[BarA]
|
||||
@@ -368,9 +368,9 @@ namespace CapMachine.Wpf.Models
|
||||
public double GasFrTemp { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 干度[%]
|
||||
/// 干度[-]
|
||||
/// </summary>
|
||||
[Name("干度[%]")]
|
||||
[Name("干度[-]")]
|
||||
public double Dryness { get; set; }
|
||||
|
||||
/// <summary>
|
||||
@@ -394,7 +394,7 @@ namespace CapMachine.Wpf.Models
|
||||
/// <summary>
|
||||
/// 压缩机性能系数(制热)
|
||||
/// </summary>
|
||||
[Name("压缩机性能系数(制热)")]
|
||||
[Name("压缩机性能系数(制热COP)")]
|
||||
public double COPHeat { get; set; }
|
||||
|
||||
/// <summary>
|
||||
@@ -412,7 +412,7 @@ namespace CapMachine.Wpf.Models
|
||||
/// <summary>
|
||||
/// 压缩机性能系数(制冷)
|
||||
/// </summary>
|
||||
[Name("压缩机性能系数(制冷)")]
|
||||
[Name("压缩机性能系数(制冷COP)")]
|
||||
public double COPCool { get; set; }
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -22,9 +22,9 @@ namespace CapMachine.Wpf.Models
|
||||
Map(m => m.ExPress).Name("排气压力[BarA]");
|
||||
Map(m => m.InhPress).Name("吸气压力[BarA]");
|
||||
Map(m => m.InhTemp).Name("吸气温度[℃]");
|
||||
Map(m => m.Cond1Temp).Name("COND1温度[℃]");
|
||||
Map(m => m.LubePress).Name("润滑油压力[BarA]");
|
||||
Map(m => m.Cond2Press).Name("COND2压力[BarA]");
|
||||
//Map(m => m.Cond1Temp).Name("COND1温度[℃]");
|
||||
//Map(m => m.LubePress).Name("润滑油压力[BarA]");
|
||||
//Map(m => m.Cond2Press).Name("COND2压力[BarA]");
|
||||
Map(m => m.OCR).Name("OCR[%]");
|
||||
Map(m => m.HV).Name("HV[V]");
|
||||
Map(m => m.HVCur).Name("HV[A]");
|
||||
@@ -34,22 +34,20 @@ namespace CapMachine.Wpf.Models
|
||||
Map(m => m.EnvTemp).Name("环境温度[℃]");
|
||||
Map(m => m.EnvRH).Name("环境湿度[%]");
|
||||
Map(m => m.OS1Temp).Name("OS1温度[℃]");
|
||||
Map(m => m.OS2Temp).Name("OS2温度[℃]");
|
||||
Map(m => m.Cond2Temp).Name("COND2温度[℃]");
|
||||
Map(m => m.EVAPExpTemp).Name("EVAP出口温度[℃]");
|
||||
//Map(m => m.OS2Temp).Name("OS2温度[℃]");
|
||||
//Map(m => m.Cond2Temp).Name("COND2温度[℃]");
|
||||
Map(m => m.VRV).Name("冷媒流量[kg/h]");
|
||||
Map(m => m.LubeFlow).Name("润滑油流量[kg/h]");
|
||||
Map(m => m.ExTemp).Name("排气温度[℃]");
|
||||
Map(m => m.TxvFrPress).Name("膨胀阀前压力[BarA]");
|
||||
Map(m => m.TxvFrTemp).Name("膨胀阀前温度[℃]");
|
||||
Map(m => m.EVAPExpPress).Name("EVAP出口压力[BarA]");
|
||||
//Map(m => m.TxvFrTemp).Name("膨胀阀前温度[℃]");
|
||||
Map(m => m.IntrplPress).Name("腔内压力[BarA]");
|
||||
Map(m => m.CapSurfTemp).Name("压缩机表面温度[℃]");
|
||||
Map(m => m.PTCFlow).Name("PTC流量[L/min]");
|
||||
Map(m => m.PTCEntTemp).Name("PTC入水温度[℃]");
|
||||
Map(m => m.PTCExpTemp).Name("PTC出水温度[℃]");
|
||||
Map(m => m.AT04_01Temp).Name("AT04_01[℃]");
|
||||
Map(m => m.AT04_02Temp).Name("AT04_02[℃]");
|
||||
//Map(m => m.AT04_01Temp).Name("AT04_01[℃]");
|
||||
//Map(m => m.AT04_02Temp).Name("AT04_02[℃]");
|
||||
Map(m => m.ComCapBusCur).Name("通讯Cmp母线电流[A]");
|
||||
Map(m => m.ComCapBusVol).Name("通讯Cmp母线电压[V]");
|
||||
Map(m => m.ComCapInvTemp).Name("通讯Cmp逆变器温度[℃]");
|
||||
@@ -63,28 +61,26 @@ namespace CapMachine.Wpf.Models
|
||||
Map(m => m.ComPTCFlmTemp).Name("通讯PTC膜温[℃]");
|
||||
Map(m => m.ComPTCMdTemp).Name("通讯PTC模块温度[℃]");
|
||||
Map(m => m.LiqRefFlow).Name("液冷媒流量[kg/h]");
|
||||
Map(m => m.DryFlow).Name("干度流量[kg/h]");
|
||||
Map(m => m.H5InhMixTemp).Name("H5吸气混合器温度[℃]");
|
||||
Map(m => m.CONDCirWaterTemp).Name("COND循环水温[℃]");
|
||||
Map(m => m.SubcoolOutTemp).Name("SUBCOOL出口温度[℃]");
|
||||
Map(m => m.InhMixOutTemp).Name("吸气混合器出口温度[℃]");
|
||||
Map(m => m.H1OutTemp).Name("H1出口温度[℃]");
|
||||
Map(m => m.SCCirWaterTemp).Name("S.C循环水温[℃]");
|
||||
Map(m => m.EvapCirWaterTemp).Name("EVAP循环水温[℃]");
|
||||
Map(m => m.InhMixOutPress).Name("吸气混合器出口压力[BarA]");
|
||||
Map(m => m.GasFrPress).Name("气路阀前压力[BarA]");
|
||||
Map(m => m.GasFrTemp).Name("气路阀前温度[℃]");
|
||||
Map(m => m.Dryness).Name("干度[%]");
|
||||
Map(m => m.Dryness).Name("干度[-]", "干度[%]");
|
||||
Map(m => m.Subcooling).Name("过冷度[K]");
|
||||
Map(m => m.Superheat).Name("过热度[K]");
|
||||
|
||||
Map(m => m.HeatingCapacity).Name("制热量Qh[W]").TypeConverterOption.Format("0");
|
||||
Map(m => m.COPHeat).Name("压缩机性能系数(制热)").TypeConverterOption.Format("0.0");
|
||||
Map(m => m.COPHeat).Name("压缩机性能系数(制热COP)", "压缩机性能系数(制热)").TypeConverterOption.Format("0.0");
|
||||
Map(m => m.IsentrpEff).Name("等熵效率ns[%]").TypeConverterOption.Format("0.0");
|
||||
Map(m => m.CoolCapacity).Name("制冷量Qc[W]").TypeConverterOption.Format("0");
|
||||
Map(m => m.COPCool).Name("压缩机性能系数(制冷)").TypeConverterOption.Format("0.0");
|
||||
Map(m => m.COPCool).Name("压缩机性能系数(制冷COP)", "压缩机性能系数(制冷)").TypeConverterOption.Format("0.0");
|
||||
Map(m => m.VoltricEff).Name("容积效率nv[%]").TypeConverterOption.Format("0.0");
|
||||
Map(m => m.CreateTime).Name("时间");
|
||||
Map(m => m.CreateTime).Name("时间", "创建时间");
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -209,12 +209,12 @@ namespace CapMachine.Wpf.Models.LightChart
|
||||
return CurHistoryData.Select(a => new ChartPoint() { Value = a.InhPress, Time = a.CreateTime }).OrderBy(a => a.Time).ToList();
|
||||
case "吸气温度[℃]":
|
||||
return CurHistoryData.Select(a => new ChartPoint() { Value = a.InhTemp, Time = a.CreateTime }).OrderBy(a => a.Time).ToList();
|
||||
case "COND1温度[℃]":
|
||||
return CurHistoryData.Select(a => new ChartPoint() { Value = a.Cond1Temp, Time = a.CreateTime }).OrderBy(a => a.Time).ToList();
|
||||
case "润滑油压力[BarA]":
|
||||
return CurHistoryData.Select(a => new ChartPoint() { Value = a.LubePress, Time = a.CreateTime }).OrderBy(a => a.Time).ToList();
|
||||
case "COND2压力[BarA]":
|
||||
return CurHistoryData.Select(a => new ChartPoint() { Value = a.Cond2Press, Time = a.CreateTime }).OrderBy(a => a.Time).ToList();
|
||||
//case "COND1温度[℃]":
|
||||
// return CurHistoryData.Select(a => new ChartPoint() { Value = a.Cond1Temp, Time = a.CreateTime }).OrderBy(a => a.Time).ToList();
|
||||
//case "润滑油压力[BarA]":
|
||||
// return CurHistoryData.Select(a => new ChartPoint() { Value = a.LubePress, Time = a.CreateTime }).OrderBy(a => a.Time).ToList();
|
||||
//case "COND2压力[BarA]":
|
||||
// return CurHistoryData.Select(a => new ChartPoint() { Value = a.Cond2Press, Time = a.CreateTime }).OrderBy(a => a.Time).ToList();
|
||||
case "OCR[%]":
|
||||
return CurHistoryData.Select(a => new ChartPoint() { Value = a.OCR, Time = a.CreateTime }).OrderBy(a => a.Time).ToList();
|
||||
case "HV[V]":
|
||||
@@ -233,12 +233,12 @@ namespace CapMachine.Wpf.Models.LightChart
|
||||
return CurHistoryData.Select(a => new ChartPoint() { Value = a.EnvRH, Time = a.CreateTime }).OrderBy(a => a.Time).ToList();
|
||||
case "OS1温度[℃]":
|
||||
return CurHistoryData.Select(a => new ChartPoint() { Value = a.OS1Temp, Time = a.CreateTime }).OrderBy(a => a.Time).ToList();
|
||||
case "OS2温度[℃]":
|
||||
return CurHistoryData.Select(a => new ChartPoint() { Value = a.OS2Temp, Time = a.CreateTime }).OrderBy(a => a.Time).ToList();
|
||||
case "COND2温度[℃]":
|
||||
return CurHistoryData.Select(a => new ChartPoint() { Value = a.Cond2Temp, Time = a.CreateTime }).OrderBy(a => a.Time).ToList();
|
||||
case "EVAP出口温度[℃]":
|
||||
return CurHistoryData.Select(a => new ChartPoint() { Value = a.EVAPExpTemp, Time = a.CreateTime }).OrderBy(a => a.Time).ToList();
|
||||
//case "OS2温度[℃]":
|
||||
// return CurHistoryData.Select(a => new ChartPoint() { Value = a.OS2Temp, Time = a.CreateTime }).OrderBy(a => a.Time).ToList();
|
||||
//case "COND2温度[℃]":
|
||||
// return CurHistoryData.Select(a => new ChartPoint() { Value = a.Cond2Temp, Time = a.CreateTime }).OrderBy(a => a.Time).ToList();
|
||||
//case "EVAP出口温度[℃]":
|
||||
// return CurHistoryData.Select(a => new ChartPoint() { Value = a.EVAPExpTemp, Time = a.CreateTime }).OrderBy(a => a.Time).ToList();
|
||||
case "冷媒流量[kg/h]":
|
||||
return CurHistoryData.Select(a => new ChartPoint() { Value = a.VRV, Time = a.CreateTime }).OrderBy(a => a.Time).ToList();
|
||||
case "润滑油流量[kg/h]":
|
||||
@@ -247,10 +247,10 @@ namespace CapMachine.Wpf.Models.LightChart
|
||||
return CurHistoryData.Select(a => new ChartPoint() { Value = a.ExTemp, Time = a.CreateTime }).OrderBy(a => a.Time).ToList();
|
||||
case "膨胀阀前压力[BarA]":
|
||||
return CurHistoryData.Select(a => new ChartPoint() { Value = a.TxvFrPress, Time = a.CreateTime }).OrderBy(a => a.Time).ToList();
|
||||
case "膨胀阀前温度[℃]":
|
||||
return CurHistoryData.Select(a => new ChartPoint() { Value = a.TxvFrTemp, Time = a.CreateTime }).OrderBy(a => a.Time).ToList();
|
||||
case "EVAP出口压力[BarA]":
|
||||
return CurHistoryData.Select(a => new ChartPoint() { Value = a.EVAPExpPress, Time = a.CreateTime }).OrderBy(a => a.Time).ToList();
|
||||
//case "膨胀阀前温度[℃]":
|
||||
// return CurHistoryData.Select(a => new ChartPoint() { Value = a.TxvFrTemp, Time = a.CreateTime }).OrderBy(a => a.Time).ToList();
|
||||
//case "EVAP出口压力[BarA]":
|
||||
// return CurHistoryData.Select(a => new ChartPoint() { Value = a.EVAPExpPress, Time = a.CreateTime }).OrderBy(a => a.Time).ToList();
|
||||
case "腔内压力[BarA]":
|
||||
return CurHistoryData.Select(a => new ChartPoint() { Value = a.IntrplPress, Time = a.CreateTime }).OrderBy(a => a.Time).ToList();
|
||||
case "压缩机表面温度[℃]":
|
||||
@@ -261,10 +261,10 @@ namespace CapMachine.Wpf.Models.LightChart
|
||||
return CurHistoryData.Select(a => new ChartPoint() { Value = a.PTCEntTemp, Time = a.CreateTime }).OrderBy(a => a.Time).ToList();
|
||||
case "PTC出水温度[℃]":
|
||||
return CurHistoryData.Select(a => new ChartPoint() { Value = a.PTCExpTemp, Time = a.CreateTime }).OrderBy(a => a.Time).ToList();
|
||||
case "AT04_01[℃]":
|
||||
return CurHistoryData.Select(a => new ChartPoint() { Value = a.AT04_01Temp, Time = a.CreateTime }).OrderBy(a => a.Time).ToList();
|
||||
case "AT04_02[℃]":
|
||||
return CurHistoryData.Select(a => new ChartPoint() { Value = a.AT04_02Temp, Time = a.CreateTime }).OrderBy(a => a.Time).ToList();
|
||||
//case "AT04_01[℃]":
|
||||
// return CurHistoryData.Select(a => new ChartPoint() { Value = a.AT04_01Temp, Time = a.CreateTime }).OrderBy(a => a.Time).ToList();
|
||||
//case "AT04_02[℃]":
|
||||
// return CurHistoryData.Select(a => new ChartPoint() { Value = a.AT04_02Temp, Time = a.CreateTime }).OrderBy(a => a.Time).ToList();
|
||||
case "通讯Cmp母线电流[A]":
|
||||
return CurHistoryData.Select(a => new ChartPoint() { Value = a.ComCapBusCur, Time = a.CreateTime }).OrderBy(a => a.Time).ToList();
|
||||
case "通讯Cmp母线电压[V]":
|
||||
@@ -291,8 +291,8 @@ namespace CapMachine.Wpf.Models.LightChart
|
||||
return CurHistoryData.Select(a => new ChartPoint() { Value = a.ComPTCMdTemp, Time = a.CreateTime }).OrderBy(a => a.Time).ToList();
|
||||
case "液冷媒流量[kg/h]":
|
||||
return CurHistoryData.Select(a => new ChartPoint() { Value = a.LiqRefFlow, Time = a.CreateTime }).OrderBy(a => a.Time).ToList();
|
||||
case "干度流量[kg/h]":
|
||||
return CurHistoryData.Select(a => new ChartPoint() { Value = a.DryFlow, Time = a.CreateTime }).OrderBy(a => a.Time).ToList();
|
||||
//case "干度流量[kg/h]":
|
||||
// return CurHistoryData.Select(a => new ChartPoint() { Value = a.DryFlow, Time = a.CreateTime }).OrderBy(a => a.Time).ToList();
|
||||
case "H5吸气混合器温度[℃]":
|
||||
return CurHistoryData.Select(a => new ChartPoint() { Value = a.H5InhMixTemp, Time = a.CreateTime }).OrderBy(a => a.Time).ToList();
|
||||
case "COND循环水温[℃]":
|
||||
@@ -305,15 +305,15 @@ namespace CapMachine.Wpf.Models.LightChart
|
||||
return CurHistoryData.Select(a => new ChartPoint() { Value = a.H1OutTemp, Time = a.CreateTime }).OrderBy(a => a.Time).ToList();
|
||||
case "S.C循环水温[℃]":
|
||||
return CurHistoryData.Select(a => new ChartPoint() { Value = a.SCCirWaterTemp, Time = a.CreateTime }).OrderBy(a => a.Time).ToList();
|
||||
case "EVAP循环水温[℃]":
|
||||
return CurHistoryData.Select(a => new ChartPoint() { Value = a.EvapCirWaterTemp, Time = a.CreateTime }).OrderBy(a => a.Time).ToList();
|
||||
//case "EVAP循环水温[℃]":
|
||||
// return CurHistoryData.Select(a => new ChartPoint() { Value = a.EvapCirWaterTemp, Time = a.CreateTime }).OrderBy(a => a.Time).ToList();
|
||||
case "吸气混合器出口压力[BarA]":
|
||||
return CurHistoryData.Select(a => new ChartPoint() { Value = a.InhMixOutPress, Time = a.CreateTime }).OrderBy(a => a.Time).ToList();
|
||||
case "气路阀前压力[BarA]":
|
||||
return CurHistoryData.Select(a => new ChartPoint() { Value = a.GasFrPress, Time = a.CreateTime }).OrderBy(a => a.Time).ToList();
|
||||
case "气路阀前温度[℃]":
|
||||
return CurHistoryData.Select(a => new ChartPoint() { Value = a.GasFrTemp, Time = a.CreateTime }).OrderBy(a => a.Time).ToList();
|
||||
case "干度[%]":
|
||||
case "干度[-]":
|
||||
return CurHistoryData.Select(a => new ChartPoint() { Value = a.Dryness, Time = a.CreateTime }).OrderBy(a => a.Time).ToList();
|
||||
case "过冷度[K]":
|
||||
return CurHistoryData.Select(a => new ChartPoint() { Value = a.Subcooling, Time = a.CreateTime }).OrderBy(a => a.Time).ToList();
|
||||
@@ -321,13 +321,13 @@ namespace CapMachine.Wpf.Models.LightChart
|
||||
return CurHistoryData.Select(a => new ChartPoint() { Value = a.Superheat, Time = a.CreateTime }).OrderBy(a => a.Time).ToList();
|
||||
case "制热量Qh[W]":
|
||||
return CurHistoryData.Select(a => new ChartPoint() { Value = a.HeatingCapacity, Time = a.CreateTime }).OrderBy(a => a.Time).ToList();
|
||||
case "压缩机性能系数(制热)":
|
||||
case "压缩机性能系数(制热COP)":
|
||||
return CurHistoryData.Select(a => new ChartPoint() { Value = a.COPHeat, Time = a.CreateTime }).OrderBy(a => a.Time).ToList();
|
||||
case "等熵效率ns[%]":
|
||||
return CurHistoryData.Select(a => new ChartPoint() { Value = a.IsentrpEff, Time = a.CreateTime }).OrderBy(a => a.Time).ToList();
|
||||
case "制冷量Qc[W]":
|
||||
return CurHistoryData.Select(a => new ChartPoint() { Value = a.CoolCapacity, Time = a.CreateTime }).OrderBy(a => a.Time).ToList();
|
||||
case "压缩机性能系数(制冷)":
|
||||
case "压缩机性能系数(制冷COP)":
|
||||
return CurHistoryData.Select(a => new ChartPoint() { Value = a.COPCool, Time = a.CreateTime }).OrderBy(a => a.Time).ToList();
|
||||
case "容积效率nv[%]":
|
||||
return CurHistoryData.Select(a => new ChartPoint() { Value = a.VoltricEff, Time = a.CreateTime }).OrderBy(a => a.Time).ToList();
|
||||
|
||||
15
CapMachine.Wpf/Models/PPCalc/TherdyConfigModel.cs
Normal file
15
CapMachine.Wpf/Models/PPCalc/TherdyConfigModel.cs
Normal file
@@ -0,0 +1,15 @@
|
||||
using Prism.Mvvm;
|
||||
|
||||
namespace CapMachine.Wpf.Models.PPCalc
|
||||
{
|
||||
public class TherdyConfigModel : BindableBase
|
||||
{
|
||||
private double _h3TempOffset_C = -10.0;
|
||||
|
||||
public double H3TempOffset_C
|
||||
{
|
||||
get { return _h3TempOffset_C; }
|
||||
set { _h3TempOffset_C = value; RaisePropertyChanged(); }
|
||||
}
|
||||
}
|
||||
}
|
||||
599
CapMachine.Wpf/PPCalculation/EnthalpyDrynessCalculator.cs
Normal file
599
CapMachine.Wpf/PPCalculation/EnthalpyDrynessCalculator.cs
Normal file
@@ -0,0 +1,599 @@
|
||||
using System;
|
||||
|
||||
namespace CapMachine.Wpf.PPCalculation
|
||||
{
|
||||
/// <summary>
|
||||
/// 干度计算(基于焓法)的独立封装:
|
||||
/// - 先分别计算气路/液路阀前的单相质量比焓(TPRHO + THERM)
|
||||
/// - 再计算吸气压力对应的饱和液/饱和气质量比焓(SATP + THERM)
|
||||
/// - 最终按既定流程计算混合焓与干度,并限幅到 [0,1]
|
||||
///
|
||||
/// 注意:该类仅做封装以便维护,不应改变既有干度计算过程与逻辑。
|
||||
/// 调用方需确保 REFPROP 已完成 SETPATH/SETUP 初始化(与现有 PPCService 保持一致)。
|
||||
/// </summary>
|
||||
public sealed class EnthalpyDrynessCalculator
|
||||
{
|
||||
private readonly object _refpropLock;
|
||||
|
||||
/// <summary>
|
||||
/// 构造函数。
|
||||
/// </summary>
|
||||
/// <param name="refpropLock">REFPROP 全局互斥锁对象(必须与系统其它 REFPROP 调用共用,以避免并发竞态)。</param>
|
||||
public EnthalpyDrynessCalculator(object refpropLock)
|
||||
{
|
||||
_refpropLock = refpropLock ?? throw new ArgumentNullException(nameof(refpropLock));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 干度计算输入模型(以 Tag 读数为准)。
|
||||
/// </summary>
|
||||
public readonly struct Input
|
||||
{
|
||||
public Input(
|
||||
double gasPreValvePressBarA,
|
||||
double gasPreValveTempC,
|
||||
double txvFrPressBarA,
|
||||
double txvFrTempC,
|
||||
double inhPressBarA,
|
||||
double vrvFlowKgPerH,
|
||||
double liqRefFlowKgPerH,
|
||||
double lubeFlowKgPerH)
|
||||
{
|
||||
GasPreValvePressBarA = gasPreValvePressBarA;
|
||||
GasPreValveTempC = gasPreValveTempC;
|
||||
TxvFrPressBarA = txvFrPressBarA;
|
||||
TxvFrTempC = txvFrTempC;
|
||||
InhPressBarA = inhPressBarA;
|
||||
VRVFlowKgPerH = vrvFlowKgPerH;
|
||||
LiqRefFlowKgPerH = liqRefFlowKgPerH;
|
||||
LubeFlowKgPerH = lubeFlowKgPerH;
|
||||
}
|
||||
|
||||
public double GasPreValvePressBarA { get; }
|
||||
public double GasPreValveTempC { get; }
|
||||
public double TxvFrPressBarA { get; }
|
||||
public double TxvFrTempC { get; }
|
||||
public double InhPressBarA { get; }
|
||||
|
||||
public double VRVFlowKgPerH { get; }
|
||||
public double LiqRefFlowKgPerH { get; }
|
||||
public double LubeFlowKgPerH { get; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 干度计算输出模型。
|
||||
/// </summary>
|
||||
public readonly struct Result
|
||||
{
|
||||
public Result(
|
||||
double gasFlowKgPerH,
|
||||
double gasEnthalpy_kJkg,
|
||||
double liquidEnthalpy_kJkg,
|
||||
double satLiquidEnthalpy_kJkg,
|
||||
double satVaporEnthalpy_kJkg,
|
||||
bool isDryness1Success,
|
||||
double dryness1_01,
|
||||
double hMix1_kJkg,
|
||||
string error1,
|
||||
bool isDryness2Success,
|
||||
double dryness2_01,
|
||||
double hMix2_kJkg,
|
||||
string error2)
|
||||
{
|
||||
GasFlowKgPerH = gasFlowKgPerH;
|
||||
GasEnthalpy_kJkg = gasEnthalpy_kJkg;
|
||||
LiquidEnthalpy_kJkg = liquidEnthalpy_kJkg;
|
||||
SatLiquidEnthalpy_kJkg = satLiquidEnthalpy_kJkg;
|
||||
SatVaporEnthalpy_kJkg = satVaporEnthalpy_kJkg;
|
||||
|
||||
IsDryness1Success = isDryness1Success;
|
||||
Dryness1_01 = dryness1_01;
|
||||
HMix1_kJkg = hMix1_kJkg;
|
||||
Error1 = error1 ?? string.Empty;
|
||||
|
||||
IsDryness2Success = isDryness2Success;
|
||||
Dryness2_01 = dryness2_01;
|
||||
HMix2_kJkg = hMix2_kJkg;
|
||||
Error2 = error2 ?? string.Empty;
|
||||
}
|
||||
|
||||
public double GasFlowKgPerH { get; }
|
||||
|
||||
public double GasEnthalpy_kJkg { get; }
|
||||
public double LiquidEnthalpy_kJkg { get; }
|
||||
public double SatLiquidEnthalpy_kJkg { get; }
|
||||
public double SatVaporEnthalpy_kJkg { get; }
|
||||
|
||||
public bool IsDryness1Success { get; }
|
||||
public double Dryness1_01 { get; }
|
||||
public double HMix1_kJkg { get; }
|
||||
public string Error1 { get; }
|
||||
|
||||
public bool IsDryness2Success { get; }
|
||||
public double Dryness2_01 { get; }
|
||||
public double HMix2_kJkg { get; }
|
||||
public string Error2 { get; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 按既有流程计算干度(两套:干度1/干度2)。
|
||||
/// </summary>
|
||||
/// <param name="input">输入数据。</param>
|
||||
/// <returns>计算结果。</returns>
|
||||
public Result Calculate(Input input)
|
||||
{
|
||||
// 气体流量 kg/h = 冷媒流量 kg/h - 液冷媒流量 kg/h
|
||||
double gasFlowKgPerH = input.VRVFlowKgPerH - input.LiqRefFlowKgPerH;
|
||||
|
||||
// 定义气相质量焓 kJ/kg(注意:保持既有逻辑,默认 0,仅在成功计算时赋值)
|
||||
double gas_hVap_kJkg = 0.0;
|
||||
|
||||
// 步骤1: 计算气路阀前气相焓 h_vap (单相气相)
|
||||
if (TryTPRHO_VaporDensity_ByTP_MPa_C(input.GasPreValvePressBarA * 0.1, input.GasPreValveTempC, out var dVap_molL, out _))
|
||||
{
|
||||
if (TryTHERM_VaporEnthalpy_ByTD(input.GasPreValveTempC, dVap_molL, out var hVap_kJkg, out _))
|
||||
{
|
||||
gas_hVap_kJkg = hVap_kJkg;
|
||||
}
|
||||
}
|
||||
|
||||
// 定义液相质量焓 kJ/kg(保持既有逻辑,默认 0,仅在成功计算时赋值)
|
||||
double liquid_hLiq_kJkg = 0.0;
|
||||
|
||||
// 步骤2: 计算液路阀前液相焓 h_liq (单相液相)
|
||||
if (TryTPRHO_LiquidDensity_ByTP_MPa_C(input.TxvFrPressBarA * 0.1, input.TxvFrTempC, out var dLiq_molL, out _))
|
||||
{
|
||||
if (TryTHERM_LiquidEnthalpy_ByTD(input.TxvFrTempC, dLiq_molL, out var hLiq_kJkg, out _))
|
||||
{
|
||||
liquid_hLiq_kJkg = hLiq_kJkg;
|
||||
}
|
||||
}
|
||||
|
||||
// 定义饱和液/饱和气质量焓 kJ/kg(保持既有逻辑,默认 0,仅在同时成功时赋值)
|
||||
double hSatL_kJkg = 0.0;
|
||||
double hSatV_kJkg = 0.0;
|
||||
|
||||
if (TryGetSaturationLiquidEnthalpy_ByP_MPa(input.InhPressBarA * 0.1, out var satL, out _) &&
|
||||
TryGetSaturationVaporEnthalpy_ByP_MPa(input.InhPressBarA * 0.1, out var satV, out _))
|
||||
{
|
||||
hSatL_kJkg = satL;
|
||||
hSatV_kJkg = satV;
|
||||
}
|
||||
|
||||
// 干度1:mg=气体流量;ml=液体流量
|
||||
bool ok1 = TryComputeDrynessByEnthalpy(
|
||||
gas_hVap_kJkg,
|
||||
liquid_hLiq_kJkg,
|
||||
gasFlowKgPerH,
|
||||
input.LiqRefFlowKgPerH,
|
||||
hSatL_kJkg,
|
||||
hSatV_kJkg,
|
||||
out var dryness1,
|
||||
out var hMix1,
|
||||
out var err1);
|
||||
|
||||
// 干度2:mg=气体流量+润滑油流量;ml=液体流量(保持既有策略)
|
||||
bool ok2 = TryComputeDrynessByEnthalpy2(
|
||||
gas_hVap_kJkg,
|
||||
liquid_hLiq_kJkg,
|
||||
gasFlowKgPerH,
|
||||
input.LubeFlowKgPerH,
|
||||
input.LiqRefFlowKgPerH,
|
||||
hSatL_kJkg,
|
||||
hSatV_kJkg,
|
||||
out var dryness2,
|
||||
out var hMix2,
|
||||
out var err2);
|
||||
|
||||
return new Result(
|
||||
gasFlowKgPerH,
|
||||
gas_hVap_kJkg,
|
||||
liquid_hLiq_kJkg,
|
||||
hSatL_kJkg,
|
||||
hSatV_kJkg,
|
||||
ok1,
|
||||
dryness1,
|
||||
hMix1,
|
||||
err1,
|
||||
ok2,
|
||||
dryness2,
|
||||
hMix2,
|
||||
err2);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取指定组分的摩尔质量(kg/mol)。
|
||||
/// </summary>
|
||||
/// <param name="componentId">组分ID(icomp)。</param>
|
||||
/// <param name="molarMassKgPerMol">摩尔质量(kg/mol)。</param>
|
||||
/// <param name="error">错误信息。</param>
|
||||
/// <returns>是否成功。</returns>
|
||||
private bool TryGetMolarMassKgPerMol(long componentId, out double molarMassKgPerMol, out string error)
|
||||
{
|
||||
molarMassKgPerMol = double.NaN;
|
||||
error = string.Empty;
|
||||
|
||||
try
|
||||
{
|
||||
double wmm = 0, Trp = 0, Tnbpt = 0, Tc = 0, Pc = 0, Dc = 0, Zc = 0, acf = 0, dip = 0, Rgas = 0;
|
||||
lock (_refpropLock)
|
||||
{
|
||||
IRefProp64.INFOdll(ref componentId, ref wmm, ref Trp, ref Tnbpt, ref Tc, ref Pc, ref Dc, ref Zc, ref acf, ref dip, ref Rgas);
|
||||
}
|
||||
|
||||
molarMassKgPerMol = wmm * 0.001;
|
||||
if (double.IsNaN(molarMassKgPerMol) || double.IsInfinity(molarMassKgPerMol) || molarMassKgPerMol <= 0)
|
||||
{
|
||||
error = "无效的摩尔质量";
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
error = $"获取组分{componentId}的摩尔质量时出错: {ex.Message}";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// TPRHOdll 封装:按 T(℃)、P(MPa) 计算“气相”摩尔密度 D [mol/L](kph=2)。
|
||||
/// </summary>
|
||||
private bool TryTPRHO_VaporDensity_ByTP_MPa_C(double pressureMPa, double temperatureC, out double densityMolPerL, out string error)
|
||||
{
|
||||
densityMolPerL = double.NaN;
|
||||
error = string.Empty;
|
||||
|
||||
double tK = temperatureC + 273.15;
|
||||
double pKPa = pressureMPa * 1000.0;
|
||||
|
||||
double[] x = new double[20];
|
||||
x[0] = 1.0;
|
||||
|
||||
long kph = 2;
|
||||
long kguess = 0;
|
||||
double D = 0.0;
|
||||
long ierr = 0;
|
||||
long herrLen = 255;
|
||||
string herr = new string(' ', 255);
|
||||
|
||||
lock (_refpropLock)
|
||||
{
|
||||
IRefProp64.TPRHOdll(ref tK, ref pKPa, x, ref kph, ref kguess, ref D, ref ierr, ref herr, ref herrLen);
|
||||
}
|
||||
|
||||
if (ierr != 0)
|
||||
{
|
||||
error = $"TPRHO 错误: {herr.Trim()} (ierr={ierr})";
|
||||
return false;
|
||||
}
|
||||
|
||||
densityMolPerL = D;
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// THERMdll 封装:按 T(℃) 与 D[mol/L] 计算气相质量焓 h_vap [kJ/kg]。
|
||||
/// </summary>
|
||||
private bool TryTHERM_VaporEnthalpy_ByTD(double temperatureC, double densityMolPerL, out double h_vap_kJ_per_kg, out string error)
|
||||
{
|
||||
h_vap_kJ_per_kg = double.NaN;
|
||||
error = string.Empty;
|
||||
|
||||
double tK = temperatureC + 273.15;
|
||||
double D = densityMolPerL;
|
||||
|
||||
double[] x = new double[20];
|
||||
x[0] = 1.0;
|
||||
|
||||
double pOut = 0, e = 0, hJmol = 0, sJmolK = 0, cv = 0, cp = 0, w = 0, hjt = 0;
|
||||
|
||||
if (!TryGetMolarMassKgPerMol(1, out var molarMassKgPerMol, out error))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
lock (_refpropLock)
|
||||
{
|
||||
IRefProp64.THERMdll(ref tK, ref D, x, ref pOut, ref e, ref hJmol, ref sJmolK, ref cv, ref cp, ref w, ref hjt);
|
||||
}
|
||||
|
||||
h_vap_kJ_per_kg = (hJmol / molarMassKgPerMol) * 0.001;
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// TPRHOdll 封装:按 T(℃)、P(MPa) 计算“液相”摩尔密度 D [mol/L](kph=1)。
|
||||
/// </summary>
|
||||
private bool TryTPRHO_LiquidDensity_ByTP_MPa_C(double pressureMPa, double temperatureC, out double densityMolPerL, out string error)
|
||||
{
|
||||
densityMolPerL = double.NaN;
|
||||
error = string.Empty;
|
||||
|
||||
double tK = temperatureC + 273.15;
|
||||
double pKPa = pressureMPa * 1000.0;
|
||||
|
||||
double[] x = new double[20];
|
||||
x[0] = 1.0;
|
||||
|
||||
long kph = 1;
|
||||
long kguess = 0;
|
||||
double D = 0.0;
|
||||
long ierr = 0;
|
||||
long herrLen = 255;
|
||||
string herr = new string(' ', 255);
|
||||
|
||||
lock (_refpropLock)
|
||||
{
|
||||
IRefProp64.TPRHOdll(ref tK, ref pKPa, x, ref kph, ref kguess, ref D, ref ierr, ref herr, ref herrLen);
|
||||
}
|
||||
|
||||
if (ierr != 0)
|
||||
{
|
||||
error = $"TPRHO(液相) 错误: {herr.Trim()} (ierr={ierr})";
|
||||
return false;
|
||||
}
|
||||
|
||||
densityMolPerL = D;
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// THERMdll 封装:按 T(℃) 与 D[mol/L] 计算液相质量焓 h_liq [kJ/kg]。
|
||||
/// </summary>
|
||||
private bool TryTHERM_LiquidEnthalpy_ByTD(double temperatureC, double densityMolPerL, out double h_liq_kJ_per_kg, out string error)
|
||||
{
|
||||
h_liq_kJ_per_kg = double.NaN;
|
||||
error = string.Empty;
|
||||
|
||||
double tK = temperatureC + 273.15;
|
||||
double D = densityMolPerL;
|
||||
|
||||
double[] x = new double[20];
|
||||
x[0] = 1.0;
|
||||
|
||||
double pOut = 0, e = 0, hJmol = 0, sJmolK = 0, cv = 0, cp = 0, w = 0, hjt = 0;
|
||||
|
||||
if (!TryGetMolarMassKgPerMol(1, out var molarMassKgPerMol, out error))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
lock (_refpropLock)
|
||||
{
|
||||
IRefProp64.THERMdll(ref tK, ref D, x, ref pOut, ref e, ref hJmol, ref sJmolK, ref cv, ref cp, ref w, ref hjt);
|
||||
}
|
||||
|
||||
h_liq_kJ_per_kg = (hJmol / molarMassKgPerMol) * 0.001;
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// SATPdll:由压力 P(MPa) 求饱和温度 Tsat[K]、饱和液/气摩尔密度 Dl/Dv [mol/L]。
|
||||
/// </summary>
|
||||
private bool TrySATP_SaturationByP_MPa(double pressureMPa, out double tSatK, out double Dl_molL, out double Dv_molL, out string error)
|
||||
{
|
||||
tSatK = double.NaN;
|
||||
Dl_molL = double.NaN;
|
||||
Dv_molL = double.NaN;
|
||||
error = string.Empty;
|
||||
|
||||
double pKPa = pressureMPa * 1000.0;
|
||||
double[] x = new double[20];
|
||||
x[0] = 1.0;
|
||||
|
||||
long kph = 1;
|
||||
double Dl = 0, Dv = 0;
|
||||
double[] xliq = new double[20];
|
||||
double[] xvap = new double[20];
|
||||
long ierr = 0, herrLen = 255;
|
||||
string herr = new string(' ', 255);
|
||||
|
||||
lock (_refpropLock)
|
||||
{
|
||||
IRefProp64.SATPdll(ref pKPa, x, ref kph, ref tSatK, ref Dl, ref Dv, xliq, xvap, ref ierr, ref herr, ref herrLen);
|
||||
}
|
||||
|
||||
if (ierr != 0)
|
||||
{
|
||||
error = $"SATP 错误: {herr.Trim()} (ierr={ierr})";
|
||||
return false;
|
||||
}
|
||||
|
||||
Dl_molL = Dl;
|
||||
Dv_molL = Dv;
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// THERMdll:由 T[K] 与 D[mol/L] 计算质量比焓 h[kJ/kg]。
|
||||
/// </summary>
|
||||
private bool TryTHERM_Enthalpy_kJkg_ByT_K_D(double temperatureK, double densityMolPerL, out double h_kJ_per_kg, out string error)
|
||||
{
|
||||
h_kJ_per_kg = double.NaN;
|
||||
error = string.Empty;
|
||||
|
||||
double tK = temperatureK;
|
||||
double D = densityMolPerL;
|
||||
|
||||
double[] x = new double[20];
|
||||
x[0] = 1.0;
|
||||
|
||||
double pOut = 0, e = 0, hJmol = 0, sJmolK = 0, cv = 0, cp = 0, w = 0, hjt = 0;
|
||||
|
||||
if (!TryGetMolarMassKgPerMol(1, out var molarMassKgPerMol, out error))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
lock (_refpropLock)
|
||||
{
|
||||
IRefProp64.THERMdll(ref tK, ref D, x, ref pOut, ref e, ref hJmol, ref sJmolK, ref cv, ref cp, ref w, ref hjt);
|
||||
}
|
||||
|
||||
h_kJ_per_kg = (hJmol / molarMassKgPerMol) * 0.001;
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 便捷:由压力 P(MPa) 直接得到“饱和液”质量比焓 h_liq[kJ/kg]。
|
||||
/// </summary>
|
||||
private bool TryGetSaturationLiquidEnthalpy_ByP_MPa(double pressureMPa, out double h_liq_kJkg, out string error)
|
||||
{
|
||||
h_liq_kJkg = double.NaN;
|
||||
error = string.Empty;
|
||||
|
||||
if (!TrySATP_SaturationByP_MPa(pressureMPa, out double tSatK, out double Dl, out _, out error))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return TryTHERM_Enthalpy_kJkg_ByT_K_D(tSatK, Dl, out h_liq_kJkg, out error);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 便捷:由压力 P(MPa) 直接得到“饱和气”质量比焓 h_vap[kJ/kg]。
|
||||
/// </summary>
|
||||
private bool TryGetSaturationVaporEnthalpy_ByP_MPa(double pressureMPa, out double h_vap_kJkg, out string error)
|
||||
{
|
||||
h_vap_kJkg = double.NaN;
|
||||
error = string.Empty;
|
||||
|
||||
if (!TrySATP_SaturationByP_MPa(pressureMPa, out double tSatK, out _, out double Dv, out error))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return TryTHERM_Enthalpy_kJkg_ByT_K_D(tSatK, Dv, out h_vap_kJkg, out error);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 按图片的最终流程计算干度:
|
||||
/// 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
|
||||
/// </summary>
|
||||
private bool TryComputeDrynessByEnthalpy(
|
||||
double hVap_kJkg,
|
||||
double hLiq_kJkg,
|
||||
double mGas_kg_h,
|
||||
double mLiq_kg_h,
|
||||
double hSatL_kJkg,
|
||||
double hSatV_kJkg,
|
||||
out double dryness,
|
||||
out double hMix_kJkg,
|
||||
out string error)
|
||||
{
|
||||
dryness = double.NaN;
|
||||
hMix_kJkg = double.NaN;
|
||||
error = string.Empty;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
double mg = Math.Max(0.0, mGas_kg_h);
|
||||
double ml = Math.Max(0.0, mLiq_kg_h);
|
||||
double mSum = mg + ml;
|
||||
if (mSum <= 0)
|
||||
{
|
||||
error = "气液质量流量之和为 0,无法进行加权混合焓计算";
|
||||
return false;
|
||||
}
|
||||
|
||||
hMix_kJkg = (hVap_kJkg * mg + hLiq_kJkg * ml) / mSum;
|
||||
|
||||
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;
|
||||
|
||||
if (double.IsNaN(x) || double.IsInfinity(x))
|
||||
{
|
||||
error = "干度计算结果异常(NaN/Inf)";
|
||||
return false;
|
||||
}
|
||||
|
||||
dryness = Math.Min(1.0, Math.Max(0.0, x));
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 按图片的最终流程计算干度2:
|
||||
/// 计算逻辑同干度1,但气体流量 mg = 气体流量 + 润滑油流量。
|
||||
/// </summary>
|
||||
private bool TryComputeDrynessByEnthalpy2(
|
||||
double hVap_kJkg,
|
||||
double hLiq_kJkg,
|
||||
double mGas_kg_h,
|
||||
double lubeFlow_kg_h,
|
||||
double mLiq_kg_h,
|
||||
double hSatL_kJkg,
|
||||
double hSatV_kJkg,
|
||||
out double dryness,
|
||||
out double hMix_kJkg,
|
||||
out string error)
|
||||
{
|
||||
dryness = double.NaN;
|
||||
hMix_kJkg = double.NaN;
|
||||
error = string.Empty;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
hMix_kJkg = (hVap_kJkg * mg + hLiq_kJkg * ml) / mSum;
|
||||
|
||||
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;
|
||||
|
||||
if (double.IsNaN(x) || double.IsInfinity(x))
|
||||
{
|
||||
error = "干度计算结果异常(NaN/Inf)";
|
||||
return false;
|
||||
}
|
||||
|
||||
dryness = Math.Min(1.0, Math.Max(0.0, x));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
173
CapMachine.Wpf/PPCalculation/PPCalculation-物性计算说明.md
Normal file
173
CapMachine.Wpf/PPCalculation/PPCalculation-物性计算说明.md
Normal file
@@ -0,0 +1,173 @@
|
||||
# PPCalculation 物性计算说明
|
||||
|
||||
本文档用于说明当前工程中 **PPC 物性计算** 的整体数据流、输入输出、单位约定、关键规则,以及 REFPROP 调用链路,便于后续维护与复用。
|
||||
|
||||
## 1. 代码入口与职责边界
|
||||
|
||||
- **入口服务**:`CapMachine.Wpf.Services.PPCService`
|
||||
- 负责:
|
||||
- 从 `TagManager` 读取实时数据(压力、温度、功率、流量、转速等)。
|
||||
- 调用物性计算器(Calculator)完成计算。
|
||||
- 将结果写回 Tag(干度、过热/过冷、Qh/Qc、COP、效率等)。
|
||||
- 负责 REFPROP 初始化(SETPATH/SETUP)与全局串行化锁。
|
||||
- 不负责:
|
||||
- 具体的热力性质求解细节(已下沉到 Calculator)。
|
||||
|
||||
- **干度计算器**:`CapMachine.Wpf.PPCalculation.EnthalpyDrynessCalculator`
|
||||
- 职责:基于“加权混合焓 + 吸气压力下饱和焓差”的方法,计算干度。
|
||||
|
||||
- **六参数计算器**:`CapMachine.Wpf.PPCalculation.ThermodynamicSixResultsCalculator`
|
||||
- 职责:计算六个核心性能/效率结果:
|
||||
- `Qc`、`Qh`、`COPc`、`COPh`、`ηs`、`ηv`
|
||||
- 内部封装 REFPROP 计算链路、单位换算、以及关键规则(如 h3 的 Tsat-10°C)。
|
||||
|
||||
## 2. 单位约定(非常重要)
|
||||
|
||||
### 2.1 Tag 输入单位(来自 PLC/界面)
|
||||
|
||||
- 压力:`BarA`
|
||||
- 温度:`℃`
|
||||
- 功率:`W`(HV[W])
|
||||
- 冷媒总流量:`kg/h`
|
||||
- 转速:`rpm`
|
||||
- 排量:`cc`(cm³/rev)
|
||||
|
||||
### 2.2 REFPROP 常用单位(在 Calculator 内部处理)
|
||||
|
||||
REFPROP 不同接口参数单位不完全一致,工程中统一由 Calculator 进行换算。
|
||||
|
||||
- 温度:`K`
|
||||
- 压力:常见为 `kPa`(例如 SATP/TPRHO 采用 kPa)
|
||||
- 摩尔密度:`mol/L`
|
||||
- 焓:`J/mol`(THERM 输出),最终换算为 `kJ/kg`
|
||||
- 熵:`J/(mol·K)`(THERM 输出),最终换算为 `kJ/(kg·K)`
|
||||
|
||||
典型换算:
|
||||
- `BarA -> MPa`:乘 `0.1`
|
||||
- `MPa -> kPa`:乘 `1000`
|
||||
- `℃ -> K`:加 `273.15`
|
||||
- `J/mol -> kJ/kg`:`(J/mol) / (kg/mol) * 0.001`
|
||||
|
||||
## 3. 运行周期与整体数据流
|
||||
|
||||
`PPCService.RtScanDeviceStart()` 周期性执行(约 100ms 一次),主要步骤:
|
||||
|
||||
1. **REFPROP 幂等初始化**(第一次进入或未初始化时)
|
||||
- 调用 `EnsureRefpropInitialized()`
|
||||
- 内部在 `_refpropLock` 下执行:
|
||||
- `SETPATHdll` 设置流体库路径
|
||||
- `SETUPdll` 载入工质(当前默认 `R134A.FLD`)
|
||||
|
||||
2. **过热度/过冷度计算(当前仍在服务内直接调用 SATP)**
|
||||
- 吸气侧:由吸气压力求 `Tsat`,与吸气温度做差得到过热度
|
||||
- 膨胀阀前侧:由膨胀阀前压力求 `Tsat`,与膨胀阀前温度做差得到过冷度
|
||||
|
||||
3. **干度计算**(调用 `EnthalpyDrynessCalculator`)
|
||||
- 读取:
|
||||
- 气路阀前压力/温度(GasPreValve P/T)
|
||||
- 膨胀阀前压力/温度(TxvFr P/T)
|
||||
- 吸气压力(InhP)
|
||||
- 冷媒总流量(VRV)
|
||||
- 液体流量(LiqRefFlow)
|
||||
- 当前实现中:润滑油流量 `lubeFlowKgPerH` 固定为 `0.0`(不参与干度计算)。
|
||||
- 输出:
|
||||
- `Dryness1` 写入 `干度[%]` Tag(*100)
|
||||
- `Dryness2` 写入 `PPCService.DrynessTag2Value`(*100,用于界面绑定)
|
||||
|
||||
4. **六参数计算**(调用 `ThermodynamicSixResultsCalculator.TryCalculate`)
|
||||
- 读取输入:
|
||||
- 吸气 P/T(BarA/℃)
|
||||
- 排气 P/T(BarA/℃)
|
||||
- 膨胀阀前 P/T(BarA/℃)
|
||||
- 冷媒总流量(kg/h)
|
||||
- HV 功率(W)
|
||||
- 转速(rpm)
|
||||
- 排量(cc)
|
||||
- 输出写回:
|
||||
- `制热量Qh[W]`(kW * 1000)
|
||||
- `制冷量Qc[W]`(kW * 1000)
|
||||
- `压缩机性能系数(制热)`(COPh)
|
||||
- `压缩机性能系数(制冷)`(COPc)
|
||||
- `等熵效率ns[%]`
|
||||
- `容积效率nv[%]`
|
||||
|
||||
## 4. 干度计算(EnthalpyDrynessCalculator)概要
|
||||
|
||||
### 4.1 输入
|
||||
|
||||
- `GasPreValvePressBarA`
|
||||
- `GasPreValveTempC`
|
||||
- `TxvFrPressBarA`
|
||||
- `TxvFrTempC`
|
||||
- `InhPressBarA`
|
||||
- `VrvFlowKgPerH`
|
||||
- `LiqRefFlowKgPerH`
|
||||
- `LubeFlowKgPerH`(当前传 0)
|
||||
|
||||
### 4.2 核心思路
|
||||
|
||||
1. 分别求取:
|
||||
- 气路阀前气相焓 `h_vap`
|
||||
- 膨胀阀前液相焓 `h_liq`
|
||||
2. 由总流量与液体流量推算气体流量,按质量流量计算混合焓 `h_mix`。
|
||||
3. 由吸气压力求饱和液/饱和气焓:`h_satL`、`h_satV`。
|
||||
4. 干度:
|
||||
|
||||
`x = (h_mix - h_satL) / (h_satV - h_satL)`
|
||||
|
||||
并进行必要的边界处理(除零、NaN、限幅等由 Calculator 内实现)。
|
||||
|
||||
## 5. 六参数计算(ThermodynamicSixResultsCalculator)概要
|
||||
|
||||
### 5.1 输出结果
|
||||
|
||||
- `Qc`:制冷量(kW)
|
||||
- `Qh`:制热量(kW)
|
||||
- `COPc`:制冷 COP
|
||||
- `COPh`:制热 COP
|
||||
- `ηs`:等熵效率(%)
|
||||
- `ηv`:容积效率(%)
|
||||
|
||||
### 5.2 h3(液路阀前/冷凝出口)关键规则:Tsat-10°C
|
||||
|
||||
该规则已封装在 `ThermodynamicSixResultsCalculator` 内部:
|
||||
|
||||
- 由**排气压力**计算饱和温度 `Tsat_discharge`
|
||||
- 取 `T_for_h3 = Tsat_discharge - 10°C`
|
||||
- 用 `TxvFrPress` 与 `T_for_h3` 求液体点焓 `h3`
|
||||
|
||||
注意:这是为了对齐现场 LabVIEW 流程/截图对比,属于业务约束。
|
||||
|
||||
### 5.3 典型计算链路(概念级)
|
||||
|
||||
- h1/s1:吸气点(由吸气 P/T 求物性)
|
||||
- h2:排气点(由排气 P/T 求物性)
|
||||
- h2s:等熵压缩出口点(由排气压力 + s1 求物性)
|
||||
- h3:液体点(由 TxvFrPress + (Tsat(DischargePress)-10°C) 求物性)
|
||||
|
||||
由焓差与质量流量计算 Qc/Qh,并结合功率得到 COP。
|
||||
|
||||
## 6. REFPROP 初始化与线程安全
|
||||
|
||||
- `PPCService` 内使用静态锁:`_refpropLock`
|
||||
- 原因:REFPROP Fortran DLL 内部通常存在全局状态/非线程安全调用。
|
||||
- 约束:
|
||||
- `EnsureRefpropInitialized()` 必须在锁内进行。
|
||||
- 所有直接 REFPROP 原生调用也必须串行化。
|
||||
|
||||
Calculator 内部同样通过外部传入的锁对象串行化 REFPROP 调用。
|
||||
|
||||
## 7. 结果写回约定
|
||||
|
||||
- `DrynessTag`:按百分比写回(`x * 100`)。
|
||||
- `DrynessTag2Value`:按百分比用于界面绑定(`x * 100`)。
|
||||
- `Qh/Qc`:Tag 单位为 `W`,Calculator 输出为 `kW`,写回时乘 `1000`。
|
||||
|
||||
## 8. 扩展/维护建议
|
||||
|
||||
- 如后续希望让 `PPCService` 更纯粹:
|
||||
- 可将过热度/过冷度计算也下沉到独立 Calculator(避免在 Service 里直接调用 SATP)。
|
||||
- 工质切换:
|
||||
- 当前 `EnsureRefpropInitialized()` 默认只加载 `R134A.FLD`。
|
||||
- 若要支持 `R1234yf` 等,需要根据配置选择对应 `.FLD` 文件。
|
||||
|
||||
87
CapMachine.Wpf/PPCalculation/SuperheatSubcoolCalculator.cs
Normal file
87
CapMachine.Wpf/PPCalculation/SuperheatSubcoolCalculator.cs
Normal file
@@ -0,0 +1,87 @@
|
||||
using System;
|
||||
|
||||
namespace CapMachine.Wpf.PPCalculation
|
||||
{
|
||||
/// <summary>
|
||||
/// 过热度/过冷度计算器。
|
||||
///
|
||||
/// 说明:该类仅负责封装 SATPdll 调用与计算公式,保持与历史流程一致。
|
||||
/// - 压力换算保持原逻辑:BarA * 100.0
|
||||
/// - 温度换算保持原逻辑:Tsat[K] - 273.15
|
||||
/// - 失败时返回 0(与原先在服务中直接写 Tag 的行为一致)
|
||||
/// </summary>
|
||||
public sealed class SuperheatSubcoolCalculator
|
||||
{
|
||||
private readonly object _refpropLock;
|
||||
|
||||
/// <summary>
|
||||
/// 构造函数。
|
||||
/// </summary>
|
||||
/// <param name="refpropLock">REFPROP 全局锁(REFPROP DLL 非线程安全,需串行化调用)。</param>
|
||||
public SuperheatSubcoolCalculator(object refpropLock)
|
||||
{
|
||||
_refpropLock = refpropLock ?? throw new ArgumentNullException(nameof(refpropLock));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 按既有流程计算过热度/过冷度。
|
||||
/// </summary>
|
||||
/// <param name="inhPressBarA">吸气压力(BarA)。</param>
|
||||
/// <param name="inhTempC">吸气温度(℃)。</param>
|
||||
/// <param name="txvFrPressBarA">膨胀阀前压力(BarA)。</param>
|
||||
/// <param name="txvFrTempC">膨胀阀前温度(℃)。</param>
|
||||
/// <param name="superheatK">过热度(K)。失败时为 0。</param>
|
||||
/// <param name="subcoolK">过冷度(K)。失败时为 0。</param>
|
||||
public void Calculate(
|
||||
double inhPressBarA,
|
||||
double inhTempC,
|
||||
double txvFrPressBarA,
|
||||
double txvFrTempC,
|
||||
out double superheatK,
|
||||
out double subcoolK)
|
||||
{
|
||||
superheatK = 0.0;
|
||||
subcoolK = 0.0;
|
||||
|
||||
long iErr;
|
||||
long kph = 1;
|
||||
|
||||
double te = 0.0;
|
||||
double te1 = 0.0;
|
||||
double p = 0.0;
|
||||
double p1 = 0.0;
|
||||
double Dl = 0.0;
|
||||
double Dv = 0.0;
|
||||
|
||||
double[] x = new double[20], xliq = new double[20], xvap = new double[20];
|
||||
x[0] = 1.0;
|
||||
|
||||
//p = Convert.ToDouble(textBox2.Text) * 1000.0;//textBox2 Comp.吸气压力(kpa)
|
||||
p = inhPressBarA * 100.0;// 保持你原有流程:将 BarA 当作 MPa? 历史代码为 *1000.0,不改变你的算法
|
||||
|
||||
p1 = txvFrPressBarA * 100.0;// 保持你原有流程
|
||||
//p1 = Convert.ToDouble(textBox3.Text) * 1000.0;//textBox3 Evap.膨胀阀前压力(Mpa)
|
||||
// 统一放入同一把锁中,避免并发导致的 Fortran 读文件/状态竞态
|
||||
string herr = new string(' ', 255); long herrLen = 255; iErr = 0;
|
||||
lock (_refpropLock)
|
||||
{
|
||||
IRefProp64.SATPdll(ref p, x, ref kph, ref te, ref Dl, ref Dv, xliq, xvap, ref iErr, ref herr, ref herrLen);
|
||||
}
|
||||
|
||||
if (iErr == 0)
|
||||
superheatK = Math.Abs(inhTempC - (te - 273.15));
|
||||
else
|
||||
superheatK = 0;
|
||||
|
||||
herr = new string(' ', 255); herrLen = 255; iErr = 0;
|
||||
lock (_refpropLock)
|
||||
{
|
||||
IRefProp64.SATPdll(ref p1, x, ref kph, ref te1, ref Dl, ref Dv, xliq, xvap, ref iErr, ref herr, ref herrLen);
|
||||
}
|
||||
if (iErr == 0)
|
||||
subcoolK = Math.Abs(txvFrTempC - (te1 - 273.15));
|
||||
else
|
||||
subcoolK = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,996 @@
|
||||
using CapMachine.Core;
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Text;
|
||||
|
||||
namespace CapMachine.Wpf.PPCalculation
|
||||
{
|
||||
/// <summary>
|
||||
/// 六个物性结果(制热量/COP(制热)/等熵效率/制冷量/COP(制冷)/容积效率)计算封装类。
|
||||
///
|
||||
/// 说明:
|
||||
/// - 本类用于将原先位于 PPCService 的计算过程完整搬迁为独立类,方便后续维护与对比验证。
|
||||
/// - 计算公式、单位换算、REFPROP 调用链路应与现有实现保持一致,仅做结构性封装。
|
||||
/// </summary>
|
||||
public sealed class ThermodynamicSixResultsCalculator
|
||||
{
|
||||
private readonly object _refpropLock;
|
||||
|
||||
private static volatile bool _rpInitialized;
|
||||
private static string _rpFluidFile = string.Empty;
|
||||
|
||||
private double _h3TempOffset_C = -10.0;
|
||||
|
||||
public void SetH3TempOffset_C(double offsetC)
|
||||
{
|
||||
if (double.IsNaN(offsetC) || double.IsInfinity(offsetC))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_h3TempOffset_C = offsetC;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 构造函数。
|
||||
/// </summary>
|
||||
/// <param name="refpropLock">REFPROP 全局互斥锁对象(建议传入与 PPCService 相同的锁对象,避免并发竞态)。</param>
|
||||
public ThermodynamicSixResultsCalculator(object refpropLock)
|
||||
{
|
||||
_refpropLock = refpropLock ?? throw new ArgumentNullException(nameof(refpropLock));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 输入模型(从 Tag 或外部来源读取后传入)。
|
||||
/// </summary>
|
||||
public readonly struct Input
|
||||
{
|
||||
public Input(
|
||||
double suctionPress_BarA,
|
||||
double suctionTemp_C,
|
||||
double dischargePress_BarA,
|
||||
double dischargeTemp_C,
|
||||
double txvFrPress_BarA,
|
||||
double txvFrTemp_C,
|
||||
double hvPower_W,
|
||||
double totalFlow_kg_h,
|
||||
double speed_rpm,
|
||||
double displacement_cc)
|
||||
{
|
||||
SuctionPress_BarA = suctionPress_BarA;
|
||||
SuctionTemp_C = suctionTemp_C;
|
||||
DischargePress_BarA = dischargePress_BarA;
|
||||
DischargeTemp_C = dischargeTemp_C;
|
||||
TxvFrPress_BarA = txvFrPress_BarA;
|
||||
TxvFrTemp_C = txvFrTemp_C;
|
||||
HvPower_W = hvPower_W;
|
||||
TotalFlow_kg_h = totalFlow_kg_h;
|
||||
Speed_rpm = speed_rpm;
|
||||
Displacement_cc = displacement_cc;
|
||||
}
|
||||
|
||||
public double SuctionPress_BarA { get; }
|
||||
public double SuctionTemp_C { get; }
|
||||
|
||||
public double DischargePress_BarA { get; }
|
||||
public double DischargeTemp_C { get; }
|
||||
|
||||
public double TxvFrPress_BarA { get; }
|
||||
public double TxvFrTemp_C { get; }
|
||||
|
||||
public double HvPower_W { get; }
|
||||
public double TotalFlow_kg_h { get; }
|
||||
|
||||
public double Speed_rpm { get; }
|
||||
public double Displacement_cc { get; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 计算输出模型。
|
||||
/// </summary>
|
||||
public readonly struct Result
|
||||
{
|
||||
public Result(
|
||||
double heatingCapacityQh_kW,
|
||||
double coolingCapacityQc_kW,
|
||||
double copHeating,
|
||||
double copCooling,
|
||||
double isentropicEfficiencyPct,
|
||||
double volumetricEfficiencyPct,
|
||||
double mRef_kg_s,
|
||||
double w_kW,
|
||||
double h1_kJkg,
|
||||
double s1_JmolK,
|
||||
double v1_m3kg,
|
||||
double h2_kJkg,
|
||||
double h3_kJkg,
|
||||
double h2s_kJkg)
|
||||
{
|
||||
HeatingCapacityQh_kW = heatingCapacityQh_kW;
|
||||
CoolingCapacityQc_kW = coolingCapacityQc_kW;
|
||||
COPHeating = copHeating;
|
||||
COPCooling = copCooling;
|
||||
IsentropicEfficiencyPct = isentropicEfficiencyPct;
|
||||
VolumetricEfficiencyPct = volumetricEfficiencyPct;
|
||||
|
||||
MRef_kg_s = mRef_kg_s;
|
||||
W_kW = w_kW;
|
||||
|
||||
H1_kJkg = h1_kJkg;
|
||||
S1_JmolK = s1_JmolK;
|
||||
V1_m3kg = v1_m3kg;
|
||||
H2_kJkg = h2_kJkg;
|
||||
H3_kJkg = h3_kJkg;
|
||||
H2s_kJkg = h2s_kJkg;
|
||||
}
|
||||
|
||||
public double HeatingCapacityQh_kW { get; }
|
||||
public double CoolingCapacityQc_kW { get; }
|
||||
public double COPHeating { get; }
|
||||
public double COPCooling { get; }
|
||||
public double IsentropicEfficiencyPct { get; }
|
||||
public double VolumetricEfficiencyPct { get; }
|
||||
|
||||
public double MRef_kg_s { get; }
|
||||
public double W_kW { get; }
|
||||
|
||||
public double H1_kJkg { get; }
|
||||
public double S1_JmolK { get; }
|
||||
public double V1_m3kg { get; }
|
||||
public double H2_kJkg { get; }
|
||||
public double H3_kJkg { get; }
|
||||
public double H2s_kJkg { get; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 计算六个物性结果。
|
||||
///
|
||||
/// 返回值:
|
||||
/// - true:至少已成功计算 Qh/Qc/COP/ηs;容积效率若失败将返回 NaN,但本方法仍返回 true,并通过 error 输出警告信息。
|
||||
/// - false:关键输入/REFPROP 计算失败。
|
||||
/// </summary>
|
||||
/// <param name="input">输入参数。</param>
|
||||
/// <param name="result">输出结果。</param>
|
||||
/// <param name="error">错误/警告信息。</param>
|
||||
/// <returns>是否成功。</returns>
|
||||
public bool TryCalculate(Input input, out Result result, out string error)
|
||||
{
|
||||
result = default;
|
||||
error = string.Empty;
|
||||
|
||||
if (!EnsureRefpropInitialized(out var initErr))
|
||||
{
|
||||
error = initErr;
|
||||
return false;
|
||||
}
|
||||
|
||||
var w_W = input.HvPower_W;
|
||||
if (!double.IsNaN(w_W) && !double.IsInfinity(w_W) && w_W == 0)
|
||||
{
|
||||
result = new Result(
|
||||
heatingCapacityQh_kW: 0,
|
||||
coolingCapacityQc_kW: 0,
|
||||
copHeating: 0,
|
||||
copCooling: 0,
|
||||
isentropicEfficiencyPct: 0,
|
||||
volumetricEfficiencyPct: 0,
|
||||
mRef_kg_s: 0,
|
||||
w_kW: 0,
|
||||
h1_kJkg: 0,
|
||||
s1_JmolK: 0,
|
||||
v1_m3kg: 0,
|
||||
h2_kJkg: 0,
|
||||
h3_kJkg: 0,
|
||||
h2s_kJkg: 0);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!TryGetCompressorPower_kW(input, out var w_kW, out var wErr))
|
||||
{
|
||||
error = wErr;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!TryGetRefrigerantMassFlow_kg_s(input, out var mRef_kg_s, out var mRefErr))
|
||||
{
|
||||
error = mRefErr;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!TryGetVaporPointState_ByTP_BarA_C(input.SuctionPress_BarA, input.SuctionTemp_C, out var h1_kJkg, out var s1_JmolK, out var v1_m3kg, out var p1Err))
|
||||
{
|
||||
error = $"h1/s1/吸气比容计算失败: {p1Err}";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!TryGetVaporPointEnthalpy_ByTP_BarA_C(input.DischargePress_BarA, input.DischargeTemp_C, out var h2_kJkg, out var p2Err))
|
||||
{
|
||||
error = $"h2 计算失败: {p2Err}";
|
||||
return false;
|
||||
}
|
||||
|
||||
double txvFrTempForH3_C = input.TxvFrTemp_C;
|
||||
if (TryGetTxvFrTempForH3_ByDischargePress_BarA(input.DischargePress_BarA, out var derivedTxvFrTempForH3_C, out var satWarn))
|
||||
{
|
||||
txvFrTempForH3_C = derivedTxvFrTempForH3_C;
|
||||
}
|
||||
else if (!string.IsNullOrWhiteSpace(satWarn))
|
||||
{
|
||||
error = string.IsNullOrWhiteSpace(error)
|
||||
? $"h3温度改用SATP(排气压力)计算Tsat失败,已回退使用TxvFrTemp_C。原因: {satWarn}"
|
||||
: $"{error}; h3温度改用SATP(排气压力)计算Tsat失败,已回退使用TxvFrTemp_C。原因: {satWarn}";
|
||||
}
|
||||
|
||||
if (!TryGetLiquidPointEnthalpy_ByTP_BarA_C(input.TxvFrPress_BarA, txvFrTempForH3_C, out var h3_kJkg, out var p3Err))
|
||||
{
|
||||
error = $"h3 计算失败: {p3Err}";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!TryGetIsentropicOutletEnthalpy_h2s_ByP2AndS1_BarA(input.DischargePress_BarA, s1_JmolK, out var h2s_kJkg, out var h2sErr))
|
||||
{
|
||||
error = $"h2s 计算失败: {h2sErr}";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!TryComputeCapacitiesAndCOP(mRef_kg_s, h1_kJkg, h2_kJkg, h3_kJkg, w_kW, out var qh_kW, out var qc_kW, out var copH, out var copC, out var capErr))
|
||||
{
|
||||
error = capErr;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!TryComputeIsentropicEfficiencyPct(mRef_kg_s, h1_kJkg, h2s_kJkg, w_kW, out var etaS_pct, out var etaSErr))
|
||||
{
|
||||
error = etaSErr;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!TryComputeVolumetricEfficiencyPct(mRef_kg_s, v1_m3kg, input.Speed_rpm, input.Displacement_cc, out var etaV_pct, out var etaVErr))
|
||||
{
|
||||
result = new Result(
|
||||
heatingCapacityQh_kW: qh_kW,
|
||||
coolingCapacityQc_kW: qc_kW,
|
||||
copHeating: copH,
|
||||
copCooling: copC,
|
||||
isentropicEfficiencyPct: etaS_pct,
|
||||
volumetricEfficiencyPct: double.NaN,
|
||||
mRef_kg_s: mRef_kg_s,
|
||||
w_kW: w_kW,
|
||||
h1_kJkg: h1_kJkg,
|
||||
s1_JmolK: s1_JmolK,
|
||||
v1_m3kg: v1_m3kg,
|
||||
h2_kJkg: h2_kJkg,
|
||||
h3_kJkg: h3_kJkg,
|
||||
h2s_kJkg: h2s_kJkg);
|
||||
|
||||
error = etaVErr;
|
||||
return true;
|
||||
}
|
||||
|
||||
result = new Result(
|
||||
heatingCapacityQh_kW: qh_kW,
|
||||
coolingCapacityQc_kW: qc_kW,
|
||||
copHeating: copH,
|
||||
copCooling: copC,
|
||||
isentropicEfficiencyPct: etaS_pct,
|
||||
volumetricEfficiencyPct: etaV_pct,
|
||||
mRef_kg_s: mRef_kg_s,
|
||||
w_kW: w_kW,
|
||||
h1_kJkg: h1_kJkg,
|
||||
s1_JmolK: s1_JmolK,
|
||||
v1_m3kg: v1_m3kg,
|
||||
h2_kJkg: h2_kJkg,
|
||||
h3_kJkg: h3_kJkg,
|
||||
h2s_kJkg: h2s_kJkg);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 输出调试快照到 Console/Debug(用于人工对比验证)。
|
||||
/// </summary>
|
||||
/// <param name="title">标题/阶段标识。</param>
|
||||
/// <param name="input">输入。</param>
|
||||
/// <param name="result">输出结果(可为 null,表示计算失败时仅输出输入)。</param>
|
||||
/// <param name="error">错误/警告。</param>
|
||||
public static void PrintDebugSnapshotToConsole(string title, Input input, Result? result, string error)
|
||||
{
|
||||
void Print(string line)
|
||||
{
|
||||
try { Debug.WriteLine(line); } catch { }
|
||||
try { Console.WriteLine(line); } catch { }
|
||||
}
|
||||
|
||||
Print($"================ {title} ================");
|
||||
Print("--- Inputs ---");
|
||||
Print($"Suction : T1={input.SuctionTemp_C} °C, P1={input.SuctionPress_BarA} BarA");
|
||||
Print($"Discharge : T2={input.DischargeTemp_C} °C, P2={input.DischargePress_BarA} BarA");
|
||||
Print($"TXV-before : T3={input.TxvFrTemp_C} °C, P3={input.TxvFrPress_BarA} BarA");
|
||||
Print($"Flow : mTotal={input.TotalFlow_kg_h} kg/h");
|
||||
Print($"Power(HV) : W={input.HvPower_W} W");
|
||||
Print($"Speed : n={input.Speed_rpm} rpm");
|
||||
Print($"Disp : disp={input.Displacement_cc} cc");
|
||||
|
||||
if (result.HasValue)
|
||||
{
|
||||
var r = result.Value;
|
||||
Print("--- Intermediate (computed) ---");
|
||||
Print($"mRef={r.MRef_kg_s:F8} kg/s, W={r.W_kW:F6} kW");
|
||||
Print($"h1={r.H1_kJkg:F6} kJ/kg");
|
||||
Print($"s1={r.S1_JmolK:F6} J/(mol·K)");
|
||||
Print($"v1={r.V1_m3kg:F8} m3/kg");
|
||||
Print($"h2={r.H2_kJkg:F6} kJ/kg");
|
||||
Print($"h3={r.H3_kJkg:F6} kJ/kg");
|
||||
Print($"h2s={r.H2s_kJkg:F6} kJ/kg");
|
||||
|
||||
Print("--- Final (computed) ---");
|
||||
Print($"Qc={r.CoolingCapacityQc_kW:F5} kW");
|
||||
Print($"COP(cool)={r.COPCooling:F5}");
|
||||
Print($"Qh={r.HeatingCapacityQh_kW:F5} kW");
|
||||
Print($"COP(heat)={r.COPHeating:F5}");
|
||||
Print($"etaS={r.IsentropicEfficiencyPct:F4} %");
|
||||
Print($"etaV={r.VolumetricEfficiencyPct:F3} %");
|
||||
}
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(error))
|
||||
{
|
||||
Print($"--- Error/Warning ---\r\n{error}");
|
||||
}
|
||||
|
||||
Print("====================================================");
|
||||
}
|
||||
|
||||
private bool EnsureRefpropInitialized(out string error)
|
||||
{
|
||||
error = string.Empty;
|
||||
if (_rpInitialized) return true;
|
||||
|
||||
try
|
||||
{
|
||||
lock (_refpropLock)
|
||||
{
|
||||
if (_rpInitialized) return true;
|
||||
|
||||
string hpath = ConfigHelper.GetValue("FluidsPath");
|
||||
if (string.IsNullOrWhiteSpace(hpath)) hpath = @".\PPCalculation\REFPROP\FLUIDS";
|
||||
|
||||
string configuredCryogen = ConfigHelper.GetValue("Cryogen");
|
||||
if (string.IsNullOrWhiteSpace(configuredCryogen)) configuredCryogen = "R134a";
|
||||
|
||||
string hfldCore = configuredCryogen.Equals("R134a", StringComparison.OrdinalIgnoreCase)
|
||||
? "R134A.FLD"
|
||||
: "R134A.FLD";
|
||||
|
||||
long size = hpath.Length;
|
||||
string hpathPadded = hpath + new string(' ', Math.Max(0, 255 - (int)size));
|
||||
IRefProp64.SETPATHdll(hpathPadded, ref size);
|
||||
|
||||
long numComps = 1;
|
||||
string hfld = hfldCore;
|
||||
size = hfld.Length;
|
||||
string hfldPadded = hfld + new string(' ', Math.Max(0, 10000 - (int)size));
|
||||
|
||||
string hfmix = "hmx.bnc" + new string(' ', 255);
|
||||
string hrf = "DEF";
|
||||
string herr = new string(' ', 255);
|
||||
long ierr = 0;
|
||||
long hfldLen = hfldPadded.Length, hfmixLen = hfmix.Length, hrfLen = hrf.Length, herrLen = herr.Length;
|
||||
|
||||
IRefProp64.SETUPdll(ref numComps, ref hfldPadded, ref hfmix, ref hrf,
|
||||
ref ierr, ref herr, ref hfldLen, ref hfmixLen, ref hrfLen, ref herrLen);
|
||||
if (ierr != 0)
|
||||
{
|
||||
error = $"REFPROP 初始化失败: {herr.Trim()} (ierr={ierr})";
|
||||
_rpInitialized = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
_rpInitialized = true;
|
||||
_rpFluidFile = hfldCore;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
error = $"REFPROP 初始化异常: {ex.Message}";
|
||||
_rpInitialized = false;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private static double GetMolarMass()
|
||||
{
|
||||
double wmm = 0, Trp = 0, Tnbpt = 0, Tc = 0, Pc = 0, Dc = 0, Zc = 0, acf = 0, dip = 0, Rgas = 0;
|
||||
long componentId = 1;
|
||||
IRefProp64.INFOdll(ref componentId, ref wmm, ref Trp, ref Tnbpt, ref Tc, ref Pc, ref Dc, ref Zc, ref acf, ref dip, ref Rgas);
|
||||
return wmm * 0.001;
|
||||
}
|
||||
|
||||
private bool TryGetCompressorPower_kW(Input input, out double w_kW, out string error)
|
||||
{
|
||||
w_kW = double.NaN;
|
||||
error = string.Empty;
|
||||
|
||||
double w_W = input.HvPower_W;
|
||||
if (double.IsNaN(w_W) || double.IsInfinity(w_W) || w_W <= 0)
|
||||
{
|
||||
error = $"无效压缩机功率 HV[W]={w_W}";
|
||||
return false;
|
||||
}
|
||||
|
||||
w_kW = w_W / 1000.0;
|
||||
return true;
|
||||
}
|
||||
|
||||
private bool TryGetRefrigerantMassFlow_kg_s(Input input, out double mRef_kg_s, out string error)
|
||||
{
|
||||
mRef_kg_s = double.NaN;
|
||||
error = string.Empty;
|
||||
|
||||
double mTotal_kg_h = input.TotalFlow_kg_h;
|
||||
if (double.IsNaN(mTotal_kg_h) || double.IsInfinity(mTotal_kg_h))
|
||||
{
|
||||
error = "总流量(冷媒流量)为 NaN/Inf";
|
||||
return false;
|
||||
}
|
||||
|
||||
double mRef_kg_h = mTotal_kg_h;
|
||||
if (mRef_kg_h <= 0)
|
||||
{
|
||||
error = $"冷媒质量流量<=0,总流量={mTotal_kg_h}kg/h";
|
||||
return false;
|
||||
}
|
||||
|
||||
mRef_kg_s = mRef_kg_h / 3600.0;
|
||||
return true;
|
||||
}
|
||||
|
||||
private bool TryGetVaporPointEnthalpy_ByTP_BarA_C(double pressureBarA, double temperatureC, out double h_kJkg, out string error)
|
||||
{
|
||||
h_kJkg = double.NaN;
|
||||
error = string.Empty;
|
||||
|
||||
if (!TryTPFLSH_ByTP_BarA_C(pressureBarA, temperatureC, out _, out var h_Jmol, out _, out _, out var flashErr))
|
||||
{
|
||||
error = flashErr;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!TryConvertH_Jmol_To_kJkg(h_Jmol, out h_kJkg, out var hErr))
|
||||
{
|
||||
error = hErr;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private bool TryGetLiquidPointEnthalpy_ByTP_BarA_C(double pressureBarA, double temperatureC, out double h_kJkg, out string error)
|
||||
{
|
||||
h_kJkg = double.NaN;
|
||||
error = string.Empty;
|
||||
|
||||
double pMPa = pressureBarA * 0.1;
|
||||
if (!TryTPRHO_LiquidDensity_ByTP_MPa_C(pMPa, temperatureC, out var d_molL, out var dErr))
|
||||
{
|
||||
error = dErr;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!TryTHERM_LiquidEnthalpy_ByTD(temperatureC, d_molL, out h_kJkg, out var hErr))
|
||||
{
|
||||
error = hErr;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private bool TryGetVaporPointState_ByTP_BarA_C(
|
||||
double pressureBarA,
|
||||
double temperatureC,
|
||||
out double h_kJkg,
|
||||
out double s_JmolK,
|
||||
out double v_m3kg,
|
||||
out string error)
|
||||
{
|
||||
h_kJkg = double.NaN;
|
||||
s_JmolK = double.NaN;
|
||||
v_m3kg = double.NaN;
|
||||
error = string.Empty;
|
||||
|
||||
if (!TryTPFLSH_ByTP_BarA_C(pressureBarA, temperatureC, out var d_molL, out var h_Jmol, out var sOut_JmolK, out _, out var flashErr))
|
||||
{
|
||||
error = flashErr;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!TryConvertH_Jmol_To_kJkg(h_Jmol, out h_kJkg, out var hErr))
|
||||
{
|
||||
error = hErr;
|
||||
return false;
|
||||
}
|
||||
|
||||
s_JmolK = sOut_JmolK;
|
||||
if (double.IsNaN(s_JmolK) || double.IsInfinity(s_JmolK))
|
||||
{
|
||||
error = "无效吸气熵";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!TryConvertMolarDensityToSpecificVolume(d_molL, out v_m3kg, out var vErr))
|
||||
{
|
||||
error = vErr;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private bool TryGetIsentropicOutletEnthalpy_h2s_ByP2AndS1_BarA(double dischargePressureBarA, double suctionEntropy_JmolK, out double h2s_kJkg, out string error)
|
||||
{
|
||||
h2s_kJkg = double.NaN;
|
||||
error = string.Empty;
|
||||
|
||||
if (!EnsureRefpropInitialized(out var initErr))
|
||||
{
|
||||
error = initErr;
|
||||
return false;
|
||||
}
|
||||
|
||||
double pKPa = dischargePressureBarA * 100.0;
|
||||
if (pKPa <= 0)
|
||||
{
|
||||
error = $"无效排气压力: {dischargePressureBarA} BarA";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (double.IsNaN(suctionEntropy_JmolK) || double.IsInfinity(suctionEntropy_JmolK))
|
||||
{
|
||||
error = "无效吸气熵 s1";
|
||||
return false;
|
||||
}
|
||||
|
||||
double s_JmolK = suctionEntropy_JmolK;
|
||||
|
||||
double[] z = new double[20];
|
||||
z[0] = 1.0;
|
||||
|
||||
double t = 0.0;
|
||||
double d = 0.0;
|
||||
double Dl = 0.0;
|
||||
double Dv = 0.0;
|
||||
double[] xliq = new double[20];
|
||||
double[] xvap = new double[20];
|
||||
double q = 0.0;
|
||||
double ee = 0.0;
|
||||
double h = 0.0;
|
||||
double Cv = 0.0;
|
||||
double Cp = 0.0;
|
||||
double w = 0.0;
|
||||
long ierr = 0;
|
||||
long herrLen = 255;
|
||||
string herr = new string(' ', 255);
|
||||
|
||||
lock (_refpropLock)
|
||||
{
|
||||
IRefProp64.PSFLSHdll(ref pKPa, ref s_JmolK, z, ref t, ref d, ref Dl, ref Dv, xliq, xvap, ref q, ref ee, ref h, ref Cv, ref Cp, ref w, ref ierr, ref herr, ref herrLen);
|
||||
}
|
||||
|
||||
if (ierr != 0)
|
||||
{
|
||||
error = $"PSFLSH 错误: {herr.Trim()} (ierr={ierr})";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!TryConvertH_Jmol_To_kJkg(h, out h2s_kJkg, out var hConvErr))
|
||||
{
|
||||
error = hConvErr;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private bool TryComputeCapacitiesAndCOP(
|
||||
double mRef_kg_s,
|
||||
double h1_kJkg,
|
||||
double h2_kJkg,
|
||||
double h3_kJkg,
|
||||
double w_kW,
|
||||
out double qh_kW,
|
||||
out double qc_kW,
|
||||
out double copHeating,
|
||||
out double copCooling,
|
||||
out string error)
|
||||
{
|
||||
qh_kW = double.NaN;
|
||||
qc_kW = double.NaN;
|
||||
copHeating = double.NaN;
|
||||
copCooling = double.NaN;
|
||||
error = string.Empty;
|
||||
|
||||
if (mRef_kg_s <= 0 || double.IsNaN(mRef_kg_s) || double.IsInfinity(mRef_kg_s))
|
||||
{
|
||||
error = "无效冷媒质量流量";
|
||||
return false;
|
||||
}
|
||||
if (w_kW <= 0 || double.IsNaN(w_kW) || double.IsInfinity(w_kW))
|
||||
{
|
||||
error = "无效压缩机功率";
|
||||
return false;
|
||||
}
|
||||
|
||||
qh_kW = mRef_kg_s * (h2_kJkg - h3_kJkg);
|
||||
qc_kW = mRef_kg_s * (h1_kJkg - h3_kJkg);
|
||||
|
||||
copHeating = qh_kW / w_kW;
|
||||
copCooling = qc_kW / w_kW;
|
||||
return true;
|
||||
}
|
||||
|
||||
private bool TryComputeIsentropicEfficiencyPct(double mRef_kg_s, double h1_kJkg, double h2s_kJkg, double w_kW, out double etaS_pct, out string error)
|
||||
{
|
||||
etaS_pct = double.NaN;
|
||||
error = string.Empty;
|
||||
|
||||
if (double.IsNaN(mRef_kg_s) || double.IsInfinity(mRef_kg_s) || mRef_kg_s <= 0)
|
||||
{
|
||||
error = "无效冷媒质量流量";
|
||||
return false;
|
||||
}
|
||||
if (double.IsNaN(w_kW) || double.IsInfinity(w_kW) || w_kW <= 0)
|
||||
{
|
||||
error = "无效压缩机功率";
|
||||
return false;
|
||||
}
|
||||
|
||||
double dh_isentropic = h2s_kJkg - h1_kJkg;
|
||||
double eta = (mRef_kg_s * dh_isentropic) / w_kW;
|
||||
if (double.IsNaN(eta) || double.IsInfinity(eta))
|
||||
{
|
||||
error = "等熵效率结果异常";
|
||||
return false;
|
||||
}
|
||||
|
||||
etaS_pct = eta * 100.0;
|
||||
return true;
|
||||
}
|
||||
|
||||
private bool TryComputeVolumetricEfficiencyPct(
|
||||
double mRef_kg_s,
|
||||
double v1_m3kg,
|
||||
double speed_rpm,
|
||||
double displacement_cc,
|
||||
out double etaV_pct,
|
||||
out string error)
|
||||
{
|
||||
etaV_pct = double.NaN;
|
||||
error = string.Empty;
|
||||
|
||||
if (double.IsNaN(speed_rpm) || double.IsInfinity(speed_rpm) || speed_rpm <= 0)
|
||||
{
|
||||
error = $"无效转速: {speed_rpm} rpm";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (double.IsNaN(displacement_cc) || double.IsInfinity(displacement_cc) || displacement_cc <= 0)
|
||||
{
|
||||
error = $"无效排量: {displacement_cc} cc";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (double.IsNaN(v1_m3kg) || double.IsInfinity(v1_m3kg) || v1_m3kg <= 0)
|
||||
{
|
||||
error = "无效吸气比容";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (double.IsNaN(mRef_kg_s) || double.IsInfinity(mRef_kg_s) || mRef_kg_s <= 0)
|
||||
{
|
||||
error = "无效冷媒质量流量";
|
||||
return false;
|
||||
}
|
||||
|
||||
double suctionVolFlow_m3_h = (mRef_kg_s * 3600.0) * v1_m3kg;
|
||||
double theoVolFlow_m3_h = (speed_rpm / 60.0) * displacement_cc * 0.0036;
|
||||
if (theoVolFlow_m3_h <= 0)
|
||||
{
|
||||
error = "理论吸气体积流量<=0";
|
||||
return false;
|
||||
}
|
||||
|
||||
etaV_pct = (suctionVolFlow_m3_h / theoVolFlow_m3_h) * 100.0;
|
||||
return true;
|
||||
}
|
||||
|
||||
private bool TryTPFLSH_ByTP_BarA_C(
|
||||
double pressureBarA,
|
||||
double temperatureC,
|
||||
out double d_molL,
|
||||
out double h_Jmol,
|
||||
out double s_JmolK,
|
||||
out double t_K,
|
||||
out string error)
|
||||
{
|
||||
d_molL = double.NaN;
|
||||
h_Jmol = double.NaN;
|
||||
s_JmolK = double.NaN;
|
||||
t_K = double.NaN;
|
||||
error = string.Empty;
|
||||
|
||||
if (!EnsureRefpropInitialized(out var initErr))
|
||||
{
|
||||
error = initErr;
|
||||
return false;
|
||||
}
|
||||
|
||||
double t = temperatureC + 273.15;
|
||||
double pKPa = pressureBarA * 100.0;
|
||||
|
||||
if (pKPa <= 0)
|
||||
{
|
||||
error = $"无效压力: {pressureBarA} BarA";
|
||||
return false;
|
||||
}
|
||||
|
||||
double[] x = new double[20];
|
||||
x[0] = 1.0;
|
||||
|
||||
double d = 0.0;
|
||||
double Dl = 0.0;
|
||||
double Dv = 0.0;
|
||||
double[] xliq = new double[20];
|
||||
double[] xvap = new double[20];
|
||||
double q = 0.0;
|
||||
double ee = 0.0;
|
||||
double h = 0.0;
|
||||
double ss = 0.0;
|
||||
double Cv = 0.0;
|
||||
double Cp = 0.0;
|
||||
double w = 0.0;
|
||||
long ierr = 0;
|
||||
long herrLen = 255;
|
||||
string herr = new string(' ', 255);
|
||||
|
||||
lock (_refpropLock)
|
||||
{
|
||||
IRefProp64.TPFLSHdll(ref t, ref pKPa, x, ref d, ref Dl, ref Dv, xliq, xvap, ref q, ref ee, ref h, ref ss, ref Cv, ref Cp, ref w, ref ierr, ref herr, ref herrLen);
|
||||
}
|
||||
|
||||
if (ierr != 0)
|
||||
{
|
||||
error = $"TPFLSH 错误: {herr.Trim()} (ierr={ierr})";
|
||||
return false;
|
||||
}
|
||||
|
||||
d_molL = d;
|
||||
h_Jmol = h;
|
||||
s_JmolK = ss;
|
||||
t_K = t;
|
||||
return true;
|
||||
}
|
||||
|
||||
private bool TryConvertH_Jmol_To_kJkg(double h_Jmol, out double h_kJkg, out string error)
|
||||
{
|
||||
h_kJkg = double.NaN;
|
||||
error = string.Empty;
|
||||
|
||||
double molarMassKgPerMol = GetMolarMass();
|
||||
if (molarMassKgPerMol <= 0)
|
||||
{
|
||||
error = "无效的摩尔质量";
|
||||
return false;
|
||||
}
|
||||
|
||||
h_kJkg = (h_Jmol / molarMassKgPerMol) * 0.001;
|
||||
return true;
|
||||
}
|
||||
|
||||
private bool TryConvertMolarDensityToSpecificVolume(double d_molL, out double v_m3kg, out string error)
|
||||
{
|
||||
v_m3kg = double.NaN;
|
||||
error = string.Empty;
|
||||
|
||||
if (double.IsNaN(d_molL) || double.IsInfinity(d_molL) || d_molL <= 0)
|
||||
{
|
||||
error = $"无效摩尔密度: {d_molL} mol/L";
|
||||
return false;
|
||||
}
|
||||
|
||||
double molarMassKgPerMol = GetMolarMass();
|
||||
if (molarMassKgPerMol <= 0)
|
||||
{
|
||||
error = "无效的摩尔质量";
|
||||
return false;
|
||||
}
|
||||
|
||||
double rho_kg_m3 = d_molL * molarMassKgPerMol * 1000.0;
|
||||
if (rho_kg_m3 <= 0)
|
||||
{
|
||||
error = $"无效密度: {rho_kg_m3} kg/m3";
|
||||
return false;
|
||||
}
|
||||
|
||||
v_m3kg = 1.0 / rho_kg_m3;
|
||||
return true;
|
||||
}
|
||||
|
||||
private bool TryTPRHO_LiquidDensity_ByTP_MPa_C(double pressureMPa, double temperatureC, out double densityMolPerL, out string error)
|
||||
{
|
||||
densityMolPerL = double.NaN;
|
||||
error = string.Empty;
|
||||
|
||||
double tK = temperatureC + 273.15;
|
||||
double pKPa = pressureMPa * 1000.0;
|
||||
|
||||
double[] x = new double[20];
|
||||
x[0] = 1.0;
|
||||
|
||||
long kph = 1;
|
||||
long kguess = 0;
|
||||
double D = 0.0;
|
||||
long ierr = 0;
|
||||
long herrLen = 255;
|
||||
string herr = new string(' ', 255);
|
||||
|
||||
lock (_refpropLock)
|
||||
{
|
||||
IRefProp64.TPRHOdll(ref tK, ref pKPa, x, ref kph, ref kguess, ref D, ref ierr, ref herr, ref herrLen);
|
||||
}
|
||||
|
||||
if (ierr != 0)
|
||||
{
|
||||
error = $"TPRHO(液相) 错误: {herr.Trim()} (ierr={ierr})";
|
||||
return false;
|
||||
}
|
||||
|
||||
densityMolPerL = D;
|
||||
return true;
|
||||
}
|
||||
|
||||
private bool TryTHERM_LiquidEnthalpy_ByTD(double temperatureC, double densityMolPerL, out double h_liq_kJ_per_kg, out string error)
|
||||
{
|
||||
h_liq_kJ_per_kg = double.NaN;
|
||||
error = string.Empty;
|
||||
|
||||
double tK = temperatureC + 273.15;
|
||||
double D = densityMolPerL;
|
||||
|
||||
double[] x = new double[20];
|
||||
x[0] = 1.0;
|
||||
|
||||
double pOut = 0, e = 0, hJmol = 0, sJmolK = 0, cv = 0, cp = 0, w = 0, hjt = 0;
|
||||
|
||||
double molarMassKgPerMol = GetMolarMass();
|
||||
if (molarMassKgPerMol <= 0)
|
||||
{
|
||||
error = "无效的摩尔质量";
|
||||
return false;
|
||||
}
|
||||
|
||||
lock (_refpropLock)
|
||||
{
|
||||
IRefProp64.THERMdll(ref tK, ref D, x, ref pOut, ref e, ref hJmol, ref sJmolK, ref cv, ref cp, ref w, ref hjt);
|
||||
}
|
||||
|
||||
h_liq_kJ_per_kg = (hJmol / molarMassKgPerMol) * 0.001;
|
||||
return true;
|
||||
}
|
||||
|
||||
private bool TrySATP_SaturationTemperatureK_ByP_BarA(double pressureBarA, out double tSatK, out string error)
|
||||
{
|
||||
tSatK = double.NaN;
|
||||
error = string.Empty;
|
||||
|
||||
if (!EnsureRefpropInitialized(out var initErr))
|
||||
{
|
||||
error = initErr;
|
||||
return false;
|
||||
}
|
||||
|
||||
double pKPa = pressureBarA * 100.0;
|
||||
if (pKPa <= 0)
|
||||
{
|
||||
error = $"无效压力: {pressureBarA} BarA";
|
||||
return false;
|
||||
}
|
||||
|
||||
double[] x = new double[20];
|
||||
x[0] = 1.0;
|
||||
|
||||
long kph = 1;
|
||||
double t = 0.0;
|
||||
double Dl = 0.0;
|
||||
double Dv = 0.0;
|
||||
double[] xliq = new double[20];
|
||||
double[] xvap = new double[20];
|
||||
long ierr = 0;
|
||||
long herrLen = 255;
|
||||
string herr = new string(' ', 255);
|
||||
|
||||
lock (_refpropLock)
|
||||
{
|
||||
IRefProp64.SATPdll(ref pKPa, x, ref kph, ref t, ref Dl, ref Dv, xliq, xvap, ref ierr, ref herr, ref herrLen);
|
||||
}
|
||||
|
||||
if (ierr != 0)
|
||||
{
|
||||
error = $"SATP 错误: {herr.Trim()} (ierr={ierr})";
|
||||
return false;
|
||||
}
|
||||
|
||||
tSatK = t;
|
||||
return true;
|
||||
}
|
||||
|
||||
private bool TryGetTxvFrTempForH3_ByDischargePress_BarA(double dischargePressBarA, out double txvFrTempForH3_C, out string warning)
|
||||
{
|
||||
txvFrTempForH3_C = double.NaN;
|
||||
warning = string.Empty;
|
||||
|
||||
if (!TrySATP_SaturationTemperatureK_ByP_BarA(dischargePressBarA, out var tSatK, out var satErr))
|
||||
{
|
||||
warning = satErr;
|
||||
return false;
|
||||
}
|
||||
|
||||
double tSatC = tSatK - 273.15;
|
||||
double offsetC = _h3TempOffset_C;
|
||||
txvFrTempForH3_C = tSatC + offsetC;
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 生成一段便于保存/对比的文本报告。
|
||||
/// </summary>
|
||||
/// <param name="title">标题。</param>
|
||||
/// <param name="input">输入。</param>
|
||||
/// <param name="result">输出。</param>
|
||||
/// <param name="error">错误/警告。</param>
|
||||
/// <returns>报告文本。</returns>
|
||||
public static string BuildDebugReport(string title, Input input, Result? result, string error)
|
||||
{
|
||||
var sb = new StringBuilder(512);
|
||||
sb.AppendLine($"================ {title} ================");
|
||||
sb.AppendLine("--- Inputs ---");
|
||||
sb.AppendLine($"Suction : T1={input.SuctionTemp_C} °C, P1={input.SuctionPress_BarA} BarA");
|
||||
sb.AppendLine($"Discharge : T2={input.DischargeTemp_C} °C, P2={input.DischargePress_BarA} BarA");
|
||||
sb.AppendLine($"TXV-before : T3={input.TxvFrTemp_C} °C, P3={input.TxvFrPress_BarA} BarA");
|
||||
sb.AppendLine($"Flow : mTotal={input.TotalFlow_kg_h} kg/h");
|
||||
sb.AppendLine($"Power(HV) : W={input.HvPower_W} W");
|
||||
sb.AppendLine($"Speed : n={input.Speed_rpm} rpm");
|
||||
sb.AppendLine($"Disp : disp={input.Displacement_cc} cc");
|
||||
|
||||
if (result.HasValue)
|
||||
{
|
||||
var r = result.Value;
|
||||
sb.AppendLine("--- Intermediate (computed) ---");
|
||||
sb.AppendLine($"mRef={r.MRef_kg_s:F8} kg/s, W={r.W_kW:F6} kW");
|
||||
sb.AppendLine($"h1={r.H1_kJkg:F6} kJ/kg");
|
||||
sb.AppendLine($"s1={r.S1_JmolK:F6} J/(mol·K)");
|
||||
sb.AppendLine($"v1={r.V1_m3kg:F8} m3/kg");
|
||||
sb.AppendLine($"h2={r.H2_kJkg:F6} kJ/kg");
|
||||
sb.AppendLine($"h3={r.H3_kJkg:F6} kJ/kg");
|
||||
sb.AppendLine($"h2s={r.H2s_kJkg:F6} kJ/kg");
|
||||
|
||||
sb.AppendLine("--- Final (computed) ---");
|
||||
sb.AppendLine($"Qc={r.CoolingCapacityQc_kW:F5} kW");
|
||||
sb.AppendLine($"COP(cool)={r.COPCooling:F5}");
|
||||
sb.AppendLine($"Qh={r.HeatingCapacityQh_kW:F5} kW");
|
||||
sb.AppendLine($"COP(heat)={r.COPHeating:F5}");
|
||||
sb.AppendLine($"etaS={r.IsentropicEfficiencyPct:F4} %");
|
||||
sb.AppendLine($"etaV={r.VolumetricEfficiencyPct:F3} %");
|
||||
}
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(error))
|
||||
{
|
||||
sb.AppendLine("--- Error/Warning ---");
|
||||
sb.AppendLine(error);
|
||||
}
|
||||
|
||||
sb.AppendLine("====================================================");
|
||||
return sb.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -62,6 +62,9 @@ namespace CapMachine.Wpf.Services
|
||||
case "过热度/过冷度配置":
|
||||
ShowSuperHeatCool(msg.Par);
|
||||
break;
|
||||
case "COP物性参数回差":
|
||||
ShowTherdyConfig(msg.Par);
|
||||
break;
|
||||
case "规则转换":
|
||||
if (SysRunServer.MachineRunState1.IsRunState)
|
||||
{
|
||||
@@ -104,6 +107,17 @@ namespace CapMachine.Wpf.Services
|
||||
});
|
||||
}
|
||||
|
||||
private void ShowTherdyConfig(object par)
|
||||
{
|
||||
DialogService.ShowDialog("DialogTherdyConfigView", new DialogParameters() { { "Name", par } }, (dialogResult) =>
|
||||
{
|
||||
if (dialogResult.Result == ButtonResult.OK)
|
||||
{
|
||||
PPCService.ReloadTherdyH3TempOffset();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -122,13 +122,13 @@ namespace CapMachine.Wpf.Services
|
||||
new Columns(){ Name="OS1温度[℃]",MapType=typeof(float).ToString(),IsIdentity=false,IsPrimary=false},
|
||||
new Columns(){ Name="OS2温度[℃]",MapType=typeof(float).ToString(),IsIdentity=false,IsPrimary=false},
|
||||
new Columns(){ Name="COND2温度[℃]",MapType=typeof(float).ToString(),IsIdentity=false,IsPrimary=false},
|
||||
new Columns(){ Name="EVAP出口温度[℃]",MapType=typeof(float).ToString(),IsIdentity=false,IsPrimary=false},
|
||||
//new Columns(){ Name="EVAP出口温度[℃]",MapType=typeof(float).ToString(),IsIdentity=false,IsPrimary=false},
|
||||
new Columns(){ Name="冷媒流量[kg/h]",MapType=typeof(float).ToString(),IsIdentity=false,IsPrimary=false},
|
||||
new Columns(){ Name="润滑油流量[kg/h]",MapType=typeof(float).ToString(),IsIdentity=false,IsPrimary=false},
|
||||
new Columns(){ Name="排气温度[℃]",MapType=typeof(float).ToString(),IsIdentity=false,IsPrimary=false},
|
||||
new Columns(){ Name="膨胀阀前压力[BarA]",MapType=typeof(float).ToString(),IsIdentity=false,IsPrimary=false},
|
||||
new Columns(){ Name="膨胀阀前温度[℃]",MapType=typeof(float).ToString(),IsIdentity=false,IsPrimary=false},
|
||||
new Columns(){ Name="EVAP出口压力[BarA]",MapType=typeof(float).ToString(),IsIdentity=false,IsPrimary=false},
|
||||
//new Columns(){ Name="EVAP出口压力[BarA]",MapType=typeof(float).ToString(),IsIdentity=false,IsPrimary=false},
|
||||
new Columns(){ Name="腔内压力[BarA]",MapType=typeof(float).ToString(),IsIdentity=false,IsPrimary=false},
|
||||
new Columns(){ Name="压缩机表面温度[℃]",MapType=typeof(float).ToString(),IsIdentity=false,IsPrimary=false},
|
||||
new Columns(){ Name="PTC流量[L/min]",MapType=typeof(float).ToString(),IsIdentity=false,IsPrimary=false},
|
||||
@@ -149,27 +149,27 @@ namespace CapMachine.Wpf.Services
|
||||
new Columns(){ Name="通讯PTC膜温[℃]",MapType=typeof(float).ToString(),IsIdentity=false,IsPrimary=false},
|
||||
new Columns(){ Name="通讯PTC模块温度[℃]",MapType=typeof(float).ToString(),IsIdentity=false,IsPrimary=false},
|
||||
new Columns(){ Name="液冷媒流量[kg/h]",MapType=typeof(float).ToString(),IsIdentity=false,IsPrimary=false},
|
||||
new Columns(){ Name="干度流量[kg/h]",MapType=typeof(float).ToString(),IsIdentity=false,IsPrimary=false},
|
||||
//new Columns(){ Name="干度流量[kg/h]",MapType=typeof(float).ToString(),IsIdentity=false,IsPrimary=false},
|
||||
new Columns(){ Name="H5吸气混合器温度[℃]",MapType=typeof(float).ToString(),IsIdentity=false,IsPrimary=false},
|
||||
new Columns(){ Name="COND循环水温[℃]",MapType=typeof(float).ToString(),IsIdentity=false,IsPrimary=false},
|
||||
new Columns(){ Name="SUBCOOL出口温度[℃]",MapType=typeof(float).ToString(),IsIdentity=false,IsPrimary=false},
|
||||
new Columns(){ Name="吸气混合器出口温度[℃]",MapType=typeof(float).ToString(),IsIdentity=false,IsPrimary=false},
|
||||
new Columns(){ Name="H1出口温度[℃]",MapType=typeof(float).ToString(),IsIdentity=false,IsPrimary=false},
|
||||
new Columns(){ Name="S.C循环水温[℃]",MapType=typeof(float).ToString(),IsIdentity=false,IsPrimary=false},
|
||||
new Columns(){ Name="EVAP循环水温[℃]",MapType=typeof(float).ToString(),IsIdentity=false,IsPrimary=false},
|
||||
//new Columns(){ Name="EVAP循环水温[℃]",MapType=typeof(float).ToString(),IsIdentity=false,IsPrimary=false},
|
||||
new Columns(){ Name="吸气混合器出口压力[BarA]",MapType=typeof(float).ToString(),IsIdentity=false,IsPrimary=false},
|
||||
|
||||
new Columns(){ Name="气路阀前压力[BarA]",MapType=typeof(float).ToString(),IsIdentity=false,IsPrimary=false},
|
||||
new Columns(){ Name="气路阀前温度[℃]",MapType=typeof(float).ToString(),IsIdentity=false,IsPrimary=false},
|
||||
new Columns(){ Name="干度[%]",MapType=typeof(float).ToString(),IsIdentity=false,IsPrimary=false},
|
||||
new Columns(){ Name="干度[-]",MapType=typeof(float).ToString(),IsIdentity=false,IsPrimary=false},
|
||||
new Columns(){ Name="过冷度[K]",MapType=typeof(float).ToString(),IsIdentity=false,IsPrimary=false},
|
||||
new Columns(){ Name="过热度[K]",MapType=typeof(float).ToString(),IsIdentity=false,IsPrimary=false},
|
||||
|
||||
new Columns(){ Name="制热量Qh[W]",MapType=typeof(float).ToString(),IsIdentity=false,IsPrimary=false},
|
||||
new Columns(){ Name="压缩机性能系数(制热)",MapType=typeof(float).ToString(),IsIdentity=false,IsPrimary=false},
|
||||
new Columns(){ Name="压缩机性能系数(制热COP)",MapType=typeof(float).ToString(),IsIdentity=false,IsPrimary=false},
|
||||
new Columns(){ Name="等熵效率ns[%]",MapType=typeof(float).ToString(),IsIdentity=false,IsPrimary=false},
|
||||
new Columns(){ Name="制冷量Qc[W]",MapType=typeof(float).ToString(),IsIdentity=false,IsPrimary=false},
|
||||
new Columns(){ Name="压缩机性能系数(制冷)",MapType=typeof(float).ToString(),IsIdentity=false,IsPrimary=false},
|
||||
new Columns(){ Name="压缩机性能系数(制冷COP)",MapType=typeof(float).ToString(),IsIdentity=false,IsPrimary=false},
|
||||
new Columns(){ Name="容积效率nv[%]",MapType=typeof(float).ToString(),IsIdentity=false,IsPrimary=false},
|
||||
|
||||
new Columns(){ Name="创建时间",MapType="System.DateTime",IsIdentity=false,IsPrimary=false},
|
||||
@@ -701,6 +701,111 @@ namespace CapMachine.Wpf.Services
|
||||
HasHeaderRecord = false,
|
||||
};
|
||||
|
||||
private static readonly HashSet<string> ExcludedCsvHeaderNames = new HashSet<string>(StringComparer.OrdinalIgnoreCase)
|
||||
{
|
||||
"EVAP出口温度[℃]",
|
||||
"EVAP出口压力[BarA]",
|
||||
"干度流量[kg/h]",
|
||||
"EVAP循环水温[℃]",
|
||||
};
|
||||
|
||||
private static readonly object CsvSchemaRewriteLock = new object();
|
||||
private static readonly HashSet<string> CsvSchemaCheckedFiles = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
|
||||
|
||||
private bool TryRewriteCsvWithoutExcludedColumnsIfNeeded(string filePath)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!File.Exists(filePath))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
lock (CsvSchemaRewriteLock)
|
||||
{
|
||||
if (CsvSchemaCheckedFiles.Contains(filePath))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
using (var reader = new StreamReader(filePath, Encoding.UTF8, true))
|
||||
using (var csv = new CsvReader(reader, CultureInfo.CurrentCulture))
|
||||
{
|
||||
if (!csv.Read())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
csv.ReadHeader();
|
||||
var header = csv.HeaderRecord;
|
||||
if (header == null || header.Length == 0)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool containsExcluded = header.Any(h => !string.IsNullOrWhiteSpace(h) && ExcludedCsvHeaderNames.Contains(h.Trim()));
|
||||
if (!containsExcluded)
|
||||
{
|
||||
lock (CsvSchemaRewriteLock)
|
||||
{
|
||||
CsvSchemaCheckedFiles.Add(filePath);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
string tmpPath = filePath + ".tmp";
|
||||
using (var srcReader = new StreamReader(filePath, Encoding.UTF8, true))
|
||||
using (var srcCsv = new CsvReader(srcReader, CultureInfo.CurrentCulture))
|
||||
using (var dstWriter = new StreamWriter(tmpPath, false, Encoding.UTF8))
|
||||
using (var dstCsv = new CsvWriter(dstWriter, CultureInfo.CurrentCulture))
|
||||
{
|
||||
srcCsv.Context.RegisterClassMap<CsvRecordModelMap>();
|
||||
dstCsv.Context.RegisterClassMap<CsvRecordModelMap>();
|
||||
dstCsv.WriteRecords(srcCsv.GetRecords<CsvRecordModel>());
|
||||
}
|
||||
|
||||
string bakPath = filePath + ".bak";
|
||||
if (File.Exists(bakPath))
|
||||
{
|
||||
File.Delete(bakPath);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
File.Replace(tmpPath, filePath, bakPath, true);
|
||||
if (File.Exists(bakPath))
|
||||
{
|
||||
File.Delete(bakPath);
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
if (File.Exists(filePath))
|
||||
{
|
||||
File.Delete(filePath);
|
||||
}
|
||||
File.Move(tmpPath, filePath);
|
||||
if (File.Exists(bakPath))
|
||||
{
|
||||
File.Delete(bakPath);
|
||||
}
|
||||
}
|
||||
|
||||
lock (CsvSchemaRewriteLock)
|
||||
{
|
||||
CsvSchemaCheckedFiles.Add(filePath);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogService?.Error($"重写CSV列失败: {ex.Message}");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 保存到CSV文件
|
||||
/// </summary>
|
||||
@@ -737,6 +842,11 @@ namespace CapMachine.Wpf.Services
|
||||
{
|
||||
lock (ConfigService.CsvFileLock)
|
||||
{
|
||||
if (!TryRewriteCsvWithoutExcludedColumnsIfNeeded(FileFullInfo))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
//往已有的文件增加数据
|
||||
using (var stream = File.Open(FileFullInfo, FileMode.Append, FileAccess.Write, FileShare.ReadWrite))
|
||||
//using (var stream = new FileStream(FileFullInfo, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.ReadWrite))
|
||||
|
||||
@@ -37,8 +37,8 @@ namespace CapMachine.Wpf.Services
|
||||
//}),
|
||||
new NavigationItem("", "计算信息","",new ObservableCollection<NavigationItem>()
|
||||
{
|
||||
new NavigationItem("SuperHeatCool","过热度/过冷度配置","DialogSuperHeatCoolConfigView"),
|
||||
//new NavigationItem("Palette","过冷度",""),
|
||||
new NavigationItem("","过热度/过冷度配置","DialogSuperHeatCoolConfigView"),
|
||||
new NavigationItem("","COP物性参数回差","DialogTherdyConfigView"),
|
||||
}),
|
||||
new NavigationItem("", "规则设置","",new ObservableCollection<NavigationItem>()
|
||||
{
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1202,7 +1202,7 @@
|
||||
},
|
||||
{
|
||||
"Id": 530,
|
||||
"Name": "干度[%]",
|
||||
"Name": "干度[-]",
|
||||
"NameNoUnit": "干度",
|
||||
"EnName": "Dryness",
|
||||
"Group": "计算",
|
||||
@@ -1290,8 +1290,8 @@
|
||||
},
|
||||
{
|
||||
"Id": 570,
|
||||
"Name": "压缩机性能系数(制热)",
|
||||
"NameNoUnit": "压缩机性能系数(制热)",
|
||||
"Name": "压缩机性能系数(制热COP)",
|
||||
"NameNoUnit": "压缩机性能系数(制热COP)",
|
||||
"EnName": "COPHeat",
|
||||
"Group": "计算",
|
||||
"MinValue": 0,
|
||||
@@ -1356,8 +1356,8 @@
|
||||
},
|
||||
{
|
||||
"Id": 600,
|
||||
"Name": "压缩机性能系数(制冷)",
|
||||
"NameNoUnit": "压缩机性能系数(制冷)",
|
||||
"Name": "压缩机性能系数(制冷COP)",
|
||||
"NameNoUnit": "压缩机性能系数(制冷COP)",
|
||||
"EnName": "COPCool",
|
||||
"Group": "计算",
|
||||
"MinValue": 0,
|
||||
|
||||
116
CapMachine.Wpf/ViewModels/DialogTherdyConfigViewModel.cs
Normal file
116
CapMachine.Wpf/ViewModels/DialogTherdyConfigViewModel.cs
Normal file
@@ -0,0 +1,116 @@
|
||||
using CapMachine.Core;
|
||||
using CapMachine.Wpf.Models.PPCalc;
|
||||
using Prism.Commands;
|
||||
using Prism.Services.Dialogs;
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.Windows;
|
||||
|
||||
namespace CapMachine.Wpf.ViewModels
|
||||
{
|
||||
public class DialogTherdyConfigViewModel : DialogViewModel
|
||||
{
|
||||
private const string H3TempOffsetConfigKey = "Therdy_H3TempOffset_C";
|
||||
|
||||
public DialogTherdyConfigViewModel()
|
||||
{
|
||||
Title = "COP物性参数回差";
|
||||
|
||||
TherdyConfig = new TherdyConfigModel();
|
||||
LoadConfig();
|
||||
}
|
||||
|
||||
public TherdyConfigModel TherdyConfig { get; }
|
||||
|
||||
private string _h3TempOffsetText = string.Empty;
|
||||
public string H3TempOffsetText
|
||||
{
|
||||
get { return _h3TempOffsetText; }
|
||||
set { _h3TempOffsetText = value; RaisePropertyChanged(); }
|
||||
}
|
||||
|
||||
private DelegateCommand saveCmd;
|
||||
public DelegateCommand SaveCmd
|
||||
{
|
||||
get
|
||||
{
|
||||
if (saveCmd == null)
|
||||
{
|
||||
saveCmd = new DelegateCommand(SaveCmdMethod);
|
||||
}
|
||||
return saveCmd;
|
||||
}
|
||||
set { saveCmd = value; }
|
||||
}
|
||||
|
||||
private DelegateCommand cancelCmd;
|
||||
public DelegateCommand CancelCmd
|
||||
{
|
||||
get
|
||||
{
|
||||
if (cancelCmd == null)
|
||||
{
|
||||
cancelCmd = new DelegateCommand(CancelCmdMethod);
|
||||
}
|
||||
return cancelCmd;
|
||||
}
|
||||
set { cancelCmd = value; }
|
||||
}
|
||||
|
||||
private void LoadConfig()
|
||||
{
|
||||
try
|
||||
{
|
||||
string raw = ConfigHelper.GetValue(H3TempOffsetConfigKey);
|
||||
if (!string.IsNullOrWhiteSpace(raw) && double.TryParse(raw, NumberStyles.Float, CultureInfo.InvariantCulture, out var v))
|
||||
{
|
||||
TherdyConfig.H3TempOffset_C = v;
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
}
|
||||
|
||||
H3TempOffsetText = TherdyConfig.H3TempOffset_C.ToString(CultureInfo.InvariantCulture);
|
||||
}
|
||||
|
||||
private void SaveConfig()
|
||||
{
|
||||
ConfigHelper.SetValue(H3TempOffsetConfigKey, TherdyConfig.H3TempOffset_C.ToString(CultureInfo.InvariantCulture));
|
||||
}
|
||||
|
||||
private void SaveCmdMethod()
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!double.TryParse(H3TempOffsetText, NumberStyles.Float, CultureInfo.InvariantCulture, out var offsetC))
|
||||
{
|
||||
MessageBox.Show("回差值格式不正确,请输入数字(例如 -10)。", "提示", MessageBoxButton.OK, MessageBoxImage.Warning);
|
||||
return;
|
||||
}
|
||||
|
||||
TherdyConfig.H3TempOffset_C = offsetC;
|
||||
SaveConfig();
|
||||
DialogParameters pars = new DialogParameters
|
||||
{
|
||||
{ "H3TempOffset_C", TherdyConfig.H3TempOffset_C }
|
||||
};
|
||||
RaiseRequestClose(new DialogResult(ButtonResult.OK, pars));
|
||||
}
|
||||
catch
|
||||
{
|
||||
RaiseRequestClose(new DialogResult(ButtonResult.Cancel));
|
||||
}
|
||||
}
|
||||
|
||||
private void CancelCmdMethod()
|
||||
{
|
||||
RaiseRequestClose(new DialogResult(ButtonResult.Cancel));
|
||||
}
|
||||
|
||||
public override void OnDialogOpened(IDialogParameters parameters)
|
||||
{
|
||||
LoadConfig();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -605,8 +605,7 @@ namespace CapMachine.Wpf.ViewModels
|
||||
{
|
||||
if (File.Exists(item.FilePath))//是否存在文件
|
||||
{
|
||||
//Copy文件
|
||||
CopyToFile(item.FilePath, TargetFilePath);
|
||||
ExportFilteredCsvToFolder(item.FilePath, TargetFilePath);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -675,6 +674,42 @@ namespace CapMachine.Wpf.ViewModels
|
||||
File.Copy(SourceFilePath, destinationFilePath, true); // true 表示如果目标文件已存在,则覆盖
|
||||
}
|
||||
|
||||
public void ExportFilteredCsvToFolder(string sourceFilePath, string targetFolderPath)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(sourceFilePath) || string.IsNullOrWhiteSpace(targetFolderPath))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
string destinationFilePath = Path.Combine(targetFolderPath, Path.GetFileName(sourceFilePath));
|
||||
|
||||
try
|
||||
{
|
||||
var csvConfig = new CsvConfiguration(CultureInfo.CurrentCulture)
|
||||
{
|
||||
Delimiter = ",",
|
||||
HeaderValidated = null,
|
||||
MissingFieldFound = null,
|
||||
PrepareHeaderForMatch = args => args.Header?.Trim()
|
||||
};
|
||||
|
||||
using (var reader = new StreamReader(sourceFilePath, Encoding.UTF8, true))
|
||||
using (var csvReader = new CsvReader(reader, csvConfig))
|
||||
using (var writer = new StreamWriter(destinationFilePath, false, Encoding.UTF8))
|
||||
using (var csvWriter = new CsvWriter(writer, csvConfig))
|
||||
{
|
||||
csvReader.Context.RegisterClassMap<CsvRecordModelMap>();
|
||||
csvWriter.Context.RegisterClassMap<CsvRecordModelMap>();
|
||||
csvWriter.WriteRecords(csvReader.GetRecords<CsvRecordModel>());
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger?.Error($"导出CSV失败, 源文件: {sourceFilePath}, 错误: {ex.Message}");
|
||||
System.Windows.MessageBox.Show($"导出CSV失败: {ex.Message}", "提示", MessageBoxButton.OK, MessageBoxImage.Warning);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 复制文件夹及文件
|
||||
/// </summary>
|
||||
|
||||
54
CapMachine.Wpf/Views/DialogTherdyConfigView.xaml
Normal file
54
CapMachine.Wpf/Views/DialogTherdyConfigView.xaml
Normal file
@@ -0,0 +1,54 @@
|
||||
<UserControl x:Class="CapMachine.Wpf.Views.DialogTherdyConfigView"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:local="clr-namespace:CapMachine.Wpf.Views"
|
||||
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
|
||||
mc:Ignorable="d"
|
||||
Width="800"
|
||||
Height="240"
|
||||
d:DesignHeight="450" d:DesignWidth="800">
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition />
|
||||
<RowDefinition Height="auto" />
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<Grid Grid.Row="0">
|
||||
<StackPanel Margin="20" VerticalAlignment="Center" Orientation="Horizontal">
|
||||
<TextBlock
|
||||
Margin="10,0,10,0"
|
||||
VerticalAlignment="Center"
|
||||
FontSize="26"
|
||||
FontWeight="Bold"
|
||||
Foreground="DimGray"
|
||||
Text="排气压力饱和温度回差(℃):" />
|
||||
<TextBox
|
||||
Width="160"
|
||||
Margin="10,0,0,0"
|
||||
HorizontalContentAlignment="Center"
|
||||
VerticalContentAlignment="Center"
|
||||
FontSize="24"
|
||||
Text="{Binding H3TempOffsetText, UpdateSourceTrigger=PropertyChanged}" />
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
|
||||
<StackPanel
|
||||
Grid.Row="1"
|
||||
Margin="0,10,20,10"
|
||||
HorizontalAlignment="Right"
|
||||
Orientation="Horizontal">
|
||||
<Button
|
||||
Margin="10,0"
|
||||
Command="{Binding SaveCmd}"
|
||||
Content="确定"
|
||||
Foreground="White" />
|
||||
<Button
|
||||
Margin="10,0"
|
||||
Command="{Binding CancelCmd}"
|
||||
Content="取消"
|
||||
Foreground="White" />
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
28
CapMachine.Wpf/Views/DialogTherdyConfigView.xaml.cs
Normal file
28
CapMachine.Wpf/Views/DialogTherdyConfigView.xaml.cs
Normal file
@@ -0,0 +1,28 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Data;
|
||||
using System.Windows.Documents;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Media.Imaging;
|
||||
using System.Windows.Navigation;
|
||||
using System.Windows.Shapes;
|
||||
|
||||
namespace CapMachine.Wpf.Views
|
||||
{
|
||||
/// <summary>
|
||||
/// DialogTherdyConfigView.xaml 的交互逻辑
|
||||
/// </summary>
|
||||
public partial class DialogTherdyConfigView : UserControl
|
||||
{
|
||||
public DialogTherdyConfigView()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -211,7 +211,7 @@
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<materialDesign:Card
|
||||
Grid.ColumnSpan="5"
|
||||
Grid.ColumnSpan="4"
|
||||
Margin="3"
|
||||
Background="{DynamicResource MaterialDesignLightBackground}"
|
||||
Foreground="{DynamicResource PrimaryHueLightForegroundBrush}"
|
||||
@@ -232,6 +232,39 @@
|
||||
</StackPanel>
|
||||
</materialDesign:Card>
|
||||
|
||||
<materialDesign:Card
|
||||
Grid.Column="4"
|
||||
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="LimeGreen"
|
||||
Text="" />
|
||||
<TextBlock
|
||||
Foreground="LimeGreen"
|
||||
Style="{StaticResource TitelStyle}"
|
||||
Text="排量:" />
|
||||
<TextBlock
|
||||
VerticalAlignment="Center"
|
||||
FontSize="26"
|
||||
FontWeight="Bold"
|
||||
Text="{Binding PPCService.CurDisplacementCc}" />
|
||||
<TextBlock
|
||||
Margin="5"
|
||||
VerticalAlignment="Center"
|
||||
FontSize="22"
|
||||
FontWeight="Bold"
|
||||
Foreground="LimeGreen"
|
||||
Text="cc" />
|
||||
</StackPanel>
|
||||
</materialDesign:Card>
|
||||
|
||||
<materialDesign:Card
|
||||
Grid.Column="5"
|
||||
Margin="3"
|
||||
|
||||
Reference in New Issue
Block a user