6个物性参数和过热度和过冷度的验证OK
This commit is contained in:
@@ -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 -> BarA,kW -> 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;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user