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