xref: /petsc/src/mat/impls/aij/seq/superlu/superlu.c (revision ee1cef2c4f92b4b45b8aa3ceac59cb944062fab9)
1 #define PETSCMAT_DLL
2 
3 /*  --------------------------------------------------------------------
4 
5      This file implements a subclass of the SeqAIJ matrix class that uses
6      the SuperLU 3.0 sparse solver. You can use this as a starting point for
7      implementing your own subclass of a PETSc matrix class.
8 
9      This demonstrates a way to make an implementation inheritence of a PETSc
10      matrix type. This means constructing a new matrix type (SuperLU) by changing some
11      of the methods of the previous type (SeqAIJ), adding additional data, and possibly
12      additional method. (See any book on object oriented programming).
13 */
14 
15 /*
16      Defines the data structure for the base matrix type (SeqAIJ)
17 */
18 #include "../src/mat/impls/aij/seq/aij.h"
19 
20 /*
21      SuperLU include files
22 */
23 EXTERN_C_BEGIN
24 #if defined(PETSC_USE_COMPLEX)
25 #include "slu_zdefs.h"
26 #else
27 #include "slu_ddefs.h"
28 #endif
29 #include "slu_util.h"
30 EXTERN_C_END
31 
32 /*
33      This is the data we are "ADDING" to the SeqAIJ matrix type to get the SuperLU matrix type
34 */
35 typedef struct {
36   SuperMatrix       A,L,U,B,X;
37   superlu_options_t options;
38   PetscInt          *perm_c; /* column permutation vector */
39   PetscInt          *perm_r; /* row permutations from partial pivoting */
40   PetscInt          *etree;
41   PetscReal         *R, *C;
42   char              equed[1];
43   PetscInt          lwork;
44   void              *work;
45   PetscReal         rpg, rcond;
46   mem_usage_t       mem_usage;
47   MatStructure      flg;
48 
49   /* Flag to clean up (non-global) SuperLU objects during Destroy */
50   PetscTruth CleanUpSuperLU;
51 } Mat_SuperLU;
52 
53 extern PetscErrorCode MatFactorInfo_SuperLU(Mat,PetscViewer);
54 extern PetscErrorCode MatLUFactorNumeric_SuperLU(Mat,Mat,const MatFactorInfo *);
55 extern PetscErrorCode MatDestroy_SuperLU(Mat);
56 extern PetscErrorCode MatView_SuperLU(Mat,PetscViewer);
57 extern PetscErrorCode MatAssemblyEnd_SuperLU(Mat,MatAssemblyType);
58 extern PetscErrorCode MatSolve_SuperLU(Mat,Vec,Vec);
59 extern PetscErrorCode MatSolveTranspose_SuperLU(Mat,Vec,Vec);
60 extern PetscErrorCode MatLUFactorSymbolic_SuperLU(Mat,Mat,IS,IS,const MatFactorInfo*);
61 extern PetscErrorCode MatDuplicate_SuperLU(Mat, MatDuplicateOption, Mat *);
62 
63 /*
64     Utility function
65 */
66 #undef __FUNCT__
67 #define __FUNCT__ "MatFactorInfo_SuperLU"
68 PetscErrorCode MatFactorInfo_SuperLU(Mat A,PetscViewer viewer)
69 {
70   Mat_SuperLU       *lu= (Mat_SuperLU*)A->spptr;
71   PetscErrorCode    ierr;
72   superlu_options_t options;
73 
74   PetscFunctionBegin;
75   /* check if matrix is superlu_dist type */
76   if (A->ops->solve != MatSolve_SuperLU) PetscFunctionReturn(0);
77 
78   options = lu->options;
79   ierr = PetscViewerASCIIPrintf(viewer,"SuperLU run parameters:\n");CHKERRQ(ierr);
80   ierr = PetscViewerASCIIPrintf(viewer,"  Equil: %s\n",(options.Equil != NO) ? "YES": "NO");CHKERRQ(ierr);
81   ierr = PetscViewerASCIIPrintf(viewer,"  ColPerm: %D\n",options.ColPerm);CHKERRQ(ierr);
82   ierr = PetscViewerASCIIPrintf(viewer,"  IterRefine: %D\n",options.IterRefine);CHKERRQ(ierr);
83   ierr = PetscViewerASCIIPrintf(viewer,"  SymmetricMode: %s\n",(options.SymmetricMode != NO) ? "YES": "NO");CHKERRQ(ierr);
84   ierr = PetscViewerASCIIPrintf(viewer,"  DiagPivotThresh: %g\n",options.DiagPivotThresh);CHKERRQ(ierr);
85   ierr = PetscViewerASCIIPrintf(viewer,"  PivotGrowth: %s\n",(options.PivotGrowth != NO) ? "YES": "NO");CHKERRQ(ierr);
86   ierr = PetscViewerASCIIPrintf(viewer,"  ConditionNumber: %s\n",(options.ConditionNumber != NO) ? "YES": "NO");CHKERRQ(ierr);
87   ierr = PetscViewerASCIIPrintf(viewer,"  RowPerm: %D\n",options.RowPerm);CHKERRQ(ierr);
88   ierr = PetscViewerASCIIPrintf(viewer,"  ReplaceTinyPivot: %s\n",(options.ReplaceTinyPivot != NO) ? "YES": "NO");CHKERRQ(ierr);
89   ierr = PetscViewerASCIIPrintf(viewer,"  PrintStat: %s\n",(options.PrintStat != NO) ? "YES": "NO");CHKERRQ(ierr);
90   ierr = PetscViewerASCIIPrintf(viewer,"  lwork: %D\n",lu->lwork);CHKERRQ(ierr);
91   PetscFunctionReturn(0);
92 }
93 
94 /*
95     These are the methods provided to REPLACE the corresponding methods of the
96    SeqAIJ matrix class. Other methods of SeqAIJ are not replaced
97 */
98 #undef __FUNCT__
99 #define __FUNCT__ "MatLUFactorNumeric_SuperLU"
100 PetscErrorCode MatLUFactorNumeric_SuperLU(Mat F,Mat A,const MatFactorInfo *info)
101 {
102   Mat_SeqAIJ     *aa = (Mat_SeqAIJ*)(A)->data;
103   Mat_SuperLU    *lu = (Mat_SuperLU*)(F)->spptr;
104   PetscErrorCode ierr;
105   PetscInt       sinfo;
106   SuperLUStat_t  stat;
107   PetscReal      ferr, berr;
108   NCformat       *Ustore;
109   SCformat       *Lstore;
110 
111   PetscFunctionBegin;
112   if (lu->flg == SAME_NONZERO_PATTERN){ /* successing numerical factorization */
113     lu->options.Fact = SamePattern;
114     /* Ref: ~SuperLU_3.0/EXAMPLE/dlinsolx2.c */
115     Destroy_SuperMatrix_Store(&lu->A);
116     if ( lu->lwork >= 0 ) {
117       Destroy_SuperNode_Matrix(&lu->L);
118       Destroy_CompCol_Matrix(&lu->U);
119       lu->options.Fact = SamePattern;
120     }
121   }
122 
123   /* Create the SuperMatrix for lu->A=A^T:
124        Since SuperLU likes column-oriented matrices,we pass it the transpose,
125        and then solve A^T X = B in MatSolve(). */
126 #if defined(PETSC_USE_COMPLEX)
127   zCreate_CompCol_Matrix(&lu->A,A->cmap->n,A->rmap->n,aa->nz,(doublecomplex*)aa->a,aa->j,aa->i,
128                            SLU_NC,SLU_Z,SLU_GE);
129 #else
130   dCreate_CompCol_Matrix(&lu->A,A->cmap->n,A->rmap->n,aa->nz,aa->a,aa->j,aa->i,
131                            SLU_NC,SLU_D,SLU_GE);
132 #endif
133 
134   /* Initialize the statistics variables. */
135   StatInit(&stat);
136 
137   /* Numerical factorization */
138   lu->B.ncol = 0;  /* Indicate not to solve the system */
139 #if defined(PETSC_USE_COMPLEX)
140    zgssvx(&lu->options, &lu->A, lu->perm_c, lu->perm_r, lu->etree, lu->equed, lu->R, lu->C,
141            &lu->L, &lu->U, lu->work, lu->lwork, &lu->B, &lu->X, &lu->rpg, &lu->rcond, &ferr, &berr,
142            &lu->mem_usage, &stat, &sinfo);
143 #else
144   dgssvx(&lu->options, &lu->A, lu->perm_c, lu->perm_r, lu->etree, lu->equed, lu->R, lu->C,
145            &lu->L, &lu->U, lu->work, lu->lwork, &lu->B, &lu->X, &lu->rpg, &lu->rcond, &ferr, &berr,
146            &lu->mem_usage, &stat, &sinfo);
147 #endif
148   if ( !sinfo || sinfo == lu->A.ncol+1 ) {
149     if ( lu->options.PivotGrowth )
150       ierr = PetscPrintf(PETSC_COMM_SELF,"  Recip. pivot growth = %e\n", lu->rpg);
151     if ( lu->options.ConditionNumber )
152       ierr = PetscPrintf(PETSC_COMM_SELF,"  Recip. condition number = %e\n", lu->rcond);
153   } else if ( sinfo > 0 ){
154     if ( lu->lwork == -1 ) {
155       ierr = PetscPrintf(PETSC_COMM_SELF,"  ** Estimated memory: %D bytes\n", sinfo - lu->A.ncol);
156     } else {
157       ierr = PetscPrintf(PETSC_COMM_SELF,"  Warning: gssvx() returns info %D\n",sinfo);
158     }
159   } else { /* sinfo < 0 */
160     SETERRQ2(PETSC_ERR_LIB, "info = %D, the %D-th argument in gssvx() had an illegal value", sinfo,-sinfo);
161   }
162 
163   if ( lu->options.PrintStat ) {
164     ierr = PetscPrintf(PETSC_COMM_SELF,"MatLUFactorNumeric_SuperLU():\n");
165     StatPrint(&stat);
166     Lstore = (SCformat *) lu->L.Store;
167     Ustore = (NCformat *) lu->U.Store;
168     ierr = PetscPrintf(PETSC_COMM_SELF,"  No of nonzeros in factor L = %D\n", Lstore->nnz);
169     ierr = PetscPrintf(PETSC_COMM_SELF,"  No of nonzeros in factor U = %D\n", Ustore->nnz);
170     ierr = PetscPrintf(PETSC_COMM_SELF,"  No of nonzeros in L+U = %D\n", Lstore->nnz + Ustore->nnz - lu->A.ncol);
171     ierr = PetscPrintf(PETSC_COMM_SELF,"  L\\U MB %.3f\ttotal MB needed %.3f\n",
172 	       lu->mem_usage.for_lu/1e6, lu->mem_usage.total_needed/1e6);
173   }
174   StatFree(&stat);
175 
176   lu->flg = SAME_NONZERO_PATTERN;
177   (F)->ops->solve            = MatSolve_SuperLU;
178   (F)->ops->solvetranspose   = MatSolveTranspose_SuperLU;
179   PetscFunctionReturn(0);
180 }
181 
182 #undef __FUNCT__
183 #define __FUNCT__ "MatDestroy_SuperLU"
184 PetscErrorCode MatDestroy_SuperLU(Mat A)
185 {
186   PetscErrorCode ierr;
187   Mat_SuperLU    *lu=(Mat_SuperLU*)A->spptr;
188 
189   PetscFunctionBegin;
190   if (lu->CleanUpSuperLU) { /* Free the SuperLU datastructures */
191     Destroy_SuperMatrix_Store(&lu->A);
192     Destroy_SuperMatrix_Store(&lu->B);
193     Destroy_SuperMatrix_Store(&lu->X);
194 
195     ierr = PetscFree(lu->etree);CHKERRQ(ierr);
196     ierr = PetscFree(lu->perm_r);CHKERRQ(ierr);
197     ierr = PetscFree(lu->perm_c);CHKERRQ(ierr);
198     ierr = PetscFree(lu->R);CHKERRQ(ierr);
199     ierr = PetscFree(lu->C);CHKERRQ(ierr);
200     if ( lu->lwork >= 0 ) {
201       Destroy_SuperNode_Matrix(&lu->L);
202       Destroy_CompCol_Matrix(&lu->U);
203     }
204   }
205   ierr = MatDestroy_SeqAIJ(A);CHKERRQ(ierr);
206   PetscFunctionReturn(0);
207 }
208 
209 #undef __FUNCT__
210 #define __FUNCT__ "MatView_SuperLU"
211 PetscErrorCode MatView_SuperLU(Mat A,PetscViewer viewer)
212 {
213   PetscErrorCode    ierr;
214   PetscTruth        iascii;
215   PetscViewerFormat format;
216 
217   PetscFunctionBegin;
218   ierr = MatView_SeqAIJ(A,viewer);CHKERRQ(ierr);
219 
220   ierr = PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_ASCII,&iascii);CHKERRQ(ierr);
221   if (iascii) {
222     ierr = PetscViewerGetFormat(viewer,&format);CHKERRQ(ierr);
223     if (format == PETSC_VIEWER_ASCII_INFO) {
224       ierr = MatFactorInfo_SuperLU(A,viewer);CHKERRQ(ierr);
225     }
226   }
227   PetscFunctionReturn(0);
228 }
229 
230 
231 #undef __FUNCT__
232 #define __FUNCT__ "MatSolve_SuperLU_Private"
233 PetscErrorCode MatSolve_SuperLU_Private(Mat A,Vec b,Vec x)
234 {
235   Mat_SuperLU    *lu = (Mat_SuperLU*)A->spptr;
236   PetscScalar    *barray,*xarray;
237   PetscErrorCode ierr;
238   PetscInt       info,i;
239   SuperLUStat_t  stat;
240   PetscReal      ferr,berr;
241 
242   PetscFunctionBegin;
243   if ( lu->lwork == -1 ) {
244     PetscFunctionReturn(0);
245   }
246   lu->B.ncol = 1;   /* Set the number of right-hand side */
247   ierr = VecGetArray(b,&barray);CHKERRQ(ierr);
248   ierr = VecGetArray(x,&xarray);CHKERRQ(ierr);
249 
250 #if defined(PETSC_USE_COMPLEX)
251   ((DNformat*)lu->B.Store)->nzval = (doublecomplex*)barray;
252   ((DNformat*)lu->X.Store)->nzval = (doublecomplex*)xarray;
253 #else
254   ((DNformat*)lu->B.Store)->nzval = barray;
255   ((DNformat*)lu->X.Store)->nzval = xarray;
256 #endif
257 
258   /* Initialize the statistics variables. */
259   StatInit(&stat);
260 
261   lu->options.Fact  = FACTORED; /* Indicate the factored form of A is supplied. */
262 #if defined(PETSC_USE_COMPLEX)
263   zgssvx(&lu->options, &lu->A, lu->perm_c, lu->perm_r, lu->etree, lu->equed, lu->R, lu->C,
264            &lu->L, &lu->U, lu->work, lu->lwork, &lu->B, &lu->X, &lu->rpg, &lu->rcond, &ferr, &berr,
265            &lu->mem_usage, &stat, &info);
266 #else
267   dgssvx(&lu->options, &lu->A, lu->perm_c, lu->perm_r, lu->etree, lu->equed, lu->R, lu->C,
268            &lu->L, &lu->U, lu->work, lu->lwork, &lu->B, &lu->X, &lu->rpg, &lu->rcond, &ferr, &berr,
269            &lu->mem_usage, &stat, &info);
270 #endif
271   ierr = VecRestoreArray(b,&barray);CHKERRQ(ierr);
272   ierr = VecRestoreArray(x,&xarray);CHKERRQ(ierr);
273 
274   if ( !info || info == lu->A.ncol+1 ) {
275     if ( lu->options.IterRefine ) {
276       ierr = PetscPrintf(PETSC_COMM_SELF,"Iterative Refinement:\n");
277       ierr = PetscPrintf(PETSC_COMM_SELF,"  %8s%8s%16s%16s\n", "rhs", "Steps", "FERR", "BERR");
278       for (i = 0; i < 1; ++i)
279         ierr = PetscPrintf(PETSC_COMM_SELF,"  %8d%8d%16e%16e\n", i+1, stat.RefineSteps, ferr, berr);
280     }
281   } else if ( info > 0 ){
282     if ( lu->lwork == -1 ) {
283       ierr = PetscPrintf(PETSC_COMM_SELF,"  ** Estimated memory: %D bytes\n", info - lu->A.ncol);
284     } else {
285       ierr = PetscPrintf(PETSC_COMM_SELF,"  Warning: gssvx() returns info %D\n",info);
286     }
287   } else if (info < 0){
288     SETERRQ2(PETSC_ERR_LIB, "info = %D, the %D-th argument in gssvx() had an illegal value", info,-info);
289   }
290 
291   if ( lu->options.PrintStat ) {
292     ierr = PetscPrintf(PETSC_COMM_SELF,"MatSolve__SuperLU():\n");
293     StatPrint(&stat);
294   }
295   StatFree(&stat);
296   PetscFunctionReturn(0);
297 }
298 
299 #undef __FUNCT__
300 #define __FUNCT__ "MatSolve_SuperLU"
301 PetscErrorCode MatSolve_SuperLU(Mat A,Vec b,Vec x)
302 {
303   Mat_SuperLU    *lu = (Mat_SuperLU*)A->spptr;
304   PetscErrorCode ierr;
305 
306   PetscFunctionBegin;
307   lu->options.Trans = TRANS;
308   ierr = MatSolve_SuperLU_Private(A,b,x);CHKERRQ(ierr);
309   PetscFunctionReturn(0);
310 }
311 
312 #undef __FUNCT__
313 #define __FUNCT__ "MatSolveTranspose_SuperLU"
314 PetscErrorCode MatSolveTranspose_SuperLU(Mat A,Vec b,Vec x)
315 {
316   Mat_SuperLU    *lu = (Mat_SuperLU*)A->spptr;
317   PetscErrorCode ierr;
318 
319   PetscFunctionBegin;
320   lu->options.Trans = NOTRANS;
321   ierr = MatSolve_SuperLU_Private(A,b,x);CHKERRQ(ierr);
322   PetscFunctionReturn(0);
323 }
324 
325 
326 /*
327    Note the r permutation is ignored
328 */
329 #undef __FUNCT__
330 #define __FUNCT__ "MatLUFactorSymbolic_SuperLU"
331 PetscErrorCode MatLUFactorSymbolic_SuperLU(Mat F,Mat A,IS r,IS c,const MatFactorInfo *info)
332 {
333   Mat_SuperLU    *lu = (Mat_SuperLU*)((F)->spptr);
334   PetscErrorCode ierr;
335   PetscInt       m=A->rmap->n,n=A->cmap->n;
336 
337   PetscFunctionBegin;
338 
339   /* Allocate spaces (notice sizes are for the transpose) */
340   ierr = PetscMalloc(m*sizeof(PetscInt),&lu->etree);CHKERRQ(ierr);
341   ierr = PetscMalloc(n*sizeof(PetscInt),&lu->perm_r);CHKERRQ(ierr);
342   ierr = PetscMalloc(m*sizeof(PetscInt),&lu->perm_c);CHKERRQ(ierr);
343   ierr = PetscMalloc(n*sizeof(PetscInt),&lu->R);CHKERRQ(ierr);
344   ierr = PetscMalloc(m*sizeof(PetscInt),&lu->C);CHKERRQ(ierr);
345 
346   /* create rhs and solution x without allocate space for .Store */
347 #if defined(PETSC_USE_COMPLEX)
348   zCreate_Dense_Matrix(&lu->B, m, 1, PETSC_NULL, m, SLU_DN, SLU_Z, SLU_GE);
349   zCreate_Dense_Matrix(&lu->X, m, 1, PETSC_NULL, m, SLU_DN, SLU_Z, SLU_GE);
350 #else
351   dCreate_Dense_Matrix(&lu->B, m, 1, PETSC_NULL, m, SLU_DN, SLU_D, SLU_GE);
352   dCreate_Dense_Matrix(&lu->X, m, 1, PETSC_NULL, m, SLU_DN, SLU_D, SLU_GE);
353 #endif
354 
355   lu->flg            = DIFFERENT_NONZERO_PATTERN;
356   lu->CleanUpSuperLU = PETSC_TRUE;
357   (F)->ops->lufactornumeric  = MatLUFactorNumeric_SuperLU;
358   PetscFunctionReturn(0);
359 }
360 
361 EXTERN_C_BEGIN
362 #undef __FUNCT__
363 #define __FUNCT__ "MatFactorGetSolverPackage_seqaij_superlu"
364 PetscErrorCode MatFactorGetSolverPackage_seqaij_superlu(Mat A,const MatSolverPackage *type)
365 {
366   PetscFunctionBegin;
367   *type = MAT_SOLVER_SUPERLU;
368   PetscFunctionReturn(0);
369 }
370 EXTERN_C_END
371 
372 
373 /*MC
374   MAT_SOLVER_SUPERLU = "superlu" - A solver package roviding direct solvers (LU) for sequential matrices
375   via the external package SuperLU.
376 
377   Use config/configure.py --download-superlu to have PETSc installed with SuperLU
378 
379   Options Database Keys:
380 + -mat_superlu_ordering <0,1,2,3> - 0: natural ordering,
381                                     1: MMD applied to A'*A,
382                                     2: MMD applied to A'+A,
383                                     3: COLAMD, approximate minimum degree column ordering
384 . -mat_superlu_iterrefine - have SuperLU do iterative refinement after the triangular solve
385                           choices: NOREFINE, SINGLE, DOUBLE, EXTRA; default is NOREFINE
386 - -mat_superlu_printstat - print SuperLU statistics about the factorization
387 
388    Notes: Do not confuse this with MAT_SOLVER_SUPERLU_DIST which is for parallel sparse solves
389 
390    Level: beginner
391 
392 .seealso: PCLU, MAT_SOLVER_SUPERLU_DIST, MAT_SOLVER_MUMPS, MAT_SOLVER_SPOOLES, PCFactorSetMatSolverPackage(), MatSolverPackage
393 M*/
394 
395 EXTERN_C_BEGIN
396 #undef __FUNCT__
397 #define __FUNCT__ "MatGetFactor_seqaij_superlu"
398 PetscErrorCode MatGetFactor_seqaij_superlu(Mat A,MatFactorType ftype,Mat *F)
399 {
400   Mat            B;
401   Mat_SuperLU    *lu;
402   PetscErrorCode ierr;
403   PetscInt       indx;
404   PetscTruth     flg;
405   const char     *colperm[]={"NATURAL","MMD_ATA","MMD_AT_PLUS_A","COLAMD"}; /* MY_PERMC - not supported by the petsc interface yet */
406   const char     *iterrefine[]={"NOREFINE", "SINGLE", "DOUBLE", "EXTRA"};
407   const char     *rowperm[]={"NOROWPERM", "LargeDiag"}; /* MY_PERMC - not supported by the petsc interface yet */
408 
409   PetscFunctionBegin;
410   ierr = MatCreate(((PetscObject)A)->comm,&B);CHKERRQ(ierr);
411   ierr = MatSetSizes(B,A->rmap->n,A->cmap->n,PETSC_DETERMINE,PETSC_DETERMINE);CHKERRQ(ierr);
412   ierr = MatSetType(B,((PetscObject)A)->type_name);CHKERRQ(ierr);
413   ierr = MatSeqAIJSetPreallocation(B,0,PETSC_NULL);CHKERRQ(ierr);
414 
415   B->ops->lufactorsymbolic = MatLUFactorSymbolic_SuperLU;
416   B->ops->destroy          = MatDestroy_SuperLU;
417   B->ops->view             = MatView_SuperLU;
418   B->factor                = MAT_FACTOR_LU;
419   B->assembled             = PETSC_TRUE;  /* required by -ksp_view */
420   B->preallocated          = PETSC_TRUE;
421 
422   ierr = PetscNewLog(B,Mat_SuperLU,&lu);CHKERRQ(ierr);
423   set_default_options(&lu->options);
424   /* equilibration causes error in solve(), thus not supported here. See dgssvx.c for possible reason. */
425   lu->options.Equil = NO;
426   lu->options.PrintStat = NO;
427   lu->lwork = 0;   /* allocate space internally by system malloc */
428 
429   ierr = PetscOptionsBegin(((PetscObject)A)->comm,((PetscObject)A)->prefix,"SuperLU Options","Mat");CHKERRQ(ierr);
430     ierr = PetscOptionsEList("-mat_superlu_colperm","ColPerm","None",colperm,4,colperm[3],&indx,&flg);CHKERRQ(ierr);
431     if (flg) {lu->options.ColPerm = (colperm_t)indx;}
432     ierr = PetscOptionsEList("-mat_superlu_iterrefine","IterRefine","None",iterrefine,4,iterrefine[0],&indx,&flg);CHKERRQ(ierr);
433     if (flg) { lu->options.IterRefine = (IterRefine_t)indx;}
434     ierr = PetscOptionsTruth("-mat_superlu_symmetricmode","SymmetricMode","None",PETSC_FALSE,&flg,0);CHKERRQ(ierr);
435     if (flg) lu->options.SymmetricMode = YES;
436     ierr = PetscOptionsReal("-mat_superlu_diagpivotthresh","DiagPivotThresh","None",lu->options.DiagPivotThresh,&lu->options.DiagPivotThresh,PETSC_NULL);CHKERRQ(ierr);
437     ierr = PetscOptionsTruth("-mat_superlu_pivotgrowth","PivotGrowth","None",PETSC_FALSE,&flg,0);CHKERRQ(ierr);
438     if (flg) lu->options.PivotGrowth = YES;
439     ierr = PetscOptionsTruth("-mat_superlu_conditionnumber","ConditionNumber","None",PETSC_FALSE,&flg,0);CHKERRQ(ierr);
440     if (flg) lu->options.ConditionNumber = YES;
441     ierr = PetscOptionsEList("-mat_superlu_rowperm","rowperm","None",rowperm,2,rowperm[0],&indx,&flg);CHKERRQ(ierr);
442     if (flg) {lu->options.RowPerm = (rowperm_t)indx;}
443     ierr = PetscOptionsTruth("-mat_superlu_replacetinypivot","ReplaceTinyPivot","None",PETSC_FALSE,&flg,0);CHKERRQ(ierr);
444     if (flg) lu->options.ReplaceTinyPivot = YES;
445     ierr = PetscOptionsTruth("-mat_superlu_printstat","PrintStat","None",PETSC_FALSE,&flg,0);CHKERRQ(ierr);
446     if (flg) lu->options.PrintStat = YES;
447     ierr = PetscOptionsInt("-mat_superlu_lwork","size of work array in bytes used by factorization","None",lu->lwork,&lu->lwork,PETSC_NULL);CHKERRQ(ierr);
448     if (lu->lwork > 0 ){
449       ierr = PetscMalloc(lu->lwork,&lu->work);CHKERRQ(ierr);
450     } else if (lu->lwork != 0 && lu->lwork != -1){
451       ierr = PetscPrintf(PETSC_COMM_SELF,"   Warning: lwork %D is not supported by SUPERLU. The default lwork=0 is used.\n",lu->lwork);
452       lu->lwork = 0;
453     }
454   PetscOptionsEnd();
455 
456 #ifdef SUPERLU2
457   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatCreateNull","MatCreateNull_SuperLU",(void(*)(void))MatCreateNull_SuperLU);CHKERRQ(ierr);
458 #endif
459   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatFactorGetSolverPackage_C","MatFactorGetSolverPackage_seqaij_superlu",MatFactorGetSolverPackage_seqaij_superlu);CHKERRQ(ierr);
460   B->spptr = lu;
461   *F = B;
462   PetscFunctionReturn(0);
463 }
464 EXTERN_C_END
465