ReFRACtor
spurr_driver.cc
Go to the documentation of this file.
1 #include "spurr_driver.h"
2 #include "spurr_brdf_types.h"
3 #include "ground.h"
4 
5 using namespace FullPhysics;
6 using namespace blitz;
7 
8 //-----------------------------------------------------------------------
11 //----------------------------------------------------------------------
12 
14 {
15  switch (surface_type) {
16  case LAMBERTIAN:
17  initialize_brdf_kernel(LAMBERTIAN);
18  break;
19  case COXMUNK:
20  initialize_brdf_kernel(COXMUNK);
21  initialize_brdf_kernel(LAMBERTIAN);
22  break;
23  case BPDFVEGN:
24  case BPDFSOIL:
25  initialize_brdf_kernel(RAHMAN);
26  initialize_brdf_kernel(surface_type);
27  break;
28  default:
29  Exception e("Unhandled BRDF type index: ");
30  e << surface_type;
31  throw e;
32  }
33 }
34 
35 //-----------------------------------------------------------------------
39 //----------------------------------------------------------------------
40 
42  // Increment kernel index
43  int kernel_index = n_brdf_kernels();
44  n_brdf_kernels(n_brdf_kernels()+1);
45 
46  bool lambertian_flag = false;
47  int n_brdf_parameters;
48  bool do_factor_wfs;
49  Array<bool, 1> do_params_wfs;
50  switch (which_brdf) {
51  case LAMBERTIAN:
52  lambertian_flag = true;
53  n_brdf_parameters = 1;
54 
55  do_factor_wfs = true;
56 
57  do_params_wfs.resize(n_brdf_parameters);
58  do_params_wfs(0) = false;
59  break;
60  case COXMUNK:
61  n_brdf_parameters = 3;
62 
63  do_factor_wfs = false;
64 
65  do_params_wfs.resize(n_brdf_parameters);
66  do_params_wfs(0) = true;
67  do_params_wfs(1) = true;
68  do_params_wfs(2) = false;
69  break;
70  case RAHMAN:
71  n_brdf_parameters = 3;
72 
73  do_factor_wfs = true;
74 
75  do_params_wfs.resize(n_brdf_parameters);
76  do_params_wfs = true;
77  break;
78  case BPDFVEGN:
79  case BPDFSOIL:
80  n_brdf_parameters = 1;
81 
82  do_factor_wfs = true;
83 
84  do_params_wfs.resize(n_brdf_parameters);
85  do_params_wfs(0) = false;
86  break;
87  default:
88  Exception e("Unhandled BRDF kernel type: ");
89  e << which_brdf;
90  throw e;
91  }
92 
93  initialize_kernel_parameters(kernel_index, which_brdf, lambertian_flag, n_brdf_parameters, do_factor_wfs, do_params_wfs);
94 
95  // Count number of wfs and add to total(s)
96  int n_factor_wfs = do_factor_wfs ? 1 : 0;
97  int n_param_wfs = sum(where(do_params_wfs(Range::all()) == true, 1, 0));
98 
99  n_kernel_factor_wfs(n_kernel_factor_wfs() + n_factor_wfs);
100  n_kernel_params_wfs(n_kernel_params_wfs() + n_param_wfs);
101  n_surface_wfs(n_surface_wfs() + n_factor_wfs + n_param_wfs);
102 
103  // Determine if any parameter wfs are computed for current kernel
104  do_kparams_derivs(kernel_index, any(do_params_wfs(Range::all())));
105 }
106 
107 //-----------------------------------------------------------------------
110 //-----------------------------------------------------------------------
111 
112 ArrayAd<double, 1> SpurrBrdfDriver::setup_brdf_inputs(int surface_type, const ArrayAd<double, 1>& surface_parameters) const
113 {
114  // Copy input surface parameters as the returned value may
115  // be modified to properly account for changes to parameters
116  // made for use inside of RT
117  ArrayAd<double, 1> rt_surf_params(surface_parameters);
118 
119  // Map kernel parameter indexes to indexes in surface_parameter input array
120  // Due to heritiage code these two will not always match up, but we need
121  // to know which indexes of the paremeters array to properly account for jacobians
122  Array<int, 1> parameter_indexes;
123 
124  switch (surface_type) {
125  case LAMBERTIAN:
126  parameter_indexes.resize(1);
127  parameter_indexes(0) = 0;
128  setup_lambertian_inputs(0, rt_surf_params, parameter_indexes);
129 
130  break;
131  case COXMUNK:
132  parameter_indexes.resize(3);
133  parameter_indexes(0) = 0;
134  parameter_indexes(1) = 1;
135  parameter_indexes(2) = 3;
136  setup_coxmunk_inputs(0, rt_surf_params, parameter_indexes);
137 
138  // lamberitan component to coxmunk
139  parameter_indexes.resize(1);
140  parameter_indexes(0) = 2;
141  setup_lambertian_inputs(1, rt_surf_params, parameter_indexes);
142  break;
143  case BPDFVEGN:
144  case BPDFSOIL:
145  parameter_indexes.resize(4);
146  parameter_indexes(0) = 0; // rahman kernel factor
147  parameter_indexes(1) = 1; // hotspot parameter
148  parameter_indexes(2) = 2; // asymmetry
149  parameter_indexes(3) = 3; // anisotropy_parameter
150  setup_rahman_inputs(0, rt_surf_params, parameter_indexes);
151 
152  parameter_indexes.resize(1);
153  parameter_indexes(0) = 4; // breon kernel factor
154  setup_breon_inputs(1, rt_surf_params, parameter_indexes);
155  break;
156  default:
157  Exception e("Unhandled BRDF type index: ");
158  e << surface_type;
159  throw e;
160  }
161 
162  // Calculate BRDF base on all input setup
163  calculate_brdf();
164 
165  return rt_surf_params;
166 }
167 
168 void SpurrBrdfDriver::setup_lambertian_inputs(int kernel_index, ArrayAd<double, 1>& surface_parameters, const Array<int, 1>& parameter_indexes) const
169 {
170  // brdf_params value only used if do_brdf_surface = True
171  // albedo set to brdf weighting function so that weighting function
172  // calculated automatically. The brdf parameters for Lambertian
173  // do not have a wf defined for them
174  int albedo_idx = parameter_indexes(0);
175  brdf_factors(kernel_index) = surface_parameters(albedo_idx).value();
176 
177  // According to LIDORT user's guide section "2.7.1 BRDFs as a sum of kernel functions" this should be 1.0
178  brdf_params(kernel_index, 0) = 1.0;
179 }
180 
181 void SpurrBrdfDriver::setup_coxmunk_inputs(int kernel_index, ArrayAd<double, 1>& surface_parameters, const Array<int, 1>& parameter_indexes) const
182 {
183  brdf_factors(kernel_index) = 1.0;
184 
185  // Modify surface_parameters in place so that jacobians reflect modifications
186  int ws_idx = parameter_indexes(0);
187  int refr_idx = parameter_indexes(1);
188  int shadow_idx = parameter_indexes(2);
189 
190  // windspeed
191  surface_parameters(ws_idx) = 0.003 + 0.00512 * surface_parameters(ws_idx);
192  brdf_params(kernel_index, 0) = surface_parameters(ws_idx).value();
193  // refactive index of water (squared)
194  surface_parameters(refr_idx) = surface_parameters(refr_idx) * surface_parameters(refr_idx); // refractive index of air
195  brdf_params(kernel_index, 1) = surface_parameters(refr_idx).value();
196  // shadowing flag, for kernel routine
197  // kernel routine seems to use this value despite shadowing flag below
198  brdf_params(kernel_index, 2) = surface_parameters(shadow_idx).value();
199 
200  // Shadowing flag that seems independent of value passed to kernel function,
201  // or possibly value above is overwritten by this flag
202  do_shadow_effect(surface_parameters(shadow_idx).value() > 0.0);
203 }
204 
205 void SpurrBrdfDriver::setup_rahman_inputs(int kernel_index, ArrayAd<double, 1>& surface_parameters, const Array<int, 1>& parameter_indexes) const
206 {
207  // Modify surface_parameters in place so that jacobians reflect modifications
208  int kf_idx = parameter_indexes(0);
209  int ampl_idx = parameter_indexes(1);
210  int asym_idx = parameter_indexes(2);
211  int geom_idx = parameter_indexes(3);
212 
213  brdf_factors(kernel_index) = surface_parameters(kf_idx).value();
214 
215  // Overall amplitude
216  brdf_params(kernel_index, 0) = surface_parameters(ampl_idx).value();
217  // Asymmetry parameter
218  brdf_params(kernel_index, 1) = surface_parameters(asym_idx).value();
219  // Geometric factor
220  brdf_params(kernel_index, 2) = surface_parameters(geom_idx).value();
221 }
222 
223 void SpurrBrdfDriver::setup_breon_inputs(int kernel_index, ArrayAd<double, 1>& surface_parameters, const Array<int, 1>& parameter_indexes) const
224 {
225  int kf_idx = parameter_indexes(0);
226 
227  brdf_factors(kernel_index) = surface_parameters(kf_idx).value();
228  brdf_params(kernel_index, 0) = 2.25; // Refractive index squared, same as hardcoded value inside lrad, should be same as value in ground_brdf.cc
229 }
230 
231 /********************************************************************/
232 
233 //-----------------------------------------------------------------------
235 //-----------------------------------------------------------------------
236 
237 double SpurrRtDriver::reflectance_calculate(const Array<double, 1>& height_grid,
238  double sza, double azm, double zen,
239  int surface_type,
240  const Array<double, 1>& surface_parameters,
241  const Array<double, 1>& od,
242  const Array<double, 1>& ssa,
243  const Array<double, 2>& pf,
244  double surface_bb,
245  const Array<double, 1>& atmosphere_bb)
246 {
247  // Initialize scene
248  setup_height_grid(height_grid);
249  brdf_driver_-> setup_geometry(sza, azm, zen);
250  setup_geometry(sza, azm, zen);
251 
252  // Set up BRDF inputs, here we throw away the jacobian
253  // value of the surface parameters
254  ArrayAd<double, 1> surf_param_ad(surface_parameters.rows(), 0);
255  surf_param_ad.value() = surface_parameters;
256  ArrayAd<double, 1> lidort_surf = brdf_driver_->setup_brdf_inputs(surface_type, surf_param_ad);
257 
258  // Set up LIDORT inputs and run
259  setup_optical_inputs(od, ssa, pf);
260 
261  if (do_thermal_emission)
262  setup_thermal_inputs(surface_bb, atmosphere_bb);
263 
264  clear_linear_inputs();
265  calculate_rt();
266 
267  // Return answer
268  return get_intensity();
269 }
270 
271 //-----------------------------------------------------------------------
274 //-----------------------------------------------------------------------
275 
276 void SpurrRtDriver::reflectance_and_jacobian_calculate(const Array<double, 1>& height_grid,
277  double sza, double azm, double zen,
278  int surface_type,
279  ArrayAd<double, 1>& surface_parameters,
280  const ArrayAd<double, 1>& od,
281  const ArrayAd<double, 1>& ssa,
282  const ArrayAd<double, 2>& pf,
283  double& reflectance,
284  Array<double, 2>& jac_atm,
285  Array<double, 1>& jac_surf,
286  double surface_bb,
287  const Array<double, 1>& atmosphere_bb)
288 
289 {
290  // Initialize scene
291  setup_height_grid(height_grid);
292  brdf_driver_->setup_geometry(sza, azm, zen);
293  setup_geometry(sza, azm, zen);
294 
295  // Set up BRDF inputs and run
296  surface_parameters = brdf_driver_->setup_brdf_inputs(surface_type, surface_parameters);
297 
298  setup_optical_inputs(od.value(), ssa.value(), pf.value());
299 
300  if (do_thermal_emission)
301  setup_thermal_inputs(surface_bb, atmosphere_bb);
302 
303  bool do_surface_pd = true;
304  setup_linear_inputs(od, ssa, pf, do_surface_pd);
305  calculate_rt();
306 
307  // Copy values from LIDORT
308  reflectance = get_intensity();
309  copy_jacobians(jac_atm, jac_surf);
310 }
virtual void setup_coxmunk_inputs(int kernel_index, ArrayAd< double, 1 > &surface_parameters, const blitz::Array< int, 1 > &parameter_indexes) const
virtual void initialize_brdf_kernel(int kernel_type)
Initializes a specific BRDF kernel based on the kernel type integer Each call adds a new kernel setup...
Definition: spurr_driver.cc:41
virtual ArrayAd< double, 1 > setup_brdf_inputs(int surface_type, const ArrayAd< double, 1 > &surface_parameters) const
Sets up the BRDF inputs to be used by the BRDF calculation code This routine is intended to be called...
This is the base of the exception hierarchy for Full Physics code.
Definition: fp_exception.h:16
virtual double reflectance_calculate(const blitz::Array< double, 1 > &height_grid, double sza, double azm, double zen, int surface_type, const blitz::Array< double, 1 > &surface_parameters, const blitz::Array< double, 1 > &od, const blitz::Array< double, 1 > &ssa, const blitz::Array< double, 2 > &pf, double surface_bb=0, const blitz::Array< double, 1 > &atmosphere_bb=blitz::Array< double, 1 >())
Computes reflectance without jacobians.
Apply value function to a blitz array.
const blitz::Array< T, D > & value() const
Definition: array_ad.h:306
virtual void reflectance_and_jacobian_calculate(const blitz::Array< double, 1 > &height_grid, double sza, double azm, double zen, int surface_type, ArrayAd< double, 1 > &surface_parameters, const ArrayAd< double, 1 > &od, const ArrayAd< double, 1 > &ssa, const ArrayAd< double, 2 > &pf, double &reflectance, blitz::Array< double, 2 > &jac_atm, blitz::Array< double, 1 > &jac_surf, double surface_bb=0, const blitz::Array< double, 1 > &atmosphere_bb=blitz::Array< double, 1 >())
Calculates intensity, profile and surface weighting factors (jacobians) with the given inputs...
Contains classes to abstract away details in various Spurr Radiative Transfer software.
Definition: doxygen_python.h:1
virtual void setup_breon_inputs(int kernel_index, ArrayAd< double, 1 > &surface_parameters, const blitz::Array< int, 1 > &parameter_indexes) const
virtual void initialize_brdf_inputs(int surface_type)
Initializes the BRDF kernels for the given Ground surface type integer.
Definition: spurr_driver.cc:13
double value(const FullPhysics::AutoDerivative< double > &Ad)
virtual void setup_lambertian_inputs(int kernel_index, ArrayAd< double, 1 > &surface_parameters, const blitz::Array< int, 1 > &parameter_indexes) const
virtual void setup_rahman_inputs(int kernel_index, ArrayAd< double, 1 > &surface_parameters, const blitz::Array< int, 1 > &parameter_indexes) const

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