239 if( m_turbAtmo ==
nullptr )
244 if( m_turbAtmo->aosys() ==
nullptr )
249 if( m_turbAtmo->nLayers() <= layerNo )
252 "atmosphere is not setup (m_turbAtmo->m_layers size is <= layerNo)" );
261 N = 36.0 + 32.0 * ( m_level - 1 );
263 if( m_outerSubHarmonics )
271 m_sqrtPSD.resize( N );
274 m_scrnSz = m_turbAtmo->layer( layerNo ).scrnSz();
280 this->setChangePoint();
284 realT r0 = m_turbAtmo->aosys()->atm.r_0( m_turbAtmo->aosys()->lam_sci() );
285 realT D = m_turbAtmo->aosys()->D();
286 uint32_t wfSz = m_turbAtmo->wfSz();
288 realT beta = 0.0218 / pow( r0, 5. / 3. ) / pow( ( D / wfSz ) * m_scrnSz, 2 );
290 realT sqrt_alpha = 0.5 * 11. / 3.;
292 realT L0 = m_turbAtmo->aosys()->atm.L_0( layerNo );
296 L02 = 1.0 / pow( L0, 2 );
302 m_modes.resize( m_scrnSz, m_scrnSz, N );
305 std::vector<realT> scs;
307 if( m_outerSubHarmonics )
311 m_m = std::vector<realT>( { -1.25, -0.75, -0.25, 0.25, 0.75, 1.25, -1.25, 1.25, -1.25, 1.25,
312 -1.25, 1.25, -1.25, 1.25, -1.25, -0.75, -0.25, 0.25, 0.75, 1.25 } );
313 m_n = std::vector<realT>( { -1.25, -1.25, -1.25, -1.25, -1.25, -1.25, -0.75, -0.75, -0.25, -0.25,
314 0.25, 0.25, 0.75, 0.75, 1.25, 1.25, 1.25, 1.25, 1.25, 1.25 } );
315 scs.resize( m_m.size(), sc );
318 for(
int nl = 1; nl <= m_level; ++nl )
320 realT sc = pow( 3.0, -nl );
322 for(
int mp = -3; mp < 3; ++mp )
324 for(
int np = -3; np < 3; ++np )
330 if( np == -1 || np == 0 )
335 if( np == -1 || np == 0 )
340 m_m.push_back( sc * ( mp + 0.5 ) );
341 m_n.push_back( sc * ( np + 0.5 ) );
348 for(
int n = 0; n < m_m.size(); ++n )
350 realT k = sqrt( ( pow( m_m[n], 2 ) + pow( m_n[n], 2 ) ) ) / ( ( D / wfSz ) * m_scrnSz );
352 realT tpsd = beta / pow( k * k + L02, sqrt_alpha );
356 if( m_turbAtmo->aosys()->psd.subPiston() )
361 if( m_turbAtmo->aosys()->psd.subTipTilt() )
366 m_sqrtPSD[n] = scs[n] * sqrt( tpsd * ( 1 - Ppiston - Ptiptilt ) );
370 for(
int cc = 0; cc < m_scrnSz; ++cc )
372 realT np = cc - 0.5 * m_scrnSz;
373 for(
int rr = 0; rr < m_scrnSz; ++rr )
375 realT mp = rr - 0.5 * m_scrnSz;
376 m_modes.image( n )( rr, cc ) =
383 this->setChangePoint();
394 if( m_turbAtmo ==
nullptr )
399 if( this->isChanged() )
404 if( scrn.rows() != m_scrnSz || scrn.cols() != m_scrnSz )
412 if( m_modes.rows() != scrn.rows() || m_modes.cols() != scrn.cols() || m_modes.planes() != m_noise.size() )
419 if( m_noise.size() != m_m.size() || m_noise.size() != m_n.size() || m_sqrtPSD.size() != m_noise.size() )
426 for(
size_t n = 0; n < m_noise.size(); ++n )
428 m_noise[n] = 2 * m_turbAtmo->normVar();
431#pragma omp parallel for
432 for(
int cc = 0; cc < m_scrnSz; ++cc )
434 realT np = cc - 0.5 * m_scrnSz;
435 for(
int rr = 0; rr < m_scrnSz; ++rr )
437 realT mp = rr - 0.5 * m_scrnSz;
441 for(
unsigned n = 0; n < m_noise.size(); ++n )
443 scrn( rr, cc ) += m_noise[n] * m_modes.image( n )( rr, cc );
448 for(
unsigned n = 0; n < m_m.size(); ++n )
450 scrn( rr, cc ) += m_noise[n] * m_sqrtPSD[n] *