Home

Awesome

<p align="center"> <a href="https://github.com/sigma-py/quadpy"><img alt="quadpy" src="https://raw.githubusercontent.com/sigma-py/quadpy/main/logo/logo-with-text.svg" width="60%"></a> <p align="center">Your one-stop shop for numerical integration in Python.</p> </p>

PyPi Version PyPI pyversions GitHub stars PyPi downloads

Discord awesome

More than 1500 numerical integration schemes for line segments, circles, disks, triangles, quadrilaterals, spheres, balls, tetrahedra, hexahedra, wedges, pyramids, n-spheres, n-balls, n-cubes, n-simplices, the 1D half-space with weight functions exp(-r), the 2D space with weight functions exp(-r), the 3D space with weight functions exp(-r), the nD space with weight functions exp(-r), the 1D space with weight functions exp(-r<sup>2</sup>), the 2D space with weight functions exp(-r<sup>2</sup>), the 3D space with weight functions exp(-r<sup>2</sup>), and the nD space with weight functions exp(-r<sup>2</sup>), for fast integration of real-, complex-, and vector-valued functions.

Installation

Install quadpy from PyPI with

pip install quadpy

See here on how to get a license.

Using quadpy

Quadpy provides integration schemes for many different 1D, 2D, even nD domains.

To start off easy: If you'd numerically integrate any function over any given 1D interval, do

import numpy as np
import quadpy


def f(x):
    return np.sin(x) - x


val, err = quadpy.quad(f, 0.0, 6.0)

This is like scipy with the addition that quadpy handles complex-, vector-, matrix-valued integrands, and "intervals" in spaces of arbitrary dimension.

To integrate over a triangle, do

import numpy as np
import quadpy


def f(x):
    return np.sin(x[0]) * np.sin(x[1])


triangle = np.array([[0.0, 0.0], [1.0, 0.0], [0.7, 0.5]])

# get a "good" scheme of degree 10
scheme = quadpy.t2.get_good_scheme(10)
val = scheme.integrate(f, triangle)

Most domains have get_good_scheme(degree). If you would like to use a particular scheme, you can pick one from the dictionary quadpy.t2.schemes.

All schemes have

<!--pytest.mark.skip-->
scheme.points
scheme.weights
scheme.degree
scheme.source
scheme.test_tolerance

scheme.show()
scheme.integrate(
    # ...
)

and many have

<!--pytest.mark.skip-->
scheme.points_symbolic
scheme.weights_symbolic

You can explore schemes on the command line with, e.g.,

quadpy info s2 rabinowitz_richter_3
<quadrature scheme for S2>
  name:                 Rabinowitz-Richter 2
  source:               Perfectly Symmetric Two-Dimensional Integration Formulas with Minimal Numbers of Points
                        Philip Rabinowitz, Nira Richter
                        Mathematics of Computation, vol. 23, no. 108, pp. 765-779, 1969
                        https://doi.org/10.1090/S0025-5718-1969-0258281-4
  degree:               9
  num points/weights:   21
  max/min weight ratio: 7.632e+01
  test tolerance:       9.417e-15
  point position:       outside
  all weights positive: True

Also try quadpy show!

quadpy is fully vectorized, so if you like to compute the integral of a function on many domains at once, you can provide them all in one integrate() call, e.g.,

<!--pytest.mark.skip-->
# shape (3, 5, 2), i.e., (corners, num_triangles, xy_coords)
triangles = np.stack(
    [
        [[0.0, 0.0], [1.0, 0.0], [0.0, 1.0]],
        [[1.2, 0.6], [1.3, 0.7], [1.4, 0.8]],
        [[26.0, 31.0], [24.0, 27.0], [33.0, 28]],
        [[0.1, 0.3], [0.4, 0.4], [0.7, 0.1]],
        [[8.6, 6.0], [9.4, 5.6], [7.5, 7.4]],
    ],
    axis=-2,
)

The same goes for functions with vectorized output, e.g.,

def f(x):
    return [np.sin(x[0]), np.sin(x[1])]

More examples under test/examples_test.py.

Read more about the dimensionality of the input/output arrays in the wiki.

Advanced topics:

Schemes

Line segment (C<sub>1</sub>)

<img src="https://raw.githubusercontent.com/sigma-py/quadpy/main/plots/line-segment-gauss-legendre-20.svg" width="50%">

See here for how to generate Gauss formulas for your own weight functions.

Example:

import numpy as np
import quadpy

scheme = quadpy.c1.gauss_patterson(5)
scheme.show()
val = scheme.integrate(lambda x: np.exp(x), [0.0, 1.0])

1D half-space with weight function exp(-r) (E<sub>1</sub><sup>r</sup>)

<img src="https://raw.githubusercontent.com/sigma-py/quadpy/main/plots/e1r-gauss-laguerre-3.svg" width="50%">

Example:

import quadpy

scheme = quadpy.e1r.gauss_laguerre(5, alpha=0)
scheme.show()
val = scheme.integrate(lambda x: x**2)

1D space with weight function exp(-r<sup>2</sup>) (E<sub>1</sub><sup>r<sup>2</sup></sup>)

<img src="https://raw.githubusercontent.com/sigma-py/quadpy/main/plots/e1r2-gauss-hermite-8.svg" width="50%">

Example:

import quadpy

scheme = quadpy.e1r2.gauss_hermite(5)
scheme.show()
val = scheme.integrate(lambda x: x**2)

Circle (U<sub>2</sub>)

<img src="https://raw.githubusercontent.com/sigma-py/quadpy/main/plots/circle-krylov-30.svg" width="25%">

Example:

import numpy as np
import quadpy

scheme = quadpy.u2.get_good_scheme(7)
scheme.show()
val = scheme.integrate(lambda x: np.exp(x[0]), [0.0, 0.0], 1.0)

Triangle (T<sub>2</sub>)

<img src="https://raw.githubusercontent.com/sigma-py/quadpy/main/plots/triangle-dunavant-15.svg" width="25%">

Apart from the classical centroid, vertex, and seven-point schemes we have

Example:

import numpy as np
import quadpy

scheme = quadpy.t2.get_good_scheme(12)
scheme.show()
val = scheme.integrate(lambda x: np.exp(x[0]), [[0.0, 0.0], [1.0, 0.0], [0.5, 0.7]])

Disk (S<sub>2</sub>)

<img src="https://raw.githubusercontent.com/sigma-py/quadpy/main/plots/disk-hammer-stroud-20.svg" width="25%">

Example:

import numpy as np
import quadpy

scheme = quadpy.s2.get_good_scheme(6)
scheme.show()
val = scheme.integrate(lambda x: np.exp(x[0]), [0.0, 0.0], 1.0)

Quadrilateral (C<sub>2</sub>)

<img src="https://raw.githubusercontent.com/sigma-py/quadpy/main/plots/quad-maxwell.svg" width="25%">

Example:

import numpy as np
import quadpy

scheme = quadpy.c2.get_good_scheme(7)
val = scheme.integrate(
    lambda x: np.exp(x[0]),
    [[[0.0, 0.0], [1.0, 0.0]], [[0.0, 1.0], [1.0, 1.0]]],
)

The points are specified in an array of shape (2, 2, ...) such that arr[0][0] is the lower left corner, arr[1][1] the upper right. If your c2 has its sides aligned with the coordinate axes, you can use the convenience function

<!--pytest.mark.skip-->
quadpy.c2.rectangle_points([x0, x1], [y0, y1])

to generate the array.

2D space with weight function exp(-r) (E<sub>2</sub><sup>r</sup>)

<img src="https://raw.githubusercontent.com/sigma-py/quadpy/main/plots/e2r-rabinowitz-richter-5.svg" width="25%">

Example:

import quadpy

scheme = quadpy.e2r.get_good_scheme(5)
scheme.show()
val = scheme.integrate(lambda x: x[0] ** 2)

2D space with weight function exp(-r<sup>2</sup>) (E<sub>2</sub><sup>r<sup>2</sup></sup>)

<img src="https://raw.githubusercontent.com/sigma-py/quadpy/main/plots/e2r2-rabinowitz-richter-3.svg" width="25%">

Example:

import quadpy

scheme = quadpy.e2r2.get_good_scheme(3)
scheme.show()
val = scheme.integrate(lambda x: x[0] ** 2)

Sphere (U<sub>3</sub>)

<img src="https://raw.githubusercontent.com/sigma-py/quadpy/main/plots/sphere.png" width="25%">

Example:

import numpy as np
import quadpy

scheme = quadpy.u3.get_good_scheme(19)
# scheme.show()
val = scheme.integrate(lambda x: np.exp(x[0]), [0.0, 0.0, 0.0], 1.0)

Integration on the sphere can also be done for functions defined in spherical coordinates:

import numpy as np
import quadpy


def f(theta_phi):
    theta, phi = theta_phi
    return np.sin(phi) ** 2 * np.sin(theta)


scheme = quadpy.u3.get_good_scheme(19)
val = scheme.integrate_spherical(f)

Ball (S<sub>3</sub>)

<img src="https://raw.githubusercontent.com/sigma-py/quadpy/main/plots/ball.png" width="25%">

Example:

import numpy as np
import quadpy

scheme = quadpy.s3.get_good_scheme(4)
# scheme.show()
val = scheme.integrate(lambda x: np.exp(x[0]), [0.0, 0.0, 0.0], 1.0)

Tetrahedron (T<sub>3</sub>)

<img src="https://raw.githubusercontent.com/sigma-py/quadpy/main/plots/tet.png" width="25%">

Example:

import numpy as np
import quadpy

scheme = quadpy.t3.get_good_scheme(5)
# scheme.show()
val = scheme.integrate(
    lambda x: np.exp(x[0]),
    [[0.0, 0.0, 0.0], [1.0, 0.0, 0.0], [0.5, 0.7, 0.0], [0.3, 0.9, 1.0]],
)

Hexahedron (C<sub>3</sub>)

<img src="https://raw.githubusercontent.com/sigma-py/quadpy/main/plots/hexa.png" width="25%">

Example:

import numpy as np
import quadpy

scheme = quadpy.c3.product(quadpy.c1.newton_cotes_closed(3))
# scheme.show()
val = scheme.integrate(
    lambda x: np.exp(x[0]),
    quadpy.c3.cube_points([0.0, 1.0], [-0.3, 0.4], [1.0, 2.1]),
)

Pyramid (P<sub>3</sub>)

<img src="https://raw.githubusercontent.com/sigma-py/quadpy/main/plots/pyra.png" width="25%">

Example:

import numpy as np
import quadpy

scheme = quadpy.p3.felippa_5()

val = scheme.integrate(
    lambda x: np.exp(x[0]),
    [
        [0.0, 0.0, 0.0],
        [1.0, 0.0, 0.0],
        [0.5, 0.7, 0.0],
        [0.3, 0.9, 0.0],
        [0.0, 0.1, 1.0],
    ],
)

Wedge (W<sub>3</sub>)

<img src="https://raw.githubusercontent.com/sigma-py/quadpy/main/plots/wedge.png" width="15%">

Example:

import numpy as np
import quadpy

scheme = quadpy.w3.felippa_3()
val = scheme.integrate(
    lambda x: np.exp(x[0]),
    [
        [[0.0, 0.0, 0.0], [1.0, 0.0, 0.0], [0.5, 0.7, 0.0]],
        [[0.0, 0.0, 1.0], [1.0, 0.0, 1.0], [0.5, 0.7, 1.0]],
    ],
)

3D space with weight function exp(-r) (E<sub>3</sub><sup>r</sup>)

<img src="https://raw.githubusercontent.com/sigma-py/quadpy/main/plots/e3r.png" width="25%">

Example:

import quadpy

scheme = quadpy.e3r.get_good_scheme(5)
# scheme.show()
val = scheme.integrate(lambda x: x[0] ** 2)

3D space with weight function exp(-r<sup>2</sup>) (E<sub>3</sub><sup>r<sup>2</sup></sup>)

<img src="https://raw.githubusercontent.com/sigma-py/quadpy/main/plots/e3r2.png" width="25%">

Example:

import quadpy

scheme = quadpy.e3r2.get_good_scheme(6)
# scheme.show()
val = scheme.integrate(lambda x: x[0] ** 2)

n-Simplex (T<sub>n</sub>)

Example:

import numpy as np
import quadpy

dim = 4
scheme = quadpy.tn.grundmann_moeller(dim, 3)
val = scheme.integrate(
    lambda x: np.exp(x[0]),
    np.array(
        [
            [0.0, 0.0, 0.0, 0.0],
            [1.0, 2.0, 0.0, 0.0],
            [0.0, 1.0, 0.0, 0.0],
            [0.0, 3.0, 1.0, 0.0],
            [0.0, 0.0, 4.0, 1.0],
        ]
    ),
)

n-Sphere (U<sub>n</sub>)

Example:

import numpy as np
import quadpy

dim = 4
scheme = quadpy.un.dobrodeev_1978(dim)
val = scheme.integrate(lambda x: np.exp(x[0]), np.zeros(dim), 1.0)

n-Ball (S<sub>n</sub>)

Example:

import numpy as np
import quadpy

dim = 4
scheme = quadpy.sn.dobrodeev_1970(dim)
val = scheme.integrate(lambda x: np.exp(x[0]), np.zeros(dim), 1.0)

n-Cube (C<sub>n</sub>)

Example:

import numpy as np
import quadpy

dim = 4
scheme = quadpy.cn.stroud_cn_3_3(dim)
val = scheme.integrate(
    lambda x: np.exp(x[0]),
    quadpy.cn.ncube_points([0.0, 1.0], [0.1, 0.9], [-1.0, 1.0], [-1.0, -0.5]),
)

nD space with weight function exp(-r) (E<sub>n</sub><sup>r</sup>)

Example:

import quadpy

dim = 4
scheme = quadpy.enr.stroud_enr_5_4(dim)
val = scheme.integrate(lambda x: x[0] ** 2)

nD space with weight function exp(-r<sup>2</sup>) (E<sub>n</sub><sup>r<sup>2</sup></sup>)

Example:

import quadpy

dim = 4
scheme = quadpy.enr2.stroud_enr2_5_2(dim)
val = scheme.integrate(lambda x: x[0] ** 2)