OGS
Adsorption.cpp
Go to the documentation of this file.
1
10#include "Adsorption.h"
11
12#include "BaseLib/Logging.h"
14
15namespace
16{
17// Evaluate adsorbtion potential A
18double getPotential(const double p_Ads, const double T_Ads, const double M_Ads)
19{
21 std::log(
23 T_Ads) /
24 p_Ads) /
25 (M_Ads * 1.e3); // in kJ/kg = J/g
26}
27
28constexpr double k_rate = 6.0e-3; // to be specified
29
30template <typename T>
31T square(const T& v)
32{
33 return v * v;
34}
35} // namespace
36
37namespace Adsorption
38{
39// Saturation pressure for water used in Nunez
41{
42 // critical T and p
43 const double Tc = 647.3; // K
44 const double pc = 221.2e5; // Pa
45 // dimensionless T
46 const double Tr = T_Ads / Tc;
47 const double theta = 1. - Tr;
48 // empirical constants
49 const double c[] = {-7.69123, -26.08023, -168.17065, 64.23285, -118.96462,
50 4.16717, 20.97506, 1.0e9, 6.0};
51 const double K[] = {
52 c[0] * theta + c[1] * std::pow(theta, 2) + c[2] * std::pow(theta, 3) +
53 c[3] * std::pow(theta, 4) + c[4] * std::pow(theta, 5),
54 1. + c[5] * theta + c[6] * std::pow(theta, 2)};
55
56 const double exponent =
57 K[0] / (K[1] * Tr) - theta / (c[7] * std::pow(theta, 2) + c[8]);
58 return pc * std::exp(exponent); // in Pa
59}
60
61// Evaporation enthalpy of water from Nunez
62double AdsorptionReaction::getEvaporationEnthalpy(double T_Ads) // in kJ/kg
63{
64 T_Ads -= 273.15;
65 if (T_Ads <= 10.)
66 {
67 const double c[] = {2.50052e3, -2.1068, -3.57500e-1,
68 1.905843e-1, -5.11041e-2, 7.52511e-3,
69 -6.14313e-4, 2.59674e-5, -4.421e-7};
70 double hv = 0.;
71 for (size_t i = 0; i < sizeof(c) / sizeof(c[0]); i++)
72 {
73 hv += c[i] * std::pow(T_Ads, i);
74 }
75 return hv;
76 }
77 if (T_Ads <= 300.)
78 {
79 const double c[] = {2.50043e3, -2.35209, 1.91685e-4, -1.94824e-5,
80 2.89539e-7, -3.51199e-9, 2.06926e-11, -6.4067e-14,
81 8.518e-17, 1.558e-20, -1.122e-22};
82 double hv = 0.;
83 for (size_t i = 0; i < sizeof(c) / sizeof(c[0]); i++)
84 {
85 hv += c[i] * std::pow(T_Ads, i);
86 }
87 return hv;
88 }
89 const double c[] = {2.99866e3, -3.1837e-3, -1.566964e1,
90 -2.514e-6, 2.045933e-2, 1.0389e-8};
91 return ((c[0] + c[2] * T_Ads + c[4] * std::pow(T_Ads, 2)) /
92 (1. + c[1] * T_Ads + c[3] * std::pow(T_Ads, 2) +
93 c[5] * std::pow(T_Ads, 3)));
94}
95
96double AdsorptionReaction::getMolarFraction(double xm, double M_this,
97 double M_other)
98{
99 return M_other * xm / (M_other * xm + M_this * (1.0 - xm));
100}
101
102double AdsorptionReaction::dMolarFraction(double xm, double M_this,
103 double M_other)
104{
105 return M_other * M_this / square(M_other * xm + M_this * (1.0 - xm));
106}
107
108double AdsorptionReaction::getReactionRate(const double p_Ads,
109 const double T_Ads,
110 const double M_Ads,
111 const double loading) const
112{
113 const double A = getPotential(p_Ads, T_Ads, M_Ads);
114 const double C_eq =
115 std::max(0., getAdsorbateDensity(T_Ads) * characteristicCurve(A));
116
117 return k_rate * (C_eq - loading); // scaled with mass fraction
118 // this the rate in terms of loading!
119}
120
121double AdsorptionReaction::getLoading(const double rho_curr,
122 const double rho_dry)
123{
124 return rho_curr / rho_dry - 1.0;
125}
126
127// Calculate sorption entropy
128double AdsorptionReaction::getEntropy(const double T_Ads, const double A) const
129{
130 const double epsilon = 1.0e-8;
131
132 //* // This change will also change simulation results.
133 const double W_p = characteristicCurve(A + epsilon);
134 const double W_m = characteristicCurve(A - epsilon);
135 const double dAdlnW = 2.0 * epsilon / (std::log(W_p / W_m));
136 // */
137
138 if (W_p <= 0.0 || W_m <= 0.0)
139 {
140 ERR("characteristic curve in negative region (W-, W+): {:g}, {:g}", W_m,
141 W_p);
142 return 0.0;
143 }
144
145 return dAdlnW * getAlphaT(T_Ads);
146}
147
148// Calculate sorption enthalpy
149double AdsorptionReaction::getEnthalpy(const double p_Ads, const double T_Ads,
150 const double M_Ads) const
151{
152 // TODO [CL] consider using A as obtained from current loading (needs
153 // inverse CC A(W)) instead of p_Vapour, T_Vapour
154 const double A = getPotential(p_Ads, T_Ads, M_Ads);
155
156 return (getEvaporationEnthalpy(T_Ads) + A - T_Ads * getEntropy(T_Ads, A)) *
157 1000.0; // in J/kg
158}
159
161 const double T_Ads,
162 const double M_Ads) const
163{
164 const double A = getPotential(p_Ads, T_Ads, M_Ads);
165 return getAdsorbateDensity(T_Ads) * characteristicCurve(A);
166}
167
168} // namespace Adsorption
void ERR(fmt::format_string< Args... > fmt, Args &&... args)
Definition Logging.h:45
static double getMolarFraction(double xm, double M_this, double M_other)
static double dMolarFraction(double xm, double M_this, double M_other)
virtual double getAlphaT(const double T_Ads) const =0
double getEntropy(const double T_Ads, const double A) const
static double getEquilibriumVapourPressure(const double T_Ads)
double getEnthalpy(const double p_Ads, const double T_Ads, const double M_Ads) const override
static double getEvaporationEnthalpy(const double T_Ads)
static double getLoading(const double rho_curr, const double rho_dry)
virtual double characteristicCurve(const double A) const =0
double getReactionRate(const double p_Ads, const double T_Ads, const double M_Ads, const double loading) const override
virtual double getAdsorbateDensity(const double T_Ads) const =0
double getEquilibriumLoading(const double p_Ads, const double T_Ads, const double M_Ads) const override
double getPotential(const double p_Ads, const double T_Ads, const double M_Ads)