Actual source code: ex6.c


  2: static char help[] = "\n\n";

  4: /*
  5:      Demonstrates using DM_BOUNDARY_GHOSTED how to handle a rotated boundary conditions where one edge
  6:     is connected to its immediate neighbor

  8:     Consider the domain (with natural numbering)

 10:      6   7   8
 11:      3   4   5
 12:      0   1   2

 14:     The ghost points along the bottom (directly below the three columns above) should be 0 3 and 6
 15:     while the ghost points along the left side should be 0 1 2

 17:     Note that the ghosted local vectors extend in both the x and y directions so, for example if we have a
 18:     single MPI process the ghosted vector has (in the original natural numbering)

 20:      x  x  x  x  x
 21:      2  6  7  8  x
 22:      1  3  4  5  x
 23:      0  0  1  2  x
 24:      x  0  3  6  x

 26:     where x indicates a location that is not updated by the communication and should be used.

 28:     For this to make sense the number of grid points in the x and y directions must be the same

 30:     This ghost point mapping was suggested by: Wenbo Zhao <zhaowenbo.npic@gmail.com>
 31: */

 33: #include <petscdm.h>
 34: #include <petscdmda.h>

 36: int main(int argc,char **argv)
 37: {
 38:   PetscInt         M = 6;
 39:   DM               da;
 40:   Vec              local,global,natural;
 41:   PetscInt         i,start,end,*ifrom,x,y,xm,ym;
 42:   PetscScalar      *xnatural;
 43:   IS               from,to;
 44:   AO               ao;
 45:   VecScatter       scatter1,scatter2;
 46:   PetscViewer      subviewer;

 48:   PetscInitialize(&argc,&argv,(char*)0,help);

 50:   /* Create distributed array and get vectors */
 51:   DMDACreate2d(PETSC_COMM_WORLD,DM_BOUNDARY_GHOSTED,DM_BOUNDARY_GHOSTED,DMDA_STENCIL_STAR,M,M,PETSC_DECIDE,PETSC_DECIDE,1,1,NULL,NULL,&da);
 52:   DMSetUp(da);
 53:   DMCreateGlobalVector(da,&global);
 54:   DMCreateLocalVector(da,&local);

 56:   /* construct global to local scatter for the left side of the domain to the ghost on the bottom */
 57:   DMDAGetCorners(da,&x,&y,NULL,&xm,&ym,NULL);
 58:   if (!y) { /* only processes on the bottom of the domain fill up the ghost locations */
 59:     ISCreateStride(PETSC_COMM_SELF,xm,1,1,&to);
 60:   } else {
 61:     ISCreateStride(PETSC_COMM_SELF,0,0,0,&to);
 62:   }
 63:   PetscMalloc1(xm,&ifrom);
 64:   for (i=x;i<x+xm;i++) {
 65:     ifrom[i-x] = M*i;
 66:   }
 67:   DMDAGetAO(da,&ao);
 68:   AOApplicationToPetsc(ao,xm,ifrom);
 69:   if (!y) {
 70:     ISCreateGeneral(PETSC_COMM_WORLD,xm,ifrom,PETSC_OWN_POINTER,&from);
 71:   } else {
 72:     PetscFree(ifrom);
 73:     ISCreateGeneral(PETSC_COMM_WORLD,0,NULL,PETSC_COPY_VALUES,&from);
 74:   }
 75:   VecScatterCreate(global,from,local,to,&scatter1);
 76:   ISDestroy(&to);
 77:   ISDestroy(&from);

 79:   /* construct global to local scatter for the bottom side of the domain to the ghost on the right */
 80:   if (!x) { /* only processes on the left side of the domain fill up the ghost locations */
 81:     ISCreateStride(PETSC_COMM_SELF,ym,xm+2,xm+2,&to);
 82:   } else {
 83:     ISCreateStride(PETSC_COMM_SELF,0,0,0,&to);
 84:   }
 85:   PetscMalloc1(ym,&ifrom);
 86:   for (i=y;i<y+ym;i++) {
 87:     ifrom[i-y] = i;
 88:   }
 89:   DMDAGetAO(da,&ao);
 90:   AOApplicationToPetsc(ao,ym,ifrom);
 91:   if (!x) {
 92:     ISCreateGeneral(PETSC_COMM_WORLD,ym,ifrom,PETSC_OWN_POINTER,&from);
 93:   } else {
 94:     PetscFree(ifrom);
 95:     ISCreateGeneral(PETSC_COMM_WORLD,0,NULL,PETSC_COPY_VALUES,&from);
 96:   }
 97:   VecScatterCreate(global,from,local,to,&scatter2);
 98:   ISDestroy(&to);
 99:   ISDestroy(&from);

101:   /*
102:      fill the global vector with the natural global numbering for each local entry
103:      this is only done for testing purposes since it is easy to see if the scatter worked correctly
104:   */
105:   DMDACreateNaturalVector(da,&natural);
106:   VecGetOwnershipRange(natural,&start,&end);
107:   VecGetArray(natural,&xnatural);
108:   for (i=start; i<end; i++) {
109:     xnatural[i-start] = i;
110:   }
111:   VecRestoreArray(natural,&xnatural);
112:   DMDANaturalToGlobalBegin(da,natural,INSERT_VALUES,global);
113:   DMDANaturalToGlobalEnd(da,natural,INSERT_VALUES,global);
114:   VecDestroy(&natural);

116:   /* scatter from global to local */
117:   VecScatterBegin(scatter1,global,local,INSERT_VALUES,SCATTER_FORWARD);
118:   VecScatterEnd(scatter1,global,local,INSERT_VALUES,SCATTER_FORWARD);
119:   VecScatterBegin(scatter2,global,local,INSERT_VALUES,SCATTER_FORWARD);
120:   VecScatterEnd(scatter2,global,local,INSERT_VALUES,SCATTER_FORWARD);
121:   /*
122:      normally here you would also call
123:   DMGlobalToLocalBegin(da,global,INSERT_VALUES,local);
124:   DMGlobalToLocalEnd(da,global,INSERT_VALUES,local);
125:     to update all the interior ghost cells between neighboring processes.
126:     We don't do it here since this is only a test of "special" ghost points.
127:   */

129:   /* view each local ghosted vector */
130:   PetscViewerGetSubViewer(PETSC_VIEWER_STDOUT_WORLD,PETSC_COMM_SELF,&subviewer);
131:   VecView(local,subviewer);
132:   PetscViewerRestoreSubViewer(PETSC_VIEWER_STDOUT_WORLD,PETSC_COMM_SELF,&subviewer);

134:   VecScatterDestroy(&scatter1);
135:   VecScatterDestroy(&scatter2);
136:   VecDestroy(&local);
137:   VecDestroy(&global);
138:   DMDestroy(&da);
139:   PetscFinalize();
140:   return 0;
141: }

143: /*TEST

145:    test:

147:    test:
148:       suffix: 2
149:       nsize: 2

151:    test:
152:       suffix: 4
153:       nsize: 4

155:    test:
156:       suffix: 9
157:       nsize: 9

159: TEST*/