diff --git a/src/TNL/Solvers/IterativeSolver.h b/src/TNL/Solvers/IterativeSolver.h index c7c903cfcbc44b1fb11ee9210d18be9b0a8f3d80..75487fa0197a51b79897384de3b12ecec12c667b 100644 --- a/src/TNL/Solvers/IterativeSolver.h +++ b/src/TNL/Solvers/IterativeSolver.h @@ -88,6 +88,10 @@ protected: SolverMonitor* solverMonitor = nullptr; Index refreshRate = 1; + + String residualHistoryFileName = ""; + + std::ofstream residualHistoryFile; }; } // namespace Solvers diff --git a/src/TNL/Solvers/IterativeSolver_impl.h b/src/TNL/Solvers/IterativeSolver_impl.h index b673a5c1753f59cd0de31c3f953cbab84e0d56ed..8f28e8847f52ede82e68d6117312638c499fac5b 100644 --- a/src/TNL/Solvers/IterativeSolver_impl.h +++ b/src/TNL/Solvers/IterativeSolver_impl.h @@ -33,6 +33,8 @@ configSetup( Config::ConfigDescription& config, config.addEntry< double >( prefix + "divergence-residue", "Divergence occurs when the residue exceeds given limit.", std::numeric_limits< float >::max() ); // TODO: setting refresh rate should be done in SolverStarter::setup (it's not a parameter of the IterativeSolver) config.addEntry< int > ( prefix + "refresh-rate", "Number of iterations between solver monitor refreshes.", 1 ); + + config.addEntry< String >( prefix + "residual-history-file", "Path to the file where the residual history will be saved.", "" ); } template< typename Real, typename Index, typename SolverMonitor > @@ -41,12 +43,15 @@ IterativeSolver< Real, Index, SolverMonitor >:: setup( const Config::ParameterContainer& parameters, const String& prefix ) { - this->setMaxIterations( parameters.getParameter< int >( "max-iterations" ) ); - this->setMinIterations( parameters.getParameter< int >( "min-iterations" ) ); - this->setConvergenceResidue( parameters.getParameter< double >( "convergence-residue" ) ); - this->setDivergenceResidue( parameters.getParameter< double >( "divergence-residue" ) ); + this->setMaxIterations( parameters.getParameter< int >( prefix + "max-iterations" ) ); + this->setMinIterations( parameters.getParameter< int >( prefix + "min-iterations" ) ); + this->setConvergenceResidue( parameters.getParameter< double >( prefix + "convergence-residue" ) ); + this->setDivergenceResidue( parameters.getParameter< double >( prefix + "divergence-residue" ) ); // TODO: setting refresh rate should be done in SolverStarter::setup (it's not a parameter of the IterativeSolver) - this->setRefreshRate( parameters.getParameter< int >( "refresh-rate" ) ); + this->setRefreshRate( parameters.getParameter< int >( prefix + "refresh-rate" ) ); + this->residualHistoryFileName = parameters.getParameter< String >( prefix + "residual-history-file" ); + if( this->residualHistoryFileName ) + this->residualHistoryFile.open( this->residualHistoryFileName.getString() ); return true; } @@ -199,6 +204,11 @@ setResidue( const Real& residue ) this->currentResidue = residue; if( this->solverMonitor ) this->solverMonitor->setResidue( this->getResidue() ); + if( this->residualHistoryFile ) { + if( this->getIterations() == 0 ) + this->residualHistoryFile << "\n"; + this->residualHistoryFile << this->getIterations() << "\t" << std::scientific << residue << std::endl; + } } template< typename Real, typename Index, typename SolverMonitor >