ReFRACtor
altitude_hydrostatic.cc
Go to the documentation of this file.
1 #include "altitude_hydrostatic.h"
2 #include "old_constant.h"
3 
4 using namespace FullPhysics;
5 using namespace blitz;
6 
7 #ifdef HAVE_LUA
8 #include "register_lua.h"
10 .def(luabind::constructor<const boost::shared_ptr<Pressure>&,
14 
15 #endif
16 
17 
18 inline double sqr(double x) {return x * x;}
20 {return x * x;}
21 
22 //-----------------------------------------------------------------------
51 //-----------------------------------------------------------------------
52 
53 AutoDerivative<double> AltitudeHydrostatic::gravity_calc(double gdlat,
54  AutoDerivative<double> altit) const
55 {
56  double gclat; // geocentric latitude (radians)
57  AutoDerivative<double> radius;
58  // radial distance (metres)
60  // scratch variables
61 
62  const double d2r=3.14159265/180;
63  const double gm=3.9862216e+14;
64  const double omega=7.292116E-05;
65  const double con=.006738;
66  const double shc=1.6235e-03;
67  const double eqrad=6378178;
68  const double ge=gm/sqr(eqrad); // = gravity at Re
69 
70 // Convert from geodetic latitude (GDLAT) to geocentric latitude (GCLAT).
71  gclat=atan(tan(d2r*gdlat)/(1+con)); // radians
72  radius=1000*altit+eqrad/sqrt(1.+con*sqr(sin(gclat)));
73  ff=sqr(radius/eqrad);
74  hh=radius*sqr(omega);
75  return (ge*(1-shc*(3*sqr(sin(gclat))-1)/ff)/ff-hh*sqr(cos(gclat)))
76  *(1+0.5*sqr(sin(gclat)*cos(gclat)*(hh/ge+2*shc/sqr(ff))));
77 }
78 
79 //-----------------------------------------------------------------------
91 //-----------------------------------------------------------------------
92 
93 void AltitudeHydrostatic::altitude_calc
94 (const ArrayAdWithUnit<double, 1>& press_grid,
95  const ArrayAdWithUnit<double, 1>& temp_grid) const
96 {
97  // Gas constant for dry air, in J g^{-1} K^{-1}
99 
100  //const double epsilon = OldConstant::molar_weight_water / OldConstant::molar_weight_dry_air;
101  // constant used in calculating virtual temp, ~0.61.
102  // Would be used if had access to specific humidity in this routine
103  //const double eps2 = (1.0-epsilon)/epsilon;
104 
105  Array<AutoDerivative<double>, 1> pg(press_grid.convert(units::Pa).value.to_array());
106  ArrayAd<double, 1> tg(temp_grid.convert(units::K).value);
107 
108  ArrayAd<double, 1> altv(press_grid.value.rows(),
109  std::max(press_grid.number_variable(),
110  temp_grid.number_variable()));
111 
112  ArrayAd<double, 1> psublayer((press_grid.rows()-1)*num_sublayer, press_grid.number_variable());
113  ArrayAd<double, 1> gravv((altv.rows()-1)*num_sublayer, altv.number_variable());
114 
115  // Calculate altitude and gravity at surface using known altitude
116  altv(altv.rows() - 1) = (surface_height.value < 0 ? 0 :
117  surface_height.convert(units::km).value);
118 
119  // Calculate altitude and gravity constant
120  for(int lev_idx = pg.rows() - 1; lev_idx > 0; lev_idx--) {
121  AutoDerivative<double> dp = (pg(lev_idx-1) - pg(lev_idx)) / num_sublayer;
122  AutoDerivative<double> dt = (tg(lev_idx-1) - tg(lev_idx)) / num_sublayer;
123  AutoDerivative<double> zlo = altv(lev_idx);
124  for(int sub_count = 0; sub_count < num_sublayer; sub_count++) {
125  int sub_idx = (lev_idx-1) * num_sublayer + num_sublayer - sub_count - 1;
126  AutoDerivative<double> plo = pg(lev_idx) + sub_count * dp;
127  psublayer(sub_idx) = plo + 0.5 * dp;
128  AutoDerivative<double> logratio = log( plo / ( plo + dp ) );
129 
130  AutoDerivative<double> tlo = tg(lev_idx) + sub_count * dt;
131  AutoDerivative<double> tbar = tlo + 0.5 * dt;
132 
133  gravv(sub_idx) = gravity_calc(latitude.convert(units::deg).value, zlo);
134  AutoDerivative<double> dz = (Rd * tbar / gravv(sub_idx)) * logratio;
135  gravv(sub_idx) = gravity_calc(latitude.convert(units::deg).value, zlo+0.5*dz);
136  zlo = zlo + dz;
137  }
138  altv(lev_idx-1) = zlo;
139  }
140 
141  std::vector<AutoDerivative<double> > plevlist;
142  std::vector<AutoDerivative<double> > altlist;
143  for(int i = 0; i < pg.rows(); ++i) {
144  plevlist.push_back(pg(i));
145  altlist.push_back(altv(i));
146  }
147  std::vector<AutoDerivative<double> > playlist;
148  std::vector<AutoDerivative<double> > glist;
149  for(int i = 0; i < psublayer.rows(); ++i) {
150  playlist.push_back(psublayer(i));
151  glist.push_back(gravv(i));
152  }
153  alt.reset(new lin_type(plevlist.begin(), plevlist.end(), altlist.begin()));
154  grav.reset(new lin_type(playlist.begin(), playlist.end(), glist.begin()));
155 }
156 
157 //-----------------------------------------------------------------------
160 //-----------------------------------------------------------------------
161 
164  const DoubleWithUnit& Latitude, const DoubleWithUnit& Surface_height, const int Num_sublayer)
165 : cache_is_stale(true),
166  latitude(Latitude),
167  surface_height(Surface_height),
168  p(P),
169  t(T),
170  num_sublayer(Num_sublayer)
171 {
172  p->add_observer(*this);
173  t->add_observer(*this);
174 }
175 
176 //-----------------------------------------------------------------------
183 //-----------------------------------------------------------------------
184 
185 void AltitudeHydrostatic::calc_alt_and_grav() const
186 {
187  if(!cache_is_stale)
188  return;
189 
190  ArrayAdWithUnit<double, 1> pgrid(p->pressure_grid());
191  Array<AutoDerivative<double>, 1> tgrid(pgrid.rows());
192  for(int i = 0; i < tgrid.rows(); ++i)
193  tgrid(i) = t->temperature(pgrid(i)).convert(units::K).value;
194  altitude_calc(pgrid, ArrayAdWithUnit<double, 1>(ArrayAd<double, 1>(tgrid),
195  units::K));
196  cache_is_stale = false;
197 }
198 
199 // See base class for description.
200 
202  const boost::shared_ptr<Pressure>& Press,
203  const boost::shared_ptr<Temperature>& Temp) const
204 {
206  new AltitudeHydrostatic(Press, Temp, latitude, surface_height));
207 }
ArrayAdWithUnit< T, D > convert(const Unit &R) const
Convert to the given units.
The class handles the calculation of the altitude and gravity constants.
Definition: altitude.h:19
This class handles the calculation of the altitude an gravity constants, automatically updating with ...
const Unit Pa("Pa", N/(m *m))
#define REGISTER_LUA_DERIVED_CLASS(X, Y)
Definition: register_lua.h:136
AltitudeHydrostatic(const boost::shared_ptr< Pressure > &P, const boost::shared_ptr< Temperature > &T, const DoubleWithUnit &Latitude, const DoubleWithUnit &Surface_height, const int Num_sublayer=10)
Constructor.
Apply value function to a blitz array.
const Unit K("K", 1.0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0)
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.
double sqr(double x)
Contains classes to abstract away details in various Spurr Radiative Transfer software.
Definition: doxygen_python.h:1
#define REGISTER_LUA_END()
Definition: register_lua.h:134
const Unit km("km", 1e3 *m)
virtual boost::shared_ptr< Altitude > clone() const
Clone an Altitude object.
const Unit deg("deg", pi/180.0 *rad)
const double gas_constant
Gas constant from the ideal gas law, in J mol-1 K-1.
Definition: old_constant.h:43
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:08