xref: /petsc/src/dm/impls/da/da2.c (revision bcda9346efad4e5ba2d553af84eb238771ba1e25)
1af0996ceSBarry Smith #include <petsc/private/dmdaimpl.h> /*I   "petscdmda.h"   I*/
29804daf3SBarry Smith #include <petscdraw.h>
347c6ae99SBarry Smith 
DMView_DA_2d(DM da,PetscViewer viewer)4d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMView_DA_2d(DM da, PetscViewer viewer)
5d71ae5a4SJacob Faibussowitsch {
647c6ae99SBarry Smith   PetscMPIInt rank;
7*9f196a02SMartin Diehl   PetscBool   isascii, isdraw, isglvis, isbinary;
847c6ae99SBarry Smith   DM_DA      *dd = (DM_DA *)da->data;
9d1e78c4fSBarry Smith #if defined(PETSC_HAVE_MATLAB)
109a42bb27SBarry Smith   PetscBool ismatlab;
119a42bb27SBarry Smith #endif
1247c6ae99SBarry Smith 
1347c6ae99SBarry Smith   PetscFunctionBegin;
149566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)da), &rank));
1547c6ae99SBarry Smith 
16*9f196a02SMartin Diehl   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
179566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw));
189566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERGLVIS, &isglvis));
199566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &isbinary));
20d1e78c4fSBarry Smith #if defined(PETSC_HAVE_MATLAB)
219566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERMATLAB, &ismatlab));
229a42bb27SBarry Smith #endif
23*9f196a02SMartin Diehl   if (isascii) {
2447c6ae99SBarry Smith     PetscViewerFormat format;
2547c6ae99SBarry Smith 
269566063dSJacob Faibussowitsch     PetscCall(PetscViewerGetFormat(viewer, &format));
2776a8abe0SBarry Smith     if (format == PETSC_VIEWER_LOAD_BALANCE) {
281690c2aeSBarry Smith       PetscInt      i, nmax = 0, nmin = PETSC_INT_MAX, navg = 0, *nz, nzlocal;
2976a8abe0SBarry Smith       DMDALocalInfo info;
3076a8abe0SBarry Smith       PetscMPIInt   size;
319566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)da), &size));
329566063dSJacob Faibussowitsch       PetscCall(DMDAGetLocalInfo(da, &info));
3376a8abe0SBarry Smith       nzlocal = info.xm * info.ym;
349566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(size, &nz));
359566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Allgather(&nzlocal, 1, MPIU_INT, nz, 1, MPIU_INT, PetscObjectComm((PetscObject)da)));
36835f2295SStefano Zampini       for (i = 0; i < size; i++) {
3776a8abe0SBarry Smith         nmax = PetscMax(nmax, nz[i]);
3876a8abe0SBarry Smith         nmin = PetscMin(nmin, nz[i]);
3976a8abe0SBarry Smith         navg += nz[i];
4076a8abe0SBarry Smith       }
419566063dSJacob Faibussowitsch       PetscCall(PetscFree(nz));
4276a8abe0SBarry Smith       navg = navg / size;
4363a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  Load Balance - Grid Points: Min %" PetscInt_FMT "  avg %" PetscInt_FMT "  max %" PetscInt_FMT "\n", nmin, navg, nmax));
443ba16761SJacob Faibussowitsch       PetscFunctionReturn(PETSC_SUCCESS);
4576a8abe0SBarry Smith     }
46ce78bad3SBarry Smith     if (format != PETSC_VIEWER_ASCII_GLVIS) {
47aa219208SBarry Smith       DMDALocalInfo info;
489566063dSJacob Faibussowitsch       PetscCall(DMDAGetLocalInfo(da, &info));
499566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPushSynchronized(viewer));
5063a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "Processor [%d] M %" PetscInt_FMT " N %" PetscInt_FMT " m %" PetscInt_FMT " n %" PetscInt_FMT " w %" PetscInt_FMT " s %" PetscInt_FMT "\n", rank, dd->M, dd->N, dd->m, dd->n, dd->w, dd->s));
5163a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "X range of indices: %" PetscInt_FMT " %" PetscInt_FMT ", Y range of indices: %" PetscInt_FMT " %" PetscInt_FMT "\n", info.xs, info.xs + info.xm, info.ys, info.ys + info.ym));
529566063dSJacob Faibussowitsch       PetscCall(PetscViewerFlush(viewer));
539566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPopSynchronized(viewer));
541baa6e33SBarry Smith     } else if (format == PETSC_VIEWER_ASCII_GLVIS) PetscCall(DMView_DA_GLVis(da, viewer));
5547c6ae99SBarry Smith   } else if (isdraw) {
5647c6ae99SBarry Smith     PetscDraw       draw;
5747c6ae99SBarry Smith     double          ymin = -1 * dd->s - 1, ymax = dd->N + dd->s;
5847c6ae99SBarry Smith     double          xmin = -1 * dd->s - 1, xmax = dd->M + dd->s;
5947c6ae99SBarry Smith     double          x, y;
608ea3bf28SBarry Smith     PetscInt        base;
618ea3bf28SBarry Smith     const PetscInt *idx;
6247c6ae99SBarry Smith     char            node[10];
6347c6ae99SBarry Smith     PetscBool       isnull;
6447c6ae99SBarry Smith 
659566063dSJacob Faibussowitsch     PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw));
669566063dSJacob Faibussowitsch     PetscCall(PetscDrawIsNull(draw, &isnull));
673ba16761SJacob Faibussowitsch     if (isnull) PetscFunctionReturn(PETSC_SUCCESS);
6847c6ae99SBarry Smith 
699566063dSJacob Faibussowitsch     PetscCall(PetscDrawCheckResizedWindow(draw));
709566063dSJacob Faibussowitsch     PetscCall(PetscDrawClear(draw));
719566063dSJacob Faibussowitsch     PetscCall(PetscDrawSetCoordinates(draw, xmin, ymin, xmax, ymax));
725b399a63SLisandro Dalcin 
73d0609cedSBarry Smith     PetscDrawCollectiveBegin(draw);
7447c6ae99SBarry Smith     /* first processor draw all node lines */
75dd400576SPatrick Sanan     if (rank == 0) {
769371c9d4SSatish Balay       ymin = 0.0;
779371c9d4SSatish Balay       ymax = dd->N - 1;
7848a46eb9SPierre Jolivet       for (xmin = 0; xmin < dd->M; xmin++) PetscCall(PetscDrawLine(draw, xmin, ymin, xmin, ymax, PETSC_DRAW_BLACK));
799371c9d4SSatish Balay       xmin = 0.0;
809371c9d4SSatish Balay       xmax = dd->M - 1;
8148a46eb9SPierre Jolivet       for (ymin = 0; ymin < dd->N; ymin++) PetscCall(PetscDrawLine(draw, xmin, ymin, xmax, ymin, PETSC_DRAW_BLACK));
8247c6ae99SBarry Smith     }
83d0609cedSBarry Smith     PetscDrawCollectiveEnd(draw);
849566063dSJacob Faibussowitsch     PetscCall(PetscDrawFlush(draw));
859566063dSJacob Faibussowitsch     PetscCall(PetscDrawPause(draw));
8647c6ae99SBarry Smith 
87d0609cedSBarry Smith     PetscDrawCollectiveBegin(draw);
8847c6ae99SBarry Smith     /* draw my box */
899371c9d4SSatish Balay     xmin = dd->xs / dd->w;
909371c9d4SSatish Balay     xmax = (dd->xe - 1) / dd->w;
919371c9d4SSatish Balay     ymin = dd->ys;
929371c9d4SSatish Balay     ymax = dd->ye - 1;
939566063dSJacob Faibussowitsch     PetscCall(PetscDrawLine(draw, xmin, ymin, xmax, ymin, PETSC_DRAW_RED));
949566063dSJacob Faibussowitsch     PetscCall(PetscDrawLine(draw, xmin, ymin, xmin, ymax, PETSC_DRAW_RED));
959566063dSJacob Faibussowitsch     PetscCall(PetscDrawLine(draw, xmin, ymax, xmax, ymax, PETSC_DRAW_RED));
969566063dSJacob Faibussowitsch     PetscCall(PetscDrawLine(draw, xmax, ymin, xmax, ymax, PETSC_DRAW_RED));
9747c6ae99SBarry Smith     /* put in numbers */
9847c6ae99SBarry Smith     base = (dd->base) / dd->w;
9947c6ae99SBarry Smith     for (y = ymin; y <= ymax; y++) {
10047c6ae99SBarry Smith       for (x = xmin; x <= xmax; x++) {
101835f2295SStefano Zampini         PetscCall(PetscSNPrintf(node, sizeof(node), "%" PetscInt_FMT, base++));
1029566063dSJacob Faibussowitsch         PetscCall(PetscDrawString(draw, x, y, PETSC_DRAW_BLACK, node));
10347c6ae99SBarry Smith       }
10447c6ae99SBarry Smith     }
105d0609cedSBarry Smith     PetscDrawCollectiveEnd(draw);
1069566063dSJacob Faibussowitsch     PetscCall(PetscDrawFlush(draw));
1079566063dSJacob Faibussowitsch     PetscCall(PetscDrawPause(draw));
10847c6ae99SBarry Smith 
109d0609cedSBarry Smith     PetscDrawCollectiveBegin(draw);
1105b399a63SLisandro Dalcin     /* overlay ghost numbers, useful for error checking */
1119566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingGetBlockIndices(da->ltogmap, &idx));
1129371c9d4SSatish Balay     base = 0;
1139371c9d4SSatish Balay     xmin = dd->Xs;
1149371c9d4SSatish Balay     xmax = dd->Xe;
1159371c9d4SSatish Balay     ymin = dd->Ys;
1169371c9d4SSatish Balay     ymax = dd->Ye;
11747c6ae99SBarry Smith     for (y = ymin; y < ymax; y++) {
11847c6ae99SBarry Smith       for (x = xmin; x < xmax; x++) {
11947c6ae99SBarry Smith         if ((base % dd->w) == 0) {
1209566063dSJacob Faibussowitsch           PetscCall(PetscSNPrintf(node, sizeof(node), "%d", (int)(idx[base / dd->w])));
1219566063dSJacob Faibussowitsch           PetscCall(PetscDrawString(draw, x / dd->w, y, PETSC_DRAW_BLUE, node));
12247c6ae99SBarry Smith         }
12347c6ae99SBarry Smith         base++;
12447c6ae99SBarry Smith       }
12547c6ae99SBarry Smith     }
1269566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingRestoreBlockIndices(da->ltogmap, &idx));
127d0609cedSBarry Smith     PetscDrawCollectiveEnd(draw);
1289566063dSJacob Faibussowitsch     PetscCall(PetscDrawFlush(draw));
1299566063dSJacob Faibussowitsch     PetscCall(PetscDrawPause(draw));
1309566063dSJacob Faibussowitsch     PetscCall(PetscDrawSave(draw));
131c9493c35SStefano Zampini   } else if (isglvis) {
1329566063dSJacob Faibussowitsch     PetscCall(DMView_DA_GLVis(da, viewer));
1339a42bb27SBarry Smith   } else if (isbinary) {
1349566063dSJacob Faibussowitsch     PetscCall(DMView_DA_Binary(da, viewer));
135d1e78c4fSBarry Smith #if defined(PETSC_HAVE_MATLAB)
1369a42bb27SBarry Smith   } else if (ismatlab) {
1379566063dSJacob Faibussowitsch     PetscCall(DMView_DA_Matlab(da, viewer));
1389a42bb27SBarry Smith #endif
13911aeaf0aSBarry Smith   }
1403ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
14147c6ae99SBarry Smith }
14247c6ae99SBarry Smith 
14347c6ae99SBarry Smith #if defined(new)
14447c6ae99SBarry Smith /*
14501c1178eSBarry Smith   DMDAGetDiagonal_MFFD - Gets the diagonal for a matrix-free matrix where local
146aa219208SBarry Smith     function lives on a DMDA
14747c6ae99SBarry Smith 
14847c6ae99SBarry Smith         y ~= (F(u + ha) - F(u))/h,
14947c6ae99SBarry Smith   where F = nonlinear function, as set by SNESSetFunction()
15047c6ae99SBarry Smith         u = current iterate
15147c6ae99SBarry Smith         h = difference interval
15247c6ae99SBarry Smith */
DMDAGetDiagonal_MFFD(DM da,Vec U,Vec a)153d71ae5a4SJacob Faibussowitsch PetscErrorCode DMDAGetDiagonal_MFFD(DM da, Vec U, Vec a)
154d71ae5a4SJacob Faibussowitsch {
15547c6ae99SBarry Smith   PetscScalar   h, *aa, *ww, v;
15647c6ae99SBarry Smith   PetscReal     epsilon = PETSC_SQRT_MACHINE_EPSILON, umin = 100.0 * PETSC_SQRT_MACHINE_EPSILON;
15747c6ae99SBarry Smith   PetscInt      gI, nI;
15847c6ae99SBarry Smith   MatStencil    stencil;
159aa219208SBarry Smith   DMDALocalInfo info;
16047c6ae99SBarry Smith 
16147c6ae99SBarry Smith   PetscFunctionBegin;
1629566063dSJacob Faibussowitsch   PetscCall((*ctx->func)(0, U, a, ctx->funcctx));
1639566063dSJacob Faibussowitsch   PetscCall((*ctx->funcisetbase)(U, ctx->funcctx));
16447c6ae99SBarry Smith 
1659566063dSJacob Faibussowitsch   PetscCall(VecGetArray(U, &ww));
1669566063dSJacob Faibussowitsch   PetscCall(VecGetArray(a, &aa));
16747c6ae99SBarry Smith 
16847c6ae99SBarry Smith   nI = 0;
16947c6ae99SBarry Smith   h  = ww[gI];
17047c6ae99SBarry Smith   if (h == 0.0) h = 1.0;
17147c6ae99SBarry Smith   if (PetscAbsScalar(h) < umin && PetscRealPart(h) >= 0.0) h = umin;
17247c6ae99SBarry Smith   else if (PetscRealPart(h) < 0.0 && PetscAbsScalar(h) < umin) h = -umin;
17347c6ae99SBarry Smith   h *= epsilon;
17447c6ae99SBarry Smith 
17547c6ae99SBarry Smith   ww[gI] += h;
1769566063dSJacob Faibussowitsch   PetscCall((*ctx->funci)(i, w, &v, ctx->funcctx));
17747c6ae99SBarry Smith   aa[nI] = (v - aa[nI]) / h;
17847c6ae99SBarry Smith   ww[gI] -= h;
17947c6ae99SBarry Smith   nI++;
1808865f1eaSKarl Rupp 
1819566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(U, &ww));
1829566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(a, &aa));
1833ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
18447c6ae99SBarry Smith }
18547c6ae99SBarry Smith #endif
18647c6ae99SBarry Smith 
DMSetUp_DA_2D(DM da)187d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetUp_DA_2D(DM da)
188d71ae5a4SJacob Faibussowitsch {
18947c6ae99SBarry Smith   DM_DA          *dd = (DM_DA *)da->data;
19047c6ae99SBarry Smith   const PetscInt  M  = dd->M;
19147c6ae99SBarry Smith   const PetscInt  N  = dd->N;
1926497c311SBarry Smith   PetscMPIInt     m, n;
19347c6ae99SBarry Smith   const PetscInt  dof          = dd->w;
19447c6ae99SBarry Smith   const PetscInt  s            = dd->s;
195bff4a2f0SMatthew G. Knepley   DMBoundaryType  bx           = dd->bx;
196bff4a2f0SMatthew G. Knepley   DMBoundaryType  by           = dd->by;
19719fd82e9SBarry Smith   DMDAStencilType stencil_type = dd->stencil_type;
19847c6ae99SBarry Smith   PetscInt       *lx           = dd->lx;
19947c6ae99SBarry Smith   PetscInt       *ly           = dd->ly;
20047c6ae99SBarry Smith   MPI_Comm        comm;
2016497c311SBarry Smith   PetscMPIInt     rank, size, n0, n1, n2, n3, n5, n6, n7, n8;
202bd1fc5aeSBarry Smith   PetscInt        xs, xe, ys, ye, x, y, Xs, Xe, Ys, Ye, IXs, IXe, IYs, IYe;
2036497c311SBarry Smith   PetscInt        up, down, left, right, i, *idx, nn;
204db87c5ecSEthan Coon   PetscInt        xbase, *bases, *ldims, j, x_t, y_t, s_t, base, count;
20547c6ae99SBarry Smith   PetscInt        s_x, s_y; /* s proportionalized to w */
2066497c311SBarry Smith   PetscMPIInt     sn0 = 0, sn2 = 0, sn6 = 0, sn8 = 0;
20747c6ae99SBarry Smith   Vec             local, global;
208bd1fc5aeSBarry Smith   VecScatter      gtol;
20945b6f7e9SBarry Smith   IS              to, from;
21047c6ae99SBarry Smith 
21147c6ae99SBarry Smith   PetscFunctionBegin;
2127a8be351SBarry Smith   PetscCheck(stencil_type != DMDA_STENCIL_BOX || (bx != DM_BOUNDARY_MIRROR && by != DM_BOUNDARY_MIRROR), PetscObjectComm((PetscObject)da), PETSC_ERR_SUP, "Mirror boundary and box stencil");
2139566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)da, &comm));
2143855c12bSBarry Smith #if !defined(PETSC_USE_64BIT_INDICES)
2157de69702SBarry Smith   PetscCheck(((PetscInt64)M) * ((PetscInt64)N) * ((PetscInt64)dof) <= (PetscInt64)PETSC_MPI_INT_MAX, comm, PETSC_ERR_INT_OVERFLOW, "Mesh of %" PetscInt_FMT " by %" PetscInt_FMT " by %" PetscInt_FMT " (dof) is too large for 32-bit indices", M, N, dof);
2163855c12bSBarry Smith #endif
2176497c311SBarry Smith   PetscCall(PetscMPIIntCast(dd->m, &m));
2186497c311SBarry Smith   PetscCall(PetscMPIIntCast(dd->n, &n));
21947c6ae99SBarry Smith 
2209566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(comm, &size));
2219566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
22247c6ae99SBarry Smith 
2237d310018SBarry Smith   dd->p = 1;
22447c6ae99SBarry Smith   if (m != PETSC_DECIDE) {
2256497c311SBarry Smith     PetscCheck(m >= 1, comm, PETSC_ERR_ARG_OUTOFRANGE, "Non-positive number of processors in X direction: %d", m);
2266497c311SBarry Smith     PetscCheck(m <= size, comm, PETSC_ERR_ARG_OUTOFRANGE, "Too many processors in X direction: %d %d", m, size);
22747c6ae99SBarry Smith   }
22847c6ae99SBarry Smith   if (n != PETSC_DECIDE) {
2296497c311SBarry Smith     PetscCheck(n >= 1, comm, PETSC_ERR_ARG_OUTOFRANGE, "Non-positive number of processors in Y direction: %d", n);
2306497c311SBarry Smith     PetscCheck(n <= size, comm, PETSC_ERR_ARG_OUTOFRANGE, "Too many processors in Y direction: %d %d", n, size);
23147c6ae99SBarry Smith   }
23247c6ae99SBarry Smith 
23347c6ae99SBarry Smith   if (m == PETSC_DECIDE || n == PETSC_DECIDE) {
23447c6ae99SBarry Smith     if (n != PETSC_DECIDE) {
23547c6ae99SBarry Smith       m = size / n;
23647c6ae99SBarry Smith     } else if (m != PETSC_DECIDE) {
23747c6ae99SBarry Smith       n = size / m;
23847c6ae99SBarry Smith     } else {
23947c6ae99SBarry Smith       /* try for squarish distribution */
2406497c311SBarry Smith       m = (PetscMPIInt)(0.5 + PetscSqrtReal(((PetscReal)M) * ((PetscReal)size) / ((PetscReal)N)));
24147c6ae99SBarry Smith       if (!m) m = 1;
24247c6ae99SBarry Smith       while (m > 0) {
24347c6ae99SBarry Smith         n = size / m;
24447c6ae99SBarry Smith         if (m * n == size) break;
24547c6ae99SBarry Smith         m--;
24647c6ae99SBarry Smith       }
2479371c9d4SSatish Balay       if (M > N && m < n) {
2486497c311SBarry Smith         PetscMPIInt _m = m;
2499371c9d4SSatish Balay         m              = n;
2509371c9d4SSatish Balay         n              = _m;
2519371c9d4SSatish Balay       }
25247c6ae99SBarry Smith     }
2537a8be351SBarry Smith     PetscCheck(m * n == size, comm, PETSC_ERR_PLIB, "Unable to create partition, check the size of the communicator and input m and n ");
2547a8be351SBarry Smith   } else PetscCheck(m * n == size, comm, PETSC_ERR_ARG_OUTOFRANGE, "Given Bad partition");
25547c6ae99SBarry Smith 
2566497c311SBarry Smith   PetscCheck(M >= m, comm, PETSC_ERR_ARG_OUTOFRANGE, "Partition in x direction is too fine! %" PetscInt_FMT " %d", M, m);
2576497c311SBarry Smith   PetscCheck(N >= n, comm, PETSC_ERR_ARG_OUTOFRANGE, "Partition in y direction is too fine! %" PetscInt_FMT " %d", N, n);
25847c6ae99SBarry Smith 
25947c6ae99SBarry Smith   /*
26047c6ae99SBarry Smith      Determine locally owned region
26147c6ae99SBarry Smith      xs is the first local node number, x is the number of local nodes
26247c6ae99SBarry Smith   */
26347c6ae99SBarry Smith   if (!lx) {
2649566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(m, &dd->lx));
26547c6ae99SBarry Smith     lx = dd->lx;
266ad540459SPierre Jolivet     for (i = 0; i < m; i++) lx[i] = M / m + ((M % m) > i);
26747c6ae99SBarry Smith   }
26847c6ae99SBarry Smith   x  = lx[rank % m];
26947c6ae99SBarry Smith   xs = 0;
270ad540459SPierre Jolivet   for (i = 0; i < (rank % m); i++) xs += lx[i];
27176bd3646SJed Brown   if (PetscDefined(USE_DEBUG)) {
27247c6ae99SBarry Smith     left = xs;
273ad540459SPierre Jolivet     for (i = (rank % m); i < m; i++) left += lx[i];
27463a3b9bcSJacob Faibussowitsch     PetscCheck(left == M, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Sum of lx across processors not equal to M: %" PetscInt_FMT " %" PetscInt_FMT, left, M);
27576bd3646SJed Brown   }
27647c6ae99SBarry Smith 
27747c6ae99SBarry Smith   /*
27847c6ae99SBarry Smith      Determine locally owned region
27947c6ae99SBarry Smith      ys is the first local node number, y is the number of local nodes
28047c6ae99SBarry Smith   */
28147c6ae99SBarry Smith   if (!ly) {
2829566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(n, &dd->ly));
28347c6ae99SBarry Smith     ly = dd->ly;
284ad540459SPierre Jolivet     for (i = 0; i < n; i++) ly[i] = N / n + ((N % n) > i);
28547c6ae99SBarry Smith   }
28647c6ae99SBarry Smith   y  = ly[rank / m];
28747c6ae99SBarry Smith   ys = 0;
288ad540459SPierre Jolivet   for (i = 0; i < (rank / m); i++) ys += ly[i];
28976bd3646SJed Brown   if (PetscDefined(USE_DEBUG)) {
29047c6ae99SBarry Smith     left = ys;
291ad540459SPierre Jolivet     for (i = (rank / m); i < n; i++) left += ly[i];
29263a3b9bcSJacob Faibussowitsch     PetscCheck(left == N, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Sum of ly across processors not equal to N: %" PetscInt_FMT " %" PetscInt_FMT, left, N);
29376bd3646SJed Brown   }
29447c6ae99SBarry Smith 
295bcea557cSEthan Coon   /*
296bcea557cSEthan Coon    check if the scatter requires more than one process neighbor or wraps around
297bcea557cSEthan Coon    the domain more than once
298bcea557cSEthan Coon   */
29963a3b9bcSJacob Faibussowitsch   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);
30063a3b9bcSJacob Faibussowitsch   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);
3014ad8454bSPierre Jolivet   PetscCheck((x > s) || (bx != DM_BOUNDARY_MIRROR), PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Local x-width of domain x %" PetscInt_FMT " is smaller than stencil width s %" PetscInt_FMT " with mirror", x, s);
3024ad8454bSPierre Jolivet   PetscCheck((y > s) || (by != DM_BOUNDARY_MIRROR), PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Local y-width of domain y %" PetscInt_FMT " is smaller than stencil width s %" PetscInt_FMT " with mirror", y, s);
30347c6ae99SBarry Smith   xe = xs + x;
30447c6ae99SBarry Smith   ye = ys + y;
30547c6ae99SBarry Smith 
306ce00eea3SSatish Balay   /* determine ghost region (Xs) and region scattered into (IXs)  */
307d9c9ebe5SPeter Brune   if (xs - s > 0) {
3089371c9d4SSatish Balay     Xs  = xs - s;
3099371c9d4SSatish Balay     IXs = xs - s;
31088661749SPeter Brune   } else {
31188661749SPeter Brune     if (bx) {
31288661749SPeter Brune       Xs = xs - s;
31388661749SPeter Brune     } else {
31488661749SPeter Brune       Xs = 0;
31588661749SPeter Brune     }
31688661749SPeter Brune     IXs = 0;
31788661749SPeter Brune   }
318d9c9ebe5SPeter Brune   if (xe + s <= M) {
3199371c9d4SSatish Balay     Xe  = xe + s;
3209371c9d4SSatish Balay     IXe = xe + s;
32188661749SPeter Brune   } else {
32288661749SPeter Brune     if (bx) {
3239371c9d4SSatish Balay       Xs = xs - s;
3249371c9d4SSatish Balay       Xe = xe + s;
32588661749SPeter Brune     } else {
32688661749SPeter Brune       Xe = M;
32788661749SPeter Brune     }
32888661749SPeter Brune     IXe = M;
32988661749SPeter Brune   }
33047c6ae99SBarry Smith 
331bff4a2f0SMatthew G. Knepley   if (bx == DM_BOUNDARY_PERIODIC || bx == DM_BOUNDARY_MIRROR) {
332d9c9ebe5SPeter Brune     IXs = xs - s;
333d9c9ebe5SPeter Brune     IXe = xe + s;
334d9c9ebe5SPeter Brune     Xs  = xs - s;
335d9c9ebe5SPeter Brune     Xe  = xe + s;
33688661749SPeter Brune   }
33747c6ae99SBarry Smith 
338d9c9ebe5SPeter Brune   if (ys - s > 0) {
3399371c9d4SSatish Balay     Ys  = ys - s;
3409371c9d4SSatish Balay     IYs = ys - s;
34188661749SPeter Brune   } else {
34288661749SPeter Brune     if (by) {
34388661749SPeter Brune       Ys = ys - s;
34488661749SPeter Brune     } else {
34588661749SPeter Brune       Ys = 0;
34688661749SPeter Brune     }
34788661749SPeter Brune     IYs = 0;
34888661749SPeter Brune   }
349d9c9ebe5SPeter Brune   if (ye + s <= N) {
3509371c9d4SSatish Balay     Ye  = ye + s;
3519371c9d4SSatish Balay     IYe = ye + s;
35288661749SPeter Brune   } else {
35388661749SPeter Brune     if (by) {
35488661749SPeter Brune       Ye = ye + s;
35588661749SPeter Brune     } else {
35688661749SPeter Brune       Ye = N;
35788661749SPeter Brune     }
35888661749SPeter Brune     IYe = N;
35988661749SPeter Brune   }
36088661749SPeter Brune 
361bff4a2f0SMatthew G. Knepley   if (by == DM_BOUNDARY_PERIODIC || by == DM_BOUNDARY_MIRROR) {
362d9c9ebe5SPeter Brune     IYs = ys - s;
363d9c9ebe5SPeter Brune     IYe = ye + s;
364d9c9ebe5SPeter Brune     Ys  = ys - s;
365d9c9ebe5SPeter Brune     Ye  = ye + s;
36688661749SPeter Brune   }
36788661749SPeter Brune 
36888661749SPeter Brune   /* stencil length in each direction */
369d9c9ebe5SPeter Brune   s_x = s;
370d9c9ebe5SPeter Brune   s_y = s;
37147c6ae99SBarry Smith 
37247c6ae99SBarry Smith   /* determine starting point of each processor */
37347c6ae99SBarry Smith   nn = x * y;
3749566063dSJacob Faibussowitsch   PetscCall(PetscMalloc2(size + 1, &bases, size, &ldims));
3759566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Allgather(&nn, 1, MPIU_INT, ldims, 1, MPIU_INT, comm));
37647c6ae99SBarry Smith   bases[0] = 0;
377ad540459SPierre Jolivet   for (i = 1; i <= size; i++) bases[i] = ldims[i - 1];
378ad540459SPierre Jolivet   for (i = 1; i <= size; i++) bases[i] += bases[i - 1];
379ce00eea3SSatish Balay   base = bases[rank] * dof;
38047c6ae99SBarry Smith 
38147c6ae99SBarry Smith   /* allocate the base parallel and sequential vectors */
382ce00eea3SSatish Balay   dd->Nlocal = x * y * dof;
3839566063dSJacob Faibussowitsch   PetscCall(VecCreateMPIWithArray(comm, dof, dd->Nlocal, PETSC_DECIDE, NULL, &global));
384ce00eea3SSatish Balay   dd->nlocal = (Xe - Xs) * (Ye - Ys) * dof;
3859566063dSJacob Faibussowitsch   PetscCall(VecCreateSeqWithArray(PETSC_COMM_SELF, dof, dd->nlocal, NULL, &local));
38647c6ae99SBarry Smith 
3874104a7a0SPatrick Sanan   /* generate global to local vector scatter and local to global mapping*/
38847c6ae99SBarry Smith 
389ce00eea3SSatish Balay   /* global to local must include ghost points within the domain,
390ce00eea3SSatish Balay      but not ghost points outside the domain that aren't periodic */
3919566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1((IXe - IXs) * (IYe - IYs), &idx));
392d9c9ebe5SPeter Brune   if (stencil_type == DMDA_STENCIL_BOX) {
3939371c9d4SSatish Balay     left  = IXs - Xs;
3949371c9d4SSatish Balay     right = left + (IXe - IXs);
3959371c9d4SSatish Balay     down  = IYs - Ys;
3969371c9d4SSatish Balay     up    = down + (IYe - IYs);
397ce00eea3SSatish Balay     count = 0;
398ce00eea3SSatish Balay     for (i = down; i < up; i++) {
399ad540459SPierre Jolivet       for (j = left; j < right; j++) idx[count++] = j + i * (Xe - Xs);
400ce00eea3SSatish Balay     }
4019566063dSJacob Faibussowitsch     PetscCall(ISCreateBlock(comm, dof, count, idx, PETSC_OWN_POINTER, &to));
402ce00eea3SSatish Balay 
40347c6ae99SBarry Smith   } else {
40447c6ae99SBarry Smith     /* must drop into cross shape region */
40547c6ae99SBarry Smith     /*       ---------|
40647c6ae99SBarry Smith             |  top    |
407ce00eea3SSatish Balay          |---         ---| up
40847c6ae99SBarry Smith          |   middle      |
40947c6ae99SBarry Smith          |               |
410ce00eea3SSatish Balay          ----         ---- down
41147c6ae99SBarry Smith             | bottom  |
41247c6ae99SBarry Smith             -----------
41347c6ae99SBarry Smith          Xs xs        xe Xe */
4149371c9d4SSatish Balay     left  = xs - Xs;
4159371c9d4SSatish Balay     right = left + x;
4169371c9d4SSatish Balay     down  = ys - Ys;
4179371c9d4SSatish Balay     up    = down + y;
41847c6ae99SBarry Smith     count = 0;
419ce00eea3SSatish Balay     /* bottom */
420ce00eea3SSatish Balay     for (i = (IYs - Ys); i < down; i++) {
421ad540459SPierre Jolivet       for (j = left; j < right; j++) idx[count++] = j + i * (Xe - Xs);
42247c6ae99SBarry Smith     }
42347c6ae99SBarry Smith     /* middle */
42447c6ae99SBarry Smith     for (i = down; i < up; i++) {
425ad540459SPierre Jolivet       for (j = (IXs - Xs); j < (IXe - Xs); j++) idx[count++] = j + i * (Xe - Xs);
42647c6ae99SBarry Smith     }
42747c6ae99SBarry Smith     /* top */
428ce00eea3SSatish Balay     for (i = up; i < up + IYe - ye; i++) {
429ad540459SPierre Jolivet       for (j = left; j < right; j++) idx[count++] = j + i * (Xe - Xs);
43047c6ae99SBarry Smith     }
4319566063dSJacob Faibussowitsch     PetscCall(ISCreateBlock(comm, dof, count, idx, PETSC_OWN_POINTER, &to));
43247c6ae99SBarry Smith   }
43347c6ae99SBarry Smith 
43447c6ae99SBarry Smith   /* determine who lies on each side of us stored in    n6 n7 n8
43547c6ae99SBarry Smith                                                         n3    n5
43647c6ae99SBarry Smith                                                         n0 n1 n2
43747c6ae99SBarry Smith   */
43847c6ae99SBarry Smith 
43947c6ae99SBarry Smith   /* Assume the Non-Periodic Case */
44047c6ae99SBarry Smith   n1 = rank - m;
44147c6ae99SBarry Smith   if (rank % m) {
44247c6ae99SBarry Smith     n0 = n1 - 1;
44347c6ae99SBarry Smith   } else {
44447c6ae99SBarry Smith     n0 = -1;
44547c6ae99SBarry Smith   }
44647c6ae99SBarry Smith   if ((rank + 1) % m) {
44747c6ae99SBarry Smith     n2 = n1 + 1;
44847c6ae99SBarry Smith     n5 = rank + 1;
4499371c9d4SSatish Balay     n8 = rank + m + 1;
4509371c9d4SSatish Balay     if (n8 >= m * n) n8 = -1;
45147c6ae99SBarry Smith   } else {
4529371c9d4SSatish Balay     n2 = -1;
4539371c9d4SSatish Balay     n5 = -1;
4549371c9d4SSatish Balay     n8 = -1;
45547c6ae99SBarry Smith   }
45647c6ae99SBarry Smith   if (rank % m) {
45747c6ae99SBarry Smith     n3 = rank - 1;
4589371c9d4SSatish Balay     n6 = n3 + m;
4599371c9d4SSatish Balay     if (n6 >= m * n) n6 = -1;
46047c6ae99SBarry Smith   } else {
4619371c9d4SSatish Balay     n3 = -1;
4629371c9d4SSatish Balay     n6 = -1;
46347c6ae99SBarry Smith   }
4649371c9d4SSatish Balay   n7 = rank + m;
4659371c9d4SSatish Balay   if (n7 >= m * n) n7 = -1;
46647c6ae99SBarry Smith 
467bff4a2f0SMatthew G. Knepley   if (bx == DM_BOUNDARY_PERIODIC && by == DM_BOUNDARY_PERIODIC) {
46847c6ae99SBarry Smith     /* Modify for Periodic Cases */
46947c6ae99SBarry Smith     /* Handle all four corners */
47047c6ae99SBarry Smith     if ((n6 < 0) && (n7 < 0) && (n3 < 0)) n6 = m - 1;
47147c6ae99SBarry Smith     if ((n8 < 0) && (n7 < 0) && (n5 < 0)) n8 = 0;
47247c6ae99SBarry Smith     if ((n2 < 0) && (n5 < 0) && (n1 < 0)) n2 = size - m;
47347c6ae99SBarry Smith     if ((n0 < 0) && (n3 < 0) && (n1 < 0)) n0 = size - 1;
47447c6ae99SBarry Smith 
47547c6ae99SBarry Smith     /* Handle Top and Bottom Sides */
47647c6ae99SBarry Smith     if (n1 < 0) n1 = rank + m * (n - 1);
47747c6ae99SBarry Smith     if (n7 < 0) n7 = rank - m * (n - 1);
47847c6ae99SBarry Smith     if ((n3 >= 0) && (n0 < 0)) n0 = size - m + rank - 1;
47947c6ae99SBarry Smith     if ((n3 >= 0) && (n6 < 0)) n6 = (rank % m) - 1;
48047c6ae99SBarry Smith     if ((n5 >= 0) && (n2 < 0)) n2 = size - m + rank + 1;
48147c6ae99SBarry Smith     if ((n5 >= 0) && (n8 < 0)) n8 = (rank % m) + 1;
48247c6ae99SBarry Smith 
48347c6ae99SBarry Smith     /* Handle Left and Right Sides */
48447c6ae99SBarry Smith     if (n3 < 0) n3 = rank + (m - 1);
48547c6ae99SBarry Smith     if (n5 < 0) n5 = rank - (m - 1);
48647c6ae99SBarry Smith     if ((n1 >= 0) && (n0 < 0)) n0 = rank - 1;
48747c6ae99SBarry Smith     if ((n1 >= 0) && (n2 < 0)) n2 = rank - 2 * m + 1;
48847c6ae99SBarry Smith     if ((n7 >= 0) && (n6 < 0)) n6 = rank + 2 * m - 1;
48947c6ae99SBarry Smith     if ((n7 >= 0) && (n8 < 0)) n8 = rank + 1;
490bff4a2f0SMatthew G. Knepley   } else if (by == DM_BOUNDARY_PERIODIC) { /* Handle Top and Bottom Sides */
491ce00eea3SSatish Balay     if (n1 < 0) n1 = rank + m * (n - 1);
492ce00eea3SSatish Balay     if (n7 < 0) n7 = rank - m * (n - 1);
493ce00eea3SSatish Balay     if ((n3 >= 0) && (n0 < 0)) n0 = size - m + rank - 1;
494ce00eea3SSatish Balay     if ((n3 >= 0) && (n6 < 0)) n6 = (rank % m) - 1;
495ce00eea3SSatish Balay     if ((n5 >= 0) && (n2 < 0)) n2 = size - m + rank + 1;
496ce00eea3SSatish Balay     if ((n5 >= 0) && (n8 < 0)) n8 = (rank % m) + 1;
497bff4a2f0SMatthew G. Knepley   } else if (bx == DM_BOUNDARY_PERIODIC) { /* Handle Left and Right Sides */
498ce00eea3SSatish Balay     if (n3 < 0) n3 = rank + (m - 1);
499ce00eea3SSatish Balay     if (n5 < 0) n5 = rank - (m - 1);
500ce00eea3SSatish Balay     if ((n1 >= 0) && (n0 < 0)) n0 = rank - 1;
501ce00eea3SSatish Balay     if ((n1 >= 0) && (n2 < 0)) n2 = rank - 2 * m + 1;
502ce00eea3SSatish Balay     if ((n7 >= 0) && (n6 < 0)) n6 = rank + 2 * m - 1;
503ce00eea3SSatish Balay     if ((n7 >= 0) && (n8 < 0)) n8 = rank + 1;
50447c6ae99SBarry Smith   }
505ce00eea3SSatish Balay 
5069566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(9, &dd->neighbors));
5078865f1eaSKarl Rupp 
50847c6ae99SBarry Smith   dd->neighbors[0] = n0;
50947c6ae99SBarry Smith   dd->neighbors[1] = n1;
51047c6ae99SBarry Smith   dd->neighbors[2] = n2;
51147c6ae99SBarry Smith   dd->neighbors[3] = n3;
51247c6ae99SBarry Smith   dd->neighbors[4] = rank;
51347c6ae99SBarry Smith   dd->neighbors[5] = n5;
51447c6ae99SBarry Smith   dd->neighbors[6] = n6;
51547c6ae99SBarry Smith   dd->neighbors[7] = n7;
51647c6ae99SBarry Smith   dd->neighbors[8] = n8;
51747c6ae99SBarry Smith 
518d9c9ebe5SPeter Brune   if (stencil_type == DMDA_STENCIL_STAR) {
51947c6ae99SBarry Smith     /* save corner processor numbers */
5209371c9d4SSatish Balay     sn0 = n0;
5219371c9d4SSatish Balay     sn2 = n2;
5229371c9d4SSatish Balay     sn6 = n6;
5239371c9d4SSatish Balay     sn8 = n8;
52447c6ae99SBarry Smith     n0 = n2 = n6 = n8 = -1;
52547c6ae99SBarry Smith   }
52647c6ae99SBarry Smith 
5279566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1((Xe - Xs) * (Ye - Ys), &idx));
52847c6ae99SBarry Smith 
529ce00eea3SSatish Balay   nn    = 0;
53047c6ae99SBarry Smith   xbase = bases[rank];
53147c6ae99SBarry Smith   for (i = 1; i <= s_y; i++) {
53247c6ae99SBarry Smith     if (n0 >= 0) { /* left below */
533ce00eea3SSatish Balay       x_t = lx[n0 % m];
5344ad8454bSPierre Jolivet       y_t = ly[n0 / m];
53547c6ae99SBarry Smith       s_t = bases[n0] + x_t * y_t - (s_y - i) * x_t - s_x;
5368865f1eaSKarl Rupp       for (j = 0; j < s_x; j++) idx[nn++] = s_t++;
53747c6ae99SBarry Smith     }
538ac119b13SBarry Smith 
53947c6ae99SBarry Smith     if (n1 >= 0) { /* directly below */
54047c6ae99SBarry Smith       x_t = x;
5414ad8454bSPierre Jolivet       y_t = ly[n1 / m];
54247c6ae99SBarry Smith       s_t = bases[n1] + x_t * y_t - (s_y + 1 - i) * x_t;
5438865f1eaSKarl Rupp       for (j = 0; j < x_t; j++) idx[nn++] = s_t++;
544bff4a2f0SMatthew G. Knepley     } else if (by == DM_BOUNDARY_MIRROR) {
5458865f1eaSKarl Rupp       for (j = 0; j < x; j++) idx[nn++] = bases[rank] + x * (s_y - i + 1) + j;
54647c6ae99SBarry Smith     }
547ac119b13SBarry Smith 
54847c6ae99SBarry Smith     if (n2 >= 0) { /* right below */
549ce00eea3SSatish Balay       x_t = lx[n2 % m];
5504ad8454bSPierre Jolivet       y_t = ly[n2 / m];
55147c6ae99SBarry Smith       s_t = bases[n2] + x_t * y_t - (s_y + 1 - i) * x_t;
5528865f1eaSKarl Rupp       for (j = 0; j < s_x; j++) idx[nn++] = s_t++;
55347c6ae99SBarry Smith     }
55447c6ae99SBarry Smith   }
55547c6ae99SBarry Smith 
55647c6ae99SBarry Smith   for (i = 0; i < y; i++) {
55747c6ae99SBarry Smith     if (n3 >= 0) { /* directly left */
558ce00eea3SSatish Balay       x_t = lx[n3 % m];
55947c6ae99SBarry Smith       /* y_t = y; */
56047c6ae99SBarry Smith       s_t = bases[n3] + (i + 1) * x_t - s_x;
5618865f1eaSKarl Rupp       for (j = 0; j < s_x; j++) idx[nn++] = s_t++;
562bff4a2f0SMatthew G. Knepley     } else if (bx == DM_BOUNDARY_MIRROR) {
5638865f1eaSKarl Rupp       for (j = 0; j < s_x; j++) idx[nn++] = bases[rank] + x * i + s_x - j;
56447c6ae99SBarry Smith     }
56547c6ae99SBarry Smith 
5668865f1eaSKarl Rupp     for (j = 0; j < x; j++) idx[nn++] = xbase++; /* interior */
56747c6ae99SBarry Smith 
56847c6ae99SBarry Smith     if (n5 >= 0) { /* directly right */
569ce00eea3SSatish Balay       x_t = lx[n5 % m];
57047c6ae99SBarry Smith       /* y_t = y; */
57147c6ae99SBarry Smith       s_t = bases[n5] + (i)*x_t;
5728865f1eaSKarl Rupp       for (j = 0; j < s_x; j++) idx[nn++] = s_t++;
573bff4a2f0SMatthew G. Knepley     } else if (bx == DM_BOUNDARY_MIRROR) {
5748865f1eaSKarl Rupp       for (j = 0; j < s_x; j++) idx[nn++] = bases[rank] + x * (i + 1) - 2 - j;
57547c6ae99SBarry Smith     }
57647c6ae99SBarry Smith   }
57747c6ae99SBarry Smith 
57847c6ae99SBarry Smith   for (i = 1; i <= s_y; i++) {
57947c6ae99SBarry Smith     if (n6 >= 0) { /* left above */
580ce00eea3SSatish Balay       x_t = lx[n6 % m];
5814ad8454bSPierre Jolivet       /* y_t = ly[n6 / m]; */
58247c6ae99SBarry Smith       s_t = bases[n6] + (i)*x_t - s_x;
5838865f1eaSKarl Rupp       for (j = 0; j < s_x; j++) idx[nn++] = s_t++;
58447c6ae99SBarry Smith     }
585ac119b13SBarry Smith 
58647c6ae99SBarry Smith     if (n7 >= 0) { /* directly above */
58747c6ae99SBarry Smith       x_t = x;
5884ad8454bSPierre Jolivet       /* y_t = ly[n7 / m]; */
58947c6ae99SBarry Smith       s_t = bases[n7] + (i - 1) * x_t;
5908865f1eaSKarl Rupp       for (j = 0; j < x_t; j++) idx[nn++] = s_t++;
591bff4a2f0SMatthew G. Knepley     } else if (by == DM_BOUNDARY_MIRROR) {
5928865f1eaSKarl Rupp       for (j = 0; j < x; j++) idx[nn++] = bases[rank] + x * (y - i - 1) + j;
59347c6ae99SBarry Smith     }
594ac119b13SBarry Smith 
59547c6ae99SBarry Smith     if (n8 >= 0) { /* right above */
596ce00eea3SSatish Balay       x_t = lx[n8 % m];
5974ad8454bSPierre Jolivet       /* y_t = ly[n8 / m]; */
59847c6ae99SBarry Smith       s_t = bases[n8] + (i - 1) * x_t;
5998865f1eaSKarl Rupp       for (j = 0; j < s_x; j++) idx[nn++] = s_t++;
60047c6ae99SBarry Smith     }
60147c6ae99SBarry Smith   }
60247c6ae99SBarry Smith 
6039566063dSJacob Faibussowitsch   PetscCall(ISCreateBlock(comm, dof, nn, idx, PETSC_USE_POINTER, &from));
6049566063dSJacob Faibussowitsch   PetscCall(VecScatterCreate(global, from, local, to, &gtol));
6059566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&to));
6069566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&from));
60747c6ae99SBarry Smith 
608d9c9ebe5SPeter Brune   if (stencil_type == DMDA_STENCIL_STAR) {
6099371c9d4SSatish Balay     n0 = sn0;
6109371c9d4SSatish Balay     n2 = sn2;
6119371c9d4SSatish Balay     n6 = sn6;
6129371c9d4SSatish Balay     n8 = sn8;
613ce00eea3SSatish Balay   }
614ce00eea3SSatish Balay 
615f4f49eeaSPierre Jolivet   if ((stencil_type == DMDA_STENCIL_STAR) || (bx && bx != DM_BOUNDARY_PERIODIC) || (by && by != DM_BOUNDARY_PERIODIC)) {
61647c6ae99SBarry Smith     /*
61747c6ae99SBarry Smith         Recompute the local to global mappings, this time keeping the
618ce00eea3SSatish Balay       information about the cross corner processor numbers and any ghosted
619ce00eea3SSatish Balay       but not periodic indices.
62047c6ae99SBarry Smith     */
62147c6ae99SBarry Smith     nn    = 0;
62247c6ae99SBarry Smith     xbase = bases[rank];
62347c6ae99SBarry Smith     for (i = 1; i <= s_y; i++) {
62447c6ae99SBarry Smith       if (n0 >= 0) { /* left below */
625ce00eea3SSatish Balay         x_t = lx[n0 % m];
6264ad8454bSPierre Jolivet         y_t = ly[n0 / m];
62747c6ae99SBarry Smith         s_t = bases[n0] + x_t * y_t - (s_y - i) * x_t - s_x;
6288865f1eaSKarl Rupp         for (j = 0; j < s_x; j++) idx[nn++] = s_t++;
629ce00eea3SSatish Balay       } else if (xs - Xs > 0 && ys - Ys > 0) {
6308865f1eaSKarl Rupp         for (j = 0; j < s_x; j++) idx[nn++] = -1;
63147c6ae99SBarry Smith       }
63247c6ae99SBarry Smith       if (n1 >= 0) { /* directly below */
63347c6ae99SBarry Smith         x_t = x;
6344ad8454bSPierre Jolivet         y_t = ly[n1 / m];
63547c6ae99SBarry Smith         s_t = bases[n1] + x_t * y_t - (s_y + 1 - i) * x_t;
6368865f1eaSKarl Rupp         for (j = 0; j < x_t; j++) idx[nn++] = s_t++;
637ce00eea3SSatish Balay       } else if (ys - Ys > 0) {
638bff4a2f0SMatthew G. Knepley         if (by == DM_BOUNDARY_MIRROR) {
6398865f1eaSKarl Rupp           for (j = 0; j < x; j++) idx[nn++] = bases[rank] + x * (s_y - i + 1) + j;
640624904c4SBarry Smith         } else {
6418865f1eaSKarl Rupp           for (j = 0; j < x; j++) idx[nn++] = -1;
64247c6ae99SBarry Smith         }
643624904c4SBarry Smith       }
64447c6ae99SBarry Smith       if (n2 >= 0) { /* right below */
645ce00eea3SSatish Balay         x_t = lx[n2 % m];
6464ad8454bSPierre Jolivet         y_t = ly[n2 / m];
64747c6ae99SBarry Smith         s_t = bases[n2] + x_t * y_t - (s_y + 1 - i) * x_t;
6488865f1eaSKarl Rupp         for (j = 0; j < s_x; j++) idx[nn++] = s_t++;
649ce00eea3SSatish Balay       } else if (Xe - xe > 0 && ys - Ys > 0) {
6508865f1eaSKarl Rupp         for (j = 0; j < s_x; j++) idx[nn++] = -1;
65147c6ae99SBarry Smith       }
65247c6ae99SBarry Smith     }
65347c6ae99SBarry Smith 
65447c6ae99SBarry Smith     for (i = 0; i < y; i++) {
65547c6ae99SBarry Smith       if (n3 >= 0) { /* directly left */
656ce00eea3SSatish Balay         x_t = lx[n3 % m];
65747c6ae99SBarry Smith         /* y_t = y; */
65847c6ae99SBarry Smith         s_t = bases[n3] + (i + 1) * x_t - s_x;
6598865f1eaSKarl Rupp         for (j = 0; j < s_x; j++) idx[nn++] = s_t++;
660ce00eea3SSatish Balay       } else if (xs - Xs > 0) {
661bff4a2f0SMatthew G. Knepley         if (bx == DM_BOUNDARY_MIRROR) {
6628865f1eaSKarl Rupp           for (j = 0; j < s_x; j++) idx[nn++] = bases[rank] + x * i + s_x - j;
663624904c4SBarry Smith         } else {
6648865f1eaSKarl Rupp           for (j = 0; j < s_x; j++) idx[nn++] = -1;
66547c6ae99SBarry Smith         }
666624904c4SBarry Smith       }
66747c6ae99SBarry Smith 
6688865f1eaSKarl Rupp       for (j = 0; j < x; j++) idx[nn++] = xbase++; /* interior */
66947c6ae99SBarry Smith 
67047c6ae99SBarry Smith       if (n5 >= 0) { /* directly right */
671ce00eea3SSatish Balay         x_t = lx[n5 % m];
67247c6ae99SBarry Smith         /* y_t = y; */
67347c6ae99SBarry Smith         s_t = bases[n5] + (i)*x_t;
6748865f1eaSKarl Rupp         for (j = 0; j < s_x; j++) idx[nn++] = s_t++;
675ce00eea3SSatish Balay       } else if (Xe - xe > 0) {
676bff4a2f0SMatthew G. Knepley         if (bx == DM_BOUNDARY_MIRROR) {
6778865f1eaSKarl Rupp           for (j = 0; j < s_x; j++) idx[nn++] = bases[rank] + x * (i + 1) - 2 - j;
678624904c4SBarry Smith         } else {
6798865f1eaSKarl Rupp           for (j = 0; j < s_x; j++) idx[nn++] = -1;
68047c6ae99SBarry Smith         }
68147c6ae99SBarry Smith       }
682624904c4SBarry Smith     }
68347c6ae99SBarry Smith 
68447c6ae99SBarry Smith     for (i = 1; i <= s_y; i++) {
68547c6ae99SBarry Smith       if (n6 >= 0) { /* left above */
686ce00eea3SSatish Balay         x_t = lx[n6 % m];
6874ad8454bSPierre Jolivet         /* y_t = ly[n6 / m]; */
68847c6ae99SBarry Smith         s_t = bases[n6] + (i)*x_t - s_x;
6898865f1eaSKarl Rupp         for (j = 0; j < s_x; j++) idx[nn++] = s_t++;
690ce00eea3SSatish Balay       } else if (xs - Xs > 0 && Ye - ye > 0) {
6918865f1eaSKarl Rupp         for (j = 0; j < s_x; j++) idx[nn++] = -1;
69247c6ae99SBarry Smith       }
69347c6ae99SBarry Smith       if (n7 >= 0) { /* directly above */
69447c6ae99SBarry Smith         x_t = x;
6954ad8454bSPierre Jolivet         /* y_t = ly[n7 / m]; */
69647c6ae99SBarry Smith         s_t = bases[n7] + (i - 1) * x_t;
6978865f1eaSKarl Rupp         for (j = 0; j < x_t; j++) idx[nn++] = s_t++;
698ce00eea3SSatish Balay       } else if (Ye - ye > 0) {
699bff4a2f0SMatthew G. Knepley         if (by == DM_BOUNDARY_MIRROR) {
7008865f1eaSKarl Rupp           for (j = 0; j < x; j++) idx[nn++] = bases[rank] + x * (y - i - 1) + j;
701624904c4SBarry Smith         } else {
7028865f1eaSKarl Rupp           for (j = 0; j < x; j++) idx[nn++] = -1;
70347c6ae99SBarry Smith         }
704624904c4SBarry Smith       }
70547c6ae99SBarry Smith       if (n8 >= 0) { /* right above */
706ce00eea3SSatish Balay         x_t = lx[n8 % m];
7074ad8454bSPierre Jolivet         /* y_t = ly[n8 / m]; */
70847c6ae99SBarry Smith         s_t = bases[n8] + (i - 1) * x_t;
7098865f1eaSKarl Rupp         for (j = 0; j < s_x; j++) idx[nn++] = s_t++;
710ce00eea3SSatish Balay       } else if (Xe - xe > 0 && Ye - ye > 0) {
7118865f1eaSKarl Rupp         for (j = 0; j < s_x; j++) idx[nn++] = -1;
71247c6ae99SBarry Smith       }
71347c6ae99SBarry Smith     }
71447c6ae99SBarry Smith   }
715ce00eea3SSatish Balay   /*
716ce00eea3SSatish Balay      Set the local to global ordering in the global vector, this allows use
717ce00eea3SSatish Balay      of VecSetValuesLocal().
718ce00eea3SSatish Balay   */
7199566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingCreate(comm, dof, nn, idx, PETSC_OWN_POINTER, &da->ltogmap));
72047c6ae99SBarry Smith 
7219566063dSJacob Faibussowitsch   PetscCall(PetscFree2(bases, ldims));
7229371c9d4SSatish Balay   dd->m = m;
7239371c9d4SSatish Balay   dd->n = n;
724f0b74427SPierre Jolivet   /* note PETSc expects xs/xe/Xs/Xe to be multiplied by #dofs in many places */
7259371c9d4SSatish Balay   dd->xs = xs * dof;
7269371c9d4SSatish Balay   dd->xe = xe * dof;
7279371c9d4SSatish Balay   dd->ys = ys;
7289371c9d4SSatish Balay   dd->ye = ye;
7299371c9d4SSatish Balay   dd->zs = 0;
7309371c9d4SSatish Balay   dd->ze = 1;
7319371c9d4SSatish Balay   dd->Xs = Xs * dof;
7329371c9d4SSatish Balay   dd->Xe = Xe * dof;
7339371c9d4SSatish Balay   dd->Ys = Ys;
7349371c9d4SSatish Balay   dd->Ye = Ye;
7359371c9d4SSatish Balay   dd->Zs = 0;
7369371c9d4SSatish Balay   dd->Ze = 1;
73747c6ae99SBarry Smith 
7389566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&local));
7399566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&global));
74047c6ae99SBarry Smith 
74147c6ae99SBarry Smith   dd->gtol      = gtol;
74247c6ae99SBarry Smith   dd->base      = base;
7439a42bb27SBarry Smith   da->ops->view = DMView_DA_2d;
7440298fd71SBarry Smith   dd->ltol      = NULL;
7450298fd71SBarry Smith   dd->ao        = NULL;
7463ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
74747c6ae99SBarry Smith }
74847c6ae99SBarry Smith 
749cc4c1da9SBarry Smith /*@
750aa219208SBarry Smith   DMDACreate2d -  Creates an object that will manage the communication of two-dimensional
75112b4a537SBarry Smith   regular array data that is distributed across one or more MPI processes.
75247c6ae99SBarry Smith 
753d083f849SBarry Smith   Collective
75447c6ae99SBarry Smith 
75547c6ae99SBarry Smith   Input Parameters:
75647c6ae99SBarry Smith + comm         - MPI communicator
757a4e35b19SJacob Faibussowitsch . bx           - type of ghost nodes the x array have. Use one of `DM_BOUNDARY_NONE`, `DM_BOUNDARY_GHOSTED`, `DM_BOUNDARY_PERIODIC`.
758a4e35b19SJacob Faibussowitsch . by           - type of ghost nodes the y array have. Use one of `DM_BOUNDARY_NONE`, `DM_BOUNDARY_GHOSTED`, `DM_BOUNDARY_PERIODIC`.
759dce8aebaSBarry Smith . stencil_type - stencil type.  Use either `DMDA_STENCIL_BOX` or `DMDA_STENCIL_STAR`.
760a4e35b19SJacob Faibussowitsch . M            - global dimension in x direction of the array
761a4e35b19SJacob Faibussowitsch . N            - global dimension in y direction of the array
762a4e35b19SJacob Faibussowitsch . m            - corresponding number of processors in x dimension (or `PETSC_DECIDE` to have calculated)
763a4e35b19SJacob Faibussowitsch . n            - corresponding number of processors in y dimension (or `PETSC_DECIDE` to have calculated)
76447c6ae99SBarry Smith . dof          - number of degrees of freedom per node
76547c6ae99SBarry Smith . s            - stencil width
766a4e35b19SJacob Faibussowitsch . lx           - arrays containing the number of nodes in each cell along the x coordinates, or `NULL`.
767a4e35b19SJacob Faibussowitsch - ly           - arrays containing the number of nodes in each cell along the y coordinates, or `NULL`.
76847c6ae99SBarry Smith 
76947c6ae99SBarry Smith   Output Parameter:
77047c6ae99SBarry Smith . da - the resulting distributed array object
77147c6ae99SBarry Smith 
772dce8aebaSBarry Smith   Options Database Keys:
773dce8aebaSBarry Smith + -dm_view              - Calls `DMView()` at the conclusion of `DMDACreate2d()`
774e43dc8daSBarry Smith . -da_grid_x <nx>       - number of grid points in x direction
775e43dc8daSBarry Smith . -da_grid_y <ny>       - number of grid points in y direction
77647c6ae99SBarry Smith . -da_processors_x <nx> - number of processors in x direction
77747c6ae99SBarry Smith . -da_processors_y <ny> - number of processors in y direction
778fe58071bSMatthew G. Knepley . -da_bd_x <bx>         - boundary type in x direction
779fe58071bSMatthew G. Knepley . -da_bd_y <by>         - boundary type in y direction
780fe58071bSMatthew G. Knepley . -da_bd_all <bt>       - boundary type in all directions
781e0f5d30fSBarry Smith . -da_refine_x <rx>     - refinement ratio in x direction
782e0f5d30fSBarry Smith . -da_refine_y <ry>     - refinement ratio in y direction
78312b4a537SBarry Smith - -da_refine <n>        - refine the `DMDA` n times before creating
784e0f5d30fSBarry Smith 
78547c6ae99SBarry Smith   Level: beginner
78647c6ae99SBarry Smith 
78747c6ae99SBarry Smith   Notes:
788a4e35b19SJacob Faibussowitsch   If `lx` or `ly` are non-null, these must be of length as `m` and `n`, and the corresponding
789a4e35b19SJacob Faibussowitsch   `m` and `n` cannot be `PETSC_DECIDE`. The sum of the `lx` entries must be `M`, and the sum of
790a4e35b19SJacob Faibussowitsch   the `ly` entries must be `N`.
791a4e35b19SJacob Faibussowitsch 
792dce8aebaSBarry Smith   The stencil type `DMDA_STENCIL_STAR` with width 1 corresponds to the
793dce8aebaSBarry Smith   standard 5-pt stencil, while `DMDA_STENCIL_BOX` with width 1 denotes
79447c6ae99SBarry Smith   the standard 9-pt stencil.
79547c6ae99SBarry Smith 
796dce8aebaSBarry Smith   The array data itself is NOT stored in the `DMDA`, it is stored in `Vec` objects;
797dce8aebaSBarry Smith   The appropriate vector objects can be obtained with calls to `DMCreateGlobalVector()`
798dce8aebaSBarry Smith   and DMCreateLocalVector() and calls to `VecDuplicate()` if more are needed.
79947c6ae99SBarry Smith 
800dce8aebaSBarry Smith   You must call `DMSetUp()` after this call before using this `DM`.
801897f7067SBarry Smith 
80212b4a537SBarry Smith   To use the options database to change values in the `DMDA` call `DMSetFromOptions()` after this call
803dce8aebaSBarry Smith   but before `DMSetUp()`.
804897f7067SBarry Smith 
80512b4a537SBarry Smith .seealso: [](sec_struct), `DM`, `DMDA`, `DMDestroy()`, `DMView()`, `DMDACreate1d()`, `DMDACreate3d()`, `DMGlobalToLocalBegin()`, `DMDAGetRefinementFactor()`,
806db781477SPatrick Sanan           `DMGlobalToLocalEnd()`, `DMLocalToGlobalBegin()`, `DMLocalToLocalBegin()`, `DMLocalToLocalEnd()`, `DMDASetRefinementFactor()`,
807db781477SPatrick Sanan           `DMDAGetInfo()`, `DMCreateGlobalVector()`, `DMCreateLocalVector()`, `DMDACreateNaturalVector()`, `DMLoad()`, `DMDAGetOwnershipRanges()`,
80812b4a537SBarry Smith           `DMStagCreate2d()`, `DMBoundaryType`
80947c6ae99SBarry Smith @*/
DMDACreate2d(MPI_Comm comm,DMBoundaryType bx,DMBoundaryType by,DMDAStencilType stencil_type,PetscInt M,PetscInt N,PetscInt m,PetscInt n,PetscInt dof,PetscInt s,const PetscInt lx[],const PetscInt ly[],DM * da)810d71ae5a4SJacob Faibussowitsch PetscErrorCode DMDACreate2d(MPI_Comm comm, DMBoundaryType bx, DMBoundaryType by, DMDAStencilType stencil_type, PetscInt M, PetscInt N, PetscInt m, PetscInt n, PetscInt dof, PetscInt s, const PetscInt lx[], const PetscInt ly[], DM *da)
811d71ae5a4SJacob Faibussowitsch {
81247c6ae99SBarry Smith   PetscFunctionBegin;
8139566063dSJacob Faibussowitsch   PetscCall(DMDACreate(comm, da));
8149566063dSJacob Faibussowitsch   PetscCall(DMSetDimension(*da, 2));
8159566063dSJacob Faibussowitsch   PetscCall(DMDASetSizes(*da, M, N, 1));
8169566063dSJacob Faibussowitsch   PetscCall(DMDASetNumProcs(*da, m, n, PETSC_DECIDE));
8179566063dSJacob Faibussowitsch   PetscCall(DMDASetBoundaryType(*da, bx, by, DM_BOUNDARY_NONE));
8189566063dSJacob Faibussowitsch   PetscCall(DMDASetDof(*da, dof));
8199566063dSJacob Faibussowitsch   PetscCall(DMDASetStencilType(*da, stencil_type));
8209566063dSJacob Faibussowitsch   PetscCall(DMDASetStencilWidth(*da, s));
8219566063dSJacob Faibussowitsch   PetscCall(DMDASetOwnershipRanges(*da, lx, ly, NULL));
8223ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
82347c6ae99SBarry Smith }
824