xref: /petsc/src/mat/impls/aij/seq/spqr/aijspqr.c (revision d71ae5a4db6382e7f06317b8d368875286fe9008)
1a2fc1e05SToby Isaac 
2a2fc1e05SToby Isaac #include <petscsys.h>
3a2fc1e05SToby Isaac #include <../src/mat/impls/aij/seq/aij.h>
4a2fc1e05SToby Isaac #include <../src/mat/impls/sbaij/seq/cholmod/cholmodimpl.h>
5a2fc1e05SToby Isaac 
6a2fc1e05SToby Isaac EXTERN_C_BEGIN
7a2fc1e05SToby Isaac #include <SuiteSparseQR_C.h>
8a2fc1e05SToby Isaac EXTERN_C_END
9a2fc1e05SToby Isaac 
10*d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatWrapCholmod_SPQR_seqaij(Mat A, PetscBool values, cholmod_sparse *C, PetscBool *aijalloc, PetscBool *valloc)
11*d71ae5a4SJacob Faibussowitsch {
12a2fc1e05SToby Isaac   Mat_SeqAIJ        *aij;
13a2fc1e05SToby Isaac   Mat                AT;
14a2fc1e05SToby Isaac   const PetscScalar *aa;
15a2fc1e05SToby Isaac   PetscScalar       *ca;
16a2fc1e05SToby Isaac   const PetscInt    *ai, *aj;
17a2fc1e05SToby Isaac   PetscInt           n = A->cmap->n, i, j, k, nz;
18a2fc1e05SToby Isaac   SuiteSparse_long  *ci, *cj; /* SuiteSparse_long is the only choice for SPQR */
1902ef7dfaSPierre Jolivet   PetscBool          vain = PETSC_FALSE, flg;
20a2fc1e05SToby Isaac 
21a2fc1e05SToby Isaac   PetscFunctionBegin;
229566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)A, MATNORMALHERMITIAN, &flg));
2365f45395SPierre Jolivet   if (flg) {
249566063dSJacob Faibussowitsch     PetscCall(MatNormalHermitianGetMat(A, &A));
2565f45395SPierre Jolivet   } else if (!PetscDefined(USE_COMPLEX)) {
269566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)A, MATNORMAL, &flg));
2748a46eb9SPierre Jolivet     if (flg) PetscCall(MatNormalGetMat(A, &A));
2865f45395SPierre Jolivet   }
29a2fc1e05SToby Isaac   /* cholmod_sparse is compressed sparse column */
30b94d7dedSBarry Smith   PetscCall(MatIsSymmetric(A, 0.0, &flg));
3102ef7dfaSPierre Jolivet   if (flg) {
329566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)A));
33a2fc1e05SToby Isaac     AT = A;
34a2fc1e05SToby Isaac   } else {
359566063dSJacob Faibussowitsch     PetscCall(MatTranspose(A, MAT_INITIAL_MATRIX, &AT));
36a2fc1e05SToby Isaac   }
37a2fc1e05SToby Isaac   aij = (Mat_SeqAIJ *)AT->data;
38a2fc1e05SToby Isaac   ai  = aij->j;
39a2fc1e05SToby Isaac   aj  = aij->i;
40a2fc1e05SToby Isaac   for (j = 0, nz = 0; j < n; j++) nz += aj[j + 1] - aj[j];
419566063dSJacob Faibussowitsch   PetscCall(PetscMalloc2(n + 1, &cj, nz, &ci));
42a2fc1e05SToby Isaac   if (values) {
43a2fc1e05SToby Isaac     vain = PETSC_TRUE;
449566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(nz, &ca));
459566063dSJacob Faibussowitsch     PetscCall(MatSeqAIJGetArrayRead(AT, &aa));
46a2fc1e05SToby Isaac   }
47a2fc1e05SToby Isaac   for (j = 0, k = 0; j < n; j++) {
48a2fc1e05SToby Isaac     cj[j] = k;
49a2fc1e05SToby Isaac     for (i = aj[j]; i < aj[j + 1]; i++, k++) {
50a2fc1e05SToby Isaac       ci[k] = ai[i];
51a2fc1e05SToby Isaac       if (values) ca[k] = aa[i];
52a2fc1e05SToby Isaac     }
53a2fc1e05SToby Isaac   }
54a2fc1e05SToby Isaac   cj[j]     = k;
55a2fc1e05SToby Isaac   *aijalloc = PETSC_TRUE;
56a2fc1e05SToby Isaac   *valloc   = vain;
5748a46eb9SPierre Jolivet   if (values) PetscCall(MatSeqAIJRestoreArrayRead(AT, &aa));
58a2fc1e05SToby Isaac 
599566063dSJacob Faibussowitsch   PetscCall(PetscMemzero(C, sizeof(*C)));
60a2fc1e05SToby Isaac 
6102ef7dfaSPierre Jolivet   C->nrow   = (size_t)AT->cmap->n;
6202ef7dfaSPierre Jolivet   C->ncol   = (size_t)AT->rmap->n;
63a2fc1e05SToby Isaac   C->nzmax  = (size_t)nz;
64a2fc1e05SToby Isaac   C->p      = cj;
65a2fc1e05SToby Isaac   C->i      = ci;
66a2fc1e05SToby Isaac   C->x      = values ? ca : 0;
67a2fc1e05SToby Isaac   C->stype  = 0;
68a2fc1e05SToby Isaac   C->itype  = CHOLMOD_LONG;
69a2fc1e05SToby Isaac   C->xtype  = values ? CHOLMOD_SCALAR_TYPE : CHOLMOD_PATTERN;
70a2fc1e05SToby Isaac   C->dtype  = CHOLMOD_DOUBLE;
71a2fc1e05SToby Isaac   C->sorted = 1;
72a2fc1e05SToby Isaac   C->packed = 1;
73a2fc1e05SToby Isaac 
749566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&AT));
75a2fc1e05SToby Isaac   PetscFunctionReturn(0);
76a2fc1e05SToby Isaac }
77a2fc1e05SToby Isaac 
78*d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatFactorGetSolverType_seqaij_SPQR(Mat A, MatSolverType *type)
79*d71ae5a4SJacob Faibussowitsch {
80a2fc1e05SToby Isaac   PetscFunctionBegin;
81a2fc1e05SToby Isaac   *type = MATSOLVERSPQR;
82a2fc1e05SToby Isaac   PetscFunctionReturn(0);
83a2fc1e05SToby Isaac }
84a2fc1e05SToby Isaac 
85a2fc1e05SToby Isaac #define GET_ARRAY_READ  0
86a2fc1e05SToby Isaac #define GET_ARRAY_WRITE 1
87a2fc1e05SToby Isaac 
88*d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSolve_SPQR_Internal(Mat F, cholmod_dense *cholB, cholmod_dense **_Y_handle)
89*d71ae5a4SJacob Faibussowitsch {
90a2fc1e05SToby Isaac   Mat_CHOLMOD   *chol     = (Mat_CHOLMOD *)F->data;
9102ef7dfaSPierre Jolivet   cholmod_dense *Y_handle = NULL, *QTB_handle = NULL, *Z_handle = NULL;
92a2fc1e05SToby Isaac 
93a2fc1e05SToby Isaac   PetscFunctionBegin;
9402ef7dfaSPierre Jolivet   if (!chol->normal) {
95a2fc1e05SToby Isaac     QTB_handle = SuiteSparseQR_C_qmult(SPQR_QTX, chol->spqrfact, cholB, chol->common);
9628b400f6SJacob Faibussowitsch     PetscCheck(QTB_handle, PetscObjectComm((PetscObject)F), PETSC_ERR_LIB, "SuiteSparseQR_C_qmult failed");
97a2fc1e05SToby Isaac     Y_handle = SuiteSparseQR_C_solve(SPQR_RETX_EQUALS_B, chol->spqrfact, QTB_handle, chol->common);
9828b400f6SJacob Faibussowitsch     PetscCheck(Y_handle, PetscObjectComm((PetscObject)F), PETSC_ERR_LIB, "SuiteSparseQR_C_solve failed");
9902ef7dfaSPierre Jolivet   } else {
10002ef7dfaSPierre Jolivet     Z_handle = SuiteSparseQR_C_solve(SPQR_RTX_EQUALS_ETB, chol->spqrfact, cholB, chol->common);
10128b400f6SJacob Faibussowitsch     PetscCheck(Z_handle, PetscObjectComm((PetscObject)F), PETSC_ERR_LIB, "SuiteSparseQR_C_solve failed");
10202ef7dfaSPierre Jolivet     Y_handle = SuiteSparseQR_C_solve(SPQR_RETX_EQUALS_B, chol->spqrfact, Z_handle, chol->common);
10328b400f6SJacob Faibussowitsch     PetscCheck(Y_handle, PetscObjectComm((PetscObject)F), PETSC_ERR_LIB, "SuiteSparseQR_C_solve failed");
1049566063dSJacob Faibussowitsch     PetscCall(!cholmod_l_free_dense(&Z_handle, chol->common));
10502ef7dfaSPierre Jolivet   }
106a2fc1e05SToby Isaac   *_Y_handle = Y_handle;
1079566063dSJacob Faibussowitsch   PetscCall(!cholmod_l_free_dense(&QTB_handle, chol->common));
108a2fc1e05SToby Isaac   PetscFunctionReturn(0);
109a2fc1e05SToby Isaac }
110a2fc1e05SToby Isaac 
111*d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSolve_SPQR(Mat F, Vec B, Vec X)
112*d71ae5a4SJacob Faibussowitsch {
113a2fc1e05SToby Isaac   Mat_CHOLMOD  *chol = (Mat_CHOLMOD *)F->data;
114a2fc1e05SToby Isaac   cholmod_dense cholB, *Y_handle = NULL;
115a2fc1e05SToby Isaac   PetscInt      n;
116a2fc1e05SToby Isaac   PetscScalar  *v;
117a2fc1e05SToby Isaac 
118a2fc1e05SToby Isaac   PetscFunctionBegin;
1199566063dSJacob Faibussowitsch   PetscCall(VecWrapCholmod(B, GET_ARRAY_READ, &cholB));
1209566063dSJacob Faibussowitsch   PetscCall(MatSolve_SPQR_Internal(F, &cholB, &Y_handle));
1219566063dSJacob Faibussowitsch   PetscCall(VecGetLocalSize(X, &n));
1229566063dSJacob Faibussowitsch   PetscCall(VecGetArrayWrite(X, &v));
1239566063dSJacob Faibussowitsch   PetscCall(PetscArraycpy(v, (PetscScalar *)(Y_handle->x), n));
1249566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayWrite(X, &v));
1259566063dSJacob Faibussowitsch   PetscCall(!cholmod_l_free_dense(&Y_handle, chol->common));
1269566063dSJacob Faibussowitsch   PetscCall(VecUnWrapCholmod(B, GET_ARRAY_READ, &cholB));
127a2fc1e05SToby Isaac   PetscFunctionReturn(0);
128a2fc1e05SToby Isaac }
129a2fc1e05SToby Isaac 
130*d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMatSolve_SPQR(Mat F, Mat B, Mat X)
131*d71ae5a4SJacob Faibussowitsch {
132a2fc1e05SToby Isaac   Mat_CHOLMOD  *chol = (Mat_CHOLMOD *)F->data;
133a2fc1e05SToby Isaac   cholmod_dense cholB, *Y_handle = NULL;
134a2fc1e05SToby Isaac   PetscScalar  *v;
135a2fc1e05SToby Isaac   PetscInt      lda;
136a2fc1e05SToby Isaac 
137a2fc1e05SToby Isaac   PetscFunctionBegin;
1389566063dSJacob Faibussowitsch   PetscCall(MatDenseWrapCholmod(B, GET_ARRAY_READ, &cholB));
1399566063dSJacob Faibussowitsch   PetscCall(MatSolve_SPQR_Internal(F, &cholB, &Y_handle));
1409566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayWrite(X, &v));
1419566063dSJacob Faibussowitsch   PetscCall(MatDenseGetLDA(X, &lda));
142a2fc1e05SToby Isaac   if ((size_t)lda == Y_handle->d) {
1439566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(v, (PetscScalar *)(Y_handle->x), lda * Y_handle->ncol));
144a2fc1e05SToby Isaac   } else {
14548a46eb9SPierre Jolivet     for (size_t j = 0; j < Y_handle->ncol; j++) PetscCall(PetscArraycpy(&v[j * lda], &(((PetscScalar *)Y_handle->x)[j * Y_handle->d]), Y_handle->nrow));
146a2fc1e05SToby Isaac   }
1479566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayWrite(X, &v));
1489566063dSJacob Faibussowitsch   PetscCall(!cholmod_l_free_dense(&Y_handle, chol->common));
1499566063dSJacob Faibussowitsch   PetscCall(MatDenseUnWrapCholmod(B, GET_ARRAY_READ, &cholB));
150a2fc1e05SToby Isaac   PetscFunctionReturn(0);
151a2fc1e05SToby Isaac }
152a2fc1e05SToby Isaac 
153*d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSolveTranspose_SPQR_Internal(Mat F, cholmod_dense *cholB, cholmod_dense **_Y_handle)
154*d71ae5a4SJacob Faibussowitsch {
155a2fc1e05SToby Isaac   Mat_CHOLMOD   *chol     = (Mat_CHOLMOD *)F->data;
156a2fc1e05SToby Isaac   cholmod_dense *Y_handle = NULL, *RTB_handle = NULL;
157a2fc1e05SToby Isaac 
158a2fc1e05SToby Isaac   PetscFunctionBegin;
159a2fc1e05SToby Isaac   RTB_handle = SuiteSparseQR_C_solve(SPQR_RTX_EQUALS_ETB, chol->spqrfact, cholB, chol->common);
16028b400f6SJacob Faibussowitsch   PetscCheck(RTB_handle, PetscObjectComm((PetscObject)F), PETSC_ERR_LIB, "SuiteSparseQR_C_solve failed");
161a2fc1e05SToby Isaac   Y_handle = SuiteSparseQR_C_qmult(SPQR_QX, chol->spqrfact, RTB_handle, chol->common);
16228b400f6SJacob Faibussowitsch   PetscCheck(Y_handle, PetscObjectComm((PetscObject)F), PETSC_ERR_LIB, "SuiteSparseQR_C_qmult failed");
163a2fc1e05SToby Isaac   *_Y_handle = Y_handle;
1649566063dSJacob Faibussowitsch   PetscCall(!cholmod_l_free_dense(&RTB_handle, chol->common));
165a2fc1e05SToby Isaac   PetscFunctionReturn(0);
166a2fc1e05SToby Isaac }
167a2fc1e05SToby Isaac 
168*d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSolveTranspose_SPQR(Mat F, Vec B, Vec X)
169*d71ae5a4SJacob Faibussowitsch {
170a2fc1e05SToby Isaac   Mat_CHOLMOD  *chol = (Mat_CHOLMOD *)F->data;
171a2fc1e05SToby Isaac   cholmod_dense cholB, *Y_handle = NULL;
172a2fc1e05SToby Isaac   PetscInt      n;
173a2fc1e05SToby Isaac   PetscScalar  *v;
174a2fc1e05SToby Isaac 
175a2fc1e05SToby Isaac   PetscFunctionBegin;
1769566063dSJacob Faibussowitsch   PetscCall(VecWrapCholmod(B, GET_ARRAY_READ, &cholB));
1779566063dSJacob Faibussowitsch   PetscCall(MatSolveTranspose_SPQR_Internal(F, &cholB, &Y_handle));
1789566063dSJacob Faibussowitsch   PetscCall(VecGetLocalSize(X, &n));
1799566063dSJacob Faibussowitsch   PetscCall(VecGetArrayWrite(X, &v));
1809566063dSJacob Faibussowitsch   PetscCall(PetscArraycpy(v, (PetscScalar *)Y_handle->x, n));
1819566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayWrite(X, &v));
1829566063dSJacob Faibussowitsch   PetscCall(!cholmod_l_free_dense(&Y_handle, chol->common));
1839566063dSJacob Faibussowitsch   PetscCall(VecUnWrapCholmod(B, GET_ARRAY_READ, &cholB));
184a2fc1e05SToby Isaac   PetscFunctionReturn(0);
185a2fc1e05SToby Isaac }
186a2fc1e05SToby Isaac 
187*d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMatSolveTranspose_SPQR(Mat F, Mat B, Mat X)
188*d71ae5a4SJacob Faibussowitsch {
189a2fc1e05SToby Isaac   Mat_CHOLMOD  *chol = (Mat_CHOLMOD *)F->data;
190a2fc1e05SToby Isaac   cholmod_dense cholB, *Y_handle = NULL;
191a2fc1e05SToby Isaac   PetscScalar  *v;
192a2fc1e05SToby Isaac   PetscInt      lda;
193a2fc1e05SToby Isaac 
194a2fc1e05SToby Isaac   PetscFunctionBegin;
1959566063dSJacob Faibussowitsch   PetscCall(MatDenseWrapCholmod(B, GET_ARRAY_READ, &cholB));
1969566063dSJacob Faibussowitsch   PetscCall(MatSolveTranspose_SPQR_Internal(F, &cholB, &Y_handle));
1979566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayWrite(X, &v));
1989566063dSJacob Faibussowitsch   PetscCall(MatDenseGetLDA(X, &lda));
199a2fc1e05SToby Isaac   if ((size_t)lda == Y_handle->d) {
2009566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(v, (PetscScalar *)Y_handle->x, lda * Y_handle->ncol));
201a2fc1e05SToby Isaac   } else {
20248a46eb9SPierre Jolivet     for (size_t j = 0; j < Y_handle->ncol; j++) PetscCall(PetscArraycpy(&v[j * lda], &(((PetscScalar *)Y_handle->x)[j * Y_handle->d]), Y_handle->nrow));
203a2fc1e05SToby Isaac   }
2049566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayWrite(X, &v));
2059566063dSJacob Faibussowitsch   PetscCall(!cholmod_l_free_dense(&Y_handle, chol->common));
2069566063dSJacob Faibussowitsch   PetscCall(MatDenseUnWrapCholmod(B, GET_ARRAY_READ, &cholB));
207a2fc1e05SToby Isaac   PetscFunctionReturn(0);
208a2fc1e05SToby Isaac }
209a2fc1e05SToby Isaac 
210*d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatQRFactorNumeric_SPQR(Mat F, Mat A, const MatFactorInfo *info)
211*d71ae5a4SJacob Faibussowitsch {
212a2fc1e05SToby Isaac   Mat_CHOLMOD   *chol = (Mat_CHOLMOD *)F->data;
213a2fc1e05SToby Isaac   cholmod_sparse cholA;
21465f45395SPierre Jolivet   PetscBool      aijalloc, valloc;
215d0609cedSBarry Smith   int            err;
216a2fc1e05SToby Isaac 
217a2fc1e05SToby Isaac   PetscFunctionBegin;
2189566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)A, MATNORMALHERMITIAN, &chol->normal));
21948a46eb9SPierre Jolivet   if (!chol->normal && !PetscDefined(USE_COMPLEX)) PetscCall(PetscObjectTypeCompare((PetscObject)A, MATNORMAL, &chol->normal));
2209566063dSJacob Faibussowitsch   PetscCall((*chol->Wrap)(A, PETSC_TRUE, &cholA, &aijalloc, &valloc));
221d0609cedSBarry Smith   err = !SuiteSparseQR_C_numeric(PETSC_SMALL, &cholA, chol->spqrfact, chol->common);
222d0609cedSBarry Smith   PetscCheck(!err, PetscObjectComm((PetscObject)F), PETSC_ERR_LIB, "SPQR factorization failed with status %d", chol->common->status);
223a2fc1e05SToby Isaac 
2249566063dSJacob Faibussowitsch   if (aijalloc) PetscCall(PetscFree2(cholA.p, cholA.i));
2259566063dSJacob Faibussowitsch   if (valloc) PetscCall(PetscFree(cholA.x));
226a2fc1e05SToby Isaac 
227a2fc1e05SToby Isaac   F->ops->solve    = MatSolve_SPQR;
228a2fc1e05SToby Isaac   F->ops->matsolve = MatMatSolve_SPQR;
22902ef7dfaSPierre Jolivet   if (chol->normal) {
23002ef7dfaSPierre Jolivet     F->ops->solvetranspose    = MatSolve_SPQR;
23102ef7dfaSPierre Jolivet     F->ops->matsolvetranspose = MatMatSolve_SPQR;
23202ef7dfaSPierre Jolivet   } else if (A->cmap->n == A->rmap->n) {
233a2fc1e05SToby Isaac     F->ops->solvetranspose    = MatSolveTranspose_SPQR;
234a2fc1e05SToby Isaac     F->ops->matsolvetranspose = MatMatSolveTranspose_SPQR;
235a2fc1e05SToby Isaac   }
236a2fc1e05SToby Isaac   PetscFunctionReturn(0);
237a2fc1e05SToby Isaac }
238a2fc1e05SToby Isaac 
239*d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode MatQRFactorSymbolic_SPQR(Mat F, Mat A, IS perm, const MatFactorInfo *info)
240*d71ae5a4SJacob Faibussowitsch {
241a2fc1e05SToby Isaac   Mat_CHOLMOD   *chol = (Mat_CHOLMOD *)F->data;
242a2fc1e05SToby Isaac   cholmod_sparse cholA;
24365f45395SPierre Jolivet   PetscBool      aijalloc, valloc;
244a2fc1e05SToby Isaac 
245a2fc1e05SToby Isaac   PetscFunctionBegin;
2469566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)A, MATNORMALHERMITIAN, &chol->normal));
24748a46eb9SPierre Jolivet   if (!chol->normal && !PetscDefined(USE_COMPLEX)) PetscCall(PetscObjectTypeCompare((PetscObject)A, MATNORMAL, &chol->normal));
2489566063dSJacob Faibussowitsch   PetscCall((*chol->Wrap)(A, PETSC_TRUE, &cholA, &aijalloc, &valloc));
24948a46eb9SPierre Jolivet   if (PetscDefined(USE_DEBUG)) PetscCall(!cholmod_l_check_sparse(&cholA, chol->common));
25048a46eb9SPierre Jolivet   if (chol->spqrfact) PetscCall(!SuiteSparseQR_C_free(&chol->spqrfact, chol->common));
251d0f82a0bSPierre Jolivet   chol->spqrfact = SuiteSparseQR_C_symbolic(SPQR_ORDERING_DEFAULT, 1, &cholA, chol->common);
25228b400f6SJacob Faibussowitsch   PetscCheck(chol->spqrfact, PetscObjectComm((PetscObject)F), PETSC_ERR_LIB, "CHOLMOD analysis failed using internal ordering with status %d", chol->common->status);
253a2fc1e05SToby Isaac 
2549566063dSJacob Faibussowitsch   if (aijalloc) PetscCall(PetscFree2(cholA.p, cholA.i));
2559566063dSJacob Faibussowitsch   if (valloc) PetscCall(PetscFree(cholA.x));
256a2fc1e05SToby Isaac 
2579566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)F, "MatQRFactorNumeric_C", MatQRFactorNumeric_SPQR));
258a2fc1e05SToby Isaac   PetscFunctionReturn(0);
259a2fc1e05SToby Isaac }
260a2fc1e05SToby Isaac 
261a2fc1e05SToby Isaac /*MC
262a2fc1e05SToby Isaac   MATSOLVERSPQR
263a2fc1e05SToby Isaac 
26411a5261eSBarry Smith   A matrix type providing direct solvers, QR factorizations, for sequential matrices
265a2fc1e05SToby Isaac   via the external package SPQR.
266a2fc1e05SToby Isaac 
26711a5261eSBarry Smith   Use ./configure --download-suitesparse to install PETSc to use SPQR
268a2fc1e05SToby Isaac 
26911a5261eSBarry Smith   Consult SPQR documentation for more information about the common parameters
270a2fc1e05SToby Isaac   which correspond to the options database keys below.
271a2fc1e05SToby Isaac 
272a2fc1e05SToby Isaac    Level: beginner
273a2fc1e05SToby Isaac 
27411a5261eSBarry Smith    Note:
27511a5261eSBarry Smith    SPQR is part of SuiteSparse http://faculty.cse.tamu.edu/davis/suitesparse.html
276a2fc1e05SToby Isaac 
277db781477SPatrick Sanan .seealso: `PCQR`, `PCFactorSetMatSolverType()`, `MatSolverType`
278a2fc1e05SToby Isaac M*/
279a2fc1e05SToby Isaac 
280*d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode MatGetFactor_seqaij_spqr(Mat A, MatFactorType ftype, Mat *F)
281*d71ae5a4SJacob Faibussowitsch {
282a2fc1e05SToby Isaac   Mat          B;
283a2fc1e05SToby Isaac   Mat_CHOLMOD *chol;
284a2fc1e05SToby Isaac   PetscInt     m = A->rmap->n, n = A->cmap->n;
285a2fc1e05SToby Isaac   const char  *prefix;
286a2fc1e05SToby Isaac 
287a2fc1e05SToby Isaac   PetscFunctionBegin;
288a2fc1e05SToby Isaac   /* Create the factorization matrix F */
2899566063dSJacob Faibussowitsch   PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &B));
2909566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(B, PETSC_DECIDE, PETSC_DECIDE, m, n));
2919566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy("spqr", &((PetscObject)B)->type_name));
2929566063dSJacob Faibussowitsch   PetscCall(MatGetOptionsPrefix(A, &prefix));
2939566063dSJacob Faibussowitsch   PetscCall(MatSetOptionsPrefix(B, prefix));
2949566063dSJacob Faibussowitsch   PetscCall(MatSetUp(B));
2954dfa11a4SJacob Faibussowitsch   PetscCall(PetscNew(&chol));
296a2fc1e05SToby Isaac 
297a2fc1e05SToby Isaac   chol->Wrap = MatWrapCholmod_SPQR_seqaij;
298a2fc1e05SToby Isaac   B->data    = chol;
299a2fc1e05SToby Isaac 
300a2fc1e05SToby Isaac   B->ops->getinfo = MatGetInfo_CHOLMOD;
301a2fc1e05SToby Isaac   B->ops->view    = MatView_CHOLMOD;
302a2fc1e05SToby Isaac   B->ops->destroy = MatDestroy_CHOLMOD;
303a2fc1e05SToby Isaac 
3049566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatFactorGetSolverType_C", MatFactorGetSolverType_seqaij_SPQR));
3059566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatQRFactorSymbolic_C", MatQRFactorSymbolic_SPQR));
306a2fc1e05SToby Isaac 
307a2fc1e05SToby Isaac   B->factortype   = MAT_FACTOR_QR;
308a2fc1e05SToby Isaac   B->assembled    = PETSC_TRUE;
309a2fc1e05SToby Isaac   B->preallocated = PETSC_TRUE;
310a2fc1e05SToby Isaac 
3119566063dSJacob Faibussowitsch   PetscCall(PetscFree(B->solvertype));
3129566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(MATSOLVERCHOLMOD, &B->solvertype));
313a2fc1e05SToby Isaac   B->canuseordering = PETSC_FALSE;
3149566063dSJacob Faibussowitsch   PetscCall(CholmodStart(B));
315a2fc1e05SToby Isaac   chol->common->itype = CHOLMOD_LONG;
316a2fc1e05SToby Isaac   *F                  = B;
317a2fc1e05SToby Isaac   PetscFunctionReturn(0);
318a2fc1e05SToby Isaac }
319