From cc461c9ae033aa420b7391dc43ed3e95758d1aa9 Mon Sep 17 00:00:00 2001 From: Peter Munch Date: Wed, 27 Oct 2021 20:45:39 +0200 Subject: [PATCH] hp::Collection: allow range-based loop --- doc/news/changes/minor/20210027Munch | 4 + include/deal.II/hp/collection.h | 166 +++++++++++++++++++++++++ tests/hp/collection_iterator_01.cc | 39 ++++++ tests/hp/collection_iterator_01.output | 4 + 4 files changed, 213 insertions(+) create mode 100644 doc/news/changes/minor/20210027Munch create mode 100644 tests/hp/collection_iterator_01.cc create mode 100644 tests/hp/collection_iterator_01.output diff --git a/doc/news/changes/minor/20210027Munch b/doc/news/changes/minor/20210027Munch new file mode 100644 index 0000000000..8a138f3156 --- /dev/null +++ b/doc/news/changes/minor/20210027Munch @@ -0,0 +1,4 @@ +New: You can now perform range-based iterations on hp::FECollecion, hp::QCollection, +and hp::MappingCollection objects. +
+(Peter Munch, 2021/10/27) diff --git a/include/deal.II/hp/collection.h b/include/deal.II/hp/collection.h index 3c1c3ef17e..ebce43e177 100644 --- a/include/deal.II/hp/collection.h +++ b/include/deal.II/hp/collection.h @@ -28,6 +28,140 @@ DEAL_II_NAMESPACE_OPEN namespace hp { + /** + * An iterator for hp::Collection. + */ + template + class CollectionIterator + { + public: + /** + * Constructor. + * + * @param data The actual data of hp::Collection. + * @param index The current index. + */ + CollectionIterator(const std::vector> &data, + const std::size_t index) + : data(&data) + , index(index) + {} + + /** + * Compare for equality. + */ + bool + operator==(const CollectionIterator &other) const + { + Assert( + this->data == other.data, + ExcMessage( + "You are trying to compare iterators into different hp::Collection objects.")); + return this->index == other.index; + } + + /** + * Compare for inequality. + */ + bool + operator!=(const CollectionIterator &other) const + { + Assert( + this->data == other.data, + ExcMessage( + "You are trying to compare iterators into different hp::Collection objects.")); + return this->index != other.index; + } + + /** + * Copy assignment. + */ + CollectionIterator & + operator=(const CollectionIterator &other) = default; + + /** + * Dereferencing operator: returns the value of the current index. + */ + const T & + operator*() const + { + AssertIndexRange(index, data->size()); + return *(*data)[index]; + } + + /** + * Prefix ++ operator: ++iterator. This operator advances + * the iterator to the next index and returns a reference to + * *this. + */ + CollectionIterator & + operator++() + { + AssertIndexRange(index + 1, data->size() + 1); + index++; + return *this; + } + + /** + * This operator advances the iterator by @p offset and returns a + * reference to *this. + */ + CollectionIterator & + operator+=(const std::size_t offset) + { + AssertIndexRange(index + offset, data->size() + 1); + index += offset; + return *this; + } + + /** + * Prefix -- operator: --iterator. This operator advances + * the iterator to the previous index and returns a reference to + * *this. + */ + CollectionIterator & + operator--() + { + Assert( + index > 0, + ExcMessage( + "You can't decrement an iterator that is already at the beginning of the range.")); + --index; + return *this; + } + + /** + * Create new iterator, which is shifted by @p offset. + */ + CollectionIterator + operator+(const std::size_t &offset) const + { + AssertIndexRange(index + offset, T::size() + 1); + return CollectionIterator(*data, index + offset); + } + + /** + * Compute distance between this iterator and iterator @p other. + */ + std::ptrdiff_t + operator-(const CollectionIterator &other) const + { + return static_cast(index) - + static_cast(other.index); + } + + private: + /** + * Pointer to the actual data of hp::Collection. + */ + const std::vector> *data; + + /** + * Current index. + */ + std::size_t index; + }; + /** * This class implements a collection of objects. * @@ -75,6 +209,20 @@ namespace hp std::size_t memory_consumption() const; + /** + * @return An iterator pointing to the beginning of the underlying data (`const` + * version). + */ + CollectionIterator + begin() const; + + /** + * @return An iterator pointing to the end of the underlying data (`const` + * version). + */ + CollectionIterator + end() const; + private: /** * The real container, which stores pointers to the different objects. @@ -122,6 +270,24 @@ namespace hp return *entries[index]; } + + + template + CollectionIterator + Collection::begin() const + { + return CollectionIterator(entries, 0); + } + + + + template + CollectionIterator + Collection::end() const + { + return CollectionIterator(entries, entries.size()); + } + } // namespace hp diff --git a/tests/hp/collection_iterator_01.cc b/tests/hp/collection_iterator_01.cc new file mode 100644 index 0000000000..2fdff5c342 --- /dev/null +++ b/tests/hp/collection_iterator_01.cc @@ -0,0 +1,39 @@ +// --------------------------------------------------------------------- +// +// Copyright (C) 2021 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. +// +// --------------------------------------------------------------------- + + + +// Loop over entries of FECollection. + +#include + +#include + +#include "../tests.h" + +int +main() +{ + initlog(); + + const unsigned int dim = 2; + + hp::FECollection collection(FE_Q(1), FE_Q(2), FE_Q(3)); + + for (const auto &fe : collection) + deallog << fe.n_dofs_per_cell() << std::endl; + + return 0; +} diff --git a/tests/hp/collection_iterator_01.output b/tests/hp/collection_iterator_01.output new file mode 100644 index 0000000000..e974f84983 --- /dev/null +++ b/tests/hp/collection_iterator_01.output @@ -0,0 +1,4 @@ + +DEAL::4 +DEAL::9 +DEAL::16 -- 2.39.5