xref: /petsc/src/mat/impls/aij/seq/superlu/superlu.c (revision d61e7eb36d836a8e2bf1ad3f41344afcd0d5cf20)
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 {
187       ierr = PetscPrintf(PETSC_COMM_SELF,"  Warning: gssvx() returns info %D\n",sinfo);
188     }
189   } else { /* sinfo < 0 */
190     SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_LIB, "info = %D, the %D-th argument in gssvx() had an illegal value", sinfo,-sinfo);
191   }
192 
193   if ( lu->options.PrintStat ) {
194     ierr = PetscPrintf(PETSC_COMM_SELF,"MatLUFactorNumeric_SuperLU():\n");
195     StatPrint(&lu->stat);
196     Lstore = (SCformat *) lu->L.Store;
197     Ustore = (NCformat *) lu->U.Store;
198     ierr = PetscPrintf(PETSC_COMM_SELF,"  No of nonzeros in factor L = %D\n", Lstore->nnz);
199     ierr = PetscPrintf(PETSC_COMM_SELF,"  No of nonzeros in factor U = %D\n", Ustore->nnz);
200     ierr = PetscPrintf(PETSC_COMM_SELF,"  No of nonzeros in L+U = %D\n", Lstore->nnz + Ustore->nnz - lu->A.ncol);
201     ierr = PetscPrintf(PETSC_COMM_SELF,"  L\\U MB %.3f\ttotal MB needed %.3f\n",
202 	       lu->mem_usage.for_lu/1e6, lu->mem_usage.total_needed/1e6);
203   }
204 
205   lu->flg = SAME_NONZERO_PATTERN;
206   (F)->ops->solve          = MatSolve_SuperLU;
207   (F)->ops->solvetranspose = MatSolveTranspose_SuperLU;
208   PetscFunctionReturn(0);
209 }
210 
211 #undef __FUNCT__
212 #define __FUNCT__ "MatDestroy_SuperLU"
213 PetscErrorCode MatDestroy_SuperLU(Mat A)
214 {
215   PetscErrorCode ierr;
216   Mat_SuperLU    *lu=(Mat_SuperLU*)A->spptr;
217 
218   PetscFunctionBegin;
219   if (lu->CleanUpSuperLU) { /* Free the SuperLU datastructures */
220     Destroy_SuperMatrix_Store(&lu->A);
221     Destroy_SuperMatrix_Store(&lu->B);
222     Destroy_SuperMatrix_Store(&lu->X);
223     StatFree(&lu->stat);
224 
225     ierr = PetscFree(lu->etree);CHKERRQ(ierr);
226     ierr = PetscFree(lu->perm_r);CHKERRQ(ierr);
227     ierr = PetscFree(lu->perm_c);CHKERRQ(ierr);
228     ierr = PetscFree(lu->R);CHKERRQ(ierr);
229     ierr = PetscFree(lu->C);CHKERRQ(ierr);
230     if ( lu->lwork >= 0 ) {
231       Destroy_SuperNode_Matrix(&lu->L);
232       Destroy_CompCol_Matrix(&lu->U);
233     }
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 = MatView_SeqAIJ(A,viewer);CHKERRQ(ierr);
251 
252   ierr = PetscTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
253   if (iascii) {
254     ierr = PetscViewerGetFormat(viewer,&format);CHKERRQ(ierr);
255     if (format == PETSC_VIEWER_ASCII_INFO) {
256       ierr = MatFactorInfo_SuperLU(A,viewer);CHKERRQ(ierr);
257     }
258   }
259   PetscFunctionReturn(0);
260 }
261 
262 
263 #undef __FUNCT__
264 #define __FUNCT__ "MatSolve_SuperLU_Private"
265 PetscErrorCode MatSolve_SuperLU_Private(Mat A,Vec b,Vec x)
266 {
267   Mat_SuperLU    *lu = (Mat_SuperLU*)A->spptr;
268   PetscScalar    *barray,*xarray;
269   PetscErrorCode ierr;
270   PetscInt       info,i,n=x->map->n;
271   PetscReal      ferr,berr;
272 
273   PetscFunctionBegin;
274   if ( lu->lwork == -1 ) {
275     PetscFunctionReturn(0);
276   }
277 
278   lu->B.ncol = 1;   /* Set the number of right-hand side */
279   if (lu->options.Equil && !lu->rhs_dup){
280     /* superlu overwrites b when Equil is used, thus create rhs_dup to keep user's b unchanged */
281     ierr = PetscMalloc(n*sizeof(PetscScalar),&lu->rhs_dup);CHKERRQ(ierr);
282   }
283   if (lu->options.Equil){
284     /* Copy b into rsh_dup */
285     ierr = VecGetArray(b,&barray);CHKERRQ(ierr);
286     ierr = PetscMemcpy(lu->rhs_dup,barray,n*sizeof(PetscScalar));CHKERRQ(ierr);
287     ierr = VecRestoreArray(b,&barray);CHKERRQ(ierr);
288     barray = lu->rhs_dup;
289   } else {
290     ierr = VecGetArray(b,&barray);CHKERRQ(ierr);
291   }
292   ierr = VecGetArray(x,&xarray);CHKERRQ(ierr);
293 
294 #if defined(PETSC_USE_COMPLEX)
295   ((DNformat*)lu->B.Store)->nzval = (doublecomplex*)barray;
296   ((DNformat*)lu->X.Store)->nzval = (doublecomplex*)xarray;
297 #else
298   ((DNformat*)lu->B.Store)->nzval = barray;
299   ((DNformat*)lu->X.Store)->nzval = xarray;
300 #endif
301 
302   lu->options.Fact = FACTORED; /* Indicate the factored form of A is supplied. */
303   if (A->factortype == MAT_FACTOR_LU){
304 #if defined(PETSC_USE_COMPLEX)
305     zgssvx(&lu->options, &lu->A, lu->perm_c, lu->perm_r, lu->etree, lu->equed, lu->R, lu->C,
306            &lu->L, &lu->U, lu->work, lu->lwork, &lu->B, &lu->X, &lu->rpg, &lu->rcond, &ferr, &berr,
307            &lu->mem_usage, &lu->stat, &info);
308 #else
309     dgssvx(&lu->options, &lu->A, lu->perm_c, lu->perm_r, lu->etree, lu->equed, lu->R, lu->C,
310            &lu->L, &lu->U, lu->work, lu->lwork, &lu->B, &lu->X, &lu->rpg, &lu->rcond, &ferr, &berr,
311            &lu->mem_usage, &lu->stat, &info);
312 #endif
313   } else if (A->factortype == MAT_FACTOR_ILU){
314 #if defined(PETSC_USE_COMPLEX)
315     zgsisx(&lu->options, &lu->A, lu->perm_c, lu->perm_r, lu->etree, lu->equed, lu->R, lu->C,
316            &lu->L, &lu->U, lu->work, lu->lwork, &lu->B, &lu->X, &lu->rpg, &lu->rcond,
317            &lu->mem_usage, &lu->stat, &info);
318 #else
319     dgsisx(&lu->options, &lu->A, lu->perm_c, lu->perm_r, lu->etree, lu->equed, lu->R, lu->C,
320            &lu->L, &lu->U, lu->work, lu->lwork, &lu->B, &lu->X, &lu->rpg, &lu->rcond,
321            &lu->mem_usage, &lu->stat, &info);
322 #endif
323   } else {
324     SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Factor type not supported");
325   }
326   if (!lu->options.Equil){
327     ierr = VecRestoreArray(b,&barray);CHKERRQ(ierr);
328   }
329   ierr = VecRestoreArray(x,&xarray);CHKERRQ(ierr);
330 
331   if ( !info || info == lu->A.ncol+1 ) {
332     if ( lu->options.IterRefine ) {
333       ierr = PetscPrintf(PETSC_COMM_SELF,"Iterative Refinement:\n");
334       ierr = PetscPrintf(PETSC_COMM_SELF,"  %8s%8s%16s%16s\n", "rhs", "Steps", "FERR", "BERR");
335       for (i = 0; i < 1; ++i)
336         ierr = PetscPrintf(PETSC_COMM_SELF,"  %8d%8d%16e%16e\n", i+1, lu->stat.RefineSteps, ferr, berr);
337     }
338   } else if ( info > 0 ){
339     if ( lu->lwork == -1 ) {
340       ierr = PetscPrintf(PETSC_COMM_SELF,"  ** Estimated memory: %D bytes\n", info - lu->A.ncol);
341     } else {
342       ierr = PetscPrintf(PETSC_COMM_SELF,"  Warning: gssvx() returns info %D\n",info);
343     }
344   } else if (info < 0){
345     SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_LIB, "info = %D, the %D-th argument in gssvx() had an illegal value", info,-info);
346   }
347 
348   if ( lu->options.PrintStat ) {
349     ierr = PetscPrintf(PETSC_COMM_SELF,"MatSolve__SuperLU():\n");
350     StatPrint(&lu->stat);
351   }
352   PetscFunctionReturn(0);
353 }
354 
355 #undef __FUNCT__
356 #define __FUNCT__ "MatSolve_SuperLU"
357 PetscErrorCode MatSolve_SuperLU(Mat A,Vec b,Vec x)
358 {
359   Mat_SuperLU    *lu = (Mat_SuperLU*)A->spptr;
360   PetscErrorCode ierr;
361 
362   PetscFunctionBegin;
363   lu->options.Trans = TRANS;
364   ierr = MatSolve_SuperLU_Private(A,b,x);CHKERRQ(ierr);
365   PetscFunctionReturn(0);
366 }
367 
368 #undef __FUNCT__
369 #define __FUNCT__ "MatSolveTranspose_SuperLU"
370 PetscErrorCode MatSolveTranspose_SuperLU(Mat A,Vec b,Vec x)
371 {
372   Mat_SuperLU    *lu = (Mat_SuperLU*)A->spptr;
373   PetscErrorCode ierr;
374 
375   PetscFunctionBegin;
376   lu->options.Trans = NOTRANS;
377   ierr = MatSolve_SuperLU_Private(A,b,x);CHKERRQ(ierr);
378   PetscFunctionReturn(0);
379 }
380 
381 /*
382    Note the r permutation is ignored
383 */
384 #undef __FUNCT__
385 #define __FUNCT__ "MatLUFactorSymbolic_SuperLU"
386 PetscErrorCode MatLUFactorSymbolic_SuperLU(Mat F,Mat A,IS r,IS c,const MatFactorInfo *info)
387 {
388   Mat_SuperLU    *lu = (Mat_SuperLU*)((F)->spptr);
389 
390   PetscFunctionBegin;
391   lu->flg                   = DIFFERENT_NONZERO_PATTERN;
392   lu->CleanUpSuperLU        = PETSC_TRUE;
393   (F)->ops->lufactornumeric = MatLUFactorNumeric_SuperLU;
394   PetscFunctionReturn(0);
395 }
396 
397 EXTERN_C_BEGIN
398 #undef __FUNCT__
399 #define __FUNCT__ "MatFactorGetSolverPackage_seqaij_superlu"
400 PetscErrorCode MatFactorGetSolverPackage_seqaij_superlu(Mat A,const MatSolverPackage *type)
401 {
402   PetscFunctionBegin;
403   *type = MATSOLVERSUPERLU;
404   PetscFunctionReturn(0);
405 }
406 EXTERN_C_END
407 
408 
409 /*MC
410   MATSOLVERSUPERLU = "superlu" - A solver package providing solvers LU and ILU for sequential matrices
411   via the external package SuperLU.
412 
413   Use ./configure --download-superlu to have PETSc installed with SuperLU
414 
415   Options Database Keys:
416 +  -mat_superlu_equil: <FALSE> Equil (None)
417 .  -mat_superlu_colperm <COLAMD> (choose one of) NATURAL MMD_ATA MMD_AT_PLUS_A COLAMD
418 .  -mat_superlu_iterrefine <NOREFINE> (choose one of) NOREFINE SINGLE DOUBLE EXTRA
419 .  -mat_superlu_symmetricmode: <FALSE> SymmetricMode (None)
420 .  -mat_superlu_diagpivotthresh <1>: DiagPivotThresh (None)
421 .  -mat_superlu_pivotgrowth: <FALSE> PivotGrowth (None)
422 .  -mat_superlu_conditionnumber: <FALSE> ConditionNumber (None)
423 .  -mat_superlu_rowperm <NOROWPERM> (choose one of) NOROWPERM LargeDiag
424 .  -mat_superlu_replacetinypivot: <FALSE> ReplaceTinyPivot (None)
425 .  -mat_superlu_printstat: <FALSE> PrintStat (None)
426 .  -mat_superlu_lwork <0>: size of work array in bytes used by factorization (None)
427 .  -mat_superlu_ilu_droptol <0>: ILU_DropTol (None)
428 .  -mat_superlu_ilu_filltol <0>: ILU_FillTol (None)
429 .  -mat_superlu_ilu_fillfactor <0>: ILU_FillFactor (None)
430 .  -mat_superlu_ilu_droprull <0>: ILU_DropRule (None)
431 .  -mat_superlu_ilu_norm <0>: ILU_Norm (None)
432 -  -mat_superlu_ilu_milu <0>: ILU_MILU (None)
433 
434    Notes: Do not confuse this with MATSOLVERSUPERLU_DIST which is for parallel sparse solves
435 
436    Level: beginner
437 
438 .seealso: PCLU, PCILU, MATSOLVERSUPERLU_DIST, MATSOLVERMUMPS, MATSOLVERSPOOLES, PCFactorSetMatSolverPackage(), MatSolverPackage
439 M*/
440 
441 EXTERN_C_BEGIN
442 #undef __FUNCT__
443 #define __FUNCT__ "MatGetFactor_seqaij_superlu"
444 PetscErrorCode MatGetFactor_seqaij_superlu(Mat A,MatFactorType ftype,Mat *F)
445 {
446   Mat            B;
447   Mat_SuperLU    *lu;
448   PetscErrorCode ierr;
449   PetscInt       indx,m=A->rmap->n,n=A->cmap->n;
450   PetscBool      flg;
451   const char     *colperm[]={"NATURAL","MMD_ATA","MMD_AT_PLUS_A","COLAMD"}; /* MY_PERMC - not supported by the petsc interface yet */
452   const char     *iterrefine[]={"NOREFINE", "SINGLE", "DOUBLE", "EXTRA"};
453   const char     *rowperm[]={"NOROWPERM", "LargeDiag"}; /* MY_PERMC - not supported by the petsc interface yet */
454 
455   PetscFunctionBegin;
456   ierr = MatCreate(((PetscObject)A)->comm,&B);CHKERRQ(ierr);
457   ierr = MatSetSizes(B,A->rmap->n,A->cmap->n,PETSC_DETERMINE,PETSC_DETERMINE);CHKERRQ(ierr);
458   ierr = MatSetType(B,((PetscObject)A)->type_name);CHKERRQ(ierr);
459   ierr = MatSeqAIJSetPreallocation(B,0,PETSC_NULL);CHKERRQ(ierr);
460 
461   if (ftype == MAT_FACTOR_LU || ftype == MAT_FACTOR_ILU){
462     B->ops->lufactorsymbolic  = MatLUFactorSymbolic_SuperLU;
463     B->ops->ilufactorsymbolic = MatLUFactorSymbolic_SuperLU;
464   } else {
465     SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Factor type not supported");
466   }
467 
468   B->ops->destroy          = MatDestroy_SuperLU;
469   B->ops->view             = MatView_SuperLU;
470   B->factortype            = ftype;
471   B->assembled             = PETSC_TRUE;  /* required by -ksp_view */
472   B->preallocated          = PETSC_TRUE;
473 
474   ierr = PetscNewLog(B,Mat_SuperLU,&lu);CHKERRQ(ierr);
475 
476   if (ftype == MAT_FACTOR_LU){
477     set_default_options(&lu->options);
478     /* Comments from SuperLU_4.0/SRC/dgssvx.c:
479       "Whether or not the system will be equilibrated depends on the
480        scaling of the matrix A, but if equilibration is used, A is
481        overwritten by diag(R)*A*diag(C) and B by diag(R)*B
482        (if options->Trans=NOTRANS) or diag(C)*B (if options->Trans = TRANS or CONJ)."
483      We set 'options.Equil = NO' as default because additional space is needed for it.
484     */
485     lu->options.Equil     = NO;
486   } else if (ftype == MAT_FACTOR_ILU){
487     /* Set the default input options of ilu:
488 	options.Fact = DOFACT;
489 	options.Equil = YES;           // must be YES for ilu - don't know why
490 	options.ColPerm = COLAMD;
491 	options.DiagPivotThresh = 0.1; //different from complete LU
492 	options.Trans = NOTRANS;
493 	options.IterRefine = NOREFINE;
494 	options.SymmetricMode = NO;
495 	options.PivotGrowth = NO;
496 	options.ConditionNumber = NO;
497 	options.PrintStat = YES;
498 	options.RowPerm = LargeDiag;
499 	options.ILU_DropTol = 1e-4;
500 	options.ILU_FillTol = 1e-2;
501 	options.ILU_FillFactor = 10.0;
502 	options.ILU_DropRule = DROP_BASIC | DROP_AREA;
503 	options.ILU_Norm = INF_NORM;
504 	options.ILU_MILU = SMILU_2;
505     */
506     ilu_set_default_options(&lu->options);
507   }
508   lu->options.PrintStat = NO;
509 
510   /* Initialize the statistics variables. */
511   StatInit(&lu->stat);
512   lu->lwork = 0;   /* allocate space internally by system malloc */
513 
514   ierr = PetscOptionsBegin(((PetscObject)A)->comm,((PetscObject)A)->prefix,"SuperLU Options","Mat");CHKERRQ(ierr);
515     ierr = PetscOptionsBool("-mat_superlu_equil","Equil","None",(PetscBool)lu->options.Equil,(PetscBool *)&lu->options.Equil,0);CHKERRQ(ierr);
516     ierr = PetscOptionsEList("-mat_superlu_colperm","ColPerm","None",colperm,4,colperm[3],&indx,&flg);CHKERRQ(ierr);
517     if (flg) {lu->options.ColPerm = (colperm_t)indx;}
518     ierr = PetscOptionsEList("-mat_superlu_iterrefine","IterRefine","None",iterrefine,4,iterrefine[0],&indx,&flg);CHKERRQ(ierr);
519     if (flg) { lu->options.IterRefine = (IterRefine_t)indx;}
520     ierr = PetscOptionsBool("-mat_superlu_symmetricmode","SymmetricMode","None",(PetscBool)lu->options.SymmetricMode,&flg,0);CHKERRQ(ierr);
521     if (flg) lu->options.SymmetricMode = YES;
522     ierr = PetscOptionsReal("-mat_superlu_diagpivotthresh","DiagPivotThresh","None",lu->options.DiagPivotThresh,&lu->options.DiagPivotThresh,PETSC_NULL);CHKERRQ(ierr);
523     ierr = PetscOptionsBool("-mat_superlu_pivotgrowth","PivotGrowth","None",(PetscBool)lu->options.PivotGrowth,&flg,0);CHKERRQ(ierr);
524     if (flg) lu->options.PivotGrowth = YES;
525     ierr = PetscOptionsBool("-mat_superlu_conditionnumber","ConditionNumber","None",(PetscBool)lu->options.ConditionNumber,&flg,0);CHKERRQ(ierr);
526     if (flg) lu->options.ConditionNumber = YES;
527     ierr = PetscOptionsEList("-mat_superlu_rowperm","rowperm","None",rowperm,2,rowperm[0],&indx,&flg);CHKERRQ(ierr);
528     if (flg) {lu->options.RowPerm = (rowperm_t)indx;}
529     ierr = PetscOptionsBool("-mat_superlu_replacetinypivot","ReplaceTinyPivot","None",(PetscBool)lu->options.ReplaceTinyPivot,&flg,0);CHKERRQ(ierr);
530     if (flg) lu->options.ReplaceTinyPivot = YES;
531     ierr = PetscOptionsBool("-mat_superlu_printstat","PrintStat","None",(PetscBool)lu->options.PrintStat,&flg,0);CHKERRQ(ierr);
532     if (flg) lu->options.PrintStat = YES;
533     ierr = PetscOptionsInt("-mat_superlu_lwork","size of work array in bytes used by factorization","None",lu->lwork,&lu->lwork,PETSC_NULL);CHKERRQ(ierr);
534     if (lu->lwork > 0 ){
535       ierr = PetscMalloc(lu->lwork,&lu->work);CHKERRQ(ierr);
536     } else if (lu->lwork != 0 && lu->lwork != -1){
537       ierr = PetscPrintf(PETSC_COMM_SELF,"   Warning: lwork %D is not supported by SUPERLU. The default lwork=0 is used.\n",lu->lwork);
538       lu->lwork = 0;
539     }
540     /* ilu options */
541     ierr = PetscOptionsReal("-mat_superlu_ilu_droptol","ILU_DropTol","None",lu->options.ILU_DropTol,&lu->options.ILU_DropTol,PETSC_NULL);CHKERRQ(ierr);
542     ierr = PetscOptionsReal("-mat_superlu_ilu_filltol","ILU_FillTol","None",lu->options.ILU_FillTol,&lu->options.ILU_FillTol,PETSC_NULL);CHKERRQ(ierr);
543     ierr = PetscOptionsReal("-mat_superlu_ilu_fillfactor","ILU_FillFactor","None",lu->options.ILU_FillFactor,&lu->options.ILU_FillFactor,PETSC_NULL);CHKERRQ(ierr);
544     ierr = PetscOptionsInt("-mat_superlu_ilu_droprull","ILU_DropRule","None",lu->options.ILU_DropRule,&lu->options.ILU_DropRule,PETSC_NULL);CHKERRQ(ierr);
545     ierr = PetscOptionsInt("-mat_superlu_ilu_norm","ILU_Norm","None",lu->options.ILU_Norm,&indx,&flg);CHKERRQ(ierr);
546     if (flg){
547       lu->options.ILU_Norm = (norm_t)indx;
548     }
549     ierr = PetscOptionsInt("-mat_superlu_ilu_milu","ILU_MILU","None",lu->options.ILU_MILU,&indx,&flg);CHKERRQ(ierr);
550     if (flg){
551       lu->options.ILU_MILU = (milu_t)indx;
552     }
553   PetscOptionsEnd();
554   if (lu->options.Equil == YES) {
555     /* superlu overwrites input matrix and rhs when Equil is used, thus create A_dup to keep user's A unchanged */
556     ierr = MatDuplicate_SeqAIJ(A,MAT_COPY_VALUES,&lu->A_dup);CHKERRQ(ierr);
557   }
558 
559   /* Allocate spaces (notice sizes are for the transpose) */
560   ierr = PetscMalloc(m*sizeof(PetscInt),&lu->etree);CHKERRQ(ierr);
561   ierr = PetscMalloc(n*sizeof(PetscInt),&lu->perm_r);CHKERRQ(ierr);
562   ierr = PetscMalloc(m*sizeof(PetscInt),&lu->perm_c);CHKERRQ(ierr);
563   ierr = PetscMalloc(n*sizeof(PetscScalar),&lu->R);CHKERRQ(ierr);
564   ierr = PetscMalloc(m*sizeof(PetscScalar),&lu->C);CHKERRQ(ierr);
565 
566   /* create rhs and solution x without allocate space for .Store */
567 #if defined(PETSC_USE_COMPLEX)
568   zCreate_Dense_Matrix(&lu->B, m, 1, PETSC_NULL, m, SLU_DN, SLU_Z, SLU_GE);
569   zCreate_Dense_Matrix(&lu->X, m, 1, PETSC_NULL, m, SLU_DN, SLU_Z, SLU_GE);
570 #else
571   dCreate_Dense_Matrix(&lu->B, m, 1, PETSC_NULL, m, SLU_DN, SLU_D, SLU_GE);
572   dCreate_Dense_Matrix(&lu->X, m, 1, PETSC_NULL, m, SLU_DN, SLU_D, SLU_GE);
573 #endif
574 
575 #ifdef SUPERLU2
576   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatCreateNull","MatCreateNull_SuperLU",(void(*)(void))MatCreateNull_SuperLU);CHKERRQ(ierr);
577 #endif
578   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatFactorGetSolverPackage_C","MatFactorGetSolverPackage_seqaij_superlu",MatFactorGetSolverPackage_seqaij_superlu);CHKERRQ(ierr);
579   B->spptr = lu;
580   *F = B;
581   PetscFunctionReturn(0);
582 }
583 EXTERN_C_END
584