mxlib
c++ tools for analyzing astronomical data and other tasks by Jared R. Males. [git repo]
aoAtmosphere.hpp
Go to the documentation of this file.
1 /** \file aoAtmosphere.hpp
2  * \author Jared R. Males (jaredmales@gmail.com)
3  * \brief Provides a class to specify atmosphere parameters.
4  * \ingroup mxAO_files
5  *
6  */
7 
8 #ifndef aoAtmosphere_hpp
9 #define aoAtmosphere_hpp
10 
11 
12 
13 #include <iostream>
14 #include <numeric>
15 #include <cmath>
16 #include <cstdlib>
17 #include <vector>
18 #include <algorithm>
19 
20 
21 #include "../../mxlib.hpp"
22 #include "../../mxError.hpp"
23 
24 #include "aoConstants.hpp"
25 
26 #include "../../math/constants.hpp"
27 
28 #include "../../app/appConfigurator.hpp"
29 
30 namespace mx
31 {
32 namespace AO
33 {
34 namespace analysis
35 {
36 
37 ///A class to specify atmosphere parameters and perform related calculations.
38 /**
39  * \todo layer outer scales need work
40  * \todo layer PSD params isn't finished. Need to push that to PSD itself, and manage things like wavelength dependence.
41  *
42  * \tparam realT is the real floating type in which all calculations are performed.
43  *
44  * \ingroup mxAOAnalytic
45  */
46 template<typename _realT>
48 {
49 public:
50 
51  typedef _realT realT; ///< The real floating type in which all calculations are performed.
52 
53  ///Constructor
55 
56 protected:
57 
58  realT m_r_0; ///< Fried's parameter, in m
59 
60  realT m_lam_0 {0.5e-6}; ///<Wavelength of Fried's parameter, in m
61 
62  std::vector<realT> m_layer_Cn2; ///< Vector of layer strengths.
63 
64  std::vector<realT> m_L_0; ///< The outer scale, in m
65 
66  std::vector<realT> m_l_0; ///< The inner scale of each layer, in m
67 
68  bool m_nonKolmogorov {false}; ///< Flag indicating if non-Kolmogorov PSD parameters are used.
69 
70  std::vector<realT> m_beta {1}; ///< The PSD normalization when in non-Kolmogorov mode.
71 
72  std::vector<realT> m_alpha {0}; ///< The PSD exponent when in non-Kolmogorov mode.
73 
74  std::vector<realT> m_beta_0 {0}; ///< The PSD constant when in non-Kolmogorov mode.
75 
76  std::vector<realT> m_layer_z; ///< Vector of layer heights, in m, above the observatory.
77 
78  realT m_h_obs {0}; ///< Height of the observatory above sea level, in m.
79 
80  realT m_H {8000}; ///< The atmospheric scale height, in m.
81 
82 
83  std::vector<realT> m_layer_v_wind; ///< Vector of layer wind speeds, in m/s.
84 
85  std::vector<realT> m_layer_dir; ///<Vector of layer wind directions, in radians.
86 
87  bool m_v_wind_updated {false}; ///< whether or not m_v_wind has been updated after changes
88 
89  realT m_v_wind; ///< \f$ C_n^2 \f$ averaged windspeed
90 
91  realT m_dir_wind; ///< \f$ C_n^2 \f$ averaged direction
92 
93  bool m_z_mean_updated {false}; ///< whether or not m_z_mean has been updated after changes
94 
95  realT m_z_mean; ///< \f$ C_n^2 \f$ averaged layer height
96 
97 
98 
99 
100  /// Checks if layer vectors have consistent length.
101  /**
102  * \returns 0 if all layer vectors are the same length
103  * \returns -1 if not, and prints an error.
104  */
105  int checkLayers();
106 
107 public:
108 
109  /** \name PSD Parameters
110  * @{
111  */
112 
113  ///Get the value of Fried's parameter r_0 at the reference wavelength lam_0.
114  /**
115  * \returns the curret value of m_r_0, in m.
116  */
118 
119  ///Get the value of Fried's parameter r_0 at the specified wavelength.
120  /**
121  * \note This does not set the value of r_0.
122  *
123  * \returns the current value of m_r_0 * pow(lam, 6/5), in m.
124  */
125  realT r_0( const realT & lam /**< [in] the wavelength, in m, at which to calculate r_0*/ );
126 
127  ///Set the value of Fried's parameter and the reference wavelength.
128  /** If the provided reference wavelength is <=0, then 0.5 microns is used.
129  *
130  */
131  void r_0( const realT & r0, ///< [in] is the new value of r_0, m
132  const realT & l0 ///< [in] is the new value of lam_0 (in m), if 0 then 0.5e-6 is the default.
133  );
134 
135  ///Get the current value of the reference wavelength.
136  /** This is the wavelength at which r_0 is specified.
137  *
138  * \returns the current value of m_lam_0, in m.
139  */
141 
142  ///Get the strength of a single layer.
143  /**
144  * \returns the value of m_layer_Cn2[n].
145  */
146  realT layer_Cn2(const int n /**< [in] specifies the layer. */);
147 
148  ///Get the vector of layer strengths.
149  /**
150  * \returns a copy of the vector of layer strengths: m_layer_Cn2.
151  */
152  std::vector<realT> layer_Cn2();
153 
154  ///Set the vector layer strengths, possibly calculating r_0.
155  /**
156  * If a reference wavelength is specified (l0 > 0), then r_0 is set from the layer strengths
157  * according to
158  *
159  * Regardless of what units the strengths are specified in, they are stored normalized so that
160  * \f$ \sum_n C_n^2 = 1 \f$.
161  *
162  */
163  void layer_Cn2( const std::vector<realT> & cn2, ///< [in] is a vector containing the layer strengths
164  const realT l0 = 0 ///< [in] [optional] if l0 > 0, then r_0 is set from the layer strengths.
165  );
166 
167  ///Get the value of the outer scale for a single layer.
168  /**
169  * \returns the current value of m_L_0[n], in m.
170  */
171  realT L_0( const size_t & n );
172 
173  ///Set the vector of layer outer scales.
174  /**
175  */
176  void L_0( const std::vector<realT> & L0 /**< [in] is the new vector of outer scales, in m */);
177 
178  /// Get the vector of outer scales.
179  /**
180  * \returns a copy of the vector of layer outer scales, in m
181  */
182  std::vector<realT> L_0();
183 
184  ///Get the value of the inner scale for a single layer.
185  /**
186  * \returns the current value of m_l_0[n], in m.
187  */
188  realT l_0( const size_t & n );
189 
190  ///Set the vector of layer inner scales.
191  /**
192  */
193  void l_0( const std::vector<realT> & l0 /**< [in] is the new vector of inner scales, in m*/);
194 
195  /// Get the vector of inner scales.
196  /**
197  * \returns a copy of the vector of layer inner scales, in m
198  */
199  std::vector<realT> l_0();
200 
201  /// Set the value of m_nonKolmogorov
202  /** This flag indicates if non-Kolmogorov turbulence is being modeled.
203  */
204  void nonKolmogorov( const bool & nk /**< [in] the value of m_nonKolmogorov*/);
205 
206  /// Return the value of m_nonKolmogorov
207  /** This flag indicates if non-Kolmogorov turbulence is being modeled.
208  *
209  * \returns the current value of m_nonKolmogorov
210  */
212 
213  ///Return the PSD index for a single layer.
214  /** Satifies the requirements of psdParamsT.
215  *
216  * If m_nonKolmogorov is false, this returns
217  * \[
218  \alpha = \frac{11}{3}
219  \]
220  * Otherwise it returns the current value of m_alpha[n].
221  *
222  * \returns the PSD index.
223  */
224  realT alpha( const size_t & n );
225 
226  ///Set the vector of layer PSD indices.
227  /**
228  */
229  void alpha( const std::vector<realT> & alph /**< [in] is the new vector of PSD indices*/);
230 
231  /// Get the vector of PSD indices.
232  /**
233  * \returns a copy of the vector of PSD indices
234  */
235  std::vector<realT> alpha();
236 
237  ///Return the PSD normalization for a single layer.
238  /** Satifies the requirements of psdParamsT.
239  *
240  * If m_nonKolmogorov is false, this returns
241  * \[
242  \beta = \frac{0.0218}{r_0^{5/3}}
243  \]
244  * Otherwise it returns the current value of m_beta[n].
245  *
246  * \returns the PSD normalization.
247  */
248  realT beta( const size_t & n );
249 
250  ///Set the vector of layer PSD normalizations.
251  /**
252  */
253  void beta( const std::vector<realT> & bet /**< [in] is the new vector of PSD normalizations*/);
254 
255  /// Get the vector of PSD normalizations.
256  /**
257  * \returns a copy of the vector of PSD normalizations
258  */
259  std::vector<realT> beta();
260 
261  ///Return the PSD constant for a single layer.
262  /** Satifies the requirements of psdParamsT.
263  *
264  * If m_nonKolmogorov is false, this returns
265  * \[
266  \beta_0 = 0
267  \]
268  * Otherwise it returns the current value of m_beta_0[n].
269  *
270  * \returns the PSD constant.
271  */
272  realT beta_0( const size_t & n );
273 
274  ///Set the vector of layer PSD constants.
275  /**
276  */
277  void beta_0( const std::vector<realT> & bet /**< [in] is the new vector of PSD constants*/);
278 
279  /// Get the vector of PSD constants.
280  /**
281  * \returns a copy of the vector of PSD constants
282  */
283  std::vector<realT> beta_0();
284 
285  ///Get the number of layers
286  /**
287  * \returns the size of the m_layer_Cn2 vector if m_nonKolmogrov==false
288  * \returns the size of the m_alpha vector if m_nonKolmogrov==true
289  */
290  size_t n_layers();
291 
292  size_t currentLayer();
293 
294  void currentLayer( size_t cl );
295 
296  /// @}
297 
298 
299  ///Get the height of a single layer.
300  /**
301  * \returns the height of layer n, in m.
302  */
303  realT layer_z( const size_t n /**< [in] specifies the layer. */);
304 
305  ///Get the vector layer heights.
306  /**
307  * \returns a copy of the vector of layer heights:m_layer_z, in m.
308  */
309  std::vector<realT> layer_z();
310 
311  ///Set the vector of layer heights.
312  /**
313  */
314  void layer_z(const std::vector<realT> & layz /**< [in] new vector of layer heights, in m. */ );
315 
316  /// Get the height of the observatory.
317  /**
318  * \return the current value of m_h_obs, in m.
319  */
321 
322  /// Set the height of the observatory.
323  /**
324  */
325  void h_obs( realT nh /**< [in] the new height of the observatory [m] */);
326 
327  /// Get the atmospheric scale height.
328  /**
329  * \returns the current value of m_H, in m.
330  */
331  realT H();
332 
333  /// Set the atmospheric scale height.
334  /**
335  */
336  void H( realT nH /**< [in] the new value of m_H [m] */);
337 
338 
339 
340  ///Get the wind speed of a single layer.
341  /**
342  * \returns the value of m_layer_v_wind[n].
343  */
344  realT layer_v_wind(const int n /**< [in] specifies the layer. */);
345 
346  ///Get the vector of layer windspeeds
347  /**
348  * \returns a copy of the vector of layer windspeeds: m_layer_v_wind.
349  */
350  std::vector<realT> layer_v_wind();
351 
352  ///Set the vector of layer windspeeds.
353  /**
354  * \param
355  */
356  void layer_v_wind(const std::vector<realT> & spd /**< [in] the new vector, which is copied to m_layer_v_wind. */);
357 
358  ///Get the wind direction of a single layer.
359  /**
360  * \returns the value of m_layer_dir[n], which is the wind direction in that layer in radians.
361  */
362  realT layer_dir(const int n /**< [in] specifies the layer. */);
363 
364  ///Get the vector of layer wind directions
365  /**
366  * \returns a copy of the vector of layer wind directions: m_layer_dir.
367  */
368  std::vector<realT> layer_dir();
369 
370  ///Set the vector of layer wind directions.
371  /**
372  * \param
373  */
374  void layer_dir(const std::vector<realT> & d /**< [in] the new vector of wind directions in radians, which is copied to m_layer_dir. */);
375 
376 
377  ///Get the 5/3 moment weighted mean wind speed
378  /** Returns the weighted mean wind speed according to the 5/3's turbulence moment. This is defined as
379  *
380  \f[
381  \bar{v} = \left[\sum_i C_N^2(z_i) v_i^{5/3} \right]^{3/5}
382  \f]
383  * See Hardy (1998) Section 3.3.6. \cite hardy_1998.
384  *
385  * This is only re-calculated if either m_layer_Cn2 or m_layer_v_wind is changed, otherwise this just
386  * returns the value of m_v_wind.
387  *
388  * \returns the current value of m_v_wind.
389  */
391 
392  /// Get the mean wind speed
393  /** Returns the weighted mean wind speed according to the 5/3's turbulence moment. This is defined as
394  *
395  \f[
396  \bar{v} = \sum_i C_N^2(z_i) v_i
397  \f]
398  * See Hardy (1998) Section 3.3.6. \cite hardy_1998.
399  *
400  * This is only re-calculated if either m_layer_Cn2 or m_layer_v_wind is changed, otherwise this just
401  * returns the value of m_v_wind.
402  *
403  * \returns the current value of m_v_wind.
404  */
406 
407  /// Get the mean-squared wind speed
409 
410  realT v_max()
411  {
412  auto max = std::max_element(std::begin(m_layer_v_wind), std::end(m_layer_v_wind));
413 
414  return *max;
415  }
416 
417  ///Get the weighted mean wind direction
418  /** Returns the weighted mean wind direction according to the 5/3's turbulence moment. This is defined as
419  *
420  \f[
421  \bar{\theta} = \left[\sum_i C_N^2(z_i) \theta_i^{5/3} \right]^{3/5}
422  \f]
423  * See Hardy (1998) Section 3.3.6. \cite hardy_1998.
424  *
425  * This is only re-calculated if either m_layer_Cn2 or m_layer_v_wind is changed, otherwise this just
426  * returns the value of m_dir_wind.
427  *
428  * \returns the current value of m_dir_wind.
429  */
431 
432 protected:
433  ///Recalculate m_v_wind
434  /** Called by v_wind() whenever m_v_wind_updated is true.
435  *
436  * \todo handle dir_wind averaging across 0/2pi
437  */
439 
440 public:
441  ///Set the weighted mean m_v_wind and renormalize the layer wind speeds
442  /** Calling this function changes the values of m_layer_v_wind so that the
443  * Layer averaged 5/3 \f$C_n^2\f$ moment of wind speed is the new value specified by vw.
444  *
445  */
446  void v_wind(const realT & vw /**< [in] the new value of m_v_wind. */);
447 
448 
449  ///Get the weighted mean layer height
450  /** Returns the weighted layer height according to the 5/3's turbulence moment. This is defined as
451  \f[
452  \bar{z} = \left[\sum_i C_N^2(z_i) z_i^{5/3} \right]^{3/5}
453  \f]
454  * See Hardy (1998) Section 3.3.6 and 3.7.2. \cite hardy_1998.
455  *
456  * This is only re-calculated if either m_layer_Cn2 orm_layer_z is changed, otherwise this just
457  * returns the value of m_z_mean.
458  *
459  * \returns the current value of m_z_mean.
460  */
462 
463 protected:
464  ///Recalculate m_z_mean
465  /** Called by z_mean() whenever m_z_mean_updated is true.
466  */
468 
469 public:
470  ///Set the weighted mean m_z_mean and renormalize the layer heights
471  /** Calling this function changes the values ofm_layer_z so that the
472  * Layer averaged 5/3 \f$C_n^2\f$ moment of the height is the new value specified.
473  *
474  */
475  void z_mean(const realT & zm /**< [in] is the new value of m_v_wind. */);
476 
477 
478 
479  ///The fraction of the turbulence PSD in phase after Fresnel propagation.
480  /** See Equation (14) of Guyon (2005) \cite guyon_2005.
481  *
482  * \returns the value of the X function.
483  */
484  realT X( realT k, ///< [in] the spatial frequency, in inverse meters.
485  realT lam_sci, ///< [in] is the science observation wavelength.
486  realT secZ ///< [in] is the secant of the zenith distance.
487  );
488 
489  ///The differential fraction of the turbulence PSD in phase after Fresnel propagation.
490  /** See Equation (25) of Guyon (2005) \cite guyon_2005.
491  *
492  * \returns the value of the dX function.
493  */
494  realT dX( realT k, ///< [in] the spatial frequency, in inverse meters.
495  realT lam_sci, ///< [in] is the science observation wavelength.
496  realT lam_wfs ///< [in] is the wavefront sensor wavelength.
497  );
498 
499  ///The fraction of the turbulence PSD in amplitude after Fresnel propagation.
500  /** See Equation (15) of Guyon (2005) \cite guyon_2005.
501  *
502  * \returns the value of the Y function.
503  */
504  realT Y( realT k, ///< [in] the spatial frequency, in inverse meters.
505  realT lam_sci, ///< [in] is the science observation wavelength.
506  realT secZ ///< [in] is the secant of the zenith distance.
507  );
508 
509  ///The differential fraction of the turbulence PSD in amplitude after Fresnel propagation.
510  /** See Equation (27) of Guyon (2005) \cite guyon_2005.
511  *
512  * \returns the value of the dY function.
513  */
514  realT dY( realT k, ///< [in] the spatial frequency, in inverse meters.
515  realT lam_sci, ///< [in] is the science observation wavelength.
516  realT lam_wfs ///< [in] is the wavefront sensor wavelength.
517  );
518 
519 
520  realT n_air( realT lam /**< [in]The wavelength*/);
521 
522  realT X_Z( realT k, ///< [in] the spatial frequency, in inverse meters
523  realT lambda_sci, ///< [in] is the science observation wavelength.
524  realT lambda_wfs, ///< [in] is the wavefront sensor wavelength.
525  realT secZ ///< [in] is the secant of the zenith distance.
526  );
527 
528  ///Calculate the full-width at half-maximum of a seeing limited image for this atmosphere for a small telescope (ignoring L_0)
529  /** Calculate the FWHM of a seeing limited image with the current parameters according to Floyd et al. (2010) \cite floyd_2010
530  \f[
531  \epsilon_0 = 0.98\frac{\lambda_{sci}}{r_0(\lambda_sci)}.
532  \f]
533  *
534  * \returns the value of the FWHM for the current atmosphere parameters.
535  */
536  realT fwhm0(realT lam_sci /**< [in] the wavelength of the science observation. */ );
537 
538  ///Calculate the full-width at half-maximum of a seeing limited image for this atmosphere for a large telescope (including L_0)
539  /** Calculate the FWHM of a seeing limited image with the current parameters according to Floyd et al. (2010) \cite floyd_2010
540  \f[
541  \epsilon_0 = 0.98\frac{\lambda_{sci}}{r_0(\lambda_sci)}.
542  \f]
543  * If there is an outer scale (_L_0 > 0), then a correction is applied according to Tokovinin (2002) \cite tokovinin_2002
544  \f[
545  \left( \frac{\epsilon_{vK}}{\epsilon_0}\right)^2 = 1 - 2.183\left( \frac{r_0(\lambda_{sci}}{L_0}\right)^{0.356}
546  \f]
547  *
548  *
549  * \returns the value of the FWHM (\f$ \epsilon_{0/vK} \f$) for the current atmosphere parameters.
550  */
551  realT fwhm(realT lam_sci /**< [in] the wavelength of the science observation. */ );
552 
553  ///Get the greenwood frequency at the reference wavelength
554  /**
555  * \todo derive full value of the constant
556  */
558 
559  ///Get the greenwood frequency at a specified wavelength
560  /**
561  *
562  */
563  realT f_g(realT lam_sci /**< [in] the wavelength of the science observation. */);
564 
565  ///Get tau_0 at the reference wavelength
566  /**
567  * \todo derive full value of the constant
568  */
570 
571  ///Get tau_0 at a specified wavelength.
572  /**
573  *
574  */
575  realT tau_0(realT lam_sci /**< [in] the wavelength of the science observation. */);
576 
577  /// Scale v_wind so that tau_0 has the specified value at the specified wavelength.
578  /** Does not modify r_0.
579  */
580  void tau_0( realT tau_0, ///< [in] the desired tau_0
581  realT lam_sci ///< [in] the wavelength of the science observation.
582  );
583 
584  ///Load the default atmosphere model from Guyon (2005).
585  /** Sets the parameters from Table 4 of Guyon (2005) \cite guyon_2005.
586  */
588 
589  ///Load parameters corresponding to the median atmosphere of the GMT site survey at LCO.
590  /**
591  */
592  void loadLCO();
593 
594 
595  /// Set a single layer model.
596  /** Sets all layer vectors to size=1 and populates their fields based on these arguments.
597  *
598  */
599  void setSingleLayer( realT r0, ///< [in] is the new value of r_0
600  realT lam0, ///< [in] is the new value of lam_0, if 0 then 0.5 microns is the default.
601  realT L0, ///< [in] the new outer scale
602  realT l0, ///< [in] the new inner scale
603  realT lz, ///< [in] the layer height
604  realT vw, ///< [in] the layer wind-speed
605  realT dir ///< [in] the layer wind direction.
606  );
607 
608  ///Output current parameters to a stream
609  /** Prints a formatted list of all current parameters.
610  *
611  * \tparam iosT is a std::ostream-like type.
612  *
613  * \todo update for new vector components (L_0, etc.)
614  */
615  template<typename iosT>
616  iosT & dumpAtmosphere( iosT & ios /**< [in] a std::ostream-like stream. */);
617 
618  /// \name mx::application support
619  /** @{
620  */
621 
622  /// Setup the configurator to configure this class
623  /**
624  * \test Loading aoAtmosphere config settings \ref tests_ao_analysis_aoAtmosphere_config "[test doc]"
625  */
626  void setupConfig( app::appConfigurator & config /**< [in] the app::configurator object*/);
627 
628  /// Load the configuration of this class from a configurator
629  /**
630  * \test Loading aoAtmosphere config settings \ref tests_ao_analysis_aoAtmosphere_config "[test doc]"
631  */
632  void loadConfig( app::appConfigurator & config /**< [in] the app::configurator object*/);
633 
634 
635  /// @}
636 };
637 
638 template<typename realT>
640 {
641 }
642 
643 template<typename realT>
645 {
646  size_t n = m_L_0.size();
647 
648  if( m_l_0.size() != n)
649  {
650  mxError("aoAtmosphere", MXE_SIZEERR, "mismatched layer numbers (inner scale vs. outer scale)");
651  return -1;
652  }
653 
654  if( m_layer_z.size() != n)
655  {
656  mxError("aoAtmosphere", MXE_SIZEERR, "mismatched layer numbers (layer_z vs. outer scale)");
657  return -1;
658  }
659 
660  if( m_layer_Cn2.size() != n)
661  {
662  mxError("aoAtmosphere", MXE_SIZEERR, "mismatched layer numbers (layer_Cn2 vs. outer scale)");
663  return -1;
664  }
665 
666  if( m_layer_dir.size() != n)
667  {
668  mxError("aoAtmosphere", MXE_SIZEERR, "mismatched layer numbers (layer_dir vs. outer scale)");
669  return -1;
670  }
671 
672  if( m_layer_v_wind.size() != n)
673  {
674  mxError("aoAtmosphere", MXE_SIZEERR, "mismatched layer numbers (layer_v_wind vs. outer scale)");
675  return -1;
676  }
677 
678 
679  return 0;
680 }
681 
682 template<typename realT>
684 {
685  return m_r_0;
686 }
687 
688 template<typename realT>
690 {
691  return m_r_0*pow(lam/m_lam_0, math::six_fifths<realT>());
692 }
693 
694 template<typename realT>
695 void aoAtmosphere<realT>::r_0(const realT & r0, const realT & l0)
696 {
697  m_r_0 = r0;
698 
699  if( l0 > 0)
700  {
701  m_lam_0 = l0;
702  }
703  else
704  {
705  m_lam_0 = 0.5e-6;
706  }
707 }
708 
709 template<typename realT>
711 {
712  return m_lam_0;
713 }
714 
715 template<typename realT>
717 {
718  return m_layer_Cn2[n];
719 }
720 
721 template<typename realT>
722 std::vector<realT> aoAtmosphere<realT>::layer_Cn2()
723 {
724  return m_layer_Cn2;
725 }
726 
727 template<typename realT>
728 void aoAtmosphere<realT>::layer_Cn2(const std::vector<realT> & cn2, const realT l0)
729 {
730  m_layer_Cn2 = cn2;
731 
732  realT layer_norm = 0;
733 
734  for(size_t i=0;i < m_layer_Cn2.size();++i)
735  {
736  layer_norm += cn2[i];
737  }
738 
739  for(size_t i=0;i< m_layer_Cn2.size();++i) m_layer_Cn2[i] = m_layer_Cn2[i]/layer_norm;
740 
741  if(l0 > 0)
742  {
743  m_r_0 = 1.0 / pow(layer_norm * 5.520e13, math::three_fifths<realT>() );
744  m_lam_0 = l0;
745  }
746 
747  m_v_wind_updated = false;
748  m_z_mean_updated = false;
749 }
750 
751 template<typename realT>
753 {
754  return m_L_0[n];
755 }
756 
757 template<typename realT>
758 void aoAtmosphere<realT>::L_0(const std::vector<realT> & L_0)
759 {
760  m_L_0 = L_0;
761 }
762 
763 template<typename realT>
764 std::vector<realT> aoAtmosphere<realT>::L_0()
765 {
766  return m_L_0;
767 }
768 
769 template<typename realT>
771 {
772  return m_l_0[n];
773 }
774 
775 template<typename realT>
776 void aoAtmosphere<realT>::l_0(const std::vector<realT> & l_0)
777 {
778  m_l_0 = l_0;
779 }
780 
781 template<typename realT>
782 std::vector<realT> aoAtmosphere<realT>::l_0()
783 {
784  return m_l_0;
785 }
786 
787 template<typename realT>
788 void aoAtmosphere<realT>::nonKolmogorov( const bool & nk )
789 {
790  m_nonKolmogorov = nk;
791 }
792 
793 template<typename realT>
795 {
796  return m_nonKolmogorov;
797 }
798 
799 template<typename realT>
801 {
802  if(!m_nonKolmogorov)
803  {
804  return math::eleven_thirds<realT>();
805  }
806  else
807  {
808  return m_alpha[n];
809  }
810 }
811 
812 template<typename realT>
813 void aoAtmosphere<realT>::alpha(const std::vector<realT> & alph)
814 {
815  m_nonKolmogorov = true;
816  m_alpha = alph;
817 }
818 
819 template<typename realT>
820 std::vector<realT> aoAtmosphere<realT>::alpha()
821 {
822  return m_alpha;
823 }
824 
825 template<typename realT>
827 {
828  if(!m_nonKolmogorov)
829  {
830  return constants::a_PSD<realT>()*pow(m_r_0, -math::five_thirds<realT>());;
831  }
832  else
833  {
834  return m_beta[n];
835  }
836 }
837 
838 template<typename realT>
839 void aoAtmosphere<realT>::beta(const std::vector<realT> & bet)
840 {
841  m_nonKolmogorov = true;
842  m_beta = bet;
843 }
844 
845 template<typename realT>
846 std::vector<realT> aoAtmosphere<realT>::beta()
847 {
848  return m_beta;
849 }
850 
851 template<typename realT>
853 {
854  if(!m_nonKolmogorov)
855  {
856  return 0;
857  }
858  else
859  {
860  return m_beta_0[n];
861  }
862 }
863 
864 template<typename realT>
865 void aoAtmosphere<realT>::beta_0(const std::vector<realT> & bet)
866 {
867  m_nonKolmogorov = true;
868  m_beta_0 = bet;
869 }
870 
871 template<typename realT>
872 std::vector<realT> aoAtmosphere<realT>::beta_0()
873 {
874  return m_beta_0;
875 }
876 
877 template<typename realT>
879 {
880  if(m_nonKolmogorov) return m_alpha.size();
881  else return m_layer_Cn2.size();
882 }
883 
884 template<typename realT>
886 {
887  return m_layer_z[n];
888 }
889 
890 template<typename realT>
891 void aoAtmosphere<realT>::layer_z(const std::vector<realT> & z)
892 {
893  m_layer_z = z;
894  m_z_mean_updated = false;
895 }
896 
897 template<typename realT>
898 std::vector<realT> aoAtmosphere<realT>::layer_z()
899 {
900  return m_layer_z;
901 }
902 
903 template<typename realT>
905 {
906  return m_h_obs;
907 }
908 
909 template<typename realT>
911 {
912  m_h_obs = nh;
913 }
914 
915 template<typename realT>
917 {
918  return m_H;
919 }
920 
921 template<typename realT>
923 {
924  m_H = nH;
925 }
926 
927 template<typename realT>
929 {
930  return m_layer_v_wind[n];
931 }
932 
933 template<typename realT>
935 {
936  return m_layer_v_wind;
937 }
938 
939 template<typename realT>
940 void aoAtmosphere<realT>::layer_v_wind(const std::vector<realT> & v)
941 {
942  m_layer_v_wind = v;
943  m_v_wind_updated = false;
944 }
945 
946 template<typename realT>
948 {
949  return m_layer_dir[n];
950 }
951 
952 template<typename realT>
953 std::vector<realT> aoAtmosphere<realT>::layer_dir()
954 {
955  return m_layer_dir;
956 }
957 
958 template<typename realT>
959 void aoAtmosphere<realT>::layer_dir(const std::vector<realT> & dir)
960 {
961  m_layer_dir = dir;
962  m_v_wind_updated = false;
963 }
964 
965 
966 template<typename realT>
968 {
969  if(m_v_wind_updated == false) update_v_wind();
970  return m_v_wind;
971 }
972 
973 template<typename realT>
975 {
976  if(m_v_wind_updated == false) update_v_wind();
977  return m_dir_wind;
978 }
979 
980 template<typename realT>
982 {
983 
984  if( m_layer_v_wind.size() == 0 || m_layer_Cn2.size() == 0)
985  {
986  m_v_wind = 0;
987  m_dir_wind = 0;
988  m_v_wind_updated = true;
989  return;
990  }
991 
992  m_v_wind = 0;
993 
994  realT s = 0;
995  realT c = 0;
996 
997  for(size_t i=0;i<m_layer_Cn2.size(); ++i)
998  {
999  m_v_wind += m_layer_Cn2[i] * pow(m_layer_v_wind[i], math::five_thirds<realT>() );
1000  s += pow(m_layer_v_wind[i], math::five_thirds<realT>())*sin(m_layer_dir[i]) ;//pow( sin(m_layer_dir[i]), math::five_thirds<realT>() );
1001  c += pow(m_layer_v_wind[i], math::five_thirds<realT>())*cos(m_layer_dir[i]) ;//pow( cos(m_layer_dir[i]), math::five_thirds<realT>() );
1002  }
1003 
1004  m_v_wind = pow(m_v_wind, math::three_fifths<realT>());
1005 
1006  //m_dir_wind = atan(pow(s, math::three_fifths<realT>()) / pow(c, math::three_fifths<realT>()));
1007  m_dir_wind = atan( s / c);
1008  if(m_dir_wind < 0) m_dir_wind += math::pi<realT>();
1009 
1010  m_v_wind_updated = true;
1011 
1012 }
1013 
1014 template<typename realT>
1016 {
1017  if(m_v_wind_updated == false) update_v_wind();
1018 
1019  realT vw_old = m_v_wind;
1020 
1021  m_v_wind = vw;
1022 
1023  //Now update the layers if needed
1024  if( m_layer_v_wind.size() > 0)
1025  {
1026  for(size_t i=0; i< m_layer_v_wind.size(); ++i)
1027  {
1028  m_layer_v_wind[i] = m_layer_v_wind[i]*(vw/vw_old);
1029  }
1030  }
1031 }
1032 
1033 template<typename realT>
1035 {
1036  if(m_z_mean_updated == false) update_z_mean();
1037  return m_z_mean;
1038 }
1039 
1040 template<typename realT>
1042 {
1043  if(m_layer_z.size() == 0 || m_layer_Cn2.size() == 0)
1044  {
1045  m_z_mean = 0;
1046  m_z_mean_updated = true;
1047  return;
1048  }
1049 
1050  m_z_mean = 0;
1051 
1052  for(size_t i=0;i<m_layer_Cn2.size(); ++i)
1053  {
1054  m_z_mean += m_layer_Cn2[i] * pow(m_layer_z[i], math::five_thirds<realT>() );
1055  }
1056 
1057  m_z_mean = pow(m_z_mean, math::three_fifths<realT>());
1058 
1059  m_z_mean_updated = true;
1060 
1061 }
1062 
1063 template<typename realT>
1065 {
1066  if(m_z_mean_updated == false) update_z_mean();
1067 
1068  realT zh_old = m_z_mean;
1069 
1070  m_z_mean = zm;
1071 
1072  //Now update the layers if needed
1073  if(m_layer_z.size() > 0)
1074  {
1075  for(size_t i=0; i<m_layer_z.size(); ++i)
1076  {
1077  m_layer_z[i] =m_layer_z[i]*(zm/zh_old);
1078  }
1079  }
1080 }
1081 
1082 
1083 
1084 
1085 
1086 
1087 template<typename realT>
1089  realT lam_sci,
1090  realT secZ)
1091 {
1092  realT c = 0;
1093 
1094  for(size_t i=0;i<m_layer_Cn2.size(); ++i)
1095  {
1096  c += m_layer_Cn2[i] * pow( cos(math::pi<realT>()*k*k*lam_sci *m_layer_z[i] * secZ), 2);
1097  }
1098 
1099  return c;
1100 }
1101 
1102 template<typename realT>
1104 {
1105  realT c = 0;
1106 
1107  for(size_t i=0;i<m_layer_Cn2.size(); ++i)
1108  {
1109  c += m_layer_Cn2[i]* pow((cos( math::pi<realT>()*f*f*lam_sci *m_layer_z[i]) - cos( math::pi<realT>()*f*f*lam_wfs *m_layer_z[i])), 2);
1110  }
1111 
1112  return c;
1113 }
1114 
1115 template<typename realT>
1117  realT lam_sci,
1118  realT secZ
1119  )
1120 {
1121  realT c = 0;
1122 
1123  for(size_t i=0;i<m_layer_Cn2.size(); ++i)
1124  {
1125  c += m_layer_Cn2[i]*pow(sin( math::pi<realT>()*k*k*lam_sci *m_layer_z[i] * secZ), 2);
1126  }
1127  return c;
1128 }
1129 
1130 template<typename realT>
1132 {
1133  realT c = 0;
1134 
1135  for(size_t i=0;i<m_layer_Cn2.size(); ++i)
1136  {
1137  c += m_layer_Cn2[i]*pow( (sin(math::pi<realT>()*f*f*lam_sci *m_layer_z[i]) - sin( math::pi<realT>()*f*f*lam_wfs *m_layer_z[i])), 2);
1138  }
1139 
1140  return c;
1141 }
1142 
1143 template<typename realT>
1145 {
1146  realT ll2 = static_cast<realT>(1)/pow(lambda/1e-6, 2);
1147 
1148  return 1.0 + 8.34213e-5 + 0.0240603/(130.0 - ll2) + 0.00015997/(38.9 - ll2);
1149 }
1150 
1151 template<typename realT>
1152 realT aoAtmosphere<realT>::X_Z(realT k, realT lambda_i, realT lambda_wfs, realT secZ)
1153 {
1154  realT c = 0;
1155  realT sinZ = sqrt(1.0 - pow(1.0/secZ,2));
1156  realT tanZ = sinZ*secZ;
1157  realT x0 = (n_air(lambda_wfs) - n_air(lambda_i)) * m_H*tanZ*secZ;
1158  realT x;
1159 
1160  for(size_t i = 0; i < m_layer_Cn2.size(); ++i)
1161  {
1162  x = x0*(1-exp((m_layer_z[i]+m_h_obs)/m_H));
1163  c += m_layer_Cn2[i] * pow( cos(math::pi<realT>()*k*k*lambda_i *m_layer_z[i]*secZ), 2) * pow( sin(math::pi<realT>()*x*k*cos(0.*3.14/180.)), 2);
1164  }
1165 
1166  return 4*c;
1167 }
1168 
1169 template<typename realT>
1171 {
1172  realT r0lam = r_0(lam_sci);
1173 
1174  realT fwhm = 0.98*(lam_sci/r0lam);
1175 
1176  return fwhm;
1177 }
1178 
1179 
1180 template<typename realT>
1182 {
1183  realT r0lam = r_0(lam_sci);
1184 
1185  realT fwhm = 0.98*(lam_sci/r0lam);
1186 
1187  ///\todo this needs to handle layers with different L_0
1188  if( L_0(0) > 0) fwhm *= sqrt( 1 - 2.183*pow(r0lam/L_0(0), 0.356));
1189 
1190  return fwhm;
1191 }
1192 
1193 template<typename realT>
1195 {
1196  return 0.428*v_wind()/m_r_0;
1197 }
1198 
1199 template<typename realT>
1201 {
1202  return 0.428*pow(m_lam_0/lam_sci, math::six_fifths<realT>())*v_wind()/m_r_0;
1203 }
1204 
1205 template<typename realT>
1207 {
1208  return 0.134/f_g();
1209 }
1210 
1211 template<typename realT>
1213 {
1214  return 0.134/f_g(lam_sci);
1215 }
1216 
1217 template<typename realT>
1219  realT lam_sci
1220  )
1221 {
1222  realT vw = (0.134/tau_0) / 0.428 * m_r_0* pow(lam_sci/m_lam_0, math::six_fifths<realT>());
1223  v_wind(vw);
1224 }
1225 
1226 template<typename realT>
1228 {
1229  layer_Cn2({0.2283, 0.0883, 0.0666, 0.1458, 0.3350, 0.1350});
1230  layer_z({500, 1000, 2000, 4000, 8000, 16000});
1231  layer_v_wind({10., 10., 10., 10., 10., 10.});
1232  layer_dir({0.0, 0.0, 0.0, 0.0, 0.0, 0.0});
1233 
1234  r_0(0.2, 0.5e-6);
1235 
1236  h_obs(4200);
1237 }
1238 
1239 template<typename realT>
1241 {
1242  layer_Cn2( {0.42, 0.029, 0.062, 0.16, 0.11, 0.10, 0.12});
1243  layer_z( {250., 500., 1000., 2000., 4000., 8000., 16000. });
1244  layer_v_wind( {10.0, 10.0, 20.0, 20.0, 25.0, 30.0, 25.0});
1245  layer_dir( {1.05, 1.05, 1.31, 1.31, 1.75, 1.92, 1.75});
1246 
1247  r_0(0.17, 0.5e-6);
1248 
1249  L_0({25.0,25.0,25.0,25.0, 25.0, 25.0, 25.0});
1250  l_0({0.0,0,0,0,0,0,0});
1251 
1252  h_obs(2400);
1253 }
1254 
1255 template<typename realT>
1257  realT lam0,
1258  realT L0,
1259  realT l0,
1260  realT lz,
1261  realT vw,
1262  realT dir
1263  )
1264 {
1265  r_0(r0, lam0);
1266  L_0(std::vector<realT>({L0}));
1267  l_0(std::vector<realT>({l0}));
1268  layer_Cn2(std::vector<realT>({1}));
1269  layer_z(std::vector<realT>({lz}));
1270  layer_v_wind(std::vector<realT>({vw}));
1271  layer_dir(std::vector<realT>({dir}));
1272 }
1273 
1274 template<typename realT>
1275 template<typename iosT>
1277 {
1278  ios << "# Atmosphere Parameters:\n";
1279  ios << "# nonKolmogorov = " << std::boolalpha << nonKolmogorov() << '\n';
1280  ios << "# n_layers = " << n_layers() << '\n';
1281 
1282  if(!m_nonKolmogorov)
1283  {
1284  ios << "# r_0 = " << r_0() << '\n';
1285  ios << "# lam_0 = " << lam_0() << '\n';
1286  ios << "# tau_0 = " << tau_0(lam_0()) << '\n';
1287  ios << "# FWHM = " << fwhm(lam_0()) << '\n';
1288  ios << "# layer_Cn2 = ";
1289  for(size_t i=0;i< n_layers()-1;++i) ios << layer_Cn2()[i] << ", ";
1290  ios << layer_Cn2()[n_layers()-1] << '\n';
1291  }
1292  if(m_nonKolmogorov)
1293  {
1294  ios << "# alpha = ";
1295  for(size_t i=0;i < n_layers()-1;++i) ios << alpha()[i] << ", ";
1296  ios << alpha()[n_layers()-1] << '\n';
1297  ios << "# beta = ";
1298  for(size_t i=0;i < n_layers()-1;++i) ios << beta()[i] << ", ";
1299  ios << beta()[n_layers()-1] << '\n';
1300  ios << "# beta_0 = ";
1301  for(size_t i=0;i < n_layers()-1;++i) ios << beta_0()[i] << ", ";
1302  ios << beta_0()[n_layers()-1] << '\n';
1303  }
1304 
1305  ios << "# L_0 = ";
1306  for(size_t i=0;i < n_layers()-1;++i) ios << L_0()[i] << ", ";
1307  ios << L_0()[n_layers()-1] << '\n';
1308  ios << "# l_0 = ";
1309  for(size_t i=0;i < n_layers()-1;++i) ios << l_0()[i] << ", ";
1310  ios << l_0()[n_layers()-1] << '\n';
1311 
1312  ios << "# layer_v_wind = ";
1313  for(size_t i=0;i< n_layers()-1;++i) ios << layer_v_wind()[i] << ", ";
1314  ios << layer_v_wind()[ n_layers()-1] << '\n';
1315  ios << "# layer_dir = ";
1316  for(size_t i=0;i< n_layers()-1;++i) ios << layer_dir()[i] << ", ";
1317  ios << layer_dir()[ n_layers()-1] << '\n';
1318  ios << "# mean v_wind = " << v_wind() << '\n';
1319  ios << "# mean dir_wind = " << dir_wind() << '\n';
1320 
1321  if(!m_nonKolmogorov)
1322  {
1323  ios << "# layer_z = ";
1324  for(size_t i=0;i < n_layers()-1;++i) ios << layer_z()[i] << ", ";
1325  ios << layer_z()[ n_layers()-1] << '\n';
1326  ios << "# mean z = " << z_mean() << '\n';
1327  ios << "# h_obs = " << h_obs() << '\n';
1328  ios << "# H = " << H() << '\n';
1329  }
1330 
1331  return ios;
1332 }
1333 
1334 template<typename realT>
1336 {
1337  using namespace mx::app;
1338 
1339  config.add("atm.r_0" ,"", "atm.r_0" , argType::Required, "atm", "r_0", false, "real" , "Fried's parameter [m]");
1340  config.add("atm.lam_0" ,"", "atm.lam_0" , argType::Required, "atm", "lam_0", false, "real" , "The reference wavlength for r_0 [m]");
1341  config.add("atm.L_0" ,"", "atm.L_0" , argType::Required, "atm", "L_0", false, "vector<real>", "Layer outer scales [m]");
1342  config.add("atm.l_0" ,"", "atm.l_0" , argType::Required, "atm", "l_0", false, "vector<real>", "Layer inner scales [m]");
1343  config.add("atm.layer_z" ,"", "atm.layer_z" , argType::Required, "atm", "layer_z", false, "vector<real>", "layer heights [m]");
1344  config.add("atm.h_obs" ,"", "atm.h_obs" , argType::Required, "atm", "h_obs", false, "real" , "height of observatory [m]");
1345  config.add("atm.H" ,"", "atm.H" , argType::Required, "atm", "H", false, "real" , "atmospheric scale heights [m]");
1346  config.add("atm.layer_Cn2" ,"", "atm.layer_Cn2" , argType::Required, "atm", "layer_Cn2", false, "vector<real>", "Layer Cn^2. Note that this does not set r_0.");
1347  config.add("atm.layer_v_wind" ,"", "atm.layer_v_wind" , argType::Required, "atm", "layer_v_wind", false, "vector<real>", "Layer wind speeds [m/s]");
1348  config.add("atm.layer_dir" ,"", "atm.layer_dir" , argType::Required, "atm", "layer_dir", false, "vector<real>", "Layer wind directions [rad]");
1349  config.add("atm.v_wind" ,"", "atm.v_wind" , argType::Required, "atm", "v_wind", false, "real" , "Mean windspeed (5/3 momement), rescales layers [m/s]");
1350  config.add("atm.z_mean" ,"", "atm.z_mean" , argType::Required, "atm", "z_mean", false, "real" , "Mean layer height (5/3 momemnt), rescales layers [m/s]");
1351  config.add("atm.nonKolmogorov","", "atm.nonKolmogorov", argType::Required, "atm", "nonKolmogorov", false, "bool" , "Set to use a non-Kolmogorov PSD. See alpha and beta.");
1352  config.add("atm.alpha" ,"", "atm.alpha" , argType::Required, "atm", "alpha" , false, "vector<real>", "Non-kolmogorov PSD exponent.");
1353  config.add("atm.beta" ,"", "atm.beta" , argType::Required, "atm", "beta" , false, "vector<real>", "Non-kolmogorov PSD normalization.");
1354  config.add("atm.beta_0" ,"", "atm.beta_0" , argType::Required, "atm", "beta_0" , false, "vector<real>", "Non-kolmogorov PSD constant.");
1355 }
1356 
1357 template<typename realT>
1359 {
1360  //Here "has side effecs" means that the set function does more than simply copy the value.
1361 
1362  //The order of lam_0, Cn2, and r_0 is so that r_0 overrides the value set with Cn2 if lam_0 != 0.
1363  //lam_0 comes first because it calibrates r0 and Cn2
1364 
1365  //lam_0
1366  config(m_lam_0, "atm.lam_0");
1367 
1368  //layer_Cn2
1369  std::vector<realT> lcn2 = m_layer_Cn2;
1370  config(lcn2, "atm.layer_Cn2");
1371  if(config.isSet("atm.layer_Cn2")) layer_Cn2(lcn2);
1372 
1373  realT r0 = r_0();
1374  config(r0, "atm.r_0");
1375  if(config.isSet("atm.r_0")) r_0(r0, m_lam_0);
1376 
1377  config(m_L_0, "atm.L_0");
1378 
1379  config(m_l_0, "atm.l_0");
1380 
1381  //Has side effects:
1382  std::vector<realT> layz = m_layer_z;
1383  config(layz, "atm.layer_z"); //Do this no matter what to record source
1384  if(config.isSet("atm.layer_z")) layer_z(layz); //but only call this if changed
1385 
1386  config(m_h_obs, "atm.h_obs");
1387  config(m_H, "atm.H");
1388 
1389  //Has side effects:
1390  std::vector<realT> lvw = m_layer_v_wind;
1391  config(lvw, "atm.layer_v_wind"); //Do this no matter what to record source
1392  if(config.isSet("atm.layer_v_wind")) layer_v_wind(lvw); //but only call this if changed
1393 
1394  //Has side effects:
1395  std::vector<realT> ld = m_layer_dir;
1396  config(ld, "atm.layer_dir"); //Do this no matter what to record source
1397  if(config.isSet("atm.layer_dir")) layer_dir(ld); //but only call this if changed
1398 
1399  realT vw = m_v_wind;
1400  config(vw,"atm.v_wind"); //Do this no matter what to record source
1401  if(config.isSet("atm.v_wind")) v_wind(vw); //but only call this if changed
1402 
1403  realT zm = m_z_mean;
1404  config(zm,"atm.z_mean"); //Do this no matter what to record source
1405  if(config.isSet("atm.z_mean")) z_mean(zm); //but only call this if changed
1406 
1407  config(m_nonKolmogorov, "atm.nonKolmogorov");
1408 
1409  std::vector<realT> a = m_alpha;
1410  config(a, "atm.alpha");
1411  if(config.isSet("atm.alpha")) alpha(a); //this sets m_nonKolmogorov
1412 
1413  std::vector<realT> b = m_beta;
1414  config(b, "atm.beta");
1415  if(config.isSet("atm.beta")) beta(b); //this sets m_nonKolmogorov
1416 
1417  std::vector<realT> b0 = m_beta_0;
1418  config(b0, "atm.beta_0");
1419  if(config.isSet("atm.beta_0")) beta_0(b0); //this sets m_nonKolmogorov
1420 
1421 }
1422 
1423 
1424 extern template
1425 class aoAtmosphere<float>;
1426 
1427 extern template
1428 class aoAtmosphere<double>;
1429 
1430 extern template
1432 
1433 #ifdef HASQUAD
1434 extern template
1436 #endif
1437 
1438 }//namespace analysis
1439 }//namespace AO
1440 }//namespace mx
1441 
1442 #endif //aoAtmosphere_hpp
Calculate and provide constants related to adaptive optics.
A class to specify atmosphere parameters and perform related calculations.
void beta(const std::vector< realT > &bet)
Set the vector of layer PSD normalizations.
std::vector< realT > m_beta_0
The PSD constant when in non-Kolmogorov mode.
realT r_0(const realT &lam)
Get the value of Fried's parameter r_0 at the specified wavelength.
realT dir_wind()
Get the weighted mean wind direction.
std::vector< realT > alpha()
Get the vector of PSD indices.
realT lam_0()
Get the current value of the reference wavelength.
std::vector< realT > l_0()
Get the vector of inner scales.
void loadLCO()
Load parameters corresponding to the median atmosphere of the GMT site survey at LCO.
void layer_z(const std::vector< realT > &layz)
Set the vector of layer heights.
std::vector< realT > layer_v_wind()
Get the vector of layer windspeeds.
realT v_wind_mean2()
Get the mean-squared wind speed.
realT X(realT k, realT lam_sci, realT secZ)
The fraction of the turbulence PSD in phase after Fresnel propagation.
std::vector< realT > m_beta
The PSD normalization when in non-Kolmogorov mode.
iosT & dumpAtmosphere(iosT &ios)
Output current parameters to a stream.
realT h_obs()
Get the height of the observatory.
realT l_0(const size_t &n)
Get the value of the inner scale for a single layer.
realT m_z_mean
averaged layer height
realT layer_dir(const int n)
Get the wind direction of a single layer.
realT m_v_wind
averaged windspeed
void beta_0(const std::vector< realT > &bet)
Set the vector of layer PSD constants.
realT L_0(const size_t &n)
Get the value of the outer scale for a single layer.
realT m_dir_wind
averaged direction
std::vector< realT > m_alpha
The PSD exponent when in non-Kolmogorov mode.
std::vector< realT > beta()
Get the vector of PSD normalizations.
realT dY(realT k, realT lam_sci, realT lam_wfs)
The differential fraction of the turbulence PSD in amplitude after Fresnel propagation.
realT tau_0()
Get tau_0 at the reference wavelength.
std::vector< realT > L_0()
Get the vector of outer scales.
void layer_v_wind(const std::vector< realT > &spd)
Set the vector of layer windspeeds.
std::vector< realT > layer_dir()
Get the vector of layer wind directions.
void h_obs(realT nh)
Set the height of the observatory.
void loadGuyon2005()
Load the default atmosphere model from Guyon (2005).
void nonKolmogorov(const bool &nk)
Set the value of m_nonKolmogorov.
void layer_dir(const std::vector< realT > &d)
Set the vector of layer wind directions.
realT m_H
The atmospheric scale height, in m.
void L_0(const std::vector< realT > &L0)
Set the vector of layer outer scales.
void loadConfig(app::appConfigurator &config)
Load the configuration of this class from a configurator.
void update_z_mean()
Recalculate m_z_mean.
realT fwhm(realT lam_sci)
Calculate the full-width at half-maximum of a seeing limited image for this atmosphere for a large te...
_realT realT
The real floating type in which all calculations are performed.
bool m_nonKolmogorov
Flag indicating if non-Kolmogorov PSD parameters are used.
void alpha(const std::vector< realT > &alph)
Set the vector of layer PSD indices.
realT beta_0(const size_t &n)
Return the PSD constant for a single layer.
realT beta(const size_t &n)
Return the PSD normalization for a single layer.
realT fwhm0(realT lam_sci)
Calculate the full-width at half-maximum of a seeing limited image for this atmosphere for a small te...
realT X_Z(realT k, realT lambda_sci, realT lambda_wfs, realT secZ)
void setupConfig(app::appConfigurator &config)
Setup the configurator to configure this class.
std::vector< realT > m_L_0
The outer scale, in m.
void r_0(const realT &r0, const realT &l0)
Set the value of Fried's parameter and the reference wavelength.
void H(realT nH)
Set the atmospheric scale height.
std::vector< realT > m_layer_dir
Vector of layer wind directions, in radians.
std::vector< realT > layer_Cn2()
Get the vector of layer strengths.
void l_0(const std::vector< realT > &l0)
Set the vector of layer inner scales.
realT f_g(realT lam_sci)
Get the greenwood frequency at a specified wavelength.
realT m_r_0
Fried's parameter, in m.
void tau_0(realT tau_0, realT lam_sci)
Scale v_wind so that tau_0 has the specified value at the specified wavelength.
realT H()
Get the atmospheric scale height.
bool nonKolmogorov()
Return the value of m_nonKolmogorov.
void setSingleLayer(realT r0, realT lam0, realT L0, realT l0, realT lz, realT vw, realT dir)
Set a single layer model.
realT v_wind()
Get the 5/3 moment weighted mean wind speed.
std::vector< realT > layer_z()
Get the vector layer heights.
void layer_Cn2(const std::vector< realT > &cn2, const realT l0=0)
Set the vector layer strengths, possibly calculating r_0.
realT layer_Cn2(const int n)
Get the strength of a single layer.
realT m_h_obs
Height of the observatory above sea level, in m.
realT alpha(const size_t &n)
Return the PSD index for a single layer.
std::vector< realT > m_l_0
The inner scale of each layer, in m.
realT Y(realT k, realT lam_sci, realT secZ)
The fraction of the turbulence PSD in amplitude after Fresnel propagation.
realT layer_v_wind(const int n)
Get the wind speed of a single layer.
realT f_g()
Get the greenwood frequency at the reference wavelength.
realT z_mean()
Get the weighted mean layer height.
int checkLayers()
Checks if layer vectors have consistent length.
std::vector< realT > m_layer_Cn2
Vector of layer strengths.
std::vector< realT > m_layer_z
Vector of layer heights, in m, above the observatory.
size_t n_layers()
Get the number of layers.
std::vector< realT > beta_0()
Get the vector of PSD constants.
bool m_v_wind_updated
whether or not m_v_wind has been updated after changes
realT r_0()
Get the value of Fried's parameter r_0 at the reference wavelength lam_0.
std::vector< realT > m_layer_v_wind
Vector of layer wind speeds, in m/s.
realT v_wind_mean()
Get the mean wind speed.
void z_mean(const realT &zm)
Set the weighted mean m_z_mean and renormalize the layer heights.
realT tau_0(realT lam_sci)
Get tau_0 at a specified wavelength.
void v_wind(const realT &vw)
Set the weighted mean m_v_wind and renormalize the layer wind speeds.
realT m_lam_0
Wavelength of Fried's parameter, in m.
bool m_z_mean_updated
whether or not m_z_mean has been updated after changes
realT dX(realT k, realT lam_sci, realT lam_wfs)
The differential fraction of the turbulence PSD in phase after Fresnel propagation.
realT layer_z(const size_t n)
Get the height of a single layer.
void update_v_wind()
Recalculate m_v_wind.
constexpr units::realT c()
The speed of light.
Definition: constants.hpp:60
constexpr units::realT k()
Boltzmann Constant.
Definition: constants.hpp:71
The mxlib c++ namespace.
Definition: mxError.hpp:107
Class to manage a set of configurable values, and read their values from config/ini files and the com...
void add(const configTarget &tgt)
Add a configTarget.
bool isSet(const std::string &name, std::unordered_map< std::string, configTarget > &targets)
Check if a target has been set by the configuration.