xref: /petsc/src/mat/impls/aij/seq/spqr/aijspqr.c (revision 65f45395ee41b0220cb8038ff86f18021a88432f)
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