1 #define _CRT_SECURE_NO_WARNINGS
32 #define _USE_MATH_DEFINES
37 #define DBL_EPSILON std::numeric_limits<double>::epsilon()
42 #define M_PI 3.14159265358979323846
45 static const bool use_cache =
false;
46 static bool UseCriticalSpline =
true;
51 if (root.
HasMember(FluidName.c_str()) && root[FluidName.c_str()][key.c_str()].
IsDouble()){
52 return root[FluidName.c_str()][key.c_str()].
GetDouble();
54 else if (root.
HasMember(FluidName.c_str()) && root[FluidName.c_str()][key.c_str()].
IsInt()){
55 return root[FluidName.c_str()][key.c_str()].
GetInt();
64 if (root.
HasMember(FluidName.c_str()) && root[FluidName.c_str()][key.c_str()].
IsString()){
65 return root[FluidName.c_str()][key.c_str()].
GetString();
75 return root[FluidName.c_str()].
GetString();
84 std::vector<double> v;
86 if (root.
HasMember(FluidName.c_str()) && root[FluidName.c_str()][key.c_str()].
IsArray()){
105 if (root.
HasMember(FluidName.c_str()) && root[FluidName.c_str()][key.c_str()].
IsArray()){
107 v.resize(arr.
Size());
185 double pL,pV,rhoL,rhoV;
228 if (!
params.HSReferenceState.empty())
246 for (std::vector<phi_BC*>::iterator it =
phirlist.begin(); it !=
phirlist.end(); it++)
247 summer += (*it)->base(tau,delta);
266 for (std::vector<phi_BC*>::iterator it =
phirlist.begin(); it !=
phirlist.end(); ++it)
268 summer += (*it)->dDelta(tau,delta);
285 for (std::vector<phi_BC*>::iterator it =
phirlist.begin(); it !=
phirlist.end(); it++)
287 summer += (*it)->dDelta2(tau,delta);
304 for (std::vector<phi_BC*>::iterator it =
phirlist.begin(); it !=
phirlist.end(); it++)
305 summer += (*it)->dTau(tau,delta);
321 for (std::vector<phi_BC*>::iterator it =
phirlist.begin(); it !=
phirlist.end(); it++)
322 summer += (*it)->dTau2(tau,delta);
338 for (std::vector<phi_BC*>::iterator it =
phirlist.begin(); it !=
phirlist.end(); it++)
339 summer += (*it)->dDelta_dTau(tau,delta);
349 for (std::vector<phi_BC*>::iterator it =
phirlist.begin(); it !=
phirlist.end(); it++)
350 summer += (*it)->dTau3(tau,delta);
356 for (std::vector<phi_BC*>::iterator it =
phirlist.begin(); it !=
phirlist.end(); it++)
358 summer += (*it)->dDelta3(tau,delta);
365 for (std::vector<phi_BC*>::iterator it =
phirlist.begin(); it !=
phirlist.end(); it++)
366 summer += (*it)->dDelta_dTau2(tau,delta);
373 for (std::vector<phi_BC*>::iterator it =
phirlist.begin(); it !=
phirlist.end(); it++)
374 summer += (*it)->dDelta2_dTau(tau,delta);
384 for (std::vector<phi_BC*>::iterator it =
phi0list.begin(); it !=
phi0list.end(); it++){
385 summer += (*it)->base(tau,delta);
392 for (std::vector<phi_BC*>::iterator it =
phi0list.begin(); it !=
phi0list.end(); it++)
393 summer += (*it)->dDelta(tau,delta);
399 for (std::vector<phi_BC*>::iterator it =
phi0list.begin(); it !=
phi0list.end(); it++)
400 summer += (*it)->dDelta2(tau,delta);
406 for (std::vector<phi_BC*>::iterator it =
phi0list.begin(); it !=
phi0list.end(); it++){
407 summer += (*it)->dTau(tau,delta);
414 for (std::vector<phi_BC*>::iterator it =
phi0list.begin(); it !=
phi0list.end(); it++){
415 summer += (*it)->dTau2(tau,delta);
422 for (std::vector<phi_BC*>::iterator it =
phi0list.begin(); it !=
phi0list.end(); it++){
423 summer += (*it)->dTau3(tau,delta);
430 for (std::vector<phi_BC*>::iterator it =
phi0list.begin(); it !=
phi0list.end(); it++)
431 summer += (*it)->dDelta_dTau(tau,delta);
438 for (std::vector<std::string>::iterator it =
aliases.begin(); it !=
aliases.end(); it++)
439 if (name.compare((*it))==0)
489 double delta,tau,c1,c2,dphir_dDelta_;
494 c2=(1.0+2.0*delta*dphir_dDelta_+pow(delta,2)*
d2phir_dDelta2(tau,delta));
505 double delta,tau,c1,c2;
545 double omega,
R, m, a, b, A, B, r, q, D, u, Y, Y1, Y2, Y3, theta, phi, rho;
546 omega =
params.accentricfactor;
548 m = 0.480+1.574*omega-0.176*omega*omega;
555 r = (3*(A-B-B*B)-1)/3;
556 q = -2/27.0+1.0/3.0*(A-B-B*B)-A*B;
559 D = pow(r/3,3)+pow(q/2,2);
564 u = pow(-q/2+sqrt(D),1.0/3.0);
566 rho = p/(R*T*(Y+1.0/3.0));
571 theta = sqrt(-r*r*r/27);
572 phi = acos(-q/(2*theta));
574 Y1 = 2*pow(theta,1.0/3.0)*cos(phi/3.0);
575 Y2 = 2*pow(theta,1.0/3.0)*cos(phi/3.0+2.0*
M_PI/3.0);
576 Y3 = 2*pow(theta,1.0/3.0)*cos(phi/3.0+4.0*
M_PI/3.0);
578 double rho1 = p/(R*T*(Y1+1.0/3.0));
579 double rho2 = p/(R*T*(Y2+1.0/3.0));
580 double rho3 = p/(R*T*(Y3+1.0/3.0));
586 double min_error = 9e50;
588 if (
ValidNumber(p1) && fabs(p1-p) < min_error){min_error = fabs(p1-p); rho = rho1;}
589 if (
ValidNumber(p2) && fabs(p2-p) < min_error){min_error = fabs(p2-p); rho = rho2;}
590 if (
ValidNumber(p3) && fabs(p3-p) < min_error){min_error = fabs(p3-p); rho = rho3;}
598 else if (iValue == 1)
609 double A, B, m, a, b, Z, rhobar;
611 double Rbar = 8314.472;
616 m = 0.37464 + 1.54226*
params.accentricfactor-0.26992*pow(
params.accentricfactor,2);
618 A = a*p/(Rbar*Rbar*T*T)/1000;
621 solve_cubic(1, -1+B, A-3*B*B-2*B, -A*B+B*B+B*B*B, &x0, &x1, &x2);
622 std::vector<double> solns;
629 for (
int i = (
int)solns.size()-1; i >= 0; i--)
633 solns.erase(solns.begin()+i);
648 Z = *std::min_element(solns.begin(), solns.end());
650 else if (solution == 1)
652 Z = *std::max_element(solns.begin(), solns.end());
659 rhobar = p/(Z*Rbar*T);
663 return rhobar*
params.molemass;
689 double omega,
R, kappa, a, b, A, B, C, D, V= 1/rho;
690 omega =
params.accentricfactor;
693 kappa = 0.37464+1.54226*omega-0.26992*omega*omega;
696 double den = V*V+2*b*V-b*b;
699 A = R*
reduce.
T/(V-b)-a*kappa*kappa/(den);
700 B = +2*a*kappa*(1+kappa)/(den);
701 C = -a*(1+2*kappa+kappa*kappa)/(den)-p;
705 double sqrt_Tr1 = (-B+sqrt(B*B-4*A*C))/(2*A);
707 return sqrt_Tr1*sqrt_Tr1*
reduce.
T;
715 double Vm = 1/rho*
params.molemass;
716 return 1.0/R*(p+a/Vm/Vm)*(Vm-b);
724 std::cout <<
format(
"%s:%d: Fluid::density_Tp(double T, double p)\n", __FILE__, __LINE__, T, p).c_str();
735 long double tau,dpdrho__constT,dpddelta__constT, error=999,
R,p_EOS,rho,change=999;
741 std::cout <<
format(
"%s:%d: Fluid::density_Tp(T=%g, p=%g, rho_guess=%g)\n",__FILE__,__LINE__,T,p,rho_guess).c_str();
750 while (std::abs(error) > 1e-9 && std::abs(change) > 1e-13)
757 p_EOS =
reduce.
rho*delta*
R*T*(1+delta*dphirdDelta);
763 dpdrho__constT =
R*T*(1+2*delta*dphirdDelta+delta*delta*
d2phir_dDelta2(tau,delta));
765 dpddelta__constT = dpdrho__constT*
reduce.
rho;
768 change = (p_EOS-p)/dpddelta__constT;
775 throw SolutionError(
format(
"Number of steps in density_TP has exceeded 30 with inputs T=%g,p=%g,rho_guess=%g for fluid %s",T,p,rho_guess,
name.c_str()));
779 throw SolutionError(
format(
"Non-numeric density obtained in density_TP with inputs T=%g,p=%g,rho_guess=%g for fluid %s",T,p,rho_guess,
name.c_str()));
783 std::cout <<
format(
"%s:%d: Fluid::density_Tp(T = %g, p = %g, rho_guess = %g) = %g\n",__FILE__,__LINE__,T,p,rho_guess,rho).c_str();
803 void Fluid::saturation_s(
double s,
int Q,
double &Tsatout,
double &rhoout,
double &TLout,
double &TVout,
double &rhoLout,
double &rhoVout)
812 double rho,pL,pV,rhoL,rhoV,T;
813 SatFuncClass(
double s,
int Q,
Fluid *pFluid){
816 this->pFluid = pFluid;
818 double call(
double T){
834 } SatFunc(s, Q,
this);
837 std::cout <<
format(
"%s:%d: Fluid::saturation_s(%g,%d) \n",__FILE__,__LINE__,s,Q).c_str();
850 rhoout = SatFunc.rho;
851 rhoLout = SatFunc.rhoL;
852 rhoVout = SatFunc.rhoV;
875 void Fluid::saturation_h(
double h,
double Tmin,
double Tmax,
int Q,
double &Tsatout,
double &rhoout,
double &TsatLout,
double &TsatVout,
double &rhoLout,
double &rhoVout)
884 double rho,pL,pV,rhoL,rhoV,T;
885 SatFuncClass(
double h,
int Q,
Fluid *pFluid){
888 this->pFluid = pFluid;
890 double call(
double T){
906 } SatFunc(h, Q,
this);
909 std::cout <<
format(
"%s:%d: Fluid::saturation_h(%g,%d) \n",__FILE__,__LINE__,h,Q).c_str();
921 Tsatout =
Brent(&SatFunc,Tmin,Tmax,1e-16,1e-10,100,&errstr);
922 rhoout = SatFunc.rho;
923 rhoLout = SatFunc.rhoL;
924 rhoVout = SatFunc.rhoV;
925 TsatLout = SatFunc.T;
926 TsatVout = SatFunc.T;
948 void Fluid::saturation_T(
double T,
bool UseLUT,
double &psatLout,
double &psatVout,
double &rhosatLout,
double &rhosatVout)
952 std::cout <<
format(
"%s:%d: Fluid::saturation_T(%g,%d) \n",__FILE__,__LINE__,T,UseLUT).c_str();
980 rhosatPure_Akasaka(T, rhosatLout, rhosatVout, p, omega); psatLout = p; psatVout = p;
return;
983 catch (std::exception &)
996 catch(std::exception &)
1005 rhosatPure(T, rhosatLout, rhosatVout, p, omega,
false);
1010 catch (std::exception &)
1023 catch (std::exception &){
1036 psatLout =
psatL(T);
1037 psatVout =
psatV(T);
1049 fabs(rhoLanc/rhosatLout-1) > 0.1 || fabs(rhoVanc/rhosatVout-1) > 0.1)
1054 catch (std::exception &){
1077 SatFuncClass(
double T,
Fluid *pFluid) :T(T), pFluid(pFluid){};
1078 double call(
double p){
1099 catch (std::exception &)
1103 if (pmin <
params.ptriple)
1152 long double rhoL,rhoV,dphirL,dphirV,ddphirL,ddphirV,phirL,phirV,JL,JV,KL,KV,dJL,dJV,dKL,dKV;
1153 long double DELTA, deltaL=0, deltaV=0, tau=0, error, PL, PV, stepL, stepV;
1186 double w = 6.67228479e-09*Tc*Tc*Tc-7.20464352e-06*Tc*Tc+3.16947758e-03*Tc-2.88760012e-01;
1187 double q = -6.08930221451*w -5.42477887222;
1188 double pt = exp(q*(Tc/T-1))*pc;
1197 std::cout <<
format(
"%s:%d: Akasaka guess values deltaL = %g deltaV = %g tau = %g\n",__FILE__,__LINE__,deltaL, deltaV, tau).c_str();
1202 std::cout <<
format(
"%s:%d: right before the derivs with deltaL = %g deltaV = %g tau = %g\n",__FILE__,__LINE__,deltaL, deltaV, tau).c_str();
1209 phirL =
phir(tau,deltaL);
1210 phirV =
phir(tau,deltaV);
1212 JL = deltaL * (1 + deltaL*dphirL);
1213 JV = deltaV * (1 + deltaV*dphirV);
1214 KL = deltaL*dphirL + phirL + log(deltaL);
1215 KV = deltaV*dphirV + phirV + log(deltaV);
1221 dJL = 1 + 2*deltaL*dphirL + deltaL*deltaL*ddphirL;
1222 dJV = 1 + 2*deltaV*dphirV + deltaV*deltaV*ddphirV;
1223 dKL = 2*dphirL + deltaL*ddphirL + 1/deltaL;
1224 dKV = 2*dphirV + deltaV*ddphirV + 1/deltaV;
1226 DELTA = dJV*dKL-dJL*dKV;
1228 error = std::abs(KL-KV)+std::abs(JL-JV);
1231 stepL = omega/DELTA*( (KV-KL)*dJV-(JV-JL)*dKV);
1232 stepV = omega/DELTA*( (KV-KL)*dJL-(JV-JL)*dKL);
1234 if (deltaL+stepL > 1 && deltaV+stepV < 1 && deltaV+stepV > 0)
1249 while (error > 1e-10 && std::abs(stepL) > 10*
DBL_EPSILON*std::abs(stepL) && std::abs(stepV) > 10*
DBL_EPSILON*std::abs(stepV));
1265 resid(
double Tr){this->Tr = Tr;};
1266 double call(
double s)
1268 double w = sqrt(s*s-32*Tr/s+36-12*s);
1269 double val = log((s*(6-s)-(16*Tr/3)+s*w)/(s*(6-s)-(16*Tr/3)-s*w))-3*(6-s)*w/8*Tr;
1273 resid r(T/this->
crit.
T);
1282 double s =
Secant(&r,s0,0.01,1e-8,100,&errstr);
1285 void Fluid::rhosatPure(
double T,
double &rhoLout,
double &rhoVout,
double &pout,
double omega = 1.0,
bool use_guesses =
false)
1289 double rhoL,rhoV,p=_HUGE,error=999,x1=0,x2=0,x3,y1=0,y2,f,p_guess;
1314 while ((iter<=3 || fabs(error)>1e-6) && iter<100)
1316 if (iter==1){x1=p_guess; p=x1;}
1317 else if (iter==2){x2=1.000001*p_guess; p=x2;}
1328 x3=x2-omega*y2/(y2-y1)*(x2-x1);
1330 y1=y2; x1=x2; x2=x3;
1336 throw SolutionError(
format(
"rhosatPure failed, current values of rhoL and rhoV are %g,%g\n",rhoL,rhoV).c_str());
1346 if (x2>x1 && x>=x1 && x<=x2)
return true;
1347 else if (x1>x2 && x<=x1 && x>=x2)
return true;
1380 double Tc,rho_simple;
1385 double pL,pV,rhoL,rhoV;
1390 std::cout <<
format(
"%s:%d: Fluid::_get_rho_guess(%g,%g) phase = %d\n",__FILE__,__LINE__,T,p,phase).c_str();
1396 rho_simple = p/(
R()*T);
1409 std::cout<<
format(
"%s:%d: pL = %g rhoL = %g \n",__FILE__,__LINE__,pL,rhoL).c_str();
1414 double drho_dp = 1/dp_drho;
1415 if (drho_dp*(pL-p)> rhoL)
1421 rho_simple = rhoL-drho_dp*(pL-p);
1426 throw ValueError(
format(
"Input T [%0.16g] & p [%0.16g] are two-phase or saturated which is thermodynamically undefined\n",T,p));
1432 return (rhoL+rhoV)/2;
1435 std::cout <<
format(
"%s:%d: _get_rho_guess = %g\n",__FILE__,__LINE__,rho_simple).c_str();
1441 std::string
Fluid::phase_Tp(
double T,
double p,
double &pL,
double &pV,
double &rhoL,
double &rhoV)
1447 std::cout <<
format(
"%s:%d: phase_Tp() phase index is %d\n",iPhase).c_str();
1454 return std::string(
"Two-Phase");
1456 return std::string(
"Supercritical");
1458 return std::string(
"Gas");
1460 return std::string(
"Liquid");
1462 return std::string(
"");
1488 std::cout <<
format(
"%s:%d: phase_Tp_indices(%g,%g)\n",__FILE__,__LINE__,T,p).c_str();
1497 else if (T<crit.T && p>
crit.
p.
Pa){
1500 else if (p<
params.ptriple){
1539 std::string
Fluid::phase_Trho(
double T,
double rho,
double &pL,
double &pV,
double &rhoL,
double &rhoV)
1544 std::cout <<
format(
"%s:%d: phase index is %d\n",__FILE__,__LINE__,iPhase).c_str();
1551 return std::string(
"Two-Phase");
1553 return std::string(
"Supercritical");
1555 return std::string(
"Gas");
1557 return std::string(
"Liquid");
1559 return std::string(
"");
1599 else if (rho > 1.05*
rhosatL(T)){
1608 double Q = (1/rho-1/rhoL)/(1/rhoV-1/rhoL);
1632 else if (p<
params.ptriple){
1659 double Q = (1/rho-1/rhoL)/(1/rhoV-1/rhoL);
1663 else if (Q > 1+1e-10){
1685 double error, T, drdT, r;
1694 double pEOS = CPS.
p();
1699 error = fabs(r/pEOS);
1701 if (fabs(r/drdT) < 1e-12)
1707 throw SolutionError(
format(
"temperature_prho failed with inputs p=%g rho=%g T0=%g for fluid %s",p,rho,T0,
name.c_str()));
1709 while (error > 1e-10 );
1713 void Fluid::temperature_ph(
double p,
double h,
double &Tout,
double &rhoout,
double &rhoLout,
double &rhoVout,
double &TsatLout,
double &TsatVout,
double T0,
double rho0)
1716 bool failed =
false;
1717 double A[2][2], B[2][2],T_guess, omega = 1.0;
1718 double dar_ddelta,da0_dtau,d2a0_dtau2,dar_dtau,d2ar_ddelta_dtau,d2ar_ddelta2,d2ar_dtau2,d2a0_ddelta_dtau;
1719 double f1,f2,df1_dtau,df1_ddelta,df2_ddelta,df2_dtau;
1720 double rhoL, rhoV, hsatL,hsatV,TsatL,TsatV,tau,delta,worst_error;
1721 double h_guess, hc, rho_guess, T1, T2, h1, h2, rho1, rho2;
1722 double hsat_tol = 3000;
1726 if (T0 > 0 && rho0 > 0)
1740 T_guess =
crit.
T+30;
1742 T_guess = (
crit.
T-T_guess)/(hc-h_guess)*(h-h_guess)+T_guess;
1749 T_guess =
params.Ttriple;
1753 T_guess = (
crit.
T-T_guess)/(hc-h_guess)*(h-h_guess)+T_guess;
1760 else if (p <
params.ptriple)
1762 rho_guess =
params.rhoVtriple;
1763 T_guess =
params.ptriple;
1778 if (h>hsatV || h<hsatL)
1801 if (h > hsatV + hsat_tol)
1816 T_guess = (T2-T1)/(h2-h1)*(h-h1)+T1;
1817 rho_guess = (rho2-rho1)/(h2-h1)*(h-h1)+rho1;
1822 std::cout <<
format(
"%s:%d: temperature_ph; it is vapor(anc), hsatV = %g\n",__FILE__,__LINE__, hsatV) ;
1825 else if (h < hsatL - hsat_tol)
1832 T_guess = TsatL-(hsatL-h)/cp;
1837 T_guess =
params.Ttriple+1;
1841 T_guess = (TsatL-T_guess)/(hsatL-h_guess)*(h-h_guess)+T_guess;
1847 std::cout <<
format(
"%s:%d: temperature_ph; it is liquid(anc), hsatL = %g\n",__FILE__,__LINE__, hsatL) ;
1872 if (fabs((h-hsatL)/(hsatV-hsatL)) < 1e-8)
1878 else if (fabs((h-hsatL)/(hsatV-hsatL)-1) < 1e-8)
1899 T_guess = (T2-T1)/(h2-h1)*(h-h1)+T1;
1900 rho_guess = (rho2-rho1)/(h2-h1)*(h-h1)+rho1;
1905 std::cout <<
format(
"%s:%d: temperature_ph; it is vapor, hsatV = %g\n",__FILE__,__LINE__, hsatV) ;
1911 rho_guess = rhoLout;
1915 T_guess =
params.Ttriple;
1920 double Tmid = (T_guess + TsatL)/2.0;
1926 rho_guess = (rhoLout-rho_guess)/(hsatL-h_guess)*(h-h_guess) + rho_guess;
1927 T_guess = (TsatL-T_guess)/(hsatL-h_guess)*(h-h_guess) + T_guess;
1934 T_guess =
QuadInterp(h_guess, h_mid, hsatL, T_guess, Tmid, TsatL, h);
1935 rho_guess =
QuadInterp(h_guess, h_mid, hsatL, rho_guess, rho_mid, rhoL, h);
1938 catch(std::exception &)
1941 rho_guess = rhoLout;
1946 std::cout <<
format(
"%s:%d: temperature_ph; it is liquid, hsatL = %g, T = %g, rho = %g\n",__FILE__,__LINE__, hsatL, T_guess, rho_guess) ;
1954 double quality = (h-hsatL)/(hsatV-hsatL);
1955 Tout = quality*TsatV+(1-quality)*TsatL;
1956 double v = quality*(1/rhoV)+(1-quality)*1/rhoL;
1959 std::cout <<
format(
"%s:%d: temperature_ph; it is 2phase,Q = %g\n",__FILE__,__LINE__, quality) ;
1972 std::cout <<
format(
"%s:%d: temperature_ph guesses(p=%g,h=%g,tau=%g,delta=%g)\n",__FILE__,__LINE__, p, h, tau, delta) ;
1979 while (worst_error>1e-6 && failed ==
false)
1984 d2a0_ddelta_dtau = 0.0;
1991 f1 = delta/tau*(1+delta*dar_ddelta)-p/(rhoc*
R()*Tc);
1992 f2 = (1+delta*dar_ddelta)+tau*(da0_dtau+dar_dtau)-tau*h/(
R()*Tc);
1993 df1_dtau = (1+delta*dar_ddelta)*(-delta/tau/tau)+delta/tau*(delta*d2ar_ddelta_dtau);
1994 df1_ddelta = (1.0/tau)*(1+2.0*delta*dar_ddelta+delta*delta*d2ar_ddelta2);
1995 df2_dtau = delta*d2ar_ddelta_dtau+da0_dtau+dar_dtau+tau*(d2a0_dtau2+d2ar_dtau2)-h/(
R()*Tc);
1996 df2_ddelta = (dar_ddelta+delta*d2ar_ddelta2)+tau*(d2a0_ddelta_dtau+d2ar_ddelta_dtau);
2007 tau -= omega*(B[0][0]*f1+B[0][1]*f2);
2008 delta -= omega*(B[1][0]*f1+B[1][1]*f2);
2010 if (fabs(f1)>fabs(f2))
2011 worst_error=fabs(f1);
2013 worst_error=fabs(f2);
2023 throw SolutionError(
format(
"Thp did not converge with inputs p=%g h=%g for fluid %s",p,h,(
char*)
name.c_str()));
2034 void Fluid::temperature_ps(
double p,
double s,
double &Tout,
double &rhoout,
double &rhoLout,
double &rhoVout,
double &TsatLout,
double &TsatVout)
2037 double A[2][2], B[2][2],T_guess;
2038 double dar_ddelta,da0_dtau,d2a0_dtau2,dar_dtau,d2ar_ddelta_dtau,d2ar_ddelta2,d2ar_dtau2,d2a0_ddelta_dtau,a0,ar,da0_ddelta;
2039 double f1,f2,df1_dtau,df1_ddelta,df2_ddelta,df2_dtau;
2040 double rhoL, rhoV, ssatL,ssatV,TsatL,TsatV,tau,delta,worst_error;
2041 double s_guess, sc, rho_guess;
2042 double ssat_tol = 1;
2050 T_guess =
crit.
T+30;
2052 T_guess = (
crit.
T-T_guess)/(sc-s_guess)*(s-s_guess)+T_guess;
2062 T_guess =
params.Ttriple;
2066 T_guess = (
crit.
T-T_guess)/(sc-s_guess)*(s-s_guess)+T_guess;
2095 if (s > ssatV + ssat_tol)
2100 T_guess = (TsatV-T_guess)/(ssatV-s_guess)*(s-s_guess)+T_guess;
2104 else if (s < ssatL - ssat_tol)
2106 T_guess =
params.Ttriple;
2110 T_guess = (TsatL-T_guess)/(ssatL-s_guess)*(s-s_guess)+T_guess;
2135 if (fabs(s-ssatL) < 1e-4)
2141 else if (fabs(s-ssatV) < 1e-4)
2151 T_guess = (TsatV-T_guess)/(ssatV-s_guess)*(s-s_guess)+T_guess;
2157 T_guess =
params.Ttriple;
2161 T_guess = (TsatL-T_guess)/(ssatL-s_guess)*(s-s_guess)+T_guess;
2171 double quality = (s-ssatL)/(ssatV-ssatL);
2172 Tout = quality*TsatV+(1-quality)*TsatL;
2173 rhoout = 1/(quality/rhoV+(1-quality)/rhoL);
2183 double tau0 = tau, delta0 = delta;
2185 for(
double omega = 1.0; omega > 0; omega -= 0.3)
2187 bool failed =
false;
2188 tau = tau0; delta = delta0;
2194 while (worst_error>1e-6)
2197 a0 =
phi0(tau,delta);
2201 d2a0_ddelta_dtau = 0.0;
2203 ar =
phir(tau,delta);
2211 f1 = tau*(da0_dtau+dar_dtau)-ar-a0-s/
R();
2212 df1_dtau = tau*(d2a0_dtau2 + d2ar_dtau2)+(da0_dtau+dar_dtau)-dar_dtau-da0_dtau;
2213 df1_ddelta = tau*(d2a0_ddelta_dtau+d2ar_ddelta_dtau)-dar_ddelta-da0_ddelta;
2216 f2 = delta/tau*(1+delta*dar_ddelta)-p/(rhoc*
R()*Tc);
2217 df2_dtau = (1+delta*dar_ddelta)*(-delta/tau/tau)+delta/tau*(delta*d2ar_ddelta_dtau);
2218 df2_ddelta = (1.0/tau)*(1+2.0*delta*dar_ddelta+delta*delta*d2ar_ddelta2);
2227 tau -= omega*(B[0][0]*f1+B[0][1]*f2);
2228 delta -= omega*(B[1][0]*f1+B[1][1]*f2);
2230 if (fabs(f1)>fabs(f2))
2231 worst_error=fabs(f1);
2233 worst_error=fabs(f2);
2235 if (tau < 0 || delta < 0)
2237 failed =
true;
break;
2243 throw SolutionError(
format(
"Tsp did not converge with inputs p=%g s=%g for fluid %s",p,s,(
char*)
name.c_str()));
2249 if (failed ==
false){
break;}
2269 this->pFluid = pFluid;
2286 void Fluid::temperature_hs(
double h,
double s,
double &Tout,
double &rhoout,
double &rhoLout,
double &rhoVout,
double &TsatLout,
double &TsatVout)
2288 bool singlephase_initialized =
false;
2290 double A[2][2], B[2][2], T_guess;
2291 double dar_ddelta,da0_dtau,d2a0_dtau2,dar_dtau,d2ar_ddelta_dtau,d2ar_ddelta2,d2ar_dtau2,d2a0_ddelta_dtau,a0,ar,da0_ddelta;
2292 double f1,f2,df1_dtau,df1_ddelta,df2_ddelta,df2_dtau;
2293 double tau,delta,worst_error,rho_guess, ssat, htriple_s;
2294 double ssat_tol = 0.0001;
2304 throw ValueError(
format(
"HS inputs are solid - not allowed h: %g s: %g",h,s).c_str());
2307 else if (fabs(h-
crit.
h) < 1e-6 && fabs(s-
crit.
s) < 1e-6)
2317 double logpL, logpR, logpM, TM,rhoM,dummy, sM;
2323 logpM = (logpL + logpR)/2;
2336 singlephase_initialized =
true;
2342 double Tsat,rhosat,TL,TV,rhoL,rhoV;
2348 if (fabs(s - ssat) < ssat_tol)
2350 Tout =
Tsat; rhoout = rhoL; rhoLout = rhoL; rhoVout = rhoV; TsatLout = TL; TsatVout = TV;
2361 if (SatFunc.
Q > 1+1e-8 || SatFunc.
Q < 0-1e-8){
throw ValueError(
"Solution must be within the two-phase region"); }
2364 catch(std::exception &)
2370 if (SatFunc.
Q > 1+1e-8 || SatFunc.
Q < 0-1e-8){
throw ValueError(
"Solution must be within the two-phase region"); }
2372 catch(std::exception &)
2377 if (SatFunc.
Q > 1+1e-8 || SatFunc.
Q < 0-1e-8){
throw ValueError(
"Solution must be within the two-phase region"); }
2379 catch (std::exception &)
2383 if (SatFunc.
Q > 1+1e-8 || SatFunc.
Q < 0-1e-8){
throw ValueError(
"Solution must be within the two-phase region"); }
2385 catch (std::exception &)
2392 rhoout = SatFunc.
rho;
2393 rhoLout = SatFunc.
rhoL;
2394 rhoVout = SatFunc.
rhoV;
2402 double logpL, logpR, logpM,TM,rhoM,dummy, sM;
2409 logpM = (logpL + logpR)/2;
2422 singlephase_initialized =
true;
2431 double Tsat,rhosat,TL,TV,rhoL,rhoV;
2439 if (fabs(s-ssat) < ssat_tol)
2441 Tout =
Tsat; rhoout = rhoV; rhoLout = rhoL; rhoVout = rhoV; TsatLout = TL; TsatVout = TV;
2447 double logpL, logpR, logpM, TM,rhoM,dummy,sM;
2453 logpM = (logpL + logpR)/2;
2466 singlephase_initialized =
true;
2473 rhoout = SatFunc.
rho; rhoLout = SatFunc.
rhoL; rhoVout = SatFunc.
rhoV; TsatLout = Tout; TsatVout = Tout;
2480 if (h >
crit.
h && !singlephase_initialized)
2482 double Tsat,rhosat,TL,TV,rhoL,rhoV;
2490 if (fabs(s - ssat) < ssat_tol)
2492 Tout =
Tsat; rhoout = rhoV; rhoLout = rhoL; rhoVout = rhoV; TsatLout = TL; TsatVout = TV;
2498 double logpL, logpR, logpM,TM,rhoM,dummy, sM;
2504 logpM = (logpL + logpR)/2;
2517 singlephase_initialized =
true;
2525 rhoout = SatFunc.
rho; rhoLout = SatFunc.
rhoL; rhoVout = SatFunc.
rhoV; TsatLout = Tout; TsatVout = Tout;
2537 double Tsat,rhosat,TL,TV,rhoL,rhoV;
2546 if (fabs(s - ssat) < ssat_tol)
2548 Tout =
Tsat; rhoout = rhoL; rhoLout = rhoL; rhoVout = rhoV; TsatLout = TL; TsatVout = TV;
2554 double logpL, logpR, logpM,TM,rhoM,dummy, sM;
2561 logpM = (logpL + logpR)/2;
2574 singlephase_initialized =
true;
2581 rhoout = SatFunc.
rho; rhoLout = SatFunc.
rhoL; rhoVout = SatFunc.
rhoV; TsatLout = Tout; TsatVout = Tout;
2605 if (!singlephase_initialized)
2679 while (worst_error>1e-6)
2682 a0 =
phi0(tau,delta);
2686 d2a0_ddelta_dtau = 0.0;
2688 ar =
phir(tau,delta);
2696 f1 = tau*(da0_dtau+dar_dtau)-ar-a0-s/
R();
2697 df1_dtau = tau*(d2a0_dtau2 + d2ar_dtau2)+(da0_dtau+dar_dtau)-dar_dtau-da0_dtau;
2698 df1_ddelta = tau*(d2a0_ddelta_dtau+d2ar_ddelta_dtau)-dar_ddelta-da0_ddelta;
2701 f2 = (1+delta*dar_ddelta)+tau*(da0_dtau+dar_dtau)-tau*h/(
R()*
reduce.
T);
2702 df2_dtau = delta*d2ar_ddelta_dtau+da0_dtau+dar_dtau+tau*(d2a0_dtau2+d2ar_dtau2)-h/(
R()*
reduce.
T);
2703 df2_ddelta = (dar_ddelta+delta*d2ar_ddelta2)+tau*(d2a0_ddelta_dtau+d2ar_ddelta_dtau);
2712 tau -= B[0][0]*f1+B[0][1]*f2;
2713 delta -= B[1][0]*f1+B[1][1]*f2;
2715 if (fabs(f1)>fabs(f2))
2716 worst_error=fabs(f1);
2718 worst_error=fabs(f2);
2723 throw SolutionError(
format(
"Ths did not converge with inputs h=%g s=%g for fluid %s",h,s,(
char*)
name.c_str()));
2733 void Fluid::density_Ts(
double T,
double s,
double &rhoout,
double &pout,
double &rhoLout,
double &rhoVout,
double &psatLout,
double &psatVout)
2735 double rho_guess, ssatL, ssatV;
2742 _SinglePhase =
true;
2752 if (s < ssatL - 0.05*std::abs(ssatL))
2755 _SinglePhase =
true;
2758 else if (s > ssatV + 0.05*std::abs(ssatV))
2761 _SinglePhase =
true;
2762 rho_guess =
params.ptriple/
R()/T;
2772 double Q = (s-ssatL)/(ssatV-ssatL);
2776 _SinglePhase =
true;
2782 _SinglePhase =
true;
2783 rho_guess =
params.ptriple/
R()/T;
2789 _SinglePhase =
false;
2790 rhoout = 1/(Q/rhoVout +(1-Q)/rhoLout);
2791 pout = Q* psatVout +(1-Q)*psatLout;
2804 rhoFuncClass(
double T,
double s,
Fluid *pFluid)
2808 this->pFluid = pFluid;
2811 double call(
double rho)
2818 if (_SinglePhase ==
true)
2820 rhoFuncClass rhoFunc(T, s,
this);
2822 rhoout =
BoundedSecant(&rhoFunc, rho_guess, 0.0, 1e10, 0.1*rho_guess, 1e-8, 100, &errstr);
2831 double Tc,Tmax,Tmin,Tmid;
2837 Tmid = (Tmax+Tmin)/2.0;
2839 double tau_max = Tc/Tmin;
2840 double tau_min = Tc/Tmax;
2849 SatFuncClass(
double p_,
double Q_,
double Tc_, std::string name_,
Fluid *_pFluid){
2850 p=p_;Q=Q_;Tc=Tc_,
name=name_,pFluid = _pFluid;
2852 double call(
double tau){
2854 return log(pFluid->psatV_anc(Tc/tau)/p);
2856 return log(pFluid->psatL_anc(Tc/tau)/p);
2866 double tau =
Brent(&SatFunc,tau_min,tau_max,1e-10,1e-8,50,&errstr);
2867 if (errstr.size()>0)
2871 catch(std::exception &)
2877 double logp_min, logp_mid, logp_max;
2878 double Tmid = (Tmax+Tmin)/2.0;
2879 double tau_mid = Tc/Tmid;
2881 if (fabs(Q-1)<1e-10)
2888 else if (fabs(Q)<1e-10)
2901 double tau_interp =
QuadInterp(logp_min,logp_mid,logp_max,tau_max,tau_mid,tau_min,log(p));
2917 double arL, arV, dar_ddeltaL, dar_ddeltaV, d2ar_ddelta2L, d2ar_ddelta2V, d2ar_ddelta_dtauL, d2ar_ddelta_dtauV;
2918 double dar_dtauL,dar_dtauV;
2919 double p,R,rhoc,Tc,deltaL,deltaV,tau;
2923 this->pFluid = pFluid;
2933 arL = pFluid->
phir(tau,deltaL);
2934 arV = pFluid->
phir(tau,deltaV);
2947 return deltaL*(1+deltaL*dar_ddeltaL);
2949 return deltaV*(1+deltaV*dar_ddeltaV);
2954 return 1+2*deltaL*dar_ddeltaL+deltaL*deltaL*d2ar_ddelta2L;
2956 return 1+2*deltaV*dar_ddeltaV+deltaV*deltaV*d2ar_ddelta2V;
2961 return deltaL*deltaL*d2ar_ddelta_dtauL;
2963 return deltaV*deltaV*d2ar_ddelta_dtauV;
2968 return deltaL*dar_ddeltaL+arL+log(deltaL);
2970 return deltaV*dar_ddeltaV+arV+log(deltaV);
2975 return 2*dar_ddeltaL+deltaL*d2ar_ddelta2L+1/deltaL;
2977 return 2*dar_ddeltaV+deltaV*d2ar_ddelta2V+1/deltaV;
2982 return deltaL*d2ar_ddelta_dtauL+dar_dtauL;
2984 return deltaV*d2ar_ddelta_dtauV+dar_dtauV;
2987 std::vector<double>
call(std::vector<double>
x)
2997 std::vector<double> out = std::vector<double>(3,0);
2998 out[0]=
J(
'V')-
J(
'L');
2999 out[1]=
K(
'V')-
K(
'L');
3000 out[2]=1+deltaV*dar_ddeltaV-p*tau/(R*Tc*deltaV*rhoc);
3003 std::vector<std::vector<double> >
Jacobian(std::vector<double>
x)
3008 std::vector<std::vector<double> > out;
3009 out.resize(x.size(),std::vector<double>(x.size(),0));
3017 out[2][0] = deltaV*d2ar_ddelta2V+dar_ddeltaV+p*tau/(R*Tc*deltaV*deltaV*rhoc);
3019 out[2][2] = deltaV*d2ar_ddelta_dtauV-p/(R*Tc*deltaV*rhoc);
3055 resid = psatL-this->p;
3060 void Fluid::saturation_p(
double p,
bool UseLUT,
double &TsatL,
double &TsatV,
double &rhoLout,
double &rhoVout)
3062 double Tsat,rhoL,rhoV;
3079 std::cout<<
format(
"%s:%d: Fluid::saturation_p(%g,%d) \n",__FILE__,__LINE__,p,UseLUT).c_str();
3099 Tsat =
Secant(&SPGR,Tsat,1e-4,1e-10,50,&errstr);
3102 rhoVout = SPGR.
rhoV;
3103 rhoLout = SPGR.
rhoL;
3108 catch(std::exception &)
3114 if (Tsat >=
crit.
T){
3115 Tsat =
crit.
T-0.0000001;
3121 double Tmin = Tsat-3;
3127 throw SolutionError(
"Saturation calculation yielded invalid number using Brent's method");
3128 rhoVout = SPGR.
rhoV;
3129 rhoLout = SPGR.
rhoL;
3167 double rhoLout,rhoVout;
3168 return Tsat(p, Q, T_guess,
false, rhoLout, rhoVout);
3171 double Fluid::Tsat(
double p,
double Q,
double T_guess,
bool UseLUT,
double &rhoLout,
double &rhoVout)
3181 double Tc,Tmax,Tmin;
3199 SatFuncClass(
double p_,
double Q_,
double Tc_, std::string
name,
Fluid * pFluid){
3200 p=p_;Q=Q_;Tc=Tc_,this->name=
name,this->pFluid = pFluid;
3202 double call(
double tau){
3205 return log(pFluid->
psatL(Tc/tau)/p);
3209 return log(pFluid->
psatV(Tc/tau)/p);
3218 double tau_max = Tc/Tmin;
3219 double tau_min = Tc/Tmax;
3223 double tau =
Brent(&SatFunc,tau_min,tau_max,1e-10,1e-10,50,&errstr);
3224 if (errstr.size()>0)
3252 double eta_star, Tstar, OMEGA_2_2;
3255 OMEGA_2_2 = 1.16145*pow(Tstar,-0.14874)+ 0.52487*exp(-0.77320*Tstar)+2.16178*exp(-2.43787*Tstar);
3257 eta_star = 26.692e-3*sqrt(
params.molemass*T)/(pow(sigma,2)*OMEGA_2_2)/1e6;
3264 double k=1.3806488e-23,
3270 cp,cv,delta,num,zeta,mu,
3271 OMEGA_tilde,OMEGA_tilde0,pi=
M_PI,tau;
3277 double X = Pcrit/pow(
reduce.
rho,2)*rho/dp_drho;
3281 double Xref = Pcrit/pow(
reduce.
rho,2)*rho/dp_drho_ref*Tref/T;
3288 zeta=zeta0*pow(num/GAMMA,nu/gamma);
3294 OMEGA_tilde=2.0/pi*((cp-cv)/cp*atan(zeta*qd)+cv/cp*(zeta*qd));
3295 OMEGA_tilde0=2.0/pi*(1.0-exp(-1.0/(1.0/(qd*zeta)+1.0/3.0*(zeta*qd)*(zeta*qd)/delta/delta)));
3297 double lambda=rho*cp*1e6*(R0*k*T)/(6*pi*mu*zeta)*(OMEGA_tilde-OMEGA_tilde0);
3310 double N_A = 6.02214129e23,
3312 w =
params.accentricfactor,
3325 sigma = k*Tc*pow(N_A/Vc,2.0/3.0)*(4.35+4.14*w)*pow(t,1.26)*(1+0.19*sqrt(t)-0.25*t);
3335 *sigma = 0.809/pow(rhobarc,1.0/3.0);
3340 Fluid * InterestFluid, * ReferenceFluid;
3341 double alpha_j, Z_j;
3344 this->InterestFluid = InterestFluid;
3345 this->ReferenceFluid = ReferenceFluid;
3346 this->alpha_j = alpha_j;
3350 std::vector<double>
call(std::vector<double>
x)
3352 double T0 = x[0];
double rho0 = x[1];
3355 std::vector<double> out = std::vector<double>(2,0);
3356 out[0]=alpha_j-alpha_0;
3360 std::vector<std::vector<double> >
Jacobian(std::vector<double>
x)
3362 double T0=x[0];
double rho0=x[1];
3363 double dtau_dT = -ReferenceFluid->
reduce.
T/T0/T0;
3364 double ddelta_drho = 1/ReferenceFluid->
reduce.
rho;
3365 std::vector<std::vector<double> > out;
3366 out.resize(x.size(),std::vector<double>(x.size(),0));
3369 out[0][0] = dalpha_dT0;
3371 out[0][1] = dalpha_drho0;
3375 out[1][1] = dZ_drho0;
3384 double error,v0,v1,delta,tau,dp_drho;
3390 std::vector<double> f0,v,negative_f0;
3391 std::vector<std::vector<double> > J;
3393 std::vector<double> x0 = std::vector<double>(2,0);
3401 std::vector<double> x0_initial = x0;
3409 throw ValueError(
"Error calculating the conformal state for ECS");
3412 std::vector<double> xout(2,x0[0]);
3416 catch(std::exception &){}
3422 while (iter<30 && fabs(error)>1e-6)
3443 for (
unsigned int i = 0; i<f0.size(); i++){ negative_f0[i] *= -1;}
3448 if (x0[0]-v[0]>0 && x0[1]-v[1]>0)
3455 x0[0] -= 1.05*x0[0];
3456 x0[1] -= 1.05*x0[1];
3462 *errstring = std::string(
"ConformalTemperature reached maximum number of steps without reaching solution");
3467 std::vector<double> xout(2,x0[0]);
3481 double e_k,sigma,e0_k, sigma0, Tc0,rhoc0,T0,rho0,rhoc,Tc,
3482 eta_dilute,theta,phi,f,h,eta_resid,M,M0,F_eta,eta,psi,
3483 rhoc0bar,rhobar,rhocbar,rho0bar;
3484 std::vector<double> x0;
3489 rhoc0bar = rhoc0/M0;
3503 ReferenceFluid->
ECSParams(&e0_k,&sigma0);
3511 sigma = sigma0*pow(rhoc/rhoc0,1.0/3.0);
3539 double Bstar,Bstar0,Cstar,Cstar0,DELTABstar,DELTACstar,Zc,Zc0;
3540 double omega =
params.accentricfactor;
3545 Bstar = -6.207612-15.37641*omega-0.574946*pow(10,-omega);
3546 Bstar0 = -6.207612-15.37641*omega0-0.574946*pow(10,-omega0);
3547 Cstar = 8/3+9*Bstar/5.0/log(10.0);
3548 Cstar0 = 8/3+9*Bstar0/5.0/log(10.0);
3549 DELTABstar = Bstar-Bstar0;
3550 DELTACstar = Cstar-Cstar0;
3551 theta = (1-Cstar0+2*pow(1-Tstar,2.0/7.0)*log(Zc/Zc0)-DELTABstar+DELTACstar*log(Tstar)+Bstar/Tstar)/(1-Cstar0+Bstar0/Tstar);
3552 phi = pow(Zc,pow(1-Tstar,2.0/7.0))/pow(Zc0,pow(1-Tstar/theta,2.0/7.0));
3559 h=rhoc0bar/rhocbar*phi;
3564 std::string errstring;
3570 double p0 = Z*
R()*T0*rho0;
3582 F_eta = sqrt(f)*pow(h,-2.0/3.0)*sqrt(M/M0);
3583 eta = eta_dilute+eta_resid*F_eta;
3596 double e_k,sigma,e0_k, sigma0, Tc0,rhoc0,T0,rho0,rhoc,Tc,
3597 eta_dilute,theta,phi,f,h,lambda_resid,M,M0,F_lambda,lambda,chi,
3598 f_int,lambda_int,lambda_crit,lambda_star,rhoc0bar,rhobar,rhocbar,rho0bar;
3599 std::vector<double> x0;
3605 rhoc0bar = rhoc0/M0;
3621 ReferenceFluid->
ECSParams(&e0_k,&sigma0);
3628 sigma = sigma0*pow(rhoc/rhoc0,1.0/3.0);
3643 h=rhoc0bar/rhocbar*phi;
3649 std::string errstring;
3655 double p0 = Z*
R()*T0*rho0;
3656 if (Z<0.3 || p0 > 1.1*ReferenceFluid->
reduce.
p.
Pa || rho0 > ReferenceFluid->
reduce.
rho){
3669 lambda_star = 15e-3*
R()*(eta_dilute*1e3)/4.0;
3670 lambda_int = f_int*(eta_dilute*1e3)*(cpstar-5.0/2.0*
R() );
3671 F_lambda = sqrt(f)*pow(h,-2.0/3.0)*sqrt(M0/M);
3677 lambda = lambda_int+lambda_star+lambda_resid*F_lambda+lambda_crit;
3781 if (Tmin<pFluid->limits.Tmin)
3784 for(
int i = 0; i<N; i++)
3786 T = Tmin+(Tmax-Tmin)/(N-1)*i;
3841 double tauend = Tc/
Tend, tau = Tc/T;
3843 double k1,k2,R,Rend,a,b,c,d,rhoend;
3845 if (fabs(T-Tc)<1e-6)
3856 else if (phase == 1)
3873 double a11 = Rend*Rend*Rend;
3874 double a12 = Rend*Rend;
3876 double a21 = 3*Rend*Rend;
3877 double a22 = 2*Rend;
3881 double det = a11*a22-a21*a12;
3882 a = (b1*a22-a12*b2)/det;
3883 b = (b2*a11-a21*b1)/det;
3890 double DELTA = 18*a*b*c*d-4*b*b*b*d+b*b*c*c-4*a*c*c*c-27*a*a*d*d;
3893 double p = (3*a*c-b*b)/(3*a*a);
3894 double q = (2*b*b*b-9*a*b*c+27*a*a*d)/(27*a*a*a);
3900 if (4*p*p*p+27*q*q>0 && p<0)
3902 t0 = -2.0*fabs(q)/q*sqrt(-p/3.0)*cosh(1.0/3.0*acosh(-3.0*fabs(q)/(2.0*p)*sqrt(-3.0/p)));
3906 t0 = -2.0*sqrt(p/3.0)*sinh(1.0/3.0*asinh(3.0*q/(2.0*p)*sqrt(3.0/p)));
3913 double t0 = 2.0*sqrt(-p/3.0)*cos(1.0/3.0*acos(3.0*q/(2.0*p)*sqrt(-3.0/p))-0*2.0*
M_PI/3.0);
3914 double t1 = 2.0*sqrt(-p/3.0)*cos(1.0/3.0*acos(3.0*q/(2.0*p)*sqrt(-3.0/p))-1*2.0*
M_PI/3.0);
3915 double t2 = 2.0*sqrt(-p/3.0)*cos(1.0/3.0*acos(3.0*q/(2.0*p)*sqrt(-3.0/p))-2*2.0*
M_PI/3.0);
3917 double R0 = t0-b/(3*a);
3918 double R1 = t1-b/(3*a);
3919 double R2 = t2-b/(3*a);
3922 if (R0*Rend > 0 && fabs(R0)<=fabs(Rend))
3926 else if (R1*Rend > 0 && fabs(R1)<=fabs(Rend))
3930 else if (R2*Rend > 0 && fabs(R2)<=fabs(Rend))
3947 UseCriticalSpline =
false;
3951 double rhoL=0, rhoV=0, drhodTL=0, drhodTV=0;
3954 fp = fopen(
"CriticalSplineConstants_T.h",
"w");
3955 for (
unsigned int i = 0; i < fluid_names.size(); i++)
3957 std::cout <<
format(
"%s:\n",fluid_names[i].c_str()).c_str();
3971 rhoV = CPS.
rhoV(); rhoL = CPS.
rhoL();
3980 rhoV = CPS.
rhoV(); rhoL = CPS.
rhoL();
3987 catch(std::exception &)
3991 std::cout <<
format(
"%s : failed at 20 K \n",fluid_names[i].c_str()).c_str();
3996 std::cout <<
format(
"%s : failed at 1 K \n",fluid_names[i].c_str()).c_str();
4002 for (
double step = 0.5; step > 1e-10; step /= 100.0)
4005 for (
double b = good; b>0; b -= step)
4009 rhoV = CPS.
rhoV(); rhoL = CPS.
rhoL();
4013 catch(std::exception &){
4033 rhoV = CPS2.
rhoV(); rhoL = CPS2.
rhoL();
4036 std::cout <<
format(
"%0.20g",good).c_str() << std::endl;
4037 fprintf(fp,
"\tstd::make_pair(std::string(\"%s\"),CriticalSplineStruct_T(%0.12e,%0.12e,%0.12e,%0.12e,%0.12e) ),\n",fluid_names[i].c_str(),Tc-good,rhoL,rhoV,drhodTL,drhodTV);
4040 UseCriticalSpline =
true;
4060 std::vector<std::string> aliasesv =
get_aliases();
4061 for (std::vector<std::string>::iterator it = aliasesv.begin(); it != aliasesv.end(); it++)
4114 for (std::vector<phi_BC*>::const_iterator it =
phirlist.begin(); it !=
phirlist.end(); it++)
4117 (*it)->to_json(entry, dd);
4123 for (std::vector<phi_BC*>::const_iterator it =
phi0list.begin(); it !=
phi0list.end(); it++)
4126 (*it)->to_json(entry, dd);
4143 fp = fopen((
get_name()+
".json").c_str(),
"w");
4144 fprintf(fp,
"%s",json0.c_str());
4147 return std::string();
double JSON_lookup_double(rapidjson::Document &root, std::string FluidName, std::string key)
HSSatFuncClass(double h, double s, Fluid *pFluid)
std::vector< std::vector< double > > Jacobian(std::vector< double > x)
struct HSContainer HS
The point that is used to reduce the T and rho for EOS.
Fluid * get_fluid(long iFluid)
void rhosatPure(double T, double &rhoLout, double &rhoVout, double &pout, double omega, bool use_guesses)
DensityTpResids(Fluid *pFluid, double T, double p)
double BoundedSecant(FuncWrapper1D *f, double x0, double xmin, double xmax, double dx, double tol, int maxiter, std::string *errstring)
std::vector< double > a_hs_satL
double drhoVdT_sat
Derivative of density w.r.t. temperature along the saturated vapor curve.
virtual double d3phir_dDelta_dTau2(double tau, double delta)
std::vector< phi_BC * > phirlist
double R()
Returns the mass-specific gas constant for the fluid in the desired units.
virtual double d2phi0_dTau2(double tau, double delta)
FluidCacheElement dphir_dDelta
double interpolateV(double T)
void rebuild_CriticalSplineConstants_T()
Rebuild the constants.
AncillaryCurveClass * h_ancillary
True if it is a pure fluid, false otherwise.
int set_reference_stateP(Fluid *pFluid, std::string reference_state)
virtual double d2phir_dDelta_dTau(double tau, double delta)
Saturation_p_IterateSaturationT_Resids(Fluid *pFluid, double p)
virtual void temperature_ph(double p, double h, double &Tout, double &rhoout, double &rhoL, double &rhoV, double &TsatLout, double &TsatVout, double T0=-1, double rho0=-1)
long get_Fluid_index(std::string FluidName)
double build(double pmin, double pmax, TTSETwoPhaseTableClass *other=NULL)
double reverseinterpolateL(double y)
bool build_TTSE_LUT(bool force=false)
Build of the TTSE LUT.
virtual void temperature_ps(double p, double s, double &Tout, double &rhoout, double &rhoL, double &rhoV, double &TsatLout, double &TsatVout)
struct FluidLimits limits
virtual double d3phir_dDelta3(double tau, double delta)
virtual double density_Tp(double T, double p)
double reverseinterpolateV(double y)
double rhoendV
Saturated vapor density at the last temperature for which the conventional methods can be used...
virtual void temperature_hs(double h, double s, double &Tout, double &rhoout, double &rhoL, double &rhoV, double &TsatLout, double &TsatVout)
rhosatPure_BrentrhoVResidClass(double T, Fluid *pFluid)
void enable_TTSE_LUT_writing(void)
Enable the writing of TTSE tables to file.
virtual void saturation_s(double s, int Q, double &Tsatout, double &rhoout, double &TsatLout, double &TsatVout, double &rhoLout, double &rhoVout)
double Tsat_anc(double p, double Q)
bool isenabled_TTSE_LUT_writing(void)
Check if the writing of TTSE tables to file is enabled.
virtual double d3phi0_dTau3(double tau, double delta)
double psatV_anc(double T)
virtual void saturation_h(double h, double Tmin, double Tmax, int Q, double &Tsatout, double &rhoout, double &TsatLout, double &TsatVout, double &rhoLout, double &rhoVout)
GenericValue & SetObject()
Set this value as an empty object.
double interpolateL(double T)
std::vector< std::string > get_aliases()
double specific_heat_p_ideal_Trho(double T)
virtual double viscosity_background(double T, double rho)
virtual double d3phir_dTau3(double tau, double delta)
std::string ECSReferenceFluid
A list of aliases of names for the Fluid, each element is a std::string instance. ...
const char * GetString() const
FluidCacheElement d2phir_dDelta2
SaturationPressureGivenResids(Fluid *pFluid, double p)
std::string name
A container to hold the cache for residual Helmholtz derivatives.
~SaturationPressureGivenResids()
AncillaryCurveClass * s_ancillary
unsigned SizeType
Use 32-bit array/string indices even for 64-bit platform, instead of using size_t.
std::vector< double > call(std::vector< double > x)
virtual double phi0(double tau, double delta)
EXPORT_CODE int CONVENTION get_debug_level()
const GenericValue & Accept(Handler &handler) const
Generate events of this value to a Handler.
FluidCacheElement d2phir_dTau2
void set_TTSESinglePhase_LUT_range(double hmin, double hmax, double pmin, double pmax)
Over-ride the default range of the single-phase LUT.
virtual double ECS_psi_viscosity(double rhor)
double drhodT_along_sat_liquid(void)
std::string to_json()
Export this fluid as a JSON file;.
double viscosity_ECS_Trho(double T, double rho, Fluid *ReferenceFluid)
double gibbs_Trho(double T, double rho)
virtual double psat(double T)
double rhoendL
Saturated liquid density at the last temperature for which the conventional methods can be used...
double pressure_Trho(double T, double rho)
Writer with indentation and spacing.
void disable_EXTTP(void)
Disable the TTSE.
void update(long iInput1, double Value1, long iInput2, double Value2, double T0=-1, double rho0=-1)
A stub class to do the density(T,p) calculations for near the critical point using Brent solver...
long phase_prho_indices(double p, double rho, double &T, double &TL, double &TV, double &rhoL, double &rhoV)
double conductivity_critical(double T, double rho, double qd=2e9, double GAMMA=0.0496, double zeta0=1.94e-10)
double psatL_anc(double T)
std::vector< std::string > aliases
The REFPROP-compliant name if REFPROP-"name" is not a compatible fluid name. If not included...
void set_size_Trho(unsigned int NT=100, unsigned int Nrho=100)
Set the sizes of the matrices with Trho as inputs.
virtual double dphi0_dTau(double tau, double delta)
double entropy_Trho(double T, double rho)
double _get_rho_guess(double T, double p)
TTSETwoPhaseTableClass * SatL
double density_Tp_Soave(double T, double p, int iValue=0)
Get the density using the Soave EOS.
struct CriticalStruct reduce
A pointer to the point that is used to reduce the T and rho for EOS.
std::vector< double > JSON_lookup_dblvector(rapidjson::Document &root, std::string FluidName, std::string key)
double internal_energy_Trho(double T, double rho)
~SaturationFunctionOfPressureResids()
Represents an in-memory output stream.
long phase_Trho_indices(double T, double rho, double &pL, double &pV, double &rhoL, double &rhoV)
Return the phase using the phase flags from phase enum in CoolProp.h.
void set_TTSESinglePhase_LUT_size(int Np, int Nh)
Over-ride the default size of the single-phase LUT.
void update(Fluid *pFluid, std::string Output)
std::string get_name()
Returns a std::string with the name of the fluid.
void rhosatPure_BrentrhoV(double T, double &rhoLout, double &rhoVout, double &pout)
virtual double surface_tension_T(double T)
virtual void ECSParams(double *e_k, double *sigma)
virtual double rhosatV(double T)
double speed_sound_Trho(double T, double rho)
Fluid * pFluid
A pointer to a CoolProp fluid.
virtual double viscosity_dilute(double T, double e_k, double sigma)
TTSETwoPhaseTableClass TTSESatV
Fluid is the abstract base class that is employed by all the other fluids.
double drhodT_along_sat_vapor(void)
GenericValue & SetString(const Ch *s, SizeType length)
Set this value as a string without copying source string.
FluidCacheElement dphir_dTau
virtual double dphir_dTau(double tau, double delta)
double PropsSI(std::string Output, std::string Name1, double Prop1, std::string Name2, double Prop2, std::string Ref)
virtual double dphi0_dDelta(double tau, double delta)
EnvironmentalFactorsStruct environment
SizeType Size() const
Get the number of elements in array.
struct CriticalStruct * preduce
long phase_Tp_indices(double T, double p, double &pL, double &pV, double &rhoL, double &rhoV)
Return the phase using the phase flags from phase enum in CoolProp.h.
void enable_TTSE_LUT(void)
GenericValue & AddMember(GenericValue &name, GenericValue &value, Allocator &allocator)
Add a member (name-value pair) to the object.
void set_TTSESat_LUT_size(int Nsat)
Over-ride the default size of both of the saturation LUT.
double hsatV_anc(double T)
double build_ph(double hmin, double hmax, double pmin, double pmax, TTSETwoPhaseTableClass *SatL=NULL, TTSETwoPhaseTableClass *SatV=NULL)
TTSESinglePhaseTableClass TTSESinglePhase
std::vector< double > x(ncmax, 0)
std::string REFPROPname
The name of the fluid.
bool isenabled_EXTTP(void)
Check if TTSE is enabled.
FluidCacheElement d2phir_dDelta_dTau
std::vector< std::vector< double > > linsolve(std::vector< std::vector< double > > const &A, std::vector< std::vector< double > > const &B)
struct OtherParameters params
bool isPure
A std::string that contains a reference for the transport properties of the fluid.
std::string FluidList()
Returns a std::string of a comma-separated list of the CoolProp names of all the fluids that are load...
GenericValue & PushBack(GenericValue &value, Allocator &allocator)
Append a value at the end of the array.
double hsatL_anc(double T)
std::string JSON_lookup_string(rapidjson::Document &root, std::string FluidName, std::string key)
std::vector< int > n_hs_satL
double specific_heat_v_Trho(double T, double rho)
void rhosatPure_Brent(double T, double &rhoLout, double &rhoVout, double &pout)
A document for parsing JSON text as DOM.
CriticalSplineStruct_T CriticalSpline_T
void set_size(unsigned int N)
double Tsat(double p, double Q, double T_guess)
bool isBetween(double x1, double x2, double x)
virtual double psatV(double T)
void rhosatPure_Akasaka(double T, double &rhoLout, double &rhoVout, double &pout, double omega, bool use_guesses=false)
void disable_TTSE_LUT_writing(void)
Disable the writing of TTSE tables to file.
double density_Tp_PengRobinson(double T, double p, int solution)
double evaluate(long iParam, double p)
double Brent(FuncWrapper1D *f, double a, double b, double macheps, double t, int maxiter, std::string *errstr)
virtual double d2phir_dDelta2(double tau, double delta)
double drhodT_p_Trho(double T, double rho)
struct CriticalStruct crit
std::vector< double > ConformalTemperature(Fluid *InterestFluid, Fluid *ReferenceFluid, double T, double rho, double T0, double rho0, std::string *errstring)
Allocator & GetAllocator()
Get the allocator of this document.
TTSETwoPhaseTableClass * SatV
BibTeXKeysStruct BibTeXKeys
void write_all_to_file(std::string root_path=std::string())
double dpdrho_Trho(double T, double rho)
virtual double phir(double tau, double delta)
bool enabled_TTSE_LUT
Parameters for the Tabular Taylor Series Expansion (TTSE) Method.
~Saturation_p_IterateSaturationT_Resids()
double temperature_prho(double p, double rho, double T0)
double DerivTerms(long iTerm, double T, double rho, Fluid *pFluid)
virtual double ECS_f_int(double T)
void calculate_parameters(double deltaV, double deltaL, double tau)
virtual double conductivity_background(double T, double rho)
virtual double d2phi0_dDelta2(double tau, double delta)
std::string phase_Tp(double T, double p, double &pL, double &pV, double &rhoL, double &rhoV)
Return the phase given the temperature and pressure.
void get_TTSESinglePhase_LUT_range(double *hmin, double *hmax, double *pmin, double *pmax)
Get the current range of the single-phase LUT.
long get_param_index(std::string param)
std::vector< phi_BC * > phi0list
A vector of instances of the phi_BC classes for the residual Helmholtz energy contribution.
void update(long iInput1, double Value1, long iInput2, double Value2)
double build_Trho(double Tmin, double Tmax, double rhomin, double rhomax, TTSETwoPhaseTableClass *SatL, TTSETwoPhaseTableClass *SatV)
double dpdT_Trho(double T, double rho)
double specific_heat_p_Trho(double T, double rho)
bool read_all_from_file(std::string root_path)
std::vector< double > NDNewtonRaphson_Jacobian(FuncWrapperND *f, std::vector< double > x0, double tol, int maxiter, std::string *errstring)
double Secant(FuncWrapper1D *f, double x0, double dx, double tol, int maxiter, std::string *errstring)
void post_load(rapidjson::Document &JSON, rapidjson::Document &JSON_CAS)
bool enable_writing_tables_to_files
bool HasMember(const Ch *name) const
Check whether a member exists in the object.
bool isAlias(std::string name)
virtual double viscosity_Trho(double T, double rho)
virtual double ECS_chi_conductivity(double rhor)
virtual double d2phi0_dDelta_dTau(double tau, double delta)
bool isenabled_TTSE_LUT(void)
Check if TTSE is enabled.
void set_size_ph(unsigned int Np=100, unsigned int Nh=100)
Set the sizes of the matrices with h,p as inputs.
double conductivity_ECS_Trho(double T, double rho, Fluid *ReferenceFluid)
std::string JSON_lookup_CAS(rapidjson::Document &root, std::string FluidName)
bool pure()
Returns true if the fluid is pure, false if pseudo-pure or a mixture.
void saturation_VdW(double T, double &rhoL, double &rhoV, double &p, double s0=-1)
virtual double d2phir_dTau2(double tau, double delta)
virtual double psatL(double T)
double temperature_prho_PengRobinson(double p, double rho)
TTSETwoPhaseTableClass TTSESatL
double interpolate_rho(Fluid *pFluid, int phase, double T)
virtual double dphir_dDelta(double tau, double delta)
Represents a JSON value. Use Value for UTF8 encoding and default allocator.
std::vector< int > JSON_lookup_intvector(rapidjson::Document &root, std::string FluidName, std::string key)
virtual double rhosatL(double T)
virtual void saturation_p(double p, bool UseLUT, double &TsatLout, double &TsatVout, double &rhoLout, double &rhoVout)
double ssatL_anc(double T)
virtual double d3phir_dDelta2_dTau(double tau, double delta)
bool enable_writing_tables_to_files
virtual double conductivity_Trho(double T, double rho)
double enthalpy_Trho(double T, double rho)
const Ch * GetString() const
SaturationFunctionOfPressureResids(Fluid *pFluid, double p, double R, double rhoc, double Tc)
void disable_TTSE_LUT(void)
Disable the TTSE.
double temperature_prho_VanDerWaals(double p, double rho)
virtual void density_Ts(double T, double s, double &rhoout, double &pout, double &rhoLout, double &rhoVout, double &psatLout, double &psatVout)
virtual void saturation_T(double T, bool UseLUT, double &psatLout, double &psatVout, double &rhoLout, double &rhoVout)
double drhoLdT_sat
Derivative of density w.r.t. temperature along the saturated liquid curve.
double Tend
The last temperature for which the conventional methods can be used.
double ssatV_anc(double T)
std::string phase_Trho(double T, double rho, double &pL, double &pV, double &rhoL, double &rhoV)
Return the phase given the temperature and the density.
double dpdT_constrho(void)