1421d9b32SPeter Brune /* Defines the basic SNES object */ 26038b46bSPeter Brune #include <../src/snes/impls/fas/fasimpls.h> /*I "petscsnesfas.h" I*/ 3421d9b32SPeter Brune 407144faaSPeter Brune const char *SNESFASTypes[] = {"MULTIPLICATIVE","ADDITIVE","SNESFASType","SNES_FAS",0}; 507144faaSPeter Brune 6421d9b32SPeter Brune /*MC 7ef536925SPeter Brune 8ef536925SPeter Brune SNESFAS - Full Approximation Scheme nonlinear multigrid solver. 9421d9b32SPeter Brune 10421d9b32SPeter Brune The nonlinear problem is solved via the repeated application of nonlinear preconditioners and coarse-grid corrections 11421d9b32SPeter Brune 12421d9b32SPeter Brune .seealso: SNESCreate(), SNES, SNESSetType(), SNESType (for list of available types) 13421d9b32SPeter Brune M*/ 14421d9b32SPeter Brune 15421d9b32SPeter Brune extern PetscErrorCode SNESDestroy_FAS(SNES snes); 16421d9b32SPeter Brune extern PetscErrorCode SNESSetUp_FAS(SNES snes); 17421d9b32SPeter Brune extern PetscErrorCode SNESSetFromOptions_FAS(SNES snes); 18421d9b32SPeter Brune extern PetscErrorCode SNESView_FAS(SNES snes, PetscViewer viewer); 19421d9b32SPeter Brune extern PetscErrorCode SNESSolve_FAS(SNES snes); 20421d9b32SPeter Brune extern PetscErrorCode SNESReset_FAS(SNES snes); 216273346dSPeter Brune extern PetscErrorCode SNESFASGalerkinDefaultFunction(SNES, Vec, Vec, void *); 22421d9b32SPeter Brune 23421d9b32SPeter Brune EXTERN_C_BEGIN 24ddebd997SPeter Brune #undef __FUNCT__ 25ddebd997SPeter Brune #define __FUNCT__ "SNESLineSearchSetType_FAS" 26ddebd997SPeter Brune PetscErrorCode SNESLineSearchSetType_FAS(SNES snes, SNESLineSearchType type) 27ddebd997SPeter Brune { 28ddebd997SPeter Brune PetscErrorCode ierr; 29ddebd997SPeter Brune PetscFunctionBegin; 30ddebd997SPeter Brune 31ddebd997SPeter Brune switch (type) { 32ddebd997SPeter Brune case SNES_LS_BASIC: 33ddebd997SPeter Brune ierr = SNESLineSearchSet(snes,SNESLineSearchNo,PETSC_NULL);CHKERRQ(ierr); 34ddebd997SPeter Brune break; 35ddebd997SPeter Brune case SNES_LS_BASIC_NONORMS: 36ddebd997SPeter Brune ierr = SNESLineSearchSet(snes,SNESLineSearchNoNorms,PETSC_NULL);CHKERRQ(ierr); 37ddebd997SPeter Brune break; 38ddebd997SPeter Brune case SNES_LS_QUADRATIC: 39ddebd997SPeter Brune ierr = SNESLineSearchSet(snes,SNESLineSearchQuadraticSecant,PETSC_NULL);CHKERRQ(ierr); 40ddebd997SPeter Brune break; 41ddebd997SPeter Brune default: 42ddebd997SPeter Brune SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP,"Unknown line search type."); 43ddebd997SPeter Brune break; 44ddebd997SPeter Brune } 45ddebd997SPeter Brune snes->ls_type = type; 46ddebd997SPeter Brune PetscFunctionReturn(0); 47ddebd997SPeter Brune } 48ddebd997SPeter Brune EXTERN_C_END 49ddebd997SPeter Brune 50ddebd997SPeter Brune EXTERN_C_BEGIN 51421d9b32SPeter Brune 52421d9b32SPeter Brune #undef __FUNCT__ 53421d9b32SPeter Brune #define __FUNCT__ "SNESCreate_FAS" 54421d9b32SPeter Brune PetscErrorCode SNESCreate_FAS(SNES snes) 55421d9b32SPeter Brune { 56421d9b32SPeter Brune SNES_FAS * fas; 57421d9b32SPeter Brune PetscErrorCode ierr; 58421d9b32SPeter Brune 59421d9b32SPeter Brune PetscFunctionBegin; 60421d9b32SPeter Brune snes->ops->destroy = SNESDestroy_FAS; 61421d9b32SPeter Brune snes->ops->setup = SNESSetUp_FAS; 62421d9b32SPeter Brune snes->ops->setfromoptions = SNESSetFromOptions_FAS; 63421d9b32SPeter Brune snes->ops->view = SNESView_FAS; 64421d9b32SPeter Brune snes->ops->solve = SNESSolve_FAS; 65421d9b32SPeter Brune snes->ops->reset = SNESReset_FAS; 66421d9b32SPeter Brune 67ed020824SBarry Smith snes->usesksp = PETSC_FALSE; 68ed020824SBarry Smith snes->usespc = PETSC_FALSE; 69ed020824SBarry Smith 70421d9b32SPeter Brune ierr = PetscNewLog(snes, SNES_FAS, &fas);CHKERRQ(ierr); 71421d9b32SPeter Brune snes->data = (void*) fas; 72421d9b32SPeter Brune fas->level = 0; 73293a7e31SPeter Brune fas->levels = 1; 74ee78dd50SPeter Brune fas->n_cycles = 1; 75ee78dd50SPeter Brune fas->max_up_it = 1; 76ee78dd50SPeter Brune fas->max_down_it = 1; 77ee78dd50SPeter Brune fas->upsmooth = PETSC_NULL; 78ee78dd50SPeter Brune fas->downsmooth = PETSC_NULL; 79421d9b32SPeter Brune fas->next = PETSC_NULL; 806273346dSPeter Brune fas->previous = PETSC_NULL; 81421d9b32SPeter Brune fas->interpolate = PETSC_NULL; 82421d9b32SPeter Brune fas->restrct = PETSC_NULL; 83efe1f98aSPeter Brune fas->inject = PETSC_NULL; 84cc05f883SPeter Brune fas->monitor = PETSC_NULL; 85cc05f883SPeter Brune fas->usedmfornumberoflevels = PETSC_FALSE; 86ddebd997SPeter Brune fas->fastype = SNES_FAS_MULTIPLICATIVE; 87ddebd997SPeter Brune 88ddebd997SPeter Brune ierr = PetscObjectComposeFunctionDynamic((PetscObject)snes,"SNESLineSearchSetType_C","SNESLineSearchSetType_FAS",SNESLineSearchSetType_FAS);CHKERRQ(ierr); 89ddebd997SPeter Brune ierr = SNESLineSearchSetType(snes, SNES_LS_QUADRATIC);CHKERRQ(ierr); 90ddebd997SPeter Brune 91421d9b32SPeter Brune PetscFunctionReturn(0); 92421d9b32SPeter Brune } 93421d9b32SPeter Brune EXTERN_C_END 94421d9b32SPeter Brune 95421d9b32SPeter Brune #undef __FUNCT__ 96421d9b32SPeter Brune #define __FUNCT__ "SNESFASGetLevels" 97c79ef259SPeter Brune /*@ 98722262beSPeter Brune SNESFASGetLevels - Gets the number of levels in a FAS. 99c79ef259SPeter Brune 100c79ef259SPeter Brune Input Parameter: 101c79ef259SPeter Brune . snes - the preconditioner context 102c79ef259SPeter Brune 103c79ef259SPeter Brune Output parameter: 104c79ef259SPeter Brune . levels - the number of levels 105c79ef259SPeter Brune 106c79ef259SPeter Brune Level: advanced 107c79ef259SPeter Brune 108c79ef259SPeter Brune .keywords: MG, get, levels, multigrid 109c79ef259SPeter Brune 110c79ef259SPeter Brune .seealso: SNESFASSetLevels(), PCMGGetLevels() 111c79ef259SPeter Brune @*/ 112421d9b32SPeter Brune PetscErrorCode SNESFASGetLevels(SNES snes, PetscInt * levels) { 113421d9b32SPeter Brune SNES_FAS * fas = (SNES_FAS *)snes->data; 114421d9b32SPeter Brune PetscFunctionBegin; 115ee1fd11aSPeter Brune *levels = fas->levels; 116421d9b32SPeter Brune PetscFunctionReturn(0); 117421d9b32SPeter Brune } 118421d9b32SPeter Brune 119421d9b32SPeter Brune #undef __FUNCT__ 120646217ecSPeter Brune #define __FUNCT__ "SNESFASSetCycles" 121c79ef259SPeter Brune /*@ 122c79ef259SPeter Brune SNESFASSetCycles - Sets the type cycles to use. Use SNESFASSetCyclesOnLevel() for more 123c79ef259SPeter Brune complicated cycling. 124c79ef259SPeter Brune 125c79ef259SPeter Brune Logically Collective on SNES 126c79ef259SPeter Brune 127c79ef259SPeter Brune Input Parameters: 128c79ef259SPeter Brune + snes - the multigrid context 129c79ef259SPeter Brune - cycles - the number of cycles -- 1 for V-cycle, 2 for W-cycle 130c79ef259SPeter Brune 131c79ef259SPeter Brune Options Database Key: 132c79ef259SPeter Brune $ -snes_fas_cycles 1 or 2 133c79ef259SPeter Brune 134c79ef259SPeter Brune Level: advanced 135c79ef259SPeter Brune 136c79ef259SPeter Brune .keywords: MG, set, cycles, V-cycle, W-cycle, multigrid 137c79ef259SPeter Brune 138c79ef259SPeter Brune .seealso: SNESFASSetCyclesOnLevel() 139c79ef259SPeter Brune @*/ 140646217ecSPeter Brune PetscErrorCode SNESFASSetCycles(SNES snes, PetscInt cycles) { 141646217ecSPeter Brune SNES_FAS * fas = (SNES_FAS *)snes->data; 142646217ecSPeter Brune PetscErrorCode ierr; 143646217ecSPeter Brune PetscFunctionBegin; 144646217ecSPeter Brune fas->n_cycles = cycles; 145646217ecSPeter Brune if (fas->next) { 146646217ecSPeter Brune ierr = SNESFASSetCycles(fas->next, cycles);CHKERRQ(ierr); 147646217ecSPeter Brune } 148646217ecSPeter Brune PetscFunctionReturn(0); 149646217ecSPeter Brune } 150646217ecSPeter Brune 151eff52c0eSPeter Brune #undef __FUNCT__ 152c79ef259SPeter Brune #define __FUNCT__ "SNESFASSetCyclesOnLevel" 153c79ef259SPeter Brune /*@ 154722262beSPeter Brune SNESFASSetCyclesOnLevel - Sets the type cycles to use on a particular level. 155c79ef259SPeter Brune 156c79ef259SPeter Brune Logically Collective on SNES 157c79ef259SPeter Brune 158c79ef259SPeter Brune Input Parameters: 159c79ef259SPeter Brune + snes - the multigrid context 160c79ef259SPeter Brune . level - the level to set the number of cycles on 161c79ef259SPeter Brune - cycles - the number of cycles -- 1 for V-cycle, 2 for W-cycle 162c79ef259SPeter Brune 163c79ef259SPeter Brune Level: advanced 164c79ef259SPeter Brune 165c79ef259SPeter Brune .keywords: MG, set, cycles, V-cycle, W-cycle, multigrid 166c79ef259SPeter Brune 167c79ef259SPeter Brune .seealso: SNESFASSetCycles() 168c79ef259SPeter Brune @*/ 169c79ef259SPeter Brune PetscErrorCode SNESFASSetCyclesOnLevel(SNES snes, PetscInt level, PetscInt cycles) { 170c79ef259SPeter Brune SNES_FAS * fas = (SNES_FAS *)snes->data; 171c79ef259SPeter Brune PetscInt top_level = fas->level,i; 172c79ef259SPeter Brune 173c79ef259SPeter Brune PetscFunctionBegin; 174c79ef259SPeter Brune if (level > top_level) 175c79ef259SPeter Brune SETERRQ1(((PetscObject)snes)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Bad level number %d in SNESFASSetCyclesOnLevel", level); 176c79ef259SPeter Brune /* get to the correct level */ 177c79ef259SPeter Brune for (i = fas->level; i > level; i--) { 178c79ef259SPeter Brune fas = (SNES_FAS *)fas->next->data; 179c79ef259SPeter Brune } 180c79ef259SPeter Brune if (fas->level != level) 181c79ef259SPeter Brune SETERRQ(((PetscObject)snes)->comm, PETSC_ERR_ARG_WRONG, "Inconsistent level labelling in SNESFASSetCyclesOnLevel"); 182c79ef259SPeter Brune fas->n_cycles = cycles; 183c79ef259SPeter Brune PetscFunctionReturn(0); 184c79ef259SPeter Brune } 185c79ef259SPeter Brune 186c79ef259SPeter Brune #undef __FUNCT__ 187eff52c0eSPeter Brune #define __FUNCT__ "SNESFASSetGS" 188aeed3662SMatthew G Knepley /*@C 189c79ef259SPeter Brune SNESFASSetGS - Sets a nonlinear GS smoother and if it should be used. 190c79ef259SPeter Brune Use SNESFASSetGSOnLevel() for more complicated staging of smoothers 191c79ef259SPeter Brune and nonlinear preconditioners. 192c79ef259SPeter Brune 193c79ef259SPeter Brune Logically Collective on SNES 194c79ef259SPeter Brune 195c79ef259SPeter Brune Input Parameters: 196c79ef259SPeter Brune + snes - the multigrid context 197c79ef259SPeter Brune . gsfunc - the nonlinear smoother function 198c79ef259SPeter Brune . ctx - the user context for the nonlinear smoother 199c79ef259SPeter Brune - use_gs - whether to use the nonlinear smoother or not 200c79ef259SPeter Brune 201c79ef259SPeter Brune Level: advanced 202c79ef259SPeter Brune 203c79ef259SPeter Brune .keywords: FAS, MG, set, cycles, gauss-seidel, multigrid 204c79ef259SPeter Brune 205c79ef259SPeter Brune .seealso: SNESSetGS(), SNESFASSetGSOnLevel() 206c79ef259SPeter Brune @*/ 207eff52c0eSPeter Brune PetscErrorCode SNESFASSetGS(SNES snes, PetscErrorCode (*gsfunc)(SNES,Vec,Vec,void *), void * ctx, PetscBool use_gs) { 208eff52c0eSPeter Brune PetscErrorCode ierr = 0; 209eff52c0eSPeter Brune SNES_FAS *fas = (SNES_FAS *)snes->data; 210eff52c0eSPeter Brune PetscFunctionBegin; 211eff52c0eSPeter Brune 212eff52c0eSPeter Brune if (gsfunc) { 213eff52c0eSPeter Brune ierr = SNESSetGS(snes, gsfunc, ctx);CHKERRQ(ierr); 214eff52c0eSPeter Brune /* push the provided GS up the tree */ 215eff52c0eSPeter Brune if (fas->next) ierr = SNESFASSetGS(fas->next, gsfunc, ctx, use_gs);CHKERRQ(ierr); 216eff52c0eSPeter Brune } else if (snes->ops->computegs) { 217eff52c0eSPeter Brune /* assume that the user has set the GS solver at this level */ 218eff52c0eSPeter Brune if (fas->next) ierr = SNESFASSetGS(fas->next, PETSC_NULL, PETSC_NULL, use_gs);CHKERRQ(ierr); 219eff52c0eSPeter Brune } else if (use_gs) { 220eff52c0eSPeter Brune SETERRQ1(((PetscObject)snes)->comm, PETSC_ERR_ARG_WRONG, "No user Gauss-Seidel function provided in SNESFASSetGS on level %d", fas->level); 221eff52c0eSPeter Brune } 222eff52c0eSPeter Brune PetscFunctionReturn(0); 223eff52c0eSPeter Brune } 224eff52c0eSPeter Brune 225eff52c0eSPeter Brune #undef __FUNCT__ 226eff52c0eSPeter Brune #define __FUNCT__ "SNESFASSetGSOnLevel" 227aeed3662SMatthew G Knepley /*@C 228c79ef259SPeter Brune SNESFASSetGSOnLevel - Sets the nonlinear smoother on a particular level. 229c79ef259SPeter Brune 230c79ef259SPeter Brune Logically Collective on SNES 231c79ef259SPeter Brune 232c79ef259SPeter Brune Input Parameters: 233c79ef259SPeter Brune + snes - the multigrid context 234c79ef259SPeter Brune . level - the level to set the nonlinear smoother on 235c79ef259SPeter Brune . gsfunc - the nonlinear smoother function 236c79ef259SPeter Brune . ctx - the user context for the nonlinear smoother 237c79ef259SPeter Brune - use_gs - whether to use the nonlinear smoother or not 238c79ef259SPeter Brune 239c79ef259SPeter Brune Level: advanced 240c79ef259SPeter Brune 241c79ef259SPeter Brune .keywords: FAS, MG, set, cycles, Gauss-Seidel, multigrid 242c79ef259SPeter Brune 243c79ef259SPeter Brune .seealso: SNESSetGS(), SNESFASSetGS() 244c79ef259SPeter Brune @*/ 245eff52c0eSPeter Brune PetscErrorCode SNESFASSetGSOnLevel(SNES snes, PetscInt level, PetscErrorCode (*gsfunc)(SNES,Vec,Vec,void *), void * ctx, PetscBool use_gs) { 246eff52c0eSPeter Brune SNES_FAS *fas = (SNES_FAS *)snes->data; 247eff52c0eSPeter Brune PetscErrorCode ierr; 248eff52c0eSPeter Brune PetscInt top_level = fas->level,i; 249eff52c0eSPeter Brune SNES cur_snes = snes; 250eff52c0eSPeter Brune PetscFunctionBegin; 251eff52c0eSPeter Brune if (level > top_level) 252eff52c0eSPeter Brune SETERRQ1(((PetscObject)snes)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Bad level number %d in SNESFASSetCyclesOnLevel", level); 253eff52c0eSPeter Brune /* get to the correct level */ 254eff52c0eSPeter Brune for (i = fas->level; i > level; i--) { 255eff52c0eSPeter Brune fas = (SNES_FAS *)fas->next->data; 256eff52c0eSPeter Brune cur_snes = fas->next; 257eff52c0eSPeter Brune } 258eff52c0eSPeter Brune if (fas->level != level) 259eff52c0eSPeter Brune SETERRQ(((PetscObject)snes)->comm, PETSC_ERR_ARG_WRONG, "Inconsistent level labelling in SNESFASSetCyclesOnLevel"); 260eff52c0eSPeter Brune if (gsfunc) { 2616273346dSPeter Brune ierr = SNESSetGS(cur_snes, gsfunc, ctx);CHKERRQ(ierr); 262eff52c0eSPeter Brune } 263eff52c0eSPeter Brune PetscFunctionReturn(0); 264eff52c0eSPeter Brune } 265eff52c0eSPeter Brune 266646217ecSPeter Brune #undef __FUNCT__ 267421d9b32SPeter Brune #define __FUNCT__ "SNESFASGetSNES" 268c79ef259SPeter Brune /*@ 269c79ef259SPeter Brune SNESFASGetSNES - Gets the SNES corresponding to a particular 270c79ef259SPeter Brune level of the FAS hierarchy. 271c79ef259SPeter Brune 272c79ef259SPeter Brune Input Parameters: 273c79ef259SPeter Brune + snes - the multigrid context 274c79ef259SPeter Brune level - the level to get 275c79ef259SPeter Brune - lsnes - whether to use the nonlinear smoother or not 276c79ef259SPeter Brune 277c79ef259SPeter Brune Level: advanced 278c79ef259SPeter Brune 279c79ef259SPeter Brune .keywords: FAS, MG, set, cycles, Gauss-Seidel, multigrid 280c79ef259SPeter Brune 281c79ef259SPeter Brune .seealso: SNESFASSetLevels(), SNESFASGetLevels() 282c79ef259SPeter Brune @*/ 283421d9b32SPeter Brune PetscErrorCode SNESFASGetSNES(SNES snes, PetscInt level, SNES * lsnes) { 284421d9b32SPeter Brune SNES_FAS * fas = (SNES_FAS *)snes->data; 285421d9b32SPeter Brune PetscInt levels = fas->level; 286421d9b32SPeter Brune PetscInt i; 287421d9b32SPeter Brune PetscFunctionBegin; 288421d9b32SPeter Brune *lsnes = snes; 289421d9b32SPeter Brune if (fas->level < level) { 290421d9b32SPeter Brune SETERRQ(((PetscObject)snes)->comm, PETSC_ERR_ARG_OUTOFRANGE, "SNESFASGetSNES should only be called on a finer SNESFAS instance than the level."); 291421d9b32SPeter Brune } 292421d9b32SPeter Brune if (level > levels - 1) { 293421d9b32SPeter Brune SETERRQ(((PetscObject)snes)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Level %d doesn't exist in the SNESFAS."); 294421d9b32SPeter Brune } 295421d9b32SPeter Brune for (i = fas->level; i > level; i--) { 296421d9b32SPeter Brune *lsnes = fas->next; 297421d9b32SPeter Brune fas = (SNES_FAS *)(*lsnes)->data; 298421d9b32SPeter Brune } 299421d9b32SPeter Brune if (fas->level != level) SETERRQ(((PetscObject)snes)->comm, PETSC_ERR_ARG_OUTOFRANGE, "SNESFASGetSNES didn't return the right level!"); 300421d9b32SPeter Brune PetscFunctionReturn(0); 301421d9b32SPeter Brune } 302421d9b32SPeter Brune 303421d9b32SPeter Brune #undef __FUNCT__ 30407144faaSPeter Brune #define __FUNCT__ "SNESFASSetType" 30507144faaSPeter Brune /*@ 30607144faaSPeter Brune SNESFASSetType - Sets the update and correction type used for FAS. 30707144faaSPeter Brune e 30807144faaSPeter Brune 30907144faaSPeter Brune 31007144faaSPeter Brune @*/ 31107144faaSPeter Brune PetscErrorCode SNESFASSetType(SNES snes,SNESFASType fastype) 31207144faaSPeter Brune { 31307144faaSPeter Brune SNES_FAS *fas = (SNES_FAS*)snes->data; 31407144faaSPeter Brune 31507144faaSPeter Brune PetscFunctionBegin; 31607144faaSPeter Brune PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 31707144faaSPeter Brune PetscValidLogicalCollectiveEnum(snes,fastype,2); 31807144faaSPeter Brune fas->fastype = fastype; 31907144faaSPeter Brune PetscFunctionReturn(0); 32007144faaSPeter Brune } 32107144faaSPeter Brune 32207144faaSPeter Brune 32307144faaSPeter Brune 32407144faaSPeter Brune #undef __FUNCT__ 325421d9b32SPeter Brune #define __FUNCT__ "SNESFASSetLevels" 326aeed3662SMatthew G Knepley /*@C 327c79ef259SPeter Brune SNESFASSetLevels - Sets the number of levels to use with FAS. 328c79ef259SPeter Brune Must be called before any other FAS routine. 329c79ef259SPeter Brune 330c79ef259SPeter Brune Input Parameters: 331c79ef259SPeter Brune + snes - the snes context 332c79ef259SPeter Brune . levels - the number of levels 333c79ef259SPeter Brune - comms - optional communicators for each level; this is to allow solving the coarser 334c79ef259SPeter Brune problems on smaller sets of processors. Use PETSC_NULL_OBJECT for default in 335c79ef259SPeter Brune Fortran. 336c79ef259SPeter Brune 337c79ef259SPeter Brune Level: intermediate 338c79ef259SPeter Brune 339c79ef259SPeter Brune Notes: 340c79ef259SPeter Brune If the number of levels is one then the multigrid uses the -fas_levels prefix 341c79ef259SPeter Brune for setting the level options rather than the -fas_coarse prefix. 342c79ef259SPeter Brune 343c79ef259SPeter Brune .keywords: FAS, MG, set, levels, multigrid 344c79ef259SPeter Brune 345c79ef259SPeter Brune .seealso: SNESFASGetLevels() 346c79ef259SPeter Brune @*/ 347421d9b32SPeter Brune PetscErrorCode SNESFASSetLevels(SNES snes, PetscInt levels, MPI_Comm * comms) { 348421d9b32SPeter Brune PetscErrorCode ierr; 349421d9b32SPeter Brune PetscInt i; 350421d9b32SPeter Brune SNES_FAS * fas = (SNES_FAS *)snes->data; 3516273346dSPeter Brune SNES prevsnes; 352421d9b32SPeter Brune MPI_Comm comm; 353421d9b32SPeter Brune PetscFunctionBegin; 354ee1fd11aSPeter Brune comm = ((PetscObject)snes)->comm; 355ee1fd11aSPeter Brune if (levels == fas->levels) { 356ee1fd11aSPeter Brune if (!comms) 357ee1fd11aSPeter Brune PetscFunctionReturn(0); 358ee1fd11aSPeter Brune } 359421d9b32SPeter Brune /* user has changed the number of levels; reset */ 360421d9b32SPeter Brune ierr = SNESReset(snes);CHKERRQ(ierr); 361421d9b32SPeter Brune /* destroy any coarser levels if necessary */ 362421d9b32SPeter Brune if (fas->next) SNESDestroy(&fas->next);CHKERRQ(ierr); 363ee1fd11aSPeter Brune fas->next = PETSC_NULL; 3646273346dSPeter Brune fas->previous = PETSC_NULL; 3656273346dSPeter Brune prevsnes = snes; 366421d9b32SPeter Brune /* setup the finest level */ 367421d9b32SPeter Brune for (i = levels - 1; i >= 0; i--) { 368421d9b32SPeter Brune if (comms) comm = comms[i]; 369421d9b32SPeter Brune fas->level = i; 370421d9b32SPeter Brune fas->levels = levels; 371ee1fd11aSPeter Brune fas->next = PETSC_NULL; 372421d9b32SPeter Brune if (i > 0) { 373421d9b32SPeter Brune ierr = SNESCreate(comm, &fas->next);CHKERRQ(ierr); 3744a6b3fb8SBarry Smith ierr = SNESSetOptionsPrefix(fas->next,((PetscObject)snes)->prefix);CHKERRQ(ierr); 375421d9b32SPeter Brune ierr = SNESSetType(fas->next, SNESFAS);CHKERRQ(ierr); 376794bee33SPeter Brune ierr = PetscObjectIncrementTabLevel((PetscObject)fas->next, (PetscObject)snes, levels - i);CHKERRQ(ierr); 3776273346dSPeter Brune ((SNES_FAS *)fas->next->data)->previous = prevsnes; 3786273346dSPeter Brune prevsnes = fas->next; 3796273346dSPeter Brune fas = (SNES_FAS *)prevsnes->data; 380421d9b32SPeter Brune } 381421d9b32SPeter Brune } 382421d9b32SPeter Brune PetscFunctionReturn(0); 383421d9b32SPeter Brune } 384421d9b32SPeter Brune 385421d9b32SPeter Brune #undef __FUNCT__ 386c79ef259SPeter Brune #define __FUNCT__ "SNESFASSetNumberSmoothUp" 387c79ef259SPeter Brune /*@ 388c79ef259SPeter Brune SNESFASSetNumberSmoothUp - Sets the number of post-smoothing steps to 389c79ef259SPeter Brune use on all levels. 390c79ef259SPeter Brune 391fde0ff24SPeter Brune Logically Collective on SNES 392c79ef259SPeter Brune 393c79ef259SPeter Brune Input Parameters: 394c79ef259SPeter Brune + snes - the multigrid context 395c79ef259SPeter Brune - n - the number of smoothing steps 396c79ef259SPeter Brune 397c79ef259SPeter Brune Options Database Key: 398d28543b3SPeter Brune . -snes_fas_smoothup <n> - Sets number of pre-smoothing steps 399c79ef259SPeter Brune 400c79ef259SPeter Brune Level: advanced 401c79ef259SPeter Brune 402c79ef259SPeter Brune .keywords: FAS, MG, smooth, down, pre-smoothing, steps, multigrid 403c79ef259SPeter Brune 404c79ef259SPeter Brune .seealso: SNESFASSetNumberSmoothDown() 405c79ef259SPeter Brune @*/ 406c79ef259SPeter Brune PetscErrorCode SNESFASSetNumberSmoothUp(SNES snes, PetscInt n) { 407c79ef259SPeter Brune SNES_FAS * fas = (SNES_FAS *)snes->data; 408c79ef259SPeter Brune PetscErrorCode ierr = 0; 409c79ef259SPeter Brune PetscFunctionBegin; 410c79ef259SPeter Brune fas->max_up_it = n; 411c79ef259SPeter Brune if (fas->next) { 412c79ef259SPeter Brune ierr = SNESFASSetNumberSmoothUp(fas->next, n);CHKERRQ(ierr); 413c79ef259SPeter Brune } 414c79ef259SPeter Brune PetscFunctionReturn(0); 415c79ef259SPeter Brune } 416c79ef259SPeter Brune 417c79ef259SPeter Brune #undef __FUNCT__ 418c79ef259SPeter Brune #define __FUNCT__ "SNESFASSetNumberSmoothDown" 419c79ef259SPeter Brune /*@ 420c79ef259SPeter Brune SNESFASSetNumberSmoothDown - Sets the number of pre-smoothing steps to 421c79ef259SPeter Brune use on all levels. 422c79ef259SPeter Brune 423fde0ff24SPeter Brune Logically Collective on SNES 424c79ef259SPeter Brune 425c79ef259SPeter Brune Input Parameters: 426c79ef259SPeter Brune + snes - the multigrid context 427c79ef259SPeter Brune - n - the number of smoothing steps 428c79ef259SPeter Brune 429c79ef259SPeter Brune Options Database Key: 430d28543b3SPeter Brune . -snes_fas_smoothdown <n> - Sets number of pre-smoothing steps 431c79ef259SPeter Brune 432c79ef259SPeter Brune Level: advanced 433c79ef259SPeter Brune 434c79ef259SPeter Brune .keywords: FAS, MG, smooth, down, pre-smoothing, steps, multigrid 435c79ef259SPeter Brune 436c79ef259SPeter Brune .seealso: SNESFASSetNumberSmoothUp() 437c79ef259SPeter Brune @*/ 438c79ef259SPeter Brune PetscErrorCode SNESFASSetNumberSmoothDown(SNES snes, PetscInt n) { 439c79ef259SPeter Brune SNES_FAS * fas = (SNES_FAS *)snes->data; 440c79ef259SPeter Brune PetscErrorCode ierr = 0; 441c79ef259SPeter Brune PetscFunctionBegin; 442c79ef259SPeter Brune fas->max_down_it = n; 443c79ef259SPeter Brune if (fas->next) { 444c79ef259SPeter Brune ierr = SNESFASSetNumberSmoothDown(fas->next, n);CHKERRQ(ierr); 445c79ef259SPeter Brune } 446c79ef259SPeter Brune PetscFunctionReturn(0); 447c79ef259SPeter Brune } 448c79ef259SPeter Brune 449c79ef259SPeter Brune #undef __FUNCT__ 450421d9b32SPeter Brune #define __FUNCT__ "SNESFASSetInterpolation" 451c79ef259SPeter Brune /*@ 452c79ef259SPeter Brune SNESFASSetInterpolation - Sets the function to be used to calculate the 453c79ef259SPeter Brune interpolation from l-1 to the lth level 454c79ef259SPeter Brune 455c79ef259SPeter Brune Input Parameters: 456c79ef259SPeter Brune + snes - the multigrid context 457c79ef259SPeter Brune . mat - the interpolation operator 458c79ef259SPeter Brune - level - the level (0 is coarsest) to supply [do not supply 0] 459c79ef259SPeter Brune 460c79ef259SPeter Brune Level: advanced 461c79ef259SPeter Brune 462c79ef259SPeter Brune Notes: 463c79ef259SPeter Brune Usually this is the same matrix used also to set the restriction 464c79ef259SPeter Brune for the same level. 465c79ef259SPeter Brune 466c79ef259SPeter Brune One can pass in the interpolation matrix or its transpose; PETSc figures 467c79ef259SPeter Brune out from the matrix size which one it is. 468c79ef259SPeter Brune 469c79ef259SPeter Brune .keywords: FAS, multigrid, set, interpolate, level 470c79ef259SPeter Brune 471c79ef259SPeter Brune .seealso: SNESFASSetInjection(), SNESFASSetRestriction(), SNESFASSetRscale() 472c79ef259SPeter Brune @*/ 473421d9b32SPeter Brune PetscErrorCode SNESFASSetInterpolation(SNES snes, PetscInt level, Mat mat) { 474421d9b32SPeter Brune SNES_FAS * fas = (SNES_FAS *)snes->data; 475d9ce41dcSBarry Smith PetscInt top_level = fas->level,i; 476421d9b32SPeter Brune 477421d9b32SPeter Brune PetscFunctionBegin; 478421d9b32SPeter Brune if (level > top_level) 479421d9b32SPeter Brune SETERRQ1(((PetscObject)snes)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Bad level number %d in SNESFASSetInterpolation", level); 480421d9b32SPeter Brune /* get to the correct level */ 481d9ce41dcSBarry Smith for (i = fas->level; i > level; i--) { 482421d9b32SPeter Brune fas = (SNES_FAS *)fas->next->data; 483421d9b32SPeter Brune } 484421d9b32SPeter Brune if (fas->level != level) 485421d9b32SPeter Brune SETERRQ(((PetscObject)snes)->comm, PETSC_ERR_ARG_WRONG, "Inconsistent level labelling in SNESFASSetInterpolation"); 486421d9b32SPeter Brune fas->interpolate = mat; 487421d9b32SPeter Brune PetscFunctionReturn(0); 488421d9b32SPeter Brune } 489421d9b32SPeter Brune 490421d9b32SPeter Brune #undef __FUNCT__ 491421d9b32SPeter Brune #define __FUNCT__ "SNESFASSetRestriction" 492c79ef259SPeter Brune /*@ 493c79ef259SPeter Brune SNESFASSetRestriction - Sets the function to be used to restrict the defect 494c79ef259SPeter Brune from level l to l-1. 495c79ef259SPeter Brune 496c79ef259SPeter Brune Input Parameters: 497c79ef259SPeter Brune + snes - the multigrid context 498c79ef259SPeter Brune . mat - the restriction matrix 499c79ef259SPeter Brune - level - the level (0 is coarsest) to supply [Do not supply 0] 500c79ef259SPeter Brune 501c79ef259SPeter Brune Level: advanced 502c79ef259SPeter Brune 503c79ef259SPeter Brune Notes: 504c79ef259SPeter Brune Usually this is the same matrix used also to set the interpolation 505c79ef259SPeter Brune for the same level. 506c79ef259SPeter Brune 507c79ef259SPeter Brune One can pass in the interpolation matrix or its transpose; PETSc figures 508c79ef259SPeter Brune out from the matrix size which one it is. 509c79ef259SPeter Brune 510fde0ff24SPeter Brune If you do not set this, the transpose of the Mat set with SNESFASSetInterpolation() 511c79ef259SPeter Brune is used. 512c79ef259SPeter Brune 513c79ef259SPeter Brune .keywords: FAS, MG, set, multigrid, restriction, level 514c79ef259SPeter Brune 515c79ef259SPeter Brune .seealso: SNESFASSetInterpolation(), SNESFASSetInjection() 516c79ef259SPeter Brune @*/ 517421d9b32SPeter Brune PetscErrorCode SNESFASSetRestriction(SNES snes, PetscInt level, Mat mat) { 518421d9b32SPeter Brune SNES_FAS * fas = (SNES_FAS *)snes->data; 519d9ce41dcSBarry Smith PetscInt top_level = fas->level,i; 520421d9b32SPeter Brune 521421d9b32SPeter Brune PetscFunctionBegin; 522421d9b32SPeter Brune if (level > top_level) 523421d9b32SPeter Brune SETERRQ1(((PetscObject)snes)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Bad level number %d in SNESFASSetRestriction", level); 524421d9b32SPeter Brune /* get to the correct level */ 525d9ce41dcSBarry Smith for (i = fas->level; i > level; i--) { 526421d9b32SPeter Brune fas = (SNES_FAS *)fas->next->data; 527421d9b32SPeter Brune } 528421d9b32SPeter Brune if (fas->level != level) 529421d9b32SPeter Brune SETERRQ(((PetscObject)snes)->comm, PETSC_ERR_ARG_WRONG, "Inconsistent level labelling in SNESFASSetRestriction"); 530421d9b32SPeter Brune fas->restrct = mat; 531421d9b32SPeter Brune PetscFunctionReturn(0); 532421d9b32SPeter Brune } 533421d9b32SPeter Brune 534efe1f98aSPeter Brune 535421d9b32SPeter Brune #undef __FUNCT__ 536421d9b32SPeter Brune #define __FUNCT__ "SNESFASSetRScale" 537c79ef259SPeter Brune /*@ 538c79ef259SPeter Brune SNESFASSetRScale - Sets the scaling factor of the restriction 539c79ef259SPeter Brune operator from level l to l-1. 540c79ef259SPeter Brune 541c79ef259SPeter Brune Input Parameters: 542c79ef259SPeter Brune + snes - the multigrid context 543c79ef259SPeter Brune . rscale - the restriction scaling 544c79ef259SPeter Brune - level - the level (0 is coarsest) to supply [Do not supply 0] 545c79ef259SPeter Brune 546c79ef259SPeter Brune Level: advanced 547c79ef259SPeter Brune 548c79ef259SPeter Brune Notes: 549c79ef259SPeter Brune This is only used in the case that the injection is not set. 550c79ef259SPeter Brune 551c79ef259SPeter Brune .keywords: FAS, MG, set, multigrid, restriction, level 552c79ef259SPeter Brune 553c79ef259SPeter Brune .seealso: SNESFASSetInjection(), SNESFASSetRestriction() 554c79ef259SPeter Brune @*/ 555421d9b32SPeter Brune PetscErrorCode SNESFASSetRScale(SNES snes, PetscInt level, Vec rscale) { 556421d9b32SPeter Brune SNES_FAS * fas = (SNES_FAS *)snes->data; 557d9ce41dcSBarry Smith PetscInt top_level = fas->level,i; 558421d9b32SPeter Brune 559421d9b32SPeter Brune PetscFunctionBegin; 560421d9b32SPeter Brune if (level > top_level) 561421d9b32SPeter Brune SETERRQ1(((PetscObject)snes)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Bad level number %d in SNESFASSetRestriction", level); 562421d9b32SPeter Brune /* get to the correct level */ 563d9ce41dcSBarry Smith for (i = fas->level; i > level; i--) { 564421d9b32SPeter Brune fas = (SNES_FAS *)fas->next->data; 565421d9b32SPeter Brune } 566421d9b32SPeter Brune if (fas->level != level) 567421d9b32SPeter Brune SETERRQ(((PetscObject)snes)->comm, PETSC_ERR_ARG_WRONG, "Inconsistent level labelling in SNESFASSetRestriction"); 568421d9b32SPeter Brune fas->rscale = rscale; 569421d9b32SPeter Brune PetscFunctionReturn(0); 570421d9b32SPeter Brune } 571421d9b32SPeter Brune 572efe1f98aSPeter Brune 573efe1f98aSPeter Brune #undef __FUNCT__ 574efe1f98aSPeter Brune #define __FUNCT__ "SNESFASSetInjection" 575c79ef259SPeter Brune /*@ 576c79ef259SPeter Brune SNESFASSetInjection - Sets the function to be used to inject the solution 577c79ef259SPeter Brune from level l to l-1. 578c79ef259SPeter Brune 579c79ef259SPeter Brune Input Parameters: 580c79ef259SPeter Brune + snes - the multigrid context 581c79ef259SPeter Brune . mat - the restriction matrix 582c79ef259SPeter Brune - level - the level (0 is coarsest) to supply [Do not supply 0] 583c79ef259SPeter Brune 584c79ef259SPeter Brune Level: advanced 585c79ef259SPeter Brune 586c79ef259SPeter Brune Notes: 587c79ef259SPeter Brune If you do not set this, the restriction and rscale is used to 588c79ef259SPeter Brune project the solution instead. 589c79ef259SPeter Brune 590c79ef259SPeter Brune .keywords: FAS, MG, set, multigrid, restriction, level 591c79ef259SPeter Brune 592c79ef259SPeter Brune .seealso: SNESFASSetInterpolation(), SNESFASSetRestriction() 593c79ef259SPeter Brune @*/ 594efe1f98aSPeter Brune PetscErrorCode SNESFASSetInjection(SNES snes, PetscInt level, Mat mat) { 595efe1f98aSPeter Brune SNES_FAS * fas = (SNES_FAS *)snes->data; 596efe1f98aSPeter Brune PetscInt top_level = fas->level,i; 597efe1f98aSPeter Brune 598efe1f98aSPeter Brune PetscFunctionBegin; 599efe1f98aSPeter Brune if (level > top_level) 600efe1f98aSPeter Brune SETERRQ1(((PetscObject)snes)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Bad level number %d in SNESFASSetInjection", level); 601efe1f98aSPeter Brune /* get to the correct level */ 602efe1f98aSPeter Brune for (i = fas->level; i > level; i--) { 603efe1f98aSPeter Brune fas = (SNES_FAS *)fas->next->data; 604efe1f98aSPeter Brune } 605efe1f98aSPeter Brune if (fas->level != level) 606efe1f98aSPeter Brune SETERRQ(((PetscObject)snes)->comm, PETSC_ERR_ARG_WRONG, "Inconsistent level labelling in SNESFASSetInjection"); 607efe1f98aSPeter Brune fas->inject = mat; 608efe1f98aSPeter Brune PetscFunctionReturn(0); 609efe1f98aSPeter Brune } 610efe1f98aSPeter Brune 611421d9b32SPeter Brune #undef __FUNCT__ 612421d9b32SPeter Brune #define __FUNCT__ "SNESReset_FAS" 613421d9b32SPeter Brune PetscErrorCode SNESReset_FAS(SNES snes) 614421d9b32SPeter Brune { 61577df8cc4SPeter Brune PetscErrorCode ierr = 0; 616421d9b32SPeter Brune SNES_FAS * fas = (SNES_FAS *)snes->data; 617421d9b32SPeter Brune 618421d9b32SPeter Brune PetscFunctionBegin; 619742fe5e2SPeter Brune if (fas->upsmooth) ierr = SNESReset(fas->upsmooth);CHKERRQ(ierr); 620742fe5e2SPeter Brune if (fas->downsmooth) ierr = SNESReset(fas->downsmooth);CHKERRQ(ierr); 6213dccd265SPeter Brune if (fas->inject) { 6223dccd265SPeter Brune ierr = MatDestroy(&fas->inject);CHKERRQ(ierr); 6233dccd265SPeter Brune } 6243dccd265SPeter Brune if (fas->interpolate == fas->restrct) { 6253dccd265SPeter Brune if (fas->interpolate) ierr = MatDestroy(&fas->interpolate);CHKERRQ(ierr); 6263dccd265SPeter Brune fas->restrct = PETSC_NULL; 6273dccd265SPeter Brune } else { 6283dccd265SPeter Brune if (fas->interpolate) ierr = MatDestroy(&fas->interpolate);CHKERRQ(ierr); 6293dccd265SPeter Brune if (fas->restrct) ierr = MatDestroy(&fas->restrct);CHKERRQ(ierr); 6303dccd265SPeter Brune } 6313dccd265SPeter Brune if (fas->rscale) ierr = VecDestroy(&fas->rscale);CHKERRQ(ierr); 6323dccd265SPeter Brune 6333dccd265SPeter Brune if (fas->upsmooth) ierr = SNESReset(fas->upsmooth);CHKERRQ(ierr); 6343dccd265SPeter Brune if (fas->downsmooth) ierr = SNESReset(fas->downsmooth);CHKERRQ(ierr); 635742fe5e2SPeter Brune if (fas->next) ierr = SNESReset(fas->next);CHKERRQ(ierr); 636421d9b32SPeter Brune PetscFunctionReturn(0); 637421d9b32SPeter Brune } 638421d9b32SPeter Brune 639421d9b32SPeter Brune #undef __FUNCT__ 640421d9b32SPeter Brune #define __FUNCT__ "SNESDestroy_FAS" 641421d9b32SPeter Brune PetscErrorCode SNESDestroy_FAS(SNES snes) 642421d9b32SPeter Brune { 643421d9b32SPeter Brune SNES_FAS * fas = (SNES_FAS *)snes->data; 644742fe5e2SPeter Brune PetscErrorCode ierr = 0; 645421d9b32SPeter Brune 646421d9b32SPeter Brune PetscFunctionBegin; 647421d9b32SPeter Brune /* recursively resets and then destroys */ 64851e86f29SPeter Brune if (fas->upsmooth) ierr = SNESDestroy(&fas->upsmooth);CHKERRQ(ierr); 64951e86f29SPeter Brune if (fas->downsmooth) ierr = SNESDestroy(&fas->downsmooth);CHKERRQ(ierr); 650421d9b32SPeter Brune if (fas->next) ierr = SNESDestroy(&fas->next);CHKERRQ(ierr); 651421d9b32SPeter Brune ierr = PetscFree(fas);CHKERRQ(ierr); 652ee1fd11aSPeter Brune 653421d9b32SPeter Brune PetscFunctionReturn(0); 654421d9b32SPeter Brune } 655421d9b32SPeter Brune 656421d9b32SPeter Brune #undef __FUNCT__ 657421d9b32SPeter Brune #define __FUNCT__ "SNESSetUp_FAS" 658421d9b32SPeter Brune PetscErrorCode SNESSetUp_FAS(SNES snes) 659421d9b32SPeter Brune { 66048bfdf8aSPeter Brune SNES_FAS *fas = (SNES_FAS *) snes->data; 661421d9b32SPeter Brune PetscErrorCode ierr; 662efe1f98aSPeter Brune VecScatter injscatter; 663d1adcc6fSPeter Brune PetscInt dm_levels; 6643dccd265SPeter Brune Vec vec_sol, vec_func, vec_sol_update, vec_rhs; /* preserve these if they're set through the reset */ 665d1adcc6fSPeter Brune 666421d9b32SPeter Brune PetscFunctionBegin; 667eff52c0eSPeter Brune 668cc05f883SPeter Brune if (fas->usedmfornumberoflevels && (fas->level == fas->levels - 1)) { 669d1adcc6fSPeter Brune ierr = DMGetRefineLevel(snes->dm,&dm_levels);CHKERRQ(ierr); 670d1adcc6fSPeter Brune dm_levels++; 671cc05f883SPeter Brune if (dm_levels > fas->levels) { 6723dccd265SPeter Brune 6733dccd265SPeter Brune /* we don't want the solution and func vectors to be destroyed in the SNESReset when it's called in SNESSetUp_FAS*/ 6743dccd265SPeter Brune vec_sol = snes->vec_sol; 6753dccd265SPeter Brune vec_func = snes->vec_func; 6763dccd265SPeter Brune vec_sol_update = snes->vec_sol_update; 6773dccd265SPeter Brune vec_rhs = snes->vec_rhs; 6783dccd265SPeter Brune snes->vec_sol = PETSC_NULL; 6793dccd265SPeter Brune snes->vec_func = PETSC_NULL; 6803dccd265SPeter Brune snes->vec_sol_update = PETSC_NULL; 6813dccd265SPeter Brune snes->vec_rhs = PETSC_NULL; 6823dccd265SPeter Brune 6833dccd265SPeter Brune /* reset the number of levels */ 684d1adcc6fSPeter Brune ierr = SNESFASSetLevels(snes,dm_levels,PETSC_NULL);CHKERRQ(ierr); 685cc05f883SPeter Brune ierr = SNESSetFromOptions(snes);CHKERRQ(ierr); 6863dccd265SPeter Brune 6873dccd265SPeter Brune snes->vec_sol = vec_sol; 6883dccd265SPeter Brune snes->vec_func = vec_func; 6893dccd265SPeter Brune snes->vec_rhs = vec_rhs; 6903dccd265SPeter Brune snes->vec_sol_update = vec_sol_update; 691d1adcc6fSPeter Brune } 692d1adcc6fSPeter Brune } 693d1adcc6fSPeter Brune 6943dccd265SPeter Brune if (fas->level != fas->levels - 1) snes->gridsequence = 0; /* no grid sequencing inside the multigrid hierarchy! */ 6953dccd265SPeter Brune 69607144faaSPeter Brune if (fas->fastype == SNES_FAS_MULTIPLICATIVE) { 697fde0ff24SPeter Brune ierr = SNESDefaultGetWork(snes, 4);CHKERRQ(ierr); /* work vectors used for intergrid transfers */ 69807144faaSPeter Brune } else { 699ddebd997SPeter Brune ierr = SNESDefaultGetWork(snes, 4);CHKERRQ(ierr); /* work vectors used for intergrid transfers */ 70007144faaSPeter Brune } 701cc05f883SPeter Brune 70248bfdf8aSPeter Brune /* setup the pre and post smoothers and set their function, jacobian, and gs evaluation routines if the user has neglected this */ 70348bfdf8aSPeter Brune if (fas->upsmooth) { 70448bfdf8aSPeter Brune if (snes->ops->computefunction && !fas->upsmooth->ops->computefunction) { 70548bfdf8aSPeter Brune ierr = SNESSetFunction(fas->upsmooth, PETSC_NULL, snes->ops->computefunction, snes->funP);CHKERRQ(ierr); 70648bfdf8aSPeter Brune } 70748bfdf8aSPeter Brune if (snes->ops->computejacobian && !fas->upsmooth->ops->computejacobian) { 70848bfdf8aSPeter Brune ierr = SNESSetJacobian(fas->upsmooth, fas->upsmooth->jacobian, fas->upsmooth->jacobian_pre, snes->ops->computejacobian, snes->jacP);CHKERRQ(ierr); 70948bfdf8aSPeter Brune } 71048bfdf8aSPeter Brune if (snes->ops->computegs && !fas->upsmooth->ops->computegs) { 71148bfdf8aSPeter Brune ierr = SNESSetGS(fas->upsmooth, snes->ops->computegs, snes->gsP);CHKERRQ(ierr); 71248bfdf8aSPeter Brune } 713fde0ff24SPeter Brune ierr = SNESSetFromOptions(fas->upsmooth);CHKERRQ(ierr); 71448bfdf8aSPeter Brune } 71548bfdf8aSPeter Brune if (fas->downsmooth) { 71648bfdf8aSPeter Brune if (snes->ops->computefunction && !fas->downsmooth->ops->computefunction) { 71748bfdf8aSPeter Brune ierr = SNESSetFunction(fas->downsmooth, PETSC_NULL, snes->ops->computefunction, snes->funP);CHKERRQ(ierr); 71848bfdf8aSPeter Brune } 71948bfdf8aSPeter Brune if (snes->ops->computejacobian && !fas->downsmooth->ops->computejacobian) { 72048bfdf8aSPeter Brune ierr = SNESSetJacobian(fas->downsmooth, fas->downsmooth->jacobian, fas->downsmooth->jacobian_pre, snes->ops->computejacobian, snes->jacP);CHKERRQ(ierr); 72148bfdf8aSPeter Brune } 72248bfdf8aSPeter Brune if (snes->ops->computegs && !fas->downsmooth->ops->computegs) { 72348bfdf8aSPeter Brune ierr = SNESSetGS(fas->downsmooth, snes->ops->computegs, snes->gsP);CHKERRQ(ierr); 72448bfdf8aSPeter Brune } 725fde0ff24SPeter Brune ierr = SNESSetFromOptions(fas->downsmooth);CHKERRQ(ierr); 7261a266240SBarry Smith } 72748bfdf8aSPeter Brune /*pass the smoother, function, and jacobian up to the next level if it's not user set already */ 728646217ecSPeter Brune if (fas->next) { 7296273346dSPeter Brune if (fas->galerkin) { 7306273346dSPeter Brune ierr = SNESSetFunction(fas->next, PETSC_NULL, SNESFASGalerkinDefaultFunction, fas->next);CHKERRQ(ierr); 7316273346dSPeter Brune } else { 73248bfdf8aSPeter Brune if (snes->ops->computefunction && !fas->next->ops->computefunction) { 73348bfdf8aSPeter Brune ierr = SNESSetFunction(fas->next, PETSC_NULL, snes->ops->computefunction, snes->funP);CHKERRQ(ierr); 73448bfdf8aSPeter Brune } 73548bfdf8aSPeter Brune if (snes->ops->computejacobian && !fas->next->ops->computejacobian) { 73648bfdf8aSPeter Brune ierr = SNESSetJacobian(fas->next, fas->next->jacobian, fas->next->jacobian_pre, snes->ops->computejacobian, snes->jacP);CHKERRQ(ierr); 73748bfdf8aSPeter Brune } 73848bfdf8aSPeter Brune if (snes->ops->computegs && !fas->next->ops->computegs) { 739646217ecSPeter Brune ierr = SNESSetGS(fas->next, snes->ops->computegs, snes->gsP);CHKERRQ(ierr); 740646217ecSPeter Brune } 741646217ecSPeter Brune } 7426273346dSPeter Brune } 743421d9b32SPeter Brune if (snes->dm) { 744421d9b32SPeter Brune /* construct EVERYTHING from the DM -- including the progressive set of smoothers */ 745421d9b32SPeter Brune if (fas->next) { 746421d9b32SPeter Brune /* for now -- assume the DM and the evaluation functions have been set externally */ 747ee78dd50SPeter Brune if (!fas->next->dm) { 748ee78dd50SPeter Brune ierr = DMCoarsen(snes->dm, ((PetscObject)fas->next)->comm, &fas->next->dm);CHKERRQ(ierr); 749ee78dd50SPeter Brune ierr = SNESSetDM(fas->next, fas->next->dm);CHKERRQ(ierr); 750ee78dd50SPeter Brune } 751421d9b32SPeter Brune /* set the interpolation and restriction from the DM */ 752ee78dd50SPeter Brune if (!fas->interpolate) { 753e727c939SJed Brown ierr = DMCreateInterpolation(fas->next->dm, snes->dm, &fas->interpolate, &fas->rscale);CHKERRQ(ierr); 754421d9b32SPeter Brune fas->restrct = fas->interpolate; 755421d9b32SPeter Brune } 756efe1f98aSPeter Brune /* set the injection from the DM */ 757efe1f98aSPeter Brune if (!fas->inject) { 758e727c939SJed Brown ierr = DMCreateInjection(fas->next->dm, snes->dm, &injscatter);CHKERRQ(ierr); 759efe1f98aSPeter Brune ierr = MatCreateScatter(((PetscObject)snes)->comm, injscatter, &fas->inject);CHKERRQ(ierr); 760efe1f98aSPeter Brune ierr = VecScatterDestroy(&injscatter);CHKERRQ(ierr); 761efe1f98aSPeter Brune } 762421d9b32SPeter Brune } 763ee78dd50SPeter Brune /* set the DMs of the pre and post-smoothers here */ 764*6bed07a3SBarry Smith if (fas->upsmooth) {ierr = SNESSetDM(fas->upsmooth, snes->dm);CHKERRQ(ierr);} 765*6bed07a3SBarry Smith if (fas->downsmooth){ierr = SNESSetDM(fas->downsmooth, snes->dm);CHKERRQ(ierr);} 766421d9b32SPeter Brune } 767cc05f883SPeter Brune 7686273346dSPeter Brune /* setup FAS work vectors */ 7696273346dSPeter Brune if (fas->galerkin) { 7706273346dSPeter Brune ierr = VecDuplicate(snes->vec_sol, &fas->Xg);CHKERRQ(ierr); 7716273346dSPeter Brune ierr = VecDuplicate(snes->vec_sol, &fas->Fg);CHKERRQ(ierr); 7726273346dSPeter Brune } 7736273346dSPeter Brune 774fa9694d7SPeter Brune if (fas->next) { 775fa9694d7SPeter Brune /* gotta set up the solution vector for this to work */ 776*6bed07a3SBarry Smith if (!fas->next->vec_sol) {ierr = VecDuplicate(fas->rscale, &fas->next->vec_sol);CHKERRQ(ierr);} 777742fe5e2SPeter Brune if (!fas->next->vec_rhs) {ierr = VecDuplicate(fas->rscale, &fas->next->vec_rhs);CHKERRQ(ierr);} 778fa9694d7SPeter Brune ierr = SNESSetUp(fas->next);CHKERRQ(ierr); 779fa9694d7SPeter Brune } 780fa9694d7SPeter Brune /* got to set them all up at once */ 781421d9b32SPeter Brune PetscFunctionReturn(0); 782421d9b32SPeter Brune } 783421d9b32SPeter Brune 784421d9b32SPeter Brune #undef __FUNCT__ 785421d9b32SPeter Brune #define __FUNCT__ "SNESSetFromOptions_FAS" 786421d9b32SPeter Brune PetscErrorCode SNESSetFromOptions_FAS(SNES snes) 787421d9b32SPeter Brune { 788ee78dd50SPeter Brune SNES_FAS *fas = (SNES_FAS *) snes->data; 789ee78dd50SPeter Brune PetscInt levels = 1; 790fde0ff24SPeter Brune PetscBool flg, smoothflg, smoothupflg, smoothdownflg, smoothcoarseflg = PETSC_FALSE, monflg; 791421d9b32SPeter Brune PetscErrorCode ierr; 792ee78dd50SPeter Brune const char *def_smooth = SNESNRICHARDSON; 793ee78dd50SPeter Brune char pre_type[256]; 794ee78dd50SPeter Brune char post_type[256]; 795ee78dd50SPeter Brune char monfilename[PETSC_MAX_PATH_LEN]; 79607144faaSPeter Brune SNESFASType fastype; 797fde0ff24SPeter Brune const char *optionsprefix; 798fde0ff24SPeter Brune const char *prefix; 799421d9b32SPeter Brune 800421d9b32SPeter Brune PetscFunctionBegin; 801c90fad12SPeter Brune ierr = PetscOptionsHead("SNESFAS Options-----------------------------------");CHKERRQ(ierr); 802ee78dd50SPeter Brune 803ee78dd50SPeter Brune /* number of levels -- only process on the finest level */ 804ee78dd50SPeter Brune if (fas->levels - 1 == fas->level) { 805ee78dd50SPeter Brune ierr = PetscOptionsInt("-snes_fas_levels", "Number of Levels", "SNESFASSetLevels", levels, &levels, &flg);CHKERRQ(ierr); 806c732cbdbSBarry Smith if (!flg && snes->dm) { 807c732cbdbSBarry Smith ierr = DMGetRefineLevel(snes->dm,&levels);CHKERRQ(ierr); 808c732cbdbSBarry Smith levels++; 809d1adcc6fSPeter Brune fas->usedmfornumberoflevels = PETSC_TRUE; 810c732cbdbSBarry Smith } 811ee78dd50SPeter Brune ierr = SNESFASSetLevels(snes, levels, PETSC_NULL);CHKERRQ(ierr); 812ee78dd50SPeter Brune } 813ee78dd50SPeter Brune 814ee78dd50SPeter Brune /* type of pre and/or post smoothers -- set both at once */ 815ee78dd50SPeter Brune ierr = PetscMemcpy(post_type, def_smooth, 256);CHKERRQ(ierr); 816ee78dd50SPeter Brune ierr = PetscMemcpy(pre_type, def_smooth, 256);CHKERRQ(ierr); 81707144faaSPeter Brune fastype = fas->fastype; 81807144faaSPeter Brune ierr = PetscOptionsEnum("-snes_fas_type","FAS correction type","SNESFASSetType",SNESFASTypes,(PetscEnum)fastype,(PetscEnum*)&fastype,&flg);CHKERRQ(ierr); 81907144faaSPeter Brune if (flg) { 82007144faaSPeter Brune ierr = SNESFASSetType(snes, fastype);CHKERRQ(ierr); 82107144faaSPeter Brune } 822ee78dd50SPeter Brune 823fde0ff24SPeter Brune ierr = SNESGetOptionsPrefix(snes, &optionsprefix);CHKERRQ(ierr); 824fde0ff24SPeter Brune 825fde0ff24SPeter Brune /* smoother setup options */ 826fde0ff24SPeter Brune ierr = PetscOptionsHasName(optionsprefix, "-fas_snes_type", &smoothflg);CHKERRQ(ierr); 827fde0ff24SPeter Brune ierr = PetscOptionsHasName(optionsprefix, "-fas_up_snes_type", &smoothupflg);CHKERRQ(ierr); 828fde0ff24SPeter Brune ierr = PetscOptionsHasName(optionsprefix, "-fas_down_snes_type", &smoothdownflg);CHKERRQ(ierr); 829fde0ff24SPeter Brune if (fas->level == 0) { 830fde0ff24SPeter Brune ierr = PetscOptionsHasName(optionsprefix, "-fas_coarse_snes_type", &smoothcoarseflg);CHKERRQ(ierr); 831fde0ff24SPeter Brune } 832ee78dd50SPeter Brune /* options for the number of preconditioning cycles and cycle type */ 833fde0ff24SPeter Brune 834d1adcc6fSPeter Brune ierr = PetscOptionsInt("-snes_fas_cycles","Number of cycles","SNESFASSetCycles",fas->n_cycles,&fas->n_cycles,&flg);CHKERRQ(ierr); 835ee78dd50SPeter Brune 8366273346dSPeter Brune ierr = PetscOptionsBool("-snes_fas_galerkin", "Form coarse problems with Galerkin","SNESFAS",fas->galerkin,&fas->galerkin,&flg);CHKERRQ(ierr); 8376273346dSPeter Brune 838646217ecSPeter Brune ierr = PetscOptionsString("-snes_fas_monitor","Monitor FAS progress","SNESMonitorSet","stdout",monfilename,PETSC_MAX_PATH_LEN,&monflg);CHKERRQ(ierr); 839ee78dd50SPeter Brune 840ee78dd50SPeter Brune 841421d9b32SPeter Brune ierr = PetscOptionsTail();CHKERRQ(ierr); 8428cc86e31SPeter Brune /* setup from the determined types if there is no pointwise procedure or smoother defined */ 843eff52c0eSPeter Brune 844fde0ff24SPeter Brune if ((!fas->downsmooth) && smoothcoarseflg) { 845fde0ff24SPeter Brune ierr = SNESGetOptionsPrefix(snes,&prefix);CHKERRQ(ierr); 846fde0ff24SPeter Brune ierr = SNESCreate(((PetscObject)snes)->comm, &fas->downsmooth);CHKERRQ(ierr); 847fde0ff24SPeter Brune ierr = SNESSetOptionsPrefix(fas->downsmooth,prefix);CHKERRQ(ierr); 848fde0ff24SPeter Brune ierr = SNESAppendOptionsPrefix(fas->downsmooth,"fas_coarse_");CHKERRQ(ierr); 849fde0ff24SPeter Brune ierr = PetscObjectIncrementTabLevel((PetscObject)fas->downsmooth, (PetscObject)snes, 1);CHKERRQ(ierr); 850fde0ff24SPeter Brune } 851fde0ff24SPeter Brune 852fde0ff24SPeter Brune if ((!fas->downsmooth) && smoothdownflg) { 8538cc86e31SPeter Brune ierr = SNESGetOptionsPrefix(snes,&prefix);CHKERRQ(ierr); 8548cc86e31SPeter Brune ierr = SNESCreate(((PetscObject)snes)->comm, &fas->downsmooth);CHKERRQ(ierr); 8558cc86e31SPeter Brune ierr = SNESSetOptionsPrefix(fas->downsmooth,prefix);CHKERRQ(ierr); 856fde0ff24SPeter Brune ierr = SNESAppendOptionsPrefix(fas->downsmooth,"fas_down_");CHKERRQ(ierr); 8578cc86e31SPeter Brune ierr = PetscObjectIncrementTabLevel((PetscObject)fas->downsmooth, (PetscObject)snes, 1);CHKERRQ(ierr); 8588cc86e31SPeter Brune } 8598cc86e31SPeter Brune 860fde0ff24SPeter Brune if ((!fas->upsmooth) && (fas->level != 0) && smoothupflg) { 86167339d5cSBarry Smith ierr = SNESGetOptionsPrefix(snes,&prefix);CHKERRQ(ierr); 862ee78dd50SPeter Brune ierr = SNESCreate(((PetscObject)snes)->comm, &fas->upsmooth);CHKERRQ(ierr); 86367339d5cSBarry Smith ierr = SNESSetOptionsPrefix(fas->upsmooth,prefix);CHKERRQ(ierr); 864fde0ff24SPeter Brune ierr = SNESAppendOptionsPrefix(fas->upsmooth,"fas_up_");CHKERRQ(ierr); 865293a7e31SPeter Brune ierr = PetscObjectIncrementTabLevel((PetscObject)fas->upsmooth, (PetscObject)snes, 1);CHKERRQ(ierr); 866ee78dd50SPeter Brune } 867fde0ff24SPeter Brune 868fde0ff24SPeter Brune if ((!fas->downsmooth) && smoothflg) { 869fde0ff24SPeter Brune ierr = SNESGetOptionsPrefix(snes,&prefix);CHKERRQ(ierr); 870fde0ff24SPeter Brune ierr = SNESCreate(((PetscObject)snes)->comm, &fas->downsmooth);CHKERRQ(ierr); 871fde0ff24SPeter Brune ierr = SNESSetOptionsPrefix(fas->downsmooth,prefix);CHKERRQ(ierr); 872fde0ff24SPeter Brune ierr = SNESAppendOptionsPrefix(fas->downsmooth,"fas_");CHKERRQ(ierr); 873fde0ff24SPeter Brune ierr = PetscObjectIncrementTabLevel((PetscObject)fas->downsmooth, (PetscObject)snes, 1);CHKERRQ(ierr); 874fde0ff24SPeter Brune } 875fde0ff24SPeter Brune 876fde0ff24SPeter Brune if ((!fas->upsmooth) && (fas->level != 0) && smoothflg) { 877fde0ff24SPeter Brune ierr = SNESGetOptionsPrefix(snes,&prefix);CHKERRQ(ierr); 878fde0ff24SPeter Brune ierr = SNESCreate(((PetscObject)snes)->comm, &fas->upsmooth);CHKERRQ(ierr); 879fde0ff24SPeter Brune ierr = SNESSetOptionsPrefix(fas->upsmooth,prefix);CHKERRQ(ierr); 880fde0ff24SPeter Brune ierr = SNESAppendOptionsPrefix(fas->upsmooth,"fas_");CHKERRQ(ierr); 881fde0ff24SPeter Brune ierr = PetscObjectIncrementTabLevel((PetscObject)fas->upsmooth, (PetscObject)snes, 1);CHKERRQ(ierr); 882fde0ff24SPeter Brune } 883fde0ff24SPeter Brune 8841a266240SBarry Smith if (fas->upsmooth) { 885fde0ff24SPeter Brune ierr = SNESSetTolerances(fas->upsmooth, fas->upsmooth->abstol, fas->upsmooth->rtol, fas->upsmooth->xtol, 1, 1000);CHKERRQ(ierr); 8861a266240SBarry Smith } 8871a266240SBarry Smith 8881a266240SBarry Smith if (fas->downsmooth) { 889fde0ff24SPeter Brune ierr = SNESSetTolerances(fas->downsmooth, fas->downsmooth->abstol, fas->downsmooth->rtol, fas->downsmooth->xtol, 1, 1000);CHKERRQ(ierr); 8901a266240SBarry Smith } 891ee78dd50SPeter Brune 892742fe5e2SPeter Brune if (fas->level != fas->levels - 1) { 893fde0ff24SPeter Brune ierr = SNESSetTolerances(snes, snes->abstol, snes->rtol, snes->xtol, fas->n_cycles, 1000);CHKERRQ(ierr); 894742fe5e2SPeter Brune } 895742fe5e2SPeter Brune 896ce11c761SPeter Brune /* control the simple Richardson smoother that is default if there's no upsmooth or downsmooth */ 897ce11c761SPeter Brune if (!fas->downsmooth) { 898ce11c761SPeter Brune ierr = PetscOptionsInt("-fas_down_snes_max_it","Number of cycles","SNESFASSetCycles",fas->max_down_it,&fas->max_down_it,&flg);CHKERRQ(ierr); 899ce11c761SPeter Brune if (fas->level == 0) { 900ce11c761SPeter Brune ierr = PetscOptionsInt("-fas_coarse_snes_max_it","Number of cycles","SNESFASSetCycles",fas->max_down_it,&fas->max_down_it,&flg);CHKERRQ(ierr); 901ce11c761SPeter Brune } 902ce11c761SPeter Brune } 903ce11c761SPeter Brune 904ce11c761SPeter Brune if (!fas->upsmooth) { 905ce11c761SPeter Brune ierr = PetscOptionsInt("-fas_up_snes_max_it","Number of cycles","SNESFASSetCycles",fas->max_up_it,&fas->max_up_it,&flg);CHKERRQ(ierr); 906ce11c761SPeter Brune } 907ce11c761SPeter Brune 908ee78dd50SPeter Brune if (monflg) { 909646217ecSPeter Brune fas->monitor = PETSC_VIEWER_STDOUT_(((PetscObject)snes)->comm);CHKERRQ(ierr); 910794bee33SPeter Brune /* set the monitors for the upsmoother and downsmoother */ 9112f7ea302SPeter Brune ierr = SNESMonitorCancel(snes);CHKERRQ(ierr); 912742fe5e2SPeter Brune ierr = SNESMonitorSet(snes,SNESMonitorDefault,PETSC_NULL,(PetscErrorCode (*)(void**))PetscViewerDestroy);CHKERRQ(ierr); 913293a7e31SPeter Brune if (fas->upsmooth) ierr = SNESMonitorSet(fas->upsmooth,SNESMonitorDefault,PETSC_NULL,(PetscErrorCode (*)(void**))PetscViewerDestroy);CHKERRQ(ierr); 914293a7e31SPeter Brune if (fas->downsmooth) ierr = SNESMonitorSet(fas->downsmooth,SNESMonitorDefault,PETSC_NULL,(PetscErrorCode (*)(void**))PetscViewerDestroy);CHKERRQ(ierr); 915d28543b3SPeter Brune } else { 916d28543b3SPeter Brune /* unset the monitors on the coarse levels */ 917d28543b3SPeter Brune if (fas->level != fas->levels - 1) { 918d28543b3SPeter Brune ierr = SNESMonitorCancel(snes);CHKERRQ(ierr); 919d28543b3SPeter Brune } 920ee78dd50SPeter Brune } 921ee78dd50SPeter Brune 922ee78dd50SPeter Brune /* recursive option setting for the smoothers */ 923d28543b3SPeter Brune if (fas->next) {ierr = SNESSetFromOptions(fas->next);CHKERRQ(ierr);} 924421d9b32SPeter Brune PetscFunctionReturn(0); 925421d9b32SPeter Brune } 926421d9b32SPeter Brune 927421d9b32SPeter Brune #undef __FUNCT__ 928421d9b32SPeter Brune #define __FUNCT__ "SNESView_FAS" 929421d9b32SPeter Brune PetscErrorCode SNESView_FAS(SNES snes, PetscViewer viewer) 930421d9b32SPeter Brune { 931421d9b32SPeter Brune SNES_FAS *fas = (SNES_FAS *) snes->data; 932421d9b32SPeter Brune PetscBool iascii; 933421d9b32SPeter Brune PetscErrorCode ierr; 934421d9b32SPeter Brune 935421d9b32SPeter Brune PetscFunctionBegin; 936421d9b32SPeter Brune ierr = PetscTypeCompare((PetscObject) viewer, PETSCVIEWERASCII, &iascii);CHKERRQ(ierr); 937421d9b32SPeter Brune if (iascii) { 938421d9b32SPeter Brune ierr = PetscViewerASCIIPrintf(viewer, "FAS, levels = %d\n", fas->levels);CHKERRQ(ierr); 939421d9b32SPeter Brune ierr = PetscViewerASCIIPushTab(viewer); 940421d9b32SPeter Brune ierr = PetscViewerASCIIPrintf(viewer, "level: %d\n", fas->level);CHKERRQ(ierr); 941ee78dd50SPeter Brune if (fas->upsmooth) { 94239a4b097SPeter Brune ierr = PetscViewerASCIIPrintf(viewer, "up-smoother on level %D:\n", fas->level);CHKERRQ(ierr); 943421d9b32SPeter Brune ierr = PetscViewerASCIIPushTab(viewer); 944ee78dd50SPeter Brune ierr = SNESView(fas->upsmooth, viewer);CHKERRQ(ierr); 945421d9b32SPeter Brune ierr = PetscViewerASCIIPopTab(viewer); 946421d9b32SPeter Brune } else { 947ee78dd50SPeter Brune ierr = PetscViewerASCIIPrintf(viewer, "no up-smoother on level %D\n", fas->level);CHKERRQ(ierr); 948421d9b32SPeter Brune } 949ee78dd50SPeter Brune if (fas->downsmooth) { 95039a4b097SPeter Brune ierr = PetscViewerASCIIPrintf(viewer, "down-smoother on level %D:\n", fas->level);CHKERRQ(ierr); 951421d9b32SPeter Brune ierr = PetscViewerASCIIPushTab(viewer); 952ee78dd50SPeter Brune ierr = SNESView(fas->downsmooth, viewer);CHKERRQ(ierr); 953421d9b32SPeter Brune ierr = PetscViewerASCIIPopTab(viewer); 954421d9b32SPeter Brune } else { 955ee78dd50SPeter Brune ierr = PetscViewerASCIIPrintf(viewer, "no down-smoother on level %D\n", fas->level);CHKERRQ(ierr); 956421d9b32SPeter Brune } 957421d9b32SPeter Brune ierr = PetscViewerASCIIPopTab(viewer); 958421d9b32SPeter Brune } else { 959421d9b32SPeter Brune SETERRQ1(((PetscObject)snes)->comm,PETSC_ERR_SUP,"Viewer type %s not supported for SNESFAS",((PetscObject)viewer)->type_name); 960421d9b32SPeter Brune } 961421d9b32SPeter Brune PetscFunctionReturn(0); 962421d9b32SPeter Brune } 963421d9b32SPeter Brune 964421d9b32SPeter Brune #undef __FUNCT__ 96539bd7f45SPeter Brune #define __FUNCT__ "FASDownSmooth" 96639bd7f45SPeter Brune /* 96739bd7f45SPeter Brune Defines the action of the downsmoother 96839bd7f45SPeter Brune */ 96939bd7f45SPeter Brune PetscErrorCode FASDownSmooth(SNES snes, Vec B, Vec X, Vec F){ 97039bd7f45SPeter Brune PetscErrorCode ierr = 0; 971fde0ff24SPeter Brune PetscReal fnorm, gnorm, ynorm, xnorm = 0.0; 972742fe5e2SPeter Brune SNESConvergedReason reason; 97339bd7f45SPeter Brune SNES_FAS *fas = (SNES_FAS *)snes->data; 974fde0ff24SPeter Brune Vec G, W, Y; 975fde0ff24SPeter Brune PetscBool lssuccess; 976fde0ff24SPeter Brune PetscInt k; 977421d9b32SPeter Brune PetscFunctionBegin; 978fde0ff24SPeter Brune G = snes->work[1]; 979fde0ff24SPeter Brune W = snes->work[2]; 980fde0ff24SPeter Brune Y = snes->work[3]; 981d1adcc6fSPeter Brune if (fas->downsmooth) { 982d1adcc6fSPeter Brune ierr = SNESSolve(fas->downsmooth, B, X);CHKERRQ(ierr); 983742fe5e2SPeter Brune /* check convergence reason for the smoother */ 984742fe5e2SPeter Brune ierr = SNESGetConvergedReason(fas->downsmooth,&reason);CHKERRQ(ierr); 985742fe5e2SPeter Brune if (reason < 0 && reason != SNES_DIVERGED_MAX_IT) { 986742fe5e2SPeter Brune snes->reason = SNES_DIVERGED_INNER; 987742fe5e2SPeter Brune PetscFunctionReturn(0); 988742fe5e2SPeter Brune } 989fde0ff24SPeter Brune } else { 990fde0ff24SPeter Brune /* basic richardson smoother */ 991fde0ff24SPeter Brune for (k = 0; k < fas->max_up_it; k++) { 992794bee33SPeter Brune ierr = SNESComputeFunction(snes, X, F);CHKERRQ(ierr); 993794bee33SPeter Brune ierr = VecNorm(F, NORM_2, &fnorm);CHKERRQ(ierr); 994fde0ff24SPeter Brune ierr = VecCopy(F, Y);CHKERRQ(ierr); 995fde0ff24SPeter Brune ierr = (*snes->ops->linesearch)(snes,snes->lsP,X,F,Y,fnorm,xnorm,G,W,&ynorm,&gnorm,&lssuccess);CHKERRQ(ierr); 996fde0ff24SPeter Brune if (!lssuccess) { 997fde0ff24SPeter Brune if (++snes->numFailures >= snes->maxFailures) { 998fde0ff24SPeter Brune snes->reason = SNES_DIVERGED_LINE_SEARCH; 9992f7ea302SPeter Brune PetscFunctionReturn(0); 10002f7ea302SPeter Brune } 1001fe6f9142SPeter Brune } 1002fde0ff24SPeter Brune ierr = VecCopy(W, X);CHKERRQ(ierr); 1003fde0ff24SPeter Brune ierr = VecCopy(G, F);CHKERRQ(ierr); 1004fde0ff24SPeter Brune fnorm = gnorm; 1005fde0ff24SPeter Brune } 1006fde0ff24SPeter Brune } 100739bd7f45SPeter Brune PetscFunctionReturn(0); 100839bd7f45SPeter Brune } 100939bd7f45SPeter Brune 101039bd7f45SPeter Brune 101139bd7f45SPeter Brune #undef __FUNCT__ 101239bd7f45SPeter Brune #define __FUNCT__ "FASUpSmooth" 101339bd7f45SPeter Brune /* 101407144faaSPeter Brune Defines the action of the upsmoother 101539bd7f45SPeter Brune */ 101639bd7f45SPeter Brune PetscErrorCode FASUpSmooth (SNES snes, Vec B, Vec X, Vec F) { 101739bd7f45SPeter Brune PetscErrorCode ierr = 0; 1018fde0ff24SPeter Brune PetscReal fnorm, gnorm, ynorm, xnorm = 0.0; 101939bd7f45SPeter Brune SNESConvergedReason reason; 102039bd7f45SPeter Brune SNES_FAS *fas = (SNES_FAS *)snes->data; 1021fde0ff24SPeter Brune Vec G, W, Y; 1022fde0ff24SPeter Brune PetscBool lssuccess; 1023fde0ff24SPeter Brune PetscInt k; 102439bd7f45SPeter Brune PetscFunctionBegin; 1025fde0ff24SPeter Brune G = snes->work[1]; 1026fde0ff24SPeter Brune W = snes->work[2]; 1027fde0ff24SPeter Brune Y = snes->work[3]; 102839bd7f45SPeter Brune if (fas->upsmooth) { 1029fde0ff24SPeter Brune ierr = SNESSolve(fas->upsmooth, B, X);CHKERRQ(ierr); 103039bd7f45SPeter Brune /* check convergence reason for the smoother */ 1031fde0ff24SPeter Brune ierr = SNESGetConvergedReason(fas->upsmooth,&reason);CHKERRQ(ierr); 103239bd7f45SPeter Brune if (reason < 0 && reason != SNES_DIVERGED_MAX_IT) { 103339bd7f45SPeter Brune snes->reason = SNES_DIVERGED_INNER; 103439bd7f45SPeter Brune PetscFunctionReturn(0); 103539bd7f45SPeter Brune } 1036fde0ff24SPeter Brune } else { 1037fde0ff24SPeter Brune /* basic richardson smoother */ 1038fde0ff24SPeter Brune for (k = 0; k < fas->max_up_it; k++) { 103939bd7f45SPeter Brune ierr = SNESComputeFunction(snes, X, F);CHKERRQ(ierr); 104039bd7f45SPeter Brune ierr = VecNorm(F, NORM_2, &fnorm);CHKERRQ(ierr); 1041fde0ff24SPeter Brune ierr = VecCopy(F, Y);CHKERRQ(ierr); 1042fde0ff24SPeter Brune ierr = (*snes->ops->linesearch)(snes,snes->lsP,X,F,Y,fnorm,xnorm,G,W,&ynorm,&gnorm,&lssuccess);CHKERRQ(ierr); 1043fde0ff24SPeter Brune if (!lssuccess) { 1044fde0ff24SPeter Brune if (++snes->numFailures >= snes->maxFailures) { 1045fde0ff24SPeter Brune snes->reason = SNES_DIVERGED_LINE_SEARCH; 104639bd7f45SPeter Brune PetscFunctionReturn(0); 104739bd7f45SPeter Brune } 104839bd7f45SPeter Brune } 1049fde0ff24SPeter Brune ierr = VecCopy(W, X);CHKERRQ(ierr); 1050fde0ff24SPeter Brune ierr = VecCopy(G, F);CHKERRQ(ierr); 1051fde0ff24SPeter Brune fnorm = gnorm; 1052fde0ff24SPeter Brune } 1053fde0ff24SPeter Brune } 105439bd7f45SPeter Brune PetscFunctionReturn(0); 105539bd7f45SPeter Brune } 105639bd7f45SPeter Brune 105739bd7f45SPeter Brune #undef __FUNCT__ 105839bd7f45SPeter Brune #define __FUNCT__ "FASCoarseCorrection" 105939bd7f45SPeter Brune /* 106039bd7f45SPeter Brune 106139bd7f45SPeter Brune Performs the FAS coarse correction as: 106239bd7f45SPeter Brune 106339bd7f45SPeter Brune fine problem: F(x) = 0 106439bd7f45SPeter Brune coarse problem: F^c(x) = b^c 106539bd7f45SPeter Brune 106639bd7f45SPeter Brune b^c = F^c(I^c_fx^f - I^c_fF(x)) 106739bd7f45SPeter Brune 106839bd7f45SPeter Brune with correction: 106939bd7f45SPeter Brune 107039bd7f45SPeter Brune 107139bd7f45SPeter Brune 107239bd7f45SPeter Brune */ 107339a4b097SPeter Brune PetscErrorCode FASCoarseCorrection(SNES snes, Vec X, Vec F, Vec X_new) { 107439bd7f45SPeter Brune PetscErrorCode ierr; 107539bd7f45SPeter Brune Vec X_c, Xo_c, F_c, B_c; 107639bd7f45SPeter Brune SNES_FAS *fas = (SNES_FAS *)snes->data; 107739bd7f45SPeter Brune SNESConvergedReason reason; 107839bd7f45SPeter Brune PetscFunctionBegin; 1079fa9694d7SPeter Brune if (fas->next) { 1080ee78dd50SPeter Brune ierr = SNESComputeFunction(snes, X, F);CHKERRQ(ierr); 1081794bee33SPeter Brune 1082c90fad12SPeter Brune X_c = fas->next->vec_sol; 1083293a7e31SPeter Brune Xo_c = fas->next->work[0]; 1084c90fad12SPeter Brune F_c = fas->next->vec_func; 1085742fe5e2SPeter Brune B_c = fas->next->vec_rhs; 1086efe1f98aSPeter Brune 1087efe1f98aSPeter Brune /* inject the solution */ 1088efe1f98aSPeter Brune if (fas->inject) { 1089a3cb90a9SPeter Brune ierr = MatRestrict(fas->inject, X, Xo_c);CHKERRQ(ierr); 1090efe1f98aSPeter Brune } else { 1091a3cb90a9SPeter Brune ierr = MatRestrict(fas->restrct, X, Xo_c);CHKERRQ(ierr); 1092a3cb90a9SPeter Brune ierr = VecPointwiseMult(Xo_c, fas->rscale, Xo_c);CHKERRQ(ierr); 1093efe1f98aSPeter Brune } 1094293a7e31SPeter Brune ierr = VecScale(F, -1.0);CHKERRQ(ierr); 1095293a7e31SPeter Brune 1096293a7e31SPeter Brune /* restrict the defect */ 1097293a7e31SPeter Brune ierr = MatRestrict(fas->restrct, F, B_c);CHKERRQ(ierr); 1098293a7e31SPeter Brune 1099c90fad12SPeter Brune /* solve the coarse problem corresponding to F^c(x^c) = b^c = Rb + F^c(Rx) - RF(x) */ 1100ee78dd50SPeter Brune fas->next->vec_rhs = PETSC_NULL; /*unset the RHS to evaluate function instead of residual*/ 1101c90fad12SPeter Brune ierr = SNESComputeFunction(fas->next, Xo_c, F_c);CHKERRQ(ierr); 1102742fe5e2SPeter Brune 1103293a7e31SPeter Brune ierr = VecAXPY(B_c, 1.0, F_c);CHKERRQ(ierr); /* add F_c(X) to the RHS */ 1104c90fad12SPeter Brune 1105ee78dd50SPeter Brune /* set initial guess of the coarse problem to the projected fine solution */ 1106ee78dd50SPeter Brune ierr = VecCopy(Xo_c, X_c);CHKERRQ(ierr); 1107c90fad12SPeter Brune 1108c90fad12SPeter Brune /* recurse to the next level */ 1109f5a6d4f9SBarry Smith fas->next->vec_rhs = B_c; 1110742fe5e2SPeter Brune /* ierr = FASCycle_Private(fas->next, X_c);CHKERRQ(ierr); */ 1111742fe5e2SPeter Brune ierr = SNESSolve(fas->next, B_c, X_c);CHKERRQ(ierr); 1112742fe5e2SPeter Brune ierr = SNESGetConvergedReason(fas->next,&reason);CHKERRQ(ierr); 1113742fe5e2SPeter Brune if (reason < 0 && reason != SNES_DIVERGED_MAX_IT) { 1114742fe5e2SPeter Brune snes->reason = SNES_DIVERGED_INNER; 1115742fe5e2SPeter Brune PetscFunctionReturn(0); 1116742fe5e2SPeter Brune } 1117742fe5e2SPeter Brune /* fas->next->vec_rhs = PETSC_NULL; */ 1118ee78dd50SPeter Brune 1119fa9694d7SPeter Brune /* correct as x <- x + I(x^c - Rx)*/ 1120fa9694d7SPeter Brune ierr = VecAXPY(X_c, -1.0, Xo_c);CHKERRQ(ierr); 112139bd7f45SPeter Brune ierr = MatInterpolateAdd(fas->interpolate, X_c, X, X_new);CHKERRQ(ierr); 1122293a7e31SPeter Brune } 112339bd7f45SPeter Brune PetscFunctionReturn(0); 112439bd7f45SPeter Brune } 112539bd7f45SPeter Brune 112639bd7f45SPeter Brune #undef __FUNCT__ 112739bd7f45SPeter Brune #define __FUNCT__ "FASCycle_Additive" 112839bd7f45SPeter Brune /* 112939bd7f45SPeter Brune 113039bd7f45SPeter Brune The additive cycle looks like: 113139bd7f45SPeter Brune 113207144faaSPeter Brune xhat = x 113307144faaSPeter Brune xhat = dS(x, b) 113407144faaSPeter Brune x = coarsecorrection(xhat, b_d) 113507144faaSPeter Brune x = x + nu*(xhat - x); 113639bd7f45SPeter Brune (optional) x = uS(x, b) 113739bd7f45SPeter Brune 113839bd7f45SPeter Brune With the coarse RHS (defect correction) as below. 113939bd7f45SPeter Brune 114039bd7f45SPeter Brune */ 114139bd7f45SPeter Brune PetscErrorCode FASCycle_Additive(SNES snes, Vec X) { 114207144faaSPeter Brune Vec F, B, Xhat; 1143ddebd997SPeter Brune Vec X_c, Xo_c, F_c, B_c, G, W; 114439bd7f45SPeter Brune PetscErrorCode ierr; 114507144faaSPeter Brune SNES_FAS * fas = (SNES_FAS *)snes->data; 114607144faaSPeter Brune SNESConvergedReason reason; 1147ddebd997SPeter Brune PetscReal xnorm = 0., fnorm = 0., gnorm = 0., ynorm = 0.; 1148ddebd997SPeter Brune PetscBool lssucceed; 114939bd7f45SPeter Brune PetscFunctionBegin; 115039bd7f45SPeter Brune 115139bd7f45SPeter Brune F = snes->vec_func; 115239bd7f45SPeter Brune B = snes->vec_rhs; 1153fde0ff24SPeter Brune Xhat = snes->work[3]; 1154fde0ff24SPeter Brune G = snes->work[1]; 1155fde0ff24SPeter Brune W = snes->work[2]; 115607144faaSPeter Brune ierr = VecCopy(X, Xhat);CHKERRQ(ierr); 115707144faaSPeter Brune /* recurse first */ 115807144faaSPeter Brune if (fas->next) { 115907144faaSPeter Brune ierr = SNESComputeFunction(snes, Xhat, F);CHKERRQ(ierr); 116039bd7f45SPeter Brune 116107144faaSPeter Brune X_c = fas->next->vec_sol; 116207144faaSPeter Brune Xo_c = fas->next->work[0]; 116307144faaSPeter Brune F_c = fas->next->vec_func; 116407144faaSPeter Brune B_c = fas->next->vec_rhs; 116539bd7f45SPeter Brune 116607144faaSPeter Brune /* inject the solution */ 116707144faaSPeter Brune if (fas->inject) { 116807144faaSPeter Brune ierr = MatRestrict(fas->inject, Xhat, Xo_c);CHKERRQ(ierr); 116907144faaSPeter Brune } else { 117007144faaSPeter Brune ierr = MatRestrict(fas->restrct, Xhat, Xo_c);CHKERRQ(ierr); 117107144faaSPeter Brune ierr = VecPointwiseMult(Xo_c, fas->rscale, Xo_c);CHKERRQ(ierr); 117207144faaSPeter Brune } 117307144faaSPeter Brune ierr = VecScale(F, -1.0);CHKERRQ(ierr); 117407144faaSPeter Brune 117507144faaSPeter Brune /* restrict the defect */ 117607144faaSPeter Brune ierr = MatRestrict(fas->restrct, F, B_c);CHKERRQ(ierr); 117707144faaSPeter Brune 117807144faaSPeter Brune /* solve the coarse problem corresponding to F^c(x^c) = b^c = Rb + F^c(Rx) - RF(x) */ 117907144faaSPeter Brune fas->next->vec_rhs = PETSC_NULL; /*unset the RHS to evaluate function instead of residual*/ 118007144faaSPeter Brune ierr = SNESComputeFunction(fas->next, Xo_c, F_c);CHKERRQ(ierr); 118107144faaSPeter Brune 118207144faaSPeter Brune ierr = VecAXPY(B_c, 1.0, F_c);CHKERRQ(ierr); /* add F_c(X) to the RHS */ 118307144faaSPeter Brune 118407144faaSPeter Brune /* set initial guess of the coarse problem to the projected fine solution */ 118507144faaSPeter Brune ierr = VecCopy(Xo_c, X_c);CHKERRQ(ierr); 118607144faaSPeter Brune 118707144faaSPeter Brune /* recurse */ 118807144faaSPeter Brune fas->next->vec_rhs = B_c; 118907144faaSPeter Brune ierr = SNESSolve(fas->next, B_c, X_c);CHKERRQ(ierr); 119007144faaSPeter Brune 119107144faaSPeter Brune /* smooth on this level */ 119207144faaSPeter Brune ierr = FASDownSmooth(snes, B, X, F);CHKERRQ(ierr); 119307144faaSPeter Brune 119407144faaSPeter Brune ierr = SNESGetConvergedReason(fas->next,&reason);CHKERRQ(ierr); 119507144faaSPeter Brune if (reason < 0 && reason != SNES_DIVERGED_MAX_IT) { 119607144faaSPeter Brune snes->reason = SNES_DIVERGED_INNER; 119707144faaSPeter Brune PetscFunctionReturn(0); 119807144faaSPeter Brune } 119907144faaSPeter Brune 120007144faaSPeter Brune /* correct as x <- x + I(x^c - Rx)*/ 120107144faaSPeter Brune ierr = VecAXPY(X_c, -1.0, Xo_c);CHKERRQ(ierr); 1202ddebd997SPeter Brune ierr = MatInterpolate(fas->interpolate, X_c, Xhat);CHKERRQ(ierr); 120307144faaSPeter Brune 1204ddebd997SPeter Brune /* additive correction of the coarse direction*/ 1205ddebd997SPeter Brune ierr = SNESComputeFunction(snes, X, F);CHKERRQ(ierr); 1206ddebd997SPeter Brune ierr = VecNorm(F, NORM_2, &fnorm);CHKERRQ(ierr); 1207eb1825c3SPeter Brune ierr = VecScale(Xhat, -1.0);CHKERRQ(ierr); 1208ddebd997SPeter Brune ierr = (*snes->ops->linesearch)(snes,snes->lsP,X,F,Xhat,fnorm,xnorm,G,W,&ynorm,&gnorm,&lssucceed);CHKERRQ(ierr); 1209ddebd997SPeter Brune ierr = VecCopy(W, X);CHKERRQ(ierr); 1210ddebd997SPeter Brune ierr = VecCopy(G, F);CHKERRQ(ierr); 1211ddebd997SPeter Brune fnorm = gnorm; 121207144faaSPeter Brune } else { 121307144faaSPeter Brune ierr = FASDownSmooth(snes, B, X, F);CHKERRQ(ierr); 121407144faaSPeter Brune } 121539bd7f45SPeter Brune PetscFunctionReturn(0); 121639bd7f45SPeter Brune } 121739bd7f45SPeter Brune 121839bd7f45SPeter Brune #undef __FUNCT__ 121939bd7f45SPeter Brune #define __FUNCT__ "FASCycle_Multiplicative" 122039bd7f45SPeter Brune /* 122139bd7f45SPeter Brune 122239bd7f45SPeter Brune Defines the FAS cycle as: 122339bd7f45SPeter Brune 122439bd7f45SPeter Brune fine problem: F(x) = 0 122539bd7f45SPeter Brune coarse problem: F^c(x) = b^c 122639bd7f45SPeter Brune 122739bd7f45SPeter Brune b^c = F^c(I^c_fx^f - I^c_fF(x)) 122839bd7f45SPeter Brune 122939bd7f45SPeter Brune correction: 123039bd7f45SPeter Brune 123139bd7f45SPeter Brune x = x + I(x^c - Rx) 123239bd7f45SPeter Brune 123339bd7f45SPeter Brune */ 123439bd7f45SPeter Brune PetscErrorCode FASCycle_Multiplicative(SNES snes, Vec X) { 123539bd7f45SPeter Brune 123639bd7f45SPeter Brune PetscErrorCode ierr; 123739bd7f45SPeter Brune Vec F,B; 123839bd7f45SPeter Brune SNES_FAS *fas = (SNES_FAS *)snes->data; 123939bd7f45SPeter Brune 124039bd7f45SPeter Brune PetscFunctionBegin; 124139bd7f45SPeter Brune F = snes->vec_func; 124239bd7f45SPeter Brune B = snes->vec_rhs; 124339bd7f45SPeter Brune /* pre-smooth -- just update using the pre-smoother */ 124439bd7f45SPeter Brune ierr = FASDownSmooth(snes, B, X, F);CHKERRQ(ierr); 124539bd7f45SPeter Brune 124639a4b097SPeter Brune ierr = FASCoarseCorrection(snes, X, F, X);CHKERRQ(ierr); 124739bd7f45SPeter Brune 1248c90fad12SPeter Brune if (fas->level != 0) { 124939bd7f45SPeter Brune ierr = FASUpSmooth(snes, B, X, F);CHKERRQ(ierr); 1250fe6f9142SPeter Brune } 1251fe6f9142SPeter Brune ierr = SNESComputeFunction(snes, X, F);CHKERRQ(ierr); 1252fa9694d7SPeter Brune 1253fa9694d7SPeter Brune PetscFunctionReturn(0); 1254421d9b32SPeter Brune } 1255421d9b32SPeter Brune 1256421d9b32SPeter Brune #undef __FUNCT__ 1257421d9b32SPeter Brune #define __FUNCT__ "SNESSolve_FAS" 1258421d9b32SPeter Brune 1259421d9b32SPeter Brune PetscErrorCode SNESSolve_FAS(SNES snes) 1260421d9b32SPeter Brune { 1261fa9694d7SPeter Brune PetscErrorCode ierr; 1262fe6f9142SPeter Brune PetscInt i, maxits; 1263ddb5aff1SPeter Brune Vec X, F; 1264fe6f9142SPeter Brune PetscReal fnorm; 126507144faaSPeter Brune SNES_FAS *fas = (SNES_FAS *)snes->data; 1266421d9b32SPeter Brune PetscFunctionBegin; 1267fe6f9142SPeter Brune maxits = snes->max_its; /* maximum number of iterations */ 1268fe6f9142SPeter Brune snes->reason = SNES_CONVERGED_ITERATING; 1269fa9694d7SPeter Brune X = snes->vec_sol; 1270f5a6d4f9SBarry Smith F = snes->vec_func; 1271293a7e31SPeter Brune 1272293a7e31SPeter Brune /*norm setup */ 1273fe6f9142SPeter Brune ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr); 1274fe6f9142SPeter Brune snes->iter = 0; 1275fe6f9142SPeter Brune snes->norm = 0.; 1276fe6f9142SPeter Brune ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr); 1277fe6f9142SPeter Brune ierr = SNESComputeFunction(snes,X,F);CHKERRQ(ierr); 1278fe6f9142SPeter Brune if (snes->domainerror) { 1279fe6f9142SPeter Brune snes->reason = SNES_DIVERGED_FUNCTION_DOMAIN; 1280fe6f9142SPeter Brune PetscFunctionReturn(0); 1281fe6f9142SPeter Brune } 1282fe6f9142SPeter Brune ierr = VecNorm(F, NORM_2, &fnorm);CHKERRQ(ierr); /* fnorm <- ||F|| */ 1283fe6f9142SPeter Brune if (PetscIsInfOrNanReal(fnorm)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"Infinite or not-a-number generated in norm"); 1284fe6f9142SPeter Brune ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr); 1285fe6f9142SPeter Brune snes->norm = fnorm; 1286fe6f9142SPeter Brune ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr); 1287fe6f9142SPeter Brune SNESLogConvHistory(snes,fnorm,0); 1288fe6f9142SPeter Brune ierr = SNESMonitor(snes,0,fnorm);CHKERRQ(ierr); 1289fe6f9142SPeter Brune 1290fe6f9142SPeter Brune /* set parameter for default relative tolerance convergence test */ 1291fe6f9142SPeter Brune snes->ttol = fnorm*snes->rtol; 1292fe6f9142SPeter Brune /* test convergence */ 1293fe6f9142SPeter Brune ierr = (*snes->ops->converged)(snes,0,0.0,0.0,fnorm,&snes->reason,snes->cnvP);CHKERRQ(ierr); 1294fe6f9142SPeter Brune if (snes->reason) PetscFunctionReturn(0); 1295fe6f9142SPeter Brune for (i = 0; i < maxits; i++) { 1296fe6f9142SPeter Brune /* Call general purpose update function */ 1297646217ecSPeter Brune 1298fe6f9142SPeter Brune if (snes->ops->update) { 1299fe6f9142SPeter Brune ierr = (*snes->ops->update)(snes, snes->iter);CHKERRQ(ierr); 1300fe6f9142SPeter Brune } 130107144faaSPeter Brune if (fas->fastype == SNES_FAS_MULTIPLICATIVE) { 130239bd7f45SPeter Brune ierr = FASCycle_Multiplicative(snes, X);CHKERRQ(ierr); 130307144faaSPeter Brune } else { 130407144faaSPeter Brune ierr = FASCycle_Additive(snes, X);CHKERRQ(ierr); 130507144faaSPeter Brune } 1306742fe5e2SPeter Brune 1307742fe5e2SPeter Brune /* check for FAS cycle divergence */ 1308742fe5e2SPeter Brune if (snes->reason != SNES_CONVERGED_ITERATING) { 1309742fe5e2SPeter Brune PetscFunctionReturn(0); 1310742fe5e2SPeter Brune } 1311c90fad12SPeter Brune ierr = VecNorm(F, NORM_2, &fnorm);CHKERRQ(ierr); /* fnorm <- ||F|| */ 1312c90fad12SPeter Brune /* Monitor convergence */ 1313c90fad12SPeter Brune ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr); 1314c90fad12SPeter Brune snes->iter = i+1; 1315c90fad12SPeter Brune snes->norm = fnorm; 1316c90fad12SPeter Brune ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr); 1317c90fad12SPeter Brune SNESLogConvHistory(snes,snes->norm,0); 1318c90fad12SPeter Brune ierr = SNESMonitor(snes,snes->iter,snes->norm);CHKERRQ(ierr); 1319c90fad12SPeter Brune /* Test for convergence */ 1320c90fad12SPeter Brune ierr = (*snes->ops->converged)(snes,snes->iter,0.0,0.0,fnorm,&snes->reason,snes->cnvP);CHKERRQ(ierr); 1321c90fad12SPeter Brune if (snes->reason) break; 1322fe6f9142SPeter Brune } 1323fe6f9142SPeter Brune if (i == maxits) { 1324fe6f9142SPeter Brune ierr = PetscInfo1(snes, "Maximum number of iterations has been reached: %D\n", maxits);CHKERRQ(ierr); 1325fe6f9142SPeter Brune if (!snes->reason) snes->reason = SNES_DIVERGED_MAX_IT; 1326fe6f9142SPeter Brune } 1327421d9b32SPeter Brune PetscFunctionReturn(0); 1328421d9b32SPeter Brune } 1329