寻找用于在细分域上进行数值积分的 Python 包

发布于 2024-11-06 04:36:26 字数 634 浏览 2 评论 0原文

我想知道是否有人知道基于 numpy/scipy 的 python 包,可以在镶嵌域(在我的具体情况下,由 voronoi 单元格界定的 2D 域)上对复杂的数值函数进行数值积分?过去,我使用了几个 matlab 文件交换之外的包,但如果可能的话,希望保留在我当前的 python 工作流程中。 Matlab 例程为

http://www.mathworks.com/matlabcentral/fileexchange/9435- n-Dimensional-simplex-quadrature

用于求积和网格生成,使用:

http ://www.mathworks.com/matlabcentral/fileexchange/25555-mesh2d-automatic-mesh- Generation

任何有关网格生成以及对该网格进行数值积分的建议将不胜感激。

I was wondering if anyone knew of a numpy/scipy based python package to numerically integrate a complicated numerical function over a tessellated domain (in my specific case, a 2D domain bounded by a voronoi cell)? In the past I used a couple of packages off of the matlab file exchange, but would like to stay within my current python workflow if possible. The matlab routines were

http://www.mathworks.com/matlabcentral/fileexchange/9435-n-dimensional-simplex-quadrature

for the quadrature and mesh generation using:

http://www.mathworks.com/matlabcentral/fileexchange/25555-mesh2d-automatic-mesh-generation

Any suggestions on mesh generation and then numerical integration over that mesh would be appreciated.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

吃不饱 2024-11-13 04:36:27

这直接在三角形上积分,而不是 Voronoi 区域,但应该很接近。 (用不同数量的点运行来查看?)它也适用于 2d、3d ...

#!/usr/bin/env python
from __future__ import division
import numpy as np

__date__ = "2011-06-15 jun denis"

#...............................................................................
def sumtriangles( xy, z, triangles ):
    """ integrate scattered data, given a triangulation
    zsum, areasum = sumtriangles( xy, z, triangles )
    In:
        xy: npt, dim data points in 2d, 3d ...
        z: npt data values at the points, scalars or vectors
        triangles: ntri, dim+1 indices of triangles or simplexes, as from
http://docs.scipy.org/doc/scipy/reference/generated/scipy.spatial.Delaunay.html
    Out:
        zsum: sum over all triangles of (area * z at midpoint).
            Thus z at a point where 5 triangles meet
            enters the sum 5 times, each weighted by that triangle's area / 3.
        areasum: the area or volume of the convex hull of the data points.
            For points over the unit square, zsum outside the hull is 0,
            so zsum / areasum would compensate for that.
            Or, make sure that the corners of the square or cube are in xy.
    """
        # z concave or convex => under or overestimates
    npt, dim = xy.shape
    ntri, dim1 = triangles.shape
    assert npt == len(z), "shape mismatch: xy %s z %s" % (xy.shape, z.shape)
    assert dim1 == dim+1, "triangles ? %s" % triangles.shape
    zsum = np.zeros( z[0].shape )
    areasum = 0
    dimfac = np.prod( np.arange( 1, dim+1 ))
    for tri in triangles:
        corners = xy[tri]
        t = corners[1:] - corners[0]
        if dim == 2:
            area = abs( t[0,0] * t[1,1] - t[0,1] * t[1,0] ) / 2
        else:
            area = abs( np.linalg.det( t )) / dimfac  # v slow
        zsum += area * z[tri].mean(axis=0)
        areasum += area
    return (zsum, areasum)

#...............................................................................
if __name__ == "__main__":
    import sys
    from time import time
    from scipy.spatial import Delaunay

    npt = 500
    dim = 2
    seed = 1

    exec( "\n".join( sys.argv[1:] ))  # run this.py npt= dim= ...
    np.set_printoptions( 2, threshold=100, edgeitems=5, suppress=True )
    np.random.seed(seed)

    points = np.random.uniform( size=(npt,dim) )
    z = points  # vec; zsum should be ~ constant
    # z = points[:,0]
    t0 = time()
    tessellation = Delaunay( points )
    t1 = time()
    triangles = tessellation.vertices  # ntri, dim+1
    zsum, areasum = sumtriangles( points, z, triangles )
    t2 = time()

    print "%s: %.0f msec Delaunay, %.0f msec sum %d triangles:  zsum %s  areasum %.3g" % (
        points.shape, (t1 - t0) * 1000, (t2 - t1) * 1000,
        len(triangles), zsum, areasum )
# mac ppc, numpy 1.5.1 15jun:
# (500, 2): 25 msec Delaunay, 279 msec sum 983 triangles:  zsum [ 0.48  0.48]  areasum 0.969
# (500, 3): 111 msec Delaunay, 3135 msec sum 3046 triangles:  zsum [ 0.45  0.45  0.44]  areasum 0.892

This integrates over triangles directly, not the Voronoi regions, but should be close. (Run with different numbers of points to see ?) Also it works in 2d, 3d ...

#!/usr/bin/env python
from __future__ import division
import numpy as np

__date__ = "2011-06-15 jun denis"

#...............................................................................
def sumtriangles( xy, z, triangles ):
    """ integrate scattered data, given a triangulation
    zsum, areasum = sumtriangles( xy, z, triangles )
    In:
        xy: npt, dim data points in 2d, 3d ...
        z: npt data values at the points, scalars or vectors
        triangles: ntri, dim+1 indices of triangles or simplexes, as from
http://docs.scipy.org/doc/scipy/reference/generated/scipy.spatial.Delaunay.html
    Out:
        zsum: sum over all triangles of (area * z at midpoint).
            Thus z at a point where 5 triangles meet
            enters the sum 5 times, each weighted by that triangle's area / 3.
        areasum: the area or volume of the convex hull of the data points.
            For points over the unit square, zsum outside the hull is 0,
            so zsum / areasum would compensate for that.
            Or, make sure that the corners of the square or cube are in xy.
    """
        # z concave or convex => under or overestimates
    npt, dim = xy.shape
    ntri, dim1 = triangles.shape
    assert npt == len(z), "shape mismatch: xy %s z %s" % (xy.shape, z.shape)
    assert dim1 == dim+1, "triangles ? %s" % triangles.shape
    zsum = np.zeros( z[0].shape )
    areasum = 0
    dimfac = np.prod( np.arange( 1, dim+1 ))
    for tri in triangles:
        corners = xy[tri]
        t = corners[1:] - corners[0]
        if dim == 2:
            area = abs( t[0,0] * t[1,1] - t[0,1] * t[1,0] ) / 2
        else:
            area = abs( np.linalg.det( t )) / dimfac  # v slow
        zsum += area * z[tri].mean(axis=0)
        areasum += area
    return (zsum, areasum)

#...............................................................................
if __name__ == "__main__":
    import sys
    from time import time
    from scipy.spatial import Delaunay

    npt = 500
    dim = 2
    seed = 1

    exec( "\n".join( sys.argv[1:] ))  # run this.py npt= dim= ...
    np.set_printoptions( 2, threshold=100, edgeitems=5, suppress=True )
    np.random.seed(seed)

    points = np.random.uniform( size=(npt,dim) )
    z = points  # vec; zsum should be ~ constant
    # z = points[:,0]
    t0 = time()
    tessellation = Delaunay( points )
    t1 = time()
    triangles = tessellation.vertices  # ntri, dim+1
    zsum, areasum = sumtriangles( points, z, triangles )
    t2 = time()

    print "%s: %.0f msec Delaunay, %.0f msec sum %d triangles:  zsum %s  areasum %.3g" % (
        points.shape, (t1 - t0) * 1000, (t2 - t1) * 1000,
        len(triangles), zsum, areasum )
# mac ppc, numpy 1.5.1 15jun:
# (500, 2): 25 msec Delaunay, 279 msec sum 983 triangles:  zsum [ 0.48  0.48]  areasum 0.969
# (500, 3): 111 msec Delaunay, 3135 msec sum 3046 triangles:  zsum [ 0.45  0.45  0.44]  areasum 0.892
心碎的声音 2024-11-13 04:36:27

数值积分通常是在三角形或矩形等简单元素上定义的。也就是说,您可以将每个 polgon 分解为一系列三角形。运气好的话,您的多边形网格有一个三角形对偶,这将使集成变得更加容易。

quadpy (我的一个项目)对许多域(例如三角形)进行数值积分:

import numpy
import quadpy


sol, error_estimate = quadpy.t2.integrate_adaptive(
    lambda x: numpy.exp(x[0]),
    numpy.array(
        [
            [[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]],
            [[1.0, 0.0], [1.0, 0.0], [1.0, 0.0], [1.0, 0.0], [1.0, 0.0]],
            [[0.0, 1.0], [0.0, 1.0], [0.0, 1.0], [0.0, 1.0], [0.0, 1.0]],
        ]
    ),
    1.0e-10,
)

print(sol)
3.5914091422921017

您也可以积分通过为三角形提供数百种方案之一来非自适应地实现。

Numerical integration is typically defined over simple elements like triangles or rectangles. That said, you can decompose every polgon into a series of triangles. With any luck, your polygonal mesh has a triangular dual which would make integration much easier.

quadpy (a project of mine) does numerical integration over many domains, e.g., triangles:

import numpy
import quadpy


sol, error_estimate = quadpy.t2.integrate_adaptive(
    lambda x: numpy.exp(x[0]),
    numpy.array(
        [
            [[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]],
            [[1.0, 0.0], [1.0, 0.0], [1.0, 0.0], [1.0, 0.0], [1.0, 0.0]],
            [[0.0, 1.0], [0.0, 1.0], [0.0, 1.0], [0.0, 1.0], [0.0, 1.0]],
        ]
    ),
    1.0e-10,
)

print(sol)
3.5914091422921017

You can also integrate non-adaptively by providing one of hundreds of schemes for the triangle.

怀里藏娇 2024-11-13 04:36:27

scipy.integrate.dblquad怎么样?它使用自适应求积规则,因此您可以放弃对积分网格的控制。不知道这对你的申请来说是有利还是不利。

How about scipy.integrate.dblquad? It uses a adaptive quadrature rule so you relinquish your control over your integrating mesh. Don't know if that is a plus or minus for your application.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文