Actual source code: fasfunc.c
petsc-3.13.6 2020-09-29
Report Typos and Errors

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

      4: /* -------------- functions called on the fine level -------------- */

      6: /*@
      7:     SNESFASSetType - Sets the update and correction type used for FAS.

      9:    Logically Collective

     11: Input Parameters:
     12: + snes  - FAS context
     13: - fastype  - SNES_FAS_ADDITIVE, SNES_FAS_MULTIPLICATIVE, SNES_FAS_FULL, or SNES_FAS_KASKADE

     15: Level: intermediate

     17: .seealso: PCMGSetType()
     18: @*/
     19: PetscErrorCode  SNESFASSetType(SNES snes,SNESFASType fastype)
     20: {
     21:   SNES_FAS       *fas;

     27:   fas = (SNES_FAS*)snes->data;
     28:   fas->fastype = fastype;
     29:   if (fas->next) {
     30:     SNESFASSetType(fas->next, fastype);
     31:   }
     32:   return(0);
     33: }

     36: /*@
     37: SNESFASGetType - Sets the update and correction type used for FAS.

     39: Logically Collective

     41: Input Parameters:
     42: . snes - FAS context

     44: Output Parameters:
     45: . fastype - SNES_FAS_ADDITIVE or SNES_FAS_MULTIPLICATIVE

     47: Level: intermediate

     49: .seealso: PCMGSetType()
     50: @*/
     51: PetscErrorCode  SNESFASGetType(SNES snes,SNESFASType *fastype)
     52: {
     53:   SNES_FAS *fas;

     58:   fas = (SNES_FAS*)snes->data;
     59:   *fastype = fas->fastype;
     60:   return(0);
     61: }

     63: /*@C
     64:    SNESFASSetLevels - Sets the number of levels to use with FAS.
     65:    Must be called before any other FAS routine.

     67:    Input Parameters:
     68: +  snes   - the snes context
     69: .  levels - the number of levels
     70: -  comms  - optional communicators for each level; this is to allow solving the coarser
     71:             problems on smaller sets of processors.

     73:    Level: intermediate

     75:    Notes:
     76:      If the number of levels is one then the multigrid uses the -fas_levels prefix
     77:   for setting the level options rather than the -fas_coarse prefix.

     79: .seealso: SNESFASGetLevels()
     80: @*/
     81: PetscErrorCode SNESFASSetLevels(SNES snes, PetscInt levels, MPI_Comm *comms)
     82: {
     84:   PetscInt       i;
     85:   const char     *optionsprefix;
     86:   char           tprefix[128];
     87:   SNES_FAS       *fas;
     88:   SNES           prevsnes;
     89:   MPI_Comm       comm;

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

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

    127:       prevsnes = fas->next;
    128:       fas      = (SNES_FAS*)prevsnes->data;
    129:     }
    130:   }
    131:   return(0);
    132: }

    135: /*@
    136:    SNESFASGetLevels - Gets the number of levels in a FAS, including fine and coarse grids

    138:    Input Parameter:
    139: .  snes - the nonlinear solver context

    141:    Output parameter:
    142: .  levels - the number of levels

    144:    Level: advanced

    146: .seealso: SNESFASSetLevels(), PCMGGetLevels()
    147: @*/
    148: PetscErrorCode SNESFASGetLevels(SNES snes, PetscInt *levels)
    149: {
    150:   SNES_FAS *fas;

    155:   fas = (SNES_FAS*)snes->data;
    156:   *levels = fas->levels;
    157:   return(0);
    158: }

    161: /*@
    162:    SNESFASGetCycleSNES - Gets the SNES corresponding to a particular
    163:    level of the FAS hierarchy.

    165:    Input Parameters:
    166: +  snes    - the multigrid context
    167:    level   - the level to get
    168: -  lsnes   - whether to use the nonlinear smoother or not

    170:    Level: advanced

    172: .seealso: SNESFASSetLevels(), SNESFASGetLevels()
    173: @*/
    174: PetscErrorCode SNESFASGetCycleSNES(SNES snes,PetscInt level,SNES *lsnes)
    175: {
    176:   SNES_FAS *fas;
    177:   PetscInt i;

    182:   fas = (SNES_FAS*)snes->data;
    183:   if (level > fas->levels-1) SETERRQ2(PetscObjectComm((PetscObject)snes),PETSC_ERR_ARG_OUTOFRANGE,"Requested level %D from SNESFAS containing %D levels",level,fas->levels);
    184:   if (fas->level !=  fas->levels - 1) SETERRQ2(PetscObjectComm((PetscObject)snes),PETSC_ERR_ARG_OUTOFRANGE,"SNESFASGetCycleSNES may only be called on the finest-level SNES.",level,fas->level);

    186:   *lsnes = snes;
    187:   for (i = fas->level; i > level; i--) {
    188:     *lsnes = fas->next;
    189:     fas    = (SNES_FAS*)(*lsnes)->data;
    190:   }
    191:   if (fas->level != level) SETERRQ(PetscObjectComm((PetscObject)snes),PETSC_ERR_PLIB,"SNESFAS level hierarchy corrupt");
    192:   return(0);
    193: }

    195: /*@
    196:    SNESFASSetNumberSmoothUp - Sets the number of post-smoothing steps to
    197:    use on all levels.

    199:    Logically Collective on SNES

    201:    Input Parameters:
    202: +  snes - the multigrid context
    203: -  n    - the number of smoothing steps

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

    208:    Level: advanced

    210: .seealso: SNESFASSetNumberSmoothDown()
    211: @*/
    212: PetscErrorCode SNESFASSetNumberSmoothUp(SNES snes, PetscInt n)
    213: {
    214:   SNES_FAS       *fas;

    219:   fas =  (SNES_FAS*)snes->data;
    220:   fas->max_up_it = n;
    221:   if (!fas->smoothu && fas->level != 0) {
    222:     SNESFASCycleCreateSmoother_Private(snes, &fas->smoothu);
    223:   }
    224:   if (fas->smoothu) {
    225:     SNESSetTolerances(fas->smoothu, fas->smoothu->abstol, fas->smoothu->rtol, fas->smoothu->stol, n, fas->smoothu->max_funcs);
    226:   }
    227:   if (fas->next) {
    228:     SNESFASSetNumberSmoothUp(fas->next, n);
    229:   }
    230:   return(0);
    231: }

    233: /*@
    234:    SNESFASSetNumberSmoothDown - Sets the number of pre-smoothing steps to
    235:    use on all levels.

    237:    Logically Collective on SNES

    239:    Input Parameters:
    240: +  snes - the multigrid context
    241: -  n    - the number of smoothing steps

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

    246:    Level: advanced

    248: .seealso: SNESFASSetNumberSmoothUp()
    249: @*/
    250: PetscErrorCode SNESFASSetNumberSmoothDown(SNES snes, PetscInt n)
    251: {
    252:   SNES_FAS       *fas;

    257:   fas = (SNES_FAS*)snes->data;
    258:   if (!fas->smoothd) {
    259:     SNESFASCycleCreateSmoother_Private(snes, &fas->smoothd);
    260:   }
    261:   SNESSetTolerances(fas->smoothd, fas->smoothd->abstol, fas->smoothd->rtol, fas->smoothd->stol, n, fas->smoothd->max_funcs);

    263:   fas->max_down_it = n;
    264:   if (fas->next) {
    265:     SNESFASSetNumberSmoothDown(fas->next, n);
    266:   }
    267:   return(0);
    268: }

    271: /*@
    272:    SNESFASSetContinuation - Sets the FAS cycle to default to exact Newton solves on the upsweep

    274:    Logically Collective on SNES

    276:    Input Parameters:
    277: +  snes - the multigrid context
    278: -  n    - the number of smoothing steps

    280:    Options Database Key:
    281: .  -snes_fas_continuation - sets continuation to true

    283:    Level: advanced

    285:    Notes:
    286:     This sets the prefix on the upsweep smoothers to -fas_continuation

    288: .seealso: SNESFAS
    289: @*/
    290: PetscErrorCode SNESFASSetContinuation(SNES snes,PetscBool continuation)
    291: {
    292:   const char     *optionsprefix;
    293:   char           tprefix[128];
    294:   SNES_FAS       *fas;

    299:   fas  = (SNES_FAS*)snes->data;
    300:   SNESGetOptionsPrefix(fas->fine, &optionsprefix);
    301:   if (!fas->smoothu) {
    302:     SNESFASCycleCreateSmoother_Private(snes, &fas->smoothu);
    303:   }
    304:   PetscStrncpy(tprefix,"fas_levels_continuation_",sizeof(tprefix));
    305:   SNESSetOptionsPrefix(fas->smoothu, optionsprefix);
    306:   SNESAppendOptionsPrefix(fas->smoothu, tprefix);
    307:   SNESSetType(fas->smoothu,SNESNEWTONLS);
    308:   SNESSetTolerances(fas->smoothu,fas->fine->abstol,fas->fine->rtol,fas->fine->stol,50,100);
    309:   fas->continuation = continuation;
    310:   if (fas->next) {
    311:     SNESFASSetContinuation(fas->next,continuation);
    312:   }
    313:   return(0);
    314: }

    317: /*@
    318:    SNESFASSetCycles - Sets the number of FAS multigrid cycles to use each time a grid is visited.  Use SNESFASSetCyclesOnLevel() for more
    319:    complicated cycling.

    321:    Logically Collective on SNES

    323:    Input Parameters:
    324: +  snes   - the multigrid context
    325: -  cycles - the number of cycles -- 1 for V-cycle, 2 for W-cycle

    327:    Options Database Key:
    328: .  -snes_fas_cycles 1 or 2

    330:    Level: advanced

    332: .seealso: SNESFASSetCyclesOnLevel()
    333: @*/
    334: PetscErrorCode SNESFASSetCycles(SNES snes, PetscInt cycles)
    335: {
    336:   SNES_FAS       *fas;
    338:   PetscBool      isFine;

    342:   SNESFASCycleIsFine(snes, &isFine);
    343:   fas = (SNES_FAS*)snes->data;
    344:   fas->n_cycles = cycles;
    345:   if (!isFine) {
    346:     SNESSetTolerances(snes, snes->abstol, snes->rtol, snes->stol, cycles, snes->max_funcs);
    347:   }
    348:   if (fas->next) {
    349:     SNESFASSetCycles(fas->next, cycles);
    350:   }
    351:   return(0);
    352: }

    355: /*@
    356:    SNESFASSetMonitor - Sets the method-specific cycle monitoring

    358:    Logically Collective on SNES

    360:    Input Parameters:
    361: +  snes   - the FAS context
    362: .  vf     - viewer and format structure (may be NULL if flg is FALSE)
    363: -  flg    - monitor or not

    365:    Level: advanced

    367: .seealso: SNESFASSetCyclesOnLevel()
    368: @*/
    369: PetscErrorCode SNESFASSetMonitor(SNES snes, PetscViewerAndFormat *vf, PetscBool flg)
    370: {
    371:   SNES_FAS       *fas;
    373:   PetscBool      isFine;
    374:   PetscInt       i, levels;
    375:   SNES           levelsnes;

    379:   SNESFASCycleIsFine(snes, &isFine);
    380:   fas = (SNES_FAS*)snes->data;
    381:   levels = fas->levels;
    382:   if (isFine) {
    383:     for (i = 0; i < levels; i++) {
    384:       SNESFASGetCycleSNES(snes, i, &levelsnes);
    385:       fas  = (SNES_FAS*)levelsnes->data;
    386:       if (flg) {
    387:         /* set the monitors for the upsmoother and downsmoother */
    388:         SNESMonitorCancel(levelsnes);
    389:         /* Only register destroy on finest level */
    390:         SNESMonitorSet(levelsnes,(PetscErrorCode (*)(SNES,PetscInt,PetscReal,void*))SNESMonitorDefault,vf,(!i ? (PetscErrorCode (*)(void**))PetscViewerAndFormatDestroy : NULL));
    391:       } else if (i != fas->levels - 1) {
    392:         /* unset the monitors on the coarse levels */
    393:         SNESMonitorCancel(levelsnes);
    394:       }
    395:     }
    396:   }
    397:   return(0);
    398: }

    400: /*@
    401:    SNESFASSetLog - Sets or unsets time logging for various FAS stages on all levels

    403:    Logically Collective on SNES

    405:    Input Parameters:
    406: +  snes   - the FAS context
    407: -  flg    - monitor or not

    409:    Level: advanced

    411: .seealso: SNESFASSetMonitor()
    412: @*/
    413: PetscErrorCode SNESFASSetLog(SNES snes, PetscBool flg)
    414: {
    415:   SNES_FAS       *fas;
    417:   PetscBool      isFine;
    418:   PetscInt       i, levels;
    419:   SNES           levelsnes;
    420:   char           eventname[128];

    424:   SNESFASCycleIsFine(snes, &isFine);
    425:   fas = (SNES_FAS*)snes->data;
    426:   levels = fas->levels;
    427:   if (isFine) {
    428:     for (i = 0; i < levels; i++) {
    429:       SNESFASGetCycleSNES(snes, i, &levelsnes);
    430:       fas  = (SNES_FAS*)levelsnes->data;
    431:       if (flg) {
    432:         PetscSNPrintf(eventname,sizeof(eventname),"FASSetup  %d",(int)i);
    433:         PetscLogEventRegister(eventname,((PetscObject)snes)->classid,&fas->eventsmoothsetup);
    434:         PetscSNPrintf(eventname,sizeof(eventname),"FASSmooth %d",(int)i);
    435:         PetscLogEventRegister(eventname,((PetscObject)snes)->classid,&fas->eventsmoothsolve);
    436:         PetscSNPrintf(eventname,sizeof(eventname),"FASResid  %d",(int)i);
    437:         PetscLogEventRegister(eventname,((PetscObject)snes)->classid,&fas->eventresidual);
    438:         PetscSNPrintf(eventname,sizeof(eventname),"FASInterp %d",(int)i);
    439:         PetscLogEventRegister(eventname,((PetscObject)snes)->classid,&fas->eventinterprestrict);
    440:       } else {
    441:         fas->eventsmoothsetup    = 0;
    442:         fas->eventsmoothsolve    = 0;
    443:         fas->eventresidual       = 0;
    444:         fas->eventinterprestrict = 0;
    445:       }
    446:     }
    447:   }
    448:   return(0);
    449: }

    451: /*
    452: Creates the default smoother type.

    454: This is SNESNRICHARDSON on each fine level and SNESNEWTONLS on the coarse level.

    456:  */
    457: PetscErrorCode SNESFASCycleCreateSmoother_Private(SNES snes, SNES *smooth)
    458: {
    459:   SNES_FAS       *fas;
    460:   const char     *optionsprefix;
    461:   char           tprefix[128];
    463:   SNES           nsmooth;

    468:   fas  = (SNES_FAS*)snes->data;
    469:   SNESGetOptionsPrefix(fas->fine, &optionsprefix);
    470:   /* create the default smoother */
    471:   SNESCreate(PetscObjectComm((PetscObject)snes), &nsmooth);
    472:   if (fas->level == 0) {
    473:     PetscStrncpy(tprefix,"fas_coarse_",sizeof(tprefix));
    474:     SNESAppendOptionsPrefix(nsmooth, optionsprefix);
    475:     SNESAppendOptionsPrefix(nsmooth, tprefix);
    476:     SNESSetType(nsmooth, SNESNEWTONLS);
    477:     SNESSetTolerances(nsmooth, nsmooth->abstol, nsmooth->rtol, nsmooth->stol, nsmooth->max_its, nsmooth->max_funcs);
    478:   } else {
    479:     PetscSNPrintf(tprefix,sizeof(tprefix),"fas_levels_%d_",(int)fas->level);
    480:     SNESAppendOptionsPrefix(nsmooth, optionsprefix);
    481:     SNESAppendOptionsPrefix(nsmooth, tprefix);
    482:     SNESSetType(nsmooth, SNESNRICHARDSON);
    483:     SNESSetTolerances(nsmooth, 0.0, 0.0, 0.0, fas->max_down_it, nsmooth->max_funcs);
    484:   }
    485:   PetscObjectIncrementTabLevel((PetscObject)nsmooth, (PetscObject)snes, 1);
    486:   PetscLogObjectParent((PetscObject)snes,(PetscObject)nsmooth);
    487:   PetscObjectCopyFortranFunctionPointers((PetscObject)snes, (PetscObject)nsmooth);
    488:   PetscObjectComposedDataSetInt((PetscObject) nsmooth, PetscMGLevelId, fas->level);
    489:   *smooth = nsmooth;
    490:   return(0);
    491: }

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

    495: /*@
    496:    SNESFASCycleSetCycles - Sets the number of cycles on a particular level.

    498:    Logically Collective on SNES

    500:    Input Parameters:
    501: +  snes   - the multigrid context
    502: .  level  - the level to set the number of cycles on
    503: -  cycles - the number of cycles -- 1 for V-cycle, 2 for W-cycle

    505:    Level: advanced

    507: .seealso: SNESFASSetCycles()
    508: @*/
    509: PetscErrorCode SNESFASCycleSetCycles(SNES snes, PetscInt cycles)
    510: {
    511:   SNES_FAS       *fas;

    516:   fas = (SNES_FAS*)snes->data;
    517:   fas->n_cycles = cycles;
    518:   SNESSetTolerances(snes, snes->abstol, snes->rtol, snes->stol, cycles, snes->max_funcs);
    519:   return(0);
    520: }

    523: /*@
    524:    SNESFASCycleGetSmoother - Gets the smoother on a particular cycle level.

    526:    Logically Collective on SNES

    528:    Input Parameters:
    529: .  snes   - the multigrid context

    531:    Output Parameters:
    532: .  smooth - the smoother

    534:    Level: advanced

    536: .seealso: SNESFASCycleGetSmootherUp(), SNESFASCycleGetSmootherDown()
    537: @*/
    538: PetscErrorCode SNESFASCycleGetSmoother(SNES snes, SNES *smooth)
    539: {
    540:   SNES_FAS *fas;

    545:   fas     = (SNES_FAS*)snes->data;
    546:   *smooth = fas->smoothd;
    547:   return(0);
    548: }
    549: /*@
    550:    SNESFASCycleGetSmootherUp - Gets the up smoother on a particular cycle level.

    552:    Logically Collective on SNES

    554:    Input Parameters:
    555: .  snes   - the multigrid context

    557:    Output Parameters:
    558: .  smoothu - the smoother

    560:    Notes:
    561:    Returns the downsmoother if no up smoother is available.  This enables transparent
    562:    default behavior in the process of the solve.

    564:    Level: advanced

    566: .seealso: SNESFASCycleGetSmoother(), SNESFASCycleGetSmootherDown()
    567: @*/
    568: PetscErrorCode SNESFASCycleGetSmootherUp(SNES snes, SNES *smoothu)
    569: {
    570:   SNES_FAS *fas;

    575:   fas = (SNES_FAS*)snes->data;
    576:   if (!fas->smoothu) *smoothu = fas->smoothd;
    577:   else *smoothu = fas->smoothu;
    578:   return(0);
    579: }

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

    584:    Logically Collective on SNES

    586:    Input Parameters:
    587: .  snes   - the multigrid context

    589:    Output Parameters:
    590: .  smoothd - the smoother

    592:    Level: advanced

    594: .seealso: SNESFASCycleGetSmootherUp(), SNESFASCycleGetSmoother()
    595: @*/
    596: PetscErrorCode SNESFASCycleGetSmootherDown(SNES snes, SNES *smoothd)
    597: {
    598:   SNES_FAS *fas;

    603:   fas = (SNES_FAS*)snes->data;
    604:   *smoothd = fas->smoothd;
    605:   return(0);
    606: }

    609: /*@
    610:    SNESFASCycleGetCorrection - Gets the coarse correction FAS context for this level

    612:    Logically Collective on SNES

    614:    Input Parameters:
    615: .  snes   - the multigrid context

    617:    Output Parameters:
    618: .  correction - the coarse correction on this level

    620:    Notes:
    621:    Returns NULL on the coarsest level.

    623:    Level: advanced

    625: .seealso: SNESFASCycleGetSmootherUp(), SNESFASCycleGetSmoother()
    626: @*/
    627: PetscErrorCode SNESFASCycleGetCorrection(SNES snes, SNES *correction)
    628: {
    629:   SNES_FAS *fas;

    634:   fas = (SNES_FAS*)snes->data;
    635:   *correction = fas->next;
    636:   return(0);
    637: }

    639: /*@
    640:    SNESFASCycleGetInterpolation - Gets the interpolation on this level

    642:    Logically Collective on SNES

    644:    Input Parameters:
    645: .  snes   - the multigrid context

    647:    Output Parameters:
    648: .  mat    - the interpolation operator on this level

    650:    Level: developer

    652: .seealso: SNESFASCycleGetSmootherUp(), SNESFASCycleGetSmoother()
    653: @*/
    654: PetscErrorCode SNESFASCycleGetInterpolation(SNES snes, Mat *mat)
    655: {
    656:   SNES_FAS *fas;

    661:   fas = (SNES_FAS*)snes->data;
    662:   *mat = fas->interpolate;
    663:   return(0);
    664: }

    667: /*@
    668:    SNESFASCycleGetRestriction - Gets the restriction on this level

    670:    Logically Collective on SNES

    672:    Input Parameters:
    673: .  snes   - the multigrid context

    675:    Output Parameters:
    676: .  mat    - the restriction operator on this level

    678:    Level: developer

    680: .seealso: SNESFASGetRestriction(), SNESFASCycleGetInterpolation()
    681: @*/
    682: PetscErrorCode SNESFASCycleGetRestriction(SNES snes, Mat *mat)
    683: {
    684:   SNES_FAS *fas;

    689:   fas = (SNES_FAS*)snes->data;
    690:   *mat = fas->restrct;
    691:   return(0);
    692: }

    695: /*@
    696:    SNESFASCycleGetInjection - Gets the injection on this level

    698:    Logically Collective on SNES

    700:    Input Parameters:
    701: .  snes   - the multigrid context

    703:    Output Parameters:
    704: .  mat    - the restriction operator on this level

    706:    Level: developer

    708: .seealso: SNESFASGetInjection(), SNESFASCycleGetRestriction()
    709: @*/
    710: PetscErrorCode SNESFASCycleGetInjection(SNES snes, Mat *mat)
    711: {
    712:   SNES_FAS *fas;

    717:   fas = (SNES_FAS*)snes->data;
    718:   *mat = fas->inject;
    719:   return(0);
    720: }

    722: /*@
    723:    SNESFASCycleGetRScale - Gets the injection on this level

    725:    Logically Collective on SNES

    727:    Input Parameters:
    728: .  snes   - the multigrid context

    730:    Output Parameters:
    731: .  mat    - the restriction operator on this level

    733:    Level: developer

    735: .seealso: SNESFASCycleGetRestriction(), SNESFASGetRScale()
    736: @*/
    737: PetscErrorCode SNESFASCycleGetRScale(SNES snes, Vec *vec)
    738: {
    739:   SNES_FAS *fas;

    744:   fas  = (SNES_FAS*)snes->data;
    745:   *vec = fas->rscale;
    746:   return(0);
    747: }

    749: /*@
    750:    SNESFASCycleIsFine - Determines if a given cycle is the fine level.

    752:    Logically Collective on SNES

    754:    Input Parameters:
    755: .  snes   - the FAS context

    757:    Output Parameters:
    758: .  flg - indicates if this is the fine level or not

    760:    Level: advanced

    762: .seealso: SNESFASSetLevels()
    763: @*/
    764: PetscErrorCode SNESFASCycleIsFine(SNES snes, PetscBool *flg)
    765: {
    766:   SNES_FAS *fas;

    771:   fas = (SNES_FAS*)snes->data;
    772:   if (fas->level == fas->levels - 1) *flg = PETSC_TRUE;
    773:   else *flg = PETSC_FALSE;
    774:   return(0);
    775: }

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

    779: /*@
    780:    SNESFASSetInterpolation - Sets the function to be used to calculate the
    781:    interpolation from l-1 to the lth level

    783:    Input Parameters:
    784: +  snes      - the multigrid context
    785: .  mat       - the interpolation operator
    786: -  level     - the level (0 is coarsest) to supply [do not supply 0]

    788:    Level: advanced

    790:    Notes:
    791:           Usually this is the same matrix used also to set the restriction
    792:     for the same level.

    794:           One can pass in the interpolation matrix or its transpose; PETSc figures
    795:     out from the matrix size which one it is.

    797: .seealso: SNESFASSetInjection(), SNESFASSetRestriction(), SNESFASSetRScale()
    798: @*/
    799: PetscErrorCode SNESFASSetInterpolation(SNES snes, PetscInt level, Mat mat)
    800: {
    801:   SNES_FAS       *fas;
    803:   SNES           levelsnes;

    808:   SNESFASGetCycleSNES(snes, level, &levelsnes);
    809:   fas  = (SNES_FAS*)levelsnes->data;
    810:   PetscObjectReference((PetscObject)mat);
    811:   MatDestroy(&fas->interpolate);
    812:   fas->interpolate = mat;
    813:   return(0);
    814: }

    816: /*@
    817:    SNESFASGetInterpolation - Gets the matrix used to calculate the
    818:    interpolation from l-1 to the lth level

    820:    Input Parameters:
    821: +  snes      - the multigrid context
    822: -  level     - the level (0 is coarsest) to supply [do not supply 0]

    824:    Output Parameters:
    825: .  mat       - the interpolation operator

    827:    Level: advanced

    829: .seealso: SNESFASSetInterpolation(), SNESFASGetInjection(), SNESFASGetRestriction(), SNESFASGetRScale()
    830: @*/
    831: PetscErrorCode SNESFASGetInterpolation(SNES snes, PetscInt level, Mat *mat)
    832: {
    833:   SNES_FAS       *fas;
    835:   SNES           levelsnes;

    840:   SNESFASGetCycleSNES(snes, level, &levelsnes);
    841:   fas  = (SNES_FAS*)levelsnes->data;
    842:   *mat = fas->interpolate;
    843:   return(0);
    844: }

    846: /*@
    847:    SNESFASSetRestriction - Sets the function to be used to restrict the defect
    848:    from level l to l-1.

    850:    Input Parameters:
    851: +  snes  - the multigrid context
    852: .  mat   - the restriction matrix
    853: -  level - the level (0 is coarsest) to supply [Do not supply 0]

    855:    Level: advanced

    857:    Notes:
    858:           Usually this is the same matrix used also to set the interpolation
    859:     for the same level.

    861:           One can pass in the interpolation matrix or its transpose; PETSc figures
    862:     out from the matrix size which one it is.

    864:          If you do not set this, the transpose of the Mat set with SNESFASSetInterpolation()
    865:     is used.

    867: .seealso: SNESFASSetInterpolation(), SNESFASSetInjection()
    868: @*/
    869: PetscErrorCode SNESFASSetRestriction(SNES snes, PetscInt level, Mat mat)
    870: {
    871:   SNES_FAS       *fas;
    873:   SNES           levelsnes;

    878:   SNESFASGetCycleSNES(snes, level, &levelsnes);
    879:   fas  = (SNES_FAS*)levelsnes->data;
    880:   PetscObjectReference((PetscObject)mat);
    881:   MatDestroy(&fas->restrct);
    882:   fas->restrct = mat;
    883:   return(0);
    884: }

    886: /*@
    887:    SNESFASGetRestriction - Gets the matrix used to calculate the
    888:    restriction from l to the l-1th level

    890:    Input Parameters:
    891: +  snes      - the multigrid context
    892: -  level     - the level (0 is coarsest) to supply [do not supply 0]

    894:    Output Parameters:
    895: .  mat       - the interpolation operator

    897:    Level: advanced

    899: .seealso: SNESFASSetRestriction(), SNESFASGetInjection(), SNESFASGetInterpolation(), SNESFASGetRScale()
    900: @*/
    901: PetscErrorCode SNESFASGetRestriction(SNES snes, PetscInt level, Mat *mat)
    902: {
    903:   SNES_FAS       *fas;
    905:   SNES           levelsnes;

    910:   SNESFASGetCycleSNES(snes, level, &levelsnes);
    911:   fas  = (SNES_FAS*)levelsnes->data;
    912:   *mat = fas->restrct;
    913:   return(0);
    914: }

    917: /*@
    918:    SNESFASSetInjection - Sets the function to be used to inject the solution
    919:    from level l to l-1.

    921:    Input Parameters:
    922:  +  snes  - the multigrid context
    923: .  mat   - the restriction matrix
    924: -  level - the level (0 is coarsest) to supply [Do not supply 0]

    926:    Level: advanced

    928:    Notes:
    929:          If you do not set this, the restriction and rscale is used to
    930:    project the solution instead.

    932: .seealso: SNESFASSetInterpolation(), SNESFASSetRestriction()
    933: @*/
    934: PetscErrorCode SNESFASSetInjection(SNES snes, PetscInt level, Mat mat)
    935: {
    936:   SNES_FAS       *fas;
    938:   SNES           levelsnes;

    943:   SNESFASGetCycleSNES(snes, level, &levelsnes);
    944:   fas  = (SNES_FAS*)levelsnes->data;
    945:   PetscObjectReference((PetscObject)mat);
    946:   MatDestroy(&fas->inject);

    948:   fas->inject = mat;
    949:   return(0);
    950: }

    953: /*@
    954:    SNESFASGetInjection - Gets the matrix used to calculate the
    955:    injection from l-1 to the lth level

    957:    Input Parameters:
    958: +  snes      - the multigrid context
    959: -  level     - the level (0 is coarsest) to supply [do not supply 0]

    961:    Output Parameters:
    962: .  mat       - the injection operator

    964:    Level: advanced

    966: .seealso: SNESFASSetInjection(), SNESFASGetRestriction(), SNESFASGetInterpolation(), SNESFASGetRScale()
    967: @*/
    968: PetscErrorCode SNESFASGetInjection(SNES snes, PetscInt level, Mat *mat)
    969: {
    970:   SNES_FAS       *fas;
    972:   SNES           levelsnes;

    977:   SNESFASGetCycleSNES(snes, level, &levelsnes);
    978:   fas  = (SNES_FAS*)levelsnes->data;
    979:   *mat = fas->inject;
    980:   return(0);
    981: }

    983: /*@
    984:    SNESFASSetRScale - Sets the scaling factor of the restriction
    985:    operator from level l to l-1.

    987:    Input Parameters:
    988: +  snes   - the multigrid context
    989: .  rscale - the restriction scaling
    990: -  level  - the level (0 is coarsest) to supply [Do not supply 0]

    992:    Level: advanced

    994:    Notes:
    995:          This is only used in the case that the injection is not set.

    997: .seealso: SNESFASSetInjection(), SNESFASSetRestriction()
    998: @*/
    999: PetscErrorCode SNESFASSetRScale(SNES snes, PetscInt level, Vec rscale)
    1000: {
    1001:   SNES_FAS       *fas;
    1003:   SNES           levelsnes;

    1008:   SNESFASGetCycleSNES(snes, level, &levelsnes);
    1009:   fas  = (SNES_FAS*)levelsnes->data;
    1010:   PetscObjectReference((PetscObject)rscale);
    1011:   VecDestroy(&fas->rscale);
    1012:   fas->rscale = rscale;
    1013:   return(0);
    1014: }

    1016: /*@
    1017:    SNESFASGetSmoother - Gets the default smoother on a level.

    1019:    Input Parameters:
    1020: +  snes   - the multigrid context
    1021: -  level  - the level (0 is coarsest) to supply

    1023:    Output Parameters:
    1024:    smooth  - the smoother

    1026:    Level: advanced

    1028: .seealso: SNESFASSetInjection(), SNESFASSetRestriction()
    1029: @*/
    1030: PetscErrorCode SNESFASGetSmoother(SNES snes, PetscInt level, SNES *smooth)
    1031: {
    1032:   SNES_FAS       *fas;
    1034:   SNES           levelsnes;

    1039:   SNESFASGetCycleSNES(snes, level, &levelsnes);
    1040:   fas  = (SNES_FAS*)levelsnes->data;
    1041:   if (!fas->smoothd) {
    1042:     SNESFASCycleCreateSmoother_Private(levelsnes, &fas->smoothd);
    1043:   }
    1044:   *smooth = fas->smoothd;
    1045:   return(0);
    1046: }

    1048: /*@
    1049:    SNESFASGetSmootherDown - Gets the downsmoother on a level.

    1051:    Input Parameters:
    1052: +  snes   - the multigrid context
    1053: -  level  - the level (0 is coarsest) to supply

    1055:    Output Parameters:
    1056:    smooth  - the smoother

    1058:    Level: advanced

    1060: .seealso: SNESFASSetInjection(), SNESFASSetRestriction()
    1061: @*/
    1062: PetscErrorCode SNESFASGetSmootherDown(SNES snes, PetscInt level, SNES *smooth)
    1063: {
    1064:   SNES_FAS       *fas;
    1066:   SNES           levelsnes;

    1071:   SNESFASGetCycleSNES(snes, level, &levelsnes);
    1072:   fas  = (SNES_FAS*)levelsnes->data;
    1073:   /* if the user chooses to differentiate smoothers, create them both at this point */
    1074:   if (!fas->smoothd) {
    1075:     SNESFASCycleCreateSmoother_Private(levelsnes, &fas->smoothd);
    1076:   }
    1077:   if (!fas->smoothu) {
    1078:     SNESFASCycleCreateSmoother_Private(levelsnes, &fas->smoothu);
    1079:   }
    1080:   *smooth = fas->smoothd;
    1081:   return(0);
    1082: }

    1084: /*@
    1085:    SNESFASGetSmootherUp - Gets the upsmoother on a level.

    1087:    Input Parameters:
    1088: +  snes   - the multigrid context
    1089: -  level  - the level (0 is coarsest)

    1091:    Output Parameters:
    1092:    smooth  - the smoother

    1094:    Level: advanced

    1096: .seealso: SNESFASSetInjection(), SNESFASSetRestriction()
    1097: @*/
    1098: PetscErrorCode SNESFASGetSmootherUp(SNES snes, PetscInt level, SNES *smooth)
    1099: {
    1100:   SNES_FAS       *fas;
    1102:   SNES           levelsnes;

    1107:   SNESFASGetCycleSNES(snes, level, &levelsnes);
    1108:   fas  = (SNES_FAS*)levelsnes->data;
    1109:   /* if the user chooses to differentiate smoothers, create them both at this point */
    1110:   if (!fas->smoothd) {
    1111:     SNESFASCycleCreateSmoother_Private(levelsnes, &fas->smoothd);
    1112:   }
    1113:   if (!fas->smoothu) {
    1114:     SNESFASCycleCreateSmoother_Private(levelsnes, &fas->smoothu);
    1115:   }
    1116:   *smooth = fas->smoothu;
    1117:   return(0);
    1118: }

    1120: /*@
    1121:   SNESFASGetCoarseSolve - Gets the coarsest solver.

    1123:   Input Parameters:
    1124: . snes - the multigrid context

    1126:   Output Parameters:
    1127: . coarse - the coarse-level solver

    1129:   Level: advanced

    1131: .seealso: SNESFASSetInjection(), SNESFASSetRestriction()
    1132: @*/
    1133: PetscErrorCode SNESFASGetCoarseSolve(SNES snes, SNES *coarse)
    1134: {
    1135:   SNES_FAS       *fas;
    1137:   SNES           levelsnes;

    1142:   SNESFASGetCycleSNES(snes, 0, &levelsnes);
    1143:   fas  = (SNES_FAS*)levelsnes->data;
    1144:   /* if the user chooses to differentiate smoothers, create them both at this point */
    1145:   if (!fas->smoothd) {
    1146:     SNESFASCycleCreateSmoother_Private(levelsnes, &fas->smoothd);
    1147:   }
    1148:   *coarse = fas->smoothd;
    1149:   return(0);
    1150: }

    1152: /*@
    1153:    SNESFASFullSetDownSweep - Smooth during the initial downsweep for SNESFAS

    1155:    Logically Collective on SNES

    1157:    Input Parameters:
    1158: +  snes - the multigrid context
    1159: -  swp - whether to downsweep or not

    1161:    Options Database Key:
    1162: .  -snes_fas_full_downsweep - Sets number of pre-smoothing steps

    1164:    Level: advanced

    1166: .seealso: SNESFASSetNumberSmoothUp()
    1167: @*/
    1168: PetscErrorCode SNESFASFullSetDownSweep(SNES snes,PetscBool swp)
    1169: {
    1170:   SNES_FAS       *fas;

    1175:   fas = (SNES_FAS*)snes->data;
    1176:   fas->full_downsweep = swp;
    1177:   if (fas->next) {
    1178:     SNESFASFullSetDownSweep(fas->next,swp);
    1179:   }
    1180:   return(0);
    1181: }