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 640244768SBarry Smith static PetscErrorCode SNESReset_FAS(SNES snes) 7421d9b32SPeter Brune { 877df8cc4SPeter Brune PetscErrorCode ierr = 0; 9421d9b32SPeter Brune SNES_FAS * fas = (SNES_FAS*)snes->data; 10421d9b32SPeter Brune 11421d9b32SPeter Brune PetscFunctionBegin; 12ab8d36c9SPeter Brune ierr = SNESDestroy(&fas->smoothu);CHKERRQ(ierr); 13ab8d36c9SPeter Brune ierr = SNESDestroy(&fas->smoothd);CHKERRQ(ierr); 143dccd265SPeter Brune ierr = MatDestroy(&fas->inject);CHKERRQ(ierr); 15bccf9bb3SJed Brown ierr = MatDestroy(&fas->interpolate);CHKERRQ(ierr); 16bccf9bb3SJed Brown ierr = MatDestroy(&fas->restrct);CHKERRQ(ierr); 17bccf9bb3SJed Brown ierr = VecDestroy(&fas->rscale);CHKERRQ(ierr); 187cd33a7bSPeter Brune if (fas->galerkin) { 197cd33a7bSPeter Brune ierr = VecDestroy(&fas->Xg);CHKERRQ(ierr); 207cd33a7bSPeter Brune ierr = VecDestroy(&fas->Fg);CHKERRQ(ierr); 217cd33a7bSPeter Brune } 22d477d801SPeter Brune if (fas->next) {ierr = SNESReset(fas->next);CHKERRQ(ierr);} 23421d9b32SPeter Brune PetscFunctionReturn(0); 24421d9b32SPeter Brune } 25421d9b32SPeter Brune 2640244768SBarry Smith static PetscErrorCode SNESDestroy_FAS(SNES snes) 27421d9b32SPeter Brune { 28421d9b32SPeter Brune SNES_FAS * fas = (SNES_FAS*)snes->data; 29742fe5e2SPeter Brune PetscErrorCode ierr = 0; 30421d9b32SPeter Brune 31421d9b32SPeter Brune PetscFunctionBegin; 32421d9b32SPeter Brune /* recursively resets and then destroys */ 3379d9a41aSPeter Brune ierr = SNESReset(snes);CHKERRQ(ierr); 341aa26658SKarl Rupp if (fas->next) { 351aa26658SKarl Rupp ierr = SNESDestroy(&fas->next);CHKERRQ(ierr); 361aa26658SKarl Rupp } 37421d9b32SPeter Brune ierr = PetscFree(fas);CHKERRQ(ierr); 38421d9b32SPeter Brune PetscFunctionReturn(0); 39421d9b32SPeter Brune } 40421d9b32SPeter Brune 4140244768SBarry Smith static PetscErrorCode SNESSetUp_FAS(SNES snes) 42421d9b32SPeter Brune { 4348bfdf8aSPeter Brune SNES_FAS *fas = (SNES_FAS*) snes->data; 44421d9b32SPeter Brune PetscErrorCode ierr; 45d1adcc6fSPeter Brune PetscInt dm_levels; 463dccd265SPeter Brune Vec vec_sol, vec_func, vec_sol_update, vec_rhs; /* preserve these if they're set through the reset */ 47ab8d36c9SPeter Brune SNES next; 480a7266b2SPatrick Farrell PetscBool isFine, hasCreateRestriction; 49f89ba88eSPeter Brune SNESLineSearch linesearch; 50f89ba88eSPeter Brune SNESLineSearch slinesearch; 51f89ba88eSPeter Brune void *lsprectx,*lspostctx; 526b2b7091SBarry Smith PetscErrorCode (*precheck)(SNESLineSearch,Vec,Vec,PetscBool*,void*); 536b2b7091SBarry Smith PetscErrorCode (*postcheck)(SNESLineSearch,Vec,Vec,Vec,PetscBool*,PetscBool*,void*); 54eff52c0eSPeter Brune 556b2b7091SBarry Smith PetscFunctionBegin; 56ab8d36c9SPeter Brune ierr = SNESFASCycleIsFine(snes, &isFine);CHKERRQ(ierr); 57ab8d36c9SPeter Brune if (fas->usedmfornumberoflevels && isFine) { 58d1adcc6fSPeter Brune ierr = DMGetRefineLevel(snes->dm,&dm_levels);CHKERRQ(ierr); 59d1adcc6fSPeter Brune dm_levels++; 60cc05f883SPeter Brune if (dm_levels > fas->levels) { 612e8ce248SJed Brown /* we don't want the solution and func vectors to be destroyed in the SNESReset when it's called in SNESFASSetLevels_FAS*/ 623dccd265SPeter Brune vec_sol = snes->vec_sol; 633dccd265SPeter Brune vec_func = snes->vec_func; 643dccd265SPeter Brune vec_sol_update = snes->vec_sol_update; 653dccd265SPeter Brune vec_rhs = snes->vec_rhs; 660298fd71SBarry Smith snes->vec_sol = NULL; 670298fd71SBarry Smith snes->vec_func = NULL; 680298fd71SBarry Smith snes->vec_sol_update = NULL; 690298fd71SBarry Smith snes->vec_rhs = NULL; 703dccd265SPeter Brune 713dccd265SPeter Brune /* reset the number of levels */ 720298fd71SBarry Smith ierr = SNESFASSetLevels(snes,dm_levels,NULL);CHKERRQ(ierr); 73cc05f883SPeter Brune ierr = SNESSetFromOptions(snes);CHKERRQ(ierr); 743dccd265SPeter Brune 753dccd265SPeter Brune snes->vec_sol = vec_sol; 763dccd265SPeter Brune snes->vec_func = vec_func; 773dccd265SPeter Brune snes->vec_rhs = vec_rhs; 783dccd265SPeter Brune snes->vec_sol_update = vec_sol_update; 79d1adcc6fSPeter Brune } 80d1adcc6fSPeter Brune } 81ab8d36c9SPeter Brune ierr = SNESFASCycleGetCorrection(snes, &next);CHKERRQ(ierr); 82ab8d36c9SPeter Brune if (!isFine) snes->gridsequence = 0; /* no grid sequencing inside the multigrid hierarchy! */ 833dccd265SPeter Brune 84fa0ddf94SBarry Smith ierr = SNESSetWorkVecs(snes, 2);CHKERRQ(ierr); /* work vectors used for intergrid transfers */ 85cc05f883SPeter Brune 86ab8d36c9SPeter Brune /* set up the smoothers if they haven't already been set up */ 87ab8d36c9SPeter Brune if (!fas->smoothd) { 88ab8d36c9SPeter Brune ierr = SNESFASCycleCreateSmoother_Private(snes, &fas->smoothd);CHKERRQ(ierr); 89ab8d36c9SPeter Brune } 90ab8d36c9SPeter Brune 9179d9a41aSPeter Brune if (snes->dm) { 92ab8d36c9SPeter Brune /* set the smoother DMs properly */ 93ab8d36c9SPeter Brune if (fas->smoothu) ierr = SNESSetDM(fas->smoothu, snes->dm);CHKERRQ(ierr); 94ab8d36c9SPeter Brune ierr = SNESSetDM(fas->smoothd, snes->dm);CHKERRQ(ierr); 9579d9a41aSPeter Brune /* construct EVERYTHING from the DM -- including the progressive set of smoothers */ 96ab8d36c9SPeter Brune if (next) { 9779d9a41aSPeter Brune /* for now -- assume the DM and the evaluation functions have been set externally */ 98ab8d36c9SPeter Brune if (!next->dm) { 99ce94432eSBarry Smith ierr = DMCoarsen(snes->dm, PetscObjectComm((PetscObject)next), &next->dm);CHKERRQ(ierr); 100ab8d36c9SPeter Brune ierr = SNESSetDM(next, next->dm);CHKERRQ(ierr); 10179d9a41aSPeter Brune } 10279d9a41aSPeter Brune /* set the interpolation and restriction from the DM */ 10379d9a41aSPeter Brune if (!fas->interpolate) { 104ab8d36c9SPeter Brune ierr = DMCreateInterpolation(next->dm, snes->dm, &fas->interpolate, &fas->rscale);CHKERRQ(ierr); 105bccf9bb3SJed Brown if (!fas->restrct) { 1060a7266b2SPatrick Farrell ierr = DMHasCreateRestriction(next->dm, &hasCreateRestriction);CHKERRQ(ierr); 1070a7266b2SPatrick Farrell /* DM can create restrictions, use that */ 1080a7266b2SPatrick Farrell if (hasCreateRestriction) { 1090a7266b2SPatrick Farrell ierr = DMCreateRestriction(next->dm, snes->dm, &fas->restrct);CHKERRQ(ierr); 1100a7266b2SPatrick Farrell } else { 111bccf9bb3SJed Brown ierr = PetscObjectReference((PetscObject)fas->interpolate);CHKERRQ(ierr); 11279d9a41aSPeter Brune fas->restrct = fas->interpolate; 11379d9a41aSPeter Brune } 114bccf9bb3SJed Brown } 1150a7266b2SPatrick Farrell } 11679d9a41aSPeter Brune /* set the injection from the DM */ 11779d9a41aSPeter Brune if (!fas->inject) { 11823e68893SLawrence Mitchell PetscBool flg; 11923e68893SLawrence Mitchell ierr = DMHasCreateInjection(next->dm, &flg);CHKERRQ(ierr); 12023e68893SLawrence Mitchell if (flg) { 1216dbf9973SLawrence Mitchell ierr = DMCreateInjection(next->dm, snes->dm, &fas->inject);CHKERRQ(ierr); 12279d9a41aSPeter Brune } 12379d9a41aSPeter Brune } 12479d9a41aSPeter Brune } 12523e68893SLawrence Mitchell } 12679d9a41aSPeter Brune /*pass the smoother, function, and jacobian up to the next level if it's not user set already */ 12779d9a41aSPeter Brune if (fas->galerkin) { 1281aa26658SKarl Rupp if (next) { 129*25acbd8eSLisandro Dalcin ierr = SNESSetFunction(next, NULL, SNESFASGalerkinFunctionDefault, next);CHKERRQ(ierr); 1301aa26658SKarl Rupp } 1311aa26658SKarl Rupp if (fas->smoothd && fas->level != fas->levels - 1) { 132*25acbd8eSLisandro Dalcin ierr = SNESSetFunction(fas->smoothd, NULL, SNESFASGalerkinFunctionDefault, snes);CHKERRQ(ierr); 1331aa26658SKarl Rupp } 1341aa26658SKarl Rupp if (fas->smoothu && fas->level != fas->levels - 1) { 135*25acbd8eSLisandro Dalcin ierr = SNESSetFunction(fas->smoothu, NULL, SNESFASGalerkinFunctionDefault, snes);CHKERRQ(ierr); 1361aa26658SKarl Rupp } 13779d9a41aSPeter Brune } 13879d9a41aSPeter Brune 139534ebe21SPeter Brune /* sets the down (pre) smoother's default norm and sets it from options */ 140534ebe21SPeter Brune if (fas->smoothd) { 141bc3f2f05SPeter Brune if (fas->level == 0 && fas->levels != 1) { 142365a6726SPeter Brune ierr = SNESSetNormSchedule(fas->smoothd, SNES_NORM_NONE);CHKERRQ(ierr); 143534ebe21SPeter Brune } else { 144365a6726SPeter Brune ierr = SNESSetNormSchedule(fas->smoothd, SNES_NORM_FINAL_ONLY);CHKERRQ(ierr); 145534ebe21SPeter Brune } 1467fce8c19SPeter Brune ierr = PetscObjectCopyFortranFunctionPointers((PetscObject)snes, (PetscObject)fas->smoothd);CHKERRQ(ierr); 147534ebe21SPeter Brune ierr = SNESSetFromOptions(fas->smoothd);CHKERRQ(ierr); 1487601faf0SJed Brown ierr = SNESGetLineSearch(snes,&linesearch);CHKERRQ(ierr); 1497601faf0SJed Brown ierr = SNESGetLineSearch(fas->smoothd,&slinesearch);CHKERRQ(ierr); 1506b2b7091SBarry Smith ierr = SNESLineSearchGetPreCheck(linesearch,&precheck,&lsprectx);CHKERRQ(ierr); 1516b2b7091SBarry Smith ierr = SNESLineSearchGetPostCheck(linesearch,&postcheck,&lspostctx);CHKERRQ(ierr); 1526b2b7091SBarry Smith ierr = SNESLineSearchSetPreCheck(slinesearch,precheck,lsprectx);CHKERRQ(ierr); 1536b2b7091SBarry Smith ierr = SNESLineSearchSetPostCheck(slinesearch,postcheck,lspostctx);CHKERRQ(ierr); 154f89ba88eSPeter Brune ierr = PetscObjectCopyFortranFunctionPointers((PetscObject)linesearch, (PetscObject)slinesearch);CHKERRQ(ierr); 1550dd27c6cSPeter Brune 1560dd27c6cSPeter Brune fas->smoothd->vec_sol = snes->vec_sol; 1570dd27c6cSPeter Brune ierr = PetscObjectReference((PetscObject)snes->vec_sol);CHKERRQ(ierr); 1580dd27c6cSPeter Brune fas->smoothd->vec_sol_update = snes->vec_sol_update; 1590dd27c6cSPeter Brune ierr = PetscObjectReference((PetscObject)snes->vec_sol_update);CHKERRQ(ierr); 1600dd27c6cSPeter Brune fas->smoothd->vec_func = snes->vec_func; 1610dd27c6cSPeter Brune ierr = PetscObjectReference((PetscObject)snes->vec_func);CHKERRQ(ierr); 1620dd27c6cSPeter Brune 163217044c2SLisandro Dalcin if (fas->eventsmoothsetup) {ierr = PetscLogEventBegin(fas->eventsmoothsetup,fas->smoothd,0,0,0);CHKERRQ(ierr);} 1640dd27c6cSPeter Brune ierr = SNESSetUp(fas->smoothd);CHKERRQ(ierr); 165217044c2SLisandro Dalcin if (fas->eventsmoothsetup) {ierr = PetscLogEventEnd(fas->eventsmoothsetup,fas->smoothd,0,0,0);CHKERRQ(ierr);} 166534ebe21SPeter Brune } 167534ebe21SPeter Brune 168534ebe21SPeter Brune /* sets the up (post) smoother's default norm and sets it from options */ 169534ebe21SPeter Brune if (fas->smoothu) { 170534ebe21SPeter Brune if (fas->level != fas->levels - 1) { 171365a6726SPeter Brune ierr = SNESSetNormSchedule(fas->smoothu, SNES_NORM_NONE);CHKERRQ(ierr); 172534ebe21SPeter Brune } else { 173365a6726SPeter Brune ierr = SNESSetNormSchedule(fas->smoothu, SNES_NORM_FINAL_ONLY);CHKERRQ(ierr); 174534ebe21SPeter Brune } 1757fce8c19SPeter Brune ierr = PetscObjectCopyFortranFunctionPointers((PetscObject)snes, (PetscObject)fas->smoothu);CHKERRQ(ierr); 176534ebe21SPeter Brune ierr = SNESSetFromOptions(fas->smoothu);CHKERRQ(ierr); 1777601faf0SJed Brown ierr = SNESGetLineSearch(snes,&linesearch);CHKERRQ(ierr); 1787601faf0SJed Brown ierr = SNESGetLineSearch(fas->smoothu,&slinesearch);CHKERRQ(ierr); 1796b2b7091SBarry Smith ierr = SNESLineSearchGetPreCheck(linesearch,&precheck,&lsprectx);CHKERRQ(ierr); 1806b2b7091SBarry Smith ierr = SNESLineSearchGetPostCheck(linesearch,&postcheck,&lspostctx);CHKERRQ(ierr); 1816b2b7091SBarry Smith ierr = SNESLineSearchSetPreCheck(slinesearch,precheck,lsprectx);CHKERRQ(ierr); 1826b2b7091SBarry Smith ierr = SNESLineSearchSetPostCheck(slinesearch,postcheck,lspostctx);CHKERRQ(ierr); 183f89ba88eSPeter Brune ierr = PetscObjectCopyFortranFunctionPointers((PetscObject)linesearch, (PetscObject)slinesearch);CHKERRQ(ierr); 1840dd27c6cSPeter Brune 1850dd27c6cSPeter Brune fas->smoothu->vec_sol = snes->vec_sol; 1860dd27c6cSPeter Brune ierr = PetscObjectReference((PetscObject)snes->vec_sol);CHKERRQ(ierr); 1870dd27c6cSPeter Brune fas->smoothu->vec_sol_update = snes->vec_sol_update; 1880dd27c6cSPeter Brune ierr = PetscObjectReference((PetscObject)snes->vec_sol_update);CHKERRQ(ierr); 1890dd27c6cSPeter Brune fas->smoothu->vec_func = snes->vec_func; 1900dd27c6cSPeter Brune ierr = PetscObjectReference((PetscObject)snes->vec_func);CHKERRQ(ierr); 1910dd27c6cSPeter Brune 192217044c2SLisandro Dalcin if (fas->eventsmoothsetup) {ierr = PetscLogEventBegin(fas->eventsmoothsetup,fas->smoothu,0,0,0);CHKERRQ(ierr);} 1930dd27c6cSPeter Brune ierr = SNESSetUp(fas->smoothu);CHKERRQ(ierr); 194217044c2SLisandro Dalcin if (fas->eventsmoothsetup) {ierr = PetscLogEventEnd(fas->eventsmoothsetup,fas->smoothu,0,0,0);CHKERRQ(ierr);} 1950dd27c6cSPeter Brune 196534ebe21SPeter Brune } 197d06165b7SPeter Brune 198ab8d36c9SPeter Brune if (next) { 19979d9a41aSPeter Brune /* gotta set up the solution vector for this to work */ 200ab8d36c9SPeter Brune if (!next->vec_sol) {ierr = SNESFASCreateCoarseVec(snes,&next->vec_sol);CHKERRQ(ierr);} 201ab8d36c9SPeter Brune if (!next->vec_rhs) {ierr = SNESFASCreateCoarseVec(snes,&next->vec_rhs);CHKERRQ(ierr);} 2027fce8c19SPeter Brune ierr = PetscObjectCopyFortranFunctionPointers((PetscObject)snes, (PetscObject)next);CHKERRQ(ierr); 2037601faf0SJed Brown ierr = SNESGetLineSearch(snes,&linesearch);CHKERRQ(ierr); 2047601faf0SJed Brown ierr = SNESGetLineSearch(fas->next,&slinesearch);CHKERRQ(ierr); 2056b2b7091SBarry Smith ierr = SNESLineSearchGetPreCheck(linesearch,&precheck,&lsprectx);CHKERRQ(ierr); 2066b2b7091SBarry Smith ierr = SNESLineSearchGetPostCheck(linesearch,&postcheck,&lspostctx);CHKERRQ(ierr); 2076b2b7091SBarry Smith ierr = SNESLineSearchSetPreCheck(slinesearch,precheck,lsprectx);CHKERRQ(ierr); 2086b2b7091SBarry Smith ierr = SNESLineSearchSetPostCheck(slinesearch,postcheck,lspostctx);CHKERRQ(ierr); 209f89ba88eSPeter Brune ierr = PetscObjectCopyFortranFunctionPointers((PetscObject)linesearch, (PetscObject)slinesearch);CHKERRQ(ierr); 210ab8d36c9SPeter Brune ierr = SNESSetUp(next);CHKERRQ(ierr); 21179d9a41aSPeter Brune } 2126273346dSPeter Brune /* setup FAS work vectors */ 2136273346dSPeter Brune if (fas->galerkin) { 2146273346dSPeter Brune ierr = VecDuplicate(snes->vec_sol, &fas->Xg);CHKERRQ(ierr); 2156273346dSPeter Brune ierr = VecDuplicate(snes->vec_sol, &fas->Fg);CHKERRQ(ierr); 2166273346dSPeter Brune } 217421d9b32SPeter Brune PetscFunctionReturn(0); 218421d9b32SPeter Brune } 219421d9b32SPeter Brune 22040244768SBarry Smith static PetscErrorCode SNESSetFromOptions_FAS(PetscOptionItems *PetscOptionsObject,SNES snes) 221421d9b32SPeter Brune { 222ee78dd50SPeter Brune SNES_FAS *fas = (SNES_FAS*) snes->data; 223ee78dd50SPeter Brune PetscInt levels = 1; 22487f44e3fSPeter Brune PetscBool flg = PETSC_FALSE, upflg = PETSC_FALSE, downflg = PETSC_FALSE, monflg = PETSC_FALSE, galerkinflg = PETSC_FALSE,continuationflg = PETSC_FALSE; 225421d9b32SPeter Brune PetscErrorCode ierr; 22607144faaSPeter Brune SNESFASType fastype; 227fde0ff24SPeter Brune const char *optionsprefix; 228f1c6b773SPeter Brune SNESLineSearch linesearch; 22966585501SPeter Brune PetscInt m, n_up, n_down; 230ab8d36c9SPeter Brune SNES next; 231ab8d36c9SPeter Brune PetscBool isFine; 232421d9b32SPeter Brune 233421d9b32SPeter Brune PetscFunctionBegin; 234ab8d36c9SPeter Brune ierr = SNESFASCycleIsFine(snes, &isFine);CHKERRQ(ierr); 235e55864a3SBarry Smith ierr = PetscOptionsHead(PetscOptionsObject,"SNESFAS Options-----------------------------------");CHKERRQ(ierr); 236ee78dd50SPeter Brune 237ab8d36c9SPeter Brune /* number of levels -- only process most options on the finest level */ 238ab8d36c9SPeter Brune if (isFine) { 239ee78dd50SPeter Brune ierr = PetscOptionsInt("-snes_fas_levels", "Number of Levels", "SNESFASSetLevels", levels, &levels, &flg);CHKERRQ(ierr); 240c732cbdbSBarry Smith if (!flg && snes->dm) { 241c732cbdbSBarry Smith ierr = DMGetRefineLevel(snes->dm,&levels);CHKERRQ(ierr); 242c732cbdbSBarry Smith levels++; 243d1adcc6fSPeter Brune fas->usedmfornumberoflevels = PETSC_TRUE; 244c732cbdbSBarry Smith } 2450298fd71SBarry Smith ierr = SNESFASSetLevels(snes, levels, NULL);CHKERRQ(ierr); 24607144faaSPeter Brune fastype = fas->fastype; 24707144faaSPeter Brune ierr = PetscOptionsEnum("-snes_fas_type","FAS correction type","SNESFASSetType",SNESFASTypes,(PetscEnum)fastype,(PetscEnum*)&fastype,&flg);CHKERRQ(ierr); 24807144faaSPeter Brune if (flg) { 24907144faaSPeter Brune ierr = SNESFASSetType(snes, fastype);CHKERRQ(ierr); 25007144faaSPeter Brune } 251ee78dd50SPeter Brune 252fde0ff24SPeter Brune ierr = SNESGetOptionsPrefix(snes, &optionsprefix);CHKERRQ(ierr); 253ab8d36c9SPeter Brune ierr = PetscOptionsInt("-snes_fas_cycles","Number of cycles","SNESFASSetCycles",fas->n_cycles,&m,&flg);CHKERRQ(ierr); 254ab8d36c9SPeter Brune if (flg) { 255ab8d36c9SPeter Brune ierr = SNESFASSetCycles(snes, m);CHKERRQ(ierr); 256fde0ff24SPeter Brune } 25787f44e3fSPeter Brune ierr = PetscOptionsBool("-snes_fas_continuation","Corrected grid-sequence continuation","SNESFASSetContinuation",fas->continuation,&continuationflg,&flg);CHKERRQ(ierr); 25887f44e3fSPeter Brune if (flg) { 25987f44e3fSPeter Brune ierr = SNESFASSetContinuation(snes,continuationflg);CHKERRQ(ierr); 26087f44e3fSPeter Brune } 261fde0ff24SPeter Brune 262ab8d36c9SPeter Brune ierr = PetscOptionsBool("-snes_fas_galerkin", "Form coarse problems with Galerkin","SNESFASSetGalerkin",fas->galerkin,&galerkinflg,&flg);CHKERRQ(ierr); 263ab8d36c9SPeter Brune if (flg) { 264ab8d36c9SPeter Brune ierr = SNESFASSetGalerkin(snes, galerkinflg);CHKERRQ(ierr); 265ab8d36c9SPeter Brune } 266ee78dd50SPeter Brune 267928e959bSPeter Brune if (fas->fastype == SNES_FAS_FULL) { 268928e959bSPeter 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); 269928e959bSPeter Brune if (flg) {SNESFASFullSetDownSweep(snes,fas->full_downsweep);CHKERRQ(ierr);} 270928e959bSPeter Brune } 271928e959bSPeter Brune 27266585501SPeter Brune ierr = PetscOptionsInt("-snes_fas_smoothup","Number of post-smoothing steps","SNESFASSetNumberSmoothUp",fas->max_up_it,&n_up,&upflg);CHKERRQ(ierr); 273162d76ddSPeter Brune 27466585501SPeter Brune ierr = PetscOptionsInt("-snes_fas_smoothdown","Number of pre-smoothing steps","SNESFASSetNumberSmoothDown",fas->max_down_it,&n_down,&downflg);CHKERRQ(ierr); 275162d76ddSPeter Brune 276d142ab34SLawrence Mitchell { 277d142ab34SLawrence Mitchell PetscViewer viewer; 278d142ab34SLawrence Mitchell PetscViewerFormat format; 279d142ab34SLawrence Mitchell ierr = PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes),((PetscObject)snes)->prefix, 280d142ab34SLawrence Mitchell "-snes_fas_monitor",&viewer,&format,&monflg);CHKERRQ(ierr); 281d142ab34SLawrence Mitchell if (monflg) { 282d142ab34SLawrence Mitchell PetscViewerAndFormat *vf; 283d142ab34SLawrence Mitchell ierr = PetscViewerAndFormatCreate(viewer,format,&vf);CHKERRQ(ierr); 284d142ab34SLawrence Mitchell ierr = PetscObjectDereference((PetscObject)viewer);CHKERRQ(ierr); 285d142ab34SLawrence Mitchell ierr = SNESFASSetMonitor(snes,vf,PETSC_TRUE);CHKERRQ(ierr); 286d142ab34SLawrence Mitchell } 287d142ab34SLawrence Mitchell } 2880dd27c6cSPeter Brune flg = PETSC_FALSE; 2890dd27c6cSPeter Brune monflg = PETSC_TRUE; 2900dd27c6cSPeter Brune ierr = PetscOptionsBool("-snes_fas_log","Log times for each FAS level","SNESFASSetLog",monflg,&monflg,&flg);CHKERRQ(ierr); 2910dd27c6cSPeter Brune if (flg) {ierr = SNESFASSetLog(snes,monflg);CHKERRQ(ierr);} 292ab8d36c9SPeter Brune } 293ee78dd50SPeter Brune 294421d9b32SPeter Brune ierr = PetscOptionsTail();CHKERRQ(ierr); 2958cc86e31SPeter Brune /* setup from the determined types if there is no pointwise procedure or smoother defined */ 296162d76ddSPeter Brune if (upflg) { 29766585501SPeter Brune ierr = SNESFASSetNumberSmoothUp(snes,n_up);CHKERRQ(ierr); 298162d76ddSPeter Brune } 299162d76ddSPeter Brune if (downflg) { 30066585501SPeter Brune ierr = SNESFASSetNumberSmoothDown(snes,n_down);CHKERRQ(ierr); 301162d76ddSPeter Brune } 302eff52c0eSPeter Brune 3039e764e56SPeter Brune /* set up the default line search for coarse grid corrections */ 3049e764e56SPeter Brune if (fas->fastype == SNES_FAS_ADDITIVE) { 3059e764e56SPeter Brune if (!snes->linesearch) { 3067601faf0SJed Brown ierr = SNESGetLineSearch(snes, &linesearch);CHKERRQ(ierr); 3071a4f838cSPeter Brune ierr = SNESLineSearchSetType(linesearch, SNESLINESEARCHL2);CHKERRQ(ierr); 3089e764e56SPeter Brune } 3099e764e56SPeter Brune } 3109e764e56SPeter Brune 311ab8d36c9SPeter Brune ierr = SNESFASCycleGetCorrection(snes, &next);CHKERRQ(ierr); 312ee78dd50SPeter Brune /* recursive option setting for the smoothers */ 313ab8d36c9SPeter Brune if (next) {ierr = SNESSetFromOptions(next);CHKERRQ(ierr);} 314421d9b32SPeter Brune PetscFunctionReturn(0); 315421d9b32SPeter Brune } 316421d9b32SPeter Brune 3179804daf3SBarry Smith #include <petscdraw.h> 31840244768SBarry Smith static PetscErrorCode SNESView_FAS(SNES snes, PetscViewer viewer) 319421d9b32SPeter Brune { 320421d9b32SPeter Brune SNES_FAS *fas = (SNES_FAS*) snes->data; 321656ede7eSPeter Brune PetscBool isFine,iascii,isdraw; 322ab8d36c9SPeter Brune PetscInt i; 323421d9b32SPeter Brune PetscErrorCode ierr; 324ab8d36c9SPeter Brune SNES smoothu, smoothd, levelsnes; 325421d9b32SPeter Brune 326421d9b32SPeter Brune PetscFunctionBegin; 327ab8d36c9SPeter Brune ierr = SNESFASCycleIsFine(snes, &isFine);CHKERRQ(ierr); 328ab8d36c9SPeter Brune if (isFine) { 329251f4c67SDmitry Karpeev ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr); 330656ede7eSPeter Brune ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERDRAW,&isdraw);CHKERRQ(ierr); 331421d9b32SPeter Brune if (iascii) { 332efd4aadfSBarry Smith ierr = PetscViewerASCIIPrintf(viewer, " type is %s, levels=%D, cycles=%D\n", SNESFASTypes[fas->fastype], fas->levels, fas->n_cycles);CHKERRQ(ierr); 333ab8d36c9SPeter Brune if (fas->galerkin) { 334ab8d36c9SPeter Brune ierr = PetscViewerASCIIPrintf(viewer," Using Galerkin computed coarse grid function evaluation\n");CHKERRQ(ierr); 335421d9b32SPeter Brune } else { 336ab8d36c9SPeter Brune ierr = PetscViewerASCIIPrintf(viewer," Not using Galerkin computed coarse grid function evaluation\n");CHKERRQ(ierr); 337421d9b32SPeter Brune } 338ab8d36c9SPeter Brune for (i=0; i<fas->levels; i++) { 339ab8d36c9SPeter Brune ierr = SNESFASGetCycleSNES(snes, i, &levelsnes);CHKERRQ(ierr); 340ab8d36c9SPeter Brune ierr = SNESFASCycleGetSmootherUp(levelsnes, &smoothu);CHKERRQ(ierr); 341ab8d36c9SPeter Brune ierr = SNESFASCycleGetSmootherDown(levelsnes, &smoothd);CHKERRQ(ierr); 342ab8d36c9SPeter Brune if (!i) { 343ab8d36c9SPeter Brune ierr = PetscViewerASCIIPrintf(viewer," Coarse grid solver -- level %D -------------------------------\n",i);CHKERRQ(ierr); 344421d9b32SPeter Brune } else { 345ab8d36c9SPeter Brune ierr = PetscViewerASCIIPrintf(viewer," Down solver (pre-smoother) on level %D -------------------------------\n",i);CHKERRQ(ierr); 346421d9b32SPeter Brune } 347ab8d36c9SPeter Brune ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); 348166b3ea4SJed Brown if (smoothd) { 349ab8d36c9SPeter Brune ierr = SNESView(smoothd,viewer);CHKERRQ(ierr); 350166b3ea4SJed Brown } else { 351166b3ea4SJed Brown ierr = PetscViewerASCIIPrintf(viewer,"Not yet available\n");CHKERRQ(ierr); 352166b3ea4SJed Brown } 353ab8d36c9SPeter Brune ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); 354ab8d36c9SPeter Brune if (i && (smoothd == smoothu)) { 355ab8d36c9SPeter Brune ierr = PetscViewerASCIIPrintf(viewer," Up solver (post-smoother) same as down solver (pre-smoother)\n");CHKERRQ(ierr); 356ab8d36c9SPeter Brune } else if (i) { 357ab8d36c9SPeter Brune ierr = PetscViewerASCIIPrintf(viewer," Up solver (post-smoother) on level %D -------------------------------\n",i);CHKERRQ(ierr); 358ab8d36c9SPeter Brune ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); 359166b3ea4SJed Brown if (smoothu) { 360ab8d36c9SPeter Brune ierr = SNESView(smoothu,viewer);CHKERRQ(ierr); 361166b3ea4SJed Brown } else { 362166b3ea4SJed Brown ierr = PetscViewerASCIIPrintf(viewer,"Not yet available\n");CHKERRQ(ierr); 363166b3ea4SJed Brown } 364ab8d36c9SPeter Brune ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); 365ab8d36c9SPeter Brune } 366ab8d36c9SPeter Brune } 367656ede7eSPeter Brune } else if (isdraw) { 368656ede7eSPeter Brune PetscDraw draw; 369b4375e8dSPeter Brune PetscReal x,w,y,bottom,th,wth; 370656ede7eSPeter Brune SNES_FAS *curfas = fas; 371656ede7eSPeter Brune ierr = PetscViewerDrawGetDraw(viewer,0,&draw);CHKERRQ(ierr); 372656ede7eSPeter Brune ierr = PetscDrawGetCurrentPoint(draw,&x,&y);CHKERRQ(ierr); 373656ede7eSPeter Brune ierr = PetscDrawStringGetSize(draw,&wth,&th);CHKERRQ(ierr); 374656ede7eSPeter Brune bottom = y - th; 375656ede7eSPeter Brune while (curfas) { 376b4375e8dSPeter Brune if (!curfas->smoothu) { 377656ede7eSPeter Brune ierr = PetscDrawPushCurrentPoint(draw,x,bottom);CHKERRQ(ierr); 378656ede7eSPeter Brune if (curfas->smoothd) ierr = SNESView(curfas->smoothd,viewer);CHKERRQ(ierr); 379656ede7eSPeter Brune ierr = PetscDrawPopCurrentPoint(draw);CHKERRQ(ierr); 380b4375e8dSPeter Brune } else { 381b4375e8dSPeter Brune w = 0.5*PetscMin(1.0-x,x); 382b4375e8dSPeter Brune ierr = PetscDrawPushCurrentPoint(draw,x-w,bottom);CHKERRQ(ierr); 383b4375e8dSPeter Brune if (curfas->smoothd) ierr = SNESView(curfas->smoothd,viewer);CHKERRQ(ierr); 384b4375e8dSPeter Brune ierr = PetscDrawPopCurrentPoint(draw);CHKERRQ(ierr); 385b4375e8dSPeter Brune ierr = PetscDrawPushCurrentPoint(draw,x+w,bottom);CHKERRQ(ierr); 386b4375e8dSPeter Brune if (curfas->smoothu) ierr = SNESView(curfas->smoothu,viewer);CHKERRQ(ierr); 387b4375e8dSPeter Brune ierr = PetscDrawPopCurrentPoint(draw);CHKERRQ(ierr); 388b4375e8dSPeter Brune } 389656ede7eSPeter Brune /* this is totally bogus but we have no way of knowing how low the previous one was draw to */ 390656ede7eSPeter Brune bottom -= 5*th; 3911aa26658SKarl Rupp if (curfas->next) curfas = (SNES_FAS*)curfas->next->data; 3920298fd71SBarry Smith else curfas = NULL; 393656ede7eSPeter Brune } 394421d9b32SPeter Brune } 395ab8d36c9SPeter Brune } 396421d9b32SPeter Brune PetscFunctionReturn(0); 397421d9b32SPeter Brune } 398421d9b32SPeter Brune 39939bd7f45SPeter Brune /* 40039bd7f45SPeter Brune Defines the action of the downsmoother 40139bd7f45SPeter Brune */ 40240244768SBarry Smith static PetscErrorCode SNESFASDownSmooth_Private(SNES snes, Vec B, Vec X, Vec F, PetscReal *fnorm) 403b9c2fdf1SPeter Brune { 40439bd7f45SPeter Brune PetscErrorCode ierr = 0; 405742fe5e2SPeter Brune SNESConvergedReason reason; 406ab8d36c9SPeter Brune Vec FPC; 407ab8d36c9SPeter Brune SNES smoothd; 4086cbb2f26SLawrence Mitchell PetscBool flg; 4090dd27c6cSPeter Brune SNES_FAS *fas = (SNES_FAS*) snes->data; 4106e111a19SKarl Rupp 411421d9b32SPeter Brune PetscFunctionBegin; 412ab8d36c9SPeter Brune ierr = SNESFASCycleGetSmootherDown(snes, &smoothd);CHKERRQ(ierr); 413e4ed7901SPeter Brune ierr = SNESSetInitialFunction(smoothd, F);CHKERRQ(ierr); 414217044c2SLisandro Dalcin if (fas->eventsmoothsolve) {ierr = PetscLogEventBegin(fas->eventsmoothsolve,smoothd,B,X,0);CHKERRQ(ierr);} 415ab8d36c9SPeter Brune ierr = SNESSolve(smoothd, B, X);CHKERRQ(ierr); 416217044c2SLisandro Dalcin if (fas->eventsmoothsolve) {ierr = PetscLogEventEnd(fas->eventsmoothsolve,smoothd,B,X,0);CHKERRQ(ierr);} 417742fe5e2SPeter Brune /* check convergence reason for the smoother */ 418ab8d36c9SPeter Brune ierr = SNESGetConvergedReason(smoothd,&reason);CHKERRQ(ierr); 4191ff805c3SPeter Brune if (reason < 0 && !(reason == SNES_DIVERGED_MAX_IT || reason == SNES_DIVERGED_LOCAL_MIN || reason == SNES_DIVERGED_LINE_SEARCH)) { 420742fe5e2SPeter Brune snes->reason = SNES_DIVERGED_INNER; 421742fe5e2SPeter Brune PetscFunctionReturn(0); 422742fe5e2SPeter Brune } 4236cbb2f26SLawrence Mitchell 4240298fd71SBarry Smith ierr = SNESGetFunction(smoothd, &FPC, NULL, NULL);CHKERRQ(ierr); 4256cbb2f26SLawrence Mitchell ierr = SNESGetAlwaysComputesFinalResidual(smoothd, &flg);CHKERRQ(ierr); 4266cbb2f26SLawrence Mitchell if (!flg) { 4276cbb2f26SLawrence Mitchell ierr = SNESComputeFunction(smoothd, X, FPC);CHKERRQ(ierr); 4286cbb2f26SLawrence Mitchell } 4294b32a720SPeter Brune ierr = VecCopy(FPC, F);CHKERRQ(ierr); 43071dbe336SPeter Brune if (fnorm) {ierr = VecNorm(F,NORM_2,fnorm);CHKERRQ(ierr);} 43139bd7f45SPeter Brune PetscFunctionReturn(0); 43239bd7f45SPeter Brune } 43339bd7f45SPeter Brune 43439bd7f45SPeter Brune 43539bd7f45SPeter Brune /* 43607144faaSPeter Brune Defines the action of the upsmoother 43739bd7f45SPeter Brune */ 43840244768SBarry Smith static PetscErrorCode SNESFASUpSmooth_Private(SNES snes, Vec B, Vec X, Vec F, PetscReal *fnorm) 4390adebc6cSBarry Smith { 44039bd7f45SPeter Brune PetscErrorCode ierr = 0; 44139bd7f45SPeter Brune SNESConvergedReason reason; 442ab8d36c9SPeter Brune Vec FPC; 443ab8d36c9SPeter Brune SNES smoothu; 4446cbb2f26SLawrence Mitchell PetscBool flg; 4450dd27c6cSPeter Brune SNES_FAS *fas = (SNES_FAS*) snes->data; 446ab8d36c9SPeter Brune 4476e111a19SKarl Rupp PetscFunctionBegin; 448ab8d36c9SPeter Brune ierr = SNESFASCycleGetSmootherUp(snes, &smoothu);CHKERRQ(ierr); 449217044c2SLisandro Dalcin if (fas->eventsmoothsolve) {ierr = PetscLogEventBegin(fas->eventsmoothsolve,smoothu,0,0,0);CHKERRQ(ierr);} 450ab8d36c9SPeter Brune ierr = SNESSolve(smoothu, B, X);CHKERRQ(ierr); 451217044c2SLisandro Dalcin if (fas->eventsmoothsolve) {ierr = PetscLogEventEnd(fas->eventsmoothsolve,smoothu,0,0,0);CHKERRQ(ierr);} 45239bd7f45SPeter Brune /* check convergence reason for the smoother */ 453ab8d36c9SPeter Brune ierr = SNESGetConvergedReason(smoothu,&reason);CHKERRQ(ierr); 4541ff805c3SPeter Brune if (reason < 0 && !(reason == SNES_DIVERGED_MAX_IT || reason == SNES_DIVERGED_LOCAL_MIN || reason == SNES_DIVERGED_LINE_SEARCH)) { 45539bd7f45SPeter Brune snes->reason = SNES_DIVERGED_INNER; 45639bd7f45SPeter Brune PetscFunctionReturn(0); 45739bd7f45SPeter Brune } 4580298fd71SBarry Smith ierr = SNESGetFunction(smoothu, &FPC, NULL, NULL);CHKERRQ(ierr); 4596cbb2f26SLawrence Mitchell ierr = SNESGetAlwaysComputesFinalResidual(smoothu, &flg);CHKERRQ(ierr); 4606cbb2f26SLawrence Mitchell if (!flg) { 4616cbb2f26SLawrence Mitchell ierr = SNESComputeFunction(smoothu, X, FPC);CHKERRQ(ierr); 4626cbb2f26SLawrence Mitchell } 4634b32a720SPeter Brune ierr = VecCopy(FPC, F);CHKERRQ(ierr); 46471dbe336SPeter Brune if (fnorm) {ierr = VecNorm(F,NORM_2,fnorm);CHKERRQ(ierr);} 46539bd7f45SPeter Brune PetscFunctionReturn(0); 46639bd7f45SPeter Brune } 46739bd7f45SPeter Brune 468938e4a01SJed Brown /*@ 469938e4a01SJed Brown SNESFASCreateCoarseVec - create Vec corresponding to a state vector on one level coarser than current level 470938e4a01SJed Brown 471938e4a01SJed Brown Collective 472938e4a01SJed Brown 473938e4a01SJed Brown Input Arguments: 474938e4a01SJed Brown . snes - SNESFAS 475938e4a01SJed Brown 476938e4a01SJed Brown Output Arguments: 477938e4a01SJed Brown . Xcoarse - vector on level one coarser than snes 478938e4a01SJed Brown 479938e4a01SJed Brown Level: developer 480938e4a01SJed Brown 481938e4a01SJed Brown .seealso: SNESFASSetRestriction(), SNESFASRestrict() 482938e4a01SJed Brown @*/ 483938e4a01SJed Brown PetscErrorCode SNESFASCreateCoarseVec(SNES snes,Vec *Xcoarse) 484938e4a01SJed Brown { 485938e4a01SJed Brown PetscErrorCode ierr; 486938e4a01SJed Brown SNES_FAS *fas = (SNES_FAS*)snes->data; 487938e4a01SJed Brown 488938e4a01SJed Brown PetscFunctionBegin; 4891aa26658SKarl Rupp if (fas->rscale) { 4901aa26658SKarl Rupp ierr = VecDuplicate(fas->rscale,Xcoarse);CHKERRQ(ierr); 491f5af7f23SKarl Rupp } else if (fas->inject) { 4922a7a6963SBarry Smith ierr = MatCreateVecs(fas->inject,Xcoarse,NULL);CHKERRQ(ierr); 49313903a91SSatish Balay } else SETERRQ(PetscObjectComm((PetscObject)snes),PETSC_ERR_ARG_WRONGSTATE,"Must set restriction or injection"); 494938e4a01SJed Brown PetscFunctionReturn(0); 495938e4a01SJed Brown } 496938e4a01SJed Brown 497e9923e8dSJed Brown /*@ 498e9923e8dSJed Brown SNESFASRestrict - restrict a Vec to the next coarser level 499e9923e8dSJed Brown 500e9923e8dSJed Brown Collective 501e9923e8dSJed Brown 502e9923e8dSJed Brown Input Arguments: 503e9923e8dSJed Brown + fine - SNES from which to restrict 504e9923e8dSJed Brown - Xfine - vector to restrict 505e9923e8dSJed Brown 506e9923e8dSJed Brown Output Arguments: 507e9923e8dSJed Brown . Xcoarse - result of restriction 508e9923e8dSJed Brown 509e9923e8dSJed Brown Level: developer 510e9923e8dSJed Brown 511e9923e8dSJed Brown .seealso: SNESFASSetRestriction(), SNESFASSetInjection() 512e9923e8dSJed Brown @*/ 513e9923e8dSJed Brown PetscErrorCode SNESFASRestrict(SNES fine,Vec Xfine,Vec Xcoarse) 514e9923e8dSJed Brown { 515e9923e8dSJed Brown PetscErrorCode ierr; 516e9923e8dSJed Brown SNES_FAS *fas = (SNES_FAS*)fine->data; 517e9923e8dSJed Brown 518e9923e8dSJed Brown PetscFunctionBegin; 519e9923e8dSJed Brown PetscValidHeaderSpecific(fine,SNES_CLASSID,1); 520e9923e8dSJed Brown PetscValidHeaderSpecific(Xfine,VEC_CLASSID,2); 521e9923e8dSJed Brown PetscValidHeaderSpecific(Xcoarse,VEC_CLASSID,3); 522e9923e8dSJed Brown if (fas->inject) { 523e9923e8dSJed Brown ierr = MatRestrict(fas->inject,Xfine,Xcoarse);CHKERRQ(ierr); 524e9923e8dSJed Brown } else { 525e9923e8dSJed Brown ierr = MatRestrict(fas->restrct,Xfine,Xcoarse);CHKERRQ(ierr); 526e9923e8dSJed Brown ierr = VecPointwiseMult(Xcoarse,fas->rscale,Xcoarse);CHKERRQ(ierr); 527e9923e8dSJed Brown } 528e9923e8dSJed Brown PetscFunctionReturn(0); 529e9923e8dSJed Brown } 530e9923e8dSJed Brown 53139bd7f45SPeter Brune /* 53239bd7f45SPeter Brune 53339bd7f45SPeter Brune Performs the FAS coarse correction as: 53439bd7f45SPeter Brune 535b5527d98SMatthew G. Knepley fine problem: F(x) = b 536b5527d98SMatthew G. Knepley coarse problem: F^c(x^c) = b^c 53739bd7f45SPeter Brune 538b5527d98SMatthew G. Knepley b^c = F^c(Rx) - R(F(x) - b) 53939bd7f45SPeter Brune 54039bd7f45SPeter Brune */ 5410adebc6cSBarry Smith PetscErrorCode SNESFASCoarseCorrection(SNES snes, Vec X, Vec F, Vec X_new) 5420adebc6cSBarry Smith { 54339bd7f45SPeter Brune PetscErrorCode ierr; 54439bd7f45SPeter Brune Vec X_c, Xo_c, F_c, B_c; 54539bd7f45SPeter Brune SNESConvergedReason reason; 546ab8d36c9SPeter Brune SNES next; 547ab8d36c9SPeter Brune Mat restrct, interpolate; 5480dd27c6cSPeter Brune SNES_FAS *fasc; 5495fd66863SKarl Rupp 55039bd7f45SPeter Brune PetscFunctionBegin; 551ab8d36c9SPeter Brune ierr = SNESFASCycleGetCorrection(snes, &next);CHKERRQ(ierr); 552ab8d36c9SPeter Brune if (next) { 5530dd27c6cSPeter Brune fasc = (SNES_FAS*)next->data; 5540dd27c6cSPeter Brune 555ab8d36c9SPeter Brune ierr = SNESFASCycleGetRestriction(snes, &restrct);CHKERRQ(ierr); 556ab8d36c9SPeter Brune ierr = SNESFASCycleGetInterpolation(snes, &interpolate);CHKERRQ(ierr); 557ab8d36c9SPeter Brune 558ab8d36c9SPeter Brune X_c = next->vec_sol; 559ab8d36c9SPeter Brune Xo_c = next->work[0]; 560ab8d36c9SPeter Brune F_c = next->vec_func; 561ab8d36c9SPeter Brune B_c = next->vec_rhs; 562efe1f98aSPeter Brune 563217044c2SLisandro Dalcin if (fasc->eventinterprestrict) {ierr = PetscLogEventBegin(fasc->eventinterprestrict,snes,0,0,0);CHKERRQ(ierr);} 564938e4a01SJed Brown ierr = SNESFASRestrict(snes, X, Xo_c);CHKERRQ(ierr); 5655609cbf2SMatthew G. Knepley /* restrict the defect: R(F(x) - b) */ 566ab8d36c9SPeter Brune ierr = MatRestrict(restrct, F, B_c);CHKERRQ(ierr); 567217044c2SLisandro Dalcin if (fasc->eventinterprestrict) {ierr = PetscLogEventEnd(fasc->eventinterprestrict,snes,0,0,0);CHKERRQ(ierr);} 5680dd27c6cSPeter Brune 569217044c2SLisandro Dalcin if (fasc->eventresidual) {ierr = PetscLogEventBegin(fasc->eventresidual,next,0,0,0);CHKERRQ(ierr);} 5705609cbf2SMatthew G. Knepley /* F_c = F^c(Rx) - R(F(x) - b) since the second term was sitting in next->vec_rhs */ 571ab8d36c9SPeter Brune ierr = SNESComputeFunction(next, Xo_c, F_c);CHKERRQ(ierr); 572217044c2SLisandro Dalcin if (fasc->eventresidual) {ierr = PetscLogEventEnd(fasc->eventresidual,next,0,0,0);CHKERRQ(ierr);} 5730dd27c6cSPeter Brune 5740dd27c6cSPeter Brune /* solve the coarse problem corresponding to F^c(x^c) = b^c = F^c(Rx) - R(F(x) - b) */ 575e4ed7901SPeter Brune ierr = VecCopy(B_c, X_c);CHKERRQ(ierr); 576b9c2fdf1SPeter Brune ierr = VecCopy(F_c, B_c);CHKERRQ(ierr); 577e4ed7901SPeter Brune ierr = VecCopy(X_c, F_c);CHKERRQ(ierr); 578ee78dd50SPeter Brune /* set initial guess of the coarse problem to the projected fine solution */ 579ee78dd50SPeter Brune ierr = VecCopy(Xo_c, X_c);CHKERRQ(ierr); 580c90fad12SPeter Brune 581c90fad12SPeter Brune /* recurse to the next level */ 582e4ed7901SPeter Brune ierr = SNESSetInitialFunction(next, F_c);CHKERRQ(ierr); 583ab8d36c9SPeter Brune ierr = SNESSolve(next, B_c, X_c);CHKERRQ(ierr); 584ab8d36c9SPeter Brune ierr = SNESGetConvergedReason(next,&reason);CHKERRQ(ierr); 585742fe5e2SPeter Brune if (reason < 0 && reason != SNES_DIVERGED_MAX_IT) { 586742fe5e2SPeter Brune snes->reason = SNES_DIVERGED_INNER; 587742fe5e2SPeter Brune PetscFunctionReturn(0); 588742fe5e2SPeter Brune } 589fa9694d7SPeter Brune /* correct as x <- x + I(x^c - Rx)*/ 590fa9694d7SPeter Brune ierr = VecAXPY(X_c, -1.0, Xo_c);CHKERRQ(ierr); 5910dd27c6cSPeter Brune 592217044c2SLisandro Dalcin if (fasc->eventinterprestrict) {ierr = PetscLogEventBegin(fasc->eventinterprestrict,snes,0,0,0);CHKERRQ(ierr);} 593ab8d36c9SPeter Brune ierr = MatInterpolateAdd(interpolate, X_c, X, X_new);CHKERRQ(ierr); 594fb8dc43dSMatthew G. Knepley ierr = PetscObjectSetName((PetscObject) X_c, "Coarse correction");CHKERRQ(ierr); 595fb8dc43dSMatthew G. Knepley ierr = VecViewFromOptions(X_c, NULL, "-fas_coarse_solution_view");CHKERRQ(ierr); 596fb8dc43dSMatthew G. Knepley ierr = PetscObjectSetName((PetscObject) X_new, "Updated Fine solution");CHKERRQ(ierr); 597fb8dc43dSMatthew G. Knepley ierr = VecViewFromOptions(X_new, NULL, "-fas_levels_1_solution_view");CHKERRQ(ierr); 598217044c2SLisandro Dalcin if (fasc->eventinterprestrict) {ierr = PetscLogEventEnd(fasc->eventinterprestrict,snes,0,0,0);CHKERRQ(ierr);} 599293a7e31SPeter Brune } 60039bd7f45SPeter Brune PetscFunctionReturn(0); 60139bd7f45SPeter Brune } 60239bd7f45SPeter Brune 60339bd7f45SPeter Brune /* 60439bd7f45SPeter Brune 60539bd7f45SPeter Brune The additive cycle looks like: 60639bd7f45SPeter Brune 60707144faaSPeter Brune xhat = x 60807144faaSPeter Brune xhat = dS(x, b) 60907144faaSPeter Brune x = coarsecorrection(xhat, b_d) 61007144faaSPeter Brune x = x + nu*(xhat - x); 61139bd7f45SPeter Brune (optional) x = uS(x, b) 61239bd7f45SPeter Brune 61339bd7f45SPeter Brune With the coarse RHS (defect correction) as below. 61439bd7f45SPeter Brune 61539bd7f45SPeter Brune */ 61640244768SBarry Smith static PetscErrorCode SNESFASCycle_Additive(SNES snes, Vec X) 6170adebc6cSBarry Smith { 61807144faaSPeter Brune Vec F, B, Xhat; 61922c1e704SPeter Brune Vec X_c, Xo_c, F_c, B_c; 62039bd7f45SPeter Brune PetscErrorCode ierr; 62107144faaSPeter Brune SNESConvergedReason reason; 62222c1e704SPeter Brune PetscReal xnorm, fnorm, ynorm; 623422a814eSBarry Smith SNESLineSearchReason lsresult; 624ab8d36c9SPeter Brune SNES next; 625ab8d36c9SPeter Brune Mat restrct, interpolate; 6260dd27c6cSPeter Brune SNES_FAS *fas = (SNES_FAS*)snes->data,*fasc; 6270dd27c6cSPeter Brune 62839bd7f45SPeter Brune PetscFunctionBegin; 629ab8d36c9SPeter Brune ierr = SNESFASCycleGetCorrection(snes, &next);CHKERRQ(ierr); 63039bd7f45SPeter Brune F = snes->vec_func; 63139bd7f45SPeter Brune B = snes->vec_rhs; 632e7f468e7SPeter Brune Xhat = snes->work[1]; 63307144faaSPeter Brune ierr = VecCopy(X, Xhat);CHKERRQ(ierr); 63407144faaSPeter Brune /* recurse first */ 635ab8d36c9SPeter Brune if (next) { 6360dd27c6cSPeter Brune fasc = (SNES_FAS*)next->data; 637ab8d36c9SPeter Brune ierr = SNESFASCycleGetRestriction(snes, &restrct);CHKERRQ(ierr); 638ab8d36c9SPeter Brune ierr = SNESFASCycleGetInterpolation(snes, &interpolate);CHKERRQ(ierr); 639217044c2SLisandro Dalcin if (fas->eventresidual) {ierr = PetscLogEventBegin(fas->eventresidual,snes,0,0,0);CHKERRQ(ierr);} 64007144faaSPeter Brune ierr = SNESComputeFunction(snes, Xhat, F);CHKERRQ(ierr); 641217044c2SLisandro Dalcin if (fas->eventresidual) {ierr = PetscLogEventEnd(fas->eventresidual,snes,0,0,0);CHKERRQ(ierr);} 642c2a02606SPeter Brune ierr = VecNorm(F, NORM_2, &fnorm);CHKERRQ(ierr); 643ab8d36c9SPeter Brune X_c = next->vec_sol; 644ab8d36c9SPeter Brune Xo_c = next->work[0]; 645ab8d36c9SPeter Brune F_c = next->vec_func; 646ab8d36c9SPeter Brune B_c = next->vec_rhs; 64739bd7f45SPeter Brune 648938e4a01SJed Brown ierr = SNESFASRestrict(snes,Xhat,Xo_c);CHKERRQ(ierr); 64907144faaSPeter Brune /* restrict the defect */ 650ab8d36c9SPeter Brune ierr = MatRestrict(restrct, F, B_c);CHKERRQ(ierr); 65107144faaSPeter Brune 65207144faaSPeter Brune /* solve the coarse problem corresponding to F^c(x^c) = b^c = Rb + F^c(Rx) - RF(x) */ 653217044c2SLisandro Dalcin if (fasc->eventresidual) {ierr = PetscLogEventBegin(fasc->eventresidual,next,0,0,0);CHKERRQ(ierr);} 654ab8d36c9SPeter Brune ierr = SNESComputeFunction(next, Xo_c, F_c);CHKERRQ(ierr); 655217044c2SLisandro Dalcin if (fasc->eventresidual) {ierr = PetscLogEventEnd(fasc->eventresidual,next,0,0,0);CHKERRQ(ierr);} 656e4ed7901SPeter Brune ierr = VecCopy(B_c, X_c);CHKERRQ(ierr); 657b9c2fdf1SPeter Brune ierr = VecCopy(F_c, B_c);CHKERRQ(ierr); 658e4ed7901SPeter Brune ierr = VecCopy(X_c, F_c);CHKERRQ(ierr); 65907144faaSPeter Brune /* set initial guess of the coarse problem to the projected fine solution */ 66007144faaSPeter Brune ierr = VecCopy(Xo_c, X_c);CHKERRQ(ierr); 66107144faaSPeter Brune 66207144faaSPeter Brune /* recurse */ 663e4ed7901SPeter Brune ierr = SNESSetInitialFunction(next, F_c);CHKERRQ(ierr); 664ab8d36c9SPeter Brune ierr = SNESSolve(next, B_c, X_c);CHKERRQ(ierr); 66507144faaSPeter Brune 66607144faaSPeter Brune /* smooth on this level */ 66791f99d7cSPeter Brune ierr = SNESFASDownSmooth_Private(snes, B, X, F, &fnorm);CHKERRQ(ierr); 66807144faaSPeter Brune 669ab8d36c9SPeter Brune ierr = SNESGetConvergedReason(next,&reason);CHKERRQ(ierr); 67007144faaSPeter Brune if (reason < 0 && reason != SNES_DIVERGED_MAX_IT) { 67107144faaSPeter Brune snes->reason = SNES_DIVERGED_INNER; 67207144faaSPeter Brune PetscFunctionReturn(0); 67307144faaSPeter Brune } 67407144faaSPeter Brune 67507144faaSPeter Brune /* correct as x <- x + I(x^c - Rx)*/ 676c68acad4SPeter Brune ierr = VecAYPX(X_c, -1.0, Xo_c);CHKERRQ(ierr); 677ab8d36c9SPeter Brune ierr = MatInterpolate(interpolate, X_c, Xhat);CHKERRQ(ierr); 67807144faaSPeter Brune 679ddebd997SPeter Brune /* additive correction of the coarse direction*/ 680f1c6b773SPeter Brune ierr = SNESLineSearchApply(snes->linesearch, X, F, &fnorm, Xhat);CHKERRQ(ierr); 681422a814eSBarry Smith ierr = SNESLineSearchGetReason(snes->linesearch, &lsresult);CHKERRQ(ierr); 682422a814eSBarry Smith ierr = SNESLineSearchGetNorms(snes->linesearch, &xnorm, &snes->norm, &ynorm);CHKERRQ(ierr); 683422a814eSBarry Smith if (lsresult) { 6849e764e56SPeter Brune if (++snes->numFailures >= snes->maxFailures) { 6859e764e56SPeter Brune snes->reason = SNES_DIVERGED_LINE_SEARCH; 6869e764e56SPeter Brune PetscFunctionReturn(0); 6879e764e56SPeter Brune } 6889e764e56SPeter Brune } 68907144faaSPeter Brune } else { 69091f99d7cSPeter Brune ierr = SNESFASDownSmooth_Private(snes, B, X, F, &snes->norm);CHKERRQ(ierr); 69107144faaSPeter Brune } 69239bd7f45SPeter Brune PetscFunctionReturn(0); 69339bd7f45SPeter Brune } 69439bd7f45SPeter Brune 69539bd7f45SPeter Brune /* 69639bd7f45SPeter Brune 69739bd7f45SPeter Brune Defines the FAS cycle as: 69839bd7f45SPeter Brune 699b5527d98SMatthew G. Knepley fine problem: F(x) = b 70039bd7f45SPeter Brune coarse problem: F^c(x) = b^c 70139bd7f45SPeter Brune 702b5527d98SMatthew G. Knepley b^c = F^c(Rx) - R(F(x) - b) 70339bd7f45SPeter Brune 70439bd7f45SPeter Brune correction: 70539bd7f45SPeter Brune 70639bd7f45SPeter Brune x = x + I(x^c - Rx) 70739bd7f45SPeter Brune 70839bd7f45SPeter Brune */ 70940244768SBarry Smith static PetscErrorCode SNESFASCycle_Multiplicative(SNES snes, Vec X) 7100adebc6cSBarry Smith { 71139bd7f45SPeter Brune 71239bd7f45SPeter Brune PetscErrorCode ierr; 71339bd7f45SPeter Brune Vec F,B; 71434d65b3cSPeter Brune SNES next; 71539bd7f45SPeter Brune 71639bd7f45SPeter Brune PetscFunctionBegin; 71739bd7f45SPeter Brune F = snes->vec_func; 71839bd7f45SPeter Brune B = snes->vec_rhs; 71939bd7f45SPeter Brune /* pre-smooth -- just update using the pre-smoother */ 72034d65b3cSPeter Brune ierr = SNESFASCycleGetCorrection(snes,&next);CHKERRQ(ierr); 72191f99d7cSPeter Brune ierr = SNESFASDownSmooth_Private(snes, B, X, F, &snes->norm);CHKERRQ(ierr); 72234d65b3cSPeter Brune if (next) { 7238c40d5fbSBarry Smith ierr = SNESFASCoarseCorrection(snes, X, F, X);CHKERRQ(ierr); 72491f99d7cSPeter Brune ierr = SNESFASUpSmooth_Private(snes, B, X, F, &snes->norm);CHKERRQ(ierr); 725fe6f9142SPeter Brune } 726fa9694d7SPeter Brune PetscFunctionReturn(0); 727421d9b32SPeter Brune } 728421d9b32SPeter Brune 72940244768SBarry Smith static PetscErrorCode SNESFASCycleSetupPhase_Full(SNES snes) 7308c94862eSPeter Brune { 7318c94862eSPeter Brune SNES next; 7328c94862eSPeter Brune SNES_FAS *fas = (SNES_FAS*)snes->data; 7338c94862eSPeter Brune PetscBool isFine; 7348c94862eSPeter Brune PetscErrorCode ierr; 7358c94862eSPeter Brune 7368c94862eSPeter Brune PetscFunctionBegin; 7378c94862eSPeter Brune /* pre-smooth -- just update using the pre-smoother */ 7388c94862eSPeter Brune ierr = SNESFASCycleIsFine(snes,&isFine);CHKERRQ(ierr); 7398c94862eSPeter Brune ierr = SNESFASCycleGetCorrection(snes,&next);CHKERRQ(ierr); 7408c94862eSPeter Brune fas->full_stage = 0; 7418c94862eSPeter Brune if (next) {ierr = SNESFASCycleSetupPhase_Full(next);CHKERRQ(ierr);} 7428c94862eSPeter Brune PetscFunctionReturn(0); 7438c94862eSPeter Brune } 7448c94862eSPeter Brune 74540244768SBarry Smith static PetscErrorCode SNESFASCycle_Full(SNES snes, Vec X) 7468c94862eSPeter Brune { 7478c94862eSPeter Brune PetscErrorCode ierr; 7488c94862eSPeter Brune Vec F,B; 7498c94862eSPeter Brune SNES_FAS *fas = (SNES_FAS*)snes->data; 7508c94862eSPeter Brune PetscBool isFine; 7518c94862eSPeter Brune SNES next; 7528c94862eSPeter Brune 7538c94862eSPeter Brune PetscFunctionBegin; 7548c94862eSPeter Brune F = snes->vec_func; 7558c94862eSPeter Brune B = snes->vec_rhs; 7568c94862eSPeter Brune ierr = SNESFASCycleIsFine(snes,&isFine);CHKERRQ(ierr); 7578c94862eSPeter Brune ierr = SNESFASCycleGetCorrection(snes,&next);CHKERRQ(ierr); 7588c94862eSPeter Brune 7598c94862eSPeter Brune if (isFine) { 7608c94862eSPeter Brune ierr = SNESFASCycleSetupPhase_Full(snes);CHKERRQ(ierr); 7618c94862eSPeter Brune } 7628c94862eSPeter Brune 7638c94862eSPeter Brune if (fas->full_stage == 0) { 764928e959bSPeter Brune /* downsweep */ 7658c94862eSPeter Brune if (next) { 7668c94862eSPeter Brune if (fas->level != 1) next->max_its += 1; 767928e959bSPeter Brune if (fas->full_downsweep||isFine) {ierr = SNESFASDownSmooth_Private(snes,B,X,F,&snes->norm);CHKERRQ(ierr);} 7688c94862eSPeter Brune ierr = SNESFASCoarseCorrection(snes,X,F,X);CHKERRQ(ierr); 7698c94862eSPeter Brune ierr = SNESFASUpSmooth_Private(snes,B,X,F,&snes->norm);CHKERRQ(ierr); 7708c94862eSPeter Brune if (fas->level != 1) next->max_its -= 1; 7718c94862eSPeter Brune } else { 772a3a80b83SMatthew G. Knepley /* The smoother on the coarse level is the coarse solver */ 7738c94862eSPeter Brune ierr = SNESFASDownSmooth_Private(snes,B,X,F,&snes->norm);CHKERRQ(ierr); 7748c94862eSPeter Brune } 7758c94862eSPeter Brune fas->full_stage = 1; 7768c94862eSPeter Brune } else if (fas->full_stage == 1) { 7778c94862eSPeter Brune if (snes->iter == 0) {ierr = SNESFASDownSmooth_Private(snes,B,X,F,&snes->norm);CHKERRQ(ierr);} 7788c94862eSPeter Brune if (next) { 7798c94862eSPeter Brune ierr = SNESFASCoarseCorrection(snes,X,F,X);CHKERRQ(ierr); 7808c94862eSPeter Brune ierr = SNESFASUpSmooth_Private(snes,B,X,F,&snes->norm);CHKERRQ(ierr); 7818c94862eSPeter Brune } 7828c94862eSPeter Brune } 7838c94862eSPeter Brune /* final v-cycle */ 7848c94862eSPeter Brune if (isFine) { 7858c94862eSPeter Brune if (next) { 7868c94862eSPeter Brune ierr = SNESFASCoarseCorrection(snes,X,F,X);CHKERRQ(ierr); 7878c94862eSPeter Brune ierr = SNESFASUpSmooth_Private(snes,B,X,F,&snes->norm);CHKERRQ(ierr); 7888c94862eSPeter Brune } 7898c94862eSPeter Brune } 7908c94862eSPeter Brune PetscFunctionReturn(0); 7918c94862eSPeter Brune } 7928c94862eSPeter Brune 79340244768SBarry Smith static PetscErrorCode SNESFASCycle_Kaskade(SNES snes, Vec X) 79434d65b3cSPeter Brune { 79534d65b3cSPeter Brune PetscErrorCode ierr; 79634d65b3cSPeter Brune Vec F,B; 79734d65b3cSPeter Brune SNES next; 79834d65b3cSPeter Brune 79934d65b3cSPeter Brune PetscFunctionBegin; 80034d65b3cSPeter Brune F = snes->vec_func; 80134d65b3cSPeter Brune B = snes->vec_rhs; 80234d65b3cSPeter Brune ierr = SNESFASCycleGetCorrection(snes,&next);CHKERRQ(ierr); 80334d65b3cSPeter Brune if (next) { 80434d65b3cSPeter Brune ierr = SNESFASCoarseCorrection(snes,X,F,X);CHKERRQ(ierr); 80534d65b3cSPeter Brune ierr = SNESFASUpSmooth_Private(snes,B,X,F,&snes->norm);CHKERRQ(ierr); 80634d65b3cSPeter Brune } else { 80734d65b3cSPeter Brune ierr = SNESFASDownSmooth_Private(snes,B,X,F,&snes->norm);CHKERRQ(ierr); 80834d65b3cSPeter Brune } 80934d65b3cSPeter Brune PetscFunctionReturn(0); 81034d65b3cSPeter Brune } 81134d65b3cSPeter Brune 812fffbeea8SBarry Smith PetscBool SNEScite = PETSC_FALSE; 813fffbeea8SBarry Smith const char SNESCitation[] = "@techreport{pbmkbsxt2012,\n" 814fffbeea8SBarry Smith " title = {Composing Scalable Nonlinear Algebraic Solvers},\n" 815fffbeea8SBarry Smith " author = {Peter Brune and Mathew Knepley and Barry Smith and Xuemin Tu},\n" 816fffbeea8SBarry Smith " year = 2013,\n" 817fffbeea8SBarry Smith " type = Preprint,\n" 818fffbeea8SBarry Smith " number = {ANL/MCS-P2010-0112},\n" 819fffbeea8SBarry Smith " institution = {Argonne National Laboratory}\n}\n"; 820fffbeea8SBarry Smith 82140244768SBarry Smith static PetscErrorCode SNESSolve_FAS(SNES snes) 822421d9b32SPeter Brune { 823fa9694d7SPeter Brune PetscErrorCode ierr; 824fe6f9142SPeter Brune PetscInt i, maxits; 825ddb5aff1SPeter Brune Vec X, F; 826fe6f9142SPeter Brune PetscReal fnorm; 827b17ce1afSJed Brown SNES_FAS *fas = (SNES_FAS*)snes->data,*ffas; 828b17ce1afSJed Brown DM dm; 829e70c42e5SPeter Brune PetscBool isFine; 830b17ce1afSJed Brown 831421d9b32SPeter Brune PetscFunctionBegin; 832c579b300SPatrick Farrell 8336c4ed002SBarry 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); 834c579b300SPatrick Farrell 835fffbeea8SBarry Smith ierr = PetscCitationsRegister(SNESCitation,&SNEScite);CHKERRQ(ierr); 836fe6f9142SPeter Brune maxits = snes->max_its; /* maximum number of iterations */ 837fe6f9142SPeter Brune snes->reason = SNES_CONVERGED_ITERATING; 838fa9694d7SPeter Brune X = snes->vec_sol; 839f5a6d4f9SBarry Smith F = snes->vec_func; 840293a7e31SPeter Brune 84118a66777SPeter Brune ierr = SNESFASCycleIsFine(snes, &isFine);CHKERRQ(ierr); 842293a7e31SPeter Brune /*norm setup */ 843e04113cfSBarry Smith ierr = PetscObjectSAWsTakeAccess((PetscObject)snes);CHKERRQ(ierr); 844fe6f9142SPeter Brune snes->iter = 0; 845fe6f9142SPeter Brune snes->norm = 0.; 846e04113cfSBarry Smith ierr = PetscObjectSAWsGrantAccess((PetscObject)snes);CHKERRQ(ierr); 847e4ed7901SPeter Brune if (!snes->vec_func_init_set) { 848217044c2SLisandro Dalcin if (fas->eventresidual) {ierr = PetscLogEventBegin(fas->eventresidual,snes,0,0,0);CHKERRQ(ierr);} 849fe6f9142SPeter Brune ierr = SNESComputeFunction(snes,X,F);CHKERRQ(ierr); 850217044c2SLisandro Dalcin if (fas->eventresidual) {ierr = PetscLogEventEnd(fas->eventresidual,snes,0,0,0);CHKERRQ(ierr);} 8511aa26658SKarl Rupp } else snes->vec_func_init_set = PETSC_FALSE; 852e4ed7901SPeter Brune 853fe6f9142SPeter Brune ierr = VecNorm(F, NORM_2, &fnorm);CHKERRQ(ierr); /* fnorm <- ||F|| */ 854422a814eSBarry Smith SNESCheckFunctionNorm(snes,fnorm); 855e04113cfSBarry Smith ierr = PetscObjectSAWsTakeAccess((PetscObject)snes);CHKERRQ(ierr); 856fe6f9142SPeter Brune snes->norm = fnorm; 857e04113cfSBarry Smith ierr = PetscObjectSAWsGrantAccess((PetscObject)snes);CHKERRQ(ierr); 858a71f0d7dSBarry Smith ierr = SNESLogConvergenceHistory(snes,fnorm,0);CHKERRQ(ierr); 859fe6f9142SPeter Brune ierr = SNESMonitor(snes,0,fnorm);CHKERRQ(ierr); 860fe6f9142SPeter Brune 861fe6f9142SPeter Brune /* test convergence */ 862fe6f9142SPeter Brune ierr = (*snes->ops->converged)(snes,0,0.0,0.0,fnorm,&snes->reason,snes->cnvP);CHKERRQ(ierr); 863fe6f9142SPeter Brune if (snes->reason) PetscFunctionReturn(0); 864e4ed7901SPeter Brune 865b17ce1afSJed Brown 866b9c2fdf1SPeter Brune if (isFine) { 867b9c2fdf1SPeter Brune /* propagate scale-dependent data up the hierarchy */ 868b17ce1afSJed Brown ierr = SNESGetDM(snes,&dm);CHKERRQ(ierr); 869b17ce1afSJed Brown for (ffas=fas; ffas->next; ffas=(SNES_FAS*)ffas->next->data) { 870b17ce1afSJed Brown DM dmcoarse; 871b17ce1afSJed Brown ierr = SNESGetDM(ffas->next,&dmcoarse);CHKERRQ(ierr); 872b17ce1afSJed Brown ierr = DMRestrict(dm,ffas->restrct,ffas->rscale,ffas->inject,dmcoarse);CHKERRQ(ierr); 873b17ce1afSJed Brown dm = dmcoarse; 874b17ce1afSJed Brown } 875b9c2fdf1SPeter Brune } 876b17ce1afSJed Brown 877fe6f9142SPeter Brune for (i = 0; i < maxits; i++) { 878fe6f9142SPeter Brune /* Call general purpose update function */ 879646217ecSPeter Brune 880fe6f9142SPeter Brune if (snes->ops->update) { 881fe6f9142SPeter Brune ierr = (*snes->ops->update)(snes, snes->iter);CHKERRQ(ierr); 882fe6f9142SPeter Brune } 88307144faaSPeter Brune if (fas->fastype == SNES_FAS_MULTIPLICATIVE) { 88491f99d7cSPeter Brune ierr = SNESFASCycle_Multiplicative(snes, X);CHKERRQ(ierr); 8858c94862eSPeter Brune } else if (fas->fastype == SNES_FAS_ADDITIVE) { 88691f99d7cSPeter Brune ierr = SNESFASCycle_Additive(snes, X);CHKERRQ(ierr); 8878c94862eSPeter Brune } else if (fas->fastype == SNES_FAS_FULL) { 8888c94862eSPeter Brune ierr = SNESFASCycle_Full(snes, X);CHKERRQ(ierr); 88934d65b3cSPeter Brune } else if (fas->fastype ==SNES_FAS_KASKADE) { 89034d65b3cSPeter Brune ierr = SNESFASCycle_Kaskade(snes, X);CHKERRQ(ierr); 8916c4ed002SBarry Smith } else SETERRQ(PetscObjectComm((PetscObject)snes),PETSC_ERR_ARG_WRONGSTATE,"Unsupported FAS type"); 892742fe5e2SPeter Brune 893742fe5e2SPeter Brune /* check for FAS cycle divergence */ 8941aa26658SKarl Rupp if (snes->reason != SNES_CONVERGED_ITERATING) PetscFunctionReturn(0); 895b9c2fdf1SPeter Brune 896c90fad12SPeter Brune /* Monitor convergence */ 897e04113cfSBarry Smith ierr = PetscObjectSAWsTakeAccess((PetscObject)snes);CHKERRQ(ierr); 898c90fad12SPeter Brune snes->iter = i+1; 899e04113cfSBarry Smith ierr = PetscObjectSAWsGrantAccess((PetscObject)snes);CHKERRQ(ierr); 900a71f0d7dSBarry Smith ierr = SNESLogConvergenceHistory(snes,snes->norm,0);CHKERRQ(ierr); 901c90fad12SPeter Brune ierr = SNESMonitor(snes,snes->iter,snes->norm);CHKERRQ(ierr); 902c90fad12SPeter Brune /* Test for convergence */ 90366585501SPeter Brune if (isFine) { 904b9c2fdf1SPeter Brune ierr = (*snes->ops->converged)(snes,snes->iter,0.0,0.0,snes->norm,&snes->reason,snes->cnvP);CHKERRQ(ierr); 905c90fad12SPeter Brune if (snes->reason) break; 906fe6f9142SPeter Brune } 90766585501SPeter Brune } 908fe6f9142SPeter Brune if (i == maxits) { 909fe6f9142SPeter Brune ierr = PetscInfo1(snes, "Maximum number of iterations has been reached: %D\n", maxits);CHKERRQ(ierr); 910fe6f9142SPeter Brune if (!snes->reason) snes->reason = SNES_DIVERGED_MAX_IT; 911fe6f9142SPeter Brune } 912421d9b32SPeter Brune PetscFunctionReturn(0); 913421d9b32SPeter Brune } 91440244768SBarry Smith 91540244768SBarry Smith /*MC 91640244768SBarry Smith 91740244768SBarry Smith SNESFAS - Full Approximation Scheme nonlinear multigrid solver. 91840244768SBarry Smith 91940244768SBarry Smith The nonlinear problem is solved by correction using coarse versions 92040244768SBarry Smith of the nonlinear problem. This problem is perturbed so that a projected 92140244768SBarry Smith solution of the fine problem elicits no correction from the coarse problem. 92240244768SBarry Smith 92340244768SBarry Smith Options Database: 92440244768SBarry Smith + -snes_fas_levels - The number of levels 92540244768SBarry Smith . -snes_fas_cycles<1> - The number of cycles -- 1 for V, 2 for W 92640244768SBarry Smith . -snes_fas_type<additive,multiplicative,full,kaskade> - Additive or multiplicative cycle 92740244768SBarry Smith . -snes_fas_galerkin<PETSC_FALSE> - Form coarse problems by projection back upon the fine problem 92840244768SBarry Smith . -snes_fas_smoothup<1> - The number of iterations of the post-smoother 92940244768SBarry Smith . -snes_fas_smoothdown<1> - The number of iterations of the pre-smoother 93040244768SBarry Smith . -snes_fas_monitor - Monitor progress of all of the levels 93140244768SBarry Smith . -snes_fas_full_downsweep<PETSC_FALSE> - call the downsmooth on the initial downsweep of full FAS 93240244768SBarry Smith . -fas_levels_snes_ - SNES options for all smoothers 93340244768SBarry Smith . -fas_levels_cycle_snes_ - SNES options for all cycles 93440244768SBarry Smith . -fas_levels_i_snes_ - SNES options for the smoothers on level i 93540244768SBarry Smith . -fas_levels_i_cycle_snes_ - SNES options for the cycle on level i 93640244768SBarry Smith - -fas_coarse_snes_ - SNES options for the coarsest smoother 93740244768SBarry Smith 93840244768SBarry Smith Notes: 93940244768SBarry Smith The organization of the FAS solver is slightly different from the organization of PCMG 94040244768SBarry Smith As each level has smoother SNES instances(down and potentially up) and a cycle SNES instance. 94140244768SBarry Smith The cycle SNES instance may be used for monitoring convergence on a particular level. 94240244768SBarry Smith 94340244768SBarry Smith Level: beginner 94440244768SBarry Smith 94540244768SBarry Smith References: 94640244768SBarry Smith . 1. - Peter R. Brune, Matthew G. Knepley, Barry F. Smith, and Xuemin Tu, "Composing Scalable Nonlinear Algebraic Solvers", 94740244768SBarry Smith SIAM Review, 57(4), 2015 94840244768SBarry Smith 94940244768SBarry Smith .seealso: PCMG, SNESCreate(), SNES, SNESSetType(), SNESType (for list of available types) 95040244768SBarry Smith M*/ 95140244768SBarry Smith 95240244768SBarry Smith PETSC_EXTERN PetscErrorCode SNESCreate_FAS(SNES snes) 95340244768SBarry Smith { 95440244768SBarry Smith SNES_FAS *fas; 95540244768SBarry Smith PetscErrorCode ierr; 95640244768SBarry Smith 95740244768SBarry Smith PetscFunctionBegin; 95840244768SBarry Smith snes->ops->destroy = SNESDestroy_FAS; 95940244768SBarry Smith snes->ops->setup = SNESSetUp_FAS; 96040244768SBarry Smith snes->ops->setfromoptions = SNESSetFromOptions_FAS; 96140244768SBarry Smith snes->ops->view = SNESView_FAS; 96240244768SBarry Smith snes->ops->solve = SNESSolve_FAS; 96340244768SBarry Smith snes->ops->reset = SNESReset_FAS; 96440244768SBarry Smith 96540244768SBarry Smith snes->usesksp = PETSC_FALSE; 966efd4aadfSBarry Smith snes->usesnpc = PETSC_FALSE; 96740244768SBarry Smith 96840244768SBarry Smith if (!snes->tolerancesset) { 96940244768SBarry Smith snes->max_funcs = 30000; 97040244768SBarry Smith snes->max_its = 10000; 97140244768SBarry Smith } 97240244768SBarry Smith 9734fc747eaSLawrence Mitchell snes->alwayscomputesfinalresidual = PETSC_TRUE; 9744fc747eaSLawrence Mitchell 97540244768SBarry Smith ierr = PetscNewLog(snes,&fas);CHKERRQ(ierr); 97640244768SBarry Smith 97740244768SBarry Smith snes->data = (void*) fas; 97840244768SBarry Smith fas->level = 0; 97940244768SBarry Smith fas->levels = 1; 98040244768SBarry Smith fas->n_cycles = 1; 98140244768SBarry Smith fas->max_up_it = 1; 98240244768SBarry Smith fas->max_down_it = 1; 98340244768SBarry Smith fas->smoothu = NULL; 98440244768SBarry Smith fas->smoothd = NULL; 98540244768SBarry Smith fas->next = NULL; 98640244768SBarry Smith fas->previous = NULL; 98740244768SBarry Smith fas->fine = snes; 98840244768SBarry Smith fas->interpolate = NULL; 98940244768SBarry Smith fas->restrct = NULL; 99040244768SBarry Smith fas->inject = NULL; 99140244768SBarry Smith fas->usedmfornumberoflevels = PETSC_FALSE; 99240244768SBarry Smith fas->fastype = SNES_FAS_MULTIPLICATIVE; 99340244768SBarry Smith fas->full_downsweep = PETSC_FALSE; 99440244768SBarry Smith 99540244768SBarry Smith fas->eventsmoothsetup = 0; 99640244768SBarry Smith fas->eventsmoothsolve = 0; 99740244768SBarry Smith fas->eventresidual = 0; 99840244768SBarry Smith fas->eventinterprestrict = 0; 99940244768SBarry Smith PetscFunctionReturn(0); 100040244768SBarry Smith } 1001