xref: /petsc/src/snes/impls/fas/fas.c (revision 217044c2fa7ae23423a3a4756ec431a235346ff3)
1421d9b32SPeter Brune /* Defines the basic SNES object */
2a055c8caSBarry Smith #include <../src/snes/impls/fas/fasimpls.h>    /*I  "petscsnes.h"  I*/
3421d9b32SPeter Brune 
434d65b3cSPeter Brune const char *const SNESFASTypes[] = {"MULTIPLICATIVE","ADDITIVE","FULL","KASKADE","SNESFASType","SNES_FAS",0};
507144faaSPeter Brune 
66273346dSPeter Brune extern PetscErrorCode SNESFASGalerkinDefaultFunction(SNES,Vec,Vec,void*);
7efe1f98aSPeter Brune 
840244768SBarry Smith static PetscErrorCode SNESReset_FAS(SNES snes)
9421d9b32SPeter Brune {
1077df8cc4SPeter Brune   PetscErrorCode ierr  = 0;
11421d9b32SPeter Brune   SNES_FAS       * fas = (SNES_FAS*)snes->data;
12421d9b32SPeter Brune 
13421d9b32SPeter Brune   PetscFunctionBegin;
14ab8d36c9SPeter Brune   ierr = SNESDestroy(&fas->smoothu);CHKERRQ(ierr);
15ab8d36c9SPeter Brune   ierr = SNESDestroy(&fas->smoothd);CHKERRQ(ierr);
163dccd265SPeter Brune   ierr = MatDestroy(&fas->inject);CHKERRQ(ierr);
17bccf9bb3SJed Brown   ierr = MatDestroy(&fas->interpolate);CHKERRQ(ierr);
18bccf9bb3SJed Brown   ierr = MatDestroy(&fas->restrct);CHKERRQ(ierr);
19bccf9bb3SJed Brown   ierr = VecDestroy(&fas->rscale);CHKERRQ(ierr);
207cd33a7bSPeter Brune   if (fas->galerkin) {
217cd33a7bSPeter Brune     ierr = VecDestroy(&fas->Xg);CHKERRQ(ierr);
227cd33a7bSPeter Brune     ierr = VecDestroy(&fas->Fg);CHKERRQ(ierr);
237cd33a7bSPeter Brune   }
24d477d801SPeter Brune   if (fas->next) {ierr = SNESReset(fas->next);CHKERRQ(ierr);}
25421d9b32SPeter Brune   PetscFunctionReturn(0);
26421d9b32SPeter Brune }
27421d9b32SPeter Brune 
2840244768SBarry Smith static PetscErrorCode SNESDestroy_FAS(SNES snes)
29421d9b32SPeter Brune {
30421d9b32SPeter Brune   SNES_FAS       * fas = (SNES_FAS*)snes->data;
31742fe5e2SPeter Brune   PetscErrorCode ierr  = 0;
32421d9b32SPeter Brune 
33421d9b32SPeter Brune   PetscFunctionBegin;
34421d9b32SPeter Brune   /* recursively resets and then destroys */
3579d9a41aSPeter Brune   ierr = SNESReset(snes);CHKERRQ(ierr);
361aa26658SKarl Rupp   if (fas->next) {
371aa26658SKarl Rupp     ierr = SNESDestroy(&fas->next);CHKERRQ(ierr);
381aa26658SKarl Rupp   }
39421d9b32SPeter Brune   ierr = PetscFree(fas);CHKERRQ(ierr);
40421d9b32SPeter Brune   PetscFunctionReturn(0);
41421d9b32SPeter Brune }
42421d9b32SPeter Brune 
4340244768SBarry Smith static PetscErrorCode SNESSetUp_FAS(SNES snes)
44421d9b32SPeter Brune {
4548bfdf8aSPeter Brune   SNES_FAS       *fas = (SNES_FAS*) snes->data;
46421d9b32SPeter Brune   PetscErrorCode ierr;
47d1adcc6fSPeter Brune   PetscInt       dm_levels;
483dccd265SPeter Brune   Vec            vec_sol, vec_func, vec_sol_update, vec_rhs; /* preserve these if they're set through the reset */
49ab8d36c9SPeter Brune   SNES           next;
500a7266b2SPatrick Farrell   PetscBool      isFine, hasCreateRestriction;
51f89ba88eSPeter Brune   SNESLineSearch linesearch;
52f89ba88eSPeter Brune   SNESLineSearch slinesearch;
53f89ba88eSPeter Brune   void           *lsprectx,*lspostctx;
546b2b7091SBarry Smith   PetscErrorCode (*precheck)(SNESLineSearch,Vec,Vec,PetscBool*,void*);
556b2b7091SBarry Smith   PetscErrorCode (*postcheck)(SNESLineSearch,Vec,Vec,Vec,PetscBool*,PetscBool*,void*);
56eff52c0eSPeter Brune 
576b2b7091SBarry Smith   PetscFunctionBegin;
58ab8d36c9SPeter Brune   ierr = SNESFASCycleIsFine(snes, &isFine);CHKERRQ(ierr);
59ab8d36c9SPeter Brune   if (fas->usedmfornumberoflevels && isFine) {
60d1adcc6fSPeter Brune     ierr = DMGetRefineLevel(snes->dm,&dm_levels);CHKERRQ(ierr);
61d1adcc6fSPeter Brune     dm_levels++;
62cc05f883SPeter Brune     if (dm_levels > fas->levels) {
632e8ce248SJed Brown       /* we don't want the solution and func vectors to be destroyed in the SNESReset when it's called in SNESFASSetLevels_FAS*/
643dccd265SPeter Brune       vec_sol              = snes->vec_sol;
653dccd265SPeter Brune       vec_func             = snes->vec_func;
663dccd265SPeter Brune       vec_sol_update       = snes->vec_sol_update;
673dccd265SPeter Brune       vec_rhs              = snes->vec_rhs;
680298fd71SBarry Smith       snes->vec_sol        = NULL;
690298fd71SBarry Smith       snes->vec_func       = NULL;
700298fd71SBarry Smith       snes->vec_sol_update = NULL;
710298fd71SBarry Smith       snes->vec_rhs        = NULL;
723dccd265SPeter Brune 
733dccd265SPeter Brune       /* reset the number of levels */
740298fd71SBarry Smith       ierr = SNESFASSetLevels(snes,dm_levels,NULL);CHKERRQ(ierr);
75cc05f883SPeter Brune       ierr = SNESSetFromOptions(snes);CHKERRQ(ierr);
763dccd265SPeter Brune 
773dccd265SPeter Brune       snes->vec_sol        = vec_sol;
783dccd265SPeter Brune       snes->vec_func       = vec_func;
793dccd265SPeter Brune       snes->vec_rhs        = vec_rhs;
803dccd265SPeter Brune       snes->vec_sol_update = vec_sol_update;
81d1adcc6fSPeter Brune     }
82d1adcc6fSPeter Brune   }
83ab8d36c9SPeter Brune   ierr = SNESFASCycleGetCorrection(snes, &next);CHKERRQ(ierr);
84ab8d36c9SPeter Brune   if (!isFine) snes->gridsequence = 0; /* no grid sequencing inside the multigrid hierarchy! */
853dccd265SPeter Brune 
86fa0ddf94SBarry Smith   ierr = SNESSetWorkVecs(snes, 2);CHKERRQ(ierr); /* work vectors used for intergrid transfers */
87cc05f883SPeter Brune 
88ab8d36c9SPeter Brune   /* set up the smoothers if they haven't already been set up */
89ab8d36c9SPeter Brune   if (!fas->smoothd) {
90ab8d36c9SPeter Brune     ierr = SNESFASCycleCreateSmoother_Private(snes, &fas->smoothd);CHKERRQ(ierr);
91ab8d36c9SPeter Brune   }
92ab8d36c9SPeter Brune 
9379d9a41aSPeter Brune   if (snes->dm) {
94ab8d36c9SPeter Brune     /* set the smoother DMs properly */
95ab8d36c9SPeter Brune     if (fas->smoothu) ierr = SNESSetDM(fas->smoothu, snes->dm);CHKERRQ(ierr);
96ab8d36c9SPeter Brune     ierr = SNESSetDM(fas->smoothd, snes->dm);CHKERRQ(ierr);
9779d9a41aSPeter Brune     /* construct EVERYTHING from the DM -- including the progressive set of smoothers */
98ab8d36c9SPeter Brune     if (next) {
9979d9a41aSPeter Brune       /* for now -- assume the DM and the evaluation functions have been set externally */
100ab8d36c9SPeter Brune       if (!next->dm) {
101ce94432eSBarry Smith         ierr = DMCoarsen(snes->dm, PetscObjectComm((PetscObject)next), &next->dm);CHKERRQ(ierr);
102ab8d36c9SPeter Brune         ierr = SNESSetDM(next, next->dm);CHKERRQ(ierr);
10379d9a41aSPeter Brune       }
10479d9a41aSPeter Brune       /* set the interpolation and restriction from the DM */
10579d9a41aSPeter Brune       if (!fas->interpolate) {
106ab8d36c9SPeter Brune         ierr = DMCreateInterpolation(next->dm, snes->dm, &fas->interpolate, &fas->rscale);CHKERRQ(ierr);
107bccf9bb3SJed Brown         if (!fas->restrct) {
1080a7266b2SPatrick Farrell           ierr = DMHasCreateRestriction(next->dm, &hasCreateRestriction);CHKERRQ(ierr);
1090a7266b2SPatrick Farrell           /* DM can create restrictions, use that */
1100a7266b2SPatrick Farrell           if (hasCreateRestriction) {
1110a7266b2SPatrick Farrell             ierr = DMCreateRestriction(next->dm, snes->dm, &fas->restrct);CHKERRQ(ierr);
1120a7266b2SPatrick Farrell           } else {
113bccf9bb3SJed Brown             ierr         = PetscObjectReference((PetscObject)fas->interpolate);CHKERRQ(ierr);
11479d9a41aSPeter Brune             fas->restrct = fas->interpolate;
11579d9a41aSPeter Brune           }
116bccf9bb3SJed Brown         }
1170a7266b2SPatrick Farrell       }
11879d9a41aSPeter Brune       /* set the injection from the DM */
11979d9a41aSPeter Brune       if (!fas->inject) {
12023e68893SLawrence Mitchell         PetscBool flg;
12123e68893SLawrence Mitchell         ierr = DMHasCreateInjection(next->dm, &flg);CHKERRQ(ierr);
12223e68893SLawrence Mitchell         if (flg) {
1236dbf9973SLawrence Mitchell           ierr = DMCreateInjection(next->dm, snes->dm, &fas->inject);CHKERRQ(ierr);
12479d9a41aSPeter Brune         }
12579d9a41aSPeter Brune       }
12679d9a41aSPeter Brune     }
12723e68893SLawrence Mitchell   }
12879d9a41aSPeter Brune   /*pass the smoother, function, and jacobian up to the next level if it's not user set already */
12979d9a41aSPeter Brune   if (fas->galerkin) {
1301aa26658SKarl Rupp     if (next) {
1310298fd71SBarry Smith       ierr = SNESSetFunction(next, NULL, SNESFASGalerkinDefaultFunction, next);CHKERRQ(ierr);
1321aa26658SKarl Rupp     }
1331aa26658SKarl Rupp     if (fas->smoothd && fas->level != fas->levels - 1) {
1340298fd71SBarry Smith       ierr = SNESSetFunction(fas->smoothd, NULL, SNESFASGalerkinDefaultFunction, snes);CHKERRQ(ierr);
1351aa26658SKarl Rupp     }
1361aa26658SKarl Rupp     if (fas->smoothu && fas->level != fas->levels - 1) {
1370298fd71SBarry Smith       ierr = SNESSetFunction(fas->smoothu, NULL, SNESFASGalerkinDefaultFunction, snes);CHKERRQ(ierr);
1381aa26658SKarl Rupp     }
13979d9a41aSPeter Brune   }
14079d9a41aSPeter Brune 
141534ebe21SPeter Brune   /* sets the down (pre) smoother's default norm and sets it from options */
142534ebe21SPeter Brune   if (fas->smoothd) {
143bc3f2f05SPeter Brune     if (fas->level == 0 && fas->levels != 1) {
144365a6726SPeter Brune       ierr = SNESSetNormSchedule(fas->smoothd, SNES_NORM_NONE);CHKERRQ(ierr);
145534ebe21SPeter Brune     } else {
146365a6726SPeter Brune       ierr = SNESSetNormSchedule(fas->smoothd, SNES_NORM_FINAL_ONLY);CHKERRQ(ierr);
147534ebe21SPeter Brune     }
1487fce8c19SPeter Brune     ierr = PetscObjectCopyFortranFunctionPointers((PetscObject)snes, (PetscObject)fas->smoothd);CHKERRQ(ierr);
149534ebe21SPeter Brune     ierr = SNESSetFromOptions(fas->smoothd);CHKERRQ(ierr);
1507601faf0SJed Brown     ierr = SNESGetLineSearch(snes,&linesearch);CHKERRQ(ierr);
1517601faf0SJed Brown     ierr = SNESGetLineSearch(fas->smoothd,&slinesearch);CHKERRQ(ierr);
1526b2b7091SBarry Smith     ierr = SNESLineSearchGetPreCheck(linesearch,&precheck,&lsprectx);CHKERRQ(ierr);
1536b2b7091SBarry Smith     ierr = SNESLineSearchGetPostCheck(linesearch,&postcheck,&lspostctx);CHKERRQ(ierr);
1546b2b7091SBarry Smith     ierr = SNESLineSearchSetPreCheck(slinesearch,precheck,lsprectx);CHKERRQ(ierr);
1556b2b7091SBarry Smith     ierr = SNESLineSearchSetPostCheck(slinesearch,postcheck,lspostctx);CHKERRQ(ierr);
156f89ba88eSPeter Brune     ierr = PetscObjectCopyFortranFunctionPointers((PetscObject)linesearch, (PetscObject)slinesearch);CHKERRQ(ierr);
1570dd27c6cSPeter Brune 
1580dd27c6cSPeter Brune     fas->smoothd->vec_sol        = snes->vec_sol;
1590dd27c6cSPeter Brune     ierr                         = PetscObjectReference((PetscObject)snes->vec_sol);CHKERRQ(ierr);
1600dd27c6cSPeter Brune     fas->smoothd->vec_sol_update = snes->vec_sol_update;
1610dd27c6cSPeter Brune     ierr                         = PetscObjectReference((PetscObject)snes->vec_sol_update);CHKERRQ(ierr);
1620dd27c6cSPeter Brune     fas->smoothd->vec_func       = snes->vec_func;
1630dd27c6cSPeter Brune     ierr                         = PetscObjectReference((PetscObject)snes->vec_func);CHKERRQ(ierr);
1640dd27c6cSPeter Brune 
165*217044c2SLisandro Dalcin     if (fas->eventsmoothsetup) {ierr = PetscLogEventBegin(fas->eventsmoothsetup,fas->smoothd,0,0,0);CHKERRQ(ierr);}
1660dd27c6cSPeter Brune     ierr = SNESSetUp(fas->smoothd);CHKERRQ(ierr);
167*217044c2SLisandro Dalcin     if (fas->eventsmoothsetup) {ierr = PetscLogEventEnd(fas->eventsmoothsetup,fas->smoothd,0,0,0);CHKERRQ(ierr);}
168534ebe21SPeter Brune   }
169534ebe21SPeter Brune 
170534ebe21SPeter Brune   /* sets the up (post) smoother's default norm and sets it from options */
171534ebe21SPeter Brune   if (fas->smoothu) {
172534ebe21SPeter Brune     if (fas->level != fas->levels - 1) {
173365a6726SPeter Brune       ierr = SNESSetNormSchedule(fas->smoothu, SNES_NORM_NONE);CHKERRQ(ierr);
174534ebe21SPeter Brune     } else {
175365a6726SPeter Brune       ierr = SNESSetNormSchedule(fas->smoothu, SNES_NORM_FINAL_ONLY);CHKERRQ(ierr);
176534ebe21SPeter Brune     }
1777fce8c19SPeter Brune     ierr = PetscObjectCopyFortranFunctionPointers((PetscObject)snes, (PetscObject)fas->smoothu);CHKERRQ(ierr);
178534ebe21SPeter Brune     ierr = SNESSetFromOptions(fas->smoothu);CHKERRQ(ierr);
1797601faf0SJed Brown     ierr = SNESGetLineSearch(snes,&linesearch);CHKERRQ(ierr);
1807601faf0SJed Brown     ierr = SNESGetLineSearch(fas->smoothu,&slinesearch);CHKERRQ(ierr);
1816b2b7091SBarry Smith     ierr = SNESLineSearchGetPreCheck(linesearch,&precheck,&lsprectx);CHKERRQ(ierr);
1826b2b7091SBarry Smith     ierr = SNESLineSearchGetPostCheck(linesearch,&postcheck,&lspostctx);CHKERRQ(ierr);
1836b2b7091SBarry Smith     ierr = SNESLineSearchSetPreCheck(slinesearch,precheck,lsprectx);CHKERRQ(ierr);
1846b2b7091SBarry Smith     ierr = SNESLineSearchSetPostCheck(slinesearch,postcheck,lspostctx);CHKERRQ(ierr);
185f89ba88eSPeter Brune     ierr = PetscObjectCopyFortranFunctionPointers((PetscObject)linesearch, (PetscObject)slinesearch);CHKERRQ(ierr);
1860dd27c6cSPeter Brune 
1870dd27c6cSPeter Brune     fas->smoothu->vec_sol        = snes->vec_sol;
1880dd27c6cSPeter Brune     ierr                         = PetscObjectReference((PetscObject)snes->vec_sol);CHKERRQ(ierr);
1890dd27c6cSPeter Brune     fas->smoothu->vec_sol_update = snes->vec_sol_update;
1900dd27c6cSPeter Brune     ierr                         = PetscObjectReference((PetscObject)snes->vec_sol_update);CHKERRQ(ierr);
1910dd27c6cSPeter Brune     fas->smoothu->vec_func       = snes->vec_func;
1920dd27c6cSPeter Brune     ierr                         = PetscObjectReference((PetscObject)snes->vec_func);CHKERRQ(ierr);
1930dd27c6cSPeter Brune 
194*217044c2SLisandro Dalcin     if (fas->eventsmoothsetup) {ierr = PetscLogEventBegin(fas->eventsmoothsetup,fas->smoothu,0,0,0);CHKERRQ(ierr);}
1950dd27c6cSPeter Brune     ierr = SNESSetUp(fas->smoothu);CHKERRQ(ierr);
196*217044c2SLisandro Dalcin     if (fas->eventsmoothsetup) {ierr = PetscLogEventEnd(fas->eventsmoothsetup,fas->smoothu,0,0,0);CHKERRQ(ierr);}
1970dd27c6cSPeter Brune 
198534ebe21SPeter Brune   }
199d06165b7SPeter Brune 
200ab8d36c9SPeter Brune   if (next) {
20179d9a41aSPeter Brune     /* gotta set up the solution vector for this to work */
202ab8d36c9SPeter Brune     if (!next->vec_sol) {ierr = SNESFASCreateCoarseVec(snes,&next->vec_sol);CHKERRQ(ierr);}
203ab8d36c9SPeter Brune     if (!next->vec_rhs) {ierr = SNESFASCreateCoarseVec(snes,&next->vec_rhs);CHKERRQ(ierr);}
2047fce8c19SPeter Brune     ierr = PetscObjectCopyFortranFunctionPointers((PetscObject)snes, (PetscObject)next);CHKERRQ(ierr);
2057601faf0SJed Brown     ierr = SNESGetLineSearch(snes,&linesearch);CHKERRQ(ierr);
2067601faf0SJed Brown     ierr = SNESGetLineSearch(fas->next,&slinesearch);CHKERRQ(ierr);
2076b2b7091SBarry Smith     ierr = SNESLineSearchGetPreCheck(linesearch,&precheck,&lsprectx);CHKERRQ(ierr);
2086b2b7091SBarry Smith     ierr = SNESLineSearchGetPostCheck(linesearch,&postcheck,&lspostctx);CHKERRQ(ierr);
2096b2b7091SBarry Smith     ierr = SNESLineSearchSetPreCheck(slinesearch,precheck,lsprectx);CHKERRQ(ierr);
2106b2b7091SBarry Smith     ierr = SNESLineSearchSetPostCheck(slinesearch,postcheck,lspostctx);CHKERRQ(ierr);
211f89ba88eSPeter Brune     ierr = PetscObjectCopyFortranFunctionPointers((PetscObject)linesearch, (PetscObject)slinesearch);CHKERRQ(ierr);
212ab8d36c9SPeter Brune     ierr = SNESSetUp(next);CHKERRQ(ierr);
21379d9a41aSPeter Brune   }
2146273346dSPeter Brune   /* setup FAS work vectors */
2156273346dSPeter Brune   if (fas->galerkin) {
2166273346dSPeter Brune     ierr = VecDuplicate(snes->vec_sol, &fas->Xg);CHKERRQ(ierr);
2176273346dSPeter Brune     ierr = VecDuplicate(snes->vec_sol, &fas->Fg);CHKERRQ(ierr);
2186273346dSPeter Brune   }
219421d9b32SPeter Brune   PetscFunctionReturn(0);
220421d9b32SPeter Brune }
221421d9b32SPeter Brune 
22240244768SBarry Smith static PetscErrorCode SNESSetFromOptions_FAS(PetscOptionItems *PetscOptionsObject,SNES snes)
223421d9b32SPeter Brune {
224ee78dd50SPeter Brune   SNES_FAS       *fas   = (SNES_FAS*) snes->data;
225ee78dd50SPeter Brune   PetscInt       levels = 1;
22687f44e3fSPeter Brune   PetscBool      flg    = PETSC_FALSE, upflg = PETSC_FALSE, downflg = PETSC_FALSE, monflg = PETSC_FALSE, galerkinflg = PETSC_FALSE,continuationflg = PETSC_FALSE;
227421d9b32SPeter Brune   PetscErrorCode ierr;
22807144faaSPeter Brune   SNESFASType    fastype;
229fde0ff24SPeter Brune   const char     *optionsprefix;
230f1c6b773SPeter Brune   SNESLineSearch linesearch;
23166585501SPeter Brune   PetscInt       m, n_up, n_down;
232ab8d36c9SPeter Brune   SNES           next;
233ab8d36c9SPeter Brune   PetscBool      isFine;
234421d9b32SPeter Brune 
235421d9b32SPeter Brune   PetscFunctionBegin;
236ab8d36c9SPeter Brune   ierr = SNESFASCycleIsFine(snes, &isFine);CHKERRQ(ierr);
237e55864a3SBarry Smith   ierr = PetscOptionsHead(PetscOptionsObject,"SNESFAS Options-----------------------------------");CHKERRQ(ierr);
238ee78dd50SPeter Brune 
239ab8d36c9SPeter Brune   /* number of levels -- only process most options on the finest level */
240ab8d36c9SPeter Brune   if (isFine) {
241ee78dd50SPeter Brune     ierr = PetscOptionsInt("-snes_fas_levels", "Number of Levels", "SNESFASSetLevels", levels, &levels, &flg);CHKERRQ(ierr);
242c732cbdbSBarry Smith     if (!flg && snes->dm) {
243c732cbdbSBarry Smith       ierr = DMGetRefineLevel(snes->dm,&levels);CHKERRQ(ierr);
244c732cbdbSBarry Smith       levels++;
245d1adcc6fSPeter Brune       fas->usedmfornumberoflevels = PETSC_TRUE;
246c732cbdbSBarry Smith     }
2470298fd71SBarry Smith     ierr    = SNESFASSetLevels(snes, levels, NULL);CHKERRQ(ierr);
24807144faaSPeter Brune     fastype = fas->fastype;
24907144faaSPeter Brune     ierr    = PetscOptionsEnum("-snes_fas_type","FAS correction type","SNESFASSetType",SNESFASTypes,(PetscEnum)fastype,(PetscEnum*)&fastype,&flg);CHKERRQ(ierr);
25007144faaSPeter Brune     if (flg) {
25107144faaSPeter Brune       ierr = SNESFASSetType(snes, fastype);CHKERRQ(ierr);
25207144faaSPeter Brune     }
253ee78dd50SPeter Brune 
254fde0ff24SPeter Brune     ierr = SNESGetOptionsPrefix(snes, &optionsprefix);CHKERRQ(ierr);
255ab8d36c9SPeter Brune     ierr = PetscOptionsInt("-snes_fas_cycles","Number of cycles","SNESFASSetCycles",fas->n_cycles,&m,&flg);CHKERRQ(ierr);
256ab8d36c9SPeter Brune     if (flg) {
257ab8d36c9SPeter Brune       ierr = SNESFASSetCycles(snes, m);CHKERRQ(ierr);
258fde0ff24SPeter Brune     }
25987f44e3fSPeter Brune     ierr = PetscOptionsBool("-snes_fas_continuation","Corrected grid-sequence continuation","SNESFASSetContinuation",fas->continuation,&continuationflg,&flg);CHKERRQ(ierr);
26087f44e3fSPeter Brune     if (flg) {
26187f44e3fSPeter Brune       ierr = SNESFASSetContinuation(snes,continuationflg);CHKERRQ(ierr);
26287f44e3fSPeter Brune     }
263fde0ff24SPeter Brune 
264ab8d36c9SPeter Brune     ierr = PetscOptionsBool("-snes_fas_galerkin", "Form coarse problems with Galerkin","SNESFASSetGalerkin",fas->galerkin,&galerkinflg,&flg);CHKERRQ(ierr);
265ab8d36c9SPeter Brune     if (flg) {
266ab8d36c9SPeter Brune       ierr = SNESFASSetGalerkin(snes, galerkinflg);CHKERRQ(ierr);
267ab8d36c9SPeter Brune     }
268ee78dd50SPeter Brune 
269928e959bSPeter Brune     if (fas->fastype == SNES_FAS_FULL) {
270928e959bSPeter Brune       ierr   = PetscOptionsBool("-snes_fas_full_downsweep","Smooth on the initial upsweep for full FAS cycles","SNESFASFullSetDownSweep",fas->full_downsweep,&fas->full_downsweep,&flg);CHKERRQ(ierr);
271928e959bSPeter Brune       if (flg) {SNESFASFullSetDownSweep(snes,fas->full_downsweep);CHKERRQ(ierr);}
272928e959bSPeter Brune     }
273928e959bSPeter Brune 
27466585501SPeter Brune     ierr = PetscOptionsInt("-snes_fas_smoothup","Number of post-smoothing steps","SNESFASSetNumberSmoothUp",fas->max_up_it,&n_up,&upflg);CHKERRQ(ierr);
275162d76ddSPeter Brune 
27666585501SPeter Brune     ierr = PetscOptionsInt("-snes_fas_smoothdown","Number of pre-smoothing steps","SNESFASSetNumberSmoothDown",fas->max_down_it,&n_down,&downflg);CHKERRQ(ierr);
277162d76ddSPeter Brune 
278d142ab34SLawrence Mitchell     {
279d142ab34SLawrence Mitchell       PetscViewer viewer;
280d142ab34SLawrence Mitchell       PetscViewerFormat format;
281d142ab34SLawrence Mitchell       ierr = PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes),((PetscObject)snes)->prefix,
282d142ab34SLawrence Mitchell                                    "-snes_fas_monitor",&viewer,&format,&monflg);CHKERRQ(ierr);
283d142ab34SLawrence Mitchell       if (monflg) {
284d142ab34SLawrence Mitchell         PetscViewerAndFormat *vf;
285d142ab34SLawrence Mitchell         ierr = PetscViewerAndFormatCreate(viewer,format,&vf);CHKERRQ(ierr);
286d142ab34SLawrence Mitchell         ierr = PetscObjectDereference((PetscObject)viewer);CHKERRQ(ierr);
287d142ab34SLawrence Mitchell         ierr = SNESFASSetMonitor(snes,vf,PETSC_TRUE);CHKERRQ(ierr);
288d142ab34SLawrence Mitchell       }
289d142ab34SLawrence Mitchell     }
2900dd27c6cSPeter Brune     flg    = PETSC_FALSE;
2910dd27c6cSPeter Brune     monflg = PETSC_TRUE;
2920dd27c6cSPeter Brune     ierr   = PetscOptionsBool("-snes_fas_log","Log times for each FAS level","SNESFASSetLog",monflg,&monflg,&flg);CHKERRQ(ierr);
2930dd27c6cSPeter Brune     if (flg) {ierr = SNESFASSetLog(snes,monflg);CHKERRQ(ierr);}
294ab8d36c9SPeter Brune   }
295ee78dd50SPeter Brune 
296421d9b32SPeter Brune   ierr = PetscOptionsTail();CHKERRQ(ierr);
2978cc86e31SPeter Brune   /* setup from the determined types if there is no pointwise procedure or smoother defined */
298162d76ddSPeter Brune   if (upflg) {
29966585501SPeter Brune     ierr = SNESFASSetNumberSmoothUp(snes,n_up);CHKERRQ(ierr);
300162d76ddSPeter Brune   }
301162d76ddSPeter Brune   if (downflg) {
30266585501SPeter Brune     ierr = SNESFASSetNumberSmoothDown(snes,n_down);CHKERRQ(ierr);
303162d76ddSPeter Brune   }
304eff52c0eSPeter Brune 
3059e764e56SPeter Brune   /* set up the default line search for coarse grid corrections */
3069e764e56SPeter Brune   if (fas->fastype == SNES_FAS_ADDITIVE) {
3079e764e56SPeter Brune     if (!snes->linesearch) {
3087601faf0SJed Brown       ierr = SNESGetLineSearch(snes, &linesearch);CHKERRQ(ierr);
3091a4f838cSPeter Brune       ierr = SNESLineSearchSetType(linesearch, SNESLINESEARCHL2);CHKERRQ(ierr);
3109e764e56SPeter Brune     }
3119e764e56SPeter Brune   }
3129e764e56SPeter Brune 
313ab8d36c9SPeter Brune   ierr = SNESFASCycleGetCorrection(snes, &next);CHKERRQ(ierr);
314ee78dd50SPeter Brune   /* recursive option setting for the smoothers */
315ab8d36c9SPeter Brune   if (next) {ierr = SNESSetFromOptions(next);CHKERRQ(ierr);}
316421d9b32SPeter Brune   PetscFunctionReturn(0);
317421d9b32SPeter Brune }
318421d9b32SPeter Brune 
3199804daf3SBarry Smith #include <petscdraw.h>
32040244768SBarry Smith static PetscErrorCode SNESView_FAS(SNES snes, PetscViewer viewer)
321421d9b32SPeter Brune {
322421d9b32SPeter Brune   SNES_FAS       *fas = (SNES_FAS*) snes->data;
323656ede7eSPeter Brune   PetscBool      isFine,iascii,isdraw;
324ab8d36c9SPeter Brune   PetscInt       i;
325421d9b32SPeter Brune   PetscErrorCode ierr;
326ab8d36c9SPeter Brune   SNES           smoothu, smoothd, levelsnes;
327421d9b32SPeter Brune 
328421d9b32SPeter Brune   PetscFunctionBegin;
329ab8d36c9SPeter Brune   ierr = SNESFASCycleIsFine(snes, &isFine);CHKERRQ(ierr);
330ab8d36c9SPeter Brune   if (isFine) {
331251f4c67SDmitry Karpeev     ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
332656ede7eSPeter Brune     ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERDRAW,&isdraw);CHKERRQ(ierr);
333421d9b32SPeter Brune     if (iascii) {
334efd4aadfSBarry Smith       ierr = PetscViewerASCIIPrintf(viewer, "  type is %s, levels=%D, cycles=%D\n",  SNESFASTypes[fas->fastype], fas->levels, fas->n_cycles);CHKERRQ(ierr);
335ab8d36c9SPeter Brune       if (fas->galerkin) {
336ab8d36c9SPeter Brune         ierr = PetscViewerASCIIPrintf(viewer,"  Using Galerkin computed coarse grid function evaluation\n");CHKERRQ(ierr);
337421d9b32SPeter Brune       } else {
338ab8d36c9SPeter Brune         ierr = PetscViewerASCIIPrintf(viewer,"  Not using Galerkin computed coarse grid function evaluation\n");CHKERRQ(ierr);
339421d9b32SPeter Brune       }
340ab8d36c9SPeter Brune       for (i=0; i<fas->levels; i++) {
341ab8d36c9SPeter Brune         ierr = SNESFASGetCycleSNES(snes, i, &levelsnes);CHKERRQ(ierr);
342ab8d36c9SPeter Brune         ierr = SNESFASCycleGetSmootherUp(levelsnes, &smoothu);CHKERRQ(ierr);
343ab8d36c9SPeter Brune         ierr = SNESFASCycleGetSmootherDown(levelsnes, &smoothd);CHKERRQ(ierr);
344ab8d36c9SPeter Brune         if (!i) {
345ab8d36c9SPeter Brune           ierr = PetscViewerASCIIPrintf(viewer,"  Coarse grid solver -- level %D -------------------------------\n",i);CHKERRQ(ierr);
346421d9b32SPeter Brune         } else {
347ab8d36c9SPeter Brune           ierr = PetscViewerASCIIPrintf(viewer,"  Down solver (pre-smoother) on level %D -------------------------------\n",i);CHKERRQ(ierr);
348421d9b32SPeter Brune         }
349ab8d36c9SPeter Brune         ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr);
350166b3ea4SJed Brown         if (smoothd) {
351ab8d36c9SPeter Brune           ierr = SNESView(smoothd,viewer);CHKERRQ(ierr);
352166b3ea4SJed Brown         } else {
353166b3ea4SJed Brown           ierr = PetscViewerASCIIPrintf(viewer,"Not yet available\n");CHKERRQ(ierr);
354166b3ea4SJed Brown         }
355ab8d36c9SPeter Brune         ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr);
356ab8d36c9SPeter Brune         if (i && (smoothd == smoothu)) {
357ab8d36c9SPeter Brune           ierr = PetscViewerASCIIPrintf(viewer,"  Up solver (post-smoother) same as down solver (pre-smoother)\n");CHKERRQ(ierr);
358ab8d36c9SPeter Brune         } else if (i) {
359ab8d36c9SPeter Brune           ierr = PetscViewerASCIIPrintf(viewer,"  Up solver (post-smoother) on level %D -------------------------------\n",i);CHKERRQ(ierr);
360ab8d36c9SPeter Brune           ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr);
361166b3ea4SJed Brown           if (smoothu) {
362ab8d36c9SPeter Brune             ierr = SNESView(smoothu,viewer);CHKERRQ(ierr);
363166b3ea4SJed Brown           } else {
364166b3ea4SJed Brown             ierr = PetscViewerASCIIPrintf(viewer,"Not yet available\n");CHKERRQ(ierr);
365166b3ea4SJed Brown           }
366ab8d36c9SPeter Brune           ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr);
367ab8d36c9SPeter Brune         }
368ab8d36c9SPeter Brune       }
369656ede7eSPeter Brune     } else if (isdraw) {
370656ede7eSPeter Brune       PetscDraw draw;
371b4375e8dSPeter Brune       PetscReal x,w,y,bottom,th,wth;
372656ede7eSPeter Brune       SNES_FAS  *curfas = fas;
373656ede7eSPeter Brune       ierr   = PetscViewerDrawGetDraw(viewer,0,&draw);CHKERRQ(ierr);
374656ede7eSPeter Brune       ierr   = PetscDrawGetCurrentPoint(draw,&x,&y);CHKERRQ(ierr);
375656ede7eSPeter Brune       ierr   = PetscDrawStringGetSize(draw,&wth,&th);CHKERRQ(ierr);
376656ede7eSPeter Brune       bottom = y - th;
377656ede7eSPeter Brune       while (curfas) {
378b4375e8dSPeter Brune         if (!curfas->smoothu) {
379656ede7eSPeter Brune           ierr = PetscDrawPushCurrentPoint(draw,x,bottom);CHKERRQ(ierr);
380656ede7eSPeter Brune           if (curfas->smoothd) ierr = SNESView(curfas->smoothd,viewer);CHKERRQ(ierr);
381656ede7eSPeter Brune           ierr = PetscDrawPopCurrentPoint(draw);CHKERRQ(ierr);
382b4375e8dSPeter Brune         } else {
383b4375e8dSPeter Brune           w    = 0.5*PetscMin(1.0-x,x);
384b4375e8dSPeter Brune           ierr = PetscDrawPushCurrentPoint(draw,x-w,bottom);CHKERRQ(ierr);
385b4375e8dSPeter Brune           if (curfas->smoothd) ierr = SNESView(curfas->smoothd,viewer);CHKERRQ(ierr);
386b4375e8dSPeter Brune           ierr = PetscDrawPopCurrentPoint(draw);CHKERRQ(ierr);
387b4375e8dSPeter Brune           ierr = PetscDrawPushCurrentPoint(draw,x+w,bottom);CHKERRQ(ierr);
388b4375e8dSPeter Brune           if (curfas->smoothu) ierr = SNESView(curfas->smoothu,viewer);CHKERRQ(ierr);
389b4375e8dSPeter Brune           ierr = PetscDrawPopCurrentPoint(draw);CHKERRQ(ierr);
390b4375e8dSPeter Brune         }
391656ede7eSPeter Brune         /* this is totally bogus but we have no way of knowing how low the previous one was draw to */
392656ede7eSPeter Brune         bottom -= 5*th;
3931aa26658SKarl Rupp         if (curfas->next) curfas = (SNES_FAS*)curfas->next->data;
3940298fd71SBarry Smith         else curfas = NULL;
395656ede7eSPeter Brune       }
396421d9b32SPeter Brune     }
397ab8d36c9SPeter Brune   }
398421d9b32SPeter Brune   PetscFunctionReturn(0);
399421d9b32SPeter Brune }
400421d9b32SPeter Brune 
40139bd7f45SPeter Brune /*
40239bd7f45SPeter Brune Defines the action of the downsmoother
40339bd7f45SPeter Brune  */
40440244768SBarry Smith static PetscErrorCode SNESFASDownSmooth_Private(SNES snes, Vec B, Vec X, Vec F, PetscReal *fnorm)
405b9c2fdf1SPeter Brune {
40639bd7f45SPeter Brune   PetscErrorCode      ierr = 0;
407742fe5e2SPeter Brune   SNESConvergedReason reason;
408ab8d36c9SPeter Brune   Vec                 FPC;
409ab8d36c9SPeter Brune   SNES                smoothd;
4106cbb2f26SLawrence Mitchell   PetscBool           flg;
4110dd27c6cSPeter Brune   SNES_FAS            *fas = (SNES_FAS*) snes->data;
4126e111a19SKarl Rupp 
413421d9b32SPeter Brune   PetscFunctionBegin;
414ab8d36c9SPeter Brune   ierr = SNESFASCycleGetSmootherDown(snes, &smoothd);CHKERRQ(ierr);
415e4ed7901SPeter Brune   ierr = SNESSetInitialFunction(smoothd, F);CHKERRQ(ierr);
416*217044c2SLisandro Dalcin   if (fas->eventsmoothsolve) {ierr = PetscLogEventBegin(fas->eventsmoothsolve,smoothd,B,X,0);CHKERRQ(ierr);}
417ab8d36c9SPeter Brune   ierr = SNESSolve(smoothd, B, X);CHKERRQ(ierr);
418*217044c2SLisandro Dalcin   if (fas->eventsmoothsolve) {ierr = PetscLogEventEnd(fas->eventsmoothsolve,smoothd,B,X,0);CHKERRQ(ierr);}
419742fe5e2SPeter Brune   /* check convergence reason for the smoother */
420ab8d36c9SPeter Brune   ierr = SNESGetConvergedReason(smoothd,&reason);CHKERRQ(ierr);
4211ff805c3SPeter Brune   if (reason < 0 && !(reason == SNES_DIVERGED_MAX_IT || reason == SNES_DIVERGED_LOCAL_MIN || reason == SNES_DIVERGED_LINE_SEARCH)) {
422742fe5e2SPeter Brune     snes->reason = SNES_DIVERGED_INNER;
423742fe5e2SPeter Brune     PetscFunctionReturn(0);
424742fe5e2SPeter Brune   }
4256cbb2f26SLawrence Mitchell 
4260298fd71SBarry Smith   ierr = SNESGetFunction(smoothd, &FPC, NULL, NULL);CHKERRQ(ierr);
4276cbb2f26SLawrence Mitchell   ierr = SNESGetAlwaysComputesFinalResidual(smoothd, &flg);CHKERRQ(ierr);
4286cbb2f26SLawrence Mitchell   if (!flg) {
4296cbb2f26SLawrence Mitchell     ierr = SNESComputeFunction(smoothd, X, FPC);CHKERRQ(ierr);
4306cbb2f26SLawrence Mitchell   }
4314b32a720SPeter Brune   ierr = VecCopy(FPC, F);CHKERRQ(ierr);
43271dbe336SPeter Brune   if (fnorm) {ierr = VecNorm(F,NORM_2,fnorm);CHKERRQ(ierr);}
43339bd7f45SPeter Brune   PetscFunctionReturn(0);
43439bd7f45SPeter Brune }
43539bd7f45SPeter Brune 
43639bd7f45SPeter Brune 
43739bd7f45SPeter Brune /*
43807144faaSPeter Brune Defines the action of the upsmoother
43939bd7f45SPeter Brune  */
44040244768SBarry Smith static PetscErrorCode SNESFASUpSmooth_Private(SNES snes, Vec B, Vec X, Vec F, PetscReal *fnorm)
4410adebc6cSBarry Smith {
44239bd7f45SPeter Brune   PetscErrorCode      ierr = 0;
44339bd7f45SPeter Brune   SNESConvergedReason reason;
444ab8d36c9SPeter Brune   Vec                 FPC;
445ab8d36c9SPeter Brune   SNES                smoothu;
4466cbb2f26SLawrence Mitchell   PetscBool           flg;
4470dd27c6cSPeter Brune   SNES_FAS            *fas = (SNES_FAS*) snes->data;
448ab8d36c9SPeter Brune 
4496e111a19SKarl Rupp   PetscFunctionBegin;
450ab8d36c9SPeter Brune   ierr = SNESFASCycleGetSmootherUp(snes, &smoothu);CHKERRQ(ierr);
451*217044c2SLisandro Dalcin   if (fas->eventsmoothsolve) {ierr = PetscLogEventBegin(fas->eventsmoothsolve,smoothu,0,0,0);CHKERRQ(ierr);}
452ab8d36c9SPeter Brune   ierr = SNESSolve(smoothu, B, X);CHKERRQ(ierr);
453*217044c2SLisandro Dalcin   if (fas->eventsmoothsolve) {ierr = PetscLogEventEnd(fas->eventsmoothsolve,smoothu,0,0,0);CHKERRQ(ierr);}
45439bd7f45SPeter Brune   /* check convergence reason for the smoother */
455ab8d36c9SPeter Brune   ierr = SNESGetConvergedReason(smoothu,&reason);CHKERRQ(ierr);
4561ff805c3SPeter Brune   if (reason < 0 && !(reason == SNES_DIVERGED_MAX_IT || reason == SNES_DIVERGED_LOCAL_MIN || reason == SNES_DIVERGED_LINE_SEARCH)) {
45739bd7f45SPeter Brune     snes->reason = SNES_DIVERGED_INNER;
45839bd7f45SPeter Brune     PetscFunctionReturn(0);
45939bd7f45SPeter Brune   }
4600298fd71SBarry Smith   ierr = SNESGetFunction(smoothu, &FPC, NULL, NULL);CHKERRQ(ierr);
4616cbb2f26SLawrence Mitchell   ierr = SNESGetAlwaysComputesFinalResidual(smoothu, &flg);CHKERRQ(ierr);
4626cbb2f26SLawrence Mitchell   if (!flg) {
4636cbb2f26SLawrence Mitchell     ierr = SNESComputeFunction(smoothu, X, FPC);CHKERRQ(ierr);
4646cbb2f26SLawrence Mitchell   }
4654b32a720SPeter Brune   ierr = VecCopy(FPC, F);CHKERRQ(ierr);
46671dbe336SPeter Brune   if (fnorm) {ierr = VecNorm(F,NORM_2,fnorm);CHKERRQ(ierr);}
46739bd7f45SPeter Brune   PetscFunctionReturn(0);
46839bd7f45SPeter Brune }
46939bd7f45SPeter Brune 
470938e4a01SJed Brown /*@
471938e4a01SJed Brown    SNESFASCreateCoarseVec - create Vec corresponding to a state vector on one level coarser than current level
472938e4a01SJed Brown 
473938e4a01SJed Brown    Collective
474938e4a01SJed Brown 
475938e4a01SJed Brown    Input Arguments:
476938e4a01SJed Brown .  snes - SNESFAS
477938e4a01SJed Brown 
478938e4a01SJed Brown    Output Arguments:
479938e4a01SJed Brown .  Xcoarse - vector on level one coarser than snes
480938e4a01SJed Brown 
481938e4a01SJed Brown    Level: developer
482938e4a01SJed Brown 
483938e4a01SJed Brown .seealso: SNESFASSetRestriction(), SNESFASRestrict()
484938e4a01SJed Brown @*/
485938e4a01SJed Brown PetscErrorCode SNESFASCreateCoarseVec(SNES snes,Vec *Xcoarse)
486938e4a01SJed Brown {
487938e4a01SJed Brown   PetscErrorCode ierr;
488938e4a01SJed Brown   SNES_FAS       *fas = (SNES_FAS*)snes->data;
489938e4a01SJed Brown 
490938e4a01SJed Brown   PetscFunctionBegin;
4911aa26658SKarl Rupp   if (fas->rscale) {
4921aa26658SKarl Rupp     ierr = VecDuplicate(fas->rscale,Xcoarse);CHKERRQ(ierr);
493f5af7f23SKarl Rupp   } else if (fas->inject) {
4942a7a6963SBarry Smith     ierr = MatCreateVecs(fas->inject,Xcoarse,NULL);CHKERRQ(ierr);
49513903a91SSatish Balay   } else SETERRQ(PetscObjectComm((PetscObject)snes),PETSC_ERR_ARG_WRONGSTATE,"Must set restriction or injection");
496938e4a01SJed Brown   PetscFunctionReturn(0);
497938e4a01SJed Brown }
498938e4a01SJed Brown 
499e9923e8dSJed Brown /*@
500e9923e8dSJed Brown    SNESFASRestrict - restrict a Vec to the next coarser level
501e9923e8dSJed Brown 
502e9923e8dSJed Brown    Collective
503e9923e8dSJed Brown 
504e9923e8dSJed Brown    Input Arguments:
505e9923e8dSJed Brown +  fine - SNES from which to restrict
506e9923e8dSJed Brown -  Xfine - vector to restrict
507e9923e8dSJed Brown 
508e9923e8dSJed Brown    Output Arguments:
509e9923e8dSJed Brown .  Xcoarse - result of restriction
510e9923e8dSJed Brown 
511e9923e8dSJed Brown    Level: developer
512e9923e8dSJed Brown 
513e9923e8dSJed Brown .seealso: SNESFASSetRestriction(), SNESFASSetInjection()
514e9923e8dSJed Brown @*/
515e9923e8dSJed Brown PetscErrorCode SNESFASRestrict(SNES fine,Vec Xfine,Vec Xcoarse)
516e9923e8dSJed Brown {
517e9923e8dSJed Brown   PetscErrorCode ierr;
518e9923e8dSJed Brown   SNES_FAS       *fas = (SNES_FAS*)fine->data;
519e9923e8dSJed Brown 
520e9923e8dSJed Brown   PetscFunctionBegin;
521e9923e8dSJed Brown   PetscValidHeaderSpecific(fine,SNES_CLASSID,1);
522e9923e8dSJed Brown   PetscValidHeaderSpecific(Xfine,VEC_CLASSID,2);
523e9923e8dSJed Brown   PetscValidHeaderSpecific(Xcoarse,VEC_CLASSID,3);
524e9923e8dSJed Brown   if (fas->inject) {
525e9923e8dSJed Brown     ierr = MatRestrict(fas->inject,Xfine,Xcoarse);CHKERRQ(ierr);
526e9923e8dSJed Brown   } else {
527e9923e8dSJed Brown     ierr = MatRestrict(fas->restrct,Xfine,Xcoarse);CHKERRQ(ierr);
528e9923e8dSJed Brown     ierr = VecPointwiseMult(Xcoarse,fas->rscale,Xcoarse);CHKERRQ(ierr);
529e9923e8dSJed Brown   }
530e9923e8dSJed Brown   PetscFunctionReturn(0);
531e9923e8dSJed Brown }
532e9923e8dSJed Brown 
53339bd7f45SPeter Brune /*
53439bd7f45SPeter Brune 
53539bd7f45SPeter Brune Performs the FAS coarse correction as:
53639bd7f45SPeter Brune 
537b5527d98SMatthew G. Knepley fine problem:   F(x) = b
538b5527d98SMatthew G. Knepley coarse problem: F^c(x^c) = b^c
53939bd7f45SPeter Brune 
540b5527d98SMatthew G. Knepley b^c = F^c(Rx) - R(F(x) - b)
54139bd7f45SPeter Brune 
54239bd7f45SPeter Brune  */
5430adebc6cSBarry Smith PetscErrorCode SNESFASCoarseCorrection(SNES snes, Vec X, Vec F, Vec X_new)
5440adebc6cSBarry Smith {
54539bd7f45SPeter Brune   PetscErrorCode      ierr;
54639bd7f45SPeter Brune   Vec                 X_c, Xo_c, F_c, B_c;
54739bd7f45SPeter Brune   SNESConvergedReason reason;
548ab8d36c9SPeter Brune   SNES                next;
549ab8d36c9SPeter Brune   Mat                 restrct, interpolate;
5500dd27c6cSPeter Brune   SNES_FAS            *fasc;
5515fd66863SKarl Rupp 
55239bd7f45SPeter Brune   PetscFunctionBegin;
553ab8d36c9SPeter Brune   ierr = SNESFASCycleGetCorrection(snes, &next);CHKERRQ(ierr);
554ab8d36c9SPeter Brune   if (next) {
5550dd27c6cSPeter Brune     fasc = (SNES_FAS*)next->data;
5560dd27c6cSPeter Brune 
557ab8d36c9SPeter Brune     ierr = SNESFASCycleGetRestriction(snes, &restrct);CHKERRQ(ierr);
558ab8d36c9SPeter Brune     ierr = SNESFASCycleGetInterpolation(snes, &interpolate);CHKERRQ(ierr);
559ab8d36c9SPeter Brune 
560ab8d36c9SPeter Brune     X_c  = next->vec_sol;
561ab8d36c9SPeter Brune     Xo_c = next->work[0];
562ab8d36c9SPeter Brune     F_c  = next->vec_func;
563ab8d36c9SPeter Brune     B_c  = next->vec_rhs;
564efe1f98aSPeter Brune 
565*217044c2SLisandro Dalcin     if (fasc->eventinterprestrict) {ierr = PetscLogEventBegin(fasc->eventinterprestrict,snes,0,0,0);CHKERRQ(ierr);}
566938e4a01SJed Brown     ierr = SNESFASRestrict(snes,X,Xo_c);CHKERRQ(ierr);
5675609cbf2SMatthew G. Knepley     /* restrict the defect: R(F(x) - b) */
568ab8d36c9SPeter Brune     ierr = MatRestrict(restrct, F, B_c);CHKERRQ(ierr);
569*217044c2SLisandro Dalcin     if (fasc->eventinterprestrict) {ierr = PetscLogEventEnd(fasc->eventinterprestrict,snes,0,0,0);CHKERRQ(ierr);}
5700dd27c6cSPeter Brune 
571*217044c2SLisandro Dalcin     if (fasc->eventresidual) {ierr = PetscLogEventBegin(fasc->eventresidual,next,0,0,0);CHKERRQ(ierr);}
5725609cbf2SMatthew G. Knepley     /* F_c = F^c(Rx) - R(F(x) - b) since the second term was sitting in next->vec_rhs */
573ab8d36c9SPeter Brune     ierr = SNESComputeFunction(next, Xo_c, F_c);CHKERRQ(ierr);
574*217044c2SLisandro Dalcin     if (fasc->eventresidual) {ierr = PetscLogEventEnd(fasc->eventresidual,next,0,0,0);CHKERRQ(ierr);}
5750dd27c6cSPeter Brune 
5760dd27c6cSPeter Brune     /* solve the coarse problem corresponding to F^c(x^c) = b^c = F^c(Rx) - R(F(x) - b) */
577e4ed7901SPeter Brune     ierr = VecCopy(B_c, X_c);CHKERRQ(ierr);
578b9c2fdf1SPeter Brune     ierr = VecCopy(F_c, B_c);CHKERRQ(ierr);
579e4ed7901SPeter Brune     ierr = VecCopy(X_c, F_c);CHKERRQ(ierr);
580ee78dd50SPeter Brune     /* set initial guess of the coarse problem to the projected fine solution */
581ee78dd50SPeter Brune     ierr = VecCopy(Xo_c, X_c);CHKERRQ(ierr);
582c90fad12SPeter Brune 
583c90fad12SPeter Brune     /* recurse to the next level */
584e4ed7901SPeter Brune     ierr = SNESSetInitialFunction(next, F_c);CHKERRQ(ierr);
585ab8d36c9SPeter Brune     ierr = SNESSolve(next, B_c, X_c);CHKERRQ(ierr);
586ab8d36c9SPeter Brune     ierr = SNESGetConvergedReason(next,&reason);CHKERRQ(ierr);
587742fe5e2SPeter Brune     if (reason < 0 && reason != SNES_DIVERGED_MAX_IT) {
588742fe5e2SPeter Brune       snes->reason = SNES_DIVERGED_INNER;
589742fe5e2SPeter Brune       PetscFunctionReturn(0);
590742fe5e2SPeter Brune     }
591fa9694d7SPeter Brune     /* correct as x <- x + I(x^c - Rx)*/
592fa9694d7SPeter Brune     ierr = VecAXPY(X_c, -1.0, Xo_c);CHKERRQ(ierr);
5930dd27c6cSPeter Brune 
594*217044c2SLisandro Dalcin     if (fasc->eventinterprestrict) {ierr = PetscLogEventBegin(fasc->eventinterprestrict,snes,0,0,0);CHKERRQ(ierr);}
595ab8d36c9SPeter Brune     ierr = MatInterpolateAdd(interpolate, X_c, X, X_new);CHKERRQ(ierr);
596fb8dc43dSMatthew G. Knepley     ierr = PetscObjectSetName((PetscObject) X_c, "Coarse correction");CHKERRQ(ierr);
597fb8dc43dSMatthew G. Knepley     ierr = VecViewFromOptions(X_c, NULL, "-fas_coarse_solution_view");CHKERRQ(ierr);
598fb8dc43dSMatthew G. Knepley     ierr = PetscObjectSetName((PetscObject) X_new, "Updated Fine solution");CHKERRQ(ierr);
599fb8dc43dSMatthew G. Knepley     ierr = VecViewFromOptions(X_new, NULL, "-fas_levels_1_solution_view");CHKERRQ(ierr);
600*217044c2SLisandro Dalcin     if (fasc->eventinterprestrict) {ierr = PetscLogEventEnd(fasc->eventinterprestrict,snes,0,0,0);CHKERRQ(ierr);}
601293a7e31SPeter Brune   }
60239bd7f45SPeter Brune   PetscFunctionReturn(0);
60339bd7f45SPeter Brune }
60439bd7f45SPeter Brune 
60539bd7f45SPeter Brune /*
60639bd7f45SPeter Brune 
60739bd7f45SPeter Brune The additive cycle looks like:
60839bd7f45SPeter Brune 
60907144faaSPeter Brune xhat = x
61007144faaSPeter Brune xhat = dS(x, b)
61107144faaSPeter Brune x = coarsecorrection(xhat, b_d)
61207144faaSPeter Brune x = x + nu*(xhat - x);
61339bd7f45SPeter Brune (optional) x = uS(x, b)
61439bd7f45SPeter Brune 
61539bd7f45SPeter Brune With the coarse RHS (defect correction) as below.
61639bd7f45SPeter Brune 
61739bd7f45SPeter Brune  */
61840244768SBarry Smith static PetscErrorCode SNESFASCycle_Additive(SNES snes, Vec X)
6190adebc6cSBarry Smith {
62007144faaSPeter Brune   Vec                  F, B, Xhat;
62122c1e704SPeter Brune   Vec                  X_c, Xo_c, F_c, B_c;
62239bd7f45SPeter Brune   PetscErrorCode       ierr;
62307144faaSPeter Brune   SNESConvergedReason  reason;
62422c1e704SPeter Brune   PetscReal            xnorm, fnorm, ynorm;
625422a814eSBarry Smith   SNESLineSearchReason lsresult;
626ab8d36c9SPeter Brune   SNES                 next;
627ab8d36c9SPeter Brune   Mat                  restrct, interpolate;
6280dd27c6cSPeter Brune   SNES_FAS             *fas = (SNES_FAS*)snes->data,*fasc;
6290dd27c6cSPeter Brune 
63039bd7f45SPeter Brune   PetscFunctionBegin;
631ab8d36c9SPeter Brune   ierr = SNESFASCycleGetCorrection(snes, &next);CHKERRQ(ierr);
63239bd7f45SPeter Brune   F    = snes->vec_func;
63339bd7f45SPeter Brune   B    = snes->vec_rhs;
634e7f468e7SPeter Brune   Xhat = snes->work[1];
63507144faaSPeter Brune   ierr = VecCopy(X, Xhat);CHKERRQ(ierr);
63607144faaSPeter Brune   /* recurse first */
637ab8d36c9SPeter Brune   if (next) {
6380dd27c6cSPeter Brune     fasc = (SNES_FAS*)next->data;
639ab8d36c9SPeter Brune     ierr = SNESFASCycleGetRestriction(snes, &restrct);CHKERRQ(ierr);
640ab8d36c9SPeter Brune     ierr = SNESFASCycleGetInterpolation(snes, &interpolate);CHKERRQ(ierr);
641*217044c2SLisandro Dalcin     if (fas->eventresidual) {ierr = PetscLogEventBegin(fas->eventresidual,snes,0,0,0);CHKERRQ(ierr);}
64207144faaSPeter Brune     ierr = SNESComputeFunction(snes, Xhat, F);CHKERRQ(ierr);
643*217044c2SLisandro Dalcin     if (fas->eventresidual) {ierr = PetscLogEventEnd(fas->eventresidual,snes,0,0,0);CHKERRQ(ierr);}
644c2a02606SPeter Brune     ierr = VecNorm(F, NORM_2, &fnorm);CHKERRQ(ierr);
645ab8d36c9SPeter Brune     X_c  = next->vec_sol;
646ab8d36c9SPeter Brune     Xo_c = next->work[0];
647ab8d36c9SPeter Brune     F_c  = next->vec_func;
648ab8d36c9SPeter Brune     B_c  = next->vec_rhs;
64939bd7f45SPeter Brune 
650938e4a01SJed Brown     ierr = SNESFASRestrict(snes,Xhat,Xo_c);CHKERRQ(ierr);
65107144faaSPeter Brune     /* restrict the defect */
652ab8d36c9SPeter Brune     ierr = MatRestrict(restrct, F, B_c);CHKERRQ(ierr);
65307144faaSPeter Brune 
65407144faaSPeter Brune     /* solve the coarse problem corresponding to F^c(x^c) = b^c = Rb + F^c(Rx) - RF(x) */
655*217044c2SLisandro Dalcin     if (fasc->eventresidual) {ierr = PetscLogEventBegin(fasc->eventresidual,next,0,0,0);CHKERRQ(ierr);}
656ab8d36c9SPeter Brune     ierr = SNESComputeFunction(next, Xo_c, F_c);CHKERRQ(ierr);
657*217044c2SLisandro Dalcin     if (fasc->eventresidual) {ierr = PetscLogEventEnd(fasc->eventresidual,next,0,0,0);CHKERRQ(ierr);}
658e4ed7901SPeter Brune     ierr = VecCopy(B_c, X_c);CHKERRQ(ierr);
659b9c2fdf1SPeter Brune     ierr = VecCopy(F_c, B_c);CHKERRQ(ierr);
660e4ed7901SPeter Brune     ierr = VecCopy(X_c, F_c);CHKERRQ(ierr);
66107144faaSPeter Brune     /* set initial guess of the coarse problem to the projected fine solution */
66207144faaSPeter Brune     ierr = VecCopy(Xo_c, X_c);CHKERRQ(ierr);
66307144faaSPeter Brune 
66407144faaSPeter Brune     /* recurse */
665e4ed7901SPeter Brune     ierr = SNESSetInitialFunction(next, F_c);CHKERRQ(ierr);
666ab8d36c9SPeter Brune     ierr = SNESSolve(next, B_c, X_c);CHKERRQ(ierr);
66707144faaSPeter Brune 
66807144faaSPeter Brune     /* smooth on this level */
66991f99d7cSPeter Brune     ierr = SNESFASDownSmooth_Private(snes, B, X, F, &fnorm);CHKERRQ(ierr);
67007144faaSPeter Brune 
671ab8d36c9SPeter Brune     ierr = SNESGetConvergedReason(next,&reason);CHKERRQ(ierr);
67207144faaSPeter Brune     if (reason < 0 && reason != SNES_DIVERGED_MAX_IT) {
67307144faaSPeter Brune       snes->reason = SNES_DIVERGED_INNER;
67407144faaSPeter Brune       PetscFunctionReturn(0);
67507144faaSPeter Brune     }
67607144faaSPeter Brune 
67707144faaSPeter Brune     /* correct as x <- x + I(x^c - Rx)*/
678c68acad4SPeter Brune     ierr = VecAYPX(X_c, -1.0, Xo_c);CHKERRQ(ierr);
679ab8d36c9SPeter Brune     ierr = MatInterpolate(interpolate, X_c, Xhat);CHKERRQ(ierr);
68007144faaSPeter Brune 
681ddebd997SPeter Brune     /* additive correction of the coarse direction*/
682f1c6b773SPeter Brune     ierr = SNESLineSearchApply(snes->linesearch, X, F, &fnorm, Xhat);CHKERRQ(ierr);
683422a814eSBarry Smith     ierr = SNESLineSearchGetReason(snes->linesearch, &lsresult);CHKERRQ(ierr);
684422a814eSBarry Smith     ierr = SNESLineSearchGetNorms(snes->linesearch, &xnorm, &snes->norm, &ynorm);CHKERRQ(ierr);
685422a814eSBarry Smith     if (lsresult) {
6869e764e56SPeter Brune       if (++snes->numFailures >= snes->maxFailures) {
6879e764e56SPeter Brune         snes->reason = SNES_DIVERGED_LINE_SEARCH;
6889e764e56SPeter Brune         PetscFunctionReturn(0);
6899e764e56SPeter Brune       }
6909e764e56SPeter Brune     }
69107144faaSPeter Brune   } else {
69291f99d7cSPeter Brune     ierr = SNESFASDownSmooth_Private(snes, B, X, F, &snes->norm);CHKERRQ(ierr);
69307144faaSPeter Brune   }
69439bd7f45SPeter Brune   PetscFunctionReturn(0);
69539bd7f45SPeter Brune }
69639bd7f45SPeter Brune 
69739bd7f45SPeter Brune /*
69839bd7f45SPeter Brune 
69939bd7f45SPeter Brune Defines the FAS cycle as:
70039bd7f45SPeter Brune 
701b5527d98SMatthew G. Knepley fine problem: F(x) = b
70239bd7f45SPeter Brune coarse problem: F^c(x) = b^c
70339bd7f45SPeter Brune 
704b5527d98SMatthew G. Knepley b^c = F^c(Rx) - R(F(x) - b)
70539bd7f45SPeter Brune 
70639bd7f45SPeter Brune correction:
70739bd7f45SPeter Brune 
70839bd7f45SPeter Brune x = x + I(x^c - Rx)
70939bd7f45SPeter Brune 
71039bd7f45SPeter Brune  */
71140244768SBarry Smith static PetscErrorCode SNESFASCycle_Multiplicative(SNES snes, Vec X)
7120adebc6cSBarry Smith {
71339bd7f45SPeter Brune 
71439bd7f45SPeter Brune   PetscErrorCode ierr;
71539bd7f45SPeter Brune   Vec            F,B;
71634d65b3cSPeter Brune   SNES           next;
71739bd7f45SPeter Brune 
71839bd7f45SPeter Brune   PetscFunctionBegin;
71939bd7f45SPeter Brune   F = snes->vec_func;
72039bd7f45SPeter Brune   B = snes->vec_rhs;
72139bd7f45SPeter Brune   /* pre-smooth -- just update using the pre-smoother */
72234d65b3cSPeter Brune   ierr = SNESFASCycleGetCorrection(snes,&next);CHKERRQ(ierr);
72391f99d7cSPeter Brune   ierr = SNESFASDownSmooth_Private(snes, B, X, F, &snes->norm);CHKERRQ(ierr);
72434d65b3cSPeter Brune   if (next) {
7258c40d5fbSBarry Smith     ierr = SNESFASCoarseCorrection(snes, X, F, X);CHKERRQ(ierr);
72691f99d7cSPeter Brune     ierr = SNESFASUpSmooth_Private(snes, B, X, F, &snes->norm);CHKERRQ(ierr);
727fe6f9142SPeter Brune   }
728fa9694d7SPeter Brune   PetscFunctionReturn(0);
729421d9b32SPeter Brune }
730421d9b32SPeter Brune 
73140244768SBarry Smith static PetscErrorCode SNESFASCycleSetupPhase_Full(SNES snes)
7328c94862eSPeter Brune {
7338c94862eSPeter Brune   SNES           next;
7348c94862eSPeter Brune   SNES_FAS       *fas = (SNES_FAS*)snes->data;
7358c94862eSPeter Brune   PetscBool      isFine;
7368c94862eSPeter Brune   PetscErrorCode ierr;
7378c94862eSPeter Brune 
7388c94862eSPeter Brune   PetscFunctionBegin;
7398c94862eSPeter Brune   /* pre-smooth -- just update using the pre-smoother */
7408c94862eSPeter Brune   ierr = SNESFASCycleIsFine(snes,&isFine);CHKERRQ(ierr);
7418c94862eSPeter Brune   ierr = SNESFASCycleGetCorrection(snes,&next);CHKERRQ(ierr);
7428c94862eSPeter Brune   fas->full_stage = 0;
7438c94862eSPeter Brune   if (next) {ierr = SNESFASCycleSetupPhase_Full(next);CHKERRQ(ierr);}
7448c94862eSPeter Brune   PetscFunctionReturn(0);
7458c94862eSPeter Brune }
7468c94862eSPeter Brune 
74740244768SBarry Smith static PetscErrorCode SNESFASCycle_Full(SNES snes, Vec X)
7488c94862eSPeter Brune {
7498c94862eSPeter Brune   PetscErrorCode ierr;
7508c94862eSPeter Brune   Vec            F,B;
7518c94862eSPeter Brune   SNES_FAS       *fas = (SNES_FAS*)snes->data;
7528c94862eSPeter Brune   PetscBool      isFine;
7538c94862eSPeter Brune   SNES           next;
7548c94862eSPeter Brune 
7558c94862eSPeter Brune   PetscFunctionBegin;
7568c94862eSPeter Brune   F = snes->vec_func;
7578c94862eSPeter Brune   B = snes->vec_rhs;
7588c94862eSPeter Brune   ierr = SNESFASCycleIsFine(snes,&isFine);CHKERRQ(ierr);
7598c94862eSPeter Brune   ierr = SNESFASCycleGetCorrection(snes,&next);CHKERRQ(ierr);
7608c94862eSPeter Brune 
7618c94862eSPeter Brune   if (isFine) {
7628c94862eSPeter Brune     ierr = SNESFASCycleSetupPhase_Full(snes);CHKERRQ(ierr);
7638c94862eSPeter Brune   }
7648c94862eSPeter Brune 
7658c94862eSPeter Brune   if (fas->full_stage == 0) {
766928e959bSPeter Brune     /* downsweep */
7678c94862eSPeter Brune     if (next) {
7688c94862eSPeter Brune       if (fas->level != 1) next->max_its += 1;
769928e959bSPeter Brune       if (fas->full_downsweep||isFine) {ierr = SNESFASDownSmooth_Private(snes,B,X,F,&snes->norm);CHKERRQ(ierr);}
7708c94862eSPeter Brune       ierr = SNESFASCoarseCorrection(snes,X,F,X);CHKERRQ(ierr);
7718c94862eSPeter Brune       ierr = SNESFASUpSmooth_Private(snes,B,X,F,&snes->norm);CHKERRQ(ierr);
7728c94862eSPeter Brune       if (fas->level != 1) next->max_its -= 1;
7738c94862eSPeter Brune     } else {
774a3a80b83SMatthew G. Knepley       /* The smoother on the coarse level is the coarse solver */
7758c94862eSPeter Brune       ierr = SNESFASDownSmooth_Private(snes,B,X,F,&snes->norm);CHKERRQ(ierr);
7768c94862eSPeter Brune     }
7778c94862eSPeter Brune     fas->full_stage = 1;
7788c94862eSPeter Brune   } else if (fas->full_stage == 1) {
7798c94862eSPeter Brune     if (snes->iter == 0) {ierr = SNESFASDownSmooth_Private(snes,B,X,F,&snes->norm);CHKERRQ(ierr);}
7808c94862eSPeter Brune     if (next) {
7818c94862eSPeter Brune       ierr = SNESFASCoarseCorrection(snes,X,F,X);CHKERRQ(ierr);
7828c94862eSPeter Brune       ierr = SNESFASUpSmooth_Private(snes,B,X,F,&snes->norm);CHKERRQ(ierr);
7838c94862eSPeter Brune     }
7848c94862eSPeter Brune   }
7858c94862eSPeter Brune   /* final v-cycle */
7868c94862eSPeter Brune   if (isFine) {
7878c94862eSPeter Brune     if (next) {
7888c94862eSPeter Brune       ierr = SNESFASCoarseCorrection(snes,X,F,X);CHKERRQ(ierr);
7898c94862eSPeter Brune       ierr = SNESFASUpSmooth_Private(snes,B,X,F,&snes->norm);CHKERRQ(ierr);
7908c94862eSPeter Brune     }
7918c94862eSPeter Brune   }
7928c94862eSPeter Brune   PetscFunctionReturn(0);
7938c94862eSPeter Brune }
7948c94862eSPeter Brune 
79540244768SBarry Smith static PetscErrorCode SNESFASCycle_Kaskade(SNES snes, Vec X)
79634d65b3cSPeter Brune {
79734d65b3cSPeter Brune   PetscErrorCode ierr;
79834d65b3cSPeter Brune   Vec            F,B;
79934d65b3cSPeter Brune   SNES           next;
80034d65b3cSPeter Brune 
80134d65b3cSPeter Brune   PetscFunctionBegin;
80234d65b3cSPeter Brune   F = snes->vec_func;
80334d65b3cSPeter Brune   B = snes->vec_rhs;
80434d65b3cSPeter Brune   ierr = SNESFASCycleGetCorrection(snes,&next);CHKERRQ(ierr);
80534d65b3cSPeter Brune   if (next) {
80634d65b3cSPeter Brune     ierr = SNESFASCoarseCorrection(snes,X,F,X);CHKERRQ(ierr);
80734d65b3cSPeter Brune     ierr = SNESFASUpSmooth_Private(snes,B,X,F,&snes->norm);CHKERRQ(ierr);
80834d65b3cSPeter Brune   } else {
80934d65b3cSPeter Brune     ierr = SNESFASDownSmooth_Private(snes,B,X,F,&snes->norm);CHKERRQ(ierr);
81034d65b3cSPeter Brune   }
81134d65b3cSPeter Brune   PetscFunctionReturn(0);
81234d65b3cSPeter Brune }
81334d65b3cSPeter Brune 
814fffbeea8SBarry Smith PetscBool SNEScite = PETSC_FALSE;
815fffbeea8SBarry Smith const char SNESCitation[] = "@techreport{pbmkbsxt2012,\n"
816fffbeea8SBarry Smith                             "  title = {Composing Scalable Nonlinear Algebraic Solvers},\n"
817fffbeea8SBarry Smith                             "  author = {Peter Brune and Mathew Knepley and Barry Smith and Xuemin Tu},\n"
818fffbeea8SBarry Smith                             "  year = 2013,\n"
819fffbeea8SBarry Smith                             "  type = Preprint,\n"
820fffbeea8SBarry Smith                             "  number = {ANL/MCS-P2010-0112},\n"
821fffbeea8SBarry Smith                             "  institution = {Argonne National Laboratory}\n}\n";
822fffbeea8SBarry Smith 
82340244768SBarry Smith static PetscErrorCode SNESSolve_FAS(SNES snes)
824421d9b32SPeter Brune {
825fa9694d7SPeter Brune   PetscErrorCode ierr;
826fe6f9142SPeter Brune   PetscInt       i, maxits;
827ddb5aff1SPeter Brune   Vec            X, F;
828fe6f9142SPeter Brune   PetscReal      fnorm;
829b17ce1afSJed Brown   SNES_FAS       *fas = (SNES_FAS*)snes->data,*ffas;
830b17ce1afSJed Brown   DM             dm;
831e70c42e5SPeter Brune   PetscBool      isFine;
832b17ce1afSJed Brown 
833421d9b32SPeter Brune   PetscFunctionBegin;
834c579b300SPatrick Farrell 
8356c4ed002SBarry 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);
836c579b300SPatrick Farrell 
837fffbeea8SBarry Smith   ierr = PetscCitationsRegister(SNESCitation,&SNEScite);CHKERRQ(ierr);
838fe6f9142SPeter Brune   maxits       = snes->max_its;      /* maximum number of iterations */
839fe6f9142SPeter Brune   snes->reason = SNES_CONVERGED_ITERATING;
840fa9694d7SPeter Brune   X            = snes->vec_sol;
841f5a6d4f9SBarry Smith   F            = snes->vec_func;
842293a7e31SPeter Brune 
84318a66777SPeter Brune   ierr = SNESFASCycleIsFine(snes, &isFine);CHKERRQ(ierr);
844293a7e31SPeter Brune   /*norm setup */
845e04113cfSBarry Smith   ierr       = PetscObjectSAWsTakeAccess((PetscObject)snes);CHKERRQ(ierr);
846fe6f9142SPeter Brune   snes->iter = 0;
847fe6f9142SPeter Brune   snes->norm = 0.;
848e04113cfSBarry Smith   ierr       = PetscObjectSAWsGrantAccess((PetscObject)snes);CHKERRQ(ierr);
849e4ed7901SPeter Brune   if (!snes->vec_func_init_set) {
850*217044c2SLisandro Dalcin     if (fas->eventresidual) {ierr = PetscLogEventBegin(fas->eventresidual,snes,0,0,0);CHKERRQ(ierr);}
851fe6f9142SPeter Brune     ierr = SNESComputeFunction(snes,X,F);CHKERRQ(ierr);
852*217044c2SLisandro Dalcin     if (fas->eventresidual) {ierr = PetscLogEventEnd(fas->eventresidual,snes,0,0,0);CHKERRQ(ierr);}
8531aa26658SKarl Rupp   } else snes->vec_func_init_set = PETSC_FALSE;
854e4ed7901SPeter Brune 
855fe6f9142SPeter Brune   ierr = VecNorm(F, NORM_2, &fnorm);CHKERRQ(ierr); /* fnorm <- ||F||  */
856422a814eSBarry Smith   SNESCheckFunctionNorm(snes,fnorm);
857e04113cfSBarry Smith   ierr       = PetscObjectSAWsTakeAccess((PetscObject)snes);CHKERRQ(ierr);
858fe6f9142SPeter Brune   snes->norm = fnorm;
859e04113cfSBarry Smith   ierr       = PetscObjectSAWsGrantAccess((PetscObject)snes);CHKERRQ(ierr);
860a71f0d7dSBarry Smith   ierr       = SNESLogConvergenceHistory(snes,fnorm,0);CHKERRQ(ierr);
861fe6f9142SPeter Brune   ierr       = SNESMonitor(snes,0,fnorm);CHKERRQ(ierr);
862fe6f9142SPeter Brune 
863fe6f9142SPeter Brune   /* test convergence */
864fe6f9142SPeter Brune   ierr = (*snes->ops->converged)(snes,0,0.0,0.0,fnorm,&snes->reason,snes->cnvP);CHKERRQ(ierr);
865fe6f9142SPeter Brune   if (snes->reason) PetscFunctionReturn(0);
866e4ed7901SPeter Brune 
867b17ce1afSJed Brown 
868b9c2fdf1SPeter Brune   if (isFine) {
869b9c2fdf1SPeter Brune     /* propagate scale-dependent data up the hierarchy */
870b17ce1afSJed Brown     ierr = SNESGetDM(snes,&dm);CHKERRQ(ierr);
871b17ce1afSJed Brown     for (ffas=fas; ffas->next; ffas=(SNES_FAS*)ffas->next->data) {
872b17ce1afSJed Brown       DM dmcoarse;
873b17ce1afSJed Brown       ierr = SNESGetDM(ffas->next,&dmcoarse);CHKERRQ(ierr);
874b17ce1afSJed Brown       ierr = DMRestrict(dm,ffas->restrct,ffas->rscale,ffas->inject,dmcoarse);CHKERRQ(ierr);
875b17ce1afSJed Brown       dm   = dmcoarse;
876b17ce1afSJed Brown     }
877b9c2fdf1SPeter Brune   }
878b17ce1afSJed Brown 
879fe6f9142SPeter Brune   for (i = 0; i < maxits; i++) {
880fe6f9142SPeter Brune     /* Call general purpose update function */
881646217ecSPeter Brune 
882fe6f9142SPeter Brune     if (snes->ops->update) {
883fe6f9142SPeter Brune       ierr = (*snes->ops->update)(snes, snes->iter);CHKERRQ(ierr);
884fe6f9142SPeter Brune     }
88507144faaSPeter Brune     if (fas->fastype == SNES_FAS_MULTIPLICATIVE) {
88691f99d7cSPeter Brune       ierr = SNESFASCycle_Multiplicative(snes, X);CHKERRQ(ierr);
8878c94862eSPeter Brune     } else if (fas->fastype == SNES_FAS_ADDITIVE) {
88891f99d7cSPeter Brune       ierr = SNESFASCycle_Additive(snes, X);CHKERRQ(ierr);
8898c94862eSPeter Brune     } else if (fas->fastype == SNES_FAS_FULL) {
8908c94862eSPeter Brune       ierr = SNESFASCycle_Full(snes, X);CHKERRQ(ierr);
89134d65b3cSPeter Brune     } else if (fas->fastype ==SNES_FAS_KASKADE) {
89234d65b3cSPeter Brune       ierr = SNESFASCycle_Kaskade(snes, X);CHKERRQ(ierr);
8936c4ed002SBarry Smith     } else SETERRQ(PetscObjectComm((PetscObject)snes),PETSC_ERR_ARG_WRONGSTATE,"Unsupported FAS type");
894742fe5e2SPeter Brune 
895742fe5e2SPeter Brune     /* check for FAS cycle divergence */
8961aa26658SKarl Rupp     if (snes->reason != SNES_CONVERGED_ITERATING) PetscFunctionReturn(0);
897b9c2fdf1SPeter Brune 
898c90fad12SPeter Brune     /* Monitor convergence */
899e04113cfSBarry Smith     ierr       = PetscObjectSAWsTakeAccess((PetscObject)snes);CHKERRQ(ierr);
900c90fad12SPeter Brune     snes->iter = i+1;
901e04113cfSBarry Smith     ierr       = PetscObjectSAWsGrantAccess((PetscObject)snes);CHKERRQ(ierr);
902a71f0d7dSBarry Smith     ierr       = SNESLogConvergenceHistory(snes,snes->norm,0);CHKERRQ(ierr);
903c90fad12SPeter Brune     ierr       = SNESMonitor(snes,snes->iter,snes->norm);CHKERRQ(ierr);
904c90fad12SPeter Brune     /* Test for convergence */
90566585501SPeter Brune     if (isFine) {
906b9c2fdf1SPeter Brune       ierr = (*snes->ops->converged)(snes,snes->iter,0.0,0.0,snes->norm,&snes->reason,snes->cnvP);CHKERRQ(ierr);
907c90fad12SPeter Brune       if (snes->reason) break;
908fe6f9142SPeter Brune     }
90966585501SPeter Brune   }
910fe6f9142SPeter Brune   if (i == maxits) {
911fe6f9142SPeter Brune     ierr = PetscInfo1(snes, "Maximum number of iterations has been reached: %D\n", maxits);CHKERRQ(ierr);
912fe6f9142SPeter Brune     if (!snes->reason) snes->reason = SNES_DIVERGED_MAX_IT;
913fe6f9142SPeter Brune   }
914421d9b32SPeter Brune   PetscFunctionReturn(0);
915421d9b32SPeter Brune }
91640244768SBarry Smith 
91740244768SBarry Smith /*MC
91840244768SBarry Smith 
91940244768SBarry Smith SNESFAS - Full Approximation Scheme nonlinear multigrid solver.
92040244768SBarry Smith 
92140244768SBarry Smith    The nonlinear problem is solved by correction using coarse versions
92240244768SBarry Smith    of the nonlinear problem.  This problem is perturbed so that a projected
92340244768SBarry Smith    solution of the fine problem elicits no correction from the coarse problem.
92440244768SBarry Smith 
92540244768SBarry Smith Options Database:
92640244768SBarry Smith +   -snes_fas_levels -  The number of levels
92740244768SBarry Smith .   -snes_fas_cycles<1> -  The number of cycles -- 1 for V, 2 for W
92840244768SBarry Smith .   -snes_fas_type<additive,multiplicative,full,kaskade>  -  Additive or multiplicative cycle
92940244768SBarry Smith .   -snes_fas_galerkin<PETSC_FALSE> -  Form coarse problems by projection back upon the fine problem
93040244768SBarry Smith .   -snes_fas_smoothup<1> -  The number of iterations of the post-smoother
93140244768SBarry Smith .   -snes_fas_smoothdown<1> -  The number of iterations of the pre-smoother
93240244768SBarry Smith .   -snes_fas_monitor -  Monitor progress of all of the levels
93340244768SBarry Smith .   -snes_fas_full_downsweep<PETSC_FALSE> - call the downsmooth on the initial downsweep of full FAS
93440244768SBarry Smith .   -fas_levels_snes_ -  SNES options for all smoothers
93540244768SBarry Smith .   -fas_levels_cycle_snes_ -  SNES options for all cycles
93640244768SBarry Smith .   -fas_levels_i_snes_ -  SNES options for the smoothers on level i
93740244768SBarry Smith .   -fas_levels_i_cycle_snes_ - SNES options for the cycle on level i
93840244768SBarry Smith -   -fas_coarse_snes_ -  SNES options for the coarsest smoother
93940244768SBarry Smith 
94040244768SBarry Smith Notes:
94140244768SBarry Smith    The organization of the FAS solver is slightly different from the organization of PCMG
94240244768SBarry Smith    As each level has smoother SNES instances(down and potentially up) and a cycle SNES instance.
94340244768SBarry Smith    The cycle SNES instance may be used for monitoring convergence on a particular level.
94440244768SBarry Smith 
94540244768SBarry Smith Level: beginner
94640244768SBarry Smith 
94740244768SBarry Smith    References:
94840244768SBarry Smith . 1. -  Peter R. Brune, Matthew G. Knepley, Barry F. Smith, and Xuemin Tu, "Composing Scalable Nonlinear Algebraic Solvers",
94940244768SBarry Smith    SIAM Review, 57(4), 2015
95040244768SBarry Smith 
95140244768SBarry Smith .seealso: PCMG, SNESCreate(), SNES, SNESSetType(), SNESType (for list of available types)
95240244768SBarry Smith M*/
95340244768SBarry Smith 
95440244768SBarry Smith PETSC_EXTERN PetscErrorCode SNESCreate_FAS(SNES snes)
95540244768SBarry Smith {
95640244768SBarry Smith   SNES_FAS       *fas;
95740244768SBarry Smith   PetscErrorCode ierr;
95840244768SBarry Smith 
95940244768SBarry Smith   PetscFunctionBegin;
96040244768SBarry Smith   snes->ops->destroy        = SNESDestroy_FAS;
96140244768SBarry Smith   snes->ops->setup          = SNESSetUp_FAS;
96240244768SBarry Smith   snes->ops->setfromoptions = SNESSetFromOptions_FAS;
96340244768SBarry Smith   snes->ops->view           = SNESView_FAS;
96440244768SBarry Smith   snes->ops->solve          = SNESSolve_FAS;
96540244768SBarry Smith   snes->ops->reset          = SNESReset_FAS;
96640244768SBarry Smith 
96740244768SBarry Smith   snes->usesksp = PETSC_FALSE;
968efd4aadfSBarry Smith   snes->usesnpc = PETSC_FALSE;
96940244768SBarry Smith 
97040244768SBarry Smith   if (!snes->tolerancesset) {
97140244768SBarry Smith     snes->max_funcs = 30000;
97240244768SBarry Smith     snes->max_its   = 10000;
97340244768SBarry Smith   }
97440244768SBarry Smith 
9754fc747eaSLawrence Mitchell   snes->alwayscomputesfinalresidual = PETSC_TRUE;
9764fc747eaSLawrence Mitchell 
97740244768SBarry Smith   ierr = PetscNewLog(snes,&fas);CHKERRQ(ierr);
97840244768SBarry Smith 
97940244768SBarry Smith   snes->data                  = (void*) fas;
98040244768SBarry Smith   fas->level                  = 0;
98140244768SBarry Smith   fas->levels                 = 1;
98240244768SBarry Smith   fas->n_cycles               = 1;
98340244768SBarry Smith   fas->max_up_it              = 1;
98440244768SBarry Smith   fas->max_down_it            = 1;
98540244768SBarry Smith   fas->smoothu                = NULL;
98640244768SBarry Smith   fas->smoothd                = NULL;
98740244768SBarry Smith   fas->next                   = NULL;
98840244768SBarry Smith   fas->previous               = NULL;
98940244768SBarry Smith   fas->fine                   = snes;
99040244768SBarry Smith   fas->interpolate            = NULL;
99140244768SBarry Smith   fas->restrct                = NULL;
99240244768SBarry Smith   fas->inject                 = NULL;
99340244768SBarry Smith   fas->usedmfornumberoflevels = PETSC_FALSE;
99440244768SBarry Smith   fas->fastype                = SNES_FAS_MULTIPLICATIVE;
99540244768SBarry Smith   fas->full_downsweep         = PETSC_FALSE;
99640244768SBarry Smith 
99740244768SBarry Smith   fas->eventsmoothsetup    = 0;
99840244768SBarry Smith   fas->eventsmoothsolve    = 0;
99940244768SBarry Smith   fas->eventresidual       = 0;
100040244768SBarry Smith   fas->eventinterprestrict = 0;
100140244768SBarry Smith   PetscFunctionReturn(0);
100240244768SBarry Smith }
1003