13 template <
typename function_type>
double integrate_1d(
const function_type&
fcn,
const double& min,
const double& max, gsl_integration_workspace* ws =
nullptr)
15 gsl_integration_workspace* w = (ws ==
nullptr) ? gsl_integration_workspace_alloc (1000) : ws;
20 if constexpr( is_functor<function_type, double(
const double& )>::value )
22 F.function = [](
double x,
void* p) ->
double {
return (*
static_cast<function_type*
>(p))(x); };
24 else if constexpr( is_functor<function_type, double(
const std::array<double, 1>& )>::value )
26 F.function = [](
double x,
void* p) ->
double {
return (*
static_cast<function_type*
>(p))( std::array<double,1>{x} ); };
28 else static_assert(
true,
"function matches no signature!");
30 F.params =
const_cast<function_type*
>(&
fcn);
31 gsl_integration_qags (&F, min, max, 0, 1e-5, 1000, w, &result, &error);
32 if( ws ==
nullptr ) gsl_integration_workspace_free (w);
35 template <
typename function_type>
double integrate_1d_inf(
const function_type&
fcn, gsl_integration_workspace* ws =
nullptr)
37 gsl_integration_workspace* w = (ws ==
nullptr) ? gsl_integration_workspace_alloc (1000) : ws;
41 F.function = [](
double x,
void* p) ->
double {
return (*
static_cast<function_type*
>(p))(x); };
42 F.params =
const_cast<function_type*
>(&
fcn);
43 gsl_integration_qagi(&F, 0, 1e-5, 1000, w, &result, &error);
44 if( ws ==
nullptr ) gsl_integration_workspace_free (w);
49 template <
typename function_type>
double integrate_1d_cauchy(
const function_type&
fcn,
const double& x0,
const double& min,
const double& max, gsl_integration_workspace* ws =
nullptr)
51 gsl_integration_workspace* w = (ws ==
nullptr) ? gsl_integration_workspace_alloc (1000) : ws;
55 F.function = [](
double x,
void* p) ->
double {
return (*
static_cast<function_type*
>(p))(x); };
56 F.params =
const_cast<function_type*
>(&
fcn);
57 gsl_integration_qawc(&F, min, max, x0, 0, 1e-8, 1000, w, &result, &error);
58 if( ws ==
nullptr ) gsl_integration_workspace_free (w);
82 template <
unsigned dim,
typename fcn>
double integrate(
const fcn& F,
const std::array<double, dim> xmin,
const std::array<double, dim>& xmax)
95 if constexpr( dim == 1 ){
96 if constexpr( is_functor<
fcn, double(
const double&)>::value ) {
integrate_1d(F, xmin[0], xmax[0] ); }
97 else if constexpr( is_functor<
fcn, double(
const std::array<double, 1>& ) >::value ){
98 return integrate_1d( [&F](
const double& x){
return F( std::array<double,1>{x} ); }, xmin[0], xmax[0] );
100 else static_assert(
true,
"1D function doesn't have recognised signature");
105 double epsrel = 1e-10;
114 unsigned int ifncls = 0;
119 constexpr unsigned irlcls = get_power<2,dim>::value +2*dim*(dim+1)+1;
120 constexpr unsigned minpts = get_power<2,dim>::value +2*dim*(dim+1)+1;
121 constexpr unsigned maxpts = 1000000;
123 std::array<integral<dim>, ( 1 + maxpts/irlcls)/2 > partial_integrals;
127 for (
unsigned j=0; j<dim; j++) {
128 current_integral->a[j] = (xmax[j] + xmin[j])*0.5;
129 current_integral->b[j] = (xmax[j] - xmin[j])*0.5;
132 unsigned int idvax0=0;
136 auto [rgnval, rgnerr, idvaxn] =
integrate_fp<dim>( F, current_integral->a, current_integral->b );
141 double aresult = std::abs(result);
145 tmp.
a = current_integral->a;
146 tmp.
b = current_integral->b;
153 if (isbtmp > isbrgs)
break;
154 if (isbtmp < isbrgs && partial_integrals[isbtmp].var < partial_integrals[isbtmp+1].var ) isbtmp++;
155 if (rgnerr >= partial_integrals[isbtmp].var )
break;
156 partial_integrals[isbrgn] = partial_integrals[isbtmp] ;
164 if ( isbtmp >= 1 && rgnerr > partial_integrals[isbtmp].var ) {
165 partial_integrals[isbrgn] = partial_integrals[isbtmp];
168 }
while ( isbtmp >= 1 && rgnerr > partial_integrals[isbtmp].var );
171 partial_integrals[isbrgn] = tmp;
174 current_integral = &(partial_integrals[isbrgn]);
177 partial_integrals[isbrgn].a = current_integral->a;
178 partial_integrals[isbrgn].b = current_integral->b;
179 partial_integrals[isbrgn].a[idvax0] += 2*current_integral->b[idvax0];
180 current_integral = &(partial_integrals[isbrgn]);
184 relerr = std::abs(result) == 0 ? abserr : abserr/std::abs(result);
185 if ((relerr < epsrel && aresult < epsabs) or
186 ( ( relerr < epsrel || abserr < epsabs ) && ifncls > minpts) ){ status = 0; break ; }
187 if (( isbrgs >= partial_integrals.size()-1) or ( ifncls+2*irlcls > maxpts ) ) { status = 2;
break; }
191 current_integral = &( partial_integrals[isbrgn] );
193 abserr -= current_integral->var;
194 result -= current_integral->value;
195 idvax0 = current_integral->index;
197 current_integral -> b[idvax0] *= 0.5;
198 current_integral -> a[idvax0] -= current_integral->b[idvax0];
200 }
while( status == 3 );
std::tuple< double, double, unsigned > integrate_fp_scalar(const fcn &F, const std::array< double, dim > &ctr, const std::array< double, dim > &wth)