干度251018
This commit is contained in:
@@ -1,29 +1,14 @@
|
||||
using CapMachine.Core;
|
||||
using CapMachine.Model.CANLIN;
|
||||
using CapMachine.Wpf.Dtos;
|
||||
using CapMachine.Wpf.Models.Tag;
|
||||
using CapMachine.Wpf.Models;
|
||||
using CapMachine.Wpf.Services;
|
||||
using HslCommunication;
|
||||
using ImTools;
|
||||
using NLog;
|
||||
using NPOI.OpenXmlFormats.Wordprocessing;
|
||||
using Prism.Ioc;
|
||||
using Prism.Mvvm;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
using System.Windows.Interop;
|
||||
using static CapMachine.Wpf.CanDrive.USB2CAN;
|
||||
using CapMachine.Wpf.Models;
|
||||
|
||||
namespace CapMachine.Wpf.CanDrive
|
||||
{
|
||||
|
||||
BIN
CapMachine.Wpf/PPCalculation/2025-10-18.xlsx
Normal file
BIN
CapMachine.Wpf/PPCalculation/2025-10-18.xlsx
Normal file
Binary file not shown.
@@ -84,6 +84,7 @@ namespace CapMachine.Wpf.Services
|
||||
{
|
||||
LiqRefFlowTag = LiqRefFlowShortTag!;
|
||||
}
|
||||
//kg/h L/min
|
||||
if (TagManager.TryGetShortTagByName("冷媒流量[L/min]", out ShortValueTag? VRVShortTag))
|
||||
{
|
||||
VRVTag = VRVShortTag!;
|
||||
@@ -133,11 +134,16 @@ namespace CapMachine.Wpf.Services
|
||||
DrynessTag = drynessPct!;
|
||||
DrynessTagIsPercent = true;
|
||||
}
|
||||
else if (TagManager.TryGetShortTagByName("干度[-]", out ShortValueTag? drynessAbs))
|
||||
{
|
||||
DrynessTag = drynessAbs!;
|
||||
DrynessTagIsPercent = false;
|
||||
}
|
||||
|
||||
SuperHeatCoolConfig.FluidsPath = ConfigHelper.GetValue("FluidsPath");
|
||||
SuperHeatCoolConfig.Cryogen = ConfigHelper.GetValue("Cryogen");
|
||||
|
||||
//RtScanDeviceStart();
|
||||
RtScanDeviceStart();
|
||||
}
|
||||
|
||||
|
||||
@@ -265,6 +271,10 @@ namespace CapMachine.Wpf.Services
|
||||
/// </summary>
|
||||
private bool RtCalcEnable { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// 触发日志
|
||||
/// </summary>
|
||||
private bool DebugLog { get; set; }=false;
|
||||
|
||||
/// <summary>
|
||||
/// PLC扫描线程
|
||||
@@ -273,86 +283,68 @@ namespace CapMachine.Wpf.Services
|
||||
{
|
||||
CalcTask = Task.Run(async () =>
|
||||
{
|
||||
//Stopwatch stopwatch = new Stopwatch();
|
||||
//物性的过热度和过冷度的相关物性计算
|
||||
while (RtCalcEnable)
|
||||
{
|
||||
await Task.Delay(1000);
|
||||
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;
|
||||
|
||||
double tk = 0.0, wm = 0.0, prevDeltaH = 0.0;//prevDeltaH 未使用
|
||||
|
||||
// 统一初始化(仅必要时),避免循环内重复 SETUP/SETPATH
|
||||
if (!EnsureRefpropInitialized(out string initErrLoop))
|
||||
{
|
||||
// 初始化失败:保护性置零并进入下一轮
|
||||
Superheat.PVModel.EngValue = 0;
|
||||
Subcool.PVModel.EngValue = 0;
|
||||
// 可选:记录 initErrLoop
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
// 在统一的锁内进行 REFPROP 计算,保证并发安全与状态一致性
|
||||
|
||||
lock (_refpropLock)
|
||||
{
|
||||
// 建立纯工质组分(摩尔分数)
|
||||
double[] xLoc = new double[20]; xLoc[0] = 1.0;
|
||||
double[] xliqLoc = new double[20];
|
||||
double[] xvapLoc = new double[20];
|
||||
double DlLoc = 0, DvLoc = 0;
|
||||
string herr2 = new string(' ', 255);
|
||||
long herrLen2 = 255;
|
||||
|
||||
// 计算过热度/过冷度(封装方法,BarA→kPa)
|
||||
// 过热度
|
||||
if (TryComputeSuperheatK_ByBarA(InhPressTag.PVModel.EngValue, InhTempTag.PVModel.EngValue, out double superheatK, out string shErr))
|
||||
Superheat.PVModel.EngValue = superheatK;
|
||||
else
|
||||
{
|
||||
Superheat.PVModel.EngValue = 0;
|
||||
Logger.Error($"过热度计算失败:{shErr}");
|
||||
if (DebugLog) Logger.Error($"过热度计算失败:{shErr}");
|
||||
}
|
||||
|
||||
// 过冷度
|
||||
if (TryComputeSubcoolK_ByBarA(TxvFrPressTag.PVModel.EngValue, TxvFrTempTag.PVModel.EngValue, out double subcoolK, out string scErr))
|
||||
Subcool.PVModel.EngValue = subcoolK;
|
||||
else
|
||||
{
|
||||
Subcool.PVModel.EngValue = 0;
|
||||
Logger.Error($"过冷度计算失败:{scErr}");
|
||||
if (DebugLog) Logger.Error($"过冷度计算失败:{scErr}");
|
||||
}
|
||||
|
||||
// 干度计算(LabVIEW 严格流程,质量流量加权):
|
||||
// A) 阀前两路相焓(TPRHO→THERM)
|
||||
// B) 质量流量加权混合焓
|
||||
// C) 吸气压力同压饱和焓(SATP→THERM)
|
||||
// D) x = (h_mix - h_l)/(h_v - h_l)
|
||||
try
|
||||
{
|
||||
// 输入校验:必要测点是否齐全
|
||||
// 干度计算
|
||||
var missing = new List<string>();
|
||||
if (InhPressTag == null) missing.Add("吸气压力[BarA]");
|
||||
if (GasPreValvePressTag == null) missing.Add("气路阀前压力[BarA]");
|
||||
if (GasPreValveTempTag == null) missing.Add("气路阀前温度[℃]");
|
||||
if (TxvFrPressTag == null) missing.Add("膨胀阀前压力[BarA]");
|
||||
if (TxvFrTempTag == null) missing.Add("SUBCOOL出口温度[℃]");
|
||||
if (VRVTag == null) missing.Add("气体质量流量[kg/h]");
|
||||
if (LiqRefFlowTag == null) missing.Add("液冷媒流量[kg/h]");
|
||||
|
||||
if (missing.Count > 0)
|
||||
{
|
||||
if (DrynessTag != null)
|
||||
{
|
||||
DrynessTag.PVModel.EngValue = 0;
|
||||
}
|
||||
Logger.Error($"质量流量加权干度:必要测点缺失,已将干度置0。缺失: {string.Join(", ", missing)}");
|
||||
if (DrynessTag != null) DrynessTag.PVModel.EngValue = 0;
|
||||
if (DebugLog) Logger.Error($"质量流量加权干度:必要测点缺失,已将干度置0。缺失: {string.Join(", ", missing)}");
|
||||
}
|
||||
else
|
||||
{
|
||||
string dryErr;
|
||||
//double ps = InhPressTag.PVModel.EngValue;
|
||||
//double pg = GasPreValvePressTag.PVModel.EngValue;
|
||||
//double tg = GasPreValveTempTag.PVModel.EngValue;
|
||||
//double plv = TxvFrPressTag.PVModel.EngValue;
|
||||
//double tlv = TxvFrTempTag.PVModel.EngValue;
|
||||
|
||||
double ps = InhPressTag.PVModel.EngValue;//吸气压力
|
||||
//ps = 2.374421;//Mpa ->BarA
|
||||
double pg = GasPreValvePressTag.PVModel.EngValue;//气路阀前压力
|
||||
@@ -364,16 +356,19 @@ namespace CapMachine.Wpf.Services
|
||||
double tlv = TxvFrTempTag.PVModel.EngValue;//膨胀阀前温度 = SUBCOOL出口温度 =液路阀前温度
|
||||
//tlv = 64.96428;
|
||||
|
||||
// 单位说明:
|
||||
// - 液体质量流量 ml[kg/h] = LiqRefFlowTag.PVModel.EngValue
|
||||
// - 气体质量流量 mg[kg/h] = VRVTag.PVModel.EngValue(VRV 位于气管,单位已为 kg/h)
|
||||
double LiquidMassFlowKgPerH = Math.Max(0.0, LiqRefFlowTag?.PVModel?.EngValue ?? 0.0);
|
||||
//double LiquidMassFlowKgPerH = 214.3051;
|
||||
//double GasMassFlowKgPerH = Math.Max(0.0, VRVTag?.PVModel?.EngValue ?? 0.0);
|
||||
double GasMassFlowKgPerH = (double)(VRVTag?.PVModel?.EngValue - LiquidMassFlowKgPerH);
|
||||
|
||||
double GasMassFlowKgPerH, LiquidMassFlowKgPerH;
|
||||
|
||||
LiquidMassFlowKgPerH = LiqRefFlowTag.PVModel.EngValue; // [kg/h]
|
||||
//GasMassFlowKgPerH = Math.Max(0.0, VRVTag?.PVModel?.EngValue ?? 0.0); // [kg/h]
|
||||
GasMassFlowKgPerH = (double)(VRVTag?.PVModel?.EngValue - LiquidMassFlowKgPerH);
|
||||
//压力参数要求为BarA
|
||||
// 校验总质量流量
|
||||
if ((GasMassFlowKgPerH + LiquidMassFlowKgPerH) <= 0)
|
||||
{
|
||||
if (DrynessTag != null) DrynessTag.PVModel.EngValue = 0;
|
||||
if (DebugLog) Logger.Error("质量流量加权干度:气/液质量流量和<=0,已将干度置0。");
|
||||
}
|
||||
else
|
||||
{
|
||||
double dryness = Step_ComputeDryness_LV_FlowWeighted(
|
||||
GasMassFlowKgPerH,
|
||||
LiquidMassFlowKgPerH,
|
||||
@@ -381,37 +376,24 @@ namespace CapMachine.Wpf.Services
|
||||
out dryErr
|
||||
);
|
||||
|
||||
double val = (!double.IsNaN(dryness)) ? dryness : 0.0;
|
||||
if (!double.IsNaN(dryness))
|
||||
{
|
||||
// 物理意义上干度应在 [0,1],写入 Tag 时进行夹紧保护
|
||||
double drynessClamped = Math.Min(1.0, Math.Max(0.0, dryness));
|
||||
if (DrynessTag != null)
|
||||
{
|
||||
DrynessTag.PVModel.EngValue = DrynessTagIsPercent ? val * 100.0 : val;
|
||||
DrynessTag.PVModel.EngValue = DrynessTagIsPercent ? drynessClamped * 100.0 : drynessClamped;
|
||||
}
|
||||
|
||||
if (double.IsNaN(dryness))
|
||||
else
|
||||
{
|
||||
Logger.Error($"质量流量加权干度计算失败:{dryErr};已置0。输入: mg={GasMassFlowKgPerH:F3} kg/h, ml={LiquidMassFlowKgPerH:F3} kg/h, Ps={ps:F3} BarA, Pg={pg:F3} BarA, Tg={tg:F3} ℃, Pl={plv:F3} BarA, Tl={tlv:F3} ℃");
|
||||
if (DebugLog) Logger.Warn($"质量流量加权干度计算失败:{dryErr};已跳过本次干度写入。输入: mg={GasMassFlowKgPerH:F3} kg/h, ml={LiquidMassFlowKgPerH:F3} kg/h, Ps={ps:F3} BarA, Pg={pg:F3} BarA, Tg={tg:F3} ℃, Pl={plv:F3} BarA, Tl={tlv:F3} ℃");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (DrynessTag != null) DrynessTag.PVModel.EngValue = 0;
|
||||
Logger.Error("质量流量加权干度计算异常,已置0");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//p = Convert.ToDouble(textBox2.Text) * 100.0;//textBox2 Comp.吸气压力(BarA→kPa)
|
||||
p = (InhPressTag.PVModel.EngValue) * 100.0;//textBox2 Comp.吸气压力(BarA→kPa)
|
||||
kph = 1;
|
||||
|
||||
p1 = (TxvFrPressTag.PVModel.EngValue) * 100.0;//textBox3 Evap.膨胀阀前压力(BarA→kPa)
|
||||
//p1 = Convert.ToDouble(textBox3.Text) * 100.0;//textBox3 Evap.膨胀阀前压力(BarA→kPa)
|
||||
// 重复的 SATP 与干度计算已在上方 lock(_refpropLock) 中统一完成,此处移除重复调用
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
//logger.Error(String.Format("ErrSource : {0} ErrMsg : {1}", ex.StackTrace.ToString(), ex.Message.ToString()));
|
||||
Logger.Error(String.Format("ErrSource : {0} ErrMsg : {1}", ex.StackTrace.ToString(), ex.Message.ToString()));
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -460,7 +442,7 @@ namespace CapMachine.Wpf.Services
|
||||
}
|
||||
if (ierr != 0) { error = $"SATP 失败: {herr.Trim()} (ierr={ierr})"; return false; }
|
||||
double tSatC = tSatK - 273.15;
|
||||
subcoolK = preValveTempC - tSatC;
|
||||
subcoolK = tSatC - preValveTempC;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -514,7 +496,7 @@ namespace CapMachine.Wpf.Services
|
||||
herr = new string(' ', 255); herrLen = 255; iErr = 0;
|
||||
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 = TxvFrTempTag.PVModel.EngValue - (te1 - 273.15);
|
||||
Subcool.PVModel.EngValue = (te1 - 273.15) - TxvFrTempTag.PVModel.EngValue;
|
||||
|
||||
else
|
||||
Subcool.PVModel.EngValue = 0;
|
||||
@@ -567,16 +549,60 @@ namespace CapMachine.Wpf.Services
|
||||
{
|
||||
h_kJkg = double.NaN; error = string.Empty;
|
||||
if (!EnsureRefpropInitialized(out error)) return false;
|
||||
|
||||
// 统一输入与数组
|
||||
double[] x = new double[20]; x[0] = 1.0;
|
||||
double wmm = 0; // g/mol
|
||||
double tK = temperatureC + 273.15;
|
||||
double pKPa = pressureBarA * 100.0;
|
||||
double D = 0; long kguess = 0; long ierr = 0; string herr = new string(' ', 255); long ln = 255;
|
||||
double pOut = 0, el = 0, hl = 0, sl = 0, cvl = 0, cpl = 0, wl = 0, hjt = 0;
|
||||
|
||||
// 相态自适应:当期望液相(kph=1)但温度高于同压饱和或接近相边界时,改用 TPFLSH 或饱和液焓,避免跳变
|
||||
const double EpsBandK = 0.4; // 饱和带宽(K)
|
||||
lock (_refpropLock)
|
||||
{
|
||||
IRefProp64.WMOLdll(x, ref wmm);
|
||||
if (!(wmm > 0)) { error = "WMOL 返回无效摩尔质量"; return false; }
|
||||
|
||||
// 计算当前压力下的饱和温度
|
||||
double tSat = 0, DlSat = 0, DvSat = 0; long kphSat = 1; string herrSat = new string(' ', 255); long lnSat = 255; long ierrSat = 0;
|
||||
double pForSat = pKPa;
|
||||
IRefProp64.SATPdll(ref pForSat, x, ref kphSat, ref tSat, ref DlSat, ref DvSat, new double[20], new double[20], ref ierrSat, ref herrSat, ref lnSat);
|
||||
double tSatC = (ierrSat == 0) ? (tSat - 273.15) : double.NaN;
|
||||
|
||||
// 当调用者要求液相,但温度在饱和带内或高于饱和温度时,优先使用 TPFLSH 获取真实相态焓
|
||||
if (kphPhase == 1 && !double.IsNaN(tSatC))
|
||||
{
|
||||
double dT = temperatureC - tSatC;
|
||||
if (dT >= EpsBandK)
|
||||
{
|
||||
// 已明显高于饱和:按真实相态计算焓(TPFLSH)
|
||||
string e2;
|
||||
if (TryComputeHmassKJkgByTP_BarAC(pressureBarA, temperatureC, out double hMassTPF, out e2))
|
||||
{ h_kJkg = hMassTPF; return true; }
|
||||
// 若 TPFLSH 也失败,则退化为气相路径 TPRHO
|
||||
long kphGas = 2; double tK2 = tK; double pKPa2 = pKPa; double DG = 0; long ierr2 = 0; string herr2 = new string(' ', 255); long ln2 = 255;
|
||||
IRefProp64.TPRHOdll(ref tK2, ref pKPa2, x, ref kphGas, ref kguess, ref DG, ref ierr2, ref herr2, ref ln2);
|
||||
if (ierr2 == 0)
|
||||
{
|
||||
double tLocal2 = tK2; double DLocal2 = DG;
|
||||
IRefProp64.THERMdll(ref tLocal2, ref DLocal2, x, ref pOut, ref el, ref hl, ref sl, ref cvl, ref cpl, ref wl, ref hjt);
|
||||
h_kJkg = hl / wmm; return true;
|
||||
}
|
||||
// 否则继续走默认液相路径(尽力返回)
|
||||
}
|
||||
else if (Math.Abs(dT) <= EpsBandK)
|
||||
{
|
||||
// 接近饱和:改用 TPFLSH(T,P) 真实相态焓,避免“直接切换为饱和液焓”导致阶跃
|
||||
string e2b;
|
||||
if (TryComputeHmassKJkgByTP_BarAC(pressureBarA, temperatureC, out double hMassTPF2, out e2b))
|
||||
{ h_kJkg = hMassTPF2; return true; }
|
||||
// 若失败,继续默认液相路径
|
||||
}
|
||||
}
|
||||
|
||||
// 默认:按给定 kphPhase 走 TPRHO→THERM(与 LV 路径一致)
|
||||
IRefProp64.TPRHOdll(ref tK, ref pKPa, x, ref kphPhase, ref kguess, ref D, ref ierr, ref herr, ref ln);
|
||||
if (ierr != 0) { error = $"TPRHO 失败: {herr.Trim()} (ierr={ierr})"; return false; }
|
||||
double tLocal = tK; double DLocal = D;
|
||||
@@ -626,7 +652,8 @@ namespace CapMachine.Wpf.Services
|
||||
if (Math.Abs(denom) < 1e-9) { error = "饱和焓差过小,可能临界附近"; return false; }
|
||||
double val = (hMix_kJkg - hl_kJkg) / denom;
|
||||
if (double.IsNaN(val) || double.IsInfinity(val)) { error = "干度数值异常"; return false; }
|
||||
x = Math.Max(0.0, Math.Min(1.0, val));
|
||||
// 不再夹紧到 [0,1],返回原始 x(可能 <0 或 >1),以避免跨界限时的阶跃
|
||||
x = val;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user