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
9#include "cantera/base/ctml.h"
12
13namespace Cantera
14{
16 m_waterIAPWS(0),
17 m_own_sub(false)
18{
19 // object owns its own water evaluator
21 m_own_sub = true;
22}
23
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 {
34 m_own_sub = true;
35 }
36}
37
39 m_waterIAPWS(0),
40 m_own_sub(false)
41{
42 if (waterIAPWS) {
43 m_waterIAPWS = waterIAPWS;
44 m_own_sub = false;
45 } else {
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
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 }
264}
265
266}
Implementation of a pressure dependent standard state virtual function for a Pure Water Phase (see Sp...
Header for a class used to house several approximation routines for properties of water.
Base class for exceptions thrown by Cantera classes.
Definition: ctexceptions.h:61
Class for the liquid water pressure dependent standard state.
Definition: PDSS_Water.h:50
WaterPropsIAPWS * getWater()
Get a pointer to a changeable WaterPropsIAPWS object.
Definition: PDSS_Water.h:142
Class for calculating the equation of state of water.
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.
doublereal coeffThermExp() const
Returns the coefficient of thermal expansion.
doublereal psat(doublereal temperature, int waterState=WATER_LIQUID)
This function returns the saturation pressure given the temperature as an input parameter,...
doublereal isothermalCompressibility() const
Returns the coefficient of isothermal compressibility for the state of the object.
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
WaterPropsIAPWS * m_waterIAPWS
Pointer to the WaterPropsIAPWS object.
Definition: WaterProps.h:246
doublereal coeffThermalExp_IAPWS(doublereal T, doublereal P)
returns the coefficient of thermal expansion
Definition: WaterProps.cpp:246
doublereal density_IAPWS() const
Returns the density of water.
Definition: WaterProps.cpp:241
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
doublereal isothermalCompressibility_IAPWS(doublereal T, doublereal P)
Returns the isothermal compressibility of water.
Definition: WaterProps.cpp:256
WaterProps()
Default constructor.
Definition: WaterProps.cpp:15
static doublereal density_T(doublereal T, doublereal P, int ifunc)
Simple calculation of water density at atmospheric pressure.
Definition: WaterProps.cpp:58
bool m_own_sub
true if we own the WaterPropsIAPWS object
Definition: WaterProps.h:249
doublereal satPressure(doublereal T)
Returns the saturation pressure given the temperature.
Definition: WaterProps.cpp:231
CTML ("Cantera Markup Language") is the variant of XML that Cantera uses to store data.
const double Pi
Pi.
Definition: ct_defs.h:52
Namespace for the Cantera kernel.
Definition: AnyMap.h:29
const double Avogadro
Avogadro's Number [number/kmol].
Definition: ct_defs.h:66
const double epsilon_0
Permittivity of free space [F/m].
Definition: ct_defs.h:134
const double GasConstant
Universal Gas Constant [J/kmol/K].
Definition: ct_defs.h:113
const double ElectronCharge
Elementary charge [C].
Definition: ct_defs.h:75
Contains declarations for string manipulation functions within Cantera.