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, >ol)); 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