Advertisement
manac68974

Untitled

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