xref: /petsc/src/mat/impls/aij/mpi/mumps/mumps.c (revision 43244d563de9cca7a5637c197866c90d36fd3410)
1 #define PETSCMAT_DLL
2 
3 /*
4     Provides an interface to the MUMPS sparse solver
5 */
6 #include "src/mat/impls/aij/seq/aij.h"
7 #include "src/mat/impls/aij/mpi/mpiaij.h"
8 #include "src/mat/impls/sbaij/seq/sbaij.h"
9 #include "src/mat/impls/sbaij/mpi/mpisbaij.h"
10 
11 EXTERN_C_BEGIN
12 #if defined(PETSC_USE_COMPLEX)
13 #include "zmumps_c.h"
14 #else
15 #include "dmumps_c.h"
16 #endif
17 EXTERN_C_END
18 #define JOB_INIT -1
19 #define JOB_END -2
20 /* macros s.t. indices match MUMPS documentation */
21 #define ICNTL(I) icntl[(I)-1]
22 #define CNTL(I) cntl[(I)-1]
23 #define INFOG(I) infog[(I)-1]
24 #define INFO(I) info[(I)-1]
25 #define RINFOG(I) rinfog[(I)-1]
26 #define RINFO(I) rinfo[(I)-1]
27 
28 typedef struct {
29 #if defined(PETSC_USE_COMPLEX)
30   ZMUMPS_STRUC_C id;
31 #else
32   DMUMPS_STRUC_C id;
33 #endif
34   MatStructure   matstruc;
35   PetscMPIInt    myid,size;
36   PetscInt       *irn,*jcn,sym,nSolve;
37   PetscScalar    *val;
38   MPI_Comm       comm_mumps;
39   VecScatter     scat_rhs, scat_sol;
40   PetscTruth     isAIJ,CleanUpMUMPS;
41   Vec            b_seq,x_seq;
42 } Mat_MUMPS;
43 
44 EXTERN PetscErrorCode MatDuplicate_MUMPS(Mat,MatDuplicateOption,Mat*);
45 
46 /* convert Petsc mpiaij matrix to triples: row[nz], col[nz], val[nz] */
47 /*
48   input:
49     A       - matrix in mpiaij or mpisbaij (bs=1) format
50     shift   - 0: C style output triple; 1: Fortran style output triple.
51     valOnly - FALSE: spaces are allocated and values are set for the triple
52               TRUE:  only the values in v array are updated
53   output:
54     nnz     - dim of r, c, and v (number of local nonzero entries of A)
55     r, c, v - row and col index, matrix values (matrix triples)
56  */
57 PetscErrorCode MatConvertToTriples(Mat A,int shift,PetscTruth valOnly,int *nnz,int **r, int **c, PetscScalar **v)
58 {
59   PetscInt       *ai, *aj, *bi, *bj, rstart,nz, *garray;
60   PetscErrorCode ierr;
61   PetscInt       i,j,jj,jB,irow,m=A->rmap.n,*ajj,*bjj,countA,countB,colA_start,jcol;
62   PetscInt       *row,*col;
63   PetscScalar    *av, *bv,*val;
64   PetscTruth     isAIJ;
65 
66   PetscFunctionBegin;
67   ierr = PetscTypeCompare((PetscObject)A,MATMPIAIJ,&isAIJ);CHKERRQ(ierr);
68   if (isAIJ){
69     Mat_MPIAIJ    *mat =  (Mat_MPIAIJ*)A->data;
70     Mat_SeqAIJ    *aa=(Mat_SeqAIJ*)(mat->A)->data;
71     Mat_SeqAIJ    *bb=(Mat_SeqAIJ*)(mat->B)->data;
72     nz = aa->nz + bb->nz;
73     ai=aa->i; aj=aa->j; bi=bb->i; bj=bb->j; rstart= A->rmap.rstart;
74     garray = mat->garray;
75     av=aa->a; bv=bb->a;
76 
77   } else {
78     Mat_MPISBAIJ  *mat =  (Mat_MPISBAIJ*)A->data;
79     Mat_SeqSBAIJ  *aa=(Mat_SeqSBAIJ*)(mat->A)->data;
80     Mat_SeqBAIJ    *bb=(Mat_SeqBAIJ*)(mat->B)->data;
81     if (A->rmap.bs > 1) SETERRQ1(PETSC_ERR_SUP," bs=%d is not supported yet\n", A->rmap.bs);
82     nz = aa->nz + bb->nz;
83     ai=aa->i; aj=aa->j; bi=bb->i; bj=bb->j; rstart= A->rmap.rstart;
84     garray = mat->garray;
85     av=aa->a; bv=bb->a;
86   }
87 
88   if (!valOnly){
89     ierr = PetscMalloc(nz*sizeof(PetscInt) ,&row);CHKERRQ(ierr);
90     ierr = PetscMalloc(nz*sizeof(PetscInt),&col);CHKERRQ(ierr);
91     ierr = PetscMalloc(nz*sizeof(PetscScalar),&val);CHKERRQ(ierr);
92     *r = row; *c = col; *v = val;
93   } else {
94     row = *r; col = *c; val = *v;
95   }
96   *nnz = nz;
97 
98   jj = 0; irow = rstart;
99   for ( i=0; i<m; i++ ) {
100     ajj = aj + ai[i];                 /* ptr to the beginning of this row */
101     countA = ai[i+1] - ai[i];
102     countB = bi[i+1] - bi[i];
103     bjj = bj + bi[i];
104 
105     /* get jB, the starting local col index for the 2nd B-part */
106     colA_start = rstart + ajj[0]; /* the smallest col index for A */
107     j=-1;
108     do {
109       j++;
110       if (j == countB) break;
111       jcol = garray[bjj[j]];
112     } while (jcol < colA_start);
113     jB = j;
114 
115     /* B-part, smaller col index */
116     colA_start = rstart + ajj[0]; /* the smallest col index for A */
117     for (j=0; j<jB; j++){
118       jcol = garray[bjj[j]];
119       if (!valOnly){
120         row[jj] = irow + shift; col[jj] = jcol + shift;
121 
122       }
123       val[jj++] = *bv++;
124     }
125     /* A-part */
126     for (j=0; j<countA; j++){
127       if (!valOnly){
128         row[jj] = irow + shift; col[jj] = rstart + ajj[j] + shift;
129       }
130       val[jj++] = *av++;
131     }
132     /* B-part, larger col index */
133     for (j=jB; j<countB; j++){
134       if (!valOnly){
135         row[jj] = irow + shift; col[jj] = garray[bjj[j]] + shift;
136       }
137       val[jj++] = *bv++;
138     }
139     irow++;
140   }
141 
142   PetscFunctionReturn(0);
143 }
144 
145 #undef __FUNCT__
146 #define __FUNCT__ "MatDestroy_MUMPS"
147 PetscErrorCode MatDestroy_MUMPS(Mat A)
148 {
149   Mat_MUMPS      *lu=(Mat_MUMPS*)A->spptr;
150   PetscErrorCode ierr;
151   PetscMPIInt    size=lu->size;
152 
153   PetscFunctionBegin;
154   if (lu->CleanUpMUMPS) {
155     /* Terminate instance, deallocate memories */
156     if (size > 1){
157       ierr = PetscFree(lu->id.sol_loc);CHKERRQ(ierr);
158       ierr = VecScatterDestroy(lu->scat_rhs);CHKERRQ(ierr);
159       ierr = VecDestroy(lu->b_seq);CHKERRQ(ierr);
160       if (lu->nSolve && lu->scat_sol){ierr = VecScatterDestroy(lu->scat_sol);CHKERRQ(ierr);}
161       if (lu->nSolve && lu->x_seq){ierr = VecDestroy(lu->x_seq);CHKERRQ(ierr);}
162       ierr = PetscFree(lu->val);CHKERRQ(ierr);
163     }
164     lu->id.job=JOB_END;
165 #if defined(PETSC_USE_COMPLEX)
166     zmumps_c(&lu->id);
167 #else
168     dmumps_c(&lu->id);
169 #endif
170     ierr = PetscFree(lu->irn);CHKERRQ(ierr);
171     ierr = PetscFree(lu->jcn);CHKERRQ(ierr);
172     ierr = MPI_Comm_free(&(lu->comm_mumps));CHKERRQ(ierr);
173   }
174   ierr = (*A->ops->destroy)(A);CHKERRQ(ierr);
175   PetscFunctionReturn(0);
176 }
177 
178 #undef __FUNCT__
179 #define __FUNCT__ "MatSolve_MUMPS"
180 PetscErrorCode MatSolve_MUMPS(Mat A,Vec b,Vec x)
181 {
182   Mat_MUMPS      *lu=(Mat_MUMPS*)A->spptr;
183   PetscScalar    *array;
184   Vec            x_seq;
185   IS             is_iden,is_petsc;
186   PetscErrorCode ierr;
187   PetscInt       i;
188 
189   PetscFunctionBegin;
190   lu->id.nrhs = 1;
191   x_seq = lu->b_seq;
192   if (lu->size > 1){
193     /* MUMPS only supports centralized rhs. Scatter b into a seqential rhs vector */
194     ierr = VecScatterBegin(lu->scat_rhs,b,x_seq,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
195     ierr = VecScatterEnd(lu->scat_rhs,b,x_seq,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
196     if (!lu->myid) {ierr = VecGetArray(x_seq,&array);CHKERRQ(ierr);}
197   } else {  /* size == 1 */
198     ierr = VecCopy(b,x);CHKERRQ(ierr);
199     ierr = VecGetArray(x,&array);CHKERRQ(ierr);
200   }
201   if (!lu->myid) { /* define rhs on the host */
202 #if defined(PETSC_USE_COMPLEX)
203     lu->id.rhs = (mumps_double_complex*)array;
204 #else
205     lu->id.rhs = array;
206 #endif
207   }
208   if (lu->size == 1){
209     ierr = VecRestoreArray(x,&array);CHKERRQ(ierr);
210   } else if (!lu->myid){
211     ierr = VecRestoreArray(x_seq,&array);CHKERRQ(ierr);
212   }
213 
214   if (lu->size > 1){
215     /* distributed solution */
216     lu->id.ICNTL(21) = 1;
217     if (!lu->nSolve){
218       /* Create x_seq=sol_loc for repeated use */
219       PetscInt    lsol_loc;
220       PetscScalar *sol_loc;
221       lsol_loc = lu->id.INFO(23); /* length of sol_loc */
222       ierr = PetscMalloc((1+lsol_loc)*(sizeof(PetscScalar)+sizeof(PetscInt)),&sol_loc);CHKERRQ(ierr);
223       lu->id.isol_loc = (PetscInt *)(sol_loc + lsol_loc);
224       lu->id.lsol_loc = lsol_loc;
225 #if defined(PETSC_USE_COMPLEX)
226       lu->id.sol_loc  = (ZMUMPS_DOUBLE *)sol_loc;
227 #else
228       lu->id.sol_loc  = (DMUMPS_DOUBLE *)sol_loc;
229 #endif
230       ierr = VecCreateSeqWithArray(PETSC_COMM_SELF,lsol_loc,sol_loc,&lu->x_seq);CHKERRQ(ierr);
231     }
232   }
233 
234   /* solve phase */
235   /*-------------*/
236   lu->id.job = 3;
237 #if defined(PETSC_USE_COMPLEX)
238   zmumps_c(&lu->id);
239 #else
240   dmumps_c(&lu->id);
241 #endif
242   if (lu->id.INFOG(1) < 0) {
243     SETERRQ1(PETSC_ERR_LIB,"Error reported by MUMPS in solve phase: INFOG(1)=%d\n",lu->id.INFOG(1));
244   }
245 
246   if (lu->size > 1) { /* convert mumps distributed solution to petsc mpi x */
247     if (!lu->nSolve){ /* create scatter scat_sol */
248       ierr = ISCreateStride(PETSC_COMM_SELF,lu->id.lsol_loc,0,1,&is_iden);CHKERRQ(ierr); /* from */
249       for (i=0; i<lu->id.lsol_loc; i++){
250         lu->id.isol_loc[i] -= 1; /* change Fortran style to C style */
251       }
252       ierr = ISCreateGeneral(PETSC_COMM_SELF,lu->id.lsol_loc,lu->id.isol_loc,&is_petsc);CHKERRQ(ierr);  /* to */
253       ierr = VecScatterCreate(lu->x_seq,is_iden,x,is_petsc,&lu->scat_sol);CHKERRQ(ierr);
254       ierr = ISDestroy(is_iden);CHKERRQ(ierr);
255       ierr = ISDestroy(is_petsc);CHKERRQ(ierr);
256     }
257     ierr = VecScatterBegin(lu->scat_sol,lu->x_seq,x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
258     ierr = VecScatterEnd(lu->scat_sol,lu->x_seq,x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
259   }
260   lu->nSolve++;
261   PetscFunctionReturn(0);
262 }
263 
264 #if !defined(PETSC_USE_COMPLEX)
265 /*
266   input:
267    F:        numeric factor
268   output:
269    nneg:     total number of negative pivots
270    nzero:    0
271    npos:     (global dimension of F) - nneg
272 */
273 
274 #undef __FUNCT__
275 #define __FUNCT__ "MatGetInertia_SBAIJMUMPS"
276 PetscErrorCode MatGetInertia_SBAIJMUMPS(Mat F,int *nneg,int *nzero,int *npos)
277 {
278   Mat_MUMPS      *lu =(Mat_MUMPS*)F->spptr;
279   PetscErrorCode ierr;
280   PetscMPIInt    size;
281 
282   PetscFunctionBegin;
283   ierr = MPI_Comm_size(((PetscObject)F)->comm,&size);CHKERRQ(ierr);
284   /* MUMPS 4.3.1 calls ScaLAPACK when ICNTL(13)=0 (default), which does not offer the possibility to compute the inertia of a dense matrix. Set ICNTL(13)=1 to skip ScaLAPACK */
285   if (size > 1 && lu->id.ICNTL(13) != 1){
286     SETERRQ1(PETSC_ERR_ARG_WRONG,"ICNTL(13)=%d. -mat_mumps_icntl_13 must be set as 1 for correct global matrix inertia\n",lu->id.INFOG(13));
287   }
288   if (nneg){
289     if (!lu->myid){
290       *nneg = lu->id.INFOG(12);
291     }
292     ierr = MPI_Bcast(nneg,1,MPI_INT,0,lu->comm_mumps);CHKERRQ(ierr);
293   }
294   if (nzero) *nzero = 0;
295   if (npos)  *npos  = F->rmap.N - (*nneg);
296   PetscFunctionReturn(0);
297 }
298 #endif /* !defined(PETSC_USE_COMPLEX) */
299 
300 #undef __FUNCT__
301 #define __FUNCT__ "MatFactorNumeric_MUMPS"
302 PetscErrorCode MatFactorNumeric_MUMPS(Mat A,MatFactorInfo *info,Mat *F)
303 {
304   Mat_MUMPS      *lu =(Mat_MUMPS*)(*F)->spptr;
305   PetscErrorCode ierr;
306   PetscInt       rnz,nnz,nz=0,i,M=A->rmap.N,*ai,*aj,icntl;
307   PetscTruth     valOnly,flg;
308   Mat            F_diag;
309   IS             is_iden;
310   Vec            b;
311   PetscTruth     isSeqAIJ,isSeqSBAIJ;
312 
313   PetscFunctionBegin;
314   ierr = PetscTypeCompare((PetscObject)A,MATSEQAIJ,&isSeqAIJ);CHKERRQ(ierr);
315   ierr = PetscTypeCompare((PetscObject)A,MATSEQSBAIJ,&isSeqSBAIJ);CHKERRQ(ierr);
316   if (lu->matstruc == DIFFERENT_NONZERO_PATTERN){
317     (*F)->ops->solve    = MatSolve_MUMPS;
318 
319     /* Initialize a MUMPS instance */
320     ierr = MPI_Comm_rank(((PetscObject)A)->comm, &lu->myid);
321     ierr = MPI_Comm_size(((PetscObject)A)->comm,&lu->size);CHKERRQ(ierr);
322     lu->id.job = JOB_INIT;
323     ierr = MPI_Comm_dup(((PetscObject)A)->comm,&(lu->comm_mumps));CHKERRQ(ierr);
324     lu->id.comm_fortran = MPI_Comm_c2f(lu->comm_mumps);
325 
326     /* Set mumps options */
327     ierr = PetscOptionsBegin(((PetscObject)A)->comm,((PetscObject)A)->prefix,"MUMPS Options","Mat");CHKERRQ(ierr);
328     lu->id.par=1;  /* host participates factorizaton and solve */
329     lu->id.sym=lu->sym;
330     if (lu->sym == 2){
331       ierr = PetscOptionsInt("-mat_mumps_sym","SYM: (1,2)","None",lu->id.sym,&icntl,&flg);CHKERRQ(ierr);
332       if (flg && icntl == 1) lu->id.sym=icntl;  /* matrix is spd */
333     }
334 #if defined(PETSC_USE_COMPLEX)
335     zmumps_c(&lu->id);
336 #else
337     dmumps_c(&lu->id);
338 #endif
339 
340     if (isSeqAIJ || isSeqSBAIJ){
341       lu->id.ICNTL(18) = 0;   /* centralized assembled matrix input */
342     } else {
343       lu->id.ICNTL(18) = 3;   /* distributed assembled matrix input */
344     }
345 
346     icntl=-1;
347     lu->id.ICNTL(4) = 0;  /* level of printing; overwrite mumps default ICNTL(4)=2 */
348     ierr = PetscOptionsInt("-mat_mumps_icntl_4","ICNTL(4): level of printing (0 to 4)","None",lu->id.ICNTL(4),&icntl,&flg);CHKERRQ(ierr);
349     if ((flg && icntl > 0) || PetscLogPrintInfo) {
350       lu->id.ICNTL(4)=icntl; /* and use mumps default icntl(i), i=1,2,3 */
351     } else { /* no output */
352       lu->id.ICNTL(1) = 0;  /* error message, default= 6 */
353       lu->id.ICNTL(2) = -1; /* output stream for diagnostic printing, statistics, and warning. default=0 */
354       lu->id.ICNTL(3) = -1; /* output stream for global information, default=6 */
355     }
356     ierr = PetscOptionsInt("-mat_mumps_icntl_6","ICNTL(6): matrix prescaling (0 to 7)","None",lu->id.ICNTL(6),&lu->id.ICNTL(6),PETSC_NULL);CHKERRQ(ierr);
357     icntl=-1;
358     ierr = PetscOptionsInt("-mat_mumps_icntl_7","ICNTL(7): matrix ordering (0 to 7)","None",lu->id.ICNTL(7),&icntl,&flg);CHKERRQ(ierr);
359     if (flg) {
360       if (icntl== 1){
361         SETERRQ(PETSC_ERR_SUP,"pivot order be set by the user in PERM_IN -- not supported by the PETSc/MUMPS interface\n");
362       } else {
363         lu->id.ICNTL(7) = icntl;
364       }
365     }
366     ierr = PetscOptionsInt("-mat_mumps_icntl_9","ICNTL(9): A or A^T x=b to be solved. 1: A; otherwise: A^T","None",lu->id.ICNTL(9),&lu->id.ICNTL(9),PETSC_NULL);CHKERRQ(ierr);
367     ierr = PetscOptionsInt("-mat_mumps_icntl_10","ICNTL(10): max num of refinements","None",lu->id.ICNTL(10),&lu->id.ICNTL(10),PETSC_NULL);CHKERRQ(ierr);
368     ierr = PetscOptionsInt("-mat_mumps_icntl_11","ICNTL(11): error analysis, a positive value returns statistics (by -ksp_view)","None",lu->id.ICNTL(11),&lu->id.ICNTL(11),PETSC_NULL);CHKERRQ(ierr);
369     ierr = PetscOptionsInt("-mat_mumps_icntl_12","ICNTL(12): efficiency control","None",lu->id.ICNTL(12),&lu->id.ICNTL(12),PETSC_NULL);CHKERRQ(ierr);
370     ierr = PetscOptionsInt("-mat_mumps_icntl_13","ICNTL(13): efficiency control","None",lu->id.ICNTL(13),&lu->id.ICNTL(13),PETSC_NULL);CHKERRQ(ierr);
371     ierr = PetscOptionsInt("-mat_mumps_icntl_14","ICNTL(14): percentage of estimated workspace increase","None",lu->id.ICNTL(14),&lu->id.ICNTL(14),PETSC_NULL);CHKERRQ(ierr);
372     ierr = PetscOptionsInt("-mat_mumps_icntl_15","ICNTL(15): efficiency control","None",lu->id.ICNTL(15),&lu->id.ICNTL(15),PETSC_NULL);CHKERRQ(ierr);
373 
374     ierr = PetscOptionsReal("-mat_mumps_cntl_1","CNTL(1): relative pivoting threshold","None",lu->id.CNTL(1),&lu->id.CNTL(1),PETSC_NULL);CHKERRQ(ierr);
375     ierr = PetscOptionsReal("-mat_mumps_cntl_2","CNTL(2): stopping criterion of refinement","None",lu->id.CNTL(2),&lu->id.CNTL(2),PETSC_NULL);CHKERRQ(ierr);
376     ierr = PetscOptionsReal("-mat_mumps_cntl_3","CNTL(3): absolute pivoting threshold","None",lu->id.CNTL(3),&lu->id.CNTL(3),PETSC_NULL);CHKERRQ(ierr);
377     ierr = PetscOptionsReal("-mat_mumps_cntl_4","CNTL(4): value for static pivoting","None",lu->id.CNTL(4),&lu->id.CNTL(4),PETSC_NULL);CHKERRQ(ierr);
378     PetscOptionsEnd();
379   }
380 
381   /* define matrix A */
382   switch (lu->id.ICNTL(18)){
383   case 0:  /* centralized assembled matrix input (size=1) */
384     if (!lu->myid) {
385       if (isSeqAIJ){
386         Mat_SeqAIJ   *aa = (Mat_SeqAIJ*)A->data;
387         nz               = aa->nz;
388         ai = aa->i; aj = aa->j; lu->val = aa->a;
389       } else if (isSeqSBAIJ) {
390         Mat_SeqSBAIJ *aa = (Mat_SeqSBAIJ*)A->data;
391         nz                  =  aa->nz;
392         ai = aa->i; aj = aa->j; lu->val = aa->a;
393       } else {
394         SETERRQ(PETSC_ERR_SUP,"No mumps factorization for this matrix type");
395       }
396       if (lu->matstruc == DIFFERENT_NONZERO_PATTERN){ /* first numeric factorization, get irn and jcn */
397         ierr = PetscMalloc(nz*sizeof(PetscInt),&lu->irn);CHKERRQ(ierr);
398         ierr = PetscMalloc(nz*sizeof(PetscInt),&lu->jcn);CHKERRQ(ierr);
399         nz = 0;
400         for (i=0; i<M; i++){
401           rnz = ai[i+1] - ai[i];
402           while (rnz--) {  /* Fortran row/col index! */
403             lu->irn[nz] = i+1; lu->jcn[nz] = (*aj)+1; aj++; nz++;
404           }
405         }
406       }
407     }
408     break;
409   case 3:  /* distributed assembled matrix input (size>1) */
410     if (lu->matstruc == DIFFERENT_NONZERO_PATTERN){
411       valOnly = PETSC_FALSE;
412     } else {
413       valOnly = PETSC_TRUE; /* only update mat values, not row and col index */
414     }
415     ierr = MatConvertToTriples(A,1,valOnly, &nnz, &lu->irn, &lu->jcn, &lu->val);CHKERRQ(ierr);
416     break;
417   default: SETERRQ(PETSC_ERR_SUP,"Matrix input format is not supported by MUMPS.");
418   }
419 
420   /* analysis phase */
421   /*----------------*/
422   if (lu->matstruc == DIFFERENT_NONZERO_PATTERN){
423     lu->id.job = 1;
424 
425     lu->id.n = M;
426     switch (lu->id.ICNTL(18)){
427     case 0:  /* centralized assembled matrix input */
428       if (!lu->myid) {
429         lu->id.nz =nz; lu->id.irn=lu->irn; lu->id.jcn=lu->jcn;
430         if (lu->id.ICNTL(6)>1){
431 #if defined(PETSC_USE_COMPLEX)
432           lu->id.a = (mumps_double_complex*)lu->val;
433 #else
434           lu->id.a = lu->val;
435 #endif
436         }
437       }
438       break;
439     case 3:  /* distributed assembled matrix input (size>1) */
440       lu->id.nz_loc = nnz;
441       lu->id.irn_loc=lu->irn; lu->id.jcn_loc=lu->jcn;
442       if (lu->id.ICNTL(6)>1) {
443 #if defined(PETSC_USE_COMPLEX)
444         lu->id.a_loc = (mumps_double_complex*)lu->val;
445 #else
446         lu->id.a_loc = lu->val;
447 #endif
448       }
449       /* MUMPS only supports centralized rhs. Create scatter scat_rhs for repeated use in MatSolve() */
450       if (!lu->myid){
451         ierr = VecCreateSeq(PETSC_COMM_SELF,A->cmap.N,&lu->b_seq);CHKERRQ(ierr);
452         ierr = ISCreateStride(PETSC_COMM_SELF,A->cmap.N,0,1,&is_iden);CHKERRQ(ierr);
453       } else {
454         ierr = VecCreateSeq(PETSC_COMM_SELF,0,&lu->b_seq);CHKERRQ(ierr);
455         ierr = ISCreateStride(PETSC_COMM_SELF,0,0,1,&is_iden);CHKERRQ(ierr);
456       }
457       ierr = VecCreate(((PetscObject)A)->comm,&b);CHKERRQ(ierr);
458       ierr = VecSetSizes(b,A->rmap.n,PETSC_DECIDE);CHKERRQ(ierr);
459       ierr = VecSetFromOptions(b);CHKERRQ(ierr);
460 
461       ierr = VecScatterCreate(b,is_iden,lu->b_seq,is_iden,&lu->scat_rhs);CHKERRQ(ierr);
462       ierr = ISDestroy(is_iden);CHKERRQ(ierr);
463       ierr = VecDestroy(b);CHKERRQ(ierr);
464       break;
465     }
466 #if defined(PETSC_USE_COMPLEX)
467     zmumps_c(&lu->id);
468 #else
469     dmumps_c(&lu->id);
470 #endif
471     if (lu->id.INFOG(1) < 0) {
472       SETERRQ1(PETSC_ERR_LIB,"Error reported by MUMPS in analysis phase: INFOG(1)=%d\n",lu->id.INFOG(1));
473     }
474   }
475 
476   /* numerical factorization phase */
477   /*-------------------------------*/
478   lu->id.job = 2;
479   if(!lu->id.ICNTL(18)) {
480     if (!lu->myid) {
481 #if defined(PETSC_USE_COMPLEX)
482       lu->id.a = (mumps_double_complex*)lu->val;
483 #else
484       lu->id.a = lu->val;
485 #endif
486     }
487   } else {
488 #if defined(PETSC_USE_COMPLEX)
489     lu->id.a_loc = (mumps_double_complex*)lu->val;
490 #else
491     lu->id.a_loc = lu->val;
492 #endif
493   }
494 #if defined(PETSC_USE_COMPLEX)
495   zmumps_c(&lu->id);
496 #else
497   dmumps_c(&lu->id);
498 #endif
499   if (lu->id.INFOG(1) < 0) {
500     if (lu->id.INFO(1) == -13) {
501       SETERRQ1(PETSC_ERR_LIB,"Error reported by MUMPS in numerical factorization phase: Cannot allocate required memory %d megabytes\n",lu->id.INFO(2));
502     } else {
503       SETERRQ2(PETSC_ERR_LIB,"Error reported by MUMPS in numerical factorization phase: INFO(1)=%d, INFO(2)=%d\n",lu->id.INFO(1),lu->id.INFO(2));
504     }
505   }
506 
507   if (!lu->myid && lu->id.ICNTL(16) > 0){
508     SETERRQ1(PETSC_ERR_LIB,"  lu->id.ICNTL(16):=%d\n",lu->id.INFOG(16));
509   }
510 
511   if (lu->size > 1){
512     if ((*F)->factor == MAT_FACTOR_LU){
513       F_diag = ((Mat_MPIAIJ *)(*F)->data)->A;
514     } else {
515       F_diag = ((Mat_MPISBAIJ *)(*F)->data)->A;
516     }
517     F_diag->assembled = PETSC_TRUE;
518     if (lu->nSolve){
519       ierr = VecScatterDestroy(lu->scat_sol);CHKERRQ(ierr);
520       ierr = PetscFree(lu->id.sol_loc);CHKERRQ(ierr);
521       ierr = VecDestroy(lu->x_seq);CHKERRQ(ierr);
522     }
523   }
524   (*F)->assembled   = PETSC_TRUE;
525   lu->matstruc      = SAME_NONZERO_PATTERN;
526   lu->CleanUpMUMPS  = PETSC_TRUE;
527   lu->nSolve        = 0;
528   PetscFunctionReturn(0);
529 }
530 
531 
532 /* Note the Petsc r and c permutations are ignored */
533 #undef __FUNCT__
534 #define __FUNCT__ "MatLUFactorSymbolic_AIJMUMPS"
535 PetscErrorCode MatLUFactorSymbolic_AIJMUMPS(Mat A,IS r,IS c,MatFactorInfo *info,Mat *F)
536 {
537   Mat_MUMPS      *lu = (Mat_MUMPS*)(*F)->spptr;
538 
539   PetscFunctionBegin;
540   lu->sym                 = 0;
541   lu->matstruc            = DIFFERENT_NONZERO_PATTERN;
542   PetscFunctionReturn(0);
543 }
544 
545 EXTERN_C_BEGIN
546 /*
547     The seq and mpi versions of this function are the same
548 */
549 #undef __FUNCT__
550 #define __FUNCT__ "MatGetFactor_seqaij_mumps"
551 PetscErrorCode MatGetFactor_seqaij_mumps(Mat A,MatFactorType ftype,Mat *F)
552 {
553   Mat            B;
554   PetscErrorCode ierr;
555   Mat_MUMPS      *mumps;
556 
557   PetscFunctionBegin;
558   if (ftype != MAT_FACTOR_LU) {
559     SETERRQ(PETSC_ERR_SUP,"Cannot use PETSc AIJ matrices with MUMPS Cholesky, use SBAIJ matrix");
560   }
561   /* Create the factorization matrix */
562   ierr = MatCreate(((PetscObject)A)->comm,&B);CHKERRQ(ierr);
563   ierr = MatSetSizes(B,A->rmap.n,A->cmap.n,A->rmap.N,A->cmap.N);CHKERRQ(ierr);
564   ierr = MatSetType(B,((PetscObject)A)->type_name);CHKERRQ(ierr);
565   ierr = MatSeqAIJSetPreallocation(B,0,PETSC_NULL);CHKERRQ(ierr);
566 
567   B->ops->lufactornumeric  = MatFactorNumeric_MUMPS;
568   B->ops->lufactorsymbolic = MatLUFactorSymbolic_AIJMUMPS;
569   B->factor                = MAT_FACTOR_LU;
570 
571   ierr = PetscNewLog(B,Mat_MUMPS,&mumps);CHKERRQ(ierr);
572   mumps->CleanUpMUMPS              = PETSC_FALSE;
573   mumps->isAIJ                     = PETSC_TRUE;
574   mumps->scat_rhs                  = PETSC_NULL;
575   mumps->scat_sol                  = PETSC_NULL;
576   mumps->nSolve                    = 0;
577 
578   B->spptr                         = (void*)mumps;
579 
580   *F = B;
581   PetscFunctionReturn(0);
582 }
583 EXTERN_C_END
584 
585 EXTERN_C_BEGIN
586 #undef __FUNCT__
587 #define __FUNCT__ "MatGetFactor_mpiaij_mumps"
588 PetscErrorCode MatGetFactor_mpiaij_mumps(Mat A,MatFactorType ftype,Mat *F)
589 {
590   Mat            B;
591   PetscErrorCode ierr;
592   Mat_MUMPS      *mumps;
593 
594   PetscFunctionBegin;
595   if (ftype != MAT_FACTOR_LU) {
596     SETERRQ(PETSC_ERR_SUP,"Cannot use PETSc AIJ matrices with MUMPS Cholesky, use SBAIJ matrix");
597   }
598   /* Create the factorization matrix */
599   ierr = MatCreate(((PetscObject)A)->comm,&B);CHKERRQ(ierr);
600   ierr = MatSetSizes(B,A->rmap.n,A->cmap.n,A->rmap.N,A->cmap.N);CHKERRQ(ierr);
601   ierr = MatSetType(B,((PetscObject)A)->type_name);CHKERRQ(ierr);
602   ierr = MatSeqAIJSetPreallocation(B,0,PETSC_NULL);CHKERRQ(ierr);
603   ierr = MatMPIAIJSetPreallocation(B,0,PETSC_NULL,0,PETSC_NULL);CHKERRQ(ierr);
604 
605   B->ops->lufactornumeric  = MatFactorNumeric_MUMPS;
606   B->ops->lufactorsymbolic = MatLUFactorSymbolic_AIJMUMPS;
607   B->factor                = MAT_FACTOR_LU;
608 
609   ierr = PetscNewLog(B,Mat_MUMPS,&mumps);CHKERRQ(ierr);
610   mumps->CleanUpMUMPS              = PETSC_FALSE;
611   mumps->isAIJ                     = PETSC_TRUE;
612   mumps->scat_rhs                  = PETSC_NULL;
613   mumps->scat_sol                  = PETSC_NULL;
614   mumps->nSolve                    = 0;
615 
616   B->spptr                         = (void*)mumps;
617 
618   *F = B;
619   PetscFunctionReturn(0);
620 }
621 EXTERN_C_END
622 
623 /* Note the Petsc r permutation is ignored */
624 #undef __FUNCT__
625 #define __FUNCT__ "MatCholeskyFactorSymbolic_SBAIJMUMPS"
626 PetscErrorCode MatCholeskyFactorSymbolic_SBAIJMUMPS(Mat A,IS r,MatFactorInfo *info,Mat *F)
627 {
628   Mat_MUMPS      *lu = (Mat_MUMPS*)(*F)->spptr;
629 
630   PetscFunctionBegin;
631   lu->sym                       = 2;
632   lu->matstruc                  = DIFFERENT_NONZERO_PATTERN;
633   PetscFunctionReturn(0);
634 }
635 
636 EXTERN_C_BEGIN
637 #undef __FUNCT__
638 #define __FUNCT__ "MatGetFactor_seqsbaij_mumps"
639 PetscErrorCode MatGetFactor_seqsbaij_mumps(Mat A,MatFactorType ftype,Mat *F)
640 {
641   Mat            B;
642   PetscErrorCode ierr;
643   Mat_MUMPS      *mumps;
644 
645   PetscFunctionBegin;
646   if (ftype != MAT_FACTOR_CHOLESKY) {
647     SETERRQ(PETSC_ERR_SUP,"Cannot use PETSc SBAIJ matrices with MUMPS LU, use AIJ matrix");
648   }
649   /* Create the factorization matrix */
650   ierr = MatCreate(((PetscObject)A)->comm,&B);CHKERRQ(ierr);
651   ierr = MatSetSizes(B,A->rmap.n,A->cmap.n,A->rmap.N,A->cmap.N);CHKERRQ(ierr);
652   ierr = MatSetType(B,((PetscObject)A)->type_name);CHKERRQ(ierr);
653   ierr = MatSeqSBAIJSetPreallocation(B,1,0,PETSC_NULL);CHKERRQ(ierr);
654   ierr = MatMPISBAIJSetPreallocation(B,1,0,PETSC_NULL,0,PETSC_NULL);CHKERRQ(ierr);
655 
656   B->ops->choleskyfactorsymbolic = MatCholeskyFactorSymbolic_SBAIJMUMPS;
657   B->ops->choleskyfactornumeric  = MatFactorNumeric_MUMPS;
658 #if !defined(PETSC_USE_COMPLEX)
659   B->ops->getinertia             = MatGetInertia_SBAIJMUMPS;
660 #endif
661   B->factor                      = MAT_FACTOR_CHOLESKY;
662 
663   ierr = PetscNewLog(B,Mat_MUMPS,&mumps);CHKERRQ(ierr);
664   mumps->CleanUpMUMPS              = PETSC_FALSE;
665   mumps->isAIJ                     = PETSC_TRUE;
666   mumps->scat_rhs                  = PETSC_NULL;
667   mumps->scat_sol                  = PETSC_NULL;
668   mumps->nSolve                    = 0;
669   B->spptr                         = (void*)mumps;
670   *F = B;
671   PetscFunctionReturn(0);
672 }
673 EXTERN_C_END
674 
675 EXTERN_C_BEGIN
676 #undef __FUNCT__
677 #define __FUNCT__ "MatGetFactor_mpisbaij_mumps"
678 PetscErrorCode MatGetFactor_mpisbaij_mumps(Mat A,MatFactorType ftype,Mat *F)
679 {
680   Mat            B;
681   PetscErrorCode ierr;
682   Mat_MUMPS      *mumps;
683 
684   PetscFunctionBegin;
685   if (ftype != MAT_FACTOR_CHOLESKY) {
686     SETERRQ(PETSC_ERR_SUP,"Cannot use PETSc SBAIJ matrices with MUMPS LU, use AIJ matrix");
687   }
688   /* Create the factorization matrix */
689   ierr = MatCreate(((PetscObject)A)->comm,&B);CHKERRQ(ierr);
690   ierr = MatSetSizes(B,A->rmap.n,A->cmap.n,A->rmap.N,A->cmap.N);CHKERRQ(ierr);
691   ierr = MatSetType(B,((PetscObject)A)->type_name);CHKERRQ(ierr);
692   ierr = MatSeqSBAIJSetPreallocation(B,1,0,PETSC_NULL);CHKERRQ(ierr);
693   ierr = MatMPISBAIJSetPreallocation(B,1,0,PETSC_NULL,0,PETSC_NULL);CHKERRQ(ierr);
694 
695   B->ops->choleskyfactorsymbolic = MatCholeskyFactorSymbolic_SBAIJMUMPS;
696   B->ops->choleskyfactornumeric  = MatFactorNumeric_MUMPS;
697 #if !defined(PETSC_USE_COMPLEX)
698   B->ops->getinertia             = MatGetInertia_SBAIJMUMPS;
699 #endif
700   B->factor                      = MAT_FACTOR_CHOLESKY;
701 
702   ierr = PetscNewLog(B,Mat_MUMPS,&mumps);CHKERRQ(ierr);
703   mumps->CleanUpMUMPS              = PETSC_FALSE;
704   mumps->isAIJ                     = PETSC_TRUE;
705   mumps->scat_rhs                  = PETSC_NULL;
706   mumps->scat_sol                  = PETSC_NULL;
707   mumps->nSolve                    = 0;
708   B->spptr                         = (void*)mumps;
709   *F = B;
710   PetscFunctionReturn(0);
711 }
712 EXTERN_C_END
713 
714 #undef __FUNCT__
715 #define __FUNCT__ "MatFactorInfo_MUMPS"
716 PetscErrorCode MatFactorInfo_MUMPS(Mat A,PetscViewer viewer) {
717   Mat_MUMPS      *lu=(Mat_MUMPS*)A->spptr;
718   PetscErrorCode ierr;
719 
720   PetscFunctionBegin;
721   /* check if matrix is mumps type */
722   if (A->ops->solve != MatSolve_MUMPS) PetscFunctionReturn(0);
723 
724   ierr = PetscViewerASCIIPrintf(viewer,"MUMPS run parameters:\n");CHKERRQ(ierr);
725   ierr = PetscViewerASCIIPrintf(viewer,"  SYM (matrix type):                  %d \n",lu->id.sym);CHKERRQ(ierr);
726   ierr = PetscViewerASCIIPrintf(viewer,"  PAR (host participation):           %d \n",lu->id.par);CHKERRQ(ierr);
727   ierr = PetscViewerASCIIPrintf(viewer,"  ICNTL(1) (output for error):        %d \n",lu->id.ICNTL(1));CHKERRQ(ierr);
728   ierr = PetscViewerASCIIPrintf(viewer,"  ICNTL(2) (output of diagnostic msg):%d \n",lu->id.ICNTL(2));CHKERRQ(ierr);
729   ierr = PetscViewerASCIIPrintf(viewer,"  ICNTL(3) (output for global info):  %d \n",lu->id.ICNTL(3));CHKERRQ(ierr);
730   ierr = PetscViewerASCIIPrintf(viewer,"  ICNTL(4) (level of printing):       %d \n",lu->id.ICNTL(4));CHKERRQ(ierr);
731   ierr = PetscViewerASCIIPrintf(viewer,"  ICNTL(5) (input mat struct):        %d \n",lu->id.ICNTL(5));CHKERRQ(ierr);
732   ierr = PetscViewerASCIIPrintf(viewer,"  ICNTL(6) (matrix prescaling):       %d \n",lu->id.ICNTL(6));CHKERRQ(ierr);
733   ierr = PetscViewerASCIIPrintf(viewer,"  ICNTL(7) (matrix ordering):         %d \n",lu->id.ICNTL(7));CHKERRQ(ierr);
734   ierr = PetscViewerASCIIPrintf(viewer,"  ICNTL(8) (scalling strategy):       %d \n",lu->id.ICNTL(8));CHKERRQ(ierr);
735   ierr = PetscViewerASCIIPrintf(viewer,"  ICNTL(9) (A/A^T x=b is solved):     %d \n",lu->id.ICNTL(9));CHKERRQ(ierr);
736   ierr = PetscViewerASCIIPrintf(viewer,"  ICNTL(10) (max num of refinements): %d \n",lu->id.ICNTL(10));CHKERRQ(ierr);
737   ierr = PetscViewerASCIIPrintf(viewer,"  ICNTL(11) (error analysis):         %d \n",lu->id.ICNTL(11));CHKERRQ(ierr);
738   if (!lu->myid && lu->id.ICNTL(11)>0) {
739     ierr = PetscPrintf(PETSC_COMM_SELF,"        RINFOG(4) (inf norm of input mat):        %g\n",lu->id.RINFOG(4));CHKERRQ(ierr);
740     ierr = PetscPrintf(PETSC_COMM_SELF,"        RINFOG(5) (inf norm of solution):         %g\n",lu->id.RINFOG(5));CHKERRQ(ierr);
741     ierr = PetscPrintf(PETSC_COMM_SELF,"        RINFOG(6) (inf norm of residual):         %g\n",lu->id.RINFOG(6));CHKERRQ(ierr);
742     ierr = PetscPrintf(PETSC_COMM_SELF,"        RINFOG(7),RINFOG(8) (backward error est): %g, %g\n",lu->id.RINFOG(7),lu->id.RINFOG(8));CHKERRQ(ierr);
743     ierr = PetscPrintf(PETSC_COMM_SELF,"        RINFOG(9) (error estimate):               %g \n",lu->id.RINFOG(9));CHKERRQ(ierr);
744     ierr = PetscPrintf(PETSC_COMM_SELF,"        RINFOG(10),RINFOG(11)(condition numbers): %g, %g\n",lu->id.RINFOG(10),lu->id.RINFOG(11));CHKERRQ(ierr);
745 
746   }
747   ierr = PetscViewerASCIIPrintf(viewer,"  ICNTL(12) (efficiency control):                         %d \n",lu->id.ICNTL(12));CHKERRQ(ierr);
748   ierr = PetscViewerASCIIPrintf(viewer,"  ICNTL(13) (efficiency control):                         %d \n",lu->id.ICNTL(13));CHKERRQ(ierr);
749   ierr = PetscViewerASCIIPrintf(viewer,"  ICNTL(14) (percentage of estimated workspace increase): %d \n",lu->id.ICNTL(14));CHKERRQ(ierr);
750   /* ICNTL(15-17) not used */
751   ierr = PetscViewerASCIIPrintf(viewer,"  ICNTL(18) (input mat struct):                           %d \n",lu->id.ICNTL(18));CHKERRQ(ierr);
752   ierr = PetscViewerASCIIPrintf(viewer,"  ICNTL(19) (Shur complement info):                       %d \n",lu->id.ICNTL(19));CHKERRQ(ierr);
753   ierr = PetscViewerASCIIPrintf(viewer,"  ICNTL(20) (rhs sparse pattern):                         %d \n",lu->id.ICNTL(20));CHKERRQ(ierr);
754   ierr = PetscViewerASCIIPrintf(viewer,"  ICNTL(21) (solution struct):                            %d \n",lu->id.ICNTL(21));CHKERRQ(ierr);
755 
756   ierr = PetscViewerASCIIPrintf(viewer,"  CNTL(1) (relative pivoting threshold):      %g \n",lu->id.CNTL(1));CHKERRQ(ierr);
757   ierr = PetscViewerASCIIPrintf(viewer,"  CNTL(2) (stopping criterion of refinement): %g \n",lu->id.CNTL(2));CHKERRQ(ierr);
758   ierr = PetscViewerASCIIPrintf(viewer,"  CNTL(3) (absolute pivoting threshold):      %g \n",lu->id.CNTL(3));CHKERRQ(ierr);
759   ierr = PetscViewerASCIIPrintf(viewer,"  CNTL(4) (value of static pivoting):         %g \n",lu->id.CNTL(4));CHKERRQ(ierr);
760 
761   /* infomation local to each processor */
762   if (!lu->myid) {ierr = PetscPrintf(PETSC_COMM_SELF, "      RINFO(1) (local estimated flops for the elimination after analysis): \n");CHKERRQ(ierr);}
763   ierr = PetscSynchronizedPrintf(((PetscObject)A)->comm,"             [%d] %g \n",lu->myid,lu->id.RINFO(1));CHKERRQ(ierr);
764   ierr = PetscSynchronizedFlush(((PetscObject)A)->comm);
765   if (!lu->myid) {ierr = PetscPrintf(PETSC_COMM_SELF, "      RINFO(2) (local estimated flops for the assembly after factorization): \n");CHKERRQ(ierr);}
766   ierr = PetscSynchronizedPrintf(((PetscObject)A)->comm,"             [%d]  %g \n",lu->myid,lu->id.RINFO(2));CHKERRQ(ierr);
767   ierr = PetscSynchronizedFlush(((PetscObject)A)->comm);
768   if (!lu->myid) {ierr = PetscPrintf(PETSC_COMM_SELF, "      RINFO(3) (local estimated flops for the elimination after factorization): \n");CHKERRQ(ierr);}
769   ierr = PetscSynchronizedPrintf(((PetscObject)A)->comm,"             [%d]  %g \n",lu->myid,lu->id.RINFO(3));CHKERRQ(ierr);
770   ierr = PetscSynchronizedFlush(((PetscObject)A)->comm);
771   /*
772   if (!lu->myid) {ierr = PetscPrintf(PETSC_COMM_SELF, "      INFO(2) (info about error or warning ): \n");CHKERRQ(ierr);}
773   ierr = PetscSynchronizedPrintf(((PetscObject)A)->comm,"             [%d] %d \n",lu->myid,lu->id.INFO(2));CHKERRQ(ierr);
774   ierr = PetscSynchronizedFlush(((PetscObject)A)->comm);
775   */
776 
777   if (!lu->myid) {ierr = PetscPrintf(PETSC_COMM_SELF, "      INFO(15) (estimated size of (in MB) MUMPS internal data for running numerical factorization): \n");CHKERRQ(ierr);}
778   ierr = PetscSynchronizedPrintf(((PetscObject)A)->comm,"             [%d] %d \n",lu->myid,lu->id.INFO(15));CHKERRQ(ierr);
779   ierr = PetscSynchronizedFlush(((PetscObject)A)->comm);
780 
781   if (!lu->myid) {ierr = PetscPrintf(PETSC_COMM_SELF, "      INFO(16) (size of (in MB) MUMPS internal data used during numerical factorization): \n");CHKERRQ(ierr);}
782   ierr = PetscSynchronizedPrintf(((PetscObject)A)->comm,"             [%d] %d \n",lu->myid,lu->id.INFO(16));CHKERRQ(ierr);
783   ierr = PetscSynchronizedFlush(((PetscObject)A)->comm);
784 
785   if (!lu->myid) {ierr = PetscPrintf(PETSC_COMM_SELF, "      INFO(23) (num of pivots eliminated on this processor after factorization): \n");CHKERRQ(ierr);}
786   ierr = PetscSynchronizedPrintf(((PetscObject)A)->comm,"             [%d] %d \n",lu->myid,lu->id.INFO(23));CHKERRQ(ierr);
787   ierr = PetscSynchronizedFlush(((PetscObject)A)->comm);
788 
789   if (!lu->myid){ /* information from the host */
790     ierr = PetscViewerASCIIPrintf(viewer,"  RINFOG(1) (global estimated flops for the elimination after analysis): %g \n",lu->id.RINFOG(1));CHKERRQ(ierr);
791     ierr = PetscViewerASCIIPrintf(viewer,"  RINFOG(2) (global estimated flops for the assembly after factorization): %g \n",lu->id.RINFOG(2));CHKERRQ(ierr);
792     ierr = PetscViewerASCIIPrintf(viewer,"  RINFOG(3) (global estimated flops for the elimination after factorization): %g \n",lu->id.RINFOG(3));CHKERRQ(ierr);
793 
794     ierr = PetscViewerASCIIPrintf(viewer,"  INFOG(3) (estimated real workspace for factors on all processors after analysis): %d \n",lu->id.INFOG(3));CHKERRQ(ierr);
795     ierr = PetscViewerASCIIPrintf(viewer,"  INFOG(4) (estimated integer workspace for factors on all processors after analysis): %d \n",lu->id.INFOG(4));CHKERRQ(ierr);
796     ierr = PetscViewerASCIIPrintf(viewer,"  INFOG(5) (estimated maximum front size in the complete tree): %d \n",lu->id.INFOG(5));CHKERRQ(ierr);
797     ierr = PetscViewerASCIIPrintf(viewer,"  INFOG(6) (number of nodes in the complete tree): %d \n",lu->id.INFOG(6));CHKERRQ(ierr);
798     ierr = PetscViewerASCIIPrintf(viewer,"  INFOG(7) (ordering option effectively uese after analysis): %d \n",lu->id.INFOG(7));CHKERRQ(ierr);
799     ierr = PetscViewerASCIIPrintf(viewer,"  INFOG(8) (structural symmetry in percent of the permuted matrix after analysis): %d \n",lu->id.INFOG(8));CHKERRQ(ierr);
800     ierr = PetscViewerASCIIPrintf(viewer,"  INFOG(9) (total real/complex workspace to store the matrix factors after factorization): %d \n",lu->id.INFOG(9));CHKERRQ(ierr);
801     ierr = PetscViewerASCIIPrintf(viewer,"  INFOG(10) (total integer space store the matrix factors after factorization): %d \n",lu->id.INFOG(10));CHKERRQ(ierr);
802     ierr = PetscViewerASCIIPrintf(viewer,"  INFOG(11) (order of largest frontal matrix after factorization): %d \n",lu->id.INFOG(11));CHKERRQ(ierr);
803     ierr = PetscViewerASCIIPrintf(viewer,"  INFOG(12) (number of off-diagonal pivots): %d \n",lu->id.INFOG(12));CHKERRQ(ierr);
804     ierr = PetscViewerASCIIPrintf(viewer,"  INFOG(13) (number of delayed pivots after factorization): %d \n",lu->id.INFOG(13));CHKERRQ(ierr);
805     ierr = PetscViewerASCIIPrintf(viewer,"  INFOG(14) (number of memory compress after factorization): %d \n",lu->id.INFOG(14));CHKERRQ(ierr);
806     ierr = PetscViewerASCIIPrintf(viewer,"  INFOG(15) (number of steps of iterative refinement after solution): %d \n",lu->id.INFOG(15));CHKERRQ(ierr);
807     ierr = PetscViewerASCIIPrintf(viewer,"  INFOG(16) (estimated size (in MB) of all MUMPS internal data for factorization after analysis: value on the most memory consuming processor): %d \n",lu->id.INFOG(16));CHKERRQ(ierr);
808     ierr = PetscViewerASCIIPrintf(viewer,"  INFOG(17) (estimated size of all MUMPS internal data for factorization after analysis: sum over all processors): %d \n",lu->id.INFOG(17));CHKERRQ(ierr);
809     ierr = PetscViewerASCIIPrintf(viewer,"  INFOG(18) (size of all MUMPS internal data allocated during factorization: value on the most memory consuming processor): %d \n",lu->id.INFOG(18));CHKERRQ(ierr);
810     ierr = PetscViewerASCIIPrintf(viewer,"  INFOG(19) (size of all MUMPS internal data allocated during factorization: sum over all processors): %d \n",lu->id.INFOG(19));CHKERRQ(ierr);
811      ierr = PetscViewerASCIIPrintf(viewer,"  INFOG(20) (estimated number of entries in the factors): %d \n",lu->id.INFOG(20));CHKERRQ(ierr);
812      ierr = PetscViewerASCIIPrintf(viewer,"  INFOG(21) (size in MB of memory effectively used during factorization - value on the most memory consuming processor): %d \n",lu->id.INFOG(21));CHKERRQ(ierr);
813      ierr = PetscViewerASCIIPrintf(viewer,"  INFOG(22) (size in MB of memory effectively used during factorization - sum over all processors): %d \n",lu->id.INFOG(22));CHKERRQ(ierr);
814      ierr = PetscViewerASCIIPrintf(viewer,"  INFOG(23) (after analysis: value of ICNTL(6) effectively used): %d \n",lu->id.INFOG(23));CHKERRQ(ierr);
815      ierr = PetscViewerASCIIPrintf(viewer,"  INFOG(24) (after analysis: value of ICNTL(12) effectively used): %d \n",lu->id.INFOG(24));CHKERRQ(ierr);
816      ierr = PetscViewerASCIIPrintf(viewer,"  INFOG(25) (after factorization: number of pivots modified by static pivoting): %d \n",lu->id.INFOG(25));CHKERRQ(ierr);
817   }
818 
819   PetscFunctionReturn(0);
820 }
821 
822 #undef __FUNCT__
823 #define __FUNCT__ "MatView_MUMPS"
824 PetscErrorCode MatView_MUMPS(Mat A,PetscViewer viewer)
825 {
826   PetscErrorCode    ierr;
827   PetscTruth        iascii;
828   PetscViewerFormat format;
829 
830   PetscFunctionBegin;
831     ierr = PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_ASCII,&iascii);CHKERRQ(ierr);
832   if (iascii) {
833     ierr = PetscViewerGetFormat(viewer,&format);CHKERRQ(ierr);
834     if (format == PETSC_VIEWER_ASCII_INFO){
835       ierr = MatFactorInfo_MUMPS(A,viewer);CHKERRQ(ierr);
836     }
837   }
838   PetscFunctionReturn(0);
839 }
840 
841 
842 /*MC
843   MATAIJMUMPS - MATAIJMUMPS = "aijmumps" - A matrix type providing direct solvers (LU) for distributed
844   and sequential matrices via the external package MUMPS.
845 
846   If MUMPS is installed (see the manual for instructions
847   on how to declare the existence of external packages),
848   a matrix type can be constructed which invokes MUMPS solvers.
849   After calling MatCreate(...,A), simply call MatSetType(A,MATAIJMUMPS), then
850   optionally call MatSeqAIJSetPreallocation() or MatMPIAIJSetPreallocation() etc DO NOT
851   call MatCreateSeqAIJ/MPIAIJ() directly or the preallocation information will be LOST!
852 
853   If created with a single process communicator, this matrix type inherits from MATSEQAIJ.
854   Otherwise, this matrix type inherits from MATMPIAIJ.  Hence for single process communicators,
855   MatSeqAIJSetPreallocation() is supported, and similarly MatMPIAIJSetPreallocation() is supported
856   for communicators controlling multiple processes.  It is recommended that you call both of
857   the above preallocation routines for simplicity.  One can also call MatConvert() for an inplace
858   conversion to or from the MATSEQAIJ or MATMPIAIJ type (depending on the communicator size)
859   without data copy AFTER the matrix values are set.
860 
861   Options Database Keys:
862 + -mat_type aijmumps - sets the matrix type to "aijmumps" during a call to MatSetFromOptions()
863 . -mat_mumps_sym <0,1,2> - 0 the matrix is unsymmetric, 1 symmetric positive definite, 2 symmetric
864 . -mat_mumps_icntl_4 <0,1,2,3,4> - print level
865 . -mat_mumps_icntl_6 <0,...,7> - matrix prescaling options (see MUMPS User's Guide)
866 . -mat_mumps_icntl_7 <0,...,7> - matrix orderings (see MUMPS User's Guide)
867 . -mat_mumps_icntl_9 <1,2> - A or A^T x=b to be solved: 1 denotes A, 2 denotes A^T
868 . -mat_mumps_icntl_10 <n> - maximum number of iterative refinements
869 . -mat_mumps_icntl_11 <n> - error analysis, a positive value returns statistics during -ksp_view
870 . -mat_mumps_icntl_12 <n> - efficiency control (see MUMPS User's Guide)
871 . -mat_mumps_icntl_13 <n> - efficiency control (see MUMPS User's Guide)
872 . -mat_mumps_icntl_14 <n> - efficiency control (see MUMPS User's Guide)
873 . -mat_mumps_icntl_15 <n> - efficiency control (see MUMPS User's Guide)
874 . -mat_mumps_cntl_1 <delta> - relative pivoting threshold
875 . -mat_mumps_cntl_2 <tol> - stopping criterion for refinement
876 - -mat_mumps_cntl_3 <adelta> - absolute pivoting threshold
877 
878   Level: beginner
879 
880 .seealso: MATSBAIJMUMPS
881 M*/
882 
883 
884 /*MC
885   MATSBAIJMUMPS - MATSBAIJMUMPS = "sbaijmumps" - A symmetric matrix type providing direct solvers (Cholesky) for
886   distributed and sequential matrices via the external package MUMPS.
887 
888   If MUMPS is installed (see the manual for instructions
889   on how to declare the existence of external packages),
890   a matrix type can be constructed which invokes MUMPS solvers.
891   After calling MatCreate(...,A), simply call MatSetType(A,MATSBAIJMUMPS), then
892   optionally call MatSeqSBAIJSetPreallocation() or MatMPISBAIJSetPreallocation() DO NOT
893   call MatCreateSeqSBAIJ/MPISBAIJ() directly or the preallocation information will be LOST!
894 
895   If created with a single process communicator, this matrix type inherits from MATSEQSBAIJ.
896   Otherwise, this matrix type inherits from MATMPISBAIJ.  Hence for single process communicators,
897   MatSeqSBAIJSetPreallocation() is supported, and similarly MatMPISBAIJSetPreallocation() is supported
898   for communicators controlling multiple processes.  It is recommended that you call both of
899   the above preallocation routines for simplicity.  One can also call MatConvert() for an inplace
900   conversion to or from the MATSEQSBAIJ or MATMPISBAIJ type (depending on the communicator size)
901   without data copy AFTER the matrix values have been set.
902 
903   Options Database Keys:
904 + -mat_type sbaijmumps - sets the matrix type to "sbaijmumps" during a call to MatSetFromOptions()
905 . -mat_mumps_sym <0,1,2> - 0 the matrix is unsymmetric, 1 symmetric positive definite, 2 symmetric
906 . -mat_mumps_icntl_4 <0,...,4> - print level
907 . -mat_mumps_icntl_6 <0,...,7> - matrix prescaling options (see MUMPS User's Guide)
908 . -mat_mumps_icntl_7 <0,...,7> - matrix orderings (see MUMPS User's Guide)
909 . -mat_mumps_icntl_9 <1,2> - A or A^T x=b to be solved: 1 denotes A, 2 denotes A^T
910 . -mat_mumps_icntl_10 <n> - maximum number of iterative refinements
911 . -mat_mumps_icntl_11 <n> - error analysis, a positive value returns statistics during -ksp_view
912 . -mat_mumps_icntl_12 <n> - efficiency control (see MUMPS User's Guide)
913 . -mat_mumps_icntl_13 <n> - efficiency control (see MUMPS User's Guide)
914 . -mat_mumps_icntl_14 <n> - efficiency control (see MUMPS User's Guide)
915 . -mat_mumps_icntl_15 <n> - efficiency control (see MUMPS User's Guide)
916 . -mat_mumps_cntl_1 <delta> - relative pivoting threshold
917 . -mat_mumps_cntl_2 <tol> - stopping criterion for refinement
918 - -mat_mumps_cntl_3 <adelta> - absolute pivoting threshold
919 
920   Level: beginner
921 
922 .seealso: MATAIJMUMPS
923 M*/
924 
925