Cantera 2.6.0

WaterProps.cpp
Go to the documentation of this file.
1/**
2 * @file WaterProps.cpp
3 */
4
5// This file is part of Cantera. See License.txt in the top-level directory or
6// at https://cantera.org/license.txt for license and copyright information.
7
8#include "cantera/thermo/WaterProps.h"
9#include "cantera/base/ctml.h"
10#include "cantera/thermo/PDSS_Water.h"
11#include "cantera/base/stringUtils.h"
12
13 namespace Cantera
14{
15 WaterProps::WaterProps():
16 m_waterIAPWS(0),
17 m_own_sub(false)
18{
19 // object owns its own water evaluator
20 m_waterIAPWS = new WaterPropsIAPWS();
21 m_own_sub = true;
22}
23
24 WaterProps::WaterProps(PDSS_Water* wptr) :
25 m_waterIAPWS(0),
26 m_own_sub(false)
27{
28 if (wptr) {
29 // object in slave mode; it doesn't own its own water evaluator.
30 m_waterIAPWS = wptr->getWater();
31 m_own_sub = false;
32 } else {
33 m_waterIAPWS = new WaterPropsIAPWS();
34 m_own_sub = true;
35 }
36}
37
38 WaterProps::WaterProps(WaterPropsIAPWS* waterIAPWS) :
39 m_waterIAPWS(0),
40 m_own_sub(false)
41{
42 if (waterIAPWS) {
43 m_waterIAPWS = waterIAPWS;
44 m_own_sub = false;
45 } else {
46 m_waterIAPWS = new WaterPropsIAPWS();
47 m_own_sub = true;
48 }
49}
50
51WaterProps::~WaterProps()
52{
53 if (m_own_sub) {
54 delete m_waterIAPWS;
55 }
56}
57
58doublereal WaterProps::density_T(doublereal T, doublereal P, int ifunc)
59{
60 static const doublereal Tc = T - 273.15;
61 static const doublereal U1 = 288.9414;
62 static const doublereal U2 = 508929.2;
63 static const doublereal U3 = 68.12963;
64 static const doublereal U4 = -3.9863;
65
66 doublereal tmp1 = Tc + U1;
67 doublereal tmp4 = Tc + U4;
68 doublereal t4t4 = tmp4 * tmp4;
69 doublereal tmp3 = Tc + U3;
70 doublereal rho = 1000. * (1.0 - tmp1*t4t4/(U2 * tmp3));
71
72 // Impose an ideal gas lower bound on rho. We need this to ensure positivity
73 // of rho, even though it is grossly unrepresentative.
74 doublereal rhomin = P / (GasConstant * T);
75 if (rho < rhomin) {
76 rho = rhomin;
77 if (ifunc == 1) {
78 return - rhomin / T;
79 } else if (ifunc == 3) {
80 return rhomin / P;
81 } else if (ifunc == 2) {
82 return 2.0 * rhomin / (T * T);
83 }
84 }
85
86 if (ifunc == 1) {
87 doublereal drhodT = 1000./U2 * (
88 - tmp4 * tmp4 / (tmp3)
89 - tmp1 * 2 * tmp4 / (tmp3)
90 + tmp1 * t4t4 / (tmp3*tmp3)
91 );
92 return drhodT;
93 } else if (ifunc == 3) {
94 return 0.0;
95 } else if (ifunc == 2) {
96 doublereal t3t3 = tmp3 * tmp3;
97 doublereal d2rhodT2 = 1000./U2 *
98 ((-4.0*tmp4-2.0*tmp1)/tmp3 +
99 (2.0*t4t4 + 4.0*tmp1*tmp4)/t3t3
100 - 2.0*tmp1 * t4t4/(t3t3*tmp3));
101 return d2rhodT2;
102 }
103 return rho;
104}
105
106doublereal WaterProps::relEpsilon(doublereal T, doublereal P_pascal,
107 int ifunc)
108{
109 static const doublereal U1 = 3.4279E2;
110 static const doublereal U2 = -5.0866E-3;
111 static const doublereal U3 = 9.4690E-7;
112 static const doublereal U4 = -2.0525;
113 static const doublereal U5 = 3.1159E3;
114 static const doublereal U6 = -1.8289E2;
115 static const doublereal U7 = -8.0325E3;
116 static const doublereal U8 = 4.2142E6;
117 static const doublereal U9 = 2.1417;
118 doublereal T2 = T * T;
119
120 doublereal eps1000 = U1 * exp(U2 * T + U3 * T2);
121 doublereal C = U4 + U5/(U6 + T);
122 doublereal B = U7 + U8/T + U9 * T;
123 doublereal Pbar = P_pascal * 1.0E-5;
124 doublereal tmpBpar = B + Pbar;
125 doublereal tmpB1000 = B + 1000.0;
126 doublereal ltmp = log(tmpBpar/tmpB1000);
127 doublereal epsRel = eps1000 + C * ltmp;
128
129 if (ifunc == 1 || ifunc == 2) {
130 doublereal tmpC = U6 + T;
131 doublereal dCdT = - U5/(tmpC * tmpC);
132 doublereal dBdT = - U8/(T * T) + U9;
133 doublereal deps1000dT = eps1000 * (U2 + 2.0 * U3 * T);
134 doublereal dltmpdT = (dBdT/tmpBpar - dBdT/tmpB1000);
135 if (ifunc == 1) {
136 return deps1000dT + dCdT * ltmp + C * dltmpdT;
137 }
138 doublereal T3 = T2 * T;
139 doublereal d2CdT2 = - 2.0 * dCdT / tmpC;
140 doublereal d2BdT2 = 2.0 * U8 / (T3);
141 doublereal d2ltmpdT2 = (d2BdT2*(1.0/tmpBpar - 1.0/tmpB1000) +
142 dBdT*dBdT*(1.0/(tmpB1000*tmpB1000) - 1.0/(tmpBpar*tmpBpar)));
143 doublereal d2eps1000dT2 = (deps1000dT * (U2 + 2.0 * U3 * T) + eps1000 * (2.0 * U3));
144
145 if (ifunc == 2) {
146 doublereal d2epsReldT2 = (d2eps1000dT2 + d2CdT2 * ltmp + 2.0 * dCdT * dltmpdT
147 + C * d2ltmpdT2);
148 return d2epsReldT2;
149 }
150 }
151 if (ifunc == 3) {
152 doublereal dltmpdP = 1.0E-5 / tmpBpar;
153 return C * dltmpdP;
154 }
155 return epsRel;
156}
157
158doublereal WaterProps::ADebye(doublereal T, doublereal P_input, int ifunc)
159{
160 doublereal psat = satPressure(T);
161 doublereal P;
162 if (psat > P_input) {
163 P = psat;
164 } else {
165 P = P_input;
166 }
167 doublereal epsRelWater = relEpsilon(T, P, 0);
168 doublereal epsilon = epsilon_0 * epsRelWater;
169 doublereal dw = density_IAPWS(T, P);
170 doublereal tmp = sqrt(2.0 * Avogadro * dw / 1000.);
171 doublereal tmp2 = ElectronCharge * ElectronCharge * Avogadro /
172 (epsilon * GasConstant * T);
173 doublereal tmp3 = tmp2 * sqrt(tmp2);
174 doublereal A_Debye = tmp * tmp3 / (8.0 * Pi);
175
176 // dAdT = - 3/2 Ad/T + 1/2 Ad/dw d(dw)/dT - 3/2 Ad/eps d(eps)/dT
177 // dAdT = - 3/2 Ad/T - 1/2 Ad/Vw d(Vw)/dT - 3/2 Ad/eps d(eps)/dT
178 if (ifunc == 1 || ifunc == 2) {
179 doublereal dAdT = - 1.5 * A_Debye / T;
180
181 doublereal depsRelWaterdT = relEpsilon(T, P, 1);
182 dAdT -= A_Debye * (1.5 * depsRelWaterdT / epsRelWater);
183
184 // calculate d(lnV)/dT _constantP, that is, the cte
185 doublereal cte = coeffThermalExp_IAPWS(T, P);
186 doublereal contrib2 = - A_Debye * (0.5 * cte);
187 dAdT += contrib2;
188
189 if (ifunc == 1) {
190 return dAdT;
191 }
192
193 if (ifunc == 2) {
194 // Get the second derivative of the dielectric constant wrt T
195 // -> we will take each of the terms in dAdT and differentiate
196 // it again.
197 doublereal d2AdT2 = 1.5 / T * (A_Debye/T - dAdT);
198 doublereal d2epsRelWaterdT2 = relEpsilon(T, P, 2);
199 d2AdT2 += 1.5 * (- dAdT * depsRelWaterdT / epsRelWater
200 - A_Debye / epsRelWater *
201 (d2epsRelWaterdT2 - depsRelWaterdT * depsRelWaterdT / epsRelWater));
202 doublereal deltaT = -0.1;
203 doublereal Tdel = T + deltaT;
204 doublereal cte_del = coeffThermalExp_IAPWS(Tdel, P);
205 doublereal dctedT = (cte_del - cte) / Tdel;
206 doublereal contrib3 = 0.5 * (-(dAdT * cte) -(A_Debye * dctedT));
207 d2AdT2 += contrib3;
208 return d2AdT2;
209 }
210 }
211
212 // A_Debye = (1/(8 Pi)) sqrt(2 Na dw / 1000)
213 // (e e/(epsilon R T))^3/2
214 //
215 // dAdP = + 1/2 Ad/dw d(dw)/dP - 3/2 Ad/eps d(eps)/dP
216 // dAdP = - 1/2 Ad/Vw d(Vw)/dP - 3/2 Ad/eps d(eps)/dP
217 // dAdP = + 1/2 Ad * kappa - 3/2 Ad/eps d(eps)/dP
218 //
219 // where kappa = - 1/Vw d(Vw)/dP_T (isothermal compressibility)
220 if (ifunc == 3) {
221 doublereal dAdP = 0.0;
222 doublereal depsRelWaterdP = relEpsilon(T, P, 3);
223 dAdP -= A_Debye * (1.5 * depsRelWaterdP / epsRelWater);
224 doublereal kappa = isothermalCompressibility_IAPWS(T,P);
225 dAdP += A_Debye * (0.5 * kappa);
226 return dAdP;
227 }
228 return A_Debye;
229}
230
231doublereal WaterProps::satPressure(doublereal T)
232{
233 return m_waterIAPWS->psat(T);
234}
235
236doublereal WaterProps::density_IAPWS(doublereal temp, doublereal press)
237{
238 return m_waterIAPWS->density(temp, press, WATER_LIQUID);
239}
240
241doublereal WaterProps::density_IAPWS() const
242{
243 return m_waterIAPWS->density();
244}
245
246doublereal WaterProps::coeffThermalExp_IAPWS(doublereal temp, doublereal press)
247{
248 doublereal dens = m_waterIAPWS->density(temp, press, WATER_LIQUID);
249 if (dens < 0.0) {
250 throw CanteraError("WaterProps::coeffThermalExp_IAPWS",
251 "Unable to solve for density at T = {} and P = {}", temp, press);
252 }
253 return m_waterIAPWS->coeffThermExp();
254}
255
256doublereal WaterProps::isothermalCompressibility_IAPWS(doublereal temp, doublereal press)
257{
258 doublereal dens = m_waterIAPWS->density(temp, press, WATER_LIQUID);
259 if (dens < 0.0) {
260 throw CanteraError("WaterProps::isothermalCompressibility_IAPWS",
261 "Unable to solve for density at T = {} and P = {}", temp, press);
262 }
263 return m_waterIAPWS->isothermalCompressibility();
264}
265
266}
PDSS_Water.h
Implementation of a pressure dependent standard state virtual function for a Pure Water Phase (see Sp...
WaterProps.h
Header for a class used to house several approximation routines for properties of water.
Cantera::CanteraError
Base class for exceptions thrown by Cantera classes.
Definition: ctexceptions.h:61
Cantera::PDSS_Water
Class for the liquid water pressure dependent standard state.
Definition: PDSS_Water.h:50
Cantera::PDSS_Water::getWater
WaterPropsIAPWS * getWater()
Get a pointer to a changeable WaterPropsIAPWS object.
Definition: PDSS_Water.h:142
Cantera::WaterPropsIAPWS
Class for calculating the equation of state of water.
Definition: WaterPropsIAPWS.h:163
Cantera::WaterPropsIAPWS::density
doublereal density(doublereal temperature, doublereal pressure, int phase=-1, doublereal rhoguess=-1.0)
Calculates the density given the temperature and the pressure, and a guess at the density.
Definition: WaterPropsIAPWS.cpp:78
Cantera::WaterPropsIAPWS::coeffThermExp
doublereal coeffThermExp() const
Returns the coefficient of thermal expansion.
Definition: WaterPropsIAPWS.cpp:259
Cantera::WaterPropsIAPWS::psat
doublereal psat(doublereal temperature, int waterState=WATER_LIQUID)
This function returns the saturation pressure given the temperature as an input parameter,...
Definition: WaterPropsIAPWS.cpp:323
Cantera::WaterPropsIAPWS::isothermalCompressibility
doublereal isothermalCompressibility() const
Returns the coefficient of isothermal compressibility for the state of the object.
Definition: WaterPropsIAPWS.cpp:240
Cantera::WaterProps::ADebye
doublereal ADebye(doublereal T, doublereal P, int ifunc)
ADebye calculates the value of A_Debye as a function of temperature and pressure according to relatio...
Definition: WaterProps.cpp:158
Cantera::WaterProps::m_waterIAPWS
WaterPropsIAPWS * m_waterIAPWS
Pointer to the WaterPropsIAPWS object.
Definition: WaterProps.h:246
Cantera::WaterProps::coeffThermalExp_IAPWS
doublereal coeffThermalExp_IAPWS(doublereal T, doublereal P)
returns the coefficient of thermal expansion
Definition: WaterProps.cpp:246
Cantera::WaterProps::density_IAPWS
doublereal density_IAPWS() const
Returns the density of water.
Definition: WaterProps.cpp:241
Cantera::WaterProps::relEpsilon
doublereal relEpsilon(doublereal T, doublereal P_pascal, int ifunc=0)
Bradley-Pitzer equation for the dielectric constant of water as a function of temperature and pressur...
Definition: WaterProps.cpp:106
Cantera::WaterProps::isothermalCompressibility_IAPWS
doublereal isothermalCompressibility_IAPWS(doublereal T, doublereal P)
Returns the isothermal compressibility of water.
Definition: WaterProps.cpp:256
Cantera::WaterProps::WaterProps
WaterProps()
Default constructor.
Definition: WaterProps.cpp:15
Cantera::WaterProps::density_T
static doublereal density_T(doublereal T, doublereal P, int ifunc)
Simple calculation of water density at atmospheric pressure.
Definition: WaterProps.cpp:58
Cantera::WaterProps::m_own_sub
bool m_own_sub
true if we own the WaterPropsIAPWS object
Definition: WaterProps.h:249
Cantera::WaterProps::satPressure
doublereal satPressure(doublereal T)
Returns the saturation pressure given the temperature.
Definition: WaterProps.cpp:231
ctml.h
CTML ("Cantera Markup Language") is the variant of XML that Cantera uses to store data.
Cantera::Pi
const double Pi
Pi.
Definition: ct_defs.h:52
Cantera
Namespace for the Cantera kernel.
Definition: AnyMap.cpp:557
Cantera::Avogadro
const double Avogadro
Avogadro's Number [number/kmol].
Definition: ct_defs.h:66
Cantera::epsilon_0
const double epsilon_0
Permittivity of free space [F/m].
Definition: ct_defs.h:134
Cantera::GasConstant
const double GasConstant
Universal Gas Constant [J/kmol/K].
Definition: ct_defs.h:113
Cantera::ElectronCharge
const double ElectronCharge
Elementary charge [C].
Definition: ct_defs.h:75
stringUtils.h
Contains declarations for string manipulation functions within Cantera.