Modelando el universo: la mecánica celeste claramente



Imaginemos que necesitamos lanzar una pelota de fútbol en la órbita de la Tierra. ¡No se necesitan cohetes! Suficientes montañas, una altura de 100 kilómetros y notable fuerza. Pero, ¿cuánto necesitas para patear la pelota para que nunca vuelva a la Tierra? ¿Cómo enviar la pelota en un viaje a las estrellas, teniendo solo la fuerza bruta y el conocimiento de la mecánica celeste?

Hoy en el programa:

  • Infinitas posibilidades de una fórmula
  • Cómo tomar energía de Júpiter
  • ¿De dónde vienen los planetas?
  • Cómo las matemáticas ayudaron a descubrir Neptuno

Afortunadamente, vivimos en la era de la tecnología informática. No necesitamos escalar una montaña alta y patear la pelota con todas nuestras fuerzas, ¡todo se puede modelar! Empecemos.

Una fórmula


El mismo, conocido por las lecciones de física y astronomía:



muestra cuán fuertemente interactuarán los cuerpos, dependiendo de sus masas, la distancia entre ellos y la constante gravitacional G.

Escribí un programa en el que puedes colocar bolas que interactúan entre sí mediante fuerzas gravitacionales, con Cada bola tiene su propia masa, velocidad y coordenadas. Para mayor claridad, las bolas dejan un rastro.

Pongamos una bola azul grande y masiva (Tierra) y una pequeña bola roja cerca de ella. Ejecute la simulación: se



cayó!

Para entrar en órbita, se necesita velocidad para que la pelota caiga y pierda la tierra todo el tiempo. ¿Pero qué velocidad? Y nuevamente, el conocimiento escolar viene al rescate:

la velocidad mínima requerida para ingresar a la órbita de la Tierra se llamaprimera velocidad cósmica .

Para la Tierra, es de 7.91 km / s. Y para la simulación se puede calcular fácilmente:



dispersamos la pelota y vemos el resultado:



¡vuelo normal!

La pelota describe un círculo con la Tierra en el centro. ¿Qué pasará si le das un poco más de velocidad? Ahora



revisemos : ahora la forma de la órbita es elíptica, podemos distinguir 2 puntos muy importantes: apogeo y perigeo .

Apogee es el punto en el que la pelota está lo más lejos posible de la Tierra.

Perigeo: por el contrario, el punto más cercano a la Tierra.

Con un aumento en la velocidad inicial, el perigeo no cambia, pero el apogeo se está alejando, y al final tiene una distancia infinita a la Tierra. Aquí nos acercamos al conceptosegunda velocidad espacial . Esta es la velocidad que se le debe dar a la pelota para que supere la gravedad de la Tierra y vuele para arar las extensiones del universo. Por tierra, es de 11,2 km / s.

Un truco interesante: si multiplicamos la primera velocidad cósmica por √2, obtenemos la segunda velocidad cósmica.

Multiplicado. Lanzado. Recibido: ¡



Se fue volando irrevocablemente! Por cierto, ahora tiene una órbita parabólica. Y si ejecutas la pelota aún más fuerte, obtenemos una hipérbola. Resulta interesante que las matemáticas nos persiguen en todas partes.

En este caso, la fórmula sigue siendo la misma. El círculo se convierte en una elipse, una elipse en una parábola y una parábola en una hipérbola debido al alargamiento de la órbita ( excentricidad aumentada ).

¿Cómo tomar energía de Júpiter?


Expandamos nuestro modelo, agreguemos el Sol, hagamos que la Tierra gire a su alrededor.



Imagine que la pelota necesita una velocidad tal que vuele fuera del sistema solar, la tercera velocidad cósmica . En el mundo real, es 16,7 km / s. Desafortunadamente, esta velocidad es demasiado alta, me temo que no tendremos suficiente fuerza ...

¡Espera! Pero, ¿qué pasa si tomas un poco de velocidad de un cuerpo masivo, por ejemplo, Júpiter? Podemos volar hasta algo muy masivo y hacer una maniobra gravitacional . Al volar más allá de Júpiter, las fuerzas gravitatorias atraen mutuamente la bola y el gigante gaseoso, pero la masa de la bola es tan pequeña que casi no tiene efecto en el movimiento de Júpiter, y Júpiter acelera un cuerpo que pasa a altas velocidades.

Habla menos, trabaja más:



El momento de la maniobra gravitacional: la pelota voló hacia Júpiter.



¡Hurra! Tenemos una velocidad suficiente para salir del sistema solar, sin gastar nada. Es cierto que Júpiter comenzó a moverse un poco más lento, pero definitivamente no lo notaremos.

Todas las naves espaciales lanzadas por el hombre más allá de los límites del sistema solar (Voyagers 1 y 2, Pioneers 10 y 11, New Horizons) utilizaron tal método para la aceleración.

¡Acercarse!


Agregué la fricción de las partículas para que cuando chocan, transfieran parte de la energía entre sí. También introduje el poder de una reacción normal, ahora las partículas respetan su espacio personal, alejando a los demás de sí mismos.

Ponemos la generación aleatoria de bolas y les damos una dirección y velocidad aleatorias. Déjalos ser, digamos, 100 piezas.



Caos completo, cada partícula se mueve donde quiera, pero, sin embargo, las fuerzas gravitacionales cobran su precio y comienzan a formarse grupos de bolas:



y después de un tiempo se forma un cuerpo grande, que consta de 99 bolas y una sola bola que orbita a su alrededor:



con otro lanzamiento, lo siguiente :



Dos cuerpos masivos que orbitan un centro de masa común. Si imaginamos que estos dos objetos son estrellas, entonces obtenemos una estrella doble. Curiosamente, aproximadamente la mitad de las estrellas en nuestra galaxia son binarias. Si nuestro Sol tuviera una estrella compañera, entonces en el cielo podríamos observar la siguiente imagen:



¿De dónde vienen los planetas?


La razón principal de la aparición de anillos es la destrucción de los satélites que vuelan demasiado cerca del planeta, o más bien, cruzan el límite de Roche . En este caso, las fuerzas de marea causadas por la gravedad del planeta se hacen más grandes que las fuerzas que mantienen el satélite intacto, y se rompe en muchas partes, dejando atrás un anillo que rodea el planeta. Simulemos esta situación:



el satélite está un poco más allá del límite de Roche, gira alrededor del planeta en una órbita circular estable. Pero, ¿qué sucede si lo genera un poco más cerca del planeta?



El satélite se dispersó en muchas partes pequeñas que formaron anillos alrededor del planeta. Así es en el mundo real. Tritón (satélite de Neptuno) se acerca gradualmente al planeta, y en 2 mil millones de años se desgarrará, y Neptuno tendrá más anillos que Saturno.

¿Cómo se descubrió Neptuno y qué tienen que ver las matemáticas con él?


Como estamos hablando de Neptuno, hablemos de su descubrimiento. "Un planeta abierto en la punta de un bolígrafo" tiene una masa, lo que significa que actúa sobre los objetos que lo rodean. Los astrónomos del siglo XIX notaron cambios en la órbita de Urano, su órbita era diferente de la calculada, aparentemente, algo lo afectó. La órbita de Urano tenía perturbaciones:



este modelo exagerado muestra cómo un cuerpo desconocido más allá de Urano afectó su órbita. Los astrónomos solo podían calcular la posición de un planeta secreto y mirar a través de un telescopio. De hecho, ¡el planeta Neptuno estaba exactamente donde se predijo!



Conclusión


Por supuesto, esta simulación no generaliza todas las leyes y fenómenos que ocurren en el espacio, por ejemplo, la teoría de la relatividad de Einstein no se tiene en cuenta aquí, ya que la velocidad de las partículas está lejos de la velocidad de la luz. Pero hay muchas cosas más interesantes que se pueden implementar en esta simulación. ¡Inténtalo tú mismo! Todo lo que necesitas es Python3 y la biblioteca Pygame.

Fuente
# 
Track = True

# 
Track_time = 5

# 
G = 5

#  (  -
#,  - )
MagnConst = 0

# 
count = 100

#  
kv = 6

#  
RANDOM = True

#  
r = 3

#   
WIN_WIDTH, WIN_HEIGHT = 900, 650


''',  ,   '''

#   
zg = 2

#   
zm = 2

#. ,    -   
k = 40

# 
antiG = 0.1

max_speed = 3

ResDist = 1

# 
EarthG = 0

#   
Mirror = True

import pygame
from math import hypot, ceil, sqrt
from random import randint, random


def custom_pos():
    '''      '''
    '''   RANDOM = FALSE'''
    B.append(Ball(200, 300, YELLOW, r = 10, mass = 200, vx = 0.151))    #x, y, col, r, vx, vy, mass
    B.append(Ball(200, 50, GREEN, r = 6, mass = 10, vx = -(200 * G / 250)**0.5))
    

class Ball:
    def __init__(self, x, y, col, r = 4, vx = 0, vy = 0, mass = 4):
        self.x = x
        self.y = y
        self.r = r
        self.col = col
        self.vx = vx
        self.vy = vy
        self.mass = mass
        
    def move(self, Walls, WIN_WIDTH, WIN_HEIGHT, ofs_x, ofs_y):
        if Walls:
            x = self.x - ofs_x
            y = self.y - ofs_y
            if x <= 0 and self.vx < 0:
                if Mirror:
                    self.vx = -self.vx
                else:
                    self.x += WIN_WIDTH
                self.vx, self.vy = self.v_norm(self.vx, self.vy)
            if x >= WIN_WIDTH and self.vx > 0:
                if Mirror:
                    self.vx = -self.vx
                else:
                    self.x -= WIN_WIDTH
                self.vx, self.vy = self.v_norm(self.vx, self.vy)
            if y <= 0 and self.vy < 0:
                if Mirror:
                    self.vy = -self.vy
                else:
                    self.y += WIN_HEIGHT
                self.vx, self.vy = self.v_norm(self.vx, self.vy)
            if y >= WIN_HEIGHT and self.vy > 0:
                if Mirror:
                    self.vy = -self.vy
                else:
                    self.y -= WIN_HEIGHT
                self.vx, self.vy = self.v_norm(self.vx, self.vy)
            
        self.x += self.vx
        self.y += self.vy

        
    def force(self, ind, selfind):
        ox = B[ind].x
        oy = B[ind].y
        m = B[ind].mass
        if m < 0.01 and self.mass < 0.01:
            return 0
        r = B[ind].r
        vx = B[ind].vx
        vy = B[ind].vy
        dist = hypot(self.x - ox, self.y - oy)
        min_dist = (self.r + B[ind].r) * ResDist
        f = 0
        m_relative = self.mass / B[ind].mass
        if dist <= min_dist:
            newVx = (vx * m + self.vx * self.mass) / (m + self.mass)
            newVy = (vy * m + self.vy * self.mass) / (m + self.mass)
            self.vx = (newVx + k * self.vx) / (k + 1)
            B[ind].vx = (newVx + k * B[ind].vx) / (k + 1)
            self.vy = (newVy + k * self.vy) / (k + 1)
            B[ind].vy = (newVy + k * B[ind].vy) / (k + 1)
            f -= antiG * min(abs(min_dist - dist), min(m, self.mass) * 3)
        else:
            f += min(self.mass * B[ind].mass * G  / (dist ** zg), G / 10)
            mf = MagnConst * self.mass / (dist ** zm)
            if B[ind].col == B[selfind].col:
                mf = - mf
            f += mf
        fx = f * ((ox - self.x) / dist)
        fy = f * ((oy - self.y) / dist)
        ax = fx / self.mass
        ay = fy / self.mass
        self.vx += ax
        self.vy += ay + EarthG
        B[ind].vx -= ax * m_relative
        B[ind].vy -= ay * m_relative - EarthG

    @staticmethod
    def v_norm(vx, vy):
        v = hypot(vx, vy)
        if v > max_speed:
            vx = max_speed * (vx / v)
            vy = max_speed * (vy / v)
        return vx, vy


class Point:
    def __init__(self, x, y, col, r = 0, max_age = Track_time):
        self.age = 0
        self.x = x
        self.y = y
        self.col = col
        self.r = r
        self.max_age = max_age
    def vis(self, ofs_x, ofs_y):
        pygame.draw.circle(sc, self.col, (round(self.x - ofs_x),
                                          round(self.y - ofs_y)), self.r, 0)
        self.age += 1
        if self.age > self.max_age:
            T.remove(self)
        
def rand(count, WIN_WIDTH, WIN_HEIGHT):
    global kv
    B = []
    for i in range(count):
        m = r ** 2
        x = randint(0, WIN_WIDTH) + random()
        y = randint(0, WIN_HEIGHT) + random()
        vx = kv * randint(-100, 100) / 100
        vy = kv * randint(-100, 100) / 100
        col = Colors[randint(0, len(Colors) - 1)]
        B.append(Ball(x, y, col, r = r, vx = vx, vy = vy, mass = m))
    return B

def createBall(col, x, y, r = r, m = r):
    m = r
    B.append(Ball(x, y, col))

def get_offset(B):
    sum_x, sum_y = 0, 0
    m = 0
    for i in range(len(B)):
        sum_x += B[i].x * B[i].mass
        sum_y += B[i].y * B[i].mass
        m += B[i].mass
    if len(B) == 0:
        return 0, 0
    return sum_x / m, sum_y / m

def visBalls(B):
    for i in range(len(B)):
        pygame.draw.circle(sc, B[i].col, (round(B[i].x - ofs_x),
                                          round(B[i].y - ofs_y)), B[i].r, 0)
        T.append(Point(B[i].x, B[i].y, B[i].col))
        
FPS = 60
darkblue = (0, 2, 25)
ORANGE = (255, 200, 150)
RED = (255, 150, 150)
GREEN = (150, 255, 150)
BLUE = (150, 150, 255)
YELLOW = (255, 255, 0)
Colors = [RED, BLUE]#, GREEN]#, ORANGE]                       
pygame.init() 
clock = pygame.time.Clock()
sc = pygame.display.set_mode((WIN_WIDTH, WIN_HEIGHT))
sc.fill(darkblue)

maxF = 0.3
minv = 0.01
Walls = True
Collisions = True
Same = True
Check = False
tt = []

B = []
if RANDOM:
    B = rand(count, WIN_WIDTH, WIN_HEIGHT)
else:
    custom_pos()
    
Pause = False
delay = 0

if Track:
    T = []
for z in range(100000):
    sc = pygame.display.set_mode((WIN_WIDTH, WIN_HEIGHT))
    sc.fill(darkblue)
    ofs_x, ofs_y = get_offset(B)
    ofs_x -= WIN_WIDTH // 2
    ofs_y -= WIN_HEIGHT // 2
    for i in pygame.event.get():
        if i.type == pygame.QUIT:
            pygame.quit()
            quit()
        if i.type == pygame.KEYDOWN:
            if i.key == pygame.K_SPACE:
                Pause = not Pause
            elif i.key == pygame.K_w:
                WIN_HEIGHT += 10
                WIN_WIDTH += 10
            elif i.key == pygame.K_s:
                WIN_HEIGHT -= 10
                WIN_WIDTH -= 10
                
    pressed = pygame.mouse.get_pressed()
    pos = pygame.mouse.get_pos()
    x = pos[0]
    y = pos[1]
    if pressed[0] and delay < 0:
        delay = 20
        createBall(RED, x + ofs_x, y + ofs_y)
    if pressed[2] and delay < 0:
        delay = 20
        createBall(BLUE, x + ofs_x, y + ofs_y )
    delay -= 1
    
    if not Pause:
        for i in range(len(B)):
            for j in range(i + 1, len(B)):
                B[i].force(j, i)
        for i in range(len(B)):
            B[i].move(Walls, WIN_WIDTH, WIN_HEIGHT, ofs_x, ofs_y)
    for i in range(len(T)):
        try:
            T[i].vis(ofs_x, ofs_y)
        except IndexError:
            pass
    visBalls(B)
    
    pygame.display.update()
    clock.tick(FPS)


Espero que este artículo haya sido informativo para ti. ¡Gracias por la atención!

All Articles