xref: /petsc/src/dm/impls/da/da2.c (revision a4e35b1925eceef64945ea472b84f2bf06a67b5e)
19a42bb27SBarry Smith 
2af0996ceSBarry Smith #include <petsc/private/dmdaimpl.h> /*I   "petscdmda.h"   I*/
39804daf3SBarry Smith #include <petscdraw.h>
447c6ae99SBarry Smith 
5d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMView_DA_2d(DM da, PetscViewer viewer)
6d71ae5a4SJacob Faibussowitsch {
747c6ae99SBarry Smith   PetscMPIInt rank;
8c9493c35SStefano Zampini   PetscBool   iascii, isdraw, isglvis, isbinary;
947c6ae99SBarry Smith   DM_DA      *dd = (DM_DA *)da->data;
10d1e78c4fSBarry Smith #if defined(PETSC_HAVE_MATLAB)
119a42bb27SBarry Smith   PetscBool ismatlab;
129a42bb27SBarry Smith #endif
1347c6ae99SBarry Smith 
1447c6ae99SBarry Smith   PetscFunctionBegin;
159566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)da), &rank));
1647c6ae99SBarry Smith 
179566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
189566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw));
199566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERGLVIS, &isglvis));
209566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &isbinary));
21d1e78c4fSBarry Smith #if defined(PETSC_HAVE_MATLAB)
229566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERMATLAB, &ismatlab));
239a42bb27SBarry Smith #endif
2447c6ae99SBarry Smith   if (iascii) {
2547c6ae99SBarry Smith     PetscViewerFormat format;
2647c6ae99SBarry Smith 
279566063dSJacob Faibussowitsch     PetscCall(PetscViewerGetFormat(viewer, &format));
2876a8abe0SBarry Smith     if (format == PETSC_VIEWER_LOAD_BALANCE) {
2976a8abe0SBarry Smith       PetscInt      i, nmax = 0, nmin = PETSC_MAX_INT, navg = 0, *nz, nzlocal;
3076a8abe0SBarry Smith       DMDALocalInfo info;
3176a8abe0SBarry Smith       PetscMPIInt   size;
329566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)da), &size));
339566063dSJacob Faibussowitsch       PetscCall(DMDAGetLocalInfo(da, &info));
3476a8abe0SBarry Smith       nzlocal = info.xm * info.ym;
359566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(size, &nz));
369566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Allgather(&nzlocal, 1, MPIU_INT, nz, 1, MPIU_INT, PetscObjectComm((PetscObject)da)));
3776a8abe0SBarry Smith       for (i = 0; i < (PetscInt)size; i++) {
3876a8abe0SBarry Smith         nmax = PetscMax(nmax, nz[i]);
3976a8abe0SBarry Smith         nmin = PetscMin(nmin, nz[i]);
4076a8abe0SBarry Smith         navg += nz[i];
4176a8abe0SBarry Smith       }
429566063dSJacob Faibussowitsch       PetscCall(PetscFree(nz));
4376a8abe0SBarry Smith       navg = navg / size;
4463a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  Load Balance - Grid Points: Min %" PetscInt_FMT "  avg %" PetscInt_FMT "  max %" PetscInt_FMT "\n", nmin, navg, nmax));
453ba16761SJacob Faibussowitsch       PetscFunctionReturn(PETSC_SUCCESS);
4676a8abe0SBarry Smith     }
478ec8862eSJed Brown     if (format != PETSC_VIEWER_ASCII_VTK_DEPRECATED && format != PETSC_VIEWER_ASCII_VTK_CELL_DEPRECATED && format != PETSC_VIEWER_ASCII_GLVIS) {
48aa219208SBarry Smith       DMDALocalInfo info;
499566063dSJacob Faibussowitsch       PetscCall(DMDAGetLocalInfo(da, &info));
509566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPushSynchronized(viewer));
5163a3b9bcSJacob 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));
5263a3b9bcSJacob 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));
539566063dSJacob Faibussowitsch       PetscCall(PetscViewerFlush(viewer));
549566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPopSynchronized(viewer));
551baa6e33SBarry Smith     } else if (format == PETSC_VIEWER_ASCII_GLVIS) PetscCall(DMView_DA_GLVis(da, viewer));
561baa6e33SBarry Smith     else PetscCall(DMView_DA_VTK(da, viewer));
5747c6ae99SBarry Smith   } else if (isdraw) {
5847c6ae99SBarry Smith     PetscDraw       draw;
5947c6ae99SBarry Smith     double          ymin = -1 * dd->s - 1, ymax = dd->N + dd->s;
6047c6ae99SBarry Smith     double          xmin = -1 * dd->s - 1, xmax = dd->M + dd->s;
6147c6ae99SBarry Smith     double          x, y;
628ea3bf28SBarry Smith     PetscInt        base;
638ea3bf28SBarry Smith     const PetscInt *idx;
6447c6ae99SBarry Smith     char            node[10];
6547c6ae99SBarry Smith     PetscBool       isnull;
6647c6ae99SBarry Smith 
679566063dSJacob Faibussowitsch     PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw));
689566063dSJacob Faibussowitsch     PetscCall(PetscDrawIsNull(draw, &isnull));
693ba16761SJacob Faibussowitsch     if (isnull) PetscFunctionReturn(PETSC_SUCCESS);
7047c6ae99SBarry Smith 
719566063dSJacob Faibussowitsch     PetscCall(PetscDrawCheckResizedWindow(draw));
729566063dSJacob Faibussowitsch     PetscCall(PetscDrawClear(draw));
739566063dSJacob Faibussowitsch     PetscCall(PetscDrawSetCoordinates(draw, xmin, ymin, xmax, ymax));
745b399a63SLisandro Dalcin 
75d0609cedSBarry Smith     PetscDrawCollectiveBegin(draw);
7647c6ae99SBarry Smith     /* first processor draw all node lines */
77dd400576SPatrick Sanan     if (rank == 0) {
789371c9d4SSatish Balay       ymin = 0.0;
799371c9d4SSatish Balay       ymax = dd->N - 1;
8048a46eb9SPierre Jolivet       for (xmin = 0; xmin < dd->M; xmin++) PetscCall(PetscDrawLine(draw, xmin, ymin, xmin, ymax, PETSC_DRAW_BLACK));
819371c9d4SSatish Balay       xmin = 0.0;
829371c9d4SSatish Balay       xmax = dd->M - 1;
8348a46eb9SPierre Jolivet       for (ymin = 0; ymin < dd->N; ymin++) PetscCall(PetscDrawLine(draw, xmin, ymin, xmax, ymin, PETSC_DRAW_BLACK));
8447c6ae99SBarry Smith     }
85d0609cedSBarry Smith     PetscDrawCollectiveEnd(draw);
869566063dSJacob Faibussowitsch     PetscCall(PetscDrawFlush(draw));
879566063dSJacob Faibussowitsch     PetscCall(PetscDrawPause(draw));
8847c6ae99SBarry Smith 
89d0609cedSBarry Smith     PetscDrawCollectiveBegin(draw);
9047c6ae99SBarry Smith     /* draw my box */
919371c9d4SSatish Balay     xmin = dd->xs / dd->w;
929371c9d4SSatish Balay     xmax = (dd->xe - 1) / dd->w;
939371c9d4SSatish Balay     ymin = dd->ys;
949371c9d4SSatish Balay     ymax = dd->ye - 1;
959566063dSJacob Faibussowitsch     PetscCall(PetscDrawLine(draw, xmin, ymin, xmax, ymin, PETSC_DRAW_RED));
969566063dSJacob Faibussowitsch     PetscCall(PetscDrawLine(draw, xmin, ymin, xmin, ymax, PETSC_DRAW_RED));
979566063dSJacob Faibussowitsch     PetscCall(PetscDrawLine(draw, xmin, ymax, xmax, ymax, PETSC_DRAW_RED));
989566063dSJacob Faibussowitsch     PetscCall(PetscDrawLine(draw, xmax, ymin, xmax, ymax, PETSC_DRAW_RED));
9947c6ae99SBarry Smith     /* put in numbers */
10047c6ae99SBarry Smith     base = (dd->base) / dd->w;
10147c6ae99SBarry Smith     for (y = ymin; y <= ymax; y++) {
10247c6ae99SBarry Smith       for (x = xmin; x <= xmax; x++) {
1039566063dSJacob Faibussowitsch         PetscCall(PetscSNPrintf(node, sizeof(node), "%d", (int)base++));
1049566063dSJacob Faibussowitsch         PetscCall(PetscDrawString(draw, x, y, PETSC_DRAW_BLACK, node));
10547c6ae99SBarry Smith       }
10647c6ae99SBarry Smith     }
107d0609cedSBarry Smith     PetscDrawCollectiveEnd(draw);
1089566063dSJacob Faibussowitsch     PetscCall(PetscDrawFlush(draw));
1099566063dSJacob Faibussowitsch     PetscCall(PetscDrawPause(draw));
11047c6ae99SBarry Smith 
111d0609cedSBarry Smith     PetscDrawCollectiveBegin(draw);
1125b399a63SLisandro Dalcin     /* overlay ghost numbers, useful for error checking */
1139566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingGetBlockIndices(da->ltogmap, &idx));
1149371c9d4SSatish Balay     base = 0;
1159371c9d4SSatish Balay     xmin = dd->Xs;
1169371c9d4SSatish Balay     xmax = dd->Xe;
1179371c9d4SSatish Balay     ymin = dd->Ys;
1189371c9d4SSatish Balay     ymax = dd->Ye;
11947c6ae99SBarry Smith     for (y = ymin; y < ymax; y++) {
12047c6ae99SBarry Smith       for (x = xmin; x < xmax; x++) {
12147c6ae99SBarry Smith         if ((base % dd->w) == 0) {
1229566063dSJacob Faibussowitsch           PetscCall(PetscSNPrintf(node, sizeof(node), "%d", (int)(idx[base / dd->w])));
1239566063dSJacob Faibussowitsch           PetscCall(PetscDrawString(draw, x / dd->w, y, PETSC_DRAW_BLUE, node));
12447c6ae99SBarry Smith         }
12547c6ae99SBarry Smith         base++;
12647c6ae99SBarry Smith       }
12747c6ae99SBarry Smith     }
1289566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingRestoreBlockIndices(da->ltogmap, &idx));
129d0609cedSBarry Smith     PetscDrawCollectiveEnd(draw);
1309566063dSJacob Faibussowitsch     PetscCall(PetscDrawFlush(draw));
1319566063dSJacob Faibussowitsch     PetscCall(PetscDrawPause(draw));
1329566063dSJacob Faibussowitsch     PetscCall(PetscDrawSave(draw));
133c9493c35SStefano Zampini   } else if (isglvis) {
1349566063dSJacob Faibussowitsch     PetscCall(DMView_DA_GLVis(da, viewer));
1359a42bb27SBarry Smith   } else if (isbinary) {
1369566063dSJacob Faibussowitsch     PetscCall(DMView_DA_Binary(da, viewer));
137d1e78c4fSBarry Smith #if defined(PETSC_HAVE_MATLAB)
1389a42bb27SBarry Smith   } else if (ismatlab) {
1399566063dSJacob Faibussowitsch     PetscCall(DMView_DA_Matlab(da, viewer));
1409a42bb27SBarry Smith #endif
14111aeaf0aSBarry Smith   }
1423ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
14347c6ae99SBarry Smith }
14447c6ae99SBarry Smith 
14547c6ae99SBarry Smith #if defined(new)
14647c6ae99SBarry Smith /*
14701c1178eSBarry Smith   DMDAGetDiagonal_MFFD - Gets the diagonal for a matrix-free matrix where local
148aa219208SBarry Smith     function lives on a DMDA
14947c6ae99SBarry Smith 
15047c6ae99SBarry Smith         y ~= (F(u + ha) - F(u))/h,
15147c6ae99SBarry Smith   where F = nonlinear function, as set by SNESSetFunction()
15247c6ae99SBarry Smith         u = current iterate
15347c6ae99SBarry Smith         h = difference interval
15447c6ae99SBarry Smith */
155d71ae5a4SJacob Faibussowitsch PetscErrorCode DMDAGetDiagonal_MFFD(DM da, Vec U, Vec a)
156d71ae5a4SJacob Faibussowitsch {
15747c6ae99SBarry Smith   PetscScalar   h, *aa, *ww, v;
15847c6ae99SBarry Smith   PetscReal     epsilon = PETSC_SQRT_MACHINE_EPSILON, umin = 100.0 * PETSC_SQRT_MACHINE_EPSILON;
15947c6ae99SBarry Smith   PetscInt      gI, nI;
16047c6ae99SBarry Smith   MatStencil    stencil;
161aa219208SBarry Smith   DMDALocalInfo info;
16247c6ae99SBarry Smith 
16347c6ae99SBarry Smith   PetscFunctionBegin;
1649566063dSJacob Faibussowitsch   PetscCall((*ctx->func)(0, U, a, ctx->funcctx));
1659566063dSJacob Faibussowitsch   PetscCall((*ctx->funcisetbase)(U, ctx->funcctx));
16647c6ae99SBarry Smith 
1679566063dSJacob Faibussowitsch   PetscCall(VecGetArray(U, &ww));
1689566063dSJacob Faibussowitsch   PetscCall(VecGetArray(a, &aa));
16947c6ae99SBarry Smith 
17047c6ae99SBarry Smith   nI = 0;
17147c6ae99SBarry Smith   h  = ww[gI];
17247c6ae99SBarry Smith   if (h == 0.0) h = 1.0;
17347c6ae99SBarry Smith   if (PetscAbsScalar(h) < umin && PetscRealPart(h) >= 0.0) h = umin;
17447c6ae99SBarry Smith   else if (PetscRealPart(h) < 0.0 && PetscAbsScalar(h) < umin) h = -umin;
17547c6ae99SBarry Smith   h *= epsilon;
17647c6ae99SBarry Smith 
17747c6ae99SBarry Smith   ww[gI] += h;
1789566063dSJacob Faibussowitsch   PetscCall((*ctx->funci)(i, w, &v, ctx->funcctx));
17947c6ae99SBarry Smith   aa[nI] = (v - aa[nI]) / h;
18047c6ae99SBarry Smith   ww[gI] -= h;
18147c6ae99SBarry Smith   nI++;
1828865f1eaSKarl Rupp 
1839566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(U, &ww));
1849566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(a, &aa));
1853ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
18647c6ae99SBarry Smith }
18747c6ae99SBarry Smith #endif
18847c6ae99SBarry Smith 
189d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetUp_DA_2D(DM da)
190d71ae5a4SJacob Faibussowitsch {
19147c6ae99SBarry Smith   DM_DA          *dd           = (DM_DA *)da->data;
19247c6ae99SBarry Smith   const PetscInt  M            = dd->M;
19347c6ae99SBarry Smith   const PetscInt  N            = dd->N;
19447c6ae99SBarry Smith   PetscInt        m            = dd->m;
19547c6ae99SBarry Smith   PetscInt        n            = dd->n;
19647c6ae99SBarry Smith   const PetscInt  dof          = dd->w;
19747c6ae99SBarry Smith   const PetscInt  s            = dd->s;
198bff4a2f0SMatthew G. Knepley   DMBoundaryType  bx           = dd->bx;
199bff4a2f0SMatthew G. Knepley   DMBoundaryType  by           = dd->by;
20019fd82e9SBarry Smith   DMDAStencilType stencil_type = dd->stencil_type;
20147c6ae99SBarry Smith   PetscInt       *lx           = dd->lx;
20247c6ae99SBarry Smith   PetscInt       *ly           = dd->ly;
20347c6ae99SBarry Smith   MPI_Comm        comm;
20447c6ae99SBarry Smith   PetscMPIInt     rank, size;
205bd1fc5aeSBarry Smith   PetscInt        xs, xe, ys, ye, x, y, Xs, Xe, Ys, Ye, IXs, IXe, IYs, IYe;
2068ea3bf28SBarry Smith   PetscInt        up, down, left, right, i, n0, n1, n2, n3, n5, n6, n7, n8, *idx, nn;
207db87c5ecSEthan Coon   PetscInt        xbase, *bases, *ldims, j, x_t, y_t, s_t, base, count;
20847c6ae99SBarry Smith   PetscInt        s_x, s_y; /* s proportionalized to w */
20947c6ae99SBarry Smith   PetscInt        sn0 = 0, sn2 = 0, sn6 = 0, sn8 = 0;
21047c6ae99SBarry Smith   Vec             local, global;
211bd1fc5aeSBarry Smith   VecScatter      gtol;
21245b6f7e9SBarry Smith   IS              to, from;
21347c6ae99SBarry Smith 
21447c6ae99SBarry Smith   PetscFunctionBegin;
2157a8be351SBarry 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");
2169566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)da, &comm));
2173855c12bSBarry Smith #if !defined(PETSC_USE_64BIT_INDICES)
2187de69702SBarry 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);
2193855c12bSBarry Smith #endif
22047c6ae99SBarry Smith 
2219566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(comm, &size));
2229566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
22347c6ae99SBarry Smith 
2247d310018SBarry Smith   dd->p = 1;
22547c6ae99SBarry Smith   if (m != PETSC_DECIDE) {
22663a3b9bcSJacob Faibussowitsch     PetscCheck(m >= 1, comm, PETSC_ERR_ARG_OUTOFRANGE, "Non-positive number of processors in X direction: %" PetscInt_FMT, m);
227f7d195e4SLawrence Mitchell     PetscCheck(m <= size, comm, PETSC_ERR_ARG_OUTOFRANGE, "Too many processors in X direction: %" PetscInt_FMT " %d", m, size);
22847c6ae99SBarry Smith   }
22947c6ae99SBarry Smith   if (n != PETSC_DECIDE) {
23063a3b9bcSJacob Faibussowitsch     PetscCheck(n >= 1, comm, PETSC_ERR_ARG_OUTOFRANGE, "Non-positive number of processors in Y direction: %" PetscInt_FMT, n);
231f7d195e4SLawrence Mitchell     PetscCheck(n <= size, comm, PETSC_ERR_ARG_OUTOFRANGE, "Too many processors in Y direction: %" PetscInt_FMT " %d", n, size);
23247c6ae99SBarry Smith   }
23347c6ae99SBarry Smith 
23447c6ae99SBarry Smith   if (m == PETSC_DECIDE || n == PETSC_DECIDE) {
23547c6ae99SBarry Smith     if (n != PETSC_DECIDE) {
23647c6ae99SBarry Smith       m = size / n;
23747c6ae99SBarry Smith     } else if (m != PETSC_DECIDE) {
23847c6ae99SBarry Smith       n = size / m;
23947c6ae99SBarry Smith     } else {
24047c6ae99SBarry Smith       /* try for squarish distribution */
241369cc0aeSBarry Smith       m = (PetscInt)(0.5 + PetscSqrtReal(((PetscReal)M) * ((PetscReal)size) / ((PetscReal)N)));
24247c6ae99SBarry Smith       if (!m) m = 1;
24347c6ae99SBarry Smith       while (m > 0) {
24447c6ae99SBarry Smith         n = size / m;
24547c6ae99SBarry Smith         if (m * n == size) break;
24647c6ae99SBarry Smith         m--;
24747c6ae99SBarry Smith       }
2489371c9d4SSatish Balay       if (M > N && m < n) {
2499371c9d4SSatish Balay         PetscInt _m = m;
2509371c9d4SSatish Balay         m           = n;
2519371c9d4SSatish Balay         n           = _m;
2529371c9d4SSatish Balay       }
25347c6ae99SBarry Smith     }
2547a8be351SBarry Smith     PetscCheck(m * n == size, comm, PETSC_ERR_PLIB, "Unable to create partition, check the size of the communicator and input m and n ");
2557a8be351SBarry Smith   } else PetscCheck(m * n == size, comm, PETSC_ERR_ARG_OUTOFRANGE, "Given Bad partition");
25647c6ae99SBarry Smith 
25763a3b9bcSJacob Faibussowitsch   PetscCheck(M >= m, comm, PETSC_ERR_ARG_OUTOFRANGE, "Partition in x direction is too fine! %" PetscInt_FMT " %" PetscInt_FMT, M, m);
25863a3b9bcSJacob Faibussowitsch   PetscCheck(N >= n, comm, PETSC_ERR_ARG_OUTOFRANGE, "Partition in y direction is too fine! %" PetscInt_FMT " %" PetscInt_FMT, N, n);
25947c6ae99SBarry Smith 
26047c6ae99SBarry Smith   /*
26147c6ae99SBarry Smith      Determine locally owned region
26247c6ae99SBarry Smith      xs is the first local node number, x is the number of local nodes
26347c6ae99SBarry Smith   */
26447c6ae99SBarry Smith   if (!lx) {
2659566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(m, &dd->lx));
26647c6ae99SBarry Smith     lx = dd->lx;
267ad540459SPierre Jolivet     for (i = 0; i < m; i++) lx[i] = M / m + ((M % m) > i);
26847c6ae99SBarry Smith   }
26947c6ae99SBarry Smith   x  = lx[rank % m];
27047c6ae99SBarry Smith   xs = 0;
271ad540459SPierre Jolivet   for (i = 0; i < (rank % m); i++) xs += lx[i];
27276bd3646SJed Brown   if (PetscDefined(USE_DEBUG)) {
27347c6ae99SBarry Smith     left = xs;
274ad540459SPierre Jolivet     for (i = (rank % m); i < m; i++) left += lx[i];
27563a3b9bcSJacob 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);
27676bd3646SJed Brown   }
27747c6ae99SBarry Smith 
27847c6ae99SBarry Smith   /*
27947c6ae99SBarry Smith      Determine locally owned region
28047c6ae99SBarry Smith      ys is the first local node number, y is the number of local nodes
28147c6ae99SBarry Smith   */
28247c6ae99SBarry Smith   if (!ly) {
2839566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(n, &dd->ly));
28447c6ae99SBarry Smith     ly = dd->ly;
285ad540459SPierre Jolivet     for (i = 0; i < n; i++) ly[i] = N / n + ((N % n) > i);
28647c6ae99SBarry Smith   }
28747c6ae99SBarry Smith   y  = ly[rank / m];
28847c6ae99SBarry Smith   ys = 0;
289ad540459SPierre Jolivet   for (i = 0; i < (rank / m); i++) ys += ly[i];
29076bd3646SJed Brown   if (PetscDefined(USE_DEBUG)) {
29147c6ae99SBarry Smith     left = ys;
292ad540459SPierre Jolivet     for (i = (rank / m); i < n; i++) left += ly[i];
29363a3b9bcSJacob 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);
29476bd3646SJed Brown   }
29547c6ae99SBarry Smith 
296bcea557cSEthan Coon   /*
297bcea557cSEthan Coon    check if the scatter requires more than one process neighbor or wraps around
298bcea557cSEthan Coon    the domain more than once
299bcea557cSEthan Coon   */
30063a3b9bcSJacob 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);
30163a3b9bcSJacob 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);
30247c6ae99SBarry Smith   xe = xs + x;
30347c6ae99SBarry Smith   ye = ys + y;
30447c6ae99SBarry Smith 
305ce00eea3SSatish Balay   /* determine ghost region (Xs) and region scattered into (IXs)  */
306d9c9ebe5SPeter Brune   if (xs - s > 0) {
3079371c9d4SSatish Balay     Xs  = xs - s;
3089371c9d4SSatish Balay     IXs = xs - s;
30988661749SPeter Brune   } else {
31088661749SPeter Brune     if (bx) {
31188661749SPeter Brune       Xs = xs - s;
31288661749SPeter Brune     } else {
31388661749SPeter Brune       Xs = 0;
31488661749SPeter Brune     }
31588661749SPeter Brune     IXs = 0;
31688661749SPeter Brune   }
317d9c9ebe5SPeter Brune   if (xe + s <= M) {
3189371c9d4SSatish Balay     Xe  = xe + s;
3199371c9d4SSatish Balay     IXe = xe + s;
32088661749SPeter Brune   } else {
32188661749SPeter Brune     if (bx) {
3229371c9d4SSatish Balay       Xs = xs - s;
3239371c9d4SSatish Balay       Xe = xe + s;
32488661749SPeter Brune     } else {
32588661749SPeter Brune       Xe = M;
32688661749SPeter Brune     }
32788661749SPeter Brune     IXe = M;
32888661749SPeter Brune   }
32947c6ae99SBarry Smith 
330bff4a2f0SMatthew G. Knepley   if (bx == DM_BOUNDARY_PERIODIC || bx == DM_BOUNDARY_MIRROR) {
331d9c9ebe5SPeter Brune     IXs = xs - s;
332d9c9ebe5SPeter Brune     IXe = xe + s;
333d9c9ebe5SPeter Brune     Xs  = xs - s;
334d9c9ebe5SPeter Brune     Xe  = xe + s;
33588661749SPeter Brune   }
33647c6ae99SBarry Smith 
337d9c9ebe5SPeter Brune   if (ys - s > 0) {
3389371c9d4SSatish Balay     Ys  = ys - s;
3399371c9d4SSatish Balay     IYs = ys - s;
34088661749SPeter Brune   } else {
34188661749SPeter Brune     if (by) {
34288661749SPeter Brune       Ys = ys - s;
34388661749SPeter Brune     } else {
34488661749SPeter Brune       Ys = 0;
34588661749SPeter Brune     }
34688661749SPeter Brune     IYs = 0;
34788661749SPeter Brune   }
348d9c9ebe5SPeter Brune   if (ye + s <= N) {
3499371c9d4SSatish Balay     Ye  = ye + s;
3509371c9d4SSatish Balay     IYe = ye + s;
35188661749SPeter Brune   } else {
35288661749SPeter Brune     if (by) {
35388661749SPeter Brune       Ye = ye + s;
35488661749SPeter Brune     } else {
35588661749SPeter Brune       Ye = N;
35688661749SPeter Brune     }
35788661749SPeter Brune     IYe = N;
35888661749SPeter Brune   }
35988661749SPeter Brune 
360bff4a2f0SMatthew G. Knepley   if (by == DM_BOUNDARY_PERIODIC || by == DM_BOUNDARY_MIRROR) {
361d9c9ebe5SPeter Brune     IYs = ys - s;
362d9c9ebe5SPeter Brune     IYe = ye + s;
363d9c9ebe5SPeter Brune     Ys  = ys - s;
364d9c9ebe5SPeter Brune     Ye  = ye + s;
36588661749SPeter Brune   }
36688661749SPeter Brune 
36788661749SPeter Brune   /* stencil length in each direction */
368d9c9ebe5SPeter Brune   s_x = s;
369d9c9ebe5SPeter Brune   s_y = s;
37047c6ae99SBarry Smith 
37147c6ae99SBarry Smith   /* determine starting point of each processor */
37247c6ae99SBarry Smith   nn = x * y;
3739566063dSJacob Faibussowitsch   PetscCall(PetscMalloc2(size + 1, &bases, size, &ldims));
3749566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Allgather(&nn, 1, MPIU_INT, ldims, 1, MPIU_INT, comm));
37547c6ae99SBarry Smith   bases[0] = 0;
376ad540459SPierre Jolivet   for (i = 1; i <= size; i++) bases[i] = ldims[i - 1];
377ad540459SPierre Jolivet   for (i = 1; i <= size; i++) bases[i] += bases[i - 1];
378ce00eea3SSatish Balay   base = bases[rank] * dof;
37947c6ae99SBarry Smith 
38047c6ae99SBarry Smith   /* allocate the base parallel and sequential vectors */
381ce00eea3SSatish Balay   dd->Nlocal = x * y * dof;
3829566063dSJacob Faibussowitsch   PetscCall(VecCreateMPIWithArray(comm, dof, dd->Nlocal, PETSC_DECIDE, NULL, &global));
383ce00eea3SSatish Balay   dd->nlocal = (Xe - Xs) * (Ye - Ys) * dof;
3849566063dSJacob Faibussowitsch   PetscCall(VecCreateSeqWithArray(PETSC_COMM_SELF, dof, dd->nlocal, NULL, &local));
38547c6ae99SBarry Smith 
3864104a7a0SPatrick Sanan   /* generate global to local vector scatter and local to global mapping*/
38747c6ae99SBarry Smith 
388ce00eea3SSatish Balay   /* global to local must include ghost points within the domain,
389ce00eea3SSatish Balay      but not ghost points outside the domain that aren't periodic */
3909566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1((IXe - IXs) * (IYe - IYs), &idx));
391d9c9ebe5SPeter Brune   if (stencil_type == DMDA_STENCIL_BOX) {
3929371c9d4SSatish Balay     left  = IXs - Xs;
3939371c9d4SSatish Balay     right = left + (IXe - IXs);
3949371c9d4SSatish Balay     down  = IYs - Ys;
3959371c9d4SSatish Balay     up    = down + (IYe - IYs);
396ce00eea3SSatish Balay     count = 0;
397ce00eea3SSatish Balay     for (i = down; i < up; i++) {
398ad540459SPierre Jolivet       for (j = left; j < right; j++) idx[count++] = j + i * (Xe - Xs);
399ce00eea3SSatish Balay     }
4009566063dSJacob Faibussowitsch     PetscCall(ISCreateBlock(comm, dof, count, idx, PETSC_OWN_POINTER, &to));
401ce00eea3SSatish Balay 
40247c6ae99SBarry Smith   } else {
40347c6ae99SBarry Smith     /* must drop into cross shape region */
40447c6ae99SBarry Smith     /*       ---------|
40547c6ae99SBarry Smith             |  top    |
406ce00eea3SSatish Balay          |---         ---| up
40747c6ae99SBarry Smith          |   middle      |
40847c6ae99SBarry Smith          |               |
409ce00eea3SSatish Balay          ----         ---- down
41047c6ae99SBarry Smith             | bottom  |
41147c6ae99SBarry Smith             -----------
41247c6ae99SBarry Smith          Xs xs        xe Xe */
4139371c9d4SSatish Balay     left  = xs - Xs;
4149371c9d4SSatish Balay     right = left + x;
4159371c9d4SSatish Balay     down  = ys - Ys;
4169371c9d4SSatish Balay     up    = down + y;
41747c6ae99SBarry Smith     count = 0;
418ce00eea3SSatish Balay     /* bottom */
419ce00eea3SSatish Balay     for (i = (IYs - Ys); i < down; i++) {
420ad540459SPierre Jolivet       for (j = left; j < right; j++) idx[count++] = j + i * (Xe - Xs);
42147c6ae99SBarry Smith     }
42247c6ae99SBarry Smith     /* middle */
42347c6ae99SBarry Smith     for (i = down; i < up; i++) {
424ad540459SPierre Jolivet       for (j = (IXs - Xs); j < (IXe - Xs); j++) idx[count++] = j + i * (Xe - Xs);
42547c6ae99SBarry Smith     }
42647c6ae99SBarry Smith     /* top */
427ce00eea3SSatish Balay     for (i = up; i < up + IYe - ye; i++) {
428ad540459SPierre Jolivet       for (j = left; j < right; j++) idx[count++] = j + i * (Xe - Xs);
42947c6ae99SBarry Smith     }
4309566063dSJacob Faibussowitsch     PetscCall(ISCreateBlock(comm, dof, count, idx, PETSC_OWN_POINTER, &to));
43147c6ae99SBarry Smith   }
43247c6ae99SBarry Smith 
43347c6ae99SBarry Smith   /* determine who lies on each side of us stored in    n6 n7 n8
43447c6ae99SBarry Smith                                                         n3    n5
43547c6ae99SBarry Smith                                                         n0 n1 n2
43647c6ae99SBarry Smith   */
43747c6ae99SBarry Smith 
43847c6ae99SBarry Smith   /* Assume the Non-Periodic Case */
43947c6ae99SBarry Smith   n1 = rank - m;
44047c6ae99SBarry Smith   if (rank % m) {
44147c6ae99SBarry Smith     n0 = n1 - 1;
44247c6ae99SBarry Smith   } else {
44347c6ae99SBarry Smith     n0 = -1;
44447c6ae99SBarry Smith   }
44547c6ae99SBarry Smith   if ((rank + 1) % m) {
44647c6ae99SBarry Smith     n2 = n1 + 1;
44747c6ae99SBarry Smith     n5 = rank + 1;
4489371c9d4SSatish Balay     n8 = rank + m + 1;
4499371c9d4SSatish Balay     if (n8 >= m * n) n8 = -1;
45047c6ae99SBarry Smith   } else {
4519371c9d4SSatish Balay     n2 = -1;
4529371c9d4SSatish Balay     n5 = -1;
4539371c9d4SSatish Balay     n8 = -1;
45447c6ae99SBarry Smith   }
45547c6ae99SBarry Smith   if (rank % m) {
45647c6ae99SBarry Smith     n3 = rank - 1;
4579371c9d4SSatish Balay     n6 = n3 + m;
4589371c9d4SSatish Balay     if (n6 >= m * n) n6 = -1;
45947c6ae99SBarry Smith   } else {
4609371c9d4SSatish Balay     n3 = -1;
4619371c9d4SSatish Balay     n6 = -1;
46247c6ae99SBarry Smith   }
4639371c9d4SSatish Balay   n7 = rank + m;
4649371c9d4SSatish Balay   if (n7 >= m * n) n7 = -1;
46547c6ae99SBarry Smith 
466bff4a2f0SMatthew G. Knepley   if (bx == DM_BOUNDARY_PERIODIC && by == DM_BOUNDARY_PERIODIC) {
46747c6ae99SBarry Smith     /* Modify for Periodic Cases */
46847c6ae99SBarry Smith     /* Handle all four corners */
46947c6ae99SBarry Smith     if ((n6 < 0) && (n7 < 0) && (n3 < 0)) n6 = m - 1;
47047c6ae99SBarry Smith     if ((n8 < 0) && (n7 < 0) && (n5 < 0)) n8 = 0;
47147c6ae99SBarry Smith     if ((n2 < 0) && (n5 < 0) && (n1 < 0)) n2 = size - m;
47247c6ae99SBarry Smith     if ((n0 < 0) && (n3 < 0) && (n1 < 0)) n0 = size - 1;
47347c6ae99SBarry Smith 
47447c6ae99SBarry Smith     /* Handle Top and Bottom Sides */
47547c6ae99SBarry Smith     if (n1 < 0) n1 = rank + m * (n - 1);
47647c6ae99SBarry Smith     if (n7 < 0) n7 = rank - m * (n - 1);
47747c6ae99SBarry Smith     if ((n3 >= 0) && (n0 < 0)) n0 = size - m + rank - 1;
47847c6ae99SBarry Smith     if ((n3 >= 0) && (n6 < 0)) n6 = (rank % m) - 1;
47947c6ae99SBarry Smith     if ((n5 >= 0) && (n2 < 0)) n2 = size - m + rank + 1;
48047c6ae99SBarry Smith     if ((n5 >= 0) && (n8 < 0)) n8 = (rank % m) + 1;
48147c6ae99SBarry Smith 
48247c6ae99SBarry Smith     /* Handle Left and Right Sides */
48347c6ae99SBarry Smith     if (n3 < 0) n3 = rank + (m - 1);
48447c6ae99SBarry Smith     if (n5 < 0) n5 = rank - (m - 1);
48547c6ae99SBarry Smith     if ((n1 >= 0) && (n0 < 0)) n0 = rank - 1;
48647c6ae99SBarry Smith     if ((n1 >= 0) && (n2 < 0)) n2 = rank - 2 * m + 1;
48747c6ae99SBarry Smith     if ((n7 >= 0) && (n6 < 0)) n6 = rank + 2 * m - 1;
48847c6ae99SBarry Smith     if ((n7 >= 0) && (n8 < 0)) n8 = rank + 1;
489bff4a2f0SMatthew G. Knepley   } else if (by == DM_BOUNDARY_PERIODIC) { /* Handle Top and Bottom Sides */
490ce00eea3SSatish Balay     if (n1 < 0) n1 = rank + m * (n - 1);
491ce00eea3SSatish Balay     if (n7 < 0) n7 = rank - m * (n - 1);
492ce00eea3SSatish Balay     if ((n3 >= 0) && (n0 < 0)) n0 = size - m + rank - 1;
493ce00eea3SSatish Balay     if ((n3 >= 0) && (n6 < 0)) n6 = (rank % m) - 1;
494ce00eea3SSatish Balay     if ((n5 >= 0) && (n2 < 0)) n2 = size - m + rank + 1;
495ce00eea3SSatish Balay     if ((n5 >= 0) && (n8 < 0)) n8 = (rank % m) + 1;
496bff4a2f0SMatthew G. Knepley   } else if (bx == DM_BOUNDARY_PERIODIC) { /* Handle Left and Right Sides */
497ce00eea3SSatish Balay     if (n3 < 0) n3 = rank + (m - 1);
498ce00eea3SSatish Balay     if (n5 < 0) n5 = rank - (m - 1);
499ce00eea3SSatish Balay     if ((n1 >= 0) && (n0 < 0)) n0 = rank - 1;
500ce00eea3SSatish Balay     if ((n1 >= 0) && (n2 < 0)) n2 = rank - 2 * m + 1;
501ce00eea3SSatish Balay     if ((n7 >= 0) && (n6 < 0)) n6 = rank + 2 * m - 1;
502ce00eea3SSatish Balay     if ((n7 >= 0) && (n8 < 0)) n8 = rank + 1;
50347c6ae99SBarry Smith   }
504ce00eea3SSatish Balay 
5059566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(9, &dd->neighbors));
5068865f1eaSKarl Rupp 
50747c6ae99SBarry Smith   dd->neighbors[0] = n0;
50847c6ae99SBarry Smith   dd->neighbors[1] = n1;
50947c6ae99SBarry Smith   dd->neighbors[2] = n2;
51047c6ae99SBarry Smith   dd->neighbors[3] = n3;
51147c6ae99SBarry Smith   dd->neighbors[4] = rank;
51247c6ae99SBarry Smith   dd->neighbors[5] = n5;
51347c6ae99SBarry Smith   dd->neighbors[6] = n6;
51447c6ae99SBarry Smith   dd->neighbors[7] = n7;
51547c6ae99SBarry Smith   dd->neighbors[8] = n8;
51647c6ae99SBarry Smith 
517d9c9ebe5SPeter Brune   if (stencil_type == DMDA_STENCIL_STAR) {
51847c6ae99SBarry Smith     /* save corner processor numbers */
5199371c9d4SSatish Balay     sn0 = n0;
5209371c9d4SSatish Balay     sn2 = n2;
5219371c9d4SSatish Balay     sn6 = n6;
5229371c9d4SSatish Balay     sn8 = n8;
52347c6ae99SBarry Smith     n0 = n2 = n6 = n8 = -1;
52447c6ae99SBarry Smith   }
52547c6ae99SBarry Smith 
5269566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1((Xe - Xs) * (Ye - Ys), &idx));
52747c6ae99SBarry Smith 
528ce00eea3SSatish Balay   nn    = 0;
52947c6ae99SBarry Smith   xbase = bases[rank];
53047c6ae99SBarry Smith   for (i = 1; i <= s_y; i++) {
53147c6ae99SBarry Smith     if (n0 >= 0) { /* left below */
532ce00eea3SSatish Balay       x_t = lx[n0 % m];
53347c6ae99SBarry Smith       y_t = ly[(n0 / m)];
53447c6ae99SBarry Smith       s_t = bases[n0] + x_t * y_t - (s_y - i) * x_t - s_x;
5358865f1eaSKarl Rupp       for (j = 0; j < s_x; j++) idx[nn++] = s_t++;
53647c6ae99SBarry Smith     }
537ac119b13SBarry Smith 
53847c6ae99SBarry Smith     if (n1 >= 0) { /* directly below */
53947c6ae99SBarry Smith       x_t = x;
54047c6ae99SBarry Smith       y_t = ly[(n1 / m)];
54147c6ae99SBarry Smith       s_t = bases[n1] + x_t * y_t - (s_y + 1 - i) * x_t;
5428865f1eaSKarl Rupp       for (j = 0; j < x_t; j++) idx[nn++] = s_t++;
543bff4a2f0SMatthew G. Knepley     } else if (by == DM_BOUNDARY_MIRROR) {
5448865f1eaSKarl Rupp       for (j = 0; j < x; j++) idx[nn++] = bases[rank] + x * (s_y - i + 1) + j;
54547c6ae99SBarry Smith     }
546ac119b13SBarry Smith 
54747c6ae99SBarry Smith     if (n2 >= 0) { /* right below */
548ce00eea3SSatish Balay       x_t = lx[n2 % m];
54947c6ae99SBarry Smith       y_t = ly[(n2 / m)];
55047c6ae99SBarry Smith       s_t = bases[n2] + x_t * y_t - (s_y + 1 - i) * x_t;
5518865f1eaSKarl Rupp       for (j = 0; j < s_x; j++) idx[nn++] = s_t++;
55247c6ae99SBarry Smith     }
55347c6ae99SBarry Smith   }
55447c6ae99SBarry Smith 
55547c6ae99SBarry Smith   for (i = 0; i < y; i++) {
55647c6ae99SBarry Smith     if (n3 >= 0) { /* directly left */
557ce00eea3SSatish Balay       x_t = lx[n3 % m];
55847c6ae99SBarry Smith       /* y_t = y; */
55947c6ae99SBarry Smith       s_t = bases[n3] + (i + 1) * x_t - s_x;
5608865f1eaSKarl Rupp       for (j = 0; j < s_x; j++) idx[nn++] = s_t++;
561bff4a2f0SMatthew G. Knepley     } else if (bx == DM_BOUNDARY_MIRROR) {
5628865f1eaSKarl Rupp       for (j = 0; j < s_x; j++) idx[nn++] = bases[rank] + x * i + s_x - j;
56347c6ae99SBarry Smith     }
56447c6ae99SBarry Smith 
5658865f1eaSKarl Rupp     for (j = 0; j < x; j++) idx[nn++] = xbase++; /* interior */
56647c6ae99SBarry Smith 
56747c6ae99SBarry Smith     if (n5 >= 0) { /* directly right */
568ce00eea3SSatish Balay       x_t = lx[n5 % m];
56947c6ae99SBarry Smith       /* y_t = y; */
57047c6ae99SBarry Smith       s_t = bases[n5] + (i)*x_t;
5718865f1eaSKarl Rupp       for (j = 0; j < s_x; j++) idx[nn++] = s_t++;
572bff4a2f0SMatthew G. Knepley     } else if (bx == DM_BOUNDARY_MIRROR) {
5738865f1eaSKarl Rupp       for (j = 0; j < s_x; j++) idx[nn++] = bases[rank] + x * (i + 1) - 2 - j;
57447c6ae99SBarry Smith     }
57547c6ae99SBarry Smith   }
57647c6ae99SBarry Smith 
57747c6ae99SBarry Smith   for (i = 1; i <= s_y; i++) {
57847c6ae99SBarry Smith     if (n6 >= 0) { /* left above */
579ce00eea3SSatish Balay       x_t = lx[n6 % m];
58047c6ae99SBarry Smith       /* y_t = ly[(n6/m)]; */
58147c6ae99SBarry Smith       s_t = bases[n6] + (i)*x_t - s_x;
5828865f1eaSKarl Rupp       for (j = 0; j < s_x; j++) idx[nn++] = s_t++;
58347c6ae99SBarry Smith     }
584ac119b13SBarry Smith 
58547c6ae99SBarry Smith     if (n7 >= 0) { /* directly above */
58647c6ae99SBarry Smith       x_t = x;
58747c6ae99SBarry Smith       /* y_t = ly[(n7/m)]; */
58847c6ae99SBarry Smith       s_t = bases[n7] + (i - 1) * x_t;
5898865f1eaSKarl Rupp       for (j = 0; j < x_t; j++) idx[nn++] = s_t++;
590bff4a2f0SMatthew G. Knepley     } else if (by == DM_BOUNDARY_MIRROR) {
5918865f1eaSKarl Rupp       for (j = 0; j < x; j++) idx[nn++] = bases[rank] + x * (y - i - 1) + j;
59247c6ae99SBarry Smith     }
593ac119b13SBarry Smith 
59447c6ae99SBarry Smith     if (n8 >= 0) { /* right above */
595ce00eea3SSatish Balay       x_t = lx[n8 % m];
59647c6ae99SBarry Smith       /* y_t = ly[(n8/m)]; */
59747c6ae99SBarry Smith       s_t = bases[n8] + (i - 1) * x_t;
5988865f1eaSKarl Rupp       for (j = 0; j < s_x; j++) idx[nn++] = s_t++;
59947c6ae99SBarry Smith     }
60047c6ae99SBarry Smith   }
60147c6ae99SBarry Smith 
6029566063dSJacob Faibussowitsch   PetscCall(ISCreateBlock(comm, dof, nn, idx, PETSC_USE_POINTER, &from));
6039566063dSJacob Faibussowitsch   PetscCall(VecScatterCreate(global, from, local, to, &gtol));
6049566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&to));
6059566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&from));
60647c6ae99SBarry Smith 
607d9c9ebe5SPeter Brune   if (stencil_type == DMDA_STENCIL_STAR) {
6089371c9d4SSatish Balay     n0 = sn0;
6099371c9d4SSatish Balay     n2 = sn2;
6109371c9d4SSatish Balay     n6 = sn6;
6119371c9d4SSatish Balay     n8 = sn8;
612ce00eea3SSatish Balay   }
613ce00eea3SSatish Balay 
614288e7d53SBarry Smith   if (((stencil_type == DMDA_STENCIL_STAR) || (bx && bx != DM_BOUNDARY_PERIODIC) || (by && by != DM_BOUNDARY_PERIODIC))) {
61547c6ae99SBarry Smith     /*
61647c6ae99SBarry Smith         Recompute the local to global mappings, this time keeping the
617ce00eea3SSatish Balay       information about the cross corner processor numbers and any ghosted
618ce00eea3SSatish Balay       but not periodic indices.
61947c6ae99SBarry Smith     */
62047c6ae99SBarry Smith     nn    = 0;
62147c6ae99SBarry Smith     xbase = bases[rank];
62247c6ae99SBarry Smith     for (i = 1; i <= s_y; i++) {
62347c6ae99SBarry Smith       if (n0 >= 0) { /* left below */
624ce00eea3SSatish Balay         x_t = lx[n0 % m];
62547c6ae99SBarry Smith         y_t = ly[(n0 / m)];
62647c6ae99SBarry Smith         s_t = bases[n0] + x_t * y_t - (s_y - i) * x_t - s_x;
6278865f1eaSKarl Rupp         for (j = 0; j < s_x; j++) idx[nn++] = s_t++;
628ce00eea3SSatish Balay       } else if (xs - Xs > 0 && ys - Ys > 0) {
6298865f1eaSKarl Rupp         for (j = 0; j < s_x; j++) idx[nn++] = -1;
63047c6ae99SBarry Smith       }
63147c6ae99SBarry Smith       if (n1 >= 0) { /* directly below */
63247c6ae99SBarry Smith         x_t = x;
63347c6ae99SBarry Smith         y_t = ly[(n1 / m)];
63447c6ae99SBarry Smith         s_t = bases[n1] + x_t * y_t - (s_y + 1 - i) * x_t;
6358865f1eaSKarl Rupp         for (j = 0; j < x_t; j++) idx[nn++] = s_t++;
636ce00eea3SSatish Balay       } else if (ys - Ys > 0) {
637bff4a2f0SMatthew G. Knepley         if (by == DM_BOUNDARY_MIRROR) {
6388865f1eaSKarl Rupp           for (j = 0; j < x; j++) idx[nn++] = bases[rank] + x * (s_y - i + 1) + j;
639624904c4SBarry Smith         } else {
6408865f1eaSKarl Rupp           for (j = 0; j < x; j++) idx[nn++] = -1;
64147c6ae99SBarry Smith         }
642624904c4SBarry Smith       }
64347c6ae99SBarry Smith       if (n2 >= 0) { /* right below */
644ce00eea3SSatish Balay         x_t = lx[n2 % m];
64547c6ae99SBarry Smith         y_t = ly[(n2 / m)];
64647c6ae99SBarry Smith         s_t = bases[n2] + x_t * y_t - (s_y + 1 - i) * x_t;
6478865f1eaSKarl Rupp         for (j = 0; j < s_x; j++) idx[nn++] = s_t++;
648ce00eea3SSatish Balay       } else if (Xe - xe > 0 && ys - Ys > 0) {
6498865f1eaSKarl Rupp         for (j = 0; j < s_x; j++) idx[nn++] = -1;
65047c6ae99SBarry Smith       }
65147c6ae99SBarry Smith     }
65247c6ae99SBarry Smith 
65347c6ae99SBarry Smith     for (i = 0; i < y; i++) {
65447c6ae99SBarry Smith       if (n3 >= 0) { /* directly left */
655ce00eea3SSatish Balay         x_t = lx[n3 % m];
65647c6ae99SBarry Smith         /* y_t = y; */
65747c6ae99SBarry Smith         s_t = bases[n3] + (i + 1) * x_t - s_x;
6588865f1eaSKarl Rupp         for (j = 0; j < s_x; j++) idx[nn++] = s_t++;
659ce00eea3SSatish Balay       } else if (xs - Xs > 0) {
660bff4a2f0SMatthew G. Knepley         if (bx == DM_BOUNDARY_MIRROR) {
6618865f1eaSKarl Rupp           for (j = 0; j < s_x; j++) idx[nn++] = bases[rank] + x * i + s_x - j;
662624904c4SBarry Smith         } else {
6638865f1eaSKarl Rupp           for (j = 0; j < s_x; j++) idx[nn++] = -1;
66447c6ae99SBarry Smith         }
665624904c4SBarry Smith       }
66647c6ae99SBarry Smith 
6678865f1eaSKarl Rupp       for (j = 0; j < x; j++) idx[nn++] = xbase++; /* interior */
66847c6ae99SBarry Smith 
66947c6ae99SBarry Smith       if (n5 >= 0) { /* directly right */
670ce00eea3SSatish Balay         x_t = lx[n5 % m];
67147c6ae99SBarry Smith         /* y_t = y; */
67247c6ae99SBarry Smith         s_t = bases[n5] + (i)*x_t;
6738865f1eaSKarl Rupp         for (j = 0; j < s_x; j++) idx[nn++] = s_t++;
674ce00eea3SSatish Balay       } else if (Xe - xe > 0) {
675bff4a2f0SMatthew G. Knepley         if (bx == DM_BOUNDARY_MIRROR) {
6768865f1eaSKarl Rupp           for (j = 0; j < s_x; j++) idx[nn++] = bases[rank] + x * (i + 1) - 2 - j;
677624904c4SBarry Smith         } else {
6788865f1eaSKarl Rupp           for (j = 0; j < s_x; j++) idx[nn++] = -1;
67947c6ae99SBarry Smith         }
68047c6ae99SBarry Smith       }
681624904c4SBarry Smith     }
68247c6ae99SBarry Smith 
68347c6ae99SBarry Smith     for (i = 1; i <= s_y; i++) {
68447c6ae99SBarry Smith       if (n6 >= 0) { /* left above */
685ce00eea3SSatish Balay         x_t = lx[n6 % m];
68647c6ae99SBarry Smith         /* y_t = ly[(n6/m)]; */
68747c6ae99SBarry Smith         s_t = bases[n6] + (i)*x_t - s_x;
6888865f1eaSKarl Rupp         for (j = 0; j < s_x; j++) idx[nn++] = s_t++;
689ce00eea3SSatish Balay       } else if (xs - Xs > 0 && Ye - ye > 0) {
6908865f1eaSKarl Rupp         for (j = 0; j < s_x; j++) idx[nn++] = -1;
69147c6ae99SBarry Smith       }
69247c6ae99SBarry Smith       if (n7 >= 0) { /* directly above */
69347c6ae99SBarry Smith         x_t = x;
69447c6ae99SBarry Smith         /* y_t = ly[(n7/m)]; */
69547c6ae99SBarry Smith         s_t = bases[n7] + (i - 1) * x_t;
6968865f1eaSKarl Rupp         for (j = 0; j < x_t; j++) idx[nn++] = s_t++;
697ce00eea3SSatish Balay       } else if (Ye - ye > 0) {
698bff4a2f0SMatthew G. Knepley         if (by == DM_BOUNDARY_MIRROR) {
6998865f1eaSKarl Rupp           for (j = 0; j < x; j++) idx[nn++] = bases[rank] + x * (y - i - 1) + j;
700624904c4SBarry Smith         } else {
7018865f1eaSKarl Rupp           for (j = 0; j < x; j++) idx[nn++] = -1;
70247c6ae99SBarry Smith         }
703624904c4SBarry Smith       }
70447c6ae99SBarry Smith       if (n8 >= 0) { /* right above */
705ce00eea3SSatish Balay         x_t = lx[n8 % m];
70647c6ae99SBarry Smith         /* y_t = ly[(n8/m)]; */
70747c6ae99SBarry Smith         s_t = bases[n8] + (i - 1) * x_t;
7088865f1eaSKarl Rupp         for (j = 0; j < s_x; j++) idx[nn++] = s_t++;
709ce00eea3SSatish Balay       } else if (Xe - xe > 0 && Ye - ye > 0) {
7108865f1eaSKarl Rupp         for (j = 0; j < s_x; j++) idx[nn++] = -1;
71147c6ae99SBarry Smith       }
71247c6ae99SBarry Smith     }
71347c6ae99SBarry Smith   }
714ce00eea3SSatish Balay   /*
715ce00eea3SSatish Balay      Set the local to global ordering in the global vector, this allows use
716ce00eea3SSatish Balay      of VecSetValuesLocal().
717ce00eea3SSatish Balay   */
7189566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingCreate(comm, dof, nn, idx, PETSC_OWN_POINTER, &da->ltogmap));
71947c6ae99SBarry Smith 
7209566063dSJacob Faibussowitsch   PetscCall(PetscFree2(bases, ldims));
7219371c9d4SSatish Balay   dd->m = m;
7229371c9d4SSatish Balay   dd->n = n;
723ce00eea3SSatish Balay   /* note petsc expects xs/xe/Xs/Xe to be multiplied by #dofs in many places */
7249371c9d4SSatish Balay   dd->xs = xs * dof;
7259371c9d4SSatish Balay   dd->xe = xe * dof;
7269371c9d4SSatish Balay   dd->ys = ys;
7279371c9d4SSatish Balay   dd->ye = ye;
7289371c9d4SSatish Balay   dd->zs = 0;
7299371c9d4SSatish Balay   dd->ze = 1;
7309371c9d4SSatish Balay   dd->Xs = Xs * dof;
7319371c9d4SSatish Balay   dd->Xe = Xe * dof;
7329371c9d4SSatish Balay   dd->Ys = Ys;
7339371c9d4SSatish Balay   dd->Ye = Ye;
7349371c9d4SSatish Balay   dd->Zs = 0;
7359371c9d4SSatish Balay   dd->Ze = 1;
73647c6ae99SBarry Smith 
7379566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&local));
7389566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&global));
73947c6ae99SBarry Smith 
74047c6ae99SBarry Smith   dd->gtol      = gtol;
74147c6ae99SBarry Smith   dd->base      = base;
7429a42bb27SBarry Smith   da->ops->view = DMView_DA_2d;
7430298fd71SBarry Smith   dd->ltol      = NULL;
7440298fd71SBarry Smith   dd->ao        = NULL;
7453ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
74647c6ae99SBarry Smith }
74747c6ae99SBarry Smith 
74847c6ae99SBarry Smith /*@C
749aa219208SBarry Smith   DMDACreate2d -  Creates an object that will manage the communication of  two-dimensional
75047c6ae99SBarry Smith   regular array data that is distributed across some processors.
75147c6ae99SBarry Smith 
752d083f849SBarry Smith   Collective
75347c6ae99SBarry Smith 
75447c6ae99SBarry Smith   Input Parameters:
75547c6ae99SBarry Smith + comm         - MPI communicator
756*a4e35b19SJacob Faibussowitsch . bx           - type of ghost nodes the x array have. Use one of `DM_BOUNDARY_NONE`, `DM_BOUNDARY_GHOSTED`, `DM_BOUNDARY_PERIODIC`.
757*a4e35b19SJacob Faibussowitsch . by           - type of ghost nodes the y array have. Use one of `DM_BOUNDARY_NONE`, `DM_BOUNDARY_GHOSTED`, `DM_BOUNDARY_PERIODIC`.
758dce8aebaSBarry Smith . stencil_type - stencil type.  Use either `DMDA_STENCIL_BOX` or `DMDA_STENCIL_STAR`.
759*a4e35b19SJacob Faibussowitsch . M            - global dimension in x direction of the array
760*a4e35b19SJacob Faibussowitsch . N            - global dimension in y direction of the array
761*a4e35b19SJacob Faibussowitsch . m            - corresponding number of processors in x dimension (or `PETSC_DECIDE` to have calculated)
762*a4e35b19SJacob Faibussowitsch . n            - corresponding number of processors in y dimension (or `PETSC_DECIDE` to have calculated)
76347c6ae99SBarry Smith . dof          - number of degrees of freedom per node
76447c6ae99SBarry Smith . s            - stencil width
765*a4e35b19SJacob Faibussowitsch . lx           - arrays containing the number of nodes in each cell along the x coordinates, or `NULL`.
766*a4e35b19SJacob Faibussowitsch - ly           - arrays containing the number of nodes in each cell along the y coordinates, or `NULL`.
76747c6ae99SBarry Smith 
76847c6ae99SBarry Smith   Output Parameter:
76947c6ae99SBarry Smith . da - the resulting distributed array object
77047c6ae99SBarry Smith 
771dce8aebaSBarry Smith   Options Database Keys:
772dce8aebaSBarry Smith + -dm_view              - Calls `DMView()` at the conclusion of `DMDACreate2d()`
773e43dc8daSBarry Smith . -da_grid_x <nx>       - number of grid points in x direction
774e43dc8daSBarry Smith . -da_grid_y <ny>       - number of grid points in y direction
77547c6ae99SBarry Smith . -da_processors_x <nx> - number of processors in x direction
77647c6ae99SBarry Smith . -da_processors_y <ny> - number of processors in y direction
777e0f5d30fSBarry Smith . -da_refine_x <rx>     - refinement ratio in x direction
778e0f5d30fSBarry Smith . -da_refine_y <ry>     - refinement ratio in y direction
779e43dc8daSBarry Smith - -da_refine <n>        - refine the DMDA n times before creating
780e0f5d30fSBarry Smith 
78147c6ae99SBarry Smith   Level: beginner
78247c6ae99SBarry Smith 
78347c6ae99SBarry Smith   Notes:
784*a4e35b19SJacob Faibussowitsch   If `lx` or `ly` are non-null, these must be of length as `m` and `n`, and the corresponding
785*a4e35b19SJacob Faibussowitsch   `m` and `n` cannot be `PETSC_DECIDE`. The sum of the `lx` entries must be `M`, and the sum of
786*a4e35b19SJacob Faibussowitsch   the `ly` entries must be `N`.
787*a4e35b19SJacob Faibussowitsch 
788dce8aebaSBarry Smith   The stencil type `DMDA_STENCIL_STAR` with width 1 corresponds to the
789dce8aebaSBarry Smith   standard 5-pt stencil, while `DMDA_STENCIL_BOX` with width 1 denotes
79047c6ae99SBarry Smith   the standard 9-pt stencil.
79147c6ae99SBarry Smith 
792dce8aebaSBarry Smith   The array data itself is NOT stored in the `DMDA`, it is stored in `Vec` objects;
793dce8aebaSBarry Smith   The appropriate vector objects can be obtained with calls to `DMCreateGlobalVector()`
794dce8aebaSBarry Smith   and DMCreateLocalVector() and calls to `VecDuplicate()` if more are needed.
79547c6ae99SBarry Smith 
796dce8aebaSBarry Smith   You must call `DMSetUp()` after this call before using this `DM`.
797897f7067SBarry Smith 
798dce8aebaSBarry Smith   If you wish to use the options database to change values in the `DMDA` call `DMSetFromOptions()` after this call
799dce8aebaSBarry Smith   but before `DMSetUp()`.
800897f7067SBarry Smith 
801dce8aebaSBarry Smith .seealso: `DM`, `DMDA`, `DMDestroy()`, `DMView()`, `DMDACreate1d()`, `DMDACreate3d()`, `DMGlobalToLocalBegin()`, `DMDAGetRefinementFactor()`,
802db781477SPatrick Sanan           `DMGlobalToLocalEnd()`, `DMLocalToGlobalBegin()`, `DMLocalToLocalBegin()`, `DMLocalToLocalEnd()`, `DMDASetRefinementFactor()`,
803db781477SPatrick Sanan           `DMDAGetInfo()`, `DMCreateGlobalVector()`, `DMCreateLocalVector()`, `DMDACreateNaturalVector()`, `DMLoad()`, `DMDAGetOwnershipRanges()`,
804db781477SPatrick Sanan           `DMStagCreate2d()`
80547c6ae99SBarry Smith @*/
806d71ae5a4SJacob 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)
807d71ae5a4SJacob Faibussowitsch {
80847c6ae99SBarry Smith   PetscFunctionBegin;
8099566063dSJacob Faibussowitsch   PetscCall(DMDACreate(comm, da));
8109566063dSJacob Faibussowitsch   PetscCall(DMSetDimension(*da, 2));
8119566063dSJacob Faibussowitsch   PetscCall(DMDASetSizes(*da, M, N, 1));
8129566063dSJacob Faibussowitsch   PetscCall(DMDASetNumProcs(*da, m, n, PETSC_DECIDE));
8139566063dSJacob Faibussowitsch   PetscCall(DMDASetBoundaryType(*da, bx, by, DM_BOUNDARY_NONE));
8149566063dSJacob Faibussowitsch   PetscCall(DMDASetDof(*da, dof));
8159566063dSJacob Faibussowitsch   PetscCall(DMDASetStencilType(*da, stencil_type));
8169566063dSJacob Faibussowitsch   PetscCall(DMDASetStencilWidth(*da, s));
8179566063dSJacob Faibussowitsch   PetscCall(DMDASetOwnershipRanges(*da, lx, ly, NULL));
8183ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
81947c6ae99SBarry Smith }
820