ReFRACtor
absco.cc
Go to the documentation of this file.
1 #include "absco.h"
2 #include "fp_exception.h"
3 #include "linear_algebra.h"
4 #include <algorithm>
5 using namespace FullPhysics;
6 using namespace blitz;
7 
8 #ifdef HAVE_LUA
9 #include "register_lua.h"
12 #endif
13 
14 //-----------------------------------------------------------------------
16 //-----------------------------------------------------------------------
17 
18 double Absco::interpol(double X, const std::vector<double>& Xv,
19  int& i, double& df_dx) const
20 {
21  // Find index number of largest Xv that is < X.
22  i = (int) (std::lower_bound(Xv.begin(), Xv.end(), X) - Xv.begin()) - 1;
23  if(i < 0)
24  i = 0;
25  if(i > (int) Xv.size() - 2)
26  i = (int) Xv.size() - 2;
27  df_dx = 1 / (Xv[i + 1] - Xv[i]);
28  return (X - Xv[i]) * df_dx ;
29 }
30 
31 //-----------------------------------------------------------------------
33 //-----------------------------------------------------------------------
34 
35 double AbscoInterpolator::interpol(double X, const std::vector<double>& Xv,
36  int& i, double& df_dx) const
37 {
38  // Find index number of largest Xv that is < X.
39  i = (int) (std::lower_bound(Xv.begin(), Xv.end(), X) - Xv.begin()) - 1;
40  if(i < 0)
41  i = 0;
42  if(i > (int) Xv.size() - 2)
43  i = (int) Xv.size() - 2;
44  df_dx = 1 / (Xv[i + 1] - Xv[i]);
45  return (X - Xv[i]) * df_dx ;
46 }
47 
48 //-----------------------------------------------------------------------
53 //-----------------------------------------------------------------------
54 
55 void Absco::fill_pgrid_tgrid_and_bgrid() const
56 {
57  // Store grid in a form that is easier to search.
58  if(pgrid.size() == 0) {
59  Array<double, 1> pgridg(pressure_grid());
60  Array<double, 2> tg(temperature_grid());
61  Array<double, 1> bgridg(broadener_vmr_grid());
62  pgrid.resize(pgridg.rows());
63  tgrid.resize(tg.rows());
64  bgrid.resize(std::max(bgridg.rows(), 1));
65  for(int i = 0; i < pgridg.rows(); ++i)
66  pgrid[i] = pgridg(i);
67  for(int i = 0; i < bgridg.rows(); ++i)
68  bgrid[i] = bgridg(i);
69  if(bgridg.rows() ==0)
70  bgrid[0] = 0;
71  for(int i = 0; i < tg.rows(); ++i) {
72  tgrid[i].resize(tg.cols());
73  for(int j = 0; j < tg.cols(); ++j)
74  tgrid[i][j] = tg(i,j);
75  }
76  }
77 }
78 
79 // See base class for description.
81 (double Wn, const DoubleWithUnit& Press, const DoubleWithUnit& Temp,
82  const DoubleWithUnit& Broadener_vmr) const
83 {
86  p.units = Press.units;
87  p.value.resize(1);
88  p.value(0) = Press.value;
89  t.units = Temp.units;
90  t.value.resize(1, 0);
91  t.value(0) = Temp.value;
92  b.units = Broadener_vmr.units;
93  b.value.resize(1, 0);
94  b.value(0) = Broadener_vmr.value;
95  boost::shared_ptr<Absco> self_ptr = to_ptr(const_cast<Absco&>(*this));
96  AbscoInterpolator aint(self_ptr, p, t, b);
98  "cm^2");
99 }
100 
101 // See base class for description.
103 (double Wn, const DoubleWithUnit& Press,
104  const AutoDerivativeWithUnit<double>& Temp,
105  const AutoDerivativeWithUnit<double>& Broadener_vmr) const
106 {
109  p.units = Press.units;
110  p.value.resize(1);
111  p.value(0) = Press.value;
112  t.units = Temp.units;
113  t.value.resize(1, Temp.value.number_variable());
114  t.value(0) = Temp.value;
115  b.units = Broadener_vmr.units;
116  b.value.resize(1, Broadener_vmr.value.number_variable());
117  b.value(0) = Broadener_vmr.value;
118  boost::shared_ptr<Absco> self_ptr = to_ptr(const_cast<Absco&>(*this));
119  AbscoInterpolator aint(self_ptr, p, t, b);
121  (aint.absorption_cross_section_deriv(Wn)(0), "cm^2");
122 }
123 
124 //-----------------------------------------------------------------------
134 //-----------------------------------------------------------------------
137  const ArrayWithUnit<double, 1>& Press,
138  const ArrayAdWithUnit<double, 1>& Temp,
139  const ArrayAdWithUnit<double, 1>& Broadener_vmr)
140  : absco(A),
141  ip(Press.rows()), itp1(Press.rows()), itp2(Press.rows()), ib(Press.rows()),
142  ib2(Press.rows()), dftp1_dt(Press.rows()),
143  dftp2_dt(Press.rows()), dfb_db(Press.rows()), fp(Press.rows()),
144  fb(Press.rows()), ftp1(Press.rows()), ftp2(Press.rows()),
145  res(Press.rows(), std::max(Temp.value.number_variable(),
146  Broadener_vmr.value.number_variable()))
147 {
148  if(Press.rows() != Temp.rows() ||
149  Press.rows() != Broadener_vmr.rows())
150  throw Exception("Pressure, Temperature, and Broadener_vmr arrays needs to be the same size");
151  p.reference(Press.convert(units::Pa).value);
152  t.reference(Temp.convert(units::K).value);
153  b.reference(Broadener_vmr.convert(units::dimensionless).value);
154  t_jac.reference(to_c_order(t.jacobian()));
155  b_jac.reference(to_c_order(b.jacobian()));
156 
157  absco->fill_pgrid_tgrid_and_bgrid();
158  for(int i = 0; i < p.rows(); ++i) {
159  double unused;
160  fp(i) = interpol(p(i), absco->pgrid, ip(i), unused);
161  // We might not actually need to interpolate over broadener
162  if(absco->bgrid.size() ==1) {
163  ib(i) = 0;
164  ib2(i) = 0;
165  dfb_db(i) = 0;
166  fb(i) = 1;
167  } else {
168  fb(i) = interpol(b.value()(i), absco->bgrid, ib(i), dfb_db(i));
169  ib2(i) = ib(i) + 1;
170  }
171  ftp1(i) = interpol(t.value()(i), absco->tgrid[ip(i)], itp1(i), dftp1_dt(i));
172  ftp2(i) = interpol(t.value()(i), absco->tgrid[ip(i) + 1], itp2(i),
173  dftp2_dt(i));
174  }
175 }
176 
177 template<class T> Array<double, 1>
178 AbscoInterpolator::absorption_cross_section_noderiv_calc(double wn) const
179 {
180  Array<T, 3> a(absco->read<T>(wn));
181  for(int i = 0; i < res.rows(); ++i) {
182  double t11 = a(ip(i), itp1(i), ib(i)) * (1 - ftp1(i)) +
183  a(ip(i), itp1(i) + 1, ib(i)) * ftp1(i);
184  double t12 = a(ip(i) + 1, itp2(i), ib(i)) * (1 - ftp2(i)) +
185  a(ip(i) + 1, itp2(i) + 1, ib(i)) * ftp2(i);
186  double t1 = t11 * (1 - fp(i)) + t12 * fp(i);
187  double t21 = a(ip(i), itp1(i), ib2(i)) * (1 - ftp1(i)) +
188  a(ip(i), itp1(i) + 1, ib2(i)) * ftp1(i);
189  double t22 = a(ip(i) + 1, itp2(i), ib2(i)) * (1 - ftp2(i)) +
190  a(ip(i) + 1, itp2(i) + 1, ib2(i)) * ftp2(i);
191  double t2 = t21 * (1 - fp(i)) + t22 * fp(i);
192  res.value()(i) = t1 * (1 - fb(i)) + t2 * fb(i);
193  }
194  // Apply scale
195  res.value() *= absco->table_scale(wn);
196  return res.value();
197 }
198 
199 template Array<double, 1> AbscoInterpolator::absorption_cross_section_noderiv_calc<double>(double wn) const;
200 template Array<double, 1> AbscoInterpolator::absorption_cross_section_noderiv_calc<float>(double wn) const;
201 
202 //-----------------------------------------------------------------------
206 //-----------------------------------------------------------------------
207 
209 (double wn) const
210 {
211  if(absco->is_float())
212  return absorption_cross_section_noderiv_calc<float>(wn);
213  else
214  return absorption_cross_section_noderiv_calc<double>(wn);
215 }
216 
217 template<class T> ArrayAd<double, 1>
218 AbscoInterpolator::absorption_cross_section_deriv_calc(double wn) const
219 {
220  Range ra(Range::all());
221  Array<T, 3> a(absco->read<T>(wn));
222  // Turns out that jacobian calculation is faster if we use pointers.
223  // This is *not* true for things like itp1(i), the speed is the same
224  // (for gcc 4.6, -O2), so we leave these with the clearer expression.
225  double *restrict res_jac_p = res.jacobian().data();
226  const double* restrict t_jac_p = t_jac.data();
227  const double* restrict b_jac_p = b_jac.data();
228  for(int i = 0; i < res.rows(); ++i) {
229  double t11 = a(ip(i), itp1(i), ib(i)) * (1 - ftp1(i)) +
230  a(ip(i), itp1(i) + 1, ib(i)) * ftp1(i);
231  double dt11_dt =
232  (a(ip(i), itp1(i) + 1, ib(i)) - a(ip(i), itp1(i), ib(i))) * dftp1_dt(i);
233  double t12 = a(ip(i) + 1, itp2(i), ib(i)) * (1 - ftp2(i)) +
234  a(ip(i) + 1, itp2(i) + 1, ib(i)) * ftp2(i);
235  double dt12_dt =
236  (a(ip(i) + 1, itp2(i) + 1, ib(i)) - a(ip(i) + 1, itp2(i), ib(i))) *
237  dftp2_dt(i);
238  double t1 = t11 * (1 - fp(i)) + t12 * fp(i);
239  double dt1_dt =
240  dt11_dt * (1 - fp(i)) + dt12_dt * fp(i);
241 
242  double t21 = a(ip(i), itp1(i), ib2(i)) * (1 - ftp1(i)) +
243  a(ip(i), itp1(i) + 1, ib2(i)) * ftp1(i);
244  double dt21_dt =
245  (a(ip(i), itp1(i) + 1, ib2(i)) - a(ip(i), itp1(i), ib2(i))) * dftp1_dt(i);
246  double t22 = a(ip(i) + 1, itp2(i), ib2(i)) * (1 - ftp2(i)) +
247  a(ip(i) + 1, itp2(i) + 1, ib2(i)) * ftp2(i);
248  double dt22_dt =
249  (a(ip(i) + 1, itp2(i) + 1, ib2(i)) - a(ip(i) + 1, itp2(i), ib2(i))) *
250  dftp2_dt(i);
251  double t2 = t21 * (1 - fp(i)) + t22 * fp(i);
252  double dt2_dt =
253  dt21_dt * (1 - fp(i)) + dt22_dt * fp(i);
254  res.value()(i) = t1 * (1 - fb(i)) + t2 * fb(i);
255  double dr_db =
256  (t2 - t1) * dfb_db(i);
257  double dr_dt =
258  dt1_dt * (1 - fb(i)) + dt2_dt * fb(i);
259  if(!t.is_constant() && !b.is_constant())
260  for(int k = 0; k < res.jacobian().cols(); ++k)
261  *res_jac_p++ = dr_dt * *t_jac_p++ + dr_db * *b_jac_p++;
262  else if(!t.is_constant())
263  for(int k = 0; k < res.jacobian().cols(); ++k)
264  *res_jac_p++ = dr_dt * *t_jac_p++;
265  else if(!b.is_constant())
266  for(int k = 0; k < res.jacobian().cols(); ++k)
267  *res_jac_p++ = dr_db * *b_jac_p++;
268  }
269  // Apply scale
270  double s = absco->table_scale(wn);
271  res.value() *= s;
272  res.jacobian() *= s;
273  return res;
274 }
275 
276 template ArrayAd<double, 1> AbscoInterpolator::absorption_cross_section_deriv_calc<double>(double wn) const;
277 template ArrayAd<double, 1> AbscoInterpolator::absorption_cross_section_deriv_calc<float>(double wn) const;
278 
279 //-----------------------------------------------------------------------
283 //-----------------------------------------------------------------------
284 
286 (double wn) const
287 {
288  if(absco->is_float())
289  return absorption_cross_section_deriv_calc<float>(wn);
290  else
291  return absorption_cross_section_deriv_calc<double>(wn);
292 }
This class is used to read the absco tables.
Definition: absco.h:56
ArrayAdWithUnit< T, D > convert(const Unit &R) const
Convert to the given units.
const Unit s("s", 1.0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0)
AbscoInterpolator(const boost::shared_ptr< Absco > &A, const ArrayWithUnit< double, 1 > &Press, const ArrayAdWithUnit< double, 1 > &Temp, const ArrayAdWithUnit< double, 1 > &Broadener_vmr)
Set up a AbscoInterpolator for the given set up pressure, temperature, and broadner VMR...
Definition: absco.cc:136
This is a AutoDerivative that also has units associated with it.
const Unit dimensionless("dimensionless", 1.0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
const Unit Pa("Pa", N/(m *m))
ArrayAd< double, 1 > absorption_cross_section_deriv(double wn) const
Return absorption cross section, with derivatives.
Definition: absco.cc:286
This is the base of the exception hierarchy for Full Physics code.
Definition: fp_exception.h:16
boost::shared_ptr< T > to_ptr(T &t)
Helper routine to get a shared_ptr from a reference.
Definition: null_deleter.h:24
#define REGISTER_LUA_DERIVED_CLASS(X, Y)
Definition: register_lua.h:136
blitz::Array< T, D > value
Apply value function to a blitz array.
const Unit A("A", 1.0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0)
void resize(const blitz::TinyVector< int, D > &Shape, int nvar)
Definition: array_ad.h:177
const Unit K("K", 1.0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0)
This is a helper class that calculates the absorption cross section for a fixed set of Pressure...
Definition: absco.h:20
int number_variable() const
Number of variables in gradient.
We frequently have a double with units associated with it.
int number_variable() const
Definition: array_ad.h:376
virtual DoubleWithUnit absorption_cross_section(double Wn, const DoubleWithUnit &Press, const DoubleWithUnit &Temp, const DoubleWithUnit &Broadener_vmr) const
This interpolates the ABSCO data to give absorption cross section for a given pressure, temperature, and broadener VMR.
Definition: absco.cc:81
This class determine the gaseous absorption coefficient for a given wave number, temperature and pres...
blitz::Array< double, 1 > absorption_cross_section_noderiv(double wn) const
Return absorption cross section, without derivatives.
Definition: absco.cc:209
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
ArrayWithUnit< T, D > convert(const Unit &R) const
Convert to the given units.
blitz::Array< T, D > to_c_order(const blitz::Array< T, D > &In)
Ensure that a given blitz::Array is contiguous, not reversed, and in C RowMajorArray format...

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