From 77b658f8da62673f60e0a3c8b331e33d6d64d021 Mon Sep 17 00:00:00 2001 From: Tobias Leibner <tobias.leibner@googlemail.com> Date: Fri, 25 Sep 2020 14:29:03 +0200 Subject: [PATCH] [test.la] fix undefined behavior --- dune/xt/la/solver/istl/schurcomplement.hh | 19 ++++++++++++++----- dune/xt/test/la/solver.tpl | 4 ++++ 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/dune/xt/la/solver/istl/schurcomplement.hh b/dune/xt/la/solver/istl/schurcomplement.hh index 06c71fb8b..38806e292 100644 --- a/dune/xt/la/solver/istl/schurcomplement.hh +++ b/dune/xt/la/solver/istl/schurcomplement.hh @@ -15,8 +15,10 @@ #include <dune/istl/operators.hh> #include <dune/istl/solvers.hh> -#include <dune/xt/common/exceptions.hh> #include <dune/xt/common/configuration.hh> +#include <dune/xt/common/exceptions.hh> +#include <dune/xt/common/math.hh> + #include <dune/xt/la/container/istl.hh> #include <dune/xt/la/solver.hh> @@ -82,10 +84,17 @@ public: auto& B1x = m_vec_1_; B1_.mv(x, B1x); // calculate A^{-1} B1 x - auto& AinvB1x = m_vec_2_; - A_inv_.apply(B1x, AinvB1x, solver_opts_); - // apply B2^T - B2_.mtv(AinvB1x, y); + if (XT::Common::is_zero(B1x.two_norm())) { + // if B1x is zero, y will also be zero + // this special case is here to avoid calling the dune-istl CG solver with an + // initial defect of 0 which causes undefined behavior (division-by-zero) + y *= 0.; + } else { + auto& AinvB1x = m_vec_2_; + A_inv_.apply(B1x, AinvB1x, solver_opts_); + // apply B2^T + B2_.mtv(AinvB1x, y); + } // calculate Cx auto& Cx = n_vec_1_; C_.mv(x, Cx); diff --git a/dune/xt/test/la/solver.tpl b/dune/xt/test/la/solver.tpl index 7bca7c8ca..6cf370c3d 100644 --- a/dune/xt/test/la/solver.tpl +++ b/dune/xt/test/la/solver.tpl @@ -64,6 +64,10 @@ struct SolverTest_{{T_NAME}} : public ::testing::Test options.report(out, " "); // dynamic tests + // Matrix is the identity matrix, solution and rhs are initially filled with ones + // Multiply by 2 to avoid calling the istl iterative solver with an + // initial defect of 0 which results in undefined behavior (division-by-zero) + solution *= 2.; solver.apply(rhs, solution, type); EXPECT_TRUE(XT::Common::FloatCmp::eq(solution, rhs)); solution *= 0.; -- GitLab