xref: /petsc/src/ksp/pc/impls/mg/mg.c (revision 40cbb1a031ea8f2be4fe2b92dc842b003ad37be3)
1 
2 /*
3     Defines the multigrid preconditioner interface.
4 */
5 #include <petsc/private/pcmgimpl.h>                    /*I "petscksp.h" I*/
6 #include <petsc/private/kspimpl.h>
7 #include <petscdm.h>
8 PETSC_INTERN PetscErrorCode PCPreSolveChangeRHS(PC,PetscBool*);
9 
10 /*
11    Contains the list of registered coarse space construction routines
12 */
13 PetscFunctionList PCMGCoarseList = NULL;
14 
15 PetscErrorCode PCMGMCycle_Private(PC pc,PC_MG_Levels **mglevelsin,PetscBool transpose,PetscBool matapp,PCRichardsonConvergedReason *reason)
16 {
17   PC_MG          *mg = (PC_MG*)pc->data;
18   PC_MG_Levels   *mgc,*mglevels = *mglevelsin;
19   PetscInt       cycles = (mglevels->level == 1) ? 1 : (PetscInt) mglevels->cycles;
20 
21   PetscFunctionBegin;
22   if (mglevels->eventsmoothsolve) PetscCall(PetscLogEventBegin(mglevels->eventsmoothsolve,0,0,0,0));
23   if (!transpose) {
24     if (matapp) {
25       PetscCall(KSPMatSolve(mglevels->smoothd,mglevels->B,mglevels->X));  /* pre-smooth */
26       PetscCall(KSPCheckSolve(mglevels->smoothd,pc,NULL));
27     } else {
28       PetscCall(KSPSolve(mglevels->smoothd,mglevels->b,mglevels->x));  /* pre-smooth */
29       PetscCall(KSPCheckSolve(mglevels->smoothd,pc,mglevels->x));
30     }
31   } else {
32     PetscCheck(!matapp,PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Not supported");
33     PetscCall(KSPSolveTranspose(mglevels->smoothu,mglevels->b,mglevels->x)); /* transpose of post-smooth */
34     PetscCall(KSPCheckSolve(mglevels->smoothu,pc,mglevels->x));
35   }
36   if (mglevels->eventsmoothsolve) PetscCall(PetscLogEventEnd(mglevels->eventsmoothsolve,0,0,0,0));
37   if (mglevels->level) {  /* not the coarsest grid */
38     if (mglevels->eventresidual) PetscCall(PetscLogEventBegin(mglevels->eventresidual,0,0,0,0));
39     if (matapp && !mglevels->R) {
40       PetscCall(MatDuplicate(mglevels->B,MAT_DO_NOT_COPY_VALUES,&mglevels->R));
41     }
42     if (!transpose) {
43       if (matapp) PetscCall((*mglevels->matresidual)(mglevels->A,mglevels->B,mglevels->X,mglevels->R));
44       else PetscCall((*mglevels->residual)(mglevels->A,mglevels->b,mglevels->x,mglevels->r));
45     } else {
46       if (matapp) PetscCall((*mglevels->matresidualtranspose)(mglevels->A,mglevels->B,mglevels->X,mglevels->R));
47       else PetscCall((*mglevels->residualtranspose)(mglevels->A,mglevels->b,mglevels->x,mglevels->r));
48     }
49     if (mglevels->eventresidual) PetscCall(PetscLogEventEnd(mglevels->eventresidual,0,0,0,0));
50 
51     /* if on finest level and have convergence criteria set */
52     if (mglevels->level == mglevels->levels-1 && mg->ttol && reason) {
53       PetscReal rnorm;
54       PetscCall(VecNorm(mglevels->r,NORM_2,&rnorm));
55       if (rnorm <= mg->ttol) {
56         if (rnorm < mg->abstol) {
57           *reason = PCRICHARDSON_CONVERGED_ATOL;
58           PetscCall(PetscInfo(pc,"Linear solver has converged. Residual norm %g is less than absolute tolerance %g\n",(double)rnorm,(double)mg->abstol));
59         } else {
60           *reason = PCRICHARDSON_CONVERGED_RTOL;
61           PetscCall(PetscInfo(pc,"Linear solver has converged. Residual norm %g is less than relative tolerance times initial residual norm %g\n",(double)rnorm,(double)mg->ttol));
62         }
63         PetscFunctionReturn(0);
64       }
65     }
66 
67     mgc = *(mglevelsin - 1);
68     if (mglevels->eventinterprestrict) PetscCall(PetscLogEventBegin(mglevels->eventinterprestrict,0,0,0,0));
69     if (!transpose) {
70       if (matapp) PetscCall(MatMatRestrict(mglevels->restrct,mglevels->R,&mgc->B));
71       else PetscCall(MatRestrict(mglevels->restrct,mglevels->r,mgc->b));
72     } else {
73       if (matapp) PetscCall(MatMatRestrict(mglevels->interpolate,mglevels->R,&mgc->B));
74       else PetscCall(MatRestrict(mglevels->interpolate,mglevels->r,mgc->b));
75     }
76     if (mglevels->eventinterprestrict) PetscCall(PetscLogEventEnd(mglevels->eventinterprestrict,0,0,0,0));
77     if (matapp) {
78       if (!mgc->X) {
79         PetscCall(MatDuplicate(mgc->B,MAT_DO_NOT_COPY_VALUES,&mgc->X));
80       } else {
81         PetscCall(MatZeroEntries(mgc->X));
82       }
83     } else {
84       PetscCall(VecZeroEntries(mgc->x));
85     }
86     while (cycles--) {
87       PetscCall(PCMGMCycle_Private(pc,mglevelsin-1,transpose,matapp,reason));
88     }
89     if (mglevels->eventinterprestrict) PetscCall(PetscLogEventBegin(mglevels->eventinterprestrict,0,0,0,0));
90     if (!transpose) {
91       if (matapp) PetscCall(MatMatInterpolateAdd(mglevels->interpolate,mgc->X,mglevels->X,&mglevels->X));
92       else PetscCall(MatInterpolateAdd(mglevels->interpolate,mgc->x,mglevels->x,mglevels->x));
93     } else {
94       PetscCall(MatInterpolateAdd(mglevels->restrct,mgc->x,mglevels->x,mglevels->x));
95     }
96     if (mglevels->eventinterprestrict) PetscCall(PetscLogEventEnd(mglevels->eventinterprestrict,0,0,0,0));
97     if (mglevels->eventsmoothsolve) PetscCall(PetscLogEventBegin(mglevels->eventsmoothsolve,0,0,0,0));
98     if (!transpose) {
99       if (matapp) {
100         PetscCall(KSPMatSolve(mglevels->smoothu,mglevels->B,mglevels->X));    /* post smooth */
101         PetscCall(KSPCheckSolve(mglevels->smoothu,pc,NULL));
102       } else {
103         PetscCall(KSPSolve(mglevels->smoothu,mglevels->b,mglevels->x));    /* post smooth */
104         PetscCall(KSPCheckSolve(mglevels->smoothu,pc,mglevels->x));
105       }
106     } else {
107       PetscCheck(!matapp,PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Not supported");
108       PetscCall(KSPSolveTranspose(mglevels->smoothd,mglevels->b,mglevels->x));    /* post smooth */
109       PetscCall(KSPCheckSolve(mglevels->smoothd,pc,mglevels->x));
110     }
111     if (mglevels->cr) {
112       PetscCheck(!matapp,PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Not supported");
113       /* TODO Turn on copy and turn off noisy if we have an exact solution
114       PetscCall(VecCopy(mglevels->x, mglevels->crx));
115       PetscCall(VecCopy(mglevels->b, mglevels->crb)); */
116       PetscCall(KSPSetNoisy_Private(mglevels->crx));
117       PetscCall(KSPSolve(mglevels->cr,mglevels->crb,mglevels->crx));    /* compatible relaxation */
118       PetscCall(KSPCheckSolve(mglevels->cr,pc,mglevels->crx));
119     }
120     if (mglevels->eventsmoothsolve) PetscCall(PetscLogEventEnd(mglevels->eventsmoothsolve,0,0,0,0));
121   }
122   PetscFunctionReturn(0);
123 }
124 
125 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)
126 {
127   PC_MG          *mg        = (PC_MG*)pc->data;
128   PC_MG_Levels   **mglevels = mg->levels;
129   PC             tpc;
130   PetscBool      changeu,changed;
131   PetscInt       levels = mglevels[0]->levels,i;
132 
133   PetscFunctionBegin;
134   /* When the DM is supplying the matrix then it will not exist until here */
135   for (i=0; i<levels; i++) {
136     if (!mglevels[i]->A) {
137       PetscCall(KSPGetOperators(mglevels[i]->smoothu,&mglevels[i]->A,NULL));
138       PetscCall(PetscObjectReference((PetscObject)mglevels[i]->A));
139     }
140   }
141 
142   PetscCall(KSPGetPC(mglevels[levels-1]->smoothd,&tpc));
143   PetscCall(PCPreSolveChangeRHS(tpc,&changed));
144   PetscCall(KSPGetPC(mglevels[levels-1]->smoothu,&tpc));
145   PetscCall(PCPreSolveChangeRHS(tpc,&changeu));
146   if (!changed && !changeu) {
147     PetscCall(VecDestroy(&mglevels[levels-1]->b));
148     mglevels[levels-1]->b = b;
149   } else { /* if the smoother changes the rhs during PreSolve, we cannot use the input vector */
150     if (!mglevels[levels-1]->b) {
151       Vec *vec;
152 
153       PetscCall(KSPCreateVecs(mglevels[levels-1]->smoothd,1,&vec,0,NULL));
154       mglevels[levels-1]->b = *vec;
155       PetscCall(PetscFree(vec));
156     }
157     PetscCall(VecCopy(b,mglevels[levels-1]->b));
158   }
159   mglevels[levels-1]->x = x;
160 
161   mg->rtol   = rtol;
162   mg->abstol = abstol;
163   mg->dtol   = dtol;
164   if (rtol) {
165     /* compute initial residual norm for relative convergence test */
166     PetscReal rnorm;
167     if (zeroguess) {
168       PetscCall(VecNorm(b,NORM_2,&rnorm));
169     } else {
170       PetscCall((*mglevels[levels-1]->residual)(mglevels[levels-1]->A,b,x,w));
171       PetscCall(VecNorm(w,NORM_2,&rnorm));
172     }
173     mg->ttol = PetscMax(rtol*rnorm,abstol);
174   } else if (abstol) mg->ttol = abstol;
175   else mg->ttol = 0.0;
176 
177   /* since smoother is applied to full system, not just residual we need to make sure that smoothers don't
178      stop prematurely due to small residual */
179   for (i=1; i<levels; i++) {
180     PetscCall(KSPSetTolerances(mglevels[i]->smoothu,0,PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT));
181     if (mglevels[i]->smoothu != mglevels[i]->smoothd) {
182       /* For Richardson the initial guess is nonzero since it is solving in each cycle the original system not just applying as a preconditioner */
183       PetscCall(KSPSetInitialGuessNonzero(mglevels[i]->smoothd,PETSC_TRUE));
184       PetscCall(KSPSetTolerances(mglevels[i]->smoothd,0,PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT));
185     }
186   }
187 
188   *reason = (PCRichardsonConvergedReason)0;
189   for (i=0; i<its; i++) {
190     PetscCall(PCMGMCycle_Private(pc,mglevels+levels-1,PETSC_FALSE,PETSC_FALSE,reason));
191     if (*reason) break;
192   }
193   if (!*reason) *reason = PCRICHARDSON_CONVERGED_ITS;
194   *outits = i;
195   if (!changed && !changeu) mglevels[levels-1]->b = NULL;
196   PetscFunctionReturn(0);
197 }
198 
199 PetscErrorCode PCReset_MG(PC pc)
200 {
201   PC_MG          *mg        = (PC_MG*)pc->data;
202   PC_MG_Levels   **mglevels = mg->levels;
203   PetscInt       i,n;
204 
205   PetscFunctionBegin;
206   if (mglevels) {
207     n = mglevels[0]->levels;
208     for (i=0; i<n-1; i++) {
209       PetscCall(VecDestroy(&mglevels[i+1]->r));
210       PetscCall(VecDestroy(&mglevels[i]->b));
211       PetscCall(VecDestroy(&mglevels[i]->x));
212       PetscCall(MatDestroy(&mglevels[i+1]->R));
213       PetscCall(MatDestroy(&mglevels[i]->B));
214       PetscCall(MatDestroy(&mglevels[i]->X));
215       PetscCall(VecDestroy(&mglevels[i]->crx));
216       PetscCall(VecDestroy(&mglevels[i]->crb));
217       PetscCall(MatDestroy(&mglevels[i+1]->restrct));
218       PetscCall(MatDestroy(&mglevels[i+1]->interpolate));
219       PetscCall(MatDestroy(&mglevels[i+1]->inject));
220       PetscCall(VecDestroy(&mglevels[i+1]->rscale));
221     }
222     PetscCall(VecDestroy(&mglevels[n-1]->crx));
223     PetscCall(VecDestroy(&mglevels[n-1]->crb));
224     /* this is not null only if the smoother on the finest level
225        changes the rhs during PreSolve */
226     PetscCall(VecDestroy(&mglevels[n-1]->b));
227     PetscCall(MatDestroy(&mglevels[n-1]->B));
228 
229     for (i=0; i<n; i++) {
230       PetscCall(MatDestroy(&mglevels[i]->coarseSpace));
231       PetscCall(MatDestroy(&mglevels[i]->A));
232       if (mglevels[i]->smoothd != mglevels[i]->smoothu) {
233         PetscCall(KSPReset(mglevels[i]->smoothd));
234       }
235       PetscCall(KSPReset(mglevels[i]->smoothu));
236       if (mglevels[i]->cr) PetscCall(KSPReset(mglevels[i]->cr));
237     }
238     mg->Nc = 0;
239   }
240   PetscFunctionReturn(0);
241 }
242 
243 /* Implementing CR
244 
245 We only want to make corrections that ``do not change'' the coarse solution. What we mean by not changing is that if I prolong my coarse solution to the fine grid and then inject that fine solution back to the coarse grid, I get the same answer. Injection is what Brannick calls R. We want the complementary projector to Inj, which we will call S, after Brannick, so that Inj S = 0. Now the orthogonal projector onto the range of Inj^T is
246 
247   Inj^T (Inj Inj^T)^{-1} Inj
248 
249 and if Inj is a VecScatter, as it is now in PETSc, we have
250 
251   Inj^T Inj
252 
253 and
254 
255   S = I - Inj^T Inj
256 
257 since
258 
259   Inj S = Inj - (Inj Inj^T) Inj = 0.
260 
261 Brannick suggests
262 
263   A \to S^T A S  \qquad\mathrm{and}\qquad M \to S^T M S
264 
265 but I do not think his :math:`S^T S = I` is correct. Our S is an orthogonal projector, so :math:`S^T S = S^2 = S`. We will use
266 
267   M^{-1} A \to S M^{-1} A S
268 
269 In fact, since it is somewhat hard in PETSc to do the symmetric application, we will just apply S on the left.
270 
271   Check: || Inj P - I ||_F < tol
272   Check: In general, Inj Inj^T = I
273 */
274 
275 typedef struct {
276   PC       mg;  /* The PCMG object */
277   PetscInt l;   /* The multigrid level for this solver */
278   Mat      Inj; /* The injection matrix */
279   Mat      S;   /* I - Inj^T Inj */
280 } CRContext;
281 
282 static PetscErrorCode CRSetup_Private(PC pc)
283 {
284   CRContext     *ctx;
285   Mat            It;
286 
287   PetscFunctionBeginUser;
288   PetscCall(PCShellGetContext(pc, &ctx));
289   PetscCall(PCMGGetInjection(ctx->mg, ctx->l, &It));
290   PetscCheck(It,PetscObjectComm((PetscObject) pc), PETSC_ERR_ARG_WRONGSTATE, "CR requires that injection be defined for this PCMG");
291   PetscCall(MatCreateTranspose(It, &ctx->Inj));
292   PetscCall(MatCreateNormal(ctx->Inj, &ctx->S));
293   PetscCall(MatScale(ctx->S, -1.0));
294   PetscCall(MatShift(ctx->S,  1.0));
295   PetscFunctionReturn(0);
296 }
297 
298 static PetscErrorCode CRApply_Private(PC pc, Vec x, Vec y)
299 {
300   CRContext     *ctx;
301 
302   PetscFunctionBeginUser;
303   PetscCall(PCShellGetContext(pc, &ctx));
304   PetscCall(MatMult(ctx->S, x, y));
305   PetscFunctionReturn(0);
306 }
307 
308 static PetscErrorCode CRDestroy_Private(PC pc)
309 {
310   CRContext     *ctx;
311 
312   PetscFunctionBeginUser;
313   PetscCall(PCShellGetContext(pc, &ctx));
314   PetscCall(MatDestroy(&ctx->Inj));
315   PetscCall(MatDestroy(&ctx->S));
316   PetscCall(PetscFree(ctx));
317   PetscCall(PCShellSetContext(pc, NULL));
318   PetscFunctionReturn(0);
319 }
320 
321 static PetscErrorCode CreateCR_Private(PC pc, PetscInt l, PC *cr)
322 {
323   CRContext     *ctx;
324 
325   PetscFunctionBeginUser;
326   PetscCall(PCCreate(PetscObjectComm((PetscObject) pc), cr));
327   PetscCall(PetscObjectSetName((PetscObject) *cr, "S (complementary projector to injection)"));
328   PetscCall(PetscCalloc1(1, &ctx));
329   ctx->mg = pc;
330   ctx->l  = l;
331   PetscCall(PCSetType(*cr, PCSHELL));
332   PetscCall(PCShellSetContext(*cr, ctx));
333   PetscCall(PCShellSetApply(*cr, CRApply_Private));
334   PetscCall(PCShellSetSetUp(*cr, CRSetup_Private));
335   PetscCall(PCShellSetDestroy(*cr, CRDestroy_Private));
336   PetscFunctionReturn(0);
337 }
338 
339 PetscErrorCode PCMGSetLevels_MG(PC pc,PetscInt levels,MPI_Comm *comms)
340 {
341   PC_MG          *mg        = (PC_MG*)pc->data;
342   MPI_Comm       comm;
343   PC_MG_Levels   **mglevels = mg->levels;
344   PCMGType       mgtype     = mg->am;
345   PetscInt       mgctype    = (PetscInt) PC_MG_CYCLE_V;
346   PetscInt       i;
347   PetscMPIInt    size;
348   const char     *prefix;
349   PC             ipc;
350   PetscInt       n;
351 
352   PetscFunctionBegin;
353   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
354   PetscValidLogicalCollectiveInt(pc,levels,2);
355   if (mg->nlevels == levels) PetscFunctionReturn(0);
356   PetscCall(PetscObjectGetComm((PetscObject)pc,&comm));
357   if (mglevels) {
358     mgctype = mglevels[0]->cycles;
359     /* changing the number of levels so free up the previous stuff */
360     PetscCall(PCReset_MG(pc));
361     n    = mglevels[0]->levels;
362     for (i=0; i<n; i++) {
363       if (mglevels[i]->smoothd != mglevels[i]->smoothu) {
364         PetscCall(KSPDestroy(&mglevels[i]->smoothd));
365       }
366       PetscCall(KSPDestroy(&mglevels[i]->smoothu));
367       PetscCall(KSPDestroy(&mglevels[i]->cr));
368       PetscCall(PetscFree(mglevels[i]));
369     }
370     PetscCall(PetscFree(mg->levels));
371   }
372 
373   mg->nlevels = levels;
374 
375   PetscCall(PetscMalloc1(levels,&mglevels));
376   PetscCall(PetscLogObjectMemory((PetscObject)pc,levels*(sizeof(PC_MG*))));
377 
378   PetscCall(PCGetOptionsPrefix(pc,&prefix));
379 
380   mg->stageApply = 0;
381   for (i=0; i<levels; i++) {
382     PetscCall(PetscNewLog(pc,&mglevels[i]));
383 
384     mglevels[i]->level               = i;
385     mglevels[i]->levels              = levels;
386     mglevels[i]->cycles              = mgctype;
387     mg->default_smoothu              = 2;
388     mg->default_smoothd              = 2;
389     mglevels[i]->eventsmoothsetup    = 0;
390     mglevels[i]->eventsmoothsolve    = 0;
391     mglevels[i]->eventresidual       = 0;
392     mglevels[i]->eventinterprestrict = 0;
393 
394     if (comms) comm = comms[i];
395     if (comm != MPI_COMM_NULL) {
396       PetscCall(KSPCreate(comm,&mglevels[i]->smoothd));
397       PetscCall(KSPSetErrorIfNotConverged(mglevels[i]->smoothd,pc->erroriffailure));
398       PetscCall(PetscObjectIncrementTabLevel((PetscObject)mglevels[i]->smoothd,(PetscObject)pc,levels-i));
399       PetscCall(KSPSetOptionsPrefix(mglevels[i]->smoothd,prefix));
400       PetscCall(PetscObjectComposedDataSetInt((PetscObject) mglevels[i]->smoothd, PetscMGLevelId, mglevels[i]->level));
401       if (i || levels == 1) {
402         char tprefix[128];
403 
404         PetscCall(KSPSetType(mglevels[i]->smoothd,KSPCHEBYSHEV));
405         PetscCall(KSPSetConvergenceTest(mglevels[i]->smoothd,KSPConvergedSkip,NULL,NULL));
406         PetscCall(KSPSetNormType(mglevels[i]->smoothd,KSP_NORM_NONE));
407         PetscCall(KSPGetPC(mglevels[i]->smoothd,&ipc));
408         PetscCall(PCSetType(ipc,PCSOR));
409         PetscCall(KSPSetTolerances(mglevels[i]->smoothd,PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT, mg->default_smoothd));
410 
411         PetscCall(PetscSNPrintf(tprefix,128,"mg_levels_%d_",(int)i));
412         PetscCall(KSPAppendOptionsPrefix(mglevels[i]->smoothd,tprefix));
413       } else {
414         PetscCall(KSPAppendOptionsPrefix(mglevels[0]->smoothd,"mg_coarse_"));
415 
416         /* coarse solve is (redundant) LU by default; set shifttype NONZERO to avoid annoying zero-pivot in LU preconditioner */
417         PetscCall(KSPSetType(mglevels[0]->smoothd,KSPPREONLY));
418         PetscCall(KSPGetPC(mglevels[0]->smoothd,&ipc));
419         PetscCallMPI(MPI_Comm_size(comm,&size));
420         if (size > 1) {
421           PetscCall(PCSetType(ipc,PCREDUNDANT));
422         } else {
423           PetscCall(PCSetType(ipc,PCLU));
424         }
425         PetscCall(PCFactorSetShiftType(ipc,MAT_SHIFT_INBLOCKS));
426       }
427       PetscCall(PetscLogObjectParent((PetscObject)pc,(PetscObject)mglevels[i]->smoothd));
428     }
429     mglevels[i]->smoothu = mglevels[i]->smoothd;
430     mg->rtol             = 0.0;
431     mg->abstol           = 0.0;
432     mg->dtol             = 0.0;
433     mg->ttol             = 0.0;
434     mg->cyclesperpcapply = 1;
435   }
436   mg->levels = mglevels;
437   PetscCall(PCMGSetType(pc,mgtype));
438   PetscFunctionReturn(0);
439 }
440 
441 /*@C
442    PCMGSetLevels - Sets the number of levels to use with MG.
443    Must be called before any other MG routine.
444 
445    Logically Collective on PC
446 
447    Input Parameters:
448 +  pc - the preconditioner context
449 .  levels - the number of levels
450 -  comms - optional communicators for each level; this is to allow solving the coarser problems
451            on smaller sets of processes. For processes that are not included in the computation
452            you must pass MPI_COMM_NULL. Use comms = NULL to specify that all processes
453            should participate in each level of problem.
454 
455    Level: intermediate
456 
457    Notes:
458      If the number of levels is one then the multigrid uses the -mg_levels prefix
459      for setting the level options rather than the -mg_coarse prefix.
460 
461      You can free the information in comms after this routine is called.
462 
463      The array of MPI communicators must contain MPI_COMM_NULL for those ranks that at each level
464      are not participating in the coarser solve. For example, with 2 levels and 1 and 2 ranks on
465      the two levels, rank 0 in the original communicator will pass in an array of 2 communicators
466      of size 2 and 1, while rank 1 in the original communicator will pass in array of 2 communicators
467      the first of size 2 and the second of value MPI_COMM_NULL since the rank 1 does not participate
468      in the coarse grid solve.
469 
470      Since each coarser level may have a new MPI_Comm with fewer ranks than the previous, one
471      must take special care in providing the restriction and interpolation operation. We recommend
472      providing these as two step operations; first perform a standard restriction or interpolation on
473      the full number of ranks for that level and then use an MPI call to copy the resulting vector
474      array entries (after calls to VecGetArray()) to the smaller or larger number of ranks, note in both
475      cases the MPI calls must be made on the larger of the two communicators. Traditional MPI send and
476      recieves or MPI_AlltoAllv() could be used to do the reshuffling of the vector entries.
477 
478    Fortran Notes:
479      Use comms = PETSC_NULL_MPI_COMM as the equivalent of NULL in the C interface. Note PETSC_NULL_MPI_COMM
480      is not MPI_COMM_NULL. It is more like PETSC_NULL_INTEGER, PETSC_NULL_REAL etc.
481 
482 .seealso: `PCMGSetType()`, `PCMGGetLevels()`
483 @*/
484 PetscErrorCode PCMGSetLevels(PC pc,PetscInt levels,MPI_Comm *comms)
485 {
486   PetscFunctionBegin;
487   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
488   if (comms) PetscValidPointer(comms,3);
489   PetscTryMethod(pc,"PCMGSetLevels_C",(PC,PetscInt,MPI_Comm*),(pc,levels,comms));
490   PetscFunctionReturn(0);
491 }
492 
493 PetscErrorCode PCDestroy_MG(PC pc)
494 {
495   PC_MG          *mg        = (PC_MG*)pc->data;
496   PC_MG_Levels   **mglevels = mg->levels;
497   PetscInt       i,n;
498 
499   PetscFunctionBegin;
500   PetscCall(PCReset_MG(pc));
501   if (mglevels) {
502     n = mglevels[0]->levels;
503     for (i=0; i<n; i++) {
504       if (mglevels[i]->smoothd != mglevels[i]->smoothu) {
505         PetscCall(KSPDestroy(&mglevels[i]->smoothd));
506       }
507       PetscCall(KSPDestroy(&mglevels[i]->smoothu));
508       PetscCall(KSPDestroy(&mglevels[i]->cr));
509       PetscCall(PetscFree(mglevels[i]));
510     }
511     PetscCall(PetscFree(mg->levels));
512   }
513   PetscCall(PetscFree(pc->data));
514   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCGetInterpolations_C",NULL));
515   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCGetCoarseOperators_C",NULL));
516   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCMGSetGalerkin_C",NULL));
517   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCMGGetLevels_C",NULL));
518   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCMGSetLevels_C",NULL));
519   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCGetInterpolations_C",NULL));
520   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCGetCoarseOperators_C",NULL));
521   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCMGSetAdaptInterpolation_C",NULL));
522   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCMGGetAdaptInterpolation_C",NULL));
523   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCMGSetAdaptCR_C",NULL));
524   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCMGGetAdaptCR_C",NULL));
525   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCMGSetAdaptCoarseSpaceType_C",NULL));
526   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCMGGetAdaptCoarseSpaceType_C",NULL));
527   PetscFunctionReturn(0);
528 }
529 
530 /*
531    PCApply_MG - Runs either an additive, multiplicative, Kaskadic
532              or full cycle of multigrid.
533 
534   Note:
535   A simple wrapper which calls PCMGMCycle(),PCMGACycle(), or PCMGFCycle().
536 */
537 static PetscErrorCode PCApply_MG_Internal(PC pc,Vec b,Vec x,Mat B,Mat X,PetscBool transpose)
538 {
539   PC_MG          *mg        = (PC_MG*)pc->data;
540   PC_MG_Levels   **mglevels = mg->levels;
541   PC             tpc;
542   PetscInt       levels = mglevels[0]->levels,i;
543   PetscBool      changeu,changed,matapp;
544 
545   PetscFunctionBegin;
546   matapp = (PetscBool)(B && X);
547   if (mg->stageApply) PetscCall(PetscLogStagePush(mg->stageApply));
548   /* When the DM is supplying the matrix then it will not exist until here */
549   for (i=0; i<levels; i++) {
550     if (!mglevels[i]->A) {
551       PetscCall(KSPGetOperators(mglevels[i]->smoothu,&mglevels[i]->A,NULL));
552       PetscCall(PetscObjectReference((PetscObject)mglevels[i]->A));
553     }
554   }
555 
556   PetscCall(KSPGetPC(mglevels[levels-1]->smoothd,&tpc));
557   PetscCall(PCPreSolveChangeRHS(tpc,&changed));
558   PetscCall(KSPGetPC(mglevels[levels-1]->smoothu,&tpc));
559   PetscCall(PCPreSolveChangeRHS(tpc,&changeu));
560   if (!changeu && !changed) {
561     if (matapp) {
562       PetscCall(MatDestroy(&mglevels[levels-1]->B));
563       mglevels[levels-1]->B = B;
564     } else {
565       PetscCall(VecDestroy(&mglevels[levels-1]->b));
566       mglevels[levels-1]->b = b;
567     }
568   } else { /* if the smoother changes the rhs during PreSolve, we cannot use the input vector */
569     if (matapp) {
570       if (mglevels[levels-1]->B) {
571         PetscInt  N1,N2;
572         PetscBool flg;
573 
574         PetscCall(MatGetSize(mglevels[levels-1]->B,NULL,&N1));
575         PetscCall(MatGetSize(B,NULL,&N2));
576         PetscCall(PetscObjectTypeCompare((PetscObject)mglevels[levels-1]->B,((PetscObject)B)->type_name,&flg));
577         if (N1 != N2 || !flg) {
578           PetscCall(MatDestroy(&mglevels[levels-1]->B));
579         }
580       }
581       if (!mglevels[levels-1]->B) {
582         PetscCall(MatDuplicate(B,MAT_COPY_VALUES,&mglevels[levels-1]->B));
583       } else {
584         PetscCall(MatCopy(B,mglevels[levels-1]->B,SAME_NONZERO_PATTERN));
585       }
586     } else {
587       if (!mglevels[levels-1]->b) {
588         Vec *vec;
589 
590         PetscCall(KSPCreateVecs(mglevels[levels-1]->smoothd,1,&vec,0,NULL));
591         mglevels[levels-1]->b = *vec;
592         PetscCall(PetscFree(vec));
593       }
594       PetscCall(VecCopy(b,mglevels[levels-1]->b));
595     }
596   }
597   if (matapp) { mglevels[levels-1]->X = X; }
598   else { mglevels[levels-1]->x = x; }
599 
600   /* If coarser Xs are present, it means we have already block applied the PC at least once
601      Reset operators if sizes/type do no match */
602   if (matapp && levels > 1 && mglevels[levels-2]->X) {
603     PetscInt  Xc,Bc;
604     PetscBool flg;
605 
606     PetscCall(MatGetSize(mglevels[levels-2]->X,NULL,&Xc));
607     PetscCall(MatGetSize(mglevels[levels-1]->B,NULL,&Bc));
608     PetscCall(PetscObjectTypeCompare((PetscObject)mglevels[levels-2]->X,((PetscObject)mglevels[levels-1]->X)->type_name,&flg));
609     if (Xc != Bc || !flg) {
610       PetscCall(MatDestroy(&mglevels[levels-1]->R));
611       for (i=0;i<levels-1;i++) {
612         PetscCall(MatDestroy(&mglevels[i]->R));
613         PetscCall(MatDestroy(&mglevels[i]->B));
614         PetscCall(MatDestroy(&mglevels[i]->X));
615       }
616     }
617   }
618 
619   if (mg->am == PC_MG_MULTIPLICATIVE) {
620     if (matapp) PetscCall(MatZeroEntries(X));
621     else PetscCall(VecZeroEntries(x));
622     for (i=0; i<mg->cyclesperpcapply; i++) {
623       PetscCall(PCMGMCycle_Private(pc,mglevels+levels-1,transpose,matapp,NULL));
624     }
625   } else if (mg->am == PC_MG_ADDITIVE) {
626     PetscCall(PCMGACycle_Private(pc,mglevels,transpose,matapp));
627   } else if (mg->am == PC_MG_KASKADE) {
628     PetscCall(PCMGKCycle_Private(pc,mglevels,transpose,matapp));
629   } else {
630     PetscCall(PCMGFCycle_Private(pc,mglevels,transpose,matapp));
631   }
632   if (mg->stageApply) PetscCall(PetscLogStagePop());
633   if (!changeu && !changed) {
634     if (matapp) { mglevels[levels-1]->B = NULL; }
635     else { mglevels[levels-1]->b = NULL; }
636   }
637   PetscFunctionReturn(0);
638 }
639 
640 static PetscErrorCode PCApply_MG(PC pc,Vec b,Vec x)
641 {
642   PetscFunctionBegin;
643   PetscCall(PCApply_MG_Internal(pc,b,x,NULL,NULL,PETSC_FALSE));
644   PetscFunctionReturn(0);
645 }
646 
647 static PetscErrorCode PCApplyTranspose_MG(PC pc,Vec b,Vec x)
648 {
649   PetscFunctionBegin;
650   PetscCall(PCApply_MG_Internal(pc,b,x,NULL,NULL,PETSC_TRUE));
651   PetscFunctionReturn(0);
652 }
653 
654 static PetscErrorCode PCMatApply_MG(PC pc,Mat b,Mat x)
655 {
656   PetscFunctionBegin;
657   PetscCall(PCApply_MG_Internal(pc,NULL,NULL,b,x,PETSC_FALSE));
658   PetscFunctionReturn(0);
659 }
660 
661 PetscErrorCode PCSetFromOptions_MG(PetscOptionItems *PetscOptionsObject,PC pc)
662 {
663   PetscInt            levels,cycles;
664   PetscBool           flg, flg2;
665   PC_MG               *mg = (PC_MG*)pc->data;
666   PC_MG_Levels        **mglevels;
667   PCMGType            mgtype;
668   PCMGCycleType       mgctype;
669   PCMGGalerkinType    gtype;
670   PCMGCoarseSpaceType coarseSpaceType;
671 
672   PetscFunctionBegin;
673   levels = PetscMax(mg->nlevels,1);
674   PetscOptionsHeadBegin(PetscOptionsObject,"Multigrid options");
675   PetscCall(PetscOptionsInt("-pc_mg_levels","Number of Levels","PCMGSetLevels",levels,&levels,&flg));
676   if (!flg && !mg->levels && pc->dm) {
677     PetscCall(DMGetRefineLevel(pc->dm,&levels));
678     levels++;
679     mg->usedmfornumberoflevels = PETSC_TRUE;
680   }
681   PetscCall(PCMGSetLevels(pc,levels,NULL));
682   mglevels = mg->levels;
683 
684   mgctype = (PCMGCycleType) mglevels[0]->cycles;
685   PetscCall(PetscOptionsEnum("-pc_mg_cycle_type","V cycle or for W-cycle","PCMGSetCycleType",PCMGCycleTypes,(PetscEnum)mgctype,(PetscEnum*)&mgctype,&flg));
686   if (flg) {
687     PetscCall(PCMGSetCycleType(pc,mgctype));
688   }
689   gtype = mg->galerkin;
690   PetscCall(PetscOptionsEnum("-pc_mg_galerkin","Use Galerkin process to compute coarser operators","PCMGSetGalerkin",PCMGGalerkinTypes,(PetscEnum)gtype,(PetscEnum*)&gtype,&flg));
691   if (flg) {
692     PetscCall(PCMGSetGalerkin(pc,gtype));
693   }
694   coarseSpaceType = mg->coarseSpaceType;
695   PetscCall(PetscOptionsEnum("-pc_mg_adapt_interp_coarse_space","Type of adaptive coarse space: none, polynomial, harmonic, eigenvector, generalized_eigenvector, gdsw","PCMGSetAdaptCoarseSpaceType",PCMGCoarseSpaceTypes,(PetscEnum)coarseSpaceType,(PetscEnum*)&coarseSpaceType,&flg));
696   if (flg) PetscCall(PCMGSetAdaptCoarseSpaceType(pc,coarseSpaceType));
697   PetscCall(PetscOptionsInt("-pc_mg_adapt_interp_n","Size of the coarse space for adaptive interpolation","PCMGSetCoarseSpace",mg->Nc,&mg->Nc,&flg));
698   PetscCall(PetscOptionsBool("-pc_mg_mesp_monitor","Monitor the multilevel eigensolver","PCMGSetAdaptInterpolation",PETSC_FALSE,&mg->mespMonitor,&flg));
699   flg2 = PETSC_FALSE;
700   PetscCall(PetscOptionsBool("-pc_mg_adapt_cr","Monitor coarse space quality using Compatible Relaxation (CR)","PCMGSetAdaptCR",PETSC_FALSE,&flg2,&flg));
701   if (flg) PetscCall(PCMGSetAdaptCR(pc, flg2));
702   flg = PETSC_FALSE;
703   PetscCall(PetscOptionsBool("-pc_mg_distinct_smoothup","Create separate smoothup KSP and append the prefix _up","PCMGSetDistinctSmoothUp",PETSC_FALSE,&flg,NULL));
704   if (flg) {
705     PetscCall(PCMGSetDistinctSmoothUp(pc));
706   }
707   mgtype = mg->am;
708   PetscCall(PetscOptionsEnum("-pc_mg_type","Multigrid type","PCMGSetType",PCMGTypes,(PetscEnum)mgtype,(PetscEnum*)&mgtype,&flg));
709   if (flg) {
710     PetscCall(PCMGSetType(pc,mgtype));
711   }
712   if (mg->am == PC_MG_MULTIPLICATIVE) {
713     PetscCall(PetscOptionsInt("-pc_mg_multiplicative_cycles","Number of cycles for each preconditioner step","PCMGMultiplicativeSetCycles",mg->cyclesperpcapply,&cycles,&flg));
714     if (flg) {
715       PetscCall(PCMGMultiplicativeSetCycles(pc,cycles));
716     }
717   }
718   flg  = PETSC_FALSE;
719   PetscCall(PetscOptionsBool("-pc_mg_log","Log times for each multigrid level","None",flg,&flg,NULL));
720   if (flg) {
721     PetscInt i;
722     char     eventname[128];
723 
724     levels = mglevels[0]->levels;
725     for (i=0; i<levels; i++) {
726       sprintf(eventname,"MGSetup Level %d",(int)i);
727       PetscCall(PetscLogEventRegister(eventname,((PetscObject)pc)->classid,&mglevels[i]->eventsmoothsetup));
728       sprintf(eventname,"MGSmooth Level %d",(int)i);
729       PetscCall(PetscLogEventRegister(eventname,((PetscObject)pc)->classid,&mglevels[i]->eventsmoothsolve));
730       if (i) {
731         sprintf(eventname,"MGResid Level %d",(int)i);
732         PetscCall(PetscLogEventRegister(eventname,((PetscObject)pc)->classid,&mglevels[i]->eventresidual));
733         sprintf(eventname,"MGInterp Level %d",(int)i);
734         PetscCall(PetscLogEventRegister(eventname,((PetscObject)pc)->classid,&mglevels[i]->eventinterprestrict));
735       }
736     }
737 
738 #if defined(PETSC_USE_LOG)
739     {
740       const char    *sname = "MG Apply";
741       PetscStageLog stageLog;
742       PetscInt      st;
743 
744       PetscCall(PetscLogGetStageLog(&stageLog));
745       for (st = 0; st < stageLog->numStages; ++st) {
746         PetscBool same;
747 
748         PetscCall(PetscStrcmp(stageLog->stageInfo[st].name, sname, &same));
749         if (same) mg->stageApply = st;
750       }
751       if (!mg->stageApply) {
752         PetscCall(PetscLogStageRegister(sname, &mg->stageApply));
753       }
754     }
755 #endif
756   }
757   PetscOptionsHeadEnd();
758   /* Check option consistency */
759   PetscCall(PCMGGetGalerkin(pc, &gtype));
760   PetscCall(PCMGGetAdaptInterpolation(pc, &flg));
761   PetscCheck(!flg || !(gtype >= PC_MG_GALERKIN_NONE),PetscObjectComm((PetscObject) pc), PETSC_ERR_ARG_INCOMP, "Must use Galerkin coarse operators when adapting the interpolator");
762   PetscFunctionReturn(0);
763 }
764 
765 const char *const PCMGTypes[] = {"MULTIPLICATIVE","ADDITIVE","FULL","KASKADE","PCMGType","PC_MG",NULL};
766 const char *const PCMGCycleTypes[] = {"invalid","v","w","PCMGCycleType","PC_MG_CYCLE",NULL};
767 const char *const PCMGGalerkinTypes[] = {"both","pmat","mat","none","external","PCMGGalerkinType","PC_MG_GALERKIN",NULL};
768 const char *const PCMGCoarseSpaceTypes[] = {"none","polynomial","harmonic","eigenvector","generalized_eigenvector","gdsw","PCMGCoarseSpaceType","PCMG_ADAPT_NONE",NULL};
769 
770 #include <petscdraw.h>
771 PetscErrorCode PCView_MG(PC pc,PetscViewer viewer)
772 {
773   PC_MG          *mg        = (PC_MG*)pc->data;
774   PC_MG_Levels   **mglevels = mg->levels;
775   PetscInt       levels = mglevels ? mglevels[0]->levels : 0,i;
776   PetscBool      iascii,isbinary,isdraw;
777 
778   PetscFunctionBegin;
779   PetscCall(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii));
780   PetscCall(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERBINARY,&isbinary));
781   PetscCall(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERDRAW,&isdraw));
782   if (iascii) {
783     const char *cyclename = levels ? (mglevels[0]->cycles == PC_MG_CYCLE_V ? "v" : "w") : "unknown";
784     PetscCall(PetscViewerASCIIPrintf(viewer,"  type is %s, levels=%" PetscInt_FMT " cycles=%s\n", PCMGTypes[mg->am],levels,cyclename));
785     if (mg->am == PC_MG_MULTIPLICATIVE) {
786       PetscCall(PetscViewerASCIIPrintf(viewer,"    Cycles per PCApply=%" PetscInt_FMT "\n",mg->cyclesperpcapply));
787     }
788     if (mg->galerkin == PC_MG_GALERKIN_BOTH) {
789       PetscCall(PetscViewerASCIIPrintf(viewer,"    Using Galerkin computed coarse grid matrices\n"));
790     } else if (mg->galerkin == PC_MG_GALERKIN_PMAT) {
791       PetscCall(PetscViewerASCIIPrintf(viewer,"    Using Galerkin computed coarse grid matrices for pmat\n"));
792     } else if (mg->galerkin == PC_MG_GALERKIN_MAT) {
793       PetscCall(PetscViewerASCIIPrintf(viewer,"    Using Galerkin computed coarse grid matrices for mat\n"));
794     } else if (mg->galerkin == PC_MG_GALERKIN_EXTERNAL) {
795       PetscCall(PetscViewerASCIIPrintf(viewer,"    Using externally compute Galerkin coarse grid matrices\n"));
796     } else {
797       PetscCall(PetscViewerASCIIPrintf(viewer,"    Not using Galerkin computed coarse grid matrices\n"));
798     }
799     if (mg->view) {
800       PetscCall((*mg->view)(pc,viewer));
801     }
802     for (i=0; i<levels; i++) {
803       if (i) {
804         PetscCall(PetscViewerASCIIPrintf(viewer,"Down solver (pre-smoother) on level %" PetscInt_FMT " -------------------------------\n",i));
805       } else {
806         PetscCall(PetscViewerASCIIPrintf(viewer,"Coarse grid solver -- level %" PetscInt_FMT " -------------------------------\n",i));
807       }
808       PetscCall(PetscViewerASCIIPushTab(viewer));
809       PetscCall(KSPView(mglevels[i]->smoothd,viewer));
810       PetscCall(PetscViewerASCIIPopTab(viewer));
811       if (i && mglevels[i]->smoothd == mglevels[i]->smoothu) {
812         PetscCall(PetscViewerASCIIPrintf(viewer,"Up solver (post-smoother) same as down solver (pre-smoother)\n"));
813       } else if (i) {
814         PetscCall(PetscViewerASCIIPrintf(viewer,"Up solver (post-smoother) on level %" PetscInt_FMT " -------------------------------\n",i));
815         PetscCall(PetscViewerASCIIPushTab(viewer));
816         PetscCall(KSPView(mglevels[i]->smoothu,viewer));
817         PetscCall(PetscViewerASCIIPopTab(viewer));
818       }
819       if (i && mglevels[i]->cr) {
820         PetscCall(PetscViewerASCIIPrintf(viewer,"CR solver on level %" PetscInt_FMT " -------------------------------\n",i));
821         PetscCall(PetscViewerASCIIPushTab(viewer));
822         PetscCall(KSPView(mglevels[i]->cr,viewer));
823         PetscCall(PetscViewerASCIIPopTab(viewer));
824       }
825     }
826   } else if (isbinary) {
827     for (i=levels-1; i>=0; i--) {
828       PetscCall(KSPView(mglevels[i]->smoothd,viewer));
829       if (i && mglevels[i]->smoothd != mglevels[i]->smoothu) {
830         PetscCall(KSPView(mglevels[i]->smoothu,viewer));
831       }
832     }
833   } else if (isdraw) {
834     PetscDraw draw;
835     PetscReal x,w,y,bottom,th;
836     PetscCall(PetscViewerDrawGetDraw(viewer,0,&draw));
837     PetscCall(PetscDrawGetCurrentPoint(draw,&x,&y));
838     PetscCall(PetscDrawStringGetSize(draw,NULL,&th));
839     bottom = y - th;
840     for (i=levels-1; i>=0; i--) {
841       if (!mglevels[i]->smoothu || (mglevels[i]->smoothu == mglevels[i]->smoothd)) {
842         PetscCall(PetscDrawPushCurrentPoint(draw,x,bottom));
843         PetscCall(KSPView(mglevels[i]->smoothd,viewer));
844         PetscCall(PetscDrawPopCurrentPoint(draw));
845       } else {
846         w    = 0.5*PetscMin(1.0-x,x);
847         PetscCall(PetscDrawPushCurrentPoint(draw,x+w,bottom));
848         PetscCall(KSPView(mglevels[i]->smoothd,viewer));
849         PetscCall(PetscDrawPopCurrentPoint(draw));
850         PetscCall(PetscDrawPushCurrentPoint(draw,x-w,bottom));
851         PetscCall(KSPView(mglevels[i]->smoothu,viewer));
852         PetscCall(PetscDrawPopCurrentPoint(draw));
853       }
854       PetscCall(PetscDrawGetBoundingBox(draw,NULL,&bottom,NULL,NULL));
855       bottom -= th;
856     }
857   }
858   PetscFunctionReturn(0);
859 }
860 
861 #include <petsc/private/kspimpl.h>
862 
863 /*
864     Calls setup for the KSP on each level
865 */
866 PetscErrorCode PCSetUp_MG(PC pc)
867 {
868   PC_MG        *mg        = (PC_MG*)pc->data;
869   PC_MG_Levels **mglevels = mg->levels;
870   PetscInt     i,n;
871   PC           cpc;
872   PetscBool    dump = PETSC_FALSE,opsset,use_amat,missinginterpolate = PETSC_FALSE;
873   Mat          dA,dB;
874   Vec          tvec;
875   DM           *dms;
876   PetscViewer  viewer = NULL;
877   PetscBool    dAeqdB = PETSC_FALSE, needRestricts = PETSC_FALSE, doCR = PETSC_FALSE;
878   PetscBool    adaptInterpolation = mg->adaptInterpolation;
879 
880   PetscFunctionBegin;
881   PetscCheck(mglevels,PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONGSTATE,"Must set MG levels with PCMGSetLevels() before setting up");
882   n = mglevels[0]->levels;
883   /* FIX: Move this to PCSetFromOptions_MG? */
884   if (mg->usedmfornumberoflevels) {
885     PetscInt levels;
886     PetscCall(DMGetRefineLevel(pc->dm,&levels));
887     levels++;
888     if (levels > n) { /* the problem is now being solved on a finer grid */
889       PetscCall(PCMGSetLevels(pc,levels,NULL));
890       n        = levels;
891       PetscCall(PCSetFromOptions(pc)); /* it is bad to call this here, but otherwise will never be called for the new hierarchy */
892       mglevels = mg->levels;
893     }
894   }
895   PetscCall(KSPGetPC(mglevels[0]->smoothd,&cpc));
896 
897   /* If user did not provide fine grid operators OR operator was not updated since last global KSPSetOperators() */
898   /* so use those from global PC */
899   /* Is this what we always want? What if user wants to keep old one? */
900   PetscCall(KSPGetOperatorsSet(mglevels[n-1]->smoothd,NULL,&opsset));
901   if (opsset) {
902     Mat mmat;
903     PetscCall(KSPGetOperators(mglevels[n-1]->smoothd,NULL,&mmat));
904     if (mmat == pc->pmat) opsset = PETSC_FALSE;
905   }
906 
907   /* Create CR solvers */
908   PetscCall(PCMGGetAdaptCR(pc, &doCR));
909   if (doCR) {
910     const char *prefix;
911 
912     PetscCall(PCGetOptionsPrefix(pc, &prefix));
913     for (i = 1; i < n; ++i) {
914       PC   ipc, cr;
915       char crprefix[128];
916 
917       PetscCall(KSPCreate(PetscObjectComm((PetscObject) pc), &mglevels[i]->cr));
918       PetscCall(KSPSetErrorIfNotConverged(mglevels[i]->cr, PETSC_FALSE));
919       PetscCall(PetscObjectIncrementTabLevel((PetscObject) mglevels[i]->cr, (PetscObject) pc, n-i));
920       PetscCall(KSPSetOptionsPrefix(mglevels[i]->cr, prefix));
921       PetscCall(PetscObjectComposedDataSetInt((PetscObject) mglevels[i]->cr, PetscMGLevelId, mglevels[i]->level));
922       PetscCall(KSPSetType(mglevels[i]->cr, KSPCHEBYSHEV));
923       PetscCall(KSPSetConvergenceTest(mglevels[i]->cr, KSPConvergedSkip, NULL, NULL));
924       PetscCall(KSPSetNormType(mglevels[i]->cr, KSP_NORM_PRECONDITIONED));
925       PetscCall(KSPGetPC(mglevels[i]->cr, &ipc));
926 
927       PetscCall(PCSetType(ipc, PCCOMPOSITE));
928       PetscCall(PCCompositeSetType(ipc, PC_COMPOSITE_MULTIPLICATIVE));
929       PetscCall(PCCompositeAddPCType(ipc, PCSOR));
930       PetscCall(CreateCR_Private(pc, i, &cr));
931       PetscCall(PCCompositeAddPC(ipc, cr));
932       PetscCall(PCDestroy(&cr));
933 
934       PetscCall(KSPSetTolerances(mglevels[i]->cr, PETSC_DEFAULT, PETSC_DEFAULT, PETSC_DEFAULT, mg->default_smoothd));
935       PetscCall(KSPSetInitialGuessNonzero(mglevels[i]->cr, PETSC_TRUE));
936       PetscCall(PetscSNPrintf(crprefix, 128, "mg_levels_%d_cr_", (int) i));
937       PetscCall(KSPAppendOptionsPrefix(mglevels[i]->cr, crprefix));
938       PetscCall(PetscLogObjectParent((PetscObject) pc, (PetscObject) mglevels[i]->cr));
939     }
940   }
941 
942   if (!opsset) {
943     PetscCall(PCGetUseAmat(pc,&use_amat));
944     if (use_amat) {
945       PetscCall(PetscInfo(pc,"Using outer operators to define finest grid operator \n  because PCMGGetSmoother(pc,nlevels-1,&ksp);KSPSetOperators(ksp,...); was not called.\n"));
946       PetscCall(KSPSetOperators(mglevels[n-1]->smoothd,pc->mat,pc->pmat));
947     } else {
948       PetscCall(PetscInfo(pc,"Using matrix (pmat) operators to define finest grid operator \n  because PCMGGetSmoother(pc,nlevels-1,&ksp);KSPSetOperators(ksp,...); was not called.\n"));
949       PetscCall(KSPSetOperators(mglevels[n-1]->smoothd,pc->pmat,pc->pmat));
950     }
951   }
952 
953   for (i=n-1; i>0; i--) {
954     if (!(mglevels[i]->interpolate || mglevels[i]->restrct)) {
955       missinginterpolate = PETSC_TRUE;
956       break;
957     }
958   }
959 
960   PetscCall(KSPGetOperators(mglevels[n-1]->smoothd,&dA,&dB));
961   if (dA == dB) dAeqdB = PETSC_TRUE;
962   if (mg->galerkin == PC_MG_GALERKIN_NONE || ((mg->galerkin == PC_MG_GALERKIN_PMAT || mg->galerkin == PC_MG_GALERKIN_MAT) && !dAeqdB)) {
963     needRestricts = PETSC_TRUE;  /* user must compute either mat, pmat, or both so must restrict x to coarser levels */
964   }
965 
966   if (pc->dm && !pc->setupcalled) {
967     /* finest smoother also gets DM but it is not active, independent of whether galerkin==PC_MG_GALERKIN_EXTERNAL */
968     PetscCall(KSPSetDM(mglevels[n-1]->smoothd,pc->dm));
969     PetscCall(KSPSetDMActive(mglevels[n-1]->smoothd,PETSC_FALSE));
970     if (mglevels[n-1]->smoothd != mglevels[n-1]->smoothu) {
971       PetscCall(KSPSetDM(mglevels[n-1]->smoothu,pc->dm));
972       PetscCall(KSPSetDMActive(mglevels[n-1]->smoothu,PETSC_FALSE));
973     }
974     if (mglevels[n-1]->cr) {
975       PetscCall(KSPSetDM(mglevels[n-1]->cr,pc->dm));
976       PetscCall(KSPSetDMActive(mglevels[n-1]->cr,PETSC_FALSE));
977     }
978   }
979 
980   /*
981    Skipping if user has provided all interpolation/restriction needed (since DM might not be able to produce them (when coming from SNES/TS)
982    Skipping for externally managed hierarchy (such as ML and GAMG). Cleaner logic here would be great. Wrap ML/GAMG as DMs?
983   */
984   if (missinginterpolate && mg->galerkin != PC_MG_GALERKIN_EXTERNAL && !pc->setupcalled) {
985     /* first see if we can compute a coarse space */
986     if (mg->coarseSpaceType == PCMG_ADAPT_GDSW) {
987       for (i=n-2; i>-1; i--) {
988         if (!mglevels[i+1]->restrct && !mglevels[i+1]->interpolate) {
989           PetscCall(PCMGComputeCoarseSpace_Internal(pc, i+1, mg->coarseSpaceType, mg->Nc, NULL, &mglevels[i+1]->coarseSpace));
990           PetscCall(PCMGSetInterpolation(pc,i+1,mglevels[i+1]->coarseSpace));
991         }
992       }
993     } else { /* construct the interpolation from the DMs */
994       Mat p;
995       Vec rscale;
996       PetscCall(PetscMalloc1(n,&dms));
997       dms[n-1] = pc->dm;
998       /* Separately create them so we do not get DMKSP interference between levels */
999       for (i=n-2; i>-1; i--) PetscCall(DMCoarsen(dms[i+1],MPI_COMM_NULL,&dms[i]));
1000       for (i=n-2; i>-1; i--) {
1001         DMKSP     kdm;
1002         PetscBool dmhasrestrict, dmhasinject;
1003         PetscCall(KSPSetDM(mglevels[i]->smoothd,dms[i]));
1004         if (!needRestricts) PetscCall(KSPSetDMActive(mglevels[i]->smoothd,PETSC_FALSE));
1005         if (mglevels[i]->smoothd != mglevels[i]->smoothu) {
1006           PetscCall(KSPSetDM(mglevels[i]->smoothu,dms[i]));
1007           if (!needRestricts) PetscCall(KSPSetDMActive(mglevels[i]->smoothu,PETSC_FALSE));
1008         }
1009         if (mglevels[i]->cr) {
1010           PetscCall(KSPSetDM(mglevels[i]->cr,dms[i]));
1011           if (!needRestricts) PetscCall(KSPSetDMActive(mglevels[i]->cr,PETSC_FALSE));
1012         }
1013         PetscCall(DMGetDMKSPWrite(dms[i],&kdm));
1014         /* Ugly hack so that the next KSPSetUp() will use the RHS that we set. A better fix is to change dmActive to take
1015          * a bitwise OR of computing the matrix, RHS, and initial iterate. */
1016         kdm->ops->computerhs = NULL;
1017         kdm->rhsctx          = NULL;
1018         if (!mglevels[i+1]->interpolate) {
1019           PetscCall(DMCreateInterpolation(dms[i],dms[i+1],&p,&rscale));
1020           PetscCall(PCMGSetInterpolation(pc,i+1,p));
1021           if (rscale) PetscCall(PCMGSetRScale(pc,i+1,rscale));
1022           PetscCall(VecDestroy(&rscale));
1023           PetscCall(MatDestroy(&p));
1024         }
1025         PetscCall(DMHasCreateRestriction(dms[i],&dmhasrestrict));
1026         if (dmhasrestrict && !mglevels[i+1]->restrct) {
1027           PetscCall(DMCreateRestriction(dms[i],dms[i+1],&p));
1028           PetscCall(PCMGSetRestriction(pc,i+1,p));
1029           PetscCall(MatDestroy(&p));
1030         }
1031         PetscCall(DMHasCreateInjection(dms[i],&dmhasinject));
1032         if (dmhasinject && !mglevels[i+1]->inject) {
1033           PetscCall(DMCreateInjection(dms[i],dms[i+1],&p));
1034           PetscCall(PCMGSetInjection(pc,i+1,p));
1035           PetscCall(MatDestroy(&p));
1036         }
1037       }
1038 
1039       for (i=n-2; i>-1; i--) PetscCall(DMDestroy(&dms[i]));
1040       PetscCall(PetscFree(dms));
1041     }
1042   }
1043 
1044   if (mg->galerkin < PC_MG_GALERKIN_NONE) {
1045     Mat       A,B;
1046     PetscBool doA = PETSC_FALSE,doB = PETSC_FALSE;
1047     MatReuse  reuse = MAT_INITIAL_MATRIX;
1048 
1049     if (mg->galerkin == PC_MG_GALERKIN_PMAT || mg->galerkin == PC_MG_GALERKIN_BOTH) doB = PETSC_TRUE;
1050     if (mg->galerkin == PC_MG_GALERKIN_MAT || (mg->galerkin == PC_MG_GALERKIN_BOTH && dA != dB)) doA = PETSC_TRUE;
1051     if (pc->setupcalled) reuse = MAT_REUSE_MATRIX;
1052     for (i=n-2; i>-1; i--) {
1053       PetscCheck(mglevels[i+1]->restrct || mglevels[i+1]->interpolate,PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONGSTATE,"Must provide interpolation or restriction for each MG level except level 0");
1054       if (!mglevels[i+1]->interpolate) {
1055         PetscCall(PCMGSetInterpolation(pc,i+1,mglevels[i+1]->restrct));
1056       }
1057       if (!mglevels[i+1]->restrct) {
1058         PetscCall(PCMGSetRestriction(pc,i+1,mglevels[i+1]->interpolate));
1059       }
1060       if (reuse == MAT_REUSE_MATRIX) {
1061         PetscCall(KSPGetOperators(mglevels[i]->smoothd,&A,&B));
1062       }
1063       if (doA) {
1064         PetscCall(MatGalerkin(mglevels[i+1]->restrct,dA,mglevels[i+1]->interpolate,reuse,1.0,&A));
1065       }
1066       if (doB) {
1067         PetscCall(MatGalerkin(mglevels[i+1]->restrct,dB,mglevels[i+1]->interpolate,reuse,1.0,&B));
1068       }
1069       /* the management of the PetscObjectReference() and PetscObjecDereference() below is rather delicate */
1070       if (!doA && dAeqdB) {
1071         if (reuse == MAT_INITIAL_MATRIX) PetscCall(PetscObjectReference((PetscObject)B));
1072         A = B;
1073       } else if (!doA && reuse == MAT_INITIAL_MATRIX) {
1074         PetscCall(KSPGetOperators(mglevels[i]->smoothd,&A,NULL));
1075         PetscCall(PetscObjectReference((PetscObject)A));
1076       }
1077       if (!doB && dAeqdB) {
1078         if (reuse == MAT_INITIAL_MATRIX) PetscCall(PetscObjectReference((PetscObject)A));
1079         B = A;
1080       } else if (!doB && reuse == MAT_INITIAL_MATRIX) {
1081         PetscCall(KSPGetOperators(mglevels[i]->smoothd,NULL,&B));
1082         PetscCall(PetscObjectReference((PetscObject)B));
1083       }
1084       if (reuse == MAT_INITIAL_MATRIX) {
1085         PetscCall(KSPSetOperators(mglevels[i]->smoothd,A,B));
1086         PetscCall(PetscObjectDereference((PetscObject)A));
1087         PetscCall(PetscObjectDereference((PetscObject)B));
1088       }
1089       dA = A;
1090       dB = B;
1091     }
1092   }
1093 
1094   /* Adapt interpolation matrices */
1095   if (adaptInterpolation) {
1096     for (i = 0; i < n; ++i) {
1097       if (!mglevels[i]->coarseSpace) {
1098         PetscCall(PCMGComputeCoarseSpace_Internal(pc, i, mg->coarseSpaceType, mg->Nc, !i ? NULL : mglevels[i-1]->coarseSpace, &mglevels[i]->coarseSpace));
1099       }
1100       if (i) PetscCall(PCMGAdaptInterpolator_Internal(pc, i, mglevels[i-1]->smoothu, mglevels[i]->smoothu, mglevels[i-1]->coarseSpace, mglevels[i]->coarseSpace));
1101     }
1102     for (i = n-2; i > -1; --i) {
1103       PetscCall(PCMGRecomputeLevelOperators_Internal(pc, i));
1104     }
1105   }
1106 
1107   if (needRestricts && pc->dm) {
1108     for (i=n-2; i>=0; i--) {
1109       DM  dmfine,dmcoarse;
1110       Mat Restrict,Inject;
1111       Vec rscale;
1112       PetscCall(KSPGetDM(mglevels[i+1]->smoothd,&dmfine));
1113       PetscCall(KSPGetDM(mglevels[i]->smoothd,&dmcoarse));
1114       PetscCall(PCMGGetRestriction(pc,i+1,&Restrict));
1115       PetscCall(PCMGGetRScale(pc,i+1,&rscale));
1116       PetscCall(PCMGGetInjection(pc,i+1,&Inject));
1117       PetscCall(DMRestrict(dmfine,Restrict,rscale,Inject,dmcoarse));
1118     }
1119   }
1120 
1121   if (!pc->setupcalled) {
1122     for (i=0; i<n; i++) {
1123       PetscCall(KSPSetFromOptions(mglevels[i]->smoothd));
1124     }
1125     for (i=1; i<n; i++) {
1126       if (mglevels[i]->smoothu && (mglevels[i]->smoothu != mglevels[i]->smoothd)) {
1127         PetscCall(KSPSetFromOptions(mglevels[i]->smoothu));
1128       }
1129       if (mglevels[i]->cr) {
1130         PetscCall(KSPSetFromOptions(mglevels[i]->cr));
1131       }
1132     }
1133     /* insure that if either interpolation or restriction is set the other other one is set */
1134     for (i=1; i<n; i++) {
1135       PetscCall(PCMGGetInterpolation(pc,i,NULL));
1136       PetscCall(PCMGGetRestriction(pc,i,NULL));
1137     }
1138     for (i=0; i<n-1; i++) {
1139       if (!mglevels[i]->b) {
1140         Vec *vec;
1141         PetscCall(KSPCreateVecs(mglevels[i]->smoothd,1,&vec,0,NULL));
1142         PetscCall(PCMGSetRhs(pc,i,*vec));
1143         PetscCall(VecDestroy(vec));
1144         PetscCall(PetscFree(vec));
1145       }
1146       if (!mglevels[i]->r && i) {
1147         PetscCall(VecDuplicate(mglevels[i]->b,&tvec));
1148         PetscCall(PCMGSetR(pc,i,tvec));
1149         PetscCall(VecDestroy(&tvec));
1150       }
1151       if (!mglevels[i]->x) {
1152         PetscCall(VecDuplicate(mglevels[i]->b,&tvec));
1153         PetscCall(PCMGSetX(pc,i,tvec));
1154         PetscCall(VecDestroy(&tvec));
1155       }
1156       if (doCR) {
1157         PetscCall(VecDuplicate(mglevels[i]->b,&mglevels[i]->crx));
1158         PetscCall(VecDuplicate(mglevels[i]->b,&mglevels[i]->crb));
1159         PetscCall(VecZeroEntries(mglevels[i]->crb));
1160       }
1161     }
1162     if (n != 1 && !mglevels[n-1]->r) {
1163       /* PCMGSetR() on the finest level if user did not supply it */
1164       Vec *vec;
1165       PetscCall(KSPCreateVecs(mglevels[n-1]->smoothd,1,&vec,0,NULL));
1166       PetscCall(PCMGSetR(pc,n-1,*vec));
1167       PetscCall(VecDestroy(vec));
1168       PetscCall(PetscFree(vec));
1169     }
1170     if (doCR) {
1171       PetscCall(VecDuplicate(mglevels[n-1]->r, &mglevels[n-1]->crx));
1172       PetscCall(VecDuplicate(mglevels[n-1]->r, &mglevels[n-1]->crb));
1173       PetscCall(VecZeroEntries(mglevels[n-1]->crb));
1174     }
1175   }
1176 
1177   if (pc->dm) {
1178     /* need to tell all the coarser levels to rebuild the matrix using the DM for that level */
1179     for (i=0; i<n-1; i++) {
1180       if (mglevels[i]->smoothd->setupstage != KSP_SETUP_NEW) mglevels[i]->smoothd->setupstage = KSP_SETUP_NEWMATRIX;
1181     }
1182   }
1183   // We got here (PCSetUp_MG) because the matrix has changed, which means the smoother needs to be set up again (e.g.,
1184   // new diagonal for Jacobi). Setting it here allows it to be logged under PCSetUp rather than deep inside a PCApply.
1185   if (mglevels[n-1]->smoothd->setupstage != KSP_SETUP_NEW) mglevels[n-1]->smoothd->setupstage = KSP_SETUP_NEWMATRIX;
1186 
1187   for (i=1; i<n; i++) {
1188     if (mglevels[i]->smoothu == mglevels[i]->smoothd || mg->am == PC_MG_FULL || mg->am == PC_MG_KASKADE || mg->cyclesperpcapply > 1) {
1189       /* if doing only down then initial guess is zero */
1190       PetscCall(KSPSetInitialGuessNonzero(mglevels[i]->smoothd,PETSC_TRUE));
1191     }
1192     if (mglevels[i]->cr) PetscCall(KSPSetInitialGuessNonzero(mglevels[i]->cr,PETSC_TRUE));
1193     if (mglevels[i]->eventsmoothsetup) PetscCall(PetscLogEventBegin(mglevels[i]->eventsmoothsetup,0,0,0,0));
1194     PetscCall(KSPSetUp(mglevels[i]->smoothd));
1195     if (mglevels[i]->smoothd->reason == KSP_DIVERGED_PC_FAILED) {
1196       pc->failedreason = PC_SUBPC_ERROR;
1197     }
1198     if (mglevels[i]->eventsmoothsetup) PetscCall(PetscLogEventEnd(mglevels[i]->eventsmoothsetup,0,0,0,0));
1199     if (!mglevels[i]->residual) {
1200       Mat mat;
1201       PetscCall(KSPGetOperators(mglevels[i]->smoothd,&mat,NULL));
1202       PetscCall(PCMGSetResidual(pc,i,PCMGResidualDefault,mat));
1203     }
1204     if (!mglevels[i]->residualtranspose) {
1205       Mat mat;
1206       PetscCall(KSPGetOperators(mglevels[i]->smoothd,&mat,NULL));
1207       PetscCall(PCMGSetResidualTranspose(pc,i,PCMGResidualTransposeDefault,mat));
1208     }
1209   }
1210   for (i=1; i<n; i++) {
1211     if (mglevels[i]->smoothu && mglevels[i]->smoothu != mglevels[i]->smoothd) {
1212       Mat downmat,downpmat;
1213 
1214       /* check if operators have been set for up, if not use down operators to set them */
1215       PetscCall(KSPGetOperatorsSet(mglevels[i]->smoothu,&opsset,NULL));
1216       if (!opsset) {
1217         PetscCall(KSPGetOperators(mglevels[i]->smoothd,&downmat,&downpmat));
1218         PetscCall(KSPSetOperators(mglevels[i]->smoothu,downmat,downpmat));
1219       }
1220 
1221       PetscCall(KSPSetInitialGuessNonzero(mglevels[i]->smoothu,PETSC_TRUE));
1222       if (mglevels[i]->eventsmoothsetup) PetscCall(PetscLogEventBegin(mglevels[i]->eventsmoothsetup,0,0,0,0));
1223       PetscCall(KSPSetUp(mglevels[i]->smoothu));
1224       if (mglevels[i]->smoothu->reason == KSP_DIVERGED_PC_FAILED) {
1225         pc->failedreason = PC_SUBPC_ERROR;
1226       }
1227       if (mglevels[i]->eventsmoothsetup) PetscCall(PetscLogEventEnd(mglevels[i]->eventsmoothsetup,0,0,0,0));
1228     }
1229     if (mglevels[i]->cr) {
1230       Mat downmat,downpmat;
1231 
1232       /* check if operators have been set for up, if not use down operators to set them */
1233       PetscCall(KSPGetOperatorsSet(mglevels[i]->cr,&opsset,NULL));
1234       if (!opsset) {
1235         PetscCall(KSPGetOperators(mglevels[i]->smoothd,&downmat,&downpmat));
1236         PetscCall(KSPSetOperators(mglevels[i]->cr,downmat,downpmat));
1237       }
1238 
1239       PetscCall(KSPSetInitialGuessNonzero(mglevels[i]->cr,PETSC_TRUE));
1240       if (mglevels[i]->eventsmoothsetup) PetscCall(PetscLogEventBegin(mglevels[i]->eventsmoothsetup,0,0,0,0));
1241       PetscCall(KSPSetUp(mglevels[i]->cr));
1242       if (mglevels[i]->cr->reason == KSP_DIVERGED_PC_FAILED) {
1243         pc->failedreason = PC_SUBPC_ERROR;
1244       }
1245       if (mglevels[i]->eventsmoothsetup) PetscCall(PetscLogEventEnd(mglevels[i]->eventsmoothsetup,0,0,0,0));
1246     }
1247   }
1248 
1249   if (mglevels[0]->eventsmoothsetup) PetscCall(PetscLogEventBegin(mglevels[0]->eventsmoothsetup,0,0,0,0));
1250   PetscCall(KSPSetUp(mglevels[0]->smoothd));
1251   if (mglevels[0]->smoothd->reason == KSP_DIVERGED_PC_FAILED) {
1252     pc->failedreason = PC_SUBPC_ERROR;
1253   }
1254   if (mglevels[0]->eventsmoothsetup) PetscCall(PetscLogEventEnd(mglevels[0]->eventsmoothsetup,0,0,0,0));
1255 
1256   /*
1257      Dump the interpolation/restriction matrices plus the
1258    Jacobian/stiffness on each level. This allows MATLAB users to
1259    easily check if the Galerkin condition A_c = R A_f R^T is satisfied.
1260 
1261    Only support one or the other at the same time.
1262   */
1263 #if defined(PETSC_USE_SOCKET_VIEWER)
1264   PetscCall(PetscOptionsGetBool(((PetscObject)pc)->options,((PetscObject)pc)->prefix,"-pc_mg_dump_matlab",&dump,NULL));
1265   if (dump) viewer = PETSC_VIEWER_SOCKET_(PetscObjectComm((PetscObject)pc));
1266   dump = PETSC_FALSE;
1267 #endif
1268   PetscCall(PetscOptionsGetBool(((PetscObject)pc)->options,((PetscObject)pc)->prefix,"-pc_mg_dump_binary",&dump,NULL));
1269   if (dump) viewer = PETSC_VIEWER_BINARY_(PetscObjectComm((PetscObject)pc));
1270 
1271   if (viewer) {
1272     for (i=1; i<n; i++) {
1273       PetscCall(MatView(mglevels[i]->restrct,viewer));
1274     }
1275     for (i=0; i<n; i++) {
1276       PetscCall(KSPGetPC(mglevels[i]->smoothd,&pc));
1277       PetscCall(MatView(pc->mat,viewer));
1278     }
1279   }
1280   PetscFunctionReturn(0);
1281 }
1282 
1283 /* -------------------------------------------------------------------------------------*/
1284 
1285 PetscErrorCode PCMGGetLevels_MG(PC pc, PetscInt *levels)
1286 {
1287   PC_MG *mg = (PC_MG *) pc->data;
1288 
1289   PetscFunctionBegin;
1290   *levels = mg->nlevels;
1291   PetscFunctionReturn(0);
1292 }
1293 
1294 /*@
1295    PCMGGetLevels - Gets the number of levels to use with MG.
1296 
1297    Not Collective
1298 
1299    Input Parameter:
1300 .  pc - the preconditioner context
1301 
1302    Output parameter:
1303 .  levels - the number of levels
1304 
1305    Level: advanced
1306 
1307 .seealso: `PCMGSetLevels()`
1308 @*/
1309 PetscErrorCode PCMGGetLevels(PC pc,PetscInt *levels)
1310 {
1311   PetscFunctionBegin;
1312   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
1313   PetscValidIntPointer(levels,2);
1314   *levels = 0;
1315   PetscTryMethod(pc,"PCMGGetLevels_C",(PC,PetscInt*),(pc,levels));
1316   PetscFunctionReturn(0);
1317 }
1318 
1319 /*@
1320    PCMGGetGridComplexity - compute operator and grid complexity of MG hierarchy
1321 
1322    Input Parameter:
1323 .  pc - the preconditioner context
1324 
1325    Output Parameters:
1326 +  gc - grid complexity = sum_i(n_i) / n_0
1327 -  oc - operator complexity = sum_i(nnz_i) / nnz_0
1328 
1329    Level: advanced
1330 
1331 .seealso: `PCMGGetLevels()`
1332 @*/
1333 PetscErrorCode PCMGGetGridComplexity(PC pc, PetscReal *gc, PetscReal *oc)
1334 {
1335   PC_MG          *mg      = (PC_MG*)pc->data;
1336   PC_MG_Levels   **mglevels = mg->levels;
1337   PetscInt       lev,N;
1338   PetscLogDouble nnz0 = 0, sgc = 0, soc = 0, n0 = 0;
1339   MatInfo        info;
1340 
1341   PetscFunctionBegin;
1342   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
1343   if (gc) PetscValidRealPointer(gc,2);
1344   if (oc) PetscValidRealPointer(oc,3);
1345   if (!pc->setupcalled) {
1346     if (gc) *gc = 0;
1347     if (oc) *oc = 0;
1348     PetscFunctionReturn(0);
1349   }
1350   PetscCheck(mg->nlevels > 0,PETSC_COMM_SELF,PETSC_ERR_PLIB,"MG has no levels");
1351   for (lev=0; lev<mg->nlevels; lev++) {
1352     Mat dB;
1353     PetscCall(KSPGetOperators(mglevels[lev]->smoothd,NULL,&dB));
1354     PetscCall(MatGetInfo(dB,MAT_GLOBAL_SUM,&info)); /* global reduction */
1355     PetscCall(MatGetSize(dB,&N,NULL));
1356     sgc += N;
1357     soc += info.nz_used;
1358     if (lev==mg->nlevels-1) {nnz0 = info.nz_used; n0 = N;}
1359   }
1360   if (n0 > 0 && gc) *gc = (PetscReal)(sgc/n0);
1361   else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Number for grid points on finest level is not available");
1362   if (nnz0 > 0 && oc) *oc = (PetscReal)(soc/nnz0);
1363   PetscFunctionReturn(0);
1364 }
1365 
1366 /*@
1367    PCMGSetType - Determines the form of multigrid to use:
1368    multiplicative, additive, full, or the Kaskade algorithm.
1369 
1370    Logically Collective on PC
1371 
1372    Input Parameters:
1373 +  pc - the preconditioner context
1374 -  form - multigrid form, one of PC_MG_MULTIPLICATIVE, PC_MG_ADDITIVE,
1375    PC_MG_FULL, PC_MG_KASKADE
1376 
1377    Options Database Key:
1378 .  -pc_mg_type <form> - Sets <form>, one of multiplicative,
1379    additive, full, kaskade
1380 
1381    Level: advanced
1382 
1383 .seealso: `PCMGSetLevels()`
1384 @*/
1385 PetscErrorCode  PCMGSetType(PC pc,PCMGType form)
1386 {
1387   PC_MG *mg = (PC_MG*)pc->data;
1388 
1389   PetscFunctionBegin;
1390   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
1391   PetscValidLogicalCollectiveEnum(pc,form,2);
1392   mg->am = form;
1393   if (form == PC_MG_MULTIPLICATIVE) pc->ops->applyrichardson = PCApplyRichardson_MG;
1394   else pc->ops->applyrichardson = NULL;
1395   PetscFunctionReturn(0);
1396 }
1397 
1398 /*@
1399    PCMGGetType - Determines the form of multigrid to use:
1400    multiplicative, additive, full, or the Kaskade algorithm.
1401 
1402    Logically Collective on PC
1403 
1404    Input Parameter:
1405 .  pc - the preconditioner context
1406 
1407    Output Parameter:
1408 .  type - one of PC_MG_MULTIPLICATIVE, PC_MG_ADDITIVE,PC_MG_FULL, PC_MG_KASKADE
1409 
1410    Level: advanced
1411 
1412 .seealso: `PCMGSetLevels()`
1413 @*/
1414 PetscErrorCode  PCMGGetType(PC pc,PCMGType *type)
1415 {
1416   PC_MG *mg = (PC_MG*)pc->data;
1417 
1418   PetscFunctionBegin;
1419   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
1420   *type = mg->am;
1421   PetscFunctionReturn(0);
1422 }
1423 
1424 /*@
1425    PCMGSetCycleType - Sets the type cycles to use.  Use PCMGSetCycleTypeOnLevel() for more
1426    complicated cycling.
1427 
1428    Logically Collective on PC
1429 
1430    Input Parameters:
1431 +  pc - the multigrid context
1432 -  n - either PC_MG_CYCLE_V or PC_MG_CYCLE_W
1433 
1434    Options Database Key:
1435 .  -pc_mg_cycle_type <v,w> - provide the cycle desired
1436 
1437    Level: advanced
1438 
1439 .seealso: `PCMGSetCycleTypeOnLevel()`
1440 @*/
1441 PetscErrorCode  PCMGSetCycleType(PC pc,PCMGCycleType n)
1442 {
1443   PC_MG        *mg        = (PC_MG*)pc->data;
1444   PC_MG_Levels **mglevels = mg->levels;
1445   PetscInt     i,levels;
1446 
1447   PetscFunctionBegin;
1448   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
1449   PetscValidLogicalCollectiveEnum(pc,n,2);
1450   PetscCheck(mglevels,PetscObjectComm((PetscObject)pc),PETSC_ERR_ORDER,"Must set MG levels with PCMGSetLevels() before calling");
1451   levels = mglevels[0]->levels;
1452   for (i=0; i<levels; i++) mglevels[i]->cycles = n;
1453   PetscFunctionReturn(0);
1454 }
1455 
1456 /*@
1457    PCMGMultiplicativeSetCycles - Sets the number of cycles to use for each preconditioner step
1458          of multigrid when PCMGType of PC_MG_MULTIPLICATIVE is used
1459 
1460    Logically Collective on PC
1461 
1462    Input Parameters:
1463 +  pc - the multigrid context
1464 -  n - number of cycles (default is 1)
1465 
1466    Options Database Key:
1467 .  -pc_mg_multiplicative_cycles n - set the number of cycles
1468 
1469    Level: advanced
1470 
1471    Notes:
1472     This is not associated with setting a v or w cycle, that is set with PCMGSetCycleType()
1473 
1474 .seealso: `PCMGSetCycleTypeOnLevel()`, `PCMGSetCycleType()`
1475 @*/
1476 PetscErrorCode  PCMGMultiplicativeSetCycles(PC pc,PetscInt n)
1477 {
1478   PC_MG        *mg        = (PC_MG*)pc->data;
1479 
1480   PetscFunctionBegin;
1481   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
1482   PetscValidLogicalCollectiveInt(pc,n,2);
1483   mg->cyclesperpcapply = n;
1484   PetscFunctionReturn(0);
1485 }
1486 
1487 PetscErrorCode PCMGSetGalerkin_MG(PC pc,PCMGGalerkinType use)
1488 {
1489   PC_MG *mg = (PC_MG*)pc->data;
1490 
1491   PetscFunctionBegin;
1492   mg->galerkin = use;
1493   PetscFunctionReturn(0);
1494 }
1495 
1496 /*@
1497    PCMGSetGalerkin - Causes the coarser grid matrices to be computed from the
1498       finest grid via the Galerkin process: A_i-1 = r_i * A_i * p_i
1499 
1500    Logically Collective on PC
1501 
1502    Input Parameters:
1503 +  pc - the multigrid context
1504 -  use - one of PC_MG_GALERKIN_BOTH,PC_MG_GALERKIN_PMAT,PC_MG_GALERKIN_MAT, or PC_MG_GALERKIN_NONE
1505 
1506    Options Database Key:
1507 .  -pc_mg_galerkin <both,pmat,mat,none> - set the matrices to form via the Galerkin process
1508 
1509    Level: intermediate
1510 
1511    Notes:
1512     Some codes that use PCMG such as PCGAMG use Galerkin internally while constructing the hierarchy and thus do not
1513      use the PCMG construction of the coarser grids.
1514 
1515 .seealso: `PCMGGetGalerkin()`, `PCMGGalerkinType`
1516 
1517 @*/
1518 PetscErrorCode PCMGSetGalerkin(PC pc,PCMGGalerkinType use)
1519 {
1520   PetscFunctionBegin;
1521   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
1522   PetscTryMethod(pc,"PCMGSetGalerkin_C",(PC,PCMGGalerkinType),(pc,use));
1523   PetscFunctionReturn(0);
1524 }
1525 
1526 /*@
1527    PCMGGetGalerkin - Checks if Galerkin multigrid is being used, i.e.
1528       A_i-1 = r_i * A_i * p_i
1529 
1530    Not Collective
1531 
1532    Input Parameter:
1533 .  pc - the multigrid context
1534 
1535    Output Parameter:
1536 .  galerkin - one of PC_MG_GALERKIN_BOTH,PC_MG_GALERKIN_PMAT,PC_MG_GALERKIN_MAT, PC_MG_GALERKIN_NONE, or PC_MG_GALERKIN_EXTERNAL
1537 
1538    Level: intermediate
1539 
1540 .seealso: `PCMGSetGalerkin()`, `PCMGGalerkinType`
1541 
1542 @*/
1543 PetscErrorCode  PCMGGetGalerkin(PC pc,PCMGGalerkinType  *galerkin)
1544 {
1545   PC_MG *mg = (PC_MG*)pc->data;
1546 
1547   PetscFunctionBegin;
1548   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
1549   *galerkin = mg->galerkin;
1550   PetscFunctionReturn(0);
1551 }
1552 
1553 PetscErrorCode PCMGSetAdaptInterpolation_MG(PC pc, PetscBool adapt)
1554 {
1555   PC_MG *mg = (PC_MG *) pc->data;
1556 
1557   PetscFunctionBegin;
1558   mg->adaptInterpolation = adapt;
1559   PetscFunctionReturn(0);
1560 }
1561 
1562 PetscErrorCode PCMGGetAdaptInterpolation_MG(PC pc, PetscBool *adapt)
1563 {
1564   PC_MG *mg = (PC_MG *) pc->data;
1565 
1566   PetscFunctionBegin;
1567   *adapt = mg->adaptInterpolation;
1568   PetscFunctionReturn(0);
1569 }
1570 
1571 PetscErrorCode PCMGSetAdaptCoarseSpaceType_MG(PC pc, PCMGCoarseSpaceType ctype)
1572 {
1573   PC_MG *mg = (PC_MG *) pc->data;
1574 
1575   PetscFunctionBegin;
1576   mg->adaptInterpolation = ctype != PCMG_ADAPT_NONE ? PETSC_TRUE : PETSC_FALSE;
1577   mg->coarseSpaceType = ctype;
1578   PetscFunctionReturn(0);
1579 }
1580 
1581 PetscErrorCode PCMGGetAdaptCoarseSpaceType_MG(PC pc, PCMGCoarseSpaceType *ctype)
1582 {
1583   PC_MG *mg = (PC_MG *) pc->data;
1584 
1585   PetscFunctionBegin;
1586   *ctype = mg->coarseSpaceType;
1587   PetscFunctionReturn(0);
1588 }
1589 
1590 PetscErrorCode PCMGSetAdaptCR_MG(PC pc, PetscBool cr)
1591 {
1592   PC_MG *mg = (PC_MG *) pc->data;
1593 
1594   PetscFunctionBegin;
1595   mg->compatibleRelaxation = cr;
1596   PetscFunctionReturn(0);
1597 }
1598 
1599 PetscErrorCode PCMGGetAdaptCR_MG(PC pc, PetscBool *cr)
1600 {
1601   PC_MG *mg = (PC_MG *) pc->data;
1602 
1603   PetscFunctionBegin;
1604   *cr = mg->compatibleRelaxation;
1605   PetscFunctionReturn(0);
1606 }
1607 
1608 /*@C
1609   PCMGSetAdaptCoarseSpaceType - Set the type of adaptive coarse space.
1610 
1611   Adapts or creates the interpolator based upon a vector space which should be accurately captured by the next coarser mesh, and thus accurately interpolated.
1612 
1613   Logically Collective on PC
1614 
1615   Input Parameters:
1616 + pc    - the multigrid context
1617 - ctype - the type of coarse space
1618 
1619   Options Database Keys:
1620 + -pc_mg_adapt_interp_n <int>             - The number of modes to use
1621 - -pc_mg_adapt_interp_coarse_space <type> - The type of coarse space: none, polynomial, harmonic, eigenvector, generalized_eigenvector, gdsw
1622 
1623   Level: intermediate
1624 
1625 .keywords: MG, set, Galerkin
1626 .seealso: `PCMGCoarseSpaceType`, `PCMGGetAdaptCoarseSpaceType()`, `PCMGSetGalerkin()`
1627 @*/
1628 PetscErrorCode PCMGSetAdaptCoarseSpaceType(PC pc, PCMGCoarseSpaceType ctype)
1629 {
1630   PetscFunctionBegin;
1631   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
1632   PetscValidLogicalCollectiveEnum(pc,ctype,2);
1633   PetscTryMethod(pc,"PCMGSetAdaptCoarseSpaceType_C",(PC,PCMGCoarseSpaceType),(pc,ctype));
1634   PetscFunctionReturn(0);
1635 }
1636 
1637 /*@C
1638   PCMGGetAdaptCoarseSpaceType - Get the type of adaptive coarse space.
1639 
1640   Not Collective
1641 
1642   Input Parameter:
1643 . pc    - the multigrid context
1644 
1645   Output Parameter:
1646 . ctype - the type of coarse space
1647 
1648   Level: intermediate
1649 
1650 .keywords: MG, Get, Galerkin
1651 .seealso: `PCMGCoarseSpaceType`, `PCMGSetAdaptCoarseSpaceType()`, `PCMGSetGalerkin()`
1652 @*/
1653 PetscErrorCode PCMGGetAdaptCoarseSpaceType(PC pc, PCMGCoarseSpaceType *ctype)
1654 {
1655   PetscFunctionBegin;
1656   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
1657   PetscValidPointer(ctype,2);
1658   PetscUseMethod(pc,"PCMGGetAdaptCoarseSpaceType_C",(PC,PCMGCoarseSpaceType*),(pc,ctype));
1659   PetscFunctionReturn(0);
1660 }
1661 
1662 /* MATT: REMOVE? */
1663 /*@
1664   PCMGSetAdaptInterpolation - Adapt the interpolator based upon a vector space which should be accurately captured by the next coarser mesh, and thus accurately interpolated.
1665 
1666   Logically Collective on PC
1667 
1668   Input Parameters:
1669 + pc    - the multigrid context
1670 - adapt - flag for adaptation of the interpolator
1671 
1672   Options Database Keys:
1673 + -pc_mg_adapt_interp                     - Turn on adaptation
1674 . -pc_mg_adapt_interp_n <int>             - The number of modes to use, should be divisible by dimension
1675 - -pc_mg_adapt_interp_coarse_space <type> - The type of coarse space: polynomial, harmonic, eigenvector, generalized_eigenvector
1676 
1677   Level: intermediate
1678 
1679 .keywords: MG, set, Galerkin
1680 .seealso: `PCMGGetAdaptInterpolation()`, `PCMGSetGalerkin()`
1681 @*/
1682 PetscErrorCode PCMGSetAdaptInterpolation(PC pc, PetscBool adapt)
1683 {
1684   PetscFunctionBegin;
1685   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
1686   PetscTryMethod(pc,"PCMGSetAdaptInterpolation_C",(PC,PetscBool),(pc,adapt));
1687   PetscFunctionReturn(0);
1688 }
1689 
1690 /*@
1691   PCMGGetAdaptInterpolation - Get the flag to adapt the interpolator based upon a vector space which should be accurately captured by the next coarser mesh, and thus accurately interpolated.
1692 
1693   Not collective
1694 
1695   Input Parameter:
1696 . pc    - the multigrid context
1697 
1698   Output Parameter:
1699 . adapt - flag for adaptation of the interpolator
1700 
1701   Level: intermediate
1702 
1703 .keywords: MG, set, Galerkin
1704 .seealso: `PCMGSetAdaptInterpolation()`, `PCMGSetGalerkin()`
1705 @*/
1706 PetscErrorCode PCMGGetAdaptInterpolation(PC pc, PetscBool *adapt)
1707 {
1708   PetscFunctionBegin;
1709   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
1710   PetscValidBoolPointer(adapt, 2);
1711   PetscUseMethod(pc,"PCMGGetAdaptInterpolation_C",(PC,PetscBool*),(pc,adapt));
1712   PetscFunctionReturn(0);
1713 }
1714 
1715 /*@
1716   PCMGSetAdaptCR - Monitor the coarse space quality using an auxiliary solve with compatible relaxation.
1717 
1718   Logically Collective on PC
1719 
1720   Input Parameters:
1721 + pc - the multigrid context
1722 - cr - flag for compatible relaxation
1723 
1724   Options Database Keys:
1725 . -pc_mg_adapt_cr - Turn on compatible relaxation
1726 
1727   Level: intermediate
1728 
1729 .keywords: MG, set, Galerkin
1730 .seealso: `PCMGGetAdaptCR()`, `PCMGSetAdaptInterpolation()`, `PCMGSetGalerkin()`
1731 @*/
1732 PetscErrorCode PCMGSetAdaptCR(PC pc, PetscBool cr)
1733 {
1734   PetscFunctionBegin;
1735   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
1736   PetscTryMethod(pc,"PCMGSetAdaptCR_C",(PC,PetscBool),(pc,cr));
1737   PetscFunctionReturn(0);
1738 }
1739 
1740 /*@
1741   PCMGGetAdaptCR - Get the flag to monitor coarse space quality using an auxiliary solve with compatible relaxation.
1742 
1743   Not collective
1744 
1745   Input Parameter:
1746 . pc    - the multigrid context
1747 
1748   Output Parameter:
1749 . cr - flag for compatible relaxaion
1750 
1751   Level: intermediate
1752 
1753 .keywords: MG, set, Galerkin
1754 .seealso: `PCMGSetAdaptCR()`, `PCMGGetAdaptInterpolation()`, `PCMGSetGalerkin()`
1755 @*/
1756 PetscErrorCode PCMGGetAdaptCR(PC pc, PetscBool *cr)
1757 {
1758   PetscFunctionBegin;
1759   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
1760   PetscValidBoolPointer(cr, 2);
1761   PetscUseMethod(pc,"PCMGGetAdaptCR_C",(PC,PetscBool*),(pc,cr));
1762   PetscFunctionReturn(0);
1763 }
1764 
1765 /*@
1766    PCMGSetNumberSmooth - Sets the number of pre and post-smoothing steps to use
1767    on all levels.  Use PCMGDistinctSmoothUp() to create separate up and down smoothers if you want different numbers of
1768    pre- and post-smoothing steps.
1769 
1770    Logically Collective on PC
1771 
1772    Input Parameters:
1773 +  mg - the multigrid context
1774 -  n - the number of smoothing steps
1775 
1776    Options Database Key:
1777 .  -mg_levels_ksp_max_it <n> - Sets number of pre and post-smoothing steps
1778 
1779    Level: advanced
1780 
1781    Notes:
1782     this does not set a value on the coarsest grid, since we assume that
1783     there is no separate smooth up on the coarsest grid.
1784 
1785 .seealso: `PCMGSetDistinctSmoothUp()`
1786 @*/
1787 PetscErrorCode  PCMGSetNumberSmooth(PC pc,PetscInt n)
1788 {
1789   PC_MG          *mg        = (PC_MG*)pc->data;
1790   PC_MG_Levels   **mglevels = mg->levels;
1791   PetscInt       i,levels;
1792 
1793   PetscFunctionBegin;
1794   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
1795   PetscValidLogicalCollectiveInt(pc,n,2);
1796   PetscCheck(mglevels,PetscObjectComm((PetscObject)pc),PETSC_ERR_ORDER,"Must set MG levels with PCMGSetLevels() before calling");
1797   levels = mglevels[0]->levels;
1798 
1799   for (i=1; i<levels; i++) {
1800     PetscCall(KSPSetTolerances(mglevels[i]->smoothu,PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT,n));
1801     PetscCall(KSPSetTolerances(mglevels[i]->smoothd,PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT,n));
1802     mg->default_smoothu = n;
1803     mg->default_smoothd = n;
1804   }
1805   PetscFunctionReturn(0);
1806 }
1807 
1808 /*@
1809    PCMGSetDistinctSmoothUp - sets the up (post) smoother to be a separate KSP from the down (pre) smoother on all levels
1810        and adds the suffix _up to the options name
1811 
1812    Logically Collective on PC
1813 
1814    Input Parameters:
1815 .  pc - the preconditioner context
1816 
1817    Options Database Key:
1818 .  -pc_mg_distinct_smoothup <bool> - use distinct smoothing objects
1819 
1820    Level: advanced
1821 
1822    Notes:
1823     this does not set a value on the coarsest grid, since we assume that
1824     there is no separate smooth up on the coarsest grid.
1825 
1826 .seealso: `PCMGSetNumberSmooth()`
1827 @*/
1828 PetscErrorCode  PCMGSetDistinctSmoothUp(PC pc)
1829 {
1830   PC_MG          *mg        = (PC_MG*)pc->data;
1831   PC_MG_Levels   **mglevels = mg->levels;
1832   PetscInt       i,levels;
1833   KSP            subksp;
1834 
1835   PetscFunctionBegin;
1836   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
1837   PetscCheck(mglevels,PetscObjectComm((PetscObject)pc),PETSC_ERR_ORDER,"Must set MG levels with PCMGSetLevels() before calling");
1838   levels = mglevels[0]->levels;
1839 
1840   for (i=1; i<levels; i++) {
1841     const char *prefix = NULL;
1842     /* make sure smoother up and down are different */
1843     PetscCall(PCMGGetSmootherUp(pc,i,&subksp));
1844     PetscCall(KSPGetOptionsPrefix(mglevels[i]->smoothd,&prefix));
1845     PetscCall(KSPSetOptionsPrefix(subksp,prefix));
1846     PetscCall(KSPAppendOptionsPrefix(subksp,"up_"));
1847   }
1848   PetscFunctionReturn(0);
1849 }
1850 
1851 /* No new matrices are created, and the coarse operator matrices are the references to the original ones */
1852 PetscErrorCode  PCGetInterpolations_MG(PC pc,PetscInt *num_levels,Mat *interpolations[])
1853 {
1854   PC_MG          *mg        = (PC_MG*)pc->data;
1855   PC_MG_Levels   **mglevels = mg->levels;
1856   Mat            *mat;
1857   PetscInt       l;
1858 
1859   PetscFunctionBegin;
1860   PetscCheck(mglevels,PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONGSTATE,"Must set MG levels before calling");
1861   PetscCall(PetscMalloc1(mg->nlevels,&mat));
1862   for (l=1; l< mg->nlevels; l++) {
1863     mat[l-1] = mglevels[l]->interpolate;
1864     PetscCall(PetscObjectReference((PetscObject)mat[l-1]));
1865   }
1866   *num_levels = mg->nlevels;
1867   *interpolations = mat;
1868   PetscFunctionReturn(0);
1869 }
1870 
1871 /* No new matrices are created, and the coarse operator matrices are the references to the original ones */
1872 PetscErrorCode  PCGetCoarseOperators_MG(PC pc,PetscInt *num_levels,Mat *coarseOperators[])
1873 {
1874   PC_MG          *mg        = (PC_MG*)pc->data;
1875   PC_MG_Levels   **mglevels = mg->levels;
1876   PetscInt       l;
1877   Mat            *mat;
1878 
1879   PetscFunctionBegin;
1880   PetscCheck(mglevels,PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONGSTATE,"Must set MG levels before calling");
1881   PetscCall(PetscMalloc1(mg->nlevels,&mat));
1882   for (l=0; l<mg->nlevels-1; l++) {
1883     PetscCall(KSPGetOperators(mglevels[l]->smoothd,NULL,&(mat[l])));
1884     PetscCall(PetscObjectReference((PetscObject)mat[l]));
1885   }
1886   *num_levels = mg->nlevels;
1887   *coarseOperators = mat;
1888   PetscFunctionReturn(0);
1889 }
1890 
1891 /*@C
1892   PCMGRegisterCoarseSpaceConstructor -  Adds a method to the PCMG package for coarse space construction.
1893 
1894   Not collective
1895 
1896   Input Parameters:
1897 + name     - name of the constructor
1898 - function - constructor routine
1899 
1900   Notes:
1901   Calling sequence for the routine:
1902 $ my_csp(PC pc, PetscInt l, DM dm, KSP smooth, PetscInt Nc, Mat initGuess, Mat *coarseSp)
1903 $   pc        - The PC object
1904 $   l         - The multigrid level, 0 is the coarse level
1905 $   dm        - The DM for this level
1906 $   smooth    - The level smoother
1907 $   Nc        - The size of the coarse space
1908 $   initGuess - Basis for an initial guess for the space
1909 $   coarseSp  - A basis for the computed coarse space
1910 
1911   Level: advanced
1912 
1913 .seealso: `PCMGGetCoarseSpaceConstructor()`, `PCRegister()`
1914 @*/
1915 PetscErrorCode PCMGRegisterCoarseSpaceConstructor(const char name[], PetscErrorCode (*function)(PC, PetscInt, DM, KSP, PetscInt, Mat, Mat*))
1916 {
1917   PetscFunctionBegin;
1918   PetscCall(PCInitializePackage());
1919   PetscCall(PetscFunctionListAdd(&PCMGCoarseList,name,function));
1920   PetscFunctionReturn(0);
1921 }
1922 
1923 /*@C
1924   PCMGGetCoarseSpaceConstructor -  Returns the given coarse space construction method.
1925 
1926   Not collective
1927 
1928   Input Parameter:
1929 . name     - name of the constructor
1930 
1931   Output Parameter:
1932 . function - constructor routine
1933 
1934   Notes:
1935   Calling sequence for the routine:
1936 $ my_csp(PC pc, PetscInt l, DM dm, KSP smooth, PetscInt Nc, Mat initGuess, Mat *coarseSp)
1937 $   pc        - The PC object
1938 $   l         - The multigrid level, 0 is the coarse level
1939 $   dm        - The DM for this level
1940 $   smooth    - The level smoother
1941 $   Nc        - The size of the coarse space
1942 $   initGuess - Basis for an initial guess for the space
1943 $   coarseSp  - A basis for the computed coarse space
1944 
1945   Level: advanced
1946 
1947 .seealso: `PCMGRegisterCoarseSpaceConstructor()`, `PCRegister()`
1948 @*/
1949 PetscErrorCode PCMGGetCoarseSpaceConstructor(const char name[], PetscErrorCode (**function)(PC, PetscInt, DM, KSP, PetscInt, Mat, Mat*))
1950 {
1951   PetscFunctionBegin;
1952   PetscCall(PetscFunctionListFind(PCMGCoarseList,name,function));
1953   PetscFunctionReturn(0);
1954 }
1955 
1956 /* ----------------------------------------------------------------------------------------*/
1957 
1958 /*MC
1959    PCMG - Use multigrid preconditioning. This preconditioner requires you provide additional
1960     information about the coarser grid matrices and restriction/interpolation operators.
1961 
1962    Options Database Keys:
1963 +  -pc_mg_levels <nlevels> - number of levels including finest
1964 .  -pc_mg_cycle_type <v,w> - provide the cycle desired
1965 .  -pc_mg_type <additive,multiplicative,full,kaskade> - multiplicative is the default
1966 .  -pc_mg_log - log information about time spent on each level of the solver
1967 .  -pc_mg_distinct_smoothup - configure up (after interpolation) and down (before restriction) smoothers separately (with different options prefixes)
1968 .  -pc_mg_galerkin <both,pmat,mat,none> - use Galerkin process to compute coarser operators, i.e. Acoarse = R A R'
1969 .  -pc_mg_multiplicative_cycles - number of cycles to use as the preconditioner (defaults to 1)
1970 .  -pc_mg_dump_matlab - dumps the matrices for each level and the restriction/interpolation matrices
1971                         to the Socket viewer for reading from MATLAB.
1972 -  -pc_mg_dump_binary - dumps the matrices for each level and the restriction/interpolation matrices
1973                         to the binary output file called binaryoutput
1974 
1975    Notes:
1976     If one uses a Krylov method such GMRES or CG as the smoother then one must use KSPFGMRES, KSPGCR, or KSPRICHARDSON as the outer Krylov method
1977 
1978        When run with a single level the smoother options are used on that level NOT the coarse grid solver options
1979 
1980        When run with KSPRICHARDSON the convergence test changes slightly if monitor is turned on. The iteration count may change slightly. This
1981        is because without monitoring the residual norm is computed WITHIN each multigrid cycle on the finest level after the pre-smoothing
1982        (because the residual has just been computed for the multigrid algorithm and is hence available for free) while with monitoring the
1983        residual is computed at the end of each cycle.
1984 
1985    Level: intermediate
1986 
1987 .seealso: `PCCreate()`, `PCSetType()`, `PCType`, `PC`, `PCMGType`, `PCEXOTIC`, `PCGAMG`, `PCML`, `PCHYPRE`
1988           `PCMGSetLevels()`, `PCMGGetLevels()`, `PCMGSetType()`, `PCMGSetCycleType()`,
1989           `PCMGSetDistinctSmoothUp()`, `PCMGGetCoarseSolve()`, `PCMGSetResidual()`, `PCMGSetInterpolation()`,
1990           `PCMGSetRestriction()`, `PCMGGetSmoother()`, `PCMGGetSmootherUp()`, `PCMGGetSmootherDown()`,
1991           `PCMGSetCycleTypeOnLevel()`, `PCMGSetRhs()`, `PCMGSetX()`, `PCMGSetR()`
1992 M*/
1993 
1994 PETSC_EXTERN PetscErrorCode PCCreate_MG(PC pc)
1995 {
1996   PC_MG          *mg;
1997 
1998   PetscFunctionBegin;
1999   PetscCall(PetscNewLog(pc,&mg));
2000   pc->data     = mg;
2001   mg->nlevels  = -1;
2002   mg->am       = PC_MG_MULTIPLICATIVE;
2003   mg->galerkin = PC_MG_GALERKIN_NONE;
2004   mg->adaptInterpolation = PETSC_FALSE;
2005   mg->Nc                 = -1;
2006   mg->eigenvalue         = -1;
2007 
2008   pc->useAmat = PETSC_TRUE;
2009 
2010   pc->ops->apply          = PCApply_MG;
2011   pc->ops->applytranspose = PCApplyTranspose_MG;
2012   pc->ops->matapply       = PCMatApply_MG;
2013   pc->ops->setup          = PCSetUp_MG;
2014   pc->ops->reset          = PCReset_MG;
2015   pc->ops->destroy        = PCDestroy_MG;
2016   pc->ops->setfromoptions = PCSetFromOptions_MG;
2017   pc->ops->view           = PCView_MG;
2018 
2019   PetscCall(PetscObjectComposedDataRegister(&mg->eigenvalue));
2020   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCMGSetGalerkin_C",PCMGSetGalerkin_MG));
2021   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCMGGetLevels_C",PCMGGetLevels_MG));
2022   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCMGSetLevels_C",PCMGSetLevels_MG));
2023   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCGetInterpolations_C",PCGetInterpolations_MG));
2024   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCGetCoarseOperators_C",PCGetCoarseOperators_MG));
2025   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCMGSetAdaptInterpolation_C",PCMGSetAdaptInterpolation_MG));
2026   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCMGGetAdaptInterpolation_C",PCMGGetAdaptInterpolation_MG));
2027   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCMGSetAdaptCR_C",PCMGSetAdaptCR_MG));
2028   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCMGGetAdaptCR_C",PCMGGetAdaptCR_MG));
2029   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCMGSetAdaptCoarseSpaceType_C",PCMGSetAdaptCoarseSpaceType_MG));
2030   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCMGGetAdaptCoarseSpaceType_C",PCMGGetAdaptCoarseSpaceType_MG));
2031   PetscFunctionReturn(0);
2032 }
2033