YauhenMardan

Untitled

Dec 23rd, 2019
152
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 5.65 KB | None | 0 0
  1. // main.cpp
  2. // CA-Lab4
  3. //
  4. // Created by Zhenya Mordan on 12/15/19.
  5. // Copyright © 2019 Zhenya Mordan. All rights reserved.
  6. //
  7.  
  8. #include <iostream>
  9. #include <fstream>
  10. #include <algorithm>
  11. #include <iomanip>
  12. #include "mpi.h"
  13. #include <cmath>
  14.  
  15. // 1D composition
  16.  
  17. using namespace std;
  18.  
  19. ofstream fout("output.txt");
  20.  
  21. int n = 100; // points count for y
  22. double lower_border_y = 0, upper_border_y = 1; //
  23.  
  24. int m = 100; // points count for x
  25. double lower_border_x = 0, upper_border_x = 1;
  26.  
  27. double hx = (upper_border_x - lower_border_x) / (m - 1); // step by x
  28. double hy = (upper_border_y - lower_border_y) / (n - 1); // step by y
  29.  
  30. double yc = 1 / (hy * hy); // 1 / (hy * hy)
  31. double xc = 1 / (hx * hx); // 1 / (hx * hx)
  32. double c = 2 * (xc + yc); // 2 * (1 / (hx * hx) + 1 / (hy * hy))
  33.  
  34.  
  35. double f(double x, double y)
  36. {
  37. return x*y;
  38. }
  39.  
  40. double f1(double y)
  41. {
  42. return sin(y);
  43. }
  44.  
  45. double f2(double y)
  46. {
  47. return y;
  48. }
  49.  
  50. double f3(double x)
  51. {
  52. return x*x*x;
  53. }
  54.  
  55. double f4(double x)
  56. {
  57. return x*x;
  58. }
  59.  
  60. void fill(int* recvcounts, int* displs, int size, int l);
  61.  
  62. int main(int argc, char ** argv)
  63. {
  64. int rank, size;
  65. MPI_Status status;
  66.  
  67. double time_start;
  68. double* u = new double[n * m];
  69. double* u_result = new double[n * m]; // result value table
  70.  
  71. MPI_Init(&argc, &argv);
  72. MPI_Comm_rank(MPI_COMM_WORLD, &rank);
  73. MPI_Comm_size(MPI_COMM_WORLD, &size);
  74.  
  75. // fill values of table u by zeros
  76. for (int i = 0; i < n; i++)
  77. {
  78. for (int j = 0; j < m; j++)
  79. u[i * m + j] = 0;
  80. }
  81.  
  82. int l = (n - 2) / size + 2; // rows count per process
  83.  
  84. int first = rank * (l - 2); // [first index,
  85. int last = first + l; // ,last index)
  86.  
  87. double x; // current x
  88. double y; // current y
  89.  
  90. // fill border values
  91. // for bottom and upper border (only in main process and last process)
  92. if (rank == 0)
  93. {
  94. x = lower_border_x;
  95. for (int j = 0; j < m; j++)
  96. {
  97. u[0 * m + j] = f3(x);
  98. x += hx;
  99. }
  100. }
  101.  
  102. if (rank == size - 1)
  103. {
  104. x = lower_border_x;
  105. for (int j = 0; j < m; j++)
  106. {
  107. u[(n - 1) * m + j] = f4(x);
  108. x += hx;
  109. }
  110. }
  111.  
  112. y = lower_border_y + first * hy;
  113.  
  114. // for left and right borders (in all processes)
  115. for (int i = first; i < last; i++)
  116. {
  117. u[i * m] = f1(y);
  118. u[i * m + m - 1] = f2(y);
  119. y += hy;
  120. }
  121.  
  122. // start of time
  123. if (rank == 0)
  124. time_start = MPI_Wtime();
  125.  
  126. // begin of computation
  127. double epsilon = 1e-6; // wanted accuracy
  128. double error = 1; // current accuracy
  129.  
  130. while (error > epsilon)
  131. {
  132. error = 0;
  133. // difference schema for numerical solving of differential equation
  134. y = lower_border_y + (first + 1) * hy;
  135. for (int i = first + 1; i < last - 1; i++)
  136. {
  137. x = lower_border_x + hx;
  138. for (int j = 1; j < m - 1; j++)
  139. {
  140. double uprev = u[i * m + j];
  141. u[i * m + j] = (-f(x, y) + yc * (u[(i - 1) * m + j] + u[(i + 1) * m + j]) + xc * (u[i * m + j - 1] + u[i * m + j + 1])) / c;
  142. error = max(error, abs(uprev - u[i * m + j]));
  143. x += hx;
  144. }
  145. y += hy;
  146. }
  147.  
  148. // get error from all additional processes in main + calculate max error
  149. if (rank == 0)
  150. {
  151. double currentError;
  152. for (int i = 1; i < size; i++)
  153. {
  154. MPI_Recv(&currentError, 1, MPI_DOUBLE, i, 0, MPI_COMM_WORLD, &status);
  155. error = max(error, currentError);
  156. }
  157. }
  158. else
  159. MPI_Send(&error, 1, MPI_DOUBLE, 0, 0, MPI_COMM_WORLD);
  160.  
  161. // send max delta from main process to all additional
  162. if (rank == 0)
  163. for (int i = 1; i < size; i++)
  164. MPI_Send(&error, 1, MPI_DOUBLE, i, 1, MPI_COMM_WORLD);
  165. else
  166. MPI_Recv(&error, 1, MPI_DOUBLE, 0, 1, MPI_COMM_WORLD, &status);
  167.  
  168. // send new rows to neighbours
  169. if (rank < size - 1)
  170. {
  171. MPI_Send(&u[(last - 2) * m], m, MPI_DOUBLE, rank + 1, 2, MPI_COMM_WORLD);
  172. MPI_Recv(&u[(last - 1) * m], m, MPI_DOUBLE, rank + 1, 2, MPI_COMM_WORLD, &status);
  173. }
  174.  
  175. if (rank > 0)
  176. {
  177. MPI_Send(&u[(first + 1) * m], m, MPI_DOUBLE, rank - 1, 2, MPI_COMM_WORLD);
  178. MPI_Recv(&u[first * m], m, MPI_DOUBLE, rank - 1, 2, MPI_COMM_WORLD, &status);
  179. }
  180. }
  181.  
  182. // fill recvcounts (count of receved process data) and displs (positions of sent proccess data)
  183. int* recvcounts = new int[size], *displs = new int[size];
  184. if (rank == 0)
  185. {
  186. fill(recvcounts, displs, size, l);
  187. }
  188.  
  189. MPI_Gatherv(&u[(first + 2 * (rank > 0)) * m], (l - 2 * (rank > 0)) * m, MPI_DOUBLE, u_result, recvcounts, displs, MPI_DOUBLE, 0, MPI_COMM_WORLD);
  190.  
  191. // output computation time
  192. if (rank == 0)
  193. cout << MPI_Wtime() - time_start << endl;
  194.  
  195. // write answer to file
  196. if (rank == 0)
  197. {
  198. for (int i = 0; i < n; i++)
  199. {
  200. for (int j = 0; j < m; j++)
  201. fout << fixed << setprecision(6) << lower_border_x+j*hx <<" "<<lower_border_y+i*hy <<" "<< u_result[i * m + j] << "\n";
  202. }
  203. }
  204.  
  205. MPI_Finalize();
  206.  
  207. return 0;
  208. }
  209.  
  210. void fill(int* recvcounts, int* displs, int size, int l)
  211. {
  212. recvcounts[0] = l * m;
  213. for (int i = 1; i < size; i++)
  214. recvcounts[i] = (l - 2) * m;
  215.  
  216. displs[0] = 0;
  217. for (int i = 1; i < size; i++)
  218. displs[i] = ((l - 2) * i + 2) * m;
  219. }
Advertisement
Add Comment
Please, Sign In to add comment