diff --git a/exercise3/wave_1d_parallel.c b/exercise3/wave_1d_parallel.c index d81c084..275a7bf 100644 --- a/exercise3/wave_1d_parallel.c +++ b/exercise3/wave_1d_parallel.c @@ -53,6 +53,8 @@ real_t // Save the present time step in a numbered file under 'data/'. void domain_save(int_t step) { // BEGIN: T8 + if (comm_rank != ROOT) + return; char filename[256]; sprintf(filename, "data/%.5ld.dat", step); FILE *out = fopen(filename, "wb"); @@ -67,12 +69,13 @@ void domain_save(int_t step) { // and set the time step. void domain_initialize(void) { // BEGIN: T3 - buffers[0] = malloc((N + 2) * sizeof(real_t)); - buffers[1] = malloc((N + 2) * sizeof(real_t)); - buffers[2] = malloc((N + 2) * sizeof(real_t)); + const int_t bufsize = (comm_rank == ROOT ? N : n + 2); + buffers[0] = malloc(bufsize * sizeof(real_t)); + buffers[1] = malloc(bufsize * sizeof(real_t)); + buffers[2] = malloc(bufsize * sizeof(real_t)); - for (int_t i = 0; i < N; i++) { - U_prv(i) = U(i) = cos(2 * M_PI * i / (real_t)N); + for (int_t i = 0; i < n; i++) { + U_prv(i) = U(i) = cos(2 * M_PI * (i + offset) / (real_t)N); } // END: T3 @@ -99,7 +102,7 @@ void move_buffer_window(void) { // Derive step t+1 from steps t and t-1. void time_step(void) { // BEGIN: T4 - for (int_t i = 0; i < N; i++) { + for (int_t i = 0; i < n; i++) { U_nxt(i) = -U_prv(i) + 2.0 * U(i) + (dt * dt * c * c) / (dx * dx) * (U(i - 1) + U(i + 1) - 2.0 * U(i)); } // END: T4 @@ -109,8 +112,12 @@ void time_step(void) { // Neumann (reflective) boundary condition. void boundary_condition(void) { // BEGIN: T6 - U(-1) = U(1); - U(N) = U(N - 2); + if (comm_rank == ROOT) { + U(-1) = U(1); + } + if (comm_rank == comm_size - 1) { + U(n) = U(n - 2); + } // END: T6 } @@ -118,7 +125,16 @@ void boundary_condition(void) { // Communicate the border between processes. void border_exchange(void) { // BEGIN: T5 - ; + int left = (comm_size + comm_rank - 1) % comm_size; + int right = (comm_rank + 1) % comm_size; + + MPI_Sendrecv(&U(n - 1), 1, MPI_DOUBLE, right, 0, + &U(-1), 1, MPI_DOUBLE, left, 0, + MPI_COMM_WORLD, MPI_STATUS_IGNORE); + + MPI_Sendrecv(&U(0), 1, MPI_DOUBLE, left, 1, + &U(n), 1, MPI_DOUBLE, right, 1, + MPI_COMM_WORLD, MPI_STATUS_IGNORE); // END: T5 } @@ -127,7 +143,16 @@ void border_exchange(void) { // to root and assemble it in the root buffer void send_data_to_root() { // BEGIN: T7 - ; + if (comm_rank != ROOT) { + MPI_Send(&U(0), n, MPI_DOUBLE, ROOT, 0, MPI_COMM_WORLD); + } else { + int offset = n; + for (int i = 1; i < comm_size; i++) { + int proc_n = N / comm_size + (i < N % comm_size); + MPI_Recv(&U(offset), proc_n, MPI_DOUBLE, i, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE); + offset += proc_n; + } + } // END: T7 } @@ -170,7 +195,17 @@ int main(int argc, char **argv) { // TASK: T2 // Time your code // BEGIN: T2 + if (comm_rank == ROOT) + gettimeofday(&t_start, NULL); simulate(); + MPI_Barrier(MPI_COMM_WORLD); + + if (comm_rank == ROOT) { + gettimeofday(&t_end, NULL); + + printf("Total elapsed time: %lf seconds\n", + WALLTIME(t_end) - WALLTIME(t_start)); + } // END: T2 domain_finalize();