OGS
Adsorption.cpp
Go to the documentation of this file.
1 
10 #include "Adsorption.h"
11 
12 #include "BaseLib/Logging.h"
14 
15 namespace
16 {
17 // Evaluate adsorbtion potential A
18 double 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 
28 constexpr double k_rate = 6.0e-3; // to be specified
29 
30 template <typename T>
31 T square(const T& v)
32 {
33  return v * v;
34 }
35 } // namespace
36 
37 namespace 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
62 double 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 
96 double 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 
102 double 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 
108 double 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 
121 double 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
128 double 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
149 double 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(char const *fmt, Args const &... args)
Definition: Logging.h:42
static double getMolarFraction(double xm, double M_this, double M_other)
Definition: Adsorption.cpp:96
static double dMolarFraction(double xm, double M_this, double M_other)
Definition: Adsorption.cpp:102
virtual double getAlphaT(const double T_Ads) const =0
double getEntropy(const double T_Ads, const double A) const
Definition: Adsorption.cpp:128
static double getEquilibriumVapourPressure(const double T_Ads)
Definition: Adsorption.cpp:40
double getEnthalpy(const double p_Ads, const double T_Ads, const double M_Ads) const override
Definition: Adsorption.cpp:149
static double getEvaporationEnthalpy(const double T_Ads)
Definition: Adsorption.cpp:62
static double getLoading(const double rho_curr, const double rho_dry)
Definition: Adsorption.cpp:121
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
Definition: Adsorption.cpp:108
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
Definition: Adsorption.cpp:160
double getPotential(const double p_Ads, const double T_Ads, const double M_Ads)
Definition: Adsorption.cpp:18