建模宇宙:天体力学清晰



假设我们需要将一个足球发射到地球的轨道上。不需要火箭!足够多的山脉,海拔100公里,实力非凡。但是,您需要踢多少球才能使其永远不会回到地球上?如何在仅具有蛮力和天体力学知识的情况下将球发送到星星的旅程?

今天在程序中:

  • 一个公式的无限可能性
  • 如何从木星中获取能量
  • 行星从哪里来
  • 数学如何帮助发现海王星

幸运的是,我们生活在计算机技术时代。我们无需竭尽全力攀登高山和踢球,一切都可以建模!让我们开始吧。

一个公式


从物理学和天文学的课程中可以得知,这是相同的:



它显示了物体之间的相互作用的强度,取决于它们的质量,它们与重力常数G之间的距离。

我编写了一个程序,您可以在其中放置球,这些球可以通过重力彼此相互作用。每个球都有自己的质量,速度和坐标。为了清楚起见,这些球留下了痕迹。

让我们在其附近放一个大而重的蓝色球(地球),再放一个小红色球。运行模拟:



他摔倒了!

要进入轨道,需要速度,以便球始终掉落并错过地球。但是什么速度?再一次,学校的知识可以解救:

进入地球轨道所需的最低速度称为第一宇宙速度

对于地球,它是7.91 km / s。对于仿真,它可以很容易地计算出:我们



分散球并看到结果:



正常飞行!

球描绘了一个以地球为中心的圆。如果再加快一点速度会怎样?现在



让我们检查一下:现在轨道的形状为椭圆形,我们可以区分两个非常重要的点- 顶点近地点

Apogee是球尽可能远离地球的位置。

近地点-相反,最接近地球的点。

随着初始速度的增加,近地点不会改变,但是远地点越来越远,最终它与地球之间的距离无限远。在这里,我们接近概念第二空速这是必须赋予球的速度,这样球才能克服地球的重力并飞走以犁开宇宙的广阔空间。对于陆地,速度为11.2 km / s。

一个有趣的技巧:如果将第一宇宙速度乘以√2,我们将获得第二宇宙速度。

相乘。推出了。收到:



他不可回避地飞走了!顺便说一下,现在它具有抛物线轨道。如果您将球踢得更强,我们就会得到双曲线。有趣的是,数学无处不在。

在这种情况下,公式保持不变。由于轨道的延长(偏心率增加,圆变成椭圆形,椭圆变成抛物线,抛物线变成双曲线

如何从木星中吸收能量?


让我们扩展模型,添加太阳,使地球围绕它旋转。



想象一下,需要给球提供这样的速度,使其能够飞行到太阳系之外,即第三宇宙速度。在现实世界中,速度为16.7 km / s。不幸的是,这个速度太高了,恐怕我们将没有足够的力量...

等等!但是,如果您从某个巨大的物体(例如木星)上稍微走一点速度怎么办?我们可以飞到非常重的物体上并进行重力操纵。当飞越木星时,重力会相互吸引球和气体巨人,但是球的质量很小,几乎对木星的运动没有影响,木星本身会加速高速经过的物体。

少说话,多工作:



重力动作的瞬间-球飞到了木星。



万岁!我们有足够的速度退出太阳系,而没有花任何钱。没错,木星开始缓慢移动,但是我们绝对不会注意到它。

人类发射的所有航天器都超出了太阳系的限制(“新视野号”的“旅行者1”和“ 2”,“新视野号”的“先锋10”和“ 11”)就是这种加速方法。

放大!


我添加了粒子的摩擦力,以便当它们碰撞时,它们将一部分能量彼此传递。我还介绍了正常反应的力量,现在粒子尊重他们的个人空间,将其他人推离自己。

我们把球随机生成,并给它们随机的方向和速度。假设它们是100件。



完全混乱,每个粒子移动到所需的位置,但重力仍然对其造成影响,并开始形成球团:



一段时间后,形成了一个大物体,由99个球和一个围绕其绕行的单个球组成:



随着另一次发射, :



两个质量大的物体围绕一个共同的质心运动。如果我们想象这两个物体是星星,那么我们得到一个双星有趣的是,我们银河系中大约一半的恒星是双星的。如果我们的太阳有伴星,那么在天空中我们可以观察到以下图片:



行星从哪里来?


出现这些环的主要原因是摧毁了飞离地球太近或越过罗氏极限的卫星在这种情况下,由行星重力引起的潮汐力变得大于保持卫星完好无损的力,它分裂成许多部分,留下了环绕行星的环。让我们模拟这种情况:



卫星比Roche极限稍微远一点,它绕着行星以稳定的圆形轨道旋转。但是,如果将其生成到离地球更近的地方会发生什么呢?



卫星分散成许多小部分,形成了围绕地球的环。在现实世界中也是如此。海王星卫星海卫一(Triton)正在逐渐接近地球,在20亿年内它将被撕裂,海王星的环数将超过土星。

海王星是如何发现的,数学与之有什么关系?


由于我们在谈论海王星,因此我们来谈谈它的发现。“在笔尖打开的行星”有一个质量,这意味着它作用在周围的物体上。19世纪的天文学家注意到天王星的轨道发生了变化,它的轨道与计算得出的轨道不同,显然是有某种影响。天王星的轨道受到干扰:



这个夸大的模型显示了天王星以外的未知物体是如何影响其轨道的。天文学家只能计算出一颗秘密行星的位置,并通过望远镜观察。确实,海王星行星正是它的预言!



结论


当然,该模拟并不能概括出空间中发生的所有定律和现象,例如,由于粒子的速度远非光速,因此此处未考虑爱因斯坦的相对论。但是,在此模拟中可以实现更多有趣的事情。自己尝试!您只需要Python3和Pygame库。

资源
# 
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)


希望本文对您有所帮助。感谢您的关注!

All Articles