Actual source code: fdmpiaij.c
1: #define PETSCMAT_DLL
3: #include ../src/mat/impls/aij/mpi/mpiaij.h
5: EXTERN PetscErrorCode CreateColmap_MPIAIJ_Private(Mat);
9: PetscErrorCode MatFDColoringCreate_MPIAIJ(Mat mat,ISColoring iscoloring,MatFDColoring c)
10: {
11: Mat_MPIAIJ *aij = (Mat_MPIAIJ*)mat->data;
12: PetscErrorCode ierr;
13: PetscMPIInt size,*ncolsonproc,*disp,nn;
14: PetscInt i,n,nrows,j,k,m,*rows = 0,*A_ci,*A_cj,ncols,col;
15: const PetscInt *is;
16: PetscInt nis = iscoloring->n,nctot,*cols,*B_ci,*B_cj;
17: PetscInt *rowhit,M,cstart,cend,colb;
18: PetscInt *columnsforrow,l;
19: IS *isa;
20: PetscTruth done,flg;
21: ISLocalToGlobalMapping map = mat->mapping;
22: PetscInt *ltog = (map ? map->indices : (PetscInt*) PETSC_NULL) ,ctype=c->ctype;
25: if (!mat->assembled) {
26: SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Matrix must be assembled first; MatAssemblyBegin/End();");
27: }
28: if (ctype == IS_COLORING_GHOSTED && !map) SETERRQ(PETSC_ERR_ARG_INCOMP,"When using ghosted differencing matrix must have local to global mapping provided with MatSetLocalToGlobalMapping");
30: ISColoringGetIS(iscoloring,PETSC_IGNORE,&isa);
32: M = mat->rmap->n;
33: cstart = mat->cmap->rstart;
34: cend = mat->cmap->rend;
35: c->M = mat->rmap->N; /* set the global rows and columns and local rows */
36: c->N = mat->cmap->N;
37: c->m = mat->rmap->n;
38: c->rstart = mat->rmap->rstart;
40: c->ncolors = nis;
41: PetscMalloc(nis*sizeof(PetscInt),&c->ncolumns);
42: PetscMalloc(nis*sizeof(PetscInt*),&c->columns);
43: PetscMalloc(nis*sizeof(PetscInt),&c->nrows);
44: PetscMalloc(nis*sizeof(PetscInt*),&c->rows);
45: PetscMalloc(nis*sizeof(PetscInt*),&c->columnsforrow);
46: PetscLogObjectMemory(c,5*nis*sizeof(PetscInt));
48: /* Allow access to data structures of local part of matrix */
49: if (!aij->colmap) {
50: CreateColmap_MPIAIJ_Private(mat);
51: }
52: MatGetColumnIJ(aij->A,0,PETSC_FALSE,PETSC_FALSE,&ncols,&A_ci,&A_cj,&done);
53: MatGetColumnIJ(aij->B,0,PETSC_FALSE,PETSC_FALSE,&ncols,&B_ci,&B_cj,&done);
54:
55: PetscMalloc((M+1)*sizeof(PetscInt),&rowhit);
56: PetscMalloc((M+1)*sizeof(PetscInt),&columnsforrow);
58: for (i=0; i<nis; i++) {
59: ISGetLocalSize(isa[i],&n);
60: ISGetIndices(isa[i],&is);
61: c->ncolumns[i] = n;
62: if (n) {
63: PetscMalloc(n*sizeof(PetscInt),&c->columns[i]);
64: PetscLogObjectMemory(c,n*sizeof(PetscInt));
65: PetscMemcpy(c->columns[i],is,n*sizeof(PetscInt));
66: } else {
67: c->columns[i] = 0;
68: }
70: if (ctype == IS_COLORING_GLOBAL){
71: /* Determine the total (parallel) number of columns of this color */
72: MPI_Comm_size(((PetscObject)mat)->comm,&size);
73: PetscMalloc2(size,PetscMPIInt,&ncolsonproc,size,PetscMPIInt,&disp);
75: nn = PetscMPIIntCast(n);
76: MPI_Allgather(&nn,1,MPI_INT,ncolsonproc,1,MPI_INT,((PetscObject)mat)->comm);
77: nctot = 0; for (j=0; j<size; j++) {nctot += ncolsonproc[j];}
78: if (!nctot) {
79: PetscInfo(mat,"Coloring of matrix has some unneeded colors with no corresponding rows\n");
80: }
82: disp[0] = 0;
83: for (j=1; j<size; j++) {
84: disp[j] = disp[j-1] + ncolsonproc[j-1];
85: }
87: /* Get complete list of columns for color on each processor */
88: PetscMalloc((nctot+1)*sizeof(PetscInt),&cols);
89: MPI_Allgatherv((void*)is,n,MPIU_INT,cols,ncolsonproc,disp,MPIU_INT,((PetscObject)mat)->comm);
90: PetscFree2(ncolsonproc,disp);
91: } else if (ctype == IS_COLORING_GHOSTED){
92: /* Determine local number of columns of this color on this process, including ghost points */
93: nctot = n;
94: PetscMalloc((nctot+1)*sizeof(PetscInt),&cols);
95: PetscMemcpy(cols,is,n*sizeof(PetscInt));
96: } else {
97: SETERRQ(PETSC_ERR_SUP,"Not provided for this MatFDColoring type");
98: }
100: /*
101: Mark all rows affect by these columns
102: */
103: /* Temporary option to allow for debugging/testing */
104: flg = PETSC_FALSE;
105: PetscOptionsGetTruth(PETSC_NULL,"-matfdcoloring_slow",&flg,PETSC_NULL);
106: if (!flg) {/*-----------------------------------------------------------------------------*/
107: /* crude, fast version */
108: PetscMemzero(rowhit,M*sizeof(PetscInt));
109: /* loop over columns*/
110: for (j=0; j<nctot; j++) {
111: if (ctype == IS_COLORING_GHOSTED) {
112: col = ltog[cols[j]];
113: } else {
114: col = cols[j];
115: }
116: if (col >= cstart && col < cend) {
117: /* column is in diagonal block of matrix */
118: rows = A_cj + A_ci[col-cstart];
119: m = A_ci[col-cstart+1] - A_ci[col-cstart];
120: } else {
121: #if defined (PETSC_USE_CTABLE)
122: PetscTableFind(aij->colmap,col+1,&colb);CHKERRQ(ierr)
123: colb --;
124: #else
125: colb = aij->colmap[col] - 1;
126: #endif
127: if (colb == -1) {
128: m = 0;
129: } else {
130: rows = B_cj + B_ci[colb];
131: m = B_ci[colb+1] - B_ci[colb];
132: }
133: }
134: /* loop over columns marking them in rowhit */
135: for (k=0; k<m; k++) {
136: rowhit[*rows++] = col + 1;
137: }
138: }
140: /* count the number of hits */
141: nrows = 0;
142: for (j=0; j<M; j++) {
143: if (rowhit[j]) nrows++;
144: }
145: c->nrows[i] = nrows;
146: PetscMalloc((nrows+1)*sizeof(PetscInt),&c->rows[i]);
147: PetscMalloc((nrows+1)*sizeof(PetscInt),&c->columnsforrow[i]);
148: PetscLogObjectMemory(c,2*(nrows+1)*sizeof(PetscInt));
149: nrows = 0;
150: for (j=0; j<M; j++) {
151: if (rowhit[j]) {
152: c->rows[i][nrows] = j;
153: c->columnsforrow[i][nrows] = rowhit[j] - 1;
154: nrows++;
155: }
156: }
157: } else {/*-------------------------------------------------------------------------------*/
158: /* slow version, using rowhit as a linked list */
159: PetscInt currentcol,fm,mfm;
160: rowhit[M] = M;
161: nrows = 0;
162: /* loop over columns*/
163: for (j=0; j<nctot; j++) {
164: if (ctype == IS_COLORING_GHOSTED) {
165: col = ltog[cols[j]];
166: } else {
167: col = cols[j];
168: }
169: if (col >= cstart && col < cend) {
170: /* column is in diagonal block of matrix */
171: rows = A_cj + A_ci[col-cstart];
172: m = A_ci[col-cstart+1] - A_ci[col-cstart];
173: } else {
174: #if defined (PETSC_USE_CTABLE)
175: PetscTableFind(aij->colmap,col+1,&colb);
176: colb --;
177: #else
178: colb = aij->colmap[col] - 1;
179: #endif
180: if (colb == -1) {
181: m = 0;
182: } else {
183: rows = B_cj + B_ci[colb];
184: m = B_ci[colb+1] - B_ci[colb];
185: }
186: }
188: /* loop over columns marking them in rowhit */
189: fm = M; /* fm points to first entry in linked list */
190: for (k=0; k<m; k++) {
191: currentcol = *rows++;
192: /* is it already in the list? */
193: do {
194: mfm = fm;
195: fm = rowhit[fm];
196: } while (fm < currentcol);
197: /* not in list so add it */
198: if (fm != currentcol) {
199: nrows++;
200: columnsforrow[currentcol] = col;
201: /* next three lines insert new entry into linked list */
202: rowhit[mfm] = currentcol;
203: rowhit[currentcol] = fm;
204: fm = currentcol;
205: /* fm points to present position in list since we know the columns are sorted */
206: } else {
207: SETERRQ(PETSC_ERR_PLIB,"Invalid coloring of matrix detected");
208: }
209: }
210: }
211: c->nrows[i] = nrows;
212: PetscMalloc((nrows+1)*sizeof(PetscInt),&c->rows[i]);
213: PetscMalloc((nrows+1)*sizeof(PetscInt),&c->columnsforrow[i]);
214: PetscLogObjectMemory(c,(nrows+1)*sizeof(PetscInt));
215: /* now store the linked list of rows into c->rows[i] */
216: nrows = 0;
217: fm = rowhit[M];
218: do {
219: c->rows[i][nrows] = fm;
220: c->columnsforrow[i][nrows++] = columnsforrow[fm];
221: fm = rowhit[fm];
222: } while (fm < M);
223: } /* ---------------------------------------------------------------------------------------*/
224: PetscFree(cols);
225: }
227: /* Optimize by adding the vscale, and scaleforrow[][] fields */
228: /*
229: vscale will contain the "diagonal" on processor scalings followed by the off processor
230: */
231: if (ctype == IS_COLORING_GLOBAL) {
232: VecCreateGhost(((PetscObject)mat)->comm,aij->A->rmap->n,PETSC_DETERMINE,aij->B->cmap->n,aij->garray,&c->vscale);
233: PetscMalloc(c->ncolors*sizeof(PetscInt*),&c->vscaleforrow);
234: for (k=0; k<c->ncolors; k++) {
235: PetscMalloc((c->nrows[k]+1)*sizeof(PetscInt),&c->vscaleforrow[k]);
236: for (l=0; l<c->nrows[k]; l++) {
237: col = c->columnsforrow[k][l];
238: if (col >= cstart && col < cend) {
239: /* column is in diagonal block of matrix */
240: colb = col - cstart;
241: } else {
242: /* column is in "off-processor" part */
243: #if defined (PETSC_USE_CTABLE)
244: PetscTableFind(aij->colmap,col+1,&colb);
245: colb --;
246: #else
247: colb = aij->colmap[col] - 1;
248: #endif
249: colb += cend - cstart;
250: }
251: c->vscaleforrow[k][l] = colb;
252: }
253: }
254: } else if (ctype == IS_COLORING_GHOSTED) {
255: /* Get gtol mapping */
256: PetscInt N = mat->cmap->N, *gtol;
257: PetscMalloc((N+1)*sizeof(PetscInt),>ol);
258: for (i=0; i<N; i++) gtol[i] = -1;
259: for (i=0; i<map->n; i++) gtol[ltog[i]] = i;
260:
261: c->vscale = 0; /* will be created in MatFDColoringApply() */
262: PetscMalloc(c->ncolors*sizeof(PetscInt*),&c->vscaleforrow);
263: for (k=0; k<c->ncolors; k++) {
264: PetscMalloc((c->nrows[k]+1)*sizeof(PetscInt),&c->vscaleforrow[k]);
265: for (l=0; l<c->nrows[k]; l++) {
266: col = c->columnsforrow[k][l]; /* global column index */
267: c->vscaleforrow[k][l] = gtol[col]; /* local column index */
268: }
269: }
270: PetscFree(gtol);
271: }
272: ISColoringRestoreIS(iscoloring,&isa);
274: PetscFree(rowhit);
275: PetscFree(columnsforrow);
276: MatRestoreColumnIJ(aij->A,0,PETSC_FALSE,PETSC_FALSE,&ncols,&A_ci,&A_cj,&done);
277: MatRestoreColumnIJ(aij->B,0,PETSC_FALSE,PETSC_FALSE,&ncols,&B_ci,&B_cj,&done);
278: return(0);
279: }