N-Body Simulation Checklist

Goals

Operating System Issue

Sorry, no IDE supports IO redirection or piping; use the Terminal/Command Prompt.

FAQ

Learn Sedgewick’s StdDraw and StdAudio libraries and familiarize yourself with the command line.

For help with standard input, review Students.kt. Compile and execute to make sure your system is configured properly. You can use students.txt as input.

For help with standard drawing, review BouncingBall.kt. There are many methods in StdDraw, but for this assignment, you will need only those used in BouncingBall.kt. Compile and execute to make sure your system is configured properly. You will need stdlib.jar, laser.wav, pop.wav, and earth.gif.

This program is more involved than the previous ones, so you should budget more time accordingly. The best advice we can give you is to carefully test, debug, and re-test your code as you write it. Do not attempt to write the whole program at once—if you do, then you will have no idea where to find the errors when the program doesn't work. Proactive testing will save you enormous amounts of time in the long run.

Yes, or you will lose a substantial number of points.

The java.util.Scanner class documentation is here.

They are avaiable through these links: StdDraw and StdAudio.

The command StdDraw.picture(x, y, filename) reads the image (either JPEG, GIF, or PNG format) from the specified filename and draws it to standard drawing, centered at (x, y).

Simulation

No, as indicated in the assignment, you must separate Step A (calculate all of the forces) from Step B(iii) (update the positions); otherwise, you will be computing the forces at time t using the velocities and positions of some of bodies at time t and others at time t + Δt.

It's the change in x-coordinate between two bodies (not between a body at time t and at time t + Δt).

Simulate the universe as long as t < Τ. For example, if Τ is 50,000 and Δt is 25,000, you should simulate the system for two steps (t = 0 and 25,000). If Τ is 60,000 and Δt is 25,000, you should simulate the system for three steps (t = 0, 25,000 and 50,000).

No.

Errors and Bugs

By convention, a variable in Kotlin should begin with a lowercase letter and use camel case, such as isLeapYear. A constant variable (a variable whose value does not change during the execution of a program, or from one execution of the program to the next) should begin with an uppercase letter and use underscores to separate any word boundaries, such as GRAVITATIONAL_CONSTANT. So, a Kotlin variable name might not always perfectly align with the corresponding domain-specific mathematical notation. In this case, tao or stoppingTime would be fine choices.

Be sure to follow the template in BouncingBall.kt. In particular, call StdDraw.enableDoubleBuffering() once at the beginning of your program; and call StdDraw.show() and StdDraw.pause(20) at the end of each time step (frame), not after each call to StdDraw.picture().

Check that you followed the assignment instructions exactly. In particular, you should have separate loops for Steps A, B, and C and you should update the velocities before the positions in Step B.

Did you use StdDraw.setXscale() and StdDraw.setYscale() to change the x- and y-coordinate systems to use the physics coordinates instead of the unit box? Since you want it centered on the origin with a "square radius" of radius, the minimum of each axis should be –radius and the maximum should be +radius.

Make sure that you get the sign right when you apply Newton's law of gravitation: (x[j] - x[i]) vs. (x[i] - x[j]). Note that Δx and Δy can be positive or negative so do not use kotlin.math.abs(). Do not consider changing the universal gravitational constant G to patch your code!

Sound

This application, or a library it uses, is using the deprecated Carbon Component Manager
for hosting Audio Units. Support for this will be removed in a future release.

You can ignore it. It is a warning intended for the authors of the Mac OS X Java 6 sound library. You should update your JDK to Java 8.

If you are running Windows, be sure that the audio stream that Java uses is not muted via Start -> Programs -> Accessories -> Multimedia -> Volume Control -> Wave Out.

java.util.prefs.WindowsPreferences (init).
Could not open/create prefs root node Software\JavaSoft\Prefs at root 0x80000002.
Windows RegCreateKeyEx(...) returned error code 5.

Try running your command prompt as administrator (right-click on the shortcut icon). Then use it as before and try again.

Testing and Debugging

Inserting print statements is a good way to trace what your program is doing. Our input files were created with the following println() statements.

println(n)
println("%.2e".format(radius))
for (i in 0 until n) {
    println("%11.4e %11.4e %11.4e %11.4e %11.4e %12s"
        .format(px[i], py[i], vx[i], vy[i], mass[i], image[i]))
}

As indicated in the collaboration policy, you may not copy or adapt code (except from the course materials). Moreover, you need to cite any code that you copy or adapt (except for code provided with the assignment). So, you are free to copy or adapt this code fragment, with or without citation.

Here are our results for a few sample inputs. Note that I had unzipped the file ‘nbody.zip’ into my current directory that contains the Kotlin source code for this project. During unzipping, the ‘nbody’ folder should have been created and other files should have been unzipped into the ‘nbody’ directory automatically.

$ java NbodyKt 0.0 25000.0 < nbody/planets.txt           // zero steps
5
2.50e+11
 1.4960e+11  0.0000e+00  0.0000e+00  2.9800e+04  5.9740e+24    earth.gif
 2.2790e+11  0.0000e+00  0.0000e+00  2.4100e+04  6.4190e+23     mars.gif
 5.7900e+10  0.0000e+00  0.0000e+00  4.7900e+04  3.3020e+23  mercury.gif
 0.0000e+00  0.0000e+00  0.0000e+00  0.0000e+00  1.9890e+30      sun.gif
 1.0820e+11  0.0000e+00  0.0000e+00  3.5000e+04  4.8690e+24    venus.gif

$ java NbodyKt 25000.0 25000.0 < nbody/planets.txt       // one step
5
2.50e+11
 1.4960e+11  7.4500e+08 -1.4820e+02  2.9800e+04  5.9740e+24    earth.gif
 2.2790e+11  6.0250e+08 -6.3860e+01  2.4100e+04  6.4190e+23     mars.gif
 5.7875e+10  1.1975e+09 -9.8933e+02  4.7900e+04  3.3020e+23  mercury.gif
 3.3087e+01  0.0000e+00  1.3235e-03  0.0000e+00  1.9890e+30      sun.gif
 1.0819e+11  8.7500e+08 -2.8329e+02  3.5000e+04  4.8690e+24    venus.gif

$ java NbodyKt 50000.0 25000.0 < nbody/planets.txt       // two steps
5
2.50e+11
 1.4959e+11  1.4900e+09 -2.9640e+02  2.9799e+04  5.9740e+24    earth.gif
 2.2790e+11  1.2050e+09 -1.2772e+02  2.4100e+04  6.4190e+23     mars.gif
 5.7826e+10  2.3945e+09 -1.9789e+03  4.7880e+04  3.3020e+23  mercury.gif
 9.9262e+01  2.8198e-01  2.6470e-03  1.1279e-05  1.9890e+30      sun.gif
 1.0818e+11  1.7499e+09 -5.6660e+02  3.4998e+04  4.8690e+24    venus.gif

$ java NbodyKt 60000.0 25000.0 < nbody/planets.txt       // three steps
5
2.50e+11
 1.4958e+11  2.2349e+09 -4.4460e+02  2.9798e+04  5.9740e+24    earth.gif
 2.2789e+11  1.8075e+09 -1.9158e+02  2.4099e+04  6.4190e+23     mars.gif
 5.7752e+10  3.5905e+09 -2.9682e+03  4.7839e+04  3.3020e+23  mercury.gif
 1.9852e+02  1.1280e+00  3.9705e-03  3.3841e-05  1.9890e+30      sun.gif
 1.0816e+11  2.6248e+09 -8.4989e+02  3.4993e+04  4.8690e+24    venus.gif


$ java NbodyKt 31557600.0 25000.0 < nbody/planets.txt    // one year
5
2.50e+11
 1.4959e+11 -1.6531e+09  3.2949e+02  2.9798e+04  5.9740e+24    earth.gif
-2.2153e+11 -4.9263e+10  5.1805e+03 -2.3640e+04  6.4190e+23     mars.gif
 3.4771e+10  4.5752e+10 -3.8269e+04  2.9415e+04  3.3020e+23  mercury.gif
 5.9426e+05  6.2357e+06 -5.8569e-02  1.6285e-01  1.9890e+30      sun.gif
-7.3731e+10 -7.9391e+10  2.5433e+04 -2.3973e+04  4.8690e+24    venus.gif

// this test should take only a few seconds. 4.294E9 is bigger than the largest Int
$ java NbodyKt 4.294E9 2.147E9 < nbody/3body.txt
3
1.25e+11
 2.1470e+12 -7.8082e-03  5.0000e+02 -3.6368e-12  5.9740e+24    earth.gif
 1.2882e+14 -1.5100e+17  3.0000e+04 -3.5165e+07  1.9890e+30      sun.gif
-1.2882e+14  1.5100e+17 -3.0000e+04  3.5165e+07  1.9890e+30      sun.gif

Possible Progress Steps

These are purely suggestions for how you might make progress. You do not have to follow these steps. If you get stumped or frustrated on some portion of the assignment, you should not hesitate to consult your lab instructor, or a TA, or a tutor.

The key to composing a large program is decomposing it into smaller steps that can be implemented and tested incrementally. Here is the decomposition we recommend for this assignment.

Parse command-line arguments

Read universe from standard input

Initialize standard drawing

Play music on standard audio

Simulate the universe

  1. Calculate net forces
  2. Update velocities and positions
  3. Draw universe to standard drawing

Print universe to standard output

These are the order in which the components will appear in your code. However, to facilitate testing and debugging, we recommend implementing them in the following order.

Step 1: parse command-line arguments

Step 2: read universe from standard input

Step 6: print universe to standard output

Step 3: initialize standard drawing

Step 4: play music on standard audio

Step 5: simulate the universe

Step 5B: update the velocities and positions

Step 5C: draw universe to standard drawing

Step 5A: calculate the forces

Enrichment

It's the fanfare to Also sprach Zarathustra by Richard Strauss. It was popularized as the key musical motif in Stanley Kubrick's 1968 film 2001: A Space Odyssey.

The leapfrog method is more stable for integrating Hamiltonian systems than conventional numerical methods like Euler's method or Runge–Kutta. The leapfrog method is symplectic, which means it preserves properties specific to Hamiltonian systems (conservation of linear and angular momentum, time-reversibility, and conservation of energy of the discrete Hamiltonian). In contrast, ordinary numerical methods become dissipative and exhibit qualitatively different long-term behavior. For example, the earth would slowly spiral into (or away from) the sun. For these reasons, symplectic methods are extremely popular for n-body calculations in practice. You asked!

Here's a more complete explanation of how you should interpret the variables. The classic Euler method updates the position uses the velocity at time t instead of using the updated velocity at time t + Δt. A better idea is to use the velocity at the midpoint t + Δt / 2. The leapfrog method does this in a clever way. It maintains the position and velocity one-half time step out of phase: At the beginning of an iteration, (px, py) represents the position at time t and (vx, vy) represents the velocity at time t − Δt / 2. Interpreting the position and velocity in this way, the updated position (px + Δt vx, py + Δt vy). uses the velocity at time t + Δt / 2. Almost magically, the only special care needed to deal with the half time-steps is to initialize the system's velocity at time t = −Δt / 2 (instead of t = 0.0), and you can assume that we have already done this for you. Note also that the acceleration is computed at time t so that when we update the velocity, we are using the acceleration at the midpoint of the interval under consideration.

Yes, Sundman and Wang developed global analytic solutions using convergent power series. However, the series converge so slowly that they are not useful in practice. See The Solution of the N-body Problem for a brief history of the problem.

N-body simulations play a crucial role in our understanding of the universe. Astrophysicists use it to study stellar dynamics at the galactic center, stellar dynamics in a globular cluster, colliding galaxies, and the formation of the structure of the Universe. The strongest evidence we have for the belief that there is a black hole in the center of the Milky Way comes from very accurate n-body simulations. Many of the problems that astrophysicists want to solve have millions or billions of particles. More sophisticated computational techniques are needed.

The same methods are also widely used in molecular dynamics, except that the heavenly bodies are replaced by atoms, gravity is replaced by some other force, and the leapfrog method is called Verlet's method. With van der Waals forces, the interaction energy may decay as 1/R 6 instead of an inverse square law. Occasionally, 3-way interactions must be taken into account, e.g., to account for the covalent bonds in diamond crystals.

Kepler's Orrery uses an n-body simulator to compose and play music.

Here's a wealth of information on n-body simulation.

Here are some interesting two-body systems. Here is beautiful 21-body system in a figure-8 —reproducing this system (in a data file in our format) will earn you a small amount of extra credit.