Home
Name Modified Size InfoDownloads / Week
3D_Cluster.png 2017-01-18 11.7 kB
starClusterIn3D.c 2017-01-18 24.6 kB
ClusterSimulationIn3D.c 2016-12-03 23.5 kB
readMe 2012-02-19 10.0 kB
nBody01_3.tgz 2012-02-19 19.2 kB
nBody01_2.tgz 2012-01-23 17.2 kB
nBody0_1.1.tgz 2011-12-31 15.1 kB
Totals: 7 Items   121.3 kB 0
The nBody program.

The program is currently configured to run on a Linux system, and these
instructions assume that that is the case.  This is a very CPU intensive
application, so the faster your system, the better your results.  It was
developed on a 64 bit system, but will run on a 32 bit system.  You'll need to
have the GNU C development suite installed, including gcc and make.  The
debugger, gdb, is also recommended, as, of course, is a familiarity with C and
programming in general. The Python visualizer programs of course require that
you have Python installed on your machine.

The programs are designed to be run from a command line.  Feel free to create a
GUI interface if you so desire.

These programs are designed with the idea that you, the user, will edit the code
to enhance/tweak/modify it to make it do your bidding.  I have tried to comment
it so that what it's doing should be clear.

This read me should get you started, but I urge you to read the code itself for
a deep understanding of what's going on.

Installation:

   Download nBody.tgz to your machine.

   Copy it to the directory where you'll be using it, for example:

     cp nbody.tgz /home/myRootDir/nBody

   In that directory, unzip and untar it, continuing with the example:

     cd /home/myRootDir/nBody
     unzip nbody.tgz
     tar -xf nbody.tgz
   
   To compile large cluster:

     make

     Your executable will be called largeCluster.

   To compile small cluster:

     gcc -O2 -o nb 2 -Wall $1 smallCluster.c -lm

     This compiles to a version that will run quickly, but not be debuggable.

     gcc -o nb -Wall -g smallCluster -lm

     This compiles to a debuggable (with the Gnu debugger) version.

     The executable version in both cases is named nb.

     Run it from the command line with this command:

       ./nb <outputFileName> <number of stars>

       Output file name is the name you want to give this run.
       Number of stars is the number of stars you want in the simulation.

     Run time on a 2.7 Ghz 64 bit Linux machine is about a minute for 16 stars,
     and a day for 256 stars.

     If the computer is turned off during a run, you can restart the run with
     the same command that you used to start it.  SmallCluster.c periodically
     saves the state of the cluster in a backup file on the nBody directory.
     When the run finishes, this file is deleted.  If the run was interrupted,
     the backup file is read and the run continues.


What this program does is take an initial arrangement of stars and allow them
to gravitationally interact, using standard Newtonian gravity, for the number
of iterations specified in orbit.c.

The simple story (as coded in smallCluster.c). For each iteration, each star
looks at every other star and calculates the distance between them.  Then the
gravitational force between the stars is calculated by, you guessed it:

     Fg = G m1 m2 / r^2.

Of course, we need to allow for the vector components, so the real equation is:

         i = 3
          _
     Fg = \ G m1 m2 x(i) / r^3.
          /_
         i = 1

One then sums these forces into the total force, and then calculates the
acceleration for the given star, i, and calculate for all three dimensions:

    a(i) = F / m(i);

The change in velocity is:

    v(i) = v(i)  + (a(i) dt / 2)

where dt is the time interval we're using. Dt is calculated by finding the two
stars that are closest to each other and determining the orbital velocity
between these stars as if they were in a stable, circular orbit with each other.
Dt is set to 1/1000th of this orbital time.  This makes for a slow simulation,
but minimizes energy creep while maintaining high accuracy.  

The initial purpose of NBody was to simulate the formation of binary stars in
newly forming clusters, thus the need for the accuracy.

Finally, the position changes by:

    x(i) = x(i) + v(i);

over the three dimensions.

Simple, huh?  With this you can move planets, as Feynman shows in volume 1
of his physics lectures.

Stars aren't so simple.  The problem is when two stars happen to get very
close to one another, the force becomes quite large.  Then the velocity change
is greatly effected, to, and this passes on to the position.  Bingo. Suddenly
these stars are quite far apart, and they have high velocity. In reality, as
the stars separate, their mutual gravity slows them down, but not here.  We
only calculate gravity each dt, not continuously, as nature does.  We've added
fictitious energy, or energy creep, into the stem.  Something must be done.

Small cluster does it by making the delta time, dt very small, as described
above.  Large cluster is a bit more complex.

It should also be noted that stars very far from the star you are currently
moving have only a minimal impact on your star.  This is inefficient.

Large cluster deals with these issues by only looking at stars that are within a
cube that is accDst * 2 in size. These stars are given the Newtonian treatment,
all other stars are lumped into a single mass at the cluster's center, and
then treated as a single star. It also checks the distance between the two
stars in the cube, and if it's smaller than minRadius, it puts them into a
group of close stars (*group). This small group is the processed with the
Newtonian treatment, except that dt is modified so the stars would only move
at most about 10 degrees in their orbit per dt.

How it works:

  NewLargeRun.c creates as many stars as you desire (nSt) and gives them an
initial position and velocity.  In practice, users back up newLargeRun.c
to another file, say originalNewRun.c and copy a version of newLarge Run.c that
configures the simulation to their current project.

  LargeCluster.c moves the stars. Each iteration begins by clearing the
acceleration and hash variables, updating each star's position, and calculating
the amount of mass is between the center of the star and a series of radii
from it (nRadii).  This latter quantity is used for stars greater than accDis
from the star whose motion is being calculated (current star).

  Also calculated at this time is a series of hashes that place a star in the
three coordinates, x, y, and z. Later, these hashes will be searched for stars
close to current star. Not having to check all of the stars for each current
stars is a helpful speed up.

  The iteration continues by searching the hashes for stars near the current
star and saving them into an array, near.

  For all stars in near, the mutual distances are calculated and stored in the
two dimensional r array. If the stars are closer than minRadius, they are
placed in the group array. After all of the stars not in the group array are
processed, the group array as a whole is processed, using only the stars in the
group, and making the time interval as small as needs be to prevent adding the
energy creep mentioned above.

  When the contributions from all the nearby stars have been added up, all
other star are treated as if they were at the center of the cluster.  These are
then added to the force as a whole, and the star is ready to be moved.

 Stars near the cluster's center are all treated as if they are close together.

  Every iteration/iter times, orbit calls ckMomentum.  This calculates the
virial theorem for the cluster, which is a good measure of how it's doing. If
the (potential energy) / (kinetic energy) should be around 2.

  All of the units used by nBody are MKS.  I know, one can rationalize the
units, (e.g. G == 1) and avoid a multiplication, but this can be done after
everything else is shown to be correct.

  Unlike most programs you find on the internet, nBody expects that you're
going to edit the code itself to change parameters.  If you mess up, you can
always download it again and start over!  So a short description of nBody's
components is in order.

largeCluster.c: The program that moves the stars and generates the results.

largeCluster.h: Variables common to two or more modules, system includes.

largeClusterDisplay.py: A python program that displays star movement projected
                onto the X-Y plane.  You'll need to have output formatted
                by orbit.c with this snippet (currently commented out)
                for it to work:

                 // Convert the positions into accurate integers for the
                 // python visualizer.
                 /*for (i = 0; i < nSt; i++) {
                     j = (int) (x[i] * scale);
                     k = (int) (y[i] * scale);
                     printf("%d %d^", j, k);
                   }
                   printf("\n"); //TEST */

plotSmallCluster.py: This plots the results of smallCluster.c much as 
                     largeClusterDisplay.py plots the results of largeCluster.

Makefile: Compile everything, and make an executable called largeCluster.
          Just type "make" to do this.

newLarge Run.c: This sets up the stars, and assigns each a position,
         velocity and  mass.

readme: This document.

output directory: Every N iterations, write out the status of the program
                  and eliminate any systematic drift (all velocities should
                  sum to zero). This is done by updateRun, and the results
                  are stored here.

smallCluster.c: Apply the simple method to all stars.  Don't check for close
                encounters. O n^2, but fast enough for less than 100 stars.
                It's currently set up for 16 stars.

                Use this program to accurately simulate small numbers (<1024)
                of stars.

Notes.

   After quite a bit of futzing around with both versions of the program, I have
found that smallCluster.c gives the results that I had originally built NBody
for.  LargeCluster has been a bit neglected of late.

ToDo:

  Create a version of the program(s) that simulates dark matter.

  Cause stars to age as a function of their mass.

  Parallize the code so that it runs on an Nvidia card using their CUDA system.
Source: readMe, updated 2012-02-19