Я очень кратко попытаюсь объяснить, что я делаю, тем, кто менее опытен в математике, это действительно довольно просто.
Мы пытаемся заполнить сетку следующим образом:
![enter image description here](https://i.stack.imgur.com/qYnqA.png)
Находим оранжевую точку, U(j,n+1)
, используя три точки подряд под ней, U(j-1,n), U(j,n), U(j,n+1)
Где значение Uво всем нижнем ряду дано, и является периодическим.Таким образом, теоретически мы можем заполнить всю эту сетку.
Формула для вычисления оранжевой точки:
U(j,n+1) = U(j,n) + (delta_t / (2 * delta_x)) * (U(j+1,n) - U(j-1,n))
Мы можем легко написать это как систему линейных уравнений следующим образом:
![enter image description here](https://i.stack.imgur.com/2q2m7.jpg)
И теперь мы просто повторяем этот процесс умножения на эту матрицу (итерации по временной переменной) столько, сколько мы хотим.Это простой способ численно аппроксимировать решение дифференциального уравнения в частных производных.
Я написал код, который делает это, а затем сравниваю свою последнюю строку с известным решением дифференциального уравнения.
Это код
import math
import numpy
def f(x):
return math.cos(2 * math.pi * x)
def solution(x, t):
return math.cos(2 * math.pi * (x + t))
# setting everything up
N = 16
Lambda = 10 ** (-20)
Delta_x = 1/(N+1)
Delta_t = Lambda * Delta_x * Delta_x
t_f = 5
v_0 = numpy.zeros((N, 1))
# Filling first row, initial condition was given
for i in range(N):
v_0[i, 0] = f(i * Delta_x)
# Create coefficient matrix
M = numpy.zeros((N, N))
for i in range(N):
M[i, i - 1] = -Delta_t / (2 * Delta_x)
M[i, i] = 1
M[i, (i + 1) % N] = Delta_t / (2 * Delta_x)
# start iterating through time
v_i = v_0
for i in range(math.floor(t_f / Delta_t) - 1):
v_i = numpy.dot(M, v_i)
v_final = v_i
if (Delta_t * math.ceil(t_f / Delta_t) != t_f): #we don't reach t_f exactly using Delta_t
v_final = (1/2) * (v_i + numpy.dot(M, v_i))
u = numpy.zeros(v_final.shape)
for i in range(N):
u[i, 0] = solution(i * Delta_x, t_f)
for x in range(v_final.shape[0]):
print (v_final[x], u[x])
Теоретически, я должен быть в состоянии найти лямбду достаточно маленькой, чтобы v_final и известное решение, u, были очень похожи.
Но я не могу.Независимо от того, насколько маленьким я делаю лямбду, каким точным я делаю сетку, мне кажется, что что-то не так.Они не близко.
Я не могу на всю жизнь понять проблему.У кого-нибудь есть идеи, что может быть не так?