ReFRACtor
rayleigh.cc
Go to the documentation of this file.
1 #include "rayleigh.h"
2 
3 using namespace FullPhysics;
4 using namespace blitz;
5 extern "C" {
6  void rayleigh_wrap(const double* wn,
7  const double* depolar_fact,
8  const double* a,
9  const double* b,
10  double* rayleigh_cross_section);
11  /* depolar_fact depolarization factor for air is 0.02790 (young, 1980) */
12  /* a and b are wavelength dependence coefficients for the refractive index
13  (allen, 1964) (note: wavelengths must be in microns)
14  For Earth, a = 2.871e-04, b = 5.67e-03 */
15 }
16 
17 //-----------------------------------------------------------------------
19 //-----------------------------------------------------------------------
21  const std::vector<boost::shared_ptr<Altitude> >& Alt,
22  const Constant& C)
23  : pres(Pres), alt(Alt), cache_is_stale(true),
24  a(C.rayleigh_a().value), b(C.rayleigh_b().value),
25  depolar_fact(C.rayleigh_depolarization_factor()),
26  molar_weight_dry_air(C.molar_weight_dry_air().convert(Unit("g / mol")).value)
27 {
28  pres->add_observer(*this);
29  BOOST_FOREACH(boost::shared_ptr<Altitude>& a, alt)
30  a->add_observer(*this);
31 }
32 
33 
34 //-----------------------------------------------------------------------
37 //-----------------------------------------------------------------------
38 
40  const Constant& C)
41 {
42  double rayleigh_cross_section;
43  double wn = W.convert_wave(units::inv_cm).value;
44  double a = C.rayleigh_a().value;
45  double b = C.rayleigh_b().value;
46  double depolar_fact = C.rayleigh_depolarization_factor();
47  rayleigh_wrap(&wn, &depolar_fact, &a, &b, &rayleigh_cross_section);
48  return DoubleWithUnit(rayleigh_cross_section, Unit("m^2"));
49 }
50 
51 //-----------------------------------------------------------------------
61 //-----------------------------------------------------------------------
62 
64 Rayleigh::optical_depth_each_layer(double wn, int spec_index) const
65 {
66  range_check(spec_index, 0, (int) alt.size());
67  fill_cache();
68  double rayleigh_cross_section;
69 
70  rayleigh_wrap(&wn, &depolar_fact, &a, &b, &rayleigh_cross_section);
71  ArrayAd<double, 1> res(part_independent_wn(spec_index, Range::all()).copy());
72  res.value() *= rayleigh_cross_section;
73  res.jacobian() *= rayleigh_cross_section;
74  return res;
75 }
76 
77 //-----------------------------------------------------------------------
79 //-----------------------------------------------------------------------
80 void Rayleigh::fill_cache() const
81 {
82  if(!cache_is_stale)
83  return;
84 
85  // A comment in the old fortran code indicates this is Avogadro's
86  // number. However, this actually is not (Avogadro's number is
87  // 6.02214179e23 /mol. I'm not actually sure what this number is.
88  // You can look at the file exe/full_physics/src/rtmod/ray_tau.F90
89  // in tagged B2.06.02_plus_2.07_backport version to find the
90  // original code and comment
91  const double a0 = 6.02297e26;
92 
93  int nvar = pres->pressure_grid().value.number_variable();
94  for(int i = 0; i < (int) alt.size(); ++i)
95  nvar = std::max(nvar, alt[i]->gravity(pres->pressure_grid()(0)).value.number_variable());
96  part_independent_wn.resize((int) alt.size(), pres->number_layer(), nvar);
97  for(int i = 0; i < part_independent_wn.cols(); ++i)
98  for(int j = 0; j < part_independent_wn.rows(); ++j) {
99  AutoDerivativeWithUnit<double> deltap = pres->pressure_grid()(i + 1) -
100  pres->pressure_grid()(i);
102  pres->pressure_grid()(i) + deltap / 2;
103  part_independent_wn(j, i) = a0 * deltap.convert(units::Pa).value /
104  (molar_weight_dry_air * alt[j]->gravity(play).convert(Unit("m/s^2")).value);
105  }
106  cache_is_stale = false;
107 }
108 
#define range_check(V, Min, Max)
Range check.
Definition: fp_exception.h:140
DoubleWithUnit convert_wave(const Unit &R) const
We often need to handle conversion from wavenumber to/from wavelength.
int cols() const
Definition: array_ad.h:369
This is a AutoDerivative that also has units associated with it.
AutoDerivativeWithUnit< T > convert(const Unit &R) const
Convert to the given units.
virtual DoubleWithUnit rayleigh_a() const =0
Rayleigh "a" value.
Rayleigh(const boost::shared_ptr< Pressure > &Pres, const std::vector< boost::shared_ptr< Altitude > > &Alt, const Constant &C)
Constructor.
Definition: rayleigh.cc:20
const Unit Pa("Pa", N/(m *m))
ArrayAd< double, 1 > optical_depth_each_layer(double wn, int spec_index) const
This gives the optical depth for each layer, for the given wave number.
Definition: rayleigh.cc:64
const blitz::Array< T, D+1 > jacobian() const
Definition: array_ad.h:307
Apply value function to a blitz array.
const blitz::Array< T, D > & value() const
Definition: array_ad.h:306
const Unit inv_cm("cm^-1", pow(cm, -1))
void resize(const blitz::TinyVector< int, D > &Shape, int nvar)
Definition: array_ad.h:177
This class contains various constants.
Definition: constant.h:11
virtual double rayleigh_depolarization_factor() const =0
Rayleigh depolarization factor.
static DoubleWithUnit cross_section(const DoubleWithUnit &W, const Constant &C=DefaultConstant())
Calculate the rayleigh cross section for the given wavenumber/wavelength.
Definition: rayleigh.cc:39
const double molar_weight_dry_air
Molar weight of dry air, in g mol^-1.
Definition: old_constant.h:24
We frequently have a double with units associated with it.
Libraries such as boost::units allow unit handling where we know the units at compile time...
Definition: unit.h:25
Contains classes to abstract away details in various Spurr Radiative Transfer software.
Definition: doxygen_python.h:1
virtual DoubleWithUnit rayleigh_b() const =0
Rayleigh "b" value.
void rayleigh_wrap(const double *wn, const double *depolar_fact, const double *a, const double *b, double *rayleigh_cross_section)
double value(const FullPhysics::AutoDerivative< double > &Ad)
const Unit W("W", J/s)
int rows() const
Definition: array_ad.h:368

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