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