2 #define _CRT_SECURE_NO_WARNINGS
28 static const char ITc=
'B';
29 static double epsilon=0.621945,R_bar=8.314472;
30 static int FlagUseVirialCorrelations=0,FlagUseIsothermCompressCorrelation=0,FlagUseIdealGasEnthalpyCorrelations=0;
34 static double MM_Air(
void)
38 static double MM_Water(
void)
42 static double B_Air(
double T)
44 return DerivTerms((
char *)
"B",T,1e-12,(
char *)
"Air");
46 static double dBdT_Air(
double T)
48 return DerivTerms((
char *)
"dBdT",T,1e-12,(
char *)
"Air");
50 static double B_Water(
double T)
52 return DerivTerms((
char *)
"B",T,1e-12,(
char *)
"Water");
54 static double dBdT_Water(
double T)
56 return DerivTerms((
char *)
"dBdT",T,1e-12,(
char *)
"Water");
58 static double C_Air(
double T)
60 return DerivTerms((
char *)
"C",T,1e-12,(
char *)
"Air");
62 static double dCdT_Air(
double T)
64 return DerivTerms((
char *)
"dCdT",T,1e-12,(
char *)
"Air");
66 static double C_Water(
double T)
68 return DerivTerms((
char *)
"C",T,1e-12,(
char *)
"Water");
70 static double dCdT_Water(
double T)
72 return DerivTerms((
char *)
"dCdT",T,1e-12,(
char *)
"Water");
76 if (flag==0 || flag==1)
78 FlagUseVirialCorrelations=flag;
82 printf(
"UseVirialCorrelations takes an integer, either 0 (no) or 1 (yes)\n");
88 if (flag==0 || flag==1)
90 FlagUseIsothermCompressCorrelation=flag;
94 printf(
"UseIsothermCompressCorrelation takes an integer, either 0 (no) or 1 (yes)\n");
99 if (flag==0 || flag==1)
101 FlagUseIdealGasEnthalpyCorrelations=flag;
105 printf(
"UseIdealGasEnthalpyCorrelations takes an integer, either 0 (no) or 1 (yes)\n");
108 static double Brent_HAProps_T(
char *OutputName,
char *Input1Name,
double Input1,
char *Input2Name,
double Input2,
double TargetVal,
double T_min,
double T_max)
114 double Input1,Input2,TargetVal;
115 char *OutputName,*Input1Name,*Input2Name;
118 BrentSolverResids(
char *OutputName,
char *Input1Name,
double Input1,
char *Input2Name,
double Input2,
double TargetVal)
120 this->OutputName = OutputName;
121 this->Input1Name = Input1Name;
122 this->Input2Name = Input2Name;
123 this->Input1 = Input1;
124 this->Input2 = Input2;
125 this->TargetVal = TargetVal;
127 ~BrentSolverResids(){};
129 double call(
double T){
130 return HAProps(OutputName,(
char *)
"T",T,Input1Name,Input1,Input2Name,Input2)-TargetVal;
134 BrentSolverResids *BSR =
new BrentSolverResids(OutputName, Input1Name, Input1, Input2Name, Input2, TargetVal);
137 T =
Brent(BSR,T_min,T_max,1e-7,1e-4,50,&errstr);
143 static double Secant_HAProps_T(
char *OutputName,
char *Input1Name,
double Input1,
char *Input2Name,
double Input2,
double TargetVal,
double T_guess)
146 double x1=0,x2=0,x3=0,y1=0,y2=0,eps=5e-7,f=999,T=300,change;
149 while ((iter<=3 || (fabs(f)>eps && fabs(change)>1e-10)) && iter<100)
151 if (iter==1){x1=T_guess; T=x1;}
152 if (iter==2){x2=T_guess+0.001; T=x2;}
154 f=
HAProps(OutputName,(
char *)
"T",T,Input1Name,Input1,Input2Name,Input2)-TargetVal;
159 x3=x2-y2/(y2-y1)*(x2-x1);
160 change = y2/(y2-y1)*(x2-x1);
168 static double Secant_HAProps_W(
const char *OutputName,
const char *Input1Name,
double Input1,
const char *Input2Name,
double Input2,
double TargetVal,
double W_guess)
171 double x1=0,x2=0,x3=0,y1=0,y2=0,eps=1e-8,f=999,W=0.0001;
174 while ((iter<=3 || fabs(f)>eps) && iter<100)
176 if (iter == 1){x1 = W_guess; W = x1;}
177 if (iter == 2){x2 = W_guess+0.001; W = x2;}
178 if (iter > 2) {W = x2;}
179 f =
HAProps(OutputName,(
char *)
"W",W,Input1Name,Input1,Input2Name,Input2)-TargetVal;
180 if (iter == 1){y1 = f;}
184 x3=x2-y2/(y2-y1)*(x2-x1);
193 static double _B_aw(
double T)
196 double a[]={0,0.665687e2,-0.238834e3,-0.176755e3};
197 double b[]={0,-0.237,-1.048,-3.183};
198 double rhobarstar=1000,Tstar=100;
199 return 1/rhobarstar*(a[1]*pow(T/Tstar,b[1])+a[2]*pow(T/Tstar,b[2])+a[3]*pow(T/Tstar,b[3]));
202 static double _dB_aw_dT(
double T)
205 double a[]={0,0.665687e2,-0.238834e3,-0.176755e3};
206 double b[]={0,-0.237,-1.048,-3.183};
207 double rhobarstar=1000,Tstar=100;
208 return 1/rhobarstar/Tstar*(a[1]*b[1]*pow(T/Tstar,b[1]-1)+a[2]*b[2]*pow(T/Tstar,b[2]-1)+a[3]*b[3]*pow(T/Tstar,b[3]-1));
211 static double _C_aaw(
double T)
214 double c[]={0,0.482737e3,0.105678e6,-0.656394e8,0.294442e11,-0.319317e13};
215 double rhobarstar=1000,Tstar=1,summer=0;
int i;
218 summer+=c[i]*pow(T/Tstar,1-i);
220 return 1.0/rhobarstar/rhobarstar*summer;
223 static double _dC_aaw_dT(
double T)
226 double c[]={0,0.482737e3,0.105678e6,-0.656394e8,0.294442e11,-0.319317e13};
227 double rhobarstar=1000,Tstar=1,summer=0;
int i;
230 summer+=c[i]*(1-i)*pow(T/Tstar,-i);
232 return 1.0/rhobarstar/rhobarstar/Tstar*summer;
235 static double _C_aww(
double T)
238 double d[]={0,-0.1072887e2,0.347804e4,-0.383383e6,0.334060e8};
239 double rhobarstar=1,Tstar=1,summer=0;
int i;
242 summer+=d[i]*pow(T/Tstar,1-i);
244 return -1.0/rhobarstar/rhobarstar*exp(summer);
247 static double _dC_aww_dT(
double T)
250 double d[]={0,-0.1072887e2,0.347804e4,-0.383383e6,0.334060e8};
251 double rhobarstar=1,Tstar=1,summer1=0,summer2=0;
int i;
254 summer1+=d[i]*pow(T/Tstar,1-i);
258 summer2+=d[i]*(1-i)*pow(T/Tstar,-i);
260 return -1.0/rhobarstar/rhobarstar/Tstar*exp(summer1)*summer2;
264 static double B_m(
double T,
double psi_w)
267 double Tj,tau_Air,tau_Water,B_aa,B_ww,B_aw;
272 if (FlagUseVirialCorrelations==1)
274 B_aa=-0.000721183853646 +1.142682674467e-05*T -8.838228412173e-08*pow(T,2)
275 +4.104150642775e-10*pow(T,3) -1.192780880645e-12*pow(T,4) +2.134201312070e-15*pow(T,5)
276 -2.157430412913e-18*pow(T,6) +9.453830907795e-22*pow(T,7);
277 B_ww=-10.8963128394 +2.439761625859e-01*T -2.353884845100e-03*pow(T,2)
278 +1.265864734412e-05*pow(T,3) -4.092175700300e-08*pow(T,4) +7.943925411344e-11*pow(T,5)
279 -8.567808759123e-14*pow(T,6) +3.958203548563e-17*pow(T,7);
283 B_aa=B_Air(T)*MM_Air()/1e3;
284 B_ww=B_Water(T)*MM_Water()/1e3;
288 return pow(1-psi_w,2)*B_aa+2*(1-psi_w)*psi_w*B_aw+psi_w*psi_w*B_ww;
291 static double dB_m_dT(
double T,
double psi_w)
294 double Tj,tau_Air,tau_Water,dB_dT_aa,dB_dT_ww,dB_dT_aw;
299 if (FlagUseVirialCorrelations)
301 dB_dT_aa=1.65159324353e-05 -3.026130954749e-07*T +2.558323847166e-09*pow(T,2) -1.250695660784e-11*pow(T,3) +3.759401946106e-14*pow(T,4) -6.889086380822e-17*pow(T,5) +7.089457032972e-20*pow(T,6) -3.149942145971e-23*pow(T,7);
302 dB_dT_ww=0.65615868848 -1.487953162679e-02*T +1.450134660689e-04*pow(T,2) -7.863187630094e-07*pow(T,3) +2.559556607010e-09*pow(T,4) -4.997942221914e-12*pow(T,5) +5.417678681513e-15*pow(T,6) -2.513856275241e-18*pow(T,7);
306 dB_dT_aa=dBdT_Air(T)*MM_Air()/1e3;
307 dB_dT_ww=dBdT_Water(T)*MM_Water()/1e3;
309 dB_dT_aw=_dB_aw_dT(T)/1e3;
310 return pow(1-psi_w,2)*dB_dT_aa+2*(1-psi_w)*psi_w*dB_dT_aw+psi_w*psi_w*dB_dT_ww;
313 static double C_m(
double T,
double psi_w)
316 double Tj,tau_Air,tau_Water,C_aaa,C_www,C_aww,C_aaw;
321 if (FlagUseVirialCorrelations)
323 C_aaa=1.29192158975e-08 -1.776054020409e-10*T +1.359641176409e-12*pow(T,2)
324 -6.234878717893e-15*pow(T,3) +1.791668730770e-17*pow(T,4) -3.175283581294e-20*pow(T,5)
325 +3.184306136120e-23*pow(T,6) -1.386043640106e-26*pow(T,7);
326 C_www=-0.580595811134 +1.365952762696e-02*T -1.375986293288e-04*pow(T,2)
327 +7.687692259692e-07*pow(T,3) -2.571440816920e-09*pow(T,4) +5.147432221082e-12*pow(T,5)
328 -5.708156494894e-15*pow(T,6) +2.704605721778e-18*pow(T,7);
332 C_aaa=C_Air(T)*MM_Air()*MM_Air()/1e6;
333 C_www=C_Water(T)*MM_Water()*MM_Water()/1e6;
337 return pow(1-psi_w,3)*C_aaa+3*pow(1-psi_w,2)*psi_w*C_aaw+3*(1-psi_w)*psi_w*psi_w*C_aww+pow(psi_w,3)*C_www;
340 static double dC_m_dT(
double T,
double psi_w)
344 double Tj,tau_Air,tau_Water,dC_dT_aaa,dC_dT_www,dC_dT_aww,dC_dT_aaw;
349 if (FlagUseVirialCorrelations)
351 dC_dT_aaa=-2.46582342273e-10 +4.425401935447e-12*T -3.669987371644e-14*pow(T,2) +1.765891183964e-16*pow(T,3) -5.240097805744e-19*pow(T,4) +9.502177003614e-22*pow(T,5) -9.694252610339e-25*pow(T,6) +4.276261986741e-28*pow(T,7);
352 dC_dT_www=0.0984601196142 -2.356713397262e-03*T +2.409113323685e-05*pow(T,2) -1.363083778715e-07*pow(T,3) +4.609623799524e-10*pow(T,4) -9.316416405390e-13*pow(T,5) +1.041909136255e-15*pow(T,6) -4.973918480607e-19*pow(T,7);
356 dC_dT_aaa=dCdT_Air(T)*MM_Air()*MM_Air()/1e6;
357 dC_dT_www=dCdT_Water(T)*MM_Water()*MM_Water()/1e6;
359 dC_dT_aaw=_dC_aaw_dT(T)/1e6;
360 dC_dT_aww=_dC_aww_dT(T)/1e6;
361 return pow(1-psi_w,3)*dC_dT_aaa+3*pow(1-psi_w,2)*psi_w*dC_dT_aaw+3*(1-psi_w)*psi_w*psi_w*dC_dT_aww+pow(psi_w,3)*dC_dT_www;
365 return psi_w*epsilon/(1-psi_w);
368 static double HenryConstant(
double T)
371 double p_ws,beta_N2,beta_O2,beta_Ar,beta_a,tau,Tr,Tc=647.096;
374 p_ws=
Props(
"P",
"T",T,
"Q",1.0,
"Water");
375 beta_N2=p_ws*exp(-9.67578/Tr+4.72162*pow(tau,0.355)/Tr+11.70585*pow(Tr,-0.41)*exp(tau));
376 beta_O2=p_ws*exp(-9.44833/Tr+4.43822*pow(tau,0.355)/Tr+11.42005*pow(Tr,-0.41)*exp(tau));
377 beta_Ar=p_ws*exp(-8.40954/Tr+4.29587*pow(tau,0.355)/Tr+10.52779*pow(Tr,-0.41)*exp(tau));
378 beta_a=1/(0.7812/beta_N2+0.2095/beta_O2+0.0093/beta_Ar);
379 return 1/(1.01325*beta_a)/1000.0;
384 double f=0,Rbar=8.314371,eps=1e-8,Tj;
385 double x1=0,x2=0,x3,y1=0,y2,change=_HUGE;
387 double p_ws,tau_Air,tau_Water,B_aa,B_aw,B_ww,C_aaa,C_aaw,C_aww,C_www,
388 line1,line2,line3,line4,line5,line6,line7,line8,k_T,beta_H,LHS,RHS,psi_ws,
398 p_ws=
PropsSI(
"P",
"T",T,
"Q",0,
"Water");
399 if (FlagUseIsothermCompressCorrelation)
401 k_T = 1.6261876614E-22*pow(T,6) - 3.3016385196E-19*pow(T,5) + 2.7978984577E-16*pow(T,4)
402 - 1.2672392901E-13*pow(T,3) + 3.2382864853E-11*pow(T,2) - 4.4318979503E-09*T + 2.5455947289E-07;
406 double rho =
PropsSI(
"D",
"T",T,
"P",p,
"Water");
407 k_T=
DerivTerms((
char *)
"IsothermalCompressibility",T,rho,(
char *)
"Water")/1000;
409 beta_H=HenryConstant(T);
410 vbar_ws=1.0/
Props(
"D",
"T",T,
"Q",0,
"Water")*MM_Water()/1000;
418 vbar_ws=
dg_dp_Ice(T,p/1000)*MM_Water()/1000/1000;
432 if (FlagUseVirialCorrelations)
434 B_aa=-0.000721183853646 +1.142682674467e-05*T -8.838228412173e-08*pow(T,2)
435 +4.104150642775e-10*pow(T,3) -1.192780880645e-12*pow(T,4) +2.134201312070e-15*pow(T,5)
436 -2.157430412913e-18*pow(T,6) +9.453830907795e-22*pow(T,7);
437 B_ww=-10.8963128394 +2.439761625859e-01*T -2.353884845100e-03*pow(T,2)
438 +1.265864734412e-05*pow(T,3) -4.092175700300e-08*pow(T,4) +7.943925411344e-11*pow(T,5)
439 -8.567808759123e-14*pow(T,6) +3.958203548563e-17*pow(T,7);
440 C_aaa=1.29192158975e-08 -1.776054020409e-10*T +1.359641176409e-12*pow(T,2)
441 -6.234878717893e-15*pow(T,3) +1.791668730770e-17*pow(T,4) -3.175283581294e-20*pow(T,5)
442 +3.184306136120e-23*pow(T,6) -1.386043640106e-26*pow(T,7);
443 C_www=-0.580595811134 +1.365952762696e-02*T -1.375986293288e-04*pow(T,2)
444 +7.687692259692e-07*pow(T,3) -2.571440816920e-09*pow(T,4) +5.147432221082e-12*pow(T,5)
445 -5.708156494894e-15*pow(T,6) +2.704605721778e-18*pow(T,7);
449 B_aa=B_Air(T)*MM_Air()/1e3;
450 C_aaa=C_Air(T)*MM_Air()*MM_Air()/1e6;
451 B_ww=B_Water(T)*MM_Water()/1e3;
452 C_www=C_Water(T)*MM_Water()*MM_Water()/1e6;
460 while ((iter<=3 || change>eps) && iter<100)
462 if (iter==1){x1=1.00; f=x1;}
463 if (iter==2){x2=1.00+0.000001; f=x2;}
472 line1=((1+k_T*p_ws)*(p-p_ws)-k_T*(p*p-p_ws*p_ws)/2.0)/(Rbar*T)*vbar_ws+log(1-beta_H*(1-psi_ws)*p);
473 line2=pow(1-psi_ws,2)*p/(Rbar*T)*B_aa-2*pow(1-psi_ws,2)*p/(Rbar*T)*B_aw-(p-p_ws-pow(1-psi_ws,2)*p)/(Rbar*T)*B_ww;
474 line3=pow(1-psi_ws,3)*p*p/pow(Rbar*T,2)*C_aaa+(3*pow(1-psi_ws,2)*(1-2*(1-psi_ws))*p*p)/(2*pow(Rbar*T,2))*C_aaw;
475 line4=-3*pow(1-psi_ws,2)*psi_ws*p*p/pow(Rbar*T,2)*C_aww-((3-2*psi_ws)*psi_ws*psi_ws*p*p-p_ws*p_ws)/(2*pow(Rbar*T,2))*C_www;
476 line5=-(pow(1-psi_ws,2)*(-2+3*psi_ws)*psi_ws*p*p)/pow(Rbar*T,2)*B_aa*B_ww;
477 line6=-(2*pow(1-psi_ws,3)*(-1+3*psi_ws)*p*p)/pow(Rbar*T,2)*B_aa*B_aw;
478 line7=(6*pow(1-psi_ws,2)*psi_ws*psi_ws*p*p)/pow(Rbar*T,2)*B_ww*B_aw-(3*pow(1-psi_ws,4)*p*p)/(2*pow(Rbar*T,2))*B_aa*B_aa;
479 line8=-(2*pow(1-psi_ws,2)*psi_ws*(-2+3*psi_ws)*p*p)/pow(Rbar*T,2)*B_aw*B_aw-(p_ws*p_ws-(4-3*psi_ws)*pow(psi_ws,3)*p*p)/(2*pow(Rbar*T,2))*B_ww*B_ww;
480 RHS=line1+line2+line3+line4+line5+line6+line7+line8;
482 if (iter==1){y1=LHS-RHS;}
486 x3=x2-y2/(y2-y1)*(x2-x1);
487 change=fabs(y2/(y2-y1)*(x2-x1));
499 printf(
"Sorry, Need to update!");
503 if (!strcmp(Code,
"GIVEN_TDP"))
505 else if (!strcmp(Code,
"GIVEN_HUMRAT"))
507 else if (!strcmp(Code,
"GIVEN_TWB"))
509 else if (!strcmp(Code,
"GIVEN_RH"))
511 else if (!strcmp(Code,
"GIVEN_ENTHALPY"))
515 fprintf(stderr,
"Code to returnHumAirCode in HumAir.c [%s] not understood",Code);
528 double mu_a,mu_w,Phi_av,Phi_va,Ma,Mw;
532 mu_a=
Props(
"V",
"T",T,
"P",p,
"Air");
534 mu_w=
Props(
"V",
"P",p,
"Q",1,
"Water");
535 Phi_av=sqrt(2.0)/4.0*pow(1+Ma/Mw,-0.5)*pow(1+sqrt(mu_a/mu_w)*pow(Mw/Ma,0.25),2);
536 Phi_va=sqrt(2.0)/4.0*pow(1+Mw/Ma,-0.5)*pow(1+sqrt(mu_w/mu_a)*pow(Ma/Mw,0.25),2);
537 return (1-psi_w)*mu_a/((1-psi_w)+psi_w*Phi_av)+psi_w*mu_w/(psi_w+(1-psi_w)*Phi_va);
548 double mu_a,mu_w,k_a,k_w,Phi_av,Phi_va,Ma,Mw;
552 k_a=
Props(
"L",
"T",T,
"P",p,
"Air");
553 mu_a=
Props(
"V",
"T",T,
"P",p,
"Air");
555 k_w=
Props(
"L",
"P",p,
"Q",1,
"Water");
556 mu_w=
Props(
"V",
"P",p,
"Q",1,
"Water");
557 Phi_av=sqrt(2.0)/4.0*pow(1+Ma/Mw,-0.5)*pow(1+sqrt(mu_a/mu_w)*pow(Mw/Ma,0.25),2);
558 Phi_va=sqrt(2.0)/4.0*pow(1+Mw/Ma,-0.5)*pow(1+sqrt(mu_w/mu_a)*pow(Ma/Mw,0.25),2);
559 return (1-psi_w)*k_a/((1-psi_w)+psi_w*Phi_av)+psi_w*k_w/(psi_w+(1-psi_w)*Phi_va);
565 double v_bar0, v_bar=0, R_bar=8.314472,x1=0,x2=0,x3,y1=0,y2,resid,eps,Bm,Cm;
572 v_bar0=R_bar*T/p/1000;
578 iter=1; eps=1e-8; resid=999;
579 while ((iter<=3 || fabs(resid)>eps) && iter<100)
581 if (iter==1){x1=v_bar0; v_bar=x1;}
582 if (iter==2){x2=v_bar0+0.000001; v_bar=x2;}
583 if (iter>2) {v_bar=x2;}
587 resid=p-(R_bar/1000)*T/v_bar*(1+Bm/v_bar+Cm/(v_bar*v_bar));
589 if (iter==1){y1=resid;}
593 x3=x2-y2/(y2-y1)*(x2-x1);
602 double hbar_w_0,tau,rhobar,hbar_w,rho;
604 hbar_w_0=-0.01102303806;
605 tau = Water.
crit.
T/T;
613 double sbar_w,tau,R_bar,rho;
615 tau = Water.
crit.
T/T;
616 rho = p/(R_bar/MM_Water()*T);
622 double hbar_a_0,tau,rhobar,hbar_a,R_bar_Lemmon, rho;
624 hbar_a_0=-7914.149298;
628 rho = rhobar *
Props1(
"Air",
"molemass");
629 R_bar_Lemmon=8.314510;
630 hbar_a=hbar_a_0+R_bar_Lemmon*T*(1+tau*
DerivTerms((
char *)
"dphi0_dTau",T,rho,(
char *)
"Air"));
635 double sbar_0_Lem,tau,sbar_a,R_bar_Lemmon,T0=273.15,p0=101.325,v_0,v_bar_0, rho_a,rho_bar_a, rho_bar_0,rho_0;
636 R_bar_Lemmon=8.314510;
638 sbar_0_Lem=-196.1375815;
641 v_0 = R_bar_Lemmon/MM_Air()*T0/p0;
642 rho_bar_a = 1/v_bar_a;
643 rho_a = rho_bar_a *
Props1(
"Air",
"molemass");
644 v_bar_0 = R_bar_Lemmon*T0/p0;
645 rho_bar_0 = 1/v_bar_0;
646 rho_0 = rho_bar_0 *
Props1(
"Air",
"molemass");
647 sbar_a=sbar_0_Lem+R_bar_Lemmon*(tau*
DerivTerms((
char *)
"dphi0_dTau",T,rho_0,(
char *)
"Air")-
DerivTerms((
char *)
"phi0",T,rho_0,(
char *)
"Air"))+R_bar_Lemmon*log(v_bar_a/v_bar_0);
657 double hbar_0,hbar_a,hbar_w,hbar,R_bar=8.314472;
665 if (FlagUseIdealGasEnthalpyCorrelations)
667 hbar_w=2.7030251618E-03*T*T + 3.1994361015E+01*T + 3.6123174929E+04;
668 hbar_a=9.2486716590E-04*T*T + 2.8557221776E+01*T - 7.8616129429E+03;
676 hbar=hbar_0+(1-psi_w)*hbar_a+psi_w*hbar_w+R_bar*T*((B_m(T,psi_w)-T*dB_m_dT(T,psi_w))/v_bar+(C_m(T,psi_w)-T/2.0*dC_m_dT(T,psi_w))/(v_bar*v_bar));
684 double M_ha = MM_Water()*psi_w+(1-psi_w)*28.966;
685 return h_bar*(1+W)/M_ha;
696 double x1=0,x2=0,x3=0,y1=0,y2=0,eps=1e-8,f=999,R_bar_Lem=8.314510;
698 double sbar_0,sbar_a=0,sbar_w=0,sbar,R_bar=8.314472,vbar_a_guess, Baa, Caaa,vbar_a=0;
699 double B,dBdT,C,dCdT;
701 sbar_0=0.02366427495;
707 dBdT = dB_m_dT(T,psi_w);
710 dCdT = dC_m_dT(T,psi_w);
712 vbar_a_guess = R_bar_Lem*T/p;
714 while ((iter<=3 || fabs(f)>eps) && iter<100)
716 if (iter==1){x1=vbar_a_guess; vbar_a=x1;}
717 if (iter==2){x2=vbar_a_guess+0.001; vbar_a=x2;}
718 if (iter>2) {vbar_a=x2;}
719 f=R_bar_Lem*T/vbar_a*(1+Baa/vbar_a+Caaa/pow(vbar_a,2))-p;
724 x3=x2-y2/(y2-y1)*(x2-x1);
728 if (iter>100){
return _HUGE; }
731 if (FlagUseIdealGasEnthalpyCorrelations)
733 std::cout <<
"Not implemented" << std::endl;
742 sbar=sbar_0+(1-psi_w)*sbar_a+psi_w*sbar_w-R_bar*(
743 (B+T*dBdT)/v_bar+(C+T*dCdT)/(2*pow(v_bar,2))+
744 (1-psi_w)*log(1-psi_w)+psi_w*log(psi_w));
755 double p_w,eps,resid,Tdp=0,x1=0,x2=0,x3,y1=0,y2,T0;
773 if (p_w > 0.6116547241637944){
774 T0 =
Props(
"T",
"P",p_w,
"Q",1.0,
"Water");
782 iter=1; eps=1e-8; resid=999;
783 while ((iter<=3 || fabs(resid)>eps) && iter<100)
785 if (iter==1){x1 = T0; Tdp=x1;}
786 if (iter==2){x2 = x1 + 0.1; Tdp=x2;}
787 if (iter>2) {Tdp=x2;}
792 p_ws_dp=
Props(
"P",
"T",Tdp,
"Q",0,
"Water");
802 resid=p_w-p_ws_dp*f_dp;
804 if (iter==1){y1=resid;}
808 x3=x2-y2/(y2-y1)*(x2-x1);
819 double _T,_p,_W,LHS,v_bar_w,M_ha;
824 _W = epsilon*psi_w/(1-psi_w);
828 M_ha = MM_Water()*psi_w+(1-psi_w)*28.966;
834 double epsilon=0.621945;
835 double f_wb,p_ws_wb,p_s_wb,W_s_wb,h_w,M_ha_wb,psi_wb,v_bar_wb;
842 p_ws_wb=
Props(
"P",
"T",Twb,
"Q",0,
"Water");
851 p_s_wb = f_wb*p_ws_wb;
853 W_s_wb = epsilon*p_s_wb/(_p-p_s_wb);
855 psi_wb = W_s_wb/(epsilon+W_s_wb);
859 h_w=
Props(
"H",
"T",Twb,
"P",_p,
"Water");
864 h_w=
h_Ice(Twb,_p)/1000;
868 M_ha_wb=MM_Water()*psi_wb+(1-psi_wb)*28.966;
870 double RHS = (
MolarEnthalpy(Twb,_p,psi_wb,v_bar_wb)*(1+W_s_wb)/M_ha_wb+(_W-W_s_wb)*h_w);
907 double Tsat =
Props(
"T",
"P",p,
"Q",1.0,
"Water");
920 return_val =
Secant(&WBS,Tmax,0.0001,1e-8,50,&errstr);
925 catch(std::exception &)
935 double Tmin =
Brent(&WBTS,210,Tsat-1,1e-12,1e-12,50,&errstr);
937 return_val =
Brent(&WBS,Tmin-30,Tmax-1,1e-12,1e-12,50,&errstr);
939 catch(std::exception)
946 static int Name2Type(
const char *Name)
948 if (!strcmp(Name,
"Omega") || !strcmp(Name,
"HumRat") || !strcmp(Name,
"W"))
950 else if (!strcmp(Name,
"Tdp") || !strcmp(Name,
"T_dp") || !strcmp(Name,
"DewPoint") || !strcmp(Name,
"D"))
952 else if (!strcmp(Name,
"Twb") || !strcmp(Name,
"T_wb") || !strcmp(Name,
"WetBulb") || !strcmp(Name,
"B"))
954 else if (!strcmp(Name,
"Enthalpy") || !strcmp(Name,
"H"))
956 else if (!strcmp(Name,
"RH") || !strcmp(Name,
"RelHum") || !strcmp(Name,
"R"))
958 else if (!strcmp(Name,
"Tdb") || !strcmp(Name,
"T_db") || !strcmp(Name,
"T"))
960 else if (!strcmp(Name,
"P"))
962 else if (!strcmp(Name,
"V") || !strcmp(Name,
"Vda"))
964 else if (!strcmp(Name,
"mu") || !strcmp(Name,
"Visc") || !strcmp(Name,
"M"))
966 else if (!strcmp(Name,
"k") || !strcmp(Name,
"Conductivity") || !strcmp(Name,
"K"))
969 printf(
"Sorry, your input [%s] was not understood to Name2Type in HumAir.c. Acceptable values are T,P,R,W,D,B,H,M,K and aliases thereof\n",Name);
972 int TypeMatch(
int TypeCode,
const char *Input1Name,
const char *Input2Name,
const char *Input3Name)
975 if (TypeCode==Name2Type(Input1Name))
977 if (TypeCode==Name2Type(Input2Name))
979 if (TypeCode==Name2Type(Input3Name))
986 double p_ws,f,W,epsilon=0.621945,Tdp,p_ws_dp,f_dp,p_w_dp,p_s,RH;
991 return W/(epsilon+W);
998 p_ws=
Props(
"P",
"T",T,
"Q",0,
"Water");
1012 W=epsilon*RH*p_s/(p-RH*p_s);
1013 return W/(epsilon+W);
1021 p_ws_dp=
Props(
"P",
"T",Tdp,
"Q",0,
"Water");
1031 p_w_dp=f_dp*p_ws_dp;
1043 double p_ws,f,p_s,W;
1047 p_ws=
Props(
"P",
"T",T,
"Q",0,
"Water");
1063 return W/epsilon*p/(p_s*(1+W/epsilon));
1065 EXPORT_CODE double CONVENTION HAProps(
const char *OutputName,
const char *Input1Name,
double Input1,
const char *Input2Name,
double Input2,
const char *Input3Name,
double Input3)
1069 int In1Type, In2Type, In3Type,
iT,iW,iTdp,iRH,ip,Type1,Type2;
1070 double vals[3],p,T,RH,W,Tdp,psi_w,M_ha,v_bar,h_bar,s_bar,MainInputValue,SecondaryInputValue,T_guess;
1071 double Value1,Value2,W_guess;
1072 char MainInputName[100], SecondaryInputName[100],Name1[100],Name2[100];
1079 In1Type=Name2Type(Input1Name);
1080 In2Type=Name2Type(Input2Name);
1081 In3Type=Name2Type(Input3Name);
1123 strcpy(SecondaryInputName,Input1Name);
1124 SecondaryInputValue=Input1;
1128 strcpy(SecondaryInputName,Input2Name);
1129 SecondaryInputValue=Input2;
1133 strcpy(SecondaryInputName,Input3Name);
1134 SecondaryInputValue=Input3;
1141 W=Secant_HAProps_W(SecondaryInputName,
"P",p,
"T",T,SecondaryInputValue,W_guess);
1158 strcpy(Name1,Input2Name);
1160 strcpy(Name2,Input3Name);
1165 strcpy(Name1,Input1Name);
1167 strcpy(Name2,Input3Name);
1172 strcpy(Name1,Input1Name);
1174 strcpy(Name2,Input2Name);
1182 Type1=Name2Type(Name1);
1183 Type2=Name2Type(Name2);
1192 MainInputValue=Value1;
1193 strcpy(MainInputName,Name1);
1195 SecondaryInputValue=Value2;
1196 strcpy(SecondaryInputName,Name2);
1203 MainInputValue=Value2;
1204 strcpy(MainInputName,Name2);
1206 SecondaryInputValue=Value1;
1207 strcpy(SecondaryInputName,Name1);
1211 printf(
"Sorry, but currently at least one of the variables as an input to HAProps() must be temperature, relative humidity, humidity ratio, or dewpoint\n Eventually will add a 2-D NR solver to find T and psi_w simultaneously, but not included now\n");
1221 for (T_guess = 210; T_guess < 450; T_guess += 60)
1224 T = Secant_HAProps_T(SecondaryInputName,(
char *)
"P",p,MainInputName,MainInputValue,SecondaryInputValue,T_guess);
1225 double val =
HAProps(SecondaryInputName,(
char *)
"T",T,(
char *)
"P",p,MainInputName,MainInputValue);
1226 if (!
ValidNumber(T) || !
ValidNumber(val) || !(T_min < T && T < T_max) || fabs(val-SecondaryInputValue)>1e-6)
1235 catch (std::exception &){};
1241 T = Brent_HAProps_T(SecondaryInputName,(
char *)
"P",p,MainInputName,MainInputValue,SecondaryInputValue,T_min,T_max);
1245 if (Name2Type(OutputName)==
GIVEN_T)
1250 W=
HAProps((
char *)
"W",(
char *)
"T",T,(
char *)
"P",p,MainInputName,MainInputValue);
1254 M_ha=(1-psi_w)*28.966+MM_Water()*psi_w;
1259 if (!strcmp(OutputName,
"Vda") || !strcmp(OutputName,
"V"))
1263 return v_bar*(1+W)/M_ha*1000;
1265 else if (!strcmp(OutputName,
"Vha"))
1268 return v_bar/M_ha*1000;
1270 else if (!strcmp(OutputName,
"Y"))
1274 else if (!strcmp(OutputName,
"Hda") || !strcmp(OutputName,
"H"))
1278 else if (!strcmp(OutputName,
"Hha"))
1284 else if (!strcmp(OutputName,
"S") || !strcmp(OutputName,
"Entropy"))
1289 return s_bar*(1+W)/M_ha;
1291 else if (!strcmp(OutputName,
"C") || !strcmp(OutputName,
"cp"))
1293 double v_bar1,v_bar2,h_bar1,h_bar2, cp_bar, dT = 1e-3;
1299 cp_bar = (h_bar2-h_bar1)/(2*dT);
1300 return cp_bar*(1+W)/M_ha;
1302 else if (!strcmp(OutputName,
"Cha") || !strcmp(OutputName,
"cp_ha"))
1304 double v_bar1,v_bar2,h_bar1,h_bar2, cp_bar, dT = 1e-3;
1310 cp_bar = (h_bar2-h_bar1)/(2*dT);
1313 else if (!strcmp(OutputName,
"Tdp") || !strcmp(OutputName,
"D"))
1317 else if (!strcmp(OutputName,
"Twb") || !strcmp(OutputName,
"T_wb") || !strcmp(OutputName,
"WetBulb") || !strcmp(OutputName,
"B"))
1321 else if (!strcmp(OutputName,
"Omega") || !strcmp(OutputName,
"HumRat") || !strcmp(OutputName,
"W"))
1325 else if (!strcmp(OutputName,
"RH") || !strcmp(OutputName,
"RelHum") || !strcmp(OutputName,
"R"))
1329 else if (!strcmp(OutputName,
"mu") || !strcmp(OutputName,
"Visc") || !strcmp(OutputName,
"M"))
1333 else if (!strcmp(OutputName,
"k") || !strcmp(OutputName,
"Conductivity") || !strcmp(OutputName,
"K"))
1342 catch (std::exception &e)
1360 double psi_w,Tj,tau_Water,tau_Air,B_aa,C_aaa,B_ww,C_www,B_aw,C_aaw,C_aww,v_bar,delta, tau;
1367 if (!strcmp(Name,
"Baa"))
1369 B_aa=B_Air(T)*MM_Air()/1e3;
1370 strcpy(units,
"m^3/mol");
1373 else if (!strcmp(Name,
"Caaa"))
1375 C_aaa=C_Air(T)*MM_Air()*MM_Air()/1e6;
1376 strcpy(units,
"m^6/mol^2");
1379 else if (!strcmp(Name,
"Bww"))
1381 B_ww=B_Water(T)*MM_Water()/1e3;
1382 strcpy(units,
"m^3/mol");
1385 else if (!strcmp(Name,
"Cwww"))
1387 C_www=C_Water(T)*MM_Water()*MM_Water()/1e6;
1388 strcpy(units,
"m^6/mol^2");
1391 else if (!strcmp(Name,
"dBaa"))
1393 B_aa=dBdT_Air(T)*MM_Air()/1e3;
1394 strcpy(units,
"m^3/mol");
1397 else if (!strcmp(Name,
"dCaaa"))
1399 C_aaa=dCdT_Air(T)*MM_Air()*MM_Air()/1e6;
1400 strcpy(units,
"m^6/mol^2");
1403 else if (!strcmp(Name,
"dBww"))
1405 B_ww=dBdT_Water(T)*MM_Water()/1e3;
1406 strcpy(units,
"m^3/mol");
1409 else if (!strcmp(Name,
"dCwww"))
1411 C_www=dCdT_Water(T)*MM_Water()*MM_Water()/1e6;
1412 strcpy(units,
"m^6/mol^2");
1415 else if (!strcmp(Name,
"Baw"))
1418 strcpy(units,
"m^3/mol");
1421 else if (!strcmp(Name,
"Caww"))
1423 C_aww=_C_aww(T)/1e6;
1424 strcpy(units,
"m^6/mol^2");
1427 else if (!strcmp(Name,
"Caaw"))
1429 C_aaw=_C_aaw(T)/1e6;
1430 strcpy(units,
"m^6/mol^2");
1433 else if (!strcmp(Name,
"dBaw"))
1435 double dB_aw=_dB_aw_dT(T)/1e3;
1436 strcpy(units,
"m^3/mol");
1439 else if (!strcmp(Name,
"dCaww"))
1441 double dC_aww=_dC_aww_dT(T)/1e6;
1442 strcpy(units,
"m^6/mol^2");
1445 else if (!strcmp(Name,
"dCaaw"))
1447 double dC_aaw=_dC_aaw_dT(T)/1e6;
1448 strcpy(units,
"m^6/mol^2");
1451 else if (!strcmp(Name,
"beta_H"))
1453 strcpy(units,
"1/Pa");
1454 return HenryConstant(T);
1456 else if (!strcmp(Name,
"kT"))
1458 strcpy(units,
"1/Pa");
1461 double rho =
Props(
"D",
"T",T,
"P",p,
"Water");
1462 return DerivTerms((
char *)
"IsothermalCompressibility",T,rho,(
char *)
"Water")/1000;
1467 else if (!strcmp(Name,
"p_ws"))
1469 strcpy(units,
"kPa");
1471 return Props(
"P",
"T",T,
"Q",0,
"Water");
1475 else if (!strcmp(Name,
"vbar_ws"))
1477 strcpy(units,
"m^3/mol");
1481 return 1.0/
Props(
"D",
"T",T,
"Q",0,
"Water")*MM_Water()/1000;
1486 return dg_dp_Ice(T,p/1000)*MM_Water()/1000/1000;
1489 else if (!strcmp(Name,
"f"))
1496 if (!strcmp(Name,
"Bm"))
1498 strcpy(units,
"m^3/mol");
1499 return B_m(T,psi_w);
1501 else if (!strcmp(Name,
"Cm"))
1503 strcpy(units,
"m^6/mol^2");
1504 return C_m(T,psi_w);
1506 else if (!strcmp(Name,
"hvirial"))
1509 return 8.3145*T*((B_m(T,psi_w)-T*dB_m_dT(T,psi_w))/v_bar+(C_m(T,psi_w)-T/2.0*dC_m_dT(T,psi_w))/(v_bar*v_bar));
1511 else if (!strcmp(Name,
"ha"))
1513 delta=1.1/322; tau=132/T;
1514 return 1+tau*
DerivTerms((
char *)
"dphi0_dTau",tau,delta,(
char *)
"Water");
1516 else if (!strcmp(Name,
"hw"))
1519 delta=1000/322; tau=647/T;
1521 return 1+tau*
DerivTerms((
char *)
"dphi0_dTau",tau,delta,(
char *)
"Water");
1523 else if (!strcmp(Name,
"hbaro_w"))
1528 else if (!strcmp(Name,
"hbaro_a"))
1535 printf(
"Sorry I didn't understand your input [%s] to HAProps_Aux\n",Name);
1539 catch(std::exception &)
1552 return 2.14627073E+03-3.28917768E+01*T+1.89471075E-01*T*T-4.86290986E-04*T*T*T+4.69540143E-07*T*T*T*T;
1557 if (!strcmp(Name,
"s"))
1559 return s_Ice(T,p*1000.0);
1561 else if (!strcmp(Name,
"rho"))
1565 else if (!strcmp(Name,
"h"))
1567 return h_Ice(T,p*1000.0);
1576 #ifndef DISABLE_CATCH
1579 TEST_CASE((
char*)
"Tests from ASHRAE RP-1485",(
char*)
"[RP1485]")
1583 double p1 = 101.325, T= 473.15;
1585 std::string rows1[] ={
"0.00 45.07 1.341 202.52 0.5558",
1586 "0.05 55.38 1.448 346.49 1.0299",
1587 "0.10 61.85 1.556 490.43 1.4736",
1588 "0.20 69.95 1.771 778.24 2.3336",
1589 "0.30 75.00 1.986 1066.00 3.1751",
1590 "0.40 78.51 2.201 1353.71 4.0059",
1591 "0.50 81.12 2.416 1641.40 4.8295",
1592 "0.60 83.14 2.630 1929.06 5.6479",
1593 "0.70 84.76 2.845 2216.70 6.4623",
1594 "0.80 86.09 3.060 2504.32 7.2736",
1595 "0.90 87.20 3.274 2791.94 8.0824",
1596 "1.00 88.15 3.489 3079.55 8.8890"};
1597 for (
int i = 0; i < 12; i++)
1599 std::vector<std::string> elements =
strsplit(rows1[i],
' ');
1600 double W = strtod(elements[0].c_str(),NULL);
1603 double B = strtod(elements[1].c_str(),NULL);
1604 double BCP =
HAProps(
"B",
"T",T,
"W",W,
"P",p1) - 273.15;
1607 CHECK(fabs(BCP-B) < 0.01);
1611 double V = strtod(elements[2].c_str(),NULL);
1612 double VCP =
HAProps(
"V",
"T",T,
"W",W,
"P",p1);
1615 CHECK(fabs(VCP-V) < 0.01);
1619 double H = strtod(elements[3].c_str(),NULL);
1620 double HCP =
HAProps(
"H",
"T",T,
"W",W,
"P",p1);
1623 CHECK(fabs(HCP-H) < 0.01);
1627 double S = strtod(elements[4].c_str(),NULL);
1628 double SCP =
HAProps(
"S",
"T",T,
"W",W,
"P",p1);
1631 CHECK(fabs(SCP-S) < 0.01);
double MolarEntropy(double T, double p, double psi_w, double v_bar)
double f_factor(double T, double p)
double h_Ice(double T, double p)
void UseVirialCorrelations(int flag)
double WetbulbTemperature(double T, double p, double psi_w)
EXPORT_CODE double CONVENTION HAProps(const char *OutputName, const char *Input1Name, double Input1, const char *Input2Name, double Input2, const char *Input3Name, double Input3)
double IdealGasMolarEnthalpy_Air(double T, double v_bar)
int TypeMatch(int TypeCode, const char *Input1Name, const char *Input2Name, const char *Input3Name)
int returnHumAirCode(const char *Code)
void UseIdealGasEnthalpyCorrelations(int flag)
virtual double phi0(double tau, double delta)
double rho_Ice(double T, double p)
double Props(std::string Output, std::string Name1, double Prop1, std::string Name2, double Prop2, std::string Ref)
double Props1(std::string FluidName, std::string Output)
WetBulbSolver(double T, double p, double psi_w)
virtual double dphi0_dTau(double tau, double delta)
struct CriticalStruct reduce
A pointer to the point that is used to reduce the T and rho for EOS.
double IdealGasMolarEntropy_Air(double T, double v_bar_a)
double RelativeHumidity(double T, double p, double psi_w)
double IdealGasMolarEnthalpy_Water(double T, double v_bar)
void UseIsothermCompressCorrelation(int flag)
double PropsSI(std::string Output, std::string Name1, double Prop1, std::string Name2, double Prop2, std::string Ref)
virtual double call(double)=0
double IdealGasMolarEntropy_Water(double T, double p)
WetBulbTminSolver(double p, double hair_dry)
double MoleFractionWater(double T, double p, int HumInput, double InVal)
double cair_sat(double T)
TEST_CASE((char *)"Tests from ASHRAE RP-1485",(char *)"[RP1485]")
struct OtherParameters params
double MolarEnthalpy(double T, double p, double psi_w, double v_bar)
double IceProps(const char *Name, double T, double p)
double Brent(FuncWrapper1D *f, double a, double b, double macheps, double t, int maxiter, std::string *errstr)
struct CriticalStruct crit
EXPORT_CODE double CONVENTION HAProps_Aux(const char *Name, double T, double p, double W, char *units)
double HumidityRatio(double psi_w)
double Viscosity(double T, double p, double psi_w)
double Conductivity(double T, double p, double psi_w)
double DerivTerms(long iTerm, double T, double rho, Fluid *pFluid)
double IsothermCompress_Ice(double T, double p)
double psub_Ice(double T)
double Secant(FuncWrapper1D *f, double x0, double dx, double tol, int maxiter, std::string *errstring)
double dg_dp_Ice(double T, double p)
void set_err_string(std::string error_string)
#define SECTION(name, description)
double MolarVolume(double T, double p, double psi_w)
double DewpointTemperature(double T, double p, double psi_w)
double MassEnthalpy(double T, double p, double psi_w)
double s_Ice(double T, double p)