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