GasFlowMeter/User/NG 带注释/Therm.c

714 lines
21 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.

/*************************************************************************
* 文件: therm.c
* 描述: 包含仪表对象的热力学函数
* 热容、焓、熵、声速
* 包含以下函数:
* ThermInit(), ThermDestroy(), Run(), coth(), CpiMolar(), Ho(), So(),
* CprCvrHS(), HS_Mode(), H(), S()
* 版本: ver 1.7 2002.11.17
* 作者: W.B. Peterson
* 修订:
* 版权: (c) 2002 美国天然气协会
**************************************************************************/
#include "NGCal.h"
#include "Detail.h"
#include "Therm.h"
#include <math.h>
#include <stdbool.h> // 添加bool类型支持
// 添加函数前置声明解决隐式声明问题
static void CprCvrHS(AGA10STRUCT *ptAGA10, Detail *ptD);
static double H(AGA10STRUCT *ptAGA10, Detail *ptD);
static double S(AGA10STRUCT *ptAGA10, Detail *ptD);
static void HS_Mode(AGA10STRUCT *ptAGA10, Detail *ptD, double H_target, double S_target, bool bGuess);
double CalTH = 4.1840;
// 高斯积分的根和权重
double GK_root[5] = {
0.14887433898163121088,
0.43339539412924719080,
0.67940956829902440263,
0.86506336668898451073,
0.97390652851717172008
};
double GK_weight[5] = {
0.29552422471475286217,
0.26926671930999634918,
0.21908636251598204295,
0.14945134915058059038,
0.066671344308688137179
};
// 设置积分点数
int GK_points = 5;
// 理想气体热容、焓和熵的方程常数
double ThermConstants[NUMBEROFCOMPONENTS][11] = {
{-29776.4, 7.95454, 43.9417, 1037.09, 1.56373, 813.205, -24.9027, 1019.98,-10.1601, 1070.14,-20.0615},
{-3495.34, 6.95587, 0.272892, 662.738,-0.291318,-680.562, 1.78980, 1740.06, 0.0, 100.0, 4.49823},
{ 20.7307, 6.96237, 2.68645, 500.371,-2.56429,-530.443, 3.91921, 500.198, 2.13290, 2197.22, 5.81381},
{-37524.4, 7.98139, 24.3668, 752.320, 3.53990, 272.846, 8.44724, 1020.13,-13.2732, 869.510,-22.4010},
{-56072.1, 8.14319, 37.0629, 735.402, 9.38159, 247.190, 13.4556, 1454.78,-11.7342, 984.518,-24.0426},
{-13773.1, 7.97183, 6.27078, 2572.63, 2.05010, 1156.72, 0.0, 100.0, 0.0, 100.0, -3.24989},
{-10085.4, 7.94680,-0.08380, 433.801, 2.85539, 843.792, 6.31595, 1481.43,-2.88457, 1102.23,-0.51551},
{-5565.60, 6.66789, 2.33458, 2584.98, .749019, 559.656, 0.0, 100.0, 0.0, 100.0, -7.94821},
{-2753.49, 6.95854, 2.02441, 1541.22, .096774, 3674.81, 0.0, 100.0, 0.0, 100.0, 6.23387},
{-3497.45, 6.96302, 2.40013, 2522.05, 2.21752, 1154.15, 0.0, 100.0, 0.0, 100.0, 9.19749},
{-72387.0, 17.8143, 58.2062, 1787.39, 40.7621, 808.645, 0.0, 100.0, 0.0, 100.0, -44.1341},
{-72674.8, 18.6383, 57.4178, 1792.73, 38.6599, 814.151, 0.0, 100.0, 0.0, 100.0, -46.1938},
{-91505.5, 21.3861, 74.3410, 1701.58, 47.0587, 775.899, 0.0, 100.0, 0.0, 100.0, -60.2474},
{-83845.2, 22.5012, 69.5789, 1719.58, 46.2164, 802.174, 0.0, 100.0, 0.0, 100.0, -62.2197},
{-94982.5, 26.6225, 80.3819, 1718.49, 55.6598, 802.069, 0.0, 100.0, 0.0, 100.0, -77.5366},
{-103353., 30.4029, 90.6941, 1669.32, 63.2028, 786.001, 0.0, 100.0, 0.0, 100.0, -92.0164},
{-109674., 34.0847, 100.253, 1611.55, 69.7675, 768.847, 0.0, 100.0, 0.0, 100.0, -106.149},
{-122599., 38.5014, 111.446, 1646.48, 80.5015, 781.588, 0.0, 100.0, 0.0, 100.0, -122.444},
{-133564., 42.7143, 122.173, 1654.85, 90.2255, 785.564, 0.0, 100.0, 0.0, 100.0, -138.006},
{ 0.0, 4.9680, 0.0, 100.0, 0.0, 100.0, 0.0, 100.0, 0.0, 100.0, 0.0 },
{ 0.0, 4.9680, 0.0, 100.0, 0.0, 100.0, 0.0, 100.0, 0.0, 100.0, 0.0 }
};
// 全局变量
static double dSi = 0.0;
static double dTold = 0.0;
static double dMrxold = 0.0;
/**************************************************************************
* 函数: ThermInit
* 参数: void
* 返回: void
* 目的: 默认构造函数
* 修订:
**************************************************************************/
void ThermInit(void)
{
// 初始化3个历史敏感变量
dSi = 0.0;
dTold = 0.0;
dMrxold = 0.0;
}
/**************************************************************************
* 函数: ThermDestroy
* 参数: void
* 返回: void
* 目的: 默认析构函数
* 修订:
**************************************************************************/
void ThermDestroy(void)
{
// 无动态资源需要释放
}
/**************************************************************************
* 函数: coth
* 参数: double x
* 返回: double
* 目的: 计算双曲余切函数; 用于Ho计算
* 修订:
* 备注: 不是Therm对象类成员只是本文件的工具函数。
* C语言本身不支持双曲余切函数
**************************************************************************/
double coth(double x)
{
return cosh(x)/sinh(x);
}
/**************************************************************************
* 函数: Run
* 参数: AGA10STRUCT *ptAGA10, Detail *ptD
* 返回: void
* 目的: 总体执行控制; SOS和k的顶层数学计算
* 修订:
**************************************************************************/
void Run(AGA10STRUCT *ptAGA10, Detail *ptD)
{
// 局部变量
double c, x, y, z;
// 首先运行AGA 8(1994)详细方法中的基本函数集
Detail_Run(ptD, ptAGA10);
// 找到Z对D的一阶偏导数
Detail_dZdD(ptD, ptAGA10->dDf);
// 找到真实气体的cv, cp, 比焓和比熵
CprCvrHS(ptAGA10, ptD);
// 真实气体比热比
ptAGA10->dk = ptAGA10->dCp / ptAGA10->dCv;
// 分三步计算c为了清晰和便于调试
x = ptAGA10->dk * RGAS * 1000.0 * ptAGA10->dTf;
y = ptAGA10->dMrx;
z = ptAGA10->dZf + ptAGA10->dDf * ptD->ddZdD;
// 计算c即SOS^2
c = (x / y) * z;
// 声速
ptAGA10->dSOS = sqrt(c);
// 计算真实气体等熵指数
// 使用功能上等同于方程3.2的表达式
ptAGA10->dKappa = (c * ptAGA10->dRhof) / ptAGA10->dPf;
}
/**************************************************************************
* 函数: CpiMolar
* 参数: AGA10STRUCT *ptAGA10
* 返回: double
* 目的: 计算理想气体定压摩尔热容(J/mol-K)应用Aly, Lee, McFall的方程
* 备注: 为了连续性,保留了原始常数和方程。
* 主计算完成后应用从热化学卡路里(th)到焦耳的转换。
* 修订:
**************************************************************************/
double CpiMolar(AGA10STRUCT *ptAGA10)
{
double Cp = 0.0;
double Cpx;
double DT, FT, HT, JT;
double Dx, Fx, Hx, Jx;
double T;
int i;
// 为提高可读性使用中间变量T
T = ptAGA10->dTf;
// 计算每个组分的比热容
for (i = 0; i < NUMBEROFCOMPONENTS; i++)
{
// 跳过浓度为零的组分
if (ptAGA10->adMixture[i] <= 0.0) continue;
// 初始化组分比热为零
Cpx = 0.0;
// 计算组分中间项
DT = ThermConstants[i][coefD] / T;
FT = ThermConstants[i][coefF] / T;
HT = ThermConstants[i][coefH] / T;
JT = ThermConstants[i][coefJ] / T;
// 使用中间项避免冗余计算
Dx = DT/sinh(DT);
Fx = FT/cosh(FT);
Hx = HT/sinh(HT);
Jx = JT/cosh(JT);
Cpx += ThermConstants[i][coefB];
Cpx += ThermConstants[i][coefC] * Dx * Dx;
Cpx += ThermConstants[i][coefE] * Fx * Fx;
Cpx += ThermConstants[i][coefG] * Hx * Hx;
Cpx += ThermConstants[i][coefI] * Jx * Jx;
// 使用当前摩尔分数加权贡献
Cpx *= ptAGA10->adMixture[i];
// 将此贡献加到总和中
Cp += Cpx;
}
// 从cal(th)/mol-K转换为J/mol-K
Cp *= CalTH;
return Cp;
}
/**************************************************************************
* 函数: Ho
* 参数: AGA10STRUCT *ptAGA10
* 返回: double
* 目的: 计算理想气体比焓(J/kg)
* 备注: 为了连续性,保留了原始常数和方程。
* 主计算完成后应用从热化学卡路里(th)到焦耳的转换。
* 修订:
**************************************************************************/
double Ho(AGA10STRUCT *ptAGA10)
{
double H = 0.0;
double Hx;
double DT, FT, HT, JT;
double cothDT, tanhFT, cothHT, tanhJT;
double T;
int i;
// 为提高可读性使用中间变量T
T = ptAGA10->dTf;
for (i = 0; i < NUMBEROFCOMPONENTS; i++)
{
// 跳过浓度为零的组分
if (ptAGA10->adMixture[i] <= 0.0) continue;
Hx = 0.0;
// 计算组分中间项
DT = ThermConstants[i][coefD] / T;
FT = ThermConstants[i][coefF] / T;
HT = ThermConstants[i][coefH] / T;
JT = ThermConstants[i][coefJ] / T;
cothDT = coth(DT);
tanhFT = tanh(FT);
cothHT = coth(HT);
tanhJT = tanh(JT);
Hx += ThermConstants[i][coefA];
Hx += ThermConstants[i][coefB] * T;
Hx += ThermConstants[i][coefC] * ThermConstants[i][coefD] * cothDT;
Hx -= ThermConstants[i][coefE] * ThermConstants[i][coefF] * tanhFT;
Hx += ThermConstants[i][coefG] * ThermConstants[i][coefH] * cothHT;
Hx -= ThermConstants[i][coefI] * ThermConstants[i][coefJ] * tanhJT;
// 使用当前摩尔分数加权贡献
Hx *= ptAGA10->adMixture[i];
// 将此贡献加到总和中
H += Hx;
}
// 从cal(th)/g-mol转换为kJ/kg-mol
H *= CalTH;
// 从kJ/kg-mol转换为J/kg
H /= ptAGA10->dMrx;
// 返回J/kg
return H * 1.e3;
}
/**************************************************************************
* 函数: So
* 参数: AGA10STRUCT *ptAGA10
* 返回: double
* 目的: 计算理想气体比熵(J/kg-K)
* 备注: 为了连续性,保留了原始常数和方程。
* 主计算完成后应用从热化学卡路里(th)到焦耳的转换。
* 修订:
**************************************************************************/
double So(AGA10STRUCT *ptAGA10)
{
double S = 0.0;
double Sx;
double DT, FT, HT, JT;
double cothDT, tanhFT, cothHT, tanhJT;
double sinhDT, coshFT, sinhHT, coshJT;
double T;
int i;
// 为提高可读性使用中间变量T
T = ptAGA10->dTf;
for (i = 0; i < NUMBEROFCOMPONENTS; i++)
{
// 跳过浓度为零的组分
if (ptAGA10->adMixture[i] <= 0.0) continue;
Sx = 0.0;
// 计算组分中间项
DT = ThermConstants[i][coefD] / T;
FT = ThermConstants[i][coefF] / T;
HT = ThermConstants[i][coefH] / T;
JT = ThermConstants[i][coefJ] / T;
cothDT = coth(DT);
tanhFT = tanh(FT);
cothHT = coth(HT);
tanhJT = tanh(JT);
sinhDT = sinh(DT);
coshFT = cosh(FT);
sinhHT = sinh(HT);
coshJT = cosh(JT);
Sx += ThermConstants[i][coefK];
Sx += ThermConstants[i][coefB] * log(T);
Sx += ThermConstants[i][coefC] * (DT * cothDT - log(sinhDT));
Sx -= ThermConstants[i][coefE] * (FT * tanhFT - log(coshFT));
Sx += ThermConstants[i][coefG] * (HT * cothHT - log(sinhHT));
Sx -= ThermConstants[i][coefI] * (JT * tanhJT - log(coshJT));
// 使用当前摩尔分数加权贡献
Sx *= ptAGA10->adMixture[i];
// 将此贡献加到总和中
S += Sx;
}
// 从cal(th)/mol-K转换为kJ/kg mol-K
S *= CalTH;
// 从kJ/kg mol-K转换为kJ/kg-K
S /= ptAGA10->dMrx;
// 返回J/kg-K
return S * 1.e3;
}
/**************************************************************************
* 函数: CprCvrHS
* 参数: AGA10STRUCT *ptAGA10, Detail *ptD
* 返回: void
* 目的: 高效地分组计算Cp, Cv, H和S
* 修订:
**************************************************************************/
void CprCvrHS(AGA10STRUCT *ptAGA10, Detail *ptD)
{
double Cvinc, Cvr, Cpr;
double Hinc;
double Sinc;
double Smixing;
double Cp, Si;
double a, b, x;
int i;
// 初始化积分为零
Cvinc = 0.0;
Hinc = 0.0;
Sinc = 0.0;
// 初始化混合熵
Smixing = 0.0;
// 找到理想气体Cp
Cp = CpiMolar(ptAGA10);
// 找到理想气体焓
ptAGA10->dHo = Ho(ptAGA10);
// 找到理想气体熵
Si = So(ptAGA10);
// 计算理想气体定压比热容(J/kgK)
ptAGA10->dCpi = (Cp * 1000.0) / ptAGA10->dMrx;
// 从D=0到D=D积分偏导数应用Gauss-Kronrod求积法
for (i = 0; i < GK_points; i++)
{
// 在+横坐标处设置计算点
x = ptAGA10->dDf * (1.0 + GK_root[i]) / 2.0;
// 在D处获取Z
Detail_zdetail(ptD, x);
Detail_dZdT(ptD, x);
Detail_d2ZdT2(ptD, x);
// 在+横坐标处收集贡献,应用权重因子
Hinc += GK_weight[i] * ptD->ddZdT / x;
Cvinc += GK_weight[i] * (2.0 * ptD->ddZdT + ptAGA10->dTf * ptD->dd2ZdT2) / x;
Sinc += GK_weight[i] * (ptD->dZ + ptAGA10->dTf * ptD->ddZdT - 1.0) / x;
// 在-横坐标处设置计算点
x = ptAGA10->dDf * (1.0 - GK_root[i]) / 2.0;
// 在D处获取Z
Detail_zdetail(ptD, x);
// 计算Z对T的一阶和二阶偏导数
Detail_dZdT(ptD, x);
Detail_d2ZdT2(ptD, x);
// 在-横坐标处收集贡献,应用权重因子
Hinc += GK_weight[i] * ptD->ddZdT / x;
Cvinc += GK_weight[i] * (2.0 * ptD->ddZdT + ptAGA10->dTf * ptD->dd2ZdT2) / x;
Sinc += GK_weight[i] * (ptD->dZ + ptAGA10->dTf * ptD->ddZdT - 1.0) / x;
}
// 将Z和偏导数恢复到全摩尔密度
Detail_zdetail(ptD, ptAGA10->dDf);
Detail_dZdT(ptD, ptAGA10->dDf);
Detail_d2ZdT2(ptD, ptAGA10->dDf);
// 完成Cv摩尔计算
Cvr = Cp - RGAS * (1.0 + ptAGA10->dTf * Cvinc * 0.5 * ptAGA10->dDf);
// Cp的中间值包含2个偏导数
a = (ptAGA10->dZf + ptAGA10->dTf * ptD->ddZdT);
b = (ptAGA10->dZf + ptAGA10->dDf * ptD->ddZdD);
// 完成摩尔Cp计算的方程取消适当的项
Cpr = Cvr + RGAS * ((a * a)/b);
// 从摩尔基准转换为质量基准
Cpr /= ptAGA10->dMrx;
Cvr /= ptAGA10->dMrx;
// 写入数据结构
ptAGA10->dCv = Cvr * 1000.0; // 从joules/kgK转换为kilojoules/kgK
ptAGA10->dCp = Cpr * 1000.0;
// 计算比焓
ptAGA10->dH = ptAGA10->dHo + 1000.0 * RGAS * ptAGA10->dTf *
(ptAGA10->dZf - 1.0 - ptAGA10->dTf * Hinc * 0.5 * ptAGA10->dDf) / ptAGA10->dMrx;
// 计算混合熵
for (i = 0; i < NUMBEROFCOMPONENTS; i++)
{
if (ptAGA10->adMixture[i] > 0.0) // 避免log(0)
Smixing += ptAGA10->adMixture[i] * log(ptAGA10->adMixture[i]);
}
Smixing *= RGAS;
// 计算比熵
ptAGA10->dS = Si - Smixing - 1000.0 * RGAS *
(log(ptAGA10->dPf/101325.0) - log(ptAGA10->dZf) + Sinc * 0.5 * ptAGA10->dDf) / ptAGA10->dMrx;
}
/**************************************************************************
* 函数: HS_Mode
* 参数: AGA10STRUCT *ptAGA10, Detail *ptD, double H_target, double S_target, bool bGuess
* 返回: void
* 目的: 从已知焓和熵计算压力和温度,有或没有先验估计。
* 此函数在计算C*时有作用。
* 解决方案基于双重嵌套的试错算法和牛顿法。
*
* 为说明目的,此示例支持两种方法。
* 如果您在不知道P和T的情况下开始将输入参数bGuess设置为false
* 从而指定保守的搜索方法。
* 但是如果您有猜测P和T的基础(例如临界流喷嘴的集气室条件)
* 通过AGA10STRUCT设置P和T并设置bGuess = true。
* 初始猜测允许搜索函数更积极且通常更快。
* 修订:
**************************************************************************/
void HS_Mode(AGA10STRUCT *ptAGA10, Detail *ptD, double H_target, double S_target, bool bGuess)
{
double s0, s1, s2, t0, t1, t2, tmin, tmax;
double h0, h1, h2, p0, p1, p2, px, pmin, pmax;
double delta1, delta2;
double tolerance = 0.001; // 收敛容差(用于H和S搜索)
int i, j;
// s0和h0是我们的真实气体参考点
s0 = S_target;
h0 = H_target;
// 调用函数指定搜索参数是通过ptAGA10提供还是未知
if (bGuess)
{
t1 = ptAGA10->dTf;
px = ptAGA10->dPf;
pmax = px * 2.0;
pmin = px * 0.1;
tmax = t1 * 1.5;
tmin = t1 * 0.67;
}
else // 使用任意通用限制
{
t1 = 273.15;
px = 1013250.0; // 10个大气压
pmax = P_MAX;
pmin = 10000.0; // 10 kPa
tmax = T_MAX;
tmin = T_MIN;
}
// 设置温度差
t2 = t1 + 10.0;
// 开始双重试错搜索T和P
// 用初始猜测运行计算
Detail_Run(ptD, ptAGA10);
// h1是给定h和h@Tf, Pf之间的差
h1 = H(ptAGA10, ptD) - h0;
// 外循环: 搜索满足恒定焓的t2
for (i = 0; i < MAX_NUM_OF_ITERATIONS; i++)
{
ptAGA10->dTf = t2;
p1 = px; // 重置一个括号
p2 = px * 0.1; // 将另一个括号设置为上括号的0.1倍
ptAGA10->dPf = p1;
Detail_Run(ptD, ptAGA10);
s1 = S(ptAGA10, ptD) - s0;
// 内循环: 搜索满足恒定熵的p2
for (j = 0; j < MAX_NUM_OF_ITERATIONS; j++)
{
ptAGA10->dPf = p2;
Detail_Run(ptD, ptAGA10);
s2 = S(ptAGA10, ptD) - s0;
// 计算我们的比例变化
delta2 = fabs(s1 - s2) / s0;
// 足够接近?
if (delta2 < tolerance) break;
// 将我们的估计修正为p2
p0 = p2;
p2 = (p1 * s2 - p2 * s1) / (s2 - s1);
// 检查负压并钳制到pmin以确保安全
if (p2 <= pmin)
{
p2 = pmin;
}
// 检查是否创建了不切实际的压力
if (p2 >= pmax) p2 = pmax;
// 交换值
p1 = p0;
s1 = s2;
}
// 检查是否未能收敛
if (j >= MAX_NUM_OF_ITERATIONS)
ptAGA10->lStatus = MAX_NUM_OF_ITERATIONS_EXCEEDED;
// 在猜测的P和当前迭代T处计算焓
h2 = H(ptAGA10, ptD) - h0;
// 计算我们的比例变化
delta1 = fabs(h1 - h2) / h0;
// 足够接近?
if (delta1 < tolerance && i > 0) break;
// 将我们的估计修正为t2
t0 = t2;
t2 = (t1 * h2 - t2 * h1) / (h2 - h1);
// 检查是否创建了不切实际的温度
if (t2 >= tmax) t2 = tmax;
// 如有必要修正t2
if (t2 <= tmin)
{
t2 = t0 + 10.0;
ptAGA10->dTf = t2;
Detail_Run(ptD, ptAGA10);
h2 = H(ptAGA10, ptD) - h0;
}
t1 = t0;
h1 = h2;
}
// 检查是否未能收敛
if (i >= MAX_NUM_OF_ITERATIONS)
ptAGA10->lStatus = MAX_NUM_OF_ITERATIONS_EXCEEDED;
}
/**************************************************************************
* 函数: H
* 参数: AGA10STRUCT *ptAGA10, Detail *ptD
* 返回: double
* 目的: 真实气体比焓
* 修订:
**************************************************************************/
double H(AGA10STRUCT *ptAGA10, Detail *ptD)
{
double Hinc;
double x;
int i;
// 初始化积分
Hinc = 0.0;
// 找到理想气体焓
ptAGA10->dHo = Ho(ptAGA10);
// 从D=0到D=D积分偏导数应用Gauss-Kronrod求积法
for (i = 0; i < GK_points; i++)
{
// 计算Z对T的一阶和二阶偏导数
x = ptAGA10->dDf * (1.0 + GK_root[i]) / 2.0;
Detail_zdetail(ptD, x);
Detail_dZdT(ptD, x);
Detail_d2ZdT2(ptD, x);
Hinc += GK_weight[i] * ptD->ddZdT / x;
if (i == 10) break;
x = ptAGA10->dDf * (1.0 - GK_root[i]) / 2.0;
Detail_zdetail(ptD, x);
Detail_dZdT(ptD, x);
Detail_d2ZdT2(ptD, x);
Hinc += GK_weight[i] * ptD->ddZdT / x;
}
Detail_zdetail(ptD, ptAGA10->dDf);
Detail_dZdT(ptD, ptAGA10->dDf);
Detail_d2ZdT2(ptD, ptAGA10->dDf);
// 计算比焓
ptAGA10->dH = ptAGA10->dHo + 1000.0 * RGAS * ptAGA10->dTf *
(ptAGA10->dZf - 1.0 - ptAGA10->dTf * Hinc * 0.5 * ptAGA10->dDf) / ptAGA10->dMrx;
return ptAGA10->dH;
}
/**************************************************************************
* 函数: S
* 参数: AGA10STRUCT *ptAGA10, Detail *ptD
* 返回: double
* 目的: 真实气体比熵
* 修订:
**************************************************************************/
double S(AGA10STRUCT *ptAGA10, Detail *ptD)
{
double Sinc;
double Smixing;
double x;
int i;
// 初始化积分
Sinc = 0.0;
// 初始化混合熵
Smixing = 0.0;
// 从D=0到D=D积分偏导数应用Gauss-Kronrod求积法
for (i = 0; i < GK_points; i++)
{
// 计算Z对T的一阶和二阶偏导数
x = ptAGA10->dDf * (1.0 + GK_root[i]) / 2.0;
Detail_zdetail(ptD, x);
Detail_dZdT(ptD, x);
Detail_d2ZdT2(ptD, x);
Sinc += GK_weight[i] * (ptD->dZ + ptAGA10->dTf * ptD->ddZdT - 1.0) / x;
if (i == 10) break;
x = ptAGA10->dDf * (1.0 - GK_root[i]) / 2.0;
Detail_zdetail(ptD, x);
Detail_dZdT(ptD, x);
Detail_d2ZdT2(ptD, x);
Sinc += GK_weight[i] * (ptD->dZ + ptAGA10->dTf * ptD->ddZdT - 1.0) / x;
}
// 重置Z和偏导数dZdT和d2ZdT2
Detail_zdetail(ptD, ptAGA10->dDf);
Detail_dZdT(ptD, ptAGA10->dDf);
Detail_d2ZdT2(ptD, ptAGA10->dDf);
// 找到理想气体熵,但仅在温度或组成发生变化时
if (ptAGA10->dTf != dTold || ptAGA10->dMrx != dMrxold)
{
dSi = So(ptAGA10);
dTold = ptAGA10->dTf;
dMrxold = ptAGA10->dMrx;
}
// 计算混合熵
for (i = 0; i < NUMBEROFCOMPONENTS; i++)
{
if (ptAGA10->adMixture[i] > 0.0) // 避免log(0)
Smixing += ptAGA10->adMixture[i] * log(ptAGA10->adMixture[i]);
}
Smixing *= RGAS;
// 计算比熵
ptAGA10->dS = dSi - Smixing - 1000.0 * RGAS *
(log(ptAGA10->dPf/101325.0) - log(ptAGA10->dZf) + Sinc * 0.5 * ptAGA10->dDf) / ptAGA10->dMrx;
return ptAGA10->dS;
}