Skip to content

Commit

Permalink
hp::Collection: allow range-based loop
Browse files Browse the repository at this point in the history
  • Loading branch information
peterrum committed Oct 27, 2021
1 parent 21e7779 commit cc461c9
Show file tree
Hide file tree
Showing 4 changed files with 213 additions and 0 deletions.
4 changes: 4 additions & 0 deletions doc/news/changes/minor/20210027Munch
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
New: You can now perform range-based iterations on hp::FECollecion, hp::QCollection,
and hp::MappingCollection objects.
<br>
(Peter Munch, 2021/10/27)
166 changes: 166 additions & 0 deletions include/deal.II/hp/collection.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,140 @@ DEAL_II_NAMESPACE_OPEN

namespace hp
{
/**
* An iterator for hp::Collection.
*/
template <typename T>
class CollectionIterator
{
public:
/**
* Constructor.
*
* @param data The actual data of hp::Collection.
* @param index The current index.
*/
CollectionIterator(const std::vector<std::shared_ptr<const T>> &data,
const std::size_t index)
: data(&data)
, index(index)
{}

/**
* Compare for equality.
*/
bool
operator==(const CollectionIterator<T> &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<T> &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<T> &
operator=(const CollectionIterator<T> &other) = default;

/**
* Dereferencing operator: returns the value of the current index.
*/
const T &
operator*() const
{
AssertIndexRange(index, data->size());
return *(*data)[index];
}

/**
* Prefix <tt>++</tt> operator: <tt>++iterator</tt>. This operator advances
* the iterator to the next index and returns a reference to
* <tt>*this</tt>.
*/
CollectionIterator<T> &
operator++()
{
AssertIndexRange(index + 1, data->size() + 1);
index++;
return *this;
}

/**
* This operator advances the iterator by @p offset and returns a
* reference to <tt>*this</tt>.
*/
CollectionIterator<T> &
operator+=(const std::size_t offset)
{
AssertIndexRange(index + offset, data->size() + 1);
index += offset;
return *this;
}

/**
* Prefix <tt>--</tt> operator: <tt>--iterator</tt>. This operator advances
* the iterator to the previous index and returns a reference to
* <tt>*this</tt>.
*/
CollectionIterator<T> &
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<T>
operator+(const std::size_t &offset) const
{
AssertIndexRange(index + offset, T::size() + 1);
return CollectionIterator<T>(*data, index + offset);
}

/**
* Compute distance between this iterator and iterator @p other.
*/
std::ptrdiff_t
operator-(const CollectionIterator<T> &other) const
{
return static_cast<std::ptrdiff_t>(index) -
static_cast<ptrdiff_t>(other.index);
}

private:
/**
* Pointer to the actual data of hp::Collection.
*/
const std::vector<std::shared_ptr<const T>> *data;

/**
* Current index.
*/
std::size_t index;
};

/**
* This class implements a collection of objects.
*
Expand Down Expand Up @@ -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<T>
begin() const;

/**
* @return An iterator pointing to the end of the underlying data (`const`
* version).
*/
CollectionIterator<T>
end() const;

private:
/**
* The real container, which stores pointers to the different objects.
Expand Down Expand Up @@ -122,6 +270,24 @@ namespace hp
return *entries[index];
}



template <typename T>
CollectionIterator<T>
Collection<T>::begin() const
{
return CollectionIterator<T>(entries, 0);
}



template <typename T>
CollectionIterator<T>
Collection<T>::end() const
{
return CollectionIterator<T>(entries, entries.size());
}

} // namespace hp


Expand Down
39 changes: 39 additions & 0 deletions tests/hp/collection_iterator_01.cc
Original file line number Diff line number Diff line change
@@ -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 <deal.II/fe/fe_q.h>

#include <deal.II/hp/fe_collection.h>

#include "../tests.h"

int
main()
{
initlog();

const unsigned int dim = 2;

hp::FECollection<dim> collection(FE_Q<dim>(1), FE_Q<dim>(2), FE_Q<dim>(3));

for (const auto &fe : collection)
deallog << fe.n_dofs_per_cell() << std::endl;

return 0;
}
4 changes: 4 additions & 0 deletions tests/hp/collection_iterator_01.output
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@

DEAL::4
DEAL::9
DEAL::16

0 comments on commit cc461c9

Please sign in to comment.