Parallel Programming - Tidied things up
[matches/honours.git] / course / semester2 / pprog / assignment1 / single-thread / nbody.c
index 1dedde7..47820d1 100644 (file)
@@ -9,20 +9,31 @@
 #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) 
 {
@@ -30,28 +41,31 @@ 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) 
 {
@@ -60,7 +74,9 @@ 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) 
 {
@@ -69,32 +85,59 @@ 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;
@@ -103,6 +146,7 @@ void System_Init(System * s, char *fileName)
        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");
 
@@ -134,10 +178,51 @@ void System_Init(System * s, char *fileName)
 }
 
 /**
- * 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);
 }
 

UCC git Repository :: git.ucc.asn.au