4#include "../../../catch2/catch.hpp"
6#define MX_NO_ERROR_REPORTS
14using namespace mx::app;
15using namespace mx::AO::analysis;
23TEST_CASE(
"Loading aoAtmosphere config settings",
"[ao::analysis::aoAtmosphere]" )
25 GIVEN(
"a valid config file" )
30 WHEN(
"all normal settings" )
36 {
"atm",
"atm",
"atm",
"atm",
"atm",
"atm",
"atm",
"atm",
"atm",
"atm" },
37 {
"r_0",
"lam_0",
"L_0",
"l_0",
"layer_z",
"h_obs",
"H",
"layer_Cn2",
"layer_v_wind",
"layer_dir" },
53 REQUIRE( atm.
r_0() == 0.25 );
54 REQUIRE( atm.
lam_0() == 0.4e-9 );
56 REQUIRE( atm.
L_0( 0 ) == 10 );
57 REQUIRE( atm.
L_0( 1 ) == 15 );
58 REQUIRE( atm.
L_0( 2 ) == 22.5 );
60 REQUIRE( atm.
l_0( 0 ) == 0.1 );
61 REQUIRE( atm.
l_0( 1 ) == 0.01 );
62 REQUIRE( atm.
l_0( 2 ) == 0.001 );
64 REQUIRE( atm.
layer_z( 0 ) == 1000 );
65 REQUIRE( atm.
layer_z( 1 ) == 2000 );
66 REQUIRE( atm.
layer_z( 2 ) == 5000 );
68 REQUIRE( atm.
h_obs() == 3002 );
70 REQUIRE( atm.
H() == 2.3 );
72 REQUIRE( atm.
layer_Cn2( 0 ) == Approx( 0.2 ) );
73 REQUIRE( atm.
layer_Cn2( 1 ) == Approx( 0.2 ) );
74 REQUIRE( atm.
layer_Cn2( 2 ) == Approx( 0.6 ) );
80 REQUIRE( atm.
layer_dir( 0 ) == Approx( 0.1 ) );
81 REQUIRE( atm.
layer_dir( 1 ) == Approx( 0.6 ) );
82 REQUIRE( atm.
layer_dir( 2 ) == Approx( 1.6 ) );
84 REQUIRE( atm.
v_wind() == Approx( 19.278644205193533 ) );
85 REQUIRE( atm.
z_mean() == Approx( 3886.4496373530733 ) );
89 WHEN(
"setting v_wind and z_mean" )
91 atm.
L_0( { 25.0, 25.0, 25.0 } );
92 atm.
l_0( { 0.0, 0.0, 0.0 } );
96 {
"atm",
"atm",
"atm",
"atm",
"atm",
"atm" },
97 {
"layer_z",
"layer_Cn2",
"layer_v_wind",
"layer_dir",
"v_wind",
"z_mean" },
98 {
"1000,2000,5000",
"1,1,3.0",
"10.5,11.2,23.7",
"0.1,0.6,1.6",
"15.0",
"5001.0" } );
104 REQUIRE( atm.
v_wind() == Approx( 15.0 ) );
105 REQUIRE( atm.
z_mean() == Approx( 5001.0 ) );
109 WHEN(
"setting nonKolmogorov to false" )
113 writeConfigFile(
"aoAtmosphere.conf", {
"atm" }, {
"nonKolmogorov" }, {
"false" } );
121 WHEN(
"setting nonKolmogorov to false" )
125 writeConfigFile(
"aoAtmosphere.conf", {
"atm" }, {
"nonKolmogorov" }, {
"true" } );
134 WHEN(
"setting nonKolmogorov alpha" )
141 writeConfigFile(
"aoAtmosphere.conf", {
"atm" }, {
"alpha" }, {
"4.7" } );
147 REQUIRE( atm.
alpha( 0 ) == Approx( 4.7 ) );
151 WHEN(
"setting nonKolmogorov beta" )
158 writeConfigFile(
"aoAtmosphere.conf", {
"atm" }, {
"beta" }, {
"0.026" } );
164 REQUIRE( atm.
beta( 0 ) == Approx( 0.026 ) );
168 WHEN(
"setting nonKolmogorov beta_0" )
175 writeConfigFile(
"aoAtmosphere.conf", {
"atm" }, {
"beta_0" }, {
"1e-7" } );
181 REQUIRE( atm.
beta_0( 0 ) == Approx( 1e-7 ) );
185 GIVEN(
"command line options" )
190 WHEN(
"setting nonKolmogorov to true" )
193 std::vector<std::string> argvs( 2 );
196 argvs[1] =
"--atm.nonKolmogorov=true";
199 argv[0] = (
char *)argvs[0].data();
200 argv[1] = (
char *)argvs[1].data();
209 WHEN(
"setting nonKolmogorov to true" )
212 std::vector<std::string> argvs( 2 );
215 argvs[1] =
"--atm.nonKolmogorov=false";
218 argv[0] = (
char *)argvs[0].data();
219 argv[1] = (
char *)argvs[1].data();
236TEST_CASE(
"Atmosphere layer-strength normalization is transactional",
"[ao::analysis::aoAtmosphere]" )
239 atmosphere.
setSingleLayer( 0.2, 0.5e-6, 25.0, 0.0, 0.0, 10.0, 0.0 );
240 const std::vector<realT> originalStrength = atmosphere.
layer_Cn2();
242 SECTION(
"empty strengths" )
247 SECTION(
"negative strength" )
252 SECTION(
"nonfinite strength" )
257 SECTION(
"nonfinite sum" )
259 REQUIRE( atmosphere.
layer_Cn2( { std::numeric_limits<realT>::max(), std::numeric_limits<realT>::max() } ) ==
263 SECTION(
"zero sum" )
268 SECTION(
"invalid reference wavelength" )
273 REQUIRE( atmosphere.
layer_Cn2() == originalStrength );
282TEST_CASE(
"Atmosphere validation rejects mismatched layer vectors",
"[ao::analysis::aoAtmosphere]" )
285 atmosphere.
setSingleLayer( 0.2, 0.5e-6, 25.0, 0.0, 0.0, 10.0, 0.0 );
287 SECTION(
"layer strengths" )
292 SECTION(
"outer scales" )
294 atmosphere.
L_0( { 25.0, 25.0 } );
297 SECTION(
"inner scales" )
299 atmosphere.
l_0( { 0.0, 0.0 } );
302 SECTION(
"layer heights" )
304 atmosphere.
layer_z( { 0.0, 0.0 } );
307 SECTION(
"wind speeds" )
312 SECTION(
"wind directions" )
317 SECTION(
"non-Kolmogorov exponents" )
319 atmosphere.
alpha( { 11.0 / 3.0, 11.0 / 3.0 } );
322 SECTION(
"non-Kolmogorov normalizations" )
324 atmosphere.
beta( { 1.0, 1.0 } );
327 SECTION(
"non-Kolmogorov constants" )
329 atmosphere.
beta_0( { 0.0, 0.0 } );
340TEST_CASE(
"Atmosphere validation rejects invalid physical values",
"[ao::analysis::aoAtmosphere]" )
343 atmosphere.
setSingleLayer( 0.2, 0.5e-6, 25.0, 0.0, 0.0, 10.0, 0.0 );
345 SECTION(
"invalid Fried parameter" )
347 atmosphere.
r_0( 0.0, 0.5e-6 );
350 SECTION(
"invalid observatory height" )
352 atmosphere.
h_obs( -1.0 );
355 SECTION(
"invalid atmospheric scale height" )
360 SECTION(
"nonfinite outer scale" )
362 atmosphere.
L_0( std::vector<realT>{ std::numeric_limits<realT>::infinity() } );
365 SECTION(
"negative inner scale" )
367 atmosphere.
l_0( std::vector<realT>{ -1.0 } );
370 SECTION(
"negative layer height" )
372 atmosphere.
layer_z( std::vector<realT>{ -1.0 } );
375 SECTION(
"negative wind speed" )
380 SECTION(
"nonfinite wind direction" )
382 atmosphere.
layer_dir( std::vector<realT>{ std::numeric_limits<realT>::quiet_NaN() } );
385 SECTION(
"invalid non-Kolmogorov normalization" )
388 atmosphere.
beta( std::vector<realT>{ 0.0 } );
400TEST_CASE(
"Atmosphere validation accepts supported physical conventions",
"[ao::analysis::aoAtmosphere]" )
403 atmosphere.
setSingleLayer( 0.2, 0.5e-6, 25.0, 0.0, 0.0, 10.0, 0.0 );
405 SECTION(
"static layer" )
410 SECTION(
"infinite outer scale" )
412 atmosphere.
L_0( std::vector<realT>{ 0.0 } );
415 SECTION(
"non-Kolmogorov model without a Fried parameter" )
417 atmosphere.
r_0( 0.0, 0.5e-6 );
430TEST_CASE(
"Atmosphere configuration propagates invalid layer strengths",
"[ao::analysis::aoAtmosphere]" )
433 atmosphere.
setSingleLayer( 0.2, 0.5e-6, 25.0, 0.0, 0.0, 10.0, 0.0 );
436 writeConfigFile(
"aoAtmosphere.conf", {
"atm" }, {
"layer_Cn2" }, {
"0,0" } );
442 REQUIRE( atmosphere.
layer_Cn2() == std::vector<realT>{ 1.0 } );
Provides a class to specify atmosphere parameters.
void writeConfigFile(const std::string &fname, const std::vector< std::string > §ions, const std::vector< std::string > &keywords, const std::vector< std::string > &values)
A simple config file writing function, useful for testing.
A class to specify atmosphere parameters and perform related calculations.
realT lam_0()
Get the current value of the reference wavelength.
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.
realT L_0(const size_t &n)
Get the value of the outer scale for a single layer.
void nonKolmogorov(const bool &nk)
Set the value of m_nonKolmogorov.
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.
void setupConfig(app::appConfigurator &config)
Setup the configurator to configure this class.
realT H()
Get the atmospheric scale height.
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.
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.
realT layer_v_wind(const int n)
Get the wind speed of a single layer.
realT z_mean()
Get the weighted mean layer height.
realT r_0()
Get the value of Fried's parameter r_0 at the reference wavelength lam_0.
error_t loadConfig(app::appConfigurator &config)
Load the configuration of this class from a configurator.
realT layer_z(const size_t n)
Get the height of a single layer.
TEST_CASE("Loading aoAtmosphere config settings", "[ao::analysis::aoAtmosphere]")
Verify parsing and validation of atmosphere configuration settings.
@ noerror
No error has occurred.
@ sizeerr
A size was invalid or calculated incorrectly.
@ invalidconfig
A config setting was invalid.
@ invalidarg
An argument was invalid.
Class to manage a set of configurable values, and read their values from config/ini files and the com...
int readConfig(const std::string &fname, bool reportFileNotFound=true)
Read and parse a config/ini file, updating the targets.
void parseCommandLine(int argc, char **argv, const std::string &oneTarget="")
Parse the command line, updating the targets.