xref: /petsc/src/snes/impls/fas/fasfunc.c (revision 6dd63270497ad23dcf16ae500a87ff2b2a0b7474)
1 #include <../src/snes/impls/fas/fasimpls.h> /*I  "petscsnes.h"  I*/
2 
3 /*@
4   SNESFASSetType - Sets the update and correction type used for `SNESFAS`.
5 
6   Logically Collective
7 
8   Input Parameters:
9 + snes    - `SNESFAS` context
10 - fastype - `SNES_FAS_ADDITIVE`, `SNES_FAS_MULTIPLICATIVE`, `SNES_FAS_FULL`, or `SNES_FAS_KASKADE`
11 
12   Level: intermediate
13 
14 .seealso: [](ch_snes), `SNES`, `SNESFAS`, `PCMGSetType()`, `SNESFASGetType()`, `SNES_FAS_ADDITIVE`, `SNES_FAS_MULTIPLICATIVE`, `SNES_FAS_FULL`, `SNES_FAS_KASKADE`
15 @*/
16 PetscErrorCode SNESFASSetType(SNES snes, SNESFASType fastype)
17 {
18   SNES_FAS *fas;
19 
20   PetscFunctionBegin;
21   PetscValidHeaderSpecificType(snes, SNES_CLASSID, 1, SNESFAS);
22   PetscValidLogicalCollectiveEnum(snes, fastype, 2);
23   fas          = (SNES_FAS *)snes->data;
24   fas->fastype = fastype;
25   if (fas->next) PetscCall(SNESFASSetType(fas->next, fastype));
26   PetscFunctionReturn(PETSC_SUCCESS);
27 }
28 
29 /*@
30   SNESFASGetType - Gets the update and correction type used for `SNESFAS`.
31 
32   Logically Collective
33 
34   Input Parameter:
35 . snes - `SNESFAS` context
36 
37   Output Parameter:
38 . fastype - `SNES_FAS_ADDITIVE`, `SNES_FAS_MULTIPLICATIVE`, `SNES_FAS_FULL`, or `SNES_FAS_KASKADE`
39 
40   Level: intermediate
41 
42 .seealso: [](ch_snes), `SNES`, `SNESFAS`, `PCMGSetType()`, `SNESFASSetType()`, `SNES_FAS_ADDITIVE`, `SNES_FAS_MULTIPLICATIVE`, `SNES_FAS_FULL`, `SNES_FAS_KASKADE`
43 @*/
44 PetscErrorCode SNESFASGetType(SNES snes, SNESFASType *fastype)
45 {
46   SNES_FAS *fas;
47 
48   PetscFunctionBegin;
49   PetscValidHeaderSpecificType(snes, SNES_CLASSID, 1, SNESFAS);
50   PetscAssertPointer(fastype, 2);
51   fas      = (SNES_FAS *)snes->data;
52   *fastype = fas->fastype;
53   PetscFunctionReturn(PETSC_SUCCESS);
54 }
55 
56 /*@C
57   SNESFASSetLevels - Sets the number of levels to use with `SNESFAS`.
58   Must be called before any other `SNESFAS` routine.
59 
60   Input Parameters:
61 + snes   - the `SNES` context of `SNESType` `SNESFAS`
62 . levels - the number of levels
63 - comms  - optional communicators for each level; this is to allow solving the coarser
64             problems on smaller sets of processors.
65 
66   Level: intermediate
67 
68   Note:
69   If the number of levels is one then the solver uses the `-fas_levels` prefix
70   for setting the level options rather than the `-fas_coarse` prefix.
71 
72 .seealso: [](ch_snes), `SNES`, `SNESFAS`, `SNESFASGetLevels()`
73 @*/
74 PetscErrorCode SNESFASSetLevels(SNES snes, PetscInt levels, MPI_Comm *comms)
75 {
76   PetscInt    i;
77   const char *optionsprefix;
78   char        tprefix[128];
79   SNES_FAS   *fas;
80   SNES        prevsnes;
81   MPI_Comm    comm;
82 
83   PetscFunctionBegin;
84   PetscValidHeaderSpecificType(snes, SNES_CLASSID, 1, SNESFAS);
85   fas = (SNES_FAS *)snes->data;
86   PetscCall(PetscObjectGetComm((PetscObject)snes, &comm));
87   if (levels == fas->levels) {
88     if (!comms) PetscFunctionReturn(PETSC_SUCCESS);
89   }
90   /* user has changed the number of levels; reset */
91   PetscUseTypeMethod(snes, reset);
92   /* destroy any coarser levels if necessary */
93   PetscCall(SNESDestroy(&fas->next));
94   fas->next     = NULL;
95   fas->previous = NULL;
96   prevsnes      = snes;
97   /* setup the finest level */
98   PetscCall(SNESGetOptionsPrefix(snes, &optionsprefix));
99   PetscCall(PetscObjectComposedDataSetInt((PetscObject)snes, PetscMGLevelId, levels - 1));
100   for (i = levels - 1; i >= 0; i--) {
101     if (comms) comm = comms[i];
102     fas->level  = i;
103     fas->levels = levels;
104     fas->fine   = snes;
105     fas->next   = NULL;
106     if (i > 0) {
107       PetscCall(SNESCreate(comm, &fas->next));
108       PetscCall(SNESGetOptionsPrefix(fas->fine, &optionsprefix));
109       PetscCall(PetscSNPrintf(tprefix, sizeof(tprefix), "fas_levels_%" PetscInt_FMT "_cycle_", fas->level));
110       PetscCall(SNESAppendOptionsPrefix(fas->next, optionsprefix));
111       PetscCall(SNESAppendOptionsPrefix(fas->next, tprefix));
112       PetscCall(SNESSetType(fas->next, SNESFAS));
113       PetscCall(SNESSetTolerances(fas->next, fas->next->abstol, fas->next->rtol, fas->next->stol, fas->n_cycles, fas->next->max_funcs));
114       PetscCall(PetscObjectIncrementTabLevel((PetscObject)fas->next, (PetscObject)snes, levels - i));
115       PetscCall(PetscObjectComposedDataSetInt((PetscObject)fas->next, PetscMGLevelId, i - 1));
116 
117       ((SNES_FAS *)fas->next->data)->previous = prevsnes;
118 
119       prevsnes = fas->next;
120       fas      = (SNES_FAS *)prevsnes->data;
121     }
122   }
123   PetscFunctionReturn(PETSC_SUCCESS);
124 }
125 
126 /*@
127   SNESFASGetLevels - Gets the number of levels in a `SNESFAS`, including fine and coarse grids
128 
129   Input Parameter:
130 . snes - the `SNES` nonlinear solver context of `SNESType` `SNESFAS`
131 
132   Output Parameter:
133 . levels - the number of levels
134 
135   Level: advanced
136 
137 .seealso: [](ch_snes), `SNES`, `SNESFAS`, `SNESFASSetLevels()`, `PCMGGetLevels()`
138 @*/
139 PetscErrorCode SNESFASGetLevels(SNES snes, PetscInt *levels)
140 {
141   SNES_FAS *fas;
142 
143   PetscFunctionBegin;
144   PetscValidHeaderSpecificType(snes, SNES_CLASSID, 1, SNESFAS);
145   PetscAssertPointer(levels, 2);
146   fas     = (SNES_FAS *)snes->data;
147   *levels = fas->levels;
148   PetscFunctionReturn(PETSC_SUCCESS);
149 }
150 
151 /*@
152   SNESFASGetCycleSNES - Gets the `SNES` corresponding to a particular level of the `SNESFAS` hierarchy
153 
154   Input Parameters:
155 + snes  - the `SNES` nonlinear multigrid context
156 - level - the level to get
157 
158   Output Parameter:
159 . lsnes - the `SNES` for the requested level
160 
161   Level: advanced
162 
163 .seealso: [](ch_snes), `SNES`, `SNESFAS`, `SNESFASSetLevels()`, `SNESFASGetLevels()`
164 @*/
165 PetscErrorCode SNESFASGetCycleSNES(SNES snes, PetscInt level, SNES *lsnes)
166 {
167   SNES_FAS *fas;
168   PetscInt  i;
169 
170   PetscFunctionBegin;
171   PetscValidHeaderSpecificType(snes, SNES_CLASSID, 1, SNESFAS);
172   PetscAssertPointer(lsnes, 3);
173   fas = (SNES_FAS *)snes->data;
174   PetscCheck(level <= fas->levels - 1, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Requested level %" PetscInt_FMT " from SNESFAS containing %" PetscInt_FMT " levels", level, fas->levels);
175   PetscCheck(fas->level == fas->levels - 1, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "SNESFASGetCycleSNES may only be called on the finest-level SNES");
176 
177   *lsnes = snes;
178   for (i = fas->level; i > level; i--) {
179     *lsnes = fas->next;
180     fas    = (SNES_FAS *)(*lsnes)->data;
181   }
182   PetscCheck(fas->level == level, PetscObjectComm((PetscObject)snes), PETSC_ERR_PLIB, "SNESFAS level hierarchy corrupt");
183   PetscFunctionReturn(PETSC_SUCCESS);
184 }
185 
186 /*@
187   SNESFASSetNumberSmoothUp - Sets the number of post-smoothing steps to
188   use on all levels.
189 
190   Logically Collective
191 
192   Input Parameters:
193 + snes - the `SNES` nonlinear multigrid context
194 - n    - the number of smoothing steps to use
195 
196   Options Database Key:
197 . -snes_fas_smoothup <n> - Sets number of pre-smoothing steps
198 
199   Level: advanced
200 
201 .seealso: [](ch_snes), `SNES`, `SNESFAS`, `SNESFASSetNumberSmoothDown()`
202 @*/
203 PetscErrorCode SNESFASSetNumberSmoothUp(SNES snes, PetscInt n)
204 {
205   SNES_FAS *fas;
206 
207   PetscFunctionBegin;
208   PetscValidHeaderSpecificType(snes, SNES_CLASSID, 1, SNESFAS);
209   fas            = (SNES_FAS *)snes->data;
210   fas->max_up_it = n;
211   if (!fas->smoothu && fas->level != 0) PetscCall(SNESFASCycleCreateSmoother_Private(snes, &fas->smoothu));
212   if (fas->smoothu) PetscCall(SNESSetTolerances(fas->smoothu, fas->smoothu->abstol, fas->smoothu->rtol, fas->smoothu->stol, n, fas->smoothu->max_funcs));
213   if (fas->next) PetscCall(SNESFASSetNumberSmoothUp(fas->next, n));
214   PetscFunctionReturn(PETSC_SUCCESS);
215 }
216 
217 /*@
218   SNESFASSetNumberSmoothDown - Sets the number of pre-smoothing steps to
219   use on all levels.
220 
221   Logically Collective
222 
223   Input Parameters:
224 + snes - the `SNESFAS` nonlinear multigrid context
225 - n    - the number of smoothing steps to use
226 
227   Options Database Key:
228 . -snes_fas_smoothdown <n> - Sets number of pre-smoothing steps
229 
230   Level: advanced
231 
232 .seealso: [](ch_snes), `SNES`, `SNESFAS`, `SNESFASSetNumberSmoothUp()`
233 @*/
234 PetscErrorCode SNESFASSetNumberSmoothDown(SNES snes, PetscInt n)
235 {
236   SNES_FAS *fas;
237 
238   PetscFunctionBegin;
239   PetscValidHeaderSpecificType(snes, SNES_CLASSID, 1, SNESFAS);
240   fas = (SNES_FAS *)snes->data;
241   if (!fas->smoothd) PetscCall(SNESFASCycleCreateSmoother_Private(snes, &fas->smoothd));
242   PetscCall(SNESSetTolerances(fas->smoothd, fas->smoothd->abstol, fas->smoothd->rtol, fas->smoothd->stol, n, fas->smoothd->max_funcs));
243 
244   fas->max_down_it = n;
245   if (fas->next) PetscCall(SNESFASSetNumberSmoothDown(fas->next, n));
246   PetscFunctionReturn(PETSC_SUCCESS);
247 }
248 
249 /*@
250   SNESFASSetContinuation - Sets the `SNESFAS` cycle to default to using exact Newton solves on the upsweep
251 
252   Logically Collective
253 
254   Input Parameters:
255 + snes         - the `SNESFAS` nonlinear multigrid context
256 - continuation - whether to use continuation
257 
258   Options Database Key:
259 . -snes_fas_continuation - sets continuation to true
260 
261   Level: advanced
262 
263   Note:
264   This sets the prefix on the upsweep smoothers to -fas_continuation
265 
266 .seealso: [](ch_snes), `SNES`, `SNESFAS`, `SNESFASSetNumberSmoothUp()`
267 @*/
268 PetscErrorCode SNESFASSetContinuation(SNES snes, PetscBool continuation)
269 {
270   const char *optionsprefix;
271   char        tprefix[128];
272   SNES_FAS   *fas;
273 
274   PetscFunctionBegin;
275   PetscValidHeaderSpecificType(snes, SNES_CLASSID, 1, SNESFAS);
276   fas = (SNES_FAS *)snes->data;
277   PetscCall(SNESGetOptionsPrefix(fas->fine, &optionsprefix));
278   if (!fas->smoothu) PetscCall(SNESFASCycleCreateSmoother_Private(snes, &fas->smoothu));
279   PetscCall(PetscStrncpy(tprefix, "fas_levels_continuation_", sizeof(tprefix)));
280   PetscCall(SNESSetOptionsPrefix(fas->smoothu, optionsprefix));
281   PetscCall(SNESAppendOptionsPrefix(fas->smoothu, tprefix));
282   PetscCall(SNESSetType(fas->smoothu, SNESNEWTONLS));
283   PetscCall(SNESSetTolerances(fas->smoothu, fas->fine->abstol, fas->fine->rtol, fas->fine->stol, 50, 100));
284   fas->continuation = continuation;
285   if (fas->next) PetscCall(SNESFASSetContinuation(fas->next, continuation));
286   PetscFunctionReturn(PETSC_SUCCESS);
287 }
288 
289 /*@
290   SNESFASSetCycles - Sets the number of `SNESFAS` multigrid cycles to use each time a grid is visited.  Use `SNESFASSetCyclesOnLevel()` for more
291   complicated cycling.
292 
293   Logically Collective
294 
295   Input Parameters:
296 + snes   - the `SNESFAS` nonlinear multigrid context
297 - cycles - the number of cycles -- 1 for V-cycle, 2 for W-cycle
298 
299   Options Database Key:
300 . -snes_fas_cycles <1,2> - 1 for V-cycle, 2 for W-cycle
301 
302   Level: advanced
303 
304 .seealso: [](ch_snes), `SNES`, `SNESFAS`, `SNESFASSetCyclesOnLevel()`
305 @*/
306 PetscErrorCode SNESFASSetCycles(SNES snes, PetscInt cycles)
307 {
308   SNES_FAS *fas;
309   PetscBool isFine;
310 
311   PetscFunctionBegin;
312   PetscValidHeaderSpecificType(snes, SNES_CLASSID, 1, SNESFAS);
313   PetscCall(SNESFASCycleIsFine(snes, &isFine));
314   fas           = (SNES_FAS *)snes->data;
315   fas->n_cycles = cycles;
316   if (!isFine) PetscCall(SNESSetTolerances(snes, snes->abstol, snes->rtol, snes->stol, cycles, snes->max_funcs));
317   if (fas->next) PetscCall(SNESFASSetCycles(fas->next, cycles));
318   PetscFunctionReturn(PETSC_SUCCESS);
319 }
320 
321 /*@C
322   SNESFASSetMonitor - Sets the method-specific cycle monitoring
323 
324   Logically Collective
325 
326   Input Parameters:
327 + snes - the `SNESFAS` context
328 . vf   - viewer and format structure (may be `NULL` if `flg` is `PETSC_FALSE`)
329 - flg  - monitor or not
330 
331   Level: advanced
332 
333 .seealso: [](ch_snes), `SNES`, `SNESFAS`, `SNESMonitorSet()`, `SNESFASSetCyclesOnLevel()`
334 @*/
335 PetscErrorCode SNESFASSetMonitor(SNES snes, PetscViewerAndFormat *vf, PetscBool flg)
336 {
337   SNES_FAS *fas;
338   PetscBool isFine;
339   PetscInt  i, levels;
340   SNES      levelsnes;
341 
342   PetscFunctionBegin;
343   PetscValidHeaderSpecificType(snes, SNES_CLASSID, 1, SNESFAS);
344   PetscCall(SNESFASCycleIsFine(snes, &isFine));
345   fas    = (SNES_FAS *)snes->data;
346   levels = fas->levels;
347   if (isFine) {
348     for (i = 0; i < levels; i++) {
349       PetscCall(SNESFASGetCycleSNES(snes, i, &levelsnes));
350       fas = (SNES_FAS *)levelsnes->data;
351       if (flg) {
352         /* set the monitors for the upsmoother and downsmoother */
353         PetscCall(SNESMonitorCancel(levelsnes));
354         /* Only register destroy on finest level */
355         PetscCall(SNESMonitorSet(levelsnes, (PetscErrorCode (*)(SNES, PetscInt, PetscReal, void *))SNESMonitorDefault, vf, !i ? (PetscCtxDestroyFn *)PetscViewerAndFormatDestroy : NULL));
356       } else if (i != fas->levels - 1) {
357         /* unset the monitors on the coarse levels */
358         PetscCall(SNESMonitorCancel(levelsnes));
359       }
360     }
361   }
362   PetscFunctionReturn(PETSC_SUCCESS);
363 }
364 
365 /*@
366   SNESFASSetLog - Sets or unsets time logging for various `SNESFAS` stages on all levels
367 
368   Logically Collective
369 
370   Input Parameters:
371 + snes - the `SNESFAS` context
372 - flg  - whether to log or not
373 
374   Level: advanced
375 
376 .seealso: [](ch_snes), `SNES`, `SNESFAS`, `SNESFASSetMonitor()`
377 @*/
378 PetscErrorCode SNESFASSetLog(SNES snes, PetscBool flg)
379 {
380   SNES_FAS *fas;
381   PetscBool isFine;
382   PetscInt  i, levels;
383   SNES      levelsnes;
384   char      eventname[128];
385 
386   PetscFunctionBegin;
387   PetscValidHeaderSpecificType(snes, SNES_CLASSID, 1, SNESFAS);
388   PetscCall(SNESFASCycleIsFine(snes, &isFine));
389   fas    = (SNES_FAS *)snes->data;
390   levels = fas->levels;
391   if (isFine) {
392     for (i = 0; i < levels; i++) {
393       PetscCall(SNESFASGetCycleSNES(snes, i, &levelsnes));
394       fas = (SNES_FAS *)levelsnes->data;
395       if (flg) {
396         PetscCall(PetscSNPrintf(eventname, sizeof(eventname), "FASSetup  %" PetscInt_FMT, i));
397         PetscCall(PetscLogEventRegister(eventname, ((PetscObject)snes)->classid, &fas->eventsmoothsetup));
398         PetscCall(PetscSNPrintf(eventname, sizeof(eventname), "FASSmooth %" PetscInt_FMT, i));
399         PetscCall(PetscLogEventRegister(eventname, ((PetscObject)snes)->classid, &fas->eventsmoothsolve));
400         PetscCall(PetscSNPrintf(eventname, sizeof(eventname), "FASResid  %" PetscInt_FMT, i));
401         PetscCall(PetscLogEventRegister(eventname, ((PetscObject)snes)->classid, &fas->eventresidual));
402         PetscCall(PetscSNPrintf(eventname, sizeof(eventname), "FASInterp %" PetscInt_FMT, i));
403         PetscCall(PetscLogEventRegister(eventname, ((PetscObject)snes)->classid, &fas->eventinterprestrict));
404       } else {
405         fas->eventsmoothsetup    = 0;
406         fas->eventsmoothsolve    = 0;
407         fas->eventresidual       = 0;
408         fas->eventinterprestrict = 0;
409       }
410     }
411   }
412   PetscFunctionReturn(PETSC_SUCCESS);
413 }
414 
415 /*
416 Creates the default smoother type.
417 
418 This is SNESNRICHARDSON on each fine level and SNESNEWTONLS on the coarse level.
419  */
420 PetscErrorCode SNESFASCycleCreateSmoother_Private(SNES snes, SNES *smooth)
421 {
422   SNES_FAS   *fas;
423   const char *optionsprefix;
424   char        tprefix[128];
425   SNES        nsmooth;
426 
427   PetscFunctionBegin;
428   PetscValidHeaderSpecificType(snes, SNES_CLASSID, 1, SNESFAS);
429   PetscAssertPointer(smooth, 2);
430   fas = (SNES_FAS *)snes->data;
431   PetscCall(SNESGetOptionsPrefix(fas->fine, &optionsprefix));
432   /* create the default smoother */
433   PetscCall(SNESCreate(PetscObjectComm((PetscObject)snes), &nsmooth));
434   if (fas->level == 0) {
435     PetscCall(PetscStrncpy(tprefix, "fas_coarse_", sizeof(tprefix)));
436     PetscCall(SNESAppendOptionsPrefix(nsmooth, optionsprefix));
437     PetscCall(SNESAppendOptionsPrefix(nsmooth, tprefix));
438     PetscCall(SNESSetType(nsmooth, SNESNEWTONLS));
439     PetscCall(SNESSetTolerances(nsmooth, nsmooth->abstol, nsmooth->rtol, nsmooth->stol, nsmooth->max_its, nsmooth->max_funcs));
440   } else {
441     PetscCall(PetscSNPrintf(tprefix, sizeof(tprefix), "fas_levels_%" PetscInt_FMT "_", fas->level));
442     PetscCall(SNESAppendOptionsPrefix(nsmooth, optionsprefix));
443     PetscCall(SNESAppendOptionsPrefix(nsmooth, tprefix));
444     PetscCall(SNESSetType(nsmooth, SNESNRICHARDSON));
445     PetscCall(SNESSetTolerances(nsmooth, 0.0, 0.0, 0.0, fas->max_down_it, nsmooth->max_funcs));
446   }
447   PetscCall(PetscObjectIncrementTabLevel((PetscObject)nsmooth, (PetscObject)snes, 1));
448   PetscCall(PetscObjectCopyFortranFunctionPointers((PetscObject)snes, (PetscObject)nsmooth));
449   PetscCall(PetscObjectComposedDataSetInt((PetscObject)nsmooth, PetscMGLevelId, fas->level));
450   *smooth = nsmooth;
451   PetscFunctionReturn(PETSC_SUCCESS);
452 }
453 
454 /* ------------- Functions called on a particular level ----------------- */
455 
456 /*@
457   SNESFASCycleSetCycles - Sets the number of cycles for all levels in a `SNESFAS`
458 
459   Logically Collective
460 
461   Input Parameters:
462 + snes   - the `SNESFAS` nonlinear multigrid context
463 - cycles - the number of cycles -- 1 for V-cycle, 2 for W-cycle
464 
465   Level: advanced
466 
467 .seealso: [](ch_snes), `SNES`, `SNESFAS`, `SNESFASSetCycles()`
468 @*/
469 PetscErrorCode SNESFASCycleSetCycles(SNES snes, PetscInt cycles)
470 {
471   SNES_FAS *fas;
472 
473   PetscFunctionBegin;
474   PetscValidHeaderSpecificType(snes, SNES_CLASSID, 1, SNESFAS);
475   fas           = (SNES_FAS *)snes->data;
476   fas->n_cycles = cycles;
477   PetscCall(SNESSetTolerances(snes, snes->abstol, snes->rtol, snes->stol, cycles, snes->max_funcs));
478   PetscFunctionReturn(PETSC_SUCCESS);
479 }
480 
481 /*@
482   SNESFASCycleGetSmoother - Gets the smoother on a particular cycle level.
483 
484   Logically Collective
485 
486   Input Parameter:
487 . snes - the `SNESFAS` obtained with `SNESFASGetCycleSNES()`
488 
489   Output Parameter:
490 . smooth - the smoother
491 
492   Level: advanced
493 
494 .seealso: [](ch_snes), `SNES`, `SNESFAS`, `SNESFASCycleGetSmootherUp()`, `SNESFASCycleGetSmootherDown()`, `SNESFASGetCycleSNES()`
495 @*/
496 PetscErrorCode SNESFASCycleGetSmoother(SNES snes, SNES *smooth)
497 {
498   SNES_FAS *fas;
499 
500   PetscFunctionBegin;
501   PetscValidHeaderSpecificType(snes, SNES_CLASSID, 1, SNESFAS);
502   PetscAssertPointer(smooth, 2);
503   fas     = (SNES_FAS *)snes->data;
504   *smooth = fas->smoothd;
505   PetscFunctionReturn(PETSC_SUCCESS);
506 }
507 /*@
508   SNESFASCycleGetSmootherUp - Gets the up smoother on a particular cycle level.
509 
510   Logically Collective
511 
512   Input Parameter:
513 . snes - the `SNESFAS` obtained with `SNESFASGetCycleSNES()`
514 
515   Output Parameter:
516 . smoothu - the smoother
517 
518   Level: advanced
519 
520   Note:
521   Returns the downsmoother if no up smoother is available.  This enables transparent
522   default behavior in the process of the solve.
523 
524 .seealso: [](ch_snes), `SNES`, `SNESFAS`, `SNESFASCycleGetSmoother()`, `SNESFASCycleGetSmootherDown()`, `SNESFASGetCycleSNES()`
525 @*/
526 PetscErrorCode SNESFASCycleGetSmootherUp(SNES snes, SNES *smoothu)
527 {
528   SNES_FAS *fas;
529 
530   PetscFunctionBegin;
531   PetscValidHeaderSpecificType(snes, SNES_CLASSID, 1, SNESFAS);
532   PetscAssertPointer(smoothu, 2);
533   fas = (SNES_FAS *)snes->data;
534   if (!fas->smoothu) *smoothu = fas->smoothd;
535   else *smoothu = fas->smoothu;
536   PetscFunctionReturn(PETSC_SUCCESS);
537 }
538 
539 /*@
540   SNESFASCycleGetSmootherDown - Gets the down smoother on a particular cycle level.
541 
542   Logically Collective
543 
544   Input Parameter:
545 . snes - `SNESFAS` obtained with `SNESFASGetCycleSNES()`
546 
547   Output Parameter:
548 . smoothd - the smoother
549 
550   Level: advanced
551 
552 .seealso: [](ch_snes), `SNES`, `SNESFAS`, `SNESFASCycleGetSmootherUp()`, `SNESFASCycleGetSmoother()`, `SNESFASGetCycleSNES()`
553 @*/
554 PetscErrorCode SNESFASCycleGetSmootherDown(SNES snes, SNES *smoothd)
555 {
556   SNES_FAS *fas;
557 
558   PetscFunctionBegin;
559   PetscValidHeaderSpecificType(snes, SNES_CLASSID, 1, SNESFAS);
560   PetscAssertPointer(smoothd, 2);
561   fas      = (SNES_FAS *)snes->data;
562   *smoothd = fas->smoothd;
563   PetscFunctionReturn(PETSC_SUCCESS);
564 }
565 
566 /*@
567   SNESFASCycleGetCorrection - Gets the coarse correction `SNESFAS` context for this level
568 
569   Logically Collective
570 
571   Input Parameter:
572 . snes - the `SNESFAS` obtained with `SNESFASGetCycleSNES()`
573 
574   Output Parameter:
575 . correction - the coarse correction solve on this level
576 
577   Level: advanced
578 
579   Note:
580   Returns `NULL` on the coarsest level.
581 
582 .seealso: [](ch_snes), `SNES`, `SNESFAS` `SNESFASCycleGetSmootherUp()`, `SNESFASCycleGetSmoother()`
583 @*/
584 PetscErrorCode SNESFASCycleGetCorrection(SNES snes, SNES *correction)
585 {
586   SNES_FAS *fas;
587 
588   PetscFunctionBegin;
589   PetscValidHeaderSpecificType(snes, SNES_CLASSID, 1, SNESFAS);
590   PetscAssertPointer(correction, 2);
591   fas         = (SNES_FAS *)snes->data;
592   *correction = fas->next;
593   PetscFunctionReturn(PETSC_SUCCESS);
594 }
595 
596 /*@
597   SNESFASCycleGetInterpolation - Gets the interpolation on a level
598 
599   Logically Collective
600 
601   Input Parameter:
602 . snes - the `SNESFAS` obtained with `SNESFASGetCycleSNES()`
603 
604   Output Parameter:
605 . mat - the interpolation operator on this level
606 
607   Level: advanced
608 
609 .seealso: [](ch_snes), `SNES`, `SNESFAS`, `SNESFASCycleGetSmootherUp()`, `SNESFASCycleGetSmoother()`
610 @*/
611 PetscErrorCode SNESFASCycleGetInterpolation(SNES snes, Mat *mat)
612 {
613   SNES_FAS *fas;
614 
615   PetscFunctionBegin;
616   PetscValidHeaderSpecificType(snes, SNES_CLASSID, 1, SNESFAS);
617   PetscAssertPointer(mat, 2);
618   fas  = (SNES_FAS *)snes->data;
619   *mat = fas->interpolate;
620   PetscFunctionReturn(PETSC_SUCCESS);
621 }
622 
623 /*@
624   SNESFASCycleGetRestriction - Gets the restriction on a level
625 
626   Logically Collective
627 
628   Input Parameter:
629 . snes - the `SNESFAS` obtained with `SNESFASGetCycleSNES()`
630 
631   Output Parameter:
632 . mat - the restriction operator on this level
633 
634   Level: advanced
635 
636 .seealso: [](ch_snes), `SNES`, `SNESFAS`, `SNESFASGetRestriction()`, `SNESFASCycleGetInterpolation()`
637 @*/
638 PetscErrorCode SNESFASCycleGetRestriction(SNES snes, Mat *mat)
639 {
640   SNES_FAS *fas;
641 
642   PetscFunctionBegin;
643   PetscValidHeaderSpecificType(snes, SNES_CLASSID, 1, SNESFAS);
644   PetscAssertPointer(mat, 2);
645   fas  = (SNES_FAS *)snes->data;
646   *mat = fas->restrct;
647   PetscFunctionReturn(PETSC_SUCCESS);
648 }
649 
650 /*@
651   SNESFASCycleGetInjection - Gets the injection on a level
652 
653   Logically Collective
654 
655   Input Parameter:
656 . snes - the `SNESFAS` obtained with `SNESFASGetCycleSNES()`
657 
658   Output Parameter:
659 . mat - the restriction operator on this level
660 
661   Level: advanced
662 
663 .seealso: [](ch_snes), `SNES`, `SNESFAS`, `SNESFASGetInjection()`, `SNESFASCycleGetRestriction()`
664 @*/
665 PetscErrorCode SNESFASCycleGetInjection(SNES snes, Mat *mat)
666 {
667   SNES_FAS *fas;
668 
669   PetscFunctionBegin;
670   PetscValidHeaderSpecificType(snes, SNES_CLASSID, 1, SNESFAS);
671   PetscAssertPointer(mat, 2);
672   fas  = (SNES_FAS *)snes->data;
673   *mat = fas->inject;
674   PetscFunctionReturn(PETSC_SUCCESS);
675 }
676 
677 /*@
678   SNESFASCycleGetRScale - Gets the injection scale-factor on a level
679 
680   Logically Collective
681 
682   Input Parameter:
683 . snes - the  `SNESFAS` obtained with `SNESFASGetCycleSNES()`
684 
685   Output Parameter:
686 . vec - the restriction operator on this level
687 
688   Level: advanced
689 
690 .seealso: [](ch_snes), `SNES`, `SNESFAS`, `SNESFASCycleGetRestriction()`, `SNESFASGetRScale()`
691 @*/
692 PetscErrorCode SNESFASCycleGetRScale(SNES snes, Vec *vec)
693 {
694   SNES_FAS *fas;
695 
696   PetscFunctionBegin;
697   PetscValidHeaderSpecificType(snes, SNES_CLASSID, 1, SNESFAS);
698   PetscAssertPointer(vec, 2);
699   fas  = (SNES_FAS *)snes->data;
700   *vec = fas->rscale;
701   PetscFunctionReturn(PETSC_SUCCESS);
702 }
703 
704 /*@
705   SNESFASCycleIsFine - Determines if a given `SNES` is the finest level in a `SNESFAS`
706 
707   Logically Collective
708 
709   Input Parameter:
710 . snes - the `SNESFAS` context obtained with `SNESFASGetCycleSNES()`
711 
712   Output Parameter:
713 . flg - indicates if this is the fine level or not
714 
715   Level: advanced
716 
717 .seealso: [](ch_snes), `SNES`, `SNESFAS`, `SNESFASSetLevels()`
718 @*/
719 PetscErrorCode SNESFASCycleIsFine(SNES snes, PetscBool *flg)
720 {
721   SNES_FAS *fas;
722 
723   PetscFunctionBegin;
724   PetscValidHeaderSpecificType(snes, SNES_CLASSID, 1, SNESFAS);
725   PetscAssertPointer(flg, 2);
726   fas = (SNES_FAS *)snes->data;
727   if (fas->level == fas->levels - 1) *flg = PETSC_TRUE;
728   else *flg = PETSC_FALSE;
729   PetscFunctionReturn(PETSC_SUCCESS);
730 }
731 
732 /*  functions called on the finest level that return level-specific information  */
733 
734 /*@
735   SNESFASSetInterpolation - Sets the `Mat` to be used to apply the
736   interpolation from l-1 to the lth level
737 
738   Input Parameters:
739 + snes  - the `SNESFAS` nonlinear multigrid context
740 . mat   - the interpolation operator
741 - level - the level (0 is coarsest) to supply [do not supply 0]
742 
743   Level: advanced
744 
745   Notes:
746   Usually this is the same matrix used also to set the restriction
747   for the same level.
748 
749   One can pass in the interpolation matrix or its transpose; PETSc figures
750   out from the matrix dimensions which one it is.
751 
752 .seealso: [](ch_snes), `SNES`, `SNESFAS`, `SNESFASSetInjection()`, `SNESFASSetRestriction()`, `SNESFASSetRScale()`
753 @*/
754 PetscErrorCode SNESFASSetInterpolation(SNES snes, PetscInt level, Mat mat)
755 {
756   SNES_FAS *fas;
757   SNES      levelsnes;
758 
759   PetscFunctionBegin;
760   PetscValidHeaderSpecificType(snes, SNES_CLASSID, 1, SNESFAS);
761   if (mat) PetscValidHeaderSpecific(mat, MAT_CLASSID, 3);
762   PetscCall(SNESFASGetCycleSNES(snes, level, &levelsnes));
763   fas = (SNES_FAS *)levelsnes->data;
764   PetscCall(PetscObjectReference((PetscObject)mat));
765   PetscCall(MatDestroy(&fas->interpolate));
766   fas->interpolate = mat;
767   PetscFunctionReturn(PETSC_SUCCESS);
768 }
769 
770 /*@
771   SNESFASGetInterpolation - Gets the matrix used to calculate the
772   interpolation from l-1 to the lth level
773 
774   Input Parameters:
775 + snes  - the `SNESFAS` nonlinear multigrid context
776 - level - the level (0 is coarsest) to supply [do not supply 0]
777 
778   Output Parameter:
779 . mat - the interpolation operator
780 
781   Level: advanced
782 
783 .seealso: [](ch_snes), `SNES`, `SNESFAS`, `SNESFASSetInterpolation()`, `SNESFASGetInjection()`, `SNESFASGetRestriction()`, `SNESFASGetRScale()`
784 @*/
785 PetscErrorCode SNESFASGetInterpolation(SNES snes, PetscInt level, Mat *mat)
786 {
787   SNES_FAS *fas;
788   SNES      levelsnes;
789 
790   PetscFunctionBegin;
791   PetscValidHeaderSpecificType(snes, SNES_CLASSID, 1, SNESFAS);
792   PetscAssertPointer(mat, 3);
793   PetscCall(SNESFASGetCycleSNES(snes, level, &levelsnes));
794   fas  = (SNES_FAS *)levelsnes->data;
795   *mat = fas->interpolate;
796   PetscFunctionReturn(PETSC_SUCCESS);
797 }
798 
799 /*@
800   SNESFASSetRestriction - Sets the matrix to be used to restrict the defect
801   from level l to l-1.
802 
803   Input Parameters:
804 + snes  - the `SNESFAS` nonlinear multigrid context
805 . mat   - the restriction matrix
806 - level - the level (0 is coarsest) to supply [Do not supply 0]
807 
808   Level: advanced
809 
810   Notes:
811   Usually this is the same matrix used also to set the interpolation
812   for the same level.
813 
814   One can pass in the interpolation matrix or its transpose; PETSc figures
815   out from the matrix dimensions which one it is.
816 
817   If you do not set this, the transpose of the `Mat` set with SNESFASSetInterpolation()
818   is used.
819 
820 .seealso: [](ch_snes), `SNES`, `SNESFAS`, `SNESFASSetInterpolation()`, `SNESFASSetInjection()`
821 @*/
822 PetscErrorCode SNESFASSetRestriction(SNES snes, PetscInt level, Mat mat)
823 {
824   SNES_FAS *fas;
825   SNES      levelsnes;
826 
827   PetscFunctionBegin;
828   PetscValidHeaderSpecificType(snes, SNES_CLASSID, 1, SNESFAS);
829   if (mat) PetscValidHeaderSpecific(mat, MAT_CLASSID, 3);
830   PetscCall(SNESFASGetCycleSNES(snes, level, &levelsnes));
831   fas = (SNES_FAS *)levelsnes->data;
832   PetscCall(PetscObjectReference((PetscObject)mat));
833   PetscCall(MatDestroy(&fas->restrct));
834   fas->restrct = mat;
835   PetscFunctionReturn(PETSC_SUCCESS);
836 }
837 
838 /*@
839   SNESFASGetRestriction - Gets the matrix used to calculate the
840   restriction from l to the l-1th level
841 
842   Input Parameters:
843 + snes  - the `SNESFAS` nonlinear multigrid context
844 - level - the level (0 is coarsest) to supply [do not supply 0]
845 
846   Output Parameter:
847 . mat - the interpolation operator
848 
849   Level: advanced
850 
851 .seealso: [](ch_snes), `SNES`, `SNESFAS`, `SNESFASSetRestriction()`, `SNESFASGetInjection()`, `SNESFASGetInterpolation()`, `SNESFASGetRScale()`
852 @*/
853 PetscErrorCode SNESFASGetRestriction(SNES snes, PetscInt level, Mat *mat)
854 {
855   SNES_FAS *fas;
856   SNES      levelsnes;
857 
858   PetscFunctionBegin;
859   PetscValidHeaderSpecificType(snes, SNES_CLASSID, 1, SNESFAS);
860   PetscAssertPointer(mat, 3);
861   PetscCall(SNESFASGetCycleSNES(snes, level, &levelsnes));
862   fas  = (SNES_FAS *)levelsnes->data;
863   *mat = fas->restrct;
864   PetscFunctionReturn(PETSC_SUCCESS);
865 }
866 
867 /*@
868   SNESFASSetInjection - Sets the matrix to be used to inject the solution
869   from `level` to `level-1`.
870 
871   Input Parameters:
872 + snes  - the `SNESFAS` nonlinear multigrid context
873 . mat   - the injection matrix
874 - level - the level (0 is coarsest) to supply [Do not supply 0]
875 
876   Level: advanced
877 
878   Note:
879   If you do not set this, the restriction and rscale is used to
880   project the solution instead.
881 
882 .seealso: [](ch_snes), `SNES`, `SNESFAS`, `SNESFASSetInterpolation()`, `SNESFASSetRestriction()`
883 @*/
884 PetscErrorCode SNESFASSetInjection(SNES snes, PetscInt level, Mat mat)
885 {
886   SNES_FAS *fas;
887   SNES      levelsnes;
888 
889   PetscFunctionBegin;
890   PetscValidHeaderSpecificType(snes, SNES_CLASSID, 1, SNESFAS);
891   if (mat) PetscValidHeaderSpecific(mat, MAT_CLASSID, 3);
892   PetscCall(SNESFASGetCycleSNES(snes, level, &levelsnes));
893   fas = (SNES_FAS *)levelsnes->data;
894   PetscCall(PetscObjectReference((PetscObject)mat));
895   PetscCall(MatDestroy(&fas->inject));
896 
897   fas->inject = mat;
898   PetscFunctionReturn(PETSC_SUCCESS);
899 }
900 
901 /*@
902   SNESFASGetInjection - Gets the matrix used to calculate the
903   injection from l-1 to the lth level
904 
905   Input Parameters:
906 + snes  - the `SNESFAS` nonlinear multigrid context
907 - level - the level (0 is coarsest) to supply [do not supply 0]
908 
909   Output Parameter:
910 . mat - the injection operator
911 
912   Level: advanced
913 
914 .seealso: [](ch_snes), `SNES`, `SNESFAS`, `SNESFASSetInjection()`, `SNESFASGetRestriction()`, `SNESFASGetInterpolation()`, `SNESFASGetRScale()`
915 @*/
916 PetscErrorCode SNESFASGetInjection(SNES snes, PetscInt level, Mat *mat)
917 {
918   SNES_FAS *fas;
919   SNES      levelsnes;
920 
921   PetscFunctionBegin;
922   PetscValidHeaderSpecificType(snes, SNES_CLASSID, 1, SNESFAS);
923   PetscAssertPointer(mat, 3);
924   PetscCall(SNESFASGetCycleSNES(snes, level, &levelsnes));
925   fas  = (SNES_FAS *)levelsnes->data;
926   *mat = fas->inject;
927   PetscFunctionReturn(PETSC_SUCCESS);
928 }
929 
930 /*@
931   SNESFASSetRScale - Sets the scaling factor of the restriction
932   operator from level l to l-1.
933 
934   Input Parameters:
935 + snes   - the `SNESFAS` nonlinear multigrid context
936 . rscale - the restriction scaling
937 - level  - the level (0 is coarsest) to supply [Do not supply 0]
938 
939   Level: advanced
940 
941   Note:
942   This is only used when the injection is not set.
943 
944 .seealso: [](ch_snes), `SNES`, `SNESFAS`, `SNESFASSetInjection()`, `SNESFASSetRestriction()`
945 @*/
946 PetscErrorCode SNESFASSetRScale(SNES snes, PetscInt level, Vec rscale)
947 {
948   SNES_FAS *fas;
949   SNES      levelsnes;
950 
951   PetscFunctionBegin;
952   PetscValidHeaderSpecificType(snes, SNES_CLASSID, 1, SNESFAS);
953   if (rscale) PetscValidHeaderSpecific(rscale, VEC_CLASSID, 3);
954   PetscCall(SNESFASGetCycleSNES(snes, level, &levelsnes));
955   fas = (SNES_FAS *)levelsnes->data;
956   PetscCall(PetscObjectReference((PetscObject)rscale));
957   PetscCall(VecDestroy(&fas->rscale));
958   fas->rscale = rscale;
959   PetscFunctionReturn(PETSC_SUCCESS);
960 }
961 
962 /*@
963   SNESFASGetSmoother - Gets the default smoother on a level.
964 
965   Input Parameters:
966 + snes  - the `SNESFAS` nonlinear multigrid context
967 - level - the level (0 is coarsest) to supply
968 
969   Output Parameter:
970 . smooth - the smoother
971 
972   Level: advanced
973 
974 .seealso: [](ch_snes), `SNES`, `SNESFAS`, `SNESFASSetInjection()`, `SNESFASSetRestriction()`
975 @*/
976 PetscErrorCode SNESFASGetSmoother(SNES snes, PetscInt level, SNES *smooth)
977 {
978   SNES_FAS *fas;
979   SNES      levelsnes;
980 
981   PetscFunctionBegin;
982   PetscValidHeaderSpecificType(snes, SNES_CLASSID, 1, SNESFAS);
983   PetscAssertPointer(smooth, 3);
984   PetscCall(SNESFASGetCycleSNES(snes, level, &levelsnes));
985   fas = (SNES_FAS *)levelsnes->data;
986   if (!fas->smoothd) PetscCall(SNESFASCycleCreateSmoother_Private(levelsnes, &fas->smoothd));
987   *smooth = fas->smoothd;
988   PetscFunctionReturn(PETSC_SUCCESS);
989 }
990 
991 /*@
992   SNESFASGetSmootherDown - Gets the downsmoother on a level.
993 
994   Input Parameters:
995 + snes  - the `SNESFAS` nonlinear multigrid context
996 - level - the level (0 is coarsest) to supply
997 
998   Output Parameter:
999 . smooth - the smoother
1000 
1001   Level: advanced
1002 
1003 .seealso: [](ch_snes), `SNES`, `SNESFAS`, `SNESFASSetInjection()`, `SNESFASSetRestriction()`
1004 @*/
1005 PetscErrorCode SNESFASGetSmootherDown(SNES snes, PetscInt level, SNES *smooth)
1006 {
1007   SNES_FAS *fas;
1008   SNES      levelsnes;
1009 
1010   PetscFunctionBegin;
1011   PetscValidHeaderSpecificType(snes, SNES_CLASSID, 1, SNESFAS);
1012   PetscAssertPointer(smooth, 3);
1013   PetscCall(SNESFASGetCycleSNES(snes, level, &levelsnes));
1014   fas = (SNES_FAS *)levelsnes->data;
1015   /* if the user chooses to differentiate smoothers, create them both at this point */
1016   if (!fas->smoothd) PetscCall(SNESFASCycleCreateSmoother_Private(levelsnes, &fas->smoothd));
1017   if (!fas->smoothu) PetscCall(SNESFASCycleCreateSmoother_Private(levelsnes, &fas->smoothu));
1018   *smooth = fas->smoothd;
1019   PetscFunctionReturn(PETSC_SUCCESS);
1020 }
1021 
1022 /*@
1023   SNESFASGetSmootherUp - Gets the upsmoother on a level.
1024 
1025   Input Parameters:
1026 + snes  - the `SNESFAS` nonlinear multigrid context
1027 - level - the level (0 is coarsest)
1028 
1029   Output Parameter:
1030 . smooth - the smoother
1031 
1032   Level: advanced
1033 
1034 .seealso: [](ch_snes), `SNES`, `SNESFAS`, `SNESFASSetInjection()`, `SNESFASSetRestriction()`
1035 @*/
1036 PetscErrorCode SNESFASGetSmootherUp(SNES snes, PetscInt level, SNES *smooth)
1037 {
1038   SNES_FAS *fas;
1039   SNES      levelsnes;
1040 
1041   PetscFunctionBegin;
1042   PetscValidHeaderSpecificType(snes, SNES_CLASSID, 1, SNESFAS);
1043   PetscAssertPointer(smooth, 3);
1044   PetscCall(SNESFASGetCycleSNES(snes, level, &levelsnes));
1045   fas = (SNES_FAS *)levelsnes->data;
1046   /* if the user chooses to differentiate smoothers, create them both at this point */
1047   if (!fas->smoothd) PetscCall(SNESFASCycleCreateSmoother_Private(levelsnes, &fas->smoothd));
1048   if (!fas->smoothu) PetscCall(SNESFASCycleCreateSmoother_Private(levelsnes, &fas->smoothu));
1049   *smooth = fas->smoothu;
1050   PetscFunctionReturn(PETSC_SUCCESS);
1051 }
1052 
1053 /*@
1054   SNESFASGetCoarseSolve - Gets the coarsest level solver.
1055 
1056   Input Parameter:
1057 . snes - the `SNESFAS` nonlinear multigrid context
1058 
1059   Output Parameter:
1060 . coarse - the coarse-level solver
1061 
1062   Level: advanced
1063 
1064 .seealso: [](ch_snes), `SNES`, `SNESFAS`, `SNESFASSetInjection()`, `SNESFASSetRestriction()`
1065 @*/
1066 PetscErrorCode SNESFASGetCoarseSolve(SNES snes, SNES *coarse)
1067 {
1068   SNES_FAS *fas;
1069   SNES      levelsnes;
1070 
1071   PetscFunctionBegin;
1072   PetscValidHeaderSpecificType(snes, SNES_CLASSID, 1, SNESFAS);
1073   PetscAssertPointer(coarse, 2);
1074   PetscCall(SNESFASGetCycleSNES(snes, 0, &levelsnes));
1075   fas = (SNES_FAS *)levelsnes->data;
1076   /* if the user chooses to differentiate smoothers, create them both at this point */
1077   if (!fas->smoothd) PetscCall(SNESFASCycleCreateSmoother_Private(levelsnes, &fas->smoothd));
1078   *coarse = fas->smoothd;
1079   PetscFunctionReturn(PETSC_SUCCESS);
1080 }
1081 
1082 /*@
1083   SNESFASFullSetDownSweep - Smooth during the initial downsweep for `SNESFAS`
1084 
1085   Logically Collective
1086 
1087   Input Parameters:
1088 + snes - the `SNESFAS` nonlinear multigrid context
1089 - swp  - whether to downsweep or not
1090 
1091   Options Database Key:
1092 . -snes_fas_full_downsweep - Sets whether to smooth on the initial downsweep
1093 
1094   Level: advanced
1095 
1096 .seealso: [](ch_snes), `SNES`, `SNESFAS`, `SNESFASSetNumberSmoothUp()`
1097 @*/
1098 PetscErrorCode SNESFASFullSetDownSweep(SNES snes, PetscBool swp)
1099 {
1100   SNES_FAS *fas;
1101 
1102   PetscFunctionBegin;
1103   PetscValidHeaderSpecificType(snes, SNES_CLASSID, 1, SNESFAS);
1104   fas                 = (SNES_FAS *)snes->data;
1105   fas->full_downsweep = swp;
1106   if (fas->next) PetscCall(SNESFASFullSetDownSweep(fas->next, swp));
1107   PetscFunctionReturn(PETSC_SUCCESS);
1108 }
1109 
1110 /*@
1111   SNESFASFullSetTotal - Use total residual restriction and total interpolation on the initial down and up sweep of full `SNESFAS` cycles
1112 
1113   Logically Collective
1114 
1115   Input Parameters:
1116 + snes  - the `SNESFAS`  nonlinear multigrid context
1117 - total - whether to use total restriction / interpolatiaon or not (the alternative is defect restriction and correction interpolation)
1118 
1119   Options Database Key:
1120 . -snes_fas_full_total - Use total restriction and interpolation on the initial down and up sweeps for the full `SNESFAS` cycle
1121 
1122   Level: advanced
1123 
1124   Note:
1125   This option is only significant if the interpolation of a coarse correction (`MatInterpolate()`) is significantly different from total
1126   solution interpolation (`DMInterpolateSolution()`).
1127 
1128 .seealso: [](ch_snes), `SNES`, `SNESFAS`, `SNESFASSetNumberSmoothUp()`, `DMInterpolateSolution()`
1129 @*/
1130 PetscErrorCode SNESFASFullSetTotal(SNES snes, PetscBool total)
1131 {
1132   SNES_FAS *fas;
1133 
1134   PetscFunctionBegin;
1135   PetscValidHeaderSpecificType(snes, SNES_CLASSID, 1, SNESFAS);
1136   fas             = (SNES_FAS *)snes->data;
1137   fas->full_total = total;
1138   if (fas->next) PetscCall(SNESFASFullSetTotal(fas->next, total));
1139   PetscFunctionReturn(PETSC_SUCCESS);
1140 }
1141 
1142 /*@
1143   SNESFASFullGetTotal - Use total residual restriction and total interpolation on the initial down and up sweep of full FAS cycles
1144 
1145   Logically Collective
1146 
1147   Input Parameter:
1148 . snes - the `SNESFAS` nonlinear multigrid context
1149 
1150   Output Parameter:
1151 . total - whether to use total restriction / interpolatiaon or not (the alternative is defect restriction and correction interpolation)
1152 
1153   Level: advanced
1154 
1155 .seealso: [](ch_snes), `SNES`, `SNESFAS`, `SNESFASSetNumberSmoothUp()`, `DMInterpolateSolution()`, `SNESFullSetTotal()`
1156 @*/
1157 PetscErrorCode SNESFASFullGetTotal(SNES snes, PetscBool *total)
1158 {
1159   SNES_FAS *fas;
1160 
1161   PetscFunctionBegin;
1162   PetscValidHeaderSpecificType(snes, SNES_CLASSID, 1, SNESFAS);
1163   fas    = (SNES_FAS *)snes->data;
1164   *total = fas->full_total;
1165   PetscFunctionReturn(PETSC_SUCCESS);
1166 }
1167