xref: /petsc/src/dm/impls/da/dadd.c (revision 834855d6effb0d027771461c8e947ee1ce5a1e17)
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