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_AIJMUMPS" 456 PetscErrorCode MatFactorNumeric_AIJMUMPS(Mat A,MatFactorInfo *info,Mat *F) 457 { 458 Mat_MUMPS *lu =(Mat_MUMPS*)(*F)->spptr; 459 Mat_MUMPS *lua=(Mat_MUMPS*)(A)->spptr; 460 PetscErrorCode ierr; 461 PetscInt rnz,nnz,nz,i,M=A->M,*ai,*aj,icntl; 462 PetscTruth valOnly,flg; 463 464 PetscFunctionBegin; 465 if (lu->matstruc == DIFFERENT_NONZERO_PATTERN){ 466 (*F)->ops->solve = MatSolve_AIJMUMPS; 467 468 /* Initialize a MUMPS instance */ 469 ierr = MPI_Comm_rank(A->comm, &lu->myid); 470 ierr = MPI_Comm_size(A->comm,&lu->size);CHKERRQ(ierr); 471 lua->myid = lu->myid; lua->size = lu->size; 472 lu->id.job = JOB_INIT; 473 ierr = MPI_Comm_dup(A->comm,&(lu->comm_mumps));CHKERRQ(ierr); 474 lu->id.comm_fortran = lu->comm_mumps; 475 476 /* Set mumps options */ 477 ierr = PetscOptionsBegin(A->comm,A->prefix,"MUMPS Options","Mat");CHKERRQ(ierr); 478 lu->id.par=1; /* host participates factorizaton and solve */ 479 lu->id.sym=lu->sym; 480 if (lu->sym == 2){ 481 ierr = PetscOptionsInt("-mat_mumps_sym","SYM: (1,2)","None",lu->id.sym,&icntl,&flg);CHKERRQ(ierr); 482 if (flg && icntl == 1) lu->id.sym=icntl; /* matrix is spd */ 483 } 484 #if defined(PETSC_USE_COMPLEX) 485 zmumps_c(&lu->id); 486 #else 487 dmumps_c(&lu->id); 488 #endif 489 490 if (lu->size == 1){ 491 lu->id.ICNTL(18) = 0; /* centralized assembled matrix input */ 492 } else { 493 lu->id.ICNTL(18) = 3; /* distributed assembled matrix input */ 494 } 495 496 icntl=-1; 497 ierr = PetscOptionsInt("-mat_mumps_icntl_4","ICNTL(4): level of printing (0 to 4)","None",lu->id.ICNTL(4),&icntl,&flg);CHKERRQ(ierr); 498 if ((flg && icntl > 0) || PetscLogPrintInfo) { 499 lu->id.ICNTL(4)=icntl; /* and use mumps default icntl(i), i=1,2,3 */ 500 } else { /* no output */ 501 lu->id.ICNTL(1) = 0; /* error message, default= 6 */ 502 lu->id.ICNTL(2) = -1; /* output stream for diagnostic printing, statistics, and warning. default=0 */ 503 lu->id.ICNTL(3) = -1; /* output stream for global information, default=6 */ 504 lu->id.ICNTL(4) = 0; /* level of printing, 0,1,2,3,4, default=2 */ 505 } 506 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); 507 icntl=-1; 508 ierr = PetscOptionsInt("-mat_mumps_icntl_7","ICNTL(7): matrix ordering (0 to 7)","None",lu->id.ICNTL(7),&icntl,&flg);CHKERRQ(ierr); 509 if (flg) { 510 if (icntl== 1){ 511 SETERRQ(PETSC_ERR_SUP,"pivot order be set by the user in PERM_IN -- not supported by the PETSc/MUMPS interface\n"); 512 } else { 513 lu->id.ICNTL(7) = icntl; 514 } 515 } 516 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); 517 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); 518 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); 519 ierr = PetscOptionsInt("-mat_mumps_icntl_12","ICNTL(12): efficiency control","None",lu->id.ICNTL(12),&lu->id.ICNTL(12),PETSC_NULL);CHKERRQ(ierr); 520 ierr = PetscOptionsInt("-mat_mumps_icntl_13","ICNTL(13): efficiency control","None",lu->id.ICNTL(13),&lu->id.ICNTL(13),PETSC_NULL);CHKERRQ(ierr); 521 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); 522 ierr = PetscOptionsInt("-mat_mumps_icntl_15","ICNTL(15): efficiency control","None",lu->id.ICNTL(15),&lu->id.ICNTL(15),PETSC_NULL);CHKERRQ(ierr); 523 524 /* 525 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); 526 if (flg){ 527 if (icntl >-1 && icntl <3 ){ 528 if (lu->myid==0) lu->id.ICNTL(16) = icntl; 529 } else { 530 SETERRQ1(PETSC_ERR_SUP,"ICNTL(16)=%d -- not supported\n",icntl); 531 } 532 } 533 */ 534 535 ierr = PetscOptionsReal("-mat_mumps_cntl_1","CNTL(1): relative pivoting threshold","None",lu->id.CNTL(1),&lu->id.CNTL(1),PETSC_NULL);CHKERRQ(ierr); 536 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); 537 ierr = PetscOptionsReal("-mat_mumps_cntl_3","CNTL(3): absolute pivoting threshold","None",lu->id.CNTL(3),&lu->id.CNTL(3),PETSC_NULL);CHKERRQ(ierr); 538 PetscOptionsEnd(); 539 } 540 541 /* define matrix A */ 542 switch (lu->id.ICNTL(18)){ 543 case 0: /* centralized assembled matrix input (size=1) */ 544 if (!lu->myid) { 545 if (lua->isAIJ){ 546 Mat_SeqAIJ *aa = (Mat_SeqAIJ*)A->data; 547 nz = aa->nz; 548 ai = aa->i; aj = aa->j; lu->val = aa->a; 549 } else { 550 Mat_SeqSBAIJ *aa = (Mat_SeqSBAIJ*)A->data; 551 nz = aa->nz; 552 ai = aa->i; aj = aa->j; lu->val = aa->a; 553 } 554 if (lu->matstruc == DIFFERENT_NONZERO_PATTERN){ /* first numeric factorization, get irn and jcn */ 555 ierr = PetscMalloc(nz*sizeof(int),&lu->irn);CHKERRQ(ierr); 556 ierr = PetscMalloc(nz*sizeof(int),&lu->jcn);CHKERRQ(ierr); 557 nz = 0; 558 for (i=0; i<M; i++){ 559 rnz = ai[i+1] - ai[i]; 560 while (rnz--) { /* Fortran row/col index! */ 561 lu->irn[nz] = i+1; lu->jcn[nz] = (*aj)+1; aj++; nz++; 562 } 563 } 564 } 565 } 566 break; 567 case 3: /* distributed assembled matrix input (size>1) */ 568 if (lu->matstruc == DIFFERENT_NONZERO_PATTERN){ 569 valOnly = PETSC_FALSE; 570 } else { 571 valOnly = PETSC_TRUE; /* only update mat values, not row and col index */ 572 } 573 ierr = MatConvertToTriples(A,1,valOnly, &nnz, &lu->irn, &lu->jcn, &lu->val);CHKERRQ(ierr); 574 break; 575 default: SETERRQ(PETSC_ERR_SUP,"Matrix input format is not supported by MUMPS."); 576 } 577 578 /* analysis phase */ 579 if (lu->matstruc == DIFFERENT_NONZERO_PATTERN){ 580 lu->id.n = M; 581 switch (lu->id.ICNTL(18)){ 582 case 0: /* centralized assembled matrix input */ 583 if (!lu->myid) { 584 lu->id.nz =nz; lu->id.irn=lu->irn; lu->id.jcn=lu->jcn; 585 if (lu->id.ICNTL(6)>1){ 586 #if defined(PETSC_USE_COMPLEX) 587 lu->id.a = (mumps_double_complex*)lu->val; 588 #else 589 lu->id.a = lu->val; 590 #endif 591 } 592 } 593 break; 594 case 3: /* distributed assembled matrix input (size>1) */ 595 lu->id.nz_loc = nnz; 596 lu->id.irn_loc=lu->irn; lu->id.jcn_loc=lu->jcn; 597 if (lu->id.ICNTL(6)>1) { 598 #if defined(PETSC_USE_COMPLEX) 599 lu->id.a_loc = (mumps_double_complex*)lu->val; 600 #else 601 lu->id.a_loc = lu->val; 602 #endif 603 } 604 break; 605 } 606 lu->id.job=1; 607 #if defined(PETSC_USE_COMPLEX) 608 zmumps_c(&lu->id); 609 #else 610 dmumps_c(&lu->id); 611 #endif 612 if (lu->id.INFOG(1) < 0) { 613 SETERRQ1(PETSC_ERR_LIB,"Error reported by MUMPS in analysis phase: INFOG(1)=%d\n",lu->id.INFOG(1)); 614 } 615 } 616 617 /* numerical factorization phase */ 618 if(!lu->id.ICNTL(18)) { 619 if (!lu->myid) { 620 #if defined(PETSC_USE_COMPLEX) 621 lu->id.a = (mumps_double_complex*)lu->val; 622 #else 623 lu->id.a = lu->val; 624 #endif 625 } 626 } else { 627 #if defined(PETSC_USE_COMPLEX) 628 lu->id.a_loc = (mumps_double_complex*)lu->val; 629 #else 630 lu->id.a_loc = lu->val; 631 #endif 632 } 633 lu->id.job=2; 634 #if defined(PETSC_USE_COMPLEX) 635 zmumps_c(&lu->id); 636 #else 637 dmumps_c(&lu->id); 638 #endif 639 if (lu->id.INFOG(1) < 0) { 640 if (lu->id.INFO(1) == -13) { 641 SETERRQ1(PETSC_ERR_LIB,"Error reported by MUMPS in numerical factorization phase: Cannot allocate required memory %d megabytes\n",lu->id.INFO(2)); 642 } else { 643 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)); 644 } 645 } 646 647 if (!lu->myid && lu->id.ICNTL(16) > 0){ 648 SETERRQ1(PETSC_ERR_LIB," lu->id.ICNTL(16):=%d\n",lu->id.INFOG(16)); 649 } 650 651 (*F)->assembled = PETSC_TRUE; 652 lu->matstruc = SAME_NONZERO_PATTERN; 653 lu->CleanUpMUMPS = PETSC_TRUE; 654 PetscFunctionReturn(0); 655 } 656 657 /* Note the Petsc r and c permutations are ignored */ 658 #undef __FUNCT__ 659 #define __FUNCT__ "MatLUFactorSymbolic_AIJMUMPS" 660 PetscErrorCode MatLUFactorSymbolic_AIJMUMPS(Mat A,IS r,IS c,MatFactorInfo *info,Mat *F) { 661 Mat B; 662 Mat_MUMPS *lu; 663 PetscErrorCode ierr; 664 665 PetscFunctionBegin; 666 667 /* Create the factorization matrix */ 668 ierr = MatCreate(A->comm,A->m,A->n,A->M,A->N,&B);CHKERRQ(ierr); 669 ierr = MatSetType(B,A->type_name);CHKERRQ(ierr); 670 ierr = MatSeqAIJSetPreallocation(B,0,PETSC_NULL);CHKERRQ(ierr); 671 ierr = MatMPIAIJSetPreallocation(B,0,PETSC_NULL,0,PETSC_NULL);CHKERRQ(ierr); 672 673 B->ops->lufactornumeric = MatFactorNumeric_AIJMUMPS; 674 B->factor = FACTOR_LU; 675 lu = (Mat_MUMPS*)B->spptr; 676 lu->sym = 0; 677 lu->matstruc = DIFFERENT_NONZERO_PATTERN; 678 679 *F = B; 680 PetscFunctionReturn(0); 681 } 682 683 /* Note the Petsc r permutation is ignored */ 684 #undef __FUNCT__ 685 #define __FUNCT__ "MatCholeskyFactorSymbolic_SBAIJMUMPS" 686 PetscErrorCode MatCholeskyFactorSymbolic_SBAIJMUMPS(Mat A,IS r,MatFactorInfo *info,Mat *F) { 687 Mat B; 688 Mat_MUMPS *lu; 689 PetscErrorCode ierr; 690 691 PetscFunctionBegin; 692 /* Create the factorization matrix */ 693 ierr = MatCreate(A->comm,A->m,A->n,A->M,A->N,&B);CHKERRQ(ierr); 694 ierr = MatSetType(B,A->type_name);CHKERRQ(ierr); 695 ierr = MatSeqSBAIJSetPreallocation(B,1,0,PETSC_NULL);CHKERRQ(ierr); 696 ierr = MatMPISBAIJSetPreallocation(B,1,0,PETSC_NULL,0,PETSC_NULL);CHKERRQ(ierr); 697 698 B->ops->choleskyfactornumeric = MatFactorNumeric_AIJMUMPS; 699 B->ops->getinertia = MatGetInertia_SBAIJMUMPS; 700 B->factor = FACTOR_CHOLESKY; 701 lu = (Mat_MUMPS*)B->spptr; 702 lu->sym = 2; 703 lu->matstruc = DIFFERENT_NONZERO_PATTERN; 704 705 *F = B; 706 PetscFunctionReturn(0); 707 } 708 709 #undef __FUNCT__ 710 #define __FUNCT__ "MatAssemblyEnd_AIJMUMPS" 711 PetscErrorCode MatAssemblyEnd_AIJMUMPS(Mat A,MatAssemblyType mode) { 712 PetscErrorCode ierr; 713 Mat_MUMPS *mumps=(Mat_MUMPS*)A->spptr; 714 715 PetscFunctionBegin; 716 ierr = (*mumps->MatAssemblyEnd)(A,mode);CHKERRQ(ierr); 717 718 mumps->MatLUFactorSymbolic = A->ops->lufactorsymbolic; 719 mumps->MatCholeskyFactorSymbolic = A->ops->choleskyfactorsymbolic; 720 A->ops->lufactorsymbolic = MatLUFactorSymbolic_AIJMUMPS; 721 PetscFunctionReturn(0); 722 } 723 724 EXTERN_C_BEGIN 725 #undef __FUNCT__ 726 #define __FUNCT__ "MatConvert_AIJ_AIJMUMPS" 727 PetscErrorCode MatConvert_AIJ_AIJMUMPS(Mat A,const MatType newtype,Mat *newmat) 728 { 729 PetscErrorCode ierr; 730 PetscMPIInt size; 731 MPI_Comm comm; 732 Mat B=*newmat; 733 Mat_MUMPS *mumps; 734 735 PetscFunctionBegin; 736 if (B != A) { 737 ierr = MatDuplicate(A,MAT_COPY_VALUES,&B);CHKERRQ(ierr); 738 } 739 740 ierr = PetscObjectGetComm((PetscObject)A,&comm);CHKERRQ(ierr); 741 ierr = PetscNew(Mat_MUMPS,&mumps);CHKERRQ(ierr); 742 743 mumps->MatDuplicate = A->ops->duplicate; 744 mumps->MatView = A->ops->view; 745 mumps->MatAssemblyEnd = A->ops->assemblyend; 746 mumps->MatLUFactorSymbolic = A->ops->lufactorsymbolic; 747 mumps->MatCholeskyFactorSymbolic = A->ops->choleskyfactorsymbolic; 748 mumps->MatDestroy = A->ops->destroy; 749 mumps->specialdestroy = MatDestroy_AIJMUMPS; 750 mumps->CleanUpMUMPS = PETSC_FALSE; 751 mumps->isAIJ = PETSC_TRUE; 752 753 B->spptr = (void*)mumps; 754 B->ops->duplicate = MatDuplicate_MUMPS; 755 B->ops->view = MatView_AIJMUMPS; 756 B->ops->assemblyend = MatAssemblyEnd_AIJMUMPS; 757 B->ops->lufactorsymbolic = MatLUFactorSymbolic_AIJMUMPS; 758 B->ops->destroy = MatDestroy_MUMPS; 759 760 ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr);CHKERRQ(ierr); 761 if (size == 1) { 762 ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatConvert_seqaij_aijmumps_C", 763 "MatConvert_AIJ_AIJMUMPS",MatConvert_AIJ_AIJMUMPS);CHKERRQ(ierr); 764 ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatConvert_aijmumps_seqaij_C", 765 "MatConvert_MUMPS_Base",MatConvert_MUMPS_Base);CHKERRQ(ierr); 766 } else { 767 ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatConvert_mpiaij_aijmumps_C", 768 "MatConvert_AIJ_AIJMUMPS",MatConvert_AIJ_AIJMUMPS);CHKERRQ(ierr); 769 ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatConvert_aijmumps_mpiaij_C", 770 "MatConvert_MUMPS_Base",MatConvert_MUMPS_Base);CHKERRQ(ierr); 771 } 772 773 PetscLogInfo(0,"Using MUMPS for LU factorization and solves."); 774 ierr = PetscObjectChangeTypeName((PetscObject)B,newtype);CHKERRQ(ierr); 775 *newmat = B; 776 PetscFunctionReturn(0); 777 } 778 EXTERN_C_END 779 780 /*MC 781 MATAIJMUMPS - MATAIJMUMPS = "aijmumps" - A matrix type providing direct solvers (LU) for distributed 782 and sequential matrices via the external package MUMPS. 783 784 If MUMPS is installed (see the manual for instructions 785 on how to declare the existence of external packages), 786 a matrix type can be constructed which invokes MUMPS solvers. 787 After calling MatCreate(...,A), simply call MatSetType(A,MATAIJMUMPS). 788 789 If created with a single process communicator, this matrix type inherits from MATSEQAIJ. 790 Otherwise, this matrix type inherits from MATMPIAIJ. Hence for single process communicators, 791 MatSeqAIJSetPreallocation is supported, and similarly MatMPIAIJSetPreallocation is supported 792 for communicators controlling multiple processes. It is recommended that you call both of 793 the above preallocation routines for simplicity. One can also call MatConvert for an inplace 794 conversion to or from the MATSEQAIJ or MATMPIAIJ type (depending on the communicator size) 795 without data copy. 796 797 Options Database Keys: 798 + -mat_type aijmumps - sets the matrix type to "aijmumps" during a call to MatSetFromOptions() 799 . -mat_mumps_sym <0,1,2> - 0 the matrix is unsymmetric, 1 symmetric positive definite, 2 symmetric 800 . -mat_mumps_icntl_4 <0,1,2,3,4> - print level 801 . -mat_mumps_icntl_6 <0,...,7> - matrix prescaling options (see MUMPS User's Guide) 802 . -mat_mumps_icntl_7 <0,...,7> - matrix orderings (see MUMPS User's Guide) 803 . -mat_mumps_icntl_9 <1,2> - A or A^T x=b to be solved: 1 denotes A, 2 denotes A^T 804 . -mat_mumps_icntl_10 <n> - maximum number of iterative refinements 805 . -mat_mumps_icntl_11 <n> - error analysis, a positive value returns statistics during -ksp_view 806 . -mat_mumps_icntl_12 <n> - efficiency control (see MUMPS User's Guide) 807 . -mat_mumps_icntl_13 <n> - efficiency control (see MUMPS User's Guide) 808 . -mat_mumps_icntl_14 <n> - efficiency control (see MUMPS User's Guide) 809 . -mat_mumps_icntl_15 <n> - efficiency control (see MUMPS User's Guide) 810 . -mat_mumps_cntl_1 <delta> - relative pivoting threshold 811 . -mat_mumps_cntl_2 <tol> - stopping criterion for refinement 812 - -mat_mumps_cntl_3 <adelta> - absolute pivoting threshold 813 814 Level: beginner 815 816 .seealso: MATSBAIJMUMPS 817 M*/ 818 819 EXTERN_C_BEGIN 820 #undef __FUNCT__ 821 #define __FUNCT__ "MatCreate_AIJMUMPS" 822 PetscErrorCode MatCreate_AIJMUMPS(Mat A) 823 { 824 PetscErrorCode ierr; 825 int size; 826 Mat A_diag; 827 MPI_Comm comm; 828 829 PetscFunctionBegin; 830 /* Change type name before calling MatSetType to force proper construction of SeqAIJ or MPIAIJ */ 831 /* and AIJMUMPS types */ 832 ierr = PetscObjectChangeTypeName((PetscObject)A,MATAIJMUMPS);CHKERRQ(ierr); 833 ierr = PetscObjectGetComm((PetscObject)A,&comm);CHKERRQ(ierr); 834 ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr);CHKERRQ(ierr); 835 if (size == 1) { 836 ierr = MatSetType(A,MATSEQAIJ);CHKERRQ(ierr); 837 } else { 838 ierr = MatSetType(A,MATMPIAIJ);CHKERRQ(ierr); 839 A_diag = ((Mat_MPIAIJ *)A->data)->A; 840 ierr = MatConvert_AIJ_AIJMUMPS(A_diag,MATAIJMUMPS,&A_diag);CHKERRQ(ierr); 841 } 842 ierr = MatConvert_AIJ_AIJMUMPS(A,MATAIJMUMPS,&A);CHKERRQ(ierr); 843 PetscFunctionReturn(0); 844 } 845 EXTERN_C_END 846 847 #undef __FUNCT__ 848 #define __FUNCT__ "MatAssemblyEnd_SBAIJMUMPS" 849 PetscErrorCode MatAssemblyEnd_SBAIJMUMPS(Mat A,MatAssemblyType mode) 850 { 851 PetscErrorCode ierr; 852 Mat_MUMPS *mumps=(Mat_MUMPS*)A->spptr; 853 854 PetscFunctionBegin; 855 ierr = (*mumps->MatAssemblyEnd)(A,mode);CHKERRQ(ierr); 856 mumps->MatLUFactorSymbolic = A->ops->lufactorsymbolic; 857 mumps->MatCholeskyFactorSymbolic = A->ops->choleskyfactorsymbolic; 858 A->ops->choleskyfactorsymbolic = MatCholeskyFactorSymbolic_SBAIJMUMPS; 859 PetscFunctionReturn(0); 860 } 861 862 EXTERN_C_BEGIN 863 #undef __FUNCT__ 864 #define __FUNCT__ "MatMPISBAIJSetPreallocation_MPISBAIJMUMPS" 865 PetscErrorCode MatMPISBAIJSetPreallocation_MPISBAIJMUMPS(Mat B,int bs,int d_nz,int *d_nnz,int o_nz,int *o_nnz) 866 { 867 Mat A; 868 Mat_MUMPS *mumps=(Mat_MUMPS*)B->spptr; 869 PetscErrorCode ierr; 870 871 PetscFunctionBegin; 872 /* 873 After performing the MPISBAIJ Preallocation, we need to convert the local diagonal block matrix 874 into MUMPS type so that the block jacobi preconditioner (for example) can use MUMPS. I would 875 like this to be done in the MatCreate routine, but the creation of this inner matrix requires 876 block size info so that PETSc can determine the local size properly. The block size info is set 877 in the preallocation routine. 878 */ 879 ierr = (*mumps->MatPreallocate)(B,bs,d_nz,d_nnz,o_nz,o_nnz); 880 A = ((Mat_MPISBAIJ *)B->data)->A; 881 ierr = MatConvert_SBAIJ_SBAIJMUMPS(A,MATSBAIJMUMPS,&A);CHKERRQ(ierr); 882 PetscFunctionReturn(0); 883 } 884 EXTERN_C_END 885 886 EXTERN_C_BEGIN 887 #undef __FUNCT__ 888 #define __FUNCT__ "MatConvert_SBAIJ_SBAIJMUMPS" 889 PetscErrorCode MatConvert_SBAIJ_SBAIJMUMPS(Mat A,const MatType newtype,Mat *newmat) 890 { 891 PetscErrorCode ierr; 892 PetscMPIInt size; 893 MPI_Comm comm; 894 Mat B=*newmat; 895 Mat_MUMPS *mumps; 896 void (*f)(void); 897 898 PetscFunctionBegin; 899 if (B != A) { 900 ierr = MatDuplicate(A,MAT_COPY_VALUES,&B);CHKERRQ(ierr); 901 } 902 903 ierr = PetscObjectGetComm((PetscObject)A,&comm);CHKERRQ(ierr); 904 ierr = PetscNew(Mat_MUMPS,&mumps);CHKERRQ(ierr); 905 906 mumps->MatDuplicate = A->ops->duplicate; 907 mumps->MatView = A->ops->view; 908 mumps->MatAssemblyEnd = A->ops->assemblyend; 909 mumps->MatLUFactorSymbolic = A->ops->lufactorsymbolic; 910 mumps->MatCholeskyFactorSymbolic = A->ops->choleskyfactorsymbolic; 911 mumps->MatDestroy = A->ops->destroy; 912 mumps->specialdestroy = MatDestroy_SBAIJMUMPS; 913 mumps->CleanUpMUMPS = PETSC_FALSE; 914 mumps->isAIJ = PETSC_FALSE; 915 916 B->spptr = (void*)mumps; 917 B->ops->duplicate = MatDuplicate_MUMPS; 918 B->ops->view = MatView_AIJMUMPS; 919 B->ops->assemblyend = MatAssemblyEnd_SBAIJMUMPS; 920 B->ops->choleskyfactorsymbolic = MatCholeskyFactorSymbolic_SBAIJMUMPS; 921 B->ops->destroy = MatDestroy_MUMPS; 922 923 ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr);CHKERRQ(ierr); 924 if (size == 1) { 925 ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatConvert_seqsbaij_sbaijmumps_C", 926 "MatConvert_SBAIJ_SBAIJMUMPS",MatConvert_SBAIJ_SBAIJMUMPS);CHKERRQ(ierr); 927 ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatConvert_sbaijmumps_seqsbaij_C", 928 "MatConvert_MUMPS_Base",MatConvert_MUMPS_Base);CHKERRQ(ierr); 929 } else { 930 /* I really don't like needing to know the tag: MatMPISBAIJSetPreallocation_C */ 931 ierr = PetscObjectQueryFunction((PetscObject)B,"MatMPISBAIJSetPreallocation_C",&f);CHKERRQ(ierr); 932 if (f) { /* This case should always be true when this routine is called */ 933 mumps->MatPreallocate = (PetscErrorCode (*)(Mat,int,int,int*,int,int*))f; 934 ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatMPISBAIJSetPreallocation_C", 935 "MatMPISBAIJSetPreallocation_MPISBAIJMUMPS", 936 MatMPISBAIJSetPreallocation_MPISBAIJMUMPS);CHKERRQ(ierr); 937 } 938 ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatConvert_mpisbaij_sbaijmumps_C", 939 "MatConvert_SBAIJ_SBAIJMUMPS",MatConvert_SBAIJ_SBAIJMUMPS);CHKERRQ(ierr); 940 ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatConvert_sbaijmumps_mpisbaij_C", 941 "MatConvert_MUMPS_Base",MatConvert_MUMPS_Base);CHKERRQ(ierr); 942 } 943 944 PetscLogInfo(0,"Using MUMPS for Cholesky factorization and solves."); 945 ierr = PetscObjectChangeTypeName((PetscObject)B,newtype);CHKERRQ(ierr); 946 *newmat = B; 947 PetscFunctionReturn(0); 948 } 949 EXTERN_C_END 950 951 #undef __FUNCT__ 952 #define __FUNCT__ "MatDuplicate_MUMPS" 953 PetscErrorCode MatDuplicate_MUMPS(Mat A, MatDuplicateOption op, Mat *M) { 954 PetscErrorCode ierr; 955 Mat_MUMPS *lu=(Mat_MUMPS *)A->spptr; 956 957 PetscFunctionBegin; 958 ierr = (*lu->MatDuplicate)(A,op,M);CHKERRQ(ierr); 959 ierr = PetscMemcpy((*M)->spptr,lu,sizeof(Mat_MUMPS));CHKERRQ(ierr); 960 PetscFunctionReturn(0); 961 } 962 963 /*MC 964 MATSBAIJMUMPS - MATSBAIJMUMPS = "sbaijmumps" - A symmetric matrix type providing direct solvers (Cholesky) for 965 distributed and sequential matrices via the external package MUMPS. 966 967 If MUMPS is installed (see the manual for instructions 968 on how to declare the existence of external packages), 969 a matrix type can be constructed which invokes MUMPS solvers. 970 After calling MatCreate(...,A), simply call MatSetType(A,MATSBAIJMUMPS). 971 972 If created with a single process communicator, this matrix type inherits from MATSEQSBAIJ. 973 Otherwise, this matrix type inherits from MATMPISBAIJ. Hence for single process communicators, 974 MatSeqSBAIJSetPreallocation is supported, and similarly MatMPISBAIJSetPreallocation is supported 975 for communicators controlling multiple processes. It is recommended that you call both of 976 the above preallocation routines for simplicity. One can also call MatConvert for an inplace 977 conversion to or from the MATSEQSBAIJ or MATMPISBAIJ type (depending on the communicator size) 978 without data copy. 979 980 Options Database Keys: 981 + -mat_type sbaijmumps - sets the matrix type to "sbaijmumps" during a call to MatSetFromOptions() 982 . -mat_mumps_sym <0,1,2> - 0 the matrix is unsymmetric, 1 symmetric positive definite, 2 symmetric 983 . -mat_mumps_icntl_4 <0,...,4> - print level 984 . -mat_mumps_icntl_6 <0,...,7> - matrix prescaling options (see MUMPS User's Guide) 985 . -mat_mumps_icntl_7 <0,...,7> - matrix orderings (see MUMPS User's Guide) 986 . -mat_mumps_icntl_9 <1,2> - A or A^T x=b to be solved: 1 denotes A, 2 denotes A^T 987 . -mat_mumps_icntl_10 <n> - maximum number of iterative refinements 988 . -mat_mumps_icntl_11 <n> - error analysis, a positive value returns statistics during -ksp_view 989 . -mat_mumps_icntl_12 <n> - efficiency control (see MUMPS User's Guide) 990 . -mat_mumps_icntl_13 <n> - efficiency control (see MUMPS User's Guide) 991 . -mat_mumps_icntl_14 <n> - efficiency control (see MUMPS User's Guide) 992 . -mat_mumps_icntl_15 <n> - efficiency control (see MUMPS User's Guide) 993 . -mat_mumps_cntl_1 <delta> - relative pivoting threshold 994 . -mat_mumps_cntl_2 <tol> - stopping criterion for refinement 995 - -mat_mumps_cntl_3 <adelta> - absolute pivoting threshold 996 997 Level: beginner 998 999 .seealso: MATAIJMUMPS 1000 M*/ 1001 1002 EXTERN_C_BEGIN 1003 #undef __FUNCT__ 1004 #define __FUNCT__ "MatCreate_SBAIJMUMPS" 1005 PetscErrorCode MatCreate_SBAIJMUMPS(Mat A) 1006 { 1007 PetscErrorCode ierr; 1008 int size; 1009 1010 PetscFunctionBegin; 1011 /* Change type name before calling MatSetType to force proper construction of SeqSBAIJ or MPISBAIJ */ 1012 /* and SBAIJMUMPS types */ 1013 ierr = PetscObjectChangeTypeName((PetscObject)A,MATSBAIJMUMPS);CHKERRQ(ierr); 1014 ierr = MPI_Comm_size(A->comm,&size);CHKERRQ(ierr);CHKERRQ(ierr); 1015 if (size == 1) { 1016 ierr = MatSetType(A,MATSEQSBAIJ);CHKERRQ(ierr); 1017 } else { 1018 ierr = MatSetType(A,MATMPISBAIJ);CHKERRQ(ierr); 1019 } 1020 ierr = MatConvert_SBAIJ_SBAIJMUMPS(A,MATSBAIJMUMPS,&A);CHKERRQ(ierr); 1021 PetscFunctionReturn(0); 1022 } 1023 EXTERN_C_END 1024