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: }