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