Actual source code: umfpack.c
1: /*$Id: umfpack.c,v 1.10 2001/08/15 15:56:50 bsmith Exp $*/
3: /*
4: Provides an interface to the UMFPACK sparse solver
5: */
7: #include src/mat/impls/aij/seq/aij.h
9: EXTERN_C_BEGIN
10: #include "umfpack.h"
11: EXTERN_C_END
13: typedef struct {
14: void *Symbolic, *Numeric;
15: double Info[UMFPACK_INFO], Control[UMFPACK_CONTROL],*W;
16: int *Wi,*ai,*aj,*perm_c;
17: PetscScalar *av;
18: MatStructure flg;
19: PetscTruth PetscMatOdering;
21: /* A few function pointers for inheritance */
22: int (*MatDuplicate)(Mat,MatDuplicateOption,Mat*);
23: int (*MatView)(Mat,PetscViewer);
24: int (*MatAssemblyEnd)(Mat,MatAssemblyType);
25: int (*MatLUFactorSymbolic)(Mat,IS,IS,MatFactorInfo*,Mat*);
26: int (*MatDestroy)(Mat);
27:
28: /* Flag to clean up UMFPACK objects during Destroy */
29: PetscTruth CleanUpUMFPACK;
30: } Mat_UMFPACK;
32: EXTERN int MatDuplicate_UMFPACK(Mat,MatDuplicateOption,Mat*);
34: EXTERN_C_BEGIN
37: int MatConvert_UMFPACK_SeqAIJ(Mat A,const MatType type,Mat *newmat) {
38: /* This routine is only called to convert an unfactored PETSc-UMFPACK matrix */
39: /* to its base PETSc type, so we will ignore 'MatType type'. */
40: int ierr;
41: Mat B=*newmat;
42: Mat_UMFPACK *lu=(Mat_UMFPACK*)A->spptr;
45: if (B != A) {
46: /* This routine was inherited from SeqAIJ. */
47: MatDuplicate(A,MAT_COPY_VALUES,&B);
48: }
49: /* Reset the original function pointers */
50: A->ops->duplicate = lu->MatDuplicate;
51: A->ops->view = lu->MatView;
52: A->ops->assemblyend = lu->MatAssemblyEnd;
53: A->ops->lufactorsymbolic = lu->MatLUFactorSymbolic;
54: A->ops->destroy = lu->MatDestroy;
55:
56: PetscFree(lu);
57: PetscObjectChangeTypeName((PetscObject)B,MATSEQAIJ);
58: *newmat = B;
59: return(0);
60: }
61: EXTERN_C_END
65: int MatDestroy_UMFPACK(Mat A) {
66: int ierr;
67: Mat_UMFPACK *lu=(Mat_UMFPACK*)A->spptr;
70: if (lu->CleanUpUMFPACK) {
71: umfpack_di_free_symbolic(&lu->Symbolic) ;
72: umfpack_di_free_numeric(&lu->Numeric) ;
73: PetscFree(lu->Wi);
74: PetscFree(lu->W);
76: if (lu->PetscMatOdering) {
77: PetscFree(lu->perm_c);
78: }
79: }
80: MatConvert_UMFPACK_SeqAIJ(A,MATSEQAIJ,&A);
81: (*A->ops->destroy)(A);
82: return(0);
83: }
87: int MatSolve_UMFPACK(Mat A,Vec b,Vec x) {
88: Mat_UMFPACK *lu = (Mat_UMFPACK*)A->spptr;
89: PetscScalar *av=lu->av,*ba,*xa;
90: int ierr,*ai=lu->ai,*aj=lu->aj,status;
91:
93: /* solve Ax = b by umfpack_di_wsolve */
94: /* ----------------------------------*/
95: VecGetArray(b,&ba);
96: VecGetArray(x,&xa);
98: status = umfpack_di_wsolve(UMFPACK_At,ai,aj,av,xa,ba,lu->Numeric,lu->Control,lu->Info,lu->Wi,lu->W);
99: umfpack_di_report_info(lu->Control, lu->Info);
100: if (status < 0){
101: umfpack_di_report_status(lu->Control, status) ;
102: SETERRQ(1,"umfpack_di_wsolve failed") ;
103: }
104:
105: VecRestoreArray(b,&ba);
106: VecRestoreArray(x,&xa);
107: return(0);
108: }
112: int MatLUFactorNumeric_UMFPACK(Mat A,Mat *F) {
113: Mat_UMFPACK *lu=(Mat_UMFPACK*)(*F)->spptr;
114: int *ai=lu->ai,*aj=lu->aj,m=A->m,status,ierr;
115: PetscScalar *av=lu->av;
118: /* numeric factorization of A' */
119: /* ----------------------------*/
120: status = umfpack_di_numeric (ai,aj,av,lu->Symbolic,&lu->Numeric,lu->Control,lu->Info) ;
121: if (status < 0) SETERRQ(1,"umfpack_di_numeric failed");
122: /* report numeric factorization of A' when Control[PRL] > 3 */
123: (void) umfpack_di_report_numeric (lu->Numeric, lu->Control) ;
125: if (lu->flg == DIFFERENT_NONZERO_PATTERN){ /* first numeric factorization */
126: /* allocate working space to be used by Solve */
127: PetscMalloc(m * sizeof(int), &lu->Wi);
128: PetscMalloc(5*m * sizeof(double), &lu->W);
130: lu->flg = SAME_NONZERO_PATTERN;
131: }
133: return(0);
134: }
136: /*
137: Note the r permutation is ignored
138: */
141: int MatLUFactorSymbolic_UMFPACK(Mat A,IS r,IS c,MatFactorInfo *info,Mat *F) {
142: Mat B;
143: Mat_SeqAIJ *mat=(Mat_SeqAIJ*)A->data;
144: Mat_UMFPACK *lu;
145: int ierr,m=A->m,n=A->n,*ai=mat->i,*aj=mat->j,status,*ca;
146: PetscScalar *av=mat->a;
147:
149: /* Create the factorization matrix F */
150: MatCreate(A->comm,PETSC_DECIDE,PETSC_DECIDE,m,n,&B);
151: MatSetType(B,A->type_name);
152: MatSeqAIJSetPreallocation(B,0,PETSC_NULL);
153:
154: B->ops->lufactornumeric = MatLUFactorNumeric_UMFPACK;
155: B->ops->solve = MatSolve_UMFPACK;
156: B->factor = FACTOR_LU;
157: B->assembled = PETSC_TRUE; /* required by -ksp_view */
159: lu = (Mat_UMFPACK*)(B->spptr);
160:
161: /* initializations */
162: /* ------------------------------------------------*/
163: /* get the default control parameters */
164: umfpack_di_defaults (lu->Control) ;
165: lu->perm_c = PETSC_NULL; /* use defaul UMFPACK col permutation */
167: PetscOptionsBegin(A->comm,A->prefix,"UMFPACK Options","Mat");
168: /* Control parameters used by reporting routiones */
169: PetscOptionsReal("-mat_umfpack_prl","Control[UMFPACK_PRL]","None",lu->Control[UMFPACK_PRL],&lu->Control[UMFPACK_PRL],PETSC_NULL);
171: /* Control parameters for symbolic factorization */
172: PetscOptionsReal("-mat_umfpack_dense_col","Control[UMFPACK_DENSE_COL]","None",lu->Control[UMFPACK_DENSE_COL],&lu->Control[UMFPACK_DENSE_COL],PETSC_NULL);
173: PetscOptionsReal("-mat_umfpack_dense_row","Control[UMFPACK_DENSE_ROW]","None",lu->Control[UMFPACK_DENSE_ROW],&lu->Control[UMFPACK_DENSE_ROW],PETSC_NULL);
174: PetscOptionsReal("-mat_umfpack_block_size","Control[UMFPACK_BLOCK_SIZE]","None",lu->Control[UMFPACK_BLOCK_SIZE],&lu->Control[UMFPACK_BLOCK_SIZE],PETSC_NULL);
176: /* Control parameters used by numeric factorization */
177: PetscOptionsReal("-mat_umfpack_pivot_tolerance","Control[UMFPACK_PIVOT_TOLERANCE]","None",lu->Control[UMFPACK_PIVOT_TOLERANCE],&lu->Control[UMFPACK_PIVOT_TOLERANCE],PETSC_NULL);
178: #if !defined(PETSC_HAVE_UMFPACK_41_OR_NEWER)
179: PetscOptionsReal("-mat_umfpack_relaxed_amalgamation","Control[UMFPACK_RELAXED_AMALGAMATION]","None",lu->Control[UMFPACK_RELAXED_AMALGAMATION],&lu->Control[UMFPACK_RELAXED_AMALGAMATION],PETSC_NULL);
180: PetscOptionsReal("-mat_umfpack_relaxed2_amalgamation","Control[UMFPACK_RELAXED2_AMALGAMATION]","None",lu->Control[UMFPACK_RELAXED2_AMALGAMATION],&lu->Control[UMFPACK_RELAXED2_AMALGAMATION],PETSC_NULL);
181: PetscOptionsReal("-mat_umfpack_relaxed3_amalgamation","Control[UMFPACK_RELAXED3_AMALGAMATION]","None",lu->Control[UMFPACK_RELAXED3_AMALGAMATION],&lu->Control[UMFPACK_RELAXED3_AMALGAMATION],PETSC_NULL);
182: #endif
183: PetscOptionsReal("-mat_umfpack_alloc_init","Control[UMFPACK_ALLOC_INIT]","None",lu->Control[UMFPACK_ALLOC_INIT],&lu->Control[UMFPACK_ALLOC_INIT],PETSC_NULL);
185: /* Control parameters used by solve */
186: PetscOptionsReal("-mat_umfpack_irstep","Control[UMFPACK_IRSTEP]","None",lu->Control[UMFPACK_IRSTEP],&lu->Control[UMFPACK_IRSTEP],PETSC_NULL);
187:
188: /* use Petsc mat ordering (notice size is for the transpose) */
189: PetscOptionsHasName(PETSC_NULL,"-pc_lu_mat_ordering_type",&lu->PetscMatOdering);
190: if (lu->PetscMatOdering) {
191: ISGetIndices(c,&ca);
192: PetscMalloc(A->m*sizeof(int),&lu->perm_c);
193: PetscMemcpy(lu->perm_c,ca,A->m*sizeof(int));
194: ISRestoreIndices(c,&ca);
195: }
196: PetscOptionsEnd();
198: /* print the control parameters */
199: if( lu->Control[UMFPACK_PRL] > 1 ) umfpack_di_report_control (lu->Control);
201: /* symbolic factorization of A' */
202: /* ---------------------------------------------------------------------- */
203: #if defined(PETSC_HAVE_UMFPACK_41_OR_NEWER)
204: status = umfpack_di_qsymbolic(n,m,ai,aj,PETSC_NULL,lu->perm_c,&lu->Symbolic,lu->Control,lu->Info) ;
205: #else
206: status = umfpack_di_qsymbolic(n,m,ai,aj,lu->perm_c,&lu->Symbolic,lu->Control,lu->Info) ;
207: #endif
208: if (status < 0){
209: umfpack_di_report_info(lu->Control, lu->Info) ;
210: umfpack_di_report_status(lu->Control, status) ;
211: SETERRQ(1,"umfpack_di_symbolic failed");
212: }
213: /* report sumbolic factorization of A' when Control[PRL] > 3 */
214: (void) umfpack_di_report_symbolic(lu->Symbolic, lu->Control) ;
216: lu->flg = DIFFERENT_NONZERO_PATTERN;
217: lu->ai = ai;
218: lu->aj = aj;
219: lu->av = av;
220: lu->CleanUpUMFPACK = PETSC_TRUE;
221: *F = B;
222: return(0);
223: }
227: int MatAssemblyEnd_UMFPACK(Mat A,MatAssemblyType mode) {
228: int ierr;
229: Mat_UMFPACK *lu=(Mat_UMFPACK*)(A->spptr);
232: (*lu->MatAssemblyEnd)(A,mode);
233: lu->MatLUFactorSymbolic = A->ops->lufactorsymbolic;
234: A->ops->lufactorsymbolic = MatLUFactorSymbolic_UMFPACK;
235: return(0);
236: }
238: /* used by -ksp_view */
241: int MatFactorInfo_UMFPACK(Mat A,PetscViewer viewer) {
242: Mat_UMFPACK *lu= (Mat_UMFPACK*)A->spptr;
243: int ierr;
246: /* check if matrix is UMFPACK type */
247: if (A->ops->solve != MatSolve_UMFPACK) return(0);
249: PetscViewerASCIIPrintf(viewer,"UMFPACK run parameters:\n");
250: /* Control parameters used by reporting routiones */
251: PetscViewerASCIIPrintf(viewer," Control[UMFPACK_PRL]: %g\n",lu->Control[UMFPACK_PRL]);
253: /* Control parameters used by symbolic factorization */
254: PetscViewerASCIIPrintf(viewer," Control[UMFPACK_DENSE_COL]: %g\n",lu->Control[UMFPACK_DENSE_COL]);
255: PetscViewerASCIIPrintf(viewer," Control[UMFPACK_DENSE_ROW]: %g\n",lu->Control[UMFPACK_DENSE_ROW]);
256: PetscViewerASCIIPrintf(viewer," Control[UMFPACK_BLOCK_SIZE]: %g\n",lu->Control[UMFPACK_BLOCK_SIZE]);
258: /* Control parameters used by numeric factorization */
259: PetscViewerASCIIPrintf(viewer," Control[UMFPACK_PIVOT_TOLERANCE]: %g\n",lu->Control[UMFPACK_PIVOT_TOLERANCE]);
260: #if !defined(PETSC_HAVE_UMFPACK_41_OR_NEWER)
261: PetscViewerASCIIPrintf(viewer," Control[UMFPACK_RELAXED_AMALGAMATION]: %g\n",lu->Control[UMFPACK_RELAXED_AMALGAMATION]);
262: PetscViewerASCIIPrintf(viewer," Control[UMFPACK_RELAXED2_AMALGAMATION]: %g\n",lu->Control[UMFPACK_RELAXED2_AMALGAMATION]);
263: PetscViewerASCIIPrintf(viewer," Control[UMFPACK_RELAXED3_AMALGAMATION]: %g\n",lu->Control[UMFPACK_RELAXED3_AMALGAMATION]);
264: #endif
265: PetscViewerASCIIPrintf(viewer," Control[UMFPACK_ALLOC_INIT]: %g\n",lu->Control[UMFPACK_ALLOC_INIT]);
267: /* Control parameters used by solve */
268: PetscViewerASCIIPrintf(viewer," Control[UMFPACK_IRSTEP]: %g\n",lu->Control[UMFPACK_IRSTEP]);
270: /* mat ordering */
271: if(!lu->PetscMatOdering) PetscViewerASCIIPrintf(viewer," UMFPACK default matrix ordering is used (not the PETSc matrix ordering) \n");
273: return(0);
274: }
278: int MatView_UMFPACK(Mat A,PetscViewer viewer) {
279: int ierr;
280: PetscTruth isascii;
281: PetscViewerFormat format;
282: Mat_UMFPACK *lu=(Mat_UMFPACK*)(A->spptr);
285: (*lu->MatView)(A,viewer);
287: PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_ASCII,&isascii);
288: if (isascii) {
289: PetscViewerGetFormat(viewer,&format);
290: if (format == PETSC_VIEWER_ASCII_FACTOR_INFO) {
291: MatFactorInfo_UMFPACK(A,viewer);
292: }
293: }
294: return(0);
295: }
297: EXTERN_C_BEGIN
300: int MatConvert_SeqAIJ_UMFPACK(Mat A,const MatType type,Mat *newmat) {
301: /* This routine is only called to convert to MATUMFPACK */
302: /* from MATSEQAIJ, so we will ignore 'MatType type'. */
303: int ierr;
304: Mat B=*newmat;
305: Mat_UMFPACK *lu;
308: if (B != A) {
309: MatDuplicate(A,MAT_COPY_VALUES,&B);
310: }
312: PetscNew(Mat_UMFPACK,&lu);
313: lu->MatDuplicate = A->ops->duplicate;
314: lu->MatView = A->ops->view;
315: lu->MatAssemblyEnd = A->ops->assemblyend;
316: lu->MatLUFactorSymbolic = A->ops->lufactorsymbolic;
317: lu->MatDestroy = A->ops->destroy;
318: lu->CleanUpUMFPACK = PETSC_FALSE;
320: B->spptr = (void*)lu;
321: B->ops->duplicate = MatDuplicate_UMFPACK;
322: B->ops->view = MatView_UMFPACK;
323: B->ops->assemblyend = MatAssemblyEnd_UMFPACK;
324: B->ops->lufactorsymbolic = MatLUFactorSymbolic_UMFPACK;
325: B->ops->destroy = MatDestroy_UMFPACK;
327: PetscObjectComposeFunctionDynamic((PetscObject)B,"MatConvert_seqaij_umfpack_C",
328: "MatConvert_SeqAIJ_UMFPACK",MatConvert_SeqAIJ_UMFPACK);
329: PetscObjectComposeFunctionDynamic((PetscObject)B,"MatConvert_umfpack_seqaij_C",
330: "MatConvert_UMFPACK_SeqAIJ",MatConvert_UMFPACK_SeqAIJ);
331: PetscLogInfo(0,"Using UMFPACK for SeqAIJ LU factorization and solves.");
332: PetscObjectChangeTypeName((PetscObject)B,MATUMFPACK);
333: *newmat = B;
334: return(0);
335: }
336: EXTERN_C_END
340: int MatDuplicate_UMFPACK(Mat A, MatDuplicateOption op, Mat *M) {
341: int ierr;
342: Mat_UMFPACK *lu=(Mat_UMFPACK*)A->spptr;
345: (*lu->MatDuplicate)(A,op,M);
346: PetscMemcpy((*M)->spptr,lu,sizeof(Mat_UMFPACK));
347: return(0);
348: }
350: /*MC
351: MATUMFPACK - MATUMFPACK = "umfpack" - A matrix type providing direct solvers (LU) for sequential matrices
352: via the external package UMFPACK.
354: If UMFPACK is installed (see the manual for
355: instructions on how to declare the existence of external packages),
356: a matrix type can be constructed which invokes UMFPACK solvers.
357: After calling MatCreate(...,A), simply call MatSetType(A,UMFPACK).
358: This matrix type is only supported for double precision real.
360: This matrix inherits from MATSEQAIJ. As a result, MatSeqAIJSetPreallocation is
361: supported for this matrix type. One can also call MatConvert for an inplace conversion to or from
362: the MATSEQAIJ type without data copy.
364: Consult UMFPACK documentation for more information about the Control parameters
365: which correspond to the options database keys below.
367: Options Database Keys:
368: + -mat_type umfpack - sets the matrix type to "umfpack" during a call to MatSetFromOptions()
369: . -mat_umfpack_prl - UMFPACK print level: Control[UMFPACK_PRL]
370: . -mat_umfpack_dense_col <alpha_c> - UMFPACK dense column threshold: Control[UMFPACK_DENSE_COL]
371: . -mat_umfpack_block_size <bs> - UMFPACK block size for BLAS-Level 3 calls: Control[UMFPACK_BLOCK_SIZE]
372: . -mat_umfpack_pivot_tolerance <delta> - UMFPACK partial pivot tolerance: Control[UMFPACK_PIVOT_TOLERANCE]
373: . -mat_umfpack_alloc_init <delta> - UMFPACK factorized matrix allocation modifier: Control[UMFPACK_ALLOC_INIT]
374: - -mat_umfpack_irstep <maxit> - UMFPACK maximum number of iterative refinement steps: Control[UMFPACK_IRSTEP]
376: Level: beginner
378: .seealso: PCLU
379: M*/
381: EXTERN_C_BEGIN
384: int MatCreate_UMFPACK(Mat A) {
385: int ierr;
388: /* Change type name before calling MatSetType to force proper construction of SeqAIJ and UMFPACK types */
389: PetscObjectChangeTypeName((PetscObject)A,MATUMFPACK);
390: MatSetType(A,MATSEQAIJ);
391: MatConvert_SeqAIJ_UMFPACK(A,MATUMFPACK,&A);
392: return(0);
393: }
394: EXTERN_C_END