Task: N-body problem



C#: using System;
using System.IO;

namespace NBodyProblem {
    class Vector3D {
        public Vector3D(double x, double y, double z) {
            X = x;
            Y = y;
            Z = z;
        }

        public double X { get; }
        public double Y { get; }
        public double Z { get; }

        public double Mod() {
            return Math.Sqrt(X * X + Y * Y + Z * Z);
        }

        public static Vector3D operator +(Vector3D lhs, Vector3D rhs) {
            return new Vector3D(lhs.X + rhs.X, lhs.Y + rhs.Y, lhs.Z + rhs.Z);
        }

        public static Vector3D operator -(Vector3D lhs, Vector3D rhs) {
            return new Vector3D(lhs.X - rhs.X, lhs.Y - rhs.Y, lhs.Z - rhs.Z);
        }

        public static Vector3D operator *(Vector3D lhs, double rhs) {
            return new Vector3D(lhs.X * rhs, lhs.Y * rhs, lhs.Z * rhs);
        }
    }

    class NBody {
        private readonly double gc;
        private readonly int bodies;
        private readonly int timeSteps;
        private readonly double[] masses;
        private readonly Vector3D[] positions;
        private readonly Vector3D[] velocities;
        private readonly Vector3D[] accelerations;

        public NBody(string fileName) {
            string[] lines = File.ReadAllLines(fileName);

            string[] gbt = lines[0].Split();
            gc = double.Parse(gbt[0]);
            bodies = int.Parse(gbt[1]);
            timeSteps = int.Parse(gbt[2]);

            masses = new double[bodies];
            positions = new Vector3D[bodies];
            velocities = new Vector3D[bodies];
            accelerations = new Vector3D[bodies];
            for (int i = 0; i < bodies; ++i) {
                masses[i] = double.Parse(lines[i * 3 + 1]);
                positions[i] = Decompose(lines[i * 3 + 2]);
                velocities[i] = Decompose(lines[i * 3 + 3]);
            }

            Console.WriteLine("Contents of {0}", fileName);
            foreach (string line in lines) {
                Console.WriteLine(line);
            }
            Console.WriteLine();
            Console.Write("Body   :      x          y          z    |");
            Console.WriteLine("     vx         vy         vz");
        }

        public int GetTimeSteps() {
            return timeSteps;
        }

        private Vector3D Decompose(string line) {
            string[] xyz = line.Split();
            double x = double.Parse(xyz[0]);
            double y = double.Parse(xyz[1]);
            double z = double.Parse(xyz[2]);
            return new Vector3D(x, y, z);
        }

        private void ComputeAccelerations() {
            for (int i = 0; i < bodies; ++i) {
                accelerations[i] = new Vector3D(0, 0, 0);
                for (int j = 0; j < bodies; ++j) {
                    if (i != j) {
                        double temp = gc * masses[j] / Math.Pow((positions[i] - positions[j]).Mod(), 3);
                        accelerations[i] = accelerations[i] + (positions[j] - positions[i]) * temp;
                    }
                }
            }
        }

        private void ComputeVelocities() {
            for (int i = 0; i < bodies; ++i) {
                velocities[i] = velocities[i] + accelerations[i];
            }
        }

        private void ComputePositions() {
            for (int i = 0; i < bodies; ++i) {
                positions[i] = positions[i] + velocities[i] + accelerations[i] * 0.5;
            }
        }

        private void ResolveCollisions() {
            for (int i = 0; i < bodies; ++i) {
                for (int j = i + 1; j < bodies; ++j) {
                    if (positions[i].X == positions[j].X
                     && positions[i].Y == positions[j].Y
                     && positions[i].Z == positions[j].Z) {
                        Vector3D temp = velocities[i];
                        velocities[i] = velocities[j];
                        velocities[j] = temp;
                    }
                }
            }
        }

        public void Simulate() {
            ComputeAccelerations();
            ComputePositions();
            ComputeVelocities();
            ResolveCollisions();
        }

        public void PrintResults() {
            for (int i = 0; i < bodies; ++i) {
                Console.WriteLine(
                    "Body {0} : {1,9:F6}  {2,9:F6}  {3,9:F6} | {4,9:F6}  {5,9:F6}  {6,9:F6}",
                    i + 1,
                    positions[i].X, positions[i].Y, positions[i].Z,
                    velocities[i].X, velocities[i].Y, velocities[i].Z
                );
            }
        }
    }

    class Program {
        static void Main(string[] args) {
            NBody nb = new NBody("nbody.txt");

            for (int i = 0; i < nb.GetTimeSteps(); ++i) {
                Console.WriteLine();
                Console.WriteLine("Cycle {0}", i + 1);
                nb.Simulate();
                nb.PrintResults();
            }
        }
    }
}





Python: import math

class Vector:
    def __init__(self, x, y, z):
        self.x = x
        self.y = y
        self.z = z

    def __add__(self, other):
        return Vector(self.x + other.x, self.y + other.y, self.z + other.z)

    def __sub__(self, other):
        return Vector(self.x - other.x, self.y - other.y, self.z - other.z)

    def __mul__(self, other):
        return Vector(self.x * other, self.y * other, self.z * other)

    def __div__(self, other):
        return Vector(self.x / other, self.y / other, self.z / other)

    def __eq__(self, other):
        if isinstance(other, Vector):
            return self.x == other.x and self.y == other.y and self.z == other.z
        return False

    def __ne__(self, other):
        return not self.__eq__(other)

    def __str__(self):
        return '({x}, {y}, {z})'.format(x=self.x, y=self.y, z=self.z)

    def abs(self):
        return math.sqrt(self.x*self.x + self.y*self.y + self.z*self.z)

origin = Vector(0, 0, 0)

class NBody:
    def __init__(self, fileName):
        with open(fileName, "r") as fh:
            lines = fh.readlines()
            gbt = lines[0].split()
            self.gc = float(gbt[0])
            self.bodies = int(gbt[1])
            self.timeSteps = int(gbt[2])
            self.masses = [0.0 for i in range(self.bodies)]
            self.positions = [origin for i in range(self.bodies)]
            self.velocities = [origin for i in range(self.bodies)]
            self.accelerations = [origin for i in range(self.bodies)]
            for i in range(self.bodies):
                self.masses[i] = float(lines[i*3 + 1])
                self.positions[i] = self.__decompose(lines[i*3 + 2])
                self.velocities[i] = self.__decompose(lines[i*3 + 3])

            print "Contents of", fileName
            for line in lines:
                print line.rstrip()
            print
            print "Body   :      x          y          z    |",
            print "     vx         vy         vz"

    def __decompose(self, line):
        xyz = line.split()
        x = float(xyz[0])
        y = float(xyz[1])
        z = float(xyz[2])
        return Vector(x, y, z)

    def __computeAccelerations(self):
        for i in xrange(self.bodies):
            self.accelerations[i] = origin
            for j in xrange(self.bodies):
                if i != j:
                    temp = self.gc * self.masses[j] / math.pow((self.positions[i] - self.positions[j]).abs(), 3)
                    self.accelerations[i] += (self.positions[j] - self.positions[i]) * temp
        return None

    def __computePositions(self):
        for i in xrange(self.bodies):
            self.positions[i] += self.velocities[i] + self.accelerations[i] * 0.5
        return None

    def __computeVelocities(self):
        for i in xrange(self.bodies):
            self.velocities[i] += self.accelerations[i]
        return None

    def __resolveCollisions(self):
        for i in xrange(self.bodies):
            for j in xrange(self.bodies):
                if self.positions[i] == self.positions[j]:
                    (self.velocities[i], self.velocities[j]) = (self.velocities[j], self.velocities[i])
        return None

    def simulate(self):
        self.__computeAccelerations()
        self.__computePositions()
        self.__computeVelocities()
        self.__resolveCollisions()
        return None

    def printResults(self):
        fmt = "Body %d : % 8.6f  % 8.6f  % 8.6f | % 8.6f  % 8.6f  % 8.6f"
        for i in xrange(self.bodies):
            print fmt % (i+1, self.positions[i].x, self.positions[i].y, self.positions[i].z, self.velocities[i].x, self.velocities[i].y, self.velocities[i].z)
        return None

nb = NBody("nbody.txt")
for i in xrange(nb.timeSteps):
    print "\nCycle %d" % (i + 1)
    nb.simulate()
    nb.printResults()