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