1 /*$Id: superlu.c,v 1.10 2001/08/15 15:56:50 bsmith Exp $*/ 2 3 /* 4 Provides an interface to the SuperLU 3.0 sparse solver 5 */ 6 7 #include "src/mat/impls/aij/seq/aij.h" 8 9 EXTERN_C_BEGIN 10 #if defined(PETSC_USE_COMPLEX) 11 #include "zsp_defs.h" 12 #else 13 #include "dsp_defs.h" 14 #endif 15 #include "util.h" 16 EXTERN_C_END 17 18 typedef struct { 19 SuperMatrix A,L,U,B,X; 20 superlu_options_t options; 21 int *perm_c; /* column permutation vector */ 22 int *perm_r; /* row permutations from partial pivoting */ 23 int *etree; 24 double *R, *C; 25 char equed[1]; 26 int lwork; 27 void *work; 28 double rpg, rcond; 29 mem_usage_t mem_usage; 30 MatStructure flg; 31 32 /* A few function pointers for inheritance */ 33 int (*MatDuplicate)(Mat,MatDuplicateOption,Mat*); 34 int (*MatView)(Mat,PetscViewer); 35 int (*MatAssemblyEnd)(Mat,MatAssemblyType); 36 int (*MatLUFactorSymbolic)(Mat,IS,IS,MatFactorInfo*,Mat*); 37 int (*MatDestroy)(Mat); 38 39 /* Flag to clean up (non-global) SuperLU objects during Destroy */ 40 PetscTruth CleanUpSuperLU; 41 } Mat_SuperLU; 42 43 44 EXTERN int MatFactorInfo_SuperLU(Mat,PetscViewer); 45 EXTERN int MatLUFactorSymbolic_SuperLU(Mat,IS,IS,MatFactorInfo*,Mat*); 46 47 EXTERN_C_BEGIN 48 EXTERN int MatConvert_SuperLU_SeqAIJ(Mat,const MatType,Mat*); 49 EXTERN int MatConvert_SeqAIJ_SuperLU(Mat,const MatType,Mat*); 50 EXTERN_C_END 51 52 #undef __FUNCT__ 53 #define __FUNCT__ "MatDestroy_SuperLU" 54 int MatDestroy_SuperLU(Mat A) 55 { 56 int ierr; 57 Mat_SuperLU *lu = (Mat_SuperLU*)A->spptr; 58 59 PetscFunctionBegin; 60 if (lu->CleanUpSuperLU) { /* Free the SuperLU datastructures */ 61 Destroy_SuperMatrix_Store(&lu->A); 62 Destroy_SuperMatrix_Store(&lu->B); 63 Destroy_SuperMatrix_Store(&lu->X); 64 65 ierr = PetscFree(lu->etree);CHKERRQ(ierr); 66 ierr = PetscFree(lu->perm_r);CHKERRQ(ierr); 67 ierr = PetscFree(lu->perm_c);CHKERRQ(ierr); 68 ierr = PetscFree(lu->R);CHKERRQ(ierr); 69 ierr = PetscFree(lu->C);CHKERRQ(ierr); 70 if ( lu->lwork >= 0 ) { 71 Destroy_SuperNode_Matrix(&lu->L); 72 Destroy_CompCol_Matrix(&lu->U); 73 } 74 } 75 ierr = MatConvert_SuperLU_SeqAIJ(A,MATSEQAIJ,&A);CHKERRQ(ierr); 76 ierr = (*A->ops->destroy)(A);CHKERRQ(ierr); 77 PetscFunctionReturn(0); 78 } 79 80 #undef __FUNCT__ 81 #define __FUNCT__ "MatView_SuperLU" 82 int MatView_SuperLU(Mat A,PetscViewer viewer) 83 { 84 int ierr; 85 PetscTruth isascii; 86 PetscViewerFormat format; 87 Mat_SuperLU *lu=(Mat_SuperLU*)(A->spptr); 88 89 PetscFunctionBegin; 90 ierr = (*lu->MatView)(A,viewer);CHKERRQ(ierr); 91 92 ierr = PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_ASCII,&isascii);CHKERRQ(ierr); 93 if (isascii) { 94 ierr = PetscViewerGetFormat(viewer,&format);CHKERRQ(ierr); 95 if (format == PETSC_VIEWER_ASCII_FACTOR_INFO) { 96 ierr = MatFactorInfo_SuperLU(A,viewer);CHKERRQ(ierr); 97 } 98 } 99 PetscFunctionReturn(0); 100 } 101 102 #undef __FUNCT__ 103 #define __FUNCT__ "MatAssemblyEnd_SuperLU" 104 int MatAssemblyEnd_SuperLU(Mat A,MatAssemblyType mode) { 105 int ierr; 106 Mat_SuperLU *lu=(Mat_SuperLU*)(A->spptr); 107 108 PetscFunctionBegin; 109 ierr = (*lu->MatAssemblyEnd)(A,mode);CHKERRQ(ierr); 110 111 lu->MatLUFactorSymbolic = A->ops->lufactorsymbolic; 112 A->ops->lufactorsymbolic = MatLUFactorSymbolic_SuperLU; 113 PetscFunctionReturn(0); 114 } 115 116 /* This function was written for SuperLU 2.0 by Matthew Knepley. Not tested for SuperLU 3.0! */ 117 #ifdef SuperLU2 118 #include "src/mat/impls/dense/seq/dense.h" 119 #undef __FUNCT__ 120 #define __FUNCT__ "MatCreateNull_SuperLU" 121 int MatCreateNull_SuperLU(Mat A,Mat *nullMat) 122 { 123 Mat_SuperLU *lu = (Mat_SuperLU*)A->spptr; 124 int numRows = A->m,numCols = A->n; 125 SCformat *Lstore; 126 int numNullCols,size; 127 SuperLUStat_t stat; 128 #if defined(PETSC_USE_COMPLEX) 129 doublecomplex *nullVals,*workVals; 130 #else 131 PetscScalar *nullVals,*workVals; 132 #endif 133 int row,newRow,col,newCol,block,b,ierr; 134 135 PetscFunctionBegin; 136 if (!A->factor) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Unfactored matrix"); 137 numNullCols = numCols - numRows; 138 if (numNullCols < 0) SETERRQ(PETSC_ERR_ARG_WRONG,"Function only applies to underdetermined problems"); 139 /* Create the null matrix using MATSEQDENSE explicitly */ 140 ierr = MatCreate(A->comm,numRows,numNullCols,numRows,numNullCols,nullMat);CHKERRQ(ierr); 141 ierr = MatSetType(*nullMat,MATSEQDENSE);CHKERRQ(ierr); 142 ierr = MatSeqDenseSetPreallocation(*nullMat,PETSC_NULL);CHKERRQ(ierr); 143 if (numNullCols == 0) { 144 ierr = MatAssemblyBegin(*nullMat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 145 ierr = MatAssemblyEnd(*nullMat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 146 PetscFunctionReturn(0); 147 } 148 #if defined(PETSC_USE_COMPLEX) 149 nullVals = (doublecomplex*)((Mat_SeqDense*)(*nullMat)->data)->v; 150 #else 151 nullVals = ((Mat_SeqDense*)(*nullMat)->data)->v; 152 #endif 153 /* Copy in the columns */ 154 Lstore = (SCformat*)lu->L.Store; 155 for(block = 0; block <= Lstore->nsuper; block++) { 156 newRow = Lstore->sup_to_col[block]; 157 size = Lstore->sup_to_col[block+1] - Lstore->sup_to_col[block]; 158 for(col = Lstore->rowind_colptr[newRow]; col < Lstore->rowind_colptr[newRow+1]; col++) { 159 newCol = Lstore->rowind[col]; 160 if (newCol >= numRows) { 161 for(b = 0; b < size; b++) 162 #if defined(PETSC_USE_COMPLEX) 163 nullVals[(newCol-numRows)*numRows+newRow+b] = ((doublecomplex*)Lstore->nzval)[Lstore->nzval_colptr[newRow+b]+col]; 164 #else 165 nullVals[(newCol-numRows)*numRows+newRow+b] = ((double*)Lstore->nzval)[Lstore->nzval_colptr[newRow+b]+col]; 166 #endif 167 } 168 } 169 } 170 /* Permute rhs to form P^T_c B */ 171 ierr = PetscMalloc(numRows*sizeof(double),&workVals);CHKERRQ(ierr); 172 for(b = 0; b < numNullCols; b++) { 173 for(row = 0; row < numRows; row++) workVals[lu->perm_c[row]] = nullVals[b*numRows+row]; 174 for(row = 0; row < numRows; row++) nullVals[b*numRows+row] = workVals[row]; 175 } 176 /* Backward solve the upper triangle A x = b */ 177 for(b = 0; b < numNullCols; b++) { 178 #if defined(PETSC_USE_COMPLEX) 179 sp_ztrsv("L","T","U",&lu->L,&lu->U,&nullVals[b*numRows],&stat,&ierr); 180 #else 181 sp_dtrsv("L","T","U",&lu->L,&lu->U,&nullVals[b*numRows],&stat,&ierr); 182 #endif 183 if (ierr < 0) 184 SETERRQ1(PETSC_ERR_ARG_WRONG,"The argument %d was invalid",-ierr); 185 } 186 ierr = PetscFree(workVals);CHKERRQ(ierr); 187 188 ierr = MatAssemblyBegin(*nullMat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 189 ierr = MatAssemblyEnd(*nullMat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 190 PetscFunctionReturn(0); 191 } 192 #endif 193 194 #undef __FUNCT__ 195 #define __FUNCT__ "MatSolve_SuperLU" 196 int MatSolve_SuperLU(Mat A,Vec b,Vec x) 197 { 198 Mat_SuperLU *lu = (Mat_SuperLU*)A->spptr; 199 PetscScalar *barray,*xarray; 200 int ierr,info,i; 201 SuperLUStat_t stat; 202 double ferr,berr; 203 204 PetscFunctionBegin; 205 if ( lu->lwork == -1 ) { 206 PetscFunctionReturn(0); 207 } 208 lu->B.ncol = 1; /* Set the number of right-hand side */ 209 ierr = VecGetArray(b,&barray);CHKERRQ(ierr); 210 ierr = VecGetArray(x,&xarray);CHKERRQ(ierr); 211 212 #if defined(PETSC_USE_COMPLEX) 213 ((DNformat*)lu->B.Store)->nzval = (doublecomplex*)barray; 214 ((DNformat*)lu->X.Store)->nzval = (doublecomplex*)xarray; 215 #else 216 ((DNformat*)lu->B.Store)->nzval = barray; 217 ((DNformat*)lu->X.Store)->nzval = xarray; 218 #endif 219 220 /* Initialize the statistics variables. */ 221 StatInit(&stat); 222 223 lu->options.Fact = FACTORED; /* Indicate the factored form of A is supplied. */ 224 lu->options.Trans = TRANS; 225 #if defined(PETSC_USE_COMPLEX) 226 zgssvx(&lu->options, &lu->A, lu->perm_c, lu->perm_r, lu->etree, lu->equed, lu->R, lu->C, 227 &lu->L, &lu->U, lu->work, lu->lwork, &lu->B, &lu->X, &lu->rpg, &lu->rcond, &ferr, &berr, 228 &lu->mem_usage, &stat, &info); 229 #else 230 dgssvx(&lu->options, &lu->A, lu->perm_c, lu->perm_r, lu->etree, lu->equed, lu->R, lu->C, 231 &lu->L, &lu->U, lu->work, lu->lwork, &lu->B, &lu->X, &lu->rpg, &lu->rcond, &ferr, &berr, 232 &lu->mem_usage, &stat, &info); 233 #endif 234 ierr = VecRestoreArray(b,&barray);CHKERRQ(ierr); 235 ierr = VecRestoreArray(x,&xarray);CHKERRQ(ierr); 236 237 if ( info == 0 || info == lu->A.ncol+1 ) { 238 if ( lu->options.IterRefine ) { 239 ierr = PetscPrintf(PETSC_COMM_SELF,"Iterative Refinement:\n"); 240 ierr = PetscPrintf(PETSC_COMM_SELF," %8s%8s%16s%16s\n", "rhs", "Steps", "FERR", "BERR"); 241 for (i = 0; i < 1; ++i) 242 ierr = PetscPrintf(PETSC_COMM_SELF," %8d%8d%16e%16e\n", i+1, stat.RefineSteps, ferr, berr); 243 } 244 } else if ( info > 0 ){ 245 if ( lu->lwork == -1 ) { 246 ierr = PetscPrintf(PETSC_COMM_SELF," ** Estimated memory: %d bytes\n", info - lu->A.ncol); 247 } else { 248 ierr = PetscPrintf(PETSC_COMM_SELF," Warning: gssvx() returns info %d\n",info); 249 } 250 } else if (info < 0){ 251 SETERRQ2(1, "info = %d, the %d-th argument in gssvx() had an illegal value", info,-info); 252 } 253 254 if ( lu->options.PrintStat ) { 255 ierr = PetscPrintf(PETSC_COMM_SELF,"MatSolve__SuperLU():\n"); 256 StatPrint(&stat); 257 } 258 StatFree(&stat); 259 PetscFunctionReturn(0); 260 } 261 262 #undef __FUNCT__ 263 #define __FUNCT__ "MatLUFactorNumeric_SuperLU" 264 int MatLUFactorNumeric_SuperLU(Mat A,Mat *F) 265 { 266 Mat_SeqAIJ *aa = (Mat_SeqAIJ*)(A)->data; 267 Mat_SuperLU *lu = (Mat_SuperLU*)(*F)->spptr; 268 int ierr,info; 269 PetscTruth flag; 270 SuperLUStat_t stat; 271 double ferr, berr; 272 NCformat *Ustore; 273 SCformat *Lstore; 274 275 PetscFunctionBegin; 276 if (lu->flg == SAME_NONZERO_PATTERN){ /* successing numerical factorization */ 277 lu->options.Fact = SamePattern; 278 /* Ref: ~SuperLU_3.0/EXAMPLE/dlinsolx2.c */ 279 Destroy_SuperMatrix_Store(&lu->A); 280 if ( lu->lwork >= 0 ) { 281 Destroy_SuperNode_Matrix(&lu->L); 282 Destroy_CompCol_Matrix(&lu->U); 283 lu->options.Fact = SamePattern; 284 } 285 } 286 287 /* Create the SuperMatrix for lu->A=A^T: 288 Since SuperLU likes column-oriented matrices,we pass it the transpose, 289 and then solve A^T X = B in MatSolve(). */ 290 #if defined(PETSC_USE_COMPLEX) 291 zCreate_CompCol_Matrix(&lu->A,A->n,A->m,aa->nz,(doublecomplex*)aa->a,aa->j,aa->i, 292 SLU_NC,SLU_Z,SLU_GE); 293 #else 294 dCreate_CompCol_Matrix(&lu->A,A->n,A->m,aa->nz,aa->a,aa->j,aa->i, 295 SLU_NC,SLU_D,SLU_GE); 296 #endif 297 298 /* Initialize the statistics variables. */ 299 StatInit(&stat); 300 301 /* Numerical factorization */ 302 lu->B.ncol = 0; /* Indicate not to solve the system */ 303 #if defined(PETSC_USE_COMPLEX) 304 zgssvx(&lu->options, &lu->A, lu->perm_c, lu->perm_r, lu->etree, lu->equed, lu->R, lu->C, 305 &lu->L, &lu->U, lu->work, lu->lwork, &lu->B, &lu->X, &lu->rpg, &lu->rcond, &ferr, &berr, 306 &lu->mem_usage, &stat, &info); 307 #else 308 dgssvx(&lu->options, &lu->A, lu->perm_c, lu->perm_r, lu->etree, lu->equed, lu->R, lu->C, 309 &lu->L, &lu->U, lu->work, lu->lwork, &lu->B, &lu->X, &lu->rpg, &lu->rcond, &ferr, &berr, 310 &lu->mem_usage, &stat, &info); 311 #endif 312 if ( info == 0 || info == lu->A.ncol+1 ) { 313 if ( lu->options.PivotGrowth ) 314 ierr = PetscPrintf(PETSC_COMM_SELF," Recip. pivot growth = %e\n", lu->rpg); 315 if ( lu->options.ConditionNumber ) 316 ierr = PetscPrintf(PETSC_COMM_SELF," Recip. condition number = %e\n", lu->rcond); 317 } else if ( info > 0 ){ 318 if ( lu->lwork == -1 ) { 319 ierr = PetscPrintf(PETSC_COMM_SELF," ** Estimated memory: %d bytes\n", info - lu->A.ncol); 320 } else { 321 ierr = PetscPrintf(PETSC_COMM_SELF," Warning: gssvx() returns info %d\n",info); 322 } 323 } else { /* info < 0 */ 324 SETERRQ2(1, "info = %d, the %d-th argument in gssvx() had an illegal value", info,-info); 325 } 326 327 if ( lu->options.PrintStat ) { 328 ierr = PetscPrintf(PETSC_COMM_SELF,"MatLUFactorNumeric_SuperLU():\n"); 329 StatPrint(&stat); 330 Lstore = (SCformat *) lu->L.Store; 331 Ustore = (NCformat *) lu->U.Store; 332 ierr = PetscPrintf(PETSC_COMM_SELF," No of nonzeros in factor L = %d\n", Lstore->nnz); 333 ierr = PetscPrintf(PETSC_COMM_SELF," No of nonzeros in factor U = %d\n", Ustore->nnz); 334 ierr = PetscPrintf(PETSC_COMM_SELF," No of nonzeros in L+U = %d\n", Lstore->nnz + Ustore->nnz - lu->A.ncol); 335 ierr = PetscPrintf(PETSC_COMM_SELF," L\\U MB %.3f\ttotal MB needed %.3f\texpansions %d\n", 336 lu->mem_usage.for_lu/1e6, lu->mem_usage.total_needed/1e6, 337 lu->mem_usage.expansions); 338 } 339 StatFree(&stat); 340 341 lu->flg = SAME_NONZERO_PATTERN; 342 PetscFunctionReturn(0); 343 } 344 345 /* 346 Note the r permutation is ignored 347 */ 348 #undef __FUNCT__ 349 #define __FUNCT__ "MatLUFactorSymbolic_SuperLU" 350 int MatLUFactorSymbolic_SuperLU(Mat A,IS r,IS c,MatFactorInfo *info,Mat *F) 351 { 352 Mat B; 353 Mat_SuperLU *lu; 354 int ierr,m=A->m,n=A->n,indx; 355 PetscTruth flg; 356 const char *colperm[]={"NATURAL","MMD_ATA","MMD_AT_PLUS_A","COLAMD"}; /* MY_PERMC - not supported by the petsc interface yet */ 357 const char *iterrefine[]={"NOREFINE", "SINGLE", "DOUBLE", "EXTRA"}; 358 const char *rowperm[]={"NOROWPERM", "LargeDiag"}; /* MY_PERMC - not supported by the petsc interface yet */ 359 360 PetscFunctionBegin; 361 362 ierr = MatCreate(A->comm,A->m,A->n,PETSC_DETERMINE,PETSC_DETERMINE,&B);CHKERRQ(ierr); 363 ierr = MatSetType(B,A->type_name);CHKERRQ(ierr); 364 ierr = MatSeqAIJSetPreallocation(B,0,PETSC_NULL);CHKERRQ(ierr); 365 366 B->ops->lufactornumeric = MatLUFactorNumeric_SuperLU; 367 B->ops->solve = MatSolve_SuperLU; 368 B->factor = FACTOR_LU; 369 B->assembled = PETSC_TRUE; /* required by -ksp_view */ 370 371 lu = (Mat_SuperLU*)(B->spptr); 372 373 /* Set SuperLU options */ 374 /* the default values for options argument: 375 options.Fact = DOFACT; 376 options.Equil = YES; 377 options.ColPerm = COLAMD; 378 options.DiagPivotThresh = 1.0; 379 options.Trans = NOTRANS; 380 options.IterRefine = NOREFINE; 381 options.SymmetricMode = NO; 382 options.PivotGrowth = NO; 383 options.ConditionNumber = NO; 384 options.PrintStat = YES; 385 */ 386 set_default_options(&lu->options); 387 /* equilibration causes error in solve(), thus not supported here. See dgssvx.c for possible reason. */ 388 lu->options.Equil = NO; 389 lu->options.PrintStat = NO; 390 lu->lwork = 0; /* allocate space internally by system malloc */ 391 392 ierr = PetscOptionsBegin(A->comm,A->prefix,"SuperLU Options","Mat");CHKERRQ(ierr); 393 /* 394 ierr = PetscOptionsLogical("-mat_superlu_equil","Equil","None",PETSC_FALSE,&flg,0);CHKERRQ(ierr); 395 if (flg) lu->options.Equil = YES; -- not supported by the interface !!! 396 */ 397 ierr = PetscOptionsEList("-mat_superlu_colperm","ColPerm","None",colperm,4,colperm[3],&indx,&flg);CHKERRQ(ierr); 398 if (flg) {lu->options.ColPerm = (colperm_t)indx;} 399 ierr = PetscOptionsEList("-mat_superlu_iterrefine","IterRefine","None",iterrefine,4,iterrefine[0],&indx,&flg);CHKERRQ(ierr); 400 if (flg) { lu->options.IterRefine = (IterRefine_t)indx;} 401 ierr = PetscOptionsLogical("-mat_superlu_symmetricmode","SymmetricMode","None",PETSC_FALSE,&flg,0);CHKERRQ(ierr); 402 if (flg) lu->options.SymmetricMode = YES; 403 ierr = PetscOptionsReal("-mat_superlu_diagpivotthresh","DiagPivotThresh","None",lu->options.DiagPivotThresh,&lu->options.DiagPivotThresh,PETSC_NULL);CHKERRQ(ierr); 404 ierr = PetscOptionsLogical("-mat_superlu_pivotgrowth","PivotGrowth","None",PETSC_FALSE,&flg,0);CHKERRQ(ierr); 405 if (flg) lu->options.PivotGrowth = YES; 406 ierr = PetscOptionsLogical("-mat_superlu_conditionnumber","ConditionNumber","None",PETSC_FALSE,&flg,0);CHKERRQ(ierr); 407 if (flg) lu->options.ConditionNumber = YES; 408 ierr = PetscOptionsEList("-mat_superlu_rowperm","rowperm","None",rowperm,2,rowperm[0],&indx,&flg);CHKERRQ(ierr); 409 if (flg) {lu->options.RowPerm = (rowperm_t)indx;} 410 ierr = PetscOptionsLogical("-mat_superlu_replacetinypivot","ReplaceTinyPivot","None",PETSC_FALSE,&flg,0);CHKERRQ(ierr); 411 if (flg) lu->options.ReplaceTinyPivot = YES; 412 ierr = PetscOptionsLogical("-mat_superlu_printstat","PrintStat","None",PETSC_FALSE,&flg,0);CHKERRQ(ierr); 413 if (flg) lu->options.PrintStat = YES; 414 ierr = PetscOptionsInt("-mat_superlu_lwork","size of work array in bytes used by factorization","None",lu->lwork,&lu->lwork,PETSC_NULL);CHKERRQ(ierr); 415 if (lu->lwork > 0 ){ 416 ierr = PetscMalloc(lu->lwork,&lu->work);CHKERRQ(ierr); 417 } else if (lu->lwork != 0 && lu->lwork != -1){ 418 ierr = PetscPrintf(PETSC_COMM_SELF," Warning: lwork %d is not supported by SUPERLU. The default lwork=0 is used.\n",lu->lwork); 419 lu->lwork = 0; 420 } 421 PetscOptionsEnd(); 422 423 #ifdef SUPERLU2 424 ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatCreateNull","MatCreateNull_SuperLU", 425 (void(*)(void))MatCreateNull_SuperLU);CHKERRQ(ierr); 426 #endif 427 428 /* Allocate spaces (notice sizes are for the transpose) */ 429 ierr = PetscMalloc(m*sizeof(int),&lu->etree);CHKERRQ(ierr); 430 ierr = PetscMalloc(n*sizeof(int),&lu->perm_r);CHKERRQ(ierr); 431 ierr = PetscMalloc(m*sizeof(int),&lu->perm_c);CHKERRQ(ierr); 432 ierr = PetscMalloc(n*sizeof(int),&lu->R);CHKERRQ(ierr); 433 ierr = PetscMalloc(m*sizeof(int),&lu->C);CHKERRQ(ierr); 434 435 /* create rhs and solution x without allocate space for .Store */ 436 #if defined(PETSC_USE_COMPLEX) 437 zCreate_Dense_Matrix(&lu->B, m, 1, PETSC_NULL, m, SLU_DN, SLU_Z, SLU_GE); 438 zCreate_Dense_Matrix(&lu->X, m, 1, PETSC_NULL, m, SLU_DN, SLU_Z, SLU_GE); 439 #else 440 dCreate_Dense_Matrix(&lu->B, m, 1, PETSC_NULL, m, SLU_DN, SLU_D, SLU_GE); 441 dCreate_Dense_Matrix(&lu->X, m, 1, PETSC_NULL, m, SLU_DN, SLU_D, SLU_GE); 442 #endif 443 444 lu->flg = DIFFERENT_NONZERO_PATTERN; 445 lu->CleanUpSuperLU = PETSC_TRUE; 446 447 *F = B; 448 PetscLogObjectMemory(B,(A->m+A->n)*sizeof(int)+sizeof(Mat_SuperLU)); 449 PetscFunctionReturn(0); 450 } 451 452 /* used by -ksp_view */ 453 #undef __FUNCT__ 454 #define __FUNCT__ "MatFactorInfo_SuperLU" 455 int MatFactorInfo_SuperLU(Mat A,PetscViewer viewer) 456 { 457 Mat_SuperLU *lu= (Mat_SuperLU*)A->spptr; 458 int ierr; 459 superlu_options_t options; 460 461 PetscFunctionBegin; 462 /* check if matrix is superlu_dist type */ 463 if (A->ops->solve != MatSolve_SuperLU) PetscFunctionReturn(0); 464 465 options = lu->options; 466 ierr = PetscViewerASCIIPrintf(viewer,"SuperLU run parameters:\n");CHKERRQ(ierr); 467 ierr = PetscViewerASCIIPrintf(viewer," Equil: %s\n",(options.Equil != NO) ? "YES": "NO");CHKERRQ(ierr); 468 ierr = PetscViewerASCIIPrintf(viewer," ColPerm: %d\n",options.ColPerm);CHKERRQ(ierr); 469 ierr = PetscViewerASCIIPrintf(viewer," IterRefine: %d\n",options.IterRefine);CHKERRQ(ierr); 470 ierr = PetscViewerASCIIPrintf(viewer," SymmetricMode: %s\n",(options.SymmetricMode != NO) ? "YES": "NO");CHKERRQ(ierr); 471 ierr = PetscViewerASCIIPrintf(viewer," DiagPivotThresh: %g\n",options.DiagPivotThresh);CHKERRQ(ierr); 472 ierr = PetscViewerASCIIPrintf(viewer," PivotGrowth: %s\n",(options.PivotGrowth != NO) ? "YES": "NO");CHKERRQ(ierr); 473 ierr = PetscViewerASCIIPrintf(viewer," ConditionNumber: %s\n",(options.ConditionNumber != NO) ? "YES": "NO");CHKERRQ(ierr); 474 ierr = PetscViewerASCIIPrintf(viewer," RowPerm: %d\n",options.RowPerm);CHKERRQ(ierr); 475 ierr = PetscViewerASCIIPrintf(viewer," ReplaceTinyPivot: %s\n",(options.ReplaceTinyPivot != NO) ? "YES": "NO");CHKERRQ(ierr); 476 ierr = PetscViewerASCIIPrintf(viewer," PrintStat: %s\n",(options.PrintStat != NO) ? "YES": "NO");CHKERRQ(ierr); 477 ierr = PetscViewerASCIIPrintf(viewer," lwork: %d\n",lu->lwork);CHKERRQ(ierr); 478 479 PetscFunctionReturn(0); 480 } 481 482 #undef __FUNCT__ 483 #define __FUNCT__ "MatDuplicate_SuperLU" 484 int MatDuplicate_SuperLU(Mat A, MatDuplicateOption op, Mat *M) { 485 int ierr; 486 Mat_SuperLU *lu=(Mat_SuperLU *)A->spptr; 487 488 PetscFunctionBegin; 489 ierr = (*lu->MatDuplicate)(A,op,M);CHKERRQ(ierr); 490 ierr = PetscMemcpy((*M)->spptr,lu,sizeof(Mat_SuperLU));CHKERRQ(ierr); 491 PetscFunctionReturn(0); 492 } 493 494 EXTERN_C_BEGIN 495 #undef __FUNCT__ 496 #define __FUNCT__ "MatConvert_SuperLU_SeqAIJ" 497 int MatConvert_SuperLU_SeqAIJ(Mat A,const MatType type,Mat *newmat) { 498 /* This routine is only called to convert an unfactored PETSc-SuperLU matrix */ 499 /* to its base PETSc type, so we will ignore 'MatType type'. */ 500 int ierr; 501 Mat B=*newmat; 502 Mat_SuperLU *lu=(Mat_SuperLU *)A->spptr; 503 504 PetscFunctionBegin; 505 if (B != A) { 506 ierr = MatDuplicate(A,MAT_COPY_VALUES,&B);CHKERRQ(ierr); 507 } 508 /* Reset the original function pointers */ 509 B->ops->duplicate = lu->MatDuplicate; 510 B->ops->view = lu->MatView; 511 B->ops->assemblyend = lu->MatAssemblyEnd; 512 B->ops->lufactorsymbolic = lu->MatLUFactorSymbolic; 513 B->ops->destroy = lu->MatDestroy; 514 /* lu is only a function pointer stash unless we've factored the matrix, which we haven't! */ 515 ierr = PetscFree(lu);CHKERRQ(ierr); 516 ierr = PetscObjectChangeTypeName((PetscObject)B,MATSEQAIJ);CHKERRQ(ierr); 517 *newmat = B; 518 PetscFunctionReturn(0); 519 } 520 EXTERN_C_END 521 522 EXTERN_C_BEGIN 523 #undef __FUNCT__ 524 #define __FUNCT__ "MatConvert_SeqAIJ_SuperLU" 525 int MatConvert_SeqAIJ_SuperLU(Mat A,const MatType type,Mat *newmat) { 526 /* This routine is only called to convert to MATSUPERLU */ 527 /* from MATSEQAIJ, so we will ignore 'MatType type'. */ 528 int ierr; 529 Mat B=*newmat; 530 Mat_SuperLU *lu; 531 532 PetscFunctionBegin; 533 if (B != A) { 534 ierr = MatDuplicate(A,MAT_COPY_VALUES,&B);CHKERRQ(ierr); 535 } 536 537 ierr = PetscNew(Mat_SuperLU,&lu);CHKERRQ(ierr); 538 lu->MatDuplicate = A->ops->duplicate; 539 lu->MatView = A->ops->view; 540 lu->MatAssemblyEnd = A->ops->assemblyend; 541 lu->MatLUFactorSymbolic = A->ops->lufactorsymbolic; 542 lu->MatDestroy = A->ops->destroy; 543 lu->CleanUpSuperLU = PETSC_FALSE; 544 545 B->spptr = (void*)lu; 546 B->ops->duplicate = MatDuplicate_SuperLU; 547 B->ops->view = MatView_SuperLU; 548 B->ops->assemblyend = MatAssemblyEnd_SuperLU; 549 B->ops->lufactorsymbolic = MatLUFactorSymbolic_SuperLU; 550 B->ops->destroy = MatDestroy_SuperLU; 551 552 ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatConvert_seqaij_superlu_C", 553 "MatConvert_SeqAIJ_SuperLU",MatConvert_SeqAIJ_SuperLU);CHKERRQ(ierr); 554 ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatConvert_superlu_seqaij_C", 555 "MatConvert_SuperLU_SeqAIJ",MatConvert_SuperLU_SeqAIJ);CHKERRQ(ierr); 556 PetscLogInfo(0,"Using SuperLU for SeqAIJ LU factorization and solves."); 557 ierr = PetscObjectChangeTypeName((PetscObject)B,MATSUPERLU);CHKERRQ(ierr); 558 *newmat = B; 559 PetscFunctionReturn(0); 560 } 561 EXTERN_C_END 562 563 /*MC 564 MATSUPERLU - MATSUPERLU = "superlu" - A matrix type providing direct solvers (LU) for sequential matrices 565 via the external package SuperLU. 566 567 If SuperLU is installed (see the manual for 568 instructions on how to declare the existence of external packages), 569 a matrix type can be constructed which invokes SuperLU solvers. 570 After calling MatCreate(...,A), simply call MatSetType(A,MATSUPERLU). 571 This matrix type is only supported for double precision real. 572 573 This matrix inherits from MATSEQAIJ. As a result, MatSeqAIJSetPreallocation is 574 supported for this matrix type. One can also call MatConvert for an inplace conversion to or from 575 the MATSEQAIJ type without data copy. 576 577 Options Database Keys: 578 + -mat_type superlu - sets the matrix type to "superlu" during a call to MatSetFromOptions() 579 - -mat_superlu_ordering <0,1,2,3> - 0: natural ordering, 580 1: MMD applied to A'*A, 581 2: MMD applied to A'+A, 582 3: COLAMD, approximate minimum degree column ordering 583 584 Level: beginner 585 586 .seealso: PCLU 587 M*/ 588 589 EXTERN_C_BEGIN 590 #undef __FUNCT__ 591 #define __FUNCT__ "MatCreate_SuperLU" 592 int MatCreate_SuperLU(Mat A) { 593 int ierr; 594 595 PetscFunctionBegin; 596 /* Change type name before calling MatSetType to force proper construction of SeqAIJ and SUPERLU types */ 597 ierr = PetscObjectChangeTypeName((PetscObject)A,MATSUPERLU);CHKERRQ(ierr); 598 ierr = MatSetType(A,MATSEQAIJ);CHKERRQ(ierr); 599 ierr = MatConvert_SeqAIJ_SuperLU(A,MATSUPERLU,&A);CHKERRQ(ierr); 600 PetscFunctionReturn(0); 601 } 602 EXTERN_C_END 603