diff --git a/include/ITAPropagationPathSim/AtmosphericRayTracing/Simulation/ARTEngine.h b/include/ITAPropagationPathSim/AtmosphericRayTracing/Simulation/ARTEngine.h index e72f1c81e119b700727be7d66b57118f6da5f08c..fb3027c4559df55235ea0dbef5ad7a2470924e71 100644 --- a/include/ITAPropagationPathSim/AtmosphericRayTracing/Simulation/ARTEngine.h +++ b/include/ITAPropagationPathSim/AtmosphericRayTracing/Simulation/ARTEngine.h @@ -47,16 +47,22 @@ namespace ITAPropagationPathSim Simulation::Settings settings; public: - inline CEngine( ) { pExternalWatcher = std::make_shared<CAbortAtMaxTime>( ); }; - inline CEngine( std::shared_ptr<IExternalWatcher> pWatcher ) : pExternalWatcher( pWatcher ) { }; + CEngine( bool bSuppressWarnings = false ); + CEngine( std::shared_ptr<IExternalWatcher> pWatcher, bool bSuppressWarnings = false ); public: + // Initializes rays with given source position and initial direction, traces and returns them std::vector<std::shared_ptr<CRay>> Run( const ITAGeo::CStratifiedAtmosphere& atmosphere, const VistaVector3D& m_v3SourcePosition, const std::vector<VistaVector3D>& v3RayDirections ) const; - void Run( const ITAGeo::CStratifiedAtmosphere& atmosphere, const std::set<std::shared_ptr<CRay>>& rays ) const; + // Traces given rays and returns true if all rays were inside valid bounds of atmosphere + bool Run( const ITAGeo::CStratifiedAtmosphere& atmosphere, const std::set<std::shared_ptr<CRay>>& rays ) const; private: - void TraceRays( const ITAGeo::CStratifiedAtmosphere& atmosphere, const std::vector<std::shared_ptr<CRay>>& rays ) const; + // Traces rays and returns true if all rays were inside valid bounds of atmosphere + bool TraceRays( const ITAGeo::CStratifiedAtmosphere& atmosphere, const std::vector<std::shared_ptr<CRay>>& rays ) const; + + bool m_bSuppressWarnings; // If set to true, suppresses out of atmosphere bounds warning + bool m_bOutOfAtmosphereBounds = false; // Indicates whether last Run() call used data above the specified limit of the atmosphere }; } // namespace Simulation } // namespace AtmosphericRayTracing diff --git a/src/ITAPropagationPathSim/AtmosphericRayTracing/EigenraySearch/EigenrayEngine.cpp b/src/ITAPropagationPathSim/AtmosphericRayTracing/EigenraySearch/EigenrayEngine.cpp index ddb63f4464c18f2ff2426c76445b89250667d219..5864361dcf62b795903a2f71076128a2f870cf24 100644 --- a/src/ITAPropagationPathSim/AtmosphericRayTracing/EigenraySearch/EigenrayEngine.cpp +++ b/src/ITAPropagationPathSim/AtmosphericRayTracing/EigenraySearch/EigenrayEngine.cpp @@ -34,16 +34,20 @@ std::vector<std::shared_ptr<CRay>> ITAPropagationPathSim::AtmosphericRayTracing: RayVector eigenrays; bool bAccuracyReached = true; + bool bRaysInsideAtmosphereBounds = true; for( int reflectionOrder = 0; reflectionOrder < initialRayGrids.size( ); reflectionOrder++ ) { CAdaptiveWorker worker( initialRayGrids[reflectionOrder], receiverPosition, simulationSettings, eigenraySettings, reflectionOrder ); eigenrays.push_back( worker.Run( atmosphere ) ); viTotalNumRaysTraced.push_back( worker.TotalNumRaysTraced( ) ); bAccuracyReached &= eigenrays.back( )->ReceiverHit( ); + bRaysInsideAtmosphereBounds &= worker.RaysInsideAtmosphereBounds( ); } if( !bAccuracyReached ) ART_WARN( "EigenraySearch::Engine: Could not find eigenray(s) with proper accuracy. Abort criterion reached." ); + if( !bRaysInsideAtmosphereBounds ) + ART_WARN( "EigenraySearch::Engine: Maximum altitude of atmosphere exceeded for at least one ray during eigenray search. Results should be treated with care." ); return eigenrays; } diff --git a/src/ITAPropagationPathSim/AtmosphericRayTracing/EigenraySearch/Worker.cpp b/src/ITAPropagationPathSim/AtmosphericRayTracing/EigenraySearch/Worker.cpp index 70c4a7d53dc1ba8ff161e91952845a59e05dc5ce..180fd3d0acb6ff4d3e34776241079bf0374be93e 100644 --- a/src/ITAPropagationPathSim/AtmosphericRayTracing/EigenraySearch/Worker.cpp +++ b/src/ITAPropagationPathSim/AtmosphericRayTracing/EigenraySearch/Worker.cpp @@ -62,6 +62,7 @@ EigenraySearch::CWorkerBase::CWorkerBase( const VistaVector3D& sourcePosition, c , m_v3ReceiverPosition( receiverPosition ) , m_rayTracingAbortSettings( abortSettings ) , m_v3MirroredReceiverPosition( receiverPosition ) + , m_simulationEngine( Simulation::CEngine(true) ) //Suppress warnings in simulation engine to catch them in this one { m_simulationEngine.settings = simSettings; m_v3MirroredReceiverPosition[Vista::Z] = -m_v3MirroredReceiverPosition[Vista::Z]; @@ -76,7 +77,7 @@ const VistaVector3D& EigenraySearch::CWorkerBase::VirtualReceiverPosition( const void EigenraySearch::CWorkerBase::RunRayTracing( const ITAGeo::CStratifiedAtmosphere& atmosphere, const std::set<RayPtr>& rays ) { m_pSimulationWatcher->InitRayReceiverDistances( rays ); - m_simulationEngine.Run( atmosphere, rays ); + m_bRaysInsideAtmosphereBounds &= m_simulationEngine.Run( atmosphere, rays ); m_iTotalNumRaysTraced += int( rays.size( ) ); } EigenraySearch::RayPtr EigenraySearch::CWorkerBase::FindMinimumDistanceRay( const std::set<RayPtr>& rays, const int reflectionOrder ) const @@ -265,7 +266,7 @@ void EigenraySearch::CAdaptiveWorker::CalculateEigenraySpreadingLoss( const ITAG dDeltaPhi *= 10; m_adaptiveRayGrid.ZoomIntoRay( m_pMinDistanceRay, m_rayAdaptationSettings.accuracy.maxAngleForGeomSpreading, dDeltaPhi ); - auto tmpSimulationEngine = Simulation::CEngine( std::make_shared<Simulation::CAbortAtMaxTime>( time ) ); + auto tmpSimulationEngine = Simulation::CEngine( std::make_shared<Simulation::CAbortAtMaxTime>( time ), true ); tmpSimulationEngine.settings = m_simulationEngine.settings; tmpSimulationEngine.Run( atmosphere, m_adaptiveRayGrid.NewRaysOfLastAdaptation( ) ); } diff --git a/src/ITAPropagationPathSim/AtmosphericRayTracing/EigenraySearch/Worker.h b/src/ITAPropagationPathSim/AtmosphericRayTracing/EigenraySearch/Worker.h index 4be890aef4f24c8579ea34ffdae3eaa6aa434e2a..5487e7e12d69a667e0554809ebbfa4af63dc5406 100644 --- a/src/ITAPropagationPathSim/AtmosphericRayTracing/EigenraySearch/Worker.h +++ b/src/ITAPropagationPathSim/AtmosphericRayTracing/EigenraySearch/Worker.h @@ -93,6 +93,7 @@ namespace ITAPropagationPathSim RayTracingAbortSettings m_rayTracingAbortSettings; VistaVector3D m_v3SourcePosition; int m_iTotalNumRaysTraced = 0; + bool m_bRaysInsideAtmosphereBounds = true; private: VistaVector3D m_v3ReceiverPosition; @@ -103,6 +104,7 @@ namespace ITAPropagationPathSim const RayTracingAbortSettings& abortSettings ); // Returns the total number of rays traced by this worker inline int TotalNumRaysTraced( ) { return m_iTotalNumRaysTraced; }; + inline bool RaysInsideAtmosphereBounds( ) { return m_bRaysInsideAtmosphereBounds; }; protected: inline const VistaVector3D& ReceiverPosition( ) const { return m_v3ReceiverPosition; }; diff --git a/src/ITAPropagationPathSim/AtmosphericRayTracing/Simulation/ARTEngine.cpp b/src/ITAPropagationPathSim/AtmosphericRayTracing/Simulation/ARTEngine.cpp index 2cec7428430efaed4988e4156257768a6bd842c1..9e0f672560dc8add54f0680849762d1171837ac4 100644 --- a/src/ITAPropagationPathSim/AtmosphericRayTracing/Simulation/ARTEngine.cpp +++ b/src/ITAPropagationPathSim/AtmosphericRayTracing/Simulation/ARTEngine.cpp @@ -3,9 +3,11 @@ // ITA includes #include "AdaptiveSolver.h" +#include <ART_instrumentation.h> #include <ITAPropagationPathSim/AtmosphericRayTracing/ODESolver/ODESolver.h> // STD +#include <algorithm> #include <cmath> // OMP @@ -90,7 +92,8 @@ namespace ITAPropagationPathSim while( !rExternalWatcher.AbortRequested( pRay ) ) ExtendRayByOnePeriod( ); }; - inline void CalculateRay( const ITAGeo::CStratifiedAtmosphere& atmosphere ) + //Calculates the path using given atmosphere for initialized ray and returns its maximum altitude + inline double CalculateRay( const ITAGeo::CStratifiedAtmosphere& atmosphere ) { VistaVector3D r = pRay->LastPoint( ); double rz = r[Vista::Z]; @@ -100,6 +103,7 @@ namespace ITAPropagationPathSim VistaVector3D s = ODESolver::NormalToSlowness( n, rz, atmosphere ); VistaVector3D rNew, sNew; + double rzMax = rz; while( !rExternalWatcher.AbortRequested( pRay ) ) { solver.Process( r, s, atmosphere, rNew, sNew ); @@ -121,12 +125,12 @@ namespace ITAPropagationPathSim } if( rExternalWatcher.AbortRequested( pRay ) ) - return; + return rzMax; if( pRay->ReflectionOrder( ) >= 2 ) // Ray is periodic { ExtendRayPeriodically( ); - return; + return rzMax; } } @@ -135,14 +139,18 @@ namespace ITAPropagationPathSim time += dt; pRay->Append( r, n, time ); rExternalWatcher.ProcessRay( pRay ); + + rzMax = std::max( rzMax, (double)r[Vista::Z] ); } + return rzMax; }; public: - inline void TraceRay( const ITAGeo::CStratifiedAtmosphere& atmosphere ) + inline double TraceRay( const ITAGeo::CStratifiedAtmosphere& atmosphere ) { - CalculateRay( atmosphere ); + const double rzMax = CalculateRay( atmosphere ); rExternalWatcher.FinalizeRay( pRay ); + return rzMax; }; }; } // namespace Simulation @@ -150,6 +158,17 @@ namespace ITAPropagationPathSim } // namespace ITAPropagationPathSim +CEngine::CEngine( bool bSuppressWarnings ) : m_bSuppressWarnings( bSuppressWarnings ) +{ + pExternalWatcher = std::make_shared<CAbortAtMaxTime>( ); +} + +CEngine::CEngine( std::shared_ptr<IExternalWatcher> pWatcher, bool bSuppressWarnings ) + : pExternalWatcher( pWatcher ) + , m_bSuppressWarnings( bSuppressWarnings ) +{ +} + std::vector<std::shared_ptr<CRay>> CEngine::Run( const ITAGeo::CStratifiedAtmosphere& atmosphere, const VistaVector3D& m_v3SourcePosition, const std::vector<VistaVector3D>& v3RayDirections ) const { @@ -161,17 +180,18 @@ std::vector<std::shared_ptr<CRay>> CEngine::Run( const ITAGeo::CStratifiedAtmosp TraceRays( atmosphere, rays ); return rays; } -void CEngine::Run( const ITAGeo::CStratifiedAtmosphere& atmosphere, const std::set<std::shared_ptr<CRay>>& rays ) const +bool CEngine::Run( const ITAGeo::CStratifiedAtmosphere& atmosphere, const std::set<std::shared_ptr<CRay>>& rays ) const { - TraceRays( atmosphere, std::vector<std::shared_ptr<CRay>>( rays.begin( ), rays.end( ) ) ); + return TraceRays( atmosphere, std::vector<std::shared_ptr<CRay>>( rays.begin( ), rays.end( ) ) ); } -void CEngine::TraceRays( const ITAGeo::CStratifiedAtmosphere& atmosphere, const std::vector<std::shared_ptr<CRay>>& rays ) const +bool CEngine::TraceRays( const ITAGeo::CStratifiedAtmosphere& atmosphere, const std::vector<std::shared_ptr<CRay>>& rays ) const { std::shared_ptr<IExternalWatcher> simulationWatcher = pExternalWatcher; if( !simulationWatcher ) ITA_EXCEPT_INVALID_PARAMETER( "Simulation-Engine: Interface to external watcher is not set. Cannot run simulation." ); + std::vector<double> vdMaxRayAltitude( rays.size( ) ); if( settings.bMultiThreading ) { #pragma omp parallel for schedule( static ) @@ -181,7 +201,7 @@ void CEngine::TraceRays( const ITAGeo::CStratifiedAtmosphere& atmosphere, const continue; auto worker = CWorker( rays[idx], settings, *simulationWatcher ); - worker.TraceRay( atmosphere ); + vdMaxRayAltitude[idx] = worker.TraceRay( atmosphere ); } } else @@ -192,7 +212,12 @@ void CEngine::TraceRays( const ITAGeo::CStratifiedAtmosphere& atmosphere, const continue; auto worker = CWorker( rays[idx], settings, *simulationWatcher ); - worker.TraceRay( atmosphere ); + vdMaxRayAltitude[idx] = worker.TraceRay( atmosphere ); } } + const double dMaxRayAltitude = *std::max_element( vdMaxRayAltitude.begin( ), vdMaxRayAltitude.end( ) ); + const bool bInsideBounds = atmosphere.InsideBounds( dMaxRayAltitude ); + if( !m_bSuppressWarnings && !bInsideBounds ) + ART_WARN( "Simulation::Engine: Maximum altitude of atmosphere exceeded for at least one ray. Results should be treated with care." ); + return bInsideBounds; }