ESPResSo
Extensible Simulation Package for Research on Soft Matter Systems
Loading...
Searching...
No Matches
mmm-modpsi.cpp
Go to the documentation of this file.
1/*
2 * Copyright (C) 2010-2022 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 <config/config.hpp>
23
24#if defined(ESPRESSO_ELECTROSTATICS) and defined(ESPRESSO_GSL)
25
26#include "mmm1d.hpp"
27
28#include <gsl/gsl_sf_zeta.h>
29
30#include <cmath>
31#include <numbers>
32#include <vector>
33
34static void preparePolygammaEven(int n, double binom,
35 std::vector<double> &series) {
36 /* (-0.5 n) psi^2n/2n! (-0.5 n) and psi^(2n+1)/(2n)! series expansions
37 note that BOTH carry 2n! */
38 auto const deriv = static_cast<double>(2 * n);
39 if (n == 0) {
40 // psi^0 has a slightly different series expansion
41 double maxx = 0.25;
42 series.resize(1);
43 series[0] = 2. * (1. - std::numbers::egamma);
44 for (int order = 1;; order += 1) {
45 auto const x_order = static_cast<double>(2 * order);
46 auto const coeff = -2. * gsl_sf_hzeta(x_order + 1., 2.);
47 if (fabs(maxx * coeff) * (4.0 / 3.0) < round_error_prec)
48 break;
49 series.push_back(coeff);
50
51 maxx *= 0.25;
52 }
53 } else {
54 // even, n > 0
55 double maxx = 1.;
56 double pref = 2.;
57
58 for (int order = 0;; order++) {
59 // only even exponents of x
60 auto const x_order = static_cast<double>(2 * order);
61 auto const coeff = pref * gsl_sf_hzeta(1. + deriv + x_order, 2.);
62 if ((fabs(maxx * coeff) * (4.0 / 3.0) < round_error_prec) &&
63 (x_order > deriv))
64 break;
65 series.push_back(-binom * coeff);
66
67 maxx *= 0.25;
68 pref *= (1.0 + deriv / (x_order + 1.));
69 pref *= (1.0 + deriv / (x_order + 2.));
70 }
71 }
72}
73
74static void preparePolygammaOdd(int n, double binom,
75 std::vector<double> &series) {
76 auto const deriv = static_cast<double>(2 * n + 1);
77 auto maxx = 0.5;
78 // to get 1/(2n)! instead of 1/(2n+1)!
79 auto pref = 2 * deriv * (1 + deriv);
80
81 for (int order = 0;; order++) {
82 // only odd exponents of x
83 auto const x_order = static_cast<double>(2 * order + 1);
84 auto const coeff = pref * gsl_sf_hzeta(1. + deriv + x_order, 2.);
85 if ((fabs(maxx * coeff) * (4.0 / 3.0) < round_error_prec) &&
86 (x_order > deriv))
87 break;
88
89 series.push_back(-binom * coeff);
90 maxx *= 0.25;
91 pref *= (1.0 + deriv / (x_order + 1));
92 pref *= (1.0 + deriv / (x_order + 2));
93 }
94}
95
96void CoulombMMM1D::create_mod_psi_up_to(int new_n) {
97 auto const old_n = static_cast<int>(modPsi.size() >> 1);
98 if (new_n > old_n) {
99 modPsi.resize(2 * new_n);
100
101 double binom = 1.0;
102 for (int n = 0; n < old_n; n++)
103 binom *= (-0.5 - n) / static_cast<double>(n + 1);
104
105 for (int n = old_n; n < new_n; n++) {
106 preparePolygammaEven(n, binom, modPsi[2 * n]);
107 preparePolygammaOdd(n, binom, modPsi[2 * n + 1]);
108 binom *= (-0.5 - n) / static_cast<double>(n + 1);
109 }
110 }
111}
112
113#endif // defined(ESPRESSO_ELECTROSTATICS) and defined(ESPRESSO_GSL)
cudaStream_t stream[1]
CUDA streams for parallel computing on CPU and GPU.
constexpr auto round_error_prec
Precision below which a double-precision float is assumed to be zero.
Definition config.hpp:38
static void preparePolygammaOdd(int n, double binom, std::vector< double > &series)
static void preparePolygammaEven(int n, double binom, std::vector< double > &series)
MMM1D algorithm for long-range Coulomb interactions on the CPU.