xref: /petsc/src/mat/impls/aij/seq/spqr/aijspqr.c (revision 1cc06b555e92f8ec64db10330b8bbd830e5bc876)
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 
10d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatWrapCholmod_SPQR_seqaij(Mat A, PetscBool values, cholmod_sparse *C, PetscBool *aijalloc, PetscBool *valloc)
11d71ae5a4SJacob 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));
753ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
76a2fc1e05SToby Isaac }
77a2fc1e05SToby Isaac 
78d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatFactorGetSolverType_seqaij_SPQR(Mat A, MatSolverType *type)
79d71ae5a4SJacob Faibussowitsch {
80a2fc1e05SToby Isaac   PetscFunctionBegin;
81a2fc1e05SToby Isaac   *type = MATSOLVERSPQR;
823ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
83a2fc1e05SToby Isaac }
84a2fc1e05SToby Isaac 
85a2fc1e05SToby Isaac #define GET_ARRAY_READ  0
86a2fc1e05SToby Isaac #define GET_ARRAY_WRITE 1
87a2fc1e05SToby Isaac 
88d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSolve_SPQR_Internal(Mat F, cholmod_dense *cholB, cholmod_dense **_Y_handle)
89d71ae5a4SJacob 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");
1043ba16761SJacob Faibussowitsch     PetscCallExternal(!cholmod_l_free_dense, &Z_handle, chol->common);
10502ef7dfaSPierre Jolivet   }
106a2fc1e05SToby Isaac   *_Y_handle = Y_handle;
1073ba16761SJacob Faibussowitsch   PetscCallExternal(!cholmod_l_free_dense, &QTB_handle, chol->common);
1083ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
109a2fc1e05SToby Isaac }
110a2fc1e05SToby Isaac 
111d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSolve_SPQR(Mat F, Vec B, Vec X)
112d71ae5a4SJacob 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));
1253ba16761SJacob Faibussowitsch   PetscCallExternal(!cholmod_l_free_dense, &Y_handle, chol->common);
1269566063dSJacob Faibussowitsch   PetscCall(VecUnWrapCholmod(B, GET_ARRAY_READ, &cholB));
1273ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
128a2fc1e05SToby Isaac }
129a2fc1e05SToby Isaac 
130d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMatSolve_SPQR(Mat F, Mat B, Mat X)
131d71ae5a4SJacob 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));
1483ba16761SJacob Faibussowitsch   PetscCallExternal(!cholmod_l_free_dense, &Y_handle, chol->common);
1499566063dSJacob Faibussowitsch   PetscCall(MatDenseUnWrapCholmod(B, GET_ARRAY_READ, &cholB));
1503ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
151a2fc1e05SToby Isaac }
152a2fc1e05SToby Isaac 
153d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSolveTranspose_SPQR_Internal(Mat F, cholmod_dense *cholB, cholmod_dense **_Y_handle)
154d71ae5a4SJacob 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;
1643ba16761SJacob Faibussowitsch   PetscCallExternal(!cholmod_l_free_dense, &RTB_handle, chol->common);
1653ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
166a2fc1e05SToby Isaac }
167a2fc1e05SToby Isaac 
168d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSolveTranspose_SPQR(Mat F, Vec B, Vec X)
169d71ae5a4SJacob 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));
1823ba16761SJacob Faibussowitsch   PetscCallExternal(!cholmod_l_free_dense, &Y_handle, chol->common);
1839566063dSJacob Faibussowitsch   PetscCall(VecUnWrapCholmod(B, GET_ARRAY_READ, &cholB));
1843ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
185a2fc1e05SToby Isaac }
186a2fc1e05SToby Isaac 
187d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMatSolveTranspose_SPQR(Mat F, Mat B, Mat X)
188d71ae5a4SJacob 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));
2053ba16761SJacob Faibussowitsch   PetscCallExternal(!cholmod_l_free_dense, &Y_handle, chol->common);
2069566063dSJacob Faibussowitsch   PetscCall(MatDenseUnWrapCholmod(B, GET_ARRAY_READ, &cholB));
2073ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
208a2fc1e05SToby Isaac }
209a2fc1e05SToby Isaac 
210d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatQRFactorNumeric_SPQR(Mat F, Mat A, const MatFactorInfo *info)
211d71ae5a4SJacob 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   }
2363ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
237a2fc1e05SToby Isaac }
238a2fc1e05SToby Isaac 
239d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode MatQRFactorSymbolic_SPQR(Mat F, Mat A, IS perm, const MatFactorInfo *info)
240d71ae5a4SJacob 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));
2493ba16761SJacob Faibussowitsch   if (PetscDefined(USE_DEBUG)) PetscCallExternal(!cholmod_l_check_sparse, &cholA, chol->common);
2503ba16761SJacob Faibussowitsch   if (chol->spqrfact) PetscCallExternal(!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));
2583ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
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 
2672ef1f0ffSBarry 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 
277*1cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `PCQR`, `PCFactorSetMatSolverType()`, `MatSolverType`
278a2fc1e05SToby Isaac M*/
279a2fc1e05SToby Isaac 
280d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode MatGetFactor_seqaij_spqr(Mat A, MatFactorType ftype, Mat *F)
281d71ae5a4SJacob 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;
3173ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
318a2fc1e05SToby Isaac }
319