ReFRACtor
chapman_boa.cc
Go to the documentation of this file.
1 #include "chapman_boa.h"
2 #include "rf_gauleg.h"
3 #include "refractive_index.h"
4 #include "fp_exception.h"
5 
6 using namespace FullPhysics;
7 using namespace blitz;
8 
10 ChapmanBOA::ChapmanBOA(double rearth,
11  bool do_plane_parallel,
12  const blitz::Array<double, 1>& sza_values,
13  const blitz::Array<AutoDerivative<double>, 1>& heights)
14 {
15  straightline_geometry(do_plane_parallel, rearth, heights, sza_values, chapmanfactors_, toa_nadir_szangles_, toa_entry_szangles_);
16 }
17 
19 ChapmanBOA::ChapmanBOA(double rearth,
20  const blitz::Array<double, 1>& sza_values,
21  const blitz::Array<AutoDerivative<double>, 1>& heights,
22  const std::vector<boost::shared_ptr<AtmRefractiveIndex> >& refr_index)
23 {
24  refractive_geometry(rearth, heights, refr_index, sza_values, chapmanfactors_, toa_nadir_szangles_, toa_entry_szangles_);
25 }
26 
28 ChapmanBOA::ChapmanBOA(double rearth,
29  const double sza,
30  const blitz::Array<AutoDerivative<double>, 1>& heights,
31  const boost::shared_ptr<AtmRefractiveIndex>& refr_index)
32 {
33  Array<double, 1> sza_values(1);
34  sza_values(0) = sza;
35 
36  std::vector<boost::shared_ptr<AtmRefractiveIndex> > refr_index_arr;
37  refr_index_arr.push_back(refr_index);
38 
39  refractive_geometry(rearth, heights, refr_index_arr, sza_values, chapmanfactors_, toa_nadir_szangles_, toa_entry_szangles_);
40 }
41 
43 const blitz::Array<AutoDerivative<double>, 1> ChapmanBOA::transmittance(const blitz::Array<AutoDerivative<double>, 1>& extinction) const
44 {
45  Array<AutoDerivative<double>, 1> trans(chapmanfactors_.extent(secondDim));
46  for(int ib = 0; ib < chapmanfactors_.extent(secondDim); ib++) {
47  trans(ib) = transmittance(extinction, ib);
48  }
49  return trans;
50 }
51 
53 const AutoDerivative<double> ChapmanBOA::transmittance(const blitz::Array<AutoDerivative<double>, 1>& extinction, int beam_index) const
54 {
55  AutoDerivative<double> trans = 1.0e0;
56  for(int n = 0; n < chapmanfactors_.extent(firstDim); n++) {
57  AutoDerivative<double> tr = 0.0e0;
58  AutoDerivative<double> arg = extinction(n) * chapmanfactors_(n,beam_index);
59  if ( arg < 32.0e0 ) tr = exp ( - arg );
60  trans = trans * tr;
61  }
62  return trans;
63 }
64 
65 /****************************************************************/
70  bool do_plane_parallel,
71  double rearth,
72  const blitz::Array<AutoDerivative<double>, 1>& heights,
73  const blitz::Array<double, 1>& sza_values,
74  // Outputs
75  blitz::Array<AutoDerivative<double>, 2>& chapmanfactors,
76  blitz::Array<AutoDerivative<double>, 1>& toa_nadir_szangles,
77  blitz::Array<AutoDerivative<double>, 1>& toa_entry_szangles )
78 {
79 
80  // Sizes of input data dimensions
81  int nlayers = heights.extent(firstDim)-1;
82  int nbeams = sza_values.extent(firstDim);
83 
84  // Resize output arguments
85  chapmanfactors.resize(nlayers,nbeams);
86  toa_nadir_szangles.resize(nbeams);
87  toa_entry_szangles.resize(nbeams);
88 
89  Array<AutoDerivative<double>, 1> radii(nlayers+1);
90 
91  // initialize
92  toa_nadir_szangles = 0.0e0;
93  toa_entry_szangles = 0.0e0;
94  chapmanfactors = 0.0e0;
95 
96  // set up some local values
97  double dtr = atan(1.0e0)/45.0e0;
98 
99  // set up local atmosphere quantities
100  for(int n = 0; n < nlayers+1; n++)
101  radii(n) = rearth + heights(n);
102 
103  // start Loop over solar beams
104  // ===========================
105  for(int ibeam = 0; ibeam < nbeams; ibeam++) {
106 
107  // get TOA solar zenith angle
108  double xboa = sza_values(ibeam);
109  toa_nadir_szangles(ibeam) = xboa;
110  double xboa_r = xboa * dtr;
111  double mu_boa = cos(xboa_r);
112 
113  if ( do_plane_parallel ) {
114  // Plane parallel
115 
116  toa_entry_szangles (ibeam) = xboa;
117  for(int k = 0; k < nlayers; k++)
118  chapmanfactors(k,ibeam) = 1.0e0 / mu_boa;
119 
120  } else {
121  // Curved atmopshere
122  // sine-rule; PHI = earth-centered angle
123 
124  double gm_boa = sqrt(1.0e0 - mu_boa*mu_boa);
125  AutoDerivative<double> sinth1 = gm_boa * radii(nlayers) / radii(0);
126  AutoDerivative<double> sth1 = asin(sinth1);
127  toa_entry_szangles(ibeam) = sth1 / dtr;
128  AutoDerivative<double> re_upper = radii(0);
129 
130  for(int k = 0; k < nlayers; k++) {
131  AutoDerivative<double> delz = heights(k) - heights(k+1);
132  AutoDerivative<double> re_lower = re_upper - delz;
133  AutoDerivative<double> sinth2 = re_upper * sinth1 / re_lower;
134  AutoDerivative<double> sth2 = asin(sinth2);
135  AutoDerivative<double> phi = sth2 - sth1;
136  AutoDerivative<double> sinphi = sin(phi);
137  AutoDerivative<double> dist = re_upper * sinphi / sinth2;
138  chapmanfactors(k,ibeam) = dist / delz;
139 
140  re_upper = re_lower;
141  sinth1 = sinth2;
142  sth1 = sth2;
143  }
144  }
145 
146  } // End beam loop
147 
148  // end subroutine straightline_geometry
149 }
150 
152  double rearth,
153  const blitz::Array<AutoDerivative<double>, 1>& heights,
154  const std::vector<boost::shared_ptr<AtmRefractiveIndex> >& refr_index,
155  const blitz::Array<double, 1>& sza_values,
156  // Output
157  blitz::Array<AutoDerivative<double>, 2>& chapmanfactors,
158  blitz::Array<AutoDerivative<double>, 1>& toa_nadir_szangles,
159  blitz::Array<AutoDerivative<double>, 1>& toa_entry_szangles)
160 {
161  // Sizes of input data dimensions
162  int nlayers = heights.extent(firstDim)-1;
163  int nbeams = sza_values.extent(firstDim);
164 
165  if((int) refr_index.size() != nbeams) {
166  Exception err;
167  err << "Number of refractive index objects: " << refr_index.size()
168  << " does not match number of solar zenith angles: " << nbeams;
169  throw err;
170  }
171 
172  // Resize output arguments
173 
174  // chapman factors to BOA, and TOA Sza angles
175  chapmanfactors.resize(nlayers,nbeams);
176  toa_nadir_szangles.resize(nbeams);
177  toa_entry_szangles.resize(nbeams);
178 
179  // Local
180  // =====
181 
182  // Set initial gridding Control variables
183  int nupper = 10;
184  int nlower = 20;
185  double changeheight = 20.0e0;
186 
187  // Will never allocate more than this
188  int max_nquads = 100;//max(nupper, nlower);
189 
190  // ray constants
191  Array<AutoDerivative<double>, 2> rtimesn(nlayers+1,nbeams);
192  Array<AutoDerivative<double>, 1> radii(nlayers+1);
193 
194  // partial and whole layer fine gridding
195  Array<int, 1> nquad(nlayers);
196 
197  // Fine layering stuff (whole atmosphere)
198  Array<AutoDerivative<double>, 2> fineweight (nlayers,max_nquads);
199  Array<AutoDerivative<double>, 2> fineradii (nlayers,max_nquads);
200  Array<AutoDerivative<double>, 3> finersqnsq (nlayers,max_nquads,nbeams);
201 
202  // initialize
203  toa_nadir_szangles = 0.0e0;
204  toa_entry_szangles = 0.0e0;
205  chapmanfactors = 0.0e0;
206  Range ra = Range::all();
207 
208  // set up some local values
209  double dtr = atan(1.0e0)/45.0e0;
210 
211  // set up local atmosphere quantities
212  for (int i = 0; i <= nlayers; i++) {
213  radii(i) = rearth + heights(i);
214  for(int ibeam = 0; ibeam < nbeams; ibeam++)
215  rtimesn(i, ibeam) = radii(i) * refr_index[ibeam]->at_level(i);
216  }
217 
218  // full gridding of atmosphere
220  ( rearth, nlower, nupper, changeheight, heights, refr_index,
221  fineweight, fineradii, finersqnsq, nquad );
222 
223  // start Loop over solar beams
224  // ===========================
225  for(int ibeam = 0; ibeam < nbeams; ibeam++) {
226 
227  // local solar zenith angles
228  double xboa = sza_values(ibeam);
229 
230  // refraction from BOA, with distances
231  Array<AutoDerivative<double>, 1> distances(nlayers);
232  AutoDerivative<double> xtoa, alpha; // returned values
234  ( nlayers, xboa, dtr, rtimesn(ra, ibeam), nquad,
235  fineweight, fineradii, finersqnsq(ra, ra, ibeam),
236  distances, alpha, xtoa );
237 
238  // get TOA solar zenith angle, BOA-level Chapmans
239  toa_nadir_szangles (ibeam) = xtoa;
240  toa_entry_szangles (ibeam) = alpha;
241  for(int k = nlayers-1; k >= 0; k--) {
242  AutoDerivative<double> delz = heights(k) - heights(k+1);
243  chapmanfactors(k,ibeam) = distances(k) / delz;
244  }
245 
246  } // End beam loop
247 
248 } // End of refractive_geometry
249 
251  int start_lay, // Starting at Level n and working out to TOA
252  double theta, // Function Guess (level angle)
253  double dtr,
254  const blitz::Array<AutoDerivative<double>, 1>& rtimesn,
255  const blitz::Array<int, 1>& nquad,
256  // Layer fine gridding
257  const blitz::Array<AutoDerivative<double>, 2>& fineweight,
258  const blitz::Array<AutoDerivative<double>, 2>& fineradii,
259  const blitz::Array<AutoDerivative<double>, 2>& finersqnsq,
260  // Output local distances, cumulative angles and function value
261  blitz::Array<AutoDerivative<double>, 1>& distances,
262  AutoDerivative<double>& alpha,
263  AutoDerivative<double>& anglefunc )
264 {
265 
266  // Sizes of input data dimensions
267  int nlayers = rtimesn.extent(firstDim)-1;
268 
269  // Resize output arrays
270  distances.resize(nlayers);
271 
272  // Initialize
273  anglefunc = 0.0e0;
274  distances = 0.0e0;
275 
276  // constants
277  double theta_r = theta*dtr;
278  double sintheta = sin(theta_r);
279  AutoDerivative<double> raycons = rtimesn(start_lay)*sintheta;
280  AutoDerivative<double> csq = raycons * raycons;
281  alpha = asin(raycons/rtimesn(0))/dtr;
282 
283  // distance calculation
284  for(int i = start_lay-1; i >= 0; i--) {
285  AutoDerivative<double> sum = 0.0e0;
286  for(int k = 0; k < nquad(i); k++) {
287  AutoDerivative<double> Fik = 1.0e0 / ( finersqnsq(i,k) - csq);
288  AutoDerivative<double> Xik_sq = 1.0e0 + csq * Fik;
289  AutoDerivative<double> Xik = sqrt(Xik_sq);
290  sum = sum + fineweight(i,k) * Xik;
291  distances(i) = sum;
292  }
293  }
294 
295  // angle calculations
296  AutoDerivative<double> phi_rad = 0.0e0;
297  for(int i = start_lay-1; i >= 0; i--) {
298  AutoDerivative<double> sum = 0.0e0;
299  for(int k = 0; k < nquad(i); k++) {
300  AutoDerivative<double> help = sqrt((finersqnsq(i,k)/csq) - 1.0);
301  sum = sum + fineweight(i,k)/help/fineradii(i,k);
302  }
303  phi_rad = phi_rad + sum;
304  }
305  AutoDerivative<double> phicum = phi_rad / dtr;
306 
307  // SZA at beam entry + total E-C angle should equal SZA at TOA
308  // This function should be zero
309  // anglefunc = theta + phicum - alpha
310  anglefunc = phicum + alpha;
311 
312 } // End of refractive_bending
313 
315  double rearth,
316  // Gridding Control
317  int nlower,
318  int nupper,
319  double changeheight,
320  const blitz::Array<AutoDerivative<double>, 1>& heights,
321  const std::vector<boost::shared_ptr<AtmRefractiveIndex> >& refr_index,
322  // Outputs
323  // Fine layering stuff
324  blitz::Array<AutoDerivative<double>, 2>& fineweight,
325  blitz::Array<AutoDerivative<double>, 2>& fineradii,
326  blitz::Array<AutoDerivative<double>, 3>& finersqnsq,
327  // partial and whole layer fine gridding
328  blitz::Array<int, 1>& nquad)
329 {
330 
331  // Input arguments
332  // ---------------
333 
334  // Dimensioning
335  int nlayers = heights.extent(firstDim)-1;
336  int max_nquads = fineweight.extent(secondDim);
337 
338  // initialize
339  nquad = 0;
340  fineweight = 0.0e0;
341  fineradii = 0.0e0;
342  finersqnsq = 0.0e0;
343 
344  // Set up gridding
345  for(int i = 0; i < nlayers; i++) {
346  nquad(i) = nlower;
347  if (heights(i) > changeheight)
348  nquad(i) = nupper;
349  }
350 
351  Array<AutoDerivative<double>, 1> xgrid(max_nquads);
352  Array<AutoDerivative<double>, 1> wgrid(max_nquads);
353 
354  // Gauss-Legendre Integration
355  for(int i = 0; i < nlayers; i++) {
356  rf_gauleg(heights(i+1), heights(i), xgrid, wgrid, nquad(i));
357 
358  for(int k = 0; k < nquad(i); k++) {
359  fineradii(i,k) = rearth + xgrid(k);
360  fineweight(i,k) = wgrid(k);
361  AutoDerivative<double> xd = (xgrid(k) - heights(i+1)) / (heights(i) - heights(i+1));
362  for(int beam_idx = 0; beam_idx < finersqnsq.extent(thirdDim); beam_idx++) {
363  AutoDerivative<double> fn = refr_index[beam_idx]->at_layer(i, xd);
364  finersqnsq(i,k,beam_idx) = pow(fineradii(i,k), 2) * pow(fn, 2);
365  }
366  }
367  }
368 } // End of full_gridding
void refractive_geometry(double rearth, const blitz::Array< AutoDerivative< double >, 1 > &heights, const std::vector< boost::shared_ptr< AtmRefractiveIndex > > &refr_index, const blitz::Array< double, 1 > &sza_values, blitz::Array< AutoDerivative< double >, 2 > &chapmanfactors, blitz::Array< AutoDerivative< double >, 1 > &toa_nadir_szangles, blitz::Array< AutoDerivative< double >, 1 > &toa_entry_szangles)
Definition: chapman_boa.cc:151
void rf_gauleg(AutoDerivative< double > X1, AutoDerivative< double > X2, blitz::Array< AutoDerivative< double >, 1 > &X, blitz::Array< AutoDerivative< double >, 1 > &W, int KNUM)
Definition: rf_gauleg.cc:4
void full_gridding(double rearth, int nlower, int nupper, double changeheight, const blitz::Array< AutoDerivative< double >, 1 > &heights, const std::vector< boost::shared_ptr< AtmRefractiveIndex > > &refr_index, blitz::Array< AutoDerivative< double >, 2 > &fineweight, blitz::Array< AutoDerivative< double >, 2 > &fineradii, blitz::Array< AutoDerivative< double >, 3 > &finersqnsq, blitz::Array< int, 1 > &nquad)
Output partial and whole layer fine gridding: nquad
Definition: chapman_boa.cc:314
This is the base of the exception hierarchy for Full Physics code.
Definition: fp_exception.h:16
void straightline_geometry(bool do_plane_parallel, double rearth, const blitz::Array< AutoDerivative< double >, 1 > &heights, const blitz::Array< double, 1 > &sza_values, blitz::Array< AutoDerivative< double >, 2 > &chapmanfactors, blitz::Array< AutoDerivative< double >, 1 > &toa_nadir_szangles, blitz::Array< AutoDerivative< double >, 1 > &toa_entry_szangles)
Free functions translated from Fortran.
Definition: chapman_boa.cc:69
Apply value function to a blitz array.
void refractive_bending(int start_lay, double theta, double dtr, const blitz::Array< AutoDerivative< double >, 1 > &rtimesn, const blitz::Array< int, 1 > &nquad, const blitz::Array< AutoDerivative< double >, 2 > &fineweight, const blitz::Array< AutoDerivative< double >, 2 > &fineradii, const blitz::Array< AutoDerivative< double >, 2 > &finersqnsq, blitz::Array< AutoDerivative< double >, 1 > &distances, AutoDerivative< double > &alpha, AutoDerivative< double > &anglefunc)
Definition: chapman_boa.cc:250
Unit pow(const Unit &Dunit, const boost::rational< int > &Exponent)
Definition: unit.cc:158
ChapmanBOA(double rearth, bool do_plane_parallel, const blitz::Array< double, 1 > &sza_values, const blitz::Array< AutoDerivative< double >, 1 > &heights)
Straight line geometry constructor.
Definition: chapman_boa.cc:10
Contains classes to abstract away details in various Spurr Radiative Transfer software.
Definition: doxygen_python.h:1
const blitz::Array< AutoDerivative< double >, 1 > transmittance(const blitz::Array< AutoDerivative< double >, 1 > &extinction) const
Compute transmittance using molecular extinction and pre-computed angles.
Definition: chapman_boa.cc:43

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