X-Git-Url: https://git.ucc.asn.au/?a=blobdiff_plain;f=course%2Fsemester2%2Fpprog%2Fassignment1%2Fsingle-thread%2Fnbody.c;h=c54661f817a0273e902c864c2fc329e70ff5398e;hb=19e590cc4f7dbc186cad9418bf5a2321bfa3fe1a;hp=1dedde717226e4b539cfb8424858d7cd64528ece;hpb=7a341db1fbf5db94b711135b2a79e852c6fb1bc4;p=matches%2Fhonours.git diff --git a/course/semester2/pprog/assignment1/single-thread/nbody.c b/course/semester2/pprog/assignment1/single-thread/nbody.c index 1dedde71..c54661f8 100644 --- a/course/semester2/pprog/assignment1/single-thread/nbody.c +++ b/course/semester2/pprog/assignment1/single-thread/nbody.c @@ -9,20 +9,31 @@ #include #include #include +#include +#include +#include #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,58 @@ 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 +145,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 +177,63 @@ 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); } + +/** + * @function ExitCondition + * @purpose Helper to check whether the program is supposed to exit + * Does not check for user triggered quit + * Checks for either a timeout, or computation of the required number of steps + */ +bool ExitCondition(void) +{ + return (runstate != RUN || (options.timeout > 0.00 && ((unsigned)(time(NULL) - options.start_time.tv_sec) >= options.timeout)) + || (options.num_steps > 0 && universe.steps > options.num_steps)); +}