1 /* 2 Provides an interface to the PaStiX sparse solver 3 */ 4 #include <../src/mat/impls/aij/seq/aij.h> 5 #include <../src/mat/impls/aij/mpi/mpiaij.h> 6 #include <../src/mat/impls/sbaij/seq/sbaij.h> 7 #include <../src/mat/impls/sbaij/mpi/mpisbaij.h> 8 9 #if defined(PETSC_USE_COMPLEX) 10 #define _H_COMPLEX 11 #endif 12 13 EXTERN_C_BEGIN 14 #include <pastix.h> 15 EXTERN_C_END 16 17 #if defined(PETSC_USE_COMPLEX) 18 #if defined(PETSC_USE_REAL_SINGLE) 19 #define PASTIX_CALL c_pastix 20 #else 21 #define PASTIX_CALL z_pastix 22 #endif 23 24 #else /* PETSC_USE_COMPLEX */ 25 26 #if defined(PETSC_USE_REAL_SINGLE) 27 #define PASTIX_CALL s_pastix 28 #else 29 #define PASTIX_CALL d_pastix 30 #endif 31 32 #endif /* PETSC_USE_COMPLEX */ 33 34 typedef PetscScalar PastixScalar; 35 36 typedef struct Mat_Pastix_ { 37 pastix_data_t *pastix_data; /* Pastix data storage structure */ 38 MatStructure matstruc; 39 PetscInt n; /* Number of columns in the matrix */ 40 PetscInt *colptr; /* Index of first element of each column in row and val */ 41 PetscInt *row; /* Row of each element of the matrix */ 42 PetscScalar *val; /* Value of each element of the matrix */ 43 PetscInt *perm; /* Permutation tabular */ 44 PetscInt *invp; /* Reverse permutation tabular */ 45 PetscScalar *rhs; /* Rhight-hand-side member */ 46 PetscInt rhsnbr; /* Rhight-hand-side number (must be 1) */ 47 PetscInt iparm[IPARM_SIZE]; /* Integer parameters */ 48 double dparm[DPARM_SIZE]; /* Floating point parameters */ 49 MPI_Comm pastix_comm; /* PaStiX MPI communicator */ 50 PetscMPIInt commRank; /* MPI rank */ 51 PetscMPIInt commSize; /* MPI communicator size */ 52 PetscBool CleanUpPastix; /* Boolean indicating if we call PaStiX clean step */ 53 VecScatter scat_rhs; 54 VecScatter scat_sol; 55 Vec b_seq; 56 } Mat_Pastix; 57 58 extern PetscErrorCode MatDuplicate_Pastix(Mat,MatDuplicateOption,Mat*); 59 60 /* 61 convert Petsc seqaij matrix to CSC: colptr[n], row[nz], val[nz] 62 63 input: 64 A - matrix in seqaij or mpisbaij (bs=1) format 65 valOnly - FALSE: spaces are allocated and values are set for the CSC 66 TRUE: Only fill values 67 output: 68 n - Size of the matrix 69 colptr - Index of first element of each column in row and val 70 row - Row of each element of the matrix 71 values - Value of each element of the matrix 72 */ 73 PetscErrorCode MatConvertToCSC(Mat A,PetscBool valOnly,PetscInt *n,PetscInt **colptr,PetscInt **row,PetscScalar **values) 74 { 75 Mat_SeqAIJ *aa = (Mat_SeqAIJ*)A->data; 76 PetscInt *rowptr = aa->i; 77 PetscInt *col = aa->j; 78 PetscScalar *rvalues = aa->a; 79 PetscInt m = A->rmap->N; 80 PetscInt nnz; 81 PetscInt i,j, k; 82 PetscInt base = 1; 83 PetscInt idx; 84 PetscErrorCode ierr; 85 PetscInt colidx; 86 PetscInt *colcount; 87 PetscBool isSBAIJ; 88 PetscBool isSeqSBAIJ; 89 PetscBool isMpiSBAIJ; 90 PetscBool isSym; 91 92 PetscFunctionBegin; 93 ierr = MatIsSymmetric(A,0.0,&isSym);CHKERRQ(ierr); 94 ierr = PetscObjectTypeCompare((PetscObject)A,MATSBAIJ,&isSBAIJ);CHKERRQ(ierr); 95 ierr = PetscObjectTypeCompare((PetscObject)A,MATSEQSBAIJ,&isSeqSBAIJ);CHKERRQ(ierr); 96 ierr = PetscObjectTypeCompare((PetscObject)A,MATMPISBAIJ,&isMpiSBAIJ);CHKERRQ(ierr); 97 98 *n = A->cmap->N; 99 100 /* PaStiX only needs triangular matrix if matrix is symmetric 101 */ 102 if (isSym && !(isSBAIJ || isSeqSBAIJ || isMpiSBAIJ)) nnz = (aa->nz - *n)/2 + *n; 103 else nnz = aa->nz; 104 105 if (!valOnly) { 106 ierr = PetscMalloc1((*n)+1,colptr);CHKERRQ(ierr); 107 ierr = PetscMalloc1(nnz,row);CHKERRQ(ierr); 108 ierr = PetscMalloc1(nnz,values);CHKERRQ(ierr); 109 110 if (isSBAIJ || isSeqSBAIJ || isMpiSBAIJ) { 111 ierr = PetscArraycpy (*colptr, rowptr, (*n)+1);CHKERRQ(ierr); 112 for (i = 0; i < *n+1; i++) (*colptr)[i] += base; 113 ierr = PetscArraycpy (*row, col, nnz);CHKERRQ(ierr); 114 for (i = 0; i < nnz; i++) (*row)[i] += base; 115 ierr = PetscArraycpy (*values, rvalues, nnz);CHKERRQ(ierr); 116 } else { 117 ierr = PetscMalloc1(*n,&colcount);CHKERRQ(ierr); 118 119 for (i = 0; i < m; i++) colcount[i] = 0; 120 /* Fill-in colptr */ 121 for (i = 0; i < m; i++) { 122 for (j = rowptr[i]; j < rowptr[i+1]; j++) { 123 if (!isSym || col[j] <= i) colcount[col[j]]++; 124 } 125 } 126 127 (*colptr)[0] = base; 128 for (j = 0; j < *n; j++) { 129 (*colptr)[j+1] = (*colptr)[j] + colcount[j]; 130 /* in next loop we fill starting from (*colptr)[colidx] - base */ 131 colcount[j] = -base; 132 } 133 134 /* Fill-in rows and values */ 135 for (i = 0; i < m; i++) { 136 for (j = rowptr[i]; j < rowptr[i+1]; j++) { 137 if (!isSym || col[j] <= i) { 138 colidx = col[j]; 139 idx = (*colptr)[colidx] + colcount[colidx]; 140 (*row)[idx] = i + base; 141 (*values)[idx] = rvalues[j]; 142 colcount[colidx]++; 143 } 144 } 145 } 146 ierr = PetscFree(colcount);CHKERRQ(ierr); 147 } 148 } else { 149 /* Fill-in only values */ 150 for (i = 0; i < m; i++) { 151 for (j = rowptr[i]; j < rowptr[i+1]; j++) { 152 colidx = col[j]; 153 if ((isSBAIJ || isSeqSBAIJ || isMpiSBAIJ) ||!isSym || col[j] <= i) { 154 /* look for the value to fill */ 155 for (k = (*colptr)[colidx] - base; k < (*colptr)[colidx + 1] - base; k++) { 156 if (((*row)[k]-base) == i) { 157 (*values)[k] = rvalues[j]; 158 break; 159 } 160 } 161 /* data structure of sparse matrix has changed */ 162 if (k == (*colptr)[colidx + 1] - base) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_PLIB,"overflow on k %D",k); 163 } 164 } 165 } 166 } 167 PetscFunctionReturn(0); 168 } 169 170 /* 171 Call clean step of PaStiX if lu->CleanUpPastix == true. 172 Free the CSC matrix. 173 */ 174 PetscErrorCode MatDestroy_Pastix(Mat A) 175 { 176 Mat_Pastix *lu=(Mat_Pastix*)A->data; 177 PetscErrorCode ierr; 178 179 PetscFunctionBegin; 180 if (lu->CleanUpPastix) { 181 /* Terminate instance, deallocate memories */ 182 ierr = VecScatterDestroy(&lu->scat_rhs);CHKERRQ(ierr); 183 ierr = VecDestroy(&lu->b_seq);CHKERRQ(ierr); 184 ierr = VecScatterDestroy(&lu->scat_sol);CHKERRQ(ierr); 185 186 lu->iparm[IPARM_START_TASK]=API_TASK_CLEAN; 187 lu->iparm[IPARM_END_TASK] =API_TASK_CLEAN; 188 189 PASTIX_CALL(&(lu->pastix_data), 190 lu->pastix_comm, 191 lu->n, 192 lu->colptr, 193 lu->row, 194 (PastixScalar*)lu->val, 195 lu->perm, 196 lu->invp, 197 (PastixScalar*)lu->rhs, 198 lu->rhsnbr, 199 lu->iparm, 200 lu->dparm); 201 if (lu->iparm[IPARM_ERROR_NUMBER] != 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error reported by PaStiX in destroy: iparm(IPARM_ERROR_NUMBER)=%d\n",lu->iparm[IPARM_ERROR_NUMBER]); 202 ierr = PetscFree(lu->colptr);CHKERRQ(ierr); 203 ierr = PetscFree(lu->row);CHKERRQ(ierr); 204 ierr = PetscFree(lu->val);CHKERRQ(ierr); 205 ierr = PetscFree(lu->perm);CHKERRQ(ierr); 206 ierr = PetscFree(lu->invp);CHKERRQ(ierr); 207 ierr = MPI_Comm_free(&(lu->pastix_comm));CHKERRQ(ierr); 208 } 209 ierr = PetscFree(A->data);CHKERRQ(ierr); 210 PetscFunctionReturn(0); 211 } 212 213 /* 214 Gather right-hand-side. 215 Call for Solve step. 216 Scatter solution. 217 */ 218 PetscErrorCode MatSolve_PaStiX(Mat A,Vec b,Vec x) 219 { 220 Mat_Pastix *lu=(Mat_Pastix*)A->data; 221 PetscScalar *array; 222 Vec x_seq; 223 PetscErrorCode ierr; 224 225 PetscFunctionBegin; 226 lu->rhsnbr = 1; 227 x_seq = lu->b_seq; 228 if (lu->commSize > 1) { 229 /* PaStiX only supports centralized rhs. Scatter b into a seqential rhs vector */ 230 ierr = VecScatterBegin(lu->scat_rhs,b,x_seq,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 231 ierr = VecScatterEnd(lu->scat_rhs,b,x_seq,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 232 ierr = VecGetArray(x_seq,&array);CHKERRQ(ierr); 233 } else { /* size == 1 */ 234 ierr = VecCopy(b,x);CHKERRQ(ierr); 235 ierr = VecGetArray(x,&array);CHKERRQ(ierr); 236 } 237 lu->rhs = array; 238 if (lu->commSize == 1) { 239 ierr = VecRestoreArray(x,&array);CHKERRQ(ierr); 240 } else { 241 ierr = VecRestoreArray(x_seq,&array);CHKERRQ(ierr); 242 } 243 244 /* solve phase */ 245 /*-------------*/ 246 lu->iparm[IPARM_START_TASK] = API_TASK_SOLVE; 247 lu->iparm[IPARM_END_TASK] = API_TASK_REFINE; 248 lu->iparm[IPARM_RHS_MAKING] = API_RHS_B; 249 250 PASTIX_CALL(&(lu->pastix_data), 251 lu->pastix_comm, 252 lu->n, 253 lu->colptr, 254 lu->row, 255 (PastixScalar*)lu->val, 256 lu->perm, 257 lu->invp, 258 (PastixScalar*)lu->rhs, 259 lu->rhsnbr, 260 lu->iparm, 261 lu->dparm); 262 if (lu->iparm[IPARM_ERROR_NUMBER] != 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error reported by PaStiX in solve phase: lu->iparm[IPARM_ERROR_NUMBER] = %d\n",lu->iparm[IPARM_ERROR_NUMBER]); 263 264 if (lu->commSize == 1) { 265 ierr = VecRestoreArray(x,&(lu->rhs));CHKERRQ(ierr); 266 } else { 267 ierr = VecRestoreArray(x_seq,&(lu->rhs));CHKERRQ(ierr); 268 } 269 270 if (lu->commSize > 1) { /* convert PaStiX centralized solution to petsc mpi x */ 271 ierr = VecScatterBegin(lu->scat_sol,x_seq,x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 272 ierr = VecScatterEnd(lu->scat_sol,x_seq,x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 273 } 274 PetscFunctionReturn(0); 275 } 276 277 /* 278 Numeric factorisation using PaStiX solver. 279 280 */ 281 PetscErrorCode MatFactorNumeric_PaStiX(Mat F,Mat A,const MatFactorInfo *info) 282 { 283 Mat_Pastix *lu =(Mat_Pastix*)(F)->data; 284 Mat *tseq; 285 PetscErrorCode ierr = 0; 286 PetscInt icntl; 287 PetscInt M=A->rmap->N; 288 PetscBool valOnly,flg, isSym; 289 IS is_iden; 290 Vec b; 291 IS isrow; 292 PetscBool isSeqAIJ,isSeqSBAIJ,isMPIAIJ; 293 294 PetscFunctionBegin; 295 ierr = PetscObjectTypeCompare((PetscObject)A,MATSEQAIJ,&isSeqAIJ);CHKERRQ(ierr); 296 ierr = PetscObjectTypeCompare((PetscObject)A,MATMPIAIJ,&isMPIAIJ);CHKERRQ(ierr); 297 ierr = PetscObjectTypeCompare((PetscObject)A,MATSEQSBAIJ,&isSeqSBAIJ);CHKERRQ(ierr); 298 if (lu->matstruc == DIFFERENT_NONZERO_PATTERN) { 299 (F)->ops->solve = MatSolve_PaStiX; 300 301 /* Initialize a PASTIX instance */ 302 ierr = MPI_Comm_dup(PetscObjectComm((PetscObject)A),&(lu->pastix_comm));CHKERRQ(ierr); 303 ierr = MPI_Comm_rank(lu->pastix_comm, &lu->commRank);CHKERRQ(ierr); 304 ierr = MPI_Comm_size(lu->pastix_comm, &lu->commSize);CHKERRQ(ierr); 305 306 /* Set pastix options */ 307 lu->iparm[IPARM_MODIFY_PARAMETER] = API_NO; 308 lu->iparm[IPARM_START_TASK] = API_TASK_INIT; 309 lu->iparm[IPARM_END_TASK] = API_TASK_INIT; 310 311 lu->rhsnbr = 1; 312 313 /* Call to set default pastix options */ 314 PASTIX_CALL(&(lu->pastix_data), 315 lu->pastix_comm, 316 lu->n, 317 lu->colptr, 318 lu->row, 319 (PastixScalar*)lu->val, 320 lu->perm, 321 lu->invp, 322 (PastixScalar*)lu->rhs, 323 lu->rhsnbr, 324 lu->iparm, 325 lu->dparm); 326 if (lu->iparm[IPARM_ERROR_NUMBER] != 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error reported by PaStiX in MatFactorNumeric: iparm(IPARM_ERROR_NUMBER)=%d\n",lu->iparm[IPARM_ERROR_NUMBER]); 327 328 ierr = PetscOptionsBegin(PetscObjectComm((PetscObject)A),((PetscObject)A)->prefix,"PaStiX Options","Mat");CHKERRQ(ierr); 329 icntl = -1; 330 lu->iparm[IPARM_VERBOSE] = API_VERBOSE_NOT; 331 ierr = PetscOptionsInt("-mat_pastix_verbose","iparm[IPARM_VERBOSE] : level of printing (0 to 2)","None",lu->iparm[IPARM_VERBOSE],&icntl,&flg);CHKERRQ(ierr); 332 if ((flg && icntl >= 0) || PetscLogPrintInfo) { 333 lu->iparm[IPARM_VERBOSE] = icntl; 334 } 335 icntl=-1; 336 ierr = PetscOptionsInt("-mat_pastix_threadnbr","iparm[IPARM_THREAD_NBR] : Number of thread by MPI node","None",lu->iparm[IPARM_THREAD_NBR],&icntl,&flg);CHKERRQ(ierr); 337 if ((flg && icntl > 0)) { 338 lu->iparm[IPARM_THREAD_NBR] = icntl; 339 } 340 PetscOptionsEnd(); 341 valOnly = PETSC_FALSE; 342 } else { 343 if (isSeqAIJ || isMPIAIJ) { 344 ierr = PetscFree(lu->colptr);CHKERRQ(ierr); 345 ierr = PetscFree(lu->row);CHKERRQ(ierr); 346 ierr = PetscFree(lu->val);CHKERRQ(ierr); 347 valOnly = PETSC_FALSE; 348 } else valOnly = PETSC_TRUE; 349 } 350 351 lu->iparm[IPARM_MATRIX_VERIFICATION] = API_YES; 352 353 /* convert mpi A to seq mat A */ 354 ierr = ISCreateStride(PETSC_COMM_SELF,M,0,1,&isrow);CHKERRQ(ierr); 355 ierr = MatCreateSubMatrices(A,1,&isrow,&isrow,MAT_INITIAL_MATRIX,&tseq);CHKERRQ(ierr); 356 ierr = ISDestroy(&isrow);CHKERRQ(ierr); 357 358 ierr = MatConvertToCSC(*tseq,valOnly, &lu->n, &lu->colptr, &lu->row, &lu->val);CHKERRQ(ierr); 359 ierr = MatIsSymmetric(*tseq,0.0,&isSym);CHKERRQ(ierr); 360 ierr = MatDestroyMatrices(1,&tseq);CHKERRQ(ierr); 361 362 if (!lu->perm) { 363 ierr = PetscMalloc1(lu->n,&(lu->perm));CHKERRQ(ierr); 364 ierr = PetscMalloc1(lu->n,&(lu->invp));CHKERRQ(ierr); 365 } 366 367 if (isSym) { 368 /* On symmetric matrix, LLT */ 369 lu->iparm[IPARM_SYM] = API_SYM_YES; 370 lu->iparm[IPARM_FACTORIZATION] = API_FACT_LDLT; 371 } else { 372 /* On unsymmetric matrix, LU */ 373 lu->iparm[IPARM_SYM] = API_SYM_NO; 374 lu->iparm[IPARM_FACTORIZATION] = API_FACT_LU; 375 } 376 377 /*----------------*/ 378 if (lu->matstruc == DIFFERENT_NONZERO_PATTERN) { 379 if (!(isSeqAIJ || isSeqSBAIJ) && !lu->b_seq) { 380 /* PaStiX only supports centralized rhs. Create scatter scat_rhs for repeated use in MatSolve() */ 381 ierr = VecCreateSeq(PETSC_COMM_SELF,A->cmap->N,&lu->b_seq);CHKERRQ(ierr); 382 ierr = ISCreateStride(PETSC_COMM_SELF,A->cmap->N,0,1,&is_iden);CHKERRQ(ierr); 383 ierr = MatCreateVecs(A,NULL,&b);CHKERRQ(ierr); 384 ierr = VecScatterCreate(b,is_iden,lu->b_seq,is_iden,&lu->scat_rhs);CHKERRQ(ierr); 385 ierr = VecScatterCreate(lu->b_seq,is_iden,b,is_iden,&lu->scat_sol);CHKERRQ(ierr); 386 ierr = ISDestroy(&is_iden);CHKERRQ(ierr); 387 ierr = VecDestroy(&b);CHKERRQ(ierr); 388 } 389 lu->iparm[IPARM_START_TASK] = API_TASK_ORDERING; 390 lu->iparm[IPARM_END_TASK] = API_TASK_NUMFACT; 391 392 PASTIX_CALL(&(lu->pastix_data), 393 lu->pastix_comm, 394 lu->n, 395 lu->colptr, 396 lu->row, 397 (PastixScalar*)lu->val, 398 lu->perm, 399 lu->invp, 400 (PastixScalar*)lu->rhs, 401 lu->rhsnbr, 402 lu->iparm, 403 lu->dparm); 404 if (lu->iparm[IPARM_ERROR_NUMBER] != 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error reported by PaStiX in analysis phase: iparm(IPARM_ERROR_NUMBER)=%d\n",lu->iparm[IPARM_ERROR_NUMBER]); 405 } else { 406 lu->iparm[IPARM_START_TASK] = API_TASK_NUMFACT; 407 lu->iparm[IPARM_END_TASK] = API_TASK_NUMFACT; 408 PASTIX_CALL(&(lu->pastix_data), 409 lu->pastix_comm, 410 lu->n, 411 lu->colptr, 412 lu->row, 413 (PastixScalar*)lu->val, 414 lu->perm, 415 lu->invp, 416 (PastixScalar*)lu->rhs, 417 lu->rhsnbr, 418 lu->iparm, 419 lu->dparm); 420 if (lu->iparm[IPARM_ERROR_NUMBER] != 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error reported by PaStiX in analysis phase: iparm(IPARM_ERROR_NUMBER)=%d\n",lu->iparm[IPARM_ERROR_NUMBER]); 421 } 422 423 (F)->assembled = PETSC_TRUE; 424 lu->matstruc = SAME_NONZERO_PATTERN; 425 lu->CleanUpPastix = PETSC_TRUE; 426 PetscFunctionReturn(0); 427 } 428 429 /* Note the Petsc r and c permutations are ignored */ 430 PetscErrorCode MatLUFactorSymbolic_AIJPASTIX(Mat F,Mat A,IS r,IS c,const MatFactorInfo *info) 431 { 432 Mat_Pastix *lu = (Mat_Pastix*)F->data; 433 434 PetscFunctionBegin; 435 lu->iparm[IPARM_FACTORIZATION] = API_FACT_LU; 436 lu->iparm[IPARM_SYM] = API_SYM_YES; 437 lu->matstruc = DIFFERENT_NONZERO_PATTERN; 438 F->ops->lufactornumeric = MatFactorNumeric_PaStiX; 439 PetscFunctionReturn(0); 440 } 441 442 443 /* Note the Petsc r permutation is ignored */ 444 PetscErrorCode MatCholeskyFactorSymbolic_SBAIJPASTIX(Mat F,Mat A,IS r,const MatFactorInfo *info) 445 { 446 Mat_Pastix *lu = (Mat_Pastix*)(F)->data; 447 448 PetscFunctionBegin; 449 lu->iparm[IPARM_FACTORIZATION] = API_FACT_LLT; 450 lu->iparm[IPARM_SYM] = API_SYM_NO; 451 lu->matstruc = DIFFERENT_NONZERO_PATTERN; 452 (F)->ops->choleskyfactornumeric = MatFactorNumeric_PaStiX; 453 PetscFunctionReturn(0); 454 } 455 456 PetscErrorCode MatView_PaStiX(Mat A,PetscViewer viewer) 457 { 458 PetscErrorCode ierr; 459 PetscBool iascii; 460 PetscViewerFormat format; 461 462 PetscFunctionBegin; 463 ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr); 464 if (iascii) { 465 ierr = PetscViewerGetFormat(viewer,&format);CHKERRQ(ierr); 466 if (format == PETSC_VIEWER_ASCII_INFO) { 467 Mat_Pastix *lu=(Mat_Pastix*)A->data; 468 469 ierr = PetscViewerASCIIPrintf(viewer,"PaStiX run parameters:\n");CHKERRQ(ierr); 470 ierr = PetscViewerASCIIPrintf(viewer," Matrix type : %s \n",((lu->iparm[IPARM_SYM] == API_SYM_YES) ? "Symmetric" : "Unsymmetric"));CHKERRQ(ierr); 471 ierr = PetscViewerASCIIPrintf(viewer," Level of printing (0,1,2): %d \n",lu->iparm[IPARM_VERBOSE]);CHKERRQ(ierr); 472 ierr = PetscViewerASCIIPrintf(viewer," Number of refinements iterations : %d \n",lu->iparm[IPARM_NBITER]);CHKERRQ(ierr); 473 ierr = PetscPrintf(PETSC_COMM_SELF," Error : %g \n",lu->dparm[DPARM_RELATIVE_ERROR]);CHKERRQ(ierr); 474 } 475 } 476 PetscFunctionReturn(0); 477 } 478 479 480 /*MC 481 MATSOLVERPASTIX - A solver package providing direct solvers (LU) for distributed 482 and sequential matrices via the external package PaStiX. 483 484 Use ./configure --download-pastix --download-ptscotch to have PETSc installed with PasTiX 485 486 Use -pc_type lu -pc_factor_mat_solver_type pastix to use this direct solver 487 488 Options Database Keys: 489 + -mat_pastix_verbose <0,1,2> - print level 490 - -mat_pastix_threadnbr <integer> - Set the thread number by MPI task. 491 492 Notes: 493 This only works for matrices with symmetric nonzero structure, if you pass it a matrix with 494 nonsymmetric structure PasTiX and hence PETSc return with an error. 495 496 Level: beginner 497 498 .seealso: PCFactorSetMatSolverType(), MatSolverType 499 500 M*/ 501 502 503 PetscErrorCode MatGetInfo_PaStiX(Mat A,MatInfoType flag,MatInfo *info) 504 { 505 Mat_Pastix *lu =(Mat_Pastix*)A->data; 506 507 PetscFunctionBegin; 508 info->block_size = 1.0; 509 info->nz_allocated = lu->iparm[IPARM_NNZEROS]; 510 info->nz_used = lu->iparm[IPARM_NNZEROS]; 511 info->nz_unneeded = 0.0; 512 info->assemblies = 0.0; 513 info->mallocs = 0.0; 514 info->memory = 0.0; 515 info->fill_ratio_given = 0; 516 info->fill_ratio_needed = 0; 517 info->factor_mallocs = 0; 518 PetscFunctionReturn(0); 519 } 520 521 static PetscErrorCode MatFactorGetSolverType_pastix(Mat A,MatSolverType *type) 522 { 523 PetscFunctionBegin; 524 *type = MATSOLVERPASTIX; 525 PetscFunctionReturn(0); 526 } 527 528 /* 529 The seq and mpi versions of this function are the same 530 */ 531 static PetscErrorCode MatGetFactor_seqaij_pastix(Mat A,MatFactorType ftype,Mat *F) 532 { 533 Mat B; 534 PetscErrorCode ierr; 535 Mat_Pastix *pastix; 536 537 PetscFunctionBegin; 538 if (ftype != MAT_FACTOR_LU) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot use PETSc AIJ matrices with PaStiX Cholesky, use SBAIJ matrix"); 539 /* Create the factorization matrix */ 540 ierr = MatCreate(PetscObjectComm((PetscObject)A),&B);CHKERRQ(ierr); 541 ierr = MatSetSizes(B,A->rmap->n,A->cmap->n,A->rmap->N,A->cmap->N);CHKERRQ(ierr); 542 ierr = PetscStrallocpy("pastix",&((PetscObject)B)->type_name);CHKERRQ(ierr); 543 ierr = MatSetUp(B);CHKERRQ(ierr); 544 545 B->ops->lufactorsymbolic = MatLUFactorSymbolic_AIJPASTIX; 546 B->ops->view = MatView_PaStiX; 547 B->ops->getinfo = MatGetInfo_PaStiX; 548 549 ierr = PetscObjectComposeFunction((PetscObject)B,"MatFactorGetSolverType_C",MatFactorGetSolverType_pastix);CHKERRQ(ierr); 550 551 B->factortype = MAT_FACTOR_LU; 552 553 /* set solvertype */ 554 ierr = PetscFree(B->solvertype);CHKERRQ(ierr); 555 ierr = PetscStrallocpy(MATSOLVERPASTIX,&B->solvertype);CHKERRQ(ierr); 556 557 ierr = PetscNewLog(B,&pastix);CHKERRQ(ierr); 558 559 pastix->CleanUpPastix = PETSC_FALSE; 560 pastix->scat_rhs = NULL; 561 pastix->scat_sol = NULL; 562 B->ops->getinfo = MatGetInfo_External; 563 B->ops->destroy = MatDestroy_Pastix; 564 B->data = (void*)pastix; 565 566 *F = B; 567 PetscFunctionReturn(0); 568 } 569 570 static PetscErrorCode MatGetFactor_mpiaij_pastix(Mat A,MatFactorType ftype,Mat *F) 571 { 572 Mat B; 573 PetscErrorCode ierr; 574 Mat_Pastix *pastix; 575 576 PetscFunctionBegin; 577 if (ftype != MAT_FACTOR_LU) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot use PETSc AIJ matrices with PaStiX Cholesky, use SBAIJ matrix"); 578 /* Create the factorization matrix */ 579 ierr = MatCreate(PetscObjectComm((PetscObject)A),&B);CHKERRQ(ierr); 580 ierr = MatSetSizes(B,A->rmap->n,A->cmap->n,A->rmap->N,A->cmap->N);CHKERRQ(ierr); 581 ierr = PetscStrallocpy("pastix",&((PetscObject)B)->type_name);CHKERRQ(ierr); 582 ierr = MatSetUp(B);CHKERRQ(ierr); 583 584 B->ops->lufactorsymbolic = MatLUFactorSymbolic_AIJPASTIX; 585 B->ops->view = MatView_PaStiX; 586 B->ops->getinfo = MatGetInfo_PaStiX; 587 ierr = PetscObjectComposeFunction((PetscObject)B,"MatFactorGetSolverType_C",MatFactorGetSolverType_pastix);CHKERRQ(ierr); 588 589 B->factortype = MAT_FACTOR_LU; 590 591 /* set solvertype */ 592 ierr = PetscFree(B->solvertype);CHKERRQ(ierr); 593 ierr = PetscStrallocpy(MATSOLVERPASTIX,&B->solvertype);CHKERRQ(ierr); 594 595 ierr = PetscNewLog(B,&pastix);CHKERRQ(ierr); 596 597 pastix->CleanUpPastix = PETSC_FALSE; 598 pastix->scat_rhs = NULL; 599 pastix->scat_sol = NULL; 600 B->ops->getinfo = MatGetInfo_External; 601 B->ops->destroy = MatDestroy_Pastix; 602 B->data = (void*)pastix; 603 604 *F = B; 605 PetscFunctionReturn(0); 606 } 607 608 static PetscErrorCode MatGetFactor_seqsbaij_pastix(Mat A,MatFactorType ftype,Mat *F) 609 { 610 Mat B; 611 PetscErrorCode ierr; 612 Mat_Pastix *pastix; 613 614 PetscFunctionBegin; 615 if (ftype != MAT_FACTOR_CHOLESKY) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot use PETSc SBAIJ matrices with PaStiX LU, use AIJ matrix"); 616 /* Create the factorization matrix */ 617 ierr = MatCreate(PetscObjectComm((PetscObject)A),&B);CHKERRQ(ierr); 618 ierr = MatSetSizes(B,A->rmap->n,A->cmap->n,A->rmap->N,A->cmap->N);CHKERRQ(ierr); 619 ierr = PetscStrallocpy("pastix",&((PetscObject)B)->type_name);CHKERRQ(ierr); 620 ierr = MatSetUp(B);CHKERRQ(ierr); 621 622 B->ops->choleskyfactorsymbolic = MatCholeskyFactorSymbolic_SBAIJPASTIX; 623 B->ops->view = MatView_PaStiX; 624 B->ops->getinfo = MatGetInfo_PaStiX; 625 ierr = PetscObjectComposeFunction((PetscObject)B,"MatFactorGetSolverType_C",MatFactorGetSolverType_pastix);CHKERRQ(ierr); 626 627 B->factortype = MAT_FACTOR_CHOLESKY; 628 629 /* set solvertype */ 630 ierr = PetscFree(B->solvertype);CHKERRQ(ierr); 631 ierr = PetscStrallocpy(MATSOLVERPASTIX,&B->solvertype);CHKERRQ(ierr); 632 633 ierr = PetscNewLog(B,&pastix);CHKERRQ(ierr); 634 635 pastix->CleanUpPastix = PETSC_FALSE; 636 pastix->scat_rhs = NULL; 637 pastix->scat_sol = NULL; 638 B->ops->getinfo = MatGetInfo_External; 639 B->ops->destroy = MatDestroy_Pastix; 640 B->data = (void*)pastix; 641 642 *F = B; 643 PetscFunctionReturn(0); 644 } 645 646 static PetscErrorCode MatGetFactor_mpisbaij_pastix(Mat A,MatFactorType ftype,Mat *F) 647 { 648 Mat B; 649 PetscErrorCode ierr; 650 Mat_Pastix *pastix; 651 652 PetscFunctionBegin; 653 if (ftype != MAT_FACTOR_CHOLESKY) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot use PETSc SBAIJ matrices with PaStiX LU, use AIJ matrix"); 654 655 /* Create the factorization matrix */ 656 ierr = MatCreate(PetscObjectComm((PetscObject)A),&B);CHKERRQ(ierr); 657 ierr = MatSetSizes(B,A->rmap->n,A->cmap->n,A->rmap->N,A->cmap->N);CHKERRQ(ierr); 658 ierr = PetscStrallocpy("pastix",&((PetscObject)B)->type_name);CHKERRQ(ierr); 659 ierr = MatSetUp(B);CHKERRQ(ierr); 660 661 B->ops->choleskyfactorsymbolic = MatCholeskyFactorSymbolic_SBAIJPASTIX; 662 B->ops->view = MatView_PaStiX; 663 B->ops->getinfo = MatGetInfo_PaStiX; 664 B->ops->destroy = MatDestroy_Pastix; 665 ierr = PetscObjectComposeFunction((PetscObject)B,"MatFactorGetSolverType_C",MatFactorGetSolverType_pastix);CHKERRQ(ierr); 666 667 B->factortype = MAT_FACTOR_CHOLESKY; 668 669 /* set solvertype */ 670 ierr = PetscFree(B->solvertype);CHKERRQ(ierr); 671 ierr = PetscStrallocpy(MATSOLVERPASTIX,&B->solvertype);CHKERRQ(ierr); 672 673 ierr = PetscNewLog(B,&pastix);CHKERRQ(ierr); 674 675 pastix->CleanUpPastix = PETSC_FALSE; 676 pastix->scat_rhs = NULL; 677 pastix->scat_sol = NULL; 678 B->data = (void*)pastix; 679 680 *F = B; 681 PetscFunctionReturn(0); 682 } 683 684 PETSC_EXTERN PetscErrorCode MatSolverTypeRegister_Pastix(void) 685 { 686 PetscErrorCode ierr; 687 688 PetscFunctionBegin; 689 ierr = MatSolverTypeRegister(MATSOLVERPASTIX,MATMPIAIJ, MAT_FACTOR_LU,MatGetFactor_mpiaij_pastix);CHKERRQ(ierr); 690 ierr = MatSolverTypeRegister(MATSOLVERPASTIX,MATSEQAIJ, MAT_FACTOR_LU,MatGetFactor_seqaij_pastix);CHKERRQ(ierr); 691 ierr = MatSolverTypeRegister(MATSOLVERPASTIX,MATMPISBAIJ, MAT_FACTOR_CHOLESKY,MatGetFactor_mpisbaij_pastix);CHKERRQ(ierr); 692 ierr = MatSolverTypeRegister(MATSOLVERPASTIX,MATSEQSBAIJ, MAT_FACTOR_CHOLESKY,MatGetFactor_seqsbaij_pastix);CHKERRQ(ierr); 693 PetscFunctionReturn(0); 694 } 695