Python Numerical Integration for Volume of Region Python Numerical Integration for Volume of Region numpy numpy

Python Numerical Integration for Volume of Region


As the others have already noted, finding the volume of domain that's given by a Boolean function is hard. You could used pygalmesh (a small project of mine) which sits on top of CGAL and gives you back a tetrahedral mesh. This

import numpyimport pygalmeshimport meshplexclass Custom(pygalmesh.DomainBase):    def __init__(self):        super(Custom, self).__init__()        return    def eval(self, x):        return (x[0]**2 + x[1]**2 + x[2]**2) - 1.0    def get_bounding_sphere_squared_radius(self):        return 2.0mesh = pygalmesh.generate_mesh(Custom(), cell_size=1.0e-1)

gives you

enter image description here

From there on out, you can use a variety of packages for extracting the volume. One possibility: meshplex (another one out of my zoo):

import meshplexmp = meshplex.MeshTetra(mesh.points, mesh.cells["tetra"])print(numpy.sum(mp.cell_volumes))

gives

4.161777

which is close enough to the true value 4/3 pi = 4.18879020478.... If want more precision, decrease the cell_size in the mesh generation above.


Your function is not a continuous function, I think it's difficult to do the integration.

How about:

import numpy as npdef sphere(x,y,z):    return x**2 + y**2 + z**2 <= 1x, y, z = np.random.uniform(-2, 2, (3, 2000000))sphere(x, y, z).mean() * (4**3), 4/3.0*np.pi

output:

(4.1930560000000003, 4.1887902047863905)

Or VTK:

from tvtk.api import tvtkn = 151r = 2.0x0, x1 = -r, ry0, y1 = -r, rz0, z1 = -r, rX,Y,Z = np.mgrid[x0:x1:n*1j, y0:y1:n*1j, z0:z1:n*1j]s = sphere(X, Y, Z)img = tvtk.ImageData(spacing=((x1-x0)/(n-1), (y1-y0)/(n-1), (z1-z0)/(n-1)),                      origin=(x0, y0, z0), dimensions=(n, n, n))img.point_data.scalars = s.astype(float).ravel()blur = tvtk.ImageGaussianSmooth(input=img) blur.set_standard_deviation(1)contours = tvtk.ContourFilter(input = blur.output) contours.set_value(0, 0.5)mp = tvtk.MassProperties(input = contours.output)mp.volume, mp.surface_area

output:

4.186006622559839, 12.621690438955586


It seems to be very difficult without giving a little hint on the boundary:

import numpy as npfrom scipy.integrate import *def integrand(z,y,x):    return 1. if x**2 + y**2 + z**2 <= 1. else 0.g=lambda x: -2h=lambda x: 2q=lambda x,y: -np.sqrt(max(0, 1-x**2-y**2))r=lambda x,y: np.sqrt(max(0, 1-x**2-y**2))I=tplquad(integrand,-2.,2.,g,h,q,r)print I