نمذجة الكون: الميكانيكا السماوية بشكل واضح



دعونا نتخيل أننا بحاجة إلى إطلاق كرة قدم في مدار الأرض. لا حاجة لصواريخ! ما يكفي من الجبال ، بارتفاع 100 كيلومتر وقوة رائعة. ولكن كم تحتاج إلى ركل الكرة حتى لا تعود إلى الأرض؟ كيفية إرسال الكرة في رحلة إلى النجوم ، مع امتلاك القوة الوحشية فقط ومعرفة الميكانيكا السماوية؟

اليوم في البرنامج:

  • الاحتمالات اللانهائية لصيغة واحدة
  • كيف تأخذ الطاقة من المشتري
  • من أين تأتي الكواكب
  • كيف ساعدت الرياضيات في اكتشاف نبتون

لحسن الحظ ، نحن نعيش عصر تكنولوجيا الكمبيوتر. نحن لسنا بحاجة لتسلق جبل عال وركل الكرة بكل قوتنا ، يمكن تشكيل كل شيء! هيا بنا نبدأ.

صيغة واحدة


نفس الشيء ، المعروف من دروس الفيزياء وعلم الفلك:



يوضح مدى قوة تفاعل الأجسام ، اعتمادًا على كتلها ، والمسافة بينها وثابت الجاذبية G.

لقد كتبت برنامجًا يمكنك من خلاله وضع الكرات التي تتفاعل مع بعضها البعض بواسطة قوى الجاذبية ، مع لكل كرة كتلتها وسرعتها وإحداثياتها. من أجل الوضوح ، تترك الكرات أثرًا.

دعونا نضع كرة زرقاء كبيرة وضخمة (الأرض) وكرة حمراء صغيرة بالقرب منها. تشغيل المحاكاة:



سقط!

للدخول إلى المدار ، هناك حاجة إلى السرعة حتى تسقط الكرة وتفوت الأرض طوال الوقت. لكن ما السرعة؟ ومرة أخرى ، تأتي معرفة المدرسة لإنقاذها:

الحد الأدنى للسرعة المطلوبة لدخول مدار الأرض يسمىالسرعة الكونية الأولى .

بالنسبة للأرض ، تبلغ 7.91 كم / ثانية. وللمحاكاة يمكن حسابها بسهولة: نقوم



بتفريق الكرة ونرى النتيجة:



رحلة عادية!

تصف الكرة دائرة مع الأرض في المنتصف. ماذا سيحدث إذا أعطيته سرعة أكبر قليلاً؟ الآن



دعونا الاختيار: الآن على شكل المدار هو بيضاوي الشكل، يمكننا أن نميز 2 نقطة مهمة جدا - الأوج و الحضيض .

الأوج هو النقطة التي تكون فيها الكرة بعيدة عن الأرض قدر الإمكان.

الحضيض - على العكس ، النقطة الأقرب إلى الأرض.

مع زيادة السرعة الأولية ، لا يتغير الحضيض ، لكن الأوج يتقدم ، وفي النهاية لديه مسافة لا نهائية من الأرض. هنا نقترب من المفهومسرعة الفضاء الثانية . هذه هي السرعة التي يجب أن تعطى للكرة بحيث تتغلب على جاذبية الأرض وتطير بعيدًا لحرث مساحات الكون. بالنسبة للأرض ، تبلغ 11.2 كم / ثانية.

خدعة مثيرة للاهتمام: إذا ضربنا السرعة الكونية الأولى بمقدار √2 ، نحصل على السرعة الكونية الثانية.

ضرب. انطلقت. تلقى:



طار بلا رجعة! بالمناسبة ، الآن لديها مدار مكافئ. وإذا قمت بتشغيل الكرة بشكل أقوى ، نحصل على hyperbola. اتضح أن الرياضيات تطاردنا في كل مكان.

في هذه الحالة ، تبقى الصيغة كما هي. تتحول الدائرة إلى القطع الناقص ، القطع الناقص إلى القطع المكافئ ، القطع المكافئ إلى القطع الزائد بسبب إطالة المدار (زيادة الانحراف ).

كيف تأخذ الطاقة من المشتري؟


دعونا نوسع نموذجنا ، نضيف الشمس ، ونجعل الأرض تدور حولها.



تخيل أن الكرة تحتاج إلى أن تعطى السرعة التي تطير خارج النظام الشمسي - السرعة الكونية الثالثة . في العالم الحقيقي ، تبلغ 16.7 كم / ثانية. لسوء الحظ ، هذه السرعة عالية جدًا ، أخشى أنه لن يكون لدينا ما يكفي من القوة ...

انتظر! ولكن ماذا لو أخذت سرعة صغيرة من جسم ضخم ، على سبيل المثال ، المشتري. يمكننا أن نطير إلى شيء ضخم للغاية ونقوم بمناورة جاذبية . عند التحليق فوق المشتري ، تجذب قوى الجاذبية الكرة وعملاق الغاز بشكل متبادل ، لكن كتلة الكرة صغيرة جدًا بحيث لا يكون لها أي تأثير تقريبًا على حركة المشتري ، ويسرع المشتري نفسه جسمًا يمر بسرعة عالية.

تحدث أقل واعمل أكثر:



لحظة مناورة الجاذبية - طارت الكرة إلى المشتري.



مرحى! حصلنا على سرعة كافية للخروج من النظام الشمسي ، مع عدم إنفاق أي شيء. صحيح ، بدأ المشتري في التحرك بشكل أبطأ قليلاً ، لكننا بالتأكيد لن نلاحظ ذلك.

استخدمت جميع المركبات الفضائية التي أطلقها الإنسان خارج حدود النظام الشمسي (فوييجر 1 و 2 ، بايونيرز 10 و 11 ، نيو هورايزونز) مثل هذه الطريقة في التسارع.

تكبير!


أضفت احتكاك الجسيمات بحيث عندما تصطدم ، تنقل جزءًا من الطاقة إلى بعضها البعض. لقد قدمت أيضًا قوة التفاعل الطبيعي ، والآن تحترم الجسيمات مساحتها الشخصية ، مما يدفع الآخرين بعيدًا عن أنفسهم.

نضع الجيل العشوائي للكرات ونمنحهم اتجاهًا عشوائيًا وسرعة. فليكن ، على سبيل المثال ، 100 قطعة.



فوضى كاملة ، يتحرك كل جسيم أينما يريد ، ولكن مع ذلك ، فإن قوى الجاذبية تأخذ حصيلة من الكرات وتبدأ مجموعات الكرات في التكون:



وبعد فترة يتم تشكيل جسم كبير ، يتكون من 99 كرة وكرة واحدة تدور حوله:



مع إطلاق آخر ، ما يلي :



جسمان ضخمان يدوران حول مركز كتلة مشترك. إذا تخيلنا أن هذين الجسمين نجومان ، فإننا نحصل على نجمة مزدوجة. من المثير للاهتمام أن حوالي نصف النجوم في مجرتنا ثنائية. إذا كان لشمسنا نجمة رفيقة ، فيمكننا في السماء ملاحظة الصورة التالية:



من أين تأتي الكواكب؟


السبب الرئيسي لظهور الحلقات هو تدمير الأقمار الصناعية التي تحلق بالقرب من الكوكب ، أو بالأحرى عبور حدود روش . في هذه الحالة ، تصبح قوى المد والجزر التي تسببها جاذبية الكوكب أكبر من القوى التي تحافظ على القمر الصناعي سليمة ، وتقتحم أجزاء عديدة ، تاركة خلفها حلقة تحيط بالكوكب. لنقم بمحاكاة هذا الموقف:



القمر الصناعي أبعد قليلاً من حد روش ، إنه يدور حول الكوكب في مدار دائري مستقر. لكن ماذا يحدث إذا أنتجته أقرب قليلاً إلى الكوكب؟



تناثر القمر الصناعي في العديد من الأجزاء الصغيرة التي شكلت حلقات حول الكوكب. لذلك هو في العالم الحقيقي. يقترب Triton (قمر نبتون) تدريجيًا من الكوكب ، وفي 2 مليار سنة سيتمزق ، وسوف يكون لنبتون حلقات أكثر من زحل.

كيف تم اكتشاف نبتون وما علاقة الرياضيات به؟


بما أننا نتحدث عن نبتون ، فلنتحدث عن اكتشافه. "كوكب مفتوح على طرف قلم" له كتلة ، مما يعني أنه يعمل على الأشياء المحيطة. لاحظ علماء الفلك في القرن التاسع عشر تغيرات في مدار أورانوس ، وكان مداره مختلفًا عن المدار المحسوب ، على ما يبدو ، شيء أثر عليه. كان مدار أورانوس يعاني من اضطرابات:



يوضح هذا النموذج المبالغ فيه كيف أثر جسم غير معروف خارج أورانوس على مداره. استطاع الفلكيون حساب موقع الكوكب السري فقط والنظر من خلال التلسكوب. في الواقع ، كان كوكب نبتون بالضبط حيث كان متوقعًا!



استنتاج


بالطبع ، لا تعمم هذه المحاكاة جميع القوانين والظواهر التي تحدث في الفضاء ، على سبيل المثال ، لا تؤخذ نظرية النسبية لأينشتاين بعين الاعتبار هنا ، لأن سرعة الجسيمات بعيدة عن سرعة الضوء. ولكن هناك العديد من الأشياء الأكثر إثارة للاهتمام والتي يمكن تنفيذها في هذه المحاكاة. جربها بنفسك! كل ما تحتاجه هو 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