mgr inż. Wacław Libront * Bobowa 2017-2019
ZSO Bobowa, ul. Długoszowskich 1, 38-350 Bobowa, tel: 0183514009, fax: 0183530221, email: sekretariat@zsobobowa.eu, www: zsobobowa.eu
Fizyka
Zmiana przyspieszenia do zasymulowania rzutów w polu grawitacyjnym jest zagadnieniem
względnie prostym. Ale jak poddać analizie kilka obiektów, które się nawzajem przyciągają? Jak zasymulować grawitacyjne przyciąganie planet w Układzie Słonecznym?
Planety przyciągają się grawitacyjnie siłami, które jako pierwszy nazwał i opisał w XVII wieku Newton. Aby z wartości sił, którymi działają na siebie masywne obiekty przejść do równań ruchu (położenia, prędkości i przyspieszenia) należy je zróżniczkować. Matematycznie, zwłaszcza w dobie komputerów, nie jest to proces skomplikowany i czasochłonny; w czasach Newtona prawie niemożliwy do rozwiązania dla więcej niż dwóch planet.
Nie wdając się w matematyczne szczegóły przedstawiony zostanie gotowy algorytm, tzw. metoda Eulera. Analizujemy każdy obiekt i jego oddziaływanie na każdy inny – podwójna pętla. Z grawitacyjnego wzoru Newtona wyliczamy dla każdego obiektu jego przyspieszenie (potrzebne są masy, odległości i poprzednie przyspieszenia). Z przyspieszeń wyliczamy prędkości obiektów (potrzebne są przyspieszenia i poprzednie prędkości), a z prędkości nowe położenia (potrzebne prędkości i poprzednie położenia)… i tak w koło…
Animacja
Pętla animacyjna jest taka sama, jak w poprzednich lekcjach. W tablicy
będziemy przechowywać współrzędne i parametry Słońca, Ziemi i Marsa i
zasymulujemy taki mini Układ Słoneczny. Parametry będą zbliżone do tych
prawdziwych.
<canvas id="c1" width="600" height="600"></canvas> <script> var c = c1.getContext('2d') var w = c.canvas.width; var h = c.canvas.height; var skok = 1; var czas; // PLANETA function planeta(x,y,r,k) { c.beginPath(); c.strokeStyle=k; c.fillStyle=k; c.arc(x,y,r,0,2*Math.PI); c.stroke(); c.fill(); }; // ANIMACJA function animacja() { c.clearRect(0, 0, w, h); c.strokeStyle="black"; c.strokeRect(0, 0, w, h); planeta(w/2, h/2, 50, "yellow"); clearTimeout(czas); czas = setTimeout(animacja, skok); } animacja(); </script> |
Funkcja planeta rysuje wypełnione koło o środku w punkcie (x,y), promieniu r i kolorze k. Parametry początkowe ustawimy w ten sposób, aby nieruchome Słońce znajdowało się w środku obszaru canvas, a dwie planety ją obiegały z odpowiednimi prędkościami.
G – stała grawitacji – w naszej symulacji przyjmujemy, że będzie miała wartość 10, w rzeczywistości wynosi ona 6.67e-11 [m3 kg-1 s-2]. Ponieważ zmieniamy parametry Wszechświata, dlatego będziemy musieli odpowiednio dopasować prędkości i masy planet
dt – skok czasu podczas obliczeń – można dopasować w zależności od wymaganej szybkości przesuwania się planet
P – wektor współrzędnych obiektu
V – wektor składowych szybkości
A – wektor składowych przyspieszenia
TP – tablica na wektory współrzędnych obiektów
TV – tablica na wektory szybkości
TA – tablica na wektory przyspieszeń
TM – tablica na masy planet
TR – tablica na promienie (w pikselach)
TK – tablica na kolory
ILE – ilość animowanych obiektów
Wszystkie niezbędne do obliczeń dane przechowujemy w tablicach: TP – położenia, TV – prędkości, TA – przyspieszenia, TM – masy, TR – promienie. Bardzo duże znaczenie podczas obliczeń ma tzw. krok czasowy – dt. Jeśli jest zbyt mały, to symulacja jest dokładna, ale wolna. Jeśli jest zbyt duży, to planety poruszają się szybciej, ale obliczenia są niedokładne – pojawiają się tzw. kumulacje niedokładności.
W oknie znajdują się parametry startowe dla 4 obiektów kosmicznych; zostały dobrane tak, aby zasymulować Słońce, Ziemię, Mars i przelatującą przez ten układ kometę.
var G=10; var dt=0.00001; var P={x:0,y:0}; var V={x:0,y:0}; var A={x:0,y:0}; var TP=[]; var TV=[]; var TA=[]; var TM=[]; var TR=[]; var TK=[]; var ILE=4; //PARAMETRY STARTOWE // masy // promienie // kolory TM[0]=2e10; TR[0]=40; TK[0]="yellow"; TM[1]=6e4; TR[1]=5; TK[1]="blue"; TM[2]=6e3; TR[2]=4; TK[2]="red"; TM[3]=100; TR[3]=1; TK[3]="black"; // położenia // szybkości // przyspieszenia TP[0]={x:w/2,y:h/2}; TV[0]={x:0,y:0}; TA[0]={x:0,y:0}; TP[1]={x:w/2-150,y:h/2}; TV[1]={x:0,y:30000}; TA[1]={x:0,y:0}; TP[2]={x:w/2-230,y:h/2}; TV[2]={x:0,y:24000}; TA[2]={x:0,y:0}; TP[3]={x:-200,y:-100}; TV[3]={x:25000,y:10000}; TA[3]={x:0,y:0}; |
Algorytm Eulera
Potrzebne nam są dwie zagnieżdżone pętle, za pomocą których porównamy każdy badany obiekt z każdym innym.
Pętle kolejna przerysuje wszystkie obiekty w tablicy.
for (var i=0;i<ILE;i++) { // ... zerujemy wektory przyspieszeń for (var j=0;j<ILE;j++) { if (i!=j){ // ... wyliczamy odległości // ... wyliczamy przyspieszenia } } // ... wyliczamy prędkości i położenia } // rysowanie wszystkich obiektów for (var i=0;i<ILE;i++){ planeta(TP[i].x,TP[i].y,TR[i],TK[i]); |
Odległości i przyspieszenia
Dla wszystkich planet (każda z każdą) wyliczamy działające między nimi przyspieszenia (Newton). Aby wzory były bardziej przejrzyste, pobrano do osobnych zmiennych położenia porównywanych obiektów, obliczamy odległość między nimi (Pitagoras).
Szybkości i położenia
Po obliczeniu przyspieszeń, wyliczamy prędkości, a następnie nowe położenia.
I to już tyle, żeby rozpocząć eksplorację naszego małego kosmosu.
// zerujemy wektory przyspieszeń TA[i]={x:0,y:0} // odległość między obiektami var xi = TP[i].x; var xj = TP[j].x; var yi = TP[i].y; var yj = TP[j].y; var d = Math.sqrt((xi-xj)*(xi-xj) + (yi-yj)*(yi-yj)); // nowe przyspieszenia TA[i].x = TA[i].x + -G*TM[j]*(xi-xj)/ Math.pow(d,3); TA[i].y = TA[i].y + -G*TM[j]*(yi-yj)/ Math.pow(d,3); // nowe szybkości TV[i].x = TV[i].x + TA[i].x * dt; TV[i].y = TV[i].y + TA[i].y * dt; // nowe położenia TP[i].x = TP[i].x + TV[i].x * dt; TP[i].y = TP[i].y + TV[i].y * dt; |
Poszczególne fragmenty wstawiamy w odpowiednie miejsca pętli Eulera
<canvas id="c1" width="600" height="600"></canvas> <script> var c = c1.getContext('2d') var w = c.canvas.width; var h = c.canvas.height; var skok = 1; var czas; // PLANETA function planeta(x,y,r,k) { c.beginPath(); c.strokeStyle=k; c.fillStyle=k; c.arc(x,y,r,0,2*Math.PI); c.stroke(); c.fill(); }; var G=10; var dt=0.00001; var P={x:0,y:0}; var V={x:0,y:0}; var A={x:0,y:0}; var TP=[]; var TV=[]; var TA=[]; var TM=[]; var TR=[]; var TK=[]; var ILE=4; //PARAMETRY STARTOWE // masy // promienie // kolory TM[0]=2e10; TR[0]=40; TK[0]="yellow"; TM[1]=6e4; TR[1]=5; TK[1]="blue"; TM[2]=6e3; TR[2]=4; TK[2]="red"; TM[3]=100; TR[3]=1; TK[3]="black"; // położenia // szybkości // przyspieszenia TP[0]={x:w/2,y:h/2}; TV[0]={x:0,y:0}; TA[0]={x:0,y:0}; TP[1]={x:w/2-150,y:h/2}; TV[1]={x:0,y:30000}; TA[1]={x:0,y:0}; TP[2]={x:w/2-230,y:h/2}; TV[2]={x:0,y:24000}; TA[2]={x:0,y:0}; TP[3]={x:-200,y:-100}; TV[3]={x:25000,y:10000}; TA[3]={x:0,y:0}; // ANIMACJA function animacja() { c.clearRect(0, 0, w, h); c.strokeStyle="black"; c.strokeRect(0, 0, w, h); planeta(w/2, h/2, 50, "yellow"); for (var i=0;i<ILE;i++) { // zerujemy wektory przyspieszeń TA[i]={x:0,y:0} for (var j=0;j<ILE;j++) { if (i!=j){ // odległość między obiektami var xi = TP[i].x; var xj = TP[j].x; var yi = TP[i].y; var yj = TP[j].y; var d = Math.sqrt((xi-xj)*(xi-xj) + (yi-yj)*(yi-yj)); // nowe przyspieszenia TA[i].x = TA[i].x + -G*TM[j]*(xi-xj)/ Math.pow(d,3); TA[i].y = TA[i].y + -G*TM[j]*(yi-yj)/ Math.pow(d,3); } } // nowe szybkości TV[i].x = TV[i].x + TA[i].x * dt; TV[i].y = TV[i].y + TA[i].y * dt; // nowe położenia TP[i].x = TP[i].x + TV[i].x * dt; TP[i].y = TP[i].y + TV[i].y * dt; } // rysowanie wszystkich obiektów for (var i=0;i<ILE;i++){ planeta(TP[i].x,TP[i].y,TR[i],TK[i]); } clearTimeout(czas); czas = setTimeout(animacja, skok); } animacja(); </script> |
Pulsar
Inny zestaw parametrów początkowych pozwala przebadać dwie planety krążące wokół siebie. Zmieniamy grawitację i czas, aby wartości były mniejsze.
// PULSAR var G=1; var dt=1; var ILE=2; TM[0]=600; TR[0]=5; TK[0]="black"; TM[1]=600; TR[1]=5; TK[1]="black"; TP[0]={x:w/2-100,y:h/2}; TV[0]={x:1,y:-1}; TA[0]={x:0,y:0}; TP[1]={x:w/2+100,y:h/2}; TV[1]={x:-1,y:1}; TA[1]={x:0,y:0}; |
Zderzenia
Co się stanie, jeśli obiekty kosmiczne się ze sobą zderzą? Nasz program nie uwzględnia takiej możliwości
i w momencie, gdy odległość między planetami będzie wynosiła zero (lub niewielka liczba
bliską zera) zostaną obliczone bardzo duże przyspieszenia… i planeta „odleci” w kosmos.
Czy możemy zmienić coś w programie? Matematycznie symulujemy zderzenie. Jeśli odległość pomiędzy obiektami zmniejszy się do sumy odległości promieni tych obiektów, to się zderzają. Powinny się połączyć w jeden
obiekt i odtąd wspólnie razem podróżować.
Wyliczymy wypadkową prędkość z zasady zachowania pędu (średnia ważona), powiększamy masę większego obiektu i zwiększamy jego promień (sumowanie pól powierzchni. Mniejszy
obiekt zostanie wyzerowany.
// gdy odległość między obiektami // mniejsza niż suma ich promieni if (d<=(TR[i]+TR[j])){ // szukamy masywniejszego if (TM[i]>=TM[j]){ // pierwszy obiekt większy // ... wypadkowe prędkości ... // ... nowa masa i promień ... // ... zerowanie mniejszego ... } else{ // drugi obiekt większy } |
Problemy
kosmologiczne
Jakie mogą pojawiać się problemy? Jeśli będziemy próbować symulować kosmos w rzeczywistych jednostkach (ten program to umożliwia!), to musimy zdać sobie sprawę z ogromnych rozpiętości wartości liczbowych, którymi będziemy musieli się posługiwać. Już sam nasz Układ Słoneczny wymaga zastosowania skali od 10-11 (stała grawitacji) do 1030 (masa Słońca). Obliczenia na tak zróżnicowanych liczbach muszą generować rozmaite niedokładności.
Kolejna problem dotyczy symulowania w czasie rzeczywistym, Chcąc prześledzić losy planet w naszym układzie musielibyśmy czekać rok, żeby Ziemia obiegła Słońce, albo przyspieszyć całą symulację - co powoduje błędy obliczeń. Co możemy zrobić? Znane są inne, bardziej dokładne sposoby wyliczania parametrów planet. Możemy ulepszać algorym Eulera (uśrednianie szeregiem Taylora), zastosować algorytm Verleta lub Rungego-Kutty. Głównym celem tych algorytmów jest wyliczenie położeń w punktach pośrednich pomiędzy założonym przedziałem czasowym.
Na początku, czyli mniej więcej 14 miliardów lat temu, był Wielki Wybuch. Cała powstała w tym ułamku sekundy materia rozprzestrzeniła się w znanym nam Wszechświecie. Powstały niezliczone ilości gwiazd, planet, komet i mnóstwa innych obiektów kosmicznych, z których najbardziej tajemnicze są tzw. Czarne Dziury. Jak to się stało, że powstały gwiazdy? Możemy w prosty sposób zasymulować po modyfikacji naszego podstawowego programu.
Wszechświat "działa" w nieskomplikowany sposób: materia rozprzestrzenia się nieustannie, ale jednocześnie działa siła grawitacji, która powoduje ściskanie i w niektórych miejscach gromadzi się jej więcej. Ściśnięta w ten sposób materia się rozgrzewa i dochodzi do swoistego "zapłonu" - w ten sposób "płoną" reakcją termojądrową gwiazdy.
Ale dlaczego wszystko się kręci? I wszystko jest w ruchu? I takie ogromne przestrzenie? I nic się nie zderza? Na te wszystkie, i być może inne pytania, znajdziesz być może odpowiedź po obejrzeniu zmodyfikowanej symulacji - 1000 obiektów kosmicznych przyciąga się siłami grawitacji. A jeśli chcesz dowiedzieć się więcej o kosmologicznych problemach przeczytaj moją pracę dyplomową http://zsobobowa.eu/pliki/fizyka/symulacja.pdf
Szablon
<canvas width="400" height="400" id="can"></canvas> <script> var c = can.getContext("2d"); </script> |