ESPResSo
Extensible Simulation Package for Research on Soft Matter Systems
Loading...
Searching...
No Matches
BondList.hpp
Go to the documentation of this file.
1/*
2 * Copyright (C) 2020-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_BONDLIST_HPP
20#define ESPRESSO_BONDLIST_HPP
21
22#include <utils/Span.hpp>
24
25#include <boost/container/vector.hpp>
26#include <boost/iterator/iterator_facade.hpp>
27#include <boost/range/algorithm/copy.hpp>
28#include <boost/serialization/access.hpp>
29#include <boost/serialization/array.hpp>
30#include <boost/version.hpp>
31
32#include <algorithm>
33#include <cassert>
34#include <cstddef>
35#include <memory>
36#include <type_traits>
37
38/**
39 * @brief Immutable view on a bond.
40 *
41 * The bond id and ids of the partner particles
42 * of a bond can be inspected (but not changed)
43 * via this view.
44 */
45class BondView {
46 /* Bond id */
47 int m_id = -1;
48 Utils::Span<const int> m_partners;
49
50public:
51 BondView() = default;
53 : m_id(id), m_partners(partners) {}
54
55 int bond_id() const { return m_id; }
56 Utils::Span<const int> const &partner_ids() const { return m_partners; }
57
58 bool operator==(BondView const &rhs) const {
59 return m_id == rhs.m_id and boost::equal(m_partners, rhs.m_partners);
60 }
61
62 bool operator!=(BondView const &rhs) const { return not(*this == rhs); }
63};
64
65/**
66 * @brief Bond storage.
67 *
68 * This holds the bonds of a particle.
69 *
70 * Implementation notes:
71 * Internally the bond list is represented as a sequence of
72 * integers. For each bond, first the ids of the bond partners
73 * are stored (which are positive numbers), then the negative
74 * of the value of the id of the bond plus one (which also is positive) is
75 * stored. This way we can use the sign bit of the int as a delimiter,
76 * every time a negative number is encountered one bond ends, and
77 * a new one starts. This mechanism allows us to efficiently store
78 * bonds of different numbers of partners in contiguous memory.
79 *
80 * This is hidden from the client by providing access to the
81 * bonds only thru iterators that restore the semantic meanings
82 * of the entries, and know how to proceed to the next bond.
83 *
84 */
85class BondList {
86public:
88
89private:
90 using storage_iterator = storage_type::const_iterator;
91
92 /**
93 * @brief Find the end of bond.
94 *
95 * @param it Valid iterator into the underlying storage.
96 * @return iterator pointing to the last element of the bond.
97 */
98 static storage_iterator find_end(storage_iterator it) {
99 while (*it >= 0) {
100 ++it;
101 }
102 return it;
103 }
104
105 storage_type m_storage;
106
107 friend boost::serialization::access;
108 template <class Archive> void serialize(Archive &ar, long int /* version */) {
109 if (Archive::is_loading::value) {
110 std::size_t size{};
111 ar & size;
112 m_storage.resize(size);
113 }
114
115 if (Archive::is_saving::value) {
116 auto size = m_storage.size();
117 ar & size;
118 }
119
120 ar &boost::serialization::make_array(m_storage.data(), m_storage.size());
121 }
122
123public:
125 : public boost::iterator_facade<Iterator, BondView,
126 boost::forward_traversal_tag, BondView> {
127 public:
128 explicit Iterator(storage_iterator it) : m_it(it) {}
129
130 private:
131 /** Iterator into the bond list */
132 storage_iterator m_it;
133
134 friend BondList;
135 friend boost::iterator_core_access;
136 void increment() { m_it = std::next(find_end(m_it)); }
137 bool equal(Iterator const &other) const { return this->m_it == other.m_it; }
138 BondView dereference() const {
139 auto const id_pos = find_end(m_it);
140 auto const partners_begin = m_it;
141 auto const partners_end = id_pos;
142 auto const dist = std::distance(partners_begin, partners_end);
143 return {-(*id_pos) - 1, Utils::make_span(std::addressof(*partners_begin),
144 static_cast<size_type>(dist))};
145 }
146 };
147
148public:
150 using reference = std::add_lvalue_reference_t<BondView>;
151 using const_reference = std::add_const_t<reference>;
152 using size_type = std::size_t;
153 using difference_type = std::ptrdiff_t;
156
157 BondList() = default;
158 BondList(BondList const &) = default;
159 BondList(BondList &&) = default;
161 if (this != std::addressof(rhs)) {
162 m_storage = rhs.m_storage;
163 }
164
165 return *this;
166 }
167 // NOLINTNEXTLINE(bugprone-exception-escape)
168 BondList &operator=(BondList &&rhs) noexcept {
169 if (this != std::addressof(rhs)) {
170 std::swap(m_storage, rhs.m_storage);
171 }
172
173 return *this;
174 }
175
176 /**
177 * @brief Iterator to the beginning of the range of bonds in the list.
178 */
179 const_iterator begin() const { return Iterator{m_storage.begin()}; }
180 /**
181 * @brief Iterator past the end of the range of bonds in the list.
182 */
183 const_iterator end() const { return Iterator{m_storage.end()}; }
184
185 /**
186 * @brief Add a bond to the list.
187 *
188 * @param bond Bond to add.
189 */
190 void insert(BondView const &bond) {
191 boost::copy(bond.partner_ids(), std::back_inserter(m_storage));
192 assert(bond.bond_id() >= 0);
193 m_storage.push_back(-(bond.bond_id() + 1));
194 }
195
196 /**
197 * @brief Erase a bond from the list.
198 * @param pos Iterator pointing to element to erase.
199 * @return iterator pointing one past the erased element.
200 */
202 return Iterator{m_storage.erase(pos.m_it, std::next(find_end(pos.m_it)))};
203 }
204
205 /**
206 * @brief Number of bonds.
207 * @return The number of bonds in the list.
208 */
209 auto size() const {
210 return static_cast<size_type>(std::distance(begin(), end()));
211 }
212
213 /**
214 * @brief Erase all bonds from the list.
215 */
216 void clear() { m_storage.clear(); }
217
218 /**
219 * @brief Check if the are any bonds in the list.
220 */
221 bool empty() const { return m_storage.empty(); }
222
223 // NOLINTNEXTLINE(bugprone-exception-escape)
224 friend void swap(BondList &lhs, BondList &rhs) {
225 using std::swap;
226
227 swap(lhs.m_storage, rhs.m_storage);
228 }
229};
230
231/**
232 * @brief Check if there is a specific bond in a bond list.
233 *
234 * @param bonds List of bonds to check
235 * @param partner_id Id of the bond partner
236 * @param bond_id Id of the bond parameters.
237 * @return True iff there is a bond to the specified id of the specified type.
238 */
239inline bool pair_bond_exists_on(BondList const &bonds, int partner_id,
240 int bond_id) {
241 return std::any_of(bonds.begin(), bonds.end(), [=](BondView const &bond) {
242 return (bond.bond_id() == bond_id) and
243 (bond.partner_ids()[0] == partner_id);
244 });
245}
246
247#endif // ESPRESSO_BONDLIST_HPP
bool pair_bond_exists_on(BondList const &bonds, int partner_id, int bond_id)
Check if there is a specific bond in a bond list.
Definition BondList.hpp:239
__shared__ int pos[MAXDEPTH *THREADS5/WARPSIZE]
Iterator(storage_iterator it)
Definition BondList.hpp:128
Bond storage.
Definition BondList.hpp:85
BondList(BondList const &)=default
const_iterator erase(const_iterator pos)
Erase a bond from the list.
Definition BondList.hpp:201
BondList(BondList &&)=default
BondList & operator=(BondList const &rhs)
Definition BondList.hpp:160
friend void swap(BondList &lhs, BondList &rhs)
Definition BondList.hpp:224
const_iterator begin() const
Iterator to the beginning of the range of bonds in the list.
Definition BondList.hpp:179
std::add_const_t< reference > const_reference
Definition BondList.hpp:151
Utils::compact_vector< int > storage_type
Definition BondList.hpp:87
void insert(BondView const &bond)
Add a bond to the list.
Definition BondList.hpp:190
auto size() const
Number of bonds.
Definition BondList.hpp:209
std::ptrdiff_t difference_type
Definition BondList.hpp:153
void clear()
Erase all bonds from the list.
Definition BondList.hpp:216
const_iterator end() const
Iterator past the end of the range of bonds in the list.
Definition BondList.hpp:183
BondList()=default
bool empty() const
Check if the are any bonds in the list.
Definition BondList.hpp:221
std::add_lvalue_reference_t< BondView > reference
Definition BondList.hpp:150
BondList & operator=(BondList &&rhs) noexcept
Definition BondList.hpp:168
std::size_t size_type
Definition BondList.hpp:152
Immutable view on a bond.
Definition BondList.hpp:45
BondView(int id, Utils::Span< const int > partners)
Definition BondList.hpp:52
int bond_id() const
Definition BondList.hpp:55
bool operator!=(BondView const &rhs) const
Definition BondList.hpp:62
bool operator==(BondView const &rhs) const
Definition BondList.hpp:58
BondView()=default
Utils::Span< const int > const & partner_ids() const
Definition BondList.hpp:56
A stripped-down version of std::span from C++17.
Definition Span.hpp:38
DEVICE_QUALIFIER constexpr Span< T > make_span(T *p, std::size_t N)
Definition Span.hpp:112