Nel caso di un problema ai limiti: \( \bullet \) Per le condizioni ai bordi ti consiglio di scrivere su un foglio la prima e l'ultima riga, in modo da avere chiaro cosa dover "azzerare", o comunque cosa dover modificare.
Per la condizione a $x=1$ basterebbe azzerare la prima riga della matrice che discretizza la derivata prima e modificare la prima riga della matrice che discretizza la derivata seconda lasciando solo l'entrata (1,1) pari a $1$.
Cioè
- Codice:
A(1,1:2)=[1,0]; B(1,2)=0;
A(m,m-1:m)=[0,1]; B(m,m-1)=0;
A questo punto, definiamo il termine noto $b= -4 - \frac{x^3}{3}$, con la prima e ultima entrata rispettivamente
- Codice:
b(1)=- 17/(h^2);
b(m)= - 43/(3*h^2);
\( \bullet \) Definiamo la funzione da azzerare $F(u)= Au + \frac{1}{8} (\diag(u) \dot ( B \dot u ) + \vec{b})$
Evidentemente è un funzionale non lineare e dunque come hai visto bisogna usare Newton.
\( \bullet \) Lo parte più difficile per fare lo jacobiano è quella riguardante il termine $\diag(u) \cdot (B \cdot u)$.
Ci sono più modi: il più semplice consiste nello scrivere l'i-esima riga generale di questo prodotto:
$u_i \cdot \frac{u_{i+1} - u_{i-1}}{2h}$
Derivando rispetto alla i-1-esima: $-\frac{u_i}{2h}$
Derivando rispetto alle i-esima: $\frac{u_{i+1}-u_{i-1}}{2h}$
Derivando rispetto alla i+1-esima: $\frac{u_i}{2h}$
Quello che risulta è una matrice
tridiagonale, che è equivalente a quella scritta da te.
La matrice jacobiana è dunque $J=A + \frac{1}{8} \cdot (diag(B \cdot u) + diag(u) \cdot B)$
\( \bullet \) Il metodo di Newton, essendo iterativo, prevede un guess iniziale. Sotto
opportune ipotesi Newton converge quadraticamente. Un buon guess iniziale può essere una retta congiungente i due estremi:
- Codice:
u0=linspace(a,b,m)';
Una sua possibile implementazione, facendo riferimento al tuo codice, è questa:
- Codice:
u0 = %dato iniziale;
AbsTol=1e-9;
RelTol=1e-6;
delta=-JF(u0)\F(u0);
while (norm(delta,inf)> AbsTol + norm(res,inf)*RelTol)
u0=u0+delta;
delta=JF(u0)\F(u0);
end
Nel codice ho mostrato anche che l'ordine di convergenza è effettivamente $2$, mentre per risolvere il sistema non lineare ho utilizzato un criterio d'arresto misto con Newton inesatto (cioè usando sempre la stessa matrice jacobiana). Provando a cambiare il guess iniziale in quello da me suggerito, dovresti vedere che il metodo impiega meno iterazioni (passi da 28 iterate a 25).
Inoltre, usando il metodo di Newton (non inesatto quindi), hai che in 4 iterazioni hai raggiunto la soluzione.
- Codice:
clear all
close all
count=0;
mrange=2.^(4:10)+1;
for m=mrange
count=count+1;
x=linspace (1,3,m)'; % intervallo del problema differenziale
h=(2)/(m-1);%lunghezza dell'intervallo
A = toeplitz(sparse([1,1],[1,2],[-2,1]/(h^2),1,m));
B = toeplitz(sparse(1,2,-1/(2*h),1,m), sparse(1,2,1/(2*h),1,m));
b=zeros(m,1);
%C. AL BORDO
A(1,1:2)=[1/(h^2),0];
B(1,1:2)=[0,0];
A(m,m-1:m)=[0,1/(h^2)];
B(m,m-1:m)=[0,0];
b= -4*ones(m,1) - (1/4)*(x.^3);
b(1,1)=- 17/(h^2);
b(m,1)= - 43/(3*h^2);
F=@(u) A*u + (1/8)*(diag(u)*(B*u))+ b;
JF=@(u) A + 1/8*(diag(B*u) + diag(u)*B);
%PARAMETRI INIZIALI
% u0=ones(m,1);
u0=linspace(1,3,m)';
u=u0;
delta=-JF(u)\F(u);
i=0;
RelTol=1e-6;
AbsTol=1e-9;
while(norm(delta,inf)>RelTol*norm(delta,inf) + AbsTol)
i=i+1;
u=u+delta;
delta=-JF(u0) \ F(u); %newton inesatto, convergenza lineare
end
u=u+delta;
s=@(x) x.^2 + 16./x;
err(count)=norm(u- s(x),inf)
end
figure
plot(x,u,'*',x,x.^2 + 16./x,'r')
title('soluzioni')
legend('sol numerica','sol analitica')
xlabel('x')
ylabel('u(x)')
i %iterate
figure(2)
loglog(mrange,err,'sk',mrange,(err(end))*(mrange/mrange(end)).^-2,'r',mrange,mrange.^(-1),'b')
title('errore')
legend('errore','O(m^-2)','O(m^-1)')
xlabel('m')
ylabel('err')
grid on