Skip to content
Snippets Groups Projects
Commit 4aa9d2bd authored by Armin Damon Riess's avatar Armin Damon Riess
Browse files

corrected leapfrog integration

parent 4fe77ad7
No related branches found
No related tags found
No related merge requests found
...@@ -30,7 +30,6 @@ nBodySim::nBodySim(std::string datafile) { ...@@ -30,7 +30,6 @@ nBodySim::nBodySim(std::string datafile) {
for (unsigned i=0; i < 3; ++i) { for (unsigned i=0; i < 3; ++i) {
for (unsigned j=0; j < nParticles_; ++j) { for (unsigned j=0; j < nParticles_; ++j) {
file >> velocities_[i+3*j]; file >> velocities_[i+3*j];
velocities_[i+3*j] *= 0.0001;
} }
} }
...@@ -44,14 +43,11 @@ nBodySim::nBodySim(std::string datafile) { ...@@ -44,14 +43,11 @@ nBodySim::nBodySim(std::string datafile) {
} }
forces_ = new double[3*nParticles_]; forces_ = new double[3*nParticles_];
#pragma omp parallel for updateForces();
for (unsigned i=0; i < 3*nParticles_; ++i) {
forces_[i] = 0.0;
}
file.close(); file.close();
softening_ = 0.1;// * calculateMeanInterparticleDistance(); softening_ = 0.01;
Vector center{0.0, 0.0, 0.0}; Vector center{0.0, 0.0, 0.0};
tree_ = new Tree(mass_, positions_, forces_, softening_, nParticles_, maxCoord, center); tree_ = new Tree(mass_, positions_, forces_, softening_, nParticles_, maxCoord, center);
...@@ -66,25 +62,31 @@ nBodySim::~nBodySim() { ...@@ -66,25 +62,31 @@ nBodySim::~nBodySim() {
} }
void nBodySim::runSimulation(double dt, unsigned nSteps) { void nBodySim::runSimulation(double dt, unsigned nSteps) {
const unsigned skip = 10;
std::ofstream file("../out/positions.dat"); std::ofstream file("../out/positions.dat");
double avgtime = 0; file << nParticles_ << " " << skip << " " << dt << std::endl;
for (unsigned i=0; i < nSteps; ++i) { for (unsigned i=0; i < nSteps; ++i) {
write2file(positions_, file, 3, skip);
// Integrate with leapfrog
auto start = std::chrono::high_resolution_clock::now(); auto start = std::chrono::high_resolution_clock::now();
treeUpdateForces(); kick(dt/2.0);
drift(dt);
updateForces();
kick(dt/2.0);
auto stop = std::chrono::high_resolution_clock::now(); auto stop = std::chrono::high_resolution_clock::now();
auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(stop - start); auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(stop - start);
avgtime += duration.count();
std::cout << std::right << "Step " << std::setw(5) << i std::cout << std::right << "Step " << std::setw(5) << i
<< ": MFM = " << std::setw(12) << calculateMeanForceMagnitude() << ": MFM = " << std::setw(12) << calculateMeanForceMagnitude()
<< ", DEV = " << std::setw(12) << verifyForces() // << ", DEV = " << std::setw(12) << verifyForces()
<< ", MID = " << std::setw(8) << calculateMeanInterparticleDistance() << ", MCD = " << std::setw(8) << calculateMeanCenterDistance()
<< ", T = " << std::setw(8) << duration.count()/1000.0 << " s" // << ", MID = " << std::setw(8) << calculateMeanCenterDistance()
<< ", E = " << std::setw(12) << calculateTotalEnergy()
<< ", T = " << std::setw(8) << duration.count()/1000.0 << " s"
<< std::endl; << std::endl;
updateForces(); // updateTree();
std::cout << std::right << " correct MFM = " << std::setw(12) << calculateMeanForceMagnitude() << std::endl;
doTimeStep(dt);
updateTree();
} }
file.close(); file.close();
} }
...@@ -139,10 +141,6 @@ void nBodySim::updateForces() { ...@@ -139,10 +141,6 @@ void nBodySim::updateForces() {
} }
void nBodySim::treeUpdateForces() { void nBodySim::treeUpdateForces() {
#pragma omp parallel for
for (unsigned i=0; i < 3*nParticles_; ++i) {
forces_[i] = 0.0;
}
#pragma omp parallel for #pragma omp parallel for
for (unsigned i=0; i < nParticles_; ++i) { for (unsigned i=0; i < nParticles_; ++i) {
tree_->updateForce(i); tree_->updateForce(i);
...@@ -187,6 +185,28 @@ double nBodySim::verifyForces() const { ...@@ -187,6 +185,28 @@ double nBodySim::verifyForces() const {
return avgdev; return avgdev;
} }
void nBodySim::kick(double dt) {
#pragma omp parallel for
for (unsigned i=0; i < nParticles_; ++i) {
for (unsigned j=0; j < 3; ++j) {
velocities_[3*i+j] += forces_[3*i+j] * dt / mass_;
}
}
}
void nBodySim::drift(double dt) {
#pragma omp parallel for
for (unsigned i=0; i < nParticles_; ++i) {
for (unsigned j=0; j < 3; ++j) {
positions_[3*i+j] += velocities_[3*i+j] * dt;
}
}
}
void nBodySim::updateTree() {
tree_->update();
}
double nBodySim::calculateMeanInterparticleDistance() const { double nBodySim::calculateMeanInterparticleDistance() const {
double meanInterparticleDistance = 0.0; double meanInterparticleDistance = 0.0;
// loop over each pair of particles and calculate the distance between them // loop over each pair of particles and calculate the distance between them
...@@ -226,24 +246,52 @@ double nBodySim::calculateMeanForceMagnitude() const { ...@@ -226,24 +246,52 @@ double nBodySim::calculateMeanForceMagnitude() const {
return forceMagnitude; return forceMagnitude;
} }
void nBodySim::doTimeStep(double dt) { double nBodySim::calculateMeanCenterDistance() const {
// update velocities, then positions double avgDist = 0.0;
#pragma omp parallel for #pragma omp parallel for reduction(+:avgDist)
for (unsigned i=0; i < nParticles_; ++i) { for (unsigned i = 0; i < nParticles_; i++) {
for (unsigned j=0; j < 3; ++j) { double x = positions_[3*i];
velocities_[3*i+j] += 0.5 * forces_[3*i+j] * dt / mass_; double y = positions_[3*i+1];
positions_[3*i+j] += velocities_[3*i+j] * dt; double z = positions_[3*i+2];
} double d2 = x*x + y*y + z*z;
double d = std::sqrt(d2);
avgDist += d;
} }
avgDist /= nParticles_;
return avgDist;
} }
void nBodySim::updateTree() { double nBodySim::calculateTotalEnergy() const {
tree_->update(); double totalEnergy = 0.0;
#pragma omp parallel for reduction(+:totalEnergy)
for (unsigned i = 0; i < nParticles_; i++) {
double px = positions_[3*i];
double py = positions_[3*i+1];
double pz = positions_[3*i+2];
double vx = velocities_[3*i];
double vy = velocities_[3*i+1];
double vz = velocities_[3*i+2];
double v2 = vx*vx + vy*vy + vz*vz;
double kineticEnergy = 0.5 * mass_ * v2;
double potentialEnergy = 0.0;
for (unsigned j = 0; j < nParticles_; ++j) {
if (j == i) continue;
// calculate distance between particles
double dx = positions_[3*j] - px;
double dy = positions_[3*j+1] - py;
double dz = positions_[3*j+2] - pz;
double r2 = dx*dx + dy*dy + dz*dz;
double r = std::sqrt(r2);
potentialEnergy -= mass_*mass_ / r;
}
totalEnergy += kineticEnergy + potentialEnergy;
}
return totalEnergy;
} }
void nBodySim::write2file(const double* array, std::ofstream& file, unsigned dim) const { void nBodySim::write2file(const double* array, std::ofstream& file, unsigned dim, unsigned skip) const {
// writes array to file, with N rows and dim columns // writes array to file, with N rows and dim columns
for (unsigned i = 0; i < nParticles_; i++) { for (unsigned i = 0; i < nParticles_; i+=skip) {
for (unsigned j = 0; j < dim; j++) { for (unsigned j = 0; j < dim; j++) {
file << std::right << std::setw(16) << array[dim*i+j] << " "; file << std::right << std::setw(16) << array[dim*i+j] << " ";
} }
......
...@@ -21,18 +21,24 @@ public: ...@@ -21,18 +21,24 @@ public:
// Loops over all pairs of particles and calculates forces, checks if forces are correct // Loops over all pairs of particles and calculates forces, checks if forces are correct
double verifyForces() const; double verifyForces() const;
// Leapfrog: update velocities
void kick(double dt);
// Leapfrog: update positions
void drift(double dt);
// Update tree
void updateTree();
// Loop over all pairs of particles and calculate mean interparticle distance // Loop over all pairs of particles and calculate mean interparticle distance
double calculateMeanInterparticleDistance() const; double calculateMeanInterparticleDistance() const;
// Loop over all force vectors and calculate mean force magnitude // Loop over all force vectors and calculate mean force magnitude
double calculateMeanForceMagnitude() const; double calculateMeanForceMagnitude() const;
// loop over every particle and calculate the mean distance from the center
// Integrate using leapfrog algorithm. doesn't update forces, doesn't update tree double calculateMeanCenterDistance() const;
void doTimeStep(double dt); // Loop over all particles and calculate the total energy
// Update tree double calculateTotalEnergy() const;
void updateTree();
// Writes data to file, every row is a particle // Writes data to file, every row is a particle
void write2file(const double* array, std::ofstream& file, unsigned dim) const; void write2file(const double* array, std::ofstream& file, unsigned dim, unsigned skip) const;
// Write current state of simulation to file // Write current state of simulation to file
void saveState2file(unsigned step, std::ofstream& file) const; void saveState2file(unsigned step, std::ofstream& file) const;
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment