17d6ea485SPieter Ghysels #include <../src/mat/impls/aij/seq/aij.h> 27d6ea485SPieter Ghysels #include <../src/mat/impls/aij/mpi/mpiaij.h> 37d6ea485SPieter Ghysels #include <StrumpackSparseSolver.h> 47d6ea485SPieter Ghysels 57d6ea485SPieter Ghysels /* 67d6ea485SPieter Ghysels These are only relevant for MATMPIAIJ, not for MATSEQAIJ. 77d6ea485SPieter Ghysels REPLICATED - STRUMPACK expects the entire sparse matrix and right-hand side on every process. 87d6ea485SPieter Ghysels DISTRIBUTED - STRUMPACK expects the sparse matrix and right-hand side to be distributed across the entire MPI communicator. 97d6ea485SPieter Ghysels */ 107d6ea485SPieter Ghysels typedef enum {REPLICATED, DISTRIBUTED} STRUMPACK_MatInputMode; 117d6ea485SPieter Ghysels const char *STRUMPACK_MatInputModes[] = {"REPLICATED","DISTRIBUTED","STRUMPACK_MatInputMode","PETSC_",0}; 127d6ea485SPieter Ghysels 137d6ea485SPieter Ghysels typedef struct { 147d6ea485SPieter Ghysels STRUMPACK_SparseSolver S; 157d6ea485SPieter Ghysels STRUMPACK_MatInputMode MatInputMode; 167d6ea485SPieter Ghysels } STRUMPACK_data; 177d6ea485SPieter Ghysels 187d6ea485SPieter Ghysels 197d6ea485SPieter Ghysels #undef __FUNCT__ 207d6ea485SPieter Ghysels #define __FUNCT__ "MatGetDiagonal_STRUMPACK" 21ad0c5e61SPieter Ghysels static PetscErrorCode MatGetDiagonal_STRUMPACK(Mat A,Vec v) 227d6ea485SPieter Ghysels { 237d6ea485SPieter Ghysels PetscFunctionBegin; 247d6ea485SPieter Ghysels SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"Mat type: STRUMPACK factor"); 257d6ea485SPieter Ghysels PetscFunctionReturn(0); 267d6ea485SPieter Ghysels } 277d6ea485SPieter Ghysels 287d6ea485SPieter Ghysels #undef __FUNCT__ 297d6ea485SPieter Ghysels #define __FUNCT__ "MatDestroy_STRUMPACK" 30ad0c5e61SPieter Ghysels static PetscErrorCode MatDestroy_STRUMPACK(Mat A) 317d6ea485SPieter Ghysels { 327d6ea485SPieter Ghysels STRUMPACK_data *sp = (STRUMPACK_data*)A->spptr; 337d6ea485SPieter Ghysels PetscErrorCode ierr; 347d6ea485SPieter Ghysels PetscBool flg; 357d6ea485SPieter Ghysels 367d6ea485SPieter Ghysels PetscFunctionBegin; 377d6ea485SPieter Ghysels /* Deallocate STRUMPACK storage */ 387d6ea485SPieter Ghysels PetscStackCall("STRUMPACK_destroy",STRUMPACK_destroy(&(sp->S))); 397d6ea485SPieter Ghysels ierr = PetscFree(A->spptr);CHKERRQ(ierr); 407d6ea485SPieter Ghysels ierr = PetscObjectTypeCompare((PetscObject)A,MATSEQAIJ,&flg);CHKERRQ(ierr); 417d6ea485SPieter Ghysels if (flg) { 427d6ea485SPieter Ghysels ierr = MatDestroy_SeqAIJ(A);CHKERRQ(ierr); 437d6ea485SPieter Ghysels } else { 447d6ea485SPieter Ghysels ierr = MatDestroy_MPIAIJ(A);CHKERRQ(ierr); 457d6ea485SPieter Ghysels } 46575704cbSPieter Ghysels 47575704cbSPieter Ghysels /* clear composed functions */ 48575704cbSPieter Ghysels ierr = PetscObjectComposeFunction((PetscObject)A,"MatFactorGetSolverPackage_C",NULL);CHKERRQ(ierr); 49575704cbSPieter Ghysels ierr = PetscObjectComposeFunction((PetscObject)A,"MatSTRUMPACKSetHSSRelCompTol_C",NULL);CHKERRQ(ierr); 50575704cbSPieter Ghysels ierr = PetscObjectComposeFunction((PetscObject)A,"MatSTRUMPACKSetHSSMinSize_C",NULL);CHKERRQ(ierr); 51575704cbSPieter Ghysels ierr = PetscObjectComposeFunction((PetscObject)A,"MatSTRUMPACKSetColPerm_C",NULL);CHKERRQ(ierr); 52575704cbSPieter Ghysels 53575704cbSPieter Ghysels PetscFunctionReturn(0); 54575704cbSPieter Ghysels } 55575704cbSPieter Ghysels 56575704cbSPieter Ghysels #undef __FUNCT__ 57575704cbSPieter Ghysels #define __FUNCT__ "MatSTRUMPACKSetHSSRelCompTol_STRUMPACK" 58575704cbSPieter Ghysels static PetscErrorCode MatSTRUMPACKSetHSSRelCompTol_STRUMPACK(Mat F,PetscReal rctol) 59575704cbSPieter Ghysels { 60575704cbSPieter Ghysels STRUMPACK_data *sp = (STRUMPACK_data*)F->spptr; 61575704cbSPieter Ghysels 62575704cbSPieter Ghysels PetscFunctionBegin; 63575704cbSPieter Ghysels PetscStackCall("STRUMPACK_set_rctol", STRUMPACK_set_rctol(sp->S,rctol)); 64575704cbSPieter Ghysels PetscFunctionReturn(0); 65575704cbSPieter Ghysels } 66575704cbSPieter Ghysels 67575704cbSPieter Ghysels #undef __FUNCT__ 68575704cbSPieter Ghysels #define __FUNCT__ "MatSTRUMPACKSetHSSRelCompTol" 69575704cbSPieter Ghysels /*@ 70575704cbSPieter Ghysels MatSTRUMPACKSetHSSRelCompTol - Set STRUMPACK relative tolerance for HSS compression 71575704cbSPieter Ghysels Logically Collective on Mat 72575704cbSPieter Ghysels 73575704cbSPieter Ghysels Input Parameters: 74575704cbSPieter Ghysels + F - the factored matrix obtained by calling MatGetFactor() from PETSc-STRUMPACK interface 75575704cbSPieter Ghysels - rctol - relative compression tolerance 76575704cbSPieter Ghysels 77575704cbSPieter Ghysels Options Database: 78575704cbSPieter Ghysels . -mat_strumpack_rctol <rctol> 79575704cbSPieter Ghysels 80575704cbSPieter Ghysels Level: beginner 81575704cbSPieter Ghysels 82575704cbSPieter Ghysels References: 83575704cbSPieter Ghysels . STRUMPACK manual 84575704cbSPieter Ghysels 85575704cbSPieter Ghysels .seealso: MatGetFactor() 86575704cbSPieter Ghysels @*/ 87575704cbSPieter Ghysels PetscErrorCode MatSTRUMPACKSetHSSRelCompTol(Mat F,PetscReal rctol) 88575704cbSPieter Ghysels { 89575704cbSPieter Ghysels PetscErrorCode ierr; 90575704cbSPieter Ghysels 91575704cbSPieter Ghysels PetscFunctionBegin; 92575704cbSPieter Ghysels PetscValidHeaderSpecific(F,MAT_CLASSID,1); 93575704cbSPieter Ghysels PetscValidLogicalCollectiveReal(F,rctol,2); 94575704cbSPieter Ghysels ierr = PetscTryMethod(F,"MatSTRUMPACKSetHSSRelCompTol_C",(Mat,PetscReal),(F,rctol));CHKERRQ(ierr); 95575704cbSPieter Ghysels PetscFunctionReturn(0); 96575704cbSPieter Ghysels } 97575704cbSPieter Ghysels 98575704cbSPieter Ghysels #undef __FUNCT__ 99575704cbSPieter Ghysels #define __FUNCT__ "MatSTRUMPACKSetHSSMinSize_STRUMPACK" 100575704cbSPieter Ghysels static PetscErrorCode MatSTRUMPACKSetHSSMinSize_STRUMPACK(Mat F,PetscInt hssminsize) 101575704cbSPieter Ghysels { 102575704cbSPieter Ghysels STRUMPACK_data *sp = (STRUMPACK_data*)F->spptr; 103575704cbSPieter Ghysels 104575704cbSPieter Ghysels PetscFunctionBegin; 105575704cbSPieter Ghysels PetscStackCall("STRUMPACK_set_minimum_HSS_size", STRUMPACK_set_minimum_HSS_size(sp->S,hssminsize)); 106575704cbSPieter Ghysels PetscFunctionReturn(0); 107575704cbSPieter Ghysels } 108575704cbSPieter Ghysels 109575704cbSPieter Ghysels #undef __FUNCT__ 110575704cbSPieter Ghysels #define __FUNCT__ "MatSTRUMPACKSetHSSMinSize" 111575704cbSPieter Ghysels /*@ 112575704cbSPieter Ghysels MatSTRUMPACKSetHSSMinSize - Set STRUMPACK minimum dense matrix size for low-rank approximation 113575704cbSPieter Ghysels Logically Collective on Mat 114575704cbSPieter Ghysels 115575704cbSPieter Ghysels Input Parameters: 116575704cbSPieter Ghysels + F - the factored matrix obtained by calling MatGetFactor() from PETSc-STRUMPACK interface 117575704cbSPieter Ghysels - hssminsize - minimum dense matrix size for low-rank approximation 118575704cbSPieter Ghysels 119575704cbSPieter Ghysels Options Database: 120575704cbSPieter Ghysels . -mat_strumpack_hssminsize <hssminsize> 121575704cbSPieter Ghysels 122575704cbSPieter Ghysels Level: beginner 123575704cbSPieter Ghysels 124575704cbSPieter Ghysels References: 125575704cbSPieter Ghysels . STRUMPACK manual 126575704cbSPieter Ghysels 127575704cbSPieter Ghysels .seealso: MatGetFactor() 128575704cbSPieter Ghysels @*/ 129575704cbSPieter Ghysels PetscErrorCode MatSTRUMPACKSetHSSMinSize(Mat F,PetscInt hssminsize) 130575704cbSPieter Ghysels { 131575704cbSPieter Ghysels PetscErrorCode ierr; 132575704cbSPieter Ghysels 133575704cbSPieter Ghysels PetscFunctionBegin; 134575704cbSPieter Ghysels PetscValidHeaderSpecific(F,MAT_CLASSID,1); 135575704cbSPieter Ghysels PetscValidLogicalCollectiveInt(F,hssminsize,2); 136575704cbSPieter Ghysels ierr = PetscTryMethod(F,"MatSTRUMPACKSetHSSMinSize_C",(Mat,PetscInt),(F,hssminsize));CHKERRQ(ierr); 137575704cbSPieter Ghysels PetscFunctionReturn(0); 138575704cbSPieter Ghysels } 139575704cbSPieter Ghysels 140575704cbSPieter Ghysels #undef __FUNCT__ 141575704cbSPieter Ghysels #define __FUNCT__ "MatSTRUMPACKSetColPerm_STRUMPACK" 142575704cbSPieter Ghysels static PetscErrorCode MatSTRUMPACKSetColPerm_STRUMPACK(Mat F,PetscBool cperm) 143575704cbSPieter Ghysels { 144575704cbSPieter Ghysels STRUMPACK_data *sp = (STRUMPACK_data*)F->spptr; 145575704cbSPieter Ghysels 146575704cbSPieter Ghysels PetscFunctionBegin; 147575704cbSPieter Ghysels PetscStackCall("STRUMPACK_set_mc64job",STRUMPACK_set_mc64job(sp->S,cperm ? 5 : 0)); 148575704cbSPieter Ghysels PetscFunctionReturn(0); 149575704cbSPieter Ghysels } 150575704cbSPieter Ghysels 151575704cbSPieter Ghysels #undef __FUNCT__ 152575704cbSPieter Ghysels #define __FUNCT__ "MatSTRUMPACKSetColPerm" 153575704cbSPieter Ghysels /*@ 154575704cbSPieter Ghysels MatSTRUMPACKSetColPerm - Set whether STRUMPACK should try to permute the columns of the matrix in order to get a nonzero diagonal 155575704cbSPieter Ghysels Logically Collective on Mat 156575704cbSPieter Ghysels 157575704cbSPieter Ghysels Input Parameters: 158575704cbSPieter Ghysels + F - the factored matrix obtained by calling MatGetFactor() from PETSc-STRUMPACK interface 159575704cbSPieter Ghysels - cperm - whether or not to permute (internally) the columns of the matrix 160575704cbSPieter Ghysels 161575704cbSPieter Ghysels Options Database: 162575704cbSPieter Ghysels . -mat_strumpack_colperm <cperm> 163575704cbSPieter Ghysels 164575704cbSPieter Ghysels Level: beginner 165575704cbSPieter Ghysels 166575704cbSPieter Ghysels References: 167575704cbSPieter Ghysels . STRUMPACK manual 168575704cbSPieter Ghysels 169575704cbSPieter Ghysels .seealso: MatGetFactor() 170575704cbSPieter Ghysels @*/ 171575704cbSPieter Ghysels PetscErrorCode MatSTRUMPACKSetColPerm(Mat F,PetscBool cperm) 172575704cbSPieter Ghysels { 173575704cbSPieter Ghysels PetscErrorCode ierr; 174575704cbSPieter Ghysels 175575704cbSPieter Ghysels PetscFunctionBegin; 176575704cbSPieter Ghysels PetscValidHeaderSpecific(F,MAT_CLASSID,1); 177575704cbSPieter Ghysels PetscValidLogicalCollectiveBool(F,cperm,2); 178575704cbSPieter Ghysels ierr = PetscTryMethod(F,"MatSTRUMPACKSetColPerm_C",(Mat,PetscBool),(F,cperm));CHKERRQ(ierr); 1797d6ea485SPieter Ghysels PetscFunctionReturn(0); 1807d6ea485SPieter Ghysels } 1817d6ea485SPieter Ghysels 1827d6ea485SPieter Ghysels #undef __FUNCT__ 1837d6ea485SPieter Ghysels #define __FUNCT__ "MatSolve_STRUMPACK" 184ad0c5e61SPieter Ghysels static PetscErrorCode MatSolve_STRUMPACK(Mat A,Vec b_mpi,Vec x) 1857d6ea485SPieter Ghysels { 1867d6ea485SPieter Ghysels STRUMPACK_data *sp = (STRUMPACK_data*)A->spptr; 1877d6ea485SPieter Ghysels STRUMPACK_RETURN_CODE sp_err; 1887d6ea485SPieter Ghysels PetscErrorCode ierr; 1897d6ea485SPieter Ghysels PetscMPIInt size; 1907d6ea485SPieter Ghysels PetscInt N=A->cmap->N; 1917d6ea485SPieter Ghysels const PetscScalar *bptr; 1927d6ea485SPieter Ghysels PetscScalar *xptr; 1937d6ea485SPieter Ghysels Vec x_seq,b_seq; 1947d6ea485SPieter Ghysels IS iden; 1957d6ea485SPieter Ghysels VecScatter scat; 1967d6ea485SPieter Ghysels 1977d6ea485SPieter Ghysels PetscFunctionBegin; 1987d6ea485SPieter Ghysels ierr = MPI_Comm_size(PetscObjectComm((PetscObject)A),&size);CHKERRQ(ierr); 1997d6ea485SPieter Ghysels if (size > 1 && sp->MatInputMode == REPLICATED) { 2007d6ea485SPieter Ghysels ierr = VecCreateSeq(PETSC_COMM_SELF,N,&x_seq);CHKERRQ(ierr); 2017d6ea485SPieter Ghysels ierr = VecGetArray(x_seq,&xptr);CHKERRQ(ierr); 20224a4cbefSPieter Ghysels /* replicated mat input, convert b to b_seq */ 2037d6ea485SPieter Ghysels ierr = VecCreateSeq(PETSC_COMM_SELF,N,&b_seq);CHKERRQ(ierr); 2047d6ea485SPieter Ghysels ierr = ISCreateStride(PETSC_COMM_SELF,N,0,1,&iden);CHKERRQ(ierr); 2057d6ea485SPieter Ghysels ierr = VecScatterCreate(b_mpi,iden,b_seq,iden,&scat);CHKERRQ(ierr); 2067d6ea485SPieter Ghysels ierr = ISDestroy(&iden);CHKERRQ(ierr); 2077d6ea485SPieter Ghysels ierr = VecScatterBegin(scat,b_mpi,b_seq,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 2087d6ea485SPieter Ghysels ierr = VecScatterEnd(scat,b_mpi,b_seq,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 2097d6ea485SPieter Ghysels ierr = VecGetArrayRead(b_seq,&bptr);CHKERRQ(ierr); 2107d6ea485SPieter Ghysels } else { /* size==1 || distributed mat input */ 2117d6ea485SPieter Ghysels ierr = VecGetArray(x,&xptr);CHKERRQ(ierr); 2127d6ea485SPieter Ghysels ierr = VecGetArrayRead(b_mpi,&bptr);CHKERRQ(ierr); 2137d6ea485SPieter Ghysels } 2147d6ea485SPieter Ghysels 2157d6ea485SPieter Ghysels PetscStackCall("STRUMPACK_solve",sp_err = STRUMPACK_solve(sp->S,(PetscScalar*)bptr,xptr,0)); 2167d6ea485SPieter Ghysels 2177d6ea485SPieter Ghysels if (sp_err != STRUMPACK_SUCCESS) { 2187d6ea485SPieter Ghysels if (sp_err == STRUMPACK_MATRIX_NOT_SET) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"STRUMPACK error: matrix was not set"); 2197d6ea485SPieter Ghysels else if (sp_err == STRUMPACK_REORDERING_ERROR) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"STRUMPACK error: matrix reordering failed"); 2207d6ea485SPieter Ghysels else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"STRUMPACK error: solve failed"); 2217d6ea485SPieter Ghysels } 2227d6ea485SPieter Ghysels 2237d6ea485SPieter Ghysels if (size > 1 && sp->MatInputMode == REPLICATED) { 2247d6ea485SPieter Ghysels ierr = VecRestoreArrayRead(b_seq,&bptr);CHKERRQ(ierr); 2257d6ea485SPieter Ghysels ierr = VecDestroy(&b_seq);CHKERRQ(ierr); 2267d6ea485SPieter Ghysels /* convert seq x to mpi x */ 2277d6ea485SPieter Ghysels ierr = VecRestoreArray(x_seq,&xptr);CHKERRQ(ierr); 2287d6ea485SPieter Ghysels ierr = VecScatterBegin(scat,x_seq,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 2297d6ea485SPieter Ghysels ierr = VecScatterEnd(scat,x_seq,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 2307d6ea485SPieter Ghysels ierr = VecScatterDestroy(&scat);CHKERRQ(ierr); 2317d6ea485SPieter Ghysels ierr = VecDestroy(&x_seq);CHKERRQ(ierr); 2327d6ea485SPieter Ghysels } else { 2337d6ea485SPieter Ghysels ierr = VecRestoreArray(x,&xptr);CHKERRQ(ierr); 2347d6ea485SPieter Ghysels ierr = VecRestoreArrayRead(b_mpi,&bptr);CHKERRQ(ierr); 2357d6ea485SPieter Ghysels } 2367d6ea485SPieter Ghysels 2377d6ea485SPieter Ghysels PetscFunctionReturn(0); 2387d6ea485SPieter Ghysels } 2397d6ea485SPieter Ghysels 2407d6ea485SPieter Ghysels #undef __FUNCT__ 2417d6ea485SPieter Ghysels #define __FUNCT__ "MatMatSolve_STRUMPACK" 242ad0c5e61SPieter Ghysels static PetscErrorCode MatMatSolve_STRUMPACK(Mat A,Mat B_mpi,Mat X) 2437d6ea485SPieter Ghysels { 2447d6ea485SPieter Ghysels PetscErrorCode ierr; 2457d6ea485SPieter Ghysels PetscBool flg; 2467d6ea485SPieter Ghysels 2477d6ea485SPieter Ghysels PetscFunctionBegin; 2487d6ea485SPieter Ghysels ierr = PetscObjectTypeCompareAny((PetscObject)B_mpi,&flg,MATSEQDENSE,MATMPIDENSE,NULL);CHKERRQ(ierr); 2497d6ea485SPieter Ghysels if (!flg) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONG,"Matrix B must be MATDENSE matrix"); 2507d6ea485SPieter Ghysels ierr = PetscObjectTypeCompareAny((PetscObject)X,&flg,MATSEQDENSE,MATMPIDENSE,NULL);CHKERRQ(ierr); 2517d6ea485SPieter Ghysels if (!flg) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONG,"Matrix X must be MATDENSE matrix"); 2527d6ea485SPieter Ghysels SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"MatMatSolve_STRUMPACK() is not implemented yet"); 2537d6ea485SPieter Ghysels PetscFunctionReturn(0); 2547d6ea485SPieter Ghysels } 2557d6ea485SPieter Ghysels 256ad0c5e61SPieter Ghysels #undef __FUNCT__ 257ad0c5e61SPieter Ghysels #define __FUNCT__ "MatFactorInfo_STRUMPACK" 258ad0c5e61SPieter Ghysels static PetscErrorCode MatFactorInfo_STRUMPACK(Mat A,PetscViewer viewer) 259ad0c5e61SPieter Ghysels { 260ad0c5e61SPieter Ghysels PetscErrorCode ierr; 261ad0c5e61SPieter Ghysels 262ad0c5e61SPieter Ghysels PetscFunctionBegin; 263ad0c5e61SPieter Ghysels /* check if matrix is strumpack type */ 264ad0c5e61SPieter Ghysels if (A->ops->solve != MatSolve_STRUMPACK) PetscFunctionReturn(0); 265ad0c5e61SPieter Ghysels ierr = PetscViewerASCIIPrintf(viewer,"STRUMPACK sparse solver!\n");CHKERRQ(ierr); 266ad0c5e61SPieter Ghysels PetscFunctionReturn(0); 267ad0c5e61SPieter Ghysels } 268ad0c5e61SPieter Ghysels 269ad0c5e61SPieter Ghysels #undef __FUNCT__ 270ad0c5e61SPieter Ghysels #define __FUNCT__ "MatView_STRUMPACK" 271ad0c5e61SPieter Ghysels static PetscErrorCode MatView_STRUMPACK(Mat A,PetscViewer viewer) 272ad0c5e61SPieter Ghysels { 273ad0c5e61SPieter Ghysels PetscErrorCode ierr; 274ad0c5e61SPieter Ghysels PetscBool iascii; 275ad0c5e61SPieter Ghysels PetscViewerFormat format; 276ad0c5e61SPieter Ghysels 277ad0c5e61SPieter Ghysels PetscFunctionBegin; 278ad0c5e61SPieter Ghysels ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr); 279ad0c5e61SPieter Ghysels if (iascii) { 280ad0c5e61SPieter Ghysels ierr = PetscViewerGetFormat(viewer,&format);CHKERRQ(ierr); 281ad0c5e61SPieter Ghysels if (format == PETSC_VIEWER_ASCII_INFO) { 282ad0c5e61SPieter Ghysels ierr = MatFactorInfo_STRUMPACK(A,viewer);CHKERRQ(ierr); 283ad0c5e61SPieter Ghysels } 284ad0c5e61SPieter Ghysels } 285ad0c5e61SPieter Ghysels PetscFunctionReturn(0); 286ad0c5e61SPieter Ghysels } 2877d6ea485SPieter Ghysels 2887d6ea485SPieter Ghysels #undef __FUNCT__ 2897d6ea485SPieter Ghysels #define __FUNCT__ "MatLUFactorNumeric_STRUMPACK" 290ad0c5e61SPieter Ghysels static PetscErrorCode MatLUFactorNumeric_STRUMPACK(Mat F,Mat A,const MatFactorInfo *info) 2917d6ea485SPieter Ghysels { 2927d6ea485SPieter Ghysels STRUMPACK_data *sp = (STRUMPACK_data*)F->spptr; 2937d6ea485SPieter Ghysels STRUMPACK_RETURN_CODE sp_err; 2947d6ea485SPieter Ghysels Mat *tseq,A_seq = NULL; 2957d6ea485SPieter Ghysels Mat_SeqAIJ *A_d,*A_o; 2967d6ea485SPieter Ghysels Mat_MPIAIJ *mat; 2977d6ea485SPieter Ghysels PetscErrorCode ierr; 2987d6ea485SPieter Ghysels PetscInt M=A->rmap->N,m=A->rmap->n,N=A->cmap->N; 2997d6ea485SPieter Ghysels PetscMPIInt size; 3007d6ea485SPieter Ghysels IS isrow; 3017d6ea485SPieter Ghysels PetscBool flg; 3027d6ea485SPieter Ghysels 3037d6ea485SPieter Ghysels PetscFunctionBegin; 3047d6ea485SPieter Ghysels ierr = MPI_Comm_size(PetscObjectComm((PetscObject)A),&size);CHKERRQ(ierr); 3057d6ea485SPieter Ghysels 3067d6ea485SPieter Ghysels ierr = PetscObjectTypeCompare((PetscObject)A,MATMPIAIJ,&flg);CHKERRQ(ierr); 3077d6ea485SPieter Ghysels if (flg) { /* A is MATMPIAIJ */ 3087d6ea485SPieter Ghysels if (sp->MatInputMode == REPLICATED) { 3097d6ea485SPieter Ghysels if (size > 1) { /* convert mpi A to seq mat A */ 3107d6ea485SPieter Ghysels ierr = ISCreateStride(PETSC_COMM_SELF,M,0,1,&isrow);CHKERRQ(ierr); 3117d6ea485SPieter Ghysels ierr = MatGetSubMatrices(A,1,&isrow,&isrow,MAT_INITIAL_MATRIX,&tseq);CHKERRQ(ierr); 3127d6ea485SPieter Ghysels ierr = ISDestroy(&isrow);CHKERRQ(ierr); 3137d6ea485SPieter Ghysels A_seq = *tseq; 3147d6ea485SPieter Ghysels ierr = PetscFree(tseq);CHKERRQ(ierr); 3157d6ea485SPieter Ghysels A_d = (Mat_SeqAIJ*)A_seq->data; 3167d6ea485SPieter Ghysels } else { /* size == 1 */ 3177d6ea485SPieter Ghysels mat = (Mat_MPIAIJ*)A->data; 3187d6ea485SPieter Ghysels A_d = (Mat_SeqAIJ*)(mat->A)->data; 3197d6ea485SPieter Ghysels } 3207d6ea485SPieter Ghysels PetscStackCall("STRUMPACK_set_csr_matrix",STRUMPACK_set_csr_matrix(sp->S,&N,A_d->i,A_d->j,A_d->a,0)); 3217d6ea485SPieter Ghysels } else { /* sp->MatInputMode == DISTRIBUTED */ 3227d6ea485SPieter Ghysels mat = (Mat_MPIAIJ*)A->data; 3237d6ea485SPieter Ghysels A_d = (Mat_SeqAIJ*)(mat->A)->data; 3247d6ea485SPieter Ghysels A_o = (Mat_SeqAIJ*)(mat->B)->data; 3257d6ea485SPieter Ghysels PetscStackCall("STRUMPACK_set_MPIAIJ_matrix",STRUMPACK_set_MPIAIJ_matrix(sp->S,&m,A_d->i,A_d->j,A_d->a,A_o->i,A_o->j,A_o->a,mat->garray)); 3267d6ea485SPieter Ghysels } 3277d6ea485SPieter Ghysels } else { /* A is MATSEQAIJ */ 3287d6ea485SPieter Ghysels A_d = (Mat_SeqAIJ*)A->data; 3297d6ea485SPieter Ghysels PetscStackCall("STRUMPACK_set_csr_matrix",STRUMPACK_set_csr_matrix(sp->S,&N,A_d->i,A_d->j,A_d->a,0)); 3307d6ea485SPieter Ghysels } 3317d6ea485SPieter Ghysels 3327d6ea485SPieter Ghysels /* Reorder and Factor the matrix. */ 3337d6ea485SPieter Ghysels /* TODO figure out how to avoid reorder if the matrix values changed, but the pattern remains the same. */ 3347d6ea485SPieter Ghysels PetscStackCall("STRUMPACK_reorder",sp_err = STRUMPACK_reorder(sp->S)); 3357d6ea485SPieter Ghysels PetscStackCall("STRUMPACK_factor",sp_err = STRUMPACK_factor(sp->S)); 3367d6ea485SPieter Ghysels if (sp_err != STRUMPACK_SUCCESS) { 3377d6ea485SPieter Ghysels if (sp_err == STRUMPACK_MATRIX_NOT_SET) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"STRUMPACK error: matrix was not set"); 3387d6ea485SPieter Ghysels else if (sp_err == STRUMPACK_REORDERING_ERROR) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"STRUMPACK error: matrix reordering failed"); 3397d6ea485SPieter Ghysels else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"STRUMPACK error: factorization failed"); 3407d6ea485SPieter Ghysels } 3417d6ea485SPieter Ghysels if (flg && sp->MatInputMode == REPLICATED && size > 1) { 3427d6ea485SPieter Ghysels ierr = MatDestroy(&A_seq);CHKERRQ(ierr); 3437d6ea485SPieter Ghysels } 3447d6ea485SPieter Ghysels PetscFunctionReturn(0); 3457d6ea485SPieter Ghysels } 3467d6ea485SPieter Ghysels 3477d6ea485SPieter Ghysels #undef __FUNCT__ 3487d6ea485SPieter Ghysels #define __FUNCT__ "MatLUFactorSymbolic_STRUMPACK" 349ad0c5e61SPieter Ghysels static PetscErrorCode MatLUFactorSymbolic_STRUMPACK(Mat F,Mat A,IS r,IS c,const MatFactorInfo *info) 3507d6ea485SPieter Ghysels { 3517d6ea485SPieter Ghysels PetscFunctionBegin; 3527d6ea485SPieter Ghysels F->ops->lufactornumeric = MatLUFactorNumeric_STRUMPACK; 3537d6ea485SPieter Ghysels F->ops->solve = MatSolve_STRUMPACK; 3547d6ea485SPieter Ghysels F->ops->matsolve = MatMatSolve_STRUMPACK; 3557d6ea485SPieter Ghysels PetscFunctionReturn(0); 3567d6ea485SPieter Ghysels } 3577d6ea485SPieter Ghysels 3587d6ea485SPieter Ghysels #undef __FUNCT__ 3597d6ea485SPieter Ghysels #define __FUNCT__ "MatFactorGetSolverPackage_aij_strumpack" 360ad0c5e61SPieter Ghysels static PetscErrorCode MatFactorGetSolverPackage_aij_strumpack(Mat A,const MatSolverPackage *type) 3617d6ea485SPieter Ghysels { 3627d6ea485SPieter Ghysels PetscFunctionBegin; 3637d6ea485SPieter Ghysels *type = MATSOLVERSTRUMPACK; 3647d6ea485SPieter Ghysels PetscFunctionReturn(0); 3657d6ea485SPieter Ghysels } 3667d6ea485SPieter Ghysels 367575704cbSPieter Ghysels /*MC 368575704cbSPieter Ghysels MATSOLVERSSTRUMPACK = "strumpack" - A solver package providing a direct sparse solver (PCLU) 369575704cbSPieter Ghysels and a preconditioner (PCILU) using low-rank compression via the external package STRUMPACK. 370575704cbSPieter Ghysels 371575704cbSPieter Ghysels Consult the STRUMPACK-sparse manual for more info. 372575704cbSPieter Ghysels 373575704cbSPieter Ghysels Use 374575704cbSPieter Ghysels ./configure --download-strumpack 375575704cbSPieter Ghysels to have PETSc installed with STRUMPACK 376575704cbSPieter Ghysels 377575704cbSPieter Ghysels Use 378575704cbSPieter Ghysels -pc_type lu -pc_factor_mat_solver_package strumpack 379575704cbSPieter Ghysels to use this as an exact (direct) solver, use 380575704cbSPieter Ghysels -pc_type ilu -pc_factor_mat_solver_package strumpack 381575704cbSPieter Ghysels to enable low-rank compression (i.e, use as a preconditioner). 382575704cbSPieter Ghysels 383575704cbSPieter Ghysels Works with AIJ matrices 384575704cbSPieter Ghysels 385575704cbSPieter Ghysels Options Database Keys: 386575704cbSPieter Ghysels + -mat_strumpack_rctol <1e-4> - Relative compression tolerance (None) 387575704cbSPieter Ghysels . -mat_strumpack_hssminsize <512> - Minimum size of dense block for HSS compression (None) 388575704cbSPieter Ghysels . -mat_strumpack_colperm <TRUE> - Permute matrix to make diagonal nonzeros (None) 389575704cbSPieter Ghysels 390575704cbSPieter Ghysels Level: beginner 391575704cbSPieter Ghysels 392575704cbSPieter Ghysels .seealso: PCLU, PCILU, MATSOLVERSUPERLU_DIST, MATSOLVERMUMPS, PCFactorSetMatSolverPackage(), MatSolverPackage 393575704cbSPieter Ghysels M*/ 3947d6ea485SPieter Ghysels #undef __FUNCT__ 3957d6ea485SPieter Ghysels #define __FUNCT__ "MatGetFactor_aij_strumpack" 396ad0c5e61SPieter Ghysels static PetscErrorCode MatGetFactor_aij_strumpack(Mat A,MatFactorType ftype,Mat *F) 3977d6ea485SPieter Ghysels { 3987d6ea485SPieter Ghysels Mat B; 3997d6ea485SPieter Ghysels STRUMPACK_data *sp; 4007d6ea485SPieter Ghysels PetscErrorCode ierr; 4017d6ea485SPieter Ghysels PetscInt M=A->rmap->N,N=A->cmap->N; 4027d6ea485SPieter Ghysels PetscMPIInt size; 4037d6ea485SPieter Ghysels STRUMPACK_INTERFACE iface; 404575704cbSPieter Ghysels PetscBool verb,flg,set; 405575704cbSPieter Ghysels PetscReal rctol; 406575704cbSPieter Ghysels PetscInt hssminsize; 4077d6ea485SPieter Ghysels int argc; 40855c022e5SPieter Ghysels char **args,*copts,*pname; 40955c022e5SPieter Ghysels size_t len; 4107d6ea485SPieter Ghysels const STRUMPACK_PRECISION table[2][2][2] = {{{STRUMPACK_FLOATCOMPLEX_64,STRUMPACK_DOUBLECOMPLEX_64}, 4117d6ea485SPieter Ghysels {STRUMPACK_FLOAT_64,STRUMPACK_DOUBLE_64}}, 4127d6ea485SPieter Ghysels {{STRUMPACK_FLOATCOMPLEX,STRUMPACK_DOUBLECOMPLEX}, 4137d6ea485SPieter Ghysels {STRUMPACK_FLOAT,STRUMPACK_DOUBLE}}}; 4147d6ea485SPieter Ghysels const STRUMPACK_PRECISION prec = table[(sizeof(PetscInt)==8)?0:1][(PETSC_SCALAR==PETSC_COMPLEX)?0:1][(PETSC_REAL==PETSC_FLOAT)?0:1]; 4157d6ea485SPieter Ghysels 4167d6ea485SPieter Ghysels PetscFunctionBegin; 4177d6ea485SPieter Ghysels ierr = MPI_Comm_size(PetscObjectComm((PetscObject)A),&size);CHKERRQ(ierr); 4187d6ea485SPieter Ghysels /* Create the factorization matrix */ 4197d6ea485SPieter Ghysels ierr = MatCreate(PetscObjectComm((PetscObject)A),&B);CHKERRQ(ierr); 4207d6ea485SPieter Ghysels ierr = MatSetSizes(B,A->rmap->n,A->cmap->n,M,N);CHKERRQ(ierr); 4217d6ea485SPieter Ghysels ierr = MatSetType(B,((PetscObject)A)->type_name);CHKERRQ(ierr); 4227d6ea485SPieter Ghysels ierr = MatSeqAIJSetPreallocation(B,0,NULL); 4237d6ea485SPieter Ghysels ierr = MatMPIAIJSetPreallocation(B,0,NULL,0,NULL);CHKERRQ(ierr); 424575704cbSPieter Ghysels if (ftype == MAT_FACTOR_LU || ftype == MAT_FACTOR_ILU) { 4257d6ea485SPieter Ghysels B->ops->lufactorsymbolic = MatLUFactorSymbolic_STRUMPACK; 426575704cbSPieter Ghysels B->ops->ilufactorsymbolic = MatLUFactorSymbolic_STRUMPACK; 427575704cbSPieter Ghysels } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Factor type not supported"); 4287d6ea485SPieter Ghysels B->ops->view = MatView_STRUMPACK; 4297d6ea485SPieter Ghysels B->ops->destroy = MatDestroy_STRUMPACK; 4307d6ea485SPieter Ghysels B->ops->getdiagonal = MatGetDiagonal_STRUMPACK; 4317d6ea485SPieter Ghysels ierr = PetscObjectComposeFunction((PetscObject)B,"MatFactorGetSolverPackage_C",MatFactorGetSolverPackage_aij_strumpack);CHKERRQ(ierr); 432575704cbSPieter Ghysels ierr = PetscObjectComposeFunction((PetscObject)B,"MatSTRUMPACKSetHSSRelCompTol_C",MatSTRUMPACKSetHSSRelCompTol_STRUMPACK);CHKERRQ(ierr); 433575704cbSPieter Ghysels ierr = PetscObjectComposeFunction((PetscObject)B,"MatSTRUMPACKSetHSSMinSize_C",MatSTRUMPACKSetHSSMinSize_STRUMPACK);CHKERRQ(ierr); 434575704cbSPieter Ghysels ierr = PetscObjectComposeFunction((PetscObject)B,"MatSTRUMPACKSetColPerm_C",MatSTRUMPACKSetColPerm_STRUMPACK);CHKERRQ(ierr); 435575704cbSPieter Ghysels B->factortype = ftype; 4367d6ea485SPieter Ghysels ierr = PetscNewLog(B,&sp);CHKERRQ(ierr); 4377d6ea485SPieter Ghysels B->spptr = sp; 4387d6ea485SPieter Ghysels 4397d6ea485SPieter Ghysels ierr = PetscOptionsBegin(PetscObjectComm((PetscObject)A),((PetscObject)A)->prefix,"STRUMPACK Options","Mat");CHKERRQ(ierr); 4407d6ea485SPieter Ghysels sp->MatInputMode = DISTRIBUTED; 44124a4cbefSPieter Ghysels ierr = PetscOptionsEnum("-mat_strumpack_matinput","Matrix input mode (replicated or distributed)","None",STRUMPACK_MatInputModes, 4427d6ea485SPieter Ghysels (PetscEnum)sp->MatInputMode,(PetscEnum*)&sp->MatInputMode,NULL);CHKERRQ(ierr); 4437d6ea485SPieter Ghysels if (sp->MatInputMode == DISTRIBUTED && size == 1) sp->MatInputMode = REPLICATED; 44487e1f858SPieter Ghysels switch (sp->MatInputMode) { 44587e1f858SPieter Ghysels case REPLICATED: 44687e1f858SPieter Ghysels iface = STRUMPACK_MPI; 44787e1f858SPieter Ghysels break; 44887e1f858SPieter Ghysels case DISTRIBUTED: 44987e1f858SPieter Ghysels default: 45087e1f858SPieter Ghysels iface = STRUMPACK_MPI_DIST; 45187e1f858SPieter Ghysels } 4527d6ea485SPieter Ghysels ierr = PetscObjectTypeCompare((PetscObject)A,MATSEQAIJ,&flg); 4537d6ea485SPieter Ghysels if (flg) iface = STRUMPACK_MT; 4547d6ea485SPieter Ghysels 455575704cbSPieter Ghysels verb = PetscLogPrintInfo ? PETSC_TRUE : PETSC_FALSE; 4567d6ea485SPieter Ghysels ierr = PetscOptionsBool("-mat_strumpack_verbose","Print STRUMPACK information","None",verb,&verb,NULL);CHKERRQ(ierr); 4577d6ea485SPieter Ghysels 45855c022e5SPieter Ghysels ierr = PetscOptionsGetAll(NULL,&copts);CHKERRQ(ierr); 45955c022e5SPieter Ghysels ierr = PetscStrlen(copts,&len);CHKERRQ(ierr); 46055c022e5SPieter Ghysels len += PETSC_MAX_PATH_LEN+1; 46155c022e5SPieter Ghysels ierr = PetscMalloc1(len,&pname);CHKERRQ(ierr); 46255c022e5SPieter Ghysels /* first string is assumed to be the program name, so add program name to options string */ 46355c022e5SPieter Ghysels ierr = PetscGetProgramName(pname,len);CHKERRQ(ierr); 46455c022e5SPieter Ghysels ierr = PetscStrcat(pname," ");CHKERRQ(ierr); 46555c022e5SPieter Ghysels ierr = PetscStrcat(pname,copts);CHKERRQ(ierr); 466ee5a0f3aSPieter Ghysels ierr = PetscStrToArray(pname,' ',&argc,&args);CHKERRQ(ierr); 46755c022e5SPieter Ghysels ierr = PetscFree(copts);CHKERRQ(ierr); 46855c022e5SPieter Ghysels ierr = PetscFree(pname);CHKERRQ(ierr); 46955c022e5SPieter Ghysels 4707d6ea485SPieter Ghysels PetscStackCall("STRUMPACK_init",STRUMPACK_init(&(sp->S),PetscObjectComm((PetscObject)A),prec,iface,argc,args,verb)); 4717d6ea485SPieter Ghysels 472575704cbSPieter Ghysels PetscStackCall("STRUMPACK_get_rctol",rctol = (PetscReal)STRUMPACK_get_rctol(sp->S)); 473575704cbSPieter Ghysels ierr = PetscOptionsReal("-mat_strumpack_rctol","Relative compression tolerance","None",rctol,&rctol,&set);CHKERRQ(ierr); 474575704cbSPieter Ghysels if (set) PetscStackCall("STRUMPACK_set_rctol",STRUMPACK_set_rctol(sp->S,(double)rctol)); 475575704cbSPieter Ghysels 476575704cbSPieter Ghysels PetscStackCall("STRUMPACK_get_mc64job",flg = (STRUMPACK_get_mc64job(sp->S) == 0) ? PETSC_FALSE : PETSC_TRUE); 477575704cbSPieter Ghysels ierr = PetscOptionsBool("-mat_strumpack_colperm","Find a col perm to get nonzero diagonal","None",flg,&flg,&set);CHKERRQ(ierr); 478575704cbSPieter Ghysels if (set) PetscStackCall("STRUMPACK_set_mc64job",STRUMPACK_set_mc64job(sp->S,flg ? 5 : 0)); 479575704cbSPieter Ghysels 480575704cbSPieter Ghysels PetscStackCall("STRUMPACK_get_minimum_HSS_size",hssminsize = (PetscInt)STRUMPACK_get_minimum_HSS_size(sp->S)); 481575704cbSPieter Ghysels ierr = PetscOptionsInt("-mat_strumpack_hssminsize","Minimum size of dense block for HSS compression","None",hssminsize,&hssminsize,&set);CHKERRQ(ierr); 482575704cbSPieter Ghysels if (set) PetscStackCall("STRUMPACK_set_minimum_HSS_size",STRUMPACK_set_minimum_HSS_size(sp->S,(int)hssminsize)); 483575704cbSPieter Ghysels 484575704cbSPieter Ghysels PetscOptionsEnd(); 485575704cbSPieter Ghysels 486*88382b05SPieter Ghysels if (ftype == MAT_FACTOR_ILU) { 487*88382b05SPieter Ghysels /* When enabling HSS compression, the STRUMPACK solver becomes an incomplete */ 488*88382b05SPieter Ghysels /* (or approximate) LU factorization. */ 489*88382b05SPieter Ghysels PetscStackCall("STRUMPACK_use_HSS",STRUMPACK_use_HSS(sp->S,1)); 490575704cbSPieter Ghysels /* Disable the outer iterative solver from STRUMPACK. */ 491575704cbSPieter Ghysels /* When STRUMPACK is used as a direct solver, it will by default do iterative refinement. */ 492575704cbSPieter Ghysels /* When STRUMPACK is used with as an approximate factorization preconditioner (by enabling */ 493*88382b05SPieter Ghysels /* low-rank compression), it will use it's own GMRES. Here we can disable the */ 494575704cbSPieter Ghysels /* outer iterative solver, as PETSc uses STRUMPACK from within a KSP. */ 495575704cbSPieter Ghysels PetscStackCall("STRUMPACK_set_Krylov_solver", STRUMPACK_set_Krylov_solver(sp->S, STRUMPACK_DIRECT)); 496*88382b05SPieter Ghysels } 497575704cbSPieter Ghysels 498575704cbSPieter Ghysels /* Allow the user to set or overwrite the above options from the command line */ 499575704cbSPieter Ghysels PetscStackCall("STRUMPACK_set_from_options",STRUMPACK_set_from_options(sp->S)); 50055c022e5SPieter Ghysels ierr = PetscStrToArrayDestroy(argc,args);CHKERRQ(ierr); 50155c022e5SPieter Ghysels 5027d6ea485SPieter Ghysels *F = B; 5037d6ea485SPieter Ghysels PetscFunctionReturn(0); 5047d6ea485SPieter Ghysels } 5057d6ea485SPieter Ghysels 5067d6ea485SPieter Ghysels #undef __FUNCT__ 5077d6ea485SPieter Ghysels #define __FUNCT__ "MatSolverPackageRegister_STRUMPACK" 5087d6ea485SPieter Ghysels PETSC_EXTERN PetscErrorCode MatSolverPackageRegister_STRUMPACK(void) 5097d6ea485SPieter Ghysels { 5107d6ea485SPieter Ghysels PetscErrorCode ierr; 5117d6ea485SPieter Ghysels 5127d6ea485SPieter Ghysels PetscFunctionBegin; 5137d6ea485SPieter Ghysels ierr = MatSolverPackageRegister(MATSOLVERSTRUMPACK,MATMPIAIJ,MAT_FACTOR_LU,MatGetFactor_aij_strumpack);CHKERRQ(ierr); 5147d6ea485SPieter Ghysels ierr = MatSolverPackageRegister(MATSOLVERSTRUMPACK,MATSEQAIJ,MAT_FACTOR_LU,MatGetFactor_aij_strumpack);CHKERRQ(ierr); 515575704cbSPieter Ghysels ierr = MatSolverPackageRegister(MATSOLVERSTRUMPACK,MATMPIAIJ,MAT_FACTOR_ILU,MatGetFactor_aij_strumpack);CHKERRQ(ierr); 516575704cbSPieter Ghysels ierr = MatSolverPackageRegister(MATSOLVERSTRUMPACK,MATSEQAIJ,MAT_FACTOR_ILU,MatGetFactor_aij_strumpack);CHKERRQ(ierr); 5177d6ea485SPieter Ghysels PetscFunctionReturn(0); 5187d6ea485SPieter Ghysels } 519