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