Рекомендация для метода конечных разностей в научном Python

20

Для проекта, над которым я работаю (в гиперболических PDE), я хотел бы получить некоторую приблизительную информацию о поведении, взглянув на некоторые цифры. Я, однако, не очень хороший программист.

Можете ли вы порекомендовать некоторые ресурсы для изучения того, как эффективно кодировать конечно-разностные схемы в Scientific Python (другие языки с небольшой кривой обучения также приветствуются)?

Чтобы дать вам представление об аудитории (я) по этой рекомендации:

  • Я чистый математик по образованию, и я немного знаком с теоретическими аспектами конечно-разностных схем
  • Мне нужна помощь в том, чтобы заставить компьютер вычислять то, что я хочу вычислить, особенно таким образом, чтобы я не дублировал слишком много усилий, уже приложенных другими (чтобы не заново изобретать колесо, когда пакет уже доступен). (Другая вещь, которую я хотел бы избежать, - это глупо кодировать что-то вручную, когда существуют установленные структуры данных, соответствующие цели.)
  • У меня был некоторый опыт кодирования; но у меня не было ни одного в Python (поэтому я не против, если есть хорошие ресурсы для изучения другого языка [скажем, например, Octave]).
  • Книги, документация были бы полезны, как и коллекции примеров кода.
Вилли Вонг
источник
Основная проблема в том, что я даже не знаю, с чего начать, поэтому даже базовые предложения будут полезны.
Вилли Вонг
Ограничение только в том, что я (пока) не знаком с методами конечного объема; поэтому мне придется изучить метод в сочетании. Я бы не стал возражать против такого ответа, конечно.
Вилли Вонг
PyClaw может обрабатывать нелинейные исходные термины, но написание вашего собственного решателя Римана будет сложным, особенно во 2-м или более высоком измерении. Если вы хотите попробовать простую конечно-разностную схему со структурированными сетками, ваш следующий вариант - это попробовать что-то в petsc4py , (Раскрытие: я также связан с этим проектом), который имеет более общее назначение и не так хорошо документированы.
Арон Ахмадиа
давайте продолжим это обсуждение в чате
Арон Ахмадиа
Привет, Вилли (и для читателей, которые не смотрели чат), я думаю, вы уже знаете это, но, поскольку вы упомянули гиперболические PDE, вам, вероятно, будет лучше использовать метод конечных объемов.
Мэтью Эммет

Ответы:

10

Вот 97-строчный пример решения простого многомерного PDE с использованием методов конечных разностей, предоставленный профессором Дэвидом Кетчесоном из репозитория 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()
Арон Ахмадия
источник
8

Вы можете взглянуть на Fenics , фреймворк на python / C, который позволяет решать довольно общие уравнения с помощью специального языка разметки. Он в основном использует конечные элементы, но стоит посмотреть. Учебник должен дать вам представление о том , как легко можно решить проблемы.

moyner
источник
3

Эта ссылка может быть очень полезной для вас. Это открытая книга в интернете. Я узнал (все еще учусь), Python из этой книги. Я нашел это очень хороший ресурс действительно.

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

Для численного расчета нужно определенно пойти на «NumPy». (просто убедитесь, что вы правильно поняли «массив», «матрица» и «список») (для этого обратитесь к документации numpy)

Subodh
источник