xref: /petsc/src/dm/impls/da/fdda.c (revision 48a46eb9bd028bec07ec0f396b1a3abb43f14558)
147c6ae99SBarry Smith 
2af0996ceSBarry Smith #include <petsc/private/dmdaimpl.h> /*I      "petscdmda.h"     I*/
307475bc1SBarry Smith #include <petscmat.h>
4e432b41dSStefano Zampini #include <petscbt.h>
547c6ae99SBarry Smith 
6e727c939SJed Brown extern PetscErrorCode DMCreateColoring_DA_1d_MPIAIJ(DM, ISColoringType, ISColoring *);
7e727c939SJed Brown extern PetscErrorCode DMCreateColoring_DA_2d_MPIAIJ(DM, ISColoringType, ISColoring *);
8e727c939SJed Brown extern PetscErrorCode DMCreateColoring_DA_2d_5pt_MPIAIJ(DM, ISColoringType, ISColoring *);
9e727c939SJed Brown extern PetscErrorCode DMCreateColoring_DA_3d_MPIAIJ(DM, ISColoringType, ISColoring *);
1047c6ae99SBarry Smith 
1147c6ae99SBarry Smith /*
1247c6ae99SBarry Smith    For ghost i that may be negative or greater than the upper bound this
1347c6ae99SBarry Smith   maps it into the 0:m-1 range using periodicity
1447c6ae99SBarry Smith */
1547c6ae99SBarry Smith #define SetInRange(i, m) ((i < 0) ? m + i : ((i >= m) ? i - m : i))
1647c6ae99SBarry Smith 
179371c9d4SSatish Balay static PetscErrorCode DMDASetBlockFills_Private(const PetscInt *dfill, PetscInt w, PetscInt **rfill) {
1847c6ae99SBarry Smith   PetscInt i, j, nz, *fill;
1947c6ae99SBarry Smith 
2047c6ae99SBarry Smith   PetscFunctionBegin;
2147c6ae99SBarry Smith   if (!dfill) PetscFunctionReturn(0);
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;
4747c6ae99SBarry Smith   PetscFunctionReturn(0);
4847c6ae99SBarry Smith }
4947c6ae99SBarry Smith 
509371c9d4SSatish Balay static PetscErrorCode DMDASetBlockFillsSparse_Private(const PetscInt *dfillsparse, PetscInt w, PetscInt **rfill) {
51767d920cSKarl Rupp   PetscInt nz;
5209e28618SBarry Smith 
5309e28618SBarry Smith   PetscFunctionBegin;
5409e28618SBarry Smith   if (!dfillsparse) PetscFunctionReturn(0);
5509e28618SBarry Smith 
5609e28618SBarry Smith   /* Determine number of non-zeros */
5709e28618SBarry Smith   nz = (dfillsparse[w] - w - 1);
5809e28618SBarry Smith 
5909e28618SBarry Smith   /* Allocate space for our copy of the given sparse matrix representation. */
609566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(nz + w + 1, rfill));
619566063dSJacob Faibussowitsch   PetscCall(PetscArraycpy(*rfill, dfillsparse, nz + w + 1));
6209e28618SBarry Smith   PetscFunctionReturn(0);
6309e28618SBarry Smith }
6409e28618SBarry Smith 
659371c9d4SSatish Balay static PetscErrorCode DMDASetBlockFills_Private2(DM_DA *dd) {
6609e28618SBarry Smith   PetscInt i, k, cnt = 1;
6709e28618SBarry Smith 
6809e28618SBarry Smith   PetscFunctionBegin;
6909e28618SBarry Smith 
7009e28618SBarry Smith   /* ofillcount tracks the columns of ofill that have any nonzero in thems; the value in each location is the number of
7109e28618SBarry Smith    columns to the left with any nonzeros in them plus 1 */
729566063dSJacob Faibussowitsch   PetscCall(PetscCalloc1(dd->w, &dd->ofillcols));
7309e28618SBarry Smith   for (i = 0; i < dd->w; i++) {
7409e28618SBarry Smith     for (k = dd->ofill[i]; k < dd->ofill[i + 1]; k++) dd->ofillcols[dd->ofill[k]] = 1;
7509e28618SBarry Smith   }
7609e28618SBarry Smith   for (i = 0; i < dd->w; i++) {
779371c9d4SSatish Balay     if (dd->ofillcols[i]) { dd->ofillcols[i] = cnt++; }
7809e28618SBarry Smith   }
7909e28618SBarry Smith   PetscFunctionReturn(0);
8009e28618SBarry Smith }
8109e28618SBarry Smith 
8247c6ae99SBarry Smith /*@
83aa219208SBarry Smith     DMDASetBlockFills - Sets the fill pattern in each block for a multi-component problem
84950540a4SJed Brown     of the matrix returned by DMCreateMatrix().
8547c6ae99SBarry Smith 
86d083f849SBarry Smith     Logically Collective on da
8747c6ae99SBarry Smith 
88d8d19677SJose E. Roman     Input Parameters:
8947c6ae99SBarry Smith +   da - the distributed array
900298fd71SBarry Smith .   dfill - the fill pattern in the diagonal block (may be NULL, means use dense block)
9147c6ae99SBarry Smith -   ofill - the fill pattern in the off-diagonal blocks
9247c6ae99SBarry Smith 
9347c6ae99SBarry Smith     Level: developer
9447c6ae99SBarry Smith 
9595452b02SPatrick Sanan     Notes:
9695452b02SPatrick Sanan     This only makes sense when you are doing multicomponent problems but using the
9747c6ae99SBarry Smith        MPIAIJ matrix format
9847c6ae99SBarry Smith 
9947c6ae99SBarry Smith            The format for dfill and ofill is a 2 dimensional dof by dof matrix with 1 entries
10047c6ae99SBarry Smith        representing coupling and 0 entries for missing coupling. For example
10147c6ae99SBarry Smith $             dfill[9] = {1, 0, 0,
10247c6ae99SBarry Smith $                         1, 1, 0,
10347c6ae99SBarry Smith $                         0, 1, 1}
10447c6ae99SBarry Smith        means that row 0 is coupled with only itself in the diagonal block, row 1 is coupled with
10547c6ae99SBarry Smith        itself and row 0 (in the diagonal block) and row 2 is coupled with itself and row 1 (in the
10647c6ae99SBarry Smith        diagonal block).
10747c6ae99SBarry Smith 
108aa219208SBarry Smith      DMDASetGetMatrix() allows you to provide general code for those more complicated nonzero patterns then
10947c6ae99SBarry Smith      can be represented in the dfill, ofill format
11047c6ae99SBarry Smith 
11147c6ae99SBarry Smith    Contributed by Glenn Hammond
11247c6ae99SBarry Smith 
113db781477SPatrick Sanan .seealso `DMCreateMatrix()`, `DMDASetGetMatrix()`, `DMSetMatrixPreallocateOnly()`
11447c6ae99SBarry Smith 
11547c6ae99SBarry Smith @*/
1169371c9d4SSatish Balay PetscErrorCode DMDASetBlockFills(DM da, const PetscInt *dfill, const PetscInt *ofill) {
11747c6ae99SBarry Smith   DM_DA *dd = (DM_DA *)da->data;
11847c6ae99SBarry Smith 
11947c6ae99SBarry Smith   PetscFunctionBegin;
12009e28618SBarry Smith   /* save the given dfill and ofill information */
1219566063dSJacob Faibussowitsch   PetscCall(DMDASetBlockFills_Private(dfill, dd->w, &dd->dfill));
1229566063dSJacob Faibussowitsch   PetscCall(DMDASetBlockFills_Private(ofill, dd->w, &dd->ofill));
123ae4f298aSBarry Smith 
12409e28618SBarry Smith   /* count nonzeros in ofill columns */
1259566063dSJacob Faibussowitsch   PetscCall(DMDASetBlockFills_Private2(dd));
12609e28618SBarry Smith   PetscFunctionReturn(0);
127ae4f298aSBarry Smith }
12809e28618SBarry Smith 
12909e28618SBarry Smith /*@
13009e28618SBarry Smith     DMDASetBlockFillsSparse - Sets the fill pattern in each block for a multi-component problem
13109e28618SBarry Smith     of the matrix returned by DMCreateMatrix(), using sparse representations
13209e28618SBarry Smith     of fill patterns.
13309e28618SBarry Smith 
134d083f849SBarry Smith     Logically Collective on da
13509e28618SBarry Smith 
136d8d19677SJose E. Roman     Input Parameters:
13709e28618SBarry Smith +   da - the distributed array
13809e28618SBarry Smith .   dfill - the sparse fill pattern in the diagonal block (may be NULL, means use dense block)
13909e28618SBarry Smith -   ofill - the sparse fill pattern in the off-diagonal blocks
14009e28618SBarry Smith 
14109e28618SBarry Smith     Level: developer
14209e28618SBarry Smith 
14309e28618SBarry Smith     Notes: This only makes sense when you are doing multicomponent problems but using the
14409e28618SBarry Smith        MPIAIJ matrix format
14509e28618SBarry Smith 
14609e28618SBarry Smith            The format for dfill and ofill is a sparse representation of a
14709e28618SBarry Smith            dof-by-dof matrix with 1 entries representing coupling and 0 entries
14809e28618SBarry Smith            for missing coupling.  The sparse representation is a 1 dimensional
14909e28618SBarry Smith            array of length nz + dof + 1, where nz is the number of non-zeros in
15009e28618SBarry Smith            the matrix.  The first dof entries in the array give the
15109e28618SBarry Smith            starting array indices of each row's items in the rest of the array,
15260942847SBarry Smith            the dof+1st item contains the value nz + dof + 1 (i.e. the entire length of the array)
15309e28618SBarry Smith            and the remaining nz items give the column indices of each of
15409e28618SBarry Smith            the 1s within the logical 2D matrix.  Each row's items within
15509e28618SBarry Smith            the array are the column indices of the 1s within that row
15609e28618SBarry Smith            of the 2D matrix.  PETSc developers may recognize that this is the
15709e28618SBarry Smith            same format as that computed by the DMDASetBlockFills_Private()
15809e28618SBarry Smith            function from a dense 2D matrix representation.
15909e28618SBarry Smith 
16009e28618SBarry Smith      DMDASetGetMatrix() allows you to provide general code for those more complicated nonzero patterns then
16109e28618SBarry Smith      can be represented in the dfill, ofill format
16209e28618SBarry Smith 
16309e28618SBarry Smith    Contributed by Philip C. Roth
16409e28618SBarry Smith 
165db781477SPatrick Sanan .seealso `DMDASetBlockFills()`, `DMCreateMatrix()`, `DMDASetGetMatrix()`, `DMSetMatrixPreallocateOnly()`
16609e28618SBarry Smith 
16709e28618SBarry Smith @*/
1689371c9d4SSatish Balay PetscErrorCode DMDASetBlockFillsSparse(DM da, const PetscInt *dfillsparse, const PetscInt *ofillsparse) {
16909e28618SBarry Smith   DM_DA *dd = (DM_DA *)da->data;
17009e28618SBarry Smith 
17109e28618SBarry Smith   PetscFunctionBegin;
17209e28618SBarry Smith   /* save the given dfill and ofill information */
1739566063dSJacob Faibussowitsch   PetscCall(DMDASetBlockFillsSparse_Private(dfillsparse, dd->w, &dd->dfill));
1749566063dSJacob Faibussowitsch   PetscCall(DMDASetBlockFillsSparse_Private(ofillsparse, dd->w, &dd->ofill));
17509e28618SBarry Smith 
17609e28618SBarry Smith   /* count nonzeros in ofill columns */
1779566063dSJacob Faibussowitsch   PetscCall(DMDASetBlockFills_Private2(dd));
17847c6ae99SBarry Smith   PetscFunctionReturn(0);
17947c6ae99SBarry Smith }
18047c6ae99SBarry Smith 
1819371c9d4SSatish Balay PetscErrorCode DMCreateColoring_DA(DM da, ISColoringType ctype, ISColoring *coloring) {
18247c6ae99SBarry Smith   PetscInt       dim, m, n, p, nc;
183bff4a2f0SMatthew G. Knepley   DMBoundaryType bx, by, bz;
18447c6ae99SBarry Smith   MPI_Comm       comm;
18547c6ae99SBarry Smith   PetscMPIInt    size;
18647c6ae99SBarry Smith   PetscBool      isBAIJ;
18747c6ae99SBarry Smith   DM_DA         *dd = (DM_DA *)da->data;
18847c6ae99SBarry Smith 
18947c6ae99SBarry Smith   PetscFunctionBegin;
19047c6ae99SBarry Smith   /*
19147c6ae99SBarry Smith                                   m
19247c6ae99SBarry Smith           ------------------------------------------------------
19347c6ae99SBarry Smith          |                                                     |
19447c6ae99SBarry Smith          |                                                     |
19547c6ae99SBarry Smith          |               ----------------------                |
19647c6ae99SBarry Smith          |               |                    |                |
19747c6ae99SBarry Smith       n  |           yn  |                    |                |
19847c6ae99SBarry Smith          |               |                    |                |
19947c6ae99SBarry Smith          |               .---------------------                |
20047c6ae99SBarry Smith          |             (xs,ys)     xn                          |
20147c6ae99SBarry Smith          |            .                                        |
20247c6ae99SBarry Smith          |         (gxs,gys)                                   |
20347c6ae99SBarry Smith          |                                                     |
20447c6ae99SBarry Smith           -----------------------------------------------------
20547c6ae99SBarry Smith   */
20647c6ae99SBarry Smith 
20747c6ae99SBarry Smith   /*
20847c6ae99SBarry Smith          nc - number of components per grid point
20947c6ae99SBarry Smith          col - number of colors needed in one direction for single component problem
21047c6ae99SBarry Smith 
21147c6ae99SBarry Smith   */
2129566063dSJacob Faibussowitsch   PetscCall(DMDAGetInfo(da, &dim, NULL, NULL, NULL, &m, &n, &p, &nc, NULL, &bx, &by, &bz, NULL));
21347c6ae99SBarry Smith 
2149566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)da, &comm));
2159566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(comm, &size));
2165bdb020cSBarry Smith   if (ctype == IS_COLORING_LOCAL) {
21747c6ae99SBarry Smith     if (size == 1) {
21847c6ae99SBarry Smith       ctype = IS_COLORING_GLOBAL;
21947c6ae99SBarry Smith     } else if (dim > 1) {
220bff4a2f0SMatthew G. Knepley       if ((m == 1 && bx == DM_BOUNDARY_PERIODIC) || (n == 1 && by == DM_BOUNDARY_PERIODIC) || (p == 1 && bz == DM_BOUNDARY_PERIODIC)) {
2215bdb020cSBarry Smith         SETERRQ(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");
22247c6ae99SBarry Smith       }
22347c6ae99SBarry Smith     }
22447c6ae99SBarry Smith   }
22547c6ae99SBarry Smith 
226aa219208SBarry Smith   /* Tell the DMDA it has 1 degree of freedom per grid point so that the coloring for BAIJ
22747c6ae99SBarry Smith      matrices is for the blocks, not the individual matrix elements  */
2289566063dSJacob Faibussowitsch   PetscCall(PetscStrbeginswith(da->mattype, MATBAIJ, &isBAIJ));
2299566063dSJacob Faibussowitsch   if (!isBAIJ) PetscCall(PetscStrbeginswith(da->mattype, MATMPIBAIJ, &isBAIJ));
2309566063dSJacob Faibussowitsch   if (!isBAIJ) PetscCall(PetscStrbeginswith(da->mattype, MATSEQBAIJ, &isBAIJ));
23147c6ae99SBarry Smith   if (isBAIJ) {
23247c6ae99SBarry Smith     dd->w  = 1;
23347c6ae99SBarry Smith     dd->xs = dd->xs / nc;
23447c6ae99SBarry Smith     dd->xe = dd->xe / nc;
23547c6ae99SBarry Smith     dd->Xs = dd->Xs / nc;
23647c6ae99SBarry Smith     dd->Xe = dd->Xe / nc;
23747c6ae99SBarry Smith   }
23847c6ae99SBarry Smith 
23947c6ae99SBarry Smith   /*
240aa219208SBarry Smith      We do not provide a getcoloring function in the DMDA operations because
2419a1b256bSStefano Zampini    the basic DMDA does not know about matrices. We think of DMDA as being
24247c6ae99SBarry Smith    more low-level then matrices.
24347c6ae99SBarry Smith   */
2441baa6e33SBarry Smith   if (dim == 1) PetscCall(DMCreateColoring_DA_1d_MPIAIJ(da, ctype, coloring));
2451baa6e33SBarry Smith   else if (dim == 2) PetscCall(DMCreateColoring_DA_2d_MPIAIJ(da, ctype, coloring));
2461baa6e33SBarry Smith   else if (dim == 3) PetscCall(DMCreateColoring_DA_3d_MPIAIJ(da, ctype, coloring));
2471baa6e33SBarry 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);
24847c6ae99SBarry Smith   if (isBAIJ) {
24947c6ae99SBarry Smith     dd->w  = nc;
25047c6ae99SBarry Smith     dd->xs = dd->xs * nc;
25147c6ae99SBarry Smith     dd->xe = dd->xe * nc;
25247c6ae99SBarry Smith     dd->Xs = dd->Xs * nc;
25347c6ae99SBarry Smith     dd->Xe = dd->Xe * nc;
25447c6ae99SBarry Smith   }
25547c6ae99SBarry Smith   PetscFunctionReturn(0);
25647c6ae99SBarry Smith }
25747c6ae99SBarry Smith 
25847c6ae99SBarry Smith /* ---------------------------------------------------------------------------------*/
25947c6ae99SBarry Smith 
2609371c9d4SSatish Balay PetscErrorCode DMCreateColoring_DA_2d_MPIAIJ(DM da, ISColoringType ctype, ISColoring *coloring) {
26147c6ae99SBarry Smith   PetscInt         xs, ys, nx, ny, i, j, ii, gxs, gys, gnx, gny, m, n, M, N, dim, s, k, nc, col;
26247c6ae99SBarry Smith   PetscInt         ncolors;
26347c6ae99SBarry Smith   MPI_Comm         comm;
264bff4a2f0SMatthew G. Knepley   DMBoundaryType   bx, by;
265aa219208SBarry Smith   DMDAStencilType  st;
26647c6ae99SBarry Smith   ISColoringValue *colors;
26747c6ae99SBarry Smith   DM_DA           *dd = (DM_DA *)da->data;
26847c6ae99SBarry Smith 
26947c6ae99SBarry Smith   PetscFunctionBegin;
27047c6ae99SBarry Smith   /*
27147c6ae99SBarry Smith          nc - number of components per grid point
27247c6ae99SBarry Smith          col - number of colors needed in one direction for single component problem
27347c6ae99SBarry Smith 
27447c6ae99SBarry Smith   */
2759566063dSJacob Faibussowitsch   PetscCall(DMDAGetInfo(da, &dim, &m, &n, NULL, &M, &N, NULL, &nc, &s, &bx, &by, NULL, &st));
27647c6ae99SBarry Smith   col = 2 * s + 1;
2779566063dSJacob Faibussowitsch   PetscCall(DMDAGetCorners(da, &xs, &ys, NULL, &nx, &ny, NULL));
2789566063dSJacob Faibussowitsch   PetscCall(DMDAGetGhostCorners(da, &gxs, &gys, NULL, &gnx, &gny, NULL));
2799566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)da, &comm));
28047c6ae99SBarry Smith 
28147c6ae99SBarry Smith   /* special case as taught to us by Paul Hovland */
282aa219208SBarry Smith   if (st == DMDA_STENCIL_STAR && s == 1) {
2839566063dSJacob Faibussowitsch     PetscCall(DMCreateColoring_DA_2d_5pt_MPIAIJ(da, ctype, coloring));
28447c6ae99SBarry Smith   } else {
28547c6ae99SBarry Smith     if (ctype == IS_COLORING_GLOBAL) {
28647c6ae99SBarry Smith       if (!dd->localcoloring) {
2879566063dSJacob Faibussowitsch         PetscCall(PetscMalloc1(nc * nx * ny, &colors));
28847c6ae99SBarry Smith         ii = 0;
28947c6ae99SBarry Smith         for (j = ys; j < ys + ny; j++) {
29047c6ae99SBarry Smith           for (i = xs; i < xs + nx; i++) {
2919371c9d4SSatish Balay             for (k = 0; k < nc; k++) { colors[ii++] = k + nc * ((i % col) + col * (j % col)); }
29247c6ae99SBarry Smith           }
29347c6ae99SBarry Smith         }
29447c6ae99SBarry Smith         ncolors = nc + nc * (col - 1 + col * (col - 1));
2959566063dSJacob Faibussowitsch         PetscCall(ISColoringCreate(comm, ncolors, nc * nx * ny, colors, PETSC_OWN_POINTER, &dd->localcoloring));
29647c6ae99SBarry Smith       }
29747c6ae99SBarry Smith       *coloring = dd->localcoloring;
2985bdb020cSBarry Smith     } else if (ctype == IS_COLORING_LOCAL) {
29947c6ae99SBarry Smith       if (!dd->ghostedcoloring) {
3009566063dSJacob Faibussowitsch         PetscCall(PetscMalloc1(nc * gnx * gny, &colors));
30147c6ae99SBarry Smith         ii = 0;
30247c6ae99SBarry Smith         for (j = gys; j < gys + gny; j++) {
30347c6ae99SBarry Smith           for (i = gxs; i < gxs + gnx; i++) {
30447c6ae99SBarry Smith             for (k = 0; k < nc; k++) {
30547c6ae99SBarry Smith               /* the complicated stuff is to handle periodic boundaries */
30647c6ae99SBarry Smith               colors[ii++] = k + nc * ((SetInRange(i, m) % col) + col * (SetInRange(j, n) % col));
30747c6ae99SBarry Smith             }
30847c6ae99SBarry Smith           }
30947c6ae99SBarry Smith         }
31047c6ae99SBarry Smith         ncolors = nc + nc * (col - 1 + col * (col - 1));
3119566063dSJacob Faibussowitsch         PetscCall(ISColoringCreate(comm, ncolors, nc * gnx * gny, colors, PETSC_OWN_POINTER, &dd->ghostedcoloring));
31247c6ae99SBarry Smith         /* PetscIntView(ncolors,(PetscInt*)colors,0); */
31347c6ae99SBarry Smith 
3149566063dSJacob Faibussowitsch         PetscCall(ISColoringSetType(dd->ghostedcoloring, IS_COLORING_LOCAL));
31547c6ae99SBarry Smith       }
31647c6ae99SBarry Smith       *coloring = dd->ghostedcoloring;
31798921bdaSJacob Faibussowitsch     } else SETERRQ(PetscObjectComm((PetscObject)da), PETSC_ERR_ARG_WRONG, "Unknown ISColoringType %d", (int)ctype);
31847c6ae99SBarry Smith   }
3199566063dSJacob Faibussowitsch   PetscCall(ISColoringReference(*coloring));
32047c6ae99SBarry Smith   PetscFunctionReturn(0);
32147c6ae99SBarry Smith }
32247c6ae99SBarry Smith 
32347c6ae99SBarry Smith /* ---------------------------------------------------------------------------------*/
32447c6ae99SBarry Smith 
3259371c9d4SSatish Balay PetscErrorCode DMCreateColoring_DA_3d_MPIAIJ(DM da, ISColoringType ctype, ISColoring *coloring) {
32647c6ae99SBarry 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;
32747c6ae99SBarry Smith   PetscInt         ncolors;
32847c6ae99SBarry Smith   MPI_Comm         comm;
329bff4a2f0SMatthew G. Knepley   DMBoundaryType   bx, by, bz;
330aa219208SBarry Smith   DMDAStencilType  st;
33147c6ae99SBarry Smith   ISColoringValue *colors;
33247c6ae99SBarry Smith   DM_DA           *dd = (DM_DA *)da->data;
33347c6ae99SBarry Smith 
33447c6ae99SBarry Smith   PetscFunctionBegin;
33547c6ae99SBarry Smith   /*
33647c6ae99SBarry Smith          nc - number of components per grid point
33747c6ae99SBarry Smith          col - number of colors needed in one direction for single component problem
33847c6ae99SBarry Smith 
33947c6ae99SBarry Smith   */
3409566063dSJacob Faibussowitsch   PetscCall(DMDAGetInfo(da, &dim, &m, &n, &p, &M, &N, &P, &nc, &s, &bx, &by, &bz, &st));
34147c6ae99SBarry Smith   col = 2 * s + 1;
3429566063dSJacob Faibussowitsch   PetscCall(DMDAGetCorners(da, &xs, &ys, &zs, &nx, &ny, &nz));
3439566063dSJacob Faibussowitsch   PetscCall(DMDAGetGhostCorners(da, &gxs, &gys, &gzs, &gnx, &gny, &gnz));
3449566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)da, &comm));
34547c6ae99SBarry Smith 
34647c6ae99SBarry Smith   /* create the coloring */
34747c6ae99SBarry Smith   if (ctype == IS_COLORING_GLOBAL) {
34847c6ae99SBarry Smith     if (!dd->localcoloring) {
3499566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(nc * nx * ny * nz, &colors));
35047c6ae99SBarry Smith       ii = 0;
35147c6ae99SBarry Smith       for (k = zs; k < zs + nz; k++) {
35247c6ae99SBarry Smith         for (j = ys; j < ys + ny; j++) {
35347c6ae99SBarry Smith           for (i = xs; i < xs + nx; i++) {
3549371c9d4SSatish Balay             for (l = 0; l < nc; l++) { colors[ii++] = l + nc * ((i % col) + col * (j % col) + col * col * (k % col)); }
35547c6ae99SBarry Smith           }
35647c6ae99SBarry Smith         }
35747c6ae99SBarry Smith       }
35847c6ae99SBarry Smith       ncolors = nc + nc * (col - 1 + col * (col - 1) + col * col * (col - 1));
3599566063dSJacob Faibussowitsch       PetscCall(ISColoringCreate(comm, ncolors, nc * nx * ny * nz, colors, PETSC_OWN_POINTER, &dd->localcoloring));
36047c6ae99SBarry Smith     }
36147c6ae99SBarry Smith     *coloring = dd->localcoloring;
3625bdb020cSBarry Smith   } else if (ctype == IS_COLORING_LOCAL) {
36347c6ae99SBarry Smith     if (!dd->ghostedcoloring) {
3649566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(nc * gnx * gny * gnz, &colors));
36547c6ae99SBarry Smith       ii = 0;
36647c6ae99SBarry Smith       for (k = gzs; k < gzs + gnz; k++) {
36747c6ae99SBarry Smith         for (j = gys; j < gys + gny; j++) {
36847c6ae99SBarry Smith           for (i = gxs; i < gxs + gnx; i++) {
36947c6ae99SBarry Smith             for (l = 0; l < nc; l++) {
37047c6ae99SBarry Smith               /* the complicated stuff is to handle periodic boundaries */
37147c6ae99SBarry Smith               colors[ii++] = l + nc * ((SetInRange(i, m) % col) + col * (SetInRange(j, n) % col) + col * col * (SetInRange(k, p) % col));
37247c6ae99SBarry Smith             }
37347c6ae99SBarry Smith           }
37447c6ae99SBarry Smith         }
37547c6ae99SBarry Smith       }
37647c6ae99SBarry Smith       ncolors = nc + nc * (col - 1 + col * (col - 1) + col * col * (col - 1));
3779566063dSJacob Faibussowitsch       PetscCall(ISColoringCreate(comm, ncolors, nc * gnx * gny * gnz, colors, PETSC_OWN_POINTER, &dd->ghostedcoloring));
3789566063dSJacob Faibussowitsch       PetscCall(ISColoringSetType(dd->ghostedcoloring, IS_COLORING_LOCAL));
37947c6ae99SBarry Smith     }
38047c6ae99SBarry Smith     *coloring = dd->ghostedcoloring;
38198921bdaSJacob Faibussowitsch   } else SETERRQ(PetscObjectComm((PetscObject)da), PETSC_ERR_ARG_WRONG, "Unknown ISColoringType %d", (int)ctype);
3829566063dSJacob Faibussowitsch   PetscCall(ISColoringReference(*coloring));
38347c6ae99SBarry Smith   PetscFunctionReturn(0);
38447c6ae99SBarry Smith }
38547c6ae99SBarry Smith 
38647c6ae99SBarry Smith /* ---------------------------------------------------------------------------------*/
38747c6ae99SBarry Smith 
3889371c9d4SSatish Balay PetscErrorCode DMCreateColoring_DA_1d_MPIAIJ(DM da, ISColoringType ctype, ISColoring *coloring) {
38947c6ae99SBarry Smith   PetscInt         xs, nx, i, i1, gxs, gnx, l, m, M, dim, s, nc, col;
39047c6ae99SBarry Smith   PetscInt         ncolors;
39147c6ae99SBarry Smith   MPI_Comm         comm;
392bff4a2f0SMatthew G. Knepley   DMBoundaryType   bx;
39347c6ae99SBarry Smith   ISColoringValue *colors;
39447c6ae99SBarry Smith   DM_DA           *dd = (DM_DA *)da->data;
39547c6ae99SBarry Smith 
39647c6ae99SBarry Smith   PetscFunctionBegin;
39747c6ae99SBarry Smith   /*
39847c6ae99SBarry Smith          nc - number of components per grid point
39947c6ae99SBarry Smith          col - number of colors needed in one direction for single component problem
40047c6ae99SBarry Smith 
40147c6ae99SBarry Smith   */
4029566063dSJacob Faibussowitsch   PetscCall(DMDAGetInfo(da, &dim, &m, NULL, NULL, &M, NULL, NULL, &nc, &s, &bx, NULL, NULL, NULL));
40347c6ae99SBarry Smith   col = 2 * s + 1;
4049566063dSJacob Faibussowitsch   PetscCall(DMDAGetCorners(da, &xs, NULL, NULL, &nx, NULL, NULL));
4059566063dSJacob Faibussowitsch   PetscCall(DMDAGetGhostCorners(da, &gxs, NULL, NULL, &gnx, NULL, NULL));
4069566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)da, &comm));
40747c6ae99SBarry Smith 
40847c6ae99SBarry Smith   /* create the coloring */
40947c6ae99SBarry Smith   if (ctype == IS_COLORING_GLOBAL) {
41047c6ae99SBarry Smith     if (!dd->localcoloring) {
4119566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(nc * nx, &colors));
412ae4f298aSBarry Smith       if (dd->ofillcols) {
413ae4f298aSBarry Smith         PetscInt tc = 0;
414ae4f298aSBarry Smith         for (i = 0; i < nc; i++) tc += (PetscInt)(dd->ofillcols[i] > 0);
415ae4f298aSBarry Smith         i1 = 0;
416ae4f298aSBarry Smith         for (i = xs; i < xs + nx; i++) {
417ae4f298aSBarry Smith           for (l = 0; l < nc; l++) {
418ae4f298aSBarry Smith             if (dd->ofillcols[l] && (i % col)) {
419ae4f298aSBarry Smith               colors[i1++] = nc - 1 + tc * ((i % col) - 1) + dd->ofillcols[l];
420ae4f298aSBarry Smith             } else {
421ae4f298aSBarry Smith               colors[i1++] = l;
422ae4f298aSBarry Smith             }
423ae4f298aSBarry Smith           }
424ae4f298aSBarry Smith         }
425ae4f298aSBarry Smith         ncolors = nc + 2 * s * tc;
426ae4f298aSBarry Smith       } else {
42747c6ae99SBarry Smith         i1 = 0;
42847c6ae99SBarry Smith         for (i = xs; i < xs + nx; i++) {
4299371c9d4SSatish Balay           for (l = 0; l < nc; l++) { colors[i1++] = l + nc * (i % col); }
43047c6ae99SBarry Smith         }
43147c6ae99SBarry Smith         ncolors = nc + nc * (col - 1);
432ae4f298aSBarry Smith       }
4339566063dSJacob Faibussowitsch       PetscCall(ISColoringCreate(comm, ncolors, nc * nx, colors, PETSC_OWN_POINTER, &dd->localcoloring));
43447c6ae99SBarry Smith     }
43547c6ae99SBarry Smith     *coloring = dd->localcoloring;
4365bdb020cSBarry Smith   } else if (ctype == IS_COLORING_LOCAL) {
43747c6ae99SBarry Smith     if (!dd->ghostedcoloring) {
4389566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(nc * gnx, &colors));
43947c6ae99SBarry Smith       i1 = 0;
44047c6ae99SBarry Smith       for (i = gxs; i < gxs + gnx; i++) {
44147c6ae99SBarry Smith         for (l = 0; l < nc; l++) {
44247c6ae99SBarry Smith           /* the complicated stuff is to handle periodic boundaries */
44347c6ae99SBarry Smith           colors[i1++] = l + nc * (SetInRange(i, m) % col);
44447c6ae99SBarry Smith         }
44547c6ae99SBarry Smith       }
44647c6ae99SBarry Smith       ncolors = nc + nc * (col - 1);
4479566063dSJacob Faibussowitsch       PetscCall(ISColoringCreate(comm, ncolors, nc * gnx, colors, PETSC_OWN_POINTER, &dd->ghostedcoloring));
4489566063dSJacob Faibussowitsch       PetscCall(ISColoringSetType(dd->ghostedcoloring, IS_COLORING_LOCAL));
44947c6ae99SBarry Smith     }
45047c6ae99SBarry Smith     *coloring = dd->ghostedcoloring;
45198921bdaSJacob Faibussowitsch   } else SETERRQ(PetscObjectComm((PetscObject)da), PETSC_ERR_ARG_WRONG, "Unknown ISColoringType %d", (int)ctype);
4529566063dSJacob Faibussowitsch   PetscCall(ISColoringReference(*coloring));
45347c6ae99SBarry Smith   PetscFunctionReturn(0);
45447c6ae99SBarry Smith }
45547c6ae99SBarry Smith 
4569371c9d4SSatish Balay PetscErrorCode DMCreateColoring_DA_2d_5pt_MPIAIJ(DM da, ISColoringType ctype, ISColoring *coloring) {
45747c6ae99SBarry Smith   PetscInt         xs, ys, nx, ny, i, j, ii, gxs, gys, gnx, gny, m, n, dim, s, k, nc;
45847c6ae99SBarry Smith   PetscInt         ncolors;
45947c6ae99SBarry Smith   MPI_Comm         comm;
460bff4a2f0SMatthew G. Knepley   DMBoundaryType   bx, by;
46147c6ae99SBarry Smith   ISColoringValue *colors;
46247c6ae99SBarry Smith   DM_DA           *dd = (DM_DA *)da->data;
46347c6ae99SBarry Smith 
46447c6ae99SBarry Smith   PetscFunctionBegin;
46547c6ae99SBarry Smith   /*
46647c6ae99SBarry Smith          nc - number of components per grid point
46747c6ae99SBarry Smith          col - number of colors needed in one direction for single component problem
46847c6ae99SBarry Smith 
46947c6ae99SBarry Smith   */
4709566063dSJacob Faibussowitsch   PetscCall(DMDAGetInfo(da, &dim, &m, &n, NULL, NULL, NULL, NULL, &nc, &s, &bx, &by, NULL, NULL));
4719566063dSJacob Faibussowitsch   PetscCall(DMDAGetCorners(da, &xs, &ys, NULL, &nx, &ny, NULL));
4729566063dSJacob Faibussowitsch   PetscCall(DMDAGetGhostCorners(da, &gxs, &gys, NULL, &gnx, &gny, NULL));
4739566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)da, &comm));
47447c6ae99SBarry Smith   /* create the coloring */
47547c6ae99SBarry Smith   if (ctype == IS_COLORING_GLOBAL) {
47647c6ae99SBarry Smith     if (!dd->localcoloring) {
4779566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(nc * nx * ny, &colors));
47847c6ae99SBarry Smith       ii = 0;
47947c6ae99SBarry Smith       for (j = ys; j < ys + ny; j++) {
48047c6ae99SBarry Smith         for (i = xs; i < xs + nx; i++) {
4819371c9d4SSatish Balay           for (k = 0; k < nc; k++) { colors[ii++] = k + nc * ((3 * j + i) % 5); }
48247c6ae99SBarry Smith         }
48347c6ae99SBarry Smith       }
48447c6ae99SBarry Smith       ncolors = 5 * nc;
4859566063dSJacob Faibussowitsch       PetscCall(ISColoringCreate(comm, ncolors, nc * nx * ny, colors, PETSC_OWN_POINTER, &dd->localcoloring));
48647c6ae99SBarry Smith     }
48747c6ae99SBarry Smith     *coloring = dd->localcoloring;
4885bdb020cSBarry Smith   } else if (ctype == IS_COLORING_LOCAL) {
48947c6ae99SBarry Smith     if (!dd->ghostedcoloring) {
4909566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(nc * gnx * gny, &colors));
49147c6ae99SBarry Smith       ii = 0;
49247c6ae99SBarry Smith       for (j = gys; j < gys + gny; j++) {
49347c6ae99SBarry Smith         for (i = gxs; i < gxs + gnx; i++) {
4949371c9d4SSatish Balay           for (k = 0; k < nc; k++) { colors[ii++] = k + nc * ((3 * SetInRange(j, n) + SetInRange(i, m)) % 5); }
49547c6ae99SBarry Smith         }
49647c6ae99SBarry Smith       }
49747c6ae99SBarry Smith       ncolors = 5 * nc;
4989566063dSJacob Faibussowitsch       PetscCall(ISColoringCreate(comm, ncolors, nc * gnx * gny, colors, PETSC_OWN_POINTER, &dd->ghostedcoloring));
4999566063dSJacob Faibussowitsch       PetscCall(ISColoringSetType(dd->ghostedcoloring, IS_COLORING_LOCAL));
50047c6ae99SBarry Smith     }
50147c6ae99SBarry Smith     *coloring = dd->ghostedcoloring;
50298921bdaSJacob Faibussowitsch   } else SETERRQ(PetscObjectComm((PetscObject)da), PETSC_ERR_ARG_WRONG, "Unknown ISColoringType %d", (int)ctype);
50347c6ae99SBarry Smith   PetscFunctionReturn(0);
50447c6ae99SBarry Smith }
50547c6ae99SBarry Smith 
50647c6ae99SBarry Smith /* =========================================================================== */
507e432b41dSStefano Zampini extern PetscErrorCode DMCreateMatrix_DA_1d_MPIAIJ(DM, Mat);
508ce308e1dSBarry Smith extern PetscErrorCode DMCreateMatrix_DA_1d_MPIAIJ_Fill(DM, Mat);
509e432b41dSStefano Zampini extern PetscErrorCode DMCreateMatrix_DA_1d_SeqAIJ_NoPreallocation(DM, Mat);
510e432b41dSStefano Zampini extern PetscErrorCode DMCreateMatrix_DA_2d_MPIAIJ(DM, Mat);
511950540a4SJed Brown extern PetscErrorCode DMCreateMatrix_DA_2d_MPIAIJ_Fill(DM, Mat);
512e432b41dSStefano Zampini extern PetscErrorCode DMCreateMatrix_DA_3d_MPIAIJ(DM, Mat);
513950540a4SJed Brown extern PetscErrorCode DMCreateMatrix_DA_3d_MPIAIJ_Fill(DM, Mat);
514950540a4SJed Brown extern PetscErrorCode DMCreateMatrix_DA_2d_MPIBAIJ(DM, Mat);
515950540a4SJed Brown extern PetscErrorCode DMCreateMatrix_DA_3d_MPIBAIJ(DM, Mat);
516950540a4SJed Brown extern PetscErrorCode DMCreateMatrix_DA_2d_MPISBAIJ(DM, Mat);
517950540a4SJed Brown extern PetscErrorCode DMCreateMatrix_DA_3d_MPISBAIJ(DM, Mat);
518d4002b98SHong Zhang extern PetscErrorCode DMCreateMatrix_DA_2d_MPISELL(DM, Mat);
519d4002b98SHong Zhang extern PetscErrorCode DMCreateMatrix_DA_3d_MPISELL(DM, Mat);
520e584696dSStefano Zampini extern PetscErrorCode DMCreateMatrix_DA_IS(DM, Mat);
52147c6ae99SBarry Smith 
5228bbdbebaSMatthew G Knepley /*@C
523c688c046SMatthew G Knepley    MatSetupDM - Sets the DMDA that is to be used by the HYPRE_StructMatrix PETSc matrix
52447c6ae99SBarry Smith 
525d083f849SBarry Smith    Logically Collective on mat
52647c6ae99SBarry Smith 
52747c6ae99SBarry Smith    Input Parameters:
52847c6ae99SBarry Smith +  mat - the matrix
52947c6ae99SBarry Smith -  da - the da
53047c6ae99SBarry Smith 
53147c6ae99SBarry Smith    Level: intermediate
53247c6ae99SBarry Smith 
53347c6ae99SBarry Smith @*/
5349371c9d4SSatish Balay PetscErrorCode MatSetupDM(Mat mat, DM da) {
53547c6ae99SBarry Smith   PetscFunctionBegin;
53647c6ae99SBarry Smith   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
537064a246eSJacob Faibussowitsch   PetscValidHeaderSpecificType(da, DM_CLASSID, 2, DMDA);
538cac4c232SBarry Smith   PetscTryMethod(mat, "MatSetupDM_C", (Mat, DM), (mat, da));
53947c6ae99SBarry Smith   PetscFunctionReturn(0);
54047c6ae99SBarry Smith }
54147c6ae99SBarry Smith 
5429371c9d4SSatish Balay PetscErrorCode MatView_MPI_DA(Mat A, PetscViewer viewer) {
5439a42bb27SBarry Smith   DM                da;
54447c6ae99SBarry Smith   const char       *prefix;
54547c6ae99SBarry Smith   Mat               Anatural;
54647c6ae99SBarry Smith   AO                ao;
54747c6ae99SBarry Smith   PetscInt          rstart, rend, *petsc, i;
54847c6ae99SBarry Smith   IS                is;
54947c6ae99SBarry Smith   MPI_Comm          comm;
55074388724SJed Brown   PetscViewerFormat format;
55147c6ae99SBarry Smith 
55247c6ae99SBarry Smith   PetscFunctionBegin;
55374388724SJed Brown   /* Check whether we are just printing info, in which case MatView() already viewed everything we wanted to view */
5549566063dSJacob Faibussowitsch   PetscCall(PetscViewerGetFormat(viewer, &format));
55574388724SJed Brown   if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) PetscFunctionReturn(0);
55674388724SJed Brown 
5579566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)A, &comm));
5589566063dSJacob Faibussowitsch   PetscCall(MatGetDM(A, &da));
5597a8be351SBarry Smith   PetscCheck(da, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Matrix not generated from a DMDA");
56047c6ae99SBarry Smith 
5619566063dSJacob Faibussowitsch   PetscCall(DMDAGetAO(da, &ao));
5629566063dSJacob Faibussowitsch   PetscCall(MatGetOwnershipRange(A, &rstart, &rend));
5639566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(rend - rstart, &petsc));
56447c6ae99SBarry Smith   for (i = rstart; i < rend; i++) petsc[i - rstart] = i;
5659566063dSJacob Faibussowitsch   PetscCall(AOApplicationToPetsc(ao, rend - rstart, petsc));
5669566063dSJacob Faibussowitsch   PetscCall(ISCreateGeneral(comm, rend - rstart, petsc, PETSC_OWN_POINTER, &is));
56747c6ae99SBarry Smith 
56847c6ae99SBarry Smith   /* call viewer on natural ordering */
5699566063dSJacob Faibussowitsch   PetscCall(MatCreateSubMatrix(A, is, is, MAT_INITIAL_MATRIX, &Anatural));
5709566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&is));
5719566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetOptionsPrefix((PetscObject)A, &prefix));
5729566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetOptionsPrefix((PetscObject)Anatural, prefix));
5739566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)Anatural, ((PetscObject)A)->name));
574f0ed2f47SStefano Zampini   ((PetscObject)Anatural)->donotPetscObjectPrintClassNamePrefixType = PETSC_TRUE;
5759566063dSJacob Faibussowitsch   PetscCall(MatView(Anatural, viewer));
576f0ed2f47SStefano Zampini   ((PetscObject)Anatural)->donotPetscObjectPrintClassNamePrefixType = PETSC_FALSE;
5779566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&Anatural));
57847c6ae99SBarry Smith   PetscFunctionReturn(0);
57947c6ae99SBarry Smith }
58047c6ae99SBarry Smith 
5819371c9d4SSatish Balay PetscErrorCode MatLoad_MPI_DA(Mat A, PetscViewer viewer) {
5829a42bb27SBarry Smith   DM       da;
58347c6ae99SBarry Smith   Mat      Anatural, Aapp;
58447c6ae99SBarry Smith   AO       ao;
585539c167fSBarry Smith   PetscInt rstart, rend, *app, i, m, n, M, N;
58647c6ae99SBarry Smith   IS       is;
58747c6ae99SBarry Smith   MPI_Comm comm;
58847c6ae99SBarry Smith 
58947c6ae99SBarry Smith   PetscFunctionBegin;
5909566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)A, &comm));
5919566063dSJacob Faibussowitsch   PetscCall(MatGetDM(A, &da));
5927a8be351SBarry Smith   PetscCheck(da, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Matrix not generated from a DMDA");
59347c6ae99SBarry Smith 
59447c6ae99SBarry Smith   /* Load the matrix in natural ordering */
5959566063dSJacob Faibussowitsch   PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &Anatural));
5969566063dSJacob Faibussowitsch   PetscCall(MatSetType(Anatural, ((PetscObject)A)->type_name));
5979566063dSJacob Faibussowitsch   PetscCall(MatGetSize(A, &M, &N));
5989566063dSJacob Faibussowitsch   PetscCall(MatGetLocalSize(A, &m, &n));
5999566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(Anatural, m, n, M, N));
6009566063dSJacob Faibussowitsch   PetscCall(MatLoad(Anatural, viewer));
60147c6ae99SBarry Smith 
60247c6ae99SBarry Smith   /* Map natural ordering to application ordering and create IS */
6039566063dSJacob Faibussowitsch   PetscCall(DMDAGetAO(da, &ao));
6049566063dSJacob Faibussowitsch   PetscCall(MatGetOwnershipRange(Anatural, &rstart, &rend));
6059566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(rend - rstart, &app));
60647c6ae99SBarry Smith   for (i = rstart; i < rend; i++) app[i - rstart] = i;
6079566063dSJacob Faibussowitsch   PetscCall(AOPetscToApplication(ao, rend - rstart, app));
6089566063dSJacob Faibussowitsch   PetscCall(ISCreateGeneral(comm, rend - rstart, app, PETSC_OWN_POINTER, &is));
60947c6ae99SBarry Smith 
61047c6ae99SBarry Smith   /* Do permutation and replace header */
6119566063dSJacob Faibussowitsch   PetscCall(MatCreateSubMatrix(Anatural, is, is, MAT_INITIAL_MATRIX, &Aapp));
6129566063dSJacob Faibussowitsch   PetscCall(MatHeaderReplace(A, &Aapp));
6139566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&is));
6149566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&Anatural));
61547c6ae99SBarry Smith   PetscFunctionReturn(0);
61647c6ae99SBarry Smith }
61747c6ae99SBarry Smith 
6189371c9d4SSatish Balay PetscErrorCode DMCreateMatrix_DA(DM da, Mat *J) {
61947c6ae99SBarry Smith   PetscInt dim, dof, nx, ny, nz, dims[3], starts[3], M, N, P;
62047c6ae99SBarry Smith   Mat      A;
62147c6ae99SBarry Smith   MPI_Comm comm;
62219fd82e9SBarry Smith   MatType  Atype;
623e584696dSStefano Zampini   void (*aij)(void) = NULL, (*baij)(void) = NULL, (*sbaij)(void) = NULL, (*sell)(void) = NULL, (*is)(void) = NULL;
624b412c318SBarry Smith   MatType     mtype;
62547c6ae99SBarry Smith   PetscMPIInt size;
62647c6ae99SBarry Smith   DM_DA      *dd = (DM_DA *)da->data;
62747c6ae99SBarry Smith 
62847c6ae99SBarry Smith   PetscFunctionBegin;
6299566063dSJacob Faibussowitsch   PetscCall(MatInitializePackage());
630b412c318SBarry Smith   mtype = da->mattype;
63147c6ae99SBarry Smith 
63247c6ae99SBarry Smith   /*
63347c6ae99SBarry Smith                                   m
63447c6ae99SBarry Smith           ------------------------------------------------------
63547c6ae99SBarry Smith          |                                                     |
63647c6ae99SBarry Smith          |                                                     |
63747c6ae99SBarry Smith          |               ----------------------                |
63847c6ae99SBarry Smith          |               |                    |                |
63947c6ae99SBarry Smith       n  |           ny  |                    |                |
64047c6ae99SBarry Smith          |               |                    |                |
64147c6ae99SBarry Smith          |               .---------------------                |
64247c6ae99SBarry Smith          |             (xs,ys)     nx                          |
64347c6ae99SBarry Smith          |            .                                        |
64447c6ae99SBarry Smith          |         (gxs,gys)                                   |
64547c6ae99SBarry Smith          |                                                     |
64647c6ae99SBarry Smith           -----------------------------------------------------
64747c6ae99SBarry Smith   */
64847c6ae99SBarry Smith 
64947c6ae99SBarry Smith   /*
65047c6ae99SBarry Smith          nc - number of components per grid point
65147c6ae99SBarry Smith          col - number of colors needed in one direction for single component problem
65247c6ae99SBarry Smith 
65347c6ae99SBarry Smith   */
654e30e807fSPeter Brune   M   = dd->M;
655e30e807fSPeter Brune   N   = dd->N;
656e30e807fSPeter Brune   P   = dd->P;
657c73cfb54SMatthew G. Knepley   dim = da->dim;
658e30e807fSPeter Brune   dof = dd->w;
6599566063dSJacob Faibussowitsch   /* PetscCall(DMDAGetInfo(da,&dim,&M,&N,&P,NULL,NULL,NULL,&dof,NULL,NULL,NULL,NULL,NULL)); */
6609566063dSJacob Faibussowitsch   PetscCall(DMDAGetCorners(da, NULL, NULL, NULL, &nx, &ny, &nz));
6619566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)da, &comm));
6629566063dSJacob Faibussowitsch   PetscCall(MatCreate(comm, &A));
6639566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(A, dof * nx * ny * nz, dof * nx * ny * nz, dof * M * N * P, dof * M * N * P));
6649566063dSJacob Faibussowitsch   PetscCall(MatSetType(A, mtype));
6659566063dSJacob Faibussowitsch   PetscCall(MatSetFromOptions(A));
66674427ab1SRichard Tran Mills   if (dof * nx * ny * nz < da->bind_below) {
6679566063dSJacob Faibussowitsch     PetscCall(MatSetBindingPropagates(A, PETSC_TRUE));
6689566063dSJacob Faibussowitsch     PetscCall(MatBindToCPU(A, PETSC_TRUE));
66974427ab1SRichard Tran Mills   }
6709566063dSJacob Faibussowitsch   PetscCall(MatSetDM(A, da));
6711baa6e33SBarry Smith   if (da->structure_only) PetscCall(MatSetOption(A, MAT_STRUCTURE_ONLY, PETSC_TRUE));
6729566063dSJacob Faibussowitsch   PetscCall(MatGetType(A, &Atype));
67347c6ae99SBarry Smith   /*
674aa219208SBarry Smith      We do not provide a getmatrix function in the DMDA operations because
675aa219208SBarry Smith    the basic DMDA does not know about matrices. We think of DMDA as being more
67647c6ae99SBarry Smith    more low-level than matrices. This is kind of cheating but, cause sometimes
677aa219208SBarry Smith    we think of DMDA has higher level than matrices.
67847c6ae99SBarry Smith 
67947c6ae99SBarry Smith      We could switch based on Atype (or mtype), but we do not since the
680844bd0d7SStefano Zampini    specialized setting routines depend only on the particular preallocation
68147c6ae99SBarry Smith    details of the matrix, not the type itself.
68247c6ae99SBarry Smith   */
6839566063dSJacob Faibussowitsch   PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatMPIAIJSetPreallocation_C", &aij));
684*48a46eb9SPierre Jolivet   if (!aij) PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatSeqAIJSetPreallocation_C", &aij));
68547c6ae99SBarry Smith   if (!aij) {
6869566063dSJacob Faibussowitsch     PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatMPIBAIJSetPreallocation_C", &baij));
687*48a46eb9SPierre Jolivet     if (!baij) PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatSeqBAIJSetPreallocation_C", &baij));
68847c6ae99SBarry Smith     if (!baij) {
6899566063dSJacob Faibussowitsch       PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatMPISBAIJSetPreallocation_C", &sbaij));
690*48a46eb9SPierre Jolivet       if (!sbaij) PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatSeqSBAIJSetPreallocation_C", &sbaij));
6915e26d47bSHong Zhang       if (!sbaij) {
6929566063dSJacob Faibussowitsch         PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatMPISELLSetPreallocation_C", &sell));
693*48a46eb9SPierre Jolivet         if (!sell) PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatSeqSELLSetPreallocation_C", &sell));
6945e26d47bSHong Zhang       }
695*48a46eb9SPierre Jolivet       if (!sell) PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatISSetPreallocation_C", &is));
69647c6ae99SBarry Smith     }
69747c6ae99SBarry Smith   }
69847c6ae99SBarry Smith   if (aij) {
69947c6ae99SBarry Smith     if (dim == 1) {
700ce308e1dSBarry Smith       if (dd->ofill) {
7019566063dSJacob Faibussowitsch         PetscCall(DMCreateMatrix_DA_1d_MPIAIJ_Fill(da, A));
702ce308e1dSBarry Smith       } else {
70319b08ed1SBarry Smith         DMBoundaryType bx;
70419b08ed1SBarry Smith         PetscMPIInt    size;
7059566063dSJacob Faibussowitsch         PetscCall(DMDAGetInfo(da, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &bx, NULL, NULL, NULL));
7069566063dSJacob Faibussowitsch         PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)da), &size));
70719b08ed1SBarry Smith         if (size == 1 && bx == DM_BOUNDARY_NONE) {
7089566063dSJacob Faibussowitsch           PetscCall(DMCreateMatrix_DA_1d_SeqAIJ_NoPreallocation(da, A));
70919b08ed1SBarry Smith         } else {
7109566063dSJacob Faibussowitsch           PetscCall(DMCreateMatrix_DA_1d_MPIAIJ(da, A));
711ce308e1dSBarry Smith         }
71219b08ed1SBarry Smith       }
71347c6ae99SBarry Smith     } else if (dim == 2) {
71447c6ae99SBarry Smith       if (dd->ofill) {
7159566063dSJacob Faibussowitsch         PetscCall(DMCreateMatrix_DA_2d_MPIAIJ_Fill(da, A));
71647c6ae99SBarry Smith       } else {
7179566063dSJacob Faibussowitsch         PetscCall(DMCreateMatrix_DA_2d_MPIAIJ(da, A));
71847c6ae99SBarry Smith       }
71947c6ae99SBarry Smith     } else if (dim == 3) {
72047c6ae99SBarry Smith       if (dd->ofill) {
7219566063dSJacob Faibussowitsch         PetscCall(DMCreateMatrix_DA_3d_MPIAIJ_Fill(da, A));
72247c6ae99SBarry Smith       } else {
7239566063dSJacob Faibussowitsch         PetscCall(DMCreateMatrix_DA_3d_MPIAIJ(da, A));
72447c6ae99SBarry Smith       }
72547c6ae99SBarry Smith     }
72647c6ae99SBarry Smith   } else if (baij) {
72747c6ae99SBarry Smith     if (dim == 2) {
7289566063dSJacob Faibussowitsch       PetscCall(DMCreateMatrix_DA_2d_MPIBAIJ(da, A));
72947c6ae99SBarry Smith     } else if (dim == 3) {
7309566063dSJacob Faibussowitsch       PetscCall(DMCreateMatrix_DA_3d_MPIBAIJ(da, A));
73163a3b9bcSJacob 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);
73247c6ae99SBarry Smith   } else if (sbaij) {
73347c6ae99SBarry Smith     if (dim == 2) {
7349566063dSJacob Faibussowitsch       PetscCall(DMCreateMatrix_DA_2d_MPISBAIJ(da, A));
73547c6ae99SBarry Smith     } else if (dim == 3) {
7369566063dSJacob Faibussowitsch       PetscCall(DMCreateMatrix_DA_3d_MPISBAIJ(da, A));
73763a3b9bcSJacob 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);
738d4002b98SHong Zhang   } else if (sell) {
7395e26d47bSHong Zhang     if (dim == 2) {
7409566063dSJacob Faibussowitsch       PetscCall(DMCreateMatrix_DA_2d_MPISELL(da, A));
741711261dbSHong Zhang     } else if (dim == 3) {
7429566063dSJacob Faibussowitsch       PetscCall(DMCreateMatrix_DA_3d_MPISELL(da, A));
74363a3b9bcSJacob 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);
744e584696dSStefano Zampini   } else if (is) {
7459566063dSJacob Faibussowitsch     PetscCall(DMCreateMatrix_DA_IS(da, A));
746869776cdSLisandro Dalcin   } else {
74745b6f7e9SBarry Smith     ISLocalToGlobalMapping ltog;
748e584696dSStefano Zampini 
7499566063dSJacob Faibussowitsch     PetscCall(MatSetBlockSize(A, dof));
7509566063dSJacob Faibussowitsch     PetscCall(MatSetUp(A));
7519566063dSJacob Faibussowitsch     PetscCall(DMGetLocalToGlobalMapping(da, &ltog));
7529566063dSJacob Faibussowitsch     PetscCall(MatSetLocalToGlobalMapping(A, ltog, ltog));
75347c6ae99SBarry Smith   }
7549566063dSJacob Faibussowitsch   PetscCall(DMDAGetGhostCorners(da, &starts[0], &starts[1], &starts[2], &dims[0], &dims[1], &dims[2]));
7559566063dSJacob Faibussowitsch   PetscCall(MatSetStencil(A, dim, dims, starts, dof));
7569566063dSJacob Faibussowitsch   PetscCall(MatSetDM(A, da));
7579566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(comm, &size));
75847c6ae99SBarry Smith   if (size > 1) {
75947c6ae99SBarry Smith     /* change viewer to display matrix in natural ordering */
7609566063dSJacob Faibussowitsch     PetscCall(MatSetOperation(A, MATOP_VIEW, (void (*)(void))MatView_MPI_DA));
7619566063dSJacob Faibussowitsch     PetscCall(MatSetOperation(A, MATOP_LOAD, (void (*)(void))MatLoad_MPI_DA));
76247c6ae99SBarry Smith   }
76347c6ae99SBarry Smith   *J = A;
76447c6ae99SBarry Smith   PetscFunctionReturn(0);
76547c6ae99SBarry Smith }
76647c6ae99SBarry Smith 
76747c6ae99SBarry Smith /* ---------------------------------------------------------------------------------*/
768844bd0d7SStefano Zampini PETSC_EXTERN PetscErrorCode MatISSetPreallocation_IS(Mat, PetscInt, const PetscInt[], PetscInt, const PetscInt[]);
769844bd0d7SStefano Zampini 
7709371c9d4SSatish Balay PetscErrorCode DMCreateMatrix_DA_IS(DM dm, Mat J) {
771e584696dSStefano Zampini   DM_DA                 *da = (DM_DA *)dm->data;
772e432b41dSStefano Zampini   Mat                    lJ, P;
773e584696dSStefano Zampini   ISLocalToGlobalMapping ltog;
774e432b41dSStefano Zampini   IS                     is;
775e432b41dSStefano Zampini   PetscBT                bt;
77605339c03SStefano Zampini   const PetscInt        *e_loc, *idx;
777e432b41dSStefano Zampini   PetscInt               i, nel, nen, nv, dof, *gidx, n, N;
778e584696dSStefano Zampini 
779e584696dSStefano Zampini   /* The l2g map of DMDA has all ghosted nodes, and e_loc is a subset of all the local nodes (including the ghosted)
780e432b41dSStefano Zampini      We need to filter out the local indices that are not represented through the DMDAGetElements decomposition */
781e584696dSStefano Zampini   PetscFunctionBegin;
782e584696dSStefano Zampini   dof = da->w;
7839566063dSJacob Faibussowitsch   PetscCall(MatSetBlockSize(J, dof));
7849566063dSJacob Faibussowitsch   PetscCall(DMGetLocalToGlobalMapping(dm, &ltog));
785e432b41dSStefano Zampini 
786e432b41dSStefano Zampini   /* flag local elements indices in local DMDA numbering */
7879566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingGetSize(ltog, &nv));
7889566063dSJacob Faibussowitsch   PetscCall(PetscBTCreate(nv / dof, &bt));
7899566063dSJacob Faibussowitsch   PetscCall(DMDAGetElements(dm, &nel, &nen, &e_loc)); /* this will throw an error if the stencil type is not DMDA_STENCIL_BOX */
7909566063dSJacob Faibussowitsch   for (i = 0; i < nel * nen; i++) PetscCall(PetscBTSet(bt, e_loc[i]));
791e432b41dSStefano Zampini 
792e432b41dSStefano Zampini   /* filter out (set to -1) the global indices not used by the local elements */
7939566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(nv / dof, &gidx));
7949566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingGetBlockIndices(ltog, &idx));
7959566063dSJacob Faibussowitsch   PetscCall(PetscArraycpy(gidx, idx, nv / dof));
7969566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingRestoreBlockIndices(ltog, &idx));
7979371c9d4SSatish Balay   for (i = 0; i < nv / dof; i++)
7989371c9d4SSatish Balay     if (!PetscBTLookup(bt, i)) gidx[i] = -1;
7999566063dSJacob Faibussowitsch   PetscCall(PetscBTDestroy(&bt));
8009566063dSJacob Faibussowitsch   PetscCall(ISCreateBlock(PetscObjectComm((PetscObject)dm), dof, nv / dof, gidx, PETSC_OWN_POINTER, &is));
8019566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingCreateIS(is, &ltog));
8029566063dSJacob Faibussowitsch   PetscCall(MatSetLocalToGlobalMapping(J, ltog, ltog));
8039566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingDestroy(&ltog));
8049566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&is));
80505339c03SStefano Zampini 
806e432b41dSStefano Zampini   /* Preallocation */
807e306f867SJed Brown   if (dm->prealloc_skip) {
8089566063dSJacob Faibussowitsch     PetscCall(MatSetUp(J));
809e306f867SJed Brown   } else {
8109566063dSJacob Faibussowitsch     PetscCall(MatISGetLocalMat(J, &lJ));
8119566063dSJacob Faibussowitsch     PetscCall(MatGetLocalToGlobalMapping(lJ, &ltog, NULL));
8129566063dSJacob Faibussowitsch     PetscCall(MatCreate(PetscObjectComm((PetscObject)lJ), &P));
8139566063dSJacob Faibussowitsch     PetscCall(MatSetType(P, MATPREALLOCATOR));
8149566063dSJacob Faibussowitsch     PetscCall(MatSetLocalToGlobalMapping(P, ltog, ltog));
8159566063dSJacob Faibussowitsch     PetscCall(MatGetSize(lJ, &N, NULL));
8169566063dSJacob Faibussowitsch     PetscCall(MatGetLocalSize(lJ, &n, NULL));
8179566063dSJacob Faibussowitsch     PetscCall(MatSetSizes(P, n, n, N, N));
8189566063dSJacob Faibussowitsch     PetscCall(MatSetBlockSize(P, dof));
8199566063dSJacob Faibussowitsch     PetscCall(MatSetUp(P));
820*48a46eb9SPierre Jolivet     for (i = 0; i < nel; i++) PetscCall(MatSetValuesBlockedLocal(P, nen, e_loc + i * nen, nen, e_loc + i * nen, NULL, INSERT_VALUES));
8219566063dSJacob Faibussowitsch     PetscCall(MatPreallocatorPreallocate(P, (PetscBool)!da->prealloc_only, lJ));
8229566063dSJacob Faibussowitsch     PetscCall(MatISRestoreLocalMat(J, &lJ));
8239566063dSJacob Faibussowitsch     PetscCall(DMDARestoreElements(dm, &nel, &nen, &e_loc));
8249566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&P));
825e432b41dSStefano Zampini 
8269566063dSJacob Faibussowitsch     PetscCall(MatAssemblyBegin(J, MAT_FINAL_ASSEMBLY));
8279566063dSJacob Faibussowitsch     PetscCall(MatAssemblyEnd(J, MAT_FINAL_ASSEMBLY));
828e306f867SJed Brown   }
829e584696dSStefano Zampini   PetscFunctionReturn(0);
830e584696dSStefano Zampini }
831e584696dSStefano Zampini 
8329371c9d4SSatish Balay PetscErrorCode DMCreateMatrix_DA_2d_MPISELL(DM da, Mat J) {
8335e26d47bSHong 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;
8345e26d47bSHong Zhang   PetscInt               lstart, lend, pstart, pend, *dnz, *onz;
8355e26d47bSHong Zhang   MPI_Comm               comm;
8365e26d47bSHong Zhang   PetscScalar           *values;
8375e26d47bSHong Zhang   DMBoundaryType         bx, by;
8385e26d47bSHong Zhang   ISLocalToGlobalMapping ltog;
8395e26d47bSHong Zhang   DMDAStencilType        st;
8405e26d47bSHong Zhang 
8415e26d47bSHong Zhang   PetscFunctionBegin;
8425e26d47bSHong Zhang   /*
8435e26d47bSHong Zhang          nc - number of components per grid point
8445e26d47bSHong Zhang          col - number of colors needed in one direction for single component problem
8455e26d47bSHong Zhang 
8465e26d47bSHong Zhang   */
8479566063dSJacob Faibussowitsch   PetscCall(DMDAGetInfo(da, &dim, &m, &n, NULL, NULL, NULL, NULL, &nc, &s, &bx, &by, NULL, &st));
8485e26d47bSHong Zhang   col = 2 * s + 1;
8499566063dSJacob Faibussowitsch   PetscCall(DMDAGetCorners(da, &xs, &ys, NULL, &nx, &ny, NULL));
8509566063dSJacob Faibussowitsch   PetscCall(DMDAGetGhostCorners(da, &gxs, &gys, NULL, &gnx, &gny, NULL));
8519566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)da, &comm));
8525e26d47bSHong Zhang 
8539566063dSJacob Faibussowitsch   PetscCall(PetscMalloc2(nc, &rows, col * col * nc * nc, &cols));
8549566063dSJacob Faibussowitsch   PetscCall(DMGetLocalToGlobalMapping(da, &ltog));
8555e26d47bSHong Zhang 
8569566063dSJacob Faibussowitsch   PetscCall(MatSetBlockSize(J, nc));
8575e26d47bSHong Zhang   /* determine the matrix preallocation information */
858d0609cedSBarry Smith   MatPreallocateBegin(comm, nc * nx * ny, nc * nx * ny, dnz, onz);
8595e26d47bSHong Zhang   for (i = xs; i < xs + nx; i++) {
8605e26d47bSHong Zhang     pstart = (bx == DM_BOUNDARY_PERIODIC) ? -s : (PetscMax(-s, -i));
8615e26d47bSHong Zhang     pend   = (bx == DM_BOUNDARY_PERIODIC) ? s : (PetscMin(s, m - i - 1));
8625e26d47bSHong Zhang 
8635e26d47bSHong Zhang     for (j = ys; j < ys + ny; j++) {
8645e26d47bSHong Zhang       slot = i - gxs + gnx * (j - gys);
8655e26d47bSHong Zhang 
8665e26d47bSHong Zhang       lstart = (by == DM_BOUNDARY_PERIODIC) ? -s : (PetscMax(-s, -j));
8675e26d47bSHong Zhang       lend   = (by == DM_BOUNDARY_PERIODIC) ? s : (PetscMin(s, n - j - 1));
8685e26d47bSHong Zhang 
8695e26d47bSHong Zhang       cnt = 0;
8705e26d47bSHong Zhang       for (k = 0; k < nc; k++) {
8715e26d47bSHong Zhang         for (l = lstart; l < lend + 1; l++) {
8725e26d47bSHong Zhang           for (p = pstart; p < pend + 1; p++) {
8735e26d47bSHong Zhang             if ((st == DMDA_STENCIL_BOX) || (!l || !p)) { /* entries on star have either l = 0 or p = 0 */
8745e26d47bSHong Zhang               cols[cnt++] = k + nc * (slot + gnx * l + p);
8755e26d47bSHong Zhang             }
8765e26d47bSHong Zhang           }
8775e26d47bSHong Zhang         }
8785e26d47bSHong Zhang         rows[k] = k + nc * (slot);
8795e26d47bSHong Zhang       }
8809566063dSJacob Faibussowitsch       PetscCall(MatPreallocateSetLocal(ltog, nc, rows, ltog, cnt, cols, dnz, onz));
8815e26d47bSHong Zhang     }
8825e26d47bSHong Zhang   }
8839566063dSJacob Faibussowitsch   PetscCall(MatSetBlockSize(J, nc));
8849566063dSJacob Faibussowitsch   PetscCall(MatSeqSELLSetPreallocation(J, 0, dnz));
8859566063dSJacob Faibussowitsch   PetscCall(MatMPISELLSetPreallocation(J, 0, dnz, 0, onz));
886d0609cedSBarry Smith   MatPreallocateEnd(dnz, onz);
8875e26d47bSHong Zhang 
8889566063dSJacob Faibussowitsch   PetscCall(MatSetLocalToGlobalMapping(J, ltog, ltog));
8895e26d47bSHong Zhang 
8905e26d47bSHong Zhang   /*
8915e26d47bSHong Zhang     For each node in the grid: we get the neighbors in the local (on processor ordering
8925e26d47bSHong Zhang     that includes the ghost points) then MatSetValuesLocal() maps those indices to the global
8935e26d47bSHong Zhang     PETSc ordering.
8945e26d47bSHong Zhang   */
8955e26d47bSHong Zhang   if (!da->prealloc_only) {
8969566063dSJacob Faibussowitsch     PetscCall(PetscCalloc1(col * col * nc * nc, &values));
8975e26d47bSHong Zhang     for (i = xs; i < xs + nx; i++) {
8985e26d47bSHong Zhang       pstart = (bx == DM_BOUNDARY_PERIODIC) ? -s : (PetscMax(-s, -i));
8995e26d47bSHong Zhang       pend   = (bx == DM_BOUNDARY_PERIODIC) ? s : (PetscMin(s, m - i - 1));
9005e26d47bSHong Zhang 
9015e26d47bSHong Zhang       for (j = ys; j < ys + ny; j++) {
9025e26d47bSHong Zhang         slot = i - gxs + gnx * (j - gys);
9035e26d47bSHong Zhang 
9045e26d47bSHong Zhang         lstart = (by == DM_BOUNDARY_PERIODIC) ? -s : (PetscMax(-s, -j));
9055e26d47bSHong Zhang         lend   = (by == DM_BOUNDARY_PERIODIC) ? s : (PetscMin(s, n - j - 1));
9065e26d47bSHong Zhang 
9075e26d47bSHong Zhang         cnt = 0;
9085e26d47bSHong Zhang         for (k = 0; k < nc; k++) {
9095e26d47bSHong Zhang           for (l = lstart; l < lend + 1; l++) {
9105e26d47bSHong Zhang             for (p = pstart; p < pend + 1; p++) {
9115e26d47bSHong Zhang               if ((st == DMDA_STENCIL_BOX) || (!l || !p)) { /* entries on star have either l = 0 or p = 0 */
9125e26d47bSHong Zhang                 cols[cnt++] = k + nc * (slot + gnx * l + p);
9135e26d47bSHong Zhang               }
9145e26d47bSHong Zhang             }
9155e26d47bSHong Zhang           }
9165e26d47bSHong Zhang           rows[k] = k + nc * (slot);
9175e26d47bSHong Zhang         }
9189566063dSJacob Faibussowitsch         PetscCall(MatSetValuesLocal(J, nc, rows, cnt, cols, values, INSERT_VALUES));
9195e26d47bSHong Zhang       }
9205e26d47bSHong Zhang     }
9219566063dSJacob Faibussowitsch     PetscCall(PetscFree(values));
922e7e92044SBarry Smith     /* do not copy values to GPU since they are all zero and not yet needed there */
9239566063dSJacob Faibussowitsch     PetscCall(MatBindToCPU(J, PETSC_TRUE));
9249566063dSJacob Faibussowitsch     PetscCall(MatAssemblyBegin(J, MAT_FINAL_ASSEMBLY));
9259566063dSJacob Faibussowitsch     PetscCall(MatAssemblyEnd(J, MAT_FINAL_ASSEMBLY));
9269566063dSJacob Faibussowitsch     PetscCall(MatBindToCPU(J, PETSC_FALSE));
9279566063dSJacob Faibussowitsch     PetscCall(MatSetOption(J, MAT_NEW_NONZERO_LOCATION_ERR, PETSC_TRUE));
9285e26d47bSHong Zhang   }
9299566063dSJacob Faibussowitsch   PetscCall(PetscFree2(rows, cols));
9305e26d47bSHong Zhang   PetscFunctionReturn(0);
9315e26d47bSHong Zhang }
9325e26d47bSHong Zhang 
9339371c9d4SSatish Balay PetscErrorCode DMCreateMatrix_DA_3d_MPISELL(DM da, Mat J) {
934711261dbSHong Zhang   PetscInt               xs, ys, nx, ny, i, j, slot, gxs, gys, gnx, gny;
935711261dbSHong Zhang   PetscInt               m, n, dim, s, *cols = NULL, k, nc, *rows = NULL, col, cnt, l, p, *dnz = NULL, *onz = NULL;
936711261dbSHong Zhang   PetscInt               istart, iend, jstart, jend, kstart, kend, zs, nz, gzs, gnz, ii, jj, kk, M, N, P;
937711261dbSHong Zhang   MPI_Comm               comm;
938711261dbSHong Zhang   PetscScalar           *values;
939711261dbSHong Zhang   DMBoundaryType         bx, by, bz;
940711261dbSHong Zhang   ISLocalToGlobalMapping ltog;
941711261dbSHong Zhang   DMDAStencilType        st;
942711261dbSHong Zhang 
943711261dbSHong Zhang   PetscFunctionBegin;
944711261dbSHong Zhang   /*
945711261dbSHong Zhang          nc - number of components per grid point
946711261dbSHong Zhang          col - number of colors needed in one direction for single component problem
947711261dbSHong Zhang 
948711261dbSHong Zhang   */
9499566063dSJacob Faibussowitsch   PetscCall(DMDAGetInfo(da, &dim, &m, &n, &p, &M, &N, &P, &nc, &s, &bx, &by, &bz, &st));
950711261dbSHong Zhang   col = 2 * s + 1;
9519566063dSJacob Faibussowitsch   PetscCall(DMDAGetCorners(da, &xs, &ys, &zs, &nx, &ny, &nz));
9529566063dSJacob Faibussowitsch   PetscCall(DMDAGetGhostCorners(da, &gxs, &gys, &gzs, &gnx, &gny, &gnz));
9539566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)da, &comm));
954711261dbSHong Zhang 
9559566063dSJacob Faibussowitsch   PetscCall(PetscMalloc2(nc, &rows, col * col * col * nc * nc, &cols));
9569566063dSJacob Faibussowitsch   PetscCall(DMGetLocalToGlobalMapping(da, &ltog));
957711261dbSHong Zhang 
9589566063dSJacob Faibussowitsch   PetscCall(MatSetBlockSize(J, nc));
959711261dbSHong Zhang   /* determine the matrix preallocation information */
960d0609cedSBarry Smith   MatPreallocateBegin(comm, nc * nx * ny * nz, nc * nx * ny * nz, dnz, onz);
961711261dbSHong Zhang   for (i = xs; i < xs + nx; i++) {
962711261dbSHong Zhang     istart = (bx == DM_BOUNDARY_PERIODIC) ? -s : (PetscMax(-s, -i));
963711261dbSHong Zhang     iend   = (bx == DM_BOUNDARY_PERIODIC) ? s : (PetscMin(s, m - i - 1));
964711261dbSHong Zhang     for (j = ys; j < ys + ny; j++) {
965711261dbSHong Zhang       jstart = (by == DM_BOUNDARY_PERIODIC) ? -s : (PetscMax(-s, -j));
966711261dbSHong Zhang       jend   = (by == DM_BOUNDARY_PERIODIC) ? s : (PetscMin(s, n - j - 1));
967711261dbSHong Zhang       for (k = zs; k < zs + nz; k++) {
968711261dbSHong Zhang         kstart = (bz == DM_BOUNDARY_PERIODIC) ? -s : (PetscMax(-s, -k));
969711261dbSHong Zhang         kend   = (bz == DM_BOUNDARY_PERIODIC) ? s : (PetscMin(s, p - k - 1));
970711261dbSHong Zhang 
971711261dbSHong Zhang         slot = i - gxs + gnx * (j - gys) + gnx * gny * (k - gzs);
972711261dbSHong Zhang 
973711261dbSHong Zhang         cnt = 0;
974711261dbSHong Zhang         for (l = 0; l < nc; l++) {
975711261dbSHong Zhang           for (ii = istart; ii < iend + 1; ii++) {
976711261dbSHong Zhang             for (jj = jstart; jj < jend + 1; jj++) {
977711261dbSHong Zhang               for (kk = kstart; kk < kend + 1; kk++) {
978711261dbSHong Zhang                 if ((st == DMDA_STENCIL_BOX) || ((!ii && !jj) || (!jj && !kk) || (!ii && !kk))) { /* entries on star*/
979711261dbSHong Zhang                   cols[cnt++] = l + nc * (slot + ii + gnx * jj + gnx * gny * kk);
980711261dbSHong Zhang                 }
981711261dbSHong Zhang               }
982711261dbSHong Zhang             }
983711261dbSHong Zhang           }
984711261dbSHong Zhang           rows[l] = l + nc * (slot);
985711261dbSHong Zhang         }
9869566063dSJacob Faibussowitsch         PetscCall(MatPreallocateSetLocal(ltog, nc, rows, ltog, cnt, cols, dnz, onz));
987711261dbSHong Zhang       }
988711261dbSHong Zhang     }
989711261dbSHong Zhang   }
9909566063dSJacob Faibussowitsch   PetscCall(MatSetBlockSize(J, nc));
9919566063dSJacob Faibussowitsch   PetscCall(MatSeqSELLSetPreallocation(J, 0, dnz));
9929566063dSJacob Faibussowitsch   PetscCall(MatMPISELLSetPreallocation(J, 0, dnz, 0, onz));
993d0609cedSBarry Smith   MatPreallocateEnd(dnz, onz);
9949566063dSJacob Faibussowitsch   PetscCall(MatSetLocalToGlobalMapping(J, ltog, ltog));
995711261dbSHong Zhang 
996711261dbSHong Zhang   /*
997711261dbSHong Zhang     For each node in the grid: we get the neighbors in the local (on processor ordering
998711261dbSHong Zhang     that includes the ghost points) then MatSetValuesLocal() maps those indices to the global
999711261dbSHong Zhang     PETSc ordering.
1000711261dbSHong Zhang   */
1001711261dbSHong Zhang   if (!da->prealloc_only) {
10029566063dSJacob Faibussowitsch     PetscCall(PetscCalloc1(col * col * col * nc * nc * nc, &values));
1003711261dbSHong Zhang     for (i = xs; i < xs + nx; i++) {
1004711261dbSHong Zhang       istart = (bx == DM_BOUNDARY_PERIODIC) ? -s : (PetscMax(-s, -i));
1005711261dbSHong Zhang       iend   = (bx == DM_BOUNDARY_PERIODIC) ? s : (PetscMin(s, m - i - 1));
1006711261dbSHong Zhang       for (j = ys; j < ys + ny; j++) {
1007711261dbSHong Zhang         jstart = (by == DM_BOUNDARY_PERIODIC) ? -s : (PetscMax(-s, -j));
1008711261dbSHong Zhang         jend   = (by == DM_BOUNDARY_PERIODIC) ? s : (PetscMin(s, n - j - 1));
1009711261dbSHong Zhang         for (k = zs; k < zs + nz; k++) {
1010711261dbSHong Zhang           kstart = (bz == DM_BOUNDARY_PERIODIC) ? -s : (PetscMax(-s, -k));
1011711261dbSHong Zhang           kend   = (bz == DM_BOUNDARY_PERIODIC) ? s : (PetscMin(s, p - k - 1));
1012711261dbSHong Zhang 
1013711261dbSHong Zhang           slot = i - gxs + gnx * (j - gys) + gnx * gny * (k - gzs);
1014711261dbSHong Zhang 
1015711261dbSHong Zhang           cnt = 0;
1016711261dbSHong Zhang           for (l = 0; l < nc; l++) {
1017711261dbSHong Zhang             for (ii = istart; ii < iend + 1; ii++) {
1018711261dbSHong Zhang               for (jj = jstart; jj < jend + 1; jj++) {
1019711261dbSHong Zhang                 for (kk = kstart; kk < kend + 1; kk++) {
1020711261dbSHong Zhang                   if ((st == DMDA_STENCIL_BOX) || ((!ii && !jj) || (!jj && !kk) || (!ii && !kk))) { /* entries on star*/
1021711261dbSHong Zhang                     cols[cnt++] = l + nc * (slot + ii + gnx * jj + gnx * gny * kk);
1022711261dbSHong Zhang                   }
1023711261dbSHong Zhang                 }
1024711261dbSHong Zhang               }
1025711261dbSHong Zhang             }
1026711261dbSHong Zhang             rows[l] = l + nc * (slot);
1027711261dbSHong Zhang           }
10289566063dSJacob Faibussowitsch           PetscCall(MatSetValuesLocal(J, nc, rows, cnt, cols, values, INSERT_VALUES));
1029711261dbSHong Zhang         }
1030711261dbSHong Zhang       }
1031711261dbSHong Zhang     }
10329566063dSJacob Faibussowitsch     PetscCall(PetscFree(values));
1033e7e92044SBarry Smith     /* do not copy values to GPU since they are all zero and not yet needed there */
10349566063dSJacob Faibussowitsch     PetscCall(MatBindToCPU(J, PETSC_TRUE));
10359566063dSJacob Faibussowitsch     PetscCall(MatAssemblyBegin(J, MAT_FINAL_ASSEMBLY));
10369566063dSJacob Faibussowitsch     PetscCall(MatAssemblyEnd(J, MAT_FINAL_ASSEMBLY));
10379566063dSJacob Faibussowitsch     PetscCall(MatBindToCPU(J, PETSC_FALSE));
10389566063dSJacob Faibussowitsch     PetscCall(MatSetOption(J, MAT_NEW_NONZERO_LOCATION_ERR, PETSC_TRUE));
1039711261dbSHong Zhang   }
10409566063dSJacob Faibussowitsch   PetscCall(PetscFree2(rows, cols));
1041711261dbSHong Zhang   PetscFunctionReturn(0);
1042711261dbSHong Zhang }
1043711261dbSHong Zhang 
10449371c9d4SSatish Balay PetscErrorCode DMCreateMatrix_DA_2d_MPIAIJ(DM da, Mat J) {
1045c1154cd5SBarry 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;
104647c6ae99SBarry Smith   PetscInt               lstart, lend, pstart, pend, *dnz, *onz;
104747c6ae99SBarry Smith   MPI_Comm               comm;
1048bff4a2f0SMatthew G. Knepley   DMBoundaryType         bx, by;
1049844bd0d7SStefano Zampini   ISLocalToGlobalMapping ltog, mltog;
1050aa219208SBarry Smith   DMDAStencilType        st;
1051b294de21SRichard Tran Mills   PetscBool              removedups = PETSC_FALSE, alreadyboundtocpu = PETSC_TRUE;
105247c6ae99SBarry Smith 
105347c6ae99SBarry Smith   PetscFunctionBegin;
105447c6ae99SBarry Smith   /*
105547c6ae99SBarry Smith          nc - number of components per grid point
105647c6ae99SBarry Smith          col - number of colors needed in one direction for single component problem
105747c6ae99SBarry Smith 
105847c6ae99SBarry Smith   */
1059924e958dSJunchao Zhang   PetscCall(DMDAGetInfo(da, &dim, &m, &n, NULL, &M, &N, NULL, &nc, &s, &bx, &by, NULL, &st));
10601baa6e33SBarry Smith   if (bx == DM_BOUNDARY_NONE && by == DM_BOUNDARY_NONE) PetscCall(MatSetOption(J, MAT_SORTED_FULL, PETSC_TRUE));
106147c6ae99SBarry Smith   col = 2 * s + 1;
1062c1154cd5SBarry Smith   /*
1063c1154cd5SBarry Smith        With one processor in periodic domains in a skinny dimension the code will label nonzero columns multiple times
1064c1154cd5SBarry Smith        because of "wrapping" around the end of the domain hitting an entry already counted in the other direction.
1065c1154cd5SBarry Smith   */
1066c1154cd5SBarry Smith   if (M == 1 && 2 * s >= m) removedups = PETSC_TRUE;
1067c1154cd5SBarry Smith   if (N == 1 && 2 * s >= n) removedups = PETSC_TRUE;
10689566063dSJacob Faibussowitsch   PetscCall(DMDAGetCorners(da, &xs, &ys, NULL, &nx, &ny, NULL));
10699566063dSJacob Faibussowitsch   PetscCall(DMDAGetGhostCorners(da, &gxs, &gys, NULL, &gnx, &gny, NULL));
10709566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)da, &comm));
107147c6ae99SBarry Smith 
10729566063dSJacob Faibussowitsch   PetscCall(PetscMalloc2(nc, &rows, col * col * nc * nc, &cols));
10739566063dSJacob Faibussowitsch   PetscCall(DMGetLocalToGlobalMapping(da, &ltog));
107447c6ae99SBarry Smith 
10759566063dSJacob Faibussowitsch   PetscCall(MatSetBlockSize(J, nc));
107647c6ae99SBarry Smith   /* determine the matrix preallocation information */
1077d0609cedSBarry Smith   MatPreallocateBegin(comm, nc * nx * ny, nc * nx * ny, dnz, onz);
107847c6ae99SBarry Smith   for (i = xs; i < xs + nx; i++) {
1079bff4a2f0SMatthew G. Knepley     pstart = (bx == DM_BOUNDARY_PERIODIC) ? -s : (PetscMax(-s, -i));
1080bff4a2f0SMatthew G. Knepley     pend   = (bx == DM_BOUNDARY_PERIODIC) ? s : (PetscMin(s, m - i - 1));
108147c6ae99SBarry Smith 
108247c6ae99SBarry Smith     for (j = ys; j < ys + ny; j++) {
108347c6ae99SBarry Smith       slot = i - gxs + gnx * (j - gys);
108447c6ae99SBarry Smith 
1085bff4a2f0SMatthew G. Knepley       lstart = (by == DM_BOUNDARY_PERIODIC) ? -s : (PetscMax(-s, -j));
1086bff4a2f0SMatthew G. Knepley       lend   = (by == DM_BOUNDARY_PERIODIC) ? s : (PetscMin(s, n - j - 1));
108747c6ae99SBarry Smith 
108847c6ae99SBarry Smith       cnt = 0;
108947c6ae99SBarry Smith       for (k = 0; k < nc; k++) {
109047c6ae99SBarry Smith         for (l = lstart; l < lend + 1; l++) {
109147c6ae99SBarry Smith           for (p = pstart; p < pend + 1; p++) {
1092aa219208SBarry Smith             if ((st == DMDA_STENCIL_BOX) || (!l || !p)) { /* entries on star have either l = 0 or p = 0 */
109347c6ae99SBarry Smith               cols[cnt++] = k + nc * (slot + gnx * l + p);
109447c6ae99SBarry Smith             }
109547c6ae99SBarry Smith           }
109647c6ae99SBarry Smith         }
109747c6ae99SBarry Smith         rows[k] = k + nc * (slot);
109847c6ae99SBarry Smith       }
10991baa6e33SBarry Smith       if (removedups) PetscCall(MatPreallocateSetLocalRemoveDups(ltog, nc, rows, ltog, cnt, cols, dnz, onz));
11001baa6e33SBarry Smith       else PetscCall(MatPreallocateSetLocal(ltog, nc, rows, ltog, cnt, cols, dnz, onz));
110147c6ae99SBarry Smith     }
1102c1154cd5SBarry Smith   }
11039566063dSJacob Faibussowitsch   PetscCall(MatSetBlockSize(J, nc));
11049566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJSetPreallocation(J, 0, dnz));
11059566063dSJacob Faibussowitsch   PetscCall(MatMPIAIJSetPreallocation(J, 0, dnz, 0, onz));
1106d0609cedSBarry Smith   MatPreallocateEnd(dnz, onz);
11079566063dSJacob Faibussowitsch   PetscCall(MatGetLocalToGlobalMapping(J, &mltog, NULL));
11081baa6e33SBarry Smith   if (!mltog) PetscCall(MatSetLocalToGlobalMapping(J, ltog, ltog));
110947c6ae99SBarry Smith 
111047c6ae99SBarry Smith   /*
111147c6ae99SBarry Smith     For each node in the grid: we get the neighbors in the local (on processor ordering
111247c6ae99SBarry Smith     that includes the ghost points) then MatSetValuesLocal() maps those indices to the global
111347c6ae99SBarry Smith     PETSc ordering.
111447c6ae99SBarry Smith   */
1115fcfd50ebSBarry Smith   if (!da->prealloc_only) {
111647c6ae99SBarry Smith     for (i = xs; i < xs + nx; i++) {
1117bff4a2f0SMatthew G. Knepley       pstart = (bx == DM_BOUNDARY_PERIODIC) ? -s : (PetscMax(-s, -i));
1118bff4a2f0SMatthew G. Knepley       pend   = (bx == DM_BOUNDARY_PERIODIC) ? s : (PetscMin(s, m - i - 1));
111947c6ae99SBarry Smith 
112047c6ae99SBarry Smith       for (j = ys; j < ys + ny; j++) {
112147c6ae99SBarry Smith         slot = i - gxs + gnx * (j - gys);
112247c6ae99SBarry Smith 
1123bff4a2f0SMatthew G. Knepley         lstart = (by == DM_BOUNDARY_PERIODIC) ? -s : (PetscMax(-s, -j));
1124bff4a2f0SMatthew G. Knepley         lend   = (by == DM_BOUNDARY_PERIODIC) ? s : (PetscMin(s, n - j - 1));
112547c6ae99SBarry Smith 
112647c6ae99SBarry Smith         cnt = 0;
112747c6ae99SBarry Smith         for (l = lstart; l < lend + 1; l++) {
112847c6ae99SBarry Smith           for (p = pstart; p < pend + 1; p++) {
1129aa219208SBarry Smith             if ((st == DMDA_STENCIL_BOX) || (!l || !p)) { /* entries on star have either l = 0 or p = 0 */
1130071fcb05SBarry Smith               cols[cnt++] = nc * (slot + gnx * l + p);
1131071fcb05SBarry Smith               for (k = 1; k < nc; k++) {
11329371c9d4SSatish Balay                 cols[cnt] = 1 + cols[cnt - 1];
11339371c9d4SSatish Balay                 cnt++;
113447c6ae99SBarry Smith               }
113547c6ae99SBarry Smith             }
113647c6ae99SBarry Smith           }
113747c6ae99SBarry Smith         }
1138071fcb05SBarry Smith         for (k = 0; k < nc; k++) rows[k] = k + nc * (slot);
11399566063dSJacob Faibussowitsch         PetscCall(MatSetValuesLocal(J, nc, rows, cnt, cols, NULL, INSERT_VALUES));
114047c6ae99SBarry Smith       }
114147c6ae99SBarry Smith     }
1142e7e92044SBarry Smith     /* do not copy values to GPU since they are all zero and not yet needed there */
11439566063dSJacob Faibussowitsch     PetscCall(MatBoundToCPU(J, &alreadyboundtocpu));
11449566063dSJacob Faibussowitsch     PetscCall(MatBindToCPU(J, PETSC_TRUE));
11459566063dSJacob Faibussowitsch     PetscCall(MatAssemblyBegin(J, MAT_FINAL_ASSEMBLY));
11469566063dSJacob Faibussowitsch     PetscCall(MatAssemblyEnd(J, MAT_FINAL_ASSEMBLY));
11479566063dSJacob Faibussowitsch     if (!alreadyboundtocpu) PetscCall(MatBindToCPU(J, PETSC_FALSE));
11489566063dSJacob Faibussowitsch     PetscCall(MatSetOption(J, MAT_NEW_NONZERO_LOCATION_ERR, PETSC_TRUE));
11491baa6e33SBarry Smith     if (bx == DM_BOUNDARY_NONE && by == DM_BOUNDARY_NONE) PetscCall(MatSetOption(J, MAT_SORTED_FULL, PETSC_FALSE));
115047c6ae99SBarry Smith   }
11519566063dSJacob Faibussowitsch   PetscCall(PetscFree2(rows, cols));
115247c6ae99SBarry Smith   PetscFunctionReturn(0);
115347c6ae99SBarry Smith }
115447c6ae99SBarry Smith 
11559371c9d4SSatish Balay PetscErrorCode DMCreateMatrix_DA_2d_MPIAIJ_Fill(DM da, Mat J) {
115647c6ae99SBarry Smith   PetscInt               xs, ys, nx, ny, i, j, slot, gxs, gys, gnx, gny;
1157c1154cd5SBarry Smith   PetscInt               m, n, dim, s, *cols, k, nc, row, col, cnt, maxcnt = 0, l, p, M, N;
115847c6ae99SBarry Smith   PetscInt               lstart, lend, pstart, pend, *dnz, *onz;
115947c6ae99SBarry Smith   DM_DA                 *dd = (DM_DA *)da->data;
116047c6ae99SBarry Smith   PetscInt               ifill_col, *ofill = dd->ofill, *dfill = dd->dfill;
116147c6ae99SBarry Smith   MPI_Comm               comm;
1162bff4a2f0SMatthew G. Knepley   DMBoundaryType         bx, by;
116345b6f7e9SBarry Smith   ISLocalToGlobalMapping ltog;
1164aa219208SBarry Smith   DMDAStencilType        st;
1165c1154cd5SBarry Smith   PetscBool              removedups = PETSC_FALSE;
116647c6ae99SBarry Smith 
116747c6ae99SBarry Smith   PetscFunctionBegin;
116847c6ae99SBarry Smith   /*
116947c6ae99SBarry Smith          nc - number of components per grid point
117047c6ae99SBarry Smith          col - number of colors needed in one direction for single component problem
117147c6ae99SBarry Smith 
117247c6ae99SBarry Smith   */
1173924e958dSJunchao Zhang   PetscCall(DMDAGetInfo(da, &dim, &m, &n, NULL, &M, &N, NULL, &nc, &s, &bx, &by, NULL, &st));
117447c6ae99SBarry Smith   col = 2 * s + 1;
1175c1154cd5SBarry Smith   /*
1176c1154cd5SBarry Smith        With one processor in periodic domains in a skinny dimension the code will label nonzero columns multiple times
1177c1154cd5SBarry Smith        because of "wrapping" around the end of the domain hitting an entry already counted in the other direction.
1178c1154cd5SBarry Smith   */
1179c1154cd5SBarry Smith   if (M == 1 && 2 * s >= m) removedups = PETSC_TRUE;
1180c1154cd5SBarry Smith   if (N == 1 && 2 * s >= n) removedups = PETSC_TRUE;
11819566063dSJacob Faibussowitsch   PetscCall(DMDAGetCorners(da, &xs, &ys, NULL, &nx, &ny, NULL));
11829566063dSJacob Faibussowitsch   PetscCall(DMDAGetGhostCorners(da, &gxs, &gys, NULL, &gnx, &gny, NULL));
11839566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)da, &comm));
118447c6ae99SBarry Smith 
11859566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(col * col * nc, &cols));
11869566063dSJacob Faibussowitsch   PetscCall(DMGetLocalToGlobalMapping(da, &ltog));
118747c6ae99SBarry Smith 
11889566063dSJacob Faibussowitsch   PetscCall(MatSetBlockSize(J, nc));
118947c6ae99SBarry Smith   /* determine the matrix preallocation information */
1190d0609cedSBarry Smith   MatPreallocateBegin(comm, nc * nx * ny, nc * nx * ny, dnz, onz);
119147c6ae99SBarry Smith   for (i = xs; i < xs + nx; i++) {
1192bff4a2f0SMatthew G. Knepley     pstart = (bx == DM_BOUNDARY_PERIODIC) ? -s : (PetscMax(-s, -i));
1193bff4a2f0SMatthew G. Knepley     pend   = (bx == DM_BOUNDARY_PERIODIC) ? s : (PetscMin(s, m - i - 1));
119447c6ae99SBarry Smith 
119547c6ae99SBarry Smith     for (j = ys; j < ys + ny; j++) {
119647c6ae99SBarry Smith       slot = i - gxs + gnx * (j - gys);
119747c6ae99SBarry Smith 
1198bff4a2f0SMatthew G. Knepley       lstart = (by == DM_BOUNDARY_PERIODIC) ? -s : (PetscMax(-s, -j));
1199bff4a2f0SMatthew G. Knepley       lend   = (by == DM_BOUNDARY_PERIODIC) ? s : (PetscMin(s, n - j - 1));
120047c6ae99SBarry Smith 
120147c6ae99SBarry Smith       for (k = 0; k < nc; k++) {
120247c6ae99SBarry Smith         cnt = 0;
120347c6ae99SBarry Smith         for (l = lstart; l < lend + 1; l++) {
120447c6ae99SBarry Smith           for (p = pstart; p < pend + 1; p++) {
120547c6ae99SBarry Smith             if (l || p) {
1206aa219208SBarry Smith               if ((st == DMDA_STENCIL_BOX) || (!l || !p)) { /* entries on star */
12078865f1eaSKarl Rupp                 for (ifill_col = ofill[k]; ifill_col < ofill[k + 1]; ifill_col++) cols[cnt++] = ofill[ifill_col] + nc * (slot + gnx * l + p);
120847c6ae99SBarry Smith               }
120947c6ae99SBarry Smith             } else {
121047c6ae99SBarry Smith               if (dfill) {
12118865f1eaSKarl Rupp                 for (ifill_col = dfill[k]; ifill_col < dfill[k + 1]; ifill_col++) cols[cnt++] = dfill[ifill_col] + nc * (slot + gnx * l + p);
121247c6ae99SBarry Smith               } else {
12138865f1eaSKarl Rupp                 for (ifill_col = 0; ifill_col < nc; ifill_col++) cols[cnt++] = ifill_col + nc * (slot + gnx * l + p);
121447c6ae99SBarry Smith               }
121547c6ae99SBarry Smith             }
121647c6ae99SBarry Smith           }
121747c6ae99SBarry Smith         }
121847c6ae99SBarry Smith         row    = k + nc * (slot);
1219c0ab637bSBarry Smith         maxcnt = PetscMax(maxcnt, cnt);
12201baa6e33SBarry Smith         if (removedups) PetscCall(MatPreallocateSetLocalRemoveDups(ltog, 1, &row, ltog, cnt, cols, dnz, onz));
12211baa6e33SBarry Smith         else PetscCall(MatPreallocateSetLocal(ltog, 1, &row, ltog, cnt, cols, dnz, onz));
122247c6ae99SBarry Smith       }
122347c6ae99SBarry Smith     }
1224c1154cd5SBarry Smith   }
12259566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJSetPreallocation(J, 0, dnz));
12269566063dSJacob Faibussowitsch   PetscCall(MatMPIAIJSetPreallocation(J, 0, dnz, 0, onz));
1227d0609cedSBarry Smith   MatPreallocateEnd(dnz, onz);
12289566063dSJacob Faibussowitsch   PetscCall(MatSetLocalToGlobalMapping(J, ltog, ltog));
122947c6ae99SBarry Smith 
123047c6ae99SBarry Smith   /*
123147c6ae99SBarry Smith     For each node in the grid: we get the neighbors in the local (on processor ordering
123247c6ae99SBarry Smith     that includes the ghost points) then MatSetValuesLocal() maps those indices to the global
123347c6ae99SBarry Smith     PETSc ordering.
123447c6ae99SBarry Smith   */
1235fcfd50ebSBarry Smith   if (!da->prealloc_only) {
123647c6ae99SBarry Smith     for (i = xs; i < xs + nx; i++) {
1237bff4a2f0SMatthew G. Knepley       pstart = (bx == DM_BOUNDARY_PERIODIC) ? -s : (PetscMax(-s, -i));
1238bff4a2f0SMatthew G. Knepley       pend   = (bx == DM_BOUNDARY_PERIODIC) ? s : (PetscMin(s, m - i - 1));
123947c6ae99SBarry Smith 
124047c6ae99SBarry Smith       for (j = ys; j < ys + ny; j++) {
124147c6ae99SBarry Smith         slot = i - gxs + gnx * (j - gys);
124247c6ae99SBarry Smith 
1243bff4a2f0SMatthew G. Knepley         lstart = (by == DM_BOUNDARY_PERIODIC) ? -s : (PetscMax(-s, -j));
1244bff4a2f0SMatthew G. Knepley         lend   = (by == DM_BOUNDARY_PERIODIC) ? s : (PetscMin(s, n - j - 1));
124547c6ae99SBarry Smith 
124647c6ae99SBarry Smith         for (k = 0; k < nc; k++) {
124747c6ae99SBarry Smith           cnt = 0;
124847c6ae99SBarry Smith           for (l = lstart; l < lend + 1; l++) {
124947c6ae99SBarry Smith             for (p = pstart; p < pend + 1; p++) {
125047c6ae99SBarry Smith               if (l || p) {
1251aa219208SBarry Smith                 if ((st == DMDA_STENCIL_BOX) || (!l || !p)) { /* entries on star */
12528865f1eaSKarl Rupp                   for (ifill_col = ofill[k]; ifill_col < ofill[k + 1]; ifill_col++) cols[cnt++] = ofill[ifill_col] + nc * (slot + gnx * l + p);
125347c6ae99SBarry Smith                 }
125447c6ae99SBarry Smith               } else {
125547c6ae99SBarry Smith                 if (dfill) {
12568865f1eaSKarl Rupp                   for (ifill_col = dfill[k]; ifill_col < dfill[k + 1]; ifill_col++) cols[cnt++] = dfill[ifill_col] + nc * (slot + gnx * l + p);
125747c6ae99SBarry Smith                 } else {
12588865f1eaSKarl Rupp                   for (ifill_col = 0; ifill_col < nc; ifill_col++) cols[cnt++] = ifill_col + nc * (slot + gnx * l + p);
125947c6ae99SBarry Smith                 }
126047c6ae99SBarry Smith               }
126147c6ae99SBarry Smith             }
126247c6ae99SBarry Smith           }
126347c6ae99SBarry Smith           row = k + nc * (slot);
12649566063dSJacob Faibussowitsch           PetscCall(MatSetValuesLocal(J, 1, &row, cnt, cols, NULL, INSERT_VALUES));
126547c6ae99SBarry Smith         }
126647c6ae99SBarry Smith       }
126747c6ae99SBarry Smith     }
1268e7e92044SBarry Smith     /* do not copy values to GPU since they are all zero and not yet needed there */
12699566063dSJacob Faibussowitsch     PetscCall(MatBindToCPU(J, PETSC_TRUE));
12709566063dSJacob Faibussowitsch     PetscCall(MatAssemblyBegin(J, MAT_FINAL_ASSEMBLY));
12719566063dSJacob Faibussowitsch     PetscCall(MatAssemblyEnd(J, MAT_FINAL_ASSEMBLY));
12729566063dSJacob Faibussowitsch     PetscCall(MatBindToCPU(J, PETSC_FALSE));
12739566063dSJacob Faibussowitsch     PetscCall(MatSetOption(J, MAT_NEW_NONZERO_LOCATION_ERR, PETSC_TRUE));
127447c6ae99SBarry Smith   }
12759566063dSJacob Faibussowitsch   PetscCall(PetscFree(cols));
127647c6ae99SBarry Smith   PetscFunctionReturn(0);
127747c6ae99SBarry Smith }
127847c6ae99SBarry Smith 
127947c6ae99SBarry Smith /* ---------------------------------------------------------------------------------*/
128047c6ae99SBarry Smith 
12819371c9d4SSatish Balay PetscErrorCode DMCreateMatrix_DA_3d_MPIAIJ(DM da, Mat J) {
128247c6ae99SBarry Smith   PetscInt               xs, ys, nx, ny, i, j, slot, gxs, gys, gnx, gny;
12830298fd71SBarry Smith   PetscInt               m, n, dim, s, *cols = NULL, k, nc, *rows = NULL, col, cnt, l, p, *dnz = NULL, *onz = NULL;
1284c1154cd5SBarry Smith   PetscInt               istart, iend, jstart, jend, kstart, kend, zs, nz, gzs, gnz, ii, jj, kk, M, N, P;
128547c6ae99SBarry Smith   MPI_Comm               comm;
1286bff4a2f0SMatthew G. Knepley   DMBoundaryType         bx, by, bz;
1287844bd0d7SStefano Zampini   ISLocalToGlobalMapping ltog, mltog;
1288aa219208SBarry Smith   DMDAStencilType        st;
1289c1154cd5SBarry Smith   PetscBool              removedups = PETSC_FALSE;
129047c6ae99SBarry Smith 
129147c6ae99SBarry Smith   PetscFunctionBegin;
129247c6ae99SBarry Smith   /*
129347c6ae99SBarry Smith          nc - number of components per grid point
129447c6ae99SBarry Smith          col - number of colors needed in one direction for single component problem
129547c6ae99SBarry Smith 
129647c6ae99SBarry Smith   */
12979566063dSJacob Faibussowitsch   PetscCall(DMDAGetInfo(da, &dim, &m, &n, &p, &M, &N, &P, &nc, &s, &bx, &by, &bz, &st));
1298*48a46eb9SPierre Jolivet   if (bx == DM_BOUNDARY_NONE && by == DM_BOUNDARY_NONE && bz == DM_BOUNDARY_NONE) PetscCall(MatSetOption(J, MAT_SORTED_FULL, PETSC_TRUE));
129947c6ae99SBarry Smith   col = 2 * s + 1;
130047c6ae99SBarry Smith 
1301c1154cd5SBarry Smith   /*
1302c1154cd5SBarry Smith        With one processor in periodic domains in a skinny dimension the code will label nonzero columns multiple times
1303c1154cd5SBarry Smith        because of "wrapping" around the end of the domain hitting an entry already counted in the other direction.
1304c1154cd5SBarry Smith   */
1305c1154cd5SBarry Smith   if (M == 1 && 2 * s >= m) removedups = PETSC_TRUE;
1306c1154cd5SBarry Smith   if (N == 1 && 2 * s >= n) removedups = PETSC_TRUE;
1307c1154cd5SBarry Smith   if (P == 1 && 2 * s >= p) removedups = PETSC_TRUE;
1308c1154cd5SBarry Smith 
13099566063dSJacob Faibussowitsch   PetscCall(DMDAGetCorners(da, &xs, &ys, &zs, &nx, &ny, &nz));
13109566063dSJacob Faibussowitsch   PetscCall(DMDAGetGhostCorners(da, &gxs, &gys, &gzs, &gnx, &gny, &gnz));
13119566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)da, &comm));
131247c6ae99SBarry Smith 
13139566063dSJacob Faibussowitsch   PetscCall(PetscMalloc2(nc, &rows, col * col * col * nc * nc, &cols));
13149566063dSJacob Faibussowitsch   PetscCall(DMGetLocalToGlobalMapping(da, &ltog));
131547c6ae99SBarry Smith 
13169566063dSJacob Faibussowitsch   PetscCall(MatSetBlockSize(J, nc));
131747c6ae99SBarry Smith   /* determine the matrix preallocation information */
1318d0609cedSBarry Smith   MatPreallocateBegin(comm, nc * nx * ny * nz, nc * nx * ny * nz, dnz, onz);
131947c6ae99SBarry Smith   for (i = xs; i < xs + nx; i++) {
1320bff4a2f0SMatthew G. Knepley     istart = (bx == DM_BOUNDARY_PERIODIC) ? -s : (PetscMax(-s, -i));
1321bff4a2f0SMatthew G. Knepley     iend   = (bx == DM_BOUNDARY_PERIODIC) ? s : (PetscMin(s, m - i - 1));
132247c6ae99SBarry Smith     for (j = ys; j < ys + ny; j++) {
1323bff4a2f0SMatthew G. Knepley       jstart = (by == DM_BOUNDARY_PERIODIC) ? -s : (PetscMax(-s, -j));
1324bff4a2f0SMatthew G. Knepley       jend   = (by == DM_BOUNDARY_PERIODIC) ? s : (PetscMin(s, n - j - 1));
132547c6ae99SBarry Smith       for (k = zs; k < zs + nz; k++) {
1326bff4a2f0SMatthew G. Knepley         kstart = (bz == DM_BOUNDARY_PERIODIC) ? -s : (PetscMax(-s, -k));
1327bff4a2f0SMatthew G. Knepley         kend   = (bz == DM_BOUNDARY_PERIODIC) ? s : (PetscMin(s, p - k - 1));
132847c6ae99SBarry Smith 
132947c6ae99SBarry Smith         slot = i - gxs + gnx * (j - gys) + gnx * gny * (k - gzs);
133047c6ae99SBarry Smith 
133147c6ae99SBarry Smith         cnt = 0;
133247c6ae99SBarry Smith         for (l = 0; l < nc; l++) {
133347c6ae99SBarry Smith           for (ii = istart; ii < iend + 1; ii++) {
133447c6ae99SBarry Smith             for (jj = jstart; jj < jend + 1; jj++) {
133547c6ae99SBarry Smith               for (kk = kstart; kk < kend + 1; kk++) {
1336aa219208SBarry Smith                 if ((st == DMDA_STENCIL_BOX) || ((!ii && !jj) || (!jj && !kk) || (!ii && !kk))) { /* entries on star*/
133747c6ae99SBarry Smith                   cols[cnt++] = l + nc * (slot + ii + gnx * jj + gnx * gny * kk);
133847c6ae99SBarry Smith                 }
133947c6ae99SBarry Smith               }
134047c6ae99SBarry Smith             }
134147c6ae99SBarry Smith           }
134247c6ae99SBarry Smith           rows[l] = l + nc * (slot);
134347c6ae99SBarry Smith         }
13441baa6e33SBarry Smith         if (removedups) PetscCall(MatPreallocateSetLocalRemoveDups(ltog, nc, rows, ltog, cnt, cols, dnz, onz));
13451baa6e33SBarry Smith         else PetscCall(MatPreallocateSetLocal(ltog, nc, rows, ltog, cnt, cols, dnz, onz));
134647c6ae99SBarry Smith       }
134747c6ae99SBarry Smith     }
1348c1154cd5SBarry Smith   }
13499566063dSJacob Faibussowitsch   PetscCall(MatSetBlockSize(J, nc));
13509566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJSetPreallocation(J, 0, dnz));
13519566063dSJacob Faibussowitsch   PetscCall(MatMPIAIJSetPreallocation(J, 0, dnz, 0, onz));
1352d0609cedSBarry Smith   MatPreallocateEnd(dnz, onz);
13539566063dSJacob Faibussowitsch   PetscCall(MatGetLocalToGlobalMapping(J, &mltog, NULL));
1354*48a46eb9SPierre Jolivet   if (!mltog) PetscCall(MatSetLocalToGlobalMapping(J, ltog, ltog));
135547c6ae99SBarry Smith 
135647c6ae99SBarry Smith   /*
135747c6ae99SBarry Smith     For each node in the grid: we get the neighbors in the local (on processor ordering
135847c6ae99SBarry Smith     that includes the ghost points) then MatSetValuesLocal() maps those indices to the global
135947c6ae99SBarry Smith     PETSc ordering.
136047c6ae99SBarry Smith   */
1361fcfd50ebSBarry Smith   if (!da->prealloc_only) {
136247c6ae99SBarry Smith     for (i = xs; i < xs + nx; i++) {
1363bff4a2f0SMatthew G. Knepley       istart = (bx == DM_BOUNDARY_PERIODIC) ? -s : (PetscMax(-s, -i));
1364bff4a2f0SMatthew G. Knepley       iend   = (bx == DM_BOUNDARY_PERIODIC) ? s : (PetscMin(s, m - i - 1));
136547c6ae99SBarry Smith       for (j = ys; j < ys + ny; j++) {
1366bff4a2f0SMatthew G. Knepley         jstart = (by == DM_BOUNDARY_PERIODIC) ? -s : (PetscMax(-s, -j));
1367bff4a2f0SMatthew G. Knepley         jend   = (by == DM_BOUNDARY_PERIODIC) ? s : (PetscMin(s, n - j - 1));
136847c6ae99SBarry Smith         for (k = zs; k < zs + nz; k++) {
1369bff4a2f0SMatthew G. Knepley           kstart = (bz == DM_BOUNDARY_PERIODIC) ? -s : (PetscMax(-s, -k));
1370bff4a2f0SMatthew G. Knepley           kend   = (bz == DM_BOUNDARY_PERIODIC) ? s : (PetscMin(s, p - k - 1));
137147c6ae99SBarry Smith 
137247c6ae99SBarry Smith           slot = i - gxs + gnx * (j - gys) + gnx * gny * (k - gzs);
137347c6ae99SBarry Smith 
137447c6ae99SBarry Smith           cnt = 0;
137547c6ae99SBarry Smith           for (kk = kstart; kk < kend + 1; kk++) {
1376071fcb05SBarry Smith             for (jj = jstart; jj < jend + 1; jj++) {
1377071fcb05SBarry Smith               for (ii = istart; ii < iend + 1; ii++) {
1378aa219208SBarry Smith                 if ((st == DMDA_STENCIL_BOX) || ((!ii && !jj) || (!jj && !kk) || (!ii && !kk))) { /* entries on star*/
1379071fcb05SBarry Smith                   cols[cnt++] = nc * (slot + ii + gnx * jj + gnx * gny * kk);
1380071fcb05SBarry Smith                   for (l = 1; l < nc; l++) {
13819371c9d4SSatish Balay                     cols[cnt] = 1 + cols[cnt - 1];
13829371c9d4SSatish Balay                     cnt++;
138347c6ae99SBarry Smith                   }
138447c6ae99SBarry Smith                 }
138547c6ae99SBarry Smith               }
138647c6ae99SBarry Smith             }
138747c6ae99SBarry Smith           }
13889371c9d4SSatish Balay           rows[0] = nc * (slot);
13899371c9d4SSatish Balay           for (l = 1; l < nc; l++) rows[l] = 1 + rows[l - 1];
13909566063dSJacob Faibussowitsch           PetscCall(MatSetValuesLocal(J, nc, rows, cnt, cols, NULL, INSERT_VALUES));
139147c6ae99SBarry Smith         }
139247c6ae99SBarry Smith       }
139347c6ae99SBarry Smith     }
1394e7e92044SBarry Smith     /* do not copy values to GPU since they are all zero and not yet needed there */
13959566063dSJacob Faibussowitsch     PetscCall(MatBindToCPU(J, PETSC_TRUE));
13969566063dSJacob Faibussowitsch     PetscCall(MatAssemblyBegin(J, MAT_FINAL_ASSEMBLY));
13979566063dSJacob Faibussowitsch     PetscCall(MatAssemblyEnd(J, MAT_FINAL_ASSEMBLY));
1398*48a46eb9SPierre Jolivet     if (bx == DM_BOUNDARY_NONE && by == DM_BOUNDARY_NONE && bz == DM_BOUNDARY_NONE) PetscCall(MatSetOption(J, MAT_SORTED_FULL, PETSC_FALSE));
13999566063dSJacob Faibussowitsch     PetscCall(MatBindToCPU(J, PETSC_FALSE));
14009566063dSJacob Faibussowitsch     PetscCall(MatSetOption(J, MAT_NEW_NONZERO_LOCATION_ERR, PETSC_TRUE));
140147c6ae99SBarry Smith   }
14029566063dSJacob Faibussowitsch   PetscCall(PetscFree2(rows, cols));
140347c6ae99SBarry Smith   PetscFunctionReturn(0);
140447c6ae99SBarry Smith }
140547c6ae99SBarry Smith 
140647c6ae99SBarry Smith /* ---------------------------------------------------------------------------------*/
140747c6ae99SBarry Smith 
14089371c9d4SSatish Balay PetscErrorCode DMCreateMatrix_DA_1d_MPIAIJ_Fill(DM da, Mat J) {
1409ce308e1dSBarry Smith   DM_DA                 *dd = (DM_DA *)da->data;
1410ce308e1dSBarry Smith   PetscInt               xs, nx, i, j, gxs, gnx, row, k, l;
14118d4c968fSBarry Smith   PetscInt               m, dim, s, *cols = NULL, nc, cnt, maxcnt = 0, *ocols;
14120acb5bebSBarry Smith   PetscInt              *ofill = dd->ofill, *dfill = dd->dfill;
1413bff4a2f0SMatthew G. Knepley   DMBoundaryType         bx;
141445b6f7e9SBarry Smith   ISLocalToGlobalMapping ltog;
1415ce308e1dSBarry Smith   PetscMPIInt            rank, size;
1416ce308e1dSBarry Smith 
1417ce308e1dSBarry Smith   PetscFunctionBegin;
14189566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)da), &rank));
14199566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)da), &size));
1420ce308e1dSBarry Smith 
1421ce308e1dSBarry Smith   /*
1422ce308e1dSBarry Smith          nc - number of components per grid point
1423ce308e1dSBarry Smith 
1424ce308e1dSBarry Smith   */
14259566063dSJacob Faibussowitsch   PetscCall(DMDAGetInfo(da, &dim, &m, NULL, NULL, NULL, NULL, NULL, &nc, &s, &bx, NULL, NULL, NULL));
142608401ef6SPierre Jolivet   PetscCheck(s <= 1, PetscObjectComm((PetscObject)da), PETSC_ERR_SUP, "Matrix creation for 1d not implemented correctly for stencil width larger than 1");
14279566063dSJacob Faibussowitsch   PetscCall(DMDAGetCorners(da, &xs, NULL, NULL, &nx, NULL, NULL));
14289566063dSJacob Faibussowitsch   PetscCall(DMDAGetGhostCorners(da, &gxs, NULL, NULL, &gnx, NULL, NULL));
1429ce308e1dSBarry Smith 
14309566063dSJacob Faibussowitsch   PetscCall(MatSetBlockSize(J, nc));
14319566063dSJacob Faibussowitsch   PetscCall(PetscCalloc2(nx * nc, &cols, nx * nc, &ocols));
1432ce308e1dSBarry Smith 
1433ce308e1dSBarry Smith   /*
1434ce308e1dSBarry Smith         note should be smaller for first and last process with no periodic
1435ce308e1dSBarry Smith         does not handle dfill
1436ce308e1dSBarry Smith   */
1437ce308e1dSBarry Smith   cnt = 0;
1438ce308e1dSBarry Smith   /* coupling with process to the left */
1439ce308e1dSBarry Smith   for (i = 0; i < s; i++) {
1440ce308e1dSBarry Smith     for (j = 0; j < nc; j++) {
1441dd400576SPatrick Sanan       ocols[cnt] = ((rank == 0) ? 0 : (s - i) * (ofill[j + 1] - ofill[j]));
14420acb5bebSBarry Smith       cols[cnt]  = dfill[j + 1] - dfill[j] + (s + i) * (ofill[j + 1] - ofill[j]);
1443dd400576SPatrick Sanan       if (rank == 0 && (dd->bx == DM_BOUNDARY_PERIODIC)) {
1444831644c1SBarry Smith         if (size > 1) ocols[cnt] += (s - i) * (ofill[j + 1] - ofill[j]);
1445831644c1SBarry Smith         else cols[cnt] += (s - i) * (ofill[j + 1] - ofill[j]);
1446831644c1SBarry Smith       }
1447c0ab637bSBarry Smith       maxcnt = PetscMax(maxcnt, ocols[cnt] + cols[cnt]);
1448ce308e1dSBarry Smith       cnt++;
1449ce308e1dSBarry Smith     }
1450ce308e1dSBarry Smith   }
1451ce308e1dSBarry Smith   for (i = s; i < nx - s; i++) {
1452ce308e1dSBarry Smith     for (j = 0; j < nc; j++) {
14530acb5bebSBarry Smith       cols[cnt] = dfill[j + 1] - dfill[j] + 2 * s * (ofill[j + 1] - ofill[j]);
1454c0ab637bSBarry Smith       maxcnt    = PetscMax(maxcnt, ocols[cnt] + cols[cnt]);
1455ce308e1dSBarry Smith       cnt++;
1456ce308e1dSBarry Smith     }
1457ce308e1dSBarry Smith   }
1458ce308e1dSBarry Smith   /* coupling with process to the right */
1459ce308e1dSBarry Smith   for (i = nx - s; i < nx; i++) {
1460ce308e1dSBarry Smith     for (j = 0; j < nc; j++) {
1461ce308e1dSBarry Smith       ocols[cnt] = ((rank == (size - 1)) ? 0 : (i - nx + s + 1) * (ofill[j + 1] - ofill[j]));
14620acb5bebSBarry Smith       cols[cnt]  = dfill[j + 1] - dfill[j] + (s + nx - i - 1) * (ofill[j + 1] - ofill[j]);
1463831644c1SBarry Smith       if ((rank == size - 1) && (dd->bx == DM_BOUNDARY_PERIODIC)) {
1464831644c1SBarry Smith         if (size > 1) ocols[cnt] += (i - nx + s + 1) * (ofill[j + 1] - ofill[j]);
1465831644c1SBarry Smith         else cols[cnt] += (i - nx + s + 1) * (ofill[j + 1] - ofill[j]);
1466831644c1SBarry Smith       }
1467c0ab637bSBarry Smith       maxcnt = PetscMax(maxcnt, ocols[cnt] + cols[cnt]);
1468ce308e1dSBarry Smith       cnt++;
1469ce308e1dSBarry Smith     }
1470ce308e1dSBarry Smith   }
1471ce308e1dSBarry Smith 
14729566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJSetPreallocation(J, 0, cols));
14739566063dSJacob Faibussowitsch   PetscCall(MatMPIAIJSetPreallocation(J, 0, cols, 0, ocols));
14749566063dSJacob Faibussowitsch   PetscCall(PetscFree2(cols, ocols));
1475ce308e1dSBarry Smith 
14769566063dSJacob Faibussowitsch   PetscCall(DMGetLocalToGlobalMapping(da, &ltog));
14779566063dSJacob Faibussowitsch   PetscCall(MatSetLocalToGlobalMapping(J, ltog, ltog));
1478ce308e1dSBarry Smith 
1479ce308e1dSBarry Smith   /*
1480ce308e1dSBarry Smith     For each node in the grid: we get the neighbors in the local (on processor ordering
1481ce308e1dSBarry Smith     that includes the ghost points) then MatSetValuesLocal() maps those indices to the global
1482ce308e1dSBarry Smith     PETSc ordering.
1483ce308e1dSBarry Smith   */
1484ce308e1dSBarry Smith   if (!da->prealloc_only) {
14859566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(maxcnt, &cols));
1486ce308e1dSBarry Smith     row = xs * nc;
1487ce308e1dSBarry Smith     /* coupling with process to the left */
1488ce308e1dSBarry Smith     for (i = xs; i < xs + s; i++) {
1489ce308e1dSBarry Smith       for (j = 0; j < nc; j++) {
1490ce308e1dSBarry Smith         cnt = 0;
1491ce308e1dSBarry Smith         if (rank) {
1492ce308e1dSBarry Smith           for (l = 0; l < s; l++) {
1493ce308e1dSBarry Smith             for (k = ofill[j]; k < ofill[j + 1]; k++) cols[cnt++] = (i - s + l) * nc + ofill[k];
1494ce308e1dSBarry Smith           }
1495ce308e1dSBarry Smith         }
1496dd400576SPatrick Sanan         if (rank == 0 && (dd->bx == DM_BOUNDARY_PERIODIC)) {
1497831644c1SBarry Smith           for (l = 0; l < s; l++) {
1498831644c1SBarry Smith             for (k = ofill[j]; k < ofill[j + 1]; k++) cols[cnt++] = (m + i - s - l) * nc + ofill[k];
1499831644c1SBarry Smith           }
1500831644c1SBarry Smith         }
15010acb5bebSBarry Smith         if (dfill) {
15029371c9d4SSatish Balay           for (k = dfill[j]; k < dfill[j + 1]; k++) { cols[cnt++] = i * nc + dfill[k]; }
15030acb5bebSBarry Smith         } else {
15049371c9d4SSatish Balay           for (k = 0; k < nc; k++) { cols[cnt++] = i * nc + k; }
15050acb5bebSBarry Smith         }
1506ce308e1dSBarry Smith         for (l = 0; l < s; l++) {
1507ce308e1dSBarry Smith           for (k = ofill[j]; k < ofill[j + 1]; k++) cols[cnt++] = (i + s - l) * nc + ofill[k];
1508ce308e1dSBarry Smith         }
15099566063dSJacob Faibussowitsch         PetscCall(MatSetValues(J, 1, &row, cnt, cols, NULL, INSERT_VALUES));
1510ce308e1dSBarry Smith         row++;
1511ce308e1dSBarry Smith       }
1512ce308e1dSBarry Smith     }
1513ce308e1dSBarry Smith     for (i = xs + s; i < xs + nx - s; i++) {
1514ce308e1dSBarry Smith       for (j = 0; j < nc; j++) {
1515ce308e1dSBarry Smith         cnt = 0;
1516ce308e1dSBarry Smith         for (l = 0; l < s; l++) {
1517ce308e1dSBarry Smith           for (k = ofill[j]; k < ofill[j + 1]; k++) cols[cnt++] = (i - s + l) * nc + ofill[k];
1518ce308e1dSBarry Smith         }
15190acb5bebSBarry Smith         if (dfill) {
15209371c9d4SSatish Balay           for (k = dfill[j]; k < dfill[j + 1]; k++) { cols[cnt++] = i * nc + dfill[k]; }
15210acb5bebSBarry Smith         } else {
15229371c9d4SSatish Balay           for (k = 0; k < nc; k++) { cols[cnt++] = i * nc + k; }
15230acb5bebSBarry Smith         }
1524ce308e1dSBarry Smith         for (l = 0; l < s; l++) {
1525ce308e1dSBarry Smith           for (k = ofill[j]; k < ofill[j + 1]; k++) cols[cnt++] = (i + s - l) * nc + ofill[k];
1526ce308e1dSBarry Smith         }
15279566063dSJacob Faibussowitsch         PetscCall(MatSetValues(J, 1, &row, cnt, cols, NULL, INSERT_VALUES));
1528ce308e1dSBarry Smith         row++;
1529ce308e1dSBarry Smith       }
1530ce308e1dSBarry Smith     }
1531ce308e1dSBarry Smith     /* coupling with process to the right */
1532ce308e1dSBarry Smith     for (i = xs + nx - s; i < xs + nx; i++) {
1533ce308e1dSBarry Smith       for (j = 0; j < nc; j++) {
1534ce308e1dSBarry Smith         cnt = 0;
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         }
15380acb5bebSBarry Smith         if (dfill) {
15399371c9d4SSatish Balay           for (k = dfill[j]; k < dfill[j + 1]; k++) { cols[cnt++] = i * nc + dfill[k]; }
15400acb5bebSBarry Smith         } else {
15419371c9d4SSatish Balay           for (k = 0; k < nc; k++) { cols[cnt++] = i * nc + k; }
15420acb5bebSBarry Smith         }
1543ce308e1dSBarry Smith         if (rank < size - 1) {
1544ce308e1dSBarry Smith           for (l = 0; l < s; l++) {
1545ce308e1dSBarry Smith             for (k = ofill[j]; k < ofill[j + 1]; k++) cols[cnt++] = (i + s - l) * nc + ofill[k];
1546ce308e1dSBarry Smith           }
1547ce308e1dSBarry Smith         }
1548831644c1SBarry Smith         if ((rank == size - 1) && (dd->bx == DM_BOUNDARY_PERIODIC)) {
1549831644c1SBarry Smith           for (l = 0; l < s; l++) {
1550831644c1SBarry Smith             for (k = ofill[j]; k < ofill[j + 1]; k++) cols[cnt++] = (i - s - l - m + 2) * nc + ofill[k];
1551831644c1SBarry Smith           }
1552831644c1SBarry Smith         }
15539566063dSJacob Faibussowitsch         PetscCall(MatSetValues(J, 1, &row, cnt, cols, NULL, INSERT_VALUES));
1554ce308e1dSBarry Smith         row++;
1555ce308e1dSBarry Smith       }
1556ce308e1dSBarry Smith     }
15579566063dSJacob Faibussowitsch     PetscCall(PetscFree(cols));
1558e7e92044SBarry Smith     /* do not copy values to GPU since they are all zero and not yet needed there */
15599566063dSJacob Faibussowitsch     PetscCall(MatBindToCPU(J, PETSC_TRUE));
15609566063dSJacob Faibussowitsch     PetscCall(MatAssemblyBegin(J, MAT_FINAL_ASSEMBLY));
15619566063dSJacob Faibussowitsch     PetscCall(MatAssemblyEnd(J, MAT_FINAL_ASSEMBLY));
15629566063dSJacob Faibussowitsch     PetscCall(MatBindToCPU(J, PETSC_FALSE));
15639566063dSJacob Faibussowitsch     PetscCall(MatSetOption(J, MAT_NEW_NONZERO_LOCATION_ERR, PETSC_TRUE));
1564ce308e1dSBarry Smith   }
1565ce308e1dSBarry Smith   PetscFunctionReturn(0);
1566ce308e1dSBarry Smith }
1567ce308e1dSBarry Smith 
1568ce308e1dSBarry Smith /* ---------------------------------------------------------------------------------*/
1569ce308e1dSBarry Smith 
15709371c9d4SSatish Balay PetscErrorCode DMCreateMatrix_DA_1d_MPIAIJ(DM da, Mat J) {
157147c6ae99SBarry Smith   PetscInt               xs, nx, i, i1, slot, gxs, gnx;
15720298fd71SBarry Smith   PetscInt               m, dim, s, *cols = NULL, nc, *rows = NULL, col, cnt, l;
157347c6ae99SBarry Smith   PetscInt               istart, iend;
1574bff4a2f0SMatthew G. Knepley   DMBoundaryType         bx;
1575844bd0d7SStefano Zampini   ISLocalToGlobalMapping ltog, mltog;
157647c6ae99SBarry Smith 
157747c6ae99SBarry Smith   PetscFunctionBegin;
157847c6ae99SBarry Smith   /*
157947c6ae99SBarry Smith          nc - number of components per grid point
158047c6ae99SBarry Smith          col - number of colors needed in one direction for single component problem
158147c6ae99SBarry Smith 
158247c6ae99SBarry Smith   */
15839566063dSJacob Faibussowitsch   PetscCall(DMDAGetInfo(da, &dim, &m, NULL, NULL, NULL, NULL, NULL, &nc, &s, &bx, NULL, NULL, NULL));
1584*48a46eb9SPierre Jolivet   if (bx == DM_BOUNDARY_NONE) PetscCall(MatSetOption(J, MAT_SORTED_FULL, PETSC_TRUE));
158547c6ae99SBarry Smith   col = 2 * s + 1;
158647c6ae99SBarry Smith 
15879566063dSJacob Faibussowitsch   PetscCall(DMDAGetCorners(da, &xs, NULL, NULL, &nx, NULL, NULL));
15889566063dSJacob Faibussowitsch   PetscCall(DMDAGetGhostCorners(da, &gxs, NULL, NULL, &gnx, NULL, NULL));
158947c6ae99SBarry Smith 
15909566063dSJacob Faibussowitsch   PetscCall(MatSetBlockSize(J, nc));
15919566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJSetPreallocation(J, col * nc, NULL));
15929566063dSJacob Faibussowitsch   PetscCall(MatMPIAIJSetPreallocation(J, col * nc, NULL, col * nc, NULL));
159347c6ae99SBarry Smith 
15949566063dSJacob Faibussowitsch   PetscCall(DMGetLocalToGlobalMapping(da, &ltog));
15959566063dSJacob Faibussowitsch   PetscCall(MatGetLocalToGlobalMapping(J, &mltog, NULL));
1596*48a46eb9SPierre Jolivet   if (!mltog) PetscCall(MatSetLocalToGlobalMapping(J, ltog, ltog));
159747c6ae99SBarry Smith 
159847c6ae99SBarry Smith   /*
159947c6ae99SBarry Smith     For each node in the grid: we get the neighbors in the local (on processor ordering
160047c6ae99SBarry Smith     that includes the ghost points) then MatSetValuesLocal() maps those indices to the global
160147c6ae99SBarry Smith     PETSc ordering.
160247c6ae99SBarry Smith   */
1603fcfd50ebSBarry Smith   if (!da->prealloc_only) {
16049566063dSJacob Faibussowitsch     PetscCall(PetscMalloc2(nc, &rows, col * nc * nc, &cols));
160547c6ae99SBarry Smith     for (i = xs; i < xs + nx; i++) {
160647c6ae99SBarry Smith       istart = PetscMax(-s, gxs - i);
160747c6ae99SBarry Smith       iend   = PetscMin(s, gxs + gnx - i - 1);
160847c6ae99SBarry Smith       slot   = i - gxs;
160947c6ae99SBarry Smith 
161047c6ae99SBarry Smith       cnt = 0;
161147c6ae99SBarry Smith       for (i1 = istart; i1 < iend + 1; i1++) {
1612071fcb05SBarry Smith         cols[cnt++] = nc * (slot + i1);
1613071fcb05SBarry Smith         for (l = 1; l < nc; l++) {
16149371c9d4SSatish Balay           cols[cnt] = 1 + cols[cnt - 1];
16159371c9d4SSatish Balay           cnt++;
161647c6ae99SBarry Smith         }
161747c6ae99SBarry Smith       }
16189371c9d4SSatish Balay       rows[0] = nc * (slot);
16199371c9d4SSatish Balay       for (l = 1; l < nc; l++) rows[l] = 1 + rows[l - 1];
16209566063dSJacob Faibussowitsch       PetscCall(MatSetValuesLocal(J, nc, rows, cnt, cols, NULL, INSERT_VALUES));
162147c6ae99SBarry Smith     }
1622e7e92044SBarry Smith     /* do not copy values to GPU since they are all zero and not yet needed there */
16239566063dSJacob Faibussowitsch     PetscCall(MatBindToCPU(J, PETSC_TRUE));
16249566063dSJacob Faibussowitsch     PetscCall(MatAssemblyBegin(J, MAT_FINAL_ASSEMBLY));
16259566063dSJacob Faibussowitsch     PetscCall(MatAssemblyEnd(J, MAT_FINAL_ASSEMBLY));
1626*48a46eb9SPierre Jolivet     if (bx == DM_BOUNDARY_NONE) PetscCall(MatSetOption(J, MAT_SORTED_FULL, PETSC_FALSE));
16279566063dSJacob Faibussowitsch     PetscCall(MatBindToCPU(J, PETSC_FALSE));
16289566063dSJacob Faibussowitsch     PetscCall(MatSetOption(J, MAT_NEW_NONZERO_LOCATION_ERR, PETSC_TRUE));
16299566063dSJacob Faibussowitsch     PetscCall(PetscFree2(rows, cols));
1630ce308e1dSBarry Smith   }
163147c6ae99SBarry Smith   PetscFunctionReturn(0);
163247c6ae99SBarry Smith }
163347c6ae99SBarry Smith 
163419b08ed1SBarry Smith /* ---------------------------------------------------------------------------------*/
163519b08ed1SBarry Smith 
16369371c9d4SSatish Balay PetscErrorCode DMCreateMatrix_DA_1d_SeqAIJ_NoPreallocation(DM da, Mat J) {
163719b08ed1SBarry Smith   PetscInt               xs, nx, i, i1, slot, gxs, gnx;
163819b08ed1SBarry Smith   PetscInt               m, dim, s, *cols = NULL, nc, *rows = NULL, col, cnt, l;
163919b08ed1SBarry Smith   PetscInt               istart, iend;
164019b08ed1SBarry Smith   DMBoundaryType         bx;
164119b08ed1SBarry Smith   ISLocalToGlobalMapping ltog, mltog;
164219b08ed1SBarry Smith 
164319b08ed1SBarry Smith   PetscFunctionBegin;
164419b08ed1SBarry Smith   /*
164519b08ed1SBarry Smith          nc - number of components per grid point
164619b08ed1SBarry Smith          col - number of colors needed in one direction for single component problem
164719b08ed1SBarry Smith   */
16489566063dSJacob Faibussowitsch   PetscCall(DMDAGetInfo(da, &dim, &m, NULL, NULL, NULL, NULL, NULL, &nc, &s, &bx, NULL, NULL, NULL));
164919b08ed1SBarry Smith   col = 2 * s + 1;
165019b08ed1SBarry Smith 
16519566063dSJacob Faibussowitsch   PetscCall(DMDAGetCorners(da, &xs, NULL, NULL, &nx, NULL, NULL));
16529566063dSJacob Faibussowitsch   PetscCall(DMDAGetGhostCorners(da, &gxs, NULL, NULL, &gnx, NULL, NULL));
165319b08ed1SBarry Smith 
16549566063dSJacob Faibussowitsch   PetscCall(MatSetBlockSize(J, nc));
16559566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJSetTotalPreallocation(J, nx * nc * col * nc));
165619b08ed1SBarry Smith 
16579566063dSJacob Faibussowitsch   PetscCall(DMGetLocalToGlobalMapping(da, &ltog));
16589566063dSJacob Faibussowitsch   PetscCall(MatGetLocalToGlobalMapping(J, &mltog, NULL));
1659*48a46eb9SPierre Jolivet   if (!mltog) PetscCall(MatSetLocalToGlobalMapping(J, ltog, ltog));
166019b08ed1SBarry Smith 
166119b08ed1SBarry Smith   /*
166219b08ed1SBarry Smith     For each node in the grid: we get the neighbors in the local (on processor ordering
166319b08ed1SBarry Smith     that includes the ghost points) then MatSetValuesLocal() maps those indices to the global
166419b08ed1SBarry Smith     PETSc ordering.
166519b08ed1SBarry Smith   */
166619b08ed1SBarry Smith   if (!da->prealloc_only) {
16679566063dSJacob Faibussowitsch     PetscCall(PetscMalloc2(nc, &rows, col * nc * nc, &cols));
166819b08ed1SBarry Smith     for (i = xs; i < xs + nx; i++) {
166919b08ed1SBarry Smith       istart = PetscMax(-s, gxs - i);
167019b08ed1SBarry Smith       iend   = PetscMin(s, gxs + gnx - i - 1);
167119b08ed1SBarry Smith       slot   = i - gxs;
167219b08ed1SBarry Smith 
167319b08ed1SBarry Smith       cnt = 0;
167419b08ed1SBarry Smith       for (i1 = istart; i1 < iend + 1; i1++) {
167519b08ed1SBarry Smith         cols[cnt++] = nc * (slot + i1);
167619b08ed1SBarry Smith         for (l = 1; l < nc; l++) {
16779371c9d4SSatish Balay           cols[cnt] = 1 + cols[cnt - 1];
16789371c9d4SSatish Balay           cnt++;
167919b08ed1SBarry Smith         }
168019b08ed1SBarry Smith       }
16819371c9d4SSatish Balay       rows[0] = nc * (slot);
16829371c9d4SSatish Balay       for (l = 1; l < nc; l++) rows[l] = 1 + rows[l - 1];
16839566063dSJacob Faibussowitsch       PetscCall(MatSetValuesLocal(J, nc, rows, cnt, cols, NULL, INSERT_VALUES));
168419b08ed1SBarry Smith     }
168519b08ed1SBarry Smith     /* do not copy values to GPU since they are all zero and not yet needed there */
16869566063dSJacob Faibussowitsch     PetscCall(MatBindToCPU(J, PETSC_TRUE));
16879566063dSJacob Faibussowitsch     PetscCall(MatAssemblyBegin(J, MAT_FINAL_ASSEMBLY));
16889566063dSJacob Faibussowitsch     PetscCall(MatAssemblyEnd(J, MAT_FINAL_ASSEMBLY));
1689*48a46eb9SPierre Jolivet     if (bx == DM_BOUNDARY_NONE) PetscCall(MatSetOption(J, MAT_SORTED_FULL, PETSC_FALSE));
16909566063dSJacob Faibussowitsch     PetscCall(MatBindToCPU(J, PETSC_FALSE));
16919566063dSJacob Faibussowitsch     PetscCall(MatSetOption(J, MAT_NEW_NONZERO_LOCATION_ERR, PETSC_TRUE));
16929566063dSJacob Faibussowitsch     PetscCall(PetscFree2(rows, cols));
169319b08ed1SBarry Smith   }
16949566063dSJacob Faibussowitsch   PetscCall(MatSetOption(J, MAT_SORTED_FULL, PETSC_FALSE));
169519b08ed1SBarry Smith   PetscFunctionReturn(0);
169619b08ed1SBarry Smith }
169719b08ed1SBarry Smith 
16989371c9d4SSatish Balay PetscErrorCode DMCreateMatrix_DA_2d_MPIBAIJ(DM da, Mat J) {
169947c6ae99SBarry Smith   PetscInt               xs, ys, nx, ny, i, j, slot, gxs, gys, gnx, gny;
170047c6ae99SBarry Smith   PetscInt               m, n, dim, s, *cols, nc, col, cnt, *dnz, *onz;
170147c6ae99SBarry Smith   PetscInt               istart, iend, jstart, jend, ii, jj;
170247c6ae99SBarry Smith   MPI_Comm               comm;
170347c6ae99SBarry Smith   PetscScalar           *values;
1704bff4a2f0SMatthew G. Knepley   DMBoundaryType         bx, by;
1705aa219208SBarry Smith   DMDAStencilType        st;
170645b6f7e9SBarry Smith   ISLocalToGlobalMapping ltog;
170747c6ae99SBarry Smith 
170847c6ae99SBarry Smith   PetscFunctionBegin;
170947c6ae99SBarry Smith   /*
171047c6ae99SBarry Smith      nc - number of components per grid point
171147c6ae99SBarry Smith      col - number of colors needed in one direction for single component problem
171247c6ae99SBarry Smith   */
17139566063dSJacob Faibussowitsch   PetscCall(DMDAGetInfo(da, &dim, &m, &n, NULL, NULL, NULL, NULL, &nc, &s, &bx, &by, NULL, &st));
171447c6ae99SBarry Smith   col = 2 * s + 1;
171547c6ae99SBarry Smith 
17169566063dSJacob Faibussowitsch   PetscCall(DMDAGetCorners(da, &xs, &ys, NULL, &nx, &ny, NULL));
17179566063dSJacob Faibussowitsch   PetscCall(DMDAGetGhostCorners(da, &gxs, &gys, NULL, &gnx, &gny, NULL));
17189566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)da, &comm));
171947c6ae99SBarry Smith 
17209566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(col * col * nc * nc, &cols));
172147c6ae99SBarry Smith 
17229566063dSJacob Faibussowitsch   PetscCall(DMGetLocalToGlobalMapping(da, &ltog));
172347c6ae99SBarry Smith 
172447c6ae99SBarry Smith   /* determine the matrix preallocation information */
1725d0609cedSBarry Smith   MatPreallocateBegin(comm, nx * ny, nx * ny, dnz, onz);
172647c6ae99SBarry Smith   for (i = xs; i < xs + nx; i++) {
1727bff4a2f0SMatthew G. Knepley     istart = (bx == DM_BOUNDARY_PERIODIC) ? -s : (PetscMax(-s, -i));
1728bff4a2f0SMatthew G. Knepley     iend   = (bx == DM_BOUNDARY_PERIODIC) ? s : (PetscMin(s, m - i - 1));
172947c6ae99SBarry Smith     for (j = ys; j < ys + ny; j++) {
1730bff4a2f0SMatthew G. Knepley       jstart = (by == DM_BOUNDARY_PERIODIC) ? -s : (PetscMax(-s, -j));
1731bff4a2f0SMatthew G. Knepley       jend   = (by == DM_BOUNDARY_PERIODIC) ? s : (PetscMin(s, n - j - 1));
173247c6ae99SBarry Smith       slot   = i - gxs + gnx * (j - gys);
173347c6ae99SBarry Smith 
173447c6ae99SBarry Smith       /* Find block columns in block row */
173547c6ae99SBarry Smith       cnt = 0;
173647c6ae99SBarry Smith       for (ii = istart; ii < iend + 1; ii++) {
173747c6ae99SBarry Smith         for (jj = jstart; jj < jend + 1; jj++) {
1738aa219208SBarry Smith           if (st == DMDA_STENCIL_BOX || !ii || !jj) { /* BOX or on the STAR */
173947c6ae99SBarry Smith             cols[cnt++] = slot + ii + gnx * jj;
174047c6ae99SBarry Smith           }
174147c6ae99SBarry Smith         }
174247c6ae99SBarry Smith       }
17439566063dSJacob Faibussowitsch       PetscCall(MatPreallocateSetLocalBlock(ltog, 1, &slot, ltog, cnt, cols, dnz, onz));
174447c6ae99SBarry Smith     }
174547c6ae99SBarry Smith   }
17469566063dSJacob Faibussowitsch   PetscCall(MatSeqBAIJSetPreallocation(J, nc, 0, dnz));
17479566063dSJacob Faibussowitsch   PetscCall(MatMPIBAIJSetPreallocation(J, nc, 0, dnz, 0, onz));
1748d0609cedSBarry Smith   MatPreallocateEnd(dnz, onz);
174947c6ae99SBarry Smith 
17509566063dSJacob Faibussowitsch   PetscCall(MatSetLocalToGlobalMapping(J, ltog, ltog));
175147c6ae99SBarry Smith 
175247c6ae99SBarry Smith   /*
175347c6ae99SBarry Smith     For each node in the grid: we get the neighbors in the local (on processor ordering
175447c6ae99SBarry Smith     that includes the ghost points) then MatSetValuesLocal() maps those indices to the global
175547c6ae99SBarry Smith     PETSc ordering.
175647c6ae99SBarry Smith   */
1757fcfd50ebSBarry Smith   if (!da->prealloc_only) {
17589566063dSJacob Faibussowitsch     PetscCall(PetscCalloc1(col * col * nc * nc, &values));
175947c6ae99SBarry Smith     for (i = xs; i < xs + nx; i++) {
1760bff4a2f0SMatthew G. Knepley       istart = (bx == DM_BOUNDARY_PERIODIC) ? -s : (PetscMax(-s, -i));
1761bff4a2f0SMatthew G. Knepley       iend   = (bx == DM_BOUNDARY_PERIODIC) ? s : (PetscMin(s, m - i - 1));
176247c6ae99SBarry Smith       for (j = ys; j < ys + ny; j++) {
1763bff4a2f0SMatthew G. Knepley         jstart = (by == DM_BOUNDARY_PERIODIC) ? -s : (PetscMax(-s, -j));
1764bff4a2f0SMatthew G. Knepley         jend   = (by == DM_BOUNDARY_PERIODIC) ? s : (PetscMin(s, n - j - 1));
176547c6ae99SBarry Smith         slot   = i - gxs + gnx * (j - gys);
176647c6ae99SBarry Smith         cnt    = 0;
176747c6ae99SBarry Smith         for (ii = istart; ii < iend + 1; ii++) {
176847c6ae99SBarry Smith           for (jj = jstart; jj < jend + 1; jj++) {
1769aa219208SBarry Smith             if (st == DMDA_STENCIL_BOX || !ii || !jj) { /* BOX or on the STAR */
177047c6ae99SBarry Smith               cols[cnt++] = slot + ii + gnx * jj;
177147c6ae99SBarry Smith             }
177247c6ae99SBarry Smith           }
177347c6ae99SBarry Smith         }
17749566063dSJacob Faibussowitsch         PetscCall(MatSetValuesBlockedLocal(J, 1, &slot, cnt, cols, values, INSERT_VALUES));
177547c6ae99SBarry Smith       }
177647c6ae99SBarry Smith     }
17779566063dSJacob Faibussowitsch     PetscCall(PetscFree(values));
1778e7e92044SBarry Smith     /* do not copy values to GPU since they are all zero and not yet needed there */
17799566063dSJacob Faibussowitsch     PetscCall(MatBindToCPU(J, PETSC_TRUE));
17809566063dSJacob Faibussowitsch     PetscCall(MatAssemblyBegin(J, MAT_FINAL_ASSEMBLY));
17819566063dSJacob Faibussowitsch     PetscCall(MatAssemblyEnd(J, MAT_FINAL_ASSEMBLY));
17829566063dSJacob Faibussowitsch     PetscCall(MatBindToCPU(J, PETSC_FALSE));
17839566063dSJacob Faibussowitsch     PetscCall(MatSetOption(J, MAT_NEW_NONZERO_LOCATION_ERR, PETSC_TRUE));
178447c6ae99SBarry Smith   }
17859566063dSJacob Faibussowitsch   PetscCall(PetscFree(cols));
178647c6ae99SBarry Smith   PetscFunctionReturn(0);
178747c6ae99SBarry Smith }
178847c6ae99SBarry Smith 
17899371c9d4SSatish Balay PetscErrorCode DMCreateMatrix_DA_3d_MPIBAIJ(DM da, Mat J) {
179047c6ae99SBarry Smith   PetscInt               xs, ys, nx, ny, i, j, slot, gxs, gys, gnx, gny;
179147c6ae99SBarry Smith   PetscInt               m, n, dim, s, *cols, k, nc, col, cnt, p, *dnz, *onz;
179247c6ae99SBarry Smith   PetscInt               istart, iend, jstart, jend, kstart, kend, zs, nz, gzs, gnz, ii, jj, kk;
179347c6ae99SBarry Smith   MPI_Comm               comm;
179447c6ae99SBarry Smith   PetscScalar           *values;
1795bff4a2f0SMatthew G. Knepley   DMBoundaryType         bx, by, bz;
1796aa219208SBarry Smith   DMDAStencilType        st;
179745b6f7e9SBarry Smith   ISLocalToGlobalMapping ltog;
179847c6ae99SBarry Smith 
179947c6ae99SBarry Smith   PetscFunctionBegin;
180047c6ae99SBarry Smith   /*
180147c6ae99SBarry Smith          nc - number of components per grid point
180247c6ae99SBarry Smith          col - number of colors needed in one direction for single component problem
180347c6ae99SBarry Smith 
180447c6ae99SBarry Smith   */
18059566063dSJacob Faibussowitsch   PetscCall(DMDAGetInfo(da, &dim, &m, &n, &p, NULL, NULL, NULL, &nc, &s, &bx, &by, &bz, &st));
180647c6ae99SBarry Smith   col = 2 * s + 1;
180747c6ae99SBarry Smith 
18089566063dSJacob Faibussowitsch   PetscCall(DMDAGetCorners(da, &xs, &ys, &zs, &nx, &ny, &nz));
18099566063dSJacob Faibussowitsch   PetscCall(DMDAGetGhostCorners(da, &gxs, &gys, &gzs, &gnx, &gny, &gnz));
18109566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)da, &comm));
181147c6ae99SBarry Smith 
18129566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(col * col * col, &cols));
181347c6ae99SBarry Smith 
18149566063dSJacob Faibussowitsch   PetscCall(DMGetLocalToGlobalMapping(da, &ltog));
181547c6ae99SBarry Smith 
181647c6ae99SBarry Smith   /* determine the matrix preallocation information */
1817d0609cedSBarry Smith   MatPreallocateBegin(comm, nx * ny * nz, nx * ny * nz, dnz, onz);
181847c6ae99SBarry Smith   for (i = xs; i < xs + nx; i++) {
1819bff4a2f0SMatthew G. Knepley     istart = (bx == DM_BOUNDARY_PERIODIC) ? -s : (PetscMax(-s, -i));
1820bff4a2f0SMatthew G. Knepley     iend   = (bx == DM_BOUNDARY_PERIODIC) ? s : (PetscMin(s, m - i - 1));
182147c6ae99SBarry Smith     for (j = ys; j < ys + ny; j++) {
1822bff4a2f0SMatthew G. Knepley       jstart = (by == DM_BOUNDARY_PERIODIC) ? -s : (PetscMax(-s, -j));
1823bff4a2f0SMatthew G. Knepley       jend   = (by == DM_BOUNDARY_PERIODIC) ? s : (PetscMin(s, n - j - 1));
182447c6ae99SBarry Smith       for (k = zs; k < zs + nz; k++) {
1825bff4a2f0SMatthew G. Knepley         kstart = (bz == DM_BOUNDARY_PERIODIC) ? -s : (PetscMax(-s, -k));
1826bff4a2f0SMatthew G. Knepley         kend   = (bz == DM_BOUNDARY_PERIODIC) ? s : (PetscMin(s, p - k - 1));
182747c6ae99SBarry Smith 
182847c6ae99SBarry Smith         slot = i - gxs + gnx * (j - gys) + gnx * gny * (k - gzs);
182947c6ae99SBarry Smith 
183047c6ae99SBarry Smith         /* Find block columns in block row */
183147c6ae99SBarry Smith         cnt = 0;
183247c6ae99SBarry Smith         for (ii = istart; ii < iend + 1; ii++) {
183347c6ae99SBarry Smith           for (jj = jstart; jj < jend + 1; jj++) {
183447c6ae99SBarry Smith             for (kk = kstart; kk < kend + 1; kk++) {
1835aa219208SBarry Smith               if ((st == DMDA_STENCIL_BOX) || ((!ii && !jj) || (!jj && !kk) || (!ii && !kk))) { /* entries on star*/
183647c6ae99SBarry Smith                 cols[cnt++] = slot + ii + gnx * jj + gnx * gny * kk;
183747c6ae99SBarry Smith               }
183847c6ae99SBarry Smith             }
183947c6ae99SBarry Smith           }
184047c6ae99SBarry Smith         }
18419566063dSJacob Faibussowitsch         PetscCall(MatPreallocateSetLocalBlock(ltog, 1, &slot, ltog, cnt, cols, dnz, onz));
184247c6ae99SBarry Smith       }
184347c6ae99SBarry Smith     }
184447c6ae99SBarry Smith   }
18459566063dSJacob Faibussowitsch   PetscCall(MatSeqBAIJSetPreallocation(J, nc, 0, dnz));
18469566063dSJacob Faibussowitsch   PetscCall(MatMPIBAIJSetPreallocation(J, nc, 0, dnz, 0, onz));
1847d0609cedSBarry Smith   MatPreallocateEnd(dnz, onz);
184847c6ae99SBarry Smith 
18499566063dSJacob Faibussowitsch   PetscCall(MatSetLocalToGlobalMapping(J, ltog, ltog));
185047c6ae99SBarry Smith 
185147c6ae99SBarry Smith   /*
185247c6ae99SBarry Smith     For each node in the grid: we get the neighbors in the local (on processor ordering
185347c6ae99SBarry Smith     that includes the ghost points) then MatSetValuesLocal() maps those indices to the global
185447c6ae99SBarry Smith     PETSc ordering.
185547c6ae99SBarry Smith   */
1856fcfd50ebSBarry Smith   if (!da->prealloc_only) {
18579566063dSJacob Faibussowitsch     PetscCall(PetscCalloc1(col * col * col * nc * nc, &values));
185847c6ae99SBarry Smith     for (i = xs; i < xs + nx; i++) {
1859bff4a2f0SMatthew G. Knepley       istart = (bx == DM_BOUNDARY_PERIODIC) ? -s : (PetscMax(-s, -i));
1860bff4a2f0SMatthew G. Knepley       iend   = (bx == DM_BOUNDARY_PERIODIC) ? s : (PetscMin(s, m - i - 1));
186147c6ae99SBarry Smith       for (j = ys; j < ys + ny; j++) {
1862bff4a2f0SMatthew G. Knepley         jstart = (by == DM_BOUNDARY_PERIODIC) ? -s : (PetscMax(-s, -j));
1863bff4a2f0SMatthew G. Knepley         jend   = (by == DM_BOUNDARY_PERIODIC) ? s : (PetscMin(s, n - j - 1));
186447c6ae99SBarry Smith         for (k = zs; k < zs + nz; k++) {
1865bff4a2f0SMatthew G. Knepley           kstart = (bz == DM_BOUNDARY_PERIODIC) ? -s : (PetscMax(-s, -k));
1866bff4a2f0SMatthew G. Knepley           kend   = (bz == DM_BOUNDARY_PERIODIC) ? s : (PetscMin(s, p - k - 1));
186747c6ae99SBarry Smith 
186847c6ae99SBarry Smith           slot = i - gxs + gnx * (j - gys) + gnx * gny * (k - gzs);
186947c6ae99SBarry Smith 
187047c6ae99SBarry Smith           cnt = 0;
187147c6ae99SBarry Smith           for (ii = istart; ii < iend + 1; ii++) {
187247c6ae99SBarry Smith             for (jj = jstart; jj < jend + 1; jj++) {
187347c6ae99SBarry Smith               for (kk = kstart; kk < kend + 1; kk++) {
1874aa219208SBarry Smith                 if ((st == DMDA_STENCIL_BOX) || ((!ii && !jj) || (!jj && !kk) || (!ii && !kk))) { /* entries on star*/
187547c6ae99SBarry Smith                   cols[cnt++] = slot + ii + gnx * jj + gnx * gny * kk;
187647c6ae99SBarry Smith                 }
187747c6ae99SBarry Smith               }
187847c6ae99SBarry Smith             }
187947c6ae99SBarry Smith           }
18809566063dSJacob Faibussowitsch           PetscCall(MatSetValuesBlockedLocal(J, 1, &slot, cnt, cols, values, INSERT_VALUES));
188147c6ae99SBarry Smith         }
188247c6ae99SBarry Smith       }
188347c6ae99SBarry Smith     }
18849566063dSJacob Faibussowitsch     PetscCall(PetscFree(values));
1885e7e92044SBarry Smith     /* do not copy values to GPU since they are all zero and not yet needed there */
18869566063dSJacob Faibussowitsch     PetscCall(MatBindToCPU(J, PETSC_TRUE));
18879566063dSJacob Faibussowitsch     PetscCall(MatAssemblyBegin(J, MAT_FINAL_ASSEMBLY));
18889566063dSJacob Faibussowitsch     PetscCall(MatAssemblyEnd(J, MAT_FINAL_ASSEMBLY));
18899566063dSJacob Faibussowitsch     PetscCall(MatBindToCPU(J, PETSC_FALSE));
18909566063dSJacob Faibussowitsch     PetscCall(MatSetOption(J, MAT_NEW_NONZERO_LOCATION_ERR, PETSC_TRUE));
189147c6ae99SBarry Smith   }
18929566063dSJacob Faibussowitsch   PetscCall(PetscFree(cols));
189347c6ae99SBarry Smith   PetscFunctionReturn(0);
189447c6ae99SBarry Smith }
189547c6ae99SBarry Smith 
189647c6ae99SBarry Smith /*
189747c6ae99SBarry Smith   This helper is for of SBAIJ preallocation, to discard the lower-triangular values which are difficult to
189847c6ae99SBarry Smith   identify in the local ordering with periodic domain.
189947c6ae99SBarry Smith */
19009371c9d4SSatish Balay static PetscErrorCode L2GFilterUpperTriangular(ISLocalToGlobalMapping ltog, PetscInt *row, PetscInt *cnt, PetscInt col[]) {
190147c6ae99SBarry Smith   PetscInt i, n;
190247c6ae99SBarry Smith 
190347c6ae99SBarry Smith   PetscFunctionBegin;
19049566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingApplyBlock(ltog, 1, row, row));
19059566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingApplyBlock(ltog, *cnt, col, col));
190647c6ae99SBarry Smith   for (i = 0, n = 0; i < *cnt; i++) {
190747c6ae99SBarry Smith     if (col[i] >= *row) col[n++] = col[i];
190847c6ae99SBarry Smith   }
190947c6ae99SBarry Smith   *cnt = n;
191047c6ae99SBarry Smith   PetscFunctionReturn(0);
191147c6ae99SBarry Smith }
191247c6ae99SBarry Smith 
19139371c9d4SSatish Balay PetscErrorCode DMCreateMatrix_DA_2d_MPISBAIJ(DM da, Mat J) {
191447c6ae99SBarry Smith   PetscInt               xs, ys, nx, ny, i, j, slot, gxs, gys, gnx, gny;
191547c6ae99SBarry Smith   PetscInt               m, n, dim, s, *cols, nc, col, cnt, *dnz, *onz;
191647c6ae99SBarry Smith   PetscInt               istart, iend, jstart, jend, ii, jj;
191747c6ae99SBarry Smith   MPI_Comm               comm;
191847c6ae99SBarry Smith   PetscScalar           *values;
1919bff4a2f0SMatthew G. Knepley   DMBoundaryType         bx, by;
1920aa219208SBarry Smith   DMDAStencilType        st;
192145b6f7e9SBarry Smith   ISLocalToGlobalMapping ltog;
192247c6ae99SBarry Smith 
192347c6ae99SBarry Smith   PetscFunctionBegin;
192447c6ae99SBarry Smith   /*
192547c6ae99SBarry Smith      nc - number of components per grid point
192647c6ae99SBarry Smith      col - number of colors needed in one direction for single component problem
192747c6ae99SBarry Smith   */
19289566063dSJacob Faibussowitsch   PetscCall(DMDAGetInfo(da, &dim, &m, &n, NULL, NULL, NULL, NULL, &nc, &s, &bx, &by, NULL, &st));
192947c6ae99SBarry Smith   col = 2 * s + 1;
193047c6ae99SBarry Smith 
19319566063dSJacob Faibussowitsch   PetscCall(DMDAGetCorners(da, &xs, &ys, NULL, &nx, &ny, NULL));
19329566063dSJacob Faibussowitsch   PetscCall(DMDAGetGhostCorners(da, &gxs, &gys, NULL, &gnx, &gny, NULL));
19339566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)da, &comm));
193447c6ae99SBarry Smith 
19359566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(col * col * nc * nc, &cols));
193647c6ae99SBarry Smith 
19379566063dSJacob Faibussowitsch   PetscCall(DMGetLocalToGlobalMapping(da, &ltog));
193847c6ae99SBarry Smith 
193947c6ae99SBarry Smith   /* determine the matrix preallocation information */
1940d0609cedSBarry Smith   MatPreallocateBegin(comm, nx * ny, nx * ny, dnz, onz);
194147c6ae99SBarry Smith   for (i = xs; i < xs + nx; i++) {
1942bff4a2f0SMatthew G. Knepley     istart = (bx == DM_BOUNDARY_PERIODIC) ? -s : (PetscMax(-s, -i));
1943bff4a2f0SMatthew G. Knepley     iend   = (bx == DM_BOUNDARY_PERIODIC) ? s : (PetscMin(s, m - i - 1));
194447c6ae99SBarry Smith     for (j = ys; j < ys + ny; j++) {
1945bff4a2f0SMatthew G. Knepley       jstart = (by == DM_BOUNDARY_PERIODIC) ? -s : (PetscMax(-s, -j));
1946bff4a2f0SMatthew G. Knepley       jend   = (by == DM_BOUNDARY_PERIODIC) ? s : (PetscMin(s, n - j - 1));
194747c6ae99SBarry Smith       slot   = i - gxs + gnx * (j - gys);
194847c6ae99SBarry Smith 
194947c6ae99SBarry Smith       /* Find block columns in block row */
195047c6ae99SBarry Smith       cnt = 0;
195147c6ae99SBarry Smith       for (ii = istart; ii < iend + 1; ii++) {
195247c6ae99SBarry Smith         for (jj = jstart; jj < jend + 1; jj++) {
19539371c9d4SSatish Balay           if (st == DMDA_STENCIL_BOX || !ii || !jj) { cols[cnt++] = slot + ii + gnx * jj; }
195447c6ae99SBarry Smith         }
195547c6ae99SBarry Smith       }
19569566063dSJacob Faibussowitsch       PetscCall(L2GFilterUpperTriangular(ltog, &slot, &cnt, cols));
19579566063dSJacob Faibussowitsch       PetscCall(MatPreallocateSymmetricSetBlock(slot, cnt, cols, dnz, onz));
195847c6ae99SBarry Smith     }
195947c6ae99SBarry Smith   }
19609566063dSJacob Faibussowitsch   PetscCall(MatSeqSBAIJSetPreallocation(J, nc, 0, dnz));
19619566063dSJacob Faibussowitsch   PetscCall(MatMPISBAIJSetPreallocation(J, nc, 0, dnz, 0, onz));
1962d0609cedSBarry Smith   MatPreallocateEnd(dnz, onz);
196347c6ae99SBarry Smith 
19649566063dSJacob Faibussowitsch   PetscCall(MatSetLocalToGlobalMapping(J, ltog, ltog));
196547c6ae99SBarry Smith 
196647c6ae99SBarry Smith   /*
196747c6ae99SBarry Smith     For each node in the grid: we get the neighbors in the local (on processor ordering
196847c6ae99SBarry Smith     that includes the ghost points) then MatSetValuesLocal() maps those indices to the global
196947c6ae99SBarry Smith     PETSc ordering.
197047c6ae99SBarry Smith   */
1971fcfd50ebSBarry Smith   if (!da->prealloc_only) {
19729566063dSJacob Faibussowitsch     PetscCall(PetscCalloc1(col * col * nc * nc, &values));
197347c6ae99SBarry Smith     for (i = xs; i < xs + nx; i++) {
1974bff4a2f0SMatthew G. Knepley       istart = (bx == DM_BOUNDARY_PERIODIC) ? -s : (PetscMax(-s, -i));
1975bff4a2f0SMatthew G. Knepley       iend   = (bx == DM_BOUNDARY_PERIODIC) ? s : (PetscMin(s, m - i - 1));
197647c6ae99SBarry Smith       for (j = ys; j < ys + ny; j++) {
1977bff4a2f0SMatthew G. Knepley         jstart = (by == DM_BOUNDARY_PERIODIC) ? -s : (PetscMax(-s, -j));
1978bff4a2f0SMatthew G. Knepley         jend   = (by == DM_BOUNDARY_PERIODIC) ? s : (PetscMin(s, n - j - 1));
197947c6ae99SBarry Smith         slot   = i - gxs + gnx * (j - gys);
198047c6ae99SBarry Smith 
198147c6ae99SBarry Smith         /* Find block columns in block row */
198247c6ae99SBarry Smith         cnt = 0;
198347c6ae99SBarry Smith         for (ii = istart; ii < iend + 1; ii++) {
198447c6ae99SBarry Smith           for (jj = jstart; jj < jend + 1; jj++) {
19859371c9d4SSatish Balay             if (st == DMDA_STENCIL_BOX || !ii || !jj) { cols[cnt++] = slot + ii + gnx * jj; }
198647c6ae99SBarry Smith           }
198747c6ae99SBarry Smith         }
19889566063dSJacob Faibussowitsch         PetscCall(L2GFilterUpperTriangular(ltog, &slot, &cnt, cols));
19899566063dSJacob Faibussowitsch         PetscCall(MatSetValuesBlocked(J, 1, &slot, cnt, cols, values, INSERT_VALUES));
199047c6ae99SBarry Smith       }
199147c6ae99SBarry Smith     }
19929566063dSJacob Faibussowitsch     PetscCall(PetscFree(values));
1993e7e92044SBarry Smith     /* do not copy values to GPU since they are all zero and not yet needed there */
19949566063dSJacob Faibussowitsch     PetscCall(MatBindToCPU(J, PETSC_TRUE));
19959566063dSJacob Faibussowitsch     PetscCall(MatAssemblyBegin(J, MAT_FINAL_ASSEMBLY));
19969566063dSJacob Faibussowitsch     PetscCall(MatAssemblyEnd(J, MAT_FINAL_ASSEMBLY));
19979566063dSJacob Faibussowitsch     PetscCall(MatBindToCPU(J, PETSC_FALSE));
19989566063dSJacob Faibussowitsch     PetscCall(MatSetOption(J, MAT_NEW_NONZERO_LOCATION_ERR, PETSC_TRUE));
199947c6ae99SBarry Smith   }
20009566063dSJacob Faibussowitsch   PetscCall(PetscFree(cols));
200147c6ae99SBarry Smith   PetscFunctionReturn(0);
200247c6ae99SBarry Smith }
200347c6ae99SBarry Smith 
20049371c9d4SSatish Balay PetscErrorCode DMCreateMatrix_DA_3d_MPISBAIJ(DM da, Mat J) {
200547c6ae99SBarry Smith   PetscInt               xs, ys, nx, ny, i, j, slot, gxs, gys, gnx, gny;
200647c6ae99SBarry Smith   PetscInt               m, n, dim, s, *cols, k, nc, col, cnt, p, *dnz, *onz;
200747c6ae99SBarry Smith   PetscInt               istart, iend, jstart, jend, kstart, kend, zs, nz, gzs, gnz, ii, jj, kk;
200847c6ae99SBarry Smith   MPI_Comm               comm;
200947c6ae99SBarry Smith   PetscScalar           *values;
2010bff4a2f0SMatthew G. Knepley   DMBoundaryType         bx, by, bz;
2011aa219208SBarry Smith   DMDAStencilType        st;
201245b6f7e9SBarry Smith   ISLocalToGlobalMapping ltog;
201347c6ae99SBarry Smith 
201447c6ae99SBarry Smith   PetscFunctionBegin;
201547c6ae99SBarry Smith   /*
201647c6ae99SBarry Smith      nc - number of components per grid point
201747c6ae99SBarry Smith      col - number of colors needed in one direction for single component problem
201847c6ae99SBarry Smith   */
20199566063dSJacob Faibussowitsch   PetscCall(DMDAGetInfo(da, &dim, &m, &n, &p, NULL, NULL, NULL, &nc, &s, &bx, &by, &bz, &st));
202047c6ae99SBarry Smith   col = 2 * s + 1;
202147c6ae99SBarry Smith 
20229566063dSJacob Faibussowitsch   PetscCall(DMDAGetCorners(da, &xs, &ys, &zs, &nx, &ny, &nz));
20239566063dSJacob Faibussowitsch   PetscCall(DMDAGetGhostCorners(da, &gxs, &gys, &gzs, &gnx, &gny, &gnz));
20249566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)da, &comm));
202547c6ae99SBarry Smith 
202647c6ae99SBarry Smith   /* create the matrix */
20279566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(col * col * col, &cols));
202847c6ae99SBarry Smith 
20299566063dSJacob Faibussowitsch   PetscCall(DMGetLocalToGlobalMapping(da, &ltog));
203047c6ae99SBarry Smith 
203147c6ae99SBarry Smith   /* determine the matrix preallocation information */
2032d0609cedSBarry Smith   MatPreallocateBegin(comm, nx * ny * nz, nx * ny * nz, dnz, onz);
203347c6ae99SBarry Smith   for (i = xs; i < xs + nx; i++) {
2034bff4a2f0SMatthew G. Knepley     istart = (bx == DM_BOUNDARY_PERIODIC) ? -s : (PetscMax(-s, -i));
2035bff4a2f0SMatthew G. Knepley     iend   = (bx == DM_BOUNDARY_PERIODIC) ? s : (PetscMin(s, m - i - 1));
203647c6ae99SBarry Smith     for (j = ys; j < ys + ny; j++) {
2037bff4a2f0SMatthew G. Knepley       jstart = (by == DM_BOUNDARY_PERIODIC) ? -s : (PetscMax(-s, -j));
2038bff4a2f0SMatthew G. Knepley       jend   = (by == DM_BOUNDARY_PERIODIC) ? s : (PetscMin(s, n - j - 1));
203947c6ae99SBarry Smith       for (k = zs; k < zs + nz; k++) {
2040bff4a2f0SMatthew G. Knepley         kstart = (bz == DM_BOUNDARY_PERIODIC) ? -s : (PetscMax(-s, -k));
2041bff4a2f0SMatthew G. Knepley         kend   = (bz == DM_BOUNDARY_PERIODIC) ? s : (PetscMin(s, p - k - 1));
204247c6ae99SBarry Smith 
204347c6ae99SBarry Smith         slot = i - gxs + gnx * (j - gys) + gnx * gny * (k - gzs);
204447c6ae99SBarry Smith 
204547c6ae99SBarry Smith         /* Find block columns in block row */
204647c6ae99SBarry Smith         cnt = 0;
204747c6ae99SBarry Smith         for (ii = istart; ii < iend + 1; ii++) {
204847c6ae99SBarry Smith           for (jj = jstart; jj < jend + 1; jj++) {
204947c6ae99SBarry Smith             for (kk = kstart; kk < kend + 1; kk++) {
20509371c9d4SSatish Balay               if ((st == DMDA_STENCIL_BOX) || (!ii && !jj) || (!jj && !kk) || (!ii && !kk)) { cols[cnt++] = slot + ii + gnx * jj + gnx * gny * kk; }
205147c6ae99SBarry Smith             }
205247c6ae99SBarry Smith           }
205347c6ae99SBarry Smith         }
20549566063dSJacob Faibussowitsch         PetscCall(L2GFilterUpperTriangular(ltog, &slot, &cnt, cols));
20559566063dSJacob Faibussowitsch         PetscCall(MatPreallocateSymmetricSetBlock(slot, cnt, cols, dnz, onz));
205647c6ae99SBarry Smith       }
205747c6ae99SBarry Smith     }
205847c6ae99SBarry Smith   }
20599566063dSJacob Faibussowitsch   PetscCall(MatSeqSBAIJSetPreallocation(J, nc, 0, dnz));
20609566063dSJacob Faibussowitsch   PetscCall(MatMPISBAIJSetPreallocation(J, nc, 0, dnz, 0, onz));
2061d0609cedSBarry Smith   MatPreallocateEnd(dnz, onz);
206247c6ae99SBarry Smith 
20639566063dSJacob Faibussowitsch   PetscCall(MatSetLocalToGlobalMapping(J, ltog, ltog));
206447c6ae99SBarry Smith 
206547c6ae99SBarry Smith   /*
206647c6ae99SBarry Smith     For each node in the grid: we get the neighbors in the local (on processor ordering
206747c6ae99SBarry Smith     that includes the ghost points) then MatSetValuesLocal() maps those indices to the global
206847c6ae99SBarry Smith     PETSc ordering.
206947c6ae99SBarry Smith   */
2070fcfd50ebSBarry Smith   if (!da->prealloc_only) {
20719566063dSJacob Faibussowitsch     PetscCall(PetscCalloc1(col * col * col * nc * nc, &values));
207247c6ae99SBarry Smith     for (i = xs; i < xs + nx; i++) {
2073bff4a2f0SMatthew G. Knepley       istart = (bx == DM_BOUNDARY_PERIODIC) ? -s : (PetscMax(-s, -i));
2074bff4a2f0SMatthew G. Knepley       iend   = (bx == DM_BOUNDARY_PERIODIC) ? s : (PetscMin(s, m - i - 1));
207547c6ae99SBarry Smith       for (j = ys; j < ys + ny; j++) {
2076bff4a2f0SMatthew G. Knepley         jstart = (by == DM_BOUNDARY_PERIODIC) ? -s : (PetscMax(-s, -j));
2077bff4a2f0SMatthew G. Knepley         jend   = (by == DM_BOUNDARY_PERIODIC) ? s : (PetscMin(s, n - j - 1));
207847c6ae99SBarry Smith         for (k = zs; k < zs + nz; k++) {
2079bff4a2f0SMatthew G. Knepley           kstart = (bz == DM_BOUNDARY_PERIODIC) ? -s : (PetscMax(-s, -k));
2080bff4a2f0SMatthew G. Knepley           kend   = (bz == DM_BOUNDARY_PERIODIC) ? s : (PetscMin(s, p - k - 1));
208147c6ae99SBarry Smith 
208247c6ae99SBarry Smith           slot = i - gxs + gnx * (j - gys) + gnx * gny * (k - gzs);
208347c6ae99SBarry Smith 
208447c6ae99SBarry Smith           cnt = 0;
208547c6ae99SBarry Smith           for (ii = istart; ii < iend + 1; ii++) {
208647c6ae99SBarry Smith             for (jj = jstart; jj < jend + 1; jj++) {
208747c6ae99SBarry Smith               for (kk = kstart; kk < kend + 1; kk++) {
20889371c9d4SSatish Balay                 if ((st == DMDA_STENCIL_BOX) || (!ii && !jj) || (!jj && !kk) || (!ii && !kk)) { cols[cnt++] = slot + ii + gnx * jj + gnx * gny * kk; }
208947c6ae99SBarry Smith               }
209047c6ae99SBarry Smith             }
209147c6ae99SBarry Smith           }
20929566063dSJacob Faibussowitsch           PetscCall(L2GFilterUpperTriangular(ltog, &slot, &cnt, cols));
20939566063dSJacob Faibussowitsch           PetscCall(MatSetValuesBlocked(J, 1, &slot, cnt, cols, values, INSERT_VALUES));
209447c6ae99SBarry Smith         }
209547c6ae99SBarry Smith       }
209647c6ae99SBarry Smith     }
20979566063dSJacob Faibussowitsch     PetscCall(PetscFree(values));
2098e7e92044SBarry Smith     /* do not copy values to GPU since they are all zero and not yet needed there */
20999566063dSJacob Faibussowitsch     PetscCall(MatBindToCPU(J, PETSC_TRUE));
21009566063dSJacob Faibussowitsch     PetscCall(MatAssemblyBegin(J, MAT_FINAL_ASSEMBLY));
21019566063dSJacob Faibussowitsch     PetscCall(MatAssemblyEnd(J, MAT_FINAL_ASSEMBLY));
21029566063dSJacob Faibussowitsch     PetscCall(MatBindToCPU(J, PETSC_FALSE));
21039566063dSJacob Faibussowitsch     PetscCall(MatSetOption(J, MAT_NEW_NONZERO_LOCATION_ERR, PETSC_TRUE));
210447c6ae99SBarry Smith   }
21059566063dSJacob Faibussowitsch   PetscCall(PetscFree(cols));
210647c6ae99SBarry Smith   PetscFunctionReturn(0);
210747c6ae99SBarry Smith }
210847c6ae99SBarry Smith 
210947c6ae99SBarry Smith /* ---------------------------------------------------------------------------------*/
211047c6ae99SBarry Smith 
21119371c9d4SSatish Balay PetscErrorCode DMCreateMatrix_DA_3d_MPIAIJ_Fill(DM da, Mat J) {
211247c6ae99SBarry Smith   PetscInt               xs, ys, nx, ny, i, j, slot, gxs, gys, gnx, gny;
2113c0ab637bSBarry Smith   PetscInt               m, n, dim, s, *cols, k, nc, row, col, cnt, maxcnt = 0, l, p, *dnz, *onz;
2114c1154cd5SBarry Smith   PetscInt               istart, iend, jstart, jend, kstart, kend, zs, nz, gzs, gnz, ii, jj, kk, M, N, P;
211547c6ae99SBarry Smith   DM_DA                 *dd = (DM_DA *)da->data;
211647c6ae99SBarry Smith   PetscInt               ifill_col, *dfill = dd->dfill, *ofill = dd->ofill;
211747c6ae99SBarry Smith   MPI_Comm               comm;
211847c6ae99SBarry Smith   PetscScalar           *values;
2119bff4a2f0SMatthew G. Knepley   DMBoundaryType         bx, by, bz;
212045b6f7e9SBarry Smith   ISLocalToGlobalMapping ltog;
2121aa219208SBarry Smith   DMDAStencilType        st;
2122c1154cd5SBarry Smith   PetscBool              removedups = PETSC_FALSE;
212347c6ae99SBarry Smith 
212447c6ae99SBarry Smith   PetscFunctionBegin;
212547c6ae99SBarry Smith   /*
212647c6ae99SBarry Smith          nc - number of components per grid point
212747c6ae99SBarry Smith          col - number of colors needed in one direction for single component problem
212847c6ae99SBarry Smith 
212947c6ae99SBarry Smith   */
21309566063dSJacob Faibussowitsch   PetscCall(DMDAGetInfo(da, &dim, &m, &n, &p, &M, &N, &P, &nc, &s, &bx, &by, &bz, &st));
213147c6ae99SBarry Smith   col = 2 * s + 1;
21321dca8a05SBarry Smith   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\n\
213347c6ae99SBarry Smith                  by 2*stencil_width + 1\n");
21341dca8a05SBarry Smith   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\n\
213547c6ae99SBarry Smith                  by 2*stencil_width + 1\n");
21361dca8a05SBarry Smith   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\n\
213747c6ae99SBarry Smith                  by 2*stencil_width + 1\n");
213847c6ae99SBarry Smith 
2139c1154cd5SBarry Smith   /*
2140c1154cd5SBarry Smith        With one processor in periodic domains in a skinny dimension the code will label nonzero columns multiple times
2141c1154cd5SBarry Smith        because of "wrapping" around the end of the domain hitting an entry already counted in the other direction.
2142c1154cd5SBarry Smith   */
2143c1154cd5SBarry Smith   if (M == 1 && 2 * s >= m) removedups = PETSC_TRUE;
2144c1154cd5SBarry Smith   if (N == 1 && 2 * s >= n) removedups = PETSC_TRUE;
2145c1154cd5SBarry Smith   if (P == 1 && 2 * s >= p) removedups = PETSC_TRUE;
2146c1154cd5SBarry Smith 
21479566063dSJacob Faibussowitsch   PetscCall(DMDAGetCorners(da, &xs, &ys, &zs, &nx, &ny, &nz));
21489566063dSJacob Faibussowitsch   PetscCall(DMDAGetGhostCorners(da, &gxs, &gys, &gzs, &gnx, &gny, &gnz));
21499566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)da, &comm));
215047c6ae99SBarry Smith 
21519566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(col * col * col * nc, &cols));
21529566063dSJacob Faibussowitsch   PetscCall(DMGetLocalToGlobalMapping(da, &ltog));
215347c6ae99SBarry Smith 
215447c6ae99SBarry Smith   /* determine the matrix preallocation information */
2155d0609cedSBarry Smith   MatPreallocateBegin(comm, nc * nx * ny * nz, nc * nx * ny * nz, dnz, onz);
215647c6ae99SBarry Smith 
21579566063dSJacob Faibussowitsch   PetscCall(MatSetBlockSize(J, nc));
215847c6ae99SBarry Smith   for (i = xs; i < xs + nx; i++) {
2159bff4a2f0SMatthew G. Knepley     istart = (bx == DM_BOUNDARY_PERIODIC) ? -s : (PetscMax(-s, -i));
2160bff4a2f0SMatthew G. Knepley     iend   = (bx == DM_BOUNDARY_PERIODIC) ? s : (PetscMin(s, m - i - 1));
216147c6ae99SBarry Smith     for (j = ys; j < ys + ny; j++) {
2162bff4a2f0SMatthew G. Knepley       jstart = (by == DM_BOUNDARY_PERIODIC) ? -s : (PetscMax(-s, -j));
2163bff4a2f0SMatthew G. Knepley       jend   = (by == DM_BOUNDARY_PERIODIC) ? s : (PetscMin(s, n - j - 1));
216447c6ae99SBarry Smith       for (k = zs; k < zs + nz; k++) {
2165bff4a2f0SMatthew G. Knepley         kstart = (bz == DM_BOUNDARY_PERIODIC) ? -s : (PetscMax(-s, -k));
2166bff4a2f0SMatthew G. Knepley         kend   = (bz == DM_BOUNDARY_PERIODIC) ? s : (PetscMin(s, p - k - 1));
216747c6ae99SBarry Smith 
216847c6ae99SBarry Smith         slot = i - gxs + gnx * (j - gys) + gnx * gny * (k - gzs);
216947c6ae99SBarry Smith 
217047c6ae99SBarry Smith         for (l = 0; l < nc; l++) {
217147c6ae99SBarry Smith           cnt = 0;
217247c6ae99SBarry Smith           for (ii = istart; ii < iend + 1; ii++) {
217347c6ae99SBarry Smith             for (jj = jstart; jj < jend + 1; jj++) {
217447c6ae99SBarry Smith               for (kk = kstart; kk < kend + 1; kk++) {
217547c6ae99SBarry Smith                 if (ii || jj || kk) {
2176aa219208SBarry Smith                   if ((st == DMDA_STENCIL_BOX) || ((!ii && !jj) || (!jj && !kk) || (!ii && !kk))) { /* entries on star*/
21778865f1eaSKarl 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);
217847c6ae99SBarry Smith                   }
217947c6ae99SBarry Smith                 } else {
218047c6ae99SBarry Smith                   if (dfill) {
21818865f1eaSKarl 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);
218247c6ae99SBarry Smith                   } else {
21838865f1eaSKarl Rupp                     for (ifill_col = 0; ifill_col < nc; ifill_col++) cols[cnt++] = ifill_col + nc * (slot + ii + gnx * jj + gnx * gny * kk);
218447c6ae99SBarry Smith                   }
218547c6ae99SBarry Smith                 }
218647c6ae99SBarry Smith               }
218747c6ae99SBarry Smith             }
218847c6ae99SBarry Smith           }
218947c6ae99SBarry Smith           row    = l + nc * (slot);
2190c0ab637bSBarry Smith           maxcnt = PetscMax(maxcnt, cnt);
21911baa6e33SBarry Smith           if (removedups) PetscCall(MatPreallocateSetLocalRemoveDups(ltog, 1, &row, ltog, cnt, cols, dnz, onz));
21921baa6e33SBarry Smith           else PetscCall(MatPreallocateSetLocal(ltog, 1, &row, ltog, cnt, cols, dnz, onz));
219347c6ae99SBarry Smith         }
219447c6ae99SBarry Smith       }
219547c6ae99SBarry Smith     }
2196c1154cd5SBarry Smith   }
21979566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJSetPreallocation(J, 0, dnz));
21989566063dSJacob Faibussowitsch   PetscCall(MatMPIAIJSetPreallocation(J, 0, dnz, 0, onz));
2199d0609cedSBarry Smith   MatPreallocateEnd(dnz, onz);
22009566063dSJacob Faibussowitsch   PetscCall(MatSetLocalToGlobalMapping(J, ltog, ltog));
220147c6ae99SBarry Smith 
220247c6ae99SBarry Smith   /*
220347c6ae99SBarry Smith     For each node in the grid: we get the neighbors in the local (on processor ordering
220447c6ae99SBarry Smith     that includes the ghost points) then MatSetValuesLocal() maps those indices to the global
220547c6ae99SBarry Smith     PETSc ordering.
220647c6ae99SBarry Smith   */
2207fcfd50ebSBarry Smith   if (!da->prealloc_only) {
22089566063dSJacob Faibussowitsch     PetscCall(PetscCalloc1(maxcnt, &values));
220947c6ae99SBarry Smith     for (i = xs; i < xs + nx; i++) {
2210bff4a2f0SMatthew G. Knepley       istart = (bx == DM_BOUNDARY_PERIODIC) ? -s : (PetscMax(-s, -i));
2211bff4a2f0SMatthew G. Knepley       iend   = (bx == DM_BOUNDARY_PERIODIC) ? s : (PetscMin(s, m - i - 1));
221247c6ae99SBarry Smith       for (j = ys; j < ys + ny; j++) {
2213bff4a2f0SMatthew G. Knepley         jstart = (by == DM_BOUNDARY_PERIODIC) ? -s : (PetscMax(-s, -j));
2214bff4a2f0SMatthew G. Knepley         jend   = (by == DM_BOUNDARY_PERIODIC) ? s : (PetscMin(s, n - j - 1));
221547c6ae99SBarry Smith         for (k = zs; k < zs + nz; k++) {
2216bff4a2f0SMatthew G. Knepley           kstart = (bz == DM_BOUNDARY_PERIODIC) ? -s : (PetscMax(-s, -k));
2217bff4a2f0SMatthew G. Knepley           kend   = (bz == DM_BOUNDARY_PERIODIC) ? s : (PetscMin(s, p - k - 1));
221847c6ae99SBarry Smith 
221947c6ae99SBarry Smith           slot = i - gxs + gnx * (j - gys) + gnx * gny * (k - gzs);
222047c6ae99SBarry Smith 
222147c6ae99SBarry Smith           for (l = 0; l < nc; l++) {
222247c6ae99SBarry Smith             cnt = 0;
222347c6ae99SBarry Smith             for (ii = istart; ii < iend + 1; ii++) {
222447c6ae99SBarry Smith               for (jj = jstart; jj < jend + 1; jj++) {
222547c6ae99SBarry Smith                 for (kk = kstart; kk < kend + 1; kk++) {
222647c6ae99SBarry Smith                   if (ii || jj || kk) {
2227aa219208SBarry Smith                     if ((st == DMDA_STENCIL_BOX) || ((!ii && !jj) || (!jj && !kk) || (!ii && !kk))) { /* entries on star*/
22288865f1eaSKarl 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);
222947c6ae99SBarry Smith                     }
223047c6ae99SBarry Smith                   } else {
223147c6ae99SBarry Smith                     if (dfill) {
22328865f1eaSKarl 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);
223347c6ae99SBarry Smith                     } else {
22348865f1eaSKarl Rupp                       for (ifill_col = 0; ifill_col < nc; ifill_col++) cols[cnt++] = ifill_col + nc * (slot + ii + gnx * jj + gnx * gny * kk);
223547c6ae99SBarry Smith                     }
223647c6ae99SBarry Smith                   }
223747c6ae99SBarry Smith                 }
223847c6ae99SBarry Smith               }
223947c6ae99SBarry Smith             }
224047c6ae99SBarry Smith             row = l + nc * (slot);
22419566063dSJacob Faibussowitsch             PetscCall(MatSetValuesLocal(J, 1, &row, cnt, cols, values, INSERT_VALUES));
224247c6ae99SBarry Smith           }
224347c6ae99SBarry Smith         }
224447c6ae99SBarry Smith       }
224547c6ae99SBarry Smith     }
22469566063dSJacob Faibussowitsch     PetscCall(PetscFree(values));
2247e7e92044SBarry Smith     /* do not copy values to GPU since they are all zero and not yet needed there */
22489566063dSJacob Faibussowitsch     PetscCall(MatBindToCPU(J, PETSC_TRUE));
22499566063dSJacob Faibussowitsch     PetscCall(MatAssemblyBegin(J, MAT_FINAL_ASSEMBLY));
22509566063dSJacob Faibussowitsch     PetscCall(MatAssemblyEnd(J, MAT_FINAL_ASSEMBLY));
22519566063dSJacob Faibussowitsch     PetscCall(MatBindToCPU(J, PETSC_FALSE));
22529566063dSJacob Faibussowitsch     PetscCall(MatSetOption(J, MAT_NEW_NONZERO_LOCATION_ERR, PETSC_TRUE));
225347c6ae99SBarry Smith   }
22549566063dSJacob Faibussowitsch   PetscCall(PetscFree(cols));
225547c6ae99SBarry Smith   PetscFunctionReturn(0);
225647c6ae99SBarry Smith }
2257