Canoe
Comprehensive Atmosphere N' Ocean Engine
rk4_integrate_lnp.cpp
Go to the documentation of this file.
1 // C/C++
2 #include <algorithm>
3 #include <iostream>
4 
5 // thermodynamics
6 #include "thermodynamics.hpp"
7 
8 void Thermodynamics::rk4IntegrateLnp(AirParcel *air, Real dlnp, Method method,
9  Real adlnTdlnP) const {
10  Real step[] = {0.5, 0.5, 1.};
11  Real temp = air->w[IDN];
12  Real pres = air->w[IPR];
13  Real chi[4];
14  Real latent[1 + NVAPOR];
15 
16  for (int rk = 0; rk < 4; ++rk) {
17  EquilibrateTP(air);
18  if (method != Method::ReversibleAdiabat) {
19  for (int j = 0; j < NCLOUD; ++j) air->c[j] = 0;
20  }
21 
22  for (int i = 1; i <= NVAPOR; ++i) {
23  // make a trial run to get latent heat
24  air->w[i] += 1.E-6;
25  auto rates = TryEquilibriumTP_VaporCloud(*air, i);
26  latent[i] = GetLatentHeatMole(i, rates, air->w[IDN]) /
27  (Constants::Rgas * air->w[IDN]);
28  air->w[i] -= 1.E-6;
29  }
30 
31  // calculate tendency
32  if (method == Method::ReversibleAdiabat ||
33  method == Method::PseudoAdiabat) {
34  chi[rk] = calDlnTDlnP(*air, latent);
35  } else if (method == Method::DryAdiabat) {
36  for (int i = 1; i <= NVAPOR; ++i) latent[i] = 0;
37  chi[rk] = calDlnTDlnP(*air, latent);
38  } else { // isothermal
39  chi[rk] = 0.;
40  }
41  chi[rk] += adlnTdlnP;
42 
43  // integrate over dlnp
44  if (rk < 3) {
45  air->w[IDN] = temp * exp(chi[rk] * dlnp * step[rk]);
46  } else {
47  air->w[IDN] =
48  temp *
49  exp(1. / 6. * (chi[0] + 2. * chi[1] + 2. * chi[2] + chi[3]) * dlnp);
50  }
51  air->w[IPR] = pres * exp(dlnp);
52  }
53 
54  // recondensation
55  EquilibrateTP(air);
56  if (method != Method::ReversibleAdiabat) {
57  for (int j = 0; j < NCLOUD; ++j) air->c[j] = 0;
58  }
59 }
Real *const w
Definition: air_parcel.hpp:36
Real *const c
cloud data
Definition: air_parcel.hpp:39
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.
Real calDlnTDlnP(AirParcel const &qfrac, Real latent[]) const
Calculate moist adiabatic temperature gradient.
Real GetLatentHeatMole(int i, std::vector< Real > const &rates, Real temp) const
void EquilibrateTP(AirParcel *qfrac) const
void rk4IntegrateLnp(AirParcel *qfrac, Real dlnp, Method method, Real adlnTdlnP) const
double const Rgas
Definition: constants.hpp:5
float temp
Definition: fit_ammonia.py:6