6个物性参数和过热度和过冷度的验证OK

This commit is contained in:
2026-05-08 11:02:55 +08:00
parent 47834ea4dc
commit a8c5cda332
6 changed files with 1387 additions and 2381 deletions

View File

@@ -34,16 +34,9 @@ namespace CapMachine.Wpf.Services
public ILogService Logger { get; }
public MachineRtDataService MachineRtDataService { get; }
public IDialogService DialogService { get; }
private readonly object _refpropLock = new object();
private readonly PPCSuperheatSubcoolCalculator _superheatSubcoolCalculator;
private readonly PPCThermodynamicSixResultsCalculator _thermodynamicSixResultsCalculator;
private readonly EnthalpyDrynessCalculator _enthalpyDrynessCalculator;
private DateTime _lastSuperheatSubcoolErrorLogAt = DateTime.MinValue;
private string _lastSuperheatSubcoolErrorText = string.Empty;
private int _hvZeroStreak;
private readonly SuperheatSubcoolCalculator _superheatSubcoolCalculator;
private readonly ThermodynamicSixResultsCalculator _thermodynamicSixResultsCalculator;
/// <summary>
/// 标签中心
/// </summary>
@@ -114,22 +107,24 @@ namespace CapMachine.Wpf.Services
Subcool = TagManager.DicTags.GetValueOrDefault("过冷度[K]");
HeatingCapacity = TagManager.DicTags.GetValueOrDefault("制热量Qh[KW]")
HeatingCapacityTag = TagManager.DicTags.GetValueOrDefault("制热量Qh[KW]")
?? TagManager.DicTags.GetValueOrDefault("制热量Qh[W]");
COPHeat = TagManager.DicTags.GetValueOrDefault("压缩机性能系数(制热)[K]")
COPHeatTag = TagManager.DicTags.GetValueOrDefault("压缩机性能系数(制热)[K]")
?? TagManager.DicTags.GetValueOrDefault("压缩机性能系数(制热COP)");
IsentrpEff = TagManager.DicTags.GetValueOrDefault("等熵效率ns[%]");
CoolCapacity = TagManager.DicTags.GetValueOrDefault("制冷量Qc[KW]")
IsentrpEffTag = TagManager.DicTags.GetValueOrDefault("等熵效率ns[%]");
CoolCapacityTag = TagManager.DicTags.GetValueOrDefault("制冷量Qc[KW]")
?? TagManager.DicTags.GetValueOrDefault("制冷量Qc[W]");
COPCool = TagManager.DicTags.GetValueOrDefault("压缩机性能系数(制冷)[K]")
COPCoolTag = TagManager.DicTags.GetValueOrDefault("压缩机性能系数(制冷)[K]")
?? TagManager.DicTags.GetValueOrDefault("压缩机性能系数(制冷COP)");
VoltricEff = TagManager.DicTags.GetValueOrDefault("容积效率nv[%]");
VoltricEffTag = TagManager.DicTags.GetValueOrDefault("容积效率nv[%]");
_superheatSubcoolCalculator = new SuperheatSubcoolCalculator(_refpropLock);
_thermodynamicSixResultsCalculator = new ThermodynamicSixResultsCalculator(_refpropLock);
SuperHeatCoolConfig.FluidsPath = ConfigHelper.GetValue("FluidsPath");
SuperHeatCoolConfig.Cryogen = ConfigHelper.GetValue("Cryogen");
_superheatSubcoolCalculator = new PPCSuperheatSubcoolCalculator(_refpropLock);
_thermodynamicSixResultsCalculator = new PPCThermodynamicSixResultsCalculator(_refpropLock);
_enthalpyDrynessCalculator = new EnthalpyDrynessCalculator(_refpropLock);
ReloadTherdyH3TempOffset();
RtScanDeviceStart();
@@ -143,16 +138,16 @@ namespace CapMachine.Wpf.Services
try
{
string raw = ConfigHelper.GetValue(TherdyH3TempOffsetConfigKey);
if (!string.IsNullOrWhiteSpace(raw) && double.TryParse(raw, out var parsed))
if (!string.IsNullOrWhiteSpace(raw) && double.TryParse(raw, NumberStyles.Float, CultureInfo.InvariantCulture, out var parsed))
{
offsetC = parsed;
}
}
catch (Exception ex)
catch
{
Logger?.Error($"读取 {TherdyH3TempOffsetConfigKey} 失败: {ex.Message}");
}
TherdyH3TempOffset_C = offsetC;
_thermodynamicSixResultsCalculator.SetH3TempOffset_C(offsetC);
}
@@ -170,6 +165,17 @@ namespace CapMachine.Wpf.Services
ConfigHelper.SetValue("Cryogen", SuperHeatCoolConfig.Cryogen);
}
private double _therdyH3TempOffset_C = -10.0;
public double TherdyH3TempOffset_C
{
get { return _therdyH3TempOffset_C; }
private set
{
_therdyH3TempOffset_C = value;
RaisePropertyChanged();
}
}
/// <summary>
/// 吸气压力
/// </summary>
@@ -261,27 +267,19 @@ namespace CapMachine.Wpf.Services
/// </summary>
public ITag LubeFlowTag { get; set; }
public ITag HeatingCapacity { get; set; }
public ITag COPHeat { get; set; }
public ITag IsentrpEff { get; set; }
public ITag CoolCapacity { get; set; }
public ITag COPCool { get; set; }
public ITag VoltricEff { get; set; }
public ITag? HeatingCapacityTag { get; set; }
/// <summary>
/// 风量数据-乘以系数的后的最终结果
/// </summary>
private double AirVolumeData { get; set; } = 0.0;
public ITag? COPHeatTag { get; set; }
/// <summary>
/// 风量数据-公式计算的原始数据
/// </summary>
private double AirVolumeDataSource { get; set; } = 0;
public ITag? IsentrpEffTag { get; set; }
public ITag? CoolCapacityTag { get; set; }
public ITag? COPCoolTag { get; set; }
public ITag? VoltricEffTag { get; set; }
/// <summary>
/// 风量喷嘴启用信息数据
/// </summary>
private string RozzleEnableInfo { get; set; } = "";
/// <summary>
/// 启用计算
@@ -293,7 +291,21 @@ namespace CapMachine.Wpf.Services
/// </summary>
private bool DebugLog { get; set; } = false;
private int _CurDisplacementCc;
/// <summary>
/// 当前的排量信息(供 UI 展示)
/// </summary>
public int CurDisplacementCc
{
get { return _CurDisplacementCc; }
set { _CurDisplacementCc = value; RaisePropertyChanged(); }
}
private double _HeatingCapacityQh_kW;
/// <summary>
/// 制热量 Qh [kW]
/// </summary>
public double HeatingCapacityQh_kW
{
get { return _HeatingCapacityQh_kW; }
@@ -301,6 +313,9 @@ namespace CapMachine.Wpf.Services
}
private double _COPHeating;
/// <summary>
/// 压缩机性能系数 COP制热[-]
/// </summary>
public double COPHeating
{
get { return _COPHeating; }
@@ -308,6 +323,9 @@ namespace CapMachine.Wpf.Services
}
private double _IsentropicEfficiencyPct;
/// <summary>
/// 等熵效率 ηs [%]
/// </summary>
public double IsentropicEfficiencyPct
{
get { return _IsentropicEfficiencyPct; }
@@ -315,6 +333,9 @@ namespace CapMachine.Wpf.Services
}
private double _CoolingCapacityQc_kW;
/// <summary>
/// 制冷量 Qc [kW]
/// </summary>
public double CoolingCapacityQc_kW
{
get { return _CoolingCapacityQc_kW; }
@@ -322,6 +343,9 @@ namespace CapMachine.Wpf.Services
}
private double _COPCooling;
/// <summary>
/// 压缩机性能系数 COP制冷[-]
/// </summary>
public double COPCooling
{
get { return _COPCooling; }
@@ -329,6 +353,9 @@ namespace CapMachine.Wpf.Services
}
private double _VolumetricEfficiencyPct;
/// <summary>
/// 容积效率 ηv [%]
/// </summary>
public double VolumetricEfficiencyPct
{
get { return _VolumetricEfficiencyPct; }
@@ -347,39 +374,30 @@ namespace CapMachine.Wpf.Services
await Task.Delay(300);
try
{
_ = TryUpdateSuperheatAndSubcool(out var superheatSubcoolErr);
if (!string.IsNullOrWhiteSpace(superheatSubcoolErr))
double[] x = new double[20];
double wm = 0.0;
// 幂等初始化:仅首次或工质/路径变化时执行 SETPATH/SETUP提高每秒循环效率
if (!EnsureRefpropInitialized(out var initErr))
{
var now = DateTime.UtcNow;
if (!string.Equals(superheatSubcoolErr, _lastSuperheatSubcoolErrorText, StringComparison.Ordinal)
|| (now - _lastSuperheatSubcoolErrorLogAt) >= TimeSpan.FromSeconds(5))
{
Logger?.Error($"过热度/过冷度计算失败: {superheatSubcoolErr}");
_lastSuperheatSubcoolErrorLogAt = now;
_lastSuperheatSubcoolErrorText = superheatSubcoolErr;
}
// 初始化失败,跳过本周期
Logger?.Error($"REFPROP 初始化失败: {initErr}");
continue;
}
//if (TryUpdateDryness(out var drynessErr))
//{
// if (!string.IsNullOrWhiteSpace(drynessErr))
// {
// Logger?.Error($"干度计算警告: {drynessErr}");
// }
//}
//else
//{
// if (!string.IsNullOrWhiteSpace(drynessErr))
// {
// Logger?.Error($"干度计算失败: {drynessErr}");
// }
//}
// WMOL 仅在需要时调用;若调用,需设置 x[0]=1.0(纯工质)
x[0] = 1.0;
IRefProp64.WMOLdll(x, ref wm);
UpdateSuperheatAndSubcool_BySatp();
if (TryUpdateThermodynamicSixResults(out var thermoErr))
{
if (!string.IsNullOrWhiteSpace(thermoErr))
{
//Logger?.Error($"六个物性结果计算警告: {thermoErr}");
//Logger?.Warn($"六个物性结果计算警告: {thermoErr}");
}
}
else
@@ -399,121 +417,6 @@ namespace CapMachine.Wpf.Services
});
}
private bool TryUpdateSuperheatAndSubcool(out string error)
{
error = string.Empty;
bool updated = false;
StringBuilder errorBuilder = new StringBuilder();
if (InhPressTag == null || InhTempTag == null || Superheat == null)
{
AppendCalculationError(errorBuilder, "缺少过热度计算标签");
}
else if (_superheatSubcoolCalculator.TryCalculateSuperheatK(InhPressTag.EngPvValue, InhTempTag.EngPvValue, out var superheatValue, out var superheatErr))
{
Superheat.EngPvValue = Math.Abs(superheatValue);
updated = true;
}
else
{
AppendCalculationError(errorBuilder, superheatErr);
}
if (TxvFrPressTag == null || TxvFrTempTag == null || Subcool == null)
{
AppendCalculationError(errorBuilder, "缺少过冷度计算标签");
}
else if (_superheatSubcoolCalculator.TryCalculateSubcoolK(TxvFrPressTag.EngPvValue, TxvFrTempTag.EngPvValue, out var subcoolValue, out var subcoolErr))
{
Subcool.EngPvValue = Math.Abs(subcoolValue);
updated = true;
}
else
{
AppendCalculationError(errorBuilder, subcoolErr);
}
error = errorBuilder.ToString();
return updated;
}
private static void AppendCalculationError(StringBuilder errorBuilder, string error)
{
if (string.IsNullOrWhiteSpace(error))
{
return;
}
if (errorBuilder.Length > 0)
{
errorBuilder.Append("");
}
errorBuilder.Append(error);
}
private bool TryUpdateDryness(out string error)
{
error = string.Empty;
bool updated = false;
StringBuilder errorBuilder = new StringBuilder();
if (GasPreValvePressTag == null || GasPreValveTempTag == null || TxvFrPressTag == null || TxvFrTempTag == null || InhPressTag == null)
{
AppendCalculationError(errorBuilder, "缺少干度计算压力/温度标签");
error = errorBuilder.ToString();
return false;
}
if (VRVTag == null || LiqRefFlowTag == null)
{
AppendCalculationError(errorBuilder, "缺少干度计算流量标签");
error = errorBuilder.ToString();
return false;
}
double lubeFlowKgPerH = 0.0;
if (LubeFlowTag != null)
{
lubeFlowKgPerH = LubeFlowTag.EngPvValue;
}
var drynessResult = _enthalpyDrynessCalculator.Calculate(
new EnthalpyDrynessCalculator.Input(
gasPreValvePressBarA: GasPreValvePressTag.EngPvValue,
gasPreValveTempC: GasPreValveTempTag.EngPvValue,
txvFrPressBarA: TxvFrPressTag.EngPvValue,
txvFrTempC: TxvFrTempTag.EngPvValue,
inhPressBarA: InhPressTag.EngPvValue,
vrvFlowKgPerH: VRVTag.EngPvValue,
liqRefFlowKgPerH: LiqRefFlowTag.EngPvValue,
lubeFlowKgPerH: lubeFlowKgPerH));
if (drynessResult.IsDryness1Success)
{
if (DrynessTag != null)
{
DrynessTag.EngPvValue = Math.Round(drynessResult.Dryness1_01, 4);
}
updated = true;
}
else
{
AppendCalculationError(errorBuilder, drynessResult.Error1);
}
if (drynessResult.IsDryness2Success)
{
DrynessTag2Value = Math.Round(drynessResult.Dryness2_01, 4);
updated = true;
}
else
{
AppendCalculationError(errorBuilder, drynessResult.Error2);
}
error = errorBuilder.ToString();
return updated;
}
/// <summary>
/// 按流程图更新制热量、COP(制热)、等熵效率、制冷量、COP(制冷)、容积效率。
@@ -532,132 +435,21 @@ namespace CapMachine.Wpf.Services
{
error = string.Empty;
double w_W = HVPwTag?.EngPvValue ?? double.NaN;
if (!double.IsNaN(w_W) && !double.IsInfinity(w_W) && w_W == 0)
if (InhPressTag == null || InhTempTag == null)
{
_hvZeroStreak = Math.Min(_hvZeroStreak + 1, 1000);
if (_hvZeroStreak < 3)
{
return false;
}
HeatingCapacityQh_kW = 0;
CoolingCapacityQc_kW = 0;
COPHeating = 0;
COPCooling = 0;
IsentropicEfficiencyPct = 0;
VolumetricEfficiencyPct = 0;
if (HeatingCapacity != null)
{
HeatingCapacity.EngPvValue = 0;
}
if (COPHeat != null)
{
COPHeat.EngPvValue = 0;
}
if (IsentrpEff != null)
{
IsentrpEff.EngPvValue = 0;
}
if (CoolCapacity != null)
{
CoolCapacity.EngPvValue = 0;
}
if (COPCool != null)
{
COPCool.EngPvValue = 0;
}
if (VoltricEff != null)
{
VoltricEff.EngPvValue = 0;
}
return true;
}
_hvZeroStreak = 0;
// 先把本周期所需的标签值组装为输入模型。
// PPCService 在这里负责完成“标签 -> 领域输入对象”的映射,
// 从而把计算类和 UI/标签层解耦。
if (!TryCreateThermodynamicSixResultsInput(out var input, out var inputErr))
{
error = inputErr;
error = "缺少吸气压力/吸气温度标签";
return false;
}
// 把输入模型交给独立计算类统一完成 6 个结果的热力计算。
// 此处不再在 PPCService 中展开公式,只保留流程调度职责。
if (!_thermodynamicSixResultsCalculator.TryCalculate(input, out var result, out error))
if (TxvFrPressTag == null || TxvFrTempTag == null)
{
error = "缺少膨胀阀前压力/膨胀阀前温度标签";
return false;
}
// 先把结果同步到服务属性,供界面绑定或其他业务读取。
HeatingCapacityQh_kW = result.HeatingCapacityQh_kW;
CoolingCapacityQc_kW = result.CoolingCapacityQc_kW;
COPHeating = result.COPHeating;
COPCooling = result.COPCooling;
IsentropicEfficiencyPct = result.IsentropicEfficiencyPct;
// 再把结果回写到对应工程量标签。
if (HeatingCapacity != null)
if (ExPressTag == null || ExTempTag == null)
{
HeatingCapacity.EngPvValue = string.Equals(HeatingCapacity.Unit, "W", StringComparison.OrdinalIgnoreCase)
? HeatingCapacityQh_kW * 1000.0
: HeatingCapacityQh_kW;
error = "缺少排气压力/排气温度标签";
return false;
}
if (COPHeat != null)
{
COPHeat.EngPvValue = COPHeating;
}
if (IsentrpEff != null)
{
IsentrpEff.EngPvValue = IsentropicEfficiencyPct;
}
if (CoolCapacity != null)
{
CoolCapacity.EngPvValue = string.Equals(CoolCapacity.Unit, "W", StringComparison.OrdinalIgnoreCase)
? CoolingCapacityQc_kW * 1000.0
: CoolingCapacityQc_kW;
}
if (COPCool != null)
{
COPCool.EngPvValue = COPCooling;
}
// 容积效率在旧逻辑中允许单独失败;
// 因此只有拿到有效数值时才回写,避免覆盖已有结果为 NaN/Inf。
if (!double.IsNaN(result.VolumetricEfficiencyPct) && !double.IsInfinity(result.VolumetricEfficiencyPct))
{
VolumetricEfficiencyPct = result.VolumetricEfficiencyPct;
if (VoltricEff != null)
{
VoltricEff.EngPvValue = VolumetricEfficiencyPct;
}
}
return true;
}
/// <summary>
/// 创建六个热力结果值计算所需的输入模型。
/// </summary>
/// <param name="input">
/// 输出输入模型。
/// 该对象是 <see cref="PPCThermodynamicSixResultsCalculator"/> 与 <see cref="PPCService"/> 之间的数据边界:
/// 由服务层负责从标签提取实时值,由计算层只消费该对象而不直接依赖标签。
/// </param>
/// <param name="error">失败原因,通常为缺少标签、缺少排量配置或关键输入不可用。</param>
/// <returns>是否创建成功。</returns>
private bool TryCreateThermodynamicSixResultsInput(out PPCThermodynamicSixResultsCalculationInput input, out string error)
{
input = new PPCThermodynamicSixResultsCalculationInput();
error = string.Empty;
// 依次校验本周期计算所需的全部标签。
// 这里不做公式计算,只保证独立计算类拿到的是一套完整输入。
if (HVPwTag == null)
{
error = "缺少 HV[W] 功率标签";
@@ -668,56 +460,228 @@ namespace CapMachine.Wpf.Services
error = "缺少总流量(冷媒流量)标签";
return false;
}
if (InhPressTag == null || InhTempTag == null)
double suctionPress_BarA = InhPressTag.EngPvValue;
double suctionTemp_C = InhTempTag.EngPvValue;
double dischargePress_BarA = ExPressTag.EngPvValue;
double dischargeTemp_C = ExTempTag.EngPvValue;
double txvFrPress_BarA = TxvFrPressTag.EngPvValue;
double txvFrTemp_C = TxvFrTempTag.EngPvValue;
double totalFlow_kg_h = VRVTag.EngPvValue;
double w_W = HVPwTag.EngPvValue;
double speed_rpm = SpeedTag?.EngPvValue ?? double.NaN;
if (!TryGetCompressorDisplacement_cc(out var disp_cc, out var dispErr))
{
error = "缺少吸气压力/吸气温度标签";
error = dispErr;
return false;
}
if (ExPressTag == null || ExTempTag == null)
{
error = "缺少排气压力/排气温度标签";
return false;
}
if (TxvFrPressTag == null || TxvFrTempTag == null)
{
error = "缺少膨胀阀前压力/膨胀阀前温度标签";
return false;
}
if (SpeedTag == null)
{
error = "缺少转速标签";
return false;
}
if (!TryGetCompressorDisplacement_cc(out var displacementCc, out _))
{
displacementCc = double.NaN;
}
double oilFlowKgPerH = 0.0;
if (LubeFlowTag != null)
//这里把输入数据写死计算出结果。
//#if DEBUG
// // 附件截图输入单位换算MPa -> BarAkW -> W
// suctionPress_BarA = 0.3 * 10.0;
// suctionTemp_C = 10.8;
// dischargePress_BarA = 1.502 * 10.0;
// dischargeTemp_C = 88.4;
// txvFrPress_BarA = 1.494 * 10.0;
// txvFrTemp_C = 45.0;
// totalFlow_kg_h = 100.1;
// w_W = 1.289 * 1000.0;
// speed_rpm = 3004;
// disp_cc = 35;
//#endif
if (!double.IsNaN(w_W) && !double.IsInfinity(w_W) && w_W == 0)
{
oilFlowKgPerH = LubeFlowTag.EngPvValue;
HeatingCapacityQh_kW = 0;
CoolingCapacityQc_kW = 0;
COPHeating = 0;
COPCooling = 0;
IsentropicEfficiencyPct = 0;
VolumetricEfficiencyPct = 0;
if (HeatingCapacityTag != null)
{
HeatingCapacityTag.EngPvValue = 0;
}
if (COPHeatTag != null)
{
COPHeatTag.EngPvValue = 0;
}
if (IsentrpEffTag != null)
{
IsentrpEffTag.EngPvValue = 0;
}
if (CoolCapacityTag != null)
{
CoolCapacityTag.EngPvValue = 0;
}
if (COPCoolTag != null)
{
COPCoolTag.EngPvValue = 0;
}
if (VoltricEffTag != null)
{
VoltricEffTag.EngPvValue = 0;
}
return true;
}
// 将实时标签值与配置值组装为独立计算类可直接消费的输入对象。
input = new PPCThermodynamicSixResultsCalculationInput
{
CompressorPowerW = HVPwTag.EngPvValue,
TotalMassFlowKgPerHour = VRVTag.EngPvValue,
OilMassFlowKgPerHour = oilFlowKgPerH,
SuctionPressureBarA = InhPressTag.EngPvValue,
SuctionTemperatureC = InhTempTag.EngPvValue,
DischargePressureBarA = ExPressTag.EngPvValue,
DischargeTemperatureC = ExTempTag.EngPvValue,
LiquidPressureBarA = TxvFrPressTag.EngPvValue,
LiquidTemperatureC = TxvFrTempTag.EngPvValue,
CompressorSpeedRpm = SpeedTag.EngPvValue,
CompressorDisplacementCc = displacementCc
};
var calcInput = new ThermodynamicSixResultsCalculator.Input(
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: w_W,
totalFlow_kg_h: totalFlow_kg_h,
speed_rpm: speed_rpm,
displacement_cc: disp_cc);
if (!_thermodynamicSixResultsCalculator.TryCalculate(calcInput, out var r, out var calcErr))
{
error = calcErr;
return false;
}
HeatingCapacityQh_kW = r.HeatingCapacityQh_kW;
CoolingCapacityQc_kW = r.CoolingCapacityQc_kW;
COPHeating = r.COPHeating;
COPCooling = r.COPCooling;
IsentropicEfficiencyPct = r.IsentropicEfficiencyPct;
if (HeatingCapacityTag != null)
{
HeatingCapacityTag.EngPvValue = HeatingCapacityQh_kW * 1000.0;
}
if (COPHeatTag != null)
{
COPHeatTag.EngPvValue = COPHeating;
}
if (IsentrpEffTag != null)
{
IsentrpEffTag.EngPvValue = IsentropicEfficiencyPct;
}
if (CoolCapacityTag != null)
{
CoolCapacityTag.EngPvValue = CoolingCapacityQc_kW * 1000.0;
}
if (COPCoolTag != null)
{
COPCoolTag.EngPvValue = COPCooling;
}
if (double.IsNaN(r.VolumetricEfficiencyPct) || double.IsInfinity(r.VolumetricEfficiencyPct))
{
VolumetricEfficiencyPct = double.NaN;
error = calcErr;
return true;
}
VolumetricEfficiencyPct = r.VolumetricEfficiencyPct;
if (VoltricEffTag != null)
{
VoltricEffTag.EngPvValue = VolumetricEfficiencyPct;
}
error = calcErr;
return true;
}
private void UpdateSuperheatAndSubcool_BySatp()
{
_superheatSubcoolCalculator.Calculate(
inhPressBarA: InhPressTag.EngPvValue,
inhTempC: InhTempTag.EngPvValue,
txvFrPressBarA: TxvFrPressTag.EngPvValue,
txvFrTempC: TxvFrTempTag.EngPvValue,
out var superheatK,
out var subcoolK);
Superheat.EngPvValue = superheatK;
Subcool.EngPvValue = subcoolK;
}
// 若类中尚未定义,请添加全局互斥锁,串行化所有 REFPROP 调用
private static readonly object _refpropLock = new object();
// REFPROP 初始化状态(全局、幂等)
private static volatile bool _rpInitialized = false;
/// <summary>
/// 幂等初始化:设置流体路径/工质/参考态;确保全局只初始化一次。
/// 注意:所有 REFPROP 原生调用都需在 _refpropLock 下串行化,包括初始化调用。
/// </summary>
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";
// 现阶段仅使用 R134A.FLD如需扩展可根据 configuredCryogen 选择不同文件
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;
return true;
}
}
catch (Exception ex)
{
error = $"REFPROP 初始化异常: {ex.Message}";
Logger.Error(error);
_rpInitialized = false;
return false;
}
}
/// <summary>
/// 获取压缩机排量。
/// </summary>
@@ -775,5 +739,7 @@ namespace CapMachine.Wpf.Services
displacement_cc = defaultDisplacementCc;
return true;
}
}
}