xref: /petsc/src/dm/impls/da/da3.c (revision 12b4a53753ecbae42c98ba33876a303b79054923)
147c6ae99SBarry Smith /*
247c6ae99SBarry Smith    Code for manipulating distributed regular 3d arrays in parallel.
347c6ae99SBarry Smith    File created by Peter Mell  7/14/95
447c6ae99SBarry Smith  */
547c6ae99SBarry Smith 
6af0996ceSBarry Smith #include <petsc/private/dmdaimpl.h> /*I   "petscdmda.h"    I*/
747c6ae99SBarry Smith 
89804daf3SBarry Smith #include <petscdraw.h>
9d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMView_DA_3d(DM da, PetscViewer viewer)
10d71ae5a4SJacob Faibussowitsch {
1147c6ae99SBarry Smith   PetscMPIInt rank;
12c9493c35SStefano Zampini   PetscBool   iascii, isdraw, isglvis, isbinary;
1347c6ae99SBarry Smith   DM_DA      *dd = (DM_DA *)da->data;
146858538eSMatthew G. Knepley   Vec         coordinates;
15d1e78c4fSBarry Smith #if defined(PETSC_HAVE_MATLAB)
169a42bb27SBarry Smith   PetscBool ismatlab;
179a42bb27SBarry Smith #endif
1847c6ae99SBarry Smith 
1947c6ae99SBarry Smith   PetscFunctionBegin;
209566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)da), &rank));
2147c6ae99SBarry Smith 
229566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
239566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw));
249566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERGLVIS, &isglvis));
259566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &isbinary));
26d1e78c4fSBarry Smith #if defined(PETSC_HAVE_MATLAB)
279566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERMATLAB, &ismatlab));
289a42bb27SBarry Smith #endif
2947c6ae99SBarry Smith   if (iascii) {
3047c6ae99SBarry Smith     PetscViewerFormat format;
3147c6ae99SBarry Smith 
329566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPushSynchronized(viewer));
339566063dSJacob Faibussowitsch     PetscCall(PetscViewerGetFormat(viewer, &format));
3476a8abe0SBarry Smith     if (format == PETSC_VIEWER_LOAD_BALANCE) {
3576a8abe0SBarry Smith       PetscInt      i, nmax = 0, nmin = PETSC_MAX_INT, navg = 0, *nz, nzlocal;
3676a8abe0SBarry Smith       DMDALocalInfo info;
3776a8abe0SBarry Smith       PetscMPIInt   size;
389566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)da), &size));
399566063dSJacob Faibussowitsch       PetscCall(DMDAGetLocalInfo(da, &info));
4076a8abe0SBarry Smith       nzlocal = info.xm * info.ym * info.zm;
419566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(size, &nz));
429566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Allgather(&nzlocal, 1, MPIU_INT, nz, 1, MPIU_INT, PetscObjectComm((PetscObject)da)));
4376a8abe0SBarry Smith       for (i = 0; i < (PetscInt)size; i++) {
4476a8abe0SBarry Smith         nmax = PetscMax(nmax, nz[i]);
4576a8abe0SBarry Smith         nmin = PetscMin(nmin, nz[i]);
4676a8abe0SBarry Smith         navg += nz[i];
4776a8abe0SBarry Smith       }
489566063dSJacob Faibussowitsch       PetscCall(PetscFree(nz));
4976a8abe0SBarry Smith       navg = navg / size;
5063a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  Load Balance - Grid Points: Min %" PetscInt_FMT "  avg %" PetscInt_FMT "  max %" PetscInt_FMT "\n", nmin, navg, nmax));
513ba16761SJacob Faibussowitsch       PetscFunctionReturn(PETSC_SUCCESS);
5276a8abe0SBarry Smith     }
538ec8862eSJed Brown     if (format != PETSC_VIEWER_ASCII_VTK_DEPRECATED && format != PETSC_VIEWER_ASCII_VTK_CELL_DEPRECATED && format != PETSC_VIEWER_ASCII_GLVIS) {
54aa219208SBarry Smith       DMDALocalInfo info;
559566063dSJacob Faibussowitsch       PetscCall(DMDAGetLocalInfo(da, &info));
5663a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "Processor [%d] M %" PetscInt_FMT " N %" PetscInt_FMT " P %" PetscInt_FMT " m %" PetscInt_FMT " n %" PetscInt_FMT " p %" PetscInt_FMT " w %" PetscInt_FMT " s %" PetscInt_FMT "\n", rank, dd->M, dd->N, dd->P, dd->m, dd->n, dd->p, dd->w, dd->s));
579371c9d4SSatish Balay       PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "X range of indices: %" PetscInt_FMT " %" PetscInt_FMT ", Y range of indices: %" PetscInt_FMT " %" PetscInt_FMT ", Z range of indices: %" PetscInt_FMT " %" PetscInt_FMT "\n", info.xs,
589371c9d4SSatish Balay                                                    info.xs + info.xm, info.ys, info.ys + info.ym, info.zs, info.zs + info.zm));
596858538eSMatthew G. Knepley       PetscCall(DMGetCoordinates(da, &coordinates));
6047c6ae99SBarry Smith #if !defined(PETSC_USE_COMPLEX)
616858538eSMatthew G. Knepley       if (coordinates) {
6247c6ae99SBarry Smith         PetscInt         last;
6347c6ae99SBarry Smith         const PetscReal *coors;
646858538eSMatthew G. Knepley         PetscCall(VecGetArrayRead(coordinates, &coors));
656858538eSMatthew G. Knepley         PetscCall(VecGetLocalSize(coordinates, &last));
6647c6ae99SBarry Smith         last = last - 3;
679566063dSJacob Faibussowitsch         PetscCall(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]));
686858538eSMatthew G. Knepley         PetscCall(VecRestoreArrayRead(coordinates, &coors));
6947c6ae99SBarry Smith       }
7047c6ae99SBarry Smith #endif
719566063dSJacob Faibussowitsch       PetscCall(PetscViewerFlush(viewer));
729566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPopSynchronized(viewer));
731baa6e33SBarry Smith     } else if (format == PETSC_VIEWER_ASCII_GLVIS) PetscCall(DMView_DA_GLVis(da, viewer));
741baa6e33SBarry Smith     else PetscCall(DMView_DA_VTK(da, viewer));
7547c6ae99SBarry Smith   } else if (isdraw) {
7647c6ae99SBarry Smith     PetscDraw       draw;
7747c6ae99SBarry Smith     PetscReal       ymin = -1.0, ymax = (PetscReal)dd->N;
7847c6ae99SBarry Smith     PetscReal       xmin = -1.0, xmax = (PetscReal)((dd->M + 2) * dd->P), x, y, ycoord, xcoord;
798ea3bf28SBarry Smith     PetscInt        k, plane, base;
808ea3bf28SBarry Smith     const PetscInt *idx;
8147c6ae99SBarry Smith     char            node[10];
8247c6ae99SBarry Smith     PetscBool       isnull;
8347c6ae99SBarry Smith 
849566063dSJacob Faibussowitsch     PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw));
859566063dSJacob Faibussowitsch     PetscCall(PetscDrawIsNull(draw, &isnull));
863ba16761SJacob Faibussowitsch     if (isnull) PetscFunctionReturn(PETSC_SUCCESS);
8747c6ae99SBarry Smith 
889566063dSJacob Faibussowitsch     PetscCall(PetscDrawCheckResizedWindow(draw));
899566063dSJacob Faibussowitsch     PetscCall(PetscDrawClear(draw));
909566063dSJacob Faibussowitsch     PetscCall(PetscDrawSetCoordinates(draw, xmin, ymin, xmax, ymax));
915b399a63SLisandro Dalcin 
92d0609cedSBarry Smith     PetscDrawCollectiveBegin(draw);
9347c6ae99SBarry Smith     /* first processor draw all node lines */
94dd400576SPatrick Sanan     if (rank == 0) {
9547c6ae99SBarry Smith       for (k = 0; k < dd->P; k++) {
969371c9d4SSatish Balay         ymin = 0.0;
979371c9d4SSatish Balay         ymax = (PetscReal)(dd->N - 1);
9848a46eb9SPierre Jolivet         for (xmin = (PetscReal)(k * (dd->M + 1)); xmin < (PetscReal)(dd->M + (k * (dd->M + 1))); xmin++) PetscCall(PetscDrawLine(draw, xmin, ymin, xmin, ymax, PETSC_DRAW_BLACK));
999371c9d4SSatish Balay         xmin = (PetscReal)(k * (dd->M + 1));
1009371c9d4SSatish Balay         xmax = xmin + (PetscReal)(dd->M - 1);
10148a46eb9SPierre Jolivet         for (ymin = 0; ymin < (PetscReal)dd->N; ymin++) PetscCall(PetscDrawLine(draw, xmin, ymin, xmax, ymin, PETSC_DRAW_BLACK));
10247c6ae99SBarry Smith       }
10347c6ae99SBarry Smith     }
104d0609cedSBarry Smith     PetscDrawCollectiveEnd(draw);
1059566063dSJacob Faibussowitsch     PetscCall(PetscDrawFlush(draw));
1069566063dSJacob Faibussowitsch     PetscCall(PetscDrawPause(draw));
10747c6ae99SBarry Smith 
108d0609cedSBarry Smith     PetscDrawCollectiveBegin(draw);
1095b399a63SLisandro Dalcin     /*Go through and draw for each plane*/
1105b399a63SLisandro Dalcin     for (k = 0; k < dd->P; k++) {
11147c6ae99SBarry Smith       if ((k >= dd->zs) && (k < dd->ze)) {
11247c6ae99SBarry Smith         /* draw my box */
11347c6ae99SBarry Smith         ymin = dd->ys;
11447c6ae99SBarry Smith         ymax = dd->ye - 1;
11547c6ae99SBarry Smith         xmin = dd->xs / dd->w + (dd->M + 1) * k;
11647c6ae99SBarry Smith         xmax = (dd->xe - 1) / dd->w + (dd->M + 1) * k;
11747c6ae99SBarry Smith 
1189566063dSJacob Faibussowitsch         PetscCall(PetscDrawLine(draw, xmin, ymin, xmax, ymin, PETSC_DRAW_RED));
1199566063dSJacob Faibussowitsch         PetscCall(PetscDrawLine(draw, xmin, ymin, xmin, ymax, PETSC_DRAW_RED));
1209566063dSJacob Faibussowitsch         PetscCall(PetscDrawLine(draw, xmin, ymax, xmax, ymax, PETSC_DRAW_RED));
1219566063dSJacob Faibussowitsch         PetscCall(PetscDrawLine(draw, xmax, ymin, xmax, ymax, PETSC_DRAW_RED));
12247c6ae99SBarry Smith 
12347c6ae99SBarry Smith         xmin = dd->xs / dd->w;
12447c6ae99SBarry Smith         xmax = (dd->xe - 1) / dd->w;
12547c6ae99SBarry Smith 
126832b7cebSLisandro Dalcin         /* identify which processor owns the box */
1279566063dSJacob Faibussowitsch         PetscCall(PetscSNPrintf(node, sizeof(node), "%d", (int)rank));
1289566063dSJacob Faibussowitsch         PetscCall(PetscDrawString(draw, xmin + (dd->M + 1) * k + .2, ymin + .3, PETSC_DRAW_RED, node));
12947c6ae99SBarry Smith         /* put in numbers*/
13047c6ae99SBarry Smith         base = (dd->base + (dd->xe - dd->xs) * (dd->ye - dd->ys) * (k - dd->zs)) / dd->w;
13147c6ae99SBarry Smith         for (y = ymin; y <= ymax; y++) {
13247c6ae99SBarry Smith           for (x = xmin + (dd->M + 1) * k; x <= xmax + (dd->M + 1) * k; x++) {
1339566063dSJacob Faibussowitsch             PetscCall(PetscSNPrintf(node, sizeof(node), "%d", (int)base++));
1349566063dSJacob Faibussowitsch             PetscCall(PetscDrawString(draw, x, y, PETSC_DRAW_BLACK, node));
13547c6ae99SBarry Smith           }
13647c6ae99SBarry Smith         }
13747c6ae99SBarry Smith       }
13847c6ae99SBarry Smith     }
139d0609cedSBarry Smith     PetscDrawCollectiveEnd(draw);
1409566063dSJacob Faibussowitsch     PetscCall(PetscDrawFlush(draw));
1419566063dSJacob Faibussowitsch     PetscCall(PetscDrawPause(draw));
14247c6ae99SBarry Smith 
143d0609cedSBarry Smith     PetscDrawCollectiveBegin(draw);
14447c6ae99SBarry Smith     for (k = 0 - dd->s; k < dd->P + dd->s; k++) {
14547c6ae99SBarry Smith       /* Go through and draw for each plane */
14647c6ae99SBarry Smith       if ((k >= dd->Zs) && (k < dd->Ze)) {
14747c6ae99SBarry Smith         /* overlay ghost numbers, useful for error checking */
148565245c5SBarry Smith         base = (dd->Xe - dd->Xs) * (dd->Ye - dd->Ys) * (k - dd->Zs) / dd->w;
1499566063dSJacob Faibussowitsch         PetscCall(ISLocalToGlobalMappingGetBlockIndices(da->ltogmap, &idx));
15047c6ae99SBarry Smith         plane = k;
151565245c5SBarry Smith         /* Keep z wrap around points on the drawing */
1528865f1eaSKarl Rupp         if (k < 0) plane = dd->P + k;
1538865f1eaSKarl Rupp         if (k >= dd->P) plane = k - dd->P;
1549371c9d4SSatish Balay         ymin = dd->Ys;
1559371c9d4SSatish Balay         ymax = dd->Ye;
15647c6ae99SBarry Smith         xmin = (dd->M + 1) * plane * dd->w;
15747c6ae99SBarry Smith         xmax = (dd->M + 1) * plane * dd->w + dd->M * dd->w;
15847c6ae99SBarry Smith         for (y = ymin; y < ymax; y++) {
15947c6ae99SBarry Smith           for (x = xmin + dd->Xs; x < xmin + dd->Xe; x += dd->w) {
160a364092eSJacob Faibussowitsch             PetscCall(PetscSNPrintf(node, PETSC_STATIC_ARRAY_LENGTH(node), "%" PetscInt_FMT, idx[base]));
16147c6ae99SBarry Smith             ycoord = y;
16247c6ae99SBarry Smith             /*Keep y wrap around points on drawing */
1638865f1eaSKarl Rupp             if (y < 0) ycoord = dd->N + y;
1648865f1eaSKarl Rupp             if (y >= dd->N) ycoord = y - dd->N;
16547c6ae99SBarry Smith             xcoord = x; /* Keep x wrap points on drawing */
1668865f1eaSKarl Rupp             if (x < xmin) xcoord = xmax - (xmin - x);
1678865f1eaSKarl Rupp             if (x >= xmax) xcoord = xmin + (x - xmax);
1689566063dSJacob Faibussowitsch             PetscCall(PetscDrawString(draw, xcoord / dd->w, ycoord, PETSC_DRAW_BLUE, node));
169565245c5SBarry Smith             base++;
17047c6ae99SBarry Smith           }
17147c6ae99SBarry Smith         }
1729566063dSJacob Faibussowitsch         PetscCall(ISLocalToGlobalMappingRestoreBlockIndices(da->ltogmap, &idx));
17347c6ae99SBarry Smith       }
17447c6ae99SBarry Smith     }
175d0609cedSBarry Smith     PetscDrawCollectiveEnd(draw);
1769566063dSJacob Faibussowitsch     PetscCall(PetscDrawFlush(draw));
1779566063dSJacob Faibussowitsch     PetscCall(PetscDrawPause(draw));
1789566063dSJacob Faibussowitsch     PetscCall(PetscDrawSave(draw));
179c9493c35SStefano Zampini   } else if (isglvis) {
1809566063dSJacob Faibussowitsch     PetscCall(DMView_DA_GLVis(da, viewer));
1819a42bb27SBarry Smith   } else if (isbinary) {
1829566063dSJacob Faibussowitsch     PetscCall(DMView_DA_Binary(da, viewer));
183d1e78c4fSBarry Smith #if defined(PETSC_HAVE_MATLAB)
1849a42bb27SBarry Smith   } else if (ismatlab) {
1859566063dSJacob Faibussowitsch     PetscCall(DMView_DA_Matlab(da, viewer));
1869a42bb27SBarry Smith #endif
18711aeaf0aSBarry Smith   }
1883ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
18947c6ae99SBarry Smith }
19047c6ae99SBarry Smith 
191d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetUp_DA_3D(DM da)
192d71ae5a4SJacob Faibussowitsch {
19347c6ae99SBarry Smith   DM_DA          *dd           = (DM_DA *)da->data;
19447c6ae99SBarry Smith   const PetscInt  M            = dd->M;
19547c6ae99SBarry Smith   const PetscInt  N            = dd->N;
19647c6ae99SBarry Smith   const PetscInt  P            = dd->P;
19747c6ae99SBarry Smith   PetscInt        m            = dd->m;
19847c6ae99SBarry Smith   PetscInt        n            = dd->n;
19947c6ae99SBarry Smith   PetscInt        p            = dd->p;
20047c6ae99SBarry Smith   const PetscInt  dof          = dd->w;
20147c6ae99SBarry Smith   const PetscInt  s            = dd->s;
202bff4a2f0SMatthew G. Knepley   DMBoundaryType  bx           = dd->bx;
203bff4a2f0SMatthew G. Knepley   DMBoundaryType  by           = dd->by;
204bff4a2f0SMatthew G. Knepley   DMBoundaryType  bz           = dd->bz;
20519fd82e9SBarry Smith   DMDAStencilType stencil_type = dd->stencil_type;
20647c6ae99SBarry Smith   PetscInt       *lx           = dd->lx;
20747c6ae99SBarry Smith   PetscInt       *ly           = dd->ly;
20847c6ae99SBarry Smith   PetscInt       *lz           = dd->lz;
20947c6ae99SBarry Smith   MPI_Comm        comm;
21047c6ae99SBarry Smith   PetscMPIInt     rank, size;
211ce00eea3SSatish Balay   PetscInt        xs = 0, xe, ys = 0, ye, zs = 0, ze, x = 0, y = 0, z = 0;
212bd1fc5aeSBarry Smith   PetscInt        Xs, Xe, Ys, Ye, Zs, Ze, IXs, IXe, IYs, IYe, IZs, IZe, pm;
2138ea3bf28SBarry Smith   PetscInt        left, right, up, down, bottom, top, i, j, k, *idx, nn;
21447c6ae99SBarry Smith   PetscInt        n0, n1, n2, n3, n4, n5, n6, n7, n8, n9, n10, n11, n12, n14;
21547c6ae99SBarry Smith   PetscInt        n15, n16, n17, n18, n19, n20, n21, n22, n23, n24, n25, n26;
216db87c5ecSEthan Coon   PetscInt       *bases, *ldims, base, x_t, y_t, z_t, s_t, count, s_x, s_y, s_z;
21747c6ae99SBarry Smith   PetscInt        sn0 = 0, sn1 = 0, sn2 = 0, sn3 = 0, sn5 = 0, sn6 = 0, sn7 = 0;
21847c6ae99SBarry Smith   PetscInt        sn8 = 0, sn9 = 0, sn11 = 0, sn15 = 0, sn24 = 0, sn25 = 0, sn26 = 0;
21947c6ae99SBarry Smith   PetscInt        sn17 = 0, sn18 = 0, sn19 = 0, sn20 = 0, sn21 = 0, sn23 = 0;
22047c6ae99SBarry Smith   Vec             local, global;
221bd1fc5aeSBarry Smith   VecScatter      gtol;
22245b6f7e9SBarry Smith   IS              to, from;
2236f951b95Secoon   PetscBool       twod;
22447c6ae99SBarry Smith 
22547c6ae99SBarry Smith   PetscFunctionBegin;
2267a8be351SBarry Smith   PetscCheck(stencil_type != DMDA_STENCIL_BOX || (bx != DM_BOUNDARY_MIRROR && by != DM_BOUNDARY_MIRROR && bz != DM_BOUNDARY_MIRROR), PetscObjectComm((PetscObject)da), PETSC_ERR_SUP, "Mirror boundary and box stencil");
2279566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)da, &comm));
2283855c12bSBarry Smith #if !defined(PETSC_USE_64BIT_INDICES)
2297de69702SBarry Smith   PetscCheck(((PetscInt64)M) * ((PetscInt64)N) * ((PetscInt64)P) * ((PetscInt64)dof) <= (PetscInt64)PETSC_MPI_INT_MAX, comm, PETSC_ERR_INT_OVERFLOW, "Mesh of %" PetscInt_FMT " by %" PetscInt_FMT " by %" PetscInt_FMT " by %" PetscInt_FMT " (dof) is too large for 32-bit indices", M, N, P, dof);
2303855c12bSBarry Smith #endif
2313855c12bSBarry Smith 
2329566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(comm, &size));
2339566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
23447c6ae99SBarry Smith 
23547c6ae99SBarry Smith   if (m != PETSC_DECIDE) {
23663a3b9bcSJacob Faibussowitsch     PetscCheck(m >= 1, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Non-positive number of processors in X direction: %" PetscInt_FMT, m);
237f7d195e4SLawrence Mitchell     PetscCheck(m <= size, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Too many processors in X direction: %" PetscInt_FMT " %d", m, size);
23847c6ae99SBarry Smith   }
23947c6ae99SBarry Smith   if (n != PETSC_DECIDE) {
24063a3b9bcSJacob Faibussowitsch     PetscCheck(n >= 1, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Non-positive number of processors in Y direction: %" PetscInt_FMT, n);
241f7d195e4SLawrence Mitchell     PetscCheck(n <= size, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Too many processors in Y direction: %" PetscInt_FMT " %d", n, size);
24247c6ae99SBarry Smith   }
24347c6ae99SBarry Smith   if (p != PETSC_DECIDE) {
24463a3b9bcSJacob Faibussowitsch     PetscCheck(p >= 1, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Non-positive number of processors in Z direction: %" PetscInt_FMT, p);
245f7d195e4SLawrence Mitchell     PetscCheck(p <= size, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Too many processors in Z direction: %" PetscInt_FMT " %d", p, size);
24647c6ae99SBarry Smith   }
2471dca8a05SBarry Smith   PetscCheck(m <= 0 || n <= 0 || p <= 0 || m * n * p == size, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "m %" PetscInt_FMT " * n %" PetscInt_FMT " * p %" PetscInt_FMT " != size %d", m, n, p, size);
24847c6ae99SBarry Smith 
24947c6ae99SBarry Smith   /* Partition the array among the processors */
25047c6ae99SBarry Smith   if (m == PETSC_DECIDE && n != PETSC_DECIDE && p != PETSC_DECIDE) {
25147c6ae99SBarry Smith     m = size / (n * p);
25247c6ae99SBarry Smith   } else if (m != PETSC_DECIDE && n == PETSC_DECIDE && p != PETSC_DECIDE) {
25347c6ae99SBarry Smith     n = size / (m * p);
25447c6ae99SBarry Smith   } else if (m != PETSC_DECIDE && n != PETSC_DECIDE && p == PETSC_DECIDE) {
25547c6ae99SBarry Smith     p = size / (m * n);
25647c6ae99SBarry Smith   } else if (m == PETSC_DECIDE && n == PETSC_DECIDE && p != PETSC_DECIDE) {
25747c6ae99SBarry Smith     /* try for squarish distribution */
258369cc0aeSBarry Smith     m = (int)(0.5 + PetscSqrtReal(((PetscReal)M) * ((PetscReal)size) / ((PetscReal)N * p)));
25947c6ae99SBarry Smith     if (!m) m = 1;
26047c6ae99SBarry Smith     while (m > 0) {
26147c6ae99SBarry Smith       n = size / (m * p);
26247c6ae99SBarry Smith       if (m * n * p == size) break;
26347c6ae99SBarry Smith       m--;
26447c6ae99SBarry Smith     }
26563a3b9bcSJacob Faibussowitsch     PetscCheck(m, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "bad p value: p = %" PetscInt_FMT, p);
2669371c9d4SSatish Balay     if (M > N && m < n) {
2679371c9d4SSatish Balay       PetscInt _m = m;
2689371c9d4SSatish Balay       m           = n;
2699371c9d4SSatish Balay       n           = _m;
2709371c9d4SSatish Balay     }
27147c6ae99SBarry Smith   } else if (m == PETSC_DECIDE && n != PETSC_DECIDE && p == PETSC_DECIDE) {
27247c6ae99SBarry Smith     /* try for squarish distribution */
273369cc0aeSBarry Smith     m = (int)(0.5 + PetscSqrtReal(((PetscReal)M) * ((PetscReal)size) / ((PetscReal)P * n)));
27447c6ae99SBarry Smith     if (!m) m = 1;
27547c6ae99SBarry Smith     while (m > 0) {
27647c6ae99SBarry Smith       p = size / (m * n);
27747c6ae99SBarry Smith       if (m * n * p == size) break;
27847c6ae99SBarry Smith       m--;
27947c6ae99SBarry Smith     }
28063a3b9bcSJacob Faibussowitsch     PetscCheck(m, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "bad n value: n = %" PetscInt_FMT, n);
2819371c9d4SSatish Balay     if (M > P && m < p) {
2829371c9d4SSatish Balay       PetscInt _m = m;
2839371c9d4SSatish Balay       m           = p;
2849371c9d4SSatish Balay       p           = _m;
2859371c9d4SSatish Balay     }
28647c6ae99SBarry Smith   } else if (m != PETSC_DECIDE && n == PETSC_DECIDE && p == PETSC_DECIDE) {
28747c6ae99SBarry Smith     /* try for squarish distribution */
288369cc0aeSBarry Smith     n = (int)(0.5 + PetscSqrtReal(((PetscReal)N) * ((PetscReal)size) / ((PetscReal)P * m)));
28947c6ae99SBarry Smith     if (!n) n = 1;
29047c6ae99SBarry Smith     while (n > 0) {
29147c6ae99SBarry Smith       p = size / (m * n);
29247c6ae99SBarry Smith       if (m * n * p == size) break;
29347c6ae99SBarry Smith       n--;
29447c6ae99SBarry Smith     }
29563a3b9bcSJacob Faibussowitsch     PetscCheck(n, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "bad m value: m = %" PetscInt_FMT, n);
2969371c9d4SSatish Balay     if (N > P && n < p) {
2979371c9d4SSatish Balay       PetscInt _n = n;
2989371c9d4SSatish Balay       n           = p;
2999371c9d4SSatish Balay       p           = _n;
3009371c9d4SSatish Balay     }
30147c6ae99SBarry Smith   } else if (m == PETSC_DECIDE && n == PETSC_DECIDE && p == PETSC_DECIDE) {
30247c6ae99SBarry Smith     /* try for squarish distribution */
303369cc0aeSBarry Smith     n = (PetscInt)(0.5 + PetscPowReal(((PetscReal)N * N) * ((PetscReal)size) / ((PetscReal)P * M), (PetscReal)(1. / 3.)));
30447c6ae99SBarry Smith     if (!n) n = 1;
30547c6ae99SBarry Smith     while (n > 0) {
30647c6ae99SBarry Smith       pm = size / n;
30747c6ae99SBarry Smith       if (n * pm == size) break;
30847c6ae99SBarry Smith       n--;
30947c6ae99SBarry Smith     }
31047c6ae99SBarry Smith     if (!n) n = 1;
311369cc0aeSBarry Smith     m = (PetscInt)(0.5 + PetscSqrtReal(((PetscReal)M) * ((PetscReal)size) / ((PetscReal)P * n)));
31247c6ae99SBarry Smith     if (!m) m = 1;
31347c6ae99SBarry Smith     while (m > 0) {
31447c6ae99SBarry Smith       p = size / (m * n);
31547c6ae99SBarry Smith       if (m * n * p == size) break;
31647c6ae99SBarry Smith       m--;
31747c6ae99SBarry Smith     }
3189371c9d4SSatish Balay     if (M > P && m < p) {
3199371c9d4SSatish Balay       PetscInt _m = m;
3209371c9d4SSatish Balay       m           = p;
3219371c9d4SSatish Balay       p           = _m;
3229371c9d4SSatish Balay     }
32308401ef6SPierre Jolivet   } else PetscCheck(m * n * p == size, PetscObjectComm((PetscObject)da), PETSC_ERR_ARG_OUTOFRANGE, "Given Bad partition");
32447c6ae99SBarry Smith 
32508401ef6SPierre Jolivet   PetscCheck(m * n * p == size, PetscObjectComm((PetscObject)da), PETSC_ERR_PLIB, "Could not find good partition");
32663a3b9bcSJacob Faibussowitsch   PetscCheck(M >= m, PetscObjectComm((PetscObject)da), PETSC_ERR_ARG_OUTOFRANGE, "Partition in x direction is too fine! %" PetscInt_FMT " %" PetscInt_FMT, M, m);
32763a3b9bcSJacob Faibussowitsch   PetscCheck(N >= n, PetscObjectComm((PetscObject)da), PETSC_ERR_ARG_OUTOFRANGE, "Partition in y direction is too fine! %" PetscInt_FMT " %" PetscInt_FMT, N, n);
32863a3b9bcSJacob Faibussowitsch   PetscCheck(P >= p, PetscObjectComm((PetscObject)da), PETSC_ERR_ARG_OUTOFRANGE, "Partition in z direction is too fine! %" PetscInt_FMT " %" PetscInt_FMT, P, p);
32947c6ae99SBarry Smith 
33047c6ae99SBarry Smith   /*
33147c6ae99SBarry Smith      Determine locally owned region
33247c6ae99SBarry Smith      [x, y, or z]s is the first local node number, [x, y, z] is the number of local nodes
33347c6ae99SBarry Smith   */
33447c6ae99SBarry Smith 
33547c6ae99SBarry Smith   if (!lx) {
3369566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(m, &dd->lx));
33747c6ae99SBarry Smith     lx = dd->lx;
3388865f1eaSKarl Rupp     for (i = 0; i < m; i++) lx[i] = M / m + ((M % m) > (i % m));
33947c6ae99SBarry Smith   }
34047c6ae99SBarry Smith   x  = lx[rank % m];
34147c6ae99SBarry Smith   xs = 0;
3428865f1eaSKarl Rupp   for (i = 0; i < (rank % m); i++) xs += lx[i];
3431dca8a05SBarry Smith   PetscCheck(x >= s || (m <= 1 && bx != DM_BOUNDARY_PERIODIC), PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Local x-width of domain x %" PetscInt_FMT " is smaller than stencil width s %" PetscInt_FMT, x, s);
34447c6ae99SBarry Smith 
34547c6ae99SBarry Smith   if (!ly) {
3469566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(n, &dd->ly));
34747c6ae99SBarry Smith     ly = dd->ly;
3488865f1eaSKarl Rupp     for (i = 0; i < n; i++) ly[i] = N / n + ((N % n) > (i % n));
34947c6ae99SBarry Smith   }
35047c6ae99SBarry Smith   y = ly[(rank % (m * n)) / m];
3511dca8a05SBarry Smith   PetscCheck(y >= s || (n <= 1 && by != DM_BOUNDARY_PERIODIC), PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Local y-width of domain y %" PetscInt_FMT " is smaller than stencil width s %" PetscInt_FMT, y, s);
35230729d88SBarry Smith 
35347c6ae99SBarry Smith   ys = 0;
3548865f1eaSKarl Rupp   for (i = 0; i < (rank % (m * n)) / m; i++) ys += ly[i];
35547c6ae99SBarry Smith 
35647c6ae99SBarry Smith   if (!lz) {
3579566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(p, &dd->lz));
35847c6ae99SBarry Smith     lz = dd->lz;
3598865f1eaSKarl Rupp     for (i = 0; i < p; i++) lz[i] = P / p + ((P % p) > (i % p));
36047c6ae99SBarry Smith   }
36147c6ae99SBarry Smith   z = lz[rank / (m * n)];
362bcea557cSEthan Coon 
363fdc81ce8SEthan Coon   /* note this is different than x- and y-, as we will handle as an important special
364bff4a2f0SMatthew G. Knepley    case when p=P=1 and DM_BOUNDARY_PERIODIC and s > z.  This is to deal with 2D problems
365fdc81ce8SEthan Coon    in a 3D code.  Additional code for this case is noted with "2d case" comments */
3666f951b95Secoon   twod = PETSC_FALSE;
3678865f1eaSKarl Rupp   if (P == 1) twod = PETSC_TRUE;
3681dca8a05SBarry Smith   else PetscCheck(z >= s || (p <= 1 && bz != DM_BOUNDARY_PERIODIC), PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Local z-width of domain z %" PetscInt_FMT " is smaller than stencil width s %" PetscInt_FMT, z, s);
36947c6ae99SBarry Smith   zs = 0;
3708865f1eaSKarl Rupp   for (i = 0; i < (rank / (m * n)); i++) zs += lz[i];
37147c6ae99SBarry Smith   ye = ys + y;
37247c6ae99SBarry Smith   xe = xs + x;
37347c6ae99SBarry Smith   ze = zs + z;
37447c6ae99SBarry Smith 
37588661749SPeter Brune   /* determine ghost region (Xs) and region scattered into (IXs)  */
376d9c9ebe5SPeter Brune   if (xs - s > 0) {
3779371c9d4SSatish Balay     Xs  = xs - s;
3789371c9d4SSatish Balay     IXs = xs - s;
37988661749SPeter Brune   } else {
3808865f1eaSKarl Rupp     if (bx) Xs = xs - s;
3818865f1eaSKarl Rupp     else Xs = 0;
38288661749SPeter Brune     IXs = 0;
38388661749SPeter Brune   }
384d9c9ebe5SPeter Brune   if (xe + s <= M) {
3859371c9d4SSatish Balay     Xe  = xe + s;
3869371c9d4SSatish Balay     IXe = xe + s;
38788661749SPeter Brune   } else {
38888661749SPeter Brune     if (bx) {
3899371c9d4SSatish Balay       Xs = xs - s;
3909371c9d4SSatish Balay       Xe = xe + s;
3918865f1eaSKarl Rupp     } else Xe = M;
39288661749SPeter Brune     IXe = M;
39388661749SPeter Brune   }
39447c6ae99SBarry Smith 
395bff4a2f0SMatthew G. Knepley   if (bx == DM_BOUNDARY_PERIODIC || bx == DM_BOUNDARY_MIRROR) {
396d9c9ebe5SPeter Brune     IXs = xs - s;
397d9c9ebe5SPeter Brune     IXe = xe + s;
398d9c9ebe5SPeter Brune     Xs  = xs - s;
399d9c9ebe5SPeter Brune     Xe  = xe + s;
40088661749SPeter Brune   }
40188661749SPeter Brune 
402d9c9ebe5SPeter Brune   if (ys - s > 0) {
4039371c9d4SSatish Balay     Ys  = ys - s;
4049371c9d4SSatish Balay     IYs = ys - s;
40588661749SPeter Brune   } else {
4068865f1eaSKarl Rupp     if (by) Ys = ys - s;
4078865f1eaSKarl Rupp     else Ys = 0;
40888661749SPeter Brune     IYs = 0;
40988661749SPeter Brune   }
410d9c9ebe5SPeter Brune   if (ye + s <= N) {
4119371c9d4SSatish Balay     Ye  = ye + s;
4129371c9d4SSatish Balay     IYe = ye + s;
41388661749SPeter Brune   } else {
4148865f1eaSKarl Rupp     if (by) Ye = ye + s;
4158865f1eaSKarl Rupp     else Ye = N;
41688661749SPeter Brune     IYe = N;
41788661749SPeter Brune   }
41888661749SPeter Brune 
419bff4a2f0SMatthew G. Knepley   if (by == DM_BOUNDARY_PERIODIC || by == DM_BOUNDARY_MIRROR) {
420d9c9ebe5SPeter Brune     IYs = ys - s;
421d9c9ebe5SPeter Brune     IYe = ye + s;
422d9c9ebe5SPeter Brune     Ys  = ys - s;
423d9c9ebe5SPeter Brune     Ye  = ye + s;
42488661749SPeter Brune   }
42588661749SPeter Brune 
426d9c9ebe5SPeter Brune   if (zs - s > 0) {
4279371c9d4SSatish Balay     Zs  = zs - s;
4289371c9d4SSatish Balay     IZs = zs - s;
42988661749SPeter Brune   } else {
4308865f1eaSKarl Rupp     if (bz) Zs = zs - s;
4318865f1eaSKarl Rupp     else Zs = 0;
43288661749SPeter Brune     IZs = 0;
43388661749SPeter Brune   }
434d9c9ebe5SPeter Brune   if (ze + s <= P) {
4359371c9d4SSatish Balay     Ze  = ze + s;
4369371c9d4SSatish Balay     IZe = ze + s;
43788661749SPeter Brune   } else {
4388865f1eaSKarl Rupp     if (bz) Ze = ze + s;
4398865f1eaSKarl Rupp     else Ze = P;
44088661749SPeter Brune     IZe = P;
44188661749SPeter Brune   }
44288661749SPeter Brune 
443bff4a2f0SMatthew G. Knepley   if (bz == DM_BOUNDARY_PERIODIC || bz == DM_BOUNDARY_MIRROR) {
444d9c9ebe5SPeter Brune     IZs = zs - s;
445d9c9ebe5SPeter Brune     IZe = ze + s;
446d9c9ebe5SPeter Brune     Zs  = zs - s;
447d9c9ebe5SPeter Brune     Ze  = ze + s;
44888661749SPeter Brune   }
44947c6ae99SBarry Smith 
45047c6ae99SBarry Smith   /* Resize all X parameters to reflect w */
451d9c9ebe5SPeter Brune   s_x = s;
452d9c9ebe5SPeter Brune   s_y = s;
453d9c9ebe5SPeter Brune   s_z = s;
45447c6ae99SBarry Smith 
45547c6ae99SBarry Smith   /* determine starting point of each processor */
45647c6ae99SBarry Smith   nn = x * y * z;
4579566063dSJacob Faibussowitsch   PetscCall(PetscMalloc2(size + 1, &bases, size, &ldims));
4589566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Allgather(&nn, 1, MPIU_INT, ldims, 1, MPIU_INT, comm));
45947c6ae99SBarry Smith   bases[0] = 0;
4608865f1eaSKarl Rupp   for (i = 1; i <= size; i++) bases[i] = ldims[i - 1];
4618865f1eaSKarl Rupp   for (i = 1; i <= size; i++) bases[i] += bases[i - 1];
462ce00eea3SSatish Balay   base = bases[rank] * dof;
46347c6ae99SBarry Smith 
46447c6ae99SBarry Smith   /* allocate the base parallel and sequential vectors */
465ce00eea3SSatish Balay   dd->Nlocal = x * y * z * dof;
4669566063dSJacob Faibussowitsch   PetscCall(VecCreateMPIWithArray(comm, dof, dd->Nlocal, PETSC_DECIDE, NULL, &global));
467ce00eea3SSatish Balay   dd->nlocal = (Xe - Xs) * (Ye - Ys) * (Ze - Zs) * dof;
4689566063dSJacob Faibussowitsch   PetscCall(VecCreateSeqWithArray(PETSC_COMM_SELF, dof, dd->nlocal, NULL, &local));
46947c6ae99SBarry Smith 
4704104a7a0SPatrick Sanan   /* generate global to local vector scatter and local to global mapping*/
47147c6ae99SBarry Smith 
472ce00eea3SSatish Balay   /* global to local must include ghost points within the domain,
473ce00eea3SSatish Balay      but not ghost points outside the domain that aren't periodic */
4749566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1((IXe - IXs) * (IYe - IYs) * (IZe - IZs), &idx));
475d9c9ebe5SPeter Brune   if (stencil_type == DMDA_STENCIL_BOX) {
4769371c9d4SSatish Balay     left   = IXs - Xs;
4779371c9d4SSatish Balay     right  = left + (IXe - IXs);
4789371c9d4SSatish Balay     bottom = IYs - Ys;
4799371c9d4SSatish Balay     top    = bottom + (IYe - IYs);
4809371c9d4SSatish Balay     down   = IZs - Zs;
4819371c9d4SSatish Balay     up     = down + (IZe - IZs);
482ce00eea3SSatish Balay     count  = 0;
483ce00eea3SSatish Balay     for (i = down; i < up; i++) {
484ce00eea3SSatish Balay       for (j = bottom; j < top; j++) {
485ad540459SPierre Jolivet         for (k = left; k < right; k++) idx[count++] = (i * (Ye - Ys) + j) * (Xe - Xs) + k;
486ce00eea3SSatish Balay       }
487ce00eea3SSatish Balay     }
4889566063dSJacob Faibussowitsch     PetscCall(ISCreateBlock(comm, dof, count, idx, PETSC_OWN_POINTER, &to));
48947c6ae99SBarry Smith   } else {
49047c6ae99SBarry Smith     /* This is way ugly! We need to list the funny cross type region */
4919371c9d4SSatish Balay     left   = xs - Xs;
4929371c9d4SSatish Balay     right  = left + x;
4939371c9d4SSatish Balay     bottom = ys - Ys;
4949371c9d4SSatish Balay     top    = bottom + y;
4959371c9d4SSatish Balay     down   = zs - Zs;
4969371c9d4SSatish Balay     up     = down + z;
49747c6ae99SBarry Smith     count  = 0;
498a5b23f4aSJose E. Roman     /* the bottom chunk */
499ce00eea3SSatish Balay     for (i = (IZs - Zs); i < down; i++) {
50047c6ae99SBarry Smith       for (j = bottom; j < top; j++) {
501ce00eea3SSatish Balay         for (k = left; k < right; k++) idx[count++] = (i * (Ye - Ys) + j) * (Xe - Xs) + k;
50247c6ae99SBarry Smith       }
50347c6ae99SBarry Smith     }
50447c6ae99SBarry Smith     /* the middle piece */
50547c6ae99SBarry Smith     for (i = down; i < up; i++) {
50647c6ae99SBarry Smith       /* front */
507ce00eea3SSatish Balay       for (j = (IYs - Ys); j < bottom; j++) {
508ce00eea3SSatish Balay         for (k = left; k < right; k++) idx[count++] = (i * (Ye - Ys) + j) * (Xe - Xs) + k;
50947c6ae99SBarry Smith       }
51047c6ae99SBarry Smith       /* middle */
51147c6ae99SBarry Smith       for (j = bottom; j < top; j++) {
512ce00eea3SSatish Balay         for (k = IXs - Xs; k < IXe - Xs; k++) idx[count++] = (i * (Ye - Ys) + j) * (Xe - Xs) + k;
51347c6ae99SBarry Smith       }
51447c6ae99SBarry Smith       /* back */
515ce00eea3SSatish Balay       for (j = top; j < top + IYe - ye; j++) {
516ce00eea3SSatish Balay         for (k = left; k < right; k++) idx[count++] = (i * (Ye - Ys) + j) * (Xe - Xs) + k;
51747c6ae99SBarry Smith       }
51847c6ae99SBarry Smith     }
51947c6ae99SBarry Smith     /* the top piece */
520ce00eea3SSatish Balay     for (i = up; i < up + IZe - ze; i++) {
52147c6ae99SBarry Smith       for (j = bottom; j < top; j++) {
522ce00eea3SSatish Balay         for (k = left; k < right; k++) idx[count++] = (i * (Ye - Ys) + j) * (Xe - Xs) + k;
52347c6ae99SBarry Smith       }
52447c6ae99SBarry Smith     }
5259566063dSJacob Faibussowitsch     PetscCall(ISCreateBlock(comm, dof, count, idx, PETSC_OWN_POINTER, &to));
52647c6ae99SBarry Smith   }
52747c6ae99SBarry Smith 
52847c6ae99SBarry Smith   /* determine who lies on each side of use stored in    n24 n25 n26
52947c6ae99SBarry Smith                                                          n21 n22 n23
53047c6ae99SBarry Smith                                                          n18 n19 n20
53147c6ae99SBarry Smith 
53247c6ae99SBarry Smith                                                          n15 n16 n17
53347c6ae99SBarry Smith                                                          n12     n14
53447c6ae99SBarry Smith                                                          n9  n10 n11
53547c6ae99SBarry Smith 
53647c6ae99SBarry Smith                                                          n6  n7  n8
53747c6ae99SBarry Smith                                                          n3  n4  n5
53847c6ae99SBarry Smith                                                          n0  n1  n2
53947c6ae99SBarry Smith   */
54047c6ae99SBarry Smith 
54147c6ae99SBarry Smith   /* Solve for X,Y, and Z Periodic Case First, Then Modify Solution */
54247c6ae99SBarry Smith   /* Assume Nodes are Internal to the Cube */
54347c6ae99SBarry Smith   n0 = rank - m * n - m - 1;
54447c6ae99SBarry Smith   n1 = rank - m * n - m;
54547c6ae99SBarry Smith   n2 = rank - m * n - m + 1;
54647c6ae99SBarry Smith   n3 = rank - m * n - 1;
54747c6ae99SBarry Smith   n4 = rank - m * n;
54847c6ae99SBarry Smith   n5 = rank - m * n + 1;
54947c6ae99SBarry Smith   n6 = rank - m * n + m - 1;
55047c6ae99SBarry Smith   n7 = rank - m * n + m;
55147c6ae99SBarry Smith   n8 = rank - m * n + m + 1;
55247c6ae99SBarry Smith 
55347c6ae99SBarry Smith   n9  = rank - m - 1;
55447c6ae99SBarry Smith   n10 = rank - m;
55547c6ae99SBarry Smith   n11 = rank - m + 1;
55647c6ae99SBarry Smith   n12 = rank - 1;
55747c6ae99SBarry Smith   n14 = rank + 1;
55847c6ae99SBarry Smith   n15 = rank + m - 1;
55947c6ae99SBarry Smith   n16 = rank + m;
56047c6ae99SBarry Smith   n17 = rank + m + 1;
56147c6ae99SBarry Smith 
56247c6ae99SBarry Smith   n18 = rank + m * n - m - 1;
56347c6ae99SBarry Smith   n19 = rank + m * n - m;
56447c6ae99SBarry Smith   n20 = rank + m * n - m + 1;
56547c6ae99SBarry Smith   n21 = rank + m * n - 1;
56647c6ae99SBarry Smith   n22 = rank + m * n;
56747c6ae99SBarry Smith   n23 = rank + m * n + 1;
56847c6ae99SBarry Smith   n24 = rank + m * n + m - 1;
56947c6ae99SBarry Smith   n25 = rank + m * n + m;
57047c6ae99SBarry Smith   n26 = rank + m * n + m + 1;
57147c6ae99SBarry Smith 
57247c6ae99SBarry Smith   /* Assume Pieces are on Faces of Cube */
57347c6ae99SBarry Smith 
57447c6ae99SBarry Smith   if (xs == 0) { /* First assume not corner or edge */
57547c6ae99SBarry Smith     n0  = rank - 1 - (m * n);
57647c6ae99SBarry Smith     n3  = rank + m - 1 - (m * n);
57747c6ae99SBarry Smith     n6  = rank + 2 * m - 1 - (m * n);
57847c6ae99SBarry Smith     n9  = rank - 1;
57947c6ae99SBarry Smith     n12 = rank + m - 1;
58047c6ae99SBarry Smith     n15 = rank + 2 * m - 1;
58147c6ae99SBarry Smith     n18 = rank - 1 + (m * n);
58247c6ae99SBarry Smith     n21 = rank + m - 1 + (m * n);
58347c6ae99SBarry Smith     n24 = rank + 2 * m - 1 + (m * n);
58447c6ae99SBarry Smith   }
58547c6ae99SBarry Smith 
586ce00eea3SSatish Balay   if (xe == M) { /* First assume not corner or edge */
58747c6ae99SBarry Smith     n2  = rank - 2 * m + 1 - (m * n);
58847c6ae99SBarry Smith     n5  = rank - m + 1 - (m * n);
58947c6ae99SBarry Smith     n8  = rank + 1 - (m * n);
59047c6ae99SBarry Smith     n11 = rank - 2 * m + 1;
59147c6ae99SBarry Smith     n14 = rank - m + 1;
59247c6ae99SBarry Smith     n17 = rank + 1;
59347c6ae99SBarry Smith     n20 = rank - 2 * m + 1 + (m * n);
59447c6ae99SBarry Smith     n23 = rank - m + 1 + (m * n);
59547c6ae99SBarry Smith     n26 = rank + 1 + (m * n);
59647c6ae99SBarry Smith   }
59747c6ae99SBarry Smith 
59847c6ae99SBarry Smith   if (ys == 0) { /* First assume not corner or edge */
59947c6ae99SBarry Smith     n0  = rank + m * (n - 1) - 1 - (m * n);
60047c6ae99SBarry Smith     n1  = rank + m * (n - 1) - (m * n);
60147c6ae99SBarry Smith     n2  = rank + m * (n - 1) + 1 - (m * n);
60247c6ae99SBarry Smith     n9  = rank + m * (n - 1) - 1;
60347c6ae99SBarry Smith     n10 = rank + m * (n - 1);
60447c6ae99SBarry Smith     n11 = rank + m * (n - 1) + 1;
60547c6ae99SBarry Smith     n18 = rank + m * (n - 1) - 1 + (m * n);
60647c6ae99SBarry Smith     n19 = rank + m * (n - 1) + (m * n);
60747c6ae99SBarry Smith     n20 = rank + m * (n - 1) + 1 + (m * n);
60847c6ae99SBarry Smith   }
60947c6ae99SBarry Smith 
61047c6ae99SBarry Smith   if (ye == N) { /* First assume not corner or edge */
61147c6ae99SBarry Smith     n6  = rank - m * (n - 1) - 1 - (m * n);
61247c6ae99SBarry Smith     n7  = rank - m * (n - 1) - (m * n);
61347c6ae99SBarry Smith     n8  = rank - m * (n - 1) + 1 - (m * n);
61447c6ae99SBarry Smith     n15 = rank - m * (n - 1) - 1;
61547c6ae99SBarry Smith     n16 = rank - m * (n - 1);
61647c6ae99SBarry Smith     n17 = rank - m * (n - 1) + 1;
61747c6ae99SBarry Smith     n24 = rank - m * (n - 1) - 1 + (m * n);
61847c6ae99SBarry Smith     n25 = rank - m * (n - 1) + (m * n);
61947c6ae99SBarry Smith     n26 = rank - m * (n - 1) + 1 + (m * n);
62047c6ae99SBarry Smith   }
62147c6ae99SBarry Smith 
62247c6ae99SBarry Smith   if (zs == 0) { /* First assume not corner or edge */
62347c6ae99SBarry Smith     n0 = size - (m * n) + rank - m - 1;
62447c6ae99SBarry Smith     n1 = size - (m * n) + rank - m;
62547c6ae99SBarry Smith     n2 = size - (m * n) + rank - m + 1;
62647c6ae99SBarry Smith     n3 = size - (m * n) + rank - 1;
62747c6ae99SBarry Smith     n4 = size - (m * n) + rank;
62847c6ae99SBarry Smith     n5 = size - (m * n) + rank + 1;
62947c6ae99SBarry Smith     n6 = size - (m * n) + rank + m - 1;
63047c6ae99SBarry Smith     n7 = size - (m * n) + rank + m;
63147c6ae99SBarry Smith     n8 = size - (m * n) + rank + m + 1;
63247c6ae99SBarry Smith   }
63347c6ae99SBarry Smith 
63447c6ae99SBarry Smith   if (ze == P) { /* First assume not corner or edge */
63547c6ae99SBarry Smith     n18 = (m * n) - (size - rank) - m - 1;
63647c6ae99SBarry Smith     n19 = (m * n) - (size - rank) - m;
63747c6ae99SBarry Smith     n20 = (m * n) - (size - rank) - m + 1;
63847c6ae99SBarry Smith     n21 = (m * n) - (size - rank) - 1;
63947c6ae99SBarry Smith     n22 = (m * n) - (size - rank);
64047c6ae99SBarry Smith     n23 = (m * n) - (size - rank) + 1;
64147c6ae99SBarry Smith     n24 = (m * n) - (size - rank) + m - 1;
64247c6ae99SBarry Smith     n25 = (m * n) - (size - rank) + m;
64347c6ae99SBarry Smith     n26 = (m * n) - (size - rank) + m + 1;
64447c6ae99SBarry Smith   }
64547c6ae99SBarry Smith 
64647c6ae99SBarry Smith   if ((xs == 0) && (zs == 0)) { /* Assume an edge, not corner */
64747c6ae99SBarry Smith     n0 = size - m * n + rank + m - 1 - m;
64847c6ae99SBarry Smith     n3 = size - m * n + rank + m - 1;
64947c6ae99SBarry Smith     n6 = size - m * n + rank + m - 1 + m;
65047c6ae99SBarry Smith   }
65147c6ae99SBarry Smith 
65247c6ae99SBarry Smith   if ((xs == 0) && (ze == P)) { /* Assume an edge, not corner */
65347c6ae99SBarry Smith     n18 = m * n - (size - rank) + m - 1 - m;
65447c6ae99SBarry Smith     n21 = m * n - (size - rank) + m - 1;
65547c6ae99SBarry Smith     n24 = m * n - (size - rank) + m - 1 + m;
65647c6ae99SBarry Smith   }
65747c6ae99SBarry Smith 
65847c6ae99SBarry Smith   if ((xs == 0) && (ys == 0)) { /* Assume an edge, not corner */
65947c6ae99SBarry Smith     n0  = rank + m * n - 1 - m * n;
66047c6ae99SBarry Smith     n9  = rank + m * n - 1;
66147c6ae99SBarry Smith     n18 = rank + m * n - 1 + m * n;
66247c6ae99SBarry Smith   }
66347c6ae99SBarry Smith 
66447c6ae99SBarry Smith   if ((xs == 0) && (ye == N)) { /* Assume an edge, not corner */
66547c6ae99SBarry Smith     n6  = rank - m * (n - 1) + m - 1 - m * n;
66647c6ae99SBarry Smith     n15 = rank - m * (n - 1) + m - 1;
66747c6ae99SBarry Smith     n24 = rank - m * (n - 1) + m - 1 + m * n;
66847c6ae99SBarry Smith   }
66947c6ae99SBarry Smith 
670ce00eea3SSatish Balay   if ((xe == M) && (zs == 0)) { /* Assume an edge, not corner */
67147c6ae99SBarry Smith     n2 = size - (m * n - rank) - (m - 1) - m;
67247c6ae99SBarry Smith     n5 = size - (m * n - rank) - (m - 1);
67347c6ae99SBarry Smith     n8 = size - (m * n - rank) - (m - 1) + m;
67447c6ae99SBarry Smith   }
67547c6ae99SBarry Smith 
676ce00eea3SSatish Balay   if ((xe == M) && (ze == P)) { /* Assume an edge, not corner */
67747c6ae99SBarry Smith     n20 = m * n - (size - rank) - (m - 1) - m;
67847c6ae99SBarry Smith     n23 = m * n - (size - rank) - (m - 1);
67947c6ae99SBarry Smith     n26 = m * n - (size - rank) - (m - 1) + m;
68047c6ae99SBarry Smith   }
68147c6ae99SBarry Smith 
682ce00eea3SSatish Balay   if ((xe == M) && (ys == 0)) { /* Assume an edge, not corner */
68347c6ae99SBarry Smith     n2  = rank + m * (n - 1) - (m - 1) - m * n;
68447c6ae99SBarry Smith     n11 = rank + m * (n - 1) - (m - 1);
68547c6ae99SBarry Smith     n20 = rank + m * (n - 1) - (m - 1) + m * n;
68647c6ae99SBarry Smith   }
68747c6ae99SBarry Smith 
688ce00eea3SSatish Balay   if ((xe == M) && (ye == N)) { /* Assume an edge, not corner */
68947c6ae99SBarry Smith     n8  = rank - m * n + 1 - m * n;
69047c6ae99SBarry Smith     n17 = rank - m * n + 1;
69147c6ae99SBarry Smith     n26 = rank - m * n + 1 + m * n;
69247c6ae99SBarry Smith   }
69347c6ae99SBarry Smith 
69447c6ae99SBarry Smith   if ((ys == 0) && (zs == 0)) { /* Assume an edge, not corner */
69547c6ae99SBarry Smith     n0 = size - m + rank - 1;
69647c6ae99SBarry Smith     n1 = size - m + rank;
69747c6ae99SBarry Smith     n2 = size - m + rank + 1;
69847c6ae99SBarry Smith   }
69947c6ae99SBarry Smith 
70047c6ae99SBarry Smith   if ((ys == 0) && (ze == P)) { /* Assume an edge, not corner */
70147c6ae99SBarry Smith     n18 = m * n - (size - rank) + m * (n - 1) - 1;
70247c6ae99SBarry Smith     n19 = m * n - (size - rank) + m * (n - 1);
70347c6ae99SBarry Smith     n20 = m * n - (size - rank) + m * (n - 1) + 1;
70447c6ae99SBarry Smith   }
70547c6ae99SBarry Smith 
70647c6ae99SBarry Smith   if ((ye == N) && (zs == 0)) { /* Assume an edge, not corner */
70747c6ae99SBarry Smith     n6 = size - (m * n - rank) - m * (n - 1) - 1;
70847c6ae99SBarry Smith     n7 = size - (m * n - rank) - m * (n - 1);
70947c6ae99SBarry Smith     n8 = size - (m * n - rank) - m * (n - 1) + 1;
71047c6ae99SBarry Smith   }
71147c6ae99SBarry Smith 
71247c6ae99SBarry Smith   if ((ye == N) && (ze == P)) { /* Assume an edge, not corner */
71347c6ae99SBarry Smith     n24 = rank - (size - m) - 1;
71447c6ae99SBarry Smith     n25 = rank - (size - m);
71547c6ae99SBarry Smith     n26 = rank - (size - m) + 1;
71647c6ae99SBarry Smith   }
71747c6ae99SBarry Smith 
71847c6ae99SBarry Smith   /* Check for Corners */
7198865f1eaSKarl Rupp   if ((xs == 0) && (ys == 0) && (zs == 0)) n0 = size - 1;
7208865f1eaSKarl Rupp   if ((xs == 0) && (ys == 0) && (ze == P)) n18 = m * n - 1;
7218865f1eaSKarl Rupp   if ((xs == 0) && (ye == N) && (zs == 0)) n6 = (size - 1) - m * (n - 1);
7228865f1eaSKarl Rupp   if ((xs == 0) && (ye == N) && (ze == P)) n24 = m - 1;
7238865f1eaSKarl Rupp   if ((xe == M) && (ys == 0) && (zs == 0)) n2 = size - m;
7248865f1eaSKarl Rupp   if ((xe == M) && (ys == 0) && (ze == P)) n20 = m * n - m;
7258865f1eaSKarl Rupp   if ((xe == M) && (ye == N) && (zs == 0)) n8 = size - m * n;
7268865f1eaSKarl Rupp   if ((xe == M) && (ye == N) && (ze == P)) n26 = 0;
72747c6ae99SBarry Smith 
72847c6ae99SBarry Smith   /* Check for when not X,Y, and Z Periodic */
72947c6ae99SBarry Smith 
73047c6ae99SBarry Smith   /* If not X periodic */
731bff4a2f0SMatthew G. Knepley   if (bx != DM_BOUNDARY_PERIODIC) {
7328865f1eaSKarl Rupp     if (xs == 0) n0 = n3 = n6 = n9 = n12 = n15 = n18 = n21 = n24 = -2;
7338865f1eaSKarl Rupp     if (xe == M) n2 = n5 = n8 = n11 = n14 = n17 = n20 = n23 = n26 = -2;
73447c6ae99SBarry Smith   }
73547c6ae99SBarry Smith 
73647c6ae99SBarry Smith   /* If not Y periodic */
737bff4a2f0SMatthew G. Knepley   if (by != DM_BOUNDARY_PERIODIC) {
7388865f1eaSKarl Rupp     if (ys == 0) n0 = n1 = n2 = n9 = n10 = n11 = n18 = n19 = n20 = -2;
7398865f1eaSKarl Rupp     if (ye == N) n6 = n7 = n8 = n15 = n16 = n17 = n24 = n25 = n26 = -2;
74047c6ae99SBarry Smith   }
74147c6ae99SBarry Smith 
74247c6ae99SBarry Smith   /* If not Z periodic */
743bff4a2f0SMatthew G. Knepley   if (bz != DM_BOUNDARY_PERIODIC) {
7448865f1eaSKarl Rupp     if (zs == 0) n0 = n1 = n2 = n3 = n4 = n5 = n6 = n7 = n8 = -2;
7458865f1eaSKarl Rupp     if (ze == P) n18 = n19 = n20 = n21 = n22 = n23 = n24 = n25 = n26 = -2;
74647c6ae99SBarry Smith   }
74747c6ae99SBarry Smith 
7489566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(27, &dd->neighbors));
7498865f1eaSKarl Rupp 
75047c6ae99SBarry Smith   dd->neighbors[0]  = n0;
75147c6ae99SBarry Smith   dd->neighbors[1]  = n1;
75247c6ae99SBarry Smith   dd->neighbors[2]  = n2;
75347c6ae99SBarry Smith   dd->neighbors[3]  = n3;
75447c6ae99SBarry Smith   dd->neighbors[4]  = n4;
75547c6ae99SBarry Smith   dd->neighbors[5]  = n5;
75647c6ae99SBarry Smith   dd->neighbors[6]  = n6;
75747c6ae99SBarry Smith   dd->neighbors[7]  = n7;
75847c6ae99SBarry Smith   dd->neighbors[8]  = n8;
75947c6ae99SBarry Smith   dd->neighbors[9]  = n9;
76047c6ae99SBarry Smith   dd->neighbors[10] = n10;
76147c6ae99SBarry Smith   dd->neighbors[11] = n11;
76247c6ae99SBarry Smith   dd->neighbors[12] = n12;
76347c6ae99SBarry Smith   dd->neighbors[13] = rank;
76447c6ae99SBarry Smith   dd->neighbors[14] = n14;
76547c6ae99SBarry Smith   dd->neighbors[15] = n15;
76647c6ae99SBarry Smith   dd->neighbors[16] = n16;
76747c6ae99SBarry Smith   dd->neighbors[17] = n17;
76847c6ae99SBarry Smith   dd->neighbors[18] = n18;
76947c6ae99SBarry Smith   dd->neighbors[19] = n19;
77047c6ae99SBarry Smith   dd->neighbors[20] = n20;
77147c6ae99SBarry Smith   dd->neighbors[21] = n21;
77247c6ae99SBarry Smith   dd->neighbors[22] = n22;
77347c6ae99SBarry Smith   dd->neighbors[23] = n23;
77447c6ae99SBarry Smith   dd->neighbors[24] = n24;
77547c6ae99SBarry Smith   dd->neighbors[25] = n25;
77647c6ae99SBarry Smith   dd->neighbors[26] = n26;
77747c6ae99SBarry Smith 
77847c6ae99SBarry Smith   /* If star stencil then delete the corner neighbors */
779d9c9ebe5SPeter Brune   if (stencil_type == DMDA_STENCIL_STAR) {
78047c6ae99SBarry Smith     /* save information about corner neighbors */
7819371c9d4SSatish Balay     sn0  = n0;
7829371c9d4SSatish Balay     sn1  = n1;
7839371c9d4SSatish Balay     sn2  = n2;
7849371c9d4SSatish Balay     sn3  = n3;
7859371c9d4SSatish Balay     sn5  = n5;
7869371c9d4SSatish Balay     sn6  = n6;
7879371c9d4SSatish Balay     sn7  = n7;
7889371c9d4SSatish Balay     sn8  = n8;
7899371c9d4SSatish Balay     sn9  = n9;
7909371c9d4SSatish Balay     sn11 = n11;
7919371c9d4SSatish Balay     sn15 = n15;
7929371c9d4SSatish Balay     sn17 = n17;
7939371c9d4SSatish Balay     sn18 = n18;
7949371c9d4SSatish Balay     sn19 = n19;
7959371c9d4SSatish Balay     sn20 = n20;
7969371c9d4SSatish Balay     sn21 = n21;
7979371c9d4SSatish Balay     sn23 = n23;
7989371c9d4SSatish Balay     sn24 = n24;
7999371c9d4SSatish Balay     sn25 = n25;
80047c6ae99SBarry Smith     sn26 = n26;
8018865f1eaSKarl Rupp     n0 = n1 = n2 = n3 = n5 = n6 = n7 = n8 = n9 = n11 = n15 = n17 = n18 = n19 = n20 = n21 = n23 = n24 = n25 = n26 = -1;
80247c6ae99SBarry Smith   }
80347c6ae99SBarry Smith 
8049566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1((Xe - Xs) * (Ye - Ys) * (Ze - Zs), &idx));
80547c6ae99SBarry Smith 
80647c6ae99SBarry Smith   nn = 0;
80747c6ae99SBarry Smith   /* Bottom Level */
80847c6ae99SBarry Smith   for (k = 0; k < s_z; k++) {
80947c6ae99SBarry Smith     for (i = 1; i <= s_y; i++) {
81047c6ae99SBarry Smith       if (n0 >= 0) { /* left below */
811ce00eea3SSatish Balay         x_t = lx[n0 % m];
81247c6ae99SBarry Smith         y_t = ly[(n0 % (m * n)) / m];
81347c6ae99SBarry Smith         z_t = lz[n0 / (m * n)];
81447c6ae99SBarry Smith         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;
8158865f1eaSKarl Rupp         if (twod && (s_t < 0)) s_t = bases[n0] + x_t * y_t * z_t - (s_y - i) * x_t - s_x; /* 2D case */
8168865f1eaSKarl Rupp         for (j = 0; j < s_x; j++) idx[nn++] = s_t++;
81747c6ae99SBarry Smith       }
81847c6ae99SBarry Smith       if (n1 >= 0) { /* directly below */
81947c6ae99SBarry Smith         x_t = x;
82047c6ae99SBarry Smith         y_t = ly[(n1 % (m * n)) / m];
82147c6ae99SBarry Smith         z_t = lz[n1 / (m * n)];
82247c6ae99SBarry Smith         s_t = bases[n1] + x_t * y_t * z_t - (s_y + 1 - i) * x_t - (s_z - k - 1) * x_t * y_t;
8238865f1eaSKarl Rupp         if (twod && (s_t < 0)) s_t = bases[n1] + x_t * y_t * z_t - (s_y + 1 - i) * x_t; /* 2D case */
8248865f1eaSKarl Rupp         for (j = 0; j < x_t; j++) idx[nn++] = s_t++;
82547c6ae99SBarry Smith       }
82647c6ae99SBarry Smith       if (n2 >= 0) { /* right below */
827ce00eea3SSatish Balay         x_t = lx[n2 % m];
82847c6ae99SBarry Smith         y_t = ly[(n2 % (m * n)) / m];
82947c6ae99SBarry Smith         z_t = lz[n2 / (m * n)];
83047c6ae99SBarry Smith         s_t = bases[n2] + x_t * y_t * z_t - (s_y + 1 - i) * x_t - (s_z - k - 1) * x_t * y_t;
8318865f1eaSKarl Rupp         if (twod && (s_t < 0)) s_t = bases[n2] + x_t * y_t * z_t - (s_y + 1 - i) * x_t; /* 2D case */
8328865f1eaSKarl Rupp         for (j = 0; j < s_x; j++) idx[nn++] = s_t++;
83347c6ae99SBarry Smith       }
83447c6ae99SBarry Smith     }
83547c6ae99SBarry Smith 
83647c6ae99SBarry Smith     for (i = 0; i < y; i++) {
83747c6ae99SBarry Smith       if (n3 >= 0) { /* directly left */
838ce00eea3SSatish Balay         x_t = lx[n3 % m];
83947c6ae99SBarry Smith         y_t = y;
84047c6ae99SBarry Smith         z_t = lz[n3 / (m * n)];
84147c6ae99SBarry Smith         s_t = bases[n3] + (i + 1) * x_t - s_x + x_t * y_t * z_t - (s_z - k) * x_t * y_t;
8428865f1eaSKarl Rupp         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 */
8438865f1eaSKarl Rupp         for (j = 0; j < s_x; j++) idx[nn++] = s_t++;
84447c6ae99SBarry Smith       }
84547c6ae99SBarry Smith 
84647c6ae99SBarry Smith       if (n4 >= 0) { /* middle */
84747c6ae99SBarry Smith         x_t = x;
84847c6ae99SBarry Smith         y_t = y;
84947c6ae99SBarry Smith         z_t = lz[n4 / (m * n)];
85047c6ae99SBarry Smith         s_t = bases[n4] + i * x_t + x_t * y_t * z_t - (s_z - k) * x_t * y_t;
8518865f1eaSKarl Rupp         if (twod && (s_t < 0)) s_t = bases[n4] + i * x_t + x_t * y_t * z_t - x_t * y_t; /* 2D case */
8528865f1eaSKarl Rupp         for (j = 0; j < x_t; j++) idx[nn++] = s_t++;
853bff4a2f0SMatthew G. Knepley       } else if (bz == DM_BOUNDARY_MIRROR) {
854a6fd6b0aSBarry Smith         for (j = 0; j < x; j++) idx[nn++] = bases[rank] + j + x * i + (s_z - k - 1) * x * y;
85547c6ae99SBarry Smith       }
85647c6ae99SBarry Smith 
85747c6ae99SBarry Smith       if (n5 >= 0) { /* directly right */
858ce00eea3SSatish Balay         x_t = lx[n5 % m];
85947c6ae99SBarry Smith         y_t = y;
86047c6ae99SBarry Smith         z_t = lz[n5 / (m * n)];
86147c6ae99SBarry Smith         s_t = bases[n5] + i * x_t + x_t * y_t * z_t - (s_z - k) * x_t * y_t;
8628865f1eaSKarl Rupp         if (twod && (s_t < 0)) s_t = bases[n5] + i * x_t + x_t * y_t * z_t - x_t * y_t; /* 2D case */
8638865f1eaSKarl Rupp         for (j = 0; j < s_x; j++) idx[nn++] = s_t++;
86447c6ae99SBarry Smith       }
86547c6ae99SBarry Smith     }
86647c6ae99SBarry Smith 
86747c6ae99SBarry Smith     for (i = 1; i <= s_y; i++) {
86847c6ae99SBarry Smith       if (n6 >= 0) { /* left above */
869ce00eea3SSatish Balay         x_t = lx[n6 % m];
87047c6ae99SBarry Smith         y_t = ly[(n6 % (m * n)) / m];
87147c6ae99SBarry Smith         z_t = lz[n6 / (m * n)];
87247c6ae99SBarry Smith         s_t = bases[n6] + i * x_t - s_x + x_t * y_t * z_t - (s_z - k) * x_t * y_t;
8738865f1eaSKarl Rupp         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 */
8748865f1eaSKarl Rupp         for (j = 0; j < s_x; j++) idx[nn++] = s_t++;
87547c6ae99SBarry Smith       }
87647c6ae99SBarry Smith       if (n7 >= 0) { /* directly above */
87747c6ae99SBarry Smith         x_t = x;
87847c6ae99SBarry Smith         y_t = ly[(n7 % (m * n)) / m];
87947c6ae99SBarry Smith         z_t = lz[n7 / (m * n)];
88047c6ae99SBarry Smith         s_t = bases[n7] + (i - 1) * x_t + x_t * y_t * z_t - (s_z - k) * x_t * y_t;
8818865f1eaSKarl Rupp         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 */
8828865f1eaSKarl Rupp         for (j = 0; j < x_t; j++) idx[nn++] = s_t++;
88347c6ae99SBarry Smith       }
88447c6ae99SBarry Smith       if (n8 >= 0) { /* right above */
885ce00eea3SSatish Balay         x_t = lx[n8 % m];
88647c6ae99SBarry Smith         y_t = ly[(n8 % (m * n)) / m];
88747c6ae99SBarry Smith         z_t = lz[n8 / (m * n)];
88847c6ae99SBarry Smith         s_t = bases[n8] + (i - 1) * x_t + x_t * y_t * z_t - (s_z - k) * x_t * y_t;
8898865f1eaSKarl Rupp         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 */
8908865f1eaSKarl Rupp         for (j = 0; j < s_x; j++) idx[nn++] = s_t++;
89147c6ae99SBarry Smith       }
89247c6ae99SBarry Smith     }
89347c6ae99SBarry Smith   }
89447c6ae99SBarry Smith 
89547c6ae99SBarry Smith   /* Middle Level */
89647c6ae99SBarry Smith   for (k = 0; k < z; k++) {
89747c6ae99SBarry Smith     for (i = 1; i <= s_y; i++) {
89847c6ae99SBarry Smith       if (n9 >= 0) { /* left below */
899ce00eea3SSatish Balay         x_t = lx[n9 % m];
90047c6ae99SBarry Smith         y_t = ly[(n9 % (m * n)) / m];
90147c6ae99SBarry Smith         /* z_t = z; */
90247c6ae99SBarry Smith         s_t = bases[n9] - (s_y - i) * x_t - s_x + (k + 1) * x_t * y_t;
9038865f1eaSKarl Rupp         for (j = 0; j < s_x; j++) idx[nn++] = s_t++;
90447c6ae99SBarry Smith       }
90547c6ae99SBarry Smith       if (n10 >= 0) { /* directly below */
90647c6ae99SBarry Smith         x_t = x;
90747c6ae99SBarry Smith         y_t = ly[(n10 % (m * n)) / m];
90847c6ae99SBarry Smith         /* z_t = z; */
90947c6ae99SBarry Smith         s_t = bases[n10] - (s_y + 1 - i) * x_t + (k + 1) * x_t * y_t;
9108865f1eaSKarl Rupp         for (j = 0; j < x_t; j++) idx[nn++] = s_t++;
911bff4a2f0SMatthew G. Knepley       } else if (by == DM_BOUNDARY_MIRROR) {
912a6fd6b0aSBarry Smith         for (j = 0; j < x; j++) idx[nn++] = bases[rank] + j + k * x * y + (s_y - i) * x;
91347c6ae99SBarry Smith       }
91447c6ae99SBarry Smith       if (n11 >= 0) { /* right below */
915ce00eea3SSatish Balay         x_t = lx[n11 % m];
91647c6ae99SBarry Smith         y_t = ly[(n11 % (m * n)) / m];
91747c6ae99SBarry Smith         /* z_t = z; */
91847c6ae99SBarry Smith         s_t = bases[n11] - (s_y + 1 - i) * x_t + (k + 1) * x_t * y_t;
9198865f1eaSKarl Rupp         for (j = 0; j < s_x; j++) idx[nn++] = s_t++;
92047c6ae99SBarry Smith       }
92147c6ae99SBarry Smith     }
92247c6ae99SBarry Smith 
92347c6ae99SBarry Smith     for (i = 0; i < y; i++) {
92447c6ae99SBarry Smith       if (n12 >= 0) { /* directly left */
925ce00eea3SSatish Balay         x_t = lx[n12 % m];
92647c6ae99SBarry Smith         y_t = y;
92747c6ae99SBarry Smith         /* z_t = z; */
92847c6ae99SBarry Smith         s_t = bases[n12] + (i + 1) * x_t - s_x + k * x_t * y_t;
9298865f1eaSKarl Rupp         for (j = 0; j < s_x; j++) idx[nn++] = s_t++;
930bff4a2f0SMatthew G. Knepley       } else if (bx == DM_BOUNDARY_MIRROR) {
931a6fd6b0aSBarry Smith         for (j = 0; j < s_x; j++) idx[nn++] = bases[rank] + s_x - j - 1 + k * x * y + i * x;
93247c6ae99SBarry Smith       }
93347c6ae99SBarry Smith 
93447c6ae99SBarry Smith       /* Interior */
93547c6ae99SBarry Smith       s_t = bases[rank] + i * x + k * x * y;
9368865f1eaSKarl Rupp       for (j = 0; j < x; j++) idx[nn++] = s_t++;
93747c6ae99SBarry Smith 
93847c6ae99SBarry Smith       if (n14 >= 0) { /* directly right */
939ce00eea3SSatish Balay         x_t = lx[n14 % m];
94047c6ae99SBarry Smith         y_t = y;
94147c6ae99SBarry Smith         /* z_t = z; */
94247c6ae99SBarry Smith         s_t = bases[n14] + i * x_t + k * x_t * y_t;
9438865f1eaSKarl Rupp         for (j = 0; j < s_x; j++) idx[nn++] = s_t++;
944bff4a2f0SMatthew G. Knepley       } else if (bx == DM_BOUNDARY_MIRROR) {
945a6fd6b0aSBarry Smith         for (j = 0; j < s_x; j++) idx[nn++] = bases[rank] + x - j - 1 + k * x * y + i * x;
94647c6ae99SBarry Smith       }
94747c6ae99SBarry Smith     }
94847c6ae99SBarry Smith 
94947c6ae99SBarry Smith     for (i = 1; i <= s_y; i++) {
95047c6ae99SBarry Smith       if (n15 >= 0) { /* left above */
951ce00eea3SSatish Balay         x_t = lx[n15 % m];
95247c6ae99SBarry Smith         y_t = ly[(n15 % (m * n)) / m];
95347c6ae99SBarry Smith         /* z_t = z; */
95447c6ae99SBarry Smith         s_t = bases[n15] + i * x_t - s_x + k * x_t * y_t;
9558865f1eaSKarl Rupp         for (j = 0; j < s_x; j++) idx[nn++] = s_t++;
95647c6ae99SBarry Smith       }
95747c6ae99SBarry Smith       if (n16 >= 0) { /* directly above */
95847c6ae99SBarry Smith         x_t = x;
95947c6ae99SBarry Smith         y_t = ly[(n16 % (m * n)) / m];
96047c6ae99SBarry Smith         /* z_t = z; */
96147c6ae99SBarry Smith         s_t = bases[n16] + (i - 1) * x_t + k * x_t * y_t;
9628865f1eaSKarl Rupp         for (j = 0; j < x_t; j++) idx[nn++] = s_t++;
963bff4a2f0SMatthew G. Knepley       } else if (by == DM_BOUNDARY_MIRROR) {
964a6fd6b0aSBarry Smith         for (j = 0; j < x; j++) idx[nn++] = bases[rank] + j + k * x * y + (y - i) * x;
96547c6ae99SBarry Smith       }
96647c6ae99SBarry Smith       if (n17 >= 0) { /* right above */
967ce00eea3SSatish Balay         x_t = lx[n17 % m];
96847c6ae99SBarry Smith         y_t = ly[(n17 % (m * n)) / m];
96947c6ae99SBarry Smith         /* z_t = z; */
97047c6ae99SBarry Smith         s_t = bases[n17] + (i - 1) * x_t + k * x_t * y_t;
9718865f1eaSKarl Rupp         for (j = 0; j < s_x; j++) idx[nn++] = s_t++;
97247c6ae99SBarry Smith       }
97347c6ae99SBarry Smith     }
97447c6ae99SBarry Smith   }
97547c6ae99SBarry Smith 
97647c6ae99SBarry Smith   /* Upper Level */
97747c6ae99SBarry Smith   for (k = 0; k < s_z; k++) {
97847c6ae99SBarry Smith     for (i = 1; i <= s_y; i++) {
97947c6ae99SBarry Smith       if (n18 >= 0) { /* left below */
980ce00eea3SSatish Balay         x_t = lx[n18 % m];
98147c6ae99SBarry Smith         y_t = ly[(n18 % (m * n)) / m];
98247c6ae99SBarry Smith         /* z_t = lz[n18 / (m*n)]; */
98347c6ae99SBarry Smith         s_t = bases[n18] - (s_y - i) * x_t - s_x + (k + 1) * x_t * y_t;
9848865f1eaSKarl Rupp         if (twod && (s_t >= M * N * P)) s_t = bases[n18] - (s_y - i) * x_t - s_x + x_t * y_t; /* 2d case */
9858865f1eaSKarl Rupp         for (j = 0; j < s_x; j++) idx[nn++] = s_t++;
98647c6ae99SBarry Smith       }
98747c6ae99SBarry Smith       if (n19 >= 0) { /* directly below */
98847c6ae99SBarry Smith         x_t = x;
98947c6ae99SBarry Smith         y_t = ly[(n19 % (m * n)) / m];
99047c6ae99SBarry Smith         /* z_t = lz[n19 / (m*n)]; */
99147c6ae99SBarry Smith         s_t = bases[n19] - (s_y + 1 - i) * x_t + (k + 1) * x_t * y_t;
9928865f1eaSKarl Rupp         if (twod && (s_t >= M * N * P)) s_t = bases[n19] - (s_y + 1 - i) * x_t + x_t * y_t; /* 2d case */
9938865f1eaSKarl Rupp         for (j = 0; j < x_t; j++) idx[nn++] = s_t++;
99447c6ae99SBarry Smith       }
99547c6ae99SBarry Smith       if (n20 >= 0) { /* right below */
996ce00eea3SSatish Balay         x_t = lx[n20 % m];
99747c6ae99SBarry Smith         y_t = ly[(n20 % (m * n)) / m];
99847c6ae99SBarry Smith         /* z_t = lz[n20 / (m*n)]; */
99947c6ae99SBarry Smith         s_t = bases[n20] - (s_y + 1 - i) * x_t + (k + 1) * x_t * y_t;
10008865f1eaSKarl Rupp         if (twod && (s_t >= M * N * P)) s_t = bases[n20] - (s_y + 1 - i) * x_t + x_t * y_t; /* 2d case */
10018865f1eaSKarl Rupp         for (j = 0; j < s_x; j++) idx[nn++] = s_t++;
100247c6ae99SBarry Smith       }
100347c6ae99SBarry Smith     }
100447c6ae99SBarry Smith 
100547c6ae99SBarry Smith     for (i = 0; i < y; i++) {
100647c6ae99SBarry Smith       if (n21 >= 0) { /* directly left */
1007ce00eea3SSatish Balay         x_t = lx[n21 % m];
100847c6ae99SBarry Smith         y_t = y;
100947c6ae99SBarry Smith         /* z_t = lz[n21 / (m*n)]; */
101047c6ae99SBarry Smith         s_t = bases[n21] + (i + 1) * x_t - s_x + k * x_t * y_t;
10118865f1eaSKarl Rupp         if (twod && (s_t >= M * N * P)) s_t = bases[n21] + (i + 1) * x_t - s_x; /* 2d case */
10128865f1eaSKarl Rupp         for (j = 0; j < s_x; j++) idx[nn++] = s_t++;
101347c6ae99SBarry Smith       }
101447c6ae99SBarry Smith 
101547c6ae99SBarry Smith       if (n22 >= 0) { /* middle */
101647c6ae99SBarry Smith         x_t = x;
101747c6ae99SBarry Smith         y_t = y;
101847c6ae99SBarry Smith         /* z_t = lz[n22 / (m*n)]; */
101947c6ae99SBarry Smith         s_t = bases[n22] + i * x_t + k * x_t * y_t;
10208865f1eaSKarl Rupp         if (twod && (s_t >= M * N * P)) s_t = bases[n22] + i * x_t; /* 2d case */
10218865f1eaSKarl Rupp         for (j = 0; j < x_t; j++) idx[nn++] = s_t++;
1022bff4a2f0SMatthew G. Knepley       } else if (bz == DM_BOUNDARY_MIRROR) {
1023a6fd6b0aSBarry Smith         for (j = 0; j < x; j++) idx[nn++] = bases[rank] + j + (z - k - 1) * x * y + i * x;
102447c6ae99SBarry Smith       }
102547c6ae99SBarry Smith 
102647c6ae99SBarry Smith       if (n23 >= 0) { /* directly right */
1027ce00eea3SSatish Balay         x_t = lx[n23 % m];
102847c6ae99SBarry Smith         y_t = y;
102947c6ae99SBarry Smith         /* z_t = lz[n23 / (m*n)]; */
103047c6ae99SBarry Smith         s_t = bases[n23] + i * x_t + k * x_t * y_t;
10318865f1eaSKarl Rupp         if (twod && (s_t >= M * N * P)) s_t = bases[n23] + i * x_t; /* 2d case */
10328865f1eaSKarl Rupp         for (j = 0; j < s_x; j++) idx[nn++] = s_t++;
103347c6ae99SBarry Smith       }
103447c6ae99SBarry Smith     }
103547c6ae99SBarry Smith 
103647c6ae99SBarry Smith     for (i = 1; i <= s_y; i++) {
103747c6ae99SBarry Smith       if (n24 >= 0) { /* left above */
1038ce00eea3SSatish Balay         x_t = lx[n24 % m];
103947c6ae99SBarry Smith         y_t = ly[(n24 % (m * n)) / m];
104047c6ae99SBarry Smith         /* z_t = lz[n24 / (m*n)]; */
104147c6ae99SBarry Smith         s_t = bases[n24] + i * x_t - s_x + k * x_t * y_t;
10428865f1eaSKarl Rupp         if (twod && (s_t >= M * N * P)) s_t = bases[n24] + i * x_t - s_x; /* 2d case */
10438865f1eaSKarl Rupp         for (j = 0; j < s_x; j++) idx[nn++] = s_t++;
104447c6ae99SBarry Smith       }
104547c6ae99SBarry Smith       if (n25 >= 0) { /* directly above */
104647c6ae99SBarry Smith         x_t = x;
104747c6ae99SBarry Smith         y_t = ly[(n25 % (m * n)) / m];
104847c6ae99SBarry Smith         /* z_t = lz[n25 / (m*n)]; */
104947c6ae99SBarry Smith         s_t = bases[n25] + (i - 1) * x_t + k * x_t * y_t;
10508865f1eaSKarl Rupp         if (twod && (s_t >= M * N * P)) s_t = bases[n25] + (i - 1) * x_t; /* 2d case */
10518865f1eaSKarl Rupp         for (j = 0; j < x_t; j++) idx[nn++] = s_t++;
105247c6ae99SBarry Smith       }
105347c6ae99SBarry Smith       if (n26 >= 0) { /* right above */
1054ce00eea3SSatish Balay         x_t = lx[n26 % m];
105547c6ae99SBarry Smith         y_t = ly[(n26 % (m * n)) / m];
105647c6ae99SBarry Smith         /* z_t = lz[n26 / (m*n)]; */
105747c6ae99SBarry Smith         s_t = bases[n26] + (i - 1) * x_t + k * x_t * y_t;
10588865f1eaSKarl Rupp         if (twod && (s_t >= M * N * P)) s_t = bases[n26] + (i - 1) * x_t; /* 2d case */
10598865f1eaSKarl Rupp         for (j = 0; j < s_x; j++) idx[nn++] = s_t++;
106047c6ae99SBarry Smith       }
106147c6ae99SBarry Smith     }
106247c6ae99SBarry Smith   }
1063ce00eea3SSatish Balay 
10649566063dSJacob Faibussowitsch   PetscCall(ISCreateBlock(comm, dof, nn, idx, PETSC_USE_POINTER, &from));
10659566063dSJacob Faibussowitsch   PetscCall(VecScatterCreate(global, from, local, to, &gtol));
10669566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&to));
10679566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&from));
106847c6ae99SBarry Smith 
1069d9c9ebe5SPeter Brune   if (stencil_type == DMDA_STENCIL_STAR) {
10709371c9d4SSatish Balay     n0  = sn0;
10719371c9d4SSatish Balay     n1  = sn1;
10729371c9d4SSatish Balay     n2  = sn2;
10739371c9d4SSatish Balay     n3  = sn3;
10749371c9d4SSatish Balay     n5  = sn5;
10759371c9d4SSatish Balay     n6  = sn6;
10769371c9d4SSatish Balay     n7  = sn7;
10779371c9d4SSatish Balay     n8  = sn8;
10789371c9d4SSatish Balay     n9  = sn9;
10799371c9d4SSatish Balay     n11 = sn11;
10809371c9d4SSatish Balay     n15 = sn15;
10819371c9d4SSatish Balay     n17 = sn17;
10829371c9d4SSatish Balay     n18 = sn18;
10839371c9d4SSatish Balay     n19 = sn19;
10849371c9d4SSatish Balay     n20 = sn20;
10859371c9d4SSatish Balay     n21 = sn21;
10869371c9d4SSatish Balay     n23 = sn23;
10879371c9d4SSatish Balay     n24 = sn24;
10889371c9d4SSatish Balay     n25 = sn25;
108947c6ae99SBarry Smith     n26 = sn26;
1090ce00eea3SSatish Balay   }
109147c6ae99SBarry Smith 
1092288e7d53SBarry Smith   if (((stencil_type == DMDA_STENCIL_STAR) || (bx != DM_BOUNDARY_PERIODIC && bx) || (by != DM_BOUNDARY_PERIODIC && by) || (bz != DM_BOUNDARY_PERIODIC && bz))) {
1093ce00eea3SSatish Balay     /*
1094ce00eea3SSatish Balay         Recompute the local to global mappings, this time keeping the
1095ce00eea3SSatish Balay       information about the cross corner processor numbers.
1096ce00eea3SSatish Balay     */
109747c6ae99SBarry Smith     nn = 0;
109847c6ae99SBarry Smith     /* Bottom Level */
109947c6ae99SBarry Smith     for (k = 0; k < s_z; k++) {
110047c6ae99SBarry Smith       for (i = 1; i <= s_y; i++) {
110147c6ae99SBarry Smith         if (n0 >= 0) { /* left below */
1102ce00eea3SSatish Balay           x_t = lx[n0 % m];
110347c6ae99SBarry Smith           y_t = ly[(n0 % (m * n)) / m];
110447c6ae99SBarry Smith           z_t = lz[n0 / (m * n)];
110547c6ae99SBarry Smith           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;
11068865f1eaSKarl Rupp           for (j = 0; j < s_x; j++) idx[nn++] = s_t++;
1107ce00eea3SSatish Balay         } else if (Xs - xs < 0 && Ys - ys < 0 && Zs - zs < 0) {
11088865f1eaSKarl Rupp           for (j = 0; j < s_x; j++) idx[nn++] = -1;
110947c6ae99SBarry Smith         }
111047c6ae99SBarry Smith         if (n1 >= 0) { /* directly below */
111147c6ae99SBarry Smith           x_t = x;
111247c6ae99SBarry Smith           y_t = ly[(n1 % (m * n)) / m];
111347c6ae99SBarry Smith           z_t = lz[n1 / (m * n)];
111447c6ae99SBarry Smith           s_t = bases[n1] + x_t * y_t * z_t - (s_y + 1 - i) * x_t - (s_z - k - 1) * x_t * y_t;
11158865f1eaSKarl Rupp           for (j = 0; j < x_t; j++) idx[nn++] = s_t++;
1116ce00eea3SSatish Balay         } else if (Ys - ys < 0 && Zs - zs < 0) {
11178865f1eaSKarl Rupp           for (j = 0; j < x; j++) idx[nn++] = -1;
111847c6ae99SBarry Smith         }
111947c6ae99SBarry Smith         if (n2 >= 0) { /* right below */
1120ce00eea3SSatish Balay           x_t = lx[n2 % m];
112147c6ae99SBarry Smith           y_t = ly[(n2 % (m * n)) / m];
112247c6ae99SBarry Smith           z_t = lz[n2 / (m * n)];
112347c6ae99SBarry Smith           s_t = bases[n2] + x_t * y_t * z_t - (s_y + 1 - i) * x_t - (s_z - k - 1) * x_t * y_t;
11248865f1eaSKarl Rupp           for (j = 0; j < s_x; j++) idx[nn++] = s_t++;
1125ce00eea3SSatish Balay         } else if (xe - Xe < 0 && Ys - ys < 0 && Zs - zs < 0) {
11268865f1eaSKarl Rupp           for (j = 0; j < s_x; j++) idx[nn++] = -1;
112747c6ae99SBarry Smith         }
112847c6ae99SBarry Smith       }
112947c6ae99SBarry Smith 
113047c6ae99SBarry Smith       for (i = 0; i < y; i++) {
113147c6ae99SBarry Smith         if (n3 >= 0) { /* directly left */
1132ce00eea3SSatish Balay           x_t = lx[n3 % m];
113347c6ae99SBarry Smith           y_t = y;
113447c6ae99SBarry Smith           z_t = lz[n3 / (m * n)];
113547c6ae99SBarry Smith           s_t = bases[n3] + (i + 1) * x_t - s_x + x_t * y_t * z_t - (s_z - k) * x_t * y_t;
11368865f1eaSKarl Rupp           for (j = 0; j < s_x; j++) idx[nn++] = s_t++;
1137ce00eea3SSatish Balay         } else if (Xs - xs < 0 && Zs - zs < 0) {
11388865f1eaSKarl Rupp           for (j = 0; j < s_x; j++) idx[nn++] = -1;
113947c6ae99SBarry Smith         }
114047c6ae99SBarry Smith 
114147c6ae99SBarry Smith         if (n4 >= 0) { /* middle */
114247c6ae99SBarry Smith           x_t = x;
114347c6ae99SBarry Smith           y_t = y;
114447c6ae99SBarry Smith           z_t = lz[n4 / (m * n)];
114547c6ae99SBarry Smith           s_t = bases[n4] + i * x_t + x_t * y_t * z_t - (s_z - k) * x_t * y_t;
11468865f1eaSKarl Rupp           for (j = 0; j < x_t; j++) idx[nn++] = s_t++;
1147ce00eea3SSatish Balay         } else if (Zs - zs < 0) {
1148bff4a2f0SMatthew G. Knepley           if (bz == DM_BOUNDARY_MIRROR) {
1149a6fd6b0aSBarry Smith             for (j = 0; j < x; j++) idx[nn++] = bases[rank] + j + x * i + (s_z - k - 1) * x * y;
1150c2859e5eSBarry Smith           } else {
11518865f1eaSKarl Rupp             for (j = 0; j < x; j++) idx[nn++] = -1;
115247c6ae99SBarry Smith           }
1153c2859e5eSBarry Smith         }
115447c6ae99SBarry Smith 
115547c6ae99SBarry Smith         if (n5 >= 0) { /* directly right */
1156ce00eea3SSatish Balay           x_t = lx[n5 % m];
115747c6ae99SBarry Smith           y_t = y;
115847c6ae99SBarry Smith           z_t = lz[n5 / (m * n)];
115947c6ae99SBarry Smith           s_t = bases[n5] + i * x_t + x_t * y_t * z_t - (s_z - k) * x_t * y_t;
11608865f1eaSKarl Rupp           for (j = 0; j < s_x; j++) idx[nn++] = s_t++;
1161ce00eea3SSatish Balay         } else if (xe - Xe < 0 && Zs - zs < 0) {
11628865f1eaSKarl Rupp           for (j = 0; j < s_x; j++) idx[nn++] = -1;
116347c6ae99SBarry Smith         }
116447c6ae99SBarry Smith       }
116547c6ae99SBarry Smith 
116647c6ae99SBarry Smith       for (i = 1; i <= s_y; i++) {
116747c6ae99SBarry Smith         if (n6 >= 0) { /* left above */
1168ce00eea3SSatish Balay           x_t = lx[n6 % m];
116947c6ae99SBarry Smith           y_t = ly[(n6 % (m * n)) / m];
117047c6ae99SBarry Smith           z_t = lz[n6 / (m * n)];
117147c6ae99SBarry Smith           s_t = bases[n6] + i * x_t - s_x + x_t * y_t * z_t - (s_z - k) * x_t * y_t;
11728865f1eaSKarl Rupp           for (j = 0; j < s_x; j++) idx[nn++] = s_t++;
1173ce00eea3SSatish Balay         } else if (Xs - xs < 0 && ye - Ye < 0 && Zs - zs < 0) {
11748865f1eaSKarl Rupp           for (j = 0; j < s_x; j++) idx[nn++] = -1;
117547c6ae99SBarry Smith         }
117647c6ae99SBarry Smith         if (n7 >= 0) { /* directly above */
117747c6ae99SBarry Smith           x_t = x;
117847c6ae99SBarry Smith           y_t = ly[(n7 % (m * n)) / m];
117947c6ae99SBarry Smith           z_t = lz[n7 / (m * n)];
118047c6ae99SBarry Smith           s_t = bases[n7] + (i - 1) * x_t + x_t * y_t * z_t - (s_z - k) * x_t * y_t;
11818865f1eaSKarl Rupp           for (j = 0; j < x_t; j++) idx[nn++] = s_t++;
1182ce00eea3SSatish Balay         } else if (ye - Ye < 0 && Zs - zs < 0) {
11838865f1eaSKarl Rupp           for (j = 0; j < x; j++) idx[nn++] = -1;
118447c6ae99SBarry Smith         }
118547c6ae99SBarry Smith         if (n8 >= 0) { /* right above */
1186ce00eea3SSatish Balay           x_t = lx[n8 % m];
118747c6ae99SBarry Smith           y_t = ly[(n8 % (m * n)) / m];
118847c6ae99SBarry Smith           z_t = lz[n8 / (m * n)];
118947c6ae99SBarry Smith           s_t = bases[n8] + (i - 1) * x_t + x_t * y_t * z_t - (s_z - k) * x_t * y_t;
11908865f1eaSKarl Rupp           for (j = 0; j < s_x; j++) idx[nn++] = s_t++;
1191ce00eea3SSatish Balay         } else if (xe - Xe < 0 && ye - Ye < 0 && Zs - zs < 0) {
11928865f1eaSKarl Rupp           for (j = 0; j < s_x; j++) idx[nn++] = -1;
119347c6ae99SBarry Smith         }
119447c6ae99SBarry Smith       }
119547c6ae99SBarry Smith     }
119647c6ae99SBarry Smith 
119747c6ae99SBarry Smith     /* Middle Level */
119847c6ae99SBarry Smith     for (k = 0; k < z; k++) {
119947c6ae99SBarry Smith       for (i = 1; i <= s_y; i++) {
120047c6ae99SBarry Smith         if (n9 >= 0) { /* left below */
1201ce00eea3SSatish Balay           x_t = lx[n9 % m];
120247c6ae99SBarry Smith           y_t = ly[(n9 % (m * n)) / m];
120347c6ae99SBarry Smith           /* z_t = z; */
120447c6ae99SBarry Smith           s_t = bases[n9] - (s_y - i) * x_t - s_x + (k + 1) * x_t * y_t;
12058865f1eaSKarl Rupp           for (j = 0; j < s_x; j++) idx[nn++] = s_t++;
1206ce00eea3SSatish Balay         } else if (Xs - xs < 0 && Ys - ys < 0) {
12078865f1eaSKarl Rupp           for (j = 0; j < s_x; j++) idx[nn++] = -1;
120847c6ae99SBarry Smith         }
120947c6ae99SBarry Smith         if (n10 >= 0) { /* directly below */
121047c6ae99SBarry Smith           x_t = x;
121147c6ae99SBarry Smith           y_t = ly[(n10 % (m * n)) / m];
121247c6ae99SBarry Smith           /* z_t = z; */
121347c6ae99SBarry Smith           s_t = bases[n10] - (s_y + 1 - i) * x_t + (k + 1) * x_t * y_t;
12148865f1eaSKarl Rupp           for (j = 0; j < x_t; j++) idx[nn++] = s_t++;
1215ce00eea3SSatish Balay         } else if (Ys - ys < 0) {
1216bff4a2f0SMatthew G. Knepley           if (by == DM_BOUNDARY_MIRROR) {
1217feb237baSPierre Jolivet             for (j = 0; j < x; j++) idx[nn++] = bases[rank] + j + k * x * y + (s_y - i) * x;
1218c2859e5eSBarry Smith           } else {
12198865f1eaSKarl Rupp             for (j = 0; j < x; j++) idx[nn++] = -1;
1220c2859e5eSBarry Smith           }
122147c6ae99SBarry Smith         }
122247c6ae99SBarry Smith         if (n11 >= 0) { /* right below */
1223ce00eea3SSatish Balay           x_t = lx[n11 % m];
122447c6ae99SBarry Smith           y_t = ly[(n11 % (m * n)) / m];
122547c6ae99SBarry Smith           /* z_t = z; */
122647c6ae99SBarry Smith           s_t = bases[n11] - (s_y + 1 - i) * x_t + (k + 1) * x_t * y_t;
12278865f1eaSKarl Rupp           for (j = 0; j < s_x; j++) idx[nn++] = s_t++;
1228ce00eea3SSatish Balay         } else if (xe - Xe < 0 && Ys - ys < 0) {
12298865f1eaSKarl Rupp           for (j = 0; j < s_x; j++) idx[nn++] = -1;
123047c6ae99SBarry Smith         }
123147c6ae99SBarry Smith       }
123247c6ae99SBarry Smith 
123347c6ae99SBarry Smith       for (i = 0; i < y; i++) {
123447c6ae99SBarry Smith         if (n12 >= 0) { /* directly left */
1235ce00eea3SSatish Balay           x_t = lx[n12 % m];
123647c6ae99SBarry Smith           y_t = y;
123747c6ae99SBarry Smith           /* z_t = z; */
123847c6ae99SBarry Smith           s_t = bases[n12] + (i + 1) * x_t - s_x + k * x_t * y_t;
12398865f1eaSKarl Rupp           for (j = 0; j < s_x; j++) idx[nn++] = s_t++;
1240ce00eea3SSatish Balay         } else if (Xs - xs < 0) {
1241bff4a2f0SMatthew G. Knepley           if (bx == DM_BOUNDARY_MIRROR) {
1242a6fd6b0aSBarry Smith             for (j = 0; j < s_x; j++) idx[nn++] = bases[rank] + s_x - j - 1 + k * x * y + i * x;
1243c2859e5eSBarry Smith           } else {
12448865f1eaSKarl Rupp             for (j = 0; j < s_x; j++) idx[nn++] = -1;
124547c6ae99SBarry Smith           }
1246c2859e5eSBarry Smith         }
124747c6ae99SBarry Smith 
124847c6ae99SBarry Smith         /* Interior */
124947c6ae99SBarry Smith         s_t = bases[rank] + i * x + k * x * y;
12508865f1eaSKarl Rupp         for (j = 0; j < x; j++) idx[nn++] = s_t++;
125147c6ae99SBarry Smith 
125247c6ae99SBarry Smith         if (n14 >= 0) { /* directly right */
1253ce00eea3SSatish Balay           x_t = lx[n14 % m];
125447c6ae99SBarry Smith           y_t = y;
125547c6ae99SBarry Smith           /* z_t = z; */
125647c6ae99SBarry Smith           s_t = bases[n14] + i * x_t + k * x_t * y_t;
12578865f1eaSKarl Rupp           for (j = 0; j < s_x; j++) idx[nn++] = s_t++;
1258ce00eea3SSatish Balay         } else if (xe - Xe < 0) {
1259bff4a2f0SMatthew G. Knepley           if (bx == DM_BOUNDARY_MIRROR) {
1260a6fd6b0aSBarry Smith             for (j = 0; j < s_x; j++) idx[nn++] = bases[rank] + x - j - 1 + k * x * y + i * x;
1261c2859e5eSBarry Smith           } else {
12628865f1eaSKarl Rupp             for (j = 0; j < s_x; j++) idx[nn++] = -1;
126347c6ae99SBarry Smith           }
126447c6ae99SBarry Smith         }
1265c2859e5eSBarry Smith       }
126647c6ae99SBarry Smith 
126747c6ae99SBarry Smith       for (i = 1; i <= s_y; i++) {
126847c6ae99SBarry Smith         if (n15 >= 0) { /* left above */
1269ce00eea3SSatish Balay           x_t = lx[n15 % m];
127047c6ae99SBarry Smith           y_t = ly[(n15 % (m * n)) / m];
127147c6ae99SBarry Smith           /* z_t = z; */
127247c6ae99SBarry Smith           s_t = bases[n15] + i * x_t - s_x + k * x_t * y_t;
12738865f1eaSKarl Rupp           for (j = 0; j < s_x; j++) idx[nn++] = s_t++;
1274ce00eea3SSatish Balay         } else if (Xs - xs < 0 && ye - Ye < 0) {
12758865f1eaSKarl Rupp           for (j = 0; j < s_x; j++) idx[nn++] = -1;
127647c6ae99SBarry Smith         }
127747c6ae99SBarry Smith         if (n16 >= 0) { /* directly above */
127847c6ae99SBarry Smith           x_t = x;
127947c6ae99SBarry Smith           y_t = ly[(n16 % (m * n)) / m];
128047c6ae99SBarry Smith           /* z_t = z; */
128147c6ae99SBarry Smith           s_t = bases[n16] + (i - 1) * x_t + k * x_t * y_t;
12828865f1eaSKarl Rupp           for (j = 0; j < x_t; j++) idx[nn++] = s_t++;
1283ce00eea3SSatish Balay         } else if (ye - Ye < 0) {
1284bff4a2f0SMatthew G. Knepley           if (by == DM_BOUNDARY_MIRROR) {
1285a6fd6b0aSBarry Smith             for (j = 0; j < x; j++) idx[nn++] = bases[rank] + j + k * x * y + (y - i) * x;
1286c2859e5eSBarry Smith           } else {
12878865f1eaSKarl Rupp             for (j = 0; j < x; j++) idx[nn++] = -1;
128847c6ae99SBarry Smith           }
1289c2859e5eSBarry Smith         }
129047c6ae99SBarry Smith         if (n17 >= 0) { /* right above */
1291ce00eea3SSatish Balay           x_t = lx[n17 % m];
129247c6ae99SBarry Smith           y_t = ly[(n17 % (m * n)) / m];
129347c6ae99SBarry Smith           /* z_t = z; */
129447c6ae99SBarry Smith           s_t = bases[n17] + (i - 1) * x_t + k * x_t * y_t;
12958865f1eaSKarl Rupp           for (j = 0; j < s_x; j++) idx[nn++] = s_t++;
1296ce00eea3SSatish Balay         } else if (xe - Xe < 0 && ye - Ye < 0) {
12978865f1eaSKarl Rupp           for (j = 0; j < s_x; j++) idx[nn++] = -1;
129847c6ae99SBarry Smith         }
129947c6ae99SBarry Smith       }
130047c6ae99SBarry Smith     }
130147c6ae99SBarry Smith 
130247c6ae99SBarry Smith     /* Upper Level */
130347c6ae99SBarry Smith     for (k = 0; k < s_z; k++) {
130447c6ae99SBarry Smith       for (i = 1; i <= s_y; i++) {
130547c6ae99SBarry Smith         if (n18 >= 0) { /* left below */
1306ce00eea3SSatish Balay           x_t = lx[n18 % m];
130747c6ae99SBarry Smith           y_t = ly[(n18 % (m * n)) / m];
130847c6ae99SBarry Smith           /* z_t = lz[n18 / (m*n)]; */
130947c6ae99SBarry Smith           s_t = bases[n18] - (s_y - i) * x_t - s_x + (k + 1) * x_t * y_t;
13108865f1eaSKarl Rupp           for (j = 0; j < s_x; j++) idx[nn++] = s_t++;
1311ce00eea3SSatish Balay         } else if (Xs - xs < 0 && Ys - ys < 0 && ze - Ze < 0) {
13128865f1eaSKarl Rupp           for (j = 0; j < s_x; j++) idx[nn++] = -1;
131347c6ae99SBarry Smith         }
131447c6ae99SBarry Smith         if (n19 >= 0) { /* directly below */
131547c6ae99SBarry Smith           x_t = x;
131647c6ae99SBarry Smith           y_t = ly[(n19 % (m * n)) / m];
131747c6ae99SBarry Smith           /* z_t = lz[n19 / (m*n)]; */
131847c6ae99SBarry Smith           s_t = bases[n19] - (s_y + 1 - i) * x_t + (k + 1) * x_t * y_t;
13198865f1eaSKarl Rupp           for (j = 0; j < x_t; j++) idx[nn++] = s_t++;
1320ce00eea3SSatish Balay         } else if (Ys - ys < 0 && ze - Ze < 0) {
13218865f1eaSKarl Rupp           for (j = 0; j < x; j++) idx[nn++] = -1;
132247c6ae99SBarry Smith         }
132347c6ae99SBarry Smith         if (n20 >= 0) { /* right below */
1324ce00eea3SSatish Balay           x_t = lx[n20 % m];
132547c6ae99SBarry Smith           y_t = ly[(n20 % (m * n)) / m];
132647c6ae99SBarry Smith           /* z_t = lz[n20 / (m*n)]; */
132747c6ae99SBarry Smith           s_t = bases[n20] - (s_y + 1 - i) * x_t + (k + 1) * x_t * y_t;
13288865f1eaSKarl Rupp           for (j = 0; j < s_x; j++) idx[nn++] = s_t++;
1329ce00eea3SSatish Balay         } else if (xe - Xe < 0 && Ys - ys < 0 && ze - Ze < 0) {
13308865f1eaSKarl Rupp           for (j = 0; j < s_x; j++) idx[nn++] = -1;
133147c6ae99SBarry Smith         }
133247c6ae99SBarry Smith       }
133347c6ae99SBarry Smith 
133447c6ae99SBarry Smith       for (i = 0; i < y; i++) {
133547c6ae99SBarry Smith         if (n21 >= 0) { /* directly left */
1336ce00eea3SSatish Balay           x_t = lx[n21 % m];
133747c6ae99SBarry Smith           y_t = y;
133847c6ae99SBarry Smith           /* z_t = lz[n21 / (m*n)]; */
133947c6ae99SBarry Smith           s_t = bases[n21] + (i + 1) * x_t - s_x + k * x_t * y_t;
13408865f1eaSKarl Rupp           for (j = 0; j < s_x; j++) idx[nn++] = s_t++;
1341ce00eea3SSatish Balay         } else if (Xs - xs < 0 && ze - Ze < 0) {
13428865f1eaSKarl Rupp           for (j = 0; j < s_x; j++) idx[nn++] = -1;
134347c6ae99SBarry Smith         }
134447c6ae99SBarry Smith 
134547c6ae99SBarry Smith         if (n22 >= 0) { /* middle */
134647c6ae99SBarry Smith           x_t = x;
134747c6ae99SBarry Smith           y_t = y;
134847c6ae99SBarry Smith           /* z_t = lz[n22 / (m*n)]; */
134947c6ae99SBarry Smith           s_t = bases[n22] + i * x_t + k * x_t * y_t;
13508865f1eaSKarl Rupp           for (j = 0; j < x_t; j++) idx[nn++] = s_t++;
1351ce00eea3SSatish Balay         } else if (ze - Ze < 0) {
1352bff4a2f0SMatthew G. Knepley           if (bz == DM_BOUNDARY_MIRROR) {
1353a6fd6b0aSBarry Smith             for (j = 0; j < x; j++) idx[nn++] = bases[rank] + j + (z - k - 1) * x * y + i * x;
1354c2859e5eSBarry Smith           } else {
13558865f1eaSKarl Rupp             for (j = 0; j < x; j++) idx[nn++] = -1;
135647c6ae99SBarry Smith           }
1357c2859e5eSBarry Smith         }
135847c6ae99SBarry Smith 
135947c6ae99SBarry Smith         if (n23 >= 0) { /* directly right */
1360ce00eea3SSatish Balay           x_t = lx[n23 % m];
136147c6ae99SBarry Smith           y_t = y;
136247c6ae99SBarry Smith           /* z_t = lz[n23 / (m*n)]; */
136347c6ae99SBarry Smith           s_t = bases[n23] + i * x_t + k * x_t * y_t;
13648865f1eaSKarl Rupp           for (j = 0; j < s_x; j++) idx[nn++] = s_t++;
1365ce00eea3SSatish Balay         } else if (xe - Xe < 0 && ze - Ze < 0) {
13668865f1eaSKarl Rupp           for (j = 0; j < s_x; j++) idx[nn++] = -1;
136747c6ae99SBarry Smith         }
136847c6ae99SBarry Smith       }
136947c6ae99SBarry Smith 
137047c6ae99SBarry Smith       for (i = 1; i <= s_y; i++) {
137147c6ae99SBarry Smith         if (n24 >= 0) { /* left above */
1372ce00eea3SSatish Balay           x_t = lx[n24 % m];
137347c6ae99SBarry Smith           y_t = ly[(n24 % (m * n)) / m];
137447c6ae99SBarry Smith           /* z_t = lz[n24 / (m*n)]; */
137547c6ae99SBarry Smith           s_t = bases[n24] + i * x_t - s_x + k * x_t * y_t;
13768865f1eaSKarl Rupp           for (j = 0; j < s_x; j++) idx[nn++] = s_t++;
1377ce00eea3SSatish Balay         } else if (Xs - xs < 0 && ye - Ye < 0 && ze - Ze < 0) {
13788865f1eaSKarl Rupp           for (j = 0; j < s_x; j++) idx[nn++] = -1;
137947c6ae99SBarry Smith         }
138047c6ae99SBarry Smith         if (n25 >= 0) { /* directly above */
138147c6ae99SBarry Smith           x_t = x;
138247c6ae99SBarry Smith           y_t = ly[(n25 % (m * n)) / m];
138347c6ae99SBarry Smith           /* z_t = lz[n25 / (m*n)]; */
138447c6ae99SBarry Smith           s_t = bases[n25] + (i - 1) * x_t + k * x_t * y_t;
13858865f1eaSKarl Rupp           for (j = 0; j < x_t; j++) idx[nn++] = s_t++;
1386ce00eea3SSatish Balay         } else if (ye - Ye < 0 && ze - Ze < 0) {
13878865f1eaSKarl Rupp           for (j = 0; j < x; j++) idx[nn++] = -1;
138847c6ae99SBarry Smith         }
138947c6ae99SBarry Smith         if (n26 >= 0) { /* right above */
1390ce00eea3SSatish Balay           x_t = lx[n26 % m];
139147c6ae99SBarry Smith           y_t = ly[(n26 % (m * n)) / m];
139247c6ae99SBarry Smith           /* z_t = lz[n26 / (m*n)]; */
139347c6ae99SBarry Smith           s_t = bases[n26] + (i - 1) * x_t + k * x_t * y_t;
13948865f1eaSKarl Rupp           for (j = 0; j < s_x; j++) idx[nn++] = s_t++;
1395ce00eea3SSatish Balay         } else if (xe - Xe < 0 && ye - Ye < 0 && ze - Ze < 0) {
13968865f1eaSKarl Rupp           for (j = 0; j < s_x; j++) idx[nn++] = -1;
139747c6ae99SBarry Smith         }
139847c6ae99SBarry Smith       }
139947c6ae99SBarry Smith     }
140047c6ae99SBarry Smith   }
140147c6ae99SBarry Smith   /*
140247c6ae99SBarry Smith      Set the local to global ordering in the global vector, this allows use
140347c6ae99SBarry Smith      of VecSetValuesLocal().
140447c6ae99SBarry Smith   */
14059566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingCreate(comm, dof, nn, idx, PETSC_OWN_POINTER, &da->ltogmap));
140647c6ae99SBarry Smith 
14079566063dSJacob Faibussowitsch   PetscCall(PetscFree2(bases, ldims));
14089371c9d4SSatish Balay   dd->m = m;
14099371c9d4SSatish Balay   dd->n = n;
14109371c9d4SSatish Balay   dd->p = p;
1411ce00eea3SSatish Balay   /* note petsc expects xs/xe/Xs/Xe to be multiplied by #dofs in many places */
14129371c9d4SSatish Balay   dd->xs = xs * dof;
14139371c9d4SSatish Balay   dd->xe = xe * dof;
14149371c9d4SSatish Balay   dd->ys = ys;
14159371c9d4SSatish Balay   dd->ye = ye;
14169371c9d4SSatish Balay   dd->zs = zs;
14179371c9d4SSatish Balay   dd->ze = ze;
14189371c9d4SSatish Balay   dd->Xs = Xs * dof;
14199371c9d4SSatish Balay   dd->Xe = Xe * dof;
14209371c9d4SSatish Balay   dd->Ys = Ys;
14219371c9d4SSatish Balay   dd->Ye = Ye;
14229371c9d4SSatish Balay   dd->Zs = Zs;
14239371c9d4SSatish Balay   dd->Ze = Ze;
1424ce00eea3SSatish Balay 
14259566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&local));
14269566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&global));
1427ce00eea3SSatish Balay 
1428ce00eea3SSatish Balay   dd->gtol      = gtol;
1429ce00eea3SSatish Balay   dd->base      = base;
1430ce00eea3SSatish Balay   da->ops->view = DMView_DA_3d;
14310298fd71SBarry Smith   dd->ltol      = NULL;
14320298fd71SBarry Smith   dd->ao        = NULL;
14333ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
143447c6ae99SBarry Smith }
1435564755cdSBarry Smith 
143647c6ae99SBarry Smith /*@C
1437aa219208SBarry Smith   DMDACreate3d - Creates an object that will manage the communication of three-dimensional
1438*12b4a537SBarry Smith   regular array data that is distributed across one or more MPI processes.
143947c6ae99SBarry Smith 
1440d083f849SBarry Smith   Collective
144147c6ae99SBarry Smith 
144247c6ae99SBarry Smith   Input Parameters:
144347c6ae99SBarry Smith + comm         - MPI communicator
1444a4e35b19SJacob Faibussowitsch . bx           - type of x ghost nodes the array have.
1445a4e35b19SJacob Faibussowitsch                  Use one of `DM_BOUNDARY_NONE`, `DM_BOUNDARY_GHOSTED`, `DM_BOUNDARY_PERIODIC`.
1446a4e35b19SJacob Faibussowitsch . by           - type of y ghost nodes the array have.
1447a4e35b19SJacob Faibussowitsch                  Use one of `DM_BOUNDARY_NONE`, `DM_BOUNDARY_GHOSTED`, `DM_BOUNDARY_PERIODIC`.
1448a4e35b19SJacob Faibussowitsch . bz           - type of z ghost nodes the array have.
1449dce8aebaSBarry Smith                  Use one of `DM_BOUNDARY_NONE`, `DM_BOUNDARY_GHOSTED`, `DM_BOUNDARY_PERIODIC`.
1450dce8aebaSBarry Smith . stencil_type - Type of stencil (`DMDA_STENCIL_STAR` or `DMDA_STENCIL_BOX`)
1451a4e35b19SJacob Faibussowitsch . M            - global dimension in x direction of the array
1452a4e35b19SJacob Faibussowitsch . N            - global dimension in y direction of the array
1453a4e35b19SJacob Faibussowitsch . P            - global dimension in z direction of the array
1454a4e35b19SJacob Faibussowitsch . m            - corresponding number of processors in x dimension (or `PETSC_DECIDE` to have calculated)
1455a4e35b19SJacob Faibussowitsch . n            - corresponding number of processors in y dimension (or `PETSC_DECIDE` to have calculated)
1456a4e35b19SJacob Faibussowitsch . p            - corresponding number of processors in z dimension (or `PETSC_DECIDE` to have calculated)
145747c6ae99SBarry Smith . dof          - number of degrees of freedom per node
145810d7c030SMatthew G Knepley . s            - stencil width
1459a4e35b19SJacob Faibussowitsch . lx           - arrays containing the number of nodes in each cell along the x  coordinates, or `NULL`.
1460a4e35b19SJacob Faibussowitsch . ly           - arrays containing the number of nodes in each cell along the y coordinates, or `NULL`.
1461a4e35b19SJacob Faibussowitsch - lz           - arrays containing the number of nodes in each cell along the z coordinates, or `NULL`.
146247c6ae99SBarry Smith 
146347c6ae99SBarry Smith   Output Parameter:
146447c6ae99SBarry Smith . da - the resulting distributed array object
146547c6ae99SBarry Smith 
1466dce8aebaSBarry Smith   Options Database Keys:
1467dce8aebaSBarry Smith + -dm_view              - Calls `DMView()` at the conclusion of `DMDACreate3d()`
1468e43dc8daSBarry Smith . -da_grid_x <nx>       - number of grid points in x direction
1469e43dc8daSBarry Smith . -da_grid_y <ny>       - number of grid points in y direction
1470e43dc8daSBarry Smith . -da_grid_z <nz>       - number of grid points in z direction
147147c6ae99SBarry Smith . -da_processors_x <MX> - number of processors in x direction
147247c6ae99SBarry Smith . -da_processors_y <MY> - number of processors in y direction
147347c6ae99SBarry Smith . -da_processors_z <MZ> - number of processors in z direction
1474e0f5d30fSBarry Smith . -da_refine_x <rx>     - refinement ratio in x direction
1475e0f5d30fSBarry Smith . -da_refine_y <ry>     - refinement ratio in y direction
1476e0f5d30fSBarry Smith . -da_refine_z <rz>     - refinement ratio in z directio
1477*12b4a537SBarry Smith - -da_refine <n>        - refine the `DMDA` n times before creating it
147847c6ae99SBarry Smith 
147947c6ae99SBarry Smith   Level: beginner
148047c6ae99SBarry Smith 
148147c6ae99SBarry Smith   Notes:
1482a4e35b19SJacob Faibussowitsch   If `lx`, `ly`, or `lz` are non-null, these must be of length as `m`, `n`, `p` and the
1483a4e35b19SJacob Faibussowitsch   corresponding `m`, `n`, or `p` cannot be `PETSC_DECIDE`. Sum of the `lx` entries must be `M`,
1484a4e35b19SJacob Faibussowitsch   sum of the `ly` must `N`, sum of the `lz` must be `P`.
1485a4e35b19SJacob Faibussowitsch 
1486dce8aebaSBarry Smith   The stencil type `DMDA_STENCIL_STAR` with width 1 corresponds to the
1487dce8aebaSBarry Smith   standard 7-pt stencil, while `DMDA_STENCIL_BOX` with width 1 denotes
148847c6ae99SBarry Smith   the standard 27-pt stencil.
148947c6ae99SBarry Smith 
1490dce8aebaSBarry Smith   The array data itself is NOT stored in the `DMDA`, it is stored in `Vec` objects;
1491dce8aebaSBarry Smith   The appropriate vector objects can be obtained with calls to `DMCreateGlobalVector()`
1492dce8aebaSBarry Smith   and `DMCreateLocalVector()` and calls to `VecDuplicate()` if more are needed.
149347c6ae99SBarry Smith 
1494dce8aebaSBarry Smith   You must call `DMSetUp()` after this call before using this `DM`.
1495897f7067SBarry Smith 
1496*12b4a537SBarry Smith   To use the options database to change values in the `DMDA` call `DMSetFromOptions()` after this call
1497dce8aebaSBarry Smith   but before `DMSetUp()`.
1498897f7067SBarry Smith 
1499*12b4a537SBarry Smith .seealso: [](sec_struct), `DM`, `DMDA`, `DMDestroy()`, `DMView()`, `DMDACreate1d()`, `DMDACreate2d()`, `DMGlobalToLocalBegin()`, `DMDAGetRefinementFactor()`,
1500db781477SPatrick Sanan           `DMGlobalToLocalEnd()`, `DMLocalToGlobalBegin()`, `DMLocalToLocalBegin()`, `DMLocalToLocalEnd()`, `DMDASetRefinementFactor()`,
1501db781477SPatrick Sanan           `DMDAGetInfo()`, `DMCreateGlobalVector()`, `DMCreateLocalVector()`, `DMDACreateNaturalVector()`, `DMLoad()`, `DMDAGetOwnershipRanges()`,
1502*12b4a537SBarry Smith           `DMStagCreate3d()`, `DMBoundaryType`
150347c6ae99SBarry Smith @*/
1504d71ae5a4SJacob Faibussowitsch PetscErrorCode DMDACreate3d(MPI_Comm comm, DMBoundaryType bx, DMBoundaryType by, DMBoundaryType bz, DMDAStencilType stencil_type, PetscInt M, 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)
1505d71ae5a4SJacob Faibussowitsch {
150647c6ae99SBarry Smith   PetscFunctionBegin;
15079566063dSJacob Faibussowitsch   PetscCall(DMDACreate(comm, da));
15089566063dSJacob Faibussowitsch   PetscCall(DMSetDimension(*da, 3));
15099566063dSJacob Faibussowitsch   PetscCall(DMDASetSizes(*da, M, N, P));
15109566063dSJacob Faibussowitsch   PetscCall(DMDASetNumProcs(*da, m, n, p));
15119566063dSJacob Faibussowitsch   PetscCall(DMDASetBoundaryType(*da, bx, by, bz));
15129566063dSJacob Faibussowitsch   PetscCall(DMDASetDof(*da, dof));
15139566063dSJacob Faibussowitsch   PetscCall(DMDASetStencilType(*da, stencil_type));
15149566063dSJacob Faibussowitsch   PetscCall(DMDASetStencilWidth(*da, s));
15159566063dSJacob Faibussowitsch   PetscCall(DMDASetOwnershipRanges(*da, lx, ly, lz));
15163ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
151747c6ae99SBarry Smith }
1518