1a2fc1e05SToby Isaac #include <petscsys.h> 2a2fc1e05SToby Isaac #include <../src/mat/impls/aij/seq/aij.h> 3a2fc1e05SToby Isaac #include <../src/mat/impls/sbaij/seq/cholmod/cholmodimpl.h> 4a2fc1e05SToby Isaac 5a2fc1e05SToby Isaac EXTERN_C_BEGIN 6a2fc1e05SToby Isaac #include <SuiteSparseQR_C.h> 7a2fc1e05SToby Isaac EXTERN_C_END 8a2fc1e05SToby Isaac 9d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatWrapCholmod_SPQR_seqaij(Mat A, PetscBool values, cholmod_sparse *C, PetscBool *aijalloc, PetscBool *valloc) 10d71ae5a4SJacob Faibussowitsch { 11a2fc1e05SToby Isaac Mat_SeqAIJ *aij; 12e2b46ddfSPierre Jolivet Mat AT, B = NULL; 13*b9c875b8SPierre Jolivet Vec left, right; 14e2b46ddfSPierre Jolivet const PetscScalar *aa, *L = NULL; 15*b9c875b8SPierre Jolivet PetscScalar *ca, scale; 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) { 24e2b46ddfSPierre Jolivet PetscCall(MatNormalHermitianGetMat(A, &AT)); 2565f45395SPierre Jolivet } else if (!PetscDefined(USE_COMPLEX)) { 269566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)A, MATNORMAL, &flg)); 27e2b46ddfSPierre Jolivet if (flg) PetscCall(MatNormalGetMat(A, &AT)); 28e2b46ddfSPierre Jolivet } 29e2b46ddfSPierre Jolivet if (flg) { 30e2b46ddfSPierre Jolivet B = A; 31e2b46ddfSPierre Jolivet A = AT; 32*b9c875b8SPierre Jolivet PetscCall(MatShellGetScalingShifts(B, (PetscScalar *)MAT_SHELL_NOT_ALLOWED, &scale, (Vec *)MAT_SHELL_NOT_ALLOWED, &left, &right, (Mat *)MAT_SHELL_NOT_ALLOWED, (IS *)MAT_SHELL_NOT_ALLOWED, (IS *)MAT_SHELL_NOT_ALLOWED)); 33*b9c875b8SPierre Jolivet PetscCheck(left == right, PetscObjectComm((PetscObject)B), PETSC_ERR_SUP, "Cannot call SuiteSparseQR if MatDiagonalScale() has been called on the input Mat with L != R"); 34*b9c875b8SPierre Jolivet if (values && left) { 35*b9c875b8SPierre Jolivet PetscCall(VecGetArrayRead(left, &L)); 36e2b46ddfSPierre Jolivet #if PetscDefined(USE_COMPLEX) 37e2b46ddfSPierre Jolivet for (j = 0; j < n; j++) 38e2b46ddfSPierre Jolivet PetscCheck(PetscAbsReal(PetscImaginaryPart(L[j])) < PETSC_MACHINE_EPSILON, PetscObjectComm((PetscObject)B), PETSC_ERR_SUP, "Cannot call SuiteSparseQR if MatDiagonalScale() has been called on the input Mat with a complex Vec"); 39e2b46ddfSPierre Jolivet #endif 40e2b46ddfSPierre Jolivet } 4165f45395SPierre Jolivet } 42a2fc1e05SToby Isaac /* cholmod_sparse is compressed sparse column */ 43b94d7dedSBarry Smith PetscCall(MatIsSymmetric(A, 0.0, &flg)); 4402ef7dfaSPierre Jolivet if (flg) { 459566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)A)); 46a2fc1e05SToby Isaac AT = A; 47a2fc1e05SToby Isaac } else { 489566063dSJacob Faibussowitsch PetscCall(MatTranspose(A, MAT_INITIAL_MATRIX, &AT)); 49a2fc1e05SToby Isaac } 50a2fc1e05SToby Isaac aij = (Mat_SeqAIJ *)AT->data; 51a2fc1e05SToby Isaac ai = aij->j; 52a2fc1e05SToby Isaac aj = aij->i; 53a2fc1e05SToby Isaac for (j = 0, nz = 0; j < n; j++) nz += aj[j + 1] - aj[j]; 549566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(n + 1, &cj, nz, &ci)); 55a2fc1e05SToby Isaac if (values) { 56a2fc1e05SToby Isaac vain = PETSC_TRUE; 579566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nz, &ca)); 589566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(AT, &aa)); 59a2fc1e05SToby Isaac } 60a2fc1e05SToby Isaac for (j = 0, k = 0; j < n; j++) { 61a2fc1e05SToby Isaac cj[j] = k; 62a2fc1e05SToby Isaac for (i = aj[j]; i < aj[j + 1]; i++, k++) { 63a2fc1e05SToby Isaac ci[k] = ai[i]; 64e2b46ddfSPierre Jolivet if (values) { 65e2b46ddfSPierre Jolivet ca[k] = aa[i]; 66e2b46ddfSPierre Jolivet if (L) ca[k] *= L[j]; 67e2b46ddfSPierre Jolivet } 68a2fc1e05SToby Isaac } 69a2fc1e05SToby Isaac } 70a2fc1e05SToby Isaac cj[j] = k; 71a2fc1e05SToby Isaac *aijalloc = PETSC_TRUE; 72a2fc1e05SToby Isaac *valloc = vain; 73e2b46ddfSPierre Jolivet if (values) { 74e2b46ddfSPierre Jolivet PetscCall(MatSeqAIJRestoreArrayRead(AT, &aa)); 75*b9c875b8SPierre Jolivet if (L) PetscCall(VecRestoreArrayRead(left, &L)); 76e2b46ddfSPierre Jolivet } 77a2fc1e05SToby Isaac 789566063dSJacob Faibussowitsch PetscCall(PetscMemzero(C, sizeof(*C))); 79a2fc1e05SToby Isaac 8002ef7dfaSPierre Jolivet C->nrow = (size_t)AT->cmap->n; 8102ef7dfaSPierre Jolivet C->ncol = (size_t)AT->rmap->n; 82a2fc1e05SToby Isaac C->nzmax = (size_t)nz; 83a2fc1e05SToby Isaac C->p = cj; 84a2fc1e05SToby Isaac C->i = ci; 85a2fc1e05SToby Isaac C->x = values ? ca : 0; 86a2fc1e05SToby Isaac C->stype = 0; 87a2fc1e05SToby Isaac C->itype = CHOLMOD_LONG; 88a2fc1e05SToby Isaac C->xtype = values ? CHOLMOD_SCALAR_TYPE : CHOLMOD_PATTERN; 89a2fc1e05SToby Isaac C->dtype = CHOLMOD_DOUBLE; 90a2fc1e05SToby Isaac C->sorted = 1; 91a2fc1e05SToby Isaac C->packed = 1; 92a2fc1e05SToby Isaac 939566063dSJacob Faibussowitsch PetscCall(MatDestroy(&AT)); 943ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 95a2fc1e05SToby Isaac } 96a2fc1e05SToby Isaac 97d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatFactorGetSolverType_seqaij_SPQR(Mat A, MatSolverType *type) 98d71ae5a4SJacob Faibussowitsch { 99a2fc1e05SToby Isaac PetscFunctionBegin; 100a2fc1e05SToby Isaac *type = MATSOLVERSPQR; 1013ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 102a2fc1e05SToby Isaac } 103a2fc1e05SToby Isaac 104a2fc1e05SToby Isaac #define GET_ARRAY_READ 0 105a2fc1e05SToby Isaac #define GET_ARRAY_WRITE 1 106a2fc1e05SToby Isaac 107d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSolve_SPQR_Internal(Mat F, cholmod_dense *cholB, cholmod_dense **_Y_handle) 108d71ae5a4SJacob Faibussowitsch { 109a2fc1e05SToby Isaac Mat_CHOLMOD *chol = (Mat_CHOLMOD *)F->data; 11002ef7dfaSPierre Jolivet cholmod_dense *Y_handle = NULL, *QTB_handle = NULL, *Z_handle = NULL; 111a2fc1e05SToby Isaac 112a2fc1e05SToby Isaac PetscFunctionBegin; 11302ef7dfaSPierre Jolivet if (!chol->normal) { 114a2fc1e05SToby Isaac QTB_handle = SuiteSparseQR_C_qmult(SPQR_QTX, chol->spqrfact, cholB, chol->common); 11528b400f6SJacob Faibussowitsch PetscCheck(QTB_handle, PetscObjectComm((PetscObject)F), PETSC_ERR_LIB, "SuiteSparseQR_C_qmult failed"); 116a2fc1e05SToby Isaac Y_handle = SuiteSparseQR_C_solve(SPQR_RETX_EQUALS_B, chol->spqrfact, QTB_handle, chol->common); 11728b400f6SJacob Faibussowitsch PetscCheck(Y_handle, PetscObjectComm((PetscObject)F), PETSC_ERR_LIB, "SuiteSparseQR_C_solve failed"); 11802ef7dfaSPierre Jolivet } else { 11902ef7dfaSPierre Jolivet Z_handle = SuiteSparseQR_C_solve(SPQR_RTX_EQUALS_ETB, chol->spqrfact, cholB, chol->common); 12028b400f6SJacob Faibussowitsch PetscCheck(Z_handle, PetscObjectComm((PetscObject)F), PETSC_ERR_LIB, "SuiteSparseQR_C_solve failed"); 12102ef7dfaSPierre Jolivet Y_handle = SuiteSparseQR_C_solve(SPQR_RETX_EQUALS_B, chol->spqrfact, Z_handle, chol->common); 12228b400f6SJacob Faibussowitsch PetscCheck(Y_handle, PetscObjectComm((PetscObject)F), PETSC_ERR_LIB, "SuiteSparseQR_C_solve failed"); 1233ba16761SJacob Faibussowitsch PetscCallExternal(!cholmod_l_free_dense, &Z_handle, chol->common); 12402ef7dfaSPierre Jolivet } 125a2fc1e05SToby Isaac *_Y_handle = Y_handle; 1263ba16761SJacob Faibussowitsch PetscCallExternal(!cholmod_l_free_dense, &QTB_handle, chol->common); 1273ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 128a2fc1e05SToby Isaac } 129a2fc1e05SToby Isaac 130d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSolve_SPQR(Mat F, Vec B, Vec X) 131d71ae5a4SJacob Faibussowitsch { 132a2fc1e05SToby Isaac Mat_CHOLMOD *chol = (Mat_CHOLMOD *)F->data; 133a2fc1e05SToby Isaac cholmod_dense cholB, *Y_handle = NULL; 134a2fc1e05SToby Isaac PetscInt n; 135a2fc1e05SToby Isaac PetscScalar *v; 136a2fc1e05SToby Isaac 137a2fc1e05SToby Isaac PetscFunctionBegin; 1389566063dSJacob Faibussowitsch PetscCall(VecWrapCholmod(B, GET_ARRAY_READ, &cholB)); 1399566063dSJacob Faibussowitsch PetscCall(MatSolve_SPQR_Internal(F, &cholB, &Y_handle)); 1409566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(X, &n)); 1419566063dSJacob Faibussowitsch PetscCall(VecGetArrayWrite(X, &v)); 142f4f49eeaSPierre Jolivet PetscCall(PetscArraycpy(v, (PetscScalar *)Y_handle->x, n)); 1439566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayWrite(X, &v)); 1443ba16761SJacob Faibussowitsch PetscCallExternal(!cholmod_l_free_dense, &Y_handle, chol->common); 1459566063dSJacob Faibussowitsch PetscCall(VecUnWrapCholmod(B, GET_ARRAY_READ, &cholB)); 146e2b46ddfSPierre Jolivet PetscCall(VecScale(X, chol->scale)); 1473ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 148a2fc1e05SToby Isaac } 149a2fc1e05SToby Isaac 150d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMatSolve_SPQR(Mat F, Mat B, Mat X) 151d71ae5a4SJacob Faibussowitsch { 152a2fc1e05SToby Isaac Mat_CHOLMOD *chol = (Mat_CHOLMOD *)F->data; 153a2fc1e05SToby Isaac cholmod_dense cholB, *Y_handle = NULL; 154a2fc1e05SToby Isaac PetscScalar *v; 155a2fc1e05SToby Isaac PetscInt lda; 156a2fc1e05SToby Isaac 157a2fc1e05SToby Isaac PetscFunctionBegin; 1589566063dSJacob Faibussowitsch PetscCall(MatDenseWrapCholmod(B, GET_ARRAY_READ, &cholB)); 1599566063dSJacob Faibussowitsch PetscCall(MatSolve_SPQR_Internal(F, &cholB, &Y_handle)); 1609566063dSJacob Faibussowitsch PetscCall(MatDenseGetArrayWrite(X, &v)); 1619566063dSJacob Faibussowitsch PetscCall(MatDenseGetLDA(X, &lda)); 162a2fc1e05SToby Isaac if ((size_t)lda == Y_handle->d) { 163f4f49eeaSPierre Jolivet PetscCall(PetscArraycpy(v, (PetscScalar *)Y_handle->x, lda * Y_handle->ncol)); 164a2fc1e05SToby Isaac } else { 16548a46eb9SPierre 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)); 166a2fc1e05SToby Isaac } 1679566063dSJacob Faibussowitsch PetscCall(MatDenseRestoreArrayWrite(X, &v)); 1683ba16761SJacob Faibussowitsch PetscCallExternal(!cholmod_l_free_dense, &Y_handle, chol->common); 1699566063dSJacob Faibussowitsch PetscCall(MatDenseUnWrapCholmod(B, GET_ARRAY_READ, &cholB)); 170e2b46ddfSPierre Jolivet PetscCall(MatScale(X, chol->scale)); 1713ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 172a2fc1e05SToby Isaac } 173a2fc1e05SToby Isaac 174d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSolveTranspose_SPQR_Internal(Mat F, cholmod_dense *cholB, cholmod_dense **_Y_handle) 175d71ae5a4SJacob Faibussowitsch { 176a2fc1e05SToby Isaac Mat_CHOLMOD *chol = (Mat_CHOLMOD *)F->data; 177a2fc1e05SToby Isaac cholmod_dense *Y_handle = NULL, *RTB_handle = NULL; 178a2fc1e05SToby Isaac 179a2fc1e05SToby Isaac PetscFunctionBegin; 180a2fc1e05SToby Isaac RTB_handle = SuiteSparseQR_C_solve(SPQR_RTX_EQUALS_ETB, chol->spqrfact, cholB, chol->common); 18128b400f6SJacob Faibussowitsch PetscCheck(RTB_handle, PetscObjectComm((PetscObject)F), PETSC_ERR_LIB, "SuiteSparseQR_C_solve failed"); 182a2fc1e05SToby Isaac Y_handle = SuiteSparseQR_C_qmult(SPQR_QX, chol->spqrfact, RTB_handle, chol->common); 18328b400f6SJacob Faibussowitsch PetscCheck(Y_handle, PetscObjectComm((PetscObject)F), PETSC_ERR_LIB, "SuiteSparseQR_C_qmult failed"); 184a2fc1e05SToby Isaac *_Y_handle = Y_handle; 1853ba16761SJacob Faibussowitsch PetscCallExternal(!cholmod_l_free_dense, &RTB_handle, chol->common); 1863ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 187a2fc1e05SToby Isaac } 188a2fc1e05SToby Isaac 189d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSolveTranspose_SPQR(Mat F, Vec B, Vec X) 190d71ae5a4SJacob Faibussowitsch { 191a2fc1e05SToby Isaac Mat_CHOLMOD *chol = (Mat_CHOLMOD *)F->data; 192a2fc1e05SToby Isaac cholmod_dense cholB, *Y_handle = NULL; 193a2fc1e05SToby Isaac PetscInt n; 194a2fc1e05SToby Isaac PetscScalar *v; 195a2fc1e05SToby Isaac 196a2fc1e05SToby Isaac PetscFunctionBegin; 1979566063dSJacob Faibussowitsch PetscCall(VecWrapCholmod(B, GET_ARRAY_READ, &cholB)); 1989566063dSJacob Faibussowitsch PetscCall(MatSolveTranspose_SPQR_Internal(F, &cholB, &Y_handle)); 1999566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(X, &n)); 2009566063dSJacob Faibussowitsch PetscCall(VecGetArrayWrite(X, &v)); 2019566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(v, (PetscScalar *)Y_handle->x, n)); 2029566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayWrite(X, &v)); 2033ba16761SJacob Faibussowitsch PetscCallExternal(!cholmod_l_free_dense, &Y_handle, chol->common); 2049566063dSJacob Faibussowitsch PetscCall(VecUnWrapCholmod(B, GET_ARRAY_READ, &cholB)); 2053ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 206a2fc1e05SToby Isaac } 207a2fc1e05SToby Isaac 208d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMatSolveTranspose_SPQR(Mat F, Mat B, Mat X) 209d71ae5a4SJacob Faibussowitsch { 210a2fc1e05SToby Isaac Mat_CHOLMOD *chol = (Mat_CHOLMOD *)F->data; 211a2fc1e05SToby Isaac cholmod_dense cholB, *Y_handle = NULL; 212a2fc1e05SToby Isaac PetscScalar *v; 213a2fc1e05SToby Isaac PetscInt lda; 214a2fc1e05SToby Isaac 215a2fc1e05SToby Isaac PetscFunctionBegin; 2169566063dSJacob Faibussowitsch PetscCall(MatDenseWrapCholmod(B, GET_ARRAY_READ, &cholB)); 2179566063dSJacob Faibussowitsch PetscCall(MatSolveTranspose_SPQR_Internal(F, &cholB, &Y_handle)); 2189566063dSJacob Faibussowitsch PetscCall(MatDenseGetArrayWrite(X, &v)); 2199566063dSJacob Faibussowitsch PetscCall(MatDenseGetLDA(X, &lda)); 220a2fc1e05SToby Isaac if ((size_t)lda == Y_handle->d) { 2219566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(v, (PetscScalar *)Y_handle->x, lda * Y_handle->ncol)); 222a2fc1e05SToby Isaac } else { 22348a46eb9SPierre 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)); 224a2fc1e05SToby Isaac } 2259566063dSJacob Faibussowitsch PetscCall(MatDenseRestoreArrayWrite(X, &v)); 2263ba16761SJacob Faibussowitsch PetscCallExternal(!cholmod_l_free_dense, &Y_handle, chol->common); 2279566063dSJacob Faibussowitsch PetscCall(MatDenseUnWrapCholmod(B, GET_ARRAY_READ, &cholB)); 2283ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 229a2fc1e05SToby Isaac } 230a2fc1e05SToby Isaac 231d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatQRFactorNumeric_SPQR(Mat F, Mat A, const MatFactorInfo *info) 232d71ae5a4SJacob Faibussowitsch { 233a2fc1e05SToby Isaac Mat_CHOLMOD *chol = (Mat_CHOLMOD *)F->data; 234a2fc1e05SToby Isaac cholmod_sparse cholA; 23565f45395SPierre Jolivet PetscBool aijalloc, valloc; 236d0609cedSBarry Smith int err; 237a2fc1e05SToby Isaac 238a2fc1e05SToby Isaac PetscFunctionBegin; 2399566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)A, MATNORMALHERMITIAN, &chol->normal)); 24048a46eb9SPierre Jolivet if (!chol->normal && !PetscDefined(USE_COMPLEX)) PetscCall(PetscObjectTypeCompare((PetscObject)A, MATNORMAL, &chol->normal)); 2419566063dSJacob Faibussowitsch PetscCall((*chol->Wrap)(A, PETSC_TRUE, &cholA, &aijalloc, &valloc)); 242d0609cedSBarry Smith err = !SuiteSparseQR_C_numeric(PETSC_SMALL, &cholA, chol->spqrfact, chol->common); 243d0609cedSBarry Smith PetscCheck(!err, PetscObjectComm((PetscObject)F), PETSC_ERR_LIB, "SPQR factorization failed with status %d", chol->common->status); 244a2fc1e05SToby Isaac 2459566063dSJacob Faibussowitsch if (aijalloc) PetscCall(PetscFree2(cholA.p, cholA.i)); 2469566063dSJacob Faibussowitsch if (valloc) PetscCall(PetscFree(cholA.x)); 247a2fc1e05SToby Isaac 248a2fc1e05SToby Isaac F->ops->solve = MatSolve_SPQR; 249a2fc1e05SToby Isaac F->ops->matsolve = MatMatSolve_SPQR; 25002ef7dfaSPierre Jolivet if (chol->normal) { 251*b9c875b8SPierre Jolivet PetscScalar scale; 252*b9c875b8SPierre Jolivet 253*b9c875b8SPierre Jolivet PetscCall(MatShellGetScalingShifts(A, (PetscScalar *)MAT_SHELL_NOT_ALLOWED, &scale, (Vec *)MAT_SHELL_NOT_ALLOWED, NULL, NULL, (Mat *)MAT_SHELL_NOT_ALLOWED, (IS *)MAT_SHELL_NOT_ALLOWED, (IS *)MAT_SHELL_NOT_ALLOWED)); 25402ef7dfaSPierre Jolivet F->ops->solvetranspose = MatSolve_SPQR; 25502ef7dfaSPierre Jolivet F->ops->matsolvetranspose = MatMatSolve_SPQR; 256*b9c875b8SPierre Jolivet chol->scale = 1.0 / scale; 25702ef7dfaSPierre Jolivet } else if (A->cmap->n == A->rmap->n) { 258a2fc1e05SToby Isaac F->ops->solvetranspose = MatSolveTranspose_SPQR; 259a2fc1e05SToby Isaac F->ops->matsolvetranspose = MatMatSolveTranspose_SPQR; 260e2b46ddfSPierre Jolivet chol->scale = 1.0; 261a2fc1e05SToby Isaac } 2623ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 263a2fc1e05SToby Isaac } 264a2fc1e05SToby Isaac 265d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode MatQRFactorSymbolic_SPQR(Mat F, Mat A, IS perm, const MatFactorInfo *info) 266d71ae5a4SJacob Faibussowitsch { 267a2fc1e05SToby Isaac Mat_CHOLMOD *chol = (Mat_CHOLMOD *)F->data; 268a2fc1e05SToby Isaac cholmod_sparse cholA; 26965f45395SPierre Jolivet PetscBool aijalloc, valloc; 270a2fc1e05SToby Isaac 271a2fc1e05SToby Isaac PetscFunctionBegin; 2729566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)A, MATNORMALHERMITIAN, &chol->normal)); 27348a46eb9SPierre Jolivet if (!chol->normal && !PetscDefined(USE_COMPLEX)) PetscCall(PetscObjectTypeCompare((PetscObject)A, MATNORMAL, &chol->normal)); 2749566063dSJacob Faibussowitsch PetscCall((*chol->Wrap)(A, PETSC_TRUE, &cholA, &aijalloc, &valloc)); 2753ba16761SJacob Faibussowitsch if (PetscDefined(USE_DEBUG)) PetscCallExternal(!cholmod_l_check_sparse, &cholA, chol->common); 2763ba16761SJacob Faibussowitsch if (chol->spqrfact) PetscCallExternal(!SuiteSparseQR_C_free, &chol->spqrfact, chol->common); 277d0f82a0bSPierre Jolivet chol->spqrfact = SuiteSparseQR_C_symbolic(SPQR_ORDERING_DEFAULT, 1, &cholA, chol->common); 27828b400f6SJacob Faibussowitsch PetscCheck(chol->spqrfact, PetscObjectComm((PetscObject)F), PETSC_ERR_LIB, "CHOLMOD analysis failed using internal ordering with status %d", chol->common->status); 279a2fc1e05SToby Isaac 2809566063dSJacob Faibussowitsch if (aijalloc) PetscCall(PetscFree2(cholA.p, cholA.i)); 2819566063dSJacob Faibussowitsch if (valloc) PetscCall(PetscFree(cholA.x)); 282a2fc1e05SToby Isaac 2839566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)F, "MatQRFactorNumeric_C", MatQRFactorNumeric_SPQR)); 2843ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 285a2fc1e05SToby Isaac } 286a2fc1e05SToby Isaac 287a2fc1e05SToby Isaac /*MC 288a2fc1e05SToby Isaac MATSOLVERSPQR 289a2fc1e05SToby Isaac 29011a5261eSBarry Smith A matrix type providing direct solvers, QR factorizations, for sequential matrices 291a2fc1e05SToby Isaac via the external package SPQR. 292a2fc1e05SToby Isaac 2932ef1f0ffSBarry Smith Use `./configure --download-suitesparse` to install PETSc to use SPQR 294a2fc1e05SToby Isaac 29511a5261eSBarry Smith Consult SPQR documentation for more information about the common parameters 296a2fc1e05SToby Isaac which correspond to the options database keys below. 297a2fc1e05SToby Isaac 298a2fc1e05SToby Isaac Level: beginner 299a2fc1e05SToby Isaac 30011a5261eSBarry Smith Note: 3011d27aa22SBarry Smith SPQR is part of SuiteSparse <http://faculty.cse.tamu.edu/davis/suitesparse.html> 302a2fc1e05SToby Isaac 3031cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `PCQR`, `PCFactorSetMatSolverType()`, `MatSolverType` 304a2fc1e05SToby Isaac M*/ 305a2fc1e05SToby Isaac 306d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode MatGetFactor_seqaij_spqr(Mat A, MatFactorType ftype, Mat *F) 307d71ae5a4SJacob Faibussowitsch { 308a2fc1e05SToby Isaac Mat B; 309a2fc1e05SToby Isaac Mat_CHOLMOD *chol; 310a2fc1e05SToby Isaac PetscInt m = A->rmap->n, n = A->cmap->n; 311a2fc1e05SToby Isaac const char *prefix; 312a2fc1e05SToby Isaac 313a2fc1e05SToby Isaac PetscFunctionBegin; 314a2fc1e05SToby Isaac /* Create the factorization matrix F */ 3159566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &B)); 3169566063dSJacob Faibussowitsch PetscCall(MatSetSizes(B, PETSC_DECIDE, PETSC_DECIDE, m, n)); 3179566063dSJacob Faibussowitsch PetscCall(PetscStrallocpy("spqr", &((PetscObject)B)->type_name)); 3189566063dSJacob Faibussowitsch PetscCall(MatGetOptionsPrefix(A, &prefix)); 3199566063dSJacob Faibussowitsch PetscCall(MatSetOptionsPrefix(B, prefix)); 3209566063dSJacob Faibussowitsch PetscCall(MatSetUp(B)); 3214dfa11a4SJacob Faibussowitsch PetscCall(PetscNew(&chol)); 322a2fc1e05SToby Isaac 323a2fc1e05SToby Isaac chol->Wrap = MatWrapCholmod_SPQR_seqaij; 324a2fc1e05SToby Isaac B->data = chol; 325a2fc1e05SToby Isaac 326a2fc1e05SToby Isaac B->ops->getinfo = MatGetInfo_CHOLMOD; 327a2fc1e05SToby Isaac B->ops->view = MatView_CHOLMOD; 328a2fc1e05SToby Isaac B->ops->destroy = MatDestroy_CHOLMOD; 329a2fc1e05SToby Isaac 3309566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatFactorGetSolverType_C", MatFactorGetSolverType_seqaij_SPQR)); 3319566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatQRFactorSymbolic_C", MatQRFactorSymbolic_SPQR)); 332a2fc1e05SToby Isaac 333a2fc1e05SToby Isaac B->factortype = MAT_FACTOR_QR; 334a2fc1e05SToby Isaac B->assembled = PETSC_TRUE; 335a2fc1e05SToby Isaac B->preallocated = PETSC_TRUE; 336a2fc1e05SToby Isaac 3379566063dSJacob Faibussowitsch PetscCall(PetscFree(B->solvertype)); 3389566063dSJacob Faibussowitsch PetscCall(PetscStrallocpy(MATSOLVERCHOLMOD, &B->solvertype)); 339a2fc1e05SToby Isaac B->canuseordering = PETSC_FALSE; 3409566063dSJacob Faibussowitsch PetscCall(CholmodStart(B)); 341a2fc1e05SToby Isaac chol->common->itype = CHOLMOD_LONG; 342a2fc1e05SToby Isaac *F = B; 3433ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 344a2fc1e05SToby Isaac } 345