Actual source code: umfpack.c
1: #define PETSCMAT_DLL
3: /*
4: Provides an interface to the UMFPACKv4.3 sparse solver
5: */
7: #include src/mat/impls/aij/seq/aij.h
10: #include "umfpack.h"
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: PetscErrorCode (*MatDuplicate)(Mat,MatDuplicateOption,Mat*);
23: PetscErrorCode (*MatView)(Mat,PetscViewer);
24: PetscErrorCode (*MatAssemblyEnd)(Mat,MatAssemblyType);
25: PetscErrorCode (*MatLUFactorSymbolic)(Mat,IS,IS,MatFactorInfo*,Mat*);
26: PetscErrorCode (*MatDestroy)(Mat);
27:
28: /* Flag to clean up UMFPACK objects during Destroy */
29: PetscTruth CleanUpUMFPACK;
30: } Mat_UMFPACK;
32: EXTERN PetscErrorCode MatDuplicate_UMFPACK(Mat,MatDuplicateOption,Mat*);
37: PetscErrorCode PETSCMAT_DLLEXPORT MatConvert_UMFPACK_SeqAIJ(Mat A,MatType type,MatReuse reuse,Mat *newmat)
38: {
39: /* This routine is only called to convert an unfactored PETSc-UMFPACK matrix */
40: /* to its base PETSc type, so we will ignore 'MatType type'. */
42: Mat B=*newmat;
43: Mat_UMFPACK *lu=(Mat_UMFPACK*)A->spptr;
46: if (reuse == MAT_INITIAL_MATRIX) {
47: MatDuplicate(A,MAT_COPY_VALUES,&B);
48: }
49: /* Reset the original function pointers */
50: B->ops->duplicate = lu->MatDuplicate;
51: B->ops->view = lu->MatView;
52: B->ops->assemblyend = lu->MatAssemblyEnd;
53: B->ops->lufactorsymbolic = lu->MatLUFactorSymbolic;
54: B->ops->destroy = lu->MatDestroy;
55:
56: PetscFree(lu);
58: PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_umfpack_C","",PETSC_NULL);
59: PetscObjectComposeFunction((PetscObject)B,"MatConvert_umfpack_seqaij_C","",PETSC_NULL);
61: PetscObjectChangeTypeName((PetscObject)B,MATSEQAIJ);
62: *newmat = B;
63: return(0);
64: }
69: PetscErrorCode MatDestroy_UMFPACK(Mat A)
70: {
72: Mat_UMFPACK *lu=(Mat_UMFPACK*)A->spptr;
75: if (lu->CleanUpUMFPACK) {
76: umfpack_di_free_symbolic(&lu->Symbolic);
77: umfpack_di_free_numeric(&lu->Numeric);
78: PetscFree(lu->Wi);
79: PetscFree(lu->W);
80: if (lu->PetscMatOdering) {
81: PetscFree(lu->perm_c);
82: }
83: }
84: MatConvert_UMFPACK_SeqAIJ(A,MATSEQAIJ,MAT_REUSE_MATRIX,&A);
85: (*A->ops->destroy)(A);
86: return(0);
87: }
91: PetscErrorCode MatSolve_UMFPACK(Mat A,Vec b,Vec x)
92: {
93: Mat_UMFPACK *lu = (Mat_UMFPACK*)A->spptr;
94: PetscScalar *av=lu->av,*ba,*xa;
96: int *ai=lu->ai,*aj=lu->aj,status;
97:
99: /* solve Ax = b by umfpack_di_wsolve */
100: /* ----------------------------------*/
101: VecGetArray(b,&ba);
102: VecGetArray(x,&xa);
104: status = umfpack_di_wsolve(UMFPACK_At,ai,aj,av,xa,ba,lu->Numeric,lu->Control,lu->Info,lu->Wi,lu->W);
105: umfpack_di_report_info(lu->Control, lu->Info);
106: if (status < 0){
107: umfpack_di_report_status(lu->Control, status);
108: SETERRQ(PETSC_ERR_LIB,"umfpack_di_wsolve failed");
109: }
110:
111: VecRestoreArray(b,&ba);
112: VecRestoreArray(x,&xa);
114: return(0);
115: }
119: PetscErrorCode MatLUFactorNumeric_UMFPACK(Mat A,MatFactorInfo *info,Mat *F)
120: {
121: Mat_UMFPACK *lu=(Mat_UMFPACK*)(*F)->spptr;
123: int *ai=lu->ai,*aj=lu->aj,m=A->m,status;
124: PetscScalar *av=lu->av;
127: /* numeric factorization of A' */
128: /* ----------------------------*/
129: if (lu->flg == SAME_NONZERO_PATTERN && lu->Numeric){
130: umfpack_di_free_numeric(&lu->Numeric);
131: }
132: status = umfpack_di_numeric (ai,aj,av,lu->Symbolic,&lu->Numeric,lu->Control,lu->Info);
133: if (status < 0) SETERRQ(PETSC_ERR_LIB,"umfpack_di_numeric failed");
134: /* report numeric factorization of A' when Control[PRL] > 3 */
135: (void) umfpack_di_report_numeric (lu->Numeric, lu->Control);
137: if (lu->flg == DIFFERENT_NONZERO_PATTERN){ /* first numeric factorization */
138: /* allocate working space to be used by Solve */
139: PetscMalloc(m * sizeof(int), &lu->Wi);
140: PetscMalloc(5*m * sizeof(double), &lu->W);
141: }
142: lu->flg = SAME_NONZERO_PATTERN;
143: lu->CleanUpUMFPACK = PETSC_TRUE;
144: return(0);
145: }
147: /*
148: Note the r permutation is ignored
149: */
152: PetscErrorCode MatLUFactorSymbolic_UMFPACK(Mat A,IS r,IS c,MatFactorInfo *info,Mat *F)
153: {
154: Mat B;
155: Mat_SeqAIJ *mat=(Mat_SeqAIJ*)A->data;
156: Mat_UMFPACK *lu;
158: int m=A->m,n=A->n,*ai=mat->i,*aj=mat->j,status,*ra,idx;
159: PetscScalar *av=mat->a;
160: const char *strategy[]={"AUTO","UNSYMMETRIC","SYMMETRIC","2BY2"},
161: *scale[]={"NONE","SUM","MAX"};
162: PetscTruth flg;
163:
165: /* Create the factorization matrix F */
166: MatCreate(A->comm,&B);
167: MatSetSizes(B,PETSC_DECIDE,PETSC_DECIDE,m,n);
168: MatSetType(B,A->type_name);
169: MatSeqAIJSetPreallocation(B,0,PETSC_NULL);
170:
171: B->ops->lufactornumeric = MatLUFactorNumeric_UMFPACK;
172: B->ops->solve = MatSolve_UMFPACK;
173: B->factor = FACTOR_LU;
174: B->assembled = PETSC_TRUE; /* required by -ksp_view */
176: lu = (Mat_UMFPACK*)(B->spptr);
177:
178: /* initializations */
179: /* ------------------------------------------------*/
180: /* get the default control parameters */
181: umfpack_di_defaults (lu->Control);
182: lu->perm_c = PETSC_NULL; /* use defaul UMFPACK col permutation */
183: lu->Control[UMFPACK_IRSTEP] = 0; /* max num of iterative refinement steps to attempt */
185: PetscOptionsBegin(A->comm,A->prefix,"UMFPACK Options","Mat");
186: /* Control parameters used by reporting routiones */
187: PetscOptionsReal("-mat_umfpack_prl","Control[UMFPACK_PRL]","None",lu->Control[UMFPACK_PRL],&lu->Control[UMFPACK_PRL],PETSC_NULL);
189: /* Control parameters for symbolic factorization */
190: PetscOptionsEList("-mat_umfpack_strategy","ordering and pivoting strategy","None",strategy,4,strategy[0],&idx,&flg);
191: if (flg) {
192: switch (idx){
193: case 0: lu->Control[UMFPACK_STRATEGY] = UMFPACK_STRATEGY_AUTO; break;
194: case 1: lu->Control[UMFPACK_STRATEGY] = UMFPACK_STRATEGY_UNSYMMETRIC; break;
195: case 2: lu->Control[UMFPACK_STRATEGY] = UMFPACK_STRATEGY_SYMMETRIC; break;
196: case 3: lu->Control[UMFPACK_STRATEGY] = UMFPACK_STRATEGY_2BY2; break;
197: }
198: }
199: PetscOptionsReal("-mat_umfpack_dense_col","Control[UMFPACK_DENSE_COL]","None",lu->Control[UMFPACK_DENSE_COL],&lu->Control[UMFPACK_DENSE_COL],PETSC_NULL);
200: PetscOptionsReal("-mat_umfpack_dense_row","Control[UMFPACK_DENSE_ROW]","None",lu->Control[UMFPACK_DENSE_ROW],&lu->Control[UMFPACK_DENSE_ROW],PETSC_NULL);
201: PetscOptionsReal("-mat_umfpack_amd_dense","Control[UMFPACK_AMD_DENSE]","None",lu->Control[UMFPACK_AMD_DENSE],&lu->Control[UMFPACK_AMD_DENSE],PETSC_NULL);
202: PetscOptionsReal("-mat_umfpack_block_size","Control[UMFPACK_BLOCK_SIZE]","None",lu->Control[UMFPACK_BLOCK_SIZE],&lu->Control[UMFPACK_BLOCK_SIZE],PETSC_NULL);
203: PetscOptionsReal("-mat_umfpack_2by2_tolerance","Control[UMFPACK_2BY2_TOLERANCE]","None",lu->Control[UMFPACK_2BY2_TOLERANCE],&lu->Control[UMFPACK_2BY2_TOLERANCE],PETSC_NULL);
204: PetscOptionsReal("-mat_umfpack_fixq","Control[UMFPACK_FIXQ]","None",lu->Control[UMFPACK_FIXQ],&lu->Control[UMFPACK_FIXQ],PETSC_NULL);
205: PetscOptionsReal("-mat_umfpack_aggressive","Control[UMFPACK_AGGRESSIVE]","None",lu->Control[UMFPACK_AGGRESSIVE],&lu->Control[UMFPACK_AGGRESSIVE],PETSC_NULL);
207: /* Control parameters used by numeric factorization */
208: PetscOptionsReal("-mat_umfpack_pivot_tolerance","Control[UMFPACK_PIVOT_TOLERANCE]","None",lu->Control[UMFPACK_PIVOT_TOLERANCE],&lu->Control[UMFPACK_PIVOT_TOLERANCE],PETSC_NULL);
209: PetscOptionsReal("-mat_umfpack_sym_pivot_tolerance","Control[UMFPACK_SYM_PIVOT_TOLERANCE]","None",lu->Control[UMFPACK_SYM_PIVOT_TOLERANCE],&lu->Control[UMFPACK_SYM_PIVOT_TOLERANCE],PETSC_NULL);
210: PetscOptionsEList("-mat_umfpack_scale","Control[UMFPACK_SCALE]","None",scale,3,scale[0],&idx,&flg);
211: if (flg) {
212: switch (idx){
213: case 0: lu->Control[UMFPACK_SCALE] = UMFPACK_SCALE_NONE; break;
214: case 1: lu->Control[UMFPACK_SCALE] = UMFPACK_SCALE_SUM; break;
215: case 2: lu->Control[UMFPACK_SCALE] = UMFPACK_SCALE_MAX; break;
216: }
217: }
218: PetscOptionsReal("-mat_umfpack_alloc_init","Control[UMFPACK_ALLOC_INIT]","None",lu->Control[UMFPACK_ALLOC_INIT],&lu->Control[UMFPACK_ALLOC_INIT],PETSC_NULL);
219: PetscOptionsReal("-mat_umfpack_front_alloc_init","Control[UMFPACK_FRONT_ALLOC_INIT]","None",lu->Control[UMFPACK_FRONT_ALLOC_INIT],&lu->Control[UMFPACK_ALLOC_INIT],PETSC_NULL);
220: PetscOptionsReal("-mat_umfpack_droptol","Control[UMFPACK_DROPTOL]","None",lu->Control[UMFPACK_DROPTOL],&lu->Control[UMFPACK_DROPTOL],PETSC_NULL);
222: /* Control parameters used by solve */
223: PetscOptionsReal("-mat_umfpack_irstep","Control[UMFPACK_IRSTEP]","None",lu->Control[UMFPACK_IRSTEP],&lu->Control[UMFPACK_IRSTEP],PETSC_NULL);
224:
225: /* use Petsc mat ordering (note: size is for the transpose, and PETSc r = Umfpack perm_c) */
226: PetscOptionsHasName(PETSC_NULL,"-pc_lu_mat_ordering_type",&lu->PetscMatOdering);
227: if (lu->PetscMatOdering) {
228: ISGetIndices(r,&ra);
229: PetscMalloc(A->m*sizeof(int),&lu->perm_c);
230: PetscMemcpy(lu->perm_c,ra,A->m*sizeof(int));
231: ISRestoreIndices(r,&ra);
232: }
233: PetscOptionsEnd();
235: /* print the control parameters */
236: if( lu->Control[UMFPACK_PRL] > 1 ) umfpack_di_report_control (lu->Control);
238: /* symbolic factorization of A' */
239: /* ---------------------------------------------------------------------- */
240: if (lu->PetscMatOdering) { /* use Petsc row ordering */
241: status = umfpack_di_qsymbolic(n,m,ai,aj,av,lu->perm_c,&lu->Symbolic,lu->Control,lu->Info);
242: } else { /* use Umfpack col ordering */
243: status = umfpack_di_symbolic(n,m,ai,aj,av,&lu->Symbolic,lu->Control,lu->Info);
244: }
245: if (status < 0){
246: umfpack_di_report_info(lu->Control, lu->Info);
247: umfpack_di_report_status(lu->Control, status);
248: SETERRQ(PETSC_ERR_LIB,"umfpack_di_symbolic failed");
249: }
250: /* report sumbolic factorization of A' when Control[PRL] > 3 */
251: (void) umfpack_di_report_symbolic(lu->Symbolic, lu->Control);
253: lu->flg = DIFFERENT_NONZERO_PATTERN;
254: lu->ai = ai;
255: lu->aj = aj;
256: lu->av = av;
257: lu->CleanUpUMFPACK = PETSC_TRUE;
258: *F = B;
259: return(0);
260: }
264: PetscErrorCode MatAssemblyEnd_UMFPACK(Mat A,MatAssemblyType mode)
265: {
267: Mat_UMFPACK *lu=(Mat_UMFPACK*)(A->spptr);
270: (*lu->MatAssemblyEnd)(A,mode);
271: lu->MatLUFactorSymbolic = A->ops->lufactorsymbolic;
272: A->ops->lufactorsymbolic = MatLUFactorSymbolic_UMFPACK;
273: return(0);
274: }
276: /* used by -ksp_view */
279: PetscErrorCode MatFactorInfo_UMFPACK(Mat A,PetscViewer viewer)
280: {
281: Mat_UMFPACK *lu= (Mat_UMFPACK*)A->spptr;
285: /* check if matrix is UMFPACK type */
286: if (A->ops->solve != MatSolve_UMFPACK) return(0);
288: PetscViewerASCIIPrintf(viewer,"UMFPACK run parameters:\n");
289: /* Control parameters used by reporting routiones */
290: PetscViewerASCIIPrintf(viewer," Control[UMFPACK_PRL]: %g\n",lu->Control[UMFPACK_PRL]);
292: /* Control parameters used by symbolic factorization */
293: PetscViewerASCIIPrintf(viewer," Control[UMFPACK_STRATEGY]: %g\n",lu->Control[UMFPACK_STRATEGY]);
294: PetscViewerASCIIPrintf(viewer," Control[UMFPACK_DENSE_COL]: %g\n",lu->Control[UMFPACK_DENSE_COL]);
295: PetscViewerASCIIPrintf(viewer," Control[UMFPACK_DENSE_ROW]: %g\n",lu->Control[UMFPACK_DENSE_ROW]);
296: PetscViewerASCIIPrintf(viewer," Control[UMFPACK_AMD_DENSE]: %g\n",lu->Control[UMFPACK_AMD_DENSE]);
297: PetscViewerASCIIPrintf(viewer," Control[UMFPACK_BLOCK_SIZE]: %g\n",lu->Control[UMFPACK_BLOCK_SIZE]);
298: PetscViewerASCIIPrintf(viewer," Control[UMFPACK_2BY2_TOLERANCE]: %g\n",lu->Control[UMFPACK_2BY2_TOLERANCE]);
299: PetscViewerASCIIPrintf(viewer," Control[UMFPACK_FIXQ]: %g\n",lu->Control[UMFPACK_FIXQ]);
300: PetscViewerASCIIPrintf(viewer," Control[UMFPACK_AGGRESSIVE]: %g\n",lu->Control[UMFPACK_AGGRESSIVE]);
302: /* Control parameters used by numeric factorization */
303: PetscViewerASCIIPrintf(viewer," Control[UMFPACK_PIVOT_TOLERANCE]: %g\n",lu->Control[UMFPACK_PIVOT_TOLERANCE]);
304: PetscViewerASCIIPrintf(viewer," Control[UMFPACK_SYM_PIVOT_TOLERANCE]: %g\n",lu->Control[UMFPACK_SYM_PIVOT_TOLERANCE]);
305: PetscViewerASCIIPrintf(viewer," Control[UMFPACK_SCALE]: %g\n",lu->Control[UMFPACK_SCALE]);
306: PetscViewerASCIIPrintf(viewer," Control[UMFPACK_ALLOC_INIT]: %g\n",lu->Control[UMFPACK_ALLOC_INIT]);
307: PetscViewerASCIIPrintf(viewer," Control[UMFPACK_DROPTOL]: %g\n",lu->Control[UMFPACK_DROPTOL]);
309: /* Control parameters used by solve */
310: PetscViewerASCIIPrintf(viewer," Control[UMFPACK_IRSTEP]: %g\n",lu->Control[UMFPACK_IRSTEP]);
312: /* mat ordering */
313: if(!lu->PetscMatOdering) PetscViewerASCIIPrintf(viewer," UMFPACK default matrix ordering is used (not the PETSc matrix ordering) \n");
315: return(0);
316: }
320: PetscErrorCode MatView_UMFPACK(Mat A,PetscViewer viewer)
321: {
323: PetscTruth iascii;
324: PetscViewerFormat format;
325: Mat_UMFPACK *lu=(Mat_UMFPACK*)(A->spptr);
328: (*lu->MatView)(A,viewer);
330: PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_ASCII,&iascii);
331: if (iascii) {
332: PetscViewerGetFormat(viewer,&format);
333: if (format == PETSC_VIEWER_ASCII_FACTOR_INFO) {
334: MatFactorInfo_UMFPACK(A,viewer);
335: }
336: }
337: return(0);
338: }
343: PetscErrorCode PETSCMAT_DLLEXPORT MatConvert_SeqAIJ_UMFPACK(Mat A,MatType type,MatReuse reuse,Mat *newmat)
344: {
345: /* This routine is only called to convert to MATUMFPACK */
346: /* from MATSEQAIJ, so we will ignore 'MatType type'. */
348: Mat B=*newmat;
349: Mat_UMFPACK *lu;
352: if (reuse == MAT_INITIAL_MATRIX) {
353: MatDuplicate(A,MAT_COPY_VALUES,&B);
354: }
356: PetscNew(Mat_UMFPACK,&lu);
357: lu->MatDuplicate = A->ops->duplicate;
358: lu->MatView = A->ops->view;
359: lu->MatAssemblyEnd = A->ops->assemblyend;
360: lu->MatLUFactorSymbolic = A->ops->lufactorsymbolic;
361: lu->MatDestroy = A->ops->destroy;
362: lu->CleanUpUMFPACK = PETSC_FALSE;
364: B->spptr = (void*)lu;
365: B->ops->duplicate = MatDuplicate_UMFPACK;
366: B->ops->view = MatView_UMFPACK;
367: B->ops->assemblyend = MatAssemblyEnd_UMFPACK;
368: B->ops->lufactorsymbolic = MatLUFactorSymbolic_UMFPACK;
369: B->ops->destroy = MatDestroy_UMFPACK;
371: PetscObjectComposeFunctionDynamic((PetscObject)B,"MatConvert_seqaij_umfpack_C",
372: "MatConvert_SeqAIJ_UMFPACK",MatConvert_SeqAIJ_UMFPACK);
373: PetscObjectComposeFunctionDynamic((PetscObject)B,"MatConvert_umfpack_seqaij_C",
374: "MatConvert_UMFPACK_SeqAIJ",MatConvert_UMFPACK_SeqAIJ);
375: PetscLogInfo((0,"MatConvert_SeqAIJ_UMFPACK:Using UMFPACK for SeqAIJ LU factorization and solves.\n"));
376: PetscObjectChangeTypeName((PetscObject)B,MATUMFPACK);
377: *newmat = B;
378: return(0);
379: }
384: PetscErrorCode MatDuplicate_UMFPACK(Mat A, MatDuplicateOption op, Mat *M)
385: {
387: Mat_UMFPACK *lu=(Mat_UMFPACK*)A->spptr;
390: (*lu->MatDuplicate)(A,op,M);
391: PetscMemcpy((*M)->spptr,lu,sizeof(Mat_UMFPACK));
392: return(0);
393: }
395: /*MC
396: MATUMFPACK - MATUMFPACK = "umfpack" - A matrix type providing direct solvers (LU) for sequential matrices
397: via the external package UMFPACK.
399: If UMFPACK is installed (see the manual for
400: instructions on how to declare the existence of external packages),
401: a matrix type can be constructed which invokes UMFPACK solvers.
402: After calling MatCreate(...,A), simply call MatSetType(A,UMFPACK).
403: This matrix type is only supported for double precision real.
405: This matrix inherits from MATSEQAIJ. As a result, MatSeqAIJSetPreallocation is
406: supported for this matrix type. One can also call MatConvert for an inplace conversion to or from
407: the MATSEQAIJ type without data copy.
409: Consult UMFPACK documentation for more information about the Control parameters
410: which correspond to the options database keys below.
412: Options Database Keys:
413: + -mat_type umfpack - sets the matrix type to "umfpack" during a call to MatSetFromOptions()
414: . -mat_umfpack_prl - UMFPACK print level: Control[UMFPACK_PRL]
415: . -mat_umfpack_dense_col <alpha_c> - UMFPACK dense column threshold: Control[UMFPACK_DENSE_COL]
416: . -mat_umfpack_block_size <bs> - UMFPACK block size for BLAS-Level 3 calls: Control[UMFPACK_BLOCK_SIZE]
417: . -mat_umfpack_pivot_tolerance <delta> - UMFPACK partial pivot tolerance: Control[UMFPACK_PIVOT_TOLERANCE]
418: . -mat_umfpack_alloc_init <delta> - UMFPACK factorized matrix allocation modifier: Control[UMFPACK_ALLOC_INIT]
419: - -mat_umfpack_irstep <maxit> - UMFPACK maximum number of iterative refinement steps: Control[UMFPACK_IRSTEP]
421: Level: beginner
423: .seealso: PCLU
424: M*/
429: PetscErrorCode PETSCMAT_DLLEXPORT MatCreate_UMFPACK(Mat A)
430: {
434: /* Change type name before calling MatSetType to force proper construction of SeqAIJ and UMFPACK types */
435: PetscObjectChangeTypeName((PetscObject)A,MATUMFPACK);
436: MatSetType(A,MATSEQAIJ);
437: MatConvert_SeqAIJ_UMFPACK(A,MATUMFPACK,MAT_REUSE_MATRIX,&A);
438: return(0);
439: }