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: 9072fd0fbdSBarry 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: 14172fd0fbdSBarry 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) { 224*cc85f647SBarry Smith PetscCheck(!((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 sides of the domain on the same process"); 22547c6ae99SBarry Smith } 22647c6ae99SBarry Smith 227aa219208SBarry Smith /* Tell the DMDA it has 1 degree of freedom per grid point so that the coloring for BAIJ 22847c6ae99SBarry Smith matrices is for the blocks, not the individual matrix elements */ 2299566063dSJacob Faibussowitsch PetscCall(PetscStrbeginswith(da->mattype, MATBAIJ, &isBAIJ)); 2309566063dSJacob Faibussowitsch if (!isBAIJ) PetscCall(PetscStrbeginswith(da->mattype, MATMPIBAIJ, &isBAIJ)); 2319566063dSJacob Faibussowitsch if (!isBAIJ) PetscCall(PetscStrbeginswith(da->mattype, MATSEQBAIJ, &isBAIJ)); 23247c6ae99SBarry Smith if (isBAIJ) { 23347c6ae99SBarry Smith dd->w = 1; 23447c6ae99SBarry Smith dd->xs = dd->xs / nc; 23547c6ae99SBarry Smith dd->xe = dd->xe / nc; 23647c6ae99SBarry Smith dd->Xs = dd->Xs / nc; 23747c6ae99SBarry Smith dd->Xe = dd->Xe / nc; 23847c6ae99SBarry Smith } 23947c6ae99SBarry Smith 24047c6ae99SBarry Smith /* 241aa219208SBarry Smith We do not provide a getcoloring function in the DMDA operations because 2429a1b256bSStefano Zampini the basic DMDA does not know about matrices. We think of DMDA as being 24347c6ae99SBarry Smith more low-level then matrices. 24447c6ae99SBarry Smith */ 2451baa6e33SBarry Smith if (dim == 1) PetscCall(DMCreateColoring_DA_1d_MPIAIJ(da, ctype, coloring)); 2461baa6e33SBarry Smith else if (dim == 2) PetscCall(DMCreateColoring_DA_2d_MPIAIJ(da, ctype, coloring)); 2471baa6e33SBarry Smith else if (dim == 3) PetscCall(DMCreateColoring_DA_3d_MPIAIJ(da, ctype, coloring)); 2481baa6e33SBarry 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); 24947c6ae99SBarry Smith if (isBAIJ) { 25047c6ae99SBarry Smith dd->w = nc; 25147c6ae99SBarry Smith dd->xs = dd->xs * nc; 25247c6ae99SBarry Smith dd->xe = dd->xe * nc; 25347c6ae99SBarry Smith dd->Xs = dd->Xs * nc; 25447c6ae99SBarry Smith dd->Xe = dd->Xe * nc; 25547c6ae99SBarry Smith } 2563ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 25747c6ae99SBarry Smith } 25847c6ae99SBarry Smith 259d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateColoring_DA_2d_MPIAIJ(DM da, ISColoringType ctype, ISColoring *coloring) 260d71ae5a4SJacob Faibussowitsch { 26147c6ae99SBarry Smith PetscInt xs, ys, nx, ny, i, j, ii, gxs, gys, gnx, gny, m, n, M, N, dim, s, k, nc, col; 262dec0b466SHong Zhang PetscInt ncolors = 0; 26347c6ae99SBarry Smith MPI_Comm comm; 264bff4a2f0SMatthew G. Knepley DMBoundaryType bx, by; 265aa219208SBarry Smith DMDAStencilType st; 26647c6ae99SBarry Smith ISColoringValue *colors; 26747c6ae99SBarry Smith DM_DA *dd = (DM_DA *)da->data; 26847c6ae99SBarry Smith 26947c6ae99SBarry Smith PetscFunctionBegin; 27047c6ae99SBarry Smith /* 27147c6ae99SBarry Smith nc - number of components per grid point 27247c6ae99SBarry Smith col - number of colors needed in one direction for single component problem 27347c6ae99SBarry Smith 27447c6ae99SBarry Smith */ 2759566063dSJacob Faibussowitsch PetscCall(DMDAGetInfo(da, &dim, &m, &n, NULL, &M, &N, NULL, &nc, &s, &bx, &by, NULL, &st)); 27647c6ae99SBarry Smith col = 2 * s + 1; 2779566063dSJacob Faibussowitsch PetscCall(DMDAGetCorners(da, &xs, &ys, NULL, &nx, &ny, NULL)); 2789566063dSJacob Faibussowitsch PetscCall(DMDAGetGhostCorners(da, &gxs, &gys, NULL, &gnx, &gny, NULL)); 2799566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)da, &comm)); 28047c6ae99SBarry Smith 28147c6ae99SBarry Smith /* special case as taught to us by Paul Hovland */ 282aa219208SBarry Smith if (st == DMDA_STENCIL_STAR && s == 1) { 2839566063dSJacob Faibussowitsch PetscCall(DMCreateColoring_DA_2d_5pt_MPIAIJ(da, ctype, coloring)); 28447c6ae99SBarry Smith } else { 28547c6ae99SBarry Smith if (ctype == IS_COLORING_GLOBAL) { 28647c6ae99SBarry Smith if (!dd->localcoloring) { 2879566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nc * nx * ny, &colors)); 28847c6ae99SBarry Smith ii = 0; 28947c6ae99SBarry Smith for (j = ys; j < ys + ny; j++) { 29047c6ae99SBarry Smith for (i = xs; i < xs + nx; i++) { 291ad540459SPierre Jolivet for (k = 0; k < nc; k++) colors[ii++] = k + nc * ((i % col) + col * (j % col)); 29247c6ae99SBarry Smith } 29347c6ae99SBarry Smith } 29447c6ae99SBarry Smith ncolors = nc + nc * (col - 1 + col * (col - 1)); 2959566063dSJacob Faibussowitsch PetscCall(ISColoringCreate(comm, ncolors, nc * nx * ny, colors, PETSC_OWN_POINTER, &dd->localcoloring)); 29647c6ae99SBarry Smith } 29747c6ae99SBarry Smith *coloring = dd->localcoloring; 2985bdb020cSBarry Smith } else if (ctype == IS_COLORING_LOCAL) { 29947c6ae99SBarry Smith if (!dd->ghostedcoloring) { 3009566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nc * gnx * gny, &colors)); 30147c6ae99SBarry Smith ii = 0; 30247c6ae99SBarry Smith for (j = gys; j < gys + gny; j++) { 30347c6ae99SBarry Smith for (i = gxs; i < gxs + gnx; i++) { 30447c6ae99SBarry Smith for (k = 0; k < nc; k++) { 30547c6ae99SBarry Smith /* the complicated stuff is to handle periodic boundaries */ 30647c6ae99SBarry Smith colors[ii++] = k + nc * ((SetInRange(i, m) % col) + col * (SetInRange(j, n) % col)); 30747c6ae99SBarry Smith } 30847c6ae99SBarry Smith } 30947c6ae99SBarry Smith } 31047c6ae99SBarry Smith ncolors = nc + nc * (col - 1 + col * (col - 1)); 3119566063dSJacob Faibussowitsch PetscCall(ISColoringCreate(comm, ncolors, nc * gnx * gny, colors, PETSC_OWN_POINTER, &dd->ghostedcoloring)); 31247c6ae99SBarry Smith /* PetscIntView(ncolors,(PetscInt*)colors,0); */ 31347c6ae99SBarry Smith 3149566063dSJacob Faibussowitsch PetscCall(ISColoringSetType(dd->ghostedcoloring, IS_COLORING_LOCAL)); 31547c6ae99SBarry Smith } 31647c6ae99SBarry Smith *coloring = dd->ghostedcoloring; 31798921bdaSJacob Faibussowitsch } else SETERRQ(PetscObjectComm((PetscObject)da), PETSC_ERR_ARG_WRONG, "Unknown ISColoringType %d", (int)ctype); 31847c6ae99SBarry Smith } 3199566063dSJacob Faibussowitsch PetscCall(ISColoringReference(*coloring)); 3203ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 32147c6ae99SBarry Smith } 32247c6ae99SBarry Smith 323d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateColoring_DA_3d_MPIAIJ(DM da, ISColoringType ctype, ISColoring *coloring) 324d71ae5a4SJacob Faibussowitsch { 32547c6ae99SBarry 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; 32647c6ae99SBarry Smith PetscInt ncolors; 32747c6ae99SBarry Smith MPI_Comm comm; 328bff4a2f0SMatthew G. Knepley DMBoundaryType bx, by, bz; 329aa219208SBarry Smith DMDAStencilType st; 33047c6ae99SBarry Smith ISColoringValue *colors; 33147c6ae99SBarry Smith DM_DA *dd = (DM_DA *)da->data; 33247c6ae99SBarry Smith 33347c6ae99SBarry Smith PetscFunctionBegin; 33447c6ae99SBarry Smith /* 33547c6ae99SBarry Smith nc - number of components per grid point 33647c6ae99SBarry Smith col - number of colors needed in one direction for single component problem 33747c6ae99SBarry Smith */ 3389566063dSJacob Faibussowitsch PetscCall(DMDAGetInfo(da, &dim, &m, &n, &p, &M, &N, &P, &nc, &s, &bx, &by, &bz, &st)); 33947c6ae99SBarry Smith col = 2 * s + 1; 34000045ab3SPierre 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"); 34100045ab3SPierre 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"); 34200045ab3SPierre 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"); 343494b1ccaSBarry Smith 3449566063dSJacob Faibussowitsch PetscCall(DMDAGetCorners(da, &xs, &ys, &zs, &nx, &ny, &nz)); 3459566063dSJacob Faibussowitsch PetscCall(DMDAGetGhostCorners(da, &gxs, &gys, &gzs, &gnx, &gny, &gnz)); 3469566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)da, &comm)); 34747c6ae99SBarry Smith 34847c6ae99SBarry Smith /* create the coloring */ 34947c6ae99SBarry Smith if (ctype == IS_COLORING_GLOBAL) { 35047c6ae99SBarry Smith if (!dd->localcoloring) { 3519566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nc * nx * ny * nz, &colors)); 35247c6ae99SBarry Smith ii = 0; 35347c6ae99SBarry Smith for (k = zs; k < zs + nz; k++) { 35447c6ae99SBarry Smith for (j = ys; j < ys + ny; j++) { 35547c6ae99SBarry Smith for (i = xs; i < xs + nx; i++) { 356ad540459SPierre Jolivet for (l = 0; l < nc; l++) colors[ii++] = l + nc * ((i % col) + col * (j % col) + col * col * (k % col)); 35747c6ae99SBarry Smith } 35847c6ae99SBarry Smith } 35947c6ae99SBarry Smith } 36047c6ae99SBarry Smith ncolors = nc + nc * (col - 1 + col * (col - 1) + col * col * (col - 1)); 3619566063dSJacob Faibussowitsch PetscCall(ISColoringCreate(comm, ncolors, nc * nx * ny * nz, colors, PETSC_OWN_POINTER, &dd->localcoloring)); 36247c6ae99SBarry Smith } 36347c6ae99SBarry Smith *coloring = dd->localcoloring; 3645bdb020cSBarry Smith } else if (ctype == IS_COLORING_LOCAL) { 36547c6ae99SBarry Smith if (!dd->ghostedcoloring) { 3669566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nc * gnx * gny * gnz, &colors)); 36747c6ae99SBarry Smith ii = 0; 36847c6ae99SBarry Smith for (k = gzs; k < gzs + gnz; k++) { 36947c6ae99SBarry Smith for (j = gys; j < gys + gny; j++) { 37047c6ae99SBarry Smith for (i = gxs; i < gxs + gnx; i++) { 37147c6ae99SBarry Smith for (l = 0; l < nc; l++) { 37247c6ae99SBarry Smith /* the complicated stuff is to handle periodic boundaries */ 37347c6ae99SBarry Smith colors[ii++] = l + nc * ((SetInRange(i, m) % col) + col * (SetInRange(j, n) % col) + col * col * (SetInRange(k, p) % col)); 37447c6ae99SBarry Smith } 37547c6ae99SBarry Smith } 37647c6ae99SBarry Smith } 37747c6ae99SBarry Smith } 37847c6ae99SBarry Smith ncolors = nc + nc * (col - 1 + col * (col - 1) + col * col * (col - 1)); 3799566063dSJacob Faibussowitsch PetscCall(ISColoringCreate(comm, ncolors, nc * gnx * gny * gnz, colors, PETSC_OWN_POINTER, &dd->ghostedcoloring)); 3809566063dSJacob Faibussowitsch PetscCall(ISColoringSetType(dd->ghostedcoloring, IS_COLORING_LOCAL)); 38147c6ae99SBarry Smith } 38247c6ae99SBarry Smith *coloring = dd->ghostedcoloring; 38398921bdaSJacob Faibussowitsch } else SETERRQ(PetscObjectComm((PetscObject)da), PETSC_ERR_ARG_WRONG, "Unknown ISColoringType %d", (int)ctype); 3849566063dSJacob Faibussowitsch PetscCall(ISColoringReference(*coloring)); 3853ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 38647c6ae99SBarry Smith } 38747c6ae99SBarry Smith 388d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateColoring_DA_1d_MPIAIJ(DM da, ISColoringType ctype, ISColoring *coloring) 389d71ae5a4SJacob Faibussowitsch { 39047c6ae99SBarry Smith PetscInt xs, nx, i, i1, gxs, gnx, l, m, M, dim, s, nc, col; 39147c6ae99SBarry Smith PetscInt ncolors; 39247c6ae99SBarry Smith MPI_Comm comm; 393bff4a2f0SMatthew G. Knepley DMBoundaryType bx; 39447c6ae99SBarry Smith ISColoringValue *colors; 39547c6ae99SBarry Smith DM_DA *dd = (DM_DA *)da->data; 39647c6ae99SBarry Smith 39747c6ae99SBarry Smith PetscFunctionBegin; 39847c6ae99SBarry Smith /* 39947c6ae99SBarry Smith nc - number of components per grid point 40047c6ae99SBarry Smith col - number of colors needed in one direction for single component problem 40147c6ae99SBarry Smith */ 4029566063dSJacob Faibussowitsch PetscCall(DMDAGetInfo(da, &dim, &m, NULL, NULL, &M, NULL, NULL, &nc, &s, &bx, NULL, NULL, NULL)); 40347c6ae99SBarry Smith col = 2 * s + 1; 404*cc85f647SBarry Smith PetscCheck(bx != DM_BOUNDARY_PERIODIC || !(m % col), PetscObjectComm((PetscObject)da), PETSC_ERR_SUP, "IS_COLORING_GLOBAL can only be used for periodic boundary conditions if the number of grid points %" PetscInt_FMT " is divisible by the number of colors %" PetscInt_FMT, m, col); 4059566063dSJacob Faibussowitsch PetscCall(DMDAGetCorners(da, &xs, NULL, NULL, &nx, NULL, NULL)); 4069566063dSJacob Faibussowitsch PetscCall(DMDAGetGhostCorners(da, &gxs, NULL, NULL, &gnx, NULL, NULL)); 4079566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)da, &comm)); 40847c6ae99SBarry Smith 40947c6ae99SBarry Smith /* create the coloring */ 41047c6ae99SBarry Smith if (ctype == IS_COLORING_GLOBAL) { 41147c6ae99SBarry Smith if (!dd->localcoloring) { 4129566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nc * nx, &colors)); 413ae4f298aSBarry Smith if (dd->ofillcols) { 414ae4f298aSBarry Smith PetscInt tc = 0; 415ae4f298aSBarry Smith for (i = 0; i < nc; i++) tc += (PetscInt)(dd->ofillcols[i] > 0); 416ae4f298aSBarry Smith i1 = 0; 417ae4f298aSBarry Smith for (i = xs; i < xs + nx; i++) { 418ae4f298aSBarry Smith for (l = 0; l < nc; l++) { 419ae4f298aSBarry Smith if (dd->ofillcols[l] && (i % col)) { 420ae4f298aSBarry Smith colors[i1++] = nc - 1 + tc * ((i % col) - 1) + dd->ofillcols[l]; 421ae4f298aSBarry Smith } else { 422ae4f298aSBarry Smith colors[i1++] = l; 423ae4f298aSBarry Smith } 424ae4f298aSBarry Smith } 425ae4f298aSBarry Smith } 426ae4f298aSBarry Smith ncolors = nc + 2 * s * tc; 427ae4f298aSBarry Smith } else { 42847c6ae99SBarry Smith i1 = 0; 42947c6ae99SBarry Smith for (i = xs; i < xs + nx; i++) { 430ad540459SPierre Jolivet for (l = 0; l < nc; l++) colors[i1++] = l + nc * (i % col); 43147c6ae99SBarry Smith } 43247c6ae99SBarry Smith ncolors = nc + nc * (col - 1); 433ae4f298aSBarry Smith } 4349566063dSJacob Faibussowitsch PetscCall(ISColoringCreate(comm, ncolors, nc * nx, colors, PETSC_OWN_POINTER, &dd->localcoloring)); 43547c6ae99SBarry Smith } 43647c6ae99SBarry Smith *coloring = dd->localcoloring; 4375bdb020cSBarry Smith } else if (ctype == IS_COLORING_LOCAL) { 43847c6ae99SBarry Smith if (!dd->ghostedcoloring) { 4399566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nc * gnx, &colors)); 44047c6ae99SBarry Smith i1 = 0; 44147c6ae99SBarry Smith for (i = gxs; i < gxs + gnx; i++) { 44247c6ae99SBarry Smith for (l = 0; l < nc; l++) { 44347c6ae99SBarry Smith /* the complicated stuff is to handle periodic boundaries */ 44447c6ae99SBarry Smith colors[i1++] = l + nc * (SetInRange(i, m) % col); 44547c6ae99SBarry Smith } 44647c6ae99SBarry Smith } 44747c6ae99SBarry Smith ncolors = nc + nc * (col - 1); 4489566063dSJacob Faibussowitsch PetscCall(ISColoringCreate(comm, ncolors, nc * gnx, colors, PETSC_OWN_POINTER, &dd->ghostedcoloring)); 4499566063dSJacob Faibussowitsch PetscCall(ISColoringSetType(dd->ghostedcoloring, IS_COLORING_LOCAL)); 45047c6ae99SBarry Smith } 45147c6ae99SBarry Smith *coloring = dd->ghostedcoloring; 45298921bdaSJacob Faibussowitsch } else SETERRQ(PetscObjectComm((PetscObject)da), PETSC_ERR_ARG_WRONG, "Unknown ISColoringType %d", (int)ctype); 4539566063dSJacob Faibussowitsch PetscCall(ISColoringReference(*coloring)); 4543ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 45547c6ae99SBarry Smith } 45647c6ae99SBarry Smith 457d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateColoring_DA_2d_5pt_MPIAIJ(DM da, ISColoringType ctype, ISColoring *coloring) 458d71ae5a4SJacob Faibussowitsch { 45947c6ae99SBarry Smith PetscInt xs, ys, nx, ny, i, j, ii, gxs, gys, gnx, gny, m, n, dim, s, k, nc; 46047c6ae99SBarry Smith PetscInt ncolors; 46147c6ae99SBarry Smith MPI_Comm comm; 462bff4a2f0SMatthew G. Knepley DMBoundaryType bx, by; 46347c6ae99SBarry Smith ISColoringValue *colors; 46447c6ae99SBarry Smith DM_DA *dd = (DM_DA *)da->data; 46547c6ae99SBarry Smith 46647c6ae99SBarry Smith PetscFunctionBegin; 46747c6ae99SBarry Smith /* 46847c6ae99SBarry Smith nc - number of components per grid point 46947c6ae99SBarry Smith col - number of colors needed in one direction for single component problem 47047c6ae99SBarry Smith */ 4719566063dSJacob Faibussowitsch PetscCall(DMDAGetInfo(da, &dim, &m, &n, NULL, NULL, NULL, NULL, &nc, &s, &bx, &by, NULL, NULL)); 4729566063dSJacob Faibussowitsch PetscCall(DMDAGetCorners(da, &xs, &ys, NULL, &nx, &ny, NULL)); 4739566063dSJacob Faibussowitsch PetscCall(DMDAGetGhostCorners(da, &gxs, &gys, NULL, &gnx, &gny, NULL)); 4749566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)da, &comm)); 47547c6ae99SBarry Smith /* create the coloring */ 47647c6ae99SBarry Smith if (ctype == IS_COLORING_GLOBAL) { 47747c6ae99SBarry Smith if (!dd->localcoloring) { 4789566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nc * nx * ny, &colors)); 47947c6ae99SBarry Smith ii = 0; 48047c6ae99SBarry Smith for (j = ys; j < ys + ny; j++) { 48147c6ae99SBarry Smith for (i = xs; i < xs + nx; i++) { 482ad540459SPierre Jolivet for (k = 0; k < nc; k++) colors[ii++] = k + nc * ((3 * j + i) % 5); 48347c6ae99SBarry Smith } 48447c6ae99SBarry Smith } 48547c6ae99SBarry Smith ncolors = 5 * nc; 4869566063dSJacob Faibussowitsch PetscCall(ISColoringCreate(comm, ncolors, nc * nx * ny, colors, PETSC_OWN_POINTER, &dd->localcoloring)); 48747c6ae99SBarry Smith } 48847c6ae99SBarry Smith *coloring = dd->localcoloring; 4895bdb020cSBarry Smith } else if (ctype == IS_COLORING_LOCAL) { 49047c6ae99SBarry Smith if (!dd->ghostedcoloring) { 4919566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nc * gnx * gny, &colors)); 49247c6ae99SBarry Smith ii = 0; 49347c6ae99SBarry Smith for (j = gys; j < gys + gny; j++) { 49447c6ae99SBarry Smith for (i = gxs; i < gxs + gnx; i++) { 495ad540459SPierre Jolivet for (k = 0; k < nc; k++) colors[ii++] = k + nc * ((3 * SetInRange(j, n) + SetInRange(i, m)) % 5); 49647c6ae99SBarry Smith } 49747c6ae99SBarry Smith } 49847c6ae99SBarry Smith ncolors = 5 * nc; 4999566063dSJacob Faibussowitsch PetscCall(ISColoringCreate(comm, ncolors, nc * gnx * gny, colors, PETSC_OWN_POINTER, &dd->ghostedcoloring)); 5009566063dSJacob Faibussowitsch PetscCall(ISColoringSetType(dd->ghostedcoloring, IS_COLORING_LOCAL)); 50147c6ae99SBarry Smith } 50247c6ae99SBarry Smith *coloring = dd->ghostedcoloring; 50398921bdaSJacob Faibussowitsch } else SETERRQ(PetscObjectComm((PetscObject)da), PETSC_ERR_ARG_WRONG, "Unknown ISColoringType %d", (int)ctype); 5043ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 50547c6ae99SBarry Smith } 50647c6ae99SBarry Smith 50747c6ae99SBarry Smith /* =========================================================================== */ 508e432b41dSStefano Zampini extern PetscErrorCode DMCreateMatrix_DA_1d_MPIAIJ(DM, Mat); 509ce308e1dSBarry Smith extern PetscErrorCode DMCreateMatrix_DA_1d_MPIAIJ_Fill(DM, Mat); 510e432b41dSStefano Zampini extern PetscErrorCode DMCreateMatrix_DA_1d_SeqAIJ_NoPreallocation(DM, Mat); 511e432b41dSStefano Zampini extern PetscErrorCode DMCreateMatrix_DA_2d_MPIAIJ(DM, Mat); 512950540a4SJed Brown extern PetscErrorCode DMCreateMatrix_DA_2d_MPIAIJ_Fill(DM, Mat); 513e432b41dSStefano Zampini extern PetscErrorCode DMCreateMatrix_DA_3d_MPIAIJ(DM, Mat); 514950540a4SJed Brown extern PetscErrorCode DMCreateMatrix_DA_3d_MPIAIJ_Fill(DM, Mat); 515950540a4SJed Brown extern PetscErrorCode DMCreateMatrix_DA_2d_MPIBAIJ(DM, Mat); 516950540a4SJed Brown extern PetscErrorCode DMCreateMatrix_DA_3d_MPIBAIJ(DM, Mat); 517950540a4SJed Brown extern PetscErrorCode DMCreateMatrix_DA_2d_MPISBAIJ(DM, Mat); 518950540a4SJed Brown extern PetscErrorCode DMCreateMatrix_DA_3d_MPISBAIJ(DM, Mat); 519d4002b98SHong Zhang extern PetscErrorCode DMCreateMatrix_DA_2d_MPISELL(DM, Mat); 520d4002b98SHong Zhang extern PetscErrorCode DMCreateMatrix_DA_3d_MPISELL(DM, Mat); 521e584696dSStefano Zampini extern PetscErrorCode DMCreateMatrix_DA_IS(DM, Mat); 52247c6ae99SBarry Smith 523a4e35b19SJacob Faibussowitsch static PetscErrorCode MatView_MPI_DA(Mat A, PetscViewer viewer) 524d71ae5a4SJacob Faibussowitsch { 5259a42bb27SBarry Smith DM da; 52647c6ae99SBarry Smith const char *prefix; 5272d1451d4SHong Zhang Mat AA, Anatural; 52847c6ae99SBarry Smith AO ao; 52947c6ae99SBarry Smith PetscInt rstart, rend, *petsc, i; 53047c6ae99SBarry Smith IS is; 53147c6ae99SBarry Smith MPI_Comm comm; 53274388724SJed Brown PetscViewerFormat format; 5332d1451d4SHong Zhang PetscBool flag; 53447c6ae99SBarry Smith 53547c6ae99SBarry Smith PetscFunctionBegin; 53674388724SJed Brown /* Check whether we are just printing info, in which case MatView() already viewed everything we wanted to view */ 5379566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer, &format)); 5383ba16761SJacob Faibussowitsch if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) PetscFunctionReturn(PETSC_SUCCESS); 53974388724SJed Brown 5409566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)A, &comm)); 5419566063dSJacob Faibussowitsch PetscCall(MatGetDM(A, &da)); 5427a8be351SBarry Smith PetscCheck(da, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Matrix not generated from a DMDA"); 54347c6ae99SBarry Smith 5449566063dSJacob Faibussowitsch PetscCall(DMDAGetAO(da, &ao)); 5459566063dSJacob Faibussowitsch PetscCall(MatGetOwnershipRange(A, &rstart, &rend)); 5469566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(rend - rstart, &petsc)); 54747c6ae99SBarry Smith for (i = rstart; i < rend; i++) petsc[i - rstart] = i; 5489566063dSJacob Faibussowitsch PetscCall(AOApplicationToPetsc(ao, rend - rstart, petsc)); 5499566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(comm, rend - rstart, petsc, PETSC_OWN_POINTER, &is)); 55047c6ae99SBarry Smith 55147c6ae99SBarry Smith /* call viewer on natural ordering */ 5522d1451d4SHong Zhang PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATMPISELL, &flag)); 5532d1451d4SHong Zhang if (flag) { 5542d1451d4SHong Zhang PetscCall(MatConvert(A, MATAIJ, MAT_INITIAL_MATRIX, &AA)); 5552d1451d4SHong Zhang A = AA; 5562d1451d4SHong Zhang } 5579566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(A, is, is, MAT_INITIAL_MATRIX, &Anatural)); 5589566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is)); 5599566063dSJacob Faibussowitsch PetscCall(PetscObjectGetOptionsPrefix((PetscObject)A, &prefix)); 5609566063dSJacob Faibussowitsch PetscCall(PetscObjectSetOptionsPrefix((PetscObject)Anatural, prefix)); 5619566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)Anatural, ((PetscObject)A)->name)); 562f0ed2f47SStefano Zampini ((PetscObject)Anatural)->donotPetscObjectPrintClassNamePrefixType = PETSC_TRUE; 5639566063dSJacob Faibussowitsch PetscCall(MatView(Anatural, viewer)); 564f0ed2f47SStefano Zampini ((PetscObject)Anatural)->donotPetscObjectPrintClassNamePrefixType = PETSC_FALSE; 5659566063dSJacob Faibussowitsch PetscCall(MatDestroy(&Anatural)); 5662d1451d4SHong Zhang if (flag) PetscCall(MatDestroy(&AA)); 5673ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 56847c6ae99SBarry Smith } 56947c6ae99SBarry Smith 570a4e35b19SJacob Faibussowitsch static PetscErrorCode MatLoad_MPI_DA(Mat A, PetscViewer viewer) 571d71ae5a4SJacob Faibussowitsch { 5729a42bb27SBarry Smith DM da; 57347c6ae99SBarry Smith Mat Anatural, Aapp; 57447c6ae99SBarry Smith AO ao; 575539c167fSBarry Smith PetscInt rstart, rend, *app, i, m, n, M, N; 57647c6ae99SBarry Smith IS is; 57747c6ae99SBarry Smith MPI_Comm comm; 57847c6ae99SBarry Smith 57947c6ae99SBarry Smith PetscFunctionBegin; 5809566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)A, &comm)); 5819566063dSJacob Faibussowitsch PetscCall(MatGetDM(A, &da)); 5827a8be351SBarry Smith PetscCheck(da, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Matrix not generated from a DMDA"); 58347c6ae99SBarry Smith 58447c6ae99SBarry Smith /* Load the matrix in natural ordering */ 5859566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &Anatural)); 5869566063dSJacob Faibussowitsch PetscCall(MatSetType(Anatural, ((PetscObject)A)->type_name)); 5879566063dSJacob Faibussowitsch PetscCall(MatGetSize(A, &M, &N)); 5889566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(A, &m, &n)); 5899566063dSJacob Faibussowitsch PetscCall(MatSetSizes(Anatural, m, n, M, N)); 5909566063dSJacob Faibussowitsch PetscCall(MatLoad(Anatural, viewer)); 59147c6ae99SBarry Smith 59247c6ae99SBarry Smith /* Map natural ordering to application ordering and create IS */ 5939566063dSJacob Faibussowitsch PetscCall(DMDAGetAO(da, &ao)); 5949566063dSJacob Faibussowitsch PetscCall(MatGetOwnershipRange(Anatural, &rstart, &rend)); 5959566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(rend - rstart, &app)); 59647c6ae99SBarry Smith for (i = rstart; i < rend; i++) app[i - rstart] = i; 5979566063dSJacob Faibussowitsch PetscCall(AOPetscToApplication(ao, rend - rstart, app)); 5989566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(comm, rend - rstart, app, PETSC_OWN_POINTER, &is)); 59947c6ae99SBarry Smith 60047c6ae99SBarry Smith /* Do permutation and replace header */ 6019566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(Anatural, is, is, MAT_INITIAL_MATRIX, &Aapp)); 6029566063dSJacob Faibussowitsch PetscCall(MatHeaderReplace(A, &Aapp)); 6039566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is)); 6049566063dSJacob Faibussowitsch PetscCall(MatDestroy(&Anatural)); 6053ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 60647c6ae99SBarry Smith } 60747c6ae99SBarry Smith 608d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateMatrix_DA(DM da, Mat *J) 609d71ae5a4SJacob Faibussowitsch { 61047c6ae99SBarry Smith PetscInt dim, dof, nx, ny, nz, dims[3], starts[3], M, N, P; 61147c6ae99SBarry Smith Mat A; 61247c6ae99SBarry Smith MPI_Comm comm; 61319fd82e9SBarry Smith MatType Atype; 614b412c318SBarry Smith MatType mtype; 61547c6ae99SBarry Smith PetscMPIInt size; 61647c6ae99SBarry Smith DM_DA *dd = (DM_DA *)da->data; 617ade515a3SBarry Smith void (*aij)(void) = NULL, (*baij)(void) = NULL, (*sbaij)(void) = NULL, (*sell)(void) = NULL, (*is)(void) = NULL; 61847c6ae99SBarry Smith 61947c6ae99SBarry Smith PetscFunctionBegin; 6209566063dSJacob Faibussowitsch PetscCall(MatInitializePackage()); 621b412c318SBarry Smith mtype = da->mattype; 62247c6ae99SBarry Smith 62347c6ae99SBarry Smith /* 62447c6ae99SBarry Smith m 62547c6ae99SBarry Smith ------------------------------------------------------ 62647c6ae99SBarry Smith | | 62747c6ae99SBarry Smith | | 62847c6ae99SBarry Smith | ---------------------- | 62947c6ae99SBarry Smith | | | | 63047c6ae99SBarry Smith n | ny | | | 63147c6ae99SBarry Smith | | | | 63247c6ae99SBarry Smith | .--------------------- | 63347c6ae99SBarry Smith | (xs,ys) nx | 63447c6ae99SBarry Smith | . | 63547c6ae99SBarry Smith | (gxs,gys) | 63647c6ae99SBarry Smith | | 63747c6ae99SBarry Smith ----------------------------------------------------- 63847c6ae99SBarry Smith */ 63947c6ae99SBarry Smith 64047c6ae99SBarry Smith /* 64147c6ae99SBarry Smith nc - number of components per grid point 64247c6ae99SBarry Smith col - number of colors needed in one direction for single component problem 64347c6ae99SBarry Smith */ 644e30e807fSPeter Brune M = dd->M; 645e30e807fSPeter Brune N = dd->N; 646e30e807fSPeter Brune P = dd->P; 647c73cfb54SMatthew G. Knepley dim = da->dim; 648e30e807fSPeter Brune dof = dd->w; 6499566063dSJacob Faibussowitsch /* PetscCall(DMDAGetInfo(da,&dim,&M,&N,&P,NULL,NULL,NULL,&dof,NULL,NULL,NULL,NULL,NULL)); */ 6509566063dSJacob Faibussowitsch PetscCall(DMDAGetCorners(da, NULL, NULL, NULL, &nx, &ny, &nz)); 6519566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)da, &comm)); 6529566063dSJacob Faibussowitsch PetscCall(MatCreate(comm, &A)); 6539566063dSJacob Faibussowitsch PetscCall(MatSetSizes(A, dof * nx * ny * nz, dof * nx * ny * nz, dof * M * N * P, dof * M * N * P)); 6549566063dSJacob Faibussowitsch PetscCall(MatSetType(A, mtype)); 6559566063dSJacob Faibussowitsch PetscCall(MatSetFromOptions(A)); 65674427ab1SRichard Tran Mills if (dof * nx * ny * nz < da->bind_below) { 6579566063dSJacob Faibussowitsch PetscCall(MatSetBindingPropagates(A, PETSC_TRUE)); 6589566063dSJacob Faibussowitsch PetscCall(MatBindToCPU(A, PETSC_TRUE)); 65974427ab1SRichard Tran Mills } 6609566063dSJacob Faibussowitsch PetscCall(MatSetDM(A, da)); 6611baa6e33SBarry Smith if (da->structure_only) PetscCall(MatSetOption(A, MAT_STRUCTURE_ONLY, PETSC_TRUE)); 6629566063dSJacob Faibussowitsch PetscCall(MatGetType(A, &Atype)); 66347c6ae99SBarry Smith /* 664aa219208SBarry Smith We do not provide a getmatrix function in the DMDA operations because 665aa219208SBarry Smith the basic DMDA does not know about matrices. We think of DMDA as being more 66647c6ae99SBarry Smith more low-level than matrices. This is kind of cheating but, cause sometimes 667aa219208SBarry Smith we think of DMDA has higher level than matrices. 66847c6ae99SBarry Smith 66947c6ae99SBarry Smith We could switch based on Atype (or mtype), but we do not since the 670844bd0d7SStefano Zampini specialized setting routines depend only on the particular preallocation 67147c6ae99SBarry Smith details of the matrix, not the type itself. 67247c6ae99SBarry Smith */ 673d7dabc60SJed Brown if (!da->prealloc_skip) { // Flag is likely set when user intends to use MatSetPreallocationCOO() 6749566063dSJacob Faibussowitsch PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatMPIAIJSetPreallocation_C", &aij)); 67548a46eb9SPierre Jolivet if (!aij) PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatSeqAIJSetPreallocation_C", &aij)); 67647c6ae99SBarry Smith if (!aij) { 6779566063dSJacob Faibussowitsch PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatMPIBAIJSetPreallocation_C", &baij)); 67848a46eb9SPierre Jolivet if (!baij) PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatSeqBAIJSetPreallocation_C", &baij)); 67947c6ae99SBarry Smith if (!baij) { 6809566063dSJacob Faibussowitsch PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatMPISBAIJSetPreallocation_C", &sbaij)); 68148a46eb9SPierre Jolivet if (!sbaij) PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatSeqSBAIJSetPreallocation_C", &sbaij)); 6825e26d47bSHong Zhang if (!sbaij) { 6839566063dSJacob Faibussowitsch PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatMPISELLSetPreallocation_C", &sell)); 68448a46eb9SPierre Jolivet if (!sell) PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatSeqSELLSetPreallocation_C", &sell)); 6855e26d47bSHong Zhang } 68648a46eb9SPierre Jolivet if (!sell) PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatISSetPreallocation_C", &is)); 68747c6ae99SBarry Smith } 68847c6ae99SBarry Smith } 689d7dabc60SJed Brown } 69047c6ae99SBarry Smith if (aij) { 69147c6ae99SBarry Smith if (dim == 1) { 692ce308e1dSBarry Smith if (dd->ofill) { 6939566063dSJacob Faibussowitsch PetscCall(DMCreateMatrix_DA_1d_MPIAIJ_Fill(da, A)); 694ce308e1dSBarry Smith } else { 69519b08ed1SBarry Smith DMBoundaryType bx; 69619b08ed1SBarry Smith PetscMPIInt size; 6979566063dSJacob Faibussowitsch PetscCall(DMDAGetInfo(da, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &bx, NULL, NULL, NULL)); 6989566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)da), &size)); 69919b08ed1SBarry Smith if (size == 1 && bx == DM_BOUNDARY_NONE) { 7009566063dSJacob Faibussowitsch PetscCall(DMCreateMatrix_DA_1d_SeqAIJ_NoPreallocation(da, A)); 70119b08ed1SBarry Smith } else { 7029566063dSJacob Faibussowitsch PetscCall(DMCreateMatrix_DA_1d_MPIAIJ(da, A)); 703ce308e1dSBarry Smith } 70419b08ed1SBarry Smith } 70547c6ae99SBarry Smith } else if (dim == 2) { 70647c6ae99SBarry Smith if (dd->ofill) { 7079566063dSJacob Faibussowitsch PetscCall(DMCreateMatrix_DA_2d_MPIAIJ_Fill(da, A)); 70847c6ae99SBarry Smith } else { 7099566063dSJacob Faibussowitsch PetscCall(DMCreateMatrix_DA_2d_MPIAIJ(da, A)); 71047c6ae99SBarry Smith } 71147c6ae99SBarry Smith } else if (dim == 3) { 71247c6ae99SBarry Smith if (dd->ofill) { 7139566063dSJacob Faibussowitsch PetscCall(DMCreateMatrix_DA_3d_MPIAIJ_Fill(da, A)); 71447c6ae99SBarry Smith } else { 7159566063dSJacob Faibussowitsch PetscCall(DMCreateMatrix_DA_3d_MPIAIJ(da, A)); 71647c6ae99SBarry Smith } 71747c6ae99SBarry Smith } 71847c6ae99SBarry Smith } else if (baij) { 71947c6ae99SBarry Smith if (dim == 2) { 7209566063dSJacob Faibussowitsch PetscCall(DMCreateMatrix_DA_2d_MPIBAIJ(da, A)); 72147c6ae99SBarry Smith } else if (dim == 3) { 7229566063dSJacob Faibussowitsch PetscCall(DMCreateMatrix_DA_3d_MPIBAIJ(da, A)); 72363a3b9bcSJacob 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); 72447c6ae99SBarry Smith } else if (sbaij) { 72547c6ae99SBarry Smith if (dim == 2) { 7269566063dSJacob Faibussowitsch PetscCall(DMCreateMatrix_DA_2d_MPISBAIJ(da, A)); 72747c6ae99SBarry Smith } else if (dim == 3) { 7289566063dSJacob Faibussowitsch PetscCall(DMCreateMatrix_DA_3d_MPISBAIJ(da, A)); 72963a3b9bcSJacob 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); 730d4002b98SHong Zhang } else if (sell) { 7315e26d47bSHong Zhang if (dim == 2) { 7329566063dSJacob Faibussowitsch PetscCall(DMCreateMatrix_DA_2d_MPISELL(da, A)); 733711261dbSHong Zhang } else if (dim == 3) { 7349566063dSJacob Faibussowitsch PetscCall(DMCreateMatrix_DA_3d_MPISELL(da, A)); 73563a3b9bcSJacob 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); 736e584696dSStefano Zampini } else if (is) { 7379566063dSJacob Faibussowitsch PetscCall(DMCreateMatrix_DA_IS(da, A)); 738d7dabc60SJed Brown } else { // unknown type or da->prealloc_skip so structural information may be needed, but no prealloc 73945b6f7e9SBarry Smith ISLocalToGlobalMapping ltog; 740e584696dSStefano Zampini 7419566063dSJacob Faibussowitsch PetscCall(MatSetBlockSize(A, dof)); 7429566063dSJacob Faibussowitsch PetscCall(MatSetUp(A)); 7439566063dSJacob Faibussowitsch PetscCall(DMGetLocalToGlobalMapping(da, <og)); 7449566063dSJacob Faibussowitsch PetscCall(MatSetLocalToGlobalMapping(A, ltog, ltog)); 74547c6ae99SBarry Smith } 7469566063dSJacob Faibussowitsch PetscCall(DMDAGetGhostCorners(da, &starts[0], &starts[1], &starts[2], &dims[0], &dims[1], &dims[2])); 7479566063dSJacob Faibussowitsch PetscCall(MatSetStencil(A, dim, dims, starts, dof)); 7489566063dSJacob Faibussowitsch PetscCall(MatSetDM(A, da)); 7499566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(comm, &size)); 75047c6ae99SBarry Smith if (size > 1) { 75147c6ae99SBarry Smith /* change viewer to display matrix in natural ordering */ 7529566063dSJacob Faibussowitsch PetscCall(MatSetOperation(A, MATOP_VIEW, (void (*)(void))MatView_MPI_DA)); 7539566063dSJacob Faibussowitsch PetscCall(MatSetOperation(A, MATOP_LOAD, (void (*)(void))MatLoad_MPI_DA)); 75447c6ae99SBarry Smith } 75547c6ae99SBarry Smith *J = A; 7563ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 75747c6ae99SBarry Smith } 75847c6ae99SBarry Smith 759844bd0d7SStefano Zampini PETSC_EXTERN PetscErrorCode MatISSetPreallocation_IS(Mat, PetscInt, const PetscInt[], PetscInt, const PetscInt[]); 760844bd0d7SStefano Zampini 761d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateMatrix_DA_IS(DM dm, Mat J) 762d71ae5a4SJacob Faibussowitsch { 763e584696dSStefano Zampini DM_DA *da = (DM_DA *)dm->data; 764e432b41dSStefano Zampini Mat lJ, P; 765e584696dSStefano Zampini ISLocalToGlobalMapping ltog; 766e432b41dSStefano Zampini IS is; 767e432b41dSStefano Zampini PetscBT bt; 76805339c03SStefano Zampini const PetscInt *e_loc, *idx; 769e432b41dSStefano Zampini PetscInt i, nel, nen, nv, dof, *gidx, n, N; 770e584696dSStefano Zampini 771e584696dSStefano Zampini /* The l2g map of DMDA has all ghosted nodes, and e_loc is a subset of all the local nodes (including the ghosted) 772e432b41dSStefano Zampini We need to filter out the local indices that are not represented through the DMDAGetElements decomposition */ 773e584696dSStefano Zampini PetscFunctionBegin; 774e584696dSStefano Zampini dof = da->w; 7759566063dSJacob Faibussowitsch PetscCall(MatSetBlockSize(J, dof)); 7769566063dSJacob Faibussowitsch PetscCall(DMGetLocalToGlobalMapping(dm, <og)); 777e432b41dSStefano Zampini 778e432b41dSStefano Zampini /* flag local elements indices in local DMDA numbering */ 7799566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetSize(ltog, &nv)); 7809566063dSJacob Faibussowitsch PetscCall(PetscBTCreate(nv / dof, &bt)); 7819566063dSJacob Faibussowitsch PetscCall(DMDAGetElements(dm, &nel, &nen, &e_loc)); /* this will throw an error if the stencil type is not DMDA_STENCIL_BOX */ 7829566063dSJacob Faibussowitsch for (i = 0; i < nel * nen; i++) PetscCall(PetscBTSet(bt, e_loc[i])); 783e432b41dSStefano Zampini 784e432b41dSStefano Zampini /* filter out (set to -1) the global indices not used by the local elements */ 7859566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nv / dof, &gidx)); 7869566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockIndices(ltog, &idx)); 7879566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(gidx, idx, nv / dof)); 7889566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreBlockIndices(ltog, &idx)); 7899371c9d4SSatish Balay for (i = 0; i < nv / dof; i++) 7909371c9d4SSatish Balay if (!PetscBTLookup(bt, i)) gidx[i] = -1; 7919566063dSJacob Faibussowitsch PetscCall(PetscBTDestroy(&bt)); 7929566063dSJacob Faibussowitsch PetscCall(ISCreateBlock(PetscObjectComm((PetscObject)dm), dof, nv / dof, gidx, PETSC_OWN_POINTER, &is)); 7939566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(is, <og)); 7949566063dSJacob Faibussowitsch PetscCall(MatSetLocalToGlobalMapping(J, ltog, ltog)); 7959566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(<og)); 7969566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is)); 79705339c03SStefano Zampini 798e432b41dSStefano Zampini /* Preallocation */ 799e306f867SJed Brown if (dm->prealloc_skip) { 8009566063dSJacob Faibussowitsch PetscCall(MatSetUp(J)); 801e306f867SJed Brown } else { 8029566063dSJacob Faibussowitsch PetscCall(MatISGetLocalMat(J, &lJ)); 8039566063dSJacob Faibussowitsch PetscCall(MatGetLocalToGlobalMapping(lJ, <og, NULL)); 8049566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)lJ), &P)); 8059566063dSJacob Faibussowitsch PetscCall(MatSetType(P, MATPREALLOCATOR)); 8069566063dSJacob Faibussowitsch PetscCall(MatSetLocalToGlobalMapping(P, ltog, ltog)); 8079566063dSJacob Faibussowitsch PetscCall(MatGetSize(lJ, &N, NULL)); 8089566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(lJ, &n, NULL)); 8099566063dSJacob Faibussowitsch PetscCall(MatSetSizes(P, n, n, N, N)); 8109566063dSJacob Faibussowitsch PetscCall(MatSetBlockSize(P, dof)); 8119566063dSJacob Faibussowitsch PetscCall(MatSetUp(P)); 81248a46eb9SPierre Jolivet for (i = 0; i < nel; i++) PetscCall(MatSetValuesBlockedLocal(P, nen, e_loc + i * nen, nen, e_loc + i * nen, NULL, INSERT_VALUES)); 8139566063dSJacob Faibussowitsch PetscCall(MatPreallocatorPreallocate(P, (PetscBool)!da->prealloc_only, lJ)); 8149566063dSJacob Faibussowitsch PetscCall(MatISRestoreLocalMat(J, &lJ)); 8159566063dSJacob Faibussowitsch PetscCall(DMDARestoreElements(dm, &nel, &nen, &e_loc)); 8169566063dSJacob Faibussowitsch PetscCall(MatDestroy(&P)); 817e432b41dSStefano Zampini 8189566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(J, MAT_FINAL_ASSEMBLY)); 8199566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(J, MAT_FINAL_ASSEMBLY)); 820e306f867SJed Brown } 8213ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 822e584696dSStefano Zampini } 823e584696dSStefano Zampini 824d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateMatrix_DA_2d_MPISELL(DM da, Mat J) 825d71ae5a4SJacob Faibussowitsch { 8265e26d47bSHong 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; 8275e26d47bSHong Zhang PetscInt lstart, lend, pstart, pend, *dnz, *onz; 8285e26d47bSHong Zhang MPI_Comm comm; 8295e26d47bSHong Zhang PetscScalar *values; 8305e26d47bSHong Zhang DMBoundaryType bx, by; 8315e26d47bSHong Zhang ISLocalToGlobalMapping ltog; 8325e26d47bSHong Zhang DMDAStencilType st; 8335e26d47bSHong Zhang 8345e26d47bSHong Zhang PetscFunctionBegin; 8355e26d47bSHong Zhang /* 8365e26d47bSHong Zhang nc - number of components per grid point 8375e26d47bSHong Zhang col - number of colors needed in one direction for single component problem 8385e26d47bSHong Zhang */ 8399566063dSJacob Faibussowitsch PetscCall(DMDAGetInfo(da, &dim, &m, &n, NULL, NULL, NULL, NULL, &nc, &s, &bx, &by, NULL, &st)); 8405e26d47bSHong Zhang col = 2 * s + 1; 8419566063dSJacob Faibussowitsch PetscCall(DMDAGetCorners(da, &xs, &ys, NULL, &nx, &ny, NULL)); 8429566063dSJacob Faibussowitsch PetscCall(DMDAGetGhostCorners(da, &gxs, &gys, NULL, &gnx, &gny, NULL)); 8439566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)da, &comm)); 8445e26d47bSHong Zhang 8459566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(nc, &rows, col * col * nc * nc, &cols)); 8469566063dSJacob Faibussowitsch PetscCall(DMGetLocalToGlobalMapping(da, <og)); 8475e26d47bSHong Zhang 8489566063dSJacob Faibussowitsch PetscCall(MatSetBlockSize(J, nc)); 8495e26d47bSHong Zhang /* determine the matrix preallocation information */ 850d0609cedSBarry Smith MatPreallocateBegin(comm, nc * nx * ny, nc * nx * ny, dnz, onz); 8515e26d47bSHong Zhang for (i = xs; i < xs + nx; i++) { 8525e26d47bSHong Zhang pstart = (bx == DM_BOUNDARY_PERIODIC) ? -s : (PetscMax(-s, -i)); 8535e26d47bSHong Zhang pend = (bx == DM_BOUNDARY_PERIODIC) ? s : (PetscMin(s, m - i - 1)); 8545e26d47bSHong Zhang 8555e26d47bSHong Zhang for (j = ys; j < ys + ny; j++) { 8565e26d47bSHong Zhang slot = i - gxs + gnx * (j - gys); 8575e26d47bSHong Zhang 8585e26d47bSHong Zhang lstart = (by == DM_BOUNDARY_PERIODIC) ? -s : (PetscMax(-s, -j)); 8595e26d47bSHong Zhang lend = (by == DM_BOUNDARY_PERIODIC) ? s : (PetscMin(s, n - j - 1)); 8605e26d47bSHong Zhang 8615e26d47bSHong Zhang cnt = 0; 8625e26d47bSHong Zhang for (k = 0; k < nc; k++) { 8635e26d47bSHong Zhang for (l = lstart; l < lend + 1; l++) { 8645e26d47bSHong Zhang for (p = pstart; p < pend + 1; p++) { 8655e26d47bSHong Zhang if ((st == DMDA_STENCIL_BOX) || (!l || !p)) { /* entries on star have either l = 0 or p = 0 */ 8665e26d47bSHong Zhang cols[cnt++] = k + nc * (slot + gnx * l + p); 8675e26d47bSHong Zhang } 8685e26d47bSHong Zhang } 8695e26d47bSHong Zhang } 8705e26d47bSHong Zhang rows[k] = k + nc * (slot); 8715e26d47bSHong Zhang } 8729566063dSJacob Faibussowitsch PetscCall(MatPreallocateSetLocal(ltog, nc, rows, ltog, cnt, cols, dnz, onz)); 8735e26d47bSHong Zhang } 8745e26d47bSHong Zhang } 8759566063dSJacob Faibussowitsch PetscCall(MatSetBlockSize(J, nc)); 8769566063dSJacob Faibussowitsch PetscCall(MatSeqSELLSetPreallocation(J, 0, dnz)); 8779566063dSJacob Faibussowitsch PetscCall(MatMPISELLSetPreallocation(J, 0, dnz, 0, onz)); 878d0609cedSBarry Smith MatPreallocateEnd(dnz, onz); 8795e26d47bSHong Zhang 8809566063dSJacob Faibussowitsch PetscCall(MatSetLocalToGlobalMapping(J, ltog, ltog)); 8815e26d47bSHong Zhang 8825e26d47bSHong Zhang /* 8835e26d47bSHong Zhang For each node in the grid: we get the neighbors in the local (on processor ordering 8845e26d47bSHong Zhang that includes the ghost points) then MatSetValuesLocal() maps those indices to the global 8855e26d47bSHong Zhang PETSc ordering. 8865e26d47bSHong Zhang */ 8875e26d47bSHong Zhang if (!da->prealloc_only) { 8889566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(col * col * nc * nc, &values)); 8895e26d47bSHong Zhang for (i = xs; i < xs + nx; i++) { 8905e26d47bSHong Zhang pstart = (bx == DM_BOUNDARY_PERIODIC) ? -s : (PetscMax(-s, -i)); 8915e26d47bSHong Zhang pend = (bx == DM_BOUNDARY_PERIODIC) ? s : (PetscMin(s, m - i - 1)); 8925e26d47bSHong Zhang 8935e26d47bSHong Zhang for (j = ys; j < ys + ny; j++) { 8945e26d47bSHong Zhang slot = i - gxs + gnx * (j - gys); 8955e26d47bSHong Zhang 8965e26d47bSHong Zhang lstart = (by == DM_BOUNDARY_PERIODIC) ? -s : (PetscMax(-s, -j)); 8975e26d47bSHong Zhang lend = (by == DM_BOUNDARY_PERIODIC) ? s : (PetscMin(s, n - j - 1)); 8985e26d47bSHong Zhang 8995e26d47bSHong Zhang cnt = 0; 9005e26d47bSHong Zhang for (k = 0; k < nc; k++) { 9015e26d47bSHong Zhang for (l = lstart; l < lend + 1; l++) { 9025e26d47bSHong Zhang for (p = pstart; p < pend + 1; p++) { 9035e26d47bSHong Zhang if ((st == DMDA_STENCIL_BOX) || (!l || !p)) { /* entries on star have either l = 0 or p = 0 */ 9045e26d47bSHong Zhang cols[cnt++] = k + nc * (slot + gnx * l + p); 9055e26d47bSHong Zhang } 9065e26d47bSHong Zhang } 9075e26d47bSHong Zhang } 9085e26d47bSHong Zhang rows[k] = k + nc * (slot); 9095e26d47bSHong Zhang } 9109566063dSJacob Faibussowitsch PetscCall(MatSetValuesLocal(J, nc, rows, cnt, cols, values, INSERT_VALUES)); 9115e26d47bSHong Zhang } 9125e26d47bSHong Zhang } 9139566063dSJacob Faibussowitsch PetscCall(PetscFree(values)); 914e7e92044SBarry Smith /* do not copy values to GPU since they are all zero and not yet needed there */ 9159566063dSJacob Faibussowitsch PetscCall(MatBindToCPU(J, PETSC_TRUE)); 9169566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(J, MAT_FINAL_ASSEMBLY)); 9179566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(J, MAT_FINAL_ASSEMBLY)); 9189566063dSJacob Faibussowitsch PetscCall(MatBindToCPU(J, PETSC_FALSE)); 9199566063dSJacob Faibussowitsch PetscCall(MatSetOption(J, MAT_NEW_NONZERO_LOCATION_ERR, PETSC_TRUE)); 9205e26d47bSHong Zhang } 9219566063dSJacob Faibussowitsch PetscCall(PetscFree2(rows, cols)); 9223ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 9235e26d47bSHong Zhang } 9245e26d47bSHong Zhang 925d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateMatrix_DA_3d_MPISELL(DM da, Mat J) 926d71ae5a4SJacob Faibussowitsch { 927711261dbSHong Zhang PetscInt xs, ys, nx, ny, i, j, slot, gxs, gys, gnx, gny; 928711261dbSHong Zhang PetscInt m, n, dim, s, *cols = NULL, k, nc, *rows = NULL, col, cnt, l, p, *dnz = NULL, *onz = NULL; 929711261dbSHong Zhang PetscInt istart, iend, jstart, jend, kstart, kend, zs, nz, gzs, gnz, ii, jj, kk, M, N, P; 930711261dbSHong Zhang MPI_Comm comm; 931711261dbSHong Zhang PetscScalar *values; 932711261dbSHong Zhang DMBoundaryType bx, by, bz; 933711261dbSHong Zhang ISLocalToGlobalMapping ltog; 934711261dbSHong Zhang DMDAStencilType st; 935711261dbSHong Zhang 936711261dbSHong Zhang PetscFunctionBegin; 937711261dbSHong Zhang /* 938711261dbSHong Zhang nc - number of components per grid point 939711261dbSHong Zhang col - number of colors needed in one direction for single component problem 940711261dbSHong Zhang */ 9419566063dSJacob Faibussowitsch PetscCall(DMDAGetInfo(da, &dim, &m, &n, &p, &M, &N, &P, &nc, &s, &bx, &by, &bz, &st)); 942711261dbSHong Zhang col = 2 * s + 1; 9439566063dSJacob Faibussowitsch PetscCall(DMDAGetCorners(da, &xs, &ys, &zs, &nx, &ny, &nz)); 9449566063dSJacob Faibussowitsch PetscCall(DMDAGetGhostCorners(da, &gxs, &gys, &gzs, &gnx, &gny, &gnz)); 9459566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)da, &comm)); 946711261dbSHong Zhang 9479566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(nc, &rows, col * col * col * nc * nc, &cols)); 9489566063dSJacob Faibussowitsch PetscCall(DMGetLocalToGlobalMapping(da, <og)); 949711261dbSHong Zhang 9509566063dSJacob Faibussowitsch PetscCall(MatSetBlockSize(J, nc)); 951711261dbSHong Zhang /* determine the matrix preallocation information */ 952d0609cedSBarry Smith MatPreallocateBegin(comm, nc * nx * ny * nz, nc * nx * ny * nz, dnz, onz); 953711261dbSHong Zhang for (i = xs; i < xs + nx; i++) { 954711261dbSHong Zhang istart = (bx == DM_BOUNDARY_PERIODIC) ? -s : (PetscMax(-s, -i)); 955711261dbSHong Zhang iend = (bx == DM_BOUNDARY_PERIODIC) ? s : (PetscMin(s, m - i - 1)); 956711261dbSHong Zhang for (j = ys; j < ys + ny; j++) { 957711261dbSHong Zhang jstart = (by == DM_BOUNDARY_PERIODIC) ? -s : (PetscMax(-s, -j)); 958711261dbSHong Zhang jend = (by == DM_BOUNDARY_PERIODIC) ? s : (PetscMin(s, n - j - 1)); 959711261dbSHong Zhang for (k = zs; k < zs + nz; k++) { 960711261dbSHong Zhang kstart = (bz == DM_BOUNDARY_PERIODIC) ? -s : (PetscMax(-s, -k)); 961711261dbSHong Zhang kend = (bz == DM_BOUNDARY_PERIODIC) ? s : (PetscMin(s, p - k - 1)); 962711261dbSHong Zhang 963711261dbSHong Zhang slot = i - gxs + gnx * (j - gys) + gnx * gny * (k - gzs); 964711261dbSHong Zhang 965711261dbSHong Zhang cnt = 0; 966711261dbSHong Zhang for (l = 0; l < nc; l++) { 967711261dbSHong Zhang for (ii = istart; ii < iend + 1; ii++) { 968711261dbSHong Zhang for (jj = jstart; jj < jend + 1; jj++) { 969711261dbSHong Zhang for (kk = kstart; kk < kend + 1; kk++) { 970711261dbSHong Zhang if ((st == DMDA_STENCIL_BOX) || ((!ii && !jj) || (!jj && !kk) || (!ii && !kk))) { /* entries on star*/ 971711261dbSHong Zhang cols[cnt++] = l + nc * (slot + ii + gnx * jj + gnx * gny * kk); 972711261dbSHong Zhang } 973711261dbSHong Zhang } 974711261dbSHong Zhang } 975711261dbSHong Zhang } 976711261dbSHong Zhang rows[l] = l + nc * (slot); 977711261dbSHong Zhang } 9789566063dSJacob Faibussowitsch PetscCall(MatPreallocateSetLocal(ltog, nc, rows, ltog, cnt, cols, dnz, onz)); 979711261dbSHong Zhang } 980711261dbSHong Zhang } 981711261dbSHong Zhang } 9829566063dSJacob Faibussowitsch PetscCall(MatSetBlockSize(J, nc)); 9839566063dSJacob Faibussowitsch PetscCall(MatSeqSELLSetPreallocation(J, 0, dnz)); 9849566063dSJacob Faibussowitsch PetscCall(MatMPISELLSetPreallocation(J, 0, dnz, 0, onz)); 985d0609cedSBarry Smith MatPreallocateEnd(dnz, onz); 9869566063dSJacob Faibussowitsch PetscCall(MatSetLocalToGlobalMapping(J, ltog, ltog)); 987711261dbSHong Zhang 988711261dbSHong Zhang /* 989711261dbSHong Zhang For each node in the grid: we get the neighbors in the local (on processor ordering 990711261dbSHong Zhang that includes the ghost points) then MatSetValuesLocal() maps those indices to the global 991711261dbSHong Zhang PETSc ordering. 992711261dbSHong Zhang */ 993711261dbSHong Zhang if (!da->prealloc_only) { 9949566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(col * col * col * nc * nc * nc, &values)); 995711261dbSHong Zhang for (i = xs; i < xs + nx; i++) { 996711261dbSHong Zhang istart = (bx == DM_BOUNDARY_PERIODIC) ? -s : (PetscMax(-s, -i)); 997711261dbSHong Zhang iend = (bx == DM_BOUNDARY_PERIODIC) ? s : (PetscMin(s, m - i - 1)); 998711261dbSHong Zhang for (j = ys; j < ys + ny; j++) { 999711261dbSHong Zhang jstart = (by == DM_BOUNDARY_PERIODIC) ? -s : (PetscMax(-s, -j)); 1000711261dbSHong Zhang jend = (by == DM_BOUNDARY_PERIODIC) ? s : (PetscMin(s, n - j - 1)); 1001711261dbSHong Zhang for (k = zs; k < zs + nz; k++) { 1002711261dbSHong Zhang kstart = (bz == DM_BOUNDARY_PERIODIC) ? -s : (PetscMax(-s, -k)); 1003711261dbSHong Zhang kend = (bz == DM_BOUNDARY_PERIODIC) ? s : (PetscMin(s, p - k - 1)); 1004711261dbSHong Zhang 1005711261dbSHong Zhang slot = i - gxs + gnx * (j - gys) + gnx * gny * (k - gzs); 1006711261dbSHong Zhang 1007711261dbSHong Zhang cnt = 0; 1008711261dbSHong Zhang for (l = 0; l < nc; l++) { 1009711261dbSHong Zhang for (ii = istart; ii < iend + 1; ii++) { 1010711261dbSHong Zhang for (jj = jstart; jj < jend + 1; jj++) { 1011711261dbSHong Zhang for (kk = kstart; kk < kend + 1; kk++) { 1012711261dbSHong Zhang if ((st == DMDA_STENCIL_BOX) || ((!ii && !jj) || (!jj && !kk) || (!ii && !kk))) { /* entries on star*/ 1013711261dbSHong Zhang cols[cnt++] = l + nc * (slot + ii + gnx * jj + gnx * gny * kk); 1014711261dbSHong Zhang } 1015711261dbSHong Zhang } 1016711261dbSHong Zhang } 1017711261dbSHong Zhang } 1018711261dbSHong Zhang rows[l] = l + nc * (slot); 1019711261dbSHong Zhang } 10209566063dSJacob Faibussowitsch PetscCall(MatSetValuesLocal(J, nc, rows, cnt, cols, values, INSERT_VALUES)); 1021711261dbSHong Zhang } 1022711261dbSHong Zhang } 1023711261dbSHong Zhang } 10249566063dSJacob Faibussowitsch PetscCall(PetscFree(values)); 1025e7e92044SBarry Smith /* do not copy values to GPU since they are all zero and not yet needed there */ 10269566063dSJacob Faibussowitsch PetscCall(MatBindToCPU(J, PETSC_TRUE)); 10279566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(J, MAT_FINAL_ASSEMBLY)); 10289566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(J, MAT_FINAL_ASSEMBLY)); 10299566063dSJacob Faibussowitsch PetscCall(MatBindToCPU(J, PETSC_FALSE)); 10309566063dSJacob Faibussowitsch PetscCall(MatSetOption(J, MAT_NEW_NONZERO_LOCATION_ERR, PETSC_TRUE)); 1031711261dbSHong Zhang } 10329566063dSJacob Faibussowitsch PetscCall(PetscFree2(rows, cols)); 10333ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1034711261dbSHong Zhang } 1035711261dbSHong Zhang 1036d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateMatrix_DA_2d_MPIAIJ(DM da, Mat J) 1037d71ae5a4SJacob Faibussowitsch { 1038c1154cd5SBarry 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; 103947c6ae99SBarry Smith PetscInt lstart, lend, pstart, pend, *dnz, *onz; 104047c6ae99SBarry Smith MPI_Comm comm; 1041bff4a2f0SMatthew G. Knepley DMBoundaryType bx, by; 1042844bd0d7SStefano Zampini ISLocalToGlobalMapping ltog, mltog; 1043aa219208SBarry Smith DMDAStencilType st; 1044b294de21SRichard Tran Mills PetscBool removedups = PETSC_FALSE, alreadyboundtocpu = PETSC_TRUE; 104547c6ae99SBarry Smith 104647c6ae99SBarry Smith PetscFunctionBegin; 104747c6ae99SBarry Smith /* 104847c6ae99SBarry Smith nc - number of components per grid point 104947c6ae99SBarry Smith col - number of colors needed in one direction for single component problem 105047c6ae99SBarry Smith */ 1051924e958dSJunchao Zhang PetscCall(DMDAGetInfo(da, &dim, &m, &n, NULL, &M, &N, NULL, &nc, &s, &bx, &by, NULL, &st)); 10521baa6e33SBarry Smith if (bx == DM_BOUNDARY_NONE && by == DM_BOUNDARY_NONE) PetscCall(MatSetOption(J, MAT_SORTED_FULL, PETSC_TRUE)); 105347c6ae99SBarry Smith col = 2 * s + 1; 1054c1154cd5SBarry Smith /* 1055c1154cd5SBarry Smith With one processor in periodic domains in a skinny dimension the code will label nonzero columns multiple times 1056c1154cd5SBarry Smith because of "wrapping" around the end of the domain hitting an entry already counted in the other direction. 1057c1154cd5SBarry Smith */ 1058c1154cd5SBarry Smith if (M == 1 && 2 * s >= m) removedups = PETSC_TRUE; 1059c1154cd5SBarry Smith if (N == 1 && 2 * s >= n) removedups = PETSC_TRUE; 10609566063dSJacob Faibussowitsch PetscCall(DMDAGetCorners(da, &xs, &ys, NULL, &nx, &ny, NULL)); 10619566063dSJacob Faibussowitsch PetscCall(DMDAGetGhostCorners(da, &gxs, &gys, NULL, &gnx, &gny, NULL)); 10629566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)da, &comm)); 106347c6ae99SBarry Smith 10649566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(nc, &rows, col * col * nc * nc, &cols)); 10659566063dSJacob Faibussowitsch PetscCall(DMGetLocalToGlobalMapping(da, <og)); 106647c6ae99SBarry Smith 10679566063dSJacob Faibussowitsch PetscCall(MatSetBlockSize(J, nc)); 106847c6ae99SBarry Smith /* determine the matrix preallocation information */ 1069d0609cedSBarry Smith MatPreallocateBegin(comm, nc * nx * ny, nc * nx * ny, dnz, onz); 107047c6ae99SBarry Smith for (i = xs; i < xs + nx; i++) { 1071bff4a2f0SMatthew G. Knepley pstart = (bx == DM_BOUNDARY_PERIODIC) ? -s : (PetscMax(-s, -i)); 1072bff4a2f0SMatthew G. Knepley pend = (bx == DM_BOUNDARY_PERIODIC) ? s : (PetscMin(s, m - i - 1)); 107347c6ae99SBarry Smith 107447c6ae99SBarry Smith for (j = ys; j < ys + ny; j++) { 107547c6ae99SBarry Smith slot = i - gxs + gnx * (j - gys); 107647c6ae99SBarry Smith 1077bff4a2f0SMatthew G. Knepley lstart = (by == DM_BOUNDARY_PERIODIC) ? -s : (PetscMax(-s, -j)); 1078bff4a2f0SMatthew G. Knepley lend = (by == DM_BOUNDARY_PERIODIC) ? s : (PetscMin(s, n - j - 1)); 107947c6ae99SBarry Smith 108047c6ae99SBarry Smith cnt = 0; 108147c6ae99SBarry Smith for (k = 0; k < nc; k++) { 108247c6ae99SBarry Smith for (l = lstart; l < lend + 1; l++) { 108347c6ae99SBarry Smith for (p = pstart; p < pend + 1; p++) { 1084aa219208SBarry Smith if ((st == DMDA_STENCIL_BOX) || (!l || !p)) { /* entries on star have either l = 0 or p = 0 */ 108547c6ae99SBarry Smith cols[cnt++] = k + nc * (slot + gnx * l + p); 108647c6ae99SBarry Smith } 108747c6ae99SBarry Smith } 108847c6ae99SBarry Smith } 108947c6ae99SBarry Smith rows[k] = k + nc * (slot); 109047c6ae99SBarry Smith } 10911baa6e33SBarry Smith if (removedups) PetscCall(MatPreallocateSetLocalRemoveDups(ltog, nc, rows, ltog, cnt, cols, dnz, onz)); 10921baa6e33SBarry Smith else PetscCall(MatPreallocateSetLocal(ltog, nc, rows, ltog, cnt, cols, dnz, onz)); 109347c6ae99SBarry Smith } 1094c1154cd5SBarry Smith } 10959566063dSJacob Faibussowitsch PetscCall(MatSetBlockSize(J, nc)); 10969566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocation(J, 0, dnz)); 10979566063dSJacob Faibussowitsch PetscCall(MatMPIAIJSetPreallocation(J, 0, dnz, 0, onz)); 1098d0609cedSBarry Smith MatPreallocateEnd(dnz, onz); 10999566063dSJacob Faibussowitsch PetscCall(MatGetLocalToGlobalMapping(J, &mltog, NULL)); 11001baa6e33SBarry Smith if (!mltog) PetscCall(MatSetLocalToGlobalMapping(J, ltog, ltog)); 110147c6ae99SBarry Smith 110247c6ae99SBarry Smith /* 110347c6ae99SBarry Smith For each node in the grid: we get the neighbors in the local (on processor ordering 110447c6ae99SBarry Smith that includes the ghost points) then MatSetValuesLocal() maps those indices to the global 110547c6ae99SBarry Smith PETSc ordering. 110647c6ae99SBarry Smith */ 1107fcfd50ebSBarry Smith if (!da->prealloc_only) { 110847c6ae99SBarry Smith for (i = xs; i < xs + nx; i++) { 1109bff4a2f0SMatthew G. Knepley pstart = (bx == DM_BOUNDARY_PERIODIC) ? -s : (PetscMax(-s, -i)); 1110bff4a2f0SMatthew G. Knepley pend = (bx == DM_BOUNDARY_PERIODIC) ? s : (PetscMin(s, m - i - 1)); 111147c6ae99SBarry Smith 111247c6ae99SBarry Smith for (j = ys; j < ys + ny; j++) { 111347c6ae99SBarry Smith slot = i - gxs + gnx * (j - gys); 111447c6ae99SBarry Smith 1115bff4a2f0SMatthew G. Knepley lstart = (by == DM_BOUNDARY_PERIODIC) ? -s : (PetscMax(-s, -j)); 1116bff4a2f0SMatthew G. Knepley lend = (by == DM_BOUNDARY_PERIODIC) ? s : (PetscMin(s, n - j - 1)); 111747c6ae99SBarry Smith 111847c6ae99SBarry Smith cnt = 0; 111947c6ae99SBarry Smith for (l = lstart; l < lend + 1; l++) { 112047c6ae99SBarry Smith for (p = pstart; p < pend + 1; p++) { 1121aa219208SBarry Smith if ((st == DMDA_STENCIL_BOX) || (!l || !p)) { /* entries on star have either l = 0 or p = 0 */ 1122071fcb05SBarry Smith cols[cnt++] = nc * (slot + gnx * l + p); 1123071fcb05SBarry Smith for (k = 1; k < nc; k++) { 11249371c9d4SSatish Balay cols[cnt] = 1 + cols[cnt - 1]; 11259371c9d4SSatish Balay cnt++; 112647c6ae99SBarry Smith } 112747c6ae99SBarry Smith } 112847c6ae99SBarry Smith } 112947c6ae99SBarry Smith } 1130071fcb05SBarry Smith for (k = 0; k < nc; k++) rows[k] = k + nc * (slot); 11319566063dSJacob Faibussowitsch PetscCall(MatSetValuesLocal(J, nc, rows, cnt, cols, NULL, INSERT_VALUES)); 113247c6ae99SBarry Smith } 113347c6ae99SBarry Smith } 1134e7e92044SBarry Smith /* do not copy values to GPU since they are all zero and not yet needed there */ 11359566063dSJacob Faibussowitsch PetscCall(MatBoundToCPU(J, &alreadyboundtocpu)); 11369566063dSJacob Faibussowitsch PetscCall(MatBindToCPU(J, PETSC_TRUE)); 11379566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(J, MAT_FINAL_ASSEMBLY)); 11389566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(J, MAT_FINAL_ASSEMBLY)); 11399566063dSJacob Faibussowitsch if (!alreadyboundtocpu) PetscCall(MatBindToCPU(J, PETSC_FALSE)); 11409566063dSJacob Faibussowitsch PetscCall(MatSetOption(J, MAT_NEW_NONZERO_LOCATION_ERR, PETSC_TRUE)); 11411baa6e33SBarry Smith if (bx == DM_BOUNDARY_NONE && by == DM_BOUNDARY_NONE) PetscCall(MatSetOption(J, MAT_SORTED_FULL, PETSC_FALSE)); 114247c6ae99SBarry Smith } 11439566063dSJacob Faibussowitsch PetscCall(PetscFree2(rows, cols)); 11443ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 114547c6ae99SBarry Smith } 114647c6ae99SBarry Smith 1147d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateMatrix_DA_2d_MPIAIJ_Fill(DM da, Mat J) 1148d71ae5a4SJacob Faibussowitsch { 114947c6ae99SBarry Smith PetscInt xs, ys, nx, ny, i, j, slot, gxs, gys, gnx, gny; 1150c1154cd5SBarry Smith PetscInt m, n, dim, s, *cols, k, nc, row, col, cnt, maxcnt = 0, l, p, M, N; 115147c6ae99SBarry Smith PetscInt lstart, lend, pstart, pend, *dnz, *onz; 115247c6ae99SBarry Smith DM_DA *dd = (DM_DA *)da->data; 115347c6ae99SBarry Smith PetscInt ifill_col, *ofill = dd->ofill, *dfill = dd->dfill; 115447c6ae99SBarry Smith MPI_Comm comm; 1155bff4a2f0SMatthew G. Knepley DMBoundaryType bx, by; 115645b6f7e9SBarry Smith ISLocalToGlobalMapping ltog; 1157aa219208SBarry Smith DMDAStencilType st; 1158c1154cd5SBarry Smith PetscBool removedups = PETSC_FALSE; 115947c6ae99SBarry Smith 116047c6ae99SBarry Smith PetscFunctionBegin; 116147c6ae99SBarry Smith /* 116247c6ae99SBarry Smith nc - number of components per grid point 116347c6ae99SBarry Smith col - number of colors needed in one direction for single component problem 116447c6ae99SBarry Smith */ 1165924e958dSJunchao Zhang PetscCall(DMDAGetInfo(da, &dim, &m, &n, NULL, &M, &N, NULL, &nc, &s, &bx, &by, NULL, &st)); 116647c6ae99SBarry Smith col = 2 * s + 1; 1167c1154cd5SBarry Smith /* 1168c1154cd5SBarry Smith With one processor in periodic domains in a skinny dimension the code will label nonzero columns multiple times 1169c1154cd5SBarry Smith because of "wrapping" around the end of the domain hitting an entry already counted in the other direction. 1170c1154cd5SBarry Smith */ 1171c1154cd5SBarry Smith if (M == 1 && 2 * s >= m) removedups = PETSC_TRUE; 1172c1154cd5SBarry Smith if (N == 1 && 2 * s >= n) removedups = PETSC_TRUE; 11739566063dSJacob Faibussowitsch PetscCall(DMDAGetCorners(da, &xs, &ys, NULL, &nx, &ny, NULL)); 11749566063dSJacob Faibussowitsch PetscCall(DMDAGetGhostCorners(da, &gxs, &gys, NULL, &gnx, &gny, NULL)); 11759566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)da, &comm)); 117647c6ae99SBarry Smith 11779566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(col * col * nc, &cols)); 11789566063dSJacob Faibussowitsch PetscCall(DMGetLocalToGlobalMapping(da, <og)); 117947c6ae99SBarry Smith 11809566063dSJacob Faibussowitsch PetscCall(MatSetBlockSize(J, nc)); 118147c6ae99SBarry Smith /* determine the matrix preallocation information */ 1182d0609cedSBarry Smith MatPreallocateBegin(comm, nc * nx * ny, nc * nx * ny, dnz, onz); 118347c6ae99SBarry Smith for (i = xs; i < xs + nx; i++) { 1184bff4a2f0SMatthew G. Knepley pstart = (bx == DM_BOUNDARY_PERIODIC) ? -s : (PetscMax(-s, -i)); 1185bff4a2f0SMatthew G. Knepley pend = (bx == DM_BOUNDARY_PERIODIC) ? s : (PetscMin(s, m - i - 1)); 118647c6ae99SBarry Smith 118747c6ae99SBarry Smith for (j = ys; j < ys + ny; j++) { 118847c6ae99SBarry Smith slot = i - gxs + gnx * (j - gys); 118947c6ae99SBarry Smith 1190bff4a2f0SMatthew G. Knepley lstart = (by == DM_BOUNDARY_PERIODIC) ? -s : (PetscMax(-s, -j)); 1191bff4a2f0SMatthew G. Knepley lend = (by == DM_BOUNDARY_PERIODIC) ? s : (PetscMin(s, n - j - 1)); 119247c6ae99SBarry Smith 119347c6ae99SBarry Smith for (k = 0; k < nc; k++) { 119447c6ae99SBarry Smith cnt = 0; 119547c6ae99SBarry Smith for (l = lstart; l < lend + 1; l++) { 119647c6ae99SBarry Smith for (p = pstart; p < pend + 1; p++) { 119747c6ae99SBarry Smith if (l || p) { 1198aa219208SBarry Smith if ((st == DMDA_STENCIL_BOX) || (!l || !p)) { /* entries on star */ 11998865f1eaSKarl Rupp for (ifill_col = ofill[k]; ifill_col < ofill[k + 1]; ifill_col++) cols[cnt++] = ofill[ifill_col] + nc * (slot + gnx * l + p); 120047c6ae99SBarry Smith } 120147c6ae99SBarry Smith } else { 120247c6ae99SBarry Smith if (dfill) { 12038865f1eaSKarl Rupp for (ifill_col = dfill[k]; ifill_col < dfill[k + 1]; ifill_col++) cols[cnt++] = dfill[ifill_col] + nc * (slot + gnx * l + p); 120447c6ae99SBarry Smith } else { 12058865f1eaSKarl Rupp for (ifill_col = 0; ifill_col < nc; ifill_col++) cols[cnt++] = ifill_col + nc * (slot + gnx * l + p); 120647c6ae99SBarry Smith } 120747c6ae99SBarry Smith } 120847c6ae99SBarry Smith } 120947c6ae99SBarry Smith } 121047c6ae99SBarry Smith row = k + nc * (slot); 1211c0ab637bSBarry Smith maxcnt = PetscMax(maxcnt, cnt); 12121baa6e33SBarry Smith if (removedups) PetscCall(MatPreallocateSetLocalRemoveDups(ltog, 1, &row, ltog, cnt, cols, dnz, onz)); 12131baa6e33SBarry Smith else PetscCall(MatPreallocateSetLocal(ltog, 1, &row, ltog, cnt, cols, dnz, onz)); 121447c6ae99SBarry Smith } 121547c6ae99SBarry Smith } 1216c1154cd5SBarry Smith } 12179566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocation(J, 0, dnz)); 12189566063dSJacob Faibussowitsch PetscCall(MatMPIAIJSetPreallocation(J, 0, dnz, 0, onz)); 1219d0609cedSBarry Smith MatPreallocateEnd(dnz, onz); 12209566063dSJacob Faibussowitsch PetscCall(MatSetLocalToGlobalMapping(J, ltog, ltog)); 122147c6ae99SBarry Smith 122247c6ae99SBarry Smith /* 122347c6ae99SBarry Smith For each node in the grid: we get the neighbors in the local (on processor ordering 122447c6ae99SBarry Smith that includes the ghost points) then MatSetValuesLocal() maps those indices to the global 122547c6ae99SBarry Smith PETSc ordering. 122647c6ae99SBarry Smith */ 1227fcfd50ebSBarry Smith if (!da->prealloc_only) { 122847c6ae99SBarry Smith for (i = xs; i < xs + nx; i++) { 1229bff4a2f0SMatthew G. Knepley pstart = (bx == DM_BOUNDARY_PERIODIC) ? -s : (PetscMax(-s, -i)); 1230bff4a2f0SMatthew G. Knepley pend = (bx == DM_BOUNDARY_PERIODIC) ? s : (PetscMin(s, m - i - 1)); 123147c6ae99SBarry Smith 123247c6ae99SBarry Smith for (j = ys; j < ys + ny; j++) { 123347c6ae99SBarry Smith slot = i - gxs + gnx * (j - gys); 123447c6ae99SBarry Smith 1235bff4a2f0SMatthew G. Knepley lstart = (by == DM_BOUNDARY_PERIODIC) ? -s : (PetscMax(-s, -j)); 1236bff4a2f0SMatthew G. Knepley lend = (by == DM_BOUNDARY_PERIODIC) ? s : (PetscMin(s, n - j - 1)); 123747c6ae99SBarry Smith 123847c6ae99SBarry Smith for (k = 0; k < nc; k++) { 123947c6ae99SBarry Smith cnt = 0; 124047c6ae99SBarry Smith for (l = lstart; l < lend + 1; l++) { 124147c6ae99SBarry Smith for (p = pstart; p < pend + 1; p++) { 124247c6ae99SBarry Smith if (l || p) { 1243aa219208SBarry Smith if ((st == DMDA_STENCIL_BOX) || (!l || !p)) { /* entries on star */ 12448865f1eaSKarl Rupp for (ifill_col = ofill[k]; ifill_col < ofill[k + 1]; ifill_col++) cols[cnt++] = ofill[ifill_col] + nc * (slot + gnx * l + p); 124547c6ae99SBarry Smith } 124647c6ae99SBarry Smith } else { 124747c6ae99SBarry Smith if (dfill) { 12488865f1eaSKarl Rupp for (ifill_col = dfill[k]; ifill_col < dfill[k + 1]; ifill_col++) cols[cnt++] = dfill[ifill_col] + nc * (slot + gnx * l + p); 124947c6ae99SBarry Smith } else { 12508865f1eaSKarl Rupp for (ifill_col = 0; ifill_col < nc; ifill_col++) cols[cnt++] = ifill_col + nc * (slot + gnx * l + p); 125147c6ae99SBarry Smith } 125247c6ae99SBarry Smith } 125347c6ae99SBarry Smith } 125447c6ae99SBarry Smith } 125547c6ae99SBarry Smith row = k + nc * (slot); 12569566063dSJacob Faibussowitsch PetscCall(MatSetValuesLocal(J, 1, &row, cnt, cols, NULL, INSERT_VALUES)); 125747c6ae99SBarry Smith } 125847c6ae99SBarry Smith } 125947c6ae99SBarry Smith } 1260e7e92044SBarry Smith /* do not copy values to GPU since they are all zero and not yet needed there */ 12619566063dSJacob Faibussowitsch PetscCall(MatBindToCPU(J, PETSC_TRUE)); 12629566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(J, MAT_FINAL_ASSEMBLY)); 12639566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(J, MAT_FINAL_ASSEMBLY)); 12649566063dSJacob Faibussowitsch PetscCall(MatBindToCPU(J, PETSC_FALSE)); 12659566063dSJacob Faibussowitsch PetscCall(MatSetOption(J, MAT_NEW_NONZERO_LOCATION_ERR, PETSC_TRUE)); 126647c6ae99SBarry Smith } 12679566063dSJacob Faibussowitsch PetscCall(PetscFree(cols)); 12683ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 126947c6ae99SBarry Smith } 127047c6ae99SBarry Smith 1271d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateMatrix_DA_3d_MPIAIJ(DM da, Mat J) 1272d71ae5a4SJacob Faibussowitsch { 127347c6ae99SBarry Smith PetscInt xs, ys, nx, ny, i, j, slot, gxs, gys, gnx, gny; 12740298fd71SBarry Smith PetscInt m, n, dim, s, *cols = NULL, k, nc, *rows = NULL, col, cnt, l, p, *dnz = NULL, *onz = NULL; 1275c1154cd5SBarry Smith PetscInt istart, iend, jstart, jend, kstart, kend, zs, nz, gzs, gnz, ii, jj, kk, M, N, P; 127647c6ae99SBarry Smith MPI_Comm comm; 1277bff4a2f0SMatthew G. Knepley DMBoundaryType bx, by, bz; 1278844bd0d7SStefano Zampini ISLocalToGlobalMapping ltog, mltog; 1279aa219208SBarry Smith DMDAStencilType st; 1280c1154cd5SBarry Smith PetscBool removedups = PETSC_FALSE; 128147c6ae99SBarry Smith 128247c6ae99SBarry Smith PetscFunctionBegin; 128347c6ae99SBarry Smith /* 128447c6ae99SBarry Smith nc - number of components per grid point 128547c6ae99SBarry Smith col - number of colors needed in one direction for single component problem 128647c6ae99SBarry Smith */ 12879566063dSJacob Faibussowitsch PetscCall(DMDAGetInfo(da, &dim, &m, &n, &p, &M, &N, &P, &nc, &s, &bx, &by, &bz, &st)); 128848a46eb9SPierre Jolivet if (bx == DM_BOUNDARY_NONE && by == DM_BOUNDARY_NONE && bz == DM_BOUNDARY_NONE) PetscCall(MatSetOption(J, MAT_SORTED_FULL, PETSC_TRUE)); 128947c6ae99SBarry Smith col = 2 * s + 1; 129047c6ae99SBarry Smith 1291c1154cd5SBarry Smith /* 1292c1154cd5SBarry Smith With one processor in periodic domains in a skinny dimension the code will label nonzero columns multiple times 1293c1154cd5SBarry Smith because of "wrapping" around the end of the domain hitting an entry already counted in the other direction. 1294c1154cd5SBarry Smith */ 1295c1154cd5SBarry Smith if (M == 1 && 2 * s >= m) removedups = PETSC_TRUE; 1296c1154cd5SBarry Smith if (N == 1 && 2 * s >= n) removedups = PETSC_TRUE; 1297c1154cd5SBarry Smith if (P == 1 && 2 * s >= p) removedups = PETSC_TRUE; 1298c1154cd5SBarry Smith 12999566063dSJacob Faibussowitsch PetscCall(DMDAGetCorners(da, &xs, &ys, &zs, &nx, &ny, &nz)); 13009566063dSJacob Faibussowitsch PetscCall(DMDAGetGhostCorners(da, &gxs, &gys, &gzs, &gnx, &gny, &gnz)); 13019566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)da, &comm)); 130247c6ae99SBarry Smith 13039566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(nc, &rows, col * col * col * nc * nc, &cols)); 13049566063dSJacob Faibussowitsch PetscCall(DMGetLocalToGlobalMapping(da, <og)); 130547c6ae99SBarry Smith 13069566063dSJacob Faibussowitsch PetscCall(MatSetBlockSize(J, nc)); 130747c6ae99SBarry Smith /* determine the matrix preallocation information */ 1308d0609cedSBarry Smith MatPreallocateBegin(comm, nc * nx * ny * nz, nc * nx * ny * nz, dnz, onz); 130947c6ae99SBarry Smith for (i = xs; i < xs + nx; i++) { 1310bff4a2f0SMatthew G. Knepley istart = (bx == DM_BOUNDARY_PERIODIC) ? -s : (PetscMax(-s, -i)); 1311bff4a2f0SMatthew G. Knepley iend = (bx == DM_BOUNDARY_PERIODIC) ? s : (PetscMin(s, m - i - 1)); 131247c6ae99SBarry Smith for (j = ys; j < ys + ny; j++) { 1313bff4a2f0SMatthew G. Knepley jstart = (by == DM_BOUNDARY_PERIODIC) ? -s : (PetscMax(-s, -j)); 1314bff4a2f0SMatthew G. Knepley jend = (by == DM_BOUNDARY_PERIODIC) ? s : (PetscMin(s, n - j - 1)); 131547c6ae99SBarry Smith for (k = zs; k < zs + nz; k++) { 1316bff4a2f0SMatthew G. Knepley kstart = (bz == DM_BOUNDARY_PERIODIC) ? -s : (PetscMax(-s, -k)); 1317bff4a2f0SMatthew G. Knepley kend = (bz == DM_BOUNDARY_PERIODIC) ? s : (PetscMin(s, p - k - 1)); 131847c6ae99SBarry Smith 131947c6ae99SBarry Smith slot = i - gxs + gnx * (j - gys) + gnx * gny * (k - gzs); 132047c6ae99SBarry Smith 132147c6ae99SBarry Smith cnt = 0; 132247c6ae99SBarry Smith for (l = 0; l < nc; l++) { 132347c6ae99SBarry Smith for (ii = istart; ii < iend + 1; ii++) { 132447c6ae99SBarry Smith for (jj = jstart; jj < jend + 1; jj++) { 132547c6ae99SBarry Smith for (kk = kstart; kk < kend + 1; kk++) { 1326aa219208SBarry Smith if ((st == DMDA_STENCIL_BOX) || ((!ii && !jj) || (!jj && !kk) || (!ii && !kk))) { /* entries on star*/ 132747c6ae99SBarry Smith cols[cnt++] = l + nc * (slot + ii + gnx * jj + gnx * gny * kk); 132847c6ae99SBarry Smith } 132947c6ae99SBarry Smith } 133047c6ae99SBarry Smith } 133147c6ae99SBarry Smith } 133247c6ae99SBarry Smith rows[l] = l + nc * (slot); 133347c6ae99SBarry Smith } 13341baa6e33SBarry Smith if (removedups) PetscCall(MatPreallocateSetLocalRemoveDups(ltog, nc, rows, ltog, cnt, cols, dnz, onz)); 13351baa6e33SBarry Smith else PetscCall(MatPreallocateSetLocal(ltog, nc, rows, ltog, cnt, cols, dnz, onz)); 133647c6ae99SBarry Smith } 133747c6ae99SBarry Smith } 1338c1154cd5SBarry Smith } 13399566063dSJacob Faibussowitsch PetscCall(MatSetBlockSize(J, nc)); 13409566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocation(J, 0, dnz)); 13419566063dSJacob Faibussowitsch PetscCall(MatMPIAIJSetPreallocation(J, 0, dnz, 0, onz)); 1342d0609cedSBarry Smith MatPreallocateEnd(dnz, onz); 13439566063dSJacob Faibussowitsch PetscCall(MatGetLocalToGlobalMapping(J, &mltog, NULL)); 134448a46eb9SPierre Jolivet if (!mltog) PetscCall(MatSetLocalToGlobalMapping(J, ltog, ltog)); 134547c6ae99SBarry Smith 134647c6ae99SBarry Smith /* 134747c6ae99SBarry Smith For each node in the grid: we get the neighbors in the local (on processor ordering 134847c6ae99SBarry Smith that includes the ghost points) then MatSetValuesLocal() maps those indices to the global 134947c6ae99SBarry Smith PETSc ordering. 135047c6ae99SBarry Smith */ 1351fcfd50ebSBarry Smith if (!da->prealloc_only) { 135247c6ae99SBarry Smith for (i = xs; i < xs + nx; i++) { 1353bff4a2f0SMatthew G. Knepley istart = (bx == DM_BOUNDARY_PERIODIC) ? -s : (PetscMax(-s, -i)); 1354bff4a2f0SMatthew G. Knepley iend = (bx == DM_BOUNDARY_PERIODIC) ? s : (PetscMin(s, m - i - 1)); 135547c6ae99SBarry Smith for (j = ys; j < ys + ny; j++) { 1356bff4a2f0SMatthew G. Knepley jstart = (by == DM_BOUNDARY_PERIODIC) ? -s : (PetscMax(-s, -j)); 1357bff4a2f0SMatthew G. Knepley jend = (by == DM_BOUNDARY_PERIODIC) ? s : (PetscMin(s, n - j - 1)); 135847c6ae99SBarry Smith for (k = zs; k < zs + nz; k++) { 1359bff4a2f0SMatthew G. Knepley kstart = (bz == DM_BOUNDARY_PERIODIC) ? -s : (PetscMax(-s, -k)); 1360bff4a2f0SMatthew G. Knepley kend = (bz == DM_BOUNDARY_PERIODIC) ? s : (PetscMin(s, p - k - 1)); 136147c6ae99SBarry Smith 136247c6ae99SBarry Smith slot = i - gxs + gnx * (j - gys) + gnx * gny * (k - gzs); 136347c6ae99SBarry Smith 136447c6ae99SBarry Smith cnt = 0; 136547c6ae99SBarry Smith for (kk = kstart; kk < kend + 1; kk++) { 1366071fcb05SBarry Smith for (jj = jstart; jj < jend + 1; jj++) { 1367071fcb05SBarry Smith for (ii = istart; ii < iend + 1; ii++) { 1368aa219208SBarry Smith if ((st == DMDA_STENCIL_BOX) || ((!ii && !jj) || (!jj && !kk) || (!ii && !kk))) { /* entries on star*/ 1369071fcb05SBarry Smith cols[cnt++] = nc * (slot + ii + gnx * jj + gnx * gny * kk); 1370071fcb05SBarry Smith for (l = 1; l < nc; l++) { 13719371c9d4SSatish Balay cols[cnt] = 1 + cols[cnt - 1]; 13729371c9d4SSatish Balay cnt++; 137347c6ae99SBarry Smith } 137447c6ae99SBarry Smith } 137547c6ae99SBarry Smith } 137647c6ae99SBarry Smith } 137747c6ae99SBarry Smith } 13789371c9d4SSatish Balay rows[0] = nc * (slot); 13799371c9d4SSatish Balay for (l = 1; l < nc; l++) rows[l] = 1 + rows[l - 1]; 13809566063dSJacob Faibussowitsch PetscCall(MatSetValuesLocal(J, nc, rows, cnt, cols, NULL, INSERT_VALUES)); 138147c6ae99SBarry Smith } 138247c6ae99SBarry Smith } 138347c6ae99SBarry Smith } 1384e7e92044SBarry Smith /* do not copy values to GPU since they are all zero and not yet needed there */ 13859566063dSJacob Faibussowitsch PetscCall(MatBindToCPU(J, PETSC_TRUE)); 13869566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(J, MAT_FINAL_ASSEMBLY)); 13879566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(J, MAT_FINAL_ASSEMBLY)); 138848a46eb9SPierre Jolivet if (bx == DM_BOUNDARY_NONE && by == DM_BOUNDARY_NONE && bz == DM_BOUNDARY_NONE) PetscCall(MatSetOption(J, MAT_SORTED_FULL, PETSC_FALSE)); 13899566063dSJacob Faibussowitsch PetscCall(MatBindToCPU(J, PETSC_FALSE)); 13909566063dSJacob Faibussowitsch PetscCall(MatSetOption(J, MAT_NEW_NONZERO_LOCATION_ERR, PETSC_TRUE)); 139147c6ae99SBarry Smith } 13929566063dSJacob Faibussowitsch PetscCall(PetscFree2(rows, cols)); 13933ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 139447c6ae99SBarry Smith } 139547c6ae99SBarry Smith 1396d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateMatrix_DA_1d_MPIAIJ_Fill(DM da, Mat J) 1397d71ae5a4SJacob Faibussowitsch { 1398ce308e1dSBarry Smith DM_DA *dd = (DM_DA *)da->data; 1399ce308e1dSBarry Smith PetscInt xs, nx, i, j, gxs, gnx, row, k, l; 14008d4c968fSBarry Smith PetscInt m, dim, s, *cols = NULL, nc, cnt, maxcnt = 0, *ocols; 14010acb5bebSBarry Smith PetscInt *ofill = dd->ofill, *dfill = dd->dfill; 1402bff4a2f0SMatthew G. Knepley DMBoundaryType bx; 140345b6f7e9SBarry Smith ISLocalToGlobalMapping ltog; 1404ce308e1dSBarry Smith PetscMPIInt rank, size; 1405ce308e1dSBarry Smith 1406ce308e1dSBarry Smith PetscFunctionBegin; 14079566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)da), &rank)); 14089566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)da), &size)); 1409ce308e1dSBarry Smith 1410ce308e1dSBarry Smith /* 1411ce308e1dSBarry Smith nc - number of components per grid point 1412ce308e1dSBarry Smith */ 14139566063dSJacob Faibussowitsch PetscCall(DMDAGetInfo(da, &dim, &m, NULL, NULL, NULL, NULL, NULL, &nc, &s, &bx, NULL, NULL, NULL)); 141408401ef6SPierre Jolivet PetscCheck(s <= 1, PetscObjectComm((PetscObject)da), PETSC_ERR_SUP, "Matrix creation for 1d not implemented correctly for stencil width larger than 1"); 14159566063dSJacob Faibussowitsch PetscCall(DMDAGetCorners(da, &xs, NULL, NULL, &nx, NULL, NULL)); 14169566063dSJacob Faibussowitsch PetscCall(DMDAGetGhostCorners(da, &gxs, NULL, NULL, &gnx, NULL, NULL)); 1417ce308e1dSBarry Smith 14189566063dSJacob Faibussowitsch PetscCall(MatSetBlockSize(J, nc)); 14199566063dSJacob Faibussowitsch PetscCall(PetscCalloc2(nx * nc, &cols, nx * nc, &ocols)); 1420ce308e1dSBarry Smith 1421ce308e1dSBarry Smith /* 1422ce308e1dSBarry Smith note should be smaller for first and last process with no periodic 1423ce308e1dSBarry Smith does not handle dfill 1424ce308e1dSBarry Smith */ 1425ce308e1dSBarry Smith cnt = 0; 1426ce308e1dSBarry Smith /* coupling with process to the left */ 1427ce308e1dSBarry Smith for (i = 0; i < s; i++) { 1428ce308e1dSBarry Smith for (j = 0; j < nc; j++) { 1429dd400576SPatrick Sanan ocols[cnt] = ((rank == 0) ? 0 : (s - i) * (ofill[j + 1] - ofill[j])); 14300acb5bebSBarry Smith cols[cnt] = dfill[j + 1] - dfill[j] + (s + i) * (ofill[j + 1] - ofill[j]); 1431dd400576SPatrick Sanan if (rank == 0 && (dd->bx == DM_BOUNDARY_PERIODIC)) { 1432831644c1SBarry Smith if (size > 1) ocols[cnt] += (s - i) * (ofill[j + 1] - ofill[j]); 1433831644c1SBarry Smith else cols[cnt] += (s - i) * (ofill[j + 1] - ofill[j]); 1434831644c1SBarry Smith } 1435c0ab637bSBarry Smith maxcnt = PetscMax(maxcnt, ocols[cnt] + cols[cnt]); 1436ce308e1dSBarry Smith cnt++; 1437ce308e1dSBarry Smith } 1438ce308e1dSBarry Smith } 1439ce308e1dSBarry Smith for (i = s; i < nx - s; i++) { 1440ce308e1dSBarry Smith for (j = 0; j < nc; j++) { 14410acb5bebSBarry Smith cols[cnt] = dfill[j + 1] - dfill[j] + 2 * s * (ofill[j + 1] - ofill[j]); 1442c0ab637bSBarry Smith maxcnt = PetscMax(maxcnt, ocols[cnt] + cols[cnt]); 1443ce308e1dSBarry Smith cnt++; 1444ce308e1dSBarry Smith } 1445ce308e1dSBarry Smith } 1446ce308e1dSBarry Smith /* coupling with process to the right */ 1447ce308e1dSBarry Smith for (i = nx - s; i < nx; i++) { 1448ce308e1dSBarry Smith for (j = 0; j < nc; j++) { 1449ce308e1dSBarry Smith ocols[cnt] = ((rank == (size - 1)) ? 0 : (i - nx + s + 1) * (ofill[j + 1] - ofill[j])); 14500acb5bebSBarry Smith cols[cnt] = dfill[j + 1] - dfill[j] + (s + nx - i - 1) * (ofill[j + 1] - ofill[j]); 1451831644c1SBarry Smith if ((rank == size - 1) && (dd->bx == DM_BOUNDARY_PERIODIC)) { 1452831644c1SBarry Smith if (size > 1) ocols[cnt] += (i - nx + s + 1) * (ofill[j + 1] - ofill[j]); 1453831644c1SBarry Smith else cols[cnt] += (i - nx + s + 1) * (ofill[j + 1] - ofill[j]); 1454831644c1SBarry Smith } 1455c0ab637bSBarry Smith maxcnt = PetscMax(maxcnt, ocols[cnt] + cols[cnt]); 1456ce308e1dSBarry Smith cnt++; 1457ce308e1dSBarry Smith } 1458ce308e1dSBarry Smith } 1459ce308e1dSBarry Smith 14609566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocation(J, 0, cols)); 14619566063dSJacob Faibussowitsch PetscCall(MatMPIAIJSetPreallocation(J, 0, cols, 0, ocols)); 14629566063dSJacob Faibussowitsch PetscCall(PetscFree2(cols, ocols)); 1463ce308e1dSBarry Smith 14649566063dSJacob Faibussowitsch PetscCall(DMGetLocalToGlobalMapping(da, <og)); 14659566063dSJacob Faibussowitsch PetscCall(MatSetLocalToGlobalMapping(J, ltog, ltog)); 1466ce308e1dSBarry Smith 1467ce308e1dSBarry Smith /* 1468ce308e1dSBarry Smith For each node in the grid: we get the neighbors in the local (on processor ordering 1469ce308e1dSBarry Smith that includes the ghost points) then MatSetValuesLocal() maps those indices to the global 1470ce308e1dSBarry Smith PETSc ordering. 1471ce308e1dSBarry Smith */ 1472ce308e1dSBarry Smith if (!da->prealloc_only) { 14739566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(maxcnt, &cols)); 1474ce308e1dSBarry Smith row = xs * nc; 1475ce308e1dSBarry Smith /* coupling with process to the left */ 1476ce308e1dSBarry Smith for (i = xs; i < xs + s; i++) { 1477ce308e1dSBarry Smith for (j = 0; j < nc; j++) { 1478ce308e1dSBarry Smith cnt = 0; 1479ce308e1dSBarry Smith if (rank) { 1480ce308e1dSBarry Smith for (l = 0; l < s; l++) { 1481ce308e1dSBarry Smith for (k = ofill[j]; k < ofill[j + 1]; k++) cols[cnt++] = (i - s + l) * nc + ofill[k]; 1482ce308e1dSBarry Smith } 1483ce308e1dSBarry Smith } 1484dd400576SPatrick Sanan if (rank == 0 && (dd->bx == DM_BOUNDARY_PERIODIC)) { 1485831644c1SBarry Smith for (l = 0; l < s; l++) { 1486831644c1SBarry Smith for (k = ofill[j]; k < ofill[j + 1]; k++) cols[cnt++] = (m + i - s - l) * nc + ofill[k]; 1487831644c1SBarry Smith } 1488831644c1SBarry Smith } 14890acb5bebSBarry Smith if (dfill) { 1490ad540459SPierre Jolivet for (k = dfill[j]; k < dfill[j + 1]; k++) cols[cnt++] = i * nc + dfill[k]; 14910acb5bebSBarry Smith } else { 1492ad540459SPierre Jolivet for (k = 0; k < nc; k++) cols[cnt++] = i * nc + k; 14930acb5bebSBarry Smith } 1494ce308e1dSBarry Smith for (l = 0; l < s; l++) { 1495ce308e1dSBarry Smith for (k = ofill[j]; k < ofill[j + 1]; k++) cols[cnt++] = (i + s - l) * nc + ofill[k]; 1496ce308e1dSBarry Smith } 14979566063dSJacob Faibussowitsch PetscCall(MatSetValues(J, 1, &row, cnt, cols, NULL, INSERT_VALUES)); 1498ce308e1dSBarry Smith row++; 1499ce308e1dSBarry Smith } 1500ce308e1dSBarry Smith } 1501ce308e1dSBarry Smith for (i = xs + s; i < xs + nx - s; i++) { 1502ce308e1dSBarry Smith for (j = 0; j < nc; j++) { 1503ce308e1dSBarry Smith cnt = 0; 1504ce308e1dSBarry Smith for (l = 0; l < s; l++) { 1505ce308e1dSBarry Smith for (k = ofill[j]; k < ofill[j + 1]; k++) cols[cnt++] = (i - s + l) * nc + ofill[k]; 1506ce308e1dSBarry Smith } 15070acb5bebSBarry Smith if (dfill) { 1508ad540459SPierre Jolivet for (k = dfill[j]; k < dfill[j + 1]; k++) cols[cnt++] = i * nc + dfill[k]; 15090acb5bebSBarry Smith } else { 1510ad540459SPierre Jolivet for (k = 0; k < nc; k++) cols[cnt++] = i * nc + k; 15110acb5bebSBarry Smith } 1512ce308e1dSBarry Smith for (l = 0; l < s; l++) { 1513ce308e1dSBarry Smith for (k = ofill[j]; k < ofill[j + 1]; k++) cols[cnt++] = (i + s - l) * nc + ofill[k]; 1514ce308e1dSBarry Smith } 15159566063dSJacob Faibussowitsch PetscCall(MatSetValues(J, 1, &row, cnt, cols, NULL, INSERT_VALUES)); 1516ce308e1dSBarry Smith row++; 1517ce308e1dSBarry Smith } 1518ce308e1dSBarry Smith } 1519ce308e1dSBarry Smith /* coupling with process to the right */ 1520ce308e1dSBarry Smith for (i = xs + nx - s; i < xs + nx; i++) { 1521ce308e1dSBarry Smith for (j = 0; j < nc; j++) { 1522ce308e1dSBarry Smith cnt = 0; 1523ce308e1dSBarry Smith for (l = 0; l < s; l++) { 1524ce308e1dSBarry Smith for (k = ofill[j]; k < ofill[j + 1]; k++) cols[cnt++] = (i - s + l) * nc + ofill[k]; 1525ce308e1dSBarry Smith } 15260acb5bebSBarry Smith if (dfill) { 1527ad540459SPierre Jolivet for (k = dfill[j]; k < dfill[j + 1]; k++) cols[cnt++] = i * nc + dfill[k]; 15280acb5bebSBarry Smith } else { 1529ad540459SPierre Jolivet for (k = 0; k < nc; k++) cols[cnt++] = i * nc + k; 15300acb5bebSBarry Smith } 1531ce308e1dSBarry Smith if (rank < size - 1) { 1532ce308e1dSBarry Smith for (l = 0; l < s; l++) { 1533ce308e1dSBarry Smith for (k = ofill[j]; k < ofill[j + 1]; k++) cols[cnt++] = (i + s - l) * nc + ofill[k]; 1534ce308e1dSBarry Smith } 1535ce308e1dSBarry Smith } 1536831644c1SBarry Smith if ((rank == size - 1) && (dd->bx == DM_BOUNDARY_PERIODIC)) { 1537831644c1SBarry Smith for (l = 0; l < s; l++) { 1538831644c1SBarry Smith for (k = ofill[j]; k < ofill[j + 1]; k++) cols[cnt++] = (i - s - l - m + 2) * nc + ofill[k]; 1539831644c1SBarry Smith } 1540831644c1SBarry Smith } 15419566063dSJacob Faibussowitsch PetscCall(MatSetValues(J, 1, &row, cnt, cols, NULL, INSERT_VALUES)); 1542ce308e1dSBarry Smith row++; 1543ce308e1dSBarry Smith } 1544ce308e1dSBarry Smith } 15459566063dSJacob Faibussowitsch PetscCall(PetscFree(cols)); 1546e7e92044SBarry Smith /* do not copy values to GPU since they are all zero and not yet needed there */ 15479566063dSJacob Faibussowitsch PetscCall(MatBindToCPU(J, PETSC_TRUE)); 15489566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(J, MAT_FINAL_ASSEMBLY)); 15499566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(J, MAT_FINAL_ASSEMBLY)); 15509566063dSJacob Faibussowitsch PetscCall(MatBindToCPU(J, PETSC_FALSE)); 15519566063dSJacob Faibussowitsch PetscCall(MatSetOption(J, MAT_NEW_NONZERO_LOCATION_ERR, PETSC_TRUE)); 1552ce308e1dSBarry Smith } 15533ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1554ce308e1dSBarry Smith } 1555ce308e1dSBarry Smith 1556d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateMatrix_DA_1d_MPIAIJ(DM da, Mat J) 1557d71ae5a4SJacob Faibussowitsch { 155847c6ae99SBarry Smith PetscInt xs, nx, i, i1, slot, gxs, gnx; 15590298fd71SBarry Smith PetscInt m, dim, s, *cols = NULL, nc, *rows = NULL, col, cnt, l; 156047c6ae99SBarry Smith PetscInt istart, iend; 1561bff4a2f0SMatthew G. Knepley DMBoundaryType bx; 1562844bd0d7SStefano Zampini ISLocalToGlobalMapping ltog, mltog; 156347c6ae99SBarry Smith 156447c6ae99SBarry Smith PetscFunctionBegin; 156547c6ae99SBarry Smith /* 156647c6ae99SBarry Smith nc - number of components per grid point 156747c6ae99SBarry Smith col - number of colors needed in one direction for single component problem 156847c6ae99SBarry Smith */ 15699566063dSJacob Faibussowitsch PetscCall(DMDAGetInfo(da, &dim, &m, NULL, NULL, NULL, NULL, NULL, &nc, &s, &bx, NULL, NULL, NULL)); 157048a46eb9SPierre Jolivet if (bx == DM_BOUNDARY_NONE) PetscCall(MatSetOption(J, MAT_SORTED_FULL, PETSC_TRUE)); 157147c6ae99SBarry Smith col = 2 * s + 1; 157247c6ae99SBarry Smith 15739566063dSJacob Faibussowitsch PetscCall(DMDAGetCorners(da, &xs, NULL, NULL, &nx, NULL, NULL)); 15749566063dSJacob Faibussowitsch PetscCall(DMDAGetGhostCorners(da, &gxs, NULL, NULL, &gnx, NULL, NULL)); 157547c6ae99SBarry Smith 15769566063dSJacob Faibussowitsch PetscCall(MatSetBlockSize(J, nc)); 15779566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocation(J, col * nc, NULL)); 15789566063dSJacob Faibussowitsch PetscCall(MatMPIAIJSetPreallocation(J, col * nc, NULL, col * nc, NULL)); 157947c6ae99SBarry Smith 15809566063dSJacob Faibussowitsch PetscCall(DMGetLocalToGlobalMapping(da, <og)); 15819566063dSJacob Faibussowitsch PetscCall(MatGetLocalToGlobalMapping(J, &mltog, NULL)); 158248a46eb9SPierre Jolivet if (!mltog) PetscCall(MatSetLocalToGlobalMapping(J, ltog, ltog)); 158347c6ae99SBarry Smith 158447c6ae99SBarry Smith /* 158547c6ae99SBarry Smith For each node in the grid: we get the neighbors in the local (on processor ordering 158647c6ae99SBarry Smith that includes the ghost points) then MatSetValuesLocal() maps those indices to the global 158747c6ae99SBarry Smith PETSc ordering. 158847c6ae99SBarry Smith */ 1589fcfd50ebSBarry Smith if (!da->prealloc_only) { 15909566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(nc, &rows, col * nc * nc, &cols)); 159147c6ae99SBarry Smith for (i = xs; i < xs + nx; i++) { 159247c6ae99SBarry Smith istart = PetscMax(-s, gxs - i); 159347c6ae99SBarry Smith iend = PetscMin(s, gxs + gnx - i - 1); 159447c6ae99SBarry Smith slot = i - gxs; 159547c6ae99SBarry Smith 159647c6ae99SBarry Smith cnt = 0; 159747c6ae99SBarry Smith for (i1 = istart; i1 < iend + 1; i1++) { 1598071fcb05SBarry Smith cols[cnt++] = nc * (slot + i1); 1599071fcb05SBarry Smith for (l = 1; l < nc; l++) { 16009371c9d4SSatish Balay cols[cnt] = 1 + cols[cnt - 1]; 16019371c9d4SSatish Balay cnt++; 160247c6ae99SBarry Smith } 160347c6ae99SBarry Smith } 16049371c9d4SSatish Balay rows[0] = nc * (slot); 16059371c9d4SSatish Balay for (l = 1; l < nc; l++) rows[l] = 1 + rows[l - 1]; 16069566063dSJacob Faibussowitsch PetscCall(MatSetValuesLocal(J, nc, rows, cnt, cols, NULL, INSERT_VALUES)); 160747c6ae99SBarry Smith } 1608e7e92044SBarry Smith /* do not copy values to GPU since they are all zero and not yet needed there */ 16099566063dSJacob Faibussowitsch PetscCall(MatBindToCPU(J, PETSC_TRUE)); 16109566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(J, MAT_FINAL_ASSEMBLY)); 16119566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(J, MAT_FINAL_ASSEMBLY)); 161248a46eb9SPierre Jolivet if (bx == DM_BOUNDARY_NONE) PetscCall(MatSetOption(J, MAT_SORTED_FULL, PETSC_FALSE)); 16139566063dSJacob Faibussowitsch PetscCall(MatBindToCPU(J, PETSC_FALSE)); 16149566063dSJacob Faibussowitsch PetscCall(MatSetOption(J, MAT_NEW_NONZERO_LOCATION_ERR, PETSC_TRUE)); 16159566063dSJacob Faibussowitsch PetscCall(PetscFree2(rows, cols)); 1616ce308e1dSBarry Smith } 16173ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 161847c6ae99SBarry Smith } 161947c6ae99SBarry Smith 1620d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateMatrix_DA_1d_SeqAIJ_NoPreallocation(DM da, Mat J) 1621d71ae5a4SJacob Faibussowitsch { 162219b08ed1SBarry Smith PetscInt xs, nx, i, i1, slot, gxs, gnx; 162319b08ed1SBarry Smith PetscInt m, dim, s, *cols = NULL, nc, *rows = NULL, col, cnt, l; 162419b08ed1SBarry Smith PetscInt istart, iend; 162519b08ed1SBarry Smith DMBoundaryType bx; 162619b08ed1SBarry Smith ISLocalToGlobalMapping ltog, mltog; 162719b08ed1SBarry Smith 162819b08ed1SBarry Smith PetscFunctionBegin; 162919b08ed1SBarry Smith /* 163019b08ed1SBarry Smith nc - number of components per grid point 163119b08ed1SBarry Smith col - number of colors needed in one direction for single component problem 163219b08ed1SBarry Smith */ 16339566063dSJacob Faibussowitsch PetscCall(DMDAGetInfo(da, &dim, &m, NULL, NULL, NULL, NULL, NULL, &nc, &s, &bx, NULL, NULL, NULL)); 163419b08ed1SBarry Smith col = 2 * s + 1; 163519b08ed1SBarry Smith 16369566063dSJacob Faibussowitsch PetscCall(DMDAGetCorners(da, &xs, NULL, NULL, &nx, NULL, NULL)); 16379566063dSJacob Faibussowitsch PetscCall(DMDAGetGhostCorners(da, &gxs, NULL, NULL, &gnx, NULL, NULL)); 163819b08ed1SBarry Smith 16399566063dSJacob Faibussowitsch PetscCall(MatSetBlockSize(J, nc)); 16409566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetTotalPreallocation(J, nx * nc * col * nc)); 164119b08ed1SBarry Smith 16429566063dSJacob Faibussowitsch PetscCall(DMGetLocalToGlobalMapping(da, <og)); 16439566063dSJacob Faibussowitsch PetscCall(MatGetLocalToGlobalMapping(J, &mltog, NULL)); 164448a46eb9SPierre Jolivet if (!mltog) PetscCall(MatSetLocalToGlobalMapping(J, ltog, ltog)); 164519b08ed1SBarry Smith 164619b08ed1SBarry Smith /* 164719b08ed1SBarry Smith For each node in the grid: we get the neighbors in the local (on processor ordering 164819b08ed1SBarry Smith that includes the ghost points) then MatSetValuesLocal() maps those indices to the global 164919b08ed1SBarry Smith PETSc ordering. 165019b08ed1SBarry Smith */ 165119b08ed1SBarry Smith if (!da->prealloc_only) { 16529566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(nc, &rows, col * nc * nc, &cols)); 165319b08ed1SBarry Smith for (i = xs; i < xs + nx; i++) { 165419b08ed1SBarry Smith istart = PetscMax(-s, gxs - i); 165519b08ed1SBarry Smith iend = PetscMin(s, gxs + gnx - i - 1); 165619b08ed1SBarry Smith slot = i - gxs; 165719b08ed1SBarry Smith 165819b08ed1SBarry Smith cnt = 0; 165919b08ed1SBarry Smith for (i1 = istart; i1 < iend + 1; i1++) { 166019b08ed1SBarry Smith cols[cnt++] = nc * (slot + i1); 166119b08ed1SBarry Smith for (l = 1; l < nc; l++) { 16629371c9d4SSatish Balay cols[cnt] = 1 + cols[cnt - 1]; 16639371c9d4SSatish Balay cnt++; 166419b08ed1SBarry Smith } 166519b08ed1SBarry Smith } 16669371c9d4SSatish Balay rows[0] = nc * (slot); 16679371c9d4SSatish Balay for (l = 1; l < nc; l++) rows[l] = 1 + rows[l - 1]; 16689566063dSJacob Faibussowitsch PetscCall(MatSetValuesLocal(J, nc, rows, cnt, cols, NULL, INSERT_VALUES)); 166919b08ed1SBarry Smith } 167019b08ed1SBarry Smith /* do not copy values to GPU since they are all zero and not yet needed there */ 16719566063dSJacob Faibussowitsch PetscCall(MatBindToCPU(J, PETSC_TRUE)); 16729566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(J, MAT_FINAL_ASSEMBLY)); 16739566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(J, MAT_FINAL_ASSEMBLY)); 167448a46eb9SPierre Jolivet if (bx == DM_BOUNDARY_NONE) PetscCall(MatSetOption(J, MAT_SORTED_FULL, PETSC_FALSE)); 16759566063dSJacob Faibussowitsch PetscCall(MatBindToCPU(J, PETSC_FALSE)); 16769566063dSJacob Faibussowitsch PetscCall(MatSetOption(J, MAT_NEW_NONZERO_LOCATION_ERR, PETSC_TRUE)); 16779566063dSJacob Faibussowitsch PetscCall(PetscFree2(rows, cols)); 167819b08ed1SBarry Smith } 16799566063dSJacob Faibussowitsch PetscCall(MatSetOption(J, MAT_SORTED_FULL, PETSC_FALSE)); 16803ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 168119b08ed1SBarry Smith } 168219b08ed1SBarry Smith 1683d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateMatrix_DA_2d_MPIBAIJ(DM da, Mat J) 1684d71ae5a4SJacob Faibussowitsch { 168547c6ae99SBarry Smith PetscInt xs, ys, nx, ny, i, j, slot, gxs, gys, gnx, gny; 168647c6ae99SBarry Smith PetscInt m, n, dim, s, *cols, nc, col, cnt, *dnz, *onz; 168747c6ae99SBarry Smith PetscInt istart, iend, jstart, jend, ii, jj; 168847c6ae99SBarry Smith MPI_Comm comm; 168947c6ae99SBarry Smith PetscScalar *values; 1690bff4a2f0SMatthew G. Knepley DMBoundaryType bx, by; 1691aa219208SBarry Smith DMDAStencilType st; 169245b6f7e9SBarry Smith ISLocalToGlobalMapping ltog; 169347c6ae99SBarry Smith 169447c6ae99SBarry Smith PetscFunctionBegin; 169547c6ae99SBarry Smith /* 169647c6ae99SBarry Smith nc - number of components per grid point 169747c6ae99SBarry Smith col - number of colors needed in one direction for single component problem 169847c6ae99SBarry Smith */ 16999566063dSJacob Faibussowitsch PetscCall(DMDAGetInfo(da, &dim, &m, &n, NULL, NULL, NULL, NULL, &nc, &s, &bx, &by, NULL, &st)); 170047c6ae99SBarry Smith col = 2 * s + 1; 170147c6ae99SBarry Smith 17029566063dSJacob Faibussowitsch PetscCall(DMDAGetCorners(da, &xs, &ys, NULL, &nx, &ny, NULL)); 17039566063dSJacob Faibussowitsch PetscCall(DMDAGetGhostCorners(da, &gxs, &gys, NULL, &gnx, &gny, NULL)); 17049566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)da, &comm)); 170547c6ae99SBarry Smith 17069566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(col * col * nc * nc, &cols)); 170747c6ae99SBarry Smith 17089566063dSJacob Faibussowitsch PetscCall(DMGetLocalToGlobalMapping(da, <og)); 170947c6ae99SBarry Smith 171047c6ae99SBarry Smith /* determine the matrix preallocation information */ 1711d0609cedSBarry Smith MatPreallocateBegin(comm, nx * ny, nx * ny, dnz, onz); 171247c6ae99SBarry Smith for (i = xs; i < xs + nx; i++) { 1713bff4a2f0SMatthew G. Knepley istart = (bx == DM_BOUNDARY_PERIODIC) ? -s : (PetscMax(-s, -i)); 1714bff4a2f0SMatthew G. Knepley iend = (bx == DM_BOUNDARY_PERIODIC) ? s : (PetscMin(s, m - i - 1)); 171547c6ae99SBarry Smith for (j = ys; j < ys + ny; j++) { 1716bff4a2f0SMatthew G. Knepley jstart = (by == DM_BOUNDARY_PERIODIC) ? -s : (PetscMax(-s, -j)); 1717bff4a2f0SMatthew G. Knepley jend = (by == DM_BOUNDARY_PERIODIC) ? s : (PetscMin(s, n - j - 1)); 171847c6ae99SBarry Smith slot = i - gxs + gnx * (j - gys); 171947c6ae99SBarry Smith 172047c6ae99SBarry Smith /* Find block columns in block row */ 172147c6ae99SBarry Smith cnt = 0; 172247c6ae99SBarry Smith for (ii = istart; ii < iend + 1; ii++) { 172347c6ae99SBarry Smith for (jj = jstart; jj < jend + 1; jj++) { 1724aa219208SBarry Smith if (st == DMDA_STENCIL_BOX || !ii || !jj) { /* BOX or on the STAR */ 172547c6ae99SBarry Smith cols[cnt++] = slot + ii + gnx * jj; 172647c6ae99SBarry Smith } 172747c6ae99SBarry Smith } 172847c6ae99SBarry Smith } 17299566063dSJacob Faibussowitsch PetscCall(MatPreallocateSetLocalBlock(ltog, 1, &slot, ltog, cnt, cols, dnz, onz)); 173047c6ae99SBarry Smith } 173147c6ae99SBarry Smith } 17329566063dSJacob Faibussowitsch PetscCall(MatSeqBAIJSetPreallocation(J, nc, 0, dnz)); 17339566063dSJacob Faibussowitsch PetscCall(MatMPIBAIJSetPreallocation(J, nc, 0, dnz, 0, onz)); 1734d0609cedSBarry Smith MatPreallocateEnd(dnz, onz); 173547c6ae99SBarry Smith 17369566063dSJacob Faibussowitsch PetscCall(MatSetLocalToGlobalMapping(J, ltog, ltog)); 173747c6ae99SBarry Smith 173847c6ae99SBarry Smith /* 173947c6ae99SBarry Smith For each node in the grid: we get the neighbors in the local (on processor ordering 174047c6ae99SBarry Smith that includes the ghost points) then MatSetValuesLocal() maps those indices to the global 174147c6ae99SBarry Smith PETSc ordering. 174247c6ae99SBarry Smith */ 1743fcfd50ebSBarry Smith if (!da->prealloc_only) { 17449566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(col * col * nc * nc, &values)); 174547c6ae99SBarry Smith for (i = xs; i < xs + nx; i++) { 1746bff4a2f0SMatthew G. Knepley istart = (bx == DM_BOUNDARY_PERIODIC) ? -s : (PetscMax(-s, -i)); 1747bff4a2f0SMatthew G. Knepley iend = (bx == DM_BOUNDARY_PERIODIC) ? s : (PetscMin(s, m - i - 1)); 174847c6ae99SBarry Smith for (j = ys; j < ys + ny; j++) { 1749bff4a2f0SMatthew G. Knepley jstart = (by == DM_BOUNDARY_PERIODIC) ? -s : (PetscMax(-s, -j)); 1750bff4a2f0SMatthew G. Knepley jend = (by == DM_BOUNDARY_PERIODIC) ? s : (PetscMin(s, n - j - 1)); 175147c6ae99SBarry Smith slot = i - gxs + gnx * (j - gys); 175247c6ae99SBarry Smith cnt = 0; 175347c6ae99SBarry Smith for (ii = istart; ii < iend + 1; ii++) { 175447c6ae99SBarry Smith for (jj = jstart; jj < jend + 1; jj++) { 1755aa219208SBarry Smith if (st == DMDA_STENCIL_BOX || !ii || !jj) { /* BOX or on the STAR */ 175647c6ae99SBarry Smith cols[cnt++] = slot + ii + gnx * jj; 175747c6ae99SBarry Smith } 175847c6ae99SBarry Smith } 175947c6ae99SBarry Smith } 17609566063dSJacob Faibussowitsch PetscCall(MatSetValuesBlockedLocal(J, 1, &slot, cnt, cols, values, INSERT_VALUES)); 176147c6ae99SBarry Smith } 176247c6ae99SBarry Smith } 17639566063dSJacob Faibussowitsch PetscCall(PetscFree(values)); 1764e7e92044SBarry Smith /* do not copy values to GPU since they are all zero and not yet needed there */ 17659566063dSJacob Faibussowitsch PetscCall(MatBindToCPU(J, PETSC_TRUE)); 17669566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(J, MAT_FINAL_ASSEMBLY)); 17679566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(J, MAT_FINAL_ASSEMBLY)); 17689566063dSJacob Faibussowitsch PetscCall(MatBindToCPU(J, PETSC_FALSE)); 17699566063dSJacob Faibussowitsch PetscCall(MatSetOption(J, MAT_NEW_NONZERO_LOCATION_ERR, PETSC_TRUE)); 177047c6ae99SBarry Smith } 17719566063dSJacob Faibussowitsch PetscCall(PetscFree(cols)); 17723ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 177347c6ae99SBarry Smith } 177447c6ae99SBarry Smith 1775d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateMatrix_DA_3d_MPIBAIJ(DM da, Mat J) 1776d71ae5a4SJacob Faibussowitsch { 177747c6ae99SBarry Smith PetscInt xs, ys, nx, ny, i, j, slot, gxs, gys, gnx, gny; 177847c6ae99SBarry Smith PetscInt m, n, dim, s, *cols, k, nc, col, cnt, p, *dnz, *onz; 177947c6ae99SBarry Smith PetscInt istart, iend, jstart, jend, kstart, kend, zs, nz, gzs, gnz, ii, jj, kk; 178047c6ae99SBarry Smith MPI_Comm comm; 178147c6ae99SBarry Smith PetscScalar *values; 1782bff4a2f0SMatthew G. Knepley DMBoundaryType bx, by, bz; 1783aa219208SBarry Smith DMDAStencilType st; 178445b6f7e9SBarry Smith ISLocalToGlobalMapping ltog; 178547c6ae99SBarry Smith 178647c6ae99SBarry Smith PetscFunctionBegin; 178747c6ae99SBarry Smith /* 178847c6ae99SBarry Smith nc - number of components per grid point 178947c6ae99SBarry Smith col - number of colors needed in one direction for single component problem 179047c6ae99SBarry Smith */ 17919566063dSJacob Faibussowitsch PetscCall(DMDAGetInfo(da, &dim, &m, &n, &p, NULL, NULL, NULL, &nc, &s, &bx, &by, &bz, &st)); 179247c6ae99SBarry Smith col = 2 * s + 1; 179347c6ae99SBarry Smith 17949566063dSJacob Faibussowitsch PetscCall(DMDAGetCorners(da, &xs, &ys, &zs, &nx, &ny, &nz)); 17959566063dSJacob Faibussowitsch PetscCall(DMDAGetGhostCorners(da, &gxs, &gys, &gzs, &gnx, &gny, &gnz)); 17969566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)da, &comm)); 179747c6ae99SBarry Smith 17989566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(col * col * col, &cols)); 179947c6ae99SBarry Smith 18009566063dSJacob Faibussowitsch PetscCall(DMGetLocalToGlobalMapping(da, <og)); 180147c6ae99SBarry Smith 180247c6ae99SBarry Smith /* determine the matrix preallocation information */ 1803d0609cedSBarry Smith MatPreallocateBegin(comm, nx * ny * nz, nx * ny * nz, dnz, onz); 180447c6ae99SBarry Smith for (i = xs; i < xs + nx; i++) { 1805bff4a2f0SMatthew G. Knepley istart = (bx == DM_BOUNDARY_PERIODIC) ? -s : (PetscMax(-s, -i)); 1806bff4a2f0SMatthew G. Knepley iend = (bx == DM_BOUNDARY_PERIODIC) ? s : (PetscMin(s, m - i - 1)); 180747c6ae99SBarry Smith for (j = ys; j < ys + ny; j++) { 1808bff4a2f0SMatthew G. Knepley jstart = (by == DM_BOUNDARY_PERIODIC) ? -s : (PetscMax(-s, -j)); 1809bff4a2f0SMatthew G. Knepley jend = (by == DM_BOUNDARY_PERIODIC) ? s : (PetscMin(s, n - j - 1)); 181047c6ae99SBarry Smith for (k = zs; k < zs + nz; k++) { 1811bff4a2f0SMatthew G. Knepley kstart = (bz == DM_BOUNDARY_PERIODIC) ? -s : (PetscMax(-s, -k)); 1812bff4a2f0SMatthew G. Knepley kend = (bz == DM_BOUNDARY_PERIODIC) ? s : (PetscMin(s, p - k - 1)); 181347c6ae99SBarry Smith 181447c6ae99SBarry Smith slot = i - gxs + gnx * (j - gys) + gnx * gny * (k - gzs); 181547c6ae99SBarry Smith 181647c6ae99SBarry Smith /* Find block columns in block row */ 181747c6ae99SBarry Smith cnt = 0; 181847c6ae99SBarry Smith for (ii = istart; ii < iend + 1; ii++) { 181947c6ae99SBarry Smith for (jj = jstart; jj < jend + 1; jj++) { 182047c6ae99SBarry Smith for (kk = kstart; kk < kend + 1; kk++) { 1821aa219208SBarry Smith if ((st == DMDA_STENCIL_BOX) || ((!ii && !jj) || (!jj && !kk) || (!ii && !kk))) { /* entries on star*/ 182247c6ae99SBarry Smith cols[cnt++] = slot + ii + gnx * jj + gnx * gny * kk; 182347c6ae99SBarry Smith } 182447c6ae99SBarry Smith } 182547c6ae99SBarry Smith } 182647c6ae99SBarry Smith } 18279566063dSJacob Faibussowitsch PetscCall(MatPreallocateSetLocalBlock(ltog, 1, &slot, ltog, cnt, cols, dnz, onz)); 182847c6ae99SBarry Smith } 182947c6ae99SBarry Smith } 183047c6ae99SBarry Smith } 18319566063dSJacob Faibussowitsch PetscCall(MatSeqBAIJSetPreallocation(J, nc, 0, dnz)); 18329566063dSJacob Faibussowitsch PetscCall(MatMPIBAIJSetPreallocation(J, nc, 0, dnz, 0, onz)); 1833d0609cedSBarry Smith MatPreallocateEnd(dnz, onz); 183447c6ae99SBarry Smith 18359566063dSJacob Faibussowitsch PetscCall(MatSetLocalToGlobalMapping(J, ltog, ltog)); 183647c6ae99SBarry Smith 183747c6ae99SBarry Smith /* 183847c6ae99SBarry Smith For each node in the grid: we get the neighbors in the local (on processor ordering 183947c6ae99SBarry Smith that includes the ghost points) then MatSetValuesLocal() maps those indices to the global 184047c6ae99SBarry Smith PETSc ordering. 184147c6ae99SBarry Smith */ 1842fcfd50ebSBarry Smith if (!da->prealloc_only) { 18439566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(col * col * col * nc * nc, &values)); 184447c6ae99SBarry Smith for (i = xs; i < xs + nx; i++) { 1845bff4a2f0SMatthew G. Knepley istart = (bx == DM_BOUNDARY_PERIODIC) ? -s : (PetscMax(-s, -i)); 1846bff4a2f0SMatthew G. Knepley iend = (bx == DM_BOUNDARY_PERIODIC) ? s : (PetscMin(s, m - i - 1)); 184747c6ae99SBarry Smith for (j = ys; j < ys + ny; j++) { 1848bff4a2f0SMatthew G. Knepley jstart = (by == DM_BOUNDARY_PERIODIC) ? -s : (PetscMax(-s, -j)); 1849bff4a2f0SMatthew G. Knepley jend = (by == DM_BOUNDARY_PERIODIC) ? s : (PetscMin(s, n - j - 1)); 185047c6ae99SBarry Smith for (k = zs; k < zs + nz; k++) { 1851bff4a2f0SMatthew G. Knepley kstart = (bz == DM_BOUNDARY_PERIODIC) ? -s : (PetscMax(-s, -k)); 1852bff4a2f0SMatthew G. Knepley kend = (bz == DM_BOUNDARY_PERIODIC) ? s : (PetscMin(s, p - k - 1)); 185347c6ae99SBarry Smith 185447c6ae99SBarry Smith slot = i - gxs + gnx * (j - gys) + gnx * gny * (k - gzs); 185547c6ae99SBarry Smith 185647c6ae99SBarry Smith cnt = 0; 185747c6ae99SBarry Smith for (ii = istart; ii < iend + 1; ii++) { 185847c6ae99SBarry Smith for (jj = jstart; jj < jend + 1; jj++) { 185947c6ae99SBarry Smith for (kk = kstart; kk < kend + 1; kk++) { 1860aa219208SBarry Smith if ((st == DMDA_STENCIL_BOX) || ((!ii && !jj) || (!jj && !kk) || (!ii && !kk))) { /* entries on star*/ 186147c6ae99SBarry Smith cols[cnt++] = slot + ii + gnx * jj + gnx * gny * kk; 186247c6ae99SBarry Smith } 186347c6ae99SBarry Smith } 186447c6ae99SBarry Smith } 186547c6ae99SBarry Smith } 18669566063dSJacob Faibussowitsch PetscCall(MatSetValuesBlockedLocal(J, 1, &slot, cnt, cols, values, INSERT_VALUES)); 186747c6ae99SBarry Smith } 186847c6ae99SBarry Smith } 186947c6ae99SBarry Smith } 18709566063dSJacob Faibussowitsch PetscCall(PetscFree(values)); 1871e7e92044SBarry Smith /* do not copy values to GPU since they are all zero and not yet needed there */ 18729566063dSJacob Faibussowitsch PetscCall(MatBindToCPU(J, PETSC_TRUE)); 18739566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(J, MAT_FINAL_ASSEMBLY)); 18749566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(J, MAT_FINAL_ASSEMBLY)); 18759566063dSJacob Faibussowitsch PetscCall(MatBindToCPU(J, PETSC_FALSE)); 18769566063dSJacob Faibussowitsch PetscCall(MatSetOption(J, MAT_NEW_NONZERO_LOCATION_ERR, PETSC_TRUE)); 187747c6ae99SBarry Smith } 18789566063dSJacob Faibussowitsch PetscCall(PetscFree(cols)); 18793ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 188047c6ae99SBarry Smith } 188147c6ae99SBarry Smith 188247c6ae99SBarry Smith /* 188347c6ae99SBarry Smith This helper is for of SBAIJ preallocation, to discard the lower-triangular values which are difficult to 188447c6ae99SBarry Smith identify in the local ordering with periodic domain. 188547c6ae99SBarry Smith */ 1886d71ae5a4SJacob Faibussowitsch static PetscErrorCode L2GFilterUpperTriangular(ISLocalToGlobalMapping ltog, PetscInt *row, PetscInt *cnt, PetscInt col[]) 1887d71ae5a4SJacob Faibussowitsch { 188847c6ae99SBarry Smith PetscInt i, n; 188947c6ae99SBarry Smith 189047c6ae99SBarry Smith PetscFunctionBegin; 18919566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingApplyBlock(ltog, 1, row, row)); 18929566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingApplyBlock(ltog, *cnt, col, col)); 189347c6ae99SBarry Smith for (i = 0, n = 0; i < *cnt; i++) { 189447c6ae99SBarry Smith if (col[i] >= *row) col[n++] = col[i]; 189547c6ae99SBarry Smith } 189647c6ae99SBarry Smith *cnt = n; 18973ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 189847c6ae99SBarry Smith } 189947c6ae99SBarry Smith 1900d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateMatrix_DA_2d_MPISBAIJ(DM da, Mat J) 1901d71ae5a4SJacob Faibussowitsch { 190247c6ae99SBarry Smith PetscInt xs, ys, nx, ny, i, j, slot, gxs, gys, gnx, gny; 190347c6ae99SBarry Smith PetscInt m, n, dim, s, *cols, nc, col, cnt, *dnz, *onz; 190447c6ae99SBarry Smith PetscInt istart, iend, jstart, jend, ii, jj; 190547c6ae99SBarry Smith MPI_Comm comm; 190647c6ae99SBarry Smith PetscScalar *values; 1907bff4a2f0SMatthew G. Knepley DMBoundaryType bx, by; 1908aa219208SBarry Smith DMDAStencilType st; 190945b6f7e9SBarry Smith ISLocalToGlobalMapping ltog; 191047c6ae99SBarry Smith 191147c6ae99SBarry Smith PetscFunctionBegin; 191247c6ae99SBarry Smith /* 191347c6ae99SBarry Smith nc - number of components per grid point 191447c6ae99SBarry Smith col - number of colors needed in one direction for single component problem 191547c6ae99SBarry Smith */ 19169566063dSJacob Faibussowitsch PetscCall(DMDAGetInfo(da, &dim, &m, &n, NULL, NULL, NULL, NULL, &nc, &s, &bx, &by, NULL, &st)); 191747c6ae99SBarry Smith col = 2 * s + 1; 191847c6ae99SBarry Smith 19199566063dSJacob Faibussowitsch PetscCall(DMDAGetCorners(da, &xs, &ys, NULL, &nx, &ny, NULL)); 19209566063dSJacob Faibussowitsch PetscCall(DMDAGetGhostCorners(da, &gxs, &gys, NULL, &gnx, &gny, NULL)); 19219566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)da, &comm)); 192247c6ae99SBarry Smith 19239566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(col * col * nc * nc, &cols)); 192447c6ae99SBarry Smith 19259566063dSJacob Faibussowitsch PetscCall(DMGetLocalToGlobalMapping(da, <og)); 192647c6ae99SBarry Smith 192747c6ae99SBarry Smith /* determine the matrix preallocation information */ 1928d0609cedSBarry Smith MatPreallocateBegin(comm, nx * ny, nx * ny, dnz, onz); 192947c6ae99SBarry Smith for (i = xs; i < xs + nx; i++) { 1930bff4a2f0SMatthew G. Knepley istart = (bx == DM_BOUNDARY_PERIODIC) ? -s : (PetscMax(-s, -i)); 1931bff4a2f0SMatthew G. Knepley iend = (bx == DM_BOUNDARY_PERIODIC) ? s : (PetscMin(s, m - i - 1)); 193247c6ae99SBarry Smith for (j = ys; j < ys + ny; j++) { 1933bff4a2f0SMatthew G. Knepley jstart = (by == DM_BOUNDARY_PERIODIC) ? -s : (PetscMax(-s, -j)); 1934bff4a2f0SMatthew G. Knepley jend = (by == DM_BOUNDARY_PERIODIC) ? s : (PetscMin(s, n - j - 1)); 193547c6ae99SBarry Smith slot = i - gxs + gnx * (j - gys); 193647c6ae99SBarry Smith 193747c6ae99SBarry Smith /* Find block columns in block row */ 193847c6ae99SBarry Smith cnt = 0; 193947c6ae99SBarry Smith for (ii = istart; ii < iend + 1; ii++) { 194047c6ae99SBarry Smith for (jj = jstart; jj < jend + 1; jj++) { 1941ad540459SPierre Jolivet if (st == DMDA_STENCIL_BOX || !ii || !jj) cols[cnt++] = slot + ii + gnx * jj; 194247c6ae99SBarry Smith } 194347c6ae99SBarry Smith } 19449566063dSJacob Faibussowitsch PetscCall(L2GFilterUpperTriangular(ltog, &slot, &cnt, cols)); 19459566063dSJacob Faibussowitsch PetscCall(MatPreallocateSymmetricSetBlock(slot, cnt, cols, dnz, onz)); 194647c6ae99SBarry Smith } 194747c6ae99SBarry Smith } 19489566063dSJacob Faibussowitsch PetscCall(MatSeqSBAIJSetPreallocation(J, nc, 0, dnz)); 19499566063dSJacob Faibussowitsch PetscCall(MatMPISBAIJSetPreallocation(J, nc, 0, dnz, 0, onz)); 1950d0609cedSBarry Smith MatPreallocateEnd(dnz, onz); 195147c6ae99SBarry Smith 19529566063dSJacob Faibussowitsch PetscCall(MatSetLocalToGlobalMapping(J, ltog, ltog)); 195347c6ae99SBarry Smith 195447c6ae99SBarry Smith /* 195547c6ae99SBarry Smith For each node in the grid: we get the neighbors in the local (on processor ordering 195647c6ae99SBarry Smith that includes the ghost points) then MatSetValuesLocal() maps those indices to the global 195747c6ae99SBarry Smith PETSc ordering. 195847c6ae99SBarry Smith */ 1959fcfd50ebSBarry Smith if (!da->prealloc_only) { 19609566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(col * col * nc * nc, &values)); 196147c6ae99SBarry Smith for (i = xs; i < xs + nx; i++) { 1962bff4a2f0SMatthew G. Knepley istart = (bx == DM_BOUNDARY_PERIODIC) ? -s : (PetscMax(-s, -i)); 1963bff4a2f0SMatthew G. Knepley iend = (bx == DM_BOUNDARY_PERIODIC) ? s : (PetscMin(s, m - i - 1)); 196447c6ae99SBarry Smith for (j = ys; j < ys + ny; j++) { 1965bff4a2f0SMatthew G. Knepley jstart = (by == DM_BOUNDARY_PERIODIC) ? -s : (PetscMax(-s, -j)); 1966bff4a2f0SMatthew G. Knepley jend = (by == DM_BOUNDARY_PERIODIC) ? s : (PetscMin(s, n - j - 1)); 196747c6ae99SBarry Smith slot = i - gxs + gnx * (j - gys); 196847c6ae99SBarry Smith 196947c6ae99SBarry Smith /* Find block columns in block row */ 197047c6ae99SBarry Smith cnt = 0; 197147c6ae99SBarry Smith for (ii = istart; ii < iend + 1; ii++) { 197247c6ae99SBarry Smith for (jj = jstart; jj < jend + 1; jj++) { 1973ad540459SPierre Jolivet if (st == DMDA_STENCIL_BOX || !ii || !jj) cols[cnt++] = slot + ii + gnx * jj; 197447c6ae99SBarry Smith } 197547c6ae99SBarry Smith } 19769566063dSJacob Faibussowitsch PetscCall(L2GFilterUpperTriangular(ltog, &slot, &cnt, cols)); 19779566063dSJacob Faibussowitsch PetscCall(MatSetValuesBlocked(J, 1, &slot, cnt, cols, values, INSERT_VALUES)); 197847c6ae99SBarry Smith } 197947c6ae99SBarry Smith } 19809566063dSJacob Faibussowitsch PetscCall(PetscFree(values)); 1981e7e92044SBarry Smith /* do not copy values to GPU since they are all zero and not yet needed there */ 19829566063dSJacob Faibussowitsch PetscCall(MatBindToCPU(J, PETSC_TRUE)); 19839566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(J, MAT_FINAL_ASSEMBLY)); 19849566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(J, MAT_FINAL_ASSEMBLY)); 19859566063dSJacob Faibussowitsch PetscCall(MatBindToCPU(J, PETSC_FALSE)); 19869566063dSJacob Faibussowitsch PetscCall(MatSetOption(J, MAT_NEW_NONZERO_LOCATION_ERR, PETSC_TRUE)); 198747c6ae99SBarry Smith } 19889566063dSJacob Faibussowitsch PetscCall(PetscFree(cols)); 19893ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 199047c6ae99SBarry Smith } 199147c6ae99SBarry Smith 1992d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateMatrix_DA_3d_MPISBAIJ(DM da, Mat J) 1993d71ae5a4SJacob Faibussowitsch { 199447c6ae99SBarry Smith PetscInt xs, ys, nx, ny, i, j, slot, gxs, gys, gnx, gny; 199547c6ae99SBarry Smith PetscInt m, n, dim, s, *cols, k, nc, col, cnt, p, *dnz, *onz; 199647c6ae99SBarry Smith PetscInt istart, iend, jstart, jend, kstart, kend, zs, nz, gzs, gnz, ii, jj, kk; 199747c6ae99SBarry Smith MPI_Comm comm; 199847c6ae99SBarry Smith PetscScalar *values; 1999bff4a2f0SMatthew G. Knepley DMBoundaryType bx, by, bz; 2000aa219208SBarry Smith DMDAStencilType st; 200145b6f7e9SBarry Smith ISLocalToGlobalMapping ltog; 200247c6ae99SBarry Smith 200347c6ae99SBarry Smith PetscFunctionBegin; 200447c6ae99SBarry Smith /* 200547c6ae99SBarry Smith nc - number of components per grid point 200647c6ae99SBarry Smith col - number of colors needed in one direction for single component problem 200747c6ae99SBarry Smith */ 20089566063dSJacob Faibussowitsch PetscCall(DMDAGetInfo(da, &dim, &m, &n, &p, NULL, NULL, NULL, &nc, &s, &bx, &by, &bz, &st)); 200947c6ae99SBarry Smith col = 2 * s + 1; 201047c6ae99SBarry Smith 20119566063dSJacob Faibussowitsch PetscCall(DMDAGetCorners(da, &xs, &ys, &zs, &nx, &ny, &nz)); 20129566063dSJacob Faibussowitsch PetscCall(DMDAGetGhostCorners(da, &gxs, &gys, &gzs, &gnx, &gny, &gnz)); 20139566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)da, &comm)); 201447c6ae99SBarry Smith 201547c6ae99SBarry Smith /* create the matrix */ 20169566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(col * col * col, &cols)); 201747c6ae99SBarry Smith 20189566063dSJacob Faibussowitsch PetscCall(DMGetLocalToGlobalMapping(da, <og)); 201947c6ae99SBarry Smith 202047c6ae99SBarry Smith /* determine the matrix preallocation information */ 2021d0609cedSBarry Smith MatPreallocateBegin(comm, nx * ny * nz, nx * ny * nz, dnz, onz); 202247c6ae99SBarry Smith for (i = xs; i < xs + nx; i++) { 2023bff4a2f0SMatthew G. Knepley istart = (bx == DM_BOUNDARY_PERIODIC) ? -s : (PetscMax(-s, -i)); 2024bff4a2f0SMatthew G. Knepley iend = (bx == DM_BOUNDARY_PERIODIC) ? s : (PetscMin(s, m - i - 1)); 202547c6ae99SBarry Smith for (j = ys; j < ys + ny; j++) { 2026bff4a2f0SMatthew G. Knepley jstart = (by == DM_BOUNDARY_PERIODIC) ? -s : (PetscMax(-s, -j)); 2027bff4a2f0SMatthew G. Knepley jend = (by == DM_BOUNDARY_PERIODIC) ? s : (PetscMin(s, n - j - 1)); 202847c6ae99SBarry Smith for (k = zs; k < zs + nz; k++) { 2029bff4a2f0SMatthew G. Knepley kstart = (bz == DM_BOUNDARY_PERIODIC) ? -s : (PetscMax(-s, -k)); 2030bff4a2f0SMatthew G. Knepley kend = (bz == DM_BOUNDARY_PERIODIC) ? s : (PetscMin(s, p - k - 1)); 203147c6ae99SBarry Smith 203247c6ae99SBarry Smith slot = i - gxs + gnx * (j - gys) + gnx * gny * (k - gzs); 203347c6ae99SBarry Smith 203447c6ae99SBarry Smith /* Find block columns in block row */ 203547c6ae99SBarry Smith cnt = 0; 203647c6ae99SBarry Smith for (ii = istart; ii < iend + 1; ii++) { 203747c6ae99SBarry Smith for (jj = jstart; jj < jend + 1; jj++) { 203847c6ae99SBarry Smith for (kk = kstart; kk < kend + 1; kk++) { 2039ad540459SPierre Jolivet if ((st == DMDA_STENCIL_BOX) || (!ii && !jj) || (!jj && !kk) || (!ii && !kk)) cols[cnt++] = slot + ii + gnx * jj + gnx * gny * kk; 204047c6ae99SBarry Smith } 204147c6ae99SBarry Smith } 204247c6ae99SBarry Smith } 20439566063dSJacob Faibussowitsch PetscCall(L2GFilterUpperTriangular(ltog, &slot, &cnt, cols)); 20449566063dSJacob Faibussowitsch PetscCall(MatPreallocateSymmetricSetBlock(slot, cnt, cols, dnz, onz)); 204547c6ae99SBarry Smith } 204647c6ae99SBarry Smith } 204747c6ae99SBarry Smith } 20489566063dSJacob Faibussowitsch PetscCall(MatSeqSBAIJSetPreallocation(J, nc, 0, dnz)); 20499566063dSJacob Faibussowitsch PetscCall(MatMPISBAIJSetPreallocation(J, nc, 0, dnz, 0, onz)); 2050d0609cedSBarry Smith MatPreallocateEnd(dnz, onz); 205147c6ae99SBarry Smith 20529566063dSJacob Faibussowitsch PetscCall(MatSetLocalToGlobalMapping(J, ltog, ltog)); 205347c6ae99SBarry Smith 205447c6ae99SBarry Smith /* 205547c6ae99SBarry Smith For each node in the grid: we get the neighbors in the local (on processor ordering 205647c6ae99SBarry Smith that includes the ghost points) then MatSetValuesLocal() maps those indices to the global 205747c6ae99SBarry Smith PETSc ordering. 205847c6ae99SBarry Smith */ 2059fcfd50ebSBarry Smith if (!da->prealloc_only) { 20609566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(col * col * col * nc * nc, &values)); 206147c6ae99SBarry Smith for (i = xs; i < xs + nx; i++) { 2062bff4a2f0SMatthew G. Knepley istart = (bx == DM_BOUNDARY_PERIODIC) ? -s : (PetscMax(-s, -i)); 2063bff4a2f0SMatthew G. Knepley iend = (bx == DM_BOUNDARY_PERIODIC) ? s : (PetscMin(s, m - i - 1)); 206447c6ae99SBarry Smith for (j = ys; j < ys + ny; j++) { 2065bff4a2f0SMatthew G. Knepley jstart = (by == DM_BOUNDARY_PERIODIC) ? -s : (PetscMax(-s, -j)); 2066bff4a2f0SMatthew G. Knepley jend = (by == DM_BOUNDARY_PERIODIC) ? s : (PetscMin(s, n - j - 1)); 206747c6ae99SBarry Smith for (k = zs; k < zs + nz; k++) { 2068bff4a2f0SMatthew G. Knepley kstart = (bz == DM_BOUNDARY_PERIODIC) ? -s : (PetscMax(-s, -k)); 2069bff4a2f0SMatthew G. Knepley kend = (bz == DM_BOUNDARY_PERIODIC) ? s : (PetscMin(s, p - k - 1)); 207047c6ae99SBarry Smith 207147c6ae99SBarry Smith slot = i - gxs + gnx * (j - gys) + gnx * gny * (k - gzs); 207247c6ae99SBarry Smith 207347c6ae99SBarry Smith cnt = 0; 207447c6ae99SBarry Smith for (ii = istart; ii < iend + 1; ii++) { 207547c6ae99SBarry Smith for (jj = jstart; jj < jend + 1; jj++) { 207647c6ae99SBarry Smith for (kk = kstart; kk < kend + 1; kk++) { 2077ad540459SPierre Jolivet if ((st == DMDA_STENCIL_BOX) || (!ii && !jj) || (!jj && !kk) || (!ii && !kk)) cols[cnt++] = slot + ii + gnx * jj + gnx * gny * kk; 207847c6ae99SBarry Smith } 207947c6ae99SBarry Smith } 208047c6ae99SBarry Smith } 20819566063dSJacob Faibussowitsch PetscCall(L2GFilterUpperTriangular(ltog, &slot, &cnt, cols)); 20829566063dSJacob Faibussowitsch PetscCall(MatSetValuesBlocked(J, 1, &slot, cnt, cols, values, INSERT_VALUES)); 208347c6ae99SBarry Smith } 208447c6ae99SBarry Smith } 208547c6ae99SBarry Smith } 20869566063dSJacob Faibussowitsch PetscCall(PetscFree(values)); 2087e7e92044SBarry Smith /* do not copy values to GPU since they are all zero and not yet needed there */ 20889566063dSJacob Faibussowitsch PetscCall(MatBindToCPU(J, PETSC_TRUE)); 20899566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(J, MAT_FINAL_ASSEMBLY)); 20909566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(J, MAT_FINAL_ASSEMBLY)); 20919566063dSJacob Faibussowitsch PetscCall(MatBindToCPU(J, PETSC_FALSE)); 20929566063dSJacob Faibussowitsch PetscCall(MatSetOption(J, MAT_NEW_NONZERO_LOCATION_ERR, PETSC_TRUE)); 209347c6ae99SBarry Smith } 20949566063dSJacob Faibussowitsch PetscCall(PetscFree(cols)); 20953ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 209647c6ae99SBarry Smith } 209747c6ae99SBarry Smith 2098d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateMatrix_DA_3d_MPIAIJ_Fill(DM da, Mat J) 2099d71ae5a4SJacob Faibussowitsch { 210047c6ae99SBarry Smith PetscInt xs, ys, nx, ny, i, j, slot, gxs, gys, gnx, gny; 2101c0ab637bSBarry Smith PetscInt m, n, dim, s, *cols, k, nc, row, col, cnt, maxcnt = 0, l, p, *dnz, *onz; 2102c1154cd5SBarry Smith PetscInt istart, iend, jstart, jend, kstart, kend, zs, nz, gzs, gnz, ii, jj, kk, M, N, P; 210347c6ae99SBarry Smith DM_DA *dd = (DM_DA *)da->data; 210447c6ae99SBarry Smith PetscInt ifill_col, *dfill = dd->dfill, *ofill = dd->ofill; 210547c6ae99SBarry Smith MPI_Comm comm; 210647c6ae99SBarry Smith PetscScalar *values; 2107bff4a2f0SMatthew G. Knepley DMBoundaryType bx, by, bz; 210845b6f7e9SBarry Smith ISLocalToGlobalMapping ltog; 2109aa219208SBarry Smith DMDAStencilType st; 2110c1154cd5SBarry Smith PetscBool removedups = PETSC_FALSE; 211147c6ae99SBarry Smith 211247c6ae99SBarry Smith PetscFunctionBegin; 211347c6ae99SBarry Smith /* 211447c6ae99SBarry Smith nc - number of components per grid point 211547c6ae99SBarry Smith col - number of colors needed in one direction for single component problem 211647c6ae99SBarry Smith */ 21179566063dSJacob Faibussowitsch PetscCall(DMDAGetInfo(da, &dim, &m, &n, &p, &M, &N, &P, &nc, &s, &bx, &by, &bz, &st)); 211847c6ae99SBarry Smith col = 2 * s + 1; 211947c6ae99SBarry Smith 2120c1154cd5SBarry Smith /* 2121c1154cd5SBarry Smith With one processor in periodic domains in a skinny dimension the code will label nonzero columns multiple times 2122c1154cd5SBarry Smith because of "wrapping" around the end of the domain hitting an entry already counted in the other direction. 2123c1154cd5SBarry Smith */ 2124c1154cd5SBarry Smith if (M == 1 && 2 * s >= m) removedups = PETSC_TRUE; 2125c1154cd5SBarry Smith if (N == 1 && 2 * s >= n) removedups = PETSC_TRUE; 2126c1154cd5SBarry Smith if (P == 1 && 2 * s >= p) removedups = PETSC_TRUE; 2127c1154cd5SBarry Smith 21289566063dSJacob Faibussowitsch PetscCall(DMDAGetCorners(da, &xs, &ys, &zs, &nx, &ny, &nz)); 21299566063dSJacob Faibussowitsch PetscCall(DMDAGetGhostCorners(da, &gxs, &gys, &gzs, &gnx, &gny, &gnz)); 21309566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)da, &comm)); 213147c6ae99SBarry Smith 21329566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(col * col * col * nc, &cols)); 21339566063dSJacob Faibussowitsch PetscCall(DMGetLocalToGlobalMapping(da, <og)); 213447c6ae99SBarry Smith 213547c6ae99SBarry Smith /* determine the matrix preallocation information */ 2136d0609cedSBarry Smith MatPreallocateBegin(comm, nc * nx * ny * nz, nc * nx * ny * nz, dnz, onz); 213747c6ae99SBarry Smith 21389566063dSJacob Faibussowitsch PetscCall(MatSetBlockSize(J, nc)); 213947c6ae99SBarry Smith for (i = xs; i < xs + nx; i++) { 2140bff4a2f0SMatthew G. Knepley istart = (bx == DM_BOUNDARY_PERIODIC) ? -s : (PetscMax(-s, -i)); 2141bff4a2f0SMatthew G. Knepley iend = (bx == DM_BOUNDARY_PERIODIC) ? s : (PetscMin(s, m - i - 1)); 214247c6ae99SBarry Smith for (j = ys; j < ys + ny; j++) { 2143bff4a2f0SMatthew G. Knepley jstart = (by == DM_BOUNDARY_PERIODIC) ? -s : (PetscMax(-s, -j)); 2144bff4a2f0SMatthew G. Knepley jend = (by == DM_BOUNDARY_PERIODIC) ? s : (PetscMin(s, n - j - 1)); 214547c6ae99SBarry Smith for (k = zs; k < zs + nz; k++) { 2146bff4a2f0SMatthew G. Knepley kstart = (bz == DM_BOUNDARY_PERIODIC) ? -s : (PetscMax(-s, -k)); 2147bff4a2f0SMatthew G. Knepley kend = (bz == DM_BOUNDARY_PERIODIC) ? s : (PetscMin(s, p - k - 1)); 214847c6ae99SBarry Smith 214947c6ae99SBarry Smith slot = i - gxs + gnx * (j - gys) + gnx * gny * (k - gzs); 215047c6ae99SBarry Smith 215147c6ae99SBarry Smith for (l = 0; l < nc; l++) { 215247c6ae99SBarry Smith cnt = 0; 215347c6ae99SBarry Smith for (ii = istart; ii < iend + 1; ii++) { 215447c6ae99SBarry Smith for (jj = jstart; jj < jend + 1; jj++) { 215547c6ae99SBarry Smith for (kk = kstart; kk < kend + 1; kk++) { 215647c6ae99SBarry Smith if (ii || jj || kk) { 2157aa219208SBarry Smith if ((st == DMDA_STENCIL_BOX) || ((!ii && !jj) || (!jj && !kk) || (!ii && !kk))) { /* entries on star*/ 21588865f1eaSKarl 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); 215947c6ae99SBarry Smith } 216047c6ae99SBarry Smith } else { 216147c6ae99SBarry Smith if (dfill) { 21628865f1eaSKarl 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); 216347c6ae99SBarry Smith } else { 21648865f1eaSKarl Rupp for (ifill_col = 0; ifill_col < nc; ifill_col++) cols[cnt++] = ifill_col + nc * (slot + ii + gnx * jj + gnx * gny * kk); 216547c6ae99SBarry Smith } 216647c6ae99SBarry Smith } 216747c6ae99SBarry Smith } 216847c6ae99SBarry Smith } 216947c6ae99SBarry Smith } 217047c6ae99SBarry Smith row = l + nc * (slot); 2171c0ab637bSBarry Smith maxcnt = PetscMax(maxcnt, cnt); 21721baa6e33SBarry Smith if (removedups) PetscCall(MatPreallocateSetLocalRemoveDups(ltog, 1, &row, ltog, cnt, cols, dnz, onz)); 21731baa6e33SBarry Smith else PetscCall(MatPreallocateSetLocal(ltog, 1, &row, ltog, cnt, cols, dnz, onz)); 217447c6ae99SBarry Smith } 217547c6ae99SBarry Smith } 217647c6ae99SBarry Smith } 2177c1154cd5SBarry Smith } 21789566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocation(J, 0, dnz)); 21799566063dSJacob Faibussowitsch PetscCall(MatMPIAIJSetPreallocation(J, 0, dnz, 0, onz)); 2180d0609cedSBarry Smith MatPreallocateEnd(dnz, onz); 21819566063dSJacob Faibussowitsch PetscCall(MatSetLocalToGlobalMapping(J, ltog, ltog)); 218247c6ae99SBarry Smith 218347c6ae99SBarry Smith /* 218447c6ae99SBarry Smith For each node in the grid: we get the neighbors in the local (on processor ordering 218547c6ae99SBarry Smith that includes the ghost points) then MatSetValuesLocal() maps those indices to the global 218647c6ae99SBarry Smith PETSc ordering. 218747c6ae99SBarry Smith */ 2188fcfd50ebSBarry Smith if (!da->prealloc_only) { 21899566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(maxcnt, &values)); 219047c6ae99SBarry Smith for (i = xs; i < xs + nx; i++) { 2191bff4a2f0SMatthew G. Knepley istart = (bx == DM_BOUNDARY_PERIODIC) ? -s : (PetscMax(-s, -i)); 2192bff4a2f0SMatthew G. Knepley iend = (bx == DM_BOUNDARY_PERIODIC) ? s : (PetscMin(s, m - i - 1)); 219347c6ae99SBarry Smith for (j = ys; j < ys + ny; j++) { 2194bff4a2f0SMatthew G. Knepley jstart = (by == DM_BOUNDARY_PERIODIC) ? -s : (PetscMax(-s, -j)); 2195bff4a2f0SMatthew G. Knepley jend = (by == DM_BOUNDARY_PERIODIC) ? s : (PetscMin(s, n - j - 1)); 219647c6ae99SBarry Smith for (k = zs; k < zs + nz; k++) { 2197bff4a2f0SMatthew G. Knepley kstart = (bz == DM_BOUNDARY_PERIODIC) ? -s : (PetscMax(-s, -k)); 2198bff4a2f0SMatthew G. Knepley kend = (bz == DM_BOUNDARY_PERIODIC) ? s : (PetscMin(s, p - k - 1)); 219947c6ae99SBarry Smith 220047c6ae99SBarry Smith slot = i - gxs + gnx * (j - gys) + gnx * gny * (k - gzs); 220147c6ae99SBarry Smith 220247c6ae99SBarry Smith for (l = 0; l < nc; l++) { 220347c6ae99SBarry Smith cnt = 0; 220447c6ae99SBarry Smith for (ii = istart; ii < iend + 1; ii++) { 220547c6ae99SBarry Smith for (jj = jstart; jj < jend + 1; jj++) { 220647c6ae99SBarry Smith for (kk = kstart; kk < kend + 1; kk++) { 220747c6ae99SBarry Smith if (ii || jj || kk) { 2208aa219208SBarry Smith if ((st == DMDA_STENCIL_BOX) || ((!ii && !jj) || (!jj && !kk) || (!ii && !kk))) { /* entries on star*/ 22098865f1eaSKarl 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); 221047c6ae99SBarry Smith } 221147c6ae99SBarry Smith } else { 221247c6ae99SBarry Smith if (dfill) { 22138865f1eaSKarl 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); 221447c6ae99SBarry Smith } else { 22158865f1eaSKarl Rupp for (ifill_col = 0; ifill_col < nc; ifill_col++) cols[cnt++] = ifill_col + nc * (slot + ii + gnx * jj + gnx * gny * kk); 221647c6ae99SBarry Smith } 221747c6ae99SBarry Smith } 221847c6ae99SBarry Smith } 221947c6ae99SBarry Smith } 222047c6ae99SBarry Smith } 222147c6ae99SBarry Smith row = l + nc * (slot); 22229566063dSJacob Faibussowitsch PetscCall(MatSetValuesLocal(J, 1, &row, cnt, cols, values, INSERT_VALUES)); 222347c6ae99SBarry Smith } 222447c6ae99SBarry Smith } 222547c6ae99SBarry Smith } 222647c6ae99SBarry Smith } 22279566063dSJacob Faibussowitsch PetscCall(PetscFree(values)); 2228e7e92044SBarry Smith /* do not copy values to GPU since they are all zero and not yet needed there */ 22299566063dSJacob Faibussowitsch PetscCall(MatBindToCPU(J, PETSC_TRUE)); 22309566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(J, MAT_FINAL_ASSEMBLY)); 22319566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(J, MAT_FINAL_ASSEMBLY)); 22329566063dSJacob Faibussowitsch PetscCall(MatBindToCPU(J, PETSC_FALSE)); 22339566063dSJacob Faibussowitsch PetscCall(MatSetOption(J, MAT_NEW_NONZERO_LOCATION_ERR, PETSC_TRUE)); 223447c6ae99SBarry Smith } 22359566063dSJacob Faibussowitsch PetscCall(PetscFree(cols)); 22363ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 223747c6ae99SBarry Smith } 2238