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,<og);
749: DAGetISLocalToGlobalMappingBlck(da,<ogb);
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,<og);
856: DAGetISLocalToGlobalMappingBlck(da,<ogb);
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,<og);
985: DAGetISLocalToGlobalMappingBlck(da,<ogb);
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,<og);
1102: DAGetISLocalToGlobalMappingBlck(da,<ogb);
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,<og);
1165: DAGetISLocalToGlobalMappingBlck(da,<ogb);
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,<og);
1260: DAGetISLocalToGlobalMappingBlck(da,<ogb);
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,<og);
1390: DAGetISLocalToGlobalMappingBlck(da,<ogb);
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,<og);
1489: DAGetISLocalToGlobalMappingBlck(da,<ogb);
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,<og);
1615: DAGetISLocalToGlobalMappingBlck(da,<ogb);
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: }