ReFRACtor
refractive_index.cc
Go to the documentation of this file.
1 #include "refractive_index.h"
2 #include "fp_exception.h"
3 
4 using namespace FullPhysics;
5 using namespace blitz;
6 
8  const Array<AutoDerivative<double>, 1>& press,
9  const Array<AutoDerivative<double>, 1>& temp)
10  : bwpar_(bwpar), press_(press), temp_(temp)
11 {
12  if(press_.rows() != temp_.rows()) {
13  Exception err;
14  err << "Number of pressure layers " << press_.rows()
15  << " does not match number of temperature layers " << temp_.rows();
16  throw err;
17  }
18 }
19 
20 
22 {
23  range_check(level_index, 0, number_level());
24  return refr_index_rs(bwpar_, press_(level_index), temp_(level_index));
25 }
26 
28 {
29  range_check(layer_index, 0, number_layer());
30  range_check(value(interp_val), 0.0, 1.0);
31 
32  AutoDerivative<double> fp = exp( interp_val * log(press_(layer_index)) + (1 - interp_val) * log(press_(layer_index+1)) );
33  AutoDerivative<double> ft = interp_val * temp_(layer_index) + (1 - interp_val) * temp_(layer_index+1);
34  return refr_index_rs(bwpar_, fp, ft);
35 }
36 
37 //-----------------------------------------------------------------------
38 
39 OcoRefractiveIndex::OcoRefractiveIndex(double reference_wavelength,
40  const Array<AutoDerivative<double>, 1>& press,
41  const Array<AutoDerivative<double>, 1>& temp,
42  const Array<AutoDerivative<double>, 1>& co2_vmr,
43  const Array<AutoDerivative<double>, 1>& h2o_vmr)
44  : ref_wvl_(reference_wavelength), press_(press), temp_(temp), co2_vmr_(co2_vmr), h2o_vmr_(h2o_vmr)
45 {
46  if( press_.rows() != temp_.rows() ||
47  press_.rows() != co2_vmr_.rows() ||
48  press_.rows() != h2o_vmr_.rows() ) {
49  Exception err;
50  err << "Number of pressure layers " << press_.rows()
51  << " and number of temperature layers " << temp_.rows()
52  << " and number of CO2 layers " << co2_vmr_.rows()
53  << " and number of H2O layers " << h2o_vmr_.rows()
54  << " must all be the same size.";
55  throw err;
56  }
57 }
58 
59 
61 {
62  range_check(level_index, 0, number_level());
63  return refr_index_vn(ref_wvl_, press_(level_index), temp_(level_index), co2_vmr_(level_index), h2o_vmr_(level_index));
64 }
65 
67 {
68  range_check(layer_index, 0, number_layer());
69  range_check(value(interp_val), 0.0, 1.0);
70 
71  AutoDerivative<double> fp = exp( interp_val * log(press_(layer_index)) + (1 - interp_val) * log(press_(layer_index+1)) );
72  AutoDerivative<double> ft = interp_val * temp_(layer_index) + (1 - interp_val) * temp_(layer_index+1);
73  AutoDerivative<double> fc = interp_val * co2_vmr_(layer_index) + (1 - interp_val) * co2_vmr_(layer_index+1);
74  AutoDerivative<double> fh = interp_val * h2o_vmr_(layer_index) + (1 - interp_val) * h2o_vmr_(layer_index+1);
75 
76  return refr_index_vn(ref_wvl_, fp, ft, fc, fh);
77 }
78 
80 {
81  if ( ((wavelength >= 0.755e0) && (wavelength <= 0.785e0)) ||
82  ((wavelength >= 1.58e0) && (wavelength <= 1.65e0)) ||
83  ((wavelength >= 2.03e0) && (wavelength <= 2.09e0)) )
84  return true;
85  else
86  return false;
87 }
88 
89 //-----------------------------------------------------------------------
90 
92  // Original method used by ChapmanBoa from Rob Spurr
93  //
94  // Inputs:
95  // bwpar: base refr index param w/o 1.0 part, ie 0.000288;
96  // press: pressure, Pascals
97  // temp: temperature, Kelvin
98 
99  // Standard temperature (K) and pressure (mbar).
100  const double T_STANDARD = 273.16E0;
101  const double P_STANDARD = 1013.25E0;
102  const double STP_RATIO = T_STANDARD / P_STANDARD;
103 
104  // Simple approximatio
105  // 1.0e-2 converts pressure from Pa to mb
106  double alpha = bwpar * STP_RATIO;
107  AutoDerivative<double> refindex = 1.0E0 + alpha * press * 1.0e-2 / temp;
108 
109 
110  return refindex;
111 } // End of refindex
112 
113 
115  // Improved refractive index method from Vijay Natraj,
116  // although limited to OCO bands
117  //
118  // Inputs (wl: microns, p: Pascals, T: Kelvin, xc: vmr, xw: vmr)
119 
120  // Output
122  nair = 0.e0;
123 
124  AutoDerivative<double> tc = T - 273.15e0; // temperature in degrees Celsius
125 
126  if ((wl >= 0.755e0) && (wl <= 0.785e0)) {
127  double wlm2 = 1.e0/ pow(wl, 2);
128 
129  // Refractive index of standard dry air (400 ppm CO2) at 101325 Pa, 20 C
130  // Zhang et al., Appl. Opt., 47(17), 3143-3151, 2008
131  // Eq. (14)
132  double nsm1 = (8015.514e0 + 2368616.e0 / (128.7459e0 - wlm2) +
133  19085.73e0 / (50.01974e0 - wlm2)) * 1.e-8;
134 
135  // Air density factor
136  AutoDerivative<double> Dair = calc_Dair(p, tc);
137 
138  // Refractive index of dry air (CO2 vmr = xc) at p, T
139  // Zhang et al., Appl. Opt., 47(17), 3143-3151, 2008
140  // Eq. (13), with modification for refractive index of CO2
141  // using Eq. (31)
142  AutoDerivative<double> na = 1.e0 + nsm1 * (1.e0 + 0.5294e0 * (xc - 0.0004e0)) *
143  Dair / 94449.94e0;
144 
145  // Lorentz-Lorenz factor for dry air at p, T, xc
146  AutoDerivative<double> La = (pow(na,2) - 1.e0) / (pow(na,2) + 2.e0);
147 
148  // Refractive index of pure water vapor at 1333 Pa, 20 C
149  double nw = calc_nw(wlm2);
150 
151  // Lorentz-Lorenz factor for pure water vapor at 1333 Pa, 20 C
152  double Lw = (pow(nw,2) - 1.e0) / (pow(nw,2) + 2.e0);
153 
154  // Compressibility factor for moist air (H2O vmr = xw) at p, T
155  AutoDerivative<double> Z = calc_Z(p, T, tc, xw);
156 
157  // Compressibility factor for pure water vapor at 1333 Pa, 20 C
158  AutoDerivative<double> Zw = calc_Z(1333.e0, 293.15e0, 20.e0, 1.e0);
159 
160  // Density of water vapor component of moist air at p, T, xw
161  AutoDerivative<double> rhow = calc_rho(p, xw, 0.018015e0, Z, T);
162 
163  // Density of pure water vapor at 1333 Pa, 20 C
164  AutoDerivative<double> rhows = calc_rho(1333.e0, 1.e0, 0.018015e0, Zw, 293.15e0);
165 
166  // Lorentz-Lorentz factor for moist air at p, T, xc, xw
167  AutoDerivative<double> L = La + (rhow / rhows) * Lw;
168 
169  // Refractive index of moist air at p, T, xc, xw
170  nair = sqrt((1.e0 + 2.e0 * L)/(1.e0 - L));
171 
172  } else if (((wl >= 1.58e0) && (wl <= 1.65e0)) ||
173  ((wl >= 2.03e0) && (wl <= 2.09e0))) {
174 
175  double nw, na;
176  if ((wl >= 1.58e0) && (wl <= 1.6e0)) {
177 
178  // Refractive index of standard dry air (450 ppm CO2) at 101325 Pa, 293.16 K
179  // Colavita et al., Publ. Astron. Soc. Pac., 116, 876-885, 2004
180  // Table 1
181 
182  double n1 = 2.6859e-4;
183  double n2 = 2.6855e-4;
184  na = 1.e0 + n1 + ((wl - 1.55e0) / 0.05e0) * (n2 - n1);
185 
186  // Refractive index of pure water vapor at 410 Pa, 293.16 K
187  // Colavita et al., Publ. Astron. Soc. Pac., 116, 876-885, 2004
188  // Table 1
189  n1 = 9.164e-7;
190  n2 = 9.154e-7;
191  nw = 1.e0 + n1 + ((wl - 1.55e0) / 0.05e0) * (n2 - n1);
192 
193  } else if ((wl > 1.6e0) && (wl <= 1.65e0)) {
194  double n1 = 2.6855e-4;
195  double n2 = 2.6851e-4;
196  na = 1.e0 + n1 + ((wl - 1.6e0) / 0.05e0) * (n2 - n1);
197 
198  n1 = 9.154e-7;
199  n2 = 9.144e-7;
200  nw = 1.e0 + n1 + ((wl - 1.6e0) / 0.05e0) * (n2 - n1);
201 
202  } else if ((wl >= 2.03e0) && (wl <= 2.05e0)) {
203  double n1 = 2.6833e-4;
204  double n2 = 2.6831e-4;
205  na = 1.e0 + n1 + ((wl - 2.e0) / 0.05e0) * (n2 - n1);
206 
207  n1 = 9.092e-7;
208  n2 = 9.076e-7;
209  nw = 1.e0 + n1 + ((wl - 2.e0) / 0.05e0) * (n2 - n1);
210 
211  } else if ((wl > 2.05e0) && (wl <= 2.09e0)) {
212  double n1 = 2.6831e-4;
213  double n2 = 2.683e-4;
214  na = 1.e0 + n1 + ((wl - 2.05e0) / 0.05e0) * (n2 - n1);
215 
216  n1 = 9.076e-7;
217  n2 = 9.061e-7;
218  nw = 1.e0 + n1 + ((wl - 2.05e0) / 0.05e0) * (n2 - n1);
219 
220  }
221 
222  // Compressibility factor for moist air at p, T, xw
223  AutoDerivative<double> Z = calc_Z(p, T, tc, xw);
224 
225  // Compressibility factor for standard dry air at 101325 Pa, 293.16 K
226  AutoDerivative<double> Za = calc_Z(101325.e0, 293.16e0, 20.01e0, 0.e0);
227 
228  // Compressibility factor for pure water vapor at 410 Pa, 20.01 C
229  AutoDerivative<double> Zw = calc_Z(410.e0, 293.16e0, 20.01e0, 1.e0);
230 
231  // Molar mass of dry air, xc
232  AutoDerivative<double> Ma = (28.9635e0 + 12.011e0 * (xc - 0.0004e0)) * 1.e-3;
233 
234  // Density of dry component of moist air at p, T, xc, xw
235  AutoDerivative<double> rhoa = calc_rho(p, 1.e0-xw, Ma, Z, T);
236 
237  // Molar mass of standard dry air, 450 ppm CO2
238  double Mas = (28.9635e0 + 12.011e0 * (0.00045e0 - 0.0004e0)) * 1.e-3;
239 
240  // Density of standard dry air at 101325 Pa, 293.16 K
241  AutoDerivative<double> rhoas = calc_rho(101325.e0, 1.e0, Mas, Za, 293.16e0);
242 
243  // Density of water vapor component of moist air at p, T, xw
244  AutoDerivative<double> rhow = calc_rho(p, xw, 0.018015e0, Z, T);
245 
246  // Density of pure water vapor at 1333 Pa, 20 C
247  AutoDerivative<double> rhows = calc_rho(1333.e0, 1.e0, 0.018015e0, Zw, 293.15e0);
248 
249  // Refractive index of moist air at p, T, xc, xw
250  nair = 1.e0 + (rhoa / rhoas) * (na - 1.e0) + (rhow / rhows) * (nw - 1.e0);
251 
252  } else {
253  throw Exception("Can not compute refractive index outside spectral range handled by this function");
254 
255  }
256 
257  return nair;
258 
259 }
260 
262 
263  // Zhang et al., Appl. Opt., 47(17), 3143-3151, 2008
264  // Eq. (11)
266  p * (1.e0 + p * (0.621811e0 - 0.0126531e0 * tc + 0.000066e0 * pow(tc,2)) *
267  1.e-8) / (1.e0 + 0.003661e0 * tc);
268 
269  return Dair;
270 
271 }
272 
273 double FullPhysics::calc_nw(double wlm2) {
274 
275  // Local variables
276  double w0, w1, w2, w3;
277 
278  // Ciddor, Appl. Opt., 35(9), 1566-1573, 1996
279  // Eq. (3)
280  w0 = 295.235e0;
281  w1 = 2.6422;
282  w2 = -0.03238e0;
283  w3 = 0.004028e0;
284  double nw = 1.022e0*(w0+w1*wlm2+w2*pow(wlm2,2)+w3*pow(wlm2,3))*1.e-8+1.e0;
285 
286  return nw;
287 
288 }
289 
291 
292  // Local variables
293  double a0, a1, a2, b0, b1, c0, c1, d, e;
294 
295  // Ciddor, Appl. Opt., 35(9), 1566-1573, 1996
296  // Eq. (12)
297  a0 = 1.58123e-6;
298  a1 = -2.9331e-8;
299  a2 = 1.1043e-10;
300  b0 = 5.707e-6;
301  b1 = -2.051e-8;
302  c0 = 1.9898e-4;
303  c1 = -2.376e-6;
304  d = 1.83e-11;
305  e = -0.765e-8;
306  AutoDerivative<double> Z = 1.e0-(p/T)*(a0+a1*tc+a2*pow(tc,2)+(b0+b1*tc)*xw+(c0+c1*tc)*pow(xw,2))+
307  pow((p/T),2)*(d+e*pow(xw,2));
308 
309  return Z;
310 }
311 
312 
314 
315  const double R = 8.314510e0;
316 
317  // Ciddor, Appl. Opt., 41(12), 2292-2298, 2002
318  // Eq. (3)
319  AutoDerivative<double> rho = p*x*M/(Z*R*T);
320 
321  return rho;
322 
323 }
#define range_check(V, Min, Max)
Range check.
Definition: fp_exception.h:140
AutoDerivative< double > calc_Z(const AutoDerivative< double > &p, const AutoDerivative< double > &T, const AutoDerivative< double > &tc, const AutoDerivative< double > &xw)
virtual AutoDerivative< double > at_layer(int layer_index, const AutoDerivative< double > &interp_val) const
Returns refractive index at a layer index interpolated between bounding levels using a linear interpo...
virtual AutoDerivative< double > at_level(int level_index) const
Returns refractive index at a level index.
This is the base of the exception hierarchy for Full Physics code.
Definition: fp_exception.h:16
AutoDerivative< double > refr_index_vn(double wl, const AutoDerivative< double > &p, const AutoDerivative< double > &T, const AutoDerivative< double > &xc, const AutoDerivative< double > &xw)
AutoDerivative< double > calc_rho(const AutoDerivative< double > &p, const AutoDerivative< double > &x, const AutoDerivative< double > &M, const AutoDerivative< double > &Z, const AutoDerivative< double > &T)
virtual int number_level() const
Number of levels of atmospheric data represented.
AutoDerivative< double > calc_Dair(const AutoDerivative< double > &p, const AutoDerivative< double > &tc)
Apply value function to a blitz array.
AutoDerivative< double > refr_index_rs(double bwpar, const AutoDerivative< double > &press, const AutoDerivative< double > &temp)
virtual int number_level() const
Number of levels of atmospheric data represented.
Unit pow(const Unit &Dunit, const boost::rational< int > &Exponent)
Definition: unit.cc:158
virtual int number_layer() const
Number of layers of atmospheric data represented.
virtual AutoDerivative< double > at_layer(int layer_index, const AutoDerivative< double > &interp_val) const
Returns refractive index at a layer index interpolated between bounding levels using a linear interpo...
Contains classes to abstract away details in various Spurr Radiative Transfer software.
Definition: doxygen_python.h:1
SimpleRefractiveIndex(double bwpar, const blitz::Array< AutoDerivative< double >, 1 > &press, const blitz::Array< AutoDerivative< double >, 1 > &temp)
virtual AutoDerivative< double > at_level(int level_index) const
Returns refractive index at a level index.
static bool wavelength_in_bounds(double wavelength)
Determines if the passed wavelength value in microns is within the bounds of those accepted by the cl...
double value(const FullPhysics::AutoDerivative< double > &Ad)
double calc_nw(double wlm2)
OcoRefractiveIndex(double reference_wavelength, const blitz::Array< AutoDerivative< double >, 1 > &press, const blitz::Array< AutoDerivative< double >, 1 > &temp, const blitz::Array< AutoDerivative< double >, 1 > &co2_vmr, const blitz::Array< AutoDerivative< double >, 1 > &h2o_vmr)
Creates a refractive index class that can better calculate refractive index for data with in the OCO ...

Copyright © 2017, California Institute of Technology.
ALL RIGHTS RESERVED.
U.S. Government Sponsorship acknowledged.
Generated Fri Aug 24 2018 15:44:10