xref: /petsc/src/mat/impls/aij/seq/superlu/superlu.c (revision d372ba47371068bdce79d7d3cf159aa0df7e4cba)
1 
2 /*  --------------------------------------------------------------------
3 
4      This file implements a subclass of the SeqAIJ matrix class that uses
5      the SuperLU sparse solver. You can use this as a starting point for
6      implementing your own subclass of a PETSc matrix class.
7 
8      This demonstrates a way to make an implementation inheritence of a PETSc
9      matrix type. This means constructing a new matrix type (SuperLU) by changing some
10      of the methods of the previous type (SeqAIJ), adding additional data, and possibly
11      additional method. (See any book on object oriented programming).
12 */
13 
14 /*
15      Defines the data structure for the base matrix type (SeqAIJ)
16 */
17 #include <../src/mat/impls/aij/seq/aij.h>    /*I "petscmat.h" I*/
18 
19 /*
20      SuperLU include files
21 */
22 EXTERN_C_BEGIN
23 #if defined(PETSC_USE_COMPLEX)
24 #include <slu_zdefs.h>
25 #else
26 #include <slu_ddefs.h>
27 #endif
28 #include <slu_util.h>
29 EXTERN_C_END
30 
31 /*
32      This is the data we are "ADDING" to the SeqAIJ matrix type to get the SuperLU matrix type
33 */
34 typedef struct {
35   SuperMatrix       A,L,U,B,X;
36   superlu_options_t options;
37   PetscInt          *perm_c; /* column permutation vector */
38   PetscInt          *perm_r; /* row permutations from partial pivoting */
39   PetscInt          *etree;
40   PetscReal         *R, *C;
41   char              equed[1];
42   PetscInt          lwork;
43   void              *work;
44   PetscReal         rpg, rcond;
45   mem_usage_t       mem_usage;
46   MatStructure      flg;
47   SuperLUStat_t     stat;
48   Mat               A_dup;
49   PetscScalar       *rhs_dup;
50 
51   /* Flag to clean up (non-global) SuperLU objects during Destroy */
52   PetscBool  CleanUpSuperLU;
53 } Mat_SuperLU;
54 
55 extern PetscErrorCode MatFactorInfo_SuperLU(Mat,PetscViewer);
56 extern PetscErrorCode MatLUFactorNumeric_SuperLU(Mat,Mat,const MatFactorInfo *);
57 extern PetscErrorCode MatDestroy_SuperLU(Mat);
58 extern PetscErrorCode MatView_SuperLU(Mat,PetscViewer);
59 extern PetscErrorCode MatAssemblyEnd_SuperLU(Mat,MatAssemblyType);
60 extern PetscErrorCode MatSolve_SuperLU(Mat,Vec,Vec);
61 extern PetscErrorCode MatMatSolve_SuperLU(Mat,Mat,Mat);
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   F->ops->matsolve       = MatMatSolve_SuperLU;
207   PetscFunctionReturn(0);
208 }
209 
210 #undef __FUNCT__
211 #define __FUNCT__ "MatDestroy_SuperLU"
212 PetscErrorCode MatDestroy_SuperLU(Mat A)
213 {
214   PetscErrorCode ierr;
215   Mat_SuperLU    *lu=(Mat_SuperLU*)A->spptr;
216 
217   PetscFunctionBegin;
218   if (lu->CleanUpSuperLU) { /* Free the SuperLU datastructures */
219     Destroy_SuperMatrix_Store(&lu->A);
220     Destroy_SuperMatrix_Store(&lu->B);
221     Destroy_SuperMatrix_Store(&lu->X);
222     StatFree(&lu->stat);
223     if ( lu->lwork >= 0 ) {
224       Destroy_SuperNode_Matrix(&lu->L);
225       Destroy_CompCol_Matrix(&lu->U);
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   /* clear composed functions */
236   ierr = PetscObjectComposeFunctionDynamic((PetscObject)A,"MatFactorGetSolverPackage_C","",PETSC_NULL);CHKERRQ(ierr);
237   ierr = PetscObjectComposeFunctionDynamic((PetscObject)A,"MatSuperluSetILUDropTol_C","",PETSC_NULL);CHKERRQ(ierr);
238 
239   ierr = MatDestroy_SeqAIJ(A);CHKERRQ(ierr);
240   ierr = MatDestroy(&lu->A_dup);CHKERRQ(ierr);
241   ierr = PetscFree(lu->rhs_dup);CHKERRQ(ierr);
242   PetscFunctionReturn(0);
243 }
244 
245 #undef __FUNCT__
246 #define __FUNCT__ "MatView_SuperLU"
247 PetscErrorCode MatView_SuperLU(Mat A,PetscViewer viewer)
248 {
249   PetscErrorCode    ierr;
250   PetscBool         iascii;
251   PetscViewerFormat format;
252 
253   PetscFunctionBegin;
254   ierr = PetscTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
255   if (iascii) {
256     ierr = PetscViewerGetFormat(viewer,&format);CHKERRQ(ierr);
257     if (format == PETSC_VIEWER_ASCII_INFO) {
258       ierr = MatFactorInfo_SuperLU(A,viewer);CHKERRQ(ierr);
259     }
260   }
261   PetscFunctionReturn(0);
262 }
263 
264 
265 #undef __FUNCT__
266 #define __FUNCT__ "MatSolve_SuperLU_Private"
267 PetscErrorCode MatSolve_SuperLU_Private(Mat A,Vec b,Vec x)
268 {
269   Mat_SuperLU    *lu = (Mat_SuperLU*)A->spptr;
270   PetscScalar    *barray,*xarray;
271   PetscErrorCode ierr;
272   PetscInt       info,i,n=x->map->n;
273   PetscReal      ferr,berr;
274 
275   PetscFunctionBegin;
276   if ( lu->lwork == -1 ) {
277     PetscFunctionReturn(0);
278   }
279 
280   lu->B.ncol = 1;   /* Set the number of right-hand side */
281   if (lu->options.Equil && !lu->rhs_dup){
282     /* superlu overwrites b when Equil is used, thus create rhs_dup to keep user's b unchanged */
283     ierr = PetscMalloc(n*sizeof(PetscScalar),&lu->rhs_dup);CHKERRQ(ierr);
284   }
285   if (lu->options.Equil){
286     /* Copy b into rsh_dup */
287     ierr = VecGetArray(b,&barray);CHKERRQ(ierr);
288     ierr = PetscMemcpy(lu->rhs_dup,barray,n*sizeof(PetscScalar));CHKERRQ(ierr);
289     ierr = VecRestoreArray(b,&barray);CHKERRQ(ierr);
290     barray = lu->rhs_dup;
291   } else {
292     ierr = VecGetArray(b,&barray);CHKERRQ(ierr);
293   }
294   ierr = VecGetArray(x,&xarray);CHKERRQ(ierr);
295 
296 #if defined(PETSC_USE_COMPLEX)
297   ((DNformat*)lu->B.Store)->nzval = (doublecomplex*)barray;
298   ((DNformat*)lu->X.Store)->nzval = (doublecomplex*)xarray;
299 #else
300   ((DNformat*)lu->B.Store)->nzval = barray;
301   ((DNformat*)lu->X.Store)->nzval = xarray;
302 #endif
303 
304   lu->options.Fact = FACTORED; /* Indicate the factored form of A is supplied. */
305   if (A->factortype == MAT_FACTOR_LU){
306 #if defined(PETSC_USE_COMPLEX)
307     zgssvx(&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 #else
311     dgssvx(&lu->options, &lu->A, lu->perm_c, lu->perm_r, lu->etree, lu->equed, lu->R, lu->C,
312            &lu->L, &lu->U, lu->work, lu->lwork, &lu->B, &lu->X, &lu->rpg, &lu->rcond, &ferr, &berr,
313            &lu->mem_usage, &lu->stat, &info);
314 #endif
315   } else if (A->factortype == MAT_FACTOR_ILU){
316 #if defined(PETSC_USE_COMPLEX)
317     zgsisx(&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 #else
321     dgsisx(&lu->options, &lu->A, lu->perm_c, lu->perm_r, lu->etree, lu->equed, lu->R, lu->C,
322            &lu->L, &lu->U, lu->work, lu->lwork, &lu->B, &lu->X, &lu->rpg, &lu->rcond,
323            &lu->mem_usage, &lu->stat, &info);
324 #endif
325   } else {
326     SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Factor type not supported");
327   }
328   if (!lu->options.Equil){
329     ierr = VecRestoreArray(b,&barray);CHKERRQ(ierr);
330   }
331   ierr = VecRestoreArray(x,&xarray);CHKERRQ(ierr);
332 
333   if ( !info || info == lu->A.ncol+1 ) {
334     if ( lu->options.IterRefine ) {
335       ierr = PetscPrintf(PETSC_COMM_SELF,"Iterative Refinement:\n");
336       ierr = PetscPrintf(PETSC_COMM_SELF,"  %8s%8s%16s%16s\n", "rhs", "Steps", "FERR", "BERR");
337       for (i = 0; i < 1; ++i)
338         ierr = PetscPrintf(PETSC_COMM_SELF,"  %8d%8d%16e%16e\n", i+1, lu->stat.RefineSteps, ferr, berr);
339     }
340   } else if ( info > 0 ){
341     if ( lu->lwork == -1 ) {
342       ierr = PetscPrintf(PETSC_COMM_SELF,"  ** Estimated memory: %D bytes\n", info - lu->A.ncol);
343     } else {
344       ierr = PetscPrintf(PETSC_COMM_SELF,"  Warning: gssvx() returns info %D\n",info);
345     }
346   } else if (info < 0){
347     SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_LIB, "info = %D, the %D-th argument in gssvx() had an illegal value", info,-info);
348   }
349 
350   if ( lu->options.PrintStat ) {
351     ierr = PetscPrintf(PETSC_COMM_SELF,"MatSolve__SuperLU():\n");
352     StatPrint(&lu->stat);
353   }
354   PetscFunctionReturn(0);
355 }
356 
357 #undef __FUNCT__
358 #define __FUNCT__ "MatSolve_SuperLU"
359 PetscErrorCode MatSolve_SuperLU(Mat A,Vec b,Vec x)
360 {
361   Mat_SuperLU    *lu = (Mat_SuperLU*)A->spptr;
362   PetscErrorCode ierr;
363 
364   PetscFunctionBegin;
365   lu->options.Trans = TRANS;
366   ierr = MatSolve_SuperLU_Private(A,b,x);CHKERRQ(ierr);
367   PetscFunctionReturn(0);
368 }
369 
370 #undef __FUNCT__
371 #define __FUNCT__ "MatSolveTranspose_SuperLU"
372 PetscErrorCode MatSolveTranspose_SuperLU(Mat A,Vec b,Vec x)
373 {
374   Mat_SuperLU    *lu = (Mat_SuperLU*)A->spptr;
375   PetscErrorCode ierr;
376 
377   PetscFunctionBegin;
378   lu->options.Trans = NOTRANS;
379   ierr = MatSolve_SuperLU_Private(A,b,x);CHKERRQ(ierr);
380   PetscFunctionReturn(0);
381 }
382 
383 #undef __FUNCT__
384 #define __FUNCT__ "MatMatSolve_SuperLU"
385 PetscErrorCode MatMatSolve_SuperLU(Mat A,Mat B,Mat X)
386 {
387   Mat_SuperLU    *lu = (Mat_SuperLU*)A->spptr;
388 
389   PetscFunctionBegin;
390   lu->options.Trans = TRANS;
391   SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"MatMatSolve_SuperLU() is not implemented yet");
392   PetscFunctionReturn(0);
393 }
394 
395 /*
396    Note the r permutation is ignored
397 */
398 #undef __FUNCT__
399 #define __FUNCT__ "MatLUFactorSymbolic_SuperLU"
400 PetscErrorCode MatLUFactorSymbolic_SuperLU(Mat F,Mat A,IS r,IS c,const MatFactorInfo *info)
401 {
402   Mat_SuperLU    *lu = (Mat_SuperLU*)(F->spptr);
403 
404   PetscFunctionBegin;
405   lu->flg                 = DIFFERENT_NONZERO_PATTERN;
406   lu->CleanUpSuperLU      = PETSC_TRUE;
407   F->ops->lufactornumeric = MatLUFactorNumeric_SuperLU;
408   PetscFunctionReturn(0);
409 }
410 
411 EXTERN_C_BEGIN
412 #undef __FUNCT__
413 #define __FUNCT__ "MatSuperluSetILUDropTol_SuperLU"
414 PetscErrorCode MatSuperluSetILUDropTol_SuperLU(Mat F,PetscReal dtol)
415 {
416   Mat_SuperLU *lu= (Mat_SuperLU*)F->spptr;
417 
418   PetscFunctionBegin;
419   lu->options.ILU_DropTol = dtol;
420   PetscFunctionReturn(0);
421 }
422 EXTERN_C_END
423 
424 #undef __FUNCT__
425 #define __FUNCT__ "MatSuperluSetILUDropTol"
426 /*@
427   MatSuperluSetILUDropTol - Set SuperLU ILU drop tolerance
428    Logically Collective on Mat
429 
430    Input Parameters:
431 +  F - the factored matrix obtained by calling MatGetFactor() from PETSc-SuperLU interface
432 -  dtol - drop tolerance
433 
434   Options Database:
435 .   -mat_superlu_ilu_droptol <dtol>
436 
437    Level: beginner
438 
439    References: SuperLU Users' Guide
440 
441 .seealso: MatGetFactor()
442 @*/
443 PetscErrorCode MatSuperluSetILUDropTol(Mat F,PetscReal dtol)
444 {
445   PetscErrorCode ierr;
446 
447   PetscFunctionBegin;
448   PetscValidHeaderSpecific(F,MAT_CLASSID,1);
449   PetscValidLogicalCollectiveInt(F,dtol,2);
450   ierr = PetscTryMethod(F,"MatSuperluSetILUDropTol_C",(Mat,PetscReal),(F,dtol));CHKERRQ(ierr);
451   PetscFunctionReturn(0);
452 }
453 
454 EXTERN_C_BEGIN
455 #undef __FUNCT__
456 #define __FUNCT__ "MatFactorGetSolverPackage_seqaij_superlu"
457 PetscErrorCode MatFactorGetSolverPackage_seqaij_superlu(Mat A,const MatSolverPackage *type)
458 {
459   PetscFunctionBegin;
460   *type = MATSOLVERSUPERLU;
461   PetscFunctionReturn(0);
462 }
463 EXTERN_C_END
464 
465 
466 /*MC
467   MATSOLVERSUPERLU = "superlu" - A solver package providing solvers LU and ILU for sequential matrices
468   via the external package SuperLU.
469 
470   Use ./configure --download-superlu to have PETSc installed with SuperLU
471 
472   Options Database Keys:
473 +  -mat_superlu_equil: <FALSE> Equil (None)
474 .  -mat_superlu_colperm <COLAMD> (choose one of) NATURAL MMD_ATA MMD_AT_PLUS_A COLAMD
475 .  -mat_superlu_iterrefine <NOREFINE> (choose one of) NOREFINE SINGLE DOUBLE EXTRA
476 .  -mat_superlu_symmetricmode: <FALSE> SymmetricMode (None)
477 .  -mat_superlu_diagpivotthresh <1>: DiagPivotThresh (None)
478 .  -mat_superlu_pivotgrowth: <FALSE> PivotGrowth (None)
479 .  -mat_superlu_conditionnumber: <FALSE> ConditionNumber (None)
480 .  -mat_superlu_rowperm <NOROWPERM> (choose one of) NOROWPERM LargeDiag
481 .  -mat_superlu_replacetinypivot: <FALSE> ReplaceTinyPivot (None)
482 .  -mat_superlu_printstat: <FALSE> PrintStat (None)
483 .  -mat_superlu_lwork <0>: size of work array in bytes used by factorization (None)
484 .  -mat_superlu_ilu_droptol <0>: ILU_DropTol (None)
485 .  -mat_superlu_ilu_filltol <0>: ILU_FillTol (None)
486 .  -mat_superlu_ilu_fillfactor <0>: ILU_FillFactor (None)
487 .  -mat_superlu_ilu_droprull <0>: ILU_DropRule (None)
488 .  -mat_superlu_ilu_norm <0>: ILU_Norm (None)
489 -  -mat_superlu_ilu_milu <0>: ILU_MILU (None)
490 
491    Notes: Do not confuse this with MATSOLVERSUPERLU_DIST which is for parallel sparse solves
492 
493    Level: beginner
494 
495 .seealso: PCLU, PCILU, MATSOLVERSUPERLU_DIST, MATSOLVERMUMPS, MATSOLVERSPOOLES, PCFactorSetMatSolverPackage(), MatSolverPackage
496 M*/
497 
498 EXTERN_C_BEGIN
499 #undef __FUNCT__
500 #define __FUNCT__ "MatGetFactor_seqaij_superlu"
501 PetscErrorCode MatGetFactor_seqaij_superlu(Mat A,MatFactorType ftype,Mat *F)
502 {
503   Mat            B;
504   Mat_SuperLU    *lu;
505   PetscErrorCode ierr;
506   PetscInt       indx,m=A->rmap->n,n=A->cmap->n;
507   PetscBool      flg;
508   const char     *colperm[]={"NATURAL","MMD_ATA","MMD_AT_PLUS_A","COLAMD"}; /* MY_PERMC - not supported by the petsc interface yet */
509   const char     *iterrefine[]={"NOREFINE", "SINGLE", "DOUBLE", "EXTRA"};
510   const char     *rowperm[]={"NOROWPERM", "LargeDiag"}; /* MY_PERMC - not supported by the petsc interface yet */
511 
512   PetscFunctionBegin;
513   ierr = MatCreate(((PetscObject)A)->comm,&B);CHKERRQ(ierr);
514   ierr = MatSetSizes(B,A->rmap->n,A->cmap->n,PETSC_DETERMINE,PETSC_DETERMINE);CHKERRQ(ierr);
515   ierr = MatSetType(B,((PetscObject)A)->type_name);CHKERRQ(ierr);
516   ierr = MatSeqAIJSetPreallocation(B,0,PETSC_NULL);CHKERRQ(ierr);
517 
518   if (ftype == MAT_FACTOR_LU || ftype == MAT_FACTOR_ILU){
519     B->ops->lufactorsymbolic  = MatLUFactorSymbolic_SuperLU;
520     B->ops->ilufactorsymbolic = MatLUFactorSymbolic_SuperLU;
521   } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Factor type not supported");
522 
523   B->ops->destroy          = MatDestroy_SuperLU;
524   B->ops->view             = MatView_SuperLU;
525   B->factortype            = ftype;
526   B->assembled             = PETSC_TRUE;  /* required by -ksp_view */
527   B->preallocated          = PETSC_TRUE;
528 
529   ierr = PetscNewLog(B,Mat_SuperLU,&lu);CHKERRQ(ierr);
530 
531   if (ftype == MAT_FACTOR_LU){
532     set_default_options(&lu->options);
533     /* Comments from SuperLU_4.0/SRC/dgssvx.c:
534       "Whether or not the system will be equilibrated depends on the
535        scaling of the matrix A, but if equilibration is used, A is
536        overwritten by diag(R)*A*diag(C) and B by diag(R)*B
537        (if options->Trans=NOTRANS) or diag(C)*B (if options->Trans = TRANS or CONJ)."
538      We set 'options.Equil = NO' as default because additional space is needed for it.
539     */
540     lu->options.Equil = NO;
541   } else if (ftype == MAT_FACTOR_ILU){
542     /* Set the default input options of ilu:
543 	options.Fact = DOFACT;
544 	options.Equil = YES;           // must be YES for ilu - don't know why
545 	options.ColPerm = COLAMD;
546 	options.DiagPivotThresh = 0.1; //different from complete LU
547 	options.Trans = NOTRANS;
548 	options.IterRefine = NOREFINE;
549 	options.SymmetricMode = NO;
550 	options.PivotGrowth = NO;
551 	options.ConditionNumber = NO;
552 	options.PrintStat = YES;
553 	options.RowPerm = LargeDiag;
554 	options.ILU_DropTol = 1e-4;
555 	options.ILU_FillTol = 1e-2;
556 	options.ILU_FillFactor = 10.0;
557 	options.ILU_DropRule = DROP_BASIC | DROP_AREA;
558 	options.ILU_Norm = INF_NORM;
559 	options.ILU_MILU = SMILU_2;
560     */
561     ilu_set_default_options(&lu->options);
562   }
563   lu->options.PrintStat = NO;
564 
565   /* Initialize the statistics variables. */
566   StatInit(&lu->stat);
567   lu->lwork = 0;   /* allocate space internally by system malloc */
568 
569   ierr = PetscOptionsBegin(((PetscObject)A)->comm,((PetscObject)A)->prefix,"SuperLU Options","Mat");CHKERRQ(ierr);
570     ierr = PetscOptionsBool("-mat_superlu_equil","Equil","None",(PetscBool)lu->options.Equil,(PetscBool*)&lu->options.Equil,0);CHKERRQ(ierr);
571     ierr = PetscOptionsEList("-mat_superlu_colperm","ColPerm","None",colperm,4,colperm[3],&indx,&flg);CHKERRQ(ierr);
572     if (flg) {lu->options.ColPerm = (colperm_t)indx;}
573     ierr = PetscOptionsEList("-mat_superlu_iterrefine","IterRefine","None",iterrefine,4,iterrefine[0],&indx,&flg);CHKERRQ(ierr);
574     if (flg) { lu->options.IterRefine = (IterRefine_t)indx;}
575     ierr = PetscOptionsBool("-mat_superlu_symmetricmode","SymmetricMode","None",(PetscBool)lu->options.SymmetricMode,&flg,0);CHKERRQ(ierr);
576     if (flg) lu->options.SymmetricMode = YES;
577     ierr = PetscOptionsReal("-mat_superlu_diagpivotthresh","DiagPivotThresh","None",lu->options.DiagPivotThresh,&lu->options.DiagPivotThresh,PETSC_NULL);CHKERRQ(ierr);
578     ierr = PetscOptionsBool("-mat_superlu_pivotgrowth","PivotGrowth","None",(PetscBool)lu->options.PivotGrowth,&flg,0);CHKERRQ(ierr);
579     if (flg) lu->options.PivotGrowth = YES;
580     ierr = PetscOptionsBool("-mat_superlu_conditionnumber","ConditionNumber","None",(PetscBool)lu->options.ConditionNumber,&flg,0);CHKERRQ(ierr);
581     if (flg) lu->options.ConditionNumber = YES;
582     ierr = PetscOptionsEList("-mat_superlu_rowperm","rowperm","None",rowperm,2,rowperm[lu->options.RowPerm],&indx,&flg);CHKERRQ(ierr);
583     if (flg) {lu->options.RowPerm = (rowperm_t)indx;}
584     ierr = PetscOptionsBool("-mat_superlu_replacetinypivot","ReplaceTinyPivot","None",(PetscBool)lu->options.ReplaceTinyPivot,&flg,0);CHKERRQ(ierr);
585     if (flg) lu->options.ReplaceTinyPivot = YES;
586     ierr = PetscOptionsBool("-mat_superlu_printstat","PrintStat","None",(PetscBool)lu->options.PrintStat,&flg,0);CHKERRQ(ierr);
587     if (flg) lu->options.PrintStat = YES;
588     ierr = PetscOptionsInt("-mat_superlu_lwork","size of work array in bytes used by factorization","None",lu->lwork,&lu->lwork,PETSC_NULL);CHKERRQ(ierr);
589     if (lu->lwork > 0 ){
590       ierr = PetscMalloc(lu->lwork,&lu->work);CHKERRQ(ierr);
591     } else if (lu->lwork != 0 && lu->lwork != -1){
592       ierr = PetscPrintf(PETSC_COMM_SELF,"   Warning: lwork %D is not supported by SUPERLU. The default lwork=0 is used.\n",lu->lwork);
593       lu->lwork = 0;
594     }
595     /* ilu options */
596     ierr = PetscOptionsReal("-mat_superlu_ilu_droptol","ILU_DropTol","None",lu->options.ILU_DropTol,&lu->options.ILU_DropTol,PETSC_NULL);CHKERRQ(ierr);
597     ierr = PetscOptionsReal("-mat_superlu_ilu_filltol","ILU_FillTol","None",lu->options.ILU_FillTol,&lu->options.ILU_FillTol,PETSC_NULL);CHKERRQ(ierr);
598     ierr = PetscOptionsReal("-mat_superlu_ilu_fillfactor","ILU_FillFactor","None",lu->options.ILU_FillFactor,&lu->options.ILU_FillFactor,PETSC_NULL);CHKERRQ(ierr);
599     ierr = PetscOptionsInt("-mat_superlu_ilu_droprull","ILU_DropRule","None",lu->options.ILU_DropRule,&lu->options.ILU_DropRule,PETSC_NULL);CHKERRQ(ierr);
600     ierr = PetscOptionsInt("-mat_superlu_ilu_norm","ILU_Norm","None",lu->options.ILU_Norm,&indx,&flg);CHKERRQ(ierr);
601     if (flg){
602       lu->options.ILU_Norm = (norm_t)indx;
603     }
604     ierr = PetscOptionsInt("-mat_superlu_ilu_milu","ILU_MILU","None",lu->options.ILU_MILU,&indx,&flg);CHKERRQ(ierr);
605     if (flg){
606       lu->options.ILU_MILU = (milu_t)indx;
607     }
608   PetscOptionsEnd();
609   if (lu->options.Equil == YES) {
610     /* superlu overwrites input matrix and rhs when Equil is used, thus create A_dup to keep user's A unchanged */
611     ierr = MatDuplicate_SeqAIJ(A,MAT_COPY_VALUES,&lu->A_dup);CHKERRQ(ierr);
612   }
613 
614   /* Allocate spaces (notice sizes are for the transpose) */
615   ierr = PetscMalloc(m*sizeof(PetscInt),&lu->etree);CHKERRQ(ierr);
616   ierr = PetscMalloc(n*sizeof(PetscInt),&lu->perm_r);CHKERRQ(ierr);
617   ierr = PetscMalloc(m*sizeof(PetscInt),&lu->perm_c);CHKERRQ(ierr);
618   ierr = PetscMalloc(n*sizeof(PetscScalar),&lu->R);CHKERRQ(ierr);
619   ierr = PetscMalloc(m*sizeof(PetscScalar),&lu->C);CHKERRQ(ierr);
620 
621   /* create rhs and solution x without allocate space for .Store */
622 #if defined(PETSC_USE_COMPLEX)
623   zCreate_Dense_Matrix(&lu->B, m, 1, PETSC_NULL, m, SLU_DN, SLU_Z, SLU_GE);
624   zCreate_Dense_Matrix(&lu->X, m, 1, PETSC_NULL, m, SLU_DN, SLU_Z, SLU_GE);
625 #else
626   dCreate_Dense_Matrix(&lu->B, m, 1, PETSC_NULL, m, SLU_DN, SLU_D, SLU_GE);
627   dCreate_Dense_Matrix(&lu->X, m, 1, PETSC_NULL, m, SLU_DN, SLU_D, SLU_GE);
628 #endif
629 
630 #ifdef SUPERLU2
631   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatCreateNull","MatCreateNull_SuperLU",(void(*)(void))MatCreateNull_SuperLU);CHKERRQ(ierr);
632 #endif
633   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatFactorGetSolverPackage_C","MatFactorGetSolverPackage_seqaij_superlu",MatFactorGetSolverPackage_seqaij_superlu);CHKERRQ(ierr);
634   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatSuperluSetILUDropTol_C","MatSuperluSetILUDropTol_SuperLU",MatSuperluSetILUDropTol_SuperLU);CHKERRQ(ierr);
635   B->spptr = lu;
636   *F = B;
637   PetscFunctionReturn(0);
638 }
639 EXTERN_C_END
640 
641