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 } 46*575704cbSPieter Ghysels 47*575704cbSPieter Ghysels /* clear composed functions */ 48*575704cbSPieter Ghysels ierr = PetscObjectComposeFunction((PetscObject)A,"MatFactorGetSolverPackage_C",NULL);CHKERRQ(ierr); 49*575704cbSPieter Ghysels ierr = PetscObjectComposeFunction((PetscObject)A,"MatSTRUMPACKSetHSSRelCompTol_C",NULL);CHKERRQ(ierr); 50*575704cbSPieter Ghysels ierr = PetscObjectComposeFunction((PetscObject)A,"MatSTRUMPACKSetHSSMinSize_C",NULL);CHKERRQ(ierr); 51*575704cbSPieter Ghysels ierr = PetscObjectComposeFunction((PetscObject)A,"MatSTRUMPACKSetColPerm_C",NULL);CHKERRQ(ierr); 52*575704cbSPieter Ghysels 53*575704cbSPieter Ghysels PetscFunctionReturn(0); 54*575704cbSPieter Ghysels } 55*575704cbSPieter Ghysels 56*575704cbSPieter Ghysels #undef __FUNCT__ 57*575704cbSPieter Ghysels #define __FUNCT__ "MatSTRUMPACKSetHSSRelCompTol_STRUMPACK" 58*575704cbSPieter Ghysels static PetscErrorCode MatSTRUMPACKSetHSSRelCompTol_STRUMPACK(Mat F,PetscReal rctol) 59*575704cbSPieter Ghysels { 60*575704cbSPieter Ghysels STRUMPACK_data *sp = (STRUMPACK_data*)F->spptr; 61*575704cbSPieter Ghysels 62*575704cbSPieter Ghysels PetscFunctionBegin; 63*575704cbSPieter Ghysels PetscStackCall("STRUMPACK_set_rctol", STRUMPACK_set_rctol(sp->S,rctol)); 64*575704cbSPieter Ghysels PetscFunctionReturn(0); 65*575704cbSPieter Ghysels } 66*575704cbSPieter Ghysels 67*575704cbSPieter Ghysels #undef __FUNCT__ 68*575704cbSPieter Ghysels #define __FUNCT__ "MatSTRUMPACKSetHSSRelCompTol" 69*575704cbSPieter Ghysels /*@ 70*575704cbSPieter Ghysels MatSTRUMPACKSetHSSRelCompTol - Set STRUMPACK relative tolerance for HSS compression 71*575704cbSPieter Ghysels Logically Collective on Mat 72*575704cbSPieter Ghysels 73*575704cbSPieter Ghysels Input Parameters: 74*575704cbSPieter Ghysels + F - the factored matrix obtained by calling MatGetFactor() from PETSc-STRUMPACK interface 75*575704cbSPieter Ghysels - rctol - relative compression tolerance 76*575704cbSPieter Ghysels 77*575704cbSPieter Ghysels Options Database: 78*575704cbSPieter Ghysels . -mat_strumpack_rctol <rctol> 79*575704cbSPieter Ghysels 80*575704cbSPieter Ghysels Level: beginner 81*575704cbSPieter Ghysels 82*575704cbSPieter Ghysels References: 83*575704cbSPieter Ghysels . STRUMPACK manual 84*575704cbSPieter Ghysels 85*575704cbSPieter Ghysels .seealso: MatGetFactor() 86*575704cbSPieter Ghysels @*/ 87*575704cbSPieter Ghysels PetscErrorCode MatSTRUMPACKSetHSSRelCompTol(Mat F,PetscReal rctol) 88*575704cbSPieter Ghysels { 89*575704cbSPieter Ghysels PetscErrorCode ierr; 90*575704cbSPieter Ghysels 91*575704cbSPieter Ghysels PetscFunctionBegin; 92*575704cbSPieter Ghysels PetscValidHeaderSpecific(F,MAT_CLASSID,1); 93*575704cbSPieter Ghysels PetscValidLogicalCollectiveReal(F,rctol,2); 94*575704cbSPieter Ghysels ierr = PetscTryMethod(F,"MatSTRUMPACKSetHSSRelCompTol_C",(Mat,PetscReal),(F,rctol));CHKERRQ(ierr); 95*575704cbSPieter Ghysels PetscFunctionReturn(0); 96*575704cbSPieter Ghysels } 97*575704cbSPieter Ghysels 98*575704cbSPieter Ghysels #undef __FUNCT__ 99*575704cbSPieter Ghysels #define __FUNCT__ "MatSTRUMPACKSetHSSMinSize_STRUMPACK" 100*575704cbSPieter Ghysels static PetscErrorCode MatSTRUMPACKSetHSSMinSize_STRUMPACK(Mat F,PetscInt hssminsize) 101*575704cbSPieter Ghysels { 102*575704cbSPieter Ghysels STRUMPACK_data *sp = (STRUMPACK_data*)F->spptr; 103*575704cbSPieter Ghysels 104*575704cbSPieter Ghysels PetscFunctionBegin; 105*575704cbSPieter Ghysels PetscStackCall("STRUMPACK_set_minimum_HSS_size", STRUMPACK_set_minimum_HSS_size(sp->S,hssminsize)); 106*575704cbSPieter Ghysels PetscFunctionReturn(0); 107*575704cbSPieter Ghysels } 108*575704cbSPieter Ghysels 109*575704cbSPieter Ghysels #undef __FUNCT__ 110*575704cbSPieter Ghysels #define __FUNCT__ "MatSTRUMPACKSetHSSMinSize" 111*575704cbSPieter Ghysels /*@ 112*575704cbSPieter Ghysels MatSTRUMPACKSetHSSMinSize - Set STRUMPACK minimum dense matrix size for low-rank approximation 113*575704cbSPieter Ghysels Logically Collective on Mat 114*575704cbSPieter Ghysels 115*575704cbSPieter Ghysels Input Parameters: 116*575704cbSPieter Ghysels + F - the factored matrix obtained by calling MatGetFactor() from PETSc-STRUMPACK interface 117*575704cbSPieter Ghysels - hssminsize - minimum dense matrix size for low-rank approximation 118*575704cbSPieter Ghysels 119*575704cbSPieter Ghysels Options Database: 120*575704cbSPieter Ghysels . -mat_strumpack_hssminsize <hssminsize> 121*575704cbSPieter Ghysels 122*575704cbSPieter Ghysels Level: beginner 123*575704cbSPieter Ghysels 124*575704cbSPieter Ghysels References: 125*575704cbSPieter Ghysels . STRUMPACK manual 126*575704cbSPieter Ghysels 127*575704cbSPieter Ghysels .seealso: MatGetFactor() 128*575704cbSPieter Ghysels @*/ 129*575704cbSPieter Ghysels PetscErrorCode MatSTRUMPACKSetHSSMinSize(Mat F,PetscInt hssminsize) 130*575704cbSPieter Ghysels { 131*575704cbSPieter Ghysels PetscErrorCode ierr; 132*575704cbSPieter Ghysels 133*575704cbSPieter Ghysels PetscFunctionBegin; 134*575704cbSPieter Ghysels PetscValidHeaderSpecific(F,MAT_CLASSID,1); 135*575704cbSPieter Ghysels PetscValidLogicalCollectiveInt(F,hssminsize,2); 136*575704cbSPieter Ghysels ierr = PetscTryMethod(F,"MatSTRUMPACKSetHSSMinSize_C",(Mat,PetscInt),(F,hssminsize));CHKERRQ(ierr); 137*575704cbSPieter Ghysels PetscFunctionReturn(0); 138*575704cbSPieter Ghysels } 139*575704cbSPieter Ghysels 140*575704cbSPieter Ghysels #undef __FUNCT__ 141*575704cbSPieter Ghysels #define __FUNCT__ "MatSTRUMPACKSetColPerm_STRUMPACK" 142*575704cbSPieter Ghysels static PetscErrorCode MatSTRUMPACKSetColPerm_STRUMPACK(Mat F,PetscBool cperm) 143*575704cbSPieter Ghysels { 144*575704cbSPieter Ghysels STRUMPACK_data *sp = (STRUMPACK_data*)F->spptr; 145*575704cbSPieter Ghysels 146*575704cbSPieter Ghysels PetscFunctionBegin; 147*575704cbSPieter Ghysels PetscStackCall("STRUMPACK_set_mc64job",STRUMPACK_set_mc64job(sp->S,cperm ? 5 : 0)); 148*575704cbSPieter Ghysels PetscFunctionReturn(0); 149*575704cbSPieter Ghysels } 150*575704cbSPieter Ghysels 151*575704cbSPieter Ghysels #undef __FUNCT__ 152*575704cbSPieter Ghysels #define __FUNCT__ "MatSTRUMPACKSetColPerm" 153*575704cbSPieter Ghysels /*@ 154*575704cbSPieter Ghysels MatSTRUMPACKSetColPerm - Set whether STRUMPACK should try to permute the columns of the matrix in order to get a nonzero diagonal 155*575704cbSPieter Ghysels Logically Collective on Mat 156*575704cbSPieter Ghysels 157*575704cbSPieter Ghysels Input Parameters: 158*575704cbSPieter Ghysels + F - the factored matrix obtained by calling MatGetFactor() from PETSc-STRUMPACK interface 159*575704cbSPieter Ghysels - cperm - whether or not to permute (internally) the columns of the matrix 160*575704cbSPieter Ghysels 161*575704cbSPieter Ghysels Options Database: 162*575704cbSPieter Ghysels . -mat_strumpack_colperm <cperm> 163*575704cbSPieter Ghysels 164*575704cbSPieter Ghysels Level: beginner 165*575704cbSPieter Ghysels 166*575704cbSPieter Ghysels References: 167*575704cbSPieter Ghysels . STRUMPACK manual 168*575704cbSPieter Ghysels 169*575704cbSPieter Ghysels .seealso: MatGetFactor() 170*575704cbSPieter Ghysels @*/ 171*575704cbSPieter Ghysels PetscErrorCode MatSTRUMPACKSetColPerm(Mat F,PetscBool cperm) 172*575704cbSPieter Ghysels { 173*575704cbSPieter Ghysels PetscErrorCode ierr; 174*575704cbSPieter Ghysels 175*575704cbSPieter Ghysels PetscFunctionBegin; 176*575704cbSPieter Ghysels PetscValidHeaderSpecific(F,MAT_CLASSID,1); 177*575704cbSPieter Ghysels PetscValidLogicalCollectiveBool(F,cperm,2); 178*575704cbSPieter 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 367*575704cbSPieter Ghysels /*MC 368*575704cbSPieter Ghysels MATSOLVERSSTRUMPACK = "strumpack" - A solver package providing a direct sparse solver (PCLU) 369*575704cbSPieter Ghysels and a preconditioner (PCILU) using low-rank compression via the external package STRUMPACK. 370*575704cbSPieter Ghysels 371*575704cbSPieter Ghysels Consult the STRUMPACK-sparse manual for more info. 372*575704cbSPieter Ghysels 373*575704cbSPieter Ghysels Use 374*575704cbSPieter Ghysels ./configure --download-strumpack 375*575704cbSPieter Ghysels to have PETSc installed with STRUMPACK 376*575704cbSPieter Ghysels 377*575704cbSPieter Ghysels Use 378*575704cbSPieter Ghysels -pc_type lu -pc_factor_mat_solver_package strumpack 379*575704cbSPieter Ghysels to use this as an exact (direct) solver, use 380*575704cbSPieter Ghysels -pc_type ilu -pc_factor_mat_solver_package strumpack 381*575704cbSPieter Ghysels to enable low-rank compression (i.e, use as a preconditioner). 382*575704cbSPieter Ghysels 383*575704cbSPieter Ghysels Works with AIJ matrices 384*575704cbSPieter Ghysels 385*575704cbSPieter Ghysels Options Database Keys: 386*575704cbSPieter Ghysels + -mat_strumpack_rctol <1e-4> - Relative compression tolerance (None) 387*575704cbSPieter Ghysels . -mat_strumpack_hssminsize <512> - Minimum size of dense block for HSS compression (None) 388*575704cbSPieter Ghysels . -mat_strumpack_colperm <TRUE> - Permute matrix to make diagonal nonzeros (None) 389*575704cbSPieter Ghysels 390*575704cbSPieter Ghysels Level: beginner 391*575704cbSPieter Ghysels 392*575704cbSPieter Ghysels .seealso: PCLU, PCILU, MATSOLVERSUPERLU_DIST, MATSOLVERMUMPS, PCFactorSetMatSolverPackage(), MatSolverPackage 393*575704cbSPieter 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; 404*575704cbSPieter Ghysels PetscBool verb,flg,set; 405*575704cbSPieter Ghysels PetscReal rctol; 406*575704cbSPieter 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); 424*575704cbSPieter Ghysels if (ftype == MAT_FACTOR_LU || ftype == MAT_FACTOR_ILU) { 4257d6ea485SPieter Ghysels B->ops->lufactorsymbolic = MatLUFactorSymbolic_STRUMPACK; 426*575704cbSPieter Ghysels B->ops->ilufactorsymbolic = MatLUFactorSymbolic_STRUMPACK; 427*575704cbSPieter 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); 432*575704cbSPieter Ghysels ierr = PetscObjectComposeFunction((PetscObject)B,"MatSTRUMPACKSetHSSRelCompTol_C",MatSTRUMPACKSetHSSRelCompTol_STRUMPACK);CHKERRQ(ierr); 433*575704cbSPieter Ghysels ierr = PetscObjectComposeFunction((PetscObject)B,"MatSTRUMPACKSetHSSMinSize_C",MatSTRUMPACKSetHSSMinSize_STRUMPACK);CHKERRQ(ierr); 434*575704cbSPieter Ghysels ierr = PetscObjectComposeFunction((PetscObject)B,"MatSTRUMPACKSetColPerm_C",MatSTRUMPACKSetColPerm_STRUMPACK);CHKERRQ(ierr); 435*575704cbSPieter 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 455*575704cbSPieter 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 472*575704cbSPieter Ghysels PetscStackCall("STRUMPACK_get_rctol",rctol = (PetscReal)STRUMPACK_get_rctol(sp->S)); 473*575704cbSPieter Ghysels ierr = PetscOptionsReal("-mat_strumpack_rctol","Relative compression tolerance","None",rctol,&rctol,&set);CHKERRQ(ierr); 474*575704cbSPieter Ghysels if (set) PetscStackCall("STRUMPACK_set_rctol",STRUMPACK_set_rctol(sp->S,(double)rctol)); 475*575704cbSPieter Ghysels 476*575704cbSPieter Ghysels PetscStackCall("STRUMPACK_get_mc64job",flg = (STRUMPACK_get_mc64job(sp->S) == 0) ? PETSC_FALSE : PETSC_TRUE); 477*575704cbSPieter Ghysels ierr = PetscOptionsBool("-mat_strumpack_colperm","Find a col perm to get nonzero diagonal","None",flg,&flg,&set);CHKERRQ(ierr); 478*575704cbSPieter Ghysels if (set) PetscStackCall("STRUMPACK_set_mc64job",STRUMPACK_set_mc64job(sp->S,flg ? 5 : 0)); 479*575704cbSPieter Ghysels 480*575704cbSPieter Ghysels PetscStackCall("STRUMPACK_get_minimum_HSS_size",hssminsize = (PetscInt)STRUMPACK_get_minimum_HSS_size(sp->S)); 481*575704cbSPieter Ghysels ierr = PetscOptionsInt("-mat_strumpack_hssminsize","Minimum size of dense block for HSS compression","None",hssminsize,&hssminsize,&set);CHKERRQ(ierr); 482*575704cbSPieter Ghysels if (set) PetscStackCall("STRUMPACK_set_minimum_HSS_size",STRUMPACK_set_minimum_HSS_size(sp->S,(int)hssminsize)); 483*575704cbSPieter Ghysels 484*575704cbSPieter Ghysels PetscOptionsEnd(); 485*575704cbSPieter Ghysels 486*575704cbSPieter Ghysels /* Disable the outer iterative solver from STRUMPACK. */ 487*575704cbSPieter Ghysels /* When STRUMPACK is used as a direct solver, it will by default do iterative refinement. */ 488*575704cbSPieter Ghysels /* When STRUMPACK is used with as an approximate factorization preconditioner (by enabling */ 489*575704cbSPieter Ghysels /* low-rank compression), it will use it's own GMRES. Here we can in both cases disable the */ 490*575704cbSPieter Ghysels /* outer iterative solver, as PETSc uses STRUMPACK from within a KSP. */ 491*575704cbSPieter Ghysels PetscStackCall("STRUMPACK_set_Krylov_solver", STRUMPACK_set_Krylov_solver(sp->S, STRUMPACK_DIRECT)); 492*575704cbSPieter Ghysels 493*575704cbSPieter Ghysels /* When enabling HSS compression, the STRUMPACK solver becomes an incomplete */ 494*575704cbSPieter Ghysels /* (or approximate) LU factorization. */ 495*575704cbSPieter Ghysels if (ftype == MAT_FACTOR_ILU) PetscStackCall("STRUMPACK_use_HSS",STRUMPACK_use_HSS(sp->S,1)); 496*575704cbSPieter Ghysels 497*575704cbSPieter Ghysels /* Allow the user to set or overwrite the above options from the command line */ 498*575704cbSPieter Ghysels PetscStackCall("STRUMPACK_set_from_options",STRUMPACK_set_from_options(sp->S)); 49955c022e5SPieter Ghysels ierr = PetscStrToArrayDestroy(argc,args);CHKERRQ(ierr); 50055c022e5SPieter Ghysels 5017d6ea485SPieter Ghysels *F = B; 5027d6ea485SPieter Ghysels PetscFunctionReturn(0); 5037d6ea485SPieter Ghysels } 5047d6ea485SPieter Ghysels 5057d6ea485SPieter Ghysels #undef __FUNCT__ 5067d6ea485SPieter Ghysels #define __FUNCT__ "MatSolverPackageRegister_STRUMPACK" 5077d6ea485SPieter Ghysels PETSC_EXTERN PetscErrorCode MatSolverPackageRegister_STRUMPACK(void) 5087d6ea485SPieter Ghysels { 5097d6ea485SPieter Ghysels PetscErrorCode ierr; 5107d6ea485SPieter Ghysels 5117d6ea485SPieter Ghysels PetscFunctionBegin; 5127d6ea485SPieter Ghysels ierr = MatSolverPackageRegister(MATSOLVERSTRUMPACK,MATMPIAIJ,MAT_FACTOR_LU,MatGetFactor_aij_strumpack);CHKERRQ(ierr); 5137d6ea485SPieter Ghysels ierr = MatSolverPackageRegister(MATSOLVERSTRUMPACK,MATSEQAIJ,MAT_FACTOR_LU,MatGetFactor_aij_strumpack);CHKERRQ(ierr); 514*575704cbSPieter Ghysels ierr = MatSolverPackageRegister(MATSOLVERSTRUMPACK,MATMPIAIJ,MAT_FACTOR_ILU,MatGetFactor_aij_strumpack);CHKERRQ(ierr); 515*575704cbSPieter Ghysels ierr = MatSolverPackageRegister(MATSOLVERSTRUMPACK,MATSEQAIJ,MAT_FACTOR_ILU,MatGetFactor_aij_strumpack);CHKERRQ(ierr); 5167d6ea485SPieter Ghysels PetscFunctionReturn(0); 5177d6ea485SPieter Ghysels } 518