12 using namespace blitz;
34 const blitz::Array<double, 1>& Sza,
35 const blitz::Array<double, 1>& Zen,
36 const blitz::Array<double, 1>& Azm,
38 const bool do_thermal)
40 sza(Sza.copy()), zen(Zen.copy()), azm(Azm.copy()),
41 do_solar_sources(do_solar), do_thermal_emission(do_thermal),
42 alt_spec_index_cache(-1), geo_spec_index_cache(-1)
47 throw Exception(
"Sza, Zen, and Atm all need to be size number_spectrometer()");
55 atm->add_observer(*
this);
60 if(dynamic_cast<GroundLambertian*>(
atm->ground().get())) {
62 }
else if(dynamic_cast<GroundCoxmunk*>(
atm->ground().get())) {
64 }
else if(dynamic_cast<GroundCoxmunkPlusLambertian*>(
atm->ground().get())) {
66 }
else if(dynamic_cast<GroundBrdfVeg*>(
atm->ground().get())) {
68 }
else if(dynamic_cast<GroundBrdfSoil*>(
atm->ground().get())) {
72 err_msg <<
"Spurr RT can not determine surface type integer from ground class: " 90 Array<double, 1> atm_alt(
atm->altitude(spec_index).convert(
units::km).value.value());
94 std::cout <<
"# atm_alt:\n" << atm_alt <<
"\n";
108 rt_driver_->brdf_driver()->setup_geometry(
sza(spec_index),
azm(spec_index),
zen(spec_index));
111 std::cout <<
"# Geometry:\n" <<
sza(spec_index) <<
"\n" 112 <<
azm(spec_index) <<
"\n" 113 <<
zen(spec_index) <<
"\n";
121 rt_driver_->setup_thermal_inputs(
atm->surface_blackbody(wn, spec_index).value(),
atm->atmosphere_blackbody(wn, spec_index).value());
128 Range ra(Range::all());
130 Array<double, 1> od_in, ssa_in;
133 od_in.reference(
atm->optical_depth_wrt_iv(Wn, Spec_index, Iv).value() );
134 ssa_in.reference(
atm->single_scattering_albedo_wrt_iv(Wn, Spec_index, Iv).value() );
136 pf.reference(
atm->scattering_moment_wrt_iv(Wn, Spec_index, Iv,
number_moment(), 1)(ra, ra, 0).
value() );
138 od_in.reference(
atm->optical_depth_wrt_iv(Wn, Spec_index).value() );
139 ssa_in.reference(
atm->single_scattering_albedo_wrt_iv(Wn, Spec_index).value() );
141 pf.reference(
atm->scattering_moment_wrt_iv(Wn, Spec_index,
number_moment(), 1)(ra, ra, 0).
value() );
159 rt_driver_->setup_optical_inputs(od_in, ssa_in, pf);
169 throw Exception(
"SpurrRt encountered a NaN in the radiance");
178 Range ra(Range::all());
181 Array<double, 3> jac_iv(0,0,0);
183 od.
reference(
atm->optical_depth_wrt_iv(Wn, Spec_index, Iv));
184 ssa.
reference(
atm->single_scattering_albedo_wrt_iv(Wn, Spec_index, Iv));
190 od.
reference(
atm->optical_depth_wrt_iv(Wn, Spec_index));
191 ssa.
reference(
atm->single_scattering_albedo_wrt_iv(Wn, Spec_index));
195 if(!inter_var.is_constant())
215 bool do_surface_pd = !surface_parameters.is_constant();
217 fabs(Wn - 13050.47) < 0.005)
218 std::cout <<
"# Surface type:\n " <<
surface_type() <<
"\n" 219 <<
"# Surface paramters:\n" << surface_parameters <<
"\n" 220 <<
"# Od:\n" << od <<
"\n" 221 <<
"# SSA:\n" << ssa <<
"\n" 222 <<
"# PF:\n" << pf <<
"\n" 223 <<
"# Do surface pd:\n" << do_surface_pd <<
"\n";
225 rt_driver_->setup_linear_inputs(od, ssa, pf, do_surface_pd);
231 Array<double, 2> jac_atm;
232 Array<double, 1> jac_surf;
233 rt_driver_->copy_jacobians(jac_atm, jac_surf);
244 Array<double, 1> jac(jac_iv.depth());
245 for(
int i = 0; i < jac.rows(); ++i) {
250 for(
int m = 0;
m < jac_iv.rows(); ++
m)
251 for(
int n = 0; n < jac_iv.cols(); ++n)
252 val += jac_atm(n,
m) * jac_iv(
m, n, i);
261 for(
int m = 0;
m < min(jac_surf.rows(), lidort_surface.
jacobian().rows()); ++
m) {
262 val += jac_surf(
m) * lidort_surface.
jacobian()(
m, i);
272 throw Exception(
"SpurrRt encountered a NaN in the radiance");
273 if(any(blitz_isnan(jac)))
274 throw Exception(
"SpurrRt encountered a NaN in the jacobian");
289 Os <<
" Solar zenith angle: \n";
292 Os <<
" Zenith angle: \n";
295 Os <<
" Azimuth angle: \n";
virtual void setup_thermal_inputs(double wn, int spec_index) const
#define range_check(V, Min, Max)
Range check.
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 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.
boost::shared_ptr< SpurrRtDriver > rt_driver_
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.
SpurrRt(const boost::shared_ptr< RtAtmosphere > &Atm, const boost::shared_ptr< StokesCoefficient > &Stokes_coef, const blitz::Array< double, 1 > &Sza, const blitz::Array< double, 1 > &Zen, const blitz::Array< double, 1 > &Azm, bool do_solar=true, bool do_thermal=false)
Constructor.
This is the base of the exception hierarchy for Full Physics code.
const blitz::Array< T, D+1 > jacobian() const
virtual int number_moment() const =0
Number of moments for scattering matrix.
This is a RadiativeTransfer that supplies an interface that can be called for a single wavenumber...
Apply value function to a blitz array.
const blitz::Array< T, D > & value() const
virtual void update_geometry(int spec_index) const
Update the geometry if necessary, only needs to change when spectrometer index changes.
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)
blitz::Array< double, 1 > zen
blitz::Array< double, 1 > azm
void reference(const ArrayAd< T, D > &V)
blitz::Array< double, 1 > sza
virtual void print(std::ostream &Os, bool Short_form=false) const
Print to a stream.
Contains classes to abstract away details in various Spurr Radiative Transfer software.
virtual void update_altitude(int spec_index) const
Update the altitude information.
virtual int number_stokes() const
Number of stokes in returned stokes values Note that LIDORT will only ever calculate the first stoke ...
const Unit km("km", 1e3 *m)
const Unit rad("rad", 1.0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0)
double value(const FullPhysics::AutoDerivative< double > &Ad)
virtual void print(std::ostream &Os, bool Short_form=false) const
Print to stream.
virtual int surface_type() const
Integer representing the surface type using the LIDORT indexing nomenclature.