xref: /petsc/src/mat/impls/aij/mpi/mumps/mumps.c (revision 28b08bd3b5f59ffcd1196bf53847454d207c6e8e)
1 /*$Id: mumps.c,v 1.10 2001/08/15 15:56:50 bsmith Exp $*/
2 /*
3     Provides an interface to the MUMPS_4.2_beta sparse solver
4 */
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 RINFOG(I) rinfog[(I)-1]
25 
26 typedef struct {
27 #if defined(PETSC_USE_COMPLEX)
28   ZMUMPS_STRUC_C id;
29 #else
30   DMUMPS_STRUC_C id;
31 #endif
32   MatStructure   matstruc;
33   int            myid,size,*irn,*jcn,sym;
34   PetscScalar    *val;
35   MPI_Comm       comm_mumps;
36 
37   MatType        basetype;
38   PetscTruth     isAIJ,CleanUpMUMPS;
39   int (*MatDuplicate)(Mat,MatDuplicateOption,Mat*);
40   int (*MatView)(Mat,PetscViewer);
41   int (*MatAssemblyEnd)(Mat,MatAssemblyType);
42   int (*MatLUFactorSymbolic)(Mat,IS,IS,MatFactorInfo*,Mat*);
43   int (*MatCholeskyFactorSymbolic)(Mat,IS,MatFactorInfo*,Mat*);
44   int (*MatDestroy)(Mat);
45 } Mat_MUMPS;
46 
47 EXTERN int MatDuplicate_AIJMUMPS(Mat,MatDuplicateOption,Mat*);
48 EXTERN int MatDuplicate_SBAIJMUMPS(Mat,MatDuplicateOption,Mat*);
49 
50 /* convert Petsc mpiaij matrix to triples: row[nz], col[nz], val[nz] */
51 /*
52   input:
53     A       - matrix in mpiaij format
54     shift   - 0: C style output triple; 1: Fortran style output triple.
55     valOnly - FALSE: spaces are allocated and values are set for the triple
56               TRUE:  only the values in v array are updated
57   output:
58     nnz     - dim of r, c, and v (number of local nonzero entries of A)
59     r, c, v - row and col index, matrix values (matrix triples)
60  */
61 int MatConvertToTriples(Mat A,int shift,PetscTruth valOnly,int *nnz,int **r, int **c, PetscScalar **v) {
62   int         *ai, *aj, *bi, *bj, rstart,nz, *garray;
63   int         ierr,i,j,jj,jB,irow,m=A->m,*ajj,*bjj,countA,countB,colA_start,jcol;
64   int         *row,*col;
65   PetscScalar *av, *bv,*val;
66   Mat_MUMPS   *mumps=(Mat_MUMPS*)A->spptr;
67 
68   PetscFunctionBegin;
69 
70   if (mumps->isAIJ){
71     Mat_MPIAIJ    *mat =  (Mat_MPIAIJ*)A->data;
72     Mat_SeqAIJ    *aa=(Mat_SeqAIJ*)(mat->A)->data;
73     Mat_SeqAIJ    *bb=(Mat_SeqAIJ*)(mat->B)->data;
74     nz = aa->nz + bb->nz;
75     ai=aa->i; aj=aa->j; bi=bb->i; bj=bb->j; rstart= mat->rstart;
76     garray = mat->garray;
77     av=aa->a; bv=bb->a;
78 
79   } else {
80     Mat_MPISBAIJ  *mat =  (Mat_MPISBAIJ*)A->data;
81     Mat_SeqSBAIJ  *aa=(Mat_SeqSBAIJ*)(mat->A)->data;
82     Mat_SeqBAIJ    *bb=(Mat_SeqBAIJ*)(mat->B)->data;
83     if (mat->bs > 1) SETERRQ1(PETSC_ERR_SUP," bs=%d is not supported yet\n", mat->bs);
84     nz = aa->s_nz + bb->nz;
85     ai=aa->i; aj=aa->j; bi=bb->i; bj=bb->j; rstart= mat->rstart;
86     garray = mat->garray;
87     av=aa->a; bv=bb->a;
88   }
89 
90   if (!valOnly){
91     ierr = PetscMalloc(nz*sizeof(int),&row);CHKERRQ(ierr);
92     ierr = PetscMalloc(nz*sizeof(int),&col);CHKERRQ(ierr);
93     ierr = PetscMalloc(nz*sizeof(PetscScalar),&val);CHKERRQ(ierr);
94     *r = row; *c = col; *v = val;
95   } else {
96     row = *r; col = *c; val = *v;
97   }
98   *nnz = nz;
99 
100   jj = 0; jB = 0; irow = rstart;
101   for ( i=0; i<m; i++ ) {
102     ajj = aj + ai[i];                 /* ptr to the beginning of this row */
103     countA = ai[i+1] - ai[i];
104     countB = bi[i+1] - bi[i];
105     bjj = bj + bi[i];
106 
107     /* get jB, the starting local col index for the 2nd B-part */
108     colA_start = rstart + ajj[0]; /* the smallest col index for A */
109     for (j=0; j<countB; j++){
110       jcol = garray[bjj[j]];
111       if (jcol > colA_start) { jB = j; break; }
112       if (j==countB-1) jB = countB;
113     }
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       val[jj++] = *bv++;
123     }
124     /* A-part */
125     for (j=0; j<countA; j++){
126       if (!valOnly){
127         row[jj] = irow + shift; col[jj] = rstart + ajj[j] + shift;
128       }
129       val[jj++] = *av++;
130     }
131     /* B-part, larger col index */
132     for (j=jB; j<countB; j++){
133       if (!valOnly){
134         row[jj] = irow + shift; col[jj] = garray[bjj[j]] + shift;
135       }
136       val[jj++] = *bv++;
137     }
138     irow++;
139   }
140 
141   PetscFunctionReturn(0);
142 }
143 
144 EXTERN_C_BEGIN
145 #undef __FUNCT__
146 #define __FUNCT__ "MatConvert_MUMPS_Base"
147 int MatConvert_MUMPS_Base(Mat A,MatType type,Mat *newmat) {
148   /* This routine is only called to convert an unfactored PETSc-MUMPS matrix */
149   /* to its base PETSc type, so we will ignore 'MatType type'. */
150   int       ierr;
151   Mat       B=*newmat;
152   Mat_MUMPS *mumps=(Mat_MUMPS*)A->spptr;
153 
154   PetscFunctionBegin;
155   if (B != A) {
156     ierr = MatDuplicate(A,MAT_COPY_VALUES,&B);CHKERRQ(ierr);
157   }
158   B->ops->duplicate              = mumps->MatDuplicate;
159   B->ops->view                   = mumps->MatView;
160   B->ops->assemblyend            = mumps->MatAssemblyEnd;
161   B->ops->lufactorsymbolic       = mumps->MatLUFactorSymbolic;
162   B->ops->choleskyfactorsymbolic = mumps->MatCholeskyFactorSymbolic;
163   B->ops->destroy                = mumps->MatDestroy;
164   ierr = PetscObjectChangeTypeName((PetscObject)B,mumps->basetype);CHKERRQ(ierr);
165   ierr = PetscFree(mumps);CHKERRQ(ierr);
166   *newmat = B;
167   PetscFunctionReturn(0);
168 }
169 EXTERN_C_END
170 
171 #undef __FUNCT__
172 #define __FUNCT__ "MatDestroy_AIJMUMPS"
173 int MatDestroy_AIJMUMPS(Mat A) {
174   Mat_MUMPS *lu=(Mat_MUMPS*)A->spptr;
175   int       ierr,size=lu->size;
176 
177   PetscFunctionBegin;
178   if (lu->CleanUpMUMPS) {
179     /* Terminate instance, deallocate memories */
180     lu->id.job=JOB_END;
181 #if defined(PETSC_USE_COMPLEX)
182     zmumps_c(&lu->id);
183 #else
184     dmumps_c(&lu->id);
185 #endif
186     if (lu->irn) {
187       ierr = PetscFree(lu->irn);CHKERRQ(ierr);
188     }
189     if (lu->jcn) {
190       ierr = PetscFree(lu->jcn);CHKERRQ(ierr);
191     }
192     if (size>1 && lu->val) {
193       ierr = PetscFree(lu->val);CHKERRQ(ierr);
194     }
195     ierr = MPI_Comm_free(&(lu->comm_mumps));CHKERRQ(ierr);
196   }
197   ierr = MatConvert_MUMPS_Base(A,lu->basetype,&A);CHKERRQ(ierr);
198   ierr = (*A->ops->destroy)(A);CHKERRQ(ierr);
199   PetscFunctionReturn(0);
200 }
201 
202 #undef __FUNCT__
203 #define __FUNCT__ "MatFactorInfo_MUMPS"
204 int MatFactorInfo_MUMPS(Mat A,PetscViewer viewer) {
205   Mat_MUMPS *lu=(Mat_MUMPS*)A->spptr;
206   int       ierr;
207 
208   PetscFunctionBegin;
209   ierr = PetscViewerASCIIPrintf(viewer,"MUMPS run parameters:\n");CHKERRQ(ierr);
210   ierr = PetscViewerASCIIPrintf(viewer,"  SYM (matrix type):                  %d \n",lu->id.sym);CHKERRQ(ierr);
211   ierr = PetscViewerASCIIPrintf(viewer,"  PAR (host participation):           %d \n",lu->id.par);CHKERRQ(ierr);
212   ierr = PetscViewerASCIIPrintf(viewer,"  ICNTL(4) (level of printing):       %d \n",lu->id.ICNTL(4));CHKERRQ(ierr);
213   ierr = PetscViewerASCIIPrintf(viewer,"  ICNTL(5) (input mat struct):        %d \n",lu->id.ICNTL(5));CHKERRQ(ierr);
214   ierr = PetscViewerASCIIPrintf(viewer,"  ICNTL(6) (matrix prescaling):       %d \n",lu->id.ICNTL(6));CHKERRQ(ierr);
215   ierr = PetscViewerASCIIPrintf(viewer,"  ICNTL(7) (matrix ordering):         %d \n",lu->id.ICNTL(7));CHKERRQ(ierr);
216   ierr = PetscViewerASCIIPrintf(viewer,"  ICNTL(9) (A/A^T x=b is solved):     %d \n",lu->id.ICNTL(9));CHKERRQ(ierr);
217   ierr = PetscViewerASCIIPrintf(viewer,"  ICNTL(10) (max num of refinements): %d \n",lu->id.ICNTL(10));CHKERRQ(ierr);
218   ierr = PetscViewerASCIIPrintf(viewer,"  ICNTL(11) (error analysis):         %d \n",lu->id.ICNTL(11));CHKERRQ(ierr);
219   if (lu->myid == 0 && lu->id.ICNTL(11)>0) {
220     ierr = PetscPrintf(PETSC_COMM_SELF,"        RINFOG(4) (inf norm of input mat):        %g\n",lu->id.RINFOG(4));CHKERRQ(ierr);
221     ierr = PetscPrintf(PETSC_COMM_SELF,"        RINFOG(5) (inf norm of solution):         %g\n",lu->id.RINFOG(5));CHKERRQ(ierr);
222     ierr = PetscPrintf(PETSC_COMM_SELF,"        RINFOG(6) (inf norm of residual):         %g\n",lu->id.RINFOG(6));CHKERRQ(ierr);
223     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);
224     ierr = PetscPrintf(PETSC_COMM_SELF,"        RINFOG(9) (error estimate):               %g \n",lu->id.RINFOG(9));CHKERRQ(ierr);
225     ierr = PetscPrintf(PETSC_COMM_SELF,"        RINFOG(10),RINFOG(11)(condition numbers): %g, %g\n",lu->id.RINFOG(10),lu->id.RINFOG(11));CHKERRQ(ierr);
226 
227   }
228   ierr = PetscViewerASCIIPrintf(viewer,"  ICNTL(12) (efficiency control):     %d \n",lu->id.ICNTL(12));CHKERRQ(ierr);
229   ierr = PetscViewerASCIIPrintf(viewer,"  ICNTL(13) (efficiency control):     %d \n",lu->id.ICNTL(13));CHKERRQ(ierr);
230   ierr = PetscViewerASCIIPrintf(viewer,"  ICNTL(14) (efficiency control):     %d \n",lu->id.ICNTL(14));CHKERRQ(ierr);
231   ierr = PetscViewerASCIIPrintf(viewer,"  ICNTL(15) (efficiency control):     %d \n",lu->id.ICNTL(15));CHKERRQ(ierr);
232   ierr = PetscViewerASCIIPrintf(viewer,"  ICNTL(18) (input mat struct):       %d \n",lu->id.ICNTL(18));CHKERRQ(ierr);
233 
234   ierr = PetscViewerASCIIPrintf(viewer,"  CNTL(1) (relative pivoting threshold):      %g \n",lu->id.CNTL(1));CHKERRQ(ierr);
235   ierr = PetscViewerASCIIPrintf(viewer,"  CNTL(2) (stopping criterion of refinement): %g \n",lu->id.CNTL(2));CHKERRQ(ierr);
236   ierr = PetscViewerASCIIPrintf(viewer,"  CNTL(3) (absolute pivoting threshold):      %g \n",lu->id.CNTL(3));CHKERRQ(ierr);
237   PetscFunctionReturn(0);
238 }
239 
240 #undef __FUNCT__
241 #define __FUNCT__ "MatView_AIJMUMPS"
242 int MatView_AIJMUMPS(Mat A,PetscViewer viewer) {
243   int               ierr;
244   PetscTruth        isascii;
245   PetscViewerFormat format;
246   Mat_MUMPS         *mumps=(Mat_MUMPS*)(A->spptr);
247 
248   PetscFunctionBegin;
249   ierr = (*mumps->MatView)(A,viewer);CHKERRQ(ierr);
250 
251   ierr = PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_ASCII,&isascii);CHKERRQ(ierr);
252   if (isascii) {
253     ierr = PetscViewerGetFormat(viewer,&format);CHKERRQ(ierr);
254     if (format == PETSC_VIEWER_ASCII_FACTOR_INFO) {
255       ierr = MatFactorInfo_MUMPS(A,viewer);CHKERRQ(ierr);
256     }
257   }
258   PetscFunctionReturn(0);
259 }
260 
261 #undef __FUNCT__
262 #define __FUNCT__ "MatSolve_AIJMUMPS"
263 int MatSolve_AIJMUMPS(Mat A,Vec b,Vec x) {
264   Mat_MUMPS   *lu=(Mat_MUMPS*)A->spptr;
265   PetscScalar *array;
266   Vec         x_seq;
267   IS          iden;
268   VecScatter  scat;
269   int         ierr;
270 
271   PetscFunctionBegin;
272   if (lu->size > 1){
273     if (!lu->myid){
274       ierr = VecCreateSeq(PETSC_COMM_SELF,A->N,&x_seq);CHKERRQ(ierr);
275       ierr = ISCreateStride(PETSC_COMM_SELF,A->N,0,1,&iden);CHKERRQ(ierr);
276     } else {
277       ierr = VecCreateSeq(PETSC_COMM_SELF,0,&x_seq);CHKERRQ(ierr);
278       ierr = ISCreateStride(PETSC_COMM_SELF,0,0,1,&iden);CHKERRQ(ierr);
279     }
280     ierr = VecScatterCreate(b,iden,x_seq,iden,&scat);CHKERRQ(ierr);
281     ierr = ISDestroy(iden);CHKERRQ(ierr);
282 
283     ierr = VecScatterBegin(b,x_seq,INSERT_VALUES,SCATTER_FORWARD,scat);CHKERRQ(ierr);
284     ierr = VecScatterEnd(b,x_seq,INSERT_VALUES,SCATTER_FORWARD,scat);CHKERRQ(ierr);
285     if (!lu->myid) {ierr = VecGetArray(x_seq,&array);CHKERRQ(ierr);}
286   } else {  /* size == 1 */
287     ierr = VecCopy(b,x);CHKERRQ(ierr);
288     ierr = VecGetArray(x,&array);CHKERRQ(ierr);
289   }
290   if (!lu->myid) { /* define rhs on the host */
291 #if defined(PETSC_USE_COMPLEX)
292     lu->id.rhs = (mumps_double_complex*)array;
293 #else
294     lu->id.rhs = array;
295 #endif
296   }
297 
298   /* solve phase */
299   lu->id.job=3;
300 #if defined(PETSC_USE_COMPLEX)
301   zmumps_c(&lu->id);
302 #else
303   dmumps_c(&lu->id);
304 #endif
305   if (lu->id.INFOG(1) < 0) {
306     SETERRQ1(1,"Error reported by MUMPS in solve phase: INFOG(1)=%d\n",lu->id.INFOG(1));
307   }
308 
309   /* convert mumps solution x_seq to petsc mpi x */
310   if (lu->size > 1) {
311     if (!lu->myid){
312       ierr = VecRestoreArray(x_seq,&array);CHKERRQ(ierr);
313     }
314     ierr = VecScatterBegin(x_seq,x,INSERT_VALUES,SCATTER_REVERSE,scat);CHKERRQ(ierr);
315     ierr = VecScatterEnd(x_seq,x,INSERT_VALUES,SCATTER_REVERSE,scat);CHKERRQ(ierr);
316     ierr = VecScatterDestroy(scat);CHKERRQ(ierr);
317     ierr = VecDestroy(x_seq);CHKERRQ(ierr);
318   } else {
319     ierr = VecRestoreArray(x,&array);CHKERRQ(ierr);
320   }
321 
322   PetscFunctionReturn(0);
323 }
324 
325 #undef __FUNCT__
326 #define __FUNCT__ "MatFactorNumeric_MPIAIJMUMPS"
327 int MatFactorNumeric_AIJMUMPS(Mat A,Mat *F) {
328   Mat_MUMPS  *lu =(Mat_MUMPS*)(*F)->spptr;
329   Mat_MUMPS  *lua=(Mat_MUMPS*)(A)->spptr;
330   int        rnz,nnz,ierr,nz,i,M=A->M,*ai,*aj,icntl;
331   PetscTruth valOnly,flg;
332 
333   PetscFunctionBegin;
334   if (lu->matstruc == DIFFERENT_NONZERO_PATTERN){
335     (*F)->ops->solve    = MatSolve_AIJMUMPS;
336 
337     /* Initialize a MUMPS instance */
338     ierr = MPI_Comm_rank(A->comm, &lu->myid);
339     ierr = MPI_Comm_size(A->comm,&lu->size);CHKERRQ(ierr);
340     lu->id.job = JOB_INIT;
341     ierr = MPI_Comm_dup(A->comm,&(lu->comm_mumps));CHKERRQ(ierr);
342     lu->id.comm_fortran = lu->comm_mumps;
343 
344     /* Set mumps options */
345     ierr = PetscOptionsBegin(A->comm,A->prefix,"MUMPS Options","Mat");CHKERRQ(ierr);
346     lu->id.par=1;  /* host participates factorizaton and solve */
347     lu->id.sym=lu->sym;
348     if (lu->sym == 2){
349       ierr = PetscOptionsInt("-mat_mumps_sym","SYM: (1,2)","None",lu->id.sym,&icntl,&flg);CHKERRQ(ierr);
350       if (flg && icntl == 1) lu->id.sym=icntl;  /* matrix is spd */
351     }
352 #if defined(PETSC_USE_COMPLEX)
353   zmumps_c(&lu->id);
354 #else
355   dmumps_c(&lu->id);
356 #endif
357 
358     if (lu->size == 1){
359       lu->id.ICNTL(18) = 0;   /* centralized assembled matrix input */
360     } else {
361       lu->id.ICNTL(18) = 3;   /* distributed assembled matrix input */
362     }
363 
364     icntl=-1;
365     ierr = PetscOptionsInt("-mat_mumps_icntl_4","ICNTL(4): level of printing (0 to 4)","None",lu->id.ICNTL(4),&icntl,&flg);CHKERRQ(ierr);
366     if (flg && icntl > 0) {
367       lu->id.ICNTL(4)=icntl; /* and use mumps default icntl(i), i=1,2,3 */
368     } else { /* no output */
369       lu->id.ICNTL(1) = 0;  /* error message, default= 6 */
370       lu->id.ICNTL(2) = -1; /* output stream for diagnostic printing, statistics, and warning. default=0 */
371       lu->id.ICNTL(3) = -1; /* output stream for global information, default=6 */
372       lu->id.ICNTL(4) = 0;  /* level of printing, 0,1,2,3,4, default=2 */
373     }
374     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);
375     icntl=-1;
376     ierr = PetscOptionsInt("-mat_mumps_icntl_7","ICNTL(7): matrix ordering (0 to 7)","None",lu->id.ICNTL(7),&icntl,&flg);CHKERRQ(ierr);
377     if (flg) {
378       if (icntl== 1){
379         SETERRQ(PETSC_ERR_SUP,"pivot order be set by the user in PERM_IN -- not supported by the PETSc/MUMPS interface\n");
380       } else {
381         lu->id.ICNTL(7) = icntl;
382       }
383     }
384     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);
385     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);
386     ierr = PetscOptionsInt("-mat_mumps_icntl_11","ICNTL(11): error analysis, a positive value returns statistics (by -sles_view)","None",lu->id.ICNTL(11),&lu->id.ICNTL(11),PETSC_NULL);CHKERRQ(ierr);
387     ierr = PetscOptionsInt("-mat_mumps_icntl_12","ICNTL(12): efficiency control","None",lu->id.ICNTL(12),&lu->id.ICNTL(12),PETSC_NULL);CHKERRQ(ierr);
388     ierr = PetscOptionsInt("-mat_mumps_icntl_13","ICNTL(13): efficiency control","None",lu->id.ICNTL(13),&lu->id.ICNTL(13),PETSC_NULL);CHKERRQ(ierr);
389     ierr = PetscOptionsInt("-mat_mumps_icntl_14","ICNTL(14): efficiency control","None",lu->id.ICNTL(14),&lu->id.ICNTL(14),PETSC_NULL);CHKERRQ(ierr);
390     ierr = PetscOptionsInt("-mat_mumps_icntl_15","ICNTL(15): efficiency control","None",lu->id.ICNTL(15),&lu->id.ICNTL(15),PETSC_NULL);CHKERRQ(ierr);
391 
392     /*
393     ierr = PetscOptionsInt("-mat_mumps_icntl_16","ICNTL(16): 1: rank detection; 2: rank detection and nullspace","None",lu->id.ICNTL(16),&icntl,&flg);CHKERRQ(ierr);
394     if (flg){
395       if (icntl >-1 && icntl <3 ){
396         if (lu->myid==0) lu->id.ICNTL(16) = icntl;
397       } else {
398         SETERRQ1(PETSC_ERR_SUP,"ICNTL(16)=%d -- not supported\n",icntl);
399       }
400     }
401     */
402 
403     ierr = PetscOptionsReal("-mat_mumps_cntl_1","CNTL(1): relative pivoting threshold","None",lu->id.CNTL(1),&lu->id.CNTL(1),PETSC_NULL);CHKERRQ(ierr);
404     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);
405     ierr = PetscOptionsReal("-mat_mumps_cntl_3","CNTL(3): absolute pivoting threshold","None",lu->id.CNTL(3),&lu->id.CNTL(3),PETSC_NULL);CHKERRQ(ierr);
406     PetscOptionsEnd();
407   }
408 
409   /* define matrix A */
410   switch (lu->id.ICNTL(18)){
411   case 0:  /* centralized assembled matrix input (size=1) */
412     if (!lu->myid) {
413       if (lua->isAIJ){
414         Mat_SeqAIJ   *aa = (Mat_SeqAIJ*)A->data;
415         nz               = aa->nz;
416         ai = aa->i; aj = aa->j; lu->val = aa->a;
417       } else {
418         Mat_SeqSBAIJ *aa = (Mat_SeqSBAIJ*)A->data;
419         nz                  =  aa->s_nz;
420         ai = aa->i; aj = aa->j; lu->val = aa->a;
421       }
422       if (lu->matstruc == DIFFERENT_NONZERO_PATTERN){ /* first numeric factorization, get irn and jcn */
423         ierr = PetscMalloc(nz*sizeof(int),&lu->irn);CHKERRQ(ierr);
424         ierr = PetscMalloc(nz*sizeof(int),&lu->jcn);CHKERRQ(ierr);
425         nz = 0;
426         for (i=0; i<M; i++){
427           rnz = ai[i+1] - ai[i];
428           while (rnz--) {  /* Fortran row/col index! */
429             lu->irn[nz] = i+1; lu->jcn[nz] = (*aj)+1; aj++; nz++;
430           }
431         }
432       }
433     }
434     break;
435   case 3:  /* distributed assembled matrix input (size>1) */
436     if (lu->matstruc == DIFFERENT_NONZERO_PATTERN){
437       valOnly = PETSC_FALSE;
438     } else {
439       valOnly = PETSC_TRUE; /* only update mat values, not row and col index */
440     }
441     ierr = MatConvertToTriples(A,1,valOnly, &nnz, &lu->irn, &lu->jcn, &lu->val);CHKERRQ(ierr);
442     break;
443   default: SETERRQ(PETSC_ERR_SUP,"Matrix input format is not supported by MUMPS.");
444   }
445 
446   /* analysis phase */
447   if (lu->matstruc == DIFFERENT_NONZERO_PATTERN){
448      lu->id.n = M;
449     switch (lu->id.ICNTL(18)){
450     case 0:  /* centralized assembled matrix input */
451       if (!lu->myid) {
452         lu->id.nz =nz; lu->id.irn=lu->irn; lu->id.jcn=lu->jcn;
453         if (lu->id.ICNTL(6)>1){
454 #if defined(PETSC_USE_COMPLEX)
455           lu->id.a = (mumps_double_complex*)lu->val;
456 #else
457           lu->id.a = lu->val;
458 #endif
459         }
460       }
461       break;
462     case 3:  /* distributed assembled matrix input (size>1) */
463       lu->id.nz_loc = nnz;
464       lu->id.irn_loc=lu->irn; lu->id.jcn_loc=lu->jcn;
465       if (lu->id.ICNTL(6)>1) {
466 #if defined(PETSC_USE_COMPLEX)
467         lu->id.a_loc = (mumps_double_complex*)lu->val;
468 #else
469         lu->id.a_loc = lu->val;
470 #endif
471       }
472       break;
473     }
474     lu->id.job=1;
475 #if defined(PETSC_USE_COMPLEX)
476   zmumps_c(&lu->id);
477 #else
478   dmumps_c(&lu->id);
479 #endif
480     if (lu->id.INFOG(1) < 0) {
481       SETERRQ1(1,"Error reported by MUMPS in analysis phase: INFOG(1)=%d\n",lu->id.INFOG(1));
482     }
483   }
484 
485   /* numerical factorization phase */
486   if(lu->id.ICNTL(18) == 0) {
487     if (lu->myid == 0) {
488 #if defined(PETSC_USE_COMPLEX)
489       lu->id.a = (mumps_double_complex*)lu->val;
490 #else
491       lu->id.a = lu->val;
492 #endif
493     }
494   } else {
495 #if defined(PETSC_USE_COMPLEX)
496     lu->id.a_loc = (mumps_double_complex*)lu->val;
497 #else
498     lu->id.a_loc = lu->val;
499 #endif
500   }
501   lu->id.job=2;
502 #if defined(PETSC_USE_COMPLEX)
503   zmumps_c(&lu->id);
504 #else
505   dmumps_c(&lu->id);
506 #endif
507   if (lu->id.INFOG(1) < 0) {
508     SETERRQ1(1,"1, Error reported by MUMPS in numerical factorization phase: INFOG(1)=%d\n",lu->id.INFOG(1));
509   }
510 
511   if (lu->myid==0 && lu->id.ICNTL(16) > 0){
512     SETERRQ1(1,"  lu->id.ICNTL(16):=%d\n",lu->id.INFOG(16));
513   }
514 
515   (*F)->assembled  = PETSC_TRUE;
516   lu->matstruc     = SAME_NONZERO_PATTERN;
517   lu->CleanUpMUMPS = PETSC_TRUE;
518   PetscFunctionReturn(0);
519 }
520 
521 /* Note the Petsc r and c permutations are ignored */
522 #undef __FUNCT__
523 #define __FUNCT__ "MatLUFactorSymbolic_AIJMUMPS"
524 int MatLUFactorSymbolic_AIJMUMPS(Mat A,IS r,IS c,MatFactorInfo *info,Mat *F) {
525   Mat       B;
526   Mat_MUMPS *lu;
527   int       ierr;
528 
529   PetscFunctionBegin;
530 
531   /* Create the factorization matrix */
532   ierr = MatCreate(A->comm,A->m,A->n,A->M,A->N,&B);CHKERRQ(ierr);
533   ierr = MatSetType(B,MATAIJMUMPS);CHKERRQ(ierr);
534   ierr = MatSeqAIJSetPreallocation(B,0,PETSC_NULL);CHKERRQ(ierr);
535   ierr = MatMPIAIJSetPreallocation(B,0,PETSC_NULL,0,PETSC_NULL);CHKERRQ(ierr);
536 
537   B->ops->lufactornumeric = MatFactorNumeric_AIJMUMPS;
538   B->factor               = FACTOR_LU;
539   lu                      = (Mat_MUMPS*)B->spptr;
540   lu->sym                 = 0;
541   lu->matstruc            = DIFFERENT_NONZERO_PATTERN;
542 
543   *F = B;
544   PetscFunctionReturn(0);
545 }
546 
547 /* Note the Petsc r permutation is ignored */
548 #undef __FUNCT__
549 #define __FUNCT__ "MatCholeskyFactorSymbolic_SBAIJMUMPS"
550 int MatCholeskyFactorSymbolic_SBAIJMUMPS(Mat A,IS r,MatFactorInfo *info,Mat *F) {
551   Mat       B;
552   Mat_MUMPS *lu;
553   int       ierr;
554 
555   PetscFunctionBegin;
556 
557   /* Create the factorization matrix */
558   ierr = MatCreate(A->comm,A->m,A->n,A->M,A->N,&B);CHKERRQ(ierr);
559   ierr = MatSetType(B,MATAIJMUMPS);CHKERRQ(ierr);
560   ierr = MatSeqAIJSetPreallocation(B,0,PETSC_NULL);CHKERRQ(ierr);
561   ierr = MatMPIAIJSetPreallocation(B,0,PETSC_NULL,0,PETSC_NULL);CHKERRQ(ierr);
562 
563   B->ops->choleskyfactornumeric = MatFactorNumeric_AIJMUMPS;
564   B->factor                     = FACTOR_CHOLESKY;
565   lu                            = (Mat_MUMPS*)B->spptr;
566   lu->sym                       = 2;
567   lu->matstruc                  = DIFFERENT_NONZERO_PATTERN;
568 
569   *F = B;
570   PetscFunctionReturn(0);
571 }
572 
573 #undef __FUNCT__
574 #define __FUNCT__ "MatAssemblyEnd_AIJMUMPS"
575 int MatAssemblyEnd_AIJMUMPS(Mat A,MatAssemblyType mode) {
576   int       ierr;
577   Mat_MUMPS *mumps=(Mat_MUMPS*)A->spptr;
578 
579   PetscFunctionBegin;
580   ierr = (*mumps->MatAssemblyEnd)(A,mode);CHKERRQ(ierr);
581 
582   mumps->MatLUFactorSymbolic       = A->ops->lufactorsymbolic;
583   mumps->MatCholeskyFactorSymbolic = A->ops->choleskyfactorsymbolic;
584   A->ops->lufactorsymbolic         = MatLUFactorSymbolic_AIJMUMPS;
585   PetscFunctionReturn(0);
586 }
587 
588 EXTERN_C_BEGIN
589 #undef __FUNCT__
590 #define __FUNCT__ "MatConvert_AIJ_AIJMUMPS"
591 int MatConvert_AIJ_AIJMUMPS(Mat A,MatType newtype,Mat *newmat) {
592   int       ierr,size;
593   MPI_Comm  comm;
594   Mat       B=*newmat;
595   Mat_MUMPS *mumps;
596 
597   PetscFunctionBegin;
598   if (B != A) {
599     ierr = MatDuplicate(A,MAT_COPY_VALUES,&B);CHKERRQ(ierr);
600   }
601 
602   ierr = PetscObjectGetComm((PetscObject)A,&comm);CHKERRQ(ierr);
603   ierr = PetscNew(Mat_MUMPS,&mumps);CHKERRQ(ierr);
604 
605   mumps->MatDuplicate              = A->ops->duplicate;
606   mumps->MatView                   = A->ops->view;
607   mumps->MatAssemblyEnd            = A->ops->assemblyend;
608   mumps->MatLUFactorSymbolic       = A->ops->lufactorsymbolic;
609   mumps->MatCholeskyFactorSymbolic = A->ops->choleskyfactorsymbolic;
610   mumps->MatDestroy                = A->ops->destroy;
611   mumps->CleanUpMUMPS              = PETSC_FALSE;
612   mumps->isAIJ                     = PETSC_TRUE;
613 
614   B->spptr                         = (void *)mumps;
615   B->ops->duplicate                = MatDuplicate_AIJMUMPS;
616   B->ops->view                     = MatView_AIJMUMPS;
617   B->ops->assemblyend              = MatAssemblyEnd_AIJMUMPS;
618   B->ops->lufactorsymbolic         = MatLUFactorSymbolic_AIJMUMPS;
619   B->ops->destroy                  = MatDestroy_AIJMUMPS;
620 
621   ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr);CHKERRQ(ierr);
622   if (size == 1) {
623     ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatConvert_seqaij_aijmumps_C",
624                                              "MatConvert_AIJ_AIJMUMPS",MatConvert_AIJ_AIJMUMPS);CHKERRQ(ierr);
625     ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatConvert_aijmumps_seqaij_C",
626                                              "MatConvert_MUMPS_Base",MatConvert_MUMPS_Base);CHKERRQ(ierr);
627   } else {
628     ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatConvert_mpiaij_aijmumps_C",
629                                              "MatConvert_AIJ_AIJMUMPS",MatConvert_AIJ_AIJMUMPS);CHKERRQ(ierr);
630     ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatConvert_aijmumps_mpiaij_C",
631                                              "MatConvert_MUMPS_Base",MatConvert_MUMPS_Base);CHKERRQ(ierr);
632   }
633 
634   PetscLogInfo(0,"Using MUMPS for LU factorization and solves.");
635   ierr = PetscObjectChangeTypeName((PetscObject)B,newtype);CHKERRQ(ierr);
636   *newmat = B;
637   PetscFunctionReturn(0);
638 }
639 EXTERN_C_END
640 
641 #undef __FUNCT__
642 #define __FUNCT__ "MatDuplicate_AIJMUMPS"
643 int MatDuplicate_AIJMUMPS(Mat A, MatDuplicateOption op, Mat *M) {
644   int ierr;
645   PetscFunctionBegin;
646   ierr = (*A->ops->duplicate)(A,op,M);CHKERRQ(ierr);
647   ierr = MatConvert_AIJ_AIJMUMPS(*M,MATAIJMUMPS,M);CHKERRQ(ierr);
648   PetscFunctionReturn(0);
649 }
650 
651 /*MC
652   MATAIJMUMPS - a matrix type providing direct solvers (LU) for distributed
653   and sequential matrices via the external package MUMPS.
654 
655   If MUMPS is installed (see the manual for instructions
656   on how to declare the existence of external packages),
657   a matrix type can be constructed which invokes MUMPS solvers.
658   After calling MatCreate(...,A), simply call MatSetType(A,MATAIJMUMPS).
659   This matrix type is only supported for double precision real.
660 
661   If created with a single process communicator, this matrix type inherits from MATSEQAIJ.
662   Otherwise, this matrix type inherits from MATMPIAIJ.  Hence for single process communicators,
663   MatSeqAIJSetPreallocation is supported, and similarly MatMPIAIJSetPreallocation is supported
664   for communicators controlling multiple processes.  It is recommended that you call both of
665   the above preallocation routines for simplicity.  One can also call MatConvert for an inplace
666   conversion to or from the MATSEQAIJ or MATMPIAIJ type (depending on the communicator size)
667   without data copy.
668 
669   Options Database Keys:
670 + -mat_type aijmumps
671 . -mat_mumps_sym <0,1,2> - 0 the matrix is unsymmetric, 1 symmetric positive definite, 2 symmetric
672 . -mat_mumps_icntl_4 <0,1,2,3,4> - print level
673 . -mat_mumps_icntl_6 <0,...,7> - matrix prescaling options (see MUMPS User's Guide)
674 . -mat_mumps_icntl_7 <0,...,7> - matrix orderings (see MUMPS User's Guide)
675 . -mat_mumps_icntl_9 <1,2> - A or A^T x=b to be solved: 1 denotes A, 2 denotes A^T
676 . -mat_mumps_icntl_10 <n> - maximum number of iterative refinements
677 . -mat_mumps_icntl_11 <n> - error analysis, a positive value returns statistics during -sles_view
678 . -mat_mumps_icntl_12 <n> - efficiency control (see MUMPS User's Guide)
679 . -mat_mumps_icntl_13 <n> - efficiency control (see MUMPS User's Guide)
680 . -mat_mumps_icntl_14 <n> - efficiency control (see MUMPS User's Guide)
681 . -mat_mumps_icntl_15 <n> - efficiency control (see MUMPS User's Guide)
682 . -mat_mumps_cntl_1 <delta> - relative pivoting threshold
683 . -mat_mumps_cntl_2 <tol> - stopping criterion for refinement
684 - -mat_mumps_cntl_3 <adelta> - absolute pivoting threshold
685 
686   Level: beginner
687 
688 .seealso: MATSBAIJMUMPS
689 M*/
690 
691 EXTERN_C_BEGIN
692 #undef __FUNCT__
693 #define __FUNCT__ "MatCreate_AIJMUMPS"
694 int MatCreate_AIJMUMPS(Mat A) {
695   int           ierr,size;
696   MPI_Comm      comm;
697 
698   PetscFunctionBegin;
699   /* Change type name before calling MatSetType to force proper construction of SeqAIJ or MPIAIJ */
700   /*   and AIJMUMPS types */
701   ierr = PetscObjectChangeTypeName((PetscObject)A,MATAIJMUMPS);CHKERRQ(ierr);
702   ierr = PetscObjectGetComm((PetscObject)A,&comm);CHKERRQ(ierr);
703   ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr);CHKERRQ(ierr);
704   if (size == 1) {
705     ierr = MatSetType(A,MATSEQAIJ);CHKERRQ(ierr);
706   } else {
707     ierr = MatSetType(A,MATMPIAIJ);CHKERRQ(ierr);
708   }
709   ierr = MatConvert_AIJ_AIJMUMPS(A,MATAIJMUMPS,&A);CHKERRQ(ierr);
710   PetscFunctionReturn(0);
711 }
712 EXTERN_C_END
713 
714 EXTERN_C_BEGIN
715 #undef __FUNCT__
716 #define __FUNCT__ "MatLoad_AIJMUMPS"
717 int MatLoad_AIJMUMPS(PetscViewer viewer,MatType type,Mat *A) {
718   int ierr,size,(*r)(PetscViewer,MatType,Mat*);
719   MPI_Comm comm;
720 
721   PetscFunctionBegin;
722   ierr = PetscObjectGetComm((PetscObject)viewer,&comm);CHKERRQ(ierr);
723   ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
724   if (size == 1) {
725     ierr = PetscFListFind(comm,MatLoadList,MATSEQAIJ,(void(**)(void))&r);CHKERRQ(ierr);
726   } else {
727     ierr = PetscFListFind(comm,MatLoadList,MATMPIAIJ,(void(**)(void))&r);CHKERRQ(ierr);
728   }
729   ierr = (*r)(viewer,type,A);CHKERRQ(ierr);
730   PetscFunctionReturn(0);
731 }
732 EXTERN_C_END
733 
734 #undef __FUNCT__
735 #define __FUNCT__ "MatAssemblyEnd_SBAIJMUMPS"
736 int MatAssemblyEnd_SBAIJMUMPS(Mat A,MatAssemblyType mode) {
737   int       ierr;
738   Mat_MUMPS *mumps=(Mat_MUMPS*)A->spptr;
739 
740   PetscFunctionBegin;
741   ierr = (*mumps->MatAssemblyEnd)(A,mode);CHKERRQ(ierr);
742   mumps->MatLUFactorSymbolic       = A->ops->lufactorsymbolic;
743   mumps->MatCholeskyFactorSymbolic = A->ops->choleskyfactorsymbolic;
744   A->ops->choleskyfactorsymbolic   = MatCholeskyFactorSymbolic_SBAIJMUMPS;
745   PetscFunctionReturn(0);
746 }
747 
748 EXTERN_C_BEGIN
749 #undef __FUNCT__
750 #define __FUNCT__ "MatConvert_SBAIJ_SBAIJMUMPS"
751 int MatConvert_SBAIJ_SBAIJMUMPS(Mat A,MatType newtype,Mat *newmat) {
752   int       ierr,size;
753   MPI_Comm  comm;
754   Mat       B=*newmat;
755   Mat_MUMPS *mumps;
756 
757   PetscFunctionBegin;
758   if (B != A) {
759     ierr = MatDuplicate(A,MAT_COPY_VALUES,&B);CHKERRQ(ierr);
760   }
761 
762   ierr = PetscObjectGetComm((PetscObject)A,&comm);CHKERRQ(ierr);
763   ierr = PetscNew(Mat_MUMPS,&mumps);CHKERRQ(ierr);
764 
765   mumps->MatDuplicate              = A->ops->duplicate;
766   mumps->MatView                   = A->ops->view;
767   mumps->MatAssemblyEnd            = A->ops->assemblyend;
768   mumps->MatLUFactorSymbolic       = A->ops->lufactorsymbolic;
769   mumps->MatCholeskyFactorSymbolic = A->ops->choleskyfactorsymbolic;
770   mumps->MatDestroy                = A->ops->destroy;
771   mumps->CleanUpMUMPS              = PETSC_FALSE;
772   mumps->isAIJ                     = PETSC_FALSE;
773 
774   B->spptr                         = (void *)mumps;
775   B->ops->duplicate                = MatDuplicate_SBAIJMUMPS;
776   B->ops->view                     = MatView_AIJMUMPS;
777   B->ops->assemblyend              = MatAssemblyEnd_SBAIJMUMPS;
778   B->ops->choleskyfactorsymbolic   = MatCholeskyFactorSymbolic_SBAIJMUMPS;
779   B->ops->destroy                  = MatDestroy_AIJMUMPS;
780 
781   ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr);CHKERRQ(ierr);
782   if (size == 1) {
783     ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatConvert_seqsbaij_sbaijmumps_C",
784                                              "MatConvert_SBAIJ_SBAIJMUMPS",MatConvert_SBAIJ_SBAIJMUMPS);CHKERRQ(ierr);
785     ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatConvert_sbaijmumps_seqsbaij_C",
786                                              "MatConvert_MUMPS_Base",MatConvert_MUMPS_Base);CHKERRQ(ierr);
787   } else {
788     ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatConvert_mpisbaij_sbaijmumps_C",
789                                              "MatConvert_SBAIJ_SBAIJMUMPS",MatConvert_SBAIJ_SBAIJMUMPS);CHKERRQ(ierr);
790     ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatConvert_sbaijmumps_mpisbaij_C",
791                                              "MatConvert_MUMPS_Base",MatConvert_MUMPS_Base);CHKERRQ(ierr);
792   }
793 
794   PetscLogInfo(0,"Using MUMPS for Cholesky factorization and solves.");
795   ierr = PetscObjectChangeTypeName((PetscObject)B,newtype);CHKERRQ(ierr);
796   *newmat = B;
797   PetscFunctionReturn(0);
798 }
799 EXTERN_C_END
800 
801 #undef __FUNCT__
802 #define __FUNCT__ "MatDuplicate_SBAIJMUMPS"
803 int MatDuplicate_SBAIJMUMPS(Mat A, MatDuplicateOption op, Mat *M) {
804   int ierr;
805   PetscFunctionBegin;
806   ierr = (*A->ops->duplicate)(A,op,M);CHKERRQ(ierr);
807   ierr = MatConvert_SBAIJ_SBAIJMUMPS(*M,MATSBAIJMUMPS,M);CHKERRQ(ierr);
808   PetscFunctionReturn(0);
809 }
810 
811 /*MC
812   MATSBAIJMUMPS - a symmetric matrix type providing direct solvers (Cholesky) for
813   distributed and sequential matrices via the external package MUMPS.
814 
815   If MUMPS is installed (see the manual for instructions
816   on how to declare the existence of external packages),
817   a matrix type can be constructed which invokes MUMPS solvers.
818   After calling MatCreate(...,A), simply call MatSetType(A,MATSBAIJMUMPS).
819   This matrix type is only supported for double precision real.
820 
821   If created with a single process communicator, this matrix type inherits from MATSEQSBAIJ.
822   Otherwise, this matrix type inherits from MATMPISBAIJ.  Hence for single process communicators,
823   MatSeqSBAIJSetPreallocation is supported, and similarly MatMPISBAIJSetPreallocation is supported
824   for communicators controlling multiple processes.  It is recommended that you call both of
825   the above preallocation routines for simplicity.  One can also call MatConvert for an inplace
826   conversion to or from the MATSEQSBAIJ or MATMPISBAIJ type (depending on the communicator size)
827   without data copy.
828 
829   Options Database Keys:
830 + -mat_type aijmumps
831 . -mat_mumps_sym <0,1,2> - 0 the matrix is unsymmetric, 1 symmetric positive definite, 2 symmetric
832 . -mat_mumps_icntl_4 <0,...,4> - print level
833 . -mat_mumps_icntl_6 <0,...,7> - matrix prescaling options (see MUMPS User's Guide)
834 . -mat_mumps_icntl_7 <0,...,7> - matrix orderings (see MUMPS User's Guide)
835 . -mat_mumps_icntl_9 <1,2> - A or A^T x=b to be solved: 1 denotes A, 2 denotes A^T
836 . -mat_mumps_icntl_10 <n> - maximum number of iterative refinements
837 . -mat_mumps_icntl_11 <n> - error analysis, a positive value returns statistics during -sles_view
838 . -mat_mumps_icntl_12 <n> - efficiency control (see MUMPS User's Guide)
839 . -mat_mumps_icntl_13 <n> - efficiency control (see MUMPS User's Guide)
840 . -mat_mumps_icntl_14 <n> - efficiency control (see MUMPS User's Guide)
841 . -mat_mumps_icntl_15 <n> - efficiency control (see MUMPS User's Guide)
842 . -mat_mumps_cntl_1 <delta> - relative pivoting threshold
843 . -mat_mumps_cntl_2 <tol> - stopping criterion for refinement
844 - -mat_mumps_cntl_3 <adelta> - absolute pivoting threshold
845 
846   Level: beginner
847 
848 .seealso: MATAIJMUMPS
849 M*/
850 
851 EXTERN_C_BEGIN
852 #undef __FUNCT__
853 #define __FUNCT__ "MatCreate_SBAIJMUMPS"
854 int MatCreate_SBAIJMUMPS(Mat A) {
855   int ierr,size;
856 
857   PetscFunctionBegin;
858   /* Change type name before calling MatSetType to force proper construction of SeqSBAIJ or MPISBAIJ */
859   /*   and SBAIJMUMPS types */
860   ierr = PetscObjectChangeTypeName((PetscObject)A,MATSBAIJMUMPS);CHKERRQ(ierr);
861   ierr = MPI_Comm_size(A->comm,&size);CHKERRQ(ierr);CHKERRQ(ierr);
862   if (size == 1) {
863     ierr = MatSetType(A,MATSEQSBAIJ);CHKERRQ(ierr);
864   } else {
865     ierr = MatSetType(A,MATMPISBAIJ);CHKERRQ(ierr);
866   }
867   ierr = MatConvert_SBAIJ_SBAIJMUMPS(A,MATSBAIJMUMPS,&A);CHKERRQ(ierr);
868   PetscFunctionReturn(0);
869 }
870 EXTERN_C_END
871 
872 EXTERN_C_BEGIN
873 #undef __FUNCT__
874 #define __FUNCT__ "MatLoad_SBAIJMUMPS"
875 int MatLoad_SBAIJMUMPS(PetscViewer viewer,MatType type,Mat *A) {
876   int ierr,size,(*r)(PetscViewer,MatType,Mat*);
877   MPI_Comm comm;
878 
879   PetscFunctionBegin;
880   ierr = PetscObjectGetComm((PetscObject)viewer,&comm);CHKERRQ(ierr);
881   ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
882   if (size == 1) {
883     ierr = PetscFListFind(comm,MatLoadList,MATSEQSBAIJ,(void(**)(void))&r);CHKERRQ(ierr);
884   } else {
885     ierr = PetscFListFind(comm,MatLoadList,MATMPISBAIJ,(void(**)(void))&r);CHKERRQ(ierr);
886   }
887   ierr = (*r)(viewer,type,A);CHKERRQ(ierr);
888   PetscFunctionReturn(0);
889 }
890 EXTERN_C_END
891