12 void lr_init(
const int* nstream,
13 const int* nstokes,
const int* surftype,
14 void** l_rad_struct_c);
16 void init_l_rad(
void** l_rad_struct_c,
const double* sza,
17 const double* zen,
const double* azm,
const double* alt,
18 const double* radius_km,
const int* nlayer,
19 const bool* regular_ps,
const bool* enhanced_ps,
const bool* pure_nadir);
22 const int* nstokes,
const double* tau,
23 const double* L_tau,
const double* omega,
24 const double* L_omega,
25 const double* Zmat,
const double* L_Zmat,
26 const double* fscale,
const double* L_fscale,
27 const double* spars,
const int* nspars,
28 const int* need_jacobians_i,
29 double* R1,
double* L_R1,
33 const int* n_params,
const int* nstokes,
const int* n_streams,
34 const int*n_scatt,
const double* tau,
const double* L_tau,
35 const double* omega,
const double* L_omega,
36 const double* spars,
const int* nspars,
37 const double* coefs,
const double* L_coefs,
const int* n_eff_coefs,
38 const int* need_jacobians_i,
39 double* R2,
double* L_R2,
double* Ls_R2,
40 double* ICorr,
double* L_ICorr,
double* Ls_ICorr);
42 void calc_z(
void*
const* l_rad_struct_c,
const int* nlay,
const int* nstokes,
43 const int* nmom,
const int* npar,
const double* dcoef,
44 const double* l_dcoef,
double* zmat,
double* l_zmat);
50 bool Pure_nadir,
const PsMode ps_mode)
51 : nstream(Number_stream),
52 nstokes(Number_stokes),
53 surface_type(Surface_type),
54 use_tms_correction(Tms_correction),
55 pure_nadir(Pure_nadir)
69 void LRadDriver::initialize(
const PsMode ps_mode)
80 lr_init(&nstream, &nstokes, &surface_type, &l_rad_struct);
99 int nlayer = alt.rows() - 1;
103 init_l_rad(&l_rad_struct, &sza, &zen, &azm, alt.dataFirst(),
104 &radius_km, &nlayer, ®ular_ps, &enhanced_ps, &pure_nadir);
118 int nlayer = pf.
cols();
122 zmat.
value().reference
123 (Array<double, 2>(nlayer, nstokes, ColumnMajorArray<2>()));
125 (Array<double, 3>(nlayer, nstokes, natm_jac, ColumnMajorArray<3>()));
128 int nmom = pf.
rows() - 1;
129 calc_z(&l_rad_struct, &nlayer, &nstokes, &nmom, &natm_jac, pf_f.dataFirst(),
130 l_pf_f.dataFirst(), zmat.
value().dataFirst(),
137 if (surface_param_f.rows() != surface_param.rows()) {
138 surface_param_f.reference(Array<double, 1>(surface_param.rows(), ColumnMajorArray<1>()));
140 surface_param_f = surface_param;
144 const Array<double, 1>& ssa,
145 const Array<double, 3>& pf,
146 const Array<double, 2>& zmat)
149 if (tau_f.rows() != od.rows()) {
150 tau_f.reference(Array<double, 1>(od.shape(), ColumnMajorArray<1>()));
154 if (omega_f.rows() != ssa.rows()) {
155 omega_f.reference(Array<double, 1>(ssa.shape(), ColumnMajorArray<1>()));
159 if(pf_f.rows() != pf.rows() or pf_f.cols() != pf.cols() or pf_f.depth() != pf.depth()) {
160 pf_f.reference(Array<double, 3>(pf.shape(), ColumnMajorArray<3>()));
164 if (zmat_f.rows() != zmat.rows() or zmat_f.cols() != zmat.cols()) {
165 zmat_f.reference(Array<double, 2>(zmat.shape(), ColumnMajorArray<2>()));
178 int nmom = 2 * nstream;
180 if(fscale_f.rows() != od.rows()) {
181 fscale_f.reference(Array<double, 1>(od.shape(), ColumnMajorArray<1>()));
184 if (use_tms_correction) {
185 fscale_f = pf(nmom, Range::all(), 0) / (2 * nmom + 1);
195 need_jacobians_i = 0;
199 if(jac_atm_f.rows() !=
number_stokes() or jac_atm_f.cols() != tau_f.rows()) {
204 if (jac_surf_f.rows() !=
number_stokes() or jac_surf_f.cols() != surface_param_f.rows()) {
209 if(l_tau_f.rows() != tau_f.rows()) {
210 l_tau_f.resize(tau_f.rows(), 1);
214 if(l_omega_f.rows() != omega_f.rows()) {
215 l_omega_f.resize(omega_f.rows(), 1);
219 if(l_pf_f.rows() != pf_f.rows() or l_pf_f.cols() != pf_f.cols() or l_pf_f.depth() != pf_f.depth()) {
220 l_pf_f.resize(pf_f.rows(), pf_f.cols(), pf_f.depth(), 1);
224 if(l_zmat_f.rows() != zmat_f.rows() or l_zmat_f.cols() != zmat_f.cols()) {
225 l_zmat_f.resize(zmat_f.rows(), zmat_f.cols(), 1);
229 if(l_fscale_f.rows() != fscale_f.rows()) {
230 l_fscale_f.resize(fscale_f.rows(), 1);
241 need_jacobians_i = 1;
248 if(jac_atm_f.rows() !=
number_stokes() or jac_atm_f.cols() != od.
rows() or jac_atm_f.depth() != natm_jac) {
249 jac_atm_f.reference(Array<double, 3>(
number_stokes(), od.
rows(), natm_jac, ColumnMajorArray<3>()));
252 if (jac_surf_f.rows() !=
number_stokes() or jac_surf_f.cols() != surface_param_f.rows()) {
253 jac_surf_f.reference(Array<double, 2>(
number_stokes(), surface_param_f.rows(), ColumnMajorArray<2>()));
257 if(l_tau_f.rows() != od.
jacobian().rows() or l_tau_f.cols() != od.
jacobian().cols()) {
258 l_tau_f.reference(Array<double, 2>(od.
jacobian().shape(), ColumnMajorArray<2>()));
262 if(l_omega_f.rows() != ssa.
jacobian().rows() or l_omega_f.cols() != ssa.
jacobian().cols()) {
263 l_omega_f.reference(Array<double, 2>(ssa.
jacobian().shape(), ColumnMajorArray<2>()));
267 if(l_pf_f.rows() != pf.
jacobian().rows() or l_pf_f.cols() != pf.
jacobian().cols() or l_pf_f.depth() != pf.
jacobian().extent(fourthDim) or l_pf_f.extent(fourthDim)) {
268 l_pf_f.reference(Array<double, 4>(pf.
jacobian().shape(), ColumnMajorArray<4>()));
272 if(l_zmat_f.rows() != zmat.
jacobian().rows() or l_zmat_f.cols() != zmat.
jacobian().cols() or l_zmat_f.depth() != zmat.
jacobian().depth()) {
273 l_zmat_f.reference(Array<double, 3>(zmat.
jacobian().shape(), ColumnMajorArray<3>()));
278 int nmom = 2 * nstream;
279 Range ra(Range::all());
281 if(l_fscale_f.rows() != od.
rows() or l_fscale_f.cols() != natm_jac) {
282 l_fscale_f.reference(Array<double, 2>(od.
rows(), natm_jac, ColumnMajorArray<2>()));
285 if (use_tms_correction) {
286 l_fscale_f = pf.
jacobian()(nmom, ra, 0, ra) / (2 * nmom + 1);
294 void LRadDriver::check_rt_inputs()
296 if(surface_param_f.rows() == 0) {
297 throw Exception(
"surface_param_f not allocated");
300 if(tau_f.rows() == 0) {
304 if(omega_f.rows() == 0) {
305 throw Exception(
"omega_f not allocated");
308 if(zmat_f.rows() == 0) {
312 if(fscale_f.rows() == 0) {
313 throw Exception(
"fscale_f not allocated");
316 if (need_jacobians_i == 1) {
317 if(l_tau_f.rows() == 0) {
318 throw Exception(
"l_tau_f not allocated");
321 if(l_omega_f.rows() == 0) {
322 throw Exception(
"l_omega_f not allocated");
325 if(l_zmat_f.rows() == 0) {
326 throw Exception(
"l_zmat_f not allocated");
329 if(l_fscale_f.rows() == 0) {
330 throw Exception(
"l_fscale_f not allocated");
333 if(jac_atm_f.rows() == 0) {
334 throw Exception(
"jac_atm_f not allocated");
337 if(jac_surf_f.rows() == 0) {
338 throw Exception(
"jac_surf_f not allocated");
349 stokes_val_f.reference(Array<double, 1>(
number_stokes(), ColumnMajorArray<1>()));
353 Array<double, 1> r1(stokes_val_f);
355 int nlayer = tau_f.rows();
356 int nspars = surface_param_f.rows();
357 int natm_jac = jac_atm_f.depth();
360 tau_f.dataFirst(), l_tau_f.dataFirst(),
362 l_omega_f.dataFirst(), zmat_f.dataFirst(),
363 l_zmat_f.dataFirst(), fscale_f.dataFirst(),
364 l_fscale_f.dataFirst(), surface_param_f.dataFirst(),
367 r1.dataFirst(), jac_atm_f.dataFirst(), jac_surf_f.dataFirst());
375 if(pf_f.rows() == 0) {
379 if (need_jacobians_i == 1) {
380 if(l_pf_f.rows() == 0) {
386 stokes_val_f.reference(Array<double, 1>(
number_stokes(), ColumnMajorArray<1>()));
389 int nscatt = pf_f.depth();
390 int nlayer = tau_f.rows();
391 int nmom = 2 * nstream;
392 int nspars = surface_param_f.rows();
393 int natm_jac = jac_atm_f.depth();
395 Range ra(Range::all());
400 Array<int, 1> neff_coefs(nlayer, ColumnMajorArray<1>());
401 neff_coefs = nmom - 1;
404 Array<double, 2> ls_r2(
number_stokes(), nspars, ColumnMajorArray<2>());
406 natm_jac, ColumnMajorArray<3>());
408 Array<double, 1> ls_icorr(nspars);
409 Array<double, 2> l_icorr(nlayer, natm_jac,
410 ColumnMajorArray<2>());
416 Array<double, 3> coefs_f(
to_fortran(pf_f(Range(0, nmom - 1), ra, ra)));
417 Array<double, 4> l_coefs_f(
to_fortran(l_pf_f(Range(0, nmom - 1), ra, ra)));
421 tau_f.dataFirst(), l_tau_f.dataFirst(),
422 omega_f.dataFirst(), l_omega_f.dataFirst(),
423 surface_param_f.dataFirst(), &nspars,
424 coefs_f.dataFirst(), l_coefs_f.dataFirst(),
425 neff_coefs.dataFirst(),
427 r2.dataFirst(), l_r2.dataFirst(), ls_r2.dataFirst(),
428 &icorr, l_icorr.dataFirst(), ls_icorr.dataFirst());
432 stokes_val_f(0) += icorr;
433 stokes_val_f(rpol) += r2(rpol);
435 if (need_jacobians_i == 1) {
436 jac_surf_f(0, ra) += ls_icorr;
437 jac_surf_f(rpol, ra) += ls_r2(rpol, ra);
438 jac_atm_f(0, ra, ra) += l_icorr;
439 jac_atm_f(rpol, ra, ra) += l_r2(rpol, ra, ra);
445 if (stokes_val_f.rows() == 0) {
446 throw Exception(
"Stokes have not yet been allocated, use an RT operation first");
454 if (jac_atm_f.rows() == 0) {
455 throw Exception(
"Atmospheric jacobians array has not yet been allocated. Set up linear inputs first.");
463 if (jac_surf_f.rows() == 0) {
464 throw Exception(
"Surface jacobians array has not yet been allocated. Set up linear inputs first.");
472 Os <<
"LRadDriver:\n";
473 Os <<
" Number stream: " << nstream <<
"\n" 474 <<
" Number stokes: " << nstokes <<
"\n" 475 <<
" Surface type: " << surface_type <<
"\n" 476 <<
" Use TMS Correction: " 477 << (use_tms_correction ?
"True\n" :
"False\n")
478 <<
" Pure nadir mode: " 479 << (pure_nadir ?
"True" :
"False") <<
"\n";
#define range_check(V, Min, Max)
Range check.
virtual blitz::Array< double, 3 > atmospheric_jacobian() const
Atmospheric jacobian from last calculation.
void l_rad_first_driver(void *const *l_rad_struct_c, const int *nlayer, const int *natm_der, const int *nstokes, const double *tau, const double *L_tau, const double *omega, const double *L_omega, const double *Zmat, const double *L_Zmat, const double *fscale, const double *L_fscale, const double *spars, const int *nspars, const int *need_jacobians_i, double *R1, double *L_R1, double *Ls_R1)
virtual void calculate_first_order()
Perform radiative transfer calculation with the values setup by setup_optical_inputs and setup_linear...
virtual void setup_geometry(blitz::Array< double, 1 > alt, double sza, double zen, double azm) const
Setup viewing geometry, should only be called once per instance or if the viewing geometry changes...
const DoubleWithUnit wgs84_a(6378137.0000, units::m)
Equatorial radius.
This is the base of the exception hierarchy for Full Physics code.
const blitz::Array< T, D+1 > jacobian() const
virtual int number_stokes() const
virtual void print(std::ostream &Os, bool Short_form=false) const
virtual void setup_linear_inputs(const ArrayAd< double, 1 > &od, const ArrayAd< double, 1 > &ssa, const ArrayAd< double, 3 > &pf, const ArrayAd< double, 2 > &zmat)
Set up linearization, weighting functions.
Apply value function to a blitz array.
void lr_cleanup(void **l_rad_struct_c)
const blitz::Array< T, D > & value() const
blitz::Array< T, D > to_fortran(const blitz::Array< T, D > &In)
Ensure that a given blitz::Array is contiguous, not reversed, and in fortran ColumnMajorArray format...
virtual blitz::Array< double, 2 > surface_jacobian() const
Surface jacobian.
virtual blitz::Array< double, 1 > stokes() const
Retrieve the stokes values calculated.
LRadDriver(int Number_stream, int Number_stokes, int surface_type, bool Tms_Correction=false, bool Pure_nadir=false, const PsMode ps_mode=DETECT)
virtual void setup_surface_params(const blitz::Array< double, 1 > &surface_param)
Set up surface parameters for spectral point.
ArrayAd< double, 2 > z_matrix(const ArrayAd< double, 3 > &pf) const
Calculate the z matrix.
int number_variable() const
DoubleWithUnit convert(const Unit &R) const
Convert to the given units.
virtual void setup_optical_inputs(const blitz::Array< double, 1 > &od, const blitz::Array< double, 1 > &ssa, const blitz::Array< double, 3 > &pf, const blitz::Array< double, 2 > &zmat)
Set up optical depth, single scattering albedo and scattering matrix Should be called per spectral po...
void l_rad_second_driver(void *const *l_rad_struct_c, const int *n_layers, const int *n_params, const int *nstokes, const int *n_streams, const int *n_scatt, const double *tau, const double *L_tau, const double *omega, const double *L_omega, const double *spars, const int *nspars, const double *coefs, const double *L_coefs, const int *n_eff_coefs, const int *need_jacobians_i, double *R2, double *L_R2, double *Ls_R2, double *ICorr, double *L_ICorr, double *Ls_ICorr)
void init_l_rad(void **l_rad_struct_c, const double *sza, const double *zen, const double *azm, const double *alt, const double *radius_km, const int *nlayer, const bool *regular_ps, const bool *enhanced_ps, const bool *pure_nadir)
Contains classes to abstract away details in various Spurr Radiative Transfer software.
#define range_min_check(V, Min)
Range check.
const Unit km("km", 1e3 *m)
void lr_init(const int *nstream, const int *nstokes, const int *surftype, void **l_rad_struct_c)
virtual ~LRadDriver()
Destructor.
void calc_z(void *const *l_rad_struct_c, const int *nlay, const int *nstokes, const int *nmom, const int *npar, const double *dcoef, const double *l_dcoef, double *zmat, double *l_zmat)
virtual void clear_linear_inputs()
Mark that we are not retrieving weighting functions.
virtual void calculate_second_order()
Perform radiative transfer calculation with the values setup by setup_optical_inputs and setup_linear...