Лучший способ сделать это - (как вы сказали) просто использовать определение периодических граничных условий и правильно настроить ваши уравнения с самого начала, используя тот факт, что . Фактически, еще сильнее периодические граничные условия отождествляют x = 0 с x = 1 . По этой причине у вас должна быть только одна из этих точек в вашем домене решений. Открытый интервал не имеет смысла при использовании периодических граничных условий, так как нет границы .u(0)=u(1)x=0x=1
Этот факт означает, что вам не следует помещать точку в поскольку она совпадает с x = 0 . Дискретизируя с N + 1 точками, вы затем используете тот факт, что по определению точка слева от x 0 равна x N, а точка справа от x N равна x 0 .x=1x=0N+1x0 xNxN x0
Ваш PDE может быть затем дискретизирован в пространстве как
∂∂t⎡⎣⎢⎢⎢⎢x0x1⋮xN⎤⎦⎥⎥⎥⎥=1Δx2⎡⎣⎢⎢⎢⎢xN−2x0+x1x0−2x1+x2⋮xN−1−2xN+x0⎤⎦⎥⎥⎥⎥
Это можно записать в матричной форме как
,
где
=[ - 2 1 0 ⋯ 0 1 1 -
∂∂tx⃗ =1Δx2Ax⃗
A=⎡⎣⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢−21011−2⋱⋯001⋱⋱0⋯⋯0⋱⋱100⋯⋱−21101−2⎤⎦⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥.
Конечно, нет необходимости создавать или хранить эту матрицу. Конечные различия должны быть вычислены на лету, обращаясь к первым и последним точкам, особенно по мере необходимости.
В качестве простого примера, следующие MATLAB скрипт решает
с периодическими граничными условиями на области х ∈ [ - 1 , 1 ) . Изготовленный раствор u Ref ( t , x ) = exp ( - t ) cos ( 5 π x
∂tu=∂xxu+b(t,x)
x∈[−1,1) , что означает
b ( t ,uRef(t,x)=exp(−t)cos(5πx) . Я использовал прямую дискретизацию Эйлера по времени для простоты и вычислил решение как с матрицей, так и без нее. Результаты показаны ниже.
b(t,x)=(25π2−1)exp(−t)cos(5πx)
clear
% Solve: u_t = u_xx + b
% with periodic boundary conditions
% analytical solution:
uRef = @(t,x) exp(-t)*cos(5*pi*x);
b = @(t,x) (25*pi^2-1)*exp(-t)*cos(5*pi*x);
% grid
N = 30;
x(:,1) = linspace(-1,1,N+1);
% leave off 1 point so initial condition is periodic
% (doesn't have a duplicate point)
x(end) = [];
uWithMatrix = uRef(0,x);
uNoMatrix = uRef(0,x);
dx = diff(x(1:2));
dt = dx.^2/2;
%Iteration matrix:
e = ones(N,1);
A = spdiags([e -2*e e], -1:1, N, N);
A(N,1) = 1;
A(1,N) = 1;
A = A/dx^2;
%indices (left, center, right) for second order centered difference
iLeft = [numel(x), 1:numel(x)-1]';
iCenter = (1:numel(x))';
iRight = [2:numel(x), 1]';
%plot
figure(1)
clf
hold on
h0=plot(x,uRef(0,x),'k--','linewidth',2);
h1=plot(x,uWithMatrix);
h2=plot(x,uNoMatrix,'o');
ylim([-1.2, 1.2])
legend('Analytical solution','Matrix solution','Matrix-free solution')
ht = title(sprintf('Time t = %0.2f',0));
xlabel('x')
ylabel('u')
drawnow
for t = 0:dt:1
uWithMatrix = uWithMatrix + dt*( A*uWithMatrix + b(t,x) );
uNoMatrix = uNoMatrix + dt*( ( uNoMatrix(iLeft) ...
- 2*uNoMatrix(iCenter) ...
+ uNoMatrix(iRight) )/dx^2 ...
+ b(t,x) );
set(h0,'ydata',uRef(t,x))
set(h1,'ydata',uWithMatrix)
set(h2,'ydata',uNoMatrix)
set(ht,'String',sprintf('Time t = %0.2f',t))
drawnow
end