package nbody; class Body { float G; int NUMPLANETS; float x, y; float ax, ay; float mass; float radius; array [Body] planets; int myIndex; Semaphore mySem; boolean sticky; constructor(float x_, float y_, float mass_, float radius_, float ax_, float ay_, int index, Semaphore sem) { G = -9.7; NUMPLANETS = 32; sticky = false; x = x_; y = y_; mass = mass_; radius = radius_; ax = ax_; ay = ay_; planets = new Body[NUMPLANETS]; myIndex = index; mySem = sem; } void assignBody( int index, Body partner ) { planets[index] = partner; } void move(){ int size = NUMPLANETS; float dy,dx,rad,g,force,tempx,tempy; float ax=this.ax; float ay=this.ay; float x = this.x; float y = this.y; float radius = this.radius; float mass = this.mass; boolean sticky = this.sticky; if( myIndex != 20 ) { printspec(x,y); } else { printspecb(x,y); } x = x + ax; y = y + ay; int jj = 0; while( jj < size ) { if((myIndex != jj)) { Body body = planets[jj]; dx = x - body.x; dy = y - body.y; rad = dx*dx + dy*dy; if(rad <= (radius*radius + body.radius*body.radius)) { if(sticky){ tempy = body.ay; tempx = body.ax; force = body.mass * body.ax; body.ax = body.ax - force / mass; force = body.mass * body.ay; body.ay = body.ay - force / mass; force = mass * tempx; ax = ax - force / body.mass; force = mass * tempy; ay = ay - force / body.mass; } else{ tempy = ay; tempx = ax; force = body.mass * body.ax; ax = ax + force / mass; force = body.mass * body.ay; ay = ay + force / mass; force = mass * tempx; body.ax = body.ax + force / body.mass; force = mass * tempy; body.ay = body.ay + force / body.mass; } } g = G * body.mass / rad; rad = sqrt(rad); ax = ax + g * (dx/rad); ay = ay + g * (dy/rad); } jj = jj + 1; } this.x = x; this.y = y; this.ax = ax; this.ay = ay; mySem.signal(); } } class SimEngine { array[Semaphore] sem4; // array[Semaphore] sem5; int numIter; int iter; constructor() { int i; int j; Semaphore sem; Semaphore semA; Semaphore semB; int NUMPLANETS = 32; float xsize = 400.0; float ysize = 400.0; float G = -9.7; array[Body] bodies; array[Semaphore] sem0; array[Semaphore] sem1; array[Semaphore] sem2; array[Semaphore] sem3; numIter = 10; iter = 0; // NUMPLANETS = 32; // xsize = 400.0; // ysize = 400.0; // G = -9.7; bodies = new Body[NUMPLANETS]; sem0 = new Semaphore[NUMPLANETS/2]; i = 0; while( i < NUMPLANETS ) { sem = new Semaphore(false, this, true); if( i == 20 ) { bodies[i] = new Body(([float]frandom()) * xsize, ([float]frandom()) * ysize, 500.0, 5.0, 0.0, 0.0, i, sem); } else { bodies[i] = new Body(([float]frandom()) * xsize, ([float]frandom()) * ysize, 1.0, 1.0, 0.0001 * G * G, 0.0001 * G * G, i, sem); } i = i + 1; bodies[i] = new Body(([float]frandom()) * xsize, ([float]frandom()) * ysize, 1.0, 1.0, 0.0001 * G * G, 0.0001 * G * G, i, sem); i = i + 1; sem.assignLeaves(bodies[i-2],bodies[i-1]); sem0[i/2 - 1] = sem; prints("."); cycles(); } i = 0; array[Body] lbodies = bodies; int NP = NUMPLANETS; while( i < NP ) { Body b = lbodies[i]; array[Body] planets = b.planets; j = 0; planets[j] = lbodies[j]; // sets up store capability j = j + 1; while( j < NP ) { // b.assignBody(j, bodies[j]); planets[j] = lbodies[j]; //b.planets[j] = bodies[j]; j = j + 1; } i = i + 1; prints("+"); cycles(); } membar(); i = 0; sem1 = new Semaphore[NUMPLANETS/4]; while( i < NUMPLANETS / 2 ) { sem = new Semaphore(false, this, false); semA = sem0[i]; i = i + 1; semB = sem0[i]; i = i + 1; sem.assignChildren(semA, semB); semA.assignParent(sem); semB.assignParent(sem); sem1[i/2 - 1] = sem; prints("-"); cycles(); } i = 0; sem2 = new Semaphore[NUMPLANETS/8]; while( i < NUMPLANETS / 4 ) { sem = new Semaphore(false, this, false); semA = sem1[i]; i = i + 1; semB = sem1[i]; i = i + 1; sem.assignChildren(semA, semB); semA.assignParent(sem); semB.assignParent(sem); sem2[i/2 - 1] = sem; prints("/"); cycles(); } i = 0; sem3 = new Semaphore[NUMPLANETS/16]; while( i < NUMPLANETS / 8 ) { sem = new Semaphore(false, this, false); semA = sem2[i]; i = i + 1; semB = sem2[i]; i = i + 1; sem.assignChildren(semA, semB); semA.assignParent(sem); semB.assignParent(sem); sem3[i/2 - 1] = sem; prints("*"); cycles(); } i = 0; sem4 = new Semaphore[NUMPLANETS/32]; while( i < NUMPLANETS / 16 ) { sem = new Semaphore(true, this, false); semA = sem3[i]; i = i + 1; semB = sem3[i]; i = i + 1; sem.assignChildren(semA, semB); semA.assignParent(sem); semB.assignParent(sem); sem4[i/2 - 1] = sem; prints("#"); cycles(); } // i = 0; // sem5 = new Semaphore[NUMPLANETS/64]; // while( i < NUMPLANETS / 32 ) { // sem = new Semaphore(true, this, false); // semA = sem4[i]; // i = i + 1; // semB = sem4[i]; // i = i + 1; // sem.assignChildren(semA, semB); // semA.assignParent(sem); // semB.assignParent(sem); // sem5[i/2 - 1] = sem; // } } void signal() { if( iter < numIter ) { iter = iter + 1; Semaphore s = sem4[0]; prints("barrier"); cycles(); s.go(); } else { prints("done"); cycles(); } } void step() { iter = numIter; Semaphore s = sem4[0]; s.go(); } void start() { iter = 0; Semaphore s = sem4[0]; s.go(); } } class Semaphore { int semCount; Semaphore parent; boolean top; boolean bottom; SimEngine se; Body child1, child2; Semaphore sem1, sem2; constructor(boolean isTop, SimEngine eng, boolean isBot) { if( isTop ) { prints("created top object"); } semCount = 0; top = isTop; se = eng; bottom = isBot; } void assignParent( Semaphore par ) { parent = par; } void assignChildren( Semaphore s1, Semaphore s2 ) { sem1 = s1; sem2 = s2; } void assignLeaves( Body c1, Body c2 ) { child1 = c1; child2 = c2; } void go() { if( bottom ) { child1.move(); child2.move(); } else { sem1.go(); sem2.go(); } } void signal() { semCount = semCount + 1; if( semCount == 2 ) { semCount = 0; if( !top ) { prints("signalling semaphore"); parent.signal(); } if( top ) { prints("signalling top"); se.signal(); } } } } void main() { SimEngine se; prints("init nbody..."); cycles(); se = new SimEngine(); prints("starting nbody..."); cycles(); se.start(); }