¿Cómo puedo reemplazar el método de Euler por el cuarto orden de Runge-Kutta para determinar el movimiento de caída libre en una magnitud gravitacional no constante (por ejemplo, caída libre desde 10 000 km sobre el suelo)?
Hasta ahora escribí integración simple por el método de Euler:
while()
{
v += getMagnitude(x) * dt;
x += v * dt;
time += dt;
}
x variable significa la posición actual, v significa velocidad, getMagnitude (x) devuelve la aceleración en la posición x.
Intenté implementar RK4:
while()
{
v += rk4(x, dt) * dt; // rk4() instead of getMagintude()
x += v * dt;
time += dt;
}
donde el cuerpo de la función rk4 () es:
inline double rk4(double tx, double tdt)
{
double k1 = getMagnitude(tx);
double k2 = getMagnitude(tx + 0.5 * tdt * k1);
double k3 = getMagnitude(tx + 0.5 * tdt * k2);
double k4 = getMagnitude(tx + tdt * k3);
return (k1 + 2*k2 + 2*k3 + k4)/6.0;
}
Pero algo está mal, porque me estoy integrando solo una vez usando RK4 (aceleración). La velocidad de integración con RK4 no tiene sentido porque es lo mismo que v * dt.
¿Podría decirme cómo resolver ecuaciones diferenciales de segundo orden utilizando la integración Runge-Kutta? ¿Debo implementar RK4 calculando los coeficientes k1, l1, k2, l2 ... l4? ¿Cómo puedo hacer eso?
fuente
Respuestas:
Parece haber bastante confusión acerca de cómo aplicar los métodos de varios pasos (por ejemplo, Runge-Kutta) a las EDO de segundo orden o superiores o los sistemas de EDO. El proceso es muy simple una vez que lo entiendes, pero quizás no sea obvio sin una buena explicación. El siguiente método es el que encuentro más simple.
k1
k4
X
RHS( t, X )
Desafortunadamente, C ++ no admite de manera nativa operaciones de vectores como esta, por lo que debe usar una biblioteca de vectores, usar bucles o escribir manualmente las partes separadas.En C ++ puedes usarstd::valarray
para lograr el mismo efecto. Aquí hay un ejemplo de trabajo simple con aceleración constante.fuente
typedef std::valarray<double> Vector
para tipos de uso común. 3) Use enconst int NDIM = 2
lugar de#define
por tipo de seguridad y corrección. 4) Desde C ++ 11 puede reemplazar el cuerpo de RHS simplemente conreturn {X[1], 1}
. 5) Es realmente poco común en C ++ (a diferencia de C) declarar primero las variables, luego inicializarlas, preferir declarar variables en el mismo lugar donde las inicializa (double t = 0.
, etc.)RHS()
calcula el lado derecho de la ecuación diferencial. El vector de estado X es (x, v), entonces dX / dt = (dx / dt, dv / dt) = (v, a). Para su problema (si a = G * M / x ^ 2) RHS debería regresar{ X[1], G*M/(X[0]*X[0]) }
.