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