diff --git a/NumLib/ODESolver/NonlinearSolver.cpp b/NumLib/ODESolver/NonlinearSolver.cpp index f689ddba6a3082ec39c163628cbdb2ca55f68712..62ea46f0aa8a3f0f5da2b6168f813b56bcbcc952 100644 --- a/NumLib/ODESolver/NonlinearSolver.cpp +++ b/NumLib/ODESolver/NonlinearSolver.cpp @@ -126,7 +126,7 @@ void NonlinearSolver<NonlinearSolverTag::Picard>:: NonlinearSolverStatus NonlinearSolver<NonlinearSolverTag::Picard>::solve( std::vector<GlobalVector*>& x, std::vector<GlobalVector*> const& x_prev, - std::function<void(int, std::vector<GlobalVector*> const&)> const& + std::function<void(int, bool, std::vector<GlobalVector*> const&)> const& postIterationCallback, int const process_id) { @@ -212,7 +212,7 @@ NonlinearSolverStatus NonlinearSolver<NonlinearSolverTag::Picard>::solve( { if (postIterationCallback) { - postIterationCallback(iteration, x_new); + postIterationCallback(iteration, error_norms_met, x_new); } switch (sys.postIteration(x_new_process)) @@ -330,7 +330,7 @@ void NonlinearSolver<NonlinearSolverTag::Newton>:: NonlinearSolverStatus NonlinearSolver<NonlinearSolverTag::Newton>::solve( std::vector<GlobalVector*>& x, std::vector<GlobalVector*> const& x_prev, - std::function<void(int, std::vector<GlobalVector*> const&)> const& + std::function<void(int, bool, std::vector<GlobalVector*> const&)> const& postIterationCallback, int const process_id) { @@ -453,7 +453,7 @@ NonlinearSolverStatus NonlinearSolver<NonlinearSolverTag::Newton>::solve( if (postIterationCallback) { - postIterationCallback(iteration, x_new); + postIterationCallback(iteration, error_norms_met, x_new); } switch (sys.postIteration(*x_new[process_id])) diff --git a/NumLib/ODESolver/NonlinearSolver.h b/NumLib/ODESolver/NonlinearSolver.h index f4fede727ffd0908efd18c2f6d9ebf6d83327377..494085557f220117296d4be75ff54c5c2310a439 100644 --- a/NumLib/ODESolver/NonlinearSolver.h +++ b/NumLib/ODESolver/NonlinearSolver.h @@ -53,7 +53,7 @@ public: virtual NonlinearSolverStatus solve( std::vector<GlobalVector*>& x, std::vector<GlobalVector*> const& x_prev, - std::function<void(int, std::vector<GlobalVector*> const&)> const& + std::function<void(int, bool, std::vector<GlobalVector*> const&)> const& postIterationCallback, int const process_id) = 0; @@ -118,7 +118,7 @@ public: NonlinearSolverStatus solve( std::vector<GlobalVector*>& x, std::vector<GlobalVector*> const& x_prev, - std::function<void(int, std::vector<GlobalVector*> const&)> const& + std::function<void(int, bool, std::vector<GlobalVector*> const&)> const& postIterationCallback, int const process_id) override; @@ -202,7 +202,7 @@ public: NonlinearSolverStatus solve( std::vector<GlobalVector*>& x, std::vector<GlobalVector*> const& x_prev, - std::function<void(int, std::vector<GlobalVector*> const&)> const& + std::function<void(int, bool, std::vector<GlobalVector*> const&)> const& postIterationCallback, int const process_id) override; diff --git a/NumLib/ODESolver/PETScNonlinearSolver.cpp b/NumLib/ODESolver/PETScNonlinearSolver.cpp index 73691919bfbd6070a5a2fcf136362bd8e78959c5..01f99861805bd92dff499c94d4d81872ac2db99f 100644 --- a/NumLib/ODESolver/PETScNonlinearSolver.cpp +++ b/NumLib/ODESolver/PETScNonlinearSolver.cpp @@ -149,7 +149,7 @@ NonlinearSolverStatus PETScNonlinearSolver::solve( std::vector<GlobalVector*>& x, std::vector<GlobalVector*> const& x_prev, std::function<void( - int, + int, bool, std::vector<GlobalVector*> const&)> const& /*postIterationCallback*/, int const process_id) { diff --git a/NumLib/ODESolver/PETScNonlinearSolver.h b/NumLib/ODESolver/PETScNonlinearSolver.h index b216aa41cf16d40251dea2ab0ba31171ad9f052f..0a682ac9b84f9aed3ba0178bc2d41f80f96a4c0e 100644 --- a/NumLib/ODESolver/PETScNonlinearSolver.h +++ b/NumLib/ODESolver/PETScNonlinearSolver.h @@ -51,7 +51,7 @@ public: NonlinearSolverStatus solve( std::vector<GlobalVector*>& x, std::vector<GlobalVector*> const& x_prev, - std::function<void(int, std::vector<GlobalVector*> const&)> const& + std::function<void(int, bool, std::vector<GlobalVector*> const&)> const& postIterationCallback, int const process_id) override; diff --git a/ProcessLib/Output/Output.cpp b/ProcessLib/Output/Output.cpp index 78455666fafbbfbcc5d58bc2b864287d24d4643f..84cf4df4d9a6fb9c0a7a7b69e1a85b91b05ff415 100644 --- a/ProcessLib/Output/Output.cpp +++ b/ProcessLib/Output/Output.cpp @@ -176,6 +176,7 @@ void Output::doNotProjectFromBulkMeshToSubmeshes( void Output::outputMeshes( const int timestep, const double t, const int iteration, + bool const converged, std::vector<std::reference_wrapper<const MeshLib::Mesh>> const& meshes) const { @@ -208,7 +209,7 @@ void Output::outputMeshes( } } } - _output_format->outputMeshes(timestep, t, iteration, meshes, + _output_format->outputMeshes(timestep, t, iteration, converged, meshes, _output_data_specification.output_variables); } @@ -291,6 +292,7 @@ void Output::doOutputAlways(Process const& process, int const timestep, const NumLib::Time& t, int const iteration, + bool const converged, std::vector<GlobalVector*> const& xs) const { BaseLib::RunTime time_output; @@ -327,7 +329,7 @@ void Output::doOutputAlways(Process const& process, } } - outputMeshes(timestep, t(), iteration, std::move(output_meshes)); + outputMeshes(timestep, t(), iteration, converged, std::move(output_meshes)); INFO("[time] Output of timestep {:d} took {:g} s.", timestep, time_output.elapsed()); @@ -338,11 +340,13 @@ void Output::doOutput(Process const& process, int const timestep, const NumLib::Time& t, int const iteration, + bool const converged, std::vector<GlobalVector*> const& xs) const { if (isOutputStep(timestep, t)) { - doOutputAlways(process, process_id, timestep, t, iteration, xs); + doOutputAlways(process, process_id, timestep, t, iteration, converged, + xs); } #ifdef OGS_USE_INSITU // Note: last time step may be output twice: here and in @@ -357,11 +361,13 @@ void Output::doOutputLastTimestep(Process const& process, int const timestep, const NumLib::Time& t, int const iteration, + bool const converged, std::vector<GlobalVector*> const& xs) const { if (!isOutputStep(timestep, t)) { - doOutputAlways(process, process_id, timestep, t, iteration, xs); + doOutputAlways(process, process_id, timestep, t, iteration, converged, + xs); } #ifdef OGS_USE_INSITU InSituLib::CoProcess(process.getMesh(), t, timestep, true, @@ -371,7 +377,7 @@ void Output::doOutputLastTimestep(Process const& process, void Output::doOutputNonlinearIteration( Process const& process, const int process_id, int const timestep, - const NumLib::Time& t, int const iteration, + const NumLib::Time& t, int const iteration, bool const converged, std::vector<GlobalVector*> const& xs) const { if (!_output_nonlinear_iteration_results) @@ -423,8 +429,10 @@ bool Output::isOutputStep(int const timestep, NumLib::Time const& t) const std::vector<std::string> Output::getFileNamesForOutput() const { auto construct_filename = ranges::views::transform( - [&](auto const& output_name) - { return _output_format->constructFilename(output_name, 0, 0, 0); }); + [&](auto const& output_name) { + return _output_format->constructFilename(output_name, 0, 0, 0, + true); + }); return _mesh_names_for_output | construct_filename | ranges::to<std::vector>; diff --git a/ProcessLib/Output/Output.h b/ProcessLib/Output/Output.h index 1fd79d73c552f6285c9366e64464415ff29f1a13..3dd872250b252a81fd58319550b6889d4d90e6a6 100644 --- a/ProcessLib/Output/Output.h +++ b/ProcessLib/Output/Output.h @@ -61,7 +61,7 @@ public: //! the given \c timestep. void doOutput(Process const& process, const int process_id, int const timestep, const NumLib::Time& t, - int const iteration, + int const iteration, bool const converged, std::vector<GlobalVector*> const& xs) const; //! Writes output for the given \c process if it has not been written yet. @@ -69,7 +69,7 @@ public: //! order to make sure that its results are written. void doOutputLastTimestep(Process const& process, const int process_id, int const timestep, const NumLib::Time& t, - int const iteration, + int const iteration, bool const converged, std::vector<GlobalVector*> const& xs) const; //! Writes output for the given \c process. @@ -77,7 +77,7 @@ public: //! It is intended to write output in error handling routines. void doOutputAlways(Process const& process, const int process_id, int const timestep, const NumLib::Time& t, - int const iteration, + int const iteration, bool const converged, std::vector<GlobalVector*> const& xs) const; //! Writes output for the given \c process. @@ -85,6 +85,7 @@ public: void doOutputNonlinearIteration(Process const& process, const int process_id, int const timestep, const NumLib::Time& t, const int iteration, + bool const converged, std::vector<GlobalVector*> const& xs) const; //! Tells if output will be written at the specified timestep/time. @@ -107,6 +108,7 @@ private: void outputMeshes( int const timestep, const double t, int const iteration, + bool const converged, std::vector<std::reference_wrapper<const MeshLib::Mesh>> const& meshes) const; diff --git a/ProcessLib/Output/OutputFormat.cpp b/ProcessLib/Output/OutputFormat.cpp index 63c99108ae9de22aaabed9bdb0348342d95f1bd2..30ffe445d2f30a66b182043c8d88b9bdf0eb40b7 100644 --- a/ProcessLib/Output/OutputFormat.cpp +++ b/ProcessLib/Output/OutputFormat.cpp @@ -56,10 +56,11 @@ void outputMeshVtk(std::string const& file_name, MeshLib::Mesh const& mesh, void outputMeshVtk(OutputVTKFormat const& output_file, MeshLib::IO::PVDFile& pvd_file, MeshLib::Mesh const& mesh, - double const t, int const timestep, int const iteration) + double const t, int const timestep, int const iteration, + bool const converged) { - auto const name = - output_file.constructFilename(mesh.getName(), timestep, t, iteration); + auto const name = output_file.constructFilename(mesh.getName(), timestep, t, + iteration, converged); pvd_file.addVTUFile(name, t); auto const path = BaseLib::joinPaths(output_file.directory, name); @@ -114,13 +115,14 @@ std::string OutputXDMFHDF5Format::constructFilename( void OutputXDMFHDF5Format::outputMeshXdmf( std::set<std::string> const& output_variables, std::vector<std::reference_wrapper<const MeshLib::Mesh>> const& meshes, - int const timestep, double const t, int const iteration) const + int const timestep, double const t, int const iteration, + bool const converged) const { // \TODO The XdmfOutput will create on construction the XdmfHdfWriter if (!mesh_xdmf_hdf_writer) { auto name = constructFilename(meshes[0].get().getName(), timestep, t, - iteration); + iteration, converged); std::filesystem::path path(BaseLib::joinPaths(directory, name)); mesh_xdmf_hdf_writer = std::make_unique<MeshLib::IO::XdmfHdfWriter>( meshes, path, timestep, t, output_variables, compression, n_files, @@ -134,13 +136,14 @@ void OutputXDMFHDF5Format::outputMeshXdmf( void OutputVTKFormat::outputMeshes( const int timestep, const double t, const int iteration, + bool const converged, std::vector<std::reference_wrapper<const MeshLib::Mesh>> const& meshes, [[maybe_unused]] std::set<std::string> const& output_variables) const { for (auto const& mesh : meshes) { auto& pvd_file = findOrCreatePVDFile(mesh.get().getName()); - outputMeshVtk(*this, pvd_file, mesh, t, timestep, iteration); + outputMeshVtk(*this, pvd_file, mesh, t, timestep, iteration, converged); } } } // namespace ProcessLib diff --git a/ProcessLib/Output/OutputFormat.h b/ProcessLib/Output/OutputFormat.h index d9db48eab1ebe8df9dd7ee59afaa5a66727dc85f..7068450d8fc96a88fcceb77c0c95b84e3ede5afb 100644 --- a/ProcessLib/Output/OutputFormat.h +++ b/ProcessLib/Output/OutputFormat.h @@ -39,6 +39,7 @@ struct OutputFormat virtual void outputMeshes( const int timestep, const double t, const int iteration, + bool const converged, std::vector<std::reference_wrapper<const MeshLib::Mesh>> const& meshes, std::set<std::string> const& output_variables) const = 0; virtual std::string constructFilename(std::string const& mesh_name, @@ -69,6 +70,7 @@ struct OutputVTKFormat final : public OutputFormat void outputMeshes( const int timestep, const double t, const int iteration, + bool const converged, std::vector<std::reference_wrapper<const MeshLib::Mesh>> const& meshes, std::set<std::string> const& output_variables) const override; @@ -107,10 +109,12 @@ struct OutputXDMFHDF5Format final : public OutputFormat void outputMeshes( const int timestep, const double t, const int iteration, + bool const converged, std::vector<std::reference_wrapper<const MeshLib::Mesh>> const& meshes, std::set<std::string> const& output_variables) const override { - outputMeshXdmf(output_variables, meshes, timestep, t, iteration); + outputMeshXdmf(output_variables, meshes, timestep, t, iteration, + converged); } std::string constructFilename(std::string const& mesh_name, @@ -127,7 +131,8 @@ struct OutputXDMFHDF5Format final : public OutputFormat void outputMeshXdmf( std::set<std::string> const& output_variables, std::vector<std::reference_wrapper<const MeshLib::Mesh>> const& meshes, - int const timestep, double const t, int const iteration) const; + int const timestep, double const t, int const iteration, + bool const converged) const; }; void outputMeshVtk(std::string const& file_name, MeshLib::Mesh const& mesh, diff --git a/ProcessLib/TimeLoop.cpp b/ProcessLib/TimeLoop.cpp index 06d6e74c96cd30536c7305514211f0bec6a2094b..7bb55d5fdb289efe57d543f9c73568c665370b25 100644 --- a/ProcessLib/TimeLoop.cpp +++ b/ProcessLib/TimeLoop.cpp @@ -241,7 +241,8 @@ NumLib::NonlinearSolverStatus solveOneTimeStepOneProcess( time_disc.nextTimestep(t, delta_t); auto const post_iteration_callback = - [&](int iteration, std::vector<GlobalVector*> const& x) + [&](int const iteration, bool const converged, + std::vector<GlobalVector*> const& x) { // Note: We don't call the postNonLinearSolver(), preOutput(), // computeSecondaryVariable() and postTimestep() hooks here. This might @@ -249,7 +250,8 @@ NumLib::NonlinearSolverStatus solveOneTimeStepOneProcess( for (auto const& output : outputs) { output.doOutputNonlinearIteration(process, process_id, timestep, - NumLib::Time(t), iteration, x); + NumLib::Time(t), iteration, + converged, x); } }; @@ -667,6 +669,7 @@ NumLib::NonlinearSolverStatus TimeLoop::solveUncoupledEquationSystems( output.doOutputAlways( process_data->process, process_id, timestep_id, t, process_data->nonlinear_solver_status.number_iterations, + process_data->nonlinear_solver_status.error_norms_met, _process_solutions); } OGS_FATAL(timestepper_cannot_reduce_dt.data()); @@ -726,6 +729,7 @@ void TimeLoop::outputSolutions(unsigned timestep, const double t, (output_object.*output_class_member)( pcs, process_id, timestep, NumLib::Time(t), process_data->nonlinear_solver_status.number_iterations, + process_data->nonlinear_solver_status.error_norms_met, _process_solutions); } }