3 * @author Sam Moore (20503628) 2012
4 * @purpose N-Body simulator - Definition of simulation functions; single threaded version
18 RUNSTATE runstate = RUN;
21 * @function Body_Print
22 * @purpose Print the body to a file (or stdout)
23 * @param a - Body to print'
24 * @param out - FILE* to print to
26 void Body_Print(Body * a, FILE * out)
28 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",
29 (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]);
33 * @function Body_Force
34 * @purpose Calculates the force on a single Body due to all bodies in a System
36 * @param b - The System
38 void Body_Force(Body * a, System * s)
44 for (unsigned i = 0; i < DIMENSIONS; ++i) //Set Force to zero
47 for (unsigned index = 0; index < s->N; ++index) // Step through all bodies in the System
49 Body * b = s->body+index; //Current body
51 continue; //Otherwise we would have infinite force
53 //Calculate distance between a and b
55 for (unsigned i = 0; i < DIMENSIONS; ++i)
56 distance += square(b->x[i] - a->x[i]);
57 distance = sqrt(distance);
58 con = G * a->mass * b->mass / square(distance);
60 for (unsigned i = 0; i < DIMENSIONS; ++i) //Add force from b to a's net force
61 a->F[i] += gd * (b->x[i] - a->x[i]);
66 * @function Body_Velocity
67 * @purpose Compute velocity of a body
70 void Body_Velocity(Body * a)
72 for (unsigned i = 0; i < DIMENSIONS; ++i)
73 a->v[i] += a->F[i] / a->mass * DELTA_T;
77 * @function Body_Position
78 * @purpose Compute position of a body
81 void Body_Position(Body * a)
83 for (unsigned i = 0; i < DIMENSIONS; ++i)
84 a->x[i] += a->v[i] * DELTA_T;
88 * @function System_Compute
89 * @purpose Compute forces and then positions for bodies in System
90 * NOTE: Only used in the single threaded version of the program
92 void System_Compute(System * s)
99 * @function System_Forces
100 * @purpose Compute forces on each object in System s1 due to all bodies in System s2
101 * @param s1, s2 - The two systems
102 * NOTE: In single threaded version, called with s1 == s2 == &universe
103 * In multi threaded version, called with s2 == &universe, but s1 is constructed for each thread
104 * In nested multi-threaded version, s2 is constructed for the nested threads as well
106 void System_Forces(System * s1, System * s2)
108 //printf("Compute forces for %p - %d bodies...\n", (void*)s1, s1->N);
109 for (unsigned i = 0; i < s1->N; ++i)
111 Body_Force(s1->body+i, s2);
112 Body_Velocity(s1->body+i);
114 //printf("Compute positions for %p - Done!\n", (void*)s1);
118 * @function System_Positions
119 * @purpose Compute positions of all objects in System
120 * @param s - The system
122 void System_Positions(System * s)
124 //printf("Compute positions for %p - %d bodies...\n", (void*)s, s->N);
125 for (unsigned i = 0; i < s->N; ++i)
126 Body_Position(s->body+i);
127 //printf("Compute positions for %p - Done!\n", (void*)s);
135 * @function System_Init
136 * @purpose Initialise a System from an input file
137 * @param s - The System
138 * @param fileName - The input file
140 void System_Init(System * s, const char *fileName)
142 char line[LINE_SIZE];
146 file = fopen(fileName, "rt");
147 s->N = atoi(fgets(line, LINE_SIZE, file));
148 s->body = (Body*) calloc((size_t)s->N, sizeof(Body));
151 //printf("----------------------Initial field-------------------------------\n");
153 for (unsigned i = 0; i < s->N; ++i)
155 if (fgets(line, LINE_SIZE, file) != NULL)
157 Body * a = s->body+i;
158 token = strtok(line, ",; ");
159 a->mass = atof(token);
161 for (unsigned j = 0; j < DIMENSIONS; ++j)
163 token = strtok(NULL, ",; ");
164 a->x[j] = atof(token);
166 for (unsigned j = 0; j < DIMENSIONS; ++j)
168 token = strtok(NULL, ",; ");
169 a->v[j] = atof(token);
175 //printf("--------------------------------------------------------------\n");
181 * @function Universe_Cleanup
182 * @purpose Cleans up the universe by freeing all memory
183 * Also prints the bodies in the universe to a file specified in "options" if required.
185 void Universe_Cleanup()
187 if (options.output != NULL) // An output file was specified...
189 FILE * save = fopen(options.output, "w");
191 perror("Couldn't save universe to file.");
194 fprintf(save, "# Final field:\n");
195 for (unsigned i = 0; i < universe.N; ++i) // Print all bodies to the file
197 Body_Print(universe.body+i, save);
203 free(universe.body); // Cleanup memory used for bodies
208 * @function DisplayStatistics
209 * @purpose Display useful information about the computations done,
210 * - Total number of steps computed
211 * - Time in seconds elapsed
212 * - Clock cycles executed
213 * - Equivelant time for a single thread to execute same number of clock cycles
215 void DisplayStatistics()
217 clock_t end = clock();
218 struct timeval end_time;
219 if (gettimeofday(&end_time, NULL) != 0)
221 perror("Couldn't get time of day.\n");
224 float runtime = (float)(end_time.tv_sec-options.start_time.tv_sec) + (float)(end_time.tv_usec-options.start_time.tv_usec) / 1.0e6;
225 float clock_time = (float)(end - options.start_clock) / (float)(CLOCKS_PER_SEC);
226 printf("%u\t%f\t%u\t%f\n", universe.steps, runtime, (unsigned)(end - options.start_clock), clock_time);
231 * @function ExitCondition
232 * @purpose Helper to check whether the program is supposed to exit
233 * Does not check for user triggered quit
234 * Checks for either a timeout, or computation of the required number of steps
236 bool ExitCondition(void)
238 return (runstate != RUN || (options.timeout > 0.00 && ((unsigned)(time(NULL) - options.start_time.tv_sec) >= options.timeout))
239 || (options.num_steps > 0 && universe.steps > options.num_steps));