xref: /petsc/src/dm/impls/da/dadd.c (revision f4f49eeac7efa77fffa46b7ff95a3ed169f659ed)
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 @*/
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;
413b5e53cdSSajid Ali   PetscInt        i, j, k, 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   }
813b5e53cdSSajid Ali   if (PetscLikely(nindices < 0)) {
823b5e53cdSSajid Ali     if (PetscUnlikely(skip_i && skip_j && skip_k)) {
833b5e53cdSSajid Ali       nindices = 0;
843b5e53cdSSajid Ali     } else nindices = nindices * (-1);
853b5e53cdSSajid Ali   } else SETERRQ(PetscObjectComm((PetscObject)da), PETSC_ERR_ARG_WRONG, "Lower and Upper stencils are identical! Please check inputs.");
863b5e53cdSSajid Ali 
879566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(nindices * dof, &indices));
889566063dSJacob Faibussowitsch   PetscCall(DMDAGetOffset(da, &ox, &oy, &oz, NULL, NULL, NULL));
893b5e53cdSSajid Ali 
903b5e53cdSSajid Ali   if (!valid_k) {
913b5e53cdSSajid Ali     k        = 0;
923b5e53cdSSajid Ali     upper->k = 0;
933b5e53cdSSajid Ali     lower->k = 0;
943b5e53cdSSajid Ali   }
953b5e53cdSSajid Ali   if (!valid_j) {
963b5e53cdSSajid Ali     j        = 0;
973b5e53cdSSajid Ali     upper->j = 0;
983b5e53cdSSajid Ali     lower->j = 0;
993b5e53cdSSajid Ali   }
1003b5e53cdSSajid Ali 
1013b5e53cdSSajid Ali   if (offproc) {
1029566063dSJacob Faibussowitsch     PetscCall(DMDAGetOwnershipRanges(da, &lx, &ly, &lz));
103063654ddSPeter Brune     /* start at index 0 on processor 0 */
104063654ddSPeter Brune     mr = 0;
105063654ddSPeter Brune     nr = 0;
106063654ddSPeter Brune     pr = 0;
107063654ddSPeter Brune     ms = 0;
108063654ddSPeter Brune     ns = 0;
109063654ddSPeter Brune     ps = 0;
110063654ddSPeter Brune     if (lx) me = lx[0];
111063654ddSPeter Brune     if (ly) ne = ly[0];
112063654ddSPeter Brune     if (lz) pe = lz[0];
1133b5e53cdSSajid Ali     /*
1143b5e53cdSSajid Ali        If no indices are to be returned, create an empty is,
1153b5e53cdSSajid Ali        this prevents hanging in while loops
1163b5e53cdSSajid Ali     */
1173b5e53cdSSajid Ali     if (skip_i && skip_j && skip_k) goto createis;
1183b5e53cdSSajid Ali     /*
1193b5e53cdSSajid Ali        do..while loops to ensure the block gets entered once,
1203b5e53cdSSajid Ali        regardless of control condition being met, necessary for
1213b5e53cdSSajid Ali        cases when a subset of skip_i/j/k is true
1223b5e53cdSSajid Ali     */
1239371c9d4SSatish Balay     if (skip_k) k = upper->k - oz;
1249371c9d4SSatish Balay     else k = lower->k - oz;
1253b5e53cdSSajid Ali     do {
1269371c9d4SSatish Balay       if (skip_j) j = upper->j - oy;
1279371c9d4SSatish Balay       else j = lower->j - oy;
1283b5e53cdSSajid Ali       do {
1299371c9d4SSatish Balay         if (skip_i) i = upper->i - ox;
1309371c9d4SSatish Balay         else i = lower->i - ox;
1313b5e53cdSSajid Ali         do {
132063654ddSPeter Brune           /* "actual" indices rather than ones outside of the domain */
133063654ddSPeter Brune           ii = i;
134063654ddSPeter Brune           jj = j;
135063654ddSPeter Brune           kk = k;
136063654ddSPeter Brune           if (ii < 0) ii = M + ii;
137063654ddSPeter Brune           if (jj < 0) jj = N + jj;
138063654ddSPeter Brune           if (kk < 0) kk = P + kk;
139063654ddSPeter Brune           if (ii > M - 1) ii = ii - M;
140063654ddSPeter Brune           if (jj > N - 1) jj = jj - N;
141063654ddSPeter Brune           if (kk > P - 1) kk = kk - P;
142063654ddSPeter Brune           /* gone out of processor range on x axis */
143063654ddSPeter Brune           while (ii > me - 1 || ii < ms) {
144063654ddSPeter Brune             if (mr == m - 1) {
145063654ddSPeter Brune               ms = 0;
146063654ddSPeter Brune               me = lx[0];
147063654ddSPeter Brune               mr = 0;
148063654ddSPeter Brune             } else {
149063654ddSPeter Brune               mr++;
150063654ddSPeter Brune               ms = me;
151063654ddSPeter Brune               me += lx[mr];
152063654ddSPeter Brune             }
153063654ddSPeter Brune           }
154063654ddSPeter Brune           /* gone out of processor range on y axis */
155063654ddSPeter Brune           while (jj > ne - 1 || jj < ns) {
156063654ddSPeter Brune             if (nr == n - 1) {
157063654ddSPeter Brune               ns = 0;
158063654ddSPeter Brune               ne = ly[0];
159063654ddSPeter Brune               nr = 0;
160063654ddSPeter Brune             } else {
161063654ddSPeter Brune               nr++;
162063654ddSPeter Brune               ns = ne;
163063654ddSPeter Brune               ne += ly[nr];
164063654ddSPeter Brune             }
165063654ddSPeter Brune           }
166063654ddSPeter Brune           /* gone out of processor range on z axis */
167063654ddSPeter Brune           while (kk > pe - 1 || kk < ps) {
168063654ddSPeter Brune             if (pr == p - 1) {
169063654ddSPeter Brune               ps = 0;
170063654ddSPeter Brune               pe = lz[0];
171063654ddSPeter Brune               pr = 0;
172063654ddSPeter Brune             } else {
173063654ddSPeter Brune               pr++;
174063654ddSPeter Brune               ps = pe;
175063654ddSPeter Brune               pe += lz[pr];
176063654ddSPeter Brune             }
177063654ddSPeter Brune           }
178063654ddSPeter Brune           /* compute the vector base on owning processor */
179063654ddSPeter Brune           xm   = me - ms;
180063654ddSPeter Brune           ym   = ne - ns;
181063654ddSPeter Brune           zm   = pe - ps;
182b0bff951SPeter Brune           base = ms * ym * zm + ns * M * zm + ps * M * N;
183063654ddSPeter Brune           /* compute the local coordinates on owning processor */
184063654ddSPeter Brune           si = ii - ms;
185063654ddSPeter Brune           sj = jj - ns;
186063654ddSPeter Brune           sk = kk - ps;
187063654ddSPeter Brune           for (l = 0; l < dof; l++) {
188063654ddSPeter Brune             indices[idx] = l + dof * (base + si + xm * sj + xm * ym * sk);
189ff9846d9SPeter Brune             idx++;
190ff9846d9SPeter Brune           }
1913b5e53cdSSajid Ali           i++;
1923b5e53cdSSajid Ali         } while (i < upper->i - ox);
1933b5e53cdSSajid Ali         j++;
1943b5e53cdSSajid Ali       } while (j < upper->j - oy);
1953b5e53cdSSajid Ali       k++;
1963b5e53cdSSajid Ali     } while (k < upper->k - oz);
1973b5e53cdSSajid Ali   }
1983b5e53cdSSajid Ali 
1993b5e53cdSSajid Ali   if (!offproc) {
2009566063dSJacob Faibussowitsch     PetscCall(DMDAGetCorners(da, &ms, &ns, &ps, &mw, &nw, &pw));
2013b5e53cdSSajid Ali     me = ms + mw;
2023b5e53cdSSajid Ali     if (N > 1) ne = ns + nw;
2033b5e53cdSSajid Ali     if (P > 1) pe = ps + pw;
2043b5e53cdSSajid Ali     /* Account for DM offsets */
2059371c9d4SSatish Balay     ms = ms - ox;
2069371c9d4SSatish Balay     me = me - ox;
2079371c9d4SSatish Balay     ns = ns - oy;
2089371c9d4SSatish Balay     ne = ne - oy;
2099371c9d4SSatish Balay     ps = ps - oz;
2109371c9d4SSatish Balay     pe = pe - oz;
2113b5e53cdSSajid Ali 
2123b5e53cdSSajid Ali     /* compute the vector base on owning processor */
2133b5e53cdSSajid Ali     xm   = me - ms;
2143b5e53cdSSajid Ali     ym   = ne - ns;
2153b5e53cdSSajid Ali     zm   = pe - ps;
2163b5e53cdSSajid Ali     base = ms * ym * zm + ns * M * zm + ps * M * N;
2173b5e53cdSSajid Ali     /*
2183b5e53cdSSajid Ali        if no indices are to be returned, create an empty is,
2193b5e53cdSSajid Ali        this prevents hanging in while loops
2203b5e53cdSSajid Ali     */
2213b5e53cdSSajid Ali     if (skip_i && skip_j && skip_k) goto createis;
2223b5e53cdSSajid Ali     /*
2233b5e53cdSSajid Ali        do..while loops to ensure the block gets entered once,
2243b5e53cdSSajid Ali        regardless of control condition being met, necessary for
2253b5e53cdSSajid Ali        cases when a subset of skip_i/j/k is true
2263b5e53cdSSajid Ali     */
2279371c9d4SSatish Balay     if (skip_k) k = upper->k - oz;
2289371c9d4SSatish Balay     else k = lower->k - oz;
2293b5e53cdSSajid Ali     do {
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 
2579566063dSJacob Faibussowitsch     PetscCall(PetscRealloc((size_t)(idx * sizeof(PetscInt)), (void *)&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 
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 
350*f4f49eeaSPierre 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 */
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 
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 
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