Actual source code: fasfunc.c
1: #include <../src/snes/impls/fas/fasimpls.h>
3: /*@
4: SNESFASSetType - Sets the update and correction type used for `SNESFAS`.
6: Logically Collective
8: Input Parameters:
9: + snes - `SNESFAS` context
10: - fastype - `SNES_FAS_ADDITIVE`, `SNES_FAS_MULTIPLICATIVE`, `SNES_FAS_FULL`, or `SNES_FAS_KASKADE`
12: Level: intermediate
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;
20: PetscFunctionBegin;
23: fas = (SNES_FAS *)snes->data;
24: fas->fastype = fastype;
25: if (fas->next) PetscCall(SNESFASSetType(fas->next, fastype));
26: PetscFunctionReturn(PETSC_SUCCESS);
27: }
29: /*@
30: SNESFASGetType - Gets the update and correction type used for `SNESFAS`.
32: Logically Collective
34: Input Parameter:
35: . snes - `SNESFAS` context
37: Output Parameter:
38: . fastype - `SNES_FAS_ADDITIVE`, `SNES_FAS_MULTIPLICATIVE`, `SNES_FAS_FULL`, or `SNES_FAS_KASKADE`
40: Level: intermediate
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;
48: PetscFunctionBegin;
50: PetscAssertPointer(fastype, 2);
51: fas = (SNES_FAS *)snes->data;
52: *fastype = fas->fastype;
53: PetscFunctionReturn(PETSC_SUCCESS);
54: }
56: /*@C
57: SNESFASSetLevels - Sets the number of levels to use with `SNESFAS`.
58: Must be called before any other `SNESFAS` routine.
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.
66: Level: intermediate
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.
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;
83: PetscFunctionBegin;
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_%d_cycle_", (int)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));
117: ((SNES_FAS *)fas->next->data)->previous = prevsnes;
119: prevsnes = fas->next;
120: fas = (SNES_FAS *)prevsnes->data;
121: }
122: }
123: PetscFunctionReturn(PETSC_SUCCESS);
124: }
126: /*@
127: SNESFASGetLevels - Gets the number of levels in a `SNESFAS`, including fine and coarse grids
129: Input Parameter:
130: . snes - the `SNES` nonlinear solver context of `SNESType` `SNESFAS`
132: Output Parameter:
133: . levels - the number of levels
135: Level: advanced
137: .seealso: [](ch_snes), `SNES`, `SNESFAS`, `SNESFASSetLevels()`, `PCMGGetLevels()`
138: @*/
139: PetscErrorCode SNESFASGetLevels(SNES snes, PetscInt *levels)
140: {
141: SNES_FAS *fas;
143: PetscFunctionBegin;
145: PetscAssertPointer(levels, 2);
146: fas = (SNES_FAS *)snes->data;
147: *levels = fas->levels;
148: PetscFunctionReturn(PETSC_SUCCESS);
149: }
151: /*@
152: SNESFASGetCycleSNES - Gets the `SNES` corresponding to a particular level of the `SNESFAS` hierarchy
154: Input Parameters:
155: + snes - the `SNES` nonlinear multigrid context
156: - level - the level to get
158: Output Parameter:
159: . lsnes - the `SNES` for the requested level
161: Level: advanced
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;
170: PetscFunctionBegin;
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");
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: }
186: /*@
187: SNESFASSetNumberSmoothUp - Sets the number of post-smoothing steps to
188: use on all levels.
190: Logically Collective
192: Input Parameters:
193: + snes - the `SNES` nonlinear multigrid context
194: - n - the number of smoothing steps to use
196: Options Database Key:
197: . -snes_fas_smoothup <n> - Sets number of pre-smoothing steps
199: Level: advanced
201: .seealso: [](ch_snes), `SNES`, `SNESFAS`, `SNESFASSetNumberSmoothDown()`
202: @*/
203: PetscErrorCode SNESFASSetNumberSmoothUp(SNES snes, PetscInt n)
204: {
205: SNES_FAS *fas;
207: PetscFunctionBegin;
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: }
217: /*@
218: SNESFASSetNumberSmoothDown - Sets the number of pre-smoothing steps to
219: use on all levels.
221: Logically Collective
223: Input Parameters:
224: + snes - the `SNESFAS` nonlinear multigrid context
225: - n - the number of smoothing steps to use
227: Options Database Key:
228: . -snes_fas_smoothdown <n> - Sets number of pre-smoothing steps
230: Level: advanced
232: .seealso: [](ch_snes), `SNES`, `SNESFAS`, `SNESFASSetNumberSmoothUp()`
233: @*/
234: PetscErrorCode SNESFASSetNumberSmoothDown(SNES snes, PetscInt n)
235: {
236: SNES_FAS *fas;
238: PetscFunctionBegin;
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));
244: fas->max_down_it = n;
245: if (fas->next) PetscCall(SNESFASSetNumberSmoothDown(fas->next, n));
246: PetscFunctionReturn(PETSC_SUCCESS);
247: }
249: /*@
250: SNESFASSetContinuation - Sets the `SNESFAS` cycle to default to using exact Newton solves on the upsweep
252: Logically Collective
254: Input Parameters:
255: + snes - the `SNESFAS` nonlinear multigrid context
256: - continuation - whether to use continuation
258: Options Database Key:
259: . -snes_fas_continuation - sets continuation to true
261: Level: advanced
263: Note:
264: This sets the prefix on the upsweep smoothers to -fas_continuation
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;
274: PetscFunctionBegin;
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: }
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.
293: Logically Collective
295: Input Parameters:
296: + snes - the `SNESFAS` nonlinear multigrid context
297: - cycles - the number of cycles -- 1 for V-cycle, 2 for W-cycle
299: Options Database Key:
300: . -snes_fas_cycles <1,2> - 1 for V-cycle, 2 for W-cycle
302: Level: advanced
304: .seealso: [](ch_snes), `SNES`, `SNESFAS`, `SNESFASSetCyclesOnLevel()`
305: @*/
306: PetscErrorCode SNESFASSetCycles(SNES snes, PetscInt cycles)
307: {
308: SNES_FAS *fas;
309: PetscBool isFine;
311: PetscFunctionBegin;
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: }
321: /*@C
322: SNESFASSetMonitor - Sets the method-specific cycle monitoring
324: Logically Collective
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
331: Level: advanced
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;
342: PetscFunctionBegin;
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 ? (PetscErrorCode (*)(void **))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: }
365: /*@
366: SNESFASSetLog - Sets or unsets time logging for various `SNESFAS` stages on all levels
368: Logically Collective
370: Input Parameters:
371: + snes - the `SNESFAS` context
372: - flg - whether to log or not
374: Level: advanced
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];
386: PetscFunctionBegin;
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 %d", (int)i));
397: PetscCall(PetscLogEventRegister(eventname, ((PetscObject)snes)->classid, &fas->eventsmoothsetup));
398: PetscCall(PetscSNPrintf(eventname, sizeof(eventname), "FASSmooth %d", (int)i));
399: PetscCall(PetscLogEventRegister(eventname, ((PetscObject)snes)->classid, &fas->eventsmoothsolve));
400: PetscCall(PetscSNPrintf(eventname, sizeof(eventname), "FASResid %d", (int)i));
401: PetscCall(PetscLogEventRegister(eventname, ((PetscObject)snes)->classid, &fas->eventresidual));
402: PetscCall(PetscSNPrintf(eventname, sizeof(eventname), "FASInterp %d", (int)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: }
415: /*
416: Creates the default smoother type.
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;
427: PetscFunctionBegin;
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_%d_", (int)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: }
454: /* ------------- Functions called on a particular level ----------------- */
456: /*@
457: SNESFASCycleSetCycles - Sets the number of cycles for all levels in a `SNESFAS`
459: Logically Collective
461: Input Parameters:
462: + snes - the `SNESFAS` nonlinear multigrid context
463: - cycles - the number of cycles -- 1 for V-cycle, 2 for W-cycle
465: Level: advanced
467: .seealso: [](ch_snes), `SNES`, `SNESFAS`, `SNESFASSetCycles()`
468: @*/
469: PetscErrorCode SNESFASCycleSetCycles(SNES snes, PetscInt cycles)
470: {
471: SNES_FAS *fas;
473: PetscFunctionBegin;
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: }
481: /*@
482: SNESFASCycleGetSmoother - Gets the smoother on a particular cycle level.
484: Logically Collective
486: Input Parameter:
487: . snes - the `SNESFAS` obtained with `SNESFASGetCycleSNES()`
489: Output Parameter:
490: . smooth - the smoother
492: Level: advanced
494: .seealso: [](ch_snes), `SNES`, `SNESFAS`, `SNESFASCycleGetSmootherUp()`, `SNESFASCycleGetSmootherDown()`, `SNESFASGetCycleSNES()`
495: @*/
496: PetscErrorCode SNESFASCycleGetSmoother(SNES snes, SNES *smooth)
497: {
498: SNES_FAS *fas;
500: PetscFunctionBegin;
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.
510: Logically Collective
512: Input Parameter:
513: . snes - the `SNESFAS` obtained with `SNESFASGetCycleSNES()`
515: Output Parameter:
516: . smoothu - the smoother
518: Level: advanced
520: Note:
521: Returns the downsmoother if no up smoother is available. This enables transparent
522: default behavior in the process of the solve.
524: .seealso: [](ch_snes), `SNES`, `SNESFAS`, `SNESFASCycleGetSmoother()`, `SNESFASCycleGetSmootherDown()`, `SNESFASGetCycleSNES()`
525: @*/
526: PetscErrorCode SNESFASCycleGetSmootherUp(SNES snes, SNES *smoothu)
527: {
528: SNES_FAS *fas;
530: PetscFunctionBegin;
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: }
539: /*@
540: SNESFASCycleGetSmootherDown - Gets the down smoother on a particular cycle level.
542: Logically Collective
544: Input Parameter:
545: . snes - `SNESFAS` obtained with `SNESFASGetCycleSNES()`
547: Output Parameter:
548: . smoothd - the smoother
550: Level: advanced
552: .seealso: [](ch_snes), `SNES`, `SNESFAS`, `SNESFASCycleGetSmootherUp()`, `SNESFASCycleGetSmoother()`, `SNESFASGetCycleSNES()`
553: @*/
554: PetscErrorCode SNESFASCycleGetSmootherDown(SNES snes, SNES *smoothd)
555: {
556: SNES_FAS *fas;
558: PetscFunctionBegin;
560: PetscAssertPointer(smoothd, 2);
561: fas = (SNES_FAS *)snes->data;
562: *smoothd = fas->smoothd;
563: PetscFunctionReturn(PETSC_SUCCESS);
564: }
566: /*@
567: SNESFASCycleGetCorrection - Gets the coarse correction `SNESFAS` context for this level
569: Logically Collective
571: Input Parameter:
572: . snes - the `SNESFAS` obtained with `SNESFASGetCycleSNES()`
574: Output Parameter:
575: . correction - the coarse correction solve on this level
577: Level: advanced
579: Note:
580: Returns `NULL` on the coarsest level.
582: .seealso: [](ch_snes), `SNES`, `SNESFAS` `SNESFASCycleGetSmootherUp()`, `SNESFASCycleGetSmoother()`
583: @*/
584: PetscErrorCode SNESFASCycleGetCorrection(SNES snes, SNES *correction)
585: {
586: SNES_FAS *fas;
588: PetscFunctionBegin;
590: PetscAssertPointer(correction, 2);
591: fas = (SNES_FAS *)snes->data;
592: *correction = fas->next;
593: PetscFunctionReturn(PETSC_SUCCESS);
594: }
596: /*@
597: SNESFASCycleGetInterpolation - Gets the interpolation on a level
599: Logically Collective
601: Input Parameter:
602: . snes - the `SNESFAS` obtained with `SNESFASGetCycleSNES()`
604: Output Parameter:
605: . mat - the interpolation operator on this level
607: Level: advanced
609: .seealso: [](ch_snes), `SNES`, `SNESFAS`, `SNESFASCycleGetSmootherUp()`, `SNESFASCycleGetSmoother()`
610: @*/
611: PetscErrorCode SNESFASCycleGetInterpolation(SNES snes, Mat *mat)
612: {
613: SNES_FAS *fas;
615: PetscFunctionBegin;
617: PetscAssertPointer(mat, 2);
618: fas = (SNES_FAS *)snes->data;
619: *mat = fas->interpolate;
620: PetscFunctionReturn(PETSC_SUCCESS);
621: }
623: /*@
624: SNESFASCycleGetRestriction - Gets the restriction on a level
626: Logically Collective
628: Input Parameter:
629: . snes - the `SNESFAS` obtained with `SNESFASGetCycleSNES()`
631: Output Parameter:
632: . mat - the restriction operator on this level
634: Level: advanced
636: .seealso: [](ch_snes), `SNES`, `SNESFAS`, `SNESFASGetRestriction()`, `SNESFASCycleGetInterpolation()`
637: @*/
638: PetscErrorCode SNESFASCycleGetRestriction(SNES snes, Mat *mat)
639: {
640: SNES_FAS *fas;
642: PetscFunctionBegin;
644: PetscAssertPointer(mat, 2);
645: fas = (SNES_FAS *)snes->data;
646: *mat = fas->restrct;
647: PetscFunctionReturn(PETSC_SUCCESS);
648: }
650: /*@
651: SNESFASCycleGetInjection - Gets the injection on a level
653: Logically Collective
655: Input Parameter:
656: . snes - the `SNESFAS` obtained with `SNESFASGetCycleSNES()`
658: Output Parameter:
659: . mat - the restriction operator on this level
661: Level: advanced
663: .seealso: [](ch_snes), `SNES`, `SNESFAS`, `SNESFASGetInjection()`, `SNESFASCycleGetRestriction()`
664: @*/
665: PetscErrorCode SNESFASCycleGetInjection(SNES snes, Mat *mat)
666: {
667: SNES_FAS *fas;
669: PetscFunctionBegin;
671: PetscAssertPointer(mat, 2);
672: fas = (SNES_FAS *)snes->data;
673: *mat = fas->inject;
674: PetscFunctionReturn(PETSC_SUCCESS);
675: }
677: /*@
678: SNESFASCycleGetRScale - Gets the injection scale-factor on a level
680: Logically Collective
682: Input Parameter:
683: . snes - the `SNESFAS` obtained with `SNESFASGetCycleSNES()`
685: Output Parameter:
686: . vec - the restriction operator on this level
688: Level: advanced
690: .seealso: [](ch_snes), `SNES`, `SNESFAS`, `SNESFASCycleGetRestriction()`, `SNESFASGetRScale()`
691: @*/
692: PetscErrorCode SNESFASCycleGetRScale(SNES snes, Vec *vec)
693: {
694: SNES_FAS *fas;
696: PetscFunctionBegin;
698: PetscAssertPointer(vec, 2);
699: fas = (SNES_FAS *)snes->data;
700: *vec = fas->rscale;
701: PetscFunctionReturn(PETSC_SUCCESS);
702: }
704: /*@
705: SNESFASCycleIsFine - Determines if a given `SNES` is the finest level in a `SNESFAS`
707: Logically Collective
709: Input Parameter:
710: . snes - the `SNESFAS` context obtained with `SNESFASGetCycleSNES()`
712: Output Parameter:
713: . flg - indicates if this is the fine level or not
715: Level: advanced
717: .seealso: [](ch_snes), `SNES`, `SNESFAS`, `SNESFASSetLevels()`
718: @*/
719: PetscErrorCode SNESFASCycleIsFine(SNES snes, PetscBool *flg)
720: {
721: SNES_FAS *fas;
723: PetscFunctionBegin;
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: }
732: /* functions called on the finest level that return level-specific information */
734: /*@
735: SNESFASSetInterpolation - Sets the `Mat` to be used to apply the
736: interpolation from l-1 to the lth level
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]
743: Level: advanced
745: Notes:
746: Usually this is the same matrix used also to set the restriction
747: for the same level.
749: One can pass in the interpolation matrix or its transpose; PETSc figures
750: out from the matrix dimensions which one it is.
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;
759: PetscFunctionBegin;
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: }
770: /*@
771: SNESFASGetInterpolation - Gets the matrix used to calculate the
772: interpolation from l-1 to the lth level
774: Input Parameters:
775: + snes - the `SNESFAS` nonlinear multigrid context
776: - level - the level (0 is coarsest) to supply [do not supply 0]
778: Output Parameter:
779: . mat - the interpolation operator
781: Level: advanced
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;
790: PetscFunctionBegin;
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: }
799: /*@
800: SNESFASSetRestriction - Sets the matrix to be used to restrict the defect
801: from level l to l-1.
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]
808: Level: advanced
810: Notes:
811: Usually this is the same matrix used also to set the interpolation
812: for the same level.
814: One can pass in the interpolation matrix or its transpose; PETSc figures
815: out from the matrix dimensions which one it is.
817: If you do not set this, the transpose of the `Mat` set with SNESFASSetInterpolation()
818: is used.
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;
827: PetscFunctionBegin;
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: }
838: /*@
839: SNESFASGetRestriction - Gets the matrix used to calculate the
840: restriction from l to the l-1th level
842: Input Parameters:
843: + snes - the `SNESFAS` nonlinear multigrid context
844: - level - the level (0 is coarsest) to supply [do not supply 0]
846: Output Parameter:
847: . mat - the interpolation operator
849: Level: advanced
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;
858: PetscFunctionBegin;
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: }
867: /*@
868: SNESFASSetInjection - Sets the matrix to be used to inject the solution
869: from `level` to `level-1`.
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]
876: Level: advanced
878: Note:
879: If you do not set this, the restriction and rscale is used to
880: project the solution instead.
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;
889: PetscFunctionBegin;
892: PetscCall(SNESFASGetCycleSNES(snes, level, &levelsnes));
893: fas = (SNES_FAS *)levelsnes->data;
894: PetscCall(PetscObjectReference((PetscObject)mat));
895: PetscCall(MatDestroy(&fas->inject));
897: fas->inject = mat;
898: PetscFunctionReturn(PETSC_SUCCESS);
899: }
901: /*@
902: SNESFASGetInjection - Gets the matrix used to calculate the
903: injection from l-1 to the lth level
905: Input Parameters:
906: + snes - the `SNESFAS` nonlinear multigrid context
907: - level - the level (0 is coarsest) to supply [do not supply 0]
909: Output Parameter:
910: . mat - the injection operator
912: Level: advanced
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;
921: PetscFunctionBegin;
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: }
930: /*@
931: SNESFASSetRScale - Sets the scaling factor of the restriction
932: operator from level l to l-1.
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]
939: Level: advanced
941: Note:
942: This is only used when the injection is not set.
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;
951: PetscFunctionBegin;
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: }
962: /*@
963: SNESFASGetSmoother - Gets the default smoother on a level.
965: Input Parameters:
966: + snes - the `SNESFAS` nonlinear multigrid context
967: - level - the level (0 is coarsest) to supply
969: Output Parameter:
970: . smooth - the smoother
972: Level: advanced
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;
981: PetscFunctionBegin;
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: }
991: /*@
992: SNESFASGetSmootherDown - Gets the downsmoother on a level.
994: Input Parameters:
995: + snes - the `SNESFAS` nonlinear multigrid context
996: - level - the level (0 is coarsest) to supply
998: Output Parameter:
999: . smooth - the smoother
1001: Level: advanced
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;
1010: PetscFunctionBegin;
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: }
1022: /*@
1023: SNESFASGetSmootherUp - Gets the upsmoother on a level.
1025: Input Parameters:
1026: + snes - the `SNESFAS` nonlinear multigrid context
1027: - level - the level (0 is coarsest)
1029: Output Parameter:
1030: . smooth - the smoother
1032: Level: advanced
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;
1041: PetscFunctionBegin;
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: }
1053: /*@
1054: SNESFASGetCoarseSolve - Gets the coarsest level solver.
1056: Input Parameter:
1057: . snes - the `SNESFAS` nonlinear multigrid context
1059: Output Parameter:
1060: . coarse - the coarse-level solver
1062: Level: advanced
1064: .seealso: [](ch_snes), `SNES`, `SNESFAS`, `SNESFASSetInjection()`, `SNESFASSetRestriction()`
1065: @*/
1066: PetscErrorCode SNESFASGetCoarseSolve(SNES snes, SNES *coarse)
1067: {
1068: SNES_FAS *fas;
1069: SNES levelsnes;
1071: PetscFunctionBegin;
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: }
1082: /*@
1083: SNESFASFullSetDownSweep - Smooth during the initial downsweep for `SNESFAS`
1085: Logically Collective
1087: Input Parameters:
1088: + snes - the `SNESFAS` nonlinear multigrid context
1089: - swp - whether to downsweep or not
1091: Options Database Key:
1092: . -snes_fas_full_downsweep - Sets whether to smooth on the initial downsweep
1094: Level: advanced
1096: .seealso: [](ch_snes), `SNES`, `SNESFAS`, `SNESFASSetNumberSmoothUp()`
1097: @*/
1098: PetscErrorCode SNESFASFullSetDownSweep(SNES snes, PetscBool swp)
1099: {
1100: SNES_FAS *fas;
1102: PetscFunctionBegin;
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: }
1110: /*@
1111: SNESFASFullSetTotal - Use total residual restriction and total interpolation on the initial down and up sweep of full `SNESFAS` cycles
1113: Logically Collective
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)
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
1122: Level: advanced
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()`).
1128: .seealso: [](ch_snes), `SNES`, `SNESFAS`, `SNESFASSetNumberSmoothUp()`, `DMInterpolateSolution()`
1129: @*/
1130: PetscErrorCode SNESFASFullSetTotal(SNES snes, PetscBool total)
1131: {
1132: SNES_FAS *fas;
1134: PetscFunctionBegin;
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: }
1142: /*@
1143: SNESFASFullGetTotal - Use total residual restriction and total interpolation on the initial down and up sweep of full FAS cycles
1145: Logically Collective
1147: Input Parameter:
1148: . snes - the `SNESFAS` nonlinear multigrid context
1150: Output Parameter:
1151: . total - whether to use total restriction / interpolatiaon or not (the alternative is defect restriction and correction interpolation)
1153: Level: advanced
1155: .seealso: [](ch_snes), `SNES`, `SNESFAS`, `SNESFASSetNumberSmoothUp()`, `DMInterpolateSolution()`, `SNESFullSetTotal()`
1156: @*/
1157: PetscErrorCode SNESFASFullGetTotal(SNES snes, PetscBool *total)
1158: {
1159: SNES_FAS *fas;
1161: PetscFunctionBegin;
1163: fas = (SNES_FAS *)snes->data;
1164: *total = fas->full_total;
1165: PetscFunctionReturn(PETSC_SUCCESS);
1166: }