これを行う最良の方法は、(あなたが言ったように)周期境界条件の定義を使用し、という事実を使用して最初から方程式を正しく設定することです。実際、さらに強力なのは、周期的な境界条件がx = 0をx = 1で識別することです。このため、ソリューションドメインにはこれらのポイントのうち1つのみを含める必要があります。周期的な境界条件を使用する場合、境界がないため、オープン間隔は意味がありません。u (0 )= u (1 )x = 0x = 1
この事実は、x = 0と同じであるため、点を置かないことを意味します。離散N + 1つの点、あなたはその後、事実を使用することを定義することにより、左側のポイントのx 0 IS X Nとの右のポイントxをNであるX 0を。x = 1x = 0N+ 1バツ0 バツNバツN バツ0
PDEは、空間でdiscとして離散化できます。
∂∂t⎡⎣⎢⎢⎢⎢バツ0バツ1⋮バツN⎤⎦⎥⎥⎥⎥= 1ΔのX2⎡⎣⎢⎢⎢⎢バツN− 2 x0+ x1バツ0− 2 x1+ x2⋮バツN− 1− 2 xN+ x0⎤⎦⎥⎥⎥⎥
これは、行列形式で書くことができる
ここで、
A=[ - 2 1 0 ⋯ 0 1 1 - 2 1 0 ⋯ 0
∂∂tバツ⃗ = 1ΔのX2A x⃗
A = ⎡⎣⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢− 21011− 2⋱⋯001⋱⋱0⋯⋯0⋱⋱100⋯⋱− 21101− 2⎤⎦⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥。
もちろん、このマトリックスを実際に作成または保存する必要はありません。必要に応じて最初と最後のポイントを特別に処理するように注意しながら、有限差分をその場で計算する必要があります。
∂tu = ∂x xu + b (t 、x )
X ∈ [ - 1 、 1 )あなたは参照(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