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