4 #include <boost/lexical_cast.hpp> 48 reference_wn_(Reference_wn),
53 if((
int) aprop.size() != number_particle())
54 throw Exception(
"aprop needs to be size of number_particle()");
55 for(
int i = 0; i < number_particle(); ++i) {
56 aprop[i]->add_observer(*
this);
57 aext[i]->add_observer(*
this);
59 press->add_observer(*
this);
75 blitz::Array<std::string, 1> res((
int) aext.size());
76 for(
int i = 0; i < res.rows(); i++)
77 res(i) = aext[i]->aerosol_name();
86 void AerosolOptical::fill_cache()
const 90 od_ind_wn.resize(press->number_layer(), number_particle(), nvar);
91 for(
int i = 0; i < od_ind_wn.rows(); ++i) {
93 (press->pressure_grid()(i + 1) - press->pressure_grid()(i));
100 for(
int j = 0; j < number_particle(); ++j) {
104 od_ind_wn(i, j) = 1.0 / aprop[j]->extinction_coefficient_each_layer(reference_wn_)(i) *
105 dp * aext[j]->extinction_for_layer(i);
114 nlay = press->number_layer();
115 cache_is_stale =
false;
132 Range ra(Range::all());
133 firstIndex i1; secondIndex i2; thirdIndex i3;
137 for(
int i = 0; i < number_particle(); ++i) {
141 Array<double, 1> v(res.value()(ra, i));
142 Array<double, 2> jac(res.jacobian()(ra, i, ra));
145 jac = t.
value()(i1) * jac(i1, i2);
147 jac = t.
value()(i1) * jac(i1,i2) + v(i1) * t.
jacobian()(i1, i2);
174 firstIndex i1; secondIndex i2; thirdIndex i3;
180 if(!t.is_constant() && !res.is_constant() &&
181 res.number_variable() != t.number_variable())
182 throw Exception(
"We don't currently have the code working correctly for combining intermediates and state vector derivatives. We'll need to think through how to do this.");
184 t.jacobian() = 1 / t2.
value()(i1) * t.jacobian()(i1,i2) -
186 if(res.is_constant() && !t.is_constant())
187 res.resize_number_variable(t.number_variable());
188 Array<double, 1> v(res.value());
189 Array<double, 2> jac(res.jacobian());
192 jac = t.value()(i1) * jac(i1, i2);
194 jac = t.value()(i1) * jac(i1,i2) + v(i1) * t.jacobian()(i1,i2);
217 for(
int i = 0; i < number_particle(); ++i) {
219 res.value() += t.
value();
240 return aprop[pindex]->phase_function_moment_each_layer(wn);
254 const blitz::Array<double, 2>& frac_aer)
const 257 firstIndex i1; secondIndex i2; thirdIndex i3;
258 Range ra = Range::all();
259 if(frac_aer.rows() != nlay ||
260 frac_aer.cols() != number_particle()) {
261 std::stringstream err_msg;
262 err_msg <<
"frac_aer needs to be number_active_layer = " 264 <<
" x number_particle = " 265 << number_particle() <<
", but is currently " 266 << frac_aer.rows() <<
" x " << frac_aer.cols();
269 std::vector<Array<double, 3> > pf;
272 for(
int j = 0; j < frac_aer.cols(); ++j) {
273 pf.push_back(pf_mom(wn, j).
value());
274 s1 = std::max(s1, pf[j].rows());
275 s2 = std::max(s2, pf[j].depth());
277 blitz::Array<double, 3> res(s1, nlay, s2);
279 for(
int j = 0; j < frac_aer.cols(); ++j) {
280 Range r1(0, pf[j].rows() - 1);
281 Range r2(0, pf[j].depth() - 1);
282 res(r1,ra,r2) += frac_aer(ra,j)(i2) * pf[j](i1, i2, i3);
289 int nummom,
int numscat)
const 292 firstIndex i1; secondIndex i2; thirdIndex i3; fourthIndex i4;
293 Range ra = Range::all();
294 if(frac_aer.
rows() != nlay ||
295 frac_aer.
cols() != number_particle()) {
296 std::stringstream err_msg;
297 err_msg <<
"frac_aer needs to be number_active_layer = " 299 <<
" x number_particle = " 300 << number_particle() <<
", but is currently " 301 << frac_aer.
rows() <<
" x " << frac_aer.
cols();
305 std::vector<ArrayAd<double, 3> > pf;
309 for(
int j = 0; j < frac_aer.
cols(); ++j) {
310 pf.push_back(aprop[j]->phase_function_moment_each_layer(wn, nummom, numscat));
311 s1 = std::max(s1, pf[j].rows());
312 s2 = std::max(s2, pf[j].depth());
313 nvar = std::max(nvar, pf[j].number_variable());
314 if(!pf[j].is_constant() && !frac_aer.
is_constant() &&
316 throw Exception(
"We don't currently have the code working correctly for combining intermediates and state vector derivatives. We'll need to think through how to do this.");
320 for(
int j = 0; j < frac_aer.
cols(); ++j) {
321 Range r1(0, pf[j].rows() - 1);
322 Range r2(0, pf[j].depth() - 1);
323 Array<double, 3> rv(res.
value()(r1,ra,r2));
324 Array<double, 4> rjac(res.
jacobian()(r1,ra,r2,ra));
325 Array<double, 1> fv(frac_aer.
value()(ra,j));
326 Array<double, 2> fjac(frac_aer.
jacobian()(ra,j, ra));
327 Array<double, 3> pv(pf[j].
value());
328 Array<double, 4> pjac(pf[j].
jacobian());
329 rv += fv(i2) * pv(i1, i2, i3);
330 if(pf[j].is_constant()) {
332 rjac += fjac(i2,i4) * pv(i1, i2, i3);
335 rjac += fv(i2) * pjac(i1, i2, i3, i4);
337 rjac += fjac(i2,i4) * pv(i1, i2, i3) + fv(i2) * pjac(i1, i2, i3, i4);
354 std::vector<boost::shared_ptr<AerosolExtinction> > aext_clone;
356 aext_clone.push_back(i->clone(Press));
357 std::vector<boost::shared_ptr<AerosolProperty> > aprop_clone;
359 aprop_clone.push_back(i->clone(Press, Rh));
377 Array<double, 1> pgrid(press->pressure_grid().convert(
units::Pa).value.value());
378 for(
int i = 0; i < pgrid.rows() - 1; ++i) {
380 if(pmin <= pgrid(i) && pgrid(i + 1) <= pmax)
381 res += (pgrid(i + 1) - pgrid(i)) *
382 aext[aer_idx]->extinction_for_layer(i).value();
385 else if(pmin > pgrid(i) && pmin < pgrid(i + 1) && pgrid(i + 1) <=pmax)
386 res += (pgrid(i + 1) - pmin) * aext[aer_idx]->extinction_for_layer(i).value();
389 else if(pmin <= pgrid(i) && pgrid(i) < pmax && pgrid(i + 1) > pmax)
390 res += (pmax - pgrid(i)) * aext[aer_idx]->extinction_for_layer(i).value();
407 (
double pmin,
double pmax)
const 410 for(
int j = 0; j < number_particle(); ++j)
411 res += aerosol_optical_depth(j, pmin, pmax);
420 std::vector<std::string> res;
422 res.push_back(i->aerosol_name());
429 Os <<
"AerosolOptical:";
430 for(
int i = 0; i < (int) aprop.size(); ++i) {
431 Os <<
" Aerosol Optical Property[" << i <<
"]:\n";
432 opad << *aprop[i] <<
"\n";
434 Os <<
" Aerosol Extinction[" << i <<
"]:\n";
435 opad << *aext[i] <<
"\n";
void resize_number_variable(int nvar)
#define range_check(V, Min, Max)
Range check.
blitz::Array< std::string, 1 > aerosol_name_arr() const
Aerosol names, plus the string "total" as the 1st entry.
This is a AutoDerivative that also has units associated with it.
This is a filtering stream that adds a pad to the front of every line written out.
AutoDerivativeWithUnit< T > convert(const Unit &R) const
Convert to the given units.
virtual void print(std::ostream &Os) const
const Unit Pa("Pa", N/(m *m))
This is the base of the exception hierarchy for Full Physics code.
std::vector< std::string > aerosol_name() const
Name of aerosols.
blitz::Array< T, 2 > jacobian(const blitz::Array< AutoDerivative< T >, 1 > &Ad)
Utility function to extract the Jacobian as a separate matrix from an array of AutoDerivative.
#define REGISTER_LUA_DERIVED_CLASS(X, Y)
const blitz::Array< T, D+1 > jacobian() const
double aerosol_optical_depth_total(double pmin=std::numeric_limits< double >::min(), double pmax=std::numeric_limits< double >::max()) const
This gives the total optical depth for each particle, plus adds the total optical depth for all parti...
double aerosol_optical_depth(int aer_idx, double pmin=std::numeric_limits< double >::min(), double pmax=std::numeric_limits< double >::max()) const
This gives the total aerosol optical depth for a given particle.
Apply value function to a blitz array.
AerosolOptical(const std::vector< boost::shared_ptr< AerosolExtinction > > &Aext, const std::vector< boost::shared_ptr< AerosolProperty > > &Aerosol_prop, const boost::shared_ptr< Pressure > &Press, const boost::shared_ptr< RelativeHumidity > &Rh, double Reference_wn=1e4/0.755)
Create an aerosol.
const blitz::Array< T, D > & value() const
This class maintains the aerosol portion of the state.
virtual ArrayAd< double, 2 > optical_depth_each_layer(double wn) const
This gives the optical depth for each layer, for the given wave number.
virtual boost::shared_ptr< Aerosol > clone() const
Clone a Aerosol object.
ArrayAd< T, D > copy() const
const boost::shared_ptr< AerosolProperty > & aerosol_property(int i) const
Return aerosol property.
Implementation of Aerosol.
int number_variable() const
Number of variables in gradient.
const blitz::Array< T, 1 > & gradient() const
Gradient.
int number_variable() const
virtual int number_particle() const
Number of aerosol particles.
virtual ArrayAd< double, 3 > pf_mom(double wn, int pindex) const
This calculates the portion of the phase function moments that come from the aerosol for a single par...
Contains classes to abstract away details in various Spurr Radiative Transfer software.
#define REGISTER_LUA_END()
const boost::shared_ptr< AerosolExtinction > & aerosol_extinction(int i) const
Return aerosol extinction.
Helper class for AccumulatedTimer.
double value(const FullPhysics::AutoDerivative< double > &Ad)
virtual ArrayAd< double, 1 > ssa_each_layer(double wn, int particle_index, const ArrayAd< double, 1 > &Od) const
This gives the single scatter albedo for each layer, for the given wave number, for the given particl...