xref: /petsc/src/mat/impls/aij/seq/spqr/aijspqr.c (revision 4dfa11a44d5adf2389f1d3acbc8f3c1116dc6c3a)
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 
25411a5261eSBarry Smith   A matrix type providing direct solvers, QR factorizations, for sequential matrices
255a2fc1e05SToby Isaac   via the external package SPQR.
256a2fc1e05SToby Isaac 
25711a5261eSBarry Smith   Use ./configure --download-suitesparse to install PETSc to use SPQR
258a2fc1e05SToby Isaac 
25911a5261eSBarry 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 
26411a5261eSBarry Smith    Note:
26511a5261eSBarry 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));
284*4dfa11a4SJacob Faibussowitsch   PetscCall(PetscNew(&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