#include <boost/test/unit_test.hpp>
#include <usml/waveq3d/waveq3d.h>
#include <iostream>
#include <iomanip>
#include <fstream>
#include <cstdio>
BOOST_AUTO_TEST_SUITE(eigenray_test)
using namespace boost::unit_test;
using namespace usml::waveq3d;
static const double time_step = 0.100 ;
static const double f0 = 2000 ;
static const double src_lat = 45.0;
static const double src_lng = -45.0;
static const double c0 = 1500.0;
static const double bot_depth = 1e5 ;
BOOST_AUTO_TEST_CASE( eigenray_basic ) {
cout << "=== eigenray_test: eigenray_basic ===" << endl;
const char* csvname = USML_TEST_DIR "/waveq3d/test/eigenray_basic.csv";
const char* ncname = USML_TEST_DIR "/waveq3d/test/eigenray_basic.nc";
const char* ncname_wave = USML_TEST_DIR "/waveq3d/test/eigenray_basic_wave.nc";
const double src_alt = -1000.0;
const double trg_lat = 45.02;
const double time_max = 3.5;
wposition::compute_earth_radius( src_lat );
attenuation_model* attn = new attenuation_constant(0.0);
profile_model* profile = new profile_linear(c0,attn);
boundary_model* surface = new boundary_flat();
boundary_model* bottom = new boundary_flat(3000.0);
ocean_model ocean( surface, bottom, profile );
seq_log freq( 10e3, 1.0, 1 );
wposition1 pos( src_lat, src_lng, src_alt );
seq_linear de( -60.0, 5.0, 60.0 );
seq_linear az( -4.0, 1.0, 4.0 );
wposition target( 1, 1, trg_lat, src_lng, src_alt );
proploss loss(freq, pos, de, az, time_step, &target);
wave_queue wave( ocean, freq, pos, de, az, time_step, &target) ;
wave.addEigenrayListener(&loss);
cout << "propagate wavefronts for " << time_max << " seconds" << endl;
cout << "writing wavefronts to " << ncname_wave << endl;
wave.init_netcdf( ncname_wave );
wave.save_netcdf();
while ( wave.time() < time_max ) {
wave.step();
wave.save_netcdf();
}
wave.close_netcdf();
loss.sum_eigenrays();
cout << "writing proploss to " << ncname << endl;
loss.write_netcdf(ncname,"eigenray_basic test");
cout << "writing tables to " << csvname << endl;
std::ofstream os(csvname);
os << "time,intensity,phase,s_de,s_az,t_de,t_az,srf,btm,cst"
<< endl;
os << std::setprecision(18);
cout << std::setprecision(18);
const eigenray_list *raylist = loss.eigenrays(0,0);
int n=0;
BOOST_CHECK_EQUAL( raylist->size(), 3 ) ;
for ( eigenray_list::const_iterator iter = raylist->begin();
iter != raylist->end(); ++n, ++iter )
{
const eigenray &ray = *iter ;
cout << "ray #" << n
<< " tl=" << ray.intensity(0)
<< " t=" << ray.time
<< " de=" << -ray.target_de
<< " error:" ;
os << ray.time
<< "," << ray.intensity(0)
<< "," << ray.phase(0)
<< "," << ray.source_de
<< "," << ray.source_az
<< "," << ray.target_de
<< "," << ray.target_az
<< "," << ray.surface
<< "," << ray.bottom
<< "," << ray.caustic
<< endl;
switch (n) {
case 0 :
cout << " tl=" << (ray.intensity(0)-66.9506)
<< " t=" << (ray.time-1.484018789)
<< " de=" << max( abs(ray.source_de+0.01),
abs(ray.target_de-0.01) ) << endl ;
BOOST_CHECK_SMALL( ray.intensity(0)-66.9506, 0.1 );
BOOST_CHECK_SMALL( ray.time-1.484018789, 0.002 );
BOOST_CHECK_SMALL( ray.phase(0)-0.0, 1e-6 );
BOOST_CHECK_SMALL( ray.source_de+0.01, 0.01 );
BOOST_CHECK_SMALL( ray.target_de-0.01, 0.01 );
break;
case 1 :
cout << " tl=" << (ray.intensity(0)-69.5211)
<< " t=" << (ray.time-1.995102731)
<< " de=" << max( abs(ray.source_de-41.93623171),
abs(ray.target_de+41.93623171) ) << endl ;
BOOST_CHECK_SMALL( ray.intensity(0)-69.5211, 0.1 );
BOOST_CHECK_SMALL( ray.time-1.995102731, 0.002 );
BOOST_CHECK_SMALL( ray.phase(0)+M_PI, 1e-6 );
BOOST_CHECK_SMALL( ray.source_de-41.93623171, 0.01 );
BOOST_CHECK_SMALL( ray.target_de+41.93623171, 0.01 );
break;
case 2 :
cout << " tl=" << (ray.intensity(0)-73.2126)
<< " t=" << (ray.time-3.051676949)
<< " de=" << max( abs(ray.source_de+60.91257162),
abs(ray.target_de-60.91257162) ) << endl ;
BOOST_CHECK_SMALL( ray.time-3.051676949, 0.02 );
BOOST_CHECK_SMALL( ray.phase(0)-0.0, 1e-6 );
break;
default :
break;
}
BOOST_CHECK_SMALL( ray.source_az-0.0, 1e-6 );
BOOST_CHECK_SMALL( ray.target_az-0.0, 1e-6 );
}
}
BOOST_AUTO_TEST_CASE( eigenray_concave ) {
cout << "=== eigenray_test: eigenray_concave ===" << endl;
const char* ncname_wave = USML_TEST_DIR "/waveq3d/test/eigenray_concave_wave.nc";
const char* ncname = USML_TEST_DIR "/waveq3d/test/eigenray_concave.nc";
const double src_alt = -200.0;
const double time_max = 120.0 ;
const double trg_lat = 46.2;
const double trg_lng = src_lng ;
const double trg_alt = -150.0;
wposition::compute_earth_radius( src_lat );
attenuation_model* attn = new attenuation_constant(0.0);
profile_model* profile = new profile_linear(c0,attn);
boundary_model* surface = new boundary_flat();
boundary_model* bottom = new boundary_flat(bot_depth);
ocean_model ocean( surface, bottom, profile );
seq_log freq( f0, 1.0, 1 );
wposition1 pos( src_lat, src_lng, src_alt );
seq_linear de( -1.0, 0.05, 1.0 );
seq_linear az( -4.0, 1.0, 4.0 );
wposition target( 1, 1, trg_lat, trg_lng, trg_alt );
proploss loss(freq, pos, de, az, time_step, &target);
wave_queue wave( ocean, freq, pos, de, az, time_step, &target) ;
wave.addEigenrayListener(&loss);
cout << "propagate wavefronts" << endl;
cout << "writing wavefronts to " << ncname_wave << endl;
wave.init_netcdf(ncname_wave);
wave.save_netcdf();
while (wave.time() < time_max) {
wave.step();
wave.save_netcdf();
}
wave.close_netcdf();
cout << "writing eigenrays to " << ncname << endl;
loss.sum_eigenrays();
loss.write_netcdf(ncname);
eigenray_list *raylist = loss.eigenrays(0,0);
BOOST_CHECK_EQUAL( raylist->size(), 4 ) ;
for ( eigenray_list::iterator iter=raylist->begin();
iter != raylist->end(); ++iter )
{
eigenray ray = *iter ;
double theory_t, theory_sde, theory_tde ;
if ( ray.surface == 0 ) {
cout << "direct: " ;
theory_t = 89.05102557 ;
theory_sde = -0.578554378 ;
theory_tde = 0.621445622 ;
} else {
if ( ray.source_de > 0.0 ) {
cout << "surf1: " ;
theory_t = 89.05369537 ;
theory_sde = 0.337347599 ;
theory_tde = 0.406539112 ;
} else {
if ( ray.source_de > -0.1 ) {
cout << "surf2: " ;
theory_t = 89.05379297 ;
theory_sde = -0.053251329 ;
theory_tde = 0.233038477 ;
} else {
cout << "surf3: " ;
theory_t = 89.05320459 ;
theory_sde = -0.433973977 ;
theory_tde = -0.48969753 ;
}
}
}
cout << "t = "<< ray.time
<< " sde = "<< ray.source_de
<< " tde = "<< ray.target_de
<< " error: t = "<< (ray.time-theory_t)
<< " sde = "<< (ray.source_de-theory_sde)
<< " tde = "<< (ray.target_de-theory_tde) << endl ;
BOOST_CHECK_SMALL( ray.time - theory_t, 2e-5 );
BOOST_CHECK_SMALL( ray.source_de - theory_sde, 0.05 );
BOOST_CHECK_SMALL( ray.target_de - theory_tde, 0.10 );
}
}
BOOST_AUTO_TEST_CASE( eigenray_tl_az ) {
cout << "=== eigenray_test: eigenray_tl_az ===" << endl;
const char* csvname = USML_TEST_DIR "/waveq3d/test/eigenray_tl_az.csv";
const char* ncname = USML_TEST_DIR "/waveq3d/test/eigenray_tl_az.nc";
const char* ncname_wave = USML_TEST_DIR "/waveq3d/test/eigenray_tl_az_wave.nc";
const double src_alt = -1000.0 ;
const double target_range = 2222.4 ;
const double time_max = 1.8 ;
const int num_targets = 100 ;
const double angle_sprd = 16.0 ;
const double az_start = -8.0 ;
const double az_inc = 1.0 ;
const double tar_ang_sprd = 6.0 ;
const double tar_bearing = 0.0 ;
wposition::compute_earth_radius( 0.0 );
attenuation_model* attn = new attenuation_constant(0.0);
profile_model* profile = new profile_linear(c0,attn);
boundary_model* surface = new boundary_flat();
boundary_model* bottom = new boundary_flat(3000.0);
ocean_model ocean( surface, bottom, profile );
seq_log freq( 1000.0, 1.0, 1 );
wposition1 pos( 0.0, 0.0, src_alt );
seq_linear de( -60.0, 1.0, 60.0 ) ;
seq_linear az( az_start, az_inc, az_start+angle_sprd );
wposition target( num_targets, 1, 0.0, 0.0, src_alt ) ;
double angle = (tar_ang_sprd*M_PI/180.0)/num_targets;
double bearing_inc = (tar_bearing*M_PI/180.0) ;
for (size_t n = 0; n < num_targets; ++n) {
wposition1 aTarget( pos, target_range, bearing_inc) ;
target.latitude( n, 0, aTarget.latitude());
target.longitude( n, 0, aTarget.longitude());
target.altitude( n, 0, aTarget.altitude());
bearing_inc = bearing_inc + angle;
}
proploss loss(freq, pos, de, az, time_step, &target);
wave_queue wave( ocean, freq, pos, de, az, time_step, &target) ;
wave.addEigenrayListener(&loss);
cout << "propagate wavefronts for " << time_max << " seconds" << endl;
cout << "writing wavefronts to " << ncname_wave << endl;
wave.init_netcdf( ncname_wave );
wave.save_netcdf();
while ( wave.time() < time_max ) {
wave.step();
wave.save_netcdf();
}
wave.close_netcdf();
loss.sum_eigenrays();
cout << "writing proploss to " << ncname << endl;
loss.write_netcdf(ncname,"eigenray_tl_az test");
cout << "writing tables to " << csvname << endl;
std::ofstream os(csvname);
os << std::setprecision(18);
cout << std::setprecision(18);
for ( int i=0; i < num_targets; ++i ) {
os << (tar_bearing+(tar_ang_sprd*i)/num_targets) << "," ;
const eigenray_list *raylist = loss.eigenrays(i,0);
int n=0;
for ( eigenray_list::const_iterator iter = raylist->begin();
iter != raylist->end(); ++n, ++iter )
{
const eigenray &ray = *iter ;
os << ray.intensity(0) << "," ;
}
os << "," << (20*log10(target_range))
<< "," << (20*log10(2.0*sqrt((target_range*target_range)/4.0 + src_alt*src_alt)))
<< endl ;
}
}
BOOST_AUTO_TEST_CASE( eigenray_branch_pt ) {
cout << "=== eigenray_test: eigenray_branch_pt ===" << endl;
const char* csvname = USML_TEST_DIR "/waveq3d/test/eigenray_branch_pt.csv";
const char* ncname = USML_TEST_DIR "/waveq3d/test/eigenray_branch_pt.nc";
const char* ncname_wave = USML_TEST_DIR "/waveq3d/test/eigenray_branch_pt_wave.nc";
const double src_alt = -1000.0;
const double target_range = 2226.0;
const double time_max = 3.5;
const int num_targets = 12 ;
wposition::compute_earth_radius( 0.0 );
attenuation_model* attn = new attenuation_constant(0.0);
profile_model* profile = new profile_linear(c0,attn);
boundary_model* surface = new boundary_flat();
boundary_model* bottom = new boundary_flat(3000.0);
ocean_model ocean( surface, bottom, profile );
seq_log freq( 1000.0, 1.0, 1 );
wposition1 pos( 0.0, 0.0, src_alt );
seq_linear de( -90.0, 1.0, 90.0 );
seq_linear az( 0.0, 15.0, 360.0 );
wposition target( num_targets+2, 1, 0.0, 0.0, src_alt ) ;
target.altitude( 0, 0, src_alt-500 ) ;
target.altitude( 1, 0, src_alt+500 ) ;
double angle = TWO_PI/num_targets;
double bearing_inc = 0 ;
for (size_t n = 2; n < num_targets+2; ++n) {
wposition1 aTarget( pos, target_range, bearing_inc) ;
target.latitude( n, 0, aTarget.latitude());
target.longitude( n, 0, aTarget.longitude());
target.altitude( n, 0, aTarget.altitude());
bearing_inc = bearing_inc + angle;
}
proploss loss(freq, pos, de, az, time_step, &target);
wave_queue wave( ocean, freq, pos, de, az, time_step, &target) ;
wave.addEigenrayListener(&loss);
cout << "propagate wavefronts for " << time_max << " seconds" << endl;
cout << "writing wavefronts to " << ncname_wave << endl;
wave.init_netcdf( ncname_wave );
wave.save_netcdf();
while ( wave.time() < time_max ) {
wave.step();
wave.save_netcdf();
}
wave.close_netcdf();
loss.sum_eigenrays();
cout << "writing proploss to " << ncname << endl;
loss.write_netcdf(ncname,"eigenray_az_branch_pt test");
cout << "writing tables to " << csvname << endl;
std::ofstream os(csvname);
os << "target,time,intensity,phase,s_de,s_az,t_de,t_az,srf,btm,cst"
<< endl;
os << std::setprecision(18);
cout << std::setprecision(18);
for ( int i=0; i < num_targets; ++i ) {
os << "#" << i ;
const eigenray_list *raylist = loss.eigenrays(i,0) ;
int n=0 ;
BOOST_CHECK_EQUAL( raylist->size(), 3) ;
for ( eigenray_list::const_iterator iter = raylist->begin();
iter != raylist->end(); ++n, ++iter )
{
const eigenray &ray = *iter ;
os << "," << ray.time
<< "," << ray.intensity(0)
<< "," << ray.phase(0)
<< "," << ray.source_de
<< "," << ray.source_az
<< "," << ray.target_de
<< "," << ray.target_az
<< "," << ray.surface
<< "," << ray.bottom
<< "," << ray.caustic
<< endl;
if ( i > 1 ) {
switch (n) {
case 0 :
BOOST_CHECK_SMALL( ray.intensity(0)-66.9506, 0.1 );
BOOST_CHECK_SMALL( ray.time-1.484018789, 0.002 );
BOOST_CHECK_SMALL( ray.phase(0)-0.0, 1e-6 );
BOOST_CHECK_SMALL( ray.source_de+0.01, 0.01 );
BOOST_CHECK_SMALL( ray.target_de-0.01, 0.01 );
break;
case 1 :
BOOST_CHECK_SMALL( ray.intensity(0)-69.5211, 0.1 );
BOOST_CHECK_SMALL( ray.time-1.995102731, 0.002 );
BOOST_CHECK_SMALL( ray.phase(0)+M_PI, 1e-6 );
BOOST_CHECK_SMALL( ray.source_de-41.93623171, 0.01 );
BOOST_CHECK_SMALL( ray.target_de+41.93623171, 0.01 );
break;
case 2 :
BOOST_CHECK_SMALL( ray.time-3.051676949, 0.02 );
BOOST_CHECK_SMALL( ray.phase(0)-0.0, 1e-6 );
BOOST_CHECK_SMALL( ray.source_de+60.91257162, 1.0 );
BOOST_CHECK_SMALL( ray.target_de-60.91257162, 1.0 );
break;
default :
break;
}
}
}
}
}
BOOST_AUTO_TEST_SUITE_END()