1421d9b32SPeter Brune /* Defines the basic SNES object */ 26038b46bSPeter Brune #include <../src/snes/impls/fas/fasimpls.h> /*I "petscsnesfas.h" I*/ 3421d9b32SPeter Brune 407144faaSPeter Brune const char *SNESFASTypes[] = {"MULTIPLICATIVE","ADDITIVE","SNESFASType","SNES_FAS",0}; 507144faaSPeter Brune 6421d9b32SPeter Brune 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 19*d3bc2379SPeter Brune The nonlinear problem is solved by correction using coarse versions 20*d3bc2379SPeter Brune of the nonlinear problem. This problem is perturbed so that a projected 21*d3bc2379SPeter Brune solution of the fine problem elicits no correction from the coarse problem. 22*d3bc2379SPeter Brune 23*d3bc2379SPeter Brune Options Database: 24*d3bc2379SPeter Brune + -snes_fas_levels - The number of levels 25*d3bc2379SPeter Brune . -snes_fas_cycles<1> - The number of cycles -- 1 for V, 2 for W 26*d3bc2379SPeter Brune . -snes_fas_type<additive, multiplicative> - Additive or multiplicative cycle 27*d3bc2379SPeter Brune . -snes_fas_galerkin<PETSC_FALSE> - Form coarse problems by projection back upon the fine problem 28*d3bc2379SPeter Brune . -snes_fas_smoothup<1> - The number of iterations of the post-smoother 29*d3bc2379SPeter Brune . -snes_fas_smoothdown<1> - The number of iterations of the pre-smoother 30*d3bc2379SPeter Brune . -snes_fas_monitor - Monitor progress of all of the levels 31*d3bc2379SPeter Brune . -fas_levels_snes_ - SNES options for all smoothers 32*d3bc2379SPeter Brune . -fas_levels_cycle_snes - SNES options for all cycles 33*d3bc2379SPeter Brune . -fas_levels_i_snes_ - SNES options for the smoothers on level i 34*d3bc2379SPeter Brune . -fas_levels_i_cycle_snes - SNES options for the cycle on level i 35*d3bc2379SPeter Brune - -fas_coarse_snes_ - SNES options for the coarsest smoother 36*d3bc2379SPeter Brune 37*d3bc2379SPeter Brune Notes: 38*d3bc2379SPeter Brune The organization of the FAS solver is slightly different from the organization of PCMG 39*d3bc2379SPeter Brune As each level has smoother SNES instances(down and potentially up) and a cycle SNES instance. 40*d3bc2379SPeter Brune The cycle SNES instance may be used for monitoring convergence on a particular level. 411fbfccc6SJed Brown 421fbfccc6SJed Brown Level: advanced 431fbfccc6SJed Brown 44*d3bc2379SPeter 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; 88efe1f98aSPeter Brune PetscFunctionReturn(0); 89efe1f98aSPeter Brune } 90efe1f98aSPeter Brune 91421d9b32SPeter Brune #undef __FUNCT__ 92421d9b32SPeter Brune #define __FUNCT__ "SNESReset_FAS" 93421d9b32SPeter Brune PetscErrorCode SNESReset_FAS(SNES snes) 94421d9b32SPeter Brune { 9577df8cc4SPeter Brune PetscErrorCode ierr = 0; 96421d9b32SPeter Brune SNES_FAS * fas = (SNES_FAS *)snes->data; 97421d9b32SPeter Brune 98421d9b32SPeter Brune PetscFunctionBegin; 99ab8d36c9SPeter Brune if (fas->smoothu != fas->smoothd) { 100ab8d36c9SPeter Brune ierr = SNESDestroy(&fas->smoothu);CHKERRQ(ierr); 101ab8d36c9SPeter Brune ierr = SNESDestroy(&fas->smoothd);CHKERRQ(ierr); 102ab8d36c9SPeter Brune } else { 103ab8d36c9SPeter Brune ierr = SNESDestroy(&fas->smoothd);CHKERRQ(ierr); 104ab8d36c9SPeter Brune fas->smoothu = PETSC_NULL; 105ab8d36c9SPeter Brune } 1063dccd265SPeter Brune ierr = MatDestroy(&fas->inject);CHKERRQ(ierr); 107bccf9bb3SJed Brown ierr = MatDestroy(&fas->interpolate);CHKERRQ(ierr); 108bccf9bb3SJed Brown ierr = MatDestroy(&fas->restrct);CHKERRQ(ierr); 109bccf9bb3SJed Brown ierr = VecDestroy(&fas->rscale);CHKERRQ(ierr); 110742fe5e2SPeter Brune if (fas->next) ierr = SNESReset(fas->next);CHKERRQ(ierr); 11122c1e704SPeter Brune 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); 125421d9b32SPeter Brune if (fas->next) ierr = SNESDestroy(&fas->next);CHKERRQ(ierr); 126421d9b32SPeter Brune ierr = PetscFree(fas);CHKERRQ(ierr); 127ee1fd11aSPeter Brune 128421d9b32SPeter Brune PetscFunctionReturn(0); 129421d9b32SPeter Brune } 130421d9b32SPeter Brune 131421d9b32SPeter Brune #undef __FUNCT__ 132421d9b32SPeter Brune #define __FUNCT__ "SNESSetUp_FAS" 133421d9b32SPeter Brune PetscErrorCode SNESSetUp_FAS(SNES snes) 134421d9b32SPeter Brune { 13548bfdf8aSPeter Brune SNES_FAS *fas = (SNES_FAS *) snes->data; 136421d9b32SPeter Brune PetscErrorCode ierr; 137efe1f98aSPeter Brune VecScatter injscatter; 138d1adcc6fSPeter Brune PetscInt dm_levels; 1393dccd265SPeter Brune Vec vec_sol, vec_func, vec_sol_update, vec_rhs; /* preserve these if they're set through the reset */ 140ab8d36c9SPeter Brune SNES next; 141ab8d36c9SPeter Brune PetscBool isFine; 142421d9b32SPeter Brune PetscFunctionBegin; 143eff52c0eSPeter Brune 144ab8d36c9SPeter Brune ierr = SNESFASCycleIsFine(snes, &isFine);CHKERRQ(ierr); 145ab8d36c9SPeter Brune if (fas->usedmfornumberoflevels && isFine) { 146d1adcc6fSPeter Brune ierr = DMGetRefineLevel(snes->dm,&dm_levels);CHKERRQ(ierr); 147d1adcc6fSPeter Brune dm_levels++; 148cc05f883SPeter Brune if (dm_levels > fas->levels) { 1492e8ce248SJed Brown /* we don't want the solution and func vectors to be destroyed in the SNESReset when it's called in SNESFASSetLevels_FAS*/ 1503dccd265SPeter Brune vec_sol = snes->vec_sol; 1513dccd265SPeter Brune vec_func = snes->vec_func; 1523dccd265SPeter Brune vec_sol_update = snes->vec_sol_update; 1533dccd265SPeter Brune vec_rhs = snes->vec_rhs; 1543dccd265SPeter Brune snes->vec_sol = PETSC_NULL; 1553dccd265SPeter Brune snes->vec_func = PETSC_NULL; 1563dccd265SPeter Brune snes->vec_sol_update = PETSC_NULL; 1573dccd265SPeter Brune snes->vec_rhs = PETSC_NULL; 1583dccd265SPeter Brune 1593dccd265SPeter Brune /* reset the number of levels */ 160d1adcc6fSPeter Brune ierr = SNESFASSetLevels(snes,dm_levels,PETSC_NULL);CHKERRQ(ierr); 161cc05f883SPeter Brune ierr = SNESSetFromOptions(snes);CHKERRQ(ierr); 1623dccd265SPeter Brune 1633dccd265SPeter Brune snes->vec_sol = vec_sol; 1643dccd265SPeter Brune snes->vec_func = vec_func; 1653dccd265SPeter Brune snes->vec_rhs = vec_rhs; 1663dccd265SPeter Brune snes->vec_sol_update = vec_sol_update; 167d1adcc6fSPeter Brune } 168d1adcc6fSPeter Brune } 169ab8d36c9SPeter Brune ierr = SNESFASCycleGetCorrection(snes, &next);CHKERRQ(ierr); 170ab8d36c9SPeter Brune if (!isFine) snes->gridsequence = 0; /* no grid sequencing inside the multigrid hierarchy! */ 1713dccd265SPeter Brune 17207144faaSPeter Brune if (fas->fastype == SNES_FAS_MULTIPLICATIVE) { 173fde0ff24SPeter Brune ierr = SNESDefaultGetWork(snes, 4);CHKERRQ(ierr); /* work vectors used for intergrid transfers */ 17407144faaSPeter Brune } else { 175ddebd997SPeter Brune ierr = SNESDefaultGetWork(snes, 4);CHKERRQ(ierr); /* work vectors used for intergrid transfers */ 17607144faaSPeter Brune } 177cc05f883SPeter Brune 178ab8d36c9SPeter Brune /* set up the smoothers if they haven't already been set up */ 179ab8d36c9SPeter Brune if (!fas->smoothd) { 180ab8d36c9SPeter Brune ierr = SNESFASCycleCreateSmoother_Private(snes, &fas->smoothd);CHKERRQ(ierr); 181ab8d36c9SPeter Brune } 182ab8d36c9SPeter Brune 18379d9a41aSPeter Brune if (snes->dm) { 184ab8d36c9SPeter Brune /* set the smoother DMs properly */ 185ab8d36c9SPeter Brune if (fas->smoothu) ierr = SNESSetDM(fas->smoothu, snes->dm);CHKERRQ(ierr); 186ab8d36c9SPeter Brune ierr = SNESSetDM(fas->smoothd, snes->dm);CHKERRQ(ierr); 18779d9a41aSPeter Brune /* construct EVERYTHING from the DM -- including the progressive set of smoothers */ 188ab8d36c9SPeter Brune if (next) { 18979d9a41aSPeter Brune /* for now -- assume the DM and the evaluation functions have been set externally */ 190ab8d36c9SPeter Brune if (!next->dm) { 191ab8d36c9SPeter Brune ierr = DMCoarsen(snes->dm, ((PetscObject)next)->comm, &next->dm);CHKERRQ(ierr); 192ab8d36c9SPeter Brune ierr = SNESSetDM(next, next->dm);CHKERRQ(ierr); 19379d9a41aSPeter Brune } 19479d9a41aSPeter Brune /* set the interpolation and restriction from the DM */ 19579d9a41aSPeter Brune if (!fas->interpolate) { 196ab8d36c9SPeter Brune ierr = DMCreateInterpolation(next->dm, snes->dm, &fas->interpolate, &fas->rscale);CHKERRQ(ierr); 197bccf9bb3SJed Brown if (!fas->restrct) { 198bccf9bb3SJed Brown ierr = PetscObjectReference((PetscObject)fas->interpolate);CHKERRQ(ierr); 19979d9a41aSPeter Brune fas->restrct = fas->interpolate; 20079d9a41aSPeter Brune } 201bccf9bb3SJed Brown } 20279d9a41aSPeter Brune /* set the injection from the DM */ 20379d9a41aSPeter Brune if (!fas->inject) { 204ab8d36c9SPeter Brune ierr = DMCreateInjection(next->dm, snes->dm, &injscatter);CHKERRQ(ierr); 20579d9a41aSPeter Brune ierr = MatCreateScatter(((PetscObject)snes)->comm, injscatter, &fas->inject);CHKERRQ(ierr); 20679d9a41aSPeter Brune ierr = VecScatterDestroy(&injscatter);CHKERRQ(ierr); 20779d9a41aSPeter Brune } 20879d9a41aSPeter Brune } 20979d9a41aSPeter Brune } 21079d9a41aSPeter Brune /*pass the smoother, function, and jacobian up to the next level if it's not user set already */ 21179d9a41aSPeter Brune 21279d9a41aSPeter Brune if (fas->galerkin) { 213ab8d36c9SPeter Brune if (next) 214ab8d36c9SPeter Brune ierr = SNESSetFunction(next, PETSC_NULL, SNESFASGalerkinDefaultFunction, next);CHKERRQ(ierr); 215ab8d36c9SPeter Brune if (fas->smoothd && fas->level != fas->levels - 1) ierr = SNESSetFunction(fas->smoothd, PETSC_NULL, SNESFASGalerkinDefaultFunction, snes);CHKERRQ(ierr); 216ab8d36c9SPeter Brune if (fas->smoothu && fas->level != fas->levels - 1) ierr = SNESSetFunction(fas->smoothu, PETSC_NULL, SNESFASGalerkinDefaultFunction, snes);CHKERRQ(ierr); 21779d9a41aSPeter Brune } 21879d9a41aSPeter Brune 219d06165b7SPeter Brune /* set the smoothers up here so that precedence is taken for instance-specific options over the whole-solver options */ 220d06165b7SPeter Brune if(fas->smoothu) ierr = SNESSetFromOptions(fas->smoothu);CHKERRQ(ierr); 221d06165b7SPeter Brune if(fas->smoothd) ierr = SNESSetFromOptions(fas->smoothd);CHKERRQ(ierr); 222d06165b7SPeter Brune 223ab8d36c9SPeter Brune if (next) { 22479d9a41aSPeter Brune /* gotta set up the solution vector for this to work */ 225ab8d36c9SPeter Brune if (!next->vec_sol) {ierr = SNESFASCreateCoarseVec(snes,&next->vec_sol);CHKERRQ(ierr);} 226ab8d36c9SPeter Brune if (!next->vec_rhs) {ierr = SNESFASCreateCoarseVec(snes,&next->vec_rhs);CHKERRQ(ierr);} 227ab8d36c9SPeter Brune ierr = SNESSetUp(next);CHKERRQ(ierr); 22879d9a41aSPeter Brune } 2296273346dSPeter Brune /* setup FAS work vectors */ 2306273346dSPeter Brune if (fas->galerkin) { 2316273346dSPeter Brune ierr = VecDuplicate(snes->vec_sol, &fas->Xg);CHKERRQ(ierr); 2326273346dSPeter Brune ierr = VecDuplicate(snes->vec_sol, &fas->Fg);CHKERRQ(ierr); 2336273346dSPeter Brune } 234421d9b32SPeter Brune PetscFunctionReturn(0); 235421d9b32SPeter Brune } 236421d9b32SPeter Brune 237421d9b32SPeter Brune #undef __FUNCT__ 238421d9b32SPeter Brune #define __FUNCT__ "SNESSetFromOptions_FAS" 239421d9b32SPeter Brune PetscErrorCode SNESSetFromOptions_FAS(SNES snes) 240421d9b32SPeter Brune { 241ee78dd50SPeter Brune SNES_FAS *fas = (SNES_FAS *) snes->data; 242ee78dd50SPeter Brune PetscInt levels = 1; 243162d76ddSPeter Brune PetscBool flg, upflg, downflg, monflg, galerkinflg; 244421d9b32SPeter Brune PetscErrorCode ierr; 245ee78dd50SPeter Brune char monfilename[PETSC_MAX_PATH_LEN]; 24607144faaSPeter Brune SNESFASType fastype; 247fde0ff24SPeter Brune const char *optionsprefix; 248f1c6b773SPeter Brune SNESLineSearch linesearch; 24966585501SPeter Brune PetscInt m, n_up, n_down; 250ab8d36c9SPeter Brune SNES next; 251ab8d36c9SPeter Brune PetscBool isFine; 252421d9b32SPeter Brune 253421d9b32SPeter Brune PetscFunctionBegin; 254ab8d36c9SPeter Brune ierr = SNESFASCycleIsFine(snes, &isFine);CHKERRQ(ierr); 255c90fad12SPeter Brune ierr = PetscOptionsHead("SNESFAS Options-----------------------------------");CHKERRQ(ierr); 256ee78dd50SPeter Brune 257ab8d36c9SPeter Brune /* number of levels -- only process most options on the finest level */ 258ab8d36c9SPeter Brune if (isFine) { 259ee78dd50SPeter Brune ierr = PetscOptionsInt("-snes_fas_levels", "Number of Levels", "SNESFASSetLevels", levels, &levels, &flg);CHKERRQ(ierr); 260c732cbdbSBarry Smith if (!flg && snes->dm) { 261c732cbdbSBarry Smith ierr = DMGetRefineLevel(snes->dm,&levels);CHKERRQ(ierr); 262c732cbdbSBarry Smith levels++; 263d1adcc6fSPeter Brune fas->usedmfornumberoflevels = PETSC_TRUE; 264c732cbdbSBarry Smith } 265ee78dd50SPeter Brune ierr = SNESFASSetLevels(snes, levels, PETSC_NULL);CHKERRQ(ierr); 26607144faaSPeter Brune fastype = fas->fastype; 26707144faaSPeter Brune ierr = PetscOptionsEnum("-snes_fas_type","FAS correction type","SNESFASSetType",SNESFASTypes,(PetscEnum)fastype,(PetscEnum*)&fastype,&flg);CHKERRQ(ierr); 26807144faaSPeter Brune if (flg) { 26907144faaSPeter Brune ierr = SNESFASSetType(snes, fastype);CHKERRQ(ierr); 27007144faaSPeter Brune } 271ee78dd50SPeter Brune 272fde0ff24SPeter Brune ierr = SNESGetOptionsPrefix(snes, &optionsprefix);CHKERRQ(ierr); 273ab8d36c9SPeter Brune ierr = PetscOptionsInt("-snes_fas_cycles","Number of cycles","SNESFASSetCycles",fas->n_cycles,&m,&flg);CHKERRQ(ierr); 274ab8d36c9SPeter Brune if (flg) { 275ab8d36c9SPeter Brune ierr = SNESFASSetCycles(snes, m);CHKERRQ(ierr); 276fde0ff24SPeter Brune } 277fde0ff24SPeter Brune 278ab8d36c9SPeter Brune ierr = PetscOptionsBool("-snes_fas_galerkin", "Form coarse problems with Galerkin","SNESFASSetGalerkin",fas->galerkin,&galerkinflg,&flg);CHKERRQ(ierr); 279ab8d36c9SPeter Brune if (flg) { 280ab8d36c9SPeter Brune ierr = SNESFASSetGalerkin(snes, galerkinflg);CHKERRQ(ierr); 281ab8d36c9SPeter Brune } 282ee78dd50SPeter Brune 28366585501SPeter Brune ierr = PetscOptionsInt("-snes_fas_smoothup","Number of post-smoothing steps","SNESFASSetNumberSmoothUp",fas->max_up_it,&n_up,&upflg);CHKERRQ(ierr); 284162d76ddSPeter Brune 28566585501SPeter Brune ierr = PetscOptionsInt("-snes_fas_smoothdown","Number of pre-smoothing steps","SNESFASSetNumberSmoothDown",fas->max_down_it,&n_down,&downflg);CHKERRQ(ierr); 286162d76ddSPeter Brune 287c8c899caSPeter Brune ierr = PetscOptionsString("-snes_fas_monitor","Monitor FAS progress","SNESFASSetMonitor","stdout",monfilename,PETSC_MAX_PATH_LEN,&monflg);CHKERRQ(ierr); 288c8c899caSPeter Brune if (monflg) ierr = SNESFASSetMonitor(snes, PETSC_TRUE);CHKERRQ(ierr); 289ab8d36c9SPeter Brune } 290ee78dd50SPeter Brune 291421d9b32SPeter Brune ierr = PetscOptionsTail();CHKERRQ(ierr); 2928cc86e31SPeter Brune /* setup from the determined types if there is no pointwise procedure or smoother defined */ 293162d76ddSPeter Brune if (upflg) { 29466585501SPeter Brune ierr = SNESFASSetNumberSmoothUp(snes,n_up);CHKERRQ(ierr); 295162d76ddSPeter Brune } 296162d76ddSPeter Brune if (downflg) { 29766585501SPeter Brune ierr = SNESFASSetNumberSmoothDown(snes,n_down);CHKERRQ(ierr); 298162d76ddSPeter Brune } 299eff52c0eSPeter Brune 3009e764e56SPeter Brune /* set up the default line search for coarse grid corrections */ 3019e764e56SPeter Brune if (fas->fastype == SNES_FAS_ADDITIVE) { 3029e764e56SPeter Brune if (!snes->linesearch) { 303f1c6b773SPeter Brune ierr = SNESGetSNESLineSearch(snes, &linesearch);CHKERRQ(ierr); 304f1c6b773SPeter Brune ierr = SNESLineSearchSetType(linesearch, SNES_LINESEARCH_L2);CHKERRQ(ierr); 3059e764e56SPeter Brune } 3069e764e56SPeter Brune } 3079e764e56SPeter Brune 308ab8d36c9SPeter Brune ierr = SNESFASCycleGetCorrection(snes, &next);CHKERRQ(ierr); 309ee78dd50SPeter Brune /* recursive option setting for the smoothers */ 310ab8d36c9SPeter Brune if (next) {ierr = SNESSetFromOptions(next);CHKERRQ(ierr);} 311421d9b32SPeter Brune PetscFunctionReturn(0); 312421d9b32SPeter Brune } 313421d9b32SPeter Brune 314421d9b32SPeter Brune #undef __FUNCT__ 315421d9b32SPeter Brune #define __FUNCT__ "SNESView_FAS" 316421d9b32SPeter Brune PetscErrorCode SNESView_FAS(SNES snes, PetscViewer viewer) 317421d9b32SPeter Brune { 318421d9b32SPeter Brune SNES_FAS *fas = (SNES_FAS *) snes->data; 319ab8d36c9SPeter Brune PetscBool isFine, iascii; 320ab8d36c9SPeter Brune PetscInt i; 321421d9b32SPeter Brune PetscErrorCode ierr; 322ab8d36c9SPeter Brune SNES smoothu, smoothd, levelsnes; 323421d9b32SPeter Brune 324421d9b32SPeter Brune PetscFunctionBegin; 325ab8d36c9SPeter Brune ierr = SNESFASCycleIsFine(snes, &isFine);CHKERRQ(ierr); 326ab8d36c9SPeter Brune if (isFine) { 327421d9b32SPeter Brune ierr = PetscTypeCompare((PetscObject) viewer, PETSCVIEWERASCII, &iascii);CHKERRQ(ierr); 328421d9b32SPeter Brune if (iascii) { 329ab8d36c9SPeter Brune ierr = PetscViewerASCIIPrintf(viewer, "FAS: type is %s, levels=%D, cycles=%D\n", SNESFASTypes[fas->fastype], fas->levels, fas->n_cycles);CHKERRQ(ierr); 330ab8d36c9SPeter Brune if (fas->galerkin) { 331ab8d36c9SPeter Brune ierr = PetscViewerASCIIPrintf(viewer," Using Galerkin computed coarse grid function evaluation\n");CHKERRQ(ierr); 332421d9b32SPeter Brune } else { 333ab8d36c9SPeter Brune ierr = PetscViewerASCIIPrintf(viewer," Not using Galerkin computed coarse grid function evaluation\n");CHKERRQ(ierr); 334421d9b32SPeter Brune } 335ab8d36c9SPeter Brune for (i=0; i<fas->levels; i++) { 336ab8d36c9SPeter Brune ierr = SNESFASGetCycleSNES(snes, i, &levelsnes);CHKERRQ(ierr); 337ab8d36c9SPeter Brune ierr = SNESFASCycleGetSmootherUp(levelsnes, &smoothu);CHKERRQ(ierr); 338ab8d36c9SPeter Brune ierr = SNESFASCycleGetSmootherDown(levelsnes, &smoothd);CHKERRQ(ierr); 339ab8d36c9SPeter Brune if (!i) { 340ab8d36c9SPeter Brune ierr = PetscViewerASCIIPrintf(viewer,"Coarse grid solver -- level %D -------------------------------\n",i);CHKERRQ(ierr); 341421d9b32SPeter Brune } else { 342ab8d36c9SPeter Brune ierr = PetscViewerASCIIPrintf(viewer,"Down solver (pre-smoother) on level %D -------------------------------\n",i);CHKERRQ(ierr); 343421d9b32SPeter Brune } 344ab8d36c9SPeter Brune ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); 345ab8d36c9SPeter Brune ierr = SNESView(smoothd,viewer);CHKERRQ(ierr); 346ab8d36c9SPeter Brune ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); 347ab8d36c9SPeter Brune if (i && (smoothd == smoothu)) { 348ab8d36c9SPeter Brune ierr = PetscViewerASCIIPrintf(viewer,"Up solver (post-smoother) same as down solver (pre-smoother)\n");CHKERRQ(ierr); 349ab8d36c9SPeter Brune } else if (i) { 350ab8d36c9SPeter Brune ierr = PetscViewerASCIIPrintf(viewer,"Up solver (post-smoother) on level %D -------------------------------\n",i);CHKERRQ(ierr); 351ab8d36c9SPeter Brune ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); 352ab8d36c9SPeter Brune ierr = SNESView(smoothu,viewer);CHKERRQ(ierr); 353ab8d36c9SPeter Brune ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); 354ab8d36c9SPeter Brune } 355ab8d36c9SPeter Brune } 356421d9b32SPeter Brune } else { 357421d9b32SPeter Brune SETERRQ1(((PetscObject)snes)->comm,PETSC_ERR_SUP,"Viewer type %s not supported for SNESFAS",((PetscObject)viewer)->type_name); 358421d9b32SPeter Brune } 359ab8d36c9SPeter Brune } 360421d9b32SPeter Brune PetscFunctionReturn(0); 361421d9b32SPeter Brune } 362421d9b32SPeter Brune 363421d9b32SPeter Brune #undef __FUNCT__ 36439bd7f45SPeter Brune #define __FUNCT__ "FASDownSmooth" 36539bd7f45SPeter Brune /* 36639bd7f45SPeter Brune Defines the action of the downsmoother 36739bd7f45SPeter Brune */ 36839bd7f45SPeter Brune PetscErrorCode FASDownSmooth(SNES snes, Vec B, Vec X, Vec F){ 36939bd7f45SPeter Brune PetscErrorCode ierr = 0; 370742fe5e2SPeter Brune SNESConvergedReason reason; 371ab8d36c9SPeter Brune Vec FPC; 372ab8d36c9SPeter Brune SNES smoothd; 373421d9b32SPeter Brune PetscFunctionBegin; 374ab8d36c9SPeter Brune ierr = SNESFASCycleGetSmootherDown(snes, &smoothd);CHKERRQ(ierr); 375ab8d36c9SPeter Brune ierr = SNESSolve(smoothd, B, X);CHKERRQ(ierr); 376742fe5e2SPeter Brune /* check convergence reason for the smoother */ 377ab8d36c9SPeter Brune ierr = SNESGetConvergedReason(smoothd,&reason);CHKERRQ(ierr); 378e70c42e5SPeter Brune if (reason < 0 && !(reason == SNES_DIVERGED_MAX_IT || reason == SNES_DIVERGED_LOCAL_MIN)) { 379742fe5e2SPeter Brune snes->reason = SNES_DIVERGED_INNER; 380742fe5e2SPeter Brune PetscFunctionReturn(0); 381742fe5e2SPeter Brune } 382ab8d36c9SPeter Brune ierr = SNESGetFunction(smoothd, &FPC, PETSC_NULL, PETSC_NULL);CHKERRQ(ierr); 3834b32a720SPeter Brune ierr = VecCopy(FPC, F);CHKERRQ(ierr); 38439bd7f45SPeter Brune PetscFunctionReturn(0); 38539bd7f45SPeter Brune } 38639bd7f45SPeter Brune 38739bd7f45SPeter Brune 38839bd7f45SPeter Brune #undef __FUNCT__ 38939bd7f45SPeter Brune #define __FUNCT__ "FASUpSmooth" 39039bd7f45SPeter Brune /* 39107144faaSPeter Brune Defines the action of the upsmoother 39239bd7f45SPeter Brune */ 39339bd7f45SPeter Brune PetscErrorCode FASUpSmooth (SNES snes, Vec B, Vec X, Vec F) { 39439bd7f45SPeter Brune PetscErrorCode ierr = 0; 39539bd7f45SPeter Brune SNESConvergedReason reason; 396ab8d36c9SPeter Brune Vec FPC; 397ab8d36c9SPeter Brune SNES smoothu; 39839bd7f45SPeter Brune PetscFunctionBegin; 399ab8d36c9SPeter Brune 400ab8d36c9SPeter Brune ierr = SNESFASCycleGetSmootherUp(snes, &smoothu);CHKERRQ(ierr); 401ab8d36c9SPeter Brune ierr = SNESSolve(smoothu, B, X);CHKERRQ(ierr); 40239bd7f45SPeter Brune /* check convergence reason for the smoother */ 403ab8d36c9SPeter Brune ierr = SNESGetConvergedReason(smoothu,&reason);CHKERRQ(ierr); 40439bd7f45SPeter Brune if (reason < 0 && reason != SNES_DIVERGED_MAX_IT) { 40539bd7f45SPeter Brune snes->reason = SNES_DIVERGED_INNER; 40639bd7f45SPeter Brune PetscFunctionReturn(0); 40739bd7f45SPeter Brune } 408ab8d36c9SPeter Brune ierr = SNESGetFunction(smoothu, &FPC, PETSC_NULL, PETSC_NULL);CHKERRQ(ierr); 4094b32a720SPeter Brune ierr = VecCopy(FPC, F);CHKERRQ(ierr); 41039bd7f45SPeter Brune PetscFunctionReturn(0); 41139bd7f45SPeter Brune } 41239bd7f45SPeter Brune 41339bd7f45SPeter Brune #undef __FUNCT__ 414938e4a01SJed Brown #define __FUNCT__ "SNESFASCreateCoarseVec" 415938e4a01SJed Brown /*@ 416938e4a01SJed Brown SNESFASCreateCoarseVec - create Vec corresponding to a state vector on one level coarser than current level 417938e4a01SJed Brown 418938e4a01SJed Brown Collective 419938e4a01SJed Brown 420938e4a01SJed Brown Input Arguments: 421938e4a01SJed Brown . snes - SNESFAS 422938e4a01SJed Brown 423938e4a01SJed Brown Output Arguments: 424938e4a01SJed Brown . Xcoarse - vector on level one coarser than snes 425938e4a01SJed Brown 426938e4a01SJed Brown Level: developer 427938e4a01SJed Brown 428938e4a01SJed Brown .seealso: SNESFASSetRestriction(), SNESFASRestrict() 429938e4a01SJed Brown @*/ 430938e4a01SJed Brown PetscErrorCode SNESFASCreateCoarseVec(SNES snes,Vec *Xcoarse) 431938e4a01SJed Brown { 432938e4a01SJed Brown PetscErrorCode ierr; 433938e4a01SJed Brown SNES_FAS *fas = (SNES_FAS*)snes->data; 434938e4a01SJed Brown 435938e4a01SJed Brown PetscFunctionBegin; 436938e4a01SJed Brown if (fas->rscale) {ierr = VecDuplicate(fas->rscale,Xcoarse);CHKERRQ(ierr);} 437938e4a01SJed Brown else if (fas->inject) {ierr = MatGetVecs(fas->inject,Xcoarse,PETSC_NULL);CHKERRQ(ierr);} 438938e4a01SJed Brown else SETERRQ(((PetscObject)snes)->comm,PETSC_ERR_ARG_WRONGSTATE,"Must set restriction or injection");CHKERRQ(ierr); 439938e4a01SJed Brown PetscFunctionReturn(0); 440938e4a01SJed Brown } 441938e4a01SJed Brown 442e9923e8dSJed Brown #undef __FUNCT__ 443e9923e8dSJed Brown #define __FUNCT__ "SNESFASRestrict" 444e9923e8dSJed Brown /*@ 445e9923e8dSJed Brown SNESFASRestrict - restrict a Vec to the next coarser level 446e9923e8dSJed Brown 447e9923e8dSJed Brown Collective 448e9923e8dSJed Brown 449e9923e8dSJed Brown Input Arguments: 450e9923e8dSJed Brown + fine - SNES from which to restrict 451e9923e8dSJed Brown - Xfine - vector to restrict 452e9923e8dSJed Brown 453e9923e8dSJed Brown Output Arguments: 454e9923e8dSJed Brown . Xcoarse - result of restriction 455e9923e8dSJed Brown 456e9923e8dSJed Brown Level: developer 457e9923e8dSJed Brown 458e9923e8dSJed Brown .seealso: SNESFASSetRestriction(), SNESFASSetInjection() 459e9923e8dSJed Brown @*/ 460e9923e8dSJed Brown PetscErrorCode SNESFASRestrict(SNES fine,Vec Xfine,Vec Xcoarse) 461e9923e8dSJed Brown { 462e9923e8dSJed Brown PetscErrorCode ierr; 463e9923e8dSJed Brown SNES_FAS *fas = (SNES_FAS*)fine->data; 464e9923e8dSJed Brown 465e9923e8dSJed Brown PetscFunctionBegin; 466e9923e8dSJed Brown PetscValidHeaderSpecific(fine,SNES_CLASSID,1); 467e9923e8dSJed Brown PetscValidHeaderSpecific(Xfine,VEC_CLASSID,2); 468e9923e8dSJed Brown PetscValidHeaderSpecific(Xcoarse,VEC_CLASSID,3); 469e9923e8dSJed Brown if (fas->inject) { 470e9923e8dSJed Brown ierr = MatRestrict(fas->inject,Xfine,Xcoarse);CHKERRQ(ierr); 471e9923e8dSJed Brown } else { 472e9923e8dSJed Brown ierr = MatRestrict(fas->restrct,Xfine,Xcoarse);CHKERRQ(ierr); 473e9923e8dSJed Brown ierr = VecPointwiseMult(Xcoarse,fas->rscale,Xcoarse);CHKERRQ(ierr); 474e9923e8dSJed Brown } 475e9923e8dSJed Brown PetscFunctionReturn(0); 476e9923e8dSJed Brown } 477e9923e8dSJed Brown 478e9923e8dSJed Brown #undef __FUNCT__ 47939bd7f45SPeter Brune #define __FUNCT__ "FASCoarseCorrection" 48039bd7f45SPeter Brune /* 48139bd7f45SPeter Brune 48239bd7f45SPeter Brune Performs the FAS coarse correction as: 48339bd7f45SPeter Brune 48439bd7f45SPeter Brune fine problem: F(x) = 0 48539bd7f45SPeter Brune coarse problem: F^c(x) = b^c 48639bd7f45SPeter Brune 48739bd7f45SPeter Brune b^c = F^c(I^c_fx^f - I^c_fF(x)) 48839bd7f45SPeter Brune 48939bd7f45SPeter Brune */ 49039a4b097SPeter Brune PetscErrorCode FASCoarseCorrection(SNES snes, Vec X, Vec F, Vec X_new) { 49139bd7f45SPeter Brune PetscErrorCode ierr; 49239bd7f45SPeter Brune Vec X_c, Xo_c, F_c, B_c; 49339bd7f45SPeter Brune SNESConvergedReason reason; 494ab8d36c9SPeter Brune SNES next; 495ab8d36c9SPeter Brune Mat restrct, interpolate; 49639bd7f45SPeter Brune PetscFunctionBegin; 497ab8d36c9SPeter Brune ierr = SNESFASCycleGetCorrection(snes, &next);CHKERRQ(ierr); 498ab8d36c9SPeter Brune if (next) { 499ab8d36c9SPeter Brune ierr = SNESFASCycleGetRestriction(snes, &restrct);CHKERRQ(ierr); 500ab8d36c9SPeter Brune ierr = SNESFASCycleGetInterpolation(snes, &interpolate);CHKERRQ(ierr); 501ab8d36c9SPeter Brune 502ab8d36c9SPeter Brune X_c = next->vec_sol; 503ab8d36c9SPeter Brune Xo_c = next->work[0]; 504ab8d36c9SPeter Brune F_c = next->vec_func; 505ab8d36c9SPeter Brune B_c = next->vec_rhs; 506efe1f98aSPeter Brune 507938e4a01SJed Brown ierr = SNESFASRestrict(snes,X,Xo_c);CHKERRQ(ierr); 508293a7e31SPeter Brune ierr = VecScale(F, -1.0);CHKERRQ(ierr); 509293a7e31SPeter Brune 510293a7e31SPeter Brune /* restrict the defect */ 511ab8d36c9SPeter Brune ierr = MatRestrict(restrct, F, B_c);CHKERRQ(ierr); 512293a7e31SPeter Brune 513c90fad12SPeter Brune /* solve the coarse problem corresponding to F^c(x^c) = b^c = Rb + F^c(Rx) - RF(x) */ 514ab8d36c9SPeter Brune next->vec_rhs = PETSC_NULL; /*unset the RHS to evaluate function instead of residual*/ 515ab8d36c9SPeter Brune ierr = SNESComputeFunction(next, Xo_c, F_c);CHKERRQ(ierr); 516742fe5e2SPeter Brune 517293a7e31SPeter Brune ierr = VecAXPY(B_c, 1.0, F_c);CHKERRQ(ierr); /* add F_c(X) to the RHS */ 518c90fad12SPeter Brune 519ee78dd50SPeter Brune /* set initial guess of the coarse problem to the projected fine solution */ 520ee78dd50SPeter Brune ierr = VecCopy(Xo_c, X_c);CHKERRQ(ierr); 521c90fad12SPeter Brune 522c90fad12SPeter Brune /* recurse to the next level */ 523ab8d36c9SPeter Brune next->vec_rhs = B_c; 524ab8d36c9SPeter Brune ierr = SNESSolve(next, B_c, X_c);CHKERRQ(ierr); 525ab8d36c9SPeter Brune ierr = SNESGetConvergedReason(next,&reason);CHKERRQ(ierr); 526742fe5e2SPeter Brune if (reason < 0 && reason != SNES_DIVERGED_MAX_IT) { 527742fe5e2SPeter Brune snes->reason = SNES_DIVERGED_INNER; 528742fe5e2SPeter Brune PetscFunctionReturn(0); 529742fe5e2SPeter Brune } 530ee78dd50SPeter Brune 531fa9694d7SPeter Brune /* correct as x <- x + I(x^c - Rx)*/ 532fa9694d7SPeter Brune ierr = VecAXPY(X_c, -1.0, Xo_c);CHKERRQ(ierr); 533ab8d36c9SPeter Brune ierr = MatInterpolateAdd(interpolate, X_c, X, X_new);CHKERRQ(ierr); 534293a7e31SPeter Brune } 53539bd7f45SPeter Brune PetscFunctionReturn(0); 53639bd7f45SPeter Brune } 53739bd7f45SPeter Brune 53839bd7f45SPeter Brune #undef __FUNCT__ 53939bd7f45SPeter Brune #define __FUNCT__ "FASCycle_Additive" 54039bd7f45SPeter Brune /* 54139bd7f45SPeter Brune 54239bd7f45SPeter Brune The additive cycle looks like: 54339bd7f45SPeter Brune 54407144faaSPeter Brune xhat = x 54507144faaSPeter Brune xhat = dS(x, b) 54607144faaSPeter Brune x = coarsecorrection(xhat, b_d) 54707144faaSPeter Brune x = x + nu*(xhat - x); 54839bd7f45SPeter Brune (optional) x = uS(x, b) 54939bd7f45SPeter Brune 55039bd7f45SPeter Brune With the coarse RHS (defect correction) as below. 55139bd7f45SPeter Brune 55239bd7f45SPeter Brune */ 55339bd7f45SPeter Brune PetscErrorCode FASCycle_Additive(SNES snes, Vec X) { 55407144faaSPeter Brune Vec F, B, Xhat; 55522c1e704SPeter Brune Vec X_c, Xo_c, F_c, B_c; 55639bd7f45SPeter Brune PetscErrorCode ierr; 55707144faaSPeter Brune SNESConvergedReason reason; 55822c1e704SPeter Brune PetscReal xnorm, fnorm, ynorm; 55922c1e704SPeter Brune PetscBool lssuccess; 560ab8d36c9SPeter Brune SNES next; 561ab8d36c9SPeter Brune Mat restrct, interpolate; 56239bd7f45SPeter Brune PetscFunctionBegin; 563ab8d36c9SPeter Brune ierr = SNESFASCycleGetCorrection(snes, &next);CHKERRQ(ierr); 56439bd7f45SPeter Brune F = snes->vec_func; 56539bd7f45SPeter Brune B = snes->vec_rhs; 566fde0ff24SPeter Brune Xhat = snes->work[3]; 56707144faaSPeter Brune ierr = VecCopy(X, Xhat);CHKERRQ(ierr); 56807144faaSPeter Brune /* recurse first */ 569ab8d36c9SPeter Brune if (next) { 570ab8d36c9SPeter Brune ierr = SNESFASCycleGetRestriction(snes, &restrct);CHKERRQ(ierr); 571ab8d36c9SPeter Brune ierr = SNESFASCycleGetInterpolation(snes, &interpolate);CHKERRQ(ierr); 57207144faaSPeter Brune ierr = SNESComputeFunction(snes, Xhat, F);CHKERRQ(ierr); 57339bd7f45SPeter Brune 574ab8d36c9SPeter Brune X_c = next->vec_sol; 575ab8d36c9SPeter Brune Xo_c = next->work[0]; 576ab8d36c9SPeter Brune F_c = next->vec_func; 577ab8d36c9SPeter Brune B_c = next->vec_rhs; 57839bd7f45SPeter Brune 579938e4a01SJed Brown ierr = SNESFASRestrict(snes,Xhat,Xo_c);CHKERRQ(ierr); 58007144faaSPeter Brune ierr = VecScale(F, -1.0);CHKERRQ(ierr); 58107144faaSPeter Brune 58207144faaSPeter Brune /* restrict the defect */ 583ab8d36c9SPeter Brune ierr = MatRestrict(restrct, F, B_c);CHKERRQ(ierr); 58407144faaSPeter Brune 58507144faaSPeter Brune /* solve the coarse problem corresponding to F^c(x^c) = b^c = Rb + F^c(Rx) - RF(x) */ 586ab8d36c9SPeter Brune next->vec_rhs = PETSC_NULL; /*unset the RHS to evaluate function instead of residual*/ 587ab8d36c9SPeter Brune ierr = SNESComputeFunction(next, Xo_c, F_c);CHKERRQ(ierr); 58807144faaSPeter Brune 58907144faaSPeter Brune ierr = VecAXPY(B_c, 1.0, F_c);CHKERRQ(ierr); /* add F_c(X) to the RHS */ 59007144faaSPeter Brune 59107144faaSPeter Brune /* set initial guess of the coarse problem to the projected fine solution */ 59207144faaSPeter Brune ierr = VecCopy(Xo_c, X_c);CHKERRQ(ierr); 59307144faaSPeter Brune 59407144faaSPeter Brune /* recurse */ 595ab8d36c9SPeter Brune next->vec_rhs = B_c; 596ab8d36c9SPeter Brune ierr = SNESSolve(next, B_c, X_c);CHKERRQ(ierr); 59707144faaSPeter Brune 59807144faaSPeter Brune /* smooth on this level */ 59907144faaSPeter Brune ierr = FASDownSmooth(snes, B, X, F);CHKERRQ(ierr); 60007144faaSPeter Brune 601ab8d36c9SPeter Brune ierr = SNESGetConvergedReason(next,&reason);CHKERRQ(ierr); 60207144faaSPeter Brune if (reason < 0 && reason != SNES_DIVERGED_MAX_IT) { 60307144faaSPeter Brune snes->reason = SNES_DIVERGED_INNER; 60407144faaSPeter Brune PetscFunctionReturn(0); 60507144faaSPeter Brune } 60607144faaSPeter Brune 60707144faaSPeter Brune /* correct as x <- x + I(x^c - Rx)*/ 608c68acad4SPeter Brune ierr = VecAYPX(X_c, -1.0, Xo_c);CHKERRQ(ierr); 609ab8d36c9SPeter Brune ierr = MatInterpolate(interpolate, X_c, Xhat);CHKERRQ(ierr); 61007144faaSPeter Brune 611ddebd997SPeter Brune /* additive correction of the coarse direction*/ 612ddebd997SPeter Brune ierr = SNESComputeFunction(snes, X, F);CHKERRQ(ierr); 613ddebd997SPeter Brune ierr = VecNorm(F, NORM_2, &fnorm);CHKERRQ(ierr); 614f1c6b773SPeter Brune ierr = SNESLineSearchApply(snes->linesearch, X, F, &fnorm, Xhat);CHKERRQ(ierr); 615f1c6b773SPeter Brune ierr = SNESLineSearchGetSuccess(snes->linesearch, &lssuccess);CHKERRQ(ierr); 6169e764e56SPeter Brune if (!lssuccess) { 6179e764e56SPeter Brune if (++snes->numFailures >= snes->maxFailures) { 6189e764e56SPeter Brune snes->reason = SNES_DIVERGED_LINE_SEARCH; 6199e764e56SPeter Brune PetscFunctionReturn(0); 6209e764e56SPeter Brune } 6219e764e56SPeter Brune } 622f1c6b773SPeter Brune ierr = SNESLineSearchGetNorms(snes->linesearch, &xnorm, &fnorm, &ynorm);CHKERRQ(ierr); 62307144faaSPeter Brune } else { 62407144faaSPeter Brune ierr = FASDownSmooth(snes, B, X, F);CHKERRQ(ierr); 62507144faaSPeter Brune } 62639bd7f45SPeter Brune PetscFunctionReturn(0); 62739bd7f45SPeter Brune } 62839bd7f45SPeter Brune 62939bd7f45SPeter Brune #undef __FUNCT__ 63039bd7f45SPeter Brune #define __FUNCT__ "FASCycle_Multiplicative" 63139bd7f45SPeter Brune /* 63239bd7f45SPeter Brune 63339bd7f45SPeter Brune Defines the FAS cycle as: 63439bd7f45SPeter Brune 63539bd7f45SPeter Brune fine problem: F(x) = 0 63639bd7f45SPeter Brune coarse problem: F^c(x) = b^c 63739bd7f45SPeter Brune 63839bd7f45SPeter Brune b^c = F^c(I^c_fx^f - I^c_fF(x)) 63939bd7f45SPeter Brune 64039bd7f45SPeter Brune correction: 64139bd7f45SPeter Brune 64239bd7f45SPeter Brune x = x + I(x^c - Rx) 64339bd7f45SPeter Brune 64439bd7f45SPeter Brune */ 64539bd7f45SPeter Brune PetscErrorCode FASCycle_Multiplicative(SNES snes, Vec X) { 64639bd7f45SPeter Brune 64739bd7f45SPeter Brune PetscErrorCode ierr; 64839bd7f45SPeter Brune Vec F,B; 64939bd7f45SPeter Brune SNES_FAS *fas = (SNES_FAS *)snes->data; 65039bd7f45SPeter Brune 65139bd7f45SPeter Brune PetscFunctionBegin; 65239bd7f45SPeter Brune F = snes->vec_func; 65339bd7f45SPeter Brune B = snes->vec_rhs; 65439bd7f45SPeter Brune /* pre-smooth -- just update using the pre-smoother */ 65539bd7f45SPeter Brune ierr = FASDownSmooth(snes, B, X, F);CHKERRQ(ierr); 65639bd7f45SPeter Brune 657c90fad12SPeter Brune if (fas->level != 0) { 658e70c42e5SPeter Brune ierr = FASCoarseCorrection(snes, X, F, X);CHKERRQ(ierr); 65939bd7f45SPeter Brune ierr = FASUpSmooth(snes, B, X, F);CHKERRQ(ierr); 660fe6f9142SPeter Brune } 661fa9694d7SPeter Brune PetscFunctionReturn(0); 662421d9b32SPeter Brune } 663421d9b32SPeter Brune 664421d9b32SPeter Brune #undef __FUNCT__ 665421d9b32SPeter Brune #define __FUNCT__ "SNESSolve_FAS" 666421d9b32SPeter Brune 667421d9b32SPeter Brune PetscErrorCode SNESSolve_FAS(SNES snes) 668421d9b32SPeter Brune { 669fa9694d7SPeter Brune PetscErrorCode ierr; 670fe6f9142SPeter Brune PetscInt i, maxits; 671ddb5aff1SPeter Brune Vec X, F; 672fe6f9142SPeter Brune PetscReal fnorm; 673b17ce1afSJed Brown SNES_FAS *fas = (SNES_FAS *)snes->data,*ffas; 674b17ce1afSJed Brown DM dm; 675e70c42e5SPeter Brune PetscBool isFine; 676b17ce1afSJed Brown 677421d9b32SPeter Brune PetscFunctionBegin; 678fe6f9142SPeter Brune maxits = snes->max_its; /* maximum number of iterations */ 679fe6f9142SPeter Brune snes->reason = SNES_CONVERGED_ITERATING; 680fa9694d7SPeter Brune X = snes->vec_sol; 681f5a6d4f9SBarry Smith F = snes->vec_func; 682293a7e31SPeter Brune 68318a66777SPeter Brune ierr = SNESFASCycleIsFine(snes, &isFine);CHKERRQ(ierr); 684293a7e31SPeter Brune /*norm setup */ 685fe6f9142SPeter Brune ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr); 686fe6f9142SPeter Brune snes->iter = 0; 687fe6f9142SPeter Brune snes->norm = 0.; 688fe6f9142SPeter Brune ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr); 68918a66777SPeter Brune if (isFine || fas->monitor) { 690fe6f9142SPeter Brune ierr = SNESComputeFunction(snes,X,F);CHKERRQ(ierr); 691fe6f9142SPeter Brune if (snes->domainerror) { 692fe6f9142SPeter Brune snes->reason = SNES_DIVERGED_FUNCTION_DOMAIN; 693fe6f9142SPeter Brune PetscFunctionReturn(0); 694fe6f9142SPeter Brune } 695fe6f9142SPeter Brune ierr = VecNorm(F, NORM_2, &fnorm);CHKERRQ(ierr); /* fnorm <- ||F|| */ 696fe6f9142SPeter Brune if (PetscIsInfOrNanReal(fnorm)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"Infinite or not-a-number generated in norm"); 697fe6f9142SPeter Brune ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr); 698fe6f9142SPeter Brune snes->norm = fnorm; 699fe6f9142SPeter Brune ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr); 700fe6f9142SPeter Brune SNESLogConvHistory(snes,fnorm,0); 701fe6f9142SPeter Brune ierr = SNESMonitor(snes,0,fnorm);CHKERRQ(ierr); 702fe6f9142SPeter Brune 703fe6f9142SPeter Brune /* set parameter for default relative tolerance convergence test */ 704fe6f9142SPeter Brune snes->ttol = fnorm*snes->rtol; 705fe6f9142SPeter Brune /* test convergence */ 706fe6f9142SPeter Brune ierr = (*snes->ops->converged)(snes,0,0.0,0.0,fnorm,&snes->reason,snes->cnvP);CHKERRQ(ierr); 707fe6f9142SPeter Brune if (snes->reason) PetscFunctionReturn(0); 70866585501SPeter Brune } 709b17ce1afSJed Brown 710b17ce1afSJed Brown ierr = SNESGetDM(snes,&dm);CHKERRQ(ierr); 711b17ce1afSJed Brown for (ffas=fas; ffas->next; ffas=(SNES_FAS*)ffas->next->data) { 712b17ce1afSJed Brown DM dmcoarse; 713b17ce1afSJed Brown ierr = SNESGetDM(ffas->next,&dmcoarse);CHKERRQ(ierr); 714b17ce1afSJed Brown ierr = DMRestrict(dm,ffas->restrct,ffas->rscale,ffas->inject,dmcoarse);CHKERRQ(ierr); 715b17ce1afSJed Brown dm = dmcoarse; 716b17ce1afSJed Brown } 717b17ce1afSJed Brown 718fe6f9142SPeter Brune for (i = 0; i < maxits; i++) { 719fe6f9142SPeter Brune /* Call general purpose update function */ 720646217ecSPeter Brune 721fe6f9142SPeter Brune if (snes->ops->update) { 722fe6f9142SPeter Brune ierr = (*snes->ops->update)(snes, snes->iter);CHKERRQ(ierr); 723fe6f9142SPeter Brune } 72407144faaSPeter Brune if (fas->fastype == SNES_FAS_MULTIPLICATIVE) { 72539bd7f45SPeter Brune ierr = FASCycle_Multiplicative(snes, X);CHKERRQ(ierr); 72607144faaSPeter Brune } else { 72707144faaSPeter Brune ierr = FASCycle_Additive(snes, X);CHKERRQ(ierr); 72807144faaSPeter Brune } 729742fe5e2SPeter Brune 730742fe5e2SPeter Brune /* check for FAS cycle divergence */ 731742fe5e2SPeter Brune if (snes->reason != SNES_CONVERGED_ITERATING) { 732742fe5e2SPeter Brune PetscFunctionReturn(0); 733742fe5e2SPeter Brune } 734e70c42e5SPeter Brune if (isFine || fas->monitor) { 735c90fad12SPeter Brune ierr = VecNorm(F, NORM_2, &fnorm);CHKERRQ(ierr); /* fnorm <- ||F|| */ 736e70c42e5SPeter Brune } 737c90fad12SPeter Brune /* Monitor convergence */ 738c90fad12SPeter Brune ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr); 739c90fad12SPeter Brune snes->iter = i+1; 740c90fad12SPeter Brune snes->norm = fnorm; 741c90fad12SPeter Brune ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr); 742c90fad12SPeter Brune SNESLogConvHistory(snes,snes->norm,0); 743c90fad12SPeter Brune ierr = SNESMonitor(snes,snes->iter,snes->norm);CHKERRQ(ierr); 744c90fad12SPeter Brune /* Test for convergence */ 74566585501SPeter Brune if (isFine) { 746c90fad12SPeter Brune ierr = (*snes->ops->converged)(snes,snes->iter,0.0,0.0,fnorm,&snes->reason,snes->cnvP);CHKERRQ(ierr); 747c90fad12SPeter Brune if (snes->reason) break; 748fe6f9142SPeter Brune } 74966585501SPeter Brune } 750fe6f9142SPeter Brune if (i == maxits) { 751fe6f9142SPeter Brune ierr = PetscInfo1(snes, "Maximum number of iterations has been reached: %D\n", maxits);CHKERRQ(ierr); 752fe6f9142SPeter Brune if (!snes->reason) snes->reason = SNES_DIVERGED_MAX_IT; 753fe6f9142SPeter Brune } 754421d9b32SPeter Brune PetscFunctionReturn(0); 755421d9b32SPeter Brune } 756