Date: 2013-07-02T14:45:07+00:00

Actual source code: fdda.c
petsc-3.4.2 2013-07-02

      2: #include <petsc-private/dmdaimpl.h> /*I      "petscdmda.h"     I*/
      3: #include <petscmat.h>
      4: #include <petsc-private/matimpl.h>

      6: extern PetscErrorCode DMCreateColoring_DA_1d_MPIAIJ(DM,ISColoringType,ISColoring*);
      7: extern PetscErrorCode DMCreateColoring_DA_2d_MPIAIJ(DM,ISColoringType,ISColoring*);
      8: extern PetscErrorCode DMCreateColoring_DA_2d_5pt_MPIAIJ(DM,ISColoringType,ISColoring*);
      9: extern PetscErrorCode DMCreateColoring_DA_3d_MPIAIJ(DM,ISColoringType,ISColoring*);

     11: /*
     12:    For ghost i that may be negative or greater than the upper bound this
     13:   maps it into the 0:m-1 range using periodicity
     14: */
     15: #define SetInRange(i,m) ((i < 0) ? m+i : ((i >= m) ? i-m : i))

     19: static PetscErrorCode DMDASetBlockFills_Private(const PetscInt *dfill,PetscInt w,PetscInt **rfill)
     20: {
     22:   PetscInt       i,j,nz,*fill;

     25:   if (!dfill) return(0);

     27:   /* count number nonzeros */
     28:   nz = 0;
     29:   for (i=0; i<w; i++) {
     30:     for (j=0; j<w; j++) {
     31:       if (dfill[w*i+j]) nz++;
     32:     }
     33:   }
     34:   PetscMalloc((nz + w + 1)*sizeof(PetscInt),&fill);
     35:   /* construct modified CSR storage of nonzero structure */
     36:   /*  fill[0 -- w] marks starts of each row of column indices (and end of last row)
     37:    so fill[1] - fill[0] gives number of nonzeros in first row etc */
     38:   nz = w + 1;
     39:   for (i=0; i<w; i++) {
     40:     fill[i] = nz;
     41:     for (j=0; j<w; j++) {
     42:       if (dfill[w*i+j]) {
     43:         fill[nz] = j;
     44:         nz++;
     45:       }
     46:     }
     47:   }
     48:   fill[w] = nz;

     50:   *rfill = fill;
     51:   return(0);
     52: }

     56: /*@
     57:     DMDASetBlockFills - Sets the fill pattern in each block for a multi-component problem
     58:     of the matrix returned by DMCreateMatrix().

     60:     Logically Collective on DMDA

     62:     Input Parameter:
     63: +   da - the distributed array
     64: .   dfill - the fill pattern in the diagonal block (may be NULL, means use dense block)
     65: -   ofill - the fill pattern in the off-diagonal blocks

     68:     Level: developer

     70:     Notes: This only makes sense when you are doing multicomponent problems but using the
     71:        MPIAIJ matrix format

     73:            The format for dfill and ofill is a 2 dimensional dof by dof matrix with 1 entries
     74:        representing coupling and 0 entries for missing coupling. For example
     75: $             dfill[9] = {1, 0, 0,
     76: $                         1, 1, 0,
     77: $                         0, 1, 1}
     78:        means that row 0 is coupled with only itself in the diagonal block, row 1 is coupled with
     79:        itself and row 0 (in the diagonal block) and row 2 is coupled with itself and row 1 (in the
     80:        diagonal block).

     82:      DMDASetGetMatrix() allows you to provide general code for those more complicated nonzero patterns then
     83:      can be represented in the dfill, ofill format

     85:    Contributed by Glenn Hammond

     87: .seealso DMCreateMatrix(), DMDASetGetMatrix(), DMSetMatrixPreallocateOnly()

     89: @*/
     90: PetscErrorCode  DMDASetBlockFills(DM da,const PetscInt *dfill,const PetscInt *ofill)
     91: {
     92:   DM_DA          *dd = (DM_DA*)da->data;
     94:   PetscInt       i,k,cnt = 1;

     97:   DMDASetBlockFills_Private(dfill,dd->w,&dd->dfill);
     98:   DMDASetBlockFills_Private(ofill,dd->w,&dd->ofill);

    100:   /* ofillcount tracks the columns of ofill that have any nonzero in thems; the value in each location is the number of
    101:    columns to the left with any nonzeros in them plus 1 */
    102:   PetscMalloc(dd->w*sizeof(PetscBool),&dd->ofillcols);
    103:   PetscMemzero(dd->ofillcols,dd->w*sizeof(PetscBool));
    104:   for (i=0; i<dd->w; i++) {
    105:     for (k=dd->ofill[i]; k<dd->ofill[i+1]; k++) dd->ofillcols[dd->ofill[k]] = 1;
    106:   }
    107:   for (i=0; i<dd->w; i++) {
    108:     if (dd->ofillcols[i]) {
    109:       dd->ofillcols[i] = cnt++;
    110:     }
    111:   }
    112:   return(0);
    113: }

    118: PetscErrorCode  DMCreateColoring_DA(DM da,ISColoringType ctype,MatType mtype,ISColoring *coloring)
    119: {
    120:   PetscErrorCode   ierr;
    121:   PetscInt         dim,m,n,p,nc;
    122:   DMDABoundaryType bx,by,bz;
    123:   MPI_Comm         comm;
    124:   PetscMPIInt      size;
    125:   PetscBool        isBAIJ;
    126:   DM_DA            *dd = (DM_DA*)da->data;

    129:   /*
    130:                                   m
    131:           ------------------------------------------------------
    132:          |                                                     |
    133:          |                                                     |
    134:          |               ----------------------                |
    135:          |               |                    |                |
    136:       n  |           yn  |                    |                |
    137:          |               |                    |                |
    138:          |               .---------------------                |
    139:          |             (xs,ys)     xn                          |
    140:          |            .                                        |
    141:          |         (gxs,gys)                                   |
    142:          |                                                     |
    143:           -----------------------------------------------------
    144:   */

    146:   /*
    147:          nc - number of components per grid point
    148:          col - number of colors needed in one direction for single component problem

    150:   */
    151:   DMDAGetInfo(da,&dim,0,0,0,&m,&n,&p,&nc,0,&bx,&by,&bz,0);

    153:   PetscObjectGetComm((PetscObject)da,&comm);
    154:   MPI_Comm_size(comm,&size);
    155:   if (ctype == IS_COLORING_GHOSTED) {
    156:     if (size == 1) {
    157:       ctype = IS_COLORING_GLOBAL;
    158:     } else if (dim > 1) {
    159:       if ((m==1 && bx == DMDA_BOUNDARY_PERIODIC) || (n==1 && by == DMDA_BOUNDARY_PERIODIC) || (p==1 && bz == DMDA_BOUNDARY_PERIODIC)) {
    160:         SETERRQ(PetscObjectComm((PetscObject)da),PETSC_ERR_SUP,"IS_COLORING_GHOSTED cannot be used for periodic boundary condition having both ends of the domain  on the same process");
    161:       }
    162:     }
    163:   }

    165:   /* Tell the DMDA it has 1 degree of freedom per grid point so that the coloring for BAIJ
    166:      matrices is for the blocks, not the individual matrix elements  */
    167:   PetscStrcmp(mtype,MATBAIJ,&isBAIJ);
    168:   if (!isBAIJ) {PetscStrcmp(mtype,MATMPIBAIJ,&isBAIJ);}
    169:   if (!isBAIJ) {PetscStrcmp(mtype,MATSEQBAIJ,&isBAIJ);}
    170:   if (isBAIJ) {
    171:     dd->w  = 1;
    172:     dd->xs = dd->xs/nc;
    173:     dd->xe = dd->xe/nc;
    174:     dd->Xs = dd->Xs/nc;
    175:     dd->Xe = dd->Xe/nc;
    176:   }

    178:   /*
    179:      We do not provide a getcoloring function in the DMDA operations because
    180:    the basic DMDA does not know about matrices. We think of DMDA as being more
    181:    more low-level then matrices.
    182:   */
    183:   if (dim == 1) {
    184:     DMCreateColoring_DA_1d_MPIAIJ(da,ctype,coloring);
    185:   } else if (dim == 2) {
    186:      DMCreateColoring_DA_2d_MPIAIJ(da,ctype,coloring);
    187:   } else if (dim == 3) {
    188:      DMCreateColoring_DA_3d_MPIAIJ(da,ctype,coloring);
    189:   } else SETERRQ1(PetscObjectComm((PetscObject)da),PETSC_ERR_SUP,"Not done for %D dimension, send us mail petsc-maint@mcs.anl.gov for code",dim);
    190:   if (isBAIJ) {
    191:     dd->w  = nc;
    192:     dd->xs = dd->xs*nc;
    193:     dd->xe = dd->xe*nc;
    194:     dd->Xs = dd->Xs*nc;
    195:     dd->Xe = dd->Xe*nc;
    196:   }
    197:   return(0);
    198: }

    200: /* ---------------------------------------------------------------------------------*/

    204: PetscErrorCode DMCreateColoring_DA_2d_MPIAIJ(DM da,ISColoringType ctype,ISColoring *coloring)
    205: {
    206:   PetscErrorCode   ierr;
    207:   PetscInt         xs,ys,nx,ny,i,j,ii,gxs,gys,gnx,gny,m,n,M,N,dim,s,k,nc,col;
    208:   PetscInt         ncolors;
    209:   MPI_Comm         comm;
    210:   DMDABoundaryType bx,by;
    211:   DMDAStencilType  st;
    212:   ISColoringValue  *colors;
    213:   DM_DA            *dd = (DM_DA*)da->data;

    216:   /*
    217:          nc - number of components per grid point
    218:          col - number of colors needed in one direction for single component problem

    220:   */
    221:   DMDAGetInfo(da,&dim,&m,&n,0,&M,&N,0,&nc,&s,&bx,&by,0,&st);
    222:   col  = 2*s + 1;
    223:   DMDAGetCorners(da,&xs,&ys,0,&nx,&ny,0);
    224:   DMDAGetGhostCorners(da,&gxs,&gys,0,&gnx,&gny,0);
    225:   PetscObjectGetComm((PetscObject)da,&comm);

    227:   /* special case as taught to us by Paul Hovland */
    228:   if (st == DMDA_STENCIL_STAR && s == 1) {
    229:     DMCreateColoring_DA_2d_5pt_MPIAIJ(da,ctype,coloring);
    230:   } else {

    232:     if (bx == DMDA_BOUNDARY_PERIODIC && (m % col)) SETERRQ2(PetscObjectComm((PetscObject)da),PETSC_ERR_SUP,"For coloring efficiency ensure number of grid points in X (%d) is divisible\n\
    233:                                                             by 2*stencil_width + 1 (%d)\n", m, col);
    234:     if (by == DMDA_BOUNDARY_PERIODIC && (n % col)) SETERRQ2(PetscObjectComm((PetscObject)da),PETSC_ERR_SUP,"For coloring efficiency ensure number of grid points in Y (%d) is divisible\n\
    235:                                                             by 2*stencil_width + 1 (%d)\n", n, col);
    236:     if (ctype == IS_COLORING_GLOBAL) {
    237:       if (!dd->localcoloring) {
    238:         PetscMalloc(nc*nx*ny*sizeof(ISColoringValue),&colors);
    239:         ii   = 0;
    240:         for (j=ys; j<ys+ny; j++) {
    241:           for (i=xs; i<xs+nx; i++) {
    242:             for (k=0; k<nc; k++) {
    243:               colors[ii++] = k + nc*((i % col) + col*(j % col));
    244:             }
    245:           }
    246:         }
    247:         ncolors = nc + nc*(col-1 + col*(col-1));
    248:         ISColoringCreate(comm,ncolors,nc*nx*ny,colors,&dd->localcoloring);
    249:       }
    250:       *coloring = dd->localcoloring;
    251:     } else if (ctype == IS_COLORING_GHOSTED) {
    252:       if (!dd->ghostedcoloring) {
    253:         PetscMalloc(nc*gnx*gny*sizeof(ISColoringValue),&colors);
    254:         ii   = 0;
    255:         for (j=gys; j<gys+gny; j++) {
    256:           for (i=gxs; i<gxs+gnx; i++) {
    257:             for (k=0; k<nc; k++) {
    258:               /* the complicated stuff is to handle periodic boundaries */
    259:               colors[ii++] = k + nc*((SetInRange(i,m) % col) + col*(SetInRange(j,n) % col));
    260:             }
    261:           }
    262:         }
    263:         ncolors = nc + nc*(col - 1 + col*(col-1));
    264:         ISColoringCreate(comm,ncolors,nc*gnx*gny,colors,&dd->ghostedcoloring);
    265:         /* PetscIntView(ncolors,(PetscInt*)colors,0); */

    267:         ISColoringSetType(dd->ghostedcoloring,IS_COLORING_GHOSTED);
    268:       }
    269:       *coloring = dd->ghostedcoloring;
    270:     } else SETERRQ1(PetscObjectComm((PetscObject)da),PETSC_ERR_ARG_WRONG,"Unknown ISColoringType %d",(int)ctype);
    271:   }
    272:   ISColoringReference(*coloring);
    273:   return(0);
    274: }

    276: /* ---------------------------------------------------------------------------------*/

    280: PetscErrorCode DMCreateColoring_DA_3d_MPIAIJ(DM da,ISColoringType ctype,ISColoring *coloring)
    281: {
    282:   PetscErrorCode   ierr;
    283:   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;
    284:   PetscInt         ncolors;
    285:   MPI_Comm         comm;
    286:   DMDABoundaryType bx,by,bz;
    287:   DMDAStencilType  st;
    288:   ISColoringValue  *colors;
    289:   DM_DA            *dd = (DM_DA*)da->data;

    292:   /*
    293:          nc - number of components per grid point
    294:          col - number of colors needed in one direction for single component problem

    296:   */
    297:   DMDAGetInfo(da,&dim,&m,&n,&p,&M,&N,&P,&nc,&s,&bx,&by,&bz,&st);
    298:   col  = 2*s + 1;
    299:   if (bx == DMDA_BOUNDARY_PERIODIC && (m % col)) SETERRQ(PetscObjectComm((PetscObject)da),PETSC_ERR_SUP,"For coloring efficiency ensure number of grid points in X is divisible\n\
    300:                                                          by 2*stencil_width + 1\n");
    301:   if (by == DMDA_BOUNDARY_PERIODIC && (n % col)) SETERRQ(PetscObjectComm((PetscObject)da),PETSC_ERR_SUP,"For coloring efficiency ensure number of grid points in Y is divisible\n\
    302:                                                          by 2*stencil_width + 1\n");
    303:   if (bz == DMDA_BOUNDARY_PERIODIC && (p % col)) SETERRQ(PetscObjectComm((PetscObject)da),PETSC_ERR_SUP,"For coloring efficiency ensure number of grid points in Z is divisible\n\
    304:                                                          by 2*stencil_width + 1\n");

    306:   DMDAGetCorners(da,&xs,&ys,&zs,&nx,&ny,&nz);
    307:   DMDAGetGhostCorners(da,&gxs,&gys,&gzs,&gnx,&gny,&gnz);
    308:   PetscObjectGetComm((PetscObject)da,&comm);

    310:   /* create the coloring */
    311:   if (ctype == IS_COLORING_GLOBAL) {
    312:     if (!dd->localcoloring) {
    313:       PetscMalloc(nc*nx*ny*nz*sizeof(ISColoringValue),&colors);
    314:       ii   = 0;
    315:       for (k=zs; k<zs+nz; k++) {
    316:         for (j=ys; j<ys+ny; j++) {
    317:           for (i=xs; i<xs+nx; i++) {
    318:             for (l=0; l<nc; l++) {
    319:               colors[ii++] = l + nc*((i % col) + col*(j % col) + col*col*(k % col));
    320:             }
    321:           }
    322:         }
    323:       }
    324:       ncolors = nc + nc*(col-1 + col*(col-1)+ col*col*(col-1));
    325:       ISColoringCreate(comm,ncolors,nc*nx*ny*nz,colors,&dd->localcoloring);
    326:     }
    327:     *coloring = dd->localcoloring;
    328:   } else if (ctype == IS_COLORING_GHOSTED) {
    329:     if (!dd->ghostedcoloring) {
    330:       PetscMalloc(nc*gnx*gny*gnz*sizeof(ISColoringValue),&colors);
    331:       ii   = 0;
    332:       for (k=gzs; k<gzs+gnz; k++) {
    333:         for (j=gys; j<gys+gny; j++) {
    334:           for (i=gxs; i<gxs+gnx; i++) {
    335:             for (l=0; l<nc; l++) {
    336:               /* the complicated stuff is to handle periodic boundaries */
    337:               colors[ii++] = l + nc*((SetInRange(i,m) % col) + col*(SetInRange(j,n) % col) + col*col*(SetInRange(k,p) % col));
    338:             }
    339:           }
    340:         }
    341:       }
    342:       ncolors = nc + nc*(col-1 + col*(col-1)+ col*col*(col-1));
    343:       ISColoringCreate(comm,ncolors,nc*gnx*gny*gnz,colors,&dd->ghostedcoloring);
    344:       ISColoringSetType(dd->ghostedcoloring,IS_COLORING_GHOSTED);
    345:     }
    346:     *coloring = dd->ghostedcoloring;
    347:   } else SETERRQ1(PetscObjectComm((PetscObject)da),PETSC_ERR_ARG_WRONG,"Unknown ISColoringType %d",(int)ctype);
    348:   ISColoringReference(*coloring);
    349:   return(0);
    350: }

    352: /* ---------------------------------------------------------------------------------*/

    356: PetscErrorCode DMCreateColoring_DA_1d_MPIAIJ(DM da,ISColoringType ctype,ISColoring *coloring)
    357: {
    358:   PetscErrorCode   ierr;
    359:   PetscInt         xs,nx,i,i1,gxs,gnx,l,m,M,dim,s,nc,col;
    360:   PetscInt         ncolors;
    361:   MPI_Comm         comm;
    362:   DMDABoundaryType bx;
    363:   ISColoringValue  *colors;
    364:   DM_DA            *dd = (DM_DA*)da->data;

    367:   /*
    368:          nc - number of components per grid point
    369:          col - number of colors needed in one direction for single component problem

    371:   */
    372:   DMDAGetInfo(da,&dim,&m,0,0,&M,0,0,&nc,&s,&bx,0,0,0);
    373:   col  = 2*s + 1;

    375:   if (bx == DMDA_BOUNDARY_PERIODIC && (m % col)) SETERRQ2(PetscObjectComm((PetscObject)da),PETSC_ERR_SUP,"For coloring efficiency ensure number of grid points %d is divisible\n\
    376:                                                           by 2*stencil_width + 1 %d\n",(int)m,(int)col);

    378:   DMDAGetCorners(da,&xs,0,0,&nx,0,0);
    379:   DMDAGetGhostCorners(da,&gxs,0,0,&gnx,0,0);
    380:   PetscObjectGetComm((PetscObject)da,&comm);

    382:   /* create the coloring */
    383:   if (ctype == IS_COLORING_GLOBAL) {
    384:     if (!dd->localcoloring) {
    385:       PetscMalloc(nc*nx*sizeof(ISColoringValue),&colors);
    386:       if (dd->ofillcols) {
    387:         PetscInt tc = 0;
    388:         for (i=0; i<nc; i++) tc += (PetscInt) (dd->ofillcols[i] > 0);
    389:         i1 = 0;
    390:         for (i=xs; i<xs+nx; i++) {
    391:           for (l=0; l<nc; l++) {
    392:             if (dd->ofillcols[l] && (i % col)) {
    393:               colors[i1++] =  nc - 1 + tc*((i % col) - 1) + dd->ofillcols[l];
    394:             } else {
    395:               colors[i1++] = l;
    396:             }
    397:           }
    398:         }
    399:         ncolors = nc + 2*s*tc;
    400:       } else {
    401:         i1 = 0;
    402:         for (i=xs; i<xs+nx; i++) {
    403:           for (l=0; l<nc; l++) {
    404:             colors[i1++] = l + nc*(i % col);
    405:           }
    406:         }
    407:         ncolors = nc + nc*(col-1);
    408:       }
    409:       ISColoringCreate(comm,ncolors,nc*nx,colors,&dd->localcoloring);
    410:     }
    411:     *coloring = dd->localcoloring;
    412:   } else if (ctype == IS_COLORING_GHOSTED) {
    413:     if (!dd->ghostedcoloring) {
    414:       PetscMalloc(nc*gnx*sizeof(ISColoringValue),&colors);
    415:       i1   = 0;
    416:       for (i=gxs; i<gxs+gnx; i++) {
    417:         for (l=0; l<nc; l++) {
    418:           /* the complicated stuff is to handle periodic boundaries */
    419:           colors[i1++] = l + nc*(SetInRange(i,m) % col);
    420:         }
    421:       }
    422:       ncolors = nc + nc*(col-1);
    423:       ISColoringCreate(comm,ncolors,nc*gnx,colors,&dd->ghostedcoloring);
    424:       ISColoringSetType(dd->ghostedcoloring,IS_COLORING_GHOSTED);
    425:     }
    426:     *coloring = dd->ghostedcoloring;
    427:   } else SETERRQ1(PetscObjectComm((PetscObject)da),PETSC_ERR_ARG_WRONG,"Unknown ISColoringType %d",(int)ctype);
    428:   ISColoringReference(*coloring);
    429:   return(0);
    430: }

    434: PetscErrorCode DMCreateColoring_DA_2d_5pt_MPIAIJ(DM da,ISColoringType ctype,ISColoring *coloring)
    435: {
    436:   PetscErrorCode   ierr;
    437:   PetscInt         xs,ys,nx,ny,i,j,ii,gxs,gys,gnx,gny,m,n,dim,s,k,nc;
    438:   PetscInt         ncolors;
    439:   MPI_Comm         comm;
    440:   DMDABoundaryType bx,by;
    441:   ISColoringValue  *colors;
    442:   DM_DA            *dd = (DM_DA*)da->data;

    445:   /*
    446:          nc - number of components per grid point
    447:          col - number of colors needed in one direction for single component problem

    449:   */
    450:   DMDAGetInfo(da,&dim,&m,&n,0,0,0,0,&nc,&s,&bx,&by,0,0);
    451:   DMDAGetCorners(da,&xs,&ys,0,&nx,&ny,0);
    452:   DMDAGetGhostCorners(da,&gxs,&gys,0,&gnx,&gny,0);
    453:   PetscObjectGetComm((PetscObject)da,&comm);

    455:   if (bx == DMDA_BOUNDARY_PERIODIC && (m % 5)) SETERRQ(PetscObjectComm((PetscObject)da),PETSC_ERR_SUP,"For coloring efficiency ensure number of grid points in X is divisible by 5\n");
    456:   if (by == DMDA_BOUNDARY_PERIODIC && (n % 5)) SETERRQ(PetscObjectComm((PetscObject)da),PETSC_ERR_SUP,"For coloring efficiency ensure number of grid points in Y is divisible by 5\n");

    458:   /* create the coloring */
    459:   if (ctype == IS_COLORING_GLOBAL) {
    460:     if (!dd->localcoloring) {
    461:       PetscMalloc(nc*nx*ny*sizeof(ISColoringValue),&colors);
    462:       ii   = 0;
    463:       for (j=ys; j<ys+ny; j++) {
    464:         for (i=xs; i<xs+nx; i++) {
    465:           for (k=0; k<nc; k++) {
    466:             colors[ii++] = k + nc*((3*j+i) % 5);
    467:           }
    468:         }
    469:       }
    470:       ncolors = 5*nc;
    471:       ISColoringCreate(comm,ncolors,nc*nx*ny,colors,&dd->localcoloring);
    472:     }
    473:     *coloring = dd->localcoloring;
    474:   } else if (ctype == IS_COLORING_GHOSTED) {
    475:     if (!dd->ghostedcoloring) {
    476:       PetscMalloc(nc*gnx*gny*sizeof(ISColoringValue),&colors);
    477:       ii = 0;
    478:       for (j=gys; j<gys+gny; j++) {
    479:         for (i=gxs; i<gxs+gnx; i++) {
    480:           for (k=0; k<nc; k++) {
    481:             colors[ii++] = k + nc*((3*SetInRange(j,n) + SetInRange(i,m)) % 5);
    482:           }
    483:         }
    484:       }
    485:       ncolors = 5*nc;
    486:       ISColoringCreate(comm,ncolors,nc*gnx*gny,colors,&dd->ghostedcoloring);
    487:       ISColoringSetType(dd->ghostedcoloring,IS_COLORING_GHOSTED);
    488:     }
    489:     *coloring = dd->ghostedcoloring;
    490:   } else SETERRQ1(PetscObjectComm((PetscObject)da),PETSC_ERR_ARG_WRONG,"Unknown ISColoringType %d",(int)ctype);
    491:   return(0);
    492: }

    494: /* =========================================================================== */
    495: extern PetscErrorCode DMCreateMatrix_DA_1d_MPIAIJ(DM,Mat);
    496: extern PetscErrorCode DMCreateMatrix_DA_1d_MPIAIJ_Fill(DM,Mat);
    497: extern PetscErrorCode DMCreateMatrix_DA_2d_MPIAIJ(DM,Mat);
    498: extern PetscErrorCode DMCreateMatrix_DA_2d_MPIAIJ_Fill(DM,Mat);
    499: extern PetscErrorCode DMCreateMatrix_DA_3d_MPIAIJ(DM,Mat);
    500: extern PetscErrorCode DMCreateMatrix_DA_3d_MPIAIJ_Fill(DM,Mat);
    501: extern PetscErrorCode DMCreateMatrix_DA_2d_MPIBAIJ(DM,Mat);
    502: extern PetscErrorCode DMCreateMatrix_DA_3d_MPIBAIJ(DM,Mat);
    503: extern PetscErrorCode DMCreateMatrix_DA_2d_MPISBAIJ(DM,Mat);
    504: extern PetscErrorCode DMCreateMatrix_DA_3d_MPISBAIJ(DM,Mat);

    508: /*@C
    509:    MatSetupDM - Sets the DMDA that is to be used by the HYPRE_StructMatrix PETSc matrix

    511:    Logically Collective on Mat

    513:    Input Parameters:
    514: +  mat - the matrix
    515: -  da - the da

    517:    Level: intermediate

    519: @*/
    520: PetscErrorCode MatSetupDM(Mat mat,DM da)
    521: {

    527:   PetscTryMethod(mat,"MatSetupDM_C",(Mat,DM),(mat,da));
    528:   return(0);
    529: }

    533: PetscErrorCode  MatView_MPI_DA(Mat A,PetscViewer viewer)
    534: {
    535:   DM                da;
    536:   PetscErrorCode    ierr;
    537:   const char        *prefix;
    538:   Mat               Anatural;
    539:   AO                ao;
    540:   PetscInt          rstart,rend,*petsc,i;
    541:   IS                is;
    542:   MPI_Comm          comm;
    543:   PetscViewerFormat format;

    546:   /* Check whether we are just printing info, in which case MatView() already viewed everything we wanted to view */
    547:   PetscViewerGetFormat(viewer,&format);
    548:   if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) return(0);

    550:   PetscObjectGetComm((PetscObject)A,&comm);
    551:   MatGetDM(A, &da);
    552:   if (!da) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONG,"Matrix not generated from a DMDA");

    554:   DMDAGetAO(da,&ao);
    555:   MatGetOwnershipRange(A,&rstart,&rend);
    556:   PetscMalloc((rend-rstart)*sizeof(PetscInt),&petsc);
    557:   for (i=rstart; i<rend; i++) petsc[i-rstart] = i;
    558:   AOApplicationToPetsc(ao,rend-rstart,petsc);
    559:   ISCreateGeneral(comm,rend-rstart,petsc,PETSC_OWN_POINTER,&is);

    561:   /* call viewer on natural ordering */
    562:   MatGetSubMatrix(A,is,is,MAT_INITIAL_MATRIX,&Anatural);
    563:   ISDestroy(&is);
    564:   PetscObjectGetOptionsPrefix((PetscObject)A,&prefix);
    565:   PetscObjectSetOptionsPrefix((PetscObject)Anatural,prefix);
    566:   PetscObjectSetName((PetscObject)Anatural,((PetscObject)A)->name);
    567:   MatView(Anatural,viewer);
    568:   MatDestroy(&Anatural);
    569:   return(0);
    570: }

    574: PetscErrorCode  MatLoad_MPI_DA(Mat A,PetscViewer viewer)
    575: {
    576:   DM             da;
    578:   Mat            Anatural,Aapp;
    579:   AO             ao;
    580:   PetscInt       rstart,rend,*app,i;
    581:   IS             is;
    582:   MPI_Comm       comm;

    585:   PetscObjectGetComm((PetscObject)A,&comm);
    586:   MatGetDM(A, &da);
    587:   if (!da) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONG,"Matrix not generated from a DMDA");

    589:   /* Load the matrix in natural ordering */
    590:   MatCreate(PetscObjectComm((PetscObject)A),&Anatural);
    591:   MatSetType(Anatural,((PetscObject)A)->type_name);
    592:   MatSetSizes(Anatural,A->rmap->n,A->cmap->n,A->rmap->N,A->cmap->N);
    593:   MatLoad(Anatural,viewer);

    595:   /* Map natural ordering to application ordering and create IS */
    596:   DMDAGetAO(da,&ao);
    597:   MatGetOwnershipRange(Anatural,&rstart,&rend);
    598:   PetscMalloc((rend-rstart)*sizeof(PetscInt),&app);
    599:   for (i=rstart; i<rend; i++) app[i-rstart] = i;
    600:   AOPetscToApplication(ao,rend-rstart,app);
    601:   ISCreateGeneral(comm,rend-rstart,app,PETSC_OWN_POINTER,&is);

    603:   /* Do permutation and replace header */
    604:   MatGetSubMatrix(Anatural,is,is,MAT_INITIAL_MATRIX,&Aapp);
    605:   MatHeaderReplace(A,Aapp);
    606:   ISDestroy(&is);
    607:   MatDestroy(&Anatural);
    608:   return(0);
    609: }

    613: PetscErrorCode DMCreateMatrix_DA(DM da, MatType mtype,Mat *J)
    614: {
    616:   PetscInt       dim,dof,nx,ny,nz,dims[3],starts[3],M,N,P;
    617:   Mat            A;
    618:   MPI_Comm       comm;
    619:   MatType        Atype;
    620:   PetscSection   section, sectionGlobal;
    621:   void           (*aij)(void)=NULL,(*baij)(void)=NULL,(*sbaij)(void)=NULL;
    622:   MatType        ttype[256];
    623:   PetscBool      flg;
    624:   PetscMPIInt    size;
    625:   DM_DA          *dd = (DM_DA*)da->data;

    628: #if !defined(PETSC_USE_DYNAMIC_LIBRARIES)
    629:   MatInitializePackage();
    630: #endif
    631:   if (!mtype) mtype = MATAIJ;
    632:   PetscStrcpy((char*)ttype,mtype);
    633:   PetscOptionsBegin(PetscObjectComm((PetscObject)da),((PetscObject)da)->prefix,"DMDA options","Mat");
    634:   PetscOptionsList("-dm_mat_type","Matrix type","MatSetType",MatList,mtype,(char*)ttype,256,&flg);
    635:   PetscOptionsEnd();

    637:   DMGetDefaultSection(da, &section);
    638:   if (section) {
    639:     PetscInt  bs = -1;
    640:     PetscInt  localSize;
    641:     PetscBool isShell, isBlock, isSeqBlock, isMPIBlock, isSymBlock, isSymSeqBlock, isSymMPIBlock, isSymmetric;

    643:     DMGetDefaultGlobalSection(da, &sectionGlobal);
    644:     PetscSectionGetConstrainedStorageSize(sectionGlobal, &localSize);
    645:     MatCreate(PetscObjectComm((PetscObject)da), J);
    646:     MatSetSizes(*J, localSize, localSize, PETSC_DETERMINE, PETSC_DETERMINE);
    647:     MatSetType(*J, mtype);
    648:     MatSetFromOptions(*J);
    649:     PetscStrcmp(mtype, MATSHELL, &isShell);
    650:     PetscStrcmp(mtype, MATBAIJ, &isBlock);
    651:     PetscStrcmp(mtype, MATSEQBAIJ, &isSeqBlock);
    652:     PetscStrcmp(mtype, MATMPIBAIJ, &isMPIBlock);
    653:     PetscStrcmp(mtype, MATSBAIJ, &isSymBlock);
    654:     PetscStrcmp(mtype, MATSEQSBAIJ, &isSymSeqBlock);
    655:     PetscStrcmp(mtype, MATMPISBAIJ, &isSymMPIBlock);
    656:     /* Check for symmetric storage */
    657:     isSymmetric = (PetscBool) (isSymBlock || isSymSeqBlock || isSymMPIBlock);
    658:     if (isSymmetric) {
    659:       MatSetOption(*J, MAT_IGNORE_LOWER_TRIANGULAR, PETSC_TRUE);
    660:     }
    661:     if (!isShell) {
    662:       PetscInt *dnz, *onz, *dnzu, *onzu, bsLocal;

    664:       if (bs < 0) {
    665:         if (isBlock || isSeqBlock || isMPIBlock || isSymBlock || isSymSeqBlock || isSymMPIBlock) {
    666:           PetscInt pStart, pEnd, p, dof;

    668:           PetscSectionGetChart(sectionGlobal, &pStart, &pEnd);
    669:           for (p = pStart; p < pEnd; ++p) {
    670:             PetscSectionGetDof(sectionGlobal, p, &dof);
    671:             if (dof) {
    672:               bs = dof;
    673:               break;
    674:             }
    675:           }
    676:         } else {
    677:           bs = 1;
    678:         }
    679:         /* Must have same blocksize on all procs (some might have no points) */
    680:         bsLocal = bs;
    681:         MPI_Allreduce(&bsLocal, &bs, 1, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)da));
    682:       }
    683:       PetscMalloc4(localSize/bs, PetscInt, &dnz, localSize/bs, PetscInt, &onz, localSize/bs, PetscInt, &dnzu, localSize/bs, PetscInt, &onzu);
    684:       PetscMemzero(dnz,  localSize/bs * sizeof(PetscInt));
    685:       PetscMemzero(onz,  localSize/bs * sizeof(PetscInt));
    686:       PetscMemzero(dnzu, localSize/bs * sizeof(PetscInt));
    687:       PetscMemzero(onzu, localSize/bs * sizeof(PetscInt));
    688:       /* DMPlexPreallocateOperator(dm, bs, section, sectionGlobal, dnz, onz, dnzu, onzu, *J, fillMatrix); */
    689:       PetscFree4(dnz, onz, dnzu, onzu);
    690:     }
    691:   }
    692:   /*
    693:                                   m
    694:           ------------------------------------------------------
    695:          |                                                     |
    696:          |                                                     |
    697:          |               ----------------------                |
    698:          |               |                    |                |
    699:       n  |           ny  |                    |                |
    700:          |               |                    |                |
    701:          |               .---------------------                |
    702:          |             (xs,ys)     nx                          |
    703:          |            .                                        |
    704:          |         (gxs,gys)                                   |
    705:          |                                                     |
    706:           -----------------------------------------------------
    707:   */

    709:   /*
    710:          nc - number of components per grid point
    711:          col - number of colors needed in one direction for single component problem

    713:   */
    714:   M   = dd->M;
    715:   N   = dd->N;
    716:   P   = dd->P;
    717:   dim = dd->dim;
    718:   dof = dd->w;
    719:   /* DMDAGetInfo(da,&dim,&M,&N,&P,0,0,0,&dof,0,0,0,0,0); */
    720:   DMDAGetCorners(da,0,0,0,&nx,&ny,&nz);
    721:   PetscObjectGetComm((PetscObject)da,&comm);
    722:   MatCreate(comm,&A);
    723:   MatSetSizes(A,dof*nx*ny*nz,dof*nx*ny*nz,dof*M*N*P,dof*M*N*P);
    724:   MatSetType(A,(MatType)ttype);
    725:   MatSetDM(A,da);
    726:   MatSetFromOptions(A);
    727:   MatGetType(A,&Atype);
    728:   /*
    729:      We do not provide a getmatrix function in the DMDA operations because
    730:    the basic DMDA does not know about matrices. We think of DMDA as being more
    731:    more low-level than matrices. This is kind of cheating but, cause sometimes
    732:    we think of DMDA has higher level than matrices.

    734:      We could switch based on Atype (or mtype), but we do not since the
    735:    specialized setting routines depend only the particular preallocation
    736:    details of the matrix, not the type itself.
    737:   */
    738:   PetscObjectQueryFunction((PetscObject)A,"MatMPIAIJSetPreallocation_C",&aij);
    739:   if (!aij) {
    740:     PetscObjectQueryFunction((PetscObject)A,"MatSeqAIJSetPreallocation_C",&aij);
    741:   }
    742:   if (!aij) {
    743:     PetscObjectQueryFunction((PetscObject)A,"MatMPIBAIJSetPreallocation_C",&baij);
    744:     if (!baij) {
    745:       PetscObjectQueryFunction((PetscObject)A,"MatSeqBAIJSetPreallocation_C",&baij);
    746:     }
    747:     if (!baij) {
    748:       PetscObjectQueryFunction((PetscObject)A,"MatMPISBAIJSetPreallocation_C",&sbaij);
    749:       if (!sbaij) {
    750:         PetscObjectQueryFunction((PetscObject)A,"MatSeqSBAIJSetPreallocation_C",&sbaij);
    751:       }
    752:     }
    753:   }
    754:   if (aij) {
    755:     if (dim == 1) {
    756:       if (dd->ofill) {
    757:         DMCreateMatrix_DA_1d_MPIAIJ_Fill(da,A);
    758:       } else {
    759:         DMCreateMatrix_DA_1d_MPIAIJ(da,A);
    760:       }
    761:     } else if (dim == 2) {
    762:       if (dd->ofill) {
    763:         DMCreateMatrix_DA_2d_MPIAIJ_Fill(da,A);
    764:       } else {
    765:         DMCreateMatrix_DA_2d_MPIAIJ(da,A);
    766:       }
    767:     } else if (dim == 3) {
    768:       if (dd->ofill) {
    769:         DMCreateMatrix_DA_3d_MPIAIJ_Fill(da,A);
    770:       } else {
    771:         DMCreateMatrix_DA_3d_MPIAIJ(da,A);
    772:       }
    773:     }
    774:   } else if (baij) {
    775:     if (dim == 2) {
    776:       DMCreateMatrix_DA_2d_MPIBAIJ(da,A);
    777:     } else if (dim == 3) {
    778:       DMCreateMatrix_DA_3d_MPIBAIJ(da,A);
    779:     } else SETERRQ3(PetscObjectComm((PetscObject)da),PETSC_ERR_SUP,"Not implemented for %D dimension and Matrix Type: %s in %D dimension! Send mail to petsc-maint@mcs.anl.gov for code",dim,Atype,dim);
    780:   } else if (sbaij) {
    781:     if (dim == 2) {
    782:       DMCreateMatrix_DA_2d_MPISBAIJ(da,A);
    783:     } else if (dim == 3) {
    784:       DMCreateMatrix_DA_3d_MPISBAIJ(da,A);
    785:     } else SETERRQ3(PetscObjectComm((PetscObject)da),PETSC_ERR_SUP,"Not implemented for %D dimension and Matrix Type: %s in %D dimension! Send mail to petsc-maint@mcs.anl.gov for code",dim,Atype,dim);
    786:   } else {
    787:     ISLocalToGlobalMapping ltog,ltogb;
    788:     DMGetLocalToGlobalMapping(da,&ltog);
    789:     DMGetLocalToGlobalMappingBlock(da,&ltogb);
    790:     MatSetUp(A);
    791:     MatSetLocalToGlobalMapping(A,ltog,ltog);
    792:     MatSetLocalToGlobalMappingBlock(A,ltogb,ltogb);
    793:   }
    794:   DMDAGetGhostCorners(da,&starts[0],&starts[1],&starts[2],&dims[0],&dims[1],&dims[2]);
    795:   MatSetStencil(A,dim,dims,starts,dof);
    796:   MatSetDM(A,da);
    797:   MPI_Comm_size(comm,&size);
    798:   if (size > 1) {
    799:     /* change viewer to display matrix in natural ordering */
    800:     MatShellSetOperation(A, MATOP_VIEW, (void (*)(void))MatView_MPI_DA);
    801:     MatShellSetOperation(A, MATOP_LOAD, (void (*)(void))MatLoad_MPI_DA);
    802:   }
    803:   *J = A;
    804:   return(0);
    805: }

    807: /* ---------------------------------------------------------------------------------*/
    810: PetscErrorCode DMCreateMatrix_DA_2d_MPIAIJ(DM da,Mat J)
    811: {
    812:   PetscErrorCode         ierr;
    813:   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;
    814:   PetscInt               lstart,lend,pstart,pend,*dnz,*onz;
    815:   MPI_Comm               comm;
    816:   PetscScalar            *values;
    817:   DMDABoundaryType       bx,by;
    818:   ISLocalToGlobalMapping ltog,ltogb;
    819:   DMDAStencilType        st;

    822:   /*
    823:          nc - number of components per grid point
    824:          col - number of colors needed in one direction for single component problem

    826:   */
    827:   DMDAGetInfo(da,&dim,&m,&n,0,0,0,0,&nc,&s,&bx,&by,0,&st);
    828:   col  = 2*s + 1;
    829:   DMDAGetCorners(da,&xs,&ys,0,&nx,&ny,0);
    830:   DMDAGetGhostCorners(da,&gxs,&gys,0,&gnx,&gny,0);
    831:   PetscObjectGetComm((PetscObject)da,&comm);

    833:   PetscMalloc2(nc,PetscInt,&rows,col*col*nc*nc,PetscInt,&cols);
    834:   DMGetLocalToGlobalMapping(da,&ltog);
    835:   DMGetLocalToGlobalMappingBlock(da,&ltogb);

    837:   /* determine the matrix preallocation information */
    838:   MatPreallocateInitialize(comm,nc*nx*ny,nc*nx*ny,dnz,onz);
    839:   for (i=xs; i<xs+nx; i++) {

    841:     pstart = (bx == DMDA_BOUNDARY_PERIODIC) ? -s : (PetscMax(-s,-i));
    842:     pend   = (bx == DMDA_BOUNDARY_PERIODIC) ?  s : (PetscMin(s,m-i-1));

    844:     for (j=ys; j<ys+ny; j++) {
    845:       slot = i - gxs + gnx*(j - gys);

    847:       lstart = (by == DMDA_BOUNDARY_PERIODIC) ? -s : (PetscMax(-s,-j));
    848:       lend   = (by == DMDA_BOUNDARY_PERIODIC) ?  s : (PetscMin(s,n-j-1));

    850:       cnt = 0;
    851:       for (k=0; k<nc; k++) {
    852:         for (l=lstart; l<lend+1; l++) {
    853:           for (p=pstart; p<pend+1; p++) {
    854:             if ((st == DMDA_STENCIL_BOX) || (!l || !p)) {  /* entries on star have either l = 0 or p = 0 */
    855:               cols[cnt++] = k + nc*(slot + gnx*l + p);
    856:             }
    857:           }
    858:         }
    859:         rows[k] = k + nc*(slot);
    860:       }
    861:       MatPreallocateSetLocal(ltog,nc,rows,ltog,cnt,cols,dnz,onz);
    862:     }
    863:   }
    864:   MatSetBlockSize(J,nc);
    865:   MatSeqAIJSetPreallocation(J,0,dnz);
    866:   MatMPIAIJSetPreallocation(J,0,dnz,0,onz);
    867:   MatPreallocateFinalize(dnz,onz);

    869:   MatSetLocalToGlobalMapping(J,ltog,ltog);
    870:   MatSetLocalToGlobalMappingBlock(J,ltogb,ltogb);

    872:   /*
    873:     For each node in the grid: we get the neighbors in the local (on processor ordering
    874:     that includes the ghost points) then MatSetValuesLocal() maps those indices to the global
    875:     PETSc ordering.
    876:   */
    877:   if (!da->prealloc_only) {
    878:     PetscMalloc(col*col*nc*nc*sizeof(PetscScalar),&values);
    879:     PetscMemzero(values,col*col*nc*nc*sizeof(PetscScalar));
    880:     for (i=xs; i<xs+nx; i++) {

    882:       pstart = (bx == DMDA_BOUNDARY_PERIODIC) ? -s : (PetscMax(-s,-i));
    883:       pend   = (bx == DMDA_BOUNDARY_PERIODIC) ?  s : (PetscMin(s,m-i-1));

    885:       for (j=ys; j<ys+ny; j++) {
    886:         slot = i - gxs + gnx*(j - gys);

    888:         lstart = (by == DMDA_BOUNDARY_PERIODIC) ? -s : (PetscMax(-s,-j));
    889:         lend   = (by == DMDA_BOUNDARY_PERIODIC) ?  s : (PetscMin(s,n-j-1));

    891:         cnt = 0;
    892:         for (k=0; k<nc; k++) {
    893:           for (l=lstart; l<lend+1; l++) {
    894:             for (p=pstart; p<pend+1; p++) {
    895:               if ((st == DMDA_STENCIL_BOX) || (!l || !p)) {  /* entries on star have either l = 0 or p = 0 */
    896:                 cols[cnt++] = k + nc*(slot + gnx*l + p);
    897:               }
    898:             }
    899:           }
    900:           rows[k] = k + nc*(slot);
    901:         }
    902:         MatSetValuesLocal(J,nc,rows,cnt,cols,values,INSERT_VALUES);
    903:       }
    904:     }
    905:     PetscFree(values);
    906:     MatAssemblyBegin(J,MAT_FINAL_ASSEMBLY);
    907:     MatAssemblyEnd(J,MAT_FINAL_ASSEMBLY);
    908:   }
    909:   PetscFree2(rows,cols);
    910:   return(0);
    911: }

    915: PetscErrorCode DMCreateMatrix_DA_2d_MPIAIJ_Fill(DM da,Mat J)
    916: {
    917:   PetscErrorCode         ierr;
    918:   PetscInt               xs,ys,nx,ny,i,j,slot,gxs,gys,gnx,gny;
    919:   PetscInt               m,n,dim,s,*cols,k,nc,row,col,cnt,l,p;
    920:   PetscInt               lstart,lend,pstart,pend,*dnz,*onz;
    921:   DM_DA                  *dd = (DM_DA*)da->data;
    922:   PetscInt               ifill_col,*ofill = dd->ofill, *dfill = dd->dfill;
    923:   MPI_Comm               comm;
    924:   PetscScalar            *values;
    925:   DMDABoundaryType       bx,by;
    926:   ISLocalToGlobalMapping ltog,ltogb;
    927:   DMDAStencilType        st;

    930:   /*
    931:          nc - number of components per grid point
    932:          col - number of colors needed in one direction for single component problem

    934:   */
    935:   DMDAGetInfo(da,&dim,&m,&n,0,0,0,0,&nc,&s,&bx,&by,0,&st);
    936:   col  = 2*s + 1;
    937:   DMDAGetCorners(da,&xs,&ys,0,&nx,&ny,0);
    938:   DMDAGetGhostCorners(da,&gxs,&gys,0,&gnx,&gny,0);
    939:   PetscObjectGetComm((PetscObject)da,&comm);

    941:   PetscMalloc(col*col*nc*nc*sizeof(PetscInt),&cols);
    942:   DMGetLocalToGlobalMapping(da,&ltog);
    943:   DMGetLocalToGlobalMappingBlock(da,&ltogb);

    945:   /* determine the matrix preallocation information */
    946:   MatPreallocateInitialize(comm,nc*nx*ny,nc*nx*ny,dnz,onz);
    947:   for (i=xs; i<xs+nx; i++) {

    949:     pstart = (bx == DMDA_BOUNDARY_PERIODIC) ? -s : (PetscMax(-s,-i));
    950:     pend   = (bx == DMDA_BOUNDARY_PERIODIC) ?  s : (PetscMin(s,m-i-1));

    952:     for (j=ys; j<ys+ny; j++) {
    953:       slot = i - gxs + gnx*(j - gys);

    955:       lstart = (by == DMDA_BOUNDARY_PERIODIC) ? -s : (PetscMax(-s,-j));
    956:       lend   = (by == DMDA_BOUNDARY_PERIODIC) ?  s : (PetscMin(s,n-j-1));

    958:       for (k=0; k<nc; k++) {
    959:         cnt = 0;
    960:         for (l=lstart; l<lend+1; l++) {
    961:           for (p=pstart; p<pend+1; p++) {
    962:             if (l || p) {
    963:               if ((st == DMDA_STENCIL_BOX) || (!l || !p)) {  /* entries on star */
    964:                 for (ifill_col=ofill[k]; ifill_col<ofill[k+1]; ifill_col++) cols[cnt++] = ofill[ifill_col] + nc*(slot + gnx*l + p);
    965:               }
    966:             } else {
    967:               if (dfill) {
    968:                 for (ifill_col=dfill[k]; ifill_col<dfill[k+1]; ifill_col++) cols[cnt++] = dfill[ifill_col] + nc*(slot + gnx*l + p);
    969:               } else {
    970:                 for (ifill_col=0; ifill_col<nc; ifill_col++) cols[cnt++] = ifill_col + nc*(slot + gnx*l + p);
    971:               }
    972:             }
    973:           }
    974:         }
    975:         row  = k + nc*(slot);
    976:         MatPreallocateSetLocal(ltog,1,&row,ltog,cnt,cols,dnz,onz);
    977:       }
    978:     }
    979:   }
    980:   MatSeqAIJSetPreallocation(J,0,dnz);
    981:   MatMPIAIJSetPreallocation(J,0,dnz,0,onz);
    982:   MatPreallocateFinalize(dnz,onz);
    983:   MatSetLocalToGlobalMapping(J,ltog,ltog);
    984:   MatSetLocalToGlobalMappingBlock(J,ltogb,ltogb);

    986:   /*
    987:     For each node in the grid: we get the neighbors in the local (on processor ordering
    988:     that includes the ghost points) then MatSetValuesLocal() maps those indices to the global
    989:     PETSc ordering.
    990:   */
    991:   if (!da->prealloc_only) {
    992:     PetscMalloc(col*col*nc*nc*sizeof(PetscScalar),&values);
    993:     PetscMemzero(values,col*col*nc*nc*sizeof(PetscScalar));
    994:     for (i=xs; i<xs+nx; i++) {

    996:       pstart = (bx == DMDA_BOUNDARY_PERIODIC) ? -s : (PetscMax(-s,-i));
    997:       pend   = (bx == DMDA_BOUNDARY_PERIODIC) ?  s : (PetscMin(s,m-i-1));

    999:       for (j=ys; j<ys+ny; j++) {
    1000:         slot = i - gxs + gnx*(j - gys);

    1002:         lstart = (by == DMDA_BOUNDARY_PERIODIC) ? -s : (PetscMax(-s,-j));
    1003:         lend   = (by == DMDA_BOUNDARY_PERIODIC) ?  s : (PetscMin(s,n-j-1));

    1005:         for (k=0; k<nc; k++) {
    1006:           cnt = 0;
    1007:           for (l=lstart; l<lend+1; l++) {
    1008:             for (p=pstart; p<pend+1; p++) {
    1009:               if (l || p) {
    1010:                 if ((st == DMDA_STENCIL_BOX) || (!l || !p)) {  /* entries on star */
    1011:                   for (ifill_col=ofill[k]; ifill_col<ofill[k+1]; ifill_col++) cols[cnt++] = ofill[ifill_col] + nc*(slot + gnx*l + p);
    1012:                 }
    1013:               } else {
    1014:                 if (dfill) {
    1015:                   for (ifill_col=dfill[k]; ifill_col<dfill[k+1]; ifill_col++) cols[cnt++] = dfill[ifill_col] + nc*(slot + gnx*l + p);
    1016:                 } else {
    1017:                   for (ifill_col=0; ifill_col<nc; ifill_col++) cols[cnt++] = ifill_col + nc*(slot + gnx*l + p);
    1018:                 }
    1019:               }
    1020:             }
    1021:           }
    1022:           row  = k + nc*(slot);
    1023:           MatSetValuesLocal(J,1,&row,cnt,cols,values,INSERT_VALUES);
    1024:         }
    1025:       }
    1026:     }
    1027:     PetscFree(values);
    1028:     MatAssemblyBegin(J,MAT_FINAL_ASSEMBLY);
    1029:     MatAssemblyEnd(J,MAT_FINAL_ASSEMBLY);
    1030:   }
    1031:   PetscFree(cols);
    1032:   return(0);
    1033: }

    1035: /* ---------------------------------------------------------------------------------*/

    1039: PetscErrorCode DMCreateMatrix_DA_3d_MPIAIJ(DM da,Mat J)
    1040: {
    1041:   PetscErrorCode         ierr;
    1042:   PetscInt               xs,ys,nx,ny,i,j,slot,gxs,gys,gnx,gny;
    1043:   PetscInt               m,n,dim,s,*cols = NULL,k,nc,*rows = NULL,col,cnt,l,p,*dnz = NULL,*onz = NULL;
    1044:   PetscInt               istart,iend,jstart,jend,kstart,kend,zs,nz,gzs,gnz,ii,jj,kk;
    1045:   MPI_Comm               comm;
    1046:   PetscScalar            *values;
    1047:   DMDABoundaryType       bx,by,bz;
    1048:   ISLocalToGlobalMapping ltog,ltogb;
    1049:   DMDAStencilType        st;

    1052:   /*
    1053:          nc - number of components per grid point
    1054:          col - number of colors needed in one direction for single component problem

    1056:   */
    1057:   DMDAGetInfo(da,&dim,&m,&n,&p,0,0,0,&nc,&s,&bx,&by,&bz,&st);
    1058:   col  = 2*s + 1;

    1060:   DMDAGetCorners(da,&xs,&ys,&zs,&nx,&ny,&nz);
    1061:   DMDAGetGhostCorners(da,&gxs,&gys,&gzs,&gnx,&gny,&gnz);
    1062:   PetscObjectGetComm((PetscObject)da,&comm);

    1064:   PetscMalloc2(nc,PetscInt,&rows,col*col*col*nc*nc,PetscInt,&cols);
    1065:   DMGetLocalToGlobalMapping(da,&ltog);
    1066:   DMGetLocalToGlobalMappingBlock(da,&ltogb);

    1068:   /* determine the matrix preallocation information */
    1069:   MatPreallocateInitialize(comm,nc*nx*ny*nz,nc*nx*ny*nz,dnz,onz);
    1070:   for (i=xs; i<xs+nx; i++) {
    1071:     istart = (bx == DMDA_BOUNDARY_PERIODIC) ? -s : (PetscMax(-s,-i));
    1072:     iend   = (bx == DMDA_BOUNDARY_PERIODIC) ?  s : (PetscMin(s,m-i-1));
    1073:     for (j=ys; j<ys+ny; j++) {
    1074:       jstart = (by == DMDA_BOUNDARY_PERIODIC) ? -s : (PetscMax(-s,-j));
    1075:       jend   = (by == DMDA_BOUNDARY_PERIODIC) ?  s : (PetscMin(s,n-j-1));
    1076:       for (k=zs; k<zs+nz; k++) {
    1077:         kstart = (bz == DMDA_BOUNDARY_PERIODIC) ? -s : (PetscMax(-s,-k));
    1078:         kend   = (bz == DMDA_BOUNDARY_PERIODIC) ?  s : (PetscMin(s,p-k-1));

    1080:         slot = i - gxs + gnx*(j - gys) + gnx*gny*(k - gzs);

    1082:         cnt = 0;
    1083:         for (l=0; l<nc; l++) {
    1084:           for (ii=istart; ii<iend+1; ii++) {
    1085:             for (jj=jstart; jj<jend+1; jj++) {
    1086:               for (kk=kstart; kk<kend+1; kk++) {
    1087:                 if ((st == DMDA_STENCIL_BOX) || ((!ii && !jj) || (!jj && !kk) || (!ii && !kk))) {/* entries on star*/
    1088:                   cols[cnt++] = l + nc*(slot + ii + gnx*jj + gnx*gny*kk);
    1089:                 }
    1090:               }
    1091:             }
    1092:           }
    1093:           rows[l] = l + nc*(slot);
    1094:         }
    1095:         MatPreallocateSetLocal(ltog,nc,rows,ltog,cnt,cols,dnz,onz);
    1096:       }
    1097:     }
    1098:   }
    1099:   MatSetBlockSize(J,nc);
    1100:   MatSeqAIJSetPreallocation(J,0,dnz);
    1101:   MatMPIAIJSetPreallocation(J,0,dnz,0,onz);
    1102:   MatPreallocateFinalize(dnz,onz);
    1103:   MatSetLocalToGlobalMapping(J,ltog,ltog);
    1104:   MatSetLocalToGlobalMappingBlock(J,ltogb,ltogb);

    1106:   /*
    1107:     For each node in the grid: we get the neighbors in the local (on processor ordering
    1108:     that includes the ghost points) then MatSetValuesLocal() maps those indices to the global
    1109:     PETSc ordering.
    1110:   */
    1111:   if (!da->prealloc_only) {
    1112:     PetscMalloc(col*col*col*nc*nc*nc*sizeof(PetscScalar),&values);
    1113:     PetscMemzero(values,col*col*col*nc*nc*nc*sizeof(PetscScalar));
    1114:     for (i=xs; i<xs+nx; i++) {
    1115:       istart = (bx == DMDA_BOUNDARY_PERIODIC) ? -s : (PetscMax(-s,-i));
    1116:       iend   = (bx == DMDA_BOUNDARY_PERIODIC) ?  s : (PetscMin(s,m-i-1));
    1117:       for (j=ys; j<ys+ny; j++) {
    1118:         jstart = (by == DMDA_BOUNDARY_PERIODIC) ? -s : (PetscMax(-s,-j));
    1119:         jend   = (by == DMDA_BOUNDARY_PERIODIC) ?  s : (PetscMin(s,n-j-1));
    1120:         for (k=zs; k<zs+nz; k++) {
    1121:           kstart = (bz == DMDA_BOUNDARY_PERIODIC) ? -s : (PetscMax(-s,-k));
    1122:           kend   = (bz == DMDA_BOUNDARY_PERIODIC) ?  s : (PetscMin(s,p-k-1));

    1124:           slot = i - gxs + gnx*(j - gys) + gnx*gny*(k - gzs);

    1126:           cnt = 0;
    1127:           for (l=0; l<nc; l++) {
    1128:             for (ii=istart; ii<iend+1; ii++) {
    1129:               for (jj=jstart; jj<jend+1; jj++) {
    1130:                 for (kk=kstart; kk<kend+1; kk++) {
    1131:                   if ((st == DMDA_STENCIL_BOX) || ((!ii && !jj) || (!jj && !kk) || (!ii && !kk))) {/* entries on star*/
    1132:                     cols[cnt++] = l + nc*(slot + ii + gnx*jj + gnx*gny*kk);
    1133:                   }
    1134:                 }
    1135:               }
    1136:             }
    1137:             rows[l] = l + nc*(slot);
    1138:           }
    1139:           MatSetValuesLocal(J,nc,rows,cnt,cols,values,INSERT_VALUES);
    1140:         }
    1141:       }
    1142:     }
    1143:     PetscFree(values);
    1144:     MatAssemblyBegin(J,MAT_FINAL_ASSEMBLY);
    1145:     MatAssemblyEnd(J,MAT_FINAL_ASSEMBLY);
    1146:   }
    1147:   PetscFree2(rows,cols);
    1148:   return(0);
    1149: }

    1151: /* ---------------------------------------------------------------------------------*/

    1155: PetscErrorCode DMCreateMatrix_DA_1d_MPIAIJ_Fill(DM da,Mat J)
    1156: {
    1157:   PetscErrorCode         ierr;
    1158:   DM_DA                  *dd = (DM_DA*)da->data;
    1159:   PetscInt               xs,nx,i,j,gxs,gnx,row,k,l;
    1160:   PetscInt               m,dim,s,*cols = NULL,nc,col,cnt,*ocols;
    1161:   PetscInt               *ofill = dd->ofill;
    1162:   PetscScalar            *values;
    1163:   DMDABoundaryType       bx;
    1164:   ISLocalToGlobalMapping ltog,ltogb;
    1165:   PetscMPIInt            rank,size;

    1168:   if (dd->bx == DMDA_BOUNDARY_PERIODIC) SETERRQ(PetscObjectComm((PetscObject)da),PETSC_ERR_SUP,"With fill provided not implemented with periodic boundary conditions");
    1169:   MPI_Comm_rank(PetscObjectComm((PetscObject)da),&rank);
    1170:   MPI_Comm_size(PetscObjectComm((PetscObject)da),&size);

    1172:   /*
    1173:          nc - number of components per grid point
    1174:          col - number of colors needed in one direction for single component problem

    1176:   */
    1177:   DMDAGetInfo(da,&dim,&m,0,0,0,0,0,&nc,&s,&bx,0,0,0);
    1178:   col  = 2*s + 1;

    1180:   DMDAGetCorners(da,&xs,0,0,&nx,0,0);
    1181:   DMDAGetGhostCorners(da,&gxs,0,0,&gnx,0,0);

    1183:   MatSetBlockSize(J,nc);
    1184:   PetscMalloc2(nx*nc,PetscInt,&cols,nx*nc,PetscInt,&ocols);
    1185:   PetscMemzero(cols,nx*nc*sizeof(PetscInt));
    1186:   PetscMemzero(ocols,nx*nc*sizeof(PetscInt));

    1188:   /*
    1189:         note should be smaller for first and last process with no periodic
    1190:         does not handle dfill
    1191:   */
    1192:   cnt = 0;
    1193:   /* coupling with process to the left */
    1194:   for (i=0; i<s; i++) {
    1195:     for (j=0; j<nc; j++) {
    1196:       ocols[cnt] = ((!rank) ? 0 : (s - i)*(ofill[j+1] - ofill[j]));
    1197:       cols[cnt]  = nc + (s + i)*(ofill[j+1] - ofill[j]);
    1198:       cnt++;
    1199:     }
    1200:   }
    1201:   for (i=s; i<nx-s; i++) {
    1202:     for (j=0; j<nc; j++) {
    1203:       cols[cnt] = nc + 2*s*(ofill[j+1] - ofill[j]);
    1204:       cnt++;
    1205:     }
    1206:   }
    1207:   /* coupling with process to the right */
    1208:   for (i=nx-s; i<nx; i++) {
    1209:     for (j=0; j<nc; j++) {
    1210:       ocols[cnt] = ((rank == (size-1)) ? 0 : (i - nx + s + 1)*(ofill[j+1] - ofill[j]));
    1211:       cols[cnt]  = nc + (s + nx - i - 1)*(ofill[j+1] - ofill[j]);
    1212:       cnt++;
    1213:     }
    1214:   }

    1216:   MatSeqAIJSetPreallocation(J,0,cols);
    1217:   MatMPIAIJSetPreallocation(J,0,cols,0,ocols);
    1218:   PetscFree2(cols,ocols);

    1220:   DMGetLocalToGlobalMapping(da,&ltog);
    1221:   DMGetLocalToGlobalMappingBlock(da,&ltogb);
    1222:   MatSetLocalToGlobalMapping(J,ltog,ltog);
    1223:   MatSetLocalToGlobalMappingBlock(J,ltogb,ltogb);

    1225:   /*
    1226:     For each node in the grid: we get the neighbors in the local (on processor ordering
    1227:     that includes the ghost points) then MatSetValuesLocal() maps those indices to the global
    1228:     PETSc ordering.
    1229:   */
    1230:   if (!da->prealloc_only) {
    1231:     PetscMalloc(col*nc*nc*sizeof(PetscInt),&cols);
    1232:     PetscMalloc(col*nc*nc*sizeof(PetscScalar),&values);
    1233:     PetscMemzero(values,col*nc*nc*sizeof(PetscScalar));

    1235:     row = xs*nc;
    1236:     /* coupling with process to the left */
    1237:     for (i=xs; i<xs+s; i++) {
    1238:       for (j=0; j<nc; j++) {
    1239:         cnt = 0;
    1240:         if (rank) {
    1241:           for (l=0; l<s; l++) {
    1242:             for (k=ofill[j]; k<ofill[j+1]; k++) cols[cnt++] = (i - s + l)*nc + ofill[k];
    1243:           }
    1244:         }
    1245:         for (k=0; k<nc; k++) {
    1246:           cols[cnt++] = i*nc + k;
    1247:         }
    1248:         for (l=0; l<s; l++) {
    1249:           for (k=ofill[j]; k<ofill[j+1]; k++) cols[cnt++] = (i + s - l)*nc + ofill[k];
    1250:         }
    1251:         MatSetValues(J,1,&row,cnt,cols,values,INSERT_VALUES);
    1252:         row++;
    1253:       }
    1254:     }
    1255:     for (i=xs+s; i<xs+nx-s; i++) {
    1256:       for (j=0; j<nc; j++) {
    1257:         cnt = 0;
    1258:         for (l=0; l<s; l++) {
    1259:           for (k=ofill[j]; k<ofill[j+1]; k++) cols[cnt++] = (i - s + l)*nc + ofill[k];
    1260:         }
    1261:         for (k=0; k<nc; k++) {
    1262:           cols[cnt++] = i*nc + k;
    1263:         }
    1264:         for (l=0; l<s; l++) {
    1265:           for (k=ofill[j]; k<ofill[j+1]; k++) cols[cnt++] = (i + s - l)*nc + ofill[k];
    1266:         }
    1267:         MatSetValues(J,1,&row,cnt,cols,values,INSERT_VALUES);
    1268:         row++;
    1269:       }
    1270:     }
    1271:     /* coupling with process to the right */
    1272:     for (i=xs+nx-s; i<xs+nx; i++) {
    1273:       for (j=0; j<nc; j++) {
    1274:         cnt = 0;
    1275:         for (l=0; l<s; l++) {
    1276:           for (k=ofill[j]; k<ofill[j+1]; k++) cols[cnt++] = (i - s + l)*nc + ofill[k];
    1277:         }
    1278:         for (k=0; k<nc; k++) {
    1279:           cols[cnt++] = i*nc + k;
    1280:         }
    1281:         if (rank < size-1) {
    1282:           for (l=0; l<s; l++) {
    1283:             for (k=ofill[j]; k<ofill[j+1]; k++) cols[cnt++] = (i + s - l)*nc + ofill[k];
    1284:           }
    1285:         }
    1286:         MatSetValues(J,1,&row,cnt,cols,values,INSERT_VALUES);
    1287:         row++;
    1288:       }
    1289:     }
    1290:     PetscFree(values);
    1291:     MatAssemblyBegin(J,MAT_FINAL_ASSEMBLY);
    1292:     MatAssemblyEnd(J,MAT_FINAL_ASSEMBLY);
    1293:     PetscFree(cols);
    1294:   }
    1295:   return(0);
    1296: }

    1298: /* ---------------------------------------------------------------------------------*/

    1302: PetscErrorCode DMCreateMatrix_DA_1d_MPIAIJ(DM da,Mat J)
    1303: {
    1304:   PetscErrorCode         ierr;
    1305:   PetscInt               xs,nx,i,i1,slot,gxs,gnx;
    1306:   PetscInt               m,dim,s,*cols = NULL,nc,*rows = NULL,col,cnt,l;
    1307:   PetscInt               istart,iend;
    1308:   PetscScalar            *values;
    1309:   DMDABoundaryType       bx;
    1310:   ISLocalToGlobalMapping ltog,ltogb;

    1313:   /*
    1314:          nc - number of components per grid point
    1315:          col - number of colors needed in one direction for single component problem

    1317:   */
    1318:   DMDAGetInfo(da,&dim,&m,0,0,0,0,0,&nc,&s,&bx,0,0,0);
    1319:   col  = 2*s + 1;

    1321:   DMDAGetCorners(da,&xs,0,0,&nx,0,0);
    1322:   DMDAGetGhostCorners(da,&gxs,0,0,&gnx,0,0);

    1324:   MatSetBlockSize(J,nc);
    1325:   MatSeqAIJSetPreallocation(J,col*nc,0);
    1326:   MatMPIAIJSetPreallocation(J,col*nc,0,col*nc,0);

    1328:   DMGetLocalToGlobalMapping(da,&ltog);
    1329:   DMGetLocalToGlobalMappingBlock(da,&ltogb);
    1330:   MatSetLocalToGlobalMapping(J,ltog,ltog);
    1331:   MatSetLocalToGlobalMappingBlock(J,ltogb,ltogb);

    1333:   /*
    1334:     For each node in the grid: we get the neighbors in the local (on processor ordering
    1335:     that includes the ghost points) then MatSetValuesLocal() maps those indices to the global
    1336:     PETSc ordering.
    1337:   */
    1338:   if (!da->prealloc_only) {
    1339:     PetscMalloc2(nc,PetscInt,&rows,col*nc*nc,PetscInt,&cols);
    1340:     PetscMalloc(col*nc*nc*sizeof(PetscScalar),&values);
    1341:     PetscMemzero(values,col*nc*nc*sizeof(PetscScalar));
    1342:     for (i=xs; i<xs+nx; i++) {
    1343:       istart = PetscMax(-s,gxs - i);
    1344:       iend   = PetscMin(s,gxs + gnx - i - 1);
    1345:       slot   = i - gxs;

    1347:       cnt = 0;
    1348:       for (l=0; l<nc; l++) {
    1349:         for (i1=istart; i1<iend+1; i1++) {
    1350:           cols[cnt++] = l + nc*(slot + i1);
    1351:         }
    1352:         rows[l] = l + nc*(slot);
    1353:       }
    1354:       MatSetValuesLocal(J,nc,rows,cnt,cols,values,INSERT_VALUES);
    1355:     }
    1356:     PetscFree(values);
    1357:     MatAssemblyBegin(J,MAT_FINAL_ASSEMBLY);
    1358:     MatAssemblyEnd(J,MAT_FINAL_ASSEMBLY);
    1359:     PetscFree2(rows,cols);
    1360:   }
    1361:   return(0);
    1362: }

    1366: PetscErrorCode DMCreateMatrix_DA_2d_MPIBAIJ(DM da,Mat J)
    1367: {
    1368:   PetscErrorCode         ierr;
    1369:   PetscInt               xs,ys,nx,ny,i,j,slot,gxs,gys,gnx,gny;
    1370:   PetscInt               m,n,dim,s,*cols,nc,col,cnt,*dnz,*onz;
    1371:   PetscInt               istart,iend,jstart,jend,ii,jj;
    1372:   MPI_Comm               comm;
    1373:   PetscScalar            *values;
    1374:   DMDABoundaryType       bx,by;
    1375:   DMDAStencilType        st;
    1376:   ISLocalToGlobalMapping ltog,ltogb;

    1379:   /*
    1380:      nc - number of components per grid point
    1381:      col - number of colors needed in one direction for single component problem
    1382:   */
    1383:   DMDAGetInfo(da,&dim,&m,&n,0,0,0,0,&nc,&s,&bx,&by,0,&st);
    1384:   col  = 2*s + 1;

    1386:   DMDAGetCorners(da,&xs,&ys,0,&nx,&ny,0);
    1387:   DMDAGetGhostCorners(da,&gxs,&gys,0,&gnx,&gny,0);
    1388:   PetscObjectGetComm((PetscObject)da,&comm);

    1390:   PetscMalloc(col*col*nc*nc*sizeof(PetscInt),&cols);

    1392:   DMGetLocalToGlobalMapping(da,&ltog);
    1393:   DMGetLocalToGlobalMappingBlock(da,&ltogb);

    1395:   /* determine the matrix preallocation information */
    1396:   MatPreallocateInitialize(comm,nx*ny,nx*ny,dnz,onz);
    1397:   for (i=xs; i<xs+nx; i++) {
    1398:     istart = (bx == DMDA_BOUNDARY_PERIODIC) ? -s : (PetscMax(-s,-i));
    1399:     iend   = (bx == DMDA_BOUNDARY_PERIODIC) ?  s : (PetscMin(s,m-i-1));
    1400:     for (j=ys; j<ys+ny; j++) {
    1401:       jstart = (by == DMDA_BOUNDARY_PERIODIC) ? -s : (PetscMax(-s,-j));
    1402:       jend   = (by == DMDA_BOUNDARY_PERIODIC) ?  s : (PetscMin(s,n-j-1));
    1403:       slot   = i - gxs + gnx*(j - gys);

    1405:       /* Find block columns in block row */
    1406:       cnt = 0;
    1407:       for (ii=istart; ii<iend+1; ii++) {
    1408:         for (jj=jstart; jj<jend+1; jj++) {
    1409:           if (st == DMDA_STENCIL_BOX || !ii || !jj) { /* BOX or on the STAR */
    1410:             cols[cnt++] = slot + ii + gnx*jj;
    1411:           }
    1412:         }
    1413:       }
    1414:       MatPreallocateSetLocal(ltogb,1,&slot,ltogb,cnt,cols,dnz,onz);
    1415:     }
    1416:   }
    1417:   MatSeqBAIJSetPreallocation(J,nc,0,dnz);
    1418:   MatMPIBAIJSetPreallocation(J,nc,0,dnz,0,onz);
    1419:   MatPreallocateFinalize(dnz,onz);

    1421:   MatSetLocalToGlobalMapping(J,ltog,ltog);
    1422:   MatSetLocalToGlobalMappingBlock(J,ltogb,ltogb);

    1424:   /*
    1425:     For each node in the grid: we get the neighbors in the local (on processor ordering
    1426:     that includes the ghost points) then MatSetValuesLocal() maps those indices to the global
    1427:     PETSc ordering.
    1428:   */
    1429:   if (!da->prealloc_only) {
    1430:     PetscMalloc(col*col*nc*nc*sizeof(PetscScalar),&values);
    1431:     PetscMemzero(values,col*col*nc*nc*sizeof(PetscScalar));
    1432:     for (i=xs; i<xs+nx; i++) {
    1433:       istart = (bx == DMDA_BOUNDARY_PERIODIC) ? -s : (PetscMax(-s,-i));
    1434:       iend   = (bx == DMDA_BOUNDARY_PERIODIC) ?  s : (PetscMin(s,m-i-1));
    1435:       for (j=ys; j<ys+ny; j++) {
    1436:         jstart = (by == DMDA_BOUNDARY_PERIODIC) ? -s : (PetscMax(-s,-j));
    1437:         jend   = (by == DMDA_BOUNDARY_PERIODIC) ?  s : (PetscMin(s,n-j-1));
    1438:         slot = i - gxs + gnx*(j - gys);
    1439:         cnt  = 0;
    1440:         for (ii=istart; ii<iend+1; ii++) {
    1441:           for (jj=jstart; jj<jend+1; jj++) {
    1442:             if (st == DMDA_STENCIL_BOX || !ii || !jj) { /* BOX or on the STAR */
    1443:               cols[cnt++] = slot + ii + gnx*jj;
    1444:             }
    1445:           }
    1446:         }
    1447:         MatSetValuesBlockedLocal(J,1,&slot,cnt,cols,values,INSERT_VALUES);
    1448:       }
    1449:     }
    1450:     PetscFree(values);
    1451:     MatAssemblyBegin(J,MAT_FINAL_ASSEMBLY);
    1452:     MatAssemblyEnd(J,MAT_FINAL_ASSEMBLY);
    1453:   }
    1454:   PetscFree(cols);
    1455:   return(0);
    1456: }

    1460: PetscErrorCode DMCreateMatrix_DA_3d_MPIBAIJ(DM da,Mat J)
    1461: {
    1462:   PetscErrorCode         ierr;
    1463:   PetscInt               xs,ys,nx,ny,i,j,slot,gxs,gys,gnx,gny;
    1464:   PetscInt               m,n,dim,s,*cols,k,nc,col,cnt,p,*dnz,*onz;
    1465:   PetscInt               istart,iend,jstart,jend,kstart,kend,zs,nz,gzs,gnz,ii,jj,kk;
    1466:   MPI_Comm               comm;
    1467:   PetscScalar            *values;
    1468:   DMDABoundaryType       bx,by,bz;
    1469:   DMDAStencilType        st;
    1470:   ISLocalToGlobalMapping ltog,ltogb;

    1473:   /*
    1474:          nc - number of components per grid point
    1475:          col - number of colors needed in one direction for single component problem

    1477:   */
    1478:   DMDAGetInfo(da,&dim,&m,&n,&p,0,0,0,&nc,&s,&bx,&by,&bz,&st);
    1479:   col  = 2*s + 1;

    1481:   DMDAGetCorners(da,&xs,&ys,&zs,&nx,&ny,&nz);
    1482:   DMDAGetGhostCorners(da,&gxs,&gys,&gzs,&gnx,&gny,&gnz);
    1483:   PetscObjectGetComm((PetscObject)da,&comm);

    1485:   PetscMalloc(col*col*col*sizeof(PetscInt),&cols);

    1487:   DMGetLocalToGlobalMapping(da,&ltog);
    1488:   DMGetLocalToGlobalMappingBlock(da,&ltogb);

    1490:   /* determine the matrix preallocation information */
    1491:   MatPreallocateInitialize(comm,nx*ny*nz,nx*ny*nz,dnz,onz);
    1492:   for (i=xs; i<xs+nx; i++) {
    1493:     istart = (bx == DMDA_BOUNDARY_PERIODIC) ? -s : (PetscMax(-s,-i));
    1494:     iend   = (bx == DMDA_BOUNDARY_PERIODIC) ?  s : (PetscMin(s,m-i-1));
    1495:     for (j=ys; j<ys+ny; j++) {
    1496:       jstart = (by == DMDA_BOUNDARY_PERIODIC) ? -s : (PetscMax(-s,-j));
    1497:       jend   = (by == DMDA_BOUNDARY_PERIODIC) ?  s : (PetscMin(s,n-j-1));
    1498:       for (k=zs; k<zs+nz; k++) {
    1499:         kstart = (bz == DMDA_BOUNDARY_PERIODIC) ? -s : (PetscMax(-s,-k));
    1500:         kend   = (bz == DMDA_BOUNDARY_PERIODIC) ?  s : (PetscMin(s,p-k-1));

    1502:         slot = i - gxs + gnx*(j - gys) + gnx*gny*(k - gzs);

    1504:         /* Find block columns in block row */
    1505:         cnt = 0;
    1506:         for (ii=istart; ii<iend+1; ii++) {
    1507:           for (jj=jstart; jj<jend+1; jj++) {
    1508:             for (kk=kstart; kk<kend+1; kk++) {
    1509:               if ((st == DMDA_STENCIL_BOX) || ((!ii && !jj) || (!jj && !kk) || (!ii && !kk))) {/* entries on star*/
    1510:                 cols[cnt++] = slot + ii + gnx*jj + gnx*gny*kk;
    1511:               }
    1512:             }
    1513:           }
    1514:         }
    1515:         MatPreallocateSetLocal(ltogb,1,&slot,ltogb,cnt,cols,dnz,onz);
    1516:       }
    1517:     }
    1518:   }
    1519:   MatSeqBAIJSetPreallocation(J,nc,0,dnz);
    1520:   MatMPIBAIJSetPreallocation(J,nc,0,dnz,0,onz);
    1521:   MatPreallocateFinalize(dnz,onz);

    1523:   MatSetLocalToGlobalMapping(J,ltog,ltog);
    1524:   MatSetLocalToGlobalMappingBlock(J,ltogb,ltogb);

    1526:   /*
    1527:     For each node in the grid: we get the neighbors in the local (on processor ordering
    1528:     that includes the ghost points) then MatSetValuesLocal() maps those indices to the global
    1529:     PETSc ordering.
    1530:   */
    1531:   if (!da->prealloc_only) {
    1532:     PetscMalloc(col*col*col*nc*nc*sizeof(PetscScalar),&values);
    1533:     PetscMemzero(values,col*col*col*nc*nc*sizeof(PetscScalar));
    1534:     for (i=xs; i<xs+nx; i++) {
    1535:       istart = (bx == DMDA_BOUNDARY_PERIODIC) ? -s : (PetscMax(-s,-i));
    1536:       iend   = (bx == DMDA_BOUNDARY_PERIODIC) ?  s : (PetscMin(s,m-i-1));
    1537:       for (j=ys; j<ys+ny; j++) {
    1538:         jstart = (by == DMDA_BOUNDARY_PERIODIC) ? -s : (PetscMax(-s,-j));
    1539:         jend   = (by == DMDA_BOUNDARY_PERIODIC) ?  s : (PetscMin(s,n-j-1));
    1540:         for (k=zs; k<zs+nz; k++) {
    1541:           kstart = (bz == DMDA_BOUNDARY_PERIODIC) ? -s : (PetscMax(-s,-k));
    1542:           kend   = (bz == DMDA_BOUNDARY_PERIODIC) ?  s : (PetscMin(s,p-k-1));

    1544:           slot = i - gxs + gnx*(j - gys) + gnx*gny*(k - gzs);

    1546:           cnt = 0;
    1547:           for (ii=istart; ii<iend+1; ii++) {
    1548:             for (jj=jstart; jj<jend+1; jj++) {
    1549:               for (kk=kstart; kk<kend+1; kk++) {
    1550:                 if ((st == DMDA_STENCIL_BOX) || ((!ii && !jj) || (!jj && !kk) || (!ii && !kk))) {/* entries on star*/
    1551:                   cols[cnt++] = slot + ii + gnx*jj + gnx*gny*kk;
    1552:                 }
    1553:               }
    1554:             }
    1555:           }
    1556:           MatSetValuesBlockedLocal(J,1,&slot,cnt,cols,values,INSERT_VALUES);
    1557:         }
    1558:       }
    1559:     }
    1560:     PetscFree(values);
    1561:     MatAssemblyBegin(J,MAT_FINAL_ASSEMBLY);
    1562:     MatAssemblyEnd(J,MAT_FINAL_ASSEMBLY);
    1563:   }
    1564:   PetscFree(cols);
    1565:   return(0);
    1566: }

    1570: /*
    1571:   This helper is for of SBAIJ preallocation, to discard the lower-triangular values which are difficult to
    1572:   identify in the local ordering with periodic domain.
    1573: */
    1574: static PetscErrorCode L2GFilterUpperTriangular(ISLocalToGlobalMapping ltog,PetscInt *row,PetscInt *cnt,PetscInt col[])
    1575: {
    1577:   PetscInt       i,n;

    1580:   ISLocalToGlobalMappingApply(ltog,1,row,row);
    1581:   ISLocalToGlobalMappingApply(ltog,*cnt,col,col);
    1582:   for (i=0,n=0; i<*cnt; i++) {
    1583:     if (col[i] >= *row) col[n++] = col[i];
    1584:   }
    1585:   *cnt = n;
    1586:   return(0);
    1587: }

    1591: PetscErrorCode DMCreateMatrix_DA_2d_MPISBAIJ(DM da,Mat J)
    1592: {
    1593:   PetscErrorCode         ierr;
    1594:   PetscInt               xs,ys,nx,ny,i,j,slot,gxs,gys,gnx,gny;
    1595:   PetscInt               m,n,dim,s,*cols,nc,col,cnt,*dnz,*onz;
    1596:   PetscInt               istart,iend,jstart,jend,ii,jj;
    1597:   MPI_Comm               comm;
    1598:   PetscScalar            *values;
    1599:   DMDABoundaryType       bx,by;
    1600:   DMDAStencilType        st;
    1601:   ISLocalToGlobalMapping ltog,ltogb;

    1604:   /*
    1605:      nc - number of components per grid point
    1606:      col - number of colors needed in one direction for single component problem
    1607:   */
    1608:   DMDAGetInfo(da,&dim,&m,&n,0,0,0,0,&nc,&s,&bx,&by,0,&st);
    1609:   col  = 2*s + 1;

    1611:   DMDAGetCorners(da,&xs,&ys,0,&nx,&ny,0);
    1612:   DMDAGetGhostCorners(da,&gxs,&gys,0,&gnx,&gny,0);
    1613:   PetscObjectGetComm((PetscObject)da,&comm);

    1615:   PetscMalloc(col*col*nc*nc*sizeof(PetscInt),&cols);

    1617:   DMGetLocalToGlobalMapping(da,&ltog);
    1618:   DMGetLocalToGlobalMappingBlock(da,&ltogb);

    1620:   /* determine the matrix preallocation information */
    1621:   MatPreallocateInitialize(comm,nx*ny,nx*ny,dnz,onz);
    1622:   for (i=xs; i<xs+nx; i++) {
    1623:     istart = (bx == DMDA_BOUNDARY_PERIODIC) ? -s : (PetscMax(-s,-i));
    1624:     iend   = (bx == DMDA_BOUNDARY_PERIODIC) ?  s : (PetscMin(s,m-i-1));
    1625:     for (j=ys; j<ys+ny; j++) {
    1626:       jstart = (by == DMDA_BOUNDARY_PERIODIC) ? -s : (PetscMax(-s,-j));
    1627:       jend   = (by == DMDA_BOUNDARY_PERIODIC) ?  s : (PetscMin(s,n-j-1));
    1628:       slot   = i - gxs + gnx*(j - gys);

    1630:       /* Find block columns in block row */
    1631:       cnt = 0;
    1632:       for (ii=istart; ii<iend+1; ii++) {
    1633:         for (jj=jstart; jj<jend+1; jj++) {
    1634:           if (st == DMDA_STENCIL_BOX || !ii || !jj) {
    1635:             cols[cnt++] = slot + ii + gnx*jj;
    1636:           }
    1637:         }
    1638:       }
    1639:       L2GFilterUpperTriangular(ltogb,&slot,&cnt,cols);
    1640:       MatPreallocateSymmetricSet(slot,cnt,cols,dnz,onz);
    1641:     }
    1642:   }
    1643:   MatSeqSBAIJSetPreallocation(J,nc,0,dnz);
    1644:   MatMPISBAIJSetPreallocation(J,nc,0,dnz,0,onz);
    1645:   MatPreallocateFinalize(dnz,onz);

    1647:   MatSetLocalToGlobalMapping(J,ltog,ltog);
    1648:   MatSetLocalToGlobalMappingBlock(J,ltogb,ltogb);

    1650:   /*
    1651:     For each node in the grid: we get the neighbors in the local (on processor ordering
    1652:     that includes the ghost points) then MatSetValuesLocal() maps those indices to the global
    1653:     PETSc ordering.
    1654:   */
    1655:   if (!da->prealloc_only) {
    1656:     PetscMalloc(col*col*nc*nc*sizeof(PetscScalar),&values);
    1657:     PetscMemzero(values,col*col*nc*nc*sizeof(PetscScalar));
    1658:     for (i=xs; i<xs+nx; i++) {
    1659:       istart = (bx == DMDA_BOUNDARY_PERIODIC) ? -s : (PetscMax(-s,-i));
    1660:       iend   = (bx == DMDA_BOUNDARY_PERIODIC) ?  s : (PetscMin(s,m-i-1));
    1661:       for (j=ys; j<ys+ny; j++) {
    1662:         jstart = (by == DMDA_BOUNDARY_PERIODIC) ? -s : (PetscMax(-s,-j));
    1663:         jend   = (by == DMDA_BOUNDARY_PERIODIC) ?  s : (PetscMin(s,n-j-1));
    1664:         slot   = i - gxs + gnx*(j - gys);

    1666:         /* Find block columns in block row */
    1667:         cnt = 0;
    1668:         for (ii=istart; ii<iend+1; ii++) {
    1669:           for (jj=jstart; jj<jend+1; jj++) {
    1670:             if (st == DMDA_STENCIL_BOX || !ii || !jj) {
    1671:               cols[cnt++] = slot + ii + gnx*jj;
    1672:             }
    1673:           }
    1674:         }
    1675:         L2GFilterUpperTriangular(ltogb,&slot,&cnt,cols);
    1676:         MatSetValuesBlocked(J,1,&slot,cnt,cols,values,INSERT_VALUES);
    1677:       }
    1678:     }
    1679:     PetscFree(values);
    1680:     MatAssemblyBegin(J,MAT_FINAL_ASSEMBLY);
    1681:     MatAssemblyEnd(J,MAT_FINAL_ASSEMBLY);
    1682:   }
    1683:   PetscFree(cols);
    1684:   return(0);
    1685: }

    1689: PetscErrorCode DMCreateMatrix_DA_3d_MPISBAIJ(DM da,Mat J)
    1690: {
    1691:   PetscErrorCode         ierr;
    1692:   PetscInt               xs,ys,nx,ny,i,j,slot,gxs,gys,gnx,gny;
    1693:   PetscInt               m,n,dim,s,*cols,k,nc,col,cnt,p,*dnz,*onz;
    1694:   PetscInt               istart,iend,jstart,jend,kstart,kend,zs,nz,gzs,gnz,ii,jj,kk;
    1695:   MPI_Comm               comm;
    1696:   PetscScalar            *values;
    1697:   DMDABoundaryType       bx,by,bz;
    1698:   DMDAStencilType        st;
    1699:   ISLocalToGlobalMapping ltog,ltogb;

    1702:   /*
    1703:      nc - number of components per grid point
    1704:      col - number of colors needed in one direction for single component problem
    1705:   */
    1706:   DMDAGetInfo(da,&dim,&m,&n,&p,0,0,0,&nc,&s,&bx,&by,&bz,&st);
    1707:   col  = 2*s + 1;

    1709:   DMDAGetCorners(da,&xs,&ys,&zs,&nx,&ny,&nz);
    1710:   DMDAGetGhostCorners(da,&gxs,&gys,&gzs,&gnx,&gny,&gnz);
    1711:   PetscObjectGetComm((PetscObject)da,&comm);

    1713:   /* create the matrix */
    1714:   PetscMalloc(col*col*col*sizeof(PetscInt),&cols);

    1716:   DMGetLocalToGlobalMapping(da,&ltog);
    1717:   DMGetLocalToGlobalMappingBlock(da,&ltogb);

    1719:   /* determine the matrix preallocation information */
    1720:   MatPreallocateInitialize(comm,nx*ny*nz,nx*ny*nz,dnz,onz);
    1721:   for (i=xs; i<xs+nx; i++) {
    1722:     istart = (bx == DMDA_BOUNDARY_PERIODIC) ? -s : (PetscMax(-s,-i));
    1723:     iend   = (bx == DMDA_BOUNDARY_PERIODIC) ?  s : (PetscMin(s,m-i-1));
    1724:     for (j=ys; j<ys+ny; j++) {
    1725:       jstart = (by == DMDA_BOUNDARY_PERIODIC) ? -s : (PetscMax(-s,-j));
    1726:       jend   = (by == DMDA_BOUNDARY_PERIODIC) ?  s : (PetscMin(s,n-j-1));
    1727:       for (k=zs; k<zs+nz; k++) {
    1728:         kstart = (bz == DMDA_BOUNDARY_PERIODIC) ? -s : (PetscMax(-s,-k));
    1729:         kend   = (bz == DMDA_BOUNDARY_PERIODIC) ?  s : (PetscMin(s,p-k-1));

    1731:         slot = i - gxs + gnx*(j - gys) + gnx*gny*(k - gzs);

    1733:         /* Find block columns in block row */
    1734:         cnt = 0;
    1735:         for (ii=istart; ii<iend+1; ii++) {
    1736:           for (jj=jstart; jj<jend+1; jj++) {
    1737:             for (kk=kstart; kk<kend+1; kk++) {
    1738:               if ((st == DMDA_STENCIL_BOX) || (!ii && !jj) || (!jj && !kk) || (!ii && !kk)) {
    1739:                 cols[cnt++] = slot + ii + gnx*jj + gnx*gny*kk;
    1740:               }
    1741:             }
    1742:           }
    1743:         }
    1744:         L2GFilterUpperTriangular(ltogb,&slot,&cnt,cols);
    1745:         MatPreallocateSymmetricSet(slot,cnt,cols,dnz,onz);
    1746:       }
    1747:     }
    1748:   }
    1749:   MatSeqSBAIJSetPreallocation(J,nc,0,dnz);
    1750:   MatMPISBAIJSetPreallocation(J,nc,0,dnz,0,onz);
    1751:   MatPreallocateFinalize(dnz,onz);

    1753:   MatSetLocalToGlobalMapping(J,ltog,ltog);
    1754:   MatSetLocalToGlobalMappingBlock(J,ltogb,ltogb);

    1756:   /*
    1757:     For each node in the grid: we get the neighbors in the local (on processor ordering
    1758:     that includes the ghost points) then MatSetValuesLocal() maps those indices to the global
    1759:     PETSc ordering.
    1760:   */
    1761:   if (!da->prealloc_only) {
    1762:     PetscMalloc(col*col*col*nc*nc*sizeof(PetscScalar),&values);
    1763:     PetscMemzero(values,col*col*col*nc*nc*sizeof(PetscScalar));
    1764:     for (i=xs; i<xs+nx; i++) {
    1765:       istart = (bx == DMDA_BOUNDARY_PERIODIC) ? -s : (PetscMax(-s,-i));
    1766:       iend   = (bx == DMDA_BOUNDARY_PERIODIC) ?  s : (PetscMin(s,m-i-1));
    1767:       for (j=ys; j<ys+ny; j++) {
    1768:         jstart = (by == DMDA_BOUNDARY_PERIODIC) ? -s : (PetscMax(-s,-j));
    1769:         jend   = (by == DMDA_BOUNDARY_PERIODIC) ?  s : (PetscMin(s,n-j-1));
    1770:         for (k=zs; k<zs+nz; k++) {
    1771:           kstart = (bz == DMDA_BOUNDARY_PERIODIC) ? -s : (PetscMax(-s,-k));
    1772:           kend   = (bz == DMDA_BOUNDARY_PERIODIC) ?  s : (PetscMin(s,p-k-1));

    1774:           slot = i - gxs + gnx*(j - gys) + gnx*gny*(k - gzs);

    1776:           cnt = 0;
    1777:           for (ii=istart; ii<iend+1; ii++) {
    1778:             for (jj=jstart; jj<jend+1; jj++) {
    1779:               for (kk=kstart; kk<kend+1; kk++) {
    1780:                 if ((st == DMDA_STENCIL_BOX) || (!ii && !jj) || (!jj && !kk) || (!ii && !kk)) {
    1781:                   cols[cnt++] = slot + ii + gnx*jj + gnx*gny*kk;
    1782:                 }
    1783:               }
    1784:             }
    1785:           }
    1786:           L2GFilterUpperTriangular(ltogb,&slot,&cnt,cols);
    1787:           MatSetValuesBlocked(J,1,&slot,cnt,cols,values,INSERT_VALUES);
    1788:         }
    1789:       }
    1790:     }
    1791:     PetscFree(values);
    1792:     MatAssemblyBegin(J,MAT_FINAL_ASSEMBLY);
    1793:     MatAssemblyEnd(J,MAT_FINAL_ASSEMBLY);
    1794:   }
    1795:   PetscFree(cols);
    1796:   return(0);
    1797: }

    1799: /* ---------------------------------------------------------------------------------*/

    1803: PetscErrorCode DMCreateMatrix_DA_3d_MPIAIJ_Fill(DM da,Mat J)
    1804: {
    1805:   PetscErrorCode         ierr;
    1806:   PetscInt               xs,ys,nx,ny,i,j,slot,gxs,gys,gnx,gny;
    1807:   PetscInt               m,n,dim,s,*cols,k,nc,row,col,cnt,l,p,*dnz,*onz;
    1808:   PetscInt               istart,iend,jstart,jend,kstart,kend,zs,nz,gzs,gnz,ii,jj,kk;
    1809:   DM_DA                  *dd = (DM_DA*)da->data;
    1810:   PetscInt               ifill_col,*dfill = dd->dfill,*ofill = dd->ofill;
    1811:   MPI_Comm               comm;
    1812:   PetscScalar            *values;
    1813:   DMDABoundaryType       bx,by,bz;
    1814:   ISLocalToGlobalMapping ltog,ltogb;
    1815:   DMDAStencilType        st;

    1818:   /*
    1819:          nc - number of components per grid point
    1820:          col - number of colors needed in one direction for single component problem

    1822:   */
    1823:   DMDAGetInfo(da,&dim,&m,&n,&p,0,0,0,&nc,&s,&bx,&by,&bz,&st);
    1824:   col  = 2*s + 1;
    1825:   if (bx == DMDA_BOUNDARY_PERIODIC && (m % col)) SETERRQ(PetscObjectComm((PetscObject)da),PETSC_ERR_SUP,"For coloring efficiency ensure number of grid points in X is divisible\n\
    1826:                  by 2*stencil_width + 1\n");
    1827:   if (by == DMDA_BOUNDARY_PERIODIC && (n % col)) SETERRQ(PetscObjectComm((PetscObject)da),PETSC_ERR_SUP,"For coloring efficiency ensure number of grid points in Y is divisible\n\
    1828:                  by 2*stencil_width + 1\n");
    1829:   if (bz == DMDA_BOUNDARY_PERIODIC && (p % col)) SETERRQ(PetscObjectComm((PetscObject)da),PETSC_ERR_SUP,"For coloring efficiency ensure number of grid points in Z is divisible\n\
    1830:                  by 2*stencil_width + 1\n");

    1832:   DMDAGetCorners(da,&xs,&ys,&zs,&nx,&ny,&nz);
    1833:   DMDAGetGhostCorners(da,&gxs,&gys,&gzs,&gnx,&gny,&gnz);
    1834:   PetscObjectGetComm((PetscObject)da,&comm);

    1836:   PetscMalloc(col*col*col*nc*sizeof(PetscInt),&cols);
    1837:   DMGetLocalToGlobalMapping(da,&ltog);
    1838:   DMGetLocalToGlobalMappingBlock(da,&ltogb);

    1840:   /* determine the matrix preallocation information */
    1841:   MatPreallocateInitialize(comm,nc*nx*ny*nz,nc*nx*ny*nz,dnz,onz);

    1844:   for (i=xs; i<xs+nx; i++) {
    1845:     istart = (bx == DMDA_BOUNDARY_PERIODIC) ? -s : (PetscMax(-s,-i));
    1846:     iend   = (bx == DMDA_BOUNDARY_PERIODIC) ?  s : (PetscMin(s,m-i-1));
    1847:     for (j=ys; j<ys+ny; j++) {
    1848:       jstart = (by == DMDA_BOUNDARY_PERIODIC) ? -s : (PetscMax(-s,-j));
    1849:       jend   = (by == DMDA_BOUNDARY_PERIODIC) ?  s : (PetscMin(s,n-j-1));
    1850:       for (k=zs; k<zs+nz; k++) {
    1851:         kstart = (bz == DMDA_BOUNDARY_PERIODIC) ? -s : (PetscMax(-s,-k));
    1852:         kend   = (bz == DMDA_BOUNDARY_PERIODIC) ?  s : (PetscMin(s,p-k-1));

    1854:         slot = i - gxs + gnx*(j - gys) + gnx*gny*(k - gzs);

    1856:         for (l=0; l<nc; l++) {
    1857:           cnt = 0;
    1858:           for (ii=istart; ii<iend+1; ii++) {
    1859:             for (jj=jstart; jj<jend+1; jj++) {
    1860:               for (kk=kstart; kk<kend+1; kk++) {
    1861:                 if (ii || jj || kk) {
    1862:                   if ((st == DMDA_STENCIL_BOX) || ((!ii && !jj) || (!jj && !kk) || (!ii && !kk))) {/* entries on star*/
    1863:                     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);
    1864:                   }
    1865:                 } else {
    1866:                   if (dfill) {
    1867:                     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);
    1868:                   } else {
    1869:                     for (ifill_col=0; ifill_col<nc; ifill_col++) cols[cnt++] = ifill_col + nc*(slot + ii + gnx*jj + gnx*gny*kk);
    1870:                   }
    1871:                 }
    1872:               }
    1873:             }
    1874:           }
    1875:           row  = l + nc*(slot);
    1876:           MatPreallocateSetLocal(ltog,1,&row,ltog,cnt,cols,dnz,onz);
    1877:         }
    1878:       }
    1879:     }
    1880:   }
    1881:   MatSeqAIJSetPreallocation(J,0,dnz);
    1882:   MatMPIAIJSetPreallocation(J,0,dnz,0,onz);
    1883:   MatPreallocateFinalize(dnz,onz);
    1884:   MatSetLocalToGlobalMapping(J,ltog,ltog);
    1885:   MatSetLocalToGlobalMappingBlock(J,ltogb,ltogb);

    1887:   /*
    1888:     For each node in the grid: we get the neighbors in the local (on processor ordering
    1889:     that includes the ghost points) then MatSetValuesLocal() maps those indices to the global
    1890:     PETSc ordering.
    1891:   */
    1892:   if (!da->prealloc_only) {
    1893:     PetscMalloc(col*col*col*nc*nc*nc*sizeof(PetscScalar),&values);
    1894:     PetscMemzero(values,col*col*col*nc*nc*nc*sizeof(PetscScalar));
    1895:     for (i=xs; i<xs+nx; i++) {
    1896:       istart = (bx == DMDA_BOUNDARY_PERIODIC) ? -s : (PetscMax(-s,-i));
    1897:       iend   = (bx == DMDA_BOUNDARY_PERIODIC) ?  s : (PetscMin(s,m-i-1));
    1898:       for (j=ys; j<ys+ny; j++) {
    1899:         jstart = (by == DMDA_BOUNDARY_PERIODIC) ? -s : (PetscMax(-s,-j));
    1900:         jend   = (by == DMDA_BOUNDARY_PERIODIC) ?  s : (PetscMin(s,n-j-1));
    1901:         for (k=zs; k<zs+nz; k++) {
    1902:           kstart = (bz == DMDA_BOUNDARY_PERIODIC) ? -s : (PetscMax(-s,-k));
    1903:           kend   = (bz == DMDA_BOUNDARY_PERIODIC) ?  s : (PetscMin(s,p-k-1));

    1905:           slot = i - gxs + gnx*(j - gys) + gnx*gny*(k - gzs);

    1907:           for (l=0; l<nc; l++) {
    1908:             cnt = 0;
    1909:             for (ii=istart; ii<iend+1; ii++) {
    1910:               for (jj=jstart; jj<jend+1; jj++) {
    1911:                 for (kk=kstart; kk<kend+1; kk++) {
    1912:                   if (ii || jj || kk) {
    1913:                     if ((st == DMDA_STENCIL_BOX) || ((!ii && !jj) || (!jj && !kk) || (!ii && !kk))) {/* entries on star*/
    1914:                       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);
    1915:                     }
    1916:                   } else {
    1917:                     if (dfill) {
    1918:                       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);
    1919:                     } else {
    1920:                       for (ifill_col=0; ifill_col<nc; ifill_col++) cols[cnt++] = ifill_col + nc*(slot + ii + gnx*jj + gnx*gny*kk);
    1921:                     }
    1922:                   }
    1923:                 }
    1924:               }
    1925:             }
    1926:             row  = l + nc*(slot);
    1927:             MatSetValuesLocal(J,1,&row,cnt,cols,values,INSERT_VALUES);
    1928:           }
    1929:         }
    1930:       }
    1931:     }
    1932:     PetscFree(values);
    1933:     MatAssemblyBegin(J,MAT_FINAL_ASSEMBLY);
    1934:     MatAssemblyEnd(J,MAT_FINAL_ASSEMBLY);
    1935:   }
    1936:   PetscFree(cols);
    1937:   return(0);
    1938: }