ESPResSo
Extensible Simulation Package for Research on Soft Matter Systems
Loading...
Searching...
No Matches
math.hpp
Go to the documentation of this file.
1/*
2 * Copyright (C) 2010-2024 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#pragma once
23
25#include <utils/math/sqr.hpp>
26
27#ifndef __CUDACC__
28#include <cmath>
29#endif
30#include <numbers>
31#include <stdexcept>
32#include <string>
33
34/**
35 * @brief P3M: Number of Brillouin zones taken into account
36 * in the calculation of the optimal influence function (aliasing sums).
37 */
38#define P3M_BRILLOUIN 0
39
40/**
41 * @brief Whether to use the Abramowitz/Stegun approximation @cite abramowitz65a
42 * @ref Utils::AS_erfc_part() for \f$\exp(d^2) \mathrm{erfc}(d)\f$,
43 * or the C function <tt>std::erfc()</tt> in P3M.
44 */
45#define USE_ERFC_APPROXIMATION 1
46
47/** @brief Minimal charge assignment order. */
48inline constexpr int p3m_min_cao = 1;
49/** @brief Maximal charge assignment order. */
50inline constexpr int p3m_max_cao = 7;
51
52namespace math {
53
54/** @brief Return the absolute value of x. */
55inline DEVICE_QUALIFIER auto abs(double x) { return fabs(x); }
56
57/** @brief Return the absolute value of x. */
58inline DEVICE_QUALIFIER auto abs(float x) { return fabsf(x); }
59
60/**
61 * @brief Calculate the function @f$ \mathrm{sinc}(x) = \sin(\pi x)/(\pi x) @f$.
62 *
63 * (same convention as in @cite hockney88a). In order to avoid divisions
64 * by 0, arguments whose modulus is smaller than @f$ \epsilon = 0.1 @f$
65 * are evaluated by an 8th order Taylor expansion.
66 * Note that the difference between sinc(x) and this expansion
67 * is smaller than 0.235e-12, if x is smaller than @f$ \epsilon @f$.
68 * (The next term in the expansion is the 10th order contribution, i.e.
69 * @f$ \pi^{10} x^{10}/39916800 \approx 0.2346 \cdot x^{12} @f$).
70 */
71template <typename T> DEVICE_QUALIFIER auto sinc(T x) {
72 auto constexpr epsilon = T(0.1);
73#if not defined(__CUDACC__)
74 using std::sin;
75#endif
76
77 auto const pix = std::numbers::pi_v<T> * x;
78
79 if (::math::abs(x) > epsilon)
80 return sin(pix) / pix;
81
82 auto constexpr factorial = [](int n) consteval {
83 int acc{1}, c{1};
84 while (c < n) {
85 acc *= ++c;
86 }
87 return acc;
88 };
89
90 /* Coefficients of the Taylor expansion of sinc */
91 auto constexpr c0 = T(+1) / T(factorial(1));
92 auto constexpr c2 = T(-1) / T(factorial(3));
93 auto constexpr c4 = T(+1) / T(factorial(5));
94 auto constexpr c6 = T(-1) / T(factorial(7));
95 auto constexpr c8 = T(+1) / T(factorial(9));
96
97 auto const pix2 = pix * pix;
98 return c0 + pix2 * (c2 + pix2 * (c4 + pix2 * (c6 + pix2 * c8)));
99}
100
101/**
102 * @brief One of the aliasing sums used to compute k-space errors.
103 * Fortunately the one which is most important (because it converges
104 * most slowly, since it is not damped exponentially) can be calculated
105 * analytically. The result (which depends on the order of the spline
106 * interpolation) can be written as an even trigonometric polynomial.
107 * The results are tabulated here (the employed formula is eq. 7-66
108 * p. 233 in @cite hockney88a).
109 */
110template <int cao>
112 static_assert(cao >= p3m_min_cao and cao <= p3m_max_cao);
113#if not defined(__CUDACC__)
114 using std::cos;
115#endif
116 auto const theta = static_cast<double>(n) * mesh_i * std::numbers::pi;
117 auto const c = Utils::sqr(cos(theta));
118
119 if constexpr (cao == 1) {
120 return 1.;
121 }
122 if constexpr (cao == 2) {
123 return (1. + c * 2.) / 3.;
124 }
125 if constexpr (cao == 3) {
126 return (2. + c * (11. + c * 2.)) / 15.;
127 }
128 if constexpr (cao == 4) {
129 return (17. + c * (180. + c * (114. + c * 4.))) / 315.;
130 }
131 if constexpr (cao == 5) {
132 return (62. + c * (1072. + c * (1452. + c * (247. + c * 2.)))) / 2835.;
133 }
134 if constexpr (cao == 6) {
135 return (1382. +
136 c * (35396. + c * (83021. + c * (34096. + c * (2026. + c * 4.))))) /
137 155925.;
138 }
139 return (21844. +
140 c * (776661. +
141 c * (2801040. +
142 c * (2123860. + c * (349500. + c * (8166. + c * 4.)))))) /
143 6081075.;
144}
145
147 decltype(&analytic_cotangent_sum<1>) ptr = nullptr;
148 if (cao == 1) {
150 } else if (cao == 2) {
152 } else if (cao == 3) {
154 } else if (cao == 4) {
156 } else if (cao == 5) {
158 } else if (cao == 6) {
160 } else if (cao == 7) {
162 }
163 if (ptr == nullptr) {
164 throw std::domain_error("Invalid value cao=" + std::to_string(cao));
165 }
166 return ptr;
167}
168
169} // namespace math
cudaStream_t stream[1]
CUDA streams for parallel computing on CPU and GPU.
#define DEVICE_QUALIFIER
constexpr int p3m_min_cao
Minimal charge assignment order.
Definition math.hpp:48
constexpr int p3m_max_cao
Maximal charge assignment order.
Definition math.hpp:50
DEVICE_QUALIFIER constexpr T sqr(T x)
Calculates the SQuaRe of x.
Definition sqr.hpp:28
Definition math.hpp:52
DEVICE_QUALIFIER auto abs(double x)
Return the absolute value of x.
Definition math.hpp:55
DEVICE_QUALIFIER auto sinc(T x)
Calculate the function .
Definition math.hpp:71
auto get_analytic_cotangent_sum_kernel(int cao)
Definition math.hpp:146
DEVICE_QUALIFIER auto analytic_cotangent_sum(int n, double mesh_i)
One of the aliasing sums used to compute k-space errors.
Definition math.hpp:111