Cantera  2.5.1
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 
13 namespace 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 
51 WaterProps::~WaterProps()
52 {
53  if (m_own_sub) {
54  delete m_waterIAPWS;
55  }
56 }
57 
58 doublereal 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 
106 doublereal 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 
158 doublereal 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, i.e., 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 
231 doublereal WaterProps::satPressure(doublereal T)
232 {
233  return m_waterIAPWS->psat(T);
234 }
235 
236 doublereal WaterProps::density_IAPWS(doublereal temp, doublereal press)
237 {
238  return m_waterIAPWS->density(temp, press, WATER_LIQUID);
239 }
240 
241 doublereal WaterProps::density_IAPWS() const
242 {
243  return m_waterIAPWS->density();
244 }
245 
246 doublereal 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 
256 doublereal 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 Avogadro
Avogadro's Number [number/kmol].
Definition: ct_defs.h:63
const double epsilon_0
Permittivity of free space [F/m].
Definition: ct_defs.h:129
const double GasConstant
Universal Gas Constant [J/kmol/K].
Definition: ct_defs.h:109
const double ElectronCharge
Elementary charge [C].
Definition: ct_defs.h:72
const double Pi
Pi.
Definition: ct_defs.h:53
Namespace for the Cantera kernel.
Definition: AnyMap.cpp:264
Contains declarations for string manipulation functions within Cantera.