Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

hp::Collection: allow range-based loop #12893

Merged
merged 1 commit into from
Oct 27, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
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