2: /* --------------------------------------------------------------------
4: This file implements a SupportGraph preconditioner in PETSc as part of PC.
5: You can use this as a starting point for implementing your own
6: preconditioner that is not provided with PETSc. (You might also consider
7: just using PCSHELL)
9: The following basic routines are required for each preconditioner.
10: PCCreate_XXX() - Creates a preconditioner context
11: PCSetFromOptions_XXX() - Sets runtime options
12: PCApply_XXX() - Applies the preconditioner
13: PCDestroy_XXX() - Destroys the preconditioner context
14: where the suffix "_XXX" denotes a particular implementation, in
15: this case we use _SupportGraph (e.g., PCCreate_SupportGraph, PCApply_SupportGraph).
16: These routines are actually called via the common user interface
17: routines PCCreate(), PCSetFromOptions(), PCApply(), and PCDestroy(),
18: so the application code interface remains identical for all
19: preconditioners.
21: Another key routine is:
22: PCSetUp_XXX() - Prepares for the use of a preconditioner
23: by setting data structures and options. The interface routine PCSetUp()
24: is not usually called directly by the user, but instead is called by
25: PCApply() if necessary.
27: Additional basic routines are:
28: PCView_XXX() - Prints details of runtime options that
29: have actually been used.
30: These are called by application codes via the interface routines
31: PCView().
33: The various types of solvers (preconditioners, Krylov subspace methods,
34: nonlinear solvers, timesteppers) are all organized similarly, so the
35: above description applies to these categories also. One exception is
36: that the analogues of PCApply() for these components are KSPSolve(),
37: SNESSolve(), and TSSolve().
39: Additional optional functionality unique to preconditioners is left and
40: right symmetric preconditioner application via PCApplySymmetricLeft()
41: and PCApplySymmetricRight(). The SupportGraph implementation is
42: PCApplySymmetricLeftOrRight_SupportGraph().
44: -------------------------------------------------------------------- */
46: /*
47: Include files needed for the SupportGraph preconditioner:
48: pcimpl.h - private include file intended for use by all preconditioners
49: adjacency_list.hpp
50: */
52: #include <petsc-private/pcimpl.h> /*I "petscpc.h" I*/
54: /*
55: Private context (data structure) for the SupportGraph preconditioner.
56: */
57: typedef struct {
58: Mat pre; /* Cholesky factored preconditioner matrix */
59: PetscBool augment; /* whether to augment the spanning tree */
60: PetscReal maxCong; /* create subgraph with at most this much congestion (only used with augment) */
61: PetscReal tol; /* throw out entries smaller than this */
62: } PC_SupportGraph;
66: static PetscErrorCode PCView_SupportGraph(PC pc,PetscViewer viewer) 67: {
68: PC_SupportGraph *sg = (PC_SupportGraph*)pc->data;
69: PetscErrorCode ierr;
70: PetscBool iascii;
73: PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);
74: if (iascii) {
75: PetscViewerASCIIPrintf(viewer," SupportGraph: maxCong = %f\n",sg->maxCong);
76: PetscViewerASCIIPrintf(viewer," SupportGraph: tol = %f\n",sg->tol);
77: PetscViewerASCIIPrintf(viewer," Factored Matrix:\n");
78: PetscViewerPushFormat(viewer, PETSC_VIEWER_ASCII_INFO);
79: PetscViewerASCIIPushTab(viewer);
80: PetscViewerASCIIPushTab(viewer);
81: MatView(sg->pre, viewer);
82: PetscViewerASCIIPopTab(viewer);
83: PetscViewerASCIIPopTab(viewer);
84: PetscViewerPopFormat(viewer);
85: }
86: return(0);
87: }
89: extern PetscErrorCode AugmentedLowStretchSpanningTree(Mat mat,Mat *pre,PetscBool augment,PetscReal tol,PetscReal& maxCong);
91: /* -------------------------------------------------------------------------- */
92: /*
93: PCSetUp_SupportGraph - Prepares for the use of the SupportGraph preconditioner
94: by setting data structures and options.
96: Input Parameter:
97: . pc - the preconditioner context
99: Application Interface Routine: PCSetUp()
101: Notes:
102: The interface routine PCSetUp() is not usually called directly by
103: the user, but instead is called by PCApply() if necessary.
104: */
107: static PetscErrorCode PCSetUp_SupportGraph(PC pc)108: {
109: PC_SupportGraph *sg = (PC_SupportGraph*)pc->data;
110: PetscBool isSym;
111: PetscErrorCode ierr;
112: /*
113: Vec diag;
114: PetscInt n,i;
115: PetscScalar *x;
116: PetscBool zeroflag = PETSC_FALSE;
117: */
120: if (!pc->setupcalled) {
121: MatIsSymmetric(pc->pmat, 1.0e-9, &isSym);
122: if (!isSym) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONG,"matrix must be symmetric");
123: /* note that maxCong is being updated */
124: AugmentedLowStretchSpanningTree(pc->pmat, &sg->pre, sg->augment, sg->tol, sg->maxCong);
125: }
126: return(0);
127: }
130: /* -------------------------------------------------------------------------- */
131: /*
132: PCApply_SupportGraph - Applies the SupportGraph preconditioner to a vector.
134: Input Parameters:
135: . pc - the preconditioner context
136: . x - input vector
138: Output Parameter:
139: . y - output vector
141: Application Interface Routine: PCApply()
142: */
145: static PetscErrorCode PCApply_SupportGraph(PC pc,Vec x,Vec y)146: {
147: PC_SupportGraph *sg = (PC_SupportGraph*)pc->data;
148: PetscErrorCode ierr;
151: MatSolve(sg->pre,x,y);
152: return(0);
153: }
154: /* -------------------------------------------------------------------------- */
155: /*
156: PCDestroy_SupportGraph - Destroys the private context for the SupportGraph preconditioner
157: that was created with PCCreate_SupportGraph().
159: Input Parameter:
160: . pc - the preconditioner context
162: Application Interface Routine: PCDestroy()
163: */
166: static PetscErrorCode PCDestroy_SupportGraph(PC pc)167: {
168: PC_SupportGraph *sg = (PC_SupportGraph*)pc->data;
169: PetscErrorCode ierr;
172: MatDestroy(&sg->pre);
173: /*
174: Free the private data structure that was hanging off the PC175: */
176: PetscFree(pc->data);
177: return(0);
178: }
182: static PetscErrorCode PCSetFromOptions_SupportGraph(PC pc)183: {
184: PC_SupportGraph *sg = (PC_SupportGraph*)pc->data;
185: PetscErrorCode ierr;
188: PetscOptionsHead("SupportGraph options");
189: PetscOptionsBool("-pc_sg_augment","Max congestion","",sg->augment,&sg->augment,0);
190: PetscOptionsReal("-pc_sg_cong","Max congestion","",sg->maxCong,&sg->maxCong,0);
191: PetscOptionsReal("-pc_sg_tol","Smallest usable value","",sg->tol,&sg->tol,0);
192: PetscOptionsTail();
193: return(0);
194: }
196: /* -------------------------------------------------------------------------- */
197: /*
198: PCCreate_SupportGraph - Creates a SupportGraph preconditioner context, PC_SupportGraph,
199: and sets this as the private data within the generic preconditioning
200: context, PC, that was created within PCCreate().
202: Input Parameter:
203: . pc - the preconditioner context
205: Application Interface Routine: PCCreate()
206: */
208: /*MC
209: PCSUPPORTGRAPH - SupportGraph (i.e. diagonal scaling preconditioning)
211: Options Database Key:
212: . -pc_supportgraph_augment - augment the spanning tree
214: Level: beginner
216: Concepts: SupportGraph, diagonal scaling, preconditioners
218: Notes: Zero entries along the diagonal are replaced with the value 1.0
220: .seealso: PCCreate(), PCSetType(), PCType (for list of available types), PC221: M*/
225: PETSC_EXTERN PetscErrorCode PCCreate_SupportGraph(PC pc)226: {
227: PC_SupportGraph *sg;
228: PetscErrorCode ierr;
231: /*
232: Creates the private data structure for this preconditioner and
233: attach it to the PC object.
234: */
235: PetscNewLog(pc,PC_SupportGraph,&sg);
236: pc->data = (void*)sg;
238: sg->pre = 0;
239: sg->augment = PETSC_TRUE;
240: sg->maxCong = 3.0;
241: sg->tol = 0;
244: /*
245: Set the pointers for the functions that are provided above.
246: Now when the user-level routines (such as PCApply(), PCDestroy(), etc.)
247: are called, they will automatically call these functions. Note we
248: choose not to provide a couple of these functions since they are
249: not needed.
250: */
251: pc->ops->apply = PCApply_SupportGraph;
252: pc->ops->applytranspose = 0;
253: pc->ops->setup = PCSetUp_SupportGraph;
254: pc->ops->destroy = PCDestroy_SupportGraph;
255: pc->ops->setfromoptions = PCSetFromOptions_SupportGraph;
256: pc->ops->view = PCView_SupportGraph;
257: pc->ops->applyrichardson = 0;
258: pc->ops->applysymmetricleft = 0;
259: pc->ops->applysymmetricright = 0;
260: return(0);
261: }