Actual source code: cholesky.c

  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: */
  7: #include <../src/ksp/pc/impls/factor/factor.h>         /*I "petscpc.h" I*/

  9: typedef struct {
 10:   PC_Factor        hdr;
 11:   PetscReal        actualfill;       /* actual fill in factor */
 12:   PetscBool        inplace;          /* flag indicating in-place factorization */
 13:   IS               row,col;          /* index sets used for reordering */
 14:   PetscBool        reuseordering;    /* reuses previous reordering computed */
 15:   PetscBool        reusefill;        /* reuse fill from previous Cholesky */
 16: } PC_Cholesky;

 21: PetscErrorCode  PCFactorSetReuseOrdering_Cholesky(PC pc,PetscBool  flag)
 22: {
 23:   PC_Cholesky *lu;
 24: 
 26:   lu               = (PC_Cholesky*)pc->data;
 27:   lu->reuseordering = flag;
 28:   return(0);
 29: }

 35: PetscErrorCode  PCFactorSetReuseFill_Cholesky(PC pc,PetscBool  flag)
 36: {
 37:   PC_Cholesky *lu;
 38: 
 40:   lu = (PC_Cholesky*)pc->data;
 41:   lu->reusefill = flag;
 42:   return(0);
 43: }

 48: static PetscErrorCode PCSetFromOptions_Cholesky(PC pc)
 49: {
 51: 
 53:   PetscOptionsHead("Cholesky options");
 54:     PCSetFromOptions_Factor(pc);
 55:   PetscOptionsTail();
 56:   return(0);
 57: }

 61: static PetscErrorCode PCView_Cholesky(PC pc,PetscViewer viewer)
 62: {
 63:   PC_Cholesky    *chol = (PC_Cholesky*)pc->data;
 65:   PetscBool      iascii;
 66: 
 68:   PetscTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);
 69:   if (iascii) {
 70:     if (chol->inplace) {
 71:       PetscViewerASCIIPrintf(viewer,"  Cholesky: in-place factorization\n");
 72:     } else {
 73:       PetscViewerASCIIPrintf(viewer,"  Cholesky: out-of-place factorization\n");
 74:     }
 75: 
 76:     if (chol->reusefill)    {PetscViewerASCIIPrintf(viewer,"  Reusing fill from past factorization\n");}
 77:     if (chol->reuseordering) {PetscViewerASCIIPrintf(viewer,"  Reusing reordering from past factorization\n");}
 78:   }
 79:   PCView_Factor(pc,viewer);
 80:   return(0);
 81: }


 86: static PetscErrorCode PCSetUp_Cholesky(PC pc)
 87: {
 89:   PetscBool      flg;
 90:   PC_Cholesky    *dir = (PC_Cholesky*)pc->data;

 93:   if (dir->reusefill && pc->setupcalled) ((PC_Factor*)dir)->info.fill = dir->actualfill;
 94: 
 95:   if (dir->inplace) {
 96:     if (dir->row && dir->col && (dir->row != dir->col)) {
 97:       ISDestroy(&dir->row);
 98:     }
 99:     ISDestroy(&dir->col);
100:     MatGetOrdering(pc->pmat,((PC_Factor*)dir)->ordering,&dir->row,&dir->col);
101:     if (dir->col && (dir->row != dir->col)) {  /* only use row ordering for SBAIJ */
102:       ISDestroy(&dir->col);
103:     }
104:     if (dir->row) {PetscLogObjectParent(pc,dir->row);}
105:     MatCholeskyFactor(pc->pmat,dir->row,&((PC_Factor*)dir)->info);
106:     ((PC_Factor*)dir)->fact = pc->pmat;
107:   } else {
108:     MatInfo info;
109:     if (!pc->setupcalled) {
110:       MatGetOrdering(pc->pmat,((PC_Factor*)dir)->ordering,&dir->row,&dir->col);
111:       /* check if dir->row == dir->col */
112:       ISEqual(dir->row,dir->col,&flg);
113:       if (!flg) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"row and column permutations must equal");
114:       ISDestroy(&dir->col); /* only pass one ordering into CholeskyFactor */

116:       flg  = PETSC_FALSE;
117:       PetscOptionsGetBool(((PetscObject)pc)->prefix,"-pc_factor_nonzeros_along_diagonal",&flg,PETSC_NULL);
118:       if (flg) {
119:         PetscReal tol = 1.e-10;
120:         PetscOptionsGetReal(((PetscObject)pc)->prefix,"-pc_factor_nonzeros_along_diagonal",&tol,PETSC_NULL);
121:         MatReorderForNonzeroDiagonal(pc->pmat,tol,dir->row,dir->row);
122:       }
123:       if (dir->row) {PetscLogObjectParent(pc,dir->row);}
124:       if (!((PC_Factor*)dir)->fact){
125:         MatGetFactor(pc->pmat,((PC_Factor*)dir)->solvertype,MAT_FACTOR_CHOLESKY,&((PC_Factor*)dir)->fact);
126:       }
127:       MatCholeskyFactorSymbolic(((PC_Factor*)dir)->fact,pc->pmat,dir->row,&((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)) {
134:           ISDestroy(&dir->row);
135:         }
136:         ISDestroy(&dir->col);
137:         MatGetOrdering(pc->pmat,((PC_Factor*)dir)->ordering,&dir->row,&dir->col);
138:         if (dir->col && (dir->row != dir->col)) {  /* only use row ordering for SBAIJ */
139:           ISDestroy(&dir->col);
140:         }
141:         flg  = PETSC_FALSE;
142:         PetscOptionsGetBool(((PetscObject)pc)->prefix,"-pc_factor_nonzeros_along_diagonal",&flg,PETSC_NULL);
143:         if (flg) {
144:           PetscReal tol = 1.e-10;
145:           PetscOptionsGetReal(((PetscObject)pc)->prefix,"-pc_factor_nonzeros_along_diagonal",&tol,PETSC_NULL);
146:           MatReorderForNonzeroDiagonal(pc->pmat,tol,dir->row,dir->row);
147:         }
148:         if (dir->row) {PetscLogObjectParent(pc,dir->row);}
149:       }
150:       MatDestroy(&((PC_Factor*)dir)->fact);
151:       MatGetFactor(pc->pmat,((PC_Factor*)dir)->solvertype,MAT_FACTOR_CHOLESKY,&((PC_Factor*)dir)->fact);
152:       MatCholeskyFactorSymbolic(((PC_Factor*)dir)->fact,pc->pmat,dir->row,&((PC_Factor*)dir)->info);
153:       MatGetInfo(((PC_Factor*)dir)->fact,MAT_LOCAL,&info);
154:       dir->actualfill = info.fill_ratio_needed;
155:       PetscLogObjectParent(pc,((PC_Factor*)dir)->fact);
156:     }
157:     MatCholeskyFactorNumeric(((PC_Factor*)dir)->fact,pc->pmat,&((PC_Factor*)dir)->info);
158:   }
159:   return(0);
160: }

164: static PetscErrorCode PCReset_Cholesky(PC pc)
165: {
166:   PC_Cholesky    *dir = (PC_Cholesky*)pc->data;

170:   if (!dir->inplace && ((PC_Factor*)dir)->fact) {MatDestroy(&((PC_Factor*)dir)->fact);}
171:   ISDestroy(&dir->row);
172:   ISDestroy(&dir->col);
173:   return(0);
174: }

178: static PetscErrorCode PCDestroy_Cholesky(PC pc)
179: {
180:   PC_Cholesky    *dir = (PC_Cholesky*)pc->data;

184:   PCReset_Cholesky(pc);
185:   PetscFree(((PC_Factor*)dir)->ordering);
186:   PetscFree(((PC_Factor*)dir)->solvertype);
187:   PetscFree(pc->data);
188:   return(0);
189: }

193: static PetscErrorCode PCApply_Cholesky(PC pc,Vec x,Vec y)
194: {
195:   PC_Cholesky    *dir = (PC_Cholesky*)pc->data;
197: 
199:   if (dir->inplace) {MatSolve(pc->pmat,x,y);}
200:   else              {MatSolve(((PC_Factor*)dir)->fact,x,y);}
201:   return(0);
202: }

206: static PetscErrorCode PCApplyTranspose_Cholesky(PC pc,Vec x,Vec y)
207: {
208:   PC_Cholesky    *dir = (PC_Cholesky*)pc->data;

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

217: /* -----------------------------------------------------------------------------------*/

222: PetscErrorCode  PCFactorSetUseInPlace_Cholesky(PC pc)
223: {
224:   PC_Cholesky *dir;

227:   dir = (PC_Cholesky*)pc->data;
228:   dir->inplace = PETSC_TRUE;
229:   return(0);
230: }

233: /* -----------------------------------------------------------------------------------*/

237: /*@
238:    PCFactorSetReuseOrdering - When similar matrices are factored, this
239:    causes the ordering computed in the first factor to be used for all
240:    following factors.

242:    Logically Collective on PC

244:    Input Parameters:
245: +  pc - the preconditioner context
246: -  flag - PETSC_TRUE to reuse else PETSC_FALSE

248:    Options Database Key:
249: .  -pc_factor_reuse_ordering - Activate PCFactorSetReuseOrdering()

251:    Level: intermediate

253: .keywords: PC, levels, reordering, factorization, incomplete, LU

255: .seealso: PCFactorSetReuseFill()
256: @*/
257: PetscErrorCode  PCFactorSetReuseOrdering(PC pc,PetscBool  flag)
258: {

264:   PetscTryMethod(pc,"PCFactorSetReuseOrdering_C",(PC,PetscBool),(pc,flag));
265:   return(0);
266: }


269: /*MC
270:    PCCHOLESKY - Uses a direct solver, based on Cholesky factorization, as a preconditioner

272:    Options Database Keys:
273: +  -pc_factor_reuse_ordering - Activate PCFactorSetReuseOrdering()
274: .  -pc_factor_mat_solver_package - Actives PCFactorSetMatSolverPackage() to choose the direct solver, like spooles
275: .  -pc_factor_reuse_fill - Activates PCFactorSetReuseFill()
276: .  -pc_factor_fill <fill> - Sets fill amount
277: .  -pc_factor_in_place - Activates in-place factorization
278: -  -pc_factor_mat_ordering_type <nd,rcm,...> - Sets ordering routine

280:    Notes: Not all options work for all matrix formats

282:    Level: beginner

284:    Concepts: Cholesky factorization, direct solver

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

290: .seealso:  PCCreate(), PCSetType(), PCType (for list of available types), PC,
291:            PCILU, PCLU, PCICC, PCFactorSetReuseOrdering(), PCFactorSetReuseFill(), PCFactorGetMatrix(),
292:            PCFactorSetFill(), PCFactorSetShiftNonzero(), PCFactorSetShiftType(), PCFactorSetShiftAmount()
293:            PCFactorSetUseInPlace(), PCFactorSetMatOrderingType()

295: M*/

300: PetscErrorCode  PCCreate_Cholesky(PC pc)
301: {
303:   PC_Cholesky    *dir;

306:   PetscNewLog(pc,PC_Cholesky,&dir);

308:   ((PC_Factor*)dir)->fact                   = 0;
309:   dir->inplace                = PETSC_FALSE;
310:   MatFactorInfoInitialize(&((PC_Factor*)dir)->info);
311:   ((PC_Factor*)dir)->factortype         = MAT_FACTOR_CHOLESKY;
312:   ((PC_Factor*)dir)->info.fill          = 5.0;
313:   ((PC_Factor*)dir)->info.shifttype     = (PetscReal) MAT_SHIFT_NONE;
314:   ((PC_Factor*)dir)->info.shiftamount   = 0.0;
315:   ((PC_Factor*)dir)->info.zeropivot     = 100.0*PETSC_MACHINE_EPSILON;
316:   ((PC_Factor*)dir)->info.pivotinblocks = 1.0;
317:   dir->col                    = 0;
318:   dir->row                    = 0;
319:   PetscStrallocpy(MATORDERINGNATURAL,&((PC_Factor*)dir)->ordering);
320:   PetscStrallocpy(MATSOLVERPETSC,&((PC_Factor*)dir)->solvertype);
321:   dir->reusefill        = PETSC_FALSE;
322:   dir->reuseordering    = PETSC_FALSE;
323:   pc->data              = (void*)dir;

325:   pc->ops->destroy           = PCDestroy_Cholesky;
326:   pc->ops->reset             = PCReset_Cholesky;
327:   pc->ops->apply             = PCApply_Cholesky;
328:   pc->ops->applytranspose    = PCApplyTranspose_Cholesky;
329:   pc->ops->setup             = PCSetUp_Cholesky;
330:   pc->ops->setfromoptions    = PCSetFromOptions_Cholesky;
331:   pc->ops->view              = PCView_Cholesky;
332:   pc->ops->applyrichardson   = 0;
333:   pc->ops->getfactoredmatrix = PCFactorGetMatrix_Factor;

335:   PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCFactorSetUpMatSolverPackage_C","PCFactorSetUpMatSolverPackage_Factor",
336:                     PCFactorSetUpMatSolverPackage_Factor);
337:   PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCFactorSetMatSolverPackage_C","PCFactorSetMatSolverPackage_Factor",
338:                     PCFactorSetMatSolverPackage_Factor);
339:   PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCFactorGetMatSolverPackage_C","PCFactorGetMatSolverPackage_Factor",
340:                     PCFactorGetMatSolverPackage_Factor);
341:   PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCFactorSetZeroPivot_C","PCFactorSetZeroPivot_Factor",
342:                     PCFactorSetZeroPivot_Factor);
343:   PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCFactorSetShiftType_C","PCFactorSetShiftType_Factor",
344:                     PCFactorSetShiftType_Factor);
345:   PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCFactorSetShiftAmount_C","PCFactorSetShiftAmount_Factor",
346:                     PCFactorSetShiftAmount_Factor);
347:   PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCFactorSetFill_C","PCFactorSetFill_Factor",
348:                     PCFactorSetFill_Factor);
349:   PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCFactorSetUseInPlace_C","PCFactorSetUseInPlace_Cholesky",
350:                     PCFactorSetUseInPlace_Cholesky);
351:   PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCFactorSetMatOrderingType_C","PCFactorSetMatOrderingType_Factor",
352:                     PCFactorSetMatOrderingType_Factor);
353:   PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCFactorSetReuseOrdering_C","PCFactorSetReuseOrdering_Cholesky",
354:                     PCFactorSetReuseOrdering_Cholesky);
355:   PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCFactorSetReuseFill_C","PCFactorSetReuseFill_Cholesky",
356:                     PCFactorSetReuseFill_Cholesky);
357:   return(0);
358: }