29 #ifndef mx_AO_sim_turbLayer_hpp
30 #define mx_AO_sim_turbLayer_hpp
34 #include <Eigen/Dense>
36 #include "../../improc/imageTransforms.hpp"
45 template<
typename _aoSystemT>
46 struct turbAtmosphere;
54 template<
typename _aoSystemT>
57 typedef _aoSystemT aoSystemT;
58 typedef typename aoSystemT::realT realT;
59 typedef Eigen::Array<realT, -1, -1> imageT;
80 imageT m_shiftPhaseWP;
82 imageT m_shiftPhaseWork;
104 void shift( realT dt );
126 template<
typename aoSystemT>
137 if(m_parent ==
nullptr)
139 mxThrowException(
err::paramnotset,
"mx::AO::sim::turbLayer::setLayer",
"parent is not set (m_parent is nullptr)");
142 if(m_parent->aosys() ==
nullptr)
144 mxThrowException(
err::paramnotset,
"mx::AO::sim::turbLayer::setLayer",
"parent ao system is not set (m_parent->aosys() is nullptr)");
147 realT vwind = m_parent->aosys()->atm.layer_v_wind(m_layerNo);
148 realT dwind = m_parent->aosys()->atm.layer_dir(m_layerNo);
149 realT pupD = m_parent->aosys()->D();
150 uint32_t wfSz = m_parent->wfSz();
152 m_dx = vwind*cos(dwind)/(pupD/wfSz);
153 m_dy = vwind*sin(dwind)/(pupD/wfSz);
158 template<
typename aoSystemT>
159 uint32_t turbLayer<aoSystemT>::layerNo()
164 template<
typename aoSystemT>
165 uint32_t turbLayer<aoSystemT>::scrnSz()
170 template<
typename aoSystemT>
171 void turbLayer<aoSystemT>::alloc()
173 if(m_parent ==
nullptr)
175 mxThrowException(err::paramnotset,
"mx::AO::sim::turbLayer::alloc",
"parent is not set (m_parent is nullptr)");
178 if(m_parent->aosys() ==
nullptr)
180 mxThrowException(err::paramnotset,
"mx::AO::sim::turbLayer::alloc",
"parent ao system is not set (m_parent->aosys() is nullptr)");
183 m_phase.resize(m_scrnSz, m_scrnSz);
185 uint32_t wfSz = m_parent->wfSz();
187 uint32_t buffSz = m_parent->buffSz();
189 m_shiftPhaseWP.resize( wfSz+2*buffSz, wfSz+2*buffSz);
191 m_shiftPhase.resize( wfSz+2*buffSz, wfSz+2*buffSz);
193 m_shiftPhaseWork.resize( wfSz+2*buffSz, wfSz+2*buffSz);
199 m_last_wdx = m_scrnSz + 1;
200 m_last_wdy = m_scrnSz + 1;
203 realT r0 = m_parent->aosys()->atm.r_0(m_parent->aosys()->lam_sci());
204 realT L0 = m_parent->aosys()->atm.L_0(m_layerNo);
205 realT l0 = m_parent->aosys()->atm.l_0(m_layerNo);
207 m_psd.resize(m_scrnSz, m_scrnSz);
209 m_freq.resize(m_scrnSz, m_scrnSz);
210 sigproc::frequencyGrid<imageT>(m_freq, m_parent->aosys()->D()/wfSz);
212 realT beta = 0.0218/pow( r0, 5./3.);
213 realT sqrt_alpha = 0.5*11./3.;
216 if(L0 > 0) L02 = 1.0/(L0*L0);
219 #pragma omp parallel for
220 for(
size_t jj =0; jj < m_scrnSz; ++jj)
222 for(
size_t ii=0; ii < m_scrnSz; ++ii)
225 if(m_freq(ii,jj) == 0 && L02 == 0)
231 p = beta / pow( pow(m_freq(ii,jj),2) + L02, sqrt_alpha);
232 if(l0 > 0 ) p *= exp(-1*pow( m_freq(ii,jj)*l0, 2));
237 if(m_parent->aosys()->psd.subPiston())
239 Ppiston = pow(2*
math::func::jinc(math::pi<realT>() * m_freq(ii,jj) * m_parent->aosys()->D()), 2);
241 if(m_parent->aosys()->psd.subTipTilt())
243 Ptiptilt = pow(4*
math::func::jincN(2,math::pi<realT>() * m_freq(ii,jj) * m_parent->aosys()->D()), 2);
246 m_psd(ii,jj) = sqrt(p*(1.0-Ppiston-Ptiptilt));
251 if(m_parent->shLevel() > 0)
254 m_psd(0,1) *= 0.5*0.5;
255 m_psd(1,0) *= 0.5*0.5;
256 m_psd(m_psd.rows()-1, 0) *= 0.5*0.5;
257 m_psd(0, m_psd.cols()-1) *= 0.5*0.5;
259 m_psd(1,1) *= 0.75*0.75;
260 m_psd(m_psd.rows()-1, m_psd.cols()-1) *= 0.75*0.75;
261 m_psd(m_psd.rows()-1, 1) *= 0.75*0.75;
262 m_psd(1, m_psd.cols()-1) *= 0.75*0.75;
266 template<
typename aoSystemT>
273 template<
typename aoSystemT>
279 ddx = m_x0 + m_dx*dt;
280 ddy = m_y0 + m_dy*dt;
282 wdx = (int) trunc(ddx);
285 wdy = (int) trunc(ddy);
292 if(wdx != m_last_wdx || wdy != m_last_wdy)
305 template<
typename aoSystemT>
311 template<
typename aoSystemT>
317 ddx = uniVar * (m_scrnSz);
318 ddy = uniVar * (m_scrnSz);
320 wdx = (int) trunc(ddx);
322 wdy = (int) trunc(ddy);
333 if(ddx !=0 || ddy != 0)
339 m_shiftPhase = m_shiftPhaseWP;
mxException for parameters which aren't set
A random number type, which functions like any other arithmetic type.
T2 jincN(const T1 &v, const T2 &x)
The JincN function.
T jinc(const T &x)
The Jinc function.
Simulation of a single turbulent layer.
void genDealloc()
Deallocate memory necessary for phase screen generation.
void initRandom()
Seed the uniform deviation. Call this if you intend to use shiftRandom.
mx::math::uniDistT< realT > uniVar
Uniform deviate, used in shiftRandom.
void shift(realT dt)
Shift to a timestep.
void shiftRandom(bool nofract=false)
Shift by a random amount using the uniform distribution.