Canoe
Comprehensive Atmosphere N' Ocean Engine
fu_waterliquid_cloud.cpp
Go to the documentation of this file.
1 // C/C++ headers
2 #include <algorithm>
3 #include <cassert> // assert
4 #include <cstring>
5 #include <iostream>
6 #include <stdexcept>
7 
8 // canoe
9 #include <air_parcel.hpp>
10 
11 // climath
12 #include <climath/interpolation.h>
13 
14 // snap
16 
17 // harp
18 #include <harp/radiation.hpp> // GetPhaseMomentum
19 
20 // opacity
21 #include "water_cloud.hpp"
22 
23 // coefficient from fu and liou
24 
25 // wavenumber range
26 
27 Real liquid_wband[19] = {0, 280, 400, 540, 670, 800, 980,
28  1100, 1250, 1400, 1700, 1900, 2200, 2857,
29  4000, 5263, 7692, 14286, 50000}; // cm-1
30 
31 // radiuse of water cloud
32 
33 Real re[8] = {4.18, 5.36, 5.89, 6.16, 9.27, 9.84, 12.10, 31.23};
34 
35 // fl for tau
36 Real fl[8] = {0.05, 0.14, 0.22, 0.28, 0.50, 0.47, 1.00, 2.50};
37 
38 // bz for tau
39 Real bz[18][8] = {{15.11, 40.25, 59.81, 72.43, 83.69, 73.99, 128.17, 120.91},
40  {15.74, 41.70, 61.52, 74.47, 85.78, 75.59, 130.46, 121.84},
41  {16.38, 43.52, 64.84, 77.97, 87.31, 77.36, 134.30, 124.06},
42  {17.57, 45.78, 66.44, 80.15, 90.49, 79.90, 137.56, 125.92},
43  {18.19, 46.63, 69.39, 82.20, 91.46, 79.99, 138.21, 126.08},
44  {21.30, 51.88, 77.77, 87.02, 94.91, 83.55, 143.46, 128.45},
45  {22.44, 57.35, 84.41, 103.50, 103.49, 84.17, 152.77, 132.07},
46  {18.32, 52.69, 76.67, 100.31, 105.46, 92.86, 157.82, 133.03},
47  {17.27, 50.44, 74.18, 96.76, 105.32, 95.25, 158.07, 134.48},
48  {13.73, 44.90, 67.70, 90.85, 109.16, 105.48, 163.11, 136.21},
49  {10.30, 36.28, 57.23, 76.43, 106.45, 104.90, 161.73, 136.62},
50  {7.16, 26.40, 43.51, 57.24, 92.55, 90.55, 149.10, 135.13},
51  {6.39, 21.00, 33.81, 43.36, 66.90, 63.58, 113.83, 125.65},
52  {10.33, 30.87, 47.63, 60.33, 79.54, 73.92, 127.46, 128.21},
53  {11.86, 35.64, 54.81, 69.85, 90.39, 84.16, 142.49, 135.25},
54  {10.27, 33.08, 51.81, 67.26, 93.24, 88.60, 148.71, 140.42},
55  {6.72, 24.09, 39.42, 51.68, 83.34, 80.72, 140.14, 143.57},
56  {3.92, 14.76, 25.32, 32.63, 60.85, 58.81, 112.30, 145.62}};
57 
58 // wz for ssalb
59 
60 Real wz[18][8] = {
61  {.999999, .999999, .999999, .999999, .999998, .999999, .999998, .999997},
62  {.999753, .999700, .999667, .999646, .999492, .999470, .999344, .998667},
63  {.995914, .994967, .994379, .993842, .991385, .990753, .988908, .974831},
64  {.983761, .978981, .976568, .974700, .963466, .959934, .953865, .897690},
65  {.702949, .683241, .679723, .669045, .642616, .632996, .629776, .588820},
66  {.947343, .929619, .924806, .914557, .877169, .867047, .853661, .737426},
67  {.919356, .896274, .885924, .881097, .812772, .781637, .775418, .637341},
68  {.874717, .861122, .847850, .851677, .787171, .772952, .753143, .618656},
69  {.764750, .752410, .736529, .743435, .671272, .659392, .639492, .549941},
70  {.807536, .808700, .795994, .805489, .750577, .755524, .709472, .571989},
71  {.753346, .772026, .767273, .777079, .751264, .760973, .712536, .568286},
72  {.632722, .676332, .684631, .693552, .707986, .717724, .682430, .552867},
73  {.288885, .348489, .371653, .380367, .454540, .465769, .475409, .493881},
74  {.261827, .306283, .321340, .333051, .392917, .406876, .417450, .484593},
75  {.295804, .339929, .352494, .365502, .416229, .430369, .435267, .491356},
76  {.301214, .354746, .369346, .381906, .433602, .447397, .447406, .486968},
77  {.243714, .318761, .344642, .352770, .427906, .438979, .445972, .477264},
78  {.109012, .187230, .226849, .224976, .331382, .335917, .374882, .457067}};
79 
80 // gz for gg
81 
82 Real gz[18][8] = {{.838, .839, .844, .847, .849, .860, .853, .859},
83  {.809, .810, .819, .823, .823, .849, .833, .843},
84  {.774, .787, .781, .792, .812, .836, .815, .833},
85  {.801, .802, .793, .793, .814, .829, .818, .832},
86  {.877, .873, .879, .880, .885, .899, .891, .908},
87  {.783, .769, .777, .756, .764, .776, .770, .797},
88  {.818, .805, .824, .830, .815, .801, .820, .845},
89  {.810, .802, .826, .840, .829, .853, .840, .868},
90  {.774, .766, .799, .818, .815, .869, .834, .869},
91  {.734, .728, .767, .797, .796, .871, .818, .854},
92  {.693, .688, .736, .772, .780, .880, .808, .846},
93  {.643, .646, .698, .741, .759, .882, .793, .839},
94  {.564, .582, .637, .690, .719, .871, .764, .819},
95  {.466, .494, .546, .609, .651, .823, .701, .766},
96  {.375, .410, .455, .525, .583, .773, .637, .710},
97  {.262, .301, .334, .406, .485, .695, .545, .631},
98  {.144, .181, .200, .256, .352, .562, .413, .517},
99  {.060, .077, .088, .112, .181, .310, .222, .327}};
100 
101 // TODO(cli): number density and mass density are incorrect
103  AirParcel const& qfrac) const {
104  auto pthermo = Thermodynamics::GetInstance();
105 
106  Real pre = 10.; // choose in 4.18 ~ 31.23 micron
107  // Real pre = 10.0; // choose in 4.18 ~ 31.23 micron
108  // effective radius of water cloud ( um )
109 
110  int j = locate(re, pre, 8);
111  assert(j >= 0 && j <= 7);
112 
113  int iband = locate(liquid_wband, wave, 19) + 1;
114  assert(iband >= 1 && iband <= 18);
115  iband = 18 - iband;
116 
117  Real result = 0.;
118  Real k = (1.0 / re[j + 1] - 1.0 / re[j]) / (1.0 / pre - 1.0 / re[j]);
119  Real dens =
120  qfrac.w[IPR] / (pthermo->GetRd() * qfrac.w[IDN] * pthermo->RovRd(qfrac));
121 
122  result = bz[iband - 1][j] / fl[j] +
123  (bz[iband - 1][j + 1] / fl[j + 1] - bz[iband - 1][j] / fl[j]) / k;
124 
125  return dens * qfrac.c[GetCloudIndex(0)] * result; // -> 1/m
126 }
127 
129  Real wave, AirParcel const& qfrac) const {
130  // from fu & liou code
131  Real pre = 10.;
132 
133  int j = locate(re, pre, 8);
134  assert(j >= 0 && j <= 7);
135 
136  int iband = locate(liquid_wband, wave, 19) + 1;
137  assert(iband >= 1 && iband <= 18);
138  iband = 18 - iband;
139 
140  Real ww = 0.;
141  ww = wz[iband - 1][j] + (wz[iband - 1][j + 1] - wz[iband - 1][j]) /
142  (re[j + 1] - re[j]) * (pre - re[j]);
143 
144  if (qfrac.c[GetCloudIndex(0)] < 2e-19) {
145  return 0.0;
146  } else {
147  return ww;
148  }
149 }
150 
151 void FuWaterLiquidCloud::getPhaseMomentum1(Real* pp, Real wave,
152  AirParcel const& qfrac,
153  int np) const {
154  // from fu & liou code
155 
156  Real pre = 10.;
157 
158  int j = locate(re, pre, 8);
159  assert(j >= 0 && j <= 7);
160 
161  int iband = locate(liquid_wband, wave, 19) + 1;
162  assert(iband >= 1 && iband <= 18);
163  iband = 18 - iband;
164 
165  Real gg = 0.;
166 
167  gg = gz[iband - 1][j] + (gz[iband - 1][j + 1] - gz[iband - 1][j]) /
168  (re[j + 1] - re[j]) * (pre - re[j]);
169 
170  if (qfrac.c[GetCloudIndex(0)] < 2e-19) {
172  np); // 0 for HENYEY_GREENSTEIN
173  } else {
175  np); // 0 for HENYEY_GREENSTEIN
176  }
177 }
Real *const w
Definition: air_parcel.hpp:36
Real *const c
cloud data
Definition: air_parcel.hpp:39
void getPhaseMomentum1(Real *pp, Real wave, AirParcel const &var, int np) const
Real getAttenuation1(Real wave, AirParcel const &var) const
Real getSingleScatteringAlbedo1(Real wave, AirParcel const &var) const
int GetCloudIndex(int n) const
static Thermodynamics const * GetInstance()
Return a pointer to the one and only instance of Thermodynamics.
Real bz[18][8]
Real re[8]
Real gz[18][8]
Real fl[8]
Real liquid_wband[19]
Real wz[18][8]
int locate(double const *xx, double x, int n)
Definition: locate.c:7
void get_phase_momentum(Real *pmom, int iphas, Real gg, int npmom)
Definition: radiation.cpp:256