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 /* use or don't use it according to user wishes*/ 213d28543b3SPeter Brune snes->usegs = use_gs; 214eff52c0eSPeter Brune if (gsfunc) { 215eff52c0eSPeter Brune ierr = SNESSetGS(snes, gsfunc, ctx);CHKERRQ(ierr); 216eff52c0eSPeter Brune /* push the provided GS up the tree */ 217eff52c0eSPeter Brune if (fas->next) ierr = SNESFASSetGS(fas->next, gsfunc, ctx, use_gs);CHKERRQ(ierr); 218eff52c0eSPeter Brune } else if (snes->ops->computegs) { 219eff52c0eSPeter Brune /* assume that the user has set the GS solver at this level */ 220eff52c0eSPeter Brune if (fas->next) ierr = SNESFASSetGS(fas->next, PETSC_NULL, PETSC_NULL, use_gs);CHKERRQ(ierr); 221eff52c0eSPeter Brune } else if (use_gs) { 222eff52c0eSPeter Brune SETERRQ1(((PetscObject)snes)->comm, PETSC_ERR_ARG_WRONG, "No user Gauss-Seidel function provided in SNESFASSetGS on level %d", fas->level); 223eff52c0eSPeter Brune } 224eff52c0eSPeter Brune PetscFunctionReturn(0); 225eff52c0eSPeter Brune } 226eff52c0eSPeter Brune 227eff52c0eSPeter Brune #undef __FUNCT__ 228eff52c0eSPeter Brune #define __FUNCT__ "SNESFASSetGSOnLevel" 229aeed3662SMatthew G Knepley /*@C 230c79ef259SPeter Brune SNESFASSetGSOnLevel - Sets the nonlinear smoother on a particular level. 231c79ef259SPeter Brune 232c79ef259SPeter Brune Logically Collective on SNES 233c79ef259SPeter Brune 234c79ef259SPeter Brune Input Parameters: 235c79ef259SPeter Brune + snes - the multigrid context 236c79ef259SPeter Brune . level - the level to set the nonlinear smoother on 237c79ef259SPeter Brune . gsfunc - the nonlinear smoother function 238c79ef259SPeter Brune . ctx - the user context for the nonlinear smoother 239c79ef259SPeter Brune - use_gs - whether to use the nonlinear smoother or not 240c79ef259SPeter Brune 241c79ef259SPeter Brune Level: advanced 242c79ef259SPeter Brune 243c79ef259SPeter Brune .keywords: FAS, MG, set, cycles, Gauss-Seidel, multigrid 244c79ef259SPeter Brune 245c79ef259SPeter Brune .seealso: SNESSetGS(), SNESFASSetGS() 246c79ef259SPeter Brune @*/ 247eff52c0eSPeter Brune PetscErrorCode SNESFASSetGSOnLevel(SNES snes, PetscInt level, PetscErrorCode (*gsfunc)(SNES,Vec,Vec,void *), void * ctx, PetscBool use_gs) { 248eff52c0eSPeter Brune SNES_FAS *fas = (SNES_FAS *)snes->data; 249eff52c0eSPeter Brune PetscErrorCode ierr; 250eff52c0eSPeter Brune PetscInt top_level = fas->level,i; 251eff52c0eSPeter Brune SNES cur_snes = snes; 252eff52c0eSPeter Brune PetscFunctionBegin; 253eff52c0eSPeter Brune if (level > top_level) 254eff52c0eSPeter Brune SETERRQ1(((PetscObject)snes)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Bad level number %d in SNESFASSetCyclesOnLevel", level); 255eff52c0eSPeter Brune /* get to the correct level */ 256eff52c0eSPeter Brune for (i = fas->level; i > level; i--) { 257eff52c0eSPeter Brune fas = (SNES_FAS *)fas->next->data; 258eff52c0eSPeter Brune cur_snes = fas->next; 259eff52c0eSPeter Brune } 260eff52c0eSPeter Brune if (fas->level != level) 261eff52c0eSPeter Brune SETERRQ(((PetscObject)snes)->comm, PETSC_ERR_ARG_WRONG, "Inconsistent level labelling in SNESFASSetCyclesOnLevel"); 262d28543b3SPeter Brune snes->usegs = use_gs; 263eff52c0eSPeter Brune if (gsfunc) { 2646273346dSPeter Brune ierr = SNESSetGS(cur_snes, gsfunc, ctx);CHKERRQ(ierr); 265eff52c0eSPeter Brune } 266eff52c0eSPeter Brune PetscFunctionReturn(0); 267eff52c0eSPeter Brune } 268eff52c0eSPeter Brune 269646217ecSPeter Brune #undef __FUNCT__ 270421d9b32SPeter Brune #define __FUNCT__ "SNESFASGetSNES" 271c79ef259SPeter Brune /*@ 272c79ef259SPeter Brune SNESFASGetSNES - Gets the SNES corresponding to a particular 273c79ef259SPeter Brune level of the FAS hierarchy. 274c79ef259SPeter Brune 275c79ef259SPeter Brune Input Parameters: 276c79ef259SPeter Brune + snes - the multigrid context 277c79ef259SPeter Brune level - the level to get 278c79ef259SPeter Brune - lsnes - whether to use the nonlinear smoother or not 279c79ef259SPeter Brune 280c79ef259SPeter Brune Level: advanced 281c79ef259SPeter Brune 282c79ef259SPeter Brune .keywords: FAS, MG, set, cycles, Gauss-Seidel, multigrid 283c79ef259SPeter Brune 284c79ef259SPeter Brune .seealso: SNESFASSetLevels(), SNESFASGetLevels() 285c79ef259SPeter Brune @*/ 286421d9b32SPeter Brune PetscErrorCode SNESFASGetSNES(SNES snes, PetscInt level, SNES * lsnes) { 287421d9b32SPeter Brune SNES_FAS * fas = (SNES_FAS *)snes->data; 288421d9b32SPeter Brune PetscInt levels = fas->level; 289421d9b32SPeter Brune PetscInt i; 290421d9b32SPeter Brune PetscFunctionBegin; 291421d9b32SPeter Brune *lsnes = snes; 292421d9b32SPeter Brune if (fas->level < level) { 293421d9b32SPeter Brune SETERRQ(((PetscObject)snes)->comm, PETSC_ERR_ARG_OUTOFRANGE, "SNESFASGetSNES should only be called on a finer SNESFAS instance than the level."); 294421d9b32SPeter Brune } 295421d9b32SPeter Brune if (level > levels - 1) { 296421d9b32SPeter Brune SETERRQ(((PetscObject)snes)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Level %d doesn't exist in the SNESFAS."); 297421d9b32SPeter Brune } 298421d9b32SPeter Brune for (i = fas->level; i > level; i--) { 299421d9b32SPeter Brune *lsnes = fas->next; 300421d9b32SPeter Brune fas = (SNES_FAS *)(*lsnes)->data; 301421d9b32SPeter Brune } 302421d9b32SPeter Brune if (fas->level != level) SETERRQ(((PetscObject)snes)->comm, PETSC_ERR_ARG_OUTOFRANGE, "SNESFASGetSNES didn't return the right level!"); 303421d9b32SPeter Brune PetscFunctionReturn(0); 304421d9b32SPeter Brune } 305421d9b32SPeter Brune 306421d9b32SPeter Brune #undef __FUNCT__ 30707144faaSPeter Brune #define __FUNCT__ "SNESFASSetType" 30807144faaSPeter Brune /*@ 30907144faaSPeter Brune SNESFASSetType - Sets the update and correction type used for FAS. 31007144faaSPeter Brune e 31107144faaSPeter Brune 31207144faaSPeter Brune 31307144faaSPeter Brune @*/ 31407144faaSPeter Brune PetscErrorCode SNESFASSetType(SNES snes,SNESFASType fastype) 31507144faaSPeter Brune { 31607144faaSPeter Brune SNES_FAS *fas = (SNES_FAS*)snes->data; 31707144faaSPeter Brune 31807144faaSPeter Brune PetscFunctionBegin; 31907144faaSPeter Brune PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 32007144faaSPeter Brune PetscValidLogicalCollectiveEnum(snes,fastype,2); 32107144faaSPeter Brune fas->fastype = fastype; 32207144faaSPeter Brune PetscFunctionReturn(0); 32307144faaSPeter Brune } 32407144faaSPeter Brune 32507144faaSPeter Brune 32607144faaSPeter Brune 32707144faaSPeter Brune #undef __FUNCT__ 328421d9b32SPeter Brune #define __FUNCT__ "SNESFASSetLevels" 329aeed3662SMatthew G Knepley /*@C 330c79ef259SPeter Brune SNESFASSetLevels - Sets the number of levels to use with FAS. 331c79ef259SPeter Brune Must be called before any other FAS routine. 332c79ef259SPeter Brune 333c79ef259SPeter Brune Input Parameters: 334c79ef259SPeter Brune + snes - the snes context 335c79ef259SPeter Brune . levels - the number of levels 336c79ef259SPeter Brune - comms - optional communicators for each level; this is to allow solving the coarser 337c79ef259SPeter Brune problems on smaller sets of processors. Use PETSC_NULL_OBJECT for default in 338c79ef259SPeter Brune Fortran. 339c79ef259SPeter Brune 340c79ef259SPeter Brune Level: intermediate 341c79ef259SPeter Brune 342c79ef259SPeter Brune Notes: 343c79ef259SPeter Brune If the number of levels is one then the multigrid uses the -fas_levels prefix 344c79ef259SPeter Brune for setting the level options rather than the -fas_coarse prefix. 345c79ef259SPeter Brune 346c79ef259SPeter Brune .keywords: FAS, MG, set, levels, multigrid 347c79ef259SPeter Brune 348c79ef259SPeter Brune .seealso: SNESFASGetLevels() 349c79ef259SPeter Brune @*/ 350421d9b32SPeter Brune PetscErrorCode SNESFASSetLevels(SNES snes, PetscInt levels, MPI_Comm * comms) { 351421d9b32SPeter Brune PetscErrorCode ierr; 352421d9b32SPeter Brune PetscInt i; 353421d9b32SPeter Brune SNES_FAS * fas = (SNES_FAS *)snes->data; 3546273346dSPeter Brune SNES prevsnes; 355421d9b32SPeter Brune MPI_Comm comm; 356421d9b32SPeter Brune PetscFunctionBegin; 357ee1fd11aSPeter Brune comm = ((PetscObject)snes)->comm; 358ee1fd11aSPeter Brune if (levels == fas->levels) { 359ee1fd11aSPeter Brune if (!comms) 360ee1fd11aSPeter Brune PetscFunctionReturn(0); 361ee1fd11aSPeter Brune } 362421d9b32SPeter Brune /* user has changed the number of levels; reset */ 363421d9b32SPeter Brune ierr = SNESReset(snes);CHKERRQ(ierr); 364421d9b32SPeter Brune /* destroy any coarser levels if necessary */ 365421d9b32SPeter Brune if (fas->next) SNESDestroy(&fas->next);CHKERRQ(ierr); 366ee1fd11aSPeter Brune fas->next = PETSC_NULL; 3676273346dSPeter Brune fas->previous = PETSC_NULL; 3686273346dSPeter Brune prevsnes = snes; 369421d9b32SPeter Brune /* setup the finest level */ 370421d9b32SPeter Brune for (i = levels - 1; i >= 0; i--) { 371421d9b32SPeter Brune if (comms) comm = comms[i]; 372421d9b32SPeter Brune fas->level = i; 373421d9b32SPeter Brune fas->levels = levels; 374ee1fd11aSPeter Brune fas->next = PETSC_NULL; 375421d9b32SPeter Brune if (i > 0) { 376421d9b32SPeter Brune ierr = SNESCreate(comm, &fas->next);CHKERRQ(ierr); 3774a6b3fb8SBarry Smith ierr = SNESSetOptionsPrefix(fas->next,((PetscObject)snes)->prefix);CHKERRQ(ierr); 378421d9b32SPeter Brune ierr = SNESSetType(fas->next, SNESFAS);CHKERRQ(ierr); 379794bee33SPeter Brune ierr = PetscObjectIncrementTabLevel((PetscObject)fas->next, (PetscObject)snes, levels - i);CHKERRQ(ierr); 3806273346dSPeter Brune ((SNES_FAS *)fas->next->data)->previous = prevsnes; 3816273346dSPeter Brune prevsnes = fas->next; 3826273346dSPeter Brune fas = (SNES_FAS *)prevsnes->data; 383421d9b32SPeter Brune } 384421d9b32SPeter Brune } 385421d9b32SPeter Brune PetscFunctionReturn(0); 386421d9b32SPeter Brune } 387421d9b32SPeter Brune 388421d9b32SPeter Brune #undef __FUNCT__ 389c79ef259SPeter Brune #define __FUNCT__ "SNESFASSetNumberSmoothUp" 390c79ef259SPeter Brune /*@ 391c79ef259SPeter Brune SNESFASSetNumberSmoothUp - Sets the number of post-smoothing steps to 392c79ef259SPeter Brune use on all levels. 393c79ef259SPeter Brune 394c79ef259SPeter Brune Logically Collective on PC 395c79ef259SPeter Brune 396c79ef259SPeter Brune Input Parameters: 397c79ef259SPeter Brune + snes - the multigrid context 398c79ef259SPeter Brune - n - the number of smoothing steps 399c79ef259SPeter Brune 400c79ef259SPeter Brune Options Database Key: 401d28543b3SPeter Brune . -snes_fas_smoothup <n> - Sets number of pre-smoothing steps 402c79ef259SPeter Brune 403c79ef259SPeter Brune Level: advanced 404c79ef259SPeter Brune 405c79ef259SPeter Brune .keywords: FAS, MG, smooth, down, pre-smoothing, steps, multigrid 406c79ef259SPeter Brune 407c79ef259SPeter Brune .seealso: SNESFASSetNumberSmoothDown() 408c79ef259SPeter Brune @*/ 409c79ef259SPeter Brune PetscErrorCode SNESFASSetNumberSmoothUp(SNES snes, PetscInt n) { 410c79ef259SPeter Brune SNES_FAS * fas = (SNES_FAS *)snes->data; 411c79ef259SPeter Brune PetscErrorCode ierr = 0; 412c79ef259SPeter Brune PetscFunctionBegin; 413c79ef259SPeter Brune fas->max_up_it = n; 414c79ef259SPeter Brune if (fas->next) { 415c79ef259SPeter Brune ierr = SNESFASSetNumberSmoothUp(fas->next, n);CHKERRQ(ierr); 416c79ef259SPeter Brune } 417c79ef259SPeter Brune PetscFunctionReturn(0); 418c79ef259SPeter Brune } 419c79ef259SPeter Brune 420c79ef259SPeter Brune #undef __FUNCT__ 421c79ef259SPeter Brune #define __FUNCT__ "SNESFASSetNumberSmoothDown" 422c79ef259SPeter Brune /*@ 423c79ef259SPeter Brune SNESFASSetNumberSmoothDown - Sets the number of pre-smoothing steps to 424c79ef259SPeter Brune use on all levels. 425c79ef259SPeter Brune 426c79ef259SPeter Brune Logically Collective on PC 427c79ef259SPeter Brune 428c79ef259SPeter Brune Input Parameters: 429c79ef259SPeter Brune + snes - the multigrid context 430c79ef259SPeter Brune - n - the number of smoothing steps 431c79ef259SPeter Brune 432c79ef259SPeter Brune Options Database Key: 433d28543b3SPeter Brune . -snes_fas_smoothdown <n> - Sets number of pre-smoothing steps 434c79ef259SPeter Brune 435c79ef259SPeter Brune Level: advanced 436c79ef259SPeter Brune 437c79ef259SPeter Brune .keywords: FAS, MG, smooth, down, pre-smoothing, steps, multigrid 438c79ef259SPeter Brune 439c79ef259SPeter Brune .seealso: SNESFASSetNumberSmoothUp() 440c79ef259SPeter Brune @*/ 441c79ef259SPeter Brune PetscErrorCode SNESFASSetNumberSmoothDown(SNES snes, PetscInt n) { 442c79ef259SPeter Brune SNES_FAS * fas = (SNES_FAS *)snes->data; 443c79ef259SPeter Brune PetscErrorCode ierr = 0; 444c79ef259SPeter Brune PetscFunctionBegin; 445c79ef259SPeter Brune fas->max_down_it = n; 446c79ef259SPeter Brune if (fas->next) { 447c79ef259SPeter Brune ierr = SNESFASSetNumberSmoothDown(fas->next, n);CHKERRQ(ierr); 448c79ef259SPeter Brune } 449c79ef259SPeter Brune PetscFunctionReturn(0); 450c79ef259SPeter Brune } 451c79ef259SPeter Brune 452c79ef259SPeter Brune #undef __FUNCT__ 453421d9b32SPeter Brune #define __FUNCT__ "SNESFASSetInterpolation" 454c79ef259SPeter Brune /*@ 455c79ef259SPeter Brune SNESFASSetInterpolation - Sets the function to be used to calculate the 456c79ef259SPeter Brune interpolation from l-1 to the lth level 457c79ef259SPeter Brune 458c79ef259SPeter Brune Input Parameters: 459c79ef259SPeter Brune + snes - the multigrid context 460c79ef259SPeter Brune . mat - the interpolation operator 461c79ef259SPeter Brune - level - the level (0 is coarsest) to supply [do not supply 0] 462c79ef259SPeter Brune 463c79ef259SPeter Brune Level: advanced 464c79ef259SPeter Brune 465c79ef259SPeter Brune Notes: 466c79ef259SPeter Brune Usually this is the same matrix used also to set the restriction 467c79ef259SPeter Brune for the same level. 468c79ef259SPeter Brune 469c79ef259SPeter Brune One can pass in the interpolation matrix or its transpose; PETSc figures 470c79ef259SPeter Brune out from the matrix size which one it is. 471c79ef259SPeter Brune 472c79ef259SPeter Brune .keywords: FAS, multigrid, set, interpolate, level 473c79ef259SPeter Brune 474c79ef259SPeter Brune .seealso: SNESFASSetInjection(), SNESFASSetRestriction(), SNESFASSetRscale() 475c79ef259SPeter Brune @*/ 476421d9b32SPeter Brune PetscErrorCode SNESFASSetInterpolation(SNES snes, PetscInt level, Mat mat) { 477421d9b32SPeter Brune SNES_FAS * fas = (SNES_FAS *)snes->data; 478d9ce41dcSBarry Smith PetscInt top_level = fas->level,i; 479421d9b32SPeter Brune 480421d9b32SPeter Brune PetscFunctionBegin; 481421d9b32SPeter Brune if (level > top_level) 482421d9b32SPeter Brune SETERRQ1(((PetscObject)snes)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Bad level number %d in SNESFASSetInterpolation", level); 483421d9b32SPeter Brune /* get to the correct level */ 484d9ce41dcSBarry Smith for (i = fas->level; i > level; i--) { 485421d9b32SPeter Brune fas = (SNES_FAS *)fas->next->data; 486421d9b32SPeter Brune } 487421d9b32SPeter Brune if (fas->level != level) 488421d9b32SPeter Brune SETERRQ(((PetscObject)snes)->comm, PETSC_ERR_ARG_WRONG, "Inconsistent level labelling in SNESFASSetInterpolation"); 489421d9b32SPeter Brune fas->interpolate = mat; 490421d9b32SPeter Brune PetscFunctionReturn(0); 491421d9b32SPeter Brune } 492421d9b32SPeter Brune 493421d9b32SPeter Brune #undef __FUNCT__ 494421d9b32SPeter Brune #define __FUNCT__ "SNESFASSetRestriction" 495c79ef259SPeter Brune /*@ 496c79ef259SPeter Brune SNESFASSetRestriction - Sets the function to be used to restrict the defect 497c79ef259SPeter Brune from level l to l-1. 498c79ef259SPeter Brune 499c79ef259SPeter Brune Input Parameters: 500c79ef259SPeter Brune + snes - the multigrid context 501c79ef259SPeter Brune . mat - the restriction matrix 502c79ef259SPeter Brune - level - the level (0 is coarsest) to supply [Do not supply 0] 503c79ef259SPeter Brune 504c79ef259SPeter Brune Level: advanced 505c79ef259SPeter Brune 506c79ef259SPeter Brune Notes: 507c79ef259SPeter Brune Usually this is the same matrix used also to set the interpolation 508c79ef259SPeter Brune for the same level. 509c79ef259SPeter Brune 510c79ef259SPeter Brune One can pass in the interpolation matrix or its transpose; PETSc figures 511c79ef259SPeter Brune out from the matrix size which one it is. 512c79ef259SPeter Brune 513c79ef259SPeter Brune If you do not set this, the transpose of the Mat set with PCMGSetInterpolation() 514c79ef259SPeter Brune is used. 515c79ef259SPeter Brune 516c79ef259SPeter Brune .keywords: FAS, MG, set, multigrid, restriction, level 517c79ef259SPeter Brune 518c79ef259SPeter Brune .seealso: SNESFASSetInterpolation(), SNESFASSetInjection() 519c79ef259SPeter Brune @*/ 520421d9b32SPeter Brune PetscErrorCode SNESFASSetRestriction(SNES snes, PetscInt level, Mat mat) { 521421d9b32SPeter Brune SNES_FAS * fas = (SNES_FAS *)snes->data; 522d9ce41dcSBarry Smith PetscInt top_level = fas->level,i; 523421d9b32SPeter Brune 524421d9b32SPeter Brune PetscFunctionBegin; 525421d9b32SPeter Brune if (level > top_level) 526421d9b32SPeter Brune SETERRQ1(((PetscObject)snes)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Bad level number %d in SNESFASSetRestriction", level); 527421d9b32SPeter Brune /* get to the correct level */ 528d9ce41dcSBarry Smith for (i = fas->level; i > level; i--) { 529421d9b32SPeter Brune fas = (SNES_FAS *)fas->next->data; 530421d9b32SPeter Brune } 531421d9b32SPeter Brune if (fas->level != level) 532421d9b32SPeter Brune SETERRQ(((PetscObject)snes)->comm, PETSC_ERR_ARG_WRONG, "Inconsistent level labelling in SNESFASSetRestriction"); 533421d9b32SPeter Brune fas->restrct = mat; 534421d9b32SPeter Brune PetscFunctionReturn(0); 535421d9b32SPeter Brune } 536421d9b32SPeter Brune 537efe1f98aSPeter Brune 538421d9b32SPeter Brune #undef __FUNCT__ 539421d9b32SPeter Brune #define __FUNCT__ "SNESFASSetRScale" 540c79ef259SPeter Brune /*@ 541c79ef259SPeter Brune SNESFASSetRScale - Sets the scaling factor of the restriction 542c79ef259SPeter Brune operator from level l to l-1. 543c79ef259SPeter Brune 544c79ef259SPeter Brune Input Parameters: 545c79ef259SPeter Brune + snes - the multigrid context 546c79ef259SPeter Brune . rscale - the restriction scaling 547c79ef259SPeter Brune - level - the level (0 is coarsest) to supply [Do not supply 0] 548c79ef259SPeter Brune 549c79ef259SPeter Brune Level: advanced 550c79ef259SPeter Brune 551c79ef259SPeter Brune Notes: 552c79ef259SPeter Brune This is only used in the case that the injection is not set. 553c79ef259SPeter Brune 554c79ef259SPeter Brune .keywords: FAS, MG, set, multigrid, restriction, level 555c79ef259SPeter Brune 556c79ef259SPeter Brune .seealso: SNESFASSetInjection(), SNESFASSetRestriction() 557c79ef259SPeter Brune @*/ 558421d9b32SPeter Brune PetscErrorCode SNESFASSetRScale(SNES snes, PetscInt level, Vec rscale) { 559421d9b32SPeter Brune SNES_FAS * fas = (SNES_FAS *)snes->data; 560d9ce41dcSBarry Smith PetscInt top_level = fas->level,i; 561421d9b32SPeter Brune 562421d9b32SPeter Brune PetscFunctionBegin; 563421d9b32SPeter Brune if (level > top_level) 564421d9b32SPeter Brune SETERRQ1(((PetscObject)snes)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Bad level number %d in SNESFASSetRestriction", level); 565421d9b32SPeter Brune /* get to the correct level */ 566d9ce41dcSBarry Smith for (i = fas->level; i > level; i--) { 567421d9b32SPeter Brune fas = (SNES_FAS *)fas->next->data; 568421d9b32SPeter Brune } 569421d9b32SPeter Brune if (fas->level != level) 570421d9b32SPeter Brune SETERRQ(((PetscObject)snes)->comm, PETSC_ERR_ARG_WRONG, "Inconsistent level labelling in SNESFASSetRestriction"); 571421d9b32SPeter Brune fas->rscale = rscale; 572421d9b32SPeter Brune PetscFunctionReturn(0); 573421d9b32SPeter Brune } 574421d9b32SPeter Brune 575efe1f98aSPeter Brune 576efe1f98aSPeter Brune #undef __FUNCT__ 577efe1f98aSPeter Brune #define __FUNCT__ "SNESFASSetInjection" 578c79ef259SPeter Brune /*@ 579c79ef259SPeter Brune SNESFASSetInjection - Sets the function to be used to inject the solution 580c79ef259SPeter Brune from level l to l-1. 581c79ef259SPeter Brune 582c79ef259SPeter Brune Input Parameters: 583c79ef259SPeter Brune + snes - the multigrid context 584c79ef259SPeter Brune . mat - the restriction matrix 585c79ef259SPeter Brune - level - the level (0 is coarsest) to supply [Do not supply 0] 586c79ef259SPeter Brune 587c79ef259SPeter Brune Level: advanced 588c79ef259SPeter Brune 589c79ef259SPeter Brune Notes: 590c79ef259SPeter Brune If you do not set this, the restriction and rscale is used to 591c79ef259SPeter Brune project the solution instead. 592c79ef259SPeter Brune 593c79ef259SPeter Brune .keywords: FAS, MG, set, multigrid, restriction, level 594c79ef259SPeter Brune 595c79ef259SPeter Brune .seealso: SNESFASSetInterpolation(), SNESFASSetRestriction() 596c79ef259SPeter Brune @*/ 597efe1f98aSPeter Brune PetscErrorCode SNESFASSetInjection(SNES snes, PetscInt level, Mat mat) { 598efe1f98aSPeter Brune SNES_FAS * fas = (SNES_FAS *)snes->data; 599efe1f98aSPeter Brune PetscInt top_level = fas->level,i; 600efe1f98aSPeter Brune 601efe1f98aSPeter Brune PetscFunctionBegin; 602efe1f98aSPeter Brune if (level > top_level) 603efe1f98aSPeter Brune SETERRQ1(((PetscObject)snes)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Bad level number %d in SNESFASSetInjection", level); 604efe1f98aSPeter Brune /* get to the correct level */ 605efe1f98aSPeter Brune for (i = fas->level; i > level; i--) { 606efe1f98aSPeter Brune fas = (SNES_FAS *)fas->next->data; 607efe1f98aSPeter Brune } 608efe1f98aSPeter Brune if (fas->level != level) 609efe1f98aSPeter Brune SETERRQ(((PetscObject)snes)->comm, PETSC_ERR_ARG_WRONG, "Inconsistent level labelling in SNESFASSetInjection"); 610efe1f98aSPeter Brune fas->inject = mat; 611efe1f98aSPeter Brune PetscFunctionReturn(0); 612efe1f98aSPeter Brune } 613efe1f98aSPeter Brune 614421d9b32SPeter Brune #undef __FUNCT__ 615421d9b32SPeter Brune #define __FUNCT__ "SNESReset_FAS" 616421d9b32SPeter Brune PetscErrorCode SNESReset_FAS(SNES snes) 617421d9b32SPeter Brune { 61877df8cc4SPeter Brune PetscErrorCode ierr = 0; 619421d9b32SPeter Brune SNES_FAS * fas = (SNES_FAS *)snes->data; 620421d9b32SPeter Brune 621421d9b32SPeter Brune PetscFunctionBegin; 622742fe5e2SPeter Brune if (fas->upsmooth) ierr = SNESReset(fas->upsmooth);CHKERRQ(ierr); 623742fe5e2SPeter Brune if (fas->downsmooth) ierr = SNESReset(fas->downsmooth);CHKERRQ(ierr); 6243dccd265SPeter Brune if (fas->inject) { 6253dccd265SPeter Brune ierr = MatDestroy(&fas->inject);CHKERRQ(ierr); 6263dccd265SPeter Brune } 6273dccd265SPeter Brune if (fas->interpolate == fas->restrct) { 6283dccd265SPeter Brune if (fas->interpolate) ierr = MatDestroy(&fas->interpolate);CHKERRQ(ierr); 6293dccd265SPeter Brune fas->restrct = PETSC_NULL; 6303dccd265SPeter Brune } else { 6313dccd265SPeter Brune if (fas->interpolate) ierr = MatDestroy(&fas->interpolate);CHKERRQ(ierr); 6323dccd265SPeter Brune if (fas->restrct) ierr = MatDestroy(&fas->restrct);CHKERRQ(ierr); 6333dccd265SPeter Brune } 6343dccd265SPeter Brune if (fas->rscale) ierr = VecDestroy(&fas->rscale);CHKERRQ(ierr); 6353dccd265SPeter Brune 6363dccd265SPeter Brune if (fas->upsmooth) ierr = SNESReset(fas->upsmooth);CHKERRQ(ierr); 6373dccd265SPeter Brune if (fas->downsmooth) ierr = SNESReset(fas->downsmooth);CHKERRQ(ierr); 638742fe5e2SPeter Brune if (fas->next) ierr = SNESReset(fas->next);CHKERRQ(ierr); 639421d9b32SPeter Brune PetscFunctionReturn(0); 640421d9b32SPeter Brune } 641421d9b32SPeter Brune 642421d9b32SPeter Brune #undef __FUNCT__ 643421d9b32SPeter Brune #define __FUNCT__ "SNESDestroy_FAS" 644421d9b32SPeter Brune PetscErrorCode SNESDestroy_FAS(SNES snes) 645421d9b32SPeter Brune { 646421d9b32SPeter Brune SNES_FAS * fas = (SNES_FAS *)snes->data; 647742fe5e2SPeter Brune PetscErrorCode ierr = 0; 648421d9b32SPeter Brune 649421d9b32SPeter Brune PetscFunctionBegin; 650421d9b32SPeter Brune /* recursively resets and then destroys */ 65151e86f29SPeter Brune if (fas->upsmooth) ierr = SNESDestroy(&fas->upsmooth);CHKERRQ(ierr); 65251e86f29SPeter Brune if (fas->downsmooth) ierr = SNESDestroy(&fas->downsmooth);CHKERRQ(ierr); 653421d9b32SPeter Brune if (fas->next) ierr = SNESDestroy(&fas->next);CHKERRQ(ierr); 654421d9b32SPeter Brune ierr = PetscFree(fas);CHKERRQ(ierr); 655ee1fd11aSPeter Brune 656421d9b32SPeter Brune PetscFunctionReturn(0); 657421d9b32SPeter Brune } 658421d9b32SPeter Brune 659421d9b32SPeter Brune #undef __FUNCT__ 660421d9b32SPeter Brune #define __FUNCT__ "SNESSetUp_FAS" 661421d9b32SPeter Brune PetscErrorCode SNESSetUp_FAS(SNES snes) 662421d9b32SPeter Brune { 66348bfdf8aSPeter Brune SNES_FAS *fas = (SNES_FAS *) snes->data; 664421d9b32SPeter Brune PetscErrorCode ierr; 665efe1f98aSPeter Brune VecScatter injscatter; 666d1adcc6fSPeter Brune PetscInt dm_levels; 6673dccd265SPeter Brune Vec vec_sol, vec_func, vec_sol_update, vec_rhs; /* preserve these if they're set through the reset */ 668d1adcc6fSPeter Brune 669421d9b32SPeter Brune PetscFunctionBegin; 670eff52c0eSPeter Brune 671cc05f883SPeter Brune if (fas->usedmfornumberoflevels && (fas->level == fas->levels - 1)) { 672d1adcc6fSPeter Brune ierr = DMGetRefineLevel(snes->dm,&dm_levels);CHKERRQ(ierr); 673d1adcc6fSPeter Brune dm_levels++; 674cc05f883SPeter Brune if (dm_levels > fas->levels) { 6753dccd265SPeter Brune 6763dccd265SPeter Brune /* we don't want the solution and func vectors to be destroyed in the SNESReset when it's called in SNESSetUp_FAS*/ 6773dccd265SPeter Brune vec_sol = snes->vec_sol; 6783dccd265SPeter Brune vec_func = snes->vec_func; 6793dccd265SPeter Brune vec_sol_update = snes->vec_sol_update; 6803dccd265SPeter Brune vec_rhs = snes->vec_rhs; 6813dccd265SPeter Brune snes->vec_sol = PETSC_NULL; 6823dccd265SPeter Brune snes->vec_func = PETSC_NULL; 6833dccd265SPeter Brune snes->vec_sol_update = PETSC_NULL; 6843dccd265SPeter Brune snes->vec_rhs = PETSC_NULL; 6853dccd265SPeter Brune 6863dccd265SPeter Brune /* reset the number of levels */ 687d1adcc6fSPeter Brune ierr = SNESFASSetLevels(snes,dm_levels,PETSC_NULL);CHKERRQ(ierr); 688cc05f883SPeter Brune ierr = SNESSetFromOptions(snes);CHKERRQ(ierr); 6893dccd265SPeter Brune 6903dccd265SPeter Brune snes->vec_sol = vec_sol; 6913dccd265SPeter Brune snes->vec_func = vec_func; 6923dccd265SPeter Brune snes->vec_rhs = vec_rhs; 6933dccd265SPeter Brune snes->vec_sol_update = vec_sol_update; 694d1adcc6fSPeter Brune } 695d1adcc6fSPeter Brune } 696d1adcc6fSPeter Brune 6973dccd265SPeter Brune if (fas->level != fas->levels - 1) snes->gridsequence = 0; /* no grid sequencing inside the multigrid hierarchy! */ 6983dccd265SPeter Brune 69907144faaSPeter Brune if (fas->fastype == SNES_FAS_MULTIPLICATIVE) { 7002f7ea302SPeter Brune ierr = SNESDefaultGetWork(snes, 1);CHKERRQ(ierr); /* work vectors used for intergrid transfers */ 70107144faaSPeter Brune } else { 702ddebd997SPeter Brune ierr = SNESDefaultGetWork(snes, 4);CHKERRQ(ierr); /* work vectors used for intergrid transfers */ 70307144faaSPeter Brune } 704cc05f883SPeter Brune 70548bfdf8aSPeter Brune /* setup the pre and post smoothers and set their function, jacobian, and gs evaluation routines if the user has neglected this */ 70648bfdf8aSPeter Brune if (fas->upsmooth) { 70748bfdf8aSPeter Brune ierr = SNESSetFromOptions(fas->upsmooth);CHKERRQ(ierr); 70848bfdf8aSPeter Brune if (snes->ops->computefunction && !fas->upsmooth->ops->computefunction) { 70948bfdf8aSPeter Brune ierr = SNESSetFunction(fas->upsmooth, PETSC_NULL, snes->ops->computefunction, snes->funP);CHKERRQ(ierr); 71048bfdf8aSPeter Brune } 71148bfdf8aSPeter Brune if (snes->ops->computejacobian && !fas->upsmooth->ops->computejacobian) { 71248bfdf8aSPeter Brune ierr = SNESSetJacobian(fas->upsmooth, fas->upsmooth->jacobian, fas->upsmooth->jacobian_pre, snes->ops->computejacobian, snes->jacP);CHKERRQ(ierr); 71348bfdf8aSPeter Brune } 71448bfdf8aSPeter Brune if (snes->ops->computegs && !fas->upsmooth->ops->computegs) { 71548bfdf8aSPeter Brune ierr = SNESSetGS(fas->upsmooth, snes->ops->computegs, snes->gsP);CHKERRQ(ierr); 71648bfdf8aSPeter Brune } 71748bfdf8aSPeter Brune } 71848bfdf8aSPeter Brune if (fas->downsmooth) { 71948bfdf8aSPeter Brune ierr = SNESSetFromOptions(fas->downsmooth);CHKERRQ(ierr); 72048bfdf8aSPeter Brune if (snes->ops->computefunction && !fas->downsmooth->ops->computefunction) { 72148bfdf8aSPeter Brune ierr = SNESSetFunction(fas->downsmooth, PETSC_NULL, snes->ops->computefunction, snes->funP);CHKERRQ(ierr); 72248bfdf8aSPeter Brune } 72348bfdf8aSPeter Brune if (snes->ops->computejacobian && !fas->downsmooth->ops->computejacobian) { 72448bfdf8aSPeter Brune ierr = SNESSetJacobian(fas->downsmooth, fas->downsmooth->jacobian, fas->downsmooth->jacobian_pre, snes->ops->computejacobian, snes->jacP);CHKERRQ(ierr); 72548bfdf8aSPeter Brune } 72648bfdf8aSPeter Brune if (snes->ops->computegs && !fas->downsmooth->ops->computegs) { 72748bfdf8aSPeter Brune ierr = SNESSetGS(fas->downsmooth, snes->ops->computegs, snes->gsP);CHKERRQ(ierr); 72848bfdf8aSPeter Brune } 7291a266240SBarry Smith } 73048bfdf8aSPeter Brune /*pass the smoother, function, and jacobian up to the next level if it's not user set already */ 731646217ecSPeter Brune if (fas->next) { 7326273346dSPeter Brune if (fas->galerkin) { 7336273346dSPeter Brune ierr = SNESSetFunction(fas->next, PETSC_NULL, SNESFASGalerkinDefaultFunction, fas->next);CHKERRQ(ierr); 7346273346dSPeter Brune } else { 73548bfdf8aSPeter Brune if (snes->ops->computefunction && !fas->next->ops->computefunction) { 73648bfdf8aSPeter Brune ierr = SNESSetFunction(fas->next, PETSC_NULL, snes->ops->computefunction, snes->funP);CHKERRQ(ierr); 73748bfdf8aSPeter Brune } 73848bfdf8aSPeter Brune if (snes->ops->computejacobian && !fas->next->ops->computejacobian) { 73948bfdf8aSPeter Brune ierr = SNESSetJacobian(fas->next, fas->next->jacobian, fas->next->jacobian_pre, snes->ops->computejacobian, snes->jacP);CHKERRQ(ierr); 74048bfdf8aSPeter Brune } 74148bfdf8aSPeter Brune if (snes->ops->computegs && !fas->next->ops->computegs) { 742646217ecSPeter Brune ierr = SNESSetGS(fas->next, snes->ops->computegs, snes->gsP);CHKERRQ(ierr); 743646217ecSPeter Brune } 744646217ecSPeter Brune } 7456273346dSPeter Brune } 746421d9b32SPeter Brune if (snes->dm) { 747421d9b32SPeter Brune /* construct EVERYTHING from the DM -- including the progressive set of smoothers */ 748421d9b32SPeter Brune if (fas->next) { 749421d9b32SPeter Brune /* for now -- assume the DM and the evaluation functions have been set externally */ 750ee78dd50SPeter Brune if (!fas->next->dm) { 751ee78dd50SPeter Brune ierr = DMCoarsen(snes->dm, ((PetscObject)fas->next)->comm, &fas->next->dm);CHKERRQ(ierr); 752ee78dd50SPeter Brune ierr = SNESSetDM(fas->next, fas->next->dm);CHKERRQ(ierr); 753ee78dd50SPeter Brune } 754421d9b32SPeter Brune /* set the interpolation and restriction from the DM */ 755ee78dd50SPeter Brune if (!fas->interpolate) { 756e727c939SJed Brown ierr = DMCreateInterpolation(fas->next->dm, snes->dm, &fas->interpolate, &fas->rscale);CHKERRQ(ierr); 757421d9b32SPeter Brune fas->restrct = fas->interpolate; 758421d9b32SPeter Brune } 759efe1f98aSPeter Brune /* set the injection from the DM */ 760efe1f98aSPeter Brune if (!fas->inject) { 761e727c939SJed Brown ierr = DMCreateInjection(fas->next->dm, snes->dm, &injscatter);CHKERRQ(ierr); 762efe1f98aSPeter Brune ierr = MatCreateScatter(((PetscObject)snes)->comm, injscatter, &fas->inject);CHKERRQ(ierr); 763efe1f98aSPeter Brune ierr = VecScatterDestroy(&injscatter);CHKERRQ(ierr); 764efe1f98aSPeter Brune } 765421d9b32SPeter Brune } 766ee78dd50SPeter Brune /* set the DMs of the pre and post-smoothers here */ 767*6bed07a3SBarry Smith if (fas->upsmooth) {ierr = SNESSetDM(fas->upsmooth, snes->dm);CHKERRQ(ierr);} 768*6bed07a3SBarry Smith if (fas->downsmooth){ierr = SNESSetDM(fas->downsmooth, snes->dm);CHKERRQ(ierr);} 769421d9b32SPeter Brune } 770cc05f883SPeter Brune 7716273346dSPeter Brune /* setup FAS work vectors */ 7726273346dSPeter Brune if (fas->galerkin) { 7736273346dSPeter Brune ierr = VecDuplicate(snes->vec_sol, &fas->Xg);CHKERRQ(ierr); 7746273346dSPeter Brune ierr = VecDuplicate(snes->vec_sol, &fas->Fg);CHKERRQ(ierr); 7756273346dSPeter Brune } 7766273346dSPeter Brune 777fa9694d7SPeter Brune if (fas->next) { 778fa9694d7SPeter Brune /* gotta set up the solution vector for this to work */ 779*6bed07a3SBarry Smith if (!fas->next->vec_sol) {ierr = VecDuplicate(fas->rscale, &fas->next->vec_sol);CHKERRQ(ierr);} 780742fe5e2SPeter Brune if (!fas->next->vec_rhs) {ierr = VecDuplicate(fas->rscale, &fas->next->vec_rhs);CHKERRQ(ierr);} 781fa9694d7SPeter Brune ierr = SNESSetUp(fas->next);CHKERRQ(ierr); 782fa9694d7SPeter Brune } 783fa9694d7SPeter Brune /* got to set them all up at once */ 784421d9b32SPeter Brune PetscFunctionReturn(0); 785421d9b32SPeter Brune } 786421d9b32SPeter Brune 787421d9b32SPeter Brune #undef __FUNCT__ 788421d9b32SPeter Brune #define __FUNCT__ "SNESSetFromOptions_FAS" 789421d9b32SPeter Brune PetscErrorCode SNESSetFromOptions_FAS(SNES snes) 790421d9b32SPeter Brune { 791ee78dd50SPeter Brune SNES_FAS *fas = (SNES_FAS *) snes->data; 792ee78dd50SPeter Brune PetscInt levels = 1; 793d1adcc6fSPeter Brune PetscBool flg, smoothflg, smoothupflg, smoothdownflg, monflg; 794421d9b32SPeter Brune PetscErrorCode ierr; 795ee78dd50SPeter Brune const char *def_smooth = SNESNRICHARDSON; 796ee78dd50SPeter Brune char pre_type[256]; 797ee78dd50SPeter Brune char post_type[256]; 798ee78dd50SPeter Brune char monfilename[PETSC_MAX_PATH_LEN]; 79907144faaSPeter Brune SNESFASType fastype; 800421d9b32SPeter Brune 801421d9b32SPeter Brune PetscFunctionBegin; 802c90fad12SPeter Brune ierr = PetscOptionsHead("SNESFAS Options-----------------------------------");CHKERRQ(ierr); 803ee78dd50SPeter Brune 804ee78dd50SPeter Brune /* number of levels -- only process on the finest level */ 805ee78dd50SPeter Brune if (fas->levels - 1 == fas->level) { 806ee78dd50SPeter Brune ierr = PetscOptionsInt("-snes_fas_levels", "Number of Levels", "SNESFASSetLevels", levels, &levels, &flg);CHKERRQ(ierr); 807c732cbdbSBarry Smith if (!flg && snes->dm) { 808c732cbdbSBarry Smith ierr = DMGetRefineLevel(snes->dm,&levels);CHKERRQ(ierr); 809c732cbdbSBarry Smith levels++; 810d1adcc6fSPeter Brune fas->usedmfornumberoflevels = PETSC_TRUE; 811c732cbdbSBarry Smith } 812ee78dd50SPeter Brune ierr = SNESFASSetLevels(snes, levels, PETSC_NULL);CHKERRQ(ierr); 813ee78dd50SPeter Brune } 814ee78dd50SPeter Brune 815ee78dd50SPeter Brune /* type of pre and/or post smoothers -- set both at once */ 816ee78dd50SPeter Brune ierr = PetscMemcpy(post_type, def_smooth, 256);CHKERRQ(ierr); 817ee78dd50SPeter Brune ierr = PetscMemcpy(pre_type, def_smooth, 256);CHKERRQ(ierr); 81807144faaSPeter Brune fastype = fas->fastype; 81907144faaSPeter Brune ierr = PetscOptionsEnum("-snes_fas_type","FAS correction type","SNESFASSetType",SNESFASTypes,(PetscEnum)fastype,(PetscEnum*)&fastype,&flg);CHKERRQ(ierr); 82007144faaSPeter Brune if (flg) { 82107144faaSPeter Brune ierr = SNESFASSetType(snes, fastype);CHKERRQ(ierr); 82207144faaSPeter Brune } 823d1adcc6fSPeter Brune ierr = PetscOptionsList("-snes_fas_smoother_type","Nonlinear smoother method","SNESSetType",SNESList,def_smooth,pre_type,256,&smoothflg);CHKERRQ(ierr); 824d1adcc6fSPeter Brune if (smoothflg) { 825ee78dd50SPeter Brune ierr = PetscMemcpy(post_type, pre_type, 256);CHKERRQ(ierr); 826ee78dd50SPeter Brune } else { 827d1adcc6fSPeter Brune ierr = PetscOptionsList("-snes_fas_smoothup_type", "Nonlinear smoother method","SNESSetType",SNESList,def_smooth,pre_type, 256,&smoothupflg);CHKERRQ(ierr); 828d1adcc6fSPeter Brune ierr = PetscOptionsList("-snes_fas_smoothdown_type","Nonlinear smoother method","SNESSetType",SNESList,def_smooth,post_type,256,&smoothdownflg);CHKERRQ(ierr); 829ee78dd50SPeter Brune } 830ee78dd50SPeter Brune 831ee78dd50SPeter Brune /* options for the number of preconditioning cycles and cycle type */ 832d1adcc6fSPeter Brune ierr = PetscOptionsInt("-snes_fas_smoothup","Number of post-smooth iterations","SNESFASSetNumberSmoothUp",fas->max_up_it,&fas->max_up_it,&flg);CHKERRQ(ierr); 833d1adcc6fSPeter Brune ierr = PetscOptionsInt("-snes_fas_smoothdown","Number of pre-smooth iterations","SNESFASSetNumberSmoothUp",fas->max_down_it,&fas->max_down_it,&flg);CHKERRQ(ierr); 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 /* other options for the coarsest level */ 841ee78dd50SPeter Brune if (fas->level == 0) { 842d1adcc6fSPeter Brune ierr = PetscOptionsList("-snes_fas_coarse_smoother_type","Coarsest smoother method","SNESSetType",SNESList,def_smooth,pre_type,256,&smoothflg);CHKERRQ(ierr); 843ee78dd50SPeter Brune } 844ee78dd50SPeter Brune 845421d9b32SPeter Brune ierr = PetscOptionsTail();CHKERRQ(ierr); 8468cc86e31SPeter Brune /* setup from the determined types if there is no pointwise procedure or smoother defined */ 847eff52c0eSPeter Brune 848d28543b3SPeter Brune if ((!fas->downsmooth) && ((smoothdownflg || smoothflg) || !snes->usegs)) { 8498cc86e31SPeter Brune const char *prefix; 8508cc86e31SPeter Brune ierr = SNESGetOptionsPrefix(snes,&prefix);CHKERRQ(ierr); 8518cc86e31SPeter Brune ierr = SNESCreate(((PetscObject)snes)->comm, &fas->downsmooth);CHKERRQ(ierr); 8528cc86e31SPeter Brune ierr = SNESSetOptionsPrefix(fas->downsmooth,prefix);CHKERRQ(ierr); 8538cc86e31SPeter Brune if (fas->level || (fas->levels == 1)) { 854eff52c0eSPeter Brune ierr = SNESAppendOptionsPrefix(fas->downsmooth,"fas_levels_down_");CHKERRQ(ierr); 8558cc86e31SPeter Brune } else { 8568cc86e31SPeter Brune ierr = SNESAppendOptionsPrefix(fas->downsmooth,"fas_coarse_");CHKERRQ(ierr); 8578cc86e31SPeter Brune } 8588cc86e31SPeter Brune ierr = PetscObjectIncrementTabLevel((PetscObject)fas->downsmooth, (PetscObject)snes, 1);CHKERRQ(ierr); 8598cc86e31SPeter Brune ierr = SNESSetType(fas->downsmooth, pre_type);CHKERRQ(ierr); 8608cc86e31SPeter Brune } 8618cc86e31SPeter Brune 862d28543b3SPeter Brune if ((!fas->upsmooth) && (fas->level != 0) && ((smoothupflg || smoothflg) || !snes->usegs)) { 86367339d5cSBarry Smith const char *prefix; 86467339d5cSBarry Smith ierr = SNESGetOptionsPrefix(snes,&prefix);CHKERRQ(ierr); 865ee78dd50SPeter Brune ierr = SNESCreate(((PetscObject)snes)->comm, &fas->upsmooth);CHKERRQ(ierr); 86667339d5cSBarry Smith ierr = SNESSetOptionsPrefix(fas->upsmooth,prefix);CHKERRQ(ierr); 867eff52c0eSPeter Brune ierr = SNESAppendOptionsPrefix(fas->upsmooth,"fas_levels_up_");CHKERRQ(ierr); 868293a7e31SPeter Brune ierr = PetscObjectIncrementTabLevel((PetscObject)fas->upsmooth, (PetscObject)snes, 1);CHKERRQ(ierr); 869ee78dd50SPeter Brune ierr = SNESSetType(fas->upsmooth, pre_type);CHKERRQ(ierr); 870ee78dd50SPeter Brune } 8711a266240SBarry Smith if (fas->upsmooth) { 8721a266240SBarry Smith ierr = SNESSetTolerances(fas->upsmooth, 0.0, 0.0, 0.0, fas->max_up_it, 1000);CHKERRQ(ierr); 8731a266240SBarry Smith } 8741a266240SBarry Smith 8751a266240SBarry Smith if (fas->downsmooth) { 8761a266240SBarry Smith ierr = SNESSetTolerances(fas->downsmooth, 0.0, 0.0, 0.0, fas->max_down_it, 1000);CHKERRQ(ierr); 8771a266240SBarry Smith } 878ee78dd50SPeter Brune 879742fe5e2SPeter Brune if (fas->level != fas->levels - 1) { 880742fe5e2SPeter Brune ierr = SNESSetTolerances(snes, 0.0, 0.0, 0.0, fas->n_cycles, 1000);CHKERRQ(ierr); 881742fe5e2SPeter Brune } 882742fe5e2SPeter Brune 883ee78dd50SPeter Brune if (monflg) { 884646217ecSPeter Brune fas->monitor = PETSC_VIEWER_STDOUT_(((PetscObject)snes)->comm);CHKERRQ(ierr); 885794bee33SPeter Brune /* set the monitors for the upsmoother and downsmoother */ 8862f7ea302SPeter Brune ierr = SNESMonitorCancel(snes);CHKERRQ(ierr); 887742fe5e2SPeter Brune ierr = SNESMonitorSet(snes,SNESMonitorDefault,PETSC_NULL,(PetscErrorCode (*)(void**))PetscViewerDestroy);CHKERRQ(ierr); 888293a7e31SPeter Brune if (fas->upsmooth) ierr = SNESMonitorSet(fas->upsmooth,SNESMonitorDefault,PETSC_NULL,(PetscErrorCode (*)(void**))PetscViewerDestroy);CHKERRQ(ierr); 889293a7e31SPeter Brune if (fas->downsmooth) ierr = SNESMonitorSet(fas->downsmooth,SNESMonitorDefault,PETSC_NULL,(PetscErrorCode (*)(void**))PetscViewerDestroy);CHKERRQ(ierr); 890d28543b3SPeter Brune } else { 891d28543b3SPeter Brune /* unset the monitors on the coarse levels */ 892d28543b3SPeter Brune if (fas->level != fas->levels - 1) { 893d28543b3SPeter Brune ierr = SNESMonitorCancel(snes);CHKERRQ(ierr); 894d28543b3SPeter Brune } 895ee78dd50SPeter Brune } 896ee78dd50SPeter Brune 897ee78dd50SPeter Brune /* recursive option setting for the smoothers */ 898d28543b3SPeter Brune if (fas->next) {ierr = SNESSetFromOptions(fas->next);CHKERRQ(ierr);} 899421d9b32SPeter Brune PetscFunctionReturn(0); 900421d9b32SPeter Brune } 901421d9b32SPeter Brune 902421d9b32SPeter Brune #undef __FUNCT__ 903421d9b32SPeter Brune #define __FUNCT__ "SNESView_FAS" 904421d9b32SPeter Brune PetscErrorCode SNESView_FAS(SNES snes, PetscViewer viewer) 905421d9b32SPeter Brune { 906421d9b32SPeter Brune SNES_FAS *fas = (SNES_FAS *) snes->data; 907421d9b32SPeter Brune PetscBool iascii; 908421d9b32SPeter Brune PetscErrorCode ierr; 909421d9b32SPeter Brune 910421d9b32SPeter Brune PetscFunctionBegin; 91139a4b097SPeter Brune if (fas->level != fas->levels - 1) PetscFunctionReturn(0); 912421d9b32SPeter Brune ierr = PetscTypeCompare((PetscObject) viewer, PETSCVIEWERASCII, &iascii);CHKERRQ(ierr); 913421d9b32SPeter Brune if (iascii) { 914421d9b32SPeter Brune ierr = PetscViewerASCIIPrintf(viewer, "FAS, levels = %d\n", fas->levels);CHKERRQ(ierr); 915421d9b32SPeter Brune ierr = PetscViewerASCIIPushTab(viewer); 916421d9b32SPeter Brune ierr = PetscViewerASCIIPrintf(viewer, "level: %d\n", fas->level);CHKERRQ(ierr); 917ee78dd50SPeter Brune if (fas->upsmooth) { 91839a4b097SPeter Brune ierr = PetscViewerASCIIPrintf(viewer, "up-smoother on level %D:\n", fas->level);CHKERRQ(ierr); 919421d9b32SPeter Brune ierr = PetscViewerASCIIPushTab(viewer); 920ee78dd50SPeter Brune ierr = SNESView(fas->upsmooth, viewer);CHKERRQ(ierr); 921421d9b32SPeter Brune ierr = PetscViewerASCIIPopTab(viewer); 922421d9b32SPeter Brune } else { 923ee78dd50SPeter Brune ierr = PetscViewerASCIIPrintf(viewer, "no up-smoother on level %D\n", fas->level);CHKERRQ(ierr); 924421d9b32SPeter Brune } 925ee78dd50SPeter Brune if (fas->downsmooth) { 92639a4b097SPeter Brune ierr = PetscViewerASCIIPrintf(viewer, "down-smoother on level %D:\n", fas->level);CHKERRQ(ierr); 927421d9b32SPeter Brune ierr = PetscViewerASCIIPushTab(viewer); 928ee78dd50SPeter Brune ierr = SNESView(fas->downsmooth, viewer);CHKERRQ(ierr); 929421d9b32SPeter Brune ierr = PetscViewerASCIIPopTab(viewer); 930421d9b32SPeter Brune } else { 931ee78dd50SPeter Brune ierr = PetscViewerASCIIPrintf(viewer, "no down-smoother on level %D\n", fas->level);CHKERRQ(ierr); 932421d9b32SPeter Brune } 933d28543b3SPeter Brune if (snes->usegs) { 93439a4b097SPeter Brune ierr = PetscViewerASCIIPrintf(viewer, "Using user Gauss-Seidel on level %D -- smoothdown=%D, smoothup=%D\n", 93539a4b097SPeter Brune fas->level, fas->max_down_it, fas->max_up_it);CHKERRQ(ierr); 936421d9b32SPeter Brune } 937421d9b32SPeter Brune ierr = PetscViewerASCIIPopTab(viewer); 938421d9b32SPeter Brune } else { 939421d9b32SPeter Brune SETERRQ1(((PetscObject)snes)->comm,PETSC_ERR_SUP,"Viewer type %s not supported for SNESFAS",((PetscObject)viewer)->type_name); 940421d9b32SPeter Brune } 941421d9b32SPeter Brune PetscFunctionReturn(0); 942421d9b32SPeter Brune } 943421d9b32SPeter Brune 944421d9b32SPeter Brune #undef __FUNCT__ 94539bd7f45SPeter Brune #define __FUNCT__ "FASDownSmooth" 94639bd7f45SPeter Brune /* 94739bd7f45SPeter Brune Defines the action of the downsmoother 94839bd7f45SPeter Brune */ 94939bd7f45SPeter Brune PetscErrorCode FASDownSmooth(SNES snes, Vec B, Vec X, Vec F){ 95039bd7f45SPeter Brune PetscErrorCode ierr = 0; 9512d15c84fSPeter Brune PetscReal fnorm; 952742fe5e2SPeter Brune SNESConvergedReason reason; 95339bd7f45SPeter Brune SNES_FAS *fas = (SNES_FAS *)snes->data; 954421d9b32SPeter Brune PetscFunctionBegin; 955d1adcc6fSPeter Brune if (fas->downsmooth) { 956d1adcc6fSPeter Brune ierr = SNESSolve(fas->downsmooth, B, X);CHKERRQ(ierr); 957742fe5e2SPeter Brune /* check convergence reason for the smoother */ 958742fe5e2SPeter Brune ierr = SNESGetConvergedReason(fas->downsmooth,&reason);CHKERRQ(ierr); 959742fe5e2SPeter Brune if (reason < 0 && reason != SNES_DIVERGED_MAX_IT) { 960742fe5e2SPeter Brune snes->reason = SNES_DIVERGED_INNER; 961742fe5e2SPeter Brune PetscFunctionReturn(0); 962742fe5e2SPeter Brune } 963d28543b3SPeter Brune } else if (snes->usegs && snes->ops->computegs) { 964794bee33SPeter Brune if (fas->monitor) { 965794bee33SPeter Brune ierr = SNESComputeFunction(snes, X, F);CHKERRQ(ierr); 966794bee33SPeter Brune ierr = VecNorm(F, NORM_2, &fnorm);CHKERRQ(ierr); 967d1adcc6fSPeter Brune ierr = PetscViewerASCIIAddTab(fas->monitor,((PetscObject)snes)->tablevel + 2);CHKERRQ(ierr); 968eff52c0eSPeter Brune ierr = PetscViewerASCIIPrintf(fas->monitor, "%d SNES GS Function norm %14.12e\n", 0, fnorm);CHKERRQ(ierr); 969d1adcc6fSPeter Brune ierr = PetscViewerASCIISubtractTab(fas->monitor,((PetscObject)snes)->tablevel + 2);CHKERRQ(ierr); 970794bee33SPeter Brune } 9719c44eddcSPeter Brune ierr = SNESSetGSSweeps(snes, fas->max_down_it);CHKERRQ(ierr); 972646217ecSPeter Brune ierr = SNESComputeGS(snes, B, X);CHKERRQ(ierr); 973cc05f883SPeter Brune if (fas->monitor) { 974794bee33SPeter Brune ierr = SNESComputeFunction(snes, X, F);CHKERRQ(ierr); 975794bee33SPeter Brune ierr = VecNorm(F, NORM_2, &fnorm);CHKERRQ(ierr); 976d1adcc6fSPeter Brune ierr = PetscViewerASCIIAddTab(fas->monitor,((PetscObject)snes)->tablevel + 2);CHKERRQ(ierr); 9779c44eddcSPeter Brune ierr = PetscViewerASCIIPrintf(fas->monitor, "1 SNES GS Function norm %14.12e\n", fnorm);CHKERRQ(ierr); 978d1adcc6fSPeter Brune ierr = PetscViewerASCIISubtractTab(fas->monitor,((PetscObject)snes)->tablevel + 2);CHKERRQ(ierr); 979794bee33SPeter Brune } 980c90fad12SPeter Brune } else if (snes->pc) { 981c90fad12SPeter Brune ierr = SNESSolve(snes->pc, B, X);CHKERRQ(ierr); 9822f7ea302SPeter Brune ierr = SNESGetConvergedReason(fas->downsmooth,&reason);CHKERRQ(ierr); 9832f7ea302SPeter Brune if (reason < 0 && reason != SNES_DIVERGED_MAX_IT) { 9842f7ea302SPeter Brune snes->reason = SNES_DIVERGED_INNER; 9852f7ea302SPeter Brune PetscFunctionReturn(0); 9862f7ea302SPeter Brune } 987fe6f9142SPeter Brune } 98839bd7f45SPeter Brune PetscFunctionReturn(0); 98939bd7f45SPeter Brune } 99039bd7f45SPeter Brune 99139bd7f45SPeter Brune 99239bd7f45SPeter Brune #undef __FUNCT__ 99339bd7f45SPeter Brune #define __FUNCT__ "FASUpSmooth" 99439bd7f45SPeter Brune /* 99507144faaSPeter Brune Defines the action of the upsmoother 99639bd7f45SPeter Brune */ 99739bd7f45SPeter Brune PetscErrorCode FASUpSmooth (SNES snes, Vec B, Vec X, Vec F) { 99839bd7f45SPeter Brune PetscErrorCode ierr = 0; 99939bd7f45SPeter Brune PetscReal fnorm; 100039bd7f45SPeter Brune SNESConvergedReason reason; 100139bd7f45SPeter Brune SNES_FAS *fas = (SNES_FAS *)snes->data; 100239bd7f45SPeter Brune PetscFunctionBegin; 100339bd7f45SPeter Brune if (fas->upsmooth) { 100439bd7f45SPeter Brune ierr = SNESSolve(fas->downsmooth, B, X);CHKERRQ(ierr); 100539bd7f45SPeter Brune /* check convergence reason for the smoother */ 100639bd7f45SPeter Brune ierr = SNESGetConvergedReason(fas->downsmooth,&reason);CHKERRQ(ierr); 100739bd7f45SPeter Brune if (reason < 0 && reason != SNES_DIVERGED_MAX_IT) { 100839bd7f45SPeter Brune snes->reason = SNES_DIVERGED_INNER; 100939bd7f45SPeter Brune PetscFunctionReturn(0); 101039bd7f45SPeter Brune } 101139bd7f45SPeter Brune } else if (snes->usegs && snes->ops->computegs) { 101239bd7f45SPeter Brune if (fas->monitor) { 101339bd7f45SPeter Brune ierr = SNESComputeFunction(snes, X, F);CHKERRQ(ierr); 101439bd7f45SPeter Brune ierr = VecNorm(F, NORM_2, &fnorm);CHKERRQ(ierr); 101539bd7f45SPeter Brune ierr = PetscViewerASCIIAddTab(fas->monitor,((PetscObject)snes)->tablevel + 2);CHKERRQ(ierr); 101639bd7f45SPeter Brune ierr = PetscViewerASCIIPrintf(fas->monitor, "%d SNES GS Function norm %14.12e\n", 0, fnorm);CHKERRQ(ierr); 101739bd7f45SPeter Brune ierr = PetscViewerASCIISubtractTab(fas->monitor,((PetscObject)snes)->tablevel + 2);CHKERRQ(ierr); 101839bd7f45SPeter Brune } 10199c44eddcSPeter Brune ierr = SNESSetGSSweeps(snes, fas->max_up_it);CHKERRQ(ierr); 102039bd7f45SPeter Brune ierr = SNESComputeGS(snes, B, X);CHKERRQ(ierr); 102139bd7f45SPeter Brune if (fas->monitor) { 102239bd7f45SPeter Brune ierr = SNESComputeFunction(snes, X, F);CHKERRQ(ierr); 102339bd7f45SPeter Brune ierr = VecNorm(F, NORM_2, &fnorm);CHKERRQ(ierr); 102439bd7f45SPeter Brune ierr = PetscViewerASCIIAddTab(fas->monitor,((PetscObject)snes)->tablevel + 2);CHKERRQ(ierr); 10259c44eddcSPeter Brune ierr = PetscViewerASCIIPrintf(fas->monitor, "1 SNES GS Function norm %14.12e\n", fnorm);CHKERRQ(ierr); 102639bd7f45SPeter Brune ierr = PetscViewerASCIISubtractTab(fas->monitor,((PetscObject)snes)->tablevel + 2);CHKERRQ(ierr); 102739bd7f45SPeter Brune } 102839bd7f45SPeter Brune } else if (snes->pc) { 102939bd7f45SPeter Brune ierr = SNESSolve(snes->pc, B, X);CHKERRQ(ierr); 103039bd7f45SPeter Brune ierr = SNESGetConvergedReason(fas->downsmooth,&reason);CHKERRQ(ierr); 103139bd7f45SPeter Brune if (reason < 0 && reason != SNES_DIVERGED_MAX_IT) { 103239bd7f45SPeter Brune snes->reason = SNES_DIVERGED_INNER; 103339bd7f45SPeter Brune PetscFunctionReturn(0); 103439bd7f45SPeter Brune } 103539bd7f45SPeter Brune } 103639bd7f45SPeter Brune PetscFunctionReturn(0); 103739bd7f45SPeter Brune } 103839bd7f45SPeter Brune 103939bd7f45SPeter Brune #undef __FUNCT__ 104039bd7f45SPeter Brune #define __FUNCT__ "FASCoarseCorrection" 104139bd7f45SPeter Brune /* 104239bd7f45SPeter Brune 104339bd7f45SPeter Brune Performs the FAS coarse correction as: 104439bd7f45SPeter Brune 104539bd7f45SPeter Brune fine problem: F(x) = 0 104639bd7f45SPeter Brune coarse problem: F^c(x) = b^c 104739bd7f45SPeter Brune 104839bd7f45SPeter Brune b^c = F^c(I^c_fx^f - I^c_fF(x)) 104939bd7f45SPeter Brune 105039bd7f45SPeter Brune with correction: 105139bd7f45SPeter Brune 105239bd7f45SPeter Brune 105339bd7f45SPeter Brune 105439bd7f45SPeter Brune */ 105539a4b097SPeter Brune PetscErrorCode FASCoarseCorrection(SNES snes, Vec X, Vec F, Vec X_new) { 105639bd7f45SPeter Brune PetscErrorCode ierr; 105739bd7f45SPeter Brune Vec X_c, Xo_c, F_c, B_c; 105839bd7f45SPeter Brune SNES_FAS *fas = (SNES_FAS *)snes->data; 105939bd7f45SPeter Brune SNESConvergedReason reason; 106039bd7f45SPeter Brune PetscFunctionBegin; 1061fa9694d7SPeter Brune if (fas->next) { 1062ee78dd50SPeter Brune ierr = SNESComputeFunction(snes, X, F);CHKERRQ(ierr); 1063794bee33SPeter Brune 1064c90fad12SPeter Brune X_c = fas->next->vec_sol; 1065293a7e31SPeter Brune Xo_c = fas->next->work[0]; 1066c90fad12SPeter Brune F_c = fas->next->vec_func; 1067742fe5e2SPeter Brune B_c = fas->next->vec_rhs; 1068efe1f98aSPeter Brune 1069efe1f98aSPeter Brune /* inject the solution */ 1070efe1f98aSPeter Brune if (fas->inject) { 1071a3cb90a9SPeter Brune ierr = MatRestrict(fas->inject, X, Xo_c);CHKERRQ(ierr); 1072efe1f98aSPeter Brune } else { 1073a3cb90a9SPeter Brune ierr = MatRestrict(fas->restrct, X, Xo_c);CHKERRQ(ierr); 1074a3cb90a9SPeter Brune ierr = VecPointwiseMult(Xo_c, fas->rscale, Xo_c);CHKERRQ(ierr); 1075efe1f98aSPeter Brune } 1076293a7e31SPeter Brune ierr = VecScale(F, -1.0);CHKERRQ(ierr); 1077293a7e31SPeter Brune 1078293a7e31SPeter Brune /* restrict the defect */ 1079293a7e31SPeter Brune ierr = MatRestrict(fas->restrct, F, B_c);CHKERRQ(ierr); 1080293a7e31SPeter Brune 1081c90fad12SPeter Brune /* solve the coarse problem corresponding to F^c(x^c) = b^c = Rb + F^c(Rx) - RF(x) */ 1082ee78dd50SPeter Brune fas->next->vec_rhs = PETSC_NULL; /*unset the RHS to evaluate function instead of residual*/ 1083c90fad12SPeter Brune ierr = SNESComputeFunction(fas->next, Xo_c, F_c);CHKERRQ(ierr); 1084742fe5e2SPeter Brune 1085293a7e31SPeter Brune ierr = VecAXPY(B_c, 1.0, F_c);CHKERRQ(ierr); /* add F_c(X) to the RHS */ 1086c90fad12SPeter Brune 1087ee78dd50SPeter Brune /* set initial guess of the coarse problem to the projected fine solution */ 1088ee78dd50SPeter Brune ierr = VecCopy(Xo_c, X_c);CHKERRQ(ierr); 1089c90fad12SPeter Brune 1090c90fad12SPeter Brune /* recurse to the next level */ 1091f5a6d4f9SBarry Smith fas->next->vec_rhs = B_c; 1092742fe5e2SPeter Brune /* ierr = FASCycle_Private(fas->next, X_c);CHKERRQ(ierr); */ 1093742fe5e2SPeter Brune ierr = SNESSolve(fas->next, B_c, X_c);CHKERRQ(ierr); 1094742fe5e2SPeter Brune ierr = SNESGetConvergedReason(fas->next,&reason);CHKERRQ(ierr); 1095742fe5e2SPeter Brune if (reason < 0 && reason != SNES_DIVERGED_MAX_IT) { 1096742fe5e2SPeter Brune snes->reason = SNES_DIVERGED_INNER; 1097742fe5e2SPeter Brune PetscFunctionReturn(0); 1098742fe5e2SPeter Brune } 1099742fe5e2SPeter Brune /* fas->next->vec_rhs = PETSC_NULL; */ 1100ee78dd50SPeter Brune 1101fa9694d7SPeter Brune /* correct as x <- x + I(x^c - Rx)*/ 1102fa9694d7SPeter Brune ierr = VecAXPY(X_c, -1.0, Xo_c);CHKERRQ(ierr); 110339bd7f45SPeter Brune ierr = MatInterpolateAdd(fas->interpolate, X_c, X, X_new);CHKERRQ(ierr); 1104293a7e31SPeter Brune } 110539bd7f45SPeter Brune PetscFunctionReturn(0); 110639bd7f45SPeter Brune } 110739bd7f45SPeter Brune 110839bd7f45SPeter Brune #undef __FUNCT__ 110939bd7f45SPeter Brune #define __FUNCT__ "FASCycle_Additive" 111039bd7f45SPeter Brune /* 111139bd7f45SPeter Brune 111239bd7f45SPeter Brune The additive cycle looks like: 111339bd7f45SPeter Brune 111407144faaSPeter Brune xhat = x 111507144faaSPeter Brune xhat = dS(x, b) 111607144faaSPeter Brune x = coarsecorrection(xhat, b_d) 111707144faaSPeter Brune x = x + nu*(xhat - x); 111839bd7f45SPeter Brune (optional) x = uS(x, b) 111939bd7f45SPeter Brune 112039bd7f45SPeter Brune With the coarse RHS (defect correction) as below. 112139bd7f45SPeter Brune 112239bd7f45SPeter Brune */ 112339bd7f45SPeter Brune PetscErrorCode FASCycle_Additive(SNES snes, Vec X) { 112407144faaSPeter Brune Vec F, B, Xhat; 1125ddebd997SPeter Brune Vec X_c, Xo_c, F_c, B_c, G, W; 112639bd7f45SPeter Brune PetscErrorCode ierr; 112707144faaSPeter Brune SNES_FAS * fas = (SNES_FAS *)snes->data; 112807144faaSPeter Brune SNESConvergedReason reason; 1129ddebd997SPeter Brune PetscReal xnorm = 0., fnorm = 0., gnorm = 0., ynorm = 0.; 1130ddebd997SPeter Brune PetscBool lssucceed; 113139bd7f45SPeter Brune PetscFunctionBegin; 113239bd7f45SPeter Brune 113339bd7f45SPeter Brune F = snes->vec_func; 113439bd7f45SPeter Brune B = snes->vec_rhs; 113507144faaSPeter Brune Xhat = snes->work[1]; 1136ddebd997SPeter Brune G = snes->work[2]; 1137ddebd997SPeter Brune W = snes->work[3]; 113807144faaSPeter Brune ierr = VecCopy(X, Xhat);CHKERRQ(ierr); 113907144faaSPeter Brune /* recurse first */ 114007144faaSPeter Brune if (fas->next) { 114107144faaSPeter Brune ierr = SNESComputeFunction(snes, Xhat, F);CHKERRQ(ierr); 114239bd7f45SPeter Brune 114307144faaSPeter Brune X_c = fas->next->vec_sol; 114407144faaSPeter Brune Xo_c = fas->next->work[0]; 114507144faaSPeter Brune F_c = fas->next->vec_func; 114607144faaSPeter Brune B_c = fas->next->vec_rhs; 114739bd7f45SPeter Brune 114807144faaSPeter Brune /* inject the solution */ 114907144faaSPeter Brune if (fas->inject) { 115007144faaSPeter Brune ierr = MatRestrict(fas->inject, Xhat, Xo_c);CHKERRQ(ierr); 115107144faaSPeter Brune } else { 115207144faaSPeter Brune ierr = MatRestrict(fas->restrct, Xhat, Xo_c);CHKERRQ(ierr); 115307144faaSPeter Brune ierr = VecPointwiseMult(Xo_c, fas->rscale, Xo_c);CHKERRQ(ierr); 115407144faaSPeter Brune } 115507144faaSPeter Brune ierr = VecScale(F, -1.0);CHKERRQ(ierr); 115607144faaSPeter Brune 115707144faaSPeter Brune /* restrict the defect */ 115807144faaSPeter Brune ierr = MatRestrict(fas->restrct, F, B_c);CHKERRQ(ierr); 115907144faaSPeter Brune 116007144faaSPeter Brune /* solve the coarse problem corresponding to F^c(x^c) = b^c = Rb + F^c(Rx) - RF(x) */ 116107144faaSPeter Brune fas->next->vec_rhs = PETSC_NULL; /*unset the RHS to evaluate function instead of residual*/ 116207144faaSPeter Brune ierr = SNESComputeFunction(fas->next, Xo_c, F_c);CHKERRQ(ierr); 116307144faaSPeter Brune 116407144faaSPeter Brune ierr = VecAXPY(B_c, 1.0, F_c);CHKERRQ(ierr); /* add F_c(X) to the RHS */ 116507144faaSPeter Brune 116607144faaSPeter Brune /* set initial guess of the coarse problem to the projected fine solution */ 116707144faaSPeter Brune ierr = VecCopy(Xo_c, X_c);CHKERRQ(ierr); 116807144faaSPeter Brune 116907144faaSPeter Brune /* recurse */ 117007144faaSPeter Brune fas->next->vec_rhs = B_c; 117107144faaSPeter Brune ierr = SNESSolve(fas->next, B_c, X_c);CHKERRQ(ierr); 117207144faaSPeter Brune 117307144faaSPeter Brune /* smooth on this level */ 117407144faaSPeter Brune ierr = FASDownSmooth(snes, B, X, F);CHKERRQ(ierr); 117507144faaSPeter Brune 117607144faaSPeter Brune ierr = SNESGetConvergedReason(fas->next,&reason);CHKERRQ(ierr); 117707144faaSPeter Brune if (reason < 0 && reason != SNES_DIVERGED_MAX_IT) { 117807144faaSPeter Brune snes->reason = SNES_DIVERGED_INNER; 117907144faaSPeter Brune PetscFunctionReturn(0); 118007144faaSPeter Brune } 118107144faaSPeter Brune 118207144faaSPeter Brune /* correct as x <- x + I(x^c - Rx)*/ 118307144faaSPeter Brune ierr = VecAXPY(X_c, -1.0, Xo_c);CHKERRQ(ierr); 1184ddebd997SPeter Brune ierr = MatInterpolate(fas->interpolate, X_c, Xhat);CHKERRQ(ierr); 118507144faaSPeter Brune 1186ddebd997SPeter Brune /* additive correction of the coarse direction*/ 1187ddebd997SPeter Brune ierr = SNESComputeFunction(snes, X, F);CHKERRQ(ierr); 1188ddebd997SPeter Brune ierr = VecNorm(F, NORM_2, &fnorm);CHKERRQ(ierr); 1189eb1825c3SPeter Brune ierr = VecScale(Xhat, -1.0);CHKERRQ(ierr); 1190ddebd997SPeter Brune ierr = (*snes->ops->linesearch)(snes,snes->lsP,X,F,Xhat,fnorm,xnorm,G,W,&ynorm,&gnorm,&lssucceed);CHKERRQ(ierr); 1191ddebd997SPeter Brune ierr = VecCopy(W, X);CHKERRQ(ierr); 1192ddebd997SPeter Brune ierr = VecCopy(G, F);CHKERRQ(ierr); 1193ddebd997SPeter Brune fnorm = gnorm; 119407144faaSPeter Brune } else { 119507144faaSPeter Brune ierr = FASDownSmooth(snes, B, X, F);CHKERRQ(ierr); 119607144faaSPeter Brune } 119739bd7f45SPeter Brune PetscFunctionReturn(0); 119839bd7f45SPeter Brune } 119939bd7f45SPeter Brune 120039bd7f45SPeter Brune #undef __FUNCT__ 120139bd7f45SPeter Brune #define __FUNCT__ "FASCycle_Multiplicative" 120239bd7f45SPeter Brune /* 120339bd7f45SPeter Brune 120439bd7f45SPeter Brune Defines the FAS cycle as: 120539bd7f45SPeter Brune 120639bd7f45SPeter Brune fine problem: F(x) = 0 120739bd7f45SPeter Brune coarse problem: F^c(x) = b^c 120839bd7f45SPeter Brune 120939bd7f45SPeter Brune b^c = F^c(I^c_fx^f - I^c_fF(x)) 121039bd7f45SPeter Brune 121139bd7f45SPeter Brune correction: 121239bd7f45SPeter Brune 121339bd7f45SPeter Brune x = x + I(x^c - Rx) 121439bd7f45SPeter Brune 121539bd7f45SPeter Brune */ 121639bd7f45SPeter Brune PetscErrorCode FASCycle_Multiplicative(SNES snes, Vec X) { 121739bd7f45SPeter Brune 121839bd7f45SPeter Brune PetscErrorCode ierr; 121939bd7f45SPeter Brune Vec F,B; 122039bd7f45SPeter Brune SNES_FAS *fas = (SNES_FAS *)snes->data; 122139bd7f45SPeter Brune 122239bd7f45SPeter Brune PetscFunctionBegin; 122339bd7f45SPeter Brune F = snes->vec_func; 122439bd7f45SPeter Brune B = snes->vec_rhs; 122539bd7f45SPeter Brune /* pre-smooth -- just update using the pre-smoother */ 122639bd7f45SPeter Brune ierr = FASDownSmooth(snes, B, X, F);CHKERRQ(ierr); 122739bd7f45SPeter Brune 122839a4b097SPeter Brune ierr = FASCoarseCorrection(snes, X, F, X);CHKERRQ(ierr); 122939bd7f45SPeter Brune 1230c90fad12SPeter Brune if (fas->level != 0) { 123139bd7f45SPeter Brune ierr = FASUpSmooth(snes, B, X, F);CHKERRQ(ierr); 1232fe6f9142SPeter Brune } 1233fe6f9142SPeter Brune ierr = SNESComputeFunction(snes, X, F);CHKERRQ(ierr); 1234fa9694d7SPeter Brune 1235fa9694d7SPeter Brune PetscFunctionReturn(0); 1236421d9b32SPeter Brune } 1237421d9b32SPeter Brune 1238421d9b32SPeter Brune #undef __FUNCT__ 1239421d9b32SPeter Brune #define __FUNCT__ "SNESSolve_FAS" 1240421d9b32SPeter Brune 1241421d9b32SPeter Brune PetscErrorCode SNESSolve_FAS(SNES snes) 1242421d9b32SPeter Brune { 1243fa9694d7SPeter Brune PetscErrorCode ierr; 1244fe6f9142SPeter Brune PetscInt i, maxits; 1245ddb5aff1SPeter Brune Vec X, F; 1246fe6f9142SPeter Brune PetscReal fnorm; 124707144faaSPeter Brune SNES_FAS *fas = (SNES_FAS *)snes->data; 1248421d9b32SPeter Brune PetscFunctionBegin; 1249fe6f9142SPeter Brune maxits = snes->max_its; /* maximum number of iterations */ 1250fe6f9142SPeter Brune snes->reason = SNES_CONVERGED_ITERATING; 1251fa9694d7SPeter Brune X = snes->vec_sol; 1252f5a6d4f9SBarry Smith F = snes->vec_func; 1253293a7e31SPeter Brune 1254293a7e31SPeter Brune /*norm setup */ 1255fe6f9142SPeter Brune ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr); 1256fe6f9142SPeter Brune snes->iter = 0; 1257fe6f9142SPeter Brune snes->norm = 0.; 1258fe6f9142SPeter Brune ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr); 1259fe6f9142SPeter Brune ierr = SNESComputeFunction(snes,X,F);CHKERRQ(ierr); 1260fe6f9142SPeter Brune if (snes->domainerror) { 1261fe6f9142SPeter Brune snes->reason = SNES_DIVERGED_FUNCTION_DOMAIN; 1262fe6f9142SPeter Brune PetscFunctionReturn(0); 1263fe6f9142SPeter Brune } 1264fe6f9142SPeter Brune ierr = VecNorm(F, NORM_2, &fnorm);CHKERRQ(ierr); /* fnorm <- ||F|| */ 1265fe6f9142SPeter Brune if (PetscIsInfOrNanReal(fnorm)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"Infinite or not-a-number generated in norm"); 1266fe6f9142SPeter Brune ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr); 1267fe6f9142SPeter Brune snes->norm = fnorm; 1268fe6f9142SPeter Brune ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr); 1269fe6f9142SPeter Brune SNESLogConvHistory(snes,fnorm,0); 1270fe6f9142SPeter Brune ierr = SNESMonitor(snes,0,fnorm);CHKERRQ(ierr); 1271fe6f9142SPeter Brune 1272fe6f9142SPeter Brune /* set parameter for default relative tolerance convergence test */ 1273fe6f9142SPeter Brune snes->ttol = fnorm*snes->rtol; 1274fe6f9142SPeter Brune /* test convergence */ 1275fe6f9142SPeter Brune ierr = (*snes->ops->converged)(snes,0,0.0,0.0,fnorm,&snes->reason,snes->cnvP);CHKERRQ(ierr); 1276fe6f9142SPeter Brune if (snes->reason) PetscFunctionReturn(0); 1277fe6f9142SPeter Brune for (i = 0; i < maxits; i++) { 1278fe6f9142SPeter Brune /* Call general purpose update function */ 1279646217ecSPeter Brune 1280fe6f9142SPeter Brune if (snes->ops->update) { 1281fe6f9142SPeter Brune ierr = (*snes->ops->update)(snes, snes->iter);CHKERRQ(ierr); 1282fe6f9142SPeter Brune } 128307144faaSPeter Brune if (fas->fastype == SNES_FAS_MULTIPLICATIVE) { 128439bd7f45SPeter Brune ierr = FASCycle_Multiplicative(snes, X);CHKERRQ(ierr); 128507144faaSPeter Brune } else { 128607144faaSPeter Brune ierr = FASCycle_Additive(snes, X);CHKERRQ(ierr); 128707144faaSPeter Brune } 1288742fe5e2SPeter Brune 1289742fe5e2SPeter Brune /* check for FAS cycle divergence */ 1290742fe5e2SPeter Brune if (snes->reason != SNES_CONVERGED_ITERATING) { 1291742fe5e2SPeter Brune PetscFunctionReturn(0); 1292742fe5e2SPeter Brune } 1293c90fad12SPeter Brune ierr = VecNorm(F, NORM_2, &fnorm);CHKERRQ(ierr); /* fnorm <- ||F|| */ 1294c90fad12SPeter Brune /* Monitor convergence */ 1295c90fad12SPeter Brune ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr); 1296c90fad12SPeter Brune snes->iter = i+1; 1297c90fad12SPeter Brune snes->norm = fnorm; 1298c90fad12SPeter Brune ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr); 1299c90fad12SPeter Brune SNESLogConvHistory(snes,snes->norm,0); 1300c90fad12SPeter Brune ierr = SNESMonitor(snes,snes->iter,snes->norm);CHKERRQ(ierr); 1301c90fad12SPeter Brune /* Test for convergence */ 1302c90fad12SPeter Brune ierr = (*snes->ops->converged)(snes,snes->iter,0.0,0.0,fnorm,&snes->reason,snes->cnvP);CHKERRQ(ierr); 1303c90fad12SPeter Brune if (snes->reason) break; 1304fe6f9142SPeter Brune } 1305fe6f9142SPeter Brune if (i == maxits) { 1306fe6f9142SPeter Brune ierr = PetscInfo1(snes, "Maximum number of iterations has been reached: %D\n", maxits);CHKERRQ(ierr); 1307fe6f9142SPeter Brune if (!snes->reason) snes->reason = SNES_DIVERGED_MAX_IT; 1308fe6f9142SPeter Brune } 1309421d9b32SPeter Brune PetscFunctionReturn(0); 1310421d9b32SPeter Brune } 1311