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 8421d9b32SPeter Brune #undef __FUNCT__ 9421d9b32SPeter Brune #define __FUNCT__ "SNESReset_FAS" 1040244768SBarry Smith static PetscErrorCode SNESReset_FAS(SNES snes) 11421d9b32SPeter Brune { 1277df8cc4SPeter Brune PetscErrorCode ierr = 0; 13421d9b32SPeter Brune SNES_FAS * fas = (SNES_FAS*)snes->data; 14421d9b32SPeter Brune 15421d9b32SPeter Brune PetscFunctionBegin; 16ab8d36c9SPeter Brune ierr = SNESDestroy(&fas->smoothu);CHKERRQ(ierr); 17ab8d36c9SPeter Brune ierr = SNESDestroy(&fas->smoothd);CHKERRQ(ierr); 183dccd265SPeter Brune ierr = MatDestroy(&fas->inject);CHKERRQ(ierr); 19bccf9bb3SJed Brown ierr = MatDestroy(&fas->interpolate);CHKERRQ(ierr); 20bccf9bb3SJed Brown ierr = MatDestroy(&fas->restrct);CHKERRQ(ierr); 21bccf9bb3SJed Brown ierr = VecDestroy(&fas->rscale);CHKERRQ(ierr); 227cd33a7bSPeter Brune if (fas->galerkin) { 237cd33a7bSPeter Brune ierr = VecDestroy(&fas->Xg);CHKERRQ(ierr); 247cd33a7bSPeter Brune ierr = VecDestroy(&fas->Fg);CHKERRQ(ierr); 257cd33a7bSPeter Brune } 26d477d801SPeter Brune if (fas->next) {ierr = SNESReset(fas->next);CHKERRQ(ierr);} 27421d9b32SPeter Brune PetscFunctionReturn(0); 28421d9b32SPeter Brune } 29421d9b32SPeter Brune 30421d9b32SPeter Brune #undef __FUNCT__ 31421d9b32SPeter Brune #define __FUNCT__ "SNESDestroy_FAS" 3240244768SBarry Smith static PetscErrorCode SNESDestroy_FAS(SNES snes) 33421d9b32SPeter Brune { 34421d9b32SPeter Brune SNES_FAS * fas = (SNES_FAS*)snes->data; 35742fe5e2SPeter Brune PetscErrorCode ierr = 0; 36421d9b32SPeter Brune 37421d9b32SPeter Brune PetscFunctionBegin; 38421d9b32SPeter Brune /* recursively resets and then destroys */ 3979d9a41aSPeter Brune ierr = SNESReset(snes);CHKERRQ(ierr); 401aa26658SKarl Rupp if (fas->next) { 411aa26658SKarl Rupp ierr = SNESDestroy(&fas->next);CHKERRQ(ierr); 421aa26658SKarl Rupp } 43421d9b32SPeter Brune ierr = PetscFree(fas);CHKERRQ(ierr); 44421d9b32SPeter Brune PetscFunctionReturn(0); 45421d9b32SPeter Brune } 46421d9b32SPeter Brune 47421d9b32SPeter Brune #undef __FUNCT__ 48421d9b32SPeter Brune #define __FUNCT__ "SNESSetUp_FAS" 4940244768SBarry Smith static PetscErrorCode SNESSetUp_FAS(SNES snes) 50421d9b32SPeter Brune { 5148bfdf8aSPeter Brune SNES_FAS *fas = (SNES_FAS*) snes->data; 52421d9b32SPeter Brune PetscErrorCode ierr; 53d1adcc6fSPeter Brune PetscInt dm_levels; 543dccd265SPeter Brune Vec vec_sol, vec_func, vec_sol_update, vec_rhs; /* preserve these if they're set through the reset */ 55ab8d36c9SPeter Brune SNES next; 56ab8d36c9SPeter Brune PetscBool isFine; 57f89ba88eSPeter Brune SNESLineSearch linesearch; 58f89ba88eSPeter Brune SNESLineSearch slinesearch; 59f89ba88eSPeter Brune void *lsprectx,*lspostctx; 606b2b7091SBarry Smith PetscErrorCode (*precheck)(SNESLineSearch,Vec,Vec,PetscBool*,void*); 616b2b7091SBarry Smith PetscErrorCode (*postcheck)(SNESLineSearch,Vec,Vec,Vec,PetscBool*,PetscBool*,void*); 62eff52c0eSPeter Brune 636b2b7091SBarry Smith PetscFunctionBegin; 64ab8d36c9SPeter Brune ierr = SNESFASCycleIsFine(snes, &isFine);CHKERRQ(ierr); 65ab8d36c9SPeter Brune if (fas->usedmfornumberoflevels && isFine) { 66d1adcc6fSPeter Brune ierr = DMGetRefineLevel(snes->dm,&dm_levels);CHKERRQ(ierr); 67d1adcc6fSPeter Brune dm_levels++; 68cc05f883SPeter Brune if (dm_levels > fas->levels) { 692e8ce248SJed Brown /* we don't want the solution and func vectors to be destroyed in the SNESReset when it's called in SNESFASSetLevels_FAS*/ 703dccd265SPeter Brune vec_sol = snes->vec_sol; 713dccd265SPeter Brune vec_func = snes->vec_func; 723dccd265SPeter Brune vec_sol_update = snes->vec_sol_update; 733dccd265SPeter Brune vec_rhs = snes->vec_rhs; 740298fd71SBarry Smith snes->vec_sol = NULL; 750298fd71SBarry Smith snes->vec_func = NULL; 760298fd71SBarry Smith snes->vec_sol_update = NULL; 770298fd71SBarry Smith snes->vec_rhs = NULL; 783dccd265SPeter Brune 793dccd265SPeter Brune /* reset the number of levels */ 800298fd71SBarry Smith ierr = SNESFASSetLevels(snes,dm_levels,NULL);CHKERRQ(ierr); 81cc05f883SPeter Brune ierr = SNESSetFromOptions(snes);CHKERRQ(ierr); 823dccd265SPeter Brune 833dccd265SPeter Brune snes->vec_sol = vec_sol; 843dccd265SPeter Brune snes->vec_func = vec_func; 853dccd265SPeter Brune snes->vec_rhs = vec_rhs; 863dccd265SPeter Brune snes->vec_sol_update = vec_sol_update; 87d1adcc6fSPeter Brune } 88d1adcc6fSPeter Brune } 89ab8d36c9SPeter Brune ierr = SNESFASCycleGetCorrection(snes, &next);CHKERRQ(ierr); 90ab8d36c9SPeter Brune if (!isFine) snes->gridsequence = 0; /* no grid sequencing inside the multigrid hierarchy! */ 913dccd265SPeter Brune 92fa0ddf94SBarry Smith ierr = SNESSetWorkVecs(snes, 2);CHKERRQ(ierr); /* work vectors used for intergrid transfers */ 93cc05f883SPeter Brune 94ab8d36c9SPeter Brune /* set up the smoothers if they haven't already been set up */ 95ab8d36c9SPeter Brune if (!fas->smoothd) { 96ab8d36c9SPeter Brune ierr = SNESFASCycleCreateSmoother_Private(snes, &fas->smoothd);CHKERRQ(ierr); 97ab8d36c9SPeter Brune } 98ab8d36c9SPeter Brune 9979d9a41aSPeter Brune if (snes->dm) { 100ab8d36c9SPeter Brune /* set the smoother DMs properly */ 101ab8d36c9SPeter Brune if (fas->smoothu) ierr = SNESSetDM(fas->smoothu, snes->dm);CHKERRQ(ierr); 102ab8d36c9SPeter Brune ierr = SNESSetDM(fas->smoothd, snes->dm);CHKERRQ(ierr); 10379d9a41aSPeter Brune /* construct EVERYTHING from the DM -- including the progressive set of smoothers */ 104ab8d36c9SPeter Brune if (next) { 10579d9a41aSPeter Brune /* for now -- assume the DM and the evaluation functions have been set externally */ 106ab8d36c9SPeter Brune if (!next->dm) { 107ce94432eSBarry Smith ierr = DMCoarsen(snes->dm, PetscObjectComm((PetscObject)next), &next->dm);CHKERRQ(ierr); 108ab8d36c9SPeter Brune ierr = SNESSetDM(next, next->dm);CHKERRQ(ierr); 10979d9a41aSPeter Brune } 11079d9a41aSPeter Brune /* set the interpolation and restriction from the DM */ 11179d9a41aSPeter Brune if (!fas->interpolate) { 112ab8d36c9SPeter Brune ierr = DMCreateInterpolation(next->dm, snes->dm, &fas->interpolate, &fas->rscale);CHKERRQ(ierr); 113bccf9bb3SJed Brown if (!fas->restrct) { 114bccf9bb3SJed Brown ierr = PetscObjectReference((PetscObject)fas->interpolate);CHKERRQ(ierr); 11579d9a41aSPeter Brune fas->restrct = fas->interpolate; 11679d9a41aSPeter Brune } 117bccf9bb3SJed Brown } 11879d9a41aSPeter Brune /* set the injection from the DM */ 11979d9a41aSPeter Brune if (!fas->inject) { 1206dbf9973SLawrence Mitchell ierr = DMCreateInjection(next->dm, snes->dm, &fas->inject);CHKERRQ(ierr); 12179d9a41aSPeter Brune } 12279d9a41aSPeter Brune } 12379d9a41aSPeter Brune } 12479d9a41aSPeter Brune /*pass the smoother, function, and jacobian up to the next level if it's not user set already */ 12579d9a41aSPeter Brune if (fas->galerkin) { 1261aa26658SKarl Rupp if (next) { 1270298fd71SBarry Smith ierr = SNESSetFunction(next, NULL, SNESFASGalerkinDefaultFunction, next);CHKERRQ(ierr); 1281aa26658SKarl Rupp } 1291aa26658SKarl Rupp if (fas->smoothd && fas->level != fas->levels - 1) { 1300298fd71SBarry Smith ierr = SNESSetFunction(fas->smoothd, NULL, SNESFASGalerkinDefaultFunction, snes);CHKERRQ(ierr); 1311aa26658SKarl Rupp } 1321aa26658SKarl Rupp if (fas->smoothu && fas->level != fas->levels - 1) { 1330298fd71SBarry Smith ierr = SNESSetFunction(fas->smoothu, NULL, SNESFASGalerkinDefaultFunction, snes);CHKERRQ(ierr); 1341aa26658SKarl Rupp } 13579d9a41aSPeter Brune } 13679d9a41aSPeter Brune 137534ebe21SPeter Brune /* sets the down (pre) smoother's default norm and sets it from options */ 138534ebe21SPeter Brune if (fas->smoothd) { 139bc3f2f05SPeter Brune if (fas->level == 0 && fas->levels != 1) { 140365a6726SPeter Brune ierr = SNESSetNormSchedule(fas->smoothd, SNES_NORM_NONE);CHKERRQ(ierr); 141534ebe21SPeter Brune } else { 142365a6726SPeter Brune ierr = SNESSetNormSchedule(fas->smoothd, SNES_NORM_FINAL_ONLY);CHKERRQ(ierr); 143534ebe21SPeter Brune } 1447fce8c19SPeter Brune ierr = PetscObjectCopyFortranFunctionPointers((PetscObject)snes, (PetscObject)fas->smoothd);CHKERRQ(ierr); 145534ebe21SPeter Brune ierr = SNESSetFromOptions(fas->smoothd);CHKERRQ(ierr); 1467601faf0SJed Brown ierr = SNESGetLineSearch(snes,&linesearch);CHKERRQ(ierr); 1477601faf0SJed Brown ierr = SNESGetLineSearch(fas->smoothd,&slinesearch);CHKERRQ(ierr); 1486b2b7091SBarry Smith ierr = SNESLineSearchGetPreCheck(linesearch,&precheck,&lsprectx);CHKERRQ(ierr); 1496b2b7091SBarry Smith ierr = SNESLineSearchGetPostCheck(linesearch,&postcheck,&lspostctx);CHKERRQ(ierr); 1506b2b7091SBarry Smith ierr = SNESLineSearchSetPreCheck(slinesearch,precheck,lsprectx);CHKERRQ(ierr); 1516b2b7091SBarry Smith ierr = SNESLineSearchSetPostCheck(slinesearch,postcheck,lspostctx);CHKERRQ(ierr); 152f89ba88eSPeter Brune ierr = PetscObjectCopyFortranFunctionPointers((PetscObject)linesearch, (PetscObject)slinesearch);CHKERRQ(ierr); 1530dd27c6cSPeter Brune 1540dd27c6cSPeter Brune fas->smoothd->vec_sol = snes->vec_sol; 1550dd27c6cSPeter Brune ierr = PetscObjectReference((PetscObject)snes->vec_sol);CHKERRQ(ierr); 1560dd27c6cSPeter Brune fas->smoothd->vec_sol_update = snes->vec_sol_update; 1570dd27c6cSPeter Brune ierr = PetscObjectReference((PetscObject)snes->vec_sol_update);CHKERRQ(ierr); 1580dd27c6cSPeter Brune fas->smoothd->vec_func = snes->vec_func; 1590dd27c6cSPeter Brune ierr = PetscObjectReference((PetscObject)snes->vec_func);CHKERRQ(ierr); 1600dd27c6cSPeter Brune 1610dd27c6cSPeter Brune if (fas->eventsmoothsetup) {ierr = PetscLogEventBegin(fas->eventsmoothsetup,0,0,0,0);CHKERRQ(ierr);} 1620dd27c6cSPeter Brune ierr = SNESSetUp(fas->smoothd);CHKERRQ(ierr); 1630dd27c6cSPeter Brune if (fas->eventsmoothsetup) {ierr = PetscLogEventEnd(fas->eventsmoothsetup,0,0,0,0);CHKERRQ(ierr);} 164534ebe21SPeter Brune } 165534ebe21SPeter Brune 166534ebe21SPeter Brune /* sets the up (post) smoother's default norm and sets it from options */ 167534ebe21SPeter Brune if (fas->smoothu) { 168534ebe21SPeter Brune if (fas->level != fas->levels - 1) { 169365a6726SPeter Brune ierr = SNESSetNormSchedule(fas->smoothu, SNES_NORM_NONE);CHKERRQ(ierr); 170534ebe21SPeter Brune } else { 171365a6726SPeter Brune ierr = SNESSetNormSchedule(fas->smoothu, SNES_NORM_FINAL_ONLY);CHKERRQ(ierr); 172534ebe21SPeter Brune } 1737fce8c19SPeter Brune ierr = PetscObjectCopyFortranFunctionPointers((PetscObject)snes, (PetscObject)fas->smoothu);CHKERRQ(ierr); 174534ebe21SPeter Brune ierr = SNESSetFromOptions(fas->smoothu);CHKERRQ(ierr); 1757601faf0SJed Brown ierr = SNESGetLineSearch(snes,&linesearch);CHKERRQ(ierr); 1767601faf0SJed Brown ierr = SNESGetLineSearch(fas->smoothu,&slinesearch);CHKERRQ(ierr); 1776b2b7091SBarry Smith ierr = SNESLineSearchGetPreCheck(linesearch,&precheck,&lsprectx);CHKERRQ(ierr); 1786b2b7091SBarry Smith ierr = SNESLineSearchGetPostCheck(linesearch,&postcheck,&lspostctx);CHKERRQ(ierr); 1796b2b7091SBarry Smith ierr = SNESLineSearchSetPreCheck(slinesearch,precheck,lsprectx);CHKERRQ(ierr); 1806b2b7091SBarry Smith ierr = SNESLineSearchSetPostCheck(slinesearch,postcheck,lspostctx);CHKERRQ(ierr); 181f89ba88eSPeter Brune ierr = PetscObjectCopyFortranFunctionPointers((PetscObject)linesearch, (PetscObject)slinesearch);CHKERRQ(ierr); 1820dd27c6cSPeter Brune 1830dd27c6cSPeter Brune fas->smoothu->vec_sol = snes->vec_sol; 1840dd27c6cSPeter Brune ierr = PetscObjectReference((PetscObject)snes->vec_sol);CHKERRQ(ierr); 1850dd27c6cSPeter Brune fas->smoothu->vec_sol_update = snes->vec_sol_update; 1860dd27c6cSPeter Brune ierr = PetscObjectReference((PetscObject)snes->vec_sol_update);CHKERRQ(ierr); 1870dd27c6cSPeter Brune fas->smoothu->vec_func = snes->vec_func; 1880dd27c6cSPeter Brune ierr = PetscObjectReference((PetscObject)snes->vec_func);CHKERRQ(ierr); 1890dd27c6cSPeter Brune 1900dd27c6cSPeter Brune if (fas->eventsmoothsetup) {ierr = PetscLogEventBegin(fas->eventsmoothsetup,0,0,0,0);CHKERRQ(ierr);} 1910dd27c6cSPeter Brune ierr = SNESSetUp(fas->smoothu);CHKERRQ(ierr); 1920dd27c6cSPeter Brune if (fas->eventsmoothsetup) {ierr = PetscLogEventEnd(fas->eventsmoothsetup,0,0,0,0);CHKERRQ(ierr);} 1930dd27c6cSPeter Brune 194534ebe21SPeter Brune } 195d06165b7SPeter Brune 196ab8d36c9SPeter Brune if (next) { 19779d9a41aSPeter Brune /* gotta set up the solution vector for this to work */ 198ab8d36c9SPeter Brune if (!next->vec_sol) {ierr = SNESFASCreateCoarseVec(snes,&next->vec_sol);CHKERRQ(ierr);} 199ab8d36c9SPeter Brune if (!next->vec_rhs) {ierr = SNESFASCreateCoarseVec(snes,&next->vec_rhs);CHKERRQ(ierr);} 2007fce8c19SPeter Brune ierr = PetscObjectCopyFortranFunctionPointers((PetscObject)snes, (PetscObject)next);CHKERRQ(ierr); 2017601faf0SJed Brown ierr = SNESGetLineSearch(snes,&linesearch);CHKERRQ(ierr); 2027601faf0SJed Brown ierr = SNESGetLineSearch(fas->next,&slinesearch);CHKERRQ(ierr); 2036b2b7091SBarry Smith ierr = SNESLineSearchGetPreCheck(linesearch,&precheck,&lsprectx);CHKERRQ(ierr); 2046b2b7091SBarry Smith ierr = SNESLineSearchGetPostCheck(linesearch,&postcheck,&lspostctx);CHKERRQ(ierr); 2056b2b7091SBarry Smith ierr = SNESLineSearchSetPreCheck(slinesearch,precheck,lsprectx);CHKERRQ(ierr); 2066b2b7091SBarry Smith ierr = SNESLineSearchSetPostCheck(slinesearch,postcheck,lspostctx);CHKERRQ(ierr); 207f89ba88eSPeter Brune ierr = PetscObjectCopyFortranFunctionPointers((PetscObject)linesearch, (PetscObject)slinesearch);CHKERRQ(ierr); 208ab8d36c9SPeter Brune ierr = SNESSetUp(next);CHKERRQ(ierr); 20979d9a41aSPeter Brune } 2106273346dSPeter Brune /* setup FAS work vectors */ 2116273346dSPeter Brune if (fas->galerkin) { 2126273346dSPeter Brune ierr = VecDuplicate(snes->vec_sol, &fas->Xg);CHKERRQ(ierr); 2136273346dSPeter Brune ierr = VecDuplicate(snes->vec_sol, &fas->Fg);CHKERRQ(ierr); 2146273346dSPeter Brune } 215421d9b32SPeter Brune PetscFunctionReturn(0); 216421d9b32SPeter Brune } 217421d9b32SPeter Brune 218421d9b32SPeter Brune #undef __FUNCT__ 219421d9b32SPeter Brune #define __FUNCT__ "SNESSetFromOptions_FAS" 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> 318421d9b32SPeter Brune #undef __FUNCT__ 319421d9b32SPeter Brune #define __FUNCT__ "SNESView_FAS" 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) { 334ab8d36c9SPeter Brune ierr = PetscViewerASCIIPrintf(viewer, "FAS: 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 401421d9b32SPeter Brune #undef __FUNCT__ 40291f99d7cSPeter Brune #define __FUNCT__ "SNESFASDownSmooth_Private" 40339bd7f45SPeter Brune /* 40439bd7f45SPeter Brune Defines the action of the downsmoother 40539bd7f45SPeter Brune */ 40640244768SBarry Smith static PetscErrorCode SNESFASDownSmooth_Private(SNES snes, Vec B, Vec X, Vec F, PetscReal *fnorm) 407b9c2fdf1SPeter Brune { 40839bd7f45SPeter Brune PetscErrorCode ierr = 0; 409742fe5e2SPeter Brune SNESConvergedReason reason; 410ab8d36c9SPeter Brune Vec FPC; 411ab8d36c9SPeter Brune SNES smoothd; 4120dd27c6cSPeter Brune SNES_FAS *fas = (SNES_FAS*) snes->data; 4136e111a19SKarl Rupp 414421d9b32SPeter Brune PetscFunctionBegin; 415ab8d36c9SPeter Brune ierr = SNESFASCycleGetSmootherDown(snes, &smoothd);CHKERRQ(ierr); 416e4ed7901SPeter Brune ierr = SNESSetInitialFunction(smoothd, F);CHKERRQ(ierr); 4170dd27c6cSPeter Brune if (fas->eventsmoothsolve) {ierr = PetscLogEventBegin(fas->eventsmoothsolve,0,0,0,0);CHKERRQ(ierr);} 418ab8d36c9SPeter Brune ierr = SNESSolve(smoothd, B, X);CHKERRQ(ierr); 4190dd27c6cSPeter Brune if (fas->eventsmoothsolve) {ierr = PetscLogEventEnd(fas->eventsmoothsolve,0,0,0,0);CHKERRQ(ierr);} 420742fe5e2SPeter Brune /* check convergence reason for the smoother */ 421ab8d36c9SPeter Brune ierr = SNESGetConvergedReason(smoothd,&reason);CHKERRQ(ierr); 4221ff805c3SPeter Brune if (reason < 0 && !(reason == SNES_DIVERGED_MAX_IT || reason == SNES_DIVERGED_LOCAL_MIN || reason == SNES_DIVERGED_LINE_SEARCH)) { 423742fe5e2SPeter Brune snes->reason = SNES_DIVERGED_INNER; 424742fe5e2SPeter Brune PetscFunctionReturn(0); 425742fe5e2SPeter Brune } 4260298fd71SBarry Smith ierr = SNESGetFunction(smoothd, &FPC, NULL, NULL);CHKERRQ(ierr); 4274b32a720SPeter Brune ierr = VecCopy(FPC, F);CHKERRQ(ierr); 42871dbe336SPeter Brune if (fnorm) {ierr = VecNorm(F,NORM_2,fnorm);CHKERRQ(ierr);} 42939bd7f45SPeter Brune PetscFunctionReturn(0); 43039bd7f45SPeter Brune } 43139bd7f45SPeter Brune 43239bd7f45SPeter Brune 43339bd7f45SPeter Brune #undef __FUNCT__ 43491f99d7cSPeter Brune #define __FUNCT__ "SNESFASUpSmooth_Private" 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; 4440dd27c6cSPeter Brune SNES_FAS *fas = (SNES_FAS*) snes->data; 445ab8d36c9SPeter Brune 4466e111a19SKarl Rupp PetscFunctionBegin; 447ab8d36c9SPeter Brune ierr = SNESFASCycleGetSmootherUp(snes, &smoothu);CHKERRQ(ierr); 4480dd27c6cSPeter Brune if (fas->eventsmoothsolve) {ierr = PetscLogEventBegin(fas->eventsmoothsolve,0,0,0,0);CHKERRQ(ierr);} 449ab8d36c9SPeter Brune ierr = SNESSolve(smoothu, B, X);CHKERRQ(ierr); 4500dd27c6cSPeter Brune if (fas->eventsmoothsolve) {ierr = PetscLogEventEnd(fas->eventsmoothsolve,0,0,0,0);CHKERRQ(ierr);} 45139bd7f45SPeter Brune /* check convergence reason for the smoother */ 452ab8d36c9SPeter Brune ierr = SNESGetConvergedReason(smoothu,&reason);CHKERRQ(ierr); 4531ff805c3SPeter Brune if (reason < 0 && !(reason == SNES_DIVERGED_MAX_IT || reason == SNES_DIVERGED_LOCAL_MIN || reason == SNES_DIVERGED_LINE_SEARCH)) { 45439bd7f45SPeter Brune snes->reason = SNES_DIVERGED_INNER; 45539bd7f45SPeter Brune PetscFunctionReturn(0); 45639bd7f45SPeter Brune } 4570298fd71SBarry Smith ierr = SNESGetFunction(smoothu, &FPC, NULL, NULL);CHKERRQ(ierr); 4584b32a720SPeter Brune ierr = VecCopy(FPC, F);CHKERRQ(ierr); 45971dbe336SPeter Brune if (fnorm) {ierr = VecNorm(F,NORM_2,fnorm);CHKERRQ(ierr);} 46039bd7f45SPeter Brune PetscFunctionReturn(0); 46139bd7f45SPeter Brune } 46239bd7f45SPeter Brune 46339bd7f45SPeter Brune #undef __FUNCT__ 464938e4a01SJed Brown #define __FUNCT__ "SNESFASCreateCoarseVec" 465938e4a01SJed Brown /*@ 466938e4a01SJed Brown SNESFASCreateCoarseVec - create Vec corresponding to a state vector on one level coarser than current level 467938e4a01SJed Brown 468938e4a01SJed Brown Collective 469938e4a01SJed Brown 470938e4a01SJed Brown Input Arguments: 471938e4a01SJed Brown . snes - SNESFAS 472938e4a01SJed Brown 473938e4a01SJed Brown Output Arguments: 474938e4a01SJed Brown . Xcoarse - vector on level one coarser than snes 475938e4a01SJed Brown 476938e4a01SJed Brown Level: developer 477938e4a01SJed Brown 478938e4a01SJed Brown .seealso: SNESFASSetRestriction(), SNESFASRestrict() 479938e4a01SJed Brown @*/ 480938e4a01SJed Brown PetscErrorCode SNESFASCreateCoarseVec(SNES snes,Vec *Xcoarse) 481938e4a01SJed Brown { 482938e4a01SJed Brown PetscErrorCode ierr; 483938e4a01SJed Brown SNES_FAS *fas = (SNES_FAS*)snes->data; 484938e4a01SJed Brown 485938e4a01SJed Brown PetscFunctionBegin; 4861aa26658SKarl Rupp if (fas->rscale) { 4871aa26658SKarl Rupp ierr = VecDuplicate(fas->rscale,Xcoarse);CHKERRQ(ierr); 488f5af7f23SKarl Rupp } else if (fas->inject) { 4892a7a6963SBarry Smith ierr = MatCreateVecs(fas->inject,Xcoarse,NULL);CHKERRQ(ierr); 490ce94432eSBarry Smith } else SETERRQ(PetscObjectComm((PetscObject)snes),PETSC_ERR_ARG_WRONGSTATE,"Must set restriction or injection");CHKERRQ(ierr); 491938e4a01SJed Brown PetscFunctionReturn(0); 492938e4a01SJed Brown } 493938e4a01SJed Brown 494e9923e8dSJed Brown #undef __FUNCT__ 495e9923e8dSJed Brown #define __FUNCT__ "SNESFASRestrict" 496e9923e8dSJed Brown /*@ 497e9923e8dSJed Brown SNESFASRestrict - restrict a Vec to the next coarser level 498e9923e8dSJed Brown 499e9923e8dSJed Brown Collective 500e9923e8dSJed Brown 501e9923e8dSJed Brown Input Arguments: 502e9923e8dSJed Brown + fine - SNES from which to restrict 503e9923e8dSJed Brown - Xfine - vector to restrict 504e9923e8dSJed Brown 505e9923e8dSJed Brown Output Arguments: 506e9923e8dSJed Brown . Xcoarse - result of restriction 507e9923e8dSJed Brown 508e9923e8dSJed Brown Level: developer 509e9923e8dSJed Brown 510e9923e8dSJed Brown .seealso: SNESFASSetRestriction(), SNESFASSetInjection() 511e9923e8dSJed Brown @*/ 512e9923e8dSJed Brown PetscErrorCode SNESFASRestrict(SNES fine,Vec Xfine,Vec Xcoarse) 513e9923e8dSJed Brown { 514e9923e8dSJed Brown PetscErrorCode ierr; 515e9923e8dSJed Brown SNES_FAS *fas = (SNES_FAS*)fine->data; 516e9923e8dSJed Brown 517e9923e8dSJed Brown PetscFunctionBegin; 518e9923e8dSJed Brown PetscValidHeaderSpecific(fine,SNES_CLASSID,1); 519e9923e8dSJed Brown PetscValidHeaderSpecific(Xfine,VEC_CLASSID,2); 520e9923e8dSJed Brown PetscValidHeaderSpecific(Xcoarse,VEC_CLASSID,3); 521e9923e8dSJed Brown if (fas->inject) { 522e9923e8dSJed Brown ierr = MatRestrict(fas->inject,Xfine,Xcoarse);CHKERRQ(ierr); 523e9923e8dSJed Brown } else { 524e9923e8dSJed Brown ierr = MatRestrict(fas->restrct,Xfine,Xcoarse);CHKERRQ(ierr); 525e9923e8dSJed Brown ierr = VecPointwiseMult(Xcoarse,fas->rscale,Xcoarse);CHKERRQ(ierr); 526e9923e8dSJed Brown } 527e9923e8dSJed Brown PetscFunctionReturn(0); 528e9923e8dSJed Brown } 529e9923e8dSJed Brown 530e9923e8dSJed Brown #undef __FUNCT__ 5318c40d5fbSBarry Smith #define __FUNCT__ "SNESFASCoarseCorrection" 53239bd7f45SPeter Brune /* 53339bd7f45SPeter Brune 53439bd7f45SPeter Brune Performs the FAS coarse correction as: 53539bd7f45SPeter Brune 536b5527d98SMatthew G. Knepley fine problem: F(x) = b 537b5527d98SMatthew G. Knepley coarse problem: F^c(x^c) = b^c 53839bd7f45SPeter Brune 539b5527d98SMatthew G. Knepley b^c = F^c(Rx) - R(F(x) - b) 54039bd7f45SPeter Brune 54139bd7f45SPeter Brune */ 5420adebc6cSBarry Smith PetscErrorCode SNESFASCoarseCorrection(SNES snes, Vec X, Vec F, Vec X_new) 5430adebc6cSBarry Smith { 54439bd7f45SPeter Brune PetscErrorCode ierr; 54539bd7f45SPeter Brune Vec X_c, Xo_c, F_c, B_c; 54639bd7f45SPeter Brune SNESConvergedReason reason; 547ab8d36c9SPeter Brune SNES next; 548ab8d36c9SPeter Brune Mat restrct, interpolate; 5490dd27c6cSPeter Brune SNES_FAS *fasc; 5505fd66863SKarl Rupp 55139bd7f45SPeter Brune PetscFunctionBegin; 552ab8d36c9SPeter Brune ierr = SNESFASCycleGetCorrection(snes, &next);CHKERRQ(ierr); 553ab8d36c9SPeter Brune if (next) { 5540dd27c6cSPeter Brune fasc = (SNES_FAS*)next->data; 5550dd27c6cSPeter Brune 556ab8d36c9SPeter Brune ierr = SNESFASCycleGetRestriction(snes, &restrct);CHKERRQ(ierr); 557ab8d36c9SPeter Brune ierr = SNESFASCycleGetInterpolation(snes, &interpolate);CHKERRQ(ierr); 558ab8d36c9SPeter Brune 559ab8d36c9SPeter Brune X_c = next->vec_sol; 560ab8d36c9SPeter Brune Xo_c = next->work[0]; 561ab8d36c9SPeter Brune F_c = next->vec_func; 562ab8d36c9SPeter Brune B_c = next->vec_rhs; 563efe1f98aSPeter Brune 5640dd27c6cSPeter Brune if (fasc->eventinterprestrict) {ierr = PetscLogEventBegin(fasc->eventinterprestrict,0,0,0,0);CHKERRQ(ierr);} 565938e4a01SJed Brown ierr = SNESFASRestrict(snes,X,Xo_c);CHKERRQ(ierr); 5665609cbf2SMatthew G. Knepley /* restrict the defect: R(F(x) - b) */ 567ab8d36c9SPeter Brune ierr = MatRestrict(restrct, F, B_c);CHKERRQ(ierr); 5680dd27c6cSPeter Brune if (fasc->eventinterprestrict) {ierr = PetscLogEventEnd(fasc->eventinterprestrict,0,0,0,0);CHKERRQ(ierr);} 5690dd27c6cSPeter Brune 5700dd27c6cSPeter Brune if (fasc->eventresidual) {ierr = PetscLogEventBegin(fasc->eventresidual,0,0,0,0);CHKERRQ(ierr);} 5715609cbf2SMatthew G. Knepley /* F_c = F^c(Rx) - R(F(x) - b) since the second term was sitting in next->vec_rhs */ 572ab8d36c9SPeter Brune ierr = SNESComputeFunction(next, Xo_c, F_c);CHKERRQ(ierr); 5730dd27c6cSPeter Brune if (fasc->eventresidual) {ierr = PetscLogEventEnd(fasc->eventresidual,0,0,0,0);CHKERRQ(ierr);} 5740dd27c6cSPeter Brune 5750dd27c6cSPeter Brune /* solve the coarse problem corresponding to F^c(x^c) = b^c = F^c(Rx) - R(F(x) - b) */ 576e4ed7901SPeter Brune ierr = VecCopy(B_c, X_c);CHKERRQ(ierr); 577b9c2fdf1SPeter Brune ierr = VecCopy(F_c, B_c);CHKERRQ(ierr); 578e4ed7901SPeter Brune ierr = VecCopy(X_c, F_c);CHKERRQ(ierr); 579ee78dd50SPeter Brune /* set initial guess of the coarse problem to the projected fine solution */ 580ee78dd50SPeter Brune ierr = VecCopy(Xo_c, X_c);CHKERRQ(ierr); 581c90fad12SPeter Brune 582c90fad12SPeter Brune /* recurse to the next level */ 583e4ed7901SPeter Brune ierr = SNESSetInitialFunction(next, F_c);CHKERRQ(ierr); 584ab8d36c9SPeter Brune ierr = SNESSolve(next, B_c, X_c);CHKERRQ(ierr); 585ab8d36c9SPeter Brune ierr = SNESGetConvergedReason(next,&reason);CHKERRQ(ierr); 586742fe5e2SPeter Brune if (reason < 0 && reason != SNES_DIVERGED_MAX_IT) { 587742fe5e2SPeter Brune snes->reason = SNES_DIVERGED_INNER; 588742fe5e2SPeter Brune PetscFunctionReturn(0); 589742fe5e2SPeter Brune } 590fa9694d7SPeter Brune /* correct as x <- x + I(x^c - Rx)*/ 591fa9694d7SPeter Brune ierr = VecAXPY(X_c, -1.0, Xo_c);CHKERRQ(ierr); 5920dd27c6cSPeter Brune 5930dd27c6cSPeter Brune if (fasc->eventinterprestrict) {ierr = PetscLogEventBegin(fasc->eventinterprestrict,0,0,0,0);CHKERRQ(ierr);} 594ab8d36c9SPeter Brune ierr = MatInterpolateAdd(interpolate, X_c, X, X_new);CHKERRQ(ierr); 5950dd27c6cSPeter Brune if (fasc->eventinterprestrict) {ierr = PetscLogEventEnd(fasc->eventinterprestrict,0,0,0,0);CHKERRQ(ierr);} 596293a7e31SPeter Brune } 59739bd7f45SPeter Brune PetscFunctionReturn(0); 59839bd7f45SPeter Brune } 59939bd7f45SPeter Brune 60039bd7f45SPeter Brune #undef __FUNCT__ 6012cf9d1e8SPeter Brune #define __FUNCT__ "SNESFASCycle_Additive" 60239bd7f45SPeter Brune /* 60339bd7f45SPeter Brune 60439bd7f45SPeter Brune The additive cycle looks like: 60539bd7f45SPeter Brune 60607144faaSPeter Brune xhat = x 60707144faaSPeter Brune xhat = dS(x, b) 60807144faaSPeter Brune x = coarsecorrection(xhat, b_d) 60907144faaSPeter Brune x = x + nu*(xhat - x); 61039bd7f45SPeter Brune (optional) x = uS(x, b) 61139bd7f45SPeter Brune 61239bd7f45SPeter Brune With the coarse RHS (defect correction) as below. 61339bd7f45SPeter Brune 61439bd7f45SPeter Brune */ 61540244768SBarry Smith static PetscErrorCode SNESFASCycle_Additive(SNES snes, Vec X) 6160adebc6cSBarry Smith { 61707144faaSPeter Brune Vec F, B, Xhat; 61822c1e704SPeter Brune Vec X_c, Xo_c, F_c, B_c; 61939bd7f45SPeter Brune PetscErrorCode ierr; 62007144faaSPeter Brune SNESConvergedReason reason; 62122c1e704SPeter Brune PetscReal xnorm, fnorm, ynorm; 622422a814eSBarry Smith SNESLineSearchReason lsresult; 623ab8d36c9SPeter Brune SNES next; 624ab8d36c9SPeter Brune Mat restrct, interpolate; 6250dd27c6cSPeter Brune SNES_FAS *fas = (SNES_FAS*)snes->data,*fasc; 6260dd27c6cSPeter Brune 62739bd7f45SPeter Brune PetscFunctionBegin; 628ab8d36c9SPeter Brune ierr = SNESFASCycleGetCorrection(snes, &next);CHKERRQ(ierr); 62939bd7f45SPeter Brune F = snes->vec_func; 63039bd7f45SPeter Brune B = snes->vec_rhs; 631e7f468e7SPeter Brune Xhat = snes->work[1]; 63207144faaSPeter Brune ierr = VecCopy(X, Xhat);CHKERRQ(ierr); 63307144faaSPeter Brune /* recurse first */ 634ab8d36c9SPeter Brune if (next) { 6350dd27c6cSPeter Brune fasc = (SNES_FAS*)next->data; 636ab8d36c9SPeter Brune ierr = SNESFASCycleGetRestriction(snes, &restrct);CHKERRQ(ierr); 637ab8d36c9SPeter Brune ierr = SNESFASCycleGetInterpolation(snes, &interpolate);CHKERRQ(ierr); 6380dd27c6cSPeter Brune if (fas->eventresidual) {ierr = PetscLogEventBegin(fas->eventresidual,0,0,0,0);CHKERRQ(ierr);} 63907144faaSPeter Brune ierr = SNESComputeFunction(snes, Xhat, F);CHKERRQ(ierr); 6400dd27c6cSPeter Brune if (fas->eventresidual) {ierr = PetscLogEventEnd(fas->eventresidual,0,0,0,0);CHKERRQ(ierr);} 641c2a02606SPeter Brune ierr = VecNorm(F, NORM_2, &fnorm);CHKERRQ(ierr); 642ab8d36c9SPeter Brune X_c = next->vec_sol; 643ab8d36c9SPeter Brune Xo_c = next->work[0]; 644ab8d36c9SPeter Brune F_c = next->vec_func; 645ab8d36c9SPeter Brune B_c = next->vec_rhs; 64639bd7f45SPeter Brune 647938e4a01SJed Brown ierr = SNESFASRestrict(snes,Xhat,Xo_c);CHKERRQ(ierr); 64807144faaSPeter Brune /* restrict the defect */ 649ab8d36c9SPeter Brune ierr = MatRestrict(restrct, F, B_c);CHKERRQ(ierr); 65007144faaSPeter Brune 65107144faaSPeter Brune /* solve the coarse problem corresponding to F^c(x^c) = b^c = Rb + F^c(Rx) - RF(x) */ 6520dd27c6cSPeter Brune if (fasc->eventresidual) {ierr = PetscLogEventBegin(fasc->eventresidual,0,0,0,0);CHKERRQ(ierr);} 653ab8d36c9SPeter Brune ierr = SNESComputeFunction(next, Xo_c, F_c);CHKERRQ(ierr); 6540dd27c6cSPeter Brune if (fasc->eventresidual) {ierr = PetscLogEventEnd(fasc->eventresidual,0,0,0,0);CHKERRQ(ierr);} 655e4ed7901SPeter Brune ierr = VecCopy(B_c, X_c);CHKERRQ(ierr); 656b9c2fdf1SPeter Brune ierr = VecCopy(F_c, B_c);CHKERRQ(ierr); 657e4ed7901SPeter Brune ierr = VecCopy(X_c, F_c);CHKERRQ(ierr); 65807144faaSPeter Brune /* set initial guess of the coarse problem to the projected fine solution */ 65907144faaSPeter Brune ierr = VecCopy(Xo_c, X_c);CHKERRQ(ierr); 66007144faaSPeter Brune 66107144faaSPeter Brune /* recurse */ 662e4ed7901SPeter Brune ierr = SNESSetInitialFunction(next, F_c);CHKERRQ(ierr); 663ab8d36c9SPeter Brune ierr = SNESSolve(next, B_c, X_c);CHKERRQ(ierr); 66407144faaSPeter Brune 66507144faaSPeter Brune /* smooth on this level */ 66691f99d7cSPeter Brune ierr = SNESFASDownSmooth_Private(snes, B, X, F, &fnorm);CHKERRQ(ierr); 66707144faaSPeter Brune 668ab8d36c9SPeter Brune ierr = SNESGetConvergedReason(next,&reason);CHKERRQ(ierr); 66907144faaSPeter Brune if (reason < 0 && reason != SNES_DIVERGED_MAX_IT) { 67007144faaSPeter Brune snes->reason = SNES_DIVERGED_INNER; 67107144faaSPeter Brune PetscFunctionReturn(0); 67207144faaSPeter Brune } 67307144faaSPeter Brune 67407144faaSPeter Brune /* correct as x <- x + I(x^c - Rx)*/ 675c68acad4SPeter Brune ierr = VecAYPX(X_c, -1.0, Xo_c);CHKERRQ(ierr); 676ab8d36c9SPeter Brune ierr = MatInterpolate(interpolate, X_c, Xhat);CHKERRQ(ierr); 67707144faaSPeter Brune 678ddebd997SPeter Brune /* additive correction of the coarse direction*/ 679f1c6b773SPeter Brune ierr = SNESLineSearchApply(snes->linesearch, X, F, &fnorm, Xhat);CHKERRQ(ierr); 680422a814eSBarry Smith ierr = SNESLineSearchGetReason(snes->linesearch, &lsresult);CHKERRQ(ierr); 681422a814eSBarry Smith ierr = SNESLineSearchGetNorms(snes->linesearch, &xnorm, &snes->norm, &ynorm);CHKERRQ(ierr); 682422a814eSBarry Smith if (lsresult) { 6839e764e56SPeter Brune if (++snes->numFailures >= snes->maxFailures) { 6849e764e56SPeter Brune snes->reason = SNES_DIVERGED_LINE_SEARCH; 6859e764e56SPeter Brune PetscFunctionReturn(0); 6869e764e56SPeter Brune } 6879e764e56SPeter Brune } 68807144faaSPeter Brune } else { 68991f99d7cSPeter Brune ierr = SNESFASDownSmooth_Private(snes, B, X, F, &snes->norm);CHKERRQ(ierr); 69007144faaSPeter Brune } 69139bd7f45SPeter Brune PetscFunctionReturn(0); 69239bd7f45SPeter Brune } 69339bd7f45SPeter Brune 69439bd7f45SPeter Brune #undef __FUNCT__ 6952cf9d1e8SPeter Brune #define __FUNCT__ "SNESFASCycle_Multiplicative" 69639bd7f45SPeter Brune /* 69739bd7f45SPeter Brune 69839bd7f45SPeter Brune Defines the FAS cycle as: 69939bd7f45SPeter Brune 700b5527d98SMatthew G. Knepley fine problem: F(x) = b 70139bd7f45SPeter Brune coarse problem: F^c(x) = b^c 70239bd7f45SPeter Brune 703b5527d98SMatthew G. Knepley b^c = F^c(Rx) - R(F(x) - b) 70439bd7f45SPeter Brune 70539bd7f45SPeter Brune correction: 70639bd7f45SPeter Brune 70739bd7f45SPeter Brune x = x + I(x^c - Rx) 70839bd7f45SPeter Brune 70939bd7f45SPeter Brune */ 71040244768SBarry Smith static PetscErrorCode SNESFASCycle_Multiplicative(SNES snes, Vec X) 7110adebc6cSBarry Smith { 71239bd7f45SPeter Brune 71339bd7f45SPeter Brune PetscErrorCode ierr; 71439bd7f45SPeter Brune Vec F,B; 71534d65b3cSPeter Brune SNES next; 71639bd7f45SPeter Brune 71739bd7f45SPeter Brune PetscFunctionBegin; 71839bd7f45SPeter Brune F = snes->vec_func; 71939bd7f45SPeter Brune B = snes->vec_rhs; 72039bd7f45SPeter Brune /* pre-smooth -- just update using the pre-smoother */ 72134d65b3cSPeter Brune ierr = SNESFASCycleGetCorrection(snes,&next);CHKERRQ(ierr); 72291f99d7cSPeter Brune ierr = SNESFASDownSmooth_Private(snes, B, X, F, &snes->norm);CHKERRQ(ierr); 72334d65b3cSPeter Brune if (next) { 7248c40d5fbSBarry Smith ierr = SNESFASCoarseCorrection(snes, X, F, X);CHKERRQ(ierr); 72591f99d7cSPeter Brune ierr = SNESFASUpSmooth_Private(snes, B, X, F, &snes->norm);CHKERRQ(ierr); 726fe6f9142SPeter Brune } 727fa9694d7SPeter Brune PetscFunctionReturn(0); 728421d9b32SPeter Brune } 729421d9b32SPeter Brune 730421d9b32SPeter Brune #undef __FUNCT__ 7318c94862eSPeter Brune #define __FUNCT__ "SNESFASCycleSetupPhase_Full" 73240244768SBarry Smith static PetscErrorCode SNESFASCycleSetupPhase_Full(SNES snes) 7338c94862eSPeter Brune { 7348c94862eSPeter Brune SNES next; 7358c94862eSPeter Brune SNES_FAS *fas = (SNES_FAS*)snes->data; 7368c94862eSPeter Brune PetscBool isFine; 7378c94862eSPeter Brune PetscErrorCode ierr; 7388c94862eSPeter Brune 7398c94862eSPeter Brune PetscFunctionBegin; 7408c94862eSPeter Brune /* pre-smooth -- just update using the pre-smoother */ 7418c94862eSPeter Brune ierr = SNESFASCycleIsFine(snes,&isFine);CHKERRQ(ierr); 7428c94862eSPeter Brune ierr = SNESFASCycleGetCorrection(snes,&next);CHKERRQ(ierr); 7438c94862eSPeter Brune fas->full_stage = 0; 7448c94862eSPeter Brune if (next) {ierr = SNESFASCycleSetupPhase_Full(next);CHKERRQ(ierr);} 7458c94862eSPeter Brune PetscFunctionReturn(0); 7468c94862eSPeter Brune } 7478c94862eSPeter Brune 7488c94862eSPeter Brune #undef __FUNCT__ 7498c94862eSPeter Brune #define __FUNCT__ "SNESFASCycle_Full" 75040244768SBarry Smith static PetscErrorCode SNESFASCycle_Full(SNES snes, Vec X) 7518c94862eSPeter Brune { 7528c94862eSPeter Brune PetscErrorCode ierr; 7538c94862eSPeter Brune Vec F,B; 7548c94862eSPeter Brune SNES_FAS *fas = (SNES_FAS*)snes->data; 7558c94862eSPeter Brune PetscBool isFine; 7568c94862eSPeter Brune SNES next; 7578c94862eSPeter Brune 7588c94862eSPeter Brune PetscFunctionBegin; 7598c94862eSPeter Brune F = snes->vec_func; 7608c94862eSPeter Brune B = snes->vec_rhs; 7618c94862eSPeter Brune ierr = SNESFASCycleIsFine(snes,&isFine);CHKERRQ(ierr); 7628c94862eSPeter Brune ierr = SNESFASCycleGetCorrection(snes,&next);CHKERRQ(ierr); 7638c94862eSPeter Brune 7648c94862eSPeter Brune if (isFine) { 7658c94862eSPeter Brune ierr = SNESFASCycleSetupPhase_Full(snes);CHKERRQ(ierr); 7668c94862eSPeter Brune } 7678c94862eSPeter Brune 7688c94862eSPeter Brune if (fas->full_stage == 0) { 769928e959bSPeter Brune /* downsweep */ 7708c94862eSPeter Brune if (next) { 7718c94862eSPeter Brune if (fas->level != 1) next->max_its += 1; 772928e959bSPeter Brune if (fas->full_downsweep||isFine) {ierr = SNESFASDownSmooth_Private(snes,B,X,F,&snes->norm);CHKERRQ(ierr);} 7738c94862eSPeter Brune ierr = SNESFASCoarseCorrection(snes,X,F,X);CHKERRQ(ierr); 7748c94862eSPeter Brune ierr = SNESFASUpSmooth_Private(snes,B,X,F,&snes->norm);CHKERRQ(ierr); 7758c94862eSPeter Brune if (fas->level != 1) next->max_its -= 1; 7768c94862eSPeter Brune } else { 777a3a80b83SMatthew G. Knepley /* The smoother on the coarse level is the coarse solver */ 7788c94862eSPeter Brune ierr = SNESFASDownSmooth_Private(snes,B,X,F,&snes->norm);CHKERRQ(ierr); 7798c94862eSPeter Brune } 7808c94862eSPeter Brune fas->full_stage = 1; 7818c94862eSPeter Brune } else if (fas->full_stage == 1) { 7828c94862eSPeter Brune if (snes->iter == 0) {ierr = SNESFASDownSmooth_Private(snes,B,X,F,&snes->norm);CHKERRQ(ierr);} 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 /* final v-cycle */ 7898c94862eSPeter Brune if (isFine) { 7908c94862eSPeter Brune if (next) { 7918c94862eSPeter Brune ierr = SNESFASCoarseCorrection(snes,X,F,X);CHKERRQ(ierr); 7928c94862eSPeter Brune ierr = SNESFASUpSmooth_Private(snes,B,X,F,&snes->norm);CHKERRQ(ierr); 7938c94862eSPeter Brune } 7948c94862eSPeter Brune } 7958c94862eSPeter Brune PetscFunctionReturn(0); 7968c94862eSPeter Brune } 7978c94862eSPeter Brune 7988c94862eSPeter Brune #undef __FUNCT__ 79934d65b3cSPeter Brune #define __FUNCT__ "SNESFASCycle_Kaskade" 80040244768SBarry Smith static PetscErrorCode SNESFASCycle_Kaskade(SNES snes, Vec X) 80134d65b3cSPeter Brune { 80234d65b3cSPeter Brune PetscErrorCode ierr; 80334d65b3cSPeter Brune Vec F,B; 80434d65b3cSPeter Brune SNES next; 80534d65b3cSPeter Brune 80634d65b3cSPeter Brune PetscFunctionBegin; 80734d65b3cSPeter Brune F = snes->vec_func; 80834d65b3cSPeter Brune B = snes->vec_rhs; 80934d65b3cSPeter Brune ierr = SNESFASCycleGetCorrection(snes,&next);CHKERRQ(ierr); 81034d65b3cSPeter Brune if (next) { 81134d65b3cSPeter Brune ierr = SNESFASCoarseCorrection(snes,X,F,X);CHKERRQ(ierr); 81234d65b3cSPeter Brune ierr = SNESFASUpSmooth_Private(snes,B,X,F,&snes->norm);CHKERRQ(ierr); 81334d65b3cSPeter Brune } else { 81434d65b3cSPeter Brune ierr = SNESFASDownSmooth_Private(snes,B,X,F,&snes->norm);CHKERRQ(ierr); 81534d65b3cSPeter Brune } 81634d65b3cSPeter Brune PetscFunctionReturn(0); 81734d65b3cSPeter Brune } 81834d65b3cSPeter Brune 819fffbeea8SBarry Smith PetscBool SNEScite = PETSC_FALSE; 820fffbeea8SBarry Smith const char SNESCitation[] = "@techreport{pbmkbsxt2012,\n" 821fffbeea8SBarry Smith " title = {Composing Scalable Nonlinear Algebraic Solvers},\n" 822fffbeea8SBarry Smith " author = {Peter Brune and Mathew Knepley and Barry Smith and Xuemin Tu},\n" 823fffbeea8SBarry Smith " year = 2013,\n" 824fffbeea8SBarry Smith " type = Preprint,\n" 825fffbeea8SBarry Smith " number = {ANL/MCS-P2010-0112},\n" 826fffbeea8SBarry Smith " institution = {Argonne National Laboratory}\n}\n"; 827fffbeea8SBarry Smith 82834d65b3cSPeter Brune #undef __FUNCT__ 829421d9b32SPeter Brune #define __FUNCT__ "SNESSolve_FAS" 83040244768SBarry Smith static PetscErrorCode SNESSolve_FAS(SNES snes) 831421d9b32SPeter Brune { 832fa9694d7SPeter Brune PetscErrorCode ierr; 833fe6f9142SPeter Brune PetscInt i, maxits; 834ddb5aff1SPeter Brune Vec X, F; 835fe6f9142SPeter Brune PetscReal fnorm; 836b17ce1afSJed Brown SNES_FAS *fas = (SNES_FAS*)snes->data,*ffas; 837b17ce1afSJed Brown DM dm; 838e70c42e5SPeter Brune PetscBool isFine; 839b17ce1afSJed Brown 840421d9b32SPeter Brune PetscFunctionBegin; 841c579b300SPatrick Farrell 8426c4ed002SBarry 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); 843c579b300SPatrick Farrell 844fffbeea8SBarry Smith ierr = PetscCitationsRegister(SNESCitation,&SNEScite);CHKERRQ(ierr); 845fe6f9142SPeter Brune maxits = snes->max_its; /* maximum number of iterations */ 846fe6f9142SPeter Brune snes->reason = SNES_CONVERGED_ITERATING; 847fa9694d7SPeter Brune X = snes->vec_sol; 848f5a6d4f9SBarry Smith F = snes->vec_func; 849293a7e31SPeter Brune 85018a66777SPeter Brune ierr = SNESFASCycleIsFine(snes, &isFine);CHKERRQ(ierr); 851293a7e31SPeter Brune /*norm setup */ 852e04113cfSBarry Smith ierr = PetscObjectSAWsTakeAccess((PetscObject)snes);CHKERRQ(ierr); 853fe6f9142SPeter Brune snes->iter = 0; 854fe6f9142SPeter Brune snes->norm = 0.; 855e04113cfSBarry Smith ierr = PetscObjectSAWsGrantAccess((PetscObject)snes);CHKERRQ(ierr); 856e4ed7901SPeter Brune if (!snes->vec_func_init_set) { 8570dd27c6cSPeter Brune if (fas->eventresidual) {ierr = PetscLogEventBegin(fas->eventresidual,0,0,0,0);CHKERRQ(ierr);} 858fe6f9142SPeter Brune ierr = SNESComputeFunction(snes,X,F);CHKERRQ(ierr); 8590dd27c6cSPeter Brune if (fas->eventresidual) {ierr = PetscLogEventEnd(fas->eventresidual,0,0,0,0);CHKERRQ(ierr);} 8601aa26658SKarl Rupp } else snes->vec_func_init_set = PETSC_FALSE; 861e4ed7901SPeter Brune 862fe6f9142SPeter Brune ierr = VecNorm(F, NORM_2, &fnorm);CHKERRQ(ierr); /* fnorm <- ||F|| */ 863422a814eSBarry Smith SNESCheckFunctionNorm(snes,fnorm); 864e04113cfSBarry Smith ierr = PetscObjectSAWsTakeAccess((PetscObject)snes);CHKERRQ(ierr); 865fe6f9142SPeter Brune snes->norm = fnorm; 866e04113cfSBarry Smith ierr = PetscObjectSAWsGrantAccess((PetscObject)snes);CHKERRQ(ierr); 867a71f0d7dSBarry Smith ierr = SNESLogConvergenceHistory(snes,fnorm,0);CHKERRQ(ierr); 868fe6f9142SPeter Brune ierr = SNESMonitor(snes,0,fnorm);CHKERRQ(ierr); 869fe6f9142SPeter Brune 870fe6f9142SPeter Brune /* test convergence */ 871fe6f9142SPeter Brune ierr = (*snes->ops->converged)(snes,0,0.0,0.0,fnorm,&snes->reason,snes->cnvP);CHKERRQ(ierr); 872fe6f9142SPeter Brune if (snes->reason) PetscFunctionReturn(0); 873e4ed7901SPeter Brune 874b17ce1afSJed Brown 875b9c2fdf1SPeter Brune if (isFine) { 876b9c2fdf1SPeter Brune /* propagate scale-dependent data up the hierarchy */ 877b17ce1afSJed Brown ierr = SNESGetDM(snes,&dm);CHKERRQ(ierr); 878b17ce1afSJed Brown for (ffas=fas; ffas->next; ffas=(SNES_FAS*)ffas->next->data) { 879b17ce1afSJed Brown DM dmcoarse; 880b17ce1afSJed Brown ierr = SNESGetDM(ffas->next,&dmcoarse);CHKERRQ(ierr); 881b17ce1afSJed Brown ierr = DMRestrict(dm,ffas->restrct,ffas->rscale,ffas->inject,dmcoarse);CHKERRQ(ierr); 882b17ce1afSJed Brown dm = dmcoarse; 883b17ce1afSJed Brown } 884b9c2fdf1SPeter Brune } 885b17ce1afSJed Brown 886fe6f9142SPeter Brune for (i = 0; i < maxits; i++) { 887fe6f9142SPeter Brune /* Call general purpose update function */ 888646217ecSPeter Brune 889fe6f9142SPeter Brune if (snes->ops->update) { 890fe6f9142SPeter Brune ierr = (*snes->ops->update)(snes, snes->iter);CHKERRQ(ierr); 891fe6f9142SPeter Brune } 89207144faaSPeter Brune if (fas->fastype == SNES_FAS_MULTIPLICATIVE) { 89391f99d7cSPeter Brune ierr = SNESFASCycle_Multiplicative(snes, X);CHKERRQ(ierr); 8948c94862eSPeter Brune } else if (fas->fastype == SNES_FAS_ADDITIVE) { 89591f99d7cSPeter Brune ierr = SNESFASCycle_Additive(snes, X);CHKERRQ(ierr); 8968c94862eSPeter Brune } else if (fas->fastype == SNES_FAS_FULL) { 8978c94862eSPeter Brune ierr = SNESFASCycle_Full(snes, X);CHKERRQ(ierr); 89834d65b3cSPeter Brune } else if (fas->fastype ==SNES_FAS_KASKADE) { 89934d65b3cSPeter Brune ierr = SNESFASCycle_Kaskade(snes, X);CHKERRQ(ierr); 9006c4ed002SBarry Smith } else SETERRQ(PetscObjectComm((PetscObject)snes),PETSC_ERR_ARG_WRONGSTATE,"Unsupported FAS type"); 901742fe5e2SPeter Brune 902742fe5e2SPeter Brune /* check for FAS cycle divergence */ 9031aa26658SKarl Rupp if (snes->reason != SNES_CONVERGED_ITERATING) PetscFunctionReturn(0); 904b9c2fdf1SPeter Brune 905c90fad12SPeter Brune /* Monitor convergence */ 906e04113cfSBarry Smith ierr = PetscObjectSAWsTakeAccess((PetscObject)snes);CHKERRQ(ierr); 907c90fad12SPeter Brune snes->iter = i+1; 908e04113cfSBarry Smith ierr = PetscObjectSAWsGrantAccess((PetscObject)snes);CHKERRQ(ierr); 909a71f0d7dSBarry Smith ierr = SNESLogConvergenceHistory(snes,snes->norm,0);CHKERRQ(ierr); 910c90fad12SPeter Brune ierr = SNESMonitor(snes,snes->iter,snes->norm);CHKERRQ(ierr); 911c90fad12SPeter Brune /* Test for convergence */ 91266585501SPeter Brune if (isFine) { 913b9c2fdf1SPeter Brune ierr = (*snes->ops->converged)(snes,snes->iter,0.0,0.0,snes->norm,&snes->reason,snes->cnvP);CHKERRQ(ierr); 914c90fad12SPeter Brune if (snes->reason) break; 915fe6f9142SPeter Brune } 91666585501SPeter Brune } 917fe6f9142SPeter Brune if (i == maxits) { 918fe6f9142SPeter Brune ierr = PetscInfo1(snes, "Maximum number of iterations has been reached: %D\n", maxits);CHKERRQ(ierr); 919fe6f9142SPeter Brune if (!snes->reason) snes->reason = SNES_DIVERGED_MAX_IT; 920fe6f9142SPeter Brune } 921421d9b32SPeter Brune PetscFunctionReturn(0); 922421d9b32SPeter Brune } 92340244768SBarry Smith 92440244768SBarry Smith /*MC 92540244768SBarry Smith 92640244768SBarry Smith SNESFAS - Full Approximation Scheme nonlinear multigrid solver. 92740244768SBarry Smith 92840244768SBarry Smith The nonlinear problem is solved by correction using coarse versions 92940244768SBarry Smith of the nonlinear problem. This problem is perturbed so that a projected 93040244768SBarry Smith solution of the fine problem elicits no correction from the coarse problem. 93140244768SBarry Smith 93240244768SBarry Smith Options Database: 93340244768SBarry Smith + -snes_fas_levels - The number of levels 93440244768SBarry Smith . -snes_fas_cycles<1> - The number of cycles -- 1 for V, 2 for W 93540244768SBarry Smith . -snes_fas_type<additive,multiplicative,full,kaskade> - Additive or multiplicative cycle 93640244768SBarry Smith . -snes_fas_galerkin<PETSC_FALSE> - Form coarse problems by projection back upon the fine problem 93740244768SBarry Smith . -snes_fas_smoothup<1> - The number of iterations of the post-smoother 93840244768SBarry Smith . -snes_fas_smoothdown<1> - The number of iterations of the pre-smoother 93940244768SBarry Smith . -snes_fas_monitor - Monitor progress of all of the levels 94040244768SBarry Smith . -snes_fas_full_downsweep<PETSC_FALSE> - call the downsmooth on the initial downsweep of full FAS 94140244768SBarry Smith . -fas_levels_snes_ - SNES options for all smoothers 94240244768SBarry Smith . -fas_levels_cycle_snes_ - SNES options for all cycles 94340244768SBarry Smith . -fas_levels_i_snes_ - SNES options for the smoothers on level i 94440244768SBarry Smith . -fas_levels_i_cycle_snes_ - SNES options for the cycle on level i 94540244768SBarry Smith - -fas_coarse_snes_ - SNES options for the coarsest smoother 94640244768SBarry Smith 94740244768SBarry Smith Notes: 94840244768SBarry Smith The organization of the FAS solver is slightly different from the organization of PCMG 94940244768SBarry Smith As each level has smoother SNES instances(down and potentially up) and a cycle SNES instance. 95040244768SBarry Smith The cycle SNES instance may be used for monitoring convergence on a particular level. 95140244768SBarry Smith 95240244768SBarry Smith Level: beginner 95340244768SBarry Smith 95440244768SBarry Smith References: 95540244768SBarry Smith . 1. - Peter R. Brune, Matthew G. Knepley, Barry F. Smith, and Xuemin Tu, "Composing Scalable Nonlinear Algebraic Solvers", 95640244768SBarry Smith SIAM Review, 57(4), 2015 95740244768SBarry Smith 95840244768SBarry Smith .seealso: PCMG, SNESCreate(), SNES, SNESSetType(), SNESType (for list of available types) 95940244768SBarry Smith M*/ 96040244768SBarry Smith 96140244768SBarry Smith #undef __FUNCT__ 96240244768SBarry Smith #define __FUNCT__ "SNESCreate_FAS" 96340244768SBarry Smith PETSC_EXTERN PetscErrorCode SNESCreate_FAS(SNES snes) 96440244768SBarry Smith { 96540244768SBarry Smith SNES_FAS *fas; 96640244768SBarry Smith PetscErrorCode ierr; 96740244768SBarry Smith 96840244768SBarry Smith PetscFunctionBegin; 96940244768SBarry Smith snes->ops->destroy = SNESDestroy_FAS; 97040244768SBarry Smith snes->ops->setup = SNESSetUp_FAS; 97140244768SBarry Smith snes->ops->setfromoptions = SNESSetFromOptions_FAS; 97240244768SBarry Smith snes->ops->view = SNESView_FAS; 97340244768SBarry Smith snes->ops->solve = SNESSolve_FAS; 97440244768SBarry Smith snes->ops->reset = SNESReset_FAS; 97540244768SBarry Smith 97640244768SBarry Smith snes->usesksp = PETSC_FALSE; 97740244768SBarry Smith snes->usespc = PETSC_FALSE; 97840244768SBarry Smith 97940244768SBarry Smith if (!snes->tolerancesset) { 98040244768SBarry Smith snes->max_funcs = 30000; 98140244768SBarry Smith snes->max_its = 10000; 98240244768SBarry Smith } 98340244768SBarry Smith 984*4fc747eaSLawrence Mitchell snes->alwayscomputesfinalresidual = PETSC_TRUE; 985*4fc747eaSLawrence Mitchell 98640244768SBarry Smith ierr = PetscNewLog(snes,&fas);CHKERRQ(ierr); 98740244768SBarry Smith 98840244768SBarry Smith snes->data = (void*) fas; 98940244768SBarry Smith fas->level = 0; 99040244768SBarry Smith fas->levels = 1; 99140244768SBarry Smith fas->n_cycles = 1; 99240244768SBarry Smith fas->max_up_it = 1; 99340244768SBarry Smith fas->max_down_it = 1; 99440244768SBarry Smith fas->smoothu = NULL; 99540244768SBarry Smith fas->smoothd = NULL; 99640244768SBarry Smith fas->next = NULL; 99740244768SBarry Smith fas->previous = NULL; 99840244768SBarry Smith fas->fine = snes; 99940244768SBarry Smith fas->interpolate = NULL; 100040244768SBarry Smith fas->restrct = NULL; 100140244768SBarry Smith fas->inject = NULL; 100240244768SBarry Smith fas->usedmfornumberoflevels = PETSC_FALSE; 100340244768SBarry Smith fas->fastype = SNES_FAS_MULTIPLICATIVE; 100440244768SBarry Smith fas->full_downsweep = PETSC_FALSE; 100540244768SBarry Smith 100640244768SBarry Smith fas->eventsmoothsetup = 0; 100740244768SBarry Smith fas->eventsmoothsolve = 0; 100840244768SBarry Smith fas->eventresidual = 0; 100940244768SBarry Smith fas->eventinterprestrict = 0; 101040244768SBarry Smith PetscFunctionReturn(0); 101140244768SBarry Smith } 1012