From 3c8eb8746b3c3d51448aeb8fdf756e491f8b1301 Mon Sep 17 00:00:00 2001 From: Ian Bell Date: Fri, 23 May 2014 17:13:54 +0200 Subject: [PATCH] Started with conductivity - implemented n-Hexane Signed-off-by: Ian Bell --- dev/fluids/n-Hexane.json | 72 ++++++++++ doc/transport_table/table.tex | 43 +++++- include/CoolPropFluid.h | 59 +++++++- src/Backends/Helmholtz/Fluids/FluidLibrary.h | 130 +++++++++++++++++- .../Helmholtz/HelmholtzEOSMixtureBackend.cpp | 58 +++++++- .../Helmholtz/HelmholtzEOSMixtureBackend.h | 1 + src/Backends/Helmholtz/TransportRoutines.cpp | 53 +++++++ src/Backends/Helmholtz/TransportRoutines.h | 74 +++++++++- src/Tests/CoolProp-Tests.cpp | 53 +++++-- 9 files changed, 514 insertions(+), 29 deletions(-) diff --git a/dev/fluids/n-Hexane.json b/dev/fluids/n-Hexane.json index fc6d9cff..97f1f694 100644 --- a/dev/fluids/n-Hexane.json +++ b/dev/fluids/n-Hexane.json @@ -267,6 +267,78 @@ ], "NAME": "n-Hexane", "TRANSPORT": { + "conductivity": { + "BibTeX": "Assael-JPCRD-2013-Hexane", + "critical": { + "type": "simplified_Olchowy_Sengers" + }, + "dilute": { + "A": [ + 0.0066742, + -0.0237619, + 0.0720155, + -0.0183714 + ], + "B": [ + 1 + ], + "T_reducing": 507.82, + "T_reducing_units": "K", + "m": [ + 0 + ], + "n": [ + 0, + 1, + 2, + 3 + ], + "type": "ratio_of_polynomials" + }, + "residual": { + "B": [ + -0.0301408, + 0.0218208, + 0.167975, + -0.100833, + -0.129739, + 0.077418, + 0.0382833, + -0.0215945, + -0.00370294, + 0.00212487 + ], + "T_reducing": 507.82, + "T_reducing_units": "K", + "d": [ + 1, + 1, + 2, + 2, + 3, + 3, + 4, + 4, + 5, + 5 + ], + "rhomass_reducing": 233.182, + "rhomass_reducing_units": "kg/m^3", + "t": [ + 0, + -1, + 0, + -1, + 0, + -1, + 0, + -1, + 0, + -1 + ], + "type": "polynomial" + } + }, "viscosity": { "BibTeX": "Michailidou-JCED-2013", "dilute": { diff --git a/doc/transport_table/table.tex b/doc/transport_table/table.tex index 4651871e..ab24881f 100644 --- a/doc/transport_table/table.tex +++ b/doc/transport_table/table.tex @@ -13,7 +13,6 @@ \hline\hline Fluid & Reference & $\eta^0$ & $\eta^r$ \\ \hline -Ammonia & (data) Fenghour 1995 & $\eta^0 = \dfrac{0.021357\sqrt{MT}}{\sigma^2\Game(T^*)}$\newline$\mathfrak{S}(T^*)=\exp\left(\sum_{i=0}^{4}a_i[\ln T^*]^i\right)$ & $\eta^r = B_{BV}\rho\eta^0(T) + \Delta\eta$\newline$\Delta\eta = \sum_i b_i(T)\rho^i$\\\hline H2S & Quinones-Cisneros 2012 & $\eta^0 = 0.87721\dfrac{\sqrt{T}}{S^*(T^*)}$ \newline $S^*(T^*) = \sum_i \frac{\alpha_i}{T^{*i}}$ & FRICTION THEORY\\\hline \hline \multicolumn{4}{c}{DONE below this line}\\ \hline\hline Propane & (data) Vogel 1998 & $\eta^0 = \dfrac{0.021357\sqrt{MT}}{\sigma^2\mathfrak{S}(T^*)}$\newline$\mathfrak{S}(T^*)=\exp\left(\sum_{i=0}^{4}a_i[\ln T^*]^i\right)$ & $\eta_h = \displaystyle\sum_{i=2}^n\displaystyle\sum_{j=0}^me_{ij}\frac{\delta^i}{\tau_j}+f_1\left(\frac{\delta}{\delta_0(\tau)-\delta}-\frac{\delta}{\delta_0(\tau)}\right)$ \newline $\delta_0(\tau)=g_1(1+g_2\tau^{1/2})$\\\hline @@ -37,8 +36,50 @@ R404A, R410A, R507, R407 & (data) Geller 2000 & $\eta^0 = \sum_i A_iT^i$&$\eta^r Helium & (data) Arp 1998 & hardcoded & hardcoded \\\hline R23 & (data) Shan 2000 & $\eta^0 = \frac{5}{16}\sqrt{\frac{MkT}{1000\pi N}}\frac{10^{24}}{\sigma^2\Omega^*(T^*)}$\newline $\Omega(T^*)=\exp\left(\sum_{i=0}^{4}a_i[\ln T^*]^i\right)$ & \\\hline Ethane & (data) Friend 1991 & $\eta^0 = \dfrac{12.0085\sqrt{t}}{\Omega^{(2,2)*}(t)}$ \newline $\Omega^{(2,2)*}(t) = \left[\sum_i C_it^{(i-1)/3-1} \right]^{-1}$& $\Delta\eta = 15.977\left[\displaystyle\sum_i g_i\delta^{r_i}\tau^{s_i}\right]\left[1+\displaystyle\sum_{i=10}^{11}g_i\delta^{r_i}\tau^{s_i}\right]^{-1}$\\\hline +Ammonia & (data) Fenghour 1995 & $\eta^0 = \dfrac{0.021357\sqrt{MT}}{\sigma^2\Game(T^*)}$\newline$\mathfrak{S}(T^*)=\exp\left(\sum_{i=0}^{4}a_i[\ln T^*]^i\right)$ & $\eta^r = B_{BV}\rho\eta^0(T) + \Delta\eta$\newline$\Delta\eta = \sum_i b_i(T)\rho^i$\\\hline \hline\hline \end{tabular} For a description of the conversion between $\mathfrak{S}$ and $\Omega$, see Vesovic 1990 ($CO_2$). Basically $\Omega = (5/4)\mathfrak{S}$. + +\clearpage + +\centering +\begin{tabular}{cccp{3in}p{8in}p{3in}} +\hline\hline +Fluid & Data & Reference & Dilute & Residual & Critical \\ \hline +Nitrogen, Argon, Oxygen, Air & & Lemmon 2004 & & &\\ +Ammonia & & Tufeu 1984 \\ + +CO2 & & Vesovic JPCRD 1990 \\ +Ethane & & Friend JPCRD 1991 \\ + +Helium & & Hands Cryo 1981\\ + +Isobutane & & Perkins JCED 2002\\ +R123 & & Laesecke IJR 1996 \\ +R1234ze(E) & & Perkins JCED 2011 \\ +R125 & & Perkins JCED 2006 \\ +R152A & & Krauss IJT 1996 \\ +R23 & & Shan ASHRAE 2000 \\ +R404A, R407C, R401A, R507A & & Geller IJT 2001 \\ + +Water & & Huber JPCRD 2012\\ +Butane & & Perkins JCED 2002 \\ +Octane, Nonane, Decane & & Huber FPE 2005\\ +Dodecane & & Huber EF 2004 \\ + +Ethanol & & Assael JPCRD 2013 \\ +SF6 & & Assael JPCRD 2012\\ +Toluene & & Assael JPCRD 2012\\ +Benzene & & Assael JPCRD 2012 \\ +Normal-/Parahydrogen & & Assael JPCRD 2011\\ +Heptane & & Assael JPCRD 2013\\ +Hexane & & Assael JPCRD 2013\\ + +Propane & & Marsh JCED 2002\\ +\hline\hline +\end{tabular} + + \end{document} \ No newline at end of file diff --git a/include/CoolPropFluid.h b/include/CoolPropFluid.h index 595fc05d..cbf7a92c 100644 --- a/include/CoolPropFluid.h +++ b/include/CoolPropFluid.h @@ -43,6 +43,52 @@ struct EOSLimits { double Tmin, Tmax, rhomax, pmax; }; + +struct ConductivityDiluteRatioPolynomialsData{ + long double T_reducing, p_reducing; + std::vector A, B, n, m; +}; +struct ConductivityDiluteVariables +{ + enum ConductivityDiluteEnum {CONDUCTIVITY_DILUTE_RATIO_POLYNOMIALS, + CONDUCTIVITY_DILUTE_NOT_SET + }; + int type; + ConductivityDiluteRatioPolynomialsData ratio_polynomials; + + ConductivityDiluteVariables(){type = CONDUCTIVITY_DILUTE_NOT_SET;} +}; + +struct ConductivityResidualPolynomialData{ + long double T_reducing, rhomass_reducing; + std::vector B, t, d; +}; +struct ConductivityResidualVariables +{ + enum ConductivityResidualEnum {CONDUCTIVITY_RESIDUAL_POLYNOMIAL, + CONDUCTIVITY_RESIDUAL_NOT_SET + }; + int type; + ConductivityResidualPolynomialData polynomials; + + ConductivityResidualVariables(){type = CONDUCTIVITY_RESIDUAL_NOT_SET;} +}; + +struct ConductivityCriticalSimplifiedOlchowySengers{ + long double T_reducing, p_reducing; + std::vector B, t, d; +}; +struct ConductivityCriticalVariables +{ + enum ConductivityResidualEnum {CONDUCTIVITY_CRITICAL_SIMPLIFIED_OLCHOWY_SENGERS, + CONDUCTIVITY_CRITICAL_NOT_SET + }; + int type; + ConductivityCriticalSimplifiedOlchowySengers Olchowy_Sengers; + + ConductivityCriticalVariables(){type = CONDUCTIVITY_CRITICAL_NOT_SET;} +}; + /// Variables for the dilute gas part struct ViscosityDiluteGasCollisionIntegralData { @@ -118,13 +164,22 @@ public: VISCOSITY_HARDCODED_R23, VISCOSITY_NOT_HARDCODED }; + enum ConductivityDiluteEnum { + CONDUCTIVITY_HARDCODED_WATER, + CONDUCTIVITY_NOT_HARDCODED + }; ViscosityDiluteVariables viscosity_dilute; ViscosityInitialDensityVariables viscosity_initial; ViscosityHigherOrderVariables viscosity_higher_order; + ConductivityDiluteVariables conductivity_dilute; + ConductivityResidualVariables conductivity_residual; + ConductivityCriticalVariables conductivity_critical; + std::string BibTeX_viscosity, BibTeX_conductivity; long double sigma_eta, epsilon_over_k; - int hardcoded; - TransportPropertyData(){hardcoded = VISCOSITY_NOT_HARDCODED;}; + int hardcoded_viscosity, hardcoded_conductivity; + TransportPropertyData(){hardcoded_viscosity = VISCOSITY_NOT_HARDCODED; + hardcoded_conductivity = CONDUCTIVITY_NOT_HARDCODED;}; }; /** diff --git a/src/Backends/Helmholtz/Fluids/FluidLibrary.h b/src/Backends/Helmholtz/Fluids/FluidLibrary.h index 9fa46687..6b2bc630 100644 --- a/src/Backends/Helmholtz/Fluids/FluidLibrary.h +++ b/src/Backends/Helmholtz/Fluids/FluidLibrary.h @@ -9,9 +9,11 @@ #include #include - namespace CoolProp{ +// Forward declaration of the necessary debug function to avoid including the whole header +extern int get_debug_level(); + /// A container for the fluid parameters for the CoolProp fluids /** This container holds copies of all of the fluid instances for the fluids that are loaded in CoolProp. @@ -440,13 +442,13 @@ protected: if (viscosity.HasMember("hardcoded")){ std::string target = cpjson::get_string(viscosity,"hardcoded"); if (!target.compare("Water")){ - fluid.transport.hardcoded = CoolProp::TransportPropertyData::VISCOSITY_HARDCODED_WATER; return; + fluid.transport.hardcoded_viscosity = CoolProp::TransportPropertyData::VISCOSITY_HARDCODED_WATER; return; } else if (!target.compare("Helium")){ - fluid.transport.hardcoded = CoolProp::TransportPropertyData::VISCOSITY_HARDCODED_HELIUM; return; + fluid.transport.hardcoded_viscosity = CoolProp::TransportPropertyData::VISCOSITY_HARDCODED_HELIUM; return; } else if (!target.compare("R23")){ - fluid.transport.hardcoded = CoolProp::TransportPropertyData::VISCOSITY_HARDCODED_R23; return; + fluid.transport.hardcoded_viscosity = CoolProp::TransportPropertyData::VISCOSITY_HARDCODED_R23; return; } else{ throw ValueError(); @@ -475,20 +477,130 @@ protected: parse_higher_order_viscosity(viscosity["higher_order"], fluid); } }; + + /// Parse the transport properties + void parse_dilute_conductivity(rapidjson::Value &dilute, CoolPropFluid & fluid) + { + /*if (dilute.HasMember("hardcoded")){ + std::string target = cpjson::get_string(dilute, "hardcoded"); + if (!target.compare("Ethane")){ + fluid.transport.viscosity_dilute.type = CoolProp::ViscosityDiluteVariables::VISCOSITY_DILUTE_ETHANE; return; + } + }*/ + std::string type = cpjson::get_string(dilute, "type"); + if (!type.compare("ratio_of_polynomials")){ + // Get a reference to the entry in the fluid instance + CoolProp::ConductivityDiluteRatioPolynomialsData &data = fluid.transport.conductivity_dilute.ratio_polynomials; + + // Set the type flag + fluid.transport.conductivity_dilute.type = CoolProp::ConductivityDiluteVariables::CONDUCTIVITY_DILUTE_RATIO_POLYNOMIALS; + + // Load up the values + data.A = cpjson::get_long_double_array(dilute["A"]); + data.B = cpjson::get_long_double_array(dilute["B"]); + data.n = cpjson::get_long_double_array(dilute["n"]); + data.m = cpjson::get_long_double_array(dilute["m"]); + data.T_reducing = cpjson::get_double(dilute, "T_reducing"); + } + else{ + throw ValueError(format("type [%s] is not understood for fluid %s",type.c_str(),fluid.name.c_str())); + } + }; + + /// Parse the transport properties + void parse_residual_conductivity(rapidjson::Value &dilute, CoolPropFluid & fluid) + { + /*if (dilute.HasMember("hardcoded")){ + std::string target = cpjson::get_string(dilute, "hardcoded"); + if (!target.compare("Ethane")){ + fluid.transport.viscosity_dilute.type = CoolProp::ViscosityDiluteVariables::VISCOSITY_DILUTE_ETHANE; return; + } + }*/ + std::string type = cpjson::get_string(dilute, "type"); + if (!type.compare("polynomial")){ + // Get a reference to the entry in the fluid instance + CoolProp::ConductivityResidualPolynomialData &data = fluid.transport.conductivity_residual.polynomials; + + // Set the type flag + fluid.transport.conductivity_residual.type = CoolProp::ConductivityResidualVariables::CONDUCTIVITY_RESIDUAL_POLYNOMIAL; + + // Load up the values + data.B = cpjson::get_long_double_array(dilute["B"]); + data.d = cpjson::get_long_double_array(dilute["d"]); + data.t = cpjson::get_long_double_array(dilute["t"]); + data.T_reducing = cpjson::get_double(dilute, "T_reducing"); + data.rhomass_reducing = cpjson::get_double(dilute, "rhomass_reducing"); + } + else{ + throw ValueError(format("type [%s] is not understood for fluid %s",type.c_str(),fluid.name.c_str())); + } + }; + + void parse_critical_conductivity(rapidjson::Value &critical, CoolPropFluid & fluid) + { + /*if (dilute.HasMember("hardcoded")){ + std::string target = cpjson::get_string(dilute, "hardcoded"); + if (!target.compare("Ethane")){ + fluid.transport.viscosity_dilute.type = CoolProp::ViscosityDiluteVariables::VISCOSITY_DILUTE_ETHANE; return; + } + }*/ + std::string type = cpjson::get_string(critical, "type"); + if (!type.compare("simplified_Olchowy_Sengers")){ + //// Get a reference to the entry in the fluid instance + //CoolProp::ConductivityResidualPolynomialData &data = fluid.transport.conductivity_residual.polynomials; + + // Set the type flag + fluid.transport.conductivity_critical.type = CoolProp::ConductivityCriticalVariables::CONDUCTIVITY_CRITICAL_SIMPLIFIED_OLCHOWY_SENGERS; + } + else{ + throw ValueError(format("type [%s] is not understood for fluid %s",type.c_str(),fluid.name.c_str())); + } + }; + /// Parse the thermal conductivity data void parse_thermal_conductivity(rapidjson::Value &conductivity, CoolPropFluid & fluid) { + // Load dilute conductivity term + if (conductivity.HasMember("dilute")){ + parse_dilute_conductivity(conductivity["dilute"], fluid); + } + // Load residual conductivity term + if (conductivity.HasMember("residual")){ + parse_residual_conductivity(conductivity["residual"], fluid); + } + // Load critical conductivity term + if (conductivity.HasMember("critical")){ + parse_critical_conductivity(conductivity["critical"], fluid); + } }; /// Parse the transport properties void parse_transport(rapidjson::Value &transport, CoolPropFluid & fluid) { + //if (!fluid.name.compare("n-Hexane")){ + // rapidjson::Document dd; + // dd.SetObject(); + + // dd.AddMember("core",transport,dd.GetAllocator()); + // rapidjson::StringBuffer buffer; + // rapidjson::PrettyWriter writer(buffer); + + // dd.Accept(writer); + // std::string json0 = buffer.GetString(); + // //std::cout << json0 << std::endl; + + // FILE *fp; + // fp = fopen("nHexane_transport.json","w"); + // fprintf(fp,"%s",json0.c_str()); + // fclose(fp); + //} + // Parse viscosity if (transport.HasMember("viscosity")){ parse_viscosity(transport["viscosity"],fluid); } - // Parse thermal conductivity + // Parse thermal conductivity if (transport.HasMember("conductivity")){ parse_thermal_conductivity(transport["conductivity"],fluid); } @@ -582,7 +694,9 @@ public: // Surface tension if (!(fluid_json["ANCILLARIES"].HasMember("surface_tension"))){ - std::cout << format("Surface tension curves are missing for fluid [%s]\n", fluid.name.c_str()) ; + if (get_debug_level() > 0){ + std::cout << format("Surface tension curves are missing for fluid [%s]\n", fluid.name.c_str()) ; + } } else{ parse_surface_tension(fluid_json["ANCILLARIES"]["surface_tension"], fluid); @@ -590,7 +704,9 @@ public: // Parse the environmental parameters if (!(fluid_json.HasMember("ENVIRONMENTAL"))){ - std::cout << format("Environmental data are missing for fluid [%s]\n", fluid.name.c_str()) ; + if (get_debug_level() > 0){ + std::cout << format("Environmental data are missing for fluid [%s]\n", fluid.name.c_str()) ; + } } else{ parse_environmental(fluid_json["ENVIRONMENTAL"], fluid); diff --git a/src/Backends/Helmholtz/HelmholtzEOSMixtureBackend.cpp b/src/Backends/Helmholtz/HelmholtzEOSMixtureBackend.cpp index 093b51a6..fb10dbac 100644 --- a/src/Backends/Helmholtz/HelmholtzEOSMixtureBackend.cpp +++ b/src/Backends/Helmholtz/HelmholtzEOSMixtureBackend.cpp @@ -132,9 +132,9 @@ long double HelmholtzEOSMixtureBackend::calc_viscosity(void) { if (is_pure_or_pseudopure) { - if (components[0]->transport.hardcoded != CoolProp::TransportPropertyData::VISCOSITY_NOT_HARDCODED) + if (components[0]->transport.hardcoded_viscosity != CoolProp::TransportPropertyData::VISCOSITY_NOT_HARDCODED) { - switch(components[0]->transport.hardcoded) + switch(components[0]->transport.hardcoded_viscosity) { case CoolProp::TransportPropertyData::VISCOSITY_HARDCODED_WATER: return TransportRoutines::viscosity_water_hardcoded(*this); @@ -143,7 +143,7 @@ long double HelmholtzEOSMixtureBackend::calc_viscosity(void) case CoolProp::TransportPropertyData::VISCOSITY_HARDCODED_R23: return TransportRoutines::viscosity_R23_hardcoded(*this); default: - throw ValueError(format("hardcoded viscosity type [%d] is invalid for fluid %s", components[0]->transport.hardcoded, name().c_str())); + throw ValueError(format("hardcoded viscosity type [%d] is invalid for fluid %s", components[0]->transport.hardcoded_viscosity, name().c_str())); } } // Dilute part @@ -198,6 +198,58 @@ long double HelmholtzEOSMixtureBackend::calc_viscosity(void) throw NotImplementedError(format("viscosity not implemented for mixtures")); } } +long double HelmholtzEOSMixtureBackend::calc_conductivity(void) +{ + if (is_pure_or_pseudopure) + { + if (components[0]->transport.hardcoded_conductivity != CoolProp::TransportPropertyData::CONDUCTIVITY_NOT_HARDCODED) + { + switch(components[0]->transport.hardcoded_conductivity) + { + case CoolProp::TransportPropertyData::CONDUCTIVITY_HARDCODED_WATER: + return TransportRoutines::viscosity_water_hardcoded(*this); + default: + throw ValueError(format("hardcoded viscosity type [%d] is invalid for fluid %s", components[0]->transport.hardcoded_conductivity, name().c_str())); + } + } + + // Dilute part + long double lambda_dilute = _HUGE; + switch(components[0]->transport.conductivity_dilute.type) + { + case ConductivityDiluteVariables::CONDUCTIVITY_DILUTE_RATIO_POLYNOMIALS: + lambda_dilute = TransportRoutines::conductivity_dilute_ratio_polynomials(*this); break; + default: + throw ValueError(format("dilute conductivity type [%d] is invalid for fluid %s", components[0]->transport.conductivity_dilute.type, name().c_str())); + } + + // Residual part + long double lambda_residual = _HUGE; + switch(components[0]->transport.conductivity_residual.type) + { + case ConductivityResidualVariables::CONDUCTIVITY_RESIDUAL_POLYNOMIAL: + lambda_residual = TransportRoutines::conductivity_residual_polynomial(*this); break; + default: + throw ValueError(format("residual conductivity type [%d] is invalid for fluid %s", components[0]->transport.conductivity_residual.type, name().c_str())); + } + + // Critical part + long double lambda_critical = _HUGE; + switch(components[0]->transport.conductivity_critical.type) + { + case ConductivityCriticalVariables::CONDUCTIVITY_CRITICAL_SIMPLIFIED_OLCHOWY_SENGERS: + lambda_critical = TransportRoutines::conductivity_critical_simplified_Olchowy_Sengers(*this); break; + default: + throw ValueError(format("critical conductivity type [%d] is invalid for fluid %s", components[0]->transport.viscosity_dilute.type, name().c_str())); + } + + return lambda_dilute + lambda_residual + lambda_critical; + } + else + { + throw NotImplementedError(format("viscosity not implemented for mixtures")); + } +} long double HelmholtzEOSMixtureBackend::calc_Ttriple(void) { double summer = 0; diff --git a/src/Backends/Helmholtz/HelmholtzEOSMixtureBackend.h b/src/Backends/Helmholtz/HelmholtzEOSMixtureBackend.h index e2f219a9..95c03135 100644 --- a/src/Backends/Helmholtz/HelmholtzEOSMixtureBackend.h +++ b/src/Backends/Helmholtz/HelmholtzEOSMixtureBackend.h @@ -118,6 +118,7 @@ public: long double calc_surface_tension(void); long double calc_viscosity(void); + long double calc_conductivity(void); long double calc_Tmax(void); long double calc_pmax(void); diff --git a/src/Backends/Helmholtz/TransportRoutines.cpp b/src/Backends/Helmholtz/TransportRoutines.cpp index 5ce36ef4..97971fcd 100644 --- a/src/Backends/Helmholtz/TransportRoutines.cpp +++ b/src/Backends/Helmholtz/TransportRoutines.cpp @@ -445,4 +445,57 @@ long double TransportRoutines::viscosity_ethane_higher_order_hardcoded(Helmholtz return 15.977*sum1/(1+sum2)/1e6; } +long double TransportRoutines::conductivity_dilute_ratio_polynomials(HelmholtzEOSMixtureBackend &HEOS){ + if (HEOS.is_pure_or_pseudopure) + { + // Retrieve values from the state class + CoolProp::ConductivityDiluteRatioPolynomialsData &data = HEOS.components[0]->transport.conductivity_dilute.ratio_polynomials; + + long double summer1 = 0, summer2 = 0, Tr = HEOS.T()/data.T_reducing; + for (std::size_t i = 0; i < data.A.size(); ++i) + { + summer1 += data.A[i]*pow(Tr, data.n[i]); + } + for (std::size_t i = 0; i < data.B.size(); ++i) + { + summer2 += data.B[i]*pow(Tr, data.m[i]); + } + + return summer1/summer2; + } + else{ + throw NotImplementedError("TransportRoutines::conductivity_dilute_ratio_polynomials is only for pure and pseudo-pure"); + } +}; + +long double TransportRoutines::conductivity_residual_polynomial(HelmholtzEOSMixtureBackend &HEOS){ + if (HEOS.is_pure_or_pseudopure) + { + // Retrieve values from the state class + CoolProp::ConductivityResidualPolynomialData &data = HEOS.components[0]->transport.conductivity_residual.polynomials; + + long double summer = 0, tau = data.T_reducing/HEOS.T(), delta = HEOS.keyed_output(CoolProp::iDmass)/data.rhomass_reducing; + for (std::size_t i = 0; i < data.B.size(); ++i) + { + summer += data.B[i]*pow(tau, data.t[i])*pow(delta, data.d[i]); + } + return summer; + } + else{ + throw NotImplementedError("TransportRoutines::conductivity_residual_polynomial is only for pure and pseudo-pure"); + } +}; + +long double TransportRoutines::conductivity_critical_simplified_Olchowy_Sengers(HelmholtzEOSMixtureBackend &HEOS){ + if (HEOS.is_pure_or_pseudopure) + { + return 0; + } + else{ + throw NotImplementedError("TransportRoutines::conductivity_critical_simplified_Olchowy_Sengers is only for pure and pseudo-pure"); + } +}; + + + }; /* namespace CoolProp */ \ No newline at end of file diff --git a/src/Backends/Helmholtz/TransportRoutines.h b/src/Backends/Helmholtz/TransportRoutines.h index 978eeb0c..bd45190f 100644 --- a/src/Backends/Helmholtz/TransportRoutines.h +++ b/src/Backends/Helmholtz/TransportRoutines.h @@ -40,7 +40,7 @@ public: \f[ \eta^0 = \displaystyle\sum_ia_iT^{t_i} \f] - with T in K, \f$eta^0\f$ in Pa-s + with T in K, \f$\eta^0\f$ in Pa-s */ static long double viscosity_dilute_powers_of_T(HelmholtzEOSMixtureBackend &HEOS); @@ -83,18 +83,82 @@ public: static long double viscosity_higher_order_modified_Batschinski_Hildebrand(HelmholtzEOSMixtureBackend &HEOS); static long double viscosity_dilute_ethane(HelmholtzEOSMixtureBackend &HEOS); - static long double viscosity_ethane_higher_order_hardcoded(HelmholtzEOSMixtureBackend &HEOS); static long double viscosity_water_hardcoded(HelmholtzEOSMixtureBackend &HEOS); - static long double viscosity_helium_hardcoded(HelmholtzEOSMixtureBackend &HEOS); static long double viscosity_R23_hardcoded(HelmholtzEOSMixtureBackend &HEOS); + static long double viscosity_ethane_higher_order_hardcoded(HelmholtzEOSMixtureBackend &HEOS); static long double viscosity_hydrogen_higher_order_hardcoded(HelmholtzEOSMixtureBackend &HEOS); - static long double viscosity_hexane_higher_order_hardcoded(HelmholtzEOSMixtureBackend &HEOS); - static long double viscosity_higher_order_friction_theory(HelmholtzEOSMixtureBackend &HEOS); + + /** + \brief The general dilute gas conductivity term formed of a ratio of polynomial like terms + + \f[ + \lambda^0 = \frac{A_i\displaystyle\sum_iT_r^{n_i}}{B_i\displaystyle\sum_iT_r^{m_i}} + \f] + with \f$\lambda^0\f$ in W/m/K, T_r is the reduced temperature \f$T_{r} = T/T_{red}\f$ + */ + static long double conductivity_dilute_ratio_polynomials(HelmholtzEOSMixtureBackend &HEOS); + + /** + + This term is given by + \f[ + \Delta\lambda(\rho,T) = \displaystyle\sum_iA_i\tau^{t,i}\delta^{d_i} + \f] + + As used by Assael, Perkins, Huber, etc., the residual term is given by + \f[ + \Delta\lambda(\rho,T) = \displaystyle\sum_i(B_{1,i}+B_{2,i}(T/T_c))(\rho/\rho_c)^i + \f] + which can be easily converted by noting that \f$\tau=Tc/T\f$ and \f$\delta=\rho/\rho_c\f$ + */ + static long double conductivity_residual_polynomial(HelmholtzEOSMixtureBackend &HEOS); + + /** + \brief The simplified critical conductivity term of Olchowy and Sengers + + Olchowy, G. A. & Sengers, J. V. (1989), "A Simplified Representation for the Thermal Conductivity of Fluids in the Critical Region", International Journal of Thermophysics, 10, (2), 417-426 + + \f[ + \lambda^{(c)} = \frac{\rho c_p R_DkT}{6\pi\eta\zeta}(\Omega-\Omega_0) + \f] + \f[ + \Omega = \frac{2}{\pi}\left[ \left( \frac{c_p-c_v}{c_p}\right)\arctan(q_d\zeta)+\frac{c_v}{c_p}q_d\zeta \right] + \f] + \f[ + \Omega_0 = \frac{2}{\pi}\left[1-\exp\left(-\frac{1}{(q_d\zeta)^{-1}+(q_d\zeta\rho_c/\rho)^2/3} \right) \right] + \f] + \f[ + \zeta = \zeta_0\left(\frac{p_c\rho}{\Gamma\rho_c^2}\right)^{\nu/\gamma}\left[\left.\frac{\partial \rho(T,\rho)}{\partial p} \right|_{T}- \frac{T_R}{T}\left.\frac{\partial \rho(T_R,\rho)}{\partial p} \right|_{T} \right]^{\nu/\gamma}, + \f] + where \f$\lambda^{(c)}\f$ is in W\f$\cdot\f$m\f$^{-1}\f$\f$\cdot\f$K\f$^{-1}\f$, \f$\zeta\f$ is in m, + \f$c_p\f$ and \f$c_v\f$ are in J\f$\cdot\f$kg\f$^{-1}\cdot\f$K\f$^{-1}\f$, \f$p\f$ and \f$p_c\f$ are in Pa, + \f$\rho\f$ and \f$\rho_c\f$ are in mol\f$\cdot\f$m\f$^{-3}\f$, \f$\eta\f$ is the viscosity in Pa\f$\cdot\f$s, + and the remaining parameters are defined in the following tables. + + Coefficients for use in the simplified Olchowy-Sengers critical term + Parameter | Variable | Value + --------- | -------- | ------ + Boltzmann constant | \f$k\f$ | \f$1.3806488\times 10^{-23}\f$ J\f$\cdot\f$K\f$^{-1}\f$ + Universal amplitude | \f$R_D\f$ | 1.03 + Critical exponent | \f$\nu\f$ | 0.63 + Critical exponent | \f$\gamma\f$ | 1.239 + Reference temperature | \f$T_R\f$ | 1.5\f$T_c\f$ + + Recommended default constants (see Huber (I&ECR, 2003)) + Parameter | Variable | Value + --------- | -------- | ------ + Amplitude | \f$\Gamma\f$ | 0.0496 + Amplitude |\f$\zeta_0\f$ | 1.94 \f$\times\f$ 10\f$^{-10}\f$ m + Effective cutoff | \f$q_d\f$ | 2 \f$\times\f$ 10\f$^{9}\f$ m + + */ + static long double conductivity_critical_simplified_Olchowy_Sengers(HelmholtzEOSMixtureBackend &HEOS); + }; /* class TransportRoutines */ }; /* namespace CoolProp */ diff --git a/src/Tests/CoolProp-Tests.cpp b/src/Tests/CoolProp-Tests.cpp index b1de59ee..3ffb8dfd 100644 --- a/src/Tests/CoolProp-Tests.cpp +++ b/src/Tests/CoolProp-Tests.cpp @@ -11,9 +11,9 @@ #include "catch.hpp" -namespace ViscosityValidation{ +namespace TransportValidation{ -// A structure to hold the values for one validation call for viscosity +// A structure to hold the values for one validation call struct vel { public: @@ -22,7 +22,8 @@ public: vel(std::string fluid, std::string in1, double v1, std::string in2, double v2, std::string out, double expected, double tol) { this->in1 = in1; this->in2 = in2; this->fluid = fluid; - this->v1 = v1; this->v2 = v2; this->expected = expected; this->tol = tol; + this->v1 = v1; this->v2 = v2; this->expected = expected; + this->tol = tol; }; }; @@ -199,15 +200,15 @@ vel("R134a", "T", 360, "Q", 1, "V", 1.7140264998576107e-005, 1e-4), }; -class ViscosityValidationFixture +class TransportValidationFixture { protected: long double actual, x1, x2; CoolProp::AbstractState *pState; int pair; public: - ViscosityValidationFixture(){ pState = NULL; } - ~ViscosityValidationFixture(){ delete pState; } + TransportValidationFixture(){ pState = NULL; } + ~TransportValidationFixture(){ delete pState; } void set_backend(std::string backend, std::string fluid_name){ pState = CoolProp::AbstractState::factory(backend, fluid_name); } @@ -218,13 +219,13 @@ public: long pair = CoolProp::generate_update_pair(iin1, v1, iin2, v2, o1, o2); pState->update(pair, o1, o2); } - void get_value() + void get_value(long key) { - actual = pState->viscosity(); + actual = pState->keyed_output(key); } }; -TEST_CASE_METHOD(ViscosityValidationFixture, "Compare viscosities against published data", "[viscosity]") +TEST_CASE_METHOD(TransportValidationFixture, "Compare viscosities against published data", "[viscosity]") { int inputsN = sizeof(viscosity_validation_data)/sizeof(viscosity_validation_data[0]); for (int i = 0; i < inputsN; ++i) @@ -238,14 +239,44 @@ TEST_CASE_METHOD(ViscosityValidationFixture, "Compare viscosities against publis CAPTURE(el.in2); CAPTURE(el.v2); CHECK_NOTHROW(set_pair(el.in1, el.v1, el.in2, el.v2)); - get_value(); + get_value(CoolProp::iviscosity); CAPTURE(el.expected); CAPTURE(actual); CHECK(fabs(actual/el.expected-1) < el.tol); } } -}; /* namespace ViscosityValidation */ +vel conductivity_validation_data[] = { +// From Assael, JPCRD, 2013 +vel("Hexane", "T", 250, "Dmass", 700, "L", 137.62e-3, 1e-3), +vel("Hexane", "T", 400, "Dmass", 2, "L", 23.558e-3, 1e-3), +vel("Hexane", "T", 400, "Dmass", 650, "L", 129.28e-3, 1e-3), +vel("Hexane", "T", 510, "Dmass", 2, "L", 36.772e-3, 1e-3), + +}; + +TEST_CASE_METHOD(TransportValidationFixture, "Compare thermal conductivities against published data", "[conductivity]") +{ + int inputsN = sizeof(conductivity_validation_data)/sizeof(conductivity_validation_data[0]); + for (int i = 0; i < inputsN; ++i) + { + vel el = conductivity_validation_data[i]; + CHECK_NOTHROW(set_backend("HEOS", el.fluid)); + CAPTURE(el.fluid); + CAPTURE(el.in1); + CAPTURE(el.v1); + CAPTURE(el.in2); + CAPTURE(el.v2); + CHECK_NOTHROW(set_pair(el.in1, el.v1, el.in2, el.v2)); + get_value(CoolProp::iconductivity); + CAPTURE(el.expected); + CAPTURE(actual); + CHECK(fabs(actual/el.expected-1) < el.tol); + } +} + + +}; /* namespace TransportValidation */ static int inputs[] = { CoolProp::DmolarT_INPUTS,