8#ifndef aoAtmosphere_hpp
9#define aoAtmosphere_hpp
23#include "../../math/constants.hpp"
45template <
typename _realT>
169 void L_0(
const std::vector<realT> &L0 );
186 void l_0(
const std::vector<realT> &l0 );
222 void alpha(
const std::vector<realT> &alph );
246 void beta(
const std::vector<realT> &bet );
270 void beta_0(
const std::vector<realT> &bet );
285 size_t currentLayer();
287 void currentLayer(
size_t cl );
306 void layer_z(
const std::vector<realT> &layz );
591 template <
typename iosT>
611template <
typename realT>
616template <
typename realT>
620 if( layerCount == 0 )
625 if(
m_L_0.size() != layerCount ||
m_l_0.size() != layerCount ||
m_layer_z.size() != layerCount ||
644 realT totalStrength = 0;
645 bool hasPositiveStrength =
false;
646 for(
size_t index = 0; index < layerCount; ++index )
657 hasPositiveStrength = hasPositiveStrength ||
m_layer_Cn2[index] > 0;
663 "non-Kolmogorov atmosphere parameters are invalid" );
667 if( !hasPositiveStrength || !
math::isFinite( totalStrength ) || totalStrength <= 0 )
670 "atmosphere must contain a finite positive layer-strength sum" );
676template <
typename realT>
682template <
typename realT>
688template <
typename realT>
703template <
typename realT>
709template <
typename realT>
715template <
typename realT>
721template <
typename realT>
727 "layer strengths must be nonempty and reference wavelength nonnegative" );
730 realT layer_norm = 0;
731 for(
size_t i = 0; i < cn2.size(); ++i )
736 "layer strengths must be finite and nonnegative" );
738 layer_norm += cn2[i];
746 std::vector<realT> normalized = cn2;
747 for(
size_t i = 0; i < normalized.size(); ++i )
749 normalized[i] /= layer_norm;
758 "layer strengths produce an invalid Fried parameter" );
772template <
typename realT>
778template <
typename realT>
784template <
typename realT>
790template <
typename realT>
796template <
typename realT>
802template <
typename realT>
808template <
typename realT>
814template <
typename realT>
820template <
typename realT>
833template <
typename realT>
840template <
typename realT>
846template <
typename realT>
860template <
typename realT>
867template <
typename realT>
873template <
typename realT>
886template <
typename realT>
893template <
typename realT>
899template <
typename realT>
908template <
typename realT>
914template <
typename realT>
921template <
typename realT>
927template <
typename realT>
933template <
typename realT>
939template <
typename realT>
945template <
typename realT>
951template <
typename realT>
957template <
typename realT>
963template <
typename realT>
970template <
typename realT>
976template <
typename realT>
982template <
typename realT>
989template <
typename realT>
997template <
typename realT>
1005template <
typename realT>
1041template <
typename realT>
1061template <
typename realT>
1069template <
typename realT>
1091template <
typename realT>
1104 for(
size_t i = 0; i <
m_layer_z.size(); ++i )
1111template <
typename realT>
1124template <
typename realT>
1139template <
typename realT>
1151template <
typename realT>
1166template <
typename realT>
1169 realT ll2 =
static_cast<realT>( 1 ) / pow( lambda / 1e-6, 2 );
1171 return 1.0 + 8.34213e-5 + 0.0240603 / ( 130.0 - ll2 ) + 0.00015997 / ( 38.9 - ll2 );
1174template <
typename realT>
1178 realT sinZ = sqrt( 1.0 - pow( 1.0 / secZ, 2 ) );
1179 realT tanZ = sinZ * secZ;
1193template <
typename realT>
1198 realT fwhm = 0.98 * ( lam_sci / r0lam );
1203template <
typename realT>
1208 realT fwhm = 0.98 * ( lam_sci / r0lam );
1212 fwhm *= sqrt( 1 - 2.183 * pow( r0lam /
L_0( 0 ), 0.356 ) );
1217template <
typename realT>
1223template <
typename realT>
1229template <
typename realT>
1232 return 0.134 /
f_g();
1235template <
typename realT>
1238 return 0.134 /
f_g( lam_sci );
1241template <
typename realT>
1248template <
typename realT>
1251 layer_Cn2( { 0.2283, 0.0883, 0.0666, 0.1458, 0.3350, 0.1350 } );
1252 layer_z( { 500, 1000, 2000, 4000, 8000, 16000 } );
1254 layer_dir( { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 } );
1255 L_0( { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 } );
1256 l_0( { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 } );
1263template <
typename realT>
1266 layer_Cn2( { 0.42, 0.029, 0.062, 0.16, 0.11, 0.10, 0.12 } );
1267 layer_z( { 250., 500., 1000., 2000., 4000., 8000., 16000. } );
1268 layer_v_wind( { 10.0, 10.0, 20.0, 20.0, 25.0, 30.0, 25.0 } );
1269 layer_dir( { 1.05, 1.05, 1.31, 1.31, 1.75, 1.92, 1.75 } );
1271 r_0( 0.16, 0.5e-6 );
1273 L_0( { 25.0, 25.0, 25.0, 25.0, 25.0, 25.0, 25.0 } );
1274 l_0( { 0.0, 0, 0, 0, 0, 0, 0 } );
1279template <
typename realT>
1283 L_0( std::vector<realT>( { L0 } ) );
1284 l_0( std::vector<realT>( { l0 } ) );
1285 layer_Cn2( std::vector<realT>( { 1 } ) );
1286 layer_z( std::vector<realT>( { lz } ) );
1288 layer_dir( std::vector<realT>( { dir } ) );
1291template <
typename realT>
1292template <
typename iosT>
1295 ios <<
"# Atmosphere Parameters:\n";
1296 ios <<
"# nonKolmogorov = " << std::boolalpha <<
nonKolmogorov() <<
'\n';
1297 ios <<
"# n_layers = " <<
n_layers() <<
'\n';
1301 ios <<
"# r_0 = " <<
r_0() <<
'\n';
1302 ios <<
"# lam_0 = " <<
lam_0() <<
'\n';
1303 ios <<
"# tau_0 = " <<
tau_0(
lam_0() ) <<
'\n';
1304 ios <<
"# FWHM = " <<
fwhm(
lam_0() ) <<
'\n';
1305 ios <<
"# layer_Cn2 = ";
1306 for(
size_t i = 0; i <
n_layers() - 1; ++i )
1312 ios <<
"# alpha = ";
1313 for(
size_t i = 0; i <
n_layers() - 1; ++i )
1314 ios <<
alpha()[i] <<
", ";
1317 for(
size_t i = 0; i <
n_layers() - 1; ++i )
1318 ios <<
beta()[i] <<
", ";
1320 ios <<
"# beta_0 = ";
1321 for(
size_t i = 0; i <
n_layers() - 1; ++i )
1322 ios <<
beta_0()[i] <<
", ";
1327 for(
size_t i = 0; i <
n_layers() - 1; ++i )
1328 ios <<
L_0()[i] <<
", ";
1331 for(
size_t i = 0; i <
n_layers() - 1; ++i )
1332 ios <<
l_0()[i] <<
", ";
1335 ios <<
"# layer_v_wind = ";
1336 for(
size_t i = 0; i <
n_layers() - 1; ++i )
1339 ios <<
"# layer_dir = ";
1340 for(
size_t i = 0; i <
n_layers() - 1; ++i )
1343 ios <<
"# mean v_wind = " <<
v_wind() <<
'\n';
1344 ios <<
"# mean dir_wind = " <<
dir_wind() <<
'\n';
1348 ios <<
"# layer_z = ";
1349 for(
size_t i = 0; i <
n_layers() - 1; ++i )
1352 ios <<
"# mean z = " <<
z_mean() <<
'\n';
1353 ios <<
"# h_obs = " <<
h_obs() <<
'\n';
1354 ios <<
"# H = " <<
H() <<
'\n';
1360template <
typename realT>
1363 using namespace mx::app;
1365 config.
add(
"atm.r_0",
"",
"atm.r_0", argType::Required,
"atm",
"r_0",
false,
"real",
"Fried's parameter [m]" );
1366 config.
add(
"atm.lam_0",
1374 "The reference wavlength for r_0 [m]" );
1375 config.
add(
"atm.L_0",
1383 "Layer outer scales [m]" );
1384 config.
add(
"atm.l_0",
1392 "Layer inner scales [m]" );
1393 config.
add(
"atm.layer_z",
1401 "layer heights [m]" );
1402 config.
add(
"atm.h_obs",
1410 "height of observatory [m]" );
1411 config.
add(
"atm.H",
"",
"atm.H", argType::Required,
"atm",
"H",
false,
"real",
"atmospheric scale heights [m]" );
1412 config.
add(
"atm.layer_Cn2",
1420 "Layer Cn^2. Note that this does not set r_0." );
1421 config.
add(
"atm.layer_v_wind",
1429 "Layer wind speeds [m/s]" );
1430 config.
add(
"atm.layer_dir",
1438 "Layer wind directions [rad]" );
1439 config.
add(
"atm.v_wind",
1447 "Mean windspeed (5/3 momement), rescales layer speeds [m/s]" );
1448 config.
add(
"atm.tau_0",
1456 "AO time constant, sets v_wind and rescales layer speeds. [s]" );
1457 config.
add(
"atm.z_mean",
1465 "Mean layer height (5/3 momemnt), rescales layer heights [m/s]" );
1466 config.
add(
"atm.nonKolmogorov",
1468 "atm.nonKolmogorov",
1474 "Set to use a non-Kolmogorov PSD. See alpha and beta." );
1475 config.
add(
"atm.alpha",
1483 "Non-kolmogorov PSD exponent." );
1484 config.
add(
"atm.beta",
1492 "Non-kolmogorov PSD normalization." );
1493 config.
add(
"atm.beta_0",
1501 "Non-kolmogorov PSD constant." );
1504template <
typename realT>
1513 config(
m_lam_0,
"atm.lam_0" );
1517 config( lcn2,
"atm.layer_Cn2" );
1518 if( config.
isSet(
"atm.layer_Cn2" ) )
1523 return strengthStatus;
1528 config( r0,
"atm.r_0" );
1529 if( config.
isSet(
"atm.r_0" ) )
1532 config(
m_L_0,
"atm.L_0" );
1534 config(
m_l_0,
"atm.l_0" );
1538 config( layz,
"atm.layer_z" );
1539 if( config.
isSet(
"atm.layer_z" ) )
1542 config(
m_h_obs,
"atm.h_obs" );
1543 config(
m_H,
"atm.H" );
1547 config( lvw,
"atm.layer_v_wind" );
1548 if( config.
isSet(
"atm.layer_v_wind" ) )
1553 config( ld,
"atm.layer_dir" );
1554 if( config.
isSet(
"atm.layer_dir" ) )
1558 config( vw,
"atm.v_wind" );
1561 config( t0,
"atm.tau_0" );
1563 config( zm,
"atm.z_mean" );
1567 std::vector<realT> a =
m_alpha;
1568 config( a,
"atm.alpha" );
1569 if( config.
isSet(
"atm.alpha" ) )
1572 std::vector<realT> b =
m_beta;
1573 config( b,
"atm.beta" );
1574 if( config.
isSet(
"atm.beta" ) )
1578 config( b0,
"atm.beta_0" );
1579 if( config.
isSet(
"atm.beta_0" ) )
1588 if( config.
isSet(
"atm.v_wind" ) )
1593 "configured mean wind speed must be finite and positive" );
1599 "a static atmosphere cannot be rescaled to positive mean wind" );
1604 if( config.
isSet(
"atm.tau_0" ) )
1611 "configured atmosphere time constant requires valid Fried, wavelength, and wind values" );
1616 if( config.
isSet(
"atm.z_mean" ) )
1621 "configured mean layer height must be finite and nonnegative" );
1625 if( currentHeight == 0 )
1631 "a zero-height atmosphere cannot be rescaled to a positive mean height" );
Calculate and provide constants related to adaptive optics.
An application configuration manager.
A class to specify atmosphere parameters and perform related calculations.
void beta(const std::vector< realT > &bet)
Set the vector of layer PSD normalizations.
std::vector< realT > m_beta_0
realT r_0(const realT &lam)
Get the value of Fried's parameter r_0 at the specified wavelength.
realT dir_wind()
Get the weighted mean wind direction.
std::vector< realT > alpha()
Get the vector of PSD indices.
realT lam_0()
Get the current value of the reference wavelength.
std::vector< realT > l_0()
Get the vector of inner scales.
void loadLCO()
Load parameters corresponding to the median atmosphere of the GMT site survey at LCO.
void layer_z(const std::vector< realT > &layz)
Set the vector of layer heights.
std::vector< realT > layer_v_wind()
Get the vector of layer windspeeds.
realT v_wind_mean2()
Get the mean-squared wind speed.
realT X(realT k, realT lam_sci, realT secZ)
The fraction of the turbulence PSD in phase after Fresnel propagation.
std::vector< realT > m_beta
iosT & dumpAtmosphere(iosT &ios)
Output current parameters to a stream.
realT h_obs()
Get the height of the observatory.
realT l_0(const size_t &n)
Get the value of the inner scale for a single layer.
error_t validate() const
Validate the complete atmosphere configuration for calculation.
realT layer_dir(const int n)
Get the wind direction of a single layer.
void beta_0(const std::vector< realT > &bet)
Set the vector of layer PSD constants.
realT L_0(const size_t &n)
Get the value of the outer scale for a single layer.
std::vector< realT > m_alpha
std::vector< realT > beta()
Get the vector of PSD normalizations.
realT dY(realT k, realT lam_sci, realT lam_wfs)
The differential fraction of the turbulence PSD in amplitude after Fresnel propagation.
realT tau_0()
Get tau_0 at the reference wavelength.
std::vector< realT > L_0()
Get the vector of outer scales.
void layer_v_wind(const std::vector< realT > &spd)
Set the vector of layer windspeeds.
std::vector< realT > layer_dir()
Get the vector of layer wind directions.
void h_obs(realT nh)
Set the height of the observatory.
void loadGuyon2005()
Load the default atmosphere model from Guyon (2005).
void nonKolmogorov(const bool &nk)
Set the value of m_nonKolmogorov.
void layer_dir(const std::vector< realT > &d)
Set the vector of layer wind directions.
void L_0(const std::vector< realT > &L0)
Set the vector of layer outer scales.
void update_z_mean()
Recalculate m_z_mean.
realT fwhm(realT lam_sci)
_realT realT
The real floating type in which all calculations are performed.
void alpha(const std::vector< realT > &alph)
Set the vector of layer PSD indices.
realT beta_0(const size_t &n)
Return the PSD constant for a single layer.
realT beta(const size_t &n)
Return the PSD normalization for a single layer.
realT fwhm0(realT lam_sci)
realT X_Z(realT k, realT lambda_sci, realT lambda_wfs, realT secZ)
void setupConfig(app::appConfigurator &config)
Setup the configurator to configure this class.
std::vector< realT > m_L_0
void r_0(const realT &r0, const realT &l0)
Set the value of Fried's parameter and the reference wavelength.
void H(realT nH)
Set the atmospheric scale height.
aoAtmosphere()
Constructor.
std::vector< realT > m_layer_dir
std::vector< realT > layer_Cn2()
Get the vector of layer strengths.
void l_0(const std::vector< realT > &l0)
Set the vector of layer inner scales.
realT f_g(realT lam_sci)
Get the greenwood frequency at a specified wavelength.
void tau_0(realT tau_0, realT lam_sci)
Scale v_wind so that tau_0 has the specified value at the specified wavelength.
realT H()
Get the atmospheric scale height.
bool nonKolmogorov()
Return the value of m_nonKolmogorov.
void setSingleLayer(realT r0, realT lam0, realT L0, realT l0, realT lz, realT vw, realT dir)
Set a single layer model.
realT v_wind()
Get the 5/3 moment weighted mean wind speed.
std::vector< realT > layer_z()
Get the vector layer heights.
realT layer_Cn2(const int n)
Get the strength of a single layer.
realT alpha(const size_t &n)
Return the PSD index for a single layer.
std::vector< realT > m_l_0
realT Y(realT k, realT lam_sci, realT secZ)
The fraction of the turbulence PSD in amplitude after Fresnel propagation.
realT layer_v_wind(const int n)
Get the wind speed of a single layer.
realT f_g()
Get the greenwood frequency at the reference wavelength.
realT z_mean()
Get the weighted mean layer height.
std::vector< realT > m_layer_Cn2
std::vector< realT > m_layer_z
size_t n_layers()
Get the number of layers.
std::vector< realT > beta_0()
Get the vector of PSD constants.
error_t layer_Cn2(const std::vector< realT > &cn2, const realT l0=0)
Set the vector layer strengths, possibly calculating r_0.
realT r_0()
Get the value of Fried's parameter r_0 at the reference wavelength lam_0.
std::vector< realT > m_layer_v_wind
realT v_wind_mean()
Get the mean wind speed.
void z_mean(const realT &zm)
Set the weighted mean m_z_mean and renormalize the layer heights.
realT tau_0(realT lam_sci)
Get tau_0 at a specified wavelength.
void v_wind(const realT &vw)
Set the weighted mean m_v_wind and renormalize the layer wind speeds.
error_t loadConfig(app::appConfigurator &config)
Load the configuration of this class from a configurator.
realT dX(realT k, realT lam_sci, realT lam_wfs)
The differential fraction of the turbulence PSD in phase after Fresnel propagation.
realT layer_z(const size_t n)
Get the height of a single layer.
void update_v_wind()
Recalculate m_v_wind.
Floating-point classification utilities that remain reliable under fast-math optimization.
constexpr floatT a_PSD()
The scaling constant for the Kolmorogov optical phase power spectral density.
error_t
The mxlib error codes.
@ noerror
No error has occurred.
@ sizeerr
A size was invalid or calculated incorrectly.
@ invalidconfig
A config setting was invalid.
@ invalidarg
An argument was invalid.
error_t mxlib_error_report(const error_t &code, const std::string &expl, const std::source_location &loc=std::source_location::current())
Print a report to stderr given an mxlib error_t code and explanation and return the code.
bool isFinite(realT value)
Test whether a floating-point value is finite, including under finite-math-only optimization.
constexpr T pi()
Get the value of pi.
constexpr floatT six_fifths()
Return 6/5 in the specified precision.
constexpr floatT five_thirds()
Return 5/3 in the specified precision.
constexpr floatT eleven_thirds()
Return 11/3 in the specified precision.
constexpr floatT three_fifths()
Return 3/5 in the specified precision.
Declarations of some libarary wide utilities.
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.
bool isSet(const std::string &name, std::unordered_map< std::string, configTarget > &targets)
Check if a target has been set by the configuration.