3 * @purpose OpenMP version of N-Body simulator, implementation
4 * @author Sam Moore (20503628) - 2012
8 #include "../single-thread/nbody.c" // Include original code
9 #include "graphics.h" // For Graphics_Run function only
12 #ifdef OVER_ENGINEERED
13 System * sub_system = NULL;
14 #endif //OVER_ENGINEERED
17 * @function Simulation_Run
18 * @purpose Start the simulation
19 * @param argc, argv - Passed to Graphics_Run if needed, otherwise unused
21 void Simulation_Run(int argc, char ** argv)
24 if (options.num_threads == 0)
25 options.num_threads = omp_get_max_threads();
27 if (options.draw_graphics)
29 Graphics_Run(argc, argv);
30 if (options.pedantic_graphics == false)
32 options.num_threads += 1;
34 if (omp_get_nested() == 0)
36 fprintf(stderr, "Couldn't enable nested parallelism\n.");
41 #pragma omp parallel sections num_threads(2)
64 omp_set_num_threads(options.num_threads);
65 if (omp_get_max_threads() != options.num_threads)
67 fprintf(stderr, "Couldn't use %d threads!\n", options.num_threads);
71 #ifdef OVER_ENGINEERED
72 sub_system = Split_System(&universe, options.num_threads); // I could use omp for loops instead, but I like this way
73 #endif //OVER_ENGINEERED
77 #ifdef OVER_ENGINEERED
78 int index = omp_get_thread_num();
79 #endif //OVER_ENGINEERED
80 while (!ExitCondition())
83 #ifdef OVER_ENGINEERED
84 System_Forces(sub_system+index, &universe);
85 #pragma omp barrier // Look! An explicit barrier!
86 System_Positions(sub_system+index);
90 for (unsigned a = 0; a < universe.N; ++a)
92 for (unsigned i = 0; i < DIMENSIONS; ++i)
93 (universe.body+a)->F[i] = 0;
94 //printf("Thread %d computes force for body %d\n", omp_get_thread_num(), a);
95 omp_set_num_threads(options.nested_threads);
96 #pragma omp parallel for
97 for (unsigned b = 0; b < universe.N; ++b)
100 Body_Force(universe.body+a, universe.body+b);
105 for (unsigned a = 0; a < universe.N; ++a)
107 //printf("Thread %d computes position for body %d\n", omp_get_thread_num(), a);
108 Body_Velocity(universe.body+a);
109 Body_Position(universe.body+a);
112 #endif //OVER_ENGINEERED
116 // The if statement has a cost, but if can be removed easily in an optimised version.
117 // Only the main thread is allowed to mess with glut, because glut is evil (not thread safe).
118 // Although this function may be nested, that will only happen if the if would be false.
119 // ("if the if would be false"; I am awesome at explaining code)
120 if (options.draw_graphics && options.pedantic_graphics)
128 // Only one thread should execute this, and we don't care which one.
129 // So much easier than the pthread version!
131 if (options.verbosity != 0 && universe.steps % options.verbosity == 0)