Actual source code: fdda.c

  1: #define PETSCDM_DLL
  2: 
 3:  #include private/daimpl.h
 4:  #include petscmat.h


  7: EXTERN PetscErrorCode DAGetColoring1d_MPIAIJ(DA,ISColoringType,ISColoring *);
  8: EXTERN PetscErrorCode DAGetColoring2d_MPIAIJ(DA,ISColoringType,ISColoring *);
  9: EXTERN PetscErrorCode DAGetColoring2d_5pt_MPIAIJ(DA,ISColoringType,ISColoring *);
 10: EXTERN PetscErrorCode DAGetColoring3d_MPIAIJ(DA,ISColoringType,ISColoring *);

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

 20: static PetscErrorCode DASetBlockFills_Private(PetscInt *dfill,PetscInt w,PetscInt **rfill)
 21: {
 23:   PetscInt       i,j,nz,*fill;

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

 28:   /* count number nonzeros */
 29:   nz = 0;
 30:   for (i=0; i<w; i++) {
 31:     for (j=0; j<w; j++) {
 32:       if (dfill[w*i+j]) nz++;
 33:     }
 34:   }
 35:   PetscMalloc((nz + w + 1)*sizeof(PetscInt),&fill);
 36:   /* construct modified CSR storage of nonzero structure */
 37:   nz = w + 1;
 38:   for (i=0; i<w; i++) {
 39:     fill[i] = nz;
 40:     for (j=0; j<w; j++) {
 41:       if (dfill[w*i+j]) {
 42:         fill[nz] = j;
 43:         nz++;
 44:       }
 45:     }
 46:   }
 47:   fill[w] = nz;
 48: 
 49:   *rfill = fill;
 50:   return(0);
 51: }

 55: /*@
 56:     DASetMatPreallocateOnly - When DAGetMatrix() is called the matrix will be properly
 57:        preallocated but the nonzero structure and zero values will not be set.

 59:     Collective on DA

 61:     Input Parameter:
 62: +   da - the distributed array
 63: -   only - PETSC_TRUE if only want preallocation


 66:     Level: developer

 68: .seealso DAGetMatrix(), DASetGetMatrix(), DASetBlockSize(), DASetBlockFills()

 70: @*/
 71: PetscErrorCode  DASetMatPreallocateOnly(DA da,PetscTruth only)
 72: {
 74:   da->prealloc_only = only;
 75:   return(0);
 76: }

 80: /*@
 81:     DASetBlockFills - Sets the fill pattern in each block for a multi-component problem
 82:     of the matrix returned by DAGetMatrix().

 84:     Collective on DA

 86:     Input Parameter:
 87: +   da - the distributed array
 88: .   dfill - the fill pattern in the diagonal block (may be PETSC_NULL, means use dense block)
 89: -   ofill - the fill pattern in the off-diagonal blocks


 92:     Level: developer

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

 97:            The format for dfill and ofill is a 2 dimensional dof by dof matrix with 1 entries
 98:        representing coupling and 0 entries for missing coupling. For example 
 99: $             dfill[9] = {1, 0, 0,
100: $                         1, 1, 0,
101: $                         0, 1, 1} 
102:        means that row 0 is coupled with only itself in the diagonal block, row 1 is coupled with 
103:        itself and row 0 (in the diagonal block) and row 2 is coupled with itself and row 1 (in the 
104:        diagonal block).

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

109:    Contributed by Glenn Hammond

111: .seealso DAGetMatrix(), DASetGetMatrix(), DASetMatPreallocateOnly()

113: @*/
114: PetscErrorCode  DASetBlockFills(DA da,PetscInt *dfill,PetscInt *ofill)
115: {

119:   DASetBlockFills_Private(dfill,da->w,&da->dfill);
120:   DASetBlockFills_Private(ofill,da->w,&da->ofill);
121:   return(0);
122: }


127: /*@
128:     DAGetColoring - Gets the coloring required for computing the Jacobian via
129:     finite differences on a function defined using a stencil on the DA.

131:     Collective on DA

133:     Input Parameter:
134: +   da - the distributed array
135: .   ctype - IS_COLORING_GLOBAL or IS_COLORING_GHOSTED
136: -   mtype - either MATAIJ or MATBAIJ

138:     Output Parameters:
139: .   coloring - matrix coloring for use in computing Jacobians (or PETSC_NULL if not needed)

141:     Level: advanced

143:     Notes: These compute the graph coloring of the graph of A^{T}A. The coloring used 
144:    for efficient (parallel or thread based) triangular solves etc is NOT
145:    available. 

147:         For BAIJ matrices this colors the graph for the blocks, not for the individual matrix elements;
148:     the same as MatGetColoring().

150: .seealso ISColoringView(), ISColoringGetIS(), MatFDColoringCreate(), ISColoringType, ISColoring

152: @*/
153: PetscErrorCode  DAGetColoring(DA da,ISColoringType ctype,const MatType mtype,ISColoring *coloring)
154: {
156:   PetscInt       dim,m,n,p,nc;
157:   DAPeriodicType wrap;
158:   MPI_Comm       comm;
159:   PetscMPIInt    size;
160:   PetscTruth     isBAIJ;

163:   /*
164:                                   m
165:           ------------------------------------------------------
166:          |                                                     |
167:          |                                                     |
168:          |               ----------------------                |
169:          |               |                    |                |
170:       n  |           yn  |                    |                |
171:          |               |                    |                |
172:          |               .---------------------                |
173:          |             (xs,ys)     xn                          |
174:          |            .                                        |
175:          |         (gxs,gys)                                   |
176:          |                                                     |
177:           -----------------------------------------------------
178:   */

180:   /*     
181:          nc - number of components per grid point 
182:          col - number of colors needed in one direction for single component problem
183:   
184:   */
185:   DAGetInfo(da,&dim,0,0,0,&m,&n,&p,&nc,0,&wrap,0);

187:   PetscObjectGetComm((PetscObject)da,&comm);
188:   MPI_Comm_size(comm,&size);
189:   if (ctype == IS_COLORING_GHOSTED){
190:     if (size == 1) {
191:       ctype = IS_COLORING_GLOBAL;
192:     } else if (dim > 1){
193:       if ((m==1 && DAXPeriodic(wrap)) || (n==1 && DAYPeriodic(wrap)) || (p==1 && DAZPeriodic(wrap))){
194:         SETERRQ(PETSC_ERR_SUP,"IS_COLORING_GHOSTED cannot be used for periodic boundary condition having both ends of the domain  on the same process");
195:       }
196:     }
197:   }

199:   /* Tell the DA it has 1 degree of freedom per grid point so that the coloring for BAIJ 
200:      matrices is for the blocks, not the individual matrix elements  */
201:   PetscStrcmp(mtype,MATBAIJ,&isBAIJ);
202:   if (!isBAIJ) {PetscStrcmp(mtype,MATMPIBAIJ,&isBAIJ);}
203:   if (!isBAIJ) {PetscStrcmp(mtype,MATSEQBAIJ,&isBAIJ);}
204:   if (isBAIJ) {
205:     da->w = 1;
206:     da->xs = da->xs/nc;
207:     da->xe = da->xe/nc;
208:     da->Xs = da->Xs/nc;
209:     da->Xe = da->Xe/nc;
210:   }

212:   /*
213:      We do not provide a getcoloring function in the DA operations because 
214:    the basic DA does not know about matrices. We think of DA as being more 
215:    more low-level then matrices.
216:   */
217:   if (dim == 1) {
218:     DAGetColoring1d_MPIAIJ(da,ctype,coloring);
219:   } else if (dim == 2) {
220:      DAGetColoring2d_MPIAIJ(da,ctype,coloring);
221:   } else if (dim == 3) {
222:      DAGetColoring3d_MPIAIJ(da,ctype,coloring);
223:   } else {
224:     SETERRQ1(PETSC_ERR_SUP,"Not done for %D dimension, send us mail petsc-maint@mcs.anl.gov for code",dim);
225:   }
226:   if (isBAIJ) {
227:     da->w = nc;
228:     da->xs = da->xs*nc;
229:     da->xe = da->xe*nc;
230:     da->Xs = da->Xs*nc;
231:     da->Xe = da->Xe*nc;
232:   }
233:   return(0);
234: }

236: /* ---------------------------------------------------------------------------------*/

240: PetscErrorCode DAGetColoring2d_MPIAIJ(DA da,ISColoringType ctype,ISColoring *coloring)
241: {
242:   PetscErrorCode         ierr;
243:   PetscInt               xs,ys,nx,ny,i,j,ii,gxs,gys,gnx,gny,m,n,M,N,dim,s,k,nc,col;
244:   PetscInt               ncolors;
245:   MPI_Comm               comm;
246:   DAPeriodicType         wrap;
247:   DAStencilType          st;
248:   ISColoringValue        *colors;

251:   /*     
252:          nc - number of components per grid point 
253:          col - number of colors needed in one direction for single component problem
254:   
255:   */
256:   DAGetInfo(da,&dim,&m,&n,0,&M,&N,0,&nc,&s,&wrap,&st);
257:   col    = 2*s + 1;
258:   DAGetCorners(da,&xs,&ys,0,&nx,&ny,0);
259:   DAGetGhostCorners(da,&gxs,&gys,0,&gnx,&gny,0);
260:   PetscObjectGetComm((PetscObject)da,&comm);

262:   /* special case as taught to us by Paul Hovland */
263:   if (st == DA_STENCIL_STAR && s == 1) {
264:     DAGetColoring2d_5pt_MPIAIJ(da,ctype,coloring);
265:   } else {

267:     if (DAXPeriodic(wrap) && (m % col)){
268:       SETERRQ2(PETSC_ERR_SUP,"For coloring efficiency ensure number of grid points in X (%d) is divisible\n\
269:                  by 2*stencil_width + 1 (%d)\n", m, col);
270:     }
271:     if (DAYPeriodic(wrap) && (n % col)){
272:       SETERRQ2(PETSC_ERR_SUP,"For coloring efficiency ensure number of grid points in Y (%d) is divisible\n\
273:                  by 2*stencil_width + 1 (%d)\n", n, col);
274:     }
275:     if (ctype == IS_COLORING_GLOBAL) {
276:       if (!da->localcoloring) {
277:         PetscMalloc(nc*nx*ny*sizeof(ISColoringValue),&colors);
278:         ii = 0;
279:         for (j=ys; j<ys+ny; j++) {
280:           for (i=xs; i<xs+nx; i++) {
281:             for (k=0; k<nc; k++) {
282:               colors[ii++] = k + nc*((i % col) + col*(j % col));
283:             }
284:           }
285:         }
286:         ncolors = nc + nc*(col-1 + col*(col-1));
287:         ISColoringCreate(comm,ncolors,nc*nx*ny,colors,&da->localcoloring);
288:       }
289:       *coloring = da->localcoloring;
290:     } else if (ctype == IS_COLORING_GHOSTED) {
291:       if (!da->ghostedcoloring) {
292:         PetscMalloc(nc*gnx*gny*sizeof(ISColoringValue),&colors);
293:         ii = 0;
294:         for (j=gys; j<gys+gny; j++) {
295:           for (i=gxs; i<gxs+gnx; i++) {
296:             for (k=0; k<nc; k++) {
297:               /* the complicated stuff is to handle periodic boundaries */
298:               colors[ii++] = k + nc*((SetInRange(i,m) % col) + col*(SetInRange(j,n) % col));
299:             }
300:           }
301:         }
302:         ncolors = nc + nc*(col - 1 + col*(col-1));
303:         ISColoringCreate(comm,ncolors,nc*gnx*gny,colors,&da->ghostedcoloring);
304:         /* PetscIntView(ncolors,(PetscInt *)colors,0); */

306:         ISColoringSetType(da->ghostedcoloring,IS_COLORING_GHOSTED);
307:       }
308:       *coloring = da->ghostedcoloring;
309:     } else SETERRQ1(PETSC_ERR_ARG_WRONG,"Unknown ISColoringType %d",(int)ctype);
310:   }
311:   ISColoringReference(*coloring);
312:   return(0);
313: }

315: /* ---------------------------------------------------------------------------------*/

319: PetscErrorCode DAGetColoring3d_MPIAIJ(DA da,ISColoringType ctype,ISColoring *coloring)
320: {
321:   PetscErrorCode  ierr;
322:   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;
323:   PetscInt        ncolors;
324:   MPI_Comm        comm;
325:   DAPeriodicType  wrap;
326:   DAStencilType   st;
327:   ISColoringValue *colors;

330:   /*     
331:          nc - number of components per grid point 
332:          col - number of colors needed in one direction for single component problem
333:   
334:   */
335:   DAGetInfo(da,&dim,&m,&n,&p,&M,&N,&P,&nc,&s,&wrap,&st);
336:   col    = 2*s + 1;
337:   if (DAXPeriodic(wrap) && (m % col)){
338:     SETERRQ(PETSC_ERR_SUP,"For coloring efficiency ensure number of grid points in X is divisible\n\
339:                  by 2*stencil_width + 1\n");
340:   }
341:   if (DAYPeriodic(wrap) && (n % col)){
342:     SETERRQ(PETSC_ERR_SUP,"For coloring efficiency ensure number of grid points in Y is divisible\n\
343:                  by 2*stencil_width + 1\n");
344:   }
345:   if (DAZPeriodic(wrap) && (p % col)){
346:     SETERRQ(PETSC_ERR_SUP,"For coloring efficiency ensure number of grid points in Z is divisible\n\
347:                  by 2*stencil_width + 1\n");
348:   }

350:   DAGetCorners(da,&xs,&ys,&zs,&nx,&ny,&nz);
351:   DAGetGhostCorners(da,&gxs,&gys,&gzs,&gnx,&gny,&gnz);
352:   PetscObjectGetComm((PetscObject)da,&comm);

354:   /* create the coloring */
355:   if (ctype == IS_COLORING_GLOBAL) {
356:     if (!da->localcoloring) {
357:       PetscMalloc(nc*nx*ny*nz*sizeof(ISColoringValue),&colors);
358:       ii = 0;
359:       for (k=zs; k<zs+nz; k++) {
360:         for (j=ys; j<ys+ny; j++) {
361:           for (i=xs; i<xs+nx; i++) {
362:             for (l=0; l<nc; l++) {
363:               colors[ii++] = l + nc*((i % col) + col*(j % col) + col*col*(k % col));
364:             }
365:           }
366:         }
367:       }
368:       ncolors = nc + nc*(col-1 + col*(col-1)+ col*col*(col-1));
369:       ISColoringCreate(comm,ncolors,nc*nx*ny*nz,colors,&da->localcoloring);
370:     }
371:     *coloring = da->localcoloring;
372:   } else if (ctype == IS_COLORING_GHOSTED) {
373:     if (!da->ghostedcoloring) {
374:       PetscMalloc(nc*gnx*gny*gnz*sizeof(ISColoringValue),&colors);
375:       ii = 0;
376:       for (k=gzs; k<gzs+gnz; k++) {
377:         for (j=gys; j<gys+gny; j++) {
378:           for (i=gxs; i<gxs+gnx; i++) {
379:             for (l=0; l<nc; l++) {
380:               /* the complicated stuff is to handle periodic boundaries */
381:               colors[ii++] = l + nc*((SetInRange(i,m) % col) + col*(SetInRange(j,n) % col) + col*col*(SetInRange(k,p) % col));
382:             }
383:           }
384:         }
385:       }
386:       ncolors = nc + nc*(col-1 + col*(col-1)+ col*col*(col-1));
387:       ISColoringCreate(comm,ncolors,nc*gnx*gny*gnz,colors,&da->ghostedcoloring);
388:       ISColoringSetType(da->ghostedcoloring,IS_COLORING_GHOSTED);
389:     }
390:     *coloring = da->ghostedcoloring;
391:   } else SETERRQ1(PETSC_ERR_ARG_WRONG,"Unknown ISColoringType %d",(int)ctype);
392:   ISColoringReference(*coloring);
393:   return(0);
394: }

396: /* ---------------------------------------------------------------------------------*/

400: PetscErrorCode DAGetColoring1d_MPIAIJ(DA da,ISColoringType ctype,ISColoring *coloring)
401: {
402:   PetscErrorCode  ierr;
403:   PetscInt        xs,nx,i,i1,gxs,gnx,l,m,M,dim,s,nc,col;
404:   PetscInt        ncolors;
405:   MPI_Comm        comm;
406:   DAPeriodicType  wrap;
407:   ISColoringValue *colors;

410:   /*     
411:          nc - number of components per grid point 
412:          col - number of colors needed in one direction for single component problem
413:   
414:   */
415:   DAGetInfo(da,&dim,&m,0,0,&M,0,0,&nc,&s,&wrap,0);
416:   col    = 2*s + 1;

418:   if (DAXPeriodic(wrap) && (m % col)) {
419:     SETERRQ(PETSC_ERR_SUP,"For coloring efficiency ensure number of grid points is divisible\n\
420:                  by 2*stencil_width + 1\n");
421:   }

423:   DAGetCorners(da,&xs,0,0,&nx,0,0);
424:   DAGetGhostCorners(da,&gxs,0,0,&gnx,0,0);
425:   PetscObjectGetComm((PetscObject)da,&comm);

427:   /* create the coloring */
428:   if (ctype == IS_COLORING_GLOBAL) {
429:     if (!da->localcoloring) {
430:       PetscMalloc(nc*nx*sizeof(ISColoringValue),&colors);
431:       i1 = 0;
432:       for (i=xs; i<xs+nx; i++) {
433:         for (l=0; l<nc; l++) {
434:           colors[i1++] = l + nc*(i % col);
435:         }
436:       }
437:       ncolors = nc + nc*(col-1);
438:       ISColoringCreate(comm,ncolors,nc*nx,colors,&da->localcoloring);
439:     }
440:     *coloring = da->localcoloring;
441:   } else if (ctype == IS_COLORING_GHOSTED) {
442:     if (!da->ghostedcoloring) {
443:       PetscMalloc(nc*gnx*sizeof(ISColoringValue),&colors);
444:       i1 = 0;
445:       for (i=gxs; i<gxs+gnx; i++) {
446:         for (l=0; l<nc; l++) {
447:           /* the complicated stuff is to handle periodic boundaries */
448:           colors[i1++] = l + nc*(SetInRange(i,m) % col);
449:         }
450:       }
451:       ncolors = nc + nc*(col-1);
452:       ISColoringCreate(comm,ncolors,nc*gnx,colors,&da->ghostedcoloring);
453:       ISColoringSetType(da->ghostedcoloring,IS_COLORING_GHOSTED);
454:     }
455:     *coloring = da->ghostedcoloring;
456:   } else SETERRQ1(PETSC_ERR_ARG_WRONG,"Unknown ISColoringType %d",(int)ctype);
457:   ISColoringReference(*coloring);
458:   return(0);
459: }

463: PetscErrorCode DAGetColoring2d_5pt_MPIAIJ(DA da,ISColoringType ctype,ISColoring *coloring)
464: {
465:   PetscErrorCode  ierr;
466:   PetscInt        xs,ys,nx,ny,i,j,ii,gxs,gys,gnx,gny,m,n,dim,s,k,nc;
467:   PetscInt        ncolors;
468:   MPI_Comm        comm;
469:   DAPeriodicType  wrap;
470:   ISColoringValue *colors;

473:   /*     
474:          nc - number of components per grid point 
475:          col - number of colors needed in one direction for single component problem
476:   
477:   */
478:   DAGetInfo(da,&dim,&m,&n,0,0,0,0,&nc,&s,&wrap,0);
479:   DAGetCorners(da,&xs,&ys,0,&nx,&ny,0);
480:   DAGetGhostCorners(da,&gxs,&gys,0,&gnx,&gny,0);
481:   PetscObjectGetComm((PetscObject)da,&comm);

483:   if (DAXPeriodic(wrap) && (m % 5)){
484:     SETERRQ(PETSC_ERR_SUP,"For coloring efficiency ensure number of grid points in X is divisible\n\
485:                  by 5\n");
486:   }
487:   if (DAYPeriodic(wrap) && (n % 5)){
488:     SETERRQ(PETSC_ERR_SUP,"For coloring efficiency ensure number of grid points in Y is divisible\n\
489:                  by 5\n");
490:   }

492:   /* create the coloring */
493:   if (ctype == IS_COLORING_GLOBAL) {
494:     if (!da->localcoloring) {
495:       PetscMalloc(nc*nx*ny*sizeof(ISColoringValue),&colors);
496:       ii = 0;
497:       for (j=ys; j<ys+ny; j++) {
498:         for (i=xs; i<xs+nx; i++) {
499:           for (k=0; k<nc; k++) {
500:             colors[ii++] = k + nc*((3*j+i) % 5);
501:           }
502:         }
503:       }
504:       ncolors = 5*nc;
505:       ISColoringCreate(comm,ncolors,nc*nx*ny,colors,&da->localcoloring);
506:     }
507:     *coloring = da->localcoloring;
508:   } else if (ctype == IS_COLORING_GHOSTED) {
509:     if (!da->ghostedcoloring) {
510:       PetscMalloc(nc*gnx*gny*sizeof(ISColoringValue),&colors);
511:       ii = 0;
512:       for (j=gys; j<gys+gny; j++) {
513:         for (i=gxs; i<gxs+gnx; i++) {
514:           for (k=0; k<nc; k++) {
515:             colors[ii++] = k + nc*((3*SetInRange(j,n) + SetInRange(i,m)) % 5);
516:           }
517:         }
518:       }
519:       ncolors = 5*nc;
520:       ISColoringCreate(comm,ncolors,nc*gnx*gny,colors,&da->ghostedcoloring);
521:       ISColoringSetType(da->ghostedcoloring,IS_COLORING_GHOSTED);
522:     }
523:     *coloring = da->ghostedcoloring;
524:   } else SETERRQ1(PETSC_ERR_ARG_WRONG,"Unknown ISColoringType %d",(int)ctype);
525:   return(0);
526: }

528: /* =========================================================================== */
529: EXTERN PetscErrorCode DAGetMatrix1d_MPIAIJ(DA,Mat);
530: EXTERN PetscErrorCode DAGetMatrix2d_MPIAIJ(DA,Mat);
531: EXTERN PetscErrorCode DAGetMatrix2d_MPIAIJ_Fill(DA,Mat);
532: EXTERN PetscErrorCode DAGetMatrix3d_MPIAIJ(DA,Mat);
533: EXTERN PetscErrorCode DAGetMatrix3d_MPIAIJ_Fill(DA,Mat);
534: EXTERN PetscErrorCode DAGetMatrix2d_MPIBAIJ(DA,Mat);
535: EXTERN PetscErrorCode DAGetMatrix3d_MPIBAIJ(DA,Mat);
536: EXTERN PetscErrorCode DAGetMatrix2d_MPISBAIJ(DA,Mat);
537: EXTERN PetscErrorCode DAGetMatrix3d_MPISBAIJ(DA,Mat);

541: /*@
542:    MatSetDA - Sets the DA that is to be used by the HYPRE_StructMatrix PETSc matrix

544:    Collective on Mat

546:    Input Parameters:
547: +  mat - the matrix
548: -  da - the da

550:    Level: intermediate

552: @*/
553: PetscErrorCode  MatSetDA(Mat mat,DA da)
554: {
555:   PetscErrorCode ierr,(*f)(Mat,DA);

560:   PetscObjectQueryFunction((PetscObject)mat,"MatSetDA_C",(void (**)(void))&f);
561:   if (f) {
562:     (*f)(mat,da);
563:   }
564:   return(0);
565: }


570: /*@C
571:     DAGetMatrix - Creates a matrix with the correct parallel layout and nonzero structure required for 
572:       computing the Jacobian on a function defined using the stencil set in the DA.

574:     Collective on DA

576:     Input Parameter:
577: +   da - the distributed array
578: -   mtype - Supported types are MATSEQAIJ, MATMPIAIJ, MATSEQBAIJ, MATMPIBAIJ, MATSEQSBAIJ, MATMPISBAIJ,
579:             or any type which inherits from one of these (such as MATAIJ, MATBAIJ, MATSBAIJ)

581:     Output Parameters:
582: .   J  - matrix with the correct nonzero structure
583:         (obviously without the correct Jacobian values)

585:     Level: advanced

587:     Notes: This properly preallocates the number of nonzeros in the sparse matrix so you 
588:        do not need to do it yourself. 

590:        By default it also sets the nonzero structure and puts in the zero entries. To prevent setting 
591:        the nonzero pattern call DASetMatPreallocateOnly()

593: .seealso ISColoringView(), ISColoringGetIS(), MatFDColoringCreate(), DASetBlockFills(), DASetMatPreallocateOnly()

595: @*/
596: PetscErrorCode  DAGetMatrix(DA da, const MatType mtype,Mat *J)
597: {
599:   PetscInt       dim,dof,nx,ny,nz,dims[3],starts[3];
600:   Mat            A;
601:   MPI_Comm       comm;
602:   const MatType  Atype;
603:   void           (*aij)(void)=PETSC_NULL,(*baij)(void)=PETSC_NULL,(*sbaij)(void)=PETSC_NULL;
604:   MatType        ttype[256];
605:   PetscTruth     flg;

608: #ifndef PETSC_USE_DYNAMIC_LIBRARIES
609:   MatInitializePackage(PETSC_NULL);
610: #endif
611:   PetscStrcpy((char*)ttype,mtype);
612:   PetscOptionsBegin(((PetscObject)da)->comm,((PetscObject)da)->prefix,"DA options","Mat");
613:   PetscOptionsList("-da_mat_type","Matrix type","MatSetType",MatList,mtype,(char*)ttype,256,&flg);
614:   PetscOptionsEnd();

616:   /*
617:                                   m
618:           ------------------------------------------------------
619:          |                                                     |
620:          |                                                     |
621:          |               ----------------------                |
622:          |               |                    |                |
623:       n  |           ny  |                    |                |
624:          |               |                    |                |
625:          |               .---------------------                |
626:          |             (xs,ys)     nx                          |
627:          |            .                                        |
628:          |         (gxs,gys)                                   |
629:          |                                                     |
630:           -----------------------------------------------------
631:   */

633:   /*     
634:          nc - number of components per grid point 
635:          col - number of colors needed in one direction for single component problem
636:   
637:   */
638:   DAGetInfo(da,&dim,0,0,0,0,0,0,&dof,0,0,0);
639:   DAGetCorners(da,0,0,0,&nx,&ny,&nz);
640:   PetscObjectGetComm((PetscObject)da,&comm);
641:   MatCreate(comm,&A);
642:   MatSetSizes(A,dof*nx*ny*nz,dof*nx*ny*nz,PETSC_DECIDE,PETSC_DECIDE);
643:   MatSetType(A,(const MatType)ttype);
644:   MatSetDA(A,da);
645:   MatSetFromOptions(A);
646:   MatGetType(A,&Atype);
647:   /*
648:      We do not provide a getmatrix function in the DA operations because 
649:    the basic DA does not know about matrices. We think of DA as being more 
650:    more low-level than matrices. This is kind of cheating but, cause sometimes 
651:    we think of DA has higher level than matrices.

653:      We could switch based on Atype (or mtype), but we do not since the
654:    specialized setting routines depend only the particular preallocation
655:    details of the matrix, not the type itself.
656:   */
657:   PetscObjectQueryFunction((PetscObject)A,"MatMPIAIJSetPreallocation_C",&aij);
658:   if (!aij) {
659:     PetscObjectQueryFunction((PetscObject)A,"MatSeqAIJSetPreallocation_C",&aij);
660:   }
661:   if (!aij) {
662:     PetscObjectQueryFunction((PetscObject)A,"MatMPIBAIJSetPreallocation_C",&baij);
663:     if (!baij) {
664:       PetscObjectQueryFunction((PetscObject)A,"MatSeqBAIJSetPreallocation_C",&baij);
665:     }
666:     if (!baij){
667:       PetscObjectQueryFunction((PetscObject)A,"MatMPISBAIJSetPreallocation_C",&sbaij);
668:       if (!sbaij) {
669:         PetscObjectQueryFunction((PetscObject)A,"MatSeqSBAIJSetPreallocation_C",&sbaij);
670:       }
671:       if (!sbaij) {
672:         PetscTruth flg, flg2;
673:         PetscTypeCompare((PetscObject)A,MATHYPRESTRUCT,&flg);
674:         PetscTypeCompare((PetscObject)A,MATHYPRESSTRUCT,&flg2);
675:         if (!flg && !flg2) SETERRQ2(PETSC_ERR_SUP,"Not implemented for the matrix type: %s in %D dimension!\n" \
676:                            "Send mail to petsc-maint@mcs.anl.gov for code",Atype,dim);
677:       }
678:     }
679:   }
680:   if (aij) {
681:     if (dim == 1) {
682:       DAGetMatrix1d_MPIAIJ(da,A);
683:     } else if (dim == 2) {
684:       if (da->ofill) {
685:         DAGetMatrix2d_MPIAIJ_Fill(da,A);
686:       } else {
687:         DAGetMatrix2d_MPIAIJ(da,A);
688:       }
689:     } else if (dim == 3) {
690:       if (da->ofill) {
691:         DAGetMatrix3d_MPIAIJ_Fill(da,A);
692:       } else {
693:         DAGetMatrix3d_MPIAIJ(da,A);
694:       }
695:     }
696:   } else if (baij) {
697:     if (dim == 2) {
698:       DAGetMatrix2d_MPIBAIJ(da,A);
699:     } else if (dim == 3) {
700:       DAGetMatrix3d_MPIBAIJ(da,A);
701:     } else {
702:       SETERRQ2(PETSC_ERR_SUP,"Not implemented for %D dimension and Matrix Type: %s in %D dimension!\n" \
703:                "Send mail to petsc-maint@mcs.anl.gov for code",Atype,dim);
704:     }
705:   } else if (sbaij) {
706:     if (dim == 2) {
707:       DAGetMatrix2d_MPISBAIJ(da,A);
708:     } else if (dim == 3) {
709:       DAGetMatrix3d_MPISBAIJ(da,A);
710:     } else {
711:       SETERRQ2(PETSC_ERR_SUP,"Not implemented for %D dimension and Matrix Type: %s in %D dimension!\n" \
712:                "Send mail to petsc-maint@mcs.anl.gov for code",Atype,dim);
713:     }
714:   }
715:   DAGetGhostCorners(da,&starts[0],&starts[1],&starts[2],&dims[0],&dims[1],&dims[2]);
716:   MatSetStencil(A,dim,dims,starts,dof);
717:   *J = A;
718:   return(0);
719: }

721: /* ---------------------------------------------------------------------------------*/
724: PetscErrorCode DAGetMatrix2d_MPIAIJ(DA da,Mat J)
725: {
726:   PetscErrorCode         ierr;
727:   PetscInt               xs,ys,nx,ny,i,j,slot,gxs,gys,gnx,gny,m,n,dim,s,*cols = PETSC_NULL,k,nc,*rows = PETSC_NULL,col,cnt,l,p;
728:   PetscInt               lstart,lend,pstart,pend,*dnz,*onz;
729:   MPI_Comm               comm;
730:   PetscScalar            *values;
731:   DAPeriodicType         wrap;
732:   ISLocalToGlobalMapping ltog,ltogb;
733:   DAStencilType          st;

736:   /*     
737:          nc - number of components per grid point 
738:          col - number of colors needed in one direction for single component problem
739:   
740:   */
741:   DAGetInfo(da,&dim,&m,&n,0,0,0,0,&nc,&s,&wrap,&st);
742:   col = 2*s + 1;
743:   DAGetCorners(da,&xs,&ys,0,&nx,&ny,0);
744:   DAGetGhostCorners(da,&gxs,&gys,0,&gnx,&gny,0);
745:   PetscObjectGetComm((PetscObject)da,&comm);

747:   PetscMalloc2(nc,PetscInt,&rows,col*col*nc*nc,PetscInt,&cols);
748:   DAGetISLocalToGlobalMapping(da,&ltog);
749:   DAGetISLocalToGlobalMappingBlck(da,&ltogb);
750: 
751:   /* determine the matrix preallocation information */
752:   MatPreallocateInitialize(comm,nc*nx*ny,nc*nx*ny,dnz,onz);
753:   for (i=xs; i<xs+nx; i++) {

755:     pstart = DAXPeriodic(wrap) ? -s : (PetscMax(-s,-i));
756:     pend   = DAXPeriodic(wrap) ?  s : (PetscMin(s,m-i-1));

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

761:       lstart = DAYPeriodic(wrap) ? -s : (PetscMax(-s,-j));
762:       lend   = DAYPeriodic(wrap) ?  s : (PetscMin(s,n-j-1));

764:       cnt  = 0;
765:       for (k=0; k<nc; k++) {
766:         for (l=lstart; l<lend+1; l++) {
767:           for (p=pstart; p<pend+1; p++) {
768:             if ((st == DA_STENCIL_BOX) || (!l || !p)) {  /* entries on star have either l = 0 or p = 0 */
769:               cols[cnt++]  = k + nc*(slot + gnx*l + p);
770:             }
771:           }
772:         }
773:         rows[k] = k + nc*(slot);
774:       }
775:       MatPreallocateSetLocal(ltog,nc,rows,cnt,cols,dnz,onz);
776:     }
777:   }
778:   MatSeqAIJSetPreallocation(J,0,dnz);
779:   MatMPIAIJSetPreallocation(J,0,dnz,0,onz);
780:   MatSetBlockSize(J,nc);
781:   MatPreallocateFinalize(dnz,onz);

783:   MatSetLocalToGlobalMapping(J,ltog);
784:   MatSetLocalToGlobalMappingBlock(J,ltogb);

786:   /*
787:     For each node in the grid: we get the neighbors in the local (on processor ordering
788:     that includes the ghost points) then MatSetValuesLocal() maps those indices to the global
789:     PETSc ordering.
790:   */
791:   if (!da->prealloc_only) {
792:     PetscMalloc(col*col*nc*nc*sizeof(PetscScalar),&values);
793:     PetscMemzero(values,col*col*nc*nc*sizeof(PetscScalar));
794:     for (i=xs; i<xs+nx; i++) {
795: 
796:       pstart = DAXPeriodic(wrap) ? -s : (PetscMax(-s,-i));
797:       pend   = DAXPeriodic(wrap) ?  s : (PetscMin(s,m-i-1));
798: 
799:       for (j=ys; j<ys+ny; j++) {
800:         slot = i - gxs + gnx*(j - gys);
801: 
802:         lstart = DAYPeriodic(wrap) ? -s : (PetscMax(-s,-j));
803:         lend   = DAYPeriodic(wrap) ?  s : (PetscMin(s,n-j-1));

805:         cnt  = 0;
806:         for (k=0; k<nc; k++) {
807:           for (l=lstart; l<lend+1; l++) {
808:             for (p=pstart; p<pend+1; p++) {
809:               if ((st == DA_STENCIL_BOX) || (!l || !p)) {  /* entries on star have either l = 0 or p = 0 */
810:                 cols[cnt++]  = k + nc*(slot + gnx*l + p);
811:               }
812:             }
813:           }
814:           rows[k]      = k + nc*(slot);
815:         }
816:         MatSetValuesLocal(J,nc,rows,cnt,cols,values,INSERT_VALUES);
817:       }
818:     }
819:     PetscFree(values);
820:     MatAssemblyBegin(J,MAT_FINAL_ASSEMBLY);
821:     MatAssemblyEnd(J,MAT_FINAL_ASSEMBLY);
822:   }
823:   PetscFree2(rows,cols);
824:   return(0);
825: }

829: PetscErrorCode DAGetMatrix2d_MPIAIJ_Fill(DA da,Mat J)
830: {
831:   PetscErrorCode         ierr;
832:   PetscInt               xs,ys,nx,ny,i,j,slot,gxs,gys,gnx,gny;
833:   PetscInt               m,n,dim,s,*cols,k,nc,row,col,cnt,l,p;
834:   PetscInt               lstart,lend,pstart,pend,*dnz,*onz;
835:   PetscInt               ifill_col,*ofill = da->ofill, *dfill = da->dfill;
836:   MPI_Comm               comm;
837:   PetscScalar            *values;
838:   DAPeriodicType         wrap;
839:   ISLocalToGlobalMapping ltog,ltogb;
840:   DAStencilType          st;

843:   /*     
844:          nc - number of components per grid point 
845:          col - number of colors needed in one direction for single component problem
846:   
847:   */
848:   DAGetInfo(da,&dim,&m,&n,0,0,0,0,&nc,&s,&wrap,&st);
849:   col = 2*s + 1;
850:   DAGetCorners(da,&xs,&ys,0,&nx,&ny,0);
851:   DAGetGhostCorners(da,&gxs,&gys,0,&gnx,&gny,0);
852:   PetscObjectGetComm((PetscObject)da,&comm);

854:   PetscMalloc(col*col*nc*nc*sizeof(PetscInt),&cols);
855:   DAGetISLocalToGlobalMapping(da,&ltog);
856:   DAGetISLocalToGlobalMappingBlck(da,&ltogb);
857: 
858:   /* determine the matrix preallocation information */
859:   MatPreallocateInitialize(comm,nc*nx*ny,nc*nx*ny,dnz,onz);
860:   for (i=xs; i<xs+nx; i++) {

862:     pstart = DAXPeriodic(wrap) ? -s : (PetscMax(-s,-i));
863:     pend   = DAXPeriodic(wrap) ?  s : (PetscMin(s,m-i-1));

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

868:       lstart = DAYPeriodic(wrap) ? -s : (PetscMax(-s,-j));
869:       lend   = DAYPeriodic(wrap) ?  s : (PetscMin(s,n-j-1));

871:       for (k=0; k<nc; k++) {
872:         cnt  = 0;
873:         for (l=lstart; l<lend+1; l++) {
874:           for (p=pstart; p<pend+1; p++) {
875:             if (l || p) {
876:               if ((st == DA_STENCIL_BOX) || (!l || !p)) {  /* entries on star */
877:                 for (ifill_col=ofill[k]; ifill_col<ofill[k+1]; ifill_col++)
878:                   cols[cnt++]  = ofill[ifill_col] + nc*(slot + gnx*l + p);
879:               }
880:             } else {
881:               if (dfill) {
882:                 for (ifill_col=dfill[k]; ifill_col<dfill[k+1]; ifill_col++)
883:                   cols[cnt++]  = dfill[ifill_col] + nc*(slot + gnx*l + p);
884:               } else {
885:                 for (ifill_col=0; ifill_col<nc; ifill_col++)
886:                   cols[cnt++]  = ifill_col + nc*(slot + gnx*l + p);
887:               }
888:             }
889:           }
890:         }
891:         row = k + nc*(slot);
892:         MatPreallocateSetLocal(ltog,1,&row,cnt,cols,dnz,onz);
893:       }
894:     }
895:   }
896:   MatSeqAIJSetPreallocation(J,0,dnz);
897:   MatMPIAIJSetPreallocation(J,0,dnz,0,onz);
898:   MatPreallocateFinalize(dnz,onz);
899:   MatSetLocalToGlobalMapping(J,ltog);
900:   MatSetLocalToGlobalMappingBlock(J,ltogb);

902:   /*
903:     For each node in the grid: we get the neighbors in the local (on processor ordering
904:     that includes the ghost points) then MatSetValuesLocal() maps those indices to the global
905:     PETSc ordering.
906:   */
907:   if (!da->prealloc_only) {
908:     PetscMalloc(col*col*nc*nc*sizeof(PetscScalar),&values);
909:     PetscMemzero(values,col*col*nc*nc*sizeof(PetscScalar));
910:     for (i=xs; i<xs+nx; i++) {
911: 
912:       pstart = DAXPeriodic(wrap) ? -s : (PetscMax(-s,-i));
913:       pend   = DAXPeriodic(wrap) ?  s : (PetscMin(s,m-i-1));
914: 
915:       for (j=ys; j<ys+ny; j++) {
916:         slot = i - gxs + gnx*(j - gys);
917: 
918:         lstart = DAYPeriodic(wrap) ? -s : (PetscMax(-s,-j));
919:         lend   = DAYPeriodic(wrap) ?  s : (PetscMin(s,n-j-1));

921:         for (k=0; k<nc; k++) {
922:           cnt  = 0;
923:           for (l=lstart; l<lend+1; l++) {
924:             for (p=pstart; p<pend+1; p++) {
925:               if (l || p) {
926:                 if ((st == DA_STENCIL_BOX) || (!l || !p)) {  /* entries on star */
927:                   for (ifill_col=ofill[k]; ifill_col<ofill[k+1]; ifill_col++)
928:                     cols[cnt++]  = ofill[ifill_col] + nc*(slot + gnx*l + p);
929:                 }
930:               } else {
931:                 if (dfill) {
932:                   for (ifill_col=dfill[k]; ifill_col<dfill[k+1]; ifill_col++)
933:                     cols[cnt++]  = dfill[ifill_col] + nc*(slot + gnx*l + p);
934:                 } else {
935:                   for (ifill_col=0; ifill_col<nc; ifill_col++)
936:                     cols[cnt++]  = ifill_col + nc*(slot + gnx*l + p);
937:                 }
938:               }
939:             }
940:           }
941:           row  = k + nc*(slot);
942:           MatSetValuesLocal(J,1,&row,cnt,cols,values,INSERT_VALUES);
943:         }
944:       }
945:     }
946:     PetscFree(values);
947:     MatAssemblyBegin(J,MAT_FINAL_ASSEMBLY);
948:     MatAssemblyEnd(J,MAT_FINAL_ASSEMBLY);
949:   }
950:   PetscFree(cols);
951:   return(0);
952: }

954: /* ---------------------------------------------------------------------------------*/

958: PetscErrorCode DAGetMatrix3d_MPIAIJ(DA da,Mat J)
959: {
960:   PetscErrorCode         ierr;
961:   PetscInt               xs,ys,nx,ny,i,j,slot,gxs,gys,gnx,gny;
962:   PetscInt               m,n,dim,s,*cols = PETSC_NULL,k,nc,*rows = PETSC_NULL,col,cnt,l,p,*dnz = PETSC_NULL,*onz = PETSC_NULL;
963:   PetscInt               istart,iend,jstart,jend,kstart,kend,zs,nz,gzs,gnz,ii,jj,kk;
964:   MPI_Comm               comm;
965:   PetscScalar            *values;
966:   DAPeriodicType         wrap;
967:   ISLocalToGlobalMapping ltog,ltogb;
968:   DAStencilType          st;

971:   /*     
972:          nc - number of components per grid point 
973:          col - number of colors needed in one direction for single component problem
974:   
975:   */
976:   DAGetInfo(da,&dim,&m,&n,&p,0,0,0,&nc,&s,&wrap,&st);
977:   col    = 2*s + 1;

979:   DAGetCorners(da,&xs,&ys,&zs,&nx,&ny,&nz);
980:   DAGetGhostCorners(da,&gxs,&gys,&gzs,&gnx,&gny,&gnz);
981:   PetscObjectGetComm((PetscObject)da,&comm);

983:   PetscMalloc2(nc,PetscInt,&rows,col*col*col*nc*nc,PetscInt,&cols);
984:   DAGetISLocalToGlobalMapping(da,&ltog);
985:   DAGetISLocalToGlobalMappingBlck(da,&ltogb);

987:   /* determine the matrix preallocation information */
988:   MatPreallocateInitialize(comm,nc*nx*ny*nz,nc*nx*ny*nz,dnz,onz);
989:   for (i=xs; i<xs+nx; i++) {
990:     istart = DAXPeriodic(wrap) ? -s : (PetscMax(-s,-i));
991:     iend   = DAXPeriodic(wrap) ?  s : (PetscMin(s,m-i-1));
992:     for (j=ys; j<ys+ny; j++) {
993:       jstart = DAYPeriodic(wrap) ? -s : (PetscMax(-s,-j));
994:       jend   = DAYPeriodic(wrap) ?  s : (PetscMin(s,n-j-1));
995:       for (k=zs; k<zs+nz; k++) {
996:         kstart = DAZPeriodic(wrap) ? -s : (PetscMax(-s,-k));
997:         kend   = DAZPeriodic(wrap) ?  s : (PetscMin(s,p-k-1));
998: 
999:         slot = i - gxs + gnx*(j - gys) + gnx*gny*(k - gzs);
1000: 
1001:         cnt  = 0;
1002:         for (l=0; l<nc; l++) {
1003:           for (ii=istart; ii<iend+1; ii++) {
1004:             for (jj=jstart; jj<jend+1; jj++) {
1005:               for (kk=kstart; kk<kend+1; kk++) {
1006:                 if ((st == DA_STENCIL_BOX) || ((!ii && !jj) || (!jj && !kk) || (!ii && !kk))) {/* entries on star*/
1007:                   cols[cnt++]  = l + nc*(slot + ii + gnx*jj + gnx*gny*kk);
1008:                 }
1009:               }
1010:             }
1011:           }
1012:           rows[l] = l + nc*(slot);
1013:         }
1014:         MatPreallocateSetLocal(ltog,nc,rows,cnt,cols,dnz,onz);
1015:       }
1016:     }
1017:   }
1018:   MatSeqAIJSetPreallocation(J,0,dnz);
1019:   MatMPIAIJSetPreallocation(J,0,dnz,0,onz);
1020:   MatPreallocateFinalize(dnz,onz);
1021:   MatSetBlockSize(J,nc);CHKERRQ(ierr)
1022:   MatSetLocalToGlobalMapping(J,ltog);
1023:   MatSetLocalToGlobalMappingBlock(J,ltogb);

1025:   /*
1026:     For each node in the grid: we get the neighbors in the local (on processor ordering
1027:     that includes the ghost points) then MatSetValuesLocal() maps those indices to the global
1028:     PETSc ordering.
1029:   */
1030:   if (!da->prealloc_only) {
1031:     PetscMalloc(col*col*col*nc*nc*nc*sizeof(PetscScalar),&values);
1032:     PetscMemzero(values,col*col*col*nc*nc*nc*sizeof(PetscScalar));
1033:     for (i=xs; i<xs+nx; i++) {
1034:       istart = DAXPeriodic(wrap) ? -s : (PetscMax(-s,-i));
1035:       iend   = DAXPeriodic(wrap) ?  s : (PetscMin(s,m-i-1));
1036:       for (j=ys; j<ys+ny; j++) {
1037:         jstart = DAYPeriodic(wrap) ? -s : (PetscMax(-s,-j));
1038:         jend   = DAYPeriodic(wrap) ?  s : (PetscMin(s,n-j-1));
1039:         for (k=zs; k<zs+nz; k++) {
1040:           kstart = DAZPeriodic(wrap) ? -s : (PetscMax(-s,-k));
1041:           kend   = DAZPeriodic(wrap) ?  s : (PetscMin(s,p-k-1));
1042: 
1043:           slot = i - gxs + gnx*(j - gys) + gnx*gny*(k - gzs);
1044: 
1045:           cnt  = 0;
1046:           for (l=0; l<nc; l++) {
1047:             for (ii=istart; ii<iend+1; ii++) {
1048:               for (jj=jstart; jj<jend+1; jj++) {
1049:                 for (kk=kstart; kk<kend+1; kk++) {
1050:                   if ((st == DA_STENCIL_BOX) || ((!ii && !jj) || (!jj && !kk) || (!ii && !kk))) {/* entries on star*/
1051:                     cols[cnt++]  = l + nc*(slot + ii + gnx*jj + gnx*gny*kk);
1052:                   }
1053:                 }
1054:               }
1055:             }
1056:             rows[l]      = l + nc*(slot);
1057:           }
1058:           MatSetValuesLocal(J,nc,rows,cnt,cols,values,INSERT_VALUES);
1059:         }
1060:       }
1061:     }
1062:     PetscFree(values);
1063:     MatAssemblyBegin(J,MAT_FINAL_ASSEMBLY);
1064:     MatAssemblyEnd(J,MAT_FINAL_ASSEMBLY);
1065:   }
1066:   PetscFree2(rows,cols);
1067:   return(0);
1068: }

1070: /* ---------------------------------------------------------------------------------*/

1074: PetscErrorCode DAGetMatrix1d_MPIAIJ(DA da,Mat J)
1075: {
1076:   PetscErrorCode         ierr;
1077:   PetscInt               xs,nx,i,i1,slot,gxs,gnx;
1078:   PetscInt               m,dim,s,*cols = PETSC_NULL,nc,*rows = PETSC_NULL,col,cnt,l;
1079:   PetscInt               istart,iend;
1080:   PetscScalar            *values;
1081:   DAPeriodicType         wrap;
1082:   ISLocalToGlobalMapping ltog,ltogb;

1085:   /*     
1086:          nc - number of components per grid point 
1087:          col - number of colors needed in one direction for single component problem
1088:   
1089:   */
1090:   DAGetInfo(da,&dim,&m,0,0,0,0,0,&nc,&s,&wrap,0);
1091:   col    = 2*s + 1;

1093:   DAGetCorners(da,&xs,0,0,&nx,0,0);
1094:   DAGetGhostCorners(da,&gxs,0,0,&gnx,0,0);

1096:   MatSeqAIJSetPreallocation(J,col*nc,0);
1097:   MatMPIAIJSetPreallocation(J,col*nc,0,col*nc,0);
1098:   MatSetBlockSize(J,nc);
1099:   PetscMalloc2(nc,PetscInt,&rows,col*nc*nc,PetscInt,&cols);
1100: 
1101:   DAGetISLocalToGlobalMapping(da,&ltog);
1102:   DAGetISLocalToGlobalMappingBlck(da,&ltogb);
1103:   MatSetLocalToGlobalMapping(J,ltog);
1104:   MatSetLocalToGlobalMappingBlock(J,ltogb);
1105: 
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*nc*nc*sizeof(PetscScalar),&values);
1113:     PetscMemzero(values,col*nc*nc*sizeof(PetscScalar));
1114:     for (i=xs; i<xs+nx; i++) {
1115:       istart = PetscMax(-s,gxs - i);
1116:       iend   = PetscMin(s,gxs + gnx - i - 1);
1117:       slot   = i - gxs;
1118: 
1119:       cnt  = 0;
1120:       for (l=0; l<nc; l++) {
1121:         for (i1=istart; i1<iend+1; i1++) {
1122:           cols[cnt++] = l + nc*(slot + i1);
1123:         }
1124:         rows[l]      = l + nc*(slot);
1125:       }
1126:       MatSetValuesLocal(J,nc,rows,cnt,cols,values,INSERT_VALUES);
1127:     }
1128:     PetscFree(values);
1129:     MatAssemblyBegin(J,MAT_FINAL_ASSEMBLY);
1130:     MatAssemblyEnd(J,MAT_FINAL_ASSEMBLY);
1131:   }
1132:   PetscFree2(rows,cols);
1133:   return(0);
1134: }

1138: PetscErrorCode DAGetMatrix2d_MPIBAIJ(DA da,Mat J)
1139: {
1140:   PetscErrorCode         ierr;
1141:   PetscInt               xs,ys,nx,ny,i,j,slot,gxs,gys,gnx,gny;
1142:   PetscInt               m,n,dim,s,*cols,nc,col,cnt,*dnz,*onz;
1143:   PetscInt               istart,iend,jstart,jend,ii,jj;
1144:   MPI_Comm               comm;
1145:   PetscScalar            *values;
1146:   DAPeriodicType         wrap;
1147:   DAStencilType          st;
1148:   ISLocalToGlobalMapping ltog,ltogb;

1151:   /*     
1152:      nc - number of components per grid point 
1153:      col - number of colors needed in one direction for single component problem
1154:   */
1155:   DAGetInfo(da,&dim,&m,&n,0,0,0,0,&nc,&s,&wrap,&st);
1156:   col = 2*s + 1;

1158:   DAGetCorners(da,&xs,&ys,0,&nx,&ny,0);
1159:   DAGetGhostCorners(da,&gxs,&gys,0,&gnx,&gny,0);
1160:   PetscObjectGetComm((PetscObject)da,&comm);

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

1164:   DAGetISLocalToGlobalMapping(da,&ltog);
1165:   DAGetISLocalToGlobalMappingBlck(da,&ltogb);

1167:   /* determine the matrix preallocation information */
1168:   MatPreallocateInitialize(comm,nx*ny,nx*ny,dnz,onz);
1169:   for (i=xs; i<xs+nx; i++) {
1170:     istart = DAXPeriodic(wrap) ? -s : (PetscMax(-s,-i));
1171:     iend   = DAXPeriodic(wrap) ?  s : (PetscMin(s,m-i-1));
1172:     for (j=ys; j<ys+ny; j++) {
1173:       jstart = DAYPeriodic(wrap) ? -s : (PetscMax(-s,-j));
1174:       jend   = DAYPeriodic(wrap) ?  s : (PetscMin(s,n-j-1));
1175:       slot = i - gxs + gnx*(j - gys);

1177:       /* Find block columns in block row */
1178:       cnt  = 0;
1179:       for (ii=istart; ii<iend+1; ii++) {
1180:         for (jj=jstart; jj<jend+1; jj++) {
1181:           if (st == DA_STENCIL_BOX || !ii || !jj) { /* BOX or on the STAR */
1182:             cols[cnt++]  = slot + ii + gnx*jj;
1183:           }
1184:         }
1185:       }
1186:       MatPreallocateSetLocal(ltogb,1,&slot,cnt,cols,dnz,onz);
1187:     }
1188:   }
1189:   MatSeqBAIJSetPreallocation(J,nc,0,dnz);
1190:   MatMPIBAIJSetPreallocation(J,nc,0,dnz,0,onz);
1191:   MatPreallocateFinalize(dnz,onz);

1193:   MatSetLocalToGlobalMapping(J,ltog);
1194:   MatSetLocalToGlobalMappingBlock(J,ltogb);

1196:   /*
1197:     For each node in the grid: we get the neighbors in the local (on processor ordering
1198:     that includes the ghost points) then MatSetValuesLocal() maps those indices to the global
1199:     PETSc ordering.
1200:   */
1201:   if (!da->prealloc_only) {
1202:     PetscMalloc(col*col*nc*nc*sizeof(PetscScalar),&values);
1203:     PetscMemzero(values,col*col*nc*nc*sizeof(PetscScalar));
1204:     for (i=xs; i<xs+nx; i++) {
1205:       istart = DAXPeriodic(wrap) ? -s : (PetscMax(-s,-i));
1206:       iend   = DAXPeriodic(wrap) ?  s : (PetscMin(s,m-i-1));
1207:       for (j=ys; j<ys+ny; j++) {
1208:         jstart = DAYPeriodic(wrap) ? -s : (PetscMax(-s,-j));
1209:         jend   = DAYPeriodic(wrap) ?  s : (PetscMin(s,n-j-1));
1210:         slot = i - gxs + gnx*(j - gys);
1211:         cnt  = 0;
1212:         for (ii=istart; ii<iend+1; ii++) {
1213:           for (jj=jstart; jj<jend+1; jj++) {
1214:             if (st == DA_STENCIL_BOX || !ii || !jj) { /* BOX or on the STAR */
1215:               cols[cnt++]  = slot + ii + gnx*jj;
1216:             }
1217:           }
1218:         }
1219:         MatSetValuesBlockedLocal(J,1,&slot,cnt,cols,values,INSERT_VALUES);
1220:       }
1221:     }
1222:     PetscFree(values);
1223:     MatAssemblyBegin(J,MAT_FINAL_ASSEMBLY);
1224:     MatAssemblyEnd(J,MAT_FINAL_ASSEMBLY);
1225:   }
1226:   PetscFree(cols);
1227:   return(0);
1228: }

1232: PetscErrorCode DAGetMatrix3d_MPIBAIJ(DA da,Mat J)
1233: {
1234:   PetscErrorCode         ierr;
1235:   PetscInt               xs,ys,nx,ny,i,j,slot,gxs,gys,gnx,gny;
1236:   PetscInt               m,n,dim,s,*cols,k,nc,col,cnt,p,*dnz,*onz;
1237:   PetscInt               istart,iend,jstart,jend,kstart,kend,zs,nz,gzs,gnz,ii,jj,kk;
1238:   MPI_Comm               comm;
1239:   PetscScalar            *values;
1240:   DAPeriodicType         wrap;
1241:   DAStencilType          st;
1242:   ISLocalToGlobalMapping ltog,ltogb;

1245:   /*     
1246:          nc - number of components per grid point 
1247:          col - number of colors needed in one direction for single component problem
1248:   
1249:   */
1250:   DAGetInfo(da,&dim,&m,&n,&p,0,0,0,&nc,&s,&wrap,&st);
1251:   col    = 2*s + 1;

1253:   DAGetCorners(da,&xs,&ys,&zs,&nx,&ny,&nz);
1254:   DAGetGhostCorners(da,&gxs,&gys,&gzs,&gnx,&gny,&gnz);
1255:   PetscObjectGetComm((PetscObject)da,&comm);

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

1259:   DAGetISLocalToGlobalMapping(da,&ltog);
1260:   DAGetISLocalToGlobalMappingBlck(da,&ltogb);

1262:   /* determine the matrix preallocation information */
1263:   MatPreallocateInitialize(comm,nx*ny*nz,nx*ny*nz,dnz,onz);
1264:   for (i=xs; i<xs+nx; i++) {
1265:     istart = DAXPeriodic(wrap) ? -s : (PetscMax(-s,-i));
1266:     iend   = DAXPeriodic(wrap) ?  s : (PetscMin(s,m-i-1));
1267:     for (j=ys; j<ys+ny; j++) {
1268:       jstart = DAYPeriodic(wrap) ? -s : (PetscMax(-s,-j));
1269:       jend   = DAYPeriodic(wrap) ?  s : (PetscMin(s,n-j-1));
1270:       for (k=zs; k<zs+nz; k++) {
1271:         kstart = DAZPeriodic(wrap) ? -s : (PetscMax(-s,-k));
1272:         kend   = DAZPeriodic(wrap) ?  s : (PetscMin(s,p-k-1));

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

1276:         /* Find block columns in block row */
1277:         cnt  = 0;
1278:         for (ii=istart; ii<iend+1; ii++) {
1279:           for (jj=jstart; jj<jend+1; jj++) {
1280:             for (kk=kstart; kk<kend+1; kk++) {
1281:               if ((st == DA_STENCIL_BOX) || ((!ii && !jj) || (!jj && !kk) || (!ii && !kk))) {/* entries on star*/
1282:                 cols[cnt++]  = slot + ii + gnx*jj + gnx*gny*kk;
1283:               }
1284:             }
1285:           }
1286:         }
1287:         MatPreallocateSetLocal(ltogb,1,&slot,cnt,cols,dnz,onz);
1288:       }
1289:     }
1290:   }
1291:   MatSeqBAIJSetPreallocation(J,nc,0,dnz);
1292:   MatMPIBAIJSetPreallocation(J,nc,0,dnz,0,onz);
1293:   MatPreallocateFinalize(dnz,onz);

1295:   MatSetLocalToGlobalMapping(J,ltog);
1296:   MatSetLocalToGlobalMappingBlock(J,ltogb);

1298:   /*
1299:     For each node in the grid: we get the neighbors in the local (on processor ordering
1300:     that includes the ghost points) then MatSetValuesLocal() maps those indices to the global
1301:     PETSc ordering.
1302:   */
1303:   if (!da->prealloc_only) {
1304:     PetscMalloc(col*col*col*nc*nc*sizeof(PetscScalar),&values);
1305:     PetscMemzero(values,col*col*col*nc*nc*sizeof(PetscScalar));
1306:     for (i=xs; i<xs+nx; i++) {
1307:       istart = DAXPeriodic(wrap) ? -s : (PetscMax(-s,-i));
1308:       iend   = DAXPeriodic(wrap) ?  s : (PetscMin(s,m-i-1));
1309:       for (j=ys; j<ys+ny; j++) {
1310:         jstart = DAYPeriodic(wrap) ? -s : (PetscMax(-s,-j));
1311:         jend   = DAYPeriodic(wrap) ?  s : (PetscMin(s,n-j-1));
1312:         for (k=zs; k<zs+nz; k++) {
1313:           kstart = DAZPeriodic(wrap) ? -s : (PetscMax(-s,-k));
1314:           kend   = DAZPeriodic(wrap) ?  s : (PetscMin(s,p-k-1));
1315: 
1316:           slot = i - gxs + gnx*(j - gys) + gnx*gny*(k - gzs);
1317: 
1318:           cnt  = 0;
1319:           for (ii=istart; ii<iend+1; ii++) {
1320:             for (jj=jstart; jj<jend+1; jj++) {
1321:               for (kk=kstart; kk<kend+1; kk++) {
1322:                 if ((st == DA_STENCIL_BOX) || ((!ii && !jj) || (!jj && !kk) || (!ii && !kk))) {/* entries on star*/
1323:                   cols[cnt++]  = slot + ii + gnx*jj + gnx*gny*kk;
1324:                 }
1325:               }
1326:             }
1327:           }
1328:           MatSetValuesBlockedLocal(J,1,&slot,cnt,cols,values,INSERT_VALUES);
1329:         }
1330:       }
1331:     }
1332:     PetscFree(values);
1333:     MatAssemblyBegin(J,MAT_FINAL_ASSEMBLY);
1334:     MatAssemblyEnd(J,MAT_FINAL_ASSEMBLY);
1335:   }
1336:   PetscFree(cols);
1337:   return(0);
1338: }

1342: /*
1343:   This helper is for of SBAIJ preallocation, to discard the lower-triangular values which are difficult to
1344:   identify in the local ordering with periodic domain.
1345: */
1346: static PetscErrorCode L2GFilterUpperTriangular(ISLocalToGlobalMapping ltog,PetscInt *row,PetscInt *cnt,PetscInt col[])
1347: {
1349:   PetscInt i,n;

1352:   ISLocalToGlobalMappingApply(ltog,1,row,row);
1353:   ISLocalToGlobalMappingApply(ltog,*cnt,col,col);
1354:   for (i=0,n=0; i<*cnt; i++) {
1355:     if (col[i] >= *row) col[n++] = col[i];
1356:   }
1357:   *cnt = n;
1358:   return(0);
1359: }

1363: PetscErrorCode DAGetMatrix2d_MPISBAIJ(DA da,Mat J)
1364: {
1365:   PetscErrorCode         ierr;
1366:   PetscInt               xs,ys,nx,ny,i,j,slot,gxs,gys,gnx,gny;
1367:   PetscInt               m,n,dim,s,*cols,nc,col,cnt,*dnz,*onz;
1368:   PetscInt               istart,iend,jstart,jend,ii,jj;
1369:   MPI_Comm               comm;
1370:   PetscScalar            *values;
1371:   DAPeriodicType         wrap;
1372:   DAStencilType          st;
1373:   ISLocalToGlobalMapping ltog,ltogb;

1376:   /*     
1377:      nc - number of components per grid point 
1378:      col - number of colors needed in one direction for single component problem
1379:   */
1380:   DAGetInfo(da,&dim,&m,&n,0,0,0,0,&nc,&s,&wrap,&st);
1381:   col = 2*s + 1;

1383:   DAGetCorners(da,&xs,&ys,0,&nx,&ny,0);
1384:   DAGetGhostCorners(da,&gxs,&gys,0,&gnx,&gny,0);
1385:   PetscObjectGetComm((PetscObject)da,&comm);

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

1389:   DAGetISLocalToGlobalMapping(da,&ltog);
1390:   DAGetISLocalToGlobalMappingBlck(da,&ltogb);

1392:   /* determine the matrix preallocation information */
1393:   MatPreallocateSymmetricInitialize(comm,nx*ny,nx*ny,dnz,onz);
1394:   for (i=xs; i<xs+nx; i++) {
1395:     istart = DAXPeriodic(wrap) ? -s : (PetscMax(-s,-i));
1396:     iend   = DAXPeriodic(wrap) ?  s : (PetscMin(s,m-i-1));
1397:     for (j=ys; j<ys+ny; j++) {
1398:       jstart = DAYPeriodic(wrap) ? -s : (PetscMax(-s,-j));
1399:       jend   = DAYPeriodic(wrap) ?  s : (PetscMin(s,n-j-1));
1400:       slot = i - gxs + gnx*(j - gys);

1402:       /* Find block columns in block row */
1403:       cnt  = 0;
1404:       for (ii=istart; ii<iend+1; ii++) {
1405:         for (jj=jstart; jj<jend+1; jj++) {
1406:           if (st == DA_STENCIL_BOX || !ii || !jj) {
1407:             cols[cnt++]  = slot + ii + gnx*jj;
1408:           }
1409:         }
1410:       }
1411:       L2GFilterUpperTriangular(ltogb,&slot,&cnt,cols);
1412:       MatPreallocateSymmetricSet(slot,cnt,cols,dnz,onz);
1413:     }
1414:   }
1415:   MatSeqSBAIJSetPreallocation(J,nc,0,dnz);
1416:   MatMPISBAIJSetPreallocation(J,nc,0,dnz,0,onz);
1417:   MatPreallocateFinalize(dnz,onz);

1419:   MatSetLocalToGlobalMapping(J,ltog);
1420:   MatSetLocalToGlobalMappingBlock(J,ltogb);

1422:   /*
1423:     For each node in the grid: we get the neighbors in the local (on processor ordering
1424:     that includes the ghost points) then MatSetValuesLocal() maps those indices to the global
1425:     PETSc ordering.
1426:   */
1427:   if (!da->prealloc_only) {
1428:     PetscMalloc(col*col*nc*nc*sizeof(PetscScalar),&values);
1429:     PetscMemzero(values,col*col*nc*nc*sizeof(PetscScalar));
1430:     for (i=xs; i<xs+nx; i++) {
1431:       istart = DAXPeriodic(wrap) ? -s : (PetscMax(-s,-i));
1432:       iend   = DAXPeriodic(wrap) ?  s : (PetscMin(s,m-i-1));
1433:       for (j=ys; j<ys+ny; j++) {
1434:         jstart = DAYPeriodic(wrap) ? -s : (PetscMax(-s,-j));
1435:         jend   = DAYPeriodic(wrap) ?  s : (PetscMin(s,n-j-1));
1436:         slot = i - gxs + gnx*(j - gys);

1438:         /* Find block columns in block row */
1439:         cnt  = 0;
1440:         for (ii=istart; ii<iend+1; ii++) {
1441:           for (jj=jstart; jj<jend+1; jj++) {
1442:             if (st == DA_STENCIL_BOX || !ii || !jj) {
1443:               cols[cnt++]  = slot + ii + gnx*jj;
1444:             }
1445:           }
1446:         }
1447:         L2GFilterUpperTriangular(ltogb,&slot,&cnt,cols);
1448:         MatSetValuesBlocked(J,1,&slot,cnt,cols,values,INSERT_VALUES);
1449:       }
1450:     }
1451:     PetscFree(values);
1452:     MatAssemblyBegin(J,MAT_FINAL_ASSEMBLY);
1453:     MatAssemblyEnd(J,MAT_FINAL_ASSEMBLY);
1454:   }
1455:   PetscFree(cols);
1456:   return(0);
1457: }

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

1474:   /*     
1475:      nc - number of components per grid point 
1476:      col - number of colors needed in one direction for single component problem 
1477:   */
1478:   DAGetInfo(da,&dim,&m,&n,&p,0,0,0,&nc,&s,&wrap,&st);
1479:   col = 2*s + 1;

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

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

1488:   DAGetISLocalToGlobalMapping(da,&ltog);
1489:   DAGetISLocalToGlobalMappingBlck(da,&ltogb);

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

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

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

1525:   MatSetLocalToGlobalMapping(J,ltog);
1526:   MatSetLocalToGlobalMappingBlock(J,ltogb);

1528:   /*
1529:     For each node in the grid: we get the neighbors in the local (on processor ordering
1530:     that includes the ghost points) then MatSetValuesLocal() maps those indices to the global
1531:     PETSc ordering.
1532:   */
1533:   if (!da->prealloc_only) {
1534:     PetscMalloc(col*col*col*nc*nc*sizeof(PetscScalar),&values);
1535:     PetscMemzero(values,col*col*col*nc*nc*sizeof(PetscScalar));
1536:     for (i=xs; i<xs+nx; i++) {
1537:       istart = DAXPeriodic(wrap) ? -s : (PetscMax(-s,-i));
1538:       iend   = DAXPeriodic(wrap) ?  s : (PetscMin(s,m-i-1));
1539:       for (j=ys; j<ys+ny; j++) {
1540:         jstart = DAYPeriodic(wrap) ? -s : (PetscMax(-s,-j));
1541:         jend   = DAYPeriodic(wrap) ?  s : (PetscMin(s,n-j-1));
1542:         for (k=zs; k<zs+nz; k++) {
1543:           kstart = DAZPeriodic(wrap) ? -s : (PetscMax(-s,-k));
1544:           kend   = DAZPeriodic(wrap) ?  s : (PetscMin(s,p-k-1));
1545: 
1546:           slot = i - gxs + gnx*(j - gys) + gnx*gny*(k - gzs);
1547: 
1548:           cnt  = 0;
1549:           for (ii=istart; ii<iend+1; ii++) {
1550:             for (jj=jstart; jj<jend+1; jj++) {
1551:               for (kk=kstart; kk<kend+1; kk++) {
1552:                 if ((st == DA_STENCIL_BOX) || (!ii && !jj) || (!jj && !kk) || (!ii && !kk)) {
1553:                   cols[cnt++]  = slot + ii + gnx*jj + gnx*gny*kk;
1554:                 }
1555:               }
1556:             }
1557:           }
1558:           L2GFilterUpperTriangular(ltogb,&slot,&cnt,cols);
1559:           MatSetValuesBlocked(J,1,&slot,cnt,cols,values,INSERT_VALUES);
1560:         }
1561:       }
1562:     }
1563:     PetscFree(values);
1564:     MatAssemblyBegin(J,MAT_FINAL_ASSEMBLY);
1565:     MatAssemblyEnd(J,MAT_FINAL_ASSEMBLY);
1566:   }
1567:   PetscFree(cols);
1568:   return(0);
1569: }

1571: /* ---------------------------------------------------------------------------------*/

1575: PetscErrorCode DAGetMatrix3d_MPIAIJ_Fill(DA da,Mat J)
1576: {
1577:   PetscErrorCode         ierr;
1578:   PetscInt               xs,ys,nx,ny,i,j,slot,gxs,gys,gnx,gny;
1579:   PetscInt               m,n,dim,s,*cols,k,nc,row,col,cnt,l,p,*dnz,*onz;
1580:   PetscInt               istart,iend,jstart,jend,kstart,kend,zs,nz,gzs,gnz,ii,jj,kk;
1581:   PetscInt               ifill_col,*dfill = da->dfill,*ofill = da->ofill;
1582:   MPI_Comm               comm;
1583:   PetscScalar            *values;
1584:   DAPeriodicType         wrap;
1585:   ISLocalToGlobalMapping ltog,ltogb;
1586:   DAStencilType          st;

1589:   /*     
1590:          nc - number of components per grid point 
1591:          col - number of colors needed in one direction for single component problem
1592:   
1593:   */
1594:   DAGetInfo(da,&dim,&m,&n,&p,0,0,0,&nc,&s,&wrap,&st);
1595:   col    = 2*s + 1;
1596:   if (DAXPeriodic(wrap) && (m % col)){
1597:     SETERRQ(PETSC_ERR_SUP,"For coloring efficiency ensure number of grid points in X is divisible\n\
1598:                  by 2*stencil_width + 1\n");
1599:   }
1600:   if (DAYPeriodic(wrap) && (n % col)){
1601:     SETERRQ(PETSC_ERR_SUP,"For coloring efficiency ensure number of grid points in Y is divisible\n\
1602:                  by 2*stencil_width + 1\n");
1603:   }
1604:   if (DAZPeriodic(wrap) && (p % col)){
1605:     SETERRQ(PETSC_ERR_SUP,"For coloring efficiency ensure number of grid points in Z is divisible\n\
1606:                  by 2*stencil_width + 1\n");
1607:   }

1609:   DAGetCorners(da,&xs,&ys,&zs,&nx,&ny,&nz);
1610:   DAGetGhostCorners(da,&gxs,&gys,&gzs,&gnx,&gny,&gnz);
1611:   PetscObjectGetComm((PetscObject)da,&comm);

1613:   PetscMalloc(col*col*col*nc*sizeof(PetscInt),&cols);
1614:   DAGetISLocalToGlobalMapping(da,&ltog);
1615:   DAGetISLocalToGlobalMappingBlck(da,&ltogb);

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


1621:   for (i=xs; i<xs+nx; i++) {
1622:     istart = DAXPeriodic(wrap) ? -s : (PetscMax(-s,-i));
1623:     iend   = DAXPeriodic(wrap) ?  s : (PetscMin(s,m-i-1));
1624:     for (j=ys; j<ys+ny; j++) {
1625:       jstart = DAYPeriodic(wrap) ? -s : (PetscMax(-s,-j));
1626:       jend   = DAYPeriodic(wrap) ?  s : (PetscMin(s,n-j-1));
1627:       for (k=zs; k<zs+nz; k++) {
1628:         kstart = DAZPeriodic(wrap) ? -s : (PetscMax(-s,-k));
1629:         kend   = DAZPeriodic(wrap) ?  s : (PetscMin(s,p-k-1));
1630: 
1631:         slot = i - gxs + gnx*(j - gys) + gnx*gny*(k - gzs);
1632: 
1633:         for (l=0; l<nc; l++) {
1634:           cnt  = 0;
1635:           for (ii=istart; ii<iend+1; ii++) {
1636:             for (jj=jstart; jj<jend+1; jj++) {
1637:               for (kk=kstart; kk<kend+1; kk++) {
1638:                 if (ii || jj || kk) {
1639:                   if ((st == DA_STENCIL_BOX) || ((!ii && !jj) || (!jj && !kk) || (!ii && !kk))) {/* entries on star*/
1640:                     for (ifill_col=ofill[l]; ifill_col<ofill[l+1]; ifill_col++)
1641:                       cols[cnt++]  = ofill[ifill_col] + nc*(slot + ii + gnx*jj + gnx*gny*kk);
1642:                   }
1643:                 } else {
1644:                   if (dfill) {
1645:                     for (ifill_col=dfill[l]; ifill_col<dfill[l+1]; ifill_col++)
1646:                       cols[cnt++]  = dfill[ifill_col] + nc*(slot + ii + gnx*jj + gnx*gny*kk);
1647:                   } else {
1648:                     for (ifill_col=0; ifill_col<nc; ifill_col++)
1649:                       cols[cnt++]  = ifill_col + nc*(slot + ii + gnx*jj + gnx*gny*kk);
1650:                   }
1651:                 }
1652:               }
1653:             }
1654:           }
1655:           row  = l + nc*(slot);
1656:           MatPreallocateSetLocal(ltog,1,&row,cnt,cols,dnz,onz);
1657:         }
1658:       }
1659:     }
1660:   }
1661:   MatSeqAIJSetPreallocation(J,0,dnz);
1662:   MatMPIAIJSetPreallocation(J,0,dnz,0,onz);
1663:   MatPreallocateFinalize(dnz,onz);
1664:   MatSetLocalToGlobalMapping(J,ltog);
1665:   MatSetLocalToGlobalMappingBlock(J,ltogb);

1667:   /*
1668:     For each node in the grid: we get the neighbors in the local (on processor ordering
1669:     that includes the ghost points) then MatSetValuesLocal() maps those indices to the global
1670:     PETSc ordering.
1671:   */
1672:   if (!da->prealloc_only) {
1673:     PetscMalloc(col*col*col*nc*nc*nc*sizeof(PetscScalar),&values);
1674:     PetscMemzero(values,col*col*col*nc*nc*nc*sizeof(PetscScalar));
1675:     for (i=xs; i<xs+nx; i++) {
1676:       istart = DAXPeriodic(wrap) ? -s : (PetscMax(-s,-i));
1677:       iend   = DAXPeriodic(wrap) ?  s : (PetscMin(s,m-i-1));
1678:       for (j=ys; j<ys+ny; j++) {
1679:         jstart = DAYPeriodic(wrap) ? -s : (PetscMax(-s,-j));
1680:         jend   = DAYPeriodic(wrap) ?  s : (PetscMin(s,n-j-1));
1681:         for (k=zs; k<zs+nz; k++) {
1682:           kstart = DAZPeriodic(wrap) ? -s : (PetscMax(-s,-k));
1683:           kend   = DAZPeriodic(wrap) ?  s : (PetscMin(s,p-k-1));
1684: 
1685:           slot = i - gxs + gnx*(j - gys) + gnx*gny*(k - gzs);
1686: 
1687:           for (l=0; l<nc; l++) {
1688:             cnt  = 0;
1689:             for (ii=istart; ii<iend+1; ii++) {
1690:               for (jj=jstart; jj<jend+1; jj++) {
1691:                 for (kk=kstart; kk<kend+1; kk++) {
1692:                   if (ii || jj || kk) {
1693:                     if ((st == DA_STENCIL_BOX) || ((!ii && !jj) || (!jj && !kk) || (!ii && !kk))) {/* entries on star*/
1694:                       for (ifill_col=ofill[l]; ifill_col<ofill[l+1]; ifill_col++)
1695:                         cols[cnt++]  = ofill[ifill_col] + nc*(slot + ii + gnx*jj + gnx*gny*kk);
1696:                     }
1697:                   } else {
1698:                     if (dfill) {
1699:                       for (ifill_col=dfill[l]; ifill_col<dfill[l+1]; ifill_col++)
1700:                         cols[cnt++]  = dfill[ifill_col] + nc*(slot + ii + gnx*jj + gnx*gny*kk);
1701:                     } else {
1702:                       for (ifill_col=0; ifill_col<nc; ifill_col++)
1703:                         cols[cnt++]  = ifill_col + nc*(slot + ii + gnx*jj + gnx*gny*kk);
1704:                     }
1705:                   }
1706:                 }
1707:               }
1708:             }
1709:             row  = l + nc*(slot);
1710:             MatSetValuesLocal(J,1,&row,cnt,cols,values,INSERT_VALUES);
1711:           }
1712:         }
1713:       }
1714:     }
1715:     PetscFree(values);
1716:     MatAssemblyBegin(J,MAT_FINAL_ASSEMBLY);
1717:     MatAssemblyEnd(J,MAT_FINAL_ASSEMBLY);
1718:   }
1719:   PetscFree(cols);
1720:   return(0);
1721: }