xref: /petsc/src/snes/impls/fas/fasfunc.c (revision 2bf68e3e0f2a61f71e7c65bee250bfa1c8ce0cdb)
1 #include <../src/snes/impls/fas/fasimpls.h> /*I  "petscsnes.h"  I*/
2 
3 
4 extern PetscErrorCode SNESFASCycleCreateSmoother_Private(SNES, SNES*);
5 
6 /* -------------- functions called on the fine level -------------- */
7 
8 #undef __FUNCT__
9 #define __FUNCT__ "SNESFASSetType"
10 /*@
11     SNESFASSetType - Sets the update and correction type used for FAS.
12 
13    Logically Collective
14 
15 Input Parameters:
16 + snes  - FAS context
17 - fastype  - SNES_FAS_ADDITIVE, SNES_FAS_MULTIPLICATIVE, SNES_FAS_FULL, or SNES_FAS_KASKADE
18 
19 Level: intermediate
20 
21 .seealso: PCMGSetType()
22 @*/
23 PetscErrorCode  SNESFASSetType(SNES snes,SNESFASType fastype)
24 {
25   SNES_FAS       *fas = (SNES_FAS*)snes->data;
26   PetscErrorCode ierr;
27 
28   PetscFunctionBegin;
29   PetscValidHeaderSpecific(snes,SNES_CLASSID,1);
30   PetscValidLogicalCollectiveEnum(snes,fastype,2);
31   fas->fastype = fastype;
32   if (fas->next) {
33     ierr = SNESFASSetType(fas->next, fastype);CHKERRQ(ierr);
34   }
35   PetscFunctionReturn(0);
36 }
37 
38 
39 #undef __FUNCT__
40 #define __FUNCT__ "SNESFASGetType"
41 /*@
42 SNESFASGetType - Sets the update and correction type used for FAS.
43 
44 Logically Collective
45 
46 Input Parameters:
47 . snes - FAS context
48 
49 Output Parameters:
50 . fastype - SNES_FAS_ADDITIVE or SNES_FAS_MULTIPLICATIVE
51 
52 Level: intermediate
53 
54 .seealso: PCMGSetType()
55 @*/
56 PetscErrorCode  SNESFASGetType(SNES snes,SNESFASType *fastype)
57 {
58   SNES_FAS *fas = (SNES_FAS*)snes->data;
59 
60   PetscFunctionBegin;
61   PetscValidHeaderSpecific(snes,SNES_CLASSID,1);
62   PetscValidPointer(fastype, 2);
63   *fastype = fas->fastype;
64   PetscFunctionReturn(0);
65 }
66 
67 #undef __FUNCT__
68 #define __FUNCT__ "SNESFASSetLevels"
69 /*@C
70    SNESFASSetLevels - Sets the number of levels to use with FAS.
71    Must be called before any other FAS routine.
72 
73    Input Parameters:
74 +  snes   - the snes context
75 .  levels - the number of levels
76 -  comms  - optional communicators for each level; this is to allow solving the coarser
77             problems on smaller sets of processors.
78 
79    Level: intermediate
80 
81    Notes:
82      If the number of levels is one then the multigrid uses the -fas_levels prefix
83   for setting the level options rather than the -fas_coarse prefix.
84 
85 .keywords: FAS, MG, set, levels, multigrid
86 
87 .seealso: SNESFASGetLevels()
88 @*/
89 PetscErrorCode SNESFASSetLevels(SNES snes, PetscInt levels, MPI_Comm * comms)
90 {
91   PetscErrorCode ierr;
92   PetscInt       i;
93   const char     *optionsprefix;
94   char           tprefix[128];
95   SNES_FAS       *fas = (SNES_FAS*)snes->data;
96   SNES           prevsnes;
97   MPI_Comm       comm;
98 
99   PetscFunctionBegin;
100   ierr = PetscObjectGetComm((PetscObject)snes,&comm);CHKERRQ(ierr);
101   if (levels == fas->levels) {
102     if (!comms) PetscFunctionReturn(0);
103   }
104   /* user has changed the number of levels; reset */
105   ierr = SNESReset(snes);CHKERRQ(ierr);
106   /* destroy any coarser levels if necessary */
107   if (fas->next) SNESDestroy(&fas->next);CHKERRQ(ierr);
108   fas->next     = NULL;
109   fas->previous = NULL;
110   prevsnes      = snes;
111   /* setup the finest level */
112   ierr = SNESGetOptionsPrefix(snes, &optionsprefix);CHKERRQ(ierr);
113   ierr = PetscObjectComposedDataSetInt((PetscObject) snes, PetscMGLevelId, levels-1);CHKERRQ(ierr);
114   for (i = levels - 1; i >= 0; i--) {
115     if (comms) comm = comms[i];
116     fas->level  = i;
117     fas->levels = levels;
118     fas->fine   = snes;
119     fas->next   = NULL;
120     if (i > 0) {
121       ierr = SNESCreate(comm, &fas->next);CHKERRQ(ierr);
122       ierr = SNESGetOptionsPrefix(fas->fine, &optionsprefix);CHKERRQ(ierr);
123       sprintf(tprefix,"fas_levels_%d_cycle_",(int)fas->level);
124       ierr = SNESAppendOptionsPrefix(fas->next,optionsprefix);CHKERRQ(ierr);
125       ierr = SNESAppendOptionsPrefix(fas->next,tprefix);CHKERRQ(ierr);
126       ierr = SNESSetType(fas->next, SNESFAS);CHKERRQ(ierr);
127       ierr = SNESSetTolerances(fas->next, fas->next->abstol, fas->next->rtol, fas->next->stol, fas->n_cycles, fas->next->max_funcs);CHKERRQ(ierr);
128       ierr = PetscObjectIncrementTabLevel((PetscObject)fas->next, (PetscObject)snes, levels - i);CHKERRQ(ierr);
129       ierr = PetscObjectComposedDataSetInt((PetscObject) fas->next, PetscMGLevelId, i-1);CHKERRQ(ierr);
130 
131       ((SNES_FAS*)fas->next->data)->previous = prevsnes;
132 
133       prevsnes = fas->next;
134       fas      = (SNES_FAS*)prevsnes->data;
135     }
136   }
137   PetscFunctionReturn(0);
138 }
139 
140 
141 #undef __FUNCT__
142 #define __FUNCT__ "SNESFASGetLevels"
143 /*@
144    SNESFASGetLevels - Gets the number of levels in a FAS, including fine and coarse grids
145 
146    Input Parameter:
147 .  snes - the nonlinear solver context
148 
149    Output parameter:
150 .  levels - the number of levels
151 
152    Level: advanced
153 
154 .keywords: MG, get, levels, multigrid
155 
156 .seealso: SNESFASSetLevels(), PCMGGetLevels()
157 @*/
158 PetscErrorCode SNESFASGetLevels(SNES snes, PetscInt *levels)
159 {
160   SNES_FAS * fas = (SNES_FAS*)snes->data;
161 
162   PetscFunctionBegin;
163   *levels = fas->levels;
164   PetscFunctionReturn(0);
165 }
166 
167 
168 #undef __FUNCT__
169 #define __FUNCT__ "SNESFASGetCycleSNES"
170 /*@
171    SNESFASGetCycleSNES - Gets the SNES corresponding to a particular
172    level of the FAS hierarchy.
173 
174    Input Parameters:
175 +  snes    - the multigrid context
176    level   - the level to get
177 -  lsnes   - whether to use the nonlinear smoother or not
178 
179    Level: advanced
180 
181 .keywords: FAS, MG, set, cycles, Gauss-Seidel, multigrid
182 
183 .seealso: SNESFASSetLevels(), SNESFASGetLevels()
184 @*/
185 PetscErrorCode SNESFASGetCycleSNES(SNES snes,PetscInt level,SNES *lsnes)
186 {
187   SNES_FAS *fas = (SNES_FAS*)snes->data;
188   PetscInt i;
189 
190   PetscFunctionBegin;
191   if (level > fas->levels-1) SETERRQ2(PetscObjectComm((PetscObject)snes),PETSC_ERR_ARG_OUTOFRANGE,"Requested level %D from SNESFAS containing %D levels",level,fas->levels);
192   if (fas->level !=  fas->levels - 1) SETERRQ2(PetscObjectComm((PetscObject)snes),PETSC_ERR_ARG_OUTOFRANGE,"SNESFASGetCycleSNES may only be called on the finest-level SNES.",level,fas->level);
193 
194   *lsnes = snes;
195   for (i = fas->level; i > level; i--) {
196     *lsnes = fas->next;
197     fas    = (SNES_FAS*)(*lsnes)->data;
198   }
199   if (fas->level != level) SETERRQ(PetscObjectComm((PetscObject)snes),PETSC_ERR_PLIB,"SNESFAS level hierarchy corrupt");
200   PetscFunctionReturn(0);
201 }
202 
203 #undef __FUNCT__
204 #define __FUNCT__ "SNESFASSetNumberSmoothUp"
205 /*@
206    SNESFASSetNumberSmoothUp - Sets the number of post-smoothing steps to
207    use on all levels.
208 
209    Logically Collective on SNES
210 
211    Input Parameters:
212 +  snes - the multigrid context
213 -  n    - the number of smoothing steps
214 
215    Options Database Key:
216 .  -snes_fas_smoothup <n> - Sets number of pre-smoothing steps
217 
218    Level: advanced
219 
220 .keywords: FAS, MG, smooth, down, pre-smoothing, steps, multigrid
221 
222 .seealso: SNESFASSetNumberSmoothDown()
223 @*/
224 PetscErrorCode SNESFASSetNumberSmoothUp(SNES snes, PetscInt n)
225 {
226   SNES_FAS       *fas =  (SNES_FAS*)snes->data;
227   PetscErrorCode ierr;
228 
229   PetscFunctionBegin;
230   fas->max_up_it = n;
231   if (!fas->smoothu && fas->level != 0) {
232     ierr = SNESFASCycleCreateSmoother_Private(snes, &fas->smoothu);CHKERRQ(ierr);
233   }
234   if (fas->smoothu) {
235     ierr = SNESSetTolerances(fas->smoothu, fas->smoothu->abstol, fas->smoothu->rtol, fas->smoothu->stol, n, fas->smoothu->max_funcs);CHKERRQ(ierr);
236   }
237   if (fas->next) {
238     ierr = SNESFASSetNumberSmoothUp(fas->next, n);CHKERRQ(ierr);
239   }
240   PetscFunctionReturn(0);
241 }
242 
243 #undef __FUNCT__
244 #define __FUNCT__ "SNESFASSetNumberSmoothDown"
245 /*@
246    SNESFASSetNumberSmoothDown - Sets the number of pre-smoothing steps to
247    use on all levels.
248 
249    Logically Collective on SNES
250 
251    Input Parameters:
252 +  snes - the multigrid context
253 -  n    - the number of smoothing steps
254 
255    Options Database Key:
256 .  -snes_fas_smoothdown <n> - Sets number of pre-smoothing steps
257 
258    Level: advanced
259 
260 .keywords: FAS, MG, smooth, down, pre-smoothing, steps, multigrid
261 
262 .seealso: SNESFASSetNumberSmoothUp()
263 @*/
264 PetscErrorCode SNESFASSetNumberSmoothDown(SNES snes, PetscInt n)
265 {
266   SNES_FAS       *fas =  (SNES_FAS*)snes->data;
267   PetscErrorCode ierr = 0;
268 
269   PetscFunctionBegin;
270   if (!fas->smoothd) {
271     ierr = SNESFASCycleCreateSmoother_Private(snes, &fas->smoothd);CHKERRQ(ierr);
272   }
273   ierr = SNESSetTolerances(fas->smoothd, fas->smoothd->abstol, fas->smoothd->rtol, fas->smoothd->stol, n, fas->smoothd->max_funcs);CHKERRQ(ierr);
274 
275   fas->max_down_it = n;
276   if (fas->next) {
277     ierr = SNESFASSetNumberSmoothDown(fas->next, n);CHKERRQ(ierr);
278   }
279   PetscFunctionReturn(0);
280 }
281 
282 
283 #undef __FUNCT__
284 #define __FUNCT__ "SNESFASSetContinuation"
285 /*@
286    SNESFASSetContinuation - Sets the FAS cycle to default to exact Newton solves on the upsweep
287 
288    Logically Collective on SNES
289 
290    Input Parameters:
291 +  snes - the multigrid context
292 -  n    - the number of smoothing steps
293 
294    Options Database Key:
295 .  -snes_fas_continuation - sets continuation to true
296 
297    Level: advanced
298 
299    Notes: This sets the prefix on the upsweep smoothers to -fas_continuation
300 
301 .keywords: FAS, MG, smoother, continuation
302 
303 .seealso: SNESFAS
304 @*/
305 PetscErrorCode SNESFASSetContinuation(SNES snes,PetscBool continuation)
306 {
307   const char     *optionsprefix;
308   char           tprefix[128];
309   SNES_FAS       *fas =  (SNES_FAS*)snes->data;
310   PetscErrorCode ierr = 0;
311 
312   PetscFunctionBegin;
313   ierr = SNESGetOptionsPrefix(fas->fine, &optionsprefix);CHKERRQ(ierr);
314   if (!fas->smoothu) {
315     ierr = SNESFASCycleCreateSmoother_Private(snes, &fas->smoothu);CHKERRQ(ierr);
316   }
317   sprintf(tprefix,"fas_levels_continuation_");
318   ierr = SNESSetOptionsPrefix(fas->smoothu, optionsprefix);CHKERRQ(ierr);
319   ierr = SNESAppendOptionsPrefix(fas->smoothu, tprefix);CHKERRQ(ierr);
320   ierr = SNESSetType(fas->smoothu,SNESNEWTONLS);CHKERRQ(ierr);
321   ierr = SNESSetTolerances(fas->smoothu,fas->fine->abstol,fas->fine->rtol,fas->fine->stol,50,100);CHKERRQ(ierr);
322   fas->continuation = continuation;
323   if (fas->next) {
324     ierr = SNESFASSetContinuation(fas->next,continuation);CHKERRQ(ierr);
325   }
326   PetscFunctionReturn(0);
327 }
328 
329 
330 #undef __FUNCT__
331 #define __FUNCT__ "SNESFASSetCycles"
332 /*@
333    SNESFASSetCycles - Sets the number of FAS multigrid cycles to use each time a grid is visited.  Use SNESFASSetCyclesOnLevel() for more
334    complicated cycling.
335 
336    Logically Collective on SNES
337 
338    Input Parameters:
339 +  snes   - the multigrid context
340 -  cycles - the number of cycles -- 1 for V-cycle, 2 for W-cycle
341 
342    Options Database Key:
343 .  -snes_fas_cycles 1 or 2
344 
345    Level: advanced
346 
347 .keywords: MG, set, cycles, V-cycle, W-cycle, multigrid
348 
349 .seealso: SNESFASSetCyclesOnLevel()
350 @*/
351 PetscErrorCode SNESFASSetCycles(SNES snes, PetscInt cycles)
352 {
353   SNES_FAS       *fas = (SNES_FAS*)snes->data;
354   PetscErrorCode ierr;
355   PetscBool      isFine;
356 
357   PetscFunctionBegin;
358   ierr = SNESFASCycleIsFine(snes, &isFine);CHKERRQ(ierr);
359 
360   fas->n_cycles = cycles;
361   if (!isFine) {
362     ierr = SNESSetTolerances(snes, snes->abstol, snes->rtol, snes->stol, cycles, snes->max_funcs);CHKERRQ(ierr);
363   }
364   if (fas->next) {
365     ierr = SNESFASSetCycles(fas->next, cycles);CHKERRQ(ierr);
366   }
367   PetscFunctionReturn(0);
368 }
369 
370 
371 #undef __FUNCT__
372 #define __FUNCT__ "SNESFASSetMonitor"
373 /*@
374    SNESFASSetMonitor - Sets the method-specific cycle monitoring
375 
376    Logically Collective on SNES
377 
378    Input Parameters:
379 +  snes   - the FAS context
380 .  vf     - viewer and format structure (may be NULL if flg is FALSE)
381 -  flg    - monitor or not
382 
383    Level: advanced
384 
385 .keywords: FAS, monitor
386 
387 .seealso: SNESFASSetCyclesOnLevel()
388 @*/
389 PetscErrorCode SNESFASSetMonitor(SNES snes, PetscViewerAndFormat *vf, PetscBool flg)
390 {
391   SNES_FAS       *fas = (SNES_FAS*)snes->data;
392   PetscErrorCode ierr;
393   PetscBool      isFine;
394   PetscInt       i, levels = fas->levels;
395   SNES           levelsnes;
396 
397   PetscFunctionBegin;
398   ierr = SNESFASCycleIsFine(snes, &isFine);CHKERRQ(ierr);
399   if (isFine) {
400     for (i = 0; i < levels; i++) {
401       ierr = SNESFASGetCycleSNES(snes, i, &levelsnes);CHKERRQ(ierr);
402       fas  = (SNES_FAS*)levelsnes->data;
403       if (flg) {
404         /* set the monitors for the upsmoother and downsmoother */
405         ierr = SNESMonitorCancel(levelsnes);CHKERRQ(ierr);
406         /* Only register destroy on finest level */
407         ierr = SNESMonitorSet(levelsnes,(PetscErrorCode (*)(SNES,PetscInt,PetscReal,void*))SNESMonitorDefault,vf,(!i ? (PetscErrorCode (*)(void**))PetscViewerAndFormatDestroy : NULL));CHKERRQ(ierr);
408       } else if (i != fas->levels - 1) {
409         /* unset the monitors on the coarse levels */
410         ierr = SNESMonitorCancel(levelsnes);CHKERRQ(ierr);
411       }
412     }
413   }
414   PetscFunctionReturn(0);
415 }
416 
417 #undef __FUNCT__
418 #define __FUNCT__ "SNESFASSetLog"
419 /*@
420    SNESFASSetLog - Sets or unsets time logging for various FAS stages on all levels
421 
422    Logically Collective on SNES
423 
424    Input Parameters:
425 +  snes   - the FAS context
426 -  flg    - monitor or not
427 
428    Level: advanced
429 
430 .keywords: FAS, logging
431 
432 .seealso: SNESFASSetMonitor()
433 @*/
434 PetscErrorCode SNESFASSetLog(SNES snes, PetscBool flg)
435 {
436   SNES_FAS       *fas = (SNES_FAS*)snes->data;
437   PetscErrorCode ierr;
438   PetscBool      isFine;
439   PetscInt       i, levels = fas->levels;
440   SNES           levelsnes;
441   char           eventname[128];
442 
443   PetscFunctionBegin;
444   ierr = SNESFASCycleIsFine(snes, &isFine);CHKERRQ(ierr);
445   if (isFine) {
446     for (i = 0; i < levels; i++) {
447       ierr = SNESFASGetCycleSNES(snes, i, &levelsnes);CHKERRQ(ierr);
448       fas  = (SNES_FAS*)levelsnes->data;
449       if (flg) {
450         sprintf(eventname,"FASSetup %d",(int)i);
451         ierr = PetscLogEventRegister(eventname,((PetscObject)snes)->classid,&fas->eventsmoothsetup);CHKERRQ(ierr);
452         sprintf(eventname,"FASSmooth %d",(int)i);
453         ierr = PetscLogEventRegister(eventname,((PetscObject)snes)->classid,&fas->eventsmoothsolve);CHKERRQ(ierr);
454         sprintf(eventname,"FASResid %d",(int)i);
455         ierr = PetscLogEventRegister(eventname,((PetscObject)snes)->classid,&fas->eventresidual);CHKERRQ(ierr);
456         if (i) {
457           sprintf(eventname,"FASInterp %d",(int)i);
458           ierr = PetscLogEventRegister(eventname,((PetscObject)snes)->classid,&fas->eventinterprestrict);CHKERRQ(ierr);
459         }
460       } else {
461         fas->eventsmoothsetup    = 0;
462         fas->eventsmoothsolve    = 0;
463         fas->eventresidual       = 0;
464         fas->eventinterprestrict = 0;
465       }
466     }
467   }
468   PetscFunctionReturn(0);
469 }
470 
471 #undef __FUNCT__
472 #define __FUNCT__ "SNESFASCycleCreateSmoother_Private"
473 /*
474 Creates the default smoother type.
475 
476 This is SNESNRICHARDSON on each fine level and SNESNEWTONLS on the coarse level.
477 
478  */
479 PetscErrorCode SNESFASCycleCreateSmoother_Private(SNES snes, SNES *smooth)
480 {
481   SNES_FAS       *fas;
482   const char     *optionsprefix;
483   char           tprefix[128];
484   PetscErrorCode ierr;
485   SNES           nsmooth;
486 
487   PetscFunctionBegin;
488   PetscValidHeaderSpecific(snes,SNES_CLASSID,1);
489   fas  = (SNES_FAS*)snes->data;
490   ierr = SNESGetOptionsPrefix(fas->fine, &optionsprefix);CHKERRQ(ierr);
491   /* create the default smoother */
492   ierr = SNESCreate(PetscObjectComm((PetscObject)snes), &nsmooth);CHKERRQ(ierr);
493   if (fas->level == 0) {
494     sprintf(tprefix,"fas_coarse_");
495     ierr = SNESAppendOptionsPrefix(nsmooth, optionsprefix);CHKERRQ(ierr);
496     ierr = SNESAppendOptionsPrefix(nsmooth, tprefix);CHKERRQ(ierr);
497     ierr = SNESSetType(nsmooth, SNESNEWTONLS);CHKERRQ(ierr);
498     ierr = SNESSetTolerances(nsmooth, nsmooth->abstol, nsmooth->rtol, nsmooth->stol, nsmooth->max_its, nsmooth->max_funcs);CHKERRQ(ierr);
499   } else {
500     sprintf(tprefix,"fas_levels_%d_",(int)fas->level);
501     ierr = SNESAppendOptionsPrefix(nsmooth, optionsprefix);CHKERRQ(ierr);
502     ierr = SNESAppendOptionsPrefix(nsmooth, tprefix);CHKERRQ(ierr);
503     ierr = SNESSetType(nsmooth, SNESNRICHARDSON);CHKERRQ(ierr);
504     ierr = SNESSetTolerances(nsmooth, 0.0, 0.0, 0.0, fas->max_down_it, nsmooth->max_funcs);CHKERRQ(ierr);
505   }
506   ierr    = PetscObjectIncrementTabLevel((PetscObject)nsmooth, (PetscObject)snes, 1);CHKERRQ(ierr);
507   ierr    = PetscLogObjectParent((PetscObject)snes,(PetscObject)nsmooth);CHKERRQ(ierr);
508   ierr    = PetscObjectCopyFortranFunctionPointers((PetscObject)snes, (PetscObject)nsmooth);CHKERRQ(ierr);
509   ierr    = PetscObjectComposedDataSetInt((PetscObject) nsmooth, PetscMGLevelId, fas->level);CHKERRQ(ierr);
510   *smooth = nsmooth;
511   PetscFunctionReturn(0);
512 }
513 
514 /* ------------- Functions called on a particular level ----------------- */
515 
516 #undef __FUNCT__
517 #define __FUNCT__ "SNESFASCycleSetCycles"
518 /*@
519    SNESFASCycleSetCycles - Sets the number of cycles on a particular level.
520 
521    Logically Collective on SNES
522 
523    Input Parameters:
524 +  snes   - the multigrid context
525 .  level  - the level to set the number of cycles on
526 -  cycles - the number of cycles -- 1 for V-cycle, 2 for W-cycle
527 
528    Level: advanced
529 
530 .keywords: SNES, FAS, set, cycles, V-cycle, W-cycle, multigrid
531 
532 .seealso: SNESFASSetCycles()
533 @*/
534 PetscErrorCode SNESFASCycleSetCycles(SNES snes, PetscInt cycles)
535 {
536   SNES_FAS       *fas =  (SNES_FAS*)snes->data;
537   PetscErrorCode ierr;
538 
539   PetscFunctionBegin;
540   fas->n_cycles = cycles;
541   ierr          = SNESSetTolerances(snes, snes->abstol, snes->rtol, snes->stol, cycles, snes->max_funcs);CHKERRQ(ierr);
542   PetscFunctionReturn(0);
543 }
544 
545 
546 #undef __FUNCT__
547 #define __FUNCT__ "SNESFASCycleGetSmoother"
548 /*@
549    SNESFASCycleGetSmoother - Gets the smoother on a particular cycle level.
550 
551    Logically Collective on SNES
552 
553    Input Parameters:
554 .  snes   - the multigrid context
555 
556    Output Parameters:
557 .  smooth - the smoother
558 
559    Level: advanced
560 
561 .keywords: SNES, FAS, get, smoother, multigrid
562 
563 .seealso: SNESFASCycleGetSmootherUp(), SNESFASCycleGetSmootherDown()
564 @*/
565 PetscErrorCode SNESFASCycleGetSmoother(SNES snes, SNES *smooth)
566 {
567   SNES_FAS *fas;
568 
569   PetscFunctionBegin;
570   PetscValidHeaderSpecific(snes,SNES_CLASSID,1);
571   fas     = (SNES_FAS*)snes->data;
572   *smooth = fas->smoothd;
573   PetscFunctionReturn(0);
574 }
575 #undef __FUNCT__
576 #define __FUNCT__ "SNESFASCycleGetSmootherUp"
577 /*@
578    SNESFASCycleGetSmootherUp - Gets the up smoother on a particular cycle level.
579 
580    Logically Collective on SNES
581 
582    Input Parameters:
583 .  snes   - the multigrid context
584 
585    Output Parameters:
586 .  smoothu - the smoother
587 
588    Notes:
589    Returns the downsmoother if no up smoother is available.  This enables transparent
590    default behavior in the process of the solve.
591 
592    Level: advanced
593 
594 .keywords: SNES, FAS, get, smoother, multigrid
595 
596 .seealso: SNESFASCycleGetSmoother(), SNESFASCycleGetSmootherDown()
597 @*/
598 PetscErrorCode SNESFASCycleGetSmootherUp(SNES snes, SNES *smoothu)
599 {
600   SNES_FAS *fas;
601 
602   PetscFunctionBegin;
603   PetscValidHeaderSpecific(snes,SNES_CLASSID,1);
604   fas = (SNES_FAS*)snes->data;
605   if (!fas->smoothu) *smoothu = fas->smoothd;
606   else *smoothu = fas->smoothu;
607   PetscFunctionReturn(0);
608 }
609 
610 #undef __FUNCT__
611 #define __FUNCT__ "SNESFASCycleGetSmootherDown"
612 /*@
613    SNESFASCycleGetSmootherDown - Gets the down smoother on a particular cycle level.
614 
615    Logically Collective on SNES
616 
617    Input Parameters:
618 .  snes   - the multigrid context
619 
620    Output Parameters:
621 .  smoothd - the smoother
622 
623    Level: advanced
624 
625 .keywords: SNES, FAS, get, smoother, multigrid
626 
627 .seealso: SNESFASCycleGetSmootherUp(), SNESFASCycleGetSmoother()
628 @*/
629 PetscErrorCode SNESFASCycleGetSmootherDown(SNES snes, SNES *smoothd)
630 {
631   SNES_FAS *fas;
632 
633   PetscFunctionBegin;
634   PetscValidHeaderSpecific(snes,SNES_CLASSID,1);
635   fas      = (SNES_FAS*)snes->data;
636   *smoothd = fas->smoothd;
637   PetscFunctionReturn(0);
638 }
639 
640 
641 #undef __FUNCT__
642 #define __FUNCT__ "SNESFASCycleGetCorrection"
643 /*@
644    SNESFASCycleGetCorrection - Gets the coarse correction FAS context for this level
645 
646    Logically Collective on SNES
647 
648    Input Parameters:
649 .  snes   - the multigrid context
650 
651    Output Parameters:
652 .  correction - the coarse correction on this level
653 
654    Notes:
655    Returns NULL on the coarsest level.
656 
657    Level: advanced
658 
659 .keywords: SNES, FAS, get, smoother, multigrid
660 
661 .seealso: SNESFASCycleGetSmootherUp(), SNESFASCycleGetSmoother()
662 @*/
663 PetscErrorCode SNESFASCycleGetCorrection(SNES snes, SNES *correction)
664 {
665   SNES_FAS *fas;
666 
667   PetscFunctionBegin;
668   PetscValidHeaderSpecific(snes,SNES_CLASSID,1);
669   fas         = (SNES_FAS*)snes->data;
670   *correction = fas->next;
671   PetscFunctionReturn(0);
672 }
673 
674 #undef __FUNCT__
675 #define __FUNCT__ "SNESFASCycleGetInterpolation"
676 /*@
677    SNESFASCycleGetInterpolation - Gets the interpolation on this level
678 
679    Logically Collective on SNES
680 
681    Input Parameters:
682 .  snes   - the multigrid context
683 
684    Output Parameters:
685 .  mat    - the interpolation operator on this level
686 
687    Level: developer
688 
689 .keywords: SNES, FAS, get, smoother, multigrid
690 
691 .seealso: SNESFASCycleGetSmootherUp(), SNESFASCycleGetSmoother()
692 @*/
693 PetscErrorCode SNESFASCycleGetInterpolation(SNES snes, Mat *mat)
694 {
695   SNES_FAS *fas;
696 
697   PetscFunctionBegin;
698   PetscValidHeaderSpecific(snes,SNES_CLASSID,1);
699   fas  = (SNES_FAS*)snes->data;
700   *mat = fas->interpolate;
701   PetscFunctionReturn(0);
702 }
703 
704 
705 #undef __FUNCT__
706 #define __FUNCT__ "SNESFASCycleGetRestriction"
707 /*@
708    SNESFASCycleGetRestriction - Gets the restriction on this level
709 
710    Logically Collective on SNES
711 
712    Input Parameters:
713 .  snes   - the multigrid context
714 
715    Output Parameters:
716 .  mat    - the restriction operator on this level
717 
718    Level: developer
719 
720 .keywords: SNES, FAS, get, smoother, multigrid
721 
722 .seealso: SNESFASGetRestriction(), SNESFASCycleGetInterpolation()
723 @*/
724 PetscErrorCode SNESFASCycleGetRestriction(SNES snes, Mat *mat)
725 {
726   SNES_FAS *fas;
727 
728   PetscFunctionBegin;
729   PetscValidHeaderSpecific(snes,SNES_CLASSID,1);
730   fas  = (SNES_FAS*)snes->data;
731   *mat = fas->restrct;
732   PetscFunctionReturn(0);
733 }
734 
735 
736 #undef __FUNCT__
737 #define __FUNCT__ "SNESFASCycleGetInjection"
738 /*@
739    SNESFASCycleGetInjection - Gets the injection on this level
740 
741    Logically Collective on SNES
742 
743    Input Parameters:
744 .  snes   - the multigrid context
745 
746    Output Parameters:
747 .  mat    - the restriction operator on this level
748 
749    Level: developer
750 
751 .keywords: SNES, FAS, get, smoother, multigrid
752 
753 .seealso: SNESFASGetInjection(), SNESFASCycleGetRestriction()
754 @*/
755 PetscErrorCode SNESFASCycleGetInjection(SNES snes, Mat *mat)
756 {
757   SNES_FAS *fas;
758 
759   PetscFunctionBegin;
760   PetscValidHeaderSpecific(snes,SNES_CLASSID,1);
761   fas  = (SNES_FAS*)snes->data;
762   *mat = fas->inject;
763   PetscFunctionReturn(0);
764 }
765 
766 #undef __FUNCT__
767 #define __FUNCT__ "SNESFASCycleGetRScale"
768 /*@
769    SNESFASCycleGetRScale - Gets the injection on this level
770 
771    Logically Collective on SNES
772 
773    Input Parameters:
774 .  snes   - the multigrid context
775 
776    Output Parameters:
777 .  mat    - the restriction operator on this level
778 
779    Level: developer
780 
781 .keywords: SNES, FAS, get, smoother, multigrid
782 
783 .seealso: SNESFASCycleGetRestriction(), SNESFASGetRScale()
784 @*/
785 PetscErrorCode SNESFASCycleGetRScale(SNES snes, Vec *vec)
786 {
787   SNES_FAS *fas;
788 
789   PetscFunctionBegin;
790   PetscValidHeaderSpecific(snes,SNES_CLASSID,1);
791   fas  = (SNES_FAS*)snes->data;
792   *vec = fas->rscale;
793   PetscFunctionReturn(0);
794 }
795 
796 #undef __FUNCT__
797 #define __FUNCT__ "SNESFASCycleIsFine"
798 /*@
799    SNESFASCycleIsFine - Determines if a given cycle is the fine level.
800 
801    Logically Collective on SNES
802 
803    Input Parameters:
804 .  snes   - the FAS context
805 
806    Output Parameters:
807 .  flg - indicates if this is the fine level or not
808 
809    Level: advanced
810 
811 .keywords: SNES, FAS
812 
813 .seealso: SNESFASSetLevels()
814 @*/
815 PetscErrorCode SNESFASCycleIsFine(SNES snes, PetscBool *flg)
816 {
817   SNES_FAS *fas;
818 
819   PetscFunctionBegin;
820   PetscValidHeaderSpecific(snes,SNES_CLASSID,1);
821   fas = (SNES_FAS*)snes->data;
822   if (fas->level == fas->levels - 1) *flg = PETSC_TRUE;
823   else *flg = PETSC_FALSE;
824   PetscFunctionReturn(0);
825 }
826 
827 /* ---------- functions called on the finest level that return level-specific information ---------- */
828 
829 #undef __FUNCT__
830 #define __FUNCT__ "SNESFASSetInterpolation"
831 /*@
832    SNESFASSetInterpolation - Sets the function to be used to calculate the
833    interpolation from l-1 to the lth level
834 
835    Input Parameters:
836 +  snes      - the multigrid context
837 .  mat       - the interpolation operator
838 -  level     - the level (0 is coarsest) to supply [do not supply 0]
839 
840    Level: advanced
841 
842    Notes:
843           Usually this is the same matrix used also to set the restriction
844     for the same level.
845 
846           One can pass in the interpolation matrix or its transpose; PETSc figures
847     out from the matrix size which one it is.
848 
849 .keywords:  FAS, multigrid, set, interpolate, level
850 
851 .seealso: SNESFASSetInjection(), SNESFASSetRestriction(), SNESFASSetRScale()
852 @*/
853 PetscErrorCode SNESFASSetInterpolation(SNES snes, PetscInt level, Mat mat)
854 {
855   SNES_FAS       *fas;
856   PetscErrorCode ierr;
857   SNES           levelsnes;
858 
859   PetscFunctionBegin;
860   ierr = SNESFASGetCycleSNES(snes, level, &levelsnes);CHKERRQ(ierr);
861   fas  = (SNES_FAS*)levelsnes->data;
862   ierr = PetscObjectReference((PetscObject)mat);CHKERRQ(ierr);
863   ierr = MatDestroy(&fas->interpolate);CHKERRQ(ierr);
864 
865   fas->interpolate = mat;
866   PetscFunctionReturn(0);
867 }
868 
869 #undef __FUNCT__
870 #define __FUNCT__ "SNESFASGetInterpolation"
871 /*@
872    SNESFASGetInterpolation - Gets the matrix used to calculate the
873    interpolation from l-1 to the lth level
874 
875    Input Parameters:
876 +  snes      - the multigrid context
877 -  level     - the level (0 is coarsest) to supply [do not supply 0]
878 
879    Output Parameters:
880 .  mat       - the interpolation operator
881 
882    Level: advanced
883 
884 .keywords:  FAS, multigrid, get, interpolate, level
885 
886 .seealso: SNESFASSetInterpolation(), SNESFASGetInjection(), SNESFASGetRestriction(), SNESFASGetRScale()
887 @*/
888 PetscErrorCode SNESFASGetInterpolation(SNES snes, PetscInt level, Mat *mat)
889 {
890   SNES_FAS       *fas;
891   PetscErrorCode ierr;
892   SNES           levelsnes;
893 
894   PetscFunctionBegin;
895   ierr = SNESFASGetCycleSNES(snes, level, &levelsnes);CHKERRQ(ierr);
896   fas  = (SNES_FAS*)levelsnes->data;
897   *mat = fas->interpolate;
898   PetscFunctionReturn(0);
899 }
900 
901 #undef __FUNCT__
902 #define __FUNCT__ "SNESFASSetRestriction"
903 /*@
904    SNESFASSetRestriction - Sets the function to be used to restrict the defect
905    from level l to l-1.
906 
907    Input Parameters:
908 +  snes  - the multigrid context
909 .  mat   - the restriction matrix
910 -  level - the level (0 is coarsest) to supply [Do not supply 0]
911 
912    Level: advanced
913 
914    Notes:
915           Usually this is the same matrix used also to set the interpolation
916     for the same level.
917 
918           One can pass in the interpolation matrix or its transpose; PETSc figures
919     out from the matrix size which one it is.
920 
921          If you do not set this, the transpose of the Mat set with SNESFASSetInterpolation()
922     is used.
923 
924 .keywords: FAS, MG, set, multigrid, restriction, level
925 
926 .seealso: SNESFASSetInterpolation(), SNESFASSetInjection()
927 @*/
928 PetscErrorCode SNESFASSetRestriction(SNES snes, PetscInt level, Mat mat)
929 {
930   SNES_FAS       *fas;
931   PetscErrorCode ierr;
932   SNES           levelsnes;
933 
934   PetscFunctionBegin;
935   ierr = SNESFASGetCycleSNES(snes, level, &levelsnes);CHKERRQ(ierr);
936   fas  = (SNES_FAS*)levelsnes->data;
937   ierr = PetscObjectReference((PetscObject)mat);CHKERRQ(ierr);
938   ierr = MatDestroy(&fas->restrct);CHKERRQ(ierr);
939 
940   fas->restrct = mat;
941   PetscFunctionReturn(0);
942 }
943 
944 #undef __FUNCT__
945 #define __FUNCT__ "SNESFASGetRestriction"
946 /*@
947    SNESFASGetRestriction - Gets the matrix used to calculate the
948    restriction from l to the l-1th level
949 
950    Input Parameters:
951 +  snes      - the multigrid context
952 -  level     - the level (0 is coarsest) to supply [do not supply 0]
953 
954    Output Parameters:
955 .  mat       - the interpolation operator
956 
957    Level: advanced
958 
959 .keywords:  FAS, multigrid, get, restrict, level
960 
961 .seealso: SNESFASSetRestriction(), SNESFASGetInjection(), SNESFASGetInterpolation(), SNESFASGetRScale()
962 @*/
963 PetscErrorCode SNESFASGetRestriction(SNES snes, PetscInt level, Mat *mat)
964 {
965   SNES_FAS       *fas;
966   PetscErrorCode ierr;
967   SNES           levelsnes;
968 
969   PetscFunctionBegin;
970   ierr = SNESFASGetCycleSNES(snes, level, &levelsnes);CHKERRQ(ierr);
971   fas  = (SNES_FAS*)levelsnes->data;
972   *mat = fas->restrct;
973   PetscFunctionReturn(0);
974 }
975 
976 
977 #undef __FUNCT__
978 #define __FUNCT__ "SNESFASSetInjection"
979 /*@
980    SNESFASSetInjection - Sets the function to be used to inject the solution
981    from level l to l-1.
982 
983    Input Parameters:
984  +  snes  - the multigrid context
985 .  mat   - the restriction matrix
986 -  level - the level (0 is coarsest) to supply [Do not supply 0]
987 
988    Level: advanced
989 
990    Notes:
991          If you do not set this, the restriction and rscale is used to
992    project the solution instead.
993 
994 .keywords: FAS, MG, set, multigrid, restriction, level
995 
996 .seealso: SNESFASSetInterpolation(), SNESFASSetRestriction()
997 @*/
998 PetscErrorCode SNESFASSetInjection(SNES snes, PetscInt level, Mat mat)
999 {
1000   SNES_FAS       *fas;
1001   PetscErrorCode ierr;
1002   SNES           levelsnes;
1003 
1004   PetscFunctionBegin;
1005   ierr = SNESFASGetCycleSNES(snes, level, &levelsnes);CHKERRQ(ierr);
1006   fas  = (SNES_FAS*)levelsnes->data;
1007   ierr = PetscObjectReference((PetscObject)mat);CHKERRQ(ierr);
1008   ierr = MatDestroy(&fas->inject);CHKERRQ(ierr);
1009 
1010   fas->inject = mat;
1011   PetscFunctionReturn(0);
1012 }
1013 
1014 
1015 #undef __FUNCT__
1016 #define __FUNCT__ "SNESFASGetInjection"
1017 /*@
1018    SNESFASGetInjection - Gets the matrix used to calculate the
1019    injection from l-1 to the lth level
1020 
1021    Input Parameters:
1022 +  snes      - the multigrid context
1023 -  level     - the level (0 is coarsest) to supply [do not supply 0]
1024 
1025    Output Parameters:
1026 .  mat       - the injection operator
1027 
1028    Level: advanced
1029 
1030 .keywords:  FAS, multigrid, get, restrict, level
1031 
1032 .seealso: SNESFASSetInjection(), SNESFASGetRestriction(), SNESFASGetInterpolation(), SNESFASGetRScale()
1033 @*/
1034 PetscErrorCode SNESFASGetInjection(SNES snes, PetscInt level, Mat *mat)
1035 {
1036   SNES_FAS       *fas;
1037   PetscErrorCode ierr;
1038   SNES           levelsnes;
1039 
1040   PetscFunctionBegin;
1041   ierr = SNESFASGetCycleSNES(snes, level, &levelsnes);CHKERRQ(ierr);
1042   fas  = (SNES_FAS*)levelsnes->data;
1043   *mat = fas->inject;
1044   PetscFunctionReturn(0);
1045 }
1046 
1047 #undef __FUNCT__
1048 #define __FUNCT__ "SNESFASSetRScale"
1049 /*@
1050    SNESFASSetRScale - Sets the scaling factor of the restriction
1051    operator from level l to l-1.
1052 
1053    Input Parameters:
1054 +  snes   - the multigrid context
1055 .  rscale - the restriction scaling
1056 -  level  - the level (0 is coarsest) to supply [Do not supply 0]
1057 
1058    Level: advanced
1059 
1060    Notes:
1061          This is only used in the case that the injection is not set.
1062 
1063 .keywords: FAS, MG, set, multigrid, restriction, level
1064 
1065 .seealso: SNESFASSetInjection(), SNESFASSetRestriction()
1066 @*/
1067 PetscErrorCode SNESFASSetRScale(SNES snes, PetscInt level, Vec rscale)
1068 {
1069   SNES_FAS       *fas;
1070   PetscErrorCode ierr;
1071   SNES           levelsnes;
1072 
1073   PetscFunctionBegin;
1074   ierr = SNESFASGetCycleSNES(snes, level, &levelsnes);CHKERRQ(ierr);
1075   fas  = (SNES_FAS*)levelsnes->data;
1076   ierr = PetscObjectReference((PetscObject)rscale);CHKERRQ(ierr);
1077   ierr = VecDestroy(&fas->rscale);CHKERRQ(ierr);
1078 
1079   fas->rscale = rscale;
1080   PetscFunctionReturn(0);
1081 }
1082 
1083 #undef __FUNCT__
1084 #define __FUNCT__ "SNESFASGetSmoother"
1085 /*@
1086    SNESFASGetSmoother - Gets the default smoother on a level.
1087 
1088    Input Parameters:
1089 +  snes   - the multigrid context
1090 -  level  - the level (0 is coarsest) to supply
1091 
1092    Output Parameters:
1093    smooth  - the smoother
1094 
1095    Level: advanced
1096 
1097 .keywords: FAS, MG, get, multigrid, smoother, level
1098 
1099 .seealso: SNESFASSetInjection(), SNESFASSetRestriction()
1100 @*/
1101 PetscErrorCode SNESFASGetSmoother(SNES snes, PetscInt level, SNES *smooth)
1102 {
1103   SNES_FAS       *fas;
1104   PetscErrorCode ierr;
1105   SNES           levelsnes;
1106 
1107   PetscFunctionBegin;
1108   ierr = SNESFASGetCycleSNES(snes, level, &levelsnes);CHKERRQ(ierr);
1109   fas  = (SNES_FAS*)levelsnes->data;
1110   if (!fas->smoothd) {
1111     ierr = SNESFASCycleCreateSmoother_Private(levelsnes, &fas->smoothd);CHKERRQ(ierr);
1112   }
1113   *smooth = fas->smoothd;
1114   PetscFunctionReturn(0);
1115 }
1116 
1117 #undef __FUNCT__
1118 #define __FUNCT__ "SNESFASGetSmootherDown"
1119 /*@
1120    SNESFASGetSmootherDown - Gets the downsmoother on a level.
1121 
1122    Input Parameters:
1123 +  snes   - the multigrid context
1124 -  level  - the level (0 is coarsest) to supply
1125 
1126    Output Parameters:
1127    smooth  - the smoother
1128 
1129    Level: advanced
1130 
1131 .keywords: FAS, MG, get, multigrid, smoother, level
1132 
1133 .seealso: SNESFASSetInjection(), SNESFASSetRestriction()
1134 @*/
1135 PetscErrorCode SNESFASGetSmootherDown(SNES snes, PetscInt level, SNES *smooth)
1136 {
1137   SNES_FAS       *fas;
1138   PetscErrorCode ierr;
1139   SNES           levelsnes;
1140 
1141   PetscFunctionBegin;
1142   ierr = SNESFASGetCycleSNES(snes, level, &levelsnes);CHKERRQ(ierr);
1143   fas  = (SNES_FAS*)levelsnes->data;
1144   /* if the user chooses to differentiate smoothers, create them both at this point */
1145   if (!fas->smoothd) {
1146     ierr = SNESFASCycleCreateSmoother_Private(levelsnes, &fas->smoothd);CHKERRQ(ierr);
1147   }
1148   if (!fas->smoothu) {
1149     ierr = SNESFASCycleCreateSmoother_Private(levelsnes, &fas->smoothu);CHKERRQ(ierr);
1150   }
1151   *smooth = fas->smoothd;
1152   PetscFunctionReturn(0);
1153 }
1154 
1155 #undef __FUNCT__
1156 #define __FUNCT__ "SNESFASGetSmootherUp"
1157 /*@
1158    SNESFASGetSmootherUp - Gets the upsmoother on a level.
1159 
1160    Input Parameters:
1161 +  snes   - the multigrid context
1162 -  level  - the level (0 is coarsest)
1163 
1164    Output Parameters:
1165    smooth  - the smoother
1166 
1167    Level: advanced
1168 
1169 .keywords: FAS, MG, get, multigrid, smoother, level
1170 
1171 .seealso: SNESFASSetInjection(), SNESFASSetRestriction()
1172 @*/
1173 PetscErrorCode SNESFASGetSmootherUp(SNES snes, PetscInt level, SNES *smooth)
1174 {
1175   SNES_FAS       *fas;
1176   PetscErrorCode ierr;
1177   SNES           levelsnes;
1178 
1179   PetscFunctionBegin;
1180   ierr = SNESFASGetCycleSNES(snes, level, &levelsnes);CHKERRQ(ierr);
1181   fas  = (SNES_FAS*)levelsnes->data;
1182   /* if the user chooses to differentiate smoothers, create them both at this point */
1183   if (!fas->smoothd) {
1184     ierr = SNESFASCycleCreateSmoother_Private(levelsnes, &fas->smoothd);CHKERRQ(ierr);
1185   }
1186   if (!fas->smoothu) {
1187     ierr = SNESFASCycleCreateSmoother_Private(levelsnes, &fas->smoothu);CHKERRQ(ierr);
1188   }
1189   *smooth = fas->smoothu;
1190   PetscFunctionReturn(0);
1191 }
1192 
1193 #undef __FUNCT__
1194 #define __FUNCT__ "SNESFASGetCoarseSolve"
1195 /*@
1196   SNESFASGetCoarseSolve - Gets the coarsest solver.
1197 
1198   Input Parameters:
1199 . snes - the multigrid context
1200 
1201   Output Parameters:
1202 . coarse - the coarse-level solver
1203 
1204   Level: advanced
1205 
1206 .keywords: FAS, MG, get, multigrid, solver, coarse
1207 .seealso: SNESFASSetInjection(), SNESFASSetRestriction()
1208 @*/
1209 PetscErrorCode SNESFASGetCoarseSolve(SNES snes, SNES *coarse)
1210 {
1211   SNES_FAS       *fas;
1212   PetscErrorCode ierr;
1213   SNES           levelsnes;
1214 
1215   PetscFunctionBegin;
1216   ierr = SNESFASGetCycleSNES(snes, 0, &levelsnes);CHKERRQ(ierr);
1217   fas  = (SNES_FAS*)levelsnes->data;
1218   /* if the user chooses to differentiate smoothers, create them both at this point */
1219   if (!fas->smoothd) {
1220     ierr = SNESFASCycleCreateSmoother_Private(levelsnes, &fas->smoothd);CHKERRQ(ierr);
1221   }
1222   *coarse = fas->smoothd;
1223   PetscFunctionReturn(0);
1224 }
1225 
1226 #undef __FUNCT__
1227 #define __FUNCT__ "SNESFASFullSetDownSweep"
1228 /*@
1229    SNESFASFullSetDownSweep - Smooth during the initial downsweep for SNESFAS
1230 
1231    Logically Collective on SNES
1232 
1233    Input Parameters:
1234 +  snes - the multigrid context
1235 -  swp - whether to downsweep or not
1236 
1237    Options Database Key:
1238 .  -snes_fas_full_downsweep - Sets number of pre-smoothing steps
1239 
1240    Level: advanced
1241 
1242 .keywords: FAS, MG, smooth, down, pre-smoothing, steps, multigrid
1243 
1244 .seealso: SNESFASSetNumberSmoothUp()
1245 @*/
1246 PetscErrorCode SNESFASFullSetDownSweep(SNES snes,PetscBool swp)
1247 {
1248   SNES_FAS       *fas =  (SNES_FAS*)snes->data;
1249   PetscErrorCode ierr = 0;
1250 
1251   PetscFunctionBegin;
1252   fas->full_downsweep = swp;
1253   if (fas->next) {
1254     ierr = SNESFASFullSetDownSweep(fas->next,swp);CHKERRQ(ierr);
1255   }
1256   PetscFunctionReturn(0);
1257 }
1258