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