ESPResSo
Extensible Simulation Package for Research on Soft Matter Systems
Loading...
Searching...
No Matches
SimplePore.cpp
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#include <shapes/SimplePore.hpp>
21
22#include <utils/Vector.hpp>
23
24#include <cassert>
25#include <cmath>
26#include <utility>
27
28namespace Shapes {
29/**
30 * @brief Calculate the distance function in the coordinates of the cylinder.
31 *
32 * @param r Distance from the cylinder axis.
33 * @param z Distance from the center along the axis.
34 *
35 * @returns The distance vector from the surface in the cylinder system.
36 */
37std::pair<double, double> SimplePore::dist_half_pore(double r, double z) const {
38 assert(z >= 0.0);
39 assert(r >= 0.0);
40
41 /*
42 * We have to find the line that splits area 1 (r determines distance) from
43 * area 2 (z determines distance) inside pore. In area 3 we have to consider
44 * z and r to determine the distance.
45 *
46 * | x
47 * | 2 x
48 * | x
49 * _|_ x 1
50 * \| ^ r
51 * 3 |-------|
52 * | z <-
53 */
54
55 if ((z <= c_z) && (r <= (c_z + c_r - z))) {
56 /* Cylinder section, inner */
57 return {m_rad - r, 0};
58 }
59 if (((z >= c_z) && (r >= c_r)) || ((z <= c_z) && (r > (c_z + c_r - z)))) {
60 /* Wall section and outer cylinder */
61 return {0, m_half_length - z};
62 }
63 /* Smoothing area */
64 /* Vector to center of torus segment */
65 auto const dr = c_r - r;
66 auto const dz = c_z - z;
67
68 /* Rescale to surface */
69 auto const d = std::sqrt(dr * dr + dz * dz);
70 auto const fac = (d - m_smoothing_rad) / d;
71
72 return {fac * dr, fac * dz};
73}
74
75void SimplePore::calculate_dist(const Utils::Vector3d &pos, double &dist,
76 Utils::Vector3d &vec) const {
77 /* Coordinate transform to cylinder coords
78 with origin at m_center. */
79 Utils::Vector3d const c_dist = pos - m_center;
80 auto const z = e_z * c_dist;
81 auto const r_vec = c_dist - z * e_z;
82 auto const r = r_vec.norm();
83
84 /* If exactly on the axis, chose e_r orthogonal
85 to e_z. */
86 auto const e_r = (r == 0) ? e_r_axis : r_vec / r;
87
88 /* The pore has mirror symmetry in z with regard to
89 the center in the {r,z} system. We calculate always
90 for the z > 0 case, and flip the result if appropriate. */
91 auto [dr, dz] = dist_half_pore(r, std::abs(z));
92
93 double side = -1;
94 if (((dz == 0) && (r <= m_rad)) || // cylinder section
95 ((dr == 0) && (std::abs(z) > m_half_length))) { // ||
96 side = 1;
97 } else {
98 // smoothing area
99 if (std::abs(z) >= c_z) {
100 auto const angle = std::asin((std::abs(z) - c_z) / m_smoothing_rad);
101 auto const dist_offset =
102 m_smoothing_rad - (std::cos(angle) * m_smoothing_rad);
103 if (m_half_length < std::abs(z) || r <= (m_rad + dist_offset)) {
104 side = 1;
105 }
106 }
107 }
108
109 if (z <= 0.0) {
110 dz *= -1;
111 }
112
113 dist = std::sqrt(dr * dr + dz * dz) * side;
114 vec = -dr * e_r - dz * e_z;
115}
116} // 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
T norm() const
Definition Vector.hpp:138