Advertisement
Guest User

420

a guest
Oct 18th, 2019
89
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 8.36 KB | None | 0 0
  1. /*
  2. * SEQ_Poisson.c
  3. * 2D Poison equation solver
  4. */
  5.  
  6. #include <stdio.h>
  7. #include <stdlib.h>
  8. #include <math.h>
  9. #include <time.h>
  10. #include <mpi.h>
  11. #include <string.h>
  12.  
  13. #define DEBUG 0
  14.  
  15. #define max(a,b) ((a)>(b)?a:b)
  16.  
  17. enum
  18. {
  19. X_DIR, Y_DIR
  20. };
  21.  
  22. /* MPI variables */
  23. // Process specific
  24. int proc_rank;
  25. int proc_coord[2];
  26. int proc_top, proc_right, proc_bottom, proc_left;
  27. // Same for all processes
  28. int P;
  29. int P_grid[2];
  30. MPI_Comm grid_comm;
  31. MPI_Status status;
  32.  
  33. double wtime; // Wallclock time
  34.  
  35. int gridsize[2];
  36. double precision_goal; /* precision_goal of solution */
  37. int max_iter; /* maximum number of iterations alowed */
  38.  
  39. /* benchmark related variables */
  40. clock_t ticks; /* number of systemticks */
  41. int timer_on = 0; /* is timer running? */
  42.  
  43. /* local grid related variables */
  44. double **phi; /* grid */
  45. int **source; /* TRUE if subgrid element is a source */
  46. int dim[2]; /* grid dimensions */
  47. int offset[2];
  48. MPI_Datatype border_type[2];
  49.  
  50. void Setup_Proc_Grid(int argc, char **argv);
  51. void Setup_Grid();
  52. void Setup_Mpi_Datatypes();
  53. void Exchange_Borders();
  54. double Do_Step(int parity);
  55. void Solve();
  56. void Write_Grid();
  57. void Clean_Up();
  58. void Debug(char *mesg, int terminate);
  59. void start_timer();
  60. void resume_timer();
  61. void stop_timer();
  62. void print_timer();
  63. void Setup_Mpi();
  64. void Clean_Up_Mpi();
  65.  
  66. void start_timer()
  67. {
  68. if (!timer_on)
  69. {
  70. MPI_Barrier(MPI_COMM_WORLD);
  71. ticks = clock();
  72. wtime = MPI_Wtime();
  73. timer_on = 1;
  74. }
  75. }
  76.  
  77. void resume_timer()
  78. {
  79. if (!timer_on)
  80. {
  81. ticks = clock() - ticks;
  82. wtime = MPI_Wtime() - wtime;
  83. timer_on = 1;
  84. }
  85. }
  86.  
  87. void stop_timer()
  88. {
  89. if (timer_on)
  90. {
  91. ticks = clock() - ticks;
  92. wtime = MPI_Wtime() - wtime;
  93. timer_on = 0;
  94. }
  95. }
  96.  
  97. void print_timer()
  98. {
  99. if (timer_on)
  100. {
  101. stop_timer();
  102. printf("(%i) Elapsed processortime: %14.6f s (%5.1f%% CPU)\n", proc_rank, wtime, ticks * (1.0 / CLOCKS_PER_SEC) / wtime);
  103. resume_timer();
  104. }
  105. else
  106. printf("(%i) Elapsed processortime: %14.6f s (%5.1f%% CPU)\n", proc_rank, wtime, ticks * (1.0 / CLOCKS_PER_SEC) / wtime);
  107. }
  108.  
  109. void Setup_Mpi(int argc, char **argv) {
  110. MPI_Init(&argc, &argv);
  111. Setup_Proc_Grid(argc, argv);
  112. }
  113.  
  114. void Setup_Proc_Grid(int argc, char **argv) {
  115. int wrap_around[2];
  116. int reorder;
  117.  
  118. Debug("My_MPI_Init", 0);
  119.  
  120. MPI_Comm_size(MPI_COMM_WORLD, &P);
  121.  
  122. if (argc > 2) {
  123. P_grid[X_DIR] = atoi(argv[1]);
  124. P_grid[Y_DIR] = atoi(argv[2]);
  125. if (P_grid[X_DIR] * P_grid[Y_DIR] != P)
  126. Debug("ERROR : Process grid dimensions do not match with P ", 1);
  127. }
  128. else {
  129. Debug("ERROR : Wrong parameter input", 1);
  130. }
  131.  
  132. wrap_around[X_DIR] = 0;
  133. wrap_around[Y_DIR] = 0;
  134. reorder = 1;
  135.  
  136. MPI_Cart_create(MPI_COMM_WORLD, 2, P_grid, wrap_around, reorder, &grid_comm);
  137.  
  138. MPI_Comm_rank(grid_comm, &proc_rank);
  139. MPI_Cart_coords(grid_comm, proc_rank, 2, proc_coord);
  140.  
  141. printf("(%i) (x,y)=(%i,%i)\n", proc_rank, proc_coord[X_DIR], proc_coord[Y_DIR]);
  142.  
  143. MPI_Cart_shift(grid_comm, Y_DIR, 1, &proc_bottom, &proc_top);
  144. MPI_Cart_shift(grid_comm, X_DIR, 1, &proc_left, &proc_right);
  145.  
  146. if (DEBUG) printf("(%i) top %i, right %i, bottom %i, left %i\n",
  147. proc_rank, proc_top, proc_right, proc_bottom, proc_left);
  148.  
  149. }
  150.  
  151. void Setup_Mpi_Datatypes() {
  152. Debug("Setup_Mpi_Datatypes", 0);
  153.  
  154. MPI_Type_vector(dim[X_DIR] - 2, 1, dim[Y_DIR],
  155. MPI_DOUBLE, &border_type[Y_DIR]);
  156. MPI_Type_commit(&border_type[Y_DIR]);
  157.  
  158. MPI_Type_vector(dim[Y_DIR] - 2, 1, 1,
  159. MPI_DOUBLE, &border_type[X_DIR]);
  160. }
  161.  
  162. void Exchange_Borders() {
  163. Debug("Exchange_Borders", 0);
  164.  
  165. MPI_Sendrecv(&phi[1][Y_DIR], 1, border_type[])
  166. }
  167.  
  168. void Clean_Up_Mpi() {
  169. MPI_Finalize();
  170. }
  171.  
  172. void Debug(char *mesg, int terminate)
  173. {
  174. if (DEBUG || terminate)
  175. printf("%s\n", mesg);
  176. if (terminate)
  177. exit(1);
  178. }
  179.  
  180. void Setup_Grid()
  181. {
  182. int x, y, s;
  183. double source_x, source_y, source_val;
  184. FILE *f;
  185. int upper_offset[2];
  186.  
  187. Debug("Setup_Subgrid", 0);
  188.  
  189. if (proc_rank == 0) {
  190. f = fopen("input.dat", "r");
  191. if (f == NULL) Debug("Error opening input.dat", 1);
  192. fscanf(f, "nx: %i\n", &gridsize[X_DIR]);
  193. fscanf(f, "ny: %i\n", &gridsize[Y_DIR]);
  194. fscanf(f, "precision goal: %lf\n", &precision_goal);
  195. fscanf(f, "max iterations: %i\n", &max_iter);
  196. }
  197. MPI_Bcast(&gridsize, 2, MPI_INTEGER, 0, MPI_COMM_WORLD);
  198. MPI_Bcast(&precision_goal, 1, MPI_DOUBLE, 0, MPI_COMM_WORLD);
  199. MPI_Bcast(&max_iter, 1, MPI_INTEGER, 0, MPI_COMM_WORLD);
  200.  
  201. offset[X_DIR] = gridsize[X_DIR] * proc_coord[X_DIR] / P_grid[X_DIR];
  202. offset[Y_DIR] = gridsize[Y_DIR] * proc_coord[Y_DIR] / P_grid[Y_DIR];
  203. upper_offset[X_DIR] = gridsize[X_DIR] * (proc_coord[X_DIR] + 1) / P_grid[X_DIR];
  204. upper_offset[Y_DIR] = gridsize[Y_DIR] * (proc_coord[Y_DIR] + 1) / P_grid[Y_DIR];
  205.  
  206. /* Calculate dimensions of local subgrid */
  207. dim[Y_DIR] = upper_offset[Y_DIR] - offset[Y_DIR];
  208. dim[X_DIR] = upper_offset[X_DIR] - offset[X_DIR];
  209.  
  210. dim[Y_DIR] += 2;
  211. dim[X_DIR] += 2;
  212.  
  213. /* allocate memory */
  214. if ((phi = malloc(dim[X_DIR] * sizeof(*phi))) == NULL)
  215. Debug("Setup_Subgrid : malloc(phi) failed", 1);
  216. if ((source = malloc(dim[X_DIR] * sizeof(*source))) == NULL)
  217. Debug("Setup_Subgrid : malloc(source) failed", 1);
  218. if ((phi[0] = malloc(dim[Y_DIR] * dim[X_DIR] * sizeof(**phi))) == NULL)
  219. Debug("Setup_Subgrid : malloc(*phi) failed", 1);
  220. if ((source[0] = malloc(dim[Y_DIR] * dim[X_DIR] * sizeof(**source))) == NULL)
  221. Debug("Setup_Subgrid : malloc(*source) failed", 1);
  222. for (x = 1; x < dim[X_DIR]; x++)
  223. {
  224. phi[x] = phi[0] + x * dim[Y_DIR];
  225. source[x] = source[0] + x * dim[Y_DIR];
  226. }
  227.  
  228. /* set all values to '0' */
  229. for (x = 0; x < dim[X_DIR]; x++)
  230. for (y = 0; y < dim[Y_DIR]; y++)
  231. {
  232. phi[x][y] = 0.0;
  233. source[x][y] = 0;
  234. }
  235.  
  236. /* put sources in field */
  237. do
  238. {
  239. if (proc_rank == 0) s = fscanf(f, "source: %lf %lf %lf\n", &source_x, &source_y, &source_val);
  240.  
  241. MPI_Bcast(&s, 1, MPI_INTEGER, 0, MPI_COMM_WORLD);
  242.  
  243. if (s==3)
  244. {
  245. MPI_Bcast(&source_x, 1, MPI_DOUBLE, 0, MPI_COMM_WORLD);
  246. MPI_Bcast(&source_y, 1, MPI_DOUBLE, 0, MPI_COMM_WORLD);
  247. MPI_Bcast(&source_val, 1, MPI_DOUBLE, 0, MPI_COMM_WORLD);
  248. x = source_x * gridsize[X_DIR];
  249. y = source_y * gridsize[Y_DIR];
  250. x += 1;
  251. y += 1;
  252.  
  253. x = x - offset[X_DIR];
  254. y = y - offset[Y_DIR];
  255. if ( x > 0 && x < dim[X_DIR] - 1
  256. && y > 0 && y < dim[Y_DIR] - 1) {
  257. phi[x][y] = source_val;
  258. source[x][y] = 1;
  259. }
  260. }
  261. }
  262. while (s==3);
  263.  
  264. if (proc_rank == 0) fclose(f);
  265. }
  266.  
  267. double Do_Step(int parity)
  268. {
  269. int x, y;
  270. double old_phi;
  271. double max_err = 0.0;
  272.  
  273. /* calculate interior of grid */
  274. for (x = 1; x < dim[X_DIR] - 1; x++)
  275. for (y = 1; y < dim[Y_DIR] - 1; y++)
  276. if ((x + y) % 2 == parity && source[x][y] != 1)
  277. {
  278. old_phi = phi[x][y];
  279. phi[x][y] = (phi[x + 1][y] + phi[x - 1][y] +
  280. phi[x][y + 1] + phi[x][y - 1]) * 0.25;
  281. if (max_err < fabs(old_phi - phi[x][y]))
  282. max_err = fabs(old_phi - phi[x][y]);
  283. }
  284.  
  285. return max_err;
  286. }
  287.  
  288. void Solve()
  289. {
  290. int count = 0;
  291. double delta;
  292. double delta1, delta2;
  293.  
  294. Debug("Solve", 0);
  295.  
  296. /* give global_delta a higher value then precision_goal */
  297. delta = 2 * precision_goal;
  298.  
  299. while (delta > precision_goal && count < max_iter)
  300. {
  301. Debug("Do_Step 0", 0);
  302. delta1 = Do_Step(0);
  303.  
  304. Debug("Do_Step 1", 0);
  305. delta2 = Do_Step(1);
  306.  
  307. delta = max(delta1, delta2);
  308. count++;
  309. }
  310.  
  311. printf("Number of iterations (proc %i): %i\n", proc_rank, count);
  312. }
  313.  
  314. void Write_Grid()
  315. {
  316. int x, y;
  317. FILE *f;
  318.  
  319. char rankstring[4];
  320. snprintf(rankstring, 4, "%d", proc_rank);
  321.  
  322. char filename[] = "output";
  323. strcat(filename, rankstring);
  324. strcat(filename, ".dat");
  325.  
  326. if ((f = fopen(filename, "w")) == NULL)
  327. Debug("Write_Grid : fopen failed", 1);
  328.  
  329. Debug("Write_Grid", 0);
  330.  
  331. for (x = 1; x < dim[X_DIR] - 1; x++)
  332. for (y = 1; y < dim[Y_DIR] - 1; y++)
  333. fprintf(f, "%i %i %f\n", x, y, phi[x][y]);
  334.  
  335. fclose(f);
  336. }
  337.  
  338. void Clean_Up()
  339. {
  340. Debug("Clean_Up", 0);
  341.  
  342. free(phi[0]);
  343. free(phi);
  344. free(source[0]);
  345. free(source);
  346. }
  347.  
  348. int main(int argc, char **argv)
  349. {
  350.  
  351. Setup_Mpi(argc, argv);
  352.  
  353. Setup_Mpi_Datatypes();
  354.  
  355. start_timer();
  356.  
  357. Setup_Grid();
  358.  
  359. Solve();
  360.  
  361. Write_Grid();
  362.  
  363. print_timer();
  364.  
  365. Clean_Up();
  366.  
  367. Clean_Up_Mpi();
  368.  
  369. return 0;
  370. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement