ReFRACtor
absorber_absco.h
Go to the documentation of this file.
1 #ifndef ABSORBER_ABSCO_H
2 #define ABSORBER_ABSCO_H
3 #include "absorber.h"
4 #include "absorber_vmr.h"
5 #include "state_vector.h"
6 #include "pressure.h"
7 #include "pressure_level_input.h"
8 #include "absco.h"
9 #include "temperature.h"
10 #include "altitude.h"
11 #include "constant.h"
12 #include "fp_exception.h"
13 #include "fp_gsl_integrate.h"
14 #include <vector>
15 
16 namespace FullPhysics {
17 /****************************************************************/
23 class AbsorberAbsco: public Absorber,
24  public Observer<AbsorberVmr>,
25  public Observer<Pressure>,
26  public Observer<Temperature>,
27  public Observer<Altitude> {
28 public:
29  AbsorberAbsco(const std::vector<boost::shared_ptr<AbsorberVmr> > Vmr,
30  const boost::shared_ptr<Pressure>& Press,
32  const std::vector<boost::shared_ptr<Altitude> >& Alt,
33  const std::vector<boost::shared_ptr<GasAbsorption> >&
34  Gas_absorption,
36  int Nsub = 10);
37  virtual ~AbsorberAbsco() {}
38  // We use attach_notify to directly attach the various object that
39  // AbsorberAbsco contains. This means we don't need to do anything with
40  // changes to the StateVector in this class, it is already handled
41  // by the objects we contain.
42  virtual void notify_update(const StateVector& Sv)
43  { notify_update_do(*this); }
44  virtual int number_species() const {return (int) vmr.size(); }
45  virtual int number_spectrometer() const {return (int) alt.size();}
46  virtual int number_layer() const { return press->number_layer(); }
47  virtual std::string gas_name(int Species_index) const
48  { range_check(Species_index, 0, number_species());
49  return vmr[Species_index]->gas_name();
50  }
51 
52 //-----------------------------------------------------------------------
56 //-----------------------------------------------------------------------
57 
58  virtual void notify_update(const Pressure& P)
59  {
60  cache_tau_gas_stale = true;
61  notify_update_do(*this);
62  }
63  virtual void notify_update(const Temperature& T)
64  {
65  cache_tau_gas_stale = true;
66  notify_update_do(*this);
67  }
68  virtual void notify_update(const Altitude& A)
69  {
70  cache_tau_gas_stale = true;
71  notify_update_do(*this);
72  }
73  virtual void notify_update(const AbsorberVmr& A)
74  {
75  cache_tau_gas_stale = true;
76  notify_update_do(*this);
77  }
78  virtual ArrayAd<double, 2>
79  optical_depth_each_layer(double wn, int spec_index) const;
80  virtual blitz::Array<double, 2>
81  optical_depth_each_layer_nder(double wn, int spec_index) const;
89  gas_column_thickness_layer(const std::string& Gas_name) const;
91  gas_total_column_thickness(const std::string& Gas_name) const;
92 
93  virtual AutoDerivative<double> xgas(const std::string& Gas_name) const;
94 
95  AutoDerivative<double> total_number_density(const std::string& Gas_name) const;
96  AutoDerivative<double> average_vmr(const std::string& Gas_name) const;
97 
98  virtual void print(std::ostream& Os) const;
99  virtual boost::shared_ptr<Absorber> clone() const;
101  (const boost::shared_ptr<Pressure>& Press,
102  const boost::shared_ptr<Temperature>& Temp,
103  const std::vector<boost::shared_ptr<Altitude> >& Alt) const;
104  virtual boost::shared_ptr<AbsorberVmr> absorber_vmr(const std::string& Gas_name) const;
105  const Pressure& pressure() const {return *press;}
106 
108  (const std::string& Gas_name) const;
109 
110 //----------------------------------------------------------------
113 //----------------------------------------------------------------
114 
116  { fill_tau_gas_cache(); return psub;}
117 
120  ArrayAdWithUnit<double, 1> gravity_sublayer(int Spec_index) const;
121  ArrayAdWithUnit<double, 1> vmr_sublayer(const std::string& Gas_name) const;
123  (int Spec_index, int Species_index, const DoubleWithUnit& P)
124  const;
125  double integrand
126  (double wn, double p, int Spec_index, int Species_index) const;
127  double optical_depth_each_layer_direct_integrate(double wn, int Spec_index,
128  int Species_index, int
129  Layer_index,
130  double eps_abs = 0,
131  double eps_rel = 1e-3) const;
132  blitz::Array<double, 2>
133  optical_depth_each_layer_direct_integrate(double wn, int Spec_index,
134  double eps_abs = 0,
135  double eps_rel = 1e-3) const;
136 private:
137  // Objects used to calculate the integrand
140  std::vector<boost::shared_ptr<Altitude> > alt;
141  std::vector<boost::shared_ptr<AbsorberVmr> > vmr;
142  std::vector<boost::shared_ptr<GasAbsorption> > gas_absorption;
143 
144  // Used for optical_depth_each_layer_direct_integrate. We don't use
145  // this function when using AbsorberAbsco normally, but this is a
146  // useful test function to see how well our approximate integral in
147  // optical_depth_each_layer is working.
148  GslIntegrate intg;
149 
150  // The species index that corresponds to water.
151  int h2o_index;
152 
153  // Constants used to get things like avogadro_constant and
154  // molar_weight_water.
156 
157  // Number of sub layers to use in gas calculation.
158  int nsub;
159 
160  // Cache a good portion of the tau_gas calculation, everything that
161  // is not dependent on wn.
162 
163  mutable bool cache_tau_gas_stale; // Indicate if cache data is stale
164  mutable std::vector<boost::shared_ptr<AbscoInterpolator> > absco_interp;
165  // Used to quickly get absorption
166  // coefficients for integral
167  mutable ArrayAdWithUnit<double, 1> pgrid;
168  // Pressure grid on each level.
169  mutable ArrayWithUnit<double, 1> psub;
170  // Pressures that we calculate
171  // integrand on
172  mutable std::vector<blitz::Range> layer_range;
173  // For each layer, give the Range in
174  // psub that fits in that layer.
175  mutable std::vector<ArrayWithUnit<double, 1> > weight;
176  // Weight for each layer.
177  mutable ArrayAdWithUnit<double, 3> integrand_independent_wn_sub;
178  // This is the integrand independent
179  // of wavenumber wn at each psub.
180  // This is indexed by Spec_index,
181  // Species_index, sublayer index
182 
183  // The various jacobians we need to track tend to be fairly
184  // sparse. To speed up calculation, we use a spare implementation of
185  // these arrays.
186 
187  // For each layer, store the nonzero columns, and the gradient of p1
188  // and p2 compressed to those nonzero columns.
189  mutable std::vector<std::vector<int> > pressure_nonzero_column;
190  mutable std::vector<blitz::Array<double, 1> > p1_grad;
191  mutable std::vector<blitz::Array<double, 1> > p2_grad;
192 
193  // Same thing for integrand_independent_wn_sub
194  mutable std::vector<std::vector<int> > integrand_nonzero_column;
195  mutable std::vector<blitz::Array<double, 4> > integrand_jac;
196 
197  // And for Absco (only Absco is not by layer)
198  mutable std::vector<int> absco_nonzero_column;
199 
200 
201  // Scratch variable used to calculate taug. We keep this around so
202  // we don't keep recreating the Array (so this is to improve performance)
203  mutable ArrayAd<double, 2> taug;
204 
205  blitz::Array<double, 2>
206  tau_gas_nder(double wn, int spec_index) const;
208  tau_gas_der(double wn, int spec_index) const;
209  void fill_tau_gas_cache() const;
210  void create_sublayer() const;
211 
212  // Short functions to get the temperature, gravity, and mixing
213  // levels at a particular pressure. Since we use these in a few
214  // places, it is worth wrapping up into shorter functions rather
215  // than repeating thing code in multiple places.
217  temp_func(const DoubleWithUnit& P) const
218  { return
219  temp->temperature(AutoDerivativeWithUnit<double>(P.value, P.units)); }
221  h2o_vmr_func(const DoubleWithUnit& P) const
222  {
223  if(h2o_index < 0)
225  else
226  return AutoDerivativeWithUnit<double>(vmr[h2o_index]->volume_mixing_ratio(P.convert(Unit("Pa")).value), units::dimensionless);
227  }
229  vmr_func(int Species_index, const DoubleWithUnit& P) const
230  { return AutoDerivativeWithUnit<double>(vmr[Species_index]->volume_mixing_ratio(P.convert(Unit("Pa")).value), units::dimensionless); }
232  gravity_func(int Spec_index, const DoubleWithUnit& P) const
233  { return alt[Spec_index]->gravity(AutoDerivativeWithUnit<double>(P.value, P.units)); }
234 
235 };
236 }
237 #endif
virtual std::string gas_name(int Species_index) const
Name of gases, in the order that optical_depth_each_layer returns them.
#define range_check(V, Min, Max)
Range check.
Definition: fp_exception.h:140
This class maintains the absorber portion of the state.
ArrayAd< double, 1 > pressure_weighting_function_grid() const
This is the pressure weighting function by grid level.
This is a AutoDerivative that also has units associated with it.
The class handles the calculation of the altitude and gravity constants.
Definition: altitude.h:19
virtual boost::shared_ptr< Absorber > clone() const
Clone an Absorber object.
ArrayAdWithUnit< double, 1 > h2o_vmr_sublayer() const
Return the H2O volume mixing ratio we use for each sublayer.
double integrand(double wn, double p, int Spec_index, int Species_index) const
Integrand used in the absorption calculation.
AbsorberAbsco(const std::vector< boost::shared_ptr< AbsorberVmr > > Vmr, const boost::shared_ptr< Pressure > &Press, const boost::shared_ptr< Temperature > &Temp, const std::vector< boost::shared_ptr< Altitude > > &Alt, const std::vector< boost::shared_ptr< GasAbsorption > > &Gas_absorption, const boost::shared_ptr< Constant > &C, int Nsub=10)
Create an absorber.
ArrayAdWithUnit< double, 1 > dry_air_molecular_density_layer() const
This is a helper function to compute the common part of the dry air mass and wet air mass routines...
const Unit dimensionless("dimensionless", 1.0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
virtual void print(std::ostream &Os) const
virtual boost::shared_ptr< AbsorberVmr > absorber_vmr(const std::string &Gas_name) const
Returns the AbsorberVmr object for a given species index.
virtual blitz::Array< double, 2 > optical_depth_each_layer_nder(double wn, int spec_index) const
virtual int number_layer() const
AutoDerivative< double > average_vmr(const std::string &Gas_name) const
Returns the simple average volume mixing ratio for a gas.
ArrayAdWithUnit< double, 1 > wet_air_column_thickness_layer() const
This is the wet air column thickness by layer.
AutoDerivativeWithUnit< double > integrand_independent_wn(int Spec_index, int Species_index, const DoubleWithUnit &P) const
This is the portion of the optical depth calculation integrand that is independent on the wave number...
void notify_update_do(const Absorber &Self)
Function to call to notify Observers of a state change.
Definition: observer.h:121
const Unit A("A", 1.0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0)
ArrayAd< double, 1 > pressure_weighting_function_layer() const
This is the pressure weighting function by layer.
virtual void notify_update(const Pressure &P)
For performance, we cache some data as we calculate it.
AutoDerivative< double > total_number_density(const std::string &Gas_name) const
ArrayWithUnit< double, 1 > pressure_sublayer() const
Return the pressure we use for each sublayer.
virtual ArrayAd< double, 2 > optical_depth_each_layer(double wn, int spec_index) const
This gives the optical depth for each layer, for the given wave number.
We frequently have a double with units associated with it.
double optical_depth_each_layer_direct_integrate(double wn, int Spec_index, int Species_index, int Layer_index, double eps_abs=0, double eps_rel=1e-3) const
Find the optical depth for a layer by directly integrating the integrand function.
This handles informing a set of interested objects when the state vector has updated.
Definition: state_vector.h:16
DoubleWithUnit convert(const Unit &R) const
Convert to the given units.
virtual void notify_update(const Temperature &T)
Called when the Observed object is updated.
ArrayAdWithUnit< double, 1 > vmr_sublayer(const std::string &Gas_name) const
Return the volume mixing ratio we use for each sublayer.
This gives the Gas Absorber Volumn mixing ratio for a single gas.
Definition: absorber_vmr.h:17
This class maintains the pressure portion of the state.
Definition: pressure.h:32
Libraries such as boost::units allow unit handling where we know the units at compile time...
Definition: unit.h:25
This is a thin wrapper around the GSL integration function.
virtual int number_spectrometer() const
Contains classes to abstract away details in various Spurr Radiative Transfer software.
Definition: doxygen_python.h:1
ArrayAdWithUnit< double, 1 > specific_humidity_layer() const
Returns specific humidity by layer.
ArrayAdWithUnit< double, 1 > gravity_sublayer(int Spec_index) const
Return the gravity we use for each sublayer.
This class maintains the absorber portion of the state.
Definition: absorber.h:27
This class maintains the temperature portion of the state.
Definition: temperature.h:22
virtual void notify_update(const StateVector &Sv)
Called when the Observed object is updated.
virtual void notify_update(const AbsorberVmr &A)
Called when the Observed object is updated.
ArrayAdWithUnit< double, 1 > gas_column_thickness_layer(const std::string &Gas_name) const
This is the column thickness of a gas by layer.
ArrayAdWithUnit< double, 1 > temperature_sublayer() const
Return the temperature we use for each sublayer.
virtual void notify_update(const Altitude &A)
Called when the Observed object is updated.
virtual AutoDerivative< double > xgas(const std::string &Gas_name) const
This calculates the gas column, e.g., XCO2.
AutoDerivativeWithUnit< double > gas_total_column_thickness(const std::string &Gas_name) const
This is the total column thickness of a gas.
virtual int number_species() const
Number of species.
ArrayAdWithUnit< double, 1 > dry_air_column_thickness_layer() const
This is the dry air column thickness by layer.
const Pressure & pressure() const
Simple Mixin to be and Observer of another object of class T.
Definition: observer.h:29
boost::shared_ptr< GasAbsorption > gas_absorption_ptr(const std::string &Gas_name) const
Return GasAbsorption as a pointer.

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