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);
  6: EXTERN PetscErrorCode MatGetColumnIJ_SeqAIJ(Mat,PetscInt,PetscTruth,PetscInt*,PetscInt*[],PetscInt*[],PetscTruth*);
  7: EXTERN PetscErrorCode MatRestoreColumnIJ_SeqAIJ(Mat,PetscInt,PetscTruth,PetscInt*,PetscInt*[],PetscInt*[],PetscTruth*);

 11: PetscErrorCode MatFDColoringCreate_MPIAIJ(Mat mat,ISColoring iscoloring,MatFDColoring c)
 12: {
 13:   Mat_MPIAIJ     *aij = (Mat_MPIAIJ*)mat->data;
 15:   PetscMPIInt    size,*ncolsonproc,*disp,nn;
 16:   PetscInt       i,*is,n,nrows,j,k,m,*rows = 0,*A_ci,*A_cj,ncols,col;
 17:   PetscInt       nis = iscoloring->n,nctot,*cols,*B_ci,*B_cj;
 18:   PetscInt       *rowhit,M = mat->rmap.n,cstart = mat->cmap.rstart,cend = mat->cmap.rend,colb;
 19:   PetscInt       *columnsforrow,l;
 20:   IS             *isa;
 21:   PetscTruth     done,flg;

 24:   if (!mat->assembled) {
 25:     SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Matrix must be assembled first; MatAssemblyBegin/End();");
 26:   }

 28:   ISColoringGetIS(iscoloring,PETSC_IGNORE,&isa);
 29:   c->M             = mat->rmap.N;  /* set the global rows and columns and local rows */
 30:   c->N             = mat->cmap.N;
 31:   c->m             = mat->rmap.n;
 32:   c->rstart        = mat->rmap.rstart;

 34:   c->ncolors       = nis;
 35:   PetscMalloc(nis*sizeof(PetscInt),&c->ncolumns);
 36:   PetscMalloc(nis*sizeof(PetscInt*),&c->columns);
 37:   PetscMalloc(nis*sizeof(PetscInt),&c->nrows);
 38:   PetscMalloc(nis*sizeof(PetscInt*),&c->rows);
 39:   PetscMalloc(nis*sizeof(PetscInt*),&c->columnsforrow);
 40:   PetscLogObjectMemory(c,5*nis*sizeof(PetscInt));

 42:   /* Allow access to data structures of local part of matrix */
 43:   if (!aij->colmap) {
 44:     CreateColmap_MPIAIJ_Private(mat);
 45:   }
 46:   /*
 47:       Calls the _SeqAIJ() version of these routines to make sure it does not 
 48:      get the reduced (by inodes) version of I and J
 49:   */
 50:   MatGetColumnIJ_SeqAIJ(aij->A,0,PETSC_FALSE,&ncols,&A_ci,&A_cj,&done);
 51:   MatGetColumnIJ_SeqAIJ(aij->B,0,PETSC_FALSE,&ncols,&B_ci,&B_cj,&done);

 53:   MPI_Comm_size(mat->comm,&size);
 54:   PetscMalloc(2*size*sizeof(PetscInt*),&ncolsonproc);
 55:   disp = ncolsonproc + size;

 57:   PetscMalloc((M+1)*sizeof(PetscInt),&rowhit);
 58:   PetscMalloc((M+1)*sizeof(PetscInt),&columnsforrow);

 60:   /*
 61:      Temporary option to allow for debugging/testing
 62:   */
 63:   PetscOptionsHasName(PETSC_NULL,"-matfdcoloring_slow",&flg);

 65:   for (i=0; i<nis; i++) {
 66:     ISGetLocalSize(isa[i],&n);
 67:     ISGetIndices(isa[i],&is);
 68:     c->ncolumns[i] = n;
 69:     c->ncolumns[i] = n;
 70:     if (n) {
 71:       PetscMalloc(n*sizeof(PetscInt),&c->columns[i]);
 72:       PetscLogObjectMemory(c,n*sizeof(PetscInt));
 73:       PetscMemcpy(c->columns[i],is,n*sizeof(PetscInt));
 74:     } else {
 75:       c->columns[i]  = 0;
 76:     }

 78:     /* Determine the total (parallel) number of columns of this color */
 79:     nn   = (PetscMPIInt)n;
 80:     MPI_Allgather(&nn,1,MPI_INT,ncolsonproc,1,MPI_INT,mat->comm);
 81:     nctot = 0; for (j=0; j<size; j++) {nctot += ncolsonproc[j];}
 82:     if (!nctot) {
 83:       PetscInfo(mat,"Coloring of matrix has some unneeded colors with no corresponding rows\n");
 84:     }

 86:     disp[0] = 0;
 87:     for (j=1; j<size; j++) {
 88:       disp[j] = disp[j-1] + ncolsonproc[j-1];
 89:     }
 90: 
 91:     /* Get complete list of columns for color on each processor */
 92:     PetscMalloc((nctot+1)*sizeof(PetscInt),&cols);
 93:     MPI_Allgatherv(is,n,MPIU_INT,cols,ncolsonproc,disp,MPIU_INT,mat->comm);

 95:     /*
 96:        Mark all rows affect by these columns
 97:     */
 98:     if (!flg) {/*-----------------------------------------------------------------------------*/
 99:       /* crude, fast version */
100:       PetscMemzero(rowhit,M*sizeof(PetscInt));
101:       /* loop over columns*/
102:       for (j=0; j<nctot; j++) {
103:         col  = cols[j];
104:         if (col >= cstart && col < cend) {
105:           /* column is in diagonal block of matrix */
106:           rows = A_cj + A_ci[col-cstart];
107:           m    = A_ci[col-cstart+1] - A_ci[col-cstart];
108:         } else {
109: #if defined (PETSC_USE_CTABLE)
110:           PetscTableFind(aij->colmap,col+1,&colb);CHKERRQ(ierr)
111:           colb --;
112: #else
113:           colb = aij->colmap[col] - 1;
114: #endif
115:           if (colb == -1) {
116:             m = 0;
117:           } else {
118:             rows = B_cj + B_ci[colb];
119:             m    = B_ci[colb+1] - B_ci[colb];
120:           }
121:         }
122:         /* loop over columns marking them in rowhit */
123:         for (k=0; k<m; k++) {
124:           rowhit[*rows++] = col + 1;
125:         }
126:       }

128:       /* count the number of hits */
129:       nrows = 0;
130:       for (j=0; j<M; j++) {
131:         if (rowhit[j]) nrows++;
132:       }
133:       c->nrows[i]         = nrows;
134:       PetscMalloc((nrows+1)*sizeof(PetscInt),&c->rows[i]);
135:       PetscMalloc((nrows+1)*sizeof(PetscInt),&c->columnsforrow[i]);
136:       PetscLogObjectMemory(c,2*(nrows+1)*sizeof(PetscInt));
137:       nrows = 0;
138:       for (j=0; j<M; j++) {
139:         if (rowhit[j]) {
140:           c->rows[i][nrows]           = j;
141:           c->columnsforrow[i][nrows] = rowhit[j] - 1;
142:           nrows++;
143:         }
144:       }
145:     } else {/*-------------------------------------------------------------------------------*/
146:       /* slow version, using rowhit as a linked list */
147:       PetscInt currentcol,fm,mfm;
148:       rowhit[M] = M;
149:       nrows     = 0;
150:       /* loop over columns*/
151:       for (j=0; j<nctot; j++) {
152:         col  = cols[j];
153:         if (col >= cstart && col < cend) {
154:           /* column is in diagonal block of matrix */
155:           rows = A_cj + A_ci[col-cstart];
156:           m    = A_ci[col-cstart+1] - A_ci[col-cstart];
157:         } else {
158: #if defined (PETSC_USE_CTABLE)
159:           PetscTableFind(aij->colmap,col+1,&colb);
160:           colb --;
161: #else
162:           colb = aij->colmap[col] - 1;
163: #endif
164:           if (colb == -1) {
165:             m = 0;
166:           } else {
167:             rows = B_cj + B_ci[colb];
168:             m    = B_ci[colb+1] - B_ci[colb];
169:           }
170:         }
171:         /* loop over columns marking them in rowhit */
172:         fm    = M; /* fm points to first entry in linked list */
173:         for (k=0; k<m; k++) {
174:           currentcol = *rows++;
175:           /* is it already in the list? */
176:           do {
177:             mfm  = fm;
178:             fm   = rowhit[fm];
179:           } while (fm < currentcol);
180:           /* not in list so add it */
181:           if (fm != currentcol) {
182:             nrows++;
183:             columnsforrow[currentcol] = col;
184:             /* next three lines insert new entry into linked list */
185:             rowhit[mfm]               = currentcol;
186:             rowhit[currentcol]        = fm;
187:             fm                        = currentcol;
188:             /* fm points to present position in list since we know the columns are sorted */
189:           } else {
190:             SETERRQ(PETSC_ERR_PLIB,"Invalid coloring of matrix detected");
191:           }
192:         }
193:       }
194:       c->nrows[i]         = nrows;
195:       PetscMalloc((nrows+1)*sizeof(PetscInt),&c->rows[i]);
196:       PetscMalloc((nrows+1)*sizeof(PetscInt),&c->columnsforrow[i]);
197:       PetscLogObjectMemory(c,(nrows+1)*sizeof(PetscInt));
198:       /* now store the linked list of rows into c->rows[i] */
199:       nrows = 0;
200:       fm    = rowhit[M];
201:       do {
202:         c->rows[i][nrows]            = fm;
203:         c->columnsforrow[i][nrows++] = columnsforrow[fm];
204:         fm                           = rowhit[fm];
205:       } while (fm < M);
206:     } /* ---------------------------------------------------------------------------------------*/
207:     PetscFree(cols);
208:   }

210:   /* Optimize by adding the vscale, and scaleforrow[][] fields */
211:   /*
212:        vscale will contain the "diagonal" on processor scalings followed by the off processor
213:   */
214:   VecCreateGhost(mat->comm,aij->A->rmap.n,PETSC_DETERMINE,aij->B->cmap.n,aij->garray,&c->vscale);CHKERRQ(ierr)
215:   PetscMalloc(c->ncolors*sizeof(PetscInt*),&c->vscaleforrow);
216:   for (k=0; k<c->ncolors; k++) {
217:     PetscMalloc((c->nrows[k]+1)*sizeof(PetscInt),&c->vscaleforrow[k]);
218:     for (l=0; l<c->nrows[k]; l++) {
219:       col = c->columnsforrow[k][l];
220:       if (col >= cstart && col < cend) {
221:         /* column is in diagonal block of matrix */
222:         colb = col - cstart;
223:       } else {
224:         /* column  is in "off-processor" part */
225: #if defined (PETSC_USE_CTABLE)
226:         PetscTableFind(aij->colmap,col+1,&colb);
227:         colb --;
228: #else
229:         colb = aij->colmap[col] - 1;
230: #endif
231:         colb += cend - cstart;
232:       }
233:       c->vscaleforrow[k][l] = colb;
234:     }
235:   }
236:   ISColoringRestoreIS(iscoloring,&isa);

238:   PetscFree(rowhit);
239:   PetscFree(columnsforrow);
240:   PetscFree(ncolsonproc);
241:   MatRestoreColumnIJ_SeqAIJ(aij->A,0,PETSC_FALSE,&ncols,&A_ci,&A_cj,&done);
242:   MatRestoreColumnIJ_SeqAIJ(aij->B,0,PETSC_FALSE,&ncols,&B_ci,&B_cj,&done);
243:   return(0);
244: }