xref: /petsc/src/mat/impls/aij/seq/spqr/aijspqr.c (revision 2c71b3e237ead271e4f3aa1505f92bf476e3413d)
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;
2365f45395SPierre Jolivet   ierr = PetscObjectTypeCompare((PetscObject)A, MATNORMALHERMITIAN, &flg);CHKERRQ(ierr);
2465f45395SPierre Jolivet   if (flg) {
2565f45395SPierre Jolivet     ierr = MatNormalHermitianGetMat(A, &A);CHKERRQ(ierr);
2665f45395SPierre 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     }
3165f45395SPierre 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);
102*2c71b3e2SJacob Faibussowitsch     PetscCheckFalse(!QTB_handle,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);
104*2c71b3e2SJacob Faibussowitsch     PetscCheckFalse(!Y_handle,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);
107*2c71b3e2SJacob Faibussowitsch     PetscCheckFalse(!Z_handle,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);
109*2c71b3e2SJacob Faibussowitsch     PetscCheckFalse(!Y_handle,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);
171*2c71b3e2SJacob Faibussowitsch   PetscCheckFalse(!RTB_handle,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);
173*2c71b3e2SJacob Faibussowitsch   PetscCheckFalse(!Y_handle,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;
22965f45395SPierre Jolivet   PetscBool      aijalloc,valloc;
230a2fc1e05SToby Isaac   PetscErrorCode ierr;
231a2fc1e05SToby Isaac 
232a2fc1e05SToby Isaac   PetscFunctionBegin;
23365f45395SPierre Jolivet   ierr = PetscObjectTypeCompare((PetscObject)A, MATNORMALHERMITIAN, &chol->normal);CHKERRQ(ierr);
23465f45395SPierre Jolivet   if (!chol->normal && !PetscDefined(USE_COMPLEX)) {
23565f45395SPierre Jolivet     ierr = PetscObjectTypeCompare((PetscObject)A, MATNORMAL, &chol->normal);CHKERRQ(ierr);
23665f45395SPierre 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);
239*2c71b3e2SJacob Faibussowitsch   PetscCheckFalse(ierr,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;
26165f45395SPierre Jolivet   PetscBool      aijalloc,valloc;
262a2fc1e05SToby Isaac 
263a2fc1e05SToby Isaac   PetscFunctionBegin;
26465f45395SPierre Jolivet   ierr = PetscObjectTypeCompare((PetscObject)A, MATNORMALHERMITIAN, &chol->normal);CHKERRQ(ierr);
26565f45395SPierre Jolivet   if (!chol->normal && !PetscDefined(USE_COMPLEX)) {
26665f45395SPierre Jolivet     ierr = PetscObjectTypeCompare((PetscObject)A, MATNORMAL, &chol->normal);CHKERRQ(ierr);
26765f45395SPierre 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);
276*2c71b3e2SJacob Faibussowitsch   PetscCheckFalse(!chol->spqrfact,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   Consult SPQR documentation for more information about the Common parameters
294a2fc1e05SToby Isaac   which correspond to the options database keys below.
295a2fc1e05SToby Isaac 
296a2fc1e05SToby Isaac    Level: beginner
297a2fc1e05SToby Isaac 
298a2fc1e05SToby Isaac    Note: SPQR is part of SuiteSparse http://faculty.cse.tamu.edu/davis/suitesparse.html
299a2fc1e05SToby Isaac 
300a2fc1e05SToby Isaac .seealso: PCQR, PCFactorSetMatSolverType(), MatSolverType
301a2fc1e05SToby Isaac M*/
302a2fc1e05SToby Isaac 
303a2fc1e05SToby Isaac PETSC_INTERN PetscErrorCode MatGetFactor_seqaij_spqr(Mat A,MatFactorType ftype,Mat *F)
304a2fc1e05SToby Isaac {
305a2fc1e05SToby Isaac   Mat            B;
306a2fc1e05SToby Isaac   Mat_CHOLMOD    *chol;
307a2fc1e05SToby Isaac   PetscErrorCode ierr;
308a2fc1e05SToby Isaac   PetscInt       m=A->rmap->n,n=A->cmap->n;
309a2fc1e05SToby Isaac   const char     *prefix;
310a2fc1e05SToby Isaac 
311a2fc1e05SToby Isaac   PetscFunctionBegin;
312a2fc1e05SToby Isaac   /* Create the factorization matrix F */
313a2fc1e05SToby Isaac   ierr = MatCreate(PetscObjectComm((PetscObject)A),&B);CHKERRQ(ierr);
314a2fc1e05SToby Isaac   ierr = MatSetSizes(B,PETSC_DECIDE,PETSC_DECIDE,m,n);CHKERRQ(ierr);
315a2fc1e05SToby Isaac   ierr = PetscStrallocpy("spqr",&((PetscObject)B)->type_name);CHKERRQ(ierr);
316a2fc1e05SToby Isaac   ierr = MatGetOptionsPrefix(A,&prefix);CHKERRQ(ierr);
317a2fc1e05SToby Isaac   ierr = MatSetOptionsPrefix(B,prefix);CHKERRQ(ierr);
318a2fc1e05SToby Isaac   ierr = MatSetUp(B);CHKERRQ(ierr);
319a2fc1e05SToby Isaac   ierr = PetscNewLog(B,&chol);CHKERRQ(ierr);
320a2fc1e05SToby Isaac 
321a2fc1e05SToby Isaac   chol->Wrap = MatWrapCholmod_SPQR_seqaij;
322a2fc1e05SToby Isaac   B->data    = chol;
323a2fc1e05SToby Isaac 
324a2fc1e05SToby Isaac   B->ops->getinfo = MatGetInfo_CHOLMOD;
325a2fc1e05SToby Isaac   B->ops->view    = MatView_CHOLMOD;
326a2fc1e05SToby Isaac   B->ops->destroy = MatDestroy_CHOLMOD;
327a2fc1e05SToby Isaac 
328a2fc1e05SToby Isaac   ierr = PetscObjectComposeFunction((PetscObject)B,"MatFactorGetSolverType_C",MatFactorGetSolverType_seqaij_SPQR);CHKERRQ(ierr);
3291e1ea65dSPierre Jolivet   ierr = PetscObjectComposeFunction((PetscObject)B,"MatQRFactorSymbolic_C", MatQRFactorSymbolic_SPQR);CHKERRQ(ierr);
330a2fc1e05SToby Isaac 
331a2fc1e05SToby Isaac   B->factortype   = MAT_FACTOR_QR;
332a2fc1e05SToby Isaac   B->assembled    = PETSC_TRUE;
333a2fc1e05SToby Isaac   B->preallocated = PETSC_TRUE;
334a2fc1e05SToby Isaac 
335a2fc1e05SToby Isaac   ierr = PetscFree(B->solvertype);CHKERRQ(ierr);
336a2fc1e05SToby Isaac   ierr = PetscStrallocpy(MATSOLVERCHOLMOD,&B->solvertype);CHKERRQ(ierr);
337a2fc1e05SToby Isaac   B->canuseordering = PETSC_FALSE;
338a2fc1e05SToby Isaac   ierr = CholmodStart(B);CHKERRQ(ierr);
339a2fc1e05SToby Isaac   chol->common->itype = CHOLMOD_LONG;
340a2fc1e05SToby Isaac   *F   = B;
341a2fc1e05SToby Isaac   PetscFunctionReturn(0);
342a2fc1e05SToby Isaac }
343a2fc1e05SToby Isaac 
344