Started Parallel Programming Self Assessment
[matches/honours.git] / course / semester2 / pprog / assignment0 / nbody.c
1 /**
2  * @file nbody.c
3  * @purpose Implementations for N-Body simulator
4  * @author Sam Moore
5  * @date August 2012
6  */
7
8 #include <assert.h> // To make sure I don't do anything stupid.
9 #include <math.h> //For maths and stuff
10 #include <stdio.h> //For writing data to files
11 #include "nbody.h" //Declarations of functions and structures in this file
12
13 // --- Body functions --- //
14
15 /**
16  * @function Body_Init
17  * @purpose Initialise a Body object with mass, position and velocity
18  * @param body - Target Body
19  * @param m - The mass of the Body
20  * @param x[...] - The position vector of the body
21  * @param v[...] - The velocity vector of the body
22  */
23 void Body_Init(Body * body, float m, float x[DIMENSIONS], float v[DIMENSIONS])
24 {
25         assert(body != NULL);
26         body->m = m;
27         for (unsigned i = 0; i < DIMENSIONS; ++i)
28         {
29                 body->x[i] = x[i];
30                 body->v[i] = v[i];
31                 body->F[i] = 0.00;
32         }
33         body->exists = true;
34 }
35
36 /**
37  * @function Body_Destroy
38  * @purpose Destroy a Body
39  * @param body - Target Body
40  */
41 void Body_Destroy(Body * body)
42 {
43         assert(body != NULL);
44         body->exists = false;
45 }
46
47 /**
48  * @function Body_Step
49  * @purpose Perform a single step, updating target Body
50  * @param body - Target Body
51  * @param system - System that the Body is part of (used for universal constants, etc)
52  */
53 void Body_Step(Body * body, System * system)
54 {
55         assert(body != NULL && system != NULL && body->exists);
56
57         //fprintf(stderr, "DEBUG - Body %p\t%d\n", (void*)(body), body->exists);
58         for (unsigned i = 0; i < DIMENSIONS; ++i)
59         {
60                 body->x[i] += body->v[i] * system->dt; //Update the position vector
61                 body->v[i] += (body->F[i] / body->m) * system->dt; //Update the velocity vector
62                 body->F[i] = 0.00; //Reset the net force vector
63         }
64
65         //Do collision checking
66         
67 }
68
69 /**
70  * @function Body_Force
71  * @purpose Update the net force on Body A due to Body B
72  * @param A - Body to update; subject of force from B
73  * @param B - Body causing force on A; NOT CHANGED BY THIS FUNCTION
74  * @param system - System which Body A is a part of (used for universal constants, etc)
75  */
76 void Body_Force(Body * A, Body * B, System * system)
77 {
78         
79         assert(A != NULL && B != NULL && system != NULL && A->exists && B->exists);
80         if (A == B)
81                 return;
82         
83         float r2 = 0.00;
84         for (unsigned i = 0; i < DIMENSIONS; ++i)
85                 r2 += powf((B->x[i] - A->x[i]), 2);
86
87         float k = system->G * (A->m * B->m) / powf(r2, 1.50);
88         for (unsigned i = 0; i < DIMENSIONS; ++i)
89                 A->F[i] += k * (B->x[i] - A->x[i]);
90         
91 }       
92
93 /**
94  * @function Body_Radius
95  * @purpose Calculate the radius of a body
96  * @param body - Target Body
97  * @returns The radius of body
98  */
99 float Body_Radius(Body * body)
100 {
101         assert(body != NULL && body->exists);
102         float radius = 5.0;
103         return radius;
104 }
105
106 /**
107  * @function Body_WriteData
108  * @purpose Write data about the Body to a file
109  * @param body - The target Body
110  * @param system - System to which the Body belongs
111  * @param file - File to write data to
112  */
113 void Body_WriteData(Body * body, System * system, FILE * file)
114 {
115         assert(body != NULL && system != NULL && file != NULL && body->exists);
116         fprintf(file,"%d\t%p\t%f", system->step, (void*)(body), body->m);
117         for (unsigned i = 0; i < DIMENSIONS; ++i)
118                 fprintf(file,"\t%f", body->x[i]);
119         for (unsigned i = 0; i < DIMENSIONS; ++i)
120                 fprintf(file,"\t%f", body->v[i]);
121         for (unsigned i = 0; i < DIMENSIONS; ++i)
122                 fprintf(file,"\t%f", body->F[i]);
123
124         fprintf(file,"\n");
125
126 }
127
128 // --- System functions --- //
129
130 /**
131  * @function System_Init
132  * @purpose Initialise a System object
133  * @param system - Target System
134  * @param x - The origin of the System (currently used for offset of graphics)
135  * @param dt - Time step
136  * @param G - Universal Gravitational Constant
137  * @param nMax - Number of Body objects this System will contain (DEFAULT = 10)
138  */
139 void System_Init(System * system, float x[DIMENSIONS], float dt, float G, unsigned nMax)
140 {
141         assert(system != NULL);
142         for (unsigned i = 0; i < DIMENSIONS; ++i)
143                 system->x[i] = x[i];
144
145         
146         system->dt = dt;
147         system->G = G;
148         system->nMax = nMax;
149         system->n = 0;
150         
151         system->bodies = (Body*)(calloc(sizeof(Body), nMax)); //Allocate space for nMax bodies
152         for (unsigned a = 0; a < nMax; ++a)
153                 (system->bodies+a)->exists = false;
154 }
155
156 /**
157  * @function System_Destroy
158  * @purpose Destroy all Bodies in a system
159  * @param system - Target system
160  */
161
162 void System_Destroy(System * system)
163 {
164         assert(system != NULL);
165         if (system->bodies != NULL)
166                 free(system->bodies);
167         system->nMax = 0;
168 }
169
170 /**
171  * @function System_Step
172  * @purpose Compute single step for all Bodies in System
173  * @param system - Target system
174  */
175 void System_Step(System * system)
176 {
177         assert(system != NULL);
178
179         // Update forces
180         for (unsigned a = 0; a < system->nMax; ++a)
181         {
182                 if (system->bodies[a].exists)
183                 {
184                         for (unsigned b = 0; b < system->nMax; ++b)
185                         {
186                                 //fprintf(stderr, "DEBUG1 - %p\t%p\t%d\t%d\n", (void*)(system->bodies+a), (void*)(system->bodies+b), system->bodies[a].exists, system->bodies[b].exists);
187                                 if (system->bodies[b].exists)
188                                 {
189                                         //fprintf(stderr, "DEBUG2 - %p\t%p\t%d\t%d\n", (void*)(system->bodies+a), (void*)(system->bodies+b), system->bodies[a].exists, system->bodies[b].exists);
190                                         Body_Force(&(system->bodies[a]), &(system->bodies[b]), system); //Update force on bodies[a] due to bodies[b]
191                                         //fprintf(stderr, "DEBUG3 - %p\t%p\t%d\t%d\n", (void*)(system->bodies+a), (void*)(system->bodies+b), system->bodies[a].exists, system->bodies[b].exists);
192                                 }
193                         }
194                 }
195         }
196
197         // Perform steps
198         for (unsigned a = 0; a < system->nMax; ++a)
199         {
200                 if ((system->bodies+a)->exists)
201                         Body_Step(system->bodies+a, system);
202         }
203 }
204
205 /**
206  * @function System_AddBody
207  * @purpose Add a Body to a System. Resizes the System's bodies array if necessary.
208  * @param system - Target System
209  * @param m - Mass of the new Body
210  * @param x[...] - position vector for the new Body
211  * @param v[...] - velocity vector for the new Body
212  * @returns Pointer to new Body
213  */
214
215 Body * System_AddBody(System * system, float m, float x[DIMENSIONS], float v[DIMENSIONS])
216 {
217         assert(system != NULL);
218
219         unsigned a = 0;
220         for (a = 0; a < system->nMax; ++a)
221         {
222                 if (!(system->bodies+a)->exists)
223                         break;
224         }
225         
226         if (a >= system->nMax)
227         {
228                 system->nMax = (system->nMax+1) * 2;
229                 system->bodies = (Body*)(realloc(system->bodies, sizeof(Body) * system->nMax));
230                 for (unsigned b = a; b < system->nMax; ++b)
231                         (system->bodies+b)->exists = false;
232         }
233
234         Body_Init(system->bodies+a, m, x, v);
235         system->n += 1;
236
237         return (system->bodies+a);
238         
239 }
240
241 /**
242  * @function System_WriteData
243  * @purpose Write all information about System to a file
244  * @param system - Target System
245  * @param file - Target FILE (must be opened for writing)
246  */
247 void System_WriteData(System * system, FILE * file)
248 {
249         assert(system != NULL && file != NULL);
250         for (unsigned a = 0; a < system->nMax; ++a)
251         {
252                 if ((system->bodies+a)->exists)
253                         Body_WriteData(system->bodies+a, system, file);
254         }
255         fprintf(file, "\n");
256
257 }
258
259 // --- Graphical functions --- //
260
261 #ifdef _GRAPHICS_H
262
263 /**
264  * @function Body_Draw
265  * @purpose Draw an individual Body
266  * @param body - Target Body
267  * @param system - System to which the Body belongs
268  */
269
270 void Body_Draw(Body * body, System * system)
271 {
272         assert(body != NULL && system != NULL && body->exists);
273         int pixel_pos[DIMENSIONS];
274         for (unsigned i = 0; i < DIMENSIONS; ++i)
275                 pixel_pos[i] = (int)(system->x[i] - body->x[i]);
276
277         float rgb[3] = {0.0f, 0.0f, 0.0f};
278         if (body->m >= 100.0)
279         {
280                 rgb[0] = 0.0f; rgb[1] = 0.0f; rgb[2] = 1.0f;
281         }
282         if (body->m >= 10.0)
283         {
284                 rgb[0] = 0.5f; rgb[1] = 0.5f; rgb[2] = 1.0f;
285         }
286         else if (body->m >= 1.0)
287         {
288                 rgb[0] = 0.8f; rgb[1] = 0.2f; rgb[2] = 0.1f;
289         }
290         else if (body->m >= 0.1)
291         {
292                 rgb[0] = 0.0f; rgb[1] = 0.5f; rgb[2] = 0.0f;            
293         }
294         else if (body->m >= 0.01)
295         {
296                 rgb[0] = 0.5f; rgb[1] = 0.5f; rgb[2] = 0.5f;
297         }
298
299
300         Graphics_Circle(pixel_pos,Body_Radius(body), rgb[0], rgb[1], rgb[2]);
301
302         //fprintf(stdout, "DEBUG - Body_Draw - Called\n");
303 }
304
305 /**
306  * @function System_Draw
307  * @purpose Draw a System of Bodies
308  * @param system - Target System to draw
309  */
310 void System_Draw(System * system)
311 {
312         assert(system != NULL);
313         for (unsigned a = 0; a < system->nMax; ++a)
314         {
315                 if ((system->bodies+a)->exists)
316                         Body_Draw(system->bodies+a, system);
317         }
318 }
319
320 /**
321  * @function Process_Events
322  * @purpose Handle any SDL events recieved.
323  */
324 void Process_Events()
325 {
326         SDL_Event event;
327         while (SDL_PollEvent(&event)) 
328         {
329                 switch(event.type)
330                 {
331                         case SDL_QUIT:
332                                 exit(EXIT_SUCCESS);
333                                 break;
334                 }
335         }
336         //SDL_Delay(1);
337 }
338
339 #endif //_GRAPHICS_H
340
341 //EOF
342
343

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