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