ReFRACtor
twostream_driver.cc
Go to the documentation of this file.
1 #include "twostream_driver.h"
2 #include "old_constant.h"
3 #include "wgs84_constant.h"
4 #include "ground.h"
5 #include "spurr_brdf_types.h"
7 
8 using namespace FullPhysics;
9 using namespace blitz;
10 
11 
12 //-----------------------------------------------------------------------
14 //-----------------------------------------------------------------------
15 
17 {
18  int nbeams = 1;
19  int n_user_streams = 1;
20 
21  // Number of quadtrature streams for BRDF calculation
22  // Use value consistent with LIDORT
23  int nstreams_brdf = 50;
24 
26 
27  twostream_brdf_.reset( new Twostream_Ls_Brdf_Supplement(
28  lid_pars.maxbeams, lid_pars.max_user_streams, lid_pars.max_user_obsgeoms, lid_pars.maxstreams_brdf,
29  lid_pars.max_brdf_kernels, lid_pars.max_brdf_parameters, lid_pars.max_surfacewfs,
30  nbeams, n_user_streams, nstreams_brdf) );
31 
32  brdf_params.reference( twostream_brdf_->brdf_parameters() );
33  brdf_factors.reference( twostream_brdf_->brdf_factors() );
34 
35 }
36 
37 void TwostreamBrdfDriver::setup_geometry(double sza, double azm, double zen) const
38 {
39  // Solar zenith angles (degrees) [0,90]
40  Array<double, 1> beam_szas( twostream_brdf_->beam_szas() );
41  beam_szas(0) = sza;
42 
43  // Viewing zenith angle (degrees)
44  Array<double, 1> user_angles( twostream_brdf_->user_angles() );
45  user_angles(0) = zen;
46 }
47 
49 {
50  twostream_brdf_->run();
51 }
52 
54 {
55  return twostream_brdf_->n_brdf_kernels();
56 }
57 
58 void TwostreamBrdfDriver::n_brdf_kernels(const int n_kernels)
59 {
60  twostream_brdf_->n_brdf_kernels(n_kernels);
61 }
62 
64 {
65  return twostream_brdf_->n_kernel_factor_wfs();
66 }
67 
68 void TwostreamBrdfDriver::n_kernel_factor_wfs(const int n_factors)
69 {
70  // Do not really set this, twostream calculates this internally
71  // It adds to the passed in value, so book keeping values
72  // will occur if this is non-zero
73  //twostream_brdf_->n_kernel_factor_wfs(n_factors);
74 }
75 
77 {
78  return twostream_brdf_->n_kernel_params_wfs();
79 }
80 
82 {
83  // Do not really set this, twostream calculates this internally
84  // It adds to the passed in value, so book keeping values
85  // will occur if this is non-zero
86  //twostream_brdf_->n_kernel_params_wfs(n_params);
87 }
88 
90 {
91  return twostream_brdf_->n_surface_wfs();
92 }
93 
94 void TwostreamBrdfDriver::n_surface_wfs(const int n_wfs)
95 {
96  // Do not really set this, twostream calculates this internally
97  // It adds to the passed in value, so book keeping values
98  // will occur if this is non-zero
99  //twostream_brdf_->n_surface_wfs(n_wfs);
100 }
101 
102 bool TwostreamBrdfDriver::do_kparams_derivs(const int kernel_index) const
103 {
104  return twostream_brdf_->do_kparams_derivs()(kernel_index);
105 }
106 
107 void TwostreamBrdfDriver::do_kparams_derivs(const int kernel_index, const bool do_kparams)
108 {
109  // Do not really set this, twostream calculates this internally
110  // It adds to the passed in value, so book keeping values
111  // will occur if this is non-zero
112  //Array<bool, 1> ts_do_kparams_derivs(twostream_brdf_->do_kparams_derivs());
113  //ts_do_kparams_derivs(kernel_index) = do_kparams;
114  //twostream_brdf_->do_kparams_derivs(ts_do_kparams_derivs);
115 }
116 
118  return twostream_brdf_->do_shadow_effect();
119 }
120 
121 void TwostreamBrdfDriver::do_shadow_effect(const bool do_shadow) const {
122  twostream_brdf_->do_shadow_effect(do_shadow);
123 }
124 
126  const int which_brdf,
127  const bool lambertian_flag,
128  const int n_brdf_parameters,
129  const bool do_factor_wfs,
130  const blitz::Array<bool, 1>& do_params_wfs)
131 {
132  Array<int, 1> ts_which_brdf( twostream_brdf_->which_brdf() );
133  ts_which_brdf(kernel_index) = which_brdf;
134 
135  Array<bool, 1> ts_lambertian_flag = twostream_brdf_->lambertian_kernel_flag();
136  ts_lambertian_flag(kernel_index) = lambertian_flag;
137  twostream_brdf_->lambertian_kernel_flag(ts_lambertian_flag);
138 
139  Array<int, 1> ts_n_brdf_parameters( twostream_brdf_->n_brdf_parameters() );
140  ts_n_brdf_parameters(kernel_index) = n_brdf_parameters;
141 
142  Array<bool, 1> ts_do_factor_wfs( twostream_brdf_->do_kernel_factor_wfs() );
143  ts_do_factor_wfs(kernel_index) = do_factor_wfs;
144  twostream_brdf_->do_kernel_factor_wfs(ts_do_factor_wfs);
145 
146  Array<bool, 2> ts_do_params_wfs( twostream_brdf_->do_kernel_params_wfs() );
147  ts_do_params_wfs(kernel_index, Range(0, do_params_wfs.rows()-1)) = do_params_wfs;
148  twostream_brdf_->do_kernel_params_wfs(ts_do_params_wfs);
149 }
150 
151 //=======================================================================
156 //=======================================================================
157 
158 TwostreamRtDriver::TwostreamRtDriver(int nlayers, int surface_type, bool do_fullquadrature,
159  bool do_solar, bool do_thermal)
160  : surface_type_(surface_type), do_fullquadrature_(do_fullquadrature), SpurrRtDriver(do_solar, do_thermal)
161 {
163 
164  int nbeams = 1;
165  int n_user_streams = 1;
166  int n_user_relazms = 1;
167 
168  int n_geometries = nbeams * n_user_streams * n_user_relazms;
169  int ntotal = 2 * nlayers;
170 
171  double earth_radius = OldConstant::wgs84_a.convert(units::km).value;
172 
173  Lidort_Pars lid_pars = Lidort_Pars::instance();
174 
176  lid_pars.maxlayers, lid_pars.maxtotal, lid_pars.max_messages,
177  lid_pars.maxbeams, lid_pars.max_geometries,
178  lid_pars.max_user_streams, lid_pars.max_user_relazms, lid_pars.max_user_obsgeoms,
179  lid_pars.max_atmoswfs, lid_pars.max_surfacewfs, lid_pars.max_sleavewfs,
180  nlayers, ntotal, n_user_streams, n_user_relazms, nbeams, earth_radius, n_geometries) );
181 
182  // Initialize BRDF data structure
183  brdf_driver_->initialize_brdf_inputs(surface_type_);
184 
185  initialize_rt();
186 }
187 
189 {
190 
191  // Set a value or divide by zeros will occur
192  twostream_interface_->bvpscalefactor(1.0);
193 
194  // 2stream guide says this:
195  // For scattering applications, should be set to 0.5
196  // For thermal applications, should be set to sqrt(1/3)
197  if (do_fullquadrature_)
198  twostream_interface_->stream_value( sqrt(1.0e0 / 3.0e0 ) );
199  else
200  twostream_interface_->stream_value( 0.5e0 );
201 
202  // Set stream value for BRDF interface to the same value used by 2stream interface
203  brdf_interface()->stream_value( twostream_interface_->stream_value() );
204 
205  // Always usr BRDF supplement, even for lambertian albedo
206  twostream_interface_->do_brdf_surface(true);
207 
208  // Flags for viewing mode
209  twostream_interface_->do_upwelling(true);
210  twostream_interface_->do_dnwelling(false);
211 
212  // In most instances this flag for delta-m scaling should be set
213  twostream_interface_->do_d2s_scaling(true);
214 
215  // Beam source flux, same value used for all solar angles
216  // Normally set to 1 for "sun-normalized" output
217  twostream_interface_->flux_factor(1.0);
218 
219  // Enable solar sources for RT & BRDF
220  if (do_solar_sources) {
221  twostream_interface_->do_solar_sources(true);
222 
223  brdf_interface()->do_solar_sources(true);
224  }
225 
226  // Setup thermal emission calculation for RT and BRDF
227  if (do_thermal_emission) {
228  twostream_interface_->do_thermal_emission(true);
229  twostream_interface_->do_surface_emission(true);
230 
231  brdf_interface()->do_surface_emission(true);
232  }
233 
234  // Flag for calculating profile Jacobians in layer n
235  // Calculate jacobians for all layers
236  Array<bool, 1> layer_jac_flag(twostream_interface_->layer_vary_flag());
237  layer_jac_flag = true;
238  twostream_interface_->layer_vary_flag(layer_jac_flag);
239 
240  // Link twostream interface brdf inputs to brdf interface
241  twostream_interface_->brdf_f_0().reference(brdf_interface()->brdf_f_0());
242  twostream_interface_->brdf_f().reference(brdf_interface()->brdf_f());
243  twostream_interface_->ubrdf_f().reference(brdf_interface()->ubrdf_f());
244 
245  twostream_interface_->ls_brdf_f_0().reference(brdf_interface()->ls_brdf_f_0());
246  twostream_interface_->ls_brdf_f().reference(brdf_interface()->ls_brdf_f());
247  twostream_interface_->ls_ubrdf_f().reference(brdf_interface()->ls_ubrdf_f());
248 
249  if (do_thermal_emission) {
250  twostream_interface_->ls_emissivity().reference(brdf_interface()->ls_emissivity());
251  }
252 }
253 
254 void TwostreamRtDriver::setup_height_grid(const blitz::Array<double, 1>& in_height_grid) const
255 {
256 
257  int nlayers = in_height_grid.rows() - 1;
258 
259  // Make sure incoming height grid is compatible with initialized size
260  if (twostream_interface_->nlayers() != nlayers)
261  throw Exception("TwostreamDriver does not support the number of layers changing during the retrieval.");
262 
263  // Set only the layers being used
264  Array<double, 1> ts_height_grid( twostream_interface_->height_grid() );
265  ts_height_grid(Range(0, nlayers)) = in_height_grid;
266 }
267 
268 void TwostreamRtDriver::setup_geometry(double sza, double azm, double zen) const
269 {
270  // Solar zenith angles (degrees) [0,90]
271  Array<double, 1> ts_sza( twostream_interface_->beam_szas() );
272  ts_sza(0) = sza;
273 
274  // User-defined relative angles (in degrees) for
275  // off-quadrature output.
276  Array<double, 1> ts_azm( twostream_interface_->user_relazms() );
277  ts_azm(0) = azm;
278 
279  // User-defined viewing zenith angles (in degrees) for
280  // off quadrature output.
281  Array<double, 1> ts_zen( twostream_interface_->user_angles() );
282  ts_zen(0) = zen;
283 }
284 
285 void TwostreamRtDriver::setup_thermal_inputs(double surface_bb, const blitz::Array<double, 1> atmosphere_bb) const
286 {
287  twostream_interface_->surfbb(surface_bb);
288 
289  // Thermal black body atmosphere inputs will be on levels instead of layers
290  Range rlev(0, atmosphere_bb.extent(firstDim) - 1);
291  Array<double, 1> thermal_bb_input( twostream_interface_->thermal_bb_input() );
292  thermal_bb_input(rlev) = atmosphere_bb;
293 
294  // Copy emissivity from the BRDF module, assumes that the brdf_interface setup has been run
295  twostream_interface_->emissivity(brdf_interface()->emissivity());
296 }
297 
298 void TwostreamRtDriver::setup_optical_inputs(const blitz::Array<double, 1>& od,
299  const blitz::Array<double, 1>& ssa,
300  const blitz::Array<double, 2>& pf) const
301 {
302  // Ranges for copying inputs to method
303  Range rlay(0, od.extent(firstDim) - 1);
304 
305  // Vertical optical depth thickness values for all layers
306  Array<double, 1> deltau( twostream_interface_->deltau_input() );
307  deltau(rlay) = od;
308 
309  // Single scattering albedos for all layers
310  Array<double, 1> omega( twostream_interface_->omega_input() );
311  omega(rlay) = where(ssa > 0.999, 0.999999, ssa);
312 
313  // Assymetry factor
314  // Equal to one third of the first phase function moment
315  Array<double, 1> asymm_input( twostream_interface_->asymm_input() );
316  asymm_input(rlay) = pf(1, rlay) / 3.0;
317 
318  // Delta-m scaling factor for 2-stream
319  // Equal to one fifth of the second phase function moment
320  if (twostream_interface_->do_d2s_scaling()) {
321  Array<double, 1> d2s_scaling( twostream_interface_->d2s_scaling() );
322  d2s_scaling(rlay) = pf(2, rlay) / 5.0;
323  }
324 }
325 
327 {
328  // Disable wfs for both types supported
329  twostream_interface_->do_profile_wfs(false);
330  twostream_interface_->do_surface_wfs(false);
331 }
332 
334  const ArrayAd<double, 1>& ssa,
335  const ArrayAd<double, 2>& pf,
336  bool do_surface_linearization) const
337 {
338  // Number of profile weighting functions in layer n
339  int natm_jac = od.number_variable();
340  Array<int, 1> layer_jac_number( twostream_interface_->layer_vary_number() );
341  layer_jac_number = natm_jac;
342 
343  // Ranges for copying inputs to method
344  Range rlay(0, od.rows() - 1); // number of layers
345  Range rjac(0, natm_jac - 1);
346  Range all(Range::all());
347 
348  // Flag for output of profile Jacobians
349  // Unlikely we won't need these
350  twostream_interface_->do_profile_wfs(true);
351 
352  // Needs to match the number set in the BRDF structure
353  twostream_interface_->n_surface_wfs(brdf_driver_->n_surface_wfs());
354 
355  // Flag for output of surface Jacobians
356  // Certainly wouldn't need this if not retrieving ground
357  twostream_interface_->do_surface_wfs(do_surface_linearization);
358 
359  // Check that we fit within the LIDORT configuration
360  if(twostream_interface_->l_deltau_input().rows() < od.rows()) {
361  Exception e;
362  e << "The number of layers you are using exceeds the maximum allowed by\n"
363  << "the current build of Lidort. The number requested is "
364  << od.rows() << "\nand the maximum allowed is "
365  << twostream_interface_->l_deltau_input().rows() << "\n"
366  << "\n"
367  << "You might try rebuilding with a larger value given to the configure\n"
368  << "option --with-lidort-maxlayer=value set to a larger value.\n";
369  throw e;
370  }
371  if(twostream_interface_->l_deltau_input().cols() < natm_jac) {
372  Exception e;
373  e << "The number of jacobians you are using exceeds the maximum allowed by\n"
374  << "the current build of Lidort. The number requested is "
375  << natm_jac << "\nand the maximum allowed is "
376  << twostream_interface_->l_deltau_input().cols() << "\n"
377  << "\n"
378  << "This number of jacobians is a function of the number of aerosols\n"
379  << "in your state vector, so you can reduce the number of aerosols\n"
380  << "\n"
381  << "You might also try rebuilding with a larger value given to the configure\n"
382  << "option --with-lidort-maxatmoswfs=value set to a larger value.\n";
383  throw e;
384  }
385 
386  // Setup optical linear inputs
387  Array<double, 2> l_deltau( twostream_interface_->l_deltau_input()(rlay,rjac) );
388  Array<double, 2> l_omega( twostream_interface_->l_omega_input()(rlay,rjac) );
389  Array<double, 2> l_asymm_input( twostream_interface_->l_asymm_input()(rlay,rjac) );
390  Array<double, 2> l_d2s_scaling( twostream_interface_->l_d2s_scaling()(rlay,rjac) );
391 
392  l_deltau = od.jacobian();
393  l_omega = ssa.jacobian();
394 
395  l_asymm_input = pf.jacobian()(1, all, all) / 3.0;
396  l_d2s_scaling = pf.jacobian()(2, all, all) / 5.0;
397 }
398 
400 {
401  twostream_interface_->run();
402 
403  // Exception handling
404  if (twostream_interface_->status_inputcheck() == 1) {
405  stringstream err_msg;
406  err_msg << "TwostreamInterace input check failed:" << std::endl;
407  for(int k = 0; k < twostream_interface_->c_nmessages(); k++) {
408  err_msg << " - Message # " << k << ": " << twostream_interface_->c_messages()[k] << std::endl
409  << " - Action # " << k << ": " << twostream_interface_->c_actions()[k] << std::endl;
410  }
411  throw Exception(err_msg.str());
412  }
413  if (twostream_interface_->status_execution() == 1) {
414  stringstream err_msg;
415  err_msg << "TwostreamInterace execution failed:" << std::endl
416  << twostream_interface_->e_message() << std::endl
417  << twostream_interface_->e_trace_1() << std::endl
418  << twostream_interface_->e_trace_2() << std::endl;
419  throw Exception(err_msg.str());
420  }
421 
422 }
423 
425 {
426  return twostream_interface_->intensity_toa()(0);
427 }
428 
429 void TwostreamRtDriver::copy_jacobians(blitz::Array<double, 2>& jac_atm, blitz::Array<double, 1>& jac_surf) const
430 {
431  // Copy out jacobian values
432  Range ra(Range::all());
433  jac_atm.reference( twostream_interface_->profilewf_toa()(0, ra, ra).copy() );
434  jac_atm.transposeSelf(secondDim, firstDim); // swap to same ordering as lidort
435 
436  jac_surf.reference( twostream_interface_->surfacewf_toa()(0, ra).copy() );
437 }
438 
boost::shared_ptr< Twostream_Ls_Brdf_Supplement > brdf_interface() const
void initialize_rt()
Initializes radiative transfer data structures.
virtual int n_kernel_factor_wfs() const
static Lidort_Pars & instance()
virtual void setup_geometry(double sza, double azm, double zen) const
void setup_linear_inputs(const ArrayAd< double, 1 > &od, const ArrayAd< double, 1 > &ssa, const ArrayAd< double, 2 > &pf, bool do_surface_linearization) const
Set up linearization, weighting functions.
boost::shared_ptr< Twostream_Lps_Master > twostream_interface_
TwostreamBrdfDriver(int surface_type)
Initialize Twostream BRDF interface.
const DoubleWithUnit wgs84_a(6378137.0000, units::m)
Equatorial radius.
void setup_thermal_inputs(double surface_bb, const blitz::Array< double, 1 > atmosphere_bb) const
Set up thermal emission inputs.
TwoStream specific BRDF driver implementation.
This is the base of the exception hierarchy for Full Physics code.
Definition: fp_exception.h:16
TwostreamRtDriver(int nlayers, int surface_type, bool do_fullquadrature=true, bool do_solar=true, bool do_thermal=false)
TwostreamRtDriver Sizes of layers, and number of jacobians must be set up in construtor as seen in si...
virtual bool do_kparams_derivs(const int kernel_index) const
void clear_linear_inputs() const
Mark that we are not retrieving weighting functions.
const blitz::Array< T, D+1 > jacobian() const
Definition: array_ad.h:307
Apply value function to a blitz array.
virtual void initialize_kernel_parameters(const int kernel_index, const int which_brdf, const bool lambertian_flag, const int n_brdf_parameters, const bool do_factor_wfs, const blitz::Array< bool, 1 > &do_params_wfs)
void setup_optical_inputs(const blitz::Array< double, 1 > &od, const blitz::Array< double, 1 > &ssa, const blitz::Array< double, 2 > &pf) const
Set up optical depth, single scattering albedo and phase function Should be called per spectral point...
void copy_jacobians(blitz::Array< double, 2 > &jac_atm, blitz::Array< double, 1 > &jac_surf) const
Copy jacobians out of internal xdata structures.
int number_variable() const
Definition: array_ad.h:376
DoubleWithUnit convert(const Unit &R) const
Convert to the given units.
double get_intensity() const
Retrieve the intensity value calculated.
Abstracts away set up of Radiative Transfer software from Rob Spurr into a simpler common inteface us...
Definition: spurr_driver.h:90
void setup_height_grid(const blitz::Array< double, 1 > &height_grid) const
Setup height grid, should only be called once per instance or if the height grid changes.
Contains classes to abstract away details in various Spurr Radiative Transfer software.
Definition: doxygen_python.h:1
void setup_geometry(double sza, double azm, double zen) const
Setup viewing geometry, should only be called once per instance or if the viewing geometry changes...
virtual int n_kernel_params_wfs() const
virtual void calculate_brdf() const
const Unit km("km", 1e3 *m)
virtual bool do_shadow_effect() const
boost::shared_ptr< SpurrBrdfDriver > brdf_driver_
Spurr BRDF class interface class to use.
Definition: spurr_driver.h:169
void calculate_rt() const
Perform radiative transfer calculation with the values setup by setup_optical_inputs and setup_linear...
int rows() const
Definition: array_ad.h:368

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