Simulando el sistema solar con la ley de Newton

Hice una simulación en C++ con la ley de Newton y la probé comparando las posiciones de los planetas con la posición de la calculadora del sistema solar Don Cross (que convertí de JavaScript a C++)
http://cosinekitty.com/solar_system.html

Lo que hago es cada paso de tiempo (generalmente 1 segundo, pero el paso de 0,2 segundos es muy similar al paso de 10 segundos):

  1. Calcular aceleración ( = newton se forza × tiempo delta)
  2. Velocidad de actualización y posiciones
  3. Compare las posiciones con los resultados de los algoritmos de la calculadora solar Don Cross.
    Pero después de 10 días de simulación, obtengo esta desviación de distancia (a la calculadora de Don Cross):

METRO mi r C tu r y   4498.7   k metro

V mi norte tu s   X   1939.8   k metro

mi a r t h   X   10614.6   k metro

METRO o o norte   X   7800.2   k metro

METRO a r s   X   445.2   k metro

C mi r mi s   X   129.5   k metro

PAG a yo yo a s   X   432.4   k metro

j tu norte o   X   151.4   k metro

V mi s t a   X   157.6   k metro

I d a   X   73.6   k metro

GRAMO a s pag r a   455.3   k metro

9 PAG / T 1   241.5   k metro

19 PAG / B   402.7   k metro

67 PAG / C GRAMO   533.2   k metro

81 PAG / W 2   110.7   k metro

j tu pag i t mi r   172.3   k metro

S a t tu r norte   261.2   k metro

tu r a norte tu s   71.4   k metro

norte mi pag t tu norte mi   31.3   k metro

PAG yo tu t o   X     45.7   k metro

Como puede ver, algunos planetas tienen pequeñas desviaciones y otros más grandes, por lo que mi pregunta es: ¿Puede ser exacto el de Newton? o la calculadora del sistema solar Don Cross no lo es? ¿O hay materia negra en esa región? ¿O qué más?

void CGravitator::CalcAceleration(double timeseconds){
unsigned int i,j,iend;
if (sunStatic)iend=m_np-1;
else iend=m_np;
for (i = 0; i < iend; i++) {
        m_planetas[i].aceleration.set(0,0,0);
        CVector3 totalGravitationalForce;                                       
        // Loop through all bodies in the universe to calculate their gravitational pull on the object (TODO: Ignore very far away objects for better performance)


     for (j = 0; j < m_np; j++) {
            if (i == j) continue; // No need to calculate the gravitational pull of a body on itself as it will always be 0.                                
            double distancia =CVector3::Distancia(m_planetas[i].pos,m_planetas[j].pos);
            double force = KGNEWTON * m_planetas[i].masa * m_planetas[j].masa / pow(distancia, 2);
            CVector3 forceDirection = CVector3::Normalize(m_planetas[j].pos - m_planetas[i].pos);
            
            totalGravitationalForce += forceDirection * force;
        }
            CVector3 incspeed = totalGravitationalForce / m_planetas[i].masa ;          
        m_planetas[i].aceleration += incspeed * timeseconds;
        
    
}
¿Estás calculando todas las fuerzas entre los cuerpos, o solo la fuerza entre cada cuerpo y el Sol?
Por cierto, es bastante fácil cambiar su código de la integración de Euler a un integrador simpléctico como Verlet o Leapfrog, y podrá usar un paso de tiempo mucho más grande.
"¿Puede ser exacta la de Newton? ¿O la calculadora del sistema solar de Don Cross no lo es?" Al escribir un nuevo código de simulación, siempre es bueno compararlo con algo mejor establecido. Pero cuando los resultados difieren, la suposición predeterminada debe ser que la falla está en su código.
Si está transfiriendo código que usa el mismo método, es una buena idea verificar que las mismas entradas (posiciones de planetas, intervalo de tiempo, etc.) produzcan el mismo resultado, como sugiere jkej. Eso es más un ejercicio de codificación. Aprender acerca de los problemas con ciertos métodos numéricos es más matemático, y por qué ciertos métodos son mejores para ciertos sistemas es más físico.
Hola, sumo todas las fuerzas entre todos los cuerpos. El sol comienza en (0,0,0) y puede moverse o no (casilla de verificación), pero si el sol se mueve o no dio resultados muy similares. no hay error de código.
Y después del código de aceleración, sume accel to speed y agregue speed *deltatime to position para cada planeta. no se es que si ese es el metodo de eluler
@LuisALberto Sí. Calcular la velocidad y la aceleración instantáneas, luego usarlas junto con Δ t para actualizar la posición y la velocidad en un solo paso de la manera más fácil y razonable es el método de Euler directo. Algunos métodos generales más sofisticados usan las nuevas posiciones y velocidades para hacer correcciones antes de pasar al siguiente paso de tiempo. Eso te lleva a la tierra de Runge-Kutta.
Esta no es una revisión de código , por lo que no convertiré esto en una respuesta, sino en algunos consejos para la estabilidad numérica y el rendimiento. #1 Primero estás multiplicando y luego dividiendo por m_planetas[i].masa. Cancele esos. (Y cambie "fuerza" en los nombres de sus variables a "aceleración".) #2 Primero (presumiblemente) está sacando una raíz cuadrada adentro CVector3::Distanciay luego elevando al cuadrado la distancia. Cancele esos también. Y #3 sí, evita la integración de Euler. Y #4, incluya su código de actualización de posición y velocidad real en su pregunta; es posible que tenga errores o inexactitudes numéricas que afecten sus resultados.
@LuisALberto, ¿está usando doble precisión (o mayor precisión) para sus cálculos de coma flotante?
La integración numérica, especialmente de los movimientos planetarios, es difícil, realmente difícil. Algunos métodos apenas funcionan, algunos son completamente inestables y algunos necesitan un buen ajuste para obtener resultados precisos. El problema no es Newton: es la dificultad de la integración numérica.
Una forma de verificar su programa es calcular el momento total de todos los objetos en su sistema. Esto no debería cambiar, por lo que cualquier variación representa algún tipo de error. Siempre tendrás un poco, pero debe ser muy pequeño.
Sí, la integración de Euler es el algoritmo "obvio": Δ v = a Δ t , Δ X = v Δ t . En lugar de usar la masa, es más preciso usar el parámetro gravitacional estándar ; Horizons usa valores que son ligeramente diferentes de los de Wikipedia.
¿Qué estás usando para las posiciones y velocidades iniciales de tus planetas? ¿Está utilizando el programa Don Cross para eso, o Horizons? Por cierto, la distancia media entre el centro del Sol y el baricentro del Sistema Solar es de ~830.000 km, con un máximo de alrededor de 1,5 millones de km. Tengo un gráfico (producido con Horizons) en esta respuesta .
Hay muchas cosas que están mal en el código publicado. El más grande, con diferencia, es que la técnica no utiliza la velocidad. a Δ t (aceleración por paso de tiempo) es el cambio de velocidad. No es la velocidad del planeta. Debe integrar la posición y la velocidad, lo que significa que necesita una posición inicial y una velocidad inicial.
@DavidHammen: Ese es un muy buen punto. No sabemos qué hace el código de OP con m_planetas[i].aceleration, ya que no han publicado el resto, pero el valor que almacenan en ese vector no es una aceleración. ( incspeed es una aceleración, al menos suponiendo que totalGravitationalForcesea una fuerza, pero luego se multiplica por un intervalo de tiempo).
¿ Sería la ciencia computacional un mejor hogar para esta pregunta?
El código que estoy usando ahora es de Wikipedia Verlet Newton (pero los resultados tienen una pequeña diferencia con respecto a arriba). Las velocidades y posiciones ahora son de archivos Horizon. También usé la biblioteca de precisión GMP pero es lo mismo. También traté de buscar la masa solar (por código) pero el error solo se reduce a la mitad. Tal vez la velocidad de los archivos de Horizon (tiempo delta de 1 minuto) no sea perfecta en este momento (el tiempo delta de Newton es de 0,1 segundos). ¿O tal vez hay materia negra no uniforme?
Encontré que la velocidad de Horizon para cada tiempo no es la velocidad exacta en ese momento, es la velocidad promedio al siguiente paso de tiempo, porque al sumar posición + velocidad da la siguiente posición (y no exacta porque xey son perfectas mientras que z no¿ ¿¿¿WTF???? Entonces, si se necesita usar el archivo de Horizon para encontrar la velocidad inicial para configurar Newton, está bien para calcular el paso de tiempo más pequeño que Horizon, porque un pequeño error al principio crecerá y crecerá.

Respuestas (3)

Necesitas usar un mejor método numérico. El método de Euler es notoriamente malo para la mecánica orbital porque los errores numéricos siempre se acumulan. En particular, el método de Euler no conserva la energía, por lo que obtienes órbitas que mágicamente ganan energía y se salen de control.

Necesita usar algo como el método Verlet o algún otro integrador simpléctico.

https://en.wikipedia.org/wiki/Verlet_integration

https://en.wikipedia.org/wiki/Simplectic_integrator

Gracias, pero utilicé el código Verlet de wikipedia y obtuve los mismos resultados.
Recomendaría usar las efemérides del JPL para verificar sus cálculos: ssd.jpl.nasa.gov/horizons
Gracias, intenté analizar los archivos de Horizon pero obtuve errores más grandes. Además su paso de tiempo mínimo es de 0,5 segundos. Dado que algunos planetas usan el mismo código (en la fuente de Don Cross), y los que tienen errores más grandes tienen constantes más pequeñas, intentaré con una biblioteca de precisión como gmp, pero es tedioso.
Dudo que gmp ayude. Solo tendrá las posiciones inexactas con alta precisión.
No es necesario utilizar un integrador simpléctico. JPL no usa uno, por ejemplo. Utilizan un tamaño de paso variable, un integrador de la familia Adams de orden variable. ¿Quizás Cowell o Gauss-Jackson? Estos están en la familia Adams de integradores numéricos, y tanto esa posición como la velocidad son diferentes.
Dake, tienes razón, el principal error proviene de caminar en la dirección equivocada. Nuevamente estoy tomando los datos de los archivos de Horizon y el error está relacionado con la distancia al sol (Mercurio el más grande). Así que creo que es la masa, porque no es exacta. Primero simularé algunos soles masivos y llevaré el mejor con un error mínimo a Horizon. Luego ve planeta por planeta haciendo lo mismo.
@LuisALberto Pero Mercurio no es el mayor error, lo son la Tierra y la Luna, que es lo que realmente me desconcierta de tu pregunta. Normalmente, Mercurio siempre tiene el error más grande (por múltiples razones), por lo que si algo más es el más grande (Tierra-Luna), eso elimina la mayoría de los culpables normales de una sola causa (integración no simpléctica, mala G, mala masa del Sol, etc.) .) Lo que es distinto sobre el sistema tierra-luna es la alta inclinación angular de la órbita de la luna y la gran masa de la luna en comparación con su primaria (tierra). Mi instinto es que hay algo mal con los datos de origen o los z-calcs.

Además de las deficiencias del método numérico señaladas en la otra respuesta, la simulación de la órbita de Mercurio debe tener en cuenta la gravitación de Júpiter, así como los efectos relativistas. Esto solo explica una pequeña fracción de la desviación, pero debe tenerse en cuenta cuando el método numérico mejore.

Aparentemente, la precesión del perihelio de Mercurio debido a la atracción de Júpiter y los efectos relativistas es de aproximadamente 574 segundos de arco en un siglo, o 1,57E-2 segundos de arco/día. Con una circunferencia orbital de aproximadamente 3,6E8 km y un arcosegundo de 1,296E-6 de vuelta, eso equivale a aproximadamente 4,3 km, o 43 km en 10 días.

Si bien la diferencia en la posición del perihelio no se traduce directamente en una diferencia de ubicación, debería dar una idea del efecto.

gracias, esto me da una idea de la magnitud del error

El error vino de las fuentes de datos. Ahora reemplacé a NAIF cspice.lib y descargué un archivo SPK general solo para los planetas, y el error es realmente pequeño sin otros cuerpos de gravedad como asteroides y cometas. Es realmente simple usar solo 2 funciones (furnsh_c y spkezr_c), una inclusión y una lib.
Codificado con vc6 ++ pure win 32. Ejecuté makeall.bat desde Spice descomprimido (no pude hacerlo funcionar en MFC)
También el paso de tiempo puede ser cualquier fracción de segundos para que Spice y Newton estén sincronizados. Así que Newton me dice que no hay materia negra.
Estos son los resultados sin la gravedad de asteroides y cometas durante 10 días y sin correcciones en cpsice spkezr_c

error de distancia en KM newton (Verlet) desde el
tiempo de especias = 864000.250
MERCURY BARYCENTER = 5.511496277969209e+002
SATURN BARYCENTER = 8.535731413118873e+001
VENUS BARYCENTER = 2.701394194074592e+002
URANUS BARYCENTER = 8.651056255887706e+001
EARTH = 9.664941717935676e+001
NEPTUNE BARYCENTER = 8.654038466254323e+001
MOON = 1.208560265740111e+002
MARS BARYCENTER = 5.954829440293592e+001
PLUTO BARYCENTER = 8.661640570487361e+001
JUPITER BARYCENTER = 8.256645190275238e+001
TOTAL ERROR DISTANCE = 1.525933904320919e+003
Time Ini GREGORIAN = 2000 ENE 01 12:00:00.000
Time End GREGORIAN 0.20:05 = 201 ENE 02:00