xref: /petsc/src/ksp/pc/impls/mg/mg.c (revision fc8a9adeb7fcdc98711d755fa2dc544ddccf0f3e)
1 
2 /*
3     Defines the multigrid preconditioner interface.
4 */
5 #include <petsc/private/pcmgimpl.h>                    /*I "petscksp.h" I*/
6 #include <petscdm.h>
7 PETSC_INTERN PetscErrorCode PCPreSolveChangeRHS(PC,PetscBool*);
8 
9 PetscErrorCode PCMGMCycle_Private(PC pc,PC_MG_Levels **mglevelsin,PCRichardsonConvergedReason *reason)
10 {
11   PC_MG          *mg = (PC_MG*)pc->data;
12   PC_MG_Levels   *mgc,*mglevels = *mglevelsin;
13   PetscErrorCode ierr;
14   PetscInt       cycles = (mglevels->level == 1) ? 1 : (PetscInt) mglevels->cycles;
15 
16   PetscFunctionBegin;
17   if (mglevels->eventsmoothsolve) {ierr = PetscLogEventBegin(mglevels->eventsmoothsolve,0,0,0,0);CHKERRQ(ierr);}
18   ierr = KSPSolve(mglevels->smoothd,mglevels->b,mglevels->x);CHKERRQ(ierr);  /* pre-smooth */
19   ierr = KSPCheckSolve(mglevels->smoothd,pc,mglevels->x);CHKERRQ(ierr);
20   if (mglevels->eventsmoothsolve) {ierr = PetscLogEventEnd(mglevels->eventsmoothsolve,0,0,0,0);CHKERRQ(ierr);}
21   if (mglevels->level) {  /* not the coarsest grid */
22     if (mglevels->eventresidual) {ierr = PetscLogEventBegin(mglevels->eventresidual,0,0,0,0);CHKERRQ(ierr);}
23     ierr = (*mglevels->residual)(mglevels->A,mglevels->b,mglevels->x,mglevels->r);CHKERRQ(ierr);
24     if (mglevels->eventresidual) {ierr = PetscLogEventEnd(mglevels->eventresidual,0,0,0,0);CHKERRQ(ierr);}
25 
26     /* if on finest level and have convergence criteria set */
27     if (mglevels->level == mglevels->levels-1 && mg->ttol && reason) {
28       PetscReal rnorm;
29       ierr = VecNorm(mglevels->r,NORM_2,&rnorm);CHKERRQ(ierr);
30       if (rnorm <= mg->ttol) {
31         if (rnorm < mg->abstol) {
32           *reason = PCRICHARDSON_CONVERGED_ATOL;
33           ierr    = PetscInfo2(pc,"Linear solver has converged. Residual norm %g is less than absolute tolerance %g\n",(double)rnorm,(double)mg->abstol);CHKERRQ(ierr);
34         } else {
35           *reason = PCRICHARDSON_CONVERGED_RTOL;
36           ierr    = PetscInfo2(pc,"Linear solver has converged. Residual norm %g is less than relative tolerance times initial residual norm %g\n",(double)rnorm,(double)mg->ttol);CHKERRQ(ierr);
37         }
38         PetscFunctionReturn(0);
39       }
40     }
41 
42     mgc = *(mglevelsin - 1);
43     if (mglevels->eventinterprestrict) {ierr = PetscLogEventBegin(mglevels->eventinterprestrict,0,0,0,0);CHKERRQ(ierr);}
44     ierr = MatRestrict(mglevels->restrct,mglevels->r,mgc->b);CHKERRQ(ierr);
45     if (mglevels->eventinterprestrict) {ierr = PetscLogEventEnd(mglevels->eventinterprestrict,0,0,0,0);CHKERRQ(ierr);}
46     ierr = VecSet(mgc->x,0.0);CHKERRQ(ierr);
47     while (cycles--) {
48       ierr = PCMGMCycle_Private(pc,mglevelsin-1,reason);CHKERRQ(ierr);
49     }
50     if (mglevels->eventinterprestrict) {ierr = PetscLogEventBegin(mglevels->eventinterprestrict,0,0,0,0);CHKERRQ(ierr);}
51     ierr = MatInterpolateAdd(mglevels->interpolate,mgc->x,mglevels->x,mglevels->x);CHKERRQ(ierr);
52     if (mglevels->eventinterprestrict) {ierr = PetscLogEventEnd(mglevels->eventinterprestrict,0,0,0,0);CHKERRQ(ierr);}
53     if (mglevels->eventsmoothsolve) {ierr = PetscLogEventBegin(mglevels->eventsmoothsolve,0,0,0,0);CHKERRQ(ierr);}
54     ierr = KSPSolve(mglevels->smoothu,mglevels->b,mglevels->x);CHKERRQ(ierr);    /* post smooth */
55     ierr = KSPCheckSolve(mglevels->smoothu,pc,mglevels->x);CHKERRQ(ierr);
56     if (mglevels->eventsmoothsolve) {ierr = PetscLogEventEnd(mglevels->eventsmoothsolve,0,0,0,0);CHKERRQ(ierr);}
57   }
58   PetscFunctionReturn(0);
59 }
60 
61 static PetscErrorCode PCApplyRichardson_MG(PC pc,Vec b,Vec x,Vec w,PetscReal rtol,PetscReal abstol, PetscReal dtol,PetscInt its,PetscBool zeroguess,PetscInt *outits,PCRichardsonConvergedReason *reason)
62 {
63   PC_MG          *mg        = (PC_MG*)pc->data;
64   PC_MG_Levels   **mglevels = mg->levels;
65   PetscErrorCode ierr;
66   PC             tpc;
67   PetscBool      changeu,changed;
68   PetscInt       levels = mglevels[0]->levels,i;
69 
70   PetscFunctionBegin;
71   /* When the DM is supplying the matrix then it will not exist until here */
72   for (i=0; i<levels; i++) {
73     if (!mglevels[i]->A) {
74       ierr = KSPGetOperators(mglevels[i]->smoothu,&mglevels[i]->A,NULL);CHKERRQ(ierr);
75       ierr = PetscObjectReference((PetscObject)mglevels[i]->A);CHKERRQ(ierr);
76     }
77   }
78 
79   ierr = KSPGetPC(mglevels[levels-1]->smoothd,&tpc);CHKERRQ(ierr);
80   ierr = PCPreSolveChangeRHS(tpc,&changed);CHKERRQ(ierr);
81   ierr = KSPGetPC(mglevels[levels-1]->smoothu,&tpc);CHKERRQ(ierr);
82   ierr = PCPreSolveChangeRHS(tpc,&changeu);CHKERRQ(ierr);
83   if (!changed && !changeu) {
84     ierr = VecDestroy(&mglevels[levels-1]->b);CHKERRQ(ierr);
85     mglevels[levels-1]->b = b;
86   } else { /* if the smoother changes the rhs during PreSolve, we cannot use the input vector */
87     if (!mglevels[levels-1]->b) {
88       Vec *vec;
89 
90       ierr = KSPCreateVecs(mglevels[levels-1]->smoothd,1,&vec,0,NULL);CHKERRQ(ierr);
91       mglevels[levels-1]->b = *vec;
92       ierr = PetscFree(vec);CHKERRQ(ierr);
93     }
94     ierr = VecCopy(b,mglevels[levels-1]->b);CHKERRQ(ierr);
95   }
96   mglevels[levels-1]->x = x;
97 
98   mg->rtol   = rtol;
99   mg->abstol = abstol;
100   mg->dtol   = dtol;
101   if (rtol) {
102     /* compute initial residual norm for relative convergence test */
103     PetscReal rnorm;
104     if (zeroguess) {
105       ierr = VecNorm(b,NORM_2,&rnorm);CHKERRQ(ierr);
106     } else {
107       ierr = (*mglevels[levels-1]->residual)(mglevels[levels-1]->A,b,x,w);CHKERRQ(ierr);
108       ierr = VecNorm(w,NORM_2,&rnorm);CHKERRQ(ierr);
109     }
110     mg->ttol = PetscMax(rtol*rnorm,abstol);
111   } else if (abstol) mg->ttol = abstol;
112   else mg->ttol = 0.0;
113 
114   /* since smoother is applied to full system, not just residual we need to make sure that smoothers don't
115      stop prematurely due to small residual */
116   for (i=1; i<levels; i++) {
117     ierr = KSPSetTolerances(mglevels[i]->smoothu,0,PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT);CHKERRQ(ierr);
118     if (mglevels[i]->smoothu != mglevels[i]->smoothd) {
119       /* For Richardson the initial guess is nonzero since it is solving in each cycle the original system not just applying as a preconditioner */
120       ierr = KSPSetInitialGuessNonzero(mglevels[i]->smoothd,PETSC_TRUE);CHKERRQ(ierr);
121       ierr = KSPSetTolerances(mglevels[i]->smoothd,0,PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT);CHKERRQ(ierr);
122     }
123   }
124 
125   *reason = (PCRichardsonConvergedReason)0;
126   for (i=0; i<its; i++) {
127     ierr = PCMGMCycle_Private(pc,mglevels+levels-1,reason);CHKERRQ(ierr);
128     if (*reason) break;
129   }
130   if (!*reason) *reason = PCRICHARDSON_CONVERGED_ITS;
131   *outits = i;
132   if (!changed && !changeu) mglevels[levels-1]->b = NULL;
133   PetscFunctionReturn(0);
134 }
135 
136 PetscErrorCode PCReset_MG(PC pc)
137 {
138   PC_MG          *mg        = (PC_MG*)pc->data;
139   PC_MG_Levels   **mglevels = mg->levels;
140   PetscErrorCode ierr;
141   PetscInt       i,n;
142 
143   PetscFunctionBegin;
144   if (mglevels) {
145     n = mglevels[0]->levels;
146     for (i=0; i<n-1; i++) {
147       ierr = VecDestroy(&mglevels[i+1]->r);CHKERRQ(ierr);
148       ierr = VecDestroy(&mglevels[i]->b);CHKERRQ(ierr);
149       ierr = VecDestroy(&mglevels[i]->x);CHKERRQ(ierr);
150       ierr = MatDestroy(&mglevels[i+1]->restrct);CHKERRQ(ierr);
151       ierr = MatDestroy(&mglevels[i+1]->interpolate);CHKERRQ(ierr);
152       ierr = MatDestroy(&mglevels[i+1]->inject);CHKERRQ(ierr);
153       ierr = VecDestroy(&mglevels[i+1]->rscale);CHKERRQ(ierr);
154     }
155     /* this is not null only if the smoother on the finest level
156        changes the rhs during PreSolve */
157     ierr = VecDestroy(&mglevels[n-1]->b);CHKERRQ(ierr);
158 
159     for (i=0; i<n; i++) {
160       ierr = MatDestroy(&mglevels[i]->A);CHKERRQ(ierr);
161       if (mglevels[i]->smoothd != mglevels[i]->smoothu) {
162         ierr = KSPReset(mglevels[i]->smoothd);CHKERRQ(ierr);
163       }
164       ierr = KSPReset(mglevels[i]->smoothu);CHKERRQ(ierr);
165     }
166   }
167   PetscFunctionReturn(0);
168 }
169 
170 PetscErrorCode PCMGSetLevels_MG(PC pc,PetscInt levels,MPI_Comm *comms)
171 {
172   PetscErrorCode ierr;
173   PC_MG          *mg        = (PC_MG*)pc->data;
174   MPI_Comm       comm;
175   PC_MG_Levels   **mglevels = mg->levels;
176   PCMGType       mgtype     = mg->am;
177   PetscInt       mgctype    = (PetscInt) PC_MG_CYCLE_V;
178   PetscInt       i;
179   PetscMPIInt    size;
180   const char     *prefix;
181   PC             ipc;
182   PetscInt       n;
183 
184   PetscFunctionBegin;
185   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
186   PetscValidLogicalCollectiveInt(pc,levels,2);
187   if (mg->nlevels == levels) PetscFunctionReturn(0);
188   ierr = PetscObjectGetComm((PetscObject)pc,&comm);CHKERRQ(ierr);
189   if (mglevels) {
190     mgctype = mglevels[0]->cycles;
191     /* changing the number of levels so free up the previous stuff */
192     ierr = PCReset_MG(pc);CHKERRQ(ierr);
193     n    = mglevels[0]->levels;
194     for (i=0; i<n; i++) {
195       if (mglevels[i]->smoothd != mglevels[i]->smoothu) {
196         ierr = KSPDestroy(&mglevels[i]->smoothd);CHKERRQ(ierr);
197       }
198       ierr = KSPDestroy(&mglevels[i]->smoothu);CHKERRQ(ierr);
199       ierr = PetscFree(mglevels[i]);CHKERRQ(ierr);
200     }
201     ierr = PetscFree(mg->levels);CHKERRQ(ierr);
202   }
203 
204   mg->nlevels = levels;
205 
206   ierr = PetscMalloc1(levels,&mglevels);CHKERRQ(ierr);
207   ierr = PetscLogObjectMemory((PetscObject)pc,levels*(sizeof(PC_MG*)));CHKERRQ(ierr);
208 
209   ierr = PCGetOptionsPrefix(pc,&prefix);CHKERRQ(ierr);
210 
211   mg->stageApply = 0;
212   for (i=0; i<levels; i++) {
213     ierr = PetscNewLog(pc,&mglevels[i]);CHKERRQ(ierr);
214 
215     mglevels[i]->level               = i;
216     mglevels[i]->levels              = levels;
217     mglevels[i]->cycles              = mgctype;
218     mg->default_smoothu              = 2;
219     mg->default_smoothd              = 2;
220     mglevels[i]->eventsmoothsetup    = 0;
221     mglevels[i]->eventsmoothsolve    = 0;
222     mglevels[i]->eventresidual       = 0;
223     mglevels[i]->eventinterprestrict = 0;
224 
225     if (comms) comm = comms[i];
226     ierr = KSPCreate(comm,&mglevels[i]->smoothd);CHKERRQ(ierr);
227     ierr = KSPSetErrorIfNotConverged(mglevels[i]->smoothd,pc->erroriffailure);CHKERRQ(ierr);
228     ierr = PetscObjectIncrementTabLevel((PetscObject)mglevels[i]->smoothd,(PetscObject)pc,levels-i);CHKERRQ(ierr);
229     ierr = KSPSetOptionsPrefix(mglevels[i]->smoothd,prefix);CHKERRQ(ierr);
230     ierr = PetscObjectComposedDataSetInt((PetscObject) mglevels[i]->smoothd, PetscMGLevelId, mglevels[i]->level);CHKERRQ(ierr);
231     if (i || levels == 1) {
232       char tprefix[128];
233 
234       ierr = KSPSetType(mglevels[i]->smoothd,KSPCHEBYSHEV);CHKERRQ(ierr);
235       ierr = KSPSetConvergenceTest(mglevels[i]->smoothd,KSPConvergedSkip,NULL,NULL);CHKERRQ(ierr);
236       ierr = KSPSetNormType(mglevels[i]->smoothd,KSP_NORM_NONE);CHKERRQ(ierr);
237       ierr = KSPGetPC(mglevels[i]->smoothd,&ipc);CHKERRQ(ierr);
238       ierr = PCSetType(ipc,PCSOR);CHKERRQ(ierr);
239       ierr = KSPSetTolerances(mglevels[i]->smoothd,PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT, mg->default_smoothd);CHKERRQ(ierr);
240 
241       sprintf(tprefix,"mg_levels_%d_",(int)i);
242       ierr = KSPAppendOptionsPrefix(mglevels[i]->smoothd,tprefix);CHKERRQ(ierr);
243     } else {
244       ierr = KSPAppendOptionsPrefix(mglevels[0]->smoothd,"mg_coarse_");CHKERRQ(ierr);
245 
246       /* coarse solve is (redundant) LU by default; set shifttype NONZERO to avoid annoying zero-pivot in LU preconditioner */
247       ierr = KSPSetType(mglevels[0]->smoothd,KSPPREONLY);CHKERRQ(ierr);
248       ierr = KSPGetPC(mglevels[0]->smoothd,&ipc);CHKERRQ(ierr);
249       ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
250       if (size > 1) {
251         ierr = PCSetType(ipc,PCREDUNDANT);CHKERRQ(ierr);
252       } else {
253         ierr = PCSetType(ipc,PCLU);CHKERRQ(ierr);
254       }
255       ierr = PCFactorSetShiftType(ipc,MAT_SHIFT_INBLOCKS);CHKERRQ(ierr);
256     }
257     ierr = PetscLogObjectParent((PetscObject)pc,(PetscObject)mglevels[i]->smoothd);CHKERRQ(ierr);
258 
259     mglevels[i]->smoothu = mglevels[i]->smoothd;
260     mg->rtol             = 0.0;
261     mg->abstol           = 0.0;
262     mg->dtol             = 0.0;
263     mg->ttol             = 0.0;
264     mg->cyclesperpcapply = 1;
265   }
266   mg->levels = mglevels;
267   ierr = PCMGSetType(pc,mgtype);CHKERRQ(ierr);
268   PetscFunctionReturn(0);
269 }
270 
271 /*@C
272    PCMGSetLevels - Sets the number of levels to use with MG.
273    Must be called before any other MG routine.
274 
275    Logically Collective on PC
276 
277    Input Parameters:
278 +  pc - the preconditioner context
279 .  levels - the number of levels
280 -  comms - optional communicators for each level; this is to allow solving the coarser problems
281            on smaller sets of processors.
282 
283    Level: intermediate
284 
285    Notes:
286      If the number of levels is one then the multigrid uses the -mg_levels prefix
287   for setting the level options rather than the -mg_coarse prefix.
288 
289 .keywords: MG, set, levels, multigrid
290 
291 .seealso: PCMGSetType(), PCMGGetLevels()
292 @*/
293 PetscErrorCode PCMGSetLevels(PC pc,PetscInt levels,MPI_Comm *comms)
294 {
295   PetscErrorCode ierr;
296 
297   PetscFunctionBegin;
298   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
299   if (comms) PetscValidPointer(comms,3);
300   ierr = PetscTryMethod(pc,"PCMGSetLevels_C",(PC,PetscInt,MPI_Comm*),(pc,levels,comms));CHKERRQ(ierr);
301   PetscFunctionReturn(0);
302 }
303 
304 
305 PetscErrorCode PCDestroy_MG(PC pc)
306 {
307   PetscErrorCode ierr;
308   PC_MG          *mg        = (PC_MG*)pc->data;
309   PC_MG_Levels   **mglevels = mg->levels;
310   PetscInt       i,n;
311 
312   PetscFunctionBegin;
313   ierr = PCReset_MG(pc);CHKERRQ(ierr);
314   if (mglevels) {
315     n = mglevels[0]->levels;
316     for (i=0; i<n; i++) {
317       if (mglevels[i]->smoothd != mglevels[i]->smoothu) {
318         ierr = KSPDestroy(&mglevels[i]->smoothd);CHKERRQ(ierr);
319       }
320       ierr = KSPDestroy(&mglevels[i]->smoothu);CHKERRQ(ierr);
321       ierr = PetscFree(mglevels[i]);CHKERRQ(ierr);
322     }
323     ierr = PetscFree(mg->levels);CHKERRQ(ierr);
324   }
325   ierr = PetscFree(pc->data);CHKERRQ(ierr);
326   PetscFunctionReturn(0);
327 }
328 
329 
330 
331 extern PetscErrorCode PCMGACycle_Private(PC,PC_MG_Levels**);
332 extern PetscErrorCode PCMGFCycle_Private(PC,PC_MG_Levels**);
333 extern PetscErrorCode PCMGKCycle_Private(PC,PC_MG_Levels**);
334 
335 /*
336    PCApply_MG - Runs either an additive, multiplicative, Kaskadic
337              or full cycle of multigrid.
338 
339   Note:
340   A simple wrapper which calls PCMGMCycle(),PCMGACycle(), or PCMGFCycle().
341 */
342 static PetscErrorCode PCApply_MG(PC pc,Vec b,Vec x)
343 {
344   PC_MG          *mg        = (PC_MG*)pc->data;
345   PC_MG_Levels   **mglevels = mg->levels;
346   PetscErrorCode ierr;
347   PC             tpc;
348   PetscInt       levels = mglevels[0]->levels,i;
349   PetscBool      changeu,changed;
350 
351   PetscFunctionBegin;
352   if (mg->stageApply) {ierr = PetscLogStagePush(mg->stageApply);CHKERRQ(ierr);}
353   /* When the DM is supplying the matrix then it will not exist until here */
354   for (i=0; i<levels; i++) {
355     if (!mglevels[i]->A) {
356       ierr = KSPGetOperators(mglevels[i]->smoothu,&mglevels[i]->A,NULL);CHKERRQ(ierr);
357       ierr = PetscObjectReference((PetscObject)mglevels[i]->A);CHKERRQ(ierr);
358     }
359   }
360 
361   ierr = KSPGetPC(mglevels[levels-1]->smoothd,&tpc);CHKERRQ(ierr);
362   ierr = PCPreSolveChangeRHS(tpc,&changed);CHKERRQ(ierr);
363   ierr = KSPGetPC(mglevels[levels-1]->smoothu,&tpc);CHKERRQ(ierr);
364   ierr = PCPreSolveChangeRHS(tpc,&changeu);CHKERRQ(ierr);
365   if (!changeu && !changed) {
366     ierr = VecDestroy(&mglevels[levels-1]->b);CHKERRQ(ierr);
367     mglevels[levels-1]->b = b;
368   } else { /* if the smoother changes the rhs during PreSolve, we cannot use the input vector */
369     if (!mglevels[levels-1]->b) {
370       Vec *vec;
371 
372       ierr = KSPCreateVecs(mglevels[levels-1]->smoothd,1,&vec,0,NULL);CHKERRQ(ierr);
373       mglevels[levels-1]->b = *vec;
374       ierr = PetscFree(vec);CHKERRQ(ierr);
375     }
376     ierr = VecCopy(b,mglevels[levels-1]->b);CHKERRQ(ierr);
377   }
378   mglevels[levels-1]->x = x;
379 
380   if (mg->am == PC_MG_MULTIPLICATIVE) {
381     ierr = VecSet(x,0.0);CHKERRQ(ierr);
382     for (i=0; i<mg->cyclesperpcapply; i++) {
383       ierr = PCMGMCycle_Private(pc,mglevels+levels-1,NULL);CHKERRQ(ierr);
384     }
385   } else if (mg->am == PC_MG_ADDITIVE) {
386     ierr = PCMGACycle_Private(pc,mglevels);CHKERRQ(ierr);
387   } else if (mg->am == PC_MG_KASKADE) {
388     ierr = PCMGKCycle_Private(pc,mglevels);CHKERRQ(ierr);
389   } else {
390     ierr = PCMGFCycle_Private(pc,mglevels);CHKERRQ(ierr);
391   }
392   if (mg->stageApply) {ierr = PetscLogStagePop();CHKERRQ(ierr);}
393   if (!changeu && !changed) mglevels[levels-1]->b = NULL;
394   PetscFunctionReturn(0);
395 }
396 
397 
398 PetscErrorCode PCSetFromOptions_MG(PetscOptionItems *PetscOptionsObject,PC pc)
399 {
400   PetscErrorCode   ierr;
401   PetscInt         levels,cycles;
402   PetscBool        flg;
403   PC_MG            *mg = (PC_MG*)pc->data;
404   PC_MG_Levels     **mglevels;
405   PCMGType         mgtype;
406   PCMGCycleType    mgctype;
407   PCMGGalerkinType gtype;
408 
409   PetscFunctionBegin;
410   levels = PetscMax(mg->nlevels,1);
411   ierr = PetscOptionsHead(PetscOptionsObject,"Multigrid options");CHKERRQ(ierr);
412   ierr = PetscOptionsInt("-pc_mg_levels","Number of Levels","PCMGSetLevels",levels,&levels,&flg);CHKERRQ(ierr);
413   if (!flg && !mg->levels && pc->dm) {
414     ierr = DMGetRefineLevel(pc->dm,&levels);CHKERRQ(ierr);
415     levels++;
416     mg->usedmfornumberoflevels = PETSC_TRUE;
417   }
418   ierr = PCMGSetLevels(pc,levels,NULL);CHKERRQ(ierr);
419   mglevels = mg->levels;
420 
421   mgctype = (PCMGCycleType) mglevels[0]->cycles;
422   ierr    = PetscOptionsEnum("-pc_mg_cycle_type","V cycle or for W-cycle","PCMGSetCycleType",PCMGCycleTypes,(PetscEnum)mgctype,(PetscEnum*)&mgctype,&flg);CHKERRQ(ierr);
423   if (flg) {
424     ierr = PCMGSetCycleType(pc,mgctype);CHKERRQ(ierr);
425   }
426   gtype = mg->galerkin;
427   ierr = PetscOptionsEnum("-pc_mg_galerkin","Use Galerkin process to compute coarser operators","PCMGSetGalerkin",PCMGGalerkinTypes,(PetscEnum)gtype,(PetscEnum*)&gtype,&flg);CHKERRQ(ierr);
428   if (flg) {
429     ierr = PCMGSetGalerkin(pc,gtype);CHKERRQ(ierr);
430   }
431   flg = PETSC_FALSE;
432   ierr = PetscOptionsBool("-pc_mg_distinct_smoothup","Create seperate smoothup KSP and append the prefix _up","PCMGSetDistinctSmoothUp",PETSC_FALSE,&flg,NULL);CHKERRQ(ierr);
433   if (flg) {
434     ierr = PCMGSetDistinctSmoothUp(pc);CHKERRQ(ierr);
435   }
436   mgtype = mg->am;
437   ierr   = PetscOptionsEnum("-pc_mg_type","Multigrid type","PCMGSetType",PCMGTypes,(PetscEnum)mgtype,(PetscEnum*)&mgtype,&flg);CHKERRQ(ierr);
438   if (flg) {
439     ierr = PCMGSetType(pc,mgtype);CHKERRQ(ierr);
440   }
441   if (mg->am == PC_MG_MULTIPLICATIVE) {
442     ierr = PetscOptionsInt("-pc_mg_multiplicative_cycles","Number of cycles for each preconditioner step","PCMGMultiplicativeSetCycles",mg->cyclesperpcapply,&cycles,&flg);CHKERRQ(ierr);
443     if (flg) {
444       ierr = PCMGMultiplicativeSetCycles(pc,cycles);CHKERRQ(ierr);
445     }
446   }
447   flg  = PETSC_FALSE;
448   ierr = PetscOptionsBool("-pc_mg_log","Log times for each multigrid level","None",flg,&flg,NULL);CHKERRQ(ierr);
449   if (flg) {
450     PetscInt i;
451     char     eventname[128];
452 
453     levels = mglevels[0]->levels;
454     for (i=0; i<levels; i++) {
455       sprintf(eventname,"MGSetup Level %d",(int)i);
456       ierr = PetscLogEventRegister(eventname,((PetscObject)pc)->classid,&mglevels[i]->eventsmoothsetup);CHKERRQ(ierr);
457       sprintf(eventname,"MGSmooth Level %d",(int)i);
458       ierr = PetscLogEventRegister(eventname,((PetscObject)pc)->classid,&mglevels[i]->eventsmoothsolve);CHKERRQ(ierr);
459       if (i) {
460         sprintf(eventname,"MGResid Level %d",(int)i);
461         ierr = PetscLogEventRegister(eventname,((PetscObject)pc)->classid,&mglevels[i]->eventresidual);CHKERRQ(ierr);
462         sprintf(eventname,"MGInterp Level %d",(int)i);
463         ierr = PetscLogEventRegister(eventname,((PetscObject)pc)->classid,&mglevels[i]->eventinterprestrict);CHKERRQ(ierr);
464       }
465     }
466 
467 #if defined(PETSC_USE_LOG)
468     {
469       const char    *sname = "MG Apply";
470       PetscStageLog stageLog;
471       PetscInt      st;
472 
473       ierr = PetscLogGetStageLog(&stageLog);CHKERRQ(ierr);
474       for (st = 0; st < stageLog->numStages; ++st) {
475         PetscBool same;
476 
477         ierr = PetscStrcmp(stageLog->stageInfo[st].name, sname, &same);CHKERRQ(ierr);
478         if (same) mg->stageApply = st;
479       }
480       if (!mg->stageApply) {
481         ierr = PetscLogStageRegister(sname, &mg->stageApply);CHKERRQ(ierr);
482       }
483     }
484 #endif
485   }
486   ierr = PetscOptionsTail();CHKERRQ(ierr);
487   PetscFunctionReturn(0);
488 }
489 
490 const char *const PCMGTypes[] = {"MULTIPLICATIVE","ADDITIVE","FULL","KASKADE","PCMGType","PC_MG",0};
491 const char *const PCMGCycleTypes[] = {"invalid","v","w","PCMGCycleType","PC_MG_CYCLE",0};
492 const char *const PCMGGalerkinTypes[] = {"both","pmat","mat","none","external","PCMGGalerkinType","PC_MG_GALERKIN",0};
493 
494 #include <petscdraw.h>
495 PetscErrorCode PCView_MG(PC pc,PetscViewer viewer)
496 {
497   PC_MG          *mg        = (PC_MG*)pc->data;
498   PC_MG_Levels   **mglevels = mg->levels;
499   PetscErrorCode ierr;
500   PetscInt       levels = mglevels ? mglevels[0]->levels : 0,i;
501   PetscBool      iascii,isbinary,isdraw;
502 
503   PetscFunctionBegin;
504   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
505   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERBINARY,&isbinary);CHKERRQ(ierr);
506   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERDRAW,&isdraw);CHKERRQ(ierr);
507   if (iascii) {
508     const char *cyclename = levels ? (mglevels[0]->cycles == PC_MG_CYCLE_V ? "v" : "w") : "unknown";
509     ierr = PetscViewerASCIIPrintf(viewer,"  type is %s, levels=%D cycles=%s\n", PCMGTypes[mg->am],levels,cyclename);CHKERRQ(ierr);
510     if (mg->am == PC_MG_MULTIPLICATIVE) {
511       ierr = PetscViewerASCIIPrintf(viewer,"    Cycles per PCApply=%d\n",mg->cyclesperpcapply);CHKERRQ(ierr);
512     }
513     if (mg->galerkin == PC_MG_GALERKIN_BOTH) {
514       ierr = PetscViewerASCIIPrintf(viewer,"    Using Galerkin computed coarse grid matrices\n");CHKERRQ(ierr);
515     } else if (mg->galerkin == PC_MG_GALERKIN_PMAT) {
516       ierr = PetscViewerASCIIPrintf(viewer,"    Using Galerkin computed coarse grid matrices for pmat\n");CHKERRQ(ierr);
517     } else if (mg->galerkin == PC_MG_GALERKIN_MAT) {
518       ierr = PetscViewerASCIIPrintf(viewer,"    Using Galerkin computed coarse grid matrices for mat\n");CHKERRQ(ierr);
519     } else if (mg->galerkin == PC_MG_GALERKIN_EXTERNAL) {
520       ierr = PetscViewerASCIIPrintf(viewer,"    Using externally compute Galerkin coarse grid matrices\n");CHKERRQ(ierr);
521     } else {
522       ierr = PetscViewerASCIIPrintf(viewer,"    Not using Galerkin computed coarse grid matrices\n");CHKERRQ(ierr);
523     }
524     if (mg->view){
525       ierr = (*mg->view)(pc,viewer);CHKERRQ(ierr);
526     }
527     for (i=0; i<levels; i++) {
528       if (!i) {
529         ierr = PetscViewerASCIIPrintf(viewer,"Coarse grid solver -- level -------------------------------\n",i);CHKERRQ(ierr);
530       } else {
531         ierr = PetscViewerASCIIPrintf(viewer,"Down solver (pre-smoother) on level %D -------------------------------\n",i);CHKERRQ(ierr);
532       }
533       ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr);
534       ierr = KSPView(mglevels[i]->smoothd,viewer);CHKERRQ(ierr);
535       ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr);
536       if (i && mglevels[i]->smoothd == mglevels[i]->smoothu) {
537         ierr = PetscViewerASCIIPrintf(viewer,"Up solver (post-smoother) same as down solver (pre-smoother)\n");CHKERRQ(ierr);
538       } else if (i) {
539         ierr = PetscViewerASCIIPrintf(viewer,"Up solver (post-smoother) on level %D -------------------------------\n",i);CHKERRQ(ierr);
540         ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr);
541         ierr = KSPView(mglevels[i]->smoothu,viewer);CHKERRQ(ierr);
542         ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr);
543       }
544     }
545   } else if (isbinary) {
546     for (i=levels-1; i>=0; i--) {
547       ierr = KSPView(mglevels[i]->smoothd,viewer);CHKERRQ(ierr);
548       if (i && mglevels[i]->smoothd != mglevels[i]->smoothu) {
549         ierr = KSPView(mglevels[i]->smoothu,viewer);CHKERRQ(ierr);
550       }
551     }
552   } else if (isdraw) {
553     PetscDraw draw;
554     PetscReal x,w,y,bottom,th;
555     ierr   = PetscViewerDrawGetDraw(viewer,0,&draw);CHKERRQ(ierr);
556     ierr   = PetscDrawGetCurrentPoint(draw,&x,&y);CHKERRQ(ierr);
557     ierr   = PetscDrawStringGetSize(draw,NULL,&th);CHKERRQ(ierr);
558     bottom = y - th;
559     for (i=levels-1; i>=0; i--) {
560       if (!mglevels[i]->smoothu || (mglevels[i]->smoothu == mglevels[i]->smoothd)) {
561         ierr = PetscDrawPushCurrentPoint(draw,x,bottom);CHKERRQ(ierr);
562         ierr = KSPView(mglevels[i]->smoothd,viewer);CHKERRQ(ierr);
563         ierr = PetscDrawPopCurrentPoint(draw);CHKERRQ(ierr);
564       } else {
565         w    = 0.5*PetscMin(1.0-x,x);
566         ierr = PetscDrawPushCurrentPoint(draw,x+w,bottom);CHKERRQ(ierr);
567         ierr = KSPView(mglevels[i]->smoothd,viewer);CHKERRQ(ierr);
568         ierr = PetscDrawPopCurrentPoint(draw);CHKERRQ(ierr);
569         ierr = PetscDrawPushCurrentPoint(draw,x-w,bottom);CHKERRQ(ierr);
570         ierr = KSPView(mglevels[i]->smoothu,viewer);CHKERRQ(ierr);
571         ierr = PetscDrawPopCurrentPoint(draw);CHKERRQ(ierr);
572       }
573       ierr    = PetscDrawGetBoundingBox(draw,NULL,&bottom,NULL,NULL);CHKERRQ(ierr);
574       bottom -= th;
575     }
576   }
577   PetscFunctionReturn(0);
578 }
579 
580 #include <petsc/private/dmimpl.h>
581 #include <petsc/private/kspimpl.h>
582 
583 /*
584     Calls setup for the KSP on each level
585 */
586 PetscErrorCode PCSetUp_MG(PC pc)
587 {
588   PC_MG          *mg        = (PC_MG*)pc->data;
589   PC_MG_Levels   **mglevels = mg->levels;
590   PetscErrorCode ierr;
591   PetscInt       i,n;
592   PC             cpc;
593   PetscBool      dump = PETSC_FALSE,opsset,use_amat,missinginterpolate = PETSC_FALSE;
594   Mat            dA,dB;
595   Vec            tvec;
596   DM             *dms;
597   PetscViewer    viewer = 0;
598   PetscBool      dAeqdB = PETSC_FALSE, needRestricts = PETSC_FALSE;
599 
600   PetscFunctionBegin;
601   if (!mglevels) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONGSTATE,"Must set MG levels with PCMGSetLevels() before setting up");
602   n = mglevels[0]->levels;
603   /* FIX: Move this to PCSetFromOptions_MG? */
604   if (mg->usedmfornumberoflevels) {
605     PetscInt levels;
606     ierr = DMGetRefineLevel(pc->dm,&levels);CHKERRQ(ierr);
607     levels++;
608     if (levels > n) { /* the problem is now being solved on a finer grid */
609       ierr     = PCMGSetLevels(pc,levels,NULL);CHKERRQ(ierr);
610       n        = levels;
611       ierr     = PCSetFromOptions(pc);CHKERRQ(ierr); /* it is bad to call this here, but otherwise will never be called for the new hierarchy */
612       mglevels = mg->levels;
613     }
614   }
615   ierr = KSPGetPC(mglevels[0]->smoothd,&cpc);CHKERRQ(ierr);
616 
617 
618   /* If user did not provide fine grid operators OR operator was not updated since last global KSPSetOperators() */
619   /* so use those from global PC */
620   /* Is this what we always want? What if user wants to keep old one? */
621   ierr = KSPGetOperatorsSet(mglevels[n-1]->smoothd,NULL,&opsset);CHKERRQ(ierr);
622   if (opsset) {
623     Mat mmat;
624     ierr = KSPGetOperators(mglevels[n-1]->smoothd,NULL,&mmat);CHKERRQ(ierr);
625     if (mmat == pc->pmat) opsset = PETSC_FALSE;
626   }
627 
628   if (!opsset) {
629     ierr = PCGetUseAmat(pc,&use_amat);CHKERRQ(ierr);
630     if (use_amat) {
631       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);
632       ierr = KSPSetOperators(mglevels[n-1]->smoothd,pc->mat,pc->pmat);CHKERRQ(ierr);
633     } else {
634       ierr = PetscInfo(pc,"Using matrix (pmat) operators to define finest grid operator \n  because PCMGGetSmoother(pc,nlevels-1,&ksp);KSPSetOperators(ksp,...); was not called.\n");CHKERRQ(ierr);
635       ierr = KSPSetOperators(mglevels[n-1]->smoothd,pc->pmat,pc->pmat);CHKERRQ(ierr);
636     }
637   }
638 
639   for (i=n-1; i>0; i--) {
640     if (!(mglevels[i]->interpolate || mglevels[i]->restrct)) {
641       missinginterpolate = PETSC_TRUE;
642       continue;
643     }
644   }
645 
646   ierr = KSPGetOperators(mglevels[n-1]->smoothd,&dA,&dB);CHKERRQ(ierr);
647   if (dA == dB) dAeqdB = PETSC_TRUE;
648   if ((mg->galerkin == PC_MG_GALERKIN_NONE) || (((mg->galerkin == PC_MG_GALERKIN_PMAT) || (mg->galerkin == PC_MG_GALERKIN_MAT)) && !dAeqdB)) {
649     needRestricts = PETSC_TRUE;  /* user must compute either mat, pmat, or both so must restrict x to coarser levels */
650   }
651 
652 
653   /*
654    Skipping if user has provided all interpolation/restriction needed (since DM might not be able to produce them (when coming from SNES/TS)
655    Skipping for galerkin==2 (externally managed hierarchy such as ML and GAMG). Cleaner logic here would be great. Wrap ML/GAMG as DMs?
656   */
657   if (missinginterpolate && pc->dm && mg->galerkin != PC_MG_GALERKIN_EXTERNAL && !pc->setupcalled) {
658 	/* construct the interpolation from the DMs */
659     Mat p;
660     Vec rscale;
661     ierr     = PetscMalloc1(n,&dms);CHKERRQ(ierr);
662     dms[n-1] = pc->dm;
663     /* Separately create them so we do not get DMKSP interference between levels */
664     for (i=n-2; i>-1; i--) {ierr = DMCoarsen(dms[i+1],MPI_COMM_NULL,&dms[i]);CHKERRQ(ierr);}
665 	/*
666 	   Force the mat type of coarse level operator to be AIJ because usually we want to use LU for coarse level.
667 	   Notice that it can be overwritten by -mat_type because KSPSetUp() reads command line options.
668 	   But it is safe to use -dm_mat_type.
669 
670 	   The mat type should not be hardcoded like this, we need to find a better way.
671     ierr = DMSetMatType(dms[0],MATAIJ);CHKERRQ(ierr);
672     */
673     for (i=n-2; i>-1; i--) {
674       DMKSP     kdm;
675       PetscBool dmhasrestrict, dmhasinject;
676       ierr = KSPSetDM(mglevels[i]->smoothd,dms[i]);CHKERRQ(ierr);
677       if (!needRestricts) {ierr = KSPSetDMActive(mglevels[i]->smoothd,PETSC_FALSE);CHKERRQ(ierr);}
678       if (mglevels[i]->smoothd != mglevels[i]->smoothu) {
679         ierr = KSPSetDM(mglevels[i]->smoothu,dms[i]);CHKERRQ(ierr);
680         if (!needRestricts) {ierr = KSPSetDMActive(mglevels[i]->smoothu,PETSC_FALSE);CHKERRQ(ierr);}
681       }
682       ierr = DMGetDMKSPWrite(dms[i],&kdm);CHKERRQ(ierr);
683       /* Ugly hack so that the next KSPSetUp() will use the RHS that we set. A better fix is to change dmActive to take
684        * a bitwise OR of computing the matrix, RHS, and initial iterate. */
685       kdm->ops->computerhs = NULL;
686       kdm->rhsctx          = NULL;
687       if (!mglevels[i+1]->interpolate) {
688         ierr = DMCreateInterpolation(dms[i],dms[i+1],&p,&rscale);CHKERRQ(ierr);
689         ierr = PCMGSetInterpolation(pc,i+1,p);CHKERRQ(ierr);
690         if (rscale) {ierr = PCMGSetRScale(pc,i+1,rscale);CHKERRQ(ierr);}
691         ierr = VecDestroy(&rscale);CHKERRQ(ierr);
692         ierr = MatDestroy(&p);CHKERRQ(ierr);
693       }
694       ierr = DMHasCreateRestriction(dms[i],&dmhasrestrict);CHKERRQ(ierr);
695       if (dmhasrestrict && !mglevels[i+1]->restrct){
696         ierr = DMCreateRestriction(dms[i],dms[i+1],&p);CHKERRQ(ierr);
697         ierr = PCMGSetRestriction(pc,i+1,p);CHKERRQ(ierr);
698         ierr = MatDestroy(&p);CHKERRQ(ierr);
699       }
700       ierr = DMHasCreateInjection(dms[i],&dmhasinject);CHKERRQ(ierr);
701       if (dmhasinject && !mglevels[i+1]->inject){
702         ierr = DMCreateInjection(dms[i],dms[i+1],&p);CHKERRQ(ierr);
703         ierr = PCMGSetInjection(pc,i+1,p);CHKERRQ(ierr);
704         ierr = MatDestroy(&p);CHKERRQ(ierr);
705       }
706     }
707 
708     for (i=n-2; i>-1; i--) {ierr = DMDestroy(&dms[i]);CHKERRQ(ierr);}
709     ierr = PetscFree(dms);CHKERRQ(ierr);
710   }
711 
712   if (pc->dm && !pc->setupcalled) {
713     /* finest smoother also gets DM but it is not active, independent of whether galerkin==PC_MG_GALERKIN_EXTERNAL */
714     ierr = KSPSetDM(mglevels[n-1]->smoothd,pc->dm);CHKERRQ(ierr);
715     ierr = KSPSetDMActive(mglevels[n-1]->smoothd,PETSC_FALSE);CHKERRQ(ierr);
716     if (mglevels[n-1]->smoothd != mglevels[n-1]->smoothu) {
717       ierr = KSPSetDM(mglevels[n-1]->smoothu,pc->dm);CHKERRQ(ierr);
718       ierr = KSPSetDMActive(mglevels[n-1]->smoothu,PETSC_FALSE);CHKERRQ(ierr);
719     }
720   }
721 
722   if (mg->galerkin < PC_MG_GALERKIN_NONE) {
723     Mat       A,B;
724     PetscBool doA = PETSC_FALSE,doB = PETSC_FALSE;
725     MatReuse  reuse = MAT_INITIAL_MATRIX;
726 
727     if ((mg->galerkin == PC_MG_GALERKIN_PMAT) || (mg->galerkin == PC_MG_GALERKIN_BOTH)) doB = PETSC_TRUE;
728     if ((mg->galerkin == PC_MG_GALERKIN_MAT) || ((mg->galerkin == PC_MG_GALERKIN_BOTH) && (dA != dB))) doA = PETSC_TRUE;
729     if (pc->setupcalled) reuse = MAT_REUSE_MATRIX;
730     for (i=n-2; i>-1; i--) {
731       if (!mglevels[i+1]->restrct && !mglevels[i+1]->interpolate) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONGSTATE,"Must provide interpolation or restriction for each MG level except level 0");
732       if (!mglevels[i+1]->interpolate) {
733         ierr = PCMGSetInterpolation(pc,i+1,mglevels[i+1]->restrct);CHKERRQ(ierr);
734       }
735       if (!mglevels[i+1]->restrct) {
736         ierr = PCMGSetRestriction(pc,i+1,mglevels[i+1]->interpolate);CHKERRQ(ierr);
737       }
738       if (reuse == MAT_REUSE_MATRIX) {
739         ierr = KSPGetOperators(mglevels[i]->smoothd,&A,&B);CHKERRQ(ierr);
740       }
741       if (doA) {
742         ierr = MatGalerkin(mglevels[i+1]->restrct,dA,mglevels[i+1]->interpolate,reuse,1.0,&A);CHKERRQ(ierr);
743       }
744       if (doB) {
745         ierr = MatGalerkin(mglevels[i+1]->restrct,dB,mglevels[i+1]->interpolate,reuse,1.0,&B);CHKERRQ(ierr);
746       }
747       /* the management of the PetscObjectReference() and PetscObjecDereference() below is rather delicate */
748       if (!doA && dAeqdB) {
749         if (reuse == MAT_INITIAL_MATRIX) {ierr = PetscObjectReference((PetscObject)B);CHKERRQ(ierr);}
750         A = B;
751       } else if (!doA && reuse == MAT_INITIAL_MATRIX ) {
752         ierr = KSPGetOperators(mglevels[i]->smoothd,&A,NULL);CHKERRQ(ierr);
753         ierr = PetscObjectReference((PetscObject)A);CHKERRQ(ierr);
754       }
755       if (!doB && dAeqdB) {
756         if (reuse == MAT_INITIAL_MATRIX) {ierr = PetscObjectReference((PetscObject)A);CHKERRQ(ierr);}
757         B = A;
758       } else if (!doB && reuse == MAT_INITIAL_MATRIX) {
759         ierr = KSPGetOperators(mglevels[i]->smoothd,NULL,&B);CHKERRQ(ierr);
760         ierr = PetscObjectReference((PetscObject)B);CHKERRQ(ierr);
761       }
762       if (reuse == MAT_INITIAL_MATRIX) {
763         ierr = KSPSetOperators(mglevels[i]->smoothd,A,B);CHKERRQ(ierr);
764         ierr = PetscObjectDereference((PetscObject)A);CHKERRQ(ierr);
765         ierr = PetscObjectDereference((PetscObject)B);CHKERRQ(ierr);
766       }
767       dA = A;
768       dB = B;
769     }
770   }
771   if (needRestricts && pc->dm && pc->dm->x) {
772     /* need to restrict Jacobian location to coarser meshes for evaluation */
773     for (i=n-2; i>-1; i--) {
774       Mat R;
775       Vec rscale;
776       if (!mglevels[i]->smoothd->dm->x) {
777         Vec *vecs;
778         ierr = KSPCreateVecs(mglevels[i]->smoothd,1,&vecs,0,NULL);CHKERRQ(ierr);
779         mglevels[i]->smoothd->dm->x = vecs[0];
780         ierr = PetscFree(vecs);CHKERRQ(ierr);
781       }
782       ierr = PCMGGetRestriction(pc,i+1,&R);CHKERRQ(ierr);
783       ierr = PCMGGetRScale(pc,i+1,&rscale);CHKERRQ(ierr);
784       ierr = MatRestrict(R,mglevels[i+1]->smoothd->dm->x,mglevels[i]->smoothd->dm->x);CHKERRQ(ierr);
785       ierr = VecPointwiseMult(mglevels[i]->smoothd->dm->x,mglevels[i]->smoothd->dm->x,rscale);CHKERRQ(ierr);
786     }
787   }
788   if (needRestricts && pc->dm) {
789     for (i=n-2; i>=0; i--) {
790       DM  dmfine,dmcoarse;
791       Mat Restrict,Inject;
792       Vec rscale;
793       ierr   = KSPGetDM(mglevels[i+1]->smoothd,&dmfine);CHKERRQ(ierr);
794       ierr   = KSPGetDM(mglevels[i]->smoothd,&dmcoarse);CHKERRQ(ierr);
795       ierr   = PCMGGetRestriction(pc,i+1,&Restrict);CHKERRQ(ierr);
796       ierr   = PCMGGetRScale(pc,i+1,&rscale);CHKERRQ(ierr);
797       ierr   = PCMGGetInjection(pc,i+1,&Inject);CHKERRQ(ierr);
798       ierr   = DMRestrict(dmfine,Restrict,rscale,Inject,dmcoarse);CHKERRQ(ierr);
799     }
800   }
801 
802   if (!pc->setupcalled) {
803     for (i=0; i<n; i++) {
804       ierr = KSPSetFromOptions(mglevels[i]->smoothd);CHKERRQ(ierr);
805     }
806     for (i=1; i<n; i++) {
807       if (mglevels[i]->smoothu && (mglevels[i]->smoothu != mglevels[i]->smoothd)) {
808         ierr = KSPSetFromOptions(mglevels[i]->smoothu);CHKERRQ(ierr);
809       }
810     }
811     /* insure that if either interpolation or restriction is set the other other one is set */
812     for (i=1; i<n; i++) {
813       ierr = PCMGGetInterpolation(pc,i,NULL);CHKERRQ(ierr);
814       ierr = PCMGGetRestriction(pc,i,NULL);CHKERRQ(ierr);
815     }
816     for (i=0; i<n-1; i++) {
817       if (!mglevels[i]->b) {
818         Vec *vec;
819         ierr = KSPCreateVecs(mglevels[i]->smoothd,1,&vec,0,NULL);CHKERRQ(ierr);
820         ierr = PCMGSetRhs(pc,i,*vec);CHKERRQ(ierr);
821         ierr = VecDestroy(vec);CHKERRQ(ierr);
822         ierr = PetscFree(vec);CHKERRQ(ierr);
823       }
824       if (!mglevels[i]->r && i) {
825         ierr = VecDuplicate(mglevels[i]->b,&tvec);CHKERRQ(ierr);
826         ierr = PCMGSetR(pc,i,tvec);CHKERRQ(ierr);
827         ierr = VecDestroy(&tvec);CHKERRQ(ierr);
828       }
829       if (!mglevels[i]->x) {
830         ierr = VecDuplicate(mglevels[i]->b,&tvec);CHKERRQ(ierr);
831         ierr = PCMGSetX(pc,i,tvec);CHKERRQ(ierr);
832         ierr = VecDestroy(&tvec);CHKERRQ(ierr);
833       }
834     }
835     if (n != 1 && !mglevels[n-1]->r) {
836       /* PCMGSetR() on the finest level if user did not supply it */
837       Vec *vec;
838       ierr = KSPCreateVecs(mglevels[n-1]->smoothd,1,&vec,0,NULL);CHKERRQ(ierr);
839       ierr = PCMGSetR(pc,n-1,*vec);CHKERRQ(ierr);
840       ierr = VecDestroy(vec);CHKERRQ(ierr);
841       ierr = PetscFree(vec);CHKERRQ(ierr);
842     }
843   }
844 
845   if (pc->dm) {
846     /* need to tell all the coarser levels to rebuild the matrix using the DM for that level */
847     for (i=0; i<n-1; i++) {
848       if (mglevels[i]->smoothd->setupstage != KSP_SETUP_NEW) mglevels[i]->smoothd->setupstage = KSP_SETUP_NEWMATRIX;
849     }
850   }
851 
852   for (i=1; i<n; i++) {
853     if (mglevels[i]->smoothu == mglevels[i]->smoothd || mg->am == PC_MG_FULL || mg->am == PC_MG_KASKADE || mg->cyclesperpcapply > 1){
854       /* if doing only down then initial guess is zero */
855       ierr = KSPSetInitialGuessNonzero(mglevels[i]->smoothd,PETSC_TRUE);CHKERRQ(ierr);
856     }
857     if (mglevels[i]->eventsmoothsetup) {ierr = PetscLogEventBegin(mglevels[i]->eventsmoothsetup,0,0,0,0);CHKERRQ(ierr);}
858     ierr = KSPSetUp(mglevels[i]->smoothd);CHKERRQ(ierr);
859     if (mglevels[i]->smoothd->reason == KSP_DIVERGED_PC_FAILED) {
860       pc->failedreason = PC_SUBPC_ERROR;
861     }
862     if (mglevels[i]->eventsmoothsetup) {ierr = PetscLogEventEnd(mglevels[i]->eventsmoothsetup,0,0,0,0);CHKERRQ(ierr);}
863     if (!mglevels[i]->residual) {
864       Mat mat;
865       ierr = KSPGetOperators(mglevels[i]->smoothd,&mat,NULL);CHKERRQ(ierr);
866       ierr = PCMGSetResidual(pc,i,PCMGResidualDefault,mat);CHKERRQ(ierr);
867     }
868   }
869   for (i=1; i<n; i++) {
870     if (mglevels[i]->smoothu && mglevels[i]->smoothu != mglevels[i]->smoothd) {
871       Mat downmat,downpmat;
872 
873       /* check if operators have been set for up, if not use down operators to set them */
874       ierr = KSPGetOperatorsSet(mglevels[i]->smoothu,&opsset,NULL);CHKERRQ(ierr);
875       if (!opsset) {
876         ierr = KSPGetOperators(mglevels[i]->smoothd,&downmat,&downpmat);CHKERRQ(ierr);
877         ierr = KSPSetOperators(mglevels[i]->smoothu,downmat,downpmat);CHKERRQ(ierr);
878       }
879 
880       ierr = KSPSetInitialGuessNonzero(mglevels[i]->smoothu,PETSC_TRUE);CHKERRQ(ierr);
881       if (mglevels[i]->eventsmoothsetup) {ierr = PetscLogEventBegin(mglevels[i]->eventsmoothsetup,0,0,0,0);CHKERRQ(ierr);}
882       ierr = KSPSetUp(mglevels[i]->smoothu);CHKERRQ(ierr);
883       if (mglevels[i]->smoothu->reason == KSP_DIVERGED_PC_FAILED) {
884         pc->failedreason = PC_SUBPC_ERROR;
885       }
886       if (mglevels[i]->eventsmoothsetup) {ierr = PetscLogEventEnd(mglevels[i]->eventsmoothsetup,0,0,0,0);CHKERRQ(ierr);}
887     }
888   }
889 
890   if (mglevels[0]->eventsmoothsetup) {ierr = PetscLogEventBegin(mglevels[0]->eventsmoothsetup,0,0,0,0);CHKERRQ(ierr);}
891   ierr = KSPSetUp(mglevels[0]->smoothd);CHKERRQ(ierr);
892   if (mglevels[0]->smoothd->reason == KSP_DIVERGED_PC_FAILED) {
893     pc->failedreason = PC_SUBPC_ERROR;
894   }
895   if (mglevels[0]->eventsmoothsetup) {ierr = PetscLogEventEnd(mglevels[0]->eventsmoothsetup,0,0,0,0);CHKERRQ(ierr);}
896 
897   /*
898      Dump the interpolation/restriction matrices plus the
899    Jacobian/stiffness on each level. This allows MATLAB users to
900    easily check if the Galerkin condition A_c = R A_f R^T is satisfied.
901 
902    Only support one or the other at the same time.
903   */
904 #if defined(PETSC_USE_SOCKET_VIEWER)
905   ierr = PetscOptionsGetBool(((PetscObject)pc)->options,((PetscObject)pc)->prefix,"-pc_mg_dump_matlab",&dump,NULL);CHKERRQ(ierr);
906   if (dump) viewer = PETSC_VIEWER_SOCKET_(PetscObjectComm((PetscObject)pc));
907   dump = PETSC_FALSE;
908 #endif
909   ierr = PetscOptionsGetBool(((PetscObject)pc)->options,((PetscObject)pc)->prefix,"-pc_mg_dump_binary",&dump,NULL);CHKERRQ(ierr);
910   if (dump) viewer = PETSC_VIEWER_BINARY_(PetscObjectComm((PetscObject)pc));
911 
912   if (viewer) {
913     for (i=1; i<n; i++) {
914       ierr = MatView(mglevels[i]->restrct,viewer);CHKERRQ(ierr);
915     }
916     for (i=0; i<n; i++) {
917       ierr = KSPGetPC(mglevels[i]->smoothd,&pc);CHKERRQ(ierr);
918       ierr = MatView(pc->mat,viewer);CHKERRQ(ierr);
919     }
920   }
921   PetscFunctionReturn(0);
922 }
923 
924 /* -------------------------------------------------------------------------------------*/
925 
926 PetscErrorCode PCMGGetLevels_MG(PC pc, PetscInt *levels)
927 {
928   PC_MG *mg = (PC_MG *) pc->data;
929 
930   PetscFunctionBegin;
931   *levels = mg->nlevels;
932   PetscFunctionReturn(0);
933 }
934 
935 /*@
936    PCMGGetLevels - Gets the number of levels to use with MG.
937 
938    Not Collective
939 
940    Input Parameter:
941 .  pc - the preconditioner context
942 
943    Output parameter:
944 .  levels - the number of levels
945 
946    Level: advanced
947 
948 .keywords: MG, get, levels, multigrid
949 
950 .seealso: PCMGSetLevels()
951 @*/
952 PetscErrorCode PCMGGetLevels(PC pc,PetscInt *levels)
953 {
954   PetscErrorCode ierr;
955 
956   PetscFunctionBegin;
957   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
958   PetscValidIntPointer(levels,2);
959   *levels = 0;
960   ierr = PetscTryMethod(pc,"PCMGGetLevels_C",(PC,PetscInt*),(pc,levels));CHKERRQ(ierr);
961   PetscFunctionReturn(0);
962 }
963 
964 /*@
965    PCMGSetType - Determines the form of multigrid to use:
966    multiplicative, additive, full, or the Kaskade algorithm.
967 
968    Logically Collective on PC
969 
970    Input Parameters:
971 +  pc - the preconditioner context
972 -  form - multigrid form, one of PC_MG_MULTIPLICATIVE, PC_MG_ADDITIVE,
973    PC_MG_FULL, PC_MG_KASKADE
974 
975    Options Database Key:
976 .  -pc_mg_type <form> - Sets <form>, one of multiplicative,
977    additive, full, kaskade
978 
979    Level: advanced
980 
981 .keywords: MG, set, method, multiplicative, additive, full, Kaskade, multigrid
982 
983 .seealso: PCMGSetLevels()
984 @*/
985 PetscErrorCode  PCMGSetType(PC pc,PCMGType form)
986 {
987   PC_MG *mg = (PC_MG*)pc->data;
988 
989   PetscFunctionBegin;
990   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
991   PetscValidLogicalCollectiveEnum(pc,form,2);
992   mg->am = form;
993   if (form == PC_MG_MULTIPLICATIVE) pc->ops->applyrichardson = PCApplyRichardson_MG;
994   else pc->ops->applyrichardson = NULL;
995   PetscFunctionReturn(0);
996 }
997 
998 /*@
999    PCMGGetType - Determines the form of multigrid to use:
1000    multiplicative, additive, full, or the Kaskade algorithm.
1001 
1002    Logically Collective on PC
1003 
1004    Input Parameter:
1005 .  pc - the preconditioner context
1006 
1007    Output Parameter:
1008 .  type - one of PC_MG_MULTIPLICATIVE, PC_MG_ADDITIVE,PC_MG_FULL, PC_MG_KASKADE
1009 
1010 
1011    Level: advanced
1012 
1013 .keywords: MG, set, method, multiplicative, additive, full, Kaskade, multigrid
1014 
1015 .seealso: PCMGSetLevels()
1016 @*/
1017 PetscErrorCode  PCMGGetType(PC pc,PCMGType *type)
1018 {
1019   PC_MG *mg = (PC_MG*)pc->data;
1020 
1021   PetscFunctionBegin;
1022   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
1023   *type = mg->am;
1024   PetscFunctionReturn(0);
1025 }
1026 
1027 /*@
1028    PCMGSetCycleType - Sets the type cycles to use.  Use PCMGSetCycleTypeOnLevel() for more
1029    complicated cycling.
1030 
1031    Logically Collective on PC
1032 
1033    Input Parameters:
1034 +  pc - the multigrid context
1035 -  n - either PC_MG_CYCLE_V or PC_MG_CYCLE_W
1036 
1037    Options Database Key:
1038 .  -pc_mg_cycle_type <v,w> - provide the cycle desired
1039 
1040    Level: advanced
1041 
1042 .keywords: MG, set, cycles, V-cycle, W-cycle, multigrid
1043 
1044 .seealso: PCMGSetCycleTypeOnLevel()
1045 @*/
1046 PetscErrorCode  PCMGSetCycleType(PC pc,PCMGCycleType n)
1047 {
1048   PC_MG        *mg        = (PC_MG*)pc->data;
1049   PC_MG_Levels **mglevels = mg->levels;
1050   PetscInt     i,levels;
1051 
1052   PetscFunctionBegin;
1053   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
1054   PetscValidLogicalCollectiveEnum(pc,n,2);
1055   if (!mglevels) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ORDER,"Must set MG levels with PCMGSetLevels() before calling");
1056   levels = mglevels[0]->levels;
1057   for (i=0; i<levels; i++) mglevels[i]->cycles = n;
1058   PetscFunctionReturn(0);
1059 }
1060 
1061 /*@
1062    PCMGMultiplicativeSetCycles - Sets the number of cycles to use for each preconditioner step
1063          of multigrid when PCMGType of PC_MG_MULTIPLICATIVE is used
1064 
1065    Logically Collective on PC
1066 
1067    Input Parameters:
1068 +  pc - the multigrid context
1069 -  n - number of cycles (default is 1)
1070 
1071    Options Database Key:
1072 .  -pc_mg_multiplicative_cycles n
1073 
1074    Level: advanced
1075 
1076    Notes:
1077     This is not associated with setting a v or w cycle, that is set with PCMGSetCycleType()
1078 
1079 .keywords: MG, set, cycles, V-cycle, W-cycle, multigrid
1080 
1081 .seealso: PCMGSetCycleTypeOnLevel(), PCMGSetCycleType()
1082 @*/
1083 PetscErrorCode  PCMGMultiplicativeSetCycles(PC pc,PetscInt n)
1084 {
1085   PC_MG        *mg        = (PC_MG*)pc->data;
1086 
1087   PetscFunctionBegin;
1088   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
1089   PetscValidLogicalCollectiveInt(pc,n,2);
1090   mg->cyclesperpcapply = n;
1091   PetscFunctionReturn(0);
1092 }
1093 
1094 PetscErrorCode PCMGSetGalerkin_MG(PC pc,PCMGGalerkinType use)
1095 {
1096   PC_MG *mg = (PC_MG*)pc->data;
1097 
1098   PetscFunctionBegin;
1099   mg->galerkin = use;
1100   PetscFunctionReturn(0);
1101 }
1102 
1103 /*@
1104    PCMGSetGalerkin - Causes the coarser grid matrices to be computed from the
1105       finest grid via the Galerkin process: A_i-1 = r_i * A_i * p_i
1106 
1107    Logically Collective on PC
1108 
1109    Input Parameters:
1110 +  pc - the multigrid context
1111 -  use - one of PC_MG_GALERKIN_BOTH,PC_MG_GALERKIN_PMAT,PC_MG_GALERKIN_MAT, or PC_MG_GALERKIN_NONE
1112 
1113    Options Database Key:
1114 .  -pc_mg_galerkin <both,pmat,mat,none>
1115 
1116    Level: intermediate
1117 
1118    Notes:
1119     Some codes that use PCMG such as PCGAMG use Galerkin internally while constructing the hierarchy and thus do not
1120      use the PCMG construction of the coarser grids.
1121 
1122 .keywords: MG, set, Galerkin
1123 
1124 .seealso: PCMGGetGalerkin(), PCMGGalerkinType
1125 
1126 @*/
1127 PetscErrorCode PCMGSetGalerkin(PC pc,PCMGGalerkinType use)
1128 {
1129   PetscErrorCode ierr;
1130 
1131   PetscFunctionBegin;
1132   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
1133   ierr = PetscTryMethod(pc,"PCMGSetGalerkin_C",(PC,PCMGGalerkinType),(pc,use));CHKERRQ(ierr);
1134   PetscFunctionReturn(0);
1135 }
1136 
1137 /*@
1138    PCMGGetGalerkin - Checks if Galerkin multigrid is being used, i.e.
1139       A_i-1 = r_i * A_i * p_i
1140 
1141    Not Collective
1142 
1143    Input Parameter:
1144 .  pc - the multigrid context
1145 
1146    Output Parameter:
1147 .  galerkin - one of PC_MG_GALERKIN_BOTH,PC_MG_GALERKIN_PMAT,PC_MG_GALERKIN_MAT, PC_MG_GALERKIN_NONE, or PC_MG_GALERKIN_EXTERNAL
1148 
1149    Level: intermediate
1150 
1151 .keywords: MG, set, Galerkin
1152 
1153 .seealso: PCMGSetGalerkin(), PCMGGalerkinType
1154 
1155 @*/
1156 PetscErrorCode  PCMGGetGalerkin(PC pc,PCMGGalerkinType  *galerkin)
1157 {
1158   PC_MG *mg = (PC_MG*)pc->data;
1159 
1160   PetscFunctionBegin;
1161   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
1162   *galerkin = mg->galerkin;
1163   PetscFunctionReturn(0);
1164 }
1165 
1166 /*@
1167    PCMGSetNumberSmooth - Sets the number of pre and post-smoothing steps to use
1168    on all levels.  Use PCMGDistinctSmoothUp() to create separate up and down smoothers if you want different numbers of
1169    pre- and post-smoothing steps.
1170 
1171    Logically Collective on PC
1172 
1173    Input Parameters:
1174 +  mg - the multigrid context
1175 -  n - the number of smoothing steps
1176 
1177    Options Database Key:
1178 +  -mg_levels_ksp_max_it <n> - Sets number of pre and post-smoothing steps
1179 
1180    Level: advanced
1181 
1182    Notes:
1183     this does not set a value on the coarsest grid, since we assume that
1184     there is no separate smooth up on the coarsest grid.
1185 
1186 .keywords: MG, smooth, up, post-smoothing, steps, multigrid
1187 
1188 .seealso: PCMGSetDistinctSmoothUp()
1189 @*/
1190 PetscErrorCode  PCMGSetNumberSmooth(PC pc,PetscInt n)
1191 {
1192   PC_MG          *mg        = (PC_MG*)pc->data;
1193   PC_MG_Levels   **mglevels = mg->levels;
1194   PetscErrorCode ierr;
1195   PetscInt       i,levels;
1196 
1197   PetscFunctionBegin;
1198   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
1199   PetscValidLogicalCollectiveInt(pc,n,2);
1200   if (!mglevels) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ORDER,"Must set MG levels with PCMGSetLevels() before calling");
1201   levels = mglevels[0]->levels;
1202 
1203   for (i=1; i<levels; i++) {
1204     ierr = KSPSetTolerances(mglevels[i]->smoothu,PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT,n);CHKERRQ(ierr);
1205     ierr = KSPSetTolerances(mglevels[i]->smoothd,PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT,n);CHKERRQ(ierr);
1206     mg->default_smoothu = n;
1207     mg->default_smoothd = n;
1208   }
1209   PetscFunctionReturn(0);
1210 }
1211 
1212 /*@
1213    PCMGSetDistinctSmoothUp - sets the up (post) smoother to be a seperate KSP from the down (pre) smoother on all levels
1214        and adds the suffix _up to the options name
1215 
1216    Logically Collective on PC
1217 
1218    Input Parameters:
1219 .  pc - the preconditioner context
1220 
1221    Options Database Key:
1222 .  -pc_mg_distinct_smoothup
1223 
1224    Level: advanced
1225 
1226    Notes:
1227     this does not set a value on the coarsest grid, since we assume that
1228     there is no separate smooth up on the coarsest grid.
1229 
1230 .keywords: MG, smooth, up, post-smoothing, steps, multigrid
1231 
1232 .seealso: PCMGSetNumberSmooth()
1233 @*/
1234 PetscErrorCode  PCMGSetDistinctSmoothUp(PC pc)
1235 {
1236   PC_MG          *mg        = (PC_MG*)pc->data;
1237   PC_MG_Levels   **mglevels = mg->levels;
1238   PetscErrorCode ierr;
1239   PetscInt       i,levels;
1240   KSP            subksp;
1241 
1242   PetscFunctionBegin;
1243   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
1244   if (!mglevels) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ORDER,"Must set MG levels with PCMGSetLevels() before calling");
1245   levels = mglevels[0]->levels;
1246 
1247   for (i=1; i<levels; i++) {
1248     const char *prefix = NULL;
1249     /* make sure smoother up and down are different */
1250     ierr = PCMGGetSmootherUp(pc,i,&subksp);CHKERRQ(ierr);
1251     ierr = KSPGetOptionsPrefix(mglevels[i]->smoothd,&prefix);CHKERRQ(ierr);
1252     ierr = KSPSetOptionsPrefix(subksp,prefix);CHKERRQ(ierr);
1253     ierr = KSPAppendOptionsPrefix(subksp,"up_");CHKERRQ(ierr);
1254   }
1255   PetscFunctionReturn(0);
1256 }
1257 
1258 /* ----------------------------------------------------------------------------------------*/
1259 
1260 /*MC
1261    PCMG - Use multigrid preconditioning. This preconditioner requires you provide additional
1262     information about the coarser grid matrices and restriction/interpolation operators.
1263 
1264    Options Database Keys:
1265 +  -pc_mg_levels <nlevels> - number of levels including finest
1266 .  -pc_mg_cycle_type <v,w> - provide the cycle desired
1267 .  -pc_mg_type <additive,multiplicative,full,kaskade> - multiplicative is the default
1268 .  -pc_mg_log - log information about time spent on each level of the solver
1269 .  -pc_mg_distinct_smoothup - configure up (after interpolation) and down (before restriction) smoothers separately (with different options prefixes)
1270 .  -pc_mg_galerkin <both,pmat,mat,none> - use Galerkin process to compute coarser operators, i.e. Acoarse = R A R'
1271 .  -pc_mg_multiplicative_cycles - number of cycles to use as the preconditioner (defaults to 1)
1272 .  -pc_mg_dump_matlab - dumps the matrices for each level and the restriction/interpolation matrices
1273                         to the Socket viewer for reading from MATLAB.
1274 -  -pc_mg_dump_binary - dumps the matrices for each level and the restriction/interpolation matrices
1275                         to the binary output file called binaryoutput
1276 
1277    Notes:
1278     If one uses a Krylov method such GMRES or CG as the smoother then one must use KSPFGMRES, KSPGCR, or KSPRICHARDSON as the outer Krylov method
1279 
1280        When run with a single level the smoother options are used on that level NOT the coarse grid solver options
1281 
1282        When run with KSPRICHARDSON the convergence test changes slightly if monitor is turned on. The iteration count may change slightly. This
1283        is because without monitoring the residual norm is computed WITHIN each multigrid cycle on the finest level after the pre-smoothing
1284        (because the residual has just been computed for the multigrid algorithm and is hence available for free) while with monitoring the
1285        residual is computed at the end of each cycle.
1286 
1287    Level: intermediate
1288 
1289    Concepts: multigrid/multilevel
1290 
1291 .seealso:  PCCreate(), PCSetType(), PCType (for list of available types), PC, PCMGType, PCEXOTIC, PCGAMG, PCML, PCHYPRE
1292            PCMGSetLevels(), PCMGGetLevels(), PCMGSetType(), PCMGSetCycleType(),
1293            PCMGSetDistinctSmoothUp(), PCMGGetCoarseSolve(), PCMGSetResidual(), PCMGSetInterpolation(),
1294            PCMGSetRestriction(), PCMGGetSmoother(), PCMGGetSmootherUp(), PCMGGetSmootherDown(),
1295            PCMGSetCycleTypeOnLevel(), PCMGSetRhs(), PCMGSetX(), PCMGSetR()
1296 M*/
1297 
1298 PETSC_EXTERN PetscErrorCode PCCreate_MG(PC pc)
1299 {
1300   PC_MG          *mg;
1301   PetscErrorCode ierr;
1302 
1303   PetscFunctionBegin;
1304   ierr         = PetscNewLog(pc,&mg);CHKERRQ(ierr);
1305   pc->data     = (void*)mg;
1306   mg->nlevels  = -1;
1307   mg->am       = PC_MG_MULTIPLICATIVE;
1308   mg->galerkin = PC_MG_GALERKIN_NONE;
1309 
1310   pc->useAmat = PETSC_TRUE;
1311 
1312   pc->ops->apply          = PCApply_MG;
1313   pc->ops->setup          = PCSetUp_MG;
1314   pc->ops->reset          = PCReset_MG;
1315   pc->ops->destroy        = PCDestroy_MG;
1316   pc->ops->setfromoptions = PCSetFromOptions_MG;
1317   pc->ops->view           = PCView_MG;
1318 
1319   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCMGSetGalerkin_C",PCMGSetGalerkin_MG);CHKERRQ(ierr);
1320   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCMGGetLevels_C",PCMGGetLevels_MG);CHKERRQ(ierr);
1321   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCMGSetLevels_C",PCMGSetLevels_MG);CHKERRQ(ierr);
1322   PetscFunctionReturn(0);
1323 }
1324