ReFRACtor
solar_doppler_shift_polynomial.cc
Go to the documentation of this file.
2 #include "old_constant.h"
3 #include "wgs84_constant.h"
4 #include "fp_exception.h"
5 #include "level_1b.h"
6 #include <vector>
7 
8 using namespace FullPhysics;
9 using namespace boost::posix_time;
10 using namespace boost::gregorian;
11 using namespace units;
12 using namespace blitz;
13 
14 #ifdef HAVE_LUA
15 #include "register_lua.h"
16 
17 boost::shared_ptr<SolarDopplerShift> create_from_l1b(const Level1b& l1b, int spec_index, bool do_doppler_shift)
18 {
20  new SolarDopplerShiftPolynomial(l1b.time(spec_index),
21  l1b.latitude(spec_index),
22  l1b.solar_zenith(spec_index),
23  l1b.solar_azimuth(spec_index),
24  l1b.altitude(spec_index),
26  do_doppler_shift));
27 }
28 
30 .scope
31 [
32  luabind::def("create_from_l1b", &create_from_l1b)
33 ]
35 #endif
36 
37 
38 //-----------------------------------------------------------------------
43 //-----------------------------------------------------------------------
44 
45 template <class Type, class Vector>
46 Type Poly(size_t k, const Vector &a, const Type &z)
47 { size_t i;
48  size_t d = a.size() - 1;
49 
50  Type tmp;
51 
52  // case where derivative order greater than degree of polynomial
53  if( k > d )
54  { tmp = 0;
55  return tmp;
56  }
57  // case where we are evaluating a derivative
58  if( k > 0 )
59  { // initialize factor as (k-1) !
60  size_t factor = 1;
61  for(i = 2; i < k; i++)
62  factor *= i;
63 
64  // set b to coefficient vector corresponding to derivative
65  Vector b(d - k + 1);
66  for(i = k; i <= d; i++)
67  { factor *= i;
68  tmp = factor;
69  b[i - k] = a[i] * tmp;
70  factor /= (i - k + 1);
71  }
72  // value of derivative polynomial
73  return Poly(0, b, z);
74  }
75  // case where we are evaluating the original polynomial
76  Type sum = a[d];
77  i = d;
78  while(i > 0)
79  { sum *= z;
80  sum += a[--i];
81  }
82  return sum;
83 }
84 
85 //-----------------------------------------------------------------------
100 //-----------------------------------------------------------------------
101 
103 (
104  const Time& t,
105  const DoubleWithUnit& lat, const DoubleWithUnit& sol_zen,
106  const DoubleWithUnit& sol_az, const DoubleWithUnit& elevation,
107  const Constant& constant,
108  bool apply_doppler_shift)
109  : apply_doppler_shift_(apply_doppler_shift),
110  calculated_doppler_shift(true)
111 {
112  range_check(lat.convert(deg).value, -90.0, 90.0);
113  range_check(sol_az.convert(deg).value, 0.0, 360.0);
114  range_check(sol_zen.convert(deg).value, -90.0, 90.0);
115  calc_solar_distance(constant, t);
116 
117  // The "1" here refers to the "1st" derivative.
118 
119  const double f =
121  double slat = sin(lat.convert(rad).value);
122  double clat = cos(lat.convert(rad).value);
123  double r1 = 1.0 / sqrt(1 - (2*f - f * f) * slat * slat);
124  DoubleWithUnit r2 = (OldConstant::wgs84_a * r1 + elevation) * clat /
125  DoubleWithUnit(1, rad);
126  doppler_rot_earth_sun_ =
127  -1 * OldConstant::earth_rot_speed * r2 * sin(sol_zen.convert(rad).value) *
128  cos(sol_az.convert(rad).value - pi / 2);
129  doppler_shift_ = (total_velocity() /
131 }
132 
133 //-----------------------------------------------------------------------
149 //-----------------------------------------------------------------------
150 
152 (double Doppler_shift,
153  const Time& t,
154  const Constant& constant,
155  bool apply_doppler_shift)
156  : doppler_shift_(Doppler_shift),
157  apply_doppler_shift_(apply_doppler_shift),
158  calculated_doppler_shift(false)
159 {
160  calc_solar_distance(constant, t);
161 }
162 
163 //-----------------------------------------------------------------------
165 //-----------------------------------------------------------------------
166 
167 void SolarDopplerShiftPolynomial::calc_solar_distance
168 (const Constant& constant, const Time& t)
169 {
170  boost::array<double, 7> sdp = constant.solar_distance_param();
171  std::vector<double> solar_distance_param_v(sdp.begin(), sdp.end());
172  // The polynomial is relative to day of the year, with noon
173  // January 1 set to 1.
174  ptime pt(t);
175  double doy = pt.date().day_of_year() +
176  ((double) pt.time_of_day().total_nanoseconds()) /
177  (hours(24).total_nanoseconds()) + 0.5;
178 
179  // The "0" here refers to the "0th" derivative, e.g., we just return
180  // the results of the polynomial.
181  solar_distance_.value = Poly(0, solar_distance_param_v, doy);
182  solar_distance_.units = OldConstant::AU;
183 
184  solar_velocity_ = DoubleWithUnit(Poly(1, solar_distance_param_v, doy),
185  OldConstant::AU / day);
186 }
187 
188 //-----------------------------------------------------------------------
190 //-----------------------------------------------------------------------
191 
192 void SolarDopplerShiftPolynomial::print(std::ostream& Os) const
193 {
194  Os << "SolarDopplerShiftPolynomial\n"
195  << " Solar distance: " << solar_distance_ << "\n"
196  << " Doppler shift: " << doppler_shift_ << "\n"
197  << " Doppler shift " << (calculated_doppler_shift ? "was calculated" :
198  "was read in") << "\n"
199  << " Apply Doppler: " << (apply_doppler_shift_ ? "true" : "false");
200 }
201 
202 // See base class for description
204 const SpectralDomain& Spec_domain) const
205 {
206  if(apply_doppler_shift_) {
207  // The correction is either a multiplication for wavenumbers,
208  // or a division for wavelength.
210  return SpectralDomain(Array<double, 1>(Spec_domain.data() *
211  (1 + doppler_shift_)),
212  Spec_domain.units());
213  else
214  return SpectralDomain(Array<double, 1>(Spec_domain.data() /
215  (1 + doppler_shift_)),
216  Spec_domain.units());
217  } else
218  return Spec_domain;
219 }
220 
#define range_check(V, Min, Max)
Range check.
Definition: fp_exception.h:140
This class handles the solar Doppler stretch to calculate the shift of the solar lines with respect t...
virtual Time time(int Spec_index) const =0
Time of sounding.
const DoubleWithUnit earth_rot_speed(360/86164.09054, units::deg/units::s)
Earth angular rotation frequency (1/sec)
virtual DoubleWithUnit solar_azimuth(int i) const =0
Solar azimuth.
Type Poly(size_t k, const Vector &a, const Type &z)
This is the only place that uses the library CppAD.
virtual DoubleWithUnit altitude(int i) const =0
Altitude.
virtual SpectralDomain doppler_stretch(const SpectralDomain &Spec_domain) const
Shift wavenumbers to account for doppler stretch.
SolarDopplerShiftPolynomial(const Time &t, const DoubleWithUnit &lat, const DoubleWithUnit &sol_zen, const DoubleWithUnit &sol_az, const DoubleWithUnit &elevation, const Constant &constant=DefaultConstant(), bool apply_doppler_shift=true)
Create a SolarDopplerShiftPolynomial.
This class is an implementation of Constant that uses hard coded values suitable for Earth...
const DoubleWithUnit wgs84_a(6378137.0000, units::m)
Equatorial radius.
For different instruments, it is more natural to either work with wavenumbers (e.g., GOSAT) or wavelength (e.g., OCO).
virtual void print(std::ostream &Os) const
Print description of object.
const Unit dimensionless("dimensionless", 1.0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
#define REGISTER_LUA_DERIVED_CLASS(X, Y)
Definition: register_lua.h:136
This is used to read a Level 1B file.
Definition: level_1b.h:15
Apply value function to a blitz array.
virtual DoubleWithUnit latitude(int i) const =0
Latitude.
This class contains various constants.
Definition: constant.h:11
This class handles the solar Doppler stretch to calculate the shift of the solar lines with respect t...
const DoubleWithUnit wgs84_b(6356752.3142450, units::m)
Polar radius in meters.
virtual boost::array< double, 7 > solar_distance_param() const =0
The polynomial used to find the distance to the sun.
We frequently have a double with units associated with it.
DoubleWithUnit convert(const Unit &R) const
Convert to the given units.
TypePreference type_preference() const
Indicate if this class prefers wavelength or wavenumber.
const Unit day("day", 24 *60 *60 *s)
This is a simple time class.
Definition: fp_time.h:29
const Unit units() const
Units that go with data()
Contains classes to abstract away details in various Spurr Radiative Transfer software.
Definition: doxygen_python.h:1
const T & value() const
Convert to type T.
#define REGISTER_LUA_END()
Definition: register_lua.h:134
def(luabind::constructor< int >()) .def("rows"
const Unit AU("AU", 1.49597870691e11 *units::m)
1 AU in meters.
virtual DoubleWithUnit solar_zenith(int i) const =0
Solar zenith.
const Unit rad("rad", 1.0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0)
const blitz::Array< double, 1 > & data() const
Return data.
const DoubleWithUnit speed_of_light(299792458, units::m/units::s)
Speed of light, in m/s.
const Unit deg("deg", pi/180.0 *rad)

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