Changes between Version 7 and Version 8 of Tour


Ignore:
Timestamp:
09/21/18 10:53:44 (8 years ago)
Author:
wuwenhao
Comment:

--

Legend:

Unmodified
Added
Removed
Modified
  • Tour

    v7 v8  
    380380
    381381{{{
     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
    382409/* Input parameters */
    383410#ifdef _CIVL
     411
    384412$input int NXB = 5;               /* upper bound on nx */
    385413$input int nx;                    /* number of discrete points including endpoints */
     
    391419$assume(0 < nsteps && nsteps <= NSTEPSB);
    392420$input int wstep = 1;             /* number of time steps between printing */
     421$input int _NPROCS_LOWER_BOUND = 1;
     422$input int _NPROCS_UPPER_BOUND = 4;
    393423double oracle[nsteps + 1][nx + 2];/* result of sequential run at every time step */
    394424$input double u_init[nx];         /* arbitrary initial position of string */
    395 ...
     425
    396426#else
    397 ...
     427
     428int nx, height_init, width_init;
     429int nsteps, wstep;
     430double c;
     431
    398432#endif
    399433
     
    404438int first;                       /* global index of first cell owned by this process */
    405439int left, right;                 /* ranks of left neighbor and right neighbor */
    406 ...
     440
     441/* Returns the global index of the first cell owned
     442 * by the process with given rank */
     443int firstForProc(int rank) {
     444  return (rank*nx)/nprocs;     
     445}
     446
     447/* Returns the number of cells the given process owns */
     448int 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 */
     458void 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
    407475/* Update cells owned by processes */
    408476void update() {
     
    427495 */
    428496void initialization() {
    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
    430545  nxl = countForProc(rank);
    431546  first = firstForProc(rank);
     
    454569}
    455570
    456 ...
    457571/* Print out the value of data cells;
    458572   Do comparison in CIVL mode */
    459573void printData (int time, int first, int length, double * buf) {
    460   for(int i = 0; i < length; i++){
     574  int i;
     575
     576  for(i = 0; i < length; i++){
    461577    printf("u_curr[%d]=%8.8f   ", first + i, buf[i]);
    462578#ifdef _CIVL
     
    465581    "Error: disagreement at time %d position %d: saw %lf, expected %lf", \
    466582    time, first + i, buf[i], oracle[time + 1][first + i + 1]);
     583
    467584#endif
     585    printf("\n");
    468586  }
    469587}
    470 ...
     588
     589/* receives data from other processes and wirte frames */
     590void 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}
    471609
    472610/* Exchanging ghost cells */
     
    481619  int iter;
    482620
     621
     622#ifdef _CIVL
     623
     624  // elaborate nx to concrete value...
     625  $elaborate(nx);
     626
     627#endif
    483628  MPI_Init(&argc, &argv);
    484629  MPI_Comm_rank(MPI_COMM_WORLD, &rank);
    485630  MPI_Comm_size(MPI_COMM_WORLD, &nprocs);
    486631  initialization();
    487   ...
     632#ifdef _CIVL
     633
     634  if(nxl != 0) {
     635    memcpy(&u_curr[1], &u_init[first], sizeof(double) * nxl);
     636    memcpy(&u_prev[1], &u_curr[1], sizeof(double) * nxl);
     637  }
     638
     639#else
     640
     641  if(nxl != 0) {
     642    init(first, nxl);
     643    memcpy(&u_curr[1], &u_prev[1], nxl * sizeof(double));
     644  }
     645
     646#endif
    488647  for(iter = 0; iter < nsteps; iter++) {
    489648    if(iter % wstep == 0)
     
    499658  MPI_Finalize();
    500659  return 0;
    501 }               
     660}
    502661
    503662}}}