diff options
author | goodale <goodale@b61c5cb5-eaca-4651-9a7a-d64986f99364> | 1999-11-08 12:27:12 +0000 |
---|---|---|
committer | goodale <goodale@b61c5cb5-eaca-4651-9a7a-d64986f99364> | 1999-11-08 12:27:12 +0000 |
commit | 6624247de16085479957b8d6d85932ab2bf32d8a (patch) | |
tree | 8813a82ba9f749d64dd92ce4b072e8f02350d059 | |
parent | ddc0e18b47c191eef742920d5dcb5943189b1a41 (diff) |
A few more routines fleshed out.
Tom
git-svn-id: http://svn.cactuscode.org/arrangements/CactusPUGH/PUGH/trunk@130 b61c5cb5-eaca-4651-9a7a-d64986f99364
-rw-r--r-- | src/SetupPGV.c | 761 |
1 files changed, 748 insertions, 13 deletions
diff --git a/src/SetupPGV.c b/src/SetupPGV.c index 213855a..8b1c676 100644 --- a/src/SetupPGV.c +++ b/src/SetupPGV.c @@ -13,6 +13,18 @@ static char *rcsid = "$Header$"; #include <stdlib.h> #include <math.h> +/* Stuff to do standalone test */ +#define TEST_SETUPPGV + +#ifdef TEST_SETUPPGV +#define PUGH_NSTAGGER 4 +#define PUGH_NO_STAGGER 0 +#define PUGH_STAGGER 1 +#define PUGH_VERTEXCTR 0 +#define PUGH_FACECTR(i) i+1 +#define CCTK_REAL double +#endif /* TEST_SETUPPGV */ + typedef enum {pgv_none, pgv_scalar, pgv_array, pgv_gf} pgv_type; typedef struct PConnectivity @@ -20,6 +32,7 @@ typedef struct PConnectivity int dim; int *nprocs; int **neighbours; + int periodic; /* Is the system periodic? */ } pConnectivity; typedef struct PGS @@ -31,10 +44,12 @@ typedef struct PGS typedef struct PGExtras { int dim; /* dimension of GF */ + + int *nsize; /* The global size of the array */ + /* Processor group layouts */ CCTK_REAL maxskew; /* Maximum point skew */ - int periodic; /* Is the system periodic? */ - int **lb; /* Lower bound (nprocs X 3) for each proc */ + int **lb; /* Lower bound (nprocs X dim) for each proc */ int **ub; /* Upper bound (same sizes) */ int *lnsize; /* Size on this processor */ int npoints; /* LOCAL number of points on this proc. */ @@ -42,6 +57,7 @@ typedef struct PGExtras int **rnsize; /* [#points on a proc][in each dir] */ /* Ghosts and overlaps. */ + int *nghostzones; /* Width of ghost zone */ int *ownership[PUGH_NSTAGGER][2]; /* The box owned in each direction. */ /* [stagger][min/max][dir] */ @@ -88,7 +104,7 @@ typedef struct PGA MPI_Status ms; #endif - pGExtra *extras; + pGExtras *extras; } pGA; typedef struct PGV @@ -101,17 +117,34 @@ typedef struct PGV pGExtras *pugh_SetupPGExtras(int dim, int periodic, + int staggertype, int *sh, int *nghosts, - int *nprocs) + int total_procs, + int *nprocs, + int this_proc) { + int error; pGExtras *this; this = (pGExtras *)malloc(sizeof(pGExtras)); + /* Setup memory */ if(this) { - pgExtras_SetupBasics(); + error = pugh_SetupPGExtrasMemory(dim, + total_procs, + nprocs, + this); + + if(!error) + { + pugh_SetupPGExtrasSizes (dim, periodic, staggertype, sh, nghosts, + total_procs, nprocs, this_proc,this); + pugh_SetupPGExtrasOwnership(dim, periodic, staggertype, sh, nghosts, + total_procs, nprocs, this_proc, this); + } + } return this; @@ -135,14 +168,15 @@ pGExtras *pugh_SetupPGExtras(int dim, @@*/ pConnectivity *pugh_SetupConnectivity(int dim, int total_procs, - int *nprocs) + int *nprocs, + int periodic) { pConnectivity *this; int i; /* Allocate memory */ - this = (pConnectivity *)malloc(pConnectivity); + this = (pConnectivity *)malloc(sizeof(pConnectivity)); if(this) { @@ -151,15 +185,16 @@ pConnectivity *pugh_SetupConnectivity(int dim, if(this->nprocs && this->neighbours) { - this->neighbours[0] = (int *)malloc(nprocs*2*dim*sizeof(int)); + this->neighbours[0] = (int *)malloc(total_procs*2*dim*sizeof(int)); if(this->neighbours[0]) { - for(i = 1; i < nprocs; i++) + for(i = 1; i < total_procs; i++) { this->neighbours[i] = this->neighbours[0]+(2*dim*i); } + this->periodic = periodic; } else { @@ -188,7 +223,7 @@ pConnectivity *pugh_SetupConnectivity(int dim, pugh_GenerateTopology(dim, total_procs, this->nprocs); - pugh_GenerateNeighbours(dim, total_procs, this->nprocs, this->neighbours); + pugh_GenerateNeighbours(dim, total_procs, this->nprocs, this->neighbours, this->periodic); } @@ -279,12 +314,28 @@ int pugh_GenerateTopology(int dim, int total_procs, int *nprocs) return retval; } -int pugh_GenerateNeighbours(int dim, int total_procs, int *nprocs, int **neighbours) + /*@@ + @routine pugh_GenerateNeighbours + @date Mon Nov 8 08:15:08 1999 + @author Tom Goodale + @desc + Works out the array of neighbouring processors for + every processor. + @enddesc + @calls + @calledby + @history + + @endhistory + +@@*/ +int pugh_GenerateNeighbours(int dim, int total_procs, int *nprocs, int **neighbours, int periodic) { int retval; int i; int idim; int *pos; + int temp; pos = (int *)malloc(dim*sizeof(int)); @@ -292,7 +343,7 @@ int pugh_GenerateNeighbours(int dim, int total_procs, int *nprocs, int **neighbo { for(i = 0; i < total_procs; i++) { - pugh_DecomposeIJK(i,nprocs, pos); + pugh_DecomposeIJK(dim,i,nprocs, pos); for(idim = 0; idim < dim ; idim++) { @@ -301,7 +352,14 @@ int pugh_GenerateNeighbours(int dim, int total_procs, int *nprocs, int **neighbo if(pos[idim] > -1) { - neighbours[i][idim*2] = pugh_ComposeIJK(dim, i, nprocs, pos); + neighbours[i][idim*2] = pugh_ComposeIJK(dim, nprocs, pos); + } + else if(periodic) + { + temp = pos[idim]; + pos[idim] = nprocs[idim]-1; + neighbours[i][idim*2] = pugh_ComposeIJK(dim, nprocs, pos); + pos[idim] = temp; } pos[idim]++; @@ -313,6 +371,13 @@ int pugh_GenerateNeighbours(int dim, int total_procs, int *nprocs, int **neighbo { neighbours[i][idim*2+1] = pugh_ComposeIJK(dim, nprocs, pos); } + else if(periodic) + { + temp = pos[idim]; + pos[idim] = 0; + neighbours[i][idim*2+1] = pugh_ComposeIJK(dim, nprocs, pos); + pos[idim] = temp; + } pos[idim]--; } @@ -325,6 +390,8 @@ int pugh_GenerateNeighbours(int dim, int total_procs, int *nprocs, int **neighbo retval = 1; } + free(pos); + return retval; } @@ -401,3 +468,671 @@ int pugh_ComposeIJK(int dim, return ijk; } + + + /*@@ + @routine pugh_SetupPGExtrasMemory + @date Mon Nov 8 08:16:02 1999 + @author Tom Goodale + @desc + Allocate memory for the members of the pGExtras structure. + @enddesc + @calls + @calledby + @history + + @endhistory + +@@*/ +int pugh_SetupPGExtrasMemory(int dim, + int total_procs, + int *nprocs, + pGExtras *this) +{ + int retcode; + int i,j,k; + + retcode = 0; + + if(this) + { + /* Do it in stages. + * First: things depending on the number of processors + */ + this->lb = (int **)malloc(total_procs*sizeof(int *)); + this->ub = (int **)malloc(total_procs*sizeof(int *)); + this->rnsize = (int **)malloc(total_procs*sizeof(int *)); + this->rnpoints = (int *) malloc(total_procs*sizeof(int)); + + /* Things just depending on dimension */ + this->nghostzones = (int *)malloc(dim*sizeof(int)); + this->nsize = (int *)malloc(dim*sizeof(int)); + this->lnsize = (int *)malloc(dim*sizeof(int)); + + /* Check all the above succeeded and then get memory for + * arrays hanging off the above. + */ + if(this->lb && + this->ub && + this->rnsize && + this->rnpoints && + this->nghostzones && + this->nsize && + this->lnsize) + { + this->lb[0] = (int *)malloc(total_procs *dim*sizeof(int)); + this->ub[0] = (int *)malloc(total_procs *dim*sizeof(int)); + this->rnsize[0] = (int *)malloc(total_procs*2*dim*sizeof(int)); + + if(this->lb[0] && + this->ub[0] && + this->rnsize[0]) + { + for (i = 1; i < total_procs; i++) + { + this->lb[i] = this->lb[0] + i*dim; + this->ub[i] = this->ub[0] + i*dim; + this->rnsize[i] = this->rnsize[0] + i*2*dim; + } + } + else + { + /* Free inner arrays */ + free(this->lb[0]); + this->lb[0] = NULL; + free(this->ub[0]); + this->ub[0] = NULL; + free(this->rnsize[0]); + this->rnsize[0] = NULL; + + /* Free toplevel arrays */ + free(this->lb); + this->lb = NULL; + free(this->ub); + this->ub = NULL; + free(this->rnsize); + this->rnsize = NULL; + free(this->rnpoints); + this->rnpoints = NULL; + free(this->nghostzones); + this->nghostzones = NULL; + free(this->nsize); + this->nsize = NULL; + free(this->lnsize); + this->lnsize = NULL; + } + } + else + { + /* Free toplevel arrays */ + free(this->lb); + this->lb = NULL; + free(this->ub); + this->ub = NULL; + free(this->rnsize); + this->rnsize = NULL; + free(this->rnpoints); + this->rnpoints = NULL; + free(this->nghostzones); + this->nghostzones = NULL; + free(this->nsize); + this->nsize = NULL; + free(this->lnsize); + this->lnsize = NULL; + } + + + if(this->lb && + this->ub && + this->rnsize && + this->rnpoints && + this->nghostzones && + this->nsize && + this->lnsize) + { + retcode = 0; + for (i = 0 ; i < PUGH_NSTAGGER; i++) + { + for (j = 0; j < 2; j++) + { + this->ownership[i][j] = (int *) malloc(dim*sizeof(int)); + this->ghosts[i][j] = (int **)malloc(2*dim*sizeof(int *)); + this->overlap[i][j] = (int **)malloc(2*dim*sizeof(int *)); + if(this->ghosts[i][j] && + this->overlap[i][j]) + { + this->ghosts[i][j][0] = (int *)malloc(2*dim*dim*sizeof(int)); + this->overlap[i][j][0] = (int *)malloc(2*dim*dim*sizeof(int)); + for (k=1; k < 2*dim; k++) + { + this->ghosts[i][j][k] = this->ghosts[i][j][0] + k*dim; + this->overlap[i][j][k] = this->overlap[i][j][0] + k*dim; + } + } + else + { + free(this->ownership[i][j]); + this->ownership[i][j] = NULL; + + free(this->ghosts[i][j]); + this->ghosts[i][j] = NULL; + + free(this->overlap[i][j]); + this->overlap[i][j] = NULL; + retcode = 1; + break; + } + } + if(retcode) + { + for(j=1; j >=0 ; j--) + { + free(this->ownership[i][j]); + this->ownership[i][j] = NULL; + + free(this->ghosts[i][j]); + this->ghosts[i][j] = NULL; + + free(this->overlap[i][j]); + this->overlap[i][j] = NULL; + + } + break; + } + } + if(retcode) + { + /* Loop back through the arrays freeing things */ + for(i--; i >=0; i--) + { + for(j=1; j >=0 ; j--) + { + free(this->ghosts[i][j][0]); + free(this->overlap[i][j][0]); + + free(this->ownership[i][j]); + this->ownership[i][j] = NULL; + + free(this->ghosts[i][j]); + this->ghosts[i][j] = NULL; + + free(this->overlap[i][j]); + this->overlap[i][j] = NULL; + } + + free(this->ownership[i]); + free(this->ghosts[i]); + free(this->overlap[i]); + } + + /* Free the stuff originally allocated */ + + free(this->lb[0]); + this->lb[0] = NULL; + free(this->ub[0]); + this->ub[0] = NULL; + free(this->rnsize[0]); + this->rnsize[0] = NULL; + + free(this->lb); + this->lb = NULL; + free(this->ub); + this->ub = NULL; + free(this->rnsize); + this->rnsize = NULL; + free(this->rnpoints); + this->rnpoints = NULL; + free(this->nghostzones); + this->nghostzones = NULL; + free(this->nsize); + this->nsize = NULL; + free(this->lnsize); + this->lnsize = NULL; + } + } + } + else + { + retcode = -1; + } + + return retcode; +} + + /*@@ + @routine pugh_SetupPGExtrasSizes + @date Mon Nov 8 08:59:33 1999 + @author Tom Goodale + @desc + Sets up the size information in the pGExtras + structure. + @enddesc + @calls + @calledby + @history + + @endhistory + +@@*/ +int pugh_SetupPGExtrasSizes(int dim, + int periodic, + int staggertype, + int *sh, + int *nghosts, + int total_procs, + int *nprocs, + int this_proc, + pGExtras *this) +{ + int dir; + + /* Setup the global shape */ + for (dir=0 ; dir < dim ; dir++) + { + /* A -ve size means constant load per proc */ + if (sh[dir] < 0 && nprocs[dir] > 1) + { + this->nsize[dir] = (nprocs[dir]-2) * + (-sh[dir] - 2*nghosts[dir]) + + 2 * (-sh[dir] - nghosts[dir]); + + if (staggertype == PUGH_STAGGER) + { + this->nsize[dir] -= nprocs[dir]-1; + } + } + else + { + this->nsize[dir] = abs(sh[dir]); + } + } + + /* Set the number of ghost zones. */ + for (dir = 0; dir < dim; dir++) + { + this->nghostzones[dir] = nghosts[dir]; + } + + /* Setup the bounding box stuff */ + + pugh_SetupBoundingBox(dim, periodic, staggertype, sh, nghosts, total_procs, nprocs, this); + + /* Set the remote sizes */ + + pugh_SetupRemoteSizes(dim, periodic, staggertype, sh, nghosts, total_procs, nprocs, this); + + /* Set the local sizes */ + + for (dir = 0; dir < dim; dir++) + { + this->lnsize[dir] = this->rnsize[this_proc][dir]; + } + + + return 0; +} + + + /*@@ + @routine pugh_SetupPGExtrasOwnership + @date Mon Nov 8 09:00:10 1999 + @author Tom Goodale + @desc + Sets up ownership, overlap, ghostzones, etc + in a pGExtras structure. + + Mostly taken from original SetupOwnership by Paul. + @enddesc + @calls + @calledby + @history + + @endhistory + +@@*/ +int pugh_SetupPGExtrasOwnership(int dim, + int periodic, + int staggertype, + int *sh, + int *nghosts, + int total_procs, + int *nprocs, + int this_proc, + pGExtras *this) +{ + int tmp; + int dir, idir; + int i,j,k; + int istart, iend; + int staglcv; + + /* Ownership is pretty easy. Remember ownership is indexed as + [stagger][ijk][min/max]. See pGF_Reduction for a use of this, + among others. + Note: Ownership is same for staggered and non-staggered grids + */ + for (dir = 0 ; dir < dim; dir++) + { + this->ownership[PUGH_VERTEXCTR][0][dir] = (this->lb[this_proc][dir] == 0 ? + 0 : this->nghostzones[dir]); + this->ownership[PUGH_VERTEXCTR][1][dir]=(this->ub[this_proc][dir] == this->nsize[dir]-1 ? + this->lnsize[dir] : this->lnsize[dir] - + this->nghostzones[dir]); + } + + /* correct for periodic identification : Tue Jun 17 08:40:15 CDT 1997 */ + if(periodic) + { + for (dir = 0; dir < dim; dir++) + { + this->ownership[PUGH_VERTEXCTR][0][dir] = this->nghostzones[dir]; + this->ownership[PUGH_VERTEXCTR][1][dir] = this->lnsize[dir] - this->nghostzones[dir]; + } + } + + for (dir = 0; dir < dim; dir++) + { + if (this->nsize[dir] == 1) + { + this->ownership[PUGH_VERTEXCTR][0][dir] = 0; + this->ownership[PUGH_VERTEXCTR][1][dir] = 1; + } + } + + + /* Great now set up the overlap region. This is the region we own, + but which is covered by our neighbors ghost. So this is what we + want to SEND + */ + for (dir = 0; dir < 2*dim; dir++) + { + for (idir = 0; idir < dim; idir++) + { + istart = 0; + iend = this->lnsize[idir]; + + /* We want to send at the dir - 1 */ + + /* Correct to direction specific sweeps ... */ + if (dir == 2*idir) + { + /* Want to go from sw to sw + sw (eg, 1 to < 2, 2 to < 4) */ + istart = this->nghostzones[idir]; + iend = istart + this->nghostzones[idir]; + } + if (dir == 2*idir+1) { + /* Want to go from nx - 2 sw to nx - sw + (eg nx-2 to < nx-1, nx-4 to < nx-2) + Luckily iend is aready set to nx ... */ + tmp = iend; + istart = tmp - 2 * this->nghostzones[idir]; + iend = tmp - this->nghostzones[idir]; + } + + this->overlap[PUGH_VERTEXCTR][0][dir][idir] = istart; + this->overlap[PUGH_VERTEXCTR][1][dir][idir] = iend; + } + } + + /* And finally the ghost indices. This used to be in + pGF_FinishRecv.c, but now it is here. + */ + for (dir = 0; dir < 2*dim; dir++) + { + /* We want to send at the dir - 1 */ + for (idir = 0; idir < dim; idir++) + { + istart = 0; + iend = this->lnsize[idir]; + + /* Correct to direction specific sweeps ... */ + /* Remember this is SW less than the other way... */ + if (dir == 2*idir) + { + /* Want to go from sw to sw + sw (eg, 1 to < 2, 2 to < 4) */ + istart = 0; + iend = this->nghostzones[idir]; + } + if (dir == 2*idir+1) + { + /* Want to go from nx - 2 sw to nx - sw + (eg nx-2 to < nx-1, nx-4 to < nx-2) + Luckily iend is aready set to nx ... */ + tmp = iend; + istart = tmp - this->nghostzones[idir]; + iend = tmp; + } + + this->ghosts[PUGH_VERTEXCTR][0][dir][idir] = istart; + this->ghosts[PUGH_VERTEXCTR][1][dir][idir] = iend; + + } + + } + + /* if staggering, set up ownership, overlaps, ghosts */ + if(staggertype == PUGH_STAGGER) + { + /* copy ownership from PUGH_VERTEXCTR */ + for(i = 1; i < PUGH_NSTAGGER; i++) + { + for(j = 0; j < dim; j++) + { + for(k = 0; k < 2; k++) + { + this->ownership[i][k][j] = this->ownership[PUGH_VERTEXCTR][k][j]; + } + } + } + + /* correct ownership for staggered grids */ + for(i = 0; i < PUGH_NSTAGGER; i++) + { + for (idir = 0; idir < dim; idir++) + { + if(this->ub[this_proc][idir] != this->nsize[idir]-1) + { + this->ownership[i][1][idir] --; + } + else + { + if(i == PUGH_FACECTR(idir)) + { + this->ownership[i][1][idir] --; + } + } + } + } + + /* set overlaps for staggered grids */ + for(staglcv = 0; staglcv < PUGH_NSTAGGER; staglcv++) + { + for(dir = 0; dir < 2*dim; dir++) + { + for (idir = 0; idir < dim; idir++) + { + istart = 0; + iend = this->lnsize[idir]; + if(staglcv == PUGH_FACECTR(idir)) + { + iend --; + } + if(dir == 2*idir) + { + istart = this->nghostzones[idir]; + iend = 2 * this->nghostzones[idir]; + if(staglcv != PUGH_FACECTR(idir)) + { + istart ++; + iend ++; + } + } + if(dir == 2*idir+1) + { + istart = this->lnsize[idir] - 2 * this->nghostzones[idir] -1; + iend = istart + this->nghostzones[idir]; + } + + this->overlap[staglcv][0][dir][idir] = istart; + this->overlap[staglcv][1][dir][idir] = iend; + } + } + } + + /* set ghosts for staggered grids */ + for(staglcv = 0; staglcv < PUGH_NSTAGGER; staglcv++) + { + for(dir = 0; dir < 2*dim; dir++) + { + for(idir=0;idir<dim;idir++) + { + istart = 0; + iend = this->lnsize[idir]; + if(staglcv == PUGH_FACECTR(idir)) + { + iend --; + } + if(dir == 2*idir) + { + istart = 0; + iend = this->nghostzones[idir]; + } + if(dir == 2*idir+1) + { + istart = this->lnsize[idir] - this->nghostzones[idir]; + iend = this->lnsize[idir]; + if(staglcv == PUGH_FACECTR(idir)) + { + istart --; + iend --; + } + } + this->ghosts[staglcv][0][dir][idir] = istart; + this->ghosts[staglcv][1][dir][idir] = iend; + } + } + } + } + + return 0; +} + + /*@@ + @routine pugh_SetupBoundingBox + @date Mon Nov 8 09:03:40 1999 + @author Tom Goodale + @desc + Sets up the bounding box info for a pgExtras structure. + @enddesc + @calls + @calledby + @history + + @endhistory + +@@*/ +int pugh_SetupBoundingBox(int dim, + int periodic, + int staggertype, + int *sh, + int *nghosts, + int total_procs, + int *nprocs, + pGExtras *this) +{ + int pnum,dir; + + int *step; + int *pos; + + step = (int *)malloc(dim*sizeof(int)); + pos = (int *)malloc(dim*sizeof(int)); + + if(step && pos) + { + /* Work out the step in each direction */ + for (dir = 0 ; dir < dim; dir++) + { + step[dir] = (this->nsize[dir]-1) / nprocs[dir]; + } + + for(pnum = 0; pnum < total_procs; pnum++) + { + pugh_DecomposeIJK(dim, pnum,nprocs, pos); + + for(dir = 0 ; dir < dim; dir++) + { + if (pos[dir] == 0) + { + this->lb[pnum][dir] = 0; + } + else + { + this->lb[pnum][dir] = pos[dir]*step[dir] +1 - nghosts[dir]; + if(staggertype == PUGH_STAGGER) + { + this->lb[pnum][dir] --; + } + } + + if (pos[dir] == nprocs[dir]-1) + { + this->ub[pnum][dir] = this->nsize[dir]-1; + } + else + { + this->ub[pnum][dir] = (pos[dir]+1)*step[dir] + this->nghostzones[dir]; + } + } + } + + } + + free(step); + free(pos); + + return 0; +} + + + /*@@ + @routine pugh_SetupRemoteSizes + @date Mon Nov 8 09:07:27 1999 + @author Tom Goodale + @desc + Determines info about the sizes on each processor. + @enddesc + @calls + @calledby + @history + + @endhistory + +@@*/ +int pugh_SetupRemoteSizes(int dim, + int periodic, + int staggertype, + int *sh, + int *nghosts, + int total_procs, + int *nprocs, + pGExtras *this) +{ + int pnum; + int dir; + + /* Save the number of points on each processor */ + + for(pnum = 0; pnum < total_procs; pnum++) + { + + this->rnpoints[pnum] = 1; + for (dir=0;dir<dim;dir++) + { + this->rnsize[pnum][dir] = (this->ub[pnum][dir]-this->lb[pnum][dir]+1); + this->rnpoints[pnum] *= this->rnsize[pnum][dir]; + } + } + + return 0; +} |