18 double Absco::interpol(
double X,
const std::vector<double>& Xv,
19 int& i,
double& df_dx)
const 22 i = (int) (std::lower_bound(Xv.begin(), Xv.end(), X) - Xv.begin()) - 1;
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 ;
35 double AbscoInterpolator::interpol(
double X,
const std::vector<double>& Xv,
36 int& i,
double& df_dx)
const 39 i = (int) (std::lower_bound(Xv.begin(), Xv.end(), X) - Xv.begin()) - 1;
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 ;
55 void Absco::fill_pgrid_tgrid_and_bgrid()
const 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)
67 for(
int i = 0; i < bgridg.rows(); ++i)
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);
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()),
149 Press.
rows() != Broadener_vmr.
rows())
150 throw Exception(
"Pressure, Temperature, and Broadener_vmr arrays needs to be the same size");
157 absco->fill_pgrid_tgrid_and_bgrid();
158 for(
int i = 0; i <
p.rows(); ++i) {
160 fp(i) = interpol(
p(i), absco->pgrid, ip(i), unused);
162 if(absco->bgrid.size() ==1) {
168 fb(i) = interpol(b.value()(i), absco->bgrid, ib(i), dfb_db(i));
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),
177 template<
class T> Array<double, 1>
178 AbscoInterpolator::absorption_cross_section_noderiv_calc(
double wn)
const 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);
195 res.value() *= absco->table_scale(wn);
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;
211 if(absco->is_float())
212 return absorption_cross_section_noderiv_calc<float>(wn);
214 return absorption_cross_section_noderiv_calc<double>(
wn);
218 AbscoInterpolator::absorption_cross_section_deriv_calc(
double wn)
const 220 Range ra(Range::all());
221 Array<T, 3> a(absco->read<T>(wn));
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);
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);
236 (a(ip(i) + 1, itp2(i) + 1, ib(i)) - a(ip(i) + 1, itp2(i), ib(i))) *
238 double t1 = t11 * (1 - fp(i)) + t12 * fp(i);
240 dt11_dt * (1 - fp(i)) + dt12_dt * fp(i);
242 double t21 = a(ip(i), itp1(i), ib2(i)) * (1 - ftp1(i)) +
243 a(ip(i), itp1(i) + 1, ib2(i)) * ftp1(i);
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);
249 (a(ip(i) + 1, itp2(i) + 1, ib2(i)) - a(ip(i) + 1, itp2(i), ib2(i))) *
251 double t2 = t21 * (1 - fp(i)) + t22 * fp(i);
253 dt21_dt * (1 - fp(i)) + dt22_dt * fp(i);
254 res.value()(i) = t1 * (1 - fb(i)) + t2 * fb(i);
256 (t2 - t1) * dfb_db(i);
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++;
270 double s = absco->table_scale(wn);
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;
288 if(absco->is_float())
289 return absorption_cross_section_deriv_calc<float>(wn);
291 return absorption_cross_section_deriv_calc<double>(
wn);
This class is used to read the absco tables.
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...
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.
This is the base of the exception hierarchy for Full Physics code.
boost::shared_ptr< T > to_ptr(T &t)
Helper routine to get a shared_ptr from a reference.
#define REGISTER_LUA_DERIVED_CLASS(X, Y)
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)
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...
int number_variable() const
Number of variables in gradient.
We frequently have a double with units associated with it.
int number_variable() const
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.
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.
Contains classes to abstract away details in various Spurr Radiative Transfer software.
#define REGISTER_LUA_END()
AutoDerivative< T > value
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...