El problema
Utilice el método Runge-Kutta de orden 4 para resolver la ecuación diferencial
$ \frac{\partial^2 y}{\partial t^2} = -g + \beta e^{-y/\alpha }*\left | \frac{\partial y}{\partial t} \right |^{2} $
Y corroborar que su error global es O (h^4)
El modelo matemático
Convierto el problema en un sistema de ecuaciones diferenciales de orden 1:
- $ \frac{\partial y}{\partial t} = v $
- $ \frac{\partial v}{\partial t} = -g + \beta e^{-y/\alpha }*\left | v \right |^{2} $
Por lo tanto, defino las variables de discretización u (para la posición) y v (para la velocidad) como:
- v = f(v, u, t)
- u = g(v, t)
Y utilizar los siguientes incrementos para el método Runge-Kutta de orden 4:
Para u
- k1v = h f(vn, un, tn)
- k2v = h f(vn + 0,5 k1v, un + 0,5 k1u, tn + 0,5 h)
- k3v = h f(vn + 0,5 k2v, un + 0,5 k2u, tn + 0,5 h)
- k4v = h f(vn + k3v, un + k3u, tn + h)
Para v
- k1u = h f(vn, tn)
- k2u = h f(vn + 0,5 k1v, tn + 0,5 h)
- k3u = h f(vn + 0,5 k2v, tn + 0,5 h)
- k4u = h f(vn + k3v, tn + h)
Y utilizarlos en la expresión RK4 para cada uno de ellos:
$ u_{n+1} = u_{n} + \frac{1}{6} (k_{1u} + 2 k_{2u} + 2 k_{3u} + k_{4u}) $
$ v_{n+1} = v_{n} + \frac{1}{6} (k_{1v} + 2 k_{2v} + 2 k_{3v} + k_{4v}) $
NOTA: Primero resuelvo para v . Para calcular el orden del error, resolveré 120 = h i veces con h = 0,1, h = 0,05 y utilizar el resultado dado para h = 0,001 como valor "real", ya que no conozco la función que resuelve la EDO. Entonces debo corroborar que el valor absoluto del "real" menos el resultado que obtuve de h = 0,1 debe ser 16 veces mayor que lo que obtengo al restar el valor que obtuve de h = 0,05 del valor "real".
El programa
Estoy usando C++ para resolver esto.
#include <iostream>
#include <math.h>
#include <cmath>
#include <sstream>
#include <fstream>
#include <vector>
#include <cstdlib>
long double rungeKutta(long double h)
{
long double alpha = 6629;
long double beta = 0.0047;
long double pos = 39068;
long double speed = 0;
for (int i = 1; h*i < 120; i++)
{
long double k1v = h * (-9.8 + beta * exp(-pos/alpha) * pow(speed, 2));
long double k1y = h * speed;
long double k2v = h * (-9.8 + beta * exp(-(pos + 0.5*k1y)/alpha) * pow(speed + 0.5*k1v, 2));
long double k2y = h * (speed + 0.5*k1v);
long double k3v = h * (-9.8 + beta * exp(-(pos + 0.5*k2y)/alpha) * pow(speed + 0.5*k2v, 2));
long double k3y = h * (speed + 0.5*k2v);
long double k4v = h * (-9.8 + beta * exp(-(pos + k3y)/alpha) * pow(speed + k3v, 2));
long double k4y = h * (speed + k3v);
speed = speed + (k1v + 2.0*(k2v + k3v) + k4v)/6;
pos = pos + (k1y + 2.0*(k2y + k3y) + k4y)/6;
}
return pos;
}
int _tmain(int argc, _TCHAR* argv[])
{
long double errorOne = rungeKutta(0.01);
long double errorTwo = rungeKutta(0.005);
long double real = rungeKutta(0.0001);
cout << fabs(real-errorOne) << endl << fabs(real - errorTwo) << endl;
system("pause");
return 0;
}
Los resultados
Me parece que el error sólo se reduce a la MITAD y no a la 1/16 parte del primer resultado.
¿Qué estoy haciendo mal? Me he quedado sin ideas.
Gracias.
0 votos
He reproducido ese problema. Sólo para asegurarme de que no has cometido ningún error de programación. O ambos hicimos lo mismo.
0 votos
Gracias. Aunque eso es para peor, porque todavía no sabemos cuál es el problema :(.
2 votos
Y encima de la sección "NOTA", se escribe $ 1/6(k1+k2+k3+k4)$ que debe ser $ 1/6(k1+2 k2+2 k3+k4)$ como está escrito en su código
0 votos
¿hay un contexto para esa ecuación?
0 votos
@macydanim: Sí, es otro error de redacción en el post. Aun así, en el código puedes ver que factoricé esa expresión como 1/6(k1 + 2,0*(k2 + k3) + k4). El contexto es un objeto en caída libre desde gran altura y sometido a las fuerzas de atracción gravitatoria (la parte de -9,8) y el rozamiento con el aire (la función de y ), todo ello sin tener en cuenta la masa del objeto.
0 votos
¿Por qué se incluyen math.h y cmath? En C++ no se deben utilizar variantes de .h, y cstdlib es un dummy. ¿Qué compilador acepta _tmain?