1 #define PETSCMAT_DLL 2 3 /* -------------------------------------------------------------------- 4 5 This file implements a subclass of the SeqAIJ matrix class that uses 6 the SuperLU 3.0 sparse solver. You can use this as a starting point for 7 implementing your own subclass of a PETSc matrix class. 8 9 This demonstrates a way to make an implementation inheritence of a PETSc 10 matrix type. This means constructing a new matrix type (SuperLU) by changing some 11 of the methods of the previous type (SeqAIJ), adding additional data, and possibly 12 additional method. (See any book on object oriented programming). 13 */ 14 15 /* 16 Defines the data structure for the base matrix type (SeqAIJ) 17 */ 18 #include "src/mat/impls/aij/seq/aij.h" 19 20 /* 21 SuperLU include files 22 */ 23 EXTERN_C_BEGIN 24 #if defined(PETSC_USE_COMPLEX) 25 #include "slu_zdefs.h" 26 #else 27 #include "slu_ddefs.h" 28 #endif 29 #include "slu_util.h" 30 EXTERN_C_END 31 32 /* 33 This is the data we are "ADDING" to the SeqAIJ matrix type to get the SuperLU matrix type 34 */ 35 typedef struct { 36 SuperMatrix A,L,U,B,X; 37 superlu_options_t options; 38 PetscInt *perm_c; /* column permutation vector */ 39 PetscInt *perm_r; /* row permutations from partial pivoting */ 40 PetscInt *etree; 41 PetscReal *R, *C; 42 char equed[1]; 43 PetscInt lwork; 44 void *work; 45 PetscReal rpg, rcond; 46 mem_usage_t mem_usage; 47 MatStructure flg; 48 49 /* Flag to clean up (non-global) SuperLU objects during Destroy */ 50 PetscTruth CleanUpSuperLU; 51 } Mat_SuperLU; 52 53 extern PetscErrorCode MatFactorInfo_SuperLU(Mat,PetscViewer); 54 extern PetscErrorCode MatLUFactorNumeric_SuperLU(Mat,Mat,MatFactorInfo *); 55 extern PetscErrorCode MatDestroy_SuperLU(Mat); 56 extern PetscErrorCode MatView_SuperLU(Mat,PetscViewer); 57 extern PetscErrorCode MatAssemblyEnd_SuperLU(Mat,MatAssemblyType); 58 extern PetscErrorCode MatSolve_SuperLU(Mat,Vec,Vec); 59 extern PetscErrorCode MatSolveTranspose_SuperLU(Mat,Vec,Vec); 60 extern PetscErrorCode MatLUFactorSymbolic_SuperLU(Mat,Mat,IS,IS,MatFactorInfo*); 61 extern PetscErrorCode MatDuplicate_SuperLU(Mat, MatDuplicateOption, Mat *); 62 63 /* 64 Utility function 65 */ 66 #undef __FUNCT__ 67 #define __FUNCT__ "MatFactorInfo_SuperLU" 68 PetscErrorCode MatFactorInfo_SuperLU(Mat A,PetscViewer viewer) 69 { 70 Mat_SuperLU *lu= (Mat_SuperLU*)A->spptr; 71 PetscErrorCode ierr; 72 superlu_options_t options; 73 74 PetscFunctionBegin; 75 /* check if matrix is superlu_dist type */ 76 if (A->ops->solve != MatSolve_SuperLU) PetscFunctionReturn(0); 77 78 options = lu->options; 79 ierr = PetscViewerASCIIPrintf(viewer,"SuperLU run parameters:\n");CHKERRQ(ierr); 80 ierr = PetscViewerASCIIPrintf(viewer," Equil: %s\n",(options.Equil != NO) ? "YES": "NO");CHKERRQ(ierr); 81 ierr = PetscViewerASCIIPrintf(viewer," ColPerm: %D\n",options.ColPerm);CHKERRQ(ierr); 82 ierr = PetscViewerASCIIPrintf(viewer," IterRefine: %D\n",options.IterRefine);CHKERRQ(ierr); 83 ierr = PetscViewerASCIIPrintf(viewer," SymmetricMode: %s\n",(options.SymmetricMode != NO) ? "YES": "NO");CHKERRQ(ierr); 84 ierr = PetscViewerASCIIPrintf(viewer," DiagPivotThresh: %g\n",options.DiagPivotThresh);CHKERRQ(ierr); 85 ierr = PetscViewerASCIIPrintf(viewer," PivotGrowth: %s\n",(options.PivotGrowth != NO) ? "YES": "NO");CHKERRQ(ierr); 86 ierr = PetscViewerASCIIPrintf(viewer," ConditionNumber: %s\n",(options.ConditionNumber != NO) ? "YES": "NO");CHKERRQ(ierr); 87 ierr = PetscViewerASCIIPrintf(viewer," RowPerm: %D\n",options.RowPerm);CHKERRQ(ierr); 88 ierr = PetscViewerASCIIPrintf(viewer," ReplaceTinyPivot: %s\n",(options.ReplaceTinyPivot != NO) ? "YES": "NO");CHKERRQ(ierr); 89 ierr = PetscViewerASCIIPrintf(viewer," PrintStat: %s\n",(options.PrintStat != NO) ? "YES": "NO");CHKERRQ(ierr); 90 ierr = PetscViewerASCIIPrintf(viewer," lwork: %D\n",lu->lwork);CHKERRQ(ierr); 91 92 PetscFunctionReturn(0); 93 } 94 95 /* 96 These are the methods provided to REPLACE the corresponding methods of the 97 SeqAIJ matrix class. Other methods of SeqAIJ are not replaced 98 */ 99 #undef __FUNCT__ 100 #define __FUNCT__ "MatLUFactorNumeric_SuperLU" 101 PetscErrorCode MatLUFactorNumeric_SuperLU(Mat F,Mat A,MatFactorInfo *info) 102 { 103 Mat_SeqAIJ *aa = (Mat_SeqAIJ*)(A)->data; 104 Mat_SuperLU *lu = (Mat_SuperLU*)(F)->spptr; 105 PetscErrorCode ierr; 106 PetscInt sinfo; 107 SuperLUStat_t stat; 108 PetscReal ferr, berr; 109 NCformat *Ustore; 110 SCformat *Lstore; 111 112 PetscFunctionBegin; 113 if (lu->flg == SAME_NONZERO_PATTERN){ /* successing numerical factorization */ 114 lu->options.Fact = SamePattern; 115 /* Ref: ~SuperLU_3.0/EXAMPLE/dlinsolx2.c */ 116 Destroy_SuperMatrix_Store(&lu->A); 117 if ( lu->lwork >= 0 ) { 118 Destroy_SuperNode_Matrix(&lu->L); 119 Destroy_CompCol_Matrix(&lu->U); 120 lu->options.Fact = SamePattern; 121 } 122 } 123 124 /* Create the SuperMatrix for lu->A=A^T: 125 Since SuperLU likes column-oriented matrices,we pass it the transpose, 126 and then solve A^T X = B in MatSolve(). */ 127 #if defined(PETSC_USE_COMPLEX) 128 zCreate_CompCol_Matrix(&lu->A,A->cmap->n,A->rmap->n,aa->nz,(doublecomplex*)aa->a,aa->j,aa->i, 129 SLU_NC,SLU_Z,SLU_GE); 130 #else 131 dCreate_CompCol_Matrix(&lu->A,A->cmap->n,A->rmap->n,aa->nz,aa->a,aa->j,aa->i, 132 SLU_NC,SLU_D,SLU_GE); 133 #endif 134 135 /* Initialize the statistics variables. */ 136 StatInit(&stat); 137 138 /* Numerical factorization */ 139 lu->B.ncol = 0; /* Indicate not to solve the system */ 140 #if defined(PETSC_USE_COMPLEX) 141 zgssvx(&lu->options, &lu->A, lu->perm_c, lu->perm_r, lu->etree, lu->equed, lu->R, lu->C, 142 &lu->L, &lu->U, lu->work, lu->lwork, &lu->B, &lu->X, &lu->rpg, &lu->rcond, &ferr, &berr, 143 &lu->mem_usage, &stat, &sinfo); 144 #else 145 dgssvx(&lu->options, &lu->A, lu->perm_c, lu->perm_r, lu->etree, lu->equed, lu->R, lu->C, 146 &lu->L, &lu->U, lu->work, lu->lwork, &lu->B, &lu->X, &lu->rpg, &lu->rcond, &ferr, &berr, 147 &lu->mem_usage, &stat, &sinfo); 148 #endif 149 if ( !sinfo || sinfo == lu->A.ncol+1 ) { 150 if ( lu->options.PivotGrowth ) 151 ierr = PetscPrintf(PETSC_COMM_SELF," Recip. pivot growth = %e\n", lu->rpg); 152 if ( lu->options.ConditionNumber ) 153 ierr = PetscPrintf(PETSC_COMM_SELF," Recip. condition number = %e\n", lu->rcond); 154 } else if ( sinfo > 0 ){ 155 if ( lu->lwork == -1 ) { 156 ierr = PetscPrintf(PETSC_COMM_SELF," ** Estimated memory: %D bytes\n", sinfo - lu->A.ncol); 157 } else { 158 ierr = PetscPrintf(PETSC_COMM_SELF," Warning: gssvx() returns info %D\n",sinfo); 159 } 160 } else { /* sinfo < 0 */ 161 SETERRQ2(PETSC_ERR_LIB, "info = %D, the %D-th argument in gssvx() had an illegal value", sinfo,-sinfo); 162 } 163 164 if ( lu->options.PrintStat ) { 165 ierr = PetscPrintf(PETSC_COMM_SELF,"MatLUFactorNumeric_SuperLU():\n"); 166 StatPrint(&stat); 167 Lstore = (SCformat *) lu->L.Store; 168 Ustore = (NCformat *) lu->U.Store; 169 ierr = PetscPrintf(PETSC_COMM_SELF," No of nonzeros in factor L = %D\n", Lstore->nnz); 170 ierr = PetscPrintf(PETSC_COMM_SELF," No of nonzeros in factor U = %D\n", Ustore->nnz); 171 ierr = PetscPrintf(PETSC_COMM_SELF," No of nonzeros in L+U = %D\n", Lstore->nnz + Ustore->nnz - lu->A.ncol); 172 ierr = PetscPrintf(PETSC_COMM_SELF," L\\U MB %.3f\ttotal MB needed %.3f\texpansions %D\n", 173 lu->mem_usage.for_lu/1e6, lu->mem_usage.total_needed/1e6, 174 lu->mem_usage.expansions); 175 } 176 StatFree(&stat); 177 178 lu->flg = SAME_NONZERO_PATTERN; 179 (F)->ops->solve = MatSolve_SuperLU; 180 (F)->ops->solvetranspose = MatSolveTranspose_SuperLU; 181 PetscFunctionReturn(0); 182 } 183 184 #undef __FUNCT__ 185 #define __FUNCT__ "MatDestroy_SuperLU" 186 PetscErrorCode MatDestroy_SuperLU(Mat A) 187 { 188 PetscErrorCode ierr; 189 Mat_SuperLU *lu=(Mat_SuperLU*)A->spptr; 190 191 PetscFunctionBegin; 192 if (lu->CleanUpSuperLU) { /* Free the SuperLU datastructures */ 193 Destroy_SuperMatrix_Store(&lu->A); 194 Destroy_SuperMatrix_Store(&lu->B); 195 Destroy_SuperMatrix_Store(&lu->X); 196 197 ierr = PetscFree(lu->etree);CHKERRQ(ierr); 198 ierr = PetscFree(lu->perm_r);CHKERRQ(ierr); 199 ierr = PetscFree(lu->perm_c);CHKERRQ(ierr); 200 ierr = PetscFree(lu->R);CHKERRQ(ierr); 201 ierr = PetscFree(lu->C);CHKERRQ(ierr); 202 if ( lu->lwork >= 0 ) { 203 Destroy_SuperNode_Matrix(&lu->L); 204 Destroy_CompCol_Matrix(&lu->U); 205 } 206 } 207 ierr = MatDestroy_SeqAIJ(A);CHKERRQ(ierr); 208 PetscFunctionReturn(0); 209 } 210 211 #undef __FUNCT__ 212 #define __FUNCT__ "MatView_SuperLU" 213 PetscErrorCode MatView_SuperLU(Mat A,PetscViewer viewer) 214 { 215 PetscErrorCode ierr; 216 PetscTruth iascii; 217 PetscViewerFormat format; 218 219 PetscFunctionBegin; 220 ierr = MatView_SeqAIJ(A,viewer);CHKERRQ(ierr); 221 222 ierr = PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_ASCII,&iascii);CHKERRQ(ierr); 223 if (iascii) { 224 ierr = PetscViewerGetFormat(viewer,&format);CHKERRQ(ierr); 225 if (format == PETSC_VIEWER_ASCII_INFO) { 226 ierr = MatFactorInfo_SuperLU(A,viewer);CHKERRQ(ierr); 227 } 228 } 229 PetscFunctionReturn(0); 230 } 231 232 233 #undef __FUNCT__ 234 #define __FUNCT__ "MatSolve_SuperLU_Private" 235 PetscErrorCode MatSolve_SuperLU_Private(Mat A,Vec b,Vec x) 236 { 237 Mat_SuperLU *lu = (Mat_SuperLU*)A->spptr; 238 PetscScalar *barray,*xarray; 239 PetscErrorCode ierr; 240 PetscInt info,i; 241 SuperLUStat_t stat; 242 PetscReal ferr,berr; 243 244 PetscFunctionBegin; 245 if ( lu->lwork == -1 ) { 246 PetscFunctionReturn(0); 247 } 248 lu->B.ncol = 1; /* Set the number of right-hand side */ 249 ierr = VecGetArray(b,&barray);CHKERRQ(ierr); 250 ierr = VecGetArray(x,&xarray);CHKERRQ(ierr); 251 252 #if defined(PETSC_USE_COMPLEX) 253 ((DNformat*)lu->B.Store)->nzval = (doublecomplex*)barray; 254 ((DNformat*)lu->X.Store)->nzval = (doublecomplex*)xarray; 255 #else 256 ((DNformat*)lu->B.Store)->nzval = barray; 257 ((DNformat*)lu->X.Store)->nzval = xarray; 258 #endif 259 260 /* Initialize the statistics variables. */ 261 StatInit(&stat); 262 263 lu->options.Fact = FACTORED; /* Indicate the factored form of A is supplied. */ 264 #if defined(PETSC_USE_COMPLEX) 265 zgssvx(&lu->options, &lu->A, lu->perm_c, lu->perm_r, lu->etree, lu->equed, lu->R, lu->C, 266 &lu->L, &lu->U, lu->work, lu->lwork, &lu->B, &lu->X, &lu->rpg, &lu->rcond, &ferr, &berr, 267 &lu->mem_usage, &stat, &info); 268 #else 269 dgssvx(&lu->options, &lu->A, lu->perm_c, lu->perm_r, lu->etree, lu->equed, lu->R, lu->C, 270 &lu->L, &lu->U, lu->work, lu->lwork, &lu->B, &lu->X, &lu->rpg, &lu->rcond, &ferr, &berr, 271 &lu->mem_usage, &stat, &info); 272 #endif 273 ierr = VecRestoreArray(b,&barray);CHKERRQ(ierr); 274 ierr = VecRestoreArray(x,&xarray);CHKERRQ(ierr); 275 276 if ( !info || info == lu->A.ncol+1 ) { 277 if ( lu->options.IterRefine ) { 278 ierr = PetscPrintf(PETSC_COMM_SELF,"Iterative Refinement:\n"); 279 ierr = PetscPrintf(PETSC_COMM_SELF," %8s%8s%16s%16s\n", "rhs", "Steps", "FERR", "BERR"); 280 for (i = 0; i < 1; ++i) 281 ierr = PetscPrintf(PETSC_COMM_SELF," %8d%8d%16e%16e\n", i+1, stat.RefineSteps, ferr, berr); 282 } 283 } else if ( info > 0 ){ 284 if ( lu->lwork == -1 ) { 285 ierr = PetscPrintf(PETSC_COMM_SELF," ** Estimated memory: %D bytes\n", info - lu->A.ncol); 286 } else { 287 ierr = PetscPrintf(PETSC_COMM_SELF," Warning: gssvx() returns info %D\n",info); 288 } 289 } else if (info < 0){ 290 SETERRQ2(PETSC_ERR_LIB, "info = %D, the %D-th argument in gssvx() had an illegal value", info,-info); 291 } 292 293 if ( lu->options.PrintStat ) { 294 ierr = PetscPrintf(PETSC_COMM_SELF,"MatSolve__SuperLU():\n"); 295 StatPrint(&stat); 296 } 297 StatFree(&stat); 298 PetscFunctionReturn(0); 299 } 300 301 #undef __FUNCT__ 302 #define __FUNCT__ "MatSolve_SuperLU" 303 PetscErrorCode MatSolve_SuperLU(Mat A,Vec b,Vec x) 304 { 305 Mat_SuperLU *lu = (Mat_SuperLU*)A->spptr; 306 PetscErrorCode ierr; 307 308 PetscFunctionBegin; 309 lu->options.Trans = TRANS; 310 ierr = MatSolve_SuperLU_Private(A,b,x);CHKERRQ(ierr); 311 PetscFunctionReturn(0); 312 } 313 314 #undef __FUNCT__ 315 #define __FUNCT__ "MatSolveTranspose_SuperLU" 316 PetscErrorCode MatSolveTranspose_SuperLU(Mat A,Vec b,Vec x) 317 { 318 Mat_SuperLU *lu = (Mat_SuperLU*)A->spptr; 319 PetscErrorCode ierr; 320 321 PetscFunctionBegin; 322 lu->options.Trans = NOTRANS; 323 ierr = MatSolve_SuperLU_Private(A,b,x);CHKERRQ(ierr); 324 PetscFunctionReturn(0); 325 } 326 327 328 /* 329 Note the r permutation is ignored 330 */ 331 #undef __FUNCT__ 332 #define __FUNCT__ "MatLUFactorSymbolic_SuperLU" 333 PetscErrorCode MatLUFactorSymbolic_SuperLU(Mat F,Mat A,IS r,IS c,MatFactorInfo *info) 334 { 335 Mat_SuperLU *lu = (Mat_SuperLU*)((F)->spptr); 336 PetscErrorCode ierr; 337 PetscInt m=A->rmap->n,n=A->cmap->n; 338 339 PetscFunctionBegin; 340 341 /* Allocate spaces (notice sizes are for the transpose) */ 342 ierr = PetscMalloc(m*sizeof(PetscInt),&lu->etree);CHKERRQ(ierr); 343 ierr = PetscMalloc(n*sizeof(PetscInt),&lu->perm_r);CHKERRQ(ierr); 344 ierr = PetscMalloc(m*sizeof(PetscInt),&lu->perm_c);CHKERRQ(ierr); 345 ierr = PetscMalloc(n*sizeof(PetscInt),&lu->R);CHKERRQ(ierr); 346 ierr = PetscMalloc(m*sizeof(PetscInt),&lu->C);CHKERRQ(ierr); 347 348 /* create rhs and solution x without allocate space for .Store */ 349 #if defined(PETSC_USE_COMPLEX) 350 zCreate_Dense_Matrix(&lu->B, m, 1, PETSC_NULL, m, SLU_DN, SLU_Z, SLU_GE); 351 zCreate_Dense_Matrix(&lu->X, m, 1, PETSC_NULL, m, SLU_DN, SLU_Z, SLU_GE); 352 #else 353 dCreate_Dense_Matrix(&lu->B, m, 1, PETSC_NULL, m, SLU_DN, SLU_D, SLU_GE); 354 dCreate_Dense_Matrix(&lu->X, m, 1, PETSC_NULL, m, SLU_DN, SLU_D, SLU_GE); 355 #endif 356 357 lu->flg = DIFFERENT_NONZERO_PATTERN; 358 lu->CleanUpSuperLU = PETSC_TRUE; 359 (F)->ops->lufactornumeric = MatLUFactorNumeric_SuperLU; 360 PetscFunctionReturn(0); 361 } 362 363 364 /*MC 365 MAT_SOLVER_SUPERLU = "superlu" - A matrix type providing direct solvers (LU) for sequential matrices 366 via the external package SuperLU. 367 368 Use config/configure.py --download-superlu to have PETSc installed with SuperLU 369 370 Options Database Keys: 371 + -mat_superlu_ordering <0,1,2,3> - 0: natural ordering, 372 1: MMD applied to A'*A, 373 2: MMD applied to A'+A, 374 3: COLAMD, approximate minimum degree column ordering 375 . -mat_superlu_iterrefine - have SuperLU do iterative refinement after the triangular solve 376 choices: NOREFINE, SINGLE, DOUBLE, EXTRA; default is NOREFINE 377 - -mat_superlu_printstat - print SuperLU statistics about the factorization 378 379 Notes: Do not confuse this with MAT_SOLVER_SUPERLU_DIST which is for parallel sparse solves 380 381 Level: beginner 382 383 .seealso: PCLU, MAT_SOLVER_SUPERLU_DIST, MAT_SOLVER_MUMPS, MAT_SOLVER_SPOOLES 384 M*/ 385 386 EXTERN_C_BEGIN 387 #undef __FUNCT__ 388 #define __FUNCT__ "MatGetFactor_seqaij_superlu" 389 PetscErrorCode MatGetFactor_seqaij_superlu(Mat A,MatFactorType ftype,Mat *F) 390 { 391 Mat B; 392 Mat_SuperLU *lu; 393 PetscErrorCode ierr; 394 PetscInt indx; 395 PetscTruth flg; 396 const char *colperm[]={"NATURAL","MMD_ATA","MMD_AT_PLUS_A","COLAMD"}; /* MY_PERMC - not supported by the petsc interface yet */ 397 const char *iterrefine[]={"NOREFINE", "SINGLE", "DOUBLE", "EXTRA"}; 398 const char *rowperm[]={"NOROWPERM", "LargeDiag"}; /* MY_PERMC - not supported by the petsc interface yet */ 399 400 PetscFunctionBegin; 401 ierr = MatCreate(((PetscObject)A)->comm,&B);CHKERRQ(ierr); 402 ierr = MatSetSizes(B,A->rmap->n,A->cmap->n,PETSC_DETERMINE,PETSC_DETERMINE);CHKERRQ(ierr); 403 ierr = MatSetType(B,((PetscObject)A)->type_name);CHKERRQ(ierr); 404 ierr = MatSeqAIJSetPreallocation(B,0,PETSC_NULL);CHKERRQ(ierr); 405 406 B->ops->lufactorsymbolic = MatLUFactorSymbolic_SuperLU; 407 B->ops->destroy = MatDestroy_SuperLU; 408 B->factor = MAT_FACTOR_LU; 409 B->assembled = PETSC_TRUE; /* required by -ksp_view */ 410 B->preallocated = PETSC_TRUE; 411 412 ierr = PetscNewLog(B,Mat_SuperLU,&lu);CHKERRQ(ierr); 413 set_default_options(&lu->options); 414 /* equilibration causes error in solve(), thus not supported here. See dgssvx.c for possible reason. */ 415 lu->options.Equil = NO; 416 lu->options.PrintStat = NO; 417 lu->lwork = 0; /* allocate space internally by system malloc */ 418 419 ierr = PetscOptionsBegin(((PetscObject)A)->comm,((PetscObject)A)->prefix,"SuperLU Options","Mat");CHKERRQ(ierr); 420 ierr = PetscOptionsEList("-mat_superlu_colperm","ColPerm","None",colperm,4,colperm[3],&indx,&flg);CHKERRQ(ierr); 421 if (flg) {lu->options.ColPerm = (colperm_t)indx;} 422 ierr = PetscOptionsEList("-mat_superlu_iterrefine","IterRefine","None",iterrefine,4,iterrefine[0],&indx,&flg);CHKERRQ(ierr); 423 if (flg) { lu->options.IterRefine = (IterRefine_t)indx;} 424 ierr = PetscOptionsTruth("-mat_superlu_symmetricmode","SymmetricMode","None",PETSC_FALSE,&flg,0);CHKERRQ(ierr); 425 if (flg) lu->options.SymmetricMode = YES; 426 ierr = PetscOptionsReal("-mat_superlu_diagpivotthresh","DiagPivotThresh","None",lu->options.DiagPivotThresh,&lu->options.DiagPivotThresh,PETSC_NULL);CHKERRQ(ierr); 427 ierr = PetscOptionsTruth("-mat_superlu_pivotgrowth","PivotGrowth","None",PETSC_FALSE,&flg,0);CHKERRQ(ierr); 428 if (flg) lu->options.PivotGrowth = YES; 429 ierr = PetscOptionsTruth("-mat_superlu_conditionnumber","ConditionNumber","None",PETSC_FALSE,&flg,0);CHKERRQ(ierr); 430 if (flg) lu->options.ConditionNumber = YES; 431 ierr = PetscOptionsEList("-mat_superlu_rowperm","rowperm","None",rowperm,2,rowperm[0],&indx,&flg);CHKERRQ(ierr); 432 if (flg) {lu->options.RowPerm = (rowperm_t)indx;} 433 ierr = PetscOptionsTruth("-mat_superlu_replacetinypivot","ReplaceTinyPivot","None",PETSC_FALSE,&flg,0);CHKERRQ(ierr); 434 if (flg) lu->options.ReplaceTinyPivot = YES; 435 ierr = PetscOptionsTruth("-mat_superlu_printstat","PrintStat","None",PETSC_FALSE,&flg,0);CHKERRQ(ierr); 436 if (flg) lu->options.PrintStat = YES; 437 ierr = PetscOptionsInt("-mat_superlu_lwork","size of work array in bytes used by factorization","None",lu->lwork,&lu->lwork,PETSC_NULL);CHKERRQ(ierr); 438 if (lu->lwork > 0 ){ 439 ierr = PetscMalloc(lu->lwork,&lu->work);CHKERRQ(ierr); 440 } else if (lu->lwork != 0 && lu->lwork != -1){ 441 ierr = PetscPrintf(PETSC_COMM_SELF," Warning: lwork %D is not supported by SUPERLU. The default lwork=0 is used.\n",lu->lwork); 442 lu->lwork = 0; 443 } 444 PetscOptionsEnd(); 445 446 #ifdef SUPERLU2 447 ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatCreateNull","MatCreateNull_SuperLU",(void(*)(void))MatCreateNull_SuperLU);CHKERRQ(ierr); 448 #endif 449 B->spptr = lu; 450 *F = B; 451 PetscFunctionReturn(0); 452 } 453 EXTERN_C_END 454