1421d9b32SPeter Brune /* Defines the basic SNES object */ 2a055c8caSBarry Smith #include <../src/snes/impls/fas/fasimpls.h> /*I "petscsnes.h" I*/ 3421d9b32SPeter Brune 434d65b3cSPeter Brune const char *const SNESFASTypes[] = {"MULTIPLICATIVE","ADDITIVE","FULL","KASKADE","SNESFASType","SNES_FAS",0}; 507144faaSPeter Brune 66273346dSPeter Brune extern PetscErrorCode SNESFASGalerkinDefaultFunction(SNES,Vec,Vec,void*); 7efe1f98aSPeter Brune 840244768SBarry Smith static PetscErrorCode SNESReset_FAS(SNES snes) 9421d9b32SPeter Brune { 1077df8cc4SPeter Brune PetscErrorCode ierr = 0; 11421d9b32SPeter Brune SNES_FAS * fas = (SNES_FAS*)snes->data; 12421d9b32SPeter Brune 13421d9b32SPeter Brune PetscFunctionBegin; 14ab8d36c9SPeter Brune ierr = SNESDestroy(&fas->smoothu);CHKERRQ(ierr); 15ab8d36c9SPeter Brune ierr = SNESDestroy(&fas->smoothd);CHKERRQ(ierr); 163dccd265SPeter Brune ierr = MatDestroy(&fas->inject);CHKERRQ(ierr); 17bccf9bb3SJed Brown ierr = MatDestroy(&fas->interpolate);CHKERRQ(ierr); 18bccf9bb3SJed Brown ierr = MatDestroy(&fas->restrct);CHKERRQ(ierr); 19bccf9bb3SJed Brown ierr = VecDestroy(&fas->rscale);CHKERRQ(ierr); 207cd33a7bSPeter Brune if (fas->galerkin) { 217cd33a7bSPeter Brune ierr = VecDestroy(&fas->Xg);CHKERRQ(ierr); 227cd33a7bSPeter Brune ierr = VecDestroy(&fas->Fg);CHKERRQ(ierr); 237cd33a7bSPeter Brune } 24d477d801SPeter Brune if (fas->next) {ierr = SNESReset(fas->next);CHKERRQ(ierr);} 25421d9b32SPeter Brune PetscFunctionReturn(0); 26421d9b32SPeter Brune } 27421d9b32SPeter Brune 2840244768SBarry Smith static PetscErrorCode SNESDestroy_FAS(SNES snes) 29421d9b32SPeter Brune { 30421d9b32SPeter Brune SNES_FAS * fas = (SNES_FAS*)snes->data; 31742fe5e2SPeter Brune PetscErrorCode ierr = 0; 32421d9b32SPeter Brune 33421d9b32SPeter Brune PetscFunctionBegin; 34421d9b32SPeter Brune /* recursively resets and then destroys */ 3579d9a41aSPeter Brune ierr = SNESReset(snes);CHKERRQ(ierr); 361aa26658SKarl Rupp if (fas->next) { 371aa26658SKarl Rupp ierr = SNESDestroy(&fas->next);CHKERRQ(ierr); 381aa26658SKarl Rupp } 39421d9b32SPeter Brune ierr = PetscFree(fas);CHKERRQ(ierr); 40421d9b32SPeter Brune PetscFunctionReturn(0); 41421d9b32SPeter Brune } 42421d9b32SPeter Brune 4340244768SBarry Smith static PetscErrorCode SNESSetUp_FAS(SNES snes) 44421d9b32SPeter Brune { 4548bfdf8aSPeter Brune SNES_FAS *fas = (SNES_FAS*) snes->data; 46421d9b32SPeter Brune PetscErrorCode ierr; 47d1adcc6fSPeter Brune PetscInt dm_levels; 483dccd265SPeter Brune Vec vec_sol, vec_func, vec_sol_update, vec_rhs; /* preserve these if they're set through the reset */ 49ab8d36c9SPeter Brune SNES next; 500a7266b2SPatrick Farrell PetscBool isFine, hasCreateRestriction; 51f89ba88eSPeter Brune SNESLineSearch linesearch; 52f89ba88eSPeter Brune SNESLineSearch slinesearch; 53f89ba88eSPeter Brune void *lsprectx,*lspostctx; 546b2b7091SBarry Smith PetscErrorCode (*precheck)(SNESLineSearch,Vec,Vec,PetscBool*,void*); 556b2b7091SBarry Smith PetscErrorCode (*postcheck)(SNESLineSearch,Vec,Vec,Vec,PetscBool*,PetscBool*,void*); 56eff52c0eSPeter Brune 576b2b7091SBarry Smith PetscFunctionBegin; 58ab8d36c9SPeter Brune ierr = SNESFASCycleIsFine(snes, &isFine);CHKERRQ(ierr); 59ab8d36c9SPeter Brune if (fas->usedmfornumberoflevels && isFine) { 60d1adcc6fSPeter Brune ierr = DMGetRefineLevel(snes->dm,&dm_levels);CHKERRQ(ierr); 61d1adcc6fSPeter Brune dm_levels++; 62cc05f883SPeter Brune if (dm_levels > fas->levels) { 632e8ce248SJed Brown /* we don't want the solution and func vectors to be destroyed in the SNESReset when it's called in SNESFASSetLevels_FAS*/ 643dccd265SPeter Brune vec_sol = snes->vec_sol; 653dccd265SPeter Brune vec_func = snes->vec_func; 663dccd265SPeter Brune vec_sol_update = snes->vec_sol_update; 673dccd265SPeter Brune vec_rhs = snes->vec_rhs; 680298fd71SBarry Smith snes->vec_sol = NULL; 690298fd71SBarry Smith snes->vec_func = NULL; 700298fd71SBarry Smith snes->vec_sol_update = NULL; 710298fd71SBarry Smith snes->vec_rhs = NULL; 723dccd265SPeter Brune 733dccd265SPeter Brune /* reset the number of levels */ 740298fd71SBarry Smith ierr = SNESFASSetLevels(snes,dm_levels,NULL);CHKERRQ(ierr); 75cc05f883SPeter Brune ierr = SNESSetFromOptions(snes);CHKERRQ(ierr); 763dccd265SPeter Brune 773dccd265SPeter Brune snes->vec_sol = vec_sol; 783dccd265SPeter Brune snes->vec_func = vec_func; 793dccd265SPeter Brune snes->vec_rhs = vec_rhs; 803dccd265SPeter Brune snes->vec_sol_update = vec_sol_update; 81d1adcc6fSPeter Brune } 82d1adcc6fSPeter Brune } 83ab8d36c9SPeter Brune ierr = SNESFASCycleGetCorrection(snes, &next);CHKERRQ(ierr); 84ab8d36c9SPeter Brune if (!isFine) snes->gridsequence = 0; /* no grid sequencing inside the multigrid hierarchy! */ 853dccd265SPeter Brune 86fa0ddf94SBarry Smith ierr = SNESSetWorkVecs(snes, 2);CHKERRQ(ierr); /* work vectors used for intergrid transfers */ 87cc05f883SPeter Brune 88ab8d36c9SPeter Brune /* set up the smoothers if they haven't already been set up */ 89ab8d36c9SPeter Brune if (!fas->smoothd) { 90ab8d36c9SPeter Brune ierr = SNESFASCycleCreateSmoother_Private(snes, &fas->smoothd);CHKERRQ(ierr); 91ab8d36c9SPeter Brune } 92ab8d36c9SPeter Brune 9379d9a41aSPeter Brune if (snes->dm) { 94ab8d36c9SPeter Brune /* set the smoother DMs properly */ 95ab8d36c9SPeter Brune if (fas->smoothu) ierr = SNESSetDM(fas->smoothu, snes->dm);CHKERRQ(ierr); 96ab8d36c9SPeter Brune ierr = SNESSetDM(fas->smoothd, snes->dm);CHKERRQ(ierr); 9779d9a41aSPeter Brune /* construct EVERYTHING from the DM -- including the progressive set of smoothers */ 98ab8d36c9SPeter Brune if (next) { 9979d9a41aSPeter Brune /* for now -- assume the DM and the evaluation functions have been set externally */ 100ab8d36c9SPeter Brune if (!next->dm) { 101ce94432eSBarry Smith ierr = DMCoarsen(snes->dm, PetscObjectComm((PetscObject)next), &next->dm);CHKERRQ(ierr); 102ab8d36c9SPeter Brune ierr = SNESSetDM(next, next->dm);CHKERRQ(ierr); 10379d9a41aSPeter Brune } 10479d9a41aSPeter Brune /* set the interpolation and restriction from the DM */ 10579d9a41aSPeter Brune if (!fas->interpolate) { 106ab8d36c9SPeter Brune ierr = DMCreateInterpolation(next->dm, snes->dm, &fas->interpolate, &fas->rscale);CHKERRQ(ierr); 107bccf9bb3SJed Brown if (!fas->restrct) { 1080a7266b2SPatrick Farrell ierr = DMHasCreateRestriction(next->dm, &hasCreateRestriction);CHKERRQ(ierr); 1090a7266b2SPatrick Farrell /* DM can create restrictions, use that */ 1100a7266b2SPatrick Farrell if (hasCreateRestriction) { 1110a7266b2SPatrick Farrell ierr = DMCreateRestriction(next->dm, snes->dm, &fas->restrct);CHKERRQ(ierr); 1120a7266b2SPatrick Farrell } else { 113bccf9bb3SJed Brown ierr = PetscObjectReference((PetscObject)fas->interpolate);CHKERRQ(ierr); 11479d9a41aSPeter Brune fas->restrct = fas->interpolate; 11579d9a41aSPeter Brune } 116bccf9bb3SJed Brown } 1170a7266b2SPatrick Farrell } 11879d9a41aSPeter Brune /* set the injection from the DM */ 11979d9a41aSPeter Brune if (!fas->inject) { 120*23e68893SLawrence Mitchell PetscBool flg; 121*23e68893SLawrence Mitchell ierr = DMHasCreateInjection(next->dm, &flg);CHKERRQ(ierr); 122*23e68893SLawrence Mitchell if (flg) { 1236dbf9973SLawrence Mitchell ierr = DMCreateInjection(next->dm, snes->dm, &fas->inject);CHKERRQ(ierr); 12479d9a41aSPeter Brune } 12579d9a41aSPeter Brune } 12679d9a41aSPeter Brune } 127*23e68893SLawrence Mitchell } 12879d9a41aSPeter Brune /*pass the smoother, function, and jacobian up to the next level if it's not user set already */ 12979d9a41aSPeter Brune if (fas->galerkin) { 1301aa26658SKarl Rupp if (next) { 1310298fd71SBarry Smith ierr = SNESSetFunction(next, NULL, SNESFASGalerkinDefaultFunction, next);CHKERRQ(ierr); 1321aa26658SKarl Rupp } 1331aa26658SKarl Rupp if (fas->smoothd && fas->level != fas->levels - 1) { 1340298fd71SBarry Smith ierr = SNESSetFunction(fas->smoothd, NULL, SNESFASGalerkinDefaultFunction, snes);CHKERRQ(ierr); 1351aa26658SKarl Rupp } 1361aa26658SKarl Rupp if (fas->smoothu && fas->level != fas->levels - 1) { 1370298fd71SBarry Smith ierr = SNESSetFunction(fas->smoothu, NULL, SNESFASGalerkinDefaultFunction, snes);CHKERRQ(ierr); 1381aa26658SKarl Rupp } 13979d9a41aSPeter Brune } 14079d9a41aSPeter Brune 141534ebe21SPeter Brune /* sets the down (pre) smoother's default norm and sets it from options */ 142534ebe21SPeter Brune if (fas->smoothd) { 143bc3f2f05SPeter Brune if (fas->level == 0 && fas->levels != 1) { 144365a6726SPeter Brune ierr = SNESSetNormSchedule(fas->smoothd, SNES_NORM_NONE);CHKERRQ(ierr); 145534ebe21SPeter Brune } else { 146365a6726SPeter Brune ierr = SNESSetNormSchedule(fas->smoothd, SNES_NORM_FINAL_ONLY);CHKERRQ(ierr); 147534ebe21SPeter Brune } 1487fce8c19SPeter Brune ierr = PetscObjectCopyFortranFunctionPointers((PetscObject)snes, (PetscObject)fas->smoothd);CHKERRQ(ierr); 149534ebe21SPeter Brune ierr = SNESSetFromOptions(fas->smoothd);CHKERRQ(ierr); 1507601faf0SJed Brown ierr = SNESGetLineSearch(snes,&linesearch);CHKERRQ(ierr); 1517601faf0SJed Brown ierr = SNESGetLineSearch(fas->smoothd,&slinesearch);CHKERRQ(ierr); 1526b2b7091SBarry Smith ierr = SNESLineSearchGetPreCheck(linesearch,&precheck,&lsprectx);CHKERRQ(ierr); 1536b2b7091SBarry Smith ierr = SNESLineSearchGetPostCheck(linesearch,&postcheck,&lspostctx);CHKERRQ(ierr); 1546b2b7091SBarry Smith ierr = SNESLineSearchSetPreCheck(slinesearch,precheck,lsprectx);CHKERRQ(ierr); 1556b2b7091SBarry Smith ierr = SNESLineSearchSetPostCheck(slinesearch,postcheck,lspostctx);CHKERRQ(ierr); 156f89ba88eSPeter Brune ierr = PetscObjectCopyFortranFunctionPointers((PetscObject)linesearch, (PetscObject)slinesearch);CHKERRQ(ierr); 1570dd27c6cSPeter Brune 1580dd27c6cSPeter Brune fas->smoothd->vec_sol = snes->vec_sol; 1590dd27c6cSPeter Brune ierr = PetscObjectReference((PetscObject)snes->vec_sol);CHKERRQ(ierr); 1600dd27c6cSPeter Brune fas->smoothd->vec_sol_update = snes->vec_sol_update; 1610dd27c6cSPeter Brune ierr = PetscObjectReference((PetscObject)snes->vec_sol_update);CHKERRQ(ierr); 1620dd27c6cSPeter Brune fas->smoothd->vec_func = snes->vec_func; 1630dd27c6cSPeter Brune ierr = PetscObjectReference((PetscObject)snes->vec_func);CHKERRQ(ierr); 1640dd27c6cSPeter Brune 1650dd27c6cSPeter Brune if (fas->eventsmoothsetup) {ierr = PetscLogEventBegin(fas->eventsmoothsetup,0,0,0,0);CHKERRQ(ierr);} 1660dd27c6cSPeter Brune ierr = SNESSetUp(fas->smoothd);CHKERRQ(ierr); 1670dd27c6cSPeter Brune if (fas->eventsmoothsetup) {ierr = PetscLogEventEnd(fas->eventsmoothsetup,0,0,0,0);CHKERRQ(ierr);} 168534ebe21SPeter Brune } 169534ebe21SPeter Brune 170534ebe21SPeter Brune /* sets the up (post) smoother's default norm and sets it from options */ 171534ebe21SPeter Brune if (fas->smoothu) { 172534ebe21SPeter Brune if (fas->level != fas->levels - 1) { 173365a6726SPeter Brune ierr = SNESSetNormSchedule(fas->smoothu, SNES_NORM_NONE);CHKERRQ(ierr); 174534ebe21SPeter Brune } else { 175365a6726SPeter Brune ierr = SNESSetNormSchedule(fas->smoothu, SNES_NORM_FINAL_ONLY);CHKERRQ(ierr); 176534ebe21SPeter Brune } 1777fce8c19SPeter Brune ierr = PetscObjectCopyFortranFunctionPointers((PetscObject)snes, (PetscObject)fas->smoothu);CHKERRQ(ierr); 178534ebe21SPeter Brune ierr = SNESSetFromOptions(fas->smoothu);CHKERRQ(ierr); 1797601faf0SJed Brown ierr = SNESGetLineSearch(snes,&linesearch);CHKERRQ(ierr); 1807601faf0SJed Brown ierr = SNESGetLineSearch(fas->smoothu,&slinesearch);CHKERRQ(ierr); 1816b2b7091SBarry Smith ierr = SNESLineSearchGetPreCheck(linesearch,&precheck,&lsprectx);CHKERRQ(ierr); 1826b2b7091SBarry Smith ierr = SNESLineSearchGetPostCheck(linesearch,&postcheck,&lspostctx);CHKERRQ(ierr); 1836b2b7091SBarry Smith ierr = SNESLineSearchSetPreCheck(slinesearch,precheck,lsprectx);CHKERRQ(ierr); 1846b2b7091SBarry Smith ierr = SNESLineSearchSetPostCheck(slinesearch,postcheck,lspostctx);CHKERRQ(ierr); 185f89ba88eSPeter Brune ierr = PetscObjectCopyFortranFunctionPointers((PetscObject)linesearch, (PetscObject)slinesearch);CHKERRQ(ierr); 1860dd27c6cSPeter Brune 1870dd27c6cSPeter Brune fas->smoothu->vec_sol = snes->vec_sol; 1880dd27c6cSPeter Brune ierr = PetscObjectReference((PetscObject)snes->vec_sol);CHKERRQ(ierr); 1890dd27c6cSPeter Brune fas->smoothu->vec_sol_update = snes->vec_sol_update; 1900dd27c6cSPeter Brune ierr = PetscObjectReference((PetscObject)snes->vec_sol_update);CHKERRQ(ierr); 1910dd27c6cSPeter Brune fas->smoothu->vec_func = snes->vec_func; 1920dd27c6cSPeter Brune ierr = PetscObjectReference((PetscObject)snes->vec_func);CHKERRQ(ierr); 1930dd27c6cSPeter Brune 1940dd27c6cSPeter Brune if (fas->eventsmoothsetup) {ierr = PetscLogEventBegin(fas->eventsmoothsetup,0,0,0,0);CHKERRQ(ierr);} 1950dd27c6cSPeter Brune ierr = SNESSetUp(fas->smoothu);CHKERRQ(ierr); 1960dd27c6cSPeter Brune if (fas->eventsmoothsetup) {ierr = PetscLogEventEnd(fas->eventsmoothsetup,0,0,0,0);CHKERRQ(ierr);} 1970dd27c6cSPeter Brune 198534ebe21SPeter Brune } 199d06165b7SPeter Brune 200ab8d36c9SPeter Brune if (next) { 20179d9a41aSPeter Brune /* gotta set up the solution vector for this to work */ 202ab8d36c9SPeter Brune if (!next->vec_sol) {ierr = SNESFASCreateCoarseVec(snes,&next->vec_sol);CHKERRQ(ierr);} 203ab8d36c9SPeter Brune if (!next->vec_rhs) {ierr = SNESFASCreateCoarseVec(snes,&next->vec_rhs);CHKERRQ(ierr);} 2047fce8c19SPeter Brune ierr = PetscObjectCopyFortranFunctionPointers((PetscObject)snes, (PetscObject)next);CHKERRQ(ierr); 2057601faf0SJed Brown ierr = SNESGetLineSearch(snes,&linesearch);CHKERRQ(ierr); 2067601faf0SJed Brown ierr = SNESGetLineSearch(fas->next,&slinesearch);CHKERRQ(ierr); 2076b2b7091SBarry Smith ierr = SNESLineSearchGetPreCheck(linesearch,&precheck,&lsprectx);CHKERRQ(ierr); 2086b2b7091SBarry Smith ierr = SNESLineSearchGetPostCheck(linesearch,&postcheck,&lspostctx);CHKERRQ(ierr); 2096b2b7091SBarry Smith ierr = SNESLineSearchSetPreCheck(slinesearch,precheck,lsprectx);CHKERRQ(ierr); 2106b2b7091SBarry Smith ierr = SNESLineSearchSetPostCheck(slinesearch,postcheck,lspostctx);CHKERRQ(ierr); 211f89ba88eSPeter Brune ierr = PetscObjectCopyFortranFunctionPointers((PetscObject)linesearch, (PetscObject)slinesearch);CHKERRQ(ierr); 212ab8d36c9SPeter Brune ierr = SNESSetUp(next);CHKERRQ(ierr); 21379d9a41aSPeter Brune } 2146273346dSPeter Brune /* setup FAS work vectors */ 2156273346dSPeter Brune if (fas->galerkin) { 2166273346dSPeter Brune ierr = VecDuplicate(snes->vec_sol, &fas->Xg);CHKERRQ(ierr); 2176273346dSPeter Brune ierr = VecDuplicate(snes->vec_sol, &fas->Fg);CHKERRQ(ierr); 2186273346dSPeter Brune } 219421d9b32SPeter Brune PetscFunctionReturn(0); 220421d9b32SPeter Brune } 221421d9b32SPeter Brune 22240244768SBarry Smith static PetscErrorCode SNESSetFromOptions_FAS(PetscOptionItems *PetscOptionsObject,SNES snes) 223421d9b32SPeter Brune { 224ee78dd50SPeter Brune SNES_FAS *fas = (SNES_FAS*) snes->data; 225ee78dd50SPeter Brune PetscInt levels = 1; 22687f44e3fSPeter Brune PetscBool flg = PETSC_FALSE, upflg = PETSC_FALSE, downflg = PETSC_FALSE, monflg = PETSC_FALSE, galerkinflg = PETSC_FALSE,continuationflg = PETSC_FALSE; 227421d9b32SPeter Brune PetscErrorCode ierr; 22807144faaSPeter Brune SNESFASType fastype; 229fde0ff24SPeter Brune const char *optionsprefix; 230f1c6b773SPeter Brune SNESLineSearch linesearch; 23166585501SPeter Brune PetscInt m, n_up, n_down; 232ab8d36c9SPeter Brune SNES next; 233ab8d36c9SPeter Brune PetscBool isFine; 234421d9b32SPeter Brune 235421d9b32SPeter Brune PetscFunctionBegin; 236ab8d36c9SPeter Brune ierr = SNESFASCycleIsFine(snes, &isFine);CHKERRQ(ierr); 237e55864a3SBarry Smith ierr = PetscOptionsHead(PetscOptionsObject,"SNESFAS Options-----------------------------------");CHKERRQ(ierr); 238ee78dd50SPeter Brune 239ab8d36c9SPeter Brune /* number of levels -- only process most options on the finest level */ 240ab8d36c9SPeter Brune if (isFine) { 241ee78dd50SPeter Brune ierr = PetscOptionsInt("-snes_fas_levels", "Number of Levels", "SNESFASSetLevels", levels, &levels, &flg);CHKERRQ(ierr); 242c732cbdbSBarry Smith if (!flg && snes->dm) { 243c732cbdbSBarry Smith ierr = DMGetRefineLevel(snes->dm,&levels);CHKERRQ(ierr); 244c732cbdbSBarry Smith levels++; 245d1adcc6fSPeter Brune fas->usedmfornumberoflevels = PETSC_TRUE; 246c732cbdbSBarry Smith } 2470298fd71SBarry Smith ierr = SNESFASSetLevels(snes, levels, NULL);CHKERRQ(ierr); 24807144faaSPeter Brune fastype = fas->fastype; 24907144faaSPeter Brune ierr = PetscOptionsEnum("-snes_fas_type","FAS correction type","SNESFASSetType",SNESFASTypes,(PetscEnum)fastype,(PetscEnum*)&fastype,&flg);CHKERRQ(ierr); 25007144faaSPeter Brune if (flg) { 25107144faaSPeter Brune ierr = SNESFASSetType(snes, fastype);CHKERRQ(ierr); 25207144faaSPeter Brune } 253ee78dd50SPeter Brune 254fde0ff24SPeter Brune ierr = SNESGetOptionsPrefix(snes, &optionsprefix);CHKERRQ(ierr); 255ab8d36c9SPeter Brune ierr = PetscOptionsInt("-snes_fas_cycles","Number of cycles","SNESFASSetCycles",fas->n_cycles,&m,&flg);CHKERRQ(ierr); 256ab8d36c9SPeter Brune if (flg) { 257ab8d36c9SPeter Brune ierr = SNESFASSetCycles(snes, m);CHKERRQ(ierr); 258fde0ff24SPeter Brune } 25987f44e3fSPeter Brune ierr = PetscOptionsBool("-snes_fas_continuation","Corrected grid-sequence continuation","SNESFASSetContinuation",fas->continuation,&continuationflg,&flg);CHKERRQ(ierr); 26087f44e3fSPeter Brune if (flg) { 26187f44e3fSPeter Brune ierr = SNESFASSetContinuation(snes,continuationflg);CHKERRQ(ierr); 26287f44e3fSPeter Brune } 263fde0ff24SPeter Brune 264ab8d36c9SPeter Brune ierr = PetscOptionsBool("-snes_fas_galerkin", "Form coarse problems with Galerkin","SNESFASSetGalerkin",fas->galerkin,&galerkinflg,&flg);CHKERRQ(ierr); 265ab8d36c9SPeter Brune if (flg) { 266ab8d36c9SPeter Brune ierr = SNESFASSetGalerkin(snes, galerkinflg);CHKERRQ(ierr); 267ab8d36c9SPeter Brune } 268ee78dd50SPeter Brune 269928e959bSPeter Brune if (fas->fastype == SNES_FAS_FULL) { 270928e959bSPeter Brune ierr = PetscOptionsBool("-snes_fas_full_downsweep","Smooth on the initial upsweep for full FAS cycles","SNESFASFullSetDownSweep",fas->full_downsweep,&fas->full_downsweep,&flg);CHKERRQ(ierr); 271928e959bSPeter Brune if (flg) {SNESFASFullSetDownSweep(snes,fas->full_downsweep);CHKERRQ(ierr);} 272928e959bSPeter Brune } 273928e959bSPeter Brune 27466585501SPeter Brune ierr = PetscOptionsInt("-snes_fas_smoothup","Number of post-smoothing steps","SNESFASSetNumberSmoothUp",fas->max_up_it,&n_up,&upflg);CHKERRQ(ierr); 275162d76ddSPeter Brune 27666585501SPeter Brune ierr = PetscOptionsInt("-snes_fas_smoothdown","Number of pre-smoothing steps","SNESFASSetNumberSmoothDown",fas->max_down_it,&n_down,&downflg);CHKERRQ(ierr); 277162d76ddSPeter Brune 278d142ab34SLawrence Mitchell { 279d142ab34SLawrence Mitchell PetscViewer viewer; 280d142ab34SLawrence Mitchell PetscViewerFormat format; 281d142ab34SLawrence Mitchell ierr = PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes),((PetscObject)snes)->prefix, 282d142ab34SLawrence Mitchell "-snes_fas_monitor",&viewer,&format,&monflg);CHKERRQ(ierr); 283d142ab34SLawrence Mitchell if (monflg) { 284d142ab34SLawrence Mitchell PetscViewerAndFormat *vf; 285d142ab34SLawrence Mitchell ierr = PetscViewerAndFormatCreate(viewer,format,&vf);CHKERRQ(ierr); 286d142ab34SLawrence Mitchell ierr = PetscObjectDereference((PetscObject)viewer);CHKERRQ(ierr); 287d142ab34SLawrence Mitchell ierr = SNESFASSetMonitor(snes,vf,PETSC_TRUE);CHKERRQ(ierr); 288d142ab34SLawrence Mitchell } 289d142ab34SLawrence Mitchell } 2900dd27c6cSPeter Brune flg = PETSC_FALSE; 2910dd27c6cSPeter Brune monflg = PETSC_TRUE; 2920dd27c6cSPeter Brune ierr = PetscOptionsBool("-snes_fas_log","Log times for each FAS level","SNESFASSetLog",monflg,&monflg,&flg);CHKERRQ(ierr); 2930dd27c6cSPeter Brune if (flg) {ierr = SNESFASSetLog(snes,monflg);CHKERRQ(ierr);} 294ab8d36c9SPeter Brune } 295ee78dd50SPeter Brune 296421d9b32SPeter Brune ierr = PetscOptionsTail();CHKERRQ(ierr); 2978cc86e31SPeter Brune /* setup from the determined types if there is no pointwise procedure or smoother defined */ 298162d76ddSPeter Brune if (upflg) { 29966585501SPeter Brune ierr = SNESFASSetNumberSmoothUp(snes,n_up);CHKERRQ(ierr); 300162d76ddSPeter Brune } 301162d76ddSPeter Brune if (downflg) { 30266585501SPeter Brune ierr = SNESFASSetNumberSmoothDown(snes,n_down);CHKERRQ(ierr); 303162d76ddSPeter Brune } 304eff52c0eSPeter Brune 3059e764e56SPeter Brune /* set up the default line search for coarse grid corrections */ 3069e764e56SPeter Brune if (fas->fastype == SNES_FAS_ADDITIVE) { 3079e764e56SPeter Brune if (!snes->linesearch) { 3087601faf0SJed Brown ierr = SNESGetLineSearch(snes, &linesearch);CHKERRQ(ierr); 3091a4f838cSPeter Brune ierr = SNESLineSearchSetType(linesearch, SNESLINESEARCHL2);CHKERRQ(ierr); 3109e764e56SPeter Brune } 3119e764e56SPeter Brune } 3129e764e56SPeter Brune 313ab8d36c9SPeter Brune ierr = SNESFASCycleGetCorrection(snes, &next);CHKERRQ(ierr); 314ee78dd50SPeter Brune /* recursive option setting for the smoothers */ 315ab8d36c9SPeter Brune if (next) {ierr = SNESSetFromOptions(next);CHKERRQ(ierr);} 316421d9b32SPeter Brune PetscFunctionReturn(0); 317421d9b32SPeter Brune } 318421d9b32SPeter Brune 3199804daf3SBarry Smith #include <petscdraw.h> 32040244768SBarry Smith static PetscErrorCode SNESView_FAS(SNES snes, PetscViewer viewer) 321421d9b32SPeter Brune { 322421d9b32SPeter Brune SNES_FAS *fas = (SNES_FAS*) snes->data; 323656ede7eSPeter Brune PetscBool isFine,iascii,isdraw; 324ab8d36c9SPeter Brune PetscInt i; 325421d9b32SPeter Brune PetscErrorCode ierr; 326ab8d36c9SPeter Brune SNES smoothu, smoothd, levelsnes; 327421d9b32SPeter Brune 328421d9b32SPeter Brune PetscFunctionBegin; 329ab8d36c9SPeter Brune ierr = SNESFASCycleIsFine(snes, &isFine);CHKERRQ(ierr); 330ab8d36c9SPeter Brune if (isFine) { 331251f4c67SDmitry Karpeev ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr); 332656ede7eSPeter Brune ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERDRAW,&isdraw);CHKERRQ(ierr); 333421d9b32SPeter Brune if (iascii) { 334efd4aadfSBarry Smith ierr = PetscViewerASCIIPrintf(viewer, " type is %s, levels=%D, cycles=%D\n", SNESFASTypes[fas->fastype], fas->levels, fas->n_cycles);CHKERRQ(ierr); 335ab8d36c9SPeter Brune if (fas->galerkin) { 336ab8d36c9SPeter Brune ierr = PetscViewerASCIIPrintf(viewer," Using Galerkin computed coarse grid function evaluation\n");CHKERRQ(ierr); 337421d9b32SPeter Brune } else { 338ab8d36c9SPeter Brune ierr = PetscViewerASCIIPrintf(viewer," Not using Galerkin computed coarse grid function evaluation\n");CHKERRQ(ierr); 339421d9b32SPeter Brune } 340ab8d36c9SPeter Brune for (i=0; i<fas->levels; i++) { 341ab8d36c9SPeter Brune ierr = SNESFASGetCycleSNES(snes, i, &levelsnes);CHKERRQ(ierr); 342ab8d36c9SPeter Brune ierr = SNESFASCycleGetSmootherUp(levelsnes, &smoothu);CHKERRQ(ierr); 343ab8d36c9SPeter Brune ierr = SNESFASCycleGetSmootherDown(levelsnes, &smoothd);CHKERRQ(ierr); 344ab8d36c9SPeter Brune if (!i) { 345ab8d36c9SPeter Brune ierr = PetscViewerASCIIPrintf(viewer," Coarse grid solver -- level %D -------------------------------\n",i);CHKERRQ(ierr); 346421d9b32SPeter Brune } else { 347ab8d36c9SPeter Brune ierr = PetscViewerASCIIPrintf(viewer," Down solver (pre-smoother) on level %D -------------------------------\n",i);CHKERRQ(ierr); 348421d9b32SPeter Brune } 349ab8d36c9SPeter Brune ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); 350166b3ea4SJed Brown if (smoothd) { 351ab8d36c9SPeter Brune ierr = SNESView(smoothd,viewer);CHKERRQ(ierr); 352166b3ea4SJed Brown } else { 353166b3ea4SJed Brown ierr = PetscViewerASCIIPrintf(viewer,"Not yet available\n");CHKERRQ(ierr); 354166b3ea4SJed Brown } 355ab8d36c9SPeter Brune ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); 356ab8d36c9SPeter Brune if (i && (smoothd == smoothu)) { 357ab8d36c9SPeter Brune ierr = PetscViewerASCIIPrintf(viewer," Up solver (post-smoother) same as down solver (pre-smoother)\n");CHKERRQ(ierr); 358ab8d36c9SPeter Brune } else if (i) { 359ab8d36c9SPeter Brune ierr = PetscViewerASCIIPrintf(viewer," Up solver (post-smoother) on level %D -------------------------------\n",i);CHKERRQ(ierr); 360ab8d36c9SPeter Brune ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); 361166b3ea4SJed Brown if (smoothu) { 362ab8d36c9SPeter Brune ierr = SNESView(smoothu,viewer);CHKERRQ(ierr); 363166b3ea4SJed Brown } else { 364166b3ea4SJed Brown ierr = PetscViewerASCIIPrintf(viewer,"Not yet available\n");CHKERRQ(ierr); 365166b3ea4SJed Brown } 366ab8d36c9SPeter Brune ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); 367ab8d36c9SPeter Brune } 368ab8d36c9SPeter Brune } 369656ede7eSPeter Brune } else if (isdraw) { 370656ede7eSPeter Brune PetscDraw draw; 371b4375e8dSPeter Brune PetscReal x,w,y,bottom,th,wth; 372656ede7eSPeter Brune SNES_FAS *curfas = fas; 373656ede7eSPeter Brune ierr = PetscViewerDrawGetDraw(viewer,0,&draw);CHKERRQ(ierr); 374656ede7eSPeter Brune ierr = PetscDrawGetCurrentPoint(draw,&x,&y);CHKERRQ(ierr); 375656ede7eSPeter Brune ierr = PetscDrawStringGetSize(draw,&wth,&th);CHKERRQ(ierr); 376656ede7eSPeter Brune bottom = y - th; 377656ede7eSPeter Brune while (curfas) { 378b4375e8dSPeter Brune if (!curfas->smoothu) { 379656ede7eSPeter Brune ierr = PetscDrawPushCurrentPoint(draw,x,bottom);CHKERRQ(ierr); 380656ede7eSPeter Brune if (curfas->smoothd) ierr = SNESView(curfas->smoothd,viewer);CHKERRQ(ierr); 381656ede7eSPeter Brune ierr = PetscDrawPopCurrentPoint(draw);CHKERRQ(ierr); 382b4375e8dSPeter Brune } else { 383b4375e8dSPeter Brune w = 0.5*PetscMin(1.0-x,x); 384b4375e8dSPeter Brune ierr = PetscDrawPushCurrentPoint(draw,x-w,bottom);CHKERRQ(ierr); 385b4375e8dSPeter Brune if (curfas->smoothd) ierr = SNESView(curfas->smoothd,viewer);CHKERRQ(ierr); 386b4375e8dSPeter Brune ierr = PetscDrawPopCurrentPoint(draw);CHKERRQ(ierr); 387b4375e8dSPeter Brune ierr = PetscDrawPushCurrentPoint(draw,x+w,bottom);CHKERRQ(ierr); 388b4375e8dSPeter Brune if (curfas->smoothu) ierr = SNESView(curfas->smoothu,viewer);CHKERRQ(ierr); 389b4375e8dSPeter Brune ierr = PetscDrawPopCurrentPoint(draw);CHKERRQ(ierr); 390b4375e8dSPeter Brune } 391656ede7eSPeter Brune /* this is totally bogus but we have no way of knowing how low the previous one was draw to */ 392656ede7eSPeter Brune bottom -= 5*th; 3931aa26658SKarl Rupp if (curfas->next) curfas = (SNES_FAS*)curfas->next->data; 3940298fd71SBarry Smith else curfas = NULL; 395656ede7eSPeter Brune } 396421d9b32SPeter Brune } 397ab8d36c9SPeter Brune } 398421d9b32SPeter Brune PetscFunctionReturn(0); 399421d9b32SPeter Brune } 400421d9b32SPeter Brune 40139bd7f45SPeter Brune /* 40239bd7f45SPeter Brune Defines the action of the downsmoother 40339bd7f45SPeter Brune */ 40440244768SBarry Smith static PetscErrorCode SNESFASDownSmooth_Private(SNES snes, Vec B, Vec X, Vec F, PetscReal *fnorm) 405b9c2fdf1SPeter Brune { 40639bd7f45SPeter Brune PetscErrorCode ierr = 0; 407742fe5e2SPeter Brune SNESConvergedReason reason; 408ab8d36c9SPeter Brune Vec FPC; 409ab8d36c9SPeter Brune SNES smoothd; 4106cbb2f26SLawrence Mitchell PetscBool flg; 4110dd27c6cSPeter Brune SNES_FAS *fas = (SNES_FAS*) snes->data; 4126e111a19SKarl Rupp 413421d9b32SPeter Brune PetscFunctionBegin; 414ab8d36c9SPeter Brune ierr = SNESFASCycleGetSmootherDown(snes, &smoothd);CHKERRQ(ierr); 415e4ed7901SPeter Brune ierr = SNESSetInitialFunction(smoothd, F);CHKERRQ(ierr); 4160dd27c6cSPeter Brune if (fas->eventsmoothsolve) {ierr = PetscLogEventBegin(fas->eventsmoothsolve,0,0,0,0);CHKERRQ(ierr);} 417ab8d36c9SPeter Brune ierr = SNESSolve(smoothd, B, X);CHKERRQ(ierr); 4180dd27c6cSPeter Brune if (fas->eventsmoothsolve) {ierr = PetscLogEventEnd(fas->eventsmoothsolve,0,0,0,0);CHKERRQ(ierr);} 419742fe5e2SPeter Brune /* check convergence reason for the smoother */ 420ab8d36c9SPeter Brune ierr = SNESGetConvergedReason(smoothd,&reason);CHKERRQ(ierr); 4211ff805c3SPeter Brune if (reason < 0 && !(reason == SNES_DIVERGED_MAX_IT || reason == SNES_DIVERGED_LOCAL_MIN || reason == SNES_DIVERGED_LINE_SEARCH)) { 422742fe5e2SPeter Brune snes->reason = SNES_DIVERGED_INNER; 423742fe5e2SPeter Brune PetscFunctionReturn(0); 424742fe5e2SPeter Brune } 4256cbb2f26SLawrence Mitchell 4260298fd71SBarry Smith ierr = SNESGetFunction(smoothd, &FPC, NULL, NULL);CHKERRQ(ierr); 4276cbb2f26SLawrence Mitchell ierr = SNESGetAlwaysComputesFinalResidual(smoothd, &flg);CHKERRQ(ierr); 4286cbb2f26SLawrence Mitchell if (!flg) { 4296cbb2f26SLawrence Mitchell ierr = SNESComputeFunction(smoothd, X, FPC);CHKERRQ(ierr); 4306cbb2f26SLawrence Mitchell } 4314b32a720SPeter Brune ierr = VecCopy(FPC, F);CHKERRQ(ierr); 43271dbe336SPeter Brune if (fnorm) {ierr = VecNorm(F,NORM_2,fnorm);CHKERRQ(ierr);} 43339bd7f45SPeter Brune PetscFunctionReturn(0); 43439bd7f45SPeter Brune } 43539bd7f45SPeter Brune 43639bd7f45SPeter Brune 43739bd7f45SPeter Brune /* 43807144faaSPeter Brune Defines the action of the upsmoother 43939bd7f45SPeter Brune */ 44040244768SBarry Smith static PetscErrorCode SNESFASUpSmooth_Private(SNES snes, Vec B, Vec X, Vec F, PetscReal *fnorm) 4410adebc6cSBarry Smith { 44239bd7f45SPeter Brune PetscErrorCode ierr = 0; 44339bd7f45SPeter Brune SNESConvergedReason reason; 444ab8d36c9SPeter Brune Vec FPC; 445ab8d36c9SPeter Brune SNES smoothu; 4466cbb2f26SLawrence Mitchell PetscBool flg; 4470dd27c6cSPeter Brune SNES_FAS *fas = (SNES_FAS*) snes->data; 448ab8d36c9SPeter Brune 4496e111a19SKarl Rupp PetscFunctionBegin; 450ab8d36c9SPeter Brune ierr = SNESFASCycleGetSmootherUp(snes, &smoothu);CHKERRQ(ierr); 4510dd27c6cSPeter Brune if (fas->eventsmoothsolve) {ierr = PetscLogEventBegin(fas->eventsmoothsolve,0,0,0,0);CHKERRQ(ierr);} 452ab8d36c9SPeter Brune ierr = SNESSolve(smoothu, B, X);CHKERRQ(ierr); 4530dd27c6cSPeter Brune if (fas->eventsmoothsolve) {ierr = PetscLogEventEnd(fas->eventsmoothsolve,0,0,0,0);CHKERRQ(ierr);} 45439bd7f45SPeter Brune /* check convergence reason for the smoother */ 455ab8d36c9SPeter Brune ierr = SNESGetConvergedReason(smoothu,&reason);CHKERRQ(ierr); 4561ff805c3SPeter Brune if (reason < 0 && !(reason == SNES_DIVERGED_MAX_IT || reason == SNES_DIVERGED_LOCAL_MIN || reason == SNES_DIVERGED_LINE_SEARCH)) { 45739bd7f45SPeter Brune snes->reason = SNES_DIVERGED_INNER; 45839bd7f45SPeter Brune PetscFunctionReturn(0); 45939bd7f45SPeter Brune } 4600298fd71SBarry Smith ierr = SNESGetFunction(smoothu, &FPC, NULL, NULL);CHKERRQ(ierr); 4616cbb2f26SLawrence Mitchell ierr = SNESGetAlwaysComputesFinalResidual(smoothu, &flg);CHKERRQ(ierr); 4626cbb2f26SLawrence Mitchell if (!flg) { 4636cbb2f26SLawrence Mitchell ierr = SNESComputeFunction(smoothu, X, FPC);CHKERRQ(ierr); 4646cbb2f26SLawrence Mitchell } 4654b32a720SPeter Brune ierr = VecCopy(FPC, F);CHKERRQ(ierr); 46671dbe336SPeter Brune if (fnorm) {ierr = VecNorm(F,NORM_2,fnorm);CHKERRQ(ierr);} 46739bd7f45SPeter Brune PetscFunctionReturn(0); 46839bd7f45SPeter Brune } 46939bd7f45SPeter Brune 470938e4a01SJed Brown /*@ 471938e4a01SJed Brown SNESFASCreateCoarseVec - create Vec corresponding to a state vector on one level coarser than current level 472938e4a01SJed Brown 473938e4a01SJed Brown Collective 474938e4a01SJed Brown 475938e4a01SJed Brown Input Arguments: 476938e4a01SJed Brown . snes - SNESFAS 477938e4a01SJed Brown 478938e4a01SJed Brown Output Arguments: 479938e4a01SJed Brown . Xcoarse - vector on level one coarser than snes 480938e4a01SJed Brown 481938e4a01SJed Brown Level: developer 482938e4a01SJed Brown 483938e4a01SJed Brown .seealso: SNESFASSetRestriction(), SNESFASRestrict() 484938e4a01SJed Brown @*/ 485938e4a01SJed Brown PetscErrorCode SNESFASCreateCoarseVec(SNES snes,Vec *Xcoarse) 486938e4a01SJed Brown { 487938e4a01SJed Brown PetscErrorCode ierr; 488938e4a01SJed Brown SNES_FAS *fas = (SNES_FAS*)snes->data; 489938e4a01SJed Brown 490938e4a01SJed Brown PetscFunctionBegin; 4911aa26658SKarl Rupp if (fas->rscale) { 4921aa26658SKarl Rupp ierr = VecDuplicate(fas->rscale,Xcoarse);CHKERRQ(ierr); 493f5af7f23SKarl Rupp } else if (fas->inject) { 4942a7a6963SBarry Smith ierr = MatCreateVecs(fas->inject,Xcoarse,NULL);CHKERRQ(ierr); 49513903a91SSatish Balay } else SETERRQ(PetscObjectComm((PetscObject)snes),PETSC_ERR_ARG_WRONGSTATE,"Must set restriction or injection"); 496938e4a01SJed Brown PetscFunctionReturn(0); 497938e4a01SJed Brown } 498938e4a01SJed Brown 499e9923e8dSJed Brown /*@ 500e9923e8dSJed Brown SNESFASRestrict - restrict a Vec to the next coarser level 501e9923e8dSJed Brown 502e9923e8dSJed Brown Collective 503e9923e8dSJed Brown 504e9923e8dSJed Brown Input Arguments: 505e9923e8dSJed Brown + fine - SNES from which to restrict 506e9923e8dSJed Brown - Xfine - vector to restrict 507e9923e8dSJed Brown 508e9923e8dSJed Brown Output Arguments: 509e9923e8dSJed Brown . Xcoarse - result of restriction 510e9923e8dSJed Brown 511e9923e8dSJed Brown Level: developer 512e9923e8dSJed Brown 513e9923e8dSJed Brown .seealso: SNESFASSetRestriction(), SNESFASSetInjection() 514e9923e8dSJed Brown @*/ 515e9923e8dSJed Brown PetscErrorCode SNESFASRestrict(SNES fine,Vec Xfine,Vec Xcoarse) 516e9923e8dSJed Brown { 517e9923e8dSJed Brown PetscErrorCode ierr; 518e9923e8dSJed Brown SNES_FAS *fas = (SNES_FAS*)fine->data; 519e9923e8dSJed Brown 520e9923e8dSJed Brown PetscFunctionBegin; 521e9923e8dSJed Brown PetscValidHeaderSpecific(fine,SNES_CLASSID,1); 522e9923e8dSJed Brown PetscValidHeaderSpecific(Xfine,VEC_CLASSID,2); 523e9923e8dSJed Brown PetscValidHeaderSpecific(Xcoarse,VEC_CLASSID,3); 524e9923e8dSJed Brown if (fas->inject) { 525e9923e8dSJed Brown ierr = MatRestrict(fas->inject,Xfine,Xcoarse);CHKERRQ(ierr); 526e9923e8dSJed Brown } else { 527e9923e8dSJed Brown ierr = MatRestrict(fas->restrct,Xfine,Xcoarse);CHKERRQ(ierr); 528e9923e8dSJed Brown ierr = VecPointwiseMult(Xcoarse,fas->rscale,Xcoarse);CHKERRQ(ierr); 529e9923e8dSJed Brown } 530e9923e8dSJed Brown PetscFunctionReturn(0); 531e9923e8dSJed Brown } 532e9923e8dSJed Brown 53339bd7f45SPeter Brune /* 53439bd7f45SPeter Brune 53539bd7f45SPeter Brune Performs the FAS coarse correction as: 53639bd7f45SPeter Brune 537b5527d98SMatthew G. Knepley fine problem: F(x) = b 538b5527d98SMatthew G. Knepley coarse problem: F^c(x^c) = b^c 53939bd7f45SPeter Brune 540b5527d98SMatthew G. Knepley b^c = F^c(Rx) - R(F(x) - b) 54139bd7f45SPeter Brune 54239bd7f45SPeter Brune */ 5430adebc6cSBarry Smith PetscErrorCode SNESFASCoarseCorrection(SNES snes, Vec X, Vec F, Vec X_new) 5440adebc6cSBarry Smith { 54539bd7f45SPeter Brune PetscErrorCode ierr; 54639bd7f45SPeter Brune Vec X_c, Xo_c, F_c, B_c; 54739bd7f45SPeter Brune SNESConvergedReason reason; 548ab8d36c9SPeter Brune SNES next; 549ab8d36c9SPeter Brune Mat restrct, interpolate; 5500dd27c6cSPeter Brune SNES_FAS *fasc; 5515fd66863SKarl Rupp 55239bd7f45SPeter Brune PetscFunctionBegin; 553ab8d36c9SPeter Brune ierr = SNESFASCycleGetCorrection(snes, &next);CHKERRQ(ierr); 554ab8d36c9SPeter Brune if (next) { 5550dd27c6cSPeter Brune fasc = (SNES_FAS*)next->data; 5560dd27c6cSPeter Brune 557ab8d36c9SPeter Brune ierr = SNESFASCycleGetRestriction(snes, &restrct);CHKERRQ(ierr); 558ab8d36c9SPeter Brune ierr = SNESFASCycleGetInterpolation(snes, &interpolate);CHKERRQ(ierr); 559ab8d36c9SPeter Brune 560ab8d36c9SPeter Brune X_c = next->vec_sol; 561ab8d36c9SPeter Brune Xo_c = next->work[0]; 562ab8d36c9SPeter Brune F_c = next->vec_func; 563ab8d36c9SPeter Brune B_c = next->vec_rhs; 564efe1f98aSPeter Brune 5650dd27c6cSPeter Brune if (fasc->eventinterprestrict) {ierr = PetscLogEventBegin(fasc->eventinterprestrict,0,0,0,0);CHKERRQ(ierr);} 566938e4a01SJed Brown ierr = SNESFASRestrict(snes,X,Xo_c);CHKERRQ(ierr); 5675609cbf2SMatthew G. Knepley /* restrict the defect: R(F(x) - b) */ 568ab8d36c9SPeter Brune ierr = MatRestrict(restrct, F, B_c);CHKERRQ(ierr); 5690dd27c6cSPeter Brune if (fasc->eventinterprestrict) {ierr = PetscLogEventEnd(fasc->eventinterprestrict,0,0,0,0);CHKERRQ(ierr);} 5700dd27c6cSPeter Brune 5710dd27c6cSPeter Brune if (fasc->eventresidual) {ierr = PetscLogEventBegin(fasc->eventresidual,0,0,0,0);CHKERRQ(ierr);} 5725609cbf2SMatthew G. Knepley /* F_c = F^c(Rx) - R(F(x) - b) since the second term was sitting in next->vec_rhs */ 573ab8d36c9SPeter Brune ierr = SNESComputeFunction(next, Xo_c, F_c);CHKERRQ(ierr); 5740dd27c6cSPeter Brune if (fasc->eventresidual) {ierr = PetscLogEventEnd(fasc->eventresidual,0,0,0,0);CHKERRQ(ierr);} 5750dd27c6cSPeter Brune 5760dd27c6cSPeter Brune /* solve the coarse problem corresponding to F^c(x^c) = b^c = F^c(Rx) - R(F(x) - b) */ 577e4ed7901SPeter Brune ierr = VecCopy(B_c, X_c);CHKERRQ(ierr); 578b9c2fdf1SPeter Brune ierr = VecCopy(F_c, B_c);CHKERRQ(ierr); 579e4ed7901SPeter Brune ierr = VecCopy(X_c, F_c);CHKERRQ(ierr); 580ee78dd50SPeter Brune /* set initial guess of the coarse problem to the projected fine solution */ 581ee78dd50SPeter Brune ierr = VecCopy(Xo_c, X_c);CHKERRQ(ierr); 582c90fad12SPeter Brune 583c90fad12SPeter Brune /* recurse to the next level */ 584e4ed7901SPeter Brune ierr = SNESSetInitialFunction(next, F_c);CHKERRQ(ierr); 585ab8d36c9SPeter Brune ierr = SNESSolve(next, B_c, X_c);CHKERRQ(ierr); 586ab8d36c9SPeter Brune ierr = SNESGetConvergedReason(next,&reason);CHKERRQ(ierr); 587742fe5e2SPeter Brune if (reason < 0 && reason != SNES_DIVERGED_MAX_IT) { 588742fe5e2SPeter Brune snes->reason = SNES_DIVERGED_INNER; 589742fe5e2SPeter Brune PetscFunctionReturn(0); 590742fe5e2SPeter Brune } 591fa9694d7SPeter Brune /* correct as x <- x + I(x^c - Rx)*/ 592fa9694d7SPeter Brune ierr = VecAXPY(X_c, -1.0, Xo_c);CHKERRQ(ierr); 5930dd27c6cSPeter Brune 5940dd27c6cSPeter Brune if (fasc->eventinterprestrict) {ierr = PetscLogEventBegin(fasc->eventinterprestrict,0,0,0,0);CHKERRQ(ierr);} 595ab8d36c9SPeter Brune ierr = MatInterpolateAdd(interpolate, X_c, X, X_new);CHKERRQ(ierr); 5960dd27c6cSPeter Brune if (fasc->eventinterprestrict) {ierr = PetscLogEventEnd(fasc->eventinterprestrict,0,0,0,0);CHKERRQ(ierr);} 597293a7e31SPeter Brune } 59839bd7f45SPeter Brune PetscFunctionReturn(0); 59939bd7f45SPeter Brune } 60039bd7f45SPeter Brune 60139bd7f45SPeter Brune /* 60239bd7f45SPeter Brune 60339bd7f45SPeter Brune The additive cycle looks like: 60439bd7f45SPeter Brune 60507144faaSPeter Brune xhat = x 60607144faaSPeter Brune xhat = dS(x, b) 60707144faaSPeter Brune x = coarsecorrection(xhat, b_d) 60807144faaSPeter Brune x = x + nu*(xhat - x); 60939bd7f45SPeter Brune (optional) x = uS(x, b) 61039bd7f45SPeter Brune 61139bd7f45SPeter Brune With the coarse RHS (defect correction) as below. 61239bd7f45SPeter Brune 61339bd7f45SPeter Brune */ 61440244768SBarry Smith static PetscErrorCode SNESFASCycle_Additive(SNES snes, Vec X) 6150adebc6cSBarry Smith { 61607144faaSPeter Brune Vec F, B, Xhat; 61722c1e704SPeter Brune Vec X_c, Xo_c, F_c, B_c; 61839bd7f45SPeter Brune PetscErrorCode ierr; 61907144faaSPeter Brune SNESConvergedReason reason; 62022c1e704SPeter Brune PetscReal xnorm, fnorm, ynorm; 621422a814eSBarry Smith SNESLineSearchReason lsresult; 622ab8d36c9SPeter Brune SNES next; 623ab8d36c9SPeter Brune Mat restrct, interpolate; 6240dd27c6cSPeter Brune SNES_FAS *fas = (SNES_FAS*)snes->data,*fasc; 6250dd27c6cSPeter Brune 62639bd7f45SPeter Brune PetscFunctionBegin; 627ab8d36c9SPeter Brune ierr = SNESFASCycleGetCorrection(snes, &next);CHKERRQ(ierr); 62839bd7f45SPeter Brune F = snes->vec_func; 62939bd7f45SPeter Brune B = snes->vec_rhs; 630e7f468e7SPeter Brune Xhat = snes->work[1]; 63107144faaSPeter Brune ierr = VecCopy(X, Xhat);CHKERRQ(ierr); 63207144faaSPeter Brune /* recurse first */ 633ab8d36c9SPeter Brune if (next) { 6340dd27c6cSPeter Brune fasc = (SNES_FAS*)next->data; 635ab8d36c9SPeter Brune ierr = SNESFASCycleGetRestriction(snes, &restrct);CHKERRQ(ierr); 636ab8d36c9SPeter Brune ierr = SNESFASCycleGetInterpolation(snes, &interpolate);CHKERRQ(ierr); 6370dd27c6cSPeter Brune if (fas->eventresidual) {ierr = PetscLogEventBegin(fas->eventresidual,0,0,0,0);CHKERRQ(ierr);} 63807144faaSPeter Brune ierr = SNESComputeFunction(snes, Xhat, F);CHKERRQ(ierr); 6390dd27c6cSPeter Brune if (fas->eventresidual) {ierr = PetscLogEventEnd(fas->eventresidual,0,0,0,0);CHKERRQ(ierr);} 640c2a02606SPeter Brune ierr = VecNorm(F, NORM_2, &fnorm);CHKERRQ(ierr); 641ab8d36c9SPeter Brune X_c = next->vec_sol; 642ab8d36c9SPeter Brune Xo_c = next->work[0]; 643ab8d36c9SPeter Brune F_c = next->vec_func; 644ab8d36c9SPeter Brune B_c = next->vec_rhs; 64539bd7f45SPeter Brune 646938e4a01SJed Brown ierr = SNESFASRestrict(snes,Xhat,Xo_c);CHKERRQ(ierr); 64707144faaSPeter Brune /* restrict the defect */ 648ab8d36c9SPeter Brune ierr = MatRestrict(restrct, F, B_c);CHKERRQ(ierr); 64907144faaSPeter Brune 65007144faaSPeter Brune /* solve the coarse problem corresponding to F^c(x^c) = b^c = Rb + F^c(Rx) - RF(x) */ 6510dd27c6cSPeter Brune if (fasc->eventresidual) {ierr = PetscLogEventBegin(fasc->eventresidual,0,0,0,0);CHKERRQ(ierr);} 652ab8d36c9SPeter Brune ierr = SNESComputeFunction(next, Xo_c, F_c);CHKERRQ(ierr); 6530dd27c6cSPeter Brune if (fasc->eventresidual) {ierr = PetscLogEventEnd(fasc->eventresidual,0,0,0,0);CHKERRQ(ierr);} 654e4ed7901SPeter Brune ierr = VecCopy(B_c, X_c);CHKERRQ(ierr); 655b9c2fdf1SPeter Brune ierr = VecCopy(F_c, B_c);CHKERRQ(ierr); 656e4ed7901SPeter Brune ierr = VecCopy(X_c, F_c);CHKERRQ(ierr); 65707144faaSPeter Brune /* set initial guess of the coarse problem to the projected fine solution */ 65807144faaSPeter Brune ierr = VecCopy(Xo_c, X_c);CHKERRQ(ierr); 65907144faaSPeter Brune 66007144faaSPeter Brune /* recurse */ 661e4ed7901SPeter Brune ierr = SNESSetInitialFunction(next, F_c);CHKERRQ(ierr); 662ab8d36c9SPeter Brune ierr = SNESSolve(next, B_c, X_c);CHKERRQ(ierr); 66307144faaSPeter Brune 66407144faaSPeter Brune /* smooth on this level */ 66591f99d7cSPeter Brune ierr = SNESFASDownSmooth_Private(snes, B, X, F, &fnorm);CHKERRQ(ierr); 66607144faaSPeter Brune 667ab8d36c9SPeter Brune ierr = SNESGetConvergedReason(next,&reason);CHKERRQ(ierr); 66807144faaSPeter Brune if (reason < 0 && reason != SNES_DIVERGED_MAX_IT) { 66907144faaSPeter Brune snes->reason = SNES_DIVERGED_INNER; 67007144faaSPeter Brune PetscFunctionReturn(0); 67107144faaSPeter Brune } 67207144faaSPeter Brune 67307144faaSPeter Brune /* correct as x <- x + I(x^c - Rx)*/ 674c68acad4SPeter Brune ierr = VecAYPX(X_c, -1.0, Xo_c);CHKERRQ(ierr); 675ab8d36c9SPeter Brune ierr = MatInterpolate(interpolate, X_c, Xhat);CHKERRQ(ierr); 67607144faaSPeter Brune 677ddebd997SPeter Brune /* additive correction of the coarse direction*/ 678f1c6b773SPeter Brune ierr = SNESLineSearchApply(snes->linesearch, X, F, &fnorm, Xhat);CHKERRQ(ierr); 679422a814eSBarry Smith ierr = SNESLineSearchGetReason(snes->linesearch, &lsresult);CHKERRQ(ierr); 680422a814eSBarry Smith ierr = SNESLineSearchGetNorms(snes->linesearch, &xnorm, &snes->norm, &ynorm);CHKERRQ(ierr); 681422a814eSBarry Smith if (lsresult) { 6829e764e56SPeter Brune if (++snes->numFailures >= snes->maxFailures) { 6839e764e56SPeter Brune snes->reason = SNES_DIVERGED_LINE_SEARCH; 6849e764e56SPeter Brune PetscFunctionReturn(0); 6859e764e56SPeter Brune } 6869e764e56SPeter Brune } 68707144faaSPeter Brune } else { 68891f99d7cSPeter Brune ierr = SNESFASDownSmooth_Private(snes, B, X, F, &snes->norm);CHKERRQ(ierr); 68907144faaSPeter Brune } 69039bd7f45SPeter Brune PetscFunctionReturn(0); 69139bd7f45SPeter Brune } 69239bd7f45SPeter Brune 69339bd7f45SPeter Brune /* 69439bd7f45SPeter Brune 69539bd7f45SPeter Brune Defines the FAS cycle as: 69639bd7f45SPeter Brune 697b5527d98SMatthew G. Knepley fine problem: F(x) = b 69839bd7f45SPeter Brune coarse problem: F^c(x) = b^c 69939bd7f45SPeter Brune 700b5527d98SMatthew G. Knepley b^c = F^c(Rx) - R(F(x) - b) 70139bd7f45SPeter Brune 70239bd7f45SPeter Brune correction: 70339bd7f45SPeter Brune 70439bd7f45SPeter Brune x = x + I(x^c - Rx) 70539bd7f45SPeter Brune 70639bd7f45SPeter Brune */ 70740244768SBarry Smith static PetscErrorCode SNESFASCycle_Multiplicative(SNES snes, Vec X) 7080adebc6cSBarry Smith { 70939bd7f45SPeter Brune 71039bd7f45SPeter Brune PetscErrorCode ierr; 71139bd7f45SPeter Brune Vec F,B; 71234d65b3cSPeter Brune SNES next; 71339bd7f45SPeter Brune 71439bd7f45SPeter Brune PetscFunctionBegin; 71539bd7f45SPeter Brune F = snes->vec_func; 71639bd7f45SPeter Brune B = snes->vec_rhs; 71739bd7f45SPeter Brune /* pre-smooth -- just update using the pre-smoother */ 71834d65b3cSPeter Brune ierr = SNESFASCycleGetCorrection(snes,&next);CHKERRQ(ierr); 71991f99d7cSPeter Brune ierr = SNESFASDownSmooth_Private(snes, B, X, F, &snes->norm);CHKERRQ(ierr); 72034d65b3cSPeter Brune if (next) { 7218c40d5fbSBarry Smith ierr = SNESFASCoarseCorrection(snes, X, F, X);CHKERRQ(ierr); 72291f99d7cSPeter Brune ierr = SNESFASUpSmooth_Private(snes, B, X, F, &snes->norm);CHKERRQ(ierr); 723fe6f9142SPeter Brune } 724fa9694d7SPeter Brune PetscFunctionReturn(0); 725421d9b32SPeter Brune } 726421d9b32SPeter Brune 72740244768SBarry Smith static PetscErrorCode SNESFASCycleSetupPhase_Full(SNES snes) 7288c94862eSPeter Brune { 7298c94862eSPeter Brune SNES next; 7308c94862eSPeter Brune SNES_FAS *fas = (SNES_FAS*)snes->data; 7318c94862eSPeter Brune PetscBool isFine; 7328c94862eSPeter Brune PetscErrorCode ierr; 7338c94862eSPeter Brune 7348c94862eSPeter Brune PetscFunctionBegin; 7358c94862eSPeter Brune /* pre-smooth -- just update using the pre-smoother */ 7368c94862eSPeter Brune ierr = SNESFASCycleIsFine(snes,&isFine);CHKERRQ(ierr); 7378c94862eSPeter Brune ierr = SNESFASCycleGetCorrection(snes,&next);CHKERRQ(ierr); 7388c94862eSPeter Brune fas->full_stage = 0; 7398c94862eSPeter Brune if (next) {ierr = SNESFASCycleSetupPhase_Full(next);CHKERRQ(ierr);} 7408c94862eSPeter Brune PetscFunctionReturn(0); 7418c94862eSPeter Brune } 7428c94862eSPeter Brune 74340244768SBarry Smith static PetscErrorCode SNESFASCycle_Full(SNES snes, Vec X) 7448c94862eSPeter Brune { 7458c94862eSPeter Brune PetscErrorCode ierr; 7468c94862eSPeter Brune Vec F,B; 7478c94862eSPeter Brune SNES_FAS *fas = (SNES_FAS*)snes->data; 7488c94862eSPeter Brune PetscBool isFine; 7498c94862eSPeter Brune SNES next; 7508c94862eSPeter Brune 7518c94862eSPeter Brune PetscFunctionBegin; 7528c94862eSPeter Brune F = snes->vec_func; 7538c94862eSPeter Brune B = snes->vec_rhs; 7548c94862eSPeter Brune ierr = SNESFASCycleIsFine(snes,&isFine);CHKERRQ(ierr); 7558c94862eSPeter Brune ierr = SNESFASCycleGetCorrection(snes,&next);CHKERRQ(ierr); 7568c94862eSPeter Brune 7578c94862eSPeter Brune if (isFine) { 7588c94862eSPeter Brune ierr = SNESFASCycleSetupPhase_Full(snes);CHKERRQ(ierr); 7598c94862eSPeter Brune } 7608c94862eSPeter Brune 7618c94862eSPeter Brune if (fas->full_stage == 0) { 762928e959bSPeter Brune /* downsweep */ 7638c94862eSPeter Brune if (next) { 7648c94862eSPeter Brune if (fas->level != 1) next->max_its += 1; 765928e959bSPeter Brune if (fas->full_downsweep||isFine) {ierr = SNESFASDownSmooth_Private(snes,B,X,F,&snes->norm);CHKERRQ(ierr);} 7668c94862eSPeter Brune ierr = SNESFASCoarseCorrection(snes,X,F,X);CHKERRQ(ierr); 7678c94862eSPeter Brune ierr = SNESFASUpSmooth_Private(snes,B,X,F,&snes->norm);CHKERRQ(ierr); 7688c94862eSPeter Brune if (fas->level != 1) next->max_its -= 1; 7698c94862eSPeter Brune } else { 770a3a80b83SMatthew G. Knepley /* The smoother on the coarse level is the coarse solver */ 7718c94862eSPeter Brune ierr = SNESFASDownSmooth_Private(snes,B,X,F,&snes->norm);CHKERRQ(ierr); 7728c94862eSPeter Brune } 7738c94862eSPeter Brune fas->full_stage = 1; 7748c94862eSPeter Brune } else if (fas->full_stage == 1) { 7758c94862eSPeter Brune if (snes->iter == 0) {ierr = SNESFASDownSmooth_Private(snes,B,X,F,&snes->norm);CHKERRQ(ierr);} 7768c94862eSPeter Brune if (next) { 7778c94862eSPeter Brune ierr = SNESFASCoarseCorrection(snes,X,F,X);CHKERRQ(ierr); 7788c94862eSPeter Brune ierr = SNESFASUpSmooth_Private(snes,B,X,F,&snes->norm);CHKERRQ(ierr); 7798c94862eSPeter Brune } 7808c94862eSPeter Brune } 7818c94862eSPeter Brune /* final v-cycle */ 7828c94862eSPeter Brune if (isFine) { 7838c94862eSPeter Brune if (next) { 7848c94862eSPeter Brune ierr = SNESFASCoarseCorrection(snes,X,F,X);CHKERRQ(ierr); 7858c94862eSPeter Brune ierr = SNESFASUpSmooth_Private(snes,B,X,F,&snes->norm);CHKERRQ(ierr); 7868c94862eSPeter Brune } 7878c94862eSPeter Brune } 7888c94862eSPeter Brune PetscFunctionReturn(0); 7898c94862eSPeter Brune } 7908c94862eSPeter Brune 79140244768SBarry Smith static PetscErrorCode SNESFASCycle_Kaskade(SNES snes, Vec X) 79234d65b3cSPeter Brune { 79334d65b3cSPeter Brune PetscErrorCode ierr; 79434d65b3cSPeter Brune Vec F,B; 79534d65b3cSPeter Brune SNES next; 79634d65b3cSPeter Brune 79734d65b3cSPeter Brune PetscFunctionBegin; 79834d65b3cSPeter Brune F = snes->vec_func; 79934d65b3cSPeter Brune B = snes->vec_rhs; 80034d65b3cSPeter Brune ierr = SNESFASCycleGetCorrection(snes,&next);CHKERRQ(ierr); 80134d65b3cSPeter Brune if (next) { 80234d65b3cSPeter Brune ierr = SNESFASCoarseCorrection(snes,X,F,X);CHKERRQ(ierr); 80334d65b3cSPeter Brune ierr = SNESFASUpSmooth_Private(snes,B,X,F,&snes->norm);CHKERRQ(ierr); 80434d65b3cSPeter Brune } else { 80534d65b3cSPeter Brune ierr = SNESFASDownSmooth_Private(snes,B,X,F,&snes->norm);CHKERRQ(ierr); 80634d65b3cSPeter Brune } 80734d65b3cSPeter Brune PetscFunctionReturn(0); 80834d65b3cSPeter Brune } 80934d65b3cSPeter Brune 810fffbeea8SBarry Smith PetscBool SNEScite = PETSC_FALSE; 811fffbeea8SBarry Smith const char SNESCitation[] = "@techreport{pbmkbsxt2012,\n" 812fffbeea8SBarry Smith " title = {Composing Scalable Nonlinear Algebraic Solvers},\n" 813fffbeea8SBarry Smith " author = {Peter Brune and Mathew Knepley and Barry Smith and Xuemin Tu},\n" 814fffbeea8SBarry Smith " year = 2013,\n" 815fffbeea8SBarry Smith " type = Preprint,\n" 816fffbeea8SBarry Smith " number = {ANL/MCS-P2010-0112},\n" 817fffbeea8SBarry Smith " institution = {Argonne National Laboratory}\n}\n"; 818fffbeea8SBarry Smith 81940244768SBarry Smith static PetscErrorCode SNESSolve_FAS(SNES snes) 820421d9b32SPeter Brune { 821fa9694d7SPeter Brune PetscErrorCode ierr; 822fe6f9142SPeter Brune PetscInt i, maxits; 823ddb5aff1SPeter Brune Vec X, F; 824fe6f9142SPeter Brune PetscReal fnorm; 825b17ce1afSJed Brown SNES_FAS *fas = (SNES_FAS*)snes->data,*ffas; 826b17ce1afSJed Brown DM dm; 827e70c42e5SPeter Brune PetscBool isFine; 828b17ce1afSJed Brown 829421d9b32SPeter Brune PetscFunctionBegin; 830c579b300SPatrick Farrell 8316c4ed002SBarry Smith if (snes->xl || snes->xu || snes->ops->computevariablebounds) SETERRQ1(PetscObjectComm((PetscObject)snes),PETSC_ERR_ARG_WRONGSTATE, "SNES solver %s does not support bounds", ((PetscObject)snes)->type_name); 832c579b300SPatrick Farrell 833fffbeea8SBarry Smith ierr = PetscCitationsRegister(SNESCitation,&SNEScite);CHKERRQ(ierr); 834fe6f9142SPeter Brune maxits = snes->max_its; /* maximum number of iterations */ 835fe6f9142SPeter Brune snes->reason = SNES_CONVERGED_ITERATING; 836fa9694d7SPeter Brune X = snes->vec_sol; 837f5a6d4f9SBarry Smith F = snes->vec_func; 838293a7e31SPeter Brune 83918a66777SPeter Brune ierr = SNESFASCycleIsFine(snes, &isFine);CHKERRQ(ierr); 840293a7e31SPeter Brune /*norm setup */ 841e04113cfSBarry Smith ierr = PetscObjectSAWsTakeAccess((PetscObject)snes);CHKERRQ(ierr); 842fe6f9142SPeter Brune snes->iter = 0; 843fe6f9142SPeter Brune snes->norm = 0.; 844e04113cfSBarry Smith ierr = PetscObjectSAWsGrantAccess((PetscObject)snes);CHKERRQ(ierr); 845e4ed7901SPeter Brune if (!snes->vec_func_init_set) { 8460dd27c6cSPeter Brune if (fas->eventresidual) {ierr = PetscLogEventBegin(fas->eventresidual,0,0,0,0);CHKERRQ(ierr);} 847fe6f9142SPeter Brune ierr = SNESComputeFunction(snes,X,F);CHKERRQ(ierr); 8480dd27c6cSPeter Brune if (fas->eventresidual) {ierr = PetscLogEventEnd(fas->eventresidual,0,0,0,0);CHKERRQ(ierr);} 8491aa26658SKarl Rupp } else snes->vec_func_init_set = PETSC_FALSE; 850e4ed7901SPeter Brune 851fe6f9142SPeter Brune ierr = VecNorm(F, NORM_2, &fnorm);CHKERRQ(ierr); /* fnorm <- ||F|| */ 852422a814eSBarry Smith SNESCheckFunctionNorm(snes,fnorm); 853e04113cfSBarry Smith ierr = PetscObjectSAWsTakeAccess((PetscObject)snes);CHKERRQ(ierr); 854fe6f9142SPeter Brune snes->norm = fnorm; 855e04113cfSBarry Smith ierr = PetscObjectSAWsGrantAccess((PetscObject)snes);CHKERRQ(ierr); 856a71f0d7dSBarry Smith ierr = SNESLogConvergenceHistory(snes,fnorm,0);CHKERRQ(ierr); 857fe6f9142SPeter Brune ierr = SNESMonitor(snes,0,fnorm);CHKERRQ(ierr); 858fe6f9142SPeter Brune 859fe6f9142SPeter Brune /* test convergence */ 860fe6f9142SPeter Brune ierr = (*snes->ops->converged)(snes,0,0.0,0.0,fnorm,&snes->reason,snes->cnvP);CHKERRQ(ierr); 861fe6f9142SPeter Brune if (snes->reason) PetscFunctionReturn(0); 862e4ed7901SPeter Brune 863b17ce1afSJed Brown 864b9c2fdf1SPeter Brune if (isFine) { 865b9c2fdf1SPeter Brune /* propagate scale-dependent data up the hierarchy */ 866b17ce1afSJed Brown ierr = SNESGetDM(snes,&dm);CHKERRQ(ierr); 867b17ce1afSJed Brown for (ffas=fas; ffas->next; ffas=(SNES_FAS*)ffas->next->data) { 868b17ce1afSJed Brown DM dmcoarse; 869b17ce1afSJed Brown ierr = SNESGetDM(ffas->next,&dmcoarse);CHKERRQ(ierr); 870b17ce1afSJed Brown ierr = DMRestrict(dm,ffas->restrct,ffas->rscale,ffas->inject,dmcoarse);CHKERRQ(ierr); 871b17ce1afSJed Brown dm = dmcoarse; 872b17ce1afSJed Brown } 873b9c2fdf1SPeter Brune } 874b17ce1afSJed Brown 875fe6f9142SPeter Brune for (i = 0; i < maxits; i++) { 876fe6f9142SPeter Brune /* Call general purpose update function */ 877646217ecSPeter Brune 878fe6f9142SPeter Brune if (snes->ops->update) { 879fe6f9142SPeter Brune ierr = (*snes->ops->update)(snes, snes->iter);CHKERRQ(ierr); 880fe6f9142SPeter Brune } 88107144faaSPeter Brune if (fas->fastype == SNES_FAS_MULTIPLICATIVE) { 88291f99d7cSPeter Brune ierr = SNESFASCycle_Multiplicative(snes, X);CHKERRQ(ierr); 8838c94862eSPeter Brune } else if (fas->fastype == SNES_FAS_ADDITIVE) { 88491f99d7cSPeter Brune ierr = SNESFASCycle_Additive(snes, X);CHKERRQ(ierr); 8858c94862eSPeter Brune } else if (fas->fastype == SNES_FAS_FULL) { 8868c94862eSPeter Brune ierr = SNESFASCycle_Full(snes, X);CHKERRQ(ierr); 88734d65b3cSPeter Brune } else if (fas->fastype ==SNES_FAS_KASKADE) { 88834d65b3cSPeter Brune ierr = SNESFASCycle_Kaskade(snes, X);CHKERRQ(ierr); 8896c4ed002SBarry Smith } else SETERRQ(PetscObjectComm((PetscObject)snes),PETSC_ERR_ARG_WRONGSTATE,"Unsupported FAS type"); 890742fe5e2SPeter Brune 891742fe5e2SPeter Brune /* check for FAS cycle divergence */ 8921aa26658SKarl Rupp if (snes->reason != SNES_CONVERGED_ITERATING) PetscFunctionReturn(0); 893b9c2fdf1SPeter Brune 894c90fad12SPeter Brune /* Monitor convergence */ 895e04113cfSBarry Smith ierr = PetscObjectSAWsTakeAccess((PetscObject)snes);CHKERRQ(ierr); 896c90fad12SPeter Brune snes->iter = i+1; 897e04113cfSBarry Smith ierr = PetscObjectSAWsGrantAccess((PetscObject)snes);CHKERRQ(ierr); 898a71f0d7dSBarry Smith ierr = SNESLogConvergenceHistory(snes,snes->norm,0);CHKERRQ(ierr); 899c90fad12SPeter Brune ierr = SNESMonitor(snes,snes->iter,snes->norm);CHKERRQ(ierr); 900c90fad12SPeter Brune /* Test for convergence */ 90166585501SPeter Brune if (isFine) { 902b9c2fdf1SPeter Brune ierr = (*snes->ops->converged)(snes,snes->iter,0.0,0.0,snes->norm,&snes->reason,snes->cnvP);CHKERRQ(ierr); 903c90fad12SPeter Brune if (snes->reason) break; 904fe6f9142SPeter Brune } 90566585501SPeter Brune } 906fe6f9142SPeter Brune if (i == maxits) { 907fe6f9142SPeter Brune ierr = PetscInfo1(snes, "Maximum number of iterations has been reached: %D\n", maxits);CHKERRQ(ierr); 908fe6f9142SPeter Brune if (!snes->reason) snes->reason = SNES_DIVERGED_MAX_IT; 909fe6f9142SPeter Brune } 910421d9b32SPeter Brune PetscFunctionReturn(0); 911421d9b32SPeter Brune } 91240244768SBarry Smith 91340244768SBarry Smith /*MC 91440244768SBarry Smith 91540244768SBarry Smith SNESFAS - Full Approximation Scheme nonlinear multigrid solver. 91640244768SBarry Smith 91740244768SBarry Smith The nonlinear problem is solved by correction using coarse versions 91840244768SBarry Smith of the nonlinear problem. This problem is perturbed so that a projected 91940244768SBarry Smith solution of the fine problem elicits no correction from the coarse problem. 92040244768SBarry Smith 92140244768SBarry Smith Options Database: 92240244768SBarry Smith + -snes_fas_levels - The number of levels 92340244768SBarry Smith . -snes_fas_cycles<1> - The number of cycles -- 1 for V, 2 for W 92440244768SBarry Smith . -snes_fas_type<additive,multiplicative,full,kaskade> - Additive or multiplicative cycle 92540244768SBarry Smith . -snes_fas_galerkin<PETSC_FALSE> - Form coarse problems by projection back upon the fine problem 92640244768SBarry Smith . -snes_fas_smoothup<1> - The number of iterations of the post-smoother 92740244768SBarry Smith . -snes_fas_smoothdown<1> - The number of iterations of the pre-smoother 92840244768SBarry Smith . -snes_fas_monitor - Monitor progress of all of the levels 92940244768SBarry Smith . -snes_fas_full_downsweep<PETSC_FALSE> - call the downsmooth on the initial downsweep of full FAS 93040244768SBarry Smith . -fas_levels_snes_ - SNES options for all smoothers 93140244768SBarry Smith . -fas_levels_cycle_snes_ - SNES options for all cycles 93240244768SBarry Smith . -fas_levels_i_snes_ - SNES options for the smoothers on level i 93340244768SBarry Smith . -fas_levels_i_cycle_snes_ - SNES options for the cycle on level i 93440244768SBarry Smith - -fas_coarse_snes_ - SNES options for the coarsest smoother 93540244768SBarry Smith 93640244768SBarry Smith Notes: 93740244768SBarry Smith The organization of the FAS solver is slightly different from the organization of PCMG 93840244768SBarry Smith As each level has smoother SNES instances(down and potentially up) and a cycle SNES instance. 93940244768SBarry Smith The cycle SNES instance may be used for monitoring convergence on a particular level. 94040244768SBarry Smith 94140244768SBarry Smith Level: beginner 94240244768SBarry Smith 94340244768SBarry Smith References: 94440244768SBarry Smith . 1. - Peter R. Brune, Matthew G. Knepley, Barry F. Smith, and Xuemin Tu, "Composing Scalable Nonlinear Algebraic Solvers", 94540244768SBarry Smith SIAM Review, 57(4), 2015 94640244768SBarry Smith 94740244768SBarry Smith .seealso: PCMG, SNESCreate(), SNES, SNESSetType(), SNESType (for list of available types) 94840244768SBarry Smith M*/ 94940244768SBarry Smith 95040244768SBarry Smith PETSC_EXTERN PetscErrorCode SNESCreate_FAS(SNES snes) 95140244768SBarry Smith { 95240244768SBarry Smith SNES_FAS *fas; 95340244768SBarry Smith PetscErrorCode ierr; 95440244768SBarry Smith 95540244768SBarry Smith PetscFunctionBegin; 95640244768SBarry Smith snes->ops->destroy = SNESDestroy_FAS; 95740244768SBarry Smith snes->ops->setup = SNESSetUp_FAS; 95840244768SBarry Smith snes->ops->setfromoptions = SNESSetFromOptions_FAS; 95940244768SBarry Smith snes->ops->view = SNESView_FAS; 96040244768SBarry Smith snes->ops->solve = SNESSolve_FAS; 96140244768SBarry Smith snes->ops->reset = SNESReset_FAS; 96240244768SBarry Smith 96340244768SBarry Smith snes->usesksp = PETSC_FALSE; 964efd4aadfSBarry Smith snes->usesnpc = PETSC_FALSE; 96540244768SBarry Smith 96640244768SBarry Smith if (!snes->tolerancesset) { 96740244768SBarry Smith snes->max_funcs = 30000; 96840244768SBarry Smith snes->max_its = 10000; 96940244768SBarry Smith } 97040244768SBarry Smith 9714fc747eaSLawrence Mitchell snes->alwayscomputesfinalresidual = PETSC_TRUE; 9724fc747eaSLawrence Mitchell 97340244768SBarry Smith ierr = PetscNewLog(snes,&fas);CHKERRQ(ierr); 97440244768SBarry Smith 97540244768SBarry Smith snes->data = (void*) fas; 97640244768SBarry Smith fas->level = 0; 97740244768SBarry Smith fas->levels = 1; 97840244768SBarry Smith fas->n_cycles = 1; 97940244768SBarry Smith fas->max_up_it = 1; 98040244768SBarry Smith fas->max_down_it = 1; 98140244768SBarry Smith fas->smoothu = NULL; 98240244768SBarry Smith fas->smoothd = NULL; 98340244768SBarry Smith fas->next = NULL; 98440244768SBarry Smith fas->previous = NULL; 98540244768SBarry Smith fas->fine = snes; 98640244768SBarry Smith fas->interpolate = NULL; 98740244768SBarry Smith fas->restrct = NULL; 98840244768SBarry Smith fas->inject = NULL; 98940244768SBarry Smith fas->usedmfornumberoflevels = PETSC_FALSE; 99040244768SBarry Smith fas->fastype = SNES_FAS_MULTIPLICATIVE; 99140244768SBarry Smith fas->full_downsweep = PETSC_FALSE; 99240244768SBarry Smith 99340244768SBarry Smith fas->eventsmoothsetup = 0; 99440244768SBarry Smith fas->eventsmoothsolve = 0; 99540244768SBarry Smith fas->eventresidual = 0; 99640244768SBarry Smith fas->eventinterprestrict = 0; 99740244768SBarry Smith PetscFunctionReturn(0); 99840244768SBarry Smith } 999