xref: /petsc/src/mat/impls/aij/seq/superlu/superlu.c (revision b24902e06ab141841ce6546a773244be2474cd18)
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,MatFactorInfo *,Mat *);
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,IS,IS,MatFactorInfo *,Mat *);
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 A,MatFactorInfo *info,Mat *F)
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   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   Mat_SuperLU       *lu=(Mat_SuperLU*)(A->spptr);
217 
218   PetscFunctionBegin;
219   ierr = MatView_SeqAIJ(A,viewer);CHKERRQ(ierr);
220 
221   ierr = PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_ASCII,&iascii);CHKERRQ(ierr);
222   if (iascii) {
223     ierr = PetscViewerGetFormat(viewer,&format);CHKERRQ(ierr);
224     if (format == PETSC_VIEWER_ASCII_INFO) {
225       ierr = MatFactorInfo_SuperLU(A,viewer);CHKERRQ(ierr);
226     }
227   }
228   PetscFunctionReturn(0);
229 }
230 
231 
232 #undef __FUNCT__
233 #define __FUNCT__ "MatSolve_SuperLU_Private"
234 PetscErrorCode MatSolve_SuperLU_Private(Mat A,Vec b,Vec x)
235 {
236   Mat_SuperLU    *lu = (Mat_SuperLU*)A->spptr;
237   PetscScalar    *barray,*xarray;
238   PetscErrorCode ierr;
239   PetscInt       info,i;
240   SuperLUStat_t  stat;
241   PetscReal      ferr,berr;
242 
243   PetscFunctionBegin;
244   if ( lu->lwork == -1 ) {
245     PetscFunctionReturn(0);
246   }
247   lu->B.ncol = 1;   /* Set the number of right-hand side */
248   ierr = VecGetArray(b,&barray);CHKERRQ(ierr);
249   ierr = VecGetArray(x,&xarray);CHKERRQ(ierr);
250 
251 #if defined(PETSC_USE_COMPLEX)
252   ((DNformat*)lu->B.Store)->nzval = (doublecomplex*)barray;
253   ((DNformat*)lu->X.Store)->nzval = (doublecomplex*)xarray;
254 #else
255   ((DNformat*)lu->B.Store)->nzval = barray;
256   ((DNformat*)lu->X.Store)->nzval = xarray;
257 #endif
258 
259   /* Initialize the statistics variables. */
260   StatInit(&stat);
261 
262   lu->options.Fact  = FACTORED; /* Indicate the factored form of A is supplied. */
263 #if defined(PETSC_USE_COMPLEX)
264   zgssvx(&lu->options, &lu->A, lu->perm_c, lu->perm_r, lu->etree, lu->equed, lu->R, lu->C,
265            &lu->L, &lu->U, lu->work, lu->lwork, &lu->B, &lu->X, &lu->rpg, &lu->rcond, &ferr, &berr,
266            &lu->mem_usage, &stat, &info);
267 #else
268   dgssvx(&lu->options, &lu->A, lu->perm_c, lu->perm_r, lu->etree, lu->equed, lu->R, lu->C,
269            &lu->L, &lu->U, lu->work, lu->lwork, &lu->B, &lu->X, &lu->rpg, &lu->rcond, &ferr, &berr,
270            &lu->mem_usage, &stat, &info);
271 #endif
272   ierr = VecRestoreArray(b,&barray);CHKERRQ(ierr);
273   ierr = VecRestoreArray(x,&xarray);CHKERRQ(ierr);
274 
275   if ( !info || info == lu->A.ncol+1 ) {
276     if ( lu->options.IterRefine ) {
277       ierr = PetscPrintf(PETSC_COMM_SELF,"Iterative Refinement:\n");
278       ierr = PetscPrintf(PETSC_COMM_SELF,"  %8s%8s%16s%16s\n", "rhs", "Steps", "FERR", "BERR");
279       for (i = 0; i < 1; ++i)
280         ierr = PetscPrintf(PETSC_COMM_SELF,"  %8d%8d%16e%16e\n", i+1, stat.RefineSteps, ferr, berr);
281     }
282   } else if ( info > 0 ){
283     if ( lu->lwork == -1 ) {
284       ierr = PetscPrintf(PETSC_COMM_SELF,"  ** Estimated memory: %D bytes\n", info - lu->A.ncol);
285     } else {
286       ierr = PetscPrintf(PETSC_COMM_SELF,"  Warning: gssvx() returns info %D\n",info);
287     }
288   } else if (info < 0){
289     SETERRQ2(PETSC_ERR_LIB, "info = %D, the %D-th argument in gssvx() had an illegal value", info,-info);
290   }
291 
292   if ( lu->options.PrintStat ) {
293     ierr = PetscPrintf(PETSC_COMM_SELF,"MatSolve__SuperLU():\n");
294     StatPrint(&stat);
295   }
296   StatFree(&stat);
297   PetscFunctionReturn(0);
298 }
299 
300 #undef __FUNCT__
301 #define __FUNCT__ "MatSolve_SuperLU"
302 PetscErrorCode MatSolve_SuperLU(Mat A,Vec b,Vec x)
303 {
304   Mat_SuperLU    *lu = (Mat_SuperLU*)A->spptr;
305   PetscErrorCode ierr;
306 
307   PetscFunctionBegin;
308   lu->options.Trans = TRANS;
309   ierr = MatSolve_SuperLU_Private(A,b,x);CHKERRQ(ierr);
310   PetscFunctionReturn(0);
311 }
312 
313 #undef __FUNCT__
314 #define __FUNCT__ "MatSolveTranspose_SuperLU"
315 PetscErrorCode MatSolveTranspose_SuperLU(Mat A,Vec b,Vec x)
316 {
317   Mat_SuperLU    *lu = (Mat_SuperLU*)A->spptr;
318   PetscErrorCode ierr;
319 
320   PetscFunctionBegin;
321   lu->options.Trans = NOTRANS;
322   ierr = MatSolve_SuperLU_Private(A,b,x);CHKERRQ(ierr);
323   PetscFunctionReturn(0);
324 }
325 
326 
327 /*
328    Note the r permutation is ignored
329 */
330 #undef __FUNCT__
331 #define __FUNCT__ "MatLUFactorSymbolic_SuperLU"
332 PetscErrorCode MatLUFactorSymbolic_SuperLU(Mat A,IS r,IS c,MatFactorInfo *info,Mat *F)
333 {
334   Mat_SuperLU    *lu = (Mat_SuperLU*)((*F)->spptr);
335   PetscErrorCode ierr;
336   PetscInt       m=A->rmap.n,n=A->cmap.n,indx;
337 
338   PetscFunctionBegin;
339 
340   /* Allocate spaces (notice sizes are for the transpose) */
341   ierr = PetscMalloc(m*sizeof(PetscInt),&lu->etree);CHKERRQ(ierr);
342   ierr = PetscMalloc(n*sizeof(PetscInt),&lu->perm_r);CHKERRQ(ierr);
343   ierr = PetscMalloc(m*sizeof(PetscInt),&lu->perm_c);CHKERRQ(ierr);
344   ierr = PetscMalloc(n*sizeof(PetscInt),&lu->R);CHKERRQ(ierr);
345   ierr = PetscMalloc(m*sizeof(PetscInt),&lu->C);CHKERRQ(ierr);
346 
347   /* create rhs and solution x without allocate space for .Store */
348 #if defined(PETSC_USE_COMPLEX)
349   zCreate_Dense_Matrix(&lu->B, m, 1, PETSC_NULL, m, SLU_DN, SLU_Z, SLU_GE);
350   zCreate_Dense_Matrix(&lu->X, m, 1, PETSC_NULL, m, SLU_DN, SLU_Z, SLU_GE);
351 #else
352   dCreate_Dense_Matrix(&lu->B, m, 1, PETSC_NULL, m, SLU_DN, SLU_D, SLU_GE);
353   dCreate_Dense_Matrix(&lu->X, m, 1, PETSC_NULL, m, SLU_DN, SLU_D, SLU_GE);
354 #endif
355 
356   lu->flg            = DIFFERENT_NONZERO_PATTERN;
357   lu->CleanUpSuperLU = PETSC_TRUE;
358   PetscFunctionReturn(0);
359 }
360 
361 
362 /*MC
363   MATSUPERLU - MATSUPERLU = "superlu" - A matrix type providing direct solvers (LU) for sequential matrices
364   via the external package SuperLU.
365 
366   If SuperLU is installed (see the manual for
367   instructions on how to declare the existence of external packages),
368   a matrix type can be constructed which invokes SuperLU solvers.
369   After calling MatCreate(...,A), simply call MatSetType(A,MATSUPERLU), then
370   optionally call MatSeqAIJSetPreallocation() or MatMPIAIJSetPreallocation() DO NOT
371   call MatCreateSeqAIJ/MPIAIJ() directly or the preallocation information will be LOST!
372 
373   This matrix inherits from MATSEQAIJ.  As a result, MatSeqAIJSetPreallocation() is
374   supported for this matrix type.  One can also call MatConvert() for an inplace conversion to or from
375   the MATSEQAIJ type AFTER the matrix values are set without data copy.
376 
377   Options Database Keys:
378 + -mat_type superlu - sets the matrix type to "superlu" during a call to MatSetFromOptions()
379 . -mat_superlu_ordering <0,1,2,3> - 0: natural ordering,
380                                     1: MMD applied to A'*A,
381                                     2: MMD applied to A'+A,
382                                     3: COLAMD, approximate minimum degree column ordering
383 . -mat_superlu_iterrefine - have SuperLU do iterative refinement after the triangular solve
384                           choices: NOREFINE, SINGLE, DOUBLE, EXTRA; default is NOREFINE
385 - -mat_superlu_printstat - print SuperLU statistics about the factorization
386 
387    Level: beginner
388 
389 .seealso: PCLU
390 M*/
391 
392 #undef __FUNCT__
393 #define __FUNCT__ "MatGetFactor_seqaij_superlu"
394 PetscErrorCode MatGetFactor_seqaij_superlu(Mat A,Mat *F)
395 {
396   Mat            B;
397   Mat_SuperLU    *lu;
398   PetscErrorCode ierr;
399   PetscInt       m=A->rmap.n,n=A->cmap.n,indx;
400   PetscTruth     flg;
401   const char     *colperm[]={"NATURAL","MMD_ATA","MMD_AT_PLUS_A","COLAMD"}; /* MY_PERMC - not supported by the petsc interface yet */
402   const char     *iterrefine[]={"NOREFINE", "SINGLE", "DOUBLE", "EXTRA"};
403   const char     *rowperm[]={"NOROWPERM", "LargeDiag"}; /* MY_PERMC - not supported by the petsc interface yet */
404 
405   PetscFunctionBegin;
406   ierr = MatCreate(((PetscObject)A)->comm,&B);CHKERRQ(ierr);
407   ierr = MatSetSizes(B,A->rmap.n,A->cmap.n,PETSC_DETERMINE,PETSC_DETERMINE);CHKERRQ(ierr);
408   ierr = MatSetType(B,((PetscObject)A)->type_name);CHKERRQ(ierr);
409   ierr = MatSeqAIJSetPreallocation(B,0,PETSC_NULL);CHKERRQ(ierr);
410 
411   B->ops->lufactornumeric  = MatLUFactorNumeric_SuperLU;
412   B->ops->lufactorsymbolic = MatLUFactorSymbolic_SuperLU;
413   B->ops->solve            = MatSolve_SuperLU;
414   B->ops->solvetranspose   = MatSolveTranspose_SuperLU;
415   B->ops->destroy          = MatDestroy_SuperLU;
416   B->factor               = FACTOR_LU;
417   B->assembled            = PETSC_TRUE;  /* required by -ksp_view */
418 
419   ierr = PetscNewLog(B,Mat_SuperLU,&lu);CHKERRQ(ierr);
420   set_default_options(&lu->options);
421   /* equilibration causes error in solve(), thus not supported here. See dgssvx.c for possible reason. */
422   lu->options.Equil = NO;
423   lu->options.PrintStat = NO;
424   lu->lwork = 0;   /* allocate space internally by system malloc */
425 
426   ierr = PetscOptionsBegin(((PetscObject)A)->comm,((PetscObject)A)->prefix,"SuperLU Options","Mat");CHKERRQ(ierr);
427   ierr = PetscOptionsEList("-mat_superlu_colperm","ColPerm","None",colperm,4,colperm[3],&indx,&flg);CHKERRQ(ierr);
428   if (flg) {lu->options.ColPerm = (colperm_t)indx;}
429   ierr = PetscOptionsEList("-mat_superlu_iterrefine","IterRefine","None",iterrefine,4,iterrefine[0],&indx,&flg);CHKERRQ(ierr);
430   if (flg) { lu->options.IterRefine = (IterRefine_t)indx;}
431   ierr = PetscOptionsTruth("-mat_superlu_symmetricmode","SymmetricMode","None",PETSC_FALSE,&flg,0);CHKERRQ(ierr);
432   if (flg) lu->options.SymmetricMode = YES;
433   ierr = PetscOptionsReal("-mat_superlu_diagpivotthresh","DiagPivotThresh","None",lu->options.DiagPivotThresh,&lu->options.DiagPivotThresh,PETSC_NULL);CHKERRQ(ierr);
434   ierr = PetscOptionsTruth("-mat_superlu_pivotgrowth","PivotGrowth","None",PETSC_FALSE,&flg,0);CHKERRQ(ierr);
435   if (flg) lu->options.PivotGrowth = YES;
436   ierr = PetscOptionsTruth("-mat_superlu_conditionnumber","ConditionNumber","None",PETSC_FALSE,&flg,0);CHKERRQ(ierr);
437   if (flg) lu->options.ConditionNumber = YES;
438   ierr = PetscOptionsEList("-mat_superlu_rowperm","rowperm","None",rowperm,2,rowperm[0],&indx,&flg);CHKERRQ(ierr);
439   if (flg) {lu->options.RowPerm = (rowperm_t)indx;}
440   ierr = PetscOptionsTruth("-mat_superlu_replacetinypivot","ReplaceTinyPivot","None",PETSC_FALSE,&flg,0);CHKERRQ(ierr);
441   if (flg) lu->options.ReplaceTinyPivot = YES;
442   ierr = PetscOptionsTruth("-mat_superlu_printstat","PrintStat","None",PETSC_FALSE,&flg,0);CHKERRQ(ierr);
443   if (flg) lu->options.PrintStat = YES;
444   ierr = PetscOptionsInt("-mat_superlu_lwork","size of work array in bytes used by factorization","None",lu->lwork,&lu->lwork,PETSC_NULL);CHKERRQ(ierr);
445   if (lu->lwork > 0 ){
446     ierr = PetscMalloc(lu->lwork,&lu->work);CHKERRQ(ierr);
447   } else if (lu->lwork != 0 && lu->lwork != -1){
448     ierr = PetscPrintf(PETSC_COMM_SELF,"   Warning: lwork %D is not supported by SUPERLU. The default lwork=0 is used.\n",lu->lwork);
449     lu->lwork = 0;
450   }
451   PetscOptionsEnd();
452 
453 #ifdef SUPERLU2
454   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatCreateNull","MatCreateNull_SuperLU",
455                                     (void(*)(void))MatCreateNull_SuperLU);CHKERRQ(ierr);
456 #endif
457   *F = B;
458   PetscFunctionReturn(0);
459 }
460