Parallel Programming - Final version
[matches/honours.git] / course / semester2 / pprog / assignment1 / nbody-bh / main.c~
diff --git a/course/semester2/pprog/assignment1/nbody-bh/main.c~ b/course/semester2/pprog/assignment1/nbody-bh/main.c~
new file mode 100644 (file)
index 0000000..e9bb3ac
--- /dev/null
@@ -0,0 +1,296 @@
+/**
+ * @file main.c
+ * @author Sam Moore (20503628) - 2012
+ * @purpose Contains main function, argument handling
+ * NOTE: This file is identical for both the single-threaded and multi-threaded versions of the program
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <time.h>
+#include <signal.h>
+#include <string.h> // For parsing arguments
+
+#include "nbody.h"
+#include "graphics.h"
+
+// --- Variable definitions --- //
+System universe; // global variable declared in "nbody.h" - The universe of bodies
+Options options; // global variable declared in "nbody.h" - Options passed to program through arguments
+
+
+// --- Function forward declarations --- //
+void HandleArguments(int argc, char ** argv); //Interprets program arguments and sets up the "options" variable
+unsigned IntegerArgument(unsigned * i, int argc, char ** argv, int * store, int * store2); //Helper function to get integer switch
+void FloatArgument(unsigned * i, int argc, char ** argv, float * store); //Helper function to get switch value for float
+void DisplayStatistics(); //Called on exit of program, displays information about computation time, steps computed, etc
+void Interrupt(int dummy); // Interrupt handler function, called when SIGINT (Ctrl-C) is sent to program
+
+
+// --- Function implementations --- //
+
+/**
+ * @function main
+ * @purpose The main function. Calls HandleArguments to set up options, 
+ *             sets up functions to call at exit, starts simulation and graphics loops
+ * @param argc - Number of arguments
+ * @param argv - The argument strings
+ */
+int main(int argc, char** argv)
+{
+       //Set default options values here
+       options.program = argv[0];
+       options.input = NULL;
+       options.output = NULL;
+       options.num_threads = 0;
+       options.nested_threads = 0;
+       options.num_steps = -1; // Negative values => simulation runs forever unless otherwise specified
+       options.timeout = -1;
+       options.draw_graphics = true;
+       options.pedantic_graphics = false;
+       options.print_positions = false;
+       options.verbosity = 0;
+       options.theta = 0.50;
+
+       //If there are no arguments, print information about usage
+       if (argc == 1)
+       {
+               printf("Usage: %s [OPTIONS] field\n", argv[0]);
+               printf("Controls:\n X - exit\n I, J, K, M - rotate\n W, Z, A, S - move to view"
+                       " point\n ./, - zoom in/out\n +/- - scaled zoom in/out\n");
+               exit(EXIT_SUCCESS);
+       }
+
+       //Parse the arguments
+       HandleArguments(argc, argv);
+       
+       //Check there is an initial field.
+       if (options.input == NULL)
+       {
+               fprintf(stderr, "Usage: %s [OPTIONS] field\n", argv[0]);
+               fprintf(stderr, " (You did not provide a file for the initial field of bodies)\n");
+               exit(EXIT_FAILURE);
+       }
+
+
+
+       signal(SIGINT, Interrupt); //Handle SIGINT signals
+       atexit(Universe_Cleanup); //On exit, cleanup universe (and write positions of bodies to file if supplied).
+       atexit(DisplayStatistics); //On exit, print information about the computations done
+       System_Init(&universe,options.input); //Initialise the universe from the initial field
+       
+       //Setup the time of day at which the simulation starts
+       if (gettimeofday(&(options.start_time), NULL) != 0)
+       {
+               perror("Couldn't get time of day");
+               exit(EXIT_FAILURE);
+       }
+       
+       options.start_clock = clock(); //Get CPU cycles executed before simulation starts
+       Simulation_Run(argc, argv); // Start the simulation
+       
+       //printf("Main thread done!\n");
+       
+       //pthread_exit(NULL);
+       exit(EXIT_SUCCESS); //Should never get to this line
+}
+
+
+/**
+ * @function HandleArguments
+ * @purpose Fill the "options" variable by parsing command line arguments
+ * @param argc - Number of arguments
+ * @param argv - Argument strings
+ */
+void HandleArguments(int argc, char ** argv)
+{
+       for (unsigned i = 1; i < argc; ++i) //For all arguments
+       {
+               if (argv[i][0] != '-') //If the argument is not a switch value...
+               {
+                       //Interpret first non switch as input file, and second as output file.
+                       //If there are too many non switch arguments, give an error.
+                       if (options.input == NULL) 
+                               options.input = argv[i];
+                       else if (options.output == NULL)
+                               options.output = argv[i];
+                       else
+                       {
+                               fprintf(stderr,"Usage: %s [OPTIONS] field [output]\n", argv[0]);
+                               fprintf(stderr," (You provided too many file names)\n");
+                               exit(EXIT_FAILURE);
+                       }
+                       continue;
+               }
+               switch (argv[i][1]) //The argument is a switch if we get here
+               {
+                       case 'n': //Number of threads switch
+                               IntegerArgument(&i, argc, argv, &(options.num_threads), &(options.nested_threads));
+                               #ifdef SINGLE_THREADED
+                               fprintf(stderr, "Warning: -%c switch has no effect in the single-threaded program.\n", 'n');
+                               
+                               #else
+                               if (options.num_threads <= 0)
+                               {
+                                       fprintf(stderr, "Require at least one thread (-%c %s is invalid).\n",'n', argv[i]);
+                                       exit(EXIT_FAILURE);
+                               }
+                               #endif //SINGLE_THREADED
+                               break;
+                       case 's': //Number of steps switch
+                               IntegerArgument(&i, argc, argv, &(options.num_steps), NULL);
+                               if (options.num_steps < 0)
+                               {
+                                       fprintf(stderr, "Require zero or more steps to run (-%c %s is invalid).\n", 's', argv[i]);
+                                       exit(EXIT_FAILURE);
+                               }
+                               break;
+                       case 't': //Timeout switch (in seconds)
+                               IntegerArgument(&i, argc, argv, &(options.timeout), NULL);
+                               if (options.timeout < 0)
+                               {
+                                       fprintf(stderr, "Require a timeout greater or equal to zero (-%c %s is invalid).", 't', argv[i]);
+                                       exit(EXIT_FAILURE);
+                               }                               
+                               break;
+                       case 'g': //Graphics switch
+                               options.draw_graphics = !options.draw_graphics;
+                               break;
+                       case 'v': //Verbosity switch
+                               IntegerArgument(&i, argc, argv, &(options.verbosity), NULL);
+                               break;
+
+                       case '-':
+                               if (strcmp(argv[i]+2, "pedantic-graphics") == 0)
+                               {
+                                       options.pedantic_graphics = true;
+                                       #ifdef SINGLE_THREADED
+                                       fprintf(stderr, "Warning: %s switch has no effect in the single threaded program.\n", argv[i]);
+                                       #endif //SINGLE_THREADED
+                               }
+                               else if (strcmp(argv[i]+2, "fast-graphics") == 0)
+                               {
+                                       options.pedantic_graphics = false;
+                                       #ifdef SINGLE_THREADED
+                                       fprintf(stderr, "Warning: %s switch has no effect in the single threaded program.\n", argv[i]);
+                                       #endif //SINGLE_THREADED
+
+                               }
+                               else if (strcmp(argv[i]+2, "theta") == 0)
+                               {
+                                       FloatArgument(&i, argc, argv, &(options.theta));
+                                       #ifndef BARNES_HUT
+                                       fprintf(stderr, "Warning: %s switch only works in Barnes Hut version.\n", argv[i-1]);
+                                       #else
+                                       if (options.theta < 0)
+                                       {
+                                               fprintf(stderr, "Require a theta value greater or equal to zero (%s %s is invalid).\n", argv[i-1], argv[i]);
+                                               exit(EXIT_FAILURE);
+                                       }
+                                       
+                                       #endif //BARNS_HUT
+                                       
+                               }
+                               else
+                               {
+                                       fprintf(stderr, "Unrecognised switch %s\n", argv[i]);
+                                       exit(EXIT_FAILURE);
+                               }
+                               break;
+
+
+                       default:
+                               fprintf(stderr, "Unrecognised switch -%c\n", argv[i][1]);
+                               exit(EXIT_FAILURE);
+                               break;
+               }
+               
+       }
+}
+
+/**
+ * @function IntegerArgument
+ * @purpose Helper function to get up to two integers following a argument switch, seperated by ':'
+ * @param i - position in the argument array, will be updated after this function
+ * @param argc - number of arguments
+ * @param argv - argument strings
+ * @param store - pointer to unsigned to store result in
+ * @param store2 - pointer to second integer (set to NULL if there is only one integer)
+ * @returns 1 if store was filled, 2 if both store1 and store2 were filled
+ */
+unsigned IntegerArgument(unsigned * i, int argc, char ** argv, int * store, int * store2)
+{
+       if (*i >= argc-1)
+       {
+               fprintf(stderr,"Supply a positive integer for the -%c switch.\n", argv[*i][1]);
+               exit(EXIT_FAILURE);
+       }
+
+       char * seperator = strstr(argv[*i+1], ":");
+       if (seperator != NULL)
+       {
+               if (store2 == NULL)
+               {
+                       fprintf(stderr,"Supply a positive integer for the -%c switch.\n", argv[*i][1]);
+                       exit(EXIT_FAILURE);     
+               }
+               int val = atoi(seperator+1);
+               if (val <= 0)
+               {
+                       fprintf(stderr,"Supply a positive integer for the -%c switch.\n", argv[*i][1]);
+                       exit(EXIT_FAILURE);     
+               }       
+               *store2 = (unsigned)val;
+
+               *seperator = '\0';
+       }
+       
+       int val = atoi(argv[*i+1]);
+       if (val <= 0 && strcmp("0", argv[*i+1]) != 0)
+       {
+               fprintf(stderr,"Supply a positive integer for the -%c switch. %s is invalid.\n", argv[*i][1], argv[*i+1]);
+               exit(EXIT_FAILURE);
+       }
+       *store = val;
+       *i += 1;
+
+       return (seperator == NULL) ? 1 : 2;
+}
+/**
+ * @function FloatArgument
+ * @purpose Helper function to get a float following a argument switch
+ * @param i - position in the argument array, will be updated after this function
+ * @param argc - number of arguments
+ * @param argv - argument strings
+ * @param store - pointer to float to store result in
+ */
+void FloatArgument(unsigned * i, int argc, char ** argv, float * store)
+{
+       if (*i >= argc-1)
+       {
+               fprintf(stderr,"Supply a float for the -%c switch.\n", argv[*i][1]);
+               exit(EXIT_FAILURE);
+       }
+       *store = atof(argv[*i+1]);
+       if (*store == 0.0 && argv[*i+1][0] != '0')
+       {
+               fprintf(stderr,"Supply a float for the -%c switch.\n", argv[*i][1]);
+               exit(EXIT_FAILURE);
+       }
+       *i += 1;
+}
+
+
+
+/**
+ * @function Interrupt
+ * @purpose Handle SIGINT signal; quit the program gracefully, so that statistics are still displayed
+ * @param dummy - a dummy
+ */
+
+void Interrupt(int dummy)
+{
+       QuitProgram(false);
+}
+
+

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