Soluzione approssimata, equazione differenziale runge-kutta

_johnnyfreak_1
Ero indeciso se creare il post su analisi matematica o qui, mi scuso se ho sbagliato.
Ho un problema nella comprensione dell'algoritmo di runge-kutta.
Devo approssimare la soluzione di questo sistema di equazioni differenziali attraverso runge-kutta:
[tex]\left\{
\begin{array}{lr}
\frac{d\theta}{dt} = \omega = f_1(t, \omega) \\
\frac{d\omega}{dt} = A * sin(\theta) + B*v_a - B * \omega = f_2(t, \omega, \theta)
\end{array}}[/tex]

L'algoritmo che sto studiando è RK4:

Per risolvere [tex]\frac{dy}{dt} = f(t, x)[/tex]
[tex]h = \frac{x_{finale} - x_{iniziale}}{N}[/tex] è il passo di integrazione
[tex]k_1 = f(x_n, y_n)[/tex]
[tex]k_2 = f(x_n + \frac{h}{2}, y_n +\frac{k_1*h}{2})[/tex]
[tex]k_3 = f(x_n + \frac{h}{2}, y_n + \frac{k_2*h}{2})[/tex]
[tex]k_4 = f(x_n + h, y_n + k_3*h)[/tex]
[tex]y_{n+1} = y_n + \frac{k_1}{6} + \frac{k_2}{3} + \frac{k_3}{3} + \frac{k_4}{6} + O(h^5)[/tex]

Ma non riesco ad applicarlo perchè $f2$ ha più variabili.

Potreste darmi una mano?
Grazie

Risposte
Ska1
Stai lavorando con un sistema di equazioni differenziali del primo ordine, dunque nella forma

[tex]$\begin{cases} \underline y'(t) = \underline F(t, \underline y(t)) \\ \underline y(t_0) = \underline y_0\end{cases}$[/tex]

Nel tuo caso [tex]$\underline y(t) = \begin{bmatrix}\theta(t) \\ \omega(t)\end{bmatrix}$[/tex] e [tex]$F(t,\underline y(t)) = \begin{bmatrix}\omega(t) \\ A*\sin(\theta(t)) + B*v_a - B*\omega(t)\end{bmatrix}$[/tex]

Dunque rispetto al problema generale avrai

[tex]$\underline k_1=\underline F(x_n, \underline y_n)$[/tex]
[tex]$\underline k_2=\underline F(x_n + \frac{h}{2}, \underline y_n + \underline k_1 \frac{h}{2})$[/tex]
[tex]$\underline k_3=\underline F(x_n + \frac{h}{2}, \underline y_n + \underline k_2 \frac{h}{2})$[/tex]
[tex]$\underline k_4=\underline F(x_n + h, \underline y_n + \underline k_3 h)$[/tex]
[tex]$y_{n+1} = y_n + \frac{h}{6}(\underline k_1 + 2 \underline k_2 + 2 \underline k_3 + \underline k_4 ) + O(h^5)$[/tex]

_johnnyfreak_1
Grazie per la risposta.
Se ho capito bene devo iterare il processo per ogni funzione (quindi calcolare 2 $k_i$ e 2 $y_{i+1}$ ad ogni passo.

Ho provato a scrivere il codice in matlab:

Questa è la funzione che applica l'algoritmo:


Queste due sono le funzioni del sistema:


Che chiamo in questo modo (il penultimo parametro non serve e devo eliminarlo):
myRunge('mffunc', 'g', 0, 8, 500, 0, 0)


Ottengo un andamento oscillante a cui non so dare interpretazione ma non capisco se sbaglio l'intervallo, se sbaglio l'algoritmo o altro :(
Provo a ripensare a tutto quello che ho scritto.
Se ho scritto qualcosa di sbagliato, di cui non mi sono accorto, potreste avvertirmi?

Ska1
No no, puoi fare tutto manipolando direttamente i vettori

function [t, u] = rk4(odefun, tspan, y0, Nh, varargin)

Nh=ceil(Nh);

t=linspace(tspan(1),tspan(2), Nh + 1);
u = zeros(length(y0), length(t));
u(:,1) = y0;
h=t(2)-t(1);
for i=2:length(t)
    K1 = odefun(t(i-1), u(:,i-1));
    K2 = odefun(t(i-1) + h/2, u(:,i-1) + h/2*K1);
    K3 = odefun(t(i-1) + h/2, u(:,i-1) + h/2*K2);
    K4 = odefun(t(i), u(:,i-1) + h*K3);
    u(:,i) = u(:,i-1) + h/6*(K1 + 2*K2 + 2*K3 + K4);
end;
u=u';



Questa function realizza il metodo RK4, il formato è quello più simile alle function presenti in matlab:
- odefun rappresenta la funzione vettoriale nelle variabili [tex]$t$[/tex] e [tex]$\underline y$[/tex]
- tspan rappresenta gli estremi della variabile indipendente
- y0 è il vettore che rappresenta le condizioni iniziali
- Nh è il numero di intervallini in cui si suddivide l'intervallo considerato della variaible temporale

Si costruisce una matrice $u$ di dimensione $n \times T$, dove $n$ è il numero di componenti della variabile $y$ e $T$ è il numero degli istanti temporali considerati.

Si inizializza la prima colonna della matrice con $y_0$ condizione inziale, a questo punto si itera sui rimanenti istanti temporali, e si applica il metodo RK considerando i vettori nei vari istanti temporali.

Alla fine si traspone $u$ per mantenere la convenzione che il risultato contiene nelle colonne le soluzioni di ciascuna componente.

La tua funzione $F$ da passare dovrebbe essere ad esempio

F=@(t,y)[y(2); A*sin(y(1))+B*v_a-B*y(2)];

_johnnyfreak_1
Grazie, provo ad utilizzare il codice che hai postato applicandola al mio caso.
La funzione F di cui parli è quella che passerò come odefun giusto?

Ska1
Ho provato a risolvere l'equazione come ti ho suggerito, e il risultato è un andamento oscillate.



http://skadotnet.altervista.org/test.m
http://skadotnet.altervista.org/rk4.m

_johnnyfreak_1
si anche io ho avuto lo stesso risultato.
Però se aumenti il lasso di tempo la funzione si assesta (dovrebbe essere un punto di equilibrio)

Proverò con altri valori in base allo studio del sistema che ho fatto.
Grazie mille. Sono commosso, sei il primo che mi risponde.

oniudra
ciao a tutti...scusate se mi intrometto...

io devo effettuare l'integrazione con runge-kutta

dO/dt = w(t) => F(t,O)
O(to)=O0

mi sono scritto l'algoritmo di integrazione (un poo vedendo qui u po altrove)

ora...COME GLIELA PASSO LA FUNZIONE ??

purtroppo nn sono molto bravo in matlab

questo è il codice di runge-kutta


function [t,y] = RK(odefun,tspan,y0,h)
%RK Metodo di Runge?Kutta IV per ODE
% SINTASSI
% [t,y] = RK(odefun,tspan,y0,h)
% INPUT
% odefun : La funzione f(t,y) del problema differenzale
% y'= f(t,y)
% tspan : Valore iniziale tspan(1) e finale tspan(2)
% della procedura di integrazione
% y0 : Condizione initiale var. dipendente
% h : passo temporale
% OUTPUT
% t : Vettore dei valori delle variabili indipendenti
% y : Vettore dei valori delle variabili dipendenti
% pre?allocazione memoria var. indipendenti
t = (tspan(1):h:tspan(2))';
% numero totale di elementi
n = length(t);
% pre?allocazione memoria var. dipendenti
y = zeros(n,1);
% valore iniziale
y(1) = y0;
% ciclo principale
for j=1:n-1
k1 = feval(odefun,t(j),y(j));
k2 = feval(odefun,t(j)+h/2,y(j)+k1*(h/2));
k3 = feval(odefun,t(j)+h/2,y(j)+k2*(h/2));
k4 = feval(odefun,t(j)+h,y(j)+h*k3);
y(j+1) = y(j)+(h/6)*(k1+2*k2+2*k3+k4);

end


vi prego aiuto!!!

oniudra
la mia mail è ardu.cicchetti@gmail.com

vi prego datemi una mano!!
grazie a tutti!!

Ska1
Devi definire una function che rappresenta la funzione della tua equazione differenziale, quindi nel tuo caso $f(t,y(t)) = w(t)$ e quindi in matlab dovrai definire qualcosa del tipo

$f=\text{@}(t,y) w(t)$, dove $w$ è la funzione che hai nel problema.

Poi se devi creare il vettore $tspan$ che contiene come primo elemento il primo istante temporale $t_0$ e l'ultimo, quindi se vuoi la soluzione su $[t_0 t_n]$, $tspan=[t0 tn]$ dove $t0,tn$ sono dei valori scalari che indicano gli istanti temporali suddetti.

A questo punto puoi usare la tua function RK.

oniudra
grazie per la risp...ti dico pero il problema....io w(t) non la conosco analiticamente...so so i valori che assume in determinati istanti di tempo...come facciio??:(((

Ska1
puoi provare ad interpolare i dati che hai e usare l'interpolatore come $w(t)$ nell'equazione differenziale, tipo usare l'interpolazione spline che garantisce che la funzione interpolante sia di classe $C^2$.

oniudra
e se invece gli passassi i i valori negli istanti di tempo che ho io?

Ska1
Il metodo RK come vedi valuta la $f(t,y)$ non solo negli istanti $t_k=t_0 + k\cdot h$, ma anche a valori intermedi, dunque dovresti avere tutti questi punti, non è semplice la cosa.

oniudra
quindi mi consigli di fare l'interpolazione e usare la funzione che ottengo. giusto?
grazie mille x il consiglio

Ska1
Considera che comunque si sta introducendo un errore aggiunto causato dall'interpolazione dei dati, però non credo si possa fare molto altro, anche perchè se l'obiettivo è trovare una soluzione al problema di cauchy, ecco considera che la soluzione che calcoli ha un qualche senso nell'intervalo in cui sono contenuti i dati, fuori da quell'intervallo si perde completamente di significato.

Se i dati che hai sono abbastanza fitti e quasi equidistanti potresti anche provare a costruire una sorta di eulero esplicito sugli intervalli data dai dati che possiedi, alla fine la tua equazione differenziale si riduce al calcolo di una primitiva di $w(t)$.

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