Anda di halaman 1dari 7

Ecuaciones diferenciales ordinarias

________________________________________________________________________
6.3. Método de Runge-Kutta

Al aplicar el método de Euler, según se mostró en la sección 6.1, utilizamos el valor de la


derivada,

dy (6.3.1)
= f ( x, y )
dx

convirtiendo la ecuación anterior en una ecuación de diferencias finitas, se obtiene:

yi +1 − yi (6.3.2)
= f ( xi , y i )
xi +1 − xi

En seguida, se debe seleccionar un incremento h, también llamado paso de integración,


que nos permita obtener la precisión que deseamos o podemos aceptar, donde

h = xi +1 − xi (6.3.3)

De esa manera, utilizando la información que nos proporciona el valor de la derivada f(xi,
yi) en el punto i, podemos estimar el valor de la función en el punto i+1,

yi +1 = yi + ( xi +1 − xi ) f ( xi , yi ) , (6.3.4)

En la sección 6.2 mostramos que podemos utilizar información acerca de los valores
conocidos o estimados de las variables, no sólo en el punto i, sino también en el punto
i+1, cuando utilizamos la ecuación

1
[ f ( xi , yi ) + f ( xi +1 , yi + hf ( xi , yi )] , (6.2.3)
2

para así recalcular, tratando de obtener una estimación más precisa para el valor de la
variable dependiente y en el punto i+1,

h
yi +1 = yi + [ f ( xi , yi ) + f ( xi +1 , yi + hf ( xi , yi )] (6.2.4)
2

Existen otros métodos para la integración numérica de ecuaciones diferenciales, en los


cuales también hacemos uso no sólo de la información disponible en el punto i, sino
también de la información que podamos estimar acerca de los valores de las variables en
el punto i+1, y además en otros puntos intermedios en el intervalo (xi, xi+1). Ejemplos de
esos métodos son el método del punto medio y el método de Heun (ref. 1), y el método de
Runge-Kutta, que serán mostrados a continuación.

Unidad 6 Ricardo Ávila Pág. 6-10


Ecuaciones diferenciales ordinarias
________________________________________________________________________
Hay varios métodos de Runge-Kutta, dependiendo del orden de magnitud del error local
de truncamiento, el cual depende de que se utilice la información estimada acerca de los
valores de la función en dos, tres, o más puntos. Así resultan los métodos de Runge-Kutta
de orden dos, tres y cuatro.

6.3.1. Método de Runge-Kutta de orden cuatro

El más utilizado de los métodos de Runge-Kutta es el de orden cuatro, el cual se aplica


convirtiendo la ecuación diferencial inicial en una ecuación de diferencias finitas, y
utilizando los valores estimados en cuatro puntos en cada intervalo (xi, xi+1).

Este método utiliza entonces cuatro parámetros, los cuales son calculados de la siguiente
manera:

k1 = hf ( xi , y i ) (6.3.1.1)

h 1 (6.3.1.2)
k 2 = hf ( xi + , yi + k1 )
2 2

h 1 (6.3.1.3)
k 3 = hf ( xi + , yi + k 2 )
2 2

k 3 = hf ( xi +1 , yi + k 3 ) (6.3.1.4)

Como se puede ver en las fórmulas anteriores, los cuatro parámetros son distintas
estimaciones para el valor de las diferencias finitas para la variable dependiente y, en
diferentes puntos, es decir, para diferentes valores de la variable independiente x.

Los cuatro valores anteriores se combinan, asignándoles distintas ponderaciones a cada


uno de ellos, en la siguiente fórmula

(6.3.1.5)
yi +1 = yi +
1
(k1 + 2k 2 + 2k 3 + k 4 )
6

la cual, utilizada junto con un valor inicial y0 = y ( xo ) nos permitirá resolver el problema.

El error local de truncamiento que resulta de este método es del orden de la cuarta
potencia del paso de integración h, es decir el error es de O(h4).

Se ha presentado el método de Runge-Kutta de orden cuatro de una manera muy sencilla,


apelando a la intuición del lector, y sin demostración. La razón de esto es que el álgebra
utilizada en la derivación completa del método es laboriosa.

Unidad 6 Ricardo Ávila Pág. 6-11


Ecuaciones diferenciales ordinarias
________________________________________________________________________
6.3.2. Ejercicio: ecuación del péndulo usando Runge-Kutta

Para resolver la ecuación diferencial para el problema del movimiento de un péndulo,

d 2θ g (6.3.2.1)
− senθ = 0
dt 2 L

necesitamos conocer las dos condiciones iniciales

θ (0) = α (6.3.2.2)

θ ′(0) = β (6.3.2.3)

Para simplificar la notación, haremos el cambio de variable a y, haciendo y = θ. Nuestra


ecuación original se convierte en

d2y g (6.3.2.4)
= sen( y )
dt 2 L

Convertiremos esta ecuación del péndulo, de segundo orden, a un sistema equivalente


con dos ecuaciones simultáneas de primer orden. Para esto definimos el arreglo que
contiene a los elementos y(0) y y(1),

y ( 0) = y (6.3.2.5)
y (1) = y ′

Si obtenemos la derivada del arreglo anterior, tendremos

dy (6.3.2.6)
y ′(0) = y ′ = = y (1)
dx
d2y g
y (1) = y = 2 = sen( y )
′ ′′
dx L

Al codificar nuestro programa en C++ para resolver el problema del péndulo usando el
método de Runge-Kutta de cuarto orden, utilizando los siguientes valores

Longitud del péndulo = 1 m


Aceleración de la gravedad = -9.806 m/s2

Unidad 6 Ricardo Ávila Pág. 6-12


Ecuaciones diferenciales ordinarias
________________________________________________________________________
Las ecuaciones del sistema (6.3.2.6) se convierten en los siguientes dos renglones de
código

// El vector derivada[N] contiene las ecuaciones diferenciales a


resolver
// El vector y[N] contiene los valores de las variables dependientes

derivada[0] = y[1];
derivada[1] = -9.806 * sin (y[0]);

A continuación se presenta el código completo para resolver el problema del péndulo


usando el método de Runge-Kutta de orden cuatro.

/*
runge-k.cpp
Programa para simular movimiento de un péndulo
Integración por Método de Runge-Kutta
Ricardo E. Ávila, 2 Noviembre 2001
Longitud del péndulo = 1 m
Aceleración de la gravedad = -9.806 m/s2
*/

#include <stdlib.h>
#include <math.h>
#include <fstream.h>
#include <iomanip.h>
#include <stdio.h>

const int N = 2;
// Este programa puede resolver hasta un maximo de N = 2
// ecuaciones diferenciales ordinarias simultaneas
// de primer orden. Cambiar el valor de N segun sea necesario.

void funcion(double, double[], double[]); // Prototipo


void rungekutta(double, double, double[], double); // Prototipo

void funcion(double t, double derivada[], double y[])


{
// El vector derivada[N] contiene las ecuaciones diferenciales a
resolver
// El vector y[N] contiene los valores de las variables dependientes

derivada[0] = y[1];
derivada[1] = -9.806 * sin (y[0]);

} // fin de funcion: funcion

Unidad 6 Ricardo Ávila Pág. 6-13


Ecuaciones diferenciales ordinarias
________________________________________________________________________
void rungekutta(double t, double dt, double y[], double half_dt)
{
int indice; // para uso en ciclos for

// Variables locales de funcion rungekutta


double f[N], f1[N], f2[N], f3[N], f4[N], yy[N];

// Paso 1
funcion(t, f, y);
for (indice = 0; indice < N; indice++)
f1[indice] = dt * f[indice];

// Paso 2
double tt = t + half_dt;
for (indice = 0; indice < N; indice++)
yy[indice] = y[indice] + 0.5 * f1[indice];

funcion(tt, f, yy);

// Paso 3
for (indice = 0; indice < N; indice++)
{
f2[indice] = dt * f[indice];
yy[indice] = y[indice] + 0.5 * f2[indice];
}
funcion(tt, f, yy);

// Paso 4
double next_time_step = t + dt;
for (indice = 0; indice < N; indice++)
{
f3[indice] = dt * f[indice];
yy[indice] = y[indice] + f3[indice];
}
funcion(next_time_step, f, yy);

for (indice = 0; indice < N; indice++)


{
f4[indice] = dt * f[indice];
y[indice] = y[indice] + (f1[indice] + 2*f2[indice]
+ 2*f3[indice] +
f4[indice])/6;
}

} // fin de funcion: rungekutta

Unidad 6 Ricardo Ávila Pág. 6-14


Ecuaciones diferenciales ordinarias
________________________________________________________________________
void main ()
{
ofstream position ("pos_RK.m");
ofstream speed ("speed_RK.m");
cout.precision(5);
position.precision(6);
speed.precision(6);

double t = 0; // Tiempo inicial 0 segundos


double dt = 0.001; // Paso de integracion: incremento de tiempo

double y[N]; // El arreglo y[] contiene los valores


// de las variables dependientes

// Condiciones iniciales:
y[0] = 0.392699081; // Posicion inicial del pendulo, en radianes

y[1] = 0; // Velocidad inicial (dy/dt); condicion inicial

// Definir un apuntador para guardar datos en un archivo


FILE *archivo;

if ((archivo = fopen("pend_RK.txt", "w")) == NULL)


printf("\n No se pudo abrir el archivo pend_RK.txt \n");

cout << " Tiempo \tPosicion \tVelocidad" << endl


<< " ----------------------------------------\n";

// Escribir encabezado en archivo pend_RK.txt


fprintf(archivo, " Tiempo \tPosicion \tVelocidad\n");
fprintf(archivo, " ----------------------------------------\n");

// Simulación durante 4 segundos

int i = 10;
// i: contador para guardar resultados cada 10 ciclos de while

// variables para uso en algoritmo Runge-Kutta


double half_dt = 0.5 * dt;

while (t <= 4.000001)


{

if (i == 10)
{
position << y[0] << endl;
speed << y[1] << endl;

printf(" %.4f \t%f\t%f\n", t, y[0], y[1]);


fprintf(archivo, " %.4f \t%f\t%f\n", t, y[0], y[1]);
//

i = 1;
}

Unidad 6 Ricardo Ávila Pág. 6-15


Ecuaciones diferenciales ordinarias
________________________________________________________________________
else
{
++i;
}

rungekutta(t, dt, y, half_dt);


t = t + dt; // Incrementar variable independiente

} // Termina while

// Cerrar el archivo pend_RK.txt


fclose(archivo);

cout << "\n Presione cualquier tecla para continuar...\n";


getchar();
}
// FIN DE PROGRAMA

Unidad 6 Ricardo Ávila Pág. 6-16

Anda mungkin juga menyukai