Use math.sqrt
or np.sqrt
instead of cmath.sqrt
: integrate.dblquad
can't handle complex numbers, even if the imaginary part of those complex numbers is always zero, and mathematically it makes little sense to be using complex numbers here.
To avoid the potential issue of taking the square root of a negative number, you can either:
- adjust the integrand so that it's zero outside the region of interest, or
- adjust the limits so that you're integrating over the unit disk instead of over a square
Here's a version of your code that does the former. Note the use of np.maximum
and np.sqrt
instead of the Python builtin max
and math.sqrt
: this ensures that f
works for array arguments as well as scalar arguments, which may allow dblquad
to compute its result faster.
import numpy as np
from scipy import integrate
f = lambda y, x: np.sqrt(np.maximum(0.0, 1 - x**2 - y**2))
hemisphere = integrate.dblquad(f, -1, 1, lambda x: -1, lambda x: 1)
print(hemisphere)
For me, this produces the expected approximation to 2/3 π
:
(2.0943951045290796, 1.855738140932317e-08)
And here's a version of your code that adjusts the limits instead:
import numpy as np
from scipy import integrate
f = lambda y, x: np.sqrt(1 - x**2 - y**2)
hemisphere = integrate.dblquad(f, -1, 1, lambda x: -np.sqrt(1-x*x),
lambda x: np.sqrt(1-x*x))
print(hemisphere)