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: }