Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <mpi.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <math.h>
- #include <iostream>
- int main(int argc, char *argv[])
- {
- const int N = 100;
- const double eps = 0.001;
- int ProcNum, ProcRank, tmp;
- MPI_Status status;
- MPI_Init(&argc, &argv);
- MPI_Comm_size(MPI_COMM_WORLD, &ProcNum);
- MPI_Comm_rank(MPI_COMM_WORLD, &ProcRank);
- if (ProcNum == 1) {
- std::cout << "Use non-parallel version" << std::endl;
- MPI_Finalize();
- return -1;
- }
- int range_size;
- int range_start;
- int rows_num = N / ProcNum;
- int global_start = rows_num * ProcRank;
- if (ProcRank == 0) {
- range_start = 0;
- range_size = rows_num + 1;
- }
- else {
- //All except #0 store a previous line
- range_start = 1;
- if (ProcRank < ProcNum - 1) {
- //All except last store additionall next line
- range_size = rows_num + 2;
- }
- else {
- range_size = N - rows_num * (ProcNum - 1) + 1;
- }
- }
- std::cerr << ProcRank << ": " << range_size << "\n";
- double** u = (double**) malloc(range_size * sizeof(double*));
- for (int i = 0; i < range_size; ++i) {
- u[i] = (double*) malloc(N * sizeof(double));
- }
- //init inner values, calloc is not used because initial values can be non-zero
- for (int i = 0; i < range_size; ++i) {
- for (int j = 0; j < N; ++j) {
- u[i][j] = 0;
- }
- }
- //init boundary values
- if (ProcRank == 0) {
- for (int i = 0; i < N; ++i) {
- u[0][i] = 100.0 - 200.0 * (double) i / (double) N;
- }
- }
- if (ProcRank == ProcNum - 1) {
- for (int i = 0; i < N; ++i) {
- u[range_size - 1][i] = -100.0 + 200.0 * (double) i / (double) N;
- }
- }
- for (int i = 0; i < range_size; ++i) {
- int global_i = global_start - range_start + i;
- u[i][0] = 100 - 200.0 * (double) global_i / (double) N;
- u[i][N - 1] = -100 + 200.0 * (double) global_i / (double) N;
- }
- double max_d = 0;
- int is_finished = 0;
- while (is_finished == 0) {
- max_d = 0;
- for (int i = range_start + 1; i < range_size - 1; ++i) {
- for (int j = 1; j < N - 1; ++j) {
- double u_prev = u[i][j];
- u[i][j] = 0.25 * (u[i - 1][j] + u[i + 1][j] + u[i][j - 1] + u[i][j + 1]);
- max_d = std::max(max_d, fabs(u_prev - u[i][j]));
- }
- }
- if (ProcRank < ProcNum - 1) {
- MPI_Send(u[range_size - 2], N, MPI_DOUBLE, ProcRank + 1, 0, MPI_COMM_WORLD);
- //std::cout << "#" << ProcRank << " sends u[range_size - 1] = " << u[range_size - 1] << std::endl;
- }
- if (ProcRank > 0) {
- MPI_Recv(u[0], N, MPI_DOUBLE, ProcRank - 1, 0, MPI_COMM_WORLD, &status);
- //std::cout << "#" << ProcRank << " receives start_val = " << starting_val << std::endl;
- for (int j = 1; j < N - 1; ++j) {
- double u_prev = u[1][j];
- u[1][j] = 0.25 * (u[0][j] + u[2][j] + u[1][j - 1] + u[1][j + 1]);
- max_d = std::max(max_d, fabs(u_prev - u[1][j]));
- }
- MPI_Send(u[1], N, MPI_DOUBLE, ProcRank - 1, 0, MPI_COMM_WORLD);
- //std::cout << "#" << ProcRank << " sends u[0] = " << u[0] << std::endl;
- }
- if (ProcRank < ProcNum - 1) {
- MPI_Recv(u[range_size - 1], N, MPI_DOUBLE, ProcRank + 1, 0, MPI_COMM_WORLD, &status);
- //std::cout << "#" << ProcRank << " receives u[range_size] = " << u[range_size] << std::endl;
- }
- if (ProcRank == 0){
- double d = 0;
- for (int i = 1; i < ProcNum; i++) {
- MPI_Recv(&d, 1, MPI_DOUBLE, MPI_ANY_SOURCE, 0, MPI_COMM_WORLD, &status);
- max_d = std::max(max_d, d);
- }
- is_finished = max_d < eps ? 1 : 0;
- for (int i = 1; i < ProcNum; i++) {
- MPI_Send(&is_finished, 1, MPI_INT, i, 0, MPI_COMM_WORLD);
- }
- }
- else {
- MPI_Send(&max_d, 1, MPI_DOUBLE, 0, 0, MPI_COMM_WORLD);
- MPI_Recv(&is_finished, 1, MPI_INT, 0, 0, MPI_COMM_WORLD, &status);
- }
- }
- if (ProcRank == 0) {
- double ** m = (double**) malloc(N * sizeof(double*));
- std::cout << max_d << std::endl;
- for (int i =0; i < rows_num; ++i) {
- m[i] = u[i + range_start];
- }
- for (int n = 1; n < ProcNum; ++n) {
- int size;
- MPI_Recv(&size, 1, MPI_INT, n, 0, MPI_COMM_WORLD, &status);
- for (int i = 0; i < size; ++i) {
- m[rows_num * n + i] = (double*) malloc(N * sizeof(double));
- MPI_Recv(m[rows_num * n + i], N, MPI_DOUBLE, n, 0, MPI_COMM_WORLD, &status);
- }
- }
- for (int i = 0; i < N; ++i) {
- for (int j = 0; j < N; ++j) {
- std::cout << m[i][j] << "\t";
- }
- std::cout << std::endl;
- }
- }
- else if (ProcRank < ProcNum - 1) {
- MPI_Send(&rows_num, 1, MPI_INT, 0, 0, MPI_COMM_WORLD);
- for (int i = 0; i < rows_num; ++i) {
- MPI_Send(u[i + range_start], N, MPI_DOUBLE, 0, 0, MPI_COMM_WORLD);
- }
- }
- else {
- int size = range_size - range_start;
- MPI_Send(&size, 1, MPI_INT, 0, 0, MPI_COMM_WORLD);
- for (int i = range_start; i < range_size; ++i) {
- MPI_Send(u[i], N, MPI_DOUBLE, 0, 0, MPI_COMM_WORLD);
- }
- }
- MPI_Finalize();
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement