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