ESPResSo
Extensible Simulation Package for Research on Soft Matter Systems
Loading...
Searching...
No Matches
ParticleIterator.hpp
Go to the documentation of this file.
1/*
2 * Copyright (C) 2010-2022 The ESPResSo project
3 *
4 * This file is part of ESPResSo.
5 *
6 * ESPResSo is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * ESPResSo is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19#ifndef ESPRESSO_SRC_CORE_PARTICLE_ITERATOR_HPP
20#define ESPRESSO_SRC_CORE_PARTICLE_ITERATOR_HPP
21
22#include <boost/iterator/iterator_facade.hpp>
23
24#include <cassert>
25#include <iterator>
26#include <utility>
27
28namespace detail {
29/* Detect the particle iterator type for a given cell iterator type. */
30template <class CellIterator>
31using particle_iterator_t =
32 decltype((*std::declval<CellIterator>())->particles().begin());
33/* Detect the particle type for a given cell iterator type. */
34template <class CellIterator>
35using particle_t = typename std::iterator_traits<
36 particle_iterator_t<CellIterator>>::value_type;
37} // namespace detail
38
39template <typename BidirectionalIterator>
41 : public boost::iterator_facade<ParticleIterator<BidirectionalIterator>,
42 detail::particle_t<BidirectionalIterator>,
43 boost::forward_traversal_tag> {
44private:
45 using base_type =
46 boost::iterator_facade<ParticleIterator<BidirectionalIterator>,
47 detail::particle_t<BidirectionalIterator>,
48 boost::forward_traversal_tag>;
49 using particle_iterator = detail::particle_iterator_t<BidirectionalIterator>;
50
51 BidirectionalIterator m_cell, m_end;
52 particle_iterator m_part;
53
54public:
55 ParticleIterator(BidirectionalIterator cell, BidirectionalIterator end)
56 : m_cell(cell), m_end(end) {
57 m_part = (m_cell != m_end) ? (*m_cell)->particles().begin()
58 : particle_iterator();
59 }
60
61 ParticleIterator(BidirectionalIterator end)
62 : m_cell(end), m_end(end), m_part() {}
63
64private:
65 friend typename base_type::difference_type
66 distance(ParticleIterator const &begin, ParticleIterator const &end) {
67 if (begin == end)
68 return 0;
69
70 /* Remaining parts in this cell */
71 auto dist = std::distance(begin.m_part, (*begin.m_cell)->particles().end());
72 /* Now add the size of all cells between the next
73 one and the last one */
74 auto it = std::next(begin.m_cell);
75
76 while (it != end.m_cell) {
77 dist += (*it)->particles().size();
78 ++it;
79 }
80
81 return dist;
82 }
83
85
86 void increment() {
87 assert(m_cell != m_end);
88
89 ++m_part;
90 /* If we are at the end of the particle range of the current cell,
91 * we have to go to the next cell with particles. */
92 if (m_part == (*m_cell)->particles().end()) {
93 /* Find next cell with particles, without running over the end. */
94 do {
95 ++m_cell;
96 } while ((m_cell != m_end) && ((*m_cell)->particles().empty()));
97
98 /* If there is a cell, start go to its beginning. */
99 m_part = (m_cell != m_end) ? (*m_cell)->particles().begin()
100 : particle_iterator();
101 }
102 }
103
104 bool equal(ParticleIterator const &rhs) const {
105 return (m_cell == (rhs.m_cell)) && (m_part == rhs.m_part);
106 }
107
108 auto &dereference() const { return *m_part; }
109};
110
111#endif
ParticleRange particles(Utils::Span< Cell *const > cells)
ParticleIterator(BidirectionalIterator end)
ParticleIterator(BidirectionalIterator cell, BidirectionalIterator end)
friend base_type::difference_type distance(ParticleIterator const &begin, ParticleIterator const &end)
friend class boost::iterator_core_access