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