public static void SequentialDraw(Body[] bodies, Graphics g, float planetRadius) { for (int i = 0; i < bodies.Length; i++) { bodies[i].Paint(g, planetRadius); } }
static void Main() { // We simulate some of the planets in our solar system Body[] bodies = new Body[]{ new Body(1.496e11, 0, 0, 2.980e04, 5.974e24,Color.Blue), // Earth new Body(2.279e11, 0, 0, 2.410e04, 6.419e23,Color.Red), // Mars new Body(5.790e10, 0, 0, 4.790e04, 3.302e23, Color.Gray), // Mercury new Body(1.082e11, 0, 0, 3.500e04, 4.869e24, Color.Yellow), // Venus new Body(0, 0, 0, 0, 1.989e30, Color.Orange) // Sun }; // Comment out the section below to generate // some random bodies instead of the solar system. /* int N = 1000; Body[] bodies = NBodySolver.GenerateRandomBodies(N); */ Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); Application.Run(new NBodyForm(new NbodyPanel(800, 800, -2.5e11f, 2.5e11f, -2.5e11f, 2.5e11f, 100000, bodies, true))); // Comment out the line below to run a console based version // of the N-body problem. Remember to change the "Output type" // of the project to "Console application" // NBodyConsole(); }
public NbodyPanel( int width, // width of the panel int height, // height of the panel float xMin, // the smallest visible x-coordinate float xMax, // the largest visible x-coordinate float yMin, // the smallest visible y-coordinate float yMax, // the largest visible y-coordinate float dt, // the time step-size Body[] bodies, // the bodies to be shown bool parallel // should the calculations be done in parallel ) { this.Size = new Size(width, height); this.DoubleBuffered = true; this.BackColor = Color.Black; float xScale = (float)(width / (xMax - xMin)); float yScale = (float)(height / (yMax - yMin)); float xTranslate = (float)Math.Abs(xMin * xScale); float yTranslate = (float)Math.Abs(yMin * yScale); float planetRadius = ((xMax - xMin) / width) * 10; Timer timer = new Timer(); timer.Interval = 1; timer.Tick += delegate(Object sender, EventArgs e) { Bitmap bmpNew = new Bitmap(width, height); Graphics g = Graphics.FromImage(bmpNew); g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias; g.Transform = new System.Drawing.Drawing2D.Matrix(xScale, 0, 0, yScale, xTranslate, yTranslate); if (parallel) { NBodySolver.ParallelCalcForceAndUpdate(bodies, dt); } else { NBodySolver.SequentialCalcForceAndUpdate(bodies, dt); } NBodySolver.SequentialDraw(bodies, g, planetRadius); this.bmp = bmpNew; Refresh(); }; timer.Start(); }
/**************************** * Calculate the effect of * the Body b. This Body won't * be moved until the update * method is called. ****************************/ public void CalcForce(Body b) { double dx = b.x - x; double dy = b.y - y; double r = Math.Sqrt(dx * dx + dy * dy); double F = (G * mass * b.mass) / (r * r + EPS * EPS); xForce += F * dx / r; yForce += F * dy / r; }
/************************ Sequential methods ****************************/ public static void SequentialCalcForceAndUpdate(Body[] bodies, double dt) { for (int i = 0; i < bodies.Length; i++) { bodies[i].Reset(); for (int j = 0; j < bodies.Length; j++) if (i != j) bodies[i].CalcForce(bodies[j]); } for (int i = 0; i < bodies.Length; i++) { bodies[i].Update(dt); } }
/************************ Parallel methods ****************************/ public static void ParallelCalcForceAndUpdate(Body[] bodies, double dt) { Parallel.For(0, bodies.Length, 100, delegate(int i) { bodies[i].Reset(); for (int j = 0; j < bodies.Length; j++) if (i != j) bodies[i].CalcForce(bodies[j]); }); Parallel.For(0, bodies.Length, 100, delegate(int i) { bodies[i].Update(dt); }); }
public static Body[] GenerateRandomBodies(int N) { Random rand = new Random(); Body[] bodies = new Body[N]; // Generate some random bodies: for (int i = 0; i < N - 1; i++) { bodies[i] = new Body(RandomDouble(rand, 2.5E11), RandomDouble(rand, 2.5E11), RandomDouble(rand, 4e4), RandomDouble(rand, 4e4), RandomDouble(rand, 1E25), Color.Green); } // And one in the middle, that is much heavier than the rest bodies[N - 1] = new Body(0, 0, 0, 0, 1.989e30, Color.Orange); return bodies; }