13bf14a46SMatthew Knepley /*
23bf14a46SMatthew Knepley Provides an interface to the PaStiX sparse solver
33bf14a46SMatthew Knepley */
4c6db04a5SJed Brown #include <../src/mat/impls/aij/seq/aij.h>
5c6db04a5SJed Brown #include <../src/mat/impls/aij/mpi/mpiaij.h>
6c6db04a5SJed Brown #include <../src/mat/impls/sbaij/seq/sbaij.h>
7c6db04a5SJed Brown #include <../src/mat/impls/sbaij/mpi/mpisbaij.h>
83bf14a46SMatthew Knepley
9dbbbd53dSSatish Balay #if defined(PETSC_USE_COMPLEX)
105ec454cfSSatish Balay #define _H_COMPLEX
115ec454cfSSatish Balay #endif
125ec454cfSSatish Balay
13c6db04a5SJed Brown #include <pastix.h>
143bf14a46SMatthew Knepley
15519f805aSKarl Rupp #if defined(PETSC_USE_COMPLEX)
16519f805aSKarl Rupp #if defined(PETSC_USE_REAL_SINGLE)
17688c8ee7SFlorent Pruvost #define SPM_FLTTYPE SpmComplex32
185ec454cfSSatish Balay #else
19688c8ee7SFlorent Pruvost #define SPM_FLTTYPE SpmComplex64
205ec454cfSSatish Balay #endif
21d41469e0Sxavier lacoste #else /* PETSC_USE_COMPLEX */
22d41469e0Sxavier lacoste
23519f805aSKarl Rupp #if defined(PETSC_USE_REAL_SINGLE)
24688c8ee7SFlorent Pruvost #define SPM_FLTTYPE SpmFloat
255ec454cfSSatish Balay #else
26688c8ee7SFlorent Pruvost #define SPM_FLTTYPE SpmDouble
275ec454cfSSatish Balay #endif
28d41469e0Sxavier lacoste
29d41469e0Sxavier lacoste #endif /* PETSC_USE_COMPLEX */
30d41469e0Sxavier lacoste
31dbbbd53dSSatish Balay typedef PetscScalar PastixScalar;
32dbbbd53dSSatish Balay
333bf14a46SMatthew Knepley typedef struct Mat_Pastix_ {
343bf14a46SMatthew Knepley pastix_data_t *pastix_data; /* Pastix data storage structure */
35688c8ee7SFlorent Pruvost MPI_Comm comm; /* MPI Communicator used to initialize pastix */
36688c8ee7SFlorent Pruvost spmatrix_t *spm; /* SPM matrix structure */
3746091a0eSPierre Jolivet MatStructure matstruc; /* DIFFERENT_NONZERO_PATTERN if uninitialized, SAME otherwise */
38688c8ee7SFlorent Pruvost PetscScalar *rhs; /* Right-hand-side member */
39688c8ee7SFlorent Pruvost PetscInt rhsnbr; /* Right-hand-side number */
40688c8ee7SFlorent Pruvost pastix_int_t iparm[IPARM_SIZE]; /* Integer parameters */
41baed9decSBarry Smith double dparm[DPARM_SIZE]; /* Floating point parameters */
423bf14a46SMatthew Knepley } Mat_Pastix;
433bf14a46SMatthew Knepley
443bf14a46SMatthew Knepley /*
45688c8ee7SFlorent Pruvost convert PETSc matrix to SPM structure
463bf14a46SMatthew Knepley
473bf14a46SMatthew Knepley input:
48688c8ee7SFlorent Pruvost A - matrix in aij, baij or sbaij format
49688c8ee7SFlorent Pruvost reuse - MAT_INITIAL_MATRIX: spaces are allocated and values are set for the triple
50688c8ee7SFlorent Pruvost MAT_REUSE_MATRIX: only the values in v array are updated
513bf14a46SMatthew Knepley output:
52688c8ee7SFlorent Pruvost spm - The SPM built from A
533bf14a46SMatthew Knepley */
MatConvertToSPM(Mat A,MatReuse reuse,Mat_Pastix * pastix)54688c8ee7SFlorent Pruvost static PetscErrorCode MatConvertToSPM(Mat A, MatReuse reuse, Mat_Pastix *pastix)
55d71ae5a4SJacob Faibussowitsch {
56688c8ee7SFlorent Pruvost Mat A_loc, A_aij;
57688c8ee7SFlorent Pruvost const PetscInt *row, *col;
58688c8ee7SFlorent Pruvost PetscInt n, i;
59688c8ee7SFlorent Pruvost const PetscScalar *val;
60688c8ee7SFlorent Pruvost PetscBool ismpiaij, isseqaij, ismpisbaij, isseqsbaij;
61688c8ee7SFlorent Pruvost PetscBool flag;
62688c8ee7SFlorent Pruvost spmatrix_t spm2, *spm = NULL;
63688c8ee7SFlorent Pruvost int spm_err;
643bf14a46SMatthew Knepley
653bf14a46SMatthew Knepley PetscFunctionBegin;
66688c8ee7SFlorent Pruvost /* Get A datas */
67688c8ee7SFlorent Pruvost PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATSEQAIJ, &isseqaij));
68688c8ee7SFlorent Pruvost PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATMPIAIJ, &ismpiaij));
69688c8ee7SFlorent Pruvost /* TODO: Block Aij should be handled with dof in spm */
70688c8ee7SFlorent Pruvost PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATSEQSBAIJ, &isseqsbaij));
71688c8ee7SFlorent Pruvost PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATMPISBAIJ, &ismpisbaij));
723bf14a46SMatthew Knepley
73688c8ee7SFlorent Pruvost if (isseqsbaij || ismpisbaij) PetscCall(MatConvert(A, MATAIJ, reuse, &A_aij));
74688c8ee7SFlorent Pruvost else A_aij = A;
75745c78f7SBarry Smith
76688c8ee7SFlorent Pruvost if (ismpiaij || ismpisbaij) PetscCall(MatMPIAIJGetLocalMat(A_aij, MAT_INITIAL_MATRIX, &A_loc));
77688c8ee7SFlorent Pruvost else if (isseqaij || isseqsbaij) A_loc = A_aij;
78688c8ee7SFlorent Pruvost else SETERRQ(PetscObjectComm((PetscObject)A_aij), PETSC_ERR_SUP, "Not for type %s", ((PetscObject)A)->type_name);
79688c8ee7SFlorent Pruvost
80688c8ee7SFlorent Pruvost /* Use getRowIJ and the trick CSC/CSR instead of GetColumnIJ for performance */
81688c8ee7SFlorent Pruvost PetscCall(MatGetRowIJ(A_loc, 0, PETSC_FALSE, PETSC_FALSE, &n, &row, &col, &flag));
82688c8ee7SFlorent Pruvost PetscCheck(flag, PETSC_COMM_SELF, PETSC_ERR_SUP, "GetRowIJ failed");
83688c8ee7SFlorent Pruvost PetscCall(MatSeqAIJGetArrayRead(A_loc, &val));
84688c8ee7SFlorent Pruvost
85688c8ee7SFlorent Pruvost PetscCall(PetscMalloc1(1, &spm));
86688c8ee7SFlorent Pruvost PetscStackCallExternalVoid("spmInitDist", spmInitDist(spm, pastix->comm));
87688c8ee7SFlorent Pruvost
88688c8ee7SFlorent Pruvost spm->n = n;
89688c8ee7SFlorent Pruvost spm->nnz = row[n];
90688c8ee7SFlorent Pruvost spm->fmttype = SpmCSR;
91688c8ee7SFlorent Pruvost spm->flttype = SPM_FLTTYPE;
92688c8ee7SFlorent Pruvost spm->replicated = !(A->rmap->n != A->rmap->N);
93688c8ee7SFlorent Pruvost
94688c8ee7SFlorent Pruvost PetscStackCallExternalVoid("spmUpdateComputedFields", spmUpdateComputedFields(spm));
95688c8ee7SFlorent Pruvost PetscStackCallExternalVoid("spmAlloc", spmAlloc(spm));
96688c8ee7SFlorent Pruvost
97688c8ee7SFlorent Pruvost /* Get data distribution */
98688c8ee7SFlorent Pruvost if (!spm->replicated) {
99688c8ee7SFlorent Pruvost for (i = A->rmap->rstart; i < A->rmap->rend; i++) spm->loc2glob[i - A->rmap->rstart] = i;
100688c8ee7SFlorent Pruvost }
101688c8ee7SFlorent Pruvost
102688c8ee7SFlorent Pruvost /* Copy arrays */
103688c8ee7SFlorent Pruvost PetscCall(PetscArraycpy(spm->colptr, col, spm->nnz));
104688c8ee7SFlorent Pruvost PetscCall(PetscArraycpy(spm->rowptr, row, spm->n + 1));
105688c8ee7SFlorent Pruvost PetscCall(PetscArraycpy((PetscScalar *)spm->values, val, spm->nnzexp));
106688c8ee7SFlorent Pruvost PetscCall(MatRestoreRowIJ(A_loc, 0, PETSC_FALSE, PETSC_FALSE, &n, &row, &col, &flag));
107688c8ee7SFlorent Pruvost PetscCheck(flag, PETSC_COMM_SELF, PETSC_ERR_SUP, "RestoreRowIJ failed");
108688c8ee7SFlorent Pruvost PetscCall(MatSeqAIJRestoreArrayRead(A_loc, &val));
109688c8ee7SFlorent Pruvost if (ismpiaij || ismpisbaij) PetscCall(MatDestroy(&A_loc));
110688c8ee7SFlorent Pruvost
111688c8ee7SFlorent Pruvost /*
112688c8ee7SFlorent Pruvost PaStiX works only with CSC matrices for now, so let's lure him by telling him
113688c8ee7SFlorent Pruvost that the PETSc CSR matrix is a CSC matrix.
114688c8ee7SFlorent Pruvost Note that this is not available yet for Hermitian matrices and LL^h/LDL^h factorizations.
115745c78f7SBarry Smith */
116688c8ee7SFlorent Pruvost {
117688c8ee7SFlorent Pruvost spm_int_t *tmp;
118688c8ee7SFlorent Pruvost spm->fmttype = SpmCSC;
119688c8ee7SFlorent Pruvost tmp = spm->colptr;
120688c8ee7SFlorent Pruvost spm->colptr = spm->rowptr;
121688c8ee7SFlorent Pruvost spm->rowptr = tmp;
122688c8ee7SFlorent Pruvost pastix->iparm[IPARM_TRANSPOSE_SOLVE] = PastixTrans;
123f31ce8a6SBarry Smith }
124745c78f7SBarry Smith
125688c8ee7SFlorent Pruvost /* Update matrix to be in PaStiX format */
126688c8ee7SFlorent Pruvost PetscStackCallExternalVoid("spmCheckAndCorrect", spm_err = spmCheckAndCorrect(spm, &spm2));
127688c8ee7SFlorent Pruvost if (spm_err != 0) {
128688c8ee7SFlorent Pruvost PetscStackCallExternalVoid("spmExit", spmExit(spm));
129688c8ee7SFlorent Pruvost *spm = spm2;
1303bf14a46SMatthew Knepley }
1313bf14a46SMatthew Knepley
132688c8ee7SFlorent Pruvost if (isseqsbaij || ismpisbaij) PetscCall(MatDestroy(&A_aij));
133688c8ee7SFlorent Pruvost
134688c8ee7SFlorent Pruvost pastix->spm = spm;
1353ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
1363bf14a46SMatthew Knepley }
1373bf14a46SMatthew Knepley
1383bf14a46SMatthew Knepley /*
139688c8ee7SFlorent Pruvost Call clean step of PaStiX if initialized
140688c8ee7SFlorent Pruvost Free the SpM matrix and the PaStiX instance.
1413bf14a46SMatthew Knepley */
MatDestroy_PaStiX(Mat A)142688c8ee7SFlorent Pruvost static PetscErrorCode MatDestroy_PaStiX(Mat A)
143d71ae5a4SJacob Faibussowitsch {
144688c8ee7SFlorent Pruvost Mat_Pastix *pastix = (Mat_Pastix *)A->data;
145745c78f7SBarry Smith
1463bf14a46SMatthew Knepley PetscFunctionBegin;
147688c8ee7SFlorent Pruvost /* Finalize SPM (matrix handler of PaStiX) */
148688c8ee7SFlorent Pruvost if (pastix->spm) {
149688c8ee7SFlorent Pruvost PetscStackCallExternalVoid("spmExit", spmExit(pastix->spm));
150688c8ee7SFlorent Pruvost PetscCall(PetscFree(pastix->spm));
1513bf14a46SMatthew Knepley }
152688c8ee7SFlorent Pruvost
153688c8ee7SFlorent Pruvost /* clear composed functions */
1542e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatFactorGetSolverType_C", NULL));
155688c8ee7SFlorent Pruvost
156688c8ee7SFlorent Pruvost /* Finalize PaStiX */
157688c8ee7SFlorent Pruvost if (pastix->pastix_data) pastixFinalize(&pastix->pastix_data);
158688c8ee7SFlorent Pruvost
159688c8ee7SFlorent Pruvost /* Deallocate PaStiX structure */
1609566063dSJacob Faibussowitsch PetscCall(PetscFree(A->data));
1613ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
1623bf14a46SMatthew Knepley }
1633bf14a46SMatthew Knepley
1643bf14a46SMatthew Knepley /*
165dd8e379bSPierre Jolivet Gather right-hand side.
1663bf14a46SMatthew Knepley Call for Solve step.
1673bf14a46SMatthew Knepley Scatter solution.
1683bf14a46SMatthew Knepley */
MatSolve_PaStiX(Mat A,Vec b,Vec x)16966976f2fSJacob Faibussowitsch static PetscErrorCode MatSolve_PaStiX(Mat A, Vec b, Vec x)
170d71ae5a4SJacob Faibussowitsch {
171688c8ee7SFlorent Pruvost Mat_Pastix *pastix = (Mat_Pastix *)A->data;
172688c8ee7SFlorent Pruvost const PetscScalar *bptr;
173688c8ee7SFlorent Pruvost PetscInt ldrhs;
1743bf14a46SMatthew Knepley
1753bf14a46SMatthew Knepley PetscFunctionBegin;
176688c8ee7SFlorent Pruvost pastix->rhsnbr = 1;
177688c8ee7SFlorent Pruvost ldrhs = pastix->spm->n;
178688c8ee7SFlorent Pruvost
1799566063dSJacob Faibussowitsch PetscCall(VecCopy(b, x));
180688c8ee7SFlorent Pruvost PetscCall(VecGetArray(x, &pastix->rhs));
181688c8ee7SFlorent Pruvost PetscCall(VecGetArrayRead(b, &bptr));
1823bf14a46SMatthew Knepley
1833bf14a46SMatthew Knepley /* solve phase */
184688c8ee7SFlorent Pruvost /*-------------*/
185688c8ee7SFlorent Pruvost PetscCheck(pastix->pastix_data, PETSC_COMM_SELF, PETSC_ERR_SUP, "PaStiX hasn't been initialized");
186688c8ee7SFlorent Pruvost PetscCallExternal(pastix_task_solve, pastix->pastix_data, ldrhs, pastix->rhsnbr, pastix->rhs, ldrhs);
187688c8ee7SFlorent Pruvost PetscCallExternal(pastix_task_refine, pastix->pastix_data, ldrhs, pastix->rhsnbr, (PetscScalar *)bptr, ldrhs, pastix->rhs, ldrhs);
1883bf14a46SMatthew Knepley
189688c8ee7SFlorent Pruvost PetscCall(VecRestoreArray(x, &pastix->rhs));
190688c8ee7SFlorent Pruvost PetscCall(VecRestoreArrayRead(b, &bptr));
1913ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
1923bf14a46SMatthew Knepley }
1933bf14a46SMatthew Knepley
1943bf14a46SMatthew Knepley /*
1953bf14a46SMatthew Knepley Numeric factorisation using PaStiX solver.
1963bf14a46SMatthew Knepley
197688c8ee7SFlorent Pruvost input:
198688c8ee7SFlorent Pruvost F - PETSc matrix that contains PaStiX interface.
199f605775fSPierre Jolivet A - PETSc matrix in aij, bail or sbaij format
2003bf14a46SMatthew Knepley */
MatFactorNumeric_PaStiX(Mat F,Mat A,const MatFactorInfo * info)20166976f2fSJacob Faibussowitsch static PetscErrorCode MatFactorNumeric_PaStiX(Mat F, Mat A, const MatFactorInfo *info)
202d71ae5a4SJacob Faibussowitsch {
203688c8ee7SFlorent Pruvost Mat_Pastix *pastix = (Mat_Pastix *)F->data;
2043bf14a46SMatthew Knepley
2053bf14a46SMatthew Knepley PetscFunctionBegin;
20657508eceSPierre Jolivet F->ops->solve = MatSolve_PaStiX;
2073bf14a46SMatthew Knepley
208688c8ee7SFlorent Pruvost /* Perform Numerical Factorization */
209688c8ee7SFlorent Pruvost PetscCheck(pastix->pastix_data, PETSC_COMM_SELF, PETSC_ERR_SUP, "PaStiX hasn't been initialized");
210688c8ee7SFlorent Pruvost PetscCallExternal(pastix_task_numfact, pastix->pastix_data, pastix->spm);
2113bf14a46SMatthew Knepley
21257508eceSPierre Jolivet F->assembled = PETSC_TRUE;
2133ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
2143bf14a46SMatthew Knepley }
2153bf14a46SMatthew Knepley
MatLUFactorNumeric_PaStiX(Mat F,Mat A,const MatFactorInfo * info)216688c8ee7SFlorent Pruvost static PetscErrorCode MatLUFactorNumeric_PaStiX(Mat F, Mat A, const MatFactorInfo *info)
217d71ae5a4SJacob Faibussowitsch {
218688c8ee7SFlorent Pruvost Mat_Pastix *pastix = (Mat_Pastix *)F->data;
2193bf14a46SMatthew Knepley
2203bf14a46SMatthew Knepley PetscFunctionBegin;
221688c8ee7SFlorent Pruvost PetscCheck(pastix->iparm[IPARM_FACTORIZATION] == PastixFactGETRF, PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Incorrect factorization type for symbolic and numerical factorization by PaStiX");
222688c8ee7SFlorent Pruvost pastix->iparm[IPARM_FACTORIZATION] = PastixFactGETRF;
223688c8ee7SFlorent Pruvost PetscCall(MatFactorNumeric_PaStiX(F, A, info));
2243ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
2253bf14a46SMatthew Knepley }
2263bf14a46SMatthew Knepley
MatCholeskyFactorNumeric_PaStiX(Mat F,Mat A,const MatFactorInfo * info)227688c8ee7SFlorent Pruvost static PetscErrorCode MatCholeskyFactorNumeric_PaStiX(Mat F, Mat A, const MatFactorInfo *info)
228d71ae5a4SJacob Faibussowitsch {
229688c8ee7SFlorent Pruvost Mat_Pastix *pastix = (Mat_Pastix *)F->data;
2303bf14a46SMatthew Knepley
2313bf14a46SMatthew Knepley PetscFunctionBegin;
232688c8ee7SFlorent Pruvost PetscCheck(pastix->iparm[IPARM_FACTORIZATION] == PastixFactSYTRF, PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Incorrect factorization type for symbolic and numerical factorization by PaStiX");
233688c8ee7SFlorent Pruvost pastix->iparm[IPARM_FACTORIZATION] = PastixFactSYTRF;
234688c8ee7SFlorent Pruvost PetscCall(MatFactorNumeric_PaStiX(F, A, info));
235688c8ee7SFlorent Pruvost PetscFunctionReturn(PETSC_SUCCESS);
236688c8ee7SFlorent Pruvost }
237688c8ee7SFlorent Pruvost
238688c8ee7SFlorent Pruvost /*
239688c8ee7SFlorent Pruvost Perform Ordering step and Symbolic Factorization step
240688c8ee7SFlorent Pruvost
241f0b74427SPierre Jolivet Note the PETSc r and c permutations are ignored
242688c8ee7SFlorent Pruvost input:
243688c8ee7SFlorent Pruvost F - PETSc matrix that contains PaStiX interface.
244688c8ee7SFlorent Pruvost A - matrix in aij, bail or sbaij format
245688c8ee7SFlorent Pruvost r - permutation ?
246688c8ee7SFlorent Pruvost c - TODO
247bfe80ac4SPierre Jolivet info - Information about the factorization to perform.
248688c8ee7SFlorent Pruvost output:
249688c8ee7SFlorent Pruvost pastix_data - This instance will be updated with the SolverMatrix allocated.
250688c8ee7SFlorent Pruvost */
MatFactorSymbolic_PaStiX(Mat F,Mat A,IS r,IS c,const MatFactorInfo * info)251688c8ee7SFlorent Pruvost static PetscErrorCode MatFactorSymbolic_PaStiX(Mat F, Mat A, IS r, IS c, const MatFactorInfo *info)
252688c8ee7SFlorent Pruvost {
253688c8ee7SFlorent Pruvost Mat_Pastix *pastix = (Mat_Pastix *)F->data;
254688c8ee7SFlorent Pruvost
255688c8ee7SFlorent Pruvost PetscFunctionBegin;
256688c8ee7SFlorent Pruvost pastix->matstruc = DIFFERENT_NONZERO_PATTERN;
257688c8ee7SFlorent Pruvost
258688c8ee7SFlorent Pruvost /* Initialise SPM structure */
259688c8ee7SFlorent Pruvost PetscCall(MatConvertToSPM(A, MAT_INITIAL_MATRIX, pastix));
260688c8ee7SFlorent Pruvost
261688c8ee7SFlorent Pruvost /* Ordering - Symbolic factorization - Build SolverMatrix */
262688c8ee7SFlorent Pruvost PetscCheck(pastix->pastix_data, PETSC_COMM_SELF, PETSC_ERR_SUP, "PaStiX hasn't been initialized");
263688c8ee7SFlorent Pruvost PetscCallExternal(pastix_task_analyze, pastix->pastix_data, pastix->spm);
264688c8ee7SFlorent Pruvost PetscFunctionReturn(PETSC_SUCCESS);
265688c8ee7SFlorent Pruvost }
266688c8ee7SFlorent Pruvost
MatLUFactorSymbolic_PaStiX(Mat F,Mat A,IS r,IS c,const MatFactorInfo * info)267688c8ee7SFlorent Pruvost static PetscErrorCode MatLUFactorSymbolic_PaStiX(Mat F, Mat A, IS r, IS c, const MatFactorInfo *info)
268688c8ee7SFlorent Pruvost {
269688c8ee7SFlorent Pruvost Mat_Pastix *pastix = (Mat_Pastix *)F->data;
270688c8ee7SFlorent Pruvost
271688c8ee7SFlorent Pruvost PetscFunctionBegin;
272688c8ee7SFlorent Pruvost pastix->iparm[IPARM_FACTORIZATION] = PastixFactGETRF;
273688c8ee7SFlorent Pruvost PetscCall(MatFactorSymbolic_PaStiX(F, A, r, c, info));
274688c8ee7SFlorent Pruvost PetscFunctionReturn(PETSC_SUCCESS);
275688c8ee7SFlorent Pruvost }
276688c8ee7SFlorent Pruvost
277f0b74427SPierre Jolivet /* Note the PETSc r permutation is ignored */
MatCholeskyFactorSymbolic_PaStiX(Mat F,Mat A,IS r,const MatFactorInfo * info)278688c8ee7SFlorent Pruvost static PetscErrorCode MatCholeskyFactorSymbolic_PaStiX(Mat F, Mat A, IS r, const MatFactorInfo *info)
279688c8ee7SFlorent Pruvost {
280688c8ee7SFlorent Pruvost Mat_Pastix *pastix = (Mat_Pastix *)F->data;
281688c8ee7SFlorent Pruvost
282688c8ee7SFlorent Pruvost PetscFunctionBegin;
283f0b74427SPierre Jolivet /* Warning: Cholesky in PETSc wrapper does not handle (complex) Hermitian matrices.
284688c8ee7SFlorent Pruvost The factorization type can be forced using the parameter
285688c8ee7SFlorent Pruvost mat_pastix_factorization (see enum pastix_factotype_e in
286688c8ee7SFlorent Pruvost https://solverstack.gitlabpages.inria.fr/pastix/group__pastix__api.html). */
287688c8ee7SFlorent Pruvost pastix->iparm[IPARM_FACTORIZATION] = PastixFactSYTRF;
288688c8ee7SFlorent Pruvost PetscCall(MatFactorSymbolic_PaStiX(F, A, r, NULL, info));
2893ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
2903bf14a46SMatthew Knepley }
2913bf14a46SMatthew Knepley
MatView_PaStiX(Mat A,PetscViewer viewer)29266976f2fSJacob Faibussowitsch static PetscErrorCode MatView_PaStiX(Mat A, PetscViewer viewer)
293d71ae5a4SJacob Faibussowitsch {
294*9f196a02SMartin Diehl PetscBool isascii;
2953bf14a46SMatthew Knepley PetscViewerFormat format;
2963bf14a46SMatthew Knepley
2973bf14a46SMatthew Knepley PetscFunctionBegin;
298*9f196a02SMartin Diehl PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
299*9f196a02SMartin Diehl if (isascii) {
3009566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer, &format));
3013bf14a46SMatthew Knepley if (format == PETSC_VIEWER_ASCII_INFO) {
302688c8ee7SFlorent Pruvost Mat_Pastix *pastix = (Mat_Pastix *)A->data;
303688c8ee7SFlorent Pruvost spmatrix_t *spm = pastix->spm;
304688c8ee7SFlorent Pruvost PetscCheck(!spm, PETSC_COMM_SELF, PETSC_ERR_SUP, "Sparse matrix isn't initialized");
305b5e56a35SBarry Smith
3069566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "PaStiX run parameters:\n"));
307688c8ee7SFlorent Pruvost PetscCall(PetscViewerASCIIPrintf(viewer, " Matrix type : %s \n", ((spm->mtxtype == SpmSymmetric) ? "Symmetric" : "Unsymmetric")));
308688c8ee7SFlorent Pruvost PetscCall(PetscViewerASCIIPrintf(viewer, " Level of printing (0,1,2): %ld \n", (long)pastix->iparm[IPARM_VERBOSE]));
309688c8ee7SFlorent Pruvost PetscCall(PetscViewerASCIIPrintf(viewer, " Number of refinements iterations : %ld \n", (long)pastix->iparm[IPARM_NBITER]));
310688c8ee7SFlorent Pruvost PetscCall(PetscPrintf(PETSC_COMM_SELF, " Error : %e \n", pastix->dparm[DPARM_RELATIVE_ERROR]));
311688c8ee7SFlorent Pruvost if (pastix->iparm[IPARM_VERBOSE] > 0) spmPrintInfo(spm, stdout);
3123bf14a46SMatthew Knepley }
3133bf14a46SMatthew Knepley }
3143ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
3153bf14a46SMatthew Knepley }
3163bf14a46SMatthew Knepley
3173bf14a46SMatthew Knepley /*MC
3182692d6eeSBarry Smith MATSOLVERPASTIX - A solver package providing direct solvers (LU) for distributed
3193bf14a46SMatthew Knepley and sequential matrices via the external package PaStiX.
3203bf14a46SMatthew Knepley
321688c8ee7SFlorent Pruvost Use `./configure --download-hwloc --download-metis --download-ptscotch --download-pastix --download-netlib-lapack [or MKL for ex. --with-blaslapack-dir=${MKLROOT}]`
322688c8ee7SFlorent Pruvost to have PETSc installed with PasTiX.
323c2b89b5dSBarry Smith
324688c8ee7SFlorent Pruvost Use `-pc_type lu` `-pc_factor_mat_solver_type pastix` to use this direct solver.
3253bf14a46SMatthew Knepley
3263bf14a46SMatthew Knepley Options Database Keys:
327688c8ee7SFlorent Pruvost -mat_pastix_verbose <0,1,2> - print level of information messages from PaStiX
328688c8ee7SFlorent Pruvost -mat_pastix_factorization <0,1,2,3,4> - Factorization algorithm (Cholesky, LDL^t, LU, LL^t, LDL^h)
329688c8ee7SFlorent Pruvost -mat_pastix_itermax <integer> - Maximum number of iterations during refinement
330688c8ee7SFlorent Pruvost -mat_pastix_epsilon_refinement <double> - Epsilon for refinement
331688c8ee7SFlorent Pruvost -mat_pastix_epsilon_magn_ctrl <double> - Epsilon for magnitude control
332688c8ee7SFlorent Pruvost -mat_pastix_ordering <0,1> - Ordering (Scotch or Metis)
333688c8ee7SFlorent Pruvost -mat_pastix_thread_nbr <integer> - Set the numbers of threads for each MPI process
334688c8ee7SFlorent Pruvost -mat_pastix_scheduler <0,1,2,3,4> - Scheduler (sequential, static, parsec, starpu, dynamic)
335688c8ee7SFlorent Pruvost -mat_pastix_compress_when <0,1,2,3> - When to compress (never, minimal-theory, just-in-time, supernodes)
336688c8ee7SFlorent Pruvost -mat_pastix_compress_tolerance <double> - Tolerance for low-rank kernels.
3373bf14a46SMatthew Knepley
33895452b02SPatrick Sanan Notes:
33995452b02SPatrick Sanan This only works for matrices with symmetric nonzero structure, if you pass it a matrix with
3402ef1f0ffSBarry Smith nonsymmetric structure PasTiX, and hence, PETSc return with an error.
341baed9decSBarry Smith
3423bf14a46SMatthew Knepley Level: beginner
3433bf14a46SMatthew Knepley
3441cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `PCFactorSetMatSolverType()`, `MatSolverType`, `MatGetFactor()`
3453bf14a46SMatthew Knepley M*/
3463bf14a46SMatthew Knepley
MatGetInfo_PaStiX(Mat A,MatInfoType flag,MatInfo * info)34766976f2fSJacob Faibussowitsch static PetscErrorCode MatGetInfo_PaStiX(Mat A, MatInfoType flag, MatInfo *info)
348d71ae5a4SJacob Faibussowitsch {
349688c8ee7SFlorent Pruvost Mat_Pastix *pastix = (Mat_Pastix *)A->data;
3503bf14a46SMatthew Knepley
3513bf14a46SMatthew Knepley PetscFunctionBegin;
3523bf14a46SMatthew Knepley info->block_size = 1.0;
353688c8ee7SFlorent Pruvost info->nz_allocated = pastix->iparm[IPARM_ALLOCATED_TERMS];
354688c8ee7SFlorent Pruvost info->nz_used = pastix->iparm[IPARM_NNZEROS];
3553bf14a46SMatthew Knepley info->nz_unneeded = 0.0;
3563bf14a46SMatthew Knepley info->assemblies = 0.0;
3573bf14a46SMatthew Knepley info->mallocs = 0.0;
3583bf14a46SMatthew Knepley info->memory = 0.0;
3593bf14a46SMatthew Knepley info->fill_ratio_given = 0;
3603bf14a46SMatthew Knepley info->fill_ratio_needed = 0;
3613bf14a46SMatthew Knepley info->factor_mallocs = 0;
3623ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
3633bf14a46SMatthew Knepley }
3643bf14a46SMatthew Knepley
MatFactorGetSolverType_PaStiX(Mat A,MatSolverType * type)365688c8ee7SFlorent Pruvost static PetscErrorCode MatFactorGetSolverType_PaStiX(Mat A, MatSolverType *type)
366d71ae5a4SJacob Faibussowitsch {
3673bf14a46SMatthew Knepley PetscFunctionBegin;
3682692d6eeSBarry Smith *type = MATSOLVERPASTIX;
3693ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
3703bf14a46SMatthew Knepley }
3713bf14a46SMatthew Knepley
372688c8ee7SFlorent Pruvost /* Sets PaStiX options from the options database */
MatSetFromOptions_PaStiX(Mat A)373688c8ee7SFlorent Pruvost static PetscErrorCode MatSetFromOptions_PaStiX(Mat A)
374688c8ee7SFlorent Pruvost {
375688c8ee7SFlorent Pruvost Mat_Pastix *pastix = (Mat_Pastix *)A->data;
376688c8ee7SFlorent Pruvost pastix_int_t *iparm = pastix->iparm;
377688c8ee7SFlorent Pruvost double *dparm = pastix->dparm;
378688c8ee7SFlorent Pruvost PetscInt icntl;
379688c8ee7SFlorent Pruvost PetscReal dcntl;
380688c8ee7SFlorent Pruvost PetscBool set;
381688c8ee7SFlorent Pruvost
382688c8ee7SFlorent Pruvost PetscFunctionBegin;
383688c8ee7SFlorent Pruvost PetscOptionsBegin(PetscObjectComm((PetscObject)A), ((PetscObject)A)->prefix, "PaStiX Options", "Mat");
384688c8ee7SFlorent Pruvost
385688c8ee7SFlorent Pruvost iparm[IPARM_VERBOSE] = 0;
386688c8ee7SFlorent Pruvost iparm[IPARM_ITERMAX] = 20;
387688c8ee7SFlorent Pruvost
388688c8ee7SFlorent Pruvost PetscCall(PetscOptionsRangeInt("-mat_pastix_verbose", "iparm[IPARM_VERBOSE] : level of printing (0 to 2)", "None", iparm[IPARM_VERBOSE], &icntl, &set, 0, 2));
389688c8ee7SFlorent Pruvost if (set) iparm[IPARM_VERBOSE] = (pastix_int_t)icntl;
390688c8ee7SFlorent Pruvost
391688c8ee7SFlorent Pruvost PetscCall(PetscOptionsRangeInt("-mat_pastix_factorization", "iparm[IPARM_FACTORIZATION]: Factorization algorithm", "None", iparm[IPARM_FACTORIZATION], &icntl, &set, 0, 4));
392688c8ee7SFlorent Pruvost if (set) iparm[IPARM_FACTORIZATION] = (pastix_int_t)icntl;
393688c8ee7SFlorent Pruvost
394688c8ee7SFlorent Pruvost PetscCall(PetscOptionsBoundedInt("-mat_pastix_itermax", "iparm[IPARM_ITERMAX]: Max iterations", "None", iparm[IPARM_ITERMAX], &icntl, &set, 1));
395688c8ee7SFlorent Pruvost if (set) iparm[IPARM_ITERMAX] = (pastix_int_t)icntl;
396688c8ee7SFlorent Pruvost
397688c8ee7SFlorent Pruvost PetscCall(PetscOptionsBoundedReal("-mat_pastix_epsilon_refinement", "dparm[DPARM_EPSILON_REFINEMENT]: Epsilon refinement", "None", dparm[DPARM_EPSILON_REFINEMENT], &dcntl, &set, -1.));
398688c8ee7SFlorent Pruvost if (set) dparm[DPARM_EPSILON_REFINEMENT] = (double)dcntl;
399688c8ee7SFlorent Pruvost
400688c8ee7SFlorent Pruvost PetscCall(PetscOptionsReal("-mat_pastix_epsilon_magn_ctrl", "dparm[DPARM_EPSILON_MAGN_CTRL]: Epsilon magnitude control", "None", dparm[DPARM_EPSILON_MAGN_CTRL], &dcntl, &set));
401688c8ee7SFlorent Pruvost if (set) dparm[DPARM_EPSILON_MAGN_CTRL] = (double)dcntl;
402688c8ee7SFlorent Pruvost
403688c8ee7SFlorent Pruvost PetscCall(PetscOptionsRangeInt("-mat_pastix_ordering", "iparm[IPARM_ORDERING]: Ordering algorithm", "None", iparm[IPARM_ORDERING], &icntl, &set, 0, 2));
404688c8ee7SFlorent Pruvost if (set) iparm[IPARM_ORDERING] = (pastix_int_t)icntl;
405688c8ee7SFlorent Pruvost
406688c8ee7SFlorent Pruvost PetscCall(PetscOptionsBoundedInt("-mat_pastix_thread_nbr", "iparm[IPARM_THREAD_NBR]: Number of thread by MPI node", "None", iparm[IPARM_THREAD_NBR], &icntl, &set, -1));
407688c8ee7SFlorent Pruvost if (set) iparm[IPARM_THREAD_NBR] = (pastix_int_t)icntl;
408688c8ee7SFlorent Pruvost
409688c8ee7SFlorent Pruvost PetscCall(PetscOptionsRangeInt("-mat_pastix_scheduler", "iparm[IPARM_SCHEDULER]: Scheduler", "None", iparm[IPARM_SCHEDULER], &icntl, &set, 0, 4));
410688c8ee7SFlorent Pruvost if (set) iparm[IPARM_SCHEDULER] = (pastix_int_t)icntl;
411688c8ee7SFlorent Pruvost
412688c8ee7SFlorent Pruvost PetscCall(PetscOptionsRangeInt("-mat_pastix_compress_when", "iparm[IPARM_COMPRESS_WHEN]: When to compress", "None", iparm[IPARM_COMPRESS_WHEN], &icntl, &set, 0, 3));
413688c8ee7SFlorent Pruvost if (set) iparm[IPARM_COMPRESS_WHEN] = (pastix_int_t)icntl;
414688c8ee7SFlorent Pruvost
415688c8ee7SFlorent Pruvost PetscCall(PetscOptionsBoundedReal("-mat_pastix_compress_tolerance", "dparm[DPARM_COMPRESS_TOLERANCE]: Tolerance for low-rank kernels", "None", dparm[DPARM_COMPRESS_TOLERANCE], &dcntl, &set, 0.));
416688c8ee7SFlorent Pruvost if (set) dparm[DPARM_COMPRESS_TOLERANCE] = (double)dcntl;
417688c8ee7SFlorent Pruvost
418688c8ee7SFlorent Pruvost PetscOptionsEnd();
419688c8ee7SFlorent Pruvost PetscFunctionReturn(PETSC_SUCCESS);
420688c8ee7SFlorent Pruvost }
421688c8ee7SFlorent Pruvost
MatGetFactor_pastix(Mat A,MatFactorType ftype,Mat * F,const char * mattype)422688c8ee7SFlorent Pruvost static PetscErrorCode MatGetFactor_pastix(Mat A, MatFactorType ftype, Mat *F, const char *mattype)
423d71ae5a4SJacob Faibussowitsch {
4243bf14a46SMatthew Knepley Mat B;
4253bf14a46SMatthew Knepley Mat_Pastix *pastix;
4263bf14a46SMatthew Knepley
4273bf14a46SMatthew Knepley PetscFunctionBegin;
4283bf14a46SMatthew Knepley /* Create the factorization matrix */
4299566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &B));
4309566063dSJacob Faibussowitsch PetscCall(MatSetSizes(B, A->rmap->n, A->cmap->n, A->rmap->N, A->cmap->N));
431688c8ee7SFlorent Pruvost PetscCall(PetscStrallocpy(MATSOLVERPASTIX, &((PetscObject)B)->type_name));
4329566063dSJacob Faibussowitsch PetscCall(MatSetUp(B));
4333bf14a46SMatthew Knepley
434688c8ee7SFlorent Pruvost PetscCheck(ftype == MAT_FACTOR_LU || ftype == MAT_FACTOR_CHOLESKY, PETSC_COMM_SELF, PETSC_ERR_SUP, "Factor type not supported by PaStiX");
4353bf14a46SMatthew Knepley
43600c67f3bSHong Zhang /* set solvertype */
4379566063dSJacob Faibussowitsch PetscCall(PetscFree(B->solvertype));
4389566063dSJacob Faibussowitsch PetscCall(PetscStrallocpy(MATSOLVERPASTIX, &B->solvertype));
43900c67f3bSHong Zhang
440688c8ee7SFlorent Pruvost B->ops->lufactorsymbolic = MatLUFactorSymbolic_PaStiX;
441688c8ee7SFlorent Pruvost B->ops->lufactornumeric = MatLUFactorNumeric_PaStiX;
442688c8ee7SFlorent Pruvost B->ops->choleskyfactorsymbolic = MatCholeskyFactorSymbolic_PaStiX;
443688c8ee7SFlorent Pruvost B->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_PaStiX;
444688c8ee7SFlorent Pruvost B->ops->view = MatView_PaStiX;
445688c8ee7SFlorent Pruvost B->ops->getinfo = MatGetInfo_PaStiX;
446688c8ee7SFlorent Pruvost B->ops->destroy = MatDestroy_PaStiX;
4472205254eSKarl Rupp
448688c8ee7SFlorent Pruvost PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatFactorGetSolverType_C", MatFactorGetSolverType_PaStiX));
449688c8ee7SFlorent Pruvost
450688c8ee7SFlorent Pruvost B->factortype = ftype;
451688c8ee7SFlorent Pruvost
452688c8ee7SFlorent Pruvost /* Create the pastix structure */
453688c8ee7SFlorent Pruvost PetscCall(PetscNew(&pastix));
45458c95f1bSBarry Smith B->data = (void *)pastix;
4553bf14a46SMatthew Knepley
456688c8ee7SFlorent Pruvost /* Call to set default pastix options */
457688c8ee7SFlorent Pruvost PetscStackCallExternalVoid("pastixInitParam", pastixInitParam(pastix->iparm, pastix->dparm));
458688c8ee7SFlorent Pruvost PetscCall(MatSetFromOptions_PaStiX(B));
459688c8ee7SFlorent Pruvost
460688c8ee7SFlorent Pruvost /* Get PETSc communicator */
461688c8ee7SFlorent Pruvost PetscCall(PetscObjectGetComm((PetscObject)A, &pastix->comm));
462688c8ee7SFlorent Pruvost
463688c8ee7SFlorent Pruvost /* Initialise PaStiX structure */
464688c8ee7SFlorent Pruvost pastix->iparm[IPARM_SCOTCH_MT] = 0;
465688c8ee7SFlorent Pruvost PetscStackCallExternalVoid("pastixInit", pastixInit(&pastix->pastix_data, pastix->comm, pastix->iparm, pastix->dparm));
466688c8ee7SFlorent Pruvost
467f0b74427SPierre Jolivet /* Warning: Cholesky in PETSc wrapper does not handle (complex) Hermitian matrices.
468688c8ee7SFlorent Pruvost The factorization type can be forced using the parameter
469688c8ee7SFlorent Pruvost mat_pastix_factorization (see enum pastix_factotype_e in
470688c8ee7SFlorent Pruvost https://solverstack.gitlabpages.inria.fr/pastix/group__pastix__api.html). */
471688c8ee7SFlorent Pruvost pastix->iparm[IPARM_FACTORIZATION] = ftype == MAT_FACTOR_CHOLESKY ? PastixFactSYTRF : PastixFactGETRF;
472688c8ee7SFlorent Pruvost
4733bf14a46SMatthew Knepley *F = B;
4743ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
4753bf14a46SMatthew Knepley }
4763bf14a46SMatthew Knepley
MatGetFactor_mpiaij_pastix(Mat A,MatFactorType ftype,Mat * F)477d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatGetFactor_mpiaij_pastix(Mat A, MatFactorType ftype, Mat *F)
478d71ae5a4SJacob Faibussowitsch {
4793bf14a46SMatthew Knepley PetscFunctionBegin;
4805f80ce2aSJacob Faibussowitsch PetscCheck(ftype == MAT_FACTOR_LU, PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot use PETSc AIJ matrices with PaStiX Cholesky, use SBAIJ matrix");
481688c8ee7SFlorent Pruvost PetscCall(MatGetFactor_pastix(A, ftype, F, MATMPIAIJ));
4823ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
4833bf14a46SMatthew Knepley }
4843bf14a46SMatthew Knepley
MatGetFactor_seqaij_pastix(Mat A,MatFactorType ftype,Mat * F)485688c8ee7SFlorent Pruvost static PetscErrorCode MatGetFactor_seqaij_pastix(Mat A, MatFactorType ftype, Mat *F)
486d71ae5a4SJacob Faibussowitsch {
4873bf14a46SMatthew Knepley PetscFunctionBegin;
488688c8ee7SFlorent Pruvost PetscCheck(ftype == MAT_FACTOR_LU, PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot use PETSc AIJ matrices with PaStiX Cholesky, use SBAIJ matrix");
489688c8ee7SFlorent Pruvost PetscCall(MatGetFactor_pastix(A, ftype, F, MATSEQAIJ));
4903ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
4913bf14a46SMatthew Knepley }
4923bf14a46SMatthew Knepley
MatGetFactor_mpisbaij_pastix(Mat A,MatFactorType ftype,Mat * F)493d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatGetFactor_mpisbaij_pastix(Mat A, MatFactorType ftype, Mat *F)
494d71ae5a4SJacob Faibussowitsch {
4953bf14a46SMatthew Knepley PetscFunctionBegin;
4965f80ce2aSJacob Faibussowitsch PetscCheck(ftype == MAT_FACTOR_CHOLESKY, PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot use PETSc SBAIJ matrices with PaStiX LU, use AIJ matrix");
497688c8ee7SFlorent Pruvost PetscCall(MatGetFactor_pastix(A, ftype, F, MATMPISBAIJ));
498688c8ee7SFlorent Pruvost PetscFunctionReturn(PETSC_SUCCESS);
499688c8ee7SFlorent Pruvost }
50041c8de11SBarry Smith
MatGetFactor_seqsbaij_pastix(Mat A,MatFactorType ftype,Mat * F)501688c8ee7SFlorent Pruvost static PetscErrorCode MatGetFactor_seqsbaij_pastix(Mat A, MatFactorType ftype, Mat *F)
502688c8ee7SFlorent Pruvost {
503688c8ee7SFlorent Pruvost PetscFunctionBegin;
504688c8ee7SFlorent Pruvost PetscCheck(ftype == MAT_FACTOR_CHOLESKY, PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot use PETSc SBAIJ matrices with PaStiX LU, use AIJ matrix");
505688c8ee7SFlorent Pruvost PetscCall(MatGetFactor_pastix(A, ftype, F, MATSEQSBAIJ));
5063ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
5073bf14a46SMatthew Knepley }
508f7a08781SBarry Smith
MatSolverTypeRegister_Pastix(void)509d1f0640dSPierre Jolivet PETSC_INTERN PetscErrorCode MatSolverTypeRegister_Pastix(void)
510d71ae5a4SJacob Faibussowitsch {
51142c9c57cSBarry Smith PetscFunctionBegin;
5129566063dSJacob Faibussowitsch PetscCall(MatSolverTypeRegister(MATSOLVERPASTIX, MATMPIAIJ, MAT_FACTOR_LU, MatGetFactor_mpiaij_pastix));
5139566063dSJacob Faibussowitsch PetscCall(MatSolverTypeRegister(MATSOLVERPASTIX, MATSEQAIJ, MAT_FACTOR_LU, MatGetFactor_seqaij_pastix));
5149566063dSJacob Faibussowitsch PetscCall(MatSolverTypeRegister(MATSOLVERPASTIX, MATMPISBAIJ, MAT_FACTOR_CHOLESKY, MatGetFactor_mpisbaij_pastix));
5159566063dSJacob Faibussowitsch PetscCall(MatSolverTypeRegister(MATSOLVERPASTIX, MATSEQSBAIJ, MAT_FACTOR_CHOLESKY, MatGetFactor_seqsbaij_pastix));
5163ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
51742c9c57cSBarry Smith }
518