From 5db29256434155b5fcaab057d27d8648a627f7b2 Mon Sep 17 00:00:00 2001 From: Wolfgang Bangerth Date: Thu, 10 Jan 2019 07:01:48 -0700 Subject: [PATCH] Fix a number of exceptions in Triangulation::begin/end/last_...(). --- include/deal.II/grid/tria.h | 10 ++- source/grid/tria.cc | 122 ++++++++++++++++++++++++++++++++---- 2 files changed, 117 insertions(+), 15 deletions(-) diff --git a/include/deal.II/grid/tria.h b/include/deal.II/grid/tria.h index b73071eaa2..88be12f2a2 100644 --- a/include/deal.II/grid/tria.h +++ b/include/deal.II/grid/tria.h @@ -3394,10 +3394,14 @@ public: * * @ingroup Exceptions */ - DeclException1(ExcInvalidLevel, + DeclException2(ExcInvalidLevel, int, - << "The given level " << arg1 - << " is not in the valid range!"); + int, + << "You are requesting information from refinement level " + << arg1 + << " of a triangulation, but this triangulation only has " + << arg2 << " refinement levels. The given level " << arg1 + << " must be *less* than " << arg2 << "."); /** * The function raising this exception can only operate on an empty * Triangulation, i.e., a Triangulation without grid cells. diff --git a/source/grid/tria.cc b/source/grid/tria.cc index 3f1da7e211..19dcf0c48d 100644 --- a/source/grid/tria.cc +++ b/source/grid/tria.cc @@ -12015,7 +12015,24 @@ template typename Triangulation::raw_cell_iterator Triangulation::end_raw(const unsigned int level) const { - Assert(level < n_global_levels(), ExcInvalidLevel(level)); + // This function may be called on parallel triangulations on levels + // that exist globally, but not on the local portion of the + // triangulation. In that case, just return the end iterator. + // + // We need to use levels.size() instead of n_levels() because the + // latter function uses the cache, but we need to be able to call + // this function at a time when the cache is not currently up to + // date. + if (level >= levels.size()) + { + Assert(level < n_global_levels(), + ExcInvalidLevel(level, n_global_levels())); + return end(); + } + + // Query whether the given level is valid for the local portion of the + // triangulation. + Assert(level < levels.size(), ExcInvalidLevel(level, levels.size())); if (level < levels.size() - 1) return begin_raw(level + 1); else @@ -12027,11 +12044,28 @@ template typename Triangulation::cell_iterator Triangulation::end(const unsigned int level) const { + // This function may be called on parallel triangulations on levels + // that exist globally, but not on the local portion of the + // triangulation. In that case, just retrn the end iterator. + // + // We need to use levels.size() instead of n_levels() because the + // latter function uses the cache, but we need to be able to call + // this function at a time when the cache is not currently up to + // date. + if (level >= levels.size()) + { + Assert(level < n_global_levels(), + ExcInvalidLevel(level, n_global_levels())); + return end(); + } + + // Query whether the given level is valid for the local portion of the + // triangulation. + Assert(level < levels.size(), ExcInvalidLevel(level, levels.size())); if (level < levels.size() - 1) return begin(level + 1); - Assert(level < n_global_levels() || level < levels.size(), - ExcInvalidLevel(level)); - return end(); + else + return end(); } @@ -12039,8 +12073,24 @@ template typename Triangulation::active_cell_iterator Triangulation::end_active(const unsigned int level) const { - Assert(level < n_global_levels() || level < levels.size(), - ExcInvalidLevel(level)); + // This function may be called on parallel triangulations on levels + // that exist globally, but not on the local portion of the + // triangulation. In that case, just return the end iterator. + // + // We need to use levels.size() instead of n_levels() because the + // latter function uses the cache, but we need to be able to call + // this function at a time when the cache is not currently up to + // date. + if (level >= levels.size()) + { + Assert(level < n_global_levels(), + ExcInvalidLevel(level, n_global_levels())); + return end(); + } + + // Query whether the given level is valid for the local portion of the + // triangulation. + Assert(level < levels.size(), ExcInvalidLevel(level, levels.size())); return (level >= levels.size() - 1 ? active_cell_iterator(end()) : begin_active(level + 1)); } @@ -12213,11 +12263,27 @@ template typename Triangulation::raw_line_iterator Triangulation::begin_raw_line(const unsigned int level) const { + // This function may be called on parallel triangulations on levels + // that exist globally, but not on the local portion of the + // triangulation. In that case, just return the end iterator. + // + // We need to use levels.size() instead of n_levels() because the + // latter function uses the cache, but we need to be able to call + // this function at a time when the cache is not currently up to + // date. + if (level >= levels.size()) + { + Assert(level < n_global_levels(), + ExcInvalidLevel(level, n_global_levels())); + return end_line(); + } + switch (dim) { case 1: - Assert(level < n_global_levels() || level < levels.size(), - ExcInvalidLevel(level)); + // Query whether the given level is valid for the local portion of the + // triangulation. + Assert(level < levels.size(), ExcInvalidLevel(level, levels.size())); if (level >= levels.size() || levels[level]->cells.cells.size() == 0) return end_line(); @@ -12283,6 +12349,21 @@ template typename Triangulation::raw_quad_iterator Triangulation::begin_raw_quad(const unsigned int level) const { + // This function may be called on parallel triangulations on levels + // that exist globally, but not on the local portion of the + // triangulation. In that case, just return the end iterator. + // + // We need to use levels.size() instead of n_levels() because the + // latter function uses the cache, but we need to be able to call + // this function at a time when the cache is not currently up to + // date. + if (level >= levels.size()) + { + Assert(level < n_global_levels(), + ExcInvalidLevel(level, n_global_levels())); + return end_quad(); + } + switch (dim) { case 1: @@ -12290,8 +12371,9 @@ Triangulation::begin_raw_quad(const unsigned int level) const return raw_hex_iterator(); case 2: { - Assert(level < n_global_levels() || level < levels.size(), - ExcInvalidLevel(level)); + // Query whether the given level is valid for the local portion of the + // triangulation. + Assert(level < levels.size(), ExcInvalidLevel(level, levels.size())); if (level >= levels.size() || levels[level]->cells.cells.size() == 0) return end_quad(); @@ -12366,6 +12448,21 @@ template typename Triangulation::raw_hex_iterator Triangulation::begin_raw_hex(const unsigned int level) const { + // This function may be called on parallel triangulations on levels + // that exist globally, but not on the local portion of the + // triangulation. In that case, just return the end iterator. + // + // We need to use levels.size() instead of n_levels() because the + // latter function uses the cache, but we need to be able to call + // this function at a time when the cache is not currently up to + // date. + if (level >= levels.size()) + { + Assert(level < n_global_levels(), + ExcInvalidLevel(level, n_global_levels())); + return end_hex(); + } + switch (dim) { case 1: @@ -12374,8 +12471,9 @@ Triangulation::begin_raw_hex(const unsigned int level) const return raw_hex_iterator(); case 3: { - Assert(level < n_global_levels() || level < levels.size(), - ExcInvalidLevel(level)); + // Query whether the given level is valid for the local portion of the + // triangulation. + Assert(level < levels.size(), ExcInvalidLevel(level, levels.size())); if (level >= levels.size() || levels[level]->cells.cells.size() == 0) return end_hex(); -- 2.39.5