/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package parallelnbody;
import java.awt.Color;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.util.Locale;
import java.util.Scanner;
/**
*
* @author alefrag
*/
public class ParallelNBody {
//Set value to simulate seconds of the bodies
static final int execTime = 100;
static final boolean draw = false;
public static void main(String[] args) throws FileNotFoundException {
//Make sure we are at the correct format for input PA
Locale.setDefault(new Locale("en", "US"));
//Allow for reading from args[0] PA
String fname = args[0];
int numThreads = 1; // default
if (args.length > 1) {
try {
numThreads = Integer.parseInt(args[1]);
if (numThreads < 1) numThreads = 1;
} catch (NumberFormatException e) {
numThreads = 1;
}
}
java.util.concurrent.ExecutorService executor = java.util.concurrent.Executors.newFixedThreadPool(numThreads);
FileInputStream is = new FileInputStream(new File(fname));
System.setIn(is);
Scanner console = new Scanner(System.in);
final double dt = 0.1; // time quantum
int N = console.nextInt(); // number of particles
double radius = console.nextDouble(); // radius of universe
// turn on animation mode and rescale coordinate system PA
if (draw) {
StdDraw.show(0);
StdDraw.setXscale(-radius, +radius);
StdDraw.setYscale(-radius, +radius);
}
// read in and initialize bodies
Body[] bodies = new Body[N]; // array of N bodies
for (int i = 0; i < N; i++) {
double px = console.nextDouble();
double py = console.nextDouble();
double vx = console.nextDouble();
double vy = console.nextDouble();
double mass = console.nextDouble();
int red = console.nextInt();
int green = console.nextInt();
int blue = console.nextInt();
Color color = new Color(red, green, blue);
bodies[i] = new Body(px, py, vx, vy, mass, color);
}
// Store time after IO
long startTime = System.nanoTime();
// simulate the universe
for (double t = 0.0; t < execTime; t = t + dt) {
Quad quad = new Quad(0, 0, radius * 2);
BHTree tree = new BHTree(quad);
// build the Barnes-Hut tree (serial)
for (int i = 0; i < N; i++) {
if (bodies[i].in(quad)) {
tree.insert(bodies[i]);
}
}
// parallel update: χωρίζουμε τα bodies σε chunks, ένα Runnable ανά thread
java.util.List> tasks = new java.util.ArrayList<>(numThreads);
final int chunkSize = (N + numThreads - 1) / numThreads; // ceil
for (int ti = 0; ti < numThreads; ti++) {
final int start = ti * chunkSize;
final int end = Math.min(N, start + chunkSize);
tasks.add(new java.util.concurrent.Callable() {
@Override
public Void call() throws Exception {
for (int i = start; i < end; i++) {
bodies[i].resetForce();
tree.updateForce(bodies[i]); // read-only on tree
bodies[i].update(dt);
}
return null;
}
});
}
try {
// invokeAll θα μπλοκάρει μέχρι να ολοκληρωθούν όλα τα tasks
executor.invokeAll(tasks);
} catch (InterruptedException ex) {
Thread.currentThread().interrupt();
break;
}
// If draw is enabled update picture
if (draw) {
StdDraw.clear(StdDraw.BLACK);
for (int i = 0; i < N; i++) {
bodies[i].draw();
}
StdDraw.show(0);
}
}
//Terminating the executor
executor.shutdown();
try {
if (!executor.awaitTermination(5, java.util.concurrent.TimeUnit.SECONDS)) {
executor.shutdownNow();
}
} catch (InterruptedException ex) {
executor.shutdownNow();
Thread.currentThread().interrupt();
}
//Print execution time and exit
long endTime = System.nanoTime();
long totalTime = endTime - startTime;
System.out.println("Simulation time: " + ((double) totalTime) / 1E9);
System.exit(0);
}
}