xref: /petsc/src/dm/impls/da/fdda.c (revision 72fd0fbdbfed0156e00d46940d6a00aa32e1f56c)
1af0996ceSBarry Smith #include <petsc/private/dmdaimpl.h> /*I      "petscdmda.h"     I*/
207475bc1SBarry Smith #include <petscmat.h>
3e432b41dSStefano Zampini #include <petscbt.h>
447c6ae99SBarry Smith 
5e727c939SJed Brown extern PetscErrorCode DMCreateColoring_DA_1d_MPIAIJ(DM, ISColoringType, ISColoring *);
6e727c939SJed Brown extern PetscErrorCode DMCreateColoring_DA_2d_MPIAIJ(DM, ISColoringType, ISColoring *);
7e727c939SJed Brown extern PetscErrorCode DMCreateColoring_DA_2d_5pt_MPIAIJ(DM, ISColoringType, ISColoring *);
8e727c939SJed Brown extern PetscErrorCode DMCreateColoring_DA_3d_MPIAIJ(DM, ISColoringType, ISColoring *);
947c6ae99SBarry Smith 
1047c6ae99SBarry Smith /*
1147c6ae99SBarry Smith    For ghost i that may be negative or greater than the upper bound this
1247c6ae99SBarry Smith   maps it into the 0:m-1 range using periodicity
1347c6ae99SBarry Smith */
1447c6ae99SBarry Smith #define SetInRange(i, m) ((i < 0) ? m + i : ((i >= m) ? i - m : i))
1547c6ae99SBarry Smith 
16d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMDASetBlockFills_Private(const PetscInt *dfill, PetscInt w, PetscInt **rfill)
17d71ae5a4SJacob Faibussowitsch {
1847c6ae99SBarry Smith   PetscInt i, j, nz, *fill;
1947c6ae99SBarry Smith 
2047c6ae99SBarry Smith   PetscFunctionBegin;
213ba16761SJacob Faibussowitsch   if (!dfill) PetscFunctionReturn(PETSC_SUCCESS);
2247c6ae99SBarry Smith 
2347c6ae99SBarry Smith   /* count number nonzeros */
2447c6ae99SBarry Smith   nz = 0;
2547c6ae99SBarry Smith   for (i = 0; i < w; i++) {
2647c6ae99SBarry Smith     for (j = 0; j < w; j++) {
2747c6ae99SBarry Smith       if (dfill[w * i + j]) nz++;
2847c6ae99SBarry Smith     }
2947c6ae99SBarry Smith   }
309566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(nz + w + 1, &fill));
3147c6ae99SBarry Smith   /* construct modified CSR storage of nonzero structure */
32ce308e1dSBarry Smith   /*  fill[0 -- w] marks starts of each row of column indices (and end of last row)
33ce308e1dSBarry Smith    so fill[1] - fill[0] gives number of nonzeros in first row etc */
3447c6ae99SBarry Smith   nz = w + 1;
3547c6ae99SBarry Smith   for (i = 0; i < w; i++) {
3647c6ae99SBarry Smith     fill[i] = nz;
3747c6ae99SBarry Smith     for (j = 0; j < w; j++) {
3847c6ae99SBarry Smith       if (dfill[w * i + j]) {
3947c6ae99SBarry Smith         fill[nz] = j;
4047c6ae99SBarry Smith         nz++;
4147c6ae99SBarry Smith       }
4247c6ae99SBarry Smith     }
4347c6ae99SBarry Smith   }
4447c6ae99SBarry Smith   fill[w] = nz;
4547c6ae99SBarry Smith 
4647c6ae99SBarry Smith   *rfill = fill;
473ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4847c6ae99SBarry Smith }
4947c6ae99SBarry Smith 
50d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMDASetBlockFillsSparse_Private(const PetscInt *dfillsparse, PetscInt w, PetscInt **rfill)
51d71ae5a4SJacob Faibussowitsch {
52767d920cSKarl Rupp   PetscInt nz;
5309e28618SBarry Smith 
5409e28618SBarry Smith   PetscFunctionBegin;
553ba16761SJacob Faibussowitsch   if (!dfillsparse) PetscFunctionReturn(PETSC_SUCCESS);
5609e28618SBarry Smith 
5709e28618SBarry Smith   /* Determine number of non-zeros */
5809e28618SBarry Smith   nz = (dfillsparse[w] - w - 1);
5909e28618SBarry Smith 
6009e28618SBarry Smith   /* Allocate space for our copy of the given sparse matrix representation. */
619566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(nz + w + 1, rfill));
629566063dSJacob Faibussowitsch   PetscCall(PetscArraycpy(*rfill, dfillsparse, nz + w + 1));
633ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6409e28618SBarry Smith }
6509e28618SBarry Smith 
66d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMDASetBlockFills_Private2(DM_DA *dd)
67d71ae5a4SJacob Faibussowitsch {
6809e28618SBarry Smith   PetscInt i, k, cnt = 1;
6909e28618SBarry Smith 
7009e28618SBarry Smith   PetscFunctionBegin;
7109e28618SBarry Smith   /* ofillcount tracks the columns of ofill that have any nonzero in thems; the value in each location is the number of
7209e28618SBarry Smith    columns to the left with any nonzeros in them plus 1 */
739566063dSJacob Faibussowitsch   PetscCall(PetscCalloc1(dd->w, &dd->ofillcols));
7409e28618SBarry Smith   for (i = 0; i < dd->w; i++) {
7509e28618SBarry Smith     for (k = dd->ofill[i]; k < dd->ofill[i + 1]; k++) dd->ofillcols[dd->ofill[k]] = 1;
7609e28618SBarry Smith   }
7709e28618SBarry Smith   for (i = 0; i < dd->w; i++) {
78ad540459SPierre Jolivet     if (dd->ofillcols[i]) dd->ofillcols[i] = cnt++;
7909e28618SBarry Smith   }
803ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8109e28618SBarry Smith }
8209e28618SBarry Smith 
8347c6ae99SBarry Smith /*@
84aa219208SBarry Smith   DMDASetBlockFills - Sets the fill pattern in each block for a multi-component problem
85dce8aebaSBarry Smith   of the matrix returned by `DMCreateMatrix()`.
8647c6ae99SBarry Smith 
8720f4b53cSBarry Smith   Logically Collective
8847c6ae99SBarry Smith 
89d8d19677SJose E. Roman   Input Parameters:
90*72fd0fbdSBarry Smith + da    - the `DMDA`
9112b4a537SBarry Smith . dfill - the fill pattern in the diagonal block (may be `NULL`, means use dense block)
9247c6ae99SBarry Smith - ofill - the fill pattern in the off-diagonal blocks
9347c6ae99SBarry Smith 
9447c6ae99SBarry Smith   Level: developer
9547c6ae99SBarry Smith 
9695452b02SPatrick Sanan   Notes:
9795452b02SPatrick Sanan   This only makes sense when you are doing multicomponent problems but using the
98dce8aebaSBarry Smith   `MATMPIAIJ` matrix format
9947c6ae99SBarry Smith 
10012b4a537SBarry Smith   The format for `dfill` and `ofill` is a 2 dimensional dof by dof matrix with 1 entries
10147c6ae99SBarry Smith   representing coupling and 0 entries for missing coupling. For example
102dce8aebaSBarry Smith .vb
103dce8aebaSBarry Smith             dfill[9] = {1, 0, 0,
104dce8aebaSBarry Smith                         1, 1, 0,
105dce8aebaSBarry Smith                         0, 1, 1}
106dce8aebaSBarry Smith .ve
10747c6ae99SBarry Smith   means that row 0 is coupled with only itself in the diagonal block, row 1 is coupled with
10847c6ae99SBarry Smith   itself and row 0 (in the diagonal block) and row 2 is coupled with itself and row 1 (in the
10947c6ae99SBarry Smith   diagonal block).
11047c6ae99SBarry Smith 
111dce8aebaSBarry Smith   `DMDASetGetMatrix()` allows you to provide general code for those more complicated nonzero patterns then
11212b4a537SBarry Smith   can be represented in the `dfill`, `ofill` format
11347c6ae99SBarry Smith 
1141d27aa22SBarry Smith   Contributed by\:
1151d27aa22SBarry Smith   Glenn Hammond
11647c6ae99SBarry Smith 
11712b4a537SBarry Smith .seealso: [](sec_struct), `DM`, `DMDA`, `DMCreateMatrix()`, `DMDASetGetMatrix()`, `DMSetMatrixPreallocateOnly()`, `DMDASetBlockFillsSparse()`
11847c6ae99SBarry Smith @*/
119d71ae5a4SJacob Faibussowitsch PetscErrorCode DMDASetBlockFills(DM da, const PetscInt *dfill, const PetscInt *ofill)
120d71ae5a4SJacob Faibussowitsch {
12147c6ae99SBarry Smith   DM_DA *dd = (DM_DA *)da->data;
12247c6ae99SBarry Smith 
12347c6ae99SBarry Smith   PetscFunctionBegin;
12409e28618SBarry Smith   /* save the given dfill and ofill information */
1259566063dSJacob Faibussowitsch   PetscCall(DMDASetBlockFills_Private(dfill, dd->w, &dd->dfill));
1269566063dSJacob Faibussowitsch   PetscCall(DMDASetBlockFills_Private(ofill, dd->w, &dd->ofill));
127ae4f298aSBarry Smith 
12809e28618SBarry Smith   /* count nonzeros in ofill columns */
1299566063dSJacob Faibussowitsch   PetscCall(DMDASetBlockFills_Private2(dd));
1303ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
131ae4f298aSBarry Smith }
13209e28618SBarry Smith 
13309e28618SBarry Smith /*@
13409e28618SBarry Smith   DMDASetBlockFillsSparse - Sets the fill pattern in each block for a multi-component problem
135dce8aebaSBarry Smith   of the matrix returned by `DMCreateMatrix()`, using sparse representations
13609e28618SBarry Smith   of fill patterns.
13709e28618SBarry Smith 
13820f4b53cSBarry Smith   Logically Collective
13909e28618SBarry Smith 
140d8d19677SJose E. Roman   Input Parameters:
141*72fd0fbdSBarry Smith + da          - the `DMDA`
14260225df5SJacob Faibussowitsch . dfillsparse - the sparse fill pattern in the diagonal block (may be `NULL`, means use dense block)
14360225df5SJacob Faibussowitsch - ofillsparse - the sparse fill pattern in the off-diagonal blocks
14409e28618SBarry Smith 
14509e28618SBarry Smith   Level: developer
14609e28618SBarry Smith 
147dce8aebaSBarry Smith   Notes:
148dce8aebaSBarry Smith   This only makes sense when you are doing multicomponent problems but using the
149dce8aebaSBarry Smith   `MATMPIAIJ` matrix format
15009e28618SBarry Smith 
15120f4b53cSBarry Smith   The format for `dfill` and `ofill` is a sparse representation of a
15209e28618SBarry Smith   dof-by-dof matrix with 1 entries representing coupling and 0 entries
15309e28618SBarry Smith   for missing coupling.  The sparse representation is a 1 dimensional
15409e28618SBarry Smith   array of length nz + dof + 1, where nz is the number of non-zeros in
15509e28618SBarry Smith   the matrix.  The first dof entries in the array give the
15609e28618SBarry Smith   starting array indices of each row's items in the rest of the array,
15760942847SBarry Smith   the dof+1st item contains the value nz + dof + 1 (i.e. the entire length of the array)
15809e28618SBarry Smith   and the remaining nz items give the column indices of each of
15909e28618SBarry Smith   the 1s within the logical 2D matrix.  Each row's items within
16009e28618SBarry Smith   the array are the column indices of the 1s within that row
16109e28618SBarry Smith   of the 2D matrix.  PETSc developers may recognize that this is the
162dce8aebaSBarry Smith   same format as that computed by the `DMDASetBlockFills_Private()`
16309e28618SBarry Smith   function from a dense 2D matrix representation.
16409e28618SBarry Smith 
165dce8aebaSBarry Smith   `DMDASetGetMatrix()` allows you to provide general code for those more complicated nonzero patterns then
16620f4b53cSBarry Smith   can be represented in the `dfill`, `ofill` format
16709e28618SBarry Smith 
1681d27aa22SBarry Smith   Contributed by\:
1691d27aa22SBarry Smith   Philip C. Roth
17009e28618SBarry Smith 
17112b4a537SBarry Smith .seealso: [](sec_struct), `DM`, `DMDA`, `DMDASetBlockFills()`, `DMCreateMatrix()`, `DMDASetGetMatrix()`, `DMSetMatrixPreallocateOnly()`
17209e28618SBarry Smith @*/
173d71ae5a4SJacob Faibussowitsch PetscErrorCode DMDASetBlockFillsSparse(DM da, const PetscInt *dfillsparse, const PetscInt *ofillsparse)
174d71ae5a4SJacob Faibussowitsch {
17509e28618SBarry Smith   DM_DA *dd = (DM_DA *)da->data;
17609e28618SBarry Smith 
17709e28618SBarry Smith   PetscFunctionBegin;
17809e28618SBarry Smith   /* save the given dfill and ofill information */
1799566063dSJacob Faibussowitsch   PetscCall(DMDASetBlockFillsSparse_Private(dfillsparse, dd->w, &dd->dfill));
1809566063dSJacob Faibussowitsch   PetscCall(DMDASetBlockFillsSparse_Private(ofillsparse, dd->w, &dd->ofill));
18109e28618SBarry Smith 
18209e28618SBarry Smith   /* count nonzeros in ofill columns */
1839566063dSJacob Faibussowitsch   PetscCall(DMDASetBlockFills_Private2(dd));
1843ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
18547c6ae99SBarry Smith }
18647c6ae99SBarry Smith 
187d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateColoring_DA(DM da, ISColoringType ctype, ISColoring *coloring)
188d71ae5a4SJacob Faibussowitsch {
18947c6ae99SBarry Smith   PetscInt       dim, m, n, p, nc;
190bff4a2f0SMatthew G. Knepley   DMBoundaryType bx, by, bz;
19147c6ae99SBarry Smith   MPI_Comm       comm;
19247c6ae99SBarry Smith   PetscMPIInt    size;
19347c6ae99SBarry Smith   PetscBool      isBAIJ;
19447c6ae99SBarry Smith   DM_DA         *dd = (DM_DA *)da->data;
19547c6ae99SBarry Smith 
19647c6ae99SBarry Smith   PetscFunctionBegin;
19747c6ae99SBarry Smith   /*
19847c6ae99SBarry Smith                                   m
19947c6ae99SBarry Smith           ------------------------------------------------------
20047c6ae99SBarry Smith          |                                                     |
20147c6ae99SBarry Smith          |                                                     |
20247c6ae99SBarry Smith          |               ----------------------                |
20347c6ae99SBarry Smith          |               |                    |                |
20447c6ae99SBarry Smith       n  |           yn  |                    |                |
20547c6ae99SBarry Smith          |               |                    |                |
20647c6ae99SBarry Smith          |               .---------------------                |
20747c6ae99SBarry Smith          |             (xs,ys)     xn                          |
20847c6ae99SBarry Smith          |            .                                        |
20947c6ae99SBarry Smith          |         (gxs,gys)                                   |
21047c6ae99SBarry Smith          |                                                     |
21147c6ae99SBarry Smith           -----------------------------------------------------
21247c6ae99SBarry Smith   */
21347c6ae99SBarry Smith 
21447c6ae99SBarry Smith   /*
21547c6ae99SBarry Smith          nc - number of components per grid point
21647c6ae99SBarry Smith          col - number of colors needed in one direction for single component problem
21747c6ae99SBarry Smith 
21847c6ae99SBarry Smith   */
2199566063dSJacob Faibussowitsch   PetscCall(DMDAGetInfo(da, &dim, NULL, NULL, NULL, &m, &n, &p, &nc, NULL, &bx, &by, &bz, NULL));
22047c6ae99SBarry Smith 
2219566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)da, &comm));
2229566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(comm, &size));
2235bdb020cSBarry Smith   if (ctype == IS_COLORING_LOCAL) {
22447c6ae99SBarry Smith     if (size == 1) {
22547c6ae99SBarry Smith       ctype = IS_COLORING_GLOBAL;
2262ddab442SBarry Smith     } else {
2272ddab442SBarry Smith       PetscCheck((dim == 1) || !((m == 1 && bx == DM_BOUNDARY_PERIODIC) || (n == 1 && by == DM_BOUNDARY_PERIODIC) || (p == 1 && bz == DM_BOUNDARY_PERIODIC)), PetscObjectComm((PetscObject)da), PETSC_ERR_SUP, "IS_COLORING_LOCAL cannot be used for periodic boundary condition having both ends of the domain on the same process");
22847c6ae99SBarry Smith     }
22947c6ae99SBarry Smith   }
23047c6ae99SBarry Smith 
231aa219208SBarry Smith   /* Tell the DMDA it has 1 degree of freedom per grid point so that the coloring for BAIJ
23247c6ae99SBarry Smith      matrices is for the blocks, not the individual matrix elements  */
2339566063dSJacob Faibussowitsch   PetscCall(PetscStrbeginswith(da->mattype, MATBAIJ, &isBAIJ));
2349566063dSJacob Faibussowitsch   if (!isBAIJ) PetscCall(PetscStrbeginswith(da->mattype, MATMPIBAIJ, &isBAIJ));
2359566063dSJacob Faibussowitsch   if (!isBAIJ) PetscCall(PetscStrbeginswith(da->mattype, MATSEQBAIJ, &isBAIJ));
23647c6ae99SBarry Smith   if (isBAIJ) {
23747c6ae99SBarry Smith     dd->w  = 1;
23847c6ae99SBarry Smith     dd->xs = dd->xs / nc;
23947c6ae99SBarry Smith     dd->xe = dd->xe / nc;
24047c6ae99SBarry Smith     dd->Xs = dd->Xs / nc;
24147c6ae99SBarry Smith     dd->Xe = dd->Xe / nc;
24247c6ae99SBarry Smith   }
24347c6ae99SBarry Smith 
24447c6ae99SBarry Smith   /*
245aa219208SBarry Smith      We do not provide a getcoloring function in the DMDA operations because
2469a1b256bSStefano Zampini    the basic DMDA does not know about matrices. We think of DMDA as being
24747c6ae99SBarry Smith    more low-level then matrices.
24847c6ae99SBarry Smith   */
2491baa6e33SBarry Smith   if (dim == 1) PetscCall(DMCreateColoring_DA_1d_MPIAIJ(da, ctype, coloring));
2501baa6e33SBarry Smith   else if (dim == 2) PetscCall(DMCreateColoring_DA_2d_MPIAIJ(da, ctype, coloring));
2511baa6e33SBarry Smith   else if (dim == 3) PetscCall(DMCreateColoring_DA_3d_MPIAIJ(da, ctype, coloring));
2521baa6e33SBarry Smith   else SETERRQ(PetscObjectComm((PetscObject)da), PETSC_ERR_SUP, "Not done for %" PetscInt_FMT " dimension, send us mail petsc-maint@mcs.anl.gov for code", dim);
25347c6ae99SBarry Smith   if (isBAIJ) {
25447c6ae99SBarry Smith     dd->w  = nc;
25547c6ae99SBarry Smith     dd->xs = dd->xs * nc;
25647c6ae99SBarry Smith     dd->xe = dd->xe * nc;
25747c6ae99SBarry Smith     dd->Xs = dd->Xs * nc;
25847c6ae99SBarry Smith     dd->Xe = dd->Xe * nc;
25947c6ae99SBarry Smith   }
2603ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
26147c6ae99SBarry Smith }
26247c6ae99SBarry Smith 
263d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateColoring_DA_2d_MPIAIJ(DM da, ISColoringType ctype, ISColoring *coloring)
264d71ae5a4SJacob Faibussowitsch {
26547c6ae99SBarry Smith   PetscInt         xs, ys, nx, ny, i, j, ii, gxs, gys, gnx, gny, m, n, M, N, dim, s, k, nc, col;
266dec0b466SHong Zhang   PetscInt         ncolors = 0;
26747c6ae99SBarry Smith   MPI_Comm         comm;
268bff4a2f0SMatthew G. Knepley   DMBoundaryType   bx, by;
269aa219208SBarry Smith   DMDAStencilType  st;
27047c6ae99SBarry Smith   ISColoringValue *colors;
27147c6ae99SBarry Smith   DM_DA           *dd = (DM_DA *)da->data;
27247c6ae99SBarry Smith 
27347c6ae99SBarry Smith   PetscFunctionBegin;
27447c6ae99SBarry Smith   /*
27547c6ae99SBarry Smith          nc - number of components per grid point
27647c6ae99SBarry Smith          col - number of colors needed in one direction for single component problem
27747c6ae99SBarry Smith 
27847c6ae99SBarry Smith   */
2799566063dSJacob Faibussowitsch   PetscCall(DMDAGetInfo(da, &dim, &m, &n, NULL, &M, &N, NULL, &nc, &s, &bx, &by, NULL, &st));
28047c6ae99SBarry Smith   col = 2 * s + 1;
2819566063dSJacob Faibussowitsch   PetscCall(DMDAGetCorners(da, &xs, &ys, NULL, &nx, &ny, NULL));
2829566063dSJacob Faibussowitsch   PetscCall(DMDAGetGhostCorners(da, &gxs, &gys, NULL, &gnx, &gny, NULL));
2839566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)da, &comm));
28447c6ae99SBarry Smith 
28547c6ae99SBarry Smith   /* special case as taught to us by Paul Hovland */
286aa219208SBarry Smith   if (st == DMDA_STENCIL_STAR && s == 1) {
2879566063dSJacob Faibussowitsch     PetscCall(DMCreateColoring_DA_2d_5pt_MPIAIJ(da, ctype, coloring));
28847c6ae99SBarry Smith   } else {
28947c6ae99SBarry Smith     if (ctype == IS_COLORING_GLOBAL) {
29047c6ae99SBarry Smith       if (!dd->localcoloring) {
2919566063dSJacob Faibussowitsch         PetscCall(PetscMalloc1(nc * nx * ny, &colors));
29247c6ae99SBarry Smith         ii = 0;
29347c6ae99SBarry Smith         for (j = ys; j < ys + ny; j++) {
29447c6ae99SBarry Smith           for (i = xs; i < xs + nx; i++) {
295ad540459SPierre Jolivet             for (k = 0; k < nc; k++) colors[ii++] = k + nc * ((i % col) + col * (j % col));
29647c6ae99SBarry Smith           }
29747c6ae99SBarry Smith         }
29847c6ae99SBarry Smith         ncolors = nc + nc * (col - 1 + col * (col - 1));
2999566063dSJacob Faibussowitsch         PetscCall(ISColoringCreate(comm, ncolors, nc * nx * ny, colors, PETSC_OWN_POINTER, &dd->localcoloring));
30047c6ae99SBarry Smith       }
30147c6ae99SBarry Smith       *coloring = dd->localcoloring;
3025bdb020cSBarry Smith     } else if (ctype == IS_COLORING_LOCAL) {
30347c6ae99SBarry Smith       if (!dd->ghostedcoloring) {
3049566063dSJacob Faibussowitsch         PetscCall(PetscMalloc1(nc * gnx * gny, &colors));
30547c6ae99SBarry Smith         ii = 0;
30647c6ae99SBarry Smith         for (j = gys; j < gys + gny; j++) {
30747c6ae99SBarry Smith           for (i = gxs; i < gxs + gnx; i++) {
30847c6ae99SBarry Smith             for (k = 0; k < nc; k++) {
30947c6ae99SBarry Smith               /* the complicated stuff is to handle periodic boundaries */
31047c6ae99SBarry Smith               colors[ii++] = k + nc * ((SetInRange(i, m) % col) + col * (SetInRange(j, n) % col));
31147c6ae99SBarry Smith             }
31247c6ae99SBarry Smith           }
31347c6ae99SBarry Smith         }
31447c6ae99SBarry Smith         ncolors = nc + nc * (col - 1 + col * (col - 1));
3159566063dSJacob Faibussowitsch         PetscCall(ISColoringCreate(comm, ncolors, nc * gnx * gny, colors, PETSC_OWN_POINTER, &dd->ghostedcoloring));
31647c6ae99SBarry Smith         /* PetscIntView(ncolors,(PetscInt*)colors,0); */
31747c6ae99SBarry Smith 
3189566063dSJacob Faibussowitsch         PetscCall(ISColoringSetType(dd->ghostedcoloring, IS_COLORING_LOCAL));
31947c6ae99SBarry Smith       }
32047c6ae99SBarry Smith       *coloring = dd->ghostedcoloring;
32198921bdaSJacob Faibussowitsch     } else SETERRQ(PetscObjectComm((PetscObject)da), PETSC_ERR_ARG_WRONG, "Unknown ISColoringType %d", (int)ctype);
32247c6ae99SBarry Smith   }
3239566063dSJacob Faibussowitsch   PetscCall(ISColoringReference(*coloring));
3243ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
32547c6ae99SBarry Smith }
32647c6ae99SBarry Smith 
327d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateColoring_DA_3d_MPIAIJ(DM da, ISColoringType ctype, ISColoring *coloring)
328d71ae5a4SJacob Faibussowitsch {
32947c6ae99SBarry Smith   PetscInt         xs, ys, nx, ny, i, j, gxs, gys, gnx, gny, m, n, p, dim, s, k, nc, col, zs, gzs, ii, l, nz, gnz, M, N, P;
33047c6ae99SBarry Smith   PetscInt         ncolors;
33147c6ae99SBarry Smith   MPI_Comm         comm;
332bff4a2f0SMatthew G. Knepley   DMBoundaryType   bx, by, bz;
333aa219208SBarry Smith   DMDAStencilType  st;
33447c6ae99SBarry Smith   ISColoringValue *colors;
33547c6ae99SBarry Smith   DM_DA           *dd = (DM_DA *)da->data;
33647c6ae99SBarry Smith 
33747c6ae99SBarry Smith   PetscFunctionBegin;
33847c6ae99SBarry Smith   /*
33947c6ae99SBarry Smith          nc - number of components per grid point
34047c6ae99SBarry Smith          col - number of colors needed in one direction for single component problem
34147c6ae99SBarry Smith   */
3429566063dSJacob Faibussowitsch   PetscCall(DMDAGetInfo(da, &dim, &m, &n, &p, &M, &N, &P, &nc, &s, &bx, &by, &bz, &st));
34347c6ae99SBarry Smith   col = 2 * s + 1;
34400045ab3SPierre Jolivet   PetscCheck(bx != DM_BOUNDARY_PERIODIC || (m % col) == 0, PetscObjectComm((PetscObject)da), PETSC_ERR_SUP, "For coloring efficiency ensure number of grid points in X is divisible by 2*stencil_width + 1");
34500045ab3SPierre Jolivet   PetscCheck(by != DM_BOUNDARY_PERIODIC || (n % col) == 0, PetscObjectComm((PetscObject)da), PETSC_ERR_SUP, "For coloring efficiency ensure number of grid points in Y is divisible by 2*stencil_width + 1");
34600045ab3SPierre Jolivet   PetscCheck(bz != DM_BOUNDARY_PERIODIC || (p % col) == 0, PetscObjectComm((PetscObject)da), PETSC_ERR_SUP, "For coloring efficiency ensure number of grid points in Z is divisible by 2*stencil_width + 1");
347494b1ccaSBarry Smith 
3489566063dSJacob Faibussowitsch   PetscCall(DMDAGetCorners(da, &xs, &ys, &zs, &nx, &ny, &nz));
3499566063dSJacob Faibussowitsch   PetscCall(DMDAGetGhostCorners(da, &gxs, &gys, &gzs, &gnx, &gny, &gnz));
3509566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)da, &comm));
35147c6ae99SBarry Smith 
35247c6ae99SBarry Smith   /* create the coloring */
35347c6ae99SBarry Smith   if (ctype == IS_COLORING_GLOBAL) {
35447c6ae99SBarry Smith     if (!dd->localcoloring) {
3559566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(nc * nx * ny * nz, &colors));
35647c6ae99SBarry Smith       ii = 0;
35747c6ae99SBarry Smith       for (k = zs; k < zs + nz; k++) {
35847c6ae99SBarry Smith         for (j = ys; j < ys + ny; j++) {
35947c6ae99SBarry Smith           for (i = xs; i < xs + nx; i++) {
360ad540459SPierre Jolivet             for (l = 0; l < nc; l++) colors[ii++] = l + nc * ((i % col) + col * (j % col) + col * col * (k % col));
36147c6ae99SBarry Smith           }
36247c6ae99SBarry Smith         }
36347c6ae99SBarry Smith       }
36447c6ae99SBarry Smith       ncolors = nc + nc * (col - 1 + col * (col - 1) + col * col * (col - 1));
3659566063dSJacob Faibussowitsch       PetscCall(ISColoringCreate(comm, ncolors, nc * nx * ny * nz, colors, PETSC_OWN_POINTER, &dd->localcoloring));
36647c6ae99SBarry Smith     }
36747c6ae99SBarry Smith     *coloring = dd->localcoloring;
3685bdb020cSBarry Smith   } else if (ctype == IS_COLORING_LOCAL) {
36947c6ae99SBarry Smith     if (!dd->ghostedcoloring) {
3709566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(nc * gnx * gny * gnz, &colors));
37147c6ae99SBarry Smith       ii = 0;
37247c6ae99SBarry Smith       for (k = gzs; k < gzs + gnz; k++) {
37347c6ae99SBarry Smith         for (j = gys; j < gys + gny; j++) {
37447c6ae99SBarry Smith           for (i = gxs; i < gxs + gnx; i++) {
37547c6ae99SBarry Smith             for (l = 0; l < nc; l++) {
37647c6ae99SBarry Smith               /* the complicated stuff is to handle periodic boundaries */
37747c6ae99SBarry Smith               colors[ii++] = l + nc * ((SetInRange(i, m) % col) + col * (SetInRange(j, n) % col) + col * col * (SetInRange(k, p) % col));
37847c6ae99SBarry Smith             }
37947c6ae99SBarry Smith           }
38047c6ae99SBarry Smith         }
38147c6ae99SBarry Smith       }
38247c6ae99SBarry Smith       ncolors = nc + nc * (col - 1 + col * (col - 1) + col * col * (col - 1));
3839566063dSJacob Faibussowitsch       PetscCall(ISColoringCreate(comm, ncolors, nc * gnx * gny * gnz, colors, PETSC_OWN_POINTER, &dd->ghostedcoloring));
3849566063dSJacob Faibussowitsch       PetscCall(ISColoringSetType(dd->ghostedcoloring, IS_COLORING_LOCAL));
38547c6ae99SBarry Smith     }
38647c6ae99SBarry Smith     *coloring = dd->ghostedcoloring;
38798921bdaSJacob Faibussowitsch   } else SETERRQ(PetscObjectComm((PetscObject)da), PETSC_ERR_ARG_WRONG, "Unknown ISColoringType %d", (int)ctype);
3889566063dSJacob Faibussowitsch   PetscCall(ISColoringReference(*coloring));
3893ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
39047c6ae99SBarry Smith }
39147c6ae99SBarry Smith 
392d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateColoring_DA_1d_MPIAIJ(DM da, ISColoringType ctype, ISColoring *coloring)
393d71ae5a4SJacob Faibussowitsch {
39447c6ae99SBarry Smith   PetscInt         xs, nx, i, i1, gxs, gnx, l, m, M, dim, s, nc, col;
39547c6ae99SBarry Smith   PetscInt         ncolors;
39647c6ae99SBarry Smith   MPI_Comm         comm;
397bff4a2f0SMatthew G. Knepley   DMBoundaryType   bx;
39847c6ae99SBarry Smith   ISColoringValue *colors;
39947c6ae99SBarry Smith   DM_DA           *dd = (DM_DA *)da->data;
40047c6ae99SBarry Smith 
40147c6ae99SBarry Smith   PetscFunctionBegin;
40247c6ae99SBarry Smith   /*
40347c6ae99SBarry Smith          nc - number of components per grid point
40447c6ae99SBarry Smith          col - number of colors needed in one direction for single component problem
40547c6ae99SBarry Smith   */
4069566063dSJacob Faibussowitsch   PetscCall(DMDAGetInfo(da, &dim, &m, NULL, NULL, &M, NULL, NULL, &nc, &s, &bx, NULL, NULL, NULL));
40747c6ae99SBarry Smith   col = 2 * s + 1;
4089566063dSJacob Faibussowitsch   PetscCall(DMDAGetCorners(da, &xs, NULL, NULL, &nx, NULL, NULL));
4099566063dSJacob Faibussowitsch   PetscCall(DMDAGetGhostCorners(da, &gxs, NULL, NULL, &gnx, NULL, NULL));
4109566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)da, &comm));
41147c6ae99SBarry Smith 
41247c6ae99SBarry Smith   /* create the coloring */
41347c6ae99SBarry Smith   if (ctype == IS_COLORING_GLOBAL) {
41447c6ae99SBarry Smith     if (!dd->localcoloring) {
4159566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(nc * nx, &colors));
416ae4f298aSBarry Smith       if (dd->ofillcols) {
417ae4f298aSBarry Smith         PetscInt tc = 0;
418ae4f298aSBarry Smith         for (i = 0; i < nc; i++) tc += (PetscInt)(dd->ofillcols[i] > 0);
419ae4f298aSBarry Smith         i1 = 0;
420ae4f298aSBarry Smith         for (i = xs; i < xs + nx; i++) {
421ae4f298aSBarry Smith           for (l = 0; l < nc; l++) {
422ae4f298aSBarry Smith             if (dd->ofillcols[l] && (i % col)) {
423ae4f298aSBarry Smith               colors[i1++] = nc - 1 + tc * ((i % col) - 1) + dd->ofillcols[l];
424ae4f298aSBarry Smith             } else {
425ae4f298aSBarry Smith               colors[i1++] = l;
426ae4f298aSBarry Smith             }
427ae4f298aSBarry Smith           }
428ae4f298aSBarry Smith         }
429ae4f298aSBarry Smith         ncolors = nc + 2 * s * tc;
430ae4f298aSBarry Smith       } else {
43147c6ae99SBarry Smith         i1 = 0;
43247c6ae99SBarry Smith         for (i = xs; i < xs + nx; i++) {
433ad540459SPierre Jolivet           for (l = 0; l < nc; l++) colors[i1++] = l + nc * (i % col);
43447c6ae99SBarry Smith         }
43547c6ae99SBarry Smith         ncolors = nc + nc * (col - 1);
436ae4f298aSBarry Smith       }
4379566063dSJacob Faibussowitsch       PetscCall(ISColoringCreate(comm, ncolors, nc * nx, colors, PETSC_OWN_POINTER, &dd->localcoloring));
43847c6ae99SBarry Smith     }
43947c6ae99SBarry Smith     *coloring = dd->localcoloring;
4405bdb020cSBarry Smith   } else if (ctype == IS_COLORING_LOCAL) {
44147c6ae99SBarry Smith     if (!dd->ghostedcoloring) {
4429566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(nc * gnx, &colors));
44347c6ae99SBarry Smith       i1 = 0;
44447c6ae99SBarry Smith       for (i = gxs; i < gxs + gnx; i++) {
44547c6ae99SBarry Smith         for (l = 0; l < nc; l++) {
44647c6ae99SBarry Smith           /* the complicated stuff is to handle periodic boundaries */
44747c6ae99SBarry Smith           colors[i1++] = l + nc * (SetInRange(i, m) % col);
44847c6ae99SBarry Smith         }
44947c6ae99SBarry Smith       }
45047c6ae99SBarry Smith       ncolors = nc + nc * (col - 1);
4519566063dSJacob Faibussowitsch       PetscCall(ISColoringCreate(comm, ncolors, nc * gnx, colors, PETSC_OWN_POINTER, &dd->ghostedcoloring));
4529566063dSJacob Faibussowitsch       PetscCall(ISColoringSetType(dd->ghostedcoloring, IS_COLORING_LOCAL));
45347c6ae99SBarry Smith     }
45447c6ae99SBarry Smith     *coloring = dd->ghostedcoloring;
45598921bdaSJacob Faibussowitsch   } else SETERRQ(PetscObjectComm((PetscObject)da), PETSC_ERR_ARG_WRONG, "Unknown ISColoringType %d", (int)ctype);
4569566063dSJacob Faibussowitsch   PetscCall(ISColoringReference(*coloring));
4573ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
45847c6ae99SBarry Smith }
45947c6ae99SBarry Smith 
460d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateColoring_DA_2d_5pt_MPIAIJ(DM da, ISColoringType ctype, ISColoring *coloring)
461d71ae5a4SJacob Faibussowitsch {
46247c6ae99SBarry Smith   PetscInt         xs, ys, nx, ny, i, j, ii, gxs, gys, gnx, gny, m, n, dim, s, k, nc;
46347c6ae99SBarry Smith   PetscInt         ncolors;
46447c6ae99SBarry Smith   MPI_Comm         comm;
465bff4a2f0SMatthew G. Knepley   DMBoundaryType   bx, by;
46647c6ae99SBarry Smith   ISColoringValue *colors;
46747c6ae99SBarry Smith   DM_DA           *dd = (DM_DA *)da->data;
46847c6ae99SBarry Smith 
46947c6ae99SBarry Smith   PetscFunctionBegin;
47047c6ae99SBarry Smith   /*
47147c6ae99SBarry Smith          nc - number of components per grid point
47247c6ae99SBarry Smith          col - number of colors needed in one direction for single component problem
47347c6ae99SBarry Smith   */
4749566063dSJacob Faibussowitsch   PetscCall(DMDAGetInfo(da, &dim, &m, &n, NULL, NULL, NULL, NULL, &nc, &s, &bx, &by, NULL, NULL));
4759566063dSJacob Faibussowitsch   PetscCall(DMDAGetCorners(da, &xs, &ys, NULL, &nx, &ny, NULL));
4769566063dSJacob Faibussowitsch   PetscCall(DMDAGetGhostCorners(da, &gxs, &gys, NULL, &gnx, &gny, NULL));
4779566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)da, &comm));
47847c6ae99SBarry Smith   /* create the coloring */
47947c6ae99SBarry Smith   if (ctype == IS_COLORING_GLOBAL) {
48047c6ae99SBarry Smith     if (!dd->localcoloring) {
4819566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(nc * nx * ny, &colors));
48247c6ae99SBarry Smith       ii = 0;
48347c6ae99SBarry Smith       for (j = ys; j < ys + ny; j++) {
48447c6ae99SBarry Smith         for (i = xs; i < xs + nx; i++) {
485ad540459SPierre Jolivet           for (k = 0; k < nc; k++) colors[ii++] = k + nc * ((3 * j + i) % 5);
48647c6ae99SBarry Smith         }
48747c6ae99SBarry Smith       }
48847c6ae99SBarry Smith       ncolors = 5 * nc;
4899566063dSJacob Faibussowitsch       PetscCall(ISColoringCreate(comm, ncolors, nc * nx * ny, colors, PETSC_OWN_POINTER, &dd->localcoloring));
49047c6ae99SBarry Smith     }
49147c6ae99SBarry Smith     *coloring = dd->localcoloring;
4925bdb020cSBarry Smith   } else if (ctype == IS_COLORING_LOCAL) {
49347c6ae99SBarry Smith     if (!dd->ghostedcoloring) {
4949566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(nc * gnx * gny, &colors));
49547c6ae99SBarry Smith       ii = 0;
49647c6ae99SBarry Smith       for (j = gys; j < gys + gny; j++) {
49747c6ae99SBarry Smith         for (i = gxs; i < gxs + gnx; i++) {
498ad540459SPierre Jolivet           for (k = 0; k < nc; k++) colors[ii++] = k + nc * ((3 * SetInRange(j, n) + SetInRange(i, m)) % 5);
49947c6ae99SBarry Smith         }
50047c6ae99SBarry Smith       }
50147c6ae99SBarry Smith       ncolors = 5 * nc;
5029566063dSJacob Faibussowitsch       PetscCall(ISColoringCreate(comm, ncolors, nc * gnx * gny, colors, PETSC_OWN_POINTER, &dd->ghostedcoloring));
5039566063dSJacob Faibussowitsch       PetscCall(ISColoringSetType(dd->ghostedcoloring, IS_COLORING_LOCAL));
50447c6ae99SBarry Smith     }
50547c6ae99SBarry Smith     *coloring = dd->ghostedcoloring;
50698921bdaSJacob Faibussowitsch   } else SETERRQ(PetscObjectComm((PetscObject)da), PETSC_ERR_ARG_WRONG, "Unknown ISColoringType %d", (int)ctype);
5073ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
50847c6ae99SBarry Smith }
50947c6ae99SBarry Smith 
51047c6ae99SBarry Smith /* =========================================================================== */
511e432b41dSStefano Zampini extern PetscErrorCode DMCreateMatrix_DA_1d_MPIAIJ(DM, Mat);
512ce308e1dSBarry Smith extern PetscErrorCode DMCreateMatrix_DA_1d_MPIAIJ_Fill(DM, Mat);
513e432b41dSStefano Zampini extern PetscErrorCode DMCreateMatrix_DA_1d_SeqAIJ_NoPreallocation(DM, Mat);
514e432b41dSStefano Zampini extern PetscErrorCode DMCreateMatrix_DA_2d_MPIAIJ(DM, Mat);
515950540a4SJed Brown extern PetscErrorCode DMCreateMatrix_DA_2d_MPIAIJ_Fill(DM, Mat);
516e432b41dSStefano Zampini extern PetscErrorCode DMCreateMatrix_DA_3d_MPIAIJ(DM, Mat);
517950540a4SJed Brown extern PetscErrorCode DMCreateMatrix_DA_3d_MPIAIJ_Fill(DM, Mat);
518950540a4SJed Brown extern PetscErrorCode DMCreateMatrix_DA_2d_MPIBAIJ(DM, Mat);
519950540a4SJed Brown extern PetscErrorCode DMCreateMatrix_DA_3d_MPIBAIJ(DM, Mat);
520950540a4SJed Brown extern PetscErrorCode DMCreateMatrix_DA_2d_MPISBAIJ(DM, Mat);
521950540a4SJed Brown extern PetscErrorCode DMCreateMatrix_DA_3d_MPISBAIJ(DM, Mat);
522d4002b98SHong Zhang extern PetscErrorCode DMCreateMatrix_DA_2d_MPISELL(DM, Mat);
523d4002b98SHong Zhang extern PetscErrorCode DMCreateMatrix_DA_3d_MPISELL(DM, Mat);
524e584696dSStefano Zampini extern PetscErrorCode DMCreateMatrix_DA_IS(DM, Mat);
52547c6ae99SBarry Smith 
526a4e35b19SJacob Faibussowitsch static PetscErrorCode MatView_MPI_DA(Mat A, PetscViewer viewer)
527d71ae5a4SJacob Faibussowitsch {
5289a42bb27SBarry Smith   DM                da;
52947c6ae99SBarry Smith   const char       *prefix;
5302d1451d4SHong Zhang   Mat               AA, Anatural;
53147c6ae99SBarry Smith   AO                ao;
53247c6ae99SBarry Smith   PetscInt          rstart, rend, *petsc, i;
53347c6ae99SBarry Smith   IS                is;
53447c6ae99SBarry Smith   MPI_Comm          comm;
53574388724SJed Brown   PetscViewerFormat format;
5362d1451d4SHong Zhang   PetscBool         flag;
53747c6ae99SBarry Smith 
53847c6ae99SBarry Smith   PetscFunctionBegin;
53974388724SJed Brown   /* Check whether we are just printing info, in which case MatView() already viewed everything we wanted to view */
5409566063dSJacob Faibussowitsch   PetscCall(PetscViewerGetFormat(viewer, &format));
5413ba16761SJacob Faibussowitsch   if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) PetscFunctionReturn(PETSC_SUCCESS);
54274388724SJed Brown 
5439566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)A, &comm));
5449566063dSJacob Faibussowitsch   PetscCall(MatGetDM(A, &da));
5457a8be351SBarry Smith   PetscCheck(da, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Matrix not generated from a DMDA");
54647c6ae99SBarry Smith 
5479566063dSJacob Faibussowitsch   PetscCall(DMDAGetAO(da, &ao));
5489566063dSJacob Faibussowitsch   PetscCall(MatGetOwnershipRange(A, &rstart, &rend));
5499566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(rend - rstart, &petsc));
55047c6ae99SBarry Smith   for (i = rstart; i < rend; i++) petsc[i - rstart] = i;
5519566063dSJacob Faibussowitsch   PetscCall(AOApplicationToPetsc(ao, rend - rstart, petsc));
5529566063dSJacob Faibussowitsch   PetscCall(ISCreateGeneral(comm, rend - rstart, petsc, PETSC_OWN_POINTER, &is));
55347c6ae99SBarry Smith 
55447c6ae99SBarry Smith   /* call viewer on natural ordering */
5552d1451d4SHong Zhang   PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATMPISELL, &flag));
5562d1451d4SHong Zhang   if (flag) {
5572d1451d4SHong Zhang     PetscCall(MatConvert(A, MATAIJ, MAT_INITIAL_MATRIX, &AA));
5582d1451d4SHong Zhang     A = AA;
5592d1451d4SHong Zhang   }
5609566063dSJacob Faibussowitsch   PetscCall(MatCreateSubMatrix(A, is, is, MAT_INITIAL_MATRIX, &Anatural));
5619566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&is));
5629566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetOptionsPrefix((PetscObject)A, &prefix));
5639566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetOptionsPrefix((PetscObject)Anatural, prefix));
5649566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)Anatural, ((PetscObject)A)->name));
565f0ed2f47SStefano Zampini   ((PetscObject)Anatural)->donotPetscObjectPrintClassNamePrefixType = PETSC_TRUE;
5669566063dSJacob Faibussowitsch   PetscCall(MatView(Anatural, viewer));
567f0ed2f47SStefano Zampini   ((PetscObject)Anatural)->donotPetscObjectPrintClassNamePrefixType = PETSC_FALSE;
5689566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&Anatural));
5692d1451d4SHong Zhang   if (flag) PetscCall(MatDestroy(&AA));
5703ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
57147c6ae99SBarry Smith }
57247c6ae99SBarry Smith 
573a4e35b19SJacob Faibussowitsch static PetscErrorCode MatLoad_MPI_DA(Mat A, PetscViewer viewer)
574d71ae5a4SJacob Faibussowitsch {
5759a42bb27SBarry Smith   DM       da;
57647c6ae99SBarry Smith   Mat      Anatural, Aapp;
57747c6ae99SBarry Smith   AO       ao;
578539c167fSBarry Smith   PetscInt rstart, rend, *app, i, m, n, M, N;
57947c6ae99SBarry Smith   IS       is;
58047c6ae99SBarry Smith   MPI_Comm comm;
58147c6ae99SBarry Smith 
58247c6ae99SBarry Smith   PetscFunctionBegin;
5839566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)A, &comm));
5849566063dSJacob Faibussowitsch   PetscCall(MatGetDM(A, &da));
5857a8be351SBarry Smith   PetscCheck(da, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Matrix not generated from a DMDA");
58647c6ae99SBarry Smith 
58747c6ae99SBarry Smith   /* Load the matrix in natural ordering */
5889566063dSJacob Faibussowitsch   PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &Anatural));
5899566063dSJacob Faibussowitsch   PetscCall(MatSetType(Anatural, ((PetscObject)A)->type_name));
5909566063dSJacob Faibussowitsch   PetscCall(MatGetSize(A, &M, &N));
5919566063dSJacob Faibussowitsch   PetscCall(MatGetLocalSize(A, &m, &n));
5929566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(Anatural, m, n, M, N));
5939566063dSJacob Faibussowitsch   PetscCall(MatLoad(Anatural, viewer));
59447c6ae99SBarry Smith 
59547c6ae99SBarry Smith   /* Map natural ordering to application ordering and create IS */
5969566063dSJacob Faibussowitsch   PetscCall(DMDAGetAO(da, &ao));
5979566063dSJacob Faibussowitsch   PetscCall(MatGetOwnershipRange(Anatural, &rstart, &rend));
5989566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(rend - rstart, &app));
59947c6ae99SBarry Smith   for (i = rstart; i < rend; i++) app[i - rstart] = i;
6009566063dSJacob Faibussowitsch   PetscCall(AOPetscToApplication(ao, rend - rstart, app));
6019566063dSJacob Faibussowitsch   PetscCall(ISCreateGeneral(comm, rend - rstart, app, PETSC_OWN_POINTER, &is));
60247c6ae99SBarry Smith 
60347c6ae99SBarry Smith   /* Do permutation and replace header */
6049566063dSJacob Faibussowitsch   PetscCall(MatCreateSubMatrix(Anatural, is, is, MAT_INITIAL_MATRIX, &Aapp));
6059566063dSJacob Faibussowitsch   PetscCall(MatHeaderReplace(A, &Aapp));
6069566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&is));
6079566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&Anatural));
6083ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
60947c6ae99SBarry Smith }
61047c6ae99SBarry Smith 
611d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateMatrix_DA(DM da, Mat *J)
612d71ae5a4SJacob Faibussowitsch {
61347c6ae99SBarry Smith   PetscInt    dim, dof, nx, ny, nz, dims[3], starts[3], M, N, P;
61447c6ae99SBarry Smith   Mat         A;
61547c6ae99SBarry Smith   MPI_Comm    comm;
61619fd82e9SBarry Smith   MatType     Atype;
617b412c318SBarry Smith   MatType     mtype;
61847c6ae99SBarry Smith   PetscMPIInt size;
61947c6ae99SBarry Smith   DM_DA      *dd    = (DM_DA *)da->data;
620ade515a3SBarry Smith   void (*aij)(void) = NULL, (*baij)(void) = NULL, (*sbaij)(void) = NULL, (*sell)(void) = NULL, (*is)(void) = NULL;
62147c6ae99SBarry Smith 
62247c6ae99SBarry Smith   PetscFunctionBegin;
6239566063dSJacob Faibussowitsch   PetscCall(MatInitializePackage());
624b412c318SBarry Smith   mtype = da->mattype;
62547c6ae99SBarry Smith 
62647c6ae99SBarry Smith   /*
62747c6ae99SBarry Smith                                   m
62847c6ae99SBarry Smith           ------------------------------------------------------
62947c6ae99SBarry Smith          |                                                     |
63047c6ae99SBarry Smith          |                                                     |
63147c6ae99SBarry Smith          |               ----------------------                |
63247c6ae99SBarry Smith          |               |                    |                |
63347c6ae99SBarry Smith       n  |           ny  |                    |                |
63447c6ae99SBarry Smith          |               |                    |                |
63547c6ae99SBarry Smith          |               .---------------------                |
63647c6ae99SBarry Smith          |             (xs,ys)     nx                          |
63747c6ae99SBarry Smith          |            .                                        |
63847c6ae99SBarry Smith          |         (gxs,gys)                                   |
63947c6ae99SBarry Smith          |                                                     |
64047c6ae99SBarry Smith           -----------------------------------------------------
64147c6ae99SBarry Smith   */
64247c6ae99SBarry Smith 
64347c6ae99SBarry Smith   /*
64447c6ae99SBarry Smith          nc - number of components per grid point
64547c6ae99SBarry Smith          col - number of colors needed in one direction for single component problem
64647c6ae99SBarry Smith   */
647e30e807fSPeter Brune   M   = dd->M;
648e30e807fSPeter Brune   N   = dd->N;
649e30e807fSPeter Brune   P   = dd->P;
650c73cfb54SMatthew G. Knepley   dim = da->dim;
651e30e807fSPeter Brune   dof = dd->w;
6529566063dSJacob Faibussowitsch   /* PetscCall(DMDAGetInfo(da,&dim,&M,&N,&P,NULL,NULL,NULL,&dof,NULL,NULL,NULL,NULL,NULL)); */
6539566063dSJacob Faibussowitsch   PetscCall(DMDAGetCorners(da, NULL, NULL, NULL, &nx, &ny, &nz));
6549566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)da, &comm));
6559566063dSJacob Faibussowitsch   PetscCall(MatCreate(comm, &A));
6569566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(A, dof * nx * ny * nz, dof * nx * ny * nz, dof * M * N * P, dof * M * N * P));
6579566063dSJacob Faibussowitsch   PetscCall(MatSetType(A, mtype));
6589566063dSJacob Faibussowitsch   PetscCall(MatSetFromOptions(A));
65974427ab1SRichard Tran Mills   if (dof * nx * ny * nz < da->bind_below) {
6609566063dSJacob Faibussowitsch     PetscCall(MatSetBindingPropagates(A, PETSC_TRUE));
6619566063dSJacob Faibussowitsch     PetscCall(MatBindToCPU(A, PETSC_TRUE));
66274427ab1SRichard Tran Mills   }
6639566063dSJacob Faibussowitsch   PetscCall(MatSetDM(A, da));
6641baa6e33SBarry Smith   if (da->structure_only) PetscCall(MatSetOption(A, MAT_STRUCTURE_ONLY, PETSC_TRUE));
6659566063dSJacob Faibussowitsch   PetscCall(MatGetType(A, &Atype));
66647c6ae99SBarry Smith   /*
667aa219208SBarry Smith      We do not provide a getmatrix function in the DMDA operations because
668aa219208SBarry Smith    the basic DMDA does not know about matrices. We think of DMDA as being more
66947c6ae99SBarry Smith    more low-level than matrices. This is kind of cheating but, cause sometimes
670aa219208SBarry Smith    we think of DMDA has higher level than matrices.
67147c6ae99SBarry Smith 
67247c6ae99SBarry Smith      We could switch based on Atype (or mtype), but we do not since the
673844bd0d7SStefano Zampini    specialized setting routines depend only on the particular preallocation
67447c6ae99SBarry Smith    details of the matrix, not the type itself.
67547c6ae99SBarry Smith   */
676d7dabc60SJed Brown   if (!da->prealloc_skip) { // Flag is likely set when user intends to use MatSetPreallocationCOO()
6779566063dSJacob Faibussowitsch     PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatMPIAIJSetPreallocation_C", &aij));
67848a46eb9SPierre Jolivet     if (!aij) PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatSeqAIJSetPreallocation_C", &aij));
67947c6ae99SBarry Smith     if (!aij) {
6809566063dSJacob Faibussowitsch       PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatMPIBAIJSetPreallocation_C", &baij));
68148a46eb9SPierre Jolivet       if (!baij) PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatSeqBAIJSetPreallocation_C", &baij));
68247c6ae99SBarry Smith       if (!baij) {
6839566063dSJacob Faibussowitsch         PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatMPISBAIJSetPreallocation_C", &sbaij));
68448a46eb9SPierre Jolivet         if (!sbaij) PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatSeqSBAIJSetPreallocation_C", &sbaij));
6855e26d47bSHong Zhang         if (!sbaij) {
6869566063dSJacob Faibussowitsch           PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatMPISELLSetPreallocation_C", &sell));
68748a46eb9SPierre Jolivet           if (!sell) PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatSeqSELLSetPreallocation_C", &sell));
6885e26d47bSHong Zhang         }
68948a46eb9SPierre Jolivet         if (!sell) PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatISSetPreallocation_C", &is));
69047c6ae99SBarry Smith       }
69147c6ae99SBarry Smith     }
692d7dabc60SJed Brown   }
69347c6ae99SBarry Smith   if (aij) {
69447c6ae99SBarry Smith     if (dim == 1) {
695ce308e1dSBarry Smith       if (dd->ofill) {
6969566063dSJacob Faibussowitsch         PetscCall(DMCreateMatrix_DA_1d_MPIAIJ_Fill(da, A));
697ce308e1dSBarry Smith       } else {
69819b08ed1SBarry Smith         DMBoundaryType bx;
69919b08ed1SBarry Smith         PetscMPIInt    size;
7009566063dSJacob Faibussowitsch         PetscCall(DMDAGetInfo(da, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &bx, NULL, NULL, NULL));
7019566063dSJacob Faibussowitsch         PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)da), &size));
70219b08ed1SBarry Smith         if (size == 1 && bx == DM_BOUNDARY_NONE) {
7039566063dSJacob Faibussowitsch           PetscCall(DMCreateMatrix_DA_1d_SeqAIJ_NoPreallocation(da, A));
70419b08ed1SBarry Smith         } else {
7059566063dSJacob Faibussowitsch           PetscCall(DMCreateMatrix_DA_1d_MPIAIJ(da, A));
706ce308e1dSBarry Smith         }
70719b08ed1SBarry Smith       }
70847c6ae99SBarry Smith     } else if (dim == 2) {
70947c6ae99SBarry Smith       if (dd->ofill) {
7109566063dSJacob Faibussowitsch         PetscCall(DMCreateMatrix_DA_2d_MPIAIJ_Fill(da, A));
71147c6ae99SBarry Smith       } else {
7129566063dSJacob Faibussowitsch         PetscCall(DMCreateMatrix_DA_2d_MPIAIJ(da, A));
71347c6ae99SBarry Smith       }
71447c6ae99SBarry Smith     } else if (dim == 3) {
71547c6ae99SBarry Smith       if (dd->ofill) {
7169566063dSJacob Faibussowitsch         PetscCall(DMCreateMatrix_DA_3d_MPIAIJ_Fill(da, A));
71747c6ae99SBarry Smith       } else {
7189566063dSJacob Faibussowitsch         PetscCall(DMCreateMatrix_DA_3d_MPIAIJ(da, A));
71947c6ae99SBarry Smith       }
72047c6ae99SBarry Smith     }
72147c6ae99SBarry Smith   } else if (baij) {
72247c6ae99SBarry Smith     if (dim == 2) {
7239566063dSJacob Faibussowitsch       PetscCall(DMCreateMatrix_DA_2d_MPIBAIJ(da, A));
72447c6ae99SBarry Smith     } else if (dim == 3) {
7259566063dSJacob Faibussowitsch       PetscCall(DMCreateMatrix_DA_3d_MPIBAIJ(da, A));
72663a3b9bcSJacob Faibussowitsch     } else SETERRQ(PetscObjectComm((PetscObject)da), PETSC_ERR_SUP, "Not implemented for %" PetscInt_FMT " dimension and Matrix Type: %s in %" PetscInt_FMT " dimension! Send mail to petsc-maint@mcs.anl.gov for code", dim, Atype, dim);
72747c6ae99SBarry Smith   } else if (sbaij) {
72847c6ae99SBarry Smith     if (dim == 2) {
7299566063dSJacob Faibussowitsch       PetscCall(DMCreateMatrix_DA_2d_MPISBAIJ(da, A));
73047c6ae99SBarry Smith     } else if (dim == 3) {
7319566063dSJacob Faibussowitsch       PetscCall(DMCreateMatrix_DA_3d_MPISBAIJ(da, A));
73263a3b9bcSJacob Faibussowitsch     } else SETERRQ(PetscObjectComm((PetscObject)da), PETSC_ERR_SUP, "Not implemented for %" PetscInt_FMT " dimension and Matrix Type: %s in %" PetscInt_FMT " dimension! Send mail to petsc-maint@mcs.anl.gov for code", dim, Atype, dim);
733d4002b98SHong Zhang   } else if (sell) {
7345e26d47bSHong Zhang     if (dim == 2) {
7359566063dSJacob Faibussowitsch       PetscCall(DMCreateMatrix_DA_2d_MPISELL(da, A));
736711261dbSHong Zhang     } else if (dim == 3) {
7379566063dSJacob Faibussowitsch       PetscCall(DMCreateMatrix_DA_3d_MPISELL(da, A));
73863a3b9bcSJacob Faibussowitsch     } else SETERRQ(PetscObjectComm((PetscObject)da), PETSC_ERR_SUP, "Not implemented for %" PetscInt_FMT " dimension and Matrix Type: %s in %" PetscInt_FMT " dimension! Send mail to petsc-maint@mcs.anl.gov for code", dim, Atype, dim);
739e584696dSStefano Zampini   } else if (is) {
7409566063dSJacob Faibussowitsch     PetscCall(DMCreateMatrix_DA_IS(da, A));
741d7dabc60SJed Brown   } else { // unknown type or da->prealloc_skip so structural information may be needed, but no prealloc
74245b6f7e9SBarry Smith     ISLocalToGlobalMapping ltog;
743e584696dSStefano Zampini 
7449566063dSJacob Faibussowitsch     PetscCall(MatSetBlockSize(A, dof));
7459566063dSJacob Faibussowitsch     PetscCall(MatSetUp(A));
7469566063dSJacob Faibussowitsch     PetscCall(DMGetLocalToGlobalMapping(da, &ltog));
7479566063dSJacob Faibussowitsch     PetscCall(MatSetLocalToGlobalMapping(A, ltog, ltog));
74847c6ae99SBarry Smith   }
7499566063dSJacob Faibussowitsch   PetscCall(DMDAGetGhostCorners(da, &starts[0], &starts[1], &starts[2], &dims[0], &dims[1], &dims[2]));
7509566063dSJacob Faibussowitsch   PetscCall(MatSetStencil(A, dim, dims, starts, dof));
7519566063dSJacob Faibussowitsch   PetscCall(MatSetDM(A, da));
7529566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(comm, &size));
75347c6ae99SBarry Smith   if (size > 1) {
75447c6ae99SBarry Smith     /* change viewer to display matrix in natural ordering */
7559566063dSJacob Faibussowitsch     PetscCall(MatSetOperation(A, MATOP_VIEW, (void (*)(void))MatView_MPI_DA));
7569566063dSJacob Faibussowitsch     PetscCall(MatSetOperation(A, MATOP_LOAD, (void (*)(void))MatLoad_MPI_DA));
75747c6ae99SBarry Smith   }
75847c6ae99SBarry Smith   *J = A;
7593ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
76047c6ae99SBarry Smith }
76147c6ae99SBarry Smith 
762844bd0d7SStefano Zampini PETSC_EXTERN PetscErrorCode MatISSetPreallocation_IS(Mat, PetscInt, const PetscInt[], PetscInt, const PetscInt[]);
763844bd0d7SStefano Zampini 
764d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateMatrix_DA_IS(DM dm, Mat J)
765d71ae5a4SJacob Faibussowitsch {
766e584696dSStefano Zampini   DM_DA                 *da = (DM_DA *)dm->data;
767e432b41dSStefano Zampini   Mat                    lJ, P;
768e584696dSStefano Zampini   ISLocalToGlobalMapping ltog;
769e432b41dSStefano Zampini   IS                     is;
770e432b41dSStefano Zampini   PetscBT                bt;
77105339c03SStefano Zampini   const PetscInt        *e_loc, *idx;
772e432b41dSStefano Zampini   PetscInt               i, nel, nen, nv, dof, *gidx, n, N;
773e584696dSStefano Zampini 
774e584696dSStefano Zampini   /* The l2g map of DMDA has all ghosted nodes, and e_loc is a subset of all the local nodes (including the ghosted)
775e432b41dSStefano Zampini      We need to filter out the local indices that are not represented through the DMDAGetElements decomposition */
776e584696dSStefano Zampini   PetscFunctionBegin;
777e584696dSStefano Zampini   dof = da->w;
7789566063dSJacob Faibussowitsch   PetscCall(MatSetBlockSize(J, dof));
7799566063dSJacob Faibussowitsch   PetscCall(DMGetLocalToGlobalMapping(dm, &ltog));
780e432b41dSStefano Zampini 
781e432b41dSStefano Zampini   /* flag local elements indices in local DMDA numbering */
7829566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingGetSize(ltog, &nv));
7839566063dSJacob Faibussowitsch   PetscCall(PetscBTCreate(nv / dof, &bt));
7849566063dSJacob Faibussowitsch   PetscCall(DMDAGetElements(dm, &nel, &nen, &e_loc)); /* this will throw an error if the stencil type is not DMDA_STENCIL_BOX */
7859566063dSJacob Faibussowitsch   for (i = 0; i < nel * nen; i++) PetscCall(PetscBTSet(bt, e_loc[i]));
786e432b41dSStefano Zampini 
787e432b41dSStefano Zampini   /* filter out (set to -1) the global indices not used by the local elements */
7889566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(nv / dof, &gidx));
7899566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingGetBlockIndices(ltog, &idx));
7909566063dSJacob Faibussowitsch   PetscCall(PetscArraycpy(gidx, idx, nv / dof));
7919566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingRestoreBlockIndices(ltog, &idx));
7929371c9d4SSatish Balay   for (i = 0; i < nv / dof; i++)
7939371c9d4SSatish Balay     if (!PetscBTLookup(bt, i)) gidx[i] = -1;
7949566063dSJacob Faibussowitsch   PetscCall(PetscBTDestroy(&bt));
7959566063dSJacob Faibussowitsch   PetscCall(ISCreateBlock(PetscObjectComm((PetscObject)dm), dof, nv / dof, gidx, PETSC_OWN_POINTER, &is));
7969566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingCreateIS(is, &ltog));
7979566063dSJacob Faibussowitsch   PetscCall(MatSetLocalToGlobalMapping(J, ltog, ltog));
7989566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingDestroy(&ltog));
7999566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&is));
80005339c03SStefano Zampini 
801e432b41dSStefano Zampini   /* Preallocation */
802e306f867SJed Brown   if (dm->prealloc_skip) {
8039566063dSJacob Faibussowitsch     PetscCall(MatSetUp(J));
804e306f867SJed Brown   } else {
8059566063dSJacob Faibussowitsch     PetscCall(MatISGetLocalMat(J, &lJ));
8069566063dSJacob Faibussowitsch     PetscCall(MatGetLocalToGlobalMapping(lJ, &ltog, NULL));
8079566063dSJacob Faibussowitsch     PetscCall(MatCreate(PetscObjectComm((PetscObject)lJ), &P));
8089566063dSJacob Faibussowitsch     PetscCall(MatSetType(P, MATPREALLOCATOR));
8099566063dSJacob Faibussowitsch     PetscCall(MatSetLocalToGlobalMapping(P, ltog, ltog));
8109566063dSJacob Faibussowitsch     PetscCall(MatGetSize(lJ, &N, NULL));
8119566063dSJacob Faibussowitsch     PetscCall(MatGetLocalSize(lJ, &n, NULL));
8129566063dSJacob Faibussowitsch     PetscCall(MatSetSizes(P, n, n, N, N));
8139566063dSJacob Faibussowitsch     PetscCall(MatSetBlockSize(P, dof));
8149566063dSJacob Faibussowitsch     PetscCall(MatSetUp(P));
81548a46eb9SPierre Jolivet     for (i = 0; i < nel; i++) PetscCall(MatSetValuesBlockedLocal(P, nen, e_loc + i * nen, nen, e_loc + i * nen, NULL, INSERT_VALUES));
8169566063dSJacob Faibussowitsch     PetscCall(MatPreallocatorPreallocate(P, (PetscBool)!da->prealloc_only, lJ));
8179566063dSJacob Faibussowitsch     PetscCall(MatISRestoreLocalMat(J, &lJ));
8189566063dSJacob Faibussowitsch     PetscCall(DMDARestoreElements(dm, &nel, &nen, &e_loc));
8199566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&P));
820e432b41dSStefano Zampini 
8219566063dSJacob Faibussowitsch     PetscCall(MatAssemblyBegin(J, MAT_FINAL_ASSEMBLY));
8229566063dSJacob Faibussowitsch     PetscCall(MatAssemblyEnd(J, MAT_FINAL_ASSEMBLY));
823e306f867SJed Brown   }
8243ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
825e584696dSStefano Zampini }
826e584696dSStefano Zampini 
827d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateMatrix_DA_2d_MPISELL(DM da, Mat J)
828d71ae5a4SJacob Faibussowitsch {
8295e26d47bSHong Zhang   PetscInt               xs, ys, nx, ny, i, j, slot, gxs, gys, gnx, gny, m, n, dim, s, *cols = NULL, k, nc, *rows = NULL, col, cnt, l, p;
8305e26d47bSHong Zhang   PetscInt               lstart, lend, pstart, pend, *dnz, *onz;
8315e26d47bSHong Zhang   MPI_Comm               comm;
8325e26d47bSHong Zhang   PetscScalar           *values;
8335e26d47bSHong Zhang   DMBoundaryType         bx, by;
8345e26d47bSHong Zhang   ISLocalToGlobalMapping ltog;
8355e26d47bSHong Zhang   DMDAStencilType        st;
8365e26d47bSHong Zhang 
8375e26d47bSHong Zhang   PetscFunctionBegin;
8385e26d47bSHong Zhang   /*
8395e26d47bSHong Zhang          nc - number of components per grid point
8405e26d47bSHong Zhang          col - number of colors needed in one direction for single component problem
8415e26d47bSHong Zhang   */
8429566063dSJacob Faibussowitsch   PetscCall(DMDAGetInfo(da, &dim, &m, &n, NULL, NULL, NULL, NULL, &nc, &s, &bx, &by, NULL, &st));
8435e26d47bSHong Zhang   col = 2 * s + 1;
8449566063dSJacob Faibussowitsch   PetscCall(DMDAGetCorners(da, &xs, &ys, NULL, &nx, &ny, NULL));
8459566063dSJacob Faibussowitsch   PetscCall(DMDAGetGhostCorners(da, &gxs, &gys, NULL, &gnx, &gny, NULL));
8469566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)da, &comm));
8475e26d47bSHong Zhang 
8489566063dSJacob Faibussowitsch   PetscCall(PetscMalloc2(nc, &rows, col * col * nc * nc, &cols));
8499566063dSJacob Faibussowitsch   PetscCall(DMGetLocalToGlobalMapping(da, &ltog));
8505e26d47bSHong Zhang 
8519566063dSJacob Faibussowitsch   PetscCall(MatSetBlockSize(J, nc));
8525e26d47bSHong Zhang   /* determine the matrix preallocation information */
853d0609cedSBarry Smith   MatPreallocateBegin(comm, nc * nx * ny, nc * nx * ny, dnz, onz);
8545e26d47bSHong Zhang   for (i = xs; i < xs + nx; i++) {
8555e26d47bSHong Zhang     pstart = (bx == DM_BOUNDARY_PERIODIC) ? -s : (PetscMax(-s, -i));
8565e26d47bSHong Zhang     pend   = (bx == DM_BOUNDARY_PERIODIC) ? s : (PetscMin(s, m - i - 1));
8575e26d47bSHong Zhang 
8585e26d47bSHong Zhang     for (j = ys; j < ys + ny; j++) {
8595e26d47bSHong Zhang       slot = i - gxs + gnx * (j - gys);
8605e26d47bSHong Zhang 
8615e26d47bSHong Zhang       lstart = (by == DM_BOUNDARY_PERIODIC) ? -s : (PetscMax(-s, -j));
8625e26d47bSHong Zhang       lend   = (by == DM_BOUNDARY_PERIODIC) ? s : (PetscMin(s, n - j - 1));
8635e26d47bSHong Zhang 
8645e26d47bSHong Zhang       cnt = 0;
8655e26d47bSHong Zhang       for (k = 0; k < nc; k++) {
8665e26d47bSHong Zhang         for (l = lstart; l < lend + 1; l++) {
8675e26d47bSHong Zhang           for (p = pstart; p < pend + 1; p++) {
8685e26d47bSHong Zhang             if ((st == DMDA_STENCIL_BOX) || (!l || !p)) { /* entries on star have either l = 0 or p = 0 */
8695e26d47bSHong Zhang               cols[cnt++] = k + nc * (slot + gnx * l + p);
8705e26d47bSHong Zhang             }
8715e26d47bSHong Zhang           }
8725e26d47bSHong Zhang         }
8735e26d47bSHong Zhang         rows[k] = k + nc * (slot);
8745e26d47bSHong Zhang       }
8759566063dSJacob Faibussowitsch       PetscCall(MatPreallocateSetLocal(ltog, nc, rows, ltog, cnt, cols, dnz, onz));
8765e26d47bSHong Zhang     }
8775e26d47bSHong Zhang   }
8789566063dSJacob Faibussowitsch   PetscCall(MatSetBlockSize(J, nc));
8799566063dSJacob Faibussowitsch   PetscCall(MatSeqSELLSetPreallocation(J, 0, dnz));
8809566063dSJacob Faibussowitsch   PetscCall(MatMPISELLSetPreallocation(J, 0, dnz, 0, onz));
881d0609cedSBarry Smith   MatPreallocateEnd(dnz, onz);
8825e26d47bSHong Zhang 
8839566063dSJacob Faibussowitsch   PetscCall(MatSetLocalToGlobalMapping(J, ltog, ltog));
8845e26d47bSHong Zhang 
8855e26d47bSHong Zhang   /*
8865e26d47bSHong Zhang     For each node in the grid: we get the neighbors in the local (on processor ordering
8875e26d47bSHong Zhang     that includes the ghost points) then MatSetValuesLocal() maps those indices to the global
8885e26d47bSHong Zhang     PETSc ordering.
8895e26d47bSHong Zhang   */
8905e26d47bSHong Zhang   if (!da->prealloc_only) {
8919566063dSJacob Faibussowitsch     PetscCall(PetscCalloc1(col * col * nc * nc, &values));
8925e26d47bSHong Zhang     for (i = xs; i < xs + nx; i++) {
8935e26d47bSHong Zhang       pstart = (bx == DM_BOUNDARY_PERIODIC) ? -s : (PetscMax(-s, -i));
8945e26d47bSHong Zhang       pend   = (bx == DM_BOUNDARY_PERIODIC) ? s : (PetscMin(s, m - i - 1));
8955e26d47bSHong Zhang 
8965e26d47bSHong Zhang       for (j = ys; j < ys + ny; j++) {
8975e26d47bSHong Zhang         slot = i - gxs + gnx * (j - gys);
8985e26d47bSHong Zhang 
8995e26d47bSHong Zhang         lstart = (by == DM_BOUNDARY_PERIODIC) ? -s : (PetscMax(-s, -j));
9005e26d47bSHong Zhang         lend   = (by == DM_BOUNDARY_PERIODIC) ? s : (PetscMin(s, n - j - 1));
9015e26d47bSHong Zhang 
9025e26d47bSHong Zhang         cnt = 0;
9035e26d47bSHong Zhang         for (k = 0; k < nc; k++) {
9045e26d47bSHong Zhang           for (l = lstart; l < lend + 1; l++) {
9055e26d47bSHong Zhang             for (p = pstart; p < pend + 1; p++) {
9065e26d47bSHong Zhang               if ((st == DMDA_STENCIL_BOX) || (!l || !p)) { /* entries on star have either l = 0 or p = 0 */
9075e26d47bSHong Zhang                 cols[cnt++] = k + nc * (slot + gnx * l + p);
9085e26d47bSHong Zhang               }
9095e26d47bSHong Zhang             }
9105e26d47bSHong Zhang           }
9115e26d47bSHong Zhang           rows[k] = k + nc * (slot);
9125e26d47bSHong Zhang         }
9139566063dSJacob Faibussowitsch         PetscCall(MatSetValuesLocal(J, nc, rows, cnt, cols, values, INSERT_VALUES));
9145e26d47bSHong Zhang       }
9155e26d47bSHong Zhang     }
9169566063dSJacob Faibussowitsch     PetscCall(PetscFree(values));
917e7e92044SBarry Smith     /* do not copy values to GPU since they are all zero and not yet needed there */
9189566063dSJacob Faibussowitsch     PetscCall(MatBindToCPU(J, PETSC_TRUE));
9199566063dSJacob Faibussowitsch     PetscCall(MatAssemblyBegin(J, MAT_FINAL_ASSEMBLY));
9209566063dSJacob Faibussowitsch     PetscCall(MatAssemblyEnd(J, MAT_FINAL_ASSEMBLY));
9219566063dSJacob Faibussowitsch     PetscCall(MatBindToCPU(J, PETSC_FALSE));
9229566063dSJacob Faibussowitsch     PetscCall(MatSetOption(J, MAT_NEW_NONZERO_LOCATION_ERR, PETSC_TRUE));
9235e26d47bSHong Zhang   }
9249566063dSJacob Faibussowitsch   PetscCall(PetscFree2(rows, cols));
9253ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9265e26d47bSHong Zhang }
9275e26d47bSHong Zhang 
928d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateMatrix_DA_3d_MPISELL(DM da, Mat J)
929d71ae5a4SJacob Faibussowitsch {
930711261dbSHong Zhang   PetscInt               xs, ys, nx, ny, i, j, slot, gxs, gys, gnx, gny;
931711261dbSHong Zhang   PetscInt               m, n, dim, s, *cols = NULL, k, nc, *rows = NULL, col, cnt, l, p, *dnz = NULL, *onz = NULL;
932711261dbSHong Zhang   PetscInt               istart, iend, jstart, jend, kstart, kend, zs, nz, gzs, gnz, ii, jj, kk, M, N, P;
933711261dbSHong Zhang   MPI_Comm               comm;
934711261dbSHong Zhang   PetscScalar           *values;
935711261dbSHong Zhang   DMBoundaryType         bx, by, bz;
936711261dbSHong Zhang   ISLocalToGlobalMapping ltog;
937711261dbSHong Zhang   DMDAStencilType        st;
938711261dbSHong Zhang 
939711261dbSHong Zhang   PetscFunctionBegin;
940711261dbSHong Zhang   /*
941711261dbSHong Zhang          nc - number of components per grid point
942711261dbSHong Zhang          col - number of colors needed in one direction for single component problem
943711261dbSHong Zhang   */
9449566063dSJacob Faibussowitsch   PetscCall(DMDAGetInfo(da, &dim, &m, &n, &p, &M, &N, &P, &nc, &s, &bx, &by, &bz, &st));
945711261dbSHong Zhang   col = 2 * s + 1;
9469566063dSJacob Faibussowitsch   PetscCall(DMDAGetCorners(da, &xs, &ys, &zs, &nx, &ny, &nz));
9479566063dSJacob Faibussowitsch   PetscCall(DMDAGetGhostCorners(da, &gxs, &gys, &gzs, &gnx, &gny, &gnz));
9489566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)da, &comm));
949711261dbSHong Zhang 
9509566063dSJacob Faibussowitsch   PetscCall(PetscMalloc2(nc, &rows, col * col * col * nc * nc, &cols));
9519566063dSJacob Faibussowitsch   PetscCall(DMGetLocalToGlobalMapping(da, &ltog));
952711261dbSHong Zhang 
9539566063dSJacob Faibussowitsch   PetscCall(MatSetBlockSize(J, nc));
954711261dbSHong Zhang   /* determine the matrix preallocation information */
955d0609cedSBarry Smith   MatPreallocateBegin(comm, nc * nx * ny * nz, nc * nx * ny * nz, dnz, onz);
956711261dbSHong Zhang   for (i = xs; i < xs + nx; i++) {
957711261dbSHong Zhang     istart = (bx == DM_BOUNDARY_PERIODIC) ? -s : (PetscMax(-s, -i));
958711261dbSHong Zhang     iend   = (bx == DM_BOUNDARY_PERIODIC) ? s : (PetscMin(s, m - i - 1));
959711261dbSHong Zhang     for (j = ys; j < ys + ny; j++) {
960711261dbSHong Zhang       jstart = (by == DM_BOUNDARY_PERIODIC) ? -s : (PetscMax(-s, -j));
961711261dbSHong Zhang       jend   = (by == DM_BOUNDARY_PERIODIC) ? s : (PetscMin(s, n - j - 1));
962711261dbSHong Zhang       for (k = zs; k < zs + nz; k++) {
963711261dbSHong Zhang         kstart = (bz == DM_BOUNDARY_PERIODIC) ? -s : (PetscMax(-s, -k));
964711261dbSHong Zhang         kend   = (bz == DM_BOUNDARY_PERIODIC) ? s : (PetscMin(s, p - k - 1));
965711261dbSHong Zhang 
966711261dbSHong Zhang         slot = i - gxs + gnx * (j - gys) + gnx * gny * (k - gzs);
967711261dbSHong Zhang 
968711261dbSHong Zhang         cnt = 0;
969711261dbSHong Zhang         for (l = 0; l < nc; l++) {
970711261dbSHong Zhang           for (ii = istart; ii < iend + 1; ii++) {
971711261dbSHong Zhang             for (jj = jstart; jj < jend + 1; jj++) {
972711261dbSHong Zhang               for (kk = kstart; kk < kend + 1; kk++) {
973711261dbSHong Zhang                 if ((st == DMDA_STENCIL_BOX) || ((!ii && !jj) || (!jj && !kk) || (!ii && !kk))) { /* entries on star*/
974711261dbSHong Zhang                   cols[cnt++] = l + nc * (slot + ii + gnx * jj + gnx * gny * kk);
975711261dbSHong Zhang                 }
976711261dbSHong Zhang               }
977711261dbSHong Zhang             }
978711261dbSHong Zhang           }
979711261dbSHong Zhang           rows[l] = l + nc * (slot);
980711261dbSHong Zhang         }
9819566063dSJacob Faibussowitsch         PetscCall(MatPreallocateSetLocal(ltog, nc, rows, ltog, cnt, cols, dnz, onz));
982711261dbSHong Zhang       }
983711261dbSHong Zhang     }
984711261dbSHong Zhang   }
9859566063dSJacob Faibussowitsch   PetscCall(MatSetBlockSize(J, nc));
9869566063dSJacob Faibussowitsch   PetscCall(MatSeqSELLSetPreallocation(J, 0, dnz));
9879566063dSJacob Faibussowitsch   PetscCall(MatMPISELLSetPreallocation(J, 0, dnz, 0, onz));
988d0609cedSBarry Smith   MatPreallocateEnd(dnz, onz);
9899566063dSJacob Faibussowitsch   PetscCall(MatSetLocalToGlobalMapping(J, ltog, ltog));
990711261dbSHong Zhang 
991711261dbSHong Zhang   /*
992711261dbSHong Zhang     For each node in the grid: we get the neighbors in the local (on processor ordering
993711261dbSHong Zhang     that includes the ghost points) then MatSetValuesLocal() maps those indices to the global
994711261dbSHong Zhang     PETSc ordering.
995711261dbSHong Zhang   */
996711261dbSHong Zhang   if (!da->prealloc_only) {
9979566063dSJacob Faibussowitsch     PetscCall(PetscCalloc1(col * col * col * nc * nc * nc, &values));
998711261dbSHong Zhang     for (i = xs; i < xs + nx; i++) {
999711261dbSHong Zhang       istart = (bx == DM_BOUNDARY_PERIODIC) ? -s : (PetscMax(-s, -i));
1000711261dbSHong Zhang       iend   = (bx == DM_BOUNDARY_PERIODIC) ? s : (PetscMin(s, m - i - 1));
1001711261dbSHong Zhang       for (j = ys; j < ys + ny; j++) {
1002711261dbSHong Zhang         jstart = (by == DM_BOUNDARY_PERIODIC) ? -s : (PetscMax(-s, -j));
1003711261dbSHong Zhang         jend   = (by == DM_BOUNDARY_PERIODIC) ? s : (PetscMin(s, n - j - 1));
1004711261dbSHong Zhang         for (k = zs; k < zs + nz; k++) {
1005711261dbSHong Zhang           kstart = (bz == DM_BOUNDARY_PERIODIC) ? -s : (PetscMax(-s, -k));
1006711261dbSHong Zhang           kend   = (bz == DM_BOUNDARY_PERIODIC) ? s : (PetscMin(s, p - k - 1));
1007711261dbSHong Zhang 
1008711261dbSHong Zhang           slot = i - gxs + gnx * (j - gys) + gnx * gny * (k - gzs);
1009711261dbSHong Zhang 
1010711261dbSHong Zhang           cnt = 0;
1011711261dbSHong Zhang           for (l = 0; l < nc; l++) {
1012711261dbSHong Zhang             for (ii = istart; ii < iend + 1; ii++) {
1013711261dbSHong Zhang               for (jj = jstart; jj < jend + 1; jj++) {
1014711261dbSHong Zhang                 for (kk = kstart; kk < kend + 1; kk++) {
1015711261dbSHong Zhang                   if ((st == DMDA_STENCIL_BOX) || ((!ii && !jj) || (!jj && !kk) || (!ii && !kk))) { /* entries on star*/
1016711261dbSHong Zhang                     cols[cnt++] = l + nc * (slot + ii + gnx * jj + gnx * gny * kk);
1017711261dbSHong Zhang                   }
1018711261dbSHong Zhang                 }
1019711261dbSHong Zhang               }
1020711261dbSHong Zhang             }
1021711261dbSHong Zhang             rows[l] = l + nc * (slot);
1022711261dbSHong Zhang           }
10239566063dSJacob Faibussowitsch           PetscCall(MatSetValuesLocal(J, nc, rows, cnt, cols, values, INSERT_VALUES));
1024711261dbSHong Zhang         }
1025711261dbSHong Zhang       }
1026711261dbSHong Zhang     }
10279566063dSJacob Faibussowitsch     PetscCall(PetscFree(values));
1028e7e92044SBarry Smith     /* do not copy values to GPU since they are all zero and not yet needed there */
10299566063dSJacob Faibussowitsch     PetscCall(MatBindToCPU(J, PETSC_TRUE));
10309566063dSJacob Faibussowitsch     PetscCall(MatAssemblyBegin(J, MAT_FINAL_ASSEMBLY));
10319566063dSJacob Faibussowitsch     PetscCall(MatAssemblyEnd(J, MAT_FINAL_ASSEMBLY));
10329566063dSJacob Faibussowitsch     PetscCall(MatBindToCPU(J, PETSC_FALSE));
10339566063dSJacob Faibussowitsch     PetscCall(MatSetOption(J, MAT_NEW_NONZERO_LOCATION_ERR, PETSC_TRUE));
1034711261dbSHong Zhang   }
10359566063dSJacob Faibussowitsch   PetscCall(PetscFree2(rows, cols));
10363ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1037711261dbSHong Zhang }
1038711261dbSHong Zhang 
1039d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateMatrix_DA_2d_MPIAIJ(DM da, Mat J)
1040d71ae5a4SJacob Faibussowitsch {
1041c1154cd5SBarry Smith   PetscInt               xs, ys, nx, ny, i, j, slot, gxs, gys, gnx, gny, m, n, dim, s, *cols = NULL, k, nc, *rows = NULL, col, cnt, l, p, M, N;
104247c6ae99SBarry Smith   PetscInt               lstart, lend, pstart, pend, *dnz, *onz;
104347c6ae99SBarry Smith   MPI_Comm               comm;
1044bff4a2f0SMatthew G. Knepley   DMBoundaryType         bx, by;
1045844bd0d7SStefano Zampini   ISLocalToGlobalMapping ltog, mltog;
1046aa219208SBarry Smith   DMDAStencilType        st;
1047b294de21SRichard Tran Mills   PetscBool              removedups = PETSC_FALSE, alreadyboundtocpu = PETSC_TRUE;
104847c6ae99SBarry Smith 
104947c6ae99SBarry Smith   PetscFunctionBegin;
105047c6ae99SBarry Smith   /*
105147c6ae99SBarry Smith          nc - number of components per grid point
105247c6ae99SBarry Smith          col - number of colors needed in one direction for single component problem
105347c6ae99SBarry Smith   */
1054924e958dSJunchao Zhang   PetscCall(DMDAGetInfo(da, &dim, &m, &n, NULL, &M, &N, NULL, &nc, &s, &bx, &by, NULL, &st));
10551baa6e33SBarry Smith   if (bx == DM_BOUNDARY_NONE && by == DM_BOUNDARY_NONE) PetscCall(MatSetOption(J, MAT_SORTED_FULL, PETSC_TRUE));
105647c6ae99SBarry Smith   col = 2 * s + 1;
1057c1154cd5SBarry Smith   /*
1058c1154cd5SBarry Smith        With one processor in periodic domains in a skinny dimension the code will label nonzero columns multiple times
1059c1154cd5SBarry Smith        because of "wrapping" around the end of the domain hitting an entry already counted in the other direction.
1060c1154cd5SBarry Smith   */
1061c1154cd5SBarry Smith   if (M == 1 && 2 * s >= m) removedups = PETSC_TRUE;
1062c1154cd5SBarry Smith   if (N == 1 && 2 * s >= n) removedups = PETSC_TRUE;
10639566063dSJacob Faibussowitsch   PetscCall(DMDAGetCorners(da, &xs, &ys, NULL, &nx, &ny, NULL));
10649566063dSJacob Faibussowitsch   PetscCall(DMDAGetGhostCorners(da, &gxs, &gys, NULL, &gnx, &gny, NULL));
10659566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)da, &comm));
106647c6ae99SBarry Smith 
10679566063dSJacob Faibussowitsch   PetscCall(PetscMalloc2(nc, &rows, col * col * nc * nc, &cols));
10689566063dSJacob Faibussowitsch   PetscCall(DMGetLocalToGlobalMapping(da, &ltog));
106947c6ae99SBarry Smith 
10709566063dSJacob Faibussowitsch   PetscCall(MatSetBlockSize(J, nc));
107147c6ae99SBarry Smith   /* determine the matrix preallocation information */
1072d0609cedSBarry Smith   MatPreallocateBegin(comm, nc * nx * ny, nc * nx * ny, dnz, onz);
107347c6ae99SBarry Smith   for (i = xs; i < xs + nx; i++) {
1074bff4a2f0SMatthew G. Knepley     pstart = (bx == DM_BOUNDARY_PERIODIC) ? -s : (PetscMax(-s, -i));
1075bff4a2f0SMatthew G. Knepley     pend   = (bx == DM_BOUNDARY_PERIODIC) ? s : (PetscMin(s, m - i - 1));
107647c6ae99SBarry Smith 
107747c6ae99SBarry Smith     for (j = ys; j < ys + ny; j++) {
107847c6ae99SBarry Smith       slot = i - gxs + gnx * (j - gys);
107947c6ae99SBarry Smith 
1080bff4a2f0SMatthew G. Knepley       lstart = (by == DM_BOUNDARY_PERIODIC) ? -s : (PetscMax(-s, -j));
1081bff4a2f0SMatthew G. Knepley       lend   = (by == DM_BOUNDARY_PERIODIC) ? s : (PetscMin(s, n - j - 1));
108247c6ae99SBarry Smith 
108347c6ae99SBarry Smith       cnt = 0;
108447c6ae99SBarry Smith       for (k = 0; k < nc; k++) {
108547c6ae99SBarry Smith         for (l = lstart; l < lend + 1; l++) {
108647c6ae99SBarry Smith           for (p = pstart; p < pend + 1; p++) {
1087aa219208SBarry Smith             if ((st == DMDA_STENCIL_BOX) || (!l || !p)) { /* entries on star have either l = 0 or p = 0 */
108847c6ae99SBarry Smith               cols[cnt++] = k + nc * (slot + gnx * l + p);
108947c6ae99SBarry Smith             }
109047c6ae99SBarry Smith           }
109147c6ae99SBarry Smith         }
109247c6ae99SBarry Smith         rows[k] = k + nc * (slot);
109347c6ae99SBarry Smith       }
10941baa6e33SBarry Smith       if (removedups) PetscCall(MatPreallocateSetLocalRemoveDups(ltog, nc, rows, ltog, cnt, cols, dnz, onz));
10951baa6e33SBarry Smith       else PetscCall(MatPreallocateSetLocal(ltog, nc, rows, ltog, cnt, cols, dnz, onz));
109647c6ae99SBarry Smith     }
1097c1154cd5SBarry Smith   }
10989566063dSJacob Faibussowitsch   PetscCall(MatSetBlockSize(J, nc));
10999566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJSetPreallocation(J, 0, dnz));
11009566063dSJacob Faibussowitsch   PetscCall(MatMPIAIJSetPreallocation(J, 0, dnz, 0, onz));
1101d0609cedSBarry Smith   MatPreallocateEnd(dnz, onz);
11029566063dSJacob Faibussowitsch   PetscCall(MatGetLocalToGlobalMapping(J, &mltog, NULL));
11031baa6e33SBarry Smith   if (!mltog) PetscCall(MatSetLocalToGlobalMapping(J, ltog, ltog));
110447c6ae99SBarry Smith 
110547c6ae99SBarry Smith   /*
110647c6ae99SBarry Smith     For each node in the grid: we get the neighbors in the local (on processor ordering
110747c6ae99SBarry Smith     that includes the ghost points) then MatSetValuesLocal() maps those indices to the global
110847c6ae99SBarry Smith     PETSc ordering.
110947c6ae99SBarry Smith   */
1110fcfd50ebSBarry Smith   if (!da->prealloc_only) {
111147c6ae99SBarry Smith     for (i = xs; i < xs + nx; i++) {
1112bff4a2f0SMatthew G. Knepley       pstart = (bx == DM_BOUNDARY_PERIODIC) ? -s : (PetscMax(-s, -i));
1113bff4a2f0SMatthew G. Knepley       pend   = (bx == DM_BOUNDARY_PERIODIC) ? s : (PetscMin(s, m - i - 1));
111447c6ae99SBarry Smith 
111547c6ae99SBarry Smith       for (j = ys; j < ys + ny; j++) {
111647c6ae99SBarry Smith         slot = i - gxs + gnx * (j - gys);
111747c6ae99SBarry Smith 
1118bff4a2f0SMatthew G. Knepley         lstart = (by == DM_BOUNDARY_PERIODIC) ? -s : (PetscMax(-s, -j));
1119bff4a2f0SMatthew G. Knepley         lend   = (by == DM_BOUNDARY_PERIODIC) ? s : (PetscMin(s, n - j - 1));
112047c6ae99SBarry Smith 
112147c6ae99SBarry Smith         cnt = 0;
112247c6ae99SBarry Smith         for (l = lstart; l < lend + 1; l++) {
112347c6ae99SBarry Smith           for (p = pstart; p < pend + 1; p++) {
1124aa219208SBarry Smith             if ((st == DMDA_STENCIL_BOX) || (!l || !p)) { /* entries on star have either l = 0 or p = 0 */
1125071fcb05SBarry Smith               cols[cnt++] = nc * (slot + gnx * l + p);
1126071fcb05SBarry Smith               for (k = 1; k < nc; k++) {
11279371c9d4SSatish Balay                 cols[cnt] = 1 + cols[cnt - 1];
11289371c9d4SSatish Balay                 cnt++;
112947c6ae99SBarry Smith               }
113047c6ae99SBarry Smith             }
113147c6ae99SBarry Smith           }
113247c6ae99SBarry Smith         }
1133071fcb05SBarry Smith         for (k = 0; k < nc; k++) rows[k] = k + nc * (slot);
11349566063dSJacob Faibussowitsch         PetscCall(MatSetValuesLocal(J, nc, rows, cnt, cols, NULL, INSERT_VALUES));
113547c6ae99SBarry Smith       }
113647c6ae99SBarry Smith     }
1137e7e92044SBarry Smith     /* do not copy values to GPU since they are all zero and not yet needed there */
11389566063dSJacob Faibussowitsch     PetscCall(MatBoundToCPU(J, &alreadyboundtocpu));
11399566063dSJacob Faibussowitsch     PetscCall(MatBindToCPU(J, PETSC_TRUE));
11409566063dSJacob Faibussowitsch     PetscCall(MatAssemblyBegin(J, MAT_FINAL_ASSEMBLY));
11419566063dSJacob Faibussowitsch     PetscCall(MatAssemblyEnd(J, MAT_FINAL_ASSEMBLY));
11429566063dSJacob Faibussowitsch     if (!alreadyboundtocpu) PetscCall(MatBindToCPU(J, PETSC_FALSE));
11439566063dSJacob Faibussowitsch     PetscCall(MatSetOption(J, MAT_NEW_NONZERO_LOCATION_ERR, PETSC_TRUE));
11441baa6e33SBarry Smith     if (bx == DM_BOUNDARY_NONE && by == DM_BOUNDARY_NONE) PetscCall(MatSetOption(J, MAT_SORTED_FULL, PETSC_FALSE));
114547c6ae99SBarry Smith   }
11469566063dSJacob Faibussowitsch   PetscCall(PetscFree2(rows, cols));
11473ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
114847c6ae99SBarry Smith }
114947c6ae99SBarry Smith 
1150d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateMatrix_DA_2d_MPIAIJ_Fill(DM da, Mat J)
1151d71ae5a4SJacob Faibussowitsch {
115247c6ae99SBarry Smith   PetscInt               xs, ys, nx, ny, i, j, slot, gxs, gys, gnx, gny;
1153c1154cd5SBarry Smith   PetscInt               m, n, dim, s, *cols, k, nc, row, col, cnt, maxcnt = 0, l, p, M, N;
115447c6ae99SBarry Smith   PetscInt               lstart, lend, pstart, pend, *dnz, *onz;
115547c6ae99SBarry Smith   DM_DA                 *dd = (DM_DA *)da->data;
115647c6ae99SBarry Smith   PetscInt               ifill_col, *ofill = dd->ofill, *dfill = dd->dfill;
115747c6ae99SBarry Smith   MPI_Comm               comm;
1158bff4a2f0SMatthew G. Knepley   DMBoundaryType         bx, by;
115945b6f7e9SBarry Smith   ISLocalToGlobalMapping ltog;
1160aa219208SBarry Smith   DMDAStencilType        st;
1161c1154cd5SBarry Smith   PetscBool              removedups = PETSC_FALSE;
116247c6ae99SBarry Smith 
116347c6ae99SBarry Smith   PetscFunctionBegin;
116447c6ae99SBarry Smith   /*
116547c6ae99SBarry Smith          nc - number of components per grid point
116647c6ae99SBarry Smith          col - number of colors needed in one direction for single component problem
116747c6ae99SBarry Smith   */
1168924e958dSJunchao Zhang   PetscCall(DMDAGetInfo(da, &dim, &m, &n, NULL, &M, &N, NULL, &nc, &s, &bx, &by, NULL, &st));
116947c6ae99SBarry Smith   col = 2 * s + 1;
1170c1154cd5SBarry Smith   /*
1171c1154cd5SBarry Smith        With one processor in periodic domains in a skinny dimension the code will label nonzero columns multiple times
1172c1154cd5SBarry Smith        because of "wrapping" around the end of the domain hitting an entry already counted in the other direction.
1173c1154cd5SBarry Smith   */
1174c1154cd5SBarry Smith   if (M == 1 && 2 * s >= m) removedups = PETSC_TRUE;
1175c1154cd5SBarry Smith   if (N == 1 && 2 * s >= n) removedups = PETSC_TRUE;
11769566063dSJacob Faibussowitsch   PetscCall(DMDAGetCorners(da, &xs, &ys, NULL, &nx, &ny, NULL));
11779566063dSJacob Faibussowitsch   PetscCall(DMDAGetGhostCorners(da, &gxs, &gys, NULL, &gnx, &gny, NULL));
11789566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)da, &comm));
117947c6ae99SBarry Smith 
11809566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(col * col * nc, &cols));
11819566063dSJacob Faibussowitsch   PetscCall(DMGetLocalToGlobalMapping(da, &ltog));
118247c6ae99SBarry Smith 
11839566063dSJacob Faibussowitsch   PetscCall(MatSetBlockSize(J, nc));
118447c6ae99SBarry Smith   /* determine the matrix preallocation information */
1185d0609cedSBarry Smith   MatPreallocateBegin(comm, nc * nx * ny, nc * nx * ny, dnz, onz);
118647c6ae99SBarry Smith   for (i = xs; i < xs + nx; i++) {
1187bff4a2f0SMatthew G. Knepley     pstart = (bx == DM_BOUNDARY_PERIODIC) ? -s : (PetscMax(-s, -i));
1188bff4a2f0SMatthew G. Knepley     pend   = (bx == DM_BOUNDARY_PERIODIC) ? s : (PetscMin(s, m - i - 1));
118947c6ae99SBarry Smith 
119047c6ae99SBarry Smith     for (j = ys; j < ys + ny; j++) {
119147c6ae99SBarry Smith       slot = i - gxs + gnx * (j - gys);
119247c6ae99SBarry Smith 
1193bff4a2f0SMatthew G. Knepley       lstart = (by == DM_BOUNDARY_PERIODIC) ? -s : (PetscMax(-s, -j));
1194bff4a2f0SMatthew G. Knepley       lend   = (by == DM_BOUNDARY_PERIODIC) ? s : (PetscMin(s, n - j - 1));
119547c6ae99SBarry Smith 
119647c6ae99SBarry Smith       for (k = 0; k < nc; k++) {
119747c6ae99SBarry Smith         cnt = 0;
119847c6ae99SBarry Smith         for (l = lstart; l < lend + 1; l++) {
119947c6ae99SBarry Smith           for (p = pstart; p < pend + 1; p++) {
120047c6ae99SBarry Smith             if (l || p) {
1201aa219208SBarry Smith               if ((st == DMDA_STENCIL_BOX) || (!l || !p)) { /* entries on star */
12028865f1eaSKarl Rupp                 for (ifill_col = ofill[k]; ifill_col < ofill[k + 1]; ifill_col++) cols[cnt++] = ofill[ifill_col] + nc * (slot + gnx * l + p);
120347c6ae99SBarry Smith               }
120447c6ae99SBarry Smith             } else {
120547c6ae99SBarry Smith               if (dfill) {
12068865f1eaSKarl Rupp                 for (ifill_col = dfill[k]; ifill_col < dfill[k + 1]; ifill_col++) cols[cnt++] = dfill[ifill_col] + nc * (slot + gnx * l + p);
120747c6ae99SBarry Smith               } else {
12088865f1eaSKarl Rupp                 for (ifill_col = 0; ifill_col < nc; ifill_col++) cols[cnt++] = ifill_col + nc * (slot + gnx * l + p);
120947c6ae99SBarry Smith               }
121047c6ae99SBarry Smith             }
121147c6ae99SBarry Smith           }
121247c6ae99SBarry Smith         }
121347c6ae99SBarry Smith         row    = k + nc * (slot);
1214c0ab637bSBarry Smith         maxcnt = PetscMax(maxcnt, cnt);
12151baa6e33SBarry Smith         if (removedups) PetscCall(MatPreallocateSetLocalRemoveDups(ltog, 1, &row, ltog, cnt, cols, dnz, onz));
12161baa6e33SBarry Smith         else PetscCall(MatPreallocateSetLocal(ltog, 1, &row, ltog, cnt, cols, dnz, onz));
121747c6ae99SBarry Smith       }
121847c6ae99SBarry Smith     }
1219c1154cd5SBarry Smith   }
12209566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJSetPreallocation(J, 0, dnz));
12219566063dSJacob Faibussowitsch   PetscCall(MatMPIAIJSetPreallocation(J, 0, dnz, 0, onz));
1222d0609cedSBarry Smith   MatPreallocateEnd(dnz, onz);
12239566063dSJacob Faibussowitsch   PetscCall(MatSetLocalToGlobalMapping(J, ltog, ltog));
122447c6ae99SBarry Smith 
122547c6ae99SBarry Smith   /*
122647c6ae99SBarry Smith     For each node in the grid: we get the neighbors in the local (on processor ordering
122747c6ae99SBarry Smith     that includes the ghost points) then MatSetValuesLocal() maps those indices to the global
122847c6ae99SBarry Smith     PETSc ordering.
122947c6ae99SBarry Smith   */
1230fcfd50ebSBarry Smith   if (!da->prealloc_only) {
123147c6ae99SBarry Smith     for (i = xs; i < xs + nx; i++) {
1232bff4a2f0SMatthew G. Knepley       pstart = (bx == DM_BOUNDARY_PERIODIC) ? -s : (PetscMax(-s, -i));
1233bff4a2f0SMatthew G. Knepley       pend   = (bx == DM_BOUNDARY_PERIODIC) ? s : (PetscMin(s, m - i - 1));
123447c6ae99SBarry Smith 
123547c6ae99SBarry Smith       for (j = ys; j < ys + ny; j++) {
123647c6ae99SBarry Smith         slot = i - gxs + gnx * (j - gys);
123747c6ae99SBarry Smith 
1238bff4a2f0SMatthew G. Knepley         lstart = (by == DM_BOUNDARY_PERIODIC) ? -s : (PetscMax(-s, -j));
1239bff4a2f0SMatthew G. Knepley         lend   = (by == DM_BOUNDARY_PERIODIC) ? s : (PetscMin(s, n - j - 1));
124047c6ae99SBarry Smith 
124147c6ae99SBarry Smith         for (k = 0; k < nc; k++) {
124247c6ae99SBarry Smith           cnt = 0;
124347c6ae99SBarry Smith           for (l = lstart; l < lend + 1; l++) {
124447c6ae99SBarry Smith             for (p = pstart; p < pend + 1; p++) {
124547c6ae99SBarry Smith               if (l || p) {
1246aa219208SBarry Smith                 if ((st == DMDA_STENCIL_BOX) || (!l || !p)) { /* entries on star */
12478865f1eaSKarl Rupp                   for (ifill_col = ofill[k]; ifill_col < ofill[k + 1]; ifill_col++) cols[cnt++] = ofill[ifill_col] + nc * (slot + gnx * l + p);
124847c6ae99SBarry Smith                 }
124947c6ae99SBarry Smith               } else {
125047c6ae99SBarry Smith                 if (dfill) {
12518865f1eaSKarl Rupp                   for (ifill_col = dfill[k]; ifill_col < dfill[k + 1]; ifill_col++) cols[cnt++] = dfill[ifill_col] + nc * (slot + gnx * l + p);
125247c6ae99SBarry Smith                 } else {
12538865f1eaSKarl Rupp                   for (ifill_col = 0; ifill_col < nc; ifill_col++) cols[cnt++] = ifill_col + nc * (slot + gnx * l + p);
125447c6ae99SBarry Smith                 }
125547c6ae99SBarry Smith               }
125647c6ae99SBarry Smith             }
125747c6ae99SBarry Smith           }
125847c6ae99SBarry Smith           row = k + nc * (slot);
12599566063dSJacob Faibussowitsch           PetscCall(MatSetValuesLocal(J, 1, &row, cnt, cols, NULL, INSERT_VALUES));
126047c6ae99SBarry Smith         }
126147c6ae99SBarry Smith       }
126247c6ae99SBarry Smith     }
1263e7e92044SBarry Smith     /* do not copy values to GPU since they are all zero and not yet needed there */
12649566063dSJacob Faibussowitsch     PetscCall(MatBindToCPU(J, PETSC_TRUE));
12659566063dSJacob Faibussowitsch     PetscCall(MatAssemblyBegin(J, MAT_FINAL_ASSEMBLY));
12669566063dSJacob Faibussowitsch     PetscCall(MatAssemblyEnd(J, MAT_FINAL_ASSEMBLY));
12679566063dSJacob Faibussowitsch     PetscCall(MatBindToCPU(J, PETSC_FALSE));
12689566063dSJacob Faibussowitsch     PetscCall(MatSetOption(J, MAT_NEW_NONZERO_LOCATION_ERR, PETSC_TRUE));
126947c6ae99SBarry Smith   }
12709566063dSJacob Faibussowitsch   PetscCall(PetscFree(cols));
12713ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
127247c6ae99SBarry Smith }
127347c6ae99SBarry Smith 
1274d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateMatrix_DA_3d_MPIAIJ(DM da, Mat J)
1275d71ae5a4SJacob Faibussowitsch {
127647c6ae99SBarry Smith   PetscInt               xs, ys, nx, ny, i, j, slot, gxs, gys, gnx, gny;
12770298fd71SBarry Smith   PetscInt               m, n, dim, s, *cols = NULL, k, nc, *rows = NULL, col, cnt, l, p, *dnz = NULL, *onz = NULL;
1278c1154cd5SBarry Smith   PetscInt               istart, iend, jstart, jend, kstart, kend, zs, nz, gzs, gnz, ii, jj, kk, M, N, P;
127947c6ae99SBarry Smith   MPI_Comm               comm;
1280bff4a2f0SMatthew G. Knepley   DMBoundaryType         bx, by, bz;
1281844bd0d7SStefano Zampini   ISLocalToGlobalMapping ltog, mltog;
1282aa219208SBarry Smith   DMDAStencilType        st;
1283c1154cd5SBarry Smith   PetscBool              removedups = PETSC_FALSE;
128447c6ae99SBarry Smith 
128547c6ae99SBarry Smith   PetscFunctionBegin;
128647c6ae99SBarry Smith   /*
128747c6ae99SBarry Smith          nc - number of components per grid point
128847c6ae99SBarry Smith          col - number of colors needed in one direction for single component problem
128947c6ae99SBarry Smith   */
12909566063dSJacob Faibussowitsch   PetscCall(DMDAGetInfo(da, &dim, &m, &n, &p, &M, &N, &P, &nc, &s, &bx, &by, &bz, &st));
129148a46eb9SPierre Jolivet   if (bx == DM_BOUNDARY_NONE && by == DM_BOUNDARY_NONE && bz == DM_BOUNDARY_NONE) PetscCall(MatSetOption(J, MAT_SORTED_FULL, PETSC_TRUE));
129247c6ae99SBarry Smith   col = 2 * s + 1;
129347c6ae99SBarry Smith 
1294c1154cd5SBarry Smith   /*
1295c1154cd5SBarry Smith        With one processor in periodic domains in a skinny dimension the code will label nonzero columns multiple times
1296c1154cd5SBarry Smith        because of "wrapping" around the end of the domain hitting an entry already counted in the other direction.
1297c1154cd5SBarry Smith   */
1298c1154cd5SBarry Smith   if (M == 1 && 2 * s >= m) removedups = PETSC_TRUE;
1299c1154cd5SBarry Smith   if (N == 1 && 2 * s >= n) removedups = PETSC_TRUE;
1300c1154cd5SBarry Smith   if (P == 1 && 2 * s >= p) removedups = PETSC_TRUE;
1301c1154cd5SBarry Smith 
13029566063dSJacob Faibussowitsch   PetscCall(DMDAGetCorners(da, &xs, &ys, &zs, &nx, &ny, &nz));
13039566063dSJacob Faibussowitsch   PetscCall(DMDAGetGhostCorners(da, &gxs, &gys, &gzs, &gnx, &gny, &gnz));
13049566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)da, &comm));
130547c6ae99SBarry Smith 
13069566063dSJacob Faibussowitsch   PetscCall(PetscMalloc2(nc, &rows, col * col * col * nc * nc, &cols));
13079566063dSJacob Faibussowitsch   PetscCall(DMGetLocalToGlobalMapping(da, &ltog));
130847c6ae99SBarry Smith 
13099566063dSJacob Faibussowitsch   PetscCall(MatSetBlockSize(J, nc));
131047c6ae99SBarry Smith   /* determine the matrix preallocation information */
1311d0609cedSBarry Smith   MatPreallocateBegin(comm, nc * nx * ny * nz, nc * nx * ny * nz, dnz, onz);
131247c6ae99SBarry Smith   for (i = xs; i < xs + nx; i++) {
1313bff4a2f0SMatthew G. Knepley     istart = (bx == DM_BOUNDARY_PERIODIC) ? -s : (PetscMax(-s, -i));
1314bff4a2f0SMatthew G. Knepley     iend   = (bx == DM_BOUNDARY_PERIODIC) ? s : (PetscMin(s, m - i - 1));
131547c6ae99SBarry Smith     for (j = ys; j < ys + ny; j++) {
1316bff4a2f0SMatthew G. Knepley       jstart = (by == DM_BOUNDARY_PERIODIC) ? -s : (PetscMax(-s, -j));
1317bff4a2f0SMatthew G. Knepley       jend   = (by == DM_BOUNDARY_PERIODIC) ? s : (PetscMin(s, n - j - 1));
131847c6ae99SBarry Smith       for (k = zs; k < zs + nz; k++) {
1319bff4a2f0SMatthew G. Knepley         kstart = (bz == DM_BOUNDARY_PERIODIC) ? -s : (PetscMax(-s, -k));
1320bff4a2f0SMatthew G. Knepley         kend   = (bz == DM_BOUNDARY_PERIODIC) ? s : (PetscMin(s, p - k - 1));
132147c6ae99SBarry Smith 
132247c6ae99SBarry Smith         slot = i - gxs + gnx * (j - gys) + gnx * gny * (k - gzs);
132347c6ae99SBarry Smith 
132447c6ae99SBarry Smith         cnt = 0;
132547c6ae99SBarry Smith         for (l = 0; l < nc; l++) {
132647c6ae99SBarry Smith           for (ii = istart; ii < iend + 1; ii++) {
132747c6ae99SBarry Smith             for (jj = jstart; jj < jend + 1; jj++) {
132847c6ae99SBarry Smith               for (kk = kstart; kk < kend + 1; kk++) {
1329aa219208SBarry Smith                 if ((st == DMDA_STENCIL_BOX) || ((!ii && !jj) || (!jj && !kk) || (!ii && !kk))) { /* entries on star*/
133047c6ae99SBarry Smith                   cols[cnt++] = l + nc * (slot + ii + gnx * jj + gnx * gny * kk);
133147c6ae99SBarry Smith                 }
133247c6ae99SBarry Smith               }
133347c6ae99SBarry Smith             }
133447c6ae99SBarry Smith           }
133547c6ae99SBarry Smith           rows[l] = l + nc * (slot);
133647c6ae99SBarry Smith         }
13371baa6e33SBarry Smith         if (removedups) PetscCall(MatPreallocateSetLocalRemoveDups(ltog, nc, rows, ltog, cnt, cols, dnz, onz));
13381baa6e33SBarry Smith         else PetscCall(MatPreallocateSetLocal(ltog, nc, rows, ltog, cnt, cols, dnz, onz));
133947c6ae99SBarry Smith       }
134047c6ae99SBarry Smith     }
1341c1154cd5SBarry Smith   }
13429566063dSJacob Faibussowitsch   PetscCall(MatSetBlockSize(J, nc));
13439566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJSetPreallocation(J, 0, dnz));
13449566063dSJacob Faibussowitsch   PetscCall(MatMPIAIJSetPreallocation(J, 0, dnz, 0, onz));
1345d0609cedSBarry Smith   MatPreallocateEnd(dnz, onz);
13469566063dSJacob Faibussowitsch   PetscCall(MatGetLocalToGlobalMapping(J, &mltog, NULL));
134748a46eb9SPierre Jolivet   if (!mltog) PetscCall(MatSetLocalToGlobalMapping(J, ltog, ltog));
134847c6ae99SBarry Smith 
134947c6ae99SBarry Smith   /*
135047c6ae99SBarry Smith     For each node in the grid: we get the neighbors in the local (on processor ordering
135147c6ae99SBarry Smith     that includes the ghost points) then MatSetValuesLocal() maps those indices to the global
135247c6ae99SBarry Smith     PETSc ordering.
135347c6ae99SBarry Smith   */
1354fcfd50ebSBarry Smith   if (!da->prealloc_only) {
135547c6ae99SBarry Smith     for (i = xs; i < xs + nx; i++) {
1356bff4a2f0SMatthew G. Knepley       istart = (bx == DM_BOUNDARY_PERIODIC) ? -s : (PetscMax(-s, -i));
1357bff4a2f0SMatthew G. Knepley       iend   = (bx == DM_BOUNDARY_PERIODIC) ? s : (PetscMin(s, m - i - 1));
135847c6ae99SBarry Smith       for (j = ys; j < ys + ny; j++) {
1359bff4a2f0SMatthew G. Knepley         jstart = (by == DM_BOUNDARY_PERIODIC) ? -s : (PetscMax(-s, -j));
1360bff4a2f0SMatthew G. Knepley         jend   = (by == DM_BOUNDARY_PERIODIC) ? s : (PetscMin(s, n - j - 1));
136147c6ae99SBarry Smith         for (k = zs; k < zs + nz; k++) {
1362bff4a2f0SMatthew G. Knepley           kstart = (bz == DM_BOUNDARY_PERIODIC) ? -s : (PetscMax(-s, -k));
1363bff4a2f0SMatthew G. Knepley           kend   = (bz == DM_BOUNDARY_PERIODIC) ? s : (PetscMin(s, p - k - 1));
136447c6ae99SBarry Smith 
136547c6ae99SBarry Smith           slot = i - gxs + gnx * (j - gys) + gnx * gny * (k - gzs);
136647c6ae99SBarry Smith 
136747c6ae99SBarry Smith           cnt = 0;
136847c6ae99SBarry Smith           for (kk = kstart; kk < kend + 1; kk++) {
1369071fcb05SBarry Smith             for (jj = jstart; jj < jend + 1; jj++) {
1370071fcb05SBarry Smith               for (ii = istart; ii < iend + 1; ii++) {
1371aa219208SBarry Smith                 if ((st == DMDA_STENCIL_BOX) || ((!ii && !jj) || (!jj && !kk) || (!ii && !kk))) { /* entries on star*/
1372071fcb05SBarry Smith                   cols[cnt++] = nc * (slot + ii + gnx * jj + gnx * gny * kk);
1373071fcb05SBarry Smith                   for (l = 1; l < nc; l++) {
13749371c9d4SSatish Balay                     cols[cnt] = 1 + cols[cnt - 1];
13759371c9d4SSatish Balay                     cnt++;
137647c6ae99SBarry Smith                   }
137747c6ae99SBarry Smith                 }
137847c6ae99SBarry Smith               }
137947c6ae99SBarry Smith             }
138047c6ae99SBarry Smith           }
13819371c9d4SSatish Balay           rows[0] = nc * (slot);
13829371c9d4SSatish Balay           for (l = 1; l < nc; l++) rows[l] = 1 + rows[l - 1];
13839566063dSJacob Faibussowitsch           PetscCall(MatSetValuesLocal(J, nc, rows, cnt, cols, NULL, INSERT_VALUES));
138447c6ae99SBarry Smith         }
138547c6ae99SBarry Smith       }
138647c6ae99SBarry Smith     }
1387e7e92044SBarry Smith     /* do not copy values to GPU since they are all zero and not yet needed there */
13889566063dSJacob Faibussowitsch     PetscCall(MatBindToCPU(J, PETSC_TRUE));
13899566063dSJacob Faibussowitsch     PetscCall(MatAssemblyBegin(J, MAT_FINAL_ASSEMBLY));
13909566063dSJacob Faibussowitsch     PetscCall(MatAssemblyEnd(J, MAT_FINAL_ASSEMBLY));
139148a46eb9SPierre Jolivet     if (bx == DM_BOUNDARY_NONE && by == DM_BOUNDARY_NONE && bz == DM_BOUNDARY_NONE) PetscCall(MatSetOption(J, MAT_SORTED_FULL, PETSC_FALSE));
13929566063dSJacob Faibussowitsch     PetscCall(MatBindToCPU(J, PETSC_FALSE));
13939566063dSJacob Faibussowitsch     PetscCall(MatSetOption(J, MAT_NEW_NONZERO_LOCATION_ERR, PETSC_TRUE));
139447c6ae99SBarry Smith   }
13959566063dSJacob Faibussowitsch   PetscCall(PetscFree2(rows, cols));
13963ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
139747c6ae99SBarry Smith }
139847c6ae99SBarry Smith 
1399d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateMatrix_DA_1d_MPIAIJ_Fill(DM da, Mat J)
1400d71ae5a4SJacob Faibussowitsch {
1401ce308e1dSBarry Smith   DM_DA                 *dd = (DM_DA *)da->data;
1402ce308e1dSBarry Smith   PetscInt               xs, nx, i, j, gxs, gnx, row, k, l;
14038d4c968fSBarry Smith   PetscInt               m, dim, s, *cols = NULL, nc, cnt, maxcnt = 0, *ocols;
14040acb5bebSBarry Smith   PetscInt              *ofill = dd->ofill, *dfill = dd->dfill;
1405bff4a2f0SMatthew G. Knepley   DMBoundaryType         bx;
140645b6f7e9SBarry Smith   ISLocalToGlobalMapping ltog;
1407ce308e1dSBarry Smith   PetscMPIInt            rank, size;
1408ce308e1dSBarry Smith 
1409ce308e1dSBarry Smith   PetscFunctionBegin;
14109566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)da), &rank));
14119566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)da), &size));
1412ce308e1dSBarry Smith 
1413ce308e1dSBarry Smith   /*
1414ce308e1dSBarry Smith          nc - number of components per grid point
1415ce308e1dSBarry Smith   */
14169566063dSJacob Faibussowitsch   PetscCall(DMDAGetInfo(da, &dim, &m, NULL, NULL, NULL, NULL, NULL, &nc, &s, &bx, NULL, NULL, NULL));
141708401ef6SPierre Jolivet   PetscCheck(s <= 1, PetscObjectComm((PetscObject)da), PETSC_ERR_SUP, "Matrix creation for 1d not implemented correctly for stencil width larger than 1");
14189566063dSJacob Faibussowitsch   PetscCall(DMDAGetCorners(da, &xs, NULL, NULL, &nx, NULL, NULL));
14199566063dSJacob Faibussowitsch   PetscCall(DMDAGetGhostCorners(da, &gxs, NULL, NULL, &gnx, NULL, NULL));
1420ce308e1dSBarry Smith 
14219566063dSJacob Faibussowitsch   PetscCall(MatSetBlockSize(J, nc));
14229566063dSJacob Faibussowitsch   PetscCall(PetscCalloc2(nx * nc, &cols, nx * nc, &ocols));
1423ce308e1dSBarry Smith 
1424ce308e1dSBarry Smith   /*
1425ce308e1dSBarry Smith         note should be smaller for first and last process with no periodic
1426ce308e1dSBarry Smith         does not handle dfill
1427ce308e1dSBarry Smith   */
1428ce308e1dSBarry Smith   cnt = 0;
1429ce308e1dSBarry Smith   /* coupling with process to the left */
1430ce308e1dSBarry Smith   for (i = 0; i < s; i++) {
1431ce308e1dSBarry Smith     for (j = 0; j < nc; j++) {
1432dd400576SPatrick Sanan       ocols[cnt] = ((rank == 0) ? 0 : (s - i) * (ofill[j + 1] - ofill[j]));
14330acb5bebSBarry Smith       cols[cnt]  = dfill[j + 1] - dfill[j] + (s + i) * (ofill[j + 1] - ofill[j]);
1434dd400576SPatrick Sanan       if (rank == 0 && (dd->bx == DM_BOUNDARY_PERIODIC)) {
1435831644c1SBarry Smith         if (size > 1) ocols[cnt] += (s - i) * (ofill[j + 1] - ofill[j]);
1436831644c1SBarry Smith         else cols[cnt] += (s - i) * (ofill[j + 1] - ofill[j]);
1437831644c1SBarry Smith       }
1438c0ab637bSBarry Smith       maxcnt = PetscMax(maxcnt, ocols[cnt] + cols[cnt]);
1439ce308e1dSBarry Smith       cnt++;
1440ce308e1dSBarry Smith     }
1441ce308e1dSBarry Smith   }
1442ce308e1dSBarry Smith   for (i = s; i < nx - s; i++) {
1443ce308e1dSBarry Smith     for (j = 0; j < nc; j++) {
14440acb5bebSBarry Smith       cols[cnt] = dfill[j + 1] - dfill[j] + 2 * s * (ofill[j + 1] - ofill[j]);
1445c0ab637bSBarry Smith       maxcnt    = PetscMax(maxcnt, ocols[cnt] + cols[cnt]);
1446ce308e1dSBarry Smith       cnt++;
1447ce308e1dSBarry Smith     }
1448ce308e1dSBarry Smith   }
1449ce308e1dSBarry Smith   /* coupling with process to the right */
1450ce308e1dSBarry Smith   for (i = nx - s; i < nx; i++) {
1451ce308e1dSBarry Smith     for (j = 0; j < nc; j++) {
1452ce308e1dSBarry Smith       ocols[cnt] = ((rank == (size - 1)) ? 0 : (i - nx + s + 1) * (ofill[j + 1] - ofill[j]));
14530acb5bebSBarry Smith       cols[cnt]  = dfill[j + 1] - dfill[j] + (s + nx - i - 1) * (ofill[j + 1] - ofill[j]);
1454831644c1SBarry Smith       if ((rank == size - 1) && (dd->bx == DM_BOUNDARY_PERIODIC)) {
1455831644c1SBarry Smith         if (size > 1) ocols[cnt] += (i - nx + s + 1) * (ofill[j + 1] - ofill[j]);
1456831644c1SBarry Smith         else cols[cnt] += (i - nx + s + 1) * (ofill[j + 1] - ofill[j]);
1457831644c1SBarry Smith       }
1458c0ab637bSBarry Smith       maxcnt = PetscMax(maxcnt, ocols[cnt] + cols[cnt]);
1459ce308e1dSBarry Smith       cnt++;
1460ce308e1dSBarry Smith     }
1461ce308e1dSBarry Smith   }
1462ce308e1dSBarry Smith 
14639566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJSetPreallocation(J, 0, cols));
14649566063dSJacob Faibussowitsch   PetscCall(MatMPIAIJSetPreallocation(J, 0, cols, 0, ocols));
14659566063dSJacob Faibussowitsch   PetscCall(PetscFree2(cols, ocols));
1466ce308e1dSBarry Smith 
14679566063dSJacob Faibussowitsch   PetscCall(DMGetLocalToGlobalMapping(da, &ltog));
14689566063dSJacob Faibussowitsch   PetscCall(MatSetLocalToGlobalMapping(J, ltog, ltog));
1469ce308e1dSBarry Smith 
1470ce308e1dSBarry Smith   /*
1471ce308e1dSBarry Smith     For each node in the grid: we get the neighbors in the local (on processor ordering
1472ce308e1dSBarry Smith     that includes the ghost points) then MatSetValuesLocal() maps those indices to the global
1473ce308e1dSBarry Smith     PETSc ordering.
1474ce308e1dSBarry Smith   */
1475ce308e1dSBarry Smith   if (!da->prealloc_only) {
14769566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(maxcnt, &cols));
1477ce308e1dSBarry Smith     row = xs * nc;
1478ce308e1dSBarry Smith     /* coupling with process to the left */
1479ce308e1dSBarry Smith     for (i = xs; i < xs + s; i++) {
1480ce308e1dSBarry Smith       for (j = 0; j < nc; j++) {
1481ce308e1dSBarry Smith         cnt = 0;
1482ce308e1dSBarry Smith         if (rank) {
1483ce308e1dSBarry Smith           for (l = 0; l < s; l++) {
1484ce308e1dSBarry Smith             for (k = ofill[j]; k < ofill[j + 1]; k++) cols[cnt++] = (i - s + l) * nc + ofill[k];
1485ce308e1dSBarry Smith           }
1486ce308e1dSBarry Smith         }
1487dd400576SPatrick Sanan         if (rank == 0 && (dd->bx == DM_BOUNDARY_PERIODIC)) {
1488831644c1SBarry Smith           for (l = 0; l < s; l++) {
1489831644c1SBarry Smith             for (k = ofill[j]; k < ofill[j + 1]; k++) cols[cnt++] = (m + i - s - l) * nc + ofill[k];
1490831644c1SBarry Smith           }
1491831644c1SBarry Smith         }
14920acb5bebSBarry Smith         if (dfill) {
1493ad540459SPierre Jolivet           for (k = dfill[j]; k < dfill[j + 1]; k++) cols[cnt++] = i * nc + dfill[k];
14940acb5bebSBarry Smith         } else {
1495ad540459SPierre Jolivet           for (k = 0; k < nc; k++) cols[cnt++] = i * nc + k;
14960acb5bebSBarry Smith         }
1497ce308e1dSBarry Smith         for (l = 0; l < s; l++) {
1498ce308e1dSBarry Smith           for (k = ofill[j]; k < ofill[j + 1]; k++) cols[cnt++] = (i + s - l) * nc + ofill[k];
1499ce308e1dSBarry Smith         }
15009566063dSJacob Faibussowitsch         PetscCall(MatSetValues(J, 1, &row, cnt, cols, NULL, INSERT_VALUES));
1501ce308e1dSBarry Smith         row++;
1502ce308e1dSBarry Smith       }
1503ce308e1dSBarry Smith     }
1504ce308e1dSBarry Smith     for (i = xs + s; i < xs + nx - s; i++) {
1505ce308e1dSBarry Smith       for (j = 0; j < nc; j++) {
1506ce308e1dSBarry Smith         cnt = 0;
1507ce308e1dSBarry Smith         for (l = 0; l < s; l++) {
1508ce308e1dSBarry Smith           for (k = ofill[j]; k < ofill[j + 1]; k++) cols[cnt++] = (i - s + l) * nc + ofill[k];
1509ce308e1dSBarry Smith         }
15100acb5bebSBarry Smith         if (dfill) {
1511ad540459SPierre Jolivet           for (k = dfill[j]; k < dfill[j + 1]; k++) cols[cnt++] = i * nc + dfill[k];
15120acb5bebSBarry Smith         } else {
1513ad540459SPierre Jolivet           for (k = 0; k < nc; k++) cols[cnt++] = i * nc + k;
15140acb5bebSBarry Smith         }
1515ce308e1dSBarry Smith         for (l = 0; l < s; l++) {
1516ce308e1dSBarry Smith           for (k = ofill[j]; k < ofill[j + 1]; k++) cols[cnt++] = (i + s - l) * nc + ofill[k];
1517ce308e1dSBarry Smith         }
15189566063dSJacob Faibussowitsch         PetscCall(MatSetValues(J, 1, &row, cnt, cols, NULL, INSERT_VALUES));
1519ce308e1dSBarry Smith         row++;
1520ce308e1dSBarry Smith       }
1521ce308e1dSBarry Smith     }
1522ce308e1dSBarry Smith     /* coupling with process to the right */
1523ce308e1dSBarry Smith     for (i = xs + nx - s; i < xs + nx; i++) {
1524ce308e1dSBarry Smith       for (j = 0; j < nc; j++) {
1525ce308e1dSBarry Smith         cnt = 0;
1526ce308e1dSBarry Smith         for (l = 0; l < s; l++) {
1527ce308e1dSBarry Smith           for (k = ofill[j]; k < ofill[j + 1]; k++) cols[cnt++] = (i - s + l) * nc + ofill[k];
1528ce308e1dSBarry Smith         }
15290acb5bebSBarry Smith         if (dfill) {
1530ad540459SPierre Jolivet           for (k = dfill[j]; k < dfill[j + 1]; k++) cols[cnt++] = i * nc + dfill[k];
15310acb5bebSBarry Smith         } else {
1532ad540459SPierre Jolivet           for (k = 0; k < nc; k++) cols[cnt++] = i * nc + k;
15330acb5bebSBarry Smith         }
1534ce308e1dSBarry Smith         if (rank < size - 1) {
1535ce308e1dSBarry Smith           for (l = 0; l < s; l++) {
1536ce308e1dSBarry Smith             for (k = ofill[j]; k < ofill[j + 1]; k++) cols[cnt++] = (i + s - l) * nc + ofill[k];
1537ce308e1dSBarry Smith           }
1538ce308e1dSBarry Smith         }
1539831644c1SBarry Smith         if ((rank == size - 1) && (dd->bx == DM_BOUNDARY_PERIODIC)) {
1540831644c1SBarry Smith           for (l = 0; l < s; l++) {
1541831644c1SBarry Smith             for (k = ofill[j]; k < ofill[j + 1]; k++) cols[cnt++] = (i - s - l - m + 2) * nc + ofill[k];
1542831644c1SBarry Smith           }
1543831644c1SBarry Smith         }
15449566063dSJacob Faibussowitsch         PetscCall(MatSetValues(J, 1, &row, cnt, cols, NULL, INSERT_VALUES));
1545ce308e1dSBarry Smith         row++;
1546ce308e1dSBarry Smith       }
1547ce308e1dSBarry Smith     }
15489566063dSJacob Faibussowitsch     PetscCall(PetscFree(cols));
1549e7e92044SBarry Smith     /* do not copy values to GPU since they are all zero and not yet needed there */
15509566063dSJacob Faibussowitsch     PetscCall(MatBindToCPU(J, PETSC_TRUE));
15519566063dSJacob Faibussowitsch     PetscCall(MatAssemblyBegin(J, MAT_FINAL_ASSEMBLY));
15529566063dSJacob Faibussowitsch     PetscCall(MatAssemblyEnd(J, MAT_FINAL_ASSEMBLY));
15539566063dSJacob Faibussowitsch     PetscCall(MatBindToCPU(J, PETSC_FALSE));
15549566063dSJacob Faibussowitsch     PetscCall(MatSetOption(J, MAT_NEW_NONZERO_LOCATION_ERR, PETSC_TRUE));
1555ce308e1dSBarry Smith   }
15563ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1557ce308e1dSBarry Smith }
1558ce308e1dSBarry Smith 
1559d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateMatrix_DA_1d_MPIAIJ(DM da, Mat J)
1560d71ae5a4SJacob Faibussowitsch {
156147c6ae99SBarry Smith   PetscInt               xs, nx, i, i1, slot, gxs, gnx;
15620298fd71SBarry Smith   PetscInt               m, dim, s, *cols = NULL, nc, *rows = NULL, col, cnt, l;
156347c6ae99SBarry Smith   PetscInt               istart, iend;
1564bff4a2f0SMatthew G. Knepley   DMBoundaryType         bx;
1565844bd0d7SStefano Zampini   ISLocalToGlobalMapping ltog, mltog;
156647c6ae99SBarry Smith 
156747c6ae99SBarry Smith   PetscFunctionBegin;
156847c6ae99SBarry Smith   /*
156947c6ae99SBarry Smith          nc - number of components per grid point
157047c6ae99SBarry Smith          col - number of colors needed in one direction for single component problem
157147c6ae99SBarry Smith   */
15729566063dSJacob Faibussowitsch   PetscCall(DMDAGetInfo(da, &dim, &m, NULL, NULL, NULL, NULL, NULL, &nc, &s, &bx, NULL, NULL, NULL));
157348a46eb9SPierre Jolivet   if (bx == DM_BOUNDARY_NONE) PetscCall(MatSetOption(J, MAT_SORTED_FULL, PETSC_TRUE));
157447c6ae99SBarry Smith   col = 2 * s + 1;
157547c6ae99SBarry Smith 
15769566063dSJacob Faibussowitsch   PetscCall(DMDAGetCorners(da, &xs, NULL, NULL, &nx, NULL, NULL));
15779566063dSJacob Faibussowitsch   PetscCall(DMDAGetGhostCorners(da, &gxs, NULL, NULL, &gnx, NULL, NULL));
157847c6ae99SBarry Smith 
15799566063dSJacob Faibussowitsch   PetscCall(MatSetBlockSize(J, nc));
15809566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJSetPreallocation(J, col * nc, NULL));
15819566063dSJacob Faibussowitsch   PetscCall(MatMPIAIJSetPreallocation(J, col * nc, NULL, col * nc, NULL));
158247c6ae99SBarry Smith 
15839566063dSJacob Faibussowitsch   PetscCall(DMGetLocalToGlobalMapping(da, &ltog));
15849566063dSJacob Faibussowitsch   PetscCall(MatGetLocalToGlobalMapping(J, &mltog, NULL));
158548a46eb9SPierre Jolivet   if (!mltog) PetscCall(MatSetLocalToGlobalMapping(J, ltog, ltog));
158647c6ae99SBarry Smith 
158747c6ae99SBarry Smith   /*
158847c6ae99SBarry Smith     For each node in the grid: we get the neighbors in the local (on processor ordering
158947c6ae99SBarry Smith     that includes the ghost points) then MatSetValuesLocal() maps those indices to the global
159047c6ae99SBarry Smith     PETSc ordering.
159147c6ae99SBarry Smith   */
1592fcfd50ebSBarry Smith   if (!da->prealloc_only) {
15939566063dSJacob Faibussowitsch     PetscCall(PetscMalloc2(nc, &rows, col * nc * nc, &cols));
159447c6ae99SBarry Smith     for (i = xs; i < xs + nx; i++) {
159547c6ae99SBarry Smith       istart = PetscMax(-s, gxs - i);
159647c6ae99SBarry Smith       iend   = PetscMin(s, gxs + gnx - i - 1);
159747c6ae99SBarry Smith       slot   = i - gxs;
159847c6ae99SBarry Smith 
159947c6ae99SBarry Smith       cnt = 0;
160047c6ae99SBarry Smith       for (i1 = istart; i1 < iend + 1; i1++) {
1601071fcb05SBarry Smith         cols[cnt++] = nc * (slot + i1);
1602071fcb05SBarry Smith         for (l = 1; l < nc; l++) {
16039371c9d4SSatish Balay           cols[cnt] = 1 + cols[cnt - 1];
16049371c9d4SSatish Balay           cnt++;
160547c6ae99SBarry Smith         }
160647c6ae99SBarry Smith       }
16079371c9d4SSatish Balay       rows[0] = nc * (slot);
16089371c9d4SSatish Balay       for (l = 1; l < nc; l++) rows[l] = 1 + rows[l - 1];
16099566063dSJacob Faibussowitsch       PetscCall(MatSetValuesLocal(J, nc, rows, cnt, cols, NULL, INSERT_VALUES));
161047c6ae99SBarry Smith     }
1611e7e92044SBarry Smith     /* do not copy values to GPU since they are all zero and not yet needed there */
16129566063dSJacob Faibussowitsch     PetscCall(MatBindToCPU(J, PETSC_TRUE));
16139566063dSJacob Faibussowitsch     PetscCall(MatAssemblyBegin(J, MAT_FINAL_ASSEMBLY));
16149566063dSJacob Faibussowitsch     PetscCall(MatAssemblyEnd(J, MAT_FINAL_ASSEMBLY));
161548a46eb9SPierre Jolivet     if (bx == DM_BOUNDARY_NONE) PetscCall(MatSetOption(J, MAT_SORTED_FULL, PETSC_FALSE));
16169566063dSJacob Faibussowitsch     PetscCall(MatBindToCPU(J, PETSC_FALSE));
16179566063dSJacob Faibussowitsch     PetscCall(MatSetOption(J, MAT_NEW_NONZERO_LOCATION_ERR, PETSC_TRUE));
16189566063dSJacob Faibussowitsch     PetscCall(PetscFree2(rows, cols));
1619ce308e1dSBarry Smith   }
16203ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
162147c6ae99SBarry Smith }
162247c6ae99SBarry Smith 
1623d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateMatrix_DA_1d_SeqAIJ_NoPreallocation(DM da, Mat J)
1624d71ae5a4SJacob Faibussowitsch {
162519b08ed1SBarry Smith   PetscInt               xs, nx, i, i1, slot, gxs, gnx;
162619b08ed1SBarry Smith   PetscInt               m, dim, s, *cols = NULL, nc, *rows = NULL, col, cnt, l;
162719b08ed1SBarry Smith   PetscInt               istart, iend;
162819b08ed1SBarry Smith   DMBoundaryType         bx;
162919b08ed1SBarry Smith   ISLocalToGlobalMapping ltog, mltog;
163019b08ed1SBarry Smith 
163119b08ed1SBarry Smith   PetscFunctionBegin;
163219b08ed1SBarry Smith   /*
163319b08ed1SBarry Smith          nc - number of components per grid point
163419b08ed1SBarry Smith          col - number of colors needed in one direction for single component problem
163519b08ed1SBarry Smith   */
16369566063dSJacob Faibussowitsch   PetscCall(DMDAGetInfo(da, &dim, &m, NULL, NULL, NULL, NULL, NULL, &nc, &s, &bx, NULL, NULL, NULL));
163719b08ed1SBarry Smith   col = 2 * s + 1;
163819b08ed1SBarry Smith 
16399566063dSJacob Faibussowitsch   PetscCall(DMDAGetCorners(da, &xs, NULL, NULL, &nx, NULL, NULL));
16409566063dSJacob Faibussowitsch   PetscCall(DMDAGetGhostCorners(da, &gxs, NULL, NULL, &gnx, NULL, NULL));
164119b08ed1SBarry Smith 
16429566063dSJacob Faibussowitsch   PetscCall(MatSetBlockSize(J, nc));
16439566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJSetTotalPreallocation(J, nx * nc * col * nc));
164419b08ed1SBarry Smith 
16459566063dSJacob Faibussowitsch   PetscCall(DMGetLocalToGlobalMapping(da, &ltog));
16469566063dSJacob Faibussowitsch   PetscCall(MatGetLocalToGlobalMapping(J, &mltog, NULL));
164748a46eb9SPierre Jolivet   if (!mltog) PetscCall(MatSetLocalToGlobalMapping(J, ltog, ltog));
164819b08ed1SBarry Smith 
164919b08ed1SBarry Smith   /*
165019b08ed1SBarry Smith     For each node in the grid: we get the neighbors in the local (on processor ordering
165119b08ed1SBarry Smith     that includes the ghost points) then MatSetValuesLocal() maps those indices to the global
165219b08ed1SBarry Smith     PETSc ordering.
165319b08ed1SBarry Smith   */
165419b08ed1SBarry Smith   if (!da->prealloc_only) {
16559566063dSJacob Faibussowitsch     PetscCall(PetscMalloc2(nc, &rows, col * nc * nc, &cols));
165619b08ed1SBarry Smith     for (i = xs; i < xs + nx; i++) {
165719b08ed1SBarry Smith       istart = PetscMax(-s, gxs - i);
165819b08ed1SBarry Smith       iend   = PetscMin(s, gxs + gnx - i - 1);
165919b08ed1SBarry Smith       slot   = i - gxs;
166019b08ed1SBarry Smith 
166119b08ed1SBarry Smith       cnt = 0;
166219b08ed1SBarry Smith       for (i1 = istart; i1 < iend + 1; i1++) {
166319b08ed1SBarry Smith         cols[cnt++] = nc * (slot + i1);
166419b08ed1SBarry Smith         for (l = 1; l < nc; l++) {
16659371c9d4SSatish Balay           cols[cnt] = 1 + cols[cnt - 1];
16669371c9d4SSatish Balay           cnt++;
166719b08ed1SBarry Smith         }
166819b08ed1SBarry Smith       }
16699371c9d4SSatish Balay       rows[0] = nc * (slot);
16709371c9d4SSatish Balay       for (l = 1; l < nc; l++) rows[l] = 1 + rows[l - 1];
16719566063dSJacob Faibussowitsch       PetscCall(MatSetValuesLocal(J, nc, rows, cnt, cols, NULL, INSERT_VALUES));
167219b08ed1SBarry Smith     }
167319b08ed1SBarry Smith     /* do not copy values to GPU since they are all zero and not yet needed there */
16749566063dSJacob Faibussowitsch     PetscCall(MatBindToCPU(J, PETSC_TRUE));
16759566063dSJacob Faibussowitsch     PetscCall(MatAssemblyBegin(J, MAT_FINAL_ASSEMBLY));
16769566063dSJacob Faibussowitsch     PetscCall(MatAssemblyEnd(J, MAT_FINAL_ASSEMBLY));
167748a46eb9SPierre Jolivet     if (bx == DM_BOUNDARY_NONE) PetscCall(MatSetOption(J, MAT_SORTED_FULL, PETSC_FALSE));
16789566063dSJacob Faibussowitsch     PetscCall(MatBindToCPU(J, PETSC_FALSE));
16799566063dSJacob Faibussowitsch     PetscCall(MatSetOption(J, MAT_NEW_NONZERO_LOCATION_ERR, PETSC_TRUE));
16809566063dSJacob Faibussowitsch     PetscCall(PetscFree2(rows, cols));
168119b08ed1SBarry Smith   }
16829566063dSJacob Faibussowitsch   PetscCall(MatSetOption(J, MAT_SORTED_FULL, PETSC_FALSE));
16833ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
168419b08ed1SBarry Smith }
168519b08ed1SBarry Smith 
1686d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateMatrix_DA_2d_MPIBAIJ(DM da, Mat J)
1687d71ae5a4SJacob Faibussowitsch {
168847c6ae99SBarry Smith   PetscInt               xs, ys, nx, ny, i, j, slot, gxs, gys, gnx, gny;
168947c6ae99SBarry Smith   PetscInt               m, n, dim, s, *cols, nc, col, cnt, *dnz, *onz;
169047c6ae99SBarry Smith   PetscInt               istart, iend, jstart, jend, ii, jj;
169147c6ae99SBarry Smith   MPI_Comm               comm;
169247c6ae99SBarry Smith   PetscScalar           *values;
1693bff4a2f0SMatthew G. Knepley   DMBoundaryType         bx, by;
1694aa219208SBarry Smith   DMDAStencilType        st;
169545b6f7e9SBarry Smith   ISLocalToGlobalMapping ltog;
169647c6ae99SBarry Smith 
169747c6ae99SBarry Smith   PetscFunctionBegin;
169847c6ae99SBarry Smith   /*
169947c6ae99SBarry Smith      nc - number of components per grid point
170047c6ae99SBarry Smith      col - number of colors needed in one direction for single component problem
170147c6ae99SBarry Smith   */
17029566063dSJacob Faibussowitsch   PetscCall(DMDAGetInfo(da, &dim, &m, &n, NULL, NULL, NULL, NULL, &nc, &s, &bx, &by, NULL, &st));
170347c6ae99SBarry Smith   col = 2 * s + 1;
170447c6ae99SBarry Smith 
17059566063dSJacob Faibussowitsch   PetscCall(DMDAGetCorners(da, &xs, &ys, NULL, &nx, &ny, NULL));
17069566063dSJacob Faibussowitsch   PetscCall(DMDAGetGhostCorners(da, &gxs, &gys, NULL, &gnx, &gny, NULL));
17079566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)da, &comm));
170847c6ae99SBarry Smith 
17099566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(col * col * nc * nc, &cols));
171047c6ae99SBarry Smith 
17119566063dSJacob Faibussowitsch   PetscCall(DMGetLocalToGlobalMapping(da, &ltog));
171247c6ae99SBarry Smith 
171347c6ae99SBarry Smith   /* determine the matrix preallocation information */
1714d0609cedSBarry Smith   MatPreallocateBegin(comm, nx * ny, nx * ny, dnz, onz);
171547c6ae99SBarry Smith   for (i = xs; i < xs + nx; i++) {
1716bff4a2f0SMatthew G. Knepley     istart = (bx == DM_BOUNDARY_PERIODIC) ? -s : (PetscMax(-s, -i));
1717bff4a2f0SMatthew G. Knepley     iend   = (bx == DM_BOUNDARY_PERIODIC) ? s : (PetscMin(s, m - i - 1));
171847c6ae99SBarry Smith     for (j = ys; j < ys + ny; j++) {
1719bff4a2f0SMatthew G. Knepley       jstart = (by == DM_BOUNDARY_PERIODIC) ? -s : (PetscMax(-s, -j));
1720bff4a2f0SMatthew G. Knepley       jend   = (by == DM_BOUNDARY_PERIODIC) ? s : (PetscMin(s, n - j - 1));
172147c6ae99SBarry Smith       slot   = i - gxs + gnx * (j - gys);
172247c6ae99SBarry Smith 
172347c6ae99SBarry Smith       /* Find block columns in block row */
172447c6ae99SBarry Smith       cnt = 0;
172547c6ae99SBarry Smith       for (ii = istart; ii < iend + 1; ii++) {
172647c6ae99SBarry Smith         for (jj = jstart; jj < jend + 1; jj++) {
1727aa219208SBarry Smith           if (st == DMDA_STENCIL_BOX || !ii || !jj) { /* BOX or on the STAR */
172847c6ae99SBarry Smith             cols[cnt++] = slot + ii + gnx * jj;
172947c6ae99SBarry Smith           }
173047c6ae99SBarry Smith         }
173147c6ae99SBarry Smith       }
17329566063dSJacob Faibussowitsch       PetscCall(MatPreallocateSetLocalBlock(ltog, 1, &slot, ltog, cnt, cols, dnz, onz));
173347c6ae99SBarry Smith     }
173447c6ae99SBarry Smith   }
17359566063dSJacob Faibussowitsch   PetscCall(MatSeqBAIJSetPreallocation(J, nc, 0, dnz));
17369566063dSJacob Faibussowitsch   PetscCall(MatMPIBAIJSetPreallocation(J, nc, 0, dnz, 0, onz));
1737d0609cedSBarry Smith   MatPreallocateEnd(dnz, onz);
173847c6ae99SBarry Smith 
17399566063dSJacob Faibussowitsch   PetscCall(MatSetLocalToGlobalMapping(J, ltog, ltog));
174047c6ae99SBarry Smith 
174147c6ae99SBarry Smith   /*
174247c6ae99SBarry Smith     For each node in the grid: we get the neighbors in the local (on processor ordering
174347c6ae99SBarry Smith     that includes the ghost points) then MatSetValuesLocal() maps those indices to the global
174447c6ae99SBarry Smith     PETSc ordering.
174547c6ae99SBarry Smith   */
1746fcfd50ebSBarry Smith   if (!da->prealloc_only) {
17479566063dSJacob Faibussowitsch     PetscCall(PetscCalloc1(col * col * nc * nc, &values));
174847c6ae99SBarry Smith     for (i = xs; i < xs + nx; i++) {
1749bff4a2f0SMatthew G. Knepley       istart = (bx == DM_BOUNDARY_PERIODIC) ? -s : (PetscMax(-s, -i));
1750bff4a2f0SMatthew G. Knepley       iend   = (bx == DM_BOUNDARY_PERIODIC) ? s : (PetscMin(s, m - i - 1));
175147c6ae99SBarry Smith       for (j = ys; j < ys + ny; j++) {
1752bff4a2f0SMatthew G. Knepley         jstart = (by == DM_BOUNDARY_PERIODIC) ? -s : (PetscMax(-s, -j));
1753bff4a2f0SMatthew G. Knepley         jend   = (by == DM_BOUNDARY_PERIODIC) ? s : (PetscMin(s, n - j - 1));
175447c6ae99SBarry Smith         slot   = i - gxs + gnx * (j - gys);
175547c6ae99SBarry Smith         cnt    = 0;
175647c6ae99SBarry Smith         for (ii = istart; ii < iend + 1; ii++) {
175747c6ae99SBarry Smith           for (jj = jstart; jj < jend + 1; jj++) {
1758aa219208SBarry Smith             if (st == DMDA_STENCIL_BOX || !ii || !jj) { /* BOX or on the STAR */
175947c6ae99SBarry Smith               cols[cnt++] = slot + ii + gnx * jj;
176047c6ae99SBarry Smith             }
176147c6ae99SBarry Smith           }
176247c6ae99SBarry Smith         }
17639566063dSJacob Faibussowitsch         PetscCall(MatSetValuesBlockedLocal(J, 1, &slot, cnt, cols, values, INSERT_VALUES));
176447c6ae99SBarry Smith       }
176547c6ae99SBarry Smith     }
17669566063dSJacob Faibussowitsch     PetscCall(PetscFree(values));
1767e7e92044SBarry Smith     /* do not copy values to GPU since they are all zero and not yet needed there */
17689566063dSJacob Faibussowitsch     PetscCall(MatBindToCPU(J, PETSC_TRUE));
17699566063dSJacob Faibussowitsch     PetscCall(MatAssemblyBegin(J, MAT_FINAL_ASSEMBLY));
17709566063dSJacob Faibussowitsch     PetscCall(MatAssemblyEnd(J, MAT_FINAL_ASSEMBLY));
17719566063dSJacob Faibussowitsch     PetscCall(MatBindToCPU(J, PETSC_FALSE));
17729566063dSJacob Faibussowitsch     PetscCall(MatSetOption(J, MAT_NEW_NONZERO_LOCATION_ERR, PETSC_TRUE));
177347c6ae99SBarry Smith   }
17749566063dSJacob Faibussowitsch   PetscCall(PetscFree(cols));
17753ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
177647c6ae99SBarry Smith }
177747c6ae99SBarry Smith 
1778d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateMatrix_DA_3d_MPIBAIJ(DM da, Mat J)
1779d71ae5a4SJacob Faibussowitsch {
178047c6ae99SBarry Smith   PetscInt               xs, ys, nx, ny, i, j, slot, gxs, gys, gnx, gny;
178147c6ae99SBarry Smith   PetscInt               m, n, dim, s, *cols, k, nc, col, cnt, p, *dnz, *onz;
178247c6ae99SBarry Smith   PetscInt               istart, iend, jstart, jend, kstart, kend, zs, nz, gzs, gnz, ii, jj, kk;
178347c6ae99SBarry Smith   MPI_Comm               comm;
178447c6ae99SBarry Smith   PetscScalar           *values;
1785bff4a2f0SMatthew G. Knepley   DMBoundaryType         bx, by, bz;
1786aa219208SBarry Smith   DMDAStencilType        st;
178745b6f7e9SBarry Smith   ISLocalToGlobalMapping ltog;
178847c6ae99SBarry Smith 
178947c6ae99SBarry Smith   PetscFunctionBegin;
179047c6ae99SBarry Smith   /*
179147c6ae99SBarry Smith          nc - number of components per grid point
179247c6ae99SBarry Smith          col - number of colors needed in one direction for single component problem
179347c6ae99SBarry Smith   */
17949566063dSJacob Faibussowitsch   PetscCall(DMDAGetInfo(da, &dim, &m, &n, &p, NULL, NULL, NULL, &nc, &s, &bx, &by, &bz, &st));
179547c6ae99SBarry Smith   col = 2 * s + 1;
179647c6ae99SBarry Smith 
17979566063dSJacob Faibussowitsch   PetscCall(DMDAGetCorners(da, &xs, &ys, &zs, &nx, &ny, &nz));
17989566063dSJacob Faibussowitsch   PetscCall(DMDAGetGhostCorners(da, &gxs, &gys, &gzs, &gnx, &gny, &gnz));
17999566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)da, &comm));
180047c6ae99SBarry Smith 
18019566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(col * col * col, &cols));
180247c6ae99SBarry Smith 
18039566063dSJacob Faibussowitsch   PetscCall(DMGetLocalToGlobalMapping(da, &ltog));
180447c6ae99SBarry Smith 
180547c6ae99SBarry Smith   /* determine the matrix preallocation information */
1806d0609cedSBarry Smith   MatPreallocateBegin(comm, nx * ny * nz, nx * ny * nz, dnz, onz);
180747c6ae99SBarry Smith   for (i = xs; i < xs + nx; i++) {
1808bff4a2f0SMatthew G. Knepley     istart = (bx == DM_BOUNDARY_PERIODIC) ? -s : (PetscMax(-s, -i));
1809bff4a2f0SMatthew G. Knepley     iend   = (bx == DM_BOUNDARY_PERIODIC) ? s : (PetscMin(s, m - i - 1));
181047c6ae99SBarry Smith     for (j = ys; j < ys + ny; j++) {
1811bff4a2f0SMatthew G. Knepley       jstart = (by == DM_BOUNDARY_PERIODIC) ? -s : (PetscMax(-s, -j));
1812bff4a2f0SMatthew G. Knepley       jend   = (by == DM_BOUNDARY_PERIODIC) ? s : (PetscMin(s, n - j - 1));
181347c6ae99SBarry Smith       for (k = zs; k < zs + nz; k++) {
1814bff4a2f0SMatthew G. Knepley         kstart = (bz == DM_BOUNDARY_PERIODIC) ? -s : (PetscMax(-s, -k));
1815bff4a2f0SMatthew G. Knepley         kend   = (bz == DM_BOUNDARY_PERIODIC) ? s : (PetscMin(s, p - k - 1));
181647c6ae99SBarry Smith 
181747c6ae99SBarry Smith         slot = i - gxs + gnx * (j - gys) + gnx * gny * (k - gzs);
181847c6ae99SBarry Smith 
181947c6ae99SBarry Smith         /* Find block columns in block row */
182047c6ae99SBarry Smith         cnt = 0;
182147c6ae99SBarry Smith         for (ii = istart; ii < iend + 1; ii++) {
182247c6ae99SBarry Smith           for (jj = jstart; jj < jend + 1; jj++) {
182347c6ae99SBarry Smith             for (kk = kstart; kk < kend + 1; kk++) {
1824aa219208SBarry Smith               if ((st == DMDA_STENCIL_BOX) || ((!ii && !jj) || (!jj && !kk) || (!ii && !kk))) { /* entries on star*/
182547c6ae99SBarry Smith                 cols[cnt++] = slot + ii + gnx * jj + gnx * gny * kk;
182647c6ae99SBarry Smith               }
182747c6ae99SBarry Smith             }
182847c6ae99SBarry Smith           }
182947c6ae99SBarry Smith         }
18309566063dSJacob Faibussowitsch         PetscCall(MatPreallocateSetLocalBlock(ltog, 1, &slot, ltog, cnt, cols, dnz, onz));
183147c6ae99SBarry Smith       }
183247c6ae99SBarry Smith     }
183347c6ae99SBarry Smith   }
18349566063dSJacob Faibussowitsch   PetscCall(MatSeqBAIJSetPreallocation(J, nc, 0, dnz));
18359566063dSJacob Faibussowitsch   PetscCall(MatMPIBAIJSetPreallocation(J, nc, 0, dnz, 0, onz));
1836d0609cedSBarry Smith   MatPreallocateEnd(dnz, onz);
183747c6ae99SBarry Smith 
18389566063dSJacob Faibussowitsch   PetscCall(MatSetLocalToGlobalMapping(J, ltog, ltog));
183947c6ae99SBarry Smith 
184047c6ae99SBarry Smith   /*
184147c6ae99SBarry Smith     For each node in the grid: we get the neighbors in the local (on processor ordering
184247c6ae99SBarry Smith     that includes the ghost points) then MatSetValuesLocal() maps those indices to the global
184347c6ae99SBarry Smith     PETSc ordering.
184447c6ae99SBarry Smith   */
1845fcfd50ebSBarry Smith   if (!da->prealloc_only) {
18469566063dSJacob Faibussowitsch     PetscCall(PetscCalloc1(col * col * col * nc * nc, &values));
184747c6ae99SBarry Smith     for (i = xs; i < xs + nx; i++) {
1848bff4a2f0SMatthew G. Knepley       istart = (bx == DM_BOUNDARY_PERIODIC) ? -s : (PetscMax(-s, -i));
1849bff4a2f0SMatthew G. Knepley       iend   = (bx == DM_BOUNDARY_PERIODIC) ? s : (PetscMin(s, m - i - 1));
185047c6ae99SBarry Smith       for (j = ys; j < ys + ny; j++) {
1851bff4a2f0SMatthew G. Knepley         jstart = (by == DM_BOUNDARY_PERIODIC) ? -s : (PetscMax(-s, -j));
1852bff4a2f0SMatthew G. Knepley         jend   = (by == DM_BOUNDARY_PERIODIC) ? s : (PetscMin(s, n - j - 1));
185347c6ae99SBarry Smith         for (k = zs; k < zs + nz; k++) {
1854bff4a2f0SMatthew G. Knepley           kstart = (bz == DM_BOUNDARY_PERIODIC) ? -s : (PetscMax(-s, -k));
1855bff4a2f0SMatthew G. Knepley           kend   = (bz == DM_BOUNDARY_PERIODIC) ? s : (PetscMin(s, p - k - 1));
185647c6ae99SBarry Smith 
185747c6ae99SBarry Smith           slot = i - gxs + gnx * (j - gys) + gnx * gny * (k - gzs);
185847c6ae99SBarry Smith 
185947c6ae99SBarry Smith           cnt = 0;
186047c6ae99SBarry Smith           for (ii = istart; ii < iend + 1; ii++) {
186147c6ae99SBarry Smith             for (jj = jstart; jj < jend + 1; jj++) {
186247c6ae99SBarry Smith               for (kk = kstart; kk < kend + 1; kk++) {
1863aa219208SBarry Smith                 if ((st == DMDA_STENCIL_BOX) || ((!ii && !jj) || (!jj && !kk) || (!ii && !kk))) { /* entries on star*/
186447c6ae99SBarry Smith                   cols[cnt++] = slot + ii + gnx * jj + gnx * gny * kk;
186547c6ae99SBarry Smith                 }
186647c6ae99SBarry Smith               }
186747c6ae99SBarry Smith             }
186847c6ae99SBarry Smith           }
18699566063dSJacob Faibussowitsch           PetscCall(MatSetValuesBlockedLocal(J, 1, &slot, cnt, cols, values, INSERT_VALUES));
187047c6ae99SBarry Smith         }
187147c6ae99SBarry Smith       }
187247c6ae99SBarry Smith     }
18739566063dSJacob Faibussowitsch     PetscCall(PetscFree(values));
1874e7e92044SBarry Smith     /* do not copy values to GPU since they are all zero and not yet needed there */
18759566063dSJacob Faibussowitsch     PetscCall(MatBindToCPU(J, PETSC_TRUE));
18769566063dSJacob Faibussowitsch     PetscCall(MatAssemblyBegin(J, MAT_FINAL_ASSEMBLY));
18779566063dSJacob Faibussowitsch     PetscCall(MatAssemblyEnd(J, MAT_FINAL_ASSEMBLY));
18789566063dSJacob Faibussowitsch     PetscCall(MatBindToCPU(J, PETSC_FALSE));
18799566063dSJacob Faibussowitsch     PetscCall(MatSetOption(J, MAT_NEW_NONZERO_LOCATION_ERR, PETSC_TRUE));
188047c6ae99SBarry Smith   }
18819566063dSJacob Faibussowitsch   PetscCall(PetscFree(cols));
18823ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
188347c6ae99SBarry Smith }
188447c6ae99SBarry Smith 
188547c6ae99SBarry Smith /*
188647c6ae99SBarry Smith   This helper is for of SBAIJ preallocation, to discard the lower-triangular values which are difficult to
188747c6ae99SBarry Smith   identify in the local ordering with periodic domain.
188847c6ae99SBarry Smith */
1889d71ae5a4SJacob Faibussowitsch static PetscErrorCode L2GFilterUpperTriangular(ISLocalToGlobalMapping ltog, PetscInt *row, PetscInt *cnt, PetscInt col[])
1890d71ae5a4SJacob Faibussowitsch {
189147c6ae99SBarry Smith   PetscInt i, n;
189247c6ae99SBarry Smith 
189347c6ae99SBarry Smith   PetscFunctionBegin;
18949566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingApplyBlock(ltog, 1, row, row));
18959566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingApplyBlock(ltog, *cnt, col, col));
189647c6ae99SBarry Smith   for (i = 0, n = 0; i < *cnt; i++) {
189747c6ae99SBarry Smith     if (col[i] >= *row) col[n++] = col[i];
189847c6ae99SBarry Smith   }
189947c6ae99SBarry Smith   *cnt = n;
19003ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
190147c6ae99SBarry Smith }
190247c6ae99SBarry Smith 
1903d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateMatrix_DA_2d_MPISBAIJ(DM da, Mat J)
1904d71ae5a4SJacob Faibussowitsch {
190547c6ae99SBarry Smith   PetscInt               xs, ys, nx, ny, i, j, slot, gxs, gys, gnx, gny;
190647c6ae99SBarry Smith   PetscInt               m, n, dim, s, *cols, nc, col, cnt, *dnz, *onz;
190747c6ae99SBarry Smith   PetscInt               istart, iend, jstart, jend, ii, jj;
190847c6ae99SBarry Smith   MPI_Comm               comm;
190947c6ae99SBarry Smith   PetscScalar           *values;
1910bff4a2f0SMatthew G. Knepley   DMBoundaryType         bx, by;
1911aa219208SBarry Smith   DMDAStencilType        st;
191245b6f7e9SBarry Smith   ISLocalToGlobalMapping ltog;
191347c6ae99SBarry Smith 
191447c6ae99SBarry Smith   PetscFunctionBegin;
191547c6ae99SBarry Smith   /*
191647c6ae99SBarry Smith      nc - number of components per grid point
191747c6ae99SBarry Smith      col - number of colors needed in one direction for single component problem
191847c6ae99SBarry Smith   */
19199566063dSJacob Faibussowitsch   PetscCall(DMDAGetInfo(da, &dim, &m, &n, NULL, NULL, NULL, NULL, &nc, &s, &bx, &by, NULL, &st));
192047c6ae99SBarry Smith   col = 2 * s + 1;
192147c6ae99SBarry Smith 
19229566063dSJacob Faibussowitsch   PetscCall(DMDAGetCorners(da, &xs, &ys, NULL, &nx, &ny, NULL));
19239566063dSJacob Faibussowitsch   PetscCall(DMDAGetGhostCorners(da, &gxs, &gys, NULL, &gnx, &gny, NULL));
19249566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)da, &comm));
192547c6ae99SBarry Smith 
19269566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(col * col * nc * nc, &cols));
192747c6ae99SBarry Smith 
19289566063dSJacob Faibussowitsch   PetscCall(DMGetLocalToGlobalMapping(da, &ltog));
192947c6ae99SBarry Smith 
193047c6ae99SBarry Smith   /* determine the matrix preallocation information */
1931d0609cedSBarry Smith   MatPreallocateBegin(comm, nx * ny, nx * ny, dnz, onz);
193247c6ae99SBarry Smith   for (i = xs; i < xs + nx; i++) {
1933bff4a2f0SMatthew G. Knepley     istart = (bx == DM_BOUNDARY_PERIODIC) ? -s : (PetscMax(-s, -i));
1934bff4a2f0SMatthew G. Knepley     iend   = (bx == DM_BOUNDARY_PERIODIC) ? s : (PetscMin(s, m - i - 1));
193547c6ae99SBarry Smith     for (j = ys; j < ys + ny; j++) {
1936bff4a2f0SMatthew G. Knepley       jstart = (by == DM_BOUNDARY_PERIODIC) ? -s : (PetscMax(-s, -j));
1937bff4a2f0SMatthew G. Knepley       jend   = (by == DM_BOUNDARY_PERIODIC) ? s : (PetscMin(s, n - j - 1));
193847c6ae99SBarry Smith       slot   = i - gxs + gnx * (j - gys);
193947c6ae99SBarry Smith 
194047c6ae99SBarry Smith       /* Find block columns in block row */
194147c6ae99SBarry Smith       cnt = 0;
194247c6ae99SBarry Smith       for (ii = istart; ii < iend + 1; ii++) {
194347c6ae99SBarry Smith         for (jj = jstart; jj < jend + 1; jj++) {
1944ad540459SPierre Jolivet           if (st == DMDA_STENCIL_BOX || !ii || !jj) cols[cnt++] = slot + ii + gnx * jj;
194547c6ae99SBarry Smith         }
194647c6ae99SBarry Smith       }
19479566063dSJacob Faibussowitsch       PetscCall(L2GFilterUpperTriangular(ltog, &slot, &cnt, cols));
19489566063dSJacob Faibussowitsch       PetscCall(MatPreallocateSymmetricSetBlock(slot, cnt, cols, dnz, onz));
194947c6ae99SBarry Smith     }
195047c6ae99SBarry Smith   }
19519566063dSJacob Faibussowitsch   PetscCall(MatSeqSBAIJSetPreallocation(J, nc, 0, dnz));
19529566063dSJacob Faibussowitsch   PetscCall(MatMPISBAIJSetPreallocation(J, nc, 0, dnz, 0, onz));
1953d0609cedSBarry Smith   MatPreallocateEnd(dnz, onz);
195447c6ae99SBarry Smith 
19559566063dSJacob Faibussowitsch   PetscCall(MatSetLocalToGlobalMapping(J, ltog, ltog));
195647c6ae99SBarry Smith 
195747c6ae99SBarry Smith   /*
195847c6ae99SBarry Smith     For each node in the grid: we get the neighbors in the local (on processor ordering
195947c6ae99SBarry Smith     that includes the ghost points) then MatSetValuesLocal() maps those indices to the global
196047c6ae99SBarry Smith     PETSc ordering.
196147c6ae99SBarry Smith   */
1962fcfd50ebSBarry Smith   if (!da->prealloc_only) {
19639566063dSJacob Faibussowitsch     PetscCall(PetscCalloc1(col * col * nc * nc, &values));
196447c6ae99SBarry Smith     for (i = xs; i < xs + nx; i++) {
1965bff4a2f0SMatthew G. Knepley       istart = (bx == DM_BOUNDARY_PERIODIC) ? -s : (PetscMax(-s, -i));
1966bff4a2f0SMatthew G. Knepley       iend   = (bx == DM_BOUNDARY_PERIODIC) ? s : (PetscMin(s, m - i - 1));
196747c6ae99SBarry Smith       for (j = ys; j < ys + ny; j++) {
1968bff4a2f0SMatthew G. Knepley         jstart = (by == DM_BOUNDARY_PERIODIC) ? -s : (PetscMax(-s, -j));
1969bff4a2f0SMatthew G. Knepley         jend   = (by == DM_BOUNDARY_PERIODIC) ? s : (PetscMin(s, n - j - 1));
197047c6ae99SBarry Smith         slot   = i - gxs + gnx * (j - gys);
197147c6ae99SBarry Smith 
197247c6ae99SBarry Smith         /* Find block columns in block row */
197347c6ae99SBarry Smith         cnt = 0;
197447c6ae99SBarry Smith         for (ii = istart; ii < iend + 1; ii++) {
197547c6ae99SBarry Smith           for (jj = jstart; jj < jend + 1; jj++) {
1976ad540459SPierre Jolivet             if (st == DMDA_STENCIL_BOX || !ii || !jj) cols[cnt++] = slot + ii + gnx * jj;
197747c6ae99SBarry Smith           }
197847c6ae99SBarry Smith         }
19799566063dSJacob Faibussowitsch         PetscCall(L2GFilterUpperTriangular(ltog, &slot, &cnt, cols));
19809566063dSJacob Faibussowitsch         PetscCall(MatSetValuesBlocked(J, 1, &slot, cnt, cols, values, INSERT_VALUES));
198147c6ae99SBarry Smith       }
198247c6ae99SBarry Smith     }
19839566063dSJacob Faibussowitsch     PetscCall(PetscFree(values));
1984e7e92044SBarry Smith     /* do not copy values to GPU since they are all zero and not yet needed there */
19859566063dSJacob Faibussowitsch     PetscCall(MatBindToCPU(J, PETSC_TRUE));
19869566063dSJacob Faibussowitsch     PetscCall(MatAssemblyBegin(J, MAT_FINAL_ASSEMBLY));
19879566063dSJacob Faibussowitsch     PetscCall(MatAssemblyEnd(J, MAT_FINAL_ASSEMBLY));
19889566063dSJacob Faibussowitsch     PetscCall(MatBindToCPU(J, PETSC_FALSE));
19899566063dSJacob Faibussowitsch     PetscCall(MatSetOption(J, MAT_NEW_NONZERO_LOCATION_ERR, PETSC_TRUE));
199047c6ae99SBarry Smith   }
19919566063dSJacob Faibussowitsch   PetscCall(PetscFree(cols));
19923ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
199347c6ae99SBarry Smith }
199447c6ae99SBarry Smith 
1995d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateMatrix_DA_3d_MPISBAIJ(DM da, Mat J)
1996d71ae5a4SJacob Faibussowitsch {
199747c6ae99SBarry Smith   PetscInt               xs, ys, nx, ny, i, j, slot, gxs, gys, gnx, gny;
199847c6ae99SBarry Smith   PetscInt               m, n, dim, s, *cols, k, nc, col, cnt, p, *dnz, *onz;
199947c6ae99SBarry Smith   PetscInt               istart, iend, jstart, jend, kstart, kend, zs, nz, gzs, gnz, ii, jj, kk;
200047c6ae99SBarry Smith   MPI_Comm               comm;
200147c6ae99SBarry Smith   PetscScalar           *values;
2002bff4a2f0SMatthew G. Knepley   DMBoundaryType         bx, by, bz;
2003aa219208SBarry Smith   DMDAStencilType        st;
200445b6f7e9SBarry Smith   ISLocalToGlobalMapping ltog;
200547c6ae99SBarry Smith 
200647c6ae99SBarry Smith   PetscFunctionBegin;
200747c6ae99SBarry Smith   /*
200847c6ae99SBarry Smith      nc - number of components per grid point
200947c6ae99SBarry Smith      col - number of colors needed in one direction for single component problem
201047c6ae99SBarry Smith   */
20119566063dSJacob Faibussowitsch   PetscCall(DMDAGetInfo(da, &dim, &m, &n, &p, NULL, NULL, NULL, &nc, &s, &bx, &by, &bz, &st));
201247c6ae99SBarry Smith   col = 2 * s + 1;
201347c6ae99SBarry Smith 
20149566063dSJacob Faibussowitsch   PetscCall(DMDAGetCorners(da, &xs, &ys, &zs, &nx, &ny, &nz));
20159566063dSJacob Faibussowitsch   PetscCall(DMDAGetGhostCorners(da, &gxs, &gys, &gzs, &gnx, &gny, &gnz));
20169566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)da, &comm));
201747c6ae99SBarry Smith 
201847c6ae99SBarry Smith   /* create the matrix */
20199566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(col * col * col, &cols));
202047c6ae99SBarry Smith 
20219566063dSJacob Faibussowitsch   PetscCall(DMGetLocalToGlobalMapping(da, &ltog));
202247c6ae99SBarry Smith 
202347c6ae99SBarry Smith   /* determine the matrix preallocation information */
2024d0609cedSBarry Smith   MatPreallocateBegin(comm, nx * ny * nz, nx * ny * nz, dnz, onz);
202547c6ae99SBarry Smith   for (i = xs; i < xs + nx; i++) {
2026bff4a2f0SMatthew G. Knepley     istart = (bx == DM_BOUNDARY_PERIODIC) ? -s : (PetscMax(-s, -i));
2027bff4a2f0SMatthew G. Knepley     iend   = (bx == DM_BOUNDARY_PERIODIC) ? s : (PetscMin(s, m - i - 1));
202847c6ae99SBarry Smith     for (j = ys; j < ys + ny; j++) {
2029bff4a2f0SMatthew G. Knepley       jstart = (by == DM_BOUNDARY_PERIODIC) ? -s : (PetscMax(-s, -j));
2030bff4a2f0SMatthew G. Knepley       jend   = (by == DM_BOUNDARY_PERIODIC) ? s : (PetscMin(s, n - j - 1));
203147c6ae99SBarry Smith       for (k = zs; k < zs + nz; k++) {
2032bff4a2f0SMatthew G. Knepley         kstart = (bz == DM_BOUNDARY_PERIODIC) ? -s : (PetscMax(-s, -k));
2033bff4a2f0SMatthew G. Knepley         kend   = (bz == DM_BOUNDARY_PERIODIC) ? s : (PetscMin(s, p - k - 1));
203447c6ae99SBarry Smith 
203547c6ae99SBarry Smith         slot = i - gxs + gnx * (j - gys) + gnx * gny * (k - gzs);
203647c6ae99SBarry Smith 
203747c6ae99SBarry Smith         /* Find block columns in block row */
203847c6ae99SBarry Smith         cnt = 0;
203947c6ae99SBarry Smith         for (ii = istart; ii < iend + 1; ii++) {
204047c6ae99SBarry Smith           for (jj = jstart; jj < jend + 1; jj++) {
204147c6ae99SBarry Smith             for (kk = kstart; kk < kend + 1; kk++) {
2042ad540459SPierre Jolivet               if ((st == DMDA_STENCIL_BOX) || (!ii && !jj) || (!jj && !kk) || (!ii && !kk)) cols[cnt++] = slot + ii + gnx * jj + gnx * gny * kk;
204347c6ae99SBarry Smith             }
204447c6ae99SBarry Smith           }
204547c6ae99SBarry Smith         }
20469566063dSJacob Faibussowitsch         PetscCall(L2GFilterUpperTriangular(ltog, &slot, &cnt, cols));
20479566063dSJacob Faibussowitsch         PetscCall(MatPreallocateSymmetricSetBlock(slot, cnt, cols, dnz, onz));
204847c6ae99SBarry Smith       }
204947c6ae99SBarry Smith     }
205047c6ae99SBarry Smith   }
20519566063dSJacob Faibussowitsch   PetscCall(MatSeqSBAIJSetPreallocation(J, nc, 0, dnz));
20529566063dSJacob Faibussowitsch   PetscCall(MatMPISBAIJSetPreallocation(J, nc, 0, dnz, 0, onz));
2053d0609cedSBarry Smith   MatPreallocateEnd(dnz, onz);
205447c6ae99SBarry Smith 
20559566063dSJacob Faibussowitsch   PetscCall(MatSetLocalToGlobalMapping(J, ltog, ltog));
205647c6ae99SBarry Smith 
205747c6ae99SBarry Smith   /*
205847c6ae99SBarry Smith     For each node in the grid: we get the neighbors in the local (on processor ordering
205947c6ae99SBarry Smith     that includes the ghost points) then MatSetValuesLocal() maps those indices to the global
206047c6ae99SBarry Smith     PETSc ordering.
206147c6ae99SBarry Smith   */
2062fcfd50ebSBarry Smith   if (!da->prealloc_only) {
20639566063dSJacob Faibussowitsch     PetscCall(PetscCalloc1(col * col * col * nc * nc, &values));
206447c6ae99SBarry Smith     for (i = xs; i < xs + nx; i++) {
2065bff4a2f0SMatthew G. Knepley       istart = (bx == DM_BOUNDARY_PERIODIC) ? -s : (PetscMax(-s, -i));
2066bff4a2f0SMatthew G. Knepley       iend   = (bx == DM_BOUNDARY_PERIODIC) ? s : (PetscMin(s, m - i - 1));
206747c6ae99SBarry Smith       for (j = ys; j < ys + ny; j++) {
2068bff4a2f0SMatthew G. Knepley         jstart = (by == DM_BOUNDARY_PERIODIC) ? -s : (PetscMax(-s, -j));
2069bff4a2f0SMatthew G. Knepley         jend   = (by == DM_BOUNDARY_PERIODIC) ? s : (PetscMin(s, n - j - 1));
207047c6ae99SBarry Smith         for (k = zs; k < zs + nz; k++) {
2071bff4a2f0SMatthew G. Knepley           kstart = (bz == DM_BOUNDARY_PERIODIC) ? -s : (PetscMax(-s, -k));
2072bff4a2f0SMatthew G. Knepley           kend   = (bz == DM_BOUNDARY_PERIODIC) ? s : (PetscMin(s, p - k - 1));
207347c6ae99SBarry Smith 
207447c6ae99SBarry Smith           slot = i - gxs + gnx * (j - gys) + gnx * gny * (k - gzs);
207547c6ae99SBarry Smith 
207647c6ae99SBarry Smith           cnt = 0;
207747c6ae99SBarry Smith           for (ii = istart; ii < iend + 1; ii++) {
207847c6ae99SBarry Smith             for (jj = jstart; jj < jend + 1; jj++) {
207947c6ae99SBarry Smith               for (kk = kstart; kk < kend + 1; kk++) {
2080ad540459SPierre Jolivet                 if ((st == DMDA_STENCIL_BOX) || (!ii && !jj) || (!jj && !kk) || (!ii && !kk)) cols[cnt++] = slot + ii + gnx * jj + gnx * gny * kk;
208147c6ae99SBarry Smith               }
208247c6ae99SBarry Smith             }
208347c6ae99SBarry Smith           }
20849566063dSJacob Faibussowitsch           PetscCall(L2GFilterUpperTriangular(ltog, &slot, &cnt, cols));
20859566063dSJacob Faibussowitsch           PetscCall(MatSetValuesBlocked(J, 1, &slot, cnt, cols, values, INSERT_VALUES));
208647c6ae99SBarry Smith         }
208747c6ae99SBarry Smith       }
208847c6ae99SBarry Smith     }
20899566063dSJacob Faibussowitsch     PetscCall(PetscFree(values));
2090e7e92044SBarry Smith     /* do not copy values to GPU since they are all zero and not yet needed there */
20919566063dSJacob Faibussowitsch     PetscCall(MatBindToCPU(J, PETSC_TRUE));
20929566063dSJacob Faibussowitsch     PetscCall(MatAssemblyBegin(J, MAT_FINAL_ASSEMBLY));
20939566063dSJacob Faibussowitsch     PetscCall(MatAssemblyEnd(J, MAT_FINAL_ASSEMBLY));
20949566063dSJacob Faibussowitsch     PetscCall(MatBindToCPU(J, PETSC_FALSE));
20959566063dSJacob Faibussowitsch     PetscCall(MatSetOption(J, MAT_NEW_NONZERO_LOCATION_ERR, PETSC_TRUE));
209647c6ae99SBarry Smith   }
20979566063dSJacob Faibussowitsch   PetscCall(PetscFree(cols));
20983ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
209947c6ae99SBarry Smith }
210047c6ae99SBarry Smith 
2101d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateMatrix_DA_3d_MPIAIJ_Fill(DM da, Mat J)
2102d71ae5a4SJacob Faibussowitsch {
210347c6ae99SBarry Smith   PetscInt               xs, ys, nx, ny, i, j, slot, gxs, gys, gnx, gny;
2104c0ab637bSBarry Smith   PetscInt               m, n, dim, s, *cols, k, nc, row, col, cnt, maxcnt = 0, l, p, *dnz, *onz;
2105c1154cd5SBarry Smith   PetscInt               istart, iend, jstart, jend, kstart, kend, zs, nz, gzs, gnz, ii, jj, kk, M, N, P;
210647c6ae99SBarry Smith   DM_DA                 *dd = (DM_DA *)da->data;
210747c6ae99SBarry Smith   PetscInt               ifill_col, *dfill = dd->dfill, *ofill = dd->ofill;
210847c6ae99SBarry Smith   MPI_Comm               comm;
210947c6ae99SBarry Smith   PetscScalar           *values;
2110bff4a2f0SMatthew G. Knepley   DMBoundaryType         bx, by, bz;
211145b6f7e9SBarry Smith   ISLocalToGlobalMapping ltog;
2112aa219208SBarry Smith   DMDAStencilType        st;
2113c1154cd5SBarry Smith   PetscBool              removedups = PETSC_FALSE;
211447c6ae99SBarry Smith 
211547c6ae99SBarry Smith   PetscFunctionBegin;
211647c6ae99SBarry Smith   /*
211747c6ae99SBarry Smith          nc - number of components per grid point
211847c6ae99SBarry Smith          col - number of colors needed in one direction for single component problem
211947c6ae99SBarry Smith   */
21209566063dSJacob Faibussowitsch   PetscCall(DMDAGetInfo(da, &dim, &m, &n, &p, &M, &N, &P, &nc, &s, &bx, &by, &bz, &st));
212147c6ae99SBarry Smith   col = 2 * s + 1;
212247c6ae99SBarry Smith 
2123c1154cd5SBarry Smith   /*
2124c1154cd5SBarry Smith        With one processor in periodic domains in a skinny dimension the code will label nonzero columns multiple times
2125c1154cd5SBarry Smith        because of "wrapping" around the end of the domain hitting an entry already counted in the other direction.
2126c1154cd5SBarry Smith   */
2127c1154cd5SBarry Smith   if (M == 1 && 2 * s >= m) removedups = PETSC_TRUE;
2128c1154cd5SBarry Smith   if (N == 1 && 2 * s >= n) removedups = PETSC_TRUE;
2129c1154cd5SBarry Smith   if (P == 1 && 2 * s >= p) removedups = PETSC_TRUE;
2130c1154cd5SBarry Smith 
21319566063dSJacob Faibussowitsch   PetscCall(DMDAGetCorners(da, &xs, &ys, &zs, &nx, &ny, &nz));
21329566063dSJacob Faibussowitsch   PetscCall(DMDAGetGhostCorners(da, &gxs, &gys, &gzs, &gnx, &gny, &gnz));
21339566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)da, &comm));
213447c6ae99SBarry Smith 
21359566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(col * col * col * nc, &cols));
21369566063dSJacob Faibussowitsch   PetscCall(DMGetLocalToGlobalMapping(da, &ltog));
213747c6ae99SBarry Smith 
213847c6ae99SBarry Smith   /* determine the matrix preallocation information */
2139d0609cedSBarry Smith   MatPreallocateBegin(comm, nc * nx * ny * nz, nc * nx * ny * nz, dnz, onz);
214047c6ae99SBarry Smith 
21419566063dSJacob Faibussowitsch   PetscCall(MatSetBlockSize(J, nc));
214247c6ae99SBarry Smith   for (i = xs; i < xs + nx; i++) {
2143bff4a2f0SMatthew G. Knepley     istart = (bx == DM_BOUNDARY_PERIODIC) ? -s : (PetscMax(-s, -i));
2144bff4a2f0SMatthew G. Knepley     iend   = (bx == DM_BOUNDARY_PERIODIC) ? s : (PetscMin(s, m - i - 1));
214547c6ae99SBarry Smith     for (j = ys; j < ys + ny; j++) {
2146bff4a2f0SMatthew G. Knepley       jstart = (by == DM_BOUNDARY_PERIODIC) ? -s : (PetscMax(-s, -j));
2147bff4a2f0SMatthew G. Knepley       jend   = (by == DM_BOUNDARY_PERIODIC) ? s : (PetscMin(s, n - j - 1));
214847c6ae99SBarry Smith       for (k = zs; k < zs + nz; k++) {
2149bff4a2f0SMatthew G. Knepley         kstart = (bz == DM_BOUNDARY_PERIODIC) ? -s : (PetscMax(-s, -k));
2150bff4a2f0SMatthew G. Knepley         kend   = (bz == DM_BOUNDARY_PERIODIC) ? s : (PetscMin(s, p - k - 1));
215147c6ae99SBarry Smith 
215247c6ae99SBarry Smith         slot = i - gxs + gnx * (j - gys) + gnx * gny * (k - gzs);
215347c6ae99SBarry Smith 
215447c6ae99SBarry Smith         for (l = 0; l < nc; l++) {
215547c6ae99SBarry Smith           cnt = 0;
215647c6ae99SBarry Smith           for (ii = istart; ii < iend + 1; ii++) {
215747c6ae99SBarry Smith             for (jj = jstart; jj < jend + 1; jj++) {
215847c6ae99SBarry Smith               for (kk = kstart; kk < kend + 1; kk++) {
215947c6ae99SBarry Smith                 if (ii || jj || kk) {
2160aa219208SBarry Smith                   if ((st == DMDA_STENCIL_BOX) || ((!ii && !jj) || (!jj && !kk) || (!ii && !kk))) { /* entries on star*/
21618865f1eaSKarl Rupp                     for (ifill_col = ofill[l]; ifill_col < ofill[l + 1]; ifill_col++) cols[cnt++] = ofill[ifill_col] + nc * (slot + ii + gnx * jj + gnx * gny * kk);
216247c6ae99SBarry Smith                   }
216347c6ae99SBarry Smith                 } else {
216447c6ae99SBarry Smith                   if (dfill) {
21658865f1eaSKarl Rupp                     for (ifill_col = dfill[l]; ifill_col < dfill[l + 1]; ifill_col++) cols[cnt++] = dfill[ifill_col] + nc * (slot + ii + gnx * jj + gnx * gny * kk);
216647c6ae99SBarry Smith                   } else {
21678865f1eaSKarl Rupp                     for (ifill_col = 0; ifill_col < nc; ifill_col++) cols[cnt++] = ifill_col + nc * (slot + ii + gnx * jj + gnx * gny * kk);
216847c6ae99SBarry Smith                   }
216947c6ae99SBarry Smith                 }
217047c6ae99SBarry Smith               }
217147c6ae99SBarry Smith             }
217247c6ae99SBarry Smith           }
217347c6ae99SBarry Smith           row    = l + nc * (slot);
2174c0ab637bSBarry Smith           maxcnt = PetscMax(maxcnt, cnt);
21751baa6e33SBarry Smith           if (removedups) PetscCall(MatPreallocateSetLocalRemoveDups(ltog, 1, &row, ltog, cnt, cols, dnz, onz));
21761baa6e33SBarry Smith           else PetscCall(MatPreallocateSetLocal(ltog, 1, &row, ltog, cnt, cols, dnz, onz));
217747c6ae99SBarry Smith         }
217847c6ae99SBarry Smith       }
217947c6ae99SBarry Smith     }
2180c1154cd5SBarry Smith   }
21819566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJSetPreallocation(J, 0, dnz));
21829566063dSJacob Faibussowitsch   PetscCall(MatMPIAIJSetPreallocation(J, 0, dnz, 0, onz));
2183d0609cedSBarry Smith   MatPreallocateEnd(dnz, onz);
21849566063dSJacob Faibussowitsch   PetscCall(MatSetLocalToGlobalMapping(J, ltog, ltog));
218547c6ae99SBarry Smith 
218647c6ae99SBarry Smith   /*
218747c6ae99SBarry Smith     For each node in the grid: we get the neighbors in the local (on processor ordering
218847c6ae99SBarry Smith     that includes the ghost points) then MatSetValuesLocal() maps those indices to the global
218947c6ae99SBarry Smith     PETSc ordering.
219047c6ae99SBarry Smith   */
2191fcfd50ebSBarry Smith   if (!da->prealloc_only) {
21929566063dSJacob Faibussowitsch     PetscCall(PetscCalloc1(maxcnt, &values));
219347c6ae99SBarry Smith     for (i = xs; i < xs + nx; i++) {
2194bff4a2f0SMatthew G. Knepley       istart = (bx == DM_BOUNDARY_PERIODIC) ? -s : (PetscMax(-s, -i));
2195bff4a2f0SMatthew G. Knepley       iend   = (bx == DM_BOUNDARY_PERIODIC) ? s : (PetscMin(s, m - i - 1));
219647c6ae99SBarry Smith       for (j = ys; j < ys + ny; j++) {
2197bff4a2f0SMatthew G. Knepley         jstart = (by == DM_BOUNDARY_PERIODIC) ? -s : (PetscMax(-s, -j));
2198bff4a2f0SMatthew G. Knepley         jend   = (by == DM_BOUNDARY_PERIODIC) ? s : (PetscMin(s, n - j - 1));
219947c6ae99SBarry Smith         for (k = zs; k < zs + nz; k++) {
2200bff4a2f0SMatthew G. Knepley           kstart = (bz == DM_BOUNDARY_PERIODIC) ? -s : (PetscMax(-s, -k));
2201bff4a2f0SMatthew G. Knepley           kend   = (bz == DM_BOUNDARY_PERIODIC) ? s : (PetscMin(s, p - k - 1));
220247c6ae99SBarry Smith 
220347c6ae99SBarry Smith           slot = i - gxs + gnx * (j - gys) + gnx * gny * (k - gzs);
220447c6ae99SBarry Smith 
220547c6ae99SBarry Smith           for (l = 0; l < nc; l++) {
220647c6ae99SBarry Smith             cnt = 0;
220747c6ae99SBarry Smith             for (ii = istart; ii < iend + 1; ii++) {
220847c6ae99SBarry Smith               for (jj = jstart; jj < jend + 1; jj++) {
220947c6ae99SBarry Smith                 for (kk = kstart; kk < kend + 1; kk++) {
221047c6ae99SBarry Smith                   if (ii || jj || kk) {
2211aa219208SBarry Smith                     if ((st == DMDA_STENCIL_BOX) || ((!ii && !jj) || (!jj && !kk) || (!ii && !kk))) { /* entries on star*/
22128865f1eaSKarl Rupp                       for (ifill_col = ofill[l]; ifill_col < ofill[l + 1]; ifill_col++) cols[cnt++] = ofill[ifill_col] + nc * (slot + ii + gnx * jj + gnx * gny * kk);
221347c6ae99SBarry Smith                     }
221447c6ae99SBarry Smith                   } else {
221547c6ae99SBarry Smith                     if (dfill) {
22168865f1eaSKarl Rupp                       for (ifill_col = dfill[l]; ifill_col < dfill[l + 1]; ifill_col++) cols[cnt++] = dfill[ifill_col] + nc * (slot + ii + gnx * jj + gnx * gny * kk);
221747c6ae99SBarry Smith                     } else {
22188865f1eaSKarl Rupp                       for (ifill_col = 0; ifill_col < nc; ifill_col++) cols[cnt++] = ifill_col + nc * (slot + ii + gnx * jj + gnx * gny * kk);
221947c6ae99SBarry Smith                     }
222047c6ae99SBarry Smith                   }
222147c6ae99SBarry Smith                 }
222247c6ae99SBarry Smith               }
222347c6ae99SBarry Smith             }
222447c6ae99SBarry Smith             row = l + nc * (slot);
22259566063dSJacob Faibussowitsch             PetscCall(MatSetValuesLocal(J, 1, &row, cnt, cols, values, INSERT_VALUES));
222647c6ae99SBarry Smith           }
222747c6ae99SBarry Smith         }
222847c6ae99SBarry Smith       }
222947c6ae99SBarry Smith     }
22309566063dSJacob Faibussowitsch     PetscCall(PetscFree(values));
2231e7e92044SBarry Smith     /* do not copy values to GPU since they are all zero and not yet needed there */
22329566063dSJacob Faibussowitsch     PetscCall(MatBindToCPU(J, PETSC_TRUE));
22339566063dSJacob Faibussowitsch     PetscCall(MatAssemblyBegin(J, MAT_FINAL_ASSEMBLY));
22349566063dSJacob Faibussowitsch     PetscCall(MatAssemblyEnd(J, MAT_FINAL_ASSEMBLY));
22359566063dSJacob Faibussowitsch     PetscCall(MatBindToCPU(J, PETSC_FALSE));
22369566063dSJacob Faibussowitsch     PetscCall(MatSetOption(J, MAT_NEW_NONZERO_LOCATION_ERR, PETSC_TRUE));
223747c6ae99SBarry Smith   }
22389566063dSJacob Faibussowitsch   PetscCall(PetscFree(cols));
22393ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
224047c6ae99SBarry Smith }
2241