Como posso substituir o método de Euler pela 4ª ordem de Runge-Kutta para determinar o movimento de queda livre em magnitude gravimétrica não constante (por exemplo, queda livre de 10.000 km acima do solo)?
Até agora escrevi uma integração simples pelo método Euler:
while()
{
v += getMagnitude(x) * dt;
x += v * dt;
time += dt;
}
variável x significa posição atual, v significa velocidade, getMagnitude (x) retorna a aceleração na posição x.
Eu tentei implementar o RK4:
while()
{
v += rk4(x, dt) * dt; // rk4() instead of getMagintude()
x += v * dt;
time += dt;
}
onde o corpo da função rk4 () é:
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;
}
Mas algo está errado, porque estou integrando apenas uma vez usando o RK4 (aceleração). A integração da velocidade usando o RK4 não faz sentido porque é o mesmo que v * dt.
Você poderia me dizer como resolver equações diferenciais de segunda ordem usando a integração Runge-Kutta? Devo implementar o RK4 calculando os coeficientes k1, l1, k2, l2 ... l4? Como eu posso fazer isso?
fonte
Respostas:
Parece haver muita confusão sobre como aplicar métodos de várias etapas (por exemplo, Runge-Kutta) a ODEs de segunda ou mais alta ordem ou sistemas de ODEs. O processo é muito simples quando você o entende, mas talvez não seja óbvio sem uma boa explicação. O método a seguir é o que eu acho mais simples.
k1
k4
X
RHS( t, X )
Infelizmente, o C ++ não oferece suporte nativo a operações vetoriais como essa; portanto, você precisa usar uma biblioteca de vetores, usar loops ou gravar manualmente as partes separadas.Em C ++, você pode usarstd::valarray
para obter o mesmo efeito. Aqui está um exemplo simples de trabalho com aceleração constante.fonte
typedef std::valarray<double> Vector
para os tipos mais usados. 3) Use emconst int NDIM = 2
vez de#define
para o tipo de segurança e correção. 4) Desde o C ++ 11, você pode substituir o corpo do RHS simplesmente porreturn {X[1], 1}
. 5) É realmente incomum em C ++ (ao contrário C) para variáveis primeiramente declarar, em seguida, mais tarde inicializar eles, preferem declarar variáveis no mesmo lugar onde você inicializa-la (double t = 0.
, etc.)RHS()
calcula o lado direito da equação diferencial. O vetor de estado X é (x, v), portanto dX / dt = (dx / dt, dv / dt) = (v, a). Para o seu problema (se a = G * M / x ^ 2), o RHS deve retornar{ X[1], G*M/(X[0]*X[0]) }
.