Date: 2013-07-02T14:47:07+00:00

Actual source code: lu.c
petsc-3.4.2 2013-07-02

      2: /*
      3:    Defines a direct factorization preconditioner for any Mat implementation
      4:    Note: this need not be consided a preconditioner since it supplies
      5:          a direct solver.
      6: */

      8: #include <../src/ksp/pc/impls/factor/lu/lu.h>  /*I "petscpc.h" I*/

     12: PetscErrorCode  PCFactorReorderForNonzeroDiagonal_LU(PC pc,PetscReal z)
     13: {
     14:   PC_LU *lu = (PC_LU*)pc->data;

     17:   lu->nonzerosalongdiagonal = PETSC_TRUE;
     18:   if (z == PETSC_DECIDE) lu->nonzerosalongdiagonaltol = 1.e-10;
     19:   else lu->nonzerosalongdiagonaltol = z;
     20:   return(0);
     21: }

     25: PetscErrorCode  PCFactorSetReuseOrdering_LU(PC pc,PetscBool flag)
     26: {
     27:   PC_LU *lu = (PC_LU*)pc->data;

     30:   lu->reuseordering = flag;
     31:   return(0);
     32: }

     36: PetscErrorCode  PCFactorSetReuseFill_LU(PC pc,PetscBool flag)
     37: {
     38:   PC_LU *lu = (PC_LU*)pc->data;

     41:   lu->reusefill = flag;
     42:   return(0);
     43: }

     47: static PetscErrorCode PCSetFromOptions_LU(PC pc)
     48: {
     49:   PC_LU          *lu = (PC_LU*)pc->data;
     51:   PetscBool      flg = PETSC_FALSE;
     52:   PetscReal      tol;

     55:   PetscOptionsHead("LU options");
     56:   PCSetFromOptions_Factor(pc);

     58:   PetscOptionsName("-pc_factor_nonzeros_along_diagonal","Reorder to remove zeros from diagonal","PCFactorReorderForNonzeroDiagonal",&flg);
     59:   if (flg) {
     60:     tol  = PETSC_DECIDE;
     61:     PetscOptionsReal("-pc_factor_nonzeros_along_diagonal","Reorder to remove zeros from diagonal","PCFactorReorderForNonzeroDiagonal",lu->nonzerosalongdiagonaltol,&tol,0);
     62:     PCFactorReorderForNonzeroDiagonal(pc,tol);
     63:   }
     64:   PetscOptionsTail();
     65:   return(0);
     66: }

     70: static PetscErrorCode PCView_LU(PC pc,PetscViewer viewer)
     71: {
     72:   PC_LU          *lu = (PC_LU*)pc->data;
     74:   PetscBool      iascii;

     77:   PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);
     78:   if (iascii) {
     79:     if (lu->inplace) {
     80:       PetscViewerASCIIPrintf(viewer,"  LU: in-place factorization\n");
     81:     } else {
     82:       PetscViewerASCIIPrintf(viewer,"  LU: out-of-place factorization\n");
     83:     }

     85:     if (lu->reusefill)    {PetscViewerASCIIPrintf(viewer,"       Reusing fill from past factorization\n");}
     86:     if (lu->reuseordering) {PetscViewerASCIIPrintf(viewer,"       Reusing reordering from past factorization\n");}
     87:   }
     88:   PCView_Factor(pc,viewer);
     89:   return(0);
     90: }

     94: static PetscErrorCode PCSetUp_LU(PC pc)
     95: {
     97:   PC_LU          *dir = (PC_LU*)pc->data;

    100:   if (dir->reusefill && pc->setupcalled) ((PC_Factor*)dir)->info.fill = dir->actualfill;

    102:   if (dir->inplace) {
    103:     if (dir->row && dir->col && dir->row != dir->col) {ISDestroy(&dir->row);}
    104:     ISDestroy(&dir->col);
    105:     MatGetOrdering(pc->pmat,((PC_Factor*)dir)->ordering,&dir->row,&dir->col);
    106:     if (dir->row) {
    107:       PetscLogObjectParent(pc,dir->row);
    108:       PetscLogObjectParent(pc,dir->col);
    109:     }
    110:     MatLUFactor(pc->pmat,dir->row,dir->col,&((PC_Factor*)dir)->info);

    112:     ((PC_Factor*)dir)->fact = pc->pmat;
    113:   } else {
    114:     MatInfo info;
    115:     if (!pc->setupcalled) {
    116:       MatGetOrdering(pc->pmat,((PC_Factor*)dir)->ordering,&dir->row,&dir->col);
    117:       if (dir->nonzerosalongdiagonal) {
    118:         MatReorderForNonzeroDiagonal(pc->pmat,dir->nonzerosalongdiagonaltol,dir->row,dir->col);
    119:       }
    120:       if (dir->row) {
    121:         PetscLogObjectParent(pc,dir->row);
    122:         PetscLogObjectParent(pc,dir->col);
    123:       }
    124:       if (!((PC_Factor*)dir)->fact) {
    125:         MatGetFactor(pc->pmat,((PC_Factor*)dir)->solvertype,MAT_FACTOR_LU,&((PC_Factor*)dir)->fact);
    126:       }
    127:       MatLUFactorSymbolic(((PC_Factor*)dir)->fact,pc->pmat,dir->row,dir->col,&((PC_Factor*)dir)->info);
    128:       MatGetInfo(((PC_Factor*)dir)->fact,MAT_LOCAL,&info);
    129:       dir->actualfill = info.fill_ratio_needed;
    130:       PetscLogObjectParent(pc,((PC_Factor*)dir)->fact);
    131:     } else if (pc->flag != SAME_NONZERO_PATTERN) {
    132:       if (!dir->reuseordering) {
    133:         if (dir->row && dir->col && dir->row != dir->col) {ISDestroy(&dir->row);}
    134:         ISDestroy(&dir->col);
    135:         MatGetOrdering(pc->pmat,((PC_Factor*)dir)->ordering,&dir->row,&dir->col);
    136:         if (dir->nonzerosalongdiagonal) {
    137:           MatReorderForNonzeroDiagonal(pc->pmat,dir->nonzerosalongdiagonaltol,dir->row,dir->col);
    138:         }
    139:         if (dir->row) {
    140:           PetscLogObjectParent(pc,dir->row);
    141:           PetscLogObjectParent(pc,dir->col);
    142:         }
    143:       }
    144:       MatDestroy(&((PC_Factor*)dir)->fact);
    145:       MatGetFactor(pc->pmat,((PC_Factor*)dir)->solvertype,MAT_FACTOR_LU,&((PC_Factor*)dir)->fact);
    146:       MatLUFactorSymbolic(((PC_Factor*)dir)->fact,pc->pmat,dir->row,dir->col,&((PC_Factor*)dir)->info);
    147:       MatGetInfo(((PC_Factor*)dir)->fact,MAT_LOCAL,&info);
    148:       dir->actualfill = info.fill_ratio_needed;
    149:       PetscLogObjectParent(pc,((PC_Factor*)dir)->fact);
    150:     }
    151:     if ((!pc->setupcalled) || pc->setupcalled) {
    152:       MatLUFactorNumeric(((PC_Factor*)dir)->fact,pc->pmat,&((PC_Factor*)dir)->info);
    153:     }
    154:   }
    155:   return(0);
    156: }

    160: static PetscErrorCode PCReset_LU(PC pc)
    161: {
    162:   PC_LU          *dir = (PC_LU*)pc->data;

    166:   if (!dir->inplace && ((PC_Factor*)dir)->fact) {MatDestroy(&((PC_Factor*)dir)->fact);}
    167:   if (dir->row && dir->col && dir->row != dir->col) {ISDestroy(&dir->row);}
    168:   ISDestroy(&dir->col);
    169:   return(0);
    170: }

    174: static PetscErrorCode PCDestroy_LU(PC pc)
    175: {
    176:   PC_LU          *dir = (PC_LU*)pc->data;

    180:   PCReset_LU(pc);
    181:   PetscFree(((PC_Factor*)dir)->ordering);
    182:   PetscFree(((PC_Factor*)dir)->solvertype);
    183:   PetscFree(pc->data);
    184:   return(0);
    185: }

    189: static PetscErrorCode PCApply_LU(PC pc,Vec x,Vec y)
    190: {
    191:   PC_LU          *dir = (PC_LU*)pc->data;

    195:   if (dir->inplace) {
    196:     MatSolve(pc->pmat,x,y);
    197:   } else {
    198:     MatSolve(((PC_Factor*)dir)->fact,x,y);
    199:   }
    200:   return(0);
    201: }

    205: static PetscErrorCode PCApplyTranspose_LU(PC pc,Vec x,Vec y)
    206: {
    207:   PC_LU          *dir = (PC_LU*)pc->data;

    211:   if (dir->inplace) {
    212:     MatSolveTranspose(pc->pmat,x,y);
    213:   } else {
    214:     MatSolveTranspose(((PC_Factor*)dir)->fact,x,y);
    215:   }
    216:   return(0);
    217: }

    219: /* -----------------------------------------------------------------------------------*/

    223: PetscErrorCode  PCFactorSetUseInPlace_LU(PC pc)
    224: {
    225:   PC_LU *dir = (PC_LU*)pc->data;

    228:   dir->inplace = PETSC_TRUE;
    229:   return(0);
    230: }

    232: /* ------------------------------------------------------------------------ */

    234: /*MC
    235:    PCLU - Uses a direct solver, based on LU factorization, as a preconditioner

    237:    Options Database Keys:
    238: +  -pc_factor_reuse_ordering - Activate PCFactorSetReuseOrdering()
    239: .  -pc_factor_mat_solver_package - Actives PCFactorSetMatSolverPackage() to choose the direct solver, like superlu
    240: .  -pc_factor_reuse_fill - Activates PCFactorSetReuseFill()
    241: .  -pc_factor_fill <fill> - Sets fill amount
    242: .  -pc_factor_in_place - Activates in-place factorization
    243: .  -pc_factor_mat_ordering_type <nd,rcm,...> - Sets ordering routine
    244: .  -pc_factor_pivot_in_blocks <true,false> - allow pivoting within the small blocks during factorization (may increase
    245:                                          stability of factorization.
    246: .  -pc_factor_shift_type <shifttype> - Sets shift type or PETSC_DECIDE for the default; use '-help' for a list of available types
    247: .  -pc_factor_shift_amount <shiftamount> - Sets shift amount or PETSC_DECIDE for the default
    248: -   -pc_factor_nonzeros_along_diagonal - permutes the rows and columns to try to put nonzero value along the
    249:         diagonal.

    251:    Notes: Not all options work for all matrix formats
    252:           Run with -help to see additional options for particular matrix formats or factorization
    253:           algorithms

    255:    Level: beginner

    257:    Concepts: LU factorization, direct solver

    259:    Notes: Usually this will compute an "exact" solution in one iteration and does
    260:           not need a Krylov method (i.e. you can use -ksp_type preonly, or
    261:           KSPSetType(ksp,KSPPREONLY) for the Krylov method

    263: .seealso:  PCCreate(), PCSetType(), PCType (for list of available types), PC,
    264:            PCILU, PCCHOLESKY, PCICC, PCFactorSetReuseOrdering(), PCFactorSetReuseFill(), PCFactorGetMatrix(),
    265:            PCFactorSetFill(), PCFactorSetUseInPlace(), PCFactorSetMatOrderingType(), PCFactorSetColumnPivot(),
    266:            PCFactorSetPivotingInBlocks(),PCFactorSetShiftType(),PCFactorSetShiftAmount()
    267:            PCFactorReorderForNonzeroDiagonal()
    268: M*/

    272: PETSC_EXTERN PetscErrorCode PCCreate_LU(PC pc)
    273: {
    275:   PetscMPIInt    size;
    276:   PC_LU          *dir;

    279:   PetscNewLog(pc,PC_LU,&dir);

    281:   MatFactorInfoInitialize(&((PC_Factor*)dir)->info);

    283:   ((PC_Factor*)dir)->fact       = NULL;
    284:   ((PC_Factor*)dir)->factortype = MAT_FACTOR_LU;
    285:   dir->inplace                  = PETSC_FALSE;
    286:   dir->nonzerosalongdiagonal    = PETSC_FALSE;

    288:   ((PC_Factor*)dir)->info.fill          = 5.0;
    289:   ((PC_Factor*)dir)->info.dtcol         = 1.e-6;  /* default to pivoting; this is only thing PETSc LU supports */
    290:   ((PC_Factor*)dir)->info.shifttype     = (PetscReal)MAT_SHIFT_NONE;
    291:   ((PC_Factor*)dir)->info.shiftamount   = 0.0;
    292:   ((PC_Factor*)dir)->info.zeropivot     = 100.0*PETSC_MACHINE_EPSILON;
    293:   ((PC_Factor*)dir)->info.pivotinblocks = 1.0;
    294:   dir->col                              = 0;
    295:   dir->row                              = 0;

    297:   PetscStrallocpy(MATSOLVERPETSC,&((PC_Factor*)dir)->solvertype); /* default SolverPackage */
    298:   MPI_Comm_size(PetscObjectComm((PetscObject)pc),&size);
    299:   if (size == 1) {
    300:     PetscStrallocpy(MATORDERINGND,(char**)&((PC_Factor*)dir)->ordering);
    301:   } else {
    302:     PetscStrallocpy(MATORDERINGNATURAL,(char**)&((PC_Factor*)dir)->ordering);
    303:   }
    304:   dir->reusefill     = PETSC_FALSE;
    305:   dir->reuseordering = PETSC_FALSE;
    306:   pc->data           = (void*)dir;

    308:   pc->ops->reset             = PCReset_LU;
    309:   pc->ops->destroy           = PCDestroy_LU;
    310:   pc->ops->apply             = PCApply_LU;
    311:   pc->ops->applytranspose    = PCApplyTranspose_LU;
    312:   pc->ops->setup             = PCSetUp_LU;
    313:   pc->ops->setfromoptions    = PCSetFromOptions_LU;
    314:   pc->ops->view              = PCView_LU;
    315:   pc->ops->applyrichardson   = 0;
    316:   pc->ops->getfactoredmatrix = PCFactorGetMatrix_Factor;

    318:   PetscObjectComposeFunction((PetscObject)pc,"PCFactorSetUpMatSolverPackage_C",PCFactorSetUpMatSolverPackage_Factor);
    319:   PetscObjectComposeFunction((PetscObject)pc,"PCFactorGetMatSolverPackage_C",PCFactorGetMatSolverPackage_Factor);
    320:   PetscObjectComposeFunction((PetscObject)pc,"PCFactorSetMatSolverPackage_C",PCFactorSetMatSolverPackage_Factor);
    321:   PetscObjectComposeFunction((PetscObject)pc,"PCFactorSetZeroPivot_C",PCFactorSetZeroPivot_Factor);
    322:   PetscObjectComposeFunction((PetscObject)pc,"PCFactorSetShiftType_C",PCFactorSetShiftType_Factor);
    323:   PetscObjectComposeFunction((PetscObject)pc,"PCFactorSetShiftAmount_C",PCFactorSetShiftAmount_Factor);
    324:   PetscObjectComposeFunction((PetscObject)pc,"PCFactorSetFill_C",PCFactorSetFill_Factor);
    325:   PetscObjectComposeFunction((PetscObject)pc,"PCFactorSetUseInPlace_C",PCFactorSetUseInPlace_LU);
    326:   PetscObjectComposeFunction((PetscObject)pc,"PCFactorSetMatOrderingType_C",PCFactorSetMatOrderingType_Factor);
    327:   PetscObjectComposeFunction((PetscObject)pc,"PCFactorSetReuseOrdering_C",PCFactorSetReuseOrdering_LU);
    328:   PetscObjectComposeFunction((PetscObject)pc,"PCFactorSetReuseFill_C",PCFactorSetReuseFill_LU);
    329:   PetscObjectComposeFunction((PetscObject)pc,"PCFactorSetColumnPivot_C",PCFactorSetColumnPivot_Factor);
    330:   PetscObjectComposeFunction((PetscObject)pc,"PCFactorSetPivotInBlocks_C",PCFactorSetPivotInBlocks_Factor);
    331:   PetscObjectComposeFunction((PetscObject)pc,"PCFactorReorderForNonzeroDiagonal_C",PCFactorReorderForNonzeroDiagonal_LU);
    332:   return(0);
    333: }