From f7ec35e15d7fb960b29d4ddd2a66664b6462aee9 Mon Sep 17 00:00:00 2001 From: Dmitri Naumov <github@naumov.de> Date: Thu, 7 Jan 2021 20:36:58 +0100 Subject: [PATCH] Add iteration number output to file names. Especially useful when all nonlinear iterations should be output. See <output_iteration_results> tag. --- BaseLib/FileTools.cpp | 6 ++-- BaseLib/FileTools.h | 3 +- ProcessLib/Output/Output.cpp | 35 +++++++++++-------- ProcessLib/Output/Output.h | 10 +++--- ProcessLib/TimeLoop.cpp | 14 +++++--- .../TestConstructFormattedFileName.cpp | 27 ++++++++------ 6 files changed, 57 insertions(+), 38 deletions(-) diff --git a/BaseLib/FileTools.cpp b/BaseLib/FileTools.cpp index b0876d860e5..a70cd564db3 100644 --- a/BaseLib/FileTools.cpp +++ b/BaseLib/FileTools.cpp @@ -111,7 +111,8 @@ bool substituteKeyword(std::string& result, std::string& parenthesized_string, std::string constructFormattedFileName(std::string const& format_specification, std::string const& mesh_name, int const timestep, - double const t) + double const t, + int const iteration) { char const open_char = '{'; char const close_char = '}'; @@ -127,7 +128,8 @@ std::string constructFormattedFileName(std::string const& format_specification, std::tie(str, begin, end) = getParenthesizedString(result, open_char, close_char, begin); if (!substituteKeyword(result, str, begin, end, "timestep", timestep) && - !substituteKeyword(result, str, begin, end, "time", t)) + !substituteKeyword(result, str, begin, end, "time", t) && + !substituteKeyword(result, str, begin, end, "iteration", iteration)) { substituteKeyword(result, str, begin, end, "meshname", mesh_name); } diff --git a/BaseLib/FileTools.h b/BaseLib/FileTools.h index 74d4fbaf3a0..acbdf546fb1 100644 --- a/BaseLib/FileTools.h +++ b/BaseLib/FileTools.h @@ -44,7 +44,8 @@ getParenthesizedString(std::string const& in, std::string constructFormattedFileName(std::string const& format_specification, std::string const& mesh_name, int const timestep, - double const t); + double const t, + int const iteration); /** * \brief write value as binary into the given output stream diff --git a/ProcessLib/Output/Output.cpp b/ProcessLib/Output/Output.cpp index 76b52c5c6b5..82719102170 100644 --- a/ProcessLib/Output/Output.cpp +++ b/ProcessLib/Output/Output.cpp @@ -51,7 +51,7 @@ std::string constructPVDName(std::string const& output_directory, { return BaseLib::joinPaths(output_directory, BaseLib::constructFormattedFileName( - output_file_prefix, mesh_name, 0, 0) + + output_file_prefix, mesh_name, 0, 0, 0) + ".pvd"); } } // namespace @@ -178,8 +178,10 @@ struct Output::OutputFile OutputFile(std::string const& directory, OutputType const type, std::string const& prefix, std::string const& suffix, std::string const& mesh_name, int const timestep, double const t, - int const data_mode_, bool const compression_) - : name(constructFilename(type, prefix, suffix, mesh_name, timestep, t)), + int const iteration, int const data_mode_, + bool const compression_) + : name(constructFilename(type, prefix, suffix, mesh_name, timestep, t, + iteration)), path(BaseLib::joinPaths(directory, name)), type(type), data_mode(data_mode_), @@ -202,7 +204,8 @@ struct Output::OutputFile static std::string constructFilename(OutputType const type, std::string prefix, std::string suffix, std::string mesh_name, - int const timestep, double const t) + int const timestep, double const t, + int const iteration) { std::map<OutputType, std::string> filetype_to_extension = { {OutputType::vtk, "vtu"}, {OutputType::xdmf, "xdmf"}}; @@ -211,9 +214,9 @@ struct Output::OutputFile { std::string extension = filetype_to_extension.at(type); return BaseLib::constructFormattedFileName(prefix, mesh_name, - timestep, t) + + timestep, t, iteration) + BaseLib::constructFormattedFileName(suffix, mesh_name, - timestep, t) + + timestep, t, iteration) + "." + extension; } catch (std::out_of_range& e) @@ -266,6 +269,7 @@ void Output::doOutputAlways(Process const& process, const int process_id, int const timestep, const double t, + int const iteration, std::vector<GlobalVector*> const& x) { BaseLib::RunTime time_output; @@ -304,7 +308,7 @@ void Output::doOutputAlways(Process const& process, { OutputFile const file( _output_directory, _output_file_type, _output_file_prefix, - _output_file_suffix, mesh.getName(), timestep, t, + _output_file_suffix, mesh.getName(), timestep, t, iteration, _output_file_data_mode, _output_file_compression); pvd_file = findPVDFile(process, process_id, mesh.getName()); @@ -315,7 +319,7 @@ void Output::doOutputAlways(Process const& process, #ifdef OGS_USE_XDMF OutputFile const file(_output_directory, _output_file_type, _output_file_prefix, "", mesh.getName(), - timestep, t, _output_file_data_mode, + timestep, t, iteration, _output_file_data_mode, _output_file_compression); outputMeshXdmf(file, mesh, timestep, t); @@ -388,11 +392,12 @@ void Output::doOutput(Process const& process, const int process_id, int const timestep, const double t, + int const iteration, std::vector<GlobalVector*> const& x) { if (shallDoOutput(timestep, t)) { - doOutputAlways(process, process_id, timestep, t, x); + doOutputAlways(process, process_id, timestep, t, iteration, x); } #ifdef USE_INSITU // Note: last time step may be output twice: here and in @@ -406,11 +411,12 @@ void Output::doOutputLastTimestep(Process const& process, const int process_id, int const timestep, const double t, + int const iteration, std::vector<GlobalVector*> const& x) { if (!shallDoOutput(timestep, t)) { - doOutputAlways(process, process_id, timestep, t, x); + doOutputAlways(process, process_id, timestep, t, iteration, x); } #ifdef USE_INSITU InSituLib::CoProcess(process.getMesh(), t, timestep, true, @@ -421,8 +427,8 @@ void Output::doOutputLastTimestep(Process const& process, void Output::doOutputNonlinearIteration(Process const& process, const int process_id, int const timestep, const double t, - std::vector<GlobalVector*> const& x, - const int iteration) + int const iteration, + std::vector<GlobalVector*> const& x) { if (!_output_nonlinear_iteration_results) { @@ -459,9 +465,8 @@ void Output::doOutputNonlinearIteration(Process const& process, findPVDFile(process, process_id, process.getMesh().getName()); std::string const output_file_name = OutputFile::constructFilename( - _output_file_type, _output_file_prefix, - "_ts_{:timestep}_nliter_{:time}", process.getMesh().getName(), timestep, - iteration); + _output_file_type, _output_file_prefix, _output_file_suffix, + process.getMesh().getName(), timestep, t, iteration); std::string const output_file_path = BaseLib::joinPaths(_output_directory, output_file_name); diff --git a/ProcessLib/Output/Output.h b/ProcessLib/Output/Output.h index 1c38f1729d3..8aa7ca35aa8 100644 --- a/ProcessLib/Output/Output.h +++ b/ProcessLib/Output/Output.h @@ -56,7 +56,7 @@ public: //! Writes output for the given \c process if it should be written in the //! given \c timestep. void doOutput(Process const& process, const int process_id, - int const timestep, const double t, + int const timestep, const double t, int const iteration, std::vector<GlobalVector*> const& x); //! Writes output for the given \c process if it has not been written yet. @@ -64,22 +64,22 @@ public: //! order to make sure that its results are written. void doOutputLastTimestep(Process const& process, const int process_id, int const timestep, const double t, + int const iteration, std::vector<GlobalVector*> const& x); //! Writes output for the given \c process. //! This method will always write. //! It is intended to write output in error handling routines. void doOutputAlways(Process const& process, const int process_id, - int const timestep, const double t, + int const timestep, const double t, int const iteration, std::vector<GlobalVector*> const& x); //! Writes output for the given \c process. //! To be used for debug output after an iteration of the nonlinear solver. void doOutputNonlinearIteration(Process const& process, const int process_id, int const timestep, - const double t, - std::vector<GlobalVector*> const& x, - const int iteration); + const double t, const int iteration, + std::vector<GlobalVector*> const& x); std::vector<double> getFixedOutputTimes() const { diff --git a/ProcessLib/TimeLoop.cpp b/ProcessLib/TimeLoop.cpp index 0c01b849b8f..8e619d254c0 100644 --- a/ProcessLib/TimeLoop.cpp +++ b/ProcessLib/TimeLoop.cpp @@ -296,7 +296,7 @@ NumLib::NonlinearSolverStatus solveOneTimeStepOneProcess( auto const post_iteration_callback = [&](int iteration, std::vector<GlobalVector*> const& x) { output_control.doOutputNonlinearIteration( - process, process_id, timestep, t, x, iteration); + process, process_id, timestep, t, iteration, x); }; auto const nonlinear_solver_status = @@ -705,8 +705,10 @@ NumLib::NonlinearSolverStatus TimeLoop::solveUncoupledEquationSystems( if (!process_data->timestepper->canReduceTimestepSize()) { // save unsuccessful solution - _output->doOutputAlways(process_data->process, process_id, - timestep_id, t, _process_solutions); + _output->doOutputAlways( + process_data->process, process_id, timestep_id, t, + process_data->nonlinear_solver_status.number_iterations, + _process_solutions); OGS_FATAL(timestepper_cannot_reduce_dt.data()); } @@ -902,8 +904,10 @@ void TimeLoop::outputSolutions(bool const output_initial_condition, NumLib::GlobalVectorProvider::provider.releaseVector(x_dot); } - (output_object.*output_class_member)(pcs, process_id, timestep, t, - _process_solutions); + (output_object.*output_class_member)( + pcs, process_id, timestep, t, + process_data->nonlinear_solver_status.number_iterations, + _process_solutions); } } diff --git a/Tests/BaseLib/TestConstructFormattedFileName.cpp b/Tests/BaseLib/TestConstructFormattedFileName.cpp index 64a31f86d7f..2c6120dc84b 100644 --- a/Tests/BaseLib/TestConstructFormattedFileName.cpp +++ b/Tests/BaseLib/TestConstructFormattedFileName.cpp @@ -23,50 +23,57 @@ TEST(BaseLib, constructFormattedFileName) { { auto const formatted_filename = BaseLib::constructFormattedFileName( - "test_{:timestep}", "mesh_name", 2, 0.2); + "test_{:timestep}", "mesh_name", 2, 0.2, 3); ASSERT_EQ("test_2", formatted_filename); } { auto const formatted_filename_time = BaseLib::constructFormattedFileName("test_{:0.5time}", "mesh_name", - 2, 0.2); + 2, 0.2, 3); ASSERT_EQ("test_0.20000", formatted_filename_time); } + { + auto const formatted_filename = + BaseLib::constructFormattedFileName("test_{:iteration}", "mesh_name", + 2, 0.2, 3); + ASSERT_EQ("test_3", formatted_filename); + } { auto const formatted_filename_timestep_time = BaseLib::constructFormattedFileName("test_{:timestep}_{:0.5time}", - "mesh_name", 2, 0.2); + "mesh_name", 2, 0.2, 3); ASSERT_EQ("test_2_0.20000", formatted_filename_timestep_time); } { auto const formatted_filename_time_timestep = BaseLib::constructFormattedFileName("test_{:.4time}_{:timestep}", - "mesh_name", 2, 0.2); + "mesh_name", 2, 0.2, 3); ASSERT_EQ("test_0.2000_2", formatted_filename_time_timestep); } { auto const formatted_filename = BaseLib::constructFormattedFileName( - "test_{:.4time}_{:timestep}", "mesh_name", 2, 0.2); + "test_{:.4time}_{:timestep}", "mesh_name", 2, 0.2, 3); ASSERT_EQ("test_0.2000_2", formatted_filename); } { auto const formatted_filename = BaseLib::constructFormattedFileName( - "_ts_{:timestep}_t_{:.4time}", "mesh_name", 2, 0.2); + "_ts_{:timestep}_t_{:.4time}", "mesh_name", 2, 0.2, 3); ASSERT_EQ("_ts_2_t_0.2000", formatted_filename); } { auto const formatted_filename = BaseLib::constructFormattedFileName( - "_ts_{:0>3timestep}_t_{:.4time}", "mesh_name", 2, 0.2); + "_ts_{:0>3timestep}_t_{:.4time}", "mesh_name", 2, 0.2, 3); ASSERT_EQ("_ts_002_t_0.2000", formatted_filename); } { auto const formatted_filename = BaseLib::constructFormattedFileName( - "_ts_{:0>3timestep}_t_{:.4etime}", "mesh_name", 2, 0.2); + "_ts_{:0>3timestep}_t_{:.4etime}", "mesh_name", 2, 0.2, 3); ASSERT_EQ("_ts_002_t_2.0000e-01", formatted_filename); } { auto const formatted_filename = BaseLib::constructFormattedFileName( - "{:meshname}_ts_{:0>3timestep}_t_{:.4etime}", "mesh_name", 2, 0.2); - ASSERT_EQ("mesh_name_ts_002_t_2.0000e-01", formatted_filename); + "{:meshname}_ts_{:0>3timestep}_t_{:.4etime}_iter_{:0>2iteration}", + "mesh_name", 2, 0.2, 3); + ASSERT_EQ("mesh_name_ts_002_t_2.0000e-01_iter_03", formatted_filename); } } -- GitLab