Advertisement
Guest User

Untitled

a guest
Feb 9th, 2016
47
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 5.61 KB | None | 0 0
  1. #include <mpi.h>
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <math.h>
  5. #include <iostream>
  6.  
  7.  
  8. int main(int argc, char *argv[])
  9. {
  10.     const int N = 100;
  11.     const double eps = 0.001;
  12.    
  13.     int ProcNum, ProcRank, tmp;
  14.     MPI_Status status;
  15.     MPI_Init(&argc, &argv);
  16.     MPI_Comm_size(MPI_COMM_WORLD, &ProcNum);
  17.     MPI_Comm_rank(MPI_COMM_WORLD, &ProcRank);
  18.  
  19.     if (ProcNum == 1) {
  20.         std::cout << "Use non-parallel version" << std::endl;
  21.         MPI_Finalize();
  22.         return -1;
  23.     }
  24.  
  25.     int range_size;
  26.     int range_start;
  27.     int rows_num = N / ProcNum;
  28.     int global_start = rows_num * ProcRank;
  29.    
  30.     if (ProcRank == 0) {
  31.         range_start = 0;
  32.         range_size = rows_num + 1;
  33.     }
  34.     else {
  35.         //All except #0 store a previous line
  36.         range_start = 1;
  37.  
  38.         if (ProcRank < ProcNum - 1) {
  39.             //All except last store additionall next line
  40.             range_size = rows_num + 2;
  41.         }
  42.         else {
  43.             range_size = N - rows_num * (ProcNum - 1) + 1;
  44.         }
  45.     }
  46.     std::cerr << ProcRank << ": " << range_size << "\n";
  47.  
  48.  
  49.     double** u = (double**) malloc(range_size * sizeof(double*));
  50.     for (int i = 0; i < range_size; ++i) {
  51.         u[i] = (double*) malloc(N * sizeof(double));
  52.     }
  53.  
  54.     //init inner values, calloc is not used because initial values can be non-zero
  55.     for (int i = 0; i < range_size; ++i) {
  56.         for (int j = 0; j < N; ++j) {
  57.             u[i][j] = 0;
  58.         }
  59.     }
  60.  
  61.     //init boundary values
  62.     if (ProcRank == 0) {
  63.         for (int i = 0; i < N; ++i) {
  64.             u[0][i] =  100.0 - 200.0 * (double) i / (double) N;
  65.         }
  66.     }
  67.     if (ProcRank == ProcNum - 1) {
  68.         for (int i = 0; i < N; ++i) {
  69.             u[range_size - 1][i] = -100.0 + 200.0 * (double) i / (double) N;
  70.         }
  71.     }
  72.  
  73.     for (int i = 0; i < range_size; ++i) {
  74.         int global_i = global_start - range_start + i;
  75.         u[i][0]     =  100 - 200.0 * (double) global_i / (double) N;
  76.         u[i][N - 1] = -100 + 200.0 * (double) global_i / (double) N;
  77.     }
  78.  
  79.  
  80.     double max_d = 0;
  81.     int is_finished = 0;
  82.  
  83.     while (is_finished == 0) {
  84.         max_d = 0;
  85.  
  86.         for (int i = range_start + 1; i < range_size - 1; ++i) {
  87.             for (int j = 1; j < N - 1; ++j) {
  88.                 double u_prev = u[i][j];
  89.                 u[i][j] = 0.25 * (u[i - 1][j] + u[i + 1][j] + u[i][j - 1] + u[i][j + 1]);
  90.                 max_d = std::max(max_d, fabs(u_prev - u[i][j]));
  91.             }
  92.         }
  93.  
  94.        if (ProcRank < ProcNum - 1) {
  95.             MPI_Send(u[range_size - 2], N, MPI_DOUBLE, ProcRank + 1, 0, MPI_COMM_WORLD);
  96.             //std::cout << "#" << ProcRank << " sends u[range_size - 1] = " << u[range_size - 1] << std::endl;
  97.         }
  98.  
  99.         if (ProcRank > 0) {
  100.             MPI_Recv(u[0], N, MPI_DOUBLE, ProcRank - 1, 0, MPI_COMM_WORLD, &status);
  101.             //std::cout << "#" << ProcRank << " receives start_val = " << starting_val << std::endl;
  102.             for (int j = 1; j < N - 1; ++j) {
  103.                 double u_prev = u[1][j];
  104.                 u[1][j] = 0.25 * (u[0][j] + u[2][j] + u[1][j - 1] + u[1][j + 1]);
  105.                 max_d = std::max(max_d, fabs(u_prev - u[1][j]));
  106.             }
  107.             MPI_Send(u[1], N, MPI_DOUBLE, ProcRank - 1, 0, MPI_COMM_WORLD);
  108.             //std::cout << "#" << ProcRank << " sends u[0] = " <<  u[0] << std::endl;
  109.         }
  110.  
  111.         if (ProcRank < ProcNum - 1) {
  112.             MPI_Recv(u[range_size - 1], N, MPI_DOUBLE, ProcRank + 1, 0, MPI_COMM_WORLD, &status);
  113.             //std::cout << "#" << ProcRank << " receives u[range_size] = " << u[range_size] << std::endl;
  114.         }
  115.  
  116.         if (ProcRank == 0){
  117.             double d = 0;
  118.             for (int i = 1; i < ProcNum; i++) {
  119.                 MPI_Recv(&d, 1, MPI_DOUBLE, MPI_ANY_SOURCE, 0, MPI_COMM_WORLD, &status);
  120.                 max_d = std::max(max_d, d);
  121.             }
  122.             is_finished = max_d < eps ? 1 : 0;
  123.             for (int i = 1; i < ProcNum; i++) {
  124.                 MPI_Send(&is_finished, 1, MPI_INT, i, 0, MPI_COMM_WORLD);
  125.             }
  126.         }
  127.         else {
  128.             MPI_Send(&max_d, 1, MPI_DOUBLE, 0, 0, MPI_COMM_WORLD);
  129.             MPI_Recv(&is_finished, 1, MPI_INT, 0, 0, MPI_COMM_WORLD, &status);
  130.         }
  131.     }
  132.  
  133.    
  134.     if (ProcRank == 0) {
  135.         double ** m = (double**) malloc(N * sizeof(double*));
  136.         std::cout << max_d << std::endl;
  137.         for (int i =0; i < rows_num; ++i) {
  138.             m[i] = u[i + range_start];
  139.         }
  140.  
  141.        for (int n = 1; n < ProcNum; ++n) {
  142.             int size;
  143.             MPI_Recv(&size, 1, MPI_INT, n, 0, MPI_COMM_WORLD, &status);
  144.             for (int i = 0; i < size; ++i) {
  145.                 m[rows_num * n + i] = (double*) malloc(N * sizeof(double));
  146.                 MPI_Recv(m[rows_num * n + i], N, MPI_DOUBLE, n, 0, MPI_COMM_WORLD, &status);
  147.             }
  148.         }
  149.  
  150.         for (int i = 0; i < N; ++i) {
  151.             for (int j = 0; j < N; ++j) {
  152.                 std::cout << m[i][j] << "\t";
  153.             }
  154.             std::cout << std::endl;
  155.         }
  156.  
  157.     }
  158.     else  if (ProcRank < ProcNum - 1) {
  159.         MPI_Send(&rows_num, 1, MPI_INT, 0, 0, MPI_COMM_WORLD);
  160.         for (int i = 0; i < rows_num; ++i) {
  161.             MPI_Send(u[i + range_start], N, MPI_DOUBLE, 0, 0, MPI_COMM_WORLD);
  162.         }
  163.     }
  164.     else {
  165.         int size = range_size - range_start;
  166.         MPI_Send(&size, 1, MPI_INT, 0, 0, MPI_COMM_WORLD);
  167.         for (int i = range_start; i < range_size; ++i) {
  168.             MPI_Send(u[i], N, MPI_DOUBLE, 0, 0, MPI_COMM_WORLD);
  169.         }
  170.     }
  171.    
  172.     MPI_Finalize();
  173.     return 0;
  174. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement