簡體   English   中英

如何正確使用scipy tplquad?

[英]how to use scipy tplquad properly?

我正在嘗試使用scipy的tplquad做一些簡單的物理三重積分。 例如,我嘗試將單位球的恆定質量密度(func d)積分到單位立方體上。 這行不通。 但是,如果我將單位立方體的恆定質量密度(func f)積分到單位立方體上,則會很快得到結果。

我認為問題在於將常量積分限制提供為常量而不是函數。 我使用lambda修復了該問題,但仍然無法獲得積分。

from scipy import integrate

''' returns the mass density at a point (x,y,z)'''
def d(z, x, y):
  return int(x**2 + y**2 + z**2 <= 1) # unit ball with constant density = 1 , here all orthogonal axes are principal 

def f(x,y,z):
    return 1

integrate.tplquad(d, -1, 1, lambda x: -1, lambda x: 1,lambda x, y: -1, lambda x, y: 1) # doesn't work / too slow
integrate.tplquad(f, -1, 1, lambda x: -1, lambda x: 1,lambda x, y: -1, lambda x, y: 1) # works fine

我希望在給定范圍內d的積分為4/3 * pi。

積分不連續函數是一個困難的數值問題。

解決方法是將集成域定義為單位球:

from scipy import integrate
import numpy as np

''' returns the mass density at a point (x,y,z)'''
def d(z, x, y):
      return 1

integrate.tplquad(d, -1, 1,
                  lambda x: -np.sqrt(1-x**2), lambda x: np.sqrt(1-x**2),
                  lambda x, y: -np.sqrt(1-x**2-y**2), lambda x, y: np.sqrt(1-x**2-y**2))
# (4.188790204786397, 2.000470900043183e-09)
# 4/3*np.pi = 4.1887902047863905

另一個不理想的解決方案是人為地平滑功能。 例如,使用Logistic函數,請參閱Heaviside_step_function的解析近似值

''' returns the mass density at a point (x,y,z)'''
def d(z, x, y):
    r2 = x**2 + y**2 + z**2
    smoothing_length = 0.1 # same unit as r2
    d = 1 - 1/(1 + np.exp(-2*(r2-1)/smoothing_length))
    return d

integrate.tplquad(d, -1, 1, lambda x: -1, lambda x: 1,lambda x, y: -1, lambda x, y: 1)
# (4.182852937567993, 3.021537155780628e-08)

必須謹慎選擇值smoothing_length

蒙特卡洛積分可能是解決更復雜問題的正確方法。

大多數數值積分例程(例如tplquad )通過使用多項式逼近積分。 如果函數平滑,則效果很好。 不幸的是,特征函數除了平滑之外還具有其他所有功能,因為它們具有不連續的邊界。 這就是tplquad失敗的原因。

如果您想近似一個域的體積,一種合理的方法是為其創建三角形(2D)或四面體(3D)網格,然后添加單純形的體積。 網格生成器的一個示例是pygmshpygalmesh (屬於我的項目),但還有其他示例。

如果您確實想在球上集成一個功能,則可能應該看一下Quadpy (我的另一個項目)。 它具有針對各個領域的許多集成方案,其中包括球。 這個

import numpy
import quadpy

scheme = quadpy.ball.hammer_stroud_14_3()
val = scheme.integrate(
    lambda x: numpy.ones_like(x[0]),  # function to integrate
    [0.0, 0.0, 0.0],  # center
    1.0,  # radius
    )
print(val)  # 4.1887902047863905 == 4*pi/3

將使用度數5的方案將函數1積分到單位球上,並返回精確的結果。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM