Actual source code: fasfunc.c
1: #include <../src/snes/impls/fas/fasimpls.h>
3: /*@
4: SNESFASSetType - Sets the update and correction type used for FAS.
6: Logically Collective
8: Input Parameters:
9: + snes - FAS context
10: - fastype - `SNES_FAS_ADDITIVE`, `SNES_FAS_MULTIPLICATIVE`, `SNES_FAS_FULL`, or `SNES_FAS_KASKADE`
12: Level: intermediate
14: .seealso: `SNESFAS`, `PCMGSetType()`, `SNESFASGetType()`
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 FAS.
32: Logically Collective
34: Input Parameter:
35: . snes - `SNESFAS` context
37: Output Parameter:
38: . fastype - `SNES_FAS_ADDITIVE` or `SNES_FAS_MULTIPLICATIVE`
40: Level: intermediate
42: .seealso: `SNESFAS`, `PCMGSetType()`, `SNESFASSetType()`
43: @*/
44: PetscErrorCode SNESFASGetType(SNES snes, SNESFASType *fastype)
45: {
46: SNES_FAS *fas;
48: PetscFunctionBegin;
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 FAS routine.
60: Input Parameters:
61: + snes - the snes context
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 multigrid uses the `-fas_levels` prefix
70: for setting the level options rather than the `-fas_coarse` prefix.
72: .seealso: `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
132: Output parameter:
133: . levels - the number of levels
135: Level: advanced
137: .seealso: `SNESFAS`, `SNESFASSetLevels()`, `PCMGGetLevels()`
138: @*/
139: PetscErrorCode SNESFASGetLevels(SNES snes, PetscInt *levels)
140: {
141: SNES_FAS *fas;
143: PetscFunctionBegin;
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
153: level of the `SNESFAS` hierarchy.
155: Input Parameters:
156: + snes - the `SNES` nonlinear multigrid context
157: - level - the level to get
159: Output Parameter:
160: . lsnes - the `SNES` for the requested level
162: Level: advanced
164: .seealso: `SNESFAS`, `SNESFASSetLevels()`, `SNESFASGetLevels()`
165: @*/
166: PetscErrorCode SNESFASGetCycleSNES(SNES snes, PetscInt level, SNES *lsnes)
167: {
168: SNES_FAS *fas;
169: PetscInt i;
171: PetscFunctionBegin;
174: fas = (SNES_FAS *)snes->data;
175: 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);
176: PetscCheck(fas->level == fas->levels - 1, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "SNESFASGetCycleSNES may only be called on the finest-level SNES");
178: *lsnes = snes;
179: for (i = fas->level; i > level; i--) {
180: *lsnes = fas->next;
181: fas = (SNES_FAS *)(*lsnes)->data;
182: }
183: PetscCheck(fas->level == level, PetscObjectComm((PetscObject)snes), PETSC_ERR_PLIB, "SNESFAS level hierarchy corrupt");
184: PetscFunctionReturn(PETSC_SUCCESS);
185: }
187: /*@
188: SNESFASSetNumberSmoothUp - Sets the number of post-smoothing steps to
189: use on all levels.
191: Logically Collective
193: Input Parameters:
194: + snes - the `SNES` nonlinear multigrid context
195: - n - the number of smoothing steps
197: Options Database Key:
198: . -snes_fas_smoothup <n> - Sets number of pre-smoothing steps
200: Level: advanced
202: .seealso: `SNESFAS`, `SNESFASSetNumberSmoothDown()`
203: @*/
204: PetscErrorCode SNESFASSetNumberSmoothUp(SNES snes, PetscInt n)
205: {
206: SNES_FAS *fas;
208: PetscFunctionBegin;
210: fas = (SNES_FAS *)snes->data;
211: fas->max_up_it = n;
212: if (!fas->smoothu && fas->level != 0) PetscCall(SNESFASCycleCreateSmoother_Private(snes, &fas->smoothu));
213: if (fas->smoothu) PetscCall(SNESSetTolerances(fas->smoothu, fas->smoothu->abstol, fas->smoothu->rtol, fas->smoothu->stol, n, fas->smoothu->max_funcs));
214: if (fas->next) PetscCall(SNESFASSetNumberSmoothUp(fas->next, n));
215: PetscFunctionReturn(PETSC_SUCCESS);
216: }
218: /*@
219: SNESFASSetNumberSmoothDown - Sets the number of pre-smoothing steps to
220: use on all levels.
222: Logically Collective
224: Input Parameters:
225: + snes - the `SNESFAS` nonlinear multigrid context
226: - n - the number of smoothing steps
228: Options Database Key:
229: . -snes_fas_smoothdown <n> - Sets number of pre-smoothing steps
231: Level: advanced
233: .seealso: `SNESFAS`, `SNESFASSetNumberSmoothUp()`
234: @*/
235: PetscErrorCode SNESFASSetNumberSmoothDown(SNES snes, PetscInt n)
236: {
237: SNES_FAS *fas;
239: PetscFunctionBegin;
241: fas = (SNES_FAS *)snes->data;
242: if (!fas->smoothd) PetscCall(SNESFASCycleCreateSmoother_Private(snes, &fas->smoothd));
243: PetscCall(SNESSetTolerances(fas->smoothd, fas->smoothd->abstol, fas->smoothd->rtol, fas->smoothd->stol, n, fas->smoothd->max_funcs));
245: fas->max_down_it = n;
246: if (fas->next) PetscCall(SNESFASSetNumberSmoothDown(fas->next, n));
247: PetscFunctionReturn(PETSC_SUCCESS);
248: }
250: /*@
251: SNESFASSetContinuation - Sets the `SNESFAS` cycle to default to exact Newton solves on the upsweep
253: Logically Collective
255: Input Parameters:
256: + snes - the `SNESFAS` nonlinear multigrid context
257: - n - the number of smoothing steps
259: Options Database Key:
260: . -snes_fas_continuation - sets continuation to true
262: Level: advanced
264: Note:
265: This sets the prefix on the upsweep smoothers to -fas_continuation
267: .seealso: `SNESFAS`, `SNESFASSetNumberSmoothUp()`
268: @*/
269: PetscErrorCode SNESFASSetContinuation(SNES snes, PetscBool continuation)
270: {
271: const char *optionsprefix;
272: char tprefix[128];
273: SNES_FAS *fas;
275: PetscFunctionBegin;
277: fas = (SNES_FAS *)snes->data;
278: PetscCall(SNESGetOptionsPrefix(fas->fine, &optionsprefix));
279: if (!fas->smoothu) PetscCall(SNESFASCycleCreateSmoother_Private(snes, &fas->smoothu));
280: PetscCall(PetscStrncpy(tprefix, "fas_levels_continuation_", sizeof(tprefix)));
281: PetscCall(SNESSetOptionsPrefix(fas->smoothu, optionsprefix));
282: PetscCall(SNESAppendOptionsPrefix(fas->smoothu, tprefix));
283: PetscCall(SNESSetType(fas->smoothu, SNESNEWTONLS));
284: PetscCall(SNESSetTolerances(fas->smoothu, fas->fine->abstol, fas->fine->rtol, fas->fine->stol, 50, 100));
285: fas->continuation = continuation;
286: if (fas->next) PetscCall(SNESFASSetContinuation(fas->next, continuation));
287: PetscFunctionReturn(PETSC_SUCCESS);
288: }
290: /*@
291: SNESFASSetCycles - Sets the number of FAS multigrid cycles to use each time a grid is visited. Use `SNESFASSetCyclesOnLevel()` for more
292: complicated cycling.
294: Logically Collective
296: Input Parameters:
297: + snes - the `SNESFAS` nonlinear multigrid context
298: - cycles - the number of cycles -- 1 for V-cycle, 2 for W-cycle
300: Options Database Key:
301: . -snes_fas_cycles <1,2> - 1 for V-cycle, 2 for W-cycle
303: Level: advanced
305: .seealso: `SNES`, `SNESFAS`, `SNESFASSetCyclesOnLevel()`
306: @*/
307: PetscErrorCode SNESFASSetCycles(SNES snes, PetscInt cycles)
308: {
309: SNES_FAS *fas;
310: PetscBool isFine;
312: PetscFunctionBegin;
314: PetscCall(SNESFASCycleIsFine(snes, &isFine));
315: fas = (SNES_FAS *)snes->data;
316: fas->n_cycles = cycles;
317: if (!isFine) PetscCall(SNESSetTolerances(snes, snes->abstol, snes->rtol, snes->stol, cycles, snes->max_funcs));
318: if (fas->next) PetscCall(SNESFASSetCycles(fas->next, cycles));
319: PetscFunctionReturn(PETSC_SUCCESS);
320: }
322: /*@
323: SNESFASSetMonitor - Sets the method-specific cycle monitoring
325: Logically Collective
327: Input Parameters:
328: + snes - the `SNESFAS` context
329: . vf - viewer and format structure (may be `NULL` if flg is `PETSC_FALSE`)
330: - flg - monitor or not
332: Level: advanced
334: .seealso: `SNESFAS`, `SNESSetMonitor()`, `SNESFASSetCyclesOnLevel()`
335: @*/
336: PetscErrorCode SNESFASSetMonitor(SNES snes, PetscViewerAndFormat *vf, PetscBool flg)
337: {
338: SNES_FAS *fas;
339: PetscBool isFine;
340: PetscInt i, levels;
341: SNES levelsnes;
343: PetscFunctionBegin;
345: PetscCall(SNESFASCycleIsFine(snes, &isFine));
346: fas = (SNES_FAS *)snes->data;
347: levels = fas->levels;
348: if (isFine) {
349: for (i = 0; i < levels; i++) {
350: PetscCall(SNESFASGetCycleSNES(snes, i, &levelsnes));
351: fas = (SNES_FAS *)levelsnes->data;
352: if (flg) {
353: /* set the monitors for the upsmoother and downsmoother */
354: PetscCall(SNESMonitorCancel(levelsnes));
355: /* Only register destroy on finest level */
356: PetscCall(SNESMonitorSet(levelsnes, (PetscErrorCode(*)(SNES, PetscInt, PetscReal, void *))SNESMonitorDefault, vf, (!i ? (PetscErrorCode(*)(void **))PetscViewerAndFormatDestroy : NULL)));
357: } else if (i != fas->levels - 1) {
358: /* unset the monitors on the coarse levels */
359: PetscCall(SNESMonitorCancel(levelsnes));
360: }
361: }
362: }
363: PetscFunctionReturn(PETSC_SUCCESS);
364: }
366: /*@
367: SNESFASSetLog - Sets or unsets time logging for various `SNESFAS` stages on all levels
369: Logically Collective
371: Input Parameters:
372: + snes - the `SNESFAS` context
373: - flg - monitor or not
375: Level: advanced
377: .seealso: `SNESFAS`, `SNESFASSetMonitor()`
378: @*/
379: PetscErrorCode SNESFASSetLog(SNES snes, PetscBool flg)
380: {
381: SNES_FAS *fas;
382: PetscBool isFine;
383: PetscInt i, levels;
384: SNES levelsnes;
385: char eventname[128];
387: PetscFunctionBegin;
389: PetscCall(SNESFASCycleIsFine(snes, &isFine));
390: fas = (SNES_FAS *)snes->data;
391: levels = fas->levels;
392: if (isFine) {
393: for (i = 0; i < levels; i++) {
394: PetscCall(SNESFASGetCycleSNES(snes, i, &levelsnes));
395: fas = (SNES_FAS *)levelsnes->data;
396: if (flg) {
397: PetscCall(PetscSNPrintf(eventname, sizeof(eventname), "FASSetup %d", (int)i));
398: PetscCall(PetscLogEventRegister(eventname, ((PetscObject)snes)->classid, &fas->eventsmoothsetup));
399: PetscCall(PetscSNPrintf(eventname, sizeof(eventname), "FASSmooth %d", (int)i));
400: PetscCall(PetscLogEventRegister(eventname, ((PetscObject)snes)->classid, &fas->eventsmoothsolve));
401: PetscCall(PetscSNPrintf(eventname, sizeof(eventname), "FASResid %d", (int)i));
402: PetscCall(PetscLogEventRegister(eventname, ((PetscObject)snes)->classid, &fas->eventresidual));
403: PetscCall(PetscSNPrintf(eventname, sizeof(eventname), "FASInterp %d", (int)i));
404: PetscCall(PetscLogEventRegister(eventname, ((PetscObject)snes)->classid, &fas->eventinterprestrict));
405: } else {
406: fas->eventsmoothsetup = 0;
407: fas->eventsmoothsolve = 0;
408: fas->eventresidual = 0;
409: fas->eventinterprestrict = 0;
410: }
411: }
412: }
413: PetscFunctionReturn(PETSC_SUCCESS);
414: }
416: /*
417: Creates the default smoother type.
419: This is SNESNRICHARDSON on each fine level and SNESNEWTONLS on the coarse level.
421: */
422: PetscErrorCode SNESFASCycleCreateSmoother_Private(SNES snes, SNES *smooth)
423: {
424: SNES_FAS *fas;
425: const char *optionsprefix;
426: char tprefix[128];
427: SNES nsmooth;
429: PetscFunctionBegin;
432: fas = (SNES_FAS *)snes->data;
433: PetscCall(SNESGetOptionsPrefix(fas->fine, &optionsprefix));
434: /* create the default smoother */
435: PetscCall(SNESCreate(PetscObjectComm((PetscObject)snes), &nsmooth));
436: if (fas->level == 0) {
437: PetscCall(PetscStrncpy(tprefix, "fas_coarse_", sizeof(tprefix)));
438: PetscCall(SNESAppendOptionsPrefix(nsmooth, optionsprefix));
439: PetscCall(SNESAppendOptionsPrefix(nsmooth, tprefix));
440: PetscCall(SNESSetType(nsmooth, SNESNEWTONLS));
441: PetscCall(SNESSetTolerances(nsmooth, nsmooth->abstol, nsmooth->rtol, nsmooth->stol, nsmooth->max_its, nsmooth->max_funcs));
442: } else {
443: PetscCall(PetscSNPrintf(tprefix, sizeof(tprefix), "fas_levels_%d_", (int)fas->level));
444: PetscCall(SNESAppendOptionsPrefix(nsmooth, optionsprefix));
445: PetscCall(SNESAppendOptionsPrefix(nsmooth, tprefix));
446: PetscCall(SNESSetType(nsmooth, SNESNRICHARDSON));
447: PetscCall(SNESSetTolerances(nsmooth, 0.0, 0.0, 0.0, fas->max_down_it, nsmooth->max_funcs));
448: }
449: PetscCall(PetscObjectIncrementTabLevel((PetscObject)nsmooth, (PetscObject)snes, 1));
450: PetscCall(PetscObjectCopyFortranFunctionPointers((PetscObject)snes, (PetscObject)nsmooth));
451: PetscCall(PetscObjectComposedDataSetInt((PetscObject)nsmooth, PetscMGLevelId, fas->level));
452: *smooth = nsmooth;
453: PetscFunctionReturn(PETSC_SUCCESS);
454: }
456: /* ------------- Functions called on a particular level ----------------- */
458: /*@
459: SNESFASCycleSetCycles - Sets the number of cycles on a particular level.
461: Logically Collective
463: Input Parameters:
464: + snes - the `SNESFAS` nonlinear multigrid context
465: . level - the level to set the number of cycles on
466: - cycles - the number of cycles -- 1 for V-cycle, 2 for W-cycle
468: Level: advanced
470: .seealso: `SNESFAS`, `SNESFASSetCycles()`
471: @*/
472: PetscErrorCode SNESFASCycleSetCycles(SNES snes, PetscInt cycles)
473: {
474: SNES_FAS *fas;
476: PetscFunctionBegin;
478: fas = (SNES_FAS *)snes->data;
479: fas->n_cycles = cycles;
480: PetscCall(SNESSetTolerances(snes, snes->abstol, snes->rtol, snes->stol, cycles, snes->max_funcs));
481: PetscFunctionReturn(PETSC_SUCCESS);
482: }
484: /*@
485: SNESFASCycleGetSmoother - Gets the smoother on a particular cycle level.
487: Logically Collective
489: Input Parameter:
490: . snes - the `SNESFAS` nonlinear multigrid context
492: Output Parameter:
493: . smooth - the smoother
495: Level: advanced
497: .seealso: `SNESFAS`, `SNESFASCycleGetSmootherUp()`, `SNESFASCycleGetSmootherDown()`
498: @*/
499: PetscErrorCode SNESFASCycleGetSmoother(SNES snes, SNES *smooth)
500: {
501: SNES_FAS *fas;
503: PetscFunctionBegin;
506: fas = (SNES_FAS *)snes->data;
507: *smooth = fas->smoothd;
508: PetscFunctionReturn(PETSC_SUCCESS);
509: }
510: /*@
511: SNESFASCycleGetSmootherUp - Gets the up smoother on a particular cycle level.
513: Logically Collective
515: Input Parameter:
516: . snes - the `SNESFAS` nonlinear multigrid context
518: Output Parameter:
519: . smoothu - the smoother
521: Note:
522: Returns the downsmoother if no up smoother is available. This enables transparent
523: default behavior in the process of the solve.
525: Level: advanced
527: .seealso: `SNESFAS`, `SNESFASCycleGetSmoother()`, `SNESFASCycleGetSmootherDown()`
528: @*/
529: PetscErrorCode SNESFASCycleGetSmootherUp(SNES snes, SNES *smoothu)
530: {
531: SNES_FAS *fas;
533: PetscFunctionBegin;
536: fas = (SNES_FAS *)snes->data;
537: if (!fas->smoothu) *smoothu = fas->smoothd;
538: else *smoothu = fas->smoothu;
539: PetscFunctionReturn(PETSC_SUCCESS);
540: }
542: /*@
543: SNESFASCycleGetSmootherDown - Gets the down smoother on a particular cycle level.
545: Logically Collective
547: Input Parameter:
548: . snes - `SNESFAS`, the nonlinear multigrid context
550: Output Parameter:
551: . smoothd - the smoother
553: Level: advanced
555: .seealso: `SNESFAS`, `SNESFASCycleGetSmootherUp()`, `SNESFASCycleGetSmoother()`
556: @*/
557: PetscErrorCode SNESFASCycleGetSmootherDown(SNES snes, SNES *smoothd)
558: {
559: SNES_FAS *fas;
561: PetscFunctionBegin;
564: fas = (SNES_FAS *)snes->data;
565: *smoothd = fas->smoothd;
566: PetscFunctionReturn(PETSC_SUCCESS);
567: }
569: /*@
570: SNESFASCycleGetCorrection - Gets the coarse correction FAS context for this level
572: Logically Collective
574: Input Parameter:
575: . snes - the `SNESFAS` nonlinear multigrid context
577: Output Parameter:
578: . correction - the coarse correction solve on this level
580: Note:
581: Returns NULL on the coarsest level.
583: Level: advanced
585: .seealso: `SNESFAS` `SNESFASCycleGetSmootherUp()`, `SNESFASCycleGetSmoother()`
586: @*/
587: PetscErrorCode SNESFASCycleGetCorrection(SNES snes, SNES *correction)
588: {
589: SNES_FAS *fas;
591: PetscFunctionBegin;
594: fas = (SNES_FAS *)snes->data;
595: *correction = fas->next;
596: PetscFunctionReturn(PETSC_SUCCESS);
597: }
599: /*@
600: SNESFASCycleGetInterpolation - Gets the interpolation on this level
602: Logically Collective
604: Input Parameter:
605: . snes - the `SNESFAS` nonlinear multigrid context
607: Output Parameter:
608: . mat - the interpolation operator on this level
610: Level: advanced
612: .seealso: `SNESFAS`, `SNESFASCycleGetSmootherUp()`, `SNESFASCycleGetSmoother()`
613: @*/
614: PetscErrorCode SNESFASCycleGetInterpolation(SNES snes, Mat *mat)
615: {
616: SNES_FAS *fas;
618: PetscFunctionBegin;
621: fas = (SNES_FAS *)snes->data;
622: *mat = fas->interpolate;
623: PetscFunctionReturn(PETSC_SUCCESS);
624: }
626: /*@
627: SNESFASCycleGetRestriction - Gets the restriction on this level
629: Logically Collective
631: Input Parameter:
632: . snes - the `SNESFAS` nonlinear multigrid context
634: Output Parameter:
635: . mat - the restriction operator on this level
637: Level: advanced
639: .seealso: `SNESFAS`, `SNESFASGetRestriction()`, `SNESFASCycleGetInterpolation()`
640: @*/
641: PetscErrorCode SNESFASCycleGetRestriction(SNES snes, Mat *mat)
642: {
643: SNES_FAS *fas;
645: PetscFunctionBegin;
648: fas = (SNES_FAS *)snes->data;
649: *mat = fas->restrct;
650: PetscFunctionReturn(PETSC_SUCCESS);
651: }
653: /*@
654: SNESFASCycleGetInjection - Gets the injection on this level
656: Logically Collective
658: Input Parameter:
659: . snes - the `SNESFAS` nonlinear multigrid context
661: Output Parameter:
662: . mat - the restriction operator on this level
664: Level: advanced
666: .seealso: `SNESFAS`, `SNESFASGetInjection()`, `SNESFASCycleGetRestriction()`
667: @*/
668: PetscErrorCode SNESFASCycleGetInjection(SNES snes, Mat *mat)
669: {
670: SNES_FAS *fas;
672: PetscFunctionBegin;
675: fas = (SNES_FAS *)snes->data;
676: *mat = fas->inject;
677: PetscFunctionReturn(PETSC_SUCCESS);
678: }
680: /*@
681: SNESFASCycleGetRScale - Gets the injection on this level
683: Logically Collective
685: Input Parameter:
686: . snes - the `SNESFAS` nonlinear multigrid context
688: Output Parameter:
689: . mat - the restriction operator on this level
691: Level: advanced
693: .seealso: `SNESFAS`, `SNESFASCycleGetRestriction()`, `SNESFASGetRScale()`
694: @*/
695: PetscErrorCode SNESFASCycleGetRScale(SNES snes, Vec *vec)
696: {
697: SNES_FAS *fas;
699: PetscFunctionBegin;
702: fas = (SNES_FAS *)snes->data;
703: *vec = fas->rscale;
704: PetscFunctionReturn(PETSC_SUCCESS);
705: }
707: /*@
708: SNESFASCycleIsFine - Determines if a given cycle is the fine level.
710: Logically Collective
712: Input Parameter:
713: . snes - the `SNESFAS` `SNES` context
715: Output Parameter:
716: . flg - indicates if this is the fine level or not
718: Level: advanced
720: .seealso: `SNESFAS`, `SNESFASSetLevels()`
721: @*/
722: PetscErrorCode SNESFASCycleIsFine(SNES snes, PetscBool *flg)
723: {
724: SNES_FAS *fas;
726: PetscFunctionBegin;
729: fas = (SNES_FAS *)snes->data;
730: if (fas->level == fas->levels - 1) *flg = PETSC_TRUE;
731: else *flg = PETSC_FALSE;
732: PetscFunctionReturn(PETSC_SUCCESS);
733: }
735: /* functions called on the finest level that return level-specific information */
737: /*@
738: SNESFASSetInterpolation - Sets the `Mat` to be used to apply the
739: interpolation from l-1 to the lth level
741: Input Parameters:
742: + snes - the `SNESFAS` nonlinear multigrid context
743: . mat - the interpolation operator
744: - level - the level (0 is coarsest) to supply [do not supply 0]
746: Level: advanced
748: Notes:
749: Usually this is the same matrix used also to set the restriction
750: for the same level.
752: One can pass in the interpolation matrix or its transpose; PETSc figures
753: out from the matrix size which one it is.
755: .seealso: `SNESFAS`, `SNESFASSetInjection()`, `SNESFASSetRestriction()`, `SNESFASSetRScale()`
756: @*/
757: PetscErrorCode SNESFASSetInterpolation(SNES snes, PetscInt level, Mat mat)
758: {
759: SNES_FAS *fas;
760: SNES levelsnes;
762: PetscFunctionBegin;
765: PetscCall(SNESFASGetCycleSNES(snes, level, &levelsnes));
766: fas = (SNES_FAS *)levelsnes->data;
767: PetscCall(PetscObjectReference((PetscObject)mat));
768: PetscCall(MatDestroy(&fas->interpolate));
769: fas->interpolate = mat;
770: PetscFunctionReturn(PETSC_SUCCESS);
771: }
773: /*@
774: SNESFASGetInterpolation - Gets the matrix used to calculate the
775: interpolation from l-1 to the lth level
777: Input Parameters:
778: + snes - the `SNESFAS` nonlinear multigrid context
779: - level - the level (0 is coarsest) to supply [do not supply 0]
781: Output Parameter:
782: . mat - the interpolation operator
784: Level: advanced
786: .seealso: `SNESFAS`, `SNESFASSetInterpolation()`, `SNESFASGetInjection()`, `SNESFASGetRestriction()`, `SNESFASGetRScale()`
787: @*/
788: PetscErrorCode SNESFASGetInterpolation(SNES snes, PetscInt level, Mat *mat)
789: {
790: SNES_FAS *fas;
791: SNES levelsnes;
793: PetscFunctionBegin;
796: PetscCall(SNESFASGetCycleSNES(snes, level, &levelsnes));
797: fas = (SNES_FAS *)levelsnes->data;
798: *mat = fas->interpolate;
799: PetscFunctionReturn(PETSC_SUCCESS);
800: }
802: /*@
803: SNESFASSetRestriction - Sets the matrix to be used to restrict the defect
804: from level l to l-1.
806: Input Parameters:
807: + snes - the `SNESFAS` nonlinear multigrid context
808: . mat - the restriction matrix
809: - level - the level (0 is coarsest) to supply [Do not supply 0]
811: Level: advanced
813: Notes:
814: Usually this is the same matrix used also to set the interpolation
815: for the same level.
817: One can pass in the interpolation matrix or its transpose; PETSc figures
818: out from the matrix size which one it is.
820: If you do not set this, the transpose of the Mat set with SNESFASSetInterpolation()
821: is used.
823: .seealso: `SNESFAS`, `SNESFASSetInterpolation()`, `SNESFASSetInjection()`
824: @*/
825: PetscErrorCode SNESFASSetRestriction(SNES snes, PetscInt level, Mat mat)
826: {
827: SNES_FAS *fas;
828: SNES levelsnes;
830: PetscFunctionBegin;
833: PetscCall(SNESFASGetCycleSNES(snes, level, &levelsnes));
834: fas = (SNES_FAS *)levelsnes->data;
835: PetscCall(PetscObjectReference((PetscObject)mat));
836: PetscCall(MatDestroy(&fas->restrct));
837: fas->restrct = mat;
838: PetscFunctionReturn(PETSC_SUCCESS);
839: }
841: /*@
842: SNESFASGetRestriction - Gets the matrix used to calculate the
843: restriction from l to the l-1th level
845: Input Parameters:
846: + snes - the `SNESFAS` nonlinear multigrid context
847: - level - the level (0 is coarsest) to supply [do not supply 0]
849: Output Parameter:
850: . mat - the interpolation operator
852: Level: advanced
854: .seealso: `SNESFAS`, `SNESFASSetRestriction()`, `SNESFASGetInjection()`, `SNESFASGetInterpolation()`, `SNESFASGetRScale()`
855: @*/
856: PetscErrorCode SNESFASGetRestriction(SNES snes, PetscInt level, Mat *mat)
857: {
858: SNES_FAS *fas;
859: SNES levelsnes;
861: PetscFunctionBegin;
864: PetscCall(SNESFASGetCycleSNES(snes, level, &levelsnes));
865: fas = (SNES_FAS *)levelsnes->data;
866: *mat = fas->restrct;
867: PetscFunctionReturn(PETSC_SUCCESS);
868: }
870: /*@
871: SNESFASSetInjection - Sets the function to be used to inject the solution
872: from level l to l-1.
874: Input Parameters:
875: + snes - the `SNESFAS` nonlinear multigrid context
876: . mat - the restriction matrix
877: - level - the level (0 is coarsest) to supply [Do not supply 0]
879: Level: advanced
881: Note:
882: If you do not set this, the restriction and rscale is used to
883: project the solution instead.
885: .seealso: `SNESFAS`, `SNESFASSetInterpolation()`, `SNESFASSetRestriction()`
886: @*/
887: PetscErrorCode SNESFASSetInjection(SNES snes, PetscInt level, Mat mat)
888: {
889: SNES_FAS *fas;
890: SNES levelsnes;
892: PetscFunctionBegin;
895: PetscCall(SNESFASGetCycleSNES(snes, level, &levelsnes));
896: fas = (SNES_FAS *)levelsnes->data;
897: PetscCall(PetscObjectReference((PetscObject)mat));
898: PetscCall(MatDestroy(&fas->inject));
900: fas->inject = mat;
901: PetscFunctionReturn(PETSC_SUCCESS);
902: }
904: /*@
905: SNESFASGetInjection - Gets the matrix used to calculate the
906: injection from l-1 to the lth level
908: Input Parameters:
909: + snes - the `SNESFAS` nonlinear multigrid context
910: - level - the level (0 is coarsest) to supply [do not supply 0]
912: Output Parameter:
913: . mat - the injection operator
915: Level: advanced
917: .seealso: `SNESFAS`, `SNESFASSetInjection()`, `SNESFASGetRestriction()`, `SNESFASGetInterpolation()`, `SNESFASGetRScale()`
918: @*/
919: PetscErrorCode SNESFASGetInjection(SNES snes, PetscInt level, Mat *mat)
920: {
921: SNES_FAS *fas;
922: SNES levelsnes;
924: PetscFunctionBegin;
927: PetscCall(SNESFASGetCycleSNES(snes, level, &levelsnes));
928: fas = (SNES_FAS *)levelsnes->data;
929: *mat = fas->inject;
930: PetscFunctionReturn(PETSC_SUCCESS);
931: }
933: /*@
934: SNESFASSetRScale - Sets the scaling factor of the restriction
935: operator from level l to l-1.
937: Input Parameters:
938: + snes - the `SNESFAS` nonlinear multigrid context
939: . rscale - the restriction scaling
940: - level - the level (0 is coarsest) to supply [Do not supply 0]
942: Level: advanced
944: Note:
945: This is only used in the case that the injection is not set.
947: .seealso: `SNESFAS`, `SNESFASSetInjection()`, `SNESFASSetRestriction()`
948: @*/
949: PetscErrorCode SNESFASSetRScale(SNES snes, PetscInt level, Vec rscale)
950: {
951: SNES_FAS *fas;
952: SNES levelsnes;
954: PetscFunctionBegin;
957: PetscCall(SNESFASGetCycleSNES(snes, level, &levelsnes));
958: fas = (SNES_FAS *)levelsnes->data;
959: PetscCall(PetscObjectReference((PetscObject)rscale));
960: PetscCall(VecDestroy(&fas->rscale));
961: fas->rscale = rscale;
962: PetscFunctionReturn(PETSC_SUCCESS);
963: }
965: /*@
966: SNESFASGetSmoother - Gets the default smoother on a level.
968: Input Parameters:
969: + snes - the `SNESFAS` nonlinear multigrid context
970: - level - the level (0 is coarsest) to supply
972: Output Parameter:
973: smooth - the smoother
975: Level: advanced
977: .seealso: `SNESFAS`, `SNESFASSetInjection()`, `SNESFASSetRestriction()`
978: @*/
979: PetscErrorCode SNESFASGetSmoother(SNES snes, PetscInt level, SNES *smooth)
980: {
981: SNES_FAS *fas;
982: SNES levelsnes;
984: PetscFunctionBegin;
987: PetscCall(SNESFASGetCycleSNES(snes, level, &levelsnes));
988: fas = (SNES_FAS *)levelsnes->data;
989: if (!fas->smoothd) PetscCall(SNESFASCycleCreateSmoother_Private(levelsnes, &fas->smoothd));
990: *smooth = fas->smoothd;
991: PetscFunctionReturn(PETSC_SUCCESS);
992: }
994: /*@
995: SNESFASGetSmootherDown - Gets the downsmoother on a level.
997: Input Parameters:
998: + snes - the `SNESFAS` nonlinear multigrid context
999: - level - the level (0 is coarsest) to supply
1001: Output Parameter:
1002: smooth - the smoother
1004: Level: advanced
1006: .seealso: `SNESFAS`, `SNESFASSetInjection()`, `SNESFASSetRestriction()`
1007: @*/
1008: PetscErrorCode SNESFASGetSmootherDown(SNES snes, PetscInt level, SNES *smooth)
1009: {
1010: SNES_FAS *fas;
1011: SNES levelsnes;
1013: PetscFunctionBegin;
1016: PetscCall(SNESFASGetCycleSNES(snes, level, &levelsnes));
1017: fas = (SNES_FAS *)levelsnes->data;
1018: /* if the user chooses to differentiate smoothers, create them both at this point */
1019: if (!fas->smoothd) PetscCall(SNESFASCycleCreateSmoother_Private(levelsnes, &fas->smoothd));
1020: if (!fas->smoothu) PetscCall(SNESFASCycleCreateSmoother_Private(levelsnes, &fas->smoothu));
1021: *smooth = fas->smoothd;
1022: PetscFunctionReturn(PETSC_SUCCESS);
1023: }
1025: /*@
1026: SNESFASGetSmootherUp - Gets the upsmoother on a level.
1028: Input Parameters:
1029: + snes - the `SNESFAS` nonlinear multigrid context
1030: - level - the level (0 is coarsest)
1032: Output Parameter:
1033: smooth - the smoother
1035: Level: advanced
1037: .seealso: `SNESFAS`, `SNESFASSetInjection()`, `SNESFASSetRestriction()`
1038: @*/
1039: PetscErrorCode SNESFASGetSmootherUp(SNES snes, PetscInt level, SNES *smooth)
1040: {
1041: SNES_FAS *fas;
1042: SNES levelsnes;
1044: PetscFunctionBegin;
1047: PetscCall(SNESFASGetCycleSNES(snes, level, &levelsnes));
1048: fas = (SNES_FAS *)levelsnes->data;
1049: /* if the user chooses to differentiate smoothers, create them both at this point */
1050: if (!fas->smoothd) PetscCall(SNESFASCycleCreateSmoother_Private(levelsnes, &fas->smoothd));
1051: if (!fas->smoothu) PetscCall(SNESFASCycleCreateSmoother_Private(levelsnes, &fas->smoothu));
1052: *smooth = fas->smoothu;
1053: PetscFunctionReturn(PETSC_SUCCESS);
1054: }
1056: /*@
1057: SNESFASGetCoarseSolve - Gets the coarsest solver.
1059: Input Parameter:
1060: . snes - the `SNESFAS` nonlinear multigrid context
1062: Output Parameter:
1063: . coarse - the coarse-level solver
1065: Level: advanced
1067: .seealso: `SNESFAS`, `SNESFASSetInjection()`, `SNESFASSetRestriction()`
1068: @*/
1069: PetscErrorCode SNESFASGetCoarseSolve(SNES snes, SNES *coarse)
1070: {
1071: SNES_FAS *fas;
1072: SNES levelsnes;
1074: PetscFunctionBegin;
1077: PetscCall(SNESFASGetCycleSNES(snes, 0, &levelsnes));
1078: fas = (SNES_FAS *)levelsnes->data;
1079: /* if the user chooses to differentiate smoothers, create them both at this point */
1080: if (!fas->smoothd) PetscCall(SNESFASCycleCreateSmoother_Private(levelsnes, &fas->smoothd));
1081: *coarse = fas->smoothd;
1082: PetscFunctionReturn(PETSC_SUCCESS);
1083: }
1085: /*@
1086: SNESFASFullSetDownSweep - Smooth during the initial downsweep for `SNESFAS`
1088: Logically Collective
1090: Input Parameters:
1091: + snes - the `SNESFAS` nonlinear multigrid context
1092: - swp - whether to downsweep or not
1094: Options Database Key:
1095: . -snes_fas_full_downsweep - Sets number of pre-smoothing steps
1097: Level: advanced
1099: .seealso: `SNESFAS`, `SNESFASSetNumberSmoothUp()`
1100: @*/
1101: PetscErrorCode SNESFASFullSetDownSweep(SNES snes, PetscBool swp)
1102: {
1103: SNES_FAS *fas;
1105: PetscFunctionBegin;
1107: fas = (SNES_FAS *)snes->data;
1108: fas->full_downsweep = swp;
1109: if (fas->next) PetscCall(SNESFASFullSetDownSweep(fas->next, swp));
1110: PetscFunctionReturn(PETSC_SUCCESS);
1111: }
1113: /*@
1114: SNESFASFullSetTotal - Use total residual restriction and total interpolation on the initial down and up sweep of full FAS cycles
1116: Logically Collective
1118: Input Parameters:
1119: + snes - the `SNESFAS` nonlinear multigrid context
1120: - total - whether to use total restriction / interpolatiaon or not (the alternative is defect restriction and correction interpolation)
1122: Options Database Key:
1123: . -snes_fas_full_total - Use total restriction and interpolation on the initial down and up sweeps for the full FAS cycle
1125: Level: advanced
1127: Note:
1128: This option is only significant if the interpolation of a coarse correction (`MatInterpolate()`) is significantly different from total
1129: solution interpolation (`DMInterpolateSolution()`).
1131: .seealso: `SNESFAS`, `SNESFASSetNumberSmoothUp()`, `DMInterpolateSolution()`
1132: @*/
1133: PetscErrorCode SNESFASFullSetTotal(SNES snes, PetscBool total)
1134: {
1135: SNES_FAS *fas;
1137: PetscFunctionBegin;
1139: fas = (SNES_FAS *)snes->data;
1140: fas->full_total = total;
1141: if (fas->next) PetscCall(SNESFASFullSetTotal(fas->next, total));
1142: PetscFunctionReturn(PETSC_SUCCESS);
1143: }
1145: /*@
1146: SNESFASFullGetTotal - Use total residual restriction and total interpolation on the initial down and up sweep of full FAS cycles
1148: Logically Collective
1150: Input Parameter:
1151: . snes - the `SNESFAS` nonlinear multigrid context
1153: Output:
1154: . total - whether to use total restriction / interpolatiaon or not (the alternative is defect restriction and correction interpolation)
1156: Level: advanced
1158: .seealso: `SNESFAS`, `SNESFASSetNumberSmoothUp()`, `DMInterpolateSolution()`, `SNESFullSetTotal()`
1159: @*/
1160: PetscErrorCode SNESFASFullGetTotal(SNES snes, PetscBool *total)
1161: {
1162: SNES_FAS *fas;
1164: PetscFunctionBegin;
1166: fas = (SNES_FAS *)snes->data;
1167: *total = fas->full_total;
1168: PetscFunctionReturn(PETSC_SUCCESS);
1169: }