-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathNBody.java
More file actions
189 lines (148 loc) · 6.97 KB
/
NBody.java
File metadata and controls
189 lines (148 loc) · 6.97 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
/*******************************************************************************
*
* GOAL:
* Dependencies: StdDraw.java, StdAudio.java, Body.java
*
* N-body simulation.
* * Reads in number of bodies N, radius of universe R, initial positions,
* velocities, masses, and name of image files from text file;
* * Simulate the system from time t = 0 until t >= T and plots the
* the results to standard drawing;
*
******************************************************************************/
import java.util.Scanner;
import java.io.File;
import java.io.FileNotFoundException;
public class NBody {
// animation pause (in miliseconds)
public static final int DELAY = 20;
// music (2001 theme)
public static final String MUSIC = "2001theme.wav";
// background image
public static final String BACKGROUND = "starfield.jpg";
// parameters input file
public static String PLANETS_FILE;
// size of mesh grid
public static final int MESH_SIZE = 3;
public static final int MESH_SQUARE = MESH_SIZE * MESH_SIZE;
// numerical constants
public static final double G = 6.67e-11; // gravitational constant (N m^2 / kg^2)
public static final double T= 157788000.0; // simulate from time 0 to T (s);
public static final double dt = 25000.0; // time quantum (s);
public static final double SCALE = 0.042; // scalar for star size
// parameters from first two lines
public static int N; // number of bodies
public static double R; // radius of universe
// global arrays of Body properties
public static Body[] objects;
// read the planet file, new the parallel arrays,
// and load their values from the file.
public static void loadPlanets() {
// open a parameters File to read from
Scanner scan = null;
try { File f = new File(getFile()); scan = new Scanner( f ); }
catch(FileNotFoundException e) { System.out.println("File not found exception"); }
// read from standard input
N = scan.nextInt(); // number of bodies
R = scan.nextDouble(); // radius of universe (m)
// declare parallel arrays
objects = new Body[N];
// read in initial position, velocity, mass, and image name from .txt file
// NOTE: assumes first object is giant black hole!
objects[0] = new BlackHole(scan, R);
for (int i = 1; i < N; i++) {
objects[i] = new Star(scan, R);
}
}
public static String getFile() {
String inputFile = "chaos.txt";
System.out.print("parameters input file: " + inputFile);
return inputFile;
}
public static void runSimulation() {
// run numerical simulation from 0 to T
for (double t = 0.0; t < T; t += dt) {
// draw background
StdDraw.picture(0.0, 0.0, BACKGROUND);
// resize mesh for this round
Mesh[] mesh = new Mesh[MESH_SQUARE];
// reinit mesh for this round
for (int i = 0; i < MESH_SQUARE; i++) {
mesh[i] = new Mesh(N);
}
// assign each object to a mesh location
for (int i = 0; i < N; i++) {
// check if object is still in play
if (!objects[i].isRemoved()) {
int index = findIndex(i);
mesh[index].addObj(i);
}
}
// calculate Center of Mass of each mesh
for (int i = 0; i < MESH_SQUARE; i++) {
mesh[i].updateCOM(objects);
}
// calculate forces on each object
for (int i = 0; i < N; i++) {
// check if object is still in play
if (!objects[i].isRemoved()) {
// init the fx and fy components to 0 for next sum
objects[i].zeroF();
// find which mesh grid object i resides in
int grid_index = findIndex(i);
// update force components acting on object i from
// each GRID that object i does NOT reside in
for (int j = 0; j < MESH_SQUARE; j++) {
if (j != grid_index) {
mesh[j].updateF(objects[i], G);
}
}
// update force components acting on object i from
// each OBJECT in the SAME mesh grid as object i
for (int j = 0; j < mesh[grid_index].mesh_index; j++) {
// find the index of the next object in this mesh grid
int obj_index = mesh[grid_index].grid[j];
// update additive fx && fy components
if (i != obj_index && !objects[obj_index].isRemoved()) { objects[i].updateF(objects[obj_index], G); }
}
// reinitialize objects to match their images
if (objects[i] instanceof Star) {
if (objects[i].getImage() == "blackhole.gif") { objects[i] = new BlackHole(objects[i].params(), R); }
if (objects[i].getImage() == "neutron.gif") { objects[i] = new Neutron(objects[i].params(), R); }
if (objects[i].getImage() == "pulsar.gif") { objects[i] = new Pulsar(objects[i].params(), R); }
}
// update velocities and positions
objects[i].step(dt);
// draw this object
objects[i].draw();
}
}
// display the Canvas for this round
StdDraw.show();
StdDraw.pause(DELAY);
}
}
public static int findIndex(int i) {
// shift range from [-R, R] to [0, 2R]
double tmpX = objects[i].getRx() + R;
double tmpY = objects[i].getRy() + R;
// make MESH_SIZE number of divides across grid space
double breaks = 2 * R / MESH_SIZE;
// integer roundoff to find appropriate grid row and column && catch bounds
int col = Math.max(Math.min((int) (tmpX / breaks), 0), MESH_SIZE - 1);
int row = Math.max(Math.min((int) (tmpY / breaks), 0), MESH_SIZE - 1);
// return linearized grid index
return MESH_SIZE * row + col;
}
public static void main(String[] args) {
// read in objects from .txt file
loadPlanets();
// rescale coordinates that we can use natural x- and y-coordinates
StdDraw.setXscale(-R, +R);
StdDraw.setYscale(-R, +R);
StdAudio.play( MUSIC );
StdDraw.enableDoubleBuffering();
// Run simulation
runSimulation();
}
}