I'm trying to do this triple integral in scipy:
from scipy.integrate import dblquad, tplquad, nquad
def inte(z, y, x):
return 2*z
with tplquad
I get the right result:
volume = tplquad(inte, 0, 1, lambda x: x**3, lambda x: x, lambda x, y: 0, lambda x, y: 2*x)
volume[0]
0.33333333333333337
While this is what happens when I use nquad
:
def range_3():
return [0, 1]
def range_2(x):
return [x**3, x]
def range_1(x, y):
return [0, 2*x]
volume, error = nquad(inte, [range_1, range_2, range_3])
volume
0.2
What is wrong with my nquad
call?
I stared at this problem for a while trying to figure it out, but I finally got it. When you pass functions as the integration limits for tplquad
, the function arguments are ordered x, y
, but for nquad
it's y, x
. This can be seen when you look at the documentation.
tplquad
:
qfun : function or float
The lower boundary surface in z. It must be a function that takes two floats in the order (x, y) and returns a float or a float indicating a constant boundary surface.
nquad
:
ranges : iterable object
...If an element of ranges is a callable, then it will be called with all of the integration arguments available, as well as any parametric arguments. e.g., iffunc = f(x0, x1, x2, t0, t1)
, thenranges[0]
may be defined as either(a, b)
or else as(a, b) = range0(x1, x2, t0, t1)
.
from scipy.integrate import tplquad, nquad
def integrand(z, y, x):
return 2*z
res_tplquad, _ = tplquad(integrand,
0, 1,
lambda x: x**3, lambda x: x,
0, lambda x, y: 2*x)
print(res_tplquad) # 0.33333333333333337
def range_3():
return [0, 1]
def range_2(x):
return [x**3, x]
def range_1(y, x):
return [0, 2*x]
res_nquad, _ = nquad(integrand, [range_1, range_2, range_3])
print(res_nquad) # 0.33333333333333337