1*a2fc1e05SToby Isaac 2*a2fc1e05SToby Isaac #include <petscsys.h> 3*a2fc1e05SToby Isaac #include <../src/mat/impls/aij/seq/aij.h> 4*a2fc1e05SToby Isaac #include <../src/mat/impls/sbaij/seq/cholmod/cholmodimpl.h> 5*a2fc1e05SToby Isaac 6*a2fc1e05SToby Isaac EXTERN_C_BEGIN 7*a2fc1e05SToby Isaac #include <SuiteSparseQR_C.h> 8*a2fc1e05SToby Isaac EXTERN_C_END 9*a2fc1e05SToby Isaac 10*a2fc1e05SToby Isaac static PetscErrorCode MatWrapCholmod_SPQR_seqaij(Mat A,PetscBool values,cholmod_sparse *C,PetscBool *aijalloc,PetscBool *valloc) 11*a2fc1e05SToby Isaac { 12*a2fc1e05SToby Isaac Mat_SeqAIJ *aij; 13*a2fc1e05SToby Isaac Mat AT; 14*a2fc1e05SToby Isaac const PetscScalar *aa; 15*a2fc1e05SToby Isaac PetscScalar *ca; 16*a2fc1e05SToby Isaac const PetscInt *ai, *aj; 17*a2fc1e05SToby Isaac PetscInt n = A->cmap->n, i,j,k,nz; 18*a2fc1e05SToby Isaac SuiteSparse_long *ci, *cj; /* SuiteSparse_long is the only choice for SPQR */ 19*a2fc1e05SToby Isaac PetscBool vain = PETSC_FALSE; 20*a2fc1e05SToby Isaac PetscErrorCode ierr; 21*a2fc1e05SToby Isaac 22*a2fc1e05SToby Isaac PetscFunctionBegin; 23*a2fc1e05SToby Isaac /* cholmod_sparse is compressed sparse column */ 24*a2fc1e05SToby Isaac { 25*a2fc1e05SToby Isaac PetscBool issym; 26*a2fc1e05SToby Isaac 27*a2fc1e05SToby Isaac ierr = MatGetOption(A, MAT_SYMMETRIC, &issym);CHKERRQ(ierr); 28*a2fc1e05SToby Isaac if (issym) { 29*a2fc1e05SToby Isaac ierr = PetscObjectReference((PetscObject)A);CHKERRQ(ierr); 30*a2fc1e05SToby Isaac AT = A; 31*a2fc1e05SToby Isaac } else { 32*a2fc1e05SToby Isaac ierr = MatTranspose(A, MAT_INITIAL_MATRIX, &AT);CHKERRQ(ierr); 33*a2fc1e05SToby Isaac } 34*a2fc1e05SToby Isaac } 35*a2fc1e05SToby Isaac aij = (Mat_SeqAIJ*)AT->data; 36*a2fc1e05SToby Isaac ai = aij->j; 37*a2fc1e05SToby Isaac aj = aij->i; 38*a2fc1e05SToby Isaac for (j=0,nz=0; j<n; j++) nz += aj[j+1] - aj[j]; 39*a2fc1e05SToby Isaac ierr = PetscMalloc2(n+1,&cj,nz,&ci);CHKERRQ(ierr); 40*a2fc1e05SToby Isaac if (values) { 41*a2fc1e05SToby Isaac vain = PETSC_TRUE; 42*a2fc1e05SToby Isaac ierr = PetscMalloc1(nz,&ca);CHKERRQ(ierr); 43*a2fc1e05SToby Isaac ierr = MatSeqAIJGetArrayRead(AT,&aa);CHKERRQ(ierr); 44*a2fc1e05SToby Isaac } 45*a2fc1e05SToby Isaac for (j=0,k=0; j<n; j++) { 46*a2fc1e05SToby Isaac cj[j] = k; 47*a2fc1e05SToby Isaac for (i=aj[j]; i<aj[j+1]; i++,k++) { 48*a2fc1e05SToby Isaac ci[k] = ai[i]; 49*a2fc1e05SToby Isaac if (values) ca[k] = aa[i]; 50*a2fc1e05SToby Isaac } 51*a2fc1e05SToby Isaac } 52*a2fc1e05SToby Isaac cj[j] = k; 53*a2fc1e05SToby Isaac *aijalloc = PETSC_TRUE; 54*a2fc1e05SToby Isaac *valloc = vain; 55*a2fc1e05SToby Isaac if (values) { 56*a2fc1e05SToby Isaac ierr = MatSeqAIJRestoreArrayRead(A,&aa);CHKERRQ(ierr); 57*a2fc1e05SToby Isaac } 58*a2fc1e05SToby Isaac 59*a2fc1e05SToby Isaac ierr = PetscMemzero(C,sizeof(*C));CHKERRQ(ierr); 60*a2fc1e05SToby Isaac 61*a2fc1e05SToby Isaac C->nrow = (size_t)A->rmap->n; 62*a2fc1e05SToby Isaac C->ncol = (size_t)A->cmap->n; 63*a2fc1e05SToby Isaac C->nzmax = (size_t)nz; 64*a2fc1e05SToby Isaac C->p = cj; 65*a2fc1e05SToby Isaac C->i = ci; 66*a2fc1e05SToby Isaac C->x = values ? ca : 0; 67*a2fc1e05SToby Isaac C->stype = 0; 68*a2fc1e05SToby Isaac C->itype = CHOLMOD_LONG; 69*a2fc1e05SToby Isaac C->xtype = values ? CHOLMOD_SCALAR_TYPE : CHOLMOD_PATTERN; 70*a2fc1e05SToby Isaac C->dtype = CHOLMOD_DOUBLE; 71*a2fc1e05SToby Isaac C->sorted = 1; 72*a2fc1e05SToby Isaac C->packed = 1; 73*a2fc1e05SToby Isaac 74*a2fc1e05SToby Isaac ierr = MatDestroy(&AT);CHKERRQ(ierr); 75*a2fc1e05SToby Isaac PetscFunctionReturn(0); 76*a2fc1e05SToby Isaac } 77*a2fc1e05SToby Isaac 78*a2fc1e05SToby Isaac static PetscErrorCode MatFactorGetSolverType_seqaij_SPQR(Mat A,MatSolverType *type) 79*a2fc1e05SToby Isaac { 80*a2fc1e05SToby Isaac PetscFunctionBegin; 81*a2fc1e05SToby Isaac *type = MATSOLVERSPQR; 82*a2fc1e05SToby Isaac PetscFunctionReturn(0); 83*a2fc1e05SToby Isaac } 84*a2fc1e05SToby Isaac 85*a2fc1e05SToby Isaac #define GET_ARRAY_READ 0 86*a2fc1e05SToby Isaac #define GET_ARRAY_WRITE 1 87*a2fc1e05SToby Isaac 88*a2fc1e05SToby Isaac static PetscErrorCode MatSolve_SPQR_Internal(Mat F, cholmod_dense *cholB, cholmod_dense **_Y_handle) 89*a2fc1e05SToby Isaac { 90*a2fc1e05SToby Isaac Mat_CHOLMOD *chol = (Mat_CHOLMOD*)F->data; 91*a2fc1e05SToby Isaac cholmod_dense *Y_handle = NULL, *QTB_handle = NULL; 92*a2fc1e05SToby Isaac PetscErrorCode ierr; 93*a2fc1e05SToby Isaac 94*a2fc1e05SToby Isaac PetscFunctionBegin; 95*a2fc1e05SToby Isaac QTB_handle = SuiteSparseQR_C_qmult(SPQR_QTX, chol->spqrfact, cholB, chol->common); 96*a2fc1e05SToby Isaac if (!QTB_handle) SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_LIB, "SuiteSparseQR_C_qmult failed"); 97*a2fc1e05SToby Isaac Y_handle = SuiteSparseQR_C_solve(SPQR_RETX_EQUALS_B, chol->spqrfact, QTB_handle, chol->common); 98*a2fc1e05SToby Isaac if (!Y_handle) SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_LIB, "SuiteSparseQR_C_solve failed"); 99*a2fc1e05SToby Isaac *_Y_handle = Y_handle; 100*a2fc1e05SToby Isaac ierr = !cholmod_l_free_dense(&QTB_handle, chol->common);CHKERRQ(ierr); 101*a2fc1e05SToby Isaac PetscFunctionReturn(0); 102*a2fc1e05SToby Isaac } 103*a2fc1e05SToby Isaac 104*a2fc1e05SToby Isaac static PetscErrorCode MatSolve_SPQR(Mat F,Vec B,Vec X) 105*a2fc1e05SToby Isaac { 106*a2fc1e05SToby Isaac Mat_CHOLMOD *chol = (Mat_CHOLMOD*)F->data; 107*a2fc1e05SToby Isaac cholmod_dense cholB,*Y_handle = NULL; 108*a2fc1e05SToby Isaac PetscInt n; 109*a2fc1e05SToby Isaac PetscScalar *v; 110*a2fc1e05SToby Isaac PetscErrorCode ierr; 111*a2fc1e05SToby Isaac 112*a2fc1e05SToby Isaac PetscFunctionBegin; 113*a2fc1e05SToby Isaac ierr = VecWrapCholmod(B,GET_ARRAY_READ,&cholB);CHKERRQ(ierr); 114*a2fc1e05SToby Isaac ierr = MatSolve_SPQR_Internal(F, &cholB, &Y_handle);CHKERRQ(ierr); 115*a2fc1e05SToby Isaac ierr = VecGetLocalSize(X, &n);CHKERRQ(ierr); 116*a2fc1e05SToby Isaac ierr = VecGetArrayWrite(X, &v);CHKERRQ(ierr); 117*a2fc1e05SToby Isaac ierr = PetscArraycpy(v, (PetscScalar *) (Y_handle->x), n);CHKERRQ(ierr); 118*a2fc1e05SToby Isaac ierr = VecRestoreArrayWrite(X, &v);CHKERRQ(ierr); 119*a2fc1e05SToby Isaac ierr = !cholmod_l_free_dense(&Y_handle, chol->common);CHKERRQ(ierr); 120*a2fc1e05SToby Isaac ierr = VecUnWrapCholmod(B,GET_ARRAY_READ,&cholB);CHKERRQ(ierr); 121*a2fc1e05SToby Isaac PetscFunctionReturn(0); 122*a2fc1e05SToby Isaac } 123*a2fc1e05SToby Isaac 124*a2fc1e05SToby Isaac static PetscErrorCode MatMatSolve_SPQR(Mat F,Mat B,Mat X) 125*a2fc1e05SToby Isaac { 126*a2fc1e05SToby Isaac Mat_CHOLMOD *chol = (Mat_CHOLMOD*)F->data; 127*a2fc1e05SToby Isaac cholmod_dense cholB,*Y_handle = NULL; 128*a2fc1e05SToby Isaac PetscScalar *v; 129*a2fc1e05SToby Isaac PetscInt lda; 130*a2fc1e05SToby Isaac PetscErrorCode ierr; 131*a2fc1e05SToby Isaac 132*a2fc1e05SToby Isaac PetscFunctionBegin; 133*a2fc1e05SToby Isaac ierr = MatDenseWrapCholmod(B,GET_ARRAY_READ,&cholB);CHKERRQ(ierr); 134*a2fc1e05SToby Isaac ierr = MatSolve_SPQR_Internal(F, &cholB, &Y_handle);CHKERRQ(ierr); 135*a2fc1e05SToby Isaac ierr = MatDenseGetArrayWrite(X, &v);CHKERRQ(ierr); 136*a2fc1e05SToby Isaac ierr = MatDenseGetLDA(X, &lda);CHKERRQ(ierr); 137*a2fc1e05SToby Isaac if ((size_t) lda == Y_handle->d) { 138*a2fc1e05SToby Isaac ierr = PetscArraycpy(v, (PetscScalar *) (Y_handle->x), lda * Y_handle->ncol);CHKERRQ(ierr); 139*a2fc1e05SToby Isaac } else { 140*a2fc1e05SToby Isaac for (size_t j = 0; j < Y_handle->ncol; j++) { 141*a2fc1e05SToby Isaac ierr = PetscArraycpy(&v[j*lda], &(((PetscScalar *) Y_handle->x)[j*Y_handle->d]), Y_handle->nrow);CHKERRQ(ierr); 142*a2fc1e05SToby Isaac } 143*a2fc1e05SToby Isaac } 144*a2fc1e05SToby Isaac ierr = MatDenseRestoreArrayWrite(X, &v);CHKERRQ(ierr); 145*a2fc1e05SToby Isaac ierr = !cholmod_l_free_dense(&Y_handle, chol->common);CHKERRQ(ierr); 146*a2fc1e05SToby Isaac ierr = MatDenseUnWrapCholmod(B,GET_ARRAY_READ,&cholB);CHKERRQ(ierr); 147*a2fc1e05SToby Isaac PetscFunctionReturn(0); 148*a2fc1e05SToby Isaac } 149*a2fc1e05SToby Isaac 150*a2fc1e05SToby Isaac static PetscErrorCode MatSolveTranspose_SPQR_Internal(Mat F, cholmod_dense *cholB, cholmod_dense **_Y_handle) 151*a2fc1e05SToby Isaac { 152*a2fc1e05SToby Isaac Mat_CHOLMOD *chol = (Mat_CHOLMOD*)F->data; 153*a2fc1e05SToby Isaac cholmod_dense *Y_handle = NULL, *RTB_handle = NULL; 154*a2fc1e05SToby Isaac PetscErrorCode ierr; 155*a2fc1e05SToby Isaac 156*a2fc1e05SToby Isaac PetscFunctionBegin; 157*a2fc1e05SToby Isaac RTB_handle = SuiteSparseQR_C_solve(SPQR_RTX_EQUALS_ETB, chol->spqrfact, cholB, chol->common); 158*a2fc1e05SToby Isaac if (!RTB_handle) SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_LIB, "SuiteSparseQR_C_solve failed"); 159*a2fc1e05SToby Isaac Y_handle = SuiteSparseQR_C_qmult(SPQR_QX, chol->spqrfact, RTB_handle, chol->common); 160*a2fc1e05SToby Isaac if (!Y_handle) SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_LIB, "SuiteSparseQR_C_qmult failed"); 161*a2fc1e05SToby Isaac *_Y_handle = Y_handle; 162*a2fc1e05SToby Isaac ierr = !cholmod_l_free_dense(&RTB_handle, chol->common);CHKERRQ(ierr); 163*a2fc1e05SToby Isaac PetscFunctionReturn(0); 164*a2fc1e05SToby Isaac } 165*a2fc1e05SToby Isaac 166*a2fc1e05SToby Isaac static PetscErrorCode MatSolveTranspose_SPQR(Mat F,Vec B,Vec X) 167*a2fc1e05SToby Isaac { 168*a2fc1e05SToby Isaac Mat_CHOLMOD *chol = (Mat_CHOLMOD*)F->data; 169*a2fc1e05SToby Isaac cholmod_dense cholB,*Y_handle = NULL; 170*a2fc1e05SToby Isaac PetscInt n; 171*a2fc1e05SToby Isaac PetscScalar *v; 172*a2fc1e05SToby Isaac PetscErrorCode ierr; 173*a2fc1e05SToby Isaac 174*a2fc1e05SToby Isaac PetscFunctionBegin; 175*a2fc1e05SToby Isaac ierr = VecWrapCholmod(B,GET_ARRAY_READ,&cholB);CHKERRQ(ierr); 176*a2fc1e05SToby Isaac ierr = MatSolveTranspose_SPQR_Internal(F, &cholB, &Y_handle);CHKERRQ(ierr); 177*a2fc1e05SToby Isaac ierr = VecGetLocalSize(X, &n);CHKERRQ(ierr); 178*a2fc1e05SToby Isaac ierr = VecGetArrayWrite(X, &v);CHKERRQ(ierr); 179*a2fc1e05SToby Isaac ierr = PetscArraycpy(v, (PetscScalar *) Y_handle->x, n);CHKERRQ(ierr); 180*a2fc1e05SToby Isaac ierr = VecRestoreArrayWrite(X, &v);CHKERRQ(ierr); 181*a2fc1e05SToby Isaac ierr = !cholmod_l_free_dense(&Y_handle, chol->common);CHKERRQ(ierr); 182*a2fc1e05SToby Isaac ierr = VecUnWrapCholmod(B,GET_ARRAY_READ,&cholB);CHKERRQ(ierr); 183*a2fc1e05SToby Isaac PetscFunctionReturn(0); 184*a2fc1e05SToby Isaac } 185*a2fc1e05SToby Isaac 186*a2fc1e05SToby Isaac static PetscErrorCode MatMatSolveTranspose_SPQR(Mat F,Mat B,Mat X) 187*a2fc1e05SToby Isaac { 188*a2fc1e05SToby Isaac Mat_CHOLMOD *chol = (Mat_CHOLMOD*)F->data; 189*a2fc1e05SToby Isaac cholmod_dense cholB,*Y_handle = NULL; 190*a2fc1e05SToby Isaac PetscScalar *v; 191*a2fc1e05SToby Isaac PetscInt lda; 192*a2fc1e05SToby Isaac PetscErrorCode ierr; 193*a2fc1e05SToby Isaac 194*a2fc1e05SToby Isaac PetscFunctionBegin; 195*a2fc1e05SToby Isaac ierr = MatDenseWrapCholmod(B,GET_ARRAY_READ,&cholB);CHKERRQ(ierr); 196*a2fc1e05SToby Isaac ierr = MatSolveTranspose_SPQR_Internal(F, &cholB, &Y_handle);CHKERRQ(ierr); 197*a2fc1e05SToby Isaac ierr = MatDenseGetArrayWrite(X, &v);CHKERRQ(ierr); 198*a2fc1e05SToby Isaac ierr = MatDenseGetLDA(X, &lda);CHKERRQ(ierr); 199*a2fc1e05SToby Isaac if ((size_t) lda == Y_handle->d) { 200*a2fc1e05SToby Isaac ierr = PetscArraycpy(v, (PetscScalar *) Y_handle->x, lda * Y_handle->ncol);CHKERRQ(ierr); 201*a2fc1e05SToby Isaac } else { 202*a2fc1e05SToby Isaac for (size_t j = 0; j < Y_handle->ncol; j++) { 203*a2fc1e05SToby Isaac ierr = PetscArraycpy(&v[j*lda], &(((PetscScalar *) Y_handle->x)[j*Y_handle->d]), Y_handle->nrow);CHKERRQ(ierr); 204*a2fc1e05SToby Isaac } 205*a2fc1e05SToby Isaac } 206*a2fc1e05SToby Isaac ierr = MatDenseRestoreArrayWrite(X, &v);CHKERRQ(ierr); 207*a2fc1e05SToby Isaac ierr = !cholmod_l_free_dense(&Y_handle, chol->common);CHKERRQ(ierr); 208*a2fc1e05SToby Isaac ierr = MatDenseUnWrapCholmod(B,GET_ARRAY_READ,&cholB);CHKERRQ(ierr); 209*a2fc1e05SToby Isaac PetscFunctionReturn(0); 210*a2fc1e05SToby Isaac } 211*a2fc1e05SToby Isaac 212*a2fc1e05SToby Isaac static PetscErrorCode MatQRFactorNumeric_SPQR(Mat F,Mat A,const MatFactorInfo *info) 213*a2fc1e05SToby Isaac { 214*a2fc1e05SToby Isaac Mat_CHOLMOD *chol = (Mat_CHOLMOD*)F->data; 215*a2fc1e05SToby Isaac cholmod_sparse cholA; 216*a2fc1e05SToby Isaac PetscBool aijalloc,valloc; 217*a2fc1e05SToby Isaac PetscErrorCode ierr; 218*a2fc1e05SToby Isaac 219*a2fc1e05SToby Isaac PetscFunctionBegin; 220*a2fc1e05SToby Isaac ierr = (*chol->Wrap)(A,PETSC_TRUE,&cholA,&aijalloc,&valloc);CHKERRQ(ierr); 221*a2fc1e05SToby Isaac ierr = !SuiteSparseQR_C_numeric(SPQR_DEFAULT_TOL, &cholA, chol->spqrfact, chol->common); 222*a2fc1e05SToby Isaac if (ierr) SETERRQ1(PetscObjectComm((PetscObject)F),PETSC_ERR_LIB,"SPQR factorization failed with status %d",chol->common->status); 223*a2fc1e05SToby Isaac 224*a2fc1e05SToby Isaac if (aijalloc) {ierr = PetscFree2(cholA.p,cholA.i);CHKERRQ(ierr);} 225*a2fc1e05SToby Isaac if (valloc) {ierr = PetscFree(cholA.x);CHKERRQ(ierr);} 226*a2fc1e05SToby Isaac 227*a2fc1e05SToby Isaac F->ops->solve = MatSolve_SPQR; 228*a2fc1e05SToby Isaac F->ops->matsolve = MatMatSolve_SPQR; 229*a2fc1e05SToby Isaac if (A->cmap->n == A->rmap->n) { 230*a2fc1e05SToby Isaac F->ops->solvetranspose = MatSolveTranspose_SPQR; 231*a2fc1e05SToby Isaac F->ops->matsolvetranspose = MatMatSolveTranspose_SPQR; 232*a2fc1e05SToby Isaac } 233*a2fc1e05SToby Isaac PetscFunctionReturn(0); 234*a2fc1e05SToby Isaac } 235*a2fc1e05SToby Isaac 236*a2fc1e05SToby Isaac PETSC_INTERN PetscErrorCode MatQRFactorSymbolic_SPQR(Mat F,Mat A,IS perm,const MatFactorInfo *info) 237*a2fc1e05SToby Isaac { 238*a2fc1e05SToby Isaac Mat_CHOLMOD *chol = (Mat_CHOLMOD*)F->data; 239*a2fc1e05SToby Isaac PetscErrorCode ierr; 240*a2fc1e05SToby Isaac cholmod_sparse cholA; 241*a2fc1e05SToby Isaac PetscBool aijalloc,valloc; 242*a2fc1e05SToby Isaac 243*a2fc1e05SToby Isaac PetscFunctionBegin; 244*a2fc1e05SToby Isaac ierr = (*chol->Wrap)(A,PETSC_TRUE,&cholA,&aijalloc,&valloc);CHKERRQ(ierr); 245*a2fc1e05SToby Isaac if (PetscDefined(USE_DEBUG)) { 246*a2fc1e05SToby Isaac ierr = !cholmod_l_check_sparse(&cholA, chol->common);CHKERRQ(ierr); 247*a2fc1e05SToby Isaac } 248*a2fc1e05SToby Isaac if (chol->spqrfact) { 249*a2fc1e05SToby Isaac ierr = !SuiteSparseQR_C_free(&chol->spqrfact, chol->common);CHKERRQ(ierr); 250*a2fc1e05SToby Isaac } 251*a2fc1e05SToby Isaac chol->spqrfact = SuiteSparseQR_C_symbolic(SPQR_ORDERING_FIXED, 0, &cholA, chol->common); 252*a2fc1e05SToby Isaac if (!chol->spqrfact) SETERRQ1(PetscObjectComm((PetscObject)F),PETSC_ERR_LIB,"CHOLMOD analysis failed using internal ordering with status %d",chol->common->status); 253*a2fc1e05SToby Isaac 254*a2fc1e05SToby Isaac if (aijalloc) {ierr = PetscFree2(cholA.p,cholA.i);CHKERRQ(ierr);} 255*a2fc1e05SToby Isaac if (valloc) {ierr = PetscFree(cholA.x);CHKERRQ(ierr);} 256*a2fc1e05SToby Isaac 257*a2fc1e05SToby Isaac ierr = PetscObjectComposeFunction((PetscObject)F,"MatQRFactorNumeric_C", MatQRFactorNumeric_SPQR); 258*a2fc1e05SToby Isaac PetscFunctionReturn(0); 259*a2fc1e05SToby Isaac } 260*a2fc1e05SToby Isaac 261*a2fc1e05SToby Isaac /*MC 262*a2fc1e05SToby Isaac MATSOLVERSPQR 263*a2fc1e05SToby Isaac 264*a2fc1e05SToby Isaac A matrix type providing direct solvers (QR factorizations) for sequential matrices 265*a2fc1e05SToby Isaac via the external package SPQR. 266*a2fc1e05SToby Isaac 267*a2fc1e05SToby Isaac Use ./configure --download-suitesparse to install PETSc to use CHOLMOD 268*a2fc1e05SToby Isaac 269*a2fc1e05SToby Isaac TODO: Use -pc_type qr -pc_factor_mat_solver_type spqr to use this direct solver (TODO: PCQR) 270*a2fc1e05SToby Isaac 271*a2fc1e05SToby Isaac Consult SPQR documentation for more information about the Common parameters 272*a2fc1e05SToby Isaac which correspond to the options database keys below. 273*a2fc1e05SToby Isaac 274*a2fc1e05SToby Isaac Level: beginner 275*a2fc1e05SToby Isaac 276*a2fc1e05SToby Isaac Note: SPQR is part of SuiteSparse http://faculty.cse.tamu.edu/davis/suitesparse.html 277*a2fc1e05SToby Isaac 278*a2fc1e05SToby Isaac .seealso: PCQR, PCFactorSetMatSolverType(), MatSolverType 279*a2fc1e05SToby Isaac M*/ 280*a2fc1e05SToby Isaac 281*a2fc1e05SToby Isaac PETSC_INTERN PetscErrorCode MatGetFactor_seqaij_spqr(Mat A,MatFactorType ftype,Mat *F) 282*a2fc1e05SToby Isaac { 283*a2fc1e05SToby Isaac Mat B; 284*a2fc1e05SToby Isaac Mat_CHOLMOD *chol; 285*a2fc1e05SToby Isaac PetscErrorCode ierr; 286*a2fc1e05SToby Isaac PetscInt m=A->rmap->n,n=A->cmap->n; 287*a2fc1e05SToby Isaac const char *prefix; 288*a2fc1e05SToby Isaac 289*a2fc1e05SToby Isaac PetscFunctionBegin; 290*a2fc1e05SToby Isaac /* Create the factorization matrix F */ 291*a2fc1e05SToby Isaac ierr = MatCreate(PetscObjectComm((PetscObject)A),&B);CHKERRQ(ierr); 292*a2fc1e05SToby Isaac ierr = MatSetSizes(B,PETSC_DECIDE,PETSC_DECIDE,m,n);CHKERRQ(ierr); 293*a2fc1e05SToby Isaac ierr = PetscStrallocpy("spqr",&((PetscObject)B)->type_name);CHKERRQ(ierr); 294*a2fc1e05SToby Isaac ierr = MatGetOptionsPrefix(A,&prefix);CHKERRQ(ierr); 295*a2fc1e05SToby Isaac ierr = MatSetOptionsPrefix(B,prefix);CHKERRQ(ierr); 296*a2fc1e05SToby Isaac ierr = MatSetUp(B);CHKERRQ(ierr); 297*a2fc1e05SToby Isaac ierr = PetscNewLog(B,&chol);CHKERRQ(ierr); 298*a2fc1e05SToby Isaac 299*a2fc1e05SToby Isaac chol->Wrap = MatWrapCholmod_SPQR_seqaij; 300*a2fc1e05SToby Isaac B->data = chol; 301*a2fc1e05SToby Isaac 302*a2fc1e05SToby Isaac B->ops->getinfo = MatGetInfo_CHOLMOD; 303*a2fc1e05SToby Isaac B->ops->view = MatView_CHOLMOD; 304*a2fc1e05SToby Isaac B->ops->destroy = MatDestroy_CHOLMOD; 305*a2fc1e05SToby Isaac 306*a2fc1e05SToby Isaac ierr = PetscObjectComposeFunction((PetscObject)B,"MatFactorGetSolverType_C",MatFactorGetSolverType_seqaij_SPQR);CHKERRQ(ierr); 307*a2fc1e05SToby Isaac ierr = PetscObjectComposeFunction((PetscObject)B,"MatQRFactorSymbolic_C", MatQRFactorSymbolic_SPQR); 308*a2fc1e05SToby Isaac 309*a2fc1e05SToby Isaac B->factortype = MAT_FACTOR_QR; 310*a2fc1e05SToby Isaac B->assembled = PETSC_TRUE; 311*a2fc1e05SToby Isaac B->preallocated = PETSC_TRUE; 312*a2fc1e05SToby Isaac 313*a2fc1e05SToby Isaac ierr = PetscFree(B->solvertype);CHKERRQ(ierr); 314*a2fc1e05SToby Isaac ierr = PetscStrallocpy(MATSOLVERCHOLMOD,&B->solvertype);CHKERRQ(ierr); 315*a2fc1e05SToby Isaac B->canuseordering = PETSC_FALSE; 316*a2fc1e05SToby Isaac ierr = CholmodStart(B);CHKERRQ(ierr); 317*a2fc1e05SToby Isaac chol->common->itype = CHOLMOD_LONG; 318*a2fc1e05SToby Isaac *F = B; 319*a2fc1e05SToby Isaac PetscFunctionReturn(0); 320*a2fc1e05SToby Isaac } 321*a2fc1e05SToby Isaac 322