Programming Assignment Checklist: Barnes-Hut

The assignment is due Monday at midnight, although you can turn it in without penality until Tuesday at midnight. Please note that any assignment turned in after 12 midnight on Tuesday (Dean's Date) will receive zero credit by University rule. No exceptions.

Goals

Frequently Asked Questions

The bodies seem to move in straight lines. Is this correct? Yes, most of the bodies do end up moving in fairly straight lines. Use planets.txt to see planets orbiting or halo.txt to see some interesting effects.

Why does the update formula use dt/2 instead of dt? That's a mistake. It should be dt, although the only effect of dt/2 will be to make the time step half as big.

How should I call the static add method in class Body? Use something like c = Body.add(a, b). It's legal and equivalent to write c = b.add(a, b), but this is bad style.

What's the quad for the initial universe? It's between (-R, -R) and (+R, +R) where R is the radius of the universe. Don't forget to check that each body is in the universe before inserting it into the tree.

I get a stack overflow error? Most likely you have an infinite recursive loop in your insert method. Also, be sure that when you insert a body that it will only end up in one of the four quads, e.g., use if-else-if-else-if-else or ensure that your contains method will only place a point in at most one of the four sub-quadrants of a quad.

How do I tell if a tree node is internal or external? Check if all four children are null. Consider writing a helper method isExternal() to check this.

How do I calculate center-of-mass of a body with an aggregate body? Just treat the aggregate body like any other body - the center of mass formula works even if one body is already the center of mass of several other bodies.

None of the particles appear on the screen. What could I be doing wrong? Make sure that your particles are not being drawn in the same color as your background. Don't forget to call Turtle.pause. Make sure that the x and y coordinates that you plot are between 0 and SIZE.

When computing the net force acting on body b, do I need a special case to prevent calculating the force between b and an aggregate body that happens to contain b? No. If an aggregate body representing a quad of size s contains b, then the distance d from b to the center of mass will be at most sqrt(2) × s. But in this case θ = s / d > 1/2, so the algorithm would need to expand the aggregate body anyway.

Who discovered the first subquadratic algorithm for N-Body simulation? Andrew Appel discovered his algorithm while at Princeton University working on his senior thesis in the Department of Physics.

When was the Barnes-Hut algorithm discovered? It was developed in 1986 by two astrophysicists at Princeton's Institute for Advanced Study.

Can the Barnes-Hut algorithm be extended to three dimensions? Yes. You can use an oct-tree instead of a quad-tree, although there are more wasted links.

Input, Output, and Testing

Input. Copy the files from the directory barnes-hut into your working directory. The file test2.txt is the 5 node example from the assignment.

Compilation and execution.  The main function must be in the file NBody.java. We will compile your program with:

javac NBody.java
and execute with
java NBody < input.txt

Submission

readme.txt. Use the following readme file template and answer any questions.

Submission.  Submit NBody.java and all of the files needed to run your program. Don't forget to hit the "Run Script" button on the submission system to test that it compiles cleanly.

Possible Progress Steps

These are purely suggestions for how you might make progress. You do not have to follow these steps.

  1. Download the directory barnes-hut to your system. It contains sample data files and the brute force implementation.

  2. Write a data type Quad.java to represent quadrants. Use Quad.java as a template. Do not think about proceding before you test and debug this data type.

  3. Body data type. Make sure that you understand the Body data type provided - we'll talk about this in precept. Write the two methods in and add. The second method returns a new object so you must use the keyword new to create it.

  4. Barnes-Hut tree data type. Create a program BHTree.java to represent a Barnes-Hut tree (or subtree). Write the data members and constructor. Your constructor should not be recursive, i.e., it should not call new. Why not?

  5. insert(Body b). Carefully follow the recursive strategy outlined in the assignment. This is the trickiest part of the program, although it can be done with around 15 lines of code. You will need to use new to create new Barnes-Hut trees as the tree groes. To represent a null branch coming from an internal node, we suggest creating a BHTree object whose body field is set to null. This way, you can recursively call the BHTree methods on this external node without getting a null pointer exception. This will also simplify the methods insert and updateForce.

  6. Testing. To confirm that the tree is being constructed correctly, write a method draw that does a preorder traversal of the Barnes-Hut tree and plots each of the quads (using four line segments) in Turtle graphics. Alternatively, write a method to print out the contents of the tree in preorder notation (i.e., print its root, then recursively print all its subtrees). To do this, write a toString method in BHTree.java. Mark internal nodes with an asterisk. If you implement null branches as suggested above, this code would look something like this:
    public String toString() {
            if(NE != null) return "*" + body + "\n" + NW + NE + SW + SE;
            else           return " " + body + "\n";
    }
    
    
    For testing, modify NBody.java to print only the first iteration of the simulation, then stop.

  7. updateForce(b). Think of this method as a kind of preorder traversal of the tree. When you hit an external node during the traversal, calculate the pairwise force between it and b, and update the net force acting on b. When you hit an internal node, calculate the ratio s/d. Depending on the ratio either (i) recursively invoke updateForce on its children or (ii) calculate the force between the aggregate body stored in the internal node and b, and update the net force acting on b. If you get a null pointer exception, try returning from the method if the body in the current tree node is null.

Enrichment


COS 126 Home Page
wayne@cs.princeton.edu