Files
CapMachine/CapMachine.Wpf/Services/PPCService.cs

859 lines
34 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using CapMachine.Core;
using CapMachine.Wpf.Models.PPCalc;
using CapMachine.Wpf.Models.Tag;
using CapMachine.Wpf.PPCalculation;
using Prism.Mvvm;
using System;
using System.Globalization;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
namespace CapMachine.Wpf.Services
{
/// <summary>
/// 物性计算的服务
/// </summary>
public class PPCService : BindableBase
{
/// <summary>
/// 计算扫描 Task
/// </summary>
private static Task CalcTask { get; set; } = Task.CompletedTask;
public ConfigService ConfigService { get; }
public ILogService Logger { get; }
public MachineRtDataService MachineRtDataService { get; }
private readonly EnthalpyDrynessCalculator _enthalpyDrynessCalculator;
private readonly ThermodynamicSixResultsCalculator _thermodynamicSixResultsCalculator;
/// <summary>
/// 标签中心
/// </summary>
public TagManager TagManager { get; set; }
/// <summary>
/// 实例化
/// </summary>
public PPCService(ConfigService configService, ILogService logService,
MachineRtDataService machineRtDataService)
{
ConfigService = configService;
Logger = logService;
MachineRtDataService = machineRtDataService;
_enthalpyDrynessCalculator = new EnthalpyDrynessCalculator(_refpropLock);
_thermodynamicSixResultsCalculator = new ThermodynamicSixResultsCalculator(_refpropLock);
TagManager = MachineRtDataService.TagManger;
if (TagManager.TryGetShortTagByName("转速[rpm]", out ShortValueTag? speedShortTag))
{
SpeedTag = speedShortTag!;
}
if (TagManager.TryGetShortTagByName("排气压力[BarA]", out ShortValueTag? exPressShortTag))
{
ExPressTag = exPressShortTag!;
}
if (TagManager.TryGetShortTagByName("排气温度[℃]", out ShortValueTag? exTempShortTag))
{
ExTempTag = exTempShortTag!;
}
if (TagManager.TryGetShortTagByName("HV[W]", out ShortValueTag? hvPwShortTag))
{
HVPwTag = hvPwShortTag!;
}
if (TagManager.TryGetShortTagByName("吸气压力[BarA]", out ShortValueTag? InhPressShortControlTag))
{
InhPressTag = InhPressShortControlTag!;
}
if (TagManager.TryGetShortTagByName("吸气温度[℃]", out ShortValueTag? InhTempShortControlTag))
{
InhTempTag = InhTempShortControlTag!;
}
//InhTempTag = TagManager.DicTags.GetValueOrDefault("吸气温度[℃]")!;
//ComCapBusVolTag = TagManager.DicTags.GetValueOrDefault("通讯母线电压[V]");
//ComCapBusCurTag = TagManager.DicTags.GetValueOrDefault("通讯母线电流[A]");
//ComCapPwTag = TagManager.DicTags.GetValueOrDefault("通讯功率[W]");
//OS2TempTag = TagManager.DicTags.GetValueOrDefault("吸气混合器温度[℃]");
//TxvFrTempTag = TagManager.DicTags.GetValueOrDefault("膨胀阀前温度[℃]")!;
//TxvFrPressTag = TagManager.DicTags.GetValueOrDefault("膨胀阀前压力[BarA]")!;
if (TagManager.TryGetShortTagByName("SUBCOOL出口温度[℃]", out ShortValueTag? TxvFrTempShortTag))
{
TxvFrTempTag = TxvFrTempShortTag!;
}
if (TagManager.TryGetShortTagByName("膨胀阀前压力[BarA]", out ShortValueTag? TxvFrPressShortTag))
{
TxvFrPressTag = TxvFrPressShortTag!;
}
if (TagManager.TryGetShortTagByName("液冷媒流量[kg/h]", out ShortValueTag? LiqRefFlowShortTag))
{
LiqRefFlowTag = LiqRefFlowShortTag!;
}
//kg/h
if (TagManager.TryGetShortTagByName("冷媒流量[kg/h]", out ShortValueTag? VRVShortTag))
{
VRVTag = VRVShortTag!;
}
//润滑油流量
if (TagManager.TryGetShortTagByName("润滑油流量[kg/h]", out ShortValueTag? LubeFlowShortTag))
{
LubeFlowTag = LubeFlowShortTag!;
}
// 气路阀前 P/T用于质量流量加权混合焓的计算LabVIEW 流程)
if (TagManager.TryGetShortTagByName("气路阀前压力[BarA]", out ShortValueTag? gasPreP))
{
GasPreValvePressTag = gasPreP!;
}
if (TagManager.TryGetShortTagByName("气路阀前温度[℃]", out ShortValueTag? gasPreT))
{
GasPreValveTempTag = gasPreT!;
}
//Cond1TempTag = TagManager.DicTags.GetValueOrDefault("冷凝器出口水温[℃]");
//CondInTempTag = TagManager.DicTags.GetValueOrDefault("冷凝器进口温度[℃]");
//Superheat = TagManager.DicTags.GetValueOrDefault("过热度[K]");
//Subcool = TagManager.DicTags.GetValueOrDefault("过冷度[K]");
if (TagManager.TryGetShortTagByName("过热度[K]", out ShortValueTag? SuperheatShortTag))
{
Superheat = SuperheatShortTag!;
}
if (TagManager.TryGetShortTagByName("过冷度[K]", out ShortValueTag? SubcoolShortTag))
{
Subcool = SubcoolShortTag!;
}
// 干度标签(如不存在则仅跳过写入,不抛异常)。优先使用“干度[%]”,其次“干度[-]”。
if (TagManager.TryGetShortTagByName("干度[%]", out ShortValueTag? drynessPct))
{
DrynessTag = drynessPct!;
}
if (TagManager.TryGetShortTagByName("制热量Qh[W]", out ShortValueTag? heatingCapacityTag))
{
HeatingCapacityTag = heatingCapacityTag!;
}
if (TagManager.TryGetShortTagByName("压缩机性能系数(制热)", out ShortValueTag? copHeatTag))
{
COPHeatTag = copHeatTag!;
}
if (TagManager.TryGetShortTagByName("等熵效率ns[%]", out ShortValueTag? isentrpEffTag))
{
IsentrpEffTag = isentrpEffTag!;
}
if (TagManager.TryGetShortTagByName("制冷量Qc[W]", out ShortValueTag? coolCapacityTag))
{
CoolCapacityTag = coolCapacityTag!;
}
if (TagManager.TryGetShortTagByName("压缩机性能系数(制冷)", out ShortValueTag? copCoolTag))
{
COPCoolTag = copCoolTag!;
}
if (TagManager.TryGetShortTagByName("容积效率nv[%]", out ShortValueTag? voltricEffTag))
{
VoltricEffTag = voltricEffTag!;
}
SuperHeatCoolConfig.FluidsPath = ConfigHelper.GetValue("FluidsPath");
SuperHeatCoolConfig.Cryogen = ConfigHelper.GetValue("Cryogen");
RtScanDeviceStart();
}
/// <summary>
/// 当前的配置
/// </summary>
public SuperHeatCoolConfigModel SuperHeatCoolConfig { get; set; } = new SuperHeatCoolConfigModel();
/// <summary>
/// 保存配置信息
/// </summary>
public void SaveSuperHeatCoolConfig()
{
ConfigHelper.SetValue("FluidsPath", SuperHeatCoolConfig.FluidsPath ?? string.Empty);
ConfigHelper.SetValue("Cryogen", SuperHeatCoolConfig.Cryogen ?? string.Empty);
}
/// <summary>
/// 吸气压力
/// </summary>
public ShortValueTag InhPressTag { get; set; } = null!;
/// <summary>
/// 转速标签
/// </summary>
public ShortValueTag? SpeedTag { get; set; }
/// <summary>
/// 排气压力
/// </summary>
public ShortValueTag? ExPressTag { get; set; }
/// <summary>
/// 排气温度
/// </summary>
public ShortValueTag? ExTempTag { get; set; }
/// <summary>
/// 压缩机功率HV 电源)
/// </summary>
public ShortValueTag? HVPwTag { get; set; }
/// <summary>
/// 吸气温度
/// </summary>
public ShortValueTag InhTempTag { get; set; } = null!;
/// <summary>
/// 液体阀前温度
/// </summary>
public ShortValueTag TxvFrTempTag { get; set; } = null!;
/// <summary>
/// 液体阀前压力
/// </summary>
public ShortValueTag TxvFrPressTag { get; set; } = null!;
/// <summary>
/// 过热度
/// </summary>
public ShortValueTag Superheat { get; set; } = null!;
/// <summary>
/// 过冷度
/// </summary>
public ShortValueTag Subcool { get; set; } = null!;
/// <summary>
/// 干度(无量纲 [-]
/// </summary>
public ShortValueTag DrynessTag { get; set; } = null!;
public ShortValueTag? HeatingCapacityTag { get; set; }
public ShortValueTag? COPHeatTag { get; set; }
public ShortValueTag? IsentrpEffTag { get; set; }
public ShortValueTag? CoolCapacityTag { get; set; }
public ShortValueTag? COPCoolTag { get; set; }
public ShortValueTag? VoltricEffTag { get; set; }
private double _DrynessTag2Value;
/// <summary>
/// 干度2无量纲 [-]
/// </summary>
public double DrynessTag2Value
{
get { return _DrynessTag2Value; }
set { _DrynessTag2Value = value; RaisePropertyChanged(); }
}
/// <summary>
/// 气路阀前压力BarA
/// </summary>
public ShortValueTag GasPreValvePressTag { get; set; } = null!;
/// <summary>
/// 气路阀前温度(℃)
/// </summary>
public ShortValueTag GasPreValveTempTag { get; set; } = null!;
/// <summary>
/// 冷媒流量kg/h
/// 气体流量+液体流量=冷媒流量
/// </summary>
public ShortValueTag VRVTag { get; set; } = null!;
/// <summary>
/// 液体流量kg/h
/// 液冷媒流量kg/h=液体流量kg/h
/// </summary>
public ShortValueTag LiqRefFlowTag { get; set; } = null!;
/// <summary>
/// 润滑油流量kg/h
/// </summary>
public ShortValueTag LubeFlowTag { get; set; } = null!;
/// <summary>
/// 启用计算
/// </summary>
private bool RtCalcEnable { get; set; } = true;
/// <summary>
/// PLC扫描线程
/// </summary>
private void RtScanDeviceStart()
{
CalcTask = Task.Run(async () =>
{
while (RtCalcEnable)
{
await Task.Delay(100);
try
{
long iErr, kph = 1;
double te = 0.0, te1 = 0.0, p = 0.0, p1 = 0.0, d = 0.0, Dl = 0.0, Dv = 0.0, q = 0.0, h = 0.0, ee = 0.0, hh = 0.0, ss = 0.0, cp = 0.0, cv = 0.0, w = 0.0;
double[] x = new double[20], xliq = new double[20], xvap = new double[20];
double[] xlkg = new double[20], xvkg = new double[20];
double tk = 0.0, wm = 0.0, prevDeltaH = 0.0;//prevDeltaH 未使用
//textBox5.Text = "";
// 幂等初始化:仅首次或工质/路径变化时执行 SETPATH/SETUP提高每秒循环效率
if (!EnsureRefpropInitialized(out var initErr))
{
// 初始化失败,跳过本周期
Logger?.Error($"REFPROP 初始化失败: {initErr}");
continue;
}
// WMOL 仅在需要时调用;若调用,需设置 x[0]=1.0(纯工质)
x[0] = 1.0;
IRefProp64.WMOLdll(x, ref wm);
//p = Convert.ToDouble(textBox2.Text) * 1000.0;//textBox2 Comp.吸气压力kpa
p = (InhPressTag.PVModel.EngValue) * 100.0;// 保持你原有流程:将 BarA 当作 MPa? 历史代码为 *1000.0,不改变你的算法
kph = 1;
p1 = (TxvFrPressTag.PVModel.EngValue) * 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)
Superheat.PVModel.EngValue = Math.Abs(InhTempTag.PVModel.EngValue - (te - 273.15));
else
Superheat.PVModel.EngValue = 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)
Subcool.PVModel.EngValue = Math.Abs(TxvFrTempTag.PVModel.EngValue - (te1 - 273.15));
else
Subcool.PVModel.EngValue = 0;
//这里写死干度的输入数据
double gasPreValvePressBarA = GasPreValvePressTag.PVModel.EngValue;
double gasPreValveTempC = GasPreValveTempTag.PVModel.EngValue;
double txvFrPressBarA = TxvFrPressTag.PVModel.EngValue;
double txvFrTempC = TxvFrTempTag.PVModel.EngValue;
double inhPressBarA = InhPressTag.PVModel.EngValue;
double vrvFlowKgPerH = VRVTag.PVModel.EngValue;
double liqRefFlowKgPerH = LiqRefFlowTag.PVModel.EngValue;
double lubeFlowKgPerH = 0.0;
//干度技术
var drynessResult = _enthalpyDrynessCalculator.Calculate(
new EnthalpyDrynessCalculator.Input(
gasPreValvePressBarA,
gasPreValveTempC,
txvFrPressBarA,
txvFrTempC,
inhPressBarA,
vrvFlowKgPerH,
liqRefFlowKgPerH,
lubeFlowKgPerH));
//以前会受 LubeFlowTag 影响,现在由于固定为 0会与 Dryness1 更接近/一致(只要两者公式差异仅在油这一项)
if (drynessResult.IsDryness1Success)
{
if (DrynessTag != null)
{
DrynessTag.PVModel.EngValue = drynessResult.Dryness1_01 * 100.0;
}
//DrynessTag2Value = drynessResult.Dryness1_01 * 100.0;
//if (drynessResult.Dryness1_01 <= 0)
//{
// LogDrynessSnapshotIfNeeded(
// "TryComputeDrynessByEnthalpy(SuccessButZero)",
// string.Empty,
// drynessResult.Dryness1_01,
// drynessResult.HMix1_kJkg,
// drynessResult.GasEnthalpy_kJkg,
// drynessResult.LiquidEnthalpy_kJkg,
// drynessResult.SatLiquidEnthalpy_kJkg,
// drynessResult.SatVaporEnthalpy_kJkg,
// drynessResult.GasFlowKgPerH,
// 0,
// LiqRefFlowTag.PVModel.EngValue);
//}
}
else
{
//LogDrynessSnapshotIfNeeded(
// "TryComputeDrynessByEnthalpy(Fail)",
// drynessResult.Error1,
// double.NaN,
// double.NaN,
// drynessResult.GasEnthalpy_kJkg,
// drynessResult.LiquidEnthalpy_kJkg,
// drynessResult.SatLiquidEnthalpy_kJkg,
// drynessResult.SatVaporEnthalpy_kJkg,
// drynessResult.GasFlowKgPerH,
// 0,
// LiqRefFlowTag.PVModel.EngValue);
}
if (drynessResult.IsDryness2Success)
{
//DrynessTag.PVModel.EngValue = drynessResult.Dryness2_01 * 100.0;
DrynessTag2Value = drynessResult.Dryness2_01 * 100.0;
//if (drynessResult.Dryness2_01 <= 0)
//{
// LogDrynessSnapshotIfNeeded(
// "TryComputeDrynessByEnthalpy2(SuccessButZero)",
// string.Empty,
// drynessResult.Dryness2_01,
// drynessResult.HMix2_kJkg,
// drynessResult.GasEnthalpy_kJkg,
// drynessResult.LiquidEnthalpy_kJkg,
// drynessResult.SatLiquidEnthalpy_kJkg,
// drynessResult.SatVaporEnthalpy_kJkg,
// drynessResult.GasFlowKgPerH,
// LubeFlowTag.PVModel.EngValue,
// LiqRefFlowTag.PVModel.EngValue);
//}
}
else
{
//LogDrynessSnapshotIfNeeded(
// "TryComputeDrynessByEnthalpy2(Fail)",
// drynessResult.Error2,
// double.NaN,
// double.NaN,
// drynessResult.GasEnthalpy_kJkg,
// drynessResult.LiquidEnthalpy_kJkg,
// drynessResult.SatLiquidEnthalpy_kJkg,
// drynessResult.SatVaporEnthalpy_kJkg,
// drynessResult.GasFlowKgPerH,
// LubeFlowTag.PVModel.EngValue,
// LiqRefFlowTag.PVModel.EngValue);
}
#if DEBUG
//DebugRunThermoValidationCase_UsingCalculator_FromScreenshot_20260423();
//DebugRunDrynessValidationCase_FromScreenshot_20260425();
//DebugRunThermoValidationCase_UsingCalculator_FromScreenshot_20260428();
#endif
if (TryUpdateThermodynamicSixResults(out var thermoErr))
{
if (!string.IsNullOrWhiteSpace(thermoErr))
{
//Logger?.Warn($"六个物性结果计算警告: {thermoErr}");
}
}
else
{
if (!string.IsNullOrWhiteSpace(thermoErr))
{
//Logger?.Error($"六个物性结果计算失败: {thermoErr}");
}
}
}
catch (Exception ex)
{
Logger.Error(String.Format("ErrSource : {0} ErrMsg : {1}", ex.StackTrace ?? string.Empty, ex.Message));
}
}
});
}
// 若类中尚未定义,请添加全局互斥锁,串行化所有 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;
}
}
///制热量、压缩机性能系数COP制热、等熵效率、制冷量、压缩机性能系数COP(制冷)、容积效率 计算
#region
private double _HeatingCapacityQh_kW;
/// <summary>
/// 制热量 Qh [kW]
/// </summary>
public double HeatingCapacityQh_kW
{
get { return _HeatingCapacityQh_kW; }
set { _HeatingCapacityQh_kW = value; RaisePropertyChanged(); }
}
private double _COPHeating;
/// <summary>
/// 压缩机性能系数 COP制热[-]
/// </summary>
public double COPHeating
{
get { return _COPHeating; }
set { _COPHeating = value; RaisePropertyChanged(); }
}
private double _IsentropicEfficiencyPct;
/// <summary>
/// 等熵效率 ηs [%]
/// </summary>
public double IsentropicEfficiencyPct
{
get { return _IsentropicEfficiencyPct; }
set { _IsentropicEfficiencyPct = value; RaisePropertyChanged(); }
}
private double _CoolingCapacityQc_kW;
/// <summary>
/// 制冷量 Qc [kW]
/// </summary>
public double CoolingCapacityQc_kW
{
get { return _CoolingCapacityQc_kW; }
set { _CoolingCapacityQc_kW = value; RaisePropertyChanged(); }
}
private double _COPCooling;
/// <summary>
/// 压缩机性能系数 COP制冷[-]
/// </summary>
public double COPCooling
{
get { return _COPCooling; }
set { _COPCooling = value; RaisePropertyChanged(); }
}
private double _VolumetricEfficiencyPct;
/// <summary>
/// 容积效率 ηv [%]
/// </summary>
public double VolumetricEfficiencyPct
{
get { return _VolumetricEfficiencyPct; }
set { _VolumetricEfficiencyPct = value; RaisePropertyChanged(); }
}
/// <summary>
/// 按流程图更新制热量、COP(制热)、等熵效率、制冷量、COP(制冷)、容积效率。
/// </summary>
/// <param name="error">
/// 错误/警告信息输出。
/// - 当方法返回 <see langword="false"/> 时,<paramref name="error"/> 为失败原因,调用方应视为本周期计算无效。
/// - 当方法返回 <see langword="true"/> 但 <paramref name="error"/> 非空时,表示仅部分结果无法计算(例如缺少排量导致容积效率为 NaN
/// </param>
/// <returns>
/// 是否成功完成本周期的结果更新。
/// - <see langword="true"/>:至少已成功更新 Qh/Qc/COP/ηs 等主要结果;容积效率可能因缺失排量而为 NaN。
/// - <see langword="false"/>:关键输入或 REFPROP 计算失败,本周期结果不更新。
/// </returns>
private bool TryUpdateThermodynamicSixResults(out string error)
{
error = string.Empty;
if (InhPressTag == null || InhTempTag == null)
{
error = "缺少吸气压力/吸气温度标签";
return false;
}
if (TxvFrPressTag == null || TxvFrTempTag == null)
{
error = "缺少膨胀阀前压力/膨胀阀前温度标签";
return false;
}
if (ExPressTag == null || ExTempTag == null)
{
error = "缺少排气压力/排气温度标签";
return false;
}
if (HVPwTag == null)
{
error = "缺少 HV[W] 功率标签";
return false;
}
if (VRVTag == null)
{
error = "缺少总流量(冷媒流量)标签";
return false;
}
double suctionPress_BarA = InhPressTag.PVModel.EngValue;
double suctionTemp_C = InhTempTag.PVModel.EngValue;
double dischargePress_BarA = ExPressTag.PVModel.EngValue;
double dischargeTemp_C = ExTempTag.PVModel.EngValue;
double txvFrPress_BarA = TxvFrPressTag.PVModel.EngValue;
double txvFrTemp_C = TxvFrTempTag.PVModel.EngValue;
double totalFlow_kg_h = VRVTag.PVModel.EngValue;
double w_W = HVPwTag.PVModel.EngValue;
double speed_rpm = SpeedTag?.PVModel.EngValue ?? double.NaN;
if (!TryGetCompressorDisplacement_cc(out var disp_cc, out var dispErr))
{
error = dispErr;
return false;
}
//这里把输入数据写死计算出结果。
//#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)
{
HeatingCapacityQh_kW = 0;
CoolingCapacityQc_kW = 0;
COPHeating = 0;
COPCooling = 0;
IsentropicEfficiencyPct = 0;
VolumetricEfficiencyPct = 0;
if (HeatingCapacityTag != null)
{
HeatingCapacityTag.PVModel.EngValue = 0;
}
if (COPHeatTag != null)
{
COPHeatTag.PVModel.EngValue = 0;
}
if (IsentrpEffTag != null)
{
IsentrpEffTag.PVModel.EngValue = 0;
}
if (CoolCapacityTag != null)
{
CoolCapacityTag.PVModel.EngValue = 0;
}
if (COPCoolTag != null)
{
COPCoolTag.PVModel.EngValue = 0;
}
if (VoltricEffTag != null)
{
VoltricEffTag.PVModel.EngValue = 0;
}
return true;
}
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.PVModel.EngValue = HeatingCapacityQh_kW * 1000.0;
}
if (COPHeatTag != null)
{
COPHeatTag.PVModel.EngValue = COPHeating;
}
if (IsentrpEffTag != null)
{
IsentrpEffTag.PVModel.EngValue = IsentropicEfficiencyPct;
}
if (CoolCapacityTag != null)
{
CoolCapacityTag.PVModel.EngValue = CoolingCapacityQc_kW * 1000.0;
}
if (COPCoolTag != null)
{
COPCoolTag.PVModel.EngValue = COPCooling;
}
if (double.IsNaN(r.VolumetricEfficiencyPct) || double.IsInfinity(r.VolumetricEfficiencyPct))
{
VolumetricEfficiencyPct = double.NaN;
error = calcErr;
return true;
}
VolumetricEfficiencyPct = r.VolumetricEfficiencyPct;
if (VoltricEffTag != null)
{
VoltricEffTag.PVModel.EngValue = VolumetricEfficiencyPct;
}
error = calcErr;
return true;
}
/// <summary>
/// 获取压缩机排量。
/// </summary>
/// <param name="displacement_cc">排量输出,单位 cccm³/rev。</param>
/// <param name="error">失败原因(未配置、解析失败、数值不合法)。</param>
/// <returns>是否获取成功。</returns>
private bool TryGetCompressorDisplacement_cc(out double displacement_cc, out string error)
{
displacement_cc = double.NaN;
error = string.Empty;
const double defaultDisplacementCc = 35d;
if (ConfigService?.CurExpInfo != null &&
TryParseCompressorDisplacementTextToCc(ConfigService.CurExpInfo.CapDisplacement, out var expCc) &&
expCc > 0)
{
displacement_cc = expCc;
return true;
}
const string key = "CompressorDisplacementCc";
if (ConfigHelper.IsExist(key) && TryParseCompressorDisplacementTextToCc(ConfigHelper.GetValue(key), out var cfgCc) && cfgCc > 0)
{
displacement_cc = cfgCc;
return true;
}
displacement_cc = defaultDisplacementCc;
return true;
}
private static bool TryParseCompressorDisplacementTextToCc(string? text, out double displacementCc)
{
displacementCc = double.NaN;
if (string.IsNullOrWhiteSpace(text))
{
return false;
}
var normalized = text.Trim().ToLowerInvariant();
normalized = normalized.Replace(',', '.');
var match = Regex.Match(normalized, @"[-+]?\d+(\.\d+)?");
if (!match.Success)
{
return false;
}
if (!double.TryParse(match.Value, NumberStyles.Float, CultureInfo.InvariantCulture, out var v))
{
return false;
}
displacementCc = v;
return true;
}
#endregion
}
}