Actual source code: fasfunc.c

  1: #include <../src/snes/impls/fas/fasimpls.h>

  3: /*@
  4:   SNESFASSetType - Sets the update and correction type used for `SNESFAS`.

  6:   Logically Collective

  8:   Input Parameters:
  9: + snes    - `SNESFAS` context
 10: - fastype - `SNES_FAS_ADDITIVE`, `SNES_FAS_MULTIPLICATIVE`, `SNES_FAS_FULL`, or `SNES_FAS_KASKADE`

 12:   Level: intermediate

 14: .seealso: [](ch_snes), `SNES`, `SNESFAS`, `PCMGSetType()`, `SNESFASGetType()`, `SNES_FAS_ADDITIVE`, `SNES_FAS_MULTIPLICATIVE`, `SNES_FAS_FULL`, `SNES_FAS_KASKADE`
 15: @*/
 16: PetscErrorCode SNESFASSetType(SNES snes, SNESFASType fastype)
 17: {
 18:   SNES_FAS *fas;

 20:   PetscFunctionBegin;
 23:   fas          = (SNES_FAS *)snes->data;
 24:   fas->fastype = fastype;
 25:   if (fas->next) PetscCall(SNESFASSetType(fas->next, fastype));
 26:   PetscFunctionReturn(PETSC_SUCCESS);
 27: }

 29: /*@
 30:   SNESFASGetType - Gets the update and correction type used for `SNESFAS`.

 32:   Logically Collective

 34:   Input Parameter:
 35: . snes - `SNESFAS` context

 37:   Output Parameter:
 38: . fastype - `SNES_FAS_ADDITIVE`, `SNES_FAS_MULTIPLICATIVE`, `SNES_FAS_FULL`, or `SNES_FAS_KASKADE`

 40:   Level: intermediate

 42: .seealso: [](ch_snes), `SNES`, `SNESFAS`, `PCMGSetType()`, `SNESFASSetType()`, `SNES_FAS_ADDITIVE`, `SNES_FAS_MULTIPLICATIVE`, `SNES_FAS_FULL`, `SNES_FAS_KASKADE`
 43: @*/
 44: PetscErrorCode SNESFASGetType(SNES snes, SNESFASType *fastype)
 45: {
 46:   SNES_FAS *fas;

 48:   PetscFunctionBegin;
 50:   PetscAssertPointer(fastype, 2);
 51:   fas      = (SNES_FAS *)snes->data;
 52:   *fastype = fas->fastype;
 53:   PetscFunctionReturn(PETSC_SUCCESS);
 54: }

 56: /*@C
 57:   SNESFASSetLevels - Sets the number of levels to use with `SNESFAS`.
 58:   Must be called before any other `SNESFAS` routine.

 60:   Input Parameters:
 61: + snes   - the `SNES` context of `SNESType` `SNESFAS`
 62: . levels - the number of levels
 63: - comms  - optional communicators for each level; this is to allow solving the coarser
 64:             problems on smaller sets of processors.

 66:   Level: intermediate

 68:   Note:
 69:   If the number of levels is one then the solver uses the `-fas_levels` prefix
 70:   for setting the level options rather than the `-fas_coarse` prefix.

 72: .seealso: [](ch_snes), `SNES`, `SNESFAS`, `SNESFASGetLevels()`
 73: @*/
 74: PetscErrorCode SNESFASSetLevels(SNES snes, PetscInt levels, MPI_Comm *comms)
 75: {
 76:   PetscInt    i;
 77:   const char *optionsprefix;
 78:   char        tprefix[128];
 79:   SNES_FAS   *fas;
 80:   SNES        prevsnes;
 81:   MPI_Comm    comm;

 83:   PetscFunctionBegin;
 85:   fas = (SNES_FAS *)snes->data;
 86:   PetscCall(PetscObjectGetComm((PetscObject)snes, &comm));
 87:   if (levels == fas->levels) {
 88:     if (!comms) PetscFunctionReturn(PETSC_SUCCESS);
 89:   }
 90:   /* user has changed the number of levels; reset */
 91:   PetscUseTypeMethod(snes, reset);
 92:   /* destroy any coarser levels if necessary */
 93:   PetscCall(SNESDestroy(&fas->next));
 94:   fas->next     = NULL;
 95:   fas->previous = NULL;
 96:   prevsnes      = snes;
 97:   /* setup the finest level */
 98:   PetscCall(SNESGetOptionsPrefix(snes, &optionsprefix));
 99:   PetscCall(PetscObjectComposedDataSetInt((PetscObject)snes, PetscMGLevelId, levels - 1));
100:   for (i = levels - 1; i >= 0; i--) {
101:     if (comms) comm = comms[i];
102:     fas->level  = i;
103:     fas->levels = levels;
104:     fas->fine   = snes;
105:     fas->next   = NULL;
106:     if (i > 0) {
107:       PetscCall(SNESCreate(comm, &fas->next));
108:       PetscCall(SNESGetOptionsPrefix(fas->fine, &optionsprefix));
109:       PetscCall(PetscSNPrintf(tprefix, sizeof(tprefix), "fas_levels_%d_cycle_", (int)fas->level));
110:       PetscCall(SNESAppendOptionsPrefix(fas->next, optionsprefix));
111:       PetscCall(SNESAppendOptionsPrefix(fas->next, tprefix));
112:       PetscCall(SNESSetType(fas->next, SNESFAS));
113:       PetscCall(SNESSetTolerances(fas->next, fas->next->abstol, fas->next->rtol, fas->next->stol, fas->n_cycles, fas->next->max_funcs));
114:       PetscCall(PetscObjectIncrementTabLevel((PetscObject)fas->next, (PetscObject)snes, levels - i));
115:       PetscCall(PetscObjectComposedDataSetInt((PetscObject)fas->next, PetscMGLevelId, i - 1));

117:       ((SNES_FAS *)fas->next->data)->previous = prevsnes;

119:       prevsnes = fas->next;
120:       fas      = (SNES_FAS *)prevsnes->data;
121:     }
122:   }
123:   PetscFunctionReturn(PETSC_SUCCESS);
124: }

126: /*@
127:   SNESFASGetLevels - Gets the number of levels in a `SNESFAS`, including fine and coarse grids

129:   Input Parameter:
130: . snes - the `SNES` nonlinear solver context of `SNESType` `SNESFAS`

132:   Output Parameter:
133: . levels - the number of levels

135:   Level: advanced

137: .seealso: [](ch_snes), `SNES`, `SNESFAS`, `SNESFASSetLevels()`, `PCMGGetLevels()`
138: @*/
139: PetscErrorCode SNESFASGetLevels(SNES snes, PetscInt *levels)
140: {
141:   SNES_FAS *fas;

143:   PetscFunctionBegin;
145:   PetscAssertPointer(levels, 2);
146:   fas     = (SNES_FAS *)snes->data;
147:   *levels = fas->levels;
148:   PetscFunctionReturn(PETSC_SUCCESS);
149: }

151: /*@
152:   SNESFASGetCycleSNES - Gets the `SNES` corresponding to a particular level of the `SNESFAS` hierarchy

154:   Input Parameters:
155: + snes  - the `SNES` nonlinear multigrid context
156: - level - the level to get

158:   Output Parameter:
159: . lsnes - the `SNES` for the requested level

161:   Level: advanced

163: .seealso: [](ch_snes), `SNES`, `SNESFAS`, `SNESFASSetLevels()`, `SNESFASGetLevels()`
164: @*/
165: PetscErrorCode SNESFASGetCycleSNES(SNES snes, PetscInt level, SNES *lsnes)
166: {
167:   SNES_FAS *fas;
168:   PetscInt  i;

170:   PetscFunctionBegin;
172:   PetscAssertPointer(lsnes, 3);
173:   fas = (SNES_FAS *)snes->data;
174:   PetscCheck(level <= fas->levels - 1, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Requested level %" PetscInt_FMT " from SNESFAS containing %" PetscInt_FMT " levels", level, fas->levels);
175:   PetscCheck(fas->level == fas->levels - 1, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "SNESFASGetCycleSNES may only be called on the finest-level SNES");

177:   *lsnes = snes;
178:   for (i = fas->level; i > level; i--) {
179:     *lsnes = fas->next;
180:     fas    = (SNES_FAS *)(*lsnes)->data;
181:   }
182:   PetscCheck(fas->level == level, PetscObjectComm((PetscObject)snes), PETSC_ERR_PLIB, "SNESFAS level hierarchy corrupt");
183:   PetscFunctionReturn(PETSC_SUCCESS);
184: }

186: /*@
187:   SNESFASSetNumberSmoothUp - Sets the number of post-smoothing steps to
188:   use on all levels.

190:   Logically Collective

192:   Input Parameters:
193: + snes - the `SNES` nonlinear multigrid context
194: - n    - the number of smoothing steps to use

196:   Options Database Key:
197: . -snes_fas_smoothup <n> - Sets number of pre-smoothing steps

199:   Level: advanced

201: .seealso: [](ch_snes), `SNES`, `SNESFAS`, `SNESFASSetNumberSmoothDown()`
202: @*/
203: PetscErrorCode SNESFASSetNumberSmoothUp(SNES snes, PetscInt n)
204: {
205:   SNES_FAS *fas;

207:   PetscFunctionBegin;
209:   fas            = (SNES_FAS *)snes->data;
210:   fas->max_up_it = n;
211:   if (!fas->smoothu && fas->level != 0) PetscCall(SNESFASCycleCreateSmoother_Private(snes, &fas->smoothu));
212:   if (fas->smoothu) PetscCall(SNESSetTolerances(fas->smoothu, fas->smoothu->abstol, fas->smoothu->rtol, fas->smoothu->stol, n, fas->smoothu->max_funcs));
213:   if (fas->next) PetscCall(SNESFASSetNumberSmoothUp(fas->next, n));
214:   PetscFunctionReturn(PETSC_SUCCESS);
215: }

217: /*@
218:   SNESFASSetNumberSmoothDown - Sets the number of pre-smoothing steps to
219:   use on all levels.

221:   Logically Collective

223:   Input Parameters:
224: + snes - the `SNESFAS` nonlinear multigrid context
225: - n    - the number of smoothing steps to use

227:   Options Database Key:
228: . -snes_fas_smoothdown <n> - Sets number of pre-smoothing steps

230:   Level: advanced

232: .seealso: [](ch_snes), `SNES`, `SNESFAS`, `SNESFASSetNumberSmoothUp()`
233: @*/
234: PetscErrorCode SNESFASSetNumberSmoothDown(SNES snes, PetscInt n)
235: {
236:   SNES_FAS *fas;

238:   PetscFunctionBegin;
240:   fas = (SNES_FAS *)snes->data;
241:   if (!fas->smoothd) PetscCall(SNESFASCycleCreateSmoother_Private(snes, &fas->smoothd));
242:   PetscCall(SNESSetTolerances(fas->smoothd, fas->smoothd->abstol, fas->smoothd->rtol, fas->smoothd->stol, n, fas->smoothd->max_funcs));

244:   fas->max_down_it = n;
245:   if (fas->next) PetscCall(SNESFASSetNumberSmoothDown(fas->next, n));
246:   PetscFunctionReturn(PETSC_SUCCESS);
247: }

249: /*@
250:   SNESFASSetContinuation - Sets the `SNESFAS` cycle to default to using exact Newton solves on the upsweep

252:   Logically Collective

254:   Input Parameters:
255: + snes         - the `SNESFAS` nonlinear multigrid context
256: - continuation - whether to use continuation

258:   Options Database Key:
259: . -snes_fas_continuation - sets continuation to true

261:   Level: advanced

263:   Note:
264:   This sets the prefix on the upsweep smoothers to -fas_continuation

266: .seealso: [](ch_snes), `SNES`, `SNESFAS`, `SNESFASSetNumberSmoothUp()`
267: @*/
268: PetscErrorCode SNESFASSetContinuation(SNES snes, PetscBool continuation)
269: {
270:   const char *optionsprefix;
271:   char        tprefix[128];
272:   SNES_FAS   *fas;

274:   PetscFunctionBegin;
276:   fas = (SNES_FAS *)snes->data;
277:   PetscCall(SNESGetOptionsPrefix(fas->fine, &optionsprefix));
278:   if (!fas->smoothu) PetscCall(SNESFASCycleCreateSmoother_Private(snes, &fas->smoothu));
279:   PetscCall(PetscStrncpy(tprefix, "fas_levels_continuation_", sizeof(tprefix)));
280:   PetscCall(SNESSetOptionsPrefix(fas->smoothu, optionsprefix));
281:   PetscCall(SNESAppendOptionsPrefix(fas->smoothu, tprefix));
282:   PetscCall(SNESSetType(fas->smoothu, SNESNEWTONLS));
283:   PetscCall(SNESSetTolerances(fas->smoothu, fas->fine->abstol, fas->fine->rtol, fas->fine->stol, 50, 100));
284:   fas->continuation = continuation;
285:   if (fas->next) PetscCall(SNESFASSetContinuation(fas->next, continuation));
286:   PetscFunctionReturn(PETSC_SUCCESS);
287: }

289: /*@
290:   SNESFASSetCycles - Sets the number of `SNESFAS` multigrid cycles to use each time a grid is visited.  Use `SNESFASSetCyclesOnLevel()` for more
291:   complicated cycling.

293:   Logically Collective

295:   Input Parameters:
296: + snes   - the `SNESFAS` nonlinear multigrid context
297: - cycles - the number of cycles -- 1 for V-cycle, 2 for W-cycle

299:   Options Database Key:
300: . -snes_fas_cycles <1,2> - 1 for V-cycle, 2 for W-cycle

302:   Level: advanced

304: .seealso: [](ch_snes), `SNES`, `SNESFAS`, `SNESFASSetCyclesOnLevel()`
305: @*/
306: PetscErrorCode SNESFASSetCycles(SNES snes, PetscInt cycles)
307: {
308:   SNES_FAS *fas;
309:   PetscBool isFine;

311:   PetscFunctionBegin;
313:   PetscCall(SNESFASCycleIsFine(snes, &isFine));
314:   fas           = (SNES_FAS *)snes->data;
315:   fas->n_cycles = cycles;
316:   if (!isFine) PetscCall(SNESSetTolerances(snes, snes->abstol, snes->rtol, snes->stol, cycles, snes->max_funcs));
317:   if (fas->next) PetscCall(SNESFASSetCycles(fas->next, cycles));
318:   PetscFunctionReturn(PETSC_SUCCESS);
319: }

321: /*@
322:   SNESFASSetMonitor - Sets the method-specific cycle monitoring

324:   Logically Collective

326:   Input Parameters:
327: + snes - the `SNESFAS` context
328: . vf   - viewer and format structure (may be `NULL` if `flg` is `PETSC_FALSE`)
329: - flg  - monitor or not

331:   Level: advanced

333: .seealso: [](ch_snes), `SNES`, `SNESFAS`, `SNESMonitorSet()`, `SNESFASSetCyclesOnLevel()`
334: @*/
335: PetscErrorCode SNESFASSetMonitor(SNES snes, PetscViewerAndFormat *vf, PetscBool flg)
336: {
337:   SNES_FAS *fas;
338:   PetscBool isFine;
339:   PetscInt  i, levels;
340:   SNES      levelsnes;

342:   PetscFunctionBegin;
344:   PetscCall(SNESFASCycleIsFine(snes, &isFine));
345:   fas    = (SNES_FAS *)snes->data;
346:   levels = fas->levels;
347:   if (isFine) {
348:     for (i = 0; i < levels; i++) {
349:       PetscCall(SNESFASGetCycleSNES(snes, i, &levelsnes));
350:       fas = (SNES_FAS *)levelsnes->data;
351:       if (flg) {
352:         /* set the monitors for the upsmoother and downsmoother */
353:         PetscCall(SNESMonitorCancel(levelsnes));
354:         /* Only register destroy on finest level */
355:         PetscCall(SNESMonitorSet(levelsnes, (PetscErrorCode(*)(SNES, PetscInt, PetscReal, void *))SNESMonitorDefault, vf, (!i ? (PetscErrorCode(*)(void **))PetscViewerAndFormatDestroy : NULL)));
356:       } else if (i != fas->levels - 1) {
357:         /* unset the monitors on the coarse levels */
358:         PetscCall(SNESMonitorCancel(levelsnes));
359:       }
360:     }
361:   }
362:   PetscFunctionReturn(PETSC_SUCCESS);
363: }

365: /*@
366:   SNESFASSetLog - Sets or unsets time logging for various `SNESFAS` stages on all levels

368:   Logically Collective

370:   Input Parameters:
371: + snes - the `SNESFAS` context
372: - flg  - whether to log or not

374:   Level: advanced

376: .seealso: [](ch_snes), `SNES`, `SNESFAS`, `SNESFASSetMonitor()`
377: @*/
378: PetscErrorCode SNESFASSetLog(SNES snes, PetscBool flg)
379: {
380:   SNES_FAS *fas;
381:   PetscBool isFine;
382:   PetscInt  i, levels;
383:   SNES      levelsnes;
384:   char      eventname[128];

386:   PetscFunctionBegin;
388:   PetscCall(SNESFASCycleIsFine(snes, &isFine));
389:   fas    = (SNES_FAS *)snes->data;
390:   levels = fas->levels;
391:   if (isFine) {
392:     for (i = 0; i < levels; i++) {
393:       PetscCall(SNESFASGetCycleSNES(snes, i, &levelsnes));
394:       fas = (SNES_FAS *)levelsnes->data;
395:       if (flg) {
396:         PetscCall(PetscSNPrintf(eventname, sizeof(eventname), "FASSetup  %d", (int)i));
397:         PetscCall(PetscLogEventRegister(eventname, ((PetscObject)snes)->classid, &fas->eventsmoothsetup));
398:         PetscCall(PetscSNPrintf(eventname, sizeof(eventname), "FASSmooth %d", (int)i));
399:         PetscCall(PetscLogEventRegister(eventname, ((PetscObject)snes)->classid, &fas->eventsmoothsolve));
400:         PetscCall(PetscSNPrintf(eventname, sizeof(eventname), "FASResid  %d", (int)i));
401:         PetscCall(PetscLogEventRegister(eventname, ((PetscObject)snes)->classid, &fas->eventresidual));
402:         PetscCall(PetscSNPrintf(eventname, sizeof(eventname), "FASInterp %d", (int)i));
403:         PetscCall(PetscLogEventRegister(eventname, ((PetscObject)snes)->classid, &fas->eventinterprestrict));
404:       } else {
405:         fas->eventsmoothsetup    = 0;
406:         fas->eventsmoothsolve    = 0;
407:         fas->eventresidual       = 0;
408:         fas->eventinterprestrict = 0;
409:       }
410:     }
411:   }
412:   PetscFunctionReturn(PETSC_SUCCESS);
413: }

415: /*
416: Creates the default smoother type.

418: This is SNESNRICHARDSON on each fine level and SNESNEWTONLS on the coarse level.
419:  */
420: PetscErrorCode SNESFASCycleCreateSmoother_Private(SNES snes, SNES *smooth)
421: {
422:   SNES_FAS   *fas;
423:   const char *optionsprefix;
424:   char        tprefix[128];
425:   SNES        nsmooth;

427:   PetscFunctionBegin;
429:   PetscAssertPointer(smooth, 2);
430:   fas = (SNES_FAS *)snes->data;
431:   PetscCall(SNESGetOptionsPrefix(fas->fine, &optionsprefix));
432:   /* create the default smoother */
433:   PetscCall(SNESCreate(PetscObjectComm((PetscObject)snes), &nsmooth));
434:   if (fas->level == 0) {
435:     PetscCall(PetscStrncpy(tprefix, "fas_coarse_", sizeof(tprefix)));
436:     PetscCall(SNESAppendOptionsPrefix(nsmooth, optionsprefix));
437:     PetscCall(SNESAppendOptionsPrefix(nsmooth, tprefix));
438:     PetscCall(SNESSetType(nsmooth, SNESNEWTONLS));
439:     PetscCall(SNESSetTolerances(nsmooth, nsmooth->abstol, nsmooth->rtol, nsmooth->stol, nsmooth->max_its, nsmooth->max_funcs));
440:   } else {
441:     PetscCall(PetscSNPrintf(tprefix, sizeof(tprefix), "fas_levels_%d_", (int)fas->level));
442:     PetscCall(SNESAppendOptionsPrefix(nsmooth, optionsprefix));
443:     PetscCall(SNESAppendOptionsPrefix(nsmooth, tprefix));
444:     PetscCall(SNESSetType(nsmooth, SNESNRICHARDSON));
445:     PetscCall(SNESSetTolerances(nsmooth, 0.0, 0.0, 0.0, fas->max_down_it, nsmooth->max_funcs));
446:   }
447:   PetscCall(PetscObjectIncrementTabLevel((PetscObject)nsmooth, (PetscObject)snes, 1));
448:   PetscCall(PetscObjectCopyFortranFunctionPointers((PetscObject)snes, (PetscObject)nsmooth));
449:   PetscCall(PetscObjectComposedDataSetInt((PetscObject)nsmooth, PetscMGLevelId, fas->level));
450:   *smooth = nsmooth;
451:   PetscFunctionReturn(PETSC_SUCCESS);
452: }

454: /* ------------- Functions called on a particular level ----------------- */

456: /*@
457:   SNESFASCycleSetCycles - Sets the number of cycles for all levels in a `SNESFAS`

459:   Logically Collective

461:   Input Parameters:
462: + snes   - the `SNESFAS` nonlinear multigrid context
463: - cycles - the number of cycles -- 1 for V-cycle, 2 for W-cycle

465:   Level: advanced

467: .seealso: [](ch_snes), `SNES`, `SNESFAS`, `SNESFASSetCycles()`
468: @*/
469: PetscErrorCode SNESFASCycleSetCycles(SNES snes, PetscInt cycles)
470: {
471:   SNES_FAS *fas;

473:   PetscFunctionBegin;
475:   fas           = (SNES_FAS *)snes->data;
476:   fas->n_cycles = cycles;
477:   PetscCall(SNESSetTolerances(snes, snes->abstol, snes->rtol, snes->stol, cycles, snes->max_funcs));
478:   PetscFunctionReturn(PETSC_SUCCESS);
479: }

481: /*@
482:   SNESFASCycleGetSmoother - Gets the smoother on a particular cycle level.

484:   Logically Collective

486:   Input Parameter:
487: . snes - the `SNESFAS` obtained with `SNESFASGetCycleSNES()`

489:   Output Parameter:
490: . smooth - the smoother

492:   Level: advanced

494: .seealso: [](ch_snes), `SNES`, `SNESFAS`, `SNESFASCycleGetSmootherUp()`, `SNESFASCycleGetSmootherDown()`, `SNESFASGetCycleSNES()`
495: @*/
496: PetscErrorCode SNESFASCycleGetSmoother(SNES snes, SNES *smooth)
497: {
498:   SNES_FAS *fas;

500:   PetscFunctionBegin;
502:   PetscAssertPointer(smooth, 2);
503:   fas     = (SNES_FAS *)snes->data;
504:   *smooth = fas->smoothd;
505:   PetscFunctionReturn(PETSC_SUCCESS);
506: }
507: /*@
508:   SNESFASCycleGetSmootherUp - Gets the up smoother on a particular cycle level.

510:   Logically Collective

512:   Input Parameter:
513: . snes - the `SNESFAS` obtained with `SNESFASGetCycleSNES()`

515:   Output Parameter:
516: . smoothu - the smoother

518:   Level: advanced

520:   Note:
521:   Returns the downsmoother if no up smoother is available.  This enables transparent
522:   default behavior in the process of the solve.

524: .seealso: [](ch_snes), `SNES`, `SNESFAS`, `SNESFASCycleGetSmoother()`, `SNESFASCycleGetSmootherDown()`, `SNESFASGetCycleSNES()`
525: @*/
526: PetscErrorCode SNESFASCycleGetSmootherUp(SNES snes, SNES *smoothu)
527: {
528:   SNES_FAS *fas;

530:   PetscFunctionBegin;
532:   PetscAssertPointer(smoothu, 2);
533:   fas = (SNES_FAS *)snes->data;
534:   if (!fas->smoothu) *smoothu = fas->smoothd;
535:   else *smoothu = fas->smoothu;
536:   PetscFunctionReturn(PETSC_SUCCESS);
537: }

539: /*@
540:   SNESFASCycleGetSmootherDown - Gets the down smoother on a particular cycle level.

542:   Logically Collective

544:   Input Parameter:
545: . snes - `SNESFAS` obtained with `SNESFASGetCycleSNES()`

547:   Output Parameter:
548: . smoothd - the smoother

550:   Level: advanced

552: .seealso: [](ch_snes), `SNES`, `SNESFAS`, `SNESFASCycleGetSmootherUp()`, `SNESFASCycleGetSmoother()`, `SNESFASGetCycleSNES()`
553: @*/
554: PetscErrorCode SNESFASCycleGetSmootherDown(SNES snes, SNES *smoothd)
555: {
556:   SNES_FAS *fas;

558:   PetscFunctionBegin;
560:   PetscAssertPointer(smoothd, 2);
561:   fas      = (SNES_FAS *)snes->data;
562:   *smoothd = fas->smoothd;
563:   PetscFunctionReturn(PETSC_SUCCESS);
564: }

566: /*@
567:   SNESFASCycleGetCorrection - Gets the coarse correction `SNESFAS` context for this level

569:   Logically Collective

571:   Input Parameter:
572: . snes - the `SNESFAS` obtained with `SNESFASGetCycleSNES()`

574:   Output Parameter:
575: . correction - the coarse correction solve on this level

577:   Level: advanced

579:   Note:
580:   Returns `NULL` on the coarsest level.

582: .seealso: [](ch_snes), `SNES`, `SNESFAS` `SNESFASCycleGetSmootherUp()`, `SNESFASCycleGetSmoother()`
583: @*/
584: PetscErrorCode SNESFASCycleGetCorrection(SNES snes, SNES *correction)
585: {
586:   SNES_FAS *fas;

588:   PetscFunctionBegin;
590:   PetscAssertPointer(correction, 2);
591:   fas         = (SNES_FAS *)snes->data;
592:   *correction = fas->next;
593:   PetscFunctionReturn(PETSC_SUCCESS);
594: }

596: /*@
597:   SNESFASCycleGetInterpolation - Gets the interpolation on a level

599:   Logically Collective

601:   Input Parameter:
602: . snes - the `SNESFAS` obtained with `SNESFASGetCycleSNES()`

604:   Output Parameter:
605: . mat - the interpolation operator on this level

607:   Level: advanced

609: .seealso: [](ch_snes), `SNES`, `SNESFAS`, `SNESFASCycleGetSmootherUp()`, `SNESFASCycleGetSmoother()`
610: @*/
611: PetscErrorCode SNESFASCycleGetInterpolation(SNES snes, Mat *mat)
612: {
613:   SNES_FAS *fas;

615:   PetscFunctionBegin;
617:   PetscAssertPointer(mat, 2);
618:   fas  = (SNES_FAS *)snes->data;
619:   *mat = fas->interpolate;
620:   PetscFunctionReturn(PETSC_SUCCESS);
621: }

623: /*@
624:   SNESFASCycleGetRestriction - Gets the restriction on a level

626:   Logically Collective

628:   Input Parameter:
629: . snes - the `SNESFAS` obtained with `SNESFASGetCycleSNES()`

631:   Output Parameter:
632: . mat - the restriction operator on this level

634:   Level: advanced

636: .seealso: [](ch_snes), `SNES`, `SNESFAS`, `SNESFASGetRestriction()`, `SNESFASCycleGetInterpolation()`
637: @*/
638: PetscErrorCode SNESFASCycleGetRestriction(SNES snes, Mat *mat)
639: {
640:   SNES_FAS *fas;

642:   PetscFunctionBegin;
644:   PetscAssertPointer(mat, 2);
645:   fas  = (SNES_FAS *)snes->data;
646:   *mat = fas->restrct;
647:   PetscFunctionReturn(PETSC_SUCCESS);
648: }

650: /*@
651:   SNESFASCycleGetInjection - Gets the injection on a level

653:   Logically Collective

655:   Input Parameter:
656: . snes - the `SNESFAS` obtained with `SNESFASGetCycleSNES()`

658:   Output Parameter:
659: . mat - the restriction operator on this level

661:   Level: advanced

663: .seealso: [](ch_snes), `SNES`, `SNESFAS`, `SNESFASGetInjection()`, `SNESFASCycleGetRestriction()`
664: @*/
665: PetscErrorCode SNESFASCycleGetInjection(SNES snes, Mat *mat)
666: {
667:   SNES_FAS *fas;

669:   PetscFunctionBegin;
671:   PetscAssertPointer(mat, 2);
672:   fas  = (SNES_FAS *)snes->data;
673:   *mat = fas->inject;
674:   PetscFunctionReturn(PETSC_SUCCESS);
675: }

677: /*@
678:   SNESFASCycleGetRScale - Gets the injection scale-factor on a level

680:   Logically Collective

682:   Input Parameter:
683: . snes - the  `SNESFAS` obtained with `SNESFASGetCycleSNES()`

685:   Output Parameter:
686: . vec - the restriction operator on this level

688:   Level: advanced

690: .seealso: [](ch_snes), `SNES`, `SNESFAS`, `SNESFASCycleGetRestriction()`, `SNESFASGetRScale()`
691: @*/
692: PetscErrorCode SNESFASCycleGetRScale(SNES snes, Vec *vec)
693: {
694:   SNES_FAS *fas;

696:   PetscFunctionBegin;
698:   PetscAssertPointer(vec, 2);
699:   fas  = (SNES_FAS *)snes->data;
700:   *vec = fas->rscale;
701:   PetscFunctionReturn(PETSC_SUCCESS);
702: }

704: /*@
705:   SNESFASCycleIsFine - Determines if a given `SNES` is the finest level in a `SNESFAS`

707:   Logically Collective

709:   Input Parameter:
710: . snes - the `SNESFAS` context obtained with `SNESFASGetCycleSNES()`

712:   Output Parameter:
713: . flg - indicates if this is the fine level or not

715:   Level: advanced

717: .seealso: [](ch_snes), `SNES`, `SNESFAS`, `SNESFASSetLevels()`
718: @*/
719: PetscErrorCode SNESFASCycleIsFine(SNES snes, PetscBool *flg)
720: {
721:   SNES_FAS *fas;

723:   PetscFunctionBegin;
725:   PetscAssertPointer(flg, 2);
726:   fas = (SNES_FAS *)snes->data;
727:   if (fas->level == fas->levels - 1) *flg = PETSC_TRUE;
728:   else *flg = PETSC_FALSE;
729:   PetscFunctionReturn(PETSC_SUCCESS);
730: }

732: /*  functions called on the finest level that return level-specific information  */

734: /*@
735:   SNESFASSetInterpolation - Sets the `Mat` to be used to apply the
736:   interpolation from l-1 to the lth level

738:   Input Parameters:
739: + snes  - the `SNESFAS` nonlinear multigrid context
740: . mat   - the interpolation operator
741: - level - the level (0 is coarsest) to supply [do not supply 0]

743:   Level: advanced

745:   Notes:
746:   Usually this is the same matrix used also to set the restriction
747:   for the same level.

749:   One can pass in the interpolation matrix or its transpose; PETSc figures
750:   out from the matrix dimensions which one it is.

752: .seealso: [](ch_snes), `SNES`, `SNESFAS`, `SNESFASSetInjection()`, `SNESFASSetRestriction()`, `SNESFASSetRScale()`
753: @*/
754: PetscErrorCode SNESFASSetInterpolation(SNES snes, PetscInt level, Mat mat)
755: {
756:   SNES_FAS *fas;
757:   SNES      levelsnes;

759:   PetscFunctionBegin;
762:   PetscCall(SNESFASGetCycleSNES(snes, level, &levelsnes));
763:   fas = (SNES_FAS *)levelsnes->data;
764:   PetscCall(PetscObjectReference((PetscObject)mat));
765:   PetscCall(MatDestroy(&fas->interpolate));
766:   fas->interpolate = mat;
767:   PetscFunctionReturn(PETSC_SUCCESS);
768: }

770: /*@
771:   SNESFASGetInterpolation - Gets the matrix used to calculate the
772:   interpolation from l-1 to the lth level

774:   Input Parameters:
775: + snes  - the `SNESFAS` nonlinear multigrid context
776: - level - the level (0 is coarsest) to supply [do not supply 0]

778:   Output Parameter:
779: . mat - the interpolation operator

781:   Level: advanced

783: .seealso: [](ch_snes), `SNES`, `SNESFAS`, `SNESFASSetInterpolation()`, `SNESFASGetInjection()`, `SNESFASGetRestriction()`, `SNESFASGetRScale()`
784: @*/
785: PetscErrorCode SNESFASGetInterpolation(SNES snes, PetscInt level, Mat *mat)
786: {
787:   SNES_FAS *fas;
788:   SNES      levelsnes;

790:   PetscFunctionBegin;
792:   PetscAssertPointer(mat, 3);
793:   PetscCall(SNESFASGetCycleSNES(snes, level, &levelsnes));
794:   fas  = (SNES_FAS *)levelsnes->data;
795:   *mat = fas->interpolate;
796:   PetscFunctionReturn(PETSC_SUCCESS);
797: }

799: /*@
800:   SNESFASSetRestriction - Sets the matrix to be used to restrict the defect
801:   from level l to l-1.

803:   Input Parameters:
804: + snes  - the `SNESFAS` nonlinear multigrid context
805: . mat   - the restriction matrix
806: - level - the level (0 is coarsest) to supply [Do not supply 0]

808:   Level: advanced

810:   Notes:
811:   Usually this is the same matrix used also to set the interpolation
812:   for the same level.

814:   One can pass in the interpolation matrix or its transpose; PETSc figures
815:   out from the matrix dimensions which one it is.

817:   If you do not set this, the transpose of the `Mat` set with SNESFASSetInterpolation()
818:   is used.

820: .seealso: [](ch_snes), `SNES`, `SNESFAS`, `SNESFASSetInterpolation()`, `SNESFASSetInjection()`
821: @*/
822: PetscErrorCode SNESFASSetRestriction(SNES snes, PetscInt level, Mat mat)
823: {
824:   SNES_FAS *fas;
825:   SNES      levelsnes;

827:   PetscFunctionBegin;
830:   PetscCall(SNESFASGetCycleSNES(snes, level, &levelsnes));
831:   fas = (SNES_FAS *)levelsnes->data;
832:   PetscCall(PetscObjectReference((PetscObject)mat));
833:   PetscCall(MatDestroy(&fas->restrct));
834:   fas->restrct = mat;
835:   PetscFunctionReturn(PETSC_SUCCESS);
836: }

838: /*@
839:   SNESFASGetRestriction - Gets the matrix used to calculate the
840:   restriction from l to the l-1th level

842:   Input Parameters:
843: + snes  - the `SNESFAS` nonlinear multigrid context
844: - level - the level (0 is coarsest) to supply [do not supply 0]

846:   Output Parameter:
847: . mat - the interpolation operator

849:   Level: advanced

851: .seealso: [](ch_snes), `SNES`, `SNESFAS`, `SNESFASSetRestriction()`, `SNESFASGetInjection()`, `SNESFASGetInterpolation()`, `SNESFASGetRScale()`
852: @*/
853: PetscErrorCode SNESFASGetRestriction(SNES snes, PetscInt level, Mat *mat)
854: {
855:   SNES_FAS *fas;
856:   SNES      levelsnes;

858:   PetscFunctionBegin;
860:   PetscAssertPointer(mat, 3);
861:   PetscCall(SNESFASGetCycleSNES(snes, level, &levelsnes));
862:   fas  = (SNES_FAS *)levelsnes->data;
863:   *mat = fas->restrct;
864:   PetscFunctionReturn(PETSC_SUCCESS);
865: }

867: /*@
868:   SNESFASSetInjection - Sets the matrix to be used to inject the solution
869:   from `level` to `level-1`.

871:   Input Parameters:
872: + snes  - the `SNESFAS` nonlinear multigrid context
873: . mat   - the injection matrix
874: - level - the level (0 is coarsest) to supply [Do not supply 0]

876:   Level: advanced

878:   Note:
879:   If you do not set this, the restriction and rscale is used to
880:   project the solution instead.

882: .seealso: [](ch_snes), `SNES`, `SNESFAS`, `SNESFASSetInterpolation()`, `SNESFASSetRestriction()`
883: @*/
884: PetscErrorCode SNESFASSetInjection(SNES snes, PetscInt level, Mat mat)
885: {
886:   SNES_FAS *fas;
887:   SNES      levelsnes;

889:   PetscFunctionBegin;
892:   PetscCall(SNESFASGetCycleSNES(snes, level, &levelsnes));
893:   fas = (SNES_FAS *)levelsnes->data;
894:   PetscCall(PetscObjectReference((PetscObject)mat));
895:   PetscCall(MatDestroy(&fas->inject));

897:   fas->inject = mat;
898:   PetscFunctionReturn(PETSC_SUCCESS);
899: }

901: /*@
902:   SNESFASGetInjection - Gets the matrix used to calculate the
903:   injection from l-1 to the lth level

905:   Input Parameters:
906: + snes  - the `SNESFAS` nonlinear multigrid context
907: - level - the level (0 is coarsest) to supply [do not supply 0]

909:   Output Parameter:
910: . mat - the injection operator

912:   Level: advanced

914: .seealso: [](ch_snes), `SNES`, `SNESFAS`, `SNESFASSetInjection()`, `SNESFASGetRestriction()`, `SNESFASGetInterpolation()`, `SNESFASGetRScale()`
915: @*/
916: PetscErrorCode SNESFASGetInjection(SNES snes, PetscInt level, Mat *mat)
917: {
918:   SNES_FAS *fas;
919:   SNES      levelsnes;

921:   PetscFunctionBegin;
923:   PetscAssertPointer(mat, 3);
924:   PetscCall(SNESFASGetCycleSNES(snes, level, &levelsnes));
925:   fas  = (SNES_FAS *)levelsnes->data;
926:   *mat = fas->inject;
927:   PetscFunctionReturn(PETSC_SUCCESS);
928: }

930: /*@
931:   SNESFASSetRScale - Sets the scaling factor of the restriction
932:   operator from level l to l-1.

934:   Input Parameters:
935: + snes   - the `SNESFAS` nonlinear multigrid context
936: . rscale - the restriction scaling
937: - level  - the level (0 is coarsest) to supply [Do not supply 0]

939:   Level: advanced

941:   Note:
942:   This is only used when the injection is not set.

944: .seealso: [](ch_snes), `SNES`, `SNESFAS`, `SNESFASSetInjection()`, `SNESFASSetRestriction()`
945: @*/
946: PetscErrorCode SNESFASSetRScale(SNES snes, PetscInt level, Vec rscale)
947: {
948:   SNES_FAS *fas;
949:   SNES      levelsnes;

951:   PetscFunctionBegin;
954:   PetscCall(SNESFASGetCycleSNES(snes, level, &levelsnes));
955:   fas = (SNES_FAS *)levelsnes->data;
956:   PetscCall(PetscObjectReference((PetscObject)rscale));
957:   PetscCall(VecDestroy(&fas->rscale));
958:   fas->rscale = rscale;
959:   PetscFunctionReturn(PETSC_SUCCESS);
960: }

962: /*@
963:   SNESFASGetSmoother - Gets the default smoother on a level.

965:   Input Parameters:
966: + snes  - the `SNESFAS` nonlinear multigrid context
967: - level - the level (0 is coarsest) to supply

969:   Output Parameter:
970: . smooth - the smoother

972:   Level: advanced

974: .seealso: [](ch_snes), `SNES`, `SNESFAS`, `SNESFASSetInjection()`, `SNESFASSetRestriction()`
975: @*/
976: PetscErrorCode SNESFASGetSmoother(SNES snes, PetscInt level, SNES *smooth)
977: {
978:   SNES_FAS *fas;
979:   SNES      levelsnes;

981:   PetscFunctionBegin;
983:   PetscAssertPointer(smooth, 3);
984:   PetscCall(SNESFASGetCycleSNES(snes, level, &levelsnes));
985:   fas = (SNES_FAS *)levelsnes->data;
986:   if (!fas->smoothd) PetscCall(SNESFASCycleCreateSmoother_Private(levelsnes, &fas->smoothd));
987:   *smooth = fas->smoothd;
988:   PetscFunctionReturn(PETSC_SUCCESS);
989: }

991: /*@
992:   SNESFASGetSmootherDown - Gets the downsmoother on a level.

994:   Input Parameters:
995: + snes  - the `SNESFAS` nonlinear multigrid context
996: - level - the level (0 is coarsest) to supply

998:   Output Parameter:
999: . smooth - the smoother

1001:   Level: advanced

1003: .seealso: [](ch_snes), `SNES`, `SNESFAS`, `SNESFASSetInjection()`, `SNESFASSetRestriction()`
1004: @*/
1005: PetscErrorCode SNESFASGetSmootherDown(SNES snes, PetscInt level, SNES *smooth)
1006: {
1007:   SNES_FAS *fas;
1008:   SNES      levelsnes;

1010:   PetscFunctionBegin;
1012:   PetscAssertPointer(smooth, 3);
1013:   PetscCall(SNESFASGetCycleSNES(snes, level, &levelsnes));
1014:   fas = (SNES_FAS *)levelsnes->data;
1015:   /* if the user chooses to differentiate smoothers, create them both at this point */
1016:   if (!fas->smoothd) PetscCall(SNESFASCycleCreateSmoother_Private(levelsnes, &fas->smoothd));
1017:   if (!fas->smoothu) PetscCall(SNESFASCycleCreateSmoother_Private(levelsnes, &fas->smoothu));
1018:   *smooth = fas->smoothd;
1019:   PetscFunctionReturn(PETSC_SUCCESS);
1020: }

1022: /*@
1023:   SNESFASGetSmootherUp - Gets the upsmoother on a level.

1025:   Input Parameters:
1026: + snes  - the `SNESFAS` nonlinear multigrid context
1027: - level - the level (0 is coarsest)

1029:   Output Parameter:
1030: . smooth - the smoother

1032:   Level: advanced

1034: .seealso: [](ch_snes), `SNES`, `SNESFAS`, `SNESFASSetInjection()`, `SNESFASSetRestriction()`
1035: @*/
1036: PetscErrorCode SNESFASGetSmootherUp(SNES snes, PetscInt level, SNES *smooth)
1037: {
1038:   SNES_FAS *fas;
1039:   SNES      levelsnes;

1041:   PetscFunctionBegin;
1043:   PetscAssertPointer(smooth, 3);
1044:   PetscCall(SNESFASGetCycleSNES(snes, level, &levelsnes));
1045:   fas = (SNES_FAS *)levelsnes->data;
1046:   /* if the user chooses to differentiate smoothers, create them both at this point */
1047:   if (!fas->smoothd) PetscCall(SNESFASCycleCreateSmoother_Private(levelsnes, &fas->smoothd));
1048:   if (!fas->smoothu) PetscCall(SNESFASCycleCreateSmoother_Private(levelsnes, &fas->smoothu));
1049:   *smooth = fas->smoothu;
1050:   PetscFunctionReturn(PETSC_SUCCESS);
1051: }

1053: /*@
1054:   SNESFASGetCoarseSolve - Gets the coarsest level solver.

1056:   Input Parameter:
1057: . snes - the `SNESFAS` nonlinear multigrid context

1059:   Output Parameter:
1060: . coarse - the coarse-level solver

1062:   Level: advanced

1064: .seealso: [](ch_snes), `SNES`, `SNESFAS`, `SNESFASSetInjection()`, `SNESFASSetRestriction()`
1065: @*/
1066: PetscErrorCode SNESFASGetCoarseSolve(SNES snes, SNES *coarse)
1067: {
1068:   SNES_FAS *fas;
1069:   SNES      levelsnes;

1071:   PetscFunctionBegin;
1073:   PetscAssertPointer(coarse, 2);
1074:   PetscCall(SNESFASGetCycleSNES(snes, 0, &levelsnes));
1075:   fas = (SNES_FAS *)levelsnes->data;
1076:   /* if the user chooses to differentiate smoothers, create them both at this point */
1077:   if (!fas->smoothd) PetscCall(SNESFASCycleCreateSmoother_Private(levelsnes, &fas->smoothd));
1078:   *coarse = fas->smoothd;
1079:   PetscFunctionReturn(PETSC_SUCCESS);
1080: }

1082: /*@
1083:   SNESFASFullSetDownSweep - Smooth during the initial downsweep for `SNESFAS`

1085:   Logically Collective

1087:   Input Parameters:
1088: + snes - the `SNESFAS` nonlinear multigrid context
1089: - swp  - whether to downsweep or not

1091:   Options Database Key:
1092: . -snes_fas_full_downsweep - Sets whether to smooth on the initial downsweep

1094:   Level: advanced

1096: .seealso: [](ch_snes), `SNES`, `SNESFAS`, `SNESFASSetNumberSmoothUp()`
1097: @*/
1098: PetscErrorCode SNESFASFullSetDownSweep(SNES snes, PetscBool swp)
1099: {
1100:   SNES_FAS *fas;

1102:   PetscFunctionBegin;
1104:   fas                 = (SNES_FAS *)snes->data;
1105:   fas->full_downsweep = swp;
1106:   if (fas->next) PetscCall(SNESFASFullSetDownSweep(fas->next, swp));
1107:   PetscFunctionReturn(PETSC_SUCCESS);
1108: }

1110: /*@
1111:   SNESFASFullSetTotal - Use total residual restriction and total interpolation on the initial down and up sweep of full `SNESFAS` cycles

1113:   Logically Collective

1115:   Input Parameters:
1116: + snes  - the `SNESFAS`  nonlinear multigrid context
1117: - total - whether to use total restriction / interpolatiaon or not (the alternative is defect restriction and correction interpolation)

1119:   Options Database Key:
1120: . -snes_fas_full_total - Use total restriction and interpolation on the initial down and up sweeps for the full `SNESFAS` cycle

1122:   Level: advanced

1124:   Note:
1125:   This option is only significant if the interpolation of a coarse correction (`MatInterpolate()`) is significantly different from total
1126:   solution interpolation (`DMInterpolateSolution()`).

1128: .seealso: [](ch_snes), `SNES`, `SNESFAS`, `SNESFASSetNumberSmoothUp()`, `DMInterpolateSolution()`
1129: @*/
1130: PetscErrorCode SNESFASFullSetTotal(SNES snes, PetscBool total)
1131: {
1132:   SNES_FAS *fas;

1134:   PetscFunctionBegin;
1136:   fas             = (SNES_FAS *)snes->data;
1137:   fas->full_total = total;
1138:   if (fas->next) PetscCall(SNESFASFullSetTotal(fas->next, total));
1139:   PetscFunctionReturn(PETSC_SUCCESS);
1140: }

1142: /*@
1143:   SNESFASFullGetTotal - Use total residual restriction and total interpolation on the initial down and up sweep of full FAS cycles

1145:   Logically Collective

1147:   Input Parameter:
1148: . snes - the `SNESFAS` nonlinear multigrid context

1150:   Output Parameter:
1151: . total - whether to use total restriction / interpolatiaon or not (the alternative is defect restriction and correction interpolation)

1153:   Level: advanced

1155: .seealso: [](ch_snes), `SNES`, `SNESFAS`, `SNESFASSetNumberSmoothUp()`, `DMInterpolateSolution()`, `SNESFullSetTotal()`
1156: @*/
1157: PetscErrorCode SNESFASFullGetTotal(SNES snes, PetscBool *total)
1158: {
1159:   SNES_FAS *fas;

1161:   PetscFunctionBegin;
1163:   fas    = (SNES_FAS *)snes->data;
1164:   *total = fas->full_total;
1165:   PetscFunctionReturn(PETSC_SUCCESS);
1166: }