ESPResSo
Extensible Simulation Package for Research on Soft Matter Systems
Loading...
Searching...
No Matches
specfunc.hpp
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/** @file
23 * This file contains implementations for some special functions which are
24 * needed by the MMM family of algorithms. These are the modified Hurwitz
25 * zeta function and the modified Bessel functions of second kind. The
26 * implementations are based on the GSL code (see @ref specfunc.cpp for the
27 * original GSL header).
28 *
29 * The Hurwitz zeta function is evaluated using the Euler-Maclaurin summation
30 * formula, the Bessel functions are evaluated using several different
31 * Chebychev expansions. Both achieve a precision of nearly machine precision,
32 * which is no problem for the Hurwitz zeta function, which is only used when
33 * determining the coefficients for the modified polygamma functions.
34 */
35
36#pragma once
37
38#include <cassert>
39#include <numeric>
40#include <span>
41#include <utility>
42
43/** Hurwitz zeta function. This function was taken from the GSL code. */
44double hzeta(double order, double x);
45
46/** Modified Bessel function of second kind, order 0. This function was taken
47 * from the GSL code. Precise roughly up to machine precision.
48 * It is 16 times faster than <tt>std::cyl_bessel_k</tt>.
49 * If @c MMM1D_MACHINE_PREC is not defined, @ref LPK0 is used instead.
50 */
51double K0(double x);
52
53/** Modified Bessel function of second kind, order 1. This function was taken
54 * from the GSL code. Precise roughly up to machine precision.
55 * If @c MMM1D_MACHINE_PREC is not defined, @ref LPK1 is used instead.
56 */
57double K1(double x);
58
59/** Modified Bessel function of second kind, order 0, low precision.
60 * The implementation has an absolute precision of around 10^(-14), which is
61 * comparable to the relative precision sqrt implementation of current
62 * hardware in the ranges @f$ ]0, 8[ @f$ and @f$ ]8, 23[ @f$. Above 23,
63 * the precision starts to degrade, and above 27 the result drifts and
64 * slowly converges to 96% of the real value.
65 * It is 25 times faster than <tt>std::cyl_bessel_k</tt>
66 * and 1.5 times faster than @ref K0.
67 */
68double LPK0(double x);
69
70/** Modified Bessel function of second kind, order 1, low precision.
71 * The implementation has an absolute precision of around 10^(-14), which is
72 * comparable to the relative precision sqrt implementation of current
73 * hardware in the ranges @f$ ]0, 8[ @f$ and @f$ ]8, 23[ @f$. Above 23,
74 * the precision starts to degrade, and above 27 the result drifts and
75 * slowly converges to 111% of the real value.
76 * It is 25 times faster than <tt>std::cyl_bessel_k</tt>
77 * and 1.5 times faster than @ref K1.
78 */
79double LPK1(double x);
80
81/** Modified Bessel functions of second kind, order 0 and 1, low precision.
82 * The implementation has an absolute precision of around 10^(-14), which is
83 * comparable to the relative precision sqrt implementation of current
84 * hardware.
85 */
86std::pair<double, double> LPK01(double x);
87
88/** Evaluate the polynomial interpreted as a Taylor series via the
89 * Horner scheme.
90 */
91inline double evaluateAsTaylorSeriesAt(std::span<const double> series,
92 double x) {
93 assert(not series.empty());
94 auto const value = std::accumulate(
95 series.rbegin(), series.rend(), 0.,
96 [x](auto const &acc, auto const &coeff) { return acc * x + coeff; });
97 return value;
98}
99
100/** Evaluate the polynomial interpreted as a Chebychev series. Requires a
101 * series with at least three coefficients, i.e. no linear approximations!
102 */
103inline double evaluateAsChebychevSeriesAt(std::span<const double> series,
104 double x) {
105 assert(series.size() >= 3);
106
107 auto const *c = series.data();
108 auto const x2 = 2.0 * x;
109 auto dd = c[series.size() - 1];
110 auto d = x2 * dd + c[series.size() - 2];
111 for (auto j = static_cast<int>(series.size()) - 3; j >= 1; j--) {
112 auto const tmp = d;
113 d = x2 * d - dd + c[j];
114 dd = tmp;
115 }
116 return x * d - dd + 0.5 * c[0];
117}
double LPK1(double x)
Modified Bessel function of second kind, order 1, low precision.
Definition specfunc.cpp:348
std::pair< double, double > LPK01(double x)
Modified Bessel functions of second kind, order 0 and 1, low precision.
Definition specfunc.cpp:408
double K1(double x)
Modified Bessel function of second kind, order 1.
Definition specfunc.cpp:262
double evaluateAsChebychevSeriesAt(std::span< const double > series, double x)
Evaluate the polynomial interpreted as a Chebychev series.
Definition specfunc.hpp:103
double hzeta(double order, double x)
Hurwitz zeta function.
Definition specfunc.cpp:215
double evaluateAsTaylorSeriesAt(std::span< const double > series, double x)
Evaluate the polynomial interpreted as a Taylor series via the Horner scheme.
Definition specfunc.hpp:91
double K0(double x)
Modified Bessel function of second kind, order 0.
Definition specfunc.cpp:250
double LPK0(double x)
Modified Bessel function of second kind, order 0, low precision.
Definition specfunc.cpp:288