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:   PetscMalloc2(n,PetscInt,&lens,n,PetscInt,&permr);
 84:   for (i=0; i<n; i++) {
 85:     lens[i]  = ia[i+1] - ia[i];
 86:     permr[i] = i;
 87:   }
 88:   MatRestoreRowIJ(mat,0,PETSC_FALSE,PETSC_TRUE,&n,&ia,&ja,&done);

 90:   PetscSortIntWithPermutation(n,lens,permr);

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

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

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

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

117:    Not collective

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

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

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

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

142:    Collective on Mat

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

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


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

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

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

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

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

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

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

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

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

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

238:   PetscOptionsGetTruth(((PetscObject)mat)->prefix,"-mat_view_ordering_draw",&flg,PETSC_NULL);
239:   if (flg) {
240:     Mat tmat;
241:     flg  = PETSC_FALSE;
242:     PetscOptionsGetTruth(((PetscObject)mat)->prefix,"-mat_view_contour",&flg,PETSC_NULL);
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: }