Equazione differenziale con metodo di Newton

luca.milano3
Buongiorno a tutti, sto cercando di risolvere un'equazione differenziale non lineare discretizzando in N nodi e poi risolvendo il sistema risultante con il metodo di Newton. Il codice mi sembra che giri ma è abbastanza lento e vorrei capire se c'è qualche errore o se semplicemente questi sono i limiti del metodo di Newton.

Questa è l'equazione:
$ { ( (partial^2 T)/(partial x^2) + g/k=0 ),( T(0)=T_0 ),( T(L)=T_L ):} $

dove il termine $ k $ è pari a:
$ k=k0+a*T $

Vi riporto lo script principale:
L=1; %lunghezza
N=50; %numero nodi
dx=L/N; %intervallo spaziale

T0=0;  %temperatura in x=0
TL=0;  %temperatura in x=L

g=50;  %termine di generazione
k0=10; %primo termine della polinomiale per la conduttività termica: k=k0+aT
a=10;  %coefficiente della T
save indiretto

%METODO DI NEWTON
T=zeros(N,1);
x1=ones(N,1);
n=0;

while norm(T-x1)>1e-5
    n=n+1;
    x1=T;
    r=jac2(T)\sist2(T);
    T=T-r;
end
T;
n;


La function per il vettore delle equazioni è la seguente:
function F=sist2(T)
%devo creare il vettore colonna del sistema: F=0
load indiretto

F(1)=T(1)-T0; 
F(N)=T(L)-TL;

for j=2:N-1
    k(j)=k0+(10^-1)*T(j);
    F(j)=T(j+1)-2*T(j)+T(j-1)+g/k(j)*dx^2;
end

F=F';


Lo Jacobiano è invece questo:
function J=jac2(T)
load indiretto
J=zeros(N,N);

J(1,1)=1; J(N,N)=1;
for j=2:N-1
    k(j)=k0+10^-1*T(j);
    J(j,j-1)=1;
    J(j,j)=-2-a*g/(k0+a*T(j))^2;
    J(j,j+1)=1;    
end


Vedete qualche errore? Ci sono metodi migliori per risolvere sistemi non lineari?

Risposte
luca.milano3
Ma figurati, sei stato gentilissimo, prenditi pure il tempo che ti serve per fare i tuoi esami e più avanti se avrai voglia potrai ripassare per questa discussione. In ogni caso mi hai già aiutato tanto e per questo ti ringrazio!

Purtroppo il tuo ultimo commento ammetto di non averlo capito benissimo. In particolare, lo stesso problema ma svolto in modo lineare, quindi con $ k $ costante nota, riesco a farlo funzionare e forse per questo pensavo fosse relativamente semplice estenderlo al caso non lineare utilizzando il metodo di Newton.

Giusto per completezza ti riporto il codice del caso lineare, che magari guarderai più avanti quando avrai più tempo:

clear
clc
%CODICE CAMPO DI T CON ASSEGNATA TEMPERATURA E FLUSSO IN INGRESSO

L=10;
N=100; %numero elementi
dx=L/N;

%SPECIFICA LA TEMPERATURA ALL'INGRESSO E IL FLUSSO TERMICO
T0=100;
q0=-500;

%COEFFICIENTI DELL'EQUAZIONE: generazione di potenza e conduttività termica
g=250;
k=50; %conduttività termica

A=zeros(N,N);
b=zeros(N,1);

A(1,1)=1; %prima riga
A(2,2)=+1; %seconda riga

b=[T0 (T0-dx/k*q0-1/2*dx^2*g/k)]';
for j=3:N
A(j,j-2)=1;
A(j,j-1)=-2;
A(j,j)=1;

b(j,1)=-g/k*dx^2;
end

T=A\b;

x=linspace(0,L,N);
plot(x,T)


Lo avevo scritto prima che tu mi spiegassi come scrivere le matrici agilmente, quindi ci sono ancora i cicli for.

Buona fortuna per i tuoi esami!

feddy
Buona fortuna per i tuoi esami!

Grazie ! :)

Ad ogni modo ti ripeto che per risolvere ODE, che è quello che vuoi fare, devi ricondurre l'equazione diff. (che era al secondo ordine) in un sistema al prim'ordine e usare MatLab. Il fatto che plottasse qualcosa non vuol dire niente in realtà. Ad esempio, tu hai messo esplicitamente una condizione sul bordo a $x=L$. Quindi, faccio finta che sulle ascisse ci sia il tempo e ti scrivo 5 righe di come andrebbe fatto uno stupidissimo Eulero Esplicito per esempio col tuo problema
\( \begin{cases} (d^2 u)/dx^2 +g/k=0 \\ u(0)=u_0\\ \frac{du}{dx}(0)=-\frac{q_0}{(k(u_0))} \end{cases} \)


Ho scritto il problema al prim'ordine introducendo $u_{1}'=u_2$ e risolto un sistema differenziale con condizioni iniziali che ho scelto io, visto che tu precedentemente non le davi (ho solo assunto $u(0)=u_0=0$ poiché suppongo che la temperatura all'istante iniziale sia nulla, comunque non cambia niente, basta che sistemi $y_0$). Ancora, visto che il risultato comparirà sulla tua tesi, se vuoi garantirti un risultato migliore, senza preoccuparti della tanta teoria che ci sta dietro, puoi usare il comando ode di MatLab, che mi pare tu conosca già.

Ad ogni modo, i tuoi problemi sono più che altro sulla teoria, e continuare a scrivere pezzi di codice di problemi diversi rende questa discussione veramente "enorme" e si rischia di perdere di vista gli obiettivi. Ti ripeto che secondo me ti conviene darti una letta a del materiale sull'argomento, almeno saper distinguere una ODE da un problema ai limiti, altrimenti diventa impossibile andare avanti :roll:

clear all
close all

tf=5; #tempo finale
ts=1000; #time steps
k=tf/ts; #passo temporale

#costanti
T0=5; 
q0=0; 
g=0;  
k0=100; %primo termine della polinomiale per la conduttività termica: k=k0+aT
k1=20;  %coefficiente della T

f=@(y) [y(2);-g./(k0 + k1*y(1))];
df=@(y) [1,0;0,(g*k1)/((k0+k1*y(1)).^2)];

#Eulero esplicito
y0=[0;2]; #DATO INIZIALE: corrisponde a u(0) e u'(0)=-g/k.

y=NaN(2,ts+1);
y(:,1)=y0;
for n=1:ts
	y(:,n+1)=y(:,n)+k*f(y(:,n));
end

t=linspace(0,tf,ts+1);
plot(t,y(1,:))

luca.milano3
Ah quindi mi stai dicendo che anche la soluzione che ho trovato nel caso lineare fosse sbagliata? Eh si che sembrava tanto carina :)

feddy
Non so cosa debba venire, ma se non hai condizioni a un bordo non te le puoi certo inventare.

luca.milano3
Hai ragione, probabilmente ho bisogno di capire prima un po' meglio la teoria e cercherò di leggere bene il testo che mi hai passato. A proposito, se hai altri testi, in particolare con esempi di codici matlab, sono ben accetti.

Non so cosa debba venire, ma se non hai condizioni a un bordo non te le puoi certo inventare


Non capisco proprio a cosa ti riferisci quando dici che io mi sia inventato una condizione a un bordo: io ho impostato la funzione al nodo $1$ e la funzione al nodo $2$ (nota la derivata prima in $0$) e la soluzione trovata nel caso lineare viene corretta (l'ho confrontata con la soluzione analitica e con altri risolutori, quindi sono sicuro che sia corretta).

feddy
Un testo recente è "Modellistica numerica per problemi differenziali - Quarteroni".
Per quanto riguarda l'ultima cosa: quello che intendo è che hai risolto un problema ai valori iniziali con un metodo per problemi ai limiti, visto che non conoscevi la condizione al bordo destro. Questo è sbagliato, che venga "giusta" poi è un altro conto. Oltretutto, quello che hai fatto te è stato mettere la condizione di Dirichlet in $0$ e nel nodo successivo quella di Neumann... ma converrai che così non hai risolto veramente il problema assegnato, visto che non hai modificato lo stesso nodo. Insomma, a scanso di equivoci: per ODE si usano metodi per ODE, per BVP differenze finite

Rispondi
Per rispondere a questa discussione devi prima effettuare il login.