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> 4*e2b46ddfSPierre Jolivet #include <../src/mat/impls/shell/shell.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; 13*e2b46ddfSPierre Jolivet Mat AT, B = NULL; 14*e2b46ddfSPierre Jolivet const PetscScalar *aa, *L = NULL; 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) { 24*e2b46ddfSPierre Jolivet PetscCall(MatNormalHermitianGetMat(A, &AT)); 2565f45395SPierre Jolivet } else if (!PetscDefined(USE_COMPLEX)) { 269566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)A, MATNORMAL, &flg)); 27*e2b46ddfSPierre Jolivet if (flg) PetscCall(MatNormalGetMat(A, &AT)); 28*e2b46ddfSPierre Jolivet } 29*e2b46ddfSPierre Jolivet if (flg) { 30*e2b46ddfSPierre Jolivet B = A; 31*e2b46ddfSPierre Jolivet A = AT; 32*e2b46ddfSPierre Jolivet PetscCheck(!((Mat_Shell *)B->data)->zrows && !((Mat_Shell *)B->data)->zcols, PetscObjectComm((PetscObject)B), PETSC_ERR_SUP, "Cannot call SuiteSparseQR if MatZeroRows() or MatZeroRowsColumns() has been called on the input Mat"); // TODO FIXME 33*e2b46ddfSPierre Jolivet PetscCheck(!((Mat_Shell *)B->data)->axpy, PetscObjectComm((PetscObject)B), PETSC_ERR_SUP, "Cannot call SuiteSparseQR if MatAXPY() has been called on the input Mat"); // TODO FIXME 34*e2b46ddfSPierre Jolivet PetscCheck(((Mat_Shell *)B->data)->left == ((Mat_Shell *)B->data)->right, PetscObjectComm((PetscObject)B), PETSC_ERR_SUP, "Cannot call SuiteSparseQR if MatDiagonalScale() has been called on the input Mat with L != R"); // TODO FIXME 35*e2b46ddfSPierre Jolivet if (values && ((Mat_Shell *)B->data)->left) { 36*e2b46ddfSPierre Jolivet PetscCall(VecGetArrayRead(((Mat_Shell *)B->data)->left, &L)); 37*e2b46ddfSPierre Jolivet #if PetscDefined(USE_COMPLEX) 38*e2b46ddfSPierre Jolivet for (j = 0; j < n; j++) 39*e2b46ddfSPierre 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"); 40*e2b46ddfSPierre Jolivet #endif 41*e2b46ddfSPierre Jolivet } 42*e2b46ddfSPierre Jolivet PetscCheck(!((Mat_Shell *)B->data)->dshift, PetscObjectComm((PetscObject)B), PETSC_ERR_SUP, "Cannot call SuiteSparseQR if MatDiagonalSet() has been called on the input Mat"); // TODO FIXME 43*e2b46ddfSPierre Jolivet PetscCheck(PetscAbsScalar(((Mat_Shell *)B->data)->vshift) < PETSC_MACHINE_EPSILON, PetscObjectComm((PetscObject)B), PETSC_ERR_SUP, "Cannot call SuiteSparseQR if MatShift() has been called on the input Mat"); // TODO FIXME 4465f45395SPierre Jolivet } 45a2fc1e05SToby Isaac /* cholmod_sparse is compressed sparse column */ 46b94d7dedSBarry Smith PetscCall(MatIsSymmetric(A, 0.0, &flg)); 4702ef7dfaSPierre Jolivet if (flg) { 489566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)A)); 49a2fc1e05SToby Isaac AT = A; 50a2fc1e05SToby Isaac } else { 519566063dSJacob Faibussowitsch PetscCall(MatTranspose(A, MAT_INITIAL_MATRIX, &AT)); 52a2fc1e05SToby Isaac } 53a2fc1e05SToby Isaac aij = (Mat_SeqAIJ *)AT->data; 54a2fc1e05SToby Isaac ai = aij->j; 55a2fc1e05SToby Isaac aj = aij->i; 56a2fc1e05SToby Isaac for (j = 0, nz = 0; j < n; j++) nz += aj[j + 1] - aj[j]; 579566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(n + 1, &cj, nz, &ci)); 58a2fc1e05SToby Isaac if (values) { 59a2fc1e05SToby Isaac vain = PETSC_TRUE; 609566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nz, &ca)); 619566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(AT, &aa)); 62a2fc1e05SToby Isaac } 63a2fc1e05SToby Isaac for (j = 0, k = 0; j < n; j++) { 64a2fc1e05SToby Isaac cj[j] = k; 65a2fc1e05SToby Isaac for (i = aj[j]; i < aj[j + 1]; i++, k++) { 66a2fc1e05SToby Isaac ci[k] = ai[i]; 67*e2b46ddfSPierre Jolivet if (values) { 68*e2b46ddfSPierre Jolivet ca[k] = aa[i]; 69*e2b46ddfSPierre Jolivet if (L) ca[k] *= L[j]; 70*e2b46ddfSPierre Jolivet } 71a2fc1e05SToby Isaac } 72a2fc1e05SToby Isaac } 73a2fc1e05SToby Isaac cj[j] = k; 74a2fc1e05SToby Isaac *aijalloc = PETSC_TRUE; 75a2fc1e05SToby Isaac *valloc = vain; 76*e2b46ddfSPierre Jolivet if (values) { 77*e2b46ddfSPierre Jolivet PetscCall(MatSeqAIJRestoreArrayRead(AT, &aa)); 78*e2b46ddfSPierre Jolivet if (L) PetscCall(VecRestoreArrayRead(((Mat_Shell *)B->data)->left, &L)); 79*e2b46ddfSPierre Jolivet } 80a2fc1e05SToby Isaac 819566063dSJacob Faibussowitsch PetscCall(PetscMemzero(C, sizeof(*C))); 82a2fc1e05SToby Isaac 8302ef7dfaSPierre Jolivet C->nrow = (size_t)AT->cmap->n; 8402ef7dfaSPierre Jolivet C->ncol = (size_t)AT->rmap->n; 85a2fc1e05SToby Isaac C->nzmax = (size_t)nz; 86a2fc1e05SToby Isaac C->p = cj; 87a2fc1e05SToby Isaac C->i = ci; 88a2fc1e05SToby Isaac C->x = values ? ca : 0; 89a2fc1e05SToby Isaac C->stype = 0; 90a2fc1e05SToby Isaac C->itype = CHOLMOD_LONG; 91a2fc1e05SToby Isaac C->xtype = values ? CHOLMOD_SCALAR_TYPE : CHOLMOD_PATTERN; 92a2fc1e05SToby Isaac C->dtype = CHOLMOD_DOUBLE; 93a2fc1e05SToby Isaac C->sorted = 1; 94a2fc1e05SToby Isaac C->packed = 1; 95a2fc1e05SToby Isaac 969566063dSJacob Faibussowitsch PetscCall(MatDestroy(&AT)); 973ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 98a2fc1e05SToby Isaac } 99a2fc1e05SToby Isaac 100d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatFactorGetSolverType_seqaij_SPQR(Mat A, MatSolverType *type) 101d71ae5a4SJacob Faibussowitsch { 102a2fc1e05SToby Isaac PetscFunctionBegin; 103a2fc1e05SToby Isaac *type = MATSOLVERSPQR; 1043ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 105a2fc1e05SToby Isaac } 106a2fc1e05SToby Isaac 107a2fc1e05SToby Isaac #define GET_ARRAY_READ 0 108a2fc1e05SToby Isaac #define GET_ARRAY_WRITE 1 109a2fc1e05SToby Isaac 110d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSolve_SPQR_Internal(Mat F, cholmod_dense *cholB, cholmod_dense **_Y_handle) 111d71ae5a4SJacob Faibussowitsch { 112a2fc1e05SToby Isaac Mat_CHOLMOD *chol = (Mat_CHOLMOD *)F->data; 11302ef7dfaSPierre Jolivet cholmod_dense *Y_handle = NULL, *QTB_handle = NULL, *Z_handle = NULL; 114a2fc1e05SToby Isaac 115a2fc1e05SToby Isaac PetscFunctionBegin; 11602ef7dfaSPierre Jolivet if (!chol->normal) { 117a2fc1e05SToby Isaac QTB_handle = SuiteSparseQR_C_qmult(SPQR_QTX, chol->spqrfact, cholB, chol->common); 11828b400f6SJacob Faibussowitsch PetscCheck(QTB_handle, PetscObjectComm((PetscObject)F), PETSC_ERR_LIB, "SuiteSparseQR_C_qmult failed"); 119a2fc1e05SToby Isaac Y_handle = SuiteSparseQR_C_solve(SPQR_RETX_EQUALS_B, chol->spqrfact, QTB_handle, chol->common); 12028b400f6SJacob Faibussowitsch PetscCheck(Y_handle, PetscObjectComm((PetscObject)F), PETSC_ERR_LIB, "SuiteSparseQR_C_solve failed"); 12102ef7dfaSPierre Jolivet } else { 12202ef7dfaSPierre Jolivet Z_handle = SuiteSparseQR_C_solve(SPQR_RTX_EQUALS_ETB, chol->spqrfact, cholB, chol->common); 12328b400f6SJacob Faibussowitsch PetscCheck(Z_handle, PetscObjectComm((PetscObject)F), PETSC_ERR_LIB, "SuiteSparseQR_C_solve failed"); 12402ef7dfaSPierre Jolivet Y_handle = SuiteSparseQR_C_solve(SPQR_RETX_EQUALS_B, chol->spqrfact, Z_handle, chol->common); 12528b400f6SJacob Faibussowitsch PetscCheck(Y_handle, PetscObjectComm((PetscObject)F), PETSC_ERR_LIB, "SuiteSparseQR_C_solve failed"); 1263ba16761SJacob Faibussowitsch PetscCallExternal(!cholmod_l_free_dense, &Z_handle, chol->common); 12702ef7dfaSPierre Jolivet } 128a2fc1e05SToby Isaac *_Y_handle = Y_handle; 1293ba16761SJacob Faibussowitsch PetscCallExternal(!cholmod_l_free_dense, &QTB_handle, chol->common); 1303ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 131a2fc1e05SToby Isaac } 132a2fc1e05SToby Isaac 133d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSolve_SPQR(Mat F, Vec B, Vec X) 134d71ae5a4SJacob Faibussowitsch { 135a2fc1e05SToby Isaac Mat_CHOLMOD *chol = (Mat_CHOLMOD *)F->data; 136a2fc1e05SToby Isaac cholmod_dense cholB, *Y_handle = NULL; 137a2fc1e05SToby Isaac PetscInt n; 138a2fc1e05SToby Isaac PetscScalar *v; 139a2fc1e05SToby Isaac 140a2fc1e05SToby Isaac PetscFunctionBegin; 1419566063dSJacob Faibussowitsch PetscCall(VecWrapCholmod(B, GET_ARRAY_READ, &cholB)); 1429566063dSJacob Faibussowitsch PetscCall(MatSolve_SPQR_Internal(F, &cholB, &Y_handle)); 1439566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(X, &n)); 1449566063dSJacob Faibussowitsch PetscCall(VecGetArrayWrite(X, &v)); 1459566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(v, (PetscScalar *)(Y_handle->x), n)); 1469566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayWrite(X, &v)); 1473ba16761SJacob Faibussowitsch PetscCallExternal(!cholmod_l_free_dense, &Y_handle, chol->common); 1489566063dSJacob Faibussowitsch PetscCall(VecUnWrapCholmod(B, GET_ARRAY_READ, &cholB)); 149*e2b46ddfSPierre Jolivet PetscCall(VecScale(X, chol->scale)); 1503ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 151a2fc1e05SToby Isaac } 152a2fc1e05SToby Isaac 153d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMatSolve_SPQR(Mat F, Mat B, Mat X) 154d71ae5a4SJacob Faibussowitsch { 155a2fc1e05SToby Isaac Mat_CHOLMOD *chol = (Mat_CHOLMOD *)F->data; 156a2fc1e05SToby Isaac cholmod_dense cholB, *Y_handle = NULL; 157a2fc1e05SToby Isaac PetscScalar *v; 158a2fc1e05SToby Isaac PetscInt lda; 159a2fc1e05SToby Isaac 160a2fc1e05SToby Isaac PetscFunctionBegin; 1619566063dSJacob Faibussowitsch PetscCall(MatDenseWrapCholmod(B, GET_ARRAY_READ, &cholB)); 1629566063dSJacob Faibussowitsch PetscCall(MatSolve_SPQR_Internal(F, &cholB, &Y_handle)); 1639566063dSJacob Faibussowitsch PetscCall(MatDenseGetArrayWrite(X, &v)); 1649566063dSJacob Faibussowitsch PetscCall(MatDenseGetLDA(X, &lda)); 165a2fc1e05SToby Isaac if ((size_t)lda == Y_handle->d) { 1669566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(v, (PetscScalar *)(Y_handle->x), lda * Y_handle->ncol)); 167a2fc1e05SToby Isaac } else { 16848a46eb9SPierre 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)); 169a2fc1e05SToby Isaac } 1709566063dSJacob Faibussowitsch PetscCall(MatDenseRestoreArrayWrite(X, &v)); 1713ba16761SJacob Faibussowitsch PetscCallExternal(!cholmod_l_free_dense, &Y_handle, chol->common); 1729566063dSJacob Faibussowitsch PetscCall(MatDenseUnWrapCholmod(B, GET_ARRAY_READ, &cholB)); 173*e2b46ddfSPierre Jolivet PetscCall(MatScale(X, chol->scale)); 1743ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 175a2fc1e05SToby Isaac } 176a2fc1e05SToby Isaac 177d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSolveTranspose_SPQR_Internal(Mat F, cholmod_dense *cholB, cholmod_dense **_Y_handle) 178d71ae5a4SJacob Faibussowitsch { 179a2fc1e05SToby Isaac Mat_CHOLMOD *chol = (Mat_CHOLMOD *)F->data; 180a2fc1e05SToby Isaac cholmod_dense *Y_handle = NULL, *RTB_handle = NULL; 181a2fc1e05SToby Isaac 182a2fc1e05SToby Isaac PetscFunctionBegin; 183a2fc1e05SToby Isaac RTB_handle = SuiteSparseQR_C_solve(SPQR_RTX_EQUALS_ETB, chol->spqrfact, cholB, chol->common); 18428b400f6SJacob Faibussowitsch PetscCheck(RTB_handle, PetscObjectComm((PetscObject)F), PETSC_ERR_LIB, "SuiteSparseQR_C_solve failed"); 185a2fc1e05SToby Isaac Y_handle = SuiteSparseQR_C_qmult(SPQR_QX, chol->spqrfact, RTB_handle, chol->common); 18628b400f6SJacob Faibussowitsch PetscCheck(Y_handle, PetscObjectComm((PetscObject)F), PETSC_ERR_LIB, "SuiteSparseQR_C_qmult failed"); 187a2fc1e05SToby Isaac *_Y_handle = Y_handle; 1883ba16761SJacob Faibussowitsch PetscCallExternal(!cholmod_l_free_dense, &RTB_handle, chol->common); 1893ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 190a2fc1e05SToby Isaac } 191a2fc1e05SToby Isaac 192d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSolveTranspose_SPQR(Mat F, Vec B, Vec X) 193d71ae5a4SJacob Faibussowitsch { 194a2fc1e05SToby Isaac Mat_CHOLMOD *chol = (Mat_CHOLMOD *)F->data; 195a2fc1e05SToby Isaac cholmod_dense cholB, *Y_handle = NULL; 196a2fc1e05SToby Isaac PetscInt n; 197a2fc1e05SToby Isaac PetscScalar *v; 198a2fc1e05SToby Isaac 199a2fc1e05SToby Isaac PetscFunctionBegin; 2009566063dSJacob Faibussowitsch PetscCall(VecWrapCholmod(B, GET_ARRAY_READ, &cholB)); 2019566063dSJacob Faibussowitsch PetscCall(MatSolveTranspose_SPQR_Internal(F, &cholB, &Y_handle)); 2029566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(X, &n)); 2039566063dSJacob Faibussowitsch PetscCall(VecGetArrayWrite(X, &v)); 2049566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(v, (PetscScalar *)Y_handle->x, n)); 2059566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayWrite(X, &v)); 2063ba16761SJacob Faibussowitsch PetscCallExternal(!cholmod_l_free_dense, &Y_handle, chol->common); 2079566063dSJacob Faibussowitsch PetscCall(VecUnWrapCholmod(B, GET_ARRAY_READ, &cholB)); 2083ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 209a2fc1e05SToby Isaac } 210a2fc1e05SToby Isaac 211d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMatSolveTranspose_SPQR(Mat F, Mat B, Mat X) 212d71ae5a4SJacob Faibussowitsch { 213a2fc1e05SToby Isaac Mat_CHOLMOD *chol = (Mat_CHOLMOD *)F->data; 214a2fc1e05SToby Isaac cholmod_dense cholB, *Y_handle = NULL; 215a2fc1e05SToby Isaac PetscScalar *v; 216a2fc1e05SToby Isaac PetscInt lda; 217a2fc1e05SToby Isaac 218a2fc1e05SToby Isaac PetscFunctionBegin; 2199566063dSJacob Faibussowitsch PetscCall(MatDenseWrapCholmod(B, GET_ARRAY_READ, &cholB)); 2209566063dSJacob Faibussowitsch PetscCall(MatSolveTranspose_SPQR_Internal(F, &cholB, &Y_handle)); 2219566063dSJacob Faibussowitsch PetscCall(MatDenseGetArrayWrite(X, &v)); 2229566063dSJacob Faibussowitsch PetscCall(MatDenseGetLDA(X, &lda)); 223a2fc1e05SToby Isaac if ((size_t)lda == Y_handle->d) { 2249566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(v, (PetscScalar *)Y_handle->x, lda * Y_handle->ncol)); 225a2fc1e05SToby Isaac } else { 22648a46eb9SPierre 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)); 227a2fc1e05SToby Isaac } 2289566063dSJacob Faibussowitsch PetscCall(MatDenseRestoreArrayWrite(X, &v)); 2293ba16761SJacob Faibussowitsch PetscCallExternal(!cholmod_l_free_dense, &Y_handle, chol->common); 2309566063dSJacob Faibussowitsch PetscCall(MatDenseUnWrapCholmod(B, GET_ARRAY_READ, &cholB)); 2313ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 232a2fc1e05SToby Isaac } 233a2fc1e05SToby Isaac 234d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatQRFactorNumeric_SPQR(Mat F, Mat A, const MatFactorInfo *info) 235d71ae5a4SJacob Faibussowitsch { 236a2fc1e05SToby Isaac Mat_CHOLMOD *chol = (Mat_CHOLMOD *)F->data; 237a2fc1e05SToby Isaac cholmod_sparse cholA; 23865f45395SPierre Jolivet PetscBool aijalloc, valloc; 239d0609cedSBarry Smith int err; 240a2fc1e05SToby Isaac 241a2fc1e05SToby Isaac PetscFunctionBegin; 2429566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)A, MATNORMALHERMITIAN, &chol->normal)); 24348a46eb9SPierre Jolivet if (!chol->normal && !PetscDefined(USE_COMPLEX)) PetscCall(PetscObjectTypeCompare((PetscObject)A, MATNORMAL, &chol->normal)); 2449566063dSJacob Faibussowitsch PetscCall((*chol->Wrap)(A, PETSC_TRUE, &cholA, &aijalloc, &valloc)); 245d0609cedSBarry Smith err = !SuiteSparseQR_C_numeric(PETSC_SMALL, &cholA, chol->spqrfact, chol->common); 246d0609cedSBarry Smith PetscCheck(!err, PetscObjectComm((PetscObject)F), PETSC_ERR_LIB, "SPQR factorization failed with status %d", chol->common->status); 247a2fc1e05SToby Isaac 2489566063dSJacob Faibussowitsch if (aijalloc) PetscCall(PetscFree2(cholA.p, cholA.i)); 2499566063dSJacob Faibussowitsch if (valloc) PetscCall(PetscFree(cholA.x)); 250a2fc1e05SToby Isaac 251a2fc1e05SToby Isaac F->ops->solve = MatSolve_SPQR; 252a2fc1e05SToby Isaac F->ops->matsolve = MatMatSolve_SPQR; 25302ef7dfaSPierre Jolivet if (chol->normal) { 25402ef7dfaSPierre Jolivet F->ops->solvetranspose = MatSolve_SPQR; 25502ef7dfaSPierre Jolivet F->ops->matsolvetranspose = MatMatSolve_SPQR; 256*e2b46ddfSPierre Jolivet chol->scale = 1.0 / ((Mat_Shell *)A->data)->vscale; 25702ef7dfaSPierre Jolivet } else if (A->cmap->n == A->rmap->n) { 258a2fc1e05SToby Isaac F->ops->solvetranspose = MatSolveTranspose_SPQR; 259a2fc1e05SToby Isaac F->ops->matsolvetranspose = MatMatSolveTranspose_SPQR; 260*e2b46ddfSPierre 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