flowMeter/NGToolsPC/NG_Cal.cs

530 lines
21 KiB
C#

using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Text;
namespace NG_Tools
{
public class NG_Cal
{
public const int NORMAL = 9000;
public const int NG_Cal_INITIALIZED = 9001;
public const int MEMORY_ALLOCATION_ERROR = 9002;
public const int GENERAL_CALCULATION_FAILURE = 9003;
public const int MAX_NUM_OF_ITERATIONS_EXCEEDED = 9004;
public const int NEGATIVE_DENSITY_DERIVATIVE = 9005;
public const int MAX_DENSITY_IN_BRAKET_EXCEEDED = 9006;
/* number of components */
public const int NUMBEROFCOMPONENTS = 21;
/* maximum number of tries within search routines */
public const int MAX_NUM_OF_ITERATIONS = 100;
/* default tolerance limits */
public const double P_CHG_TOL = 0.001; /* 0.001 Pa */
public const double T_CHG_TOL = 0.001; /* 0.001 of a Kelvin */
/* maximum allowable P & T */
public const double P_MAX = 1.379e8; // maximum pressure (Pa) ~= 20,000 psi
public const double P_MIN = 0.0; // maximum pressure = 0
public const double T_MAX = 473.15; // maximum temperature (K) ~= 392 F
public const double T_MIN = 143.0; // maximum temperature (K) ~= -200 F
/* universal gas constant, in two configurations */
public const double RGASKJ = 8.314510e-3; /* in kJ mol^-1 K^-1 */
public const double RGAS = 8.314510; /* in J mol^-1 K^-1 */
/* the main data structure used by this library */
public struct GasPropsSTRUCT
{ /* corresponds to the control group in meter classes */
public int lStatus; /* calculation status 计算状态 */
public bool bForceUpdate; /*执行全部计算的标志 signal to perform full calculation */
public double[] adMixture; /*气体摩尔组成 Composition in mole fraction */
public double[] adMixtureV; /*气体体积组成 Composition in mole fraction */
public double[] adMixtureD; /*气体质量组成 Composition in mole fraction */
public int dCbtj; //参比条件 101325 0,15,20
public int dCbtj_E; //燃烧参比条件 101325 0,15,20
public double dPb; /*参比压力 Contract base Pressure (Pa) */
public double dTb; /* 参比温度Contract base temperature (K) */
public double dPf; /*绝对压力 Absolute Pressure (Pa) */
public double dTf; /*工况温度 Flowing temperature (K) */
// basic output from AGA 8 Detail method
public double dMrx; /*分子量 mixture molar mass */
public double dZb; /* 标况压缩因子compressibility at contract base condition */
public double dZf; /* 工况压缩因子compressibility at flowing condition */
public double dFpv; /*超压缩系数 supercompressibility */
public double dDb; /* 标况摩尔密度molar density at contract base conditions (moles/dm3) */
public double dDf; /*工况摩尔密度 molar density at flowing conditions (moles/dm3) */
public double dRhob; /* 标况质量密度mass density at contract base conditions (kg/m3) */
public double dRhof; /*工况质量密度 mass density at flowing conditions (kg/m3) */
public double dRD_Ideal; /* 理想气体的相对密度ideal gas relative density */
public double dRD_Real; /* 真实气体的相对密度real gas relative density */
// additional output
public double dHo; /*理想气体的比焓 ideal gas specific enthalpy */
public double dH; /*真实气体的焓 real gas specific enthalpy (J/kg) */
public double dS; /* 真实气体的熵real gas specific entropy (J/kg-mol.K)*/
public double dCpi; /*理想气体定压热容 ideal gas constant pressure heat capacity (J/kg-mol.K)*/
public double dCp; /* 定压热容real gas constant pressure heat capacity (J/kg-mol.K)*/
public double dCv; /*定容积热容 real gas constant volume heat capacity (J/kg-mol.K)*/
public double dk; /* 比热比ratio of specific heats */
public double dKappa; /*等熵指数 isentropic exponent, denoted with Greek letter kappa */
public double dSOS; /* 声速speed of sound (m/s) */
public double dCstar; /*临界流函数 critical flow factor C* */
// 11062 输出
public double dHhvMol; //摩尔高位发热量
public double dLhvMol; //摩尔低位发热量
public double dHhvv; //体积高位发热量
public double dLhvv; //体积低位发热量
public double dHhvm; //质量高位发热量
public double dLhvm; //质量地位发热量
public double dZb11062; //标况压缩因子
public double dRhob11062; /* 标况质量密度mass density at contract base conditions (kg/m3) */
public double dRhof11062; /*工况质量密度 mass density at flowing conditions (kg/m3) */
public double dRD_Ideal11062; /* 理想气体的相对密度ideal gas relative density */
public double dRD_Real11062; /* 真实气体的相对密度real gas relative density */
public double dWobbeIndex; /* 真实气体的沃泊指数 */
public double Pc; // '临界压力
public double TC; /// '临界温度
public double Bzsx; // '爆炸上限
public double Bzxx; // '爆炸下限
public double TotalC; // '总炭含量 (kg/m3)
public double C2; // 'C2组分含量 (kg/m3)
public double C2j; // 'C2以上组分含量 (kg/m3)
public double C3j; // 'C3以上组分含量 (kg/m3)
public double C4j; // 'C4以上组分含量 (kg/m3)
public double C5j; // 'C5以上组分含量 (kg/m3)
public double C6j; // 'C6以上组分含量 (kg/m3)
public double C3C4; // 'C3C4组分含量 (kg/m3)
}
public struct FlowParStruct //流量相关参数
{
//流量计算输入参数信息
public int dFlowCalbz; //流量计算标准
public int dZcalbz; //压缩因子计算标准
public int dCbtj; //计量参比条件压力
public double dPb_M; //计量参比条件压力
public double dTb_M; //计量参比条件温度
public double dPb_E; //燃烧参比条件压力
public double dTb_E; //燃烧参比条件温度
public double dPatm;//当地大气压
public int dPatmUnit;//当地大气压单位
public double[] dNG_Compents;//天然气组分
public int dMeterType;// 流量计类别
public int dCoreType;//节流装置类型
public int dPtmode; //取压方式
public int dPipeType; // 管道类型
public double dPipeD; //管道内径
public int dLenUnit; //长度单位
public double dPipeDtemp; //管道内径参考温度
public int dPileDtempUint; //温度单位
public int dPipeMaterial; //管道材料
public double dOrificeD; //孔板孔径
public int dOrificeUnit; //长度单位
public double dOrificeDtemp; //孔板内径参考温度
public int dOrificeDtempUnit; //温度单位
public int dOrificeMaterial; //孔板材料
public int dOrificeSharpness; //锐利度系数计算方法
public double dOrificeRk; //孔板入口圆弧半径
public int dOrificeRkLenUint;//长度单位
public double dPf;//输入压力
public int dPfUnit;//压力单位
public int dPfType; //压力类型
public double dTf; //输入温度
public int dTfUnit;//温度单位
public double dDp; //输入差压
public int dDpUnit; //压力单位
public int dVFlowUnit; //体积流量单位
public int dMFlowUnit; //'NG_Par(33) = ComboBox15.SelectedIndex '质量流量单位
public int dEFlowUnit; //'NG_Par(34) = ComboBox16.SelectedIndex '能量流量单位
public double dCd;//流出系数
public double dCdCalMethod;//流出系数计算方法 0 检定证书 0回归公式
public double dMeterFactor;//仪表系数
public double dPulseNum;//脉冲数
public double dVFlowMax; //'NG_par(39)=’最大体积流量
public double dVFlowMin; //'NG_par(40)=’最小体积流量
public double dVFlowCon;//'NG_par(41)=’常用流量
public double dPfRangeMin; //'NG_par(42)=’压力量程
public double dPfRangeMax; //'NG_par(42)=’压力量程
public double dDpRangeMin; //'NG_par(43)=’差压量程
public double dDpRangeMax; //'NG_par(43)=’差压量程
public double dTfRangeMin; //'NG_par(44)=’温度计量程
public double dTfRangeMax; //'NG_par(44)=’温度计量程
//流量计算输出参数
public double dE; //'求渐近速度系数 E
public double dFG; //'求相对密度系数 FG
public double dFT; //'求流动温度系数 'FT
public double dDViscosity; //'求动力粘度 dlnd
public double dDExpCoefficient; //'求可膨胀系数
public double dRnPipe; //'管道雷诺数
public double dBk; //'孔板锐利度系数Bk
public double dRoughNessPipe; //'管道粗糙度系数 Gme
public double dCdCorrect; //'修正后的流出系数
public double dCdNozell; //'喷嘴的流出系数
public double dVFlowb;//'标况体积流量 m³、s
public double dVFlowf; //'工况体积流量
public double dMFlowb;//'标况质量流量
public double dEFlowb;//'标况能量流量
public double dVelocityFlow;//'管道内天然气流速
public double dPressLost;//'压力损失
public double dBeta;//'直径比
public double dKappa;//'等熵指数
}
//public struct SqgyParStruct //输气工艺相关参数
//{
// public int dCalName; //计算项目
// public int dPipleD; //管道内径mm
// public int dPipleDw; //管道内径外径mm
// public int dPipleBh; //管道壁厚 mm
// public double dPipleTotalLength; //管道总长度 km
// public double dPiplePointLength; //管道任意点长度 km
// public double dPstart; //起点压力终点压力MPa
// public double dPend; //终点压力MPa
// public double dFlow; //输气能力
// public double dRd;//相对密度
// public double dZf;//压缩因子
// public double[] dNG_Compents;//天然气组分
// public double dPavg;//管道平均压力
// public double dPavgPoint;//管道任意点的平均压力
//}
/* enumerations for tracking gas components */
enum gascomp
{
XiC1 = 0, XiN2, XiCO2, XiC2, XiC3,
XiH2O, XiH2S, XiH2, XiCO, XiO2, XiIC4, XiNC4,
XiIC5, XiNC5, XiNC6, XiNC7, XiNC8, XiNC9, XiNC10, XiHe, XiAr
};
/* FUNCTION PROTOTYPES */
/* prototypes for initialization */
// int NG_Cal_Init(void) ; /* initialize library */
// int NG_Cal_UnInit(void) ; /* un-initialize library */
///* function prototype for basic VOS calculation */
// double SOS(ref AGA10.GasPropsSTRUCT ) ;
///* function prototype for a C* calculation */
// double Crit(ref AGA10.GasPropsSTRUCT , double) ;
public Therm ptTherm;
public Detail ptDetail;
/**************************************************************************
* Function : NG_Cal_Init()
* Arguments : void
* Returns : int
* Purpose : Initializes library; creates required objects
* Revisions :
**************************************************************************/
public int NG_Cal_Init()
{
//create object for calculating density
if (null == (ptDetail = new Detail()))
{
return MEMORY_ALLOCATION_ERROR;
}
//create object for calculating thermodynamic properties
if (null == (ptTherm = new Therm()))
{
return MEMORY_ALLOCATION_ERROR;
}
return NG_Cal_INITIALIZED;
}// NG_Cal_Init
/**************************************************************************
* Function : NG_Cal_UnInit()
* Arguments : void
* Returns : int
* Purpose : Un-initializes library; deletes objects
* Revisions :
**************************************************************************/
public int NG_Cal_UnInit()
{
// delete the objects (if they exist)
ptDetail = null;
ptTherm = null;
return 0;
}// NG_Cal_UnInit
/**************************************************************************
* Function : SOS()
* Arguments : Pointers to external AGA10 data struct
* Returns : double
* Purpose : calculates speed of sound and other parameters
* Revisions :
**************************************************************************/
public double SOS(ref GasPropsSTRUCT ptAGA10)
{
// check if library is ready; initialize if necessary
if (null == ptDetail || null == ptTherm)
{
NG_Cal_UnInit();
NG_Cal_Init();
}
switch (ptAGA10.dCbtj)
{
case 2:
ptAGA10.dPb = 101325;
ptAGA10.dTb = 273.15;
break;
case 1:
ptAGA10.dPb = 101325;
ptAGA10.dTb = 288.15;
break;
case 0:
ptAGA10.dPb = 101325;
ptAGA10.dTb = 293.15;
break;
}
//Call function to calculate densities and thermodynamic properties
ptTherm.Run(ref ptAGA10, ref ptDetail);
//the basic sound speed calculation doesn't calculate C*; initialize to zero
ptAGA10.dCstar = 0.0;
//return the speed of sound to caller
return ptAGA10.dSOS;
}// VOS()
/**************************************************************************
* Function : Crit()
* Arguments : Pointers to external AGA10 data struct, Detail and Therm
* objects and a double precision float (gas velocity in plenum)
* Returns : double
* Purpose : calculates C*
* Revisions :
**************************************************************************/
public double Crit(ref NG_Cal.GasPropsSTRUCT ptAGA10, double dPlenumVelocity)
{
//variables local to function
double DH, DDH, S, H;
double tolerance = 1.0;
double R, P, T, Z;
int i;
//check objects for readiness; try to initialize if not
if (null == ptDetail || null == ptTherm)
{
NG_Cal_UnInit();
if (NG_Cal_INITIALIZED != NG_Cal_Init())
{
ptAGA10.lStatus = MEMORY_ALLOCATION_ERROR; return 0.0;
}
}
switch (ptAGA10.dCbtj)
{
case 2:
ptAGA10.dPb = 101325;
ptAGA10.dTb = 273.15;
break;
case 1:
ptAGA10.dPb = 101325;
ptAGA10.dTb = 288.15;
break;
case 0:
ptAGA10.dPb = 101325;
ptAGA10.dTb = 293.15;
break;
}
//begin by calculating densities and thermodynamic properties
ptTherm.Run(ref ptAGA10, ref ptDetail);
//DH is enthalpy change from plenum to throat; this is our initial guess
DH = (ptAGA10.dSOS * ptAGA10.dSOS - dPlenumVelocity * dPlenumVelocity) / 2.0;
//trap plenum conditions before we alter the data stucture's contents
S = ptAGA10.dS;
H = ptAGA10.dH;
R = ptAGA10.dRhof;
P = ptAGA10.dPf;
Z = ptAGA10.dZf;
T = ptAGA10.dTf;
//initialize delta of DH to an arbitrary value outside of
//convergence tolerance
DDH = 10.0;
//Via simple repetition, search for a pressure, temperature and sound speed
//at a nozzle throat which provide constant enthalpy, given the entropy known
//at the plenum. Abort if loop executes more than 100 times without convergence.
for (i = 1; i < MAX_NUM_OF_ITERATIONS; i++)
{
// calculate P and T to satisfy H and S
ptTherm.HS_Mode(ref ptAGA10, ref ptDetail, H - DH, S, true);
//calculate new thermo, including SOS
ptTherm.Run(ref ptAGA10, ref ptDetail);
//hold DH for tolerance check
DDH = DH;
// recalculate DH
DH = (ptAGA10.dSOS * ptAGA10.dSOS - dPlenumVelocity * dPlenumVelocity) / 2.0;
// end loop if tolerance reached
if (Math.Abs(DDH - DH) < tolerance) break;
}
//C* is the real gas critical flow constant (not to be confused with Cperf or CRi)
ptAGA10.dCstar = (ptAGA10.dRhof * ptAGA10.dSOS) / Math.Sqrt(R * P * Z);
//put the original plenum pressure and temperature back
ptAGA10.dPf = P;
ptAGA10.dTf = T;
//restore fluid props to plenum conditions
ptTherm.Run(ref ptAGA10, ref ptDetail);
GB11062 ptGB11062 = new GB11062();
ptGB11062.Run(ref ptAGA10);
//return the critical flow function to caller
return ptAGA10.dCstar;
}// Crit()
/**************************************************************************
* Function : Crit()
* Arguments : Pointers to external AGA10 data struct, Detail and Therm
* objects and a double precision float (gas velocity in plenum)
* Returns : double
* Purpose : calculates C*
* Revisions :
**************************************************************************/
public double Zcal(ref NG_Cal.GasPropsSTRUCT ptAGA10, double dPlenumVelocity)
{
//variables local to function
//check objects for readiness; try to initialize if not
if (null == ptDetail || null == ptTherm)
{
NG_Cal_UnInit();
if (NG_Cal_INITIALIZED != NG_Cal_Init())
{
ptAGA10.lStatus = MEMORY_ALLOCATION_ERROR; return 0.0;
}
}
switch (ptAGA10.dCbtj)
{
case 2:
ptAGA10.dPb = 101325;
ptAGA10.dTb = 273.15;
break;
case 1:
ptAGA10.dPb = 101325;
ptAGA10.dTb = 288.15;
break;
case 0:
ptAGA10.dPb = 101325;
ptAGA10.dTb = 293.15;
break;
}
//begin by calculating densities and thermodynamic properties
ptTherm.Run(ref ptAGA10, ref ptDetail);
GB11062 ptGB11062 = new GB11062();
ptGB11062.Run(ref ptAGA10);
//return the critical flow function to caller
return ptAGA10.dZf;
}// Z()
/**************************************************************************
* Function : Cperf()
* Arguments : pointer to external AGA10 data struct
* Returns : double
* Purpose : calculates isentropic perfect gas critical flow function
* Revisions :
**************************************************************************/
double Cperf(ref NG_Cal.GasPropsSTRUCT ptAGA10)
{
double k, root, exponent;
k = ptAGA10.dKappa; root = 2.0 / (k + 1.0);
exponent = (k + 1.0) / (k - 1.0);
// isentropic perfect gas critical flow function C*i
return (Math.Sqrt(k * Math.Pow(root, exponent)));
}// Cperf
/**************************************************************************
* Function : CRi()
* Arguments : pointer to external AGA10 data struct
* Returns : double
* Purpose : calculates isentropic real gas critical flow function CRi
* Revisions :
**************************************************************************/
double CRi(ref NG_Cal.GasPropsSTRUCT ptAGA10)
{
return (Cperf(ref ptAGA10) / Math.Sqrt(ptAGA10.dZf));
}// CRi()
}
}