ReFRACtor
ground_brdf.cc
Go to the documentation of this file.
1 #include "ground_brdf.h"
2 #include "polynomial_eval.h"
3 #include "ostream_pad.h"
4 
5 using namespace FullPhysics;
6 using namespace blitz;
7 
8 // Number of coefficients per band in the state vector
9 #define NUM_COEFF 7
10 
11 // Number of parameters in spars for the RT
12 #define NUM_PARAMS 5
13 
14 extern "C" {
15  double black_sky_albedo_veg_f(const double* params, const double* sza);
16  double black_sky_albedo_soil_f(const double* params, const double* sza);
17  double exact_brdf_value_veg_f(const double* params, const double* sza, const double* vza, const double* azm);
18  double exact_brdf_value_soil_f(const double* params, const double* sza, const double* vza, const double* azm);
19 }
20 
21 #ifdef HAVE_LUA
22 #include "register_lua.h"
23 
24 double black_sky_albedo_simple_veg(const blitz::Array<double, 1>& params, const double sza) {
25  return black_sky_albedo_veg_f(params.dataFirst(), &sza);
26 }
27 
28 double black_sky_albedo_simple_soil(const blitz::Array<double, 1>& params, const double sza) {
29  return black_sky_albedo_soil_f(params.dataFirst(), &sza);
30 }
31 
32 double exact_brdf_value_simple_veg(const blitz::Array<double, 1>& params, const double sza, const double vza, const double azm) {
33  return exact_brdf_value_veg_f(params.dataFirst(), &sza, &vza, &azm);
34 }
35 
36 double exact_brdf_value_simple_soil(const blitz::Array<double, 1>& params, const double sza, const double vza, const double azm) {
37  return exact_brdf_value_soil_f(params.dataFirst(), &sza, &vza, &azm);
38 }
39 
41 .def(luabind::constructor<const blitz::Array<double, 2>&, const blitz::Array<bool, 2>&, const ArrayWithUnit<double, 1>&, const std::vector<std::string>&>())
42 .scope
43 [
44  luabind::def("black_sky_albedo", &black_sky_albedo_simple_veg)
45 ]
46 .scope
47 [
48  luabind::def("kernel_value", &exact_brdf_value_simple_veg)
49 ]
51 
53 .def(luabind::constructor<const blitz::Array<double, 2>&, const blitz::Array<bool, 2>&, const ArrayWithUnit<double, 1>&, const std::vector<std::string>&>())
54 .scope
55 [
56  luabind::def("black_sky_albedo", &black_sky_albedo_simple_soil)
57 ]
58 .scope
59 [
60  luabind::def("kernel_value", &exact_brdf_value_simple_soil)
61 ]
63 #endif
64 
65 /****************************************************************/
79 GroundBrdf::GroundBrdf(const blitz::Array<double, 2>& Coeffs,
80  const blitz::Array<bool, 2>& Flag,
81  const ArrayWithUnit<double, 1>& Ref_points,
82  const std::vector<std::string>& Desc_band_names)
83 : reference_points(Ref_points), desc_band_names(Desc_band_names)
84 {
85  if(Coeffs.cols() != NUM_COEFF) {
86  Exception err_msg;
87  err_msg << "Number of parameters in Coeffs: " << Coeffs.cols() << " is not " << NUM_COEFF << " as expected";
88  throw err_msg;
89  }
90 
91  if(Coeffs.rows() != Flag.rows()) {
92  Exception err_msg;
93  err_msg << "Number of spectrometers in Coeffs: " << Coeffs.rows() << " does not match the number in Flag: " << Flag.rows();
94  throw err_msg;
95  }
96 
97  if(Coeffs.cols() != Flag.cols()) {
98  Exception err_msg;
99  err_msg << "Number of parameters in Coeffs: " << Coeffs.cols() << " does not match the number in Flag: " << Flag.cols();
100  throw err_msg;
101  }
102 
103  if(Coeffs.rows() != (int) Desc_band_names.size()) {
104  Exception err_msg;
105  err_msg << "Number of spectrometers in Coeffs: " << Coeffs.rows() << " does not match the number in Desc_band_names: " << Desc_band_names.size();
106  throw err_msg;
107  }
108 
109  if(Ref_points.rows() != (int) Desc_band_names.size()) {
110  Exception err_msg;
111  err_msg << "Number of spectrometers in Ref_points: " << Ref_points.rows() << " does not match the number in Desc_band_names: " << Desc_band_names.size();
112  throw err_msg;
113  }
114 
115  // Make local arrays to deal with const issues on call to init. The init routine copies the data
116  Array<double, 2> coeffs(Coeffs);
117  Array<bool, 2> flags(Flag);
118 
119  // Flatten arrays for state vector
120  init(Array<double, 1>(coeffs.dataFirst(), TinyVector<int, 1>(Coeffs.rows() * Coeffs.cols()), blitz::neverDeleteData),
121  Array<bool, 1>(flags.dataFirst(), TinyVector<int, 1>(Flag.rows() * Flag.cols()), blitz::neverDeleteData));
122 }
123 
125 GroundBrdf::GroundBrdf(const blitz::Array<double, 1>& Spec_coeffs,
126  const blitz::Array<bool, 1>& Flag,
127  const ArrayWithUnit<double, 1>& Ref_points,
128  const std::vector<std::string>& Desc_band_names)
129  : SubStateVectorArray<Ground>(Spec_coeffs, Flag),
130  reference_points(Ref_points), desc_band_names(Desc_band_names)
131 {
132 }
133 
134 ArrayAd<double, 1> GroundBrdf::surface_parameter(const double wn, const int spec_index) const
135 {
136  AutoDerivative<double> w = weight(wn, spec_index);
137  ArrayAd<double, 1> spars;
138  spars.resize(NUM_PARAMS, coefficient().number_variable());
139  spars(0) = w * rahman_factor(spec_index);
140  spars(1) = hotspot_parameter(spec_index);
141  spars(2) = asymmetry_parameter(spec_index);
142  spars(3) = anisotropy_parameter(spec_index);
143  spars(4) = w * breon_factor(spec_index);
144  return spars;
145 }
146 
147 const AutoDerivative<double> GroundBrdf::weight(const double wn, const int spec_index) const
148 {
149  double ref_wn = reference_points(spec_index).convert_wave(units::inv_cm).value;
150  ArrayAd<double, 1> weight_params(2, weight_intercept(spec_index).number_variable());
151  weight_params(0) = weight_slope(spec_index);
152  weight_params(1) = weight_intercept(spec_index);
153  Poly1d weight_poly(weight_params, true);
154  AutoDerivative<double> wn_ad(wn); // Make sure we use the AutoDerivative interface to Poly1d
155  return weight_poly(wn_ad - ref_wn);
156 }
157 
158 const AutoDerivative<double> GroundBrdf::weight_intercept(const int spec_index) const
159 {
160  range_check(spec_index, 0, number_spectrometer());
161 
162  return coefficient()(NUM_COEFF * spec_index + BRDF_WEIGHT_INTERCEPT_INDEX);
163 }
164 
165 const AutoDerivative<double> GroundBrdf::weight_slope(const int spec_index) const
166 {
167  range_check(spec_index, 0, number_spectrometer());
168 
169  return coefficient()(NUM_COEFF * spec_index + BRDF_WEIGHT_SLOPE_INDEX);
170 }
171 
172 const AutoDerivative<double> GroundBrdf::rahman_factor(const int spec_index) const
173 {
174  range_check(spec_index, 0, number_spectrometer());
175 
176  return coefficient()(NUM_COEFF * spec_index + RAHMAN_KERNEL_FACTOR_INDEX);
177 }
178 
179 const AutoDerivative<double> GroundBrdf::hotspot_parameter(const int spec_index) const
180 {
181  range_check(spec_index, 0, number_spectrometer());
182 
183  return coefficient()(NUM_COEFF * spec_index + RAHMAN_OVERALL_AMPLITUDE_INDEX);
184 }
185 
187 {
188  range_check(spec_index, 0, number_spectrometer());
189 
190  return coefficient()(NUM_COEFF * spec_index + RAHMAN_ASYMMETRY_FACTOR_INDEX);
191 }
192 
194 {
195  range_check(spec_index, 0, number_spectrometer());
196 
197  return coefficient()(NUM_COEFF * spec_index + RAHMAN_GEOMETRIC_FACTOR_INDEX);
198 }
199 
200 const AutoDerivative<double> GroundBrdf::breon_factor(const int spec_index) const
201 {
202  range_check(spec_index, 0, number_spectrometer());
203 
204  return coefficient()(NUM_COEFF * spec_index + BREON_KERNEL_FACTOR_INDEX);
205 }
206 
207 //----
208 
209 void GroundBrdf::weight_intercept(const int spec_index, const AutoDerivative<double>& val)
210 {
211  range_check(spec_index, 0, number_spectrometer());
212 
213  coeff(NUM_COEFF * spec_index + BRDF_WEIGHT_INTERCEPT_INDEX) = val;
214 }
215 
216 void GroundBrdf::weight_slope(const int spec_index, const AutoDerivative<double>& val)
217 {
218  range_check(spec_index, 0, number_spectrometer());
219 
220  coeff(NUM_COEFF * spec_index + BRDF_WEIGHT_SLOPE_INDEX) = val;
221 }
222 
223 void GroundBrdf::rahman_factor(const int spec_index, const AutoDerivative<double>& val)
224 {
225  range_check(spec_index, 0, number_spectrometer());
226 
227  coeff(NUM_COEFF * spec_index + RAHMAN_KERNEL_FACTOR_INDEX) = val;
228 }
229 
230 void GroundBrdf::hotspot_parameter(const int spec_index, const AutoDerivative<double>& val)
231 {
232  range_check(spec_index, 0, number_spectrometer());
233 
234  coeff(NUM_COEFF * spec_index + RAHMAN_OVERALL_AMPLITUDE_INDEX) = val;
235 }
236 
237 void GroundBrdf::asymmetry_parameter(const int spec_index, const AutoDerivative<double>& val)
238 {
239  range_check(spec_index, 0, number_spectrometer());
240 
241  coeff(NUM_COEFF * spec_index + RAHMAN_ASYMMETRY_FACTOR_INDEX) = val;
242 }
243 
244 void GroundBrdf::anisotropy_parameter(const int spec_index, const AutoDerivative<double>& val)
245 {
246  range_check(spec_index, 0, number_spectrometer());
247 
248  coeff(NUM_COEFF * spec_index + RAHMAN_GEOMETRIC_FACTOR_INDEX) = val;
249 }
250 
251 void GroundBrdf::breon_factor(const int spec_index, const AutoDerivative<double>& val)
252 {
253  range_check(spec_index, 0, number_spectrometer());
254 
255  coeff(NUM_COEFF * spec_index + BREON_KERNEL_FACTOR_INDEX) = val;
256 }
257 
258 const blitz::Array<double, 2> GroundBrdf::brdf_covariance(const int spec_index) const
259 {
260  range_check(spec_index, 0, number_spectrometer());
261 
262  // Return empty array if covariance is empty due to not being retrieved
263  if(product(statevector_covariance().shape()) == 0) {
264  return Array<double, 2>(0, 0);
265  }
266 
267  int ret_num_param = statevector_covariance().rows() / desc_band_names.size();
268  int ret_cov_offset = ret_num_param * spec_index;
269 
270  blitz::Array<double, 2> cov(NUM_COEFF, NUM_COEFF);
271  cov = 0.0;
272 
273  // Copy out the retrieved covariance values into a matrix for the spectrometer that includes
274  // zeros for non retrieved elements
275  int in_idx_a = ret_cov_offset;
276  for (int out_idx_a = 0; out_idx_a < NUM_COEFF; out_idx_a++) {
277  if (used_flag_value()(out_idx_a)) {
278  int in_idx_b = ret_cov_offset;
279  for (int out_idx_b = 0; out_idx_b < NUM_COEFF; out_idx_b++) {
280  if (used_flag_value()(out_idx_b)) {
281  cov(out_idx_a, out_idx_b) = statevector_covariance()(in_idx_a, in_idx_b++);
282  }
283  }
284  in_idx_a++;
285  }
286  }
287 
288  return cov;
289 }
290 
291 // Helper function
292 blitz::Array<double, 1> GroundBrdf::black_sky_params(const int Spec_index)
293 {
294  double ref_wn = reference_points(Spec_index).convert_wave(units::inv_cm).value;
295  double w = weight(ref_wn, Spec_index).value();
296 
297  blitz::Array<double, 1> params(NUM_PARAMS, blitz::ColumnMajorArray<1>());
298  params(0) = w * rahman_factor(Spec_index).value();
299  params(1) = hotspot_parameter(Spec_index).value();
300  params(2) = asymmetry_parameter(Spec_index).value();
301  params(3) = anisotropy_parameter(Spec_index).value();
302  params(4) = w * breon_factor(Spec_index).value();
303  return params;
304 }
305 
306 // Helper function
307 blitz::Array<double, 1> GroundBrdf::kernel_value_params(const int Spec_index)
308 {
309  blitz::Array<double, 1> params(NUM_PARAMS, blitz::ColumnMajorArray<1>());
310  params(0) = rahman_factor(Spec_index).value();
311  params(1) = hotspot_parameter(Spec_index).value();
312  params(2) = asymmetry_parameter(Spec_index).value();
313  params(3) = anisotropy_parameter(Spec_index).value();
314  params(4) = breon_factor(Spec_index).value();
315  return params;
316 }
317 
318 const double GroundBrdfVeg::black_sky_albedo(const int Spec_index, const double Sza)
319 {
320  blitz::Array<double, 1> params = black_sky_params(Spec_index);
321  return black_sky_albedo_veg_f(params.dataFirst(), &Sza);
322 }
323 
324 const double GroundBrdfSoil::black_sky_albedo(const int Spec_index, const double Sza)
325 {
326  blitz::Array<double, 1> params = black_sky_params(Spec_index);
327  return black_sky_albedo_soil_f(params.dataFirst(), &Sza);
328 }
329 
330 const double GroundBrdfVeg::kernel_value(const int Spec_index, const double Sza, const double Vza, const double Azm)
331 {
332  blitz::Array<double, 1> params = kernel_value_params(Spec_index);
333  return exact_brdf_value_veg_f(params.dataFirst(), &Sza, &Vza, &Azm);
334 }
335 
336 const double GroundBrdfSoil::kernel_value(const int Spec_index, const double Sza, const double Vza, const double Azm)
337 {
338  blitz::Array<double, 1> params = kernel_value_params(Spec_index);
339  return exact_brdf_value_soil_f(params.dataFirst(), &Sza, &Vza, &Azm);
340 }
341 
342 std::string GroundBrdf::state_vector_name_i(int i) const {
343  int b_idx = int(i / NUM_COEFF);
344  int c_idx = i - NUM_COEFF * b_idx;
345 
346  std::stringstream name;
347  name << "Ground BRDF " << breon_type() << " " << desc_band_names[b_idx] << " ";
348  switch (c_idx) {
350  name << "BRDF Weight Intercept";
351  break;
353  name << "BRDF Weight Slope";
354  break;
356  name << "Rahman Factor";
357  break;
359  name << "Hotspot Parameter";
360  break;
362  name << "Asymmetry Parameter";
363  break;
365  name << "Anisotropy Parameter";
366  break;
368  name << "Breon Factor";
369  break;
370  default:
371  name << "Unknown Index " << i;
372  }
373 
374  return name.str();
375 }
376 
377 void GroundBrdf::print(std::ostream& Os) const
378 {
379  Os << "GroundBrdf:\n";
380  for(int spec_idx = 0; spec_idx < number_spectrometer(); spec_idx++) {
381  Os << " " << desc_band_names[spec_idx] << ":" << std::endl;
382  OstreamPad opad(Os, " ");
383  opad << "BRDF Weight Intercept: " << weight_intercept(spec_idx).value() << std::endl
384  << "BRDF Weight Slope: " << weight_slope(spec_idx).value() << std::endl
385  << "Rahman Factor: " << rahman_factor(spec_idx).value() << std::endl
386  << "Hotspot Parameter: " << hotspot_parameter(spec_idx).value() << std::endl
387  << "Asymmetry Parameter: " << asymmetry_parameter(spec_idx).value() << std::endl
388  << "Anisotropy Parameter: " << anisotropy_parameter(spec_idx).value() << std::endl
389  << "Breon Factor: " << breon_factor(spec_idx).value() << std::endl;
390  opad.strict_sync();
391  }
392 }
virtual const double kernel_value(const int Spec_index, const double Sza, const double Vza, const double Azm)
Definition: ground_brdf.cc:330
virtual ArrayAd< double, 1 > surface_parameter(const double wn, const int spec_index) const
Surface parmeters.
Definition: ground_brdf.cc:134
#define range_check(V, Min, Max)
Range check.
Definition: fp_exception.h:140
#define NUM_PARAMS
Definition: ground_brdf.cc:12
blitz::Array< double, 2 > cov
Last covariance matrix updated from the StateVector.
This is a filtering stream that adds a pad to the front of every line written out.
Definition: ostream_pad.h:32
virtual const double kernel_value(const int Spec_index, const double Sza, const double Vza, const double Azm)
Definition: ground_brdf.cc:336
double exact_brdf_value_soil_f(const double *params, const double *sza, const double *vza, const double *azm)
virtual const AutoDerivative< double > anisotropy_parameter(const int spec_index) const
Definition: ground_brdf.cc:193
double black_sky_albedo_soil_f(const double *params, const double *sza)
virtual const std::string breon_type() const =0
String describing which type of Breon surface type, also makes this class abstract.
double black_sky_albedo_veg_f(const double *params, const double *sza)
virtual const AutoDerivative< double > breon_factor(const int spec_index) const
Definition: ground_brdf.cc:200
virtual const AutoDerivative< double > weight_slope(const int spec_index) const
Definition: ground_brdf.cc:165
virtual const AutoDerivative< double > hotspot_parameter(const int spec_index) const
Definition: ground_brdf.cc:179
blitz::Array< double, 1 > kernel_value_params(const int Spec_index)
Definition: ground_brdf.cc:307
GroundBrdf(const blitz::Array< double, 2 > &Coeffs, const blitz::Array< bool, 2 > &Flag, const ArrayWithUnit< double, 1 > &Ref_points, const std::vector< std::string > &Desc_band_names)
Constructor that defines coefficients in a 2d array: Num_spectrometer * NUM_COEFF Each row has the NU...
Definition: ground_brdf.cc:79
This is the base of the exception hierarchy for Full Physics code.
Definition: fp_exception.h:16
virtual const AutoDerivative< double > weight_intercept(const int spec_index) const
Definition: ground_brdf.cc:158
const blitz::Array< bool, 1 > & used_flag_value() const
#define NUM_COEFF
Definition: ground_brdf.cc:9
#define REGISTER_LUA_DERIVED_CLASS(X, Y)
Definition: register_lua.h:136
double exact_brdf_value_veg_f(const double *params, const double *sza, const double *vza, const double *azm)
virtual const int number_spectrometer() const
Definition: ground_brdf.h:38
virtual const double black_sky_albedo(const int Spec_index, const double Sza)
Definition: ground_brdf.cc:324
This class maintains the ground portion of the state.
Definition: ground.h:22
ArrayWithUnit< double, 1 > reference_points
Definition: ground_brdf.h:92
Apply value function to a blitz array.
std::vector< std::string > desc_band_names
Definition: ground_brdf.h:93
virtual std::string state_vector_name_i(int i) const
Return state vector name for ith entry in coeff.
Definition: ground_brdf.cc:342
const Unit inv_cm("cm^-1", pow(cm, -1))
void resize(const blitz::TinyVector< int, D > &Shape, int nvar)
Definition: array_ad.h:177
A one-dimensional polynomial class.
const blitz::Array< double, 2 > & statevector_covariance() const
virtual const AutoDerivative< double > weight(const double wn, const int spec_index) const
Definition: ground_brdf.cc:147
virtual void print(std::ostream &Os) const
Definition: ground_brdf.cc:377
const ArrayAd< double, 1 > & coefficient() const
It is common to have a class that is an Observable with a set of coefficients, a subset of which are ...
Contains classes to abstract away details in various Spurr Radiative Transfer software.
Definition: doxygen_python.h:1
void init(const blitz::Array< double, 1 > &Coeff, const blitz::Array< bool, 1 > &Used_flag, const boost::shared_ptr< Pressure > &Press=boost::shared_ptr< Pressure >(), bool Mark_according_to_press=true, int Pdep_start=0)
const T & value() const
Convert to type T.
#define REGISTER_LUA_END()
Definition: register_lua.h:134
virtual const double black_sky_albedo(const int Spec_index, const double Sza)
Definition: ground_brdf.cc:318
def(luabind::constructor< int >()) .def("rows"
blitz::Array< double, 1 > black_sky_params(const int Spec_index)
Definition: ground_brdf.cc:292
const blitz::Array< double, 2 > brdf_covariance(const int spec_index) const
Definition: ground_brdf.cc:258
ArrayAd< double, 1 > coeff
Coefficients.
virtual const AutoDerivative< double > rahman_factor(const int spec_index) const
Definition: ground_brdf.cc:172
virtual const AutoDerivative< double > asymmetry_parameter(const int spec_index) const
Definition: ground_brdf.cc:186
ArrayWithUnit< T, D > convert_wave(const Unit &R) const
We often need to handle conversion from wavenumber to/from wavelength.

Copyright © 2017, California Institute of Technology.
ALL RIGHTS RESERVED.
U.S. Government Sponsorship acknowledged.
Generated Fri Aug 24 2018 15:44:08