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" 49*8cc058d9SJed Brown PETSC_EXTERN 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); 711aa26658SKarl Rupp 72421d9b32SPeter Brune snes->data = (void*) fas; 73421d9b32SPeter Brune fas->level = 0; 74293a7e31SPeter Brune fas->levels = 1; 75ee78dd50SPeter Brune fas->n_cycles = 1; 76ee78dd50SPeter Brune fas->max_up_it = 1; 77ee78dd50SPeter Brune fas->max_down_it = 1; 780298fd71SBarry Smith fas->smoothu = NULL; 790298fd71SBarry Smith fas->smoothd = NULL; 800298fd71SBarry Smith fas->next = NULL; 810298fd71SBarry Smith fas->previous = NULL; 82ab8d36c9SPeter Brune fas->fine = snes; 830298fd71SBarry Smith fas->interpolate = NULL; 840298fd71SBarry Smith fas->restrct = NULL; 850298fd71SBarry Smith fas->inject = NULL; 860298fd71SBarry Smith fas->monitor = NULL; 87cc05f883SPeter Brune fas->usedmfornumberoflevels = PETSC_FALSE; 88ddebd997SPeter Brune fas->fastype = SNES_FAS_MULTIPLICATIVE; 890dd27c6cSPeter Brune 900298fd71SBarry Smith fas->eventsmoothsetup = 0; 910298fd71SBarry Smith fas->eventsmoothsolve = 0; 920298fd71SBarry Smith fas->eventresidual = 0; 930298fd71SBarry Smith fas->eventinterprestrict = 0; 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); 112421d9b32SPeter Brune PetscFunctionReturn(0); 113421d9b32SPeter Brune } 114421d9b32SPeter Brune 115421d9b32SPeter Brune #undef __FUNCT__ 116421d9b32SPeter Brune #define __FUNCT__ "SNESDestroy_FAS" 117421d9b32SPeter Brune PetscErrorCode SNESDestroy_FAS(SNES snes) 118421d9b32SPeter Brune { 119421d9b32SPeter Brune SNES_FAS * fas = (SNES_FAS*)snes->data; 120742fe5e2SPeter Brune PetscErrorCode ierr = 0; 121421d9b32SPeter Brune 122421d9b32SPeter Brune PetscFunctionBegin; 123421d9b32SPeter Brune /* recursively resets and then destroys */ 12479d9a41aSPeter Brune ierr = SNESReset(snes);CHKERRQ(ierr); 1251aa26658SKarl Rupp if (fas->next) { 1261aa26658SKarl Rupp ierr = SNESDestroy(&fas->next);CHKERRQ(ierr); 1271aa26658SKarl Rupp } 128421d9b32SPeter Brune ierr = PetscFree(fas);CHKERRQ(ierr); 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; 1600298fd71SBarry Smith snes->vec_sol = NULL; 1610298fd71SBarry Smith snes->vec_func = NULL; 1620298fd71SBarry Smith snes->vec_sol_update = NULL; 1630298fd71SBarry Smith snes->vec_rhs = NULL; 1643dccd265SPeter Brune 1653dccd265SPeter Brune /* reset the number of levels */ 1660298fd71SBarry Smith ierr = SNESFASSetLevels(snes,dm_levels,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) { 197ce94432eSBarry Smith ierr = DMCoarsen(snes->dm, PetscObjectComm((PetscObject)next), &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); 211ce94432eSBarry Smith ierr = MatCreateScatter(PetscObjectComm((PetscObject)snes), 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) { 2181aa26658SKarl Rupp if (next) { 2190298fd71SBarry Smith ierr = SNESSetFunction(next, NULL, SNESFASGalerkinDefaultFunction, next);CHKERRQ(ierr); 2201aa26658SKarl Rupp } 2211aa26658SKarl Rupp if (fas->smoothd && fas->level != fas->levels - 1) { 2220298fd71SBarry Smith ierr = SNESSetFunction(fas->smoothd, NULL, SNESFASGalerkinDefaultFunction, snes);CHKERRQ(ierr); 2231aa26658SKarl Rupp } 2241aa26658SKarl Rupp if (fas->smoothu && fas->level != fas->levels - 1) { 2250298fd71SBarry Smith ierr = SNESSetFunction(fas->smoothu, NULL, SNESFASGalerkinDefaultFunction, snes);CHKERRQ(ierr); 2261aa26658SKarl Rupp } 22779d9a41aSPeter Brune } 22879d9a41aSPeter Brune 229534ebe21SPeter Brune /* sets the down (pre) smoother's default norm and sets it from options */ 230534ebe21SPeter Brune if (fas->smoothd) { 231bc3f2f05SPeter Brune if (fas->level == 0 && fas->levels != 1) { 232534ebe21SPeter Brune ierr = SNESSetNormType(fas->smoothd, SNES_NORM_NONE);CHKERRQ(ierr); 233534ebe21SPeter Brune } else { 234534ebe21SPeter Brune ierr = SNESSetNormType(fas->smoothd, SNES_NORM_FINAL_ONLY);CHKERRQ(ierr); 235534ebe21SPeter Brune } 2367fce8c19SPeter Brune ierr = PetscObjectCopyFortranFunctionPointers((PetscObject)snes, (PetscObject)fas->smoothd);CHKERRQ(ierr); 237534ebe21SPeter Brune ierr = SNESSetFromOptions(fas->smoothd);CHKERRQ(ierr); 238f89ba88eSPeter Brune ierr = SNESGetSNESLineSearch(snes,&linesearch);CHKERRQ(ierr); 239f89ba88eSPeter Brune ierr = SNESGetSNESLineSearch(fas->smoothd,&slinesearch);CHKERRQ(ierr); 2406b2b7091SBarry Smith ierr = SNESLineSearchGetPreCheck(linesearch,&precheck,&lsprectx);CHKERRQ(ierr); 2416b2b7091SBarry Smith ierr = SNESLineSearchGetPostCheck(linesearch,&postcheck,&lspostctx);CHKERRQ(ierr); 2426b2b7091SBarry Smith ierr = SNESLineSearchSetPreCheck(slinesearch,precheck,lsprectx);CHKERRQ(ierr); 2436b2b7091SBarry Smith ierr = SNESLineSearchSetPostCheck(slinesearch,postcheck,lspostctx);CHKERRQ(ierr); 244f89ba88eSPeter Brune ierr = PetscObjectCopyFortranFunctionPointers((PetscObject)linesearch, (PetscObject)slinesearch);CHKERRQ(ierr); 2450dd27c6cSPeter Brune 2460dd27c6cSPeter Brune fas->smoothd->vec_sol = snes->vec_sol; 2470dd27c6cSPeter Brune ierr = PetscObjectReference((PetscObject)snes->vec_sol);CHKERRQ(ierr); 2480dd27c6cSPeter Brune fas->smoothd->vec_sol_update = snes->vec_sol_update; 2490dd27c6cSPeter Brune ierr = PetscObjectReference((PetscObject)snes->vec_sol_update);CHKERRQ(ierr); 2500dd27c6cSPeter Brune fas->smoothd->vec_func = snes->vec_func; 2510dd27c6cSPeter Brune ierr = PetscObjectReference((PetscObject)snes->vec_func);CHKERRQ(ierr); 2520dd27c6cSPeter Brune 2530dd27c6cSPeter Brune if (fas->eventsmoothsetup) {ierr = PetscLogEventBegin(fas->eventsmoothsetup,0,0,0,0);CHKERRQ(ierr);} 2540dd27c6cSPeter Brune ierr = SNESSetUp(fas->smoothd);CHKERRQ(ierr); 2550dd27c6cSPeter Brune if (fas->eventsmoothsetup) {ierr = PetscLogEventEnd(fas->eventsmoothsetup,0,0,0,0);CHKERRQ(ierr);} 256534ebe21SPeter Brune } 257534ebe21SPeter Brune 258534ebe21SPeter Brune /* sets the up (post) smoother's default norm and sets it from options */ 259534ebe21SPeter Brune if (fas->smoothu) { 260534ebe21SPeter Brune if (fas->level != fas->levels - 1) { 261534ebe21SPeter Brune ierr = SNESSetNormType(fas->smoothu, SNES_NORM_NONE);CHKERRQ(ierr); 262534ebe21SPeter Brune } else { 263534ebe21SPeter Brune ierr = SNESSetNormType(fas->smoothu, SNES_NORM_FINAL_ONLY);CHKERRQ(ierr); 264534ebe21SPeter Brune } 2657fce8c19SPeter Brune ierr = PetscObjectCopyFortranFunctionPointers((PetscObject)snes, (PetscObject)fas->smoothu);CHKERRQ(ierr); 266534ebe21SPeter Brune ierr = SNESSetFromOptions(fas->smoothu);CHKERRQ(ierr); 267f89ba88eSPeter Brune ierr = SNESGetSNESLineSearch(snes,&linesearch);CHKERRQ(ierr); 268f89ba88eSPeter Brune ierr = SNESGetSNESLineSearch(fas->smoothu,&slinesearch);CHKERRQ(ierr); 2696b2b7091SBarry Smith ierr = SNESLineSearchGetPreCheck(linesearch,&precheck,&lsprectx);CHKERRQ(ierr); 2706b2b7091SBarry Smith ierr = SNESLineSearchGetPostCheck(linesearch,&postcheck,&lspostctx);CHKERRQ(ierr); 2716b2b7091SBarry Smith ierr = SNESLineSearchSetPreCheck(slinesearch,precheck,lsprectx);CHKERRQ(ierr); 2726b2b7091SBarry Smith ierr = SNESLineSearchSetPostCheck(slinesearch,postcheck,lspostctx);CHKERRQ(ierr); 273f89ba88eSPeter Brune ierr = PetscObjectCopyFortranFunctionPointers((PetscObject)linesearch, (PetscObject)slinesearch);CHKERRQ(ierr); 2740dd27c6cSPeter Brune 2750dd27c6cSPeter Brune fas->smoothu->vec_sol = snes->vec_sol; 2760dd27c6cSPeter Brune ierr = PetscObjectReference((PetscObject)snes->vec_sol);CHKERRQ(ierr); 2770dd27c6cSPeter Brune fas->smoothu->vec_sol_update = snes->vec_sol_update; 2780dd27c6cSPeter Brune ierr = PetscObjectReference((PetscObject)snes->vec_sol_update);CHKERRQ(ierr); 2790dd27c6cSPeter Brune fas->smoothu->vec_func = snes->vec_func; 2800dd27c6cSPeter Brune ierr = PetscObjectReference((PetscObject)snes->vec_func);CHKERRQ(ierr); 2810dd27c6cSPeter Brune 2820dd27c6cSPeter Brune if (fas->eventsmoothsetup) {ierr = PetscLogEventBegin(fas->eventsmoothsetup,0,0,0,0);CHKERRQ(ierr);} 2830dd27c6cSPeter Brune ierr = SNESSetUp(fas->smoothu);CHKERRQ(ierr); 2840dd27c6cSPeter Brune if (fas->eventsmoothsetup) {ierr = PetscLogEventEnd(fas->eventsmoothsetup,0,0,0,0);CHKERRQ(ierr);} 2850dd27c6cSPeter Brune 286534ebe21SPeter Brune } 287d06165b7SPeter Brune 288ab8d36c9SPeter Brune if (next) { 28979d9a41aSPeter Brune /* gotta set up the solution vector for this to work */ 290ab8d36c9SPeter Brune if (!next->vec_sol) {ierr = SNESFASCreateCoarseVec(snes,&next->vec_sol);CHKERRQ(ierr);} 291ab8d36c9SPeter Brune if (!next->vec_rhs) {ierr = SNESFASCreateCoarseVec(snes,&next->vec_rhs);CHKERRQ(ierr);} 2927fce8c19SPeter Brune ierr = PetscObjectCopyFortranFunctionPointers((PetscObject)snes, (PetscObject)next);CHKERRQ(ierr); 293f89ba88eSPeter Brune ierr = SNESGetSNESLineSearch(snes,&linesearch);CHKERRQ(ierr); 294f89ba88eSPeter Brune ierr = SNESGetSNESLineSearch(fas->next,&slinesearch);CHKERRQ(ierr); 2956b2b7091SBarry Smith ierr = SNESLineSearchGetPreCheck(linesearch,&precheck,&lsprectx);CHKERRQ(ierr); 2966b2b7091SBarry Smith ierr = SNESLineSearchGetPostCheck(linesearch,&postcheck,&lspostctx);CHKERRQ(ierr); 2976b2b7091SBarry Smith ierr = SNESLineSearchSetPreCheck(slinesearch,precheck,lsprectx);CHKERRQ(ierr); 2986b2b7091SBarry Smith ierr = SNESLineSearchSetPostCheck(slinesearch,postcheck,lspostctx);CHKERRQ(ierr); 299f89ba88eSPeter Brune ierr = PetscObjectCopyFortranFunctionPointers((PetscObject)linesearch, (PetscObject)slinesearch);CHKERRQ(ierr); 300ab8d36c9SPeter Brune ierr = SNESSetUp(next);CHKERRQ(ierr); 30179d9a41aSPeter Brune } 3026273346dSPeter Brune /* setup FAS work vectors */ 3036273346dSPeter Brune if (fas->galerkin) { 3046273346dSPeter Brune ierr = VecDuplicate(snes->vec_sol, &fas->Xg);CHKERRQ(ierr); 3056273346dSPeter Brune ierr = VecDuplicate(snes->vec_sol, &fas->Fg);CHKERRQ(ierr); 3066273346dSPeter Brune } 307421d9b32SPeter Brune PetscFunctionReturn(0); 308421d9b32SPeter Brune } 309421d9b32SPeter Brune 310421d9b32SPeter Brune #undef __FUNCT__ 311421d9b32SPeter Brune #define __FUNCT__ "SNESSetFromOptions_FAS" 312421d9b32SPeter Brune PetscErrorCode SNESSetFromOptions_FAS(SNES snes) 313421d9b32SPeter Brune { 314ee78dd50SPeter Brune SNES_FAS *fas = (SNES_FAS*) snes->data; 315ee78dd50SPeter Brune PetscInt levels = 1; 3164d26bfa5SPeter Brune PetscBool flg = PETSC_FALSE, upflg = PETSC_FALSE, downflg = PETSC_FALSE, monflg = PETSC_FALSE, galerkinflg = PETSC_FALSE; 317421d9b32SPeter Brune PetscErrorCode ierr; 318ee78dd50SPeter Brune char monfilename[PETSC_MAX_PATH_LEN]; 31907144faaSPeter Brune SNESFASType fastype; 320fde0ff24SPeter Brune const char *optionsprefix; 321f1c6b773SPeter Brune SNESLineSearch linesearch; 32266585501SPeter Brune PetscInt m, n_up, n_down; 323ab8d36c9SPeter Brune SNES next; 324ab8d36c9SPeter Brune PetscBool isFine; 325421d9b32SPeter Brune 326421d9b32SPeter Brune PetscFunctionBegin; 327ab8d36c9SPeter Brune ierr = SNESFASCycleIsFine(snes, &isFine);CHKERRQ(ierr); 328c90fad12SPeter Brune ierr = PetscOptionsHead("SNESFAS Options-----------------------------------");CHKERRQ(ierr); 329ee78dd50SPeter Brune 330ab8d36c9SPeter Brune /* number of levels -- only process most options on the finest level */ 331ab8d36c9SPeter Brune if (isFine) { 332ee78dd50SPeter Brune ierr = PetscOptionsInt("-snes_fas_levels", "Number of Levels", "SNESFASSetLevels", levels, &levels, &flg);CHKERRQ(ierr); 333c732cbdbSBarry Smith if (!flg && snes->dm) { 334c732cbdbSBarry Smith ierr = DMGetRefineLevel(snes->dm,&levels);CHKERRQ(ierr); 335c732cbdbSBarry Smith levels++; 336d1adcc6fSPeter Brune fas->usedmfornumberoflevels = PETSC_TRUE; 337c732cbdbSBarry Smith } 3380298fd71SBarry Smith ierr = SNESFASSetLevels(snes, levels, NULL);CHKERRQ(ierr); 33907144faaSPeter Brune fastype = fas->fastype; 34007144faaSPeter Brune ierr = PetscOptionsEnum("-snes_fas_type","FAS correction type","SNESFASSetType",SNESFASTypes,(PetscEnum)fastype,(PetscEnum*)&fastype,&flg);CHKERRQ(ierr); 34107144faaSPeter Brune if (flg) { 34207144faaSPeter Brune ierr = SNESFASSetType(snes, fastype);CHKERRQ(ierr); 34307144faaSPeter Brune } 344ee78dd50SPeter Brune 345fde0ff24SPeter Brune ierr = SNESGetOptionsPrefix(snes, &optionsprefix);CHKERRQ(ierr); 346ab8d36c9SPeter Brune ierr = PetscOptionsInt("-snes_fas_cycles","Number of cycles","SNESFASSetCycles",fas->n_cycles,&m,&flg);CHKERRQ(ierr); 347ab8d36c9SPeter Brune if (flg) { 348ab8d36c9SPeter Brune ierr = SNESFASSetCycles(snes, m);CHKERRQ(ierr); 349fde0ff24SPeter Brune } 350fde0ff24SPeter Brune 351ab8d36c9SPeter Brune ierr = PetscOptionsBool("-snes_fas_galerkin", "Form coarse problems with Galerkin","SNESFASSetGalerkin",fas->galerkin,&galerkinflg,&flg);CHKERRQ(ierr); 352ab8d36c9SPeter Brune if (flg) { 353ab8d36c9SPeter Brune ierr = SNESFASSetGalerkin(snes, galerkinflg);CHKERRQ(ierr); 354ab8d36c9SPeter Brune } 355ee78dd50SPeter Brune 35666585501SPeter Brune ierr = PetscOptionsInt("-snes_fas_smoothup","Number of post-smoothing steps","SNESFASSetNumberSmoothUp",fas->max_up_it,&n_up,&upflg);CHKERRQ(ierr); 357162d76ddSPeter Brune 35866585501SPeter Brune ierr = PetscOptionsInt("-snes_fas_smoothdown","Number of pre-smoothing steps","SNESFASSetNumberSmoothDown",fas->max_down_it,&n_down,&downflg);CHKERRQ(ierr); 359162d76ddSPeter Brune 360c8c899caSPeter Brune ierr = PetscOptionsString("-snes_fas_monitor","Monitor FAS progress","SNESFASSetMonitor","stdout",monfilename,PETSC_MAX_PATH_LEN,&monflg);CHKERRQ(ierr); 361c8c899caSPeter Brune if (monflg) ierr = SNESFASSetMonitor(snes, PETSC_TRUE);CHKERRQ(ierr); 3620dd27c6cSPeter Brune 3630dd27c6cSPeter Brune flg = PETSC_FALSE; 3640dd27c6cSPeter Brune monflg = PETSC_TRUE; 3650dd27c6cSPeter Brune ierr = PetscOptionsBool("-snes_fas_log","Log times for each FAS level","SNESFASSetLog",monflg,&monflg,&flg);CHKERRQ(ierr); 3660dd27c6cSPeter Brune if (flg) {ierr = SNESFASSetLog(snes,monflg);CHKERRQ(ierr);} 367ab8d36c9SPeter Brune } 368ee78dd50SPeter Brune 369421d9b32SPeter Brune ierr = PetscOptionsTail();CHKERRQ(ierr); 3708cc86e31SPeter Brune /* setup from the determined types if there is no pointwise procedure or smoother defined */ 371162d76ddSPeter Brune if (upflg) { 37266585501SPeter Brune ierr = SNESFASSetNumberSmoothUp(snes,n_up);CHKERRQ(ierr); 373162d76ddSPeter Brune } 374162d76ddSPeter Brune if (downflg) { 37566585501SPeter Brune ierr = SNESFASSetNumberSmoothDown(snes,n_down);CHKERRQ(ierr); 376162d76ddSPeter Brune } 377eff52c0eSPeter Brune 3789e764e56SPeter Brune /* set up the default line search for coarse grid corrections */ 3799e764e56SPeter Brune if (fas->fastype == SNES_FAS_ADDITIVE) { 3809e764e56SPeter Brune if (!snes->linesearch) { 381f1c6b773SPeter Brune ierr = SNESGetSNESLineSearch(snes, &linesearch);CHKERRQ(ierr); 3821a4f838cSPeter Brune ierr = SNESLineSearchSetType(linesearch, SNESLINESEARCHL2);CHKERRQ(ierr); 3839e764e56SPeter Brune } 3849e764e56SPeter Brune } 3859e764e56SPeter Brune 386ab8d36c9SPeter Brune ierr = SNESFASCycleGetCorrection(snes, &next);CHKERRQ(ierr); 387ee78dd50SPeter Brune /* recursive option setting for the smoothers */ 388ab8d36c9SPeter Brune if (next) {ierr = SNESSetFromOptions(next);CHKERRQ(ierr);} 389421d9b32SPeter Brune PetscFunctionReturn(0); 390421d9b32SPeter Brune } 391421d9b32SPeter Brune 3929804daf3SBarry Smith #include <petscdraw.h> 393421d9b32SPeter Brune #undef __FUNCT__ 394421d9b32SPeter Brune #define __FUNCT__ "SNESView_FAS" 395421d9b32SPeter Brune PetscErrorCode SNESView_FAS(SNES snes, PetscViewer viewer) 396421d9b32SPeter Brune { 397421d9b32SPeter Brune SNES_FAS *fas = (SNES_FAS*) snes->data; 398656ede7eSPeter Brune PetscBool isFine,iascii,isdraw; 399ab8d36c9SPeter Brune PetscInt i; 400421d9b32SPeter Brune PetscErrorCode ierr; 401ab8d36c9SPeter Brune SNES smoothu, smoothd, levelsnes; 402421d9b32SPeter Brune 403421d9b32SPeter Brune PetscFunctionBegin; 404ab8d36c9SPeter Brune ierr = SNESFASCycleIsFine(snes, &isFine);CHKERRQ(ierr); 405ab8d36c9SPeter Brune if (isFine) { 406251f4c67SDmitry Karpeev ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr); 407656ede7eSPeter Brune ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERDRAW,&isdraw);CHKERRQ(ierr); 408421d9b32SPeter Brune if (iascii) { 409ab8d36c9SPeter Brune ierr = PetscViewerASCIIPrintf(viewer, "FAS: type is %s, levels=%D, cycles=%D\n", SNESFASTypes[fas->fastype], fas->levels, fas->n_cycles);CHKERRQ(ierr); 410ab8d36c9SPeter Brune if (fas->galerkin) { 411ab8d36c9SPeter Brune ierr = PetscViewerASCIIPrintf(viewer," Using Galerkin computed coarse grid function evaluation\n");CHKERRQ(ierr); 412421d9b32SPeter Brune } else { 413ab8d36c9SPeter Brune ierr = PetscViewerASCIIPrintf(viewer," Not using Galerkin computed coarse grid function evaluation\n");CHKERRQ(ierr); 414421d9b32SPeter Brune } 415ab8d36c9SPeter Brune for (i=0; i<fas->levels; i++) { 416ab8d36c9SPeter Brune ierr = SNESFASGetCycleSNES(snes, i, &levelsnes);CHKERRQ(ierr); 417ab8d36c9SPeter Brune ierr = SNESFASCycleGetSmootherUp(levelsnes, &smoothu);CHKERRQ(ierr); 418ab8d36c9SPeter Brune ierr = SNESFASCycleGetSmootherDown(levelsnes, &smoothd);CHKERRQ(ierr); 419ab8d36c9SPeter Brune if (!i) { 420ab8d36c9SPeter Brune ierr = PetscViewerASCIIPrintf(viewer,"Coarse grid solver -- level %D -------------------------------\n",i);CHKERRQ(ierr); 421421d9b32SPeter Brune } else { 422ab8d36c9SPeter Brune ierr = PetscViewerASCIIPrintf(viewer,"Down solver (pre-smoother) on level %D -------------------------------\n",i);CHKERRQ(ierr); 423421d9b32SPeter Brune } 424ab8d36c9SPeter Brune ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); 425ab8d36c9SPeter Brune ierr = SNESView(smoothd,viewer);CHKERRQ(ierr); 426ab8d36c9SPeter Brune ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); 427ab8d36c9SPeter Brune if (i && (smoothd == smoothu)) { 428ab8d36c9SPeter Brune ierr = PetscViewerASCIIPrintf(viewer,"Up solver (post-smoother) same as down solver (pre-smoother)\n");CHKERRQ(ierr); 429ab8d36c9SPeter Brune } else if (i) { 430ab8d36c9SPeter Brune ierr = PetscViewerASCIIPrintf(viewer,"Up solver (post-smoother) on level %D -------------------------------\n",i);CHKERRQ(ierr); 431ab8d36c9SPeter Brune ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); 432ab8d36c9SPeter Brune ierr = SNESView(smoothu,viewer);CHKERRQ(ierr); 433ab8d36c9SPeter Brune ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); 434ab8d36c9SPeter Brune } 435ab8d36c9SPeter Brune } 436656ede7eSPeter Brune } else if (isdraw) { 437656ede7eSPeter Brune PetscDraw draw; 438b4375e8dSPeter Brune PetscReal x,w,y,bottom,th,wth; 439656ede7eSPeter Brune SNES_FAS *curfas = fas; 440656ede7eSPeter Brune ierr = PetscViewerDrawGetDraw(viewer,0,&draw);CHKERRQ(ierr); 441656ede7eSPeter Brune ierr = PetscDrawGetCurrentPoint(draw,&x,&y);CHKERRQ(ierr); 442656ede7eSPeter Brune ierr = PetscDrawStringGetSize(draw,&wth,&th);CHKERRQ(ierr); 443656ede7eSPeter Brune bottom = y - th; 444656ede7eSPeter Brune while (curfas) { 445b4375e8dSPeter Brune if (!curfas->smoothu) { 446656ede7eSPeter Brune ierr = PetscDrawPushCurrentPoint(draw,x,bottom);CHKERRQ(ierr); 447656ede7eSPeter Brune if (curfas->smoothd) ierr = SNESView(curfas->smoothd,viewer);CHKERRQ(ierr); 448656ede7eSPeter Brune ierr = PetscDrawPopCurrentPoint(draw);CHKERRQ(ierr); 449b4375e8dSPeter Brune } else { 450b4375e8dSPeter Brune w = 0.5*PetscMin(1.0-x,x); 451b4375e8dSPeter Brune ierr = PetscDrawPushCurrentPoint(draw,x-w,bottom);CHKERRQ(ierr); 452b4375e8dSPeter Brune if (curfas->smoothd) ierr = SNESView(curfas->smoothd,viewer);CHKERRQ(ierr); 453b4375e8dSPeter Brune ierr = PetscDrawPopCurrentPoint(draw);CHKERRQ(ierr); 454b4375e8dSPeter Brune ierr = PetscDrawPushCurrentPoint(draw,x+w,bottom);CHKERRQ(ierr); 455b4375e8dSPeter Brune if (curfas->smoothu) ierr = SNESView(curfas->smoothu,viewer);CHKERRQ(ierr); 456b4375e8dSPeter Brune ierr = PetscDrawPopCurrentPoint(draw);CHKERRQ(ierr); 457b4375e8dSPeter Brune } 458656ede7eSPeter Brune /* this is totally bogus but we have no way of knowing how low the previous one was draw to */ 459656ede7eSPeter Brune bottom -= 5*th; 4601aa26658SKarl Rupp if (curfas->next) curfas = (SNES_FAS*)curfas->next->data; 4610298fd71SBarry Smith else curfas = NULL; 462656ede7eSPeter Brune } 463421d9b32SPeter Brune } 464ab8d36c9SPeter Brune } 465421d9b32SPeter Brune PetscFunctionReturn(0); 466421d9b32SPeter Brune } 467421d9b32SPeter Brune 468421d9b32SPeter Brune #undef __FUNCT__ 46991f99d7cSPeter Brune #define __FUNCT__ "SNESFASDownSmooth_Private" 47039bd7f45SPeter Brune /* 47139bd7f45SPeter Brune Defines the action of the downsmoother 47239bd7f45SPeter Brune */ 47391f99d7cSPeter Brune PetscErrorCode SNESFASDownSmooth_Private(SNES snes, Vec B, Vec X, Vec F, PetscReal *fnorm) 474b9c2fdf1SPeter Brune { 47539bd7f45SPeter Brune PetscErrorCode ierr = 0; 476742fe5e2SPeter Brune SNESConvergedReason reason; 477ab8d36c9SPeter Brune Vec FPC; 478ab8d36c9SPeter Brune SNES smoothd; 4790dd27c6cSPeter Brune SNES_FAS *fas = (SNES_FAS*) snes->data; 4806e111a19SKarl Rupp 481421d9b32SPeter Brune PetscFunctionBegin; 482ab8d36c9SPeter Brune ierr = SNESFASCycleGetSmootherDown(snes, &smoothd);CHKERRQ(ierr); 483e4ed7901SPeter Brune ierr = SNESSetInitialFunction(smoothd, F);CHKERRQ(ierr); 484e4ed7901SPeter Brune ierr = SNESSetInitialFunctionNorm(smoothd, *fnorm);CHKERRQ(ierr); 4850dd27c6cSPeter Brune if (fas->eventsmoothsolve) {ierr = PetscLogEventBegin(fas->eventsmoothsolve,0,0,0,0);CHKERRQ(ierr);} 486ab8d36c9SPeter Brune ierr = SNESSolve(smoothd, B, X);CHKERRQ(ierr); 4870dd27c6cSPeter Brune if (fas->eventsmoothsolve) {ierr = PetscLogEventEnd(fas->eventsmoothsolve,0,0,0,0);CHKERRQ(ierr);} 488742fe5e2SPeter Brune /* check convergence reason for the smoother */ 489ab8d36c9SPeter Brune ierr = SNESGetConvergedReason(smoothd,&reason);CHKERRQ(ierr); 490e70c42e5SPeter Brune if (reason < 0 && !(reason == SNES_DIVERGED_MAX_IT || reason == SNES_DIVERGED_LOCAL_MIN)) { 491742fe5e2SPeter Brune snes->reason = SNES_DIVERGED_INNER; 492742fe5e2SPeter Brune PetscFunctionReturn(0); 493742fe5e2SPeter Brune } 4940298fd71SBarry Smith ierr = SNESGetFunction(smoothd, &FPC, NULL, NULL);CHKERRQ(ierr); 4954b32a720SPeter Brune ierr = VecCopy(FPC, F);CHKERRQ(ierr); 496b9c2fdf1SPeter Brune ierr = SNESGetFunctionNorm(smoothd, fnorm);CHKERRQ(ierr); 49739bd7f45SPeter Brune PetscFunctionReturn(0); 49839bd7f45SPeter Brune } 49939bd7f45SPeter Brune 50039bd7f45SPeter Brune 50139bd7f45SPeter Brune #undef __FUNCT__ 50291f99d7cSPeter Brune #define __FUNCT__ "SNESFASUpSmooth_Private" 50339bd7f45SPeter Brune /* 50407144faaSPeter Brune Defines the action of the upsmoother 50539bd7f45SPeter Brune */ 5060adebc6cSBarry Smith PetscErrorCode SNESFASUpSmooth_Private(SNES snes, Vec B, Vec X, Vec F, PetscReal *fnorm) 5070adebc6cSBarry Smith { 50839bd7f45SPeter Brune PetscErrorCode ierr = 0; 50939bd7f45SPeter Brune SNESConvergedReason reason; 510ab8d36c9SPeter Brune Vec FPC; 511ab8d36c9SPeter Brune SNES smoothu; 5120dd27c6cSPeter Brune SNES_FAS *fas = (SNES_FAS*) snes->data; 513ab8d36c9SPeter Brune 5146e111a19SKarl Rupp PetscFunctionBegin; 515ab8d36c9SPeter Brune ierr = SNESFASCycleGetSmootherUp(snes, &smoothu);CHKERRQ(ierr); 5160dd27c6cSPeter Brune if (fas->eventsmoothsolve) {ierr = PetscLogEventBegin(fas->eventsmoothsolve,0,0,0,0);CHKERRQ(ierr);} 517ab8d36c9SPeter Brune ierr = SNESSolve(smoothu, B, X);CHKERRQ(ierr); 5180dd27c6cSPeter Brune if (fas->eventsmoothsolve) {ierr = PetscLogEventEnd(fas->eventsmoothsolve,0,0,0,0);CHKERRQ(ierr);} 51939bd7f45SPeter Brune /* check convergence reason for the smoother */ 520ab8d36c9SPeter Brune ierr = SNESGetConvergedReason(smoothu,&reason);CHKERRQ(ierr); 52139bd7f45SPeter Brune if (reason < 0 && reason != SNES_DIVERGED_MAX_IT) { 52239bd7f45SPeter Brune snes->reason = SNES_DIVERGED_INNER; 52339bd7f45SPeter Brune PetscFunctionReturn(0); 52439bd7f45SPeter Brune } 5250298fd71SBarry Smith ierr = SNESGetFunction(smoothu, &FPC, NULL, NULL);CHKERRQ(ierr); 5264b32a720SPeter Brune ierr = VecCopy(FPC, F);CHKERRQ(ierr); 527b9c2fdf1SPeter Brune ierr = SNESGetFunctionNorm(smoothu, fnorm);CHKERRQ(ierr); 52839bd7f45SPeter Brune PetscFunctionReturn(0); 52939bd7f45SPeter Brune } 53039bd7f45SPeter Brune 53139bd7f45SPeter Brune #undef __FUNCT__ 532938e4a01SJed Brown #define __FUNCT__ "SNESFASCreateCoarseVec" 533938e4a01SJed Brown /*@ 534938e4a01SJed Brown SNESFASCreateCoarseVec - create Vec corresponding to a state vector on one level coarser than current level 535938e4a01SJed Brown 536938e4a01SJed Brown Collective 537938e4a01SJed Brown 538938e4a01SJed Brown Input Arguments: 539938e4a01SJed Brown . snes - SNESFAS 540938e4a01SJed Brown 541938e4a01SJed Brown Output Arguments: 542938e4a01SJed Brown . Xcoarse - vector on level one coarser than snes 543938e4a01SJed Brown 544938e4a01SJed Brown Level: developer 545938e4a01SJed Brown 546938e4a01SJed Brown .seealso: SNESFASSetRestriction(), SNESFASRestrict() 547938e4a01SJed Brown @*/ 548938e4a01SJed Brown PetscErrorCode SNESFASCreateCoarseVec(SNES snes,Vec *Xcoarse) 549938e4a01SJed Brown { 550938e4a01SJed Brown PetscErrorCode ierr; 551938e4a01SJed Brown SNES_FAS *fas = (SNES_FAS*)snes->data; 552938e4a01SJed Brown 553938e4a01SJed Brown PetscFunctionBegin; 5541aa26658SKarl Rupp if (fas->rscale) { 5551aa26658SKarl Rupp ierr = VecDuplicate(fas->rscale,Xcoarse);CHKERRQ(ierr); 556f5af7f23SKarl Rupp } else if (fas->inject) { 5570298fd71SBarry Smith ierr = MatGetVecs(fas->inject,Xcoarse,NULL);CHKERRQ(ierr); 558ce94432eSBarry Smith } else SETERRQ(PetscObjectComm((PetscObject)snes),PETSC_ERR_ARG_WRONGSTATE,"Must set restriction or injection");CHKERRQ(ierr); 559938e4a01SJed Brown PetscFunctionReturn(0); 560938e4a01SJed Brown } 561938e4a01SJed Brown 562e9923e8dSJed Brown #undef __FUNCT__ 563e9923e8dSJed Brown #define __FUNCT__ "SNESFASRestrict" 564e9923e8dSJed Brown /*@ 565e9923e8dSJed Brown SNESFASRestrict - restrict a Vec to the next coarser level 566e9923e8dSJed Brown 567e9923e8dSJed Brown Collective 568e9923e8dSJed Brown 569e9923e8dSJed Brown Input Arguments: 570e9923e8dSJed Brown + fine - SNES from which to restrict 571e9923e8dSJed Brown - Xfine - vector to restrict 572e9923e8dSJed Brown 573e9923e8dSJed Brown Output Arguments: 574e9923e8dSJed Brown . Xcoarse - result of restriction 575e9923e8dSJed Brown 576e9923e8dSJed Brown Level: developer 577e9923e8dSJed Brown 578e9923e8dSJed Brown .seealso: SNESFASSetRestriction(), SNESFASSetInjection() 579e9923e8dSJed Brown @*/ 580e9923e8dSJed Brown PetscErrorCode SNESFASRestrict(SNES fine,Vec Xfine,Vec Xcoarse) 581e9923e8dSJed Brown { 582e9923e8dSJed Brown PetscErrorCode ierr; 583e9923e8dSJed Brown SNES_FAS *fas = (SNES_FAS*)fine->data; 584e9923e8dSJed Brown 585e9923e8dSJed Brown PetscFunctionBegin; 586e9923e8dSJed Brown PetscValidHeaderSpecific(fine,SNES_CLASSID,1); 587e9923e8dSJed Brown PetscValidHeaderSpecific(Xfine,VEC_CLASSID,2); 588e9923e8dSJed Brown PetscValidHeaderSpecific(Xcoarse,VEC_CLASSID,3); 589e9923e8dSJed Brown if (fas->inject) { 590e9923e8dSJed Brown ierr = MatRestrict(fas->inject,Xfine,Xcoarse);CHKERRQ(ierr); 591e9923e8dSJed Brown } else { 592e9923e8dSJed Brown ierr = MatRestrict(fas->restrct,Xfine,Xcoarse);CHKERRQ(ierr); 593e9923e8dSJed Brown ierr = VecPointwiseMult(Xcoarse,fas->rscale,Xcoarse);CHKERRQ(ierr); 594e9923e8dSJed Brown } 595e9923e8dSJed Brown PetscFunctionReturn(0); 596e9923e8dSJed Brown } 597e9923e8dSJed Brown 598e9923e8dSJed Brown #undef __FUNCT__ 5998c40d5fbSBarry Smith #define __FUNCT__ "SNESFASCoarseCorrection" 60039bd7f45SPeter Brune /* 60139bd7f45SPeter Brune 60239bd7f45SPeter Brune Performs the FAS coarse correction as: 60339bd7f45SPeter Brune 60439bd7f45SPeter Brune fine problem: F(x) = 0 60539bd7f45SPeter Brune coarse problem: F^c(x) = b^c 60639bd7f45SPeter Brune 60739bd7f45SPeter Brune b^c = F^c(I^c_fx^f - I^c_fF(x)) 60839bd7f45SPeter Brune 60939bd7f45SPeter Brune */ 6100adebc6cSBarry Smith PetscErrorCode SNESFASCoarseCorrection(SNES snes, Vec X, Vec F, Vec X_new) 6110adebc6cSBarry Smith { 61239bd7f45SPeter Brune PetscErrorCode ierr; 61339bd7f45SPeter Brune Vec X_c, Xo_c, F_c, B_c; 61439bd7f45SPeter Brune SNESConvergedReason reason; 615ab8d36c9SPeter Brune SNES next; 616ab8d36c9SPeter Brune Mat restrct, interpolate; 6170dd27c6cSPeter Brune SNES_FAS *fasc; 6185fd66863SKarl Rupp 61939bd7f45SPeter Brune PetscFunctionBegin; 620ab8d36c9SPeter Brune ierr = SNESFASCycleGetCorrection(snes, &next);CHKERRQ(ierr); 621ab8d36c9SPeter Brune if (next) { 6220dd27c6cSPeter Brune fasc = (SNES_FAS*)next->data; 6230dd27c6cSPeter Brune 624ab8d36c9SPeter Brune ierr = SNESFASCycleGetRestriction(snes, &restrct);CHKERRQ(ierr); 625ab8d36c9SPeter Brune ierr = SNESFASCycleGetInterpolation(snes, &interpolate);CHKERRQ(ierr); 626ab8d36c9SPeter Brune 627ab8d36c9SPeter Brune X_c = next->vec_sol; 628ab8d36c9SPeter Brune Xo_c = next->work[0]; 629ab8d36c9SPeter Brune F_c = next->vec_func; 630ab8d36c9SPeter Brune B_c = next->vec_rhs; 631efe1f98aSPeter Brune 6320dd27c6cSPeter Brune if (fasc->eventinterprestrict) {ierr = PetscLogEventBegin(fasc->eventinterprestrict,0,0,0,0);CHKERRQ(ierr);} 633938e4a01SJed Brown ierr = SNESFASRestrict(snes,X,Xo_c);CHKERRQ(ierr); 634293a7e31SPeter Brune /* restrict the defect */ 635ab8d36c9SPeter Brune ierr = MatRestrict(restrct, F, B_c);CHKERRQ(ierr); 6360dd27c6cSPeter Brune if (fasc->eventinterprestrict) {ierr = PetscLogEventEnd(fasc->eventinterprestrict,0,0,0,0);CHKERRQ(ierr);} 6370dd27c6cSPeter Brune 6380dd27c6cSPeter Brune if (fasc->eventresidual) {ierr = PetscLogEventBegin(fasc->eventresidual,0,0,0,0);CHKERRQ(ierr);} 639ab8d36c9SPeter Brune ierr = SNESComputeFunction(next, Xo_c, F_c);CHKERRQ(ierr); 6400dd27c6cSPeter Brune if (fasc->eventresidual) {ierr = PetscLogEventEnd(fasc->eventresidual,0,0,0,0);CHKERRQ(ierr);} 6410dd27c6cSPeter Brune 6420dd27c6cSPeter Brune /* solve the coarse problem corresponding to F^c(x^c) = b^c = F^c(Rx) - R(F(x) - b) */ 643e4ed7901SPeter Brune ierr = VecCopy(B_c, X_c);CHKERRQ(ierr); 644b9c2fdf1SPeter Brune ierr = VecCopy(F_c, B_c);CHKERRQ(ierr); 645e4ed7901SPeter Brune ierr = VecCopy(X_c, F_c);CHKERRQ(ierr); 646ee78dd50SPeter Brune /* set initial guess of the coarse problem to the projected fine solution */ 647ee78dd50SPeter Brune ierr = VecCopy(Xo_c, X_c);CHKERRQ(ierr); 648c90fad12SPeter Brune 649c90fad12SPeter Brune /* recurse to the next level */ 650e4ed7901SPeter Brune ierr = SNESSetInitialFunction(next, F_c);CHKERRQ(ierr); 651ab8d36c9SPeter Brune ierr = SNESSolve(next, B_c, X_c);CHKERRQ(ierr); 652ab8d36c9SPeter Brune ierr = SNESGetConvergedReason(next,&reason);CHKERRQ(ierr); 653742fe5e2SPeter Brune if (reason < 0 && reason != SNES_DIVERGED_MAX_IT) { 654742fe5e2SPeter Brune snes->reason = SNES_DIVERGED_INNER; 655742fe5e2SPeter Brune PetscFunctionReturn(0); 656742fe5e2SPeter Brune } 657fa9694d7SPeter Brune /* correct as x <- x + I(x^c - Rx)*/ 658fa9694d7SPeter Brune ierr = VecAXPY(X_c, -1.0, Xo_c);CHKERRQ(ierr); 6590dd27c6cSPeter Brune 6600dd27c6cSPeter Brune if (fasc->eventinterprestrict) {ierr = PetscLogEventBegin(fasc->eventinterprestrict,0,0,0,0);CHKERRQ(ierr);} 661ab8d36c9SPeter Brune ierr = MatInterpolateAdd(interpolate, X_c, X, X_new);CHKERRQ(ierr); 6620dd27c6cSPeter Brune if (fasc->eventinterprestrict) {ierr = PetscLogEventEnd(fasc->eventinterprestrict,0,0,0,0);CHKERRQ(ierr);} 663293a7e31SPeter Brune } 66439bd7f45SPeter Brune PetscFunctionReturn(0); 66539bd7f45SPeter Brune } 66639bd7f45SPeter Brune 66739bd7f45SPeter Brune #undef __FUNCT__ 6682cf9d1e8SPeter Brune #define __FUNCT__ "SNESFASCycle_Additive" 66939bd7f45SPeter Brune /* 67039bd7f45SPeter Brune 67139bd7f45SPeter Brune The additive cycle looks like: 67239bd7f45SPeter Brune 67307144faaSPeter Brune xhat = x 67407144faaSPeter Brune xhat = dS(x, b) 67507144faaSPeter Brune x = coarsecorrection(xhat, b_d) 67607144faaSPeter Brune x = x + nu*(xhat - x); 67739bd7f45SPeter Brune (optional) x = uS(x, b) 67839bd7f45SPeter Brune 67939bd7f45SPeter Brune With the coarse RHS (defect correction) as below. 68039bd7f45SPeter Brune 68139bd7f45SPeter Brune */ 6820adebc6cSBarry Smith PetscErrorCode SNESFASCycle_Additive(SNES snes, Vec X) 6830adebc6cSBarry Smith { 68407144faaSPeter Brune Vec F, B, Xhat; 68522c1e704SPeter Brune Vec X_c, Xo_c, F_c, B_c; 68639bd7f45SPeter Brune PetscErrorCode ierr; 68707144faaSPeter Brune SNESConvergedReason reason; 68822c1e704SPeter Brune PetscReal xnorm, fnorm, ynorm; 68922c1e704SPeter Brune PetscBool lssuccess; 690ab8d36c9SPeter Brune SNES next; 691ab8d36c9SPeter Brune Mat restrct, interpolate; 6920dd27c6cSPeter Brune SNES_FAS *fas = (SNES_FAS*)snes->data,*fasc; 6930dd27c6cSPeter Brune 69439bd7f45SPeter Brune PetscFunctionBegin; 695ab8d36c9SPeter Brune ierr = SNESFASCycleGetCorrection(snes, &next);CHKERRQ(ierr); 69639bd7f45SPeter Brune F = snes->vec_func; 69739bd7f45SPeter Brune B = snes->vec_rhs; 698e7f468e7SPeter Brune Xhat = snes->work[1]; 69907144faaSPeter Brune ierr = VecCopy(X, Xhat);CHKERRQ(ierr); 70007144faaSPeter Brune /* recurse first */ 701ab8d36c9SPeter Brune if (next) { 7020dd27c6cSPeter Brune fasc = (SNES_FAS*)next->data; 703ab8d36c9SPeter Brune ierr = SNESFASCycleGetRestriction(snes, &restrct);CHKERRQ(ierr); 704ab8d36c9SPeter Brune ierr = SNESFASCycleGetInterpolation(snes, &interpolate);CHKERRQ(ierr); 7050dd27c6cSPeter Brune if (fas->eventresidual) {ierr = PetscLogEventBegin(fas->eventresidual,0,0,0,0);CHKERRQ(ierr);} 70607144faaSPeter Brune ierr = SNESComputeFunction(snes, Xhat, F);CHKERRQ(ierr); 7070dd27c6cSPeter Brune if (fas->eventresidual) {ierr = PetscLogEventEnd(fas->eventresidual,0,0,0,0);CHKERRQ(ierr);} 708c2a02606SPeter Brune ierr = VecNorm(F, NORM_2, &fnorm);CHKERRQ(ierr); 709ab8d36c9SPeter Brune X_c = next->vec_sol; 710ab8d36c9SPeter Brune Xo_c = next->work[0]; 711ab8d36c9SPeter Brune F_c = next->vec_func; 712ab8d36c9SPeter Brune B_c = next->vec_rhs; 71339bd7f45SPeter Brune 714938e4a01SJed Brown ierr = SNESFASRestrict(snes,Xhat,Xo_c);CHKERRQ(ierr); 71507144faaSPeter Brune /* restrict the defect */ 716ab8d36c9SPeter Brune ierr = MatRestrict(restrct, F, B_c);CHKERRQ(ierr); 71707144faaSPeter Brune 71807144faaSPeter Brune /* solve the coarse problem corresponding to F^c(x^c) = b^c = Rb + F^c(Rx) - RF(x) */ 7190dd27c6cSPeter Brune if (fasc->eventresidual) {ierr = PetscLogEventBegin(fasc->eventresidual,0,0,0,0);CHKERRQ(ierr);} 720ab8d36c9SPeter Brune ierr = SNESComputeFunction(next, Xo_c, F_c);CHKERRQ(ierr); 7210dd27c6cSPeter Brune if (fasc->eventresidual) {ierr = PetscLogEventEnd(fasc->eventresidual,0,0,0,0);CHKERRQ(ierr);} 722e4ed7901SPeter Brune ierr = VecCopy(B_c, X_c);CHKERRQ(ierr); 723b9c2fdf1SPeter Brune ierr = VecCopy(F_c, B_c);CHKERRQ(ierr); 724e4ed7901SPeter Brune ierr = VecCopy(X_c, F_c);CHKERRQ(ierr); 72507144faaSPeter Brune /* set initial guess of the coarse problem to the projected fine solution */ 72607144faaSPeter Brune ierr = VecCopy(Xo_c, X_c);CHKERRQ(ierr); 72707144faaSPeter Brune 72807144faaSPeter Brune /* recurse */ 729e4ed7901SPeter Brune ierr = SNESSetInitialFunction(next, F_c);CHKERRQ(ierr); 730ab8d36c9SPeter Brune ierr = SNESSolve(next, B_c, X_c);CHKERRQ(ierr); 73107144faaSPeter Brune 73207144faaSPeter Brune /* smooth on this level */ 73391f99d7cSPeter Brune ierr = SNESFASDownSmooth_Private(snes, B, X, F, &fnorm);CHKERRQ(ierr); 73407144faaSPeter Brune 735ab8d36c9SPeter Brune ierr = SNESGetConvergedReason(next,&reason);CHKERRQ(ierr); 73607144faaSPeter Brune if (reason < 0 && reason != SNES_DIVERGED_MAX_IT) { 73707144faaSPeter Brune snes->reason = SNES_DIVERGED_INNER; 73807144faaSPeter Brune PetscFunctionReturn(0); 73907144faaSPeter Brune } 74007144faaSPeter Brune 74107144faaSPeter Brune /* correct as x <- x + I(x^c - Rx)*/ 742c68acad4SPeter Brune ierr = VecAYPX(X_c, -1.0, Xo_c);CHKERRQ(ierr); 743ab8d36c9SPeter Brune ierr = MatInterpolate(interpolate, X_c, Xhat);CHKERRQ(ierr); 74407144faaSPeter Brune 745ddebd997SPeter Brune /* additive correction of the coarse direction*/ 746f1c6b773SPeter Brune ierr = SNESLineSearchApply(snes->linesearch, X, F, &fnorm, Xhat);CHKERRQ(ierr); 747f1c6b773SPeter Brune ierr = SNESLineSearchGetSuccess(snes->linesearch, &lssuccess);CHKERRQ(ierr); 7489e764e56SPeter Brune if (!lssuccess) { 7499e764e56SPeter Brune if (++snes->numFailures >= snes->maxFailures) { 7509e764e56SPeter Brune snes->reason = SNES_DIVERGED_LINE_SEARCH; 7519e764e56SPeter Brune PetscFunctionReturn(0); 7529e764e56SPeter Brune } 7539e764e56SPeter Brune } 754b9c2fdf1SPeter Brune ierr = SNESLineSearchGetNorms(snes->linesearch, &xnorm, &snes->norm, &ynorm);CHKERRQ(ierr); 75507144faaSPeter Brune } else { 75691f99d7cSPeter Brune ierr = SNESFASDownSmooth_Private(snes, B, X, F, &snes->norm);CHKERRQ(ierr); 75707144faaSPeter Brune } 75839bd7f45SPeter Brune PetscFunctionReturn(0); 75939bd7f45SPeter Brune } 76039bd7f45SPeter Brune 76139bd7f45SPeter Brune #undef __FUNCT__ 7622cf9d1e8SPeter Brune #define __FUNCT__ "SNESFASCycle_Multiplicative" 76339bd7f45SPeter Brune /* 76439bd7f45SPeter Brune 76539bd7f45SPeter Brune Defines the FAS cycle as: 76639bd7f45SPeter Brune 76739bd7f45SPeter Brune fine problem: F(x) = 0 76839bd7f45SPeter Brune coarse problem: F^c(x) = b^c 76939bd7f45SPeter Brune 77039bd7f45SPeter Brune b^c = F^c(I^c_fx^f - I^c_fF(x)) 77139bd7f45SPeter Brune 77239bd7f45SPeter Brune correction: 77339bd7f45SPeter Brune 77439bd7f45SPeter Brune x = x + I(x^c - Rx) 77539bd7f45SPeter Brune 77639bd7f45SPeter Brune */ 7770adebc6cSBarry Smith PetscErrorCode SNESFASCycle_Multiplicative(SNES snes, Vec X) 7780adebc6cSBarry Smith { 77939bd7f45SPeter Brune 78039bd7f45SPeter Brune PetscErrorCode ierr; 78139bd7f45SPeter Brune Vec F,B; 78239bd7f45SPeter Brune SNES_FAS *fas = (SNES_FAS*)snes->data; 78339bd7f45SPeter Brune 78439bd7f45SPeter Brune PetscFunctionBegin; 78539bd7f45SPeter Brune F = snes->vec_func; 78639bd7f45SPeter Brune B = snes->vec_rhs; 78739bd7f45SPeter Brune /* pre-smooth -- just update using the pre-smoother */ 78891f99d7cSPeter Brune ierr = SNESFASDownSmooth_Private(snes, B, X, F, &snes->norm);CHKERRQ(ierr); 789c90fad12SPeter Brune if (fas->level != 0) { 7908c40d5fbSBarry Smith ierr = SNESFASCoarseCorrection(snes, X, F, X);CHKERRQ(ierr); 79191f99d7cSPeter Brune ierr = SNESFASUpSmooth_Private(snes, B, X, F, &snes->norm);CHKERRQ(ierr); 792fe6f9142SPeter Brune } 793fa9694d7SPeter Brune PetscFunctionReturn(0); 794421d9b32SPeter Brune } 795421d9b32SPeter Brune 796421d9b32SPeter Brune #undef __FUNCT__ 797421d9b32SPeter Brune #define __FUNCT__ "SNESSolve_FAS" 798421d9b32SPeter Brune 799421d9b32SPeter Brune PetscErrorCode SNESSolve_FAS(SNES snes) 800421d9b32SPeter Brune { 801fa9694d7SPeter Brune PetscErrorCode ierr; 802fe6f9142SPeter Brune PetscInt i, maxits; 803ddb5aff1SPeter Brune Vec X, F; 804fe6f9142SPeter Brune PetscReal fnorm; 805b17ce1afSJed Brown SNES_FAS *fas = (SNES_FAS*)snes->data,*ffas; 806b17ce1afSJed Brown DM dm; 807e70c42e5SPeter Brune PetscBool isFine; 808b17ce1afSJed Brown 809421d9b32SPeter Brune PetscFunctionBegin; 810fe6f9142SPeter Brune maxits = snes->max_its; /* maximum number of iterations */ 811fe6f9142SPeter Brune snes->reason = SNES_CONVERGED_ITERATING; 812fa9694d7SPeter Brune X = snes->vec_sol; 813f5a6d4f9SBarry Smith F = snes->vec_func; 814293a7e31SPeter Brune 81518a66777SPeter Brune ierr = SNESFASCycleIsFine(snes, &isFine);CHKERRQ(ierr); 816293a7e31SPeter Brune /*norm setup */ 817fe6f9142SPeter Brune ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr); 818fe6f9142SPeter Brune snes->iter = 0; 819fe6f9142SPeter Brune snes->norm = 0.; 820fe6f9142SPeter Brune ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr); 821e4ed7901SPeter Brune if (!snes->vec_func_init_set) { 8220dd27c6cSPeter Brune if (fas->eventresidual) {ierr = PetscLogEventBegin(fas->eventresidual,0,0,0,0);CHKERRQ(ierr);} 823fe6f9142SPeter Brune ierr = SNESComputeFunction(snes,X,F);CHKERRQ(ierr); 8240dd27c6cSPeter Brune if (fas->eventresidual) {ierr = PetscLogEventEnd(fas->eventresidual,0,0,0,0);CHKERRQ(ierr);} 825fe6f9142SPeter Brune if (snes->domainerror) { 826fe6f9142SPeter Brune snes->reason = SNES_DIVERGED_FUNCTION_DOMAIN; 827fe6f9142SPeter Brune PetscFunctionReturn(0); 828fe6f9142SPeter Brune } 8291aa26658SKarl Rupp } else snes->vec_func_init_set = PETSC_FALSE; 830e4ed7901SPeter Brune 831e4ed7901SPeter Brune if (!snes->norm_init_set) { 832fe6f9142SPeter Brune ierr = VecNorm(F, NORM_2, &fnorm);CHKERRQ(ierr); /* fnorm <- ||F|| */ 833189a9710SBarry Smith if (PetscIsInfOrNanReal(fnorm)) { 834189a9710SBarry Smith snes->reason = SNES_DIVERGED_FNORM_NAN; 835189a9710SBarry Smith PetscFunctionReturn(0); 836189a9710SBarry Smith } 837fe6f9142SPeter Brune ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr); 838e4ed7901SPeter Brune } else { 839e4ed7901SPeter Brune fnorm = snes->norm_init; 840e4ed7901SPeter Brune snes->norm_init_set = PETSC_FALSE; 841e4ed7901SPeter Brune } 842e4ed7901SPeter Brune 843fe6f9142SPeter Brune snes->norm = fnorm; 844fe6f9142SPeter Brune ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr); 845a71f0d7dSBarry Smith ierr = SNESLogConvergenceHistory(snes,fnorm,0);CHKERRQ(ierr); 846fe6f9142SPeter Brune ierr = SNESMonitor(snes,0,fnorm);CHKERRQ(ierr); 847fe6f9142SPeter Brune 848fe6f9142SPeter Brune /* set parameter for default relative tolerance convergence test */ 849fe6f9142SPeter Brune snes->ttol = fnorm*snes->rtol; 850fe6f9142SPeter Brune /* test convergence */ 851fe6f9142SPeter Brune ierr = (*snes->ops->converged)(snes,0,0.0,0.0,fnorm,&snes->reason,snes->cnvP);CHKERRQ(ierr); 852fe6f9142SPeter Brune if (snes->reason) PetscFunctionReturn(0); 853e4ed7901SPeter Brune 854b17ce1afSJed Brown 855b9c2fdf1SPeter Brune if (isFine) { 856b9c2fdf1SPeter Brune /* propagate scale-dependent data up the hierarchy */ 857b17ce1afSJed Brown ierr = SNESGetDM(snes,&dm);CHKERRQ(ierr); 858b17ce1afSJed Brown for (ffas=fas; ffas->next; ffas=(SNES_FAS*)ffas->next->data) { 859b17ce1afSJed Brown DM dmcoarse; 860b17ce1afSJed Brown ierr = SNESGetDM(ffas->next,&dmcoarse);CHKERRQ(ierr); 861b17ce1afSJed Brown ierr = DMRestrict(dm,ffas->restrct,ffas->rscale,ffas->inject,dmcoarse);CHKERRQ(ierr); 862b17ce1afSJed Brown dm = dmcoarse; 863b17ce1afSJed Brown } 864b9c2fdf1SPeter Brune } 865b17ce1afSJed Brown 866fe6f9142SPeter Brune for (i = 0; i < maxits; i++) { 867fe6f9142SPeter Brune /* Call general purpose update function */ 868646217ecSPeter Brune 869fe6f9142SPeter Brune if (snes->ops->update) { 870fe6f9142SPeter Brune ierr = (*snes->ops->update)(snes, snes->iter);CHKERRQ(ierr); 871fe6f9142SPeter Brune } 87207144faaSPeter Brune if (fas->fastype == SNES_FAS_MULTIPLICATIVE) { 87391f99d7cSPeter Brune ierr = SNESFASCycle_Multiplicative(snes, X);CHKERRQ(ierr); 87407144faaSPeter Brune } else { 87591f99d7cSPeter Brune ierr = SNESFASCycle_Additive(snes, X);CHKERRQ(ierr); 87607144faaSPeter Brune } 877742fe5e2SPeter Brune 878742fe5e2SPeter Brune /* check for FAS cycle divergence */ 8791aa26658SKarl Rupp if (snes->reason != SNES_CONVERGED_ITERATING) PetscFunctionReturn(0); 880b9c2fdf1SPeter Brune 881c90fad12SPeter Brune /* Monitor convergence */ 882c90fad12SPeter Brune ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr); 883c90fad12SPeter Brune snes->iter = i+1; 884c90fad12SPeter Brune ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr); 885a71f0d7dSBarry Smith ierr = SNESLogConvergenceHistory(snes,snes->norm,0);CHKERRQ(ierr); 886c90fad12SPeter Brune ierr = SNESMonitor(snes,snes->iter,snes->norm);CHKERRQ(ierr); 887c90fad12SPeter Brune /* Test for convergence */ 88866585501SPeter Brune if (isFine) { 889b9c2fdf1SPeter Brune ierr = (*snes->ops->converged)(snes,snes->iter,0.0,0.0,snes->norm,&snes->reason,snes->cnvP);CHKERRQ(ierr); 890c90fad12SPeter Brune if (snes->reason) break; 891fe6f9142SPeter Brune } 89266585501SPeter Brune } 893fe6f9142SPeter Brune if (i == maxits) { 894fe6f9142SPeter Brune ierr = PetscInfo1(snes, "Maximum number of iterations has been reached: %D\n", maxits);CHKERRQ(ierr); 895fe6f9142SPeter Brune if (!snes->reason) snes->reason = SNES_DIVERGED_MAX_IT; 896fe6f9142SPeter Brune } 897421d9b32SPeter Brune PetscFunctionReturn(0); 898421d9b32SPeter Brune } 899