10 #include <boost/foreach.hpp> 13 using namespace blitz;
84 : absorber(absorberv), pressure(pressurev), temperature(temperaturev),
85 aerosol(aerosolv), rh(rhv), ground_ptr(groundv), surface_temp(surface_tempv),
86 constant(C), alt(altv),
89 spec_index_tau_cache(-1),
108 : absorber(absorberv), pressure(pressurev), temperature(temperaturev),
109 aerosol(aerosolv), rh(rhv), ground_ptr(groundv),
110 constant(C), alt(altv),
113 spec_index_tau_cache(-1),
131 : absorber(absorberv), pressure(pressurev), temperature(temperaturev),
132 aerosol(aerosolv), rh(rhv),
133 constant(C), alt(altv),
136 spec_index_tau_cache(-1),
155 : absorber(absorberv), pressure(pressurev), temperature(temperaturev),
156 rh(rhv), ground_ptr(groundv), surface_temp(surface_tempv),
157 constant(C), alt(altv),
160 spec_index_tau_cache(-1),
178 : absorber(absorberv), pressure(pressurev), temperature(temperaturev),
179 rh(rhv), ground_ptr(groundv),
180 constant(C), alt(altv),
183 spec_index_tau_cache(-1),
200 : absorber(absorberv), pressure(pressurev), temperature(temperaturev),
201 constant(C), rh(rhv), alt(altv), sv_size(0), wn_tau_cache(-1),
202 spec_index_tau_cache(-1),
208 void AtmosphereOco::initialize()
211 throw Exception(
"Absorber is not allowed to be null in AtmosphereOco");
213 throw Exception(
"Pressure is not allowed to be null in AtmosphereOco");
215 throw Exception(
"Temperature is not allowed to be null in AtmosphereOco");
218 throw Exception(
"Altitude is not allowed to be null in AtmosphereOco");
220 rayleigh.reset(
new Rayleigh(pressure, alt, *constant));
222 aerosol->add_observer(*
this);
223 pressure->add_observer(*
this);
238 aerosol = new_aerosol;
241 aerosol->add_observer(*
this);
244 aerosol->notify_update(Sv);
248 spec_index_tau_cache = -1;
258 AtmosphereOco::scattering_moment_common(
double wn,
int nummom,
262 firstIndex i1; secondIndex i2; thirdIndex i3; fourthIndex i4;
264 Range ra(Range::all());
275 if(nummom == -1 || nummom > coefsr.rows() - 1)
276 r1 = Range(0, coefsr.rows() - 1);
278 r1 = Range(0, nummom);
283 r2 = Range(0, numscat - 1);
286 int s1 = (nummom == -1 ? coefsr.rows() : nummom + 1);
292 if(s1 > coefsr.rows())
295 res(r1, i, r2) = coefsr(r1, r2);
299 Range r1(0, coefsr.rows() - 1);
300 Range ra = Range::all();
302 pf(aerosol->pf_mom(wn, frac_aer, nummom, numscat));
303 Range r2(0, coefsr.rows() - 1);
304 pf.
value()(r2,ra,ra) += frac_ray.
value()(i2) * coefsr(i1,i3);
305 pf.jacobian()(r2,ra,ra,ra) += frac_ray.
jacobian()(i2,i4) * coefsr(i1,i3);
320 std::ostringstream os;
346 bool AtmosphereOco::fill_cache(
double wn,
int spec_index)
const 348 if(fabs(wn - wn_tau_cache) < 1e-6 &&
349 spec_index == spec_index_tau_cache)
353 if(spec_index != spec_index_tau_cache) {
355 totaltaug_cache->clear();
356 spec_index_tau_cache = spec_index;
361 calc_intermediate_variable(wn, spec_index);
362 calc_rt_parameters(wn, intermediate_v);
372 void AtmosphereOco::calc_intermediate_variable(
double wn,
int spec_index)
375 firstIndex i1; secondIndex i2; thirdIndex i3;
376 Range ra(Range::all());
387 2 + (aerosol ? aerosol->number_particle() : 0),
393 Range taua_r(taua_0_index, taua_0_index +
394 (aerosol ? aerosol->number_particle() - 1 : 0));
395 taua_i.
reference(intermediate_v(ra, taua_r));
406 taur.
value() = rayleigh->optical_depth_each_layer(wn, spec_index).value();
408 taur = rayleigh->optical_depth_each_layer(wn, spec_index);
410 absorber->optical_depth_each_layer(wn, spec_index);
413 totaltaug.
value() = sum(taug_i.
value()(i2, i1), i2);
421 totaltaug_cache->insert(wn, totaltaug);
423 taug.
value() = sum(taug_i.
value()(i1, i2), i2);
435 taua_i.
value() = aerosol->optical_depth_each_layer(wn).value();
437 taua_i = aerosol->optical_depth_each_layer(wn);
455 void AtmosphereOco::calc_rt_parameters
458 firstIndex i1; secondIndex i2; thirdIndex i3;
459 Range ra(Range::all());
472 Array<double, 2> scratch(taur.
rows(), iv.
cols());
474 scratch(ra, taur_index) = 1;
476 scratch(ra, taur_index) = 0;
484 Range taua_r(taua_0_index, taua_0_index +
485 (aerosol ? aerosol->number_particle() - 1 : 0));
489 for(
int i = 0; i < taua_i.
cols(); ++i) {
490 scratch(ra, taua_0_index + i) = 1;
492 aersc(ra, i) = aerosol->ssa_each_layer(wn, i, t);
493 scratch(ra, taua_0_index + i) = 0;
501 ssasum.
value() += sum(aersc.value(), i2);
502 ssasum.jacobian() += sum(aersc.jacobian()(i1, i3, i2), i3);
504 frac_aer.
value() = aersc.value() / ssasum.value()(i1);
505 frac_aer.
jacobian() = aersc.jacobian() / ssasum.value()(i1) -
506 aersc.value()(i1,i2) / (ssasum.value()(i1) * ssasum.value()(i1)) *
507 ssasum.jacobian()(i1, i3);
509 frac_ray.
value() = taur_wrt_iv.value() / ssasum.value();
510 frac_ray.
jacobian() = taur_wrt_iv.jacobian() / ssasum.value()(i1) -
511 taur_wrt_iv.value()(i1) / (ssasum.value()(i1) * ssasum.value()(i1)) *
516 ssasum.value()(i1) / (tau.
value()(i1) * tau.
value()(i1)) *
522 omega.
value() = taur_wrt_iv.value() / tau.
value();
523 omega.
jacobian() = taur_wrt_iv.jacobian() / tau.
value()(i1) -
524 taur_wrt_iv.value()(i1) / (tau.
value()(i1) * tau.
value()(i1)) *
534 Array<AutoDerivative<double>, 1> res(p.
rows());
535 Unit u = alt[spec_index]->altitude(
p(0)).units;
536 for(
int i = 0; i < res.rows(); ++i)
537 res(i) = alt[spec_index]->altitude(
p(i)).convert(u).value;
551 for(
int lev_idx = 0; lev_idx < temp_grid.
rows(); lev_idx++) {
552 double temp_K = temp_grid(lev_idx).
convert(
Unit(
"K")).value.value();
553 black_body(lev_idx) =
planck(wn, temp_K, temp_grid(lev_idx).
value.gradient());
567 error <<
"Cannot compute surface_blackbody, atmosphere was constructed without a surface tempererature object.";
571 double surf_temp_K = surface_temp->surface_temperature(spec_index).convert(
Unit(
"K")).value.value();
572 Array<double, 1> surf_temp_grad = surface_temp->surface_temperature(spec_index).value.gradient();
573 return planck(wn, surf_temp_K, surf_temp_grad);
598 temperature->clone(pressure_clone);
601 ground_clone = ground_ptr->clone();
602 std::vector<boost::shared_ptr<Altitude> > alt_clone;
604 alt_clone.push_back(a->clone(pressure_clone, temperature_clone));
606 absorber->clone(pressure_clone, temperature_clone, alt_clone);
608 rh->clone(absorber_clone, temperature_clone, pressure_clone);
611 aerosol_clone = aerosol->clone(pressure_clone, rh_clone);
614 (
new AtmosphereOco(absorber_clone, pressure_clone, temperature_clone,
615 aerosol_clone, rh_clone, ground_clone, alt_clone,
622 Os <<
"AtmosphereOco:\n";
624 Os <<
" Constant:\n";
625 opad << *constant <<
"\n";
627 Os <<
" Absorber:\n";
628 opad << *absorber <<
"\n";
630 Os <<
" Pressure:\n";
631 opad << *pressure <<
"\n";
633 Os <<
" Temperature:\n";
634 opad << *temperature <<
"\n";
638 opad << *aerosol <<
"\n";
640 opad <<
"Rayleigh only, no aerosols\n";
644 opad << *ground_ptr <<
"\n";
646 opad <<
"No ground\n";
648 for(
int i = 0; i < (int) alt.size(); ++i) {
649 Os <<
" Altitude[" << i <<
"]:\n";
650 opad << *(alt[i]) <<
"\n";
681 for (
int spec_idx = 0; spec_idx < this->
absorber_ptr()->number_species(); spec_idx++) {
682 std::string gas_name = this->
absorber_ptr()->gas_name(spec_idx);
691 for (
int aer_idx = 0; aer_idx < this->
aerosol_ptr()->number_particle(); aer_idx++) {
694 statev.
add_observer(*aer_optical->aerosol_extinction(aer_idx));
695 statev.
add_observer(*aer_optical->aerosol_property(aer_idx));
ArrayAdWithUnit< T, D > convert(const Unit &R) const
Convert to the given units.
#define range_check(V, Min, Max)
Range check.
virtual std::string timer_info() const
Return timer information.
This class is responsible for setting up the atmosphere and ground information needed to run the Radi...
This is a filtering stream that adds a pad to the front of every line written out.
bool rayleigh_only_atmosphere() const
Indicate we have rayleigh only atmosphere, i.e., we don't have any aerosol content.
void set_aerosol(boost::shared_ptr< Aerosol > &new_aerosol, StateVector &Sv)
Changes the aerosol class used.
static AccumulatedTimer timer
Timer for Aerosol.
void set_surface_pressure(const AutoDerivative< double > &Surface_pressure)
Set the surface pressure. This is in Pascals.
const boost::shared_ptr< Pressure > & pressure_ptr() const
void reset_elapsed()
Reset elapsed time to 0.
boost::shared_ptr< AtmosphereOco > clone() const
This clones a Atmosphere object.
static AccumulatedTimer timer
Timer for RtAtmosphere.
This is the base of the exception hierarchy for Full Physics code.
#define REGISTER_LUA_DERIVED_CLASS(X, Y)
const blitz::Array< T, D+1 > jacobian() const
virtual void add_observer(Observer< StateVector > &Obs)
Add an observer.
virtual int number_layer() const
Number of layers we currently have.
virtual void reset_timer()
Reset timer.
const boost::shared_ptr< Temperature > & temperature_ptr() const
void notify_update_do(const RtAtmosphere &Self)
Function to call to notify Observers of a state change.
Apply value function to a blitz array.
const Unit A("A", 1.0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0)
virtual const boost::shared_ptr< Ground > ground() const
Object that represents the ground surface.
static const blitz::Array< double, 2 > & array(double depolar_fact=0.02790)
Return the Ralyeigh Greek Moment Array.
This class calculates the Rayleigh portion of the optical depth.
const blitz::Array< T, D > & value() const
This class maintains the aerosol portion of the state.
void resize(const blitz::TinyVector< int, D > &Shape, int nvar)
FunctionTimer function_timer(bool Auto_log=false) const
Function timer.
virtual int number_spectrometer() const
Number of spectrometers we have.
virtual void remove_observer(Observer< StateVector > &Obs)
Remove an observer.
The AutoDerivative<T> works well, and it works with blitz if you create a blitz::Array<AutoDerivative...
int number_variable() const
virtual AutoDerivative< double > surface_blackbody(double wn, int spec_index) const
The surface thermal blackbody.
static AccumulatedTimer timer
Timer for optical_depth_each_layer.
This handles informing a set of interested objects when the state vector has updated.
int number_variable() const
double planck(double wn, double temperature)
Computes the black body function value using the planck function for a given wavenumber (cm^-1) and t...
virtual void print(std::ostream &Os) const
void reference(const ArrayAd< T, D > &V)
Libraries such as boost::units allow unit handling where we know the units at compile time...
const int taug_index
Index numbers used in Intermediate variables.
const boost::shared_ptr< Aerosol > & aerosol_ptr() const
Contains classes to abstract away details in various Spurr Radiative Transfer software.
virtual boost::shared_ptr< ArrayAdCache< double, double, 1 > > & column_optical_depth_cache()
#define REGISTER_LUA_END()
This class maintains the pressure portion of the state.
const blitz::TinyVector< int, D > & shape() const
Caches ArrayAd objects using a std::map.
This class maintains the atmosphere portion of the state, and uses this to set up the atmosphere and ...
Helper class for AccumulatedTimer.
void set_surface_pressure_for_testing(double x)
For unit test purposes, it is useful to be able to directly change the surface pressure.
void attach_children_to_sv(StateVector &statev)
For unit test purposes, it is useful to be able to clone or create a new atmosphere class then attach...
virtual void notify_update(const StateVector &Sv)
Called when the Observed object is updated.
virtual ArrayAd< double, 1 > atmosphere_blackbody(double wn, int spec_index) const
The atmospheric thermal blackbody values per level.
double value(const FullPhysics::AutoDerivative< double > &Ad)
const boost::shared_ptr< Absorber > & absorber_ptr() const
virtual std::string timer_info() const
Return timer information.
virtual ArrayAdWithUnit< double, 1 > altitude(int spec_index) const
Altitude grid for current pressure grid.
virtual void reset_timer()
Reset timer.
AtmosphereOco(const boost::shared_ptr< Absorber > &absorberv, const boost::shared_ptr< Pressure > &pressurev, const boost::shared_ptr< Temperature > &temperaturev, const boost::shared_ptr< Aerosol > &aerosolv, const boost::shared_ptr< RelativeHumidity > &rhv, const boost::shared_ptr< Ground > &groundv, const boost::shared_ptr< SurfaceTemperature > &surface_tempv, const std::vector< boost::shared_ptr< Altitude > > &altv, const boost::shared_ptr< Constant > &C)
Create an an Atmosphere with all available components: