xref: /petsc/src/mat/impls/aij/seq/umfpack/umfpack.c (revision be1d678a52e6eff2808b2fa31ae986cdbf03c9fe)
1 #define PETSCMAT_DLL
2 
3 /*
4         Provides an interface to the UMFPACKv4.3 sparse solver
5 */
6 
7 #include "src/mat/impls/aij/seq/aij.h"
8 
9 EXTERN_C_BEGIN
10 #include "umfpack.h"
11 EXTERN_C_END
12 
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;
20 
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;
31 
32 EXTERN PetscErrorCode MatDuplicate_UMFPACK(Mat,MatDuplicateOption,Mat*);
33 
34 EXTERN_C_BEGIN
35 #undef __FUNCT__
36 #define __FUNCT__ "MatConvert_UMFPACK_SeqAIJ"
37 PetscErrorCode PETSCMAT_DLLEXPORT MatConvert_UMFPACK_SeqAIJ(Mat A,const 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'. */
41   PetscErrorCode ierr;
42   Mat         B=*newmat;
43   Mat_UMFPACK *lu=(Mat_UMFPACK*)A->spptr;
44 
45   PetscFunctionBegin;
46   if (reuse == MAT_INITIAL_MATRIX) {
47     ierr = MatDuplicate(A,MAT_COPY_VALUES,&B);CHKERRQ(ierr);
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   ierr = PetscFree(lu);CHKERRQ(ierr);
57 
58   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_umfpack_C","",PETSC_NULL);CHKERRQ(ierr);
59   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_umfpack_seqaij_C","",PETSC_NULL);CHKERRQ(ierr);
60 
61   ierr = PetscObjectChangeTypeName((PetscObject)B,MATSEQAIJ);CHKERRQ(ierr);
62   *newmat = B;
63   PetscFunctionReturn(0);
64 }
65 EXTERN_C_END
66 
67 #undef __FUNCT__
68 #define __FUNCT__ "MatDestroy_UMFPACK"
69 PetscErrorCode MatDestroy_UMFPACK(Mat A)
70 {
71   PetscErrorCode ierr;
72   Mat_UMFPACK *lu=(Mat_UMFPACK*)A->spptr;
73 
74   PetscFunctionBegin;
75   if (lu->CleanUpUMFPACK) {
76     umfpack_di_free_symbolic(&lu->Symbolic);
77     umfpack_di_free_numeric(&lu->Numeric);
78     ierr = PetscFree(lu->Wi);CHKERRQ(ierr);
79     ierr = PetscFree(lu->W);CHKERRQ(ierr);
80     if (lu->PetscMatOdering) {
81       ierr = PetscFree(lu->perm_c);CHKERRQ(ierr);
82     }
83   }
84   ierr = MatConvert_UMFPACK_SeqAIJ(A,MATSEQAIJ,MAT_REUSE_MATRIX,&A);CHKERRQ(ierr);
85   ierr = (*A->ops->destroy)(A);CHKERRQ(ierr);
86   PetscFunctionReturn(0);
87 }
88 
89 #undef __FUNCT__
90 #define __FUNCT__ "MatSolve_UMFPACK"
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;
95   PetscErrorCode ierr;
96   int          *ai=lu->ai,*aj=lu->aj,status;
97 
98   PetscFunctionBegin;
99   /* solve Ax = b by umfpack_di_wsolve */
100   /* ----------------------------------*/
101   ierr = VecGetArray(b,&ba);
102   ierr = VecGetArray(x,&xa);
103 
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   ierr = VecRestoreArray(b,&ba);
112   ierr = VecRestoreArray(x,&xa);
113 
114   PetscFunctionReturn(0);
115 }
116 
117 #undef __FUNCT__
118 #define __FUNCT__ "MatLUFactorNumeric_UMFPACK"
119 PetscErrorCode MatLUFactorNumeric_UMFPACK(Mat A,MatFactorInfo *info,Mat *F)
120 {
121   Mat_UMFPACK *lu=(Mat_UMFPACK*)(*F)->spptr;
122   PetscErrorCode ierr;
123   int         *ai=lu->ai,*aj=lu->aj,m=A->m,status;
124   PetscScalar *av=lu->av;
125 
126   PetscFunctionBegin;
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);
136 
137   if (lu->flg == DIFFERENT_NONZERO_PATTERN){  /* first numeric factorization */
138     /* allocate working space to be used by Solve */
139     ierr = PetscMalloc(m * sizeof(int), &lu->Wi);CHKERRQ(ierr);
140     ierr = PetscMalloc(5*m * sizeof(double), &lu->W);CHKERRQ(ierr);
141   }
142   lu->flg = SAME_NONZERO_PATTERN;
143   lu->CleanUpUMFPACK = PETSC_TRUE;
144   PetscFunctionReturn(0);
145 }
146 
147 /*
148    Note the r permutation is ignored
149 */
150 #undef __FUNCT__
151 #define __FUNCT__ "MatLUFactorSymbolic_UMFPACK"
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;
157   PetscErrorCode ierr;
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 
164   PetscFunctionBegin;
165   /* Create the factorization matrix F */
166   ierr = MatCreate(A->comm,PETSC_DECIDE,PETSC_DECIDE,m,n,&B);CHKERRQ(ierr);
167   ierr = MatSetType(B,A->type_name);CHKERRQ(ierr);
168   ierr = MatSeqAIJSetPreallocation(B,0,PETSC_NULL);CHKERRQ(ierr);
169 
170   B->ops->lufactornumeric = MatLUFactorNumeric_UMFPACK;
171   B->ops->solve           = MatSolve_UMFPACK;
172   B->factor               = FACTOR_LU;
173   B->assembled            = PETSC_TRUE;  /* required by -ksp_view */
174 
175   lu = (Mat_UMFPACK*)(B->spptr);
176 
177   /* initializations */
178   /* ------------------------------------------------*/
179   /* get the default control parameters */
180   umfpack_di_defaults (lu->Control);
181   lu->perm_c = PETSC_NULL;  /* use defaul UMFPACK col permutation */
182   lu->Control[UMFPACK_IRSTEP] = 0; /* max num of iterative refinement steps to attempt */
183 
184   ierr = PetscOptionsBegin(A->comm,A->prefix,"UMFPACK Options","Mat");CHKERRQ(ierr);
185   /* Control parameters used by reporting routiones */
186   ierr = PetscOptionsReal("-mat_umfpack_prl","Control[UMFPACK_PRL]","None",lu->Control[UMFPACK_PRL],&lu->Control[UMFPACK_PRL],PETSC_NULL);CHKERRQ(ierr);
187 
188   /* Control parameters for symbolic factorization */
189   ierr = PetscOptionsEList("-mat_umfpack_strategy","ordering and pivoting strategy","None",strategy,4,strategy[0],&idx,&flg);CHKERRQ(ierr);
190   if (flg) {
191     switch (idx){
192     case 0: lu->Control[UMFPACK_STRATEGY] = UMFPACK_STRATEGY_AUTO; break;
193     case 1: lu->Control[UMFPACK_STRATEGY] = UMFPACK_STRATEGY_UNSYMMETRIC; break;
194     case 2: lu->Control[UMFPACK_STRATEGY] = UMFPACK_STRATEGY_SYMMETRIC; break;
195     case 3: lu->Control[UMFPACK_STRATEGY] = UMFPACK_STRATEGY_2BY2; break;
196     }
197   }
198   ierr = PetscOptionsReal("-mat_umfpack_dense_col","Control[UMFPACK_DENSE_COL]","None",lu->Control[UMFPACK_DENSE_COL],&lu->Control[UMFPACK_DENSE_COL],PETSC_NULL);CHKERRQ(ierr);
199   ierr = PetscOptionsReal("-mat_umfpack_dense_row","Control[UMFPACK_DENSE_ROW]","None",lu->Control[UMFPACK_DENSE_ROW],&lu->Control[UMFPACK_DENSE_ROW],PETSC_NULL);CHKERRQ(ierr);
200   ierr = PetscOptionsReal("-mat_umfpack_amd_dense","Control[UMFPACK_AMD_DENSE]","None",lu->Control[UMFPACK_AMD_DENSE],&lu->Control[UMFPACK_AMD_DENSE],PETSC_NULL);CHKERRQ(ierr);
201   ierr = PetscOptionsReal("-mat_umfpack_block_size","Control[UMFPACK_BLOCK_SIZE]","None",lu->Control[UMFPACK_BLOCK_SIZE],&lu->Control[UMFPACK_BLOCK_SIZE],PETSC_NULL);CHKERRQ(ierr);
202   ierr = PetscOptionsReal("-mat_umfpack_2by2_tolerance","Control[UMFPACK_2BY2_TOLERANCE]","None",lu->Control[UMFPACK_2BY2_TOLERANCE],&lu->Control[UMFPACK_2BY2_TOLERANCE],PETSC_NULL);CHKERRQ(ierr);
203   ierr = PetscOptionsReal("-mat_umfpack_fixq","Control[UMFPACK_FIXQ]","None",lu->Control[UMFPACK_FIXQ],&lu->Control[UMFPACK_FIXQ],PETSC_NULL);CHKERRQ(ierr);
204   ierr = PetscOptionsReal("-mat_umfpack_aggressive","Control[UMFPACK_AGGRESSIVE]","None",lu->Control[UMFPACK_AGGRESSIVE],&lu->Control[UMFPACK_AGGRESSIVE],PETSC_NULL);CHKERRQ(ierr);
205 
206   /* Control parameters used by numeric factorization */
207   ierr = PetscOptionsReal("-mat_umfpack_pivot_tolerance","Control[UMFPACK_PIVOT_TOLERANCE]","None",lu->Control[UMFPACK_PIVOT_TOLERANCE],&lu->Control[UMFPACK_PIVOT_TOLERANCE],PETSC_NULL);CHKERRQ(ierr);
208   ierr = 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);CHKERRQ(ierr);
209   ierr = PetscOptionsEList("-mat_umfpack_scale","Control[UMFPACK_SCALE]","None",scale,3,scale[0],&idx,&flg);CHKERRQ(ierr);
210   if (flg) {
211     switch (idx){
212     case 0: lu->Control[UMFPACK_SCALE] = UMFPACK_SCALE_NONE; break;
213     case 1: lu->Control[UMFPACK_SCALE] = UMFPACK_SCALE_SUM; break;
214     case 2: lu->Control[UMFPACK_SCALE] = UMFPACK_SCALE_MAX; break;
215     }
216   }
217   ierr = PetscOptionsReal("-mat_umfpack_alloc_init","Control[UMFPACK_ALLOC_INIT]","None",lu->Control[UMFPACK_ALLOC_INIT],&lu->Control[UMFPACK_ALLOC_INIT],PETSC_NULL);CHKERRQ(ierr);
218   ierr = 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);CHKERRQ(ierr);
219   ierr = PetscOptionsReal("-mat_umfpack_droptol","Control[UMFPACK_DROPTOL]","None",lu->Control[UMFPACK_DROPTOL],&lu->Control[UMFPACK_DROPTOL],PETSC_NULL);CHKERRQ(ierr);
220 
221   /* Control parameters used by solve */
222   ierr = PetscOptionsReal("-mat_umfpack_irstep","Control[UMFPACK_IRSTEP]","None",lu->Control[UMFPACK_IRSTEP],&lu->Control[UMFPACK_IRSTEP],PETSC_NULL);CHKERRQ(ierr);
223 
224   /* use Petsc mat ordering (note: size is for the transpose, and PETSc r = Umfpack perm_c) */
225   ierr = PetscOptionsHasName(PETSC_NULL,"-pc_lu_mat_ordering_type",&lu->PetscMatOdering);CHKERRQ(ierr);
226   if (lu->PetscMatOdering) {
227     ierr = ISGetIndices(r,&ra);CHKERRQ(ierr);
228     ierr = PetscMalloc(A->m*sizeof(int),&lu->perm_c);CHKERRQ(ierr);
229     ierr = PetscMemcpy(lu->perm_c,ra,A->m*sizeof(int));CHKERRQ(ierr);
230     ierr = ISRestoreIndices(r,&ra);CHKERRQ(ierr);
231   }
232   PetscOptionsEnd();
233 
234   /* print the control parameters */
235   if( lu->Control[UMFPACK_PRL] > 1 ) umfpack_di_report_control (lu->Control);
236 
237   /* symbolic factorization of A' */
238   /* ---------------------------------------------------------------------- */
239   if (lu->PetscMatOdering) { /* use Petsc row ordering */
240     status = umfpack_di_qsymbolic(n,m,ai,aj,av,lu->perm_c,&lu->Symbolic,lu->Control,lu->Info);
241   } else { /* use Umfpack col ordering */
242     status = umfpack_di_symbolic(n,m,ai,aj,av,&lu->Symbolic,lu->Control,lu->Info);
243   }
244   if (status < 0){
245     umfpack_di_report_info(lu->Control, lu->Info);
246     umfpack_di_report_status(lu->Control, status);
247     SETERRQ(PETSC_ERR_LIB,"umfpack_di_symbolic failed");
248   }
249   /* report sumbolic factorization of A' when Control[PRL] > 3 */
250   (void) umfpack_di_report_symbolic(lu->Symbolic, lu->Control);
251 
252   lu->flg = DIFFERENT_NONZERO_PATTERN;
253   lu->ai  = ai;
254   lu->aj  = aj;
255   lu->av  = av;
256   lu->CleanUpUMFPACK = PETSC_TRUE;
257   *F = B;
258   PetscFunctionReturn(0);
259 }
260 
261 #undef __FUNCT__
262 #define __FUNCT__ "MatAssemblyEnd_UMFPACK"
263 PetscErrorCode MatAssemblyEnd_UMFPACK(Mat A,MatAssemblyType mode)
264 {
265   PetscErrorCode ierr;
266   Mat_UMFPACK *lu=(Mat_UMFPACK*)(A->spptr);
267 
268   PetscFunctionBegin;
269   ierr = (*lu->MatAssemblyEnd)(A,mode);CHKERRQ(ierr);
270   lu->MatLUFactorSymbolic  = A->ops->lufactorsymbolic;
271   A->ops->lufactorsymbolic = MatLUFactorSymbolic_UMFPACK;
272   PetscFunctionReturn(0);
273 }
274 
275 /* used by -ksp_view */
276 #undef __FUNCT__
277 #define __FUNCT__ "MatFactorInfo_UMFPACK"
278 PetscErrorCode MatFactorInfo_UMFPACK(Mat A,PetscViewer viewer)
279 {
280   Mat_UMFPACK *lu= (Mat_UMFPACK*)A->spptr;
281   PetscErrorCode ierr;
282 
283   PetscFunctionBegin;
284   /* check if matrix is UMFPACK type */
285   if (A->ops->solve != MatSolve_UMFPACK) PetscFunctionReturn(0);
286 
287   ierr = PetscViewerASCIIPrintf(viewer,"UMFPACK run parameters:\n");CHKERRQ(ierr);
288   /* Control parameters used by reporting routiones */
289   ierr = PetscViewerASCIIPrintf(viewer,"  Control[UMFPACK_PRL]: %g\n",lu->Control[UMFPACK_PRL]);CHKERRQ(ierr);
290 
291   /* Control parameters used by symbolic factorization */
292   ierr = PetscViewerASCIIPrintf(viewer,"  Control[UMFPACK_STRATEGY]: %g\n",lu->Control[UMFPACK_STRATEGY]);CHKERRQ(ierr);
293   ierr = PetscViewerASCIIPrintf(viewer,"  Control[UMFPACK_DENSE_COL]: %g\n",lu->Control[UMFPACK_DENSE_COL]);CHKERRQ(ierr);
294   ierr = PetscViewerASCIIPrintf(viewer,"  Control[UMFPACK_DENSE_ROW]: %g\n",lu->Control[UMFPACK_DENSE_ROW]);CHKERRQ(ierr);
295   ierr = PetscViewerASCIIPrintf(viewer,"  Control[UMFPACK_AMD_DENSE]: %g\n",lu->Control[UMFPACK_AMD_DENSE]);CHKERRQ(ierr);
296   ierr = PetscViewerASCIIPrintf(viewer,"  Control[UMFPACK_BLOCK_SIZE]: %g\n",lu->Control[UMFPACK_BLOCK_SIZE]);CHKERRQ(ierr);
297   ierr = PetscViewerASCIIPrintf(viewer,"  Control[UMFPACK_2BY2_TOLERANCE]: %g\n",lu->Control[UMFPACK_2BY2_TOLERANCE]);CHKERRQ(ierr);
298   ierr = PetscViewerASCIIPrintf(viewer,"  Control[UMFPACK_FIXQ]: %g\n",lu->Control[UMFPACK_FIXQ]);CHKERRQ(ierr);
299   ierr = PetscViewerASCIIPrintf(viewer,"  Control[UMFPACK_AGGRESSIVE]: %g\n",lu->Control[UMFPACK_AGGRESSIVE]);CHKERRQ(ierr);
300 
301   /* Control parameters used by numeric factorization */
302   ierr = PetscViewerASCIIPrintf(viewer,"  Control[UMFPACK_PIVOT_TOLERANCE]: %g\n",lu->Control[UMFPACK_PIVOT_TOLERANCE]);CHKERRQ(ierr);
303   ierr = PetscViewerASCIIPrintf(viewer,"  Control[UMFPACK_SYM_PIVOT_TOLERANCE]: %g\n",lu->Control[UMFPACK_SYM_PIVOT_TOLERANCE]);CHKERRQ(ierr);
304   ierr = PetscViewerASCIIPrintf(viewer,"  Control[UMFPACK_SCALE]: %g\n",lu->Control[UMFPACK_SCALE]);CHKERRQ(ierr);
305   ierr = PetscViewerASCIIPrintf(viewer,"  Control[UMFPACK_ALLOC_INIT]: %g\n",lu->Control[UMFPACK_ALLOC_INIT]);CHKERRQ(ierr);
306   ierr = PetscViewerASCIIPrintf(viewer,"  Control[UMFPACK_DROPTOL]: %g\n",lu->Control[UMFPACK_DROPTOL]);CHKERRQ(ierr);
307 
308   /* Control parameters used by solve */
309   ierr = PetscViewerASCIIPrintf(viewer,"  Control[UMFPACK_IRSTEP]: %g\n",lu->Control[UMFPACK_IRSTEP]);CHKERRQ(ierr);
310 
311   /* mat ordering */
312   if(!lu->PetscMatOdering) ierr = PetscViewerASCIIPrintf(viewer,"  UMFPACK default matrix ordering is used (not the PETSc matrix ordering) \n");CHKERRQ(ierr);
313 
314   PetscFunctionReturn(0);
315 }
316 
317 #undef __FUNCT__
318 #define __FUNCT__ "MatView_UMFPACK"
319 PetscErrorCode MatView_UMFPACK(Mat A,PetscViewer viewer)
320 {
321   PetscErrorCode ierr;
322   PetscTruth        iascii;
323   PetscViewerFormat format;
324   Mat_UMFPACK       *lu=(Mat_UMFPACK*)(A->spptr);
325 
326   PetscFunctionBegin;
327   ierr = (*lu->MatView)(A,viewer);CHKERRQ(ierr);
328 
329   ierr = PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_ASCII,&iascii);CHKERRQ(ierr);
330   if (iascii) {
331     ierr = PetscViewerGetFormat(viewer,&format);CHKERRQ(ierr);
332     if (format == PETSC_VIEWER_ASCII_FACTOR_INFO) {
333       ierr = MatFactorInfo_UMFPACK(A,viewer);CHKERRQ(ierr);
334     }
335   }
336   PetscFunctionReturn(0);
337 }
338 
339 EXTERN_C_BEGIN
340 #undef __FUNCT__
341 #define __FUNCT__ "MatConvert_SeqAIJ_UMFPACK"
342 PetscErrorCode PETSCMAT_DLLEXPORT MatConvert_SeqAIJ_UMFPACK(Mat A,const MatType type,MatReuse reuse,Mat *newmat)
343 {
344   /* This routine is only called to convert to MATUMFPACK */
345   /* from MATSEQAIJ, so we will ignore 'MatType type'. */
346   PetscErrorCode ierr;
347   Mat         B=*newmat;
348   Mat_UMFPACK *lu;
349 
350   PetscFunctionBegin;
351   if (reuse == MAT_INITIAL_MATRIX) {
352     ierr = MatDuplicate(A,MAT_COPY_VALUES,&B);CHKERRQ(ierr);
353   }
354 
355   ierr = PetscNew(Mat_UMFPACK,&lu);CHKERRQ(ierr);
356   lu->MatDuplicate         = A->ops->duplicate;
357   lu->MatView              = A->ops->view;
358   lu->MatAssemblyEnd       = A->ops->assemblyend;
359   lu->MatLUFactorSymbolic  = A->ops->lufactorsymbolic;
360   lu->MatDestroy           = A->ops->destroy;
361   lu->CleanUpUMFPACK       = PETSC_FALSE;
362 
363   B->spptr                 = (void*)lu;
364   B->ops->duplicate        = MatDuplicate_UMFPACK;
365   B->ops->view             = MatView_UMFPACK;
366   B->ops->assemblyend      = MatAssemblyEnd_UMFPACK;
367   B->ops->lufactorsymbolic = MatLUFactorSymbolic_UMFPACK;
368   B->ops->destroy          = MatDestroy_UMFPACK;
369 
370   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatConvert_seqaij_umfpack_C",
371                                            "MatConvert_SeqAIJ_UMFPACK",MatConvert_SeqAIJ_UMFPACK);CHKERRQ(ierr);
372   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatConvert_umfpack_seqaij_C",
373                                            "MatConvert_UMFPACK_SeqAIJ",MatConvert_UMFPACK_SeqAIJ);CHKERRQ(ierr);
374   ierr = PetscLogInfo((0,"MatConvert_SeqAIJ_UMFPACK:Using UMFPACK for SeqAIJ LU factorization and solves.\n"));CHKERRQ(ierr);
375   ierr = PetscObjectChangeTypeName((PetscObject)B,MATUMFPACK);CHKERRQ(ierr);
376   *newmat = B;
377   PetscFunctionReturn(0);
378 }
379 EXTERN_C_END
380 
381 #undef __FUNCT__
382 #define __FUNCT__ "MatDuplicate_UMFPACK"
383 PetscErrorCode MatDuplicate_UMFPACK(Mat A, MatDuplicateOption op, Mat *M)
384 {
385   PetscErrorCode ierr;
386   Mat_UMFPACK *lu=(Mat_UMFPACK*)A->spptr;
387 
388   PetscFunctionBegin;
389   ierr = (*lu->MatDuplicate)(A,op,M);CHKERRQ(ierr);
390   ierr = PetscMemcpy((*M)->spptr,lu,sizeof(Mat_UMFPACK));CHKERRQ(ierr);
391   PetscFunctionReturn(0);
392 }
393 
394 /*MC
395   MATUMFPACK - MATUMFPACK = "umfpack" - A matrix type providing direct solvers (LU) for sequential matrices
396   via the external package UMFPACK.
397 
398   If UMFPACK is installed (see the manual for
399   instructions on how to declare the existence of external packages),
400   a matrix type can be constructed which invokes UMFPACK solvers.
401   After calling MatCreate(...,A), simply call MatSetType(A,UMFPACK).
402   This matrix type is only supported for double precision real.
403 
404   This matrix inherits from MATSEQAIJ.  As a result, MatSeqAIJSetPreallocation is
405   supported for this matrix type.  One can also call MatConvert for an inplace conversion to or from
406   the MATSEQAIJ type without data copy.
407 
408   Consult UMFPACK documentation for more information about the Control parameters
409   which correspond to the options database keys below.
410 
411   Options Database Keys:
412 + -mat_type umfpack - sets the matrix type to "umfpack" during a call to MatSetFromOptions()
413 . -mat_umfpack_prl - UMFPACK print level: Control[UMFPACK_PRL]
414 . -mat_umfpack_dense_col <alpha_c> - UMFPACK dense column threshold: Control[UMFPACK_DENSE_COL]
415 . -mat_umfpack_block_size <bs> - UMFPACK block size for BLAS-Level 3 calls: Control[UMFPACK_BLOCK_SIZE]
416 . -mat_umfpack_pivot_tolerance <delta> - UMFPACK partial pivot tolerance: Control[UMFPACK_PIVOT_TOLERANCE]
417 . -mat_umfpack_alloc_init <delta> - UMFPACK factorized matrix allocation modifier: Control[UMFPACK_ALLOC_INIT]
418 - -mat_umfpack_irstep <maxit> - UMFPACK maximum number of iterative refinement steps: Control[UMFPACK_IRSTEP]
419 
420    Level: beginner
421 
422 .seealso: PCLU
423 M*/
424 
425 EXTERN_C_BEGIN
426 #undef __FUNCT__
427 #define __FUNCT__ "MatCreate_UMFPACK"
428 PetscErrorCode PETSCMAT_DLLEXPORT MatCreate_UMFPACK(Mat A)
429 {
430   PetscErrorCode ierr;
431 
432   PetscFunctionBegin;
433   /* Change type name before calling MatSetType to force proper construction of SeqAIJ and UMFPACK types */
434   ierr = PetscObjectChangeTypeName((PetscObject)A,MATUMFPACK);CHKERRQ(ierr);
435   ierr = MatSetType(A,MATSEQAIJ);CHKERRQ(ierr);
436   ierr = MatConvert_SeqAIJ_UMFPACK(A,MATUMFPACK,MAT_REUSE_MATRIX,&A);CHKERRQ(ierr);
437   PetscFunctionReturn(0);
438 }
439 EXTERN_C_END
440