Actual source code: umfpack.c

      1: #define PETSCMAT_DLL

      3: /*
      4:         Provides an interface to the UMFPACKv4.3 sparse solver
      5: */

     7:  #include src/mat/impls/aij/seq/aij.h

     10: #include "umfpack.h"

     13: typedef struct {
     14:   void         *Symbolic, *Numeric;
     15:   double       Info[UMFPACK_INFO], Control[UMFPACK_CONTROL],*W;
     16:   int          *Wi,*ai,*aj,*perm_c;
     17:   PetscScalar  *av;
     18:   MatStructure flg;
     19:   PetscTruth   PetscMatOdering;

     21:   /* A few function pointers for inheritance */
     22:   PetscErrorCode (*MatDuplicate)(Mat,MatDuplicateOption,Mat*);
     23:   PetscErrorCode (*MatView)(Mat,PetscViewer);
     24:   PetscErrorCode (*MatAssemblyEnd)(Mat,MatAssemblyType);
     25:   PetscErrorCode (*MatLUFactorSymbolic)(Mat,IS,IS,MatFactorInfo*,Mat*);
     26:   PetscErrorCode (*MatDestroy)(Mat);
     27:
     28:   /* Flag to clean up UMFPACK objects during Destroy */
     29:   PetscTruth CleanUpUMFPACK;
     30: } Mat_UMFPACK;

     32: EXTERN PetscErrorCode MatDuplicate_UMFPACK(Mat,MatDuplicateOption,Mat*);

     37: PetscErrorCode PETSCMAT_DLLEXPORT MatConvert_UMFPACK_SeqAIJ(Mat A,MatType type,MatReuse reuse,Mat *newmat)
     38: {
     39:   /* This routine is only called to convert an unfactored PETSc-UMFPACK matrix */
     40:   /* to its base PETSc type, so we will ignore 'MatType type'. */
     42:   Mat         B=*newmat;
     43:   Mat_UMFPACK *lu=(Mat_UMFPACK*)A->spptr;

     46:   if (reuse == MAT_INITIAL_MATRIX) {
     47:     MatDuplicate(A,MAT_COPY_VALUES,&B);
     48:   }
     49:   /* Reset the original function pointers */
     50:   B->ops->duplicate        = lu->MatDuplicate;
     51:   B->ops->view             = lu->MatView;
     52:   B->ops->assemblyend      = lu->MatAssemblyEnd;
     53:   B->ops->lufactorsymbolic = lu->MatLUFactorSymbolic;
     54:   B->ops->destroy          = lu->MatDestroy;
     55:
     56:   PetscFree(lu);

     58:   PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_umfpack_C","",PETSC_NULL);
     59:   PetscObjectComposeFunction((PetscObject)B,"MatConvert_umfpack_seqaij_C","",PETSC_NULL);

     61:   PetscObjectChangeTypeName((PetscObject)B,MATSEQAIJ);
     62:   *newmat = B;
     63:   return(0);
     64: }

     69: PetscErrorCode MatDestroy_UMFPACK(Mat A)
     70: {
     72:   Mat_UMFPACK *lu=(Mat_UMFPACK*)A->spptr;

     75:   if (lu->CleanUpUMFPACK) {
     76:     umfpack_di_free_symbolic(&lu->Symbolic);
     77:     umfpack_di_free_numeric(&lu->Numeric);
     78:     PetscFree(lu->Wi);
     79:     PetscFree(lu->W);
     80:     if (lu->PetscMatOdering) {
     81:       PetscFree(lu->perm_c);
     82:     }
     83:   }
     84:   MatConvert_UMFPACK_SeqAIJ(A,MATSEQAIJ,MAT_REUSE_MATRIX,&A);
     85:   (*A->ops->destroy)(A);
     86:   return(0);
     87: }

     91: PetscErrorCode MatSolve_UMFPACK(Mat A,Vec b,Vec x)
     92: {
     93:   Mat_UMFPACK *lu = (Mat_UMFPACK*)A->spptr;
     94:   PetscScalar *av=lu->av,*ba,*xa;
     96:   int          *ai=lu->ai,*aj=lu->aj,status;
     97:
     99:   /* solve Ax = b by umfpack_di_wsolve */
    100:   /* ----------------------------------*/
    101:   VecGetArray(b,&ba);
    102:   VecGetArray(x,&xa);

    104:   status = umfpack_di_wsolve(UMFPACK_At,ai,aj,av,xa,ba,lu->Numeric,lu->Control,lu->Info,lu->Wi,lu->W);
    105:   umfpack_di_report_info(lu->Control, lu->Info);
    106:   if (status < 0){
    107:     umfpack_di_report_status(lu->Control, status);
    108:     SETERRQ(PETSC_ERR_LIB,"umfpack_di_wsolve failed");
    109:   }
    110:
    111:   VecRestoreArray(b,&ba);
    112:   VecRestoreArray(x,&xa);

    114:   return(0);
    115: }

    119: PetscErrorCode MatLUFactorNumeric_UMFPACK(Mat A,MatFactorInfo *info,Mat *F)
    120: {
    121:   Mat_UMFPACK *lu=(Mat_UMFPACK*)(*F)->spptr;
    123:   int         *ai=lu->ai,*aj=lu->aj,m=A->m,status;
    124:   PetscScalar *av=lu->av;

    127:   /* numeric factorization of A' */
    128:   /* ----------------------------*/
    129:   if (lu->flg == SAME_NONZERO_PATTERN && lu->Numeric){
    130:       umfpack_di_free_numeric(&lu->Numeric);
    131:   }
    132:   status = umfpack_di_numeric (ai,aj,av,lu->Symbolic,&lu->Numeric,lu->Control,lu->Info);
    133:   if (status < 0) SETERRQ(PETSC_ERR_LIB,"umfpack_di_numeric failed");
    134:   /* report numeric factorization of A' when Control[PRL] > 3 */
    135:   (void) umfpack_di_report_numeric (lu->Numeric, lu->Control);

    137:   if (lu->flg == DIFFERENT_NONZERO_PATTERN){  /* first numeric factorization */
    138:     /* allocate working space to be used by Solve */
    139:     PetscMalloc(m * sizeof(int), &lu->Wi);
    140:     PetscMalloc(5*m * sizeof(double), &lu->W);
    141:   }
    142:   lu->flg = SAME_NONZERO_PATTERN;
    143:   lu->CleanUpUMFPACK = PETSC_TRUE;
    144:   return(0);
    145: }

    147: /*
    148:    Note the r permutation is ignored
    149: */
    152: PetscErrorCode MatLUFactorSymbolic_UMFPACK(Mat A,IS r,IS c,MatFactorInfo *info,Mat *F)
    153: {
    154:   Mat         B;
    155:   Mat_SeqAIJ  *mat=(Mat_SeqAIJ*)A->data;
    156:   Mat_UMFPACK *lu;
    158:   int          m=A->m,n=A->n,*ai=mat->i,*aj=mat->j,status,*ra,idx;
    159:   PetscScalar *av=mat->a;
    160:   const char  *strategy[]={"AUTO","UNSYMMETRIC","SYMMETRIC","2BY2"},
    161:               *scale[]={"NONE","SUM","MAX"};
    162:   PetscTruth  flg;
    163:
    165:   /* Create the factorization matrix F */
    166:   MatCreate(A->comm,&B);
    167:   MatSetSizes(B,PETSC_DECIDE,PETSC_DECIDE,m,n);
    168:   MatSetType(B,A->type_name);
    169:   MatSeqAIJSetPreallocation(B,0,PETSC_NULL);
    170:
    171:   B->ops->lufactornumeric = MatLUFactorNumeric_UMFPACK;
    172:   B->ops->solve           = MatSolve_UMFPACK;
    173:   B->factor               = FACTOR_LU;
    174:   B->assembled            = PETSC_TRUE;  /* required by -ksp_view */

    176:   lu = (Mat_UMFPACK*)(B->spptr);
    177:
    178:   /* initializations */
    179:   /* ------------------------------------------------*/
    180:   /* get the default control parameters */
    181:   umfpack_di_defaults (lu->Control);
    182:   lu->perm_c = PETSC_NULL;  /* use defaul UMFPACK col permutation */
    183:   lu->Control[UMFPACK_IRSTEP] = 0; /* max num of iterative refinement steps to attempt */

    185:   PetscOptionsBegin(A->comm,A->prefix,"UMFPACK Options","Mat");
    186:   /* Control parameters used by reporting routiones */
    187:   PetscOptionsReal("-mat_umfpack_prl","Control[UMFPACK_PRL]","None",lu->Control[UMFPACK_PRL],&lu->Control[UMFPACK_PRL],PETSC_NULL);

    189:   /* Control parameters for symbolic factorization */
    190:   PetscOptionsEList("-mat_umfpack_strategy","ordering and pivoting strategy","None",strategy,4,strategy[0],&idx,&flg);
    191:   if (flg) {
    192:     switch (idx){
    193:     case 0: lu->Control[UMFPACK_STRATEGY] = UMFPACK_STRATEGY_AUTO; break;
    194:     case 1: lu->Control[UMFPACK_STRATEGY] = UMFPACK_STRATEGY_UNSYMMETRIC; break;
    195:     case 2: lu->Control[UMFPACK_STRATEGY] = UMFPACK_STRATEGY_SYMMETRIC; break;
    196:     case 3: lu->Control[UMFPACK_STRATEGY] = UMFPACK_STRATEGY_2BY2; break;
    197:     }
    198:   }
    199:   PetscOptionsReal("-mat_umfpack_dense_col","Control[UMFPACK_DENSE_COL]","None",lu->Control[UMFPACK_DENSE_COL],&lu->Control[UMFPACK_DENSE_COL],PETSC_NULL);
    200:   PetscOptionsReal("-mat_umfpack_dense_row","Control[UMFPACK_DENSE_ROW]","None",lu->Control[UMFPACK_DENSE_ROW],&lu->Control[UMFPACK_DENSE_ROW],PETSC_NULL);
    201:   PetscOptionsReal("-mat_umfpack_amd_dense","Control[UMFPACK_AMD_DENSE]","None",lu->Control[UMFPACK_AMD_DENSE],&lu->Control[UMFPACK_AMD_DENSE],PETSC_NULL);
    202:   PetscOptionsReal("-mat_umfpack_block_size","Control[UMFPACK_BLOCK_SIZE]","None",lu->Control[UMFPACK_BLOCK_SIZE],&lu->Control[UMFPACK_BLOCK_SIZE],PETSC_NULL);
    203:   PetscOptionsReal("-mat_umfpack_2by2_tolerance","Control[UMFPACK_2BY2_TOLERANCE]","None",lu->Control[UMFPACK_2BY2_TOLERANCE],&lu->Control[UMFPACK_2BY2_TOLERANCE],PETSC_NULL);
    204:   PetscOptionsReal("-mat_umfpack_fixq","Control[UMFPACK_FIXQ]","None",lu->Control[UMFPACK_FIXQ],&lu->Control[UMFPACK_FIXQ],PETSC_NULL);
    205:   PetscOptionsReal("-mat_umfpack_aggressive","Control[UMFPACK_AGGRESSIVE]","None",lu->Control[UMFPACK_AGGRESSIVE],&lu->Control[UMFPACK_AGGRESSIVE],PETSC_NULL);

    207:   /* Control parameters used by numeric factorization */
    208:   PetscOptionsReal("-mat_umfpack_pivot_tolerance","Control[UMFPACK_PIVOT_TOLERANCE]","None",lu->Control[UMFPACK_PIVOT_TOLERANCE],&lu->Control[UMFPACK_PIVOT_TOLERANCE],PETSC_NULL);
    209:   PetscOptionsReal("-mat_umfpack_sym_pivot_tolerance","Control[UMFPACK_SYM_PIVOT_TOLERANCE]","None",lu->Control[UMFPACK_SYM_PIVOT_TOLERANCE],&lu->Control[UMFPACK_SYM_PIVOT_TOLERANCE],PETSC_NULL);
    210:   PetscOptionsEList("-mat_umfpack_scale","Control[UMFPACK_SCALE]","None",scale,3,scale[0],&idx,&flg);
    211:   if (flg) {
    212:     switch (idx){
    213:     case 0: lu->Control[UMFPACK_SCALE] = UMFPACK_SCALE_NONE; break;
    214:     case 1: lu->Control[UMFPACK_SCALE] = UMFPACK_SCALE_SUM; break;
    215:     case 2: lu->Control[UMFPACK_SCALE] = UMFPACK_SCALE_MAX; break;
    216:     }
    217:   }
    218:   PetscOptionsReal("-mat_umfpack_alloc_init","Control[UMFPACK_ALLOC_INIT]","None",lu->Control[UMFPACK_ALLOC_INIT],&lu->Control[UMFPACK_ALLOC_INIT],PETSC_NULL);
    219:   PetscOptionsReal("-mat_umfpack_front_alloc_init","Control[UMFPACK_FRONT_ALLOC_INIT]","None",lu->Control[UMFPACK_FRONT_ALLOC_INIT],&lu->Control[UMFPACK_ALLOC_INIT],PETSC_NULL);
    220:   PetscOptionsReal("-mat_umfpack_droptol","Control[UMFPACK_DROPTOL]","None",lu->Control[UMFPACK_DROPTOL],&lu->Control[UMFPACK_DROPTOL],PETSC_NULL);

    222:   /* Control parameters used by solve */
    223:   PetscOptionsReal("-mat_umfpack_irstep","Control[UMFPACK_IRSTEP]","None",lu->Control[UMFPACK_IRSTEP],&lu->Control[UMFPACK_IRSTEP],PETSC_NULL);
    224:
    225:   /* use Petsc mat ordering (note: size is for the transpose, and PETSc r = Umfpack perm_c) */
    226:   PetscOptionsHasName(PETSC_NULL,"-pc_lu_mat_ordering_type",&lu->PetscMatOdering);
    227:   if (lu->PetscMatOdering) {
    228:     ISGetIndices(r,&ra);
    229:     PetscMalloc(A->m*sizeof(int),&lu->perm_c);
    230:     PetscMemcpy(lu->perm_c,ra,A->m*sizeof(int));
    231:     ISRestoreIndices(r,&ra);
    232:   }
    233:   PetscOptionsEnd();

    235:   /* print the control parameters */
    236:   if( lu->Control[UMFPACK_PRL] > 1 ) umfpack_di_report_control (lu->Control);

    238:   /* symbolic factorization of A' */
    239:   /* ---------------------------------------------------------------------- */
    240:   if (lu->PetscMatOdering) { /* use Petsc row ordering */
    241:     status = umfpack_di_qsymbolic(n,m,ai,aj,av,lu->perm_c,&lu->Symbolic,lu->Control,lu->Info);
    242:   } else { /* use Umfpack col ordering */
    243:     status = umfpack_di_symbolic(n,m,ai,aj,av,&lu->Symbolic,lu->Control,lu->Info);
    244:   }
    245:   if (status < 0){
    246:     umfpack_di_report_info(lu->Control, lu->Info);
    247:     umfpack_di_report_status(lu->Control, status);
    248:     SETERRQ(PETSC_ERR_LIB,"umfpack_di_symbolic failed");
    249:   }
    250:   /* report sumbolic factorization of A' when Control[PRL] > 3 */
    251:   (void) umfpack_di_report_symbolic(lu->Symbolic, lu->Control);

    253:   lu->flg = DIFFERENT_NONZERO_PATTERN;
    254:   lu->ai  = ai;
    255:   lu->aj  = aj;
    256:   lu->av  = av;
    257:   lu->CleanUpUMFPACK = PETSC_TRUE;
    258:   *F = B;
    259:   return(0);
    260: }

    264: PetscErrorCode MatAssemblyEnd_UMFPACK(Mat A,MatAssemblyType mode)
    265: {
    267:   Mat_UMFPACK *lu=(Mat_UMFPACK*)(A->spptr);

    270:   (*lu->MatAssemblyEnd)(A,mode);
    271:   lu->MatLUFactorSymbolic  = A->ops->lufactorsymbolic;
    272:   A->ops->lufactorsymbolic = MatLUFactorSymbolic_UMFPACK;
    273:   return(0);
    274: }

    276: /* used by -ksp_view */
    279: PetscErrorCode MatFactorInfo_UMFPACK(Mat A,PetscViewer viewer)
    280: {
    281:   Mat_UMFPACK *lu= (Mat_UMFPACK*)A->spptr;

    285:   /* check if matrix is UMFPACK type */
    286:   if (A->ops->solve != MatSolve_UMFPACK) return(0);

    288:   PetscViewerASCIIPrintf(viewer,"UMFPACK run parameters:\n");
    289:   /* Control parameters used by reporting routiones */
    290:   PetscViewerASCIIPrintf(viewer,"  Control[UMFPACK_PRL]: %g\n",lu->Control[UMFPACK_PRL]);

    292:   /* Control parameters used by symbolic factorization */
    293:   PetscViewerASCIIPrintf(viewer,"  Control[UMFPACK_STRATEGY]: %g\n",lu->Control[UMFPACK_STRATEGY]);
    294:   PetscViewerASCIIPrintf(viewer,"  Control[UMFPACK_DENSE_COL]: %g\n",lu->Control[UMFPACK_DENSE_COL]);
    295:   PetscViewerASCIIPrintf(viewer,"  Control[UMFPACK_DENSE_ROW]: %g\n",lu->Control[UMFPACK_DENSE_ROW]);
    296:   PetscViewerASCIIPrintf(viewer,"  Control[UMFPACK_AMD_DENSE]: %g\n",lu->Control[UMFPACK_AMD_DENSE]);
    297:   PetscViewerASCIIPrintf(viewer,"  Control[UMFPACK_BLOCK_SIZE]: %g\n",lu->Control[UMFPACK_BLOCK_SIZE]);
    298:   PetscViewerASCIIPrintf(viewer,"  Control[UMFPACK_2BY2_TOLERANCE]: %g\n",lu->Control[UMFPACK_2BY2_TOLERANCE]);
    299:   PetscViewerASCIIPrintf(viewer,"  Control[UMFPACK_FIXQ]: %g\n",lu->Control[UMFPACK_FIXQ]);
    300:   PetscViewerASCIIPrintf(viewer,"  Control[UMFPACK_AGGRESSIVE]: %g\n",lu->Control[UMFPACK_AGGRESSIVE]);

    302:   /* Control parameters used by numeric factorization */
    303:   PetscViewerASCIIPrintf(viewer,"  Control[UMFPACK_PIVOT_TOLERANCE]: %g\n",lu->Control[UMFPACK_PIVOT_TOLERANCE]);
    304:   PetscViewerASCIIPrintf(viewer,"  Control[UMFPACK_SYM_PIVOT_TOLERANCE]: %g\n",lu->Control[UMFPACK_SYM_PIVOT_TOLERANCE]);
    305:   PetscViewerASCIIPrintf(viewer,"  Control[UMFPACK_SCALE]: %g\n",lu->Control[UMFPACK_SCALE]);
    306:   PetscViewerASCIIPrintf(viewer,"  Control[UMFPACK_ALLOC_INIT]: %g\n",lu->Control[UMFPACK_ALLOC_INIT]);
    307:   PetscViewerASCIIPrintf(viewer,"  Control[UMFPACK_DROPTOL]: %g\n",lu->Control[UMFPACK_DROPTOL]);

    309:   /* Control parameters used by solve */
    310:   PetscViewerASCIIPrintf(viewer,"  Control[UMFPACK_IRSTEP]: %g\n",lu->Control[UMFPACK_IRSTEP]);

    312:   /* mat ordering */
    313:   if(!lu->PetscMatOdering) PetscViewerASCIIPrintf(viewer,"  UMFPACK default matrix ordering is used (not the PETSc matrix ordering) \n");

    315:   return(0);
    316: }

    320: PetscErrorCode MatView_UMFPACK(Mat A,PetscViewer viewer)
    321: {
    323:   PetscTruth        iascii;
    324:   PetscViewerFormat format;
    325:   Mat_UMFPACK       *lu=(Mat_UMFPACK*)(A->spptr);

    328:   (*lu->MatView)(A,viewer);

    330:   PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_ASCII,&iascii);
    331:   if (iascii) {
    332:     PetscViewerGetFormat(viewer,&format);
    333:     if (format == PETSC_VIEWER_ASCII_FACTOR_INFO) {
    334:       MatFactorInfo_UMFPACK(A,viewer);
    335:     }
    336:   }
    337:   return(0);
    338: }

    343: PetscErrorCode PETSCMAT_DLLEXPORT MatConvert_SeqAIJ_UMFPACK(Mat A,MatType type,MatReuse reuse,Mat *newmat)
    344: {
    345:   /* This routine is only called to convert to MATUMFPACK */
    346:   /* from MATSEQAIJ, so we will ignore 'MatType type'. */
    348:   Mat         B=*newmat;
    349:   Mat_UMFPACK *lu;

    352:   if (reuse == MAT_INITIAL_MATRIX) {
    353:     MatDuplicate(A,MAT_COPY_VALUES,&B);
    354:   }

    356:   PetscNew(Mat_UMFPACK,&lu);
    357:   lu->MatDuplicate         = A->ops->duplicate;
    358:   lu->MatView              = A->ops->view;
    359:   lu->MatAssemblyEnd       = A->ops->assemblyend;
    360:   lu->MatLUFactorSymbolic  = A->ops->lufactorsymbolic;
    361:   lu->MatDestroy           = A->ops->destroy;
    362:   lu->CleanUpUMFPACK       = PETSC_FALSE;

    364:   B->spptr                 = (void*)lu;
    365:   B->ops->duplicate        = MatDuplicate_UMFPACK;
    366:   B->ops->view             = MatView_UMFPACK;
    367:   B->ops->assemblyend      = MatAssemblyEnd_UMFPACK;
    368:   B->ops->lufactorsymbolic = MatLUFactorSymbolic_UMFPACK;
    369:   B->ops->destroy          = MatDestroy_UMFPACK;

    371:   PetscObjectComposeFunctionDynamic((PetscObject)B,"MatConvert_seqaij_umfpack_C",
    372:                                            "MatConvert_SeqAIJ_UMFPACK",MatConvert_SeqAIJ_UMFPACK);
    373:   PetscObjectComposeFunctionDynamic((PetscObject)B,"MatConvert_umfpack_seqaij_C",
    374:                                            "MatConvert_UMFPACK_SeqAIJ",MatConvert_UMFPACK_SeqAIJ);
    375:   PetscLogInfo((0,"MatConvert_SeqAIJ_UMFPACK:Using UMFPACK for SeqAIJ LU factorization and solves.\n"));
    376:   PetscObjectChangeTypeName((PetscObject)B,MATUMFPACK);
    377:   *newmat = B;
    378:   return(0);
    379: }

    384: PetscErrorCode MatDuplicate_UMFPACK(Mat A, MatDuplicateOption op, Mat *M)
    385: {
    387:   Mat_UMFPACK *lu=(Mat_UMFPACK*)A->spptr;

    390:   (*lu->MatDuplicate)(A,op,M);
    391:   PetscMemcpy((*M)->spptr,lu,sizeof(Mat_UMFPACK));
    392:   return(0);
    393: }

    395: /*MC
    396:   MATUMFPACK - MATUMFPACK = "umfpack" - A matrix type providing direct solvers (LU) for sequential matrices
    397:   via the external package UMFPACK.

    399:   If UMFPACK is installed (see the manual for
    400:   instructions on how to declare the existence of external packages),
    401:   a matrix type can be constructed which invokes UMFPACK solvers.
    402:   After calling MatCreate(...,A), simply call MatSetType(A,UMFPACK).
    403:   This matrix type is only supported for double precision real.

    405:   This matrix inherits from MATSEQAIJ.  As a result, MatSeqAIJSetPreallocation is
    406:   supported for this matrix type.  One can also call MatConvert for an inplace conversion to or from
    407:   the MATSEQAIJ type without data copy.

    409:   Consult UMFPACK documentation for more information about the Control parameters
    410:   which correspond to the options database keys below.

    412:   Options Database Keys:
    413: + -mat_type umfpack - sets the matrix type to "umfpack" during a call to MatSetFromOptions()
    414: . -mat_umfpack_prl - UMFPACK print level: Control[UMFPACK_PRL]
    415: . -mat_umfpack_dense_col <alpha_c> - UMFPACK dense column threshold: Control[UMFPACK_DENSE_COL]
    416: . -mat_umfpack_block_size <bs> - UMFPACK block size for BLAS-Level 3 calls: Control[UMFPACK_BLOCK_SIZE]
    417: . -mat_umfpack_pivot_tolerance <delta> - UMFPACK partial pivot tolerance: Control[UMFPACK_PIVOT_TOLERANCE]
    418: . -mat_umfpack_alloc_init <delta> - UMFPACK factorized matrix allocation modifier: Control[UMFPACK_ALLOC_INIT]
    419: - -mat_umfpack_irstep <maxit> - UMFPACK maximum number of iterative refinement steps: Control[UMFPACK_IRSTEP]

    421:    Level: beginner

    423: .seealso: PCLU
    424: M*/

    429: PetscErrorCode PETSCMAT_DLLEXPORT MatCreate_UMFPACK(Mat A)
    430: {

    434:   /* Change type name before calling MatSetType to force proper construction of SeqAIJ and UMFPACK types */
    435:   PetscObjectChangeTypeName((PetscObject)A,MATUMFPACK);
    436:   MatSetType(A,MATSEQAIJ);
    437:   MatConvert_SeqAIJ_UMFPACK(A,MATUMFPACK,MAT_REUSE_MATRIX,&A);
    438:   return(0);
    439: }