科学 Python 中的有限差分法推荐

计算科学 Python 有限差分 参考请求 双曲-pde
2021-12-13 21:00:05

对于我正在处理的一个项目(在双曲线 PDE 中),我想通过查看一些数字来粗略地处理行为。然而,我不是一个很好的程序员。

您能否推荐一些资源来学习如何在 Scientific Python 中有效地编写有限差分方案(也欢迎其他学习曲线较小的语言)?

为了让您了解此建议的受众(我):

  • 我是一名受过训练的纯数学家,并且对有限差分方案的理论方面有些熟悉
  • 我需要帮助的是如何让计算机计算我希望它计算的东西,特别是在我不会重复其他人已经付出的太多努力的方式(以免重新发明轮子)一个包已经可用)。(我想避免的另一件事是,当存在符合目的的既定数据结构时,手动愚蠢地编写代码。)
  • 我有一些编码经验;但我在 Python 中没有(因此我不介意是否有学习不同语言的好资源 [比如 Octave])。
  • 书籍、文档以及示例代码的集合都很有用。
3个回答

这是一个 97 行示例,使用有限差分方法求解简单的多元 PDE,由David Ketcheson 教授提供,来自我维护的py4sci 存储库。对于需要在有限体积离散化中处理冲击或守恒的更复杂的问题,我建议查看pyclaw,这是我帮助开发的一个软件包。

"""Pattern formation code

    Solves the pair of PDEs:
       u_t = D_1 \nabla^2 u + f(u,v)
       v_t = D_2 \nabla^2 v + g(u,v)
"""

import matplotlib
matplotlib.use('TkAgg')
import numpy as np
import matplotlib.pyplot as plt
from scipy.sparse import spdiags,linalg,eye
from time import sleep

#Parameter values
Du=0.500; Dv=1;
delta=0.0045; tau1=0.02; tau2=0.2; alpha=0.899; beta=-0.91; gamma=-alpha;
#delta=0.0045; tau1=0.02; tau2=0.2; alpha=1.9; beta=-0.91; gamma=-alpha;
#delta=0.0045; tau1=2.02; tau2=0.; alpha=2.0; beta=-0.91; gamma=-alpha;
#delta=0.0021; tau1=3.5; tau2=0; alpha=0.899; beta=-0.91; gamma=-alpha;
#delta=0.0045; tau1=0.02; tau2=0.2; alpha=1.9; beta=-0.85; gamma=-alpha;
#delta=0.0001; tau1=0.02; tau2=0.2; alpha=0.899; beta=-0.91; gamma=-alpha;
#delta=0.0005; tau1=2.02; tau2=0.; alpha=2.0; beta=-0.91; gamma=-alpha; nx=150;

#Define the reaction functions
def f(u,v):
    return alpha*u*(1-tau1*v**2) + v*(1-tau2*u);

def g(u,v):
    return beta*v*(1+alpha*tau1/beta*u*v) + u*(gamma+tau2*v);


def five_pt_laplacian(m,a,b):
    """Construct a matrix that applies the 5-point laplacian discretization"""
    e=np.ones(m**2)
    e2=([0]+[1]*(m-1))*m
    h=(b-a)/(m+1)
    A=np.diag(-4*e,0)+np.diag(e2[1:],-1)+np.diag(e2[1:],1)+np.diag(e[m:],m)+np.diag(e[m:],-m)
    A/=h**2
    return A

def five_pt_laplacian_sparse(m,a,b):
    """Construct a sparse matrix that applies the 5-point laplacian discretization"""
    e=np.ones(m**2)
    e2=([1]*(m-1)+[0])*m
    e3=([0]+[1]*(m-1))*m
    h=(b-a)/(m+1)
    A=spdiags([-4*e,e2,e3,e,e],[0,-1,1,-m,m],m**2,m**2)
    A/=h**2
    return A

# Set up the grid
a=-1.; b=1.
m=100; h=(b-a)/m; 
x = np.linspace(-1,1,m)
y = np.linspace(-1,1,m)
Y,X = np.meshgrid(y,x)

# Initial data
u=np.random.randn(m,m)/2.;
v=np.random.randn(m,m)/2.;
plt.hold(False)
plt.pcolormesh(x,y,u)
plt.colorbar; plt.axis('image'); 
plt.draw()
u=u.reshape(-1)
v=v.reshape(-1)

A=five_pt_laplacian_sparse(m,-1.,1.);
II=eye(m*m,m*m)

t=0.
dt=h/delta/5.;
plt.ion()

#Now step forward in time
for k in range(120):
    #Simple (1st-order) operator splitting:
    u = linalg.spsolve(II-dt*delta*Du*A,u)
    v = linalg.spsolve(II-dt*delta*Dv*A,v)

    unew=u+dt*f(u,v);
    v   =v+dt*g(u,v);
    u=unew;
    t=t+dt;

    #Plot every 3rd frame
    if k/3==float(k)/3:
        U=u.reshape((m,m))
        plt.pcolormesh(x,y,U)
        plt.colorbar
        plt.axis('image')
        plt.title(str(t))
        plt.draw()

plt.ioff()

你可以看看Fenics,它是一个 python/C 框架,它允许使用特殊的标记语言来求解非常通用的方程。虽然它主要使用有限元,但值得一看。教程应该让您了解解决问题是多么容易。

此参考资料可能对您非常有用。这是一本在互联网上打开的书。我从这本书中学习(仍在学习)python。我发现它确实是非常好的资源。

http://www.openbookproject.net/thinkcs/python/english2e/

对于数值计算,绝对应该选择“numpy”。(只需确保您正确理解了“数组”、“矩阵”和“列表”)(请参阅 numpy 文档)