xref: /petsc/src/mat/impls/aij/seq/superlu/superlu.c (revision 5441df8ea7fc15821ed1fa0916d70c7c3774aeba)
114b396bbSKris Buschelman /*$Id: superlu.c,v 1.10 2001/08/15 15:56:50 bsmith Exp $*/
214b396bbSKris Buschelman 
314b396bbSKris Buschelman /*
414b396bbSKris Buschelman         Provides an interface to the SuperLU sparse solver
514b396bbSKris Buschelman           Modified for SuperLU 2.0 by Matthew Knepley
614b396bbSKris Buschelman */
714b396bbSKris Buschelman 
814b396bbSKris Buschelman #include "src/mat/impls/aij/seq/aij.h"
914b396bbSKris Buschelman 
1014b396bbSKris Buschelman EXTERN_C_BEGIN
1114b396bbSKris Buschelman #if defined(PETSC_USE_COMPLEX)
1214b396bbSKris Buschelman #include "zsp_defs.h"
1314b396bbSKris Buschelman #else
1414b396bbSKris Buschelman #include "dsp_defs.h"
1514b396bbSKris Buschelman #endif
1614b396bbSKris Buschelman #include "util.h"
1714b396bbSKris Buschelman EXTERN_C_END
1814b396bbSKris Buschelman 
1914b396bbSKris Buschelman typedef struct {
2014b396bbSKris Buschelman   SuperMatrix  A,B,AC,L,U;
2114b396bbSKris Buschelman   int          *perm_r,*perm_c,ispec,relax,panel_size;
2214b396bbSKris Buschelman   double       pivot_threshold;
2314b396bbSKris Buschelman   NCformat     *store;
2414b396bbSKris Buschelman   MatStructure flg;
2514b396bbSKris Buschelman   PetscTruth   SuperluMatOdering;
2614b396bbSKris Buschelman 
2714b396bbSKris Buschelman   /* A few function pointers for inheritance */
28f0c56d0fSKris Buschelman   int (*MatDuplicate)(Mat,MatDuplicateOption,Mat*);
2914b396bbSKris Buschelman   int (*MatView)(Mat,PetscViewer);
3014b396bbSKris Buschelman   int (*MatAssemblyEnd)(Mat,MatAssemblyType);
31b0592601SKris Buschelman   int (*MatLUFactorSymbolic)(Mat,IS,IS,MatFactorInfo*,Mat*);
3214b396bbSKris Buschelman   int (*MatDestroy)(Mat);
3314b396bbSKris Buschelman 
3414b396bbSKris Buschelman   /* Flag to clean up (non-global) SuperLU objects during Destroy */
3514b396bbSKris Buschelman   PetscTruth CleanUpSuperLU;
36f0c56d0fSKris Buschelman } Mat_SuperLU;
3714b396bbSKris Buschelman 
3814b396bbSKris Buschelman 
39f0c56d0fSKris Buschelman EXTERN int MatFactorInfo_SuperLU(Mat,PetscViewer);
40f0c56d0fSKris Buschelman EXTERN int MatLUFactorSymbolic_SuperLU(Mat,IS,IS,MatFactorInfo*,Mat*);
41b0592601SKris Buschelman 
42b0592601SKris Buschelman EXTERN_C_BEGIN
43b0592601SKris Buschelman EXTERN int MatConvert_SuperLU_SeqAIJ(Mat,MatType,Mat*);
44b0592601SKris Buschelman EXTERN int MatConvert_SeqAIJ_SuperLU(Mat,MatType,Mat*);
45b0592601SKris Buschelman EXTERN_C_END
4614b396bbSKris Buschelman 
4714b396bbSKris Buschelman #undef __FUNCT__
48f0c56d0fSKris Buschelman #define __FUNCT__ "MatDestroy_SuperLU"
49f0c56d0fSKris Buschelman int MatDestroy_SuperLU(Mat A)
5014b396bbSKris Buschelman {
51460c4903SKris Buschelman   int         ierr;
52f0c56d0fSKris Buschelman   Mat_SuperLU *lu = (Mat_SuperLU*)A->spptr;
5314b396bbSKris Buschelman 
5414b396bbSKris Buschelman   PetscFunctionBegin;
55fb3e25aaSKris Buschelman   if (lu->CleanUpSuperLU) {
56fb3e25aaSKris Buschelman     /* We have to free the global data or SuperLU crashes (sucky design)*/
57fb3e25aaSKris Buschelman     /* Since we don't know if more solves on other matrices may be done
58fb3e25aaSKris Buschelman        we cannot free the yucky SuperLU global data
59fb3e25aaSKris Buschelman        StatFree();
60fb3e25aaSKris Buschelman     */
61fb3e25aaSKris Buschelman 
62fb3e25aaSKris Buschelman     /* Free the SuperLU datastructures */
63fb3e25aaSKris Buschelman     Destroy_CompCol_Permuted(&lu->AC);
64fb3e25aaSKris Buschelman     Destroy_SuperNode_Matrix(&lu->L);
65fb3e25aaSKris Buschelman     Destroy_CompCol_Matrix(&lu->U);
66fb3e25aaSKris Buschelman     ierr = PetscFree(lu->B.Store);CHKERRQ(ierr);
67fb3e25aaSKris Buschelman     ierr = PetscFree(lu->A.Store);CHKERRQ(ierr);
68fb3e25aaSKris Buschelman     ierr = PetscFree(lu->perm_r);CHKERRQ(ierr);
69fb3e25aaSKris Buschelman     ierr = PetscFree(lu->perm_c);CHKERRQ(ierr);
70fb3e25aaSKris Buschelman   }
71b0592601SKris Buschelman   ierr = MatConvert_SuperLU_SeqAIJ(A,MATSEQAIJ,&A);CHKERRQ(ierr);
72fb3e25aaSKris Buschelman   ierr = (*A->ops->destroy)(A);CHKERRQ(ierr);
7314b396bbSKris Buschelman   PetscFunctionReturn(0);
7414b396bbSKris Buschelman }
7514b396bbSKris Buschelman 
7614b396bbSKris Buschelman #undef __FUNCT__
77f0c56d0fSKris Buschelman #define __FUNCT__ "MatView_SuperLU"
78f0c56d0fSKris Buschelman int MatView_SuperLU(Mat A,PetscViewer viewer)
7914b396bbSKris Buschelman {
8014b396bbSKris Buschelman   int               ierr;
8114b396bbSKris Buschelman   PetscTruth        isascii;
8214b396bbSKris Buschelman   PetscViewerFormat format;
83f0c56d0fSKris Buschelman   Mat_SuperLU       *lu=(Mat_SuperLU*)(A->spptr);
8414b396bbSKris Buschelman 
8514b396bbSKris Buschelman   PetscFunctionBegin;
8614b396bbSKris Buschelman   ierr = (*lu->MatView)(A,viewer);CHKERRQ(ierr);
8714b396bbSKris Buschelman 
8814b396bbSKris Buschelman   ierr = PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_ASCII,&isascii);CHKERRQ(ierr);
8914b396bbSKris Buschelman   if (isascii) {
9014b396bbSKris Buschelman     ierr = PetscViewerGetFormat(viewer,&format);CHKERRQ(ierr);
9114b396bbSKris Buschelman     if (format == PETSC_VIEWER_ASCII_FACTOR_INFO) {
92f0c56d0fSKris Buschelman       ierr = MatFactorInfo_SuperLU(A,viewer);CHKERRQ(ierr);
9314b396bbSKris Buschelman     }
9414b396bbSKris Buschelman   }
9514b396bbSKris Buschelman   PetscFunctionReturn(0);
9614b396bbSKris Buschelman }
9714b396bbSKris Buschelman 
9814b396bbSKris Buschelman #undef __FUNCT__
99f0c56d0fSKris Buschelman #define __FUNCT__ "MatAssemblyEnd_SuperLU"
100f0c56d0fSKris Buschelman int MatAssemblyEnd_SuperLU(Mat A,MatAssemblyType mode) {
10114b396bbSKris Buschelman   int         ierr;
102f0c56d0fSKris Buschelman   Mat_SuperLU *lu=(Mat_SuperLU*)(A->spptr);
10314b396bbSKris Buschelman 
10414b396bbSKris Buschelman   PetscFunctionBegin;
10514b396bbSKris Buschelman   ierr = (*lu->MatAssemblyEnd)(A,mode);CHKERRQ(ierr);
106b0592601SKris Buschelman 
107b0592601SKris Buschelman   lu->MatLUFactorSymbolic  = A->ops->lufactorsymbolic;
108f0c56d0fSKris Buschelman   A->ops->lufactorsymbolic = MatLUFactorSymbolic_SuperLU;
10914b396bbSKris Buschelman   PetscFunctionReturn(0);
11014b396bbSKris Buschelman }
11114b396bbSKris Buschelman 
11214b396bbSKris Buschelman #include "src/mat/impls/dense/seq/dense.h"
11314b396bbSKris Buschelman #undef __FUNCT__
114f0c56d0fSKris Buschelman #define __FUNCT__ "MatCreateNull_SuperLU"
115f0c56d0fSKris Buschelman int MatCreateNull_SuperLU(Mat A,Mat *nullMat)
11614b396bbSKris Buschelman {
117f0c56d0fSKris Buschelman   Mat_SuperLU   *lu = (Mat_SuperLU*)A->spptr;
11814b396bbSKris Buschelman   int           numRows = A->m,numCols = A->n;
11914b396bbSKris Buschelman   SCformat      *Lstore;
12014b396bbSKris Buschelman   int           numNullCols,size;
12114b396bbSKris Buschelman #if defined(PETSC_USE_COMPLEX)
12214b396bbSKris Buschelman   doublecomplex *nullVals,*workVals;
12314b396bbSKris Buschelman #else
12414b396bbSKris Buschelman   PetscScalar   *nullVals,*workVals;
12514b396bbSKris Buschelman #endif
12614b396bbSKris Buschelman   int           row,newRow,col,newCol,block,b,ierr;
12714b396bbSKris Buschelman 
12814b396bbSKris Buschelman   PetscFunctionBegin;
12914b396bbSKris Buschelman   PetscValidHeaderSpecific(A,MAT_COOKIE);
13014b396bbSKris Buschelman   PetscValidPointer(nullMat);
13114b396bbSKris Buschelman   if (!A->factor) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Unfactored matrix");
13214b396bbSKris Buschelman   numNullCols = numCols - numRows;
13314b396bbSKris Buschelman   if (numNullCols < 0) SETERRQ(PETSC_ERR_ARG_WRONG,"Function only applies to underdetermined problems");
13414b396bbSKris Buschelman   /* Create the null matrix */
13514b396bbSKris Buschelman   ierr = MatCreateSeqDense(A->comm,numRows,numNullCols,PETSC_NULL,nullMat);CHKERRQ(ierr);
13614b396bbSKris Buschelman   if (numNullCols == 0) {
13714b396bbSKris Buschelman     ierr = MatAssemblyBegin(*nullMat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
13814b396bbSKris Buschelman     ierr = MatAssemblyEnd(*nullMat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
13914b396bbSKris Buschelman     PetscFunctionReturn(0);
14014b396bbSKris Buschelman   }
14114b396bbSKris Buschelman #if defined(PETSC_USE_COMPLEX)
14214b396bbSKris Buschelman   nullVals = (doublecomplex*)((Mat_SeqDense*)(*nullMat)->data)->v;
14314b396bbSKris Buschelman #else
14414b396bbSKris Buschelman   nullVals = ((Mat_SeqDense*)(*nullMat)->data)->v;
14514b396bbSKris Buschelman #endif
14614b396bbSKris Buschelman   /* Copy in the columns */
14714b396bbSKris Buschelman   Lstore = (SCformat*)lu->L.Store;
14814b396bbSKris Buschelman   for(block = 0; block <= Lstore->nsuper; block++) {
14914b396bbSKris Buschelman     newRow = Lstore->sup_to_col[block];
15014b396bbSKris Buschelman     size   = Lstore->sup_to_col[block+1] - Lstore->sup_to_col[block];
15114b396bbSKris Buschelman     for(col = Lstore->rowind_colptr[newRow]; col < Lstore->rowind_colptr[newRow+1]; col++) {
15214b396bbSKris Buschelman       newCol = Lstore->rowind[col];
15314b396bbSKris Buschelman       if (newCol >= numRows) {
15414b396bbSKris Buschelman         for(b = 0; b < size; b++)
15514b396bbSKris Buschelman #if defined(PETSC_USE_COMPLEX)
15614b396bbSKris Buschelman           nullVals[(newCol-numRows)*numRows+newRow+b] = ((doublecomplex*)Lstore->nzval)[Lstore->nzval_colptr[newRow+b]+col];
15714b396bbSKris Buschelman #else
15814b396bbSKris Buschelman           nullVals[(newCol-numRows)*numRows+newRow+b] = ((double*)Lstore->nzval)[Lstore->nzval_colptr[newRow+b]+col];
15914b396bbSKris Buschelman #endif
16014b396bbSKris Buschelman       }
16114b396bbSKris Buschelman     }
16214b396bbSKris Buschelman   }
16314b396bbSKris Buschelman   /* Permute rhs to form P^T_c B */
16414b396bbSKris Buschelman   ierr = PetscMalloc(numRows*sizeof(double),&workVals);CHKERRQ(ierr);
16514b396bbSKris Buschelman   for(b = 0; b < numNullCols; b++) {
16614b396bbSKris Buschelman     for(row = 0; row < numRows; row++) workVals[lu->perm_c[row]] = nullVals[b*numRows+row];
16714b396bbSKris Buschelman     for(row = 0; row < numRows; row++) nullVals[b*numRows+row]   = workVals[row];
16814b396bbSKris Buschelman   }
16914b396bbSKris Buschelman   /* Backward solve the upper triangle A x = b */
17014b396bbSKris Buschelman   for(b = 0; b < numNullCols; b++) {
17114b396bbSKris Buschelman #if defined(PETSC_USE_COMPLEX)
17214b396bbSKris Buschelman     sp_ztrsv("L","T","U",&lu->L,&lu->U,&nullVals[b*numRows],&ierr);
17314b396bbSKris Buschelman #else
17414b396bbSKris Buschelman     sp_dtrsv("L","T","U",&lu->L,&lu->U,&nullVals[b*numRows],&ierr);
17514b396bbSKris Buschelman #endif
17614b396bbSKris Buschelman     if (ierr < 0)
17714b396bbSKris Buschelman       SETERRQ1(PETSC_ERR_ARG_WRONG,"The argument %d was invalid",-ierr);
17814b396bbSKris Buschelman   }
17914b396bbSKris Buschelman   ierr = PetscFree(workVals);CHKERRQ(ierr);
18014b396bbSKris Buschelman 
18114b396bbSKris Buschelman   ierr = MatAssemblyBegin(*nullMat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
18214b396bbSKris Buschelman   ierr = MatAssemblyEnd(*nullMat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
18314b396bbSKris Buschelman   PetscFunctionReturn(0);
18414b396bbSKris Buschelman }
18514b396bbSKris Buschelman 
18614b396bbSKris Buschelman #undef __FUNCT__
187f0c56d0fSKris Buschelman #define __FUNCT__ "MatSolve_SuperLU"
188f0c56d0fSKris Buschelman int MatSolve_SuperLU(Mat A,Vec b,Vec x)
18914b396bbSKris Buschelman {
190f0c56d0fSKris Buschelman   Mat_SuperLU *lu = (Mat_SuperLU*)A->spptr;
19114b396bbSKris Buschelman   PetscScalar *array;
19214b396bbSKris Buschelman   int         m,ierr;
19314b396bbSKris Buschelman 
19414b396bbSKris Buschelman   PetscFunctionBegin;
19514b396bbSKris Buschelman   ierr = VecGetLocalSize(b,&m);CHKERRQ(ierr);
19614b396bbSKris Buschelman   ierr = VecCopy(b,x);CHKERRQ(ierr);
19714b396bbSKris Buschelman   ierr = VecGetArray(x,&array);CHKERRQ(ierr);
19814b396bbSKris Buschelman   /* Create the Rhs */
19914b396bbSKris Buschelman   lu->B.Stype        = SLU_DN;
20014b396bbSKris Buschelman   lu->B.Mtype        = SLU_GE;
20114b396bbSKris Buschelman   lu->B.nrow         = m;
20214b396bbSKris Buschelman   lu->B.ncol         = 1;
20314b396bbSKris Buschelman   ((DNformat*)lu->B.Store)->lda   = m;
20414b396bbSKris Buschelman   ((DNformat*)lu->B.Store)->nzval = array;
20514b396bbSKris Buschelman #if defined(PETSC_USE_COMPLEX)
20614b396bbSKris Buschelman   lu->B.Dtype        = SLU_Z;
20714b396bbSKris Buschelman   zgstrs("T",&lu->L,&lu->U,lu->perm_r,lu->perm_c,&lu->B,&ierr);
20814b396bbSKris Buschelman #else
20914b396bbSKris Buschelman   lu->B.Dtype        = SLU_D;
21014b396bbSKris Buschelman   dgstrs("T",&lu->L,&lu->U,lu->perm_r,lu->perm_c,&lu->B,&ierr);
21114b396bbSKris Buschelman #endif
21214b396bbSKris Buschelman   if (ierr < 0) SETERRQ1(PETSC_ERR_ARG_WRONG,"The diagonal element of row %d was invalid",-ierr);
21314b396bbSKris Buschelman   ierr = VecRestoreArray(x,&array);CHKERRQ(ierr);
21414b396bbSKris Buschelman   PetscFunctionReturn(0);
21514b396bbSKris Buschelman }
21614b396bbSKris Buschelman 
21714b396bbSKris Buschelman static int StatInitCalled = 0;
21814b396bbSKris Buschelman 
21914b396bbSKris Buschelman #undef __FUNCT__
220f0c56d0fSKris Buschelman #define __FUNCT__ "MatLUFactorNumeric_SuperLU"
221f0c56d0fSKris Buschelman int MatLUFactorNumeric_SuperLU(Mat A,Mat *F)
22214b396bbSKris Buschelman {
22314b396bbSKris Buschelman   Mat_SeqAIJ  *aa = (Mat_SeqAIJ*)(A)->data;
224f0c56d0fSKris Buschelman   Mat_SuperLU *lu = (Mat_SuperLU*)(*F)->spptr;
225d54de34fSKris Buschelman   int         *etree,ierr;
22614b396bbSKris Buschelman   PetscTruth  flag;
22714b396bbSKris Buschelman 
22814b396bbSKris Buschelman   PetscFunctionBegin;
22914b396bbSKris Buschelman   /* Create the SuperMatrix for A^T:
23014b396bbSKris Buschelman        Since SuperLU only likes column-oriented matrices,we pass it the transpose,
23114b396bbSKris Buschelman        and then solve A^T X = B in MatSolve().
23214b396bbSKris Buschelman   */
23314b396bbSKris Buschelman 
23414b396bbSKris Buschelman   if ( lu->flg == DIFFERENT_NONZERO_PATTERN){ /* first numerical factorization */
23514b396bbSKris Buschelman     lu->A.Stype   = SLU_NC;
23614b396bbSKris Buschelman #if defined(PETSC_USE_COMPLEX)
23714b396bbSKris Buschelman     lu->A.Dtype   = SLU_Z;
23814b396bbSKris Buschelman #else
23914b396bbSKris Buschelman     lu->A.Dtype   = SLU_D;
24014b396bbSKris Buschelman #endif
24114b396bbSKris Buschelman     lu->A.Mtype   = SLU_GE;
24214b396bbSKris Buschelman     lu->A.nrow    = A->n;
24314b396bbSKris Buschelman     lu->A.ncol    = A->m;
24414b396bbSKris Buschelman 
24514b396bbSKris Buschelman     ierr = PetscMalloc(sizeof(NCformat),&lu->store);CHKERRQ(ierr);
24614b396bbSKris Buschelman     ierr = PetscMalloc(sizeof(DNformat),&lu->B.Store);CHKERRQ(ierr);
24714b396bbSKris Buschelman   }
24814b396bbSKris Buschelman   lu->store->nnz    = aa->nz;
24914b396bbSKris Buschelman   lu->store->colptr = aa->i;
25014b396bbSKris Buschelman   lu->store->rowind = aa->j;
25114b396bbSKris Buschelman   lu->store->nzval  = aa->a;
25214b396bbSKris Buschelman   lu->A.Store       = lu->store;
25314b396bbSKris Buschelman 
25414b396bbSKris Buschelman   /* Set SuperLU options */
25514b396bbSKris Buschelman   lu->relax      = sp_ienv(2);
25614b396bbSKris Buschelman   lu->panel_size = sp_ienv(1);
25714b396bbSKris Buschelman   /* We have to initialize global data or SuperLU crashes (sucky design) */
25814b396bbSKris Buschelman   if (!StatInitCalled) {
25914b396bbSKris Buschelman     StatInit(lu->panel_size,lu->relax);
26014b396bbSKris Buschelman   }
26114b396bbSKris Buschelman   StatInitCalled++;
26214b396bbSKris Buschelman 
26314b396bbSKris Buschelman   ierr = PetscOptionsBegin(A->comm,A->prefix,"SuperLU Options","Mat");CHKERRQ(ierr);
26414b396bbSKris Buschelman   /* use SuperLU mat ordeing */
26514b396bbSKris Buschelman   ierr = PetscOptionsInt("-mat_superlu_ordering","SuperLU ordering type (one of 0, 1, 2, 3)\n   0: natural ordering;\n   1: MMD applied to A'*A;\n   2: MMD applied to A'+A;\n   3: COLAMD, approximate minimum degree column ordering","None",lu->ispec,&lu->ispec,&flag);CHKERRQ(ierr);
26614b396bbSKris Buschelman   if (flag) {
26714b396bbSKris Buschelman     get_perm_c(lu->ispec, &lu->A, lu->perm_c);
26814b396bbSKris Buschelman     lu->SuperluMatOdering = PETSC_TRUE;
26914b396bbSKris Buschelman   }
27014b396bbSKris Buschelman   PetscOptionsEnd();
27114b396bbSKris Buschelman 
27214b396bbSKris Buschelman   /* Create the elimination tree */
27314b396bbSKris Buschelman   ierr = PetscMalloc(A->n*sizeof(int),&etree);CHKERRQ(ierr);
27414b396bbSKris Buschelman   sp_preorder("N",&lu->A,lu->perm_c,etree,&lu->AC);
27514b396bbSKris Buschelman   /* Factor the matrix */
27614b396bbSKris Buschelman #if defined(PETSC_USE_COMPLEX)
27714b396bbSKris Buschelman   zgstrf("N",&lu->AC,lu->pivot_threshold,0.0,lu->relax,lu->panel_size,etree,PETSC_NULL,0,lu->perm_r,lu->perm_c,&lu->L,&lu->U,&ierr);
27814b396bbSKris Buschelman #else
27914b396bbSKris Buschelman   dgstrf("N",&lu->AC,lu->pivot_threshold,0.0,lu->relax,lu->panel_size,etree,PETSC_NULL,0,lu->perm_r,lu->perm_c,&lu->L,&lu->U,&ierr);
28014b396bbSKris Buschelman #endif
28114b396bbSKris Buschelman   if (ierr < 0) {
28214b396bbSKris Buschelman     SETERRQ1(PETSC_ERR_ARG_WRONG,"The diagonal element of row %d was invalid",-ierr);
28314b396bbSKris Buschelman   } else if (ierr > 0) {
28414b396bbSKris Buschelman     if (ierr <= A->m) {
28514b396bbSKris Buschelman       SETERRQ1(PETSC_ERR_ARG_WRONG,"The diagonal element %d of U is exactly zero",ierr);
28614b396bbSKris Buschelman     } else {
28714b396bbSKris Buschelman       SETERRQ1(PETSC_ERR_ARG_WRONG,"Memory allocation failure after %d bytes were allocated",ierr-A->m);
28814b396bbSKris Buschelman     }
28914b396bbSKris Buschelman   }
29014b396bbSKris Buschelman 
29114b396bbSKris Buschelman   /* Cleanup */
29214b396bbSKris Buschelman   ierr = PetscFree(etree);CHKERRQ(ierr);
29314b396bbSKris Buschelman 
29414b396bbSKris Buschelman   lu->flg = SAME_NONZERO_PATTERN;
29514b396bbSKris Buschelman   PetscFunctionReturn(0);
29614b396bbSKris Buschelman }
29714b396bbSKris Buschelman 
29814b396bbSKris Buschelman /*
29914b396bbSKris Buschelman    Note the r permutation is ignored
30014b396bbSKris Buschelman */
30114b396bbSKris Buschelman #undef __FUNCT__
302f0c56d0fSKris Buschelman #define __FUNCT__ "MatLUFactorSymbolic_SuperLU"
303f0c56d0fSKris Buschelman int MatLUFactorSymbolic_SuperLU(Mat A,IS r,IS c,MatFactorInfo *info,Mat *F)
30414b396bbSKris Buschelman {
30514b396bbSKris Buschelman   Mat                 B;
306f0c56d0fSKris Buschelman   Mat_SuperLU  *lu;
30714b396bbSKris Buschelman   int                 ierr,*ca;
30814b396bbSKris Buschelman 
30914b396bbSKris Buschelman   PetscFunctionBegin;
31014b396bbSKris Buschelman 
311899d7b4fSKris Buschelman   ierr = MatCreate(A->comm,A->m,A->n,PETSC_DETERMINE,PETSC_DETERMINE,&B);CHKERRQ(ierr);
312899d7b4fSKris Buschelman   ierr = MatSetType(B,MATSUPERLU);CHKERRQ(ierr);
313899d7b4fSKris Buschelman   ierr = MatSeqAIJSetPreallocation(B,0,PETSC_NULL);CHKERRQ(ierr);
314f0c56d0fSKris Buschelman 
315f0c56d0fSKris Buschelman   B->ops->lufactornumeric = MatLUFactorNumeric_SuperLU;
316f0c56d0fSKris Buschelman   B->ops->solve           = MatSolve_SuperLU;
31714b396bbSKris Buschelman   B->factor               = FACTOR_LU;
318899d7b4fSKris Buschelman   B->assembled            = PETSC_TRUE;  /* required by -sles_view */
31914b396bbSKris Buschelman 
320f0c56d0fSKris Buschelman   lu = (Mat_SuperLU*)(B->spptr);
3212ecb5974SKris Buschelman   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatCreateNull","MatCreateNull_SuperLU",
322f0c56d0fSKris Buschelman                                     (void(*)(void))MatCreateNull_SuperLU);CHKERRQ(ierr);
32314b396bbSKris Buschelman 
32414b396bbSKris Buschelman   /* Allocate the work arrays required by SuperLU (notice sizes are for the transpose) */
32514b396bbSKris Buschelman   ierr = PetscMalloc(A->n*sizeof(int),&lu->perm_r);CHKERRQ(ierr);
32614b396bbSKris Buschelman   ierr = PetscMalloc(A->m*sizeof(int),&lu->perm_c);CHKERRQ(ierr);
32714b396bbSKris Buschelman 
32814b396bbSKris Buschelman   /* use PETSc mat ordering */
32914b396bbSKris Buschelman   ierr = ISGetIndices(c,&ca);CHKERRQ(ierr);
33014b396bbSKris Buschelman   ierr = PetscMemcpy(lu->perm_c,ca,A->m*sizeof(int));CHKERRQ(ierr);
33114b396bbSKris Buschelman   ierr = ISRestoreIndices(c,&ca);CHKERRQ(ierr);
33214b396bbSKris Buschelman   lu->SuperluMatOdering = PETSC_FALSE;
33314b396bbSKris Buschelman 
33414b396bbSKris Buschelman   lu->pivot_threshold = info->dtcol;
335f0c56d0fSKris Buschelman   PetscLogObjectMemory(B,(A->m+A->n)*sizeof(int)+sizeof(Mat_SuperLU));
33614b396bbSKris Buschelman 
33714b396bbSKris Buschelman   lu->flg            = DIFFERENT_NONZERO_PATTERN;
338e740cb95SKris Buschelman   lu->CleanUpSuperLU = PETSC_TRUE;
339899d7b4fSKris Buschelman 
340899d7b4fSKris Buschelman   *F = B;
34114b396bbSKris Buschelman   PetscFunctionReturn(0);
34214b396bbSKris Buschelman }
34314b396bbSKris Buschelman 
34414b396bbSKris Buschelman /* used by -sles_view */
34514b396bbSKris Buschelman #undef __FUNCT__
346f0c56d0fSKris Buschelman #define __FUNCT__ "MatFactorInfo_SuperLU"
347f0c56d0fSKris Buschelman int MatFactorInfo_SuperLU(Mat A,PetscViewer viewer)
34814b396bbSKris Buschelman {
349f0c56d0fSKris Buschelman   Mat_SuperLU *lu= (Mat_SuperLU*)A->spptr;
350f0c56d0fSKris Buschelman   int         ierr;
351f0c56d0fSKris Buschelman 
352f0c56d0fSKris Buschelman   PetscFunctionBegin;
353f0c56d0fSKris Buschelman   ierr = PetscViewerASCIIPrintf(viewer,"SuperLU run parameters:\n");CHKERRQ(ierr);
354f0c56d0fSKris Buschelman   if(lu->SuperluMatOdering) {
355f0c56d0fSKris Buschelman     ierr = PetscViewerASCIIPrintf(viewer,"  SuperLU mat ordering: %d\n",lu->ispec);CHKERRQ(ierr);
356f0c56d0fSKris Buschelman   }
357f0c56d0fSKris Buschelman   PetscFunctionReturn(0);
358f0c56d0fSKris Buschelman }
359f0c56d0fSKris Buschelman 
360f0c56d0fSKris Buschelman #undef __FUNCT__
361f0c56d0fSKris Buschelman #define __FUNCT__ "MatDuplicate_SuperLU"
362f0c56d0fSKris Buschelman int MatDuplicate_SuperLU(Mat A, MatDuplicateOption op, Mat *M) {
36314b396bbSKris Buschelman   int ierr;
36414b396bbSKris Buschelman   PetscFunctionBegin;
365f0c56d0fSKris Buschelman   ierr = (*A->ops->duplicate)(A,op,M);CHKERRQ(ierr);
366f0c56d0fSKris Buschelman   ierr = MatConvert_SeqAIJ_SuperLU(*M,MATSUPERLU,M);CHKERRQ(ierr);
36714b396bbSKris Buschelman   PetscFunctionReturn(0);
36814b396bbSKris Buschelman }
36914b396bbSKris Buschelman 
37014b396bbSKris Buschelman EXTERN_C_BEGIN
37114b396bbSKris Buschelman #undef __FUNCT__
372b0592601SKris Buschelman #define __FUNCT__ "MatConvert_SuperLU_SeqAIJ"
373b0592601SKris Buschelman int MatConvert_SuperLU_SeqAIJ(Mat A,MatType type,Mat *newmat) {
374fb3e25aaSKris Buschelman   /* This routine is only called to convert an unfactored PETSc-SuperLU matrix */
375fb3e25aaSKris Buschelman   /* to its base PETSc type, so we will ignore 'MatType type'. */
37614b396bbSKris Buschelman   int                  ierr;
377b0592601SKris Buschelman   Mat                  B=*newmat;
378f0c56d0fSKris Buschelman   Mat_SuperLU   *lu=(Mat_SuperLU *)A->spptr;
379b0592601SKris Buschelman 
380b0592601SKris Buschelman   PetscFunctionBegin;
381b0592601SKris Buschelman   if (B != A) {
382b0592601SKris Buschelman     ierr = MatDuplicate(A,MAT_COPY_VALUES,&B);CHKERRQ(ierr);
383f0c56d0fSKris Buschelman   }
384b0592601SKris Buschelman   /* Reset the original function pointers */
385f0c56d0fSKris Buschelman   B->ops->duplicate        = lu->MatDuplicate;
386b0592601SKris Buschelman   B->ops->view             = lu->MatView;
387b0592601SKris Buschelman   B->ops->assemblyend      = lu->MatAssemblyEnd;
388b0592601SKris Buschelman   B->ops->lufactorsymbolic = lu->MatLUFactorSymbolic;
389b0592601SKris Buschelman   B->ops->destroy          = lu->MatDestroy;
390b0592601SKris Buschelman   /* lu is only a function pointer stash unless we've factored the matrix, which we haven't! */
391b0592601SKris Buschelman   ierr = PetscFree(lu);CHKERRQ(ierr);
392b0592601SKris Buschelman   ierr = PetscObjectChangeTypeName((PetscObject)B,MATSEQAIJ);CHKERRQ(ierr);
393b0592601SKris Buschelman   *newmat = B;
394b0592601SKris Buschelman   PetscFunctionReturn(0);
395b0592601SKris Buschelman }
396b0592601SKris Buschelman EXTERN_C_END
397b0592601SKris Buschelman 
398b0592601SKris Buschelman EXTERN_C_BEGIN
399b0592601SKris Buschelman #undef __FUNCT__
400b0592601SKris Buschelman #define __FUNCT__ "MatConvert_SeqAIJ_SuperLU"
401b0592601SKris Buschelman int MatConvert_SeqAIJ_SuperLU(Mat A,MatType type,Mat *newmat) {
402fb3e25aaSKris Buschelman   /* This routine is only called to convert to MATSUPERLU */
403fb3e25aaSKris Buschelman   /* from MATSEQAIJ, so we will ignore 'MatType type'. */
404b0592601SKris Buschelman   int         ierr;
405b0592601SKris Buschelman   Mat         B=*newmat;
406f0c56d0fSKris Buschelman   Mat_SuperLU *lu;
40714b396bbSKris Buschelman 
40814b396bbSKris Buschelman   PetscFunctionBegin;
409b0592601SKris Buschelman   if (B != A) {
410b0592601SKris Buschelman     ierr = MatDuplicate(A,MAT_COPY_VALUES,&B);CHKERRQ(ierr);
411b0592601SKris Buschelman   }
41214b396bbSKris Buschelman 
413f0c56d0fSKris Buschelman   ierr = PetscNew(Mat_SuperLU,&lu);CHKERRQ(ierr);
414f0c56d0fSKris Buschelman   lu->MatDuplicate         = A->ops->duplicate;
41514b396bbSKris Buschelman   lu->MatView              = A->ops->view;
41614b396bbSKris Buschelman   lu->MatAssemblyEnd       = A->ops->assemblyend;
417b0592601SKris Buschelman   lu->MatLUFactorSymbolic  = A->ops->lufactorsymbolic;
41814b396bbSKris Buschelman   lu->MatDestroy           = A->ops->destroy;
41914b396bbSKris Buschelman   lu->CleanUpSuperLU       = PETSC_FALSE;
420b0592601SKris Buschelman 
421b0592601SKris Buschelman   B->spptr                 = (void*)lu;
422f0c56d0fSKris Buschelman   B->ops->duplicate        = MatDuplicate_SuperLU;
423f0c56d0fSKris Buschelman   B->ops->view             = MatView_SuperLU;
424f0c56d0fSKris Buschelman   B->ops->assemblyend      = MatAssemblyEnd_SuperLU;
425f0c56d0fSKris Buschelman   B->ops->lufactorsymbolic = MatLUFactorSymbolic_SuperLU;
426f0c56d0fSKris Buschelman   B->ops->destroy          = MatDestroy_SuperLU;
427b0592601SKris Buschelman 
428b0592601SKris Buschelman   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatConvert_seqaij_superlu_C",
429b0592601SKris Buschelman                                            "MatConvert_SeqAIJ_SuperLU",MatConvert_SeqAIJ_SuperLU);CHKERRQ(ierr);
430b0592601SKris Buschelman   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatConvert_superlu_seqaij_C",
431b0592601SKris Buschelman                                            "MatConvert_SuperLU_SeqAIJ",MatConvert_SuperLU_SeqAIJ);CHKERRQ(ierr);
432fb3e25aaSKris Buschelman   PetscLogInfo(0,"Using SuperLU for SeqAIJ LU factorization and solves.");
433fb3e25aaSKris Buschelman   ierr = PetscObjectChangeTypeName((PetscObject)B,MATSUPERLU);CHKERRQ(ierr);
434b0592601SKris Buschelman   *newmat = B;
435b0592601SKris Buschelman   PetscFunctionReturn(0);
436b0592601SKris Buschelman }
437b0592601SKris Buschelman EXTERN_C_END
438b0592601SKris Buschelman 
43924b6179bSKris Buschelman /*MC
44024b6179bSKris Buschelman   MATSUPERLU - a matrix type providing direct solvers (LU) for sequential matrices
44124b6179bSKris Buschelman   via the external package SuperLU.
44224b6179bSKris Buschelman 
44324b6179bSKris Buschelman   If SuperLU is installed (see the manual for
44424b6179bSKris Buschelman   instructions on how to declare the existence of external packages),
44524b6179bSKris Buschelman   a matrix type can be constructed which invokes SuperLU solvers.
44624b6179bSKris Buschelman   After calling MatCreate(...,A), simply call MatSetType(A,MATSUPERLU).
44724b6179bSKris Buschelman   This matrix type is only supported for double precision real.
44824b6179bSKris Buschelman 
44924b6179bSKris Buschelman   This matrix inherits from MATSEQAIJ.  As a result, MatSeqAIJSetPreallocation is
45024b6179bSKris Buschelman   supported for this matrix type.
45124b6179bSKris Buschelman 
45224b6179bSKris Buschelman   Options Database Keys:
4532f71e704SKris Buschelman + -mat_type superlu - sets the matrix type to superlu during a call to MatSetFromOptions()
45424b6179bSKris Buschelman - -mat_superlu_ordering <0,1,2,3> - 0: natural ordering,
45524b6179bSKris Buschelman                                     1: MMD applied to A'*A,
45624b6179bSKris Buschelman                                     2: MMD applied to A'+A,
45724b6179bSKris Buschelman                                     3: COLAMD, approximate minimum degree column ordering
45824b6179bSKris Buschelman 
45924b6179bSKris Buschelman    Level: beginner
46024b6179bSKris Buschelman 
46124b6179bSKris Buschelman .seealso: PCLU
46224b6179bSKris Buschelman M*/
46324b6179bSKris Buschelman 
464b0592601SKris Buschelman EXTERN_C_BEGIN
465b0592601SKris Buschelman #undef __FUNCT__
466f0c56d0fSKris Buschelman #define __FUNCT__ "MatCreate_SuperLU"
467f0c56d0fSKris Buschelman int MatCreate_SuperLU(Mat A) {
468b0592601SKris Buschelman   int ierr;
469b0592601SKris Buschelman 
470b0592601SKris Buschelman   PetscFunctionBegin;
471*5441df8eSKris Buschelman   /* Change type name before calling MatSetType to force proper construction of SeqAIJ and SUPERLU types */
472*5441df8eSKris Buschelman   ierr = PetscObjectChangeTypeName((PetscObject)A,MATSUPERLU);CHKERRQ(ierr);
473b0592601SKris Buschelman   ierr = MatSetType(A,MATSEQAIJ);CHKERRQ(ierr);
474b0592601SKris Buschelman   ierr = MatConvert_SeqAIJ_SuperLU(A,MATSUPERLU,&A);CHKERRQ(ierr);
47514b396bbSKris Buschelman   PetscFunctionReturn(0);
47614b396bbSKris Buschelman }
47714b396bbSKris Buschelman EXTERN_C_END
478