10 using namespace blitz;
17 const blitz::Array<double, 1>& Sza,
18 const blitz::Array<double, 1>& Zen,
19 const blitz::Array<double, 1>& Azm,
21 bool Use_first_order_scatt_calc,
28 (
new LRadRt(rts, Spec_bound, Sza, Zen, Azm, Pure_nadir, Use_first_order_scatt_calc,
69 const blitz::Array<double, 1>& Sza,
70 const blitz::Array<double, 1>& Zen,
71 const blitz::Array<double, 1>& Azm,
73 bool Use_first_order_scatt_calc,
75 double Spectrum_spacing,
78 Rt->atmosphere_ptr()),
79 use_first_order_scatt_calc(Use_first_order_scatt_calc),
80 do_second_order(Do_second_order),
81 sza(Sza.copy()), zen(Zen.copy()), azm(Azm.copy()),
83 alt_spec_index_cache(-1)
85 int nstream = rt->number_stream();
90 int nstokes = min(rt->number_stokes(), 3);
92 initialize(Spec_bound, Spectrum_spacing);
97 Pure_nadir, ps_mode));
131 const blitz::Array<double, 1>& Sza,
132 const blitz::Array<double, 1>& Zen,
133 const blitz::Array<double, 1>& Azm,
136 bool Do_second_order,
138 double Spectrum_spacing,
141 use_first_order_scatt_calc(true),
142 do_second_order(Do_second_order),
143 sza(Sza.copy()), zen(Zen.copy()), azm(Azm.copy()),
144 alt_spec_index_cache(-1)
146 initialize(Spec_bound, Spectrum_spacing);
148 driver.reset(
new LRadDriver(Number_stream, Number_stokes,
151 Pure_nadir, ps_mode));
155 void LRadRt::initialize(
const SpectralBound& Spec_bound,
double Spectrum_spacing)
161 throw Exception(
"Spec_bound, Sza, Zen, and Atm all need to be size number_spectrometer()");
171 throw Exception(
"LRadDriver cannot be used without a ground");
179 t = round(t / Spectrum_spacing) * Spectrum_spacing;
183 t = round(t / Spectrum_spacing) * Spectrum_spacing;
191 if(dynamic_cast<GroundLambertian*>(
atm->ground().get())) {
193 }
else if(dynamic_cast<GroundCoxmunk*>(
atm->ground().get())) {
195 }
else if(dynamic_cast<GroundCoxmunkPlusLambertian*>(
atm->ground().get())) {
197 }
else if(dynamic_cast<GroundBrdfVeg*>(
atm->ground().get())) {
199 }
else if(dynamic_cast<GroundBrdfSoil*>(
atm->ground().get())) {
203 err_msg <<
"Spurr RT can not determine surface type integer from ground class: " 209 atm->add_observer(*
this);
221 zmat_interpolate.reset(
new 223 (wmin, z_matrix_min.value(),
224 wmax, z_matrix_max.value()));
226 if(!z_matrix_min.is_constant()) {
227 l_zmat_interpolate.reset(
new 229 (wmin, z_matrix_min.jacobian(),
230 wmax, z_matrix_max.jacobian()));
239 void LRadRt::update_altitude(
int spec_index)
const 241 if(spec_index == alt_spec_index_cache) {
245 alt_spec_index_cache = spec_index;
247 Array<double, 1> alt(
atm->altitude(spec_index).convert(
units::km).value.value());
249 driver->setup_geometry(alt, sza(spec_index), zen(spec_index), azm(spec_index));
254 setup_z_matrix_interpol(wmin[spec_index], pf_min, wmax[spec_index], pf_max);
264 zmat.
value().reference((*zmat_interpolate)(Wn));
266 if(l_zmat_interpolate) {
267 zmat.
jacobian().reference((*l_zmat_interpolate)(Wn));
289 Array<double, 3> jac_iv(0, 0, 0);
294 if(!t.is_constant()) {
307 for(
int i = 0; i < stokes.
rows(); ++i) {
311 if(jac_atm.depth() != 0)
312 for(
int m = 0;
m < jac_iv.rows(); ++
m)
313 for(
int n = 0; n < jac_iv.cols(); ++n) {
314 val += jac_atm(i,
m, n) * jac_iv(
m, n, j);
317 if(!surface_param.is_constant())
318 for(
int m = 0;
m < surface_param.jacobian().rows(); ++
m)
320 jac_surf(i,
m) * surface_param.jacobian()(
m, j);
332 update_altitude(Spec_index);
334 driver->setup_surface_params(
atm->ground()->surface_parameter(Wn, Spec_index).value());
336 Array<double, 1> tau;
337 Array<double, 1> omega;
339 tau.reference(
atm->optical_depth_wrt_iv(Wn, Spec_index).value());
340 omega.reference(
atm->single_scattering_albedo_wrt_iv(Wn, Spec_index).value());
342 tau.reference(
atm->optical_depth_wrt_iv(Wn, Spec_index, Iv).value());
343 omega.reference(
atm->single_scattering_albedo_wrt_iv(Wn, Spec_index, Iv).value());
346 Array<double, 3> pf(0, 0, 0);
348 if(rt || do_second_order) {
350 int nscat = (do_second_order ? -1 : 1);
354 pf.reference(
atm->scattering_moment_wrt_iv(Wn, Spec_index, nmom,
357 pf.reference(
atm->scattering_moment_wrt_iv(Wn, Spec_index, Iv, nmom,
367 Array<double, 2> zmat = get_z_matrix(Wn, Spec_index, Iv).
value();
369 driver->setup_optical_inputs(tau, omega, pf, zmat);
371 driver->clear_linear_inputs();
373 driver->calculate_first_order();
377 if(!use_first_order_scatt_calc) {
378 driver->stokes()(0) = 0;
381 if(do_second_order) {
382 driver->calculate_second_order();
387 Array<double, 1>
stokes(driver->stokes().shape());
388 stokes = driver->stokes();
393 Array<double, 1> t(rt->stokes_single_wn(Wn, Spec_index, Iv));
407 update_altitude(Spec_index);
409 driver->setup_surface_params(
atm->ground()->surface_parameter(Wn, Spec_index).value());
413 Array<double, 3> jac_iv(0, 0, 0);
416 tau.
reference(
atm->optical_depth_wrt_iv(Wn, Spec_index));
417 omega.
reference(
atm->single_scattering_albedo_wrt_iv(Wn, Spec_index));
420 if(!t.is_constant()) {
424 tau.
reference(
atm->optical_depth_wrt_iv(Wn, Spec_index, Iv));
425 omega.
reference(
atm->single_scattering_albedo_wrt_iv(Wn, Spec_index, Iv));
434 if(rt || do_second_order) {
436 int nscat = (do_second_order ? -1 : 1);
440 pf.
reference(
atm->scattering_moment_wrt_iv(Wn, Spec_index, nmom,
443 pf.
reference(
atm->scattering_moment_wrt_iv(Wn, Spec_index, Iv, nmom,
457 driver->setup_linear_inputs(tau, omega, pf, zmat);
459 driver->calculate_first_order();
463 if(!use_first_order_scatt_calc) {
464 driver->stokes()(0) = 0;
465 driver->surface_jacobian()(0, Range::all()) = 0;
466 driver->atmospheric_jacobian()(0, Range::all(), Range::all()) = 0;
469 if(do_second_order) {
470 driver->calculate_second_order();
477 stokes.
value() = driver->stokes();
479 apply_jacobians(Wn, Spec_index, stokes, driver->atmospheric_jacobian(), driver->surface_jacobian(), Iv);
497 <<
" Solar zenith angle: \n";
500 Os <<
" Zenith angle: \n";
503 Os <<
" Azimuth angle: \n";
511 Os <<
" Radiative Transfer:\n";
513 rt->print(opad1,
true);
519 driver->print(opad1, Short_form);
void resize_number_variable(int nvar)
#define range_check(V, Min, Max)
Range check.
virtual int number_stream() const
Number of streams to use in processing.
virtual int number_spectrometer() const
Number of spectrometer we have.
This is a filtering stream that adds a pad to the front of every line written out.
boost::shared_ptr< RtAtmosphere > atm
virtual blitz::Array< double, 1 > stokes_single_wn(double Wn, int Spec_index, const ArrayAd< double, 2 > &Iv) const
Calculate stokes vector for the given wavenumber.
LRadRt(const boost::shared_ptr< RadiativeTransferSingleWn > &Rt, const SpectralBound &Spec_bound, const blitz::Array< double, 1 > &Sza, const blitz::Array< double, 1 > &Zen, const blitz::Array< double, 1 > &Azm, bool Pure_nadir, bool Use_first_order_scatt_calc=true, bool Do_second_order=false, double Spectrum_spacing=0.01, const LRadDriver::PsMode ps_mode=LRadDriver::DETECT)
Constructor.
virtual ArrayAd< double, 1 > stokes_and_jacobian_single_wn(double Wn, int Spec_index, const ArrayAd< double, 2 > &Iv) const
Calculate stokes vector and Jacobian for the given wavenumber.
This is the base of the exception hierarchy for Full Physics code.
#define REGISTER_LUA_DERIVED_CLASS(X, Y)
This class drives the LRAD code, which gives a polarization correction to scalar intensity and jacobi...
const blitz::Array< T, D+1 > jacobian() const
virtual int surface_type() const
Returns an integer with l_rad's representation of surface type.
This is a RadiativeTransfer that supplies an interface that can be called for a single wavenumber...
Apply value function to a blitz array.
DoubleWithUnit lower_bound(int Spec_index) const
Lower bound of window slot.
const blitz::Array< T, D > & value() const
const Unit inv_cm("cm^-1", pow(cm, -1))
This runs a Radiative Transfer code to determine the reflectance for a given set of wavelengths...
The AutoDerivative<T> works well, and it works with blitz if you create a blitz::Array<AutoDerivative...
This gives the upper and lower bounds of the SpectralWindow.
This does linear interpolate between two points.
virtual blitz::Array< double, 2 > stokes(const SpectralDomain &Spec_domain, int Spec_index) const
Calculate stokes vector for the given set of wavenumbers/wavelengths.
const Unit m("m", 1.0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
int number_variable() const
This class drives the LRAD code, which gives a polarization correction to scalar intensity and jacobi...
virtual int number_stokes() const
Number of stokes parameters we will return in stokes and stokes_and_jacobian.
void reference(const ArrayAd< T, D > &V)
Contains classes to abstract away details in various Spurr Radiative Transfer software.
#define REGISTER_LUA_END()
def(luabind::constructor< int >()) .def("rows"
int number_spectrometer() const
Number of spectrometers.
const Unit km("km", 1e3 *m)
virtual void print(std::ostream &Os, bool Short_form=false) const
Print to stream.
DoubleWithUnit upper_bound(int Spec_index) const
Upper bound of window slot.
virtual void print(std::ostream &Os, bool Short_form=false) const
Print to stream.