我想用python解决以下PDE:
\frac{\partial U}{\partial t}=\frac{\partial^2 U}{\partial x^2}-h(U,Q)\\
\frac{\partial Q}{\partial t}=h(U,Q)
其中h是U和Q的给定函数,具有混合边界条件:
Q(0,t)=1
\left[\frac{\partial U}{\partial x}\right]_{x=0}=-\alpha*(1-U(0,t))
Q(x\to\infty,t)=U(x\to\infty,t)=0
其中\ alpha是给定的常数。我使用了有限差分法和Picard迭代法。使用以下算法,一切进展顺利
import numpy as np
import matplotlib.pyplot as plt
import os
## number of time steps
n = 3200
## total time
t = 1200.
## time increment
dt =1.*t/n
## number of finite displacements
k = 600
## maximal distance
x = 200
## finite displacement
dx = 1.*x/k
## initial conditions for U
x0U = 1
u0 = 1.
## initial conditions for U have the form of a Heaviside step function
u = np.zeros((n,k))
u[0,:x0U] = u0
## initial conditions for Q
x0Q = 3
q0 = 1.
## the initial conditions for Q have the form of a Heaviside step function
q = np.zeros((n,k))
q[0,:x0Q] = q0
## alpha
alpha = 10**(-1)
## the following is the value for the boundary condition at infinity
bond = 10.**(-25)
## define h
def h(y1,y2):
return 1.*y1*(1.-y2)
## this is the matrix Mat used for Mat.u=b(u)
Mat = np.zeros((k,k))
for i in range(1,k-1):
Mat[i,i+1]=1./(dx)**2
Mat[i, i] = -1./dt - 2./(dx)**2
Mat[i, i - 1] = 1./(dx)**2
Mat[0, 1] = 2./(dx)**2
Mat[0, 0] = -2./(dx)**2 - 2.*alpha/dx - 1./dt
Mat[k-1, k-1] = 1.
## define b(u)
b=np.zeros(k)
qQ = np.zeros(k)
uU = np.zeros(k)
## this is used to test whether the guess values are close enough to the results of the equation
epsilon = 10.**(-3.);
## the initial guess for u and q (called uG and qG) is the value in the previous time step
for i in range(1,n):
qG = q[i-1]
uG = u[i-1]
if i%100==0:
print 'uG ',uG[0]
print 'qG ',qG[10]
## Picard's iteration starts here
check = 0;
while check != 1:
## find Q
qQ = dt*h(uG, qG)+1.*q[i-1,:]
## update the constant term
b = h(uG, qQ) -1.*u[i-1,:]/dt
b[0] -= 2.*alpha/dx
b[k-1] = bond
## solve the equation for U
uU = np.linalg.solve(Mat,b)
## check if the guess values are already close enough to the results of the equations
if sum(abs(qQ - qG)) < epsilon and sum(abs(uU - uG)) < epsilon:
check = 1
## update Q and U
else:
qG = qQ
uG = uU
if i%50==0:
print "time step ", i
## save the values for Q and U corresponding to time i
q[i] = qQ
u[i] = uU
fig1=plt.figure(1)
plt.plot(u[500])
plt.plot(u[1000])
plt.plot(u[1500])
plt.plot(u[2000])
fig5=plt.figure(2)
plt.plot(q[500])
plt.plot(q[1000])
plt.plot(q[1500])
plt.plot(q[2000])
plt.show()
对于四个不同的t值,该算法将返回两个表示U和Q作为x的函数的图。 当我对边界条件使用更复杂的公式时会出现问题,例如
\left[\frac{\partial U}{\partial x}\right]_{x=0}=-\frac{\alpha*(1-U(0,t))}{\alpha+(1-U(0,t))}
其中\ alpha是时间的函数。在这些情况下,U会变得大于1,这是不应该发生的。我想知道: 1)一般来说,如果我的算法可以改进和提高 2)如果使用有限差分法是一个好主意,或者对于这种特殊情况有更好的方法(或者甚至其他对我有用的软件包) 3)Picard迭代是否以正确的方式实现 4)为什么在更复杂的边界条件下遇到这些数值问题以及避免该问题的一般技巧(如果有)