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 10a2fc1e05SToby Isaac static PetscErrorCode MatWrapCholmod_SPQR_seqaij(Mat A,PetscBool values,cholmod_sparse *C,PetscBool *aijalloc,PetscBool *valloc) 11a2fc1e05SToby Isaac { 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 PetscErrorCode ierr; 21a2fc1e05SToby Isaac 22a2fc1e05SToby Isaac PetscFunctionBegin; 23*65f45395SPierre Jolivet ierr = PetscObjectTypeCompare((PetscObject)A, MATNORMALHERMITIAN, &flg);CHKERRQ(ierr); 24*65f45395SPierre Jolivet if (flg) { 25*65f45395SPierre Jolivet ierr = MatNormalHermitianGetMat(A, &A);CHKERRQ(ierr); 26*65f45395SPierre Jolivet } else if (!PetscDefined(USE_COMPLEX)) { 2702ef7dfaSPierre Jolivet ierr = PetscObjectTypeCompare((PetscObject)A, MATNORMAL, &flg);CHKERRQ(ierr); 2802ef7dfaSPierre Jolivet if (flg) { 2902ef7dfaSPierre Jolivet ierr = MatNormalGetMat(A, &A);CHKERRQ(ierr); 3002ef7dfaSPierre Jolivet } 31*65f45395SPierre Jolivet } 32a2fc1e05SToby Isaac /* cholmod_sparse is compressed sparse column */ 3302ef7dfaSPierre Jolivet ierr = MatGetOption(A, MAT_SYMMETRIC, &flg);CHKERRQ(ierr); 3402ef7dfaSPierre Jolivet if (flg) { 35a2fc1e05SToby Isaac ierr = PetscObjectReference((PetscObject)A);CHKERRQ(ierr); 36a2fc1e05SToby Isaac AT = A; 37a2fc1e05SToby Isaac } else { 38a2fc1e05SToby Isaac ierr = MatTranspose(A, MAT_INITIAL_MATRIX, &AT);CHKERRQ(ierr); 39a2fc1e05SToby Isaac } 40a2fc1e05SToby Isaac aij = (Mat_SeqAIJ*)AT->data; 41a2fc1e05SToby Isaac ai = aij->j; 42a2fc1e05SToby Isaac aj = aij->i; 43a2fc1e05SToby Isaac for (j=0,nz=0; j<n; j++) nz += aj[j+1] - aj[j]; 44a2fc1e05SToby Isaac ierr = PetscMalloc2(n+1,&cj,nz,&ci);CHKERRQ(ierr); 45a2fc1e05SToby Isaac if (values) { 46a2fc1e05SToby Isaac vain = PETSC_TRUE; 47a2fc1e05SToby Isaac ierr = PetscMalloc1(nz,&ca);CHKERRQ(ierr); 48a2fc1e05SToby Isaac ierr = MatSeqAIJGetArrayRead(AT,&aa);CHKERRQ(ierr); 49a2fc1e05SToby Isaac } 50a2fc1e05SToby Isaac for (j=0,k=0; j<n; j++) { 51a2fc1e05SToby Isaac cj[j] = k; 52a2fc1e05SToby Isaac for (i=aj[j]; i<aj[j+1]; i++,k++) { 53a2fc1e05SToby Isaac ci[k] = ai[i]; 54a2fc1e05SToby Isaac if (values) ca[k] = aa[i]; 55a2fc1e05SToby Isaac } 56a2fc1e05SToby Isaac } 57a2fc1e05SToby Isaac cj[j] = k; 58a2fc1e05SToby Isaac *aijalloc = PETSC_TRUE; 59a2fc1e05SToby Isaac *valloc = vain; 60a2fc1e05SToby Isaac if (values) { 61b2397800SPierre Jolivet ierr = MatSeqAIJRestoreArrayRead(AT,&aa);CHKERRQ(ierr); 62a2fc1e05SToby Isaac } 63a2fc1e05SToby Isaac 64a2fc1e05SToby Isaac ierr = PetscMemzero(C,sizeof(*C));CHKERRQ(ierr); 65a2fc1e05SToby Isaac 6602ef7dfaSPierre Jolivet C->nrow = (size_t)AT->cmap->n; 6702ef7dfaSPierre Jolivet C->ncol = (size_t)AT->rmap->n; 68a2fc1e05SToby Isaac C->nzmax = (size_t)nz; 69a2fc1e05SToby Isaac C->p = cj; 70a2fc1e05SToby Isaac C->i = ci; 71a2fc1e05SToby Isaac C->x = values ? ca : 0; 72a2fc1e05SToby Isaac C->stype = 0; 73a2fc1e05SToby Isaac C->itype = CHOLMOD_LONG; 74a2fc1e05SToby Isaac C->xtype = values ? CHOLMOD_SCALAR_TYPE : CHOLMOD_PATTERN; 75a2fc1e05SToby Isaac C->dtype = CHOLMOD_DOUBLE; 76a2fc1e05SToby Isaac C->sorted = 1; 77a2fc1e05SToby Isaac C->packed = 1; 78a2fc1e05SToby Isaac 79a2fc1e05SToby Isaac ierr = MatDestroy(&AT);CHKERRQ(ierr); 80a2fc1e05SToby Isaac PetscFunctionReturn(0); 81a2fc1e05SToby Isaac } 82a2fc1e05SToby Isaac 83a2fc1e05SToby Isaac static PetscErrorCode MatFactorGetSolverType_seqaij_SPQR(Mat A,MatSolverType *type) 84a2fc1e05SToby Isaac { 85a2fc1e05SToby Isaac PetscFunctionBegin; 86a2fc1e05SToby Isaac *type = MATSOLVERSPQR; 87a2fc1e05SToby Isaac PetscFunctionReturn(0); 88a2fc1e05SToby Isaac } 89a2fc1e05SToby Isaac 90a2fc1e05SToby Isaac #define GET_ARRAY_READ 0 91a2fc1e05SToby Isaac #define GET_ARRAY_WRITE 1 92a2fc1e05SToby Isaac 93a2fc1e05SToby Isaac static PetscErrorCode MatSolve_SPQR_Internal(Mat F, cholmod_dense *cholB, cholmod_dense **_Y_handle) 94a2fc1e05SToby Isaac { 95a2fc1e05SToby Isaac Mat_CHOLMOD *chol = (Mat_CHOLMOD*)F->data; 9602ef7dfaSPierre Jolivet cholmod_dense *Y_handle = NULL, *QTB_handle = NULL, *Z_handle = NULL; 97a2fc1e05SToby Isaac PetscErrorCode ierr; 98a2fc1e05SToby Isaac 99a2fc1e05SToby Isaac PetscFunctionBegin; 10002ef7dfaSPierre Jolivet if (!chol->normal) { 101a2fc1e05SToby Isaac QTB_handle = SuiteSparseQR_C_qmult(SPQR_QTX, chol->spqrfact, cholB, chol->common); 102a2fc1e05SToby Isaac if (!QTB_handle) SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_LIB, "SuiteSparseQR_C_qmult failed"); 103a2fc1e05SToby Isaac Y_handle = SuiteSparseQR_C_solve(SPQR_RETX_EQUALS_B, chol->spqrfact, QTB_handle, chol->common); 104a2fc1e05SToby Isaac if (!Y_handle) SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_LIB, "SuiteSparseQR_C_solve failed"); 10502ef7dfaSPierre Jolivet } else { 10602ef7dfaSPierre Jolivet Z_handle = SuiteSparseQR_C_solve(SPQR_RTX_EQUALS_ETB, chol->spqrfact, cholB, chol->common); 10702ef7dfaSPierre Jolivet if (!Z_handle) SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_LIB, "SuiteSparseQR_C_solve failed"); 10802ef7dfaSPierre Jolivet Y_handle = SuiteSparseQR_C_solve(SPQR_RETX_EQUALS_B, chol->spqrfact, Z_handle, chol->common); 10902ef7dfaSPierre Jolivet if (!Y_handle) SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_LIB, "SuiteSparseQR_C_solve failed"); 11002ef7dfaSPierre Jolivet ierr = !cholmod_l_free_dense(&Z_handle, chol->common);CHKERRQ(ierr); 11102ef7dfaSPierre Jolivet } 112a2fc1e05SToby Isaac *_Y_handle = Y_handle; 113a2fc1e05SToby Isaac ierr = !cholmod_l_free_dense(&QTB_handle, chol->common);CHKERRQ(ierr); 114a2fc1e05SToby Isaac PetscFunctionReturn(0); 115a2fc1e05SToby Isaac } 116a2fc1e05SToby Isaac 117a2fc1e05SToby Isaac static PetscErrorCode MatSolve_SPQR(Mat F,Vec B,Vec X) 118a2fc1e05SToby Isaac { 119a2fc1e05SToby Isaac Mat_CHOLMOD *chol = (Mat_CHOLMOD*)F->data; 120a2fc1e05SToby Isaac cholmod_dense cholB,*Y_handle = NULL; 121a2fc1e05SToby Isaac PetscInt n; 122a2fc1e05SToby Isaac PetscScalar *v; 123a2fc1e05SToby Isaac PetscErrorCode ierr; 124a2fc1e05SToby Isaac 125a2fc1e05SToby Isaac PetscFunctionBegin; 126a2fc1e05SToby Isaac ierr = VecWrapCholmod(B,GET_ARRAY_READ,&cholB);CHKERRQ(ierr); 127a2fc1e05SToby Isaac ierr = MatSolve_SPQR_Internal(F, &cholB, &Y_handle);CHKERRQ(ierr); 128a2fc1e05SToby Isaac ierr = VecGetLocalSize(X, &n);CHKERRQ(ierr); 129a2fc1e05SToby Isaac ierr = VecGetArrayWrite(X, &v);CHKERRQ(ierr); 130a2fc1e05SToby Isaac ierr = PetscArraycpy(v, (PetscScalar *) (Y_handle->x), n);CHKERRQ(ierr); 131a2fc1e05SToby Isaac ierr = VecRestoreArrayWrite(X, &v);CHKERRQ(ierr); 132a2fc1e05SToby Isaac ierr = !cholmod_l_free_dense(&Y_handle, chol->common);CHKERRQ(ierr); 133a2fc1e05SToby Isaac ierr = VecUnWrapCholmod(B,GET_ARRAY_READ,&cholB);CHKERRQ(ierr); 134a2fc1e05SToby Isaac PetscFunctionReturn(0); 135a2fc1e05SToby Isaac } 136a2fc1e05SToby Isaac 137a2fc1e05SToby Isaac static PetscErrorCode MatMatSolve_SPQR(Mat F,Mat B,Mat X) 138a2fc1e05SToby Isaac { 139a2fc1e05SToby Isaac Mat_CHOLMOD *chol = (Mat_CHOLMOD*)F->data; 140a2fc1e05SToby Isaac cholmod_dense cholB,*Y_handle = NULL; 141a2fc1e05SToby Isaac PetscScalar *v; 142a2fc1e05SToby Isaac PetscInt lda; 143a2fc1e05SToby Isaac PetscErrorCode ierr; 144a2fc1e05SToby Isaac 145a2fc1e05SToby Isaac PetscFunctionBegin; 146a2fc1e05SToby Isaac ierr = MatDenseWrapCholmod(B,GET_ARRAY_READ,&cholB);CHKERRQ(ierr); 147a2fc1e05SToby Isaac ierr = MatSolve_SPQR_Internal(F, &cholB, &Y_handle);CHKERRQ(ierr); 148a2fc1e05SToby Isaac ierr = MatDenseGetArrayWrite(X, &v);CHKERRQ(ierr); 149a2fc1e05SToby Isaac ierr = MatDenseGetLDA(X, &lda);CHKERRQ(ierr); 150a2fc1e05SToby Isaac if ((size_t) lda == Y_handle->d) { 151a2fc1e05SToby Isaac ierr = PetscArraycpy(v, (PetscScalar *) (Y_handle->x), lda * Y_handle->ncol);CHKERRQ(ierr); 152a2fc1e05SToby Isaac } else { 153a2fc1e05SToby Isaac for (size_t j = 0; j < Y_handle->ncol; j++) { 154a2fc1e05SToby Isaac ierr = PetscArraycpy(&v[j*lda], &(((PetscScalar *) Y_handle->x)[j*Y_handle->d]), Y_handle->nrow);CHKERRQ(ierr); 155a2fc1e05SToby Isaac } 156a2fc1e05SToby Isaac } 157a2fc1e05SToby Isaac ierr = MatDenseRestoreArrayWrite(X, &v);CHKERRQ(ierr); 158a2fc1e05SToby Isaac ierr = !cholmod_l_free_dense(&Y_handle, chol->common);CHKERRQ(ierr); 159a2fc1e05SToby Isaac ierr = MatDenseUnWrapCholmod(B,GET_ARRAY_READ,&cholB);CHKERRQ(ierr); 160a2fc1e05SToby Isaac PetscFunctionReturn(0); 161a2fc1e05SToby Isaac } 162a2fc1e05SToby Isaac 163a2fc1e05SToby Isaac static PetscErrorCode MatSolveTranspose_SPQR_Internal(Mat F, cholmod_dense *cholB, cholmod_dense **_Y_handle) 164a2fc1e05SToby Isaac { 165a2fc1e05SToby Isaac Mat_CHOLMOD *chol = (Mat_CHOLMOD*)F->data; 166a2fc1e05SToby Isaac cholmod_dense *Y_handle = NULL, *RTB_handle = NULL; 167a2fc1e05SToby Isaac PetscErrorCode ierr; 168a2fc1e05SToby Isaac 169a2fc1e05SToby Isaac PetscFunctionBegin; 170a2fc1e05SToby Isaac RTB_handle = SuiteSparseQR_C_solve(SPQR_RTX_EQUALS_ETB, chol->spqrfact, cholB, chol->common); 171a2fc1e05SToby Isaac if (!RTB_handle) SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_LIB, "SuiteSparseQR_C_solve failed"); 172a2fc1e05SToby Isaac Y_handle = SuiteSparseQR_C_qmult(SPQR_QX, chol->spqrfact, RTB_handle, chol->common); 173a2fc1e05SToby Isaac if (!Y_handle) SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_LIB, "SuiteSparseQR_C_qmult failed"); 174a2fc1e05SToby Isaac *_Y_handle = Y_handle; 175a2fc1e05SToby Isaac ierr = !cholmod_l_free_dense(&RTB_handle, chol->common);CHKERRQ(ierr); 176a2fc1e05SToby Isaac PetscFunctionReturn(0); 177a2fc1e05SToby Isaac } 178a2fc1e05SToby Isaac 179a2fc1e05SToby Isaac static PetscErrorCode MatSolveTranspose_SPQR(Mat F,Vec B,Vec X) 180a2fc1e05SToby Isaac { 181a2fc1e05SToby Isaac Mat_CHOLMOD *chol = (Mat_CHOLMOD*)F->data; 182a2fc1e05SToby Isaac cholmod_dense cholB,*Y_handle = NULL; 183a2fc1e05SToby Isaac PetscInt n; 184a2fc1e05SToby Isaac PetscScalar *v; 185a2fc1e05SToby Isaac PetscErrorCode ierr; 186a2fc1e05SToby Isaac 187a2fc1e05SToby Isaac PetscFunctionBegin; 188a2fc1e05SToby Isaac ierr = VecWrapCholmod(B,GET_ARRAY_READ,&cholB);CHKERRQ(ierr); 189a2fc1e05SToby Isaac ierr = MatSolveTranspose_SPQR_Internal(F, &cholB, &Y_handle);CHKERRQ(ierr); 190a2fc1e05SToby Isaac ierr = VecGetLocalSize(X, &n);CHKERRQ(ierr); 191a2fc1e05SToby Isaac ierr = VecGetArrayWrite(X, &v);CHKERRQ(ierr); 192a2fc1e05SToby Isaac ierr = PetscArraycpy(v, (PetscScalar *) Y_handle->x, n);CHKERRQ(ierr); 193a2fc1e05SToby Isaac ierr = VecRestoreArrayWrite(X, &v);CHKERRQ(ierr); 194a2fc1e05SToby Isaac ierr = !cholmod_l_free_dense(&Y_handle, chol->common);CHKERRQ(ierr); 195a2fc1e05SToby Isaac ierr = VecUnWrapCholmod(B,GET_ARRAY_READ,&cholB);CHKERRQ(ierr); 196a2fc1e05SToby Isaac PetscFunctionReturn(0); 197a2fc1e05SToby Isaac } 198a2fc1e05SToby Isaac 199a2fc1e05SToby Isaac static PetscErrorCode MatMatSolveTranspose_SPQR(Mat F,Mat B,Mat X) 200a2fc1e05SToby Isaac { 201a2fc1e05SToby Isaac Mat_CHOLMOD *chol = (Mat_CHOLMOD*)F->data; 202a2fc1e05SToby Isaac cholmod_dense cholB,*Y_handle = NULL; 203a2fc1e05SToby Isaac PetscScalar *v; 204a2fc1e05SToby Isaac PetscInt lda; 205a2fc1e05SToby Isaac PetscErrorCode ierr; 206a2fc1e05SToby Isaac 207a2fc1e05SToby Isaac PetscFunctionBegin; 208a2fc1e05SToby Isaac ierr = MatDenseWrapCholmod(B,GET_ARRAY_READ,&cholB);CHKERRQ(ierr); 209a2fc1e05SToby Isaac ierr = MatSolveTranspose_SPQR_Internal(F, &cholB, &Y_handle);CHKERRQ(ierr); 210a2fc1e05SToby Isaac ierr = MatDenseGetArrayWrite(X, &v);CHKERRQ(ierr); 211a2fc1e05SToby Isaac ierr = MatDenseGetLDA(X, &lda);CHKERRQ(ierr); 212a2fc1e05SToby Isaac if ((size_t) lda == Y_handle->d) { 213a2fc1e05SToby Isaac ierr = PetscArraycpy(v, (PetscScalar *) Y_handle->x, lda * Y_handle->ncol);CHKERRQ(ierr); 214a2fc1e05SToby Isaac } else { 215a2fc1e05SToby Isaac for (size_t j = 0; j < Y_handle->ncol; j++) { 216a2fc1e05SToby Isaac ierr = PetscArraycpy(&v[j*lda], &(((PetscScalar *) Y_handle->x)[j*Y_handle->d]), Y_handle->nrow);CHKERRQ(ierr); 217a2fc1e05SToby Isaac } 218a2fc1e05SToby Isaac } 219a2fc1e05SToby Isaac ierr = MatDenseRestoreArrayWrite(X, &v);CHKERRQ(ierr); 220a2fc1e05SToby Isaac ierr = !cholmod_l_free_dense(&Y_handle, chol->common);CHKERRQ(ierr); 221a2fc1e05SToby Isaac ierr = MatDenseUnWrapCholmod(B,GET_ARRAY_READ,&cholB);CHKERRQ(ierr); 222a2fc1e05SToby Isaac PetscFunctionReturn(0); 223a2fc1e05SToby Isaac } 224a2fc1e05SToby Isaac 225a2fc1e05SToby Isaac static PetscErrorCode MatQRFactorNumeric_SPQR(Mat F,Mat A,const MatFactorInfo *info) 226a2fc1e05SToby Isaac { 227a2fc1e05SToby Isaac Mat_CHOLMOD *chol = (Mat_CHOLMOD*)F->data; 228a2fc1e05SToby Isaac cholmod_sparse cholA; 229*65f45395SPierre Jolivet PetscBool aijalloc,valloc; 230a2fc1e05SToby Isaac PetscErrorCode ierr; 231a2fc1e05SToby Isaac 232a2fc1e05SToby Isaac PetscFunctionBegin; 233*65f45395SPierre Jolivet ierr = PetscObjectTypeCompare((PetscObject)A, MATNORMALHERMITIAN, &chol->normal);CHKERRQ(ierr); 234*65f45395SPierre Jolivet if (!chol->normal && !PetscDefined(USE_COMPLEX)) { 235*65f45395SPierre Jolivet ierr = PetscObjectTypeCompare((PetscObject)A, MATNORMAL, &chol->normal);CHKERRQ(ierr); 236*65f45395SPierre Jolivet } 237a2fc1e05SToby Isaac ierr = (*chol->Wrap)(A,PETSC_TRUE,&cholA,&aijalloc,&valloc);CHKERRQ(ierr); 238d0f82a0bSPierre Jolivet ierr = !SuiteSparseQR_C_numeric(PETSC_SMALL, &cholA, chol->spqrfact, chol->common); 239a2fc1e05SToby Isaac if (ierr) SETERRQ1(PetscObjectComm((PetscObject)F),PETSC_ERR_LIB,"SPQR factorization failed with status %d",chol->common->status); 240a2fc1e05SToby Isaac 241a2fc1e05SToby Isaac if (aijalloc) {ierr = PetscFree2(cholA.p,cholA.i);CHKERRQ(ierr);} 242a2fc1e05SToby Isaac if (valloc) {ierr = PetscFree(cholA.x);CHKERRQ(ierr);} 243a2fc1e05SToby Isaac 244a2fc1e05SToby Isaac F->ops->solve = MatSolve_SPQR; 245a2fc1e05SToby Isaac F->ops->matsolve = MatMatSolve_SPQR; 24602ef7dfaSPierre Jolivet if (chol->normal) { 24702ef7dfaSPierre Jolivet F->ops->solvetranspose = MatSolve_SPQR; 24802ef7dfaSPierre Jolivet F->ops->matsolvetranspose = MatMatSolve_SPQR; 24902ef7dfaSPierre Jolivet } else if (A->cmap->n == A->rmap->n) { 250a2fc1e05SToby Isaac F->ops->solvetranspose = MatSolveTranspose_SPQR; 251a2fc1e05SToby Isaac F->ops->matsolvetranspose = MatMatSolveTranspose_SPQR; 252a2fc1e05SToby Isaac } 253a2fc1e05SToby Isaac PetscFunctionReturn(0); 254a2fc1e05SToby Isaac } 255a2fc1e05SToby Isaac 256a2fc1e05SToby Isaac PETSC_INTERN PetscErrorCode MatQRFactorSymbolic_SPQR(Mat F,Mat A,IS perm,const MatFactorInfo *info) 257a2fc1e05SToby Isaac { 258a2fc1e05SToby Isaac Mat_CHOLMOD *chol = (Mat_CHOLMOD*)F->data; 259a2fc1e05SToby Isaac PetscErrorCode ierr; 260a2fc1e05SToby Isaac cholmod_sparse cholA; 261*65f45395SPierre Jolivet PetscBool aijalloc,valloc; 262a2fc1e05SToby Isaac 263a2fc1e05SToby Isaac PetscFunctionBegin; 264*65f45395SPierre Jolivet ierr = PetscObjectTypeCompare((PetscObject)A, MATNORMALHERMITIAN, &chol->normal);CHKERRQ(ierr); 265*65f45395SPierre Jolivet if (!chol->normal && !PetscDefined(USE_COMPLEX)) { 266*65f45395SPierre Jolivet ierr = PetscObjectTypeCompare((PetscObject)A, MATNORMAL, &chol->normal);CHKERRQ(ierr); 267*65f45395SPierre Jolivet } 268a2fc1e05SToby Isaac ierr = (*chol->Wrap)(A,PETSC_TRUE,&cholA,&aijalloc,&valloc);CHKERRQ(ierr); 269a2fc1e05SToby Isaac if (PetscDefined(USE_DEBUG)) { 270a2fc1e05SToby Isaac ierr = !cholmod_l_check_sparse(&cholA, chol->common);CHKERRQ(ierr); 271a2fc1e05SToby Isaac } 272a2fc1e05SToby Isaac if (chol->spqrfact) { 273a2fc1e05SToby Isaac ierr = !SuiteSparseQR_C_free(&chol->spqrfact, chol->common);CHKERRQ(ierr); 274a2fc1e05SToby Isaac } 275d0f82a0bSPierre Jolivet chol->spqrfact = SuiteSparseQR_C_symbolic(SPQR_ORDERING_DEFAULT, 1, &cholA, chol->common); 276a2fc1e05SToby Isaac if (!chol->spqrfact) SETERRQ1(PetscObjectComm((PetscObject)F),PETSC_ERR_LIB,"CHOLMOD analysis failed using internal ordering with status %d",chol->common->status); 277a2fc1e05SToby Isaac 278a2fc1e05SToby Isaac if (aijalloc) {ierr = PetscFree2(cholA.p,cholA.i);CHKERRQ(ierr);} 279a2fc1e05SToby Isaac if (valloc) {ierr = PetscFree(cholA.x);CHKERRQ(ierr);} 280a2fc1e05SToby Isaac 2811e1ea65dSPierre Jolivet ierr = PetscObjectComposeFunction((PetscObject)F,"MatQRFactorNumeric_C", MatQRFactorNumeric_SPQR);CHKERRQ(ierr); 282a2fc1e05SToby Isaac PetscFunctionReturn(0); 283a2fc1e05SToby Isaac } 284a2fc1e05SToby Isaac 285a2fc1e05SToby Isaac /*MC 286a2fc1e05SToby Isaac MATSOLVERSPQR 287a2fc1e05SToby Isaac 288a2fc1e05SToby Isaac A matrix type providing direct solvers (QR factorizations) for sequential matrices 289a2fc1e05SToby Isaac via the external package SPQR. 290a2fc1e05SToby Isaac 291a2fc1e05SToby Isaac Use ./configure --download-suitesparse to install PETSc to use CHOLMOD 292a2fc1e05SToby Isaac 293a2fc1e05SToby Isaac TODO: Use -pc_type qr -pc_factor_mat_solver_type spqr to use this direct solver (TODO: PCQR) 294a2fc1e05SToby Isaac 295a2fc1e05SToby Isaac 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 300a2fc1e05SToby Isaac Note: SPQR is part of SuiteSparse http://faculty.cse.tamu.edu/davis/suitesparse.html 301a2fc1e05SToby Isaac 302a2fc1e05SToby Isaac .seealso: PCQR, PCFactorSetMatSolverType(), MatSolverType 303a2fc1e05SToby Isaac M*/ 304a2fc1e05SToby Isaac 305a2fc1e05SToby Isaac PETSC_INTERN PetscErrorCode MatGetFactor_seqaij_spqr(Mat A,MatFactorType ftype,Mat *F) 306a2fc1e05SToby Isaac { 307a2fc1e05SToby Isaac Mat B; 308a2fc1e05SToby Isaac Mat_CHOLMOD *chol; 309a2fc1e05SToby Isaac PetscErrorCode ierr; 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 */ 315a2fc1e05SToby Isaac ierr = MatCreate(PetscObjectComm((PetscObject)A),&B);CHKERRQ(ierr); 316a2fc1e05SToby Isaac ierr = MatSetSizes(B,PETSC_DECIDE,PETSC_DECIDE,m,n);CHKERRQ(ierr); 317a2fc1e05SToby Isaac ierr = PetscStrallocpy("spqr",&((PetscObject)B)->type_name);CHKERRQ(ierr); 318a2fc1e05SToby Isaac ierr = MatGetOptionsPrefix(A,&prefix);CHKERRQ(ierr); 319a2fc1e05SToby Isaac ierr = MatSetOptionsPrefix(B,prefix);CHKERRQ(ierr); 320a2fc1e05SToby Isaac ierr = MatSetUp(B);CHKERRQ(ierr); 321a2fc1e05SToby Isaac ierr = PetscNewLog(B,&chol);CHKERRQ(ierr); 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 330a2fc1e05SToby Isaac ierr = PetscObjectComposeFunction((PetscObject)B,"MatFactorGetSolverType_C",MatFactorGetSolverType_seqaij_SPQR);CHKERRQ(ierr); 3311e1ea65dSPierre Jolivet ierr = PetscObjectComposeFunction((PetscObject)B,"MatQRFactorSymbolic_C", MatQRFactorSymbolic_SPQR);CHKERRQ(ierr); 332a2fc1e05SToby Isaac 333a2fc1e05SToby Isaac B->factortype = MAT_FACTOR_QR; 334a2fc1e05SToby Isaac B->assembled = PETSC_TRUE; 335a2fc1e05SToby Isaac B->preallocated = PETSC_TRUE; 336a2fc1e05SToby Isaac 337a2fc1e05SToby Isaac ierr = PetscFree(B->solvertype);CHKERRQ(ierr); 338a2fc1e05SToby Isaac ierr = PetscStrallocpy(MATSOLVERCHOLMOD,&B->solvertype);CHKERRQ(ierr); 339a2fc1e05SToby Isaac B->canuseordering = PETSC_FALSE; 340a2fc1e05SToby Isaac ierr = CholmodStart(B);CHKERRQ(ierr); 341a2fc1e05SToby Isaac chol->common->itype = CHOLMOD_LONG; 342a2fc1e05SToby Isaac *F = B; 343a2fc1e05SToby Isaac PetscFunctionReturn(0); 344a2fc1e05SToby Isaac } 345a2fc1e05SToby Isaac 346