Actual source code: fasfunc.c
1: #include <../src/snes/impls/fas/fasimpls.h>
3: /* -------------- functions called on the fine level -------------- */
5: /*@
6: SNESFASSetType - Sets the update and correction type used for FAS.
8: Logically Collective
10: Input Parameters:
11: + snes - FAS context
12: - fastype - SNES_FAS_ADDITIVE, SNES_FAS_MULTIPLICATIVE, SNES_FAS_FULL, or SNES_FAS_KASKADE
14: Level: intermediate
16: .seealso: PCMGSetType()
17: @*/
18: PetscErrorCode SNESFASSetType(SNES snes,SNESFASType fastype)
19: {
20: SNES_FAS *fas;
24: fas = (SNES_FAS*)snes->data;
25: fas->fastype = fastype;
26: if (fas->next) {
27: SNESFASSetType(fas->next, fastype);
28: }
29: return 0;
30: }
32: /*@
33: SNESFASGetType - Sets the update and correction type used for FAS.
35: Logically Collective
37: Input Parameters:
38: . snes - FAS context
40: Output Parameters:
41: . fastype - SNES_FAS_ADDITIVE or SNES_FAS_MULTIPLICATIVE
43: Level: intermediate
45: .seealso: PCMGSetType()
46: @*/
47: PetscErrorCode SNESFASGetType(SNES snes,SNESFASType *fastype)
48: {
49: SNES_FAS *fas;
53: fas = (SNES_FAS*)snes->data;
54: *fastype = fas->fastype;
55: return 0;
56: }
58: /*@C
59: SNESFASSetLevels - Sets the number of levels to use with FAS.
60: Must be called before any other FAS routine.
62: Input Parameters:
63: + snes - the snes context
64: . levels - the number of levels
65: - comms - optional communicators for each level; this is to allow solving the coarser
66: problems on smaller sets of processors.
68: Level: intermediate
70: Notes:
71: If the number of levels is one then the multigrid uses the -fas_levels prefix
72: for setting the level options rather than the -fas_coarse prefix.
74: .seealso: SNESFASGetLevels()
75: @*/
76: PetscErrorCode SNESFASSetLevels(SNES snes, PetscInt levels, MPI_Comm *comms)
77: {
78: PetscInt i;
79: const char *optionsprefix;
80: char tprefix[128];
81: SNES_FAS *fas;
82: SNES prevsnes;
83: MPI_Comm comm;
86: fas = (SNES_FAS*)snes->data;
87: PetscObjectGetComm((PetscObject)snes,&comm);
88: if (levels == fas->levels) {
89: if (!comms) return 0;
90: }
91: /* user has changed the number of levels; reset */
92: (*snes->ops->reset)(snes);
93: /* destroy any coarser levels if necessary */
94: SNESDestroy(&fas->next);
95: fas->next = NULL;
96: fas->previous = NULL;
97: prevsnes = snes;
98: /* setup the finest level */
99: SNESGetOptionsPrefix(snes, &optionsprefix);
100: PetscObjectComposedDataSetInt((PetscObject) snes, PetscMGLevelId, levels-1);
101: for (i = levels - 1; i >= 0; i--) {
102: if (comms) comm = comms[i];
103: fas->level = i;
104: fas->levels = levels;
105: fas->fine = snes;
106: fas->next = NULL;
107: if (i > 0) {
108: SNESCreate(comm, &fas->next);
109: SNESGetOptionsPrefix(fas->fine, &optionsprefix);
110: PetscSNPrintf(tprefix,sizeof(tprefix),"fas_levels_%d_cycle_",(int)fas->level);
111: SNESAppendOptionsPrefix(fas->next,optionsprefix);
112: SNESAppendOptionsPrefix(fas->next,tprefix);
113: SNESSetType(fas->next, SNESFAS);
114: SNESSetTolerances(fas->next, fas->next->abstol, fas->next->rtol, fas->next->stol, fas->n_cycles, fas->next->max_funcs);
115: PetscObjectIncrementTabLevel((PetscObject)fas->next, (PetscObject)snes, levels - i);
116: PetscObjectComposedDataSetInt((PetscObject) fas->next, PetscMGLevelId, i-1);
118: ((SNES_FAS*)fas->next->data)->previous = prevsnes;
120: prevsnes = fas->next;
121: fas = (SNES_FAS*)prevsnes->data;
122: }
123: }
124: return 0;
125: }
127: /*@
128: SNESFASGetLevels - Gets the number of levels in a FAS, including fine and coarse grids
130: Input Parameter:
131: . snes - the nonlinear solver context
133: Output parameter:
134: . levels - the number of levels
136: Level: advanced
138: .seealso: SNESFASSetLevels(), PCMGGetLevels()
139: @*/
140: PetscErrorCode SNESFASGetLevels(SNES snes, PetscInt *levels)
141: {
142: SNES_FAS *fas;
146: fas = (SNES_FAS*)snes->data;
147: *levels = fas->levels;
148: return 0;
149: }
151: /*@
152: SNESFASGetCycleSNES - Gets the SNES corresponding to a particular
153: level of the FAS hierarchy.
155: Input Parameters:
156: + snes - the multigrid context
157: level - the level to get
158: - lsnes - whether to use the nonlinear smoother or not
160: Level: advanced
162: .seealso: SNESFASSetLevels(), SNESFASGetLevels()
163: @*/
164: PetscErrorCode SNESFASGetCycleSNES(SNES snes,PetscInt level,SNES *lsnes)
165: {
166: SNES_FAS *fas;
167: PetscInt i;
171: fas = (SNES_FAS*)snes->data;
175: *lsnes = snes;
176: for (i = fas->level; i > level; i--) {
177: *lsnes = fas->next;
178: fas = (SNES_FAS*)(*lsnes)->data;
179: }
181: return 0;
182: }
184: /*@
185: SNESFASSetNumberSmoothUp - Sets the number of post-smoothing steps to
186: use on all levels.
188: Logically Collective on SNES
190: Input Parameters:
191: + snes - the multigrid context
192: - n - the number of smoothing steps
194: Options Database Key:
195: . -snes_fas_smoothup <n> - Sets number of pre-smoothing steps
197: Level: advanced
199: .seealso: SNESFASSetNumberSmoothDown()
200: @*/
201: PetscErrorCode SNESFASSetNumberSmoothUp(SNES snes, PetscInt n)
202: {
203: SNES_FAS *fas;
206: fas = (SNES_FAS*)snes->data;
207: fas->max_up_it = n;
208: if (!fas->smoothu && fas->level != 0) {
209: SNESFASCycleCreateSmoother_Private(snes, &fas->smoothu);
210: }
211: if (fas->smoothu) {
212: SNESSetTolerances(fas->smoothu, fas->smoothu->abstol, fas->smoothu->rtol, fas->smoothu->stol, n, fas->smoothu->max_funcs);
213: }
214: if (fas->next) {
215: SNESFASSetNumberSmoothUp(fas->next, n);
216: }
217: return 0;
218: }
220: /*@
221: SNESFASSetNumberSmoothDown - Sets the number of pre-smoothing steps to
222: use on all levels.
224: Logically Collective on SNES
226: Input Parameters:
227: + snes - the multigrid context
228: - n - the number of smoothing steps
230: Options Database Key:
231: . -snes_fas_smoothdown <n> - Sets number of pre-smoothing steps
233: Level: advanced
235: .seealso: SNESFASSetNumberSmoothUp()
236: @*/
237: PetscErrorCode SNESFASSetNumberSmoothDown(SNES snes, PetscInt n)
238: {
239: SNES_FAS *fas;
242: fas = (SNES_FAS*)snes->data;
243: if (!fas->smoothd) {
244: SNESFASCycleCreateSmoother_Private(snes, &fas->smoothd);
245: }
246: SNESSetTolerances(fas->smoothd, fas->smoothd->abstol, fas->smoothd->rtol, fas->smoothd->stol, n, fas->smoothd->max_funcs);
248: fas->max_down_it = n;
249: if (fas->next) {
250: SNESFASSetNumberSmoothDown(fas->next, n);
251: }
252: return 0;
253: }
255: /*@
256: SNESFASSetContinuation - Sets the FAS cycle to default to exact Newton solves on the upsweep
258: Logically Collective on SNES
260: Input Parameters:
261: + snes - the multigrid context
262: - n - the number of smoothing steps
264: Options Database Key:
265: . -snes_fas_continuation - sets continuation to true
267: Level: advanced
269: Notes:
270: This sets the prefix on the upsweep smoothers to -fas_continuation
272: .seealso: SNESFAS
273: @*/
274: PetscErrorCode SNESFASSetContinuation(SNES snes,PetscBool continuation)
275: {
276: const char *optionsprefix;
277: char tprefix[128];
278: SNES_FAS *fas;
281: fas = (SNES_FAS*)snes->data;
282: SNESGetOptionsPrefix(fas->fine, &optionsprefix);
283: if (!fas->smoothu) {
284: SNESFASCycleCreateSmoother_Private(snes, &fas->smoothu);
285: }
286: PetscStrncpy(tprefix,"fas_levels_continuation_",sizeof(tprefix));
287: SNESSetOptionsPrefix(fas->smoothu, optionsprefix);
288: SNESAppendOptionsPrefix(fas->smoothu, tprefix);
289: SNESSetType(fas->smoothu,SNESNEWTONLS);
290: SNESSetTolerances(fas->smoothu,fas->fine->abstol,fas->fine->rtol,fas->fine->stol,50,100);
291: fas->continuation = continuation;
292: if (fas->next) {
293: SNESFASSetContinuation(fas->next,continuation);
294: }
295: return 0;
296: }
298: /*@
299: SNESFASSetCycles - Sets the number of FAS multigrid cycles to use each time a grid is visited. Use SNESFASSetCyclesOnLevel() for more
300: complicated cycling.
302: Logically Collective on SNES
304: Input Parameters:
305: + snes - the multigrid context
306: - cycles - the number of cycles -- 1 for V-cycle, 2 for W-cycle
308: Options Database Key:
309: . -snes_fas_cycles <1,2> - 1 for V-cycle, 2 for W-cycle
311: Level: advanced
313: .seealso: SNESFASSetCyclesOnLevel()
314: @*/
315: PetscErrorCode SNESFASSetCycles(SNES snes, PetscInt cycles)
316: {
317: SNES_FAS *fas;
318: PetscBool isFine;
321: SNESFASCycleIsFine(snes, &isFine);
322: fas = (SNES_FAS*)snes->data;
323: fas->n_cycles = cycles;
324: if (!isFine) {
325: SNESSetTolerances(snes, snes->abstol, snes->rtol, snes->stol, cycles, snes->max_funcs);
326: }
327: if (fas->next) {
328: SNESFASSetCycles(fas->next, cycles);
329: }
330: return 0;
331: }
333: /*@
334: SNESFASSetMonitor - Sets the method-specific cycle monitoring
336: Logically Collective on SNES
338: Input Parameters:
339: + snes - the FAS context
340: . vf - viewer and format structure (may be NULL if flg is FALSE)
341: - flg - monitor or not
343: Level: advanced
345: .seealso: SNESFASSetCyclesOnLevel()
346: @*/
347: PetscErrorCode SNESFASSetMonitor(SNES snes, PetscViewerAndFormat *vf, PetscBool flg)
348: {
349: SNES_FAS *fas;
350: PetscBool isFine;
351: PetscInt i, levels;
352: SNES levelsnes;
355: SNESFASCycleIsFine(snes, &isFine);
356: fas = (SNES_FAS*)snes->data;
357: levels = fas->levels;
358: if (isFine) {
359: for (i = 0; i < levels; i++) {
360: SNESFASGetCycleSNES(snes, i, &levelsnes);
361: fas = (SNES_FAS*)levelsnes->data;
362: if (flg) {
363: /* set the monitors for the upsmoother and downsmoother */
364: SNESMonitorCancel(levelsnes);
365: /* Only register destroy on finest level */
366: SNESMonitorSet(levelsnes,(PetscErrorCode (*)(SNES,PetscInt,PetscReal,void*))SNESMonitorDefault,vf,(!i ? (PetscErrorCode (*)(void**))PetscViewerAndFormatDestroy : NULL));
367: } else if (i != fas->levels - 1) {
368: /* unset the monitors on the coarse levels */
369: SNESMonitorCancel(levelsnes);
370: }
371: }
372: }
373: return 0;
374: }
376: /*@
377: SNESFASSetLog - Sets or unsets time logging for various FAS stages on all levels
379: Logically Collective on SNES
381: Input Parameters:
382: + snes - the FAS context
383: - flg - monitor or not
385: Level: advanced
387: .seealso: SNESFASSetMonitor()
388: @*/
389: PetscErrorCode SNESFASSetLog(SNES snes, PetscBool flg)
390: {
391: SNES_FAS *fas;
392: PetscBool isFine;
393: PetscInt i, levels;
394: SNES levelsnes;
395: char eventname[128];
398: SNESFASCycleIsFine(snes, &isFine);
399: fas = (SNES_FAS*)snes->data;
400: levels = fas->levels;
401: if (isFine) {
402: for (i = 0; i < levels; i++) {
403: SNESFASGetCycleSNES(snes, i, &levelsnes);
404: fas = (SNES_FAS*)levelsnes->data;
405: if (flg) {
406: PetscSNPrintf(eventname,sizeof(eventname),"FASSetup %d",(int)i);
407: PetscLogEventRegister(eventname,((PetscObject)snes)->classid,&fas->eventsmoothsetup);
408: PetscSNPrintf(eventname,sizeof(eventname),"FASSmooth %d",(int)i);
409: PetscLogEventRegister(eventname,((PetscObject)snes)->classid,&fas->eventsmoothsolve);
410: PetscSNPrintf(eventname,sizeof(eventname),"FASResid %d",(int)i);
411: PetscLogEventRegister(eventname,((PetscObject)snes)->classid,&fas->eventresidual);
412: PetscSNPrintf(eventname,sizeof(eventname),"FASInterp %d",(int)i);
413: PetscLogEventRegister(eventname,((PetscObject)snes)->classid,&fas->eventinterprestrict);
414: } else {
415: fas->eventsmoothsetup = 0;
416: fas->eventsmoothsolve = 0;
417: fas->eventresidual = 0;
418: fas->eventinterprestrict = 0;
419: }
420: }
421: }
422: return 0;
423: }
425: /*
426: Creates the default smoother type.
428: This is SNESNRICHARDSON on each fine level and SNESNEWTONLS on the coarse level.
430: */
431: PetscErrorCode SNESFASCycleCreateSmoother_Private(SNES snes, SNES *smooth)
432: {
433: SNES_FAS *fas;
434: const char *optionsprefix;
435: char tprefix[128];
436: SNES nsmooth;
440: fas = (SNES_FAS*)snes->data;
441: SNESGetOptionsPrefix(fas->fine, &optionsprefix);
442: /* create the default smoother */
443: SNESCreate(PetscObjectComm((PetscObject)snes), &nsmooth);
444: if (fas->level == 0) {
445: PetscStrncpy(tprefix,"fas_coarse_",sizeof(tprefix));
446: SNESAppendOptionsPrefix(nsmooth, optionsprefix);
447: SNESAppendOptionsPrefix(nsmooth, tprefix);
448: SNESSetType(nsmooth, SNESNEWTONLS);
449: SNESSetTolerances(nsmooth, nsmooth->abstol, nsmooth->rtol, nsmooth->stol, nsmooth->max_its, nsmooth->max_funcs);
450: } else {
451: PetscSNPrintf(tprefix,sizeof(tprefix),"fas_levels_%d_",(int)fas->level);
452: SNESAppendOptionsPrefix(nsmooth, optionsprefix);
453: SNESAppendOptionsPrefix(nsmooth, tprefix);
454: SNESSetType(nsmooth, SNESNRICHARDSON);
455: SNESSetTolerances(nsmooth, 0.0, 0.0, 0.0, fas->max_down_it, nsmooth->max_funcs);
456: }
457: PetscObjectIncrementTabLevel((PetscObject)nsmooth, (PetscObject)snes, 1);
458: PetscLogObjectParent((PetscObject)snes,(PetscObject)nsmooth);
459: PetscObjectCopyFortranFunctionPointers((PetscObject)snes, (PetscObject)nsmooth);
460: PetscObjectComposedDataSetInt((PetscObject) nsmooth, PetscMGLevelId, fas->level);
461: *smooth = nsmooth;
462: return 0;
463: }
465: /* ------------- Functions called on a particular level ----------------- */
467: /*@
468: SNESFASCycleSetCycles - Sets the number of cycles on a particular level.
470: Logically Collective on SNES
472: Input Parameters:
473: + snes - the multigrid context
474: . level - the level to set the number of cycles on
475: - cycles - the number of cycles -- 1 for V-cycle, 2 for W-cycle
477: Level: advanced
479: .seealso: SNESFASSetCycles()
480: @*/
481: PetscErrorCode SNESFASCycleSetCycles(SNES snes, PetscInt cycles)
482: {
483: SNES_FAS *fas;
486: fas = (SNES_FAS*)snes->data;
487: fas->n_cycles = cycles;
488: SNESSetTolerances(snes, snes->abstol, snes->rtol, snes->stol, cycles, snes->max_funcs);
489: return 0;
490: }
492: /*@
493: SNESFASCycleGetSmoother - Gets the smoother on a particular cycle level.
495: Logically Collective on SNES
497: Input Parameters:
498: . snes - the multigrid context
500: Output Parameters:
501: . smooth - the smoother
503: Level: advanced
505: .seealso: SNESFASCycleGetSmootherUp(), SNESFASCycleGetSmootherDown()
506: @*/
507: PetscErrorCode SNESFASCycleGetSmoother(SNES snes, SNES *smooth)
508: {
509: SNES_FAS *fas;
513: fas = (SNES_FAS*)snes->data;
514: *smooth = fas->smoothd;
515: return 0;
516: }
517: /*@
518: SNESFASCycleGetSmootherUp - Gets the up smoother on a particular cycle level.
520: Logically Collective on SNES
522: Input Parameters:
523: . snes - the multigrid context
525: Output Parameters:
526: . smoothu - the smoother
528: Notes:
529: Returns the downsmoother if no up smoother is available. This enables transparent
530: default behavior in the process of the solve.
532: Level: advanced
534: .seealso: SNESFASCycleGetSmoother(), SNESFASCycleGetSmootherDown()
535: @*/
536: PetscErrorCode SNESFASCycleGetSmootherUp(SNES snes, SNES *smoothu)
537: {
538: SNES_FAS *fas;
542: fas = (SNES_FAS*)snes->data;
543: if (!fas->smoothu) *smoothu = fas->smoothd;
544: else *smoothu = fas->smoothu;
545: return 0;
546: }
548: /*@
549: SNESFASCycleGetSmootherDown - Gets the down smoother on a particular cycle level.
551: Logically Collective on SNES
553: Input Parameters:
554: . snes - the multigrid context
556: Output Parameters:
557: . smoothd - the smoother
559: Level: advanced
561: .seealso: SNESFASCycleGetSmootherUp(), SNESFASCycleGetSmoother()
562: @*/
563: PetscErrorCode SNESFASCycleGetSmootherDown(SNES snes, SNES *smoothd)
564: {
565: SNES_FAS *fas;
569: fas = (SNES_FAS*)snes->data;
570: *smoothd = fas->smoothd;
571: return 0;
572: }
574: /*@
575: SNESFASCycleGetCorrection - Gets the coarse correction FAS context for this level
577: Logically Collective on SNES
579: Input Parameters:
580: . snes - the multigrid context
582: Output Parameters:
583: . correction - the coarse correction on this level
585: Notes:
586: Returns NULL on the coarsest level.
588: Level: advanced
590: .seealso: SNESFASCycleGetSmootherUp(), SNESFASCycleGetSmoother()
591: @*/
592: PetscErrorCode SNESFASCycleGetCorrection(SNES snes, SNES *correction)
593: {
594: SNES_FAS *fas;
598: fas = (SNES_FAS*)snes->data;
599: *correction = fas->next;
600: return 0;
601: }
603: /*@
604: SNESFASCycleGetInterpolation - Gets the interpolation on this level
606: Logically Collective on SNES
608: Input Parameters:
609: . snes - the multigrid context
611: Output Parameters:
612: . mat - the interpolation operator on this level
614: Level: developer
616: .seealso: SNESFASCycleGetSmootherUp(), SNESFASCycleGetSmoother()
617: @*/
618: PetscErrorCode SNESFASCycleGetInterpolation(SNES snes, Mat *mat)
619: {
620: SNES_FAS *fas;
624: fas = (SNES_FAS*)snes->data;
625: *mat = fas->interpolate;
626: return 0;
627: }
629: /*@
630: SNESFASCycleGetRestriction - Gets the restriction on this level
632: Logically Collective on SNES
634: Input Parameters:
635: . snes - the multigrid context
637: Output Parameters:
638: . mat - the restriction operator on this level
640: Level: developer
642: .seealso: SNESFASGetRestriction(), SNESFASCycleGetInterpolation()
643: @*/
644: PetscErrorCode SNESFASCycleGetRestriction(SNES snes, Mat *mat)
645: {
646: SNES_FAS *fas;
650: fas = (SNES_FAS*)snes->data;
651: *mat = fas->restrct;
652: return 0;
653: }
655: /*@
656: SNESFASCycleGetInjection - Gets the injection on this level
658: Logically Collective on SNES
660: Input Parameters:
661: . snes - the multigrid context
663: Output Parameters:
664: . mat - the restriction operator on this level
666: Level: developer
668: .seealso: SNESFASGetInjection(), SNESFASCycleGetRestriction()
669: @*/
670: PetscErrorCode SNESFASCycleGetInjection(SNES snes, Mat *mat)
671: {
672: SNES_FAS *fas;
676: fas = (SNES_FAS*)snes->data;
677: *mat = fas->inject;
678: return 0;
679: }
681: /*@
682: SNESFASCycleGetRScale - Gets the injection on this level
684: Logically Collective on SNES
686: Input Parameters:
687: . snes - the multigrid context
689: Output Parameters:
690: . mat - the restriction operator on this level
692: Level: developer
694: .seealso: SNESFASCycleGetRestriction(), SNESFASGetRScale()
695: @*/
696: PetscErrorCode SNESFASCycleGetRScale(SNES snes, Vec *vec)
697: {
698: SNES_FAS *fas;
702: fas = (SNES_FAS*)snes->data;
703: *vec = fas->rscale;
704: return 0;
705: }
707: /*@
708: SNESFASCycleIsFine - Determines if a given cycle is the fine level.
710: Logically Collective on SNES
712: Input Parameters:
713: . snes - the FAS context
715: Output Parameters:
716: . flg - indicates if this is the fine level or not
718: Level: advanced
720: .seealso: SNESFASSetLevels()
721: @*/
722: PetscErrorCode SNESFASCycleIsFine(SNES snes, PetscBool *flg)
723: {
724: SNES_FAS *fas;
728: fas = (SNES_FAS*)snes->data;
729: if (fas->level == fas->levels - 1) *flg = PETSC_TRUE;
730: else *flg = PETSC_FALSE;
731: return 0;
732: }
734: /* ---------- functions called on the finest level that return level-specific information ---------- */
736: /*@
737: SNESFASSetInterpolation - Sets the function to be used to calculate the
738: interpolation from l-1 to the lth level
740: Input Parameters:
741: + snes - the multigrid context
742: . mat - the interpolation operator
743: - level - the level (0 is coarsest) to supply [do not supply 0]
745: Level: advanced
747: Notes:
748: Usually this is the same matrix used also to set the restriction
749: for the same level.
751: One can pass in the interpolation matrix or its transpose; PETSc figures
752: out from the matrix size which one it is.
754: .seealso: SNESFASSetInjection(), SNESFASSetRestriction(), SNESFASSetRScale()
755: @*/
756: PetscErrorCode SNESFASSetInterpolation(SNES snes, PetscInt level, Mat mat)
757: {
758: SNES_FAS *fas;
759: SNES levelsnes;
763: SNESFASGetCycleSNES(snes, level, &levelsnes);
764: fas = (SNES_FAS*)levelsnes->data;
765: PetscObjectReference((PetscObject)mat);
766: MatDestroy(&fas->interpolate);
767: fas->interpolate = mat;
768: return 0;
769: }
771: /*@
772: SNESFASGetInterpolation - Gets the matrix used to calculate the
773: interpolation from l-1 to the lth level
775: Input Parameters:
776: + snes - the multigrid context
777: - level - the level (0 is coarsest) to supply [do not supply 0]
779: Output Parameters:
780: . mat - the interpolation operator
782: Level: advanced
784: .seealso: SNESFASSetInterpolation(), SNESFASGetInjection(), SNESFASGetRestriction(), SNESFASGetRScale()
785: @*/
786: PetscErrorCode SNESFASGetInterpolation(SNES snes, PetscInt level, Mat *mat)
787: {
788: SNES_FAS *fas;
789: SNES levelsnes;
793: SNESFASGetCycleSNES(snes, level, &levelsnes);
794: fas = (SNES_FAS*)levelsnes->data;
795: *mat = fas->interpolate;
796: return 0;
797: }
799: /*@
800: SNESFASSetRestriction - Sets the function to be used to restrict the defect
801: from level l to l-1.
803: Input Parameters:
804: + snes - the 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 size which one it is.
817: If you do not set this, the transpose of the Mat set with SNESFASSetInterpolation()
818: is used.
820: .seealso: SNESFASSetInterpolation(), SNESFASSetInjection()
821: @*/
822: PetscErrorCode SNESFASSetRestriction(SNES snes, PetscInt level, Mat mat)
823: {
824: SNES_FAS *fas;
825: SNES levelsnes;
829: SNESFASGetCycleSNES(snes, level, &levelsnes);
830: fas = (SNES_FAS*)levelsnes->data;
831: PetscObjectReference((PetscObject)mat);
832: MatDestroy(&fas->restrct);
833: fas->restrct = mat;
834: return 0;
835: }
837: /*@
838: SNESFASGetRestriction - Gets the matrix used to calculate the
839: restriction from l to the l-1th level
841: Input Parameters:
842: + snes - the multigrid context
843: - level - the level (0 is coarsest) to supply [do not supply 0]
845: Output Parameters:
846: . mat - the interpolation operator
848: Level: advanced
850: .seealso: SNESFASSetRestriction(), SNESFASGetInjection(), SNESFASGetInterpolation(), SNESFASGetRScale()
851: @*/
852: PetscErrorCode SNESFASGetRestriction(SNES snes, PetscInt level, Mat *mat)
853: {
854: SNES_FAS *fas;
855: SNES levelsnes;
859: SNESFASGetCycleSNES(snes, level, &levelsnes);
860: fas = (SNES_FAS*)levelsnes->data;
861: *mat = fas->restrct;
862: return 0;
863: }
865: /*@
866: SNESFASSetInjection - Sets the function to be used to inject the solution
867: from level l to l-1.
869: Input Parameters:
870: + snes - the multigrid context
871: . mat - the restriction matrix
872: - level - the level (0 is coarsest) to supply [Do not supply 0]
874: Level: advanced
876: Notes:
877: If you do not set this, the restriction and rscale is used to
878: project the solution instead.
880: .seealso: SNESFASSetInterpolation(), SNESFASSetRestriction()
881: @*/
882: PetscErrorCode SNESFASSetInjection(SNES snes, PetscInt level, Mat mat)
883: {
884: SNES_FAS *fas;
885: SNES levelsnes;
889: SNESFASGetCycleSNES(snes, level, &levelsnes);
890: fas = (SNES_FAS*)levelsnes->data;
891: PetscObjectReference((PetscObject)mat);
892: MatDestroy(&fas->inject);
894: fas->inject = mat;
895: return 0;
896: }
898: /*@
899: SNESFASGetInjection - Gets the matrix used to calculate the
900: injection from l-1 to the lth level
902: Input Parameters:
903: + snes - the multigrid context
904: - level - the level (0 is coarsest) to supply [do not supply 0]
906: Output Parameters:
907: . mat - the injection operator
909: Level: advanced
911: .seealso: SNESFASSetInjection(), SNESFASGetRestriction(), SNESFASGetInterpolation(), SNESFASGetRScale()
912: @*/
913: PetscErrorCode SNESFASGetInjection(SNES snes, PetscInt level, Mat *mat)
914: {
915: SNES_FAS *fas;
916: SNES levelsnes;
920: SNESFASGetCycleSNES(snes, level, &levelsnes);
921: fas = (SNES_FAS*)levelsnes->data;
922: *mat = fas->inject;
923: return 0;
924: }
926: /*@
927: SNESFASSetRScale - Sets the scaling factor of the restriction
928: operator from level l to l-1.
930: Input Parameters:
931: + snes - the multigrid context
932: . rscale - the restriction scaling
933: - level - the level (0 is coarsest) to supply [Do not supply 0]
935: Level: advanced
937: Notes:
938: This is only used in the case that the injection is not set.
940: .seealso: SNESFASSetInjection(), SNESFASSetRestriction()
941: @*/
942: PetscErrorCode SNESFASSetRScale(SNES snes, PetscInt level, Vec rscale)
943: {
944: SNES_FAS *fas;
945: SNES levelsnes;
949: SNESFASGetCycleSNES(snes, level, &levelsnes);
950: fas = (SNES_FAS*)levelsnes->data;
951: PetscObjectReference((PetscObject)rscale);
952: VecDestroy(&fas->rscale);
953: fas->rscale = rscale;
954: return 0;
955: }
957: /*@
958: SNESFASGetSmoother - Gets the default smoother on a level.
960: Input Parameters:
961: + snes - the multigrid context
962: - level - the level (0 is coarsest) to supply
964: Output Parameters:
965: smooth - the smoother
967: Level: advanced
969: .seealso: SNESFASSetInjection(), SNESFASSetRestriction()
970: @*/
971: PetscErrorCode SNESFASGetSmoother(SNES snes, PetscInt level, SNES *smooth)
972: {
973: SNES_FAS *fas;
974: SNES levelsnes;
978: SNESFASGetCycleSNES(snes, level, &levelsnes);
979: fas = (SNES_FAS*)levelsnes->data;
980: if (!fas->smoothd) {
981: SNESFASCycleCreateSmoother_Private(levelsnes, &fas->smoothd);
982: }
983: *smooth = fas->smoothd;
984: return 0;
985: }
987: /*@
988: SNESFASGetSmootherDown - Gets the downsmoother on a level.
990: Input Parameters:
991: + snes - the multigrid context
992: - level - the level (0 is coarsest) to supply
994: Output Parameters:
995: smooth - the smoother
997: Level: advanced
999: .seealso: SNESFASSetInjection(), SNESFASSetRestriction()
1000: @*/
1001: PetscErrorCode SNESFASGetSmootherDown(SNES snes, PetscInt level, SNES *smooth)
1002: {
1003: SNES_FAS *fas;
1004: SNES levelsnes;
1008: SNESFASGetCycleSNES(snes, level, &levelsnes);
1009: fas = (SNES_FAS*)levelsnes->data;
1010: /* if the user chooses to differentiate smoothers, create them both at this point */
1011: if (!fas->smoothd) {
1012: SNESFASCycleCreateSmoother_Private(levelsnes, &fas->smoothd);
1013: }
1014: if (!fas->smoothu) {
1015: SNESFASCycleCreateSmoother_Private(levelsnes, &fas->smoothu);
1016: }
1017: *smooth = fas->smoothd;
1018: return 0;
1019: }
1021: /*@
1022: SNESFASGetSmootherUp - Gets the upsmoother on a level.
1024: Input Parameters:
1025: + snes - the multigrid context
1026: - level - the level (0 is coarsest)
1028: Output Parameters:
1029: smooth - the smoother
1031: Level: advanced
1033: .seealso: SNESFASSetInjection(), SNESFASSetRestriction()
1034: @*/
1035: PetscErrorCode SNESFASGetSmootherUp(SNES snes, PetscInt level, SNES *smooth)
1036: {
1037: SNES_FAS *fas;
1038: SNES levelsnes;
1042: SNESFASGetCycleSNES(snes, level, &levelsnes);
1043: fas = (SNES_FAS*)levelsnes->data;
1044: /* if the user chooses to differentiate smoothers, create them both at this point */
1045: if (!fas->smoothd) {
1046: SNESFASCycleCreateSmoother_Private(levelsnes, &fas->smoothd);
1047: }
1048: if (!fas->smoothu) {
1049: SNESFASCycleCreateSmoother_Private(levelsnes, &fas->smoothu);
1050: }
1051: *smooth = fas->smoothu;
1052: return 0;
1053: }
1055: /*@
1056: SNESFASGetCoarseSolve - Gets the coarsest solver.
1058: Input Parameters:
1059: . snes - the multigrid context
1061: Output Parameters:
1062: . coarse - the coarse-level solver
1064: Level: advanced
1066: .seealso: SNESFASSetInjection(), SNESFASSetRestriction()
1067: @*/
1068: PetscErrorCode SNESFASGetCoarseSolve(SNES snes, SNES *coarse)
1069: {
1070: SNES_FAS *fas;
1071: SNES levelsnes;
1075: SNESFASGetCycleSNES(snes, 0, &levelsnes);
1076: fas = (SNES_FAS*)levelsnes->data;
1077: /* if the user chooses to differentiate smoothers, create them both at this point */
1078: if (!fas->smoothd) {
1079: SNESFASCycleCreateSmoother_Private(levelsnes, &fas->smoothd);
1080: }
1081: *coarse = fas->smoothd;
1082: return 0;
1083: }
1085: /*@
1086: SNESFASFullSetDownSweep - Smooth during the initial downsweep for SNESFAS
1088: Logically Collective on SNES
1090: Input Parameters:
1091: + snes - the 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: SNESFASSetNumberSmoothUp()
1100: @*/
1101: PetscErrorCode SNESFASFullSetDownSweep(SNES snes,PetscBool swp)
1102: {
1103: SNES_FAS *fas;
1106: fas = (SNES_FAS*)snes->data;
1107: fas->full_downsweep = swp;
1108: if (fas->next) {
1109: SNESFASFullSetDownSweep(fas->next,swp);
1110: }
1111: return 0;
1112: }
1114: /*@
1115: SNESFASFullSetTotal - Use total residual restriction and total interpolation on the initial down and up sweep of full FAS cycles
1117: Logically Collective on SNES
1119: Input Parameters:
1120: + snes - the multigrid context
1121: - total - whether to use total restriction / interpolatiaon or not (the alternative is defect restriction and correction interpolation)
1123: Options Database Key:
1124: . -snes_fas_full_total - Use total restriction and interpolation on the initial down and up sweeps for the full FAS cycle
1126: Level: advanced
1128: Note: this option is only significant if the interpolation of a coarse correction (MatInterpolate()) is significantly different from total solution interpolation (DMInterpolateSolution()).
1130: .seealso: SNESFASSetNumberSmoothUp(), DMInterpolateSolution()
1131: @*/
1132: PetscErrorCode SNESFASFullSetTotal(SNES snes,PetscBool total)
1133: {
1134: SNES_FAS *fas;
1137: fas = (SNES_FAS*)snes->data;
1138: fas->full_total = total;
1139: if (fas->next) {
1140: SNESFASFullSetTotal(fas->next,total);
1141: }
1142: return 0;
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 on SNES
1150: Input Parameters:
1151: . snes - the 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: SNESFASSetNumberSmoothUp(), DMInterpolateSolution(), SNESFullSetTotal()
1159: @*/
1160: PetscErrorCode SNESFASFullGetTotal(SNES snes,PetscBool *total)
1161: {
1162: SNES_FAS *fas;
1165: fas = (SNES_FAS*)snes->data;
1166: *total = fas->full_total;
1167: return 0;
1168: }