1 #define PETSCMAT_DLL 2 3 /* -------------------------------------------------------------------- 4 5 This file implements a subclass of the SeqAIJ matrix class that uses 6 the SuperLU 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 SuperLUStat_t stat; 49 Mat A_dup; 50 PetscScalar *rhs_dup; 51 52 /* Flag to clean up (non-global) SuperLU objects during Destroy */ 53 PetscBool CleanUpSuperLU; 54 } Mat_SuperLU; 55 56 extern PetscErrorCode MatFactorInfo_SuperLU(Mat,PetscViewer); 57 extern PetscErrorCode MatLUFactorNumeric_SuperLU(Mat,Mat,const MatFactorInfo *); 58 extern PetscErrorCode MatDestroy_SuperLU(Mat); 59 extern PetscErrorCode MatView_SuperLU(Mat,PetscViewer); 60 extern PetscErrorCode MatAssemblyEnd_SuperLU(Mat,MatAssemblyType); 61 extern PetscErrorCode MatSolve_SuperLU(Mat,Vec,Vec); 62 extern PetscErrorCode MatSolveTranspose_SuperLU(Mat,Vec,Vec); 63 extern PetscErrorCode MatLUFactorSymbolic_SuperLU(Mat,Mat,IS,IS,const MatFactorInfo*); 64 extern PetscErrorCode MatDuplicate_SuperLU(Mat, MatDuplicateOption, Mat *); 65 66 /* 67 Utility function 68 */ 69 #undef __FUNCT__ 70 #define __FUNCT__ "MatFactorInfo_SuperLU" 71 PetscErrorCode MatFactorInfo_SuperLU(Mat A,PetscViewer viewer) 72 { 73 Mat_SuperLU *lu= (Mat_SuperLU*)A->spptr; 74 PetscErrorCode ierr; 75 superlu_options_t options; 76 77 PetscFunctionBegin; 78 /* check if matrix is superlu_dist type */ 79 if (A->ops->solve != MatSolve_SuperLU) PetscFunctionReturn(0); 80 81 options = lu->options; 82 ierr = PetscViewerASCIIPrintf(viewer,"SuperLU run parameters:\n");CHKERRQ(ierr); 83 ierr = PetscViewerASCIIPrintf(viewer," Equil: %s\n",(options.Equil != NO) ? "YES": "NO");CHKERRQ(ierr); 84 ierr = PetscViewerASCIIPrintf(viewer," ColPerm: %D\n",options.ColPerm);CHKERRQ(ierr); 85 ierr = PetscViewerASCIIPrintf(viewer," IterRefine: %D\n",options.IterRefine);CHKERRQ(ierr); 86 ierr = PetscViewerASCIIPrintf(viewer," SymmetricMode: %s\n",(options.SymmetricMode != NO) ? "YES": "NO");CHKERRQ(ierr); 87 ierr = PetscViewerASCIIPrintf(viewer," DiagPivotThresh: %g\n",options.DiagPivotThresh);CHKERRQ(ierr); 88 ierr = PetscViewerASCIIPrintf(viewer," PivotGrowth: %s\n",(options.PivotGrowth != NO) ? "YES": "NO");CHKERRQ(ierr); 89 ierr = PetscViewerASCIIPrintf(viewer," ConditionNumber: %s\n",(options.ConditionNumber != NO) ? "YES": "NO");CHKERRQ(ierr); 90 ierr = PetscViewerASCIIPrintf(viewer," RowPerm: %D\n",options.RowPerm);CHKERRQ(ierr); 91 ierr = PetscViewerASCIIPrintf(viewer," ReplaceTinyPivot: %s\n",(options.ReplaceTinyPivot != NO) ? "YES": "NO");CHKERRQ(ierr); 92 ierr = PetscViewerASCIIPrintf(viewer," PrintStat: %s\n",(options.PrintStat != NO) ? "YES": "NO");CHKERRQ(ierr); 93 ierr = PetscViewerASCIIPrintf(viewer," lwork: %D\n",lu->lwork);CHKERRQ(ierr); 94 if (A->factortype == MAT_FACTOR_ILU){ 95 ierr = PetscViewerASCIIPrintf(viewer," ILU_DropTol: %g\n",options.ILU_DropTol);CHKERRQ(ierr); 96 ierr = PetscViewerASCIIPrintf(viewer," ILU_FillTol: %g\n",options.ILU_FillTol);CHKERRQ(ierr); 97 ierr = PetscViewerASCIIPrintf(viewer," ILU_FillFactor: %g\n",options.ILU_FillFactor);CHKERRQ(ierr); 98 ierr = PetscViewerASCIIPrintf(viewer," ILU_DropRule: %D\n",options.ILU_DropRule);CHKERRQ(ierr); 99 ierr = PetscViewerASCIIPrintf(viewer," ILU_Norm: %D\n",options.ILU_Norm);CHKERRQ(ierr); 100 ierr = PetscViewerASCIIPrintf(viewer," ILU_MILU: %D\n",options.ILU_MILU);CHKERRQ(ierr); 101 } 102 PetscFunctionReturn(0); 103 } 104 105 /* 106 These are the methods provided to REPLACE the corresponding methods of the 107 SeqAIJ matrix class. Other methods of SeqAIJ are not replaced 108 */ 109 #undef __FUNCT__ 110 #define __FUNCT__ "MatLUFactorNumeric_SuperLU" 111 PetscErrorCode MatLUFactorNumeric_SuperLU(Mat F,Mat A,const MatFactorInfo *info) 112 { 113 Mat_SuperLU *lu = (Mat_SuperLU*)(F)->spptr; 114 Mat_SeqAIJ *aa; 115 PetscErrorCode ierr; 116 PetscInt sinfo; 117 PetscReal ferr, berr; 118 NCformat *Ustore; 119 SCformat *Lstore; 120 121 PetscFunctionBegin; 122 if (lu->flg == SAME_NONZERO_PATTERN){ /* successing numerical factorization */ 123 lu->options.Fact = SamePattern; 124 /* Ref: ~SuperLU_3.0/EXAMPLE/dlinsolx2.c */ 125 Destroy_SuperMatrix_Store(&lu->A); 126 if (lu->options.Equil){ 127 ierr = MatCopy_SeqAIJ(A,lu->A_dup,SAME_NONZERO_PATTERN);CHKERRQ(ierr); 128 } 129 if ( lu->lwork >= 0 ) { 130 Destroy_SuperNode_Matrix(&lu->L); 131 Destroy_CompCol_Matrix(&lu->U); 132 lu->options.Fact = SamePattern; 133 } 134 } 135 136 /* Create the SuperMatrix for lu->A=A^T: 137 Since SuperLU likes column-oriented matrices,we pass it the transpose, 138 and then solve A^T X = B in MatSolve(). */ 139 if (lu->options.Equil){ 140 aa = (Mat_SeqAIJ*)(lu->A_dup)->data; 141 } else { 142 aa = (Mat_SeqAIJ*)(A)->data; 143 } 144 #if defined(PETSC_USE_COMPLEX) 145 zCreate_CompCol_Matrix(&lu->A,A->cmap->n,A->rmap->n,aa->nz,(doublecomplex*)aa->a,aa->j,aa->i, 146 SLU_NC,SLU_Z,SLU_GE); 147 #else 148 dCreate_CompCol_Matrix(&lu->A,A->cmap->n,A->rmap->n,aa->nz,aa->a,aa->j,aa->i, 149 SLU_NC,SLU_D,SLU_GE); 150 #endif 151 152 /* Numerical factorization */ 153 lu->B.ncol = 0; /* Indicate not to solve the system */ 154 if (F->factortype == MAT_FACTOR_LU){ 155 #if defined(PETSC_USE_COMPLEX) 156 zgssvx(&lu->options, &lu->A, lu->perm_c, lu->perm_r, lu->etree, lu->equed, lu->R, lu->C, 157 &lu->L, &lu->U, lu->work, lu->lwork, &lu->B, &lu->X, &lu->rpg, &lu->rcond, &ferr, &berr, 158 &lu->mem_usage, &lu->stat, &sinfo); 159 #else 160 dgssvx(&lu->options, &lu->A, lu->perm_c, lu->perm_r, lu->etree, lu->equed, lu->R, lu->C, 161 &lu->L, &lu->U, lu->work, lu->lwork, &lu->B, &lu->X, &lu->rpg, &lu->rcond, &ferr, &berr, 162 &lu->mem_usage, &lu->stat, &sinfo); 163 #endif 164 } else if (F->factortype == MAT_FACTOR_ILU){ 165 /* Compute the incomplete factorization, condition number and pivot growth */ 166 #if defined(PETSC_USE_COMPLEX) 167 zgsisx(&lu->options, &lu->A, lu->perm_c, lu->perm_r,lu->etree, lu->equed, lu->R, lu->C, 168 &lu->L, &lu->U, lu->work, lu->lwork, &lu->B, &lu->X, &lu->rpg, &lu->rcond, 169 &lu->mem_usage, &lu->stat, &sinfo); 170 #else 171 dgsisx(&lu->options, &lu->A, lu->perm_c, lu->perm_r, lu->etree, lu->equed, lu->R, lu->C, 172 &lu->L, &lu->U, lu->work, lu->lwork, &lu->B, &lu->X, &lu->rpg, &lu->rcond, 173 &lu->mem_usage, &lu->stat, &sinfo); 174 #endif 175 } else { 176 SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Factor type not supported"); 177 } 178 if ( !sinfo || sinfo == lu->A.ncol+1 ) { 179 if ( lu->options.PivotGrowth ) 180 ierr = PetscPrintf(PETSC_COMM_SELF," Recip. pivot growth = %e\n", lu->rpg); 181 if ( lu->options.ConditionNumber ) 182 ierr = PetscPrintf(PETSC_COMM_SELF," Recip. condition number = %e\n", lu->rcond); 183 } else if ( sinfo > 0 ){ 184 if ( lu->lwork == -1 ) { 185 ierr = PetscPrintf(PETSC_COMM_SELF," ** Estimated memory: %D bytes\n", sinfo - lu->A.ncol); 186 } else SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_MAT_LU_ZRPVT,"Zero pivot in row %D",sinfo); 187 } else { /* sinfo < 0 */ 188 SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_LIB, "info = %D, the %D-th argument in gssvx() had an illegal value", sinfo,-sinfo); 189 } 190 191 if ( lu->options.PrintStat ) { 192 ierr = PetscPrintf(PETSC_COMM_SELF,"MatLUFactorNumeric_SuperLU():\n"); 193 StatPrint(&lu->stat); 194 Lstore = (SCformat *) lu->L.Store; 195 Ustore = (NCformat *) lu->U.Store; 196 ierr = PetscPrintf(PETSC_COMM_SELF," No of nonzeros in factor L = %D\n", Lstore->nnz); 197 ierr = PetscPrintf(PETSC_COMM_SELF," No of nonzeros in factor U = %D\n", Ustore->nnz); 198 ierr = PetscPrintf(PETSC_COMM_SELF," No of nonzeros in L+U = %D\n", Lstore->nnz + Ustore->nnz - lu->A.ncol); 199 ierr = PetscPrintf(PETSC_COMM_SELF," L\\U MB %.3f\ttotal MB needed %.3f\n", 200 lu->mem_usage.for_lu/1e6, lu->mem_usage.total_needed/1e6); 201 } 202 203 lu->flg = SAME_NONZERO_PATTERN; 204 (F)->ops->solve = MatSolve_SuperLU; 205 (F)->ops->solvetranspose = MatSolveTranspose_SuperLU; 206 PetscFunctionReturn(0); 207 } 208 209 #undef __FUNCT__ 210 #define __FUNCT__ "MatDestroy_SuperLU" 211 PetscErrorCode MatDestroy_SuperLU(Mat A) 212 { 213 PetscErrorCode ierr; 214 Mat_SuperLU *lu=(Mat_SuperLU*)A->spptr; 215 216 PetscFunctionBegin; 217 if (lu->CleanUpSuperLU) { /* Free the SuperLU datastructures */ 218 Destroy_SuperMatrix_Store(&lu->A); 219 Destroy_SuperMatrix_Store(&lu->B); 220 Destroy_SuperMatrix_Store(&lu->X); 221 StatFree(&lu->stat); 222 if ( lu->lwork >= 0 ) { 223 Destroy_SuperNode_Matrix(&lu->L); 224 Destroy_CompCol_Matrix(&lu->U); 225 } 226 227 } 228 229 ierr = PetscFree(lu->etree);CHKERRQ(ierr); 230 ierr = PetscFree(lu->perm_r);CHKERRQ(ierr); 231 ierr = PetscFree(lu->perm_c);CHKERRQ(ierr); 232 ierr = PetscFree(lu->R);CHKERRQ(ierr); 233 ierr = PetscFree(lu->C);CHKERRQ(ierr); 234 235 ierr = MatDestroy_SeqAIJ(A);CHKERRQ(ierr); 236 if (lu->A_dup){ierr = MatDestroy(lu->A_dup);CHKERRQ(ierr);} 237 if (lu->rhs_dup){ierr = PetscFree(lu->rhs_dup);CHKERRQ(ierr);} 238 PetscFunctionReturn(0); 239 } 240 241 #undef __FUNCT__ 242 #define __FUNCT__ "MatView_SuperLU" 243 PetscErrorCode MatView_SuperLU(Mat A,PetscViewer viewer) 244 { 245 PetscErrorCode ierr; 246 PetscBool iascii; 247 PetscViewerFormat format; 248 249 PetscFunctionBegin; 250 ierr = PetscTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr); 251 if (iascii) { 252 ierr = PetscViewerGetFormat(viewer,&format);CHKERRQ(ierr); 253 if (format == PETSC_VIEWER_ASCII_INFO) { 254 ierr = MatFactorInfo_SuperLU(A,viewer);CHKERRQ(ierr); 255 } 256 } 257 PetscFunctionReturn(0); 258 } 259 260 261 #undef __FUNCT__ 262 #define __FUNCT__ "MatSolve_SuperLU_Private" 263 PetscErrorCode MatSolve_SuperLU_Private(Mat A,Vec b,Vec x) 264 { 265 Mat_SuperLU *lu = (Mat_SuperLU*)A->spptr; 266 PetscScalar *barray,*xarray; 267 PetscErrorCode ierr; 268 PetscInt info,i,n=x->map->n; 269 PetscReal ferr,berr; 270 271 PetscFunctionBegin; 272 if ( lu->lwork == -1 ) { 273 PetscFunctionReturn(0); 274 } 275 276 lu->B.ncol = 1; /* Set the number of right-hand side */ 277 if (lu->options.Equil && !lu->rhs_dup){ 278 /* superlu overwrites b when Equil is used, thus create rhs_dup to keep user's b unchanged */ 279 ierr = PetscMalloc(n*sizeof(PetscScalar),&lu->rhs_dup);CHKERRQ(ierr); 280 } 281 if (lu->options.Equil){ 282 /* Copy b into rsh_dup */ 283 ierr = VecGetArray(b,&barray);CHKERRQ(ierr); 284 ierr = PetscMemcpy(lu->rhs_dup,barray,n*sizeof(PetscScalar));CHKERRQ(ierr); 285 ierr = VecRestoreArray(b,&barray);CHKERRQ(ierr); 286 barray = lu->rhs_dup; 287 } else { 288 ierr = VecGetArray(b,&barray);CHKERRQ(ierr); 289 } 290 ierr = VecGetArray(x,&xarray);CHKERRQ(ierr); 291 292 #if defined(PETSC_USE_COMPLEX) 293 ((DNformat*)lu->B.Store)->nzval = (doublecomplex*)barray; 294 ((DNformat*)lu->X.Store)->nzval = (doublecomplex*)xarray; 295 #else 296 ((DNformat*)lu->B.Store)->nzval = barray; 297 ((DNformat*)lu->X.Store)->nzval = xarray; 298 #endif 299 300 lu->options.Fact = FACTORED; /* Indicate the factored form of A is supplied. */ 301 if (A->factortype == MAT_FACTOR_LU){ 302 #if defined(PETSC_USE_COMPLEX) 303 zgssvx(&lu->options, &lu->A, lu->perm_c, lu->perm_r, lu->etree, lu->equed, lu->R, lu->C, 304 &lu->L, &lu->U, lu->work, lu->lwork, &lu->B, &lu->X, &lu->rpg, &lu->rcond, &ferr, &berr, 305 &lu->mem_usage, &lu->stat, &info); 306 #else 307 dgssvx(&lu->options, &lu->A, lu->perm_c, lu->perm_r, lu->etree, lu->equed, lu->R, lu->C, 308 &lu->L, &lu->U, lu->work, lu->lwork, &lu->B, &lu->X, &lu->rpg, &lu->rcond, &ferr, &berr, 309 &lu->mem_usage, &lu->stat, &info); 310 #endif 311 } else if (A->factortype == MAT_FACTOR_ILU){ 312 #if defined(PETSC_USE_COMPLEX) 313 zgsisx(&lu->options, &lu->A, lu->perm_c, lu->perm_r, lu->etree, lu->equed, lu->R, lu->C, 314 &lu->L, &lu->U, lu->work, lu->lwork, &lu->B, &lu->X, &lu->rpg, &lu->rcond, 315 &lu->mem_usage, &lu->stat, &info); 316 #else 317 dgsisx(&lu->options, &lu->A, lu->perm_c, lu->perm_r, lu->etree, lu->equed, lu->R, lu->C, 318 &lu->L, &lu->U, lu->work, lu->lwork, &lu->B, &lu->X, &lu->rpg, &lu->rcond, 319 &lu->mem_usage, &lu->stat, &info); 320 #endif 321 } else { 322 SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Factor type not supported"); 323 } 324 if (!lu->options.Equil){ 325 ierr = VecRestoreArray(b,&barray);CHKERRQ(ierr); 326 } 327 ierr = VecRestoreArray(x,&xarray);CHKERRQ(ierr); 328 329 if ( !info || info == lu->A.ncol+1 ) { 330 if ( lu->options.IterRefine ) { 331 ierr = PetscPrintf(PETSC_COMM_SELF,"Iterative Refinement:\n"); 332 ierr = PetscPrintf(PETSC_COMM_SELF," %8s%8s%16s%16s\n", "rhs", "Steps", "FERR", "BERR"); 333 for (i = 0; i < 1; ++i) 334 ierr = PetscPrintf(PETSC_COMM_SELF," %8d%8d%16e%16e\n", i+1, lu->stat.RefineSteps, ferr, berr); 335 } 336 } else if ( info > 0 ){ 337 if ( lu->lwork == -1 ) { 338 ierr = PetscPrintf(PETSC_COMM_SELF," ** Estimated memory: %D bytes\n", info - lu->A.ncol); 339 } else { 340 ierr = PetscPrintf(PETSC_COMM_SELF," Warning: gssvx() returns info %D\n",info); 341 } 342 } else if (info < 0){ 343 SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_LIB, "info = %D, the %D-th argument in gssvx() had an illegal value", info,-info); 344 } 345 346 if ( lu->options.PrintStat ) { 347 ierr = PetscPrintf(PETSC_COMM_SELF,"MatSolve__SuperLU():\n"); 348 StatPrint(&lu->stat); 349 } 350 PetscFunctionReturn(0); 351 } 352 353 #undef __FUNCT__ 354 #define __FUNCT__ "MatSolve_SuperLU" 355 PetscErrorCode MatSolve_SuperLU(Mat A,Vec b,Vec x) 356 { 357 Mat_SuperLU *lu = (Mat_SuperLU*)A->spptr; 358 PetscErrorCode ierr; 359 360 PetscFunctionBegin; 361 lu->options.Trans = TRANS; 362 ierr = MatSolve_SuperLU_Private(A,b,x);CHKERRQ(ierr); 363 PetscFunctionReturn(0); 364 } 365 366 #undef __FUNCT__ 367 #define __FUNCT__ "MatSolveTranspose_SuperLU" 368 PetscErrorCode MatSolveTranspose_SuperLU(Mat A,Vec b,Vec x) 369 { 370 Mat_SuperLU *lu = (Mat_SuperLU*)A->spptr; 371 PetscErrorCode ierr; 372 373 PetscFunctionBegin; 374 lu->options.Trans = NOTRANS; 375 ierr = MatSolve_SuperLU_Private(A,b,x);CHKERRQ(ierr); 376 PetscFunctionReturn(0); 377 } 378 379 /* 380 Note the r permutation is ignored 381 */ 382 #undef __FUNCT__ 383 #define __FUNCT__ "MatLUFactorSymbolic_SuperLU" 384 PetscErrorCode MatLUFactorSymbolic_SuperLU(Mat F,Mat A,IS r,IS c,const MatFactorInfo *info) 385 { 386 Mat_SuperLU *lu = (Mat_SuperLU*)((F)->spptr); 387 388 PetscFunctionBegin; 389 lu->flg = DIFFERENT_NONZERO_PATTERN; 390 lu->CleanUpSuperLU = PETSC_TRUE; 391 (F)->ops->lufactornumeric = MatLUFactorNumeric_SuperLU; 392 PetscFunctionReturn(0); 393 } 394 395 EXTERN_C_BEGIN 396 #undef __FUNCT__ 397 #define __FUNCT__ "MatFactorGetSolverPackage_seqaij_superlu" 398 PetscErrorCode MatFactorGetSolverPackage_seqaij_superlu(Mat A,const MatSolverPackage *type) 399 { 400 PetscFunctionBegin; 401 *type = MATSOLVERSUPERLU; 402 PetscFunctionReturn(0); 403 } 404 EXTERN_C_END 405 406 407 /*MC 408 MATSOLVERSUPERLU = "superlu" - A solver package providing solvers LU and ILU for sequential matrices 409 via the external package SuperLU. 410 411 Use ./configure --download-superlu to have PETSc installed with SuperLU 412 413 Options Database Keys: 414 + -mat_superlu_equil: <FALSE> Equil (None) 415 . -mat_superlu_colperm <COLAMD> (choose one of) NATURAL MMD_ATA MMD_AT_PLUS_A COLAMD 416 . -mat_superlu_iterrefine <NOREFINE> (choose one of) NOREFINE SINGLE DOUBLE EXTRA 417 . -mat_superlu_symmetricmode: <FALSE> SymmetricMode (None) 418 . -mat_superlu_diagpivotthresh <1>: DiagPivotThresh (None) 419 . -mat_superlu_pivotgrowth: <FALSE> PivotGrowth (None) 420 . -mat_superlu_conditionnumber: <FALSE> ConditionNumber (None) 421 . -mat_superlu_rowperm <NOROWPERM> (choose one of) NOROWPERM LargeDiag 422 . -mat_superlu_replacetinypivot: <FALSE> ReplaceTinyPivot (None) 423 . -mat_superlu_printstat: <FALSE> PrintStat (None) 424 . -mat_superlu_lwork <0>: size of work array in bytes used by factorization (None) 425 . -mat_superlu_ilu_droptol <0>: ILU_DropTol (None) 426 . -mat_superlu_ilu_filltol <0>: ILU_FillTol (None) 427 . -mat_superlu_ilu_fillfactor <0>: ILU_FillFactor (None) 428 . -mat_superlu_ilu_droprull <0>: ILU_DropRule (None) 429 . -mat_superlu_ilu_norm <0>: ILU_Norm (None) 430 - -mat_superlu_ilu_milu <0>: ILU_MILU (None) 431 432 Notes: Do not confuse this with MATSOLVERSUPERLU_DIST which is for parallel sparse solves 433 434 Level: beginner 435 436 .seealso: PCLU, PCILU, MATSOLVERSUPERLU_DIST, MATSOLVERMUMPS, MATSOLVERSPOOLES, PCFactorSetMatSolverPackage(), MatSolverPackage 437 M*/ 438 439 EXTERN_C_BEGIN 440 #undef __FUNCT__ 441 #define __FUNCT__ "MatGetFactor_seqaij_superlu" 442 PetscErrorCode MatGetFactor_seqaij_superlu(Mat A,MatFactorType ftype,Mat *F) 443 { 444 Mat B; 445 Mat_SuperLU *lu; 446 PetscErrorCode ierr; 447 PetscInt indx,m=A->rmap->n,n=A->cmap->n; 448 PetscBool flg; 449 const char *colperm[]={"NATURAL","MMD_ATA","MMD_AT_PLUS_A","COLAMD"}; /* MY_PERMC - not supported by the petsc interface yet */ 450 const char *iterrefine[]={"NOREFINE", "SINGLE", "DOUBLE", "EXTRA"}; 451 const char *rowperm[]={"NOROWPERM", "LargeDiag"}; /* MY_PERMC - not supported by the petsc interface yet */ 452 453 PetscFunctionBegin; 454 ierr = MatCreate(((PetscObject)A)->comm,&B);CHKERRQ(ierr); 455 ierr = MatSetSizes(B,A->rmap->n,A->cmap->n,PETSC_DETERMINE,PETSC_DETERMINE);CHKERRQ(ierr); 456 ierr = MatSetType(B,((PetscObject)A)->type_name);CHKERRQ(ierr); 457 ierr = MatSeqAIJSetPreallocation(B,0,PETSC_NULL);CHKERRQ(ierr); 458 459 if (ftype == MAT_FACTOR_LU || ftype == MAT_FACTOR_ILU){ 460 B->ops->lufactorsymbolic = MatLUFactorSymbolic_SuperLU; 461 B->ops->ilufactorsymbolic = MatLUFactorSymbolic_SuperLU; 462 } else { 463 SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Factor type not supported"); 464 } 465 466 B->ops->destroy = MatDestroy_SuperLU; 467 B->ops->view = MatView_SuperLU; 468 B->factortype = ftype; 469 B->assembled = PETSC_TRUE; /* required by -ksp_view */ 470 B->preallocated = PETSC_TRUE; 471 472 ierr = PetscNewLog(B,Mat_SuperLU,&lu);CHKERRQ(ierr); 473 474 if (ftype == MAT_FACTOR_LU){ 475 set_default_options(&lu->options); 476 /* Comments from SuperLU_4.0/SRC/dgssvx.c: 477 "Whether or not the system will be equilibrated depends on the 478 scaling of the matrix A, but if equilibration is used, A is 479 overwritten by diag(R)*A*diag(C) and B by diag(R)*B 480 (if options->Trans=NOTRANS) or diag(C)*B (if options->Trans = TRANS or CONJ)." 481 We set 'options.Equil = NO' as default because additional space is needed for it. 482 */ 483 lu->options.Equil = NO; 484 } else if (ftype == MAT_FACTOR_ILU){ 485 /* Set the default input options of ilu: 486 options.Fact = DOFACT; 487 options.Equil = YES; // must be YES for ilu - don't know why 488 options.ColPerm = COLAMD; 489 options.DiagPivotThresh = 0.1; //different from complete LU 490 options.Trans = NOTRANS; 491 options.IterRefine = NOREFINE; 492 options.SymmetricMode = NO; 493 options.PivotGrowth = NO; 494 options.ConditionNumber = NO; 495 options.PrintStat = YES; 496 options.RowPerm = LargeDiag; 497 options.ILU_DropTol = 1e-4; 498 options.ILU_FillTol = 1e-2; 499 options.ILU_FillFactor = 10.0; 500 options.ILU_DropRule = DROP_BASIC | DROP_AREA; 501 options.ILU_Norm = INF_NORM; 502 options.ILU_MILU = SMILU_2; 503 */ 504 ilu_set_default_options(&lu->options); 505 } 506 lu->options.PrintStat = NO; 507 508 /* Initialize the statistics variables. */ 509 StatInit(&lu->stat); 510 lu->lwork = 0; /* allocate space internally by system malloc */ 511 512 ierr = PetscOptionsBegin(((PetscObject)A)->comm,((PetscObject)A)->prefix,"SuperLU Options","Mat");CHKERRQ(ierr); 513 ierr = PetscOptionsBool("-mat_superlu_equil","Equil","None",(PetscBool)lu->options.Equil,(PetscBool*)&lu->options.Equil,0);CHKERRQ(ierr); 514 ierr = PetscOptionsEList("-mat_superlu_colperm","ColPerm","None",colperm,4,colperm[3],&indx,&flg);CHKERRQ(ierr); 515 if (flg) {lu->options.ColPerm = (colperm_t)indx;} 516 ierr = PetscOptionsEList("-mat_superlu_iterrefine","IterRefine","None",iterrefine,4,iterrefine[0],&indx,&flg);CHKERRQ(ierr); 517 if (flg) { lu->options.IterRefine = (IterRefine_t)indx;} 518 ierr = PetscOptionsBool("-mat_superlu_symmetricmode","SymmetricMode","None",(PetscBool)lu->options.SymmetricMode,&flg,0);CHKERRQ(ierr); 519 if (flg) lu->options.SymmetricMode = YES; 520 ierr = PetscOptionsReal("-mat_superlu_diagpivotthresh","DiagPivotThresh","None",lu->options.DiagPivotThresh,&lu->options.DiagPivotThresh,PETSC_NULL);CHKERRQ(ierr); 521 ierr = PetscOptionsBool("-mat_superlu_pivotgrowth","PivotGrowth","None",(PetscBool)lu->options.PivotGrowth,&flg,0);CHKERRQ(ierr); 522 if (flg) lu->options.PivotGrowth = YES; 523 ierr = PetscOptionsBool("-mat_superlu_conditionnumber","ConditionNumber","None",(PetscBool)lu->options.ConditionNumber,&flg,0);CHKERRQ(ierr); 524 if (flg) lu->options.ConditionNumber = YES; 525 ierr = PetscOptionsEList("-mat_superlu_rowperm","rowperm","None",rowperm,2,rowperm[0],&indx,&flg);CHKERRQ(ierr); 526 if (flg) {lu->options.RowPerm = (rowperm_t)indx;} 527 ierr = PetscOptionsBool("-mat_superlu_replacetinypivot","ReplaceTinyPivot","None",(PetscBool)lu->options.ReplaceTinyPivot,&flg,0);CHKERRQ(ierr); 528 if (flg) lu->options.ReplaceTinyPivot = YES; 529 ierr = PetscOptionsBool("-mat_superlu_printstat","PrintStat","None",(PetscBool)lu->options.PrintStat,&flg,0);CHKERRQ(ierr); 530 if (flg) lu->options.PrintStat = YES; 531 ierr = PetscOptionsInt("-mat_superlu_lwork","size of work array in bytes used by factorization","None",lu->lwork,&lu->lwork,PETSC_NULL);CHKERRQ(ierr); 532 if (lu->lwork > 0 ){ 533 ierr = PetscMalloc(lu->lwork,&lu->work);CHKERRQ(ierr); 534 } else if (lu->lwork != 0 && lu->lwork != -1){ 535 ierr = PetscPrintf(PETSC_COMM_SELF," Warning: lwork %D is not supported by SUPERLU. The default lwork=0 is used.\n",lu->lwork); 536 lu->lwork = 0; 537 } 538 /* ilu options */ 539 ierr = PetscOptionsReal("-mat_superlu_ilu_droptol","ILU_DropTol","None",lu->options.ILU_DropTol,&lu->options.ILU_DropTol,PETSC_NULL);CHKERRQ(ierr); 540 ierr = PetscOptionsReal("-mat_superlu_ilu_filltol","ILU_FillTol","None",lu->options.ILU_FillTol,&lu->options.ILU_FillTol,PETSC_NULL);CHKERRQ(ierr); 541 ierr = PetscOptionsReal("-mat_superlu_ilu_fillfactor","ILU_FillFactor","None",lu->options.ILU_FillFactor,&lu->options.ILU_FillFactor,PETSC_NULL);CHKERRQ(ierr); 542 ierr = PetscOptionsInt("-mat_superlu_ilu_droprull","ILU_DropRule","None",lu->options.ILU_DropRule,&lu->options.ILU_DropRule,PETSC_NULL);CHKERRQ(ierr); 543 ierr = PetscOptionsInt("-mat_superlu_ilu_norm","ILU_Norm","None",lu->options.ILU_Norm,&indx,&flg);CHKERRQ(ierr); 544 if (flg){ 545 lu->options.ILU_Norm = (norm_t)indx; 546 } 547 ierr = PetscOptionsInt("-mat_superlu_ilu_milu","ILU_MILU","None",lu->options.ILU_MILU,&indx,&flg);CHKERRQ(ierr); 548 if (flg){ 549 lu->options.ILU_MILU = (milu_t)indx; 550 } 551 PetscOptionsEnd(); 552 if (lu->options.Equil == YES) { 553 /* superlu overwrites input matrix and rhs when Equil is used, thus create A_dup to keep user's A unchanged */ 554 ierr = MatDuplicate_SeqAIJ(A,MAT_COPY_VALUES,&lu->A_dup);CHKERRQ(ierr); 555 } 556 557 /* Allocate spaces (notice sizes are for the transpose) */ 558 ierr = PetscMalloc(m*sizeof(PetscInt),&lu->etree);CHKERRQ(ierr); 559 ierr = PetscMalloc(n*sizeof(PetscInt),&lu->perm_r);CHKERRQ(ierr); 560 ierr = PetscMalloc(m*sizeof(PetscInt),&lu->perm_c);CHKERRQ(ierr); 561 ierr = PetscMalloc(n*sizeof(PetscScalar),&lu->R);CHKERRQ(ierr); 562 ierr = PetscMalloc(m*sizeof(PetscScalar),&lu->C);CHKERRQ(ierr); 563 564 /* create rhs and solution x without allocate space for .Store */ 565 #if defined(PETSC_USE_COMPLEX) 566 zCreate_Dense_Matrix(&lu->B, m, 1, PETSC_NULL, m, SLU_DN, SLU_Z, SLU_GE); 567 zCreate_Dense_Matrix(&lu->X, m, 1, PETSC_NULL, m, SLU_DN, SLU_Z, SLU_GE); 568 #else 569 dCreate_Dense_Matrix(&lu->B, m, 1, PETSC_NULL, m, SLU_DN, SLU_D, SLU_GE); 570 dCreate_Dense_Matrix(&lu->X, m, 1, PETSC_NULL, m, SLU_DN, SLU_D, SLU_GE); 571 #endif 572 573 #ifdef SUPERLU2 574 ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatCreateNull","MatCreateNull_SuperLU",(void(*)(void))MatCreateNull_SuperLU);CHKERRQ(ierr); 575 #endif 576 ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatFactorGetSolverPackage_C","MatFactorGetSolverPackage_seqaij_superlu",MatFactorGetSolverPackage_seqaij_superlu);CHKERRQ(ierr); 577 B->spptr = lu; 578 *F = B; 579 PetscFunctionReturn(0); 580 } 581 EXTERN_C_END 582