Canoe
Comprehensive Atmosphere N' Ocean Engine
fu_waterice_cloud.cpp
Go to the documentation of this file.
1 // C/C++
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>
19 
20 // opacity
21 #include "water_cloud.hpp"
22 
23 // coefficient from fu and liou
24 
25 // wavenumber range
26 Real wband[19] = {
27  0, 280, 400, 540, 670, 800, 980, 1100, 1250, 1400,
28  1700, 1900, 2200, 2857, 4000, 5263, 7692, 14286, 50000}; // cm-1
29 
30 // ap for tau
31 
32 Real ap[18][3] = {{-0.67163E-03, 0.33056E+01, 0.0},
33  {0.25307E-03, 0.32490E+01, 0.0},
34  {-0.75524E-03, 0.33083E+01, 0.0},
35  {-0.20332E-02, 0.33865E+01, 0.0},
36  {0.40939E-02, 0.29870E+01, 0.0},
37  {-0.27583E-02, 0.34436E+01, 0.0},
38  {-7.770e-3, 3.734, 11.85},
39  {-8.088e-3, 3.717, 17.17},
40  {-8.441e-3, 3.715, 19.48},
41  {-9.061e-3, 3.741, 26.48},
42  // c-- changed by Z.F. for the windows domain in longwave
43  // spectral.^M 1 0.160239, 0.495375, -4.38738,
44  // 1 0.165637, -0.438836, 1.54020,
45  // 1 0.172217, -1.49513, 10.56623,
46  {-9.609e-3, 3.768, 34.11},
47  {-1.153e-2, 4.109, 17.32},
48  {-8.294e-3, 3.925, 1.315},
49  {-1.026e-2, 4.105, 16.36},
50  {-1.151e-2, 4.182, 31.13},
51  {-1.704e-2, 4.830, 16.27},
52  {-1.741e-2, 5.541, -58.42},
53  {-7.752e-3, 4.624, -42.01}};
54 
55 // bp for ssalb
56 
57 Real bp[18][4] = {{-0.14661E-06, 0.79495E-07, -0.10422E-09, 0.40232E-12},
58  {-0.15417E-05, 0.11489E-04, -0.77147E-08, 0.22160E-10},
59  {-0.13287E-02, 0.91493E-03, -0.39410E-05, 0.12610E-07},
60  {-0.21311E-02, 0.22827E-02, -0.13400E-04, 0.42169E-07},
61  {0.22764E+00, 0.21902E-02, -0.16743E-04, 0.53032E-07},
62  {0.59555E-01, 0.73777E-02, -0.66056E-04, 0.21750E-06},
63  {.19960E+00, .37800E-02, -.14910E-04, .00000E+00},
64  {.30140E+00, .26390E-02, -.11160E-04, .00000E+00},
65  {.39080E+00, .12720E-02, -.55640E-05, .00000E+00},
66  {.31050E+00, .26030E-02, -.11390E-04, .00000E+00},
67  {0.236894, 2.10402E-03, -3.72955E-06, 0.0},
68  {0.315225, 9.38232E-04, 1.50649E-06, 0.0},
69  {0.605243, -3.92611E-03, 2.12776E-05, 0.0},
70  // {.20370E+00, .42470E-02, -.18100E-04, .00000E+00},
71  // {.23070E+00, .38300E-02, -.16160E-04, .00000E+00},
72  // {.56310E+00, -.14340E-02, .62980E-05, .00000E+00},
73  {.52070E+00, -.97780E-03, .37250E-05, .00000E+00},
74  {.32540E+00, .34340E-02, -.30810E-04, .91430E-07},
75  {.10280E+00, .50190E-02, -.20240E-04, .00000E+00},
76  {.39640E+00, -.31550E-02, .64170E-04, -.29790E-06},
77  {.80790E+00, -.70040E-02, .52090E-04, -.14250E-06}};
78 
79 // cpir for gg ** not right for shortwave band (iband =1 ~ 6)
80 
81 Real cpir[18][4] = {
82  {.79550, 2.524e-3, -1.022e-5, 0.000e+0},
83  {.79550, 2.524e-3, -1.022e-5, 0.000e+0},
84  {.79550, 2.524e-3, -1.022e-5, 0.000e+0},
85  {.79550, 2.524e-3, -1.022e-5, 0.000e+0},
86  {.79550, 2.524e-3, -1.022e-5, 0.000e+0},
87  {.79550, 2.524e-3, -1.022e-5, 0.000e+0},
88  {.79550, 2.524e-3, -1.022e-5, 0.000e+0},
89  {.86010, 1.599e-3, -6.465e-6, 0.000e+0},
90  {.89150, 1.060e-3, -4.171e-6, 0.000e+0},
91  {.87650, 1.198e-3, -4.485e-6, 0.000e+0},
92  {0.884846, 7.52769E-05, 4.57733E-06, 0.0},
93  {0.901327, 2.03758E-04, 2.95010E-06, 0.0},
94  {0.873900, 1.45318E-03, -6.30462E-06, 0.0},
95  // .88150, 9.858e-4, -3.116e-6, 0.000e+0,
96  // .91670, 5.499e-4, -1.507e-6, 0.000e+0,
97  // .90920, 9.295e-4, -3.877e-6, 0.000e+0,
98  {.84540, 1.429e-3, -5.859e-6, 0.000e+0},
99  {.76780, 2.571e-3, -1.041e-5, 0.000e+0},
100  {.72900, 2.132e-3, -5.584e-6, 0.000e+0},
101  {.70240, 4.581e-3, -3.054e-5, 6.684e-8},
102  {.22920, 1.724e-2, -1.573e-4, 4.995e-7}};
103 
104 // TODO(cli): number density and mass density are incorrect
105 Real FuWaterIceCloud::getAttenuation1(Real wave, AirParcel const& qfrac) const {
106  auto pthermo = Thermodynamics::GetInstance();
107 
108  // from fu & liou code
109  int iband = locate(wband, wave, 19) + 1;
110  assert(iband >= 1 && iband <= 18);
111  iband = 18 - iband;
112 
113  Real result = 0.;
114  Real fw1, fw2, pde, T;
115  T = qfrac.w[IDN] - 273.15; // K to degree C
116  if (T > -60.0) {
117  pde = 326.3 + 12.42 * T + 0.197 * T * T +
118  0.0012 * T * T * T; // effective size of ice cloud ( um )
119  } else {
120  pde = 30.;
121  }
122  fw1 = pde;
123  fw2 = fw1 * pde;
124  Real dens =
125  qfrac.w[IPR] / (pthermo->GetRd() * qfrac.w[IDN] * pthermo->RovRd(qfrac));
126 
127  result = ap[iband - 1][0] + ap[iband - 1][1] / fw1 + ap[iband - 1][2] / fw2;
128 
129  return 1e3 * dens * qfrac.c[GetCloudIndex(0)] * result;
130 }
131 
133  AirParcel const& qfrac) const {
134  // from fu & liou code
135  int iband = locate(wband, wave, 19) + 1;
136  assert(iband >= 1 && iband <= 18);
137  iband = 18 - iband;
138 
139  Real wi = 0.;
140  Real fw1, fw2, fw3, pde, T;
141  T = qfrac.w[IDN] - 273.15; // K to degree C
142  if (T > -60.0) {
143  pde = 326.3 + 12.42 * T + 0.197 * T * T + 0.0012 * T * T * T;
144  } else {
145  pde = 30.;
146  }
147  fw1 = pde;
148  fw2 = fw1 * pde;
149  fw3 = fw2 * pde;
150 
151  wi = 1. - (bp[iband - 1][0] + bp[iband - 1][1] * fw1 +
152  bp[iband - 1][2] * fw2 + bp[iband - 1][3] * fw3);
153 
154  // if (prim[imols_[0]]<2e-19){
155  // return 0.0;
156  // }else{
157  return wi;
158  //}
159 }
160 
161 void FuWaterIceCloud::getPhaseMomentum1(Real* pp, Real wave,
162  AirParcel const& qfrac, int np) const {
163  // from fu & liou code
164  int iband = locate(wband, wave, 19) + 1;
165  assert(iband >= 1 && iband <= 18);
166  iband = 18 - iband;
167 
168  Real fw1, fw2, fw3, pde, T;
169  T = qfrac.w[IDN] - 273.15; // K to degree C
170  if (T > -60.0 && T < 0.) {
171  pde = 326.3 + 12.42 * T + 0.197 * T * T + 0.0012 * T * T * T;
172  } else {
173  pde = 30.;
174  }
175 
176  fw1 = pde;
177  fw2 = fw1 * pde;
178  fw3 = fw2 * pde;
179 
180  Real gg = 0.0;
181  gg = cpir[iband - 1][0] + cpir[iband - 1][1] * fw1 +
182  cpir[iband - 1][2] * fw2 + cpir[iband - 1][3] * fw3;
183 
184  // std::cout<<"pde "<<pde<<" "<<T<<" "<<gg<<"ice"<<std::endl;
185  // if (prim[imols_[0]]<2e-19){
186  // GetMom(0, 0.0, np, pp); // 0 for HENYEY_GREENSTEIN
187  // }else{
189  //}
190 }
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 getSingleScatteringAlbedo1(Real wave, AirParcel const &var) const
Real getAttenuation1(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 ap[18][3]
Real bp[18][4]
Real cpir[18][4]
Real wband[19]
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