xref: /petsc/src/mat/impls/aij/seq/superlu/superlu.c (revision 09573ac72a50d3e7ecd55a2b7f0ef28450cd0a8b)
1 #define PETSCMAT_DLL
2 
3 /*  --------------------------------------------------------------------
4 
5      This file implements a subclass of the SeqAIJ matrix class that uses
6      the SuperLU 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   SuperLUStat_t     stat;
49   Mat               A_dup;
50   PetscScalar       *rhs_dup;
51 
52   /* Flag to clean up (non-global) SuperLU objects during Destroy */
53   PetscBool  CleanUpSuperLU;
54 } Mat_SuperLU;
55 
56 extern PetscErrorCode MatFactorInfo_SuperLU(Mat,PetscViewer);
57 extern PetscErrorCode MatLUFactorNumeric_SuperLU(Mat,Mat,const MatFactorInfo *);
58 extern PetscErrorCode MatDestroy_SuperLU(Mat);
59 extern PetscErrorCode MatView_SuperLU(Mat,PetscViewer);
60 extern PetscErrorCode MatAssemblyEnd_SuperLU(Mat,MatAssemblyType);
61 extern PetscErrorCode MatSolve_SuperLU(Mat,Vec,Vec);
62 extern PetscErrorCode MatSolveTranspose_SuperLU(Mat,Vec,Vec);
63 extern PetscErrorCode MatLUFactorSymbolic_SuperLU(Mat,Mat,IS,IS,const MatFactorInfo*);
64 extern PetscErrorCode MatDuplicate_SuperLU(Mat, MatDuplicateOption, Mat *);
65 
66 /*
67     Utility function
68 */
69 #undef __FUNCT__
70 #define __FUNCT__ "MatFactorInfo_SuperLU"
71 PetscErrorCode MatFactorInfo_SuperLU(Mat A,PetscViewer viewer)
72 {
73   Mat_SuperLU       *lu= (Mat_SuperLU*)A->spptr;
74   PetscErrorCode    ierr;
75   superlu_options_t options;
76 
77   PetscFunctionBegin;
78   /* check if matrix is superlu_dist type */
79   if (A->ops->solve != MatSolve_SuperLU) PetscFunctionReturn(0);
80 
81   options = lu->options;
82   ierr = PetscViewerASCIIPrintf(viewer,"SuperLU run parameters:\n");CHKERRQ(ierr);
83   ierr = PetscViewerASCIIPrintf(viewer,"  Equil: %s\n",(options.Equil != NO) ? "YES": "NO");CHKERRQ(ierr);
84   ierr = PetscViewerASCIIPrintf(viewer,"  ColPerm: %D\n",options.ColPerm);CHKERRQ(ierr);
85   ierr = PetscViewerASCIIPrintf(viewer,"  IterRefine: %D\n",options.IterRefine);CHKERRQ(ierr);
86   ierr = PetscViewerASCIIPrintf(viewer,"  SymmetricMode: %s\n",(options.SymmetricMode != NO) ? "YES": "NO");CHKERRQ(ierr);
87   ierr = PetscViewerASCIIPrintf(viewer,"  DiagPivotThresh: %g\n",options.DiagPivotThresh);CHKERRQ(ierr);
88   ierr = PetscViewerASCIIPrintf(viewer,"  PivotGrowth: %s\n",(options.PivotGrowth != NO) ? "YES": "NO");CHKERRQ(ierr);
89   ierr = PetscViewerASCIIPrintf(viewer,"  ConditionNumber: %s\n",(options.ConditionNumber != NO) ? "YES": "NO");CHKERRQ(ierr);
90   ierr = PetscViewerASCIIPrintf(viewer,"  RowPerm: %D\n",options.RowPerm);CHKERRQ(ierr);
91   ierr = PetscViewerASCIIPrintf(viewer,"  ReplaceTinyPivot: %s\n",(options.ReplaceTinyPivot != NO) ? "YES": "NO");CHKERRQ(ierr);
92   ierr = PetscViewerASCIIPrintf(viewer,"  PrintStat: %s\n",(options.PrintStat != NO) ? "YES": "NO");CHKERRQ(ierr);
93   ierr = PetscViewerASCIIPrintf(viewer,"  lwork: %D\n",lu->lwork);CHKERRQ(ierr);
94   if (A->factortype == MAT_FACTOR_ILU){
95     ierr = PetscViewerASCIIPrintf(viewer,"  ILU_DropTol: %g\n",options.ILU_DropTol);CHKERRQ(ierr);
96     ierr = PetscViewerASCIIPrintf(viewer,"  ILU_FillTol: %g\n",options.ILU_FillTol);CHKERRQ(ierr);
97     ierr = PetscViewerASCIIPrintf(viewer,"  ILU_FillFactor: %g\n",options.ILU_FillFactor);CHKERRQ(ierr);
98     ierr = PetscViewerASCIIPrintf(viewer,"  ILU_DropRule: %D\n",options.ILU_DropRule);CHKERRQ(ierr);
99     ierr = PetscViewerASCIIPrintf(viewer,"  ILU_Norm: %D\n",options.ILU_Norm);CHKERRQ(ierr);
100     ierr = PetscViewerASCIIPrintf(viewer,"  ILU_MILU: %D\n",options.ILU_MILU);CHKERRQ(ierr);
101   }
102   PetscFunctionReturn(0);
103 }
104 
105 /*
106     These are the methods provided to REPLACE the corresponding methods of the
107    SeqAIJ matrix class. Other methods of SeqAIJ are not replaced
108 */
109 #undef __FUNCT__
110 #define __FUNCT__ "MatLUFactorNumeric_SuperLU"
111 PetscErrorCode MatLUFactorNumeric_SuperLU(Mat F,Mat A,const MatFactorInfo *info)
112 {
113   Mat_SuperLU    *lu = (Mat_SuperLU*)(F)->spptr;
114   Mat_SeqAIJ     *aa;
115   PetscErrorCode ierr;
116   PetscInt       sinfo;
117   PetscReal      ferr, berr;
118   NCformat       *Ustore;
119   SCformat       *Lstore;
120 
121   PetscFunctionBegin;
122   if (lu->flg == SAME_NONZERO_PATTERN){ /* successing numerical factorization */
123     lu->options.Fact = SamePattern;
124     /* Ref: ~SuperLU_3.0/EXAMPLE/dlinsolx2.c */
125     Destroy_SuperMatrix_Store(&lu->A);
126     if (lu->options.Equil){
127       ierr = MatCopy_SeqAIJ(A,lu->A_dup,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
128     }
129     if ( lu->lwork >= 0 ) {
130       Destroy_SuperNode_Matrix(&lu->L);
131       Destroy_CompCol_Matrix(&lu->U);
132       lu->options.Fact = SamePattern;
133     }
134   }
135 
136   /* Create the SuperMatrix for lu->A=A^T:
137        Since SuperLU likes column-oriented matrices,we pass it the transpose,
138        and then solve A^T X = B in MatSolve(). */
139   if (lu->options.Equil){
140     aa = (Mat_SeqAIJ*)(lu->A_dup)->data;
141   } else {
142     aa = (Mat_SeqAIJ*)(A)->data;
143   }
144 #if defined(PETSC_USE_COMPLEX)
145   zCreate_CompCol_Matrix(&lu->A,A->cmap->n,A->rmap->n,aa->nz,(doublecomplex*)aa->a,aa->j,aa->i,
146                            SLU_NC,SLU_Z,SLU_GE);
147 #else
148   dCreate_CompCol_Matrix(&lu->A,A->cmap->n,A->rmap->n,aa->nz,aa->a,aa->j,aa->i,
149                            SLU_NC,SLU_D,SLU_GE);
150 #endif
151 
152   /* Numerical factorization */
153   lu->B.ncol = 0;  /* Indicate not to solve the system */
154   if (F->factortype == MAT_FACTOR_LU){
155 #if defined(PETSC_USE_COMPLEX)
156     zgssvx(&lu->options, &lu->A, lu->perm_c, lu->perm_r, lu->etree, lu->equed, lu->R, lu->C,
157            &lu->L, &lu->U, lu->work, lu->lwork, &lu->B, &lu->X, &lu->rpg, &lu->rcond, &ferr, &berr,
158            &lu->mem_usage, &lu->stat, &sinfo);
159 #else
160     dgssvx(&lu->options, &lu->A, lu->perm_c, lu->perm_r, lu->etree, lu->equed, lu->R, lu->C,
161            &lu->L, &lu->U, lu->work, lu->lwork, &lu->B, &lu->X, &lu->rpg, &lu->rcond, &ferr, &berr,
162            &lu->mem_usage, &lu->stat, &sinfo);
163 #endif
164   } else if (F->factortype == MAT_FACTOR_ILU){
165     /* Compute the incomplete factorization, condition number and pivot growth */
166 #if defined(PETSC_USE_COMPLEX)
167     zgsisx(&lu->options, &lu->A, lu->perm_c, lu->perm_r,lu->etree, lu->equed, lu->R, lu->C,
168            &lu->L, &lu->U, lu->work, lu->lwork, &lu->B, &lu->X, &lu->rpg, &lu->rcond,
169            &lu->mem_usage, &lu->stat, &sinfo);
170 #else
171     dgsisx(&lu->options, &lu->A, lu->perm_c, lu->perm_r, lu->etree, lu->equed, lu->R, lu->C,
172           &lu->L, &lu->U, lu->work, lu->lwork, &lu->B, &lu->X, &lu->rpg, &lu->rcond,
173           &lu->mem_usage, &lu->stat, &sinfo);
174 #endif
175   } else {
176     SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Factor type not supported");
177   }
178   if ( !sinfo || sinfo == lu->A.ncol+1 ) {
179     if ( lu->options.PivotGrowth )
180       ierr = PetscPrintf(PETSC_COMM_SELF,"  Recip. pivot growth = %e\n", lu->rpg);
181     if ( lu->options.ConditionNumber )
182       ierr = PetscPrintf(PETSC_COMM_SELF,"  Recip. condition number = %e\n", lu->rcond);
183   } else if ( sinfo > 0 ){
184     if ( lu->lwork == -1 ) {
185       ierr = PetscPrintf(PETSC_COMM_SELF,"  ** Estimated memory: %D bytes\n", sinfo - lu->A.ncol);
186     } else SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_MAT_LU_ZRPVT,"Zero pivot in row %D",sinfo);
187   } else { /* sinfo < 0 */
188     SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_LIB, "info = %D, the %D-th argument in gssvx() had an illegal value", sinfo,-sinfo);
189   }
190 
191   if ( lu->options.PrintStat ) {
192     ierr = PetscPrintf(PETSC_COMM_SELF,"MatLUFactorNumeric_SuperLU():\n");
193     StatPrint(&lu->stat);
194     Lstore = (SCformat *) lu->L.Store;
195     Ustore = (NCformat *) lu->U.Store;
196     ierr = PetscPrintf(PETSC_COMM_SELF,"  No of nonzeros in factor L = %D\n", Lstore->nnz);
197     ierr = PetscPrintf(PETSC_COMM_SELF,"  No of nonzeros in factor U = %D\n", Ustore->nnz);
198     ierr = PetscPrintf(PETSC_COMM_SELF,"  No of nonzeros in L+U = %D\n", Lstore->nnz + Ustore->nnz - lu->A.ncol);
199     ierr = PetscPrintf(PETSC_COMM_SELF,"  L\\U MB %.3f\ttotal MB needed %.3f\n",
200 	       lu->mem_usage.for_lu/1e6, lu->mem_usage.total_needed/1e6);
201   }
202 
203   lu->flg = SAME_NONZERO_PATTERN;
204   (F)->ops->solve          = MatSolve_SuperLU;
205   (F)->ops->solvetranspose = MatSolveTranspose_SuperLU;
206   PetscFunctionReturn(0);
207 }
208 
209 #undef __FUNCT__
210 #define __FUNCT__ "MatDestroy_SuperLU"
211 PetscErrorCode MatDestroy_SuperLU(Mat A)
212 {
213   PetscErrorCode ierr;
214   Mat_SuperLU    *lu=(Mat_SuperLU*)A->spptr;
215 
216   PetscFunctionBegin;
217   if (lu->CleanUpSuperLU) { /* Free the SuperLU datastructures */
218     Destroy_SuperMatrix_Store(&lu->A);
219     Destroy_SuperMatrix_Store(&lu->B);
220     Destroy_SuperMatrix_Store(&lu->X);
221     StatFree(&lu->stat);
222     if ( lu->lwork >= 0 ) {
223       Destroy_SuperNode_Matrix(&lu->L);
224       Destroy_CompCol_Matrix(&lu->U);
225     }
226 
227   }
228 
229   ierr = PetscFree(lu->etree);CHKERRQ(ierr);
230   ierr = PetscFree(lu->perm_r);CHKERRQ(ierr);
231   ierr = PetscFree(lu->perm_c);CHKERRQ(ierr);
232   ierr = PetscFree(lu->R);CHKERRQ(ierr);
233   ierr = PetscFree(lu->C);CHKERRQ(ierr);
234 
235   ierr = MatDestroy_SeqAIJ(A);CHKERRQ(ierr);
236   if (lu->A_dup){ierr = MatDestroy(lu->A_dup);CHKERRQ(ierr);}
237   if (lu->rhs_dup){ierr = PetscFree(lu->rhs_dup);CHKERRQ(ierr);}
238   PetscFunctionReturn(0);
239 }
240 
241 #undef __FUNCT__
242 #define __FUNCT__ "MatView_SuperLU"
243 PetscErrorCode MatView_SuperLU(Mat A,PetscViewer viewer)
244 {
245   PetscErrorCode    ierr;
246   PetscBool         iascii;
247   PetscViewerFormat format;
248 
249   PetscFunctionBegin;
250   ierr = PetscTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
251   if (iascii) {
252     ierr = PetscViewerGetFormat(viewer,&format);CHKERRQ(ierr);
253     if (format == PETSC_VIEWER_ASCII_INFO) {
254       ierr = MatFactorInfo_SuperLU(A,viewer);CHKERRQ(ierr);
255     }
256   }
257   PetscFunctionReturn(0);
258 }
259 
260 
261 #undef __FUNCT__
262 #define __FUNCT__ "MatSolve_SuperLU_Private"
263 PetscErrorCode MatSolve_SuperLU_Private(Mat A,Vec b,Vec x)
264 {
265   Mat_SuperLU    *lu = (Mat_SuperLU*)A->spptr;
266   PetscScalar    *barray,*xarray;
267   PetscErrorCode ierr;
268   PetscInt       info,i,n=x->map->n;
269   PetscReal      ferr,berr;
270 
271   PetscFunctionBegin;
272   if ( lu->lwork == -1 ) {
273     PetscFunctionReturn(0);
274   }
275 
276   lu->B.ncol = 1;   /* Set the number of right-hand side */
277   if (lu->options.Equil && !lu->rhs_dup){
278     /* superlu overwrites b when Equil is used, thus create rhs_dup to keep user's b unchanged */
279     ierr = PetscMalloc(n*sizeof(PetscScalar),&lu->rhs_dup);CHKERRQ(ierr);
280   }
281   if (lu->options.Equil){
282     /* Copy b into rsh_dup */
283     ierr = VecGetArray(b,&barray);CHKERRQ(ierr);
284     ierr = PetscMemcpy(lu->rhs_dup,barray,n*sizeof(PetscScalar));CHKERRQ(ierr);
285     ierr = VecRestoreArray(b,&barray);CHKERRQ(ierr);
286     barray = lu->rhs_dup;
287   } else {
288     ierr = VecGetArray(b,&barray);CHKERRQ(ierr);
289   }
290   ierr = VecGetArray(x,&xarray);CHKERRQ(ierr);
291 
292 #if defined(PETSC_USE_COMPLEX)
293   ((DNformat*)lu->B.Store)->nzval = (doublecomplex*)barray;
294   ((DNformat*)lu->X.Store)->nzval = (doublecomplex*)xarray;
295 #else
296   ((DNformat*)lu->B.Store)->nzval = barray;
297   ((DNformat*)lu->X.Store)->nzval = xarray;
298 #endif
299 
300   lu->options.Fact = FACTORED; /* Indicate the factored form of A is supplied. */
301   if (A->factortype == MAT_FACTOR_LU){
302 #if defined(PETSC_USE_COMPLEX)
303     zgssvx(&lu->options, &lu->A, lu->perm_c, lu->perm_r, lu->etree, lu->equed, lu->R, lu->C,
304            &lu->L, &lu->U, lu->work, lu->lwork, &lu->B, &lu->X, &lu->rpg, &lu->rcond, &ferr, &berr,
305            &lu->mem_usage, &lu->stat, &info);
306 #else
307     dgssvx(&lu->options, &lu->A, lu->perm_c, lu->perm_r, lu->etree, lu->equed, lu->R, lu->C,
308            &lu->L, &lu->U, lu->work, lu->lwork, &lu->B, &lu->X, &lu->rpg, &lu->rcond, &ferr, &berr,
309            &lu->mem_usage, &lu->stat, &info);
310 #endif
311   } else if (A->factortype == MAT_FACTOR_ILU){
312 #if defined(PETSC_USE_COMPLEX)
313     zgsisx(&lu->options, &lu->A, lu->perm_c, lu->perm_r, lu->etree, lu->equed, lu->R, lu->C,
314            &lu->L, &lu->U, lu->work, lu->lwork, &lu->B, &lu->X, &lu->rpg, &lu->rcond,
315            &lu->mem_usage, &lu->stat, &info);
316 #else
317     dgsisx(&lu->options, &lu->A, lu->perm_c, lu->perm_r, lu->etree, lu->equed, lu->R, lu->C,
318            &lu->L, &lu->U, lu->work, lu->lwork, &lu->B, &lu->X, &lu->rpg, &lu->rcond,
319            &lu->mem_usage, &lu->stat, &info);
320 #endif
321   } else {
322     SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Factor type not supported");
323   }
324   if (!lu->options.Equil){
325     ierr = VecRestoreArray(b,&barray);CHKERRQ(ierr);
326   }
327   ierr = VecRestoreArray(x,&xarray);CHKERRQ(ierr);
328 
329   if ( !info || info == lu->A.ncol+1 ) {
330     if ( lu->options.IterRefine ) {
331       ierr = PetscPrintf(PETSC_COMM_SELF,"Iterative Refinement:\n");
332       ierr = PetscPrintf(PETSC_COMM_SELF,"  %8s%8s%16s%16s\n", "rhs", "Steps", "FERR", "BERR");
333       for (i = 0; i < 1; ++i)
334         ierr = PetscPrintf(PETSC_COMM_SELF,"  %8d%8d%16e%16e\n", i+1, lu->stat.RefineSteps, ferr, berr);
335     }
336   } else if ( info > 0 ){
337     if ( lu->lwork == -1 ) {
338       ierr = PetscPrintf(PETSC_COMM_SELF,"  ** Estimated memory: %D bytes\n", info - lu->A.ncol);
339     } else {
340       ierr = PetscPrintf(PETSC_COMM_SELF,"  Warning: gssvx() returns info %D\n",info);
341     }
342   } else if (info < 0){
343     SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_LIB, "info = %D, the %D-th argument in gssvx() had an illegal value", info,-info);
344   }
345 
346   if ( lu->options.PrintStat ) {
347     ierr = PetscPrintf(PETSC_COMM_SELF,"MatSolve__SuperLU():\n");
348     StatPrint(&lu->stat);
349   }
350   PetscFunctionReturn(0);
351 }
352 
353 #undef __FUNCT__
354 #define __FUNCT__ "MatSolve_SuperLU"
355 PetscErrorCode MatSolve_SuperLU(Mat A,Vec b,Vec x)
356 {
357   Mat_SuperLU    *lu = (Mat_SuperLU*)A->spptr;
358   PetscErrorCode ierr;
359 
360   PetscFunctionBegin;
361   lu->options.Trans = TRANS;
362   ierr = MatSolve_SuperLU_Private(A,b,x);CHKERRQ(ierr);
363   PetscFunctionReturn(0);
364 }
365 
366 #undef __FUNCT__
367 #define __FUNCT__ "MatSolveTranspose_SuperLU"
368 PetscErrorCode MatSolveTranspose_SuperLU(Mat A,Vec b,Vec x)
369 {
370   Mat_SuperLU    *lu = (Mat_SuperLU*)A->spptr;
371   PetscErrorCode ierr;
372 
373   PetscFunctionBegin;
374   lu->options.Trans = NOTRANS;
375   ierr = MatSolve_SuperLU_Private(A,b,x);CHKERRQ(ierr);
376   PetscFunctionReturn(0);
377 }
378 
379 /*
380    Note the r permutation is ignored
381 */
382 #undef __FUNCT__
383 #define __FUNCT__ "MatLUFactorSymbolic_SuperLU"
384 PetscErrorCode MatLUFactorSymbolic_SuperLU(Mat F,Mat A,IS r,IS c,const MatFactorInfo *info)
385 {
386   Mat_SuperLU    *lu = (Mat_SuperLU*)((F)->spptr);
387 
388   PetscFunctionBegin;
389   lu->flg                   = DIFFERENT_NONZERO_PATTERN;
390   lu->CleanUpSuperLU        = PETSC_TRUE;
391   (F)->ops->lufactornumeric = MatLUFactorNumeric_SuperLU;
392   PetscFunctionReturn(0);
393 }
394 
395 EXTERN_C_BEGIN
396 #undef __FUNCT__
397 #define __FUNCT__ "MatFactorGetSolverPackage_seqaij_superlu"
398 PetscErrorCode MatFactorGetSolverPackage_seqaij_superlu(Mat A,const MatSolverPackage *type)
399 {
400   PetscFunctionBegin;
401   *type = MATSOLVERSUPERLU;
402   PetscFunctionReturn(0);
403 }
404 EXTERN_C_END
405 
406 
407 /*MC
408   MATSOLVERSUPERLU = "superlu" - A solver package providing solvers LU and ILU for sequential matrices
409   via the external package SuperLU.
410 
411   Use ./configure --download-superlu to have PETSc installed with SuperLU
412 
413   Options Database Keys:
414 +  -mat_superlu_equil: <FALSE> Equil (None)
415 .  -mat_superlu_colperm <COLAMD> (choose one of) NATURAL MMD_ATA MMD_AT_PLUS_A COLAMD
416 .  -mat_superlu_iterrefine <NOREFINE> (choose one of) NOREFINE SINGLE DOUBLE EXTRA
417 .  -mat_superlu_symmetricmode: <FALSE> SymmetricMode (None)
418 .  -mat_superlu_diagpivotthresh <1>: DiagPivotThresh (None)
419 .  -mat_superlu_pivotgrowth: <FALSE> PivotGrowth (None)
420 .  -mat_superlu_conditionnumber: <FALSE> ConditionNumber (None)
421 .  -mat_superlu_rowperm <NOROWPERM> (choose one of) NOROWPERM LargeDiag
422 .  -mat_superlu_replacetinypivot: <FALSE> ReplaceTinyPivot (None)
423 .  -mat_superlu_printstat: <FALSE> PrintStat (None)
424 .  -mat_superlu_lwork <0>: size of work array in bytes used by factorization (None)
425 .  -mat_superlu_ilu_droptol <0>: ILU_DropTol (None)
426 .  -mat_superlu_ilu_filltol <0>: ILU_FillTol (None)
427 .  -mat_superlu_ilu_fillfactor <0>: ILU_FillFactor (None)
428 .  -mat_superlu_ilu_droprull <0>: ILU_DropRule (None)
429 .  -mat_superlu_ilu_norm <0>: ILU_Norm (None)
430 -  -mat_superlu_ilu_milu <0>: ILU_MILU (None)
431 
432    Notes: Do not confuse this with MATSOLVERSUPERLU_DIST which is for parallel sparse solves
433 
434    Level: beginner
435 
436 .seealso: PCLU, PCILU, MATSOLVERSUPERLU_DIST, MATSOLVERMUMPS, MATSOLVERSPOOLES, PCFactorSetMatSolverPackage(), MatSolverPackage
437 M*/
438 
439 EXTERN_C_BEGIN
440 #undef __FUNCT__
441 #define __FUNCT__ "MatGetFactor_seqaij_superlu"
442 PetscErrorCode MatGetFactor_seqaij_superlu(Mat A,MatFactorType ftype,Mat *F)
443 {
444   Mat            B;
445   Mat_SuperLU    *lu;
446   PetscErrorCode ierr;
447   PetscInt       indx,m=A->rmap->n,n=A->cmap->n;
448   PetscBool      flg;
449   const char     *colperm[]={"NATURAL","MMD_ATA","MMD_AT_PLUS_A","COLAMD"}; /* MY_PERMC - not supported by the petsc interface yet */
450   const char     *iterrefine[]={"NOREFINE", "SINGLE", "DOUBLE", "EXTRA"};
451   const char     *rowperm[]={"NOROWPERM", "LargeDiag"}; /* MY_PERMC - not supported by the petsc interface yet */
452 
453   PetscFunctionBegin;
454   ierr = MatCreate(((PetscObject)A)->comm,&B);CHKERRQ(ierr);
455   ierr = MatSetSizes(B,A->rmap->n,A->cmap->n,PETSC_DETERMINE,PETSC_DETERMINE);CHKERRQ(ierr);
456   ierr = MatSetType(B,((PetscObject)A)->type_name);CHKERRQ(ierr);
457   ierr = MatSeqAIJSetPreallocation(B,0,PETSC_NULL);CHKERRQ(ierr);
458 
459   if (ftype == MAT_FACTOR_LU || ftype == MAT_FACTOR_ILU){
460     B->ops->lufactorsymbolic  = MatLUFactorSymbolic_SuperLU;
461     B->ops->ilufactorsymbolic = MatLUFactorSymbolic_SuperLU;
462   } else {
463     SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Factor type not supported");
464   }
465 
466   B->ops->destroy          = MatDestroy_SuperLU;
467   B->ops->view             = MatView_SuperLU;
468   B->factortype            = ftype;
469   B->assembled             = PETSC_TRUE;  /* required by -ksp_view */
470   B->preallocated          = PETSC_TRUE;
471 
472   ierr = PetscNewLog(B,Mat_SuperLU,&lu);CHKERRQ(ierr);
473 
474   if (ftype == MAT_FACTOR_LU){
475     set_default_options(&lu->options);
476     /* Comments from SuperLU_4.0/SRC/dgssvx.c:
477       "Whether or not the system will be equilibrated depends on the
478        scaling of the matrix A, but if equilibration is used, A is
479        overwritten by diag(R)*A*diag(C) and B by diag(R)*B
480        (if options->Trans=NOTRANS) or diag(C)*B (if options->Trans = TRANS or CONJ)."
481      We set 'options.Equil = NO' as default because additional space is needed for it.
482     */
483     lu->options.Equil     = NO;
484   } else if (ftype == MAT_FACTOR_ILU){
485     /* Set the default input options of ilu:
486 	options.Fact = DOFACT;
487 	options.Equil = YES;           // must be YES for ilu - don't know why
488 	options.ColPerm = COLAMD;
489 	options.DiagPivotThresh = 0.1; //different from complete LU
490 	options.Trans = NOTRANS;
491 	options.IterRefine = NOREFINE;
492 	options.SymmetricMode = NO;
493 	options.PivotGrowth = NO;
494 	options.ConditionNumber = NO;
495 	options.PrintStat = YES;
496 	options.RowPerm = LargeDiag;
497 	options.ILU_DropTol = 1e-4;
498 	options.ILU_FillTol = 1e-2;
499 	options.ILU_FillFactor = 10.0;
500 	options.ILU_DropRule = DROP_BASIC | DROP_AREA;
501 	options.ILU_Norm = INF_NORM;
502 	options.ILU_MILU = SMILU_2;
503     */
504     ilu_set_default_options(&lu->options);
505   }
506   lu->options.PrintStat = NO;
507 
508   /* Initialize the statistics variables. */
509   StatInit(&lu->stat);
510   lu->lwork = 0;   /* allocate space internally by system malloc */
511 
512   ierr = PetscOptionsBegin(((PetscObject)A)->comm,((PetscObject)A)->prefix,"SuperLU Options","Mat");CHKERRQ(ierr);
513     ierr = PetscOptionsBool("-mat_superlu_equil","Equil","None",(PetscBool)lu->options.Equil,(PetscBool*)&lu->options.Equil,0);CHKERRQ(ierr);
514     ierr = PetscOptionsEList("-mat_superlu_colperm","ColPerm","None",colperm,4,colperm[3],&indx,&flg);CHKERRQ(ierr);
515     if (flg) {lu->options.ColPerm = (colperm_t)indx;}
516     ierr = PetscOptionsEList("-mat_superlu_iterrefine","IterRefine","None",iterrefine,4,iterrefine[0],&indx,&flg);CHKERRQ(ierr);
517     if (flg) { lu->options.IterRefine = (IterRefine_t)indx;}
518     ierr = PetscOptionsBool("-mat_superlu_symmetricmode","SymmetricMode","None",(PetscBool)lu->options.SymmetricMode,&flg,0);CHKERRQ(ierr);
519     if (flg) lu->options.SymmetricMode = YES;
520     ierr = PetscOptionsReal("-mat_superlu_diagpivotthresh","DiagPivotThresh","None",lu->options.DiagPivotThresh,&lu->options.DiagPivotThresh,PETSC_NULL);CHKERRQ(ierr);
521     ierr = PetscOptionsBool("-mat_superlu_pivotgrowth","PivotGrowth","None",(PetscBool)lu->options.PivotGrowth,&flg,0);CHKERRQ(ierr);
522     if (flg) lu->options.PivotGrowth = YES;
523     ierr = PetscOptionsBool("-mat_superlu_conditionnumber","ConditionNumber","None",(PetscBool)lu->options.ConditionNumber,&flg,0);CHKERRQ(ierr);
524     if (flg) lu->options.ConditionNumber = YES;
525     ierr = PetscOptionsEList("-mat_superlu_rowperm","rowperm","None",rowperm,2,rowperm[0],&indx,&flg);CHKERRQ(ierr);
526     if (flg) {lu->options.RowPerm = (rowperm_t)indx;}
527     ierr = PetscOptionsBool("-mat_superlu_replacetinypivot","ReplaceTinyPivot","None",(PetscBool)lu->options.ReplaceTinyPivot,&flg,0);CHKERRQ(ierr);
528     if (flg) lu->options.ReplaceTinyPivot = YES;
529     ierr = PetscOptionsBool("-mat_superlu_printstat","PrintStat","None",(PetscBool)lu->options.PrintStat,&flg,0);CHKERRQ(ierr);
530     if (flg) lu->options.PrintStat = YES;
531     ierr = PetscOptionsInt("-mat_superlu_lwork","size of work array in bytes used by factorization","None",lu->lwork,&lu->lwork,PETSC_NULL);CHKERRQ(ierr);
532     if (lu->lwork > 0 ){
533       ierr = PetscMalloc(lu->lwork,&lu->work);CHKERRQ(ierr);
534     } else if (lu->lwork != 0 && lu->lwork != -1){
535       ierr = PetscPrintf(PETSC_COMM_SELF,"   Warning: lwork %D is not supported by SUPERLU. The default lwork=0 is used.\n",lu->lwork);
536       lu->lwork = 0;
537     }
538     /* ilu options */
539     ierr = PetscOptionsReal("-mat_superlu_ilu_droptol","ILU_DropTol","None",lu->options.ILU_DropTol,&lu->options.ILU_DropTol,PETSC_NULL);CHKERRQ(ierr);
540     ierr = PetscOptionsReal("-mat_superlu_ilu_filltol","ILU_FillTol","None",lu->options.ILU_FillTol,&lu->options.ILU_FillTol,PETSC_NULL);CHKERRQ(ierr);
541     ierr = PetscOptionsReal("-mat_superlu_ilu_fillfactor","ILU_FillFactor","None",lu->options.ILU_FillFactor,&lu->options.ILU_FillFactor,PETSC_NULL);CHKERRQ(ierr);
542     ierr = PetscOptionsInt("-mat_superlu_ilu_droprull","ILU_DropRule","None",lu->options.ILU_DropRule,&lu->options.ILU_DropRule,PETSC_NULL);CHKERRQ(ierr);
543     ierr = PetscOptionsInt("-mat_superlu_ilu_norm","ILU_Norm","None",lu->options.ILU_Norm,&indx,&flg);CHKERRQ(ierr);
544     if (flg){
545       lu->options.ILU_Norm = (norm_t)indx;
546     }
547     ierr = PetscOptionsInt("-mat_superlu_ilu_milu","ILU_MILU","None",lu->options.ILU_MILU,&indx,&flg);CHKERRQ(ierr);
548     if (flg){
549       lu->options.ILU_MILU = (milu_t)indx;
550     }
551   PetscOptionsEnd();
552   if (lu->options.Equil == YES) {
553     /* superlu overwrites input matrix and rhs when Equil is used, thus create A_dup to keep user's A unchanged */
554     ierr = MatDuplicate_SeqAIJ(A,MAT_COPY_VALUES,&lu->A_dup);CHKERRQ(ierr);
555   }
556 
557   /* Allocate spaces (notice sizes are for the transpose) */
558   ierr = PetscMalloc(m*sizeof(PetscInt),&lu->etree);CHKERRQ(ierr);
559   ierr = PetscMalloc(n*sizeof(PetscInt),&lu->perm_r);CHKERRQ(ierr);
560   ierr = PetscMalloc(m*sizeof(PetscInt),&lu->perm_c);CHKERRQ(ierr);
561   ierr = PetscMalloc(n*sizeof(PetscScalar),&lu->R);CHKERRQ(ierr);
562   ierr = PetscMalloc(m*sizeof(PetscScalar),&lu->C);CHKERRQ(ierr);
563 
564   /* create rhs and solution x without allocate space for .Store */
565 #if defined(PETSC_USE_COMPLEX)
566   zCreate_Dense_Matrix(&lu->B, m, 1, PETSC_NULL, m, SLU_DN, SLU_Z, SLU_GE);
567   zCreate_Dense_Matrix(&lu->X, m, 1, PETSC_NULL, m, SLU_DN, SLU_Z, SLU_GE);
568 #else
569   dCreate_Dense_Matrix(&lu->B, m, 1, PETSC_NULL, m, SLU_DN, SLU_D, SLU_GE);
570   dCreate_Dense_Matrix(&lu->X, m, 1, PETSC_NULL, m, SLU_DN, SLU_D, SLU_GE);
571 #endif
572 
573 #ifdef SUPERLU2
574   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatCreateNull","MatCreateNull_SuperLU",(void(*)(void))MatCreateNull_SuperLU);CHKERRQ(ierr);
575 #endif
576   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatFactorGetSolverPackage_C","MatFactorGetSolverPackage_seqaij_superlu",MatFactorGetSolverPackage_seqaij_superlu);CHKERRQ(ierr);
577   B->spptr = lu;
578   *F = B;
579   PetscFunctionReturn(0);
580 }
581 EXTERN_C_END
582