ESPResSo
Extensible Simulation Package for Research on Soft Matter Systems
Loading...
Searching...
No Matches
BoxGeometry.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
20#pragma once
21
24
25#include <utils/Vector.hpp>
26#include <utils/math/sgn.hpp>
27
28#include <bitset>
29#include <cassert>
30#include <cmath>
31#include <limits>
32#include <stdexcept>
33#include <utility>
34
35namespace detail {
36/**
37 * @brief Get the minimum-image distance between two coordinates.
38 * @param a Coordinate of the terminal point.
39 * @param b Coordinate of the initial point.
40 * @param box_length Box length.
41 * @param box_length_inv Inverse box length
42 * @param box_length_half Half box length
43 * @param periodic Box periodicity.
44 * @return Shortest distance from @p b to @p a across periodic images,
45 * i.e. <tt>a - b</tt>. Can be negative.
46 */
47template <typename T>
48T get_mi_coord(T a, T b, T box_length, T box_length_inv, T box_length_half,
49 bool periodic) {
50 auto const dx = a - b;
51
52 if (periodic && (std::abs(dx) > box_length_half)) {
53 return dx - std::round(dx * box_length_inv) * box_length;
54 }
55
56 return dx;
57}
58
59/**
60 * @brief Get the minimum-image distance between two coordinates.
61 * @param a Coordinate of the terminal point.
62 * @param b Coordinate of the initial point.
63 * @param box_length Box length.
64 * @param periodic Box periodicity.
65 * @return Shortest distance from @p b to @p a across periodic images,
66 * i.e. <tt>a - b</tt>. Can be negative.
67 */
68template <typename T> T get_mi_coord(T a, T b, T box_length, bool periodic) {
69 return get_mi_coord(a, b, box_length, 1. / box_length, 0.5 * box_length,
70 periodic);
71}
72
73/** @brief Calculate image box shift vector.
74 * @param image_box image box offset
75 * @param box box length
76 * @return Image box coordinates.
77 */
78inline auto image_shift(Utils::Vector3i const &image_box,
79 Utils::Vector3d const &box) {
80 return hadamard_product(image_box, box);
81}
82
83/** @brief Unfold particle coordinates to image box.
84 * @param pos coordinate to unfold
85 * @param image_box image box offset
86 * @param box box length
87 * @return Unfolded coordinates.
88 */
89inline auto unfolded_position(Utils::Vector3d const &pos,
90 Utils::Vector3i const &image_box,
91 Utils::Vector3d const &box) {
92 return pos + image_shift(image_box, box);
93}
94} // namespace detail
95
96enum class BoxType { CUBOID = 0, LEES_EDWARDS = 1 };
97
99public:
101 set_length(Utils::Vector3d{1., 1., 1.});
102 set_periodic(0, true);
103 set_periodic(1, true);
104 set_periodic(2, true);
106 }
108 m_type = rhs.type();
109 set_length(rhs.length());
110 set_periodic(0, rhs.periodic(0));
111 set_periodic(1, rhs.periodic(1));
112 set_periodic(2, rhs.periodic(2));
113 m_lees_edwards_bc = rhs.m_lees_edwards_bc;
114 }
115
116private:
117 BoxType m_type = BoxType::CUBOID;
118 /** Flags for all three dimensions whether pbc are applied (default). */
119 std::bitset<3> m_periodic = 0b111;
120 /** Side lengths of the box */
121 Utils::Vector3d m_length = {1., 1., 1.};
122 /** Inverse side lengths of the box */
123 Utils::Vector3d m_length_inv = {1., 1., 1.};
124 /** Half side lengths of the box */
125 Utils::Vector3d m_length_half = {0.5, 0.5, 0.5};
126
127 /** Lees-Edwards boundary conditions */
128 LeesEdwardsBC m_lees_edwards_bc;
129
130public:
131 /**
132 * @brief Set periodicity for direction
133 *
134 * @param coord The coordinate to set the periodicity for.
135 * @param val True if this direction should be periodic.
136 */
137 void set_periodic(unsigned coord, bool val) { m_periodic.set(coord, val); }
138
139 /**
140 * @brief Check periodicity in direction.
141 *
142 * @param coord Direction to check
143 * @return true iff periodic in direction.
144 */
145 constexpr bool periodic(unsigned coord) const {
146 assert(coord <= 2u);
147 return m_periodic[coord];
148 }
149
150 /**
151 * @brief Box length
152 * @return Return vector of side-lengths of the box.
153 */
154 Utils::Vector3d const &length() const { return m_length; }
155
156 /**
157 * @brief Inverse box length
158 * @return Return vector of inverse side-lengths of the box.
159 */
160 Utils::Vector3d const &length_inv() const { return m_length_inv; }
161
162 /**
163 * @brief Half box length
164 * @return Return vector of half side-lengths of the box.
165 */
166 Utils::Vector3d const &length_half() const { return m_length_half; }
167
168 /**
169 * @brief Set box side lengths.
170 * @param box_l Length that should be set.
171 */
172 void set_length(Utils::Vector3d const &box_l) {
173 m_length = box_l;
174 m_length_inv = {1. / box_l[0], 1. / box_l[1], 1. / box_l[2]};
175 m_length_half = 0.5 * box_l;
176 }
177
178 /**
179 * @brief Box volume
180 * @return Return the volume of the box.
181 */
182 double volume() const { return Utils::product(m_length); }
183
184 /**
185 * @brief Get the minimum-image distance between two coordinates.
186 * @param a Coordinate of the terminal point.
187 * @param b Coordinate of the initial point.
188 * @param coord Direction
189 * @return Shortest distance from @p b to @p a across periodic images,
190 * i.e. <tt>a - b</tt>. Can be negative.
191 */
192 template <typename T> T inline get_mi_coord(T a, T b, unsigned coord) const {
193 assert(coord <= 2);
194
195 return detail::get_mi_coord(a, b, m_length[coord], m_length_inv[coord],
196 m_length_half[coord], m_periodic[coord]);
197 }
198
199 /**
200 * @brief Get the minimum-image vector between two coordinates.
201 *
202 * @tparam T Floating point type.
203 *
204 * @param a Coordinate of the terminal point.
205 * @param b Coordinate of the initial point.
206 * @return Vector from @p b to @p a that minimizes the distance across
207 * periodic images, i.e. <tt>a - b</tt>.
208 */
209 template <typename T>
211 const Utils::Vector<T, 3> &b) const {
212 if (type() == BoxType::LEES_EDWARDS) {
213 auto const shear_plane_normal =
214 static_cast<unsigned int>(lees_edwards_bc().shear_plane_normal);
215 auto a_tmp = a;
216 auto b_tmp = b;
217 a_tmp[shear_plane_normal] = Algorithm::periodic_fold(
218 a_tmp[shear_plane_normal], m_length[shear_plane_normal]);
219 b_tmp[shear_plane_normal] = Algorithm::periodic_fold(
220 b_tmp[shear_plane_normal], m_length[shear_plane_normal]);
221 return lees_edwards_bc().distance(a_tmp - b_tmp, m_length, m_length_half,
222 m_length_inv, m_periodic);
223 }
224 assert(type() == BoxType::CUBOID);
225 return {get_mi_coord(a[0], b[0], 0), get_mi_coord(a[1], b[1], 1),
226 get_mi_coord(a[2], b[2], 2)};
227 }
228
229 BoxType type() const { return m_type; }
230 void set_type(BoxType type) { m_type = type; }
231
232 LeesEdwardsBC const &lees_edwards_bc() const { return m_lees_edwards_bc; }
233 void set_lees_edwards_bc(LeesEdwardsBC bc) { m_lees_edwards_bc = bc; }
234
235 /**
236 * @brief Update the Lees-Edwards parameters of the box geometry
237 * for the current simulation time.
238 */
239 void lees_edwards_update(double pos_offset, double shear_velocity) {
240 assert(type() == BoxType::LEES_EDWARDS);
241 m_lees_edwards_bc.pos_offset = pos_offset;
242 m_lees_edwards_bc.shear_velocity = shear_velocity;
243 }
244
245 /** Calculate the velocity difference including the Lees-Edwards velocity */
247 Utils::Vector3d const &y,
248 Utils::Vector3d const &u,
249 Utils::Vector3d const &v) const {
250 auto ret = u - v;
251 if (type() == BoxType::LEES_EDWARDS) {
252 auto const &le = m_lees_edwards_bc;
253 auto const shear_plane_normal =
254 static_cast<unsigned int>(le.shear_plane_normal);
255 auto const shear_direction =
256 static_cast<unsigned int>(le.shear_direction);
257 auto const dy = x[shear_plane_normal] - y[shear_plane_normal];
258 if (fabs(dy) > 0.5 * length_half()[shear_plane_normal]) {
259 ret[shear_direction] -= Utils::sgn(dy) * le.shear_velocity;
260 }
261 }
262 return ret;
263 }
264
265 /** @brief Fold coordinates to primary simulation box in-place.
266 * Lees-Edwards offset is ignored.
267 * @param[in,out] pos coordinate to fold
268 * @param[in,out] image_box image box offset
269 */
271 for (unsigned int i = 0u; i < 3u; i++) {
272 if (m_periodic[i]) {
273 auto const result =
274 Algorithm::periodic_fold(pos[i], image_box[i], m_length[i]);
275 if (result.second == std::numeric_limits<int>::min() or
276 result.second == std::numeric_limits<int>::max()) {
277 throw std::runtime_error(
278 "Overflow in the image box count while folding a particle "
279 "coordinate into the primary simulation box. Maybe a particle "
280 "experienced a huge force.");
281 }
282 std::tie(pos[i], image_box[i]) = result;
283 }
284 }
285 }
286
287 /** @brief Calculate coordinates folded to primary simulation box.
288 * @param p coordinate to fold
289 * @return Folded coordinates.
290 */
291 auto folded_position(Utils::Vector3d const &p) const {
292 Utils::Vector3d p_folded;
293 for (unsigned int i = 0u; i < 3u; i++) {
294 if (m_periodic[i]) {
295 p_folded[i] = Algorithm::periodic_fold(p[i], m_length[i]);
296 } else {
297 p_folded[i] = p[i];
298 }
299 }
300
301 return p_folded;
302 }
303
304 /** @brief Calculate image box shift vector */
305 auto image_shift(Utils::Vector3i const &image_box) const {
306 return detail::image_shift(image_box, m_length);
307 }
308
309 /** @brief Unfold particle coordinates to image box. */
311 Utils::Vector3i const &image_box) const {
312 return detail::unfolded_position(pos, image_box, m_length);
313 }
314};
BoxType
@ LEES_EDWARDS
Vector implementation and trait types for boost qvm interoperability.
__shared__ int pos[MAXDEPTH *THREADS5/WARPSIZE]
float u[3]
auto unfolded_position(Utils::Vector3d const &pos, Utils::Vector3i const &image_box) const
Unfold particle coordinates to image box.
T get_mi_coord(T a, T b, unsigned coord) const
Get the minimum-image distance between two coordinates.
void lees_edwards_update(double pos_offset, double shear_velocity)
Update the Lees-Edwards parameters of the box geometry for the current simulation time.
Utils::Vector3d const & length() const
Box length.
LeesEdwardsBC const & lees_edwards_bc() const
BoxGeometry(BoxGeometry const &rhs)
constexpr bool periodic(unsigned coord) const
Check periodicity in direction.
double volume() const
Box volume.
auto folded_position(Utils::Vector3d const &p) const
Calculate coordinates folded to primary simulation box.
BoxType type() const
auto image_shift(Utils::Vector3i const &image_box) const
Calculate image box shift vector.
Utils::Vector< T, 3 > get_mi_vector(const Utils::Vector< T, 3 > &a, const Utils::Vector< T, 3 > &b) const
Get the minimum-image vector between two coordinates.
Utils::Vector3d const & length_half() const
Half box length.
Utils::Vector3d const & length_inv() const
Inverse box length.
void set_periodic(unsigned coord, bool val)
Set periodicity for direction.
void set_length(Utils::Vector3d const &box_l)
Set box side lengths.
void set_lees_edwards_bc(LeesEdwardsBC bc)
void fold_position(Utils::Vector3d &pos, Utils::Vector3i &image_box) const
Fold coordinates to primary simulation box in-place.
Utils::Vector3d velocity_difference(Utils::Vector3d const &x, Utils::Vector3d const &y, Utils::Vector3d const &u, Utils::Vector3d const &v) const
Calculate the velocity difference including the Lees-Edwards velocity.
void set_type(BoxType type)
std::pair< T, I > periodic_fold(T x, I i, T const l)
Fold value into primary interval.
T product(Vector< T, N > const &v)
Definition Vector.hpp:359
constexpr int sgn(T val)
Calculate signum of val.
Definition sgn.hpp:27
auto hadamard_product(Vector< T, N > const &a, Vector< U, N > const &b)
Definition Vector.hpp:364
Utils::Vector3d distance(Utils::Vector3d const &d, Utils::Vector3d const &l, Utils::Vector3d const &hal_l, Utils::Vector3d const &l_inv, std::bitset< 3 > const periodic) const
unsigned int shear_plane_normal