xref: /petsc/src/mat/impls/aij/seq/spqr/aijspqr.c (revision b94d7ded0a05f1bbd5e48daa6f92b28259c75b44)
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 
10a2fc1e05SToby Isaac static PetscErrorCode MatWrapCholmod_SPQR_seqaij(Mat A,PetscBool values,cholmod_sparse *C,PetscBool *aijalloc,PetscBool *valloc)
11a2fc1e05SToby Isaac {
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));
2702ef7dfaSPierre Jolivet     if (flg) {
289566063dSJacob Faibussowitsch       PetscCall(MatNormalGetMat(A, &A));
2902ef7dfaSPierre Jolivet     }
3065f45395SPierre Jolivet   }
31a2fc1e05SToby Isaac   /* cholmod_sparse is compressed sparse column */
32*b94d7dedSBarry Smith   PetscCall(MatIsSymmetric(A,0.0, &flg));
3302ef7dfaSPierre Jolivet   if (flg) {
349566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)A));
35a2fc1e05SToby Isaac     AT = A;
36a2fc1e05SToby Isaac   } else {
379566063dSJacob Faibussowitsch     PetscCall(MatTranspose(A, MAT_INITIAL_MATRIX, &AT));
38a2fc1e05SToby Isaac   }
39a2fc1e05SToby Isaac   aij = (Mat_SeqAIJ*)AT->data;
40a2fc1e05SToby Isaac   ai = aij->j;
41a2fc1e05SToby Isaac   aj = aij->i;
42a2fc1e05SToby Isaac   for (j=0,nz=0; j<n; j++) nz += aj[j+1] - aj[j];
439566063dSJacob Faibussowitsch   PetscCall(PetscMalloc2(n+1,&cj,nz,&ci));
44a2fc1e05SToby Isaac   if (values) {
45a2fc1e05SToby Isaac     vain = PETSC_TRUE;
469566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(nz,&ca));
479566063dSJacob Faibussowitsch     PetscCall(MatSeqAIJGetArrayRead(AT,&aa));
48a2fc1e05SToby Isaac   }
49a2fc1e05SToby Isaac   for (j=0,k=0; j<n; j++) {
50a2fc1e05SToby Isaac     cj[j] = k;
51a2fc1e05SToby Isaac     for (i=aj[j]; i<aj[j+1]; i++,k++) {
52a2fc1e05SToby Isaac       ci[k] = ai[i];
53a2fc1e05SToby Isaac       if (values) ca[k] = aa[i];
54a2fc1e05SToby Isaac     }
55a2fc1e05SToby Isaac   }
56a2fc1e05SToby Isaac   cj[j]     = k;
57a2fc1e05SToby Isaac   *aijalloc = PETSC_TRUE;
58a2fc1e05SToby Isaac   *valloc   = vain;
59a2fc1e05SToby Isaac   if (values) {
609566063dSJacob Faibussowitsch     PetscCall(MatSeqAIJRestoreArrayRead(AT,&aa));
61a2fc1e05SToby Isaac   }
62a2fc1e05SToby Isaac 
639566063dSJacob Faibussowitsch   PetscCall(PetscMemzero(C,sizeof(*C)));
64a2fc1e05SToby Isaac 
6502ef7dfaSPierre Jolivet   C->nrow   = (size_t)AT->cmap->n;
6602ef7dfaSPierre Jolivet   C->ncol   = (size_t)AT->rmap->n;
67a2fc1e05SToby Isaac   C->nzmax  = (size_t)nz;
68a2fc1e05SToby Isaac   C->p      = cj;
69a2fc1e05SToby Isaac   C->i      = ci;
70a2fc1e05SToby Isaac   C->x      = values ? ca : 0;
71a2fc1e05SToby Isaac   C->stype  = 0;
72a2fc1e05SToby Isaac   C->itype  = CHOLMOD_LONG;
73a2fc1e05SToby Isaac   C->xtype  = values ? CHOLMOD_SCALAR_TYPE : CHOLMOD_PATTERN;
74a2fc1e05SToby Isaac   C->dtype  = CHOLMOD_DOUBLE;
75a2fc1e05SToby Isaac   C->sorted = 1;
76a2fc1e05SToby Isaac   C->packed = 1;
77a2fc1e05SToby Isaac 
789566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&AT));
79a2fc1e05SToby Isaac   PetscFunctionReturn(0);
80a2fc1e05SToby Isaac }
81a2fc1e05SToby Isaac 
82a2fc1e05SToby Isaac static PetscErrorCode MatFactorGetSolverType_seqaij_SPQR(Mat A,MatSolverType *type)
83a2fc1e05SToby Isaac {
84a2fc1e05SToby Isaac   PetscFunctionBegin;
85a2fc1e05SToby Isaac   *type = MATSOLVERSPQR;
86a2fc1e05SToby Isaac   PetscFunctionReturn(0);
87a2fc1e05SToby Isaac }
88a2fc1e05SToby Isaac 
89a2fc1e05SToby Isaac #define GET_ARRAY_READ 0
90a2fc1e05SToby Isaac #define GET_ARRAY_WRITE 1
91a2fc1e05SToby Isaac 
92a2fc1e05SToby Isaac static PetscErrorCode MatSolve_SPQR_Internal(Mat F, cholmod_dense *cholB, cholmod_dense **_Y_handle)
93a2fc1e05SToby Isaac {
94a2fc1e05SToby Isaac   Mat_CHOLMOD    *chol = (Mat_CHOLMOD*)F->data;
9502ef7dfaSPierre Jolivet   cholmod_dense  *Y_handle = NULL, *QTB_handle = NULL, *Z_handle = NULL;
96a2fc1e05SToby Isaac 
97a2fc1e05SToby Isaac   PetscFunctionBegin;
9802ef7dfaSPierre Jolivet   if (!chol->normal) {
99a2fc1e05SToby Isaac     QTB_handle = SuiteSparseQR_C_qmult(SPQR_QTX, chol->spqrfact, cholB, chol->common);
10028b400f6SJacob Faibussowitsch     PetscCheck(QTB_handle,PetscObjectComm((PetscObject)F), PETSC_ERR_LIB, "SuiteSparseQR_C_qmult failed");
101a2fc1e05SToby Isaac     Y_handle = SuiteSparseQR_C_solve(SPQR_RETX_EQUALS_B, chol->spqrfact, QTB_handle, chol->common);
10228b400f6SJacob Faibussowitsch     PetscCheck(Y_handle,PetscObjectComm((PetscObject)F), PETSC_ERR_LIB, "SuiteSparseQR_C_solve failed");
10302ef7dfaSPierre Jolivet   } else {
10402ef7dfaSPierre Jolivet     Z_handle = SuiteSparseQR_C_solve(SPQR_RTX_EQUALS_ETB, chol->spqrfact, cholB, chol->common);
10528b400f6SJacob Faibussowitsch     PetscCheck(Z_handle,PetscObjectComm((PetscObject)F), PETSC_ERR_LIB, "SuiteSparseQR_C_solve failed");
10602ef7dfaSPierre Jolivet     Y_handle = SuiteSparseQR_C_solve(SPQR_RETX_EQUALS_B, chol->spqrfact, Z_handle, chol->common);
10728b400f6SJacob Faibussowitsch     PetscCheck(Y_handle,PetscObjectComm((PetscObject)F), PETSC_ERR_LIB, "SuiteSparseQR_C_solve failed");
1089566063dSJacob Faibussowitsch     PetscCall(!cholmod_l_free_dense(&Z_handle, chol->common));
10902ef7dfaSPierre Jolivet   }
110a2fc1e05SToby Isaac   *_Y_handle = Y_handle;
1119566063dSJacob Faibussowitsch   PetscCall(!cholmod_l_free_dense(&QTB_handle, chol->common));
112a2fc1e05SToby Isaac   PetscFunctionReturn(0);
113a2fc1e05SToby Isaac }
114a2fc1e05SToby Isaac 
115a2fc1e05SToby Isaac static PetscErrorCode MatSolve_SPQR(Mat F,Vec B,Vec X)
116a2fc1e05SToby Isaac {
117a2fc1e05SToby Isaac   Mat_CHOLMOD    *chol = (Mat_CHOLMOD*)F->data;
118a2fc1e05SToby Isaac   cholmod_dense  cholB,*Y_handle = NULL;
119a2fc1e05SToby Isaac   PetscInt       n;
120a2fc1e05SToby Isaac   PetscScalar    *v;
121a2fc1e05SToby Isaac 
122a2fc1e05SToby Isaac   PetscFunctionBegin;
1239566063dSJacob Faibussowitsch   PetscCall(VecWrapCholmod(B,GET_ARRAY_READ,&cholB));
1249566063dSJacob Faibussowitsch   PetscCall(MatSolve_SPQR_Internal(F, &cholB, &Y_handle));
1259566063dSJacob Faibussowitsch   PetscCall(VecGetLocalSize(X, &n));
1269566063dSJacob Faibussowitsch   PetscCall(VecGetArrayWrite(X, &v));
1279566063dSJacob Faibussowitsch   PetscCall(PetscArraycpy(v, (PetscScalar *) (Y_handle->x), n));
1289566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayWrite(X, &v));
1299566063dSJacob Faibussowitsch   PetscCall(!cholmod_l_free_dense(&Y_handle, chol->common));
1309566063dSJacob Faibussowitsch   PetscCall(VecUnWrapCholmod(B,GET_ARRAY_READ,&cholB));
131a2fc1e05SToby Isaac   PetscFunctionReturn(0);
132a2fc1e05SToby Isaac }
133a2fc1e05SToby Isaac 
134a2fc1e05SToby Isaac static PetscErrorCode MatMatSolve_SPQR(Mat F,Mat B,Mat X)
135a2fc1e05SToby Isaac {
136a2fc1e05SToby Isaac   Mat_CHOLMOD    *chol = (Mat_CHOLMOD*)F->data;
137a2fc1e05SToby Isaac   cholmod_dense  cholB,*Y_handle = NULL;
138a2fc1e05SToby Isaac   PetscScalar    *v;
139a2fc1e05SToby Isaac   PetscInt       lda;
140a2fc1e05SToby Isaac 
141a2fc1e05SToby Isaac   PetscFunctionBegin;
1429566063dSJacob Faibussowitsch   PetscCall(MatDenseWrapCholmod(B,GET_ARRAY_READ,&cholB));
1439566063dSJacob Faibussowitsch   PetscCall(MatSolve_SPQR_Internal(F, &cholB, &Y_handle));
1449566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayWrite(X, &v));
1459566063dSJacob Faibussowitsch   PetscCall(MatDenseGetLDA(X, &lda));
146a2fc1e05SToby Isaac   if ((size_t) lda == Y_handle->d) {
1479566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(v, (PetscScalar *) (Y_handle->x), lda * Y_handle->ncol));
148a2fc1e05SToby Isaac   } else {
149a2fc1e05SToby Isaac     for (size_t j = 0; j < Y_handle->ncol; j++) {
1509566063dSJacob Faibussowitsch       PetscCall(PetscArraycpy(&v[j*lda], &(((PetscScalar *) Y_handle->x)[j*Y_handle->d]), Y_handle->nrow));
151a2fc1e05SToby Isaac     }
152a2fc1e05SToby Isaac   }
1539566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayWrite(X, &v));
1549566063dSJacob Faibussowitsch   PetscCall(!cholmod_l_free_dense(&Y_handle, chol->common));
1559566063dSJacob Faibussowitsch   PetscCall(MatDenseUnWrapCholmod(B,GET_ARRAY_READ,&cholB));
156a2fc1e05SToby Isaac   PetscFunctionReturn(0);
157a2fc1e05SToby Isaac }
158a2fc1e05SToby Isaac 
159a2fc1e05SToby Isaac static PetscErrorCode MatSolveTranspose_SPQR_Internal(Mat F, cholmod_dense *cholB, cholmod_dense **_Y_handle)
160a2fc1e05SToby Isaac {
161a2fc1e05SToby Isaac   Mat_CHOLMOD    *chol = (Mat_CHOLMOD*)F->data;
162a2fc1e05SToby Isaac   cholmod_dense  *Y_handle = NULL, *RTB_handle = NULL;
163a2fc1e05SToby Isaac 
164a2fc1e05SToby Isaac   PetscFunctionBegin;
165a2fc1e05SToby Isaac   RTB_handle = SuiteSparseQR_C_solve(SPQR_RTX_EQUALS_ETB, chol->spqrfact, cholB, chol->common);
16628b400f6SJacob Faibussowitsch   PetscCheck(RTB_handle,PetscObjectComm((PetscObject)F), PETSC_ERR_LIB, "SuiteSparseQR_C_solve failed");
167a2fc1e05SToby Isaac   Y_handle = SuiteSparseQR_C_qmult(SPQR_QX, chol->spqrfact, RTB_handle, chol->common);
16828b400f6SJacob Faibussowitsch   PetscCheck(Y_handle,PetscObjectComm((PetscObject)F), PETSC_ERR_LIB, "SuiteSparseQR_C_qmult failed");
169a2fc1e05SToby Isaac   *_Y_handle = Y_handle;
1709566063dSJacob Faibussowitsch   PetscCall(!cholmod_l_free_dense(&RTB_handle, chol->common));
171a2fc1e05SToby Isaac   PetscFunctionReturn(0);
172a2fc1e05SToby Isaac }
173a2fc1e05SToby Isaac 
174a2fc1e05SToby Isaac static PetscErrorCode MatSolveTranspose_SPQR(Mat F,Vec B,Vec X)
175a2fc1e05SToby Isaac {
176a2fc1e05SToby Isaac   Mat_CHOLMOD    *chol = (Mat_CHOLMOD*)F->data;
177a2fc1e05SToby Isaac   cholmod_dense  cholB,*Y_handle = NULL;
178a2fc1e05SToby Isaac   PetscInt       n;
179a2fc1e05SToby Isaac   PetscScalar    *v;
180a2fc1e05SToby Isaac 
181a2fc1e05SToby Isaac   PetscFunctionBegin;
1829566063dSJacob Faibussowitsch   PetscCall(VecWrapCholmod(B,GET_ARRAY_READ,&cholB));
1839566063dSJacob Faibussowitsch   PetscCall(MatSolveTranspose_SPQR_Internal(F, &cholB, &Y_handle));
1849566063dSJacob Faibussowitsch   PetscCall(VecGetLocalSize(X, &n));
1859566063dSJacob Faibussowitsch   PetscCall(VecGetArrayWrite(X, &v));
1869566063dSJacob Faibussowitsch   PetscCall(PetscArraycpy(v, (PetscScalar *) Y_handle->x, n));
1879566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayWrite(X, &v));
1889566063dSJacob Faibussowitsch   PetscCall(!cholmod_l_free_dense(&Y_handle, chol->common));
1899566063dSJacob Faibussowitsch   PetscCall(VecUnWrapCholmod(B,GET_ARRAY_READ,&cholB));
190a2fc1e05SToby Isaac   PetscFunctionReturn(0);
191a2fc1e05SToby Isaac }
192a2fc1e05SToby Isaac 
193a2fc1e05SToby Isaac static PetscErrorCode MatMatSolveTranspose_SPQR(Mat F,Mat B,Mat X)
194a2fc1e05SToby Isaac {
195a2fc1e05SToby Isaac   Mat_CHOLMOD    *chol = (Mat_CHOLMOD*)F->data;
196a2fc1e05SToby Isaac   cholmod_dense  cholB,*Y_handle = NULL;
197a2fc1e05SToby Isaac   PetscScalar    *v;
198a2fc1e05SToby Isaac   PetscInt       lda;
199a2fc1e05SToby Isaac 
200a2fc1e05SToby Isaac   PetscFunctionBegin;
2019566063dSJacob Faibussowitsch   PetscCall(MatDenseWrapCholmod(B,GET_ARRAY_READ,&cholB));
2029566063dSJacob Faibussowitsch   PetscCall(MatSolveTranspose_SPQR_Internal(F, &cholB, &Y_handle));
2039566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayWrite(X, &v));
2049566063dSJacob Faibussowitsch   PetscCall(MatDenseGetLDA(X, &lda));
205a2fc1e05SToby Isaac   if ((size_t) lda == Y_handle->d) {
2069566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(v, (PetscScalar *) Y_handle->x, lda * Y_handle->ncol));
207a2fc1e05SToby Isaac   } else {
208a2fc1e05SToby Isaac     for (size_t j = 0; j < Y_handle->ncol; j++) {
2099566063dSJacob Faibussowitsch       PetscCall(PetscArraycpy(&v[j*lda], &(((PetscScalar *) Y_handle->x)[j*Y_handle->d]), Y_handle->nrow));
210a2fc1e05SToby Isaac     }
211a2fc1e05SToby Isaac   }
2129566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayWrite(X, &v));
2139566063dSJacob Faibussowitsch   PetscCall(!cholmod_l_free_dense(&Y_handle, chol->common));
2149566063dSJacob Faibussowitsch   PetscCall(MatDenseUnWrapCholmod(B,GET_ARRAY_READ,&cholB));
215a2fc1e05SToby Isaac   PetscFunctionReturn(0);
216a2fc1e05SToby Isaac }
217a2fc1e05SToby Isaac 
218a2fc1e05SToby Isaac static PetscErrorCode MatQRFactorNumeric_SPQR(Mat F,Mat A,const MatFactorInfo *info)
219a2fc1e05SToby Isaac {
220a2fc1e05SToby Isaac   Mat_CHOLMOD    *chol = (Mat_CHOLMOD*)F->data;
221a2fc1e05SToby Isaac   cholmod_sparse cholA;
22265f45395SPierre Jolivet   PetscBool      aijalloc,valloc;
223d0609cedSBarry Smith   int            err;
224a2fc1e05SToby Isaac 
225a2fc1e05SToby Isaac   PetscFunctionBegin;
2269566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)A, MATNORMALHERMITIAN, &chol->normal));
22765f45395SPierre Jolivet   if (!chol->normal && !PetscDefined(USE_COMPLEX)) {
2289566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)A, MATNORMAL, &chol->normal));
22965f45395SPierre Jolivet   }
2309566063dSJacob Faibussowitsch   PetscCall((*chol->Wrap)(A,PETSC_TRUE,&cholA,&aijalloc,&valloc));
231d0609cedSBarry Smith   err = !SuiteSparseQR_C_numeric(PETSC_SMALL, &cholA, chol->spqrfact, chol->common);
232d0609cedSBarry Smith   PetscCheck(!err,PetscObjectComm((PetscObject)F),PETSC_ERR_LIB,"SPQR factorization failed with status %d",chol->common->status);
233a2fc1e05SToby Isaac 
2349566063dSJacob Faibussowitsch   if (aijalloc) PetscCall(PetscFree2(cholA.p,cholA.i));
2359566063dSJacob Faibussowitsch   if (valloc) PetscCall(PetscFree(cholA.x));
236a2fc1e05SToby Isaac 
237a2fc1e05SToby Isaac   F->ops->solve             = MatSolve_SPQR;
238a2fc1e05SToby Isaac   F->ops->matsolve          = MatMatSolve_SPQR;
23902ef7dfaSPierre Jolivet   if (chol->normal) {
24002ef7dfaSPierre Jolivet     F->ops->solvetranspose    = MatSolve_SPQR;
24102ef7dfaSPierre Jolivet     F->ops->matsolvetranspose = MatMatSolve_SPQR;
24202ef7dfaSPierre Jolivet   } else if (A->cmap->n == A->rmap->n) {
243a2fc1e05SToby Isaac     F->ops->solvetranspose    = MatSolveTranspose_SPQR;
244a2fc1e05SToby Isaac     F->ops->matsolvetranspose = MatMatSolveTranspose_SPQR;
245a2fc1e05SToby Isaac   }
246a2fc1e05SToby Isaac   PetscFunctionReturn(0);
247a2fc1e05SToby Isaac }
248a2fc1e05SToby Isaac 
249a2fc1e05SToby Isaac PETSC_INTERN PetscErrorCode MatQRFactorSymbolic_SPQR(Mat F,Mat A,IS perm,const MatFactorInfo *info)
250a2fc1e05SToby Isaac {
251a2fc1e05SToby Isaac   Mat_CHOLMOD    *chol = (Mat_CHOLMOD*)F->data;
252a2fc1e05SToby Isaac   cholmod_sparse cholA;
25365f45395SPierre Jolivet   PetscBool      aijalloc,valloc;
254a2fc1e05SToby Isaac 
255a2fc1e05SToby Isaac   PetscFunctionBegin;
2569566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)A, MATNORMALHERMITIAN, &chol->normal));
25765f45395SPierre Jolivet   if (!chol->normal && !PetscDefined(USE_COMPLEX)) {
2589566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)A, MATNORMAL, &chol->normal));
25965f45395SPierre Jolivet   }
2609566063dSJacob Faibussowitsch   PetscCall((*chol->Wrap)(A,PETSC_TRUE,&cholA,&aijalloc,&valloc));
261a2fc1e05SToby Isaac   if (PetscDefined(USE_DEBUG)) {
2629566063dSJacob Faibussowitsch     PetscCall(!cholmod_l_check_sparse(&cholA, chol->common));
263a2fc1e05SToby Isaac   }
264a2fc1e05SToby Isaac   if (chol->spqrfact) {
2659566063dSJacob Faibussowitsch     PetscCall(!SuiteSparseQR_C_free(&chol->spqrfact, chol->common));
266a2fc1e05SToby Isaac   }
267d0f82a0bSPierre Jolivet   chol->spqrfact = SuiteSparseQR_C_symbolic(SPQR_ORDERING_DEFAULT, 1, &cholA, chol->common);
26828b400f6SJacob Faibussowitsch   PetscCheck(chol->spqrfact,PetscObjectComm((PetscObject)F),PETSC_ERR_LIB,"CHOLMOD analysis failed using internal ordering with status %d",chol->common->status);
269a2fc1e05SToby Isaac 
2709566063dSJacob Faibussowitsch   if (aijalloc) PetscCall(PetscFree2(cholA.p,cholA.i));
2719566063dSJacob Faibussowitsch   if (valloc) PetscCall(PetscFree(cholA.x));
272a2fc1e05SToby Isaac 
2739566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)F,"MatQRFactorNumeric_C", MatQRFactorNumeric_SPQR));
274a2fc1e05SToby Isaac   PetscFunctionReturn(0);
275a2fc1e05SToby Isaac }
276a2fc1e05SToby Isaac 
277a2fc1e05SToby Isaac /*MC
278a2fc1e05SToby Isaac   MATSOLVERSPQR
279a2fc1e05SToby Isaac 
280a2fc1e05SToby Isaac   A matrix type providing direct solvers (QR factorizations) for sequential matrices
281a2fc1e05SToby Isaac   via the external package SPQR.
282a2fc1e05SToby Isaac 
283a2fc1e05SToby Isaac   Use ./configure --download-suitesparse to install PETSc to use CHOLMOD
284a2fc1e05SToby Isaac 
285a2fc1e05SToby Isaac   Consult SPQR documentation for more information about the Common parameters
286a2fc1e05SToby Isaac   which correspond to the options database keys below.
287a2fc1e05SToby Isaac 
288a2fc1e05SToby Isaac    Level: beginner
289a2fc1e05SToby Isaac 
290a2fc1e05SToby Isaac    Note: SPQR is part of SuiteSparse http://faculty.cse.tamu.edu/davis/suitesparse.html
291a2fc1e05SToby Isaac 
292db781477SPatrick Sanan .seealso: `PCQR`, `PCFactorSetMatSolverType()`, `MatSolverType`
293a2fc1e05SToby Isaac M*/
294a2fc1e05SToby Isaac 
295a2fc1e05SToby Isaac PETSC_INTERN PetscErrorCode MatGetFactor_seqaij_spqr(Mat A,MatFactorType ftype,Mat *F)
296a2fc1e05SToby Isaac {
297a2fc1e05SToby Isaac   Mat            B;
298a2fc1e05SToby Isaac   Mat_CHOLMOD    *chol;
299a2fc1e05SToby Isaac   PetscInt       m=A->rmap->n,n=A->cmap->n;
300a2fc1e05SToby Isaac   const char     *prefix;
301a2fc1e05SToby Isaac 
302a2fc1e05SToby Isaac   PetscFunctionBegin;
303a2fc1e05SToby Isaac   /* Create the factorization matrix F */
3049566063dSJacob Faibussowitsch   PetscCall(MatCreate(PetscObjectComm((PetscObject)A),&B));
3059566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(B,PETSC_DECIDE,PETSC_DECIDE,m,n));
3069566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy("spqr",&((PetscObject)B)->type_name));
3079566063dSJacob Faibussowitsch   PetscCall(MatGetOptionsPrefix(A,&prefix));
3089566063dSJacob Faibussowitsch   PetscCall(MatSetOptionsPrefix(B,prefix));
3099566063dSJacob Faibussowitsch   PetscCall(MatSetUp(B));
3109566063dSJacob Faibussowitsch   PetscCall(PetscNewLog(B,&chol));
311a2fc1e05SToby Isaac 
312a2fc1e05SToby Isaac   chol->Wrap = MatWrapCholmod_SPQR_seqaij;
313a2fc1e05SToby Isaac   B->data    = chol;
314a2fc1e05SToby Isaac 
315a2fc1e05SToby Isaac   B->ops->getinfo = MatGetInfo_CHOLMOD;
316a2fc1e05SToby Isaac   B->ops->view    = MatView_CHOLMOD;
317a2fc1e05SToby Isaac   B->ops->destroy = MatDestroy_CHOLMOD;
318a2fc1e05SToby Isaac 
3199566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B,"MatFactorGetSolverType_C",MatFactorGetSolverType_seqaij_SPQR));
3209566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B,"MatQRFactorSymbolic_C", MatQRFactorSymbolic_SPQR));
321a2fc1e05SToby Isaac 
322a2fc1e05SToby Isaac   B->factortype   = MAT_FACTOR_QR;
323a2fc1e05SToby Isaac   B->assembled    = PETSC_TRUE;
324a2fc1e05SToby Isaac   B->preallocated = PETSC_TRUE;
325a2fc1e05SToby Isaac 
3269566063dSJacob Faibussowitsch   PetscCall(PetscFree(B->solvertype));
3279566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(MATSOLVERCHOLMOD,&B->solvertype));
328a2fc1e05SToby Isaac   B->canuseordering = PETSC_FALSE;
3299566063dSJacob Faibussowitsch   PetscCall(CholmodStart(B));
330a2fc1e05SToby Isaac   chol->common->itype = CHOLMOD_LONG;
331a2fc1e05SToby Isaac   *F   = B;
332a2fc1e05SToby Isaac   PetscFunctionReturn(0);
333a2fc1e05SToby Isaac }
334