mxlib
c++ tools for analyzing astronomical data and other tasks by Jared R. Males. [git repo]
aoPSDs.hpp
Go to the documentation of this file.
1 /** \file aoPSDs.hpp
2  * \author Jared R. Males (jaredmales@gmail.com)
3  * \brief Spatial power spectra used in adaptive optics.
4  * \ingroup mxAO_files
5  *
6  */
7 
8 //***********************************************************************//
9 // Copyright 2016-2018 Jared R. Males (jaredmales@gmail.com)
10 //
11 // This file is part of mxlib.
12 //
13 // mxlib is free software: you can redistribute it and/or modify
14 // it under the terms of the GNU General Public License as published by
15 // the Free Software Foundation, either version 3 of the License, or
16 // (at your option) any later version.
17 //
18 // mxlib is distributed in the hope that it will be useful,
19 // but WITHOUT ANY WARRANTY; without even the implied warranty of
20 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 // GNU General Public License for more details.
22 //
23 // You should have received a copy of the GNU General Public License
24 // along with mxlib. If not, see <http://www.gnu.org/licenses/>.
25 //***********************************************************************//
26 
27 #ifndef aoPSDs_hpp
28 #define aoPSDs_hpp
29 
30 #include <string>
31 
32 #include "../../mxError.hpp"
33 #include "../../math/constants.hpp"
34 #include "../../math/func/jinc.hpp"
35 
36 #include "aoConstants.hpp"
37 
38 #include "aoAtmosphere.hpp"
39 
40 namespace mx
41 {
42 namespace AO
43 {
44 namespace analysis
45 {
46 
47 namespace PSDComponent
48 {
49  ///Enum to specify which component of the PSD to calcualte
50  enum { phase, ///< The phase or OPD
51  amplitude, ///< The amplitude
52  dispPhase, ///< The phase component of dispersive anisoplanatism
53  dispAmplitude ///< The amplitude component of dispersive anisoplanatism
54  };
55 
56  std::string compName( int cc );
57 
58  int compNum( const std::string & name);
59 }
60 
61 ///Manage calculations using the von Karman spatial power spectrum.
62 /** This very general PSD has the form
63  *
64  * \f[
65  \mathcal{P}(k) = \frac{\beta}{ ( k^2 + k_0^2) ^{\alpha/2}}
66  \f]
67  *
68  * Where \f$ k \f$ is spatial frequency, \f$ \beta \f$ is a normalization constant, and outer scale \f$ L_0 \f$ is included via \f$ k_0 = 1/L_0 \f$.
69  * For \f$ L_0 \rightarrow \infty \f$ this becomes a simple power law with index \f$ \alpha \f$.
70  *
71  * For atmospheric turbulence \f$ \alpha = 11/3 \f$ and the normalization is
72  \f[
73  \beta = \frac{\mathcal{A}_p}{r_0^{5/3}}
74  \f]
75  * where \f$ A_p = 0.0218...\f$ (see \ref mx::AO::constants::a_PSD ).
76  *
77  * \ingroup mxAOAnalytic
78  */
79 template<typename realT>
81 {
82 
83 protected:
84  bool m_subPiston {true};///< flag controlling whether piston is subtracted from the PSD. Default is true.
85  bool m_subTipTilt {false}; ///< flag controlling whether tip and tilt are subtracted from the PSD. Default is false.
86 
87  bool m_scintillation {false}; ///< flag controlling whether or not scintillation is included
88  int m_component {PSDComponent::phase}; ///< If m_scintillation is true, this controls whether phase (0), amplitude (1), or dispersive contrast (2) is returned.
89 
90  realT m_D {1.0}; ///< Diameter used for piston and tip/tilt subtraction, in m. Default is 1 m.
91 
92  const char * m_id = "von Karman";
93 
94  //realT m_alpha {eleven_thirds<realT>()}; ///< The power-law index, 11/3 for Kolmogorov
95 
96 public:
97 
98  ///Default Constructor
100 
101  ///Constructor specifying the parameters
102  /**
103  */
104  vonKarmanSpectrum( bool subP, ///< [in] is the value of m_subPiston.
105  bool subT, ///< [in] is the value of m_subTipTilt.
106  realT D ///< [in] is the value of m_D.
107  );
108 
109  ///Get the value of m_subPiston
110  /**
111  * \returns m_subPiston
112  */
113  bool subPiston();
114 
115  ///Set the value of m_subPiston
116  /**
117  */
118  void subPiston( bool sp /**< [in] is the new value of m_subPiston */);
119 
120  ///Get the value of m_subTipTilt
121  /**
122  * \returns the value of m_subTipTilt.
123  */
124  bool subTipTilt();
125 
126  ///Set the value of the m_subTipTilt flag.
127  /**
128  */
129  void subTipTilt(bool st /**< [in] the new value of m_subTipTilt.*/);
130 
131  ///Get the value of m_scintillation
132  /**
133  * \returns m_scintillation
134  */
135  bool scintillation();
136 
137  ///Set the value of m_scintillation
138  /**
139  */
140  void scintillation(bool sc /**< [in] the new value of m_scintillation*/);
141 
142  ///Get the value of m_component
143  /**
144  * \returns m_component
145  */
146  int component();
147 
148  ///Set the value of m_component
149  /**
150  */
151  int component( int cc /**< [in] the new value of m_component */);
152 
153  ///Get the value of the diameter m_D.
154  /**
155  * \returns the current value of m_D, the diameter in m.
156  */
157  realT D();
158 
159  ///Set the aperture diameter
160  /**
161  */
162  void D(realT nd /**< [in] the new diameter in m */);
163 
164  ///Get the value of the PSD at spatial frequency k and a zenith distance.
165  /**
166  * \returns the von Karman PSD at the specified spatial frequency.
167  * \returns -1 if an error occurs.
168  *
169  */
170  template< class psdParamsT >
171  realT operator()( psdParamsT & par, ///< [in] gives the PSD parameters.
172  size_t layer_i,
173  realT k, ///< [in] is the spatial frequency in m^-1.
174  realT sec_zeta ///< [in] is the secant of the zenith distance.
175  );
176 
177  /// Get the value of the PSD at spatial frequency k and wavelength lambda, and a zenith distance, with a WFS at a different wavelength
178  /**
179  *
180  * \returns the von Karman PSD at the specified spatial frequency for the specified wavelength.
181  * \returns -1 if an error occurs.
182  */
183  template< class psdParamsT >
184  realT operator()( psdParamsT & par, ///< [in] gives the PSD parameters.
185  size_t layer_i,
186  realT k, ///< [in] is the spatial frequency in m^-1.
187  realT lambda, ///< [in] is the observation wavelength in m
188  realT lambda_wfs, ///< [in] is the wavefront measurement wavelength in m
189  realT secZeta ///< [in] is the secant of the zenith distance
190  );
191 
192  /// Get the fitting error for an actuator spacing d.
193  /**
194  * \todo generatlize for different alpha and beta
195  *
196  * \param atm gives the atmosphere parameters r_0 and L_0
197  * \param d is the actuator spacing in m
198  */
199  //realT fittingError(aoAtmosphere<realT> &atm, realT d);
200 
201  template<typename iosT>
202  iosT & dumpPSD(iosT & ios);
203 
204  /// Setup the configurator to configure this class
205  /**
206  * \test Loading aoAtmosphere config settings \ref tests_ao_analysis_aoAtmosphere_config "[test doc]"
207  */
208  void setupConfig( app::appConfigurator & config /**< [in] the app::configurator object*/);
209 
210  /// Load the configuration of this class from a configurator
211  /**
212  * \test Loading aoAtmosphere config settings \ref tests_ao_analysis_aoAtmosphere_config "[test doc]"
213  */
214  void loadConfig( app::appConfigurator & config /**< [in] the app::configurator object*/);
215 
216 };
217 
218 template< typename realT>
220 {
221 }
222 
223 template< typename realT>
224 vonKarmanSpectrum<realT>::vonKarmanSpectrum( bool subP, // [in] is the value of m_subPiston.
225  bool subT, // [in] is the value of m_subTipTilt.
226  realT D // [in] is the diameter
227  )
228 {
229  m_subPiston = subP;
230  m_subTipTilt = subT;
231  m_D = D;
232 }
233 
234 template< typename realT>
236 {
237  return m_subPiston;
238 }
239 
240 
241 template< typename realT>
242 void vonKarmanSpectrum<realT>::subPiston( bool sp /* [in] is the new value of m_subPiston */)
243 {
244  m_subPiston = sp;
245 }
246 
247 template< typename realT>
249 {
250  return m_subTipTilt;
251 }
252 
253 template< typename realT>
254 void vonKarmanSpectrum<realT>::subTipTilt(bool st /* [in] the new value of m_subTipTilt */)
255 {
256  m_subTipTilt = st;
257 }
258 
259 template< typename realT>
261 {
262  return m_scintillation;
263 }
264 
265 template< typename realT>
266 void vonKarmanSpectrum<realT>::scintillation(bool sc /* [in] the new value of m_scintillation */)
267 {
268  m_scintillation = sc;
269 }
270 
271 template< typename realT>
273 {
274  return m_component;
275 }
276 
277 template< typename realT>
278 int vonKarmanSpectrum<realT>::component( int cc /* [in] the new value of m_component */)
279 {
280  if( cc != PSDComponent::phase && cc != PSDComponent::amplitude && cc != PSDComponent::dispPhase && cc != PSDComponent::dispAmplitude )
281  {
282  mxError("vonKarmanSpectrum::component", MXE_INVALIDARG, "Unknown component");
283  return -1;
284  }
285 
286  m_component = cc;
287  return 0;
288 }
289 
290 template< typename realT>
292 {
293  return m_D;
294 }
295 
296 template< typename realT>
297 void vonKarmanSpectrum<realT>::D(realT nd /**< [in] the new diameter in m */)
298 {
299  m_D = nd;
300 }
301 
302 template< typename realT>
303 template< class psdParamsT >
304 realT vonKarmanSpectrum<realT>::operator()( psdParamsT & par, //< [in] gives the PSD parameters.
305  size_t layer_i,
306  realT k, // [in] is the spatial frequency in m^-1.
307  realT sec_zeta // [in] is the secant of the zenith distance.
308  )
309 {
310  realT k02;
311 
312  ///\todo this needs to handle layers with different L_0
313  if(par.L_0(layer_i) > 0)
314  {
315  k02 = (1)/(par.L_0(layer_i)*par.L_0(layer_i));
316  }
317  else k02 = 0;
318 
319  if(k02 == 0 && k == 0)
320  {
321  return 0;
322  }
323 
324  realT Ppiston, Ptiptilt;
325 
326  if( (m_subPiston || m_subTipTilt) )
327  {
328  if (m_D == 0)
329  {
330  mxError("aoAtmosphere", MXE_PARAMNOTSET, "Diameter D not set for Piston and/or TT subtraction.");
331  return -1;
332  }
333  if(m_subPiston)
334  {
335  Ppiston = pow(2*math::func::jinc(math::pi<realT>()*k*m_D), 2);
336  }
337  else Ppiston = 0;
338 
339  if(m_subTipTilt)
340  {
341  Ptiptilt = pow(4*math::func::jincN(2, math::pi<realT>()*k*m_D), 2);
342  }
343  else Ptiptilt = 0;
344  }
345  else
346  {
347  Ppiston = 0;
348  Ptiptilt = 0;
349  }
350 
351  return (par.beta(layer_i)*pow(k*k+k02, -1*par.alpha(layer_i)/2) + par.beta_0(layer_i) ) * (1.0-Ppiston - Ptiptilt)*sec_zeta;
352 }
353 
354 template< typename realT>
355 template< class psdParamsT >
356 realT vonKarmanSpectrum<realT>::operator()( psdParamsT & par, // [in] gives the PSD parameters.
357  size_t layer_i,
358  realT k, // [in] is the spatial frequency in m^-1.
359  realT lambda, // [in] is the observation wavelength in m. Not used if par.nonKolmogorov==true
360  realT lambda_wfs, // [in] is the wavefront measurement wavelength in m. Only used if m_scintillation==true.
361  realT secZeta // [in] is the secant of the zenith distance.
362  )
363 {
364  realT psd = operator()(par, layer_i, k, secZeta);
365 
366  if( par.nonKolmogorov() == false ) psd *= pow( par.lam_0()/lambda, 2);
367 
368  if(psd < 0) return -1;
369 
370  if(m_scintillation)
371  {
372  if(m_component == PSDComponent::phase)
373  {
374  psd *= (par.X(k, lambda, secZeta));
375  }
376  else if (m_component == PSDComponent::amplitude)
377  {
378  psd *= (par.Y(k, lambda, secZeta));
379  }
380  else if (m_component == PSDComponent::dispPhase)
381  {
382  psd *= (par.X_Z(k, lambda, lambda_wfs, secZeta));
383  }
384  else if (m_component == PSDComponent::dispAmplitude)
385  {
386  mxError("vonKarmanSpectrum::operator()", MXE_NOTIMPL, "Dispersive-aniso amplitude not implemented");
387  return 0;
388  }
389  else
390  {
391  mxError("vonKarmanSpectrum::operator()", MXE_INVALIDARG, "Invalid component specified");
392  return 0;
393  }
394  }
395 
396  return psd;
397 
398 }
399 
400 /*template< typename realT>
401 realT vonKarmanSpectrum<realT>::fittingError(aoAtmosphere<realT> &atm, realT d)
402 {
403  realT k0;
404  if(atm.L_0(0) > 0)
405  {
406  k0 = 1/ (atm.L_0(0)*atm.L_0(0));
407  }
408  else k0 = 0;
409 
410  return (math::pi<realT>() * math::six_fifths<realT>())* constants::a_PSD<realT>()/ pow(atm.r_0(), math::five_thirds<realT>()) * (1./pow( pow(0.5/d,2) + k0, math::five_sixths<realT>()));
411 }*/
412 
413 template< typename realT>
414 template<typename iosT>
416 {
417  ios << "# PSD Parameters:" << '\n';
418  ios << "# ID = " << m_id << '\n';
419  ios << "# D = " << m_D << '\n';
420  ios << "# subPiston = " << std::boolalpha << m_subPiston << '\n';
421  ios << "# subTipTilt = " << std::boolalpha << m_subTipTilt << '\n';
422  ios << "# Scintillation = " << std::boolalpha << m_scintillation << '\n';
423  ios << "# Component = " << PSDComponent::compName(m_component) << '\n';
424  return ios;
425 }
426 
427 template<typename realT>
429 {
430  using namespace mx::app;
431 
432  config.add("psd.D" , "", "psd.D" , argType::Required, "psd", "D", false, "real" , "Aperture diameter. Used for piston and tip/tilt subtraction.");
433  config.add("psd.subPiston" , "", "psd.subPiston" , argType::Required, "psd", "subPiston", false, "real" , "");
434  config.add("psd.subTipTilt" , "", "psd.subTipTilt" , argType::Required, "psd", "subTipTilt", false, "real" , "");
435  config.add("psd.scintillation", "", "psd.scintillation", argType::Required, "psd", "scintillation", false, "real" , "");
436  config.add("psd.component" , "", "psd.component" , argType::Required, "psd", "component", false, "real" , "");
437 }
438 
439 template<typename realT>
441 {
442  //Here "has side effecs" means that the set function does more than simply copy the value.
443 
444  config(m_D, "psd.D");
445  config(m_subPiston, "psd.subPiston");
446  config(m_subTipTilt, "psd.subTipTilt");
447  config(m_scintillation, "psd.scintillation");
448 
449  std::string cn = PSDComponent::compName(m_component);
450  config(cn, "psd.component");
451  component(PSDComponent::compNum(cn));
452 }
453 
454 
455 extern template
457 
458 extern template
460 
461 extern template
463 
464 #ifdef HASQUAD
465 extern template
467 #endif
468 
469 } //namespace analysis
470 } //namespace AO
471 } //namespace mx
472 
473 #endif //aoPSDs_hpp
Provides a class to specify atmosphere parameters.
Calculate and provide constants related to adaptive optics.
@ dispAmplitude
The amplitude component of dispersive anisoplanatism.
Definition: aoPSDs.hpp:53
@ phase
The phase or OPD.
Definition: aoPSDs.hpp:50
@ dispPhase
The phase component of dispersive anisoplanatism.
Definition: aoPSDs.hpp:52
@ amplitude
The amplitude.
Definition: aoPSDs.hpp:51
constexpr units::realT k()
Boltzmann Constant.
Definition: constants.hpp:71
T2 jincN(const T1 &v, const T2 &x)
The JincN function.
Definition: jinc.hpp:120
T jinc(const T &x)
The Jinc function.
Definition: jinc.hpp:64
The mxlib c++ namespace.
Definition: mxError.hpp:107
Manage calculations using the von Karman spatial power spectrum.
Definition: aoPSDs.hpp:81
bool subTipTilt()
Get the value of m_subTipTilt.
Definition: aoPSDs.hpp:248
realT D()
Get the value of the diameter m_D.
Definition: aoPSDs.hpp:291
realT operator()(psdParamsT &par, size_t layer_i, realT k, realT sec_zeta)
Get the value of the PSD at spatial frequency k and a zenith distance.
Definition: aoPSDs.hpp:304
iosT & dumpPSD(iosT &ios)
Get the fitting error for an actuator spacing d.
Definition: aoPSDs.hpp:415
int m_component
If m_scintillation is true, this controls whether phase (0), amplitude (1), or dispersive contrast (2...
Definition: aoPSDs.hpp:88
void setupConfig(app::appConfigurator &config)
Setup the configurator to configure this class.
Definition: aoPSDs.hpp:428
bool subPiston()
Get the value of m_subPiston.
Definition: aoPSDs.hpp:235
realT m_D
Diameter used for piston and tip/tilt subtraction, in m. Default is 1 m.
Definition: aoPSDs.hpp:90
vonKarmanSpectrum()
Default Constructor.
Definition: aoPSDs.hpp:219
bool scintillation()
Get the value of m_scintillation.
Definition: aoPSDs.hpp:260
void loadConfig(app::appConfigurator &config)
Load the configuration of this class from a configurator.
Definition: aoPSDs.hpp:440
int component()
Get the value of m_component.
Definition: aoPSDs.hpp:272
bool m_subTipTilt
flag controlling whether tip and tilt are subtracted from the PSD. Default is false.
Definition: aoPSDs.hpp:85
bool m_scintillation
flag controlling whether or not scintillation is included
Definition: aoPSDs.hpp:87
bool m_subPiston
flag controlling whether piston is subtracted from the PSD. Default is true.
Definition: aoPSDs.hpp:84
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.