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, <og)); 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, <og)); 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, <og)); 8029566063dSJacob Faibussowitsch PetscCall(MatSetLocalToGlobalMapping(J, ltog, ltog)); 8039566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(<og)); 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, <og, 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, <og)); 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, <og)); 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, <og)); 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, <og)); 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, <og)); 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, <og)); 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, <og)); 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, <og)); 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, <og)); 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, <og)); 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, <og)); 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, <og)); 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, <og)); 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