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