xref: /petsc/src/mat/impls/aij/seq/spqr/aijspqr.c (revision 11a5261e40035b7c793f2783a2ba6c7cd4f3b077)
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 
109371c9d4SSatish Balay static PetscErrorCode MatWrapCholmod_SPQR_seqaij(Mat A, PetscBool values, cholmod_sparse *C, PetscBool *aijalloc, PetscBool *valloc) {
11a2fc1e05SToby Isaac   Mat_SeqAIJ        *aij;
12a2fc1e05SToby Isaac   Mat                AT;
13a2fc1e05SToby Isaac   const PetscScalar *aa;
14a2fc1e05SToby Isaac   PetscScalar       *ca;
15a2fc1e05SToby Isaac   const PetscInt    *ai, *aj;
16a2fc1e05SToby Isaac   PetscInt           n = A->cmap->n, i, j, k, nz;
17a2fc1e05SToby Isaac   SuiteSparse_long  *ci, *cj; /* SuiteSparse_long is the only choice for SPQR */
1802ef7dfaSPierre Jolivet   PetscBool          vain = PETSC_FALSE, flg;
19a2fc1e05SToby Isaac 
20a2fc1e05SToby Isaac   PetscFunctionBegin;
219566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)A, MATNORMALHERMITIAN, &flg));
2265f45395SPierre Jolivet   if (flg) {
239566063dSJacob Faibussowitsch     PetscCall(MatNormalHermitianGetMat(A, &A));
2465f45395SPierre Jolivet   } else if (!PetscDefined(USE_COMPLEX)) {
259566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)A, MATNORMAL, &flg));
2648a46eb9SPierre Jolivet     if (flg) PetscCall(MatNormalGetMat(A, &A));
2765f45395SPierre Jolivet   }
28a2fc1e05SToby Isaac   /* cholmod_sparse is compressed sparse column */
29b94d7dedSBarry Smith   PetscCall(MatIsSymmetric(A, 0.0, &flg));
3002ef7dfaSPierre Jolivet   if (flg) {
319566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)A));
32a2fc1e05SToby Isaac     AT = A;
33a2fc1e05SToby Isaac   } else {
349566063dSJacob Faibussowitsch     PetscCall(MatTranspose(A, MAT_INITIAL_MATRIX, &AT));
35a2fc1e05SToby Isaac   }
36a2fc1e05SToby Isaac   aij = (Mat_SeqAIJ *)AT->data;
37a2fc1e05SToby Isaac   ai  = aij->j;
38a2fc1e05SToby Isaac   aj  = aij->i;
39a2fc1e05SToby Isaac   for (j = 0, nz = 0; j < n; j++) nz += aj[j + 1] - aj[j];
409566063dSJacob Faibussowitsch   PetscCall(PetscMalloc2(n + 1, &cj, nz, &ci));
41a2fc1e05SToby Isaac   if (values) {
42a2fc1e05SToby Isaac     vain = PETSC_TRUE;
439566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(nz, &ca));
449566063dSJacob Faibussowitsch     PetscCall(MatSeqAIJGetArrayRead(AT, &aa));
45a2fc1e05SToby Isaac   }
46a2fc1e05SToby Isaac   for (j = 0, k = 0; j < n; j++) {
47a2fc1e05SToby Isaac     cj[j] = k;
48a2fc1e05SToby Isaac     for (i = aj[j]; i < aj[j + 1]; i++, k++) {
49a2fc1e05SToby Isaac       ci[k] = ai[i];
50a2fc1e05SToby Isaac       if (values) ca[k] = aa[i];
51a2fc1e05SToby Isaac     }
52a2fc1e05SToby Isaac   }
53a2fc1e05SToby Isaac   cj[j]     = k;
54a2fc1e05SToby Isaac   *aijalloc = PETSC_TRUE;
55a2fc1e05SToby Isaac   *valloc   = vain;
5648a46eb9SPierre Jolivet   if (values) PetscCall(MatSeqAIJRestoreArrayRead(AT, &aa));
57a2fc1e05SToby Isaac 
589566063dSJacob Faibussowitsch   PetscCall(PetscMemzero(C, sizeof(*C)));
59a2fc1e05SToby Isaac 
6002ef7dfaSPierre Jolivet   C->nrow   = (size_t)AT->cmap->n;
6102ef7dfaSPierre Jolivet   C->ncol   = (size_t)AT->rmap->n;
62a2fc1e05SToby Isaac   C->nzmax  = (size_t)nz;
63a2fc1e05SToby Isaac   C->p      = cj;
64a2fc1e05SToby Isaac   C->i      = ci;
65a2fc1e05SToby Isaac   C->x      = values ? ca : 0;
66a2fc1e05SToby Isaac   C->stype  = 0;
67a2fc1e05SToby Isaac   C->itype  = CHOLMOD_LONG;
68a2fc1e05SToby Isaac   C->xtype  = values ? CHOLMOD_SCALAR_TYPE : CHOLMOD_PATTERN;
69a2fc1e05SToby Isaac   C->dtype  = CHOLMOD_DOUBLE;
70a2fc1e05SToby Isaac   C->sorted = 1;
71a2fc1e05SToby Isaac   C->packed = 1;
72a2fc1e05SToby Isaac 
739566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&AT));
74a2fc1e05SToby Isaac   PetscFunctionReturn(0);
75a2fc1e05SToby Isaac }
76a2fc1e05SToby Isaac 
779371c9d4SSatish Balay static PetscErrorCode MatFactorGetSolverType_seqaij_SPQR(Mat A, MatSolverType *type) {
78a2fc1e05SToby Isaac   PetscFunctionBegin;
79a2fc1e05SToby Isaac   *type = MATSOLVERSPQR;
80a2fc1e05SToby Isaac   PetscFunctionReturn(0);
81a2fc1e05SToby Isaac }
82a2fc1e05SToby Isaac 
83a2fc1e05SToby Isaac #define GET_ARRAY_READ  0
84a2fc1e05SToby Isaac #define GET_ARRAY_WRITE 1
85a2fc1e05SToby Isaac 
869371c9d4SSatish Balay static PetscErrorCode MatSolve_SPQR_Internal(Mat F, cholmod_dense *cholB, cholmod_dense **_Y_handle) {
87a2fc1e05SToby Isaac   Mat_CHOLMOD   *chol     = (Mat_CHOLMOD *)F->data;
8802ef7dfaSPierre Jolivet   cholmod_dense *Y_handle = NULL, *QTB_handle = NULL, *Z_handle = NULL;
89a2fc1e05SToby Isaac 
90a2fc1e05SToby Isaac   PetscFunctionBegin;
9102ef7dfaSPierre Jolivet   if (!chol->normal) {
92a2fc1e05SToby Isaac     QTB_handle = SuiteSparseQR_C_qmult(SPQR_QTX, chol->spqrfact, cholB, chol->common);
9328b400f6SJacob Faibussowitsch     PetscCheck(QTB_handle, PetscObjectComm((PetscObject)F), PETSC_ERR_LIB, "SuiteSparseQR_C_qmult failed");
94a2fc1e05SToby Isaac     Y_handle = SuiteSparseQR_C_solve(SPQR_RETX_EQUALS_B, chol->spqrfact, QTB_handle, chol->common);
9528b400f6SJacob Faibussowitsch     PetscCheck(Y_handle, PetscObjectComm((PetscObject)F), PETSC_ERR_LIB, "SuiteSparseQR_C_solve failed");
9602ef7dfaSPierre Jolivet   } else {
9702ef7dfaSPierre Jolivet     Z_handle = SuiteSparseQR_C_solve(SPQR_RTX_EQUALS_ETB, chol->spqrfact, cholB, chol->common);
9828b400f6SJacob Faibussowitsch     PetscCheck(Z_handle, PetscObjectComm((PetscObject)F), PETSC_ERR_LIB, "SuiteSparseQR_C_solve failed");
9902ef7dfaSPierre Jolivet     Y_handle = SuiteSparseQR_C_solve(SPQR_RETX_EQUALS_B, chol->spqrfact, Z_handle, chol->common);
10028b400f6SJacob Faibussowitsch     PetscCheck(Y_handle, PetscObjectComm((PetscObject)F), PETSC_ERR_LIB, "SuiteSparseQR_C_solve failed");
1019566063dSJacob Faibussowitsch     PetscCall(!cholmod_l_free_dense(&Z_handle, chol->common));
10202ef7dfaSPierre Jolivet   }
103a2fc1e05SToby Isaac   *_Y_handle = Y_handle;
1049566063dSJacob Faibussowitsch   PetscCall(!cholmod_l_free_dense(&QTB_handle, chol->common));
105a2fc1e05SToby Isaac   PetscFunctionReturn(0);
106a2fc1e05SToby Isaac }
107a2fc1e05SToby Isaac 
1089371c9d4SSatish Balay static PetscErrorCode MatSolve_SPQR(Mat F, Vec B, Vec X) {
109a2fc1e05SToby Isaac   Mat_CHOLMOD  *chol = (Mat_CHOLMOD *)F->data;
110a2fc1e05SToby Isaac   cholmod_dense cholB, *Y_handle = NULL;
111a2fc1e05SToby Isaac   PetscInt      n;
112a2fc1e05SToby Isaac   PetscScalar  *v;
113a2fc1e05SToby Isaac 
114a2fc1e05SToby Isaac   PetscFunctionBegin;
1159566063dSJacob Faibussowitsch   PetscCall(VecWrapCholmod(B, GET_ARRAY_READ, &cholB));
1169566063dSJacob Faibussowitsch   PetscCall(MatSolve_SPQR_Internal(F, &cholB, &Y_handle));
1179566063dSJacob Faibussowitsch   PetscCall(VecGetLocalSize(X, &n));
1189566063dSJacob Faibussowitsch   PetscCall(VecGetArrayWrite(X, &v));
1199566063dSJacob Faibussowitsch   PetscCall(PetscArraycpy(v, (PetscScalar *)(Y_handle->x), n));
1209566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayWrite(X, &v));
1219566063dSJacob Faibussowitsch   PetscCall(!cholmod_l_free_dense(&Y_handle, chol->common));
1229566063dSJacob Faibussowitsch   PetscCall(VecUnWrapCholmod(B, GET_ARRAY_READ, &cholB));
123a2fc1e05SToby Isaac   PetscFunctionReturn(0);
124a2fc1e05SToby Isaac }
125a2fc1e05SToby Isaac 
1269371c9d4SSatish Balay static PetscErrorCode MatMatSolve_SPQR(Mat F, Mat B, Mat X) {
127a2fc1e05SToby Isaac   Mat_CHOLMOD  *chol = (Mat_CHOLMOD *)F->data;
128a2fc1e05SToby Isaac   cholmod_dense cholB, *Y_handle = NULL;
129a2fc1e05SToby Isaac   PetscScalar  *v;
130a2fc1e05SToby Isaac   PetscInt      lda;
131a2fc1e05SToby Isaac 
132a2fc1e05SToby Isaac   PetscFunctionBegin;
1339566063dSJacob Faibussowitsch   PetscCall(MatDenseWrapCholmod(B, GET_ARRAY_READ, &cholB));
1349566063dSJacob Faibussowitsch   PetscCall(MatSolve_SPQR_Internal(F, &cholB, &Y_handle));
1359566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayWrite(X, &v));
1369566063dSJacob Faibussowitsch   PetscCall(MatDenseGetLDA(X, &lda));
137a2fc1e05SToby Isaac   if ((size_t)lda == Y_handle->d) {
1389566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(v, (PetscScalar *)(Y_handle->x), lda * Y_handle->ncol));
139a2fc1e05SToby Isaac   } else {
14048a46eb9SPierre 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));
141a2fc1e05SToby Isaac   }
1429566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayWrite(X, &v));
1439566063dSJacob Faibussowitsch   PetscCall(!cholmod_l_free_dense(&Y_handle, chol->common));
1449566063dSJacob Faibussowitsch   PetscCall(MatDenseUnWrapCholmod(B, GET_ARRAY_READ, &cholB));
145a2fc1e05SToby Isaac   PetscFunctionReturn(0);
146a2fc1e05SToby Isaac }
147a2fc1e05SToby Isaac 
1489371c9d4SSatish Balay static PetscErrorCode MatSolveTranspose_SPQR_Internal(Mat F, cholmod_dense *cholB, cholmod_dense **_Y_handle) {
149a2fc1e05SToby Isaac   Mat_CHOLMOD   *chol     = (Mat_CHOLMOD *)F->data;
150a2fc1e05SToby Isaac   cholmod_dense *Y_handle = NULL, *RTB_handle = NULL;
151a2fc1e05SToby Isaac 
152a2fc1e05SToby Isaac   PetscFunctionBegin;
153a2fc1e05SToby Isaac   RTB_handle = SuiteSparseQR_C_solve(SPQR_RTX_EQUALS_ETB, chol->spqrfact, cholB, chol->common);
15428b400f6SJacob Faibussowitsch   PetscCheck(RTB_handle, PetscObjectComm((PetscObject)F), PETSC_ERR_LIB, "SuiteSparseQR_C_solve failed");
155a2fc1e05SToby Isaac   Y_handle = SuiteSparseQR_C_qmult(SPQR_QX, chol->spqrfact, RTB_handle, chol->common);
15628b400f6SJacob Faibussowitsch   PetscCheck(Y_handle, PetscObjectComm((PetscObject)F), PETSC_ERR_LIB, "SuiteSparseQR_C_qmult failed");
157a2fc1e05SToby Isaac   *_Y_handle = Y_handle;
1589566063dSJacob Faibussowitsch   PetscCall(!cholmod_l_free_dense(&RTB_handle, chol->common));
159a2fc1e05SToby Isaac   PetscFunctionReturn(0);
160a2fc1e05SToby Isaac }
161a2fc1e05SToby Isaac 
1629371c9d4SSatish Balay static PetscErrorCode MatSolveTranspose_SPQR(Mat F, Vec B, Vec X) {
163a2fc1e05SToby Isaac   Mat_CHOLMOD  *chol = (Mat_CHOLMOD *)F->data;
164a2fc1e05SToby Isaac   cholmod_dense cholB, *Y_handle = NULL;
165a2fc1e05SToby Isaac   PetscInt      n;
166a2fc1e05SToby Isaac   PetscScalar  *v;
167a2fc1e05SToby Isaac 
168a2fc1e05SToby Isaac   PetscFunctionBegin;
1699566063dSJacob Faibussowitsch   PetscCall(VecWrapCholmod(B, GET_ARRAY_READ, &cholB));
1709566063dSJacob Faibussowitsch   PetscCall(MatSolveTranspose_SPQR_Internal(F, &cholB, &Y_handle));
1719566063dSJacob Faibussowitsch   PetscCall(VecGetLocalSize(X, &n));
1729566063dSJacob Faibussowitsch   PetscCall(VecGetArrayWrite(X, &v));
1739566063dSJacob Faibussowitsch   PetscCall(PetscArraycpy(v, (PetscScalar *)Y_handle->x, n));
1749566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayWrite(X, &v));
1759566063dSJacob Faibussowitsch   PetscCall(!cholmod_l_free_dense(&Y_handle, chol->common));
1769566063dSJacob Faibussowitsch   PetscCall(VecUnWrapCholmod(B, GET_ARRAY_READ, &cholB));
177a2fc1e05SToby Isaac   PetscFunctionReturn(0);
178a2fc1e05SToby Isaac }
179a2fc1e05SToby Isaac 
1809371c9d4SSatish Balay static PetscErrorCode MatMatSolveTranspose_SPQR(Mat F, Mat B, Mat X) {
181a2fc1e05SToby Isaac   Mat_CHOLMOD  *chol = (Mat_CHOLMOD *)F->data;
182a2fc1e05SToby Isaac   cholmod_dense cholB, *Y_handle = NULL;
183a2fc1e05SToby Isaac   PetscScalar  *v;
184a2fc1e05SToby Isaac   PetscInt      lda;
185a2fc1e05SToby Isaac 
186a2fc1e05SToby Isaac   PetscFunctionBegin;
1879566063dSJacob Faibussowitsch   PetscCall(MatDenseWrapCholmod(B, GET_ARRAY_READ, &cholB));
1889566063dSJacob Faibussowitsch   PetscCall(MatSolveTranspose_SPQR_Internal(F, &cholB, &Y_handle));
1899566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayWrite(X, &v));
1909566063dSJacob Faibussowitsch   PetscCall(MatDenseGetLDA(X, &lda));
191a2fc1e05SToby Isaac   if ((size_t)lda == Y_handle->d) {
1929566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(v, (PetscScalar *)Y_handle->x, lda * Y_handle->ncol));
193a2fc1e05SToby Isaac   } else {
19448a46eb9SPierre 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));
195a2fc1e05SToby Isaac   }
1969566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayWrite(X, &v));
1979566063dSJacob Faibussowitsch   PetscCall(!cholmod_l_free_dense(&Y_handle, chol->common));
1989566063dSJacob Faibussowitsch   PetscCall(MatDenseUnWrapCholmod(B, GET_ARRAY_READ, &cholB));
199a2fc1e05SToby Isaac   PetscFunctionReturn(0);
200a2fc1e05SToby Isaac }
201a2fc1e05SToby Isaac 
2029371c9d4SSatish Balay static PetscErrorCode MatQRFactorNumeric_SPQR(Mat F, Mat A, const MatFactorInfo *info) {
203a2fc1e05SToby Isaac   Mat_CHOLMOD   *chol = (Mat_CHOLMOD *)F->data;
204a2fc1e05SToby Isaac   cholmod_sparse cholA;
20565f45395SPierre Jolivet   PetscBool      aijalloc, valloc;
206d0609cedSBarry Smith   int            err;
207a2fc1e05SToby Isaac 
208a2fc1e05SToby Isaac   PetscFunctionBegin;
2099566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)A, MATNORMALHERMITIAN, &chol->normal));
21048a46eb9SPierre Jolivet   if (!chol->normal && !PetscDefined(USE_COMPLEX)) PetscCall(PetscObjectTypeCompare((PetscObject)A, MATNORMAL, &chol->normal));
2119566063dSJacob Faibussowitsch   PetscCall((*chol->Wrap)(A, PETSC_TRUE, &cholA, &aijalloc, &valloc));
212d0609cedSBarry Smith   err = !SuiteSparseQR_C_numeric(PETSC_SMALL, &cholA, chol->spqrfact, chol->common);
213d0609cedSBarry Smith   PetscCheck(!err, PetscObjectComm((PetscObject)F), PETSC_ERR_LIB, "SPQR factorization failed with status %d", chol->common->status);
214a2fc1e05SToby Isaac 
2159566063dSJacob Faibussowitsch   if (aijalloc) PetscCall(PetscFree2(cholA.p, cholA.i));
2169566063dSJacob Faibussowitsch   if (valloc) PetscCall(PetscFree(cholA.x));
217a2fc1e05SToby Isaac 
218a2fc1e05SToby Isaac   F->ops->solve    = MatSolve_SPQR;
219a2fc1e05SToby Isaac   F->ops->matsolve = MatMatSolve_SPQR;
22002ef7dfaSPierre Jolivet   if (chol->normal) {
22102ef7dfaSPierre Jolivet     F->ops->solvetranspose    = MatSolve_SPQR;
22202ef7dfaSPierre Jolivet     F->ops->matsolvetranspose = MatMatSolve_SPQR;
22302ef7dfaSPierre Jolivet   } else if (A->cmap->n == A->rmap->n) {
224a2fc1e05SToby Isaac     F->ops->solvetranspose    = MatSolveTranspose_SPQR;
225a2fc1e05SToby Isaac     F->ops->matsolvetranspose = MatMatSolveTranspose_SPQR;
226a2fc1e05SToby Isaac   }
227a2fc1e05SToby Isaac   PetscFunctionReturn(0);
228a2fc1e05SToby Isaac }
229a2fc1e05SToby Isaac 
2309371c9d4SSatish Balay PETSC_INTERN PetscErrorCode MatQRFactorSymbolic_SPQR(Mat F, Mat A, IS perm, const MatFactorInfo *info) {
231a2fc1e05SToby Isaac   Mat_CHOLMOD   *chol = (Mat_CHOLMOD *)F->data;
232a2fc1e05SToby Isaac   cholmod_sparse cholA;
23365f45395SPierre Jolivet   PetscBool      aijalloc, valloc;
234a2fc1e05SToby Isaac 
235a2fc1e05SToby Isaac   PetscFunctionBegin;
2369566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)A, MATNORMALHERMITIAN, &chol->normal));
23748a46eb9SPierre Jolivet   if (!chol->normal && !PetscDefined(USE_COMPLEX)) PetscCall(PetscObjectTypeCompare((PetscObject)A, MATNORMAL, &chol->normal));
2389566063dSJacob Faibussowitsch   PetscCall((*chol->Wrap)(A, PETSC_TRUE, &cholA, &aijalloc, &valloc));
23948a46eb9SPierre Jolivet   if (PetscDefined(USE_DEBUG)) PetscCall(!cholmod_l_check_sparse(&cholA, chol->common));
24048a46eb9SPierre Jolivet   if (chol->spqrfact) PetscCall(!SuiteSparseQR_C_free(&chol->spqrfact, chol->common));
241d0f82a0bSPierre Jolivet   chol->spqrfact = SuiteSparseQR_C_symbolic(SPQR_ORDERING_DEFAULT, 1, &cholA, chol->common);
24228b400f6SJacob Faibussowitsch   PetscCheck(chol->spqrfact, PetscObjectComm((PetscObject)F), PETSC_ERR_LIB, "CHOLMOD analysis failed using internal ordering with status %d", chol->common->status);
243a2fc1e05SToby Isaac 
2449566063dSJacob Faibussowitsch   if (aijalloc) PetscCall(PetscFree2(cholA.p, cholA.i));
2459566063dSJacob Faibussowitsch   if (valloc) PetscCall(PetscFree(cholA.x));
246a2fc1e05SToby Isaac 
2479566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)F, "MatQRFactorNumeric_C", MatQRFactorNumeric_SPQR));
248a2fc1e05SToby Isaac   PetscFunctionReturn(0);
249a2fc1e05SToby Isaac }
250a2fc1e05SToby Isaac 
251a2fc1e05SToby Isaac /*MC
252a2fc1e05SToby Isaac   MATSOLVERSPQR
253a2fc1e05SToby Isaac 
254*11a5261eSBarry Smith   A matrix type providing direct solvers, QR factorizations, for sequential matrices
255a2fc1e05SToby Isaac   via the external package SPQR.
256a2fc1e05SToby Isaac 
257*11a5261eSBarry Smith   Use ./configure --download-suitesparse to install PETSc to use SPQR
258a2fc1e05SToby Isaac 
259*11a5261eSBarry Smith   Consult SPQR documentation for more information about the common parameters
260a2fc1e05SToby Isaac   which correspond to the options database keys below.
261a2fc1e05SToby Isaac 
262a2fc1e05SToby Isaac    Level: beginner
263a2fc1e05SToby Isaac 
264*11a5261eSBarry Smith    Note:
265*11a5261eSBarry Smith    SPQR is part of SuiteSparse http://faculty.cse.tamu.edu/davis/suitesparse.html
266a2fc1e05SToby Isaac 
267db781477SPatrick Sanan .seealso: `PCQR`, `PCFactorSetMatSolverType()`, `MatSolverType`
268a2fc1e05SToby Isaac M*/
269a2fc1e05SToby Isaac 
2709371c9d4SSatish Balay PETSC_INTERN PetscErrorCode MatGetFactor_seqaij_spqr(Mat A, MatFactorType ftype, Mat *F) {
271a2fc1e05SToby Isaac   Mat          B;
272a2fc1e05SToby Isaac   Mat_CHOLMOD *chol;
273a2fc1e05SToby Isaac   PetscInt     m = A->rmap->n, n = A->cmap->n;
274a2fc1e05SToby Isaac   const char  *prefix;
275a2fc1e05SToby Isaac 
276a2fc1e05SToby Isaac   PetscFunctionBegin;
277a2fc1e05SToby Isaac   /* Create the factorization matrix F */
2789566063dSJacob Faibussowitsch   PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &B));
2799566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(B, PETSC_DECIDE, PETSC_DECIDE, m, n));
2809566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy("spqr", &((PetscObject)B)->type_name));
2819566063dSJacob Faibussowitsch   PetscCall(MatGetOptionsPrefix(A, &prefix));
2829566063dSJacob Faibussowitsch   PetscCall(MatSetOptionsPrefix(B, prefix));
2839566063dSJacob Faibussowitsch   PetscCall(MatSetUp(B));
2849566063dSJacob Faibussowitsch   PetscCall(PetscNewLog(B, &chol));
285a2fc1e05SToby Isaac 
286a2fc1e05SToby Isaac   chol->Wrap = MatWrapCholmod_SPQR_seqaij;
287a2fc1e05SToby Isaac   B->data    = chol;
288a2fc1e05SToby Isaac 
289a2fc1e05SToby Isaac   B->ops->getinfo = MatGetInfo_CHOLMOD;
290a2fc1e05SToby Isaac   B->ops->view    = MatView_CHOLMOD;
291a2fc1e05SToby Isaac   B->ops->destroy = MatDestroy_CHOLMOD;
292a2fc1e05SToby Isaac 
2939566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatFactorGetSolverType_C", MatFactorGetSolverType_seqaij_SPQR));
2949566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatQRFactorSymbolic_C", MatQRFactorSymbolic_SPQR));
295a2fc1e05SToby Isaac 
296a2fc1e05SToby Isaac   B->factortype   = MAT_FACTOR_QR;
297a2fc1e05SToby Isaac   B->assembled    = PETSC_TRUE;
298a2fc1e05SToby Isaac   B->preallocated = PETSC_TRUE;
299a2fc1e05SToby Isaac 
3009566063dSJacob Faibussowitsch   PetscCall(PetscFree(B->solvertype));
3019566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(MATSOLVERCHOLMOD, &B->solvertype));
302a2fc1e05SToby Isaac   B->canuseordering = PETSC_FALSE;
3039566063dSJacob Faibussowitsch   PetscCall(CholmodStart(B));
304a2fc1e05SToby Isaac   chol->common->itype = CHOLMOD_LONG;
305a2fc1e05SToby Isaac   *F                  = B;
306a2fc1e05SToby Isaac   PetscFunctionReturn(0);
307a2fc1e05SToby Isaac }
308