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