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)
55 #ifdef OVER_ENGINEERED
59 #endif //OVER_ENGINEERED
68 omp_set_num_threads(options.num_threads);
69 if (omp_get_max_threads() != options.num_threads)
71 fprintf(stderr, "Couldn't use %d threads!\n", options.num_threads);
75 #ifdef OVER_ENGINEERED
76 sub_system = Split_System(&universe, options.num_threads); // I could use omp for loops instead, but I like this way
77 #endif //OVER_ENGINEERED
81 #ifdef OVER_ENGINEERED
82 int index = omp_get_thread_num();
83 #endif //OVER_ENGINEERED
84 while (!ExitCondition())
87 #ifdef OVER_ENGINEERED
88 System_Forces(sub_system+index, &universe);
89 #pragma omp barrier // Look! An explicit barrier!
90 System_Positions(sub_system+index);
94 for (unsigned a = 0; a < universe.N; ++a)
96 for (unsigned i = 0; i < DIMENSIONS; ++i)
97 (universe.body+a)->F[i] = 0;
98 //printf("Thread %d computes force for body %d\n", omp_get_thread_num(), a);
99 omp_set_num_threads(options.nested_threads);
100 #pragma omp parallel for
101 for (unsigned b = 0; b < universe.N; ++b)
104 Body_Force(universe.body+a, universe.body+b);
109 for (unsigned a = 0; a < universe.N; ++a)
111 //printf("Thread %d computes position for body %d\n", omp_get_thread_num(), a);
112 Body_Velocity(universe.body+a);
113 Body_Position(universe.body+a);
116 #endif //OVER_ENGINEERED
120 // The if statement has a cost, but if can be removed easily in an optimised version.
121 // Only the main thread is allowed to mess with glut, because glut is evil (not thread safe).
122 // Although this function may be nested, that will only happen if the if would be false.
123 // ("if the if would be false"; I am awesome at explaining code)
124 if (options.draw_graphics && options.pedantic_graphics)
132 // Only one thread should execute this, and we don't care which one.
133 // So much easier than the pthread version!
135 if (options.verbosity != 0 && universe.steps % options.verbosity == 0)