xref: /petsc/src/ksp/pc/impls/mg/mg.c (revision e1d8e5de39983be2ba3c53bc1c210b941c65a6cf)
1 #define PETSCKSP_DLL
2 
3 /*
4     Defines the multigrid preconditioner interface.
5 */
6 #include "../src/ksp/pc/impls/mg/mgimpl.h"                    /*I "petscmg.h" I*/
7 
8 
9 #undef __FUNCT__
10 #define __FUNCT__ "PCMGMCycle_Private"
11 PetscErrorCode PCMGMCycle_Private(PC pc,PC_MG_Levels **mglevelsin,PCRichardsonConvergedReason *reason)
12 {
13   PC_MG          *mg = (PC_MG*)pc->data;
14   PC_MG_Levels   *mgc,*mglevels = *mglevelsin;
15   PetscErrorCode ierr;
16   PetscInt       cycles = (mglevels->level == 1) ? 1 : (PetscInt) mglevels->cycles;
17 
18   PetscFunctionBegin;
19 
20   if (mg->eventsmoothsolve) {ierr = PetscLogEventBegin(mg->eventsmoothsolve,0,0,0,0);CHKERRQ(ierr);}
21   ierr = KSPSolve(mglevels->smoothd,mglevels->b,mglevels->x);CHKERRQ(ierr);  /* pre-smooth */
22   if (mg->eventsmoothsolve) {ierr = PetscLogEventEnd(mg->eventsmoothsolve,0,0,0,0);CHKERRQ(ierr);}
23   if (mglevels->level) {  /* not the coarsest grid */
24     if (mg->eventresidual) {ierr = PetscLogEventBegin(mg->eventresidual,0,0,0,0);CHKERRQ(ierr);}
25     ierr = (*mglevels->residual)(mglevels->A,mglevels->b,mglevels->x,mglevels->r);CHKERRQ(ierr);
26     if (mg->eventresidual) {ierr = PetscLogEventEnd(mg->eventresidual,0,0,0,0);CHKERRQ(ierr);}
27 
28     /* if on finest level and have convergence criteria set */
29     if (mglevels->level == mglevels->levels-1 && mg->ttol && reason) {
30       PetscReal rnorm;
31       ierr = VecNorm(mglevels->r,NORM_2,&rnorm);CHKERRQ(ierr);
32       if (rnorm <= mg->ttol) {
33         if (rnorm < mg->abstol) {
34           *reason = PCRICHARDSON_CONVERGED_ATOL;
35           ierr = PetscInfo2(pc,"Linear solver has converged. Residual norm %G is less than absolute tolerance %G\n",rnorm,mg->abstol);CHKERRQ(ierr);
36         } else {
37           *reason = PCRICHARDSON_CONVERGED_RTOL;
38           ierr = PetscInfo2(pc,"Linear solver has converged. Residual norm %G is less than relative tolerance times initial residual norm %G\n",rnorm,mg->ttol);CHKERRQ(ierr);
39         }
40         PetscFunctionReturn(0);
41       }
42     }
43 
44     mgc = *(mglevelsin - 1);
45     if (mg->eventinterprestrict) {ierr = PetscLogEventBegin(mg->eventinterprestrict,0,0,0,0);CHKERRQ(ierr);}
46     ierr = MatRestrict(mglevels->restrct,mglevels->r,mgc->b);CHKERRQ(ierr);
47     if (mg->eventinterprestrict) {ierr = PetscLogEventEnd(mg->eventinterprestrict,0,0,0,0);CHKERRQ(ierr);}
48     ierr = VecSet(mgc->x,0.0);CHKERRQ(ierr);
49     while (cycles--) {
50       ierr = PCMGMCycle_Private(pc,mglevelsin-1,reason);CHKERRQ(ierr);
51     }
52     if (mg->eventinterprestrict) {ierr = PetscLogEventBegin(mg->eventinterprestrict,0,0,0,0);CHKERRQ(ierr);}
53     ierr = MatInterpolateAdd(mglevels->interpolate,mgc->x,mglevels->x,mglevels->x);CHKERRQ(ierr);
54     if (mg->eventinterprestrict) {ierr = PetscLogEventEnd(mg->eventinterprestrict,0,0,0,0);CHKERRQ(ierr);}
55     if (mg->eventsmoothsolve) {ierr = PetscLogEventBegin(mg->eventsmoothsolve,0,0,0,0);CHKERRQ(ierr);}
56     ierr = KSPSolve(mglevels->smoothu,mglevels->b,mglevels->x);CHKERRQ(ierr);    /* post smooth */
57     if (mg->eventsmoothsolve) {ierr = PetscLogEventEnd(mg->eventsmoothsolve,0,0,0,0);CHKERRQ(ierr);}
58   }
59   PetscFunctionReturn(0);
60 }
61 
62 #undef __FUNCT__
63 #define __FUNCT__ "PCApplyRichardson_MG"
64 static PetscErrorCode PCApplyRichardson_MG(PC pc,Vec b,Vec x,Vec w,PetscReal rtol,PetscReal abstol, PetscReal dtol,PetscInt its,PetscTruth zeroguess,PetscInt *outits,PCRichardsonConvergedReason *reason)
65 {
66   PC_MG          *mg = (PC_MG*)pc->data;
67   PC_MG_Levels   **mglevels = mg->levels;
68   PetscErrorCode ierr;
69   PetscInt       levels = mglevels[0]->levels,i;
70 
71   PetscFunctionBegin;
72   mglevels[levels-1]->b    = b;
73   mglevels[levels-1]->x    = x;
74 
75   mg->rtol = rtol;
76   mg->abstol = abstol;
77   mg->dtol = dtol;
78   if (rtol) {
79     /* compute initial residual norm for relative convergence test */
80     PetscReal rnorm;
81     if (zeroguess) {
82       ierr               = VecNorm(b,NORM_2,&rnorm);CHKERRQ(ierr);
83     } else {
84       ierr               = (*mglevels[levels-1]->residual)(mglevels[levels-1]->A,b,x,w);CHKERRQ(ierr);
85       ierr               = VecNorm(w,NORM_2,&rnorm);CHKERRQ(ierr);
86     }
87     mg->ttol = PetscMax(rtol*rnorm,abstol);
88   } else if (abstol) {
89     mg->ttol = abstol;
90   } else {
91     mg->ttol = 0.0;
92   }
93 
94   /* since smoother is applied to full system, not just residual we need to make sure that smoothers don't
95      stop prematurely do to small residual */
96   for (i=1; i<levels; i++) {
97     ierr = KSPSetTolerances(mglevels[i]->smoothu,0,PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT);CHKERRQ(ierr);
98     if (mglevels[i]->smoothu != mglevels[i]->smoothd) {
99       ierr = KSPSetTolerances(mglevels[i]->smoothd,0,PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT);CHKERRQ(ierr);
100     }
101   }
102 
103   *reason = (PCRichardsonConvergedReason)0;
104   for (i=0; i<its; i++) {
105     ierr = PCMGMCycle_Private(pc,mglevels+levels-1,reason);CHKERRQ(ierr);
106     if (*reason) break;
107   }
108   if (!*reason) *reason = PCRICHARDSON_CONVERGED_ITS;
109   *outits = i;
110   PetscFunctionReturn(0);
111 }
112 
113 #undef __FUNCT__
114 #define __FUNCT__ "PCMGSetLevels"
115 /*@C
116    PCMGSetLevels - Sets the number of levels to use with MG.
117    Must be called before any other MG routine.
118 
119    Collective on PC
120 
121    Input Parameters:
122 +  pc - the preconditioner context
123 .  levels - the number of levels
124 -  comms - optional communicators for each level; this is to allow solving the coarser problems
125            on smaller sets of processors. Use PETSC_NULL_OBJECT for default in Fortran
126 
127    Level: intermediate
128 
129    Notes:
130      If the number of levels is one then the multigrid uses the -mg_levels prefix
131   for setting the level options rather than the -mg_coarse prefix.
132 
133 .keywords: MG, set, levels, multigrid
134 
135 .seealso: PCMGSetType(), PCMGGetLevels()
136 @*/
137 PetscErrorCode PETSCKSP_DLLEXPORT PCMGSetLevels(PC pc,PetscInt levels,MPI_Comm *comms)
138 {
139   PetscErrorCode ierr;
140   PC_MG          *mg = (PC_MG*)pc->data;
141   MPI_Comm       comm = ((PetscObject)pc)->comm;
142   PC_MG_Levels   **mglevels;
143   PetscInt       i;
144   PetscMPIInt    size;
145   const char     *prefix;
146   PC             ipc;
147 
148   PetscFunctionBegin;
149   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
150   if (mg->nlevels > -1) SETERRQ(((PetscObject)pc)->comm,PETSC_ERR_ORDER,"Number levels already set for MG\n  make sure that you call PCMGSetLevels() before KSPSetFromOptions()");
151   if (mg->levels) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Internal error in PETSc, this array should not yet exist");
152 
153   mg->nlevels      = levels;
154   mg->galerkin     = PETSC_FALSE;
155   mg->galerkinused = PETSC_FALSE;
156 
157   ierr = PetscMalloc(levels*sizeof(PC_MG*),&mglevels);CHKERRQ(ierr);
158   ierr = PetscLogObjectMemory(pc,levels*(sizeof(PC_MG*)));CHKERRQ(ierr);
159 
160   ierr = PCGetOptionsPrefix(pc,&prefix);CHKERRQ(ierr);
161 
162   for (i=0; i<levels; i++) {
163     ierr = PetscNewLog(pc,PC_MG_Levels,&mglevels[i]);CHKERRQ(ierr);
164     mglevels[i]->level           = i;
165     mglevels[i]->levels          = levels;
166     mglevels[i]->cycles          = PC_MG_CYCLE_V;
167     mg->default_smoothu = 1;
168     mg->default_smoothd = 1;
169 
170     if (comms) comm = comms[i];
171     ierr = KSPCreate(comm,&mglevels[i]->smoothd);CHKERRQ(ierr);
172     ierr = PetscObjectIncrementTabLevel((PetscObject)mglevels[i]->smoothd,(PetscObject)pc,levels-i);CHKERRQ(ierr);
173     ierr = KSPSetTolerances(mglevels[i]->smoothd,PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT, mg->default_smoothd);CHKERRQ(ierr);
174     ierr = KSPSetOptionsPrefix(mglevels[i]->smoothd,prefix);CHKERRQ(ierr);
175 
176     /* do special stuff for coarse grid */
177     if (!i && levels > 1) {
178       ierr = KSPAppendOptionsPrefix(mglevels[0]->smoothd,"mg_coarse_");CHKERRQ(ierr);
179 
180       /* coarse solve is (redundant) LU by default */
181       ierr = KSPSetType(mglevels[0]->smoothd,KSPPREONLY);CHKERRQ(ierr);
182       ierr = KSPGetPC(mglevels[0]->smoothd,&ipc);CHKERRQ(ierr);
183       ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
184       if (size > 1) {
185         ierr = PCSetType(ipc,PCREDUNDANT);CHKERRQ(ierr);
186       } else {
187         ierr = PCSetType(ipc,PCLU);CHKERRQ(ierr);
188       }
189 
190     } else {
191       char tprefix[128];
192       sprintf(tprefix,"mg_levels_%d_",(int)i);
193       ierr = KSPAppendOptionsPrefix(mglevels[i]->smoothd,tprefix);CHKERRQ(ierr);
194     }
195     ierr = PetscLogObjectParent(pc,mglevels[i]->smoothd);CHKERRQ(ierr);
196     mglevels[i]->smoothu    = mglevels[i]->smoothd;
197     mg->rtol                = 0.0;
198     mg->abstol              = 0.0;
199     mg->dtol                = 0.0;
200     mg->ttol                = 0.0;
201     mg->eventsmoothsetup    = 0;
202     mg->eventsmoothsolve    = 0;
203     mg->eventresidual       = 0;
204     mg->eventinterprestrict = 0;
205     mg->cyclesperpcapply    = 1;
206   }
207   mg->am          = PC_MG_MULTIPLICATIVE;
208   mg->levels      = mglevels;
209   pc->ops->applyrichardson = PCApplyRichardson_MG;
210   PetscFunctionReturn(0);
211 }
212 
213 #undef __FUNCT__
214 #define __FUNCT__ "PCDestroy_MG_Private"
215 PetscErrorCode PCDestroy_MG_Private(PC pc)
216 {
217   PC_MG          *mg = (PC_MG*)pc->data;
218   PC_MG_Levels   **mglevels = mg->levels;
219   PetscErrorCode ierr;
220   PetscInt       i,n;
221 
222   PetscFunctionBegin;
223   if (mglevels) {
224     n = mglevels[0]->levels;
225     for (i=0; i<n-1; i++) {
226       if (mglevels[i+1]->r) {ierr = VecDestroy(mglevels[i+1]->r);CHKERRQ(ierr);}
227       if (mglevels[i]->b) {ierr = VecDestroy(mglevels[i]->b);CHKERRQ(ierr);}
228       if (mglevels[i]->x) {ierr = VecDestroy(mglevels[i]->x);CHKERRQ(ierr);}
229       if (mglevels[i+1]->restrct) {ierr = MatDestroy(mglevels[i+1]->restrct);CHKERRQ(ierr);}
230       if (mglevels[i+1]->interpolate) {ierr = MatDestroy(mglevels[i+1]->interpolate);CHKERRQ(ierr);}
231     }
232 
233     for (i=0; i<n; i++) {
234       if (mglevels[i]->smoothd != mglevels[i]->smoothu) {
235 	ierr = KSPDestroy(mglevels[i]->smoothd);CHKERRQ(ierr);
236       }
237       ierr = KSPDestroy(mglevels[i]->smoothu);CHKERRQ(ierr);
238       ierr = PetscFree(mglevels[i]);CHKERRQ(ierr);
239     }
240     ierr = PetscFree(mglevels);CHKERRQ(ierr);
241   }
242   mg->nlevels = -1;
243   mg->levels  = PETSC_NULL;
244   PetscFunctionReturn(0);
245 }
246 
247 #undef __FUNCT__
248 #define __FUNCT__ "PCDestroy_MG"
249 PetscErrorCode PCDestroy_MG(PC pc)
250 {
251   PC_MG          *mg = (PC_MG*)pc->data;
252   PetscErrorCode ierr;
253 
254   PetscFunctionBegin;
255   ierr = PCDestroy_MG_Private(pc);CHKERRQ(ierr);
256   ierr = PetscFree(mg);CHKERRQ(ierr);
257   PetscFunctionReturn(0);
258 }
259 
260 
261 
262 EXTERN PetscErrorCode PCMGACycle_Private(PC,PC_MG_Levels**);
263 EXTERN PetscErrorCode PCMGFCycle_Private(PC,PC_MG_Levels**);
264 EXTERN PetscErrorCode PCMGKCycle_Private(PC,PC_MG_Levels**);
265 
266 /*
267    PCApply_MG - Runs either an additive, multiplicative, Kaskadic
268              or full cycle of multigrid.
269 
270   Note:
271   A simple wrapper which calls PCMGMCycle(),PCMGACycle(), or PCMGFCycle().
272 */
273 #undef __FUNCT__
274 #define __FUNCT__ "PCApply_MG"
275 static PetscErrorCode PCApply_MG(PC pc,Vec b,Vec x)
276 {
277   PC_MG          *mg = (PC_MG*)pc->data;
278   PC_MG_Levels   **mglevels = mg->levels;
279   PetscErrorCode ierr;
280   PetscInt       levels = mglevels[0]->levels,i;
281 
282   PetscFunctionBegin;
283 
284   /* When the DM is supplying the matrix then it will not exist until here */
285   for (i=0; i<levels-1; i++) {
286     if (!mglevels[i]->A) {
287       ierr = KSPGetOperators(mglevels[i]->smoothu,&mglevels[i]->A,PETSC_NULL,PETSC_NULL);CHKERRQ(ierr);
288     }
289   }
290 
291   mglevels[levels-1]->b = b;
292   mglevels[levels-1]->x = x;
293   if (mg->am == PC_MG_MULTIPLICATIVE) {
294     ierr = VecSet(x,0.0);CHKERRQ(ierr);
295     for (i=0; i<mg->cyclesperpcapply; i++) {
296       ierr = PCMGMCycle_Private(pc,mglevels+levels-1,PETSC_NULL);CHKERRQ(ierr);
297     }
298   }
299   else if (mg->am == PC_MG_ADDITIVE) {
300     ierr = PCMGACycle_Private(pc,mglevels);CHKERRQ(ierr);
301   }
302   else if (mg->am == PC_MG_KASKADE) {
303     ierr = PCMGKCycle_Private(pc,mglevels);CHKERRQ(ierr);
304   }
305   else {
306     ierr = PCMGFCycle_Private(pc,mglevels);CHKERRQ(ierr);
307   }
308   PetscFunctionReturn(0);
309 }
310 
311 
312 #undef __FUNCT__
313 #define __FUNCT__ "PCSetFromOptions_MG"
314 PetscErrorCode PCSetFromOptions_MG(PC pc)
315 {
316   PetscErrorCode ierr;
317   PetscInt       m,levels = 1,cycles;
318   PetscTruth     flg;
319   PC_MG          *mg = (PC_MG*)pc->data;
320   PC_MG_Levels   **mglevels = mg->levels;
321   PCMGType       mgtype;
322   PCMGCycleType  mgctype;
323 
324   PetscFunctionBegin;
325   ierr = PetscOptionsHead("Multigrid options");CHKERRQ(ierr);
326     if (!mglevels) {
327       ierr = PetscOptionsInt("-pc_mg_levels","Number of Levels","PCMGSetLevels",levels,&levels,&flg);CHKERRQ(ierr);
328       ierr = PCMGSetLevels(pc,levels,PETSC_NULL);CHKERRQ(ierr);
329       mglevels = mg->levels;
330     }
331     mgctype = (PCMGCycleType) mglevels[0]->cycles;
332     ierr = PetscOptionsEnum("-pc_mg_cycle_type","V cycle or for W-cycle","PCMGSetCycleType",PCMGCycleTypes,(PetscEnum)mgctype,(PetscEnum*)&mgctype,&flg);CHKERRQ(ierr);
333     if (flg) {
334       ierr = PCMGSetCycleType(pc,mgctype);CHKERRQ(ierr);
335     };
336     flg  = PETSC_FALSE;
337     ierr = PetscOptionsTruth("-pc_mg_galerkin","Use Galerkin process to compute coarser operators","PCMGSetGalerkin",flg,&flg,PETSC_NULL);CHKERRQ(ierr);
338     if (flg) {
339       ierr = PCMGSetGalerkin(pc);CHKERRQ(ierr);
340     }
341     ierr = PetscOptionsInt("-pc_mg_smoothup","Number of post-smoothing steps","PCMGSetNumberSmoothUp",1,&m,&flg);CHKERRQ(ierr);
342     if (flg) {
343       ierr = PCMGSetNumberSmoothUp(pc,m);CHKERRQ(ierr);
344     }
345     ierr = PetscOptionsInt("-pc_mg_smoothdown","Number of pre-smoothing steps","PCMGSetNumberSmoothDown",1,&m,&flg);CHKERRQ(ierr);
346     if (flg) {
347       ierr = PCMGSetNumberSmoothDown(pc,m);CHKERRQ(ierr);
348     }
349     mgtype = mg->am;
350     ierr = PetscOptionsEnum("-pc_mg_type","Multigrid type","PCMGSetType",PCMGTypes,(PetscEnum)mgtype,(PetscEnum*)&mgtype,&flg);CHKERRQ(ierr);
351     if (flg) {
352       ierr = PCMGSetType(pc,mgtype);CHKERRQ(ierr);
353     }
354     if (mg->am == PC_MG_MULTIPLICATIVE) {
355       ierr = PetscOptionsInt("-pc_mg_multiplicative_cycles","Number of cycles for each preconditioner step","PCMGSetLevels",mg->cyclesperpcapply,&cycles,&flg);CHKERRQ(ierr);
356       if (flg) {
357 	ierr = PCMGMultiplicativeSetCycles(pc,cycles);CHKERRQ(ierr);
358       }
359     }
360     flg  = PETSC_FALSE;
361     ierr = PetscOptionsTruth("-pc_mg_log","Log times for each multigrid level","None",flg,&flg,PETSC_NULL);CHKERRQ(ierr);
362     if (flg) {
363       PetscInt i;
364       char     eventname[128];
365       if (!mg) SETERRQ(((PetscObject)pc)->comm,PETSC_ERR_ARG_WRONGSTATE,"Must set MG levels before calling");
366       levels = mglevels[0]->levels;
367       for (i=0; i<levels; i++) {
368         sprintf(eventname,"MGSetup Level %d",(int)i);
369         ierr = PetscLogEventRegister(eventname,((PetscObject)pc)->classid,&mg->eventsmoothsetup);CHKERRQ(ierr);
370         sprintf(eventname,"MGSmooth Level %d",(int)i);
371         ierr = PetscLogEventRegister(eventname,((PetscObject)pc)->classid,&mg->eventsmoothsolve);CHKERRQ(ierr);
372         if (i) {
373           sprintf(eventname,"MGResid Level %d",(int)i);
374           ierr = PetscLogEventRegister(eventname,((PetscObject)pc)->classid,&mg->eventresidual);CHKERRQ(ierr);
375           sprintf(eventname,"MGInterp Level %d",(int)i);
376           ierr = PetscLogEventRegister(eventname,((PetscObject)pc)->classid,&mg->eventinterprestrict);CHKERRQ(ierr);
377         }
378       }
379     }
380   ierr = PetscOptionsTail();CHKERRQ(ierr);
381   PetscFunctionReturn(0);
382 }
383 
384 const char *PCMGTypes[] = {"MULTIPLICATIVE","ADDITIVE","FULL","KASKADE","PCMGType","PC_MG",0};
385 const char *PCMGCycleTypes[] = {"invalid","v","w","PCMGCycleType","PC_MG_CYCLE",0};
386 
387 #undef __FUNCT__
388 #define __FUNCT__ "PCView_MG"
389 PetscErrorCode PCView_MG(PC pc,PetscViewer viewer)
390 {
391   PC_MG          *mg = (PC_MG*)pc->data;
392   PC_MG_Levels   **mglevels = mg->levels;
393   PetscErrorCode ierr;
394   PetscInt       levels = mglevels[0]->levels,i;
395   PetscTruth     iascii;
396 
397   PetscFunctionBegin;
398   ierr = PetscTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
399   if (iascii) {
400     ierr = PetscViewerASCIIPrintf(viewer,"  MG: type is %s, levels=%D cycles=%s\n", PCMGTypes[mg->am],levels,(mglevels[0]->cycles == PC_MG_CYCLE_V) ? "v" : "w");CHKERRQ(ierr);
401     if (mg->am == PC_MG_MULTIPLICATIVE) {
402       ierr = PetscViewerASCIIPrintf(viewer,"    Cycles per PCApply=%d\n",mg->cyclesperpcapply);CHKERRQ(ierr);
403     }
404     if (mg->galerkin) {
405       ierr = PetscViewerASCIIPrintf(viewer,"    Using Galerkin computed coarse grid matrices\n");CHKERRQ(ierr);
406     } else {
407       ierr = PetscViewerASCIIPrintf(viewer,"    Not using Galerkin computed coarse grid matrices\n");CHKERRQ(ierr);
408     }
409     for (i=0; i<levels; i++) {
410       if (!i) {
411         ierr = PetscViewerASCIIPrintf(viewer,"Coarse grid solver -- level %D presmooths=%D postsmooths=%D -----\n",i,mg->default_smoothd,mg->default_smoothu);CHKERRQ(ierr);
412       } else {
413         ierr = PetscViewerASCIIPrintf(viewer,"Down solver (pre-smoother) on level %D smooths=%D --------------------\n",i,mg->default_smoothd);CHKERRQ(ierr);
414       }
415       ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr);
416       ierr = KSPView(mglevels[i]->smoothd,viewer);CHKERRQ(ierr);
417       ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr);
418       if (i && mglevels[i]->smoothd == mglevels[i]->smoothu) {
419         ierr = PetscViewerASCIIPrintf(viewer,"Up solver (post-smoother) same as down solver (pre-smoother)\n");CHKERRQ(ierr);
420       } else if (i){
421         ierr = PetscViewerASCIIPrintf(viewer,"Up solver (post-smoother) on level %D smooths=%D --------------------\n",i,mg->default_smoothu);CHKERRQ(ierr);
422         ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr);
423         ierr = KSPView(mglevels[i]->smoothu,viewer);CHKERRQ(ierr);
424         ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr);
425       }
426     }
427   } else {
428     SETERRQ1(((PetscObject)pc)->comm,PETSC_ERR_SUP,"Viewer type %s not supported for PCMG",((PetscObject)viewer)->type_name);
429   }
430   PetscFunctionReturn(0);
431 }
432 
433 /*
434     Calls setup for the KSP on each level
435 */
436 #undef __FUNCT__
437 #define __FUNCT__ "PCSetUp_MG"
438 PetscErrorCode PCSetUp_MG(PC pc)
439 {
440   PC_MG                   *mg = (PC_MG*)pc->data;
441   PC_MG_Levels            **mglevels = mg->levels;
442   PetscErrorCode          ierr;
443   PetscInt                i,n = mglevels[0]->levels;
444   PC                      cpc,mpc;
445   PetscTruth              preonly,lu,redundant,cholesky,monitor = PETSC_FALSE,dump = PETSC_FALSE,opsset;
446   PetscViewerASCIIMonitor ascii;
447   PetscViewer             viewer = PETSC_NULL;
448   MPI_Comm                comm;
449   Mat                     dA,dB;
450   MatStructure            uflag;
451   Vec                     tvec;
452   DM                      *dms;
453 
454   PetscFunctionBegin;
455 
456   /* If user did not provide fine grid operators OR operator was not updated since last global KSPSetOperators() */
457   /* so use those from global PC */
458   /* Is this what we always want? What if user wants to keep old one? */
459   ierr = KSPGetOperatorsSet(mglevels[n-1]->smoothd,PETSC_NULL,&opsset);CHKERRQ(ierr);
460   ierr = KSPGetPC(mglevels[0]->smoothd,&cpc);CHKERRQ(ierr);
461   ierr = KSPGetPC(mglevels[n-1]->smoothd,&mpc);CHKERRQ(ierr);
462   if (!opsset || ((cpc->setupcalled == 1) && (mpc->setupcalled == 2)) || ((mpc == cpc) && (mpc->setupcalled == 2))) {
463     ierr = PetscInfo(pc,"Using outer operators to define finest grid operator \n  because PCMGGetSmoother(pc,nlevels-1,&ksp);KSPSetOperators(ksp,...); was not called.\n");CHKERRQ(ierr);
464     ierr = KSPSetOperators(mglevels[n-1]->smoothd,pc->mat,pc->pmat,pc->flag);CHKERRQ(ierr);
465   }
466 
467   if (pc->dm && !pc->setupcalled) {
468     /* construct the interpolation from the DMs */
469     Mat p;
470     ierr = PetscMalloc(n*sizeof(DM),&dms);CHKERRQ(ierr);
471     dms[n-1] = pc->dm;
472     for (i=n-2; i>-1; i--) {
473       ierr = DMCoarsen(dms[i+1],PETSC_NULL,&dms[i]);CHKERRQ(ierr);
474       ierr = DMSetFunction(dms[i],0);
475       ierr = DMSetInitialGuess(dms[i],0);
476       if (!mglevels[i+1]->interpolate) {
477 	ierr = DMGetInterpolation(dms[i],dms[i+1],&p,PETSC_NULL);CHKERRQ(ierr);
478 	ierr = PCMGSetInterpolation(pc,i+1,p);CHKERRQ(ierr);
479         ierr = MatDestroy(p);CHKERRQ(ierr);
480       }
481     }
482 
483     if (!mg->galerkin) {
484       /* each coarse level gets its DM */
485       for (i=n-2; i>-1; i--) {
486         ierr = KSPSetDM(mglevels[i]->smoothd,dms[i]);CHKERRQ(ierr);
487       }
488     }
489 
490     for (i=n-2; i>-1; i--) {
491       ierr = DMDestroy(dms[i]);CHKERRQ(ierr);
492     }
493     ierr = PetscFree(dms);CHKERRQ(ierr);
494   }
495 
496   if (mg->galerkin) {
497     Mat B;
498     mg->galerkinused = PETSC_TRUE;
499     /* currently only handle case where mat and pmat are the same on coarser levels */
500     ierr = KSPGetOperators(mglevels[n-1]->smoothd,&dA,&dB,&uflag);CHKERRQ(ierr);
501     if (!pc->setupcalled) {
502       for (i=n-2; i>-1; i--) {
503         ierr = MatPtAP(dB,mglevels[i+1]->interpolate,MAT_INITIAL_MATRIX,1.0,&B);CHKERRQ(ierr);
504         ierr = KSPSetOperators(mglevels[i]->smoothd,B,B,uflag);CHKERRQ(ierr);
505 	if (i != n-2) {ierr = PetscObjectDereference((PetscObject)dB);CHKERRQ(ierr);}
506         dB   = B;
507       }
508     } else {
509       for (i=n-2; i>-1; i--) {
510         ierr = KSPGetOperators(mglevels[i]->smoothd,PETSC_NULL,&B,PETSC_NULL);CHKERRQ(ierr);
511         ierr = MatPtAP(dB,mglevels[i+1]->interpolate,MAT_REUSE_MATRIX,1.0,&B);CHKERRQ(ierr);
512         ierr = KSPSetOperators(mglevels[i]->smoothd,B,B,uflag);CHKERRQ(ierr);
513         dB   = B;
514       }
515     }
516   }
517 
518   if (!pc->setupcalled) {
519     ierr = PetscOptionsGetTruth(0,"-pc_mg_monitor",&monitor,PETSC_NULL);CHKERRQ(ierr);
520 
521     for (i=0; i<n; i++) {
522       if (monitor) {
523         ierr = PetscObjectGetComm((PetscObject)mglevels[i]->smoothd,&comm);CHKERRQ(ierr);
524         ierr = PetscViewerASCIIMonitorCreate(comm,"stdout",n-i,&ascii);CHKERRQ(ierr);
525         ierr = KSPMonitorSet(mglevels[i]->smoothd,KSPMonitorDefault,ascii,(PetscErrorCode(*)(void*))PetscViewerASCIIMonitorDestroy);CHKERRQ(ierr);
526       }
527       ierr = KSPSetFromOptions(mglevels[i]->smoothd);CHKERRQ(ierr);
528     }
529     for (i=1; i<n; i++) {
530       if (mglevels[i]->smoothu && (mglevels[i]->smoothu != mglevels[i]->smoothd)) {
531         if (monitor) {
532           ierr = PetscObjectGetComm((PetscObject)mglevels[i]->smoothu,&comm);CHKERRQ(ierr);
533           ierr = PetscViewerASCIIMonitorCreate(comm,"stdout",n-i,&ascii);CHKERRQ(ierr);
534           ierr = KSPMonitorSet(mglevels[i]->smoothu,KSPMonitorDefault,ascii,(PetscErrorCode(*)(void*))PetscViewerASCIIMonitorDestroy);CHKERRQ(ierr);
535         }
536         ierr = KSPSetFromOptions(mglevels[i]->smoothu);CHKERRQ(ierr);
537       }
538     }
539     for (i=1; i<n; i++) {
540       if (!mglevels[i]->residual) {
541         Mat mat;
542         ierr = KSPGetOperators(mglevels[i]->smoothd,PETSC_NULL,&mat,PETSC_NULL);CHKERRQ(ierr);
543         ierr = PCMGSetResidual(pc,i,PCMGDefaultResidual,mat);CHKERRQ(ierr);
544       }
545       if (mglevels[i]->restrct && !mglevels[i]->interpolate) {
546         ierr = PCMGSetInterpolation(pc,i,mglevels[i]->restrct);CHKERRQ(ierr);
547       }
548       if (!mglevels[i]->restrct && mglevels[i]->interpolate) {
549         ierr = PCMGSetRestriction(pc,i,mglevels[i]->interpolate);CHKERRQ(ierr);
550       }
551 #if defined(PETSC_USE_DEBUG)
552       if (!mglevels[i]->restrct || !mglevels[i]->interpolate) {
553         SETERRQ1(((PetscObject)pc)->comm,PETSC_ERR_ARG_WRONGSTATE,"Need to set restriction or interpolation on level %d",(int)i);
554       }
555 #endif
556     }
557     for (i=0; i<n-1; i++) {
558       if (!mglevels[i]->b) {
559         Vec *vec;
560         ierr = KSPGetVecs(mglevels[i]->smoothd,1,&vec,0,PETSC_NULL);CHKERRQ(ierr);
561         ierr = PCMGSetRhs(pc,i,*vec);CHKERRQ(ierr);
562         ierr = VecDestroy(*vec);CHKERRQ(ierr);
563         ierr = PetscFree(vec);CHKERRQ(ierr);
564       }
565       if (!mglevels[i]->r && i) {
566         ierr = VecDuplicate(mglevels[i]->b,&tvec);CHKERRQ(ierr);
567         ierr = PCMGSetR(pc,i,tvec);CHKERRQ(ierr);
568         ierr = VecDestroy(tvec);CHKERRQ(ierr);
569       }
570       if (!mglevels[i]->x) {
571         ierr = VecDuplicate(mglevels[i]->b,&tvec);CHKERRQ(ierr);
572         ierr = PCMGSetX(pc,i,tvec);CHKERRQ(ierr);
573         ierr = VecDestroy(tvec);CHKERRQ(ierr);
574       }
575     }
576     if (n != 1 && !mglevels[n-1]->r) {
577       /* PCMGSetR() on the finest level if user did not supply it */
578       Vec *vec;
579       ierr = KSPGetVecs(mglevels[n-1]->smoothd,1,&vec,0,PETSC_NULL);CHKERRQ(ierr);
580       ierr = PCMGSetR(pc,n-1,*vec);CHKERRQ(ierr);
581       ierr = VecDestroy(*vec);CHKERRQ(ierr);
582       ierr = PetscFree(vec);CHKERRQ(ierr);
583     }
584   }
585 
586 
587   for (i=1; i<n; i++) {
588     if (mglevels[i]->smoothu == mglevels[i]->smoothd) {
589       /* if doing only down then initial guess is zero */
590       ierr = KSPSetInitialGuessNonzero(mglevels[i]->smoothd,PETSC_TRUE);CHKERRQ(ierr);
591     }
592     if (mg->eventsmoothsetup) {ierr = PetscLogEventBegin(mg->eventsmoothsetup,0,0,0,0);CHKERRQ(ierr);}
593     ierr = KSPSetUp(mglevels[i]->smoothd);CHKERRQ(ierr);
594     if (mg->eventsmoothsetup) {ierr = PetscLogEventEnd(mg->eventsmoothsetup,0,0,0,0);CHKERRQ(ierr);}
595   }
596   for (i=1; i<n; i++) {
597     if (mglevels[i]->smoothu && mglevels[i]->smoothu != mglevels[i]->smoothd) {
598       Mat          downmat,downpmat;
599       MatStructure matflag;
600       PetscTruth   opsset;
601 
602       /* check if operators have been set for up, if not use down operators to set them */
603       ierr = KSPGetOperatorsSet(mglevels[i]->smoothu,&opsset,PETSC_NULL);CHKERRQ(ierr);
604       if (!opsset) {
605         ierr = KSPGetOperators(mglevels[i]->smoothd,&downmat,&downpmat,&matflag);CHKERRQ(ierr);
606         ierr = KSPSetOperators(mglevels[i]->smoothu,downmat,downpmat,matflag);CHKERRQ(ierr);
607       }
608 
609       ierr = KSPSetInitialGuessNonzero(mglevels[i]->smoothu,PETSC_TRUE);CHKERRQ(ierr);
610       if (mg->eventsmoothsetup) {ierr = PetscLogEventBegin(mg->eventsmoothsetup,0,0,0,0);CHKERRQ(ierr);}
611       ierr = KSPSetUp(mglevels[i]->smoothu);CHKERRQ(ierr);
612       if (mg->eventsmoothsetup) {ierr = PetscLogEventEnd(mg->eventsmoothsetup,0,0,0,0);CHKERRQ(ierr);}
613     }
614   }
615 
616   /*
617       If coarse solver is not direct method then DO NOT USE preonly
618   */
619   ierr = PetscTypeCompare((PetscObject)mglevels[0]->smoothd,KSPPREONLY,&preonly);CHKERRQ(ierr);
620   if (preonly) {
621     ierr = PetscTypeCompare((PetscObject)cpc,PCLU,&lu);CHKERRQ(ierr);
622     ierr = PetscTypeCompare((PetscObject)cpc,PCREDUNDANT,&redundant);CHKERRQ(ierr);
623     ierr = PetscTypeCompare((PetscObject)cpc,PCCHOLESKY,&cholesky);CHKERRQ(ierr);
624     if (!lu && !redundant && !cholesky) {
625       ierr = KSPSetType(mglevels[0]->smoothd,KSPGMRES);CHKERRQ(ierr);
626     }
627   }
628 
629   if (!pc->setupcalled) {
630     if (monitor) {
631       ierr = PetscObjectGetComm((PetscObject)mglevels[0]->smoothd,&comm);CHKERRQ(ierr);
632       ierr = PetscViewerASCIIMonitorCreate(comm,"stdout",n,&ascii);CHKERRQ(ierr);
633       ierr = KSPMonitorSet(mglevels[0]->smoothd,KSPMonitorDefault,ascii,(PetscErrorCode(*)(void*))PetscViewerASCIIMonitorDestroy);CHKERRQ(ierr);
634     }
635     ierr = KSPSetFromOptions(mglevels[0]->smoothd);CHKERRQ(ierr);
636   }
637 
638   if (mg->eventsmoothsetup) {ierr = PetscLogEventBegin(mg->eventsmoothsetup,0,0,0,0);CHKERRQ(ierr);}
639   ierr = KSPSetUp(mglevels[0]->smoothd);CHKERRQ(ierr);
640   if (mg->eventsmoothsetup) {ierr = PetscLogEventEnd(mg->eventsmoothsetup,0,0,0,0);CHKERRQ(ierr);}
641 
642   /*
643      Dump the interpolation/restriction matrices plus the
644    Jacobian/stiffness on each level. This allows Matlab users to
645    easily check if the Galerkin condition A_c = R A_f R^T is satisfied.
646 
647    Only support one or the other at the same time.
648   */
649 #if defined(PETSC_USE_SOCKET_VIEWER)
650   ierr = PetscOptionsGetTruth(((PetscObject)pc)->prefix,"-pc_mg_dump_matlab",&dump,PETSC_NULL);CHKERRQ(ierr);
651   if (dump) {
652     viewer = PETSC_VIEWER_SOCKET_(((PetscObject)pc)->comm);
653   }
654   dump = PETSC_FALSE;
655 #endif
656   ierr = PetscOptionsGetTruth(((PetscObject)pc)->prefix,"-pc_mg_dump_binary",&dump,PETSC_NULL);CHKERRQ(ierr);
657   if (dump) {
658     viewer = PETSC_VIEWER_BINARY_(((PetscObject)pc)->comm);
659   }
660 
661   if (viewer) {
662     for (i=1; i<n; i++) {
663       ierr = MatView(mglevels[i]->restrct,viewer);CHKERRQ(ierr);
664     }
665     for (i=0; i<n; i++) {
666       ierr = KSPGetPC(mglevels[i]->smoothd,&pc);CHKERRQ(ierr);
667       ierr = MatView(pc->mat,viewer);CHKERRQ(ierr);
668     }
669   }
670   PetscFunctionReturn(0);
671 }
672 
673 /* -------------------------------------------------------------------------------------*/
674 
675 #undef __FUNCT__
676 #define __FUNCT__ "PCMGGetLevels"
677 /*@
678    PCMGGetLevels - Gets the number of levels to use with MG.
679 
680    Not Collective
681 
682    Input Parameter:
683 .  pc - the preconditioner context
684 
685    Output parameter:
686 .  levels - the number of levels
687 
688    Level: advanced
689 
690 .keywords: MG, get, levels, multigrid
691 
692 .seealso: PCMGSetLevels()
693 @*/
694 PetscErrorCode PETSCKSP_DLLEXPORT PCMGGetLevels(PC pc,PetscInt *levels)
695 {
696   PC_MG *mg = (PC_MG*)pc->data;
697 
698   PetscFunctionBegin;
699   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
700   PetscValidIntPointer(levels,2);
701   *levels = mg->nlevels;
702   PetscFunctionReturn(0);
703 }
704 
705 #undef __FUNCT__
706 #define __FUNCT__ "PCMGSetType"
707 /*@
708    PCMGSetType - Determines the form of multigrid to use:
709    multiplicative, additive, full, or the Kaskade algorithm.
710 
711    Collective on PC
712 
713    Input Parameters:
714 +  pc - the preconditioner context
715 -  form - multigrid form, one of PC_MG_MULTIPLICATIVE, PC_MG_ADDITIVE,
716    PC_MG_FULL, PC_MG_KASKADE
717 
718    Options Database Key:
719 .  -pc_mg_type <form> - Sets <form>, one of multiplicative,
720    additive, full, kaskade
721 
722    Level: advanced
723 
724 .keywords: MG, set, method, multiplicative, additive, full, Kaskade, multigrid
725 
726 .seealso: PCMGSetLevels()
727 @*/
728 PetscErrorCode PETSCKSP_DLLEXPORT PCMGSetType(PC pc,PCMGType form)
729 {
730   PC_MG                   *mg = (PC_MG*)pc->data;
731 
732   PetscFunctionBegin;
733   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
734   mg->am = form;
735   if (form == PC_MG_MULTIPLICATIVE) pc->ops->applyrichardson = PCApplyRichardson_MG;
736   else pc->ops->applyrichardson = 0;
737   PetscFunctionReturn(0);
738 }
739 
740 #undef __FUNCT__
741 #define __FUNCT__ "PCMGSetCycleType"
742 /*@
743    PCMGSetCycleType - Sets the type cycles to use.  Use PCMGSetCycleTypeOnLevel() for more
744    complicated cycling.
745 
746    Collective on PC
747 
748    Input Parameters:
749 +  pc - the multigrid context
750 -  PC_MG_CYCLE_V or PC_MG_CYCLE_W
751 
752    Options Database Key:
753 $  -pc_mg_cycle_type v or w
754 
755    Level: advanced
756 
757 .keywords: MG, set, cycles, V-cycle, W-cycle, multigrid
758 
759 .seealso: PCMGSetCycleTypeOnLevel()
760 @*/
761 PetscErrorCode PETSCKSP_DLLEXPORT PCMGSetCycleType(PC pc,PCMGCycleType n)
762 {
763   PC_MG        *mg = (PC_MG*)pc->data;
764   PC_MG_Levels **mglevels = mg->levels;
765   PetscInt     i,levels;
766 
767   PetscFunctionBegin;
768   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
769   if (!mglevels) SETERRQ(((PetscObject)pc)->comm,PETSC_ERR_ARG_WRONGSTATE,"Must set MG levels before calling");
770   levels = mglevels[0]->levels;
771 
772   for (i=0; i<levels; i++) {
773     mglevels[i]->cycles  = n;
774   }
775   PetscFunctionReturn(0);
776 }
777 
778 #undef __FUNCT__
779 #define __FUNCT__ "PCMGMultiplicativeSetCycles"
780 /*@
781    PCMGMultiplicativeSetCycles - Sets the number of cycles to use for each preconditioner step
782          of multigrid when PCMGType of PC_MG_MULTIPLICATIVE is used
783 
784    Collective on PC
785 
786    Input Parameters:
787 +  pc - the multigrid context
788 -  n - number of cycles (default is 1)
789 
790    Options Database Key:
791 $  -pc_mg_multiplicative_cycles n
792 
793    Level: advanced
794 
795    Notes: This is not associated with setting a v or w cycle, that is set with PCMGSetCycleType()
796 
797 .keywords: MG, set, cycles, V-cycle, W-cycle, multigrid
798 
799 .seealso: PCMGSetCycleTypeOnLevel(), PCMGSetCycleType()
800 @*/
801 PetscErrorCode PETSCKSP_DLLEXPORT PCMGMultiplicativeSetCycles(PC pc,PetscInt n)
802 {
803   PC_MG        *mg = (PC_MG*)pc->data;
804   PC_MG_Levels **mglevels = mg->levels;
805   PetscInt     i,levels;
806 
807   PetscFunctionBegin;
808   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
809   if (!mglevels) SETERRQ(((PetscObject)pc)->comm,PETSC_ERR_ARG_WRONGSTATE,"Must set MG levels before calling");
810   levels = mglevels[0]->levels;
811 
812   for (i=0; i<levels; i++) {
813     mg->cyclesperpcapply  = n;
814   }
815   PetscFunctionReturn(0);
816 }
817 
818 #undef __FUNCT__
819 #define __FUNCT__ "PCMGSetGalerkin"
820 /*@
821    PCMGSetGalerkin - Causes the coarser grid matrices to be computed from the
822       finest grid via the Galerkin process: A_i-1 = r_i * A_i * r_i^t
823 
824    Collective on PC
825 
826    Input Parameters:
827 .  pc - the multigrid context
828 
829    Options Database Key:
830 $  -pc_mg_galerkin
831 
832    Level: intermediate
833 
834 .keywords: MG, set, Galerkin
835 
836 .seealso: PCMGGetGalerkin()
837 
838 @*/
839 PetscErrorCode PETSCKSP_DLLEXPORT PCMGSetGalerkin(PC pc)
840 {
841   PC_MG        *mg = (PC_MG*)pc->data;
842 
843   PetscFunctionBegin;
844   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
845   mg->galerkin = PETSC_TRUE;
846   PetscFunctionReturn(0);
847 }
848 
849 #undef __FUNCT__
850 #define __FUNCT__ "PCMGGetGalerkin"
851 /*@
852    PCMGGetGalerkin - Checks if Galerkin multigrid is being used, i.e.
853       A_i-1 = r_i * A_i * r_i^t
854 
855    Not Collective
856 
857    Input Parameter:
858 .  pc - the multigrid context
859 
860    Output Parameter:
861 .  gelerkin - PETSC_TRUE or PETSC_FALSE
862 
863    Options Database Key:
864 $  -pc_mg_galerkin
865 
866    Level: intermediate
867 
868 .keywords: MG, set, Galerkin
869 
870 .seealso: PCMGSetGalerkin()
871 
872 @*/
873 PetscErrorCode PETSCKSP_DLLEXPORT PCMGGetGalerkin(PC pc,PetscTruth *galerkin)
874 {
875   PC_MG        *mg = (PC_MG*)pc->data;
876 
877   PetscFunctionBegin;
878   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
879   *galerkin = mg->galerkin;
880   PetscFunctionReturn(0);
881 }
882 
883 #undef __FUNCT__
884 #define __FUNCT__ "PCMGSetNumberSmoothDown"
885 /*@
886    PCMGSetNumberSmoothDown - Sets the number of pre-smoothing steps to
887    use on all levels. Use PCMGGetSmootherDown() to set different
888    pre-smoothing steps on different levels.
889 
890    Collective on PC
891 
892    Input Parameters:
893 +  mg - the multigrid context
894 -  n - the number of smoothing steps
895 
896    Options Database Key:
897 .  -pc_mg_smoothdown <n> - Sets number of pre-smoothing steps
898 
899    Level: advanced
900 
901 .keywords: MG, smooth, down, pre-smoothing, steps, multigrid
902 
903 .seealso: PCMGSetNumberSmoothUp()
904 @*/
905 PetscErrorCode PETSCKSP_DLLEXPORT PCMGSetNumberSmoothDown(PC pc,PetscInt n)
906 {
907   PC_MG          *mg = (PC_MG*)pc->data;
908   PC_MG_Levels   **mglevels = mg->levels;
909   PetscErrorCode ierr;
910   PetscInt       i,levels;
911 
912   PetscFunctionBegin;
913   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
914   if (!mglevels) SETERRQ(((PetscObject)pc)->comm,PETSC_ERR_ARG_WRONGSTATE,"Must set MG levels before calling");
915   levels = mglevels[0]->levels;
916 
917   for (i=1; i<levels; i++) {
918     /* make sure smoother up and down are different */
919     ierr = PCMGGetSmootherUp(pc,i,PETSC_NULL);CHKERRQ(ierr);
920     ierr = KSPSetTolerances(mglevels[i]->smoothd,PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT,n);CHKERRQ(ierr);
921     mg->default_smoothd = n;
922   }
923   PetscFunctionReturn(0);
924 }
925 
926 #undef __FUNCT__
927 #define __FUNCT__ "PCMGSetNumberSmoothUp"
928 /*@
929    PCMGSetNumberSmoothUp - Sets the number of post-smoothing steps to use
930    on all levels. Use PCMGGetSmootherUp() to set different numbers of
931    post-smoothing steps on different levels.
932 
933    Collective on PC
934 
935    Input Parameters:
936 +  mg - the multigrid context
937 -  n - the number of smoothing steps
938 
939    Options Database Key:
940 .  -pc_mg_smoothup <n> - Sets number of post-smoothing steps
941 
942    Level: advanced
943 
944    Note: this does not set a value on the coarsest grid, since we assume that
945     there is no separate smooth up on the coarsest grid.
946 
947 .keywords: MG, smooth, up, post-smoothing, steps, multigrid
948 
949 .seealso: PCMGSetNumberSmoothDown()
950 @*/
951 PetscErrorCode PETSCKSP_DLLEXPORT PCMGSetNumberSmoothUp(PC pc,PetscInt n)
952 {
953   PC_MG          *mg = (PC_MG*)pc->data;
954   PC_MG_Levels   **mglevels = mg->levels;
955   PetscErrorCode ierr;
956   PetscInt       i,levels;
957 
958   PetscFunctionBegin;
959   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
960   if (!mglevels) SETERRQ(((PetscObject)pc)->comm,PETSC_ERR_ARG_WRONGSTATE,"Must set MG levels before calling");
961   levels = mglevels[0]->levels;
962 
963   for (i=1; i<levels; i++) {
964     /* make sure smoother up and down are different */
965     ierr = PCMGGetSmootherUp(pc,i,PETSC_NULL);CHKERRQ(ierr);
966     ierr = KSPSetTolerances(mglevels[i]->smoothu,PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT,n);CHKERRQ(ierr);
967     mg->default_smoothu = n;
968   }
969   PetscFunctionReturn(0);
970 }
971 
972 /* ----------------------------------------------------------------------------------------*/
973 
974 /*MC
975    PCMG - Use multigrid preconditioning. This preconditioner requires you provide additional
976     information about the coarser grid matrices and restriction/interpolation operators.
977 
978    Options Database Keys:
979 +  -pc_mg_levels <nlevels> - number of levels including finest
980 .  -pc_mg_cycles v or w
981 .  -pc_mg_smoothup <n> - number of smoothing steps after interpolation
982 .  -pc_mg_smoothdown <n> - number of smoothing steps before applying restriction operator
983 .  -pc_mg_type <additive,multiplicative,full,cascade> - multiplicative is the default
984 .  -pc_mg_log - log information about time spent on each level of the solver
985 .  -pc_mg_monitor - print information on the multigrid convergence
986 .  -pc_mg_galerkin - use Galerkin process to compute coarser operators
987 -  -pc_mg_dump_matlab - dumps the matrices for each level and the restriction/interpolation matrices
988                         to the Socket viewer for reading from Matlab.
989 
990    Notes: By default this uses GMRES on the fine grid smoother so this should be used with KSPFGMRES or the smoother changed to not use GMRES
991 
992    Level: intermediate
993 
994    Concepts: multigrid/multilevel
995 
996 .seealso:  PCCreate(), PCSetType(), PCType (for list of available types), PC, PCMGType, PCEXOTIC
997            PCMGSetLevels(), PCMGGetLevels(), PCMGSetType(), PCMGSetCycleType(), PCMGSetNumberSmoothDown(),
998            PCMGSetNumberSmoothUp(), PCMGGetCoarseSolve(), PCMGSetResidual(), PCMGSetInterpolation(),
999            PCMGSetRestriction(), PCMGGetSmoother(), PCMGGetSmootherUp(), PCMGGetSmootherDown(),
1000            PCMGSetCycleTypeOnLevel(), PCMGSetRhs(), PCMGSetX(), PCMGSetR()
1001 M*/
1002 
1003 EXTERN_C_BEGIN
1004 #undef __FUNCT__
1005 #define __FUNCT__ "PCCreate_MG"
1006 PetscErrorCode PETSCKSP_DLLEXPORT PCCreate_MG(PC pc)
1007 {
1008   PC_MG          *mg;
1009   PetscErrorCode ierr;
1010 
1011   PetscFunctionBegin;
1012   ierr        = PetscNewLog(pc,PC_MG,&mg);CHKERRQ(ierr);
1013   pc->data    = (void*)mg;
1014   mg->nlevels = -1;
1015 
1016   pc->ops->apply          = PCApply_MG;
1017   pc->ops->setup          = PCSetUp_MG;
1018   pc->ops->destroy        = PCDestroy_MG;
1019   pc->ops->setfromoptions = PCSetFromOptions_MG;
1020   pc->ops->view           = PCView_MG;
1021   PetscFunctionReturn(0);
1022 }
1023 EXTERN_C_END
1024