pythonscipynumerical-integrationquad

scipy.integrate.tplquad gives wrong result for integral over large volume


I'm trying to integrate a function of 3 variables f(x,y,z) over all space.

When I integrate over a small volume, I get roughly the right result. However, when I increase the volume of integration, python says that the integral is zero.

I'm fairly confident that the issue here is that the function f is only non-zero in a small region of space, and tplquad dosen't sample over this region enough when the integration volume is large. I found an answer to a similar problem in 1D at this link; scipy.integrate.quad gives wrong result on large ranges. The solution in 1D was to pass an argument 'points' to scipy.integrate.quad, and this helped quad focus on the interval where the integral was non-zero.

My question is; is there a similar argument to 'points' for tplquad? Or perhaps some other way I can instruct tplquad to focus on a particular region of space?


Solution

  • The method tplquad is just a wrapper over nquad which does not expose all of the options of the latter. Use nquad, which supports passing points to quad via opts parameter. A simple example, with the same points for all ranges:

    import numpy as np
    from scipy.integrate import nquad
    f = lambda x, y, z: np.exp(-x**2-y**2-z**2)
    nquad(f, [[-150, 90], [-150, 90], [-150, 90]])[0]   # 2.260158041551299e-16, wrong
    nquad(f, [[-150, 90], [-150, 90], [-150, 90]], opts={"points": [-5, 5]})[0]   # 5.568327996820292, correct
    

    In general, opts can be a list of different options for different steps of multiple integration, and points can differ between them. They can also depend on other variables, like limits of integration can; see the example in the documentation.