Il modo migliore per farlo è (come hai detto) semplicemente usare la definizione di condizioni al contorno periodiche e impostare le equazioni correttamente dall'inizio usando il fatto che . In effetti, ancora più fortemente, le condizioni al contorno periodiche identificano x = 0 con x = 1 . Per questo motivo, dovresti avere solo uno di questi punti nel dominio della tua soluzione. Un intervallo aperto non ha senso quando si utilizzano condizioni al contorno periodiche poiché non esiste alcun limite .u ( 0 ) = u ( 1 )x = 0x = 1
Questo fatto significa che non dovresti posizionare un punto su poiché è uguale a x = 0 . Discretizzando con N + 1 punti, si usa quindi il fatto che, per definizione, il punto a sinistra di x 0 è x N e il punto a destra di x N è x 0 .x = 1x = 0N+ 1X0 XNXN X0
Il PDE può quindi essere discretizzato nello spazio come
∂∂t⎡⎣⎢⎢⎢⎢X0X1⋮XN⎤⎦⎥⎥⎥⎥= 1Δ x2⎡⎣⎢⎢⎢⎢XN- 2 x0+ x1X0- 2 x1+ x2⋮XN- 1- 2 xN+ x0⎤⎦⎥⎥⎥⎥
Questo può essere scritto in forma di matrice come
dove
A=[ - 2 1 0 ⋯ 0 1 1 - 2 1 0 ⋯ 0
∂∂tX⃗ = 1Δ x2A x⃗
A = ⎡⎣⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢- 21011- 2⋱⋯001⋱⋱0⋯⋯0⋱⋱100⋯⋱- 21101- 2⎤⎦⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥.
Ovviamente non è necessario creare o archiviare questa matrice. Le differenze finite dovrebbero essere calcolate al volo, avendo cura di gestire il primo e l'ultimo punto specialmente se necessario.
Come semplice esempio, il seguente script MATLAB risolve
con condizioni al contorno periodiche sul dominio x ∈ [ - 1 , 1 ) . Viene utilizzata la soluzione prodotta u Ref ( t , x ) = exp ( - t ) cos ( 5 π x ) , che significa b ( t ,
∂tu = ∂x xu + b ( t , x )
x ∈ [ - 1 , 1 )uarbitro( t , x ) = exp( - t ) cos( 5 πx ) . Ho usato la discretizzazione temporale di Euler per semplicità e ho calcolato la soluzione sia con che senza formare la matrice. I risultati sono mostrati sotto.
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