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