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