#include <math.h>
#include <time.h>
#include <string.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <unistd.h>
#include "nbody.h"
+RUNSTATE runstate = RUN;
+
/**
- * Prints the body on screen
+ * @function Body_Print
+ * @purpose Print the body to a file (or stdout)
+ * @param a - Body to print'
+ * @param out - FILE* to print to
*/
-void Body_Print(Body * a)
+void Body_Print(Body * a, FILE * out)
{
- printf("Body %p M=%f X=%f Y=%f Z=%f Fx=%f Fy=%f Fz=%f Vx=%f Vy=%f Vz=%f\n",
+ fprintf(out,"Body %p M=%f X=%f Y=%f Z=%f Fx=%f Fy=%f Fz=%f Vx=%f Vy=%f Vz=%f\n",
(void*)a, a->mass, a->x[0], a->x[1], a->x[2], a->F[0], a->F[1], a->F[2], a->v[0], a->v[1], a->v[2]);
}
/**
- * Computing forces
+ * @function Body_Force
+ * @purpose Calculates the force on a single Body due to all bodies in a System
+ * @param a - The Body
+ * @param b - The System
*/
void Body_Force(Body * a, System * s)
{
double con;
double gd;
- for (unsigned i = 0; i < DIMENSIONS; ++i)
+ for (unsigned i = 0; i < DIMENSIONS; ++i) //Set Force to zero
a->F[i] = 0;
- for (unsigned index = 0; index < s->N; ++index)
+ for (unsigned index = 0; index < s->N; ++index) // Step through all bodies in the System
{
- Body * b = s->body+index;
+ Body * b = s->body+index; //Current body
if (b == a)
- continue;
+ continue; //Otherwise we would have infinite force
+ //Calculate distance between a and b
distance = 0.0;
for (unsigned i = 0; i < DIMENSIONS; ++i)
distance += square(b->x[i] - a->x[i]);
distance = sqrt(distance);
con = G * a->mass * b->mass / square(distance);
- gd = con / distance;
- for (unsigned i = 0; i < DIMENSIONS; ++i)
+ gd = con / distance;
+ for (unsigned i = 0; i < DIMENSIONS; ++i) //Add force from b to a's net force
a->F[i] += gd * (b->x[i] - a->x[i]);
}
}
/**
- * Compute velocities
+ * @function Body_Velocity
+ * @purpose Compute velocity of a body
+ * @param a - The Body
*/
void Body_Velocity(Body * a)
{
}
/**
- * Compute positions
+ * @function Body_Position
+ * @purpose Compute position of a body
+ * @param a - The Body
*/
void Body_Position(Body * a)
{
}
/**
- * Main compute function
+ * @function System_Compute
+ * @purpose Compute forces and then positions for bodies in System
+ * NOTE: Only used in the single threaded version of the program
*/
-void System_Compute(System * s)
+void System_Compute(System * s)
{
-// clock_t start, finish;
-
-// start = clock();
+ System_Forces(s, s);
+ System_Positions(s);
+}
- for (unsigned i = 0; i < s->N; ++i)
+/**
+ * @function System_Forces
+ * @purpose Compute forces on each object in System s1 due to all bodies in System s2
+ * @param s1, s2 - The two systems
+ * NOTE: In single threaded version, called with s1 == s2 == &universe
+ * In multi threaded version, called with s2 == &universe, but s1 is constructed for each thread
+ */
+void System_Forces(System * s1, System * s2)
+{
+ //printf("Compute forces for %p - %d bodies...\n", (void*)s1, s1->N);
+ for (unsigned i = 0; i < s1->N; ++i)
{
- Body_Force(s->body+i, s);
- Body_Velocity(s->body+i);
- Body_Position(s->body+i);
+ Body_Force(s1->body+i, s2);
+ Body_Velocity(s1->body+i);
}
+ //printf("Compute positions for %p - Done!\n", (void*)s1);
+}
+/**
+ * @function System_Positions
+ * @purpose Compute positions of all objects in System
+ * @param s - The system
+ */
+void System_Positions(System * s)
+{
+ //printf("Compute positions for %p - %d bodies...\n", (void*)s, s->N);
+ for (unsigned i = 0; i < s->N; ++i)
+ Body_Position(s->body+i);
+ //printf("Compute positions for %p - Done!\n", (void*)s);
+ s->steps += 1;
}
-/*
- * This function reads an input file. You can change it if you choose a
- * different file format
+/**
+ * @function System_Init
+ * @purpose Initialise a System from an input file
+ * @param s - The System
+ * @param fileName - The input file
*/
#define LINE_SIZE BUFSIZ
-void System_Init(System * s, char *fileName)
+void System_Init(System * s, const char *fileName)
{
char line[LINE_SIZE];
char * token;
file = fopen(fileName, "rt");
s->N = atoi(fgets(line, LINE_SIZE, file));
s->body = (Body*) calloc((size_t)s->N, sizeof(Body));
+ s->steps = 0;
//printf("----------------------Initial field-------------------------------\n");
}
/**
- * Cleans up the universe by freeing all memory
+ * @function Universe_Cleanup
+ * @purpose Cleans up the universe by freeing all memory
+ * Also prints the bodies in the universe to a file specified in "options" if required.
*/
void Universe_Cleanup()
{
- free(universe.body);
+ if (options.output != NULL) // An output file was specified...
+ {
+ FILE * save = fopen(options.output, "w");
+ if (save == NULL)
+ perror("Couldn't save universe to file.");
+ else
+ {
+ fprintf(save, "# Final field:\n");
+ for (unsigned i = 0; i < universe.N; ++i) // Print all bodies to the file
+ {
+ Body_Print(universe.body+i, save);
+ }
+ fclose(save);
+ }
+
+ }
+ free(universe.body); // Cleanup memory used for bodies
+
+}
+
+/**
+ * @function DisplayStatistics
+ * @purpose Display useful information about the computations done,
+ * - Total number of steps computed
+ * - Time in seconds elapsed
+ * - Clock cycles executed
+ * - Equivelant time for a single thread to execute same number of clock cycles
+ */
+void DisplayStatistics()
+{
+ clock_t end = clock();
+ struct timeval end_time;
+ if (gettimeofday(&end_time, NULL) != 0)
+ {
+ perror("Couldn't get time of day.\n");
+ return;
+ }
+ float runtime = (float)(end_time.tv_sec-options.start_time.tv_sec) + (float)(end_time.tv_usec-options.start_time.tv_usec) / 1.0e6;
+ float clock_time = (float)(end - options.start_clock) / (float)(CLOCKS_PER_SEC);
+ printf("%u\t%f\t%u\t%f\n", universe.steps, runtime, (unsigned)(end - options.start_clock), clock_time);
}