Actual source code: sorder.c

  1: #define PETSCMAT_DLL

  3: /*
  4:      Provides the code that allows PETSc users to register their own
  5:   sequential matrix Ordering routines.
  6: */
 7:  #include private/matimpl.h
 8:  #include petscmat.h

 10: PetscFList      MatOrderingList = 0;
 11: PetscTruth MatOrderingRegisterAllCalled = PETSC_FALSE;

 13: EXTERN PetscErrorCode MatOrdering_Flow_SeqAIJ(Mat,const MatOrderingType,IS *,IS *);

 17: PetscErrorCode MatOrdering_Flow(Mat mat,const MatOrderingType type,IS *irow,IS *icol)
 18: {
 20:   SETERRQ(PETSC_ERR_SUP,"Cannot do default flow ordering for matrix type");
 21: #if !defined(PETSC_USE_DEBUG)
 22:   return(0);
 23: #endif
 24: }

 29: PetscErrorCode  MatOrdering_Natural(Mat mat,const MatOrderingType type,IS *irow,IS *icol)
 30: {
 32:   PetscInt       n,i,*ii;
 33:   PetscTruth     done;
 34:   MPI_Comm       comm;

 37:   PetscObjectGetComm((PetscObject)mat,&comm);
 38:   MatGetRowIJ(mat,0,PETSC_FALSE,PETSC_TRUE,&n,PETSC_NULL,PETSC_NULL,&done);
 39:   MatRestoreRowIJ(mat,0,PETSC_FALSE,PETSC_TRUE,&n,PETSC_NULL,PETSC_NULL,&done);
 40:   if (done) { /* matrix may be "compressed" in symbolic factorization, due to i-nodes or block storage */
 41:     /*
 42:       We actually create general index sets because this avoids mallocs to
 43:       to obtain the indices in the MatSolve() routines.
 44:       ISCreateStride(PETSC_COMM_SELF,n,0,1,irow);
 45:       ISCreateStride(PETSC_COMM_SELF,n,0,1,icol);
 46:     */
 47:     PetscMalloc(n*sizeof(PetscInt),&ii);
 48:     for (i=0; i<n; i++) ii[i] = i;
 49:     ISCreateGeneral(PETSC_COMM_SELF,n,ii,irow);
 50:     ISCreateGeneral(PETSC_COMM_SELF,n,ii,icol);
 51:     PetscFree(ii);
 52:   } else {
 53:     PetscInt start,end;

 55:     MatGetOwnershipRange(mat,&start,&end);
 56:     ISCreateStride(comm,end-start,start,1,irow);
 57:     ISCreateStride(comm,end-start,start,1,icol);
 58:   }
 59:   ISSetIdentity(*irow);
 60:   ISSetIdentity(*icol);
 61:   return(0);
 62: }

 66: /*
 67:      Orders the rows (and columns) by the lengths of the rows. 
 68:    This produces a symmetric Ordering but does not require a 
 69:    matrix with symmetric non-zero structure.
 70: */
 73: PetscErrorCode  MatOrdering_RowLength(Mat mat,const MatOrderingType type,IS *irow,IS *icol)
 74: {
 76:   PetscInt       n,*ia,*ja,*permr,*lens,i;
 77:   PetscTruth     done;

 80:   MatGetRowIJ(mat,0,PETSC_FALSE,PETSC_TRUE,&n,&ia,&ja,&done);
 81:   if (!done) SETERRQ(PETSC_ERR_SUP,"Cannot get rows for matrix");

 83:   PetscMalloc(2*n*sizeof(PetscInt),&lens);
 84:   permr = lens + n;
 85:   for (i=0; i<n; i++) {
 86:     lens[i]  = ia[i+1] - ia[i];
 87:     permr[i] = i;
 88:   }
 89:   MatRestoreRowIJ(mat,0,PETSC_FALSE,PETSC_TRUE,&n,&ia,&ja,&done);

 91:   PetscSortIntWithPermutation(n,lens,permr);

 93:   ISCreateGeneral(PETSC_COMM_SELF,n,permr,irow);
 94:   ISCreateGeneral(PETSC_COMM_SELF,n,permr,icol);
 95:   PetscFree(lens);
 96:   return(0);
 97: }

102: PetscErrorCode  MatOrderingRegister(const char sname[],const char path[],const char name[],PetscErrorCode (*function)(Mat,const MatOrderingType,IS*,IS*))
103: {
105:   char           fullname[PETSC_MAX_PATH_LEN];

108:   PetscFListConcat(path,name,fullname);
109:   PetscFListAdd(&MatOrderingList,sname,fullname,(void (*)(void))function);
110:   return(0);
111: }

115: /*@
116:    MatOrderingRegisterDestroy - Frees the list of ordering routines.

118:    Not collective

120:    Level: developer
121:    
122: .keywords: matrix, register, destroy

124: .seealso: MatOrderingRegisterDynamic(), MatOrderingRegisterAll()
125: @*/
126: PetscErrorCode  MatOrderingRegisterDestroy(void)
127: {

131:   PetscFListDestroy(&MatOrderingList);
132:   MatOrderingRegisterAllCalled = PETSC_FALSE;
133:   return(0);
134: }

136:  #include ../src/mat/impls/aij/mpi/mpiaij.h
139: /*@C
140:    MatGetOrdering - Gets a reordering for a matrix to reduce fill or to
141:    improve numerical stability of LU factorization.

143:    Collective on Mat

145:    Input Parameters:
146: +  mat - the matrix
147: -  type - type of reordering, one of the following:
148: $      MATORDERING_NATURAL - Natural
149: $      MATORDERING_ND - Nested Dissection
150: $      MATORDERING_1WD - One-way Dissection
151: $      MATORDERING_RCM - Reverse Cuthill-McKee
152: $      MATORDERING_QMD - Quotient Minimum Degree

154:    Output Parameters:
155: +  rperm - row permutation indices
156: -  cperm - column permutation indices


159:    Options Database Key:
160: . -mat_view_ordering_draw - plots matrix nonzero structure in new ordering

162:    Level: intermediate
163:    
164:    Notes:
165:       This DOES NOT actually reorder the matrix; it merely returns two index sets
166:    that define a reordering. This is usually not used directly, rather use the 
167:    options PCFactorSetMatOrderingType()

169:    The user can define additional orderings; see MatOrderingRegisterDynamic().

171: .keywords: matrix, set, ordering, factorization, direct, ILU, LU,
172:            fill, reordering, natural, Nested Dissection,
173:            One-way Dissection, Cholesky, Reverse Cuthill-McKee, 
174:            Quotient Minimum Degree

176: .seealso:   MatOrderingRegisterDynamic(), PCFactorSetMatOrderingType()
177: @*/
178: PetscErrorCode  MatGetOrdering(Mat mat,const MatOrderingType type,IS *rperm,IS *cperm)
179: {
181:   PetscInt       mmat,nmat,mis,m;
182:   PetscErrorCode (*r)(Mat,const MatOrderingType,IS*,IS*);
183:   PetscTruth     flg,isseqdense,ismpidense,ismpiaij,ismpibaij,ismpisbaij;

189:   if (!mat->assembled) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
190:   if (mat->factor) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");

192:   /* this chunk of code is REALLY bad, should maybe get the ordering from the factor matrix,
193:      then those that don't support orderings will handle their cases themselfs. */
194:   PetscTypeCompare((PetscObject)mat,MATSEQDENSE,&isseqdense);
195:   PetscTypeCompare((PetscObject)mat,MATMPIDENSE,&ismpidense);
196:   PetscTypeCompare((PetscObject)mat,MATMPIAIJ,&ismpiaij);
197:   PetscTypeCompare((PetscObject)mat,MATMPIBAIJ,&ismpibaij);
198:   PetscTypeCompare((PetscObject)mat,MATMPISBAIJ,&ismpisbaij);
199:   if (isseqdense || ismpidense || ismpiaij || ismpibaij || ismpisbaij) {
200:     MatGetLocalSize(mat,&m,PETSC_NULL);
201:     /*
202:        Dense matrices only give natural ordering
203:     */
204:     ISCreateStride(PETSC_COMM_SELF,0,m,1,cperm);
205:     ISCreateStride(PETSC_COMM_SELF,0,m,1,rperm);
206:     ISSetIdentity(*cperm);
207:     ISSetIdentity(*rperm);
208:     ISSetPermutation(*rperm);
209:     ISSetPermutation(*cperm);
210:     return(0);
211:   }

213:   if (!mat->rmap->N) { /* matrix has zero rows */
214:     ISCreateStride(PETSC_COMM_SELF,0,0,1,cperm);
215:     ISCreateStride(PETSC_COMM_SELF,0,0,1,rperm);
216:     ISSetIdentity(*cperm);
217:     ISSetIdentity(*rperm);
218:     ISSetPermutation(*rperm);
219:     ISSetPermutation(*cperm);
220:     return(0);
221:   }
222: 
223:   MatGetLocalSize(mat,&mmat,&nmat);
224:   if (mmat != nmat) SETERRQ2(PETSC_ERR_ARG_WRONG,"Must be square matrix, rows %D columns %D",mmat,nmat);

226:   if (!MatOrderingRegisterAllCalled) {MatOrderingRegisterAll(PETSC_NULL);}
227:   PetscFListFind(MatOrderingList,((PetscObject)mat)->comm,type,(void (**)(void)) &r);
228:   if (!r) {SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,"Unknown or unregistered type: %s",type);}

230:   PetscLogEventBegin(MAT_GetOrdering,mat,0,0,0);
231:   (*r)(mat,type,rperm,cperm);
232:   ISSetPermutation(*rperm);
233:   ISSetPermutation(*cperm);
234:   /* Adjust for inode (reduced matrix ordering) only if row permutation is smaller the matrix size */
235:   ISGetLocalSize(*rperm,&mis);
236:   if (mmat > mis) {MatInodeAdjustForInodes(mat,rperm,cperm);}
237:   PetscLogEventEnd(MAT_GetOrdering,mat,0,0,0);

239:   PetscOptionsHasName(((PetscObject)mat)->prefix,"-mat_view_ordering_draw",&flg);
240:   if (flg) {
241:     Mat tmat;
242:     PetscOptionsHasName(((PetscObject)mat)->prefix,"-mat_view_contour",&flg);
243:     if (flg) {
244:       PetscViewerPushFormat(PETSC_VIEWER_DRAW_(((PetscObject)mat)->comm),PETSC_VIEWER_DRAW_CONTOUR);
245:     }
246:     MatPermute(mat,*rperm,*cperm,&tmat);
247:     MatView(tmat,PETSC_VIEWER_DRAW_(((PetscObject)mat)->comm));
248:     if (flg) {
249:       PetscViewerPopFormat(PETSC_VIEWER_DRAW_(((PetscObject)mat)->comm));
250:     }
251:     MatDestroy(tmat);
252:   }

254:   return(0);
255: }

259: PetscErrorCode MatGetOrderingList(PetscFList *list)
260: {
262:   *list = MatOrderingList;
263:   return(0);
264: }