Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                

Thesis PDF

Download as pdf or txt
Download as pdf or txt
You are on page 1of 98

A Study of the Planar Circular Restricted Three

Body Problem and the Vanishing Twist

Joachim Worthington

An essay submitted in partial fulfillment of


the requirements for the degree of
B.Sc. (Honours)

Applied Mathematics
University of Sydney

October 2012
C ONTENTS

Chapter 1. Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1
Chapter 2. Background . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
2.1. History of the Three Body Problem . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
2.2. Particular Solutions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
2.3. Lagrangian and Hamiltonian Mechanics . . . . . . . . . . . . . . . . . . . . . . . . . . 9
Chapter 3. Setting Up the Three Body Problem . . . . . . . . . . . . . . . . . . . . . . . 12
3.1. The Two Body Problem: exact solution . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
3.2. The Three Body Problem . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
3.3. Dynamics of the Three Body Problem . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
3.4. The Poincaré Map . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
3.5. The Extended Phase Space . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
Chapter 4. Regularisations and other Numerical Considerations . . . . . . . 24
4.1. Splitting Method for Hamiltonian . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24
4.2. Regularising Collision Orbits . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25
4.3. Local Regularisation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27
4.4. Global Regularisations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29
4.5. The Thiele-Burrau Transformation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31
4.6. Numerical Scheme . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33
4.7. Calculating the Poincaré Map . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34
Chapter 5. Results . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36
5.1. Program Design and Methodologies . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36
5.2. Analysing Orbits . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38
Chapter 6. Conclusion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51
References . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52
Appendix A. Acknowledgements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54
Appendix B. Code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55

iii
C HAPTER 1

Introduction

Since the 17th century, the N -body problem has held the attention of genera-
tions of astronomers and mathematicians. The problem is simple: given a collec-
tion of N celestial bodies (be they planets, asteroids, stars, black holes) interacting
with each other through gravitational forces, what will their trajectories be? For
N = 2, the problem has been solved for centuries; for N ≥ 3, the problem still has
no solution in any meaningful sense. As the theory and vocabulary of dynamics
have evolved, so too has the analysis of the problem, and indeed the study of the
problem has often directly led to the development of new concepts and ideas in
dynamics.
In this thesis, we consider the planar circular restricted three body problem, a
specific case of the N -body problem for N = 3. The primary goal is to develop
a fast, user-friendly program which can quickly and reliably calculate trajectories
from user input. The program will also calculate Poincaré maps, which will be
used to analyse the system for various parameter values. We then hope to verify the
existence of a particular bifurcation called the twistless bifurcation for orbits near
the Lagrangian points. The twistless bifurcation was found for a general system by
Dullin, Meiss and Sterling [12], and it is expected that the planar circular restricted
three body problem will exhibit the same behaviour.
We begin with a discussion of the history of the problem in Chapter 2, us-
ing Barrow-Green [5], Valtonen & Karttunen [10] and James [23] as our primary
sources. This background serves a dual purpose, neatly introducing many of the
theoretical concepts used to analyse the problem. We discuss several “particular
solutions” which illustrate useful ideas and dynamics, and give a summary of the
theory of Lagrangian and Hamiltonian mechanics.
In Chapter 3, the solution to the two body problem is presented, and the dy-
namics for the three body problem are derived. Following Koon, Lo, Marsden &
Ross [22], we take a Hamiltonian approach to the problem. Other physical consid-
erations such as the Hill region and Lagrangian points are introduced. Also defined
are the Poincaré map and extended phase space.
Chapter 4 deals with the biggest obstacle in any attempt to integrate trajec-
tories of the N -body problem, regularising collision orbits. Although an elegant
split-step integrator can be found for the problem, regularising transforms are still
required. The discussion of these transformations follows from Szebehely [16],
but are here derived in the context of Hamiltonian mechanics. The Levi-Civita,
Birkhoff and Thiele-Burrau transformations are discussed. An elegant numerical
method for calculating Poincaré maps designed by Henón [20] is also presented.

1
2 1. I NTRODUCTION

Chapter 5 gives a brief outline of the development and use of the completed
program, and a comparison of the observed bifurcations to those predicted by the
theory. Also included is a consideration of the Earth-Moon system, predicting the
behaviour of a possible Earth-Moon trojan.
C HAPTER 2

Background

The study and theory of the three body problem has developed over the last
four centuries concurrent to (and often catalysing) the general theory of dynamical
systems. It is therefore natural to explore the history of the problem, not only for
context and insight but to introduce key approaches and techniques to be utilised
in the project.

2.1. History of the Three Body Problem


The three body problem as we consider it arose very naturally from the work
of Newton. In the early 17th century Kepler proposed his laws of planetary motion,
describing the orbits of the planets around the sun as ellipses. Newton formalised
these ideas in 1687’s Philosophiæ Naturalis Principia Mathematica [1], one of the
most important works in the history of science. In particular, the formula for the
gravitational force between any two point masses is given as
m1 m2
(2.1) F =G 2
r
for two masses m1 and m2 separated by a distance of r, and G the universal gravi-
tational constant. Some controversy remains whether this law should be attributed
to Newton or Hooke, but it is acknowledged that both men made very significant
contributions to the development of celestial mechanics.
Having justified the laws proposed by Kepler, Newton turned his attention to
systems more complex than a Sun-Planet system. One of his main considerations
was the Sun-Earth-Moon system. However, Newton’s work in this regard was
plagued by difficulties, and he remarked “...[his] head never ached but with his
studies on the moon”. It would not be until after Newton’s lifetime that any major
progress was made on the three body problem.
In 1747, Alexis Clairaut announced he had successfully constructed a series
approximation for the motion of the three masses. After some modification, his
approximations accounted for the perigee of the moon (the point at which the moon
is nearest to earth), which had been an aim of Newton’s. In 1752 Clairaut won the
St. Petersburg Academy prize for his work on the problem, and in 1759 the value
of his approximations was amply demonstrated when Halley’s comet passed Earth
within a month of what his equations had predicted, the margin of error he himself
had prescribed.
Meanwhile, Leonhard Euler had also turned his attentions to the three body
problem. Euler proposed considering the restricted three body problem, a simpli-
fication of the general problem where one of the bodies is taken to have negligible
3
4 2. BACKGROUND

mass (see 3.2.1). When considered with a circular orbits for the two masses, this is
also known as the Euler three body problem. Euler also used variation of parame-
ters to study perturbations of the planetary motion.
At the same time as Euler, Joseph Lagrange made significant progress on the
general three body problem. Lagrange’s major contributions to theory included re-
ducing the problem from a system of differential equations of order 18 to a system
of order 7, and describing two types of particular solutions to the general problem
(see 2.2.2). Also of major importance, not just to the three body problem but to the
general theory of dynamic systems, was his development of Lagrangian Mechanics
(see 2.3).
Unaware of Lagrange’s work, Carl Jacobi reduced the general problem to a
sixth order system and the restricted problem to a fourth-order system. A constant
of motion was found, known as Jacobi’s integral, and is the only known conserved
quantity of the restricted problem. In 1878, George Hill demonstrated a very useful
application of Jacobi’s integral, describing the regions of possible motion for the
body of negligible mass (see 3.3.2).
Another contributor to the theory of the problem was Charles-Eugéne Delau-
nay. By taking repeated canonical transformations of the problem, requiring a truly
staggering number of calculations, Delaunay completely eliminated the secular
terms of the problem. Taking over two decades to complete, Delaunay’s methods
were published in 1846 but his final results could not be published until 1860 and
1867, when they were published in two large volumes of over nine hundred pages
each. A key useful result of the work was the introduction of Delaunay variables,
a set of canonical action angles which give the equations of motion in Hamiltonian
form. Although Delaunay’s method was impractical at the time (the expressions
involved were extremely complex and converged very slowly), the theory has been
highly influential, not only in lunar theory but in fields such as quantum theory as
well.
The end of the “classical” period of work on the three
body problem was marked by the extremely influential work
of Henri Poincaré. In the late nineteenth century, King Os-
car II of Sweden established a prize for solving the N -body
problem (a more general form of the problem with N rather
than 3 masses) on the advice of Gösta Mittag-Leffler, Karl
Weierstrass, and Charles Hermite. The statement of the
problem was as follows:

Given a system of arbitrarily many mass


Henri Poincaré
points that attract each other according to
Newton’s law, under the assumption that no
two points ever collide, try to find a repre-
sentation of the coordinates of each point
as a series in a variable that is some known function of time and
for all of whose values the series converges uniformly.
2.2. PARTICULAR S OLUTIONS 5

Although Poincaré did not solve the problem as stated, his paper was so pro-
gressive and important that he won the prize regardless. However, his initial sub-
mission contained a fatal mathematical error, which led to a fallacious stability
result for the N = 3. After having all copies of the original paper destroyed (at a
high personal cost), he published an updated paper which rectified the mistake. In
doing so, he raised several influential ideas which would lead to the development
of the theory of mathematical chaos, and changed core ideas of the mathematical
study of dynamics. He also introduced the concept of a first return map, now also
known as a Poincaré map (see 3.4). For more on Poincaré’s work on the three body
problem, see Barrow-Green [5].
In fact, the problem as it had originally been stated would not be solved until
1912 by Sundman for N = 3. The general case would remain unsolved until
1991, when Qiudong Wang published The Global Solution of N -body Problem
[8]. However, in both cases, the series constructed converged so slowly that they
were essentially useless in practice. Though his work met the requirements of King
Oscar’s problem, Wang himself would characterise his result as “a tricky, simple
and useless answer” while praising the publications that Poincaré did complete
(see [7]).
After much of the foundations were laid by Poincaré, the twentieth century
saw progress on many different fronts. Simplified versions of the restricted three
body problem were analysed. For example, the Copenhagen problem assumes the
two masses to be equal, and were considered by Strömgren and colleagues from
1913 in detail.
Another approach to the problem in last century was the development of statis-
tical analysis of the orbits. Poincaré had demonstrated the system is chaotic, which
opens the possibility of systematically analysing orbits based on statistical distri-
butions. In most occurences, the general three body problem results in one mass
leaving the two other bodies permanently, and the other two forming a binary sys-
tem. This is known as an escape orbit. Valtonen and Karttunen (see [10]) applied
statistical methods to analyse the scattering of these escape orbits. These results
were directly compared to experimental values, which could be carried out thanks
to the proliferation of powerful computers at the end of the twentieth century.
An altogether different approach to classify the possible motions was Hénon’s
analysis of the restricted three body problem. By perturbing the mass of one of the
bodies near µ = 0 (an idea explored already by Poincaré), Hénon considered fam-
ilies of orbits. This research led to his fascinating books of “generating families”
[2] [3].

2.2. Particular Solutions


Concurrent with the development of the theoretical structure surrounding the
problem was the discoveries of several particular solutions in special cases.

2.2.1. Euler’s Solution. The earliest and simplest particular solution was dis-
covered by Euler in 1765. In Euler’s solution, the three masses are collinear, po-
sitioned according to their masses. Then at every future time, the masses remain
6 2. BACKGROUND

m3
m3

m1 m2

m2
m1

Figure 2.1. The Euler solution: the three bodies remain collinear at all
times, in elliptical orbits around the centre of mass. Left: all masses
equal. Right: unequal masses.

collinear, and the distances between them remain at the same ratio. In the particular
case of the three bodies having equal masses, this corresponds to a situation where
two of the bodies rotate in a circle around the third. For unequal masses, each mass
will travel in an elliptical orbit around the centre of mass. See Figure 2.1 for an
illustration of these behaviours.
Although this solution is interesting, and deeply connected to the theory we
will develop, such orbits are unstable. The smallest of perturbations will destroy
the symmetry, so such a situation will never be realised in a physical system.

m1 m3

m3

m2

m1 m2

Figure 2.2. The Lagrange solution: the three bodies form an equilateral
triangle at all times. Left: three equal masses. Right: unequal masses

2.2.2. Lagrange’s Solution. In 1772 Lagrange discovered another particular


solution. Lagrange’s solution has the three masses occur at the vertices of an equi-
lateral triangle. The masses will then follow elliptical orbits around their centre of
mass while remaining in an equilateral triangle formation. When all three masses
are equal, this gives a situation where the three bodies trace the same circular orbit
fixed distances apart. See Figure 2.2.
Lagrange and Euler’s solutions form the only explicit solutions to be discov-
ered in the classical era of investigation. Unlike Euler’s solution, Lagrange’s can
2.2. PARTICULAR S OLUTIONS 7

be stable, although only under certain conditions. If one of the masses completely
dominates the system, then the orbits become stable. In fact, such orbits explain
the existence of Trojans. Trojans are satellites (often asteroids) that orbit at spe-
cific locations relative to two larger masses. In the restricted case, both Euler and
Lagrange’s solutions reduce to a description of the Lagrangian points where these
trojans are found. These Lagrangian points are discussed in Section 3.3.1.
2.2.3. The Figure-Eight Solution. Long after Euler and Lagrange’s solu-
tions, another particular solution was found: the figure-eight solution. First discov-
ered numerically by Cristopher Moore in 1993, its existence was rigorously proved
in 2001 by Alain Chenciner and Richard Montgomery [11]. Unlike the other par-
ticular solutions it only occurs in the case of three equal masses, but remarkably
is stable. In the figure eight solution, all three bodies trace the same figure-eight
shaped orbit, with the double point at the centre also being the centre of mass. This
is illustrated in Figure 2.3.

m3
m1

m2

Figure 2.3. The figure-eight solution. The three equal masses chase
each other in a figure-eight formation.

Although the solution is not as useful in analysing the problem as Euler or La-
grange’s, it is notable for being discovered so recently. Its discovery led to what
have been termed N -body choreographies, periodic solutions to the N -body prob-
lem where all bodies trace out the same path in space. These choreographies were
studied by Carlés Simó who found many highly unlikely but extremely interesting
orbits. The ongoing research into these kinds of orbits has led to some interesting
considerations into the general N -body problem when Einstein’s theory of Gen-
eral Relativity is taken into account. For more on these orbits, and some extremely
interesting examples, see [13].
2.2.4. Hill’s Solutions. Of much more practical importance are what are termed
“Hill’s solutions”1 to the problem, also known as tight binaries. These solutions
are very familiar, corresponding to the dynamics of the Sun-Earth-Moon system.
In Hill’s solution, two of the masses will remain close to each other and form a bi-
nary which will orbit the third body which remains further away. This is illustrated
in Figure 2.4.
The kinds of orbits described by Hill are the most commonly occuring “nice”
orbits, and examples can be found for any sufficiently low energy. These orbits
will show up clearly in the model developed in this project.
1Despite the name, these do not necessarily occur as explicit solutions like Euler and Lagrange’s
solutions do.
8 2. BACKGROUND

Figure 2.4. An example of a Hill Solution.

m1=3

m3=5 m2=4

Figure 2.5. Left: The initial condition considered by the Pythagorean


problem. The bodies have masses in the ratio 3:4:5 and are at the vertices
of the 3-4-5 right angled triangle. Right: an illustration of the usual
limiting behaviour of the Pythagorean Problem (and many other initial
conditions), an escape orbit.

2.2.5. The Pythagorean Problem. The final set of “particular”2 orbits we


consider is the so-called Pythagorean problem. The Pythagorean problem consid-
ers an initial configuration of the three bodies with masses of 3, 4 and 5 units places
at the corresponding positions on a right angled triangle (see Figure 2.5). It was
2Though as we shall see, there is nothing truly “particular” about them.
2.3. L AGRANGIAN AND H AMILTONIAN M ECHANICS 9

theorised by Ernst Meissel that such a configuration would lead to periodic orbits.
By the 1960s, computers were sufficiently advanced to numerically integrate the
problem (as we shall in this paper) and it was demonstrated that the orbits were
not periodic, nor particularly unique. However, they did demonstrate a very typical
behaviour of the system: one of the three masses drifts away from the others, leav-
ing a stable binary system behind (Figure 2.5). This is common for our restricted
problem, and for high energies is the norm rather than an exception. Such orbits
are known as escape orbits.

2.3. Lagrangian and Hamiltonian Mechanics


Although the three body problem can be analysed from the equations of motion
given by classical (or Newtonian) mechanics, in this project we will use the Hamil-
tonian approach. The neccesary theory will be outlined here; for a more thorough
treatment, see [6].
The theory of Lagrangian mechanics was first formulated in 1788 by Lagrange.
Unlike in Newtonian mechanics, where a rectangular coordinate system is regu-
larly used, Lagrangian mechanics gives a much more natural way of considering
generalized coordinate systems.
For instance, consider the problem of calculating the motion of a pendulum
swinging in a two-dimensional plane under the force of gravity. The Lagrangian
formulation of this problem can be made in terms of the angle the pendulum
sweeps, rather than the x and y coordinates. Thus the problem has one degree
of freedom only, in a very natural way. This use of generalised coordinates to
incorporate constraints is a major advantage of Lagrangian mechanics.
Having established an appropriate set of coordinates, the Lagrangian itself is a
function which is constructed as
(2.2) L =T −V
where L is our Lagrangian function (or simply Lagrangian), T is the kinetic energy
of the system, and V is the potential energy of the system, all written in terms of the
generalised coordinates qi , the corresponding velocities q̇i , and the time t. Once
this formula has been derived, the Principle of Least Action gives the Lagrange
equations
 
∂L d ∂L
(2.3) = i = 1, 2, ..., n.
∂qi dt ∂ q̇i
These are n second-order differential equations for each qi . In principle, these
equations can be solved for a given initial condition to find the subsequent motion
of the system.
If the Lagrangian function does not depend on time, the system is autonomous.
In this case, we have that
( n )
d X ∂L
(2.4) q̇i − L = 0.
dt ∂ q̇i
i=1

Thus the quantity E = ni=1 q̇i ∂L∂ q̇i − L is constant, and is called the energy.
P
10 2. BACKGROUND

A refinement to these ideas came in 1833, when William Hamilton introduced


Hamiltonian mechanics. The Hamiltonian formalism follows naturally from the
Lagrangian formalism, but has some distinct differences. To switch from the La-
grangian formulation to the Hamiltonian formulation, a Legendre transform yields
X n
(2.5) H = pi q̇i − L .
i=1
The Hamiltonian H must be written in terms of the coordinates qi , the conjugate
momenta pi and time t. If the Lagrangian can be written as
1
(2.6) L = q̇T T q̇ + ΩT q̇ − V (q)
2
then the corresponding Hamiltonian is
1
(2.7) H = (p − Ω)T T − 1(p − Ω) + V (q).
2
Having constructed the Hamiltonian, rather than n second-order differential
equations, we now have 2n first-order differential equations
∂H ∂H
(2.8) q̇i = ṗi = − .
∂pi ∂qi
These are called Hamilton’s equations, and again can be solved to give the evolu-
tion of the system over time.
A useful property of the Hamiltonian is that the conservation of energy de-
scribed above is now simplified to E = H . Again, this only applies to time-
independent Hamiltonians. We will be exploiting this identity throughout the
project.
As noted, much of the power of the Hamiltonian comes from the idea of gen-
eralised coordinates. We therefore need to construct coordinate and momentum
transformations that preserve the Hamiltonian structure (that is, Hamilton’s equa-
tions will still be valid). Such transformations are called canonical transforma-
tions, between sets of canonical coordinates. These transformations are usually
calculated using generating functions. For a more thorough discussion of the theory
of generating functions see [6]. We include the results and equations for reference.
There are four kinds of generating functions, each of which give a relationship be-
tween two sets of canonical coordinates q1 , ..qn , p1 , ...pn and Q1 , ...Qn , P1 , ...PN .
By taking a function of some combination of old or new coordinates and old or new
momenta, a canonical transformation is induced according to the table below3.

3These generating functions can depend on time; for this project, we will not need this detail,
so it is omitted.
2.3. L AGRANGIAN AND H AMILTONIAN M ECHANICS 11

Function Induced Transformation


∂F1 ∂F1
F1 (qi , Qi ) pi = ∂qi Pi = − ∂Q i

F2 (qi , Pi ) pi = ∂F
∂qi
2
Qi = ∂F2
∂Pi

F3 (pi , Qi ) qi = − ∂F
∂pi
3 ∂F3
Pi = − ∂Q i

F4 (pi , Pi ) qi = − ∂F
∂pi
4 ∂F4
Qi = ∂Pi
C HAPTER 3

Setting Up the Three Body Problem

3.1. The Two Body Problem: exact solution


To begin our analysis, we present a brief treatment of the two body problem.
The exact solution of the two body problem is a well known result, but foreshadows
some concepts we need again later.
Consider two bodies of mass m1 , m2 and position r1 , r2 respectively (the same
results hold for r1 and r2 in R2 or R3 ). The only force acting upon each body is
the pull of gravity from the other. Then the Lagrangian describing their motion is
1 1 Gm1 m2
(3.1) L = m1 |ṙ1 |2 + m1 |ṙ2 |2 + .
|2 {z 2 } |r1 − r2 |
| {z }
Kinetic Energy Potential Energy
Let M = m1 + m2 be the total mass of our system, so the centre of mass is defined
by
m1 r1 + m2 r2
(3.2) rG = .
M
Then the Lagrangian can be written as
1 1 m1 m2 Gm1 m2
(3.3) L = M |ṙG |2 + |ṙ2 − ṙ1 |2 +
2 2 M |r1 − r2 |
(3.4) = LG + LR
where LG depends only on the centre of mass, and LR does not depend on the
centre of mass. As LG does not depend on rG , the centre of gravity moves with a
constant velocity.
Now consider r = r1 − r2 , equivalent to only considering the motion of r1
relative to r2 . Then LR describes a single particle of mass mM 1 m2
travelling around
the gravitational field of a fixed central body of mass M. Its path is therefore a conic
section. We only consider elliptical (or Keplerian) trajectories1.

3.2. The Three Body Problem


3.2.1. The Planar Circular Restricted Three Body Problem. We now in-
troduce the third body into the system. However, before continuing a number of
simplifications are made.
The first and most prominent simplification is that the mass of the lightest body
is negligible. We will refer to this body as a particle. This means the motion of the
1Trajectories can also be parabolic or hyperbolic, but these are not of concern here.

12
3.2. T HE T HREE B ODY P ROBLEM 13

particle will not affect the orbits of the heavier bodies, which we call the primary
masses or just primaries. This simplified system is referred to as the restricted
three body problem.
The next simplification is to fix the orbits of the primaries. As they are only
affected by each other and not the particle, the primaries are a two body system,
which we solved exactly above. Although we discovered that the two body problem
is solved by any conic section, we take a circular orbit for our simplified model.
This is the circular restricted three body problem. As noted previously, this form
of the problem was proposed by Euler.
Our final simplification is to restrict the motion of the particle to the same plane
as the orbit of of the primaries. The orbits thus occur on a two-dimensional plane.
This is the planar circular restricted three body problem, which will be referred to
as the PCR3BP in this paper.

3.2.2. Aside: Relevance of the PCR3BP. We should take a moment to jus-


tify the use of the PCR3BP as an approximation for the full problem. A number
of relevant real-life situations in celestial mechanics are very closely approximated
by the PCR3BP, including models of spacecraft trajectories. Some specific appli-
cations include modelling comets interacting with Jupiter and the sun. The motion
of these comets remain very close to Jupiter’s orbital plane (that is, they remain
near- planar with Jupiter and the Sun). For a thorough examination of the practical
applications of this model, see [22]. The assumptions also allow for the modelling
of trojans, and can predict their existence and trajectories.

3.2.3. Hamilton’s Equations for the PCR3BP. We now derive Hamilton’s


equations for the PCR3BP. Let the test particle (the body of negligible mass) be
denoted P . The primary masses, or simply primaries, are denoted M1 and M2 .
We assume, without loss of generality, that M1 has a mass greater than or equal to
that of M2 . The assumptions of the PCR3BP lead to the following:
• M1 and M2 have circular orbits around their centre of mass
• P remains in the same orbital plane as the primaries.
• The motion of the particle does not affect the motion of the primaries
To nondimensionalise the problem, take
• unit of mass the total of the masses of M1 and M2
• unit of length the distance between the primaries (which will be constant,
as in Section 3.1)
• unit of time such that the period of the orbits of the primaries is 2π
These units force a gravitational constant G = 1 . The only parameter in the
system is the mass parameter µ ∈ [0, 1/2], such that M1 has mass 1 − µ and M2
has mass µ.
Our coordinates have origin at the centre of mass of the two primary masses.
This is fairly standard, although some texts place the origin at the larger of the two
14 3. S ETTING U P THE T HREE B ODY P ROBLEM

Figure 3.1. The simplifications we take to the three body problem. Top
left: the general three body problem. Top right: the restricted three body
problem. Bottom left: the circular restricted three body problem. Bottom
right: the planar circular restricted three body problem.

bodies2. Then the trajectories of the larger bodies are given by

(3.5) (X1 , Y1 ) = (−µ cos t, −µ sin t) (X2 , Y2 ) = ((1−µ) cos t, (1−µ) sin t)

as per Section 3.1.

2for instance, [2].


3.2. T HE T HREE B ODY P ROBLEM 15

Y y

M2
-1+μ -μ 0 +μ 1-μ -μ 0 1-μ
X x
M1 M1 M2

Figure 3.2. At left: fixed coordinates. At right: fixed coordinates for


M1 and M2 and an illustrative path of the particle P.

We define r1 and r2 as the distances of P from M1 and M2 respectively:

r12 = (X + µ cos t)2 + (Y + µ sin t)2


(3.6)
r22 = (X − (1 − µ) cos t)2 + (Y − (1 − µ) sin t)2 .
Then the Lagrangian describing the motion of P is given by
1 1−µ µ
(3.7) Linertial (t, X, Y, Ẋ, Ẏ ) = (Ẋ 2 + Ẏ 2 ) + +
2 r1 r2
This Lagrangian is time dependent. As discussed in Section 2.3, many of the
nice properties of a Lagrangian or Hamiltonian system depend on having a time-
independent system. Thus a transformation is taken to a rotating frame of refer-
ence (see Figure 3.2). This coordinate system also gives clearer insight into many
behaviours of the three body problem, in particular motion near the Lagrangian
points. The transformation is

X = x cos t − y sin t
(3.8)
Y = x sin t + y cos t.
The corresponding velocities transform as

Ẋ = ẋ cos t − ẏ sin t − x sin t − y cos t


(3.9)
Ẏ = ẋ sin t + ẏ cos t + x cos t − y sin t.
The distances become
r12 = (x + µ)2 + y 2
(3.10)
r22 = (x − (1 − µ))2 + y 2
and the new Lagrangian is
16 3. S ETTING U P THE T HREE B ODY P ROBLEM

Figure 3.3. The effective potential, U , plotted against x and y for


µ = 0.3. Note the singularities around (−µ, 0) and (1 − µ, 0) marked
by “holes” in the potential, and the critical points, which coincide with
the Lagrangian points.

1 1−µ µ
(3.11) Lrotating (x, y, ẋ, ẏ) = ((ẋ − y)2 + (ẏ + x)2 ) + + .
2 r1 r2
Now, the Hamiltonian formulation is derived from the Lagrangian formulation.
The conjugate momenta are
∂L ∂L
(3.12) px = = ẋ − y py = = ẏ + x
∂ ẋ ∂ ẏ
and the Legendre transform defined by
(3.13) H = ẋpx + ẏpy − L
gives the corresponding Hamiltonian
(3.14)
µ 1−µ
H (x, y, px , py ) = 1 2 1 2
2 px + px y + 2 py − py x − r1 − r2
1 2 1 2 1 2 1 2 1−µ µ
= 2 (px + y) + 2 (py − x) − 2 x − 2 y − r1 − r2 .

This value is conserved as the Hamiltonian is independent of time. This conserved


value is the Jacobi integral.
We define the effective potential (illustrated in Figure 3.3) by 3

1 1−µ µ
U (x, y) = − (x2 + y 2 ) − −
2 r1 r2
1 1−µ µ
= − {(1 − µ)r12 + µr22 } − −
2 r1 r2
3
We have ignored some constant terms. This is allowed with Hamiltonians as Hamilton’s equa-
tions will remain unchanged, allowing us to add or remove constant terms as we wish.
3.2. T HE T HREE B ODY P ROBLEM 17

and the effective kinetic energy4 by


1
(x − py )2 + (y + px )2 .

(3.15) T (x, y, px , py ) =
2
Then
(3.16) H (x, y, px , py ) = T (x, y, px , py ) + U (r1 , r2 )
where U depends only on the location of the particle. (Note that we have written
U in terms of r1 and r2 ; this is for convenience in our later calculations.)
We now have Hamilton’s equations for the motion of the particle:
∂H
(3.17) ẋ =
∂px
= Tpx

∂H
(3.18) ẏ =
∂py
= Tpy

∂H
(3.19) p˙x = −
∂x
= −Tx − Ux
∂r1 ∂r2
= −Tx − Ur1 − Ur2
∂x ∂x
∂H
(3.20) p˙y =
∂y
= −Ty − Uy
∂r1 ∂r2
= −Ty − Ur1 − Ur2 .
∂y ∂y
It is often useful to recontextualise the Hamiltonian in complex space. If
z = x + iy and pz = px − ipy 5 then
1 1 1−µ µ
(3.21) H = |z + ip̄z | − {(1 − µ)r12 + µr22 } − −
2 2 r1 r2
1 1−µ µ
= (pz p̄z + i(zp¯ z − zpz )) − −
2 r1 r2
(3.22) r1 = |z + µ| r2 = |z − (1 − µ)|.
4It should be emphasised that this value is not the kinetic energy of the particle; this particular
splitting is made for mathematical convenience rather than physical reasons.
5Strictly speaking, this transformation is not canonical. The Poisson bracket
(an object which can be used to test if a given transformation is canonical) is
{z, pz } = {x + iy, px − ipy } = {x, px } + {y, py } = 2 rather than 1. If we scale the
√ √
variables as z = 1/ 2(x + iy), pz = 1/ 2(px − ipy ), then the transformation is canonical. In
practice, we can safely ignore this point, particularly as the equations will be converted back into
separate coordinates at the final step.
18 3. S ETTING U P THE T HREE B ODY P ROBLEM

(-μ,0) (1-μ,0)

Figure 3.4. The five fixed points for the particle, or Lagrangians, marked in red.

3.3. Dynamics of the Three Body Problem


3.3.1. The Lagrangian Points. Important in our analysis are the equilibria of
the system, which are referred to as the Lagrangian points in this context. There
are five of these points, and we use the equations of motion from the Hamiltonian
(3.14) to calculate them. By setting ṗx = 0, ṗy = 0 we get the following equations:
0 = (x + µ) (1 − µ)(r1−3 − 1) + µ(r2−3 − 1) − µ(r2−3 − 1)

(3.23)
0 = y (1 − µ)(r1−3 − 1) + µ(r2−3 − 1) .

(3.24)
If y 6= 0, it follows that
(3.25) r1 = r2 = 1
and so there are two Lagrangian points, denoted L4 and L5 , located at the third
vertex of the two equilateral triangles

with the two primary √
masses as vertices. The
exact coordinates are L4 (−µ + 2 , 2 ) and L5 (−µ + 2 , − 23 ).
1 3 1

If y = 0, then r1 = |x + µ| and r2 = |x − 1 + µ| so
1 1
(3.26) 0 = −x + (x + µ)(1 − µ) 3
+ µ(x + µ − 1) .
|x + µ| |x + µ − 1|3
This has one solution in each of the ranges (−∞, −µ), (−µ, 1−µ) and (1−µ, ∞).
These solutions can be calculated numerically as they are the roots of polynomials.
It is important to consider the stability of these Lagrangian points as well. L1 ,
L2 and L3 are always unstable. L4 and L5 are stable only p for certain values of the
mass ratio; specifically, only when M1/M2 > 25 2 (1 + 1 − 4/625) ≈ 24.96. For
 −1
our system, this becomes µ < 25
p
2 (1 + 1 − 4/625) + 1 ≈ 0.0385 (these
figures are derived in [6]).
3.4. T HE P OINCARÉ M AP 19

As L4 and L5 are stable, it is possible for an orbit to perpetuate around these


points. Objects which have orbits around L4 or L5 are called trojans. These trojans
will be studied closely in Chapter 5.
3.3.2. Energy and the Hill Region. As our Hamiltonian is independent of
time, the Hamiltonian is conserved. We refer to this as the Energy E. Having
established this, we can define the energy manifold:
(3.27) M (E, µ) = {(x, y, px , py ) | H(x, y, px , py ) = E} .
This is a three-dimensional surface in our four-dimensional phase space on
which P travels. This is defined for particular values of the parameter µ and a par-
ticular fixed energy level E, which will both be manually selected in our numerical
computation. This is a general construction for time-independent Hamiltonians.
As the kinetic energy T ≥ 0 and the effective potential U does not depend on
px or py , we can easily project this manifold onto x − y space:
(3.28) M̄ (E, µ) = {(x, y) | U (x, y) ≤ E} .
This is known as Hill’s region. Hill’s region is easily calculated and provides
useful information about the path of the orbits. There are five possible shapes for
Hill’s region, which are illustrated in Figure 3.5.
Note that the critical points of the effective potential coincide with the La-
grangian points, as shown in Figure 3.3. This will prove useful in our later analysis.
In particular, we can calculate the curve of critical values in E - µ space for L4 and
L5 6:
(3.29)
E = U (x, y) (for critical points)
1 µ 1−µ
= − {µr12 + (1 − µ)r22 } − − + µ(1 − µ)
2 r1 r2
1
= − {µ + 1 − µ} − µ − 1 − µ + µ(1 − µ) (r1 = r2 = 1 at L4,5 )
2
3
= − + µ(1 − µ).
2
3.4. The Poincaré Map
To help analyse the orbits, we can take a Poincaré map. A Poincaré map gives
the intersection of an orbit with a particular subspace, called the Poincaré section.
It is typically used for periodic orbits. The map takes a point in this fixed section,
and gives the next intersection between the corresponding orbit and the section.
Definition 3.30 (Poincaré map). Given a function Φ defining an n-dimensional
dynamical system, and S an n − 1 dimensional surface, a diffemorphism
(3.31) P :S→S
6Note that we briefly reintroduce the constants that were dropped previously; this is for consis-
tency with the program to be developed in Chapter 5
20 3. S ETTING U P THE T HREE B ODY P ROBLEM

Figure 3.5. The five possible shapes for Hill’s region. The five figures
show Hill regions for decreasing values of the energy E from top to
bottom. The white area is the region of possible motion, or Hill’s region,
and the grey area is the so-called “forbidden region". Also shown are
the Lagrangian points, which coincide with the critical points of Hill’s
region. Compare these regions to the potential function in Figure 3.3.
Also compare the critical points with the Lagrangian points in Figure
3.4.
3.4. T HE P OINCARÉ M AP 21

x
P(x) S

Figure 3.6. A Poincaré Map P . The map takes points on the surface S
to the next point where the orbit intersects the surface.

is a Poincaré map (or first return map) if for every point x ∈ S, ∃τ ≥ 0 such that
Φτ (x) ∈ S and Φt (x) ∈ / S ∀ 0 ≤ t < τ and P (x) = Φτ (x). S is called the
Poincaré section.

For our Poincaré maps, we will also take only the intersecting points that have
the same orientation. These ideas are illustrated in Figure 3.6.
Having defined this map, we can now characterise orbits based on the Poincaré
map’s action on the initial condition. For a periodic orbit, there exists some n ∈ N
such that

(3.32) P n (x) = x.

We can also define a set

(3.33) R(x) = {P n (x)|n ∈ N}.

For a periodic orbit, this set will be finite. As we will see, the nature of this set can
be used to classify particular classes of orbits.
For a fixed energy, our system is restricted to the three dimensional energy
manifold in equation (3.27). We should thus take a two dimensional section S ⊂ M .
In general for a Hamiltonian with n spatial dimensions, we can take an n − 2 di-
mensional section.
For this project, we will initially consider the section defined by

(3.34) S1 (E; µ) = {(x, y, px , py )|(x, y, px , py ) ∈ M (E; µ); y = 0; py > 0} .

This section is quite simple. The corresponding map calculates the next in-
tersection of the particle with the x-axis, with a positive y-momentum. We can
project the section into x − px space, which allows us to visually acquire a lot of
information about the dynamics of the system.
22 3. S ETTING U P THE T HREE B ODY P ROBLEM

When the user makes a selection in the x − px space, this uniquely defines an
initial condition. The fixed parameters E and µ are used to calculate py . Rearrang-
ing equation (3.14),
 
1 2 1 1−µ µ
(3.35) py − xpy + −E + p2x + ypx − − = 0.
2 2 r1 r2
As E, µ, x and px have been chosen by the user, and y has been defined by the
section, the quadratic in py can be solved to give the complete initial condition,
with the choice of root determined by the condition py > 0.
A second useful section for this problem is
S2 (E; µ) = {(x, y,px , py )|(x, y, px , py ) ∈ M (E; µ);
(3.36) √
y = 3(x + µ); pperp ≥ 0}.

This section is a line passing through the primary at (−µ, 0) and L4 . We define
pperp as the momentum in the direction perpendicular to this line
1 √
(3.37) pperp = (px − py 3)
2
and the momentum parallel to this line as
1 √
(3.38) pnorm = (px 3 + py ).
2
We can then project the section down to x − pnorm space as we did for the
previous section. The reason we study this section and the associated map is that it
allows us to see the dynamics of orbits around L4 , which will not show up on S2 .
As before equation (3.35) is used to determine the full initial condition (although
it must be rewritten in terms of pperp and pnorm ).
One note here is that for the above sections, P (x) is not necessarily well-
defined for all x ∈ S. In particular for S2 , the corresponding map P2 is undefined
for any particle that will subsequently orbit about the primary at M2 . There is no
reason why P should be well defined everywhere for an arbitrarily constructed S.
However, in practice this becomes irrelevant. The maps allow us to see partic-
ular orbits we are interested in, and ignore the orbits for which P (x) is undefined.
S1 is used to analyse orbits around either or both of the two primaries, while S2 is
used to analyse behaviour near L4 . If other behaviours need to be considered, new
sections can be defined.

3.5. The Extended Phase Space


In the next chapter, time transformations will be applied to our Hamiltonian.
For these transformations to be symplectic (that is, preserve the Hamiltonian struc-
ture), we introduce the concept of the extended phase space. In the extended phase
space, we consider the time as “just another coordinate”, allowing the construction
of time transformations as canonical transformations.
3.5. T HE E XTENDED P HASE S PACE 23

Consider a general time-independent Hamiltonian H (q1 , ..., qn , p1 , ...pn )7. For


this system, we have t as not only the integration variable but also as a physical pa-
rameter of the system. To generalise our Hamiltonian formulation, we remove this
double-duty and let t be treated the same as the other coordinates, qn+1 = t. Then
we need a new integration variable s, parametrising time as t(s). Adjusting this
parametrisation amounts to a time transformation.
If we introduce time as a coordinate, we must also introduce its conjugate
momentum, pn+1 . It can be shown that this conjugate momentum is pn+1 = −E,
the energy of the Hamiltonian. Then
(3.39) Hˆ (q1 , ..qn , t, p1 , ...pn , E) = H (q1 , ...qn , p1 , ...pn ) − E
is the new Hamiltonian in the extended phase space, with s our new variable of
dt ∂H
integration. Hamilton’s equation for t is simply ds = ∂(−E) = 1, so t and s are
equivalent. Hamilton’s equations for the other coordinates are preserved. If we
now need to take a time transformation of the form τ = f (q1 , ...qn )t, it suffices to
define
(3.40) H¯ (q1 , ..qn , τ, p1 , ...pn , E) = f (q1 , ...qn )Hˆ (q1 , ..qn , t, p1 , ...pn , E)
= f (q1 , ...qn ) (H (q1 , ...qn , p1 , ...pn ) − E) .
Constructing these new Hamiltonians ensures our time transformations are
canonical, and Hamilton’s equations will remain valid. For a more thorough treat-
ment of these concepts, see [15].

7This theory is usually derived for a time-dependent Hamiltonian, but is simplified here for
clarity.
C HAPTER 4

Regularisations and other Numerical Considerations

Having derived the necessary equations of motion, the next step is to develop
a robust integrator for these equations. This requires a discussion of some key
concerns of the problem, most notably the regularisation of collision orbits. This
chapter will also discuss some candidates for the integrator and other relevant nu-
merical concerns.

4.1. Splitting Method for Hamiltonian


A very powerful method for integrating Hamilton’s equations is the use of a
split step integrator. It works by splitting the Hamiltonian into parts, which can
often be integrated exactly.
The idea for a Hamiltonian split step integrator is a specific example of a more
general idea. For y ∈ Rn , fi : Rn → Rn for i = 1, 2, consider the system defined
by
(4.1) ẏ = f1 (y) + f2 (y).
Then if φt is the flow induced by the system above, and φ1t and φ2t are the flows
induced by ẏ = f1 (y) and ẏ = f2 (y) respectively, we can make the approximation
(4.2) φt ∼ φ1t/2 ◦ φ2t ◦ φ1t/2 .
This is known as a Strang splitting, and is a second-order method. More complex
integrators of this type can be constructed by composing more φ1αt and φ2βt with
appropriate choices of α and β. Further analysis of this process is given in Hairer
[17].
In particular, in the case of a Hamiltonian, the Hamiltonian often has the nat-
ural splitting H = T + V . We can define φTt and φVt as the flows induced by
considering T and V as separate Hamiltonians. Usually with Hamiltonians, T de-
pends only on momentum and V only on position, which makes the corresponding
flows very simple. In our case, T depends on position and momentum, but we can
still solve for the flow exactly. This idea is often known as a symplectic integrator,
as φTt will conserve the kinetic energy and φVt will conserve the potential energy.
Following on from (3.15), the differential equations for the flow induced by T
are
(4.3) ẋ = Tpx = px + y ẏ = Tpy = py − x
p˙x = −Tx = py − x p˙y = −Ty = −px − y
or, in matrix form,
24
4.2. R EGULARISING C OLLISION O RBITS 25

 
0 1 1 0
 
−1 0
 
0 1
(4.4) ẋ = 
  x = Ax.
−1 0 0 1

 
0 −1 −1 0
We can explicitly calculate etA , giving the exact solution
x(t) =A1 sin 2t + A2 cos 2t + C1
y(t) =A1 cos 2t − A2 sin 2t + C2
px (t) =A1 cos 2t − A2 sin 2t − C2
py (t) = − A1 sin 2t − A2 cos 2t + C1

where
1 1
A1 = (y(0) + px (0)) A2 = (x(0) − py (0))
2 2
1 1
C1 = (x(0) − py (0)) C2 = (y(0) − px (0)).
2 2
We can also calculate an explicit flow for the Hamiltonian given by U . The
differential equations are
(4.5) ẋ = 0 ẏ = 0 p˙x = −Ux p˙y = −Uy .
As U depends only on x and y, the flow is (left in terms of partial derivatives
for brevity)
x(t) =x(0) y(t) =y(0)
px (t) = − Ux (x(0), y(0))t + px (0) py (t) = − Uy (x(0), y(0))t + py (0).
Having calculated φTt and φU t explicitly, the value of the splitting method is
clear. We can substitute these into (4.2) to get
(4.6) φH U T U
t ∼ φt/2 ◦ φt ◦ φt/2 .

This integrator is accurate to second order. For our problem, this is more than
adequate for many orbits. However, U and Ux,y have singularities at r1 , r2 = 0.
As the orbits approach these points, the integrator becomes increasingly and fatally
unstable. To be able to consistently and accurately integrate around these points,
we must deal with these singularities.

4.2. Regularising Collision Orbits


4.2.1. Collision Orbits. Of the utmost importance in any attempt to integrate
the three body problem is the consideration of collision orbits. These are the orbits
which begin or end with r1 = 0 or r2 = 0, where our established equations of
motion demonstrate singularities. For an integrator to be useful, it must be stable
26 4. R EGULARISATIONS AND OTHER N UMERICAL C ONSIDERATIONS

around these singularities. In particular, when determining trajectory of a probe


from one planet to another, the probe will typically begin and end at the surface
of the bodies, and so the calculations must be accurate there1. Another reason the
integrator must be accurate near the primaries is the consideration of low energy
trajectories which rely on the slingshot effect whereby a probe passes very close to
planets and moons to achieve a “boost”. This is discussed futher in [22].
U has simple poles at r1 , r2 = 0. The singularities are non-essential, so we can
manage them by taking transformations. This process is called the regularisation
of collision (and near-collision) orbits. The process is to transform the plane to
describe orbits which do collide with the primaries, as well as improve the stability
of integrating orbits which come close to the primaries. The next step will be a
time transformation, equivalent to taking smaller integration steps as the particle
approaches the primaries.

4.2.2. Regularising Transformations. To transform our system of equations


to one which we can numerically integrate without issue, we will take two steps: a
regularising transformation and a time transformation.
To make our transformations more legible, the Cartesian plane is transformed
into the complex plane, introducing the variable z = x + iy. The corresponding
momentum transformation is then pz = px − ipy . 2
Then a general coordinate transformation has the form
(4.7) w = f (z), f : C → C.
This represents a conformal mapping of the plane, controlling the shape of the
orbit. Figure 4.1 illustrates this.
The corresponding canonical momentum transformation can be calculate using
the generating function
(4.8) F2 (z, pw ) = wpw
= f (z)pw .
Then
∂F2
(4.9) pz =
∂z
= f 0 (z)pw
and so
pz
(4.10) pw = 0
.
f (z)

1It should be noted that our derivation assume a point mass for both the primaries and the par-
ticle.. However, the difference in scale between the distance between planets and their diameters, as
well the relative symmetry of the bodies, means that point masses are a very practical approximation.
Relatively few changes need to be made to the model to allow for trajectories which actually begin
and/or end on the surface of a planet.
2Recall that p = p + ip is not a canonical transformation.
z x y
4.3. L OCAL R EGULARISATION 27

Then an elegant result exists for an appropriate time transformation associated


with a given regularisation. As the introduction of pw introduces a singularity at
f 0 (z) = 0, we should take the time transformation defined by
dt
(4.11) = |f 0 (z)|2

(where t is the “real” time scale and τ is our transformed time scale). The mult-
plicative factor of |f 0 (z)|2 will cancel with the singularity introduced by |pw |2 .
This will transform our equations such that a constant dτ timestep will give a sta-
ble integrator around the primaries. For a more detailed proof and discussion of
this result, as well as further motivation and discussion for the transforms used in
this chapter, see Szebehly’s Theory of Orbits [16].
As there are two singularities in our problem, we have a few choices. We
can take local regularisations, where only one singularity is removed, or a global
regularisation, where both are removed3. Each of these approaches has advantages
and disadvantages, and we shall explore both options.

4.3. Local Regularisation


A simple approach is to take a local regularisation, removing only one singu-
larity. We consider the Levi-Civita transformation, named for Tullio Levi-Civita
who developed the transform when considering the two body problem. The trans-
formation is given by
(4.12) z = w2 − µ
for regularising collision orbits with the primary at (−µ, 0), illustrated in Figure
4.1. The corresponding transform for regularising collision orbits near the other
primary is z = w2 + 1 − µ. This transformation takes the primary at (−µ, 0)
to the origin, and the primary at (1 − µ, 0) to ±1. Although the transformation
is not bijective,
√ this has no real impact on our calculations. We can thus choose
w = + z + µ (taking the principal complex square root) as our inverse.
The theory of canonical transformations affords pw , the conjugate momenta
to w that preserves Hamilton’s equations. We construct the generating function
(4.13) F2 (z, pw ) = wpw

= z + µpw .
Then
∂F2
(4.14) pz =
∂z
pw
= √
2 z+µ
pw
= .
2w
So the canonical momentum transformation is pw = 2wpz .
3It should be noted that the terminology “local” and “global” here is Birkhoff’s, and has no
deeper mathematical interpretation.
28 4. R EGULARISATIONS AND OTHER N UMERICAL C ONSIDERATIONS
Collision Orbits in q−space
2

1.5

0.5

Im(q)
0

−0.5

−1

−1.5

−2
−5 0 5
Re(q)
Collision Orbits in w−space after local transformation at q=−0.5
2.5

1.5

0.5
Im(w)

−0.5

−1

−1.5

−2

−2.5
0 0.5 1 1.5 2 2.5
Re(w)
Collision Orbits in w−space after Thiele−Barrau transformation
3

1
Im(w)

−1

−2

−3
0 0.5 1 1.5 2 2.5 3 3.5
Re(w)

Figure 4.1. An illustration of some regularisations of the plane. In each


diagram, the primaries are marked by a *. Top: several curves in z-space
(before regularisation) for µ = 1/2. Middle: the same curves after the
Levi-Civita transformation is taken to regularise collisions with z = − 21
only. Bottom: the same curves after taking the Thiele-Burrau transfor-
mation. Note that the curves are not actual orbits and are included only
to illustrate the regularisation process.

As r1 = |z + µ| = |w2 | and r2 = |z − 1 + µ| = |w2 − 1|, we can easily rewrite


the effective potential under this transformation:
1 1−µ µ
(4.15) U (r1 , r2 ) = − {(1 − µ)r12 + µr22 } − −
2 r1 r2
1 1−µ µ
= − {(1 − µ)|w|4 + µ|w2 − 1|2 } − 2
− 2 .
2 |w| |w − 1|
4.4. G LOBAL R EGULARISATIONS 29

This, along with the same transformation of the kinetic energy T , define a new
Hamiltonian H1 (w, pw ). The details are omitted here for brevity.
Similarly, for regularisation about the primary at (1 − µ, 0), the transformation
is
p
(4.16) w = z − 1 + µ pw = 2wpz
and the effective potential becomes
1 1−µ µ
(4.17) U (w) = − {(1 − µ)|w2 + 1|2 + µ|w|4 } − 2 − .
2 |w + 1| |w|2
4.3.1. Time Transformations. The next step is to take the time transforma-
tion. As we have established the structure of the extended phase space in 3.5 and
calculated the form of the time transformation, most of the work is already done.
We first define our extended phase space Hamiltonian
(4.18) Ĥ1 (w, t, pw , E) = H1 (w, pw ) − E
(the energy E is invariant under our transformations) and then take the time trans-
formation given by Equation (4.11)
(4.19) H̄1 (w, t, pw , E) = |f 0 (w)|2 Ĥ1 (w, t, pw , E)
= 4|w|2 Ĥ1 (w, t, pw , E).
The |w|2 cancels with the singularity in the potential at w = 0. Analogously,
we can derive a Hamiltonian H̄2 (w, t, pw , E) for orbits passing near the other pri-
mary.
The integration process is now
Algorithm 4.20 (Local Transformation Integrator). For some fixed θ < 12 ,
1. If r1 < θ, take a (Euler, Runge-Kutta, etc) dt integration step in φH̄
t
1
(the flow
induced by H̄1 )
2. Else, if r2 < θ, take a dt step in φH̄
t
2

H
3. Else, take a dt step in φt
4. Repeat
Such an integrator works, but is inelegant. The natural question is can we
develop a transformation that regularises both singularities at once? In the next
section we will see two examples of exactly that: the Birkhoff transformation and
the Thiele-Burrau transformation

4.4. Global Regularisations


4.4.1. The Birkhoff Transformation. The first step in developing our global
transformations is to translate the origin so the primaries are at (−1/2, 0) and
(+1/2, 0). This lends some symmetry and simplification to our transformation
functions. The canonical transformation is given by
1
(4.21) q =z+µ− , pq = pz
2
30 4. R EGULARISATIONS AND OTHER N UMERICAL C ONSIDERATIONS

(z = x + iy, as previously). Now r1 = |q + 12 | and r2 = |q − 21 |.


To motivate Birkhoff’s transformations, we look at transformations of the form
(4.22) q = f (w) = αw + βw−1 .
The inverse transformation is then
p
q± q 2 − 4αβ
(4.23) w=

and if we again take the time transform as defined by (4.11)
dt |αw2 − β|2
(4.24) = |f 0 (w)|2 = .
dτ |w|4
Then the singular part of the potential is
1−µ µ 1−µ µ
(4.25) + = +
r1 r2 |αw + βw + 2 | |αw + βw−1 − 12 |
−1 1

(1 − µ)|w| µ|w|
(4.26) = +
|αw + β + 2 w| |αw + β − 12 w|
2 1 2

and applying the time transformation gives


(4.27) !
2 − β|2 2 − β|2
 
1 − µ µ 1 (1 − µ)|αw µ|αw
|f 0 (w)|2 + = + .
r1 r2 |w|3 |αw2 + β − 12 w| |αw2 + β + 12 w|
Now, our primaries are at q = ± 12 . We wish to eliminate the singularities at
these points, and so we need q = ± 12 to be a factor of the numerators. At q = 12 , we
1 √
have w = 4α 1 ± 1 − 16αβ . But roots of the numerators in (4.27) are given
q
by w = ± αβ , so
r
1  p  β
(4.28) 1 ± 1 − 16αβ = ±
4α α
(4.29) 16αβ = 1.
We can now force ( 12 , 0) to be a fixed point of our equation, giving 1
2 = 1
4α .
Thus α = 12 and β = 81 . The completed transformation is
w 1 1 1
(4.30) q= + = (2ω + ).
2 8w 4 2ω
It should be noted from equation (4.27) that a singularity has been introduced
in the potential at |w| = 0. However this is not an issue, as this corresponds to
|q| → ∞. We can thus say our transformation regularises all points in the finite
plane. The details of the behaviour as |q| → ∞ are not interesting in our problem;
this is just our particle floating off into empty space, an escape orbit.
A neat result is the relationship between the distances in the w plane and in the
q plane. If
1 1
(4.31) ρ1 = |w + |, ρ2 = |w − |, ρ = |w|
2 2
4.5. T HE T HIELE -B URRAU T RANSFORMATION 31

and r1 , r2 are as defined previously, then


ρ21 ρ22 r1 r2
(4.32) |f 0 (w)|2 = 4
= 2
4ρ ρ
ρ 2
(4.33) r1 = 1

ρ2
(4.34) r2 = 2

so
ρ21 ρ22 1
|f 0 (w)|2 U = (1 − µ)ρ41 + µρ42 + 3 (1 − µ)ρ22 + µρ21 .
 
(4.35) 6
32ρ 2ρ
Then HBirkhoff can be constructed in the extended phase space exactly as it
was in the case of the local transformation, and we have a globally regularised
Hamiltonian.

4.5. The Thiele-Burrau Transformation


Although the Birkhoff transformation is easier to motivate and construct al-
gebraically, the resulting Hamiltonian is quite messy, and retrieving Hamilton’s
equations worse again. Therefore, we look at the Thiele-Burrau transformation, a
connected transformation that yields equations that are easier to manipulate.
Constructed first by Thorvald Thiele for the µ = 12 case, the transformation
was generalised by Carl Burrau for other values of µ (see [16] for futher back-
ground). It is defined in the q plane by
1
(4.36) q = cos w
2
(the complex-valued cos function) or, equivalently
1 1
(4.37) q = (eiw + iw ).
4 e
The canonical momentum transformation is
−2pw
(4.38) pq = .
sin w
One can compare equations (4.37) and (4.30) to see the close relationship be-
tween the Birkhoff and the Thiele-Burrau. In fact, if we let wB be the coordinates
defined by the Birkhoff transformation, and wT be the coordinates defined by the
Thiele Burrau transformation, we can confirm that
(4.39) 2wb = eiwT .
We will include the details for the transformation in this case, as we will be
using the calculations in our final integrator. Working from equation (3.21),
1 1−µ µ
(4.40) H (z, pz ) = |z + ipz |2 − µr12 − (1 − µ)r22 − −
2 r1 r2
1 1−µ µ
= (pz pz + i(zpz − zpz )) − −
2 |z + µ| |z − 1 + µ|
32 4. R EGULARISATIONS AND OTHER N UMERICAL C ONSIDERATIONS

1
(4.41) H (q, pq ) = (pq pq + i(qpq − qpq + (1/2 − µ)(pq − pq )))
2
1−µ µ
− −
|q + /2| |q − 1/2|
1

1 −2pw −2pw 1 −2pw


(4.42) H (w, pw ) = + i( cos w
2 sin w sin w 2 sin w
!
1 −2pw −2p w −2p w
− cos w + (1/2 − µ)( − ))
2 sin w sin w sin w
1−µ µ
− − 1 .
| 21 cos w + 1/2| | 2 cos w − 1/2|
In extended phase space, the time transformed Hamiltonian is

(4.43) K (w, t, pw , E) = |f 0 (w)|2 (H (w, pw ) − E)


1
= sin2 w (H (w, pw ) − E) .
4
Using a computer algebra package, we can expand this in terms of u, v, pu and
pv , where w = u + iv and pw = pu − ipv . A useful identity here is
(4.44) sin2 w = (cosh2 v − cos2 u).
The full Hamiltonian is
p2u p2v 1
(4.45) K (q, t, pq , E) =
+ + (cos u − 2µ cos u − cosh v)
2 2 2
1
+ sin u(cosh v − 2µ cosh v + cos u)pv
4
1
+ sinh v(cos u − 2µ cos u + cosh v)pu
4
1
+ (cos(2u) − cosh(2v))E
8
which yields the system of Hamilton’s equations 4
1
(4.46) u̇ = pu + ((1 − 2µ) cos u + cosh v) sinh v
4
1
(4.47) v̇ = pv + (cos u + (1 − 2µ) cosh v) sin u
4
(1 − 2µ) sin u pv sin2 u (1 − 2µ) sin u sinh vpu
(4.48) p˙u = + +
2 4 4
(cos u − (1 − 2µ) cosh v) cos upv E sin(2u)
+ +
4 4
4Care should be taken here to note that u̇ etc. now refer to derivatives with respect to τ , our new
integration variable, rather than t.
4.6. N UMERICAL S CHEME 33

sinh v sinh2 vpu (cosh v − (1 − 2µ) cos u) cosh vpu


(4.49) p˙v = − +
2 4 4
(1 − 2µ) sin u sinh vpv E sinh(2v)
− + .
4 4
For completeness, we should note that the extended variables evolve according
to
(4.50) Ė = 0
as we’d expect for a system with constant energy, and
1
(4.51) ṫ = (cos(2u) − cosh(2v))
8
1
= (cos2 u − cosh2 v)
4
dt
which corresponds to the time transformation dτ taken in (4.43).
We thus have a complete description of the regularised system. It is this trans-
formation that will be implemented in the integrator we will develop in the next
chapter.

4.6. Numerical Scheme


Having derived the equations of motion, we now need to develop an numerical
integrator. Unfortunately, a splitting method as per Section 4.1 is not obvious.
Fortunately, equations (4.46) to (4.49) do not require a consideration of the step
size or distance from the singularities thanks to the regularisation process. Thus, we
can “blindly” integrate them using an off-the-shelf method such as Runge-Kutta.
The Runge-Kutta methods are iterative methods used to approximate solutions
to systems of ordinary differential equations. We take the fourth-order Runge-
Kutta scheme, known as RK4. In general, the scheme is given as:
Algorithm 4.52 (Fourth Order Runge-Kutta scheme). For a system given by
(4.53) ẋ = f (t, x) x(t0 ) = x0 .
for some timestep ∆t, the approximation to x(t0 + ∆t) is given by
1
(4.54) x(t0 + ∆t) = x(t0 ) + (k1 + 2k2 + 2k3 + k4 )
6
where
(4.55) k1 =f (t0 , x0 )∆t
1 1
k2 =f (t0 + ∆t, x0 + k1 )∆t
2 2
1 1
k3 =f (t0 + ∆t, x0 + k2 )∆t
2 2
k4 =f (t0 + ∆t, x0 + k3 )∆t.
Iterating this scheme approximates propogating the initial condition x(t0 ).
34 4. R EGULARISATIONS AND OTHER N UMERICAL C ONSIDERATIONS

Many other Runge-Kutta schemes exist for higher orders and other choices of
coefficients in ki . We will see in the next chapter that this scheme is more than
accurate enough for our purposes.

4.7. Calculating the Poincaré Map


Another difficulty is the numerical calculation of the Poincaré maps constructed
in Section 3.4. Although in our implementation we will use a naïve but adequate
approach, we present here brief outline of a clever method proposed by Henon [20]
for calculating these maps that could be implemented in the future.
Algorithm 4.56 (Henon’s Method for Calculating Poincare Maps). First consider
a dynamical system
(4.57) ẋ = f (x) x ∈ Rn
and the associated Poincaré section
(4.58) S = {(x1 , x2 , ...xn )|(xn − a) = 0}
dxn
with Poincaré map P . By dividing the system by dt and inverting the last equa-
tion, we get the new system
dx1 f1
(4.59) =
dxn fn
dx2 f2
=
dxn fn
..
.
dxn−1 fn−1
=
dxn fn
dt 1
= .
dxn fn
Now the process to calculate the Poincaré map is given as
1. Take an initial condition x0 ∈ S
2. Propogate (4.57), calculating (xn − a) at each step
3. Stop when (xn − a) changes sign
4. Take single integration step of size ∆xn = −(xn − a) in system (4.59)
Then P (x0 ) = x, up to the accuracy of our integration method.
This algorithm must be adjusted for a more general section. Consider the
Poincaré section defined by
(4.60) S = {(x1 , x2 , ...xn )|D(x1 , x2 , ...xn ) = 0}
for some function D. Then we introduce the variable
(4.61) xn+1 = D(x1 , x2 , ...xn )
4.7. C ALCULATING THE P OINCARÉ M AP 35

and
n
X ∂D
(4.62) fn+1 (x) = fi (x) .
∂xi
i=1
Then the section is defined by xn+1 = 0, and we can follow the procedure de-
scribed above.
Although this method is accurate to the same level as our integration method
and theoretically does not require much analytical work, it does require the intro-
duction of a lot of new structure in the program to be developed in the next chapter.
A much simpler algorithm is used
Algorithm 4.63 (Simple Method for Calculating Poincare Maps). Given the sys-
tem in (4.57) and the associated section,
1. Take an initial condition x0 ∈ S
2. Propogate (4.57), calculating D, the signed distance to the section, at each
point
3. Stop when D changes sign
4. Extrapolate P (x0 ) from the current point, the previous point and their distances
from the section
Although this method is less accurate and far less defensible, our integrator
will take sufficiently small steps that we can calculate these points to a sufficiently
high accuracy.
C HAPTER 5

Results

Having established the necessary theory and discussed notable properties of


the system, the next step is to implement this theory as a computer program. Al-
though individual orbits and particular behaviours can be derived analytically, a
user-friendly program allows us to quickly get a broader (if perhaps less detailed)
insight into the dynamics of the system, especially across a large range of param-
eter values. In particular, the study of the Poincaré map for the system is very
intuitive in a visual setting, and allows numerical analysis of the bifurcations of the
system without the (extensive) analytical theory.

5.1. Program Design and Methodologies


The integration of Equations (4.46)-(4.49) using the Runge-Kutta method 4.52
is itself simple. A numerical computing environment such as MATLAB or Math-
ematica has built-in functions that not only integrate the differential equations but
display the results in very few lines of code.
However, we require the program to be interactive and user-friendly, and hope-
fully run quickly. To achieve these goals, the solution is implemented in C++. C++
is a lower-level language than MATLAB or Mathematica, and so requires consid-
erably more detailed code, but runs much faster and allows for a much greater
flexibility and level of control. OpenGL is used for the graphics and interactiv-
ity, with GLUT (the OpenGL Utility Toolkit) providing simpler access to graphic
commands.
The full code is provided in Appendix B. The control structure of the program
is summarised in Figure 5.1.
To evaluate the precision of the calculations, we define the energy error
(5.1) EE = |E − H (x, y, px , py )|
(that is, the difference between the energy parameter and the currently calculated
energy value). Informally, this value is O(10−9 ) for the periodic orbits we study,
and other orbits which do not travel too far from the primaries. This can be adjusted
by changing the size of a single integration step. As the trajectories stray from the
primaries, this energy error increases. It is thought that the error comes from the
mechanics of the Thiele-Burrau transform, which effectively “squashes” the space
far from the primaries. The limitations of C++ (in particular, the accuracy of a
double) lead to inaccuracies as the space becomes more squashed. For this project
we do not consider the dynamics of the particle past the influence of the primaries,
so this is of little concern. However, we could possibly integrate these trajectories
36
5.1. P ROGRAM D ESIGN AND M ETHODOLOGIES 37

Select µ
and E
parameters

Select
Poincaré
section

Select User
initial Interrupt
condition

Calculate
the initial
momentum

Intersected Integrate
P-section the orbit

Update
Orbit
Update window
P-section
window

Figure 5.1. Control flow diagram for the program. The user makes se-
lections for the parameters and initial condition using either the point-
and-click interface or by direct entry at the command line. Equation
(3.35) or similar is used to calculate the full initial condition. The pro-
gram then integrates the orbits and calculates the corresponding Poincaré
map until it is interrupted by the user.

by switching to the split-step integrator described in Section 4.1, which is very


accurate (if slower) away from the primaries.
Figure 5.2 shows the User Interface for the program. This has five windows
• The message window, used to display relevant data. The current choices of
parameters and initial condition are shown, as well as the “Energy Error”,
defined as the difference between the selected energy value and the current
(calculated) energy value. This window can be right clicked to access a
menu. The menu allows the user to manually enter an initial condition in
38 5. R ESULTS

the console (not shown), as well as switch Poincaré section type, change
the orbit colour, and other options.
• The parameter window. This window is used to select the values of the
E and µ parameters, with horizontal position determining µ and vertical
position determining E.
• The Poincaré section window. Clicking in this window allows the user
to select an initial condition for an orbit, which will immediately begin
integration. Also, whenever an orbit passes through the section, the point is
drawn on the section, visually showing the Poincaré map defined in Section
3.4. The grey regions delineate the Hill region, and the grey lines mark the
positions of the primaries.
• The z-space orbit window, which shows the motion of the particle in z
coordinates. One orbit is shown at a time, and will automatically be dis-
played as the trajectory is calculated. Also marked are the locations of the
primaries, the centre of mass, and the five Lagrangians. The Hill region
is delineated with a grey regions. A light grey line shows the currently
selection Poincaré section. This window can be hidden to improve perfor-
mance.
• The w-space orbit window, which shows the motion of the particle under
the Thiele-Burrau coordinates. This is mostly provided for reference and
testing. Again, it can be hidden to improve performance.

5.2. Analysing Orbits


5.2.1. Interpreting the Poincaré Section. The general procedure followed
when using the program is to select the parameter, then select a variety of initial
conditions in the section to build up an image of the Poincaré map. These diagrams
give a visual representation of the qualitative differences between different orbits.
Figure 5.3 shows this idea for the y = 0 Poincaré section, showing the initial con-
ditions which will lead to Hill orbits (trajectories that orbit one of the primaries).
The Hill orbits show up as closed curves (as indeed will any quasiperiodic orbits)
while chaotic orbits appropriately are chaotic under the Poincaré map. Figure 5.4
shows a map for the section through L4 . This allows comparisons to be made be-
tween the nature of the trajectories. Figure 5.5 shows another way of using the
program: by studying the sections, “interesting” orbits can be found. Orbits that
follow more complex paths than the circles associated with Hill orbits can be found
quite naturally, and “minimised” in the sense that periodic orbits can be found near
quasiperiodic orbits.

5.2.2. The Vanishing Twist. As noted in the introduction, a goal of this project
is to demonstrate a particular bifurcation in the system called the vanishing twist.
This follows from the theory developed in Generic twistless bifurcations by Dullin,
Meiss and Sterling [12].
In the paper, Dullin et al. proved that in the neighbourhood of the tripling bifur-
cation of a fixed point of an area-preserving map, there is what they call a twistless
5.2. A NALYSING O RBITS 39

Figure 5.2. The program’s interface. At top: message window. Top


left: parameter window. Top right: Poincaré window. Bottom left: orbit
window in z-space. Bottom right: orbit window in w-space.

bifurcation. We can access this idea for our system by defining the rotation number
of our Poincaré map.
Definition 5.2 (Rotation number). For a map f : [0, 2π) → [0, 2π), the rotation
number of f is defined as
f n (x) − x
(5.3) Ω(f ) = lim .
n→∞ n
In the paper, bifurcations occur at points corresponding to special values of this
rotation number. In particular, the twistless bifurcation occurs when the derivative
40 5. R ESULTS

Figure 5.3. Using the Poincaré section to differentiate types of orbits


around the primaries (Hill orbits). These figures use the Poincaré section
defined by y = 0, through both primaries. The top figure shows the
Poincaré map. The red section corresponds to clockwise orbits around
the left primary. The green section corresponds to anti-clockwise orbits
around the left primary. The blue section corresponds to clockwise orbits
around the right primary. The black dots are regions where the map is
chaotic, and will (after a long computation time) eventually fill out this
space. The bottom figure shows particular orbits for the red and blue
sections in the z-coordinate space.
5.2. A NALYSING O RBITS 41

Figure 5.4. Using the Poincaré section to differentiate types of orbits


around L4 . As indicated by the grey lines in the lower figures, these fig-
ures use the Poincaré section that passes through L4 and the heavier of
the primaries. The top figure shows the Poincaré map for µ = 0.0122,
E = −1.4937. The bottom figures show two orbits periodic correspond-
ing to the points at the centre of the red and blue sections of the section
respectively. The qualitative difference between the two types of orbits
can be confirmed visually: in the blue orbit the particle’s trajectory has
extra “loops”.
42 5. R ESULTS

Figure 5.5. At left: Poincaré sections for two choices of parameters. At


right: orbits corresponding to regions in these sections. For the top im-
ages, µ = 0.20, h = 0.57. For the bottom images, µ = 0.32, h = −1.95.

of the rotation number as a function of the action vanishes. The structures around
this bifurcation are shown in Figure 5.6.
The goal is then to demonstrate these behaviours in the PCR3BP. The equilib-
rium at L4 is a suitable canditate for this structure, as the Poincaré map has a fixed
point. A fixed energy is considered, close (but not too close) to the critical value of
the energy at L4 (which, as found in Equation (3.29) is E = −1.5 + µ(1 − µ)).
The Poincaré map (as a function of energy) can, for quasiperiodic orbits, be
defined on a curve isomorphic to the circle. Then the rotation number can be
defined as in 5.2 as a function of the action. At particular values of this, we observe
bifurcations. In particular, rational rotation numbers lead to resonance resulting in
a bifurcation. A formula for the mass ratios where this occurs is a known result.
Introduction to Hamiltonian Dynamical Systems and the N -Body Problem [24]
5.2. A NALYSING O RBITS 43

Figure 5.6. The bifurcations near the twistless bifurcation, and repre-
sentative phase portraits. Picture credit: Generic twistless bifurcations
[12].

gives the formula


s
1 16r2
(5.4) µr = (1 − 1− )
2 27(r2 + 1)2

where µr is the value of µ where the 1r resonance occurs (where the rotation number
is 31 ). This formula is only valid for E = −1.5 + µ(1 − µ) (the critical energy value
found in (3.29)), but gives a good estimate for close energy values.
We can then consider the rotation number of the map as a function of the action
Ω(J). Then for periodic orbits bifurcations occur at resonant values of the rotation
number. In particular,
44 5. R ESULTS

Figure 5.7. Bifurcation analysis for the Poincaré map near L4 . For these
plots, E = −1.49.
Top row, left to right: µ = 0.0025, 0.0030, 0.0035.
Second row: µ = 0.0040, 0.0045, 0.0050.
Third row: µ = 0.0055, 0.0060, 0.0065.
Bottom row: µ = 0.0075, 0.0080, 0.0085.
This continued in Figure 5.8. The bifurcations described by Figure 5.6
can be seen. In particular, note the bifurcation at µ = 0.008, and the
complex structure at µ = 0.003.
5.2. A NALYSING O RBITS 45

Figure 5.8. Bifurcation analysis for the Poincaré map near L4 . Contin-
ued from Figure 5.7
Top row, left to right: µ = 0.0090, 0.0095, 0.0100.
Second row: µ = 0.0105, 0.0110, 0.0115.
Third row: µ = 0.0120, 0.0125, 0.0130.
Bottom row: µ = 0.0135, 0.0140, 0.0145.
In particular note the bifurcation at µ = 0.0130 corresponding to the
1/3 bifurcation in Figure 5.6, and the structure at µ = 0.0100 which is

detailed in Figure 5.9


46 5. R ESULTS

Figure 5.9. Top: the Poincaré map for the Poincaré section through L4 ,
for the parameter values µ = 0.0100, E = −1.49. Bottom: the structure
predicted near the vanishing twist bifurcation by [12]. Also visible is the
additional structure in the top left of the top diagram; this small island
chain is a remnant of a resonant rotation number. Picture credit for lower
figure: Generic twistless bifurcations [12].
5.2. A NALYSING O RBITS 47

Figure 5.10. Top figure: Figure 5.9, with a particular set highlighted
which is invariant under the Poincaré map . Bottom figure: The orbit
around L4 corresponding to this invariant set. Recall that points on the
Poincaré section are generated when the orbit crosses the grey line where
the section is defined.
48 5. R ESULTS

• If Ω(0) is rational the orbit is resonant, and a chain of “islands” form. See
µ = 0.0035 and µ = 0.0045, µ = 0.0070 and µ = 0.0095 in Figures 5.7
and 5.8 for examples of this.
• If Ω(J) is rational with Ω(J) = pq for p, q ∈ N, we get chains of islands
with q smaller islands in the big island. µ = 0.0030 in Figure 5.7 corre-
sponds to this with Ω(J) = 3/10. However, there appear to be more than
10 smaller islands, though is most likely a quirk of the way the Poincaré
map has been constructed or calculated.
• A circle where Ω0 (J) = 0 is called twistless.
Based on the diagrams from the paper by Dullin et al., we can identify the
ranges where our system undergoes these bifurcations, by comparing Figures 5.7
and 5.8 and the phase portraits in Figure 5.6. The figures show the evolution of
the structure of the Poincaré map for fixed energy and µ being varied between
µ = 0.0025 and µ = 0.01451.
Of particular note are the bifurcations which occur near µ = 0.0080 and
µ = 0.0130, and the structure near the twistless bifurcation at µ = 0.0100. This
structure is shown in more detail in Figure 5.9. A striking orbit in this structure is
shown in Figure 5.10.
There are some key differences between the PCR3BP and the system consid-
ered by Dullin et al, most notably the second parameter. However, we can still
observe that the bifurcations match the theoretical predictions very closely.
5.2.3. The Earth-Moon system. One final analysis is to study the structure
of the Poincaré map when the energy parameter is altered, rather than the mass
parameter. The results of this are shown in Figures 5.11 and 5.12. Of note is the
choice of mass parameter for this analysis; we take µ = 0.01215. This is the
mass parameter for the Earth-Moon system. The moon’s orbit around the Earth
has a low eccentricity of about 0.05 (from [25]), so the “circular” part of our ap-
proximation is reasonable. As of October 2012, no trojans have been discovered
in the Earth-Moon system. This does not mean they do not exist; it was only
in July 2011 that the first trojans in the Sun-Earth system was found, an aster-
oid called TK7 (see [26]). The plots show possible stable orbits around L4 for
−1.4855 < E < −1.4975 (although the possibility of stable orbits for other en-
ergy values cannot be discounted).

1Recall that orbits around L are only stable when µ < 0.0385, so only a relatively small range
4
of the parameter is being considered.
5.2. A NALYSING O RBITS 49

Figure 5.11. Analysing the Poincaré section for the Earth-Moon system
near L4 . For the Earth-Moon system, µ = 0.01215. The above images
are the result of adjusting the Energy parameter.
Top row, left to right: E = −1.4855, −1.4860, −1.4865.
Second row: E = −1.4870, −1.4875, −1.4880.
Third row: E = −1.4885, −1.4890, −1.4895.
Bottom row: E = −1.4900, −1.4905, −1.4910.
50 5. R ESULTS

Figure 5.12. The Poincaré section for the Earth-Moon system near L4 .
Continued from Figure 5.11.
Top row, left to right: E = −1.4915, −1.4920, −1.4925.
Second row: E = −1.4930, −1.4935, −1.4940.
Third row: E = −1.4945, −1.4950, −1.4955.
Bottom row: E = −1.4960, −1.4970, −1.4975.
C HAPTER 6

Conclusion

Although the PCR3BP is a significant simplification of the general three body


problem, it is a rich problem with much unexplored depth. Our analysis has hope-
fully given the reader an appreciation of the key concerns of the system, and pro-
vided a robust derivation of the equations of motion in a Hamiltonian context. The
equations derived provide a good basis for any analysis of the PCR3BP, and many
of the ideas can be translated to similar problems.
The integrator developed in Chapter 5 provides a powerful tool for a hands-
on numerical study of the problem. The code provided could easily be expanded
to incorporate other ideas; for instance, the Poincaré map integrator describe in
Section 4.7 could be implemented with only minor additions. Much of the code
base, including the graphical routines, could be reused in future projects.
The primary mathematical success of the project is the verification of the twist-
less bifurcation for this system. The motion of objects near the L4 and L5 La-
grangian points can be very complex. The discovery of the bifurcations corre-
sponding to those derived for a general system in [12] gives a mathematical basis
for classifying the types of orbits that can occur around these points. Of particular
note is the spectacular motion observed close to the twistless bifurcation, illustrated
in Figure 5.10.
We also constructed a similar bifurcation diagram for the Earth-Moon system
in Section 5.2.3. Although this does not exhibit the same bifurcation structure as
adjusting the mass parameter, it exhibits some very interesting behaviour, which
could be later examined analytically. Such work could prove useful in searching
for trojans in the Earth-Moon system.
The work of this project raises several possible avenues for future investiga-
tion. The more obvious additions include the implementation of Henon’s method
for calculating Poincaré maps, as mentioned above, and functions to automate the
process of building bifurcation plots like Figure 5.7. Much of the structure of the
program could be reused in a study of the PR3BP (without restricting the primaries
to circular orbits), or perhaps even the R3BP (in three dimensional configuration
space). A deeper analytical study could be made of the motion around L4 and L5 ,
following from the results in [24]. This would be motivated by the numerical re-
sults and structures yielded from our program. In particular, the rotation number
could be explicitly calculated, which could be used to narrow the estimates for the
parameter values at the observed bifurcations.

51
References

[1] I. Newton, Philosophiæ Naturalis Principia Mathematica [1687]. Retrieved


from University of California Digital Library
[2] M. Hénon. Generating Families in the Restricted Three-Body Problem
[Springer, 1997]
[3] M. Hénon. Generating Families in the Restricted Three-Body Problem: II
Quantitative Study of Bifurcations [Springer, 2001]
[4] A. Katko and B. Hasselblatt. Introduction to the Modern Theory of Dynami-
cal Systems [Cambridge University Press, 1995]
[5] J. Barrow-Green. Poincaré and the Three Body Problem [The American
Mathematical Society, 1997]
[6] L. Poladian. Lagrangian and Hamiltonian Dynamics The University of Sydney
School of Mathematics & Statistics [2011]
[7] Q. Wang. On the Homoclinic Tangles of Henri Poincaré [University of Ari-
zona, 2010]
[8] Q. Wang The Global Solution of N-body Problem. Celestial Mechanics and
Dynamical Astronomy Vol 50 [1991] p. 73-88
[9] D. Ó’Mathúna. Integrable Systems in Celestial Mechanics Birkhauser [2008]
[10] M. Valtonen and H. Karttunen. The Three-Body Problem. Cambridge Uni-
versity Press [2006]
[11] R. Montgomery. A New Solution to the Three-Body Problem Notices of the
AMS Volume 48, Number 5 [2001]
[12] H. R. Dullin, J. D. Meiss and D. Sterling. Generic twistless bifurcations. Non-
linearity 13 [2000] p. 203-224
[13] R. Montgomery. N-body choreographies Scholarpedia (2010) 5(11):10666,
revision #91542
[14] C. Simó. New families of Solutions in N–Body Problems. Progress in Math-
ematics, Vol 201 [2001], p. 101–115
[15] L. A. Pars. A Treatise on Analytical Dynamics. Ox Bow Pr [1981]
[16] V. Szebehely. Theory of Orbits: The Restricted Problem of Three Bodies
Academic Press [1967]
[17] E. Hairer, C. Lubich and G. Wanner Geometric Numerical Integration:
Structure-Preserving Algorithms for Ordinary Differential Equations. 2nd
edition. Springer [2006] p. 179-236
[18] E. Hairer Variable time step integration with symplectic methods Applied Nu-
merical Mathematics 25 [1997] p. 219-227

52
R EFERENCES 53

[19] R. Broucke. Regularizations of the Plane Restricted Three-Body Problem.


Icarus 4 [1965] pp. 8-18
[20] M. Henón. On the Numerical Computation of Poincaré Maps Physica D 5 p.
412-414
[21] W. Tucker, Computing Accurate Poincaré maps [2002] Physica D 171 p. 127-
137
[22] W. S. Koon, M. W. Lo, J. E. Marsden and S. D. Ross, Dynamical Systems,
the Three-Body Problem and Space Mission Design [2008]
[23] J.D. Mireles James. Celestial Mechanics Notes, Set 4: The Circular Restricted
Three Body Problem University of Texas [2006]
[24] K. R. Meyer, G. R. Hall. Introduction to Hamiltonian Dynamical Systems and
the N-Body Problem, Springer [1992]
[25] Earth’s Moon: Facts & Figures from the NASA Website. Accessed from
http://solarsystem.nasa.gov/planets/profile.cfm?Object=Moon&Display=Facts
[26] NASA’s WISE Mission Finds First Trojan Asteroid Shar-
ing Earth’s Orbit from the NASA Website. Accessed from
http://www.nasa.gov/mission_pages/WISE/news/wise20110727.html
A PPENDIX A

Acknowledgements

The author would like to thank Holger Dullin, whose expertise and enthusiasm
have made this project not only possible but extremely gratifying.
Thanks must also go to William Rowley, whose advice on C++ was invaluable,
and Ting-Ying Chang, whose input has been exceedingly propitious.

54
A PPENDIX B

Code

/*
THREE BODY PROBLEM
JOACHIM WORTHINGTON
2012
5 jwor6721@uni.sydney.edu.au

Some functions, in particular those pertaining to unused


transformations, are unfinished/unused in the final code.
They are left in for reference and possible future use.

10 */

#include <stdio.h>
#include <tchar.h>
15 #include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <GL/glut.h>
#include <GL/gl.h>
20 #include <iostream>
#include <string>
#include <sstream>
#include <complex>

25 #include "stdafx.h" //To be removed when compiling outside VC++

std::stringstream sstm;
using namespace std;

30 /* ULTRATIGHT: For finding structure near the vanishing twist


#define MAX_MU 0.014 //Maximum value of mu parameter; minimum
is 0
#define MAX_ENERGY 1.495 //Really the minimum energy; .energy
between 0 and -this
#define MIN_ENERGY 1.485 //Again, really the maximum energy;
consider -this
#define MAX_PX 0.1 //Maximum selection of p_x in the poincare
window

55
56 B. C ODE

35 #define MIN_PX -0.15 //Minumum selection of p_x in the


poincare window
#define MAX_X 0.50 //Maximum selection of x in the poincare
window
#define MIN_X 0.38 //Minumum selection of x in the poincare
window*/

40 /* L4: For analysing orbits around L4


#define MAX_MU 0.04 //Maximum value of mu parameter; minimum
is 0.
#define MAX_ENERGY 1.5 //Really the minimum energy; .energy
between 0 and -this
#define MIN_ENERGY 1.47 //Again, really the maximum energy;
consider -this
#define MAX_PX 0.1 //Maximum selection of p_x in the poincare
window
45 #define MIN_PX -0.15 //Minumum selection of p_x in the
poincare window
#define MAX_X 0.50 //Maximum selection of x in the poincare
window
#define MIN_X 0.35 //Minumum selection of x in the poincare
window*/

50 /*FOR PRIMARY ORBITS: for orbits that orbit one or both primaries
*/
#define MAX_MU 0.5 //Maximum value of mu parameter; minimum
is 0
#define MAX_ENERGY 5.0 //Really the minimum energy; .energy
between 0 and -this
#define MIN_ENERGY -1.0 //Again, really the maximum energy;
consider -this
#define MAX_PX 2.0 //Maximum selection of p_x in the poincare
window
55 #define MIN_PX -2.0 //Minumum selection of p_x in the poincare
window
#define MAX_X 2.0 //Maximum selection of x in the poincare
window
#define MIN_X -2.0 //Minumum selection of x in the poincare
window

#define SQRT3ON2 0.8660254038


60 #define SQRT3 1.732050808
#define PI 3.14159265 //Constant relating the circumference of a
circle to its diameter
#define NEWTON_STEPS 20 //Number of steps to take in calculating
L1,2,3
B. C ODE 57

#define TOO_CLOSE 0.1 //For the switching integrator


#define TOO_FAR 5 //If the particle has flown away
65
#define CROSS_SIZE 0.02 //Size of the Cross Marker
#define PARAM_X_RES 0.01 //Keyboard right increases mu by
#define PARAM_Y_RES 0.01 //Pressing up increases h by this
#define PLANET_RADIUS 0.02 //Size the Larges Bodies are drawn at
70 #define HILL_DETAIL 1 //Higher settings render the Hill Region
more carefully, slowly
#define HILL_RES 1000 //The resolution at which to draw the Hill
Region in the P-window

//Values for the Menu


#define INTEGRATE 0
75 #define HILL_ON 1
#define RED 2
#define GREEN 3
#define BLUE 4
#define BLACK 5
80 #define POIN_ON 6
#define ZOOM_IN 7
#define ZOOM_OUT 8
#define ENTER_POIN 9
#define ENTER_PARAM 10
85 #define ORBIT_ON 11
#define ORBIT_ON_W 12
#define SWITCH_POIN 13
#define EACH_NEW 14

90 double dt=0.01; //0.01 is a reliably correct, 0.05 is


usually okay

//Varibles to store window data


int paramWindow;
int paramWindowHeight;
95 int paramWindowWidth;
int orbitWindow;
int orbitWindowHeight;
int orbitWindowWidth;
int orbitWindowW;
100 int orbitWindowWHeight;
int orbitWindowWWidth;
int poinWindow;
int poinWindowHeight;
int poinWindowWidth;
105 int UIWindow;
int UIWindowHeight;
int UIWindowWidth;
58 B. C ODE

int menu;

110
double scaleOut=0.5; //Scale for the orbit window

bool orbitWindowOn=true; //Hide the z-space Orbit Window to


achieve better performance
115 bool orbitWindowOnW=true; //Hide the W-space Orbit Window to
achieve better performance
bool hillRegionOn=true; //Turn on Hill Region plotting
bool velocityCurveOn=false; //Turn on Velocity Curve plotting (
system intensive)
bool poinRegionOn=true; //Turn on Selectable Poincare Region
bool sectionTwo=true; //Use the Poincare section through the
Trojan and the Larger Body
120 bool sectionThree=false; //Use the Poincare section through the
Trojan and the Smaller Body
bool clearOrbits=true; //Clear each orbit upon picking a new
Poincare section
bool fastMode=false; //Turns off double buffering

bool integrateOn=false; //While true, integrate the orbit


125 bool newOrbit=true; //If we press space, then press it again,
continue last orbit
int intSteps=100; //Number of steps to integrate before checking
the idle stuff again
int colour=3; //Number corresponding to the colour to use 0 is
red, 1 is blue, 2 is green

double muP=0.0; //Mass Parameter


130 double hP=-1; //Energy Parameter;

double poinX; //Initial condition


double poinPX; //Initial condition
double poinPY; //Initial condition (determined by x,p_x,E and mu)
135 double coords[4]; //Stores (u,v,p_u,p_v)

void renderBitmapString(double x, double y, void *font, char *


string); //Writes a string to the screen

//GLUT functions for the various windows


140 void renderSceneParam(void);
void reshapeParam (int w, int h);
void mouseParam(int button, int state, int x, int y);
void sKeyboardParam(int key, int x, int y);
void reshapeOrbit (int w, int h);
145 void renderSceneOrbit(void);
B. C ODE 59

void redrawOrbit(void);
void mouseOrbit(int button, int state, int x, int y);
void reshapeOrbitW (int w, int h);
void renderSceneOrbitW(void);
150 void redrawOrbitW(void);
void mouseOrbitW(int button, int state, int x, int y);
void reshapePoin (int w, int h);
void renderScenePoin(void);
void mousePoin(int button, int state, int x, int y);
155 void sKeyboardPoin(int key, int x, int y);
void reshapeUI (int w, int h);
void renderSceneUI(void);

void idle(); //GLUT idle loop


160 void createGLUTMenus();
void processMenuEvents(int option);

double H_w(double* c); //Calculate energy in terms of w, pw in T-


B space
double Energy(double x, double y, double px, double py); //Energy
in terms of z, pz
165 double K_E(double* c); //The phase space Hamiltonian (T-B space)
double initPY(double x, double px); //Calculate the initial
condition
double uHat(double x, double y); //The effective potential energy
double T(double x, double y, double px, double py); //Effective
kinetic energy
bool hillRegion(double x, double y); //Checks if points are in
the Hill region
170 void verifyParameters(); //Checks that mu and h are sensible
double *delT(double x, double y, double px, double py); //
Kinetic derivative
void tStep(double*, double step); //Kinetic step in untransformed
coordinates
double *delUhat(double*); //Effective Potential derivative
void uHatStep(double*, double step); //Effective Potential step
in untransformed coordinates
175 void integrationStep(); //Generic "total integration step"
function

void zToW_lc1(double*); //Local transformation at left singularity


void wToZ_lc1(double*); //Inverse local transformation left
singularity

180 void zToW_tb(double*); //Thiele Barrau Transform


void wToZ_tb(double*); //Inverse Theiele Barrau Transform
void uStep_tb(double*, double step); //Potential step under T-B
void tStep_tb(double*, double step); //Kinetic step under T-B
60 B. C ODE

void f_tb(double *c, double *result);


185 //Derivatives for the Thiele-Barrau transformed Hamiltonian

double *delUhat_lc1(double*); //Effective Potential derivative for


left singularity local transform
void uHatStep_lc1(double*, double step); //EP step for left
singularity local transform
double *delThat_lc1(double*); //Kinetic derivative for left
singularity local transform
190 void tHatStep_lc1(double*, double step); //Kinetic step for left
singularity local transform

void birkhoff(double*); //Birkhoff transformation


double birkhoff_inv(double*); //Inverse Birkhoff transformation
double* delUhat_birkhoff(double*); //Effective Potential
derivative for Birkhoff transform
195 void uHatStep_birkhoff(double*, double step); //EP step for
Birkhoff transform

void runge_kutta_4(double* y0, void (*derivs)(double*,double*),


double step);
//Runge-Kutta method for four-dimensional time-independent
function

200 double L1(); //Calculate the Lagrangian points


double L2();
double L3();
double Lagrangian_f(double x, int p); //For calculating the
Lagrangian points
double Lagrangian_fdash(double x, int p);
205
void renderBitmapString(double x, double y, void *font, char *
string) {
//Prints a string on the screen at x,y
char *c;
glRasterPos2f(x, y);
210 for (c=string; *c != ’\0’; c++) {
glutBitmapCharacter(font, *c);
}
}

215 //PARAMETER WINDOW


void renderSceneParam(void) {
//Render the Parameter window

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
220 glClearColor(1.0, 1.0, 1.0, 1.0);
B. C ODE 61

//Draw a cross at the Selected Parameter Point


int pSpaceW=paramWindowWidth;
double ratioW=MAX_MU/pSpaceW;
225 double crossX=(muP/ratioW);
crossX=2*crossX/paramWindowWidth-1;

int pSpaceH=paramWindowHeight;
double ratioH=(MAX_ENERGY-MIN_ENERGY)/pSpaceH;
230 double crossY=(-1*(hP+MIN_ENERGY)/ratioH);
crossY=-1*(2*crossY/paramWindowHeight-1);

glBegin( GL_LINES );
glColor3f( 0, 0, 0 );
235 glVertex2f( crossX-CROSS_SIZE, crossY );
glVertex2f( crossX+CROSS_SIZE, crossY );
glVertex2f( crossX, crossY-CROSS_SIZE );
glVertex2f( crossX, crossY+CROSS_SIZE );
glEnd();
240
if (!fastMode) glutSwapBuffers();
}

void reshapeParam (int w, int h){


245 //Reshaping the Parameter Window

paramWindowWidth=w;
paramWindowHeight=h;
glViewport(0,0,(GLsizei)w,(GLsizei)h);
250 glutPostRedisplay();
glutSetWindow(paramWindow);
renderSceneParam();
}

255 void mouseParam(int button, int state, int x, int y){


//Mouse callbacks for Parameter Window

if ( button == GLUT_LEFT_BUTTON ) {
if (state == GLUT_DOWN ) {
260
muP=x*MAX_MU/paramWindowWidth;
hP=-y*(MAX_ENERGY-MIN_ENERGY)/paramWindowHeight-MIN_ENERGY;

verifyParameters();
265
}
}
integrateOn=false;
newOrbit=true;
62 B. C ODE

270 glutSetWindow(paramWindow);
renderSceneParam();
if (orbitWindowOn)
{
glutSetWindow(orbitWindow);
275 renderSceneOrbit();
}
if (orbitWindowOnW)
{
glutSetWindow(orbitWindowW);
280 renderSceneOrbitW();
}
glutSetWindow(poinWindow);
renderScenePoin();
}
285
void sKeyboardParam(int key, int x, int y){
//Special Keyboard callback for Parameter Window

switch (key) {
290 case GLUT_KEY_UP: hP+=PARAM_Y_RES;
break;
case GLUT_KEY_DOWN: hP-=PARAM_Y_RES;
break;
case GLUT_KEY_LEFT: muP-=PARAM_X_RES;
295 break;
case GLUT_KEY_RIGHT: muP+=PARAM_X_RES;
break;
}
integrateOn=false;
300 newOrbit=true;
verifyParameters();
glutSetWindow(paramWindow);
renderSceneParam();
if (orbitWindowOn)
305 {
glutSetWindow(orbitWindow);
renderSceneOrbit();
}
if (orbitWindowOnW)
310 {
glutSetWindow(orbitWindowW);
renderSceneOrbitW();
}
glutSetWindow(poinWindow);
315 }

//ORBIT WINDOW (Z-SPACE)


B. C ODE 63

void reshapeOrbit (int w, int h){


//Reshaping the Orbit window
320
orbitWindowWidth=w;
orbitWindowHeight=h;
glViewport(0,0,(GLsizei)w,(GLsizei)h);
gluOrtho2D(-scaleOut,-scaleOut,-scaleOut,scaleOut);
325
glutPostRedisplay();
if (orbitWindowOn)
{
glutSetWindow(orbitWindow);
330 renderSceneOrbit();
}
glutSetWindow(poinWindow);
renderScenePoin();
}
335
void redrawOrbit(void){ //Needed by GLUT
if (!fastMode) glutSwapBuffers();
}

340 void renderSceneOrbit(void) {


//Render the Orbit window

glutSetWindow(orbitWindow);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
345 glClearColor(1.0, 1.0, 1.0, 1.0);

//Draw the Poincare Section projection


if (sectionTwo){
glBegin( GL_LINES );
350 glColor3f( 0.9, 0.9, 0.9 );
glVertex2f( -scaleOut*2, scaleOut*sqrt(3.0)*(-2+muP) );
glVertex2f( +scaleOut*2, scaleOut*sqrt(3.0)*(+2+muP) );
glEnd();
}
355 else if (sectionThree){
glBegin( GL_LINES );
glColor3f( 0.9, 0.9, 0.9 );
glVertex2f( -scaleOut*2, -scaleOut*sqrt(3.0)*(-2+muP-1) );
glVertex2f( +scaleOut*2, -scaleOut*sqrt(3.0)*(+2+muP-1) );
360 glEnd();
}
else{
glBegin( GL_LINES );
glColor3f( 0.9, 0.9, 0.9 );
365 glVertex2f( -1, 0 );
64 B. C ODE

glVertex2f( +1, 0 );
glEnd();
}

370 //Draw the Hill region


if (hillRegionOn){
glPointSize( 1.5/HILL_DETAIL); //Removes the Weird Lines
double x, y;
int i=1,j=1;
375 x=(i*2.0-orbitWindowHeight)/(orbitWindowHeight*scaleOut);
y=(j*2.0-orbitWindowWidth)/(orbitWindowWidth*scaleOut);
for (i=1; i<=orbitWindowHeight*HILL_DETAIL; i++){
for (j=0; j<=orbitWindowWidth*HILL_DETAIL; j++){
x=(i*(2.0/HILL_DETAIL)-orbitWindowHeight*1.0)/(
orbitWindowHeight*1.0*scaleOut);
380 y=(j*(2.0/HILL_DETAIL)-orbitWindowWidth)/(orbitWindowWidth
*scaleOut);
if (!hillRegion(x,y)){
glBegin( GL_POINTS );
glColor3f( 0.9, 0.9, 0.9 );
glVertex2f( x*scaleOut, y*scaleOut );
385 glEnd();
}
}
}
glPointSize( 1.0 );
390 }

//Draw the zero velocity curve (VERY SYSTEM INTENSIVE)


if (velocityCurveOn){
glPointSize( 2.0 );
395 double x, y;
int i=1,j=1;
bool flag; //For zero velocity curve
x=(i*2.0-orbitWindowHeight)/(orbitWindowHeight*scaleOut);
y=(j*2.0-orbitWindowWidth)/(orbitWindowWidth*scaleOut);
400 flag=hillRegion(-x,y); //Set up initial point
for (i=1; i<=orbitWindowHeight*HILL_DETAIL; i++){
for (j=1; j<=orbitWindowWidth*HILL_DETAIL; j++){
x=(i*(2.0/HILL_DETAIL)-orbitWindowHeight*1.0)/(
orbitWindowHeight*1.0*scaleOut);
y=(j*(2.0/HILL_DETAIL)-orbitWindowWidth)/(orbitWindowWidth
*scaleOut);
405 if (!hillRegion(x,y)){
if (flag){
//Plot zero velocity curve
glBegin( GL_POINTS );
glColor3f( 0, 0, 0 );
B. C ODE 65

410 glVertex2f( x*scaleOut, y*scaleOut );


glEnd();
flag=false;
}
}
415 else if (!flag){
//Plot zero velocity curve
glBegin( GL_POINTS );
glColor3f( 0, 0, 0 );
glVertex2f( x*scaleOut, y*scaleOut );
420 glEnd();
flag=true;
}

}
425 flag=true;
}
for (j=1; j<=orbitWindowWidth*HILL_DETAIL; j++){
for (i=1; i<=orbitWindowHeight*HILL_DETAIL; i++){
x=(i*(2.0/HILL_DETAIL)-orbitWindowHeight*1.0)/(
orbitWindowHeight*1.0*scaleOut);
430 y=(j*(2.0/HILL_DETAIL)-orbitWindowWidth)/(orbitWindowWidth
*scaleOut);
if (!hillRegion(x,y)){
if (flag){
//Plot zero velocity curve
glBegin( GL_POINTS );
435 glColor3f( 0, 0, 0 );
glVertex2f( x*scaleOut, y*scaleOut );
glEnd();
flag=false;
}
440 }
else if (!flag){
//Plot zero velocity curve
glBegin( GL_POINTS );
glColor3f( 0, 0, 0 );
445 glVertex2f( x*scaleOut, y*scaleOut );
glEnd();
flag=true;
}

450 }
flag=true;
}
glPointSize( 1.0 );
}
455
66 B. C ODE

//Draw the Lagrangian points


//L1
double x=-L1();
glBegin( GL_LINES );
460 glColor3f( 0, 0, 0 );
glVertex2f( -CROSS_SIZE*0.5+x*scaleOut, -CROSS_SIZE*0.5 );
glVertex2f( +CROSS_SIZE*0.5+x*scaleOut, +CROSS_SIZE*0.5 );
glVertex2f( -CROSS_SIZE*0.5+x*scaleOut, +CROSS_SIZE*0.5 );
glVertex2f( +CROSS_SIZE*0.5+x*scaleOut, -CROSS_SIZE*0.5 );
465 glEnd();
//L2
x=-L2();
glBegin( GL_LINES );
glColor3f( 0, 0, 0 );
470 glVertex2f( -CROSS_SIZE*0.5+x*scaleOut, -CROSS_SIZE*0.5 );
glVertex2f( +CROSS_SIZE*0.5+x*scaleOut, +CROSS_SIZE*0.5 );
glVertex2f( -CROSS_SIZE*0.5+x*scaleOut, +CROSS_SIZE*0.5 );
glVertex2f( +CROSS_SIZE*0.5+x*scaleOut, -CROSS_SIZE*0.5 );
glEnd();
475 //L3
x=-L3();
glBegin( GL_LINES );
glColor3f( 0, 0, 0 );
glVertex2f( -CROSS_SIZE*0.5+x*scaleOut, -CROSS_SIZE*0.5 );
480 glVertex2f( +CROSS_SIZE*0.5+x*scaleOut, +CROSS_SIZE*0.5 );
glVertex2f( -CROSS_SIZE*0.5+x*scaleOut, +CROSS_SIZE*0.5 );
glVertex2f( +CROSS_SIZE*0.5+x*scaleOut, -CROSS_SIZE*0.5 );
glEnd();
//L4
485 glBegin( GL_LINES );
glColor3f( 0, 0, 0 );
glVertex2f( -CROSS_SIZE*0.5-(muP-0.5)*scaleOut, -CROSS_SIZE
*0.5 + scaleOut*SQRT3ON2 );
glVertex2f( +CROSS_SIZE*0.5-(muP-0.5)*scaleOut, +CROSS_SIZE
*0.5 + scaleOut*SQRT3ON2 );
glVertex2f( -CROSS_SIZE*0.5-(muP-0.5)*scaleOut, +CROSS_SIZE
*0.5 + scaleOut*SQRT3ON2 );
490 glVertex2f( +CROSS_SIZE*0.5-(muP-0.5)*scaleOut, -CROSS_SIZE
*0.5 + scaleOut*SQRT3ON2 );
glEnd();
//L5
glBegin( GL_LINES );
glColor3f( 0, 0, 0 );
495 glVertex2f( -CROSS_SIZE*0.5-(muP-0.5)*scaleOut, -CROSS_SIZE
*0.5 - scaleOut*SQRT3ON2 );
glVertex2f( +CROSS_SIZE*0.5-(muP-0.5)*scaleOut, +CROSS_SIZE
*0.5 - scaleOut*SQRT3ON2 );
B. C ODE 67

glVertex2f( -CROSS_SIZE*0.5-(muP-0.5)*scaleOut, +CROSS_SIZE


*0.5 - scaleOut*SQRT3ON2 );
glVertex2f( +CROSS_SIZE*0.5-(muP-0.5)*scaleOut, -CROSS_SIZE
*0.5 - scaleOut*SQRT3ON2 );
glEnd();
500
//Draw the Centre of Mass
glBegin( GL_LINES );
glColor3f( 0, 0, 0 );
glVertex2f( 0-CROSS_SIZE, 0 );
505 glVertex2f( 0+CROSS_SIZE, 0 );
glVertex2f( 0, 0-CROSS_SIZE );
glVertex2f( 0, 0+CROSS_SIZE );
glEnd();

510 //Draw the Larger Bodies


glColor3f(0.0f, 0.0f,0.0f);
glTranslatef((1-muP)*scaleOut,0,0);
glutSolidSphere(PLANET_RADIUS*scaleOut,20,20);
glTranslatef(((muP-1))*scaleOut,0,0);
515 glTranslatef((-muP)*scaleOut,0,0);
glutSolidSphere(PLANET_RADIUS*scaleOut,20,20);
glTranslatef((+muP)*scaleOut,0,0);

if (!fastMode) glutSwapBuffers();
520 }

void addOrbit(double u, double v){

//Arguments are in w-space


525 double x=0.5*(1-2*muP+cos(u)*cosh(v)); //z-space coordinates
double y=-0.5*(sin(u)*sinh(v));
double mu1=1-muP;
double mu2=muP;
double r1=sqrt((x+mu2)*(x+mu2)+y*y);
530 double r2=sqrt((x-mu1)*(x-mu1)+y*y);

glutSetWindow(orbitWindow);
glPointSize( 2.0 );
float r=0,g=0,b=0; //Set up colour
535 if (colour==0) r=0.5;
else if (colour==1) g=0.5;
else if (colour==2) b=0.5;

glBegin( GL_POINTS );
540 glColor3f(r, g, b);
glVertex2f( x*scaleOut, y*scaleOut );
glEnd();
68 B. C ODE

if (!fastMode) glutSwapBuffers();
}
545
//ORBIT WINDOW (W-SPACE)
void reshapeOrbitW (int w, int h){
//Reshaping the Orbit window

550 orbitWindowWWidth=w;
orbitWindowWHeight=h;
glViewport(0,0,(GLsizei)w,(GLsizei)h);
gluOrtho2D(-PI,PI,-4,4);
glutPostRedisplay();
555 if (orbitWindowOnW){
glutSetWindow(orbitWindowW);
renderSceneOrbitW();
}
glutSetWindow(poinWindow);
560 renderScenePoin();
}

void redrawOrbitW(void){ //Needed by GLUT


if (!fastMode) glutSwapBuffers();
565 }

void renderSceneOrbitW(void) {
//Render the Orbit window
glutSetWindow(orbitWindowW);
570 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glClearColor(1.0, 1.0, 1.0, 1.0);

//Draw the Hill region


if (hillRegionOn){
575 glPointSize( 1.5/HILL_DETAIL); //Removes the Weird Lines
double u, v,x,y;
int i=1,j=1;
u=(i*2.0-orbitWindowWHeight)/(orbitWindowWHeight);
v=(j*2.0-orbitWindowWWidth)/(orbitWindowWWidth);
580
for (u=-PI; u<=PI; u+=0.01){
for (v=-4; v<=4; v+=0.01){
x=0.5-muP+0.5*cos(u)*cosh(v); //CONVERT TO Z-SPACE
y=0.5*sin(u)*sinh(v);
585 if (!hillRegion(x,y)){
glBegin( GL_POINTS );
glColor3f( 0.9, 0.9, 0.9 );
glVertex2f( u, v );
glEnd();
590
B. C ODE 69

}
}
}
glPointSize( 1.0 );
595 }

//Draw the Larger Bodies


glColor3f(0.0f, 0.0f,0.0f);
glutSolidSphere(PLANET_RADIUS,20,20);
600 glTranslatef(PI,0,0);
glutSolidSphere(PLANET_RADIUS,20,20);
glTranslatef(-PI,0,0);

if (!fastMode) glutSwapBuffers();
605 }

void addOrbitW(double u, double v){


if (u>PI) //u in [-PI,PI)
u-=2*PI;
610
glutSetWindow(orbitWindowW);
glPointSize( 2.0 );
float r=0,g=0,b=0; //Set the colour
if (colour==0) r=0.5;
615 else if (colour==1) g=0.5;
else if (colour==2) b=0.5;
glBegin( GL_POINTS );
glColor3f(r, g, b);
glVertex2f( u, v );
620 glEnd();
glBegin( GL_POINTS );
glColor3f(r, g, b);
glVertex2f( -u, -v ); //Each z-point maps to two w-points
glEnd();
625
if (!fastMode) glutSwapBuffers();
}

630 //POINCARE SECTION WINDOW


void reshapePoin (int w, int h){
//Reshaping the Poincare Section window
glutSetWindow(poinWindow);
poinWindowWidth=w;
635 poinWindowHeight=h;
glViewport(0,0,(GLsizei)w,(GLsizei)h);
gluOrtho2D(MIN_X, MAX_X, MIN_PX, MAX_PX);
glutPostRedisplay();
70 B. C ODE

renderScenePoin();
640 }

void redrawPoin(void){ //Needed by GLUT


if (!fastMode) glutSwapBuffers();
}
645
void renderScenePoin(void) {
//Render the Poincare Section window
glutSetWindow(poinWindow);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
650 glClearColor(1.0, 1.0, 1.0, 1.0);

if (poinRegionOn){
//Draw in Hill’s region
//(or, more accurately, draw !Hill’s region in grey)
655
double mu1=1-muP;
double mu2=muP;
glPointSize( 2.0 );

660 double x, px, y;


double a, b, c;
double r1, r2;
for (px=MIN_PX; px<=MAX_PX; px+=(MAX_PX-MIN_PX)/HILL_RES){
for (x=MIN_X; x<=MAX_X; x+=(MAX_X-MIN_X)/HILL_RES){
665 if (sectionTwo) y=SQRT3*(x+muP);
else if (sectionThree) y=-SQRT3*(x+muP-1);
else y=0;
r1=sqrt((x+mu2)*(x+mu2)+y*y);
r2=sqrt((x-mu1)*(x-mu1)+y*y);
670 if (sectionTwo){
a=0.5;
b=-0.5*(SQRT3*y+1*x);
c=-hP+0.5*px*px+0.5*(y-SQRT3*x)*px-mu2/r2-mu1/r1;
}
675 else if (sectionThree){
a=0.5;
b=0.5*(SQRT3*y-1*x);
c=-hP+0.5*px*px+0.5*(y+SQRT3*x)*px-mu2/r2-mu1/r1;
}
680 else{
a=0.5;
b=-x;
c=-hP+0.5*px*px+y*px-mu2/r2-mu1/r1;
}
685 if (b*b-4*a*c<0){
//In the region of impossible motion
B. C ODE 71

glBegin( GL_POINTS );
glColor3f( 0.8, 0.8, 0.8 );
glVertex2f( x, px );
690 glEnd();
}
}
}
}
695
//Draw lines for the Large Body coordinates
glBegin( GL_LINES );
glColor3f( 0.6, 0.6, 0.6 );
glVertex2f( -muP, -100 );
700 glVertex2f( -muP, +100 );
glVertex2f( -(muP-1), -100 );
glVertex2f( -(muP-1), +100 );
glEnd();

705 if (sectionTwo || sectionThree){


//Draw in the line for the Lagrangian Point
glBegin( GL_LINES );
glColor3f( 0.6, 0.6, 0.6 );
glVertex2f( (-muP+0.5), -100 );
710 glVertex2f( (-muP+0.5), +100 );
glEnd();
}

if (!fastMode) glutSwapBuffers();
715 }

void mousePoin(int button, int state, int x, int y){


//Mouse callbacks for Poincare Section Window

720 if ( button == GLUT_LEFT_BUTTON ) { /* ignore other buttons


*/
if (state == GLUT_DOWN ) {
poinX=(MAX_X-MIN_X)*x/(poinWindowWidth)+MIN_X;
poinPX=(MIN_PX-MAX_PX)*y/(poinWindowHeight)+MAX_PX;
poinPY=initPY(poinX,poinPX);
725 if (sectionTwo){
//convert from Normal and Parallel to px and py
double pN=poinPY;
double pP=poinPX;
poinPX=(pP-SQRT3*pN)/2;
730 poinPY=(SQRT3*pP+pN)/2;
}
else if (sectionThree){
//convert from Normal and Parallel to px and py
72 B. C ODE

double pN=poinPY;
735 double pP=poinPX;
poinPX=(pP+SQRT3*pN)/2;
poinPY=(-SQRT3*pP+pN)/2;
}
}
740 }
integrateOn=true;
verifyParameters();
if (clearOrbits){
renderSceneOrbit();
745 renderSceneOrbitW();
}
coords[0]=poinX;
if (sectionTwo) coords[1]=sqrt(3.0)*(poinX+muP);
else if (sectionThree) coords[1]=-sqrt(3.0)*(poinX+muP-1);
750 else coords[1]=0;
coords[2]=poinPX;
if (poinPY==-1111.11) integrateOn=false;
coords[3]=poinPY;
zToW_tb(coords);
755 newOrbit=false;
}

void addPoincare(double x, double px){


//Add a point on the Poincare Map
760
glutSetWindow(poinWindow);
glPointSize( 2.0 );
float r=0,g=0,b=0;
if (colour==0)
765 r=0.5;
else if (colour==1) g=0.5;
else if (colour==2) b=0.5;
glBegin( GL_POINTS );
glColor3f(r, g, b);
770 glVertex2f( x, px );
glEnd();
if (!fastMode) glutSwapBuffers();
}

775 void sKeyboardPoin(int key, int x, int y){


//Special Keyboard callback for Parameter Window

switch (key) {
case GLUT_KEY_UP: poinPX+=PARAM_Y_RES;
780 break;
case GLUT_KEY_DOWN: poinPX-=PARAM_Y_RES;
B. C ODE 73

break;
case GLUT_KEY_LEFT: poinX-=PARAM_X_RES;
break;
785 case GLUT_KEY_RIGHT: poinX+=PARAM_X_RES;
break;
}
integrateOn=false;
newOrbit=true;
790 poinPY=initPY(poinX,poinPX);
verifyParameters();
glutSetWindow(poinWindow);
renderScenePoin();
if (clearOrbits) {
795 renderSceneOrbit();
renderSceneOrbitW();
}
}

800 void nKeyboardPoin(unsigned char key, int x, int y) {


//Keyboard functions for the Poincare Section
if (key == 32) {
if (integrateOn)
integrateOn=false;
805 else {
integrateOn=true;
if (newOrbit) {
coords[0]=poinX;
if (sectionTwo) coords[1]=sqrt(3.0)*(poinX+muP);
810 else coords[1]=0;
coords[2]=poinPX;
if (initPY(poinX,poinPX)==-1111.11) integrateOn=false;
coords[3]=initPY(poinX,poinPX);
zToW_tb(coords);
815 newOrbit=false;
}
}
}
}
820
//UI WINDOW
void reshapeUI (int w, int h){
//Reshaping the Poincare Section window

825 UIWindowWidth=w;
UIWindowHeight=h;
glViewport(0,0,(GLsizei)w,(GLsizei)h);
glutPostRedisplay();
glutSetWindow(UIWindow);
74 B. C ODE

830 renderSceneUI();
}

void redrawUI(void){
if (!fastMode) glutSwapBuffers();
835 }

void renderSceneUI(void) {
//Render the UI window

840 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);


glClearColor(1.0, 1.0, 1.0, 1.0);

//Print the current values of x, px, and py


glColor3f( 0, 0, 0 );
845 char result[200];
sprintf_s(result, "x: %.4f", poinX);
sprintf_s(result, "%s px: %.4f py: ",result, poinPX);
if (poinPY==-1111.11) sprintf_s(result, "%s INVALID ",result,
poinPX);
else sprintf_s(result, "%s %.4f ",result, poinPY);
850 sprintf_s(result, "%s mu: %.4f ",result, muP);
sprintf_s(result, "%s h: %.4f ",result, hP);
sprintf_s(result, "%s Energy: %.4f ",result, abs(H_w(coords)));
sprintf_s(result, "%s Error: %.8f ",result, abs(H_w(coords)-hP))
;
renderBitmapString(-0.99,-0.6,GLUT_BITMAP_8_BY_13,result);
855
if (!fastMode) glutSwapBuffers();
}

860 //IDLE FUNCTION


void idle() {
if (integrateOn) {
int i=0; //Take a fixed number of steps before getting user
input
while (i<intSteps && integrateOn) {
865 i++;
double oldU=coords[0];
double oldV=coords[1];
double oldPU=coords[2];
double oldPV=coords[3];
870 integrationStep();
//Detect if we’ve gone through the Poincare Section
//WORKING IN W-SPACE, but for the Z-SPACE section
//NEED v=0 or u=k*pi k in ZZ
//CURRENTLY just interpolate
B. C ODE 75

875 if (sectionTwo) {
double oldVal, newVal;
oldVal=sin(oldU)*sinh(oldV)+SQRT3*cos(oldU)*cosh(oldV)+
SQRT3;
newVal=sin(coords[0])*sinh(coords[1])+SQRT3*cos(coords[0])
*cosh(coords[1])+SQRT3;
if (oldVal>0 && newVal<0) {
880 complex<double> oldw(oldU,oldV);
complex<double> oldpw(oldPU,-oldPV);
complex<double> neww(coords[0],coords[1]);
complex<double> newpw(coords[2],-coords[3]);
complex<double> oldz, oldpz, newz, newpz;
885 oldz=0.5*(1-2*muP+cos(oldw)); //Previous coordinate
oldpz=-2.0*oldpw/(sin(oldw));
newz=0.5*(1-2*muP+cos(neww)); //Current coordinate
newpz=-2.0*newpw/(sin(neww));
double ratio=oldVal/(oldVal-newVal); //Extrapolation
distance
890 double x0=real(oldz)+ratio*(real(newz)-real(oldz)); //
Extrapolate the point
double px0=real(oldpz)+ratio*(real(newpz)-real(oldpz));
double py0=imag(oldpz)+ratio*(imag(newpz)-imag(oldpz));

//Must convert to pNormal, pParallel


895 double pP=0.5*(px0-SQRT3*py0);
addPoincare(x0,pP);
}
}
else if (sectionThree){
900 double oldVal, newVal;
oldVal=-sin(oldU)*sinh(oldV)+SQRT3*cos(oldU)*cosh(oldV)-
SQRT3;
newVal=-sin(coords[0])*sinh(coords[1])+SQRT3*cos(coords
[0])*cosh(coords[1])-SQRT3;
if (oldVal<0 && newVal>0) {
complex<double> oldw(oldU,oldV);
905 complex<double> oldpw(oldPU,-oldPV);
complex<double> neww(coords[0],coords[1]);
complex<double> newpw(coords[2],-coords[3]);
complex<double> oldz, oldpz, newz, newpz;

910 oldz=0.5*(1-2*muP+cos(oldw));
oldpz=-2.0*oldpw/(sin(oldw));
newz=0.5*(1-2*muP+cos(neww));
newpz=-2.0*newpw/(sin(neww));
double ratio=oldVal/(oldVal-newVal);
915 double x0=real(oldz)+ratio*(real(newz)-real(oldz));
double px0=real(oldpz)+ratio*(real(newpz)-real(oldpz));
76 B. C ODE

double py0=imag(oldpz)+ratio*(imag(newpz)-imag(oldpz));

//Must convert to pNormal, pParallel


920 double pP=0.5*(px0+SQRT3*py0);
addPoincare(x0,pP);
}
}
else
925 {
if (oldV*coords[1]<0 || abs(oldU-coords[0])>1.5*PI || (
oldU-PI)*(coords[0]-PI)<0) {
//We’ve passed through; v=0 OR u=0/2PI OR u=PI
complex<double> oldw(oldU,oldV);
complex<double> oldpw(oldPU,-oldPV);
930 complex<double> neww(coords[0],coords[1]);
complex<double> newpw(coords[2],-coords[3]);
complex<double> oldz, oldpz, newz, newpz;

oldz=0.5*(1-2*muP+cos(oldw));
935 oldpz=-2.0*oldpw/(sin(oldw));
newz=0.5*(1-2*muP+cos(neww));
newpz=-2.0*newpw/(sin(neww));
double ratio=(imag(oldz))/(imag(oldz)-imag(newz));
double x0=real(oldz)+ratio*(real(newz)-real(oldz));
940 double px0=real(oldpz)+ratio*(real(newpz)-real(oldpz));
if (imag(newz)>=0)
addPoincare(x0,px0);
}
}
945
if (orbitWindowOn)
addOrbit(coords[0],coords[1]);
if (orbitWindowOnW)
addOrbitW(coords[0],coords[1]);
950 if (abs(K_E(coords))>1 || abs(coords[1])>TOO_FAR)
integrateOn=false;
}
}
glutSetWindow(UIWindow);
955 renderSceneUI();
}

//MENUS
960 void createGLUTMenus() {
// Create the menu
menu = glutCreateMenu(processMenuEvents);
B. C ODE 77

//Add entries to our menu


965 glutAddMenuEntry("Integrate", INTEGRATE);
glutAddMenuEntry("Clear Orbits", EACH_NEW);
glutAddMenuEntry("Switch Poincare Selection", SWITCH_POIN);
glutAddMenuEntry("Toggle Orbit Window Z", ORBIT_ON);
glutAddMenuEntry("Toggle Orbit Window W", ORBIT_ON_W);
970 glutAddMenuEntry("Hill Region Shading",HILL_ON);
glutAddMenuEntry("Poincare Region Shading", POIN_ON);
glutAddMenuEntry("Red",RED);
glutAddMenuEntry("Green",GREEN);
glutAddMenuEntry("Blue",BLUE);
975 glutAddMenuEntry("Black",BLACK);
glutAddMenuEntry("Zoom in", ZOOM_IN);
glutAddMenuEntry("Zoom out", ZOOM_OUT);
glutAddMenuEntry("Enter Parameters", ENTER_PARAM);
glutAddMenuEntry("Enter Poincare Selection", ENTER_POIN);
980
//Attach the menu to the right click
glutAttachMenu(GLUT_RIGHT_BUTTON);
}

985 void processMenuEvents(int option) {


//Deal with menu selections
switch (option) {
//Colour changes
case RED :
990 colour=0; break;
case GREEN :
colour=1; break;
case BLUE :
colour=2; break;
995 case BLACK :
colour=3; break;

case INTEGRATE:
integrateOn=true;
1000 if (newOrbit)
{
coords[0]=poinX;

if (!sectionTwo)
1005 coords[1]=0;
else
coords[1]=sqrt(3.0)*(poinX+muP);

coords[2]=poinPX;
1010 if (initPY(poinX,poinPX)==-1111.11) integrateOn=false;
coords[3]=initPY(poinX,poinPX);
78 B. C ODE

zToW_tb(coords);
newOrbit=false;
}
1015 break;
case HILL_ON:
hillRegionOn=(!hillRegionOn);
break;
case POIN_ON:
1020 poinRegionOn=(!poinRegionOn);
break;
case ZOOM_IN:
scaleOut+=0.1;
if (orbitWindowOn)
1025 {
glutSetWindow(orbitWindow);
renderSceneOrbit();
}
if (orbitWindowOnW)
1030 {
glutSetWindow(orbitWindowW);
renderSceneOrbitW();
}
glutSetWindow(poinWindow);
1035 renderScenePoin();
break;
case ZOOM_OUT:
scaleOut-=0.1;
if (scaleOut<0.1) scaleOut=0.1;
1040 if (orbitWindowOn)
{
glutSetWindow(orbitWindow);
renderSceneOrbit();
}
1045 if (orbitWindowOnW)
{
glutSetWindow(orbitWindowW);
renderSceneOrbitW();
}
1050 glutSetWindow(poinWindow);
renderScenePoin();
break;
case ENTER_PARAM:
//Enter parameter values at the Console window
1055 cout<<"\n\nEnter value of mu (mass parameter):\t";
cin>>muP;
cout<<"\nEnter energy level:\t";
cin>>hP;
integrateOn=false;
B. C ODE 79

1060 newOrbit=true;
poinPY=initPY(poinX,poinPX);
verifyParameters();
glutSetWindow(poinWindow);
renderScenePoin();
1065 glutSetWindow(paramWindow);
renderSceneParam();
break;
case ENTER_POIN:
cout<<"\n\nEnter initial value of x:\t";
1070 cin>>poinX;
cout<<"\nEnter initial value of p_x:\t";
cin>>poinPX;
integrateOn=false;
newOrbit=true;
1075 poinPY=initPY(poinX,poinPX);
verifyParameters();
glutSetWindow(poinWindow);
glutSetWindow(paramWindow);
renderSceneParam();
1080 break;
case ORBIT_ON:
orbitWindowOn=!orbitWindowOn;
if (!orbitWindowOn){
glutSetWindow(orbitWindow);
1085 glutHideWindow();
}
else{
glutSetWindow(orbitWindow);
glutShowWindow();
1090 renderSceneOrbit();
}
break;
case ORBIT_ON_W:
orbitWindowOnW=!orbitWindowOnW;
1095 if (!orbitWindowOnW){
glutSetWindow(orbitWindowW);
glutHideWindow();
}
else{
1100 glutSetWindow(orbitWindowW);
glutShowWindow();
renderSceneOrbitW();
}
break;
1105 case SWITCH_POIN:
if (sectionTwo) {
sectionTwo=false;
80 B. C ODE

sectionThree=true;
}
1110 else if (sectionThree) {
sectionThree=false;
sectionTwo=false;
}
else {
1115 sectionTwo=true;
sectionThree=false;
}
glutSetWindow(poinWindow);
renderScenePoin();
1120 glutSetWindow(paramWindow);
renderSceneParam();
glutSetWindow(orbitWindow);
renderSceneOrbit();
break;
1125 case EACH_NEW:
clearOrbits=!clearOrbits;
}
}

1130
//MATHS FUNCTIONS
void verifyParameters()
{
//Check that the current parameters are valid, if not fix them
up
1135 if (muP<0) muP=0;
if (muP>MAX_MU) muP=MAX_MU;
if (hP>-MIN_ENERGY) hP=-MIN_ENERGY;
if (hP<-MAX_ENERGY) hP=-MAX_ENERGY;
}
1140
double uHat(double x, double y){
//Calculates uHat, the effective potential, in z-space
double mu1=1-muP;
double mu2=muP;
1145 double r1=sqrt((x+mu2)*(x+mu2)+y*y);
double r2=sqrt((x-mu1)*(x-mu1)+y*y);
return 0.5*(-x*x-y*y)-mu1/r1-mu2/r2;
}

1150 double uHat_lc1(double u, double v) {


//Find uHat in locally transformed coordinates centred on the
left body
double mu1=1-muP;
double mu2=muP;
B. C ODE 81

double r1=sqrt((u*u-v*v)*(u*u-v*v)+4*u*u*v*v);
1155 double r2=sqrt((u*u-v*v-1)*(u*u-v*v-1)+4*u*u*v*v);
return -0.5*(mu1*r1*r1+mu2*r2*r2)-mu1/r1-mu2/r2;
}

double u_birkhoff(double u, double v) {


1160 //uHat in Birkhoff coordinates
double rho1=sqrt((u+0.5)*(u+0.5)+v*v);
double rho2=sqrt((u-0.5)*(u-0.5)+v*v);
double rho=sqrt(u*u+v*v);
double result=0;
1165 result=result-(1-muP)*pow(rho1,4)/(8*rho*rho);
result=result-muP*pow(rho2,4)/(8*rho*rho);
result=result-2*rho*(1-muP)/(rho1*rho1);
result=result-2*rho*muP/(rho2*rho2);
return result;
1170 }

double T(double x, double y, double px, double py){


//Kinetic energy in untransformed coordinates
return 0.5*((px+y)*(px+y)+(py-x)*(py-x));
1175 }

double Energy(double x, double y, double px, double py){


//Energy in untransformed space
double mu1=1-muP;
1180 double mu2=muP;
complex<double> z(x,y);
complex<double> pz(px,-py);
complex<double> SNO(0,1);
return real(0.5*(pz*conj(pz)+SNO*(conj(z*pz)-z*pz))-mu1/abs(z+
mu2)-mu2/abs(z-mu1));
1185 }

bool hillRegion(double x, double y){


//Returns TRUE if x,y is in the Region of Possible Motion (Hill
Region)
return uHat(x,y)<=hP;
1190 }

double initPY(double x,double px){


//Calculates the positive value of p_y, based on selection in
Parameter+Poincare windows
if (sectionTwo){
1195 //Section Two code; calculate Normal momentum from Parallel
momentum
double mu1=1-muP;
double mu2=muP;
82 B. C ODE

double y=SQRT3*(x+muP);
double r1=sqrt((x+mu2)*(x+mu2)+y*y);
1200 double r2=sqrt((x-mu1)*(x-mu1)+y*y);
double a=0.5;
double b=-0.5*(SQRT3*y+1*x);
double c=-hP+0.5*px*px+0.5*(y-SQRT3*x)*px-mu2/r2-mu1/r1;
if (b*b-4*a*c<0) return -1111.11; //Impossible Selection!
1111.11 is a dummy
1205 return (-b+sqrt(b*b-4.0*a*c))/(2.0*a); //the normal momentum
}
else if (sectionThree){
//Section Three code; calculate Normal momentum from Parallel
momentum
double mu1=1-muP;
1210 double mu2=muP;
double y=-SQRT3*(x+muP-1);
double r1=sqrt((x+mu2)*(x+mu2)+y*y);
double r2=sqrt((x-mu1)*(x-mu1)+y*y);
double a=0.5;
1215 double b=0.5*(SQRT3*y-1*x);
double c=-hP+0.5*px*px+0.5*(y+SQRT3*x)*px-mu2/r2-mu1/r1;
if (b*b-4*a*c<0) return -1111.11; //Impossible Selection!
1111.11 is a dummy
return (-b+sqrt(b*b-4.0*a*c))/(2.0*a); //the normal momentum
}
1220 else {
//Section One code
double mu1=1-muP;
double mu2=muP;
double y=0;
1225 double r1=sqrt((x+mu2)*(x+mu2)+y*y);
double r2=sqrt((x-mu1)*(x-mu1)+y*y);
double a=0.5;
double b=-x;
double c=-hP+0.5*px*px+y*px-mu2/r2-mu1/r1;
1230 if (b*b-4*a*c<0) return -1111.11; //Impossible Selection!
1111.11 is a dummy
return (-b+sqrt(b*b-4.0*a*c))/(2.0*a);
}
}

1235 double Lagrangian_f(double x, int p){


//If p=1, return the f for L1, if p=2, for L2, etc
double result=-x*(x+muP)*(x+muP)*(x+muP-1)*(x+muP-1);
if (p==3) result-=(1-muP)*(x+muP-1)*(x+muP-1);
else result+=(1-muP)*(x+muP-1)*(x+muP-1);
1240 if (p==2) result+=muP*(x+muP)*(x+muP);
else result-=muP*(x+muP)*(x+muP);
B. C ODE 83

return result;
}

1245 double Lagrangian_fdash(double x, int p){


//if p=1, return the f’ for L1, if p=2, for L2, etc
double result;
result=-(x+muP)*(x+muP)*(x+muP-1)*(x+muP-1);
result-=2*x*(x+muP)*(x+muP-1)*(x+muP-1);
1250 result-=2*x*(x+muP)*(x+muP)*(x+muP-1);
if (p==3) result-=(1-muP)*(x+muP-1)*2;
else result+=(1-muP)*(x+muP-1)*2;
if (p==2) result+=muP*(x+muP)*2;
else result-=muP*(x+muP)*2;
1255 return result;
}

double L1(){
//Calculate the Lagrangian point in the range (-mu,1-mu)
1260 double L_point=0;
int i;
for (i=0; i<NEWTON_STEPS; i++){
L_point-=(Lagrangian_f(L_point,1)/Lagrangian_fdash(L_point,1))
;
}
1265 return -L_point;
}

double L2(){
//Calculate the Lagrangian point in the range (1-mu,infinity)
1270 double L_point=3;
int i;
for (i=0; i<NEWTON_STEPS; i++){
L_point-=(Lagrangian_f(L_point,2)/Lagrangian_fdash(L_point,2))
;
}
1275 return -L_point;
}

double L3(){
//Calculate the Lagrangian point in the range (-infinity,-mu)
1280 double L_point=-1;
int i;
for (i=0; i<NEWTON_STEPS; i++){
L_point-=(Lagrangian_f(L_point,3)/Lagrangian_fdash(L_point,3))
;
}
1285 return -L_point;
}
84 B. C ODE

double K_E(double* c){


double u=c[0];
1290 double v=c[1];
double pu=c[2];
double pv=c[3];
double K =pu*pu/2 + (sinh(v)*(cosh(v) - cos(u)*(2*muP - 1))*pu)
/4
+ pv*pv/2 + (sin(u)*(cos(u) - cosh(v)*(2*muP - 1))*pv)/4
1295 - cosh(v)/2 - (cos(u)*(2*muP - 1))/2 + (hP*(cos(2*u) - cosh(2*
v)))/8;
return K;
}

void integrationStep()
1300 {
/*ORIGINAL SPLIT-STEP METHOD No transformation
uHatStep(coords,dt/2);
tStep(coords,dt);
uHatStep(coords,dt/2);*/
1305
/* UNFINISHED: Levi-Civita Local transformations
double r1=sqrt((c[0]+muP)*(c[0]+muP)+c[1]*c[1]);
double r2=sqrt((c[0]+muP)*(c[0]+muP)+c[1]*c[1]);
if (r1<TOO_CLOSE){ //If we are Too Close to the first body
1310 zToW_lc1(c);
uHatStep_lc1(c,dt/2);
tHatStep_lc1(c,dt);
uHatStep_lc1(c,dt/2);
wToZ_lc1(c);
1315 }
else
{
tStep(c,dt/2);
uHatStep(c,dt);
1320 tStep(c,dt/2);
}*/

/*UNFINISHED BIRKHOFF TRANSFORMATION Global Transformation


birkhoff(c);
1325 uHatStep_birkhoff(c,dt/2);
birkhoff_inv(c);
tStep(c,dt);
birkhoff(c);
cout<<"w="<<c[0]<<"+"<<c[1]<<"i\n\n";
1330 uHatStep_birkhoff(c,dt/2);
birkhoff_inv(c);*/
B. C ODE 85

/*THIELE-BARRAU TRANSFORMATION*/
runge_kutta_4(coords,f_tb,dt);
1335 while (coords[0]<0)
coords[0]+=2*PI;
while (coords[0]>=2*PI)
coords[0]-=2*PI;
return;
1340 }

void tStep(double* c, double step){


//Code for Approximate Step
/*
1345 double change[4];
change[0]=px+y;
change[1]=py-x;
change[2]=py-x;
change[3]=-px-y;
1350 coords[0]+=step*change[0];
coords[1]+=step*change[1];
coords[2]+=step*change[2];
coords[3]+=step*change[3];*/

1355 //Code for Exact Step


double C0=c[0]+c[3];
double C1=c[1]-c[2];
double alpha=0.5*(c[1]+c[2]);
double beta=0.5*(c[0]-c[3]);
1360 double gamma=0.5*(c[3]-c[0]);
double lambda=0.5*(c[1]+c[2]);
c[0]=0.5*C0+alpha*sin(2*step)+beta*cos(2*step);
c[1]=0.5*C1+gamma*sin(2*step)+lambda*cos(2*step);
c[2]=-0.5*C1+gamma*sin(2*step)+lambda*cos(2*step);
1365 c[3]=0.5*C0-alpha*sin(2*step)-beta*cos(2*step);

return;
}

1370 double H_w(double* c){


//Calculate the energy of the original Hamiltonian
//in terms of T-B coordinates
complex<double> w (c[0],c[1]);
complex<double> pw (c[2],-c[3]);
1375 complex<double> f, fb, fp, fbp;
f=0.5*(1.0-2.0*muP+cos(w));
fb=0.5*(1.0-2.0*muP+cos(conj(w)));
fp=-0.5*sin(w);
fbp=-0.5*sin(conj(w));
1380 complex<double> result;
86 B. C ODE

complex<double> SNO(0,1);
result=pw*conj(pw)/(2.0*fp*fbp);
result=result+SNO*0.5*((conj(pw)*fb/fbp)-(pw*f/fp));
result=result-muP/abs(f-1.0+muP);
1385 result=result-(1.0-muP)/abs(f+muP);
if (abs(imag(result))>0.1)
cout<<"There is an issue!!";
return real(result);
}
1390
double* delUhat(double* c){
//Derivative of uHat
double* delU=new double[4];
delU[0]=0;
1395 delU[1]=0;
double mu1=1-muP;
double mu2=muP;
double r1=sqrt((c[0]+mu2)*(c[0]+mu2)+c[1]*c[1]);
double r2=sqrt((c[0]-mu1)*(c[0]-mu1)+c[1]*c[1]);
1400
double Uhat_r1=-mu1*r1+mu1/(r1*r1);
double Uhat_r2=-mu2*r2+mu2/(r2*r2);
double dr1dx=(c[0]+mu2)/r1;
double dr1dy=c[1]/r1;
1405 double dr2dx=(c[0]-mu1)/r2;
double dr2dy=c[1]/r2;
double Uhat_x=Uhat_r1*dr1dx+Uhat_r2*dr2dx;
double Uhat_y=Uhat_r1*dr1dy+Uhat_r2*dr2dy;

1410 delU[2]=-Uhat_x;
delU[3]=-Uhat_y;
return delU;
}

1415 void uHatStep(double* c, double step) {


//Take a step in the uHat Hamiltonian
double* change=new double[4];
change=delUhat(c);
c[0]+=step*change[0];
1420 c[1]+=step*change[1];
c[2]+=step*change[2];
c[3]+=step*change[3];
delete change;
return;
1425 }

double* delUhat_lc1(double* c){


//Derivative of uHat under the local transformation 1
B. C ODE 87

double* delU=new double[4];


1430 delU[0]=0;
delU[1]=0;
complex<double> w(c[0],c[1]);
double mu1=1-muP;
double mu2=muP;
1435 double r1=abs(w*w);
double r2=abs(w*w+1.0);
double Uhat_r1=-6.0*(1-muP)*r1*r1-2.0*muP*r2*r2-4.0*muP/r2-4.0*
hP;
double Uhat_r2=-4.0*muP*r1*r2+4.0*muP*r1/(r2*r2);
double dr1du=2*c[0];
1440 double dr1dv=2*c[1];
double dr2du=(2*c[0]*r1)/r2;
double dr2dv=(2*c[1]*r1)/r2;
delU[2]=Uhat_r1*dr1du+Uhat_r2*dr2du;
delU[3]=Uhat_r1*dr1dv+Uhat_r2*dr2dv;
1445 return delU;
}

void uHatStep_lc1(double* c, double step){


//Take a u-step in the local transform coords
1450 double* change=new double[4];
change=delUhat_lc1(c);
c[0]+=step*change[0];
c[1]+=step*change[1];
c[2]+=step*change[2];
1455 c[3]-=step*change[3];
delete change;
return;
}

1460 void tHatStep_lc1(double* c, double step){


//t step in local transform coords
double* change=new double[4];
complex<double> w(c[0],c[1]);
complex<double> pw(c[2],-c[3]) ;
1465 complex<double> sno(0,1);
complex<double> A,B;
A=pw+2.0*sno*w*conj(w)*conj(w)+2.0*muP*sno*w;
B=conj(A);
w=w+step*B;
1470 pw=pw-step*(2.0*sno*(conj(w)*conj(w)+muP)*B-4.0*sno*w*conj(w)*A)
;
c[0]=real(w);
c[1]=imag(w);
c[2]=real(pw);
c[3]=-imag(pw);
88 B. C ODE

1475 delete change;


return;
}

void zToW_lc1(double* c){


1480 //Transform from z co-ordinates to w co-ordinates
//For the body at -mu
complex<double> z(c[0],c[1]);
complex<double> pz(c[2],-c[3]);
complex<double> w;
1485 w=sqrt(-z-muP);
complex<double> pw;
pw=-2.0*w*pz;
c[0]=real(w);
c[1]=imag(w);
1490 c[2]=real(pw);
c[3]=-imag(pw);
}

void wToZ_lc1(double* c){


1495 //Inverse of above transform
complex<double> w(c[0],c[1]);
complex<double> pw(c[2],-c[3]);
complex<double> z;
z=-w*w-muP;
1500 complex<double> pz;
pz=(-pw)/(2.0*w);
c[0]=real(z);
c[1]=imag(z);
c[2]=real(pz);
1505 c[3]=-imag(pz);
}

void zToW_tb(double* c){


complex<double> z(c[0],c[1]);
1510 complex<double> pz(c[2],-c[3]);
complex<double> q,pq;
q=z+muP-0.5;
pq=pz;
complex<double> w,pw;
1515 complex<double> SNO(0,1);
w=0.5*PI+SNO*log(SNO*(2.0*q)+sqrt(1.0-4.0*q*q));
pw=-0.5*sqrt(1.0-4.0*q*q)*pq;
c[0]=real(w);
c[1]=imag(w);
1520 c[2]=real(pw);
c[3]=-imag(pw);
return;
B. C ODE 89

1525 void wToZ_tb(double* c){


complex<double> w(c[0],c[1]);
complex<double> pw(c[2],-c[3]);
complex<double> q,pq;
q=0.5*cos(w);
1530 pq=-2.0*pw/(sin(w));
complex<double> z,pz;
z=q-muP+0.5;
pz=pq;
c[0]=real(z);
1535 c[1]=imag(z);
c[2]=real(pz);
c[3]=-imag(pz);
return;
}
1540
void tStep_tb(double* c, double step){
//Kinetic step for the T-B transform
complex<double> w(c[0],c[1]);
complex<double> pw(c[2],-c[3]);
1545 complex<double> wdot, pwdot;
complex<double> A;
complex<double> SNO(0,1);
A=cos(w)*sin(conj(w))+(1.0-2.0*muP)*sin(conj(w))-4.0*SNO*conj(pw
);
wdot=0.25*SNO*A;
1550 pwdot=-(1.0/16.0)*((cos(w)*conj(cos(w))+(1.0-2.0*muP)*cos(w))*A-
sin(w)*conj(sin(w))*conj(A));
w=w+step*wdot;
pw=pw+step*pwdot;
c[0]=real(w);
c[1]=imag(w);
1555 c[2]=real(pw);
c[3]=-imag(pw);
}

void uStep_tb(double* c, double step){


1560 //Potential step for the T-B transform
double mu1,mu2;
mu1=1-muP;
mu2=muP;
complex<double> w(c[0],c[1]);
1565 complex<double> pw(c[2],-c[3]);
complex<double> wdot, pwdot;
double r1,r2;
r1=0.5*abs(cos(w)+1.0);
90 B. C ODE

r2=0.5*abs(cos(w)-1.0);
1570 double dudr1, dudr2;
dudr1=-0.5*(3.0*mu1*r1*r1*r2+mu2*r2*r2*r2)-mu2-hP*r2;
dudr2=-0.5*(3.0*mu2*r1*r2*r2+mu1*r1*r1*r1)-mu1-hP*r1;
complex<double> dr1dw, dr2dw;
dr1dw=-(sin(w)*(cos(conj(w))+1.0))/(4.0*r1);
1575 dr2dw=-(sin(w)*(cos(conj(w))-1.0))/(4.0*r2);
wdot=0;
pwdot=dudr1*dr1dw+dudr2*dr2dw;
w=w+step*wdot;
pw=pw-step*pwdot;
1580 c[0]=real(w);
c[1]=imag(w);
c[2]=real(pw);
c[3]=-imag(pw);
return;
1585 }

double* delUhat_birkhoff(double* c){


//The derivative of uHat for Birkhoff’s transformation
double u=c[0];
1590 double v=c[1];
complex<double> w(u,v);
double rho1=abs(w+0.5);
double rho2=abs(w-0.5);
double rho=abs(w);
1595 double r1=(rho1*rho1)/(2*rho);
double r2=(rho2*rho2)/(2*rho);
double dUdrho1=-(1-muP)*pow(rho1,3)/(2*rho*rho)+(4*rho*(1-muP))/
pow(rho1,3);
double dUdrho2=-pow(rho2,3)*muP/(2*rho*rho)+(4*muP*rho)/(pow(
rho2,3));
double dUdrho=-2*(1-muP)/(rho1*rho1)/(rho1*rho1);
1600 dUdrho-=2*muP/(rho2*rho2);
dUdrho+=muP*pow(rho2,4)/(4*pow(rho,3));
dUdrho+=(1-muP)*pow(rho1,4)/(4*pow(rho,3));
double drho1du=(u+0.5)/rho1;
double drho2du=(u-0.5)/rho2;
1605 double drhodu=(u)/rho;
double drho1dv=v/rho1;
double drho2dv=v/rho2;
double drhodv=v/rho;
double dUdu=dUdrho1*drho1du
1610 +dUdrho2*drho2du
+dUdrho*drhodu;
double dUdv=dUdrho1*drho1dv
+dUdrho2*drho2dv
+dUdrho*drhodv;
B. C ODE 91

1615 double* result=new double[4];


result[0]=0;
result[1]=0;
result[2]=-dUdu;
result[3]=-dUdv;
1620 return result;
}

void uHatStep_birkhoff(double* c, double step){


double* change=new double[4];
1625 change=delUhat_birkhoff(c);
c[0]+=step*change[0];
c[1]+=step*change[1];
c[2]+=step*change[2];
c[3]+=step*change[3];
1630 delete change;
return;
}

void birkhoff(double* c){


1635 //The Birkhoff transform from q to w
complex<double> q(c[0]+muP-0.5,c[1]);
complex<double> pq(c[2],c[3]);
complex<double> w=q+sqrt(q*q-0.25);
if (imag(q)>0 && real(q)>=0)
1640 w=q-sqrt(q*q-0.25);
if (imag(q)<=0 && real(q)>0)
w=q-sqrt(q*q-0.25);
complex<double> pw=pq*(w-q)/w;
c[0]=real(w);
1645 c[1]=imag(w);
c[2]=real(pw);
c[3]=imag(pw);
}

1650 double birkhoff_inv(double* c){


//The inverse Birkhoff transform (w to q)
//Returns the appropriate timestep
complex<double> w(c[0],c[1]);
complex<double> pw(c[2],c[3]);
1655 complex<double> q;
complex<double> pq;
double rho1=abs(w-0.5);
double rho2=abs(w+0.5);
double rho=abs(w);
1660 double dtau=(rho1*rho1*rho2*rho2)/(4*pow(rho,4));
q=0.25*(2.0*w+1.0/(2.0*w));
pq=w*pw/(w-q);
92 B. C ODE

c[0]=real(q)-muP+0.5;
c[1]=imag(q);
1665 c[2]=real(pq);
c[3]=imag(pq);
return dtau;
}

1670 void runge_kutta_4(double* y0, void (*derivs)(double*,double*),


double step){
//ASSUMES A TIME-INDEPENDENT DERIVATIVE, AND FOUR COORDINATES
int i;
double *k1 = new double[4];
double *k2 = new double[4];
1675 double *k3 = new double[4];
double *k4 = new double[4];
double *p = new double[4];
derivs(y0,k1);
for (i=0; i<4; i++){
1680 k1[i]=step*k1[i];
p[i]=y0[i]+0.5*k1[i];
}
derivs(p,k2);
for (i=0; i<4; i++){
1685 k2[i]=step*k2[i];
p[i]=y0[i]+0.5*k2[i];
}
derivs(p,k3);
for (i=0; i<4; i++){
1690 k3[i]=step*k3[i];
p[i]=y0[i]+k3[i];
}
derivs(p,k4);
for (i=0; i<4; i++){
1695 k4[i]=step*k4[i];
}
for (i=0; i<4; i++)
y0[i]=y0[i]+(k1[i]+2*k2[i]+2*k3[i]+k4[i])/6.0;
delete [] k1;
1700 delete [] k2;
delete [] k3;
delete [] k4;
delete [] p;

1705 return;
}

void f_tb(double *c, double *result){


B. C ODE 93

1710 double mu1,mu2;


mu1=1-muP;
mu2=muP;
double u,v,pu,pv;
u=c[0];
1715 v=c[1];
pu=c[2];
pv=c[3];
result[0]=pu+0.25*((1-2*muP)*cos(u)+cosh(v))*sinh(v);
result[1]=pv+0.25*(cos(u)+(1-2*muP)*cosh(v))*sin(u);
1720 result[2]=+((pv*sin(u)*sin(u))/4 - (sin(u)*(2*muP - 1))/2
+ (hP*sin(2*u))/4
- (pv*cos(u)*(cos(u) - cosh(v)*(2*muP - 1)))/4
- (pu*sin(u)*sinh(v)*(2*muP - 1))/4);
result[3]=+(sinh(v)/2 - (pu*sinh(v)*sinh(v))/4 + (hP*sinh(2*v))
/4
1725 - (pu*cosh(v)*(cosh(v) - cos(u)*(2*muP - 1)))/4
+ (pv*sin(u)*sinh(v)*(2*muP - 1))/4);
return;
}

1730
int main(int argc, char **argv){
//User option: ’pretty mode’ enables double buffering, runs much
slower, less flickery
char a;
cout<<"(f)ast mode or (p)retty mode? ";
1735 cin>>a;
while (a!=’f’ && a!=’p’)
cin>>a;

if (a==’f’) fastMode=true; else fastMode=false;


1740
// Initialization for GLUT
glutInit(&argc, argv);
if (fastMode)
glutInitDisplayMode(GLUT_RGBA);
1745 else
{
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA); //LOOKS NICE
intSteps=10;
dt=0.05;
1750 }

//Create parameter window


glutInitWindowSize(400, 400);
glutInitWindowPosition(10,90);
1755 paramWindow = glutCreateWindow("Parameter Space (h vs mu)");
94 B. C ODE

glutReshapeFunc(reshapeParam);
glutDisplayFunc(renderSceneParam);
glutMouseFunc(mouseParam);
glutSpecialFunc(sKeyboardParam);
1760 glutKeyboardFunc(nKeyboardPoin);
glutSetCursor(GLUT_CURSOR_FULL_CROSSHAIR);

//Create the orbit window Z-SPACE


glutInitWindowSize(400, 400);
1765 glutInitWindowPosition(10,520);
orbitWindow = glutCreateWindow("Orbit space (z space)");
glutDisplayFunc(redrawOrbit);
glutReshapeFunc(reshapeOrbit);
glutKeyboardFunc(nKeyboardPoin);
1770 renderSceneOrbit();

//Create the orbit window W-SPACE


glutInitWindowSize(400, 400);
glutInitWindowPosition(420,520);
1775 orbitWindowW = glutCreateWindow("Orbit space (w space)");
glutDisplayFunc(redrawOrbitW);
glutReshapeFunc(reshapeOrbitW);
glutKeyboardFunc(nKeyboardPoin);
renderSceneOrbitW();
1780
//Create the Poincare Window
//CURRENTLY: just the y=0, py>0 section
glutInitWindowSize(800, 800); //Large for finding bifurcations
//glutInitWindowSize(400, 400);
1785 glutInitWindowPosition(420,90);
poinWindow = glutCreateWindow("Poincare section");
glutReshapeFunc(reshapePoin);
glutDisplayFunc(redrawPoin);
glutMouseFunc(mousePoin);
1790 glutSetCursor(GLUT_CURSOR_FULL_CROSSHAIR);
glutKeyboardFunc(nKeyboardPoin);
glutSpecialFunc(sKeyboardPoin);
renderScenePoin();

1795 //Create the Interface Window (Shows important information)


glutInitWindowSize(800, 20);
glutInitWindowPosition(10,10);
UIWindow = glutCreateWindow("Important Things");
glutReshapeFunc(reshapeUI);
1800 glutDisplayFunc(redrawUI);
renderSceneUI();

//Add the menus


B. C ODE 95

createGLUTMenus();
1805 glutSetMenu(menu);

//The idle loop; runs when not rendering anything or taking


inputs
glutIdleFunc( idle );

1810 // Enter Glut Main Loop and wait for events


glutMainLoop();
return 0;
}

You might also like