xref: /petsc/src/mat/impls/aij/mpi/strumpack/strumpack.c (revision 575704cb8135c145d565b6969a483bc3fe0041b7)
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