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