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 PetscErrorCode (*MatDestroy)(Mat); 43 } Mat_MUMPS; 44 45 EXTERN PetscErrorCode MatDuplicate_MUMPS(Mat,MatDuplicateOption,Mat*); 46 47 /* convert Petsc mpiaij matrix to triples: row[nz], col[nz], val[nz] */ 48 /* 49 input: 50 A - matrix in mpiaij or mpisbaij (bs=1) format 51 shift - 0: C style output triple; 1: Fortran style output triple. 52 valOnly - FALSE: spaces are allocated and values are set for the triple 53 TRUE: only the values in v array are updated 54 output: 55 nnz - dim of r, c, and v (number of local nonzero entries of A) 56 r, c, v - row and col index, matrix values (matrix triples) 57 */ 58 PetscErrorCode MatConvertToTriples(Mat A,int shift,PetscTruth valOnly,int *nnz,int **r, int **c, PetscScalar **v) 59 { 60 PetscInt *ai, *aj, *bi, *bj, rstart,nz, *garray; 61 PetscErrorCode ierr; 62 PetscInt i,j,jj,jB,irow,m=A->rmap->n,*ajj,*bjj,countA,countB,colA_start,jcol; 63 PetscInt *row,*col; 64 PetscScalar *av, *bv,*val; 65 PetscTruth isAIJ; 66 67 PetscFunctionBegin; 68 ierr = PetscTypeCompare((PetscObject)A,MATMPIAIJ,&isAIJ);CHKERRQ(ierr); 69 if (isAIJ){ 70 Mat_MPIAIJ *mat = (Mat_MPIAIJ*)A->data; 71 Mat_SeqAIJ *aa=(Mat_SeqAIJ*)(mat->A)->data; 72 Mat_SeqAIJ *bb=(Mat_SeqAIJ*)(mat->B)->data; 73 nz = aa->nz + bb->nz; 74 ai=aa->i; aj=aa->j; bi=bb->i; bj=bb->j; rstart= A->rmap->rstart; 75 garray = mat->garray; 76 av=aa->a; bv=bb->a; 77 78 } else { 79 Mat_MPISBAIJ *mat = (Mat_MPISBAIJ*)A->data; 80 Mat_SeqSBAIJ *aa=(Mat_SeqSBAIJ*)(mat->A)->data; 81 Mat_SeqBAIJ *bb=(Mat_SeqBAIJ*)(mat->B)->data; 82 if (A->rmap->bs > 1) SETERRQ1(PETSC_ERR_SUP," bs=%d is not supported yet\n", A->rmap->bs); 83 nz = aa->nz + bb->nz; 84 ai=aa->i; aj=aa->j; bi=bb->i; bj=bb->j; rstart= A->rmap->rstart; 85 garray = mat->garray; 86 av=aa->a; bv=bb->a; 87 } 88 89 if (!valOnly){ 90 ierr = PetscMalloc(nz*sizeof(PetscInt) ,&row);CHKERRQ(ierr); 91 ierr = PetscMalloc(nz*sizeof(PetscInt),&col);CHKERRQ(ierr); 92 ierr = PetscMalloc(nz*sizeof(PetscScalar),&val);CHKERRQ(ierr); 93 *r = row; *c = col; *v = val; 94 } else { 95 row = *r; col = *c; val = *v; 96 } 97 *nnz = nz; 98 99 jj = 0; irow = rstart; 100 for ( i=0; i<m; i++ ) { 101 ajj = aj + ai[i]; /* ptr to the beginning of this row */ 102 countA = ai[i+1] - ai[i]; 103 countB = bi[i+1] - bi[i]; 104 bjj = bj + bi[i]; 105 106 /* get jB, the starting local col index for the 2nd B-part */ 107 colA_start = rstart + ajj[0]; /* the smallest col index for A */ 108 j=-1; 109 do { 110 j++; 111 if (j == countB) break; 112 jcol = garray[bjj[j]]; 113 } while (jcol < colA_start); 114 jB = j; 115 116 /* B-part, smaller col index */ 117 colA_start = rstart + ajj[0]; /* the smallest col index for A */ 118 for (j=0; j<jB; j++){ 119 jcol = garray[bjj[j]]; 120 if (!valOnly){ 121 row[jj] = irow + shift; col[jj] = jcol + shift; 122 123 } 124 val[jj++] = *bv++; 125 } 126 /* A-part */ 127 for (j=0; j<countA; j++){ 128 if (!valOnly){ 129 row[jj] = irow + shift; col[jj] = rstart + ajj[j] + shift; 130 } 131 val[jj++] = *av++; 132 } 133 /* B-part, larger col index */ 134 for (j=jB; j<countB; j++){ 135 if (!valOnly){ 136 row[jj] = irow + shift; col[jj] = garray[bjj[j]] + shift; 137 } 138 val[jj++] = *bv++; 139 } 140 irow++; 141 } 142 143 PetscFunctionReturn(0); 144 } 145 146 #undef __FUNCT__ 147 #define __FUNCT__ "MatDestroy_MUMPS" 148 PetscErrorCode MatDestroy_MUMPS(Mat A) 149 { 150 Mat_MUMPS *lu=(Mat_MUMPS*)A->spptr; 151 PetscErrorCode ierr; 152 PetscMPIInt size=lu->size; 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 = (lu->MatDestroy)(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 F,Mat A,const MatFactorInfo *info) 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 F,Mat A,IS r,IS c,const MatFactorInfo *info) 537 { 538 Mat_MUMPS *lu = (Mat_MUMPS*)F->spptr; 539 540 PetscFunctionBegin; 541 lu->sym = 0; 542 lu->matstruc = DIFFERENT_NONZERO_PATTERN; 543 F->ops->lufactornumeric = MatFactorNumeric_MUMPS; 544 PetscFunctionReturn(0); 545 } 546 547 548 /* Note the Petsc r permutation is ignored */ 549 #undef __FUNCT__ 550 #define __FUNCT__ "MatCholeskyFactorSymbolic_SBAIJMUMPS" 551 PetscErrorCode MatCholeskyFactorSymbolic_SBAIJMUMPS(Mat F,Mat A,IS r,const MatFactorInfo *info) 552 { 553 Mat_MUMPS *lu = (Mat_MUMPS*)(F)->spptr; 554 555 PetscFunctionBegin; 556 lu->sym = 2; 557 lu->matstruc = DIFFERENT_NONZERO_PATTERN; 558 (F)->ops->choleskyfactornumeric = MatFactorNumeric_MUMPS; 559 #if !defined(PETSC_USE_COMPLEX) 560 (F)->ops->getinertia = MatGetInertia_SBAIJMUMPS; 561 #endif 562 PetscFunctionReturn(0); 563 } 564 565 #undef __FUNCT__ 566 #define __FUNCT__ "MatFactorInfo_MUMPS" 567 PetscErrorCode MatFactorInfo_MUMPS(Mat A,PetscViewer viewer) { 568 Mat_MUMPS *lu=(Mat_MUMPS*)A->spptr; 569 PetscErrorCode ierr; 570 571 PetscFunctionBegin; 572 /* check if matrix is mumps type */ 573 if (A->ops->solve != MatSolve_MUMPS) PetscFunctionReturn(0); 574 575 ierr = PetscViewerASCIIPrintf(viewer,"MUMPS run parameters:\n");CHKERRQ(ierr); 576 ierr = PetscViewerASCIIPrintf(viewer," SYM (matrix type): %d \n",lu->id.sym);CHKERRQ(ierr); 577 ierr = PetscViewerASCIIPrintf(viewer," PAR (host participation): %d \n",lu->id.par);CHKERRQ(ierr); 578 ierr = PetscViewerASCIIPrintf(viewer," ICNTL(1) (output for error): %d \n",lu->id.ICNTL(1));CHKERRQ(ierr); 579 ierr = PetscViewerASCIIPrintf(viewer," ICNTL(2) (output of diagnostic msg):%d \n",lu->id.ICNTL(2));CHKERRQ(ierr); 580 ierr = PetscViewerASCIIPrintf(viewer," ICNTL(3) (output for global info): %d \n",lu->id.ICNTL(3));CHKERRQ(ierr); 581 ierr = PetscViewerASCIIPrintf(viewer," ICNTL(4) (level of printing): %d \n",lu->id.ICNTL(4));CHKERRQ(ierr); 582 ierr = PetscViewerASCIIPrintf(viewer," ICNTL(5) (input mat struct): %d \n",lu->id.ICNTL(5));CHKERRQ(ierr); 583 ierr = PetscViewerASCIIPrintf(viewer," ICNTL(6) (matrix prescaling): %d \n",lu->id.ICNTL(6));CHKERRQ(ierr); 584 ierr = PetscViewerASCIIPrintf(viewer," ICNTL(7) (matrix ordering): %d \n",lu->id.ICNTL(7));CHKERRQ(ierr); 585 ierr = PetscViewerASCIIPrintf(viewer," ICNTL(8) (scalling strategy): %d \n",lu->id.ICNTL(8));CHKERRQ(ierr); 586 ierr = PetscViewerASCIIPrintf(viewer," ICNTL(9) (A/A^T x=b is solved): %d \n",lu->id.ICNTL(9));CHKERRQ(ierr); 587 ierr = PetscViewerASCIIPrintf(viewer," ICNTL(10) (max num of refinements): %d \n",lu->id.ICNTL(10));CHKERRQ(ierr); 588 ierr = PetscViewerASCIIPrintf(viewer," ICNTL(11) (error analysis): %d \n",lu->id.ICNTL(11));CHKERRQ(ierr); 589 if (!lu->myid && lu->id.ICNTL(11)>0) { 590 ierr = PetscPrintf(PETSC_COMM_SELF," RINFOG(4) (inf norm of input mat): %g\n",lu->id.RINFOG(4));CHKERRQ(ierr); 591 ierr = PetscPrintf(PETSC_COMM_SELF," RINFOG(5) (inf norm of solution): %g\n",lu->id.RINFOG(5));CHKERRQ(ierr); 592 ierr = PetscPrintf(PETSC_COMM_SELF," RINFOG(6) (inf norm of residual): %g\n",lu->id.RINFOG(6));CHKERRQ(ierr); 593 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); 594 ierr = PetscPrintf(PETSC_COMM_SELF," RINFOG(9) (error estimate): %g \n",lu->id.RINFOG(9));CHKERRQ(ierr); 595 ierr = PetscPrintf(PETSC_COMM_SELF," RINFOG(10),RINFOG(11)(condition numbers): %g, %g\n",lu->id.RINFOG(10),lu->id.RINFOG(11));CHKERRQ(ierr); 596 597 } 598 ierr = PetscViewerASCIIPrintf(viewer," ICNTL(12) (efficiency control): %d \n",lu->id.ICNTL(12));CHKERRQ(ierr); 599 ierr = PetscViewerASCIIPrintf(viewer," ICNTL(13) (efficiency control): %d \n",lu->id.ICNTL(13));CHKERRQ(ierr); 600 ierr = PetscViewerASCIIPrintf(viewer," ICNTL(14) (percentage of estimated workspace increase): %d \n",lu->id.ICNTL(14));CHKERRQ(ierr); 601 /* ICNTL(15-17) not used */ 602 ierr = PetscViewerASCIIPrintf(viewer," ICNTL(18) (input mat struct): %d \n",lu->id.ICNTL(18));CHKERRQ(ierr); 603 ierr = PetscViewerASCIIPrintf(viewer," ICNTL(19) (Shur complement info): %d \n",lu->id.ICNTL(19));CHKERRQ(ierr); 604 ierr = PetscViewerASCIIPrintf(viewer," ICNTL(20) (rhs sparse pattern): %d \n",lu->id.ICNTL(20));CHKERRQ(ierr); 605 ierr = PetscViewerASCIIPrintf(viewer," ICNTL(21) (solution struct): %d \n",lu->id.ICNTL(21));CHKERRQ(ierr); 606 607 ierr = PetscViewerASCIIPrintf(viewer," CNTL(1) (relative pivoting threshold): %g \n",lu->id.CNTL(1));CHKERRQ(ierr); 608 ierr = PetscViewerASCIIPrintf(viewer," CNTL(2) (stopping criterion of refinement): %g \n",lu->id.CNTL(2));CHKERRQ(ierr); 609 ierr = PetscViewerASCIIPrintf(viewer," CNTL(3) (absolute pivoting threshold): %g \n",lu->id.CNTL(3));CHKERRQ(ierr); 610 ierr = PetscViewerASCIIPrintf(viewer," CNTL(4) (value of static pivoting): %g \n",lu->id.CNTL(4));CHKERRQ(ierr); 611 612 /* infomation local to each processor */ 613 if (!lu->myid) {ierr = PetscPrintf(PETSC_COMM_SELF, " RINFO(1) (local estimated flops for the elimination after analysis): \n");CHKERRQ(ierr);} 614 ierr = PetscSynchronizedPrintf(((PetscObject)A)->comm," [%d] %g \n",lu->myid,lu->id.RINFO(1));CHKERRQ(ierr); 615 ierr = PetscSynchronizedFlush(((PetscObject)A)->comm); 616 if (!lu->myid) {ierr = PetscPrintf(PETSC_COMM_SELF, " RINFO(2) (local estimated flops for the assembly after factorization): \n");CHKERRQ(ierr);} 617 ierr = PetscSynchronizedPrintf(((PetscObject)A)->comm," [%d] %g \n",lu->myid,lu->id.RINFO(2));CHKERRQ(ierr); 618 ierr = PetscSynchronizedFlush(((PetscObject)A)->comm); 619 if (!lu->myid) {ierr = PetscPrintf(PETSC_COMM_SELF, " RINFO(3) (local estimated flops for the elimination after factorization): \n");CHKERRQ(ierr);} 620 ierr = PetscSynchronizedPrintf(((PetscObject)A)->comm," [%d] %g \n",lu->myid,lu->id.RINFO(3));CHKERRQ(ierr); 621 ierr = PetscSynchronizedFlush(((PetscObject)A)->comm); 622 /* 623 if (!lu->myid) {ierr = PetscPrintf(PETSC_COMM_SELF, " INFO(2) (info about error or warning ): \n");CHKERRQ(ierr);} 624 ierr = PetscSynchronizedPrintf(((PetscObject)A)->comm," [%d] %d \n",lu->myid,lu->id.INFO(2));CHKERRQ(ierr); 625 ierr = PetscSynchronizedFlush(((PetscObject)A)->comm); 626 */ 627 628 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);} 629 ierr = PetscSynchronizedPrintf(((PetscObject)A)->comm," [%d] %d \n",lu->myid,lu->id.INFO(15));CHKERRQ(ierr); 630 ierr = PetscSynchronizedFlush(((PetscObject)A)->comm); 631 632 if (!lu->myid) {ierr = PetscPrintf(PETSC_COMM_SELF, " INFO(16) (size of (in MB) MUMPS internal data used during numerical factorization): \n");CHKERRQ(ierr);} 633 ierr = PetscSynchronizedPrintf(((PetscObject)A)->comm," [%d] %d \n",lu->myid,lu->id.INFO(16));CHKERRQ(ierr); 634 ierr = PetscSynchronizedFlush(((PetscObject)A)->comm); 635 636 if (!lu->myid) {ierr = PetscPrintf(PETSC_COMM_SELF, " INFO(23) (num of pivots eliminated on this processor after factorization): \n");CHKERRQ(ierr);} 637 ierr = PetscSynchronizedPrintf(((PetscObject)A)->comm," [%d] %d \n",lu->myid,lu->id.INFO(23));CHKERRQ(ierr); 638 ierr = PetscSynchronizedFlush(((PetscObject)A)->comm); 639 640 if (!lu->myid){ /* information from the host */ 641 ierr = PetscViewerASCIIPrintf(viewer," RINFOG(1) (global estimated flops for the elimination after analysis): %g \n",lu->id.RINFOG(1));CHKERRQ(ierr); 642 ierr = PetscViewerASCIIPrintf(viewer," RINFOG(2) (global estimated flops for the assembly after factorization): %g \n",lu->id.RINFOG(2));CHKERRQ(ierr); 643 ierr = PetscViewerASCIIPrintf(viewer," RINFOG(3) (global estimated flops for the elimination after factorization): %g \n",lu->id.RINFOG(3));CHKERRQ(ierr); 644 645 ierr = PetscViewerASCIIPrintf(viewer," INFOG(3) (estimated real workspace for factors on all processors after analysis): %d \n",lu->id.INFOG(3));CHKERRQ(ierr); 646 ierr = PetscViewerASCIIPrintf(viewer," INFOG(4) (estimated integer workspace for factors on all processors after analysis): %d \n",lu->id.INFOG(4));CHKERRQ(ierr); 647 ierr = PetscViewerASCIIPrintf(viewer," INFOG(5) (estimated maximum front size in the complete tree): %d \n",lu->id.INFOG(5));CHKERRQ(ierr); 648 ierr = PetscViewerASCIIPrintf(viewer," INFOG(6) (number of nodes in the complete tree): %d \n",lu->id.INFOG(6));CHKERRQ(ierr); 649 ierr = PetscViewerASCIIPrintf(viewer," INFOG(7) (ordering option effectively uese after analysis): %d \n",lu->id.INFOG(7));CHKERRQ(ierr); 650 ierr = PetscViewerASCIIPrintf(viewer," INFOG(8) (structural symmetry in percent of the permuted matrix after analysis): %d \n",lu->id.INFOG(8));CHKERRQ(ierr); 651 ierr = PetscViewerASCIIPrintf(viewer," INFOG(9) (total real/complex workspace to store the matrix factors after factorization): %d \n",lu->id.INFOG(9));CHKERRQ(ierr); 652 ierr = PetscViewerASCIIPrintf(viewer," INFOG(10) (total integer space store the matrix factors after factorization): %d \n",lu->id.INFOG(10));CHKERRQ(ierr); 653 ierr = PetscViewerASCIIPrintf(viewer," INFOG(11) (order of largest frontal matrix after factorization): %d \n",lu->id.INFOG(11));CHKERRQ(ierr); 654 ierr = PetscViewerASCIIPrintf(viewer," INFOG(12) (number of off-diagonal pivots): %d \n",lu->id.INFOG(12));CHKERRQ(ierr); 655 ierr = PetscViewerASCIIPrintf(viewer," INFOG(13) (number of delayed pivots after factorization): %d \n",lu->id.INFOG(13));CHKERRQ(ierr); 656 ierr = PetscViewerASCIIPrintf(viewer," INFOG(14) (number of memory compress after factorization): %d \n",lu->id.INFOG(14));CHKERRQ(ierr); 657 ierr = PetscViewerASCIIPrintf(viewer," INFOG(15) (number of steps of iterative refinement after solution): %d \n",lu->id.INFOG(15));CHKERRQ(ierr); 658 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); 659 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); 660 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); 661 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); 662 ierr = PetscViewerASCIIPrintf(viewer," INFOG(20) (estimated number of entries in the factors): %d \n",lu->id.INFOG(20));CHKERRQ(ierr); 663 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); 664 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); 665 ierr = PetscViewerASCIIPrintf(viewer," INFOG(23) (after analysis: value of ICNTL(6) effectively used): %d \n",lu->id.INFOG(23));CHKERRQ(ierr); 666 ierr = PetscViewerASCIIPrintf(viewer," INFOG(24) (after analysis: value of ICNTL(12) effectively used): %d \n",lu->id.INFOG(24));CHKERRQ(ierr); 667 ierr = PetscViewerASCIIPrintf(viewer," INFOG(25) (after factorization: number of pivots modified by static pivoting): %d \n",lu->id.INFOG(25));CHKERRQ(ierr); 668 } 669 670 PetscFunctionReturn(0); 671 } 672 673 #undef __FUNCT__ 674 #define __FUNCT__ "MatView_MUMPS" 675 PetscErrorCode MatView_MUMPS(Mat A,PetscViewer viewer) 676 { 677 PetscErrorCode ierr; 678 PetscTruth iascii; 679 PetscViewerFormat format; 680 681 PetscFunctionBegin; 682 ierr = PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_ASCII,&iascii);CHKERRQ(ierr); 683 if (iascii) { 684 ierr = PetscViewerGetFormat(viewer,&format);CHKERRQ(ierr); 685 if (format == PETSC_VIEWER_ASCII_INFO){ 686 ierr = MatFactorInfo_MUMPS(A,viewer);CHKERRQ(ierr); 687 } 688 } 689 PetscFunctionReturn(0); 690 } 691 692 693 /*MC 694 MATAIJMUMPS - MATAIJMUMPS = "aijmumps" - A matrix type providing direct solvers (LU) for distributed 695 and sequential matrices via the external package MUMPS. 696 697 If MUMPS is installed (see the manual for instructions 698 on how to declare the existence of external packages), 699 a matrix type can be constructed which invokes MUMPS solvers. 700 After calling MatCreate(...,A), simply call MatSetType(A,MATAIJMUMPS), then 701 optionally call MatSeqAIJSetPreallocation() or MatMPIAIJSetPreallocation() etc DO NOT 702 call MatCreateSeqAIJ/MPIAIJ() directly or the preallocation information will be LOST! 703 704 If created with a single process communicator, this matrix type inherits from MATSEQAIJ. 705 Otherwise, this matrix type inherits from MATMPIAIJ. Hence for single process communicators, 706 MatSeqAIJSetPreallocation() is supported, and similarly MatMPIAIJSetPreallocation() is supported 707 for communicators controlling multiple processes. It is recommended that you call both of 708 the above preallocation routines for simplicity. One can also call MatConvert() for an inplace 709 conversion to or from the MATSEQAIJ or MATMPIAIJ type (depending on the communicator size) 710 without data copy AFTER the matrix values are set. 711 712 Options Database Keys: 713 + -mat_type aijmumps - sets the matrix type to "aijmumps" during a call to MatSetFromOptions() 714 . -mat_mumps_sym <0,1,2> - 0 the matrix is unsymmetric, 1 symmetric positive definite, 2 symmetric 715 . -mat_mumps_icntl_4 <0,1,2,3,4> - print level 716 . -mat_mumps_icntl_6 <0,...,7> - matrix prescaling options (see MUMPS User's Guide) 717 . -mat_mumps_icntl_7 <0,...,7> - matrix orderings (see MUMPS User's Guide) 718 . -mat_mumps_icntl_9 <1,2> - A or A^T x=b to be solved: 1 denotes A, 2 denotes A^T 719 . -mat_mumps_icntl_10 <n> - maximum number of iterative refinements 720 . -mat_mumps_icntl_11 <n> - error analysis, a positive value returns statistics during -ksp_view 721 . -mat_mumps_icntl_12 <n> - efficiency control (see MUMPS User's Guide) 722 . -mat_mumps_icntl_13 <n> - efficiency control (see MUMPS User's Guide) 723 . -mat_mumps_icntl_14 <n> - efficiency control (see MUMPS User's Guide) 724 . -mat_mumps_icntl_15 <n> - efficiency control (see MUMPS User's Guide) 725 . -mat_mumps_cntl_1 <delta> - relative pivoting threshold 726 . -mat_mumps_cntl_2 <tol> - stopping criterion for refinement 727 - -mat_mumps_cntl_3 <adelta> - absolute pivoting threshold 728 729 Level: beginner 730 731 .seealso: MATSBAIJMUMPS 732 M*/ 733 734 735 /*MC 736 MATSBAIJMUMPS - MATSBAIJMUMPS = "sbaijmumps" - A symmetric matrix type providing direct solvers (Cholesky) for 737 distributed and sequential matrices via the external package MUMPS. 738 739 If MUMPS is installed (see the manual for instructions 740 on how to declare the existence of external packages), 741 a matrix type can be constructed which invokes MUMPS solvers. 742 After calling MatCreate(...,A), simply call MatSetType(A,MATSBAIJMUMPS), then 743 optionally call MatSeqSBAIJSetPreallocation() or MatMPISBAIJSetPreallocation() DO NOT 744 call MatCreateSeqSBAIJ/MPISBAIJ() directly or the preallocation information will be LOST! 745 746 If created with a single process communicator, this matrix type inherits from MATSEQSBAIJ. 747 Otherwise, this matrix type inherits from MATMPISBAIJ. Hence for single process communicators, 748 MatSeqSBAIJSetPreallocation() is supported, and similarly MatMPISBAIJSetPreallocation() is supported 749 for communicators controlling multiple processes. It is recommended that you call both of 750 the above preallocation routines for simplicity. One can also call MatConvert() for an inplace 751 conversion to or from the MATSEQSBAIJ or MATMPISBAIJ type (depending on the communicator size) 752 without data copy AFTER the matrix values have been set. 753 754 Options Database Keys: 755 + -mat_type sbaijmumps - sets the matrix type to "sbaijmumps" during a call to MatSetFromOptions() 756 . -mat_mumps_sym <0,1,2> - 0 the matrix is unsymmetric, 1 symmetric positive definite, 2 symmetric 757 . -mat_mumps_icntl_4 <0,...,4> - print level 758 . -mat_mumps_icntl_6 <0,...,7> - matrix prescaling options (see MUMPS User's Guide) 759 . -mat_mumps_icntl_7 <0,...,7> - matrix orderings (see MUMPS User's Guide) 760 . -mat_mumps_icntl_9 <1,2> - A or A^T x=b to be solved: 1 denotes A, 2 denotes A^T 761 . -mat_mumps_icntl_10 <n> - maximum number of iterative refinements 762 . -mat_mumps_icntl_11 <n> - error analysis, a positive value returns statistics during -ksp_view 763 . -mat_mumps_icntl_12 <n> - efficiency control (see MUMPS User's Guide) 764 . -mat_mumps_icntl_13 <n> - efficiency control (see MUMPS User's Guide) 765 . -mat_mumps_icntl_14 <n> - efficiency control (see MUMPS User's Guide) 766 . -mat_mumps_icntl_15 <n> - efficiency control (see MUMPS User's Guide) 767 . -mat_mumps_cntl_1 <delta> - relative pivoting threshold 768 . -mat_mumps_cntl_2 <tol> - stopping criterion for refinement 769 - -mat_mumps_cntl_3 <adelta> - absolute pivoting threshold 770 771 Level: beginner 772 773 .seealso: MATAIJMUMPS 774 M*/ 775 776 EXTERN_C_BEGIN 777 /* 778 The seq and mpi versions of this function are the same 779 */ 780 #undef __FUNCT__ 781 #define __FUNCT__ "MatGetFactor_seqaij_mumps" 782 PetscErrorCode MatGetFactor_seqaij_mumps(Mat A,MatFactorType ftype,Mat *F) 783 { 784 Mat B; 785 PetscErrorCode ierr; 786 Mat_MUMPS *mumps; 787 788 PetscFunctionBegin; 789 if (ftype != MAT_FACTOR_LU) { 790 SETERRQ(PETSC_ERR_SUP,"Cannot use PETSc AIJ matrices with MUMPS Cholesky, use SBAIJ matrix"); 791 } 792 /* Create the factorization matrix */ 793 ierr = MatCreate(((PetscObject)A)->comm,&B);CHKERRQ(ierr); 794 ierr = MatSetSizes(B,A->rmap->n,A->cmap->n,A->rmap->N,A->cmap->N);CHKERRQ(ierr); 795 ierr = MatSetType(B,((PetscObject)A)->type_name);CHKERRQ(ierr); 796 ierr = MatSeqAIJSetPreallocation(B,0,PETSC_NULL);CHKERRQ(ierr); 797 798 B->ops->lufactorsymbolic = MatLUFactorSymbolic_AIJMUMPS; 799 B->ops->view = MatView_MUMPS; 800 B->factor = MAT_FACTOR_LU; 801 802 ierr = PetscNewLog(B,Mat_MUMPS,&mumps);CHKERRQ(ierr); 803 mumps->CleanUpMUMPS = PETSC_FALSE; 804 mumps->isAIJ = PETSC_TRUE; 805 mumps->scat_rhs = PETSC_NULL; 806 mumps->scat_sol = PETSC_NULL; 807 mumps->nSolve = 0; 808 mumps->MatDestroy = B->ops->destroy; 809 B->ops->destroy = MatDestroy_MUMPS; 810 B->spptr = (void*)mumps; 811 812 *F = B; 813 PetscFunctionReturn(0); 814 } 815 EXTERN_C_END 816 817 EXTERN_C_BEGIN 818 #undef __FUNCT__ 819 #define __FUNCT__ "MatGetFactor_mpiaij_mumps" 820 PetscErrorCode MatGetFactor_mpiaij_mumps(Mat A,MatFactorType ftype,Mat *F) 821 { 822 Mat B; 823 PetscErrorCode ierr; 824 Mat_MUMPS *mumps; 825 826 PetscFunctionBegin; 827 if (ftype != MAT_FACTOR_LU) { 828 SETERRQ(PETSC_ERR_SUP,"Cannot use PETSc AIJ matrices with MUMPS Cholesky, use SBAIJ matrix"); 829 } 830 /* Create the factorization matrix */ 831 ierr = MatCreate(((PetscObject)A)->comm,&B);CHKERRQ(ierr); 832 ierr = MatSetSizes(B,A->rmap->n,A->cmap->n,A->rmap->N,A->cmap->N);CHKERRQ(ierr); 833 ierr = MatSetType(B,((PetscObject)A)->type_name);CHKERRQ(ierr); 834 ierr = MatSeqAIJSetPreallocation(B,0,PETSC_NULL);CHKERRQ(ierr); 835 ierr = MatMPIAIJSetPreallocation(B,0,PETSC_NULL,0,PETSC_NULL);CHKERRQ(ierr); 836 837 B->ops->lufactorsymbolic = MatLUFactorSymbolic_AIJMUMPS; 838 B->ops->view = MatView_MUMPS; 839 B->factor = MAT_FACTOR_LU; 840 841 ierr = PetscNewLog(B,Mat_MUMPS,&mumps);CHKERRQ(ierr); 842 mumps->CleanUpMUMPS = PETSC_FALSE; 843 mumps->isAIJ = PETSC_TRUE; 844 mumps->scat_rhs = PETSC_NULL; 845 mumps->scat_sol = PETSC_NULL; 846 mumps->nSolve = 0; 847 mumps->MatDestroy = A->ops->destroy; 848 849 B->spptr = (void*)mumps; 850 851 *F = B; 852 PetscFunctionReturn(0); 853 } 854 EXTERN_C_END 855 856 EXTERN_C_BEGIN 857 #undef __FUNCT__ 858 #define __FUNCT__ "MatGetFactor_seqsbaij_mumps" 859 PetscErrorCode MatGetFactor_seqsbaij_mumps(Mat A,MatFactorType ftype,Mat *F) 860 { 861 Mat B; 862 PetscErrorCode ierr; 863 Mat_MUMPS *mumps; 864 865 PetscFunctionBegin; 866 if (ftype != MAT_FACTOR_CHOLESKY) { 867 SETERRQ(PETSC_ERR_SUP,"Cannot use PETSc SBAIJ matrices with MUMPS LU, use AIJ matrix"); 868 } 869 /* Create the factorization matrix */ 870 ierr = MatCreate(((PetscObject)A)->comm,&B);CHKERRQ(ierr); 871 ierr = MatSetSizes(B,A->rmap->n,A->cmap->n,A->rmap->N,A->cmap->N);CHKERRQ(ierr); 872 ierr = MatSetType(B,((PetscObject)A)->type_name);CHKERRQ(ierr); 873 ierr = MatSeqSBAIJSetPreallocation(B,1,0,PETSC_NULL);CHKERRQ(ierr); 874 ierr = MatMPISBAIJSetPreallocation(B,1,0,PETSC_NULL,0,PETSC_NULL);CHKERRQ(ierr); 875 876 B->ops->choleskyfactorsymbolic = MatCholeskyFactorSymbolic_SBAIJMUMPS; 877 B->ops->view = MatView_MUMPS; 878 B->factor = MAT_FACTOR_CHOLESKY; 879 880 ierr = PetscNewLog(B,Mat_MUMPS,&mumps);CHKERRQ(ierr); 881 mumps->CleanUpMUMPS = PETSC_FALSE; 882 mumps->isAIJ = PETSC_TRUE; 883 mumps->scat_rhs = PETSC_NULL; 884 mumps->scat_sol = PETSC_NULL; 885 mumps->nSolve = 0; 886 mumps->MatDestroy = B->ops->destroy; 887 B->ops->destroy = MatDestroy_MUMPS; 888 889 B->spptr = (void*)mumps; 890 *F = B; 891 PetscFunctionReturn(0); 892 } 893 EXTERN_C_END 894 895 EXTERN_C_BEGIN 896 #undef __FUNCT__ 897 #define __FUNCT__ "MatGetFactor_mpisbaij_mumps" 898 PetscErrorCode MatGetFactor_mpisbaij_mumps(Mat A,MatFactorType ftype,Mat *F) 899 { 900 Mat B; 901 PetscErrorCode ierr; 902 Mat_MUMPS *mumps; 903 904 PetscFunctionBegin; 905 if (ftype != MAT_FACTOR_CHOLESKY) { 906 SETERRQ(PETSC_ERR_SUP,"Cannot use PETSc SBAIJ matrices with MUMPS LU, use AIJ matrix"); 907 } 908 /* Create the factorization matrix */ 909 ierr = MatCreate(((PetscObject)A)->comm,&B);CHKERRQ(ierr); 910 ierr = MatSetSizes(B,A->rmap->n,A->cmap->n,A->rmap->N,A->cmap->N);CHKERRQ(ierr); 911 ierr = MatSetType(B,((PetscObject)A)->type_name);CHKERRQ(ierr); 912 ierr = MatSeqSBAIJSetPreallocation(B,1,0,PETSC_NULL);CHKERRQ(ierr); 913 ierr = MatMPISBAIJSetPreallocation(B,1,0,PETSC_NULL,0,PETSC_NULL);CHKERRQ(ierr); 914 915 B->ops->choleskyfactorsymbolic = MatCholeskyFactorSymbolic_SBAIJMUMPS; 916 B->ops->view = MatView_MUMPS; 917 B->factor = MAT_FACTOR_CHOLESKY; 918 919 ierr = PetscNewLog(B,Mat_MUMPS,&mumps);CHKERRQ(ierr); 920 mumps->CleanUpMUMPS = PETSC_FALSE; 921 mumps->isAIJ = PETSC_TRUE; 922 mumps->scat_rhs = PETSC_NULL; 923 mumps->scat_sol = PETSC_NULL; 924 mumps->nSolve = 0; 925 mumps->MatDestroy = A->ops->destroy; 926 B->spptr = (void*)mumps; 927 *F = B; 928 PetscFunctionReturn(0); 929 } 930 EXTERN_C_END 931