30 #ifndef mx_AO_sim_turbSubHarm_hpp
31 #define mx_AO_sim_turbSubHarm_hpp
37 #include "../../improc/eigenImage.hpp"
38 #include "../../improc/eigenCube.hpp"
40 #include "../../math/constants.hpp"
41 #include "../../math/func/jinc.hpp"
56 template<
typename _turbAtmosphereT>
62 typedef _turbAtmosphereT turbAtmosphereT;
63 typedef typename turbAtmosphereT::realT realT;
71 turbAtmosphereT * m_turbAtmo {
nullptr};
85 std::vector<realT> m_noise;
87 std::vector<realT> m_m;
88 std::vector<realT> m_n;
90 std::vector<realT> m_sqrtPSD;
110 void turbAtmo( turbAtmosphereT * atm );
119 void level( uint32_t ml );
142 void initGrid( uint32_t layerNo );
152 template<
typename turbAtmosphereT>
157 template<
typename turbAtmosphereT>
160 m_turbAtmo = turbatm;
163 template<
typename turbAtmosphereT>
169 template<
typename turbAtmosphereT>
175 template<
typename turbAtmosphereT>
181 template<
typename turbAtmosphereT>
187 template<
typename turbAtmosphereT>
193 template<
typename turbAtmosphereT>
198 if(m_turbAtmo ==
nullptr)
200 mxThrowException(
err::paramnotset,
"mx::AO::sim::turbSubHarmonic::initGrid",
"atmosphere is not set (m_turbAtmo is nullptr)");
203 if(m_turbAtmo->aosys() ==
nullptr)
205 mxThrowException(
err::paramnotset,
"mx::AO::sim::turbSubHarmonic::initGrid",
"ao system is not set (m_turbAtmo->m_aosys is nullptr)");
208 if(m_turbAtmo->nLayers() <= layerNo)
210 mxThrowException(
err::invalidconfig ,
"mx::AO::sim::turbSubHarmonic::initGrid",
"atmosphere is not setup (m_turbAtmo->m_layers size is <= layerNo)");
219 N = 36.0 + 32.0*(m_level-1);
227 m_scrnSz = m_turbAtmo->layer(layerNo).scrnSz();
238 realT r0 = m_turbAtmo->aosys()->atm.r_0(m_turbAtmo->aosys()->lam_sci());
239 realT D = m_turbAtmo->aosys()->D();
240 uint32_t wfSz = m_turbAtmo->wfSz();
243 realT beta = 0.0218/pow(r0, 5./3.)/pow((D/wfSz)*m_scrnSz,2) ;
245 realT sqrt_alpha = 0.5*11./3.;
247 realT L0 = m_turbAtmo->aosys()->atm.L_0(layerNo);
250 if(L0 > 0) L02 = 1.0/pow( L0, 2);
255 m_modes.resize(m_scrnSz, m_scrnSz, N);
259 for(
int nl = 1; nl <= m_level; ++nl)
261 realT sc = pow(3.0, -nl);
263 for(
int mp = -3; mp < 3; ++mp)
265 for(
int np = -3; np < 3; ++np)
271 if(np == -1 || np == 0)
continue;
275 if(np == -1 || np == 0)
continue;
279 m_m[n] = sc*(mp+0.5);
280 m_n[n] = sc*(np+0.5);
282 realT
k = sqrt((pow(m_m[n],2) + pow(m_n[n],2)))/((D/wfSz)*m_scrnSz);
284 realT tpsd = beta / pow(
k*
k + L02, sqrt_alpha);
288 if(m_turbAtmo->aosys()->psd.subPiston())
293 if(m_turbAtmo->aosys()->psd.subTipTilt())
298 m_sqrtPSD[n] = sc*sqrt(tpsd*(1-Ppiston-Ptiptilt));
302 for(
int cc=0; cc < m_scrnSz; ++cc)
304 realT np = cc - 0.5*m_scrnSz;
305 for(
int rr=0; rr < m_scrnSz; ++rr)
307 realT mp = rr - 0.5*m_scrnSz;
308 m_modes.image(n)(rr,cc) = m_sqrtPSD[n]*cos(math::two_pi<realT>()*(m_m[n]*mp + m_n[n]*np)/m_scrnSz);
319 template<
typename turbAtmosphereT>
320 void turbSubHarmonic<turbAtmosphereT>::screen(improc::eigenImage<realT> & scrn)
327 if(m_turbAtmo ==
nullptr)
329 mxThrowException(err::paramnotset,
"mx::AO::sim::turbSubHarmonic::screen",
"atmosphere is not set (m_turbAtmo is nullptr)");
332 if(scrn.rows() != m_scrnSz || scrn.cols() != m_scrnSz)
334 mxThrowException(err::sizeerr,
"mx::AO::sim::turbSubHarmonic::screen",
"input screen is not the right size");
340 if(m_modes.rows() != scrn.rows() || m_modes.cols() != scrn.cols() || m_modes.planes() != m_noise.size())
342 mxThrowException(err::sizeerr,
"mx::AO::sim::turbSubHarmonic::screen",
"modes cube wrong size, call initGrid().");
347 if( m_noise.size() != m_m.size() || m_noise.size() != m_n.size() || m_sqrtPSD.size() != m_noise.size())
349 mxThrowException(err::sizeerr,
"mx::AO::sim::turbSubHarmonic::screen",
"vectors not allocated, call initGrid().");
354 for(
size_t n=0; n < m_noise.size(); ++n)
356 m_noise[n] = 2*m_turbAtmo->normVar();
359 #pragma omp parallel for
360 for(
int cc = 0; cc < m_scrnSz; ++cc)
362 realT np = cc - 0.5*m_scrnSz;
363 for(
int rr=0; rr < m_scrnSz; ++rr)
365 realT mp = rr - 0.5*m_scrnSz;
369 for(
unsigned n =0; n < m_noise.size(); ++n)
371 scrn(rr,cc) += m_noise[n]*m_modes.image(n)(rr,cc);
376 for(
unsigned n =0; n < m_m.size(); ++n)
378 scrn(rr,cc) += m_noise[n]*m_sqrtPSD[n]*cos(math::two_pi<realT>()*(m_m[n]*mp + m_n[n]*np)/m_scrnSz);
385 template<
typename turbAtmosphereT>
392 m_modes.resize(0, 0, 0);
A class to manage low-frequency sub-harmonic phase screen generation in atmospheric turbulence.
void deinit()
Deallocate memory.
uint32_t m_scrnSz
The wavefront screen size from the layer being simulated.
bool preCalc()
Get whether or not the modes are pre-calculated.
improc::eigenCube< realT > m_modes
the pre-calculated modes
turbAtmosphereT * turbAtmo()
Get the pointer to the AO atmosphere.
uint32_t level()
Get the subharmonic level.
bool m_preCalc
whether or not the modes are pre-calculated.
unsigned m_level
The subharmonic level to apply.
mxException for invalid config settings
mxException for parameters which aren't set
constexpr units::realT k()
Boltzmann Constant.
Eigen::Array< scalarT, -1, -1 > eigenImage
Definition of the eigenImage type, which is an alias for Eigen::Array.
T2 jincN(const T1 &v, const T2 &x)
The JincN function.
T jinc(const T &x)
The Jinc function.
Declaration and definition of a turbulent atmosphere.