From b81a635a1178247f75b71fcf71c107766197894c Mon Sep 17 00:00:00 2001
From: "armindamon.riess" <armindamon.riess@uzh.ch>
Date: Wed, 30 Nov 2022 10:26:57 +0100
Subject: [PATCH] correct force calculation, implement OpenMP

---
 lib/nBodySim.cpp | 42 +++++++++++++++++++++++++++---------------
 lib/nBodySim.hpp |  6 ++++--
 2 files changed, 31 insertions(+), 17 deletions(-)

diff --git a/lib/nBodySim.cpp b/lib/nBodySim.cpp
index 89e1c0e..b681ddb 100644
--- a/lib/nBodySim.cpp
+++ b/lib/nBodySim.cpp
@@ -1,4 +1,6 @@
 #include "nBodySim.hpp"
+#include <omp.h>
+#include <cmath>
 #include <string>
 #include <fstream>
 #include <iomanip>
@@ -17,14 +19,14 @@ nBodySim::nBodySim(std::string& datafile) {
     positions_ = new double[3*N_];
     for (unsigned i=0; i < 3; ++i) {
         for (unsigned j=0; j < N_; ++j) {
-            file >> positions_[i*N_+j];
+            file >> positions_[i+3*j];
         }
     }
     
     velocities_ = new double[3*N_];
     for (unsigned i=0; i < 3; ++i) {
         for (unsigned j=0; j < N_; ++j) {
-            file >> velocities_[i*N_+j];
+            file >> velocities_[i+3*j];
         }
     }
 
@@ -39,10 +41,8 @@ nBodySim::nBodySim(std::string& datafile) {
     }
 
     forces_ = new double[3*N_];
-    for (unsigned i=0; i < 3; ++i) {
-        for (unsigned j=0; j < N_; ++j) {
-            file >> forces_[i*N_+j];
-        }
+    for (unsigned i=0; i < 3*N_; ++i) {
+        forces_[i] = 0.0;
     }
 }
 
@@ -56,29 +56,41 @@ nBodySim::~nBodySim() {
 }
 
 void nBodySim::calculateForces() {
+    #pragma omp parallel for
+    for (unsigned i=0; i < 3*N_; ++i) {
+        forces_[i] = 0.0;
+    }
     // loop over each pair of particles and calculate the force between them
+    #pragma omp parallel for collapse(2)
     for (unsigned i = 0; i < N_; i++) {
         for (unsigned j = 0; j < N_; j++) {
             if (i == j) continue;
             // calculate distance between particles
-            double dx = positions_[j]   - positions_[i];
-            double dy = positions_[j+1] - positions_[i+1];
-            double dz = positions_[j+2] - positions_[i+2];
+            double dx = positions_[3*j]   - positions_[3*i];
+            double dy = positions_[3*j+1] - positions_[3*i+1];
+            double dz = positions_[3*j+2] - positions_[3*i+2];
             double r2 = dx*dx + dy*dy + dz*dz;
+            double r = std::sqrt(r2);
+            dx /= r;
+            dy /= r;
+            dz /= r;
             // calculate force
-            forces_[i]   += masses_[j] * dx / (r2 + softening_[i]);
-            forces_[i+1] += masses_[j] * dy / (r2 + softening_[i]);
-            forces_[i+2] += masses_[j] * dz / (r2 + softening_[i]);
+            double mi = masses_[i];
+            double mj = masses_[j];
+            double s = softening_[i];
+            forces_[3*i]   += mi*mj * dx / (r2 + s*s);
+            forces_[3*i+1] += mi*mj * dy / (r2 + s*s);
+            forces_[3*i+2] += mi*mj * dz / (r2 + s*s);
         }
     }
 }
 
-void nBodySim::write2file(const double* array, std::string filename, unsigned N, unsigned dim) {
+void nBodySim::write2file(const double* array, std::string filename, unsigned dim) const {
     // writes array to file, with N rows and dim columns
     std::ofstream file(filename);
-    for (unsigned i = 0; i < N; i++) {
+    for (unsigned i = 0; i < N_; i++) {
         for (unsigned j = 0; j < dim; j++) {
-            file << std::right << std::setw(16) << array[i+j] << " ";
+            file << std::right << std::setw(16) << array[dim*i+j] << " ";
         }
         file << std::endl;
     }
diff --git a/lib/nBodySim.hpp b/lib/nBodySim.hpp
index 97c3d1a..c90d70d 100644
--- a/lib/nBodySim.hpp
+++ b/lib/nBodySim.hpp
@@ -10,9 +10,11 @@ public:
     ~nBodySim();
     // methods
     void calculateForces();
+    double* getMasses() { return masses_; }
+    double* getPositions() { return positions_; }
     double* getForces() { return forces_; }
-    void write2file(const double* array, std::string filename, unsigned N, unsigned dim);
-    unsigned getN() { return N_; }
+    void write2file(const double* array, std::string filename, unsigned dim) const;
+    unsigned getN() const { return N_; }
 private:
     unsigned N_;
     // 3d vectors are stored as a 1d array of length 3*N_ in the format x1, y1, z1, x2, y2, z2, ...
-- 
GitLab