OPALX (Object Oriented Parallel Accelerator Library for Exascal) master (dc2a29eed580)
OPALX
Loading...
Searching...
No Matches
GSLIntegration.h
Go to the documentation of this file.
1//
2// GSL Integration compatibility to replace gsl_integration
3//
4// Copyright (c) 2023, Paul Scherrer Institute, Villigen PSI, Switzerland
5// All rights reserved
6//
7// This file is part of OPAL.
8//
9// OPAL is free software: you can redistribute it and/or modify
10// it under the terms of the GNU General Public License as published by
11// the Free Software Foundation, either version 3 of the License, or
12// (at your option) any later version.
13//
14// You should have received a copy of the GNU General License
15// along with OPAL. If not, see <https://www.gnu.org/licenses/>.
16//
17
18#ifndef OPAL_GSL_INTEGRATION_HH
19#define OPAL_GSL_INTEGRATION_HH
20
21#include <cmath>
22#include <functional>
23#include <vector>
24
29 size_t limit;
30 std::vector<double> alist;
31 std::vector<double> blist;
32 std::vector<double> rlist;
33 std::vector<double> elist;
34 std::vector<size_t> order;
35 size_t size;
36 size_t nrmax;
37 size_t i;
39
41};
42
49 w->limit = n;
50 w->alist.resize(n);
51 w->blist.resize(n);
52 w->rlist.resize(n);
53 w->elist.resize(n);
54 w->order.resize(n);
55 return w;
56}
57
62
68 double (*function)(double x, void* params);
69 void* params;
70};
71
72// Helper function for adaptive integration.
73namespace {
74 std::pair<double, double> adaptive_integrate(
75 const std::function<double(double)>& func, double a, double b, double tol,
76 size_t max_depth, size_t depth) {
77 if (depth > max_depth) {
78 return {0.0, tol};
79 }
80
81 // Simpson's rule
82 auto simpson = [&func](double a, double b) -> double {
83 double h = (b - a) / 2.0;
84 double fa = func(a);
85 double fm = func(a + h);
86 double fb = func(b);
87 return (h / 3.0) * (fa + 4.0 * fm + fb);
88 };
89
90 double c = (a + b) / 2.0;
91 double sab = simpson(a, b);
92 double sac = simpson(a, c);
93 double scb = simpson(c, b);
94 double error = std::abs(sab - sac - scb) / 15.0;
95
96 if (error < tol) {
97 return {sac + scb, error};
98 } else {
99 auto left = adaptive_integrate(func, a, c, tol / 2.0, max_depth, depth + 1);
100 auto right = adaptive_integrate(func, c, b, tol / 2.0, max_depth, depth + 1);
101 return {left.first + right.first, left.second + right.second};
102 }
103 }
104} // namespace
105
122 const gsl_function* f, double a, double b, double epsabs, double epsrel, size_t /* limit */,
123 int /* key */, gsl_integration_workspace* /* workspace */, double* result, double* abserr) {
124 // Simple adaptive Simpson's rule
125 const size_t max_depth = 20;
126 double tolerance = std::max(epsabs, epsrel * std::abs(b - a));
127
128 std::function<double(double)> func = [f](double x) {
129 return f->function(x, f->params);
130 };
131
132 auto res = adaptive_integrate(func, a, b, tolerance, max_depth, 0);
133 *result = res.first;
134 *abserr = res.second;
135
136 return 0; // Success
137}
138
140constexpr int GSL_INTEG_GAUSS15 = 1;
141constexpr int GSL_INTEG_GAUSS21 = 2;
142constexpr int GSL_INTEG_GAUSS31 = 3;
143constexpr int GSL_INTEG_GAUSS41 = 4;
144constexpr int GSL_INTEG_GAUSS51 = 5;
145constexpr int GSL_INTEG_GAUSS61 = 6;
146
147#endif // OPAL_GSL_INTEGRATION_HH
constexpr int GSL_INTEG_GAUSS61
gsl_integration_workspace * gsl_integration_workspace_alloc(size_t n)
Allocate integration workspace with limit .
int gsl_integration_qag(const gsl_function *f, double a, double b, double epsabs, double epsrel, size_t, int, gsl_integration_workspace *, double *result, double *abserr)
Adaptive integration on using Simpson refinement.
constexpr int GSL_INTEG_GAUSS51
constexpr int GSL_INTEG_GAUSS31
constexpr int GSL_INTEG_GAUSS15
Integration rule identifiers (accepted but not used in this implementation).
constexpr int GSL_INTEG_GAUSS21
void gsl_integration_workspace_free(gsl_integration_workspace *w)
Free a workspace allocated by gsl_integration_workspace_alloc.
constexpr int GSL_INTEG_GAUSS41
Function wrapper used by integration routines.
double(* function)(double x, void *params)
Workspace for adaptive integration routines.
std::vector< size_t > order
std::vector< double > rlist
std::vector< double > blist
std::vector< double > alist
std::vector< double > elist