diff --git a/doc/doxygen/DoxygenDumuxLayout.xml b/doc/doxygen/DoxygenDumuxLayout.xml index 506067984e7941f4ea2dab0f9f728e84a0f2dfff..2243a0458d521965d80db01e1d748bf2b4125bf2 100644 --- a/doc/doxygen/DoxygenDumuxLayout.xml +++ b/doc/doxygen/DoxygenDumuxLayout.xml @@ -36,6 +36,7 @@ SPDX-License-Identifier: GPL-3.0-or-later <tab type="user" url="@ref changing-property-name" visible="yes" title="Changing property name" intro=""/> <tab type="user" url="@ref custom-input-data" visible="yes" title="Custom input data" intro=""/> <tab type="user" url="@ref gmsh-with-alugrid" visible="yes" title="Gmsh with ALUGrid" intro=""/> + <tab type="user" url="@ref printing-system-matrix" visible="yes" title="Printing system matrix" intro=""/> </tab> <tab type="user" url="@ref citelist" visible="yes" title="Bibliography" intro=""/> <tab type="namespaces" visible="yes" title=""> diff --git a/doc/doxygen/pages/printing-system-matrix.md b/doc/doxygen/pages/printing-system-matrix.md new file mode 100644 index 0000000000000000000000000000000000000000..3c98c945392de7b8a03b4a7e7e86dd16b9d75169 --- /dev/null +++ b/doc/doxygen/pages/printing-system-matrix.md @@ -0,0 +1,56 @@ +# Printing system matrix + +Debugging may require inspecting the system (Jacobian) matrix from time to time. + +The following example shows a possible way to achieve this for a staggered-grid free-flow problem: + +We add the output within the `solveLinearSystem_` overload for `Dune::MultiTypeBlockMatrix` Jacobians in `newtonsolver.hh`: + +```c++ + // MultiTypeBlockMatrix is not supported for printing, needs to be converted first + + // create the bcrs matrix the IterativeSolver backend can handle + const auto M = MatrixConverter<JacobianMatrix>::multiTypeToBCRSMatrix(A); + + // get the new matrix sizes + const std::size_t numRows = M.N(); + assert(numRows == M.M()); + + // create the vector the IterativeSolver backend can handle + const auto bTmp = VectorConverter<SolutionVector>::multiTypeToBlockVector(b); + assert(bTmp.size() == numRows); + + // create a blockvector to which the linear solver writes the solution + using VectorBlock = typename Dune::FieldVector<Scalar, 1>; + using BlockVector = typename Dune::BlockVector<VectorBlock>; + BlockVector y(numRows); + + /////// BEGIN PRINTING ///////////////////////////////////////////////////// + static const bool printmatrix = getParam<bool>("Problem.PrintMatrix", false); + + if (printmatrix) + { + static int counter = 0; + const auto rank = Dune::MPIHelper::getCommunication().rank(); + + Dune::storeMatrixMarket(M, "matrix_" + std::to_string(rank) + "_iter_" + std::to_string(counter) + ".log"); + Dune::storeMatrixMarket(bTmp, "rhs_" + std::to_string(rank) + "_iter_" + std::to_string(counter) + ".log"); + + ++counter; + } + /////// END PRINTING ///////////////////////////////////////////////////// + +// .... +``` + +This will write out files for the matrix and the residual vector for each Newton iteration and each process. `A` and `b` can also be accessed via `assembler.jacobian()` and `assembler.residual()` respectively. + +You may then compare files using, e.g., `kompare` or `meld`. + +Keep in mind that the `MatrixMarket`format uses indices starting with `1` instead of `0`. + +For rather small matrices, you may also directly print the output to the terminal, giving you a graphical impression of the structure: + +```c++ +Dune::printmatrix(std::cout, M, "", "", 10/*width*/, 2/*precision*/); +``` \ No newline at end of file