xref: /petsc/src/mat/impls/aij/seq/umfpack/umfpack.c (revision 7d5fd1e4d9337468ad3f05b65b7facdcd2dfd2a4)
1 
2 /*
3    Provides an interface to the UMFPACK sparse solver available through SuiteSparse version 4.2.1
4 
5    When build with PETSC_USE_64BIT_INDICES this will use Suitesparse_long as the
6    integer type in UMFPACK, otherwise it will use int. This means
7    all integers in this file as simply declared as PetscInt. Also it means
8    that one cannot use 64BIT_INDICES on 32bit machines [as Suitesparse_long is 32bit only]
9 
10 */
11 #include <../src/mat/impls/aij/seq/aij.h>
12 
13 #if defined(PETSC_USE_64BIT_INDICES)
14 #if defined(PETSC_USE_COMPLEX)
15 #define umfpack_UMF_free_symbolic                      umfpack_zl_free_symbolic
16 #define umfpack_UMF_free_numeric                       umfpack_zl_free_numeric
17 /* the type casts are needed because PetscInt is long long while SuiteSparse_long is long and compilers warn even when they are identical */
18 #define umfpack_UMF_wsolve(a,b,c,d,e,f,g,h,i,j,k,l,m,n) umfpack_zl_wsolve(a,(SuiteSparse_long*)b,(SuiteSparse_long*)c,d,e,f,g,h,i,(SuiteSparse_long*)j,k,l,(SuiteSparse_long*)m,n)
19 #define umfpack_UMF_numeric(a,b,c,d,e,f,g,h)          umfpack_zl_numeric((SuiteSparse_long*)a,(SuiteSparse_long*)b,c,d,e,f,g,h)
20 #define umfpack_UMF_report_numeric                    umfpack_zl_report_numeric
21 #define umfpack_UMF_report_control                    umfpack_zl_report_control
22 #define umfpack_UMF_report_status                     umfpack_zl_report_status
23 #define umfpack_UMF_report_info                       umfpack_zl_report_info
24 #define umfpack_UMF_report_symbolic                   umfpack_zl_report_symbolic
25 #define umfpack_UMF_qsymbolic(a,b,c,d,e,f,g,h,i,j)    umfpack_zl_qsymbolic(a,b,(SuiteSparse_long*)c,(SuiteSparse_long*)d,e,f,(SuiteSparse_long*)g,h,i,j)
26 #define umfpack_UMF_symbolic(a,b,c,d,e,f,g,h,i)       umfpack_zl_symbolic(a,b,(SuiteSparse_long*)c,(SuiteSparse_long*)d,e,f,g,h,i)
27 #define umfpack_UMF_defaults                          umfpack_zl_defaults
28 
29 #else
30 #define umfpack_UMF_free_symbolic                  umfpack_dl_free_symbolic
31 #define umfpack_UMF_free_numeric                   umfpack_dl_free_numeric
32 #define umfpack_UMF_wsolve(a,b,c,d,e,f,g,h,i,j,k)  umfpack_dl_wsolve(a,(SuiteSparse_long*)b,(SuiteSparse_long*)c,d,e,f,g,h,i,(SuiteSparse_long*)j,k)
33 #define umfpack_UMF_numeric(a,b,c,d,e,f,g)         umfpack_dl_numeric((SuiteSparse_long*)a,(SuiteSparse_long*)b,c,d,e,f,g)
34 #define umfpack_UMF_report_numeric                 umfpack_dl_report_numeric
35 #define umfpack_UMF_report_control                 umfpack_dl_report_control
36 #define umfpack_UMF_report_status                  umfpack_dl_report_status
37 #define umfpack_UMF_report_info                    umfpack_dl_report_info
38 #define umfpack_UMF_report_symbolic                umfpack_dl_report_symbolic
39 #define umfpack_UMF_qsymbolic(a,b,c,d,e,f,g,h,i)   umfpack_dl_qsymbolic(a,b,(SuiteSparse_long*)c,(SuiteSparse_long*)d,e,(SuiteSparse_long*)f,g,h,i)
40 #define umfpack_UMF_symbolic(a,b,c,d,e,f,g,h)      umfpack_dl_symbolic(a,b,(SuiteSparse_long*)c,(SuiteSparse_long*)d,e,f,g,h)
41 #define umfpack_UMF_defaults                       umfpack_dl_defaults
42 #endif
43 
44 #else
45 #if defined(PETSC_USE_COMPLEX)
46 #define umfpack_UMF_free_symbolic   umfpack_zi_free_symbolic
47 #define umfpack_UMF_free_numeric    umfpack_zi_free_numeric
48 #define umfpack_UMF_wsolve          umfpack_zi_wsolve
49 #define umfpack_UMF_numeric         umfpack_zi_numeric
50 #define umfpack_UMF_report_numeric  umfpack_zi_report_numeric
51 #define umfpack_UMF_report_control  umfpack_zi_report_control
52 #define umfpack_UMF_report_status   umfpack_zi_report_status
53 #define umfpack_UMF_report_info     umfpack_zi_report_info
54 #define umfpack_UMF_report_symbolic umfpack_zi_report_symbolic
55 #define umfpack_UMF_qsymbolic       umfpack_zi_qsymbolic
56 #define umfpack_UMF_symbolic        umfpack_zi_symbolic
57 #define umfpack_UMF_defaults        umfpack_zi_defaults
58 
59 #else
60 #define umfpack_UMF_free_symbolic   umfpack_di_free_symbolic
61 #define umfpack_UMF_free_numeric    umfpack_di_free_numeric
62 #define umfpack_UMF_wsolve          umfpack_di_wsolve
63 #define umfpack_UMF_numeric         umfpack_di_numeric
64 #define umfpack_UMF_report_numeric  umfpack_di_report_numeric
65 #define umfpack_UMF_report_control  umfpack_di_report_control
66 #define umfpack_UMF_report_status   umfpack_di_report_status
67 #define umfpack_UMF_report_info     umfpack_di_report_info
68 #define umfpack_UMF_report_symbolic umfpack_di_report_symbolic
69 #define umfpack_UMF_qsymbolic       umfpack_di_qsymbolic
70 #define umfpack_UMF_symbolic        umfpack_di_symbolic
71 #define umfpack_UMF_defaults        umfpack_di_defaults
72 #endif
73 #endif
74 
75 EXTERN_C_BEGIN
76 #include <umfpack.h>
77 EXTERN_C_END
78 
79 static const char *const UmfpackOrderingTypes[] = {"CHOLMOD","AMD","GIVEN","METIS","BEST","NONE","USER","UmfpackOrderingTypes","UMFPACK_ORDERING_",0};
80 
81 typedef struct {
82   void         *Symbolic, *Numeric;
83   double       Info[UMFPACK_INFO], Control[UMFPACK_CONTROL],*W;
84   PetscInt     *Wi,*perm_c;
85   Mat          A;               /* Matrix used for factorization */
86   MatStructure flg;
87 
88   /* Flag to clean up UMFPACK objects during Destroy */
89   PetscBool CleanUpUMFPACK;
90 } Mat_UMFPACK;
91 
92 static PetscErrorCode MatDestroy_UMFPACK(Mat A)
93 {
94   PetscErrorCode ierr;
95   Mat_UMFPACK    *lu=(Mat_UMFPACK*)A->data;
96 
97   PetscFunctionBegin;
98   if (lu->CleanUpUMFPACK) {
99     umfpack_UMF_free_symbolic(&lu->Symbolic);
100     umfpack_UMF_free_numeric(&lu->Numeric);
101     ierr = PetscFree(lu->Wi);CHKERRQ(ierr);
102     ierr = PetscFree(lu->W);CHKERRQ(ierr);
103     ierr = PetscFree(lu->perm_c);CHKERRQ(ierr);
104   }
105   ierr = MatDestroy(&lu->A);CHKERRQ(ierr);
106   ierr = PetscFree(A->data);CHKERRQ(ierr);
107   PetscFunctionReturn(0);
108 }
109 
110 static PetscErrorCode MatSolve_UMFPACK_Private(Mat A,Vec b,Vec x,int uflag)
111 {
112   Mat_UMFPACK       *lu = (Mat_UMFPACK*)A->data;
113   Mat_SeqAIJ        *a  = (Mat_SeqAIJ*)lu->A->data;
114   PetscScalar       *av = a->a,*xa;
115   const PetscScalar *ba;
116   PetscErrorCode    ierr;
117   PetscInt          *ai = a->i,*aj = a->j,status;
118   static PetscBool  cite = PETSC_FALSE;
119 
120   PetscFunctionBegin;
121   if (!A->rmap->n) PetscFunctionReturn(0);
122   ierr = PetscCitationsRegister("@article{davis2004algorithm,\n  title={Algorithm 832: {UMFPACK} V4.3---An Unsymmetric-Pattern Multifrontal Method},\n  author={Davis, Timothy A},\n  journal={ACM Transactions on Mathematical Software (TOMS)},\n  volume={30},\n  number={2},\n  pages={196--199},\n  year={2004},\n  publisher={ACM}\n}\n",&cite);CHKERRQ(ierr);
123   /* solve Ax = b by umfpack_*_wsolve */
124   /* ----------------------------------*/
125 
126   if (!lu->Wi) {  /* first time, allocate working space for wsolve */
127     ierr = PetscMalloc1(A->rmap->n,&lu->Wi);CHKERRQ(ierr);
128     ierr = PetscMalloc1(5*A->rmap->n,&lu->W);CHKERRQ(ierr);
129   }
130 
131   ierr = VecGetArrayRead(b,&ba);CHKERRQ(ierr);
132   ierr = VecGetArray(x,&xa);CHKERRQ(ierr);
133 #if defined(PETSC_USE_COMPLEX)
134   status = umfpack_UMF_wsolve(uflag,ai,aj,(PetscReal*)av,NULL,(PetscReal*)xa,NULL,(PetscReal*)ba,NULL,lu->Numeric,lu->Control,lu->Info,lu->Wi,lu->W);
135 #else
136   status = umfpack_UMF_wsolve(uflag,ai,aj,av,xa,ba,lu->Numeric,lu->Control,lu->Info,lu->Wi,lu->W);
137 #endif
138   umfpack_UMF_report_info(lu->Control, lu->Info);
139   if (status < 0) {
140     umfpack_UMF_report_status(lu->Control, status);
141     SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"umfpack_UMF_wsolve failed");
142   }
143 
144   ierr = VecRestoreArrayRead(b,&ba);CHKERRQ(ierr);
145   ierr = VecRestoreArray(x,&xa);CHKERRQ(ierr);
146   PetscFunctionReturn(0);
147 }
148 
149 static PetscErrorCode MatSolve_UMFPACK(Mat A,Vec b,Vec x)
150 {
151   PetscErrorCode ierr;
152 
153   PetscFunctionBegin;
154   /* We gave UMFPACK the algebraic transpose (because it assumes column alignment) */
155   ierr = MatSolve_UMFPACK_Private(A,b,x,UMFPACK_Aat);CHKERRQ(ierr);
156   PetscFunctionReturn(0);
157 }
158 
159 static PetscErrorCode MatSolveTranspose_UMFPACK(Mat A,Vec b,Vec x)
160 {
161   PetscErrorCode ierr;
162 
163   PetscFunctionBegin;
164   /* We gave UMFPACK the algebraic transpose (because it assumes column alignment) */
165   ierr = MatSolve_UMFPACK_Private(A,b,x,UMFPACK_A);CHKERRQ(ierr);
166   PetscFunctionReturn(0);
167 }
168 
169 static PetscErrorCode MatLUFactorNumeric_UMFPACK(Mat F,Mat A,const MatFactorInfo *info)
170 {
171   Mat_UMFPACK    *lu = (Mat_UMFPACK*)(F)->data;
172   Mat_SeqAIJ     *a  = (Mat_SeqAIJ*)A->data;
173   PetscInt       *ai = a->i,*aj=a->j,status;
174   PetscScalar    *av = a->a;
175   PetscErrorCode ierr;
176 
177   PetscFunctionBegin;
178   if (!A->rmap->n) PetscFunctionReturn(0);
179   /* numeric factorization of A' */
180   /* ----------------------------*/
181 
182   if (lu->flg == SAME_NONZERO_PATTERN && lu->Numeric) {
183     umfpack_UMF_free_numeric(&lu->Numeric);
184   }
185 #if defined(PETSC_USE_COMPLEX)
186   status = umfpack_UMF_numeric(ai,aj,(double*)av,NULL,lu->Symbolic,&lu->Numeric,lu->Control,lu->Info);
187 #else
188   status = umfpack_UMF_numeric(ai,aj,av,lu->Symbolic,&lu->Numeric,lu->Control,lu->Info);
189 #endif
190   if (status < 0) {
191     umfpack_UMF_report_status(lu->Control, status);
192     SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"umfpack_UMF_numeric failed");
193   }
194   /* report numeric factorization of A' when Control[PRL] > 3 */
195   (void) umfpack_UMF_report_numeric(lu->Numeric, lu->Control);
196 
197   ierr = PetscObjectReference((PetscObject)A);CHKERRQ(ierr);
198   ierr = MatDestroy(&lu->A);CHKERRQ(ierr);
199 
200   lu->A                  = A;
201   lu->flg                = SAME_NONZERO_PATTERN;
202   lu->CleanUpUMFPACK     = PETSC_TRUE;
203   F->ops->solve          = MatSolve_UMFPACK;
204   F->ops->solvetranspose = MatSolveTranspose_UMFPACK;
205   PetscFunctionReturn(0);
206 }
207 
208 static PetscErrorCode MatLUFactorSymbolic_UMFPACK(Mat F,Mat A,IS r,IS c,const MatFactorInfo *info)
209 {
210   Mat_SeqAIJ     *a  = (Mat_SeqAIJ*)A->data;
211   Mat_UMFPACK    *lu = (Mat_UMFPACK*)(F->data);
212   PetscErrorCode ierr;
213   PetscInt       i,*ai = a->i,*aj = a->j,m=A->rmap->n,n=A->cmap->n;
214 #if !defined(PETSC_USE_COMPLEX)
215   PetscScalar    *av = a->a;
216 #endif
217   const PetscInt *ra;
218   PetscInt       status;
219 
220   PetscFunctionBegin;
221   (F)->ops->lufactornumeric = MatLUFactorNumeric_UMFPACK;
222   if (!n) PetscFunctionReturn(0);
223   if (r) {
224     ierr = ISGetIndices(r,&ra);CHKERRQ(ierr);
225     ierr = PetscMalloc1(m,&lu->perm_c);CHKERRQ(ierr);
226     /* we cannot simply memcpy on 64 bit archs */
227     for (i = 0; i < m; i++) lu->perm_c[i] = ra[i];
228     ierr = ISRestoreIndices(r,&ra);CHKERRQ(ierr);
229   }
230 
231   /* print the control parameters */
232   if (lu->Control[UMFPACK_PRL] > 1) umfpack_UMF_report_control(lu->Control);
233 
234   /* symbolic factorization of A' */
235   /* ---------------------------------------------------------------------- */
236   if (r) { /* use Petsc row ordering */
237 #if !defined(PETSC_USE_COMPLEX)
238     status = umfpack_UMF_qsymbolic(n,m,ai,aj,av,lu->perm_c,&lu->Symbolic,lu->Control,lu->Info);
239 #else
240     status = umfpack_UMF_qsymbolic(n,m,ai,aj,NULL,NULL,lu->perm_c,&lu->Symbolic,lu->Control,lu->Info);
241 #endif
242   } else { /* use Umfpack col ordering */
243 #if !defined(PETSC_USE_COMPLEX)
244     status = umfpack_UMF_symbolic(n,m,ai,aj,av,&lu->Symbolic,lu->Control,lu->Info);
245 #else
246     status = umfpack_UMF_symbolic(n,m,ai,aj,NULL,NULL,&lu->Symbolic,lu->Control,lu->Info);
247 #endif
248   }
249   if (status < 0) {
250     umfpack_UMF_report_info(lu->Control, lu->Info);
251     umfpack_UMF_report_status(lu->Control, status);
252     SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"umfpack_UMF_symbolic failed");
253   }
254   /* report sumbolic factorization of A' when Control[PRL] > 3 */
255   (void) umfpack_UMF_report_symbolic(lu->Symbolic, lu->Control);
256 
257   lu->flg                   = DIFFERENT_NONZERO_PATTERN;
258   lu->CleanUpUMFPACK        = PETSC_TRUE;
259   PetscFunctionReturn(0);
260 }
261 
262 static PetscErrorCode MatView_Info_UMFPACK(Mat A,PetscViewer viewer)
263 {
264   Mat_UMFPACK    *lu= (Mat_UMFPACK*)A->data;
265   PetscErrorCode ierr;
266 
267   PetscFunctionBegin;
268   /* check if matrix is UMFPACK type */
269   if (A->ops->solve != MatSolve_UMFPACK) PetscFunctionReturn(0);
270 
271   ierr = PetscViewerASCIIPrintf(viewer,"UMFPACK run parameters:\n");CHKERRQ(ierr);
272   /* Control parameters used by reporting routiones */
273   ierr = PetscViewerASCIIPrintf(viewer,"  Control[UMFPACK_PRL]: %g\n",lu->Control[UMFPACK_PRL]);CHKERRQ(ierr);
274 
275   /* Control parameters used by symbolic factorization */
276   ierr = PetscViewerASCIIPrintf(viewer,"  Control[UMFPACK_STRATEGY]: %g\n",lu->Control[UMFPACK_STRATEGY]);CHKERRQ(ierr);
277   ierr = PetscViewerASCIIPrintf(viewer,"  Control[UMFPACK_DENSE_COL]: %g\n",lu->Control[UMFPACK_DENSE_COL]);CHKERRQ(ierr);
278   ierr = PetscViewerASCIIPrintf(viewer,"  Control[UMFPACK_DENSE_ROW]: %g\n",lu->Control[UMFPACK_DENSE_ROW]);CHKERRQ(ierr);
279   ierr = PetscViewerASCIIPrintf(viewer,"  Control[UMFPACK_AMD_DENSE]: %g\n",lu->Control[UMFPACK_AMD_DENSE]);CHKERRQ(ierr);
280   ierr = PetscViewerASCIIPrintf(viewer,"  Control[UMFPACK_BLOCK_SIZE]: %g\n",lu->Control[UMFPACK_BLOCK_SIZE]);CHKERRQ(ierr);
281   ierr = PetscViewerASCIIPrintf(viewer,"  Control[UMFPACK_FIXQ]: %g\n",lu->Control[UMFPACK_FIXQ]);CHKERRQ(ierr);
282   ierr = PetscViewerASCIIPrintf(viewer,"  Control[UMFPACK_AGGRESSIVE]: %g\n",lu->Control[UMFPACK_AGGRESSIVE]);CHKERRQ(ierr);
283 
284   /* Control parameters used by numeric factorization */
285   ierr = PetscViewerASCIIPrintf(viewer,"  Control[UMFPACK_PIVOT_TOLERANCE]: %g\n",lu->Control[UMFPACK_PIVOT_TOLERANCE]);CHKERRQ(ierr);
286   ierr = PetscViewerASCIIPrintf(viewer,"  Control[UMFPACK_SYM_PIVOT_TOLERANCE]: %g\n",lu->Control[UMFPACK_SYM_PIVOT_TOLERANCE]);CHKERRQ(ierr);
287   ierr = PetscViewerASCIIPrintf(viewer,"  Control[UMFPACK_SCALE]: %g\n",lu->Control[UMFPACK_SCALE]);CHKERRQ(ierr);
288   ierr = PetscViewerASCIIPrintf(viewer,"  Control[UMFPACK_ALLOC_INIT]: %g\n",lu->Control[UMFPACK_ALLOC_INIT]);CHKERRQ(ierr);
289   ierr = PetscViewerASCIIPrintf(viewer,"  Control[UMFPACK_DROPTOL]: %g\n",lu->Control[UMFPACK_DROPTOL]);CHKERRQ(ierr);
290 
291   /* Control parameters used by solve */
292   ierr = PetscViewerASCIIPrintf(viewer,"  Control[UMFPACK_IRSTEP]: %g\n",lu->Control[UMFPACK_IRSTEP]);CHKERRQ(ierr);
293 
294   /* mat ordering */
295   if (!lu->perm_c) {
296     ierr = PetscViewerASCIIPrintf(viewer,"  Control[UMFPACK_ORDERING]: AMD (not using the PETSc ordering)\n",UmfpackOrderingTypes[(int)lu->Control[UMFPACK_ORDERING]]);CHKERRQ(ierr);
297   }
298   PetscFunctionReturn(0);
299 }
300 
301 static PetscErrorCode MatView_UMFPACK(Mat A,PetscViewer viewer)
302 {
303   PetscErrorCode    ierr;
304   PetscBool         iascii;
305   PetscViewerFormat format;
306 
307   PetscFunctionBegin;
308   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
309   if (iascii) {
310     ierr = PetscViewerGetFormat(viewer,&format);CHKERRQ(ierr);
311     if (format == PETSC_VIEWER_ASCII_INFO) {
312       ierr = MatView_Info_UMFPACK(A,viewer);CHKERRQ(ierr);
313     }
314   }
315   PetscFunctionReturn(0);
316 }
317 
318 PetscErrorCode MatFactorGetSolverType_seqaij_umfpack(Mat A,MatSolverType *type)
319 {
320   PetscFunctionBegin;
321   *type = MATSOLVERUMFPACK;
322   PetscFunctionReturn(0);
323 }
324 
325 /*MC
326   MATSOLVERUMFPACK = "umfpack" - A matrix type providing direct solvers (LU) for sequential matrices
327   via the external package UMFPACK.
328 
329   Use ./configure --download-suitesparse to install PETSc to use UMFPACK
330 
331   Use -pc_type lu -pc_factor_mat_solver_type umfpack to use this direct solver
332 
333   Consult UMFPACK documentation for more information about the Control parameters
334   which correspond to the options database keys below.
335 
336   Options Database Keys:
337 + -mat_umfpack_ordering                - CHOLMOD, AMD, GIVEN, METIS, BEST, NONE
338 . -mat_umfpack_prl                     - UMFPACK print level: Control[UMFPACK_PRL]
339 . -mat_umfpack_strategy <AUTO>         - (choose one of) AUTO UNSYMMETRIC SYMMETRIC 2BY2
340 . -mat_umfpack_dense_col <alpha_c>     - UMFPACK dense column threshold: Control[UMFPACK_DENSE_COL]
341 . -mat_umfpack_dense_row <0.2>         - Control[UMFPACK_DENSE_ROW]
342 . -mat_umfpack_amd_dense <10>          - Control[UMFPACK_AMD_DENSE]
343 . -mat_umfpack_block_size <bs>         - UMFPACK block size for BLAS-Level 3 calls: Control[UMFPACK_BLOCK_SIZE]
344 . -mat_umfpack_2by2_tolerance <0.01>   - Control[UMFPACK_2BY2_TOLERANCE]
345 . -mat_umfpack_fixq <0>                - Control[UMFPACK_FIXQ]
346 . -mat_umfpack_aggressive <1>          - Control[UMFPACK_AGGRESSIVE]
347 . -mat_umfpack_pivot_tolerance <delta> - UMFPACK partial pivot tolerance: Control[UMFPACK_PIVOT_TOLERANCE]
348 . -mat_umfpack_sym_pivot_tolerance <0.001> - Control[UMFPACK_SYM_PIVOT_TOLERANCE]
349 . -mat_umfpack_scale <NONE>           - (choose one of) NONE SUM MAX
350 . -mat_umfpack_alloc_init <delta>      - UMFPACK factorized matrix allocation modifier: Control[UMFPACK_ALLOC_INIT]
351 . -mat_umfpack_droptol <0>            - Control[UMFPACK_DROPTOL]
352 - -mat_umfpack_irstep <maxit>          - UMFPACK maximum number of iterative refinement steps: Control[UMFPACK_IRSTEP]
353 
354    Level: beginner
355 
356    Note: UMFPACK is part of SuiteSparse http://faculty.cse.tamu.edu/davis/suitesparse.html
357 
358 .seealso: PCLU, MATSOLVERSUPERLU, MATSOLVERMUMPS, PCFactorSetMatSolverType(), MatSolverType
359 M*/
360 
361 PETSC_EXTERN PetscErrorCode MatGetFactor_seqaij_umfpack(Mat A,MatFactorType ftype,Mat *F)
362 {
363   Mat            B;
364   Mat_UMFPACK    *lu;
365   PetscErrorCode ierr;
366   PetscInt       m=A->rmap->n,n=A->cmap->n,idx;
367   const char     *strategy[]={"AUTO","UNSYMMETRIC","SYMMETRIC"};
368   const char     *scale[]   ={"NONE","SUM","MAX"};
369   PetscBool      flg;
370 
371   PetscFunctionBegin;
372   /* Create the factorization matrix F */
373   ierr = MatCreate(PetscObjectComm((PetscObject)A),&B);CHKERRQ(ierr);
374   ierr = MatSetSizes(B,PETSC_DECIDE,PETSC_DECIDE,m,n);CHKERRQ(ierr);
375   ierr = PetscStrallocpy("umfpack",&((PetscObject)B)->type_name);CHKERRQ(ierr);
376   ierr = MatSetUp(B);CHKERRQ(ierr);
377 
378   ierr = PetscNewLog(B,&lu);CHKERRQ(ierr);
379 
380   B->data                   = lu;
381   B->ops->getinfo          = MatGetInfo_External;
382   B->ops->lufactorsymbolic = MatLUFactorSymbolic_UMFPACK;
383   B->ops->destroy          = MatDestroy_UMFPACK;
384   B->ops->view             = MatView_UMFPACK;
385   B->ops->matsolve         = NULL;
386 
387   ierr = PetscObjectComposeFunction((PetscObject)B,"MatFactorGetSolverType_C",MatFactorGetSolverType_seqaij_umfpack);CHKERRQ(ierr);
388 
389   B->factortype   = MAT_FACTOR_LU;
390   B->assembled    = PETSC_TRUE;           /* required by -ksp_view */
391   B->preallocated = PETSC_TRUE;
392 
393   ierr = PetscFree(B->solvertype);CHKERRQ(ierr);
394   ierr = PetscStrallocpy(MATSOLVERUMFPACK,&B->solvertype);CHKERRQ(ierr);
395   B->canuseordering = PETSC_TRUE;
396   ierr = PetscStrallocpy(MATORDERINGEXTERNAL,(char**)&B->preferredordering[MAT_FACTOR_LU]);CHKERRQ(ierr);
397 
398   /* initializations */
399   /* ------------------------------------------------*/
400   /* get the default control parameters */
401   umfpack_UMF_defaults(lu->Control);
402   lu->perm_c                  = NULL; /* use defaul UMFPACK col permutation */
403   lu->Control[UMFPACK_IRSTEP] = 0;          /* max num of iterative refinement steps to attempt */
404 
405   ierr = PetscOptionsBegin(PetscObjectComm((PetscObject)A),((PetscObject)A)->prefix,"UMFPACK Options","Mat");CHKERRQ(ierr);
406   /* Control parameters used by reporting routiones */
407   ierr = PetscOptionsReal("-mat_umfpack_prl","Control[UMFPACK_PRL]","None",lu->Control[UMFPACK_PRL],&lu->Control[UMFPACK_PRL],NULL);CHKERRQ(ierr);
408 
409   /* Control parameters for symbolic factorization */
410   ierr = PetscOptionsEList("-mat_umfpack_strategy","ordering and pivoting strategy","None",strategy,3,strategy[0],&idx,&flg);CHKERRQ(ierr);
411   if (flg) {
412     switch (idx) {
413     case 0: lu->Control[UMFPACK_STRATEGY] = UMFPACK_STRATEGY_AUTO; break;
414     case 1: lu->Control[UMFPACK_STRATEGY] = UMFPACK_STRATEGY_UNSYMMETRIC; break;
415     case 2: lu->Control[UMFPACK_STRATEGY] = UMFPACK_STRATEGY_SYMMETRIC; break;
416     }
417   }
418   ierr = PetscOptionsEList("-mat_umfpack_ordering","Internal ordering method","None",UmfpackOrderingTypes,sizeof(UmfpackOrderingTypes)/sizeof(UmfpackOrderingTypes[0]),UmfpackOrderingTypes[(int)lu->Control[UMFPACK_ORDERING]],&idx,&flg);CHKERRQ(ierr);
419   if (flg) lu->Control[UMFPACK_ORDERING] = (int)idx;
420   ierr = PetscOptionsReal("-mat_umfpack_dense_col","Control[UMFPACK_DENSE_COL]","None",lu->Control[UMFPACK_DENSE_COL],&lu->Control[UMFPACK_DENSE_COL],NULL);CHKERRQ(ierr);
421   ierr = PetscOptionsReal("-mat_umfpack_dense_row","Control[UMFPACK_DENSE_ROW]","None",lu->Control[UMFPACK_DENSE_ROW],&lu->Control[UMFPACK_DENSE_ROW],NULL);CHKERRQ(ierr);
422   ierr = PetscOptionsReal("-mat_umfpack_amd_dense","Control[UMFPACK_AMD_DENSE]","None",lu->Control[UMFPACK_AMD_DENSE],&lu->Control[UMFPACK_AMD_DENSE],NULL);CHKERRQ(ierr);
423   ierr = PetscOptionsReal("-mat_umfpack_block_size","Control[UMFPACK_BLOCK_SIZE]","None",lu->Control[UMFPACK_BLOCK_SIZE],&lu->Control[UMFPACK_BLOCK_SIZE],NULL);CHKERRQ(ierr);
424   ierr = PetscOptionsReal("-mat_umfpack_fixq","Control[UMFPACK_FIXQ]","None",lu->Control[UMFPACK_FIXQ],&lu->Control[UMFPACK_FIXQ],NULL);CHKERRQ(ierr);
425   ierr = PetscOptionsReal("-mat_umfpack_aggressive","Control[UMFPACK_AGGRESSIVE]","None",lu->Control[UMFPACK_AGGRESSIVE],&lu->Control[UMFPACK_AGGRESSIVE],NULL);CHKERRQ(ierr);
426 
427   /* Control parameters used by numeric factorization */
428   ierr = PetscOptionsReal("-mat_umfpack_pivot_tolerance","Control[UMFPACK_PIVOT_TOLERANCE]","None",lu->Control[UMFPACK_PIVOT_TOLERANCE],&lu->Control[UMFPACK_PIVOT_TOLERANCE],NULL);CHKERRQ(ierr);
429   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],NULL);CHKERRQ(ierr);
430   ierr = PetscOptionsEList("-mat_umfpack_scale","Control[UMFPACK_SCALE]","None",scale,3,scale[0],&idx,&flg);CHKERRQ(ierr);
431   if (flg) {
432     switch (idx) {
433     case 0: lu->Control[UMFPACK_SCALE] = UMFPACK_SCALE_NONE; break;
434     case 1: lu->Control[UMFPACK_SCALE] = UMFPACK_SCALE_SUM; break;
435     case 2: lu->Control[UMFPACK_SCALE] = UMFPACK_SCALE_MAX; break;
436     }
437   }
438   ierr = PetscOptionsReal("-mat_umfpack_alloc_init","Control[UMFPACK_ALLOC_INIT]","None",lu->Control[UMFPACK_ALLOC_INIT],&lu->Control[UMFPACK_ALLOC_INIT],NULL);CHKERRQ(ierr);
439   ierr = PetscOptionsReal("-mat_umfpack_front_alloc_init","Control[UMFPACK_FRONT_ALLOC_INIT]","None",lu->Control[UMFPACK_FRONT_ALLOC_INIT],&lu->Control[UMFPACK_ALLOC_INIT],NULL);CHKERRQ(ierr);
440   ierr = PetscOptionsReal("-mat_umfpack_droptol","Control[UMFPACK_DROPTOL]","None",lu->Control[UMFPACK_DROPTOL],&lu->Control[UMFPACK_DROPTOL],NULL);CHKERRQ(ierr);
441 
442   /* Control parameters used by solve */
443   ierr = PetscOptionsReal("-mat_umfpack_irstep","Control[UMFPACK_IRSTEP]","None",lu->Control[UMFPACK_IRSTEP],&lu->Control[UMFPACK_IRSTEP],NULL);CHKERRQ(ierr);
444   PetscOptionsEnd();
445   *F = B;
446   PetscFunctionReturn(0);
447 }
448 
449 PETSC_INTERN PetscErrorCode MatGetFactor_seqaij_cholmod(Mat,MatFactorType,Mat*);
450 PETSC_INTERN PetscErrorCode MatGetFactor_seqsbaij_cholmod(Mat,MatFactorType,Mat*);
451 PETSC_INTERN PetscErrorCode MatGetFactor_seqaij_klu(Mat,MatFactorType,Mat*);
452 PETSC_INTERN PetscErrorCode MatGetFactor_seqaij_spqr(Mat,MatFactorType,Mat*);
453 
454 PETSC_EXTERN PetscErrorCode MatSolverTypeRegister_SuiteSparse(void)
455 {
456   PetscErrorCode ierr;
457 
458   PetscFunctionBegin;
459   ierr = MatSolverTypeRegister(MATSOLVERUMFPACK,MATSEQAIJ,  MAT_FACTOR_LU,MatGetFactor_seqaij_umfpack);CHKERRQ(ierr);
460   ierr = MatSolverTypeRegister(MATSOLVERCHOLMOD,MATSEQAIJ,  MAT_FACTOR_CHOLESKY,MatGetFactor_seqaij_cholmod);CHKERRQ(ierr);
461   ierr = MatSolverTypeRegister(MATSOLVERCHOLMOD,MATSEQSBAIJ,MAT_FACTOR_CHOLESKY,MatGetFactor_seqsbaij_cholmod);CHKERRQ(ierr);
462   ierr = MatSolverTypeRegister(MATSOLVERKLU,MATSEQAIJ,      MAT_FACTOR_LU,MatGetFactor_seqaij_klu);CHKERRQ(ierr);
463   ierr = MatSolverTypeRegister(MATSOLVERSPQR,MATSEQAIJ,     MAT_FACTOR_QR,MatGetFactor_seqaij_spqr);CHKERRQ(ierr);
464   if (!PetscDefined(USE_COMPLEX)) {
465     ierr = MatSolverTypeRegister(MATSOLVERSPQR,MATNORMAL,   MAT_FACTOR_QR,MatGetFactor_seqaij_spqr);CHKERRQ(ierr);
466   }
467   ierr = MatSolverTypeRegister(MATSOLVERSPQR,MATNORMALHERMITIAN, MAT_FACTOR_QR,MatGetFactor_seqaij_spqr);CHKERRQ(ierr);
468   PetscFunctionReturn(0);
469 }
470