Skip to content

Instantly share code, notes, and snippets.

@MarkCLewis
Created January 4, 2017 21:15
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save MarkCLewis/e1bf5fca8394916231cdc0ccbecdefc3 to your computer and use it in GitHub Desktop.
Save MarkCLewis/e1bf5fca8394916231cdc0ccbecdefc3 to your computer and use it in GitHub Desktop.
This file does a simple N-body simulation in C++ and times how long it takes to complete 1000 steps.
#include<iostream>
#include<valarray>
#include<cmath>
#include <chrono>
using namespace std;
struct MVect3 {
double x, y, z;
MVect3() {}
MVect3(double nx, double ny, double nz) {
x = nx;
y = ny;
z = nz;
}
void zero() {
x = 0.0;
y = 0.0;
z = 0.0;
}
};
struct MutableBody {
MVect3 p = {0,0,0}, v = {0,0,0};
double mass;
MutableBody() {}
MutableBody(const MVect3 &np, const MVect3 &nv, double m) {
p = np;
v = nv;
mass = m;
}
};
class NBodyMutableClass {
int numBodies;
double dt;
valarray<MutableBody> bodies;
valarray<MVect3> accel;
void initBodies() {
bodies.resize(numBodies);
accel.resize(numBodies);
bodies[0].p = MVect3(0,0,0);
bodies[0].v = MVect3(0,0,0);
bodies[0].mass = 1.0;
for(int i = 1; i < numBodies; ++i) {
bodies[i].p.x = i;
bodies[i].p.y = 0.0;
bodies[i].p.z = 0.0;
bodies[i].v.x = 0.0;
bodies[i].v.y = sqrt(1.0/i);
bodies[i].v.z = 0.0;
}
}
public:
NBodyMutableClass(int nb, double step) {
numBodies = nb;
dt = step;
initBodies();
}
void forSim(int steps) {
for(int step = 0; step < steps; ++step) {
for(int i = 0; i < numBodies; ++i) {
accel[i].zero();
}
for(int i = 0; i < numBodies; ++i) {
MutableBody & pi = bodies[i];
for(int j = i+1; j < numBodies; ++j) {
MutableBody & pj = bodies[j];
double dx = pi.p.x-pj.p.x;
double dy = pi.p.y-pj.p.y;
double dz = pi.p.z-pj.p.z;
double dist = sqrt(dx*dx+dy*dy+dz*dz);
double magi = pj.mass/(dist*dist*dist);
accel[i].x -= magi*dx;
accel[i].y -= magi*dy;
accel[i].z -= magi*dz;
double magj = pi.mass/(dist*dist*dist);
accel[j].x += magj*dx;
accel[j].y += magj*dy;
accel[j].z += magj*dz;
}
}
for(int i = 0; i < numBodies; ++i) {
MutableBody & p = bodies[i];
p.v.x += accel[i].x*dt;
p.v.y += accel[i].y*dt;
p.v.z += accel[i].z*dt;
p.p.x += p.v.x*dt;
p.p.y += p.v.y*dt;
p.p.z += p.v.z*dt;
}
}
// cout << bodies[500].p.x << "\n";
}
};
int main(int argc, char *argv[]) {
using namespace std::chrono;
NBodyMutableClass sim(1000, 0.01);
high_resolution_clock::time_point t1 = high_resolution_clock::now();
sim.forSim(1000);
high_resolution_clock::time_point t2 = high_resolution_clock::now();
duration<double> time_span = duration_cast<duration<double>>(t2 - t1);
std::cout << "It took me " << time_span.count() << " seconds.\n";
return 0;
}
@ShSohag
Copy link

ShSohag commented Aug 1, 2019

Can you please provide the steps to compile and run the code?I am trying but i couldn't help myself out.

@MarkCLewis
Copy link
Author

That will depend on your system and what C++ compiler you use. If you are on Linux then something like "g++ -Ofast NBodyMutable.cpp" followed by "./a.out" would work well. However, on a Mac or Windows you likely won't have the Gnu Compiler, so you'll have to use whatever compiler is available to you on those platforms. On Mac that generally is clang and you can get it with an XCode install.

@parsaa1234
Copy link

Thanks for sharing the code. Have you tried to visualize it?

@MarkCLewis
Copy link
Author

I haven't bothered to visualize this because it is a rather boring system. I do a lot of visualizations of more interesting simulations. This one is intentionally boring to make sure that there are never close interactions between bodies that would cause problems for this simple integrator.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment