#include #include #ifdef PLOT #include #include FILE *plot_file; #define PLOT_VALUE 1 #define PLOT_ERROR 2 #define PLOT_RESIDUAL 3 static long plot_type = 0; /* 0 means no plot */ #endif #include "sndrcv.h" #if defined(DELTA) || defined(IPSC) #define htonl(a) (a) #endif #if !defined(AIX) extern char *malloc(); #endif extern void exit(); #define MAX(a,b) (((a)>(b)) ? (a) : (b)) #define MIN(a,b) (((a)<(b)) ? (a) : (b)) #define ABS(a) (((a)>=0 ) ? (a) : -(a)) #define LO -3.1415926535 /* Phsyical dimensions */ #define HI 3.1415926535 double scale; /* Physical mesh grain */ long P, ncol_P, nrow_P; /* P = No. of processes = ncol_P * nrow_P */ long my_col_P, my_row_P; /* Co-ords of this proc. in grid of processes*/ double *buffer; /* Buffer used for exchanging rows */ long north, south, east, west; /* No. of process in that direction on process grid or -1 if no-one there */ long col_low = 0; /* Grid co-ords of top left corner */ long row_low = 0; /* Mapping from GLOBAL grid index to physical coordinates */ #define MAPCOL(I) (scale*((double) (I+col_low)) + LO) #define MAPROW(J) (scale*((double) (J+row_low)) + LO) long cs_exchange = 0; /* Timing information */ long cs_global = 0; long cs_interpolate = 0; long cs_plot = 0; long cs_total = 0; /* void ZeroGrid(grid, ncols, nrows) double **grid; long ncols, nrows; { long i,j; for (i=0; i<=ncols; i++) for (j=0; j<=nrows; j++) grid[i][j] = 0.0; } */ double Solution(x,y) double x,y; /* Model potential that defines solution and boundary conditions. This particular choice makes the discretization error quite apparent. */ { /* return cos(x)*exp(-y) + 0.1*sin(2.*x)*exp(-2.*y) + 0.1*cos(3.*x)*exp(-3.*y); */ return 0.5 * (cos(x)*exp(-y) + cos(y)*exp(-x) + 0.1*(sin(2.*x)*exp(-2.*y) + sin(2.*y)*exp(-2.*x)) + 0.1*(cos(3.*x)*exp(-3.*y) + cos(3.*y)*exp(-3.*x))); } double GridError(grid, ncols, nrows, ngrid) long ncols, nrows, ngrid; double **grid; /* Compute mean absolute error at grid points relative to the analytic solution ... error is due to either lack of convergence or discretization error. */ { long i,j, type=9, length=1; long start; double error = 0.0; for (i=1; i= 0) { SND_(&type1, (char *) grid[1], &bnrows, &west, &synch); RCV_(&type2, (char *) grid[0], &bnrows, &lenmes, &west, &nodefrom, &synch); } if (east >= 0) { SND_(&type3, (char *) grid[ncols-1], &bnrows, &east, &synch); RCV_(&type4, (char *) grid[ncols], &bnrows, &lenmes, &east, &nodefrom, &synch); } } else { if (east >= 0) { RCV_(&type1, (char *) grid[ncols], &bnrows, &lenmes, &east, &nodefrom, &synch); SND_(&type2, (char *) grid[ncols-1], &bnrows, &east, &synch); } if (west >= 0) { RCV_(&type3, (char *) grid[0], &bnrows, &lenmes, &west, &nodefrom, &synch); SND_(&type4, (char *) grid[1], &bnrows, &west, &synch); } } if (my_row_P%2) { if (north >= 0) { GATHER(1); SND_(&type5, (char *) buffer, &bncols, &north, &synch); RCV_(&type6, (char *) buffer, &bncols, &lenmes, &north, &nodefrom, &synch); SCATTER(0); } if (south >= 0) { GATHER(nrows-1); SND_(&type7, (char *) buffer, &bncols, &south, &synch); RCV_(&type8, (char *) buffer, &bncols, &lenmes, &south, &nodefrom, &synch); SCATTER(nrows); } } else { if (south >= 0) { RCV_(&type5, (char *) buffer, &bncols, &lenmes, &south, &nodefrom, &synch); SCATTER(nrows); GATHER(nrows-1); SND_(&type6, (char *) buffer, &bncols, &south, &synch); } if (north >= 0) { RCV_(&type7, (char *) buffer, &bncols, &lenmes, &north, &nodefrom, &synch); SCATTER(0); GATHER(1); SND_(&type8, (char *) buffer, &bncols, &north, &synch); } } cs_exchange += MTIME_() - start; } #ifdef PLOT void ClosePlotFile() { if (!plot_type) return; if (NODEID_() == 0) (void) fclose(plot_file); } void OpenPlotFile(maxgrid) long maxgrid; { if (!plot_type) return; if (NODEID_()) return; /* Only node 0 needs to do this */ if (!(plot_file = fopen("plot","w+"))) Error("OpenPlotFile: failed to open plot file", (long) -1); maxgrid = htonl((long) maxgrid); /* For portability */ if (fwrite((char *) &maxgrid, sizeof(int), 1, plot_file) != 1) Error("OpenPlotFile: failed to write maxgrid", (long) -1); (void) fflush(plot_file); } void InsertPlot(plot_full, ngrid, plot_grid, nrows, ncols, col_low, row_low) unsigned char *plot_full, *plot_grid; long ngrid, nrows, ncols, col_low, row_low; { long i, j; long i_lo = (col_low == 0) ? 0 : 1; long j_lo = (row_low == 0) ? 0 : 1; unsigned char *temp; /* Dink around with i_lo, j_lo so that the interior edges in the parallel case are not overwritten with incorrect values */ if (i_lo) plot_grid += nrows; for (i=i_lo; i update red then update black using new reds (gauss-seidel red-black w-relaxation). Return the mean abs. error (value of the laplacian) on the old grid. */ { double residual = 0.0; double omega = 0.94; /* Over relaxation parameter */ long i,j, type=10, length=1, jlo; double *gg, *ggm, *ggp; Exchange(grid, ncols, nrows); /* Update red */ for (i=1; i=0) && (i1<=new_ncols) && (j1>=0) && (j1<=new_nrows) ) new_grid[i1][j1] = old_grid[i][j]; } for (i=1; i<=old_ncols; i++) for (j=1; j<=old_nrows; j++) { i2 = 2*i-1+col_shift; j2 = 2*j-1+row_shift; if ( (i2>=0) && (i2<=new_ncols) && (j2>=0) && (j2<=new_nrows) ) new_grid[i2][j2] = 0.25 * (old_grid[i ][j ] + old_grid[i-1][j-1] + old_grid[i-1][j ] + old_grid[i ][j-1]); } BoundaryConditions(new_grid, new_ncols, new_nrows); Exchange(new_grid, new_ncols, new_nrows); for (i=1; i 0) ? NODEID_()-1 : -1; south = (my_row_P < (nrow_P-1)) ? NODEID_()+1 : -1; east = (my_col_P < (ncol_P-1)) ? NODEID_()+nrow_P : -1; west = (my_col_P > 0) ? NODEID_()-nrow_P : -1; ParseArguments(argc, argv, &maxgrid, &niter, &nprint, &nlevel, &thresh); ngrid1 = MAX(ncol_P,maxgrid>>(nlevel-1)); ngrid1 = MAX(nrow_P,ngrid1); /* Size of first grid */ maxgrid = ngrid1<<(nlevel-1); /* Actual size of final grid */ if (!(buffer = (double *) malloc((unsigned) (sizeof(double)*(maxgrid+1))))) Error("failed to allocate comms buffer", (long) (maxgrid+1)); #ifdef PLOT OpenPlotFile(maxgrid); #endif /* Loop from coarse to fine grids */ for (level=0; level