<<

Stable Configurations of Planetary Systems Profielwerkstuk (N&T)

Muriel van der Laan, het 4e gymnasium, Amsterdam begeleider: Sven Aerts

February 2015 Contents

Preface ...... 3 Introduction ...... 4 Introductie ...... 6

1 Kepler’s Laws of Planetary Motion 9 1.1 Newton’s Law of Gravitation ...... 9 1.2 Some Definitions ...... 10 1.2.1 Momentum ...... 10 1.2.2 Angular Momentum ...... 10 1.2.3 Total Energy ...... 10 1.3 Kepler’s First Law ...... 11 1.3.1 A Closer Look at the Total Energy ...... 11 1.3.2 The Laplace-Runge-Lenz Vector ...... 11 1.3.3 Kepler’s First Law ...... 12 1.4 Kepler’s Second Law ...... 15 1.5 Kepler’s Third Law ...... 16 1.5.1 The Area of the Ellipse ...... 16 1.5.2 The Semi-minor Axis ...... 17 1.5.3 Kepler’s Third Law ...... 18

2 Chaos in Planetary Motion 19

3 Leapfrog Integration 21 3.1 Euler Integration ...... 21 3.2 Leapfrog Integration ...... 22 3.3 Other Benefits of Leapfrog Integration ...... 24 3.4 Implementation ...... 24 3.5 Numerical Analysis of Accuracy ...... 26

1 4 Determining the Starting Values 30 4.1 The Mean Anomaly ...... 31 4.2 The Eccentric Anomaly ...... 33 4.3 The True Anomaly ...... 35 4.4 The Distance from the ...... 37 4.5 Rotating the Orbit ...... 38

5 Determining Lyapunov Exponents 40 5.1 Implementation ...... 41 5.2 Numerical analysis of the results ...... 42

6 Monte Carlo Optimization 47 6.1 Theory ...... 47 6.2 Implementation ...... 47

7 Results 51 7.1 Gliese 777 ...... 51 7.2 23 Librae ...... 52 7.3 HD 155358 ...... 52 7.4 Kepler 68 ...... 52 7.5 ...... 53

8 Conclusions & Discussion 59 8.1 The extent of similarity to the initial systems . . . . 59 8.2 Possible improvements ...... 60

Acknowledgements 72

A Properties of ellipses 73

B Other Formulae 74

C The Complete Program 75

2 Preface

My interest in the stability of planetary systems was first sparked while I was reading ’17 equations that changed the world’ by Ian Stewart. The fourth equation was Newton’s law of gravitation. The book went on to explain that Newton had used it to prove Kepler’s laws of planetary motion, which were quite familiar to me, but did not give the proof. I was quite frustrated (if you are like me and are frustrated by proofs which are mentioned, but not given, I would like to point you towards chapter 1 and advise you to skip chapter 2). A little later the book mentioned multi-planetary dynamics and I was intrigued. Skip forward a few months and I’m trying to find a good topic for my profielwerkstuk. While leafing through every single book in my room (that’s a lot of books) I came across this chapter again and figured the stability of planetary systems would be a ’pretty cool’ topic and would finally give me a good excuse to take a look at that proof of Kepler’s laws. My first plan was rather vague: I wanted to make a program to determine the stability of a system and calculate ’stuff’ with it. I talked to Simon Portegies Zwart about it, and he pointed me in the direction my profielwerkstuk took in the end and suggested some methods I could use, such as leapfrog integration. After I’d done some research on these methods (and some others) and the theoretical background of the problem I started to write the program. This was a lengthy and at times incredibly frustrating process, but the program worked in the end. I proceeded to write a report of all the interesting things I’d done, which is what you are currently holding in your hands.

3 Introduction

There currently are two main ways of detecting (planets that orbit around other than our ). Firstly, there is the transit method. This method depends on the planet in question blocking the light that we receive from the star. There are a number of constrictions on what planets we can detect using this method: the planet has to pass directly in front of the star, the planet has to be big enough to reduce the amount of light significantly and the planet has to pass in front of the star often enough for us to observe a transit in a limited timespan. Secondly, astronomers can use a phenomenon called a Doppler shift: when an object that emits light, like a star, moves towards or away from us the wavelength of the light that we receive changes. If this wavelength is measured carefully the velocity of the object can be determined. This effect can be used to determine the motion of a star under the influence of an ’s gravity. This method also has some restrictions: the planet has to be massive enough and close enough to the planet to exert a significant force on the planet. In addition to these methods exoplanets can also be observed directly, although this rarely happens. Using these methods a large number of exoplanets has been found: the numbers are currently running in the thousands. These confirmed exoplanets mainly belong to a very specific sub- set of planets, however: they are mostly large, massive and orbit very close to their host stars. Smaller planets on larger orbits are rarely found. This is unfortunate, because these would be very in- teresting to study. A fair number of these planets lie in the so-called habitable zone of their host star: not so close to the star that water evaporates, but not so far away from the star that water freezes. On these planets liquid water (believed to be essential for extraterres- trial life) can exist. Except for finding exoplanets these methods can also be used to

4 determine several characteristics of the exoplanets and their orbits. This gets a lot harder when there are multiple planets in the system, because the dynamics of the system become a lot more complicated. If the system consists of one star and one planet their relative mo- tion obeys Kepler’s laws of planetary motion and the orbit of the planet is periodic and predictable. When there are more planets in the system the gravitational forces from the other bodies in the sys- tem disturb these orbits and the motion becomes chaotic and thus unpredictable. Usually this effect is small: the of the other planets is tiny compared to that of the star, so the gravitational force from those planets is nearly negligible. There are, however, some configurations of systems in which this is not the case. This is the upside of chaos: by ruling out these configurations we can learn a lot about what configurations are possible and likely to occur.

The goal of this project was to find the most stable configura- tion of a planetary system. More concretely: given the mass of a star and the orbital elements of a planet (which remain fixed), what planet(s) should be added to the system to maximize the stability? The first two chapters of this report give (some of) the theoreti- cal background of the problem. The stability was determined by finding lyapunov exponents (chapter 5). The initial conditions of the system were found using an algorithm described in chapter 4. To find the time evolution of the systems (required for determining the lyapunov exponent) the leapfrog algorithm (chapter 3) was used. The lyapunov exponent was minimized using a Monte Carlo method (chapter 6). The results of these calculations are given in chapter 7 and discussed in chapter 8. The orbital elements were taken from five real planetary systems. In these planetary systems the most massive planet has the largest influence on the other objects in the system. For this reason the most massive planet was chosen to act as the fixed planet in the system. Real systems were used so that the results could be compared to reality, which is done in chapter 8.

5 Introductie

Er zijn op het moment twee belangrijke manieren om exoplaneten (planeten in een baan om een andere ster dan de zon) te detecteren. Als eerste is er de transit-methode. Deze methode maakt ervan ge- bruik dat een planeet op een baan rond de ster voor de ster langs beweegt en daarbij een deel van het licht van de ster blokkeert, wat kan worden waargenomen. De planeten die we kunnen detecteren met deze methode moeten wel aan een aantal eisen voldoen: de planeet moet recht voor de ster passeren, de planeet moet groot genoeg zijn om een meetbare hoeveelheid licht te blokkeren en de planeet moet vaak genoeg voor de ster langs bewegen om de transit te kunnen waarnemen in een beperkte periode. Als tweede kunnen sterrenkundigen gebruik maken van een fenoneem dat dopplerver- schuiving heet: als een object dat licht afgeeft, zoals een ster, naar ons toe of van ons af beweegt verandert de golflengte van het licht dat we ontvangen. Als deze golflengte precies genoeg wordt geme- ten kan de snelheid van het object worden bepaald. Dit effect kan gebruikt worden om de beweging van de ster onder invloed van de zwaartekracht van de exoplaneet te bepalen. Ook de planeten die met deze methode gedetecteerd kunnen worden moeten aan een aan- tal eisen voldoen: de planeet moet zwaar genoeg zijn en dicht genoeg bij de ster staan om deze zoveel te laten bewegen dat we het kun- nen waarnemen. Hiernaast kunnen exoplaneten ook direct worden waargenomen, hoewel dit weinig voorkomt. Door gebruik te maken van deze methodes is er een groot aantal exoplaneten gevonden: het aantal loopt in de duizenden. Deze planeten behoren echter voornamelijk tot een specifieke sub- set van planeten: ze zijn grotendeels groot en zwaar en bewegen op banen dichtbij hun ster. Kleinere planeten op grotere banen worden nauwelijks gevonden. Dit is jammer, want dit soort planeten is uit- zonderlijk interessant. Een deel van deze planeten ligt namelijk in

6 de leefbare zone: niet zo dicht bij de ster dat water verdampt en niet zo ver van de ster af dat water bevriest. Op deze planeten kan dus vloeibaar water, wat essentieel is voor buitenaards leven, aanwezig zijn. Behalve om exoplaneten te vinden kunnen deze methodes ook worden gebruikt om eigenschappen van de exoplaneten en hun ba- nen te bepalen. Dit wordt echter een stuk lastiger als er meerdere planeten in het stelsel aanwezig zijn, omdat de beweging van de planeten ingewikkelder wordt. Als het stelsel bestaat uit een ster en n planeet voldoet de beweging van de ster en de planeet aan de wetten van Kepler en is deze periodiek en voorspelbaar. Als er meer planeten aanwezig zijn wordt deze beweging verstoord door de zwaartekracht van de andere planeten en wordt deze chaotisch en onvoorspelbaar. Dit effect is meestal klein: vergeleken met de massa van de ster is de massa van de planeten zo klein dat de zwaartekracht afkomstig van deze bijna verwaarloosbaar is, maar er bestaan con- figuraties van planeten waarin dat niet zo is. Dit is meteen ook een voordeel van de chaos: door alleen naar stabiele (of nauwelijks chaotische) stelsels te kijken kunnen we veel leren over mogelijke configuraties van het stelsel.

Het doel van dit profielwerkstuk was het vinden van de meest stabiele configuratie van een planetenstelsel. Concreter: als de massa van een ster en de baan van een exoplaneet bekend zijn, hoe moeten daar nieuwe planeten aan worden toegevoegd om de sta- biliteit te maximaliseren? De eerste twee hoofdstukken laten (een deel van) de theoretische achtergrond van het probleem zien. De stabiliteit van de stelsels werd bepaald met behulp van lyapunov exponenten (zie hoofdstuk 5). De beginvoorwaarden van het sys- teem werden bepaald met een algoritme dat wordt beschreven in hoofdstuk 4. Om de ontwikkeling van het systeem (nodig voor de bepaling van de lyapunov exponent) te bepalen is gebruik gemaakt van leapfrog integratie (zie hoofdstuk 3.5). De lyapunov exponent werd vervolgens geminimaliseerd met een Monte Carlo methode (zie hoofdstuk 6). De resultaten van deze berekeningen worden gegeven in hoofdstuk 7 en besproken in hoofdstuk 8. De gegevens van de banen van de planeten die werden gebruikt in de berekening zijn overgenomen van bestaande planetenstelsels. Omdat de zwaarste planeet in een planetenstelsel in het algemeen de meeste invloed

7 heeft op het stelsel werd deze steeds genomen als de beginplaneet. De gegevens van echte planetenstelsels werden gebruikt zodat de re- sultaten vergeleken konden worden met de werkelijkheid. Dit wordt gedaan in hoofdstuk 8.

8 Chapter 1

Kepler’s Laws of Planetary Motion

Kepler’s laws concerning the motion of planets around the sun were published by Kepler in 1609. They are stated as follows: 1. The orbit of a planet around the Sun is an ellipse with the Sun at one of the foci. 2. A line segment joining a planet and the Sun sweeps out equal areas in equal intervals of time. 3. The square of a planet’s is proportional to the cube of the semi-major axis of its orbit.

1.1 Newton’s Law of Gravitation

Planets orbit the sun under influence of the Sun’s gravitation. The gravitation force is described by the following equation, which was discovered by Newton in 1687: Mm F = −G r (1.1) |r|3 Where F is the force on the planet, M is the mass of the Sun, m is the mass of the planet and r is the distance between the Sun and the planet. We will assume that m is negligible compared to M, although the proof can easily be extended to include a non-negligible mass m. Equally important is Newton’s second law: F = ma (1.2)

9 Where a is the acceleration of the planet.

1.2 Some Definitions

To proof Kepler’s laws we must define some useful quantities: the momentum, the angular momentum and the total energy. As it turns out, the last two of these are conserved.

1.2.1 Momentum An object’s momentum p is defined as mv. A useful relationship is found when differentiating the momentum. When we do this we get p˙ = mv˙ = ma, which, as it happens, is equal to the force on the object. In the case of planets orbitting around a star this can be k further expanded to p˙ = F = − |r|3 r by Newton’s law of universal gravitation.

1.2.2 Angular Momentum The angular momentum L is defined as p × r. In a central forcefield (F is always proportional to r) this quantity is conserved. We can show this by differentiating the angular momentum with respect to time. L˙ = p˙ × r + p × r˙ = F × r + mv × v = 0 + 0 = 0 (1.3) Both F × r and mv × v are equal to 0, because both F and r, and mv and v are proportional to each other. This means the vector L is constant. Now we can proof the first part of Kepler’s second law: the motion of a planet around a star is contained to one plane. r, the position of the planet, is by definition always orthogonal to L. This means that r lies in the plane with normal L.

1.2.3 Total Energy

k 1 2 We will define the total energy H as − |r| + 2 m|v| . This is equal 1 k p to m(v · v) − 1 . We can now write v as . This gives H = 2 (r·r) 2 m 1 p p k p·p k m( · ) − 1 = − 1 . To proof that this quantity is 2 m m (r·r) 2 2m (r·r) 2

10 conserved, we need to prove that its derivative with respect to time is equal to 0. p˙ · p + p · p˙ 1 k p˙ · p k(r˙ · r) ˙ ˙ ˙ H = + 3 · (r · r + r · r) = + 3 2m 2 (r · r) 2 m |r|

k Substituting p˙ = F and F = − |r|3 r gives: F · p k 1 k k k k H˙ = + (v·r) = ·− r·mv+ (r·v) = − (r·v)+ (r·v) = 0 m |r|3 m |r|3 |r|3 |r|3 |r|3 (1.4) Kepler’s laws describe systems with a negative total energy.

1.3 Kepler’s First Law

1.3.1 A Closer Look at the Total Energy By looking at the total energy of the system we can tell a few in- 1 2 teresting things. First of all, we note that 2 m|v| ≥ 0. This implies k k 1 2 k that − |r| ≤ − |r| + 2 m|v| . From this we can conclude that −H ≤ |r| . Ultimately, this line of thought gives the following relation: k |r| ≤ − (1.5) H p Secondly, substituting v = m into the total energy gives us a useful formula for the absolute value of p. 1 k 1 k 1 p p k |p|2 k H = m|v|2 − = m(v·v)− = m( · )− = − 2 |r| 2 |r| 2 m m |r| 2m |r| |p|2 k = H + 2m |r| k |p|2 = 2m(H + ) (1.6) |r| This formula will come in handy later.

1.3.2 The Laplace-Runge-Lenz Vector We will now define the Laplace-Runge-Lenz vector as K = p × L − km |r| r. This vector plays a large role in proofing Kepler’s first law.

11 Firstly we will show that this vector lies in the same plane as the planet’s orbit, by proofing that K · L equals 0. km km K · L = (p × L − r) · L = L · (p × L) − L · r (1.7) |r| |r| L · (p × L) is equal to zero, because p × L is orthogonal to L. km km K · L = 0 − (r × p) · r = −( r × r) · p (1.8) |r| |r| km km |r| r × r is equal to the zero vector, because |r| r and r are propor- tional to each other. We find the following: K · L = 0 · p = 0 (1.9) Secondly we will proof that the Laplace-Runge-Lenz vector is constant by taking the derivative. km km(r˙ · r) K˙ = p˙ × L + p × L˙ − r + r |r| |r|3 km km(r · v) = F × (r · p) + p × 0 − v + r |r| |r|3 k k(r · p) = (F · p)r − (F · r)p − p + r |r| |r|3 k k k k(r · p) = (− r · p)r − (− r · r)p − p + r |r|3 |r|3 |r| |r|3 k(r · p) k k k(r · p) = − r + ( |r|2)p − p + r |r|3 |r|3 |r| |r|3 k k = − p + p |r| |r| = 0 (1.10)

1.3.3 Kepler’s First Law

k We saw in section 1.3.1 that |r| ≤ − H (equation 1.5). This means that the orbit of the planet is contained in a circle C with radius k k − H . Note that − H is positive because the total energy is negative. Using this circle, we can define some more vectors. First of all, the vector s, which we will define as the projection of r onto the circle

12 k C. This vector, then, is equal to − |r|H r. Second, the vector t, the reflection of s in the line through r in the direction of v. Third, the vector n, p × L.

Figure 1.1: The vector r, v, s, t and n.

We will now try to relate the vector t to the aforementioned quantities and vectors, most importantly the Laplace-Runge-Lenz vector. First we note that, by our definition, 2((s − r) · n) t =s − n (1.11) |n|2 (see Appendix B) To simplify this equation we will break it into parts and considers

13 those separately at first. We’ll begin with (s − r) · n. k (s − r) · n = (− r − r) · n |r|H k = (− )(r · n) |r|H k = −(1 + )(r · (p × L)) |r|H k = −(1 + )((r × p) · L) |r|H k = −(1 + )(L · L) |r|H k = −(1 + )|L|2 |r|H k |L|2 = −(H + ) (1.12) |r| H Next, we will look at |n|2. k |n|2 = |p × L|2 = |p|2|L|2 = 2m(H + ) |L|2 | {z } |r| because p and L are orthogonal, see Appendix B | {z } by equation 1.6 (1.13) Combining these two, we get the following equation for t:

2 2(−(H + k ) |L| ) t = s − |r| H n k 2 2m(H + |r| )|L| k 1 = − r + n |r|H mH 1 km 1 = r + (p × L) mH |r| mH 1 = K (1.14) mH Next we will proof that the position of t never changes, by taking the derivative: 1 1 t˙ = K˙ = 0 = 0 (1.15) mH mH |{z} by equation 1.10

14 We can now proof that r forms an ellipse. We will do this by showing that the sum of the distances from r to two foci, which turn out to be o and t, is constant (see Appendix A, properties of ellipses). k |r−o|+|t−r| = |r−o|+|s−r| = |s − o| = − | {z } H because r lies on the line between o and s (1.16) k r thus forms an ellipse with foci o and t and semi-major axis − 2H .

1.4 Kepler’s Second Law

Kepler’s second law is significantly simpler to prove. We will look at the function O(t), which we will define as the area swept out by the line connecting the star and the planet since a given time t0. To proof Kepler’s second law it will suffice to show that the derivative of this function is constant. By the definition of the derivative, the following equation holds: O(t + h) − O(t) O0(t) = lim (1.17) h→0 h Notably, the numerator is (for small h) equal to the area of the triangle defined by the points o, r(t) and r(t+h). This area is equal to one half the area of the parallelogram defined by the points o, r(t), r(t+h) and r(t+h)−r(t) which is equal to |r×(r(t+h)−r(t))|. We find the following: 1 O0(t) = lim |r(t) × (r(t + h) − r(t))| h→0 2h 1 r(t + h) − r(t) = lim |r(t) × | h→0 2 h 1 1 = |r × r˙| = |r × v| (1.18) 2 2 We now only need to show that r × v is constant: (r×v)˙= r˙×v+r×v˙ = v×v+r×a = 0+ 0 = 0 |{z} because r and a are proportional (1.19)

15 This suffices to prove Kepler’s second law, but because we will need it later we’ll also derive a formula for O(t): Z t Z t 0 1 1 t 1 O(t) = O (t) dt = |r×v| dt = [ |r×v|t]t0 = |r×v|(t−t0) t0 t0 2 2 2 (1.20)

1.5 Kepler’s Third Law

1.5.1 The Area of the Ellipse We’ll proof Kepler’s third law by looking at the area swept out by the planet in one orbit. We will call this area A. In section 1.3 we have shown that the planet orbits around the star in an ellipse. We can now use the equation A = πab, where a denotes the semi-major axis, and b denotes the semi-minor axis, to determine the area A. In section 1.4 we found another formula for the area swept out by the planet. Filling in in the orbital period, which we’ll call T , will allow us to find the area A. When we have these two formulae we can combine them to produce Kepler’s third law. First of all we will rewrite equation 1.20: 1 1 p 1 |L| O(t) = |r×v|(t−t ) = |r× |(t−t ) = |r×p|(t−t ) = (t−t ) 2 0 2 m 0 2m 0 2m 0 (1.21) Filling in t0 = 0 and t = T gives the following: |L|T A = = πab (1.22) 2m Squaring equation 1.22 gives the following: |L|2T 2 = π2a2b2 4m2 T 2 π24b2m2 = (1.23) a2 |L|2

16 1.5.2 The Semi-minor Axis To make use of equation 1.23 we need to find 4b2. To find 4b2 we will make use of the following formula: b2 = a2 − c2 4b2 = 4a2 − 4c2 (1.24) (see Appendix A) The c in this formula denotes the focal length: the distance from the centre of the ellipse to either one of the foci. In this case the distance from one focus to the other, twice the focal length, is the 1 2 distance between o and t. This distance equals | mH K|. 4c , then, 1 2 1 2 is equal to | mH K| = m2H2 |K| . In order to continue with this line of thought we must find |K|2. |K|2 = K · K km km = (p × L − r) · (p × L − r) |r| |r| km km km km = (p × L) · (p × L) − (p × L) · r − r · (p × L) + r · r |r| |r| |r| |r| 2km k2m2 = |p × L|2 − (r · (p × L)) + (r · r) |r| |r|2 2 2 2 2 2 2km k m |r| = |p| |L| − |(r × p) · L + 2 | {z } |r| |r| because p and L are orthogonal 2km 2km = (2mH + ) |L|2 − (L · L) + k2m2 |r| |r| | {z } see equation 1.6 2km 2km = 2mH|L|2 + |L|2 − |L|2 + k2m2 |r| |r| = 2mH|L|2 + k2m2 (1.25) We can now continue with our line of thought. 1 2mH|L|2 + k2m2 2|L|2 k2 4c2 = |K|2 = = + (1.26) m2H2 m2H2 mH H2 To use equation 1.24 we must also find 4a2. In section 1.3.3 we k 2 2k 2 4k2 found that a is equal to − H . 4a ,then, is equal to (− H ) = H2 . We

17 can now find 4b2. k2 2|L|2 k2 2|L|2 4b2 = 4a2 − 4c2 = − − = − (1.27) H2 mH H2 mH

1.5.3 Kepler’s Third Law We can now substitute equation 1.27 into equation 1.23. T 2 π2m · −2|L|2 2π2m = = − (1.28) a2 |L|2mH H

k 1 As noted before 2a equals − H . From this we conclude that H = a −2 k . Filling this in gives the following: T 2 2π2m · 2a = a2 k T 2 4π2m = (1.29) a3 k All that remains in order to find Kepler’s third law is to substitute k = GMm: T 2 4π2 = (1.30) a3 GM

18 Chapter 2

Chaos in Planetary Motion

Now we turn our attention to the n-body problem of n bodies moving under the influence of gravity. This system obeys the following equations: X mimj ¨ri = −G 3 (ri − rj) (2.1) 2 i6=j |ri − rj|

Where ri is the position of the ith body and mi its mass. Because this is a very complex problem, we’ll only look at a simplified ver- sion of it: the planar circular restricted three-body problem.

The planar restricted circular three-body problem (PCR3BP for short) concerns the circular motion of two and a third body of negligible mass contained in one plane. The first two bodies follow a Keplerian orbit, but the third one does not. For simplicity’s sake we’ll set the gravitational constant G to be one, as well as the angular velocity ω and the total mass. If we take the mass of the first body to be µ, this makes the mass of the second body 1 − µ. We’ll also choose the origin so that it coincides with the centre of mass. Setting the gravitational attraction between the bodies equal to the centripetal force required to keep them in their orbits the bodies are found to obey the following equations: 1 − µ − 2 = −r1 (1+r2) µ − 2 = −r2 (2.2) (r1 + r2)

2 µ We use the second equation to find that (r1 + r2) = . Filling this r2

19 in in the first equation gives the following: 1 − µ µ = (2.3) r1 r2

We note that r1 = 1 − µ and r2 = 1 − µ satisfies this. Before we get started with the third body we’ll move to a rotating coordinate system with ω = 1 in which the first two bodies stay fixed at (−µ, 0) and (1 − µ, 0). x and y designate the position of the third body in this reference frame. The potential energy of the third body is given by: 1 1 − µ µ E = − (x2 + y2) − − (2.4) 2 p(x + µ)2 + y2 p(x + µ − 1)2 + y2 Figure 2.1 gives a contour plot of the potential energy for µ = 0.9. There are five points at which the potential energy is stationary. These are known as the Lagrange points. L1, L2 and L3 (on the x- axis) are situated at saddle points: a local maximum in one direction and a local minimum in the other direction. This means that L1, L2 and L3 are unstable. L4 and L5 form equilateral triangles with the two primary bodies. They are stable.

Figure 2.1: Contour plot of the potential energy for µ = 0.9

The PCR3BP also allows for periodic orbits. It was proven by Henri Poincar´ethat these orbits are chaotic (Poincar´e1892-1899).

20 Chapter 3

Leapfrog Integration

In order to analyse the stability of a system, we’ll need to know how the system evolves. The equations of motion can’t be solved analytically, so we’ll have to numerically approximate a solution. To do this we need an integration scheme. We’ll assume we know the following things: the initial position and velocity of all the particles in the system and a function y00(t) which we can use to determine the acceleration of a particle.

3.1 Euler Integration

A commonly used integration scheme is called Euler integration. It consists of the following equations used to update the position and velocity, where y(t) indicates the position of the particle at time t and ∆t is the time step used when integrating.

0 y(tn+1) = y(tn) + ∆t y (tn) 0 0 00 y (tn+1) = y (tn) + ∆t y (tn) (3.1) This is a first-order integration method, meaning that the error be- tween the exact solution and the result of the integration is propor- tional to ∆t. This result can be obtained by determining the error at each individual time step and adding these together. First we’ll introduce some notation: we’ll use τ to refer to the error at every time step, commonly known as the local truncation error, y(t) will denote the exact solution and A(y(tn)) the approximation to y(tn+1) obtained by the integration scheme described in equation 3.1. First

21 we’ll have to find A(y(tn+1)). 0 A(y(tn)) = y(tn) + ∆t y (tn) (3.2)

We’ll approach y(tn+1) using a Taylor series around tn. 1 y(t ) = y(t + ∆t) = y(t ) + ∆t y0(t ) + ∆t2 y00(t ) + O(∆t3) n+1 n n n 2 n (3.3) To find the local truncation error τ we simply have to subtract equation 3.2 from equation 3.3. This gives the following:

τ = y(tn + ∆t) 1 = y(t ) + ∆t y0(t ) + ∆t2 y00(t ) − y(t ) + ∆t y0(t ) n n 2 n n n 1 = ∆t2 y00(t ) + O(∆t3) (3.4) 2 n We conclude that leading term of the local truncation error is pro- portional to ∆t2. The global truncation error is equal to the number of timesteps multiplied by the local truncation error. Given a total T time T , the number of timesteps equals ∆t . We conclude that the 2 1 global truncation error is proportional to ∆t · ∆t = ∆t

3.2 Leapfrog Integration

The Euler integration method is very simple, which speaks for it, but is turns out to be very easy to increase the order of the integra- tion method without loss of simplicity or an increase in the amount of function evaluations. The Leapfrog integration method doesn’t evaluate the velocity at the same time as the position, but halfway in between evaluations of the position. This gives the following al- gorithm: 0 y(tn+1) = y(tn) + ∆t y (t 1 ) n+ 2 0 0 00 y (t 3 ) = y (t 1 ) + ∆t y (tn+1) (3.5) n+ 2 n+ 2 The analysis of this algorithm is slightly more complicated. First of all, we’ll need to use a Taylor expansion in t 1 . n− 2

0 1 2 00 1 3 000 4 y(tn− 1 +h) = y(tn− 1 )+hy (tn− 1 )+ h y (tn− 1 )+ h y (tn− 1 )+O(h ) 2 2 2 2 2 6 2 (3.6)

22 We’ll use this equation to find the difference between y(tn) and y(tn+1). 1 y(tn) = y(tn− 1 + ∆t) 2 2 1 0 1 2 00 = y(tn− 1 ) + ∆t y (tn− 1 ) + ∆t y (tn− 1 ) 2 2 2 8 2 1 3 000 4 + ∆t y (tn− 1 ) + O(∆t ) (3.7) 24 2

3 y(tn+1) = y(tn− 1 + ∆t) 2 2 3 0 9 2 00 = y(tn− 1 ) + ∆t y (tn− 1 ) + ∆t y (tn= 1 ) 2 2 2 8 2 27 3 000 4 + ∆t y (tn− 1 ) + O(∆t ) (3.8) 24 2

0 2 00 y(tn+1) − y(tn) =∆t y (t 1 ) + ∆t y (t 1 ) n− 2 n− 2 13 3 000 4 + ∆t y (tn− 1 ) + O(∆t ) (3.9) 12 2 Next we look at the difference the algorithm predicts.

0 A(y(tn)) = y(tn) + ∆t y (t 1 ) n+ 2 0 00 = y(tn) + ∆t(y (t 1 ) + ∆t y (t 1 )) n− 2 n− 2 0 2 00 = y(tn) + ∆t y (t 1 ) + ∆t y (t 1 ) (3.10) n− 2 n− 2

0 2 00 A(y(tn + 1)) − y(tn) = ∆t y (t 1 ) + ∆t y (t 1 ) (3.11) n− 2 n− 2 This gives the following local truncation error:

τ = y(tn+1) − A(y(tn)) = y(tn+1) − y(tn) − A(y(tn)) + y(tn)

13 3 000 4 = ∆t y (tn− 1 ) + O(∆t ) (3.12) 12 2 The leading term of which is proportional to ∆t3. As before, multi- 1 plying by ∆t gives the global truncation error, which is thus propor- tional to ∆t2, making Leapfrog integration a second-order algorithm. 0 From now on we’ll refer to y(tn) as rn, to y (t 1 ) as v 1 and n+ 2 n+ 2 00 to y (tn) as an.

23 3.3 Other Benefits of Leapfrog Integration

Leapfrog has a few other good qualities besides being second-order. First of all, it is time-reversible. We can show this by solving equa- tions 3.5 for rn and v 1 n+ 2

rn = rn+1 − ∆t v 1 n+ 2 v 1 = v 3 − ∆t an (3.13) n+ 2 n+ 2 Which of the same form as equations 3.5. Secondly Leapfrog con- serves the angular momentum L = r × v exactly. Thirdly the al- gorithm is stable, in that it tends to correct its mistakes instead of amplifying them. This is clearly seen in the figures in section 3.5. In these figures we see that the error increases in the beginning, and then starts oscillating around a straight line.

3.4 Implementation

The backbone of the program is the System class, which contains a list of objects in the system and keeps track of variables like the time and the total mass. It also contains a number of methods to add planets and stars to the system and simulate its evolution. All objects in the system are represented as instances of the Object class: #Class for planets/stars class Object: def i n i t (self ,position ,velocity ,mass): #position and velocity as numpy arrays self .r=position self .v=velocity self .m=mass def integrate(self): s e l f . r+=dt∗ s e l f . v s e l f . v+=dt∗ s e l f . a def plot(self): x.append(self .r[0]) y.append(self .r[1]) z.append(self .r[2])

24 The Object class keeps track of the mass, position and velocity of the object and contains the method for plotting the planet and for the leapfrog integration. Usually the first step in Leapfrog would be finding v 1 using Euler integration using initial values r0 and v0 with 2 ∆t step size 2 (because it’s only run once this wouldn’t influence the order of the method), but because the algorithm used to find the initial values described in chapter 4 only gives r, but can be used to find the position at different times, it was found to be easier to run the algorithm twice, once at t = t0 and once at t = t0 + ∆t and use the first formula in equations 3.5 to find v 1 : 2

r0+∆t − r0 v 1 = (3.14) 2 ∆t The acceleration is found by calculating the gravitational force act- ing on an object and dividing this by the mass of the object. Because this also requires information from the other objects in the system this is done by a method of the System class: def calcForces(self): for object in self.objects: object.a=np.array([0,0,0], float) a=len(self .objects) for i in range(a): for j in range(a): i f i>j : dr=self.objects[i ].r−s e l f . objects[j].r k=dr∗G/(np.dot(dr,dr) ∗∗(3/2) ) self .objects[i ].a+=−self .objects [ j ] .m∗k self .objects[j ].a+=self .objects[ i ] .m∗k Firstly, the method resets the acceleration of all the objects in the system. Secondly, it loops over all pairs of objects and calculates the G distance r between them. It uses this method to find |r|3 r. Thirdly, it multiplies this the mass of the other object, for both objects in the pair, and adds it to their acceleration. def integrate(self ,toplotornottoplot): self .calcForces()

25 for object in self.objects: object.integrate() if toplotornottoplot: object.plot() def simulate(self): self.state() while self.n

3.5 Numerical Analysis of Accuracy

The following figures show the error of the orbit obtained by leapfrog integration compared to the exact orbit at different dt’s. The system simulated is the sun- system, with a solar mass of 1.98855 · 1030 kg and a planetary mass of 1.8986 · 1027 kg. Jupiter’s orbit has a semi-major axis of 778547200 · 103 m, an eccentricity of 0.048775 and an inclination of 0.00559 rad. The longitude of the ascending node is 1.7539 rad and the is 4.801 rad (see chapter 4). The exact orbit was calculated using the method de- scribed in chapter 4, starting at the perihelion. To run the analysis the simulate() method of the System class was altered slightly: def simulate(self):

26 while self.n

Figure 3.1: Error in the results of Leapfrog integration, dt = 50000

27 Figure 3.2: Error in the results of Leapfrog integration, dt = 40000

Figure 3.3: Error in the results of Leapfrog integration, dt = 30000

28 Figure 3.4: Error in the results of Leapfrog integration, dt = 20000

Figure 3.5: Error in the results of Leapfrog integration, dt = 10000

29 Chapter 4

Determining the Starting Values

Figure 4.1: The orbital elements. From: http://en.wikipedia.org/wiki/Orbital elements.

Now that we have a way of predicting the motion of planets, given the initial position and speed, we need to find these initial conditions. We will consider as given the orbital elements: the ec- centricity ε, the semi-major axis a, the inclination i, the longitude of the ascending node Ω and the argument of periapsis ω. These

30 describe the shape and position of the orbit. The eccentricity and semi-major axis define the shape of the ellipse. The inclination, the longitude of the ascending node and the argument of periapsis de- fine its orientation in space. The inclination of the orbit is defined as the angle between the orbital plane and the reference plane. The longitude of the ascending node is the angle between a reference direction (that lies in the reference plane) and the ascending node, the place where the planet passes upwards through the reference plane. The argument of periapsis, finally, gives the angle between the ascending node and the periapsis, the point on the orbit that is closest to the star. Also given are the masses of the star (M) and the planet (m), and the time since perihelion t0, the point in time where the planet passed though the periapsis. From these givens we will be able to find the initial position of the planet. We will find the initial speed of the planet by calculating the position of the planet twice: once at t = t0 (which will give us r0−∆t) and once at t = t0 + ∆t (which will give us r0). We can then find the speed by using the following formula:

r0 − r0−∆t v 1 ∆t = (4.1) 2 ∆t An added benefit of this method is that is immediately gives us the 1 speed at t = 2 ∆t, which we need for the leapfrog integration, and not at t = 0. We will use the plane z = 0 as our reference plane, and the unit vector in the x-direction as our reference direction. We’ll assume the star to be located at the origin. The method used to determine the starting values has a number of steps. The first three of these calculate angles: the mean anomaly, the eccentric anomaly and the true anomaly. The fourth computes the distance from the star to the planet and the last rotates the orbit to the right orientation.

4.1 The Mean Anomaly

We begin by determining the mean anomaly. First of all we draw a circle with radius a around the centre of the ellipse (C in figure 4.2). Secondly, we project P , the position of the planet, onto this circle. We call the resulting point X. Thirdly we find the point Y so

31 [h]

Figure 4.2: An overview of the situation: with C, the centre of the ellipse, S, the position of the star, P , the position of the planet,Z, the periapsis. X, the projection of P onto the circle, d, the projection of P onto ZC, and Y . that the sector areas ZSX (where S is the position of the star) and ZCY are equal. We define the mean anomaly M to be the angle ZMY . We can find this angle by looking at the two sector areas. The sector a2M area ZCY is given by 2 (see Appendix B). This area is equal to the sector area ZSX. But this sector area is a stretched-out version a (by factor b )of sector area ZSP , which, by Kepler’s second law, is proportional to the time since perihelion. We find the following: b b b a2M abM |ZSP | = |ZSX| = |ZCY | = = = nt (4.2) a a a 2 2 0

We know that M equals 0 at t0 = 0. One orbital period later, at t0 = T (where T is the orbital period), M equals 2π. We conclude the following: 2π − 0 2π M(t ) = t = t (4.3) 0 T − 0 0 T 0

32 We can find T by making use of Kepler’s third law (see section 1.5): T 2 4π2 = a3 GM r 4π2a3 T = (4.4) GM

#determining orbital period (via Keplers third law ) T=((4∗np . pi ∗∗2∗a ∗∗3) /(G∗ s e l f .m) ) ∗∗(1/2) global ttotal g l o b a l dt g l o b a l dp t t o t a l =5∗T dt=T/1500 dp=10∗dt #determening mean anomaly M1=(2∗np . pi ∗ t /T) %(2∗np . pi ) M2=(2∗np . pi ∗(t+dt)/T)%(2∗np . pi ) Above is the code used to compute the mean anomaly. The program first computes the orbital period (T) using the semi-major axis (a) and the mass of the star (self.m). It then computes the mean anomaly using the method described. The orbital period is also used to define T, dt and dp (see section 5.2).

4.2 The Eccentric Anomaly

The second step is concerned with determining the eccentric anomaly E, which is defined as the angle ZCX. To find this angle we need to look at sector areas once more: |ZCY | = |ZSX| = |ZCX| − |SCX| (4.5)

a2M We saw before that |ZCY | is equal to 2 . By the same logic |ZCX| a2E is equal to 2 . |SCX| is easy to find: SCX is a triangle with base CS and height Xd. CS is equal to εa (see Appendix A). Xd is equal

33 Figure 4.3: The eccentric anomaly.

aε·a sin E to a sin E. This makes |SEX| equal to 2 . In conclusion: a2M a2E a2ε sin E = − 2 2 2 M = E − ε sin E (4.6)

This equation, known as Kepler’s equation, can unfortunately not be solved algebraically. However, after rewriting it to E−ε sin E−M = 0, we can use Newton’s method to find a good approximation for E: f(E) = E − ε sin E − M f 0(E) = 1 − ε sin E

En − ε sin En − M En+1 = En − (4.7) 1 − ε sin En

#determening eccentric anomaly (via Newton− Raphson ) i f M1==0 or M1==np . pi or M1==2∗np . pi : E1=M1

34 e l s e : i f e >0.8: ENR=[0,np.pi] #two values so that while− loop will work e l s e : ENR=[0,M1] #two values so that while− loop will work while not abs(ENR[−1]−ENR[ −2]) <10∗∗−8: E=ENR[ −1] ENR. append((E−(E−e∗ma. s i n (E)−M1) /(1−e∗ma .cos(E)))%(2∗np . pi ) ) E1=ENR[ −1] i f M2==0 or M2==np . pi or M2==2∗np . pi : E2=M2 e l s e : i f e >0.8: ENR=[0,np.pi] #two values so that while− loop will work e l s e : ENR=[0,M2] #two values so that while− loop will work while not abs(ENR[−1]−ENR[ −2]) <10∗∗−8: E=ENR[ −1] ENR. append((E−(E−e∗ma. s i n (E)−M2) /(1−e∗ma .cos(E)))%(2∗np . pi ) ) E2=ENR[ −1] Above is the code used to compute the eccentric anomaly. It first checks for cases in which equation 4.6 can be solved exactly. If this is not the case, checks the eccentricity and determines what value E is most likely to be close to and uses this as a starting point for Newton’s method. It continues with Newton’s method until the last two values for E are within a certain range from each other.

4.3 The True Anomaly

We now need to find the true anomaly. The true anomaly (θ) is defined as the angle ZSP . We note from the figure that Cd =

35 Figure 4.4: The true anomaly.

CS + Sd. This gives us the following equations: a cos E = aε − r cos θ r cos E = ε − cos θ (4.8) a

r 1−ε2 We know, from Kepler’s first law (see section 1.3), that a = 1+ε cos θ (see Appendix A). Filling this in gives us the following equation: 1 − ε2 cos E = ε − cos θ 1 + ε cos θ ε(1 + ε cos θ) + (1 − ε2) cos θ = 1 + ε cos θ ε + ε2 cos θ + cos θ − ε2 cos θ = 1 + ε cos θ ε + cos θ = (4.9) 1 + ε cos θ

36 Solving this equation gives the following: ε + cos θ cos E = 1 + ε cos θ (1 + ε cos θ) cos E = ε + cos θ cos E + ε cos θ cos E = ε + cos θ (ε cos E − 1) cos θ = ε − cos E ε − cos E cos θ = (4.10) ε cos E − 1

#determining true anomaly i f ( t /T) %1<0.5: th1=ma. acos ( ( e−ma.cos(E1))/(e∗ma. cos (E1) −1) th2=ma. acos ( ( e−ma.cos(E2))/(e∗ma. cos (E2) −1)) e l s e : th1=−ma. acos ( ( e−ma.cos(E1))/(e∗ma. cos (E1) −1) ) th2=−ma. acos ( ( e−ma.cos(E2))/(e∗ma. cos (E2) −1) ) Above is the code used to determine the true anomaly. Because cos φ = c has more than one solution, it first has to check which solution it should use by determining whether the planet is in the first or the second half of its orbit. After it’s done that it uses equation 4.10 to calculate the true anomaly.

4.4 The Distance from the Star

1−ε2 Recalling that r = a· 1+ε cos θ (see Appendix A), we can now find the distance from the planet to the star. Given this r and θ it is a simple matter to convert these polar coordinates to Cartesian coordinates:  cos θ  r = r ·  sin θ  (4.11) 0

The code below implements this: #determening distance to star ar1=a∗(1−e ∗∗2) /(1+e∗ma.cos(th1))

37 ar2=a∗(1−e ∗∗2) /(1+e∗ma.cos(th2))

#converting polar to cartesian coordinates r1=np.array ([ar1 ∗ma.cos(th1) ,ar1 ∗ma. s i n ( th1) ,0],float) r2=np.array ([ar2 ∗ma.cos(th2) ,ar2 ∗ma. s i n ( th2) ,0],float)

4.5 Rotating the Orbit

Now that we have found the orbit and the planet’s position on this orbit we only need to rotate the orbit and the planet so that its orientation corresponds with the given inclination, longitude of the ascending node and argument of periapsis. We’ll assume that, at first (before we started rotating), the ascending node lies in our reference direction (the x-axis). The argument of periapsis (ω), then, is simply a rotation around the z-axis. This rotation is given by the following matrix, which we’ll call A: cos ω − sin ω 0 A = sin ω cos ω 0 (4.12) 0 0 1

We now need to apply the inclination. As the inclination is a rota- tion around the ascending node and we have assumed the ascending node to lie in our reference direction, this is simply a rotation around the x-axis, given by the following matrix B: 1 0 0  B = 0 cos i − sin i (4.13) 0 sin i cos i

It is now time to apply the longitude of the ascending node. As the ascending node stays in the reference plane (the x,y-plane), this again is a rotation around the z-axis, given by the matrix C: cos Ω − sin Ω 0 C = sin Ω cos Ω 0 (4.14) 0 0 1

38 Finally we take the matrix product CBA of these matrices and apply it to r. This gives us the initial position of the planet. The code below shows this. #matrix for applying argument of periapsis A=np.array ([[ma.cos(w) ,ma. sin(w) ,0],[ −ma. s i n (w) , ma.cos(w) ,0],[0,0,1]],float)

#matrix for applying inclination B=np.array([[1 ,0 ,0] ,[0 ,ma.cos(i),−ma.sin(i)],[0, ma.sin(i),ma.cos(i)]] , float)

#matrix for applying longitude of ascending node C=np.array ([[ma.cos(o) ,ma. sin(o) ,0],[ −ma. s i n ( o ) , ma.cos(o) ,0],[0,0,1]],float)

#matrix for applying inclination , lonitude of ascending node and argument of periapsis R=np.dot(C,np.dot(B,A))

#applying R r1=np.dot(R,r1) r2=np.dot(R,r2) Finally we need to determine the initial speed. It is for this reason that we calculated the position at both t and t + ∆t. The speed is now given by: r1 − r0 v 1 = (4.15) 2 ∆t The code below performs this calculation and subsequently creates the object and adds it to the system. #determining speed v=(r2−r1 ) / dt

#creating planet self .objects.append(Object(r2 ,v,m))

39 Chapter 5

Determining Lyapunov Exponents

We now have to find the lyapunov exponent, which is commonly used to measure instability. The theory states that, in chaos cir- cumstances, the difference between two solutions which were initially close to each other will increase exponentially with time. We’ll find this exponent by taking the system we want to find the lyapunov exponent for, change it slightly and look at the difference between the system and the changed system after some time. According to λt the theory, this should be r0e , where r0 is the initial difference and λ is the lyapunov exponent. After we’ve done this a number of times, we need to find the λ that fits the results best. First, we’ll assume that r0 equals 1. Next, we’ll take the natural logarithm of both sides of the equation. This gives the following: ln r = λt (5.1)

We’ll represent our results as a set of xi and yi, where xi is t, and r yi is ln r (or ln if we don’t set r0 to be 1). This data should fit r0 an equation of the form yi = λxi. To find the optimal fit we first have to quantify the error between the data and the fitted line. Our first thought is to define this as the sum of all yi − λxi, but this doesn’t work, because yi − λxi could be both negative and positive and the errors might cancel out. To solve this problem, we square the difference. This gives the following definition of the error:

X 2 Error = (yi − λxi) (5.2)

40 We now need to find the λ which minimizes this. To do this, we differentiate with respect to λ and set the derivative equal to zero: d X X (y − λx )2 = 2x (y − λx ) = 0 dλ i i i i i X 2 xiyi − λxi = 0 X X 2 xiyi = λ xi P xiyi λ = P 2 (5.3) xi

5.1 Implementation

The stability is determined by the following piece of code: def stability(system ,maxr,maxv,maxm,p): system=deepcopy(system) #calculating the lyapunov exponent l 1=0 l 2=0 #generating systems to simulate systems =[] for i in range(l): systems.append(System()) systems [ −1].objects=permuteplanets( system. objects ,maxr,maxv,maxm,p)

#simulating systems while system.n

for system2 in systems: i f system . n

41 e l s e : system2. integrate(True) d=system. state ()−system2. state() d=(np.dot(d,d) ∗∗0.5) /p l1+=system .n∗np . log (d) l2+=system .n∗∗2 return l1/l2 The program first makes a copy of the system, so that the system can be modified within the function without interfering with the system itself. l1 and l2 are the numerator and the denominator of P xiyi P 2 respectively. Next, the program makes a number (determined xi by the variable l, which is defined earlier) of systems that differ slightly from the original system. The program integrates all the systems at the same time and determines the distance between the original systems and the modified systems at every time step and uses this to update l1 and l2. The variable d represents r0. Finally, the program divides l1 by l2 and returns this value, which is the lyapunov exponent.

5.2 Numerical analysis of the results

What follows is a numerical analysis of the results of the program above. The standard deviation was determined by creating 20 ran- dom systems and determine the lyapunov exponent twenty times for each of them. The results shown are the averages of the standard deviations found for every single system. These results were used to determine the optimal ttotal, dt and number of systems to sim- ulate to get the most accurate results, while keeping the computing time limited. In the end, a fixed number of systems was simulated, but ttotal was set to be equal to 5 times the orbital period of the first planet, because this can vary hugely (from a number of days to multiple ) and it was deemed best to have a ttotal appropriate to this timescale. The same goes for dt, which is also adapted to the orbital period: dt is set equal to the orbital period divided by 1500. dp is set to ten times dt. The graph above shows the relation between ttotal and the found lyapunov exponents. It was generated by the following script: sigma =[]

42 Figure 5.1: Relation between ttotal and the standard deviation of the found lyapunov exponents. for ttotal in [5000000,10000000,15000000,20000000,25000000,30000000, 35000000,40000000,45000000,50000000]: print(ttotal) s t d s =[] for i in range(20): p r i n t ( i ) system=randomsystem() r e s u l t s =[] for i in range(20): p r i n t ( i ) results .append(stability(system ,10∗∗12 ,3∗10∗∗8 ,10∗∗15 ,100) ) stds.append(np.std(results)) sigma.append(np.mean(stds)) plt . plot([5000000,10000000,15000000,20000000, 25000000,30000000,35000000,40000000,45000000,50000000], sigma ) Figure 5.2 shows the relation between dt and the standard de- viation of the found lyapunov exponents. It was generated by the

43 Figure 5.2: Relation between dt and the standard deviation of the found lya- punov exponents. following program: sigma =[] f o r dt in [5000,10000,15000,20000,25000,30000,35000,40000,45000, 5 0 0 0 0 ] : print(ttotal) s t d s =[] for i in range(20): p r i n t ( i ) system=randomsystem() r e s u l t s =[] for i in range(20): p r i n t ( i ) results .append(stability(system ,10∗∗12 ,3∗10∗∗8 ,10∗∗15 ,100) ) stds.append(np.std(results)) sigma.append(np.mean(stds)) p l t . p l o t ([5000,10000,15000,20000,25000,30000,35000,40000, 45000,50000],sigma)

44 Figure 5.3: Relationship between the number of systems simulated and the found lyapunov exponents.

Figure 5.3 above shows the relationship between the number of systems simulated and the standard deviation of the found lyapunov exponents. It was generated by the following code: sigma =[] for l in [1,2,3,4,5,6,7,8,9,10]: print(ttotal) s t d s =[] for i in range(20): p r i n t ( i ) system=randomsystem() r e s u l t s =[] for i in range(20): p r i n t ( i ) results .append(stability(system ,10∗∗12 ,3∗10∗∗8 ,10∗∗15 ,100) ) stds.append(np.std(results)) sigma.append(np.mean(stds)) plt.plot([1,2,3,4,5,6,7,8,9,10],sigma)

45 The standard deviation hardly seems to depend on the number of systems simulated. In the end it was decided to simulate three systems every time the lyapunov exponents are determined.

46 Chapter 6

Monte Carlo Optimization

6.1 Theory

The idea behind Monte Carlo optimization is quite intuitive. You are given a function f of a number of variables and have to find the minimum or maximum. You start at a random point in the domain of f and evaluate the function. You then go to a different point in the domain of f close to the first point and check if f gives a lower (if you’re looking for a minimum) or a higher (if you’re looking for a maximum) value for f. If this is the case you move to this point. If this not the case you stay at the first point. You then pick a new point close to where you are and repeat the process. You continue doing this until you’re satisfied you’ve seen enough points. The (approximation to the) minimum (or maximum) is at your current location. A danger is getting to a local minimum or maximum and not picking new points far enough away to leave it, but this can be solved quite easily by starting again at a new random point.

6.2 Implementation def MCMC(initialsystem ,numberofnewplanets ,max,p) : n=numberofnewplanets maxr=1500000000∗10∗∗3 maxv=299792458 maxm=10∗∗30

47 m=randomplanets(n,maxr,maxv,maxm) system=copy.deepcopy(initialsystem) system. addplanets(m) startingconditions=”” for object in system.objects: startingconditions+=”m: ”+str(object .m) +” r: ”+str(object.r[0])+”, ”+str( object.r[1])+”, ”+str(object.r[2])+” v : ”+str(object.v[0])+”, ”+str(object.v [1])+”, ”+str(object.v[2])+”\n” lm=stability (system ,maxr,maxv,maxm,p) with open(”E: \ log.txt”,”a”) as log: log.write(”First system: \ n”) log.write(datetime.datetime.now(). s t r ()+” ”+str(lm)+”\n”) log.write(startingconditions) log.write(”\n”) for i in range(max): m2=permuteplanets(m,maxr,maxv,maxm,p) system2=copy.deepcopy(initialsystem) system2. addplanets(m2) startingconditions=”” for object in system2.objects: startingconditions+=”m: ”+str(object .m)+” r: ”+str(object.r[0])+”, ”+ str(object.r[1])+”, ”+str(object.r [2])+” v: ”+str(object.v[0])+”, ”+ str(object.v[1])+”, ”+str(object.v [ 2 ] ) +”\n” lm2=stability (system2 ,maxr,maxv,maxm,p) with open(”E: \ log.txt”,”a”) as log: log.write(datetime.datetime.now(). s t r ()+” ”+str(lm2)+”\n”) log.write(startingconditions) log.write(”\n”) if np.isnan(lm2): print(”shit”) i f lm2<=lm :

48 print(’higher stability found at step ’+str(i)) m=m2 lm=lm2 system=copy.deepcopy(initialsystem) system. addplanets(m)

return system,lm The Monte Carlo optimization is integrated into the MCMC func- tion. The function first chooses a starting point m, which is repre- sented as a list of objects. A copy is then made of the system, so that it may be modified without changing anything about the orig- inal system. The list of objects is then added to the list of objects already in the system using the addplanets method. Next the stabil- ity of this system is determined. After that the log file is opened and the time and the initial conditions and the stability of the system are recorded. The function next starts generating slightly different systems and comparing their stability to the first system. The same information about these systems is recorded in the log file. If a sys- tem is found to have a lower stability then the first system, the first system is substituted by the new system and the process continues as before until the end of the for-loop is reached. The function then returns the most stable system that was found and the associated lyapunov exponent. The program uses a max of 200 and repeats the process 10 times with different starting points and picks the most stable system that is returned 0.by the function. This to avoid getting stuck at a local minimum and never finding the global min- imum.

Another problem that occurred in this particular situation was deciding how much to change the initial system at every step. Be- cause of the huge range planetary systems, with, for example, semi- major axes varying from 0.1 to 10 AU and planetary masses ranging from the order of magnitude of the mass of the to the mass of Jupiter (around 300 times the mass of the earth). In the end it was decided take a step size in proportion with the initial values. This step size is controlled by the parameter p: if p equals 0.5 the program will take steps the size of one half the initial value. The program uses a p of 0.1. This is rather large, so it will only give

49 rough estimates, but will allow the program to thoroughly cover the entire domain in a reasonable amount of time.

50 Chapter 7

Results

The program was run for five different stars: Gliese 777, 23 Librae, HD 144358, Kepler 68 and 47 Ursae Majoris. The first three of these systems have two exoplanets orbiting around them, the other two have three. For each of these systems the most massive planet was selected. Using the algorithm described in chapter 4 the initial position and velocity for its orbit were calculated. The Monte Carlo method described in chapter 6 then added another planet (two new planets for Kepler 68 and 47 Ursae Majoris) and calculated which added planet(s) would lead to the most stable configuration of the system. Below are basic descriptions of the systems, the mass and initial conditions of the planet(s) found and pictures resulting from simulations of the most stable systems.

7.1 Gliese 777

Gliese 777 has a mass 0.9 times that of the sun. It’s planetary sys- tem consists of two confirmed planets: Gliese 777b and Gliese 777c. Gliese 777b is the heaviest of the two, with 1.56 Jupiter masses. Its orbit has a semi-major axis of 4.01 AU and an eccentricity of 0.313 (Naef et al. 2003). Gliese 777b is much smaller at 0.0600 Jupiter masses. Its orbit has a semi-major axis of 0.1304 AU and an eccen- tricity of 0.237 (Vogt et al. 2005). The most stable system found has a lyapunov exponent of 3.31 · 10−9. This corresponds to a sec- ond planet with a mass of 9.78 · 1026 kg that starts at (−3.24 · 1011, 4.56 · 1010, −5.90 · 1011) with a velocity of (−7.88 · 103, −3.86 · 103, 4.27 · 103).

51 7.2 23 Librae

23 Librae has a mass of 1.07 solar masses. It has two confirmed planets orbiting around it. The most massive of the two, 23 Librae b, had a mass of 1.59 Jupiter masses and orbits with as semi-major axis of 0.81 AU and an eccentricity of 0.233 (Vogt et al. 2000). 23 Librae c has a mass of 0.82 Jupiter masses and orbits on an ellipse with a semi-major axis of 5.8AU and an eccentricity of 0.12 (Jones et al. 2010). The most stable system found has a lyapunov exponent of 3.80 · 10−7. This corresponds to a second planet with a mass of 7.09 · 1026 kg that starts at (−8.72 · 1010, 1.03 · 1011, −3.25 · 1010) with a velocity of (−1.62 · 104, −1.49 · 104, 5.69 · 103).

7.3 HD 155358

HD 155358 is a star of 0.89 solar masses orbited by two exoplanets. The heaviest of these, HD 155358b has a mass of 0.89 Jupiter masses, a semi-major axis of 0.628 AU and an eccentricity of 0.112. The other planet, HD 155358c, has a mass of 0.504 Jupiter masses, a semi-major axis of 1.224 AU and an eccentricity of 0.176 (Cochran et al. 2007). The most stable system found has a lyupanov exponent of 5.021 · 10−7. This corresponds to a second planet with a mass of 5.01 · 1026 kg that starts at (−1.37 · 1010, −1.58 · 1011, 5.27 · 1010) with a velocity of (6.59 · 103, 1.01 · 104, 1.18 · 104).

7.4 Kepler 68

Kepler 68 has a mass of 1.079 solar masses and is orbited by three different planets. Kepler 68d is the heaviest of those, with a mass of 0.87 Jupiter masses. Its orbit has a semi-major axis of 1.4 AU and an eccentricity of 0.18 (Gilliland et al. 2013). The second most massive planet is Kepler 68c with 0.015 Jupiter masses. It has an orbit with a semi-major axis of 0.9059 AU and an unknown eccentricity. The third planet has a mass of 5.9 Earth masses, a semi-major axis of 0.0617 AU and also an unknown eccentricity (Marcy et al. 2014). The most stable system found has a lyapunov exponent of 1.7384 · 10−7. This corresponds to a second planet with a mass of 1.45 · 1027 kg that starts at (1.06 · 1011, 6.08 · 108, −3.20 · 1011.0)

52 with a velocity of (2.15 · 104, 6.51 · 103, 1.94 · 103) and a third planet with a mass of 2.89 · 1026 kg that starts at (−1.33 · 1011, −3.10 · 1011, 1.85 · 1011) with a velocity of (−7.67 · 103, 1.01 · 104, 3.91 · 103).

7.5 47 Ursae Majoris

Ursa Majoris has a mass of 1.08 solar masses. Three planets orbit it: 47 Ursa Majoris b, with a mass of 2.53 Jupiter masses, a semi-major axis of 2.10 AU and an eccentricity of 0.32 (Butler & Marcy 1996), 47 Ursa Majoris c, with a mass of 0.540 Jupiter masses, a semi-major axis of 3.6 AU and an eccentricity of 0.098 (Fischer et al. 2002) (Wittenmyer et al. 2007), and 47 Ursa Majoris d, with a mass of 1.64 Jupiter masses, a semi-major axis of 11.6 AU and an eccentricity of 0.16 (Gregory & Fischer 2010). The most stable system found has a lyapunov exponent of 9.53 · 10−8. This corresponds to a second planet with a mass of 9.55 · 1027 kg that starts at (−1.60 · 1011, −4.85 · 1011, −8.91 · 1010) with a velocity of (9.59 · 103, 6.12 · 103, −1.14·104) and a third planet with a mass of 8.48·1027 kg that starts at (4.85 · 1011, 7.53 · 1010, 2.76 · 1011) with a velocity of (−7.51 · 103, −8.25 · 103, 1.23 · 104).

53 Figure 7.1: Most stable configuration for Gliese 777. The second planet has a mass of 9.78 · 1026 kg and starts at (−3.24 · 1011, 4.56 · 1010, −5.90 · 1011) with a velocity of (−7.88 · 103, −3.86 · 103, 4.27 · 103). The system has a lyapunov exponent of 3.31 · 10−9.

54 Figure 7.2: Most stable configuration for 23 Librae. The second planet has a mass of 7.09 · 1026 kg and starts at (−8.72 · 1010, 1.03 · 1011, −3.25 · 1010) with a velocity of (−1.62 · 104, −1.49 · 104, 5.69 · 103). The system has a lyapunov exponent of 3.80 · 10−7.

55 Figure 7.3: Most stable configuration for HD 155358. The second planet has a mass of 5.01 · 1026 kg and starts at (−1.37 · 1010, −1.58 · 1011, 5.27 · 1010) with a velocity of (6.59·103, 1.01·104, 1.18·104). The system has a lyupanov exponent of 5.02 · 10−7.

56 Figure 7.4: Most stable configuration for Kepler 68. The second planet has a mass of 1.45 · 1027 kg and starts at (1.06 · 1011, 6.08 · 108, −3.20 · 1011.0)(105549363137.0, 608357441.412, −320490581386.0) with a velocity of (2.15 · 104, 6.51 · 103, 1.94 · 103). The third planet has a mass of 2.89 · 1026 kg and starts at(−1.33·1011, −3.10·1011, 1.85·1011) with a velocity of (−7.67·103, 1.01 · 104, 3.91 · 103). The system has a lyapunov exponent of 1.74 · 10−7.

57 Figure 7.5: Most stable configuration for 47 Ursae Majoris. The second planet has a mass of 9.55 · 1027 kg and starts at (−1.60 · 1011, −4.85 · 1011, −8.91 · 1010) with a velocity of (9.59·103, 6.12·103, −1.14·104). The third planet has a mass of 8.48 · 1027 kg and starts at (4.85 · 1011, 7.53 · 1010, 2.76 · 1011) with a velocity of (−7.51 · 103, −8.25 · 103, 1.23 · 104). The system has a lyapunov exponent of 9.53 · 10−8.

58 Chapter 8

Conclusions & Discussion

8.1 The extent of similarity to the initial sys- tems

The found systems are not very similar to the original systems. Most notably the inclinations vary wildly. In reality most planetary sys- tem are almost flat. This is, however, understandable, as the small difference in inclination of the orbits in planetary systems is more a relic of their formation in accretion discs than of their stability. The systems found for Gliese 777, 23 Librae and HD 155358 were surprisingly similar: in all three systems the angle between the or- bital planes are around 60◦, as can be seen in figures 8.1, 8.2 and 8.3. This suggests that, for some reason, this type of system is more stable than other systems. The preference disappears when more planets are added: 47 Ursae Majoris shows 60◦angles between the orbital plane of the original planet and the orbital planes of the other planets, but the orbital planes of the added planets intersect at a different angle (see figures 8.4, 8.5 and 8.6) and not one pair of orbital planes in the system found for Kepler 68 intersects at 60◦(see figures 8.7, 8.8 and 8.9).

Because these situations with large differences in inclinations rarely happen in reality it might be interesting to exclude them from the results. This could be achieved by constricting the motion of the planets to a disk around the origin or by reducing the number of dimensions to two. The first method would give more accurate re- sults, but is significantly more complicated than the second method.

59 These simulations might result in more realistic planetary systems that correspond more closely to the initial systems.

The masses of the found planets vary between 0.5 and 5 Jupiter masses, which is fairly typical for planets. They don’t correspond very well to the masses of the planets in the actual systems however. The masses of the found planets for 23 Librae and HD 155358 come within 0.3 Jupiter masses of the true value.

The found orbits are usually roughly the size of the first orbit. In reality there is much more variation in semi-major axes. The orbits are also mostly circular, which does correspond to reality.

8.2 Possible improvements

The calculations could be easily improved on by simulating the sys- tems for a longer time, using a shorter time step, simulating more systems when determining the lyapunov exponent or running the Monte Carlo optimization longer or more often. This was not done because of limitations on the computing time. It would also be eas- ier to compare the results for different systems if the calculations were done for more of them. It might also be interesting to begin with more than one planet already in the system or to look for stable systems with more than three planets, but because a large number of systems leads to large increase in computing time, this wasn’t done either although it was the original plan was to run the calcula- tions for our own solar system (with 8 planets). Starting with just the star might also be very interesting, because it is more general, with the added benefit that it scales quite easily with the mass of the star. This would however require some changes to the program, mostly in the part where the total time and time step are deter- mined. The program would also benefit from a routine to convert the initial position and velocity of the found planets back to the orbital elements.

60 Figure 8.1: The system found for Gliese 777 shown from the side.

61 Figure 8.2: The system found for 23 Librae shown from the side.

62 Figure 8.3: The system found for HD 155358 shown from the side.

63 Figure 8.4: The system found for 47 Ursae Majoris shown from the side.

64 Figure 8.5: The system found for 47 Ursae Majoris shown from the side.

65 Figure 8.6: The system found for 47 Ursae Majoris shown from the side.

66 Figure 8.7: The system found for Kepler 68 shown from the side.

67 Figure 8.8: The system found for Kepler 68 shown from the side.

68 Figure 8.9: The system found for Kepler 68 shown from the side.

69 Bibliography

Butler, R. P. & Marcy, G. W. (1996), ‘A planet orbiting 47 ursae majoris’. Cochran, W. D., Endl, M., Wittenmyer, R. A. et al. (2007). Fischer, D. A., Marcy, G. W., Butler, P. R. et al. (2002), ‘A second planet orbiting 47 ursae majoris’. Gilliland, R. L., Marcy, G. W., Rowe, J. F. et al. (2013), ‘Kepler-68: Three planets, one with a density between that of earth and ice giants’. Gregory, P. C. & Fischer, D. A. (2010), ‘A bayesian periodogram finds evidence for three planets in 47 ursae majoris’. Jones, H. R. A., Butler, R. P., Tinney, C. G. et al. (2010), ‘A long period planet orbiting a nearby sun-like star’. Marcy, G. W., Isaacson, H., Howard, A. W. et al. (2014), ‘Masses, radii, and orbits of small kepler planets: the transition from gaseous to rocky planets’. Naef, D., Mayor, M., Korzenik, S. G. et al. (2003), ‘The elodie survey for northern extra-solar planets’. Poincar´e,H. (1892-1899), ‘New methods of celestial mechanics’. Unknown (2015), ‘Kepler’s laws of planetary motion’, http://en.wikipedia.org/wiki/Kepler%27s_laws_of_ planetary_motion#Position_as_a_function_of_time. visited on 18-1-2015. van Haandel, M. (2009), ‘De wetten van kepler’.

70 Vogt, S. S., Butler, R. P., Marcy, G. W. et al. (2005), ‘Five new multicomponent planetary systems’. Vogt, S. S., Marcy, G. W., Butler, R. P. et al. (2000), ‘Six new planets from the keck precision velocity survey’. Wittenmyer, R. A., Endl, M. & Cochran, W. D. (2007), ‘Long- period objects in the extrasolar planetary systems 47 ursae majoris and ’. Young, P. (2014), ‘The leapfrog method and other ”sympletic” al- gorithms for integrating newton’s laws of motion’.

71 Acknowledgements

I would like to thank Sven Aerts for his advice, feedback and oc- casional explanation, all of which have helped me a great deal and without which my profielwerkstuk would not be what it is today, and for giving me the freedom to do things my own way. I would also like to thank Estevan Veenstra for his support, enthusiasm and for giving me the opportunity to occasionally work on my profiel- werkstuk during my chemistry classes. Next I would like to thank Simon Portegies Zwart for his suggestions, which have proven to be very useful. Last but not least I would like to thank my parents for the countless cups of tea, the occasional advice and the rigorous proofreading (but mostly the tea).

72 Appendix A

Properties of ellipses

An ellipse is the set of points for which the sum of the distances between the point and both the foci is constant. An ellipse has a semi-major axis a: the distance from the centre of the ellipse to one of the two points that are the farthest away from it. An ellipse has a semi-major axis b: the distance from the centre of the ellipse to one of the two points that are the closest to it. An ellipse has a focal length c: the distance from the centre of the ellipse to one of the foci. c2 = a−b2 q b 2 c An ellipse has an eccentricity ε defined as 1 − ( a ) or as a . In polar coordinates with the origin at one of the foci an ellipse is a(1−ε2) represented as r = 1+ε cos θ

73 Appendix B

Other Formulae

The mirror image s of a vector v in a surface V through q and with 2((v−q)·n) normal n is given by s = v − |n|2 n. Given two vectors u and v and the angle γ between them the fol- lowing equation holds: |u × v|2 = |u|2|v|2 sin2 γ. r2θ The area of a circle sector with angle θ and radius r is given by 2 .

74 Appendix C

The Complete Program

The program shown below was used to calculate the most stable configuration for Gliese 777. For the other systems the code from systemname=”Gliese777” to n=1 was changed, where n is the amount of planets that should be added. import matplotlib.pyplot as plt from m p l toolkits .mplot3d import Axes3D import numpy as np import math as ma from random import random import pdb import copy import math from copy import deepcopy import datetime import time systemname=”Gliese777” starmass=0.9 #solar masses planetmass=1.56 #Jupiter masses semimajoraxis=4.01 #AU eccentricity=0.313 n=1

75 #Starting values dt=30000 #time interval used when integrating dp=0 #time interval between plotting ttotal=40000000 #total time to simulate a system G=6.67384∗10∗∗ −11 #gravitational consant l =3 #number of systems to simulate when determining lyapunov exponent maxr=0 maxv=0 maxm=0

#plotting stuff fig=plt.figure(0) planetplot=fig .add subplot(111,projection=’3d’)

#Class for planets/stars class Object : def i n i t (self ,position ,velocity ,mass): #position and velocity as numpy arrays self .r=position self .v=velocity self .m=mass s e l f . x =[] s e l f . y =[] s e l f . z =[] def integrate(self): s e l f . r+=dt∗ s e l f . v s e l f . v+=dt∗ s e l f . a def plot(self): self .x.append(self .r[0]) self .y.append(self .r[1]) self.z.append(self.r[2])

#Class for planetary system class System : def i n i t ( s e l f ) :

76 self .objects=[] #list of all objects in the system s e l f . n=0 #time that has passed since ’ creation’ of system s e l f . k=dp #time next time system has to be p l o t t e d s e l f .m=0 #(total) mass of star(s) def createStar(self ,mass): self . objects .append(Object(np.array ( [ 0 , 0 , 0 ] , float ),np.array([0,0,0], float ) , mass ) ) #self.objects[ −1]. p l o t () self .m+=mass def createPlanet(self ,m,a,e,i ,o,w,t): #m:mass, a:semimajor axis , e: eccentricity , i:inclination , o: longitude of ascending node, w: argument of periapsis , t::time since p e r i h e l i o n #determining orbital period (via Keplers t h i r d law ) T=((4∗np . pi ∗∗2∗a ∗∗3) /(G∗ s e l f .m) ) ∗∗(1/2) global t t o t a l global dt global dp t t o t a l =5∗T dt=T/1500 dp=10∗dt

#determening mean anomaly M1=(2∗np . pi ∗ t /T) %(2∗np . pi ) M2=(2∗np . pi ∗(t+dt)/T)%(2∗np . pi )

#determening eccentric anomaly (via Newton−Raphson ) i f M1==0 or M1==np . pi or M1==2∗np . pi : E1=M1 else : i f e >0.8:

77 ENR=[0,np. pi ] #two values so t h a t while−loop will work else : ENR=[0 ,M1] #two values so that while−loop will work while not abs (ENR[−1]−ENR[ −2]) <10∗∗−8: E=ENR[ −1] ENR. append((E−(E−e∗ma. s i n (E)−M1) /(1−e∗ma. cos(E)))%(2∗np . pi ) ) E1=ENR[ −1] i f M2==0 or M2==np . pi or M2==2∗np . pi : E2=M2 else : i f e >0.8: ENR=[0,np. pi ] #two values so t h a t while−loop will work else : ENR=[0 ,M2] #two values so that while−loop will work while not abs (ENR[−1]−ENR[ −2]) <10∗∗−8: E=ENR[ −1] ENR. append((E−(E−e∗ma. s i n (E)−M2) /(1−e∗ma. cos(E)))%(2∗np . pi ) ) E2=ENR[ −1]

#determining true anomaly i f ( t /T) %1<0.5: th1=ma. acos ( ( e−ma.cos(E1))/(e∗ma. cos (E1) −1)) th2=ma. acos ( ( e−ma.cos(E2))/(e∗ma. cos (E2) −1)) else : th1=−ma. acos ( ( e−ma.cos(E1))/(e∗ma. cos (E1) −1)) th2=−ma. acos ( ( e−ma.cos(E2))/(e∗ma. cos (E2) −1))

78 #determening distance to star ar1=a∗(1−e ∗∗2) /(1+e∗ma.cos(th1)) ar2=a∗(1−e ∗∗2) /(1+e∗ma.cos(th2))

#converting polar to cartesian coordinates r1=np.array ([ar1 ∗ma.cos(th1) ,ar1 ∗ma. s i n ( th1 ) , 0 ] , float ) r2=np.array ([ar2 ∗ma.cos(th2) ,ar2 ∗ma. s i n ( th2 ) , 0 ] , float )

#matrix for applying argument of p e r i a p s i s A=np.array ([[ma.cos(w) ,ma. sin(w) ,0],[ −ma .sin(w),ma.cos(w) ,0],[0,0,1]], float )

#matrix for applying inclination B=np.array([[1 ,0 ,0] ,[0 ,ma.cos(i),−ma. s i n (i)],[0,ma.sin(i),ma.cos(i)]] , float )

#matrix for applying longitude of ascending node C=np.array ([[ma.cos(o) ,ma. sin(o) ,0],[ −ma .sin(o),ma.cos(o) ,0],[0,0,1]], float )

#matrix for applying inclination , lonitude of ascending node and argument of periapsis R=np.dot(C,np.dot(B,A))

#a p p l y i n g R r1=np.dot(R,r1) r2=np.dot(R,r2)

#determining speed v=(r2−r1 ) / dt

#creating planet self .objects.append(Object(r2 ,v,m))

79 #self.objects[ −1]. p l o t ()

global maxr maxr=2∗np.dot(r1,r1) ∗∗0.5 global maxv maxv=2∗np.dot(v,v) ∗∗0.5 global maxm maxm=2∗m

#function to determine the state of a system def state(self): s t a t e =[] for object in self.objects: for i in object . r : state .append(i) for i in object . v : state .append(i) state=np.asarray(state) return s t a t e

def calcForces(self): for object in self.objects: object .a=np.array([0 ,0 ,0] , float ) a=len (self.objects) for i in range ( a ) : for j in range ( a ) : i f i>j : dr=self.objects[i ].r−s e l f . objects[j].r k=dr∗G/(np.dot(dr,dr) ∗∗(3/2) ) self .objects[i ].a+=−s e l f . objects[j ].m∗k self .objects[j ].a+=self . objects[i ].m∗k

def integrate(self ,toplotornottoplot):

80 self .calcForces() for object in self.objects: object .integrate() i f toplotornottoplot: object . p l o t ( )

def simulate(self): self.state() print ( s e l f . k ) while s e l f . n

def addplanets(self ,planets): #planets: list of Object−o b j e c t s for planet in p l a n e t s : self .objects.append(planet) def randomplanets(number ,maxr,maxv,maxm) : p l a n e t s =[] for i in range ( number ) : r=np.random. uniform(−maxr,maxr,3) r=random ( ) ∗maxr∗ r/(np.dot(r,r) ∗∗0.5) v=np.random. uniform(−maxv,maxv,3) while abs (ma.acos(np.dot(r,v)/((np.dot(r , r ) ∗ ∗ . 5 ) ∗(np.dot(v,v) ∗ ∗ . 5 ) ) ) )

81 planets=deepcopy(planets) r=0 v=0 m=0 for planet in p l a n e t s : r+=np.dot(planet.r ,planet.r) ∗∗0.5 v+=np.dot(planet.v,planet.v) ∗∗0.5 m+=planet .m r=r /len ( p l a n e t s ) v=v/len ( p l a n e t s ) m=m/len ( p l a n e t s ) for planet in p l a n e t s : dr=np.random. uniform(−r ∗p , r ∗p , 3 ) dv=np.random. uniform(−v∗p , v∗p , 3 ) while abs (ma.acos(np.dot(planet.r+dr, planet.v+dv)/((np.dot(planet.r+dr , planet.r+dr) ∗ ∗ . 5 ) ∗(np.dot(planet .v+dv, planet .v+dv) ∗ ∗ . 5 ) ) ) )

#function to determine lyapunov exponent def stability (system ,maxr,maxv,maxm,p): system=deepcopy(system) #calculating the lyapunov exponent l 1=0 l 2=0 #generating systems to simulate systems =[] for i in range ( l ) : systems.append(System()) systems [ −1].objects=permuteplanets( system. objects ,maxr,maxv,maxm,p)

#simulating systems

82 while system . n

state=system. state()

for system2 in systems : i f system . n

83 log.write(datetime.datetime.now(). s t r ( )+” ”+str ( lm )+”\n” ) log.write(startingconditions) log.write(”\n” ) for i in range (max): print ( i ) m2=permuteplanets(m,maxr,maxv,maxm,p) system2=copy.deepcopy(initialsystem) system2. addplanets(m2) startingconditions=”” for object in system2.objects : startingconditions+=”m: ”+str ( object .m)+” r : ”+str ( object . r [ 0 ] )+” , ”+ str ( object . r [ 1 ] )+” , ”+str ( object . r [ 2 ] )+” v : ”+str ( object . v [ 0 ] )+” , ”+ str ( object . v [ 1 ] )+” , ”+str ( object . v [ 2 ] )+”\n” lm2=stability (system2 ,maxr,maxv,maxm,p) with open(systemname+”\ log.txt”,”a”) as log : log.write(datetime.datetime.now(). s t r ( )+” ”+str ( lm2 )+”\n” ) log.write(startingconditions) log.write(”\n” ) i f lm2<=lm : print ( ’ higher s t a b i l i t y found at step ’+str ( i ) ) m=m2 lm=lm2 system=copy.deepcopy(initialsystem) system. addplanets(m) return system , lm filename=”” filename+=systemname filename+=”\ stablesystems.txt” system=System() system. createStar(starmass ∗1.9891∗10∗∗30)

84 system. createPlanet(planetmass ∗1.89813∗10∗∗27 , semimajoraxis ∗149597870700,eccentricity , 0 , 0 , 0 , 0 ) r e s u l t s ={} for i in range (10) : result ,lyapunov=MCMC(system ,n,200 ,0.5) results [lyapunov]=result lexponent=min( l i s t (results.keys())) stablesystem=results [lexponent] startingconditions=”” for object in stablesystem.objects: startingconditions+=”m: ”+str ( object .m)+” r : ”+str ( object . r [ 0 ] )+” , ”+str ( object . r [ 1 ] )+ ”, ”+str ( object . r [ 2 ] )+” v : ”+str ( object . v [ 0 ] )+” , ”+str ( object . v [ 1 ] )+” , ”+str ( object . v [ 2 ] )+”\n” with open(filename ,”a”) as stablesystems: stablesystems.write( str (lexponent)+”\n” ) stablesystems.write(startingconditions) stablesystem.simulate() planetplot.text2D(0.1,0.9,r”$\lambda=”+str ( lexponent)+”$”)

#final plotting stuff for object in stablesystem.objects: planetplot.plot( object . x , object . y , object . z , color=”k” ,marker=None, linewidth=0.3) p l t . show ( )

85