31 T utol = 1e-5, ftol = -1, umaxtol = -1, fmaxtol = -1;
35 T f1(std::function<
T(
T)> f,
T x)
const 37 return (f(x + numdr * 0.5) - f(x - numdr * 0.5)) / (numdr);
41 T f2(std::function<
T(
T)> f,
T x)
const 43 return (f1(f, x + numdr * 0.5) - f1(f, x - numdr * 0.5)) / (numdr);
48 if (ftol != -1 && ftol <= 0.0) {
49 std::cerr <<
"ftol=" << ftol <<
" too small\n" << std::endl;
52 if (umaxtol != -1 && umaxtol <= 0.0) {
53 std::cerr <<
"umaxtol=" << umaxtol <<
" too small\n" << std::endl;
56 if (fmaxtol != -1 && fmaxtol <= 0.0) {
57 std::cerr <<
"fmaxtol=" << fmaxtol <<
" too small\n" << std::endl;
67 T rmin2 = 0, rmax2 = 0;
69 bool empty()
const {
return r2.empty() && c.empty(); }
71 inline size_t numKnots()
const {
return r2.size(); }
74 void setTolerance(
T _utol,
T _ftol = -1,
T _umaxtol = -1,
T _fmaxtol = -1)
82 void setNumdr(
T _numdr) { numdr = _numdr; }
103 std::vector<T> SetUBuffer(
T,
T zlow,
T,
T zupp,
T u0low,
T u1low,
T u2low,
T u0upp,
T u1upp,
108 if (std::fabs(u0low) < 1e-9)
109 if (std::fabs(u1low) < 1e-9)
110 return {0, 0, 0, 0, 0, 0, 0};
124 T a = 6 * (w0upp - c0 - c1 * dz1 - c2 * dz2) / dz3;
125 T b = 2 * (w1upp - c1 - 2 * c2 * dz1) / dz2;
126 T c = (w2upp - 2 * c2) / dz1;
127 T c3 = (10 * a - 12 * b + 3 * c) / 6;
128 T c4 = (-15 * a + 21 * b - 6 * c) / (6 * dz1);
129 T c5 = (2 * a - 3 * b + c) / (2 * dz2);
131 return {zlow, c0, c1, c2, c3, c4, c5};
139 std::vector<bool> CheckUBuffer(std::vector<T>& ubuft,
T rlow,
T rupp,
140 std::function<
T(
T)> f)
const 145 T dr = (rupp - rlow) / (ncheck - 1);
146 std::vector<bool> vb(2,
false);
148 for (
int i = 0; i < ncheck; i++) {
149 T r1 = rlow + dr * ((
T)i);
152 T u1 = base::f1(f, r2);
153 T dz = r2 - rlow * rlow;
154 T usum = ubuft.at(1) +
157 dz * (ubuft.at(4) + dz * (ubuft.at(5) + dz * ubuft.at(6)))));
161 dz * (2 * ubuft.at(3) +
162 dz * (3 * ubuft.at(4) + dz * (4 * ubuft.at(5) + dz * (5 * ubuft.at(6)))));
164 if (std::fabs(usum - u0) > base::utol)
166 if (base::ftol != -1 && std::fabs(fsum - u1) > base::ftol)
168 if (base::umaxtol != -1 && std::fabs(usum) > base::umaxtol)
170 if (base::fmaxtol != -1 && std::fabs(usum) > base::fmaxtol)
186 size_t pos = std::lower_bound(d.r2.begin(), d.r2.end(), r2) - d.r2.begin() - 1;
187 size_t pos6 = 6 * pos;
188 assert((pos6 + 5) < d.c.size());
189 T dz = r2 - d.r2[pos];
190 if constexpr (
true) {
192 #pragma clang loop vectorize(enable) interleave(enable) 193 for (
size_t i = 5; i > 0; i--)
194 sum = dz * (sum + d.c[pos6 + i]);
195 return sum + d.c[pos6];
199 dz * (d.c[pos6 + 1] +
200 dz * (d.c[pos6 + 2] +
201 dz * (d.c[pos6 + 3] + dz * (d.c[pos6 + 4] + dz * (d.c[pos6 + 5])))));
211 size_t pos = std::lower_bound(d.r2.begin(), d.r2.end(), r2) - d.r2.begin() - 1;
212 size_t pos6 = 6 * pos;
213 T dz = r2 - d.r2[pos];
214 return (d.c[pos6 + 1] +
215 dz * (2.0 * d.c[pos6 + 2] +
216 dz * (3.0 * d.c[pos6 + 3] +
217 dz * (4.0 * d.c[pos6 + 4] + dz * (5.0 * d.c[pos6 + 5])))));
225 rmin = std::sqrt(rmin);
226 rmax = std::sqrt(rmax);
229 td.rmin2 = rmin * rmin;
230 td.rmax2 = rmax * rmax;
233 T rmax2 = rmax * rmax;
239 td.r2.push_back(zupp);
242 for (i = 0; i < mngrid; i++) {
245 std::vector<T> ubuft;
250 for (j = 0; j < ndr; j++) {
259 T u1low = base::f1(f, zlow);
260 T u2low = base::f2(f, zlow);
262 T u1upp = base::f1(f, zupp);
263 T u2upp = base::f2(f, zupp);
266 SetUBuffer(rlow, zlow, rupp, zupp, u0low, u1low, u2low, u0upp, u1upp, u2upp);
267 std::vector<bool> vb = CheckUBuffer(ubuft, rlow, rupp, f);
277 throw std::runtime_error(
"Andrea spline: try to increase utol/ftol");
278 if (ubuft.size() != 7)
279 throw std::runtime_error(
280 "Andrea spline: wrong size of ubuft, min value + 6 coefficients");
282 td.r2.push_back(zlow);
283 for (
size_t k = 1; k < ubuft.size(); k++)
284 td.c.push_back(ubuft.at(k));
289 td.rmin2 = rlow * rlow;
291 if (rlow <= rumin || repul)
296 throw std::runtime_error(
"Andrea spline: try to increase utol/ftol");
299 assert(td.c.size() % 6 == 0);
300 assert(td.c.size() / (td.r2.size() - 1) == 6);
301 assert(std::is_sorted(td.r2.rbegin(), td.r2.rend()));
302 std::reverse(td.r2.begin(), td.r2.end());
303 for (
size_t i = 0; i < td.c.size() / 2; i += 6)
304 std::swap_ranges(td.c.begin() + i, td.c.begin() + i + 6,
312 #ifdef DOCTEST_LIBRARY_INCLUDED 313 TEST_CASE(
"[Faunus] Andrea")
315 using doctest::Approx;
318 auto f = [](
double x) {
return 0.5 * x * std::sin(x) + 2; };
320 spline.setTolerance(2e-6, 1e-4);
323 CHECK(d.r2.size() == 19);
324 CHECK(d.c.size() == 108);
325 CHECK(d.numKnots() == 19);
326 CHECK(d.rmin2 == Approx(0.0));
327 CHECK(d.rmax2 == Approx(10.0));
328 CHECK(d.r2.at(0) == Approx(0.0));
329 CHECK(d.r2.at(1) == Approx(0.212991));
330 CHECK(d.r2.at(2) == Approx(0.782554));
331 CHECK(d.r2.back() == Approx(10.0));
333 CHECK(d.c.at(0) == Approx(2.0));
334 CHECK(d.c.at(1) == Approx(0.0));
335 CHECK(d.c.at(2) == Approx(0.5));
336 CHECK(d.c.back() == Approx(-0.0441931));
338 CHECK(spline.
eval(d, 1e-9) == Approx(f(1e-9)));
339 CHECK(spline.
eval(d, 5) == Approx(f(5)));
340 CHECK(spline.
eval(d, 10) == Approx(f(10)));
344 auto f_prime = [&](
double x,
double dx = 1e-10) {
345 return (spline.
eval(d, x + dx) - spline.
eval(d, x - dx)) / (2 * dx);
348 CHECK(spline.
evalDer(d, x) == Approx(f_prime(x)));
350 CHECK(spline.
evalDer(d, x) == Approx(f_prime(x)));
352 CHECK(spline.
evalDer(d, x) == Approx(f_prime(x)));
356 auto f_prime_exact = [&](
double x,
double dx = 1e-10) {
357 return (f(x + dx) - f(x - dx)) / (2 * dx);
360 CHECK(spline.
evalDer(d, x) == Approx(f_prime_exact(x)));
362 CHECK(spline.
evalDer(d, x) == Approx(f_prime_exact(x)));
364 CHECK(spline.
evalDer(d, x) == Approx(f_prime_exact(x)));
double T
floating point size
Definition: units.h:73
base::data generate(std::function< T(T)> f, double rmin, double rmax)
Tabulate f(x) in interval ]min,max].
Definition: tabulate.h:223
Definition: tabulate.h:28
Cell list class templates.
Definition: actions.cpp:11
T evalDer(const typename base::data &d, T r2) const
Get tabulated value at df(x)/dx.
Definition: tabulate.h:209
Class templates for tabulation of pair potentials.
Definition: tabulate.h:25
Andrea table with logarithmic search.
Definition: tabulate.h:95
Definition: tabulate.h:63
T eval(const typename base::data &d, T r2) const
Get tabulated value at f(x)
Definition: tabulate.h:184