Geant4 11.4.0
Toolkit for the simulation of the passage of particles through matter
Loading...
Searching...
No Matches
nf_GnG_adaptiveQuadrature.c
Go to the documentation of this file.
1/*
2# <<BEGIN-copyright>>
3# Copyright 2019, Lawrence Livermore National Security, LLC.
4# This file is part of the gidiplus package (https://github.com/LLNL/gidiplus).
5# gidiplus is licensed under the MIT license (see https://opensource.org/licenses/MIT).
6# SPDX-License-Identifier: MIT
7# <<END-copyright>>
8*/
9
10#include <float.h>
11
12#include "nf_integration.h"
13
22
23static double initialPoints[] = { 0.2311, 0.4860, 0.6068, 0.8913, 0.9501 };
24static int numberOfInitialPoints = sizeof( initialPoints ) / sizeof( initialPoints[0] );
25
26static double nf_GnG_adaptiveQuadrature2( nf_GnG_adaptiveQuadrature_info *adaptiveQuadrature_info, double currentIntrgral, double x1, double x2, int depth );
27/*
28============================================================
29*/
31 void *argList, double x1, double x2, int maxDepth, double tolerance, double *integral, long *evaluations ) {
32/*
33* See W. Gander and W. Gautschi, "Adaptive quadrature--revisited", BIT 40 (2000), 84-101.
34*/
35 int i1;
36 double estimate = 0., y1, integral_, coarse;
37 nfu_status status = nfu_Okay;
38 nf_GnG_adaptiveQuadrature_info adaptiveQuadrature_info = { nfu_Okay, integrandFunction, argList, quadratureFunction, 0., 0, maxDepth, 0 };
39
40 *integral = 0.;
41 *evaluations = 0;
42 if( x1 == x2 ) return( nfu_Okay );
43
44 if( tolerance < 10 * DBL_EPSILON ) tolerance = 10 * DBL_EPSILON;
46
47 for( i1 = 0; i1 < numberOfInitialPoints; i1++ ) {
48 if( ( status = integrandFunction( x1 + ( x2 - x1 ) * initialPoints[i1], &y1, argList ) ) != nfu_Okay ) return( status );
49 estimate += y1;
50 }
51 if( ( status = quadratureFunction( integrandFunction, argList, x1, x2, &integral_ ) ) != nfu_Okay ) return( status );
52 estimate = 0.5 * ( estimate * ( x2 - x1 ) / numberOfInitialPoints + integral_ );
53 if( estimate == 0. ) estimate = x2 - x1;
54 adaptiveQuadrature_info.estimate = tolerance * estimate / DBL_EPSILON;
55
56 if( ( status = quadratureFunction( integrandFunction, argList, x1, x2, &coarse ) ) != nfu_Okay ) return( status );
57 integral_ = nf_GnG_adaptiveQuadrature2( &adaptiveQuadrature_info, coarse, x1, x2, 0 );
58
59 for( i1 = 0; i1 < 2; i1++ ) { /* Estimate may be off by more than a factor of 10. Iterate at most 2 times. */
60 if( integral_ == 0. ) break;
61 y1 = integral_ / estimate;
62 if( ( y1 > 0.1 ) && ( y1 < 10. ) ) break;
63
64 estimate = integral_;
65 adaptiveQuadrature_info.estimate = tolerance * integral_ / DBL_EPSILON;
66 *evaluations += adaptiveQuadrature_info.evaluations;
67 adaptiveQuadrature_info.evaluations = 0;
68 integral_ = nf_GnG_adaptiveQuadrature2( &adaptiveQuadrature_info, integral_, x1, x2, 0 );
69 }
70
71 *evaluations += adaptiveQuadrature_info.evaluations;
72 if( adaptiveQuadrature_info.status == nfu_Okay ) *integral = integral_;
73 return( adaptiveQuadrature_info.status );
74}
75/*
76============================================================
77*/
78static double nf_GnG_adaptiveQuadrature2( nf_GnG_adaptiveQuadrature_info *adaptiveQuadrature_info, double coarse, double x1, double x2, int depth ) {
79
80 double xm, intregral1, intregral2, fine, extrapolate;
81
82 if( adaptiveQuadrature_info->status != nfu_Okay ) return( 0. );
83 if( x1 == x2 ) return( 0. );
84
85 adaptiveQuadrature_info->evaluations++;
86 depth++;
87 if( depth > adaptiveQuadrature_info->maxDepthReached ) adaptiveQuadrature_info->maxDepthReached = depth;
88
89 xm = 0.5 * ( x1 + x2 );
90 if( ( adaptiveQuadrature_info->status = adaptiveQuadrature_info->quadratureFunction( adaptiveQuadrature_info->integrandFunction,
91 adaptiveQuadrature_info->argList, x1, xm, &intregral1 ) ) != nfu_Okay ) return( 0. );
92 if( ( adaptiveQuadrature_info->status = adaptiveQuadrature_info->quadratureFunction( adaptiveQuadrature_info->integrandFunction,
93 adaptiveQuadrature_info->argList, xm, x2, &intregral2 ) ) != nfu_Okay ) return( 0. );
94 fine = intregral1 + intregral2;
95 extrapolate = ( 16. * fine - coarse ) / 15.;
96 if( extrapolate != 0 ) {
97 if( adaptiveQuadrature_info->estimate + ( extrapolate - fine ) == adaptiveQuadrature_info->estimate ) return( fine );
98 }
99 if( depth > adaptiveQuadrature_info->maxDepth ) return( fine );
100 return( nf_GnG_adaptiveQuadrature2( adaptiveQuadrature_info, intregral1, x1, xm, depth ) +
101 nf_GnG_adaptiveQuadrature2( adaptiveQuadrature_info, intregral2, xm, x2, depth ) );
102}
nfu_status nf_GnG_adaptiveQuadrature(nf_GnG_adaptiveQuadrature_callback quadratureFunction, nf_Legendre_GaussianQuadrature_callback integrandFunction, void *argList, double x1, double x2, int maxDepth, double tolerance, double *integral, long *evaluations)
struct nf_GnG_adaptiveQuadrature_info_s nf_GnG_adaptiveQuadrature_info
nfu_status(* nf_Legendre_GaussianQuadrature_callback)(double x, double *y, void *argList)
Definition nf_Legendre.h:33
#define nf_GnG_adaptiveQuadrature_MaxMaxDepth
nfu_status(* nf_GnG_adaptiveQuadrature_callback)(nf_Legendre_GaussianQuadrature_callback integrandFunction, void *argList, double x1, double x2, double *integral)
@ nfu_Okay
enum nfu_status_e nfu_status
nf_GnG_adaptiveQuadrature_callback quadratureFunction
nf_Legendre_GaussianQuadrature_callback integrandFunction
#define DBL_EPSILON
Definition templates.hh:66