科学Python中有限差分法的建议


20

对于我正在研究的项目(在双曲PDE中),我希望通过查看一些数字来大致了解行为。但是,我不是一个很好的程序员。

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

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

  • 我是经过培训的纯数学家,并且对有限差分方案的理论知识有些熟悉
  • 我需要帮助的是如何使计算机计算出我想要的计算量,特别是以一种方式,我不会重复别人已经付出的太多努力(以免在需要时重新发明轮子)包已可用)。(我想避免的另一件事是,在建立了适合该目的的数据结构时,手动编写一些愚蠢的代码。)
  • 我有一些编码经验;但是我没有使用Python的知识(因此我不介意是否有足够的资源来学习其他语言(例如,例如Octave))。
  • 书籍,文档以及示例代码的集合都将是有用的。

主要的问题是我什至不知道从哪里开始寻找东西:因此,即使是基本的建议也会有所帮助。
威利·黄

限制仅仅是我还不熟悉有限体积方法。因此,我将不得不结合学习该方法。我当然不反对这样的答案。
Willie Wong

PyClaw可以处理非线性源项,但是编写您自己的Riemann求解器会很复杂,尤其是在第二维或更高维中。如果您想尝试使用结构化网格的简单有限差分方案,那么您的下一个选择是尝试使用petsc4py中的内容(披露:我也隶属于该项目),这是更通用的用途,而不是那么好-记录下来。
阿隆·艾玛迪亚


嗨,威利(对于尚未看过该聊天的读者而言),我想您已经知道了,但是由于您提到了双曲线PDE,所以使用有限体积方法可能会更好。
马修·埃米特

Answers:


10

这是一条由97行代码组成的示例,该示例使用有限差分方法求解简单的多元PDE ,这我维护的py4sci存储库中的David Ketcheson教授提供的。对于需要以有限体积离散化处理冲击或守恒问题的更复杂问题,我建议查看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()

8

您可以看一下Fenics,它是一个python / C框架,它允许使用特殊的标记语言来求解非常通用的方程式。虽然它主要使用有限元素,但值得一看。本教程应该给您一种解决问题的容易程度的印象。


3

此参考可能对您非常有用。这是一本关于互联网的开放书。我从本书中学到了(仍然在学习中)python。我确实找到了很好的资源。

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

对于数值计算,绝对应该使用“ numpy”。(只要确保您已正确理解'array'和'matrix'和'list')(请参阅numpy文档)

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.