1421d9b32SPeter Brune /* Defines the basic SNES object */ 26038b46bSPeter Brune #include <../src/snes/impls/fas/fasimpls.h> /*I "petscsnesfas.h" I*/ 3421d9b32SPeter Brune 46a6fc655SJed Brown const char *const SNESFASTypes[] = {"MULTIPLICATIVE","ADDITIVE","SNESFASType","SNES_FAS",0}; 507144faaSPeter Brune 6421d9b32SPeter Brune extern PetscErrorCode SNESDestroy_FAS(SNES snes); 7421d9b32SPeter Brune extern PetscErrorCode SNESSetUp_FAS(SNES snes); 8421d9b32SPeter Brune extern PetscErrorCode SNESSetFromOptions_FAS(SNES snes); 9421d9b32SPeter Brune extern PetscErrorCode SNESView_FAS(SNES snes, PetscViewer viewer); 10421d9b32SPeter Brune extern PetscErrorCode SNESSolve_FAS(SNES snes); 11421d9b32SPeter Brune extern PetscErrorCode SNESReset_FAS(SNES snes); 126273346dSPeter Brune extern PetscErrorCode SNESFASGalerkinDefaultFunction(SNES, Vec, Vec, void *); 13ab8d36c9SPeter Brune extern PetscErrorCode SNESFASCycleCreateSmoother_Private(SNES, SNES *); 14421d9b32SPeter Brune 151fbfccc6SJed Brown /*MC 161fbfccc6SJed Brown 171fbfccc6SJed Brown SNESFAS - Full Approximation Scheme nonlinear multigrid solver. 181fbfccc6SJed Brown 19d3bc2379SPeter Brune The nonlinear problem is solved by correction using coarse versions 20d3bc2379SPeter Brune of the nonlinear problem. This problem is perturbed so that a projected 21d3bc2379SPeter Brune solution of the fine problem elicits no correction from the coarse problem. 22d3bc2379SPeter Brune 23d3bc2379SPeter Brune Options Database: 24d3bc2379SPeter Brune + -snes_fas_levels - The number of levels 25d3bc2379SPeter Brune . -snes_fas_cycles<1> - The number of cycles -- 1 for V, 2 for W 26d3bc2379SPeter Brune . -snes_fas_type<additive, multiplicative> - Additive or multiplicative cycle 27d3bc2379SPeter Brune . -snes_fas_galerkin<PETSC_FALSE> - Form coarse problems by projection back upon the fine problem 28d3bc2379SPeter Brune . -snes_fas_smoothup<1> - The number of iterations of the post-smoother 29d3bc2379SPeter Brune . -snes_fas_smoothdown<1> - The number of iterations of the pre-smoother 30d3bc2379SPeter Brune . -snes_fas_monitor - Monitor progress of all of the levels 31d3bc2379SPeter Brune . -fas_levels_snes_ - SNES options for all smoothers 327d84e935SPeter Brune . -fas_levels_cycle_snes_ - SNES options for all cycles 33d3bc2379SPeter Brune . -fas_levels_i_snes_ - SNES options for the smoothers on level i 347d84e935SPeter Brune . -fas_levels_i_cycle_snes_ - SNES options for the cycle on level i 35d3bc2379SPeter Brune - -fas_coarse_snes_ - SNES options for the coarsest smoother 36d3bc2379SPeter Brune 37d3bc2379SPeter Brune Notes: 38d3bc2379SPeter Brune The organization of the FAS solver is slightly different from the organization of PCMG 39d3bc2379SPeter Brune As each level has smoother SNES instances(down and potentially up) and a cycle SNES instance. 40d3bc2379SPeter Brune The cycle SNES instance may be used for monitoring convergence on a particular level. 411fbfccc6SJed Brown 427d84e935SPeter Brune Level: beginner 431fbfccc6SJed Brown 44d3bc2379SPeter Brune .seealso: PCMG, SNESCreate(), SNES, SNESSetType(), SNESType (for list of available types) 451fbfccc6SJed Brown M*/ 46421d9b32SPeter Brune 47421d9b32SPeter Brune #undef __FUNCT__ 48421d9b32SPeter Brune #define __FUNCT__ "SNESCreate_FAS" 491fbfccc6SJed Brown PETSC_EXTERN_C PetscErrorCode SNESCreate_FAS(SNES snes) 50421d9b32SPeter Brune { 51421d9b32SPeter Brune SNES_FAS * fas; 52421d9b32SPeter Brune PetscErrorCode ierr; 53421d9b32SPeter Brune 54421d9b32SPeter Brune PetscFunctionBegin; 55421d9b32SPeter Brune snes->ops->destroy = SNESDestroy_FAS; 56421d9b32SPeter Brune snes->ops->setup = SNESSetUp_FAS; 57421d9b32SPeter Brune snes->ops->setfromoptions = SNESSetFromOptions_FAS; 58421d9b32SPeter Brune snes->ops->view = SNESView_FAS; 59421d9b32SPeter Brune snes->ops->solve = SNESSolve_FAS; 60421d9b32SPeter Brune snes->ops->reset = SNESReset_FAS; 61421d9b32SPeter Brune 62ed020824SBarry Smith snes->usesksp = PETSC_FALSE; 63ed020824SBarry Smith snes->usespc = PETSC_FALSE; 64ed020824SBarry Smith 6588976e71SPeter Brune if (!snes->tolerancesset) { 660e444f03SPeter Brune snes->max_funcs = 30000; 670e444f03SPeter Brune snes->max_its = 10000; 6888976e71SPeter Brune } 690e444f03SPeter Brune 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; 77ab8d36c9SPeter Brune fas->smoothu = PETSC_NULL; 78ab8d36c9SPeter Brune fas->smoothd = PETSC_NULL; 79421d9b32SPeter Brune fas->next = PETSC_NULL; 806273346dSPeter Brune fas->previous = PETSC_NULL; 81ab8d36c9SPeter Brune fas->fine = snes; 82421d9b32SPeter Brune fas->interpolate = PETSC_NULL; 83421d9b32SPeter Brune fas->restrct = PETSC_NULL; 84efe1f98aSPeter Brune fas->inject = PETSC_NULL; 85cc05f883SPeter Brune fas->monitor = PETSC_NULL; 86cc05f883SPeter Brune fas->usedmfornumberoflevels = PETSC_FALSE; 87ddebd997SPeter Brune fas->fastype = SNES_FAS_MULTIPLICATIVE; 88*0dd27c6cSPeter Brune 89*0dd27c6cSPeter Brune fas->eventsmoothsetup = PETSC_FALSE; 90*0dd27c6cSPeter Brune fas->eventsmoothsolve = PETSC_FALSE; 91*0dd27c6cSPeter Brune fas->eventresidual = PETSC_FALSE; 92*0dd27c6cSPeter Brune fas->eventinterprestrict = PETSC_FALSE; 93*0dd27c6cSPeter Brune 94efe1f98aSPeter Brune PetscFunctionReturn(0); 95efe1f98aSPeter Brune } 96efe1f98aSPeter Brune 97421d9b32SPeter Brune #undef __FUNCT__ 98421d9b32SPeter Brune #define __FUNCT__ "SNESReset_FAS" 99421d9b32SPeter Brune PetscErrorCode SNESReset_FAS(SNES snes) 100421d9b32SPeter Brune { 10177df8cc4SPeter Brune PetscErrorCode ierr = 0; 102421d9b32SPeter Brune SNES_FAS * fas = (SNES_FAS *)snes->data; 103421d9b32SPeter Brune 104421d9b32SPeter Brune PetscFunctionBegin; 105ab8d36c9SPeter Brune ierr = SNESDestroy(&fas->smoothu);CHKERRQ(ierr); 106ab8d36c9SPeter Brune ierr = SNESDestroy(&fas->smoothd);CHKERRQ(ierr); 1073dccd265SPeter Brune ierr = MatDestroy(&fas->inject);CHKERRQ(ierr); 108bccf9bb3SJed Brown ierr = MatDestroy(&fas->interpolate);CHKERRQ(ierr); 109bccf9bb3SJed Brown ierr = MatDestroy(&fas->restrct);CHKERRQ(ierr); 110bccf9bb3SJed Brown ierr = VecDestroy(&fas->rscale);CHKERRQ(ierr); 111742fe5e2SPeter Brune if (fas->next) ierr = SNESReset(fas->next);CHKERRQ(ierr); 11222c1e704SPeter Brune 113421d9b32SPeter Brune PetscFunctionReturn(0); 114421d9b32SPeter Brune } 115421d9b32SPeter Brune 116421d9b32SPeter Brune #undef __FUNCT__ 117421d9b32SPeter Brune #define __FUNCT__ "SNESDestroy_FAS" 118421d9b32SPeter Brune PetscErrorCode SNESDestroy_FAS(SNES snes) 119421d9b32SPeter Brune { 120421d9b32SPeter Brune SNES_FAS * fas = (SNES_FAS *)snes->data; 121742fe5e2SPeter Brune PetscErrorCode ierr = 0; 122421d9b32SPeter Brune 123421d9b32SPeter Brune PetscFunctionBegin; 124421d9b32SPeter Brune /* recursively resets and then destroys */ 12579d9a41aSPeter Brune ierr = SNESReset(snes);CHKERRQ(ierr); 126421d9b32SPeter Brune if (fas->next) ierr = SNESDestroy(&fas->next);CHKERRQ(ierr); 127421d9b32SPeter Brune ierr = PetscFree(fas);CHKERRQ(ierr); 128ee1fd11aSPeter Brune 129421d9b32SPeter Brune PetscFunctionReturn(0); 130421d9b32SPeter Brune } 131421d9b32SPeter Brune 132421d9b32SPeter Brune #undef __FUNCT__ 133421d9b32SPeter Brune #define __FUNCT__ "SNESSetUp_FAS" 134421d9b32SPeter Brune PetscErrorCode SNESSetUp_FAS(SNES snes) 135421d9b32SPeter Brune { 13648bfdf8aSPeter Brune SNES_FAS *fas = (SNES_FAS *) snes->data; 137421d9b32SPeter Brune PetscErrorCode ierr; 138efe1f98aSPeter Brune VecScatter injscatter; 139d1adcc6fSPeter Brune PetscInt dm_levels; 1403dccd265SPeter Brune Vec vec_sol, vec_func, vec_sol_update, vec_rhs; /* preserve these if they're set through the reset */ 141ab8d36c9SPeter Brune SNES next; 142ab8d36c9SPeter Brune PetscBool isFine; 143f89ba88eSPeter Brune SNESLineSearch linesearch; 144f89ba88eSPeter Brune SNESLineSearch slinesearch; 145f89ba88eSPeter Brune void *lsprectx,*lspostctx; 1466b2b7091SBarry Smith PetscErrorCode (*precheck)(SNESLineSearch,Vec,Vec,PetscBool*,void*); 1476b2b7091SBarry Smith PetscErrorCode (*postcheck)(SNESLineSearch,Vec,Vec,Vec,PetscBool *,PetscBool *,void*); 148eff52c0eSPeter Brune 1496b2b7091SBarry Smith PetscFunctionBegin; 150ab8d36c9SPeter Brune ierr = SNESFASCycleIsFine(snes, &isFine);CHKERRQ(ierr); 151ab8d36c9SPeter Brune if (fas->usedmfornumberoflevels && isFine) { 152d1adcc6fSPeter Brune ierr = DMGetRefineLevel(snes->dm,&dm_levels);CHKERRQ(ierr); 153d1adcc6fSPeter Brune dm_levels++; 154cc05f883SPeter Brune if (dm_levels > fas->levels) { 1552e8ce248SJed Brown /* we don't want the solution and func vectors to be destroyed in the SNESReset when it's called in SNESFASSetLevels_FAS*/ 1563dccd265SPeter Brune vec_sol = snes->vec_sol; 1573dccd265SPeter Brune vec_func = snes->vec_func; 1583dccd265SPeter Brune vec_sol_update = snes->vec_sol_update; 1593dccd265SPeter Brune vec_rhs = snes->vec_rhs; 1603dccd265SPeter Brune snes->vec_sol = PETSC_NULL; 1613dccd265SPeter Brune snes->vec_func = PETSC_NULL; 1623dccd265SPeter Brune snes->vec_sol_update = PETSC_NULL; 1633dccd265SPeter Brune snes->vec_rhs = PETSC_NULL; 1643dccd265SPeter Brune 1653dccd265SPeter Brune /* reset the number of levels */ 166d1adcc6fSPeter Brune ierr = SNESFASSetLevels(snes,dm_levels,PETSC_NULL);CHKERRQ(ierr); 167cc05f883SPeter Brune ierr = SNESSetFromOptions(snes);CHKERRQ(ierr); 1683dccd265SPeter Brune 1693dccd265SPeter Brune snes->vec_sol = vec_sol; 1703dccd265SPeter Brune snes->vec_func = vec_func; 1713dccd265SPeter Brune snes->vec_rhs = vec_rhs; 1723dccd265SPeter Brune snes->vec_sol_update = vec_sol_update; 173d1adcc6fSPeter Brune } 174d1adcc6fSPeter Brune } 175ab8d36c9SPeter Brune ierr = SNESFASCycleGetCorrection(snes, &next);CHKERRQ(ierr); 176ab8d36c9SPeter Brune if (!isFine) snes->gridsequence = 0; /* no grid sequencing inside the multigrid hierarchy! */ 1773dccd265SPeter Brune 17807144faaSPeter Brune if (fas->fastype == SNES_FAS_MULTIPLICATIVE) { 179e4ed7901SPeter Brune ierr = SNESDefaultGetWork(snes, 2);CHKERRQ(ierr); /* work vectors used for intergrid transfers */ 18007144faaSPeter Brune } else { 181e7f468e7SPeter Brune ierr = SNESDefaultGetWork(snes, 2);CHKERRQ(ierr); /* work vectors used for intergrid transfers */ 18207144faaSPeter Brune } 183cc05f883SPeter Brune 184ab8d36c9SPeter Brune /* set up the smoothers if they haven't already been set up */ 185ab8d36c9SPeter Brune if (!fas->smoothd) { 186ab8d36c9SPeter Brune ierr = SNESFASCycleCreateSmoother_Private(snes, &fas->smoothd);CHKERRQ(ierr); 187ab8d36c9SPeter Brune } 188ab8d36c9SPeter Brune 18979d9a41aSPeter Brune if (snes->dm) { 190ab8d36c9SPeter Brune /* set the smoother DMs properly */ 191ab8d36c9SPeter Brune if (fas->smoothu) ierr = SNESSetDM(fas->smoothu, snes->dm);CHKERRQ(ierr); 192ab8d36c9SPeter Brune ierr = SNESSetDM(fas->smoothd, snes->dm);CHKERRQ(ierr); 19379d9a41aSPeter Brune /* construct EVERYTHING from the DM -- including the progressive set of smoothers */ 194ab8d36c9SPeter Brune if (next) { 19579d9a41aSPeter Brune /* for now -- assume the DM and the evaluation functions have been set externally */ 196ab8d36c9SPeter Brune if (!next->dm) { 197ab8d36c9SPeter Brune ierr = DMCoarsen(snes->dm, ((PetscObject)next)->comm, &next->dm);CHKERRQ(ierr); 198ab8d36c9SPeter Brune ierr = SNESSetDM(next, next->dm);CHKERRQ(ierr); 19979d9a41aSPeter Brune } 20079d9a41aSPeter Brune /* set the interpolation and restriction from the DM */ 20179d9a41aSPeter Brune if (!fas->interpolate) { 202ab8d36c9SPeter Brune ierr = DMCreateInterpolation(next->dm, snes->dm, &fas->interpolate, &fas->rscale);CHKERRQ(ierr); 203bccf9bb3SJed Brown if (!fas->restrct) { 204bccf9bb3SJed Brown ierr = PetscObjectReference((PetscObject)fas->interpolate);CHKERRQ(ierr); 20579d9a41aSPeter Brune fas->restrct = fas->interpolate; 20679d9a41aSPeter Brune } 207bccf9bb3SJed Brown } 20879d9a41aSPeter Brune /* set the injection from the DM */ 20979d9a41aSPeter Brune if (!fas->inject) { 210ab8d36c9SPeter Brune ierr = DMCreateInjection(next->dm, snes->dm, &injscatter);CHKERRQ(ierr); 21179d9a41aSPeter Brune ierr = MatCreateScatter(((PetscObject)snes)->comm, injscatter, &fas->inject);CHKERRQ(ierr); 21279d9a41aSPeter Brune ierr = VecScatterDestroy(&injscatter);CHKERRQ(ierr); 21379d9a41aSPeter Brune } 21479d9a41aSPeter Brune } 21579d9a41aSPeter Brune } 21679d9a41aSPeter Brune /*pass the smoother, function, and jacobian up to the next level if it's not user set already */ 21779d9a41aSPeter Brune if (fas->galerkin) { 218ab8d36c9SPeter Brune if (next) 219ab8d36c9SPeter Brune ierr = SNESSetFunction(next, PETSC_NULL, SNESFASGalerkinDefaultFunction, next);CHKERRQ(ierr); 220ab8d36c9SPeter Brune if (fas->smoothd && fas->level != fas->levels - 1) ierr = SNESSetFunction(fas->smoothd, PETSC_NULL, SNESFASGalerkinDefaultFunction, snes);CHKERRQ(ierr); 221ab8d36c9SPeter Brune if (fas->smoothu && fas->level != fas->levels - 1) ierr = SNESSetFunction(fas->smoothu, PETSC_NULL, SNESFASGalerkinDefaultFunction, snes);CHKERRQ(ierr); 22279d9a41aSPeter Brune } 22379d9a41aSPeter Brune 224534ebe21SPeter Brune /* sets the down (pre) smoother's default norm and sets it from options */ 225534ebe21SPeter Brune if (fas->smoothd) { 226bc3f2f05SPeter Brune if (fas->level == 0 && fas->levels != 1) { 227534ebe21SPeter Brune ierr = SNESSetNormType(fas->smoothd, SNES_NORM_NONE);CHKERRQ(ierr); 228534ebe21SPeter Brune } else { 229534ebe21SPeter Brune ierr = SNESSetNormType(fas->smoothd, SNES_NORM_FINAL_ONLY);CHKERRQ(ierr); 230534ebe21SPeter Brune } 2317fce8c19SPeter Brune ierr = PetscObjectCopyFortranFunctionPointers((PetscObject)snes, (PetscObject)fas->smoothd);CHKERRQ(ierr); 232534ebe21SPeter Brune ierr = SNESSetFromOptions(fas->smoothd);CHKERRQ(ierr); 233f89ba88eSPeter Brune ierr = SNESGetSNESLineSearch(snes,&linesearch);CHKERRQ(ierr); 234f89ba88eSPeter Brune ierr = SNESGetSNESLineSearch(fas->smoothd,&slinesearch);CHKERRQ(ierr); 2356b2b7091SBarry Smith ierr = SNESLineSearchGetPreCheck(linesearch,&precheck,&lsprectx);CHKERRQ(ierr); 2366b2b7091SBarry Smith ierr = SNESLineSearchGetPostCheck(linesearch,&postcheck,&lspostctx);CHKERRQ(ierr); 2376b2b7091SBarry Smith ierr = SNESLineSearchSetPreCheck(slinesearch,precheck,lsprectx);CHKERRQ(ierr); 2386b2b7091SBarry Smith ierr = SNESLineSearchSetPostCheck(slinesearch,postcheck,lspostctx);CHKERRQ(ierr); 239f89ba88eSPeter Brune ierr = PetscObjectCopyFortranFunctionPointers((PetscObject)linesearch, (PetscObject)slinesearch);CHKERRQ(ierr); 240*0dd27c6cSPeter Brune 241*0dd27c6cSPeter Brune fas->smoothd->vec_sol = snes->vec_sol; 242*0dd27c6cSPeter Brune ierr = PetscObjectReference((PetscObject)snes->vec_sol);CHKERRQ(ierr); 243*0dd27c6cSPeter Brune fas->smoothd->vec_sol_update = snes->vec_sol_update; 244*0dd27c6cSPeter Brune ierr = PetscObjectReference((PetscObject)snes->vec_sol_update);CHKERRQ(ierr); 245*0dd27c6cSPeter Brune fas->smoothd->vec_func = snes->vec_func; 246*0dd27c6cSPeter Brune ierr = PetscObjectReference((PetscObject)snes->vec_func);CHKERRQ(ierr); 247*0dd27c6cSPeter Brune 248*0dd27c6cSPeter Brune if (fas->eventsmoothsetup) {ierr = PetscLogEventBegin(fas->eventsmoothsetup,0,0,0,0);CHKERRQ(ierr);} 249*0dd27c6cSPeter Brune ierr = SNESSetUp(fas->smoothd);CHKERRQ(ierr); 250*0dd27c6cSPeter Brune if (fas->eventsmoothsetup) {ierr = PetscLogEventEnd(fas->eventsmoothsetup,0,0,0,0);CHKERRQ(ierr);} 251534ebe21SPeter Brune } 252534ebe21SPeter Brune 253534ebe21SPeter Brune /* sets the up (post) smoother's default norm and sets it from options */ 254534ebe21SPeter Brune if (fas->smoothu) { 255534ebe21SPeter Brune if (fas->level != fas->levels - 1) { 256534ebe21SPeter Brune ierr = SNESSetNormType(fas->smoothu, SNES_NORM_NONE);CHKERRQ(ierr); 257534ebe21SPeter Brune } else { 258534ebe21SPeter Brune ierr = SNESSetNormType(fas->smoothu, SNES_NORM_FINAL_ONLY);CHKERRQ(ierr); 259534ebe21SPeter Brune } 2607fce8c19SPeter Brune ierr = PetscObjectCopyFortranFunctionPointers((PetscObject)snes, (PetscObject)fas->smoothu);CHKERRQ(ierr); 261534ebe21SPeter Brune ierr = SNESSetFromOptions(fas->smoothu);CHKERRQ(ierr); 262f89ba88eSPeter Brune ierr = SNESGetSNESLineSearch(snes,&linesearch);CHKERRQ(ierr); 263f89ba88eSPeter Brune ierr = SNESGetSNESLineSearch(fas->smoothu,&slinesearch);CHKERRQ(ierr); 2646b2b7091SBarry Smith ierr = SNESLineSearchGetPreCheck(linesearch,&precheck,&lsprectx);CHKERRQ(ierr); 2656b2b7091SBarry Smith ierr = SNESLineSearchGetPostCheck(linesearch,&postcheck,&lspostctx);CHKERRQ(ierr); 2666b2b7091SBarry Smith ierr = SNESLineSearchSetPreCheck(slinesearch,precheck,lsprectx);CHKERRQ(ierr); 2676b2b7091SBarry Smith ierr = SNESLineSearchSetPostCheck(slinesearch,postcheck,lspostctx);CHKERRQ(ierr); 268f89ba88eSPeter Brune ierr = PetscObjectCopyFortranFunctionPointers((PetscObject)linesearch, (PetscObject)slinesearch);CHKERRQ(ierr); 269*0dd27c6cSPeter Brune 270*0dd27c6cSPeter Brune fas->smoothu->vec_sol = snes->vec_sol; 271*0dd27c6cSPeter Brune ierr = PetscObjectReference((PetscObject)snes->vec_sol);CHKERRQ(ierr); 272*0dd27c6cSPeter Brune fas->smoothu->vec_sol_update = snes->vec_sol_update; 273*0dd27c6cSPeter Brune ierr = PetscObjectReference((PetscObject)snes->vec_sol_update);CHKERRQ(ierr); 274*0dd27c6cSPeter Brune fas->smoothu->vec_func = snes->vec_func; 275*0dd27c6cSPeter Brune ierr = PetscObjectReference((PetscObject)snes->vec_func);CHKERRQ(ierr); 276*0dd27c6cSPeter Brune 277*0dd27c6cSPeter Brune if (fas->eventsmoothsetup) {ierr = PetscLogEventBegin(fas->eventsmoothsetup,0,0,0,0);CHKERRQ(ierr);} 278*0dd27c6cSPeter Brune ierr = SNESSetUp(fas->smoothu);CHKERRQ(ierr); 279*0dd27c6cSPeter Brune if (fas->eventsmoothsetup) {ierr = PetscLogEventEnd(fas->eventsmoothsetup,0,0,0,0);CHKERRQ(ierr);} 280*0dd27c6cSPeter Brune 281534ebe21SPeter Brune } 282d06165b7SPeter Brune 283ab8d36c9SPeter Brune if (next) { 28479d9a41aSPeter Brune /* gotta set up the solution vector for this to work */ 285ab8d36c9SPeter Brune if (!next->vec_sol) {ierr = SNESFASCreateCoarseVec(snes,&next->vec_sol);CHKERRQ(ierr);} 286ab8d36c9SPeter Brune if (!next->vec_rhs) {ierr = SNESFASCreateCoarseVec(snes,&next->vec_rhs);CHKERRQ(ierr);} 2877fce8c19SPeter Brune ierr = PetscObjectCopyFortranFunctionPointers((PetscObject)snes, (PetscObject)next);CHKERRQ(ierr); 288f89ba88eSPeter Brune ierr = SNESGetSNESLineSearch(snes,&linesearch);CHKERRQ(ierr); 289f89ba88eSPeter Brune ierr = SNESGetSNESLineSearch(fas->next,&slinesearch);CHKERRQ(ierr); 2906b2b7091SBarry Smith ierr = SNESLineSearchGetPreCheck(linesearch,&precheck,&lsprectx);CHKERRQ(ierr); 2916b2b7091SBarry Smith ierr = SNESLineSearchGetPostCheck(linesearch,&postcheck,&lspostctx);CHKERRQ(ierr); 2926b2b7091SBarry Smith ierr = SNESLineSearchSetPreCheck(slinesearch,precheck,lsprectx);CHKERRQ(ierr); 2936b2b7091SBarry Smith ierr = SNESLineSearchSetPostCheck(slinesearch,postcheck,lspostctx);CHKERRQ(ierr); 294f89ba88eSPeter Brune ierr = PetscObjectCopyFortranFunctionPointers((PetscObject)linesearch, (PetscObject)slinesearch);CHKERRQ(ierr); 295ab8d36c9SPeter Brune ierr = SNESSetUp(next);CHKERRQ(ierr); 29679d9a41aSPeter Brune } 2976273346dSPeter Brune /* setup FAS work vectors */ 2986273346dSPeter Brune if (fas->galerkin) { 2996273346dSPeter Brune ierr = VecDuplicate(snes->vec_sol, &fas->Xg);CHKERRQ(ierr); 3006273346dSPeter Brune ierr = VecDuplicate(snes->vec_sol, &fas->Fg);CHKERRQ(ierr); 3016273346dSPeter Brune } 302421d9b32SPeter Brune PetscFunctionReturn(0); 303421d9b32SPeter Brune } 304421d9b32SPeter Brune 305421d9b32SPeter Brune #undef __FUNCT__ 306421d9b32SPeter Brune #define __FUNCT__ "SNESSetFromOptions_FAS" 307421d9b32SPeter Brune PetscErrorCode SNESSetFromOptions_FAS(SNES snes) 308421d9b32SPeter Brune { 309ee78dd50SPeter Brune SNES_FAS *fas = (SNES_FAS *) snes->data; 310ee78dd50SPeter Brune PetscInt levels = 1; 3114d26bfa5SPeter Brune PetscBool flg = PETSC_FALSE, upflg = PETSC_FALSE, downflg = PETSC_FALSE, monflg = PETSC_FALSE, galerkinflg = PETSC_FALSE; 312421d9b32SPeter Brune PetscErrorCode ierr; 313ee78dd50SPeter Brune char monfilename[PETSC_MAX_PATH_LEN]; 31407144faaSPeter Brune SNESFASType fastype; 315fde0ff24SPeter Brune const char *optionsprefix; 316f1c6b773SPeter Brune SNESLineSearch linesearch; 31766585501SPeter Brune PetscInt m, n_up, n_down; 318ab8d36c9SPeter Brune SNES next; 319ab8d36c9SPeter Brune PetscBool isFine; 320421d9b32SPeter Brune 321421d9b32SPeter Brune PetscFunctionBegin; 322ab8d36c9SPeter Brune ierr = SNESFASCycleIsFine(snes, &isFine);CHKERRQ(ierr); 323c90fad12SPeter Brune ierr = PetscOptionsHead("SNESFAS Options-----------------------------------");CHKERRQ(ierr); 324ee78dd50SPeter Brune 325ab8d36c9SPeter Brune /* number of levels -- only process most options on the finest level */ 326ab8d36c9SPeter Brune if (isFine) { 327ee78dd50SPeter Brune ierr = PetscOptionsInt("-snes_fas_levels", "Number of Levels", "SNESFASSetLevels", levels, &levels, &flg);CHKERRQ(ierr); 328c732cbdbSBarry Smith if (!flg && snes->dm) { 329c732cbdbSBarry Smith ierr = DMGetRefineLevel(snes->dm,&levels);CHKERRQ(ierr); 330c732cbdbSBarry Smith levels++; 331d1adcc6fSPeter Brune fas->usedmfornumberoflevels = PETSC_TRUE; 332c732cbdbSBarry Smith } 333ee78dd50SPeter Brune ierr = SNESFASSetLevels(snes, levels, PETSC_NULL);CHKERRQ(ierr); 33407144faaSPeter Brune fastype = fas->fastype; 33507144faaSPeter Brune ierr = PetscOptionsEnum("-snes_fas_type","FAS correction type","SNESFASSetType",SNESFASTypes,(PetscEnum)fastype,(PetscEnum*)&fastype,&flg);CHKERRQ(ierr); 33607144faaSPeter Brune if (flg) { 33707144faaSPeter Brune ierr = SNESFASSetType(snes, fastype);CHKERRQ(ierr); 33807144faaSPeter Brune } 339ee78dd50SPeter Brune 340fde0ff24SPeter Brune ierr = SNESGetOptionsPrefix(snes, &optionsprefix);CHKERRQ(ierr); 341ab8d36c9SPeter Brune ierr = PetscOptionsInt("-snes_fas_cycles","Number of cycles","SNESFASSetCycles",fas->n_cycles,&m,&flg);CHKERRQ(ierr); 342ab8d36c9SPeter Brune if (flg) { 343ab8d36c9SPeter Brune ierr = SNESFASSetCycles(snes, m);CHKERRQ(ierr); 344fde0ff24SPeter Brune } 345fde0ff24SPeter Brune 346ab8d36c9SPeter Brune ierr = PetscOptionsBool("-snes_fas_galerkin", "Form coarse problems with Galerkin","SNESFASSetGalerkin",fas->galerkin,&galerkinflg,&flg);CHKERRQ(ierr); 347ab8d36c9SPeter Brune if (flg) { 348ab8d36c9SPeter Brune ierr = SNESFASSetGalerkin(snes, galerkinflg);CHKERRQ(ierr); 349ab8d36c9SPeter Brune } 350ee78dd50SPeter Brune 35166585501SPeter Brune ierr = PetscOptionsInt("-snes_fas_smoothup","Number of post-smoothing steps","SNESFASSetNumberSmoothUp",fas->max_up_it,&n_up,&upflg);CHKERRQ(ierr); 352162d76ddSPeter Brune 35366585501SPeter Brune ierr = PetscOptionsInt("-snes_fas_smoothdown","Number of pre-smoothing steps","SNESFASSetNumberSmoothDown",fas->max_down_it,&n_down,&downflg);CHKERRQ(ierr); 354162d76ddSPeter Brune 355c8c899caSPeter Brune ierr = PetscOptionsString("-snes_fas_monitor","Monitor FAS progress","SNESFASSetMonitor","stdout",monfilename,PETSC_MAX_PATH_LEN,&monflg);CHKERRQ(ierr); 356c8c899caSPeter Brune if (monflg) ierr = SNESFASSetMonitor(snes, PETSC_TRUE);CHKERRQ(ierr); 357*0dd27c6cSPeter Brune 358*0dd27c6cSPeter Brune flg = PETSC_FALSE; 359*0dd27c6cSPeter Brune monflg = PETSC_TRUE; 360*0dd27c6cSPeter Brune ierr = PetscOptionsBool("-snes_fas_log","Log times for each FAS level","SNESFASSetLog",monflg,&monflg,&flg);CHKERRQ(ierr); 361*0dd27c6cSPeter Brune if (flg){ierr = SNESFASSetLog(snes,monflg);CHKERRQ(ierr);} 362ab8d36c9SPeter Brune } 363ee78dd50SPeter Brune 364421d9b32SPeter Brune ierr = PetscOptionsTail();CHKERRQ(ierr); 3658cc86e31SPeter Brune /* setup from the determined types if there is no pointwise procedure or smoother defined */ 366162d76ddSPeter Brune if (upflg) { 36766585501SPeter Brune ierr = SNESFASSetNumberSmoothUp(snes,n_up);CHKERRQ(ierr); 368162d76ddSPeter Brune } 369162d76ddSPeter Brune if (downflg) { 37066585501SPeter Brune ierr = SNESFASSetNumberSmoothDown(snes,n_down);CHKERRQ(ierr); 371162d76ddSPeter Brune } 372eff52c0eSPeter Brune 3739e764e56SPeter Brune /* set up the default line search for coarse grid corrections */ 3749e764e56SPeter Brune if (fas->fastype == SNES_FAS_ADDITIVE) { 3759e764e56SPeter Brune if (!snes->linesearch) { 376f1c6b773SPeter Brune ierr = SNESGetSNESLineSearch(snes, &linesearch);CHKERRQ(ierr); 3771a4f838cSPeter Brune ierr = SNESLineSearchSetType(linesearch, SNESLINESEARCHL2);CHKERRQ(ierr); 3789e764e56SPeter Brune } 3799e764e56SPeter Brune } 3809e764e56SPeter Brune 381ab8d36c9SPeter Brune ierr = SNESFASCycleGetCorrection(snes, &next);CHKERRQ(ierr); 382ee78dd50SPeter Brune /* recursive option setting for the smoothers */ 383ab8d36c9SPeter Brune if (next) {ierr = SNESSetFromOptions(next);CHKERRQ(ierr);} 384421d9b32SPeter Brune PetscFunctionReturn(0); 385421d9b32SPeter Brune } 386421d9b32SPeter Brune 387421d9b32SPeter Brune #undef __FUNCT__ 388421d9b32SPeter Brune #define __FUNCT__ "SNESView_FAS" 389421d9b32SPeter Brune PetscErrorCode SNESView_FAS(SNES snes, PetscViewer viewer) 390421d9b32SPeter Brune { 391421d9b32SPeter Brune SNES_FAS *fas = (SNES_FAS *) snes->data; 392656ede7eSPeter Brune PetscBool isFine,iascii,isdraw; 393ab8d36c9SPeter Brune PetscInt i; 394421d9b32SPeter Brune PetscErrorCode ierr; 395ab8d36c9SPeter Brune SNES smoothu, smoothd, levelsnes; 396421d9b32SPeter Brune 397421d9b32SPeter Brune PetscFunctionBegin; 398ab8d36c9SPeter Brune ierr = SNESFASCycleIsFine(snes, &isFine);CHKERRQ(ierr); 399ab8d36c9SPeter Brune if (isFine) { 400251f4c67SDmitry Karpeev ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr); 401656ede7eSPeter Brune ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERDRAW,&isdraw);CHKERRQ(ierr); 402421d9b32SPeter Brune if (iascii) { 403ab8d36c9SPeter Brune ierr = PetscViewerASCIIPrintf(viewer, "FAS: type is %s, levels=%D, cycles=%D\n", SNESFASTypes[fas->fastype], fas->levels, fas->n_cycles);CHKERRQ(ierr); 404ab8d36c9SPeter Brune if (fas->galerkin) { 405ab8d36c9SPeter Brune ierr = PetscViewerASCIIPrintf(viewer," Using Galerkin computed coarse grid function evaluation\n");CHKERRQ(ierr); 406421d9b32SPeter Brune } else { 407ab8d36c9SPeter Brune ierr = PetscViewerASCIIPrintf(viewer," Not using Galerkin computed coarse grid function evaluation\n");CHKERRQ(ierr); 408421d9b32SPeter Brune } 409ab8d36c9SPeter Brune for (i=0; i<fas->levels; i++) { 410ab8d36c9SPeter Brune ierr = SNESFASGetCycleSNES(snes, i, &levelsnes);CHKERRQ(ierr); 411ab8d36c9SPeter Brune ierr = SNESFASCycleGetSmootherUp(levelsnes, &smoothu);CHKERRQ(ierr); 412ab8d36c9SPeter Brune ierr = SNESFASCycleGetSmootherDown(levelsnes, &smoothd);CHKERRQ(ierr); 413ab8d36c9SPeter Brune if (!i) { 414ab8d36c9SPeter Brune ierr = PetscViewerASCIIPrintf(viewer,"Coarse grid solver -- level %D -------------------------------\n",i);CHKERRQ(ierr); 415421d9b32SPeter Brune } else { 416ab8d36c9SPeter Brune ierr = PetscViewerASCIIPrintf(viewer,"Down solver (pre-smoother) on level %D -------------------------------\n",i);CHKERRQ(ierr); 417421d9b32SPeter Brune } 418ab8d36c9SPeter Brune ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); 419ab8d36c9SPeter Brune ierr = SNESView(smoothd,viewer);CHKERRQ(ierr); 420ab8d36c9SPeter Brune ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); 421ab8d36c9SPeter Brune if (i && (smoothd == smoothu)) { 422ab8d36c9SPeter Brune ierr = PetscViewerASCIIPrintf(viewer,"Up solver (post-smoother) same as down solver (pre-smoother)\n");CHKERRQ(ierr); 423ab8d36c9SPeter Brune } else if (i) { 424ab8d36c9SPeter Brune ierr = PetscViewerASCIIPrintf(viewer,"Up solver (post-smoother) on level %D -------------------------------\n",i);CHKERRQ(ierr); 425ab8d36c9SPeter Brune ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); 426ab8d36c9SPeter Brune ierr = SNESView(smoothu,viewer);CHKERRQ(ierr); 427ab8d36c9SPeter Brune ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); 428ab8d36c9SPeter Brune } 429ab8d36c9SPeter Brune } 430656ede7eSPeter Brune } else if (isdraw) { 431656ede7eSPeter Brune PetscDraw draw; 432b4375e8dSPeter Brune PetscReal x,w,y,bottom,th,wth; 433656ede7eSPeter Brune SNES_FAS *curfas = fas; 434656ede7eSPeter Brune ierr = PetscViewerDrawGetDraw(viewer,0,&draw);CHKERRQ(ierr); 435656ede7eSPeter Brune ierr = PetscDrawGetCurrentPoint(draw,&x,&y);CHKERRQ(ierr); 436656ede7eSPeter Brune ierr = PetscDrawStringGetSize(draw,&wth,&th);CHKERRQ(ierr); 437656ede7eSPeter Brune bottom = y - th; 438656ede7eSPeter Brune while (curfas) { 439b4375e8dSPeter Brune if (!curfas->smoothu) { 440656ede7eSPeter Brune ierr = PetscDrawPushCurrentPoint(draw,x,bottom);CHKERRQ(ierr); 441656ede7eSPeter Brune if (curfas->smoothd) ierr = SNESView(curfas->smoothd,viewer);CHKERRQ(ierr); 442656ede7eSPeter Brune ierr = PetscDrawPopCurrentPoint(draw);CHKERRQ(ierr); 443b4375e8dSPeter Brune } else { 444b4375e8dSPeter Brune w = 0.5*PetscMin(1.0-x,x); 445b4375e8dSPeter Brune ierr = PetscDrawPushCurrentPoint(draw,x-w,bottom);CHKERRQ(ierr); 446b4375e8dSPeter Brune if (curfas->smoothd) ierr = SNESView(curfas->smoothd,viewer);CHKERRQ(ierr); 447b4375e8dSPeter Brune ierr = PetscDrawPopCurrentPoint(draw);CHKERRQ(ierr); 448b4375e8dSPeter Brune ierr = PetscDrawPushCurrentPoint(draw,x+w,bottom);CHKERRQ(ierr); 449b4375e8dSPeter Brune if (curfas->smoothu) ierr = SNESView(curfas->smoothu,viewer);CHKERRQ(ierr); 450b4375e8dSPeter Brune ierr = PetscDrawPopCurrentPoint(draw);CHKERRQ(ierr); 451b4375e8dSPeter Brune } 452656ede7eSPeter Brune /* this is totally bogus but we have no way of knowing how low the previous one was draw to */ 453656ede7eSPeter Brune bottom -= 5*th; 454656ede7eSPeter Brune if (curfas->next) { 455656ede7eSPeter Brune curfas = (SNES_FAS*)curfas->next->data; 456656ede7eSPeter Brune } else { 457656ede7eSPeter Brune curfas = PETSC_NULL; 458656ede7eSPeter Brune } 459656ede7eSPeter Brune } 460421d9b32SPeter Brune } else { 461421d9b32SPeter Brune SETERRQ1(((PetscObject)snes)->comm,PETSC_ERR_SUP,"Viewer type %s not supported for SNESFAS",((PetscObject)viewer)->type_name); 462421d9b32SPeter Brune } 463ab8d36c9SPeter Brune } 464421d9b32SPeter Brune PetscFunctionReturn(0); 465421d9b32SPeter Brune } 466421d9b32SPeter Brune 467421d9b32SPeter Brune #undef __FUNCT__ 46891f99d7cSPeter Brune #define __FUNCT__ "SNESFASDownSmooth_Private" 46939bd7f45SPeter Brune /* 47039bd7f45SPeter Brune Defines the action of the downsmoother 47139bd7f45SPeter Brune */ 47291f99d7cSPeter Brune PetscErrorCode SNESFASDownSmooth_Private(SNES snes, Vec B, Vec X, Vec F, PetscReal *fnorm) 473b9c2fdf1SPeter Brune { 47439bd7f45SPeter Brune PetscErrorCode ierr = 0; 475742fe5e2SPeter Brune SNESConvergedReason reason; 476ab8d36c9SPeter Brune Vec FPC; 477ab8d36c9SPeter Brune SNES smoothd; 478*0dd27c6cSPeter Brune SNES_FAS *fas = (SNES_FAS *) snes->data; 4796e111a19SKarl Rupp 480421d9b32SPeter Brune PetscFunctionBegin; 481ab8d36c9SPeter Brune ierr = SNESFASCycleGetSmootherDown(snes, &smoothd);CHKERRQ(ierr); 482e4ed7901SPeter Brune ierr = SNESSetInitialFunction(smoothd, F);CHKERRQ(ierr); 483e4ed7901SPeter Brune ierr = SNESSetInitialFunctionNorm(smoothd, *fnorm);CHKERRQ(ierr); 484*0dd27c6cSPeter Brune if (fas->eventsmoothsolve) {ierr = PetscLogEventBegin(fas->eventsmoothsolve,0,0,0,0);CHKERRQ(ierr);} 485ab8d36c9SPeter Brune ierr = SNESSolve(smoothd, B, X);CHKERRQ(ierr); 486*0dd27c6cSPeter Brune if (fas->eventsmoothsolve) {ierr = PetscLogEventEnd(fas->eventsmoothsolve,0,0,0,0);CHKERRQ(ierr);} 487742fe5e2SPeter Brune /* check convergence reason for the smoother */ 488ab8d36c9SPeter Brune ierr = SNESGetConvergedReason(smoothd,&reason);CHKERRQ(ierr); 489e70c42e5SPeter Brune if (reason < 0 && !(reason == SNES_DIVERGED_MAX_IT || reason == SNES_DIVERGED_LOCAL_MIN)) { 490742fe5e2SPeter Brune snes->reason = SNES_DIVERGED_INNER; 491742fe5e2SPeter Brune PetscFunctionReturn(0); 492742fe5e2SPeter Brune } 493ab8d36c9SPeter Brune ierr = SNESGetFunction(smoothd, &FPC, PETSC_NULL, PETSC_NULL);CHKERRQ(ierr); 4944b32a720SPeter Brune ierr = VecCopy(FPC, F);CHKERRQ(ierr); 495b9c2fdf1SPeter Brune ierr = SNESGetFunctionNorm(smoothd, fnorm);CHKERRQ(ierr); 49639bd7f45SPeter Brune PetscFunctionReturn(0); 49739bd7f45SPeter Brune } 49839bd7f45SPeter Brune 49939bd7f45SPeter Brune 50039bd7f45SPeter Brune #undef __FUNCT__ 50191f99d7cSPeter Brune #define __FUNCT__ "SNESFASUpSmooth_Private" 50239bd7f45SPeter Brune /* 50307144faaSPeter Brune Defines the action of the upsmoother 50439bd7f45SPeter Brune */ 5050adebc6cSBarry Smith PetscErrorCode SNESFASUpSmooth_Private (SNES snes, Vec B, Vec X, Vec F, PetscReal *fnorm) 5060adebc6cSBarry Smith { 50739bd7f45SPeter Brune PetscErrorCode ierr = 0; 50839bd7f45SPeter Brune SNESConvergedReason reason; 509ab8d36c9SPeter Brune Vec FPC; 510ab8d36c9SPeter Brune SNES smoothu; 511*0dd27c6cSPeter Brune SNES_FAS *fas = (SNES_FAS *) snes->data; 512ab8d36c9SPeter Brune 5136e111a19SKarl Rupp PetscFunctionBegin; 514ab8d36c9SPeter Brune ierr = SNESFASCycleGetSmootherUp(snes, &smoothu);CHKERRQ(ierr); 515*0dd27c6cSPeter Brune if (fas->eventsmoothsolve) {ierr = PetscLogEventBegin(fas->eventsmoothsolve,0,0,0,0);CHKERRQ(ierr);} 516ab8d36c9SPeter Brune ierr = SNESSolve(smoothu, B, X);CHKERRQ(ierr); 517*0dd27c6cSPeter Brune if (fas->eventsmoothsolve) {ierr = PetscLogEventEnd(fas->eventsmoothsolve,0,0,0,0);CHKERRQ(ierr);} 51839bd7f45SPeter Brune /* check convergence reason for the smoother */ 519ab8d36c9SPeter Brune ierr = SNESGetConvergedReason(smoothu,&reason);CHKERRQ(ierr); 52039bd7f45SPeter Brune if (reason < 0 && reason != SNES_DIVERGED_MAX_IT) { 52139bd7f45SPeter Brune snes->reason = SNES_DIVERGED_INNER; 52239bd7f45SPeter Brune PetscFunctionReturn(0); 52339bd7f45SPeter Brune } 524ab8d36c9SPeter Brune ierr = SNESGetFunction(smoothu, &FPC, PETSC_NULL, PETSC_NULL);CHKERRQ(ierr); 5254b32a720SPeter Brune ierr = VecCopy(FPC, F);CHKERRQ(ierr); 526b9c2fdf1SPeter Brune ierr = SNESGetFunctionNorm(smoothu, fnorm);CHKERRQ(ierr); 52739bd7f45SPeter Brune PetscFunctionReturn(0); 52839bd7f45SPeter Brune } 52939bd7f45SPeter Brune 53039bd7f45SPeter Brune #undef __FUNCT__ 531938e4a01SJed Brown #define __FUNCT__ "SNESFASCreateCoarseVec" 532938e4a01SJed Brown /*@ 533938e4a01SJed Brown SNESFASCreateCoarseVec - create Vec corresponding to a state vector on one level coarser than current level 534938e4a01SJed Brown 535938e4a01SJed Brown Collective 536938e4a01SJed Brown 537938e4a01SJed Brown Input Arguments: 538938e4a01SJed Brown . snes - SNESFAS 539938e4a01SJed Brown 540938e4a01SJed Brown Output Arguments: 541938e4a01SJed Brown . Xcoarse - vector on level one coarser than snes 542938e4a01SJed Brown 543938e4a01SJed Brown Level: developer 544938e4a01SJed Brown 545938e4a01SJed Brown .seealso: SNESFASSetRestriction(), SNESFASRestrict() 546938e4a01SJed Brown @*/ 547938e4a01SJed Brown PetscErrorCode SNESFASCreateCoarseVec(SNES snes,Vec *Xcoarse) 548938e4a01SJed Brown { 549938e4a01SJed Brown PetscErrorCode ierr; 550938e4a01SJed Brown SNES_FAS *fas = (SNES_FAS*)snes->data; 551938e4a01SJed Brown 552938e4a01SJed Brown PetscFunctionBegin; 553938e4a01SJed Brown if (fas->rscale) {ierr = VecDuplicate(fas->rscale,Xcoarse);CHKERRQ(ierr);} 554938e4a01SJed Brown else if (fas->inject) {ierr = MatGetVecs(fas->inject,Xcoarse,PETSC_NULL);CHKERRQ(ierr);} 555938e4a01SJed Brown else SETERRQ(((PetscObject)snes)->comm,PETSC_ERR_ARG_WRONGSTATE,"Must set restriction or injection");CHKERRQ(ierr); 556938e4a01SJed Brown PetscFunctionReturn(0); 557938e4a01SJed Brown } 558938e4a01SJed Brown 559e9923e8dSJed Brown #undef __FUNCT__ 560e9923e8dSJed Brown #define __FUNCT__ "SNESFASRestrict" 561e9923e8dSJed Brown /*@ 562e9923e8dSJed Brown SNESFASRestrict - restrict a Vec to the next coarser level 563e9923e8dSJed Brown 564e9923e8dSJed Brown Collective 565e9923e8dSJed Brown 566e9923e8dSJed Brown Input Arguments: 567e9923e8dSJed Brown + fine - SNES from which to restrict 568e9923e8dSJed Brown - Xfine - vector to restrict 569e9923e8dSJed Brown 570e9923e8dSJed Brown Output Arguments: 571e9923e8dSJed Brown . Xcoarse - result of restriction 572e9923e8dSJed Brown 573e9923e8dSJed Brown Level: developer 574e9923e8dSJed Brown 575e9923e8dSJed Brown .seealso: SNESFASSetRestriction(), SNESFASSetInjection() 576e9923e8dSJed Brown @*/ 577e9923e8dSJed Brown PetscErrorCode SNESFASRestrict(SNES fine,Vec Xfine,Vec Xcoarse) 578e9923e8dSJed Brown { 579e9923e8dSJed Brown PetscErrorCode ierr; 580e9923e8dSJed Brown SNES_FAS *fas = (SNES_FAS*)fine->data; 581e9923e8dSJed Brown 582e9923e8dSJed Brown PetscFunctionBegin; 583e9923e8dSJed Brown PetscValidHeaderSpecific(fine,SNES_CLASSID,1); 584e9923e8dSJed Brown PetscValidHeaderSpecific(Xfine,VEC_CLASSID,2); 585e9923e8dSJed Brown PetscValidHeaderSpecific(Xcoarse,VEC_CLASSID,3); 586e9923e8dSJed Brown if (fas->inject) { 587e9923e8dSJed Brown ierr = MatRestrict(fas->inject,Xfine,Xcoarse);CHKERRQ(ierr); 588e9923e8dSJed Brown } else { 589e9923e8dSJed Brown ierr = MatRestrict(fas->restrct,Xfine,Xcoarse);CHKERRQ(ierr); 590e9923e8dSJed Brown ierr = VecPointwiseMult(Xcoarse,fas->rscale,Xcoarse);CHKERRQ(ierr); 591e9923e8dSJed Brown } 592e9923e8dSJed Brown PetscFunctionReturn(0); 593e9923e8dSJed Brown } 594e9923e8dSJed Brown 595e9923e8dSJed Brown #undef __FUNCT__ 5968c40d5fbSBarry Smith #define __FUNCT__ "SNESFASCoarseCorrection" 59739bd7f45SPeter Brune /* 59839bd7f45SPeter Brune 59939bd7f45SPeter Brune Performs the FAS coarse correction as: 60039bd7f45SPeter Brune 60139bd7f45SPeter Brune fine problem: F(x) = 0 60239bd7f45SPeter Brune coarse problem: F^c(x) = b^c 60339bd7f45SPeter Brune 60439bd7f45SPeter Brune b^c = F^c(I^c_fx^f - I^c_fF(x)) 60539bd7f45SPeter Brune 60639bd7f45SPeter Brune */ 6070adebc6cSBarry Smith PetscErrorCode SNESFASCoarseCorrection(SNES snes, Vec X, Vec F, Vec X_new) 6080adebc6cSBarry Smith { 60939bd7f45SPeter Brune PetscErrorCode ierr; 61039bd7f45SPeter Brune Vec X_c, Xo_c, F_c, B_c; 61139bd7f45SPeter Brune SNESConvergedReason reason; 612ab8d36c9SPeter Brune SNES next; 613ab8d36c9SPeter Brune Mat restrct, interpolate; 614*0dd27c6cSPeter Brune SNES_FAS *fasc; 61539bd7f45SPeter Brune PetscFunctionBegin; 616ab8d36c9SPeter Brune ierr = SNESFASCycleGetCorrection(snes, &next);CHKERRQ(ierr); 617ab8d36c9SPeter Brune if (next) { 618*0dd27c6cSPeter Brune fasc = (SNES_FAS *)next->data; 619*0dd27c6cSPeter Brune 620ab8d36c9SPeter Brune ierr = SNESFASCycleGetRestriction(snes, &restrct);CHKERRQ(ierr); 621ab8d36c9SPeter Brune ierr = SNESFASCycleGetInterpolation(snes, &interpolate);CHKERRQ(ierr); 622ab8d36c9SPeter Brune 623ab8d36c9SPeter Brune X_c = next->vec_sol; 624ab8d36c9SPeter Brune Xo_c = next->work[0]; 625ab8d36c9SPeter Brune F_c = next->vec_func; 626ab8d36c9SPeter Brune B_c = next->vec_rhs; 627efe1f98aSPeter Brune 628*0dd27c6cSPeter Brune if (fasc->eventinterprestrict) {ierr = PetscLogEventBegin(fasc->eventinterprestrict,0,0,0,0);CHKERRQ(ierr);} 629938e4a01SJed Brown ierr = SNESFASRestrict(snes,X,Xo_c);CHKERRQ(ierr); 630293a7e31SPeter Brune /* restrict the defect */ 631ab8d36c9SPeter Brune ierr = MatRestrict(restrct, F, B_c);CHKERRQ(ierr); 632*0dd27c6cSPeter Brune if (fasc->eventinterprestrict) {ierr = PetscLogEventEnd(fasc->eventinterprestrict,0,0,0,0);CHKERRQ(ierr);} 633*0dd27c6cSPeter Brune 634*0dd27c6cSPeter Brune if (fasc->eventresidual) {ierr = PetscLogEventBegin(fasc->eventresidual,0,0,0,0);CHKERRQ(ierr);} 635ab8d36c9SPeter Brune ierr = SNESComputeFunction(next, Xo_c, F_c);CHKERRQ(ierr); 636*0dd27c6cSPeter Brune if (fasc->eventresidual) {ierr = PetscLogEventEnd(fasc->eventresidual,0,0,0,0);CHKERRQ(ierr);} 637*0dd27c6cSPeter Brune 638*0dd27c6cSPeter Brune /* solve the coarse problem corresponding to F^c(x^c) = b^c = F^c(Rx) - R(F(x) - b) */ 639e4ed7901SPeter Brune ierr = VecCopy(B_c, X_c);CHKERRQ(ierr); 640b9c2fdf1SPeter Brune ierr = VecCopy(F_c, B_c);CHKERRQ(ierr); 641e4ed7901SPeter Brune ierr = VecCopy(X_c, F_c);CHKERRQ(ierr); 642ee78dd50SPeter Brune /* set initial guess of the coarse problem to the projected fine solution */ 643ee78dd50SPeter Brune ierr = VecCopy(Xo_c, X_c);CHKERRQ(ierr); 644c90fad12SPeter Brune 645c90fad12SPeter Brune /* recurse to the next level */ 646e4ed7901SPeter Brune ierr = SNESSetInitialFunction(next, F_c);CHKERRQ(ierr); 647ab8d36c9SPeter Brune ierr = SNESSolve(next, B_c, X_c);CHKERRQ(ierr); 648ab8d36c9SPeter Brune ierr = SNESGetConvergedReason(next,&reason);CHKERRQ(ierr); 649742fe5e2SPeter Brune if (reason < 0 && reason != SNES_DIVERGED_MAX_IT) { 650742fe5e2SPeter Brune snes->reason = SNES_DIVERGED_INNER; 651742fe5e2SPeter Brune PetscFunctionReturn(0); 652742fe5e2SPeter Brune } 653fa9694d7SPeter Brune /* correct as x <- x + I(x^c - Rx)*/ 654fa9694d7SPeter Brune ierr = VecAXPY(X_c, -1.0, Xo_c);CHKERRQ(ierr); 655*0dd27c6cSPeter Brune 656*0dd27c6cSPeter Brune if (fasc->eventinterprestrict) {ierr = PetscLogEventBegin(fasc->eventinterprestrict,0,0,0,0);CHKERRQ(ierr);} 657ab8d36c9SPeter Brune ierr = MatInterpolateAdd(interpolate, X_c, X, X_new);CHKERRQ(ierr); 658*0dd27c6cSPeter Brune if (fasc->eventinterprestrict) {ierr = PetscLogEventEnd(fasc->eventinterprestrict,0,0,0,0);CHKERRQ(ierr);} 659293a7e31SPeter Brune } 66039bd7f45SPeter Brune PetscFunctionReturn(0); 66139bd7f45SPeter Brune } 66239bd7f45SPeter Brune 66339bd7f45SPeter Brune #undef __FUNCT__ 6642cf9d1e8SPeter Brune #define __FUNCT__ "SNESFASCycle_Additive" 66539bd7f45SPeter Brune /* 66639bd7f45SPeter Brune 66739bd7f45SPeter Brune The additive cycle looks like: 66839bd7f45SPeter Brune 66907144faaSPeter Brune xhat = x 67007144faaSPeter Brune xhat = dS(x, b) 67107144faaSPeter Brune x = coarsecorrection(xhat, b_d) 67207144faaSPeter Brune x = x + nu*(xhat - x); 67339bd7f45SPeter Brune (optional) x = uS(x, b) 67439bd7f45SPeter Brune 67539bd7f45SPeter Brune With the coarse RHS (defect correction) as below. 67639bd7f45SPeter Brune 67739bd7f45SPeter Brune */ 6780adebc6cSBarry Smith PetscErrorCode SNESFASCycle_Additive(SNES snes, Vec X) 6790adebc6cSBarry Smith { 68007144faaSPeter Brune Vec F, B, Xhat; 68122c1e704SPeter Brune Vec X_c, Xo_c, F_c, B_c; 68239bd7f45SPeter Brune PetscErrorCode ierr; 68307144faaSPeter Brune SNESConvergedReason reason; 68422c1e704SPeter Brune PetscReal xnorm, fnorm, ynorm; 68522c1e704SPeter Brune PetscBool lssuccess; 686ab8d36c9SPeter Brune SNES next; 687ab8d36c9SPeter Brune Mat restrct, interpolate; 688*0dd27c6cSPeter Brune SNES_FAS *fas = (SNES_FAS *)snes->data,*fasc; 689*0dd27c6cSPeter Brune 69039bd7f45SPeter Brune PetscFunctionBegin; 691ab8d36c9SPeter Brune ierr = SNESFASCycleGetCorrection(snes, &next);CHKERRQ(ierr); 69239bd7f45SPeter Brune F = snes->vec_func; 69339bd7f45SPeter Brune B = snes->vec_rhs; 694e7f468e7SPeter Brune Xhat = snes->work[1]; 69507144faaSPeter Brune ierr = VecCopy(X, Xhat);CHKERRQ(ierr); 69607144faaSPeter Brune /* recurse first */ 697ab8d36c9SPeter Brune if (next) { 698*0dd27c6cSPeter Brune fasc = (SNES_FAS*)next->data; 699ab8d36c9SPeter Brune ierr = SNESFASCycleGetRestriction(snes, &restrct);CHKERRQ(ierr); 700ab8d36c9SPeter Brune ierr = SNESFASCycleGetInterpolation(snes, &interpolate);CHKERRQ(ierr); 701*0dd27c6cSPeter Brune if (fas->eventresidual) {ierr = PetscLogEventBegin(fas->eventresidual,0,0,0,0);CHKERRQ(ierr);} 70207144faaSPeter Brune ierr = SNESComputeFunction(snes, Xhat, F);CHKERRQ(ierr); 703*0dd27c6cSPeter Brune if (fas->eventresidual) {ierr = PetscLogEventEnd(fas->eventresidual,0,0,0,0);CHKERRQ(ierr);} 704c2a02606SPeter Brune ierr = VecNorm(F, NORM_2, &fnorm);CHKERRQ(ierr); 705ab8d36c9SPeter Brune X_c = next->vec_sol; 706ab8d36c9SPeter Brune Xo_c = next->work[0]; 707ab8d36c9SPeter Brune F_c = next->vec_func; 708ab8d36c9SPeter Brune B_c = next->vec_rhs; 70939bd7f45SPeter Brune 710938e4a01SJed Brown ierr = SNESFASRestrict(snes,Xhat,Xo_c);CHKERRQ(ierr); 71107144faaSPeter Brune /* restrict the defect */ 712ab8d36c9SPeter Brune ierr = MatRestrict(restrct, F, B_c);CHKERRQ(ierr); 71307144faaSPeter Brune 71407144faaSPeter Brune /* solve the coarse problem corresponding to F^c(x^c) = b^c = Rb + F^c(Rx) - RF(x) */ 715*0dd27c6cSPeter Brune if (fasc->eventresidual) {ierr = PetscLogEventBegin(fasc->eventresidual,0,0,0,0);CHKERRQ(ierr);} 716ab8d36c9SPeter Brune ierr = SNESComputeFunction(next, Xo_c, F_c);CHKERRQ(ierr); 717*0dd27c6cSPeter Brune if (fasc->eventresidual) {ierr = PetscLogEventEnd(fasc->eventresidual,0,0,0,0);CHKERRQ(ierr);} 718e4ed7901SPeter Brune ierr = VecCopy(B_c, X_c);CHKERRQ(ierr); 719b9c2fdf1SPeter Brune ierr = VecCopy(F_c, B_c);CHKERRQ(ierr); 720e4ed7901SPeter Brune ierr = VecCopy(X_c, F_c);CHKERRQ(ierr); 72107144faaSPeter Brune /* set initial guess of the coarse problem to the projected fine solution */ 72207144faaSPeter Brune ierr = VecCopy(Xo_c, X_c);CHKERRQ(ierr); 72307144faaSPeter Brune 72407144faaSPeter Brune /* recurse */ 725e4ed7901SPeter Brune ierr = SNESSetInitialFunction(next, F_c);CHKERRQ(ierr); 726ab8d36c9SPeter Brune ierr = SNESSolve(next, B_c, X_c);CHKERRQ(ierr); 72707144faaSPeter Brune 72807144faaSPeter Brune /* smooth on this level */ 72991f99d7cSPeter Brune ierr = SNESFASDownSmooth_Private(snes, B, X, F, &fnorm);CHKERRQ(ierr); 73007144faaSPeter Brune 731ab8d36c9SPeter Brune ierr = SNESGetConvergedReason(next,&reason);CHKERRQ(ierr); 73207144faaSPeter Brune if (reason < 0 && reason != SNES_DIVERGED_MAX_IT) { 73307144faaSPeter Brune snes->reason = SNES_DIVERGED_INNER; 73407144faaSPeter Brune PetscFunctionReturn(0); 73507144faaSPeter Brune } 73607144faaSPeter Brune 73707144faaSPeter Brune /* correct as x <- x + I(x^c - Rx)*/ 738c68acad4SPeter Brune ierr = VecAYPX(X_c, -1.0, Xo_c);CHKERRQ(ierr); 739ab8d36c9SPeter Brune ierr = MatInterpolate(interpolate, X_c, Xhat);CHKERRQ(ierr); 74007144faaSPeter Brune 741ddebd997SPeter Brune /* additive correction of the coarse direction*/ 742f1c6b773SPeter Brune ierr = SNESLineSearchApply(snes->linesearch, X, F, &fnorm, Xhat);CHKERRQ(ierr); 743f1c6b773SPeter Brune ierr = SNESLineSearchGetSuccess(snes->linesearch, &lssuccess);CHKERRQ(ierr); 7449e764e56SPeter Brune if (!lssuccess) { 7459e764e56SPeter Brune if (++snes->numFailures >= snes->maxFailures) { 7469e764e56SPeter Brune snes->reason = SNES_DIVERGED_LINE_SEARCH; 7479e764e56SPeter Brune PetscFunctionReturn(0); 7489e764e56SPeter Brune } 7499e764e56SPeter Brune } 750b9c2fdf1SPeter Brune ierr = SNESLineSearchGetNorms(snes->linesearch, &xnorm, &snes->norm, &ynorm);CHKERRQ(ierr); 75107144faaSPeter Brune } else { 75291f99d7cSPeter Brune ierr = SNESFASDownSmooth_Private(snes, B, X, F, &snes->norm);CHKERRQ(ierr); 75307144faaSPeter Brune } 75439bd7f45SPeter Brune PetscFunctionReturn(0); 75539bd7f45SPeter Brune } 75639bd7f45SPeter Brune 75739bd7f45SPeter Brune #undef __FUNCT__ 7582cf9d1e8SPeter Brune #define __FUNCT__ "SNESFASCycle_Multiplicative" 75939bd7f45SPeter Brune /* 76039bd7f45SPeter Brune 76139bd7f45SPeter Brune Defines the FAS cycle as: 76239bd7f45SPeter Brune 76339bd7f45SPeter Brune fine problem: F(x) = 0 76439bd7f45SPeter Brune coarse problem: F^c(x) = b^c 76539bd7f45SPeter Brune 76639bd7f45SPeter Brune b^c = F^c(I^c_fx^f - I^c_fF(x)) 76739bd7f45SPeter Brune 76839bd7f45SPeter Brune correction: 76939bd7f45SPeter Brune 77039bd7f45SPeter Brune x = x + I(x^c - Rx) 77139bd7f45SPeter Brune 77239bd7f45SPeter Brune */ 7730adebc6cSBarry Smith PetscErrorCode SNESFASCycle_Multiplicative(SNES snes, Vec X) 7740adebc6cSBarry Smith { 77539bd7f45SPeter Brune 77639bd7f45SPeter Brune PetscErrorCode ierr; 77739bd7f45SPeter Brune Vec F,B; 77839bd7f45SPeter Brune SNES_FAS *fas = (SNES_FAS *)snes->data; 77939bd7f45SPeter Brune 78039bd7f45SPeter Brune PetscFunctionBegin; 78139bd7f45SPeter Brune F = snes->vec_func; 78239bd7f45SPeter Brune B = snes->vec_rhs; 78339bd7f45SPeter Brune /* pre-smooth -- just update using the pre-smoother */ 78491f99d7cSPeter Brune ierr = SNESFASDownSmooth_Private(snes, B, X, F, &snes->norm);CHKERRQ(ierr); 785c90fad12SPeter Brune if (fas->level != 0) { 7868c40d5fbSBarry Smith ierr = SNESFASCoarseCorrection(snes, X, F, X);CHKERRQ(ierr); 78791f99d7cSPeter Brune ierr = SNESFASUpSmooth_Private(snes, B, X, F, &snes->norm);CHKERRQ(ierr); 788fe6f9142SPeter Brune } 789fa9694d7SPeter Brune PetscFunctionReturn(0); 790421d9b32SPeter Brune } 791421d9b32SPeter Brune 792421d9b32SPeter Brune #undef __FUNCT__ 793421d9b32SPeter Brune #define __FUNCT__ "SNESSolve_FAS" 794421d9b32SPeter Brune 795421d9b32SPeter Brune PetscErrorCode SNESSolve_FAS(SNES snes) 796421d9b32SPeter Brune { 797fa9694d7SPeter Brune PetscErrorCode ierr; 798fe6f9142SPeter Brune PetscInt i, maxits; 799ddb5aff1SPeter Brune Vec X, F; 800fe6f9142SPeter Brune PetscReal fnorm; 801b17ce1afSJed Brown SNES_FAS *fas = (SNES_FAS *)snes->data,*ffas; 802b17ce1afSJed Brown DM dm; 803e70c42e5SPeter Brune PetscBool isFine; 804b17ce1afSJed Brown 805421d9b32SPeter Brune PetscFunctionBegin; 806fe6f9142SPeter Brune maxits = snes->max_its; /* maximum number of iterations */ 807fe6f9142SPeter Brune snes->reason = SNES_CONVERGED_ITERATING; 808fa9694d7SPeter Brune X = snes->vec_sol; 809f5a6d4f9SBarry Smith F = snes->vec_func; 810293a7e31SPeter Brune 81118a66777SPeter Brune ierr = SNESFASCycleIsFine(snes, &isFine);CHKERRQ(ierr); 812293a7e31SPeter Brune /*norm setup */ 813fe6f9142SPeter Brune ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr); 814fe6f9142SPeter Brune snes->iter = 0; 815fe6f9142SPeter Brune snes->norm = 0.; 816fe6f9142SPeter Brune ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr); 817e4ed7901SPeter Brune if (!snes->vec_func_init_set) { 818*0dd27c6cSPeter Brune if (fas->eventresidual) {ierr = PetscLogEventBegin(fas->eventresidual,0,0,0,0);CHKERRQ(ierr);} 819fe6f9142SPeter Brune ierr = SNESComputeFunction(snes,X,F);CHKERRQ(ierr); 820*0dd27c6cSPeter Brune if (fas->eventresidual) {ierr = PetscLogEventEnd(fas->eventresidual,0,0,0,0);CHKERRQ(ierr);} 821fe6f9142SPeter Brune if (snes->domainerror) { 822fe6f9142SPeter Brune snes->reason = SNES_DIVERGED_FUNCTION_DOMAIN; 823fe6f9142SPeter Brune PetscFunctionReturn(0); 824fe6f9142SPeter Brune } 825e4ed7901SPeter Brune } else { 826e4ed7901SPeter Brune snes->vec_func_init_set = PETSC_FALSE; 827e4ed7901SPeter Brune } 828e4ed7901SPeter Brune 829e4ed7901SPeter Brune if (!snes->norm_init_set) { 830fe6f9142SPeter Brune ierr = VecNorm(F, NORM_2, &fnorm);CHKERRQ(ierr); /* fnorm <- ||F|| */ 831fe6f9142SPeter Brune if (PetscIsInfOrNanReal(fnorm)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"Infinite or not-a-number generated in norm"); 832fe6f9142SPeter Brune ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr); 833e4ed7901SPeter Brune } else { 834e4ed7901SPeter Brune fnorm = snes->norm_init; 835e4ed7901SPeter Brune snes->norm_init_set = PETSC_FALSE; 836e4ed7901SPeter Brune } 837e4ed7901SPeter Brune 838fe6f9142SPeter Brune snes->norm = fnorm; 839fe6f9142SPeter Brune ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr); 840fe6f9142SPeter Brune SNESLogConvHistory(snes,fnorm,0); 841fe6f9142SPeter Brune ierr = SNESMonitor(snes,0,fnorm);CHKERRQ(ierr); 842fe6f9142SPeter Brune 843fe6f9142SPeter Brune /* set parameter for default relative tolerance convergence test */ 844fe6f9142SPeter Brune snes->ttol = fnorm*snes->rtol; 845fe6f9142SPeter Brune /* test convergence */ 846fe6f9142SPeter Brune ierr = (*snes->ops->converged)(snes,0,0.0,0.0,fnorm,&snes->reason,snes->cnvP);CHKERRQ(ierr); 847fe6f9142SPeter Brune if (snes->reason) PetscFunctionReturn(0); 848e4ed7901SPeter Brune 849b17ce1afSJed Brown 850b9c2fdf1SPeter Brune if (isFine) { 851b9c2fdf1SPeter Brune /* propagate scale-dependent data up the hierarchy */ 852b17ce1afSJed Brown ierr = SNESGetDM(snes,&dm);CHKERRQ(ierr); 853b17ce1afSJed Brown for (ffas=fas; ffas->next; ffas=(SNES_FAS*)ffas->next->data) { 854b17ce1afSJed Brown DM dmcoarse; 855b17ce1afSJed Brown ierr = SNESGetDM(ffas->next,&dmcoarse);CHKERRQ(ierr); 856b17ce1afSJed Brown ierr = DMRestrict(dm,ffas->restrct,ffas->rscale,ffas->inject,dmcoarse);CHKERRQ(ierr); 857b17ce1afSJed Brown dm = dmcoarse; 858b17ce1afSJed Brown } 859b9c2fdf1SPeter Brune } 860b17ce1afSJed Brown 861fe6f9142SPeter Brune for (i = 0; i < maxits; i++) { 862fe6f9142SPeter Brune /* Call general purpose update function */ 863646217ecSPeter Brune 864fe6f9142SPeter Brune if (snes->ops->update) { 865fe6f9142SPeter Brune ierr = (*snes->ops->update)(snes, snes->iter);CHKERRQ(ierr); 866fe6f9142SPeter Brune } 86707144faaSPeter Brune if (fas->fastype == SNES_FAS_MULTIPLICATIVE) { 86891f99d7cSPeter Brune ierr = SNESFASCycle_Multiplicative(snes, X);CHKERRQ(ierr); 86907144faaSPeter Brune } else { 87091f99d7cSPeter Brune ierr = SNESFASCycle_Additive(snes, X);CHKERRQ(ierr); 87107144faaSPeter Brune } 872742fe5e2SPeter Brune 873742fe5e2SPeter Brune /* check for FAS cycle divergence */ 874742fe5e2SPeter Brune if (snes->reason != SNES_CONVERGED_ITERATING) { 875742fe5e2SPeter Brune PetscFunctionReturn(0); 876742fe5e2SPeter Brune } 877b9c2fdf1SPeter Brune 878c90fad12SPeter Brune /* Monitor convergence */ 879c90fad12SPeter Brune ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr); 880c90fad12SPeter Brune snes->iter = i+1; 881c90fad12SPeter Brune ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr); 882c90fad12SPeter Brune SNESLogConvHistory(snes,snes->norm,0); 883c90fad12SPeter Brune ierr = SNESMonitor(snes,snes->iter,snes->norm);CHKERRQ(ierr); 884c90fad12SPeter Brune /* Test for convergence */ 88566585501SPeter Brune if (isFine) { 886b9c2fdf1SPeter Brune ierr = (*snes->ops->converged)(snes,snes->iter,0.0,0.0,snes->norm,&snes->reason,snes->cnvP);CHKERRQ(ierr); 887c90fad12SPeter Brune if (snes->reason) break; 888fe6f9142SPeter Brune } 88966585501SPeter Brune } 890fe6f9142SPeter Brune if (i == maxits) { 891fe6f9142SPeter Brune ierr = PetscInfo1(snes, "Maximum number of iterations has been reached: %D\n", maxits);CHKERRQ(ierr); 892fe6f9142SPeter Brune if (!snes->reason) snes->reason = SNES_DIVERGED_MAX_IT; 893fe6f9142SPeter Brune } 894421d9b32SPeter Brune PetscFunctionReturn(0); 895421d9b32SPeter Brune } 896