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;
22: fas = (SNES_FAS *)snes->data;
23: fas->fastype = fastype;
24: if (fas->next) SNESFASSetType(fas->next, fastype);
25: return 0;
26: }
28: /*@
29: SNESFASGetType - Gets the update and correction type used for FAS.
31: Logically Collective
33: Input Parameter:
34: . snes - `SNESFAS` context
36: Output Parameter:
37: . fastype - `SNES_FAS_ADDITIVE` or `SNES_FAS_MULTIPLICATIVE`
39: Level: intermediate
41: .seealso: `SNESFAS`, `PCMGSetType()`, `SNESFASSetType()`
42: @*/
43: PetscErrorCode SNESFASGetType(SNES snes, SNESFASType *fastype)
44: {
45: SNES_FAS *fas;
49: fas = (SNES_FAS *)snes->data;
50: *fastype = fas->fastype;
51: return 0;
52: }
54: /*@C
55: SNESFASSetLevels - Sets the number of levels to use with `SNESFAS`.
56: Must be called before any other FAS routine.
58: Input Parameters:
59: + snes - the snes context
60: . levels - the number of levels
61: - comms - optional communicators for each level; this is to allow solving the coarser
62: problems on smaller sets of processors.
64: Level: intermediate
66: Note:
67: If the number of levels is one then the multigrid uses the -fas_levels prefix
68: for setting the level options rather than the -fas_coarse prefix.
70: .seealso: `SNESFAS`, `SNESFASGetLevels()`
71: @*/
72: PetscErrorCode SNESFASSetLevels(SNES snes, PetscInt levels, MPI_Comm *comms)
73: {
74: PetscInt i;
75: const char *optionsprefix;
76: char tprefix[128];
77: SNES_FAS *fas;
78: SNES prevsnes;
79: MPI_Comm comm;
82: fas = (SNES_FAS *)snes->data;
83: PetscObjectGetComm((PetscObject)snes, &comm);
84: if (levels == fas->levels) {
85: if (!comms) return 0;
86: }
87: /* user has changed the number of levels; reset */
88: PetscUseTypeMethod(snes, reset);
89: /* destroy any coarser levels if necessary */
90: SNESDestroy(&fas->next);
91: fas->next = NULL;
92: fas->previous = NULL;
93: prevsnes = snes;
94: /* setup the finest level */
95: SNESGetOptionsPrefix(snes, &optionsprefix);
96: PetscObjectComposedDataSetInt((PetscObject)snes, PetscMGLevelId, levels - 1);
97: for (i = levels - 1; i >= 0; i--) {
98: if (comms) comm = comms[i];
99: fas->level = i;
100: fas->levels = levels;
101: fas->fine = snes;
102: fas->next = NULL;
103: if (i > 0) {
104: SNESCreate(comm, &fas->next);
105: SNESGetOptionsPrefix(fas->fine, &optionsprefix);
106: PetscSNPrintf(tprefix, sizeof(tprefix), "fas_levels_%d_cycle_", (int)fas->level);
107: SNESAppendOptionsPrefix(fas->next, optionsprefix);
108: SNESAppendOptionsPrefix(fas->next, tprefix);
109: SNESSetType(fas->next, SNESFAS);
110: SNESSetTolerances(fas->next, fas->next->abstol, fas->next->rtol, fas->next->stol, fas->n_cycles, fas->next->max_funcs);
111: PetscObjectIncrementTabLevel((PetscObject)fas->next, (PetscObject)snes, levels - i);
112: PetscObjectComposedDataSetInt((PetscObject)fas->next, PetscMGLevelId, i - 1);
114: ((SNES_FAS *)fas->next->data)->previous = prevsnes;
116: prevsnes = fas->next;
117: fas = (SNES_FAS *)prevsnes->data;
118: }
119: }
120: return 0;
121: }
123: /*@
124: SNESFASGetLevels - Gets the number of levels in a `SNESFAS`, including fine and coarse grids
126: Input Parameter:
127: . snes - the `SNES` nonlinear solver context
129: Output parameter:
130: . levels - the number of levels
132: Level: advanced
134: .seealso: `SNESFAS`, `SNESFASSetLevels()`, `PCMGGetLevels()`
135: @*/
136: PetscErrorCode SNESFASGetLevels(SNES snes, PetscInt *levels)
137: {
138: SNES_FAS *fas;
142: fas = (SNES_FAS *)snes->data;
143: *levels = fas->levels;
144: return 0;
145: }
147: /*@
148: SNESFASGetCycleSNES - Gets the `SNES` corresponding to a particular
149: level of the `SNESFAS` hierarchy.
151: Input Parameters:
152: + snes - the `SNES` nonlinear multigrid context
153: - level - the level to get
155: Output Parameter:
156: . lsnes - the `SNES` for the requested level
158: Level: advanced
160: .seealso: `SNESFAS`, `SNESFASSetLevels()`, `SNESFASGetLevels()`
161: @*/
162: PetscErrorCode SNESFASGetCycleSNES(SNES snes, PetscInt level, SNES *lsnes)
163: {
164: SNES_FAS *fas;
165: PetscInt i;
169: fas = (SNES_FAS *)snes->data;
173: *lsnes = snes;
174: for (i = fas->level; i > level; i--) {
175: *lsnes = fas->next;
176: fas = (SNES_FAS *)(*lsnes)->data;
177: }
179: return 0;
180: }
182: /*@
183: SNESFASSetNumberSmoothUp - Sets the number of post-smoothing steps to
184: use on all levels.
186: Logically Collective
188: Input Parameters:
189: + snes - the `SNES` nonlinear multigrid context
190: - n - the number of smoothing steps
192: Options Database Key:
193: . -snes_fas_smoothup <n> - Sets number of pre-smoothing steps
195: Level: advanced
197: .seealso: `SNESFAS`, `SNESFASSetNumberSmoothDown()`
198: @*/
199: PetscErrorCode SNESFASSetNumberSmoothUp(SNES snes, PetscInt n)
200: {
201: SNES_FAS *fas;
204: fas = (SNES_FAS *)snes->data;
205: fas->max_up_it = n;
206: if (!fas->smoothu && fas->level != 0) SNESFASCycleCreateSmoother_Private(snes, &fas->smoothu);
207: if (fas->smoothu) SNESSetTolerances(fas->smoothu, fas->smoothu->abstol, fas->smoothu->rtol, fas->smoothu->stol, n, fas->smoothu->max_funcs);
208: if (fas->next) SNESFASSetNumberSmoothUp(fas->next, n);
209: return 0;
210: }
212: /*@
213: SNESFASSetNumberSmoothDown - Sets the number of pre-smoothing steps to
214: use on all levels.
216: Logically Collective
218: Input Parameters:
219: + snes - the `SNESFAS` nonlinear multigrid context
220: - n - the number of smoothing steps
222: Options Database Key:
223: . -snes_fas_smoothdown <n> - Sets number of pre-smoothing steps
225: Level: advanced
227: .seealso: `SNESFAS`, `SNESFASSetNumberSmoothUp()`
228: @*/
229: PetscErrorCode SNESFASSetNumberSmoothDown(SNES snes, PetscInt n)
230: {
231: SNES_FAS *fas;
234: fas = (SNES_FAS *)snes->data;
235: if (!fas->smoothd) SNESFASCycleCreateSmoother_Private(snes, &fas->smoothd);
236: SNESSetTolerances(fas->smoothd, fas->smoothd->abstol, fas->smoothd->rtol, fas->smoothd->stol, n, fas->smoothd->max_funcs);
238: fas->max_down_it = n;
239: if (fas->next) SNESFASSetNumberSmoothDown(fas->next, n);
240: return 0;
241: }
243: /*@
244: SNESFASSetContinuation - Sets the `SNESFAS` cycle to default to exact Newton solves on the upsweep
246: Logically Collective
248: Input Parameters:
249: + snes - the `SNESFAS` nonlinear multigrid context
250: - n - the number of smoothing steps
252: Options Database Key:
253: . -snes_fas_continuation - sets continuation to true
255: Level: advanced
257: Note:
258: This sets the prefix on the upsweep smoothers to -fas_continuation
260: .seealso: `SNESFAS`, `SNESFASSetNumberSmoothUp()`
261: @*/
262: PetscErrorCode SNESFASSetContinuation(SNES snes, PetscBool continuation)
263: {
264: const char *optionsprefix;
265: char tprefix[128];
266: SNES_FAS *fas;
269: fas = (SNES_FAS *)snes->data;
270: SNESGetOptionsPrefix(fas->fine, &optionsprefix);
271: if (!fas->smoothu) SNESFASCycleCreateSmoother_Private(snes, &fas->smoothu);
272: PetscStrncpy(tprefix, "fas_levels_continuation_", sizeof(tprefix));
273: SNESSetOptionsPrefix(fas->smoothu, optionsprefix);
274: SNESAppendOptionsPrefix(fas->smoothu, tprefix);
275: SNESSetType(fas->smoothu, SNESNEWTONLS);
276: SNESSetTolerances(fas->smoothu, fas->fine->abstol, fas->fine->rtol, fas->fine->stol, 50, 100);
277: fas->continuation = continuation;
278: if (fas->next) SNESFASSetContinuation(fas->next, continuation);
279: return 0;
280: }
282: /*@
283: SNESFASSetCycles - Sets the number of FAS multigrid cycles to use each time a grid is visited. Use `SNESFASSetCyclesOnLevel()` for more
284: complicated cycling.
286: Logically Collective
288: Input Parameters:
289: + snes - the `SNESFAS` nonlinear multigrid context
290: - cycles - the number of cycles -- 1 for V-cycle, 2 for W-cycle
292: Options Database Key:
293: . -snes_fas_cycles <1,2> - 1 for V-cycle, 2 for W-cycle
295: Level: advanced
297: .seealso: `SNES`, `SNESFAS`, `SNESFASSetCyclesOnLevel()`
298: @*/
299: PetscErrorCode SNESFASSetCycles(SNES snes, PetscInt cycles)
300: {
301: SNES_FAS *fas;
302: PetscBool isFine;
305: SNESFASCycleIsFine(snes, &isFine);
306: fas = (SNES_FAS *)snes->data;
307: fas->n_cycles = cycles;
308: if (!isFine) SNESSetTolerances(snes, snes->abstol, snes->rtol, snes->stol, cycles, snes->max_funcs);
309: if (fas->next) SNESFASSetCycles(fas->next, cycles);
310: return 0;
311: }
313: /*@
314: SNESFASSetMonitor - Sets the method-specific cycle monitoring
316: Logically Collective
318: Input Parameters:
319: + snes - the `SNESFAS` context
320: . vf - viewer and format structure (may be NULL if flg is FALSE)
321: - flg - monitor or not
323: Level: advanced
325: .seealso: `SNESFAS`, `SNESSetMonitor()`, `SNESFASSetCyclesOnLevel()`
326: @*/
327: PetscErrorCode SNESFASSetMonitor(SNES snes, PetscViewerAndFormat *vf, PetscBool flg)
328: {
329: SNES_FAS *fas;
330: PetscBool isFine;
331: PetscInt i, levels;
332: SNES levelsnes;
335: SNESFASCycleIsFine(snes, &isFine);
336: fas = (SNES_FAS *)snes->data;
337: levels = fas->levels;
338: if (isFine) {
339: for (i = 0; i < levels; i++) {
340: SNESFASGetCycleSNES(snes, i, &levelsnes);
341: fas = (SNES_FAS *)levelsnes->data;
342: if (flg) {
343: /* set the monitors for the upsmoother and downsmoother */
344: SNESMonitorCancel(levelsnes);
345: /* Only register destroy on finest level */
346: SNESMonitorSet(levelsnes, (PetscErrorCode(*)(SNES, PetscInt, PetscReal, void *))SNESMonitorDefault, vf, (!i ? (PetscErrorCode(*)(void **))PetscViewerAndFormatDestroy : NULL));
347: } else if (i != fas->levels - 1) {
348: /* unset the monitors on the coarse levels */
349: SNESMonitorCancel(levelsnes);
350: }
351: }
352: }
353: return 0;
354: }
356: /*@
357: SNESFASSetLog - Sets or unsets time logging for various `SNESFAS` stages on all levels
359: Logically Collective
361: Input Parameters:
362: + snes - the `SNESFAS` context
363: - flg - monitor or not
365: Level: advanced
367: .seealso: `SNESFAS`, `SNESFASSetMonitor()`
368: @*/
369: PetscErrorCode SNESFASSetLog(SNES snes, PetscBool flg)
370: {
371: SNES_FAS *fas;
372: PetscBool isFine;
373: PetscInt i, levels;
374: SNES levelsnes;
375: char eventname[128];
378: SNESFASCycleIsFine(snes, &isFine);
379: fas = (SNES_FAS *)snes->data;
380: levels = fas->levels;
381: if (isFine) {
382: for (i = 0; i < levels; i++) {
383: SNESFASGetCycleSNES(snes, i, &levelsnes);
384: fas = (SNES_FAS *)levelsnes->data;
385: if (flg) {
386: PetscSNPrintf(eventname, sizeof(eventname), "FASSetup %d", (int)i);
387: PetscLogEventRegister(eventname, ((PetscObject)snes)->classid, &fas->eventsmoothsetup);
388: PetscSNPrintf(eventname, sizeof(eventname), "FASSmooth %d", (int)i);
389: PetscLogEventRegister(eventname, ((PetscObject)snes)->classid, &fas->eventsmoothsolve);
390: PetscSNPrintf(eventname, sizeof(eventname), "FASResid %d", (int)i);
391: PetscLogEventRegister(eventname, ((PetscObject)snes)->classid, &fas->eventresidual);
392: PetscSNPrintf(eventname, sizeof(eventname), "FASInterp %d", (int)i);
393: PetscLogEventRegister(eventname, ((PetscObject)snes)->classid, &fas->eventinterprestrict);
394: } else {
395: fas->eventsmoothsetup = 0;
396: fas->eventsmoothsolve = 0;
397: fas->eventresidual = 0;
398: fas->eventinterprestrict = 0;
399: }
400: }
401: }
402: return 0;
403: }
405: /*
406: Creates the default smoother type.
408: This is SNESNRICHARDSON on each fine level and SNESNEWTONLS on the coarse level.
410: */
411: PetscErrorCode SNESFASCycleCreateSmoother_Private(SNES snes, SNES *smooth)
412: {
413: SNES_FAS *fas;
414: const char *optionsprefix;
415: char tprefix[128];
416: SNES nsmooth;
420: fas = (SNES_FAS *)snes->data;
421: SNESGetOptionsPrefix(fas->fine, &optionsprefix);
422: /* create the default smoother */
423: SNESCreate(PetscObjectComm((PetscObject)snes), &nsmooth);
424: if (fas->level == 0) {
425: PetscStrncpy(tprefix, "fas_coarse_", sizeof(tprefix));
426: SNESAppendOptionsPrefix(nsmooth, optionsprefix);
427: SNESAppendOptionsPrefix(nsmooth, tprefix);
428: SNESSetType(nsmooth, SNESNEWTONLS);
429: SNESSetTolerances(nsmooth, nsmooth->abstol, nsmooth->rtol, nsmooth->stol, nsmooth->max_its, nsmooth->max_funcs);
430: } else {
431: PetscSNPrintf(tprefix, sizeof(tprefix), "fas_levels_%d_", (int)fas->level);
432: SNESAppendOptionsPrefix(nsmooth, optionsprefix);
433: SNESAppendOptionsPrefix(nsmooth, tprefix);
434: SNESSetType(nsmooth, SNESNRICHARDSON);
435: SNESSetTolerances(nsmooth, 0.0, 0.0, 0.0, fas->max_down_it, nsmooth->max_funcs);
436: }
437: PetscObjectIncrementTabLevel((PetscObject)nsmooth, (PetscObject)snes, 1);
438: PetscObjectCopyFortranFunctionPointers((PetscObject)snes, (PetscObject)nsmooth);
439: PetscObjectComposedDataSetInt((PetscObject)nsmooth, PetscMGLevelId, fas->level);
440: *smooth = nsmooth;
441: return 0;
442: }
444: /* ------------- Functions called on a particular level ----------------- */
446: /*@
447: SNESFASCycleSetCycles - Sets the number of cycles on a particular level.
449: Logically Collective
451: Input Parameters:
452: + snes - the `SNESFAS` nonlinear multigrid context
453: . level - the level to set the number of cycles on
454: - cycles - the number of cycles -- 1 for V-cycle, 2 for W-cycle
456: Level: advanced
458: .seealso: `SNESFAS`, `SNESFASSetCycles()`
459: @*/
460: PetscErrorCode SNESFASCycleSetCycles(SNES snes, PetscInt cycles)
461: {
462: SNES_FAS *fas;
465: fas = (SNES_FAS *)snes->data;
466: fas->n_cycles = cycles;
467: SNESSetTolerances(snes, snes->abstol, snes->rtol, snes->stol, cycles, snes->max_funcs);
468: return 0;
469: }
471: /*@
472: SNESFASCycleGetSmoother - Gets the smoother on a particular cycle level.
474: Logically Collective
476: Input Parameter:
477: . snes - the `SNESFAS` nonlinear multigrid context
479: Output Parameter:
480: . smooth - the smoother
482: Level: advanced
484: .seealso: `SNESFAS`, `SNESFASCycleGetSmootherUp()`, `SNESFASCycleGetSmootherDown()`
485: @*/
486: PetscErrorCode SNESFASCycleGetSmoother(SNES snes, SNES *smooth)
487: {
488: SNES_FAS *fas;
492: fas = (SNES_FAS *)snes->data;
493: *smooth = fas->smoothd;
494: return 0;
495: }
496: /*@
497: SNESFASCycleGetSmootherUp - Gets the up smoother on a particular cycle level.
499: Logically Collective
501: Input Parameter:
502: . snes - the `SNESFAS` nonlinear multigrid context
504: Output Parameter:
505: . smoothu - the smoother
507: Note:
508: Returns the downsmoother if no up smoother is available. This enables transparent
509: default behavior in the process of the solve.
511: Level: advanced
513: .seealso: `SNESFAS`, `SNESFASCycleGetSmoother()`, `SNESFASCycleGetSmootherDown()`
514: @*/
515: PetscErrorCode SNESFASCycleGetSmootherUp(SNES snes, SNES *smoothu)
516: {
517: SNES_FAS *fas;
521: fas = (SNES_FAS *)snes->data;
522: if (!fas->smoothu) *smoothu = fas->smoothd;
523: else *smoothu = fas->smoothu;
524: return 0;
525: }
527: /*@
528: SNESFASCycleGetSmootherDown - Gets the down smoother on a particular cycle level.
530: Logically Collective
532: Input Parameter:
533: . snes - `SNESFAS`, the nonlinear multigrid context
535: Output Parameter:
536: . smoothd - the smoother
538: Level: advanced
540: .seealso: `SNESFAS`, `SNESFASCycleGetSmootherUp()`, `SNESFASCycleGetSmoother()`
541: @*/
542: PetscErrorCode SNESFASCycleGetSmootherDown(SNES snes, SNES *smoothd)
543: {
544: SNES_FAS *fas;
548: fas = (SNES_FAS *)snes->data;
549: *smoothd = fas->smoothd;
550: return 0;
551: }
553: /*@
554: SNESFASCycleGetCorrection - Gets the coarse correction FAS context for this level
556: Logically Collective
558: Input Parameter:
559: . snes - the `SNESFAS` nonlinear multigrid context
561: Output Parameter:
562: . correction - the coarse correction solve on this level
564: Note:
565: Returns NULL on the coarsest level.
567: Level: advanced
569: .seealso: `SNESFAS` `SNESFASCycleGetSmootherUp()`, `SNESFASCycleGetSmoother()`
570: @*/
571: PetscErrorCode SNESFASCycleGetCorrection(SNES snes, SNES *correction)
572: {
573: SNES_FAS *fas;
577: fas = (SNES_FAS *)snes->data;
578: *correction = fas->next;
579: return 0;
580: }
582: /*@
583: SNESFASCycleGetInterpolation - Gets the interpolation on this level
585: Logically Collective
587: Input Parameter:
588: . snes - the `SNESFAS` nonlinear multigrid context
590: Output Parameter:
591: . mat - the interpolation operator on this level
593: Level: advanced
595: .seealso: `SNESFAS`, `SNESFASCycleGetSmootherUp()`, `SNESFASCycleGetSmoother()`
596: @*/
597: PetscErrorCode SNESFASCycleGetInterpolation(SNES snes, Mat *mat)
598: {
599: SNES_FAS *fas;
603: fas = (SNES_FAS *)snes->data;
604: *mat = fas->interpolate;
605: return 0;
606: }
608: /*@
609: SNESFASCycleGetRestriction - Gets the restriction on this level
611: Logically Collective
613: Input Parameter:
614: . snes - the `SNESFAS` nonlinear multigrid context
616: Output Parameter:
617: . mat - the restriction operator on this level
619: Level: advanced
621: .seealso: `SNESFAS`, `SNESFASGetRestriction()`, `SNESFASCycleGetInterpolation()`
622: @*/
623: PetscErrorCode SNESFASCycleGetRestriction(SNES snes, Mat *mat)
624: {
625: SNES_FAS *fas;
629: fas = (SNES_FAS *)snes->data;
630: *mat = fas->restrct;
631: return 0;
632: }
634: /*@
635: SNESFASCycleGetInjection - Gets the injection on this level
637: Logically Collective
639: Input Parameter:
640: . snes - the `SNESFAS` nonlinear multigrid context
642: Output Parameter:
643: . mat - the restriction operator on this level
645: Level: advanced
647: .seealso: `SNESFAS`, `SNESFASGetInjection()`, `SNESFASCycleGetRestriction()`
648: @*/
649: PetscErrorCode SNESFASCycleGetInjection(SNES snes, Mat *mat)
650: {
651: SNES_FAS *fas;
655: fas = (SNES_FAS *)snes->data;
656: *mat = fas->inject;
657: return 0;
658: }
660: /*@
661: SNESFASCycleGetRScale - Gets the injection on this level
663: Logically Collective
665: Input Parameter:
666: . snes - the `SNESFAS` nonlinear multigrid context
668: Output Parameter:
669: . mat - the restriction operator on this level
671: Level: advanced
673: .seealso: `SNESFAS`, `SNESFASCycleGetRestriction()`, `SNESFASGetRScale()`
674: @*/
675: PetscErrorCode SNESFASCycleGetRScale(SNES snes, Vec *vec)
676: {
677: SNES_FAS *fas;
681: fas = (SNES_FAS *)snes->data;
682: *vec = fas->rscale;
683: return 0;
684: }
686: /*@
687: SNESFASCycleIsFine - Determines if a given cycle is the fine level.
689: Logically Collective
691: Input Parameter:
692: . snes - the `SNESFAS` `SNES` context
694: Output Parameter:
695: . flg - indicates if this is the fine level or not
697: Level: advanced
699: .seealso: `SNESFAS`, `SNESFASSetLevels()`
700: @*/
701: PetscErrorCode SNESFASCycleIsFine(SNES snes, PetscBool *flg)
702: {
703: SNES_FAS *fas;
707: fas = (SNES_FAS *)snes->data;
708: if (fas->level == fas->levels - 1) *flg = PETSC_TRUE;
709: else *flg = PETSC_FALSE;
710: return 0;
711: }
713: /* functions called on the finest level that return level-specific information */
715: /*@
716: SNESFASSetInterpolation - Sets the `Mat` to be used to apply the
717: interpolation from l-1 to the lth level
719: Input Parameters:
720: + snes - the `SNESFAS` nonlinear multigrid context
721: . mat - the interpolation operator
722: - level - the level (0 is coarsest) to supply [do not supply 0]
724: Level: advanced
726: Notes:
727: Usually this is the same matrix used also to set the restriction
728: for the same level.
730: One can pass in the interpolation matrix or its transpose; PETSc figures
731: out from the matrix size which one it is.
733: .seealso: `SNESFAS`, `SNESFASSetInjection()`, `SNESFASSetRestriction()`, `SNESFASSetRScale()`
734: @*/
735: PetscErrorCode SNESFASSetInterpolation(SNES snes, PetscInt level, Mat mat)
736: {
737: SNES_FAS *fas;
738: SNES levelsnes;
742: SNESFASGetCycleSNES(snes, level, &levelsnes);
743: fas = (SNES_FAS *)levelsnes->data;
744: PetscObjectReference((PetscObject)mat);
745: MatDestroy(&fas->interpolate);
746: fas->interpolate = mat;
747: return 0;
748: }
750: /*@
751: SNESFASGetInterpolation - Gets the matrix used to calculate the
752: interpolation from l-1 to the lth level
754: Input Parameters:
755: + snes - the `SNESFAS` nonlinear multigrid context
756: - level - the level (0 is coarsest) to supply [do not supply 0]
758: Output Parameter:
759: . mat - the interpolation operator
761: Level: advanced
763: .seealso: `SNESFAS`, `SNESFASSetInterpolation()`, `SNESFASGetInjection()`, `SNESFASGetRestriction()`, `SNESFASGetRScale()`
764: @*/
765: PetscErrorCode SNESFASGetInterpolation(SNES snes, PetscInt level, Mat *mat)
766: {
767: SNES_FAS *fas;
768: SNES levelsnes;
772: SNESFASGetCycleSNES(snes, level, &levelsnes);
773: fas = (SNES_FAS *)levelsnes->data;
774: *mat = fas->interpolate;
775: return 0;
776: }
778: /*@
779: SNESFASSetRestriction - Sets the matrix to be used to restrict the defect
780: from level l to l-1.
782: Input Parameters:
783: + snes - the `SNESFAS` nonlinear multigrid context
784: . mat - the restriction matrix
785: - level - the level (0 is coarsest) to supply [Do not supply 0]
787: Level: advanced
789: Notes:
790: Usually this is the same matrix used also to set the interpolation
791: for the same level.
793: One can pass in the interpolation matrix or its transpose; PETSc figures
794: out from the matrix size which one it is.
796: If you do not set this, the transpose of the Mat set with SNESFASSetInterpolation()
797: is used.
799: .seealso: `SNESFAS`, `SNESFASSetInterpolation()`, `SNESFASSetInjection()`
800: @*/
801: PetscErrorCode SNESFASSetRestriction(SNES snes, PetscInt level, Mat mat)
802: {
803: SNES_FAS *fas;
804: SNES levelsnes;
808: SNESFASGetCycleSNES(snes, level, &levelsnes);
809: fas = (SNES_FAS *)levelsnes->data;
810: PetscObjectReference((PetscObject)mat);
811: MatDestroy(&fas->restrct);
812: fas->restrct = mat;
813: return 0;
814: }
816: /*@
817: SNESFASGetRestriction - Gets the matrix used to calculate the
818: restriction from l to the l-1th level
820: Input Parameters:
821: + snes - the `SNESFAS` nonlinear multigrid context
822: - level - the level (0 is coarsest) to supply [do not supply 0]
824: Output Parameter:
825: . mat - the interpolation operator
827: Level: advanced
829: .seealso: `SNESFAS`, `SNESFASSetRestriction()`, `SNESFASGetInjection()`, `SNESFASGetInterpolation()`, `SNESFASGetRScale()`
830: @*/
831: PetscErrorCode SNESFASGetRestriction(SNES snes, PetscInt level, Mat *mat)
832: {
833: SNES_FAS *fas;
834: SNES levelsnes;
838: SNESFASGetCycleSNES(snes, level, &levelsnes);
839: fas = (SNES_FAS *)levelsnes->data;
840: *mat = fas->restrct;
841: return 0;
842: }
844: /*@
845: SNESFASSetInjection - Sets the function to be used to inject the solution
846: from level l to l-1.
848: Input Parameters:
849: + snes - the `SNESFAS` nonlinear multigrid context
850: . mat - the restriction matrix
851: - level - the level (0 is coarsest) to supply [Do not supply 0]
853: Level: advanced
855: Note:
856: If you do not set this, the restriction and rscale is used to
857: project the solution instead.
859: .seealso: `SNESFAS`, `SNESFASSetInterpolation()`, `SNESFASSetRestriction()`
860: @*/
861: PetscErrorCode SNESFASSetInjection(SNES snes, PetscInt level, Mat mat)
862: {
863: SNES_FAS *fas;
864: SNES levelsnes;
868: SNESFASGetCycleSNES(snes, level, &levelsnes);
869: fas = (SNES_FAS *)levelsnes->data;
870: PetscObjectReference((PetscObject)mat);
871: MatDestroy(&fas->inject);
873: fas->inject = mat;
874: return 0;
875: }
877: /*@
878: SNESFASGetInjection - Gets the matrix used to calculate the
879: injection from l-1 to the lth level
881: Input Parameters:
882: + snes - the `SNESFAS` nonlinear multigrid context
883: - level - the level (0 is coarsest) to supply [do not supply 0]
885: Output Parameter:
886: . mat - the injection operator
888: Level: advanced
890: .seealso: `SNESFAS`, `SNESFASSetInjection()`, `SNESFASGetRestriction()`, `SNESFASGetInterpolation()`, `SNESFASGetRScale()`
891: @*/
892: PetscErrorCode SNESFASGetInjection(SNES snes, PetscInt level, Mat *mat)
893: {
894: SNES_FAS *fas;
895: SNES levelsnes;
899: SNESFASGetCycleSNES(snes, level, &levelsnes);
900: fas = (SNES_FAS *)levelsnes->data;
901: *mat = fas->inject;
902: return 0;
903: }
905: /*@
906: SNESFASSetRScale - Sets the scaling factor of the restriction
907: operator from level l to l-1.
909: Input Parameters:
910: + snes - the `SNESFAS` nonlinear multigrid context
911: . rscale - the restriction scaling
912: - level - the level (0 is coarsest) to supply [Do not supply 0]
914: Level: advanced
916: Note:
917: This is only used in the case that the injection is not set.
919: .seealso: `SNESFAS`, `SNESFASSetInjection()`, `SNESFASSetRestriction()`
920: @*/
921: PetscErrorCode SNESFASSetRScale(SNES snes, PetscInt level, Vec rscale)
922: {
923: SNES_FAS *fas;
924: SNES levelsnes;
928: SNESFASGetCycleSNES(snes, level, &levelsnes);
929: fas = (SNES_FAS *)levelsnes->data;
930: PetscObjectReference((PetscObject)rscale);
931: VecDestroy(&fas->rscale);
932: fas->rscale = rscale;
933: return 0;
934: }
936: /*@
937: SNESFASGetSmoother - Gets the default smoother on a level.
939: Input Parameters:
940: + snes - the `SNESFAS` nonlinear multigrid context
941: - level - the level (0 is coarsest) to supply
943: Output Parameter:
944: smooth - the smoother
946: Level: advanced
948: .seealso: `SNESFAS`, `SNESFASSetInjection()`, `SNESFASSetRestriction()`
949: @*/
950: PetscErrorCode SNESFASGetSmoother(SNES snes, PetscInt level, SNES *smooth)
951: {
952: SNES_FAS *fas;
953: SNES levelsnes;
957: SNESFASGetCycleSNES(snes, level, &levelsnes);
958: fas = (SNES_FAS *)levelsnes->data;
959: if (!fas->smoothd) SNESFASCycleCreateSmoother_Private(levelsnes, &fas->smoothd);
960: *smooth = fas->smoothd;
961: return 0;
962: }
964: /*@
965: SNESFASGetSmootherDown - Gets the downsmoother on a level.
967: Input Parameters:
968: + snes - the `SNESFAS` nonlinear multigrid context
969: - level - the level (0 is coarsest) to supply
971: Output Parameter:
972: smooth - the smoother
974: Level: advanced
976: .seealso: `SNESFAS`, `SNESFASSetInjection()`, `SNESFASSetRestriction()`
977: @*/
978: PetscErrorCode SNESFASGetSmootherDown(SNES snes, PetscInt level, SNES *smooth)
979: {
980: SNES_FAS *fas;
981: SNES levelsnes;
985: SNESFASGetCycleSNES(snes, level, &levelsnes);
986: fas = (SNES_FAS *)levelsnes->data;
987: /* if the user chooses to differentiate smoothers, create them both at this point */
988: if (!fas->smoothd) SNESFASCycleCreateSmoother_Private(levelsnes, &fas->smoothd);
989: if (!fas->smoothu) SNESFASCycleCreateSmoother_Private(levelsnes, &fas->smoothu);
990: *smooth = fas->smoothd;
991: return 0;
992: }
994: /*@
995: SNESFASGetSmootherUp - Gets the upsmoother on a level.
997: Input Parameters:
998: + snes - the `SNESFAS` nonlinear multigrid context
999: - level - the level (0 is coarsest)
1001: Output Parameter:
1002: smooth - the smoother
1004: Level: advanced
1006: .seealso: `SNESFAS`, `SNESFASSetInjection()`, `SNESFASSetRestriction()`
1007: @*/
1008: PetscErrorCode SNESFASGetSmootherUp(SNES snes, PetscInt level, SNES *smooth)
1009: {
1010: SNES_FAS *fas;
1011: SNES levelsnes;
1015: SNESFASGetCycleSNES(snes, level, &levelsnes);
1016: fas = (SNES_FAS *)levelsnes->data;
1017: /* if the user chooses to differentiate smoothers, create them both at this point */
1018: if (!fas->smoothd) SNESFASCycleCreateSmoother_Private(levelsnes, &fas->smoothd);
1019: if (!fas->smoothu) SNESFASCycleCreateSmoother_Private(levelsnes, &fas->smoothu);
1020: *smooth = fas->smoothu;
1021: return 0;
1022: }
1024: /*@
1025: SNESFASGetCoarseSolve - Gets the coarsest solver.
1027: Input Parameter:
1028: . snes - the `SNESFAS` nonlinear multigrid context
1030: Output Parameter:
1031: . coarse - the coarse-level solver
1033: Level: advanced
1035: .seealso: `SNESFAS`, `SNESFASSetInjection()`, `SNESFASSetRestriction()`
1036: @*/
1037: PetscErrorCode SNESFASGetCoarseSolve(SNES snes, SNES *coarse)
1038: {
1039: SNES_FAS *fas;
1040: SNES levelsnes;
1044: SNESFASGetCycleSNES(snes, 0, &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) SNESFASCycleCreateSmoother_Private(levelsnes, &fas->smoothd);
1048: *coarse = fas->smoothd;
1049: return 0;
1050: }
1052: /*@
1053: SNESFASFullSetDownSweep - Smooth during the initial downsweep for `SNESFAS`
1055: Logically Collective
1057: Input Parameters:
1058: + snes - the `SNESFAS` nonlinear multigrid context
1059: - swp - whether to downsweep or not
1061: Options Database Key:
1062: . -snes_fas_full_downsweep - Sets number of pre-smoothing steps
1064: Level: advanced
1066: .seealso: `SNESFAS`, `SNESFASSetNumberSmoothUp()`
1067: @*/
1068: PetscErrorCode SNESFASFullSetDownSweep(SNES snes, PetscBool swp)
1069: {
1070: SNES_FAS *fas;
1073: fas = (SNES_FAS *)snes->data;
1074: fas->full_downsweep = swp;
1075: if (fas->next) SNESFASFullSetDownSweep(fas->next, swp);
1076: return 0;
1077: }
1079: /*@
1080: SNESFASFullSetTotal - Use total residual restriction and total interpolation on the initial down and up sweep of full FAS cycles
1082: Logically Collective
1084: Input Parameters:
1085: + snes - the `SNESFAS` nonlinear multigrid context
1086: - total - whether to use total restriction / interpolatiaon or not (the alternative is defect restriction and correction interpolation)
1088: Options Database Key:
1089: . -snes_fas_full_total - Use total restriction and interpolation on the initial down and up sweeps for the full FAS cycle
1091: Level: advanced
1093: Note:
1094: This option is only significant if the interpolation of a coarse correction (`MatInterpolate()`) is significantly different from total
1095: solution interpolation (`DMInterpolateSolution()`).
1097: .seealso: `SNESFAS`, `SNESFASSetNumberSmoothUp()`, `DMInterpolateSolution()`
1098: @*/
1099: PetscErrorCode SNESFASFullSetTotal(SNES snes, PetscBool total)
1100: {
1101: SNES_FAS *fas;
1104: fas = (SNES_FAS *)snes->data;
1105: fas->full_total = total;
1106: if (fas->next) SNESFASFullSetTotal(fas->next, total);
1107: return 0;
1108: }
1110: /*@
1111: SNESFASFullGetTotal - Use total residual restriction and total interpolation on the initial down and up sweep of full FAS cycles
1113: Logically Collective
1115: Input Parameter:
1116: . snes - the `SNESFAS` nonlinear multigrid context
1118: Output:
1119: . total - whether to use total restriction / interpolatiaon or not (the alternative is defect restriction and correction interpolation)
1121: Level: advanced
1123: .seealso: `SNESFAS`, `SNESFASSetNumberSmoothUp()`, `DMInterpolateSolution()`, `SNESFullSetTotal()`
1124: @*/
1125: PetscErrorCode SNESFASFullGetTotal(SNES snes, PetscBool *total)
1126: {
1127: SNES_FAS *fas;
1130: fas = (SNES_FAS *)snes->data;
1131: *total = fas->full_total;
1132: return 0;
1133: }