cepgen is hosted by Hepforge, IPPP Durham
CepGen 1.2.5
Central exclusive processes event generator
Loading...
Searching...
No Matches
AnalyticalIntegratorGSL.cpp
Go to the documentation of this file.
1/*
2 * CepGen: a central exclusive processes event generator
3 * Copyright (C) 2022-2024 Laurent Forthomme
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19#include <gsl/gsl_version.h>
20
21#if defined(GSL_MAJOR_VERSION) && (GSL_MAJOR_VERSION > 2 || (GSL_MAJOR_VERSION == 2 && GSL_MINOR_VERSION >= 4))
22
23#include <gsl/gsl_deriv.h>
24#include <gsl/gsl_errno.h>
25#include <gsl/gsl_integration.h>
26
31
32namespace cepgen {
33 namespace utils {
34 class AnalyticalIntegratorGSL final : public AnalyticIntegrator {
35 public:
36 explicit AnalyticalIntegratorGSL(const ParametersList& params)
37 : AnalyticIntegrator(params),
38 mode_(steerAs<int, Mode>("mode")),
39 fixed_type_(steerAs<int, FixedType>("fixedType")),
40 nodes_(steer<int>("nodes")),
41 alpha_(steer<double>("alpha")),
42 beta_(steer<double>("beta")),
43 limit_(steerAs<int, size_t>("limit")),
44 epsabs_(steer<double>("epsabs")),
45 epsrel_(steer<double>("epsrel")) {}
46
47 static ParametersDescription description() {
48 auto desc = AnalyticIntegrator::description();
49 desc.setDescription("GSL 1D integration algorithms wrapper");
50 desc.addAs<int, Mode>("mode", Mode::Fixed).setDescription("integrator algorithm to use");
51 desc.addAs<int, FixedType>("fixedType", FixedType::Jacobi).setDescription("type of quadrature");
52 desc.add<int>("nodes", 100).setDescription("number of quadrature nodes for the fixed type integration");
53 desc.add<double>("alpha", 0.).setDescription("alpha parameter for the fixed type integration");
54 desc.add<double>("beta", 0.).setDescription("alpha parameter for the fixed type integration");
55 desc.add<int>("limit", 1000).setDescription("maximum number of subintervals to build");
56 desc.add<double>("epsabs", 0.).setDescription("desired absolute error limit");
57 desc.add<double>("epsrel", 0.1).setDescription("desired relative error limit");
58 return desc;
59 }
60
61 double integrate(const Function1D& func, void* obj = nullptr, const Limits& lim = {}) const override {
62 if (obj)
63 return eval(GSLFunctionWrapper::build(func, obj).get(), lim);
64 return eval(GSLFunctionWrapper::build(func, func_params_).get(), lim);
65 }
66
67 private:
68 enum struct Mode { Fixed = 0, QNG = 1, QAG = 2, QAGS = 3, QAWC = 4 };
69 enum struct FixedType {
70 Legendre = 0,
71 Chebyshev = 1,
72 Gegenbauer = 2,
73 Jacobi = 3,
74 Laguerre = 4,
75 Hermite = 5,
76 Exponential = 6,
77 Rational = 7,
78 Chebyshev2 = 8
79 };
80 double eval(const gsl_function*, const Limits&) const;
81 const Mode mode_;
82 const FixedType fixed_type_;
83 const int nodes_;
84 const double alpha_, beta_;
85 const size_t limit_;
86 const double epsabs_, epsrel_;
87 };
88
89 double AnalyticalIntegratorGSL::eval(const gsl_function* wrp, const Limits& lim) const {
90 double result{0.};
91#if defined(GSL_MAJOR_VERSION) && (GSL_MAJOR_VERSION > 2 || (GSL_MAJOR_VERSION == 2 && GSL_MINOR_VERSION >= 1))
92 const double xmin = (lim.hasMin() ? lim.min() : range_.min());
93 const double xmax = (lim.hasMax() ? lim.max() : range_.max());
94 int res = GSL_SUCCESS;
95 if (mode_ == Mode::Fixed) {
96 const gsl_integration_fixed_type* type{nullptr};
97 switch (fixed_type_) {
98 case FixedType::Legendre:
99 type = gsl_integration_fixed_legendre;
100 break;
101 case FixedType::Chebyshev:
102 type = gsl_integration_fixed_chebyshev;
103 break;
104 case FixedType::Gegenbauer:
105 type = gsl_integration_fixed_gegenbauer;
106 break;
107 case FixedType::Jacobi:
108 type = gsl_integration_fixed_jacobi;
109 break;
110 case FixedType::Laguerre:
111 type = gsl_integration_fixed_laguerre;
112 break;
113 case FixedType::Hermite:
114 type = gsl_integration_fixed_hermite;
115 break;
116 case FixedType::Exponential:
117 type = gsl_integration_fixed_exponential;
118 break;
119 case FixedType::Rational:
120 type = gsl_integration_fixed_rational;
121 break;
122 case FixedType::Chebyshev2:
123 type = gsl_integration_fixed_chebyshev2;
124 break;
125 default:
126 throw CG_FATAL("AnalyticalIntegratorGSL") << "Invalid fixed quadrature type: " << (int)fixed_type_ << ".";
127 }
128 std::unique_ptr<gsl_integration_fixed_workspace, void (*)(gsl_integration_fixed_workspace*)> workspace(
129 gsl_integration_fixed_alloc(type, nodes_, xmin, xmax, alpha_, beta_), gsl_integration_fixed_free);
130 res = gsl_integration_fixed(wrp, &result, workspace.get());
131 } else if (mode_ == Mode::QNG) {
132 size_t neval;
133 double error;
134 res = gsl_integration_qng(wrp, xmin, xmax, epsabs_, epsrel_, &result, &error, &neval);
135 } else {
136 double error;
137 std::unique_ptr<gsl_integration_workspace, void (*)(gsl_integration_workspace*)> workspace(
138 gsl_integration_workspace_alloc(limit_), gsl_integration_workspace_free);
139 if (mode_ == Mode::QAG) {
140 int key = GSL_INTEG_GAUSS41;
141 res = gsl_integration_qag(wrp, xmin, xmax, epsabs_, epsrel_, limit_, key, workspace.get(), &result, &error);
142 } else if (mode_ == Mode::QAGS)
143 res = gsl_integration_qags(wrp, xmin, xmax, epsabs_, epsrel_, limit_, workspace.get(), &result, &error);
144 else if (mode_ == Mode::QAWC)
145 res = gsl_integration_qawc(
146 const_cast<gsl_function*>(wrp), xmin, xmax, epsabs_, epsrel_, 0., limit_, workspace.get(), &result, &error);
147 }
148 if (res != GSL_SUCCESS)
149 CG_WARNING("AnalyticalIntegratorGSL")
150 << "Failed to evaluate the integral. GSL error: " << gsl_strerror(res) << ".";
151#else
152 (void)lim;
153 (void)wrp;
154 CG_WARNING("AnalyticalIntegratorGSL") << "GSL version above 2.1 is required for integration.";
155#endif
156 return result;
157 }
158 } // namespace utils
159} // namespace cepgen
160using cepgen::utils::AnalyticalIntegratorGSL;
161REGISTER_ANALYTIC_INTEGRATOR("gsl", AnalyticalIntegratorGSL);
162#endif
#define REGISTER_ANALYTIC_INTEGRATOR(name, obj)
Add a generic analytical integrator object builder definition.
#define CG_FATAL(mod)
Definition Exception.h:61
#define CG_WARNING(mod)
Definition Message.h:228
std::string get(const std::string &var, const std::string &def)
Get an environment variable.
Common namespace for this Monte Carlo generator.
integrate(f, int num_dim, int num_iter, int num_warmup, int num_calls, list[tuple[float]] limits=[])
Definition MCint.py:12