// --- Function forward declarations --- //
void HandleArguments(int argc, char ** argv); //Interprets program arguments and sets up the "options" variable
-unsigned UnsignedArgument(unsigned * i, int argc, char ** argv, unsigned * store, unsigned * store2); //Helper function to get switch value for unsigned
+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 --- //
/**
options.output = NULL;
options.num_threads = 0;
options.nested_threads = 0;
- options.num_steps = 0;
- options.timeout = 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.pedantic_graphics = true;
options.print_positions = false;
options.verbosity = 0;
+ options.theta = 0.50;
+ options.random = 0;
//If there are no arguments, print information about usage
if (argc == 1)
HandleArguments(argc, argv);
//Check there is an initial field.
- if (options.input == NULL)
+ if (options.input == NULL && options.random <= 0)
{
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
+ if (options.input != NULL)
+ System_Init(&universe,options.input); //Initialise the universe from the initial field
+ else
+ System_Random(&universe, options.random); //Randomly create bodies
+
//Setup the time of day at which the simulation starts
if (gettimeofday(&(options.start_time), NULL) != 0)
options.start_clock = clock(); //Get CPU cycles executed before simulation starts
Simulation_Run(argc, argv); // Start the simulation
- //printf("Got here!\n");
- exit(EXIT_FAILURE); //Should never get to this line
+ //printf("Main thread done!\n");
+
+ //pthread_exit(NULL);
+ exit(EXIT_SUCCESS); //Should never get to this line
}
switch (argv[i][1]) //The argument is a switch if we get here
{
case 'n': //Number of threads switch
- UnsignedArgument(&i, argc, argv, &(options.num_threads), &(options.nested_threads));
+ 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", argv[i][1]);
+ 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
- UnsignedArgument(&i, argc, argv, &(options.num_steps), NULL);
+ 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)
- UnsignedArgument(&i, argc, argv, &(options.timeout), NULL);
+ 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 'r': //Random initial field
+ IntegerArgument(&i, argc, argv, &(options.random), NULL);
+ if (options.random < 0)
+ {
+ fprintf(stderr, "Require a positive integer number of bodies (-%c %s is invalid).", 'r', argv[i]);
+ exit(EXIT_FAILURE);
+ }
break;
case 'g': //Graphics switch
options.draw_graphics = !options.draw_graphics;
break;
case 'v': //Verbosity switch
- UnsignedArgument(&i, argc, argv, &(options.verbosity), NULL);
+ IntegerArgument(&i, argc, argv, &(options.verbosity), NULL);
break;
case '-':
- if (strcmp(argv[i]+1, "pedantic-graphics"))
+ 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]+1, "fast-graphics"))
+ 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]);
+ fprintf(stderr, "Unrecognised switch %s\n", argv[i]);
exit(EXIT_FAILURE);
}
break;
}
/**
- * @function UnsignedArgument
- * @purpose Helper function to get an unsigned integer following a argument switch
+ * @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 unsigned
+ * @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 UnsignedArgument(unsigned * i, int argc, char ** argv, unsigned * store, unsigned * store2)
+unsigned IntegerArgument(unsigned * i, int argc, char ** argv, int * store, int * store2)
{
if (*i >= argc-1)
{
}
int val = atoi(argv[*i+1]);
- if (val <= 0)
+ 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 = (unsigned)val;
+ *store = val;
*i += 1;
return (seperator == NULL) ? 1 : 2;
QuitProgram(false);
}
+