Actual source code: ilu.c

  1: /*$Id: ilu.c,v 1.164 2001/04/10 19:36:15 bsmith Exp $*/
  2: /*
  3:    Defines a ILU factorization preconditioner for any Mat implementation
  4: */
  5: #include "src/sles/pc/pcimpl.h"                 /*I "petscpc.h"  I*/
  6: #include "src/sles/pc/impls/ilu/ilu.h"
  7: #include "src/mat/matimpl.h"

  9: /* ------------------------------------------------------------------------------------------*/
 10: EXTERN_C_BEGIN
 11: int PCILUSetDamping_ILU(PC pc,PetscReal damping)
 12: {
 13:   PC_ILU *dir;

 16:   dir = (PC_ILU*)pc->data;
 17:   dir->info.damping = damping;
 18:   dir->info.damp    = 1.0;
 19:   return(0);
 20: }
 21: EXTERN_C_END

 23: EXTERN_C_BEGIN
 24: int PCILUSetUseDropTolerance_ILU(PC pc,PetscReal dt,PetscReal dtcol,int dtcount)
 25: {
 26:   PC_ILU *ilu;

 29:   ilu = (PC_ILU*)pc->data;
 30:   ilu->usedt         = PETSC_TRUE;
 31:   ilu->info.dt       = dt;
 32:   ilu->info.dtcol    = dtcol;
 33:   ilu->info.dtcount  = dtcount;
 34:   ilu->info.fill     = PETSC_DEFAULT;
 35:   return(0);
 36: }
 37: EXTERN_C_END

 39: EXTERN_C_BEGIN
 40: int PCILUSetFill_ILU(PC pc,PetscReal fill)
 41: {
 42:   PC_ILU *dir;

 45:   dir            = (PC_ILU*)pc->data;
 46:   dir->info.fill = fill;
 47:   return(0);
 48: }
 49: EXTERN_C_END

 51: EXTERN_C_BEGIN
 52: int PCILUSetMatOrdering_ILU(PC pc,MatOrderingType ordering)
 53: {
 54:   PC_ILU *dir = (PC_ILU*)pc->data;
 55:   int    ierr;
 56: 
 58:   PetscStrfree(dir->ordering);
 59:   PetscStrallocpy(ordering,&dir->ordering);
 60:   return(0);
 61: }
 62: EXTERN_C_END

 64: EXTERN_C_BEGIN
 65: int PCILUSetReuseOrdering_ILU(PC pc,PetscTruth flag)
 66: {
 67:   PC_ILU *ilu;

 70:   ilu                = (PC_ILU*)pc->data;
 71:   ilu->reuseordering = flag;
 72:   return(0);
 73: }
 74: EXTERN_C_END

 76: EXTERN_C_BEGIN
 77: int PCILUDTSetReuseFill_ILUDT(PC pc,PetscTruth flag)
 78: {
 79:   PC_ILU *ilu;

 82:   ilu = (PC_ILU*)pc->data;
 83:   ilu->reusefill = flag;
 84:   if (flag) SETERRQ(1,"Not yet supported");
 85:   return(0);
 86: }
 87: EXTERN_C_END

 89: EXTERN_C_BEGIN
 90: int PCILUSetLevels_ILU(PC pc,int levels)
 91: {
 92:   PC_ILU *ilu;

 95:   ilu = (PC_ILU*)pc->data;
 96:   ilu->info.levels = levels;
 97:   return(0);
 98: }
 99: EXTERN_C_END

101: EXTERN_C_BEGIN
102: int PCILUSetUseInPlace_ILU(PC pc)
103: {
104:   PC_ILU *dir;

107:   dir          = (PC_ILU*)pc->data;
108:   dir->inplace = PETSC_TRUE;
109:   return(0);
110: }
111: EXTERN_C_END

113: EXTERN_C_BEGIN
114: int PCILUSetAllowDiagonalFill_ILU(PC pc)
115: {
116:   PC_ILU *dir;

119:   dir                 = (PC_ILU*)pc->data;
120:   dir->info.diagonal_fill = 1;
121:   return(0);
122: }
123: EXTERN_C_END

125: /* ------------------------------------------------------------------------------------------*/
126: /*@
127:    PCILUSetDamping - adds this quantity to the diagonal of the matrix during the 
128:      ILU numerical factorization

130:    Collective on PC
131:    
132:    Input Parameters:
133: +  pc - the preconditioner context
134: -  damping - amount of damping

136:    Options Database Key:
137: .  -pc_ilu_damping <damping> - Sets damping amount

139:    Level: intermediate

141: .keywords: PC, set, factorization, direct, fill

143: .seealso: PCILUSetFill(), PCLUSetDamp()
144: @*/
145: int PCILUSetDamping(PC pc,PetscReal damping)
146: {
147:   int ierr,(*f)(PC,PetscReal);

151:   PetscObjectQueryFunction((PetscObject)pc,"PCILUSetDamping_C",(void (**)())&f);
152:   if (f) {
153:     (*f)(pc,damping);
154:   }
155:   return(0);
156: }

158: /*@
159:    PCILUSetUseDropTolerance - The preconditioner will use an ILU 
160:    based on a drop tolerance.

162:    Collective on PC

164:    Input Parameters:
165: +  pc - the preconditioner context
166: .  dt - the drop tolerance, try from 1.e-10 to .1
167: .  dtcol - tolerance for column pivot, good values [0.1 to 0.01]
168: -  maxrowcount - the max number of nonzeros allowed in a row, best value
169:                  depends on the number of nonzeros in row of original matrix

171:    Options Database Key:
172: .  -pc_ilu_use_drop_tolerance <dt,dtcol,maxrowcount> - Sets drop tolerance

174:    Level: intermediate

176:     Notes:
177:       This uses the iludt() code of Saad's SPARSKIT package

179: .keywords: PC, levels, reordering, factorization, incomplete, ILU
180: @*/
181: int PCILUSetUseDropTolerance(PC pc,PetscReal dt,PetscReal dtcol,int maxrowcount)
182: {
183:   int ierr,(*f)(PC,PetscReal,PetscReal,int);

187:   PetscObjectQueryFunction((PetscObject)pc,"PCILUSetUseDropTolerance_C",(void (**)())&f);
188:   if (f) {
189:     (*f)(pc,dt,dtcol,maxrowcount);
190:   }
191:   return(0);
192: }

194: /*@
195:    PCILUSetFill - Indicate the amount of fill you expect in the factored matrix,
196:    where fill = number nonzeros in factor/number nonzeros in original matrix.

198:    Collective on PC

200:    Input Parameters:
201: +  pc - the preconditioner context
202: -  fill - amount of expected fill

204:    Options Database Key:
205: $  -pc_ilu_fill <fill>

207:    Note:
208:    For sparse matrix factorizations it is difficult to predict how much 
209:    fill to expect. By running with the option -log_info PETSc will print the 
210:    actual amount of fill used; allowing you to set the value accurately for
211:    future runs. But default PETSc uses a value of 1.0

213:    Level: intermediate

215: .keywords: PC, set, factorization, direct, fill

217: .seealso: PCLUSetFill()
218: @*/
219: int PCILUSetFill(PC pc,PetscReal fill)
220: {
221:   int ierr,(*f)(PC,PetscReal);

225:   if (fill < 1.0) SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"Fill factor cannot be less than 1.0");
226:   PetscObjectQueryFunction((PetscObject)pc,"PCILUSetFill_C",(void (**)())&f);
227:   if (f) {
228:     (*f)(pc,fill);
229:   }
230:   return(0);
231: }

233: /*@
234:     PCILUSetMatOrdering - Sets the ordering routine (to reduce fill) to 
235:     be used in the ILU factorization.

237:     Collective on PC

239:     Input Parameters:
240: +   pc - the preconditioner context
241: -   ordering - the matrix ordering name, for example, MATORDERING_ND or MATORDERING_RCM

243:     Options Database Key:
244: .   -pc_ilu_mat_ordering_type <nd,rcm,...> - Sets ordering routine

246:     Level: intermediate

248:     Notes: natural ordering is used by default

250: .seealso: PCLUSetMatOrdering()

252: .keywords: PC, ILU, set, matrix, reordering

254: @*/
255: int PCILUSetMatOrdering(PC pc,MatOrderingType ordering)
256: {
257:   int ierr,(*f)(PC,MatOrderingType);

261:   PetscObjectQueryFunction((PetscObject)pc,"PCILUSetMatOrdering_C",(void (**)())&f);
262:   if (f) {
263:     (*f)(pc,ordering);
264:   }
265:   return(0);
266: }

268: /*@
269:    PCILUSetReuseOrdering - When similar matrices are factored, this
270:    causes the ordering computed in the first factor to be used for all
271:    following factors; applies to both fill and drop tolerance ILUs.

273:    Collective on PC

275:    Input Parameters:
276: +  pc - the preconditioner context
277: -  flag - PETSC_TRUE to reuse else PETSC_FALSE

279:    Options Database Key:
280: .  -pc_ilu_reuse_ordering - Activate PCILUSetReuseOrdering()

282:    Level: intermediate

284: .keywords: PC, levels, reordering, factorization, incomplete, ILU

286: .seealso: PCILUDTSetReuseFill(), PCLUSetReuseOrdering(), PCLUSetReuseFill()
287: @*/
288: int PCILUSetReuseOrdering(PC pc,PetscTruth flag)
289: {
290:   int ierr,(*f)(PC,PetscTruth);

294:   PetscObjectQueryFunction((PetscObject)pc,"PCILUSetReuseOrdering_C",(void (**)())&f);
295:   if (f) {
296:     (*f)(pc,flag);
297:   }
298:   return(0);
299: }

301: /*@
302:    PCILUDTSetReuseFill - When matrices with same nonzero structure are ILUDT factored,
303:    this causes later ones to use the fill computed in the initial factorization.

305:    Collective on PC

307:    Input Parameters:
308: +  pc - the preconditioner context
309: -  flag - PETSC_TRUE to reuse else PETSC_FALSE

311:    Options Database Key:
312: .  -pc_iludt_reuse_fill - Activates PCILUDTSetReuseFill()

314:    Level: intermediate

316: .keywords: PC, levels, reordering, factorization, incomplete, ILU

318: .seealso: PCILUSetReuseOrdering(), PCLUSetReuseOrdering(), PCLUSetReuseFill()
319: @*/
320: int PCILUDTSetReuseFill(PC pc,PetscTruth flag)
321: {
322:   int ierr,(*f)(PC,PetscTruth);

326:   PetscObjectQueryFunction((PetscObject)pc,"PCILUDTSetReuseFill_C",(void (**)())&f);
327:   if (f) {
328:     (*f)(pc,flag);
329:   }
330:   return(0);
331: }

333: /*@
334:    PCILUSetLevels - Sets the number of levels of fill to use.

336:    Collective on PC

338:    Input Parameters:
339: +  pc - the preconditioner context
340: -  levels - number of levels of fill

342:    Options Database Key:
343: .  -pc_ilu_levels <levels> - Sets fill level

345:    Level: intermediate

347: .keywords: PC, levels, fill, factorization, incomplete, ILU
348: @*/
349: int PCILUSetLevels(PC pc,int levels)
350: {
351:   int ierr,(*f)(PC,int);

355:   if (levels < 0) SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"negative levels");
356:   PetscObjectQueryFunction((PetscObject)pc,"PCILUSetLevels_C",(void (**)())&f);
357:   if (f) {
358:     (*f)(pc,levels);
359:   }
360:   return(0);
361: }

363: /*@
364:    PCILUSetAllowDiagonalFill - Causes all diagonal matrix entries to be 
365:    treated as level 0 fill even if there is no non-zero location.

367:    Collective on PC

369:    Input Parameters:
370: +  pc - the preconditioner context

372:    Options Database Key:
373: .  -pc_ilu_diagonal_fill

375:    Notes:
376:    Does not apply with 0 fill.

378:    Level: intermediate

380: .keywords: PC, levels, fill, factorization, incomplete, ILU
381: @*/
382: int PCILUSetAllowDiagonalFill(PC pc)
383: {
384:   int ierr,(*f)(PC);

388:   PetscObjectQueryFunction((PetscObject)pc,"PCILUSetAllowDiagonalFill_C",(void (**)())&f);
389:   if (f) {
390:     (*f)(pc);
391:   }
392:   return(0);
393: }

395: /*@
396:    PCILUSetUseInPlace - Tells the system to do an in-place incomplete factorization.
397:    Collective on PC

399:    Input Parameters:
400: .  pc - the preconditioner context

402:    Options Database Key:
403: .  -pc_ilu_in_place - Activates in-place factorization

405:    Notes:
406:    PCILUSetUseInPlace() is intended for use with matrix-free variants of
407:    Krylov methods, or when a different matrices are employed for the linear
408:    system and preconditioner, or with ASM preconditioning.  Do NOT use 
409:    this option if the linear system
410:    matrix also serves as the preconditioning matrix, since the factored
411:    matrix would then overwrite the original matrix. 

413:    Only works well with ILU(0).

415:    Level: intermediate

417: .keywords: PC, set, factorization, inplace, in-place, ILU

419: .seealso:  PCLUSetUseInPlace()
420: @*/
421: int PCILUSetUseInPlace(PC pc)
422: {
423:   int ierr,(*f)(PC);

427:   PetscObjectQueryFunction((PetscObject)pc,"PCILUSetUseInPlace_C",(void (**)())&f);
428:   if (f) {
429:     (*f)(pc);
430:   }
431:   return(0);
432: }

434: /* ------------------------------------------------------------------------------------------*/

436: static int PCSetFromOptions_ILU(PC pc)
437: {
438:   int        ierr,dtmax = 3,itmp;
439:   PetscTruth flg;
440:   PetscReal  dt[3];
441:   char       tname[256];
442:   PC_ILU     *ilu = (PC_ILU*)pc->data;
443:   PetscFList      ordlist;

446:   MatOrderingRegisterAll(PETSC_NULL);
447:   PetscOptionsHead("ILU Options");
448:     PetscOptionsInt("-pc_ilu_levels","levels of fill","PCILUSetLevels",(int)ilu->info.levels,&itmp,&flg);
449:     if (flg) ilu->info.levels = (double) itmp;
450:     PetscOptionsName("-pc_ilu_in_place","do factorization in place","PCILUSetUseInPlace",&ilu->inplace);
451:     PetscOptionsName("-pc_ilu_diagonal_fill","Allow fill into empty diagonal entry","PCILUSetAllowDiagonalFill",&flg);
452:     ilu->info.diagonal_fill = (double) flg;
453:     PetscOptionsName("-pc_iludt_reuse_fill","Reuse fill from previous ILUdt","PCILUDTSetReuseFill",&ilu->reusefill);
454:     PetscOptionsName("-pc_ilu_reuse_ordering","Reuse previous reordering","PCILUSetReuseOrdering",&ilu->reuseordering);
455:     PetscOptionsHasName(pc->prefix,"-pc_ilu_damping",&flg);
456:     if (flg) {
457:       PCILUSetDamping(pc,0.0);
458:     }
459:     PetscOptionsDouble("-pc_ilu_damping","Damping added to diagonal","PCILUSetDamping",ilu->info.damping,&ilu->info.damping,0);

461:     dt[0] = ilu->info.dt;
462:     dt[1] = ilu->info.dtcol;
463:     dt[2] = ilu->info.dtcount;
464:     PetscOptionsDoubleArray("-pc_ilu_use_drop_tolerance","<dt,dtcol,maxrowcount>","PCILUSetUseDropTolerance",dt,&dtmax,&flg);
465:     if (flg) {
466:       PCILUSetUseDropTolerance(pc,dt[0],dt[1],(int)dt[2]);
467:     }
468:     PetscOptionsDouble("-pc_ilu_fill","Expected fill in factorization","PCILUSetFill",ilu->info.fill,&ilu->info.fill,&flg);
469:     PetscOptionsDouble("-pc_ilu_nonzeros_along_diagonal","Reorder to remove zeros from diagonal","MatReorderForNonzeroDiagonal",0.0,0,0);

471:     MatGetOrderingList(&ordlist);
472:     PetscOptionsList("-pc_ilu_mat_ordering_type","Reorder to reduce nonzeros in ILU","PCILUSetMatOrdering",ordlist,ilu->ordering,tname,256,&flg);
473:     if (flg) {
474:       PCILUSetMatOrdering(pc,tname);
475:     }
476:   PetscOptionsTail();
477:   return(0);
478: }

480: static int PCView_ILU(PC pc,PetscViewer viewer)
481: {
482:   PC_ILU     *ilu = (PC_ILU*)pc->data;
483:   int        ierr;
484:   PetscTruth isstring,isascii;

487:   PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_STRING,&isstring);
488:   PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_ASCII,&isascii);
489:   if (isascii) {
490:     if (ilu->usedt) {
491:         PetscViewerASCIIPrintf(viewer,"  ILU: drop tolerance %gn",ilu->info.dt);
492:         PetscViewerASCIIPrintf(viewer,"  ILU: max nonzeros per row %dn",(int)ilu->info.dtcount);
493:         PetscViewerASCIIPrintf(viewer,"  ILU: column permutation tolerance %gn",ilu->info.dtcol);
494:     } else if (ilu->info.levels == 1) {
495:         PetscViewerASCIIPrintf(viewer,"  ILU: %d level of filln",(int)ilu->info.levels);
496:     } else {
497:         PetscViewerASCIIPrintf(viewer,"  ILU: %d levels of filln",(int)ilu->info.levels);
498:     }
499:     PetscViewerASCIIPrintf(viewer,"  ILU: max fill ratio allocated %gn",ilu->info.fill);
500:     if (ilu->inplace) {PetscViewerASCIIPrintf(viewer,"       in-place factorizationn");}
501:     else              {PetscViewerASCIIPrintf(viewer,"       out-of-place factorizationn");}
502:     PetscViewerASCIIPrintf(viewer,"       matrix ordering: %sn",ilu->ordering);
503:     if (ilu->reusefill)     {PetscViewerASCIIPrintf(viewer,"       Reusing fill from past factorizationn");}
504:     if (ilu->reuseordering) {PetscViewerASCIIPrintf(viewer,"       Reusing reordering from past factorizationn");}
505:     PetscViewerASCIIPrintf(viewer,"       Factored matrix followsn");
506:     PetscViewerASCIIPushTab(viewer);
507:     PetscViewerPushFormat(viewer,PETSC_VIEWER_ASCII_INFO);
508:     MatView(ilu->fact,viewer);
509:     PetscViewerPopFormat(viewer);
510:     PetscViewerASCIIPopTab(viewer);
511:   } else if (isstring) {
512:     PetscViewerStringSPrintf(viewer," lvls=%g,order=%s",ilu->info.levels,ilu->ordering);
513:   } else {
514:     SETERRQ1(1,"Viewer type %s not supported for PCILU",((PetscObject)viewer)->type_name);
515:   }
516:   return(0);
517: }

519: static int PCSetUp_ILU(PC pc)
520: {
521:   int        ierr;
522:   PetscTruth flg;
523:   PC_ILU     *ilu = (PC_ILU*)pc->data;

526:   if (ilu->inplace) {
527:     if (!pc->setupcalled) {

529:       /* In-place factorization only makes sense with the natural ordering,
530:          so we only need to get the ordering once, even if nonzero structure changes */
531:       MatGetOrdering(pc->pmat,ilu->ordering,&ilu->row,&ilu->col);
532:       if (ilu->row) PetscLogObjectParent(pc,ilu->row);
533:       if (ilu->col) PetscLogObjectParent(pc,ilu->col);
534:     }

536:     /* In place ILU only makes sense with fill factor of 1.0 because 
537:        cannot have levels of fill */
538:     ilu->info.fill          = 1.0;
539:     ilu->info.diagonal_fill = 0;
540:     MatILUFactor(pc->pmat,ilu->row,ilu->col,&ilu->info);
541:     ilu->fact = pc->pmat;
542:   } else if (ilu->usedt) {
543:     if (!pc->setupcalled) {
544:       MatGetOrdering(pc->pmat,ilu->ordering,&ilu->row,&ilu->col);
545:       if (ilu->row) PetscLogObjectParent(pc,ilu->row);
546:       if (ilu->col) PetscLogObjectParent(pc,ilu->col);
547:       MatILUDTFactor(pc->pmat,&ilu->info,ilu->row,ilu->col,&ilu->fact);
548:       PetscLogObjectParent(pc,ilu->fact);
549:     } else if (pc->flag != SAME_NONZERO_PATTERN) {
550:       MatDestroy(ilu->fact);
551:       if (!ilu->reuseordering) {
552:         if (ilu->row) {ISDestroy(ilu->row);}
553:         if (ilu->col) {ISDestroy(ilu->col);}
554:         MatGetOrdering(pc->pmat,ilu->ordering,&ilu->row,&ilu->col);
555:         if (ilu->row) PetscLogObjectParent(pc,ilu->row);
556:         if (ilu->col) PetscLogObjectParent(pc,ilu->col);
557:       }
558:       MatILUDTFactor(pc->pmat,&ilu->info,ilu->row,ilu->col,&ilu->fact);
559:       PetscLogObjectParent(pc,ilu->fact);
560:     } else if (!ilu->reusefill) {
561:       MatDestroy(ilu->fact);
562:       MatILUDTFactor(pc->pmat,&ilu->info,ilu->row,ilu->col,&ilu->fact);
563:       PetscLogObjectParent(pc,ilu->fact);
564:     } else {
565:       MatLUFactorNumeric(pc->pmat,&ilu->fact);
566:     }
567:   } else {
568:     if (!pc->setupcalled) {
569:       /* first time in so compute reordering and symbolic factorization */
570:       MatGetOrdering(pc->pmat,ilu->ordering,&ilu->row,&ilu->col);
571:       if (ilu->row) PetscLogObjectParent(pc,ilu->row);
572:       if (ilu->col) PetscLogObjectParent(pc,ilu->col);
573:       /*  Remove zeros along diagonal?     */
574:       PetscOptionsHasName(pc->prefix,"-pc_ilu_nonzeros_along_diagonal",&flg);
575:       if (flg) {
576:         PetscReal ntol = 1.e-10;
577:         PetscOptionsGetDouble(pc->prefix,"-pc_ilu_nonzeros_along_diagonal",&ntol,PETSC_NULL);
578:         MatReorderForNonzeroDiagonal(pc->pmat,ntol,ilu->row,ilu->col);
579:       }

581:       MatILUFactorSymbolic(pc->pmat,ilu->row,ilu->col,&ilu->info,&ilu->fact);
582:       PetscLogObjectParent(pc,ilu->fact);
583:     } else if (pc->flag != SAME_NONZERO_PATTERN) {
584:       if (!ilu->reuseordering) {
585:         /* compute a new ordering for the ILU */
586:         ISDestroy(ilu->row);
587:         ISDestroy(ilu->col);
588:         MatGetOrdering(pc->pmat,ilu->ordering,&ilu->row,&ilu->col);
589:         if (ilu->row) PetscLogObjectParent(pc,ilu->row);
590:         if (ilu->col) PetscLogObjectParent(pc,ilu->col);
591:         /*  Remove zeros along diagonal?     */
592:         PetscOptionsHasName(pc->prefix,"-pc_ilu_nonzeros_along_diagonal",&flg);
593:         if (flg) {
594:           PetscReal ntol = 1.e-10;
595:           PetscOptionsGetDouble(pc->prefix,"-pc_ilu_nonzeros_along_diagonal",&ntol,PETSC_NULL);
596:           MatReorderForNonzeroDiagonal(pc->pmat,ntol,ilu->row,ilu->col);
597:         }
598:       }
599:       MatDestroy(ilu->fact);
600:       MatILUFactorSymbolic(pc->pmat,ilu->row,ilu->col,&ilu->info,&ilu->fact);
601:       PetscLogObjectParent(pc,ilu->fact);
602:     }
603:     MatLUFactorNumeric(pc->pmat,&ilu->fact);
604:   }
605:   return(0);
606: }

608: static int PCDestroy_ILU(PC pc)
609: {
610:   PC_ILU *ilu = (PC_ILU*)pc->data;
611:   int    ierr;

614:   if (!ilu->inplace && ilu->fact) {MatDestroy(ilu->fact);}
615:   if (ilu->row && ilu->col && ilu->row != ilu->col) {ISDestroy(ilu->row);}
616:   if (ilu->col) {ISDestroy(ilu->col);}
617:   PetscStrfree(ilu->ordering);
618:   PetscFree(ilu);
619:   return(0);
620: }

622: static int PCApply_ILU(PC pc,Vec x,Vec y)
623: {
624:   PC_ILU *ilu = (PC_ILU*)pc->data;
625:   int    ierr;

628:   MatSolve(ilu->fact,x,y);
629:   return(0);
630: }

632: static int PCApplyTranspose_ILU(PC pc,Vec x,Vec y)
633: {
634:   PC_ILU *ilu = (PC_ILU*)pc->data;
635:   int    ierr;

638:   MatSolveTranspose(ilu->fact,x,y);
639:   return(0);
640: }

642: static int PCGetFactoredMatrix_ILU(PC pc,Mat *mat)
643: {
644:   PC_ILU *ilu = (PC_ILU*)pc->data;

647:   if (!ilu->fact) SETERRQ(1,"Matrix not yet factored; call after SLESSetUp() or PCSetUp()");
648:   *mat = ilu->fact;
649:   return(0);
650: }

652: EXTERN_C_BEGIN
653: int PCCreate_ILU(PC pc)
654: {
655:   int    ierr;
656:   PC_ILU *ilu;

659:   PetscNew(PC_ILU,&ilu);
660:   PetscLogObjectMemory(pc,sizeof(PC_ILU));

662:   ilu->fact               = 0;
663:   ilu->info.levels        = 0;
664:   ilu->info.fill          = 1.0;
665:   ilu->col                = 0;
666:   ilu->row                = 0;
667:   ilu->inplace            = PETSC_FALSE;
668:   PetscStrallocpy(MATORDERING_NATURAL,&ilu->ordering);
669:   ilu->reuseordering      = PETSC_FALSE;
670:   ilu->usedt              = PETSC_FALSE;
671:   ilu->info.dt            = PETSC_DEFAULT;
672:   ilu->info.dtcount       = PETSC_DEFAULT;
673:   ilu->info.dtcol         = PETSC_DEFAULT;
674:   ilu->info.damp          = 0.0;
675:   ilu->info.damping       = 0.0;
676:   ilu->reusefill          = PETSC_FALSE;
677:   ilu->info.diagonal_fill = 0;
678:   pc->data                = (void*)ilu;

680:   pc->ops->destroy           = PCDestroy_ILU;
681:   pc->ops->apply             = PCApply_ILU;
682:   pc->ops->applytranspose    = PCApplyTranspose_ILU;
683:   pc->ops->setup             = PCSetUp_ILU;
684:   pc->ops->setfromoptions    = PCSetFromOptions_ILU;
685:   pc->ops->getfactoredmatrix = PCGetFactoredMatrix_ILU;
686:   pc->ops->view              = PCView_ILU;
687:   pc->ops->applyrichardson   = 0;

689:   PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCILUSetUseDropTolerance_C","PCILUSetUseDropTolerance_ILU",
690:                     PCILUSetUseDropTolerance_ILU);
691:   PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCILUSetFill_C","PCILUSetFill_ILU",
692:                     PCILUSetFill_ILU);
693:   PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCILUSetDamping_C","PCILUSetDamping_ILU",
694:                     PCILUSetDamping_ILU);
695:   PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCILUSetMatOrdering_C","PCILUSetMatOrdering_ILU",
696:                     PCILUSetMatOrdering_ILU);
697:   PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCILUSetReuseOrdering_C","PCILUSetReuseOrdering_ILU",
698:                     PCILUSetReuseOrdering_ILU);
699:   PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCILUDTSetReuseFill_C","PCILUDTSetReuseFill_ILUDT",
700:                     PCILUDTSetReuseFill_ILUDT);
701:   PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCILUSetLevels_C","PCILUSetLevels_ILU",
702:                     PCILUSetLevels_ILU);
703:   PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCILUSetUseInPlace_C","PCILUSetUseInPlace_ILU",
704:                     PCILUSetUseInPlace_ILU);
705:   PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCILUSetAllowDiagonalFill_C","PCILUSetAllowDiagonalFill_ILU",
706:                     PCILUSetAllowDiagonalFill_ILU);

708:   return(0);
709: }
710: EXTERN_C_END