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

Lekcja 8

Fizyka. Ruch planet w JS

  1. fizyka
  2. animacja
  3. zmienne
  4. euler
  5. program
  6. pulsar
  7. zderzenia
  8. kosmologia

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.


Zmienne

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


Cały program

<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>