1af0996ceSBarry Smith #include <petsc/private/dmdaimpl.h> /*I "petscdmda.h" I*/
2e30e807fSPeter Brune
3063654ddSPeter Brune /*@
412b4a537SBarry Smith DMDACreatePatchIS - Creates an index set corresponding to a logically rectangular patch of the `DMDA`.
5ff9846d9SPeter Brune
63b5e53cdSSajid Ali Collective
7063654ddSPeter Brune
8063654ddSPeter Brune Input Parameters:
9dce8aebaSBarry Smith + da - the `DMDA`
1012b4a537SBarry Smith . lower - a `MatStencil` with i, j and k entries corresponding to the lower corner of the patch
1112b4a537SBarry Smith . upper - a `MatStencil` with i, j and k entries corresponding to the upper corner of the patch
1212b4a537SBarry Smith - offproc - indicate whether the returned `IS` will contain off process indices
13063654ddSPeter Brune
142fe279fdSBarry Smith Output Parameter:
15dce8aebaSBarry Smith . is - the `IS` corresponding to the patch
16063654ddSPeter Brune
17063654ddSPeter Brune Level: developer
18063654ddSPeter Brune
193b5e53cdSSajid Ali Notes:
2012b4a537SBarry Smith This routine always returns an `IS` on the `DMDA` communicator.
213b5e53cdSSajid Ali
2212b4a537SBarry Smith If `offproc` is set to `PETSC_TRUE`,
2312b4a537SBarry Smith the routine returns an `IS` with all the indices requested regardless of whether these indices
2412b4a537SBarry Smith are present on the requesting MPI process or not. Thus, it is upon the caller to ensure that
2512b4a537SBarry Smith the indices returned in this mode are appropriate.
2612b4a537SBarry Smith
2712b4a537SBarry Smith If `offproc` is set to `PETSC_FALSE`,
2812b4a537SBarry Smith the `IS` only returns the subset of indices that are present on the requesting MPI process and there
2912b4a537SBarry Smith is no duplication of indices between multiple MPI processes.
3012b4a537SBarry Smith
3112b4a537SBarry Smith .seealso: [](sec_struct), `DM`, `DMDA`, `DMCreateDomainDecomposition()`, `DMCreateDomainDecompositionScatters()`
32063654ddSPeter Brune @*/
DMDACreatePatchIS(DM da,MatStencil * lower,MatStencil * upper,IS * is,PetscBool offproc)33d71ae5a4SJacob Faibussowitsch PetscErrorCode DMDACreatePatchIS(DM da, MatStencil *lower, MatStencil *upper, IS *is, PetscBool offproc)
34d71ae5a4SJacob Faibussowitsch {
35063654ddSPeter Brune PetscInt ms = 0, ns = 0, ps = 0;
363b5e53cdSSajid Ali PetscInt mw = 0, nw = 0, pw = 0;
37063654ddSPeter Brune PetscInt me = 1, ne = 1, pe = 1;
38063654ddSPeter Brune PetscInt mr = 0, nr = 0, pr = 0;
39ff9846d9SPeter Brune PetscInt ii, jj, kk;
40063654ddSPeter Brune PetscInt si, sj, sk;
4163bfac88SBarry Smith PetscInt i, k = 0, l, idx = 0;
42ff9846d9SPeter Brune PetscInt base;
43063654ddSPeter Brune PetscInt xm = 1, ym = 1, zm = 1;
44ff9846d9SPeter Brune PetscInt ox, oy, oz;
45063654ddSPeter Brune PetscInt m, n, p, M, N, P, dof;
463b5e53cdSSajid Ali const PetscInt *lx, *ly, *lz;
47063654ddSPeter Brune PetscInt nindices;
48063654ddSPeter Brune PetscInt *indices;
49063654ddSPeter Brune DM_DA *dd = (DM_DA *)da->data;
503b5e53cdSSajid Ali PetscBool skip_i = PETSC_TRUE, skip_j = PETSC_TRUE, skip_k = PETSC_TRUE;
513b5e53cdSSajid Ali PetscBool valid_j = PETSC_FALSE, valid_k = PETSC_FALSE; /* DMDA has at least 1 dimension */
52ff9846d9SPeter Brune
530adebc6cSBarry Smith PetscFunctionBegin;
549371c9d4SSatish Balay M = dd->M;
559371c9d4SSatish Balay N = dd->N;
569371c9d4SSatish Balay P = dd->P;
579371c9d4SSatish Balay m = dd->m;
589371c9d4SSatish Balay n = dd->n;
599371c9d4SSatish Balay p = dd->p;
60063654ddSPeter Brune dof = dd->w;
613b5e53cdSSajid Ali
623b5e53cdSSajid Ali nindices = -1;
633b5e53cdSSajid Ali if (PetscLikely(upper->i - lower->i)) {
643b5e53cdSSajid Ali nindices = nindices * (upper->i - lower->i);
653b5e53cdSSajid Ali skip_i = PETSC_FALSE;
663b5e53cdSSajid Ali }
673b5e53cdSSajid Ali if (N > 1) {
683b5e53cdSSajid Ali valid_j = PETSC_TRUE;
693b5e53cdSSajid Ali if (PetscLikely(upper->j - lower->j)) {
703b5e53cdSSajid Ali nindices = nindices * (upper->j - lower->j);
713b5e53cdSSajid Ali skip_j = PETSC_FALSE;
723b5e53cdSSajid Ali }
733b5e53cdSSajid Ali }
743b5e53cdSSajid Ali if (P > 1) {
753b5e53cdSSajid Ali valid_k = PETSC_TRUE;
763b5e53cdSSajid Ali if (PetscLikely(upper->k - lower->k)) {
773b5e53cdSSajid Ali nindices = nindices * (upper->k - lower->k);
783b5e53cdSSajid Ali skip_k = PETSC_FALSE;
793b5e53cdSSajid Ali }
803b5e53cdSSajid Ali }
81*966bd95aSPierre Jolivet PetscCheck(PetscLikely(nindices < 0), PetscObjectComm((PetscObject)da), PETSC_ERR_ARG_WRONG, "Lower and Upper stencils are identical! Please check inputs.");
82*966bd95aSPierre Jolivet if (PetscUnlikely(skip_i && skip_j && skip_k)) nindices = 0;
83*966bd95aSPierre Jolivet else nindices = -nindices;
843b5e53cdSSajid Ali
859566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nindices * dof, &indices));
869566063dSJacob Faibussowitsch PetscCall(DMDAGetOffset(da, &ox, &oy, &oz, NULL, NULL, NULL));
873b5e53cdSSajid Ali
883b5e53cdSSajid Ali if (!valid_k) {
893b5e53cdSSajid Ali upper->k = 0;
903b5e53cdSSajid Ali lower->k = 0;
913b5e53cdSSajid Ali }
923b5e53cdSSajid Ali if (!valid_j) {
933b5e53cdSSajid Ali upper->j = 0;
943b5e53cdSSajid Ali lower->j = 0;
953b5e53cdSSajid Ali }
963b5e53cdSSajid Ali
973b5e53cdSSajid Ali if (offproc) {
989566063dSJacob Faibussowitsch PetscCall(DMDAGetOwnershipRanges(da, &lx, &ly, &lz));
99063654ddSPeter Brune /* start at index 0 on processor 0 */
100063654ddSPeter Brune mr = 0;
101063654ddSPeter Brune nr = 0;
102063654ddSPeter Brune pr = 0;
103063654ddSPeter Brune ms = 0;
104063654ddSPeter Brune ns = 0;
105063654ddSPeter Brune ps = 0;
106063654ddSPeter Brune if (lx) me = lx[0];
107063654ddSPeter Brune if (ly) ne = ly[0];
108063654ddSPeter Brune if (lz) pe = lz[0];
1093b5e53cdSSajid Ali /*
1103b5e53cdSSajid Ali If no indices are to be returned, create an empty is,
1113b5e53cdSSajid Ali this prevents hanging in while loops
1123b5e53cdSSajid Ali */
1133b5e53cdSSajid Ali if (skip_i && skip_j && skip_k) goto createis;
1143b5e53cdSSajid Ali /*
1153b5e53cdSSajid Ali do..while loops to ensure the block gets entered once,
1163b5e53cdSSajid Ali regardless of control condition being met, necessary for
1173b5e53cdSSajid Ali cases when a subset of skip_i/j/k is true
1183b5e53cdSSajid Ali */
1199371c9d4SSatish Balay if (skip_k) k = upper->k - oz;
1209371c9d4SSatish Balay else k = lower->k - oz;
1213b5e53cdSSajid Ali do {
12263bfac88SBarry Smith PetscInt j;
12363bfac88SBarry Smith
1249371c9d4SSatish Balay if (skip_j) j = upper->j - oy;
1259371c9d4SSatish Balay else j = lower->j - oy;
1263b5e53cdSSajid Ali do {
1279371c9d4SSatish Balay if (skip_i) i = upper->i - ox;
1289371c9d4SSatish Balay else i = lower->i - ox;
1293b5e53cdSSajid Ali do {
130063654ddSPeter Brune /* "actual" indices rather than ones outside of the domain */
131063654ddSPeter Brune ii = i;
132063654ddSPeter Brune jj = j;
133063654ddSPeter Brune kk = k;
134063654ddSPeter Brune if (ii < 0) ii = M + ii;
135063654ddSPeter Brune if (jj < 0) jj = N + jj;
136063654ddSPeter Brune if (kk < 0) kk = P + kk;
137063654ddSPeter Brune if (ii > M - 1) ii = ii - M;
138063654ddSPeter Brune if (jj > N - 1) jj = jj - N;
139063654ddSPeter Brune if (kk > P - 1) kk = kk - P;
140063654ddSPeter Brune /* gone out of processor range on x axis */
141063654ddSPeter Brune while (ii > me - 1 || ii < ms) {
142063654ddSPeter Brune if (mr == m - 1) {
143063654ddSPeter Brune ms = 0;
144063654ddSPeter Brune me = lx[0];
145063654ddSPeter Brune mr = 0;
146063654ddSPeter Brune } else {
147063654ddSPeter Brune mr++;
148063654ddSPeter Brune ms = me;
149063654ddSPeter Brune me += lx[mr];
150063654ddSPeter Brune }
151063654ddSPeter Brune }
152063654ddSPeter Brune /* gone out of processor range on y axis */
153063654ddSPeter Brune while (jj > ne - 1 || jj < ns) {
154063654ddSPeter Brune if (nr == n - 1) {
155063654ddSPeter Brune ns = 0;
156063654ddSPeter Brune ne = ly[0];
157063654ddSPeter Brune nr = 0;
158063654ddSPeter Brune } else {
159063654ddSPeter Brune nr++;
160063654ddSPeter Brune ns = ne;
161063654ddSPeter Brune ne += ly[nr];
162063654ddSPeter Brune }
163063654ddSPeter Brune }
164063654ddSPeter Brune /* gone out of processor range on z axis */
165063654ddSPeter Brune while (kk > pe - 1 || kk < ps) {
166063654ddSPeter Brune if (pr == p - 1) {
167063654ddSPeter Brune ps = 0;
168063654ddSPeter Brune pe = lz[0];
169063654ddSPeter Brune pr = 0;
170063654ddSPeter Brune } else {
171063654ddSPeter Brune pr++;
172063654ddSPeter Brune ps = pe;
173063654ddSPeter Brune pe += lz[pr];
174063654ddSPeter Brune }
175063654ddSPeter Brune }
176063654ddSPeter Brune /* compute the vector base on owning processor */
177063654ddSPeter Brune xm = me - ms;
178063654ddSPeter Brune ym = ne - ns;
179063654ddSPeter Brune zm = pe - ps;
180b0bff951SPeter Brune base = ms * ym * zm + ns * M * zm + ps * M * N;
181063654ddSPeter Brune /* compute the local coordinates on owning processor */
182063654ddSPeter Brune si = ii - ms;
183063654ddSPeter Brune sj = jj - ns;
184063654ddSPeter Brune sk = kk - ps;
185063654ddSPeter Brune for (l = 0; l < dof; l++) {
186063654ddSPeter Brune indices[idx] = l + dof * (base + si + xm * sj + xm * ym * sk);
187ff9846d9SPeter Brune idx++;
188ff9846d9SPeter Brune }
1893b5e53cdSSajid Ali i++;
1903b5e53cdSSajid Ali } while (i < upper->i - ox);
1913b5e53cdSSajid Ali j++;
1923b5e53cdSSajid Ali } while (j < upper->j - oy);
1933b5e53cdSSajid Ali k++;
1943b5e53cdSSajid Ali } while (k < upper->k - oz);
1953b5e53cdSSajid Ali }
1963b5e53cdSSajid Ali
1973b5e53cdSSajid Ali if (!offproc) {
1989566063dSJacob Faibussowitsch PetscCall(DMDAGetCorners(da, &ms, &ns, &ps, &mw, &nw, &pw));
1993b5e53cdSSajid Ali me = ms + mw;
2003b5e53cdSSajid Ali if (N > 1) ne = ns + nw;
2013b5e53cdSSajid Ali if (P > 1) pe = ps + pw;
2023b5e53cdSSajid Ali /* Account for DM offsets */
2039371c9d4SSatish Balay ms = ms - ox;
2049371c9d4SSatish Balay me = me - ox;
2059371c9d4SSatish Balay ns = ns - oy;
2069371c9d4SSatish Balay ne = ne - oy;
2079371c9d4SSatish Balay ps = ps - oz;
2089371c9d4SSatish Balay pe = pe - oz;
2093b5e53cdSSajid Ali
2103b5e53cdSSajid Ali /* compute the vector base on owning processor */
2113b5e53cdSSajid Ali xm = me - ms;
2123b5e53cdSSajid Ali ym = ne - ns;
2133b5e53cdSSajid Ali zm = pe - ps;
2143b5e53cdSSajid Ali base = ms * ym * zm + ns * M * zm + ps * M * N;
2153b5e53cdSSajid Ali /*
2163b5e53cdSSajid Ali if no indices are to be returned, create an empty is,
2173b5e53cdSSajid Ali this prevents hanging in while loops
2183b5e53cdSSajid Ali */
2193b5e53cdSSajid Ali if (skip_i && skip_j && skip_k) goto createis;
2203b5e53cdSSajid Ali /*
2213b5e53cdSSajid Ali do..while loops to ensure the block gets entered once,
2223b5e53cdSSajid Ali regardless of control condition being met, necessary for
2233b5e53cdSSajid Ali cases when a subset of skip_i/j/k is true
2243b5e53cdSSajid Ali */
2259371c9d4SSatish Balay if (skip_k) k = upper->k - oz;
2269371c9d4SSatish Balay else k = lower->k - oz;
2273b5e53cdSSajid Ali do {
22863bfac88SBarry Smith PetscInt j;
22963bfac88SBarry Smith
2309371c9d4SSatish Balay if (skip_j) j = upper->j - oy;
2319371c9d4SSatish Balay else j = lower->j - oy;
2323b5e53cdSSajid Ali do {
2339371c9d4SSatish Balay if (skip_i) i = upper->i - ox;
2349371c9d4SSatish Balay else i = lower->i - ox;
2353b5e53cdSSajid Ali do {
2363b5e53cdSSajid Ali if (k >= ps && k <= pe - 1) {
2373b5e53cdSSajid Ali if (j >= ns && j <= ne - 1) {
2383b5e53cdSSajid Ali if (i >= ms && i <= me - 1) {
2393b5e53cdSSajid Ali /* compute the local coordinates on owning processor */
2403b5e53cdSSajid Ali si = i - ms;
2413b5e53cdSSajid Ali sj = j - ns;
2423b5e53cdSSajid Ali sk = k - ps;
2433b5e53cdSSajid Ali for (l = 0; l < dof; l++) {
2443b5e53cdSSajid Ali indices[idx] = l + dof * (base + si + xm * sj + xm * ym * sk);
2453b5e53cdSSajid Ali idx++;
246ff9846d9SPeter Brune }
247ff9846d9SPeter Brune }
248063654ddSPeter Brune }
2493b5e53cdSSajid Ali }
2503b5e53cdSSajid Ali i++;
2513b5e53cdSSajid Ali } while (i < upper->i - ox);
2523b5e53cdSSajid Ali j++;
2533b5e53cdSSajid Ali } while (j < upper->j - oy);
2543b5e53cdSSajid Ali k++;
2553b5e53cdSSajid Ali } while (k < upper->k - oz);
2563b5e53cdSSajid Ali
257835f2295SStefano Zampini PetscCall(PetscRealloc(idx * sizeof(PetscInt), &indices));
2583b5e53cdSSajid Ali }
2593b5e53cdSSajid Ali
2603b5e53cdSSajid Ali createis:
2619566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)da), idx, indices, PETSC_OWN_POINTER, is));
2623ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
263ff9846d9SPeter Brune }
264ff9846d9SPeter Brune
DMDASubDomainDA_Private(DM dm,PetscInt * nlocal,DM ** sdm)26566976f2fSJacob Faibussowitsch static PetscErrorCode DMDASubDomainDA_Private(DM dm, PetscInt *nlocal, DM **sdm)
266d71ae5a4SJacob Faibussowitsch {
26790c77898SPeter Brune DM *da;
26890c77898SPeter Brune PetscInt dim, size, i, j, k, idx;
269e30e807fSPeter Brune DMDALocalInfo info;
270ff9846d9SPeter Brune PetscInt xsize, ysize, zsize;
271e30e807fSPeter Brune PetscInt xo, yo, zo;
27290c77898SPeter Brune PetscInt xs, ys, zs;
27390c77898SPeter Brune PetscInt xm = 1, ym = 1, zm = 1;
2747ddda789SPeter Brune PetscInt xol, yol, zol;
27590c77898SPeter Brune PetscInt m = 1, n = 1, p = 1;
27690c77898SPeter Brune PetscInt M, N, P;
27790c77898SPeter Brune PetscInt pm, mtmp;
278e30e807fSPeter Brune
279e30e807fSPeter Brune PetscFunctionBegin;
2809566063dSJacob Faibussowitsch PetscCall(DMDAGetLocalInfo(dm, &info));
2819566063dSJacob Faibussowitsch PetscCall(DMDAGetOverlap(dm, &xol, &yol, &zol));
2829566063dSJacob Faibussowitsch PetscCall(DMDAGetNumLocalSubDomains(dm, &size));
2839566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(size, &da));
2847ddda789SPeter Brune
28590c77898SPeter Brune if (nlocal) *nlocal = size;
286e30e807fSPeter Brune
28790c77898SPeter Brune dim = info.dim;
288e30e807fSPeter Brune
28990c77898SPeter Brune M = info.xm;
29090c77898SPeter Brune N = info.ym;
29190c77898SPeter Brune P = info.zm;
29290c77898SPeter Brune
29390c77898SPeter Brune if (dim == 1) {
29490c77898SPeter Brune m = size;
29590c77898SPeter Brune } else if (dim == 2) {
29690c77898SPeter Brune m = (PetscInt)(0.5 + PetscSqrtReal(((PetscReal)M) * ((PetscReal)size) / ((PetscReal)N)));
29790c77898SPeter Brune while (m > 0) {
29890c77898SPeter Brune n = size / m;
29990c77898SPeter Brune if (m * n * p == size) break;
30090c77898SPeter Brune m--;
30190c77898SPeter Brune }
30290c77898SPeter Brune } else if (dim == 3) {
3039371c9d4SSatish Balay n = (PetscInt)(0.5 + PetscPowReal(((PetscReal)N * N) * ((PetscReal)size) / ((PetscReal)P * M), (PetscReal)(1. / 3.)));
3049371c9d4SSatish Balay if (!n) n = 1;
30590c77898SPeter Brune while (n > 0) {
30690c77898SPeter Brune pm = size / n;
30790c77898SPeter Brune if (n * pm == size) break;
30890c77898SPeter Brune n--;
30990c77898SPeter Brune }
31090c77898SPeter Brune if (!n) n = 1;
31190c77898SPeter Brune m = (PetscInt)(0.5 + PetscSqrtReal(((PetscReal)M) * ((PetscReal)size) / ((PetscReal)P * n)));
31290c77898SPeter Brune if (!m) m = 1;
31390c77898SPeter Brune while (m > 0) {
31490c77898SPeter Brune p = size / (m * n);
31590c77898SPeter Brune if (m * n * p == size) break;
31690c77898SPeter Brune m--;
31790c77898SPeter Brune }
3189371c9d4SSatish Balay if (M > P && m < p) {
3199371c9d4SSatish Balay mtmp = m;
3209371c9d4SSatish Balay m = p;
3219371c9d4SSatish Balay p = mtmp;
3229371c9d4SSatish Balay }
32390c77898SPeter Brune }
32490c77898SPeter Brune
32590c77898SPeter Brune zs = info.zs;
32690c77898SPeter Brune idx = 0;
32790c77898SPeter Brune for (k = 0; k < p; k++) {
32890c77898SPeter Brune ys = info.ys;
32990c77898SPeter Brune for (j = 0; j < n; j++) {
33090c77898SPeter Brune xs = info.xs;
33190c77898SPeter Brune for (i = 0; i < m; i++) {
33290c77898SPeter Brune if (dim == 1) {
33390c77898SPeter Brune xm = M / m + ((M % m) > i);
33490c77898SPeter Brune } else if (dim == 2) {
33590c77898SPeter Brune xm = M / m + ((M % m) > i);
33690c77898SPeter Brune ym = N / n + ((N % n) > j);
33790c77898SPeter Brune } else if (dim == 3) {
33890c77898SPeter Brune xm = M / m + ((M % m) > i);
33990c77898SPeter Brune ym = N / n + ((N % n) > j);
34090c77898SPeter Brune zm = P / p + ((P % p) > k);
34190c77898SPeter Brune }
34290c77898SPeter Brune
34390c77898SPeter Brune xsize = xm;
34490c77898SPeter Brune ysize = ym;
34590c77898SPeter Brune zsize = zm;
34690c77898SPeter Brune xo = xs;
34790c77898SPeter Brune yo = ys;
34890c77898SPeter Brune zo = zs;
34990c77898SPeter Brune
350f4f49eeaSPierre Jolivet PetscCall(DMDACreate(PETSC_COMM_SELF, &da[idx]));
3519566063dSJacob Faibussowitsch PetscCall(DMSetOptionsPrefix(da[idx], "sub_"));
3529566063dSJacob Faibussowitsch PetscCall(DMSetDimension(da[idx], info.dim));
3539566063dSJacob Faibussowitsch PetscCall(DMDASetDof(da[idx], info.dof));
35490c77898SPeter Brune
3559566063dSJacob Faibussowitsch PetscCall(DMDASetStencilType(da[idx], info.st));
3569566063dSJacob Faibussowitsch PetscCall(DMDASetStencilWidth(da[idx], info.sw));
35790c77898SPeter Brune
358bff4a2f0SMatthew G. Knepley if (info.bx == DM_BOUNDARY_PERIODIC || (xs != 0)) {
3597ddda789SPeter Brune xsize += xol;
3607ddda789SPeter Brune xo -= xol;
361e30e807fSPeter Brune }
362bff4a2f0SMatthew G. Knepley if (info.by == DM_BOUNDARY_PERIODIC || (ys != 0)) {
3637ddda789SPeter Brune ysize += yol;
3647ddda789SPeter Brune yo -= yol;
365e30e807fSPeter Brune }
366bff4a2f0SMatthew G. Knepley if (info.bz == DM_BOUNDARY_PERIODIC || (zs != 0)) {
3677ddda789SPeter Brune zsize += zol;
3687ddda789SPeter Brune zo -= zol;
369e30e807fSPeter Brune }
370e30e807fSPeter Brune
371bff4a2f0SMatthew G. Knepley if (info.bx == DM_BOUNDARY_PERIODIC || (xs + xm != info.mx)) xsize += xol;
372bff4a2f0SMatthew G. Knepley if (info.by == DM_BOUNDARY_PERIODIC || (ys + ym != info.my)) ysize += yol;
373bff4a2f0SMatthew G. Knepley if (info.bz == DM_BOUNDARY_PERIODIC || (zs + zm != info.mz)) zsize += zol;
3748865f1eaSKarl Rupp
375bff4a2f0SMatthew G. Knepley if (info.bx != DM_BOUNDARY_PERIODIC) {
37690c77898SPeter Brune if (xo < 0) {
37790c77898SPeter Brune xsize += xo;
37890c77898SPeter Brune xo = 0;
37990c77898SPeter Brune }
380ad540459SPierre Jolivet if (xo + xsize > info.mx - 1) xsize -= xo + xsize - info.mx;
38190c77898SPeter Brune }
382bff4a2f0SMatthew G. Knepley if (info.by != DM_BOUNDARY_PERIODIC) {
38390c77898SPeter Brune if (yo < 0) {
38490c77898SPeter Brune ysize += yo;
38590c77898SPeter Brune yo = 0;
38690c77898SPeter Brune }
387ad540459SPierre Jolivet if (yo + ysize > info.my - 1) ysize -= yo + ysize - info.my;
38890c77898SPeter Brune }
389bff4a2f0SMatthew G. Knepley if (info.bz != DM_BOUNDARY_PERIODIC) {
39090c77898SPeter Brune if (zo < 0) {
39190c77898SPeter Brune zsize += zo;
39290c77898SPeter Brune zo = 0;
39390c77898SPeter Brune }
394ad540459SPierre Jolivet if (zo + zsize > info.mz - 1) zsize -= zo + zsize - info.mz;
39590c77898SPeter Brune }
39690c77898SPeter Brune
3979566063dSJacob Faibussowitsch PetscCall(DMDASetSizes(da[idx], xsize, ysize, zsize));
3989566063dSJacob Faibussowitsch PetscCall(DMDASetNumProcs(da[idx], 1, 1, 1));
3999566063dSJacob Faibussowitsch PetscCall(DMDASetBoundaryType(da[idx], DM_BOUNDARY_GHOSTED, DM_BOUNDARY_GHOSTED, DM_BOUNDARY_GHOSTED));
400e30e807fSPeter Brune
401e30e807fSPeter Brune /* set up as a block instead */
4029566063dSJacob Faibussowitsch PetscCall(DMSetUp(da[idx]));
403e30e807fSPeter Brune
40440234c92SPeter Brune /* nonoverlapping region */
4059566063dSJacob Faibussowitsch PetscCall(DMDASetNonOverlappingRegion(da[idx], xs, ys, zs, xm, ym, zm));
40640234c92SPeter Brune
40795c13181SPeter Brune /* this alters the behavior of DMDAGetInfo, DMDAGetLocalInfo, DMDAGetCorners, and DMDAGetGhostedCorners and should be used with care */
4089566063dSJacob Faibussowitsch PetscCall(DMDASetOffset(da[idx], xo, yo, zo, info.mx, info.my, info.mz));
40990c77898SPeter Brune xs += xm;
41090c77898SPeter Brune idx++;
41190c77898SPeter Brune }
41290c77898SPeter Brune ys += ym;
41390c77898SPeter Brune }
41490c77898SPeter Brune zs += zm;
41590c77898SPeter Brune }
41690c77898SPeter Brune *sdm = da;
4173ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
418e30e807fSPeter Brune }
419e30e807fSPeter Brune
420e30e807fSPeter Brune /*
421e30e807fSPeter Brune Fills the local vector problem on the subdomain from the global problem.
422e30e807fSPeter Brune
423285ae305SPeter Brune Right now this assumes one subdomain per processor.
424285ae305SPeter Brune
425e30e807fSPeter Brune */
DMCreateDomainDecompositionScatters_DA(DM dm,PetscInt nsubdms,DM * subdms,VecScatter ** iscat,VecScatter ** oscat,VecScatter ** lscat)426d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateDomainDecompositionScatters_DA(DM dm, PetscInt nsubdms, DM *subdms, VecScatter **iscat, VecScatter **oscat, VecScatter **lscat)
427d71ae5a4SJacob Faibussowitsch {
428285ae305SPeter Brune DMDALocalInfo info, subinfo;
429e30e807fSPeter Brune DM subdm;
430285ae305SPeter Brune MatStencil upper, lower;
431285ae305SPeter Brune IS idis, isis, odis, osis, gdis;
432285ae305SPeter Brune Vec svec, dvec, slvec;
43340234c92SPeter Brune PetscInt xm, ym, zm, xs, ys, zs;
43490c77898SPeter Brune PetscInt i;
4353b5e53cdSSajid Ali PetscBool patchis_offproc = PETSC_TRUE;
436e30e807fSPeter Brune
437e30e807fSPeter Brune PetscFunctionBegin;
438e30e807fSPeter Brune /* allocate the arrays of scatters */
4399566063dSJacob Faibussowitsch if (iscat) PetscCall(PetscMalloc1(nsubdms, iscat));
4409566063dSJacob Faibussowitsch if (oscat) PetscCall(PetscMalloc1(nsubdms, oscat));
4419566063dSJacob Faibussowitsch if (lscat) PetscCall(PetscMalloc1(nsubdms, lscat));
442e30e807fSPeter Brune
4439566063dSJacob Faibussowitsch PetscCall(DMDAGetLocalInfo(dm, &info));
44490c77898SPeter Brune for (i = 0; i < nsubdms; i++) {
44590c77898SPeter Brune subdm = subdms[i];
4469566063dSJacob Faibussowitsch PetscCall(DMDAGetLocalInfo(subdm, &subinfo));
4479566063dSJacob Faibussowitsch PetscCall(DMDAGetNonOverlappingRegion(subdm, &xs, &ys, &zs, &xm, &ym, &zm));
448e30e807fSPeter Brune
449285ae305SPeter Brune /* create the global and subdomain index sets for the inner domain */
45040234c92SPeter Brune lower.i = xs;
45140234c92SPeter Brune lower.j = ys;
45240234c92SPeter Brune lower.k = zs;
45340234c92SPeter Brune upper.i = xs + xm;
45440234c92SPeter Brune upper.j = ys + ym;
45540234c92SPeter Brune upper.k = zs + zm;
4569566063dSJacob Faibussowitsch PetscCall(DMDACreatePatchIS(dm, &lower, &upper, &idis, patchis_offproc));
4579566063dSJacob Faibussowitsch PetscCall(DMDACreatePatchIS(subdm, &lower, &upper, &isis, patchis_offproc));
458e30e807fSPeter Brune
459285ae305SPeter Brune /* create the global and subdomain index sets for the outer subdomain */
460285ae305SPeter Brune lower.i = subinfo.xs;
461285ae305SPeter Brune lower.j = subinfo.ys;
462285ae305SPeter Brune lower.k = subinfo.zs;
463285ae305SPeter Brune upper.i = subinfo.xs + subinfo.xm;
464285ae305SPeter Brune upper.j = subinfo.ys + subinfo.ym;
465285ae305SPeter Brune upper.k = subinfo.zs + subinfo.zm;
4669566063dSJacob Faibussowitsch PetscCall(DMDACreatePatchIS(dm, &lower, &upper, &odis, patchis_offproc));
4679566063dSJacob Faibussowitsch PetscCall(DMDACreatePatchIS(subdm, &lower, &upper, &osis, patchis_offproc));
468e30e807fSPeter Brune
469285ae305SPeter Brune /* global and subdomain ISes for the local indices of the subdomain */
470285ae305SPeter Brune /* todo - make this not loop over at nonperiodic boundaries, which will be more involved */
471285ae305SPeter Brune lower.i = subinfo.gxs;
472285ae305SPeter Brune lower.j = subinfo.gys;
473285ae305SPeter Brune lower.k = subinfo.gzs;
474285ae305SPeter Brune upper.i = subinfo.gxs + subinfo.gxm;
475285ae305SPeter Brune upper.j = subinfo.gys + subinfo.gym;
476285ae305SPeter Brune upper.k = subinfo.gzs + subinfo.gzm;
4779566063dSJacob Faibussowitsch PetscCall(DMDACreatePatchIS(dm, &lower, &upper, &gdis, patchis_offproc));
478e30e807fSPeter Brune
479e30e807fSPeter Brune /* form the scatter */
4809566063dSJacob Faibussowitsch PetscCall(DMGetGlobalVector(dm, &dvec));
4819566063dSJacob Faibussowitsch PetscCall(DMGetGlobalVector(subdm, &svec));
4829566063dSJacob Faibussowitsch PetscCall(DMGetLocalVector(subdm, &slvec));
483e30e807fSPeter Brune
4849566063dSJacob Faibussowitsch if (iscat) PetscCall(VecScatterCreate(dvec, idis, svec, isis, &(*iscat)[i]));
4859566063dSJacob Faibussowitsch if (oscat) PetscCall(VecScatterCreate(dvec, odis, svec, osis, &(*oscat)[i]));
4869566063dSJacob Faibussowitsch if (lscat) PetscCall(VecScatterCreate(dvec, gdis, slvec, NULL, &(*lscat)[i]));
487e30e807fSPeter Brune
4889566063dSJacob Faibussowitsch PetscCall(DMRestoreGlobalVector(dm, &dvec));
4899566063dSJacob Faibussowitsch PetscCall(DMRestoreGlobalVector(subdm, &svec));
4909566063dSJacob Faibussowitsch PetscCall(DMRestoreLocalVector(subdm, &slvec));
491e30e807fSPeter Brune
4929566063dSJacob Faibussowitsch PetscCall(ISDestroy(&idis));
4939566063dSJacob Faibussowitsch PetscCall(ISDestroy(&isis));
494e30e807fSPeter Brune
4959566063dSJacob Faibussowitsch PetscCall(ISDestroy(&odis));
4969566063dSJacob Faibussowitsch PetscCall(ISDestroy(&osis));
497e30e807fSPeter Brune
4989566063dSJacob Faibussowitsch PetscCall(ISDestroy(&gdis));
49990c77898SPeter Brune }
5003ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
501e30e807fSPeter Brune }
502e30e807fSPeter Brune
DMDASubDomainIS_Private(DM dm,PetscInt n,DM * subdm,IS ** iis,IS ** ois)50366976f2fSJacob Faibussowitsch static PetscErrorCode DMDASubDomainIS_Private(DM dm, PetscInt n, DM *subdm, IS **iis, IS **ois)
504d71ae5a4SJacob Faibussowitsch {
50590c77898SPeter Brune PetscInt i;
506e30e807fSPeter Brune DMDALocalInfo info, subinfo;
507285ae305SPeter Brune MatStencil lower, upper;
5083b5e53cdSSajid Ali PetscBool patchis_offproc = PETSC_TRUE;
509e30e807fSPeter Brune
510e30e807fSPeter Brune PetscFunctionBegin;
5119566063dSJacob Faibussowitsch PetscCall(DMDAGetLocalInfo(dm, &info));
5129566063dSJacob Faibussowitsch if (iis) PetscCall(PetscMalloc1(n, iis));
5139566063dSJacob Faibussowitsch if (ois) PetscCall(PetscMalloc1(n, ois));
514e30e807fSPeter Brune
51590c77898SPeter Brune for (i = 0; i < n; i++) {
5169566063dSJacob Faibussowitsch PetscCall(DMDAGetLocalInfo(subdm[i], &subinfo));
51790c77898SPeter Brune if (iis) {
518285ae305SPeter Brune /* create the inner IS */
519285ae305SPeter Brune lower.i = info.xs;
520285ae305SPeter Brune lower.j = info.ys;
521285ae305SPeter Brune lower.k = info.zs;
522285ae305SPeter Brune upper.i = info.xs + info.xm;
523285ae305SPeter Brune upper.j = info.ys + info.ym;
524285ae305SPeter Brune upper.k = info.zs + info.zm;
5259566063dSJacob Faibussowitsch PetscCall(DMDACreatePatchIS(dm, &lower, &upper, &(*iis)[i], patchis_offproc));
52690c77898SPeter Brune }
527e30e807fSPeter Brune
52890c77898SPeter Brune if (ois) {
529285ae305SPeter Brune /* create the outer IS */
530285ae305SPeter Brune lower.i = subinfo.xs;
531285ae305SPeter Brune lower.j = subinfo.ys;
532285ae305SPeter Brune lower.k = subinfo.zs;
533285ae305SPeter Brune upper.i = subinfo.xs + subinfo.xm;
534285ae305SPeter Brune upper.j = subinfo.ys + subinfo.ym;
535285ae305SPeter Brune upper.k = subinfo.zs + subinfo.zm;
5369566063dSJacob Faibussowitsch PetscCall(DMDACreatePatchIS(dm, &lower, &upper, &(*ois)[i], patchis_offproc));
53790c77898SPeter Brune }
53890c77898SPeter Brune }
5393ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
540e30e807fSPeter Brune }
541e30e807fSPeter Brune
DMCreateDomainDecomposition_DA(DM dm,PetscInt * len,char *** names,IS ** iis,IS ** ois,DM ** subdm)542d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateDomainDecomposition_DA(DM dm, PetscInt *len, char ***names, IS **iis, IS **ois, DM **subdm)
543d71ae5a4SJacob Faibussowitsch {
54466976f2fSJacob Faibussowitsch DM *sdm = NULL;
54566976f2fSJacob Faibussowitsch PetscInt n = 0, i;
5460a696f66SPeter Brune
5470adebc6cSBarry Smith PetscFunctionBegin;
5489566063dSJacob Faibussowitsch PetscCall(DMDASubDomainDA_Private(dm, &n, &sdm));
54990c77898SPeter Brune if (names) {
5509566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(n, names));
551ea78f98cSLisandro Dalcin for (i = 0; i < n; i++) (*names)[i] = NULL;
552e30e807fSPeter Brune }
5539566063dSJacob Faibussowitsch PetscCall(DMDASubDomainIS_Private(dm, n, sdm, iis, ois));
55490c77898SPeter Brune if (subdm) *subdm = sdm;
555e2c616c8SPeter Brune else {
55648a46eb9SPierre Jolivet for (i = 0; i < n; i++) PetscCall(DMDestroy(&sdm[i]));
557e2c616c8SPeter Brune }
55890c77898SPeter Brune if (len) *len = n;
5593ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
560e30e807fSPeter Brune }
561