diff --git a/opm/simulators/linalg/ISTLSolverEbosFlexible.hpp b/opm/simulators/linalg/ISTLSolverEbosFlexible.hpp index db703da3c..d20dd450c 100644 --- a/opm/simulators/linalg/ISTLSolverEbosFlexible.hpp +++ b/opm/simulators/linalg/ISTLSolverEbosFlexible.hpp @@ -24,6 +24,7 @@ #include #include #include +#include #include @@ -199,9 +200,11 @@ public: if (recreate_solver || !solver_) { if (isParallel()) { #if HAVE_MPI + matrix_ = &mat.istlMatrix(); solver_.reset(new SolverType(prm_, mat.istlMatrix(), weightsCalculator, *comm_)); #endif } else { + matrix_ = &mat.istlMatrix(); solver_.reset(new SolverType(prm_, mat.istlMatrix(), weightsCalculator)); } rhs_ = b; @@ -214,6 +217,7 @@ public: bool solve(VectorType& x) { solver_->apply(x, rhs_, res_); + this->writeMatrix(); return res_.converged; } @@ -275,8 +279,27 @@ protected: return weights; } - const Simulator& simulator_; + void writeMatrix() + { +#ifdef HAVE_MPI + const int verbosity = prm_.get("verbosity"); + const bool write_matrix = verbosity > 10; + if (write_matrix) { + using block_type = typename MatrixType::block_type; + using value_type = typename block_type::value_type; + using BaseBlockType = Dune::FieldMatrix; + using BaseMatrixType = Dune::BCRSMatrix; + const BaseMatrixType* matrix = reinterpret_cast(this->matrix_); + Opm::Helper::writeSystem(this->simulator_, //simulator is only used to get names + *matrix, + this->rhs_, + comm_.get()); + } +#endif + } + const Simulator& simulator_; + MatrixType* matrix_; std::unique_ptr solver_; FlowLinearSolverParameters parameters_; boost::property_tree::ptree prm_; diff --git a/opm/simulators/linalg/WriteSystemMatrixHelper.hpp b/opm/simulators/linalg/WriteSystemMatrixHelper.hpp new file mode 100644 index 000000000..f76985176 --- /dev/null +++ b/opm/simulators/linalg/WriteSystemMatrixHelper.hpp @@ -0,0 +1,78 @@ +/* + Copyright 2019 SINTEF Digital, Mathematics and Cybernetics. + + This file is part of the Open Porous Media project (OPM). + + OPM is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OPM is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with OPM. If not, see . +*/ + +#ifndef OPM_WRITESYSTEMMATRIXHELPER_HEADER_INCLUDED +#define OPM_WRITESYSTEMMATRIXHELPER_HEADER_INCLUDED + +#include + +namespace Opm +{ +namespace Helper +{ + template + void writeSystem(const SimulatorType& simulator, + const MatrixType& matrix, + const VectorType& rhs, + const Communicator* comm) + { + std::string dir = simulator.problem().outputDir(); + if (dir == ".") { + dir = ""; + } else if (!dir.empty() && dir.back() != '/') { + dir += "/"; + } + namespace fs = Opm::filesystem; + fs::path output_dir(dir); + fs::path subdir("reports"); + output_dir = output_dir / subdir; + if (!(fs::exists(output_dir))) { + fs::create_directory(output_dir); + } + // Combine and return. + std::ostringstream oss; + oss << "prob_" << simulator.episodeIndex() << "_time_"; + oss << std::setprecision(15) << std::setw(12) << std::setfill('0') << simulator.time() << "_"; + int nit = simulator.model().newtonMethod().numIterations(); + oss << "_nit_" << nit << "_"; + std::string output_file(oss.str()); + fs::path full_path = output_dir / output_file; + std::string prefix = full_path.string(); + { + std::string filename = prefix + "matrix_istl"; + if (comm != nullptr) { // comm is not set in serial runs + Dune::storeMatrixMarket(matrix, filename, *comm, true); + } else { + Dune::storeMatrixMarket(matrix, filename); + } + } + { + std::string filename = prefix + "rhs_istl"; + if (comm != nullptr) { // comm is not set in serial runs + Dune::storeMatrixMarket(rhs, filename, *comm, true); + } else { + Dune::storeMatrixMarket(rhs, filename); + } + } + } + + +} // namespace Helper +} // namespace Opm +#endif