xref: /petsc/src/dm/impls/da/da3.c (revision 4e278199b78715991f5c71ebbd945c1489263e6c)
1 
2 /*
3    Code for manipulating distributed regular 3d arrays in parallel.
4    File created by Peter Mell  7/14/95
5  */
6 
7 #include <petsc/private/dmdaimpl.h>     /*I   "petscdmda.h"    I*/
8 
9 #include <petscdraw.h>
10 static PetscErrorCode DMView_DA_3d(DM da,PetscViewer viewer)
11 {
12   PetscErrorCode ierr;
13   PetscMPIInt    rank;
14   PetscBool      iascii,isdraw,isglvis,isbinary;
15   DM_DA          *dd = (DM_DA*)da->data;
16 #if defined(PETSC_HAVE_MATLAB_ENGINE)
17   PetscBool ismatlab;
18 #endif
19 
20   PetscFunctionBegin;
21   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)da),&rank);CHKERRMPI(ierr);
22 
23   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
24   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERDRAW,&isdraw);CHKERRQ(ierr);
25   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERGLVIS,&isglvis);CHKERRQ(ierr);
26   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERBINARY,&isbinary);CHKERRQ(ierr);
27 #if defined(PETSC_HAVE_MATLAB_ENGINE)
28   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERMATLAB,&ismatlab);CHKERRQ(ierr);
29 #endif
30   if (iascii) {
31     PetscViewerFormat format;
32 
33     ierr = PetscViewerASCIIPushSynchronized(viewer);CHKERRQ(ierr);
34     ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr);
35     if (format == PETSC_VIEWER_LOAD_BALANCE) {
36       PetscInt      i,nmax = 0,nmin = PETSC_MAX_INT,navg = 0,*nz,nzlocal;
37       DMDALocalInfo info;
38       PetscMPIInt   size;
39       ierr = MPI_Comm_size(PetscObjectComm((PetscObject)da),&size);CHKERRMPI(ierr);
40       ierr = DMDAGetLocalInfo(da,&info);CHKERRQ(ierr);
41       nzlocal = info.xm*info.ym*info.zm;
42       ierr = PetscMalloc1(size,&nz);CHKERRQ(ierr);
43       ierr = MPI_Allgather(&nzlocal,1,MPIU_INT,nz,1,MPIU_INT,PetscObjectComm((PetscObject)da));CHKERRMPI(ierr);
44       for (i=0; i<(PetscInt)size; i++) {
45         nmax = PetscMax(nmax,nz[i]);
46         nmin = PetscMin(nmin,nz[i]);
47         navg += nz[i];
48       }
49       ierr = PetscFree(nz);CHKERRQ(ierr);
50       navg = navg/size;
51       ierr = PetscViewerASCIIPrintf(viewer,"  Load Balance - Grid Points: Min %D  avg %D  max %D\n",nmin,navg,nmax);CHKERRQ(ierr);
52       PetscFunctionReturn(0);
53     }
54     if (format != PETSC_VIEWER_ASCII_VTK_DEPRECATED && format != PETSC_VIEWER_ASCII_VTK_CELL_DEPRECATED && format != PETSC_VIEWER_ASCII_GLVIS) {
55       DMDALocalInfo info;
56       ierr = DMDAGetLocalInfo(da,&info);CHKERRQ(ierr);
57       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Processor [%d] M %D N %D P %D m %D n %D p %D w %D s %D\n",rank,dd->M,dd->N,dd->P,dd->m,dd->n,dd->p,dd->w,dd->s);CHKERRQ(ierr);
58       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"X range of indices: %D %D, Y range of indices: %D %D, Z range of indices: %D %D\n",
59                                                 info.xs,info.xs+info.xm,info.ys,info.ys+info.ym,info.zs,info.zs+info.zm);CHKERRQ(ierr);
60 #if !defined(PETSC_USE_COMPLEX)
61       if (da->coordinates) {
62         PetscInt        last;
63         const PetscReal *coors;
64         ierr = VecGetArrayRead(da->coordinates,&coors);CHKERRQ(ierr);
65         ierr = VecGetLocalSize(da->coordinates,&last);CHKERRQ(ierr);
66         last = last - 3;
67         ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Lower left corner %g %g %g : Upper right %g %g %g\n",(double)coors[0],(double)coors[1],(double)coors[2],(double)coors[last],(double)coors[last+1],(double)coors[last+2]);CHKERRQ(ierr);
68         ierr = VecRestoreArrayRead(da->coordinates,&coors);CHKERRQ(ierr);
69       }
70 #endif
71       ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
72       ierr = PetscViewerASCIIPopSynchronized(viewer);CHKERRQ(ierr);
73     } else if (format == PETSC_VIEWER_ASCII_GLVIS) {
74       ierr = DMView_DA_GLVis(da,viewer);CHKERRQ(ierr);
75     } else {
76       ierr = DMView_DA_VTK(da,viewer);CHKERRQ(ierr);
77     }
78   } else if (isdraw) {
79     PetscDraw      draw;
80     PetscReal      ymin = -1.0,ymax = (PetscReal)dd->N;
81     PetscReal      xmin = -1.0,xmax = (PetscReal)((dd->M+2)*dd->P),x,y,ycoord,xcoord;
82     PetscInt       k,plane,base;
83     const PetscInt *idx;
84     char           node[10];
85     PetscBool      isnull;
86 
87     ierr = PetscViewerDrawGetDraw(viewer,0,&draw);CHKERRQ(ierr);
88     ierr = PetscDrawIsNull(draw,&isnull);CHKERRQ(ierr);
89     if (isnull) PetscFunctionReturn(0);
90 
91     ierr = PetscDrawCheckResizedWindow(draw);CHKERRQ(ierr);
92     ierr = PetscDrawClear(draw);CHKERRQ(ierr);
93     ierr = PetscDrawSetCoordinates(draw,xmin,ymin,xmax,ymax);CHKERRQ(ierr);
94 
95     ierr = PetscDrawCollectiveBegin(draw);CHKERRQ(ierr);
96     /* first processor draw all node lines */
97     if (!rank) {
98       for (k=0; k<dd->P; k++) {
99         ymin = 0.0; ymax = (PetscReal)(dd->N - 1);
100         for (xmin=(PetscReal)(k*(dd->M+1)); xmin<(PetscReal)(dd->M+(k*(dd->M+1))); xmin++) {
101           ierr = PetscDrawLine(draw,xmin,ymin,xmin,ymax,PETSC_DRAW_BLACK);CHKERRQ(ierr);
102         }
103         xmin = (PetscReal)(k*(dd->M+1)); xmax = xmin + (PetscReal)(dd->M - 1);
104         for (ymin=0; ymin<(PetscReal)dd->N; ymin++) {
105           ierr = PetscDrawLine(draw,xmin,ymin,xmax,ymin,PETSC_DRAW_BLACK);CHKERRQ(ierr);
106         }
107       }
108     }
109     ierr = PetscDrawCollectiveEnd(draw);CHKERRQ(ierr);
110     ierr = PetscDrawFlush(draw);CHKERRQ(ierr);
111     ierr = PetscDrawPause(draw);CHKERRQ(ierr);
112 
113     ierr = PetscDrawCollectiveBegin(draw);CHKERRQ(ierr);
114     /*Go through and draw for each plane*/
115     for (k=0; k<dd->P; k++) {
116       if ((k >= dd->zs) && (k < dd->ze)) {
117         /* draw my box */
118         ymin = dd->ys;
119         ymax = dd->ye - 1;
120         xmin = dd->xs/dd->w    + (dd->M+1)*k;
121         xmax =(dd->xe-1)/dd->w + (dd->M+1)*k;
122 
123         ierr = PetscDrawLine(draw,xmin,ymin,xmax,ymin,PETSC_DRAW_RED);CHKERRQ(ierr);
124         ierr = PetscDrawLine(draw,xmin,ymin,xmin,ymax,PETSC_DRAW_RED);CHKERRQ(ierr);
125         ierr = PetscDrawLine(draw,xmin,ymax,xmax,ymax,PETSC_DRAW_RED);CHKERRQ(ierr);
126         ierr = PetscDrawLine(draw,xmax,ymin,xmax,ymax,PETSC_DRAW_RED);CHKERRQ(ierr);
127 
128         xmin = dd->xs/dd->w;
129         xmax =(dd->xe-1)/dd->w;
130 
131         /* identify which processor owns the box */
132         ierr = PetscSNPrintf(node,sizeof(node),"%d",(int)rank);CHKERRQ(ierr);
133         ierr = PetscDrawString(draw,xmin+(dd->M+1)*k+.2,ymin+.3,PETSC_DRAW_RED,node);CHKERRQ(ierr);
134         /* put in numbers*/
135         base = (dd->base+(dd->xe-dd->xs)*(dd->ye-dd->ys)*(k-dd->zs))/dd->w;
136         for (y=ymin; y<=ymax; y++) {
137           for (x=xmin+(dd->M+1)*k; x<=xmax+(dd->M+1)*k; x++) {
138             ierr = PetscSNPrintf(node,sizeof(node),"%d",(int)base++);CHKERRQ(ierr);
139             ierr = PetscDrawString(draw,x,y,PETSC_DRAW_BLACK,node);CHKERRQ(ierr);
140           }
141         }
142 
143       }
144     }
145     ierr = PetscDrawCollectiveEnd(draw);CHKERRQ(ierr);
146     ierr = PetscDrawFlush(draw);CHKERRQ(ierr);
147     ierr = PetscDrawPause(draw);CHKERRQ(ierr);
148 
149     ierr = PetscDrawCollectiveBegin(draw);CHKERRQ(ierr);
150     for (k=0-dd->s; k<dd->P+dd->s; k++) {
151       /* Go through and draw for each plane */
152       if ((k >= dd->Zs) && (k < dd->Ze)) {
153         /* overlay ghost numbers, useful for error checking */
154         base = (dd->Xe-dd->Xs)*(dd->Ye-dd->Ys)*(k-dd->Zs)/dd->w;
155         ierr = ISLocalToGlobalMappingGetBlockIndices(da->ltogmap,&idx);CHKERRQ(ierr);
156         plane=k;
157         /* Keep z wrap around points on the drawing */
158         if (k<0) plane=dd->P+k;
159         if (k>=dd->P) plane=k-dd->P;
160         ymin = dd->Ys; ymax = dd->Ye;
161         xmin = (dd->M+1)*plane*dd->w;
162         xmax = (dd->M+1)*plane*dd->w+dd->M*dd->w;
163         for (y=ymin; y<ymax; y++) {
164           for (x=xmin+dd->Xs; x<xmin+dd->Xe; x+=dd->w) {
165             sprintf(node,"%d",(int)(idx[base]));
166             ycoord = y;
167             /*Keep y wrap around points on drawing */
168             if (y<0) ycoord = dd->N+y;
169             if (y>=dd->N) ycoord = y-dd->N;
170             xcoord = x;   /* Keep x wrap points on drawing */
171             if (x<xmin) xcoord = xmax - (xmin-x);
172             if (x>=xmax) xcoord = xmin + (x-xmax);
173             ierr = PetscDrawString(draw,xcoord/dd->w,ycoord,PETSC_DRAW_BLUE,node);CHKERRQ(ierr);
174             base++;
175           }
176         }
177         ierr = ISLocalToGlobalMappingRestoreBlockIndices(da->ltogmap,&idx);CHKERRQ(ierr);
178       }
179     }
180     ierr = PetscDrawCollectiveEnd(draw);CHKERRQ(ierr);
181     ierr = PetscDrawFlush(draw);CHKERRQ(ierr);
182     ierr = PetscDrawPause(draw);CHKERRQ(ierr);
183     ierr = PetscDrawSave(draw);CHKERRQ(ierr);
184   } else if (isglvis) {
185     ierr = DMView_DA_GLVis(da,viewer);CHKERRQ(ierr);
186   } else if (isbinary) {
187     ierr = DMView_DA_Binary(da,viewer);CHKERRQ(ierr);
188 #if defined(PETSC_HAVE_MATLAB_ENGINE)
189   } else if (ismatlab) {
190     ierr = DMView_DA_Matlab(da,viewer);CHKERRQ(ierr);
191 #endif
192   }
193   PetscFunctionReturn(0);
194 }
195 
196 PetscErrorCode  DMSetUp_DA_3D(DM da)
197 {
198   DM_DA            *dd          = (DM_DA*)da->data;
199   const PetscInt   M            = dd->M;
200   const PetscInt   N            = dd->N;
201   const PetscInt   P            = dd->P;
202   PetscInt         m            = dd->m;
203   PetscInt         n            = dd->n;
204   PetscInt         p            = dd->p;
205   const PetscInt   dof          = dd->w;
206   const PetscInt   s            = dd->s;
207   DMBoundaryType   bx           = dd->bx;
208   DMBoundaryType   by           = dd->by;
209   DMBoundaryType   bz           = dd->bz;
210   DMDAStencilType  stencil_type = dd->stencil_type;
211   PetscInt         *lx          = dd->lx;
212   PetscInt         *ly          = dd->ly;
213   PetscInt         *lz          = dd->lz;
214   MPI_Comm         comm;
215   PetscMPIInt      rank,size;
216   PetscInt         xs = 0,xe,ys = 0,ye,zs = 0,ze,x = 0,y = 0,z = 0;
217   PetscInt         Xs,Xe,Ys,Ye,Zs,Ze,IXs,IXe,IYs,IYe,IZs,IZe,pm;
218   PetscInt         left,right,up,down,bottom,top,i,j,k,*idx,nn;
219   PetscInt         n0,n1,n2,n3,n4,n5,n6,n7,n8,n9,n10,n11,n12,n14;
220   PetscInt         n15,n16,n17,n18,n19,n20,n21,n22,n23,n24,n25,n26;
221   PetscInt         *bases,*ldims,base,x_t,y_t,z_t,s_t,count,s_x,s_y,s_z;
222   PetscInt         sn0  = 0,sn1 = 0,sn2 = 0,sn3 = 0,sn5 = 0,sn6 = 0,sn7 = 0;
223   PetscInt         sn8  = 0,sn9 = 0,sn11 = 0,sn15 = 0,sn24 = 0,sn25 = 0,sn26 = 0;
224   PetscInt         sn17 = 0,sn18 = 0,sn19 = 0,sn20 = 0,sn21 = 0,sn23 = 0;
225   Vec              local,global;
226   VecScatter       gtol;
227   IS               to,from;
228   PetscBool        twod;
229   PetscErrorCode   ierr;
230 
231   PetscFunctionBegin;
232   if (stencil_type == DMDA_STENCIL_BOX && (bx == DM_BOUNDARY_MIRROR || by == DM_BOUNDARY_MIRROR || bz == DM_BOUNDARY_MIRROR)) SETERRQ(PetscObjectComm((PetscObject)da),PETSC_ERR_SUP,"Mirror boundary and box stencil");
233   ierr = PetscObjectGetComm((PetscObject) da, &comm);CHKERRQ(ierr);
234 #if !defined(PETSC_USE_64BIT_INDICES)
235   if (((PetscInt64) M)*((PetscInt64) N)*((PetscInt64) P)*((PetscInt64) dof) > (PetscInt64) PETSC_MPI_INT_MAX) SETERRQ4(comm,PETSC_ERR_INT_OVERFLOW,"Mesh of %D by %D by %D by %D (dof) is too large for 32 bit indices",M,N,P,dof);
236 #endif
237 
238   ierr = MPI_Comm_size(comm,&size);CHKERRMPI(ierr);
239   ierr = MPI_Comm_rank(comm,&rank);CHKERRMPI(ierr);
240 
241   if (m != PETSC_DECIDE) {
242     if (m < 1) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Non-positive number of processors in X direction: %D",m);
243     else if (m > size) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Too many processors in X direction: %D %d",m,size);
244   }
245   if (n != PETSC_DECIDE) {
246     if (n < 1) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Non-positive number of processors in Y direction: %D",n);
247     else if (n > size) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Too many processors in Y direction: %D %d",n,size);
248   }
249   if (p != PETSC_DECIDE) {
250     if (p < 1) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Non-positive number of processors in Z direction: %D",p);
251     else if (p > size) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Too many processors in Z direction: %D %d",p,size);
252   }
253   if ((m > 0) && (n > 0) && (p > 0) && (m*n*p != size)) SETERRQ4(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"m %D * n %D * p %D != size %d",m,n,p,size);
254 
255   /* Partition the array among the processors */
256   if (m == PETSC_DECIDE && n != PETSC_DECIDE && p != PETSC_DECIDE) {
257     m = size/(n*p);
258   } else if (m != PETSC_DECIDE && n == PETSC_DECIDE && p != PETSC_DECIDE) {
259     n = size/(m*p);
260   } else if (m != PETSC_DECIDE && n != PETSC_DECIDE && p == PETSC_DECIDE) {
261     p = size/(m*n);
262   } else if (m == PETSC_DECIDE && n == PETSC_DECIDE && p != PETSC_DECIDE) {
263     /* try for squarish distribution */
264     m = (int)(0.5 + PetscSqrtReal(((PetscReal)M)*((PetscReal)size)/((PetscReal)N*p)));
265     if (!m) m = 1;
266     while (m > 0) {
267       n = size/(m*p);
268       if (m*n*p == size) break;
269       m--;
270     }
271     if (!m) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"bad p value: p = %D",p);
272     if (M > N && m < n) {PetscInt _m = m; m = n; n = _m;}
273   } else if (m == PETSC_DECIDE && n != PETSC_DECIDE && p == PETSC_DECIDE) {
274     /* try for squarish distribution */
275     m = (int)(0.5 + PetscSqrtReal(((PetscReal)M)*((PetscReal)size)/((PetscReal)P*n)));
276     if (!m) m = 1;
277     while (m > 0) {
278       p = size/(m*n);
279       if (m*n*p == size) break;
280       m--;
281     }
282     if (!m) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"bad n value: n = %D",n);
283     if (M > P && m < p) {PetscInt _m = m; m = p; p = _m;}
284   } else if (m != PETSC_DECIDE && n == PETSC_DECIDE && p == PETSC_DECIDE) {
285     /* try for squarish distribution */
286     n = (int)(0.5 + PetscSqrtReal(((PetscReal)N)*((PetscReal)size)/((PetscReal)P*m)));
287     if (!n) n = 1;
288     while (n > 0) {
289       p = size/(m*n);
290       if (m*n*p == size) break;
291       n--;
292     }
293     if (!n) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"bad m value: m = %D",n);
294     if (N > P && n < p) {PetscInt _n = n; n = p; p = _n;}
295   } else if (m == PETSC_DECIDE && n == PETSC_DECIDE && p == PETSC_DECIDE) {
296     /* try for squarish distribution */
297     n = (PetscInt)(0.5 + PetscPowReal(((PetscReal)N*N)*((PetscReal)size)/((PetscReal)P*M),(PetscReal)(1./3.)));
298     if (!n) n = 1;
299     while (n > 0) {
300       pm = size/n;
301       if (n*pm == size) break;
302       n--;
303     }
304     if (!n) n = 1;
305     m = (PetscInt)(0.5 + PetscSqrtReal(((PetscReal)M)*((PetscReal)size)/((PetscReal)P*n)));
306     if (!m) m = 1;
307     while (m > 0) {
308       p = size/(m*n);
309       if (m*n*p == size) break;
310       m--;
311     }
312     if (M > P && m < p) {PetscInt _m = m; m = p; p = _m;}
313   } else if (m*n*p != size) SETERRQ(PetscObjectComm((PetscObject)da),PETSC_ERR_ARG_OUTOFRANGE,"Given Bad partition");
314 
315   if (m*n*p != size) SETERRQ(PetscObjectComm((PetscObject)da),PETSC_ERR_PLIB,"Could not find good partition");
316   if (M < m) SETERRQ2(PetscObjectComm((PetscObject)da),PETSC_ERR_ARG_OUTOFRANGE,"Partition in x direction is too fine! %D %D",M,m);
317   if (N < n) SETERRQ2(PetscObjectComm((PetscObject)da),PETSC_ERR_ARG_OUTOFRANGE,"Partition in y direction is too fine! %D %D",N,n);
318   if (P < p) SETERRQ2(PetscObjectComm((PetscObject)da),PETSC_ERR_ARG_OUTOFRANGE,"Partition in z direction is too fine! %D %D",P,p);
319 
320   /*
321      Determine locally owned region
322      [x, y, or z]s is the first local node number, [x, y, z] is the number of local nodes
323   */
324 
325   if (!lx) {
326     ierr = PetscMalloc1(m, &dd->lx);CHKERRQ(ierr);
327     lx   = dd->lx;
328     for (i=0; i<m; i++) lx[i] = M/m + ((M % m) > (i % m));
329   }
330   x  = lx[rank % m];
331   xs = 0;
332   for (i=0; i<(rank%m); i++) xs += lx[i];
333   if ((x < s) && ((m > 1) || (bx == DM_BOUNDARY_PERIODIC))) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Local x-width of domain x %D is smaller than stencil width s %D",x,s);
334 
335   if (!ly) {
336     ierr = PetscMalloc1(n, &dd->ly);CHKERRQ(ierr);
337     ly   = dd->ly;
338     for (i=0; i<n; i++) ly[i] = N/n + ((N % n) > (i % n));
339   }
340   y = ly[(rank % (m*n))/m];
341   if ((y < s) && ((n > 1) || (by == DM_BOUNDARY_PERIODIC))) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Local y-width of domain y %D is smaller than stencil width s %D",y,s);
342 
343   ys = 0;
344   for (i=0; i<(rank % (m*n))/m; i++) ys += ly[i];
345 
346   if (!lz) {
347     ierr = PetscMalloc1(p, &dd->lz);CHKERRQ(ierr);
348     lz = dd->lz;
349     for (i=0; i<p; i++) lz[i] = P/p + ((P % p) > (i % p));
350   }
351   z = lz[rank/(m*n)];
352 
353   /* note this is different than x- and y-, as we will handle as an important special
354    case when p=P=1 and DM_BOUNDARY_PERIODIC and s > z.  This is to deal with 2D problems
355    in a 3D code.  Additional code for this case is noted with "2d case" comments */
356   twod = PETSC_FALSE;
357   if (P == 1) twod = PETSC_TRUE;
358   else if ((z < s) && ((p > 1) || (bz == DM_BOUNDARY_PERIODIC))) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Local z-width of domain z %D is smaller than stencil width s %D",z,s);
359   zs = 0;
360   for (i=0; i<(rank/(m*n)); i++) zs += lz[i];
361   ye = ys + y;
362   xe = xs + x;
363   ze = zs + z;
364 
365   /* determine ghost region (Xs) and region scattered into (IXs)  */
366   if (xs-s > 0) {
367     Xs = xs - s; IXs = xs - s;
368   } else {
369     if (bx) Xs = xs - s;
370     else Xs = 0;
371     IXs = 0;
372   }
373   if (xe+s <= M) {
374     Xe = xe + s; IXe = xe + s;
375   } else {
376     if (bx) {
377       Xs = xs - s; Xe = xe + s;
378     } else Xe = M;
379     IXe = M;
380   }
381 
382   if (bx == DM_BOUNDARY_PERIODIC || bx == DM_BOUNDARY_MIRROR) {
383     IXs = xs - s;
384     IXe = xe + s;
385     Xs  = xs - s;
386     Xe  = xe + s;
387   }
388 
389   if (ys-s > 0) {
390     Ys = ys - s; IYs = ys - s;
391   } else {
392     if (by) Ys = ys - s;
393     else Ys = 0;
394     IYs = 0;
395   }
396   if (ye+s <= N) {
397     Ye = ye + s; IYe = ye + s;
398   } else {
399     if (by) Ye = ye + s;
400     else Ye = N;
401     IYe = N;
402   }
403 
404   if (by == DM_BOUNDARY_PERIODIC || by == DM_BOUNDARY_MIRROR) {
405     IYs = ys - s;
406     IYe = ye + s;
407     Ys  = ys - s;
408     Ye  = ye + s;
409   }
410 
411   if (zs-s > 0) {
412     Zs = zs - s; IZs = zs - s;
413   } else {
414     if (bz) Zs = zs - s;
415     else Zs = 0;
416     IZs = 0;
417   }
418   if (ze+s <= P) {
419     Ze = ze + s; IZe = ze + s;
420   } else {
421     if (bz) Ze = ze + s;
422     else Ze = P;
423     IZe = P;
424   }
425 
426   if (bz == DM_BOUNDARY_PERIODIC || bz == DM_BOUNDARY_MIRROR) {
427     IZs = zs - s;
428     IZe = ze + s;
429     Zs  = zs - s;
430     Ze  = ze + s;
431   }
432 
433   /* Resize all X parameters to reflect w */
434   s_x = s;
435   s_y = s;
436   s_z = s;
437 
438   /* determine starting point of each processor */
439   nn       = x*y*z;
440   ierr     = PetscMalloc2(size+1,&bases,size,&ldims);CHKERRQ(ierr);
441   ierr     = MPI_Allgather(&nn,1,MPIU_INT,ldims,1,MPIU_INT,comm);CHKERRMPI(ierr);
442   bases[0] = 0;
443   for (i=1; i<=size; i++) bases[i] = ldims[i-1];
444   for (i=1; i<=size; i++) bases[i] += bases[i-1];
445   base = bases[rank]*dof;
446 
447   /* allocate the base parallel and sequential vectors */
448   dd->Nlocal = x*y*z*dof;
449   ierr       = VecCreateMPIWithArray(comm,dof,dd->Nlocal,PETSC_DECIDE,NULL,&global);CHKERRQ(ierr);
450   dd->nlocal = (Xe-Xs)*(Ye-Ys)*(Ze-Zs)*dof;
451   ierr       = VecCreateSeqWithArray(PETSC_COMM_SELF,dof,dd->nlocal,NULL,&local);CHKERRQ(ierr);
452 
453   /* generate global to local vector scatter and local to global mapping*/
454 
455   /* global to local must include ghost points within the domain,
456      but not ghost points outside the domain that aren't periodic */
457   ierr   = PetscMalloc1((IXe-IXs)*(IYe-IYs)*(IZe-IZs),&idx);CHKERRQ(ierr);
458   if (stencil_type == DMDA_STENCIL_BOX) {
459     left   = IXs - Xs; right = left + (IXe-IXs);
460     bottom = IYs - Ys; top = bottom + (IYe-IYs);
461     down   = IZs - Zs; up  = down + (IZe-IZs);
462     count  = 0;
463     for (i=down; i<up; i++) {
464       for (j=bottom; j<top; j++) {
465         for (k=left; k<right; k++) {
466           idx[count++] = (i*(Ye-Ys) + j)*(Xe-Xs) + k;
467         }
468       }
469     }
470     ierr = ISCreateBlock(comm,dof,count,idx,PETSC_OWN_POINTER,&to);CHKERRQ(ierr);
471   } else {
472     /* This is way ugly! We need to list the funny cross type region */
473     left   = xs - Xs; right = left + x;
474     bottom = ys - Ys; top = bottom + y;
475     down   = zs - Zs;   up  = down + z;
476     count  = 0;
477     /* the bottom chunck */
478     for (i=(IZs-Zs); i<down; i++) {
479       for (j=bottom; j<top; j++) {
480         for (k=left; k<right; k++) idx[count++] = (i*(Ye-Ys) + j)*(Xe-Xs) + k;
481       }
482     }
483     /* the middle piece */
484     for (i=down; i<up; i++) {
485       /* front */
486       for (j=(IYs-Ys); j<bottom; j++) {
487         for (k=left; k<right; k++) idx[count++] = (i*(Ye-Ys) + j)*(Xe-Xs) + k;
488       }
489       /* middle */
490       for (j=bottom; j<top; j++) {
491         for (k=IXs-Xs; k<IXe-Xs; k++) idx[count++] = (i*(Ye-Ys) + j)*(Xe-Xs) + k;
492       }
493       /* back */
494       for (j=top; j<top+IYe-ye; j++) {
495         for (k=left; k<right; k++) idx[count++] = (i*(Ye-Ys) + j)*(Xe-Xs) + k;
496       }
497     }
498     /* the top piece */
499     for (i=up; i<up+IZe-ze; i++) {
500       for (j=bottom; j<top; j++) {
501         for (k=left; k<right; k++) idx[count++] = (i*(Ye-Ys) + j)*(Xe-Xs) + k;
502       }
503     }
504     ierr = ISCreateBlock(comm,dof,count,idx,PETSC_OWN_POINTER,&to);CHKERRQ(ierr);
505   }
506 
507   /* determine who lies on each side of use stored in    n24 n25 n26
508                                                          n21 n22 n23
509                                                          n18 n19 n20
510 
511                                                          n15 n16 n17
512                                                          n12     n14
513                                                          n9  n10 n11
514 
515                                                          n6  n7  n8
516                                                          n3  n4  n5
517                                                          n0  n1  n2
518   */
519 
520   /* Solve for X,Y, and Z Periodic Case First, Then Modify Solution */
521   /* Assume Nodes are Internal to the Cube */
522   n0 = rank - m*n - m - 1;
523   n1 = rank - m*n - m;
524   n2 = rank - m*n - m + 1;
525   n3 = rank - m*n -1;
526   n4 = rank - m*n;
527   n5 = rank - m*n + 1;
528   n6 = rank - m*n + m - 1;
529   n7 = rank - m*n + m;
530   n8 = rank - m*n + m + 1;
531 
532   n9  = rank - m - 1;
533   n10 = rank - m;
534   n11 = rank - m + 1;
535   n12 = rank - 1;
536   n14 = rank + 1;
537   n15 = rank + m - 1;
538   n16 = rank + m;
539   n17 = rank + m + 1;
540 
541   n18 = rank + m*n - m - 1;
542   n19 = rank + m*n - m;
543   n20 = rank + m*n - m + 1;
544   n21 = rank + m*n - 1;
545   n22 = rank + m*n;
546   n23 = rank + m*n + 1;
547   n24 = rank + m*n + m - 1;
548   n25 = rank + m*n + m;
549   n26 = rank + m*n + m + 1;
550 
551   /* Assume Pieces are on Faces of Cube */
552 
553   if (xs == 0) { /* First assume not corner or edge */
554     n0  = rank       -1 - (m*n);
555     n3  = rank + m   -1 - (m*n);
556     n6  = rank + 2*m -1 - (m*n);
557     n9  = rank       -1;
558     n12 = rank + m   -1;
559     n15 = rank + 2*m -1;
560     n18 = rank       -1 + (m*n);
561     n21 = rank + m   -1 + (m*n);
562     n24 = rank + 2*m -1 + (m*n);
563   }
564 
565   if (xe == M) { /* First assume not corner or edge */
566     n2  = rank -2*m +1 - (m*n);
567     n5  = rank - m  +1 - (m*n);
568     n8  = rank      +1 - (m*n);
569     n11 = rank -2*m +1;
570     n14 = rank - m  +1;
571     n17 = rank      +1;
572     n20 = rank -2*m +1 + (m*n);
573     n23 = rank - m  +1 + (m*n);
574     n26 = rank      +1 + (m*n);
575   }
576 
577   if (ys==0) { /* First assume not corner or edge */
578     n0  = rank + m * (n-1) -1 - (m*n);
579     n1  = rank + m * (n-1)    - (m*n);
580     n2  = rank + m * (n-1) +1 - (m*n);
581     n9  = rank + m * (n-1) -1;
582     n10 = rank + m * (n-1);
583     n11 = rank + m * (n-1) +1;
584     n18 = rank + m * (n-1) -1 + (m*n);
585     n19 = rank + m * (n-1)    + (m*n);
586     n20 = rank + m * (n-1) +1 + (m*n);
587   }
588 
589   if (ye == N) { /* First assume not corner or edge */
590     n6  = rank - m * (n-1) -1 - (m*n);
591     n7  = rank - m * (n-1)    - (m*n);
592     n8  = rank - m * (n-1) +1 - (m*n);
593     n15 = rank - m * (n-1) -1;
594     n16 = rank - m * (n-1);
595     n17 = rank - m * (n-1) +1;
596     n24 = rank - m * (n-1) -1 + (m*n);
597     n25 = rank - m * (n-1)    + (m*n);
598     n26 = rank - m * (n-1) +1 + (m*n);
599   }
600 
601   if (zs == 0) { /* First assume not corner or edge */
602     n0 = size - (m*n) + rank - m - 1;
603     n1 = size - (m*n) + rank - m;
604     n2 = size - (m*n) + rank - m + 1;
605     n3 = size - (m*n) + rank - 1;
606     n4 = size - (m*n) + rank;
607     n5 = size - (m*n) + rank + 1;
608     n6 = size - (m*n) + rank + m - 1;
609     n7 = size - (m*n) + rank + m;
610     n8 = size - (m*n) + rank + m + 1;
611   }
612 
613   if (ze == P) { /* First assume not corner or edge */
614     n18 = (m*n) - (size-rank) - m - 1;
615     n19 = (m*n) - (size-rank) - m;
616     n20 = (m*n) - (size-rank) - m + 1;
617     n21 = (m*n) - (size-rank) - 1;
618     n22 = (m*n) - (size-rank);
619     n23 = (m*n) - (size-rank) + 1;
620     n24 = (m*n) - (size-rank) + m - 1;
621     n25 = (m*n) - (size-rank) + m;
622     n26 = (m*n) - (size-rank) + m + 1;
623   }
624 
625   if ((xs==0) && (zs==0)) { /* Assume an edge, not corner */
626     n0 = size - m*n + rank + m-1 - m;
627     n3 = size - m*n + rank + m-1;
628     n6 = size - m*n + rank + m-1 + m;
629   }
630 
631   if ((xs==0) && (ze==P)) { /* Assume an edge, not corner */
632     n18 = m*n - (size - rank) + m-1 - m;
633     n21 = m*n - (size - rank) + m-1;
634     n24 = m*n - (size - rank) + m-1 + m;
635   }
636 
637   if ((xs==0) && (ys==0)) { /* Assume an edge, not corner */
638     n0  = rank + m*n -1 - m*n;
639     n9  = rank + m*n -1;
640     n18 = rank + m*n -1 + m*n;
641   }
642 
643   if ((xs==0) && (ye==N)) { /* Assume an edge, not corner */
644     n6  = rank - m*(n-1) + m-1 - m*n;
645     n15 = rank - m*(n-1) + m-1;
646     n24 = rank - m*(n-1) + m-1 + m*n;
647   }
648 
649   if ((xe==M) && (zs==0)) { /* Assume an edge, not corner */
650     n2 = size - (m*n-rank) - (m-1) - m;
651     n5 = size - (m*n-rank) - (m-1);
652     n8 = size - (m*n-rank) - (m-1) + m;
653   }
654 
655   if ((xe==M) && (ze==P)) { /* Assume an edge, not corner */
656     n20 = m*n - (size - rank) - (m-1) - m;
657     n23 = m*n - (size - rank) - (m-1);
658     n26 = m*n - (size - rank) - (m-1) + m;
659   }
660 
661   if ((xe==M) && (ys==0)) { /* Assume an edge, not corner */
662     n2  = rank + m*(n-1) - (m-1) - m*n;
663     n11 = rank + m*(n-1) - (m-1);
664     n20 = rank + m*(n-1) - (m-1) + m*n;
665   }
666 
667   if ((xe==M) && (ye==N)) { /* Assume an edge, not corner */
668     n8  = rank - m*n +1 - m*n;
669     n17 = rank - m*n +1;
670     n26 = rank - m*n +1 + m*n;
671   }
672 
673   if ((ys==0) && (zs==0)) { /* Assume an edge, not corner */
674     n0 = size - m + rank -1;
675     n1 = size - m + rank;
676     n2 = size - m + rank +1;
677   }
678 
679   if ((ys==0) && (ze==P)) { /* Assume an edge, not corner */
680     n18 = m*n - (size - rank) + m*(n-1) -1;
681     n19 = m*n - (size - rank) + m*(n-1);
682     n20 = m*n - (size - rank) + m*(n-1) +1;
683   }
684 
685   if ((ye==N) && (zs==0)) { /* Assume an edge, not corner */
686     n6 = size - (m*n-rank) - m * (n-1) -1;
687     n7 = size - (m*n-rank) - m * (n-1);
688     n8 = size - (m*n-rank) - m * (n-1) +1;
689   }
690 
691   if ((ye==N) && (ze==P)) { /* Assume an edge, not corner */
692     n24 = rank - (size-m) -1;
693     n25 = rank - (size-m);
694     n26 = rank - (size-m) +1;
695   }
696 
697   /* Check for Corners */
698   if ((xs==0) && (ys==0) && (zs==0)) n0  = size -1;
699   if ((xs==0) && (ys==0) && (ze==P)) n18 = m*n-1;
700   if ((xs==0) && (ye==N) && (zs==0)) n6  = (size-1)-m*(n-1);
701   if ((xs==0) && (ye==N) && (ze==P)) n24 = m-1;
702   if ((xe==M) && (ys==0) && (zs==0)) n2  = size-m;
703   if ((xe==M) && (ys==0) && (ze==P)) n20 = m*n-m;
704   if ((xe==M) && (ye==N) && (zs==0)) n8  = size-m*n;
705   if ((xe==M) && (ye==N) && (ze==P)) n26 = 0;
706 
707   /* Check for when not X,Y, and Z Periodic */
708 
709   /* If not X periodic */
710   if (bx != DM_BOUNDARY_PERIODIC) {
711     if (xs==0) n0 = n3 = n6 = n9  = n12 = n15 = n18 = n21 = n24 = -2;
712     if (xe==M) n2 = n5 = n8 = n11 = n14 = n17 = n20 = n23 = n26 = -2;
713   }
714 
715   /* If not Y periodic */
716   if (by != DM_BOUNDARY_PERIODIC) {
717     if (ys==0) n0 = n1 = n2 = n9  = n10 = n11 = n18 = n19 = n20 = -2;
718     if (ye==N) n6 = n7 = n8 = n15 = n16 = n17 = n24 = n25 = n26 = -2;
719   }
720 
721   /* If not Z periodic */
722   if (bz != DM_BOUNDARY_PERIODIC) {
723     if (zs==0) n0  = n1  = n2  = n3  = n4  = n5  = n6  = n7  = n8  = -2;
724     if (ze==P) n18 = n19 = n20 = n21 = n22 = n23 = n24 = n25 = n26 = -2;
725   }
726 
727   ierr = PetscMalloc1(27,&dd->neighbors);CHKERRQ(ierr);
728 
729   dd->neighbors[0]  = n0;
730   dd->neighbors[1]  = n1;
731   dd->neighbors[2]  = n2;
732   dd->neighbors[3]  = n3;
733   dd->neighbors[4]  = n4;
734   dd->neighbors[5]  = n5;
735   dd->neighbors[6]  = n6;
736   dd->neighbors[7]  = n7;
737   dd->neighbors[8]  = n8;
738   dd->neighbors[9]  = n9;
739   dd->neighbors[10] = n10;
740   dd->neighbors[11] = n11;
741   dd->neighbors[12] = n12;
742   dd->neighbors[13] = rank;
743   dd->neighbors[14] = n14;
744   dd->neighbors[15] = n15;
745   dd->neighbors[16] = n16;
746   dd->neighbors[17] = n17;
747   dd->neighbors[18] = n18;
748   dd->neighbors[19] = n19;
749   dd->neighbors[20] = n20;
750   dd->neighbors[21] = n21;
751   dd->neighbors[22] = n22;
752   dd->neighbors[23] = n23;
753   dd->neighbors[24] = n24;
754   dd->neighbors[25] = n25;
755   dd->neighbors[26] = n26;
756 
757   /* If star stencil then delete the corner neighbors */
758   if (stencil_type == DMDA_STENCIL_STAR) {
759     /* save information about corner neighbors */
760     sn0 = n0; sn1 = n1; sn2 = n2; sn3 = n3; sn5 = n5; sn6 = n6; sn7 = n7;
761     sn8 = n8; sn9 = n9; sn11 = n11; sn15 = n15; sn17 = n17; sn18 = n18;
762     sn19 = n19; sn20 = n20; sn21 = n21; sn23 = n23; sn24 = n24; sn25 = n25;
763     sn26 = n26;
764     n0 = n1 = n2 = n3 = n5 = n6 = n7 = n8 = n9 = n11 = n15 = n17 = n18 = n19 = n20 = n21 = n23 = n24 = n25 = n26 = -1;
765   }
766 
767   ierr = PetscMalloc1((Xe-Xs)*(Ye-Ys)*(Ze-Zs),&idx);CHKERRQ(ierr);
768 
769   nn = 0;
770   /* Bottom Level */
771   for (k=0; k<s_z; k++) {
772     for (i=1; i<=s_y; i++) {
773       if (n0 >= 0) { /* left below */
774         x_t = lx[n0 % m];
775         y_t = ly[(n0 % (m*n))/m];
776         z_t = lz[n0 / (m*n)];
777         s_t = bases[n0] + x_t*y_t*z_t - (s_y-i)*x_t - s_x - (s_z-k-1)*x_t*y_t;
778         if (twod && (s_t < 0)) s_t = bases[n0] + x_t*y_t*z_t - (s_y-i)*x_t - s_x; /* 2D case */
779         for (j=0; j<s_x; j++) idx[nn++] = s_t++;
780       }
781       if (n1 >= 0) { /* directly below */
782         x_t = x;
783         y_t = ly[(n1 % (m*n))/m];
784         z_t = lz[n1 / (m*n)];
785         s_t = bases[n1] + x_t*y_t*z_t - (s_y+1-i)*x_t - (s_z-k-1)*x_t*y_t;
786         if (twod && (s_t < 0)) s_t = bases[n1] + x_t*y_t*z_t - (s_y+1-i)*x_t; /* 2D case */
787         for (j=0; j<x_t; j++) idx[nn++] = s_t++;
788       }
789       if (n2 >= 0) { /* right below */
790         x_t = lx[n2 % m];
791         y_t = ly[(n2 % (m*n))/m];
792         z_t = lz[n2 / (m*n)];
793         s_t = bases[n2] + x_t*y_t*z_t - (s_y+1-i)*x_t - (s_z-k-1)*x_t*y_t;
794         if (twod && (s_t < 0)) s_t = bases[n2] + x_t*y_t*z_t - (s_y+1-i)*x_t; /* 2D case */
795         for (j=0; j<s_x; j++) idx[nn++] = s_t++;
796       }
797     }
798 
799     for (i=0; i<y; i++) {
800       if (n3 >= 0) { /* directly left */
801         x_t = lx[n3 % m];
802         y_t = y;
803         z_t = lz[n3 / (m*n)];
804         s_t = bases[n3] + (i+1)*x_t - s_x + x_t*y_t*z_t - (s_z-k)*x_t*y_t;
805         if (twod && (s_t < 0)) s_t = bases[n3] + (i+1)*x_t - s_x + x_t*y_t*z_t - x_t*y_t; /* 2D case */
806         for (j=0; j<s_x; j++) idx[nn++] = s_t++;
807       }
808 
809       if (n4 >= 0) { /* middle */
810         x_t = x;
811         y_t = y;
812         z_t = lz[n4 / (m*n)];
813         s_t = bases[n4] + i*x_t + x_t*y_t*z_t - (s_z-k)*x_t*y_t;
814         if (twod && (s_t < 0)) s_t = bases[n4] + i*x_t + x_t*y_t*z_t - x_t*y_t; /* 2D case */
815         for (j=0; j<x_t; j++) idx[nn++] = s_t++;
816       } else if (bz == DM_BOUNDARY_MIRROR) {
817         for (j=0; j<x; j++) idx[nn++] = bases[rank] + j + x*i + (s_z - k - 1)*x*y;
818       }
819 
820       if (n5 >= 0) { /* directly right */
821         x_t = lx[n5 % m];
822         y_t = y;
823         z_t = lz[n5 / (m*n)];
824         s_t = bases[n5] + i*x_t + x_t*y_t*z_t - (s_z-k)*x_t*y_t;
825         if (twod && (s_t < 0)) s_t = bases[n5] + i*x_t + x_t*y_t*z_t - x_t*y_t; /* 2D case */
826         for (j=0; j<s_x; j++) idx[nn++] = s_t++;
827       }
828     }
829 
830     for (i=1; i<=s_y; i++) {
831       if (n6 >= 0) { /* left above */
832         x_t = lx[n6 % m];
833         y_t = ly[(n6 % (m*n))/m];
834         z_t = lz[n6 / (m*n)];
835         s_t = bases[n6] + i*x_t - s_x + x_t*y_t*z_t - (s_z-k)*x_t*y_t;
836         if (twod && (s_t < 0)) s_t = bases[n6] + i*x_t - s_x + x_t*y_t*z_t - x_t*y_t; /* 2D case */
837         for (j=0; j<s_x; j++) idx[nn++] = s_t++;
838       }
839       if (n7 >= 0) { /* directly above */
840         x_t = x;
841         y_t = ly[(n7 % (m*n))/m];
842         z_t = lz[n7 / (m*n)];
843         s_t = bases[n7] + (i-1)*x_t + x_t*y_t*z_t - (s_z-k)*x_t*y_t;
844         if (twod && (s_t < 0)) s_t = bases[n7] + (i-1)*x_t + x_t*y_t*z_t - x_t*y_t; /* 2D case */
845         for (j=0; j<x_t; j++) idx[nn++] = s_t++;
846       }
847       if (n8 >= 0) { /* right above */
848         x_t = lx[n8 % m];
849         y_t = ly[(n8 % (m*n))/m];
850         z_t = lz[n8 / (m*n)];
851         s_t = bases[n8] + (i-1)*x_t + x_t*y_t*z_t - (s_z-k)*x_t*y_t;
852         if (twod && (s_t < 0)) s_t = bases[n8] + (i-1)*x_t + x_t*y_t*z_t - x_t*y_t; /* 2D case */
853         for (j=0; j<s_x; j++) idx[nn++] = s_t++;
854       }
855     }
856   }
857 
858   /* Middle Level */
859   for (k=0; k<z; k++) {
860     for (i=1; i<=s_y; i++) {
861       if (n9 >= 0) { /* left below */
862         x_t = lx[n9 % m];
863         y_t = ly[(n9 % (m*n))/m];
864         /* z_t = z; */
865         s_t = bases[n9] - (s_y-i)*x_t -s_x + (k+1)*x_t*y_t;
866         for (j=0; j<s_x; j++) idx[nn++] = s_t++;
867       }
868       if (n10 >= 0) { /* directly below */
869         x_t = x;
870         y_t = ly[(n10 % (m*n))/m];
871         /* z_t = z; */
872         s_t = bases[n10] - (s_y+1-i)*x_t + (k+1)*x_t*y_t;
873         for (j=0; j<x_t; j++) idx[nn++] = s_t++;
874       }  else if (by == DM_BOUNDARY_MIRROR) {
875         for (j=0; j<x; j++) idx[nn++] = bases[rank] + j + k*x*y + (s_y - i)*x;
876       }
877       if (n11 >= 0) { /* right below */
878         x_t = lx[n11 % m];
879         y_t = ly[(n11 % (m*n))/m];
880         /* z_t = z; */
881         s_t = bases[n11] - (s_y+1-i)*x_t + (k+1)*x_t*y_t;
882         for (j=0; j<s_x; j++) idx[nn++] = s_t++;
883       }
884     }
885 
886     for (i=0; i<y; i++) {
887       if (n12 >= 0) { /* directly left */
888         x_t = lx[n12 % m];
889         y_t = y;
890         /* z_t = z; */
891         s_t = bases[n12] + (i+1)*x_t - s_x + k*x_t*y_t;
892         for (j=0; j<s_x; j++) idx[nn++] = s_t++;
893       }  else if (bx == DM_BOUNDARY_MIRROR) {
894         for (j=0; j<s_x; j++) idx[nn++] = bases[rank] + s_x - j - 1 + k*x*y + i*x;
895       }
896 
897       /* Interior */
898       s_t = bases[rank] + i*x + k*x*y;
899       for (j=0; j<x; j++) idx[nn++] = s_t++;
900 
901       if (n14 >= 0) { /* directly right */
902         x_t = lx[n14 % m];
903         y_t = y;
904         /* z_t = z; */
905         s_t = bases[n14] + i*x_t + k*x_t*y_t;
906         for (j=0; j<s_x; j++) idx[nn++] = s_t++;
907       } else if (bx == DM_BOUNDARY_MIRROR) {
908         for (j=0; j<s_x; j++) idx[nn++] = bases[rank] + x - j - 1 + k*x*y + i*x;
909       }
910     }
911 
912     for (i=1; i<=s_y; i++) {
913       if (n15 >= 0) { /* left above */
914         x_t = lx[n15 % m];
915         y_t = ly[(n15 % (m*n))/m];
916         /* z_t = z; */
917         s_t = bases[n15] + i*x_t - s_x + k*x_t*y_t;
918         for (j=0; j<s_x; j++) idx[nn++] = s_t++;
919       }
920       if (n16 >= 0) { /* directly above */
921         x_t = x;
922         y_t = ly[(n16 % (m*n))/m];
923         /* z_t = z; */
924         s_t = bases[n16] + (i-1)*x_t + k*x_t*y_t;
925         for (j=0; j<x_t; j++) idx[nn++] = s_t++;
926       } else if (by == DM_BOUNDARY_MIRROR) {
927         for (j=0; j<x; j++) idx[nn++] = bases[rank] + j + k*x*y + (y-i)*x;
928       }
929       if (n17 >= 0) { /* right above */
930         x_t = lx[n17 % m];
931         y_t = ly[(n17 % (m*n))/m];
932         /* z_t = z; */
933         s_t = bases[n17] + (i-1)*x_t + k*x_t*y_t;
934         for (j=0; j<s_x; j++) idx[nn++] = s_t++;
935       }
936     }
937   }
938 
939   /* Upper Level */
940   for (k=0; k<s_z; k++) {
941     for (i=1; i<=s_y; i++) {
942       if (n18 >= 0) { /* left below */
943         x_t = lx[n18 % m];
944         y_t = ly[(n18 % (m*n))/m];
945         /* z_t = lz[n18 / (m*n)]; */
946         s_t = bases[n18] - (s_y-i)*x_t -s_x + (k+1)*x_t*y_t;
947         if (twod && (s_t >= M*N*P)) s_t = bases[n18] - (s_y-i)*x_t -s_x + x_t*y_t; /* 2d case */
948         for (j=0; j<s_x; j++) idx[nn++] = s_t++;
949       }
950       if (n19 >= 0) { /* directly below */
951         x_t = x;
952         y_t = ly[(n19 % (m*n))/m];
953         /* z_t = lz[n19 / (m*n)]; */
954         s_t = bases[n19] - (s_y+1-i)*x_t + (k+1)*x_t*y_t;
955         if (twod && (s_t >= M*N*P)) s_t = bases[n19] - (s_y+1-i)*x_t + x_t*y_t; /* 2d case */
956         for (j=0; j<x_t; j++) idx[nn++] = s_t++;
957       }
958       if (n20 >= 0) { /* right below */
959         x_t = lx[n20 % m];
960         y_t = ly[(n20 % (m*n))/m];
961         /* z_t = lz[n20 / (m*n)]; */
962         s_t = bases[n20] - (s_y+1-i)*x_t + (k+1)*x_t*y_t;
963         if (twod && (s_t >= M*N*P)) s_t = bases[n20] - (s_y+1-i)*x_t + x_t*y_t; /* 2d case */
964         for (j=0; j<s_x; j++) idx[nn++] = s_t++;
965       }
966     }
967 
968     for (i=0; i<y; i++) {
969       if (n21 >= 0) { /* directly left */
970         x_t = lx[n21 % m];
971         y_t = y;
972         /* z_t = lz[n21 / (m*n)]; */
973         s_t = bases[n21] + (i+1)*x_t - s_x + k*x_t*y_t;
974         if (twod && (s_t >= M*N*P)) s_t = bases[n21] + (i+1)*x_t - s_x;  /* 2d case */
975         for (j=0; j<s_x; j++) idx[nn++] = s_t++;
976       }
977 
978       if (n22 >= 0) { /* middle */
979         x_t = x;
980         y_t = y;
981         /* z_t = lz[n22 / (m*n)]; */
982         s_t = bases[n22] + i*x_t + k*x_t*y_t;
983         if (twod && (s_t >= M*N*P)) s_t = bases[n22] + i*x_t; /* 2d case */
984         for (j=0; j<x_t; j++) idx[nn++] = s_t++;
985       } else if (bz == DM_BOUNDARY_MIRROR) {
986         for (j=0; j<x; j++) idx[nn++] = bases[rank] + j + (z-k-1)*x*y + i*x;
987       }
988 
989       if (n23 >= 0) { /* directly right */
990         x_t = lx[n23 % m];
991         y_t = y;
992         /* z_t = lz[n23 / (m*n)]; */
993         s_t = bases[n23] + i*x_t + k*x_t*y_t;
994         if (twod && (s_t >= M*N*P)) s_t = bases[n23] + i*x_t; /* 2d case */
995         for (j=0; j<s_x; j++) idx[nn++] = s_t++;
996       }
997     }
998 
999     for (i=1; i<=s_y; i++) {
1000       if (n24 >= 0) { /* left above */
1001         x_t = lx[n24 % m];
1002         y_t = ly[(n24 % (m*n))/m];
1003         /* z_t = lz[n24 / (m*n)]; */
1004         s_t = bases[n24] + i*x_t - s_x + k*x_t*y_t;
1005         if (twod && (s_t >= M*N*P)) s_t = bases[n24] + i*x_t - s_x; /* 2d case */
1006         for (j=0; j<s_x; j++) idx[nn++] = s_t++;
1007       }
1008       if (n25 >= 0) { /* directly above */
1009         x_t = x;
1010         y_t = ly[(n25 % (m*n))/m];
1011         /* z_t = lz[n25 / (m*n)]; */
1012         s_t = bases[n25] + (i-1)*x_t + k*x_t*y_t;
1013         if (twod && (s_t >= M*N*P)) s_t = bases[n25] + (i-1)*x_t; /* 2d case */
1014         for (j=0; j<x_t; j++) idx[nn++] = s_t++;
1015       }
1016       if (n26 >= 0) { /* right above */
1017         x_t = lx[n26 % m];
1018         y_t = ly[(n26 % (m*n))/m];
1019         /* z_t = lz[n26 / (m*n)]; */
1020         s_t = bases[n26] + (i-1)*x_t + k*x_t*y_t;
1021         if (twod && (s_t >= M*N*P)) s_t = bases[n26] + (i-1)*x_t; /* 2d case */
1022         for (j=0; j<s_x; j++) idx[nn++] = s_t++;
1023       }
1024     }
1025   }
1026 
1027   ierr = ISCreateBlock(comm,dof,nn,idx,PETSC_USE_POINTER,&from);CHKERRQ(ierr);
1028   ierr = VecScatterCreate(global,from,local,to,&gtol);CHKERRQ(ierr);
1029   ierr = PetscLogObjectParent((PetscObject)da,(PetscObject)gtol);CHKERRQ(ierr);
1030   ierr = ISDestroy(&to);CHKERRQ(ierr);
1031   ierr = ISDestroy(&from);CHKERRQ(ierr);
1032 
1033   if (stencil_type == DMDA_STENCIL_STAR) {
1034     n0  = sn0;  n1  = sn1;  n2  = sn2;  n3  = sn3;  n5  = sn5;  n6  = sn6; n7 = sn7;
1035     n8  = sn8;  n9  = sn9;  n11 = sn11; n15 = sn15; n17 = sn17; n18 = sn18;
1036     n19 = sn19; n20 = sn20; n21 = sn21; n23 = sn23; n24 = sn24; n25 = sn25;
1037     n26 = sn26;
1038   }
1039 
1040   if (((stencil_type == DMDA_STENCIL_STAR) || (bx != DM_BOUNDARY_PERIODIC && bx) || (by != DM_BOUNDARY_PERIODIC && by) || (bz != DM_BOUNDARY_PERIODIC && bz))) {
1041     /*
1042         Recompute the local to global mappings, this time keeping the
1043       information about the cross corner processor numbers.
1044     */
1045     nn = 0;
1046     /* Bottom Level */
1047     for (k=0; k<s_z; k++) {
1048       for (i=1; i<=s_y; i++) {
1049         if (n0 >= 0) { /* left below */
1050           x_t = lx[n0 % m];
1051           y_t = ly[(n0 % (m*n))/m];
1052           z_t = lz[n0 / (m*n)];
1053           s_t = bases[n0] + x_t*y_t*z_t - (s_y-i)*x_t - s_x - (s_z-k-1)*x_t*y_t;
1054           for (j=0; j<s_x; j++) idx[nn++] = s_t++;
1055         } else if (Xs-xs < 0 && Ys-ys < 0 && Zs-zs < 0) {
1056           for (j=0; j<s_x; j++) idx[nn++] = -1;
1057         }
1058         if (n1 >= 0) { /* directly below */
1059           x_t = x;
1060           y_t = ly[(n1 % (m*n))/m];
1061           z_t = lz[n1 / (m*n)];
1062           s_t = bases[n1] + x_t*y_t*z_t - (s_y+1-i)*x_t - (s_z-k-1)*x_t*y_t;
1063           for (j=0; j<x_t; j++) idx[nn++] = s_t++;
1064         } else if (Ys-ys < 0 && Zs-zs < 0) {
1065           for (j=0; j<x; j++) idx[nn++] = -1;
1066         }
1067         if (n2 >= 0) { /* right below */
1068           x_t = lx[n2 % m];
1069           y_t = ly[(n2 % (m*n))/m];
1070           z_t = lz[n2 / (m*n)];
1071           s_t = bases[n2] + x_t*y_t*z_t - (s_y+1-i)*x_t - (s_z-k-1)*x_t*y_t;
1072           for (j=0; j<s_x; j++) idx[nn++] = s_t++;
1073         } else if (xe-Xe < 0 && Ys-ys < 0 && Zs-zs < 0) {
1074           for (j=0; j<s_x; j++) idx[nn++] = -1;
1075         }
1076       }
1077 
1078       for (i=0; i<y; i++) {
1079         if (n3 >= 0) { /* directly left */
1080           x_t = lx[n3 % m];
1081           y_t = y;
1082           z_t = lz[n3 / (m*n)];
1083           s_t = bases[n3] + (i+1)*x_t - s_x + x_t*y_t*z_t - (s_z-k)*x_t*y_t;
1084           for (j=0; j<s_x; j++) idx[nn++] = s_t++;
1085         } else if (Xs-xs < 0 && Zs-zs < 0) {
1086           for (j=0; j<s_x; j++) idx[nn++] = -1;
1087         }
1088 
1089         if (n4 >= 0) { /* middle */
1090           x_t = x;
1091           y_t = y;
1092           z_t = lz[n4 / (m*n)];
1093           s_t = bases[n4] + i*x_t + x_t*y_t*z_t - (s_z-k)*x_t*y_t;
1094           for (j=0; j<x_t; j++) idx[nn++] = s_t++;
1095         } else if (Zs-zs < 0) {
1096           if (bz == DM_BOUNDARY_MIRROR) {
1097             for (j=0; j<x; j++) idx[nn++] = bases[rank] + j + x*i + (s_z - k - 1)*x*y;
1098           } else {
1099             for (j=0; j<x; j++) idx[nn++] = -1;
1100           }
1101         }
1102 
1103         if (n5 >= 0) { /* directly right */
1104           x_t = lx[n5 % m];
1105           y_t = y;
1106           z_t = lz[n5 / (m*n)];
1107           s_t = bases[n5] + i*x_t + x_t*y_t*z_t - (s_z-k)*x_t*y_t;
1108           for (j=0; j<s_x; j++) idx[nn++] = s_t++;
1109         } else if (xe-Xe < 0 && Zs-zs < 0) {
1110           for (j=0; j<s_x; j++) idx[nn++] = -1;
1111         }
1112       }
1113 
1114       for (i=1; i<=s_y; i++) {
1115         if (n6 >= 0) { /* left above */
1116           x_t = lx[n6 % m];
1117           y_t = ly[(n6 % (m*n))/m];
1118           z_t = lz[n6 / (m*n)];
1119           s_t = bases[n6] + i*x_t - s_x + x_t*y_t*z_t - (s_z-k)*x_t*y_t;
1120           for (j=0; j<s_x; j++) idx[nn++] = s_t++;
1121         } else if (Xs-xs < 0 && ye-Ye < 0 && Zs-zs < 0) {
1122           for (j=0; j<s_x; j++) idx[nn++] = -1;
1123         }
1124         if (n7 >= 0) { /* directly above */
1125           x_t = x;
1126           y_t = ly[(n7 % (m*n))/m];
1127           z_t = lz[n7 / (m*n)];
1128           s_t = bases[n7] + (i-1)*x_t + x_t*y_t*z_t - (s_z-k)*x_t*y_t;
1129           for (j=0; j<x_t; j++) idx[nn++] = s_t++;
1130         } else if (ye-Ye < 0 && Zs-zs < 0) {
1131           for (j=0; j<x; j++) idx[nn++] = -1;
1132         }
1133         if (n8 >= 0) { /* right above */
1134           x_t = lx[n8 % m];
1135           y_t = ly[(n8 % (m*n))/m];
1136           z_t = lz[n8 / (m*n)];
1137           s_t = bases[n8] + (i-1)*x_t + x_t*y_t*z_t - (s_z-k)*x_t*y_t;
1138           for (j=0; j<s_x; j++) idx[nn++] = s_t++;
1139         } else if (xe-Xe < 0 && ye-Ye < 0 && Zs-zs < 0) {
1140           for (j=0; j<s_x; j++) idx[nn++] = -1;
1141         }
1142       }
1143     }
1144 
1145     /* Middle Level */
1146     for (k=0; k<z; k++) {
1147       for (i=1; i<=s_y; i++) {
1148         if (n9 >= 0) { /* left below */
1149           x_t = lx[n9 % m];
1150           y_t = ly[(n9 % (m*n))/m];
1151           /* z_t = z; */
1152           s_t = bases[n9] - (s_y-i)*x_t -s_x + (k+1)*x_t*y_t;
1153           for (j=0; j<s_x; j++) idx[nn++] = s_t++;
1154         } else if (Xs-xs < 0 && Ys-ys < 0) {
1155           for (j=0; j<s_x; j++) idx[nn++] = -1;
1156         }
1157         if (n10 >= 0) { /* directly below */
1158           x_t = x;
1159           y_t = ly[(n10 % (m*n))/m];
1160           /* z_t = z; */
1161           s_t = bases[n10] - (s_y+1-i)*x_t + (k+1)*x_t*y_t;
1162           for (j=0; j<x_t; j++) idx[nn++] = s_t++;
1163         } else if (Ys-ys < 0) {
1164           if (by == DM_BOUNDARY_MIRROR) {
1165             for (j=0; j<x; j++) idx[nn++] = bases[rank] + j + k*x*y + (s_y - i)*x;
1166           } else {
1167             for (j=0; j<x; j++) idx[nn++] = -1;
1168           }
1169         }
1170         if (n11 >= 0) { /* right below */
1171           x_t = lx[n11 % m];
1172           y_t = ly[(n11 % (m*n))/m];
1173           /* z_t = z; */
1174           s_t = bases[n11] - (s_y+1-i)*x_t + (k+1)*x_t*y_t;
1175           for (j=0; j<s_x; j++) idx[nn++] = s_t++;
1176         } else if (xe-Xe < 0 && Ys-ys < 0) {
1177           for (j=0; j<s_x; j++) idx[nn++] = -1;
1178         }
1179       }
1180 
1181       for (i=0; i<y; i++) {
1182         if (n12 >= 0) { /* directly left */
1183           x_t = lx[n12 % m];
1184           y_t = y;
1185           /* z_t = z; */
1186           s_t = bases[n12] + (i+1)*x_t - s_x + k*x_t*y_t;
1187           for (j=0; j<s_x; j++) idx[nn++] = s_t++;
1188         } else if (Xs-xs < 0) {
1189           if (bx == DM_BOUNDARY_MIRROR) {
1190             for (j=0; j<s_x; j++) idx[nn++] = bases[rank] + s_x - j - 1 + k*x*y + i*x;
1191           } else {
1192             for (j=0; j<s_x; j++) idx[nn++] = -1;
1193           }
1194         }
1195 
1196         /* Interior */
1197         s_t = bases[rank] + i*x + k*x*y;
1198         for (j=0; j<x; j++) idx[nn++] = s_t++;
1199 
1200         if (n14 >= 0) { /* directly right */
1201           x_t = lx[n14 % m];
1202           y_t = y;
1203           /* z_t = z; */
1204           s_t = bases[n14] + i*x_t + k*x_t*y_t;
1205           for (j=0; j<s_x; j++) idx[nn++] = s_t++;
1206         } else if (xe-Xe < 0) {
1207           if (bx == DM_BOUNDARY_MIRROR) {
1208             for (j=0; j<s_x; j++) idx[nn++] = bases[rank] + x - j - 1 + k*x*y + i*x;
1209           } else {
1210             for (j=0; j<s_x; j++) idx[nn++] = -1;
1211           }
1212         }
1213       }
1214 
1215       for (i=1; i<=s_y; i++) {
1216         if (n15 >= 0) { /* left above */
1217           x_t = lx[n15 % m];
1218           y_t = ly[(n15 % (m*n))/m];
1219           /* z_t = z; */
1220           s_t = bases[n15] + i*x_t - s_x + k*x_t*y_t;
1221           for (j=0; j<s_x; j++) idx[nn++] = s_t++;
1222         } else if (Xs-xs < 0 && ye-Ye < 0) {
1223           for (j=0; j<s_x; j++) idx[nn++] = -1;
1224         }
1225         if (n16 >= 0) { /* directly above */
1226           x_t = x;
1227           y_t = ly[(n16 % (m*n))/m];
1228           /* z_t = z; */
1229           s_t = bases[n16] + (i-1)*x_t + k*x_t*y_t;
1230           for (j=0; j<x_t; j++) idx[nn++] = s_t++;
1231         } else if (ye-Ye < 0) {
1232           if (by == DM_BOUNDARY_MIRROR) {
1233             for (j=0; j<x; j++) idx[nn++] = bases[rank] + j + k*x*y + (y-i)*x;
1234           } else {
1235             for (j=0; j<x; j++) idx[nn++] = -1;
1236           }
1237         }
1238         if (n17 >= 0) { /* right above */
1239           x_t = lx[n17 % m];
1240           y_t = ly[(n17 % (m*n))/m];
1241           /* z_t = z; */
1242           s_t = bases[n17] + (i-1)*x_t + k*x_t*y_t;
1243           for (j=0; j<s_x; j++) idx[nn++] = s_t++;
1244         } else if (xe-Xe < 0 && ye-Ye < 0) {
1245           for (j=0; j<s_x; j++) idx[nn++] = -1;
1246         }
1247       }
1248     }
1249 
1250     /* Upper Level */
1251     for (k=0; k<s_z; k++) {
1252       for (i=1; i<=s_y; i++) {
1253         if (n18 >= 0) { /* left below */
1254           x_t = lx[n18 % m];
1255           y_t = ly[(n18 % (m*n))/m];
1256           /* z_t = lz[n18 / (m*n)]; */
1257           s_t = bases[n18] - (s_y-i)*x_t -s_x + (k+1)*x_t*y_t;
1258           for (j=0; j<s_x; j++) idx[nn++] = s_t++;
1259         } else if (Xs-xs < 0 && Ys-ys < 0 && ze-Ze < 0) {
1260           for (j=0; j<s_x; j++) idx[nn++] = -1;
1261         }
1262         if (n19 >= 0) { /* directly below */
1263           x_t = x;
1264           y_t = ly[(n19 % (m*n))/m];
1265           /* z_t = lz[n19 / (m*n)]; */
1266           s_t = bases[n19] - (s_y+1-i)*x_t + (k+1)*x_t*y_t;
1267           for (j=0; j<x_t; j++) idx[nn++] = s_t++;
1268         } else if (Ys-ys < 0 && ze-Ze < 0) {
1269           for (j=0; j<x; j++) idx[nn++] = -1;
1270         }
1271         if (n20 >= 0) { /* right below */
1272           x_t = lx[n20 % m];
1273           y_t = ly[(n20 % (m*n))/m];
1274           /* z_t = lz[n20 / (m*n)]; */
1275           s_t = bases[n20] - (s_y+1-i)*x_t + (k+1)*x_t*y_t;
1276           for (j=0; j<s_x; j++) idx[nn++] = s_t++;
1277         } else if (xe-Xe < 0 && Ys-ys < 0 && ze-Ze < 0) {
1278           for (j=0; j<s_x; j++) idx[nn++] = -1;
1279         }
1280       }
1281 
1282       for (i=0; i<y; i++) {
1283         if (n21 >= 0) { /* directly left */
1284           x_t = lx[n21 % m];
1285           y_t = y;
1286           /* z_t = lz[n21 / (m*n)]; */
1287           s_t = bases[n21] + (i+1)*x_t - s_x + k*x_t*y_t;
1288           for (j=0; j<s_x; j++) idx[nn++] = s_t++;
1289         } else if (Xs-xs < 0 && ze-Ze < 0) {
1290           for (j=0; j<s_x; j++) idx[nn++] = -1;
1291         }
1292 
1293         if (n22 >= 0) { /* middle */
1294           x_t = x;
1295           y_t = y;
1296           /* z_t = lz[n22 / (m*n)]; */
1297           s_t = bases[n22] + i*x_t + k*x_t*y_t;
1298           for (j=0; j<x_t; j++) idx[nn++] = s_t++;
1299         } else if (ze-Ze < 0) {
1300           if (bz == DM_BOUNDARY_MIRROR) {
1301             for (j=0; j<x; j++) idx[nn++] = bases[rank] + j + (z-k-1)*x*y + i*x;
1302           } else {
1303             for (j=0; j<x; j++) idx[nn++] = -1;
1304           }
1305         }
1306 
1307         if (n23 >= 0) { /* directly right */
1308           x_t = lx[n23 % m];
1309           y_t = y;
1310           /* z_t = lz[n23 / (m*n)]; */
1311           s_t = bases[n23] + i*x_t + k*x_t*y_t;
1312           for (j=0; j<s_x; j++) idx[nn++] = s_t++;
1313         } else if (xe-Xe < 0 && ze-Ze < 0) {
1314           for (j=0; j<s_x; j++) idx[nn++] = -1;
1315         }
1316       }
1317 
1318       for (i=1; i<=s_y; i++) {
1319         if (n24 >= 0) { /* left above */
1320           x_t = lx[n24 % m];
1321           y_t = ly[(n24 % (m*n))/m];
1322           /* z_t = lz[n24 / (m*n)]; */
1323           s_t = bases[n24] + i*x_t - s_x + k*x_t*y_t;
1324           for (j=0; j<s_x; j++) idx[nn++] = s_t++;
1325         } else if (Xs-xs < 0 && ye-Ye < 0 && ze-Ze < 0) {
1326           for (j=0; j<s_x; j++) idx[nn++] = -1;
1327         }
1328         if (n25 >= 0) { /* directly above */
1329           x_t = x;
1330           y_t = ly[(n25 % (m*n))/m];
1331           /* z_t = lz[n25 / (m*n)]; */
1332           s_t = bases[n25] + (i-1)*x_t + k*x_t*y_t;
1333           for (j=0; j<x_t; j++) idx[nn++] = s_t++;
1334         } else if (ye-Ye < 0 && ze-Ze < 0) {
1335           for (j=0; j<x; j++) idx[nn++] = -1;
1336         }
1337         if (n26 >= 0) { /* right above */
1338           x_t = lx[n26 % m];
1339           y_t = ly[(n26 % (m*n))/m];
1340           /* z_t = lz[n26 / (m*n)]; */
1341           s_t = bases[n26] + (i-1)*x_t + k*x_t*y_t;
1342           for (j=0; j<s_x; j++) idx[nn++] = s_t++;
1343         } else if (xe-Xe < 0 && ye-Ye < 0 && ze-Ze < 0) {
1344           for (j=0; j<s_x; j++) idx[nn++] = -1;
1345         }
1346       }
1347     }
1348   }
1349   /*
1350      Set the local to global ordering in the global vector, this allows use
1351      of VecSetValuesLocal().
1352   */
1353   ierr = ISLocalToGlobalMappingCreate(comm,dof,nn,idx,PETSC_OWN_POINTER,&da->ltogmap);CHKERRQ(ierr);
1354   ierr = PetscLogObjectParent((PetscObject)da,(PetscObject)da->ltogmap);CHKERRQ(ierr);
1355 
1356   ierr  = PetscFree2(bases,ldims);CHKERRQ(ierr);
1357   dd->m = m;  dd->n  = n;  dd->p  = p;
1358   /* note petsc expects xs/xe/Xs/Xe to be multiplied by #dofs in many places */
1359   dd->xs = xs*dof; dd->xe = xe*dof; dd->ys = ys; dd->ye = ye; dd->zs = zs; dd->ze = ze;
1360   dd->Xs = Xs*dof; dd->Xe = Xe*dof; dd->Ys = Ys; dd->Ye = Ye; dd->Zs = Zs; dd->Ze = Ze;
1361 
1362   ierr = VecDestroy(&local);CHKERRQ(ierr);
1363   ierr = VecDestroy(&global);CHKERRQ(ierr);
1364 
1365   dd->gtol      = gtol;
1366   dd->base      = base;
1367   da->ops->view = DMView_DA_3d;
1368   dd->ltol      = NULL;
1369   dd->ao        = NULL;
1370   PetscFunctionReturn(0);
1371 }
1372 
1373 /*@C
1374    DMDACreate3d - Creates an object that will manage the communication of three-dimensional
1375    regular array data that is distributed across some processors.
1376 
1377    Collective
1378 
1379    Input Parameters:
1380 +  comm - MPI communicator
1381 .  bx,by,bz - type of ghost nodes the array have.
1382          Use one of DM_BOUNDARY_NONE, DM_BOUNDARY_GHOSTED, DM_BOUNDARY_PERIODIC.
1383 .  stencil_type - Type of stencil (DMDA_STENCIL_STAR or DMDA_STENCIL_BOX)
1384 .  M,N,P - global dimension in each direction of the array
1385 .  m,n,p - corresponding number of processors in each dimension
1386            (or PETSC_DECIDE to have calculated)
1387 .  dof - number of degrees of freedom per node
1388 .  s - stencil width
1389 -  lx, ly, lz - arrays containing the number of nodes in each cell along
1390           the x, y, and z coordinates, or NULL. If non-null, these
1391           must be of length as m,n,p and the corresponding
1392           m,n, or p cannot be PETSC_DECIDE. Sum of the lx[] entries must be M, sum of
1393           the ly[] must N, sum of the lz[] must be P
1394 
1395    Output Parameter:
1396 .  da - the resulting distributed array object
1397 
1398    Options Database Key:
1399 +  -dm_view - Calls DMView() at the conclusion of DMDACreate3d()
1400 .  -da_grid_x <nx> - number of grid points in x direction
1401 .  -da_grid_y <ny> - number of grid points in y direction
1402 .  -da_grid_z <nz> - number of grid points in z direction
1403 .  -da_processors_x <MX> - number of processors in x direction
1404 .  -da_processors_y <MY> - number of processors in y direction
1405 .  -da_processors_z <MZ> - number of processors in z direction
1406 .  -da_refine_x <rx> - refinement ratio in x direction
1407 .  -da_refine_y <ry> - refinement ratio in y direction
1408 .  -da_refine_z <rz>- refinement ratio in z directio
1409 -  -da_refine <n> - refine the DMDA n times before creating it
1410 
1411    Level: beginner
1412 
1413    Notes:
1414    The stencil type DMDA_STENCIL_STAR with width 1 corresponds to the
1415    standard 7-pt stencil, while DMDA_STENCIL_BOX with width 1 denotes
1416    the standard 27-pt stencil.
1417 
1418    The array data itself is NOT stored in the DMDA, it is stored in Vec objects;
1419    The appropriate vector objects can be obtained with calls to DMCreateGlobalVector()
1420    and DMCreateLocalVector() and calls to VecDuplicate() if more are needed.
1421 
1422    You must call DMSetUp() after this call before using this DM.
1423 
1424    If you wish to use the options database to change values in the DMDA call DMSetFromOptions() after this call
1425    but before DMSetUp().
1426 
1427 .seealso: DMDestroy(), DMView(), DMDACreate1d(), DMDACreate2d(), DMGlobalToLocalBegin(), DMDAGetRefinementFactor(),
1428           DMGlobalToLocalEnd(), DMLocalToGlobalBegin(), DMLocalToLocalBegin(), DMLocalToLocalEnd(), DMDASetRefinementFactor(),
1429           DMDAGetInfo(), DMCreateGlobalVector(), DMCreateLocalVector(), DMDACreateNaturalVector(), DMLoad(), DMDAGetOwnershipRanges(),
1430           DMStagCreate3d()
1431 
1432 @*/
1433 PetscErrorCode  DMDACreate3d(MPI_Comm comm,DMBoundaryType bx,DMBoundaryType by,DMBoundaryType bz,DMDAStencilType stencil_type,PetscInt M,
1434                PetscInt N,PetscInt P,PetscInt m,PetscInt n,PetscInt p,PetscInt dof,PetscInt s,const PetscInt lx[],const PetscInt ly[],const PetscInt lz[],DM *da)
1435 {
1436   PetscErrorCode ierr;
1437 
1438   PetscFunctionBegin;
1439   ierr = DMDACreate(comm, da);CHKERRQ(ierr);
1440   ierr = DMSetDimension(*da, 3);CHKERRQ(ierr);
1441   ierr = DMDASetSizes(*da, M, N, P);CHKERRQ(ierr);
1442   ierr = DMDASetNumProcs(*da, m, n, p);CHKERRQ(ierr);
1443   ierr = DMDASetBoundaryType(*da, bx, by, bz);CHKERRQ(ierr);
1444   ierr = DMDASetDof(*da, dof);CHKERRQ(ierr);
1445   ierr = DMDASetStencilType(*da, stencil_type);CHKERRQ(ierr);
1446   ierr = DMDASetStencilWidth(*da, s);CHKERRQ(ierr);
1447   ierr = DMDASetOwnershipRanges(*da, lx, ly, lz);CHKERRQ(ierr);
1448   PetscFunctionReturn(0);
1449 }
1450