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 10d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatWrapCholmod_SPQR_seqaij(Mat A, PetscBool values, cholmod_sparse *C, PetscBool *aijalloc, PetscBool *valloc) 11d71ae5a4SJacob Faibussowitsch { 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)); 2748a46eb9SPierre Jolivet if (flg) PetscCall(MatNormalGetMat(A, &A)); 2865f45395SPierre Jolivet } 29a2fc1e05SToby Isaac /* cholmod_sparse is compressed sparse column */ 30b94d7dedSBarry Smith PetscCall(MatIsSymmetric(A, 0.0, &flg)); 3102ef7dfaSPierre Jolivet if (flg) { 329566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)A)); 33a2fc1e05SToby Isaac AT = A; 34a2fc1e05SToby Isaac } else { 359566063dSJacob Faibussowitsch PetscCall(MatTranspose(A, MAT_INITIAL_MATRIX, &AT)); 36a2fc1e05SToby Isaac } 37a2fc1e05SToby Isaac aij = (Mat_SeqAIJ *)AT->data; 38a2fc1e05SToby Isaac ai = aij->j; 39a2fc1e05SToby Isaac aj = aij->i; 40a2fc1e05SToby Isaac for (j = 0, nz = 0; j < n; j++) nz += aj[j + 1] - aj[j]; 419566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(n + 1, &cj, nz, &ci)); 42a2fc1e05SToby Isaac if (values) { 43a2fc1e05SToby Isaac vain = PETSC_TRUE; 449566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nz, &ca)); 459566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(AT, &aa)); 46a2fc1e05SToby Isaac } 47a2fc1e05SToby Isaac for (j = 0, k = 0; j < n; j++) { 48a2fc1e05SToby Isaac cj[j] = k; 49a2fc1e05SToby Isaac for (i = aj[j]; i < aj[j + 1]; i++, k++) { 50a2fc1e05SToby Isaac ci[k] = ai[i]; 51a2fc1e05SToby Isaac if (values) ca[k] = aa[i]; 52a2fc1e05SToby Isaac } 53a2fc1e05SToby Isaac } 54a2fc1e05SToby Isaac cj[j] = k; 55a2fc1e05SToby Isaac *aijalloc = PETSC_TRUE; 56a2fc1e05SToby Isaac *valloc = vain; 5748a46eb9SPierre Jolivet if (values) PetscCall(MatSeqAIJRestoreArrayRead(AT, &aa)); 58a2fc1e05SToby Isaac 599566063dSJacob Faibussowitsch PetscCall(PetscMemzero(C, sizeof(*C))); 60a2fc1e05SToby Isaac 6102ef7dfaSPierre Jolivet C->nrow = (size_t)AT->cmap->n; 6202ef7dfaSPierre Jolivet C->ncol = (size_t)AT->rmap->n; 63a2fc1e05SToby Isaac C->nzmax = (size_t)nz; 64a2fc1e05SToby Isaac C->p = cj; 65a2fc1e05SToby Isaac C->i = ci; 66a2fc1e05SToby Isaac C->x = values ? ca : 0; 67a2fc1e05SToby Isaac C->stype = 0; 68a2fc1e05SToby Isaac C->itype = CHOLMOD_LONG; 69a2fc1e05SToby Isaac C->xtype = values ? CHOLMOD_SCALAR_TYPE : CHOLMOD_PATTERN; 70a2fc1e05SToby Isaac C->dtype = CHOLMOD_DOUBLE; 71a2fc1e05SToby Isaac C->sorted = 1; 72a2fc1e05SToby Isaac C->packed = 1; 73a2fc1e05SToby Isaac 749566063dSJacob Faibussowitsch PetscCall(MatDestroy(&AT)); 753ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 76a2fc1e05SToby Isaac } 77a2fc1e05SToby Isaac 78d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatFactorGetSolverType_seqaij_SPQR(Mat A, MatSolverType *type) 79d71ae5a4SJacob Faibussowitsch { 80a2fc1e05SToby Isaac PetscFunctionBegin; 81a2fc1e05SToby Isaac *type = MATSOLVERSPQR; 823ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 83a2fc1e05SToby Isaac } 84a2fc1e05SToby Isaac 85a2fc1e05SToby Isaac #define GET_ARRAY_READ 0 86a2fc1e05SToby Isaac #define GET_ARRAY_WRITE 1 87a2fc1e05SToby Isaac 88d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSolve_SPQR_Internal(Mat F, cholmod_dense *cholB, cholmod_dense **_Y_handle) 89d71ae5a4SJacob Faibussowitsch { 90a2fc1e05SToby Isaac Mat_CHOLMOD *chol = (Mat_CHOLMOD *)F->data; 9102ef7dfaSPierre Jolivet cholmod_dense *Y_handle = NULL, *QTB_handle = NULL, *Z_handle = NULL; 92a2fc1e05SToby Isaac 93a2fc1e05SToby Isaac PetscFunctionBegin; 9402ef7dfaSPierre Jolivet if (!chol->normal) { 95a2fc1e05SToby Isaac QTB_handle = SuiteSparseQR_C_qmult(SPQR_QTX, chol->spqrfact, cholB, chol->common); 9628b400f6SJacob Faibussowitsch PetscCheck(QTB_handle, PetscObjectComm((PetscObject)F), PETSC_ERR_LIB, "SuiteSparseQR_C_qmult failed"); 97a2fc1e05SToby Isaac Y_handle = SuiteSparseQR_C_solve(SPQR_RETX_EQUALS_B, chol->spqrfact, QTB_handle, chol->common); 9828b400f6SJacob Faibussowitsch PetscCheck(Y_handle, PetscObjectComm((PetscObject)F), PETSC_ERR_LIB, "SuiteSparseQR_C_solve failed"); 9902ef7dfaSPierre Jolivet } else { 10002ef7dfaSPierre Jolivet Z_handle = SuiteSparseQR_C_solve(SPQR_RTX_EQUALS_ETB, chol->spqrfact, cholB, chol->common); 10128b400f6SJacob Faibussowitsch PetscCheck(Z_handle, PetscObjectComm((PetscObject)F), PETSC_ERR_LIB, "SuiteSparseQR_C_solve failed"); 10202ef7dfaSPierre Jolivet Y_handle = SuiteSparseQR_C_solve(SPQR_RETX_EQUALS_B, chol->spqrfact, Z_handle, chol->common); 10328b400f6SJacob Faibussowitsch PetscCheck(Y_handle, PetscObjectComm((PetscObject)F), PETSC_ERR_LIB, "SuiteSparseQR_C_solve failed"); 1043ba16761SJacob Faibussowitsch PetscCallExternal(!cholmod_l_free_dense, &Z_handle, chol->common); 10502ef7dfaSPierre Jolivet } 106a2fc1e05SToby Isaac *_Y_handle = Y_handle; 1073ba16761SJacob Faibussowitsch PetscCallExternal(!cholmod_l_free_dense, &QTB_handle, chol->common); 1083ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 109a2fc1e05SToby Isaac } 110a2fc1e05SToby Isaac 111d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSolve_SPQR(Mat F, Vec B, Vec X) 112d71ae5a4SJacob Faibussowitsch { 113a2fc1e05SToby Isaac Mat_CHOLMOD *chol = (Mat_CHOLMOD *)F->data; 114a2fc1e05SToby Isaac cholmod_dense cholB, *Y_handle = NULL; 115a2fc1e05SToby Isaac PetscInt n; 116a2fc1e05SToby Isaac PetscScalar *v; 117a2fc1e05SToby Isaac 118a2fc1e05SToby Isaac PetscFunctionBegin; 1199566063dSJacob Faibussowitsch PetscCall(VecWrapCholmod(B, GET_ARRAY_READ, &cholB)); 1209566063dSJacob Faibussowitsch PetscCall(MatSolve_SPQR_Internal(F, &cholB, &Y_handle)); 1219566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(X, &n)); 1229566063dSJacob Faibussowitsch PetscCall(VecGetArrayWrite(X, &v)); 1239566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(v, (PetscScalar *)(Y_handle->x), n)); 1249566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayWrite(X, &v)); 1253ba16761SJacob Faibussowitsch PetscCallExternal(!cholmod_l_free_dense, &Y_handle, chol->common); 1269566063dSJacob Faibussowitsch PetscCall(VecUnWrapCholmod(B, GET_ARRAY_READ, &cholB)); 1273ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 128a2fc1e05SToby Isaac } 129a2fc1e05SToby Isaac 130d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMatSolve_SPQR(Mat F, Mat B, Mat X) 131d71ae5a4SJacob Faibussowitsch { 132a2fc1e05SToby Isaac Mat_CHOLMOD *chol = (Mat_CHOLMOD *)F->data; 133a2fc1e05SToby Isaac cholmod_dense cholB, *Y_handle = NULL; 134a2fc1e05SToby Isaac PetscScalar *v; 135a2fc1e05SToby Isaac PetscInt lda; 136a2fc1e05SToby Isaac 137a2fc1e05SToby Isaac PetscFunctionBegin; 1389566063dSJacob Faibussowitsch PetscCall(MatDenseWrapCholmod(B, GET_ARRAY_READ, &cholB)); 1399566063dSJacob Faibussowitsch PetscCall(MatSolve_SPQR_Internal(F, &cholB, &Y_handle)); 1409566063dSJacob Faibussowitsch PetscCall(MatDenseGetArrayWrite(X, &v)); 1419566063dSJacob Faibussowitsch PetscCall(MatDenseGetLDA(X, &lda)); 142a2fc1e05SToby Isaac if ((size_t)lda == Y_handle->d) { 1439566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(v, (PetscScalar *)(Y_handle->x), lda * Y_handle->ncol)); 144a2fc1e05SToby Isaac } else { 14548a46eb9SPierre 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)); 146a2fc1e05SToby Isaac } 1479566063dSJacob Faibussowitsch PetscCall(MatDenseRestoreArrayWrite(X, &v)); 1483ba16761SJacob Faibussowitsch PetscCallExternal(!cholmod_l_free_dense, &Y_handle, chol->common); 1499566063dSJacob Faibussowitsch PetscCall(MatDenseUnWrapCholmod(B, GET_ARRAY_READ, &cholB)); 1503ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 151a2fc1e05SToby Isaac } 152a2fc1e05SToby Isaac 153d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSolveTranspose_SPQR_Internal(Mat F, cholmod_dense *cholB, cholmod_dense **_Y_handle) 154d71ae5a4SJacob Faibussowitsch { 155a2fc1e05SToby Isaac Mat_CHOLMOD *chol = (Mat_CHOLMOD *)F->data; 156a2fc1e05SToby Isaac cholmod_dense *Y_handle = NULL, *RTB_handle = NULL; 157a2fc1e05SToby Isaac 158a2fc1e05SToby Isaac PetscFunctionBegin; 159a2fc1e05SToby Isaac RTB_handle = SuiteSparseQR_C_solve(SPQR_RTX_EQUALS_ETB, chol->spqrfact, cholB, chol->common); 16028b400f6SJacob Faibussowitsch PetscCheck(RTB_handle, PetscObjectComm((PetscObject)F), PETSC_ERR_LIB, "SuiteSparseQR_C_solve failed"); 161a2fc1e05SToby Isaac Y_handle = SuiteSparseQR_C_qmult(SPQR_QX, chol->spqrfact, RTB_handle, chol->common); 16228b400f6SJacob Faibussowitsch PetscCheck(Y_handle, PetscObjectComm((PetscObject)F), PETSC_ERR_LIB, "SuiteSparseQR_C_qmult failed"); 163a2fc1e05SToby Isaac *_Y_handle = Y_handle; 1643ba16761SJacob Faibussowitsch PetscCallExternal(!cholmod_l_free_dense, &RTB_handle, chol->common); 1653ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 166a2fc1e05SToby Isaac } 167a2fc1e05SToby Isaac 168d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSolveTranspose_SPQR(Mat F, Vec B, Vec X) 169d71ae5a4SJacob Faibussowitsch { 170a2fc1e05SToby Isaac Mat_CHOLMOD *chol = (Mat_CHOLMOD *)F->data; 171a2fc1e05SToby Isaac cholmod_dense cholB, *Y_handle = NULL; 172a2fc1e05SToby Isaac PetscInt n; 173a2fc1e05SToby Isaac PetscScalar *v; 174a2fc1e05SToby Isaac 175a2fc1e05SToby Isaac PetscFunctionBegin; 1769566063dSJacob Faibussowitsch PetscCall(VecWrapCholmod(B, GET_ARRAY_READ, &cholB)); 1779566063dSJacob Faibussowitsch PetscCall(MatSolveTranspose_SPQR_Internal(F, &cholB, &Y_handle)); 1789566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(X, &n)); 1799566063dSJacob Faibussowitsch PetscCall(VecGetArrayWrite(X, &v)); 1809566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(v, (PetscScalar *)Y_handle->x, n)); 1819566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayWrite(X, &v)); 1823ba16761SJacob Faibussowitsch PetscCallExternal(!cholmod_l_free_dense, &Y_handle, chol->common); 1839566063dSJacob Faibussowitsch PetscCall(VecUnWrapCholmod(B, GET_ARRAY_READ, &cholB)); 1843ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 185a2fc1e05SToby Isaac } 186a2fc1e05SToby Isaac 187d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMatSolveTranspose_SPQR(Mat F, Mat B, Mat X) 188d71ae5a4SJacob Faibussowitsch { 189a2fc1e05SToby Isaac Mat_CHOLMOD *chol = (Mat_CHOLMOD *)F->data; 190a2fc1e05SToby Isaac cholmod_dense cholB, *Y_handle = NULL; 191a2fc1e05SToby Isaac PetscScalar *v; 192a2fc1e05SToby Isaac PetscInt lda; 193a2fc1e05SToby Isaac 194a2fc1e05SToby Isaac PetscFunctionBegin; 1959566063dSJacob Faibussowitsch PetscCall(MatDenseWrapCholmod(B, GET_ARRAY_READ, &cholB)); 1969566063dSJacob Faibussowitsch PetscCall(MatSolveTranspose_SPQR_Internal(F, &cholB, &Y_handle)); 1979566063dSJacob Faibussowitsch PetscCall(MatDenseGetArrayWrite(X, &v)); 1989566063dSJacob Faibussowitsch PetscCall(MatDenseGetLDA(X, &lda)); 199a2fc1e05SToby Isaac if ((size_t)lda == Y_handle->d) { 2009566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(v, (PetscScalar *)Y_handle->x, lda * Y_handle->ncol)); 201a2fc1e05SToby Isaac } else { 20248a46eb9SPierre 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)); 203a2fc1e05SToby Isaac } 2049566063dSJacob Faibussowitsch PetscCall(MatDenseRestoreArrayWrite(X, &v)); 2053ba16761SJacob Faibussowitsch PetscCallExternal(!cholmod_l_free_dense, &Y_handle, chol->common); 2069566063dSJacob Faibussowitsch PetscCall(MatDenseUnWrapCholmod(B, GET_ARRAY_READ, &cholB)); 2073ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 208a2fc1e05SToby Isaac } 209a2fc1e05SToby Isaac 210d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatQRFactorNumeric_SPQR(Mat F, Mat A, const MatFactorInfo *info) 211d71ae5a4SJacob Faibussowitsch { 212a2fc1e05SToby Isaac Mat_CHOLMOD *chol = (Mat_CHOLMOD *)F->data; 213a2fc1e05SToby Isaac cholmod_sparse cholA; 21465f45395SPierre Jolivet PetscBool aijalloc, valloc; 215d0609cedSBarry Smith int err; 216a2fc1e05SToby Isaac 217a2fc1e05SToby Isaac PetscFunctionBegin; 2189566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)A, MATNORMALHERMITIAN, &chol->normal)); 21948a46eb9SPierre Jolivet if (!chol->normal && !PetscDefined(USE_COMPLEX)) PetscCall(PetscObjectTypeCompare((PetscObject)A, MATNORMAL, &chol->normal)); 2209566063dSJacob Faibussowitsch PetscCall((*chol->Wrap)(A, PETSC_TRUE, &cholA, &aijalloc, &valloc)); 221d0609cedSBarry Smith err = !SuiteSparseQR_C_numeric(PETSC_SMALL, &cholA, chol->spqrfact, chol->common); 222d0609cedSBarry Smith PetscCheck(!err, PetscObjectComm((PetscObject)F), PETSC_ERR_LIB, "SPQR factorization failed with status %d", chol->common->status); 223a2fc1e05SToby Isaac 2249566063dSJacob Faibussowitsch if (aijalloc) PetscCall(PetscFree2(cholA.p, cholA.i)); 2259566063dSJacob Faibussowitsch if (valloc) PetscCall(PetscFree(cholA.x)); 226a2fc1e05SToby Isaac 227a2fc1e05SToby Isaac F->ops->solve = MatSolve_SPQR; 228a2fc1e05SToby Isaac F->ops->matsolve = MatMatSolve_SPQR; 22902ef7dfaSPierre Jolivet if (chol->normal) { 23002ef7dfaSPierre Jolivet F->ops->solvetranspose = MatSolve_SPQR; 23102ef7dfaSPierre Jolivet F->ops->matsolvetranspose = MatMatSolve_SPQR; 23202ef7dfaSPierre Jolivet } else if (A->cmap->n == A->rmap->n) { 233a2fc1e05SToby Isaac F->ops->solvetranspose = MatSolveTranspose_SPQR; 234a2fc1e05SToby Isaac F->ops->matsolvetranspose = MatMatSolveTranspose_SPQR; 235a2fc1e05SToby Isaac } 2363ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 237a2fc1e05SToby Isaac } 238a2fc1e05SToby Isaac 239d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode MatQRFactorSymbolic_SPQR(Mat F, Mat A, IS perm, const MatFactorInfo *info) 240d71ae5a4SJacob Faibussowitsch { 241a2fc1e05SToby Isaac Mat_CHOLMOD *chol = (Mat_CHOLMOD *)F->data; 242a2fc1e05SToby Isaac cholmod_sparse cholA; 24365f45395SPierre Jolivet PetscBool aijalloc, valloc; 244a2fc1e05SToby Isaac 245a2fc1e05SToby Isaac PetscFunctionBegin; 2469566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)A, MATNORMALHERMITIAN, &chol->normal)); 24748a46eb9SPierre Jolivet if (!chol->normal && !PetscDefined(USE_COMPLEX)) PetscCall(PetscObjectTypeCompare((PetscObject)A, MATNORMAL, &chol->normal)); 2489566063dSJacob Faibussowitsch PetscCall((*chol->Wrap)(A, PETSC_TRUE, &cholA, &aijalloc, &valloc)); 2493ba16761SJacob Faibussowitsch if (PetscDefined(USE_DEBUG)) PetscCallExternal(!cholmod_l_check_sparse, &cholA, chol->common); 2503ba16761SJacob Faibussowitsch if (chol->spqrfact) PetscCallExternal(!SuiteSparseQR_C_free, &chol->spqrfact, chol->common); 251d0f82a0bSPierre Jolivet chol->spqrfact = SuiteSparseQR_C_symbolic(SPQR_ORDERING_DEFAULT, 1, &cholA, chol->common); 25228b400f6SJacob Faibussowitsch PetscCheck(chol->spqrfact, PetscObjectComm((PetscObject)F), PETSC_ERR_LIB, "CHOLMOD analysis failed using internal ordering with status %d", chol->common->status); 253a2fc1e05SToby Isaac 2549566063dSJacob Faibussowitsch if (aijalloc) PetscCall(PetscFree2(cholA.p, cholA.i)); 2559566063dSJacob Faibussowitsch if (valloc) PetscCall(PetscFree(cholA.x)); 256a2fc1e05SToby Isaac 2579566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)F, "MatQRFactorNumeric_C", MatQRFactorNumeric_SPQR)); 2583ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 259a2fc1e05SToby Isaac } 260a2fc1e05SToby Isaac 261a2fc1e05SToby Isaac /*MC 262a2fc1e05SToby Isaac MATSOLVERSPQR 263a2fc1e05SToby Isaac 26411a5261eSBarry Smith A matrix type providing direct solvers, QR factorizations, for sequential matrices 265a2fc1e05SToby Isaac via the external package SPQR. 266a2fc1e05SToby Isaac 2672ef1f0ffSBarry Smith Use `./configure --download-suitesparse` to install PETSc to use SPQR 268a2fc1e05SToby Isaac 26911a5261eSBarry Smith Consult SPQR documentation for more information about the common parameters 270a2fc1e05SToby Isaac which correspond to the options database keys below. 271a2fc1e05SToby Isaac 272a2fc1e05SToby Isaac Level: beginner 273a2fc1e05SToby Isaac 27411a5261eSBarry Smith Note: 27511a5261eSBarry Smith SPQR is part of SuiteSparse http://faculty.cse.tamu.edu/davis/suitesparse.html 276a2fc1e05SToby Isaac 277*1cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `PCQR`, `PCFactorSetMatSolverType()`, `MatSolverType` 278a2fc1e05SToby Isaac M*/ 279a2fc1e05SToby Isaac 280d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode MatGetFactor_seqaij_spqr(Mat A, MatFactorType ftype, Mat *F) 281d71ae5a4SJacob Faibussowitsch { 282a2fc1e05SToby Isaac Mat B; 283a2fc1e05SToby Isaac Mat_CHOLMOD *chol; 284a2fc1e05SToby Isaac PetscInt m = A->rmap->n, n = A->cmap->n; 285a2fc1e05SToby Isaac const char *prefix; 286a2fc1e05SToby Isaac 287a2fc1e05SToby Isaac PetscFunctionBegin; 288a2fc1e05SToby Isaac /* Create the factorization matrix F */ 2899566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &B)); 2909566063dSJacob Faibussowitsch PetscCall(MatSetSizes(B, PETSC_DECIDE, PETSC_DECIDE, m, n)); 2919566063dSJacob Faibussowitsch PetscCall(PetscStrallocpy("spqr", &((PetscObject)B)->type_name)); 2929566063dSJacob Faibussowitsch PetscCall(MatGetOptionsPrefix(A, &prefix)); 2939566063dSJacob Faibussowitsch PetscCall(MatSetOptionsPrefix(B, prefix)); 2949566063dSJacob Faibussowitsch PetscCall(MatSetUp(B)); 2954dfa11a4SJacob Faibussowitsch PetscCall(PetscNew(&chol)); 296a2fc1e05SToby Isaac 297a2fc1e05SToby Isaac chol->Wrap = MatWrapCholmod_SPQR_seqaij; 298a2fc1e05SToby Isaac B->data = chol; 299a2fc1e05SToby Isaac 300a2fc1e05SToby Isaac B->ops->getinfo = MatGetInfo_CHOLMOD; 301a2fc1e05SToby Isaac B->ops->view = MatView_CHOLMOD; 302a2fc1e05SToby Isaac B->ops->destroy = MatDestroy_CHOLMOD; 303a2fc1e05SToby Isaac 3049566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatFactorGetSolverType_C", MatFactorGetSolverType_seqaij_SPQR)); 3059566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatQRFactorSymbolic_C", MatQRFactorSymbolic_SPQR)); 306a2fc1e05SToby Isaac 307a2fc1e05SToby Isaac B->factortype = MAT_FACTOR_QR; 308a2fc1e05SToby Isaac B->assembled = PETSC_TRUE; 309a2fc1e05SToby Isaac B->preallocated = PETSC_TRUE; 310a2fc1e05SToby Isaac 3119566063dSJacob Faibussowitsch PetscCall(PetscFree(B->solvertype)); 3129566063dSJacob Faibussowitsch PetscCall(PetscStrallocpy(MATSOLVERCHOLMOD, &B->solvertype)); 313a2fc1e05SToby Isaac B->canuseordering = PETSC_FALSE; 3149566063dSJacob Faibussowitsch PetscCall(CholmodStart(B)); 315a2fc1e05SToby Isaac chol->common->itype = CHOLMOD_LONG; 316a2fc1e05SToby Isaac *F = B; 3173ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 318a2fc1e05SToby Isaac } 319