Canoe
Comprehensive Atmosphere N' Ocean Engine
saturation_adjustment.cpp
Go to the documentation of this file.
1 // C/C++
2 #include <cstdlib>
3 #include <cstring>
4 #include <sstream>
5 
6 // athena
7 #include <athena/athena_arrays.hpp>
8 #include <athena/hydro/hydro.hpp>
9 
10 // application
11 #include <application/exceptions.hpp>
12 
13 // canoe
14 #include <air_parcel.hpp>
15 #include <constants.hpp>
16 
17 // snap
18 #include "thermodynamics.hpp"
19 
21  // return if there's no vapor
22  if (NVAPOR == 0) return;
23 
24  for (auto& air : air_column) {
25  air.ToMoleFraction();
26  AirParcel air0(air);
27 
28  // calculate total mole density
29  Real rmole = getDensityMole(air);
30  Real umole = getInternalEnergyMole(air);
31 
32  int iter = 0;
33 
34  Real Teq = air.w[IDN];
35  std::stringstream msg;
36 
37  while (iter++ < sa_max_iter_) {
38  // msg << "iter = " << iter << std::endl;
39  // msg << "old var = " << air << std::endl;
40 
41  Real cvd = 1. / (GetGammad(air) - 1.);
42  Real fsig = 1.;
43  for (int i = 1; i <= NVAPOR; ++i) {
44  Real qv = air.w[i];
45 
46 #pragma omp simd reduction(+ : qv)
47  for (auto j : cloud_index_set_[i]) qv += air.c[j];
48 
49  fsig += (cv_ratio_mole_[i] - 1.) * qv;
50  }
51 
52  // condensation
53  for (int i = 1; i <= NVAPOR; ++i) {
54  auto rates = TryEquilibriumTP_VaporCloud(air, i, cvd * fsig);
55 
56  // vapor condensation rate
57  air.w[i] += rates[0];
58 
59  // cloud concentration rates
60  for (int j = 1; j < rates.size(); ++j) {
61  air.c[cloud_index_set_[i][j - 1]] += rates[j];
62  }
63  }
64 
65  Real Told = air.w[IDN];
66  updateTPConservingU(&air, rmole, umole);
67  // msg << "new var = " << air << std::endl;
68  if (fabs(air.w[IDN] - Teq) < sa_ftol_) break;
69 
70  // relax temperature and pressure
71  Teq = air.w[IDN];
72  Real qgas = 1.;
73 #pragma omp simd reduction(+ : qgas)
74  for (int n = 0; n < NCLOUD; ++n) qgas += -air.c[n];
75 
76  air.w[IDN] = Told + sa_relax_ * (air.w[IDN] - Told);
77  air.w[IPR] = rmole * qgas * Constants::Rgas * air.w[IDN];
78  }
79 
80  if (iter > sa_max_iter_) {
81  msg << "Variables before iteration q0 = (" << air0 << ")" << std::endl;
82  msg << "Variables after iteration q = (" << air << ")" << std::endl;
83  throw RuntimeError("SaturationAdjustment", msg.str());
84  }
85  }
86 }
std::vector< AirParcel > AirColumn
Definition: air_parcel.hpp:121
RealArrayX TryEquilibriumTP_VaporCloud(AirParcel const &qfrac, int ivapor, Real cv_hat=0., bool misty=false) const
Calculate the equilibrium mole transfer by cloud reaction vapor -> cloud.
void SaturationAdjustment(AirColumn &ac) const
Real getDensityMole(AirParcel const &qfrac) const
int sa_max_iter_
maximum saturation adjustment iterations
std::vector< IndexSet > cloud_index_set_
cloud index set
Real sa_ftol_
saturation adjustment temperature tolerance
void updateTPConservingU(AirParcel *qfrac, Real rmole, Real umole) const
update T/P
Real sa_relax_
saturation adjustment relaxation parameter
std::array< Real, Size > cv_ratio_mole_
ratio of specific heat capacities [J/mol] at constant volume
Real GetGammad(AirParcel const &var) const
adiaibatic index of dry air [1]
Real getInternalEnergyMole(AirParcel const &qfrac) const
double const Rgas
Definition: constants.hpp:5