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