From: Sebastian Stark Date: Thu, 15 Aug 2019 07:01:54 +0000 (+0200) Subject: Add assertion to PETScWrappers::MatrixBase::begin() and end(). X-Git-Tag: v9.2.0-rc1~1201^2 X-Git-Url: https://gitweb.dealii.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=ca1ab0c9f15de5e10e43fa534bf5b4e61cce0934;p=dealii.git Add assertion to PETScWrappers::MatrixBase::begin() and end(). Add assertion to make sure that begin() and end() can only be called on a processor owning the entire matrix. Also make sure that begin() works in case the first row(s) of the matrix is(are) emtpy. Fixes #8571. --- diff --git a/doc/news/changes/minor/20190819SebastianStark b/doc/news/changes/minor/20190819SebastianStark new file mode 100644 index 0000000000..6372de139c --- /dev/null +++ b/doc/news/changes/minor/20190819SebastianStark @@ -0,0 +1,3 @@ +Fixed: Make sure that begin() and end() of PETScWrappers::MatrixBase can only be called on a processor owning all rows of the matrix. Also fix a bug which caused begin() to fail when the first row(s) of the matrix is(are) empty. +
+(Sebastian Stark, 2019/08/19) diff --git a/include/deal.II/lac/petsc_matrix_base.h b/include/deal.II/lac/petsc_matrix_base.h index 1b8bbc48e0..2716196be4 100644 --- a/include/deal.II/lac/petsc_matrix_base.h +++ b/include/deal.II/lac/petsc_matrix_base.h @@ -837,13 +837,17 @@ namespace PETScWrappers residual(VectorBase &dst, const VectorBase &x, const VectorBase &b) const; /** - * Iterator starting at the first entry. + * Iterator starting at the first entry. This can only be called on a + * processor owning the entire matrix. In all other cases refer to the + * version of begin() taking a row number as an argument. */ const_iterator begin() const; /** - * Final iterator. + * Final iterator. This can only be called on a processor owning the entire + * matrix. In all other cases refer to the version of end() taking a row + * number as an argument. */ const_iterator end() const; @@ -1491,13 +1495,29 @@ namespace PETScWrappers inline MatrixBase::const_iterator MatrixBase::begin() const { - return const_iterator(this, 0, 0); + Assert( + (in_local_range(0) && in_local_range(m() - 1)), + ExcMessage( + "begin() and end() can only be called on a processor owning the entire matrix. If this is a distributed matrix, use begin(row) and end(row) instead.")); + + // find the first non-empty row in order to make sure that the returned + // iterator points to something useful + size_type first_nonempty_row = 0; + while ((first_nonempty_row < m()) && (row_length(first_nonempty_row) == 0)) + ++first_nonempty_row; + + return const_iterator(this, first_nonempty_row, 0); } inline MatrixBase::const_iterator MatrixBase::end() const { + Assert( + (in_local_range(0) && in_local_range(m() - 1)), + ExcMessage( + "begin() and end() can only be called on a processor owning the entire matrix. If this is a distributed matrix, use begin(row) and end(row) instead.")); + return const_iterator(this, m(), 0); } diff --git a/tests/petsc/matrix_base_iterator_01.cc b/tests/petsc/matrix_base_iterator_01.cc new file mode 100644 index 0000000000..4bb63ae5cd --- /dev/null +++ b/tests/petsc/matrix_base_iterator_01.cc @@ -0,0 +1,53 @@ +// --------------------------------------------------------------------- +// +// Copyright (C) 2004 - 2018 by the deal.II authors +// +// This file is part of the deal.II library. +// +// The deal.II library is free software; you can use it, redistribute +// it, and/or modify it under the terms of the GNU Lesser General +// Public License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// The full text of the license can be found in the file LICENSE.md at +// the top level directory of deal.II. +// +// --------------------------------------------------------------------- + + + +// check that begin() works if the first row(s) is(are) empty + +#include +#include + +#include "../tests.h" + + +void +test() +{ + // test the case that the first row is empty + dealii::DynamicSparsityPattern dsp_1(2); + dsp_1.add(1, 1); + + PETScWrappers::SparseMatrix K_1(dsp_1); + + if (K_1.begin()->row() == 1) + deallog << "OK" << std::endl; + + // test the case that the entire matrix is empty + dealii::DynamicSparsityPattern dsp_2(2); + + PETScWrappers::SparseMatrix K_2(dsp_2); + + if (K_2.begin() == K_2.end()) + deallog << "OK" << std::endl; +} + +int +main(int argc, char **argv) +{ + Utilities::MPI::MPI_InitFinalize mpi_initialization(argc, argv, 1); + initlog(); + test(); +} diff --git a/tests/petsc/matrix_base_iterator_01.output b/tests/petsc/matrix_base_iterator_01.output new file mode 100644 index 0000000000..8b3b075900 --- /dev/null +++ b/tests/petsc/matrix_base_iterator_01.output @@ -0,0 +1,3 @@ + +DEAL::OK +DEAL::OK