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