| | 382 | #ifdef _CIVL |
| | 383 | #include <civlc.cvh> |
| | 384 | #endif |
| | 385 | /* wave1dBad.c: A bad wave1d.c program. It never intiate the ghost |
| | 386 | * cells of u_next to zero which is never been covered when cycling |
| | 387 | * pointers. Runing this mpi program can hardly find the bug because |
| | 388 | * the ghost cells are allocated from memory which will be zero if that |
| | 389 | * memory space is not dirty. |
| | 390 | * To execute: mpicc wave1d.c ; mpiexec -n 4 ./a.out Or |
| | 391 | * replace "4" with however many procs you want to use. To verify: |
| | 392 | * civl verify wave1d.c |
| | 393 | */ |
| | 394 | #include <stdio.h> |
| | 395 | #include <stdlib.h> |
| | 396 | #include <string.h> |
| | 397 | #include <assert.h> |
| | 398 | #include <math.h> |
| | 399 | #include <mpi.h> |
| | 400 | |
| | 401 | #define SQR(x) ((x)*(x)) |
| | 402 | #define OWNER(index) ((nprocs*(index+1)-1)/nx) |
| | 403 | |
| | 404 | /* MPI message tags */ |
| | 405 | #define FROMLEFT 1 |
| | 406 | #define FROMRIGHT 2 |
| | 407 | #define DATAPASS 3 |
| | 408 | |
| 406 | | ... |
| | 440 | |
| | 441 | /* Returns the global index of the first cell owned |
| | 442 | * by the process with given rank */ |
| | 443 | int firstForProc(int rank) { |
| | 444 | return (rank*nx)/nprocs; |
| | 445 | } |
| | 446 | |
| | 447 | /* Returns the number of cells the given process owns */ |
| | 448 | int countForProc(int rank) { |
| | 449 | int a = firstForProc(rank); |
| | 450 | int b = firstForProc(rank + 1); |
| | 451 | |
| | 452 | return b - a; |
| | 453 | } |
| | 454 | |
| | 455 | #ifndef _CIVL |
| | 456 | |
| | 457 | /* Some particular initial condition for testing only */ |
| | 458 | void init(int first, int nxl) { |
| | 459 | int i; |
| | 460 | double e = exp(1.0); |
| | 461 | |
| | 462 | for(i = 1; i < nxl+1; i++) { |
| | 463 | int idx = first + i - 1; |
| | 464 | |
| | 465 | if(idx == 1 || idx >= width_init) |
| | 466 | u_prev[i] = 0.0; |
| | 467 | else |
| | 468 | u_prev[i] = height_init * e * |
| | 469 | exp(-1.0/(1-SQR(2.0*(idx-width_init/2.0)/width_init))); |
| | 470 | } |
| | 471 | } |
| | 472 | |
| | 473 | #endif |
| | 474 | |
| 429 | | ... |
| | 497 | int i, j; |
| | 498 | |
| | 499 | #ifndef _CIVL |
| | 500 | |
| | 501 | nx = 50; |
| | 502 | c = 0.3; |
| | 503 | height_init = 10; |
| | 504 | width_init = 10; |
| | 505 | nsteps = 500; |
| | 506 | wstep = 5; |
| | 507 | |
| | 508 | #endif |
| | 509 | |
| | 510 | assert(nx >= 2); |
| | 511 | assert(c > 0); |
| | 512 | assert(nsteps >= 1); |
| | 513 | assert(wstep >= 1 && wstep <= nsteps); |
| | 514 | k = c * c; |
| | 515 | printf("Wave1d with nx=%d, c=%f, nsteps=%d, wstep=%d\n", nx, c, nsteps, wstep); |
| | 516 | |
| | 517 | #ifdef _CIVL |
| | 518 | |
| | 519 | // If in CIVL verification mode and rank is 0, |
| | 520 | // do a sequential run and store result in "oracle" |
| | 521 | // for comparison later |
| | 522 | if(rank == 0) { |
| | 523 | // sets constant boundaries for first string and |
| | 524 | // it's virtual previous string |
| | 525 | oracle[0][0] = 0; |
| | 526 | oracle[0][nx + 1] = 0; |
| | 527 | // initialization for first string and |
| | 528 | // it's virtual previous string |
| | 529 | for(i = 1; i < nx + 1; i++) { |
| | 530 | oracle[0][i] = u_init[i - 1]; |
| | 531 | oracle[1][i] = u_init[i - 1]; |
| | 532 | } |
| | 533 | for(i = 1; i < nsteps; i++){ |
| | 534 | oracle[i][0] = 0; |
| | 535 | oracle[i][nx + 1] = 0; |
| | 536 | // update |
| | 537 | for (j = 1; j < nx + 1; j++) |
| | 538 | oracle[i+1][j] = 2.0*oracle[i][j] - oracle[i-1][j] + |
| | 539 | k*(oracle[i][j+1] + oracle[i][j-1] -2.0*oracle[i][j]); |
| | 540 | } |
| | 541 | } |
| | 542 | |
| | 543 | #endif |
| | 544 | |
| 470 | | ... |
| | 588 | |
| | 589 | /* receives data from other processes and wirte frames */ |
| | 590 | void write_frame (int time) { |
| | 591 | if(rank == 0) { |
| | 592 | double buf[nx + 2]; |
| | 593 | MPI_Status status; |
| | 594 | |
| | 595 | printf("\n======= Time %d =======\n", time); |
| | 596 | printData(time, first, nxl, &u_curr[1]); |
| | 597 | for(int i=1; i < nprocs; i++) { |
| | 598 | int displ = firstForProc(i); |
| | 599 | int count; |
| | 600 | |
| | 601 | MPI_Recv(buf, nx, MPI_DOUBLE, i, DATAPASS, MPI_COMM_WORLD, &status); |
| | 602 | MPI_Get_count(&status, MPI_DOUBLE, &count); |
| | 603 | printData(time, displ, count, buf); |
| | 604 | } |
| | 605 | printf("\n"); |
| | 606 | } else |
| | 607 | MPI_Send(&u_curr[1], nxl, MPI_DOUBLE, 0, DATAPASS, MPI_COMM_WORLD); |
| | 608 | } |