ESPResSo
Extensible Simulation Package for Research on Soft Matter Systems
Loading...
Searching...
No Matches
Rhomboid.cpp
Go to the documentation of this file.
1/*
2 * Copyright (C) 2010-2026 The ESPResSo project
3 * Copyright (C) 2002,2003,2004,2005,2006,2007,2008,2009,2010
4 * Max-Planck-Institute for Polymer Research, Theory Group
5 *
6 * This file is part of ESPResSo.
7 *
8 * ESPResSo is free software: you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation, either version 3 of the License, or
11 * (at your option) any later version.
12 *
13 * ESPResSo is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program. If not, see <http://www.gnu.org/licenses/>.
20 */
21
22#include <shapes/Rhomboid.hpp>
23
24#include <utils/Vector.hpp>
25
26#include <cmath>
27#include <functional>
28
29namespace Shapes {
31 Utils::Vector3d &vec) const {
32
33 auto constexpr le = std::less_equal<double>();
34 auto constexpr ge = std::greater_equal<double>();
35 auto constexpr lt = std::less<double>();
36 auto constexpr gt = std::greater<double>();
37
38 // calculate vectors and scalars that are going to be used frequently
39
40 auto const axb = vector_product(m_a, m_b);
41 auto const bxc = vector_product(m_b, m_c);
42 auto const axc = vector_product(m_a, m_c);
43
44 auto const a_dot_bxc = m_a * bxc;
45 auto const b_dot_axc = m_b * axc;
46 auto const c_dot_axb = m_c * axb;
47
48 auto const dpos = pos - m_pos;
49
50 // compute distance from the rhomboid corners, edges and faces using linear
51 // combinations of the rhomboid edge vectors
52
53 auto const corner =
54 [this, &vec, &dist, a = bxc / a_dot_bxc, b = axc / b_dot_axc,
55 c = axb / c_dot_axb](auto const op1, auto const op2, auto const op3,
56 Utils::Vector3d const &d) {
57 /* coefficients A, B, C tell whether ppos lies within a cone defined
58 * by pos and the adjacent edges */
59 auto const A = a * d;
60 auto const B = b * d;
61 auto const C = c * d;
62 if (op1(A, 0) and op2(B, 0) and op3(C, 0)) {
63 vec = d;
64 dist = m_direction * vec.norm();
65 return true;
66 }
67 return false;
68 };
69
70 if ( // check for cone at m_pos
71 corner(le, le, le, dpos) ||
72 // check for cone at m_pos+a
73 corner(ge, le, le, dpos - m_a) ||
74 // check for cone at m_pos+b
75 corner(le, ge, le, dpos - m_b) ||
76 // check for cone at m_pos+c
77 corner(le, le, ge, dpos - m_c) ||
78 // check for cone at m_pos+a+b
79 corner(ge, ge, le, dpos - m_a - m_b) ||
80 // check for cone at m_pos+a+c
81 corner(ge, le, ge, dpos - m_a - m_c) ||
82 // check for cone at m_pos+b+c
83 corner(le, ge, ge, dpos - m_b - m_c) ||
84 // check for cone at m_pos+a+b+c
85 corner(ge, ge, ge, dpos - m_a - m_b - m_c))
86 return;
87
88 auto const edge = [this, &vec, &dist](auto const op1, auto const op2,
89 Utils::Vector3d const &d,
91 double const dir1_dot_axis1,
93 double const dir2_dot_axis2,
95 auto const A = (d * axis1) / dir1_dot_axis1;
96 auto const B = (d * axis2) / dir2_dot_axis2;
97 if (op1(A, 0) and op2(B, 0)) {
98 auto const tmp = (d * shape_edge) / shape_edge.norm2();
99 vec = d - shape_edge * tmp;
100 dist = m_direction * vec.norm();
101 return true;
102 }
103 return false;
104 };
105
106 if ( // check for prism at edge m_pos, a
107 edge(le, le, dpos, axc, b_dot_axc, axb, c_dot_axb, m_a) ||
108 // check for prism at edge m_pos, b
109 edge(le, le, dpos, bxc, a_dot_bxc, axb, c_dot_axb, m_b) ||
110 // check for prism at edge m_pos, c
111 edge(le, le, dpos, bxc, a_dot_bxc, axc, b_dot_axc, m_c) ||
112 // check for prism at edge m_pos+a, b
113 edge(ge, le, dpos - m_a, bxc, a_dot_bxc, axb, c_dot_axb, m_b) ||
114 // check for prism at edge m_pos+a, c
115 edge(ge, le, dpos - m_a, bxc, a_dot_bxc, axc, b_dot_axc, m_c) ||
116 // check for prism at edge m_pos+b+c, c
117 edge(le, ge, dpos - m_b - m_c, bxc, a_dot_bxc, axc, b_dot_axc, m_c) ||
118 // check for prism at edge m_pos+b+c, b
119 edge(le, ge, dpos - m_b - m_c, bxc, a_dot_bxc, axb, c_dot_axb, m_b) ||
120 // check for prism at edge m_pos+b+c, a
121 edge(ge, ge, dpos - m_b - m_c, axc, b_dot_axc, axb, c_dot_axb, m_a) ||
122 // check for prism at edge m_pos+a+b, a
123 edge(ge, le, dpos - m_a - m_b, axc, b_dot_axc, axb, c_dot_axb, m_a) ||
124 // check for prism at edge m_pos+a+b, c
125 edge(ge, ge, dpos - m_a - m_b, bxc, a_dot_bxc, axc, b_dot_axc, m_c) ||
126 // check for prism at edge m_pos+a+c, a
127 edge(le, ge, dpos - m_a - m_c, axc, b_dot_axc, axb, c_dot_axb, m_a) ||
128 // check for prism at edge m_pos+a+c, b
129 edge(ge, ge, dpos - m_a - m_c, bxc, a_dot_bxc, axb, c_dot_axb, m_b))
130 return;
131
132 auto const face_outside = [this, &vec, &dist](auto const op1, auto const op2,
133 Utils::Vector3d const &distance,
134 Utils::Vector3d const &axis,
135 double const dir_dot_axis,
136 int sign) {
137 auto d = distance * axis;
138 if (op1(dir_dot_axis, 0)) {
139 d *= -1;
140 }
141 if (d >= 0) {
142 auto const tmp = axis.norm();
143 d /= tmp;
144 dist = d * m_direction;
145 if (op2(dir_dot_axis, 0)) {
146 d *= -1;
147 }
148 vec = (sign * d / tmp) * axis;
149 return true;
150 }
151 return false;
152 };
153
154 if ( // check for face with normal -axb
155 face_outside(gt, lt, dpos, axb, c_dot_axb, -1) ||
156 // calculate distance to face with normal axc
157 face_outside(gt, gt, dpos, axc, b_dot_axc, +1) ||
158 // calculate distance to face with normal -bxc
159 face_outside(gt, lt, dpos, bxc, a_dot_bxc, -1) ||
160 // calculate distance to face with normal axb
161 face_outside(lt, lt, dpos - m_a - m_b - m_c, axb, c_dot_axb, +1) ||
162 // calculate distance to face with normal -axc
163 face_outside(lt, gt, dpos - m_a - m_b - m_c, axc, b_dot_axc, -1) ||
164 // calculate distance to face with normal bxc
165 face_outside(lt, lt, dpos - m_a - m_b - m_c, bxc, a_dot_bxc, +1))
166 return;
167
168 // ppos lies within rhomboid.
169 // Find nearest wall for interaction (test all 6 possibilities).
170
171 // calculate distance to face with normal -axb
172 {
173 auto d = dpos * axb;
174 if (c_dot_axb > 0.0) {
175 d *= -1;
176 }
177 auto const tmp = axb.norm();
178 d /= tmp;
179 dist = d * m_direction;
180 if (c_dot_axb < 0.0) {
181 d *= -1;
182 }
183 vec = (-d / tmp) * axb;
184 }
185
186 auto const face_inside = [this, &vec, &dist](auto const op1, auto const op2,
187 Utils::Vector3d const &distance,
188 Utils::Vector3d const &axis,
189 double const dir_dot_axis,
190 int sign) {
191 auto d = distance * axis;
192 if (op1(dir_dot_axis, 0)) {
193 d *= -1;
194 }
195 auto const tmp = axis.norm();
196 d /= tmp;
197 if (std::abs(d) < std::abs(dist)) {
198 dist = d * m_direction;
199 if (op2(dir_dot_axis, 0)) {
200 d *= -1;
201 }
202 vec = (sign * d / tmp) * axis;
203 }
204 };
205
206 // calculate distance to face with normal axc
208 // calculate distance to face with normal -bxc
210 // calculate distance to face with normal axb
211 face_inside(lt, lt, dpos - m_a - m_b - m_c, axb, c_dot_axb, +1);
212 // calculate distance to face with normal -axc
213 face_inside(lt, gt, dpos - m_a - m_b - m_c, axc, b_dot_axc, -1);
214 // calculate distance to face with normal bxc
215 face_inside(lt, lt, dpos - m_a - m_b - m_c, bxc, a_dot_bxc, +1);
216}
217
218} // namespace Shapes
Vector implementation and trait types for boost qvm interoperability.
void calculate_dist(const Utils::Vector3d &pos, double &dist, Utils::Vector3d &vec) const override
Definition Rhomboid.cpp:30
cudaStream_t stream[1]
CUDA streams for parallel computing on CPU and GPU.
__device__ void vector_product(float const *a, float const *b, float *out)