Advertisement
manac68974

Untitled

Dec 4th, 2019
115
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 27.11 KB | None | 0 0
  1. #include <mpi.h>
  2.  
  3. #include <iomanip>
  4. #include <iostream>
  5. #include <vector>
  6. #include <map>
  7. #include <cmath>
  8. #include <cstdlib>
  9. #include <algorithm>
  10.  
  11. using namespace std;
  12.  
  13. class MPIComputations{
  14. int M, N;
  15. int cur_block_size_x, cur_block_size_y, cur_block_global_offset_x, cur_block_global_offset_y;
  16. int Gx, Gy;
  17. int cur_block_global_coors_x, cur_block_global_coors_y;
  18. double h_x, h_y;
  19. int global_block_size_x, global_block_size_y;
  20. int my_rank;
  21. MPI_Comm comm;
  22. double x_left, x_right, y_bottom, y_top;
  23.  
  24. vector<double> internal_data;
  25. vector<double> old_internal_data;
  26. vector<double> external_data[4];
  27.  
  28. int IsNodeInternalCornerOrSide(int current_node_global_offset_x, int current_node_global_offset_y){
  29.  
  30. //corners
  31. //left bottom corner
  32. if (current_node_global_offset_x == 0 && current_node_global_offset_y == 0){
  33. return 2;
  34. }
  35.  
  36. //left top corner
  37. if (current_node_global_offset_x == 0 && current_node_global_offset_y == N){
  38. return 4;
  39. }
  40.  
  41. //right bottom corner
  42. if (current_node_global_offset_x == M && current_node_global_offset_y == 0){
  43. return 6;
  44. }
  45.  
  46. //right top corner
  47. if (current_node_global_offset_x == M && current_node_global_offset_y == N){
  48. return 8;
  49. }
  50.  
  51. //sides
  52. //left side
  53. if (current_node_global_offset_y >= 1 && current_node_global_offset_y <= N - 1 &&
  54. current_node_global_offset_x == 0){
  55. return 1;
  56. }
  57.  
  58. //right side
  59. if (current_node_global_offset_y >= 1 && current_node_global_offset_y <= N - 1 &&
  60. current_node_global_offset_x == M){
  61. return 3;
  62. }
  63.  
  64. //bottom side
  65. if (current_node_global_offset_x >= 1 && current_node_global_offset_x <= M - 1 &&
  66. current_node_global_offset_y == 0){
  67. return 5;
  68. }
  69.  
  70. //top side
  71. if ((current_node_global_offset_x >= 1 && current_node_global_offset_x <= M - 1 &&
  72. current_node_global_offset_y == N)){
  73. return 7;
  74. }
  75.  
  76. //internal
  77. if ((current_node_global_offset_x >= 1 && current_node_global_offset_x <= M - 1) &&
  78. (current_node_global_offset_y >= 1 && current_node_global_offset_y <= N - 1)){
  79. return 0;
  80. }
  81.  
  82. return -1;
  83. }
  84.  
  85. double k(double x, double y) {
  86. return 1 + pow(x + y, 2);
  87. }
  88.  
  89. double q(double x, double y) {
  90. return 1;
  91. }
  92.  
  93. double u(double x, double y) {
  94. return 2.0 / (1 + pow(x, 2) + pow(y, 2));
  95. }
  96.  
  97. // psi_R(x, y) = k(A2, y) * du/dx(A2, y)
  98. double psi_R(double y) {
  99. return (-12) * (pow((y + 3), 2) + 1) / pow((pow(y, 2) + 10), 2);
  100. }
  101.  
  102. // psi_L(x, y) = -k(A1, y) * du/dx(A1, y)
  103. double psi_L(double y) {
  104. return (-8) * (pow((y - 2), 2) + 1) / pow((pow(y, 2) + 5), 2);
  105. }
  106.  
  107. // psi_T(x, y) = k(x, B2) * du/dy(x, B2)
  108. double psi_T(double x) {
  109. return (-16) * (pow((x + 4), 2) + 1) / pow((pow(x, 2) + 17), 2);
  110. }
  111.  
  112. // psi_B(x, y) = -k(x, B1) * du/dy(x, B1)
  113. double psi_B(double x) {
  114. return (-4) * (pow((x - 1), 2) + 1) / pow((pow(x, 2) + 2), 2);
  115. }
  116.  
  117. // right-part function of Poisson equation
  118. double F(double x, double y) {
  119. return 2 * (pow(x,4) + pow(y,4) + 2 * (pow(x,2) + 3) * pow(y,2) + 6 * pow(x,2) + 16*x*y + 5)
  120. / pow((1 + pow(x, 2) + pow(y, 2)), 3);
  121. }
  122.  
  123. //inner_product(A[i], internal_data)
  124. double ComputeMagicInnerProductA_iw (int current_node_global_offset_x, int current_node_global_offset_y){
  125.  
  126. int glob_x = current_node_global_offset_x;
  127. int glob_y = current_node_global_offset_y;
  128.  
  129. double result = 0.0;
  130.  
  131. map <string,bool> neighbours = {
  132. {"left", true},
  133. {"right", true},
  134. {"bottom", true},
  135. {"top", true}
  136. };
  137.  
  138. double left_neighbour = 0.0, right_neighbour = 0.0, bottom_neighbour = 0.0, top_neighbour = 0.0, this_node = 0.0;
  139. double left_coeff = 1.0, right_coeff = 1.0, bottom_coeff = 1.0, top_coeff = 1.0, this_coeff = 1.0;
  140.  
  141. switch (IsNodeInternalCornerOrSide(glob_x, glob_y)){
  142. case 2:
  143. //left bottom corner
  144. neighbours["left"] = false;
  145. neighbours["bottom"] = false;
  146. break;
  147. case 4:
  148. //left top corner
  149. neighbours["left"] = false;
  150. neighbours["top"] = false;
  151. break;
  152. case 6:
  153. //right bottom corner
  154. neighbours["right"] = false;
  155. neighbours["bottom"] = false;
  156. break;
  157. case 8:
  158. //right top corner
  159. neighbours["right"] = false;
  160. neighbours["top"] = false;
  161. break;
  162. case 1:
  163. //left side
  164. neighbours["left"] = false;
  165. break;
  166. case 3:
  167. //right side
  168. neighbours["right"] = false;
  169. break;
  170. case 5:
  171. //bottom side
  172. neighbours["bottom"] = false;
  173. break;
  174. case 7:
  175. //top side
  176. neighbours["top"] = false;
  177. break;
  178. case 0:
  179. //internal
  180. break;
  181. default:
  182. cout << "[ERROR]: Bad global coords compute matrix. Global:" << glob_x << " " << glob_y<<endl;
  183. }
  184.  
  185. if (!neighbours["left"]){
  186. right_coeff = 2.0;
  187. left_coeff = 0.0;
  188. }
  189.  
  190. if (!neighbours["right"]){
  191. left_coeff = 2.0;
  192. right_coeff = 0.0;
  193. }
  194.  
  195. if (!neighbours["bottom"]){
  196. top_coeff = 2.0;
  197. bottom_coeff = 0.0;
  198. }
  199.  
  200. if (!neighbours["top"]){
  201. bottom_coeff = 2.0;
  202. top_coeff = 0.0;
  203. }
  204.  
  205.  
  206.  
  207. if (neighbours["left"]){
  208. left_coeff *= -k(x_left + (glob_x - 0.5) * h_x, y_bottom + glob_y * h_y) / pow(h_x, 2);
  209. left_neighbour = Get(glob_x - 1, glob_y);
  210. }
  211.  
  212. if (neighbours["right"]){
  213. right_coeff *= -k(x_left + (glob_x + 0.5) * h_x, y_bottom + glob_y * h_y) / pow(h_x, 2);
  214. right_neighbour = Get(glob_x + 1, glob_y);
  215. }
  216.  
  217. if (neighbours["bottom"]){
  218. bottom_coeff *= -k(x_left + glob_x * h_x, y_bottom + (glob_y - 0.5) * h_y) / pow(h_y, 2);
  219. bottom_neighbour = Get(glob_x, glob_y - 1);
  220. }
  221.  
  222. if (neighbours["top"]){
  223. top_coeff *= -k(x_left + glob_x * h_x, y_bottom + (glob_y + 0.5) * h_y) / pow(h_y, 2);
  224. top_neighbour = Get(glob_x, glob_y + 1);
  225. }
  226.  
  227. this_coeff = q(x_left + glob_x * h_x, y_bottom + glob_y * h_y) - left_coeff - right_coeff - bottom_coeff - top_coeff;
  228. this_node = Get(glob_x, glob_y);
  229.  
  230. result = left_coeff * left_neighbour +
  231. right_coeff * right_neighbour +
  232. bottom_coeff * bottom_neighbour +
  233. top_coeff * top_neighbour +
  234. this_coeff * this_node;
  235.  
  236. return result;
  237. }
  238.  
  239. double GetNodeFromB(int current_node_global_offset_x, int current_node_global_offset_y) {
  240.  
  241. int glob_x = current_node_global_offset_x;
  242. int glob_y = current_node_global_offset_y;
  243.  
  244. double result = 0.0;
  245.  
  246. switch (IsNodeInternalCornerOrSide(glob_x, glob_y)){
  247. case 2:
  248. //left bottom corner
  249. result = F(x_left, y_bottom) + 2.0 / h_x * psi_L(y_bottom) + 2.0 / h_y * psi_B(x_left);
  250. break;
  251. case 4:
  252. //left top corner
  253. result = F(x_left, y_top) + 2.0 / h_x * psi_L(y_top) + 2.0 / h_y * psi_T(x_left);
  254. break;
  255. case 6:
  256. //right bottom corner
  257. result = F(x_right, y_bottom) + 2.0 / h_x * psi_R(y_bottom) + 2.0 / h_y * psi_B(x_right);
  258. break;
  259. case 8:
  260. //right top corner
  261. result = F(x_right, y_top) + 2.0 / h_x * psi_R(y_top) + 2.0 / h_y * psi_T(x_right);
  262. break;
  263. case 1:
  264. //left side
  265. result = F(x_left, y_bottom + glob_y * h_y) + 2.0 / h_x * psi_L(y_bottom + glob_y * h_y);
  266. break;
  267. case 3:
  268. //right side
  269. result = F(x_right, y_bottom + glob_y * h_y) + 2.0 / h_x * psi_R(y_bottom + glob_y * h_y);
  270. break;
  271. case 5:
  272. //bottom side
  273. result = F(x_left + glob_x * h_x, y_bottom) + 2.0 / h_y * psi_B(x_left + glob_x * h_x);
  274. break;
  275. case 7:
  276. //top side
  277. result = F(x_left + glob_x * h_x, y_top) + 2.0 / h_y * psi_T(x_left + glob_x * h_x);
  278. break;
  279. case 0:
  280. //internal
  281. result = F(x_left + glob_x * h_x, y_bottom + glob_y * h_y);
  282. break;
  283. default:
  284. cout << "[ERROR]: Bad global coords compute matrix. Global:" << glob_x << " " << glob_y <<endl;
  285.  
  286. }
  287.  
  288. return result;
  289.  
  290. }
  291.  
  292. double GetNodeFromExact(int current_node_global_offset_x, int current_node_global_offset_y) {
  293.  
  294. int glob_x = current_node_global_offset_x;
  295. int glob_y = current_node_global_offset_y;
  296.  
  297. return u(x_left + glob_x * h_x, y_bottom + glob_y * h_y);
  298.  
  299. }
  300.  
  301. /*
  302. void SetR(int glob_x, int glob_y, double v, vector <double> &r_matrix) {
  303. int i = glob_x - cur_block_global_offset_x, j = glob_y - cur_block_global_offset_y;
  304.  
  305. if ((j >= 0) && (j < cur_block_size_y) && (i >= 0) && (i < cur_block_size_x)) {
  306. r_matrix[j + cur_block_size_y * i] = v;
  307. }
  308. else {
  309. cout << "[ERROR]: trying to set data outside the local area" << endl;
  310. }
  311.  
  312. }
  313.  
  314. double GetR(int glob_x, int glob_y, vector <double> &r_matrix) {
  315. int i = glob_x - cur_block_global_offset_x, j = glob_y - cur_block_global_offset_y;
  316.  
  317. //internal data
  318. if ((j >= 0) && (j < cur_block_size_y) && (i >= 0) && (i < cur_block_size_x)) {
  319. return r_matrix[j + cur_block_size_y * i];
  320. }
  321.  
  322. //external data
  323. //OX
  324. if ((j >= 0) && (j < cur_block_size_y)) {
  325.  
  326. if (i == -1)
  327. return external_data[0][j];
  328.  
  329. if (i == cur_block_size_x)
  330. return external_data[1][j];
  331.  
  332. }
  333.  
  334. //OY
  335. if ((i >= 0) && (i < cur_block_size_x)) {
  336.  
  337. if (j == -1)
  338. return external_data[2][i];
  339. if (j == cur_block_size_y)
  340. return external_data[3][i];
  341.  
  342. }
  343.  
  344. cout << "[ERROR]: bad local index" << endl;
  345.  
  346. return nan("");
  347.  
  348. }
  349. */
  350. void ComputeMatrixR(){
  351. /*if(my_rank == 0)
  352. cout << "[INFO]: Computation of matrix r started"<<endl;
  353. */
  354.  
  355. vector<double> r_tmp_matrix (cur_block_size_x*cur_block_size_y, 0.0);
  356.  
  357. for(int i = 0; i < cur_block_size_x; ++i){
  358. for(int j = 0; j < cur_block_size_y; ++j){
  359.  
  360. int current_node_global_offset_x = GetGlobalX(i),
  361. current_node_global_offset_y = GetGlobalY(j);
  362.  
  363. int glob_x = current_node_global_offset_x,
  364. glob_y = current_node_global_offset_y;
  365.  
  366. r_tmp_matrix [ j + cur_block_size_y*i ] = ComputeMagicInnerProductA_iw(glob_x,glob_y) - GetNodeFromB(glob_x, glob_y);
  367.  
  368. }
  369. }
  370.  
  371. for(int i = 0; i < cur_block_size_x; ++i){
  372. for(int j = 0; j < cur_block_size_y; ++j){
  373.  
  374. old_internal_data[ j + cur_block_size_y*i ] = internal_data[ j + cur_block_size_y*i];
  375. internal_data[ j + cur_block_size_y*i ] = r_tmp_matrix[ j + cur_block_size_y*i];
  376.  
  377. }
  378. }
  379.  
  380. //old_internal_data = internal_data;
  381. //internal_data = r_tmp_matrix;
  382.  
  383. SyncMPI();
  384.  
  385. }
  386.  
  387. double ComputeTauAndStopCase(bool &should_i_stop){
  388.  
  389. double local_Ar_r_inner_product_sum = 0.0;
  390. double local_Ar_Ar_inner_product_sum = 0.0;
  391. double global_Ar_r_inner_product_sum = 0.0;
  392. double global_Ar_Ar_inner_product_sum = 0.0;
  393. double local_r_norm = 0.0;
  394. double global_r_norm = 0.0;
  395.  
  396.  
  397. for(int i = 0; i < cur_block_size_x; ++i){
  398. for(int j = 0; j < cur_block_size_y; ++j){
  399. double rho = 1.0;
  400.  
  401. int current_node_global_offset_x = GetGlobalX(i),
  402. current_node_global_offset_y = GetGlobalY(j);
  403.  
  404. int glob_x = current_node_global_offset_x,
  405. glob_y = current_node_global_offset_y;
  406.  
  407. double tmp_Ar_i_j = ComputeMagicInnerProductA_iw(glob_x, glob_y);
  408.  
  409. switch (IsNodeInternalCornerOrSide(glob_x, glob_y)){
  410. case 2:
  411. case 4:
  412. case 6:
  413. case 8:
  414. //angle
  415. rho = 0.25;
  416. break;
  417. case 1:
  418. case 3:
  419. case 5:
  420. case 7:
  421. //side
  422. rho = 0.5;
  423. break;
  424. case 0:
  425. //internal
  426. rho = 1.0;
  427. break;
  428. default:
  429. cout << "[ERROR]: Bad global coords compute tau. Global:" << glob_x << " " << glob_y << endl;
  430. }
  431.  
  432. double tmp_cur_node_value = Get(glob_x, glob_y);
  433.  
  434. local_Ar_r_inner_product_sum += rho * tmp_Ar_i_j * tmp_cur_node_value * h_x*h_y;
  435. local_Ar_Ar_inner_product_sum += rho * pow (tmp_Ar_i_j, 2) * h_x*h_y;
  436. local_r_norm += rho * pow(tmp_cur_node_value, 2) * h_x*h_y;
  437.  
  438. }
  439. }
  440.  
  441. //cout << "[DEBUG]: Local"<< local_Ar_r_inner_product_sum << endl;
  442.  
  443. MPI_Allreduce(&local_Ar_r_inner_product_sum, &global_Ar_r_inner_product_sum, 1, MPI_DOUBLE, MPI_SUM,
  444. comm);
  445.  
  446. //cout << "[DEBUG]: "<< global_Ar_r_inner_product_sum << endl;
  447.  
  448. MPI_Allreduce(&local_Ar_Ar_inner_product_sum, &global_Ar_Ar_inner_product_sum, 1, MPI_DOUBLE, MPI_SUM,
  449. MPI_COMM_WORLD);
  450.  
  451. //cout << "[DEBUG]: "<< global_Ar_Ar_inner_product_sum << endl;
  452.  
  453. double global_tau = global_Ar_r_inner_product_sum/ global_Ar_Ar_inner_product_sum;
  454.  
  455. MPI_Allreduce(&local_r_norm, &global_r_norm, 1, MPI_DOUBLE, MPI_SUM,
  456. MPI_COMM_WORLD);
  457.  
  458. double eps = 1e-06;
  459.  
  460. if (global_r_norm < 0){
  461. cout << "[ERROR]: bad global r norm" << endl;
  462. }
  463.  
  464. double tmp_norm = fabs(global_tau)*sqrt(global_r_norm);
  465.  
  466. if (my_rank == 0)
  467. cout << "[DEBUG]: solution norm "<< tmp_norm << endl;
  468.  
  469. if (tmp_norm <= eps){
  470. should_i_stop = true;
  471. }else{
  472. should_i_stop = false;
  473. }
  474.  
  475. return global_tau;
  476.  
  477. }
  478.  
  479.  
  480. void ComputeNewW(double tau){
  481.  
  482. for(int i = 0; i < cur_block_size_x; ++i){
  483. for(int j = 0; j < cur_block_size_y; ++j){
  484. internal_data[ j + cur_block_size_y*i ] = old_internal_data[ j + cur_block_size_y*i ] - tau * internal_data[ j + cur_block_size_y*i ];
  485. //old_internal_data[ j + cur_block_size_y*i ] = 0.0;
  486. }
  487. }
  488. }
  489.  
  490. int GetGlobalX(int i){
  491. return cur_block_global_offset_x + i;
  492. }
  493.  
  494. int GetGlobalY(int j){
  495. return cur_block_global_offset_y + j;
  496. }
  497.  
  498. public:
  499. MPIComputations(int inpM, int inpN, int inpGx, int inpGy, int inpx_left, int inpx_right, int inpy_bottom, int inpy_top, int inp_cur_block_global_coors_x, int inp_cur_block_global_coors_y, int inprank, MPI_Comm inpcomm){
  500.  
  501. M = inpM;
  502. N = inpN;
  503.  
  504. Gx = inpGx;
  505. Gy = inpGy;
  506.  
  507. x_left = inpx_left;
  508. x_right = inpx_right;
  509. y_bottom = inpy_bottom;
  510. y_top = inpy_top;
  511.  
  512. h_x = double((x_right - x_left)) / M;
  513. h_y = double((y_top - y_bottom)) / N;
  514.  
  515. my_rank = inprank;
  516. comm = inpcomm;
  517.  
  518. cur_block_global_coors_x = inp_cur_block_global_coors_x;
  519. cur_block_global_coors_y = inp_cur_block_global_coors_y;
  520.  
  521. global_block_size_x = (M + 1) / Gx;
  522. global_block_size_y = (N + 1) / Gy;
  523.  
  524. cur_block_size_x = global_block_size_x;
  525. cur_block_size_y = global_block_size_y;
  526.  
  527. cur_block_global_offset_x = global_block_size_x * cur_block_global_coors_x;
  528. cur_block_global_offset_y = global_block_size_y * cur_block_global_coors_y;
  529.  
  530. if (cur_block_global_offset_x + global_block_size_x > M + 1){
  531. cur_block_size_x = (M + 1) % Gx;
  532. }
  533.  
  534. if (cur_block_global_offset_y + global_block_size_y > N + 1){
  535. cur_block_size_y = (N + 1) % Gy;
  536. }
  537.  
  538. internal_data.resize(cur_block_size_x * cur_block_size_y);
  539. old_internal_data.resize(cur_block_size_x * cur_block_size_y);
  540.  
  541.  
  542. //OX
  543. external_data[0].resize(cur_block_size_y);
  544. external_data[1].resize(cur_block_size_y);
  545.  
  546. //OY
  547. external_data[2].resize(cur_block_size_x);
  548. external_data[3].resize(cur_block_size_x);
  549.  
  550. }
  551.  
  552. double Get(int i, int j) {
  553. return GetLocalIndex(i - cur_block_global_offset_x, j - cur_block_global_offset_y);
  554. }
  555.  
  556. void Set(int i, int j, double v) {
  557. return SetLocalIndex(i - cur_block_global_offset_x, j - cur_block_global_offset_y, v);
  558. }
  559.  
  560. void SyncMPI(){
  561.  
  562. /*if(my_rank == 0)
  563. cout << "[INFO]: Sync started"<< endl;
  564. */
  565.  
  566. MPI_Barrier(MPI_COMM_WORLD);
  567.  
  568. //left and right sides
  569. for(int j = 0; j < cur_block_size_y; ++j){
  570.  
  571. external_data[ 0 ][ j ] = GetLocalIndex(0,j);//internal_data[ j ];
  572. external_data[ 1 ][ j ] = GetLocalIndex(cur_block_size_x - 1,j);//internal_data[ j + cur_block_size_y * (cur_block_size_x - 1) ];
  573.  
  574. }
  575.  
  576. //bottom and top sides
  577. for(int i = 0; i < cur_block_size_x; ++i){
  578.  
  579. external_data[ 2 ][ i ] = GetLocalIndex(i,0);//internal_data[ cur_block_size_y*i ];
  580. external_data[ 3 ][ i ] = GetLocalIndex(i,cur_block_size_y - 1); //internal_data[ (cur_block_size_y - 1) + cur_block_size_y*i ];
  581.  
  582. }
  583.  
  584. int my_coords[2];
  585. int targets_ranks[4];
  586.  
  587. MPI_Cart_coords(comm, my_rank, 2, my_coords);
  588.  
  589. int neighbour_offsets[ 4 ][ 2 ] = {
  590. { -1, 0 },{ 1, 0 },
  591. { 0, -1 },{ 0, 1 }
  592. };
  593.  
  594. for(int i = 0; i < 4; i++){
  595.  
  596. int target_coords[2];
  597.  
  598. target_coords[ 0 ] = my_coords[ 0 ] + neighbour_offsets[ i ][ 0 ];
  599. target_coords[ 1 ] = my_coords[ 1 ] + neighbour_offsets[ i ][ 1 ];
  600.  
  601. if (target_coords[0] >= 0 && target_coords[0] < Gx && target_coords[1] >= 0 && target_coords[1] < Gy){
  602.  
  603. MPI_Cart_rank(comm, target_coords, &targets_ranks[ i ]);
  604.  
  605. }
  606. else{
  607. targets_ranks[i] = -1;
  608. }
  609. }
  610.  
  611. //Now we have rank for all targets
  612.  
  613. for(int axis = 0; axis < 2; axis++){
  614.  
  615. int parity_bit = (my_coords[ axis ]) % 2;
  616.  
  617. //if parity_bit == 0 then
  618. // zuerst mit links, dann mit rechts tauschen
  619. //elif parity_bit == 1:
  620. // zuerst mit rechts, dann mit links tauschen
  621.  
  622. for(int tmp = 0; tmp < 2; tmp++){
  623. parity_bit = 1 - parity_bit;
  624.  
  625. //target id in external_data und targets_ranks
  626. int target_idx = 2 * axis + (1 - parity_bit);
  627.  
  628. if (targets_ranks[target_idx] != -1){
  629.  
  630. // вычисляем теги отправки и приема
  631. // в них зашиты номер ноды, ось, направление
  632. int send_tag = 100000 + my_rank * 100 + axis * 10 + parity_bit;
  633. int recv_tag = 100000 + targets_ranks[ target_idx ] * 100 + axis * 10 + (1-parity_bit);
  634.  
  635. MPI_Status tmp_status;
  636. // если отправка не на себя, то отправляем
  637. if(my_rank != targets_ranks[ target_idx ]){
  638.  
  639. MPI_Sendrecv_replace(&external_data[ target_idx ][ 0 ], external_data[ target_idx ].size(),
  640. MPI_DOUBLE, targets_ranks[ target_idx ], send_tag, targets_ranks[ target_idx ], recv_tag,
  641. comm, &tmp_status);
  642.  
  643. }
  644. }
  645. }
  646. }
  647.  
  648. MPI_Barrier(MPI_COMM_WORLD);
  649.  
  650. }
  651.  
  652. void DoIteration(bool &should_i_stop){
  653. SyncMPI();
  654. ComputeMatrixR();
  655. SyncMPI();
  656. //Now R Matrix is in internal_data
  657.  
  658. double tau = ComputeTauAndStopCase(should_i_stop);
  659. SyncMPI();
  660.  
  661. //We have in our block jetzt:
  662. //in internal_data: R Matrix
  663. //in old_internal_data: w aus letzte iteration
  664. //and we have tau
  665. //jetzt koennen wir naechste w finden
  666. SyncMPI();
  667.  
  668. ComputeNewW(tau);
  669.  
  670. SyncMPI();
  671.  
  672. }
  673.  
  674. double GetLocalIndex(int i, int j){
  675. //internal data
  676. if ((j >= 0) && (j < cur_block_size_y) && (i >= 0) && (i < cur_block_size_x)){
  677. return internal_data[ j + cur_block_size_y*i ];
  678. }
  679.  
  680. //external data
  681. //OX
  682. if((j >= 0) && (j < cur_block_size_y)){
  683.  
  684. if (i == -1)
  685. return external_data[ 0 ][ j ];
  686.  
  687. if (i == cur_block_size_x)
  688. return external_data[ 1 ][ j ];
  689.  
  690. }
  691.  
  692. //OY
  693. if((i >= 0) && (i < cur_block_size_x)){
  694.  
  695. if (j == -1)
  696. return external_data[ 2 ][ i ];
  697. if (j == cur_block_size_y)
  698. return external_data[ 3 ][ i ];
  699.  
  700. }
  701.  
  702. cout << "[ERROR]: bad local index" << endl;
  703.  
  704. return nan("");
  705. }
  706.  
  707. void SetLocalIndex(int i, int j, double v){
  708. if ((j >= 0) && (j < cur_block_size_y) && (i >= 0) && (i < cur_block_size_x)){
  709. internal_data[ j + cur_block_size_y*i ] = v;
  710. }else{
  711. cout << "[ERROR]: trying to set data outside the local area" << endl;
  712. }
  713. }
  714.  
  715. double CompareWithExact() {
  716.  
  717. double local_diff_norm = 0.0;
  718. double global_diff_norm = 0.0;
  719. /*
  720. if (my_rank == 0)
  721. cout << "[INFO]: Starting computing compare with exact" << endl;
  722. */
  723. for (int i = 0; i < cur_block_size_x; ++i){
  724. for (int j = 0; j < cur_block_size_y; ++j){
  725.  
  726.  
  727. double rho = 1.0;
  728.  
  729. int current_node_global_offset_x = GetGlobalX(i),
  730. current_node_global_offset_y = GetGlobalY(j);
  731.  
  732. int glob_x = current_node_global_offset_x,
  733. glob_y = current_node_global_offset_y;
  734.  
  735. switch (IsNodeInternalCornerOrSide(glob_x, glob_y)){
  736. case 2:
  737. case 4:
  738. case 6:
  739. case 8:
  740. //angle
  741. rho = 0.25;
  742. break;
  743. case 1:
  744. case 3:
  745. case 5:
  746. case 7:
  747. //side
  748. rho = 0.5;
  749. break;
  750. case 0:
  751. //internal
  752. rho = 1.0;
  753. break;
  754. default:
  755. cout << "[ERROR]: Bad global coords compute exact. Local:" << i << " " << j << ". Global:" << glob_x << " " << glob_y <<endl;
  756. }
  757.  
  758. double tmp_elem = Get(glob_x, glob_y) - GetNodeFromExact(glob_x, glob_y);
  759.  
  760. //local_diff_norm = max( fabs(tmp_elem), local_diff_norm);
  761.  
  762. local_diff_norm += rho * pow(tmp_elem, 2) * h_x * h_y;
  763.  
  764. }
  765. }
  766.  
  767. //cout << "[INFO]: local max diff in " << cur_block_global_offset_x << " " << cur_block_global_offset_y << " " << local_diff_norm << endl;
  768.  
  769. MPI_Allreduce(&local_diff_norm, &global_diff_norm, 1, MPI_DOUBLE, MPI_SUM,
  770. MPI_COMM_WORLD);
  771.  
  772. global_diff_norm = sqrt(global_diff_norm);
  773.  
  774. return global_diff_norm;
  775. }
  776. };
  777.  
  778.  
  779.  
  780.  
  781. int main(int argc, char* argv[]){
  782.  
  783. const double x_left = -2, x_right = 3;
  784. const double y_bottom = -1, y_top = 4;
  785.  
  786. double time_start, time_stop;
  787. double loc_t1, loc_t2;
  788. int N, Gx, Gy;
  789. int dim[2], period[2], reorder;
  790.  
  791. MPI_Comm comm;
  792.  
  793. //N - global grid size
  794. N = atoi(argv[1]);
  795.  
  796. //Gx
  797. Gx = dim[0] = atoi(argv[2]);
  798.  
  799. //Gy
  800. Gy = dim[1] = atoi(argv[3]);
  801.  
  802. period[0]=0;
  803. period[1]=0;
  804.  
  805.  
  806. MPI_Init(&argc, &argv);
  807.  
  808. time_start = MPI_Wtime();
  809.  
  810. int world_size;
  811.  
  812. int my_rank;
  813.  
  814. MPI_Comm_rank(MPI_COMM_WORLD, &my_rank);
  815. MPI_Comm_size(MPI_COMM_WORLD, &world_size);
  816.  
  817.  
  818. if(my_rank == 0){
  819. cout << "[INFO]: N = " << N << endl;
  820. cout << "[INFO]: Gx = " << dim[0] << endl;
  821. cout << "[INFO]: Gy = " << dim[1] << endl;
  822. }
  823.  
  824. if(argc <= 3){
  825. if(my_rank == 0)
  826. cout << "[ERROR]: Usage: mpieval <N> <Gx> <Gy>" << endl;
  827.  
  828. MPI_Abort(MPI_COMM_WORLD, 1);
  829. }
  830.  
  831. if(Gx * Gy != world_size){
  832. if(my_rank == 0)
  833. cout << "[ERROR]: mpi world size is not equal to "<< Gx << "*" << Gy << endl;
  834.  
  835. MPI_Abort(MPI_COMM_WORLD, 1);
  836. }
  837.  
  838. MPI_Cart_create(MPI_COMM_WORLD, 2, dim, period, 1, &comm);
  839.  
  840. if(my_rank == 0)
  841. cout << "[INFO]: Cart created"<<endl;
  842.  
  843. MPI_Comm_rank(comm, &my_rank);
  844.  
  845. int my_coords[2];
  846.  
  847. MPI_Cart_coords(comm, my_rank, 2, my_coords);
  848.  
  849.  
  850.  
  851. class MPIComputations w_func(N, N, Gx, Gy, x_left, x_right, y_bottom, y_top, my_coords[0], my_coords[1], my_rank, comm);
  852.  
  853.  
  854.  
  855. if ( my_rank == 0 ){
  856. cout << "[INFO]: Running" << endl;
  857. }
  858.  
  859. int iteration_num = 0;
  860.  
  861. bool should_i_stop = false;
  862.  
  863. while ( should_i_stop != true ){
  864. if ( (my_rank == 0) && (iteration_num % 10000 == 0) ){
  865. cout << "[INFO]: Iteration " << iteration_num << endl;
  866. }
  867.  
  868. w_func.DoIteration(should_i_stop);
  869.  
  870. iteration_num++;
  871. }
  872.  
  873. MPI_Barrier(MPI_COMM_WORLD);
  874.  
  875. double comparing = w_func.CompareWithExact();
  876.  
  877. if (my_rank == 0)
  878. cout << "[INFO]: Diff with exact solution: " << comparing << endl;
  879.  
  880.  
  881.  
  882. time_stop = MPI_Wtime();
  883. if( my_rank == 0 )
  884. cout << "Finished!" << endl
  885. << "Total iterations: " << iteration_num << endl
  886. << "Elapsed time: " << (time_stop - time_start) << endl
  887. << "Time per iteration: " << (time_stop - time_start) / double(iteration_num) << endl;
  888.  
  889. MPI_Finalize();
  890.  
  891. return 0;
  892. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement