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