Integration Rules
An integration rule is a method or algorithm used to numerically calculate the value of an integral. When an integral is calculated using the two-argument form integral(f, geometry), MeshIntegrals.jl will automatically select an integration rule. Default rules are generally well-behaved, but may not be optimal for every problem.
MeshIntegrals.jl defines an abstract type IntegrationRule with sub-types representing the various integration rules supported by this package. These rules can be specified when calculating an integral using the three-argument form integral(f, geometry, rule). Currently, the following rule types are implemented:
GaussKronrodfor adaptive Gauss-Kronrod quadrature rulesGaussLegendrefor Gauss-Legendre quadrature rulesHAdaptiveCubaturefor h-adaptive cubature rules
Gauss-Kronrod
The GaussKronrod type is used to specify an adaptive Gauss-Kronrod quadrature rule, as implemented by QuadGK.jl.
rule = GaussKronrod()All standard QuadGK.quadgk keyword-argument options are supported. These can be specified when constructing the rule, where the kwargs in GaussKronrod(kwargs...) is equivalent to quadgk(f, a, b; kwargs...), e.g.:
rule = GaussKronrod(order = 5, rtol = 1e-4)Gauss-Legendre
The GaussLegendre type is used to specify a Gauss-Legendre quadrature rule. Gauss-Legendre quadrature rules of order $N$ are used to approximate definite integrals by sampling the integrand on a fixed grid with corresponding nodes $x_i$ and weights $w_i$.
\[\int_{-1}^1 f(x) ~\text{d}x \approx \sum_{i=1}^N w_i \, f(x_i)\]
These nodes and weights are purely a function of $N$ as they are derived from the roots of $N$-th order Legendre polynomials. This has the effect of providing exact solutions for integrand functions $f$ that can be represented as degree $2N-1$ polynomials.
This integration process can also be extended into multiple dimensions, for example:
\[\int_{-1}^1 \int_{-1}^1 \int_{-1}^1 f(x, y, z) ~\text{d}x ~\text{d}y ~\text{d}z \approx \sum_{i=1}^N \sum_{j=1}^N \sum_{k=1}^N w_i\,w_j\,w_k \, f(x_i, y_i, z_i)\]
MeshIntegrals.jl uses FastGaussQuadrature.jl to efficiently compute Gauss-Legendre quadrature nodes and weights at the time a GaussLegendre rule is constructed. Once constructed, these rules can be re-used to calculate multiple integrals to improve performance. Additionally, MeshIntegrals.jl uses an allocation-free summation routine that further improves performance by avoiding storing intermediate results.
rule = GaussLegendre(N)By contrast to adaptive integration rules where compute times can sometimes vary significantly, this technique has the advantage that compute times are much more predictable. For example, calculating a one-dimensional integral whose integrand $f$ can be computed in 10 microseconds using a GaussLegendre(100) can be expected to take approximately 1 millisecond. However, this lacks many of the guard-rails present in adaptive routines: results are not automatically checked to ensure convergence, so care must be taken to ensure that an appropriate rule and order are chosen.
H-Adaptive Cubature
The HAdaptiveCubature type is used to specify an h-adaptive cubature rule, as implemented by HCubature.jl.
rule = HAdaptiveCubature()All standard HCubature.hcubature keyword-argument options are supported. These can be specified when constructing the rule, where the kwargs in HAdaptiveCubature(kwargs...) is equivalent to hcubature(f, a, b; kwargs...), e.g.:
rule = HAdaptiveCubature(order = 5, rtol = 1e-4)