xref: /petsc/src/mat/impls/aij/seq/superlu/superlu.c (revision c7c1fe80bf47b3b9a6630177da8cca3f7fe57708)
1be1d678aSKris Buschelman #define PETSCMAT_DLL
214b396bbSKris Buschelman 
314b396bbSKris Buschelman /*
475af56d4SHong Zhang         Provides an interface to the SuperLU 3.0 sparse solver
514b396bbSKris Buschelman */
614b396bbSKris Buschelman 
714b396bbSKris Buschelman #include "src/mat/impls/aij/seq/aij.h"
814b396bbSKris Buschelman 
914b396bbSKris Buschelman EXTERN_C_BEGIN
1014b396bbSKris Buschelman #if defined(PETSC_USE_COMPLEX)
1114b396bbSKris Buschelman #include "zsp_defs.h"
1214b396bbSKris Buschelman #else
1314b396bbSKris Buschelman #include "dsp_defs.h"
1414b396bbSKris Buschelman #endif
1514b396bbSKris Buschelman #include "util.h"
1614b396bbSKris Buschelman EXTERN_C_END
1714b396bbSKris Buschelman 
1814b396bbSKris Buschelman typedef struct {
1975af56d4SHong Zhang   SuperMatrix       A,L,U,B,X;
2075af56d4SHong Zhang   superlu_options_t options;
21da7a1d00SHong Zhang   PetscInt          *perm_c; /* column permutation vector */
22da7a1d00SHong Zhang   PetscInt          *perm_r; /* row permutations from partial pivoting */
23da7a1d00SHong Zhang   PetscInt          *etree;
24da7a1d00SHong Zhang   PetscReal         *R, *C;
2575af56d4SHong Zhang   char              equed[1];
26da7a1d00SHong Zhang   PetscInt          lwork;
2775af56d4SHong Zhang   void              *work;
28da7a1d00SHong Zhang   PetscReal         rpg, rcond;
2975af56d4SHong Zhang   mem_usage_t       mem_usage;
3075af56d4SHong Zhang   MatStructure      flg;
3114b396bbSKris Buschelman 
3214b396bbSKris Buschelman   /* A few function pointers for inheritance */
336849ba73SBarry Smith   PetscErrorCode (*MatDuplicate)(Mat,MatDuplicateOption,Mat*);
346849ba73SBarry Smith   PetscErrorCode (*MatView)(Mat,PetscViewer);
356849ba73SBarry Smith   PetscErrorCode (*MatAssemblyEnd)(Mat,MatAssemblyType);
366849ba73SBarry Smith   PetscErrorCode (*MatLUFactorSymbolic)(Mat,IS,IS,MatFactorInfo*,Mat*);
376849ba73SBarry Smith   PetscErrorCode (*MatDestroy)(Mat);
3814b396bbSKris Buschelman 
3914b396bbSKris Buschelman   /* Flag to clean up (non-global) SuperLU objects during Destroy */
4014b396bbSKris Buschelman   PetscTruth CleanUpSuperLU;
41f0c56d0fSKris Buschelman } Mat_SuperLU;
4214b396bbSKris Buschelman 
4314b396bbSKris Buschelman 
44dfbe8321SBarry Smith EXTERN PetscErrorCode MatFactorInfo_SuperLU(Mat,PetscViewer);
45dfbe8321SBarry Smith EXTERN PetscErrorCode MatLUFactorSymbolic_SuperLU(Mat,IS,IS,MatFactorInfo*,Mat*);
46b0592601SKris Buschelman 
47b0592601SKris Buschelman EXTERN_C_BEGIN
4875179d2cSHong Zhang EXTERN PetscErrorCode PETSCMAT_DLLEXPORT MatConvert_SuperLU_SeqAIJ(Mat,MatType,MatReuse,Mat*);
4975179d2cSHong Zhang EXTERN PetscErrorCode PETSCMAT_DLLEXPORT MatConvert_SeqAIJ_SuperLU(Mat,MatType,MatReuse,Mat*);
50b0592601SKris Buschelman EXTERN_C_END
5114b396bbSKris Buschelman 
5214b396bbSKris Buschelman #undef __FUNCT__
53f0c56d0fSKris Buschelman #define __FUNCT__ "MatDestroy_SuperLU"
54dfbe8321SBarry Smith PetscErrorCode MatDestroy_SuperLU(Mat A)
5514b396bbSKris Buschelman {
56dfbe8321SBarry Smith   PetscErrorCode ierr;
57f0c56d0fSKris Buschelman   Mat_SuperLU    *lu=(Mat_SuperLU*)A->spptr;
5814b396bbSKris Buschelman 
5914b396bbSKris Buschelman   PetscFunctionBegin;
6075af56d4SHong Zhang   if (lu->CleanUpSuperLU) { /* Free the SuperLU datastructures */
6175af56d4SHong Zhang     Destroy_SuperMatrix_Store(&lu->A);
6275af56d4SHong Zhang     Destroy_SuperMatrix_Store(&lu->B);
6375af56d4SHong Zhang     Destroy_SuperMatrix_Store(&lu->X);
649ce50919SHong Zhang 
659ce50919SHong Zhang     ierr = PetscFree(lu->etree);CHKERRQ(ierr);
669ce50919SHong Zhang     ierr = PetscFree(lu->perm_r);CHKERRQ(ierr);
679ce50919SHong Zhang     ierr = PetscFree(lu->perm_c);CHKERRQ(ierr);
689ce50919SHong Zhang     ierr = PetscFree(lu->R);CHKERRQ(ierr);
699ce50919SHong Zhang     ierr = PetscFree(lu->C);CHKERRQ(ierr);
7075af56d4SHong Zhang     if ( lu->lwork >= 0 ) {
71fb3e25aaSKris Buschelman       Destroy_SuperNode_Matrix(&lu->L);
72fb3e25aaSKris Buschelman       Destroy_CompCol_Matrix(&lu->U);
7375af56d4SHong Zhang     }
74fb3e25aaSKris Buschelman   }
75ceb03754SKris Buschelman   ierr = MatConvert_SuperLU_SeqAIJ(A,MATSEQAIJ,MAT_REUSE_MATRIX,&A);CHKERRQ(ierr);
76fb3e25aaSKris Buschelman   ierr = (*A->ops->destroy)(A);CHKERRQ(ierr);
7714b396bbSKris Buschelman   PetscFunctionReturn(0);
7814b396bbSKris Buschelman }
7914b396bbSKris Buschelman 
8014b396bbSKris Buschelman #undef __FUNCT__
81f0c56d0fSKris Buschelman #define __FUNCT__ "MatView_SuperLU"
82dfbe8321SBarry Smith PetscErrorCode MatView_SuperLU(Mat A,PetscViewer viewer)
8314b396bbSKris Buschelman {
84dfbe8321SBarry Smith   PetscErrorCode    ierr;
8532077d6dSBarry Smith   PetscTruth        iascii;
8614b396bbSKris Buschelman   PetscViewerFormat format;
87f0c56d0fSKris Buschelman   Mat_SuperLU       *lu=(Mat_SuperLU*)(A->spptr);
8814b396bbSKris Buschelman 
8914b396bbSKris Buschelman   PetscFunctionBegin;
9014b396bbSKris Buschelman   ierr = (*lu->MatView)(A,viewer);CHKERRQ(ierr);
9114b396bbSKris Buschelman 
9232077d6dSBarry Smith   ierr = PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_ASCII,&iascii);CHKERRQ(ierr);
9332077d6dSBarry Smith   if (iascii) {
9414b396bbSKris Buschelman     ierr = PetscViewerGetFormat(viewer,&format);CHKERRQ(ierr);
9514b396bbSKris Buschelman     if (format == PETSC_VIEWER_ASCII_FACTOR_INFO) {
96f0c56d0fSKris Buschelman       ierr = MatFactorInfo_SuperLU(A,viewer);CHKERRQ(ierr);
9714b396bbSKris Buschelman     }
9814b396bbSKris Buschelman   }
9914b396bbSKris Buschelman   PetscFunctionReturn(0);
10014b396bbSKris Buschelman }
10114b396bbSKris Buschelman 
10214b396bbSKris Buschelman #undef __FUNCT__
103f0c56d0fSKris Buschelman #define __FUNCT__ "MatAssemblyEnd_SuperLU"
104dfbe8321SBarry Smith PetscErrorCode MatAssemblyEnd_SuperLU(Mat A,MatAssemblyType mode) {
105dfbe8321SBarry Smith   PetscErrorCode ierr;
106f0c56d0fSKris Buschelman   Mat_SuperLU    *lu=(Mat_SuperLU*)(A->spptr);
10714b396bbSKris Buschelman 
10814b396bbSKris Buschelman   PetscFunctionBegin;
10914b396bbSKris Buschelman   ierr = (*lu->MatAssemblyEnd)(A,mode);CHKERRQ(ierr);
110b0592601SKris Buschelman   lu->MatLUFactorSymbolic  = A->ops->lufactorsymbolic;
111f0c56d0fSKris Buschelman   A->ops->lufactorsymbolic = MatLUFactorSymbolic_SuperLU;
11214b396bbSKris Buschelman   PetscFunctionReturn(0);
11314b396bbSKris Buschelman }
11414b396bbSKris Buschelman 
11575af56d4SHong Zhang /* This function was written for SuperLU 2.0 by Matthew Knepley. Not tested for SuperLU 3.0! */
11675af56d4SHong Zhang #ifdef SuperLU2
11714b396bbSKris Buschelman #include "src/mat/impls/dense/seq/dense.h"
11814b396bbSKris Buschelman #undef __FUNCT__
119f0c56d0fSKris Buschelman #define __FUNCT__ "MatCreateNull_SuperLU"
120dfbe8321SBarry Smith PetscErrorCode MatCreateNull_SuperLU(Mat A,Mat *nullMat)
12114b396bbSKris Buschelman {
122f0c56d0fSKris Buschelman   Mat_SuperLU   *lu = (Mat_SuperLU*)A->spptr;
123da7a1d00SHong Zhang   PetscInt      numRows = A->m,numCols = A->n;
12414b396bbSKris Buschelman   SCformat      *Lstore;
125da7a1d00SHong Zhang   PetscInt      numNullCols,size;
12675af56d4SHong Zhang   SuperLUStat_t stat;
12714b396bbSKris Buschelman #if defined(PETSC_USE_COMPLEX)
12814b396bbSKris Buschelman   doublecomplex *nullVals,*workVals;
12914b396bbSKris Buschelman #else
13014b396bbSKris Buschelman   PetscScalar   *nullVals,*workVals;
13114b396bbSKris Buschelman #endif
132da7a1d00SHong Zhang   PetscInt           row,newRow,col,newCol,block,b;
1336849ba73SBarry Smith   PetscErrorCode ierr;
13414b396bbSKris Buschelman 
13514b396bbSKris Buschelman   PetscFunctionBegin;
13614b396bbSKris Buschelman   if (!A->factor) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Unfactored matrix");
13714b396bbSKris Buschelman   numNullCols = numCols - numRows;
13814b396bbSKris Buschelman   if (numNullCols < 0) SETERRQ(PETSC_ERR_ARG_WRONG,"Function only applies to underdetermined problems");
139be5d1d56SKris Buschelman   /* Create the null matrix using MATSEQDENSE explicitly */
140f69a0ea3SMatthew Knepley   ierr = MatCreate(A->comm,nullMat);CHKERRQ(ierr);
141f69a0ea3SMatthew Knepley   ierr = MatSetSizes(*nullMat,numRows,numNullCols,numRows,numNullCols);CHKERRQ(ierr);
142878740d9SKris Buschelman   ierr = MatSetType(*nullMat,MATSEQDENSE);CHKERRQ(ierr);
143878740d9SKris Buschelman   ierr = MatSeqDenseSetPreallocation(*nullMat,PETSC_NULL);CHKERRQ(ierr);
144958c9bccSBarry Smith   if (!numNullCols) {
14514b396bbSKris Buschelman     ierr = MatAssemblyBegin(*nullMat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
14614b396bbSKris Buschelman     ierr = MatAssemblyEnd(*nullMat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
14714b396bbSKris Buschelman     PetscFunctionReturn(0);
14814b396bbSKris Buschelman   }
14914b396bbSKris Buschelman #if defined(PETSC_USE_COMPLEX)
15014b396bbSKris Buschelman   nullVals = (doublecomplex*)((Mat_SeqDense*)(*nullMat)->data)->v;
15114b396bbSKris Buschelman #else
15214b396bbSKris Buschelman   nullVals = ((Mat_SeqDense*)(*nullMat)->data)->v;
15314b396bbSKris Buschelman #endif
15414b396bbSKris Buschelman   /* Copy in the columns */
15514b396bbSKris Buschelman   Lstore = (SCformat*)lu->L.Store;
15614b396bbSKris Buschelman   for(block = 0; block <= Lstore->nsuper; block++) {
15714b396bbSKris Buschelman     newRow = Lstore->sup_to_col[block];
15814b396bbSKris Buschelman     size   = Lstore->sup_to_col[block+1] - Lstore->sup_to_col[block];
15914b396bbSKris Buschelman     for(col = Lstore->rowind_colptr[newRow]; col < Lstore->rowind_colptr[newRow+1]; col++) {
16014b396bbSKris Buschelman       newCol = Lstore->rowind[col];
16114b396bbSKris Buschelman       if (newCol >= numRows) {
16214b396bbSKris Buschelman         for(b = 0; b < size; b++)
16314b396bbSKris Buschelman #if defined(PETSC_USE_COMPLEX)
16414b396bbSKris Buschelman           nullVals[(newCol-numRows)*numRows+newRow+b] = ((doublecomplex*)Lstore->nzval)[Lstore->nzval_colptr[newRow+b]+col];
16514b396bbSKris Buschelman #else
16614b396bbSKris Buschelman           nullVals[(newCol-numRows)*numRows+newRow+b] = ((double*)Lstore->nzval)[Lstore->nzval_colptr[newRow+b]+col];
16714b396bbSKris Buschelman #endif
16814b396bbSKris Buschelman       }
16914b396bbSKris Buschelman     }
17014b396bbSKris Buschelman   }
17114b396bbSKris Buschelman   /* Permute rhs to form P^T_c B */
172da7a1d00SHong Zhang   ierr = PetscMalloc(numRows*sizeof(PetscReal),&workVals);CHKERRQ(ierr);
17314b396bbSKris Buschelman   for(b = 0; b < numNullCols; b++) {
17414b396bbSKris Buschelman     for(row = 0; row < numRows; row++) workVals[lu->perm_c[row]] = nullVals[b*numRows+row];
17514b396bbSKris Buschelman     for(row = 0; row < numRows; row++) nullVals[b*numRows+row]   = workVals[row];
17614b396bbSKris Buschelman   }
17714b396bbSKris Buschelman   /* Backward solve the upper triangle A x = b */
17814b396bbSKris Buschelman   for(b = 0; b < numNullCols; b++) {
17914b396bbSKris Buschelman #if defined(PETSC_USE_COMPLEX)
18075af56d4SHong Zhang     sp_ztrsv("L","T","U",&lu->L,&lu->U,&nullVals[b*numRows],&stat,&ierr);
18114b396bbSKris Buschelman #else
18275af56d4SHong Zhang     sp_dtrsv("L","T","U",&lu->L,&lu->U,&nullVals[b*numRows],&stat,&ierr);
18314b396bbSKris Buschelman #endif
18414b396bbSKris Buschelman     if (ierr < 0)
18577431f27SBarry Smith       SETERRQ1(PETSC_ERR_ARG_WRONG,"The argument %D was invalid",-ierr);
18614b396bbSKris Buschelman   }
18714b396bbSKris Buschelman   ierr = PetscFree(workVals);CHKERRQ(ierr);
18814b396bbSKris Buschelman 
18914b396bbSKris Buschelman   ierr = MatAssemblyBegin(*nullMat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
19014b396bbSKris Buschelman   ierr = MatAssemblyEnd(*nullMat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
19114b396bbSKris Buschelman   PetscFunctionReturn(0);
19214b396bbSKris Buschelman }
19375af56d4SHong Zhang #endif
19414b396bbSKris Buschelman 
19514b396bbSKris Buschelman #undef __FUNCT__
196f0c56d0fSKris Buschelman #define __FUNCT__ "MatSolve_SuperLU"
197dfbe8321SBarry Smith PetscErrorCode MatSolve_SuperLU(Mat A,Vec b,Vec x)
19814b396bbSKris Buschelman {
199f0c56d0fSKris Buschelman   Mat_SuperLU    *lu = (Mat_SuperLU*)A->spptr;
20075af56d4SHong Zhang   PetscScalar    *barray,*xarray;
201dfbe8321SBarry Smith   PetscErrorCode ierr;
202da7a1d00SHong Zhang   PetscInt       info,i;
20375af56d4SHong Zhang   SuperLUStat_t  stat;
204da7a1d00SHong Zhang   PetscReal      ferr,berr;
20514b396bbSKris Buschelman 
20614b396bbSKris Buschelman   PetscFunctionBegin;
207937a6b0eSHong Zhang   if ( lu->lwork == -1 ) {
208937a6b0eSHong Zhang     PetscFunctionReturn(0);
209937a6b0eSHong Zhang   }
21075af56d4SHong Zhang   lu->B.ncol = 1;   /* Set the number of right-hand side */
21175af56d4SHong Zhang   ierr = VecGetArray(b,&barray);CHKERRQ(ierr);
21275af56d4SHong Zhang   ierr = VecGetArray(x,&xarray);CHKERRQ(ierr);
2135fe6150dSHong Zhang 
2145fe6150dSHong Zhang #if defined(PETSC_USE_COMPLEX)
2155fe6150dSHong Zhang   ((DNformat*)lu->B.Store)->nzval = (doublecomplex*)barray;
2165fe6150dSHong Zhang   ((DNformat*)lu->X.Store)->nzval = (doublecomplex*)xarray;
2175fe6150dSHong Zhang #else
2185fe6150dSHong Zhang   ((DNformat*)lu->B.Store)->nzval = barray;
21975af56d4SHong Zhang   ((DNformat*)lu->X.Store)->nzval = xarray;
2205fe6150dSHong Zhang #endif
22175af56d4SHong Zhang 
22275af56d4SHong Zhang   /* Initialize the statistics variables. */
22375af56d4SHong Zhang   StatInit(&stat);
22475af56d4SHong Zhang 
22575af56d4SHong Zhang   lu->options.Fact  = FACTORED; /* Indicate the factored form of A is supplied. */
22675af56d4SHong Zhang   lu->options.Trans = TRANS;
2278914a3f7SHong Zhang #if defined(PETSC_USE_COMPLEX)
2288914a3f7SHong Zhang   zgssvx(&lu->options, &lu->A, lu->perm_c, lu->perm_r, lu->etree, lu->equed, lu->R, lu->C,
2298914a3f7SHong Zhang            &lu->L, &lu->U, lu->work, lu->lwork, &lu->B, &lu->X, &lu->rpg, &lu->rcond, &ferr, &berr,
2308914a3f7SHong Zhang            &lu->mem_usage, &stat, &info);
2318914a3f7SHong Zhang #else
23275af56d4SHong Zhang   dgssvx(&lu->options, &lu->A, lu->perm_c, lu->perm_r, lu->etree, lu->equed, lu->R, lu->C,
23375af56d4SHong Zhang            &lu->L, &lu->U, lu->work, lu->lwork, &lu->B, &lu->X, &lu->rpg, &lu->rcond, &ferr, &berr,
23475af56d4SHong Zhang            &lu->mem_usage, &stat, &info);
2358914a3f7SHong Zhang #endif
23675af56d4SHong Zhang   ierr = VecRestoreArray(b,&barray);CHKERRQ(ierr);
23775af56d4SHong Zhang   ierr = VecRestoreArray(x,&xarray);CHKERRQ(ierr);
23875af56d4SHong Zhang 
239958c9bccSBarry Smith   if ( !info || info == lu->A.ncol+1 ) {
24075af56d4SHong Zhang     if ( lu->options.IterRefine ) {
2418914a3f7SHong Zhang       ierr = PetscPrintf(PETSC_COMM_SELF,"Iterative Refinement:\n");
2428914a3f7SHong Zhang       ierr = PetscPrintf(PETSC_COMM_SELF,"  %8s%8s%16s%16s\n", "rhs", "Steps", "FERR", "BERR");
24375af56d4SHong Zhang       for (i = 0; i < 1; ++i)
2448914a3f7SHong Zhang         ierr = PetscPrintf(PETSC_COMM_SELF,"  %8d%8d%16e%16e\n", i+1, stat.RefineSteps, ferr, berr);
24575af56d4SHong Zhang     }
2468914a3f7SHong Zhang   } else if ( info > 0 ){
2478914a3f7SHong Zhang     if ( lu->lwork == -1 ) {
24877431f27SBarry Smith       ierr = PetscPrintf(PETSC_COMM_SELF,"  ** Estimated memory: %D bytes\n", info - lu->A.ncol);
2498914a3f7SHong Zhang     } else {
25077431f27SBarry Smith       ierr = PetscPrintf(PETSC_COMM_SELF,"  Warning: gssvx() returns info %D\n",info);
2518914a3f7SHong Zhang     }
2528914a3f7SHong Zhang   } else if (info < 0){
25377431f27SBarry Smith     SETERRQ2(PETSC_ERR_LIB, "info = %D, the %D-th argument in gssvx() had an illegal value", info,-info);
25414b396bbSKris Buschelman   }
25514b396bbSKris Buschelman 
2568914a3f7SHong Zhang   if ( lu->options.PrintStat ) {
2578914a3f7SHong Zhang     ierr = PetscPrintf(PETSC_COMM_SELF,"MatSolve__SuperLU():\n");
2588914a3f7SHong Zhang     StatPrint(&stat);
2598914a3f7SHong Zhang   }
26075af56d4SHong Zhang   StatFree(&stat);
26175af56d4SHong Zhang   PetscFunctionReturn(0);
26275af56d4SHong Zhang }
26314b396bbSKris Buschelman 
26414b396bbSKris Buschelman #undef __FUNCT__
265*c7c1fe80SHong Zhang #define __FUNCT__ "MatSolveTranspose_SuperLU"
266*c7c1fe80SHong Zhang PetscErrorCode MatSolveTranspose_SuperLU(Mat A,Vec b,Vec x)
267*c7c1fe80SHong Zhang {
268*c7c1fe80SHong Zhang   Mat_SuperLU    *lu = (Mat_SuperLU*)A->spptr;
269*c7c1fe80SHong Zhang   PetscScalar    *barray,*xarray;
270*c7c1fe80SHong Zhang   PetscErrorCode ierr;
271*c7c1fe80SHong Zhang   PetscInt       info,i;
272*c7c1fe80SHong Zhang   SuperLUStat_t  stat;
273*c7c1fe80SHong Zhang   PetscReal      ferr,berr;
274*c7c1fe80SHong Zhang 
275*c7c1fe80SHong Zhang   PetscFunctionBegin;
276*c7c1fe80SHong Zhang   if ( lu->lwork == -1 ) {
277*c7c1fe80SHong Zhang     PetscFunctionReturn(0);
278*c7c1fe80SHong Zhang   }
279*c7c1fe80SHong Zhang   lu->B.ncol = 1;   /* Set the number of right-hand side */
280*c7c1fe80SHong Zhang   ierr = VecGetArray(b,&barray);CHKERRQ(ierr);
281*c7c1fe80SHong Zhang   ierr = VecGetArray(x,&xarray);CHKERRQ(ierr);
282*c7c1fe80SHong Zhang 
283*c7c1fe80SHong Zhang #if defined(PETSC_USE_COMPLEX)
284*c7c1fe80SHong Zhang   ((DNformat*)lu->B.Store)->nzval = (doublecomplex*)barray;
285*c7c1fe80SHong Zhang   ((DNformat*)lu->X.Store)->nzval = (doublecomplex*)xarray;
286*c7c1fe80SHong Zhang #else
287*c7c1fe80SHong Zhang   ((DNformat*)lu->B.Store)->nzval = barray;
288*c7c1fe80SHong Zhang   ((DNformat*)lu->X.Store)->nzval = xarray;
289*c7c1fe80SHong Zhang #endif
290*c7c1fe80SHong Zhang 
291*c7c1fe80SHong Zhang   /* Initialize the statistics variables. */
292*c7c1fe80SHong Zhang   StatInit(&stat);
293*c7c1fe80SHong Zhang 
294*c7c1fe80SHong Zhang   lu->options.Fact  = FACTORED; /* Indicate the factored form of A is supplied. */
295*c7c1fe80SHong Zhang   lu->options.Trans = NOTRANS;
296*c7c1fe80SHong Zhang #if defined(PETSC_USE_COMPLEX)
297*c7c1fe80SHong Zhang   zgssvx(&lu->options, &lu->A, lu->perm_c, lu->perm_r, lu->etree, lu->equed, lu->R, lu->C,
298*c7c1fe80SHong Zhang            &lu->L, &lu->U, lu->work, lu->lwork, &lu->B, &lu->X, &lu->rpg, &lu->rcond, &ferr, &berr,
299*c7c1fe80SHong Zhang            &lu->mem_usage, &stat, &info);
300*c7c1fe80SHong Zhang #else
301*c7c1fe80SHong Zhang   dgssvx(&lu->options, &lu->A, lu->perm_c, lu->perm_r, lu->etree, lu->equed, lu->R, lu->C,
302*c7c1fe80SHong Zhang            &lu->L, &lu->U, lu->work, lu->lwork, &lu->B, &lu->X, &lu->rpg, &lu->rcond, &ferr, &berr,
303*c7c1fe80SHong Zhang            &lu->mem_usage, &stat, &info);
304*c7c1fe80SHong Zhang #endif
305*c7c1fe80SHong Zhang   ierr = VecRestoreArray(b,&barray);CHKERRQ(ierr);
306*c7c1fe80SHong Zhang   ierr = VecRestoreArray(x,&xarray);CHKERRQ(ierr);
307*c7c1fe80SHong Zhang 
308*c7c1fe80SHong Zhang   if ( !info || info == lu->A.ncol+1 ) {
309*c7c1fe80SHong Zhang     if ( lu->options.IterRefine ) {
310*c7c1fe80SHong Zhang       ierr = PetscPrintf(PETSC_COMM_SELF,"Iterative Refinement:\n");
311*c7c1fe80SHong Zhang       ierr = PetscPrintf(PETSC_COMM_SELF,"  %8s%8s%16s%16s\n", "rhs", "Steps", "FERR", "BERR");
312*c7c1fe80SHong Zhang       for (i = 0; i < 1; ++i)
313*c7c1fe80SHong Zhang         ierr = PetscPrintf(PETSC_COMM_SELF,"  %8d%8d%16e%16e\n", i+1, stat.RefineSteps, ferr, berr);
314*c7c1fe80SHong Zhang     }
315*c7c1fe80SHong Zhang   } else if ( info > 0 ){
316*c7c1fe80SHong Zhang     if ( lu->lwork == -1 ) {
317*c7c1fe80SHong Zhang       ierr = PetscPrintf(PETSC_COMM_SELF,"  ** Estimated memory: %D bytes\n", info - lu->A.ncol);
318*c7c1fe80SHong Zhang     } else {
319*c7c1fe80SHong Zhang       ierr = PetscPrintf(PETSC_COMM_SELF,"  Warning: gssvx() returns info %D\n",info);
320*c7c1fe80SHong Zhang     }
321*c7c1fe80SHong Zhang   } else if (info < 0){
322*c7c1fe80SHong Zhang     SETERRQ2(PETSC_ERR_LIB, "info = %D, the %D-th argument in gssvx() had an illegal value", info,-info);
323*c7c1fe80SHong Zhang   }
324*c7c1fe80SHong Zhang 
325*c7c1fe80SHong Zhang   if ( lu->options.PrintStat ) {
326*c7c1fe80SHong Zhang     ierr = PetscPrintf(PETSC_COMM_SELF,"MatSolve_SuperLU():\n");
327*c7c1fe80SHong Zhang     StatPrint(&stat);
328*c7c1fe80SHong Zhang   }
329*c7c1fe80SHong Zhang   StatFree(&stat);
330*c7c1fe80SHong Zhang   PetscFunctionReturn(0);
331*c7c1fe80SHong Zhang }
332*c7c1fe80SHong Zhang 
333*c7c1fe80SHong Zhang #undef __FUNCT__
334f0c56d0fSKris Buschelman #define __FUNCT__ "MatLUFactorNumeric_SuperLU"
335af281ebdSHong Zhang PetscErrorCode MatLUFactorNumeric_SuperLU(Mat A,MatFactorInfo *info,Mat *F)
33614b396bbSKris Buschelman {
33714b396bbSKris Buschelman   Mat_SeqAIJ     *aa = (Mat_SeqAIJ*)(A)->data;
338f0c56d0fSKris Buschelman   Mat_SuperLU    *lu = (Mat_SuperLU*)(*F)->spptr;
339dfbe8321SBarry Smith   PetscErrorCode ierr;
340da7a1d00SHong Zhang   PetscInt       sinfo;
34175af56d4SHong Zhang   SuperLUStat_t  stat;
342da7a1d00SHong Zhang   PetscReal      ferr, berr;
3438914a3f7SHong Zhang   NCformat       *Ustore;
3448914a3f7SHong Zhang   SCformat       *Lstore;
34514b396bbSKris Buschelman 
34614b396bbSKris Buschelman   PetscFunctionBegin;
3479ce50919SHong Zhang   if (lu->flg == SAME_NONZERO_PATTERN){ /* successing numerical factorization */
3489ce50919SHong Zhang     lu->options.Fact = SamePattern;
34975af56d4SHong Zhang     /* Ref: ~SuperLU_3.0/EXAMPLE/dlinsolx2.c */
35075af56d4SHong Zhang     Destroy_SuperMatrix_Store(&lu->A);
3519ce50919SHong Zhang     if ( lu->lwork >= 0 ) {
35275af56d4SHong Zhang       Destroy_SuperNode_Matrix(&lu->L);
35375af56d4SHong Zhang       Destroy_CompCol_Matrix(&lu->U);
35475af56d4SHong Zhang       lu->options.Fact = SamePattern;
35514b396bbSKris Buschelman     }
35675af56d4SHong Zhang   }
35714b396bbSKris Buschelman 
35875af56d4SHong Zhang   /* Create the SuperMatrix for lu->A=A^T:
35975af56d4SHong Zhang        Since SuperLU likes column-oriented matrices,we pass it the transpose,
36075af56d4SHong Zhang        and then solve A^T X = B in MatSolve(). */
36175af56d4SHong Zhang #if defined(PETSC_USE_COMPLEX)
3625fe6150dSHong Zhang   zCreate_CompCol_Matrix(&lu->A,A->n,A->m,aa->nz,(doublecomplex*)aa->a,aa->j,aa->i,
36375af56d4SHong Zhang                            SLU_NC,SLU_Z,SLU_GE);
36475af56d4SHong Zhang #else
36575af56d4SHong Zhang   dCreate_CompCol_Matrix(&lu->A,A->n,A->m,aa->nz,aa->a,aa->j,aa->i,
36675af56d4SHong Zhang                            SLU_NC,SLU_D,SLU_GE);
36775af56d4SHong Zhang #endif
36875af56d4SHong Zhang 
36975af56d4SHong Zhang   /* Initialize the statistics variables. */
37075af56d4SHong Zhang   StatInit(&stat);
37175af56d4SHong Zhang 
3729ce50919SHong Zhang   /* Numerical factorization */
37375af56d4SHong Zhang   lu->B.ncol = 0;  /* Indicate not to solve the system */
3748914a3f7SHong Zhang #if defined(PETSC_USE_COMPLEX)
3758914a3f7SHong Zhang    zgssvx(&lu->options, &lu->A, lu->perm_c, lu->perm_r, lu->etree, lu->equed, lu->R, lu->C,
3768914a3f7SHong Zhang            &lu->L, &lu->U, lu->work, lu->lwork, &lu->B, &lu->X, &lu->rpg, &lu->rcond, &ferr, &berr,
377da7a1d00SHong Zhang            &lu->mem_usage, &stat, &sinfo);
3788914a3f7SHong Zhang #else
37975af56d4SHong Zhang   dgssvx(&lu->options, &lu->A, lu->perm_c, lu->perm_r, lu->etree, lu->equed, lu->R, lu->C,
38075af56d4SHong Zhang            &lu->L, &lu->U, lu->work, lu->lwork, &lu->B, &lu->X, &lu->rpg, &lu->rcond, &ferr, &berr,
381da7a1d00SHong Zhang            &lu->mem_usage, &stat, &sinfo);
3828914a3f7SHong Zhang #endif
383da7a1d00SHong Zhang   if ( !sinfo || sinfo == lu->A.ncol+1 ) {
3848914a3f7SHong Zhang     if ( lu->options.PivotGrowth )
3858914a3f7SHong Zhang       ierr = PetscPrintf(PETSC_COMM_SELF,"  Recip. pivot growth = %e\n", lu->rpg);
38675af56d4SHong Zhang     if ( lu->options.ConditionNumber )
3878914a3f7SHong Zhang       ierr = PetscPrintf(PETSC_COMM_SELF,"  Recip. condition number = %e\n", lu->rcond);
388da7a1d00SHong Zhang   } else if ( sinfo > 0 ){
3898914a3f7SHong Zhang     if ( lu->lwork == -1 ) {
390da7a1d00SHong Zhang       ierr = PetscPrintf(PETSC_COMM_SELF,"  ** Estimated memory: %D bytes\n", sinfo - lu->A.ncol);
3918914a3f7SHong Zhang     } else {
392da7a1d00SHong Zhang       ierr = PetscPrintf(PETSC_COMM_SELF,"  Warning: gssvx() returns info %D\n",sinfo);
3938914a3f7SHong Zhang     }
394da7a1d00SHong Zhang   } else { /* sinfo < 0 */
395da7a1d00SHong Zhang     SETERRQ2(PETSC_ERR_LIB, "info = %D, the %D-th argument in gssvx() had an illegal value", sinfo,-sinfo);
39675af56d4SHong Zhang   }
39775af56d4SHong Zhang 
3988914a3f7SHong Zhang   if ( lu->options.PrintStat ) {
3998914a3f7SHong Zhang     ierr = PetscPrintf(PETSC_COMM_SELF,"MatLUFactorNumeric_SuperLU():\n");
4008914a3f7SHong Zhang     StatPrint(&stat);
4018914a3f7SHong Zhang     Lstore = (SCformat *) lu->L.Store;
4028914a3f7SHong Zhang     Ustore = (NCformat *) lu->U.Store;
40377431f27SBarry Smith     ierr = PetscPrintf(PETSC_COMM_SELF,"  No of nonzeros in factor L = %D\n", Lstore->nnz);
40477431f27SBarry Smith     ierr = PetscPrintf(PETSC_COMM_SELF,"  No of nonzeros in factor U = %D\n", Ustore->nnz);
40577431f27SBarry Smith     ierr = PetscPrintf(PETSC_COMM_SELF,"  No of nonzeros in L+U = %D\n", Lstore->nnz + Ustore->nnz - lu->A.ncol);
40677431f27SBarry Smith     ierr = PetscPrintf(PETSC_COMM_SELF,"  L\\U MB %.3f\ttotal MB needed %.3f\texpansions %D\n",
4078914a3f7SHong Zhang 	       lu->mem_usage.for_lu/1e6, lu->mem_usage.total_needed/1e6,
4088914a3f7SHong Zhang 	       lu->mem_usage.expansions);
4098914a3f7SHong Zhang   }
41075af56d4SHong Zhang   StatFree(&stat);
41175af56d4SHong Zhang 
41275af56d4SHong Zhang   lu->flg = SAME_NONZERO_PATTERN;
41375af56d4SHong Zhang   PetscFunctionReturn(0);
41414b396bbSKris Buschelman }
41514b396bbSKris Buschelman 
41614b396bbSKris Buschelman /*
41714b396bbSKris Buschelman    Note the r permutation is ignored
41814b396bbSKris Buschelman */
41914b396bbSKris Buschelman #undef __FUNCT__
420f0c56d0fSKris Buschelman #define __FUNCT__ "MatLUFactorSymbolic_SuperLU"
421dfbe8321SBarry Smith PetscErrorCode MatLUFactorSymbolic_SuperLU(Mat A,IS r,IS c,MatFactorInfo *info,Mat *F)
42214b396bbSKris Buschelman {
42314b396bbSKris Buschelman   Mat            B;
424f0c56d0fSKris Buschelman   Mat_SuperLU    *lu;
4256849ba73SBarry Smith   PetscErrorCode ierr;
426da7a1d00SHong Zhang   PetscInt       m=A->m,n=A->n,indx;
4279ce50919SHong Zhang   PetscTruth     flg;
4285ca28756SHong Zhang   const char   *colperm[]={"NATURAL","MMD_ATA","MMD_AT_PLUS_A","COLAMD"}; /* MY_PERMC - not supported by the petsc interface yet */
4295ca28756SHong Zhang   const char   *iterrefine[]={"NOREFINE", "SINGLE", "DOUBLE", "EXTRA"};
4305ca28756SHong Zhang   const char   *rowperm[]={"NOROWPERM", "LargeDiag"}; /* MY_PERMC - not supported by the petsc interface yet */
43114b396bbSKris Buschelman 
43214b396bbSKris Buschelman   PetscFunctionBegin;
433f69a0ea3SMatthew Knepley   ierr = MatCreate(A->comm,&B);CHKERRQ(ierr);
434f69a0ea3SMatthew Knepley   ierr = MatSetSizes(B,A->m,A->n,PETSC_DETERMINE,PETSC_DETERMINE);CHKERRQ(ierr);
435be5d1d56SKris Buschelman   ierr = MatSetType(B,A->type_name);CHKERRQ(ierr);
436899d7b4fSKris Buschelman   ierr = MatSeqAIJSetPreallocation(B,0,PETSC_NULL);CHKERRQ(ierr);
437f0c56d0fSKris Buschelman 
438f0c56d0fSKris Buschelman   B->ops->lufactornumeric = MatLUFactorNumeric_SuperLU;
439f0c56d0fSKris Buschelman   B->ops->solve           = MatSolve_SuperLU;
440*c7c1fe80SHong Zhang   B->ops->solvetranspose  = MatSolveTranspose_SuperLU;
44114b396bbSKris Buschelman   B->factor               = FACTOR_LU;
44294b7f48cSBarry Smith   B->assembled            = PETSC_TRUE;  /* required by -ksp_view */
44314b396bbSKris Buschelman 
444f0c56d0fSKris Buschelman   lu = (Mat_SuperLU*)(B->spptr);
4459ce50919SHong Zhang 
4469ce50919SHong Zhang   /* Set SuperLU options */
4479ce50919SHong Zhang     /* the default values for options argument:
4489ce50919SHong Zhang 	options.Fact = DOFACT;
4499ce50919SHong Zhang         options.Equil = YES;
4509ce50919SHong Zhang     	options.ColPerm = COLAMD;
4519ce50919SHong Zhang 	options.DiagPivotThresh = 1.0;
4529ce50919SHong Zhang     	options.Trans = NOTRANS;
4539ce50919SHong Zhang     	options.IterRefine = NOREFINE;
4549ce50919SHong Zhang     	options.SymmetricMode = NO;
4559ce50919SHong Zhang     	options.PivotGrowth = NO;
4569ce50919SHong Zhang     	options.ConditionNumber = NO;
4579ce50919SHong Zhang     	options.PrintStat = YES;
4589ce50919SHong Zhang     */
4599ce50919SHong Zhang   set_default_options(&lu->options);
4608914a3f7SHong Zhang   /* equilibration causes error in solve(), thus not supported here. See dgssvx.c for possible reason. */
4618914a3f7SHong Zhang   lu->options.Equil = NO;
4629ce50919SHong Zhang   lu->options.PrintStat = NO;
4638914a3f7SHong Zhang   lu->lwork = 0;   /* allocate space internally by system malloc */
4649ce50919SHong Zhang 
4659ce50919SHong Zhang   ierr = PetscOptionsBegin(A->comm,A->prefix,"SuperLU Options","Mat");CHKERRQ(ierr);
4669ce50919SHong Zhang   /*
4674dc4c822SBarry Smith   ierr = PetscOptionsTruth("-mat_superlu_equil","Equil","None",PETSC_FALSE,&flg,0);CHKERRQ(ierr);
4688914a3f7SHong Zhang   if (flg) lu->options.Equil = YES; -- not supported by the interface !!!
4699ce50919SHong Zhang   */
4708914a3f7SHong Zhang   ierr = PetscOptionsEList("-mat_superlu_colperm","ColPerm","None",colperm,4,colperm[3],&indx,&flg);CHKERRQ(ierr);
4719ce50919SHong Zhang   if (flg) {lu->options.ColPerm = (colperm_t)indx;}
4728914a3f7SHong Zhang   ierr = PetscOptionsEList("-mat_superlu_iterrefine","IterRefine","None",iterrefine,4,iterrefine[0],&indx,&flg);CHKERRQ(ierr);
4739ce50919SHong Zhang   if (flg) { lu->options.IterRefine = (IterRefine_t)indx;}
4744dc4c822SBarry Smith   ierr = PetscOptionsTruth("-mat_superlu_symmetricmode","SymmetricMode","None",PETSC_FALSE,&flg,0);CHKERRQ(ierr);
4759ce50919SHong Zhang   if (flg) lu->options.SymmetricMode = YES;
4768914a3f7SHong Zhang   ierr = PetscOptionsReal("-mat_superlu_diagpivotthresh","DiagPivotThresh","None",lu->options.DiagPivotThresh,&lu->options.DiagPivotThresh,PETSC_NULL);CHKERRQ(ierr);
4774dc4c822SBarry Smith   ierr = PetscOptionsTruth("-mat_superlu_pivotgrowth","PivotGrowth","None",PETSC_FALSE,&flg,0);CHKERRQ(ierr);
4789ce50919SHong Zhang   if (flg) lu->options.PivotGrowth = YES;
4794dc4c822SBarry Smith   ierr = PetscOptionsTruth("-mat_superlu_conditionnumber","ConditionNumber","None",PETSC_FALSE,&flg,0);CHKERRQ(ierr);
4809ce50919SHong Zhang   if (flg) lu->options.ConditionNumber = YES;
4818914a3f7SHong Zhang   ierr = PetscOptionsEList("-mat_superlu_rowperm","rowperm","None",rowperm,2,rowperm[0],&indx,&flg);CHKERRQ(ierr);
4829ce50919SHong Zhang   if (flg) {lu->options.RowPerm = (rowperm_t)indx;}
4834dc4c822SBarry Smith   ierr = PetscOptionsTruth("-mat_superlu_replacetinypivot","ReplaceTinyPivot","None",PETSC_FALSE,&flg,0);CHKERRQ(ierr);
4849ce50919SHong Zhang   if (flg) lu->options.ReplaceTinyPivot = YES;
4854dc4c822SBarry Smith   ierr = PetscOptionsTruth("-mat_superlu_printstat","PrintStat","None",PETSC_FALSE,&flg,0);CHKERRQ(ierr);
4869ce50919SHong Zhang   if (flg) lu->options.PrintStat = YES;
4878914a3f7SHong Zhang   ierr = PetscOptionsInt("-mat_superlu_lwork","size of work array in bytes used by factorization","None",lu->lwork,&lu->lwork,PETSC_NULL);CHKERRQ(ierr);
4885fe6150dSHong Zhang   if (lu->lwork > 0 ){
4895fe6150dSHong Zhang     ierr = PetscMalloc(lu->lwork,&lu->work);CHKERRQ(ierr);
4905fe6150dSHong Zhang   } else if (lu->lwork != 0 && lu->lwork != -1){
49177431f27SBarry Smith     ierr = PetscPrintf(PETSC_COMM_SELF,"   Warning: lwork %D is not supported by SUPERLU. The default lwork=0 is used.\n",lu->lwork);
4928914a3f7SHong Zhang     lu->lwork = 0;
4938914a3f7SHong Zhang   }
4949ce50919SHong Zhang   PetscOptionsEnd();
4959ce50919SHong Zhang 
49675af56d4SHong Zhang #ifdef SUPERLU2
4972ecb5974SKris Buschelman   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatCreateNull","MatCreateNull_SuperLU",
498f0c56d0fSKris Buschelman                                     (void(*)(void))MatCreateNull_SuperLU);CHKERRQ(ierr);
49975af56d4SHong Zhang #endif
50014b396bbSKris Buschelman 
50175af56d4SHong Zhang   /* Allocate spaces (notice sizes are for the transpose) */
502da7a1d00SHong Zhang   ierr = PetscMalloc(m*sizeof(PetscInt),&lu->etree);CHKERRQ(ierr);
503da7a1d00SHong Zhang   ierr = PetscMalloc(n*sizeof(PetscInt),&lu->perm_r);CHKERRQ(ierr);
504da7a1d00SHong Zhang   ierr = PetscMalloc(m*sizeof(PetscInt),&lu->perm_c);CHKERRQ(ierr);
505da7a1d00SHong Zhang   ierr = PetscMalloc(n*sizeof(PetscInt),&lu->R);CHKERRQ(ierr);
506da7a1d00SHong Zhang   ierr = PetscMalloc(m*sizeof(PetscInt),&lu->C);CHKERRQ(ierr);
50775af56d4SHong Zhang 
5089ce50919SHong Zhang   /* create rhs and solution x without allocate space for .Store */
5095fe6150dSHong Zhang #if defined(PETSC_USE_COMPLEX)
510937a6b0eSHong Zhang   zCreate_Dense_Matrix(&lu->B, m, 1, PETSC_NULL, m, SLU_DN, SLU_Z, SLU_GE);
511937a6b0eSHong Zhang   zCreate_Dense_Matrix(&lu->X, m, 1, PETSC_NULL, m, SLU_DN, SLU_Z, SLU_GE);
5125fe6150dSHong Zhang #else
51375af56d4SHong Zhang   dCreate_Dense_Matrix(&lu->B, m, 1, PETSC_NULL, m, SLU_DN, SLU_D, SLU_GE);
51475af56d4SHong Zhang   dCreate_Dense_Matrix(&lu->X, m, 1, PETSC_NULL, m, SLU_DN, SLU_D, SLU_GE);
5155fe6150dSHong Zhang #endif
51614b396bbSKris Buschelman 
51714b396bbSKris Buschelman   lu->flg            = DIFFERENT_NONZERO_PATTERN;
518e740cb95SKris Buschelman   lu->CleanUpSuperLU = PETSC_TRUE;
519899d7b4fSKris Buschelman 
520899d7b4fSKris Buschelman   *F = B;
521da7a1d00SHong Zhang   ierr = PetscLogObjectMemory(B,(A->m+A->n)*sizeof(PetscInt)+sizeof(Mat_SuperLU));CHKERRQ(ierr);
52214b396bbSKris Buschelman   PetscFunctionReturn(0);
52314b396bbSKris Buschelman }
52414b396bbSKris Buschelman 
52594b7f48cSBarry Smith /* used by -ksp_view */
52614b396bbSKris Buschelman #undef __FUNCT__
527f0c56d0fSKris Buschelman #define __FUNCT__ "MatFactorInfo_SuperLU"
528dfbe8321SBarry Smith PetscErrorCode MatFactorInfo_SuperLU(Mat A,PetscViewer viewer)
52914b396bbSKris Buschelman {
530f0c56d0fSKris Buschelman   Mat_SuperLU       *lu= (Mat_SuperLU*)A->spptr;
531da7a1d00SHong Zhang   PetscErrorCode    ierr;
5329ce50919SHong Zhang   superlu_options_t options;
533f0c56d0fSKris Buschelman 
534f0c56d0fSKris Buschelman   PetscFunctionBegin;
5359ce50919SHong Zhang   /* check if matrix is superlu_dist type */
5369ce50919SHong Zhang   if (A->ops->solve != MatSolve_SuperLU) PetscFunctionReturn(0);
5379ce50919SHong Zhang 
5389ce50919SHong Zhang   options = lu->options;
539f0c56d0fSKris Buschelman   ierr = PetscViewerASCIIPrintf(viewer,"SuperLU run parameters:\n");CHKERRQ(ierr);
5409ce50919SHong Zhang   ierr = PetscViewerASCIIPrintf(viewer,"  Equil: %s\n",(options.Equil != NO) ? "YES": "NO");CHKERRQ(ierr);
54177431f27SBarry Smith   ierr = PetscViewerASCIIPrintf(viewer,"  ColPerm: %D\n",options.ColPerm);CHKERRQ(ierr);
54277431f27SBarry Smith   ierr = PetscViewerASCIIPrintf(viewer,"  IterRefine: %D\n",options.IterRefine);CHKERRQ(ierr);
5439ce50919SHong Zhang   ierr = PetscViewerASCIIPrintf(viewer,"  SymmetricMode: %s\n",(options.SymmetricMode != NO) ? "YES": "NO");CHKERRQ(ierr);
5449ce50919SHong Zhang   ierr = PetscViewerASCIIPrintf(viewer,"  DiagPivotThresh: %g\n",options.DiagPivotThresh);CHKERRQ(ierr);
5459ce50919SHong Zhang   ierr = PetscViewerASCIIPrintf(viewer,"  PivotGrowth: %s\n",(options.PivotGrowth != NO) ? "YES": "NO");CHKERRQ(ierr);
5469ce50919SHong Zhang   ierr = PetscViewerASCIIPrintf(viewer,"  ConditionNumber: %s\n",(options.ConditionNumber != NO) ? "YES": "NO");CHKERRQ(ierr);
54777431f27SBarry Smith   ierr = PetscViewerASCIIPrintf(viewer,"  RowPerm: %D\n",options.RowPerm);CHKERRQ(ierr);
5489ce50919SHong Zhang   ierr = PetscViewerASCIIPrintf(viewer,"  ReplaceTinyPivot: %s\n",(options.ReplaceTinyPivot != NO) ? "YES": "NO");CHKERRQ(ierr);
5499ce50919SHong Zhang   ierr = PetscViewerASCIIPrintf(viewer,"  PrintStat: %s\n",(options.PrintStat != NO) ? "YES": "NO");CHKERRQ(ierr);
55077431f27SBarry Smith   ierr = PetscViewerASCIIPrintf(viewer,"  lwork: %D\n",lu->lwork);CHKERRQ(ierr);
5519ce50919SHong Zhang 
552f0c56d0fSKris Buschelman   PetscFunctionReturn(0);
553f0c56d0fSKris Buschelman }
554f0c56d0fSKris Buschelman 
555f0c56d0fSKris Buschelman #undef __FUNCT__
556f0c56d0fSKris Buschelman #define __FUNCT__ "MatDuplicate_SuperLU"
557dfbe8321SBarry Smith PetscErrorCode MatDuplicate_SuperLU(Mat A, MatDuplicateOption op, Mat *M) {
558da7a1d00SHong Zhang   PetscErrorCode ierr;
5598f340917SKris Buschelman   Mat_SuperLU    *lu=(Mat_SuperLU *)A->spptr;
5608f340917SKris Buschelman 
56114b396bbSKris Buschelman   PetscFunctionBegin;
5628f340917SKris Buschelman   ierr = (*lu->MatDuplicate)(A,op,M);CHKERRQ(ierr);
5633f953163SKris Buschelman   ierr = PetscMemcpy((*M)->spptr,lu,sizeof(Mat_SuperLU));CHKERRQ(ierr);
56414b396bbSKris Buschelman   PetscFunctionReturn(0);
56514b396bbSKris Buschelman }
56614b396bbSKris Buschelman 
56714b396bbSKris Buschelman EXTERN_C_BEGIN
56814b396bbSKris Buschelman #undef __FUNCT__
569b0592601SKris Buschelman #define __FUNCT__ "MatConvert_SuperLU_SeqAIJ"
57075179d2cSHong Zhang PetscErrorCode PETSCMAT_DLLEXPORT MatConvert_SuperLU_SeqAIJ(Mat A,MatType type,MatReuse reuse,Mat *newmat)
571521d7252SBarry Smith {
572fb3e25aaSKris Buschelman   /* This routine is only called to convert an unfactored PETSc-SuperLU matrix */
573fb3e25aaSKris Buschelman   /* to its base PETSc type, so we will ignore 'MatType type'. */
574da7a1d00SHong Zhang   PetscErrorCode ierr;
575b0592601SKris Buschelman   Mat            B=*newmat;
576f0c56d0fSKris Buschelman   Mat_SuperLU    *lu=(Mat_SuperLU *)A->spptr;
577b0592601SKris Buschelman 
578b0592601SKris Buschelman   PetscFunctionBegin;
579ceb03754SKris Buschelman   if (reuse == MAT_INITIAL_MATRIX) {
580b0592601SKris Buschelman     ierr = MatDuplicate(A,MAT_COPY_VALUES,&B);CHKERRQ(ierr);
581f0c56d0fSKris Buschelman   }
582b0592601SKris Buschelman   /* Reset the original function pointers */
583f0c56d0fSKris Buschelman   B->ops->duplicate        = lu->MatDuplicate;
584b0592601SKris Buschelman   B->ops->view             = lu->MatView;
585b0592601SKris Buschelman   B->ops->assemblyend      = lu->MatAssemblyEnd;
586b0592601SKris Buschelman   B->ops->lufactorsymbolic = lu->MatLUFactorSymbolic;
587b0592601SKris Buschelman   B->ops->destroy          = lu->MatDestroy;
588b0592601SKris Buschelman   /* lu is only a function pointer stash unless we've factored the matrix, which we haven't! */
589b0592601SKris Buschelman   ierr = PetscFree(lu);CHKERRQ(ierr);
590901853e0SKris Buschelman 
591901853e0SKris Buschelman   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_superlu_C","",PETSC_NULL);CHKERRQ(ierr);
592901853e0SKris Buschelman   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_superlu_seqaij_C","",PETSC_NULL);CHKERRQ(ierr);
593901853e0SKris Buschelman 
594b0592601SKris Buschelman   ierr = PetscObjectChangeTypeName((PetscObject)B,MATSEQAIJ);CHKERRQ(ierr);
595b0592601SKris Buschelman   *newmat = B;
596b0592601SKris Buschelman   PetscFunctionReturn(0);
597b0592601SKris Buschelman }
598b0592601SKris Buschelman EXTERN_C_END
599b0592601SKris Buschelman 
600b0592601SKris Buschelman EXTERN_C_BEGIN
601b0592601SKris Buschelman #undef __FUNCT__
602b0592601SKris Buschelman #define __FUNCT__ "MatConvert_SeqAIJ_SuperLU"
60375179d2cSHong Zhang PetscErrorCode PETSCMAT_DLLEXPORT MatConvert_SeqAIJ_SuperLU(Mat A,MatType type,MatReuse reuse,Mat *newmat)
604521d7252SBarry Smith {
605fb3e25aaSKris Buschelman   /* This routine is only called to convert to MATSUPERLU */
606fb3e25aaSKris Buschelman   /* from MATSEQAIJ, so we will ignore 'MatType type'. */
607da7a1d00SHong Zhang   PetscErrorCode ierr;
608b0592601SKris Buschelman   Mat            B=*newmat;
609f0c56d0fSKris Buschelman   Mat_SuperLU    *lu;
61014b396bbSKris Buschelman 
61114b396bbSKris Buschelman   PetscFunctionBegin;
612ceb03754SKris Buschelman   if (reuse == MAT_INITIAL_MATRIX) {
613b0592601SKris Buschelman     ierr = MatDuplicate(A,MAT_COPY_VALUES,&B);CHKERRQ(ierr);
614b0592601SKris Buschelman   }
61514b396bbSKris Buschelman 
616f0c56d0fSKris Buschelman   ierr = PetscNew(Mat_SuperLU,&lu);CHKERRQ(ierr);
617f0c56d0fSKris Buschelman   lu->MatDuplicate         = A->ops->duplicate;
61814b396bbSKris Buschelman   lu->MatView              = A->ops->view;
61914b396bbSKris Buschelman   lu->MatAssemblyEnd       = A->ops->assemblyend;
620b0592601SKris Buschelman   lu->MatLUFactorSymbolic  = A->ops->lufactorsymbolic;
62114b396bbSKris Buschelman   lu->MatDestroy           = A->ops->destroy;
62214b396bbSKris Buschelman   lu->CleanUpSuperLU       = PETSC_FALSE;
623b0592601SKris Buschelman 
624b0592601SKris Buschelman   B->spptr                 = (void*)lu;
625f0c56d0fSKris Buschelman   B->ops->duplicate        = MatDuplicate_SuperLU;
626f0c56d0fSKris Buschelman   B->ops->view             = MatView_SuperLU;
627f0c56d0fSKris Buschelman   B->ops->assemblyend      = MatAssemblyEnd_SuperLU;
628f0c56d0fSKris Buschelman   B->ops->lufactorsymbolic = MatLUFactorSymbolic_SuperLU;
629e4e36384SHong Zhang   B->ops->choleskyfactorsymbolic = 0;
630f0c56d0fSKris Buschelman   B->ops->destroy          = MatDestroy_SuperLU;
631b0592601SKris Buschelman 
632b0592601SKris Buschelman   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatConvert_seqaij_superlu_C",
633b0592601SKris Buschelman                                            "MatConvert_SeqAIJ_SuperLU",MatConvert_SeqAIJ_SuperLU);CHKERRQ(ierr);
634b0592601SKris Buschelman   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatConvert_superlu_seqaij_C",
635b0592601SKris Buschelman                                            "MatConvert_SuperLU_SeqAIJ",MatConvert_SuperLU_SeqAIJ);CHKERRQ(ierr);
63663ba0a88SBarry Smith   ierr = PetscLogInfo((0,"MatConvert_SeqAIJ_SuperLU:Using SuperLU for SeqAIJ LU factorization and solves.\n"));CHKERRQ(ierr);
637fb3e25aaSKris Buschelman   ierr = PetscObjectChangeTypeName((PetscObject)B,MATSUPERLU);CHKERRQ(ierr);
638b0592601SKris Buschelman   *newmat = B;
639b0592601SKris Buschelman   PetscFunctionReturn(0);
640b0592601SKris Buschelman }
641b0592601SKris Buschelman EXTERN_C_END
642b0592601SKris Buschelman 
64324b6179bSKris Buschelman /*MC
644fafad747SKris Buschelman   MATSUPERLU - MATSUPERLU = "superlu" - A matrix type providing direct solvers (LU) for sequential matrices
64524b6179bSKris Buschelman   via the external package SuperLU.
64624b6179bSKris Buschelman 
64724b6179bSKris Buschelman   If SuperLU is installed (see the manual for
64824b6179bSKris Buschelman   instructions on how to declare the existence of external packages),
64924b6179bSKris Buschelman   a matrix type can be constructed which invokes SuperLU solvers.
65024b6179bSKris Buschelman   After calling MatCreate(...,A), simply call MatSetType(A,MATSUPERLU).
65124b6179bSKris Buschelman 
65224b6179bSKris Buschelman   This matrix inherits from MATSEQAIJ.  As a result, MatSeqAIJSetPreallocation is
65328b08bd3SKris Buschelman   supported for this matrix type.  One can also call MatConvert for an inplace conversion to or from
65428b08bd3SKris Buschelman   the MATSEQAIJ type without data copy.
65524b6179bSKris Buschelman 
65624b6179bSKris Buschelman   Options Database Keys:
6570bad9183SKris Buschelman + -mat_type superlu - sets the matrix type to "superlu" during a call to MatSetFromOptions()
65824b6179bSKris Buschelman - -mat_superlu_ordering <0,1,2,3> - 0: natural ordering,
65924b6179bSKris Buschelman                                     1: MMD applied to A'*A,
66024b6179bSKris Buschelman                                     2: MMD applied to A'+A,
66124b6179bSKris Buschelman                                     3: COLAMD, approximate minimum degree column ordering
66224b6179bSKris Buschelman 
66324b6179bSKris Buschelman    Level: beginner
66424b6179bSKris Buschelman 
66524b6179bSKris Buschelman .seealso: PCLU
66624b6179bSKris Buschelman M*/
66724b6179bSKris Buschelman 
668b0592601SKris Buschelman EXTERN_C_BEGIN
669b0592601SKris Buschelman #undef __FUNCT__
670f0c56d0fSKris Buschelman #define __FUNCT__ "MatCreate_SuperLU"
671be1d678aSKris Buschelman PetscErrorCode PETSCMAT_DLLEXPORT MatCreate_SuperLU(Mat A)
672dfbe8321SBarry Smith {
673dfbe8321SBarry Smith   PetscErrorCode ierr;
674b0592601SKris Buschelman 
675b0592601SKris Buschelman   PetscFunctionBegin;
6765441df8eSKris Buschelman   /* Change type name before calling MatSetType to force proper construction of SeqAIJ and SUPERLU types */
6775441df8eSKris Buschelman   ierr = PetscObjectChangeTypeName((PetscObject)A,MATSUPERLU);CHKERRQ(ierr);
678b0592601SKris Buschelman   ierr = MatSetType(A,MATSEQAIJ);CHKERRQ(ierr);
679ceb03754SKris Buschelman   ierr = MatConvert_SeqAIJ_SuperLU(A,MATSUPERLU,MAT_REUSE_MATRIX,&A);CHKERRQ(ierr);
68014b396bbSKris Buschelman   PetscFunctionReturn(0);
68114b396bbSKris Buschelman }
68214b396bbSKris Buschelman EXTERN_C_END
683