1 /* Defines the basic SNES object */ 2 #include <../src/snes/impls/fas/fasimpls.h> /*I "petscsnesfas.h" I*/ 3 4 const char *SNESFASTypes[] = {"MULTIPLICATIVE","ADDITIVE","SNESFASType","SNES_FAS",0}; 5 6 /*MC 7 8 SNESFAS - Full Approximation Scheme nonlinear multigrid solver. 9 10 The nonlinear problem is solved via the repeated application of nonlinear preconditioners and coarse-grid corrections 11 12 .seealso: SNESCreate(), SNES, SNESSetType(), SNESType (for list of available types) 13 M*/ 14 15 extern PetscErrorCode SNESDestroy_FAS(SNES snes); 16 extern PetscErrorCode SNESSetUp_FAS(SNES snes); 17 extern PetscErrorCode SNESSetFromOptions_FAS(SNES snes); 18 extern PetscErrorCode SNESView_FAS(SNES snes, PetscViewer viewer); 19 extern PetscErrorCode SNESSolve_FAS(SNES snes); 20 extern PetscErrorCode SNESReset_FAS(SNES snes); 21 extern PetscErrorCode SNESFASGalerkinDefaultFunction(SNES, Vec, Vec, void *); 22 23 EXTERN_C_BEGIN 24 #undef __FUNCT__ 25 #define __FUNCT__ "SNESLineSearchSetType_FAS" 26 PetscErrorCode SNESLineSearchSetType_FAS(SNES snes, SNESLineSearchType type) 27 { 28 PetscErrorCode ierr; 29 PetscFunctionBegin; 30 31 switch (type) { 32 case SNES_LS_BASIC: 33 ierr = SNESLineSearchSet(snes,SNESLineSearchNo,PETSC_NULL);CHKERRQ(ierr); 34 break; 35 case SNES_LS_BASIC_NONORMS: 36 ierr = SNESLineSearchSet(snes,SNESLineSearchNoNorms,PETSC_NULL);CHKERRQ(ierr); 37 break; 38 case SNES_LS_QUADRATIC: 39 ierr = SNESLineSearchSet(snes,SNESLineSearchQuadraticSecant,PETSC_NULL);CHKERRQ(ierr); 40 break; 41 default: 42 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP,"Unknown line search type."); 43 break; 44 } 45 snes->ls_type = type; 46 PetscFunctionReturn(0); 47 } 48 EXTERN_C_END 49 50 EXTERN_C_BEGIN 51 52 #undef __FUNCT__ 53 #define __FUNCT__ "SNESCreate_FAS" 54 PetscErrorCode SNESCreate_FAS(SNES snes) 55 { 56 SNES_FAS * fas; 57 PetscErrorCode ierr; 58 59 PetscFunctionBegin; 60 snes->ops->destroy = SNESDestroy_FAS; 61 snes->ops->setup = SNESSetUp_FAS; 62 snes->ops->setfromoptions = SNESSetFromOptions_FAS; 63 snes->ops->view = SNESView_FAS; 64 snes->ops->solve = SNESSolve_FAS; 65 snes->ops->reset = SNESReset_FAS; 66 67 snes->usesksp = PETSC_FALSE; 68 snes->usespc = PETSC_FALSE; 69 70 ierr = PetscNewLog(snes, SNES_FAS, &fas);CHKERRQ(ierr); 71 snes->data = (void*) fas; 72 fas->level = 0; 73 fas->levels = 1; 74 fas->n_cycles = 1; 75 fas->max_up_it = 1; 76 fas->max_down_it = 1; 77 fas->upsmooth = PETSC_NULL; 78 fas->downsmooth = PETSC_NULL; 79 fas->next = PETSC_NULL; 80 fas->previous = PETSC_NULL; 81 fas->interpolate = PETSC_NULL; 82 fas->restrct = PETSC_NULL; 83 fas->inject = PETSC_NULL; 84 fas->monitor = PETSC_NULL; 85 fas->usedmfornumberoflevels = PETSC_FALSE; 86 fas->fastype = SNES_FAS_MULTIPLICATIVE; 87 88 ierr = PetscObjectComposeFunctionDynamic((PetscObject)snes,"SNESLineSearchSetType_C","SNESLineSearchSetType_FAS",SNESLineSearchSetType_FAS);CHKERRQ(ierr); 89 ierr = SNESLineSearchSetType(snes, SNES_LS_QUADRATIC);CHKERRQ(ierr); 90 91 PetscFunctionReturn(0); 92 } 93 EXTERN_C_END 94 95 #undef __FUNCT__ 96 #define __FUNCT__ "SNESFASGetLevels" 97 /*@ 98 SNESFASGetLevels - Gets the number of levels in a FAS, including fine and coarse grids 99 100 Input Parameter: 101 . snes - the nonlinear solver context 102 103 Output parameter: 104 . levels - the number of levels 105 106 Level: advanced 107 108 .keywords: MG, get, levels, multigrid 109 110 .seealso: SNESFASSetLevels(), PCMGGetLevels() 111 @*/ 112 PetscErrorCode SNESFASGetLevels(SNES snes, PetscInt * levels) { 113 SNES_FAS * fas = (SNES_FAS *)snes->data; 114 PetscFunctionBegin; 115 *levels = fas->levels; 116 PetscFunctionReturn(0); 117 } 118 119 #undef __FUNCT__ 120 #define __FUNCT__ "SNESFASSetCycles" 121 /*@ 122 SNESFASSetCycles - Sets the number of FAS multigrid cycles to use each time a grid is visited. Use SNESFASSetCyclesOnLevel() for more 123 complicated cycling. 124 125 Logically Collective on SNES 126 127 Input Parameters: 128 + snes - the multigrid context 129 - cycles - the number of cycles -- 1 for V-cycle, 2 for W-cycle 130 131 Options Database Key: 132 $ -snes_fas_cycles 1 or 2 133 134 Level: advanced 135 136 .keywords: MG, set, cycles, V-cycle, W-cycle, multigrid 137 138 .seealso: SNESFASSetCyclesOnLevel() 139 @*/ 140 PetscErrorCode SNESFASSetCycles(SNES snes, PetscInt cycles) { 141 SNES_FAS * fas = (SNES_FAS *)snes->data; 142 PetscErrorCode ierr; 143 PetscFunctionBegin; 144 fas->n_cycles = cycles; 145 if (fas->next) { 146 ierr = SNESFASSetCycles(fas->next, cycles);CHKERRQ(ierr); 147 } 148 PetscFunctionReturn(0); 149 } 150 151 #undef __FUNCT__ 152 #define __FUNCT__ "SNESFASSetCyclesOnLevel" 153 /*@ 154 SNESFASSetCyclesOnLevel - Sets the type cycles to use on a particular level. 155 156 Logically Collective on SNES 157 158 Input Parameters: 159 + snes - the multigrid context 160 . level - the level to set the number of cycles on 161 - cycles - the number of cycles -- 1 for V-cycle, 2 for W-cycle 162 163 Level: advanced 164 165 .keywords: MG, set, cycles, V-cycle, W-cycle, multigrid 166 167 .seealso: SNESFASSetCycles() 168 @*/ 169 PetscErrorCode SNESFASSetCyclesOnLevel(SNES snes, PetscInt level, PetscInt cycles) { 170 SNES_FAS * fas = (SNES_FAS *)snes->data; 171 PetscInt top_level = fas->level,i; 172 173 PetscFunctionBegin; 174 if (level > top_level) SETERRQ3(((PetscObject)snes)->comm,PETSC_ERR_ARG_OUTOFRANGE,"Cannot set level %D cycle count from level %D of SNESFAS with %D levels total",level,top_level,fas->levels); 175 /* get to the correct level */ 176 for (i = fas->level; i > level; i--) { 177 fas = (SNES_FAS *)fas->next->data; 178 } 179 if (fas->level != level) SETERRQ(((PetscObject)snes)->comm,PETSC_ERR_PLIB,"SNESFAS level hierarchy corrupt"); 180 fas->n_cycles = cycles; 181 PetscFunctionReturn(0); 182 } 183 184 #undef __FUNCT__ 185 #define __FUNCT__ "SNESFASSetGS" 186 /*@C 187 SNESFASSetGS - Sets a nonlinear GS smoother and if it should be used. 188 Use SNESFASSetGSOnLevel() for more complicated staging of smoothers 189 and nonlinear preconditioners. 190 191 Logically Collective on SNES 192 193 Input Parameters: 194 + snes - the multigrid context 195 . gsfunc - the nonlinear smoother function 196 . ctx - the user context for the nonlinear smoother 197 - use_gs - whether to use the nonlinear smoother or not 198 199 Level: advanced 200 201 .keywords: FAS, MG, set, cycles, gauss-seidel, multigrid 202 203 .seealso: SNESSetGS(), SNESFASSetGSOnLevel() 204 @*/ 205 PetscErrorCode SNESFASSetGS(SNES snes, PetscErrorCode (*gsfunc)(SNES,Vec,Vec,void *), void * ctx, PetscBool use_gs) { 206 PetscErrorCode ierr = 0; 207 SNES_FAS *fas = (SNES_FAS *)snes->data; 208 PetscFunctionBegin; 209 210 if (gsfunc) { 211 ierr = SNESSetGS(snes, gsfunc, ctx);CHKERRQ(ierr); 212 /* push the provided GS up the tree */ 213 if (fas->next) ierr = SNESFASSetGS(fas->next, gsfunc, ctx, use_gs);CHKERRQ(ierr); 214 } else if (snes->ops->computegs) { 215 /* assume that the user has set the GS solver at this level */ 216 if (fas->next) ierr = SNESFASSetGS(fas->next, PETSC_NULL, PETSC_NULL, use_gs);CHKERRQ(ierr); 217 } else if (use_gs) { 218 SETERRQ1(((PetscObject)snes)->comm, PETSC_ERR_ARG_WRONG, "No user Gauss-Seidel function provided in SNESFASSetGS on level %D", fas->level); 219 } 220 PetscFunctionReturn(0); 221 } 222 223 #undef __FUNCT__ 224 #define __FUNCT__ "SNESFASSetGSOnLevel" 225 /*@C 226 SNESFASSetGSOnLevel - Sets the nonlinear smoother on a particular level. 227 228 Logically Collective on SNES 229 230 Input Parameters: 231 + snes - the multigrid context 232 . level - the level to set the nonlinear smoother on 233 . gsfunc - the nonlinear smoother function 234 . ctx - the user context for the nonlinear smoother 235 - use_gs - whether to use the nonlinear smoother or not 236 237 Level: advanced 238 239 .keywords: FAS, MG, set, cycles, Gauss-Seidel, multigrid 240 241 .seealso: SNESSetGS(), SNESFASSetGS() 242 @*/ 243 PetscErrorCode SNESFASSetGSOnLevel(SNES snes, PetscInt level, PetscErrorCode (*gsfunc)(SNES,Vec,Vec,void *), void * ctx, PetscBool use_gs) { 244 SNES_FAS *fas = (SNES_FAS *)snes->data; 245 PetscErrorCode ierr; 246 PetscInt top_level = fas->level,i; 247 SNES cur_snes = snes; 248 PetscFunctionBegin; 249 if (level > top_level) SETERRQ3(((PetscObject)snes)->comm,PETSC_ERR_ARG_OUTOFRANGE,"Cannot set level %D GS from level %D of SNESFAS with %D levels total",level,top_level,fas->levels); 250 /* get to the correct level */ 251 for (i = fas->level; i > level; i--) { 252 fas = (SNES_FAS *)fas->next->data; 253 cur_snes = fas->next; 254 } 255 if (fas->level != level) SETERRQ(((PetscObject)snes)->comm,PETSC_ERR_PLIB,"SNESFAS level hierarchy corrupt"); 256 if (gsfunc) { 257 ierr = SNESSetGS(cur_snes, gsfunc, ctx);CHKERRQ(ierr); 258 } 259 PetscFunctionReturn(0); 260 } 261 262 #undef __FUNCT__ 263 #define __FUNCT__ "SNESFASGetSNES" 264 /*@ 265 SNESFASGetSNES - Gets the SNES corresponding to a particular 266 level of the FAS hierarchy. 267 268 Input Parameters: 269 + snes - the multigrid context 270 level - the level to get 271 - lsnes - whether to use the nonlinear smoother or not 272 273 Level: advanced 274 275 .keywords: FAS, MG, set, cycles, Gauss-Seidel, multigrid 276 277 .seealso: SNESFASSetLevels(), SNESFASGetLevels() 278 @*/ 279 PetscErrorCode SNESFASGetSNES(SNES snes,PetscInt level,SNES *lsnes) { 280 SNES_FAS *fas = (SNES_FAS*)snes->data; 281 PetscInt i; 282 283 PetscFunctionBegin; 284 if (level > fas->levels-1) SETERRQ2(((PetscObject)snes)->comm,PETSC_ERR_ARG_OUTOFRANGE,"Requested level %D from SNESFAS containing %D levels",level,fas->levels); 285 if (fas->level < level) SETERRQ2(((PetscObject)snes)->comm,PETSC_ERR_ARG_OUTOFRANGE,"Requested level %D from SNESFAS on level %D, must call from SNES at least as fine as level",level,fas->level); 286 *lsnes = snes; 287 for (i = fas->level; i > level; i--) { 288 *lsnes = fas->next; 289 fas = (SNES_FAS *)(*lsnes)->data; 290 } 291 if (fas->level != level) SETERRQ(((PetscObject)snes)->comm,PETSC_ERR_PLIB,"SNESFAS level hierarchy corrupt"); 292 PetscFunctionReturn(0); 293 } 294 295 #undef __FUNCT__ 296 #define __FUNCT__ "SNESFASSetType" 297 /*@ 298 SNESFASSetType - Sets the update and correction type used for FAS. 299 e 300 301 302 @*/ 303 PetscErrorCode SNESFASSetType(SNES snes,SNESFASType fastype) 304 { 305 SNES_FAS *fas = (SNES_FAS*)snes->data; 306 307 PetscFunctionBegin; 308 PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 309 PetscValidLogicalCollectiveEnum(snes,fastype,2); 310 fas->fastype = fastype; 311 PetscFunctionReturn(0); 312 } 313 314 #undef __FUNCT__ 315 #define __FUNCT__ "SNESFASSetLevels" 316 /*@C 317 SNESFASSetLevels - Sets the number of levels to use with FAS. 318 Must be called before any other FAS routine. 319 320 Input Parameters: 321 + snes - the snes context 322 . levels - the number of levels 323 - comms - optional communicators for each level; this is to allow solving the coarser 324 problems on smaller sets of processors. Use PETSC_NULL_OBJECT for default in 325 Fortran. 326 327 Level: intermediate 328 329 Notes: 330 If the number of levels is one then the multigrid uses the -fas_levels prefix 331 for setting the level options rather than the -fas_coarse prefix. 332 333 .keywords: FAS, MG, set, levels, multigrid 334 335 .seealso: SNESFASGetLevels() 336 @*/ 337 PetscErrorCode SNESFASSetLevels(SNES snes, PetscInt levels, MPI_Comm * comms) { 338 PetscErrorCode ierr; 339 PetscInt i; 340 SNES_FAS * fas = (SNES_FAS *)snes->data; 341 SNES prevsnes; 342 MPI_Comm comm; 343 PetscFunctionBegin; 344 comm = ((PetscObject)snes)->comm; 345 if (levels == fas->levels) { 346 if (!comms) 347 PetscFunctionReturn(0); 348 } 349 /* user has changed the number of levels; reset */ 350 ierr = SNESReset(snes);CHKERRQ(ierr); 351 /* destroy any coarser levels if necessary */ 352 if (fas->next) SNESDestroy(&fas->next);CHKERRQ(ierr); 353 fas->next = PETSC_NULL; 354 fas->previous = PETSC_NULL; 355 prevsnes = snes; 356 /* setup the finest level */ 357 for (i = levels - 1; i >= 0; i--) { 358 if (comms) comm = comms[i]; 359 fas->level = i; 360 fas->levels = levels; 361 fas->next = PETSC_NULL; 362 if (i > 0) { 363 ierr = SNESCreate(comm, &fas->next);CHKERRQ(ierr); 364 ierr = SNESSetOptionsPrefix(fas->next,((PetscObject)snes)->prefix);CHKERRQ(ierr); 365 ierr = SNESSetType(fas->next, SNESFAS);CHKERRQ(ierr); 366 ierr = PetscObjectIncrementTabLevel((PetscObject)fas->next, (PetscObject)snes, levels - i);CHKERRQ(ierr); 367 ((SNES_FAS *)fas->next->data)->previous = prevsnes; 368 prevsnes = fas->next; 369 fas = (SNES_FAS *)prevsnes->data; 370 } 371 } 372 PetscFunctionReturn(0); 373 } 374 375 #undef __FUNCT__ 376 #define __FUNCT__ "SNESFASSetNumberSmoothUp" 377 /*@ 378 SNESFASSetNumberSmoothUp - Sets the number of post-smoothing steps to 379 use on all levels. 380 381 Logically Collective on SNES 382 383 Input Parameters: 384 + snes - the multigrid context 385 - n - the number of smoothing steps 386 387 Options Database Key: 388 . -snes_fas_smoothup <n> - Sets number of pre-smoothing steps 389 390 Level: advanced 391 392 .keywords: FAS, MG, smooth, down, pre-smoothing, steps, multigrid 393 394 .seealso: SNESFASSetNumberSmoothDown() 395 @*/ 396 PetscErrorCode SNESFASSetNumberSmoothUp(SNES snes, PetscInt n) { 397 SNES_FAS * fas = (SNES_FAS *)snes->data; 398 PetscErrorCode ierr = 0; 399 PetscFunctionBegin; 400 fas->max_up_it = n; 401 if (fas->next) { 402 ierr = SNESFASSetNumberSmoothUp(fas->next, n);CHKERRQ(ierr); 403 } 404 PetscFunctionReturn(0); 405 } 406 407 #undef __FUNCT__ 408 #define __FUNCT__ "SNESFASSetNumberSmoothDown" 409 /*@ 410 SNESFASSetNumberSmoothDown - Sets the number of pre-smoothing steps to 411 use on all levels. 412 413 Logically Collective on SNES 414 415 Input Parameters: 416 + snes - the multigrid context 417 - n - the number of smoothing steps 418 419 Options Database Key: 420 . -snes_fas_smoothdown <n> - Sets number of pre-smoothing steps 421 422 Level: advanced 423 424 .keywords: FAS, MG, smooth, down, pre-smoothing, steps, multigrid 425 426 .seealso: SNESFASSetNumberSmoothUp() 427 @*/ 428 PetscErrorCode SNESFASSetNumberSmoothDown(SNES snes, PetscInt n) { 429 SNES_FAS * fas = (SNES_FAS *)snes->data; 430 PetscErrorCode ierr = 0; 431 PetscFunctionBegin; 432 fas->max_down_it = n; 433 if (fas->next) { 434 ierr = SNESFASSetNumberSmoothDown(fas->next, n);CHKERRQ(ierr); 435 } 436 PetscFunctionReturn(0); 437 } 438 439 #undef __FUNCT__ 440 #define __FUNCT__ "SNESFASSetInterpolation" 441 /*@ 442 SNESFASSetInterpolation - Sets the function to be used to calculate the 443 interpolation from l-1 to the lth level 444 445 Input Parameters: 446 + snes - the multigrid context 447 . mat - the interpolation operator 448 - level - the level (0 is coarsest) to supply [do not supply 0] 449 450 Level: advanced 451 452 Notes: 453 Usually this is the same matrix used also to set the restriction 454 for the same level. 455 456 One can pass in the interpolation matrix or its transpose; PETSc figures 457 out from the matrix size which one it is. 458 459 .keywords: FAS, multigrid, set, interpolate, level 460 461 .seealso: SNESFASSetInjection(), SNESFASSetRestriction(), SNESFASSetRScale() 462 @*/ 463 PetscErrorCode SNESFASSetInterpolation(SNES snes, PetscInt level, Mat mat) { 464 SNES_FAS * fas = (SNES_FAS *)snes->data; 465 PetscInt top_level = fas->level,i; 466 PetscErrorCode ierr; 467 468 PetscFunctionBegin; 469 if (level > top_level) SETERRQ3(((PetscObject)snes)->comm,PETSC_ERR_ARG_OUTOFRANGE,"Cannot set level %D interpolation from level %D of SNESFAS with %D levels total",level,top_level,fas->levels); 470 /* get to the correct level */ 471 for (i = fas->level; i > level; i--) { 472 fas = (SNES_FAS *)fas->next->data; 473 } 474 if (fas->level != level) SETERRQ(((PetscObject)snes)->comm,PETSC_ERR_PLIB,"SNESFAS level hierarchy corrupt"); 475 ierr = PetscObjectReference((PetscObject)mat);CHKERRQ(ierr); 476 ierr = MatDestroy(&fas->interpolate);CHKERRQ(ierr); 477 fas->interpolate = mat; 478 PetscFunctionReturn(0); 479 } 480 481 #undef __FUNCT__ 482 #define __FUNCT__ "SNESFASSetRestriction" 483 /*@ 484 SNESFASSetRestriction - Sets the function to be used to restrict the defect 485 from level l to l-1. 486 487 Input Parameters: 488 + snes - the multigrid context 489 . mat - the restriction matrix 490 - level - the level (0 is coarsest) to supply [Do not supply 0] 491 492 Level: advanced 493 494 Notes: 495 Usually this is the same matrix used also to set the interpolation 496 for the same level. 497 498 One can pass in the interpolation matrix or its transpose; PETSc figures 499 out from the matrix size which one it is. 500 501 If you do not set this, the transpose of the Mat set with SNESFASSetInterpolation() 502 is used. 503 504 .keywords: FAS, MG, set, multigrid, restriction, level 505 506 .seealso: SNESFASSetInterpolation(), SNESFASSetInjection() 507 @*/ 508 PetscErrorCode SNESFASSetRestriction(SNES snes, PetscInt level, Mat mat) { 509 SNES_FAS * fas = (SNES_FAS *)snes->data; 510 PetscInt top_level = fas->level,i; 511 PetscErrorCode ierr; 512 513 PetscFunctionBegin; 514 if (level > top_level) SETERRQ3(((PetscObject)snes)->comm,PETSC_ERR_ARG_OUTOFRANGE,"Cannot set level %D restriction from level %D of SNESFAS with %D levels total",level,top_level,fas->levels); 515 /* get to the correct level */ 516 for (i = fas->level; i > level; i--) { 517 fas = (SNES_FAS *)fas->next->data; 518 } 519 if (fas->level != level) SETERRQ(((PetscObject)snes)->comm,PETSC_ERR_PLIB,"SNESFAS level hierarchy corrupt"); 520 ierr = PetscObjectReference((PetscObject)mat);CHKERRQ(ierr); 521 ierr = MatDestroy(&fas->restrct);CHKERRQ(ierr); 522 fas->restrct = mat; 523 PetscFunctionReturn(0); 524 } 525 526 #undef __FUNCT__ 527 #define __FUNCT__ "SNESFASSetRScale" 528 /*@ 529 SNESFASSetRScale - Sets the scaling factor of the restriction 530 operator from level l to l-1. 531 532 Input Parameters: 533 + snes - the multigrid context 534 . rscale - the restriction scaling 535 - level - the level (0 is coarsest) to supply [Do not supply 0] 536 537 Level: advanced 538 539 Notes: 540 This is only used in the case that the injection is not set. 541 542 .keywords: FAS, MG, set, multigrid, restriction, level 543 544 .seealso: SNESFASSetInjection(), SNESFASSetRestriction() 545 @*/ 546 PetscErrorCode SNESFASSetRScale(SNES snes, PetscInt level, Vec rscale) { 547 SNES_FAS * fas = (SNES_FAS *)snes->data; 548 PetscInt top_level = fas->level,i; 549 PetscErrorCode ierr; 550 551 PetscFunctionBegin; 552 if (level > top_level) SETERRQ3(((PetscObject)snes)->comm,PETSC_ERR_ARG_OUTOFRANGE,"Cannot set level %D rscale from level %D of SNESFAS with %D levels total",level,top_level,fas->levels); 553 /* get to the correct level */ 554 for (i = fas->level; i > level; i--) { 555 fas = (SNES_FAS *)fas->next->data; 556 } 557 if (fas->level != level) SETERRQ(((PetscObject)snes)->comm,PETSC_ERR_PLIB,"SNESFAS level hierarchy corrupt"); 558 ierr = PetscObjectReference((PetscObject)rscale);CHKERRQ(ierr); 559 ierr = VecDestroy(&fas->rscale);CHKERRQ(ierr); 560 fas->rscale = rscale; 561 PetscFunctionReturn(0); 562 } 563 564 565 #undef __FUNCT__ 566 #define __FUNCT__ "SNESFASSetInjection" 567 /*@ 568 SNESFASSetInjection - Sets the function to be used to inject the solution 569 from level l to l-1. 570 571 Input Parameters: 572 + snes - the multigrid context 573 . mat - the restriction matrix 574 - level - the level (0 is coarsest) to supply [Do not supply 0] 575 576 Level: advanced 577 578 Notes: 579 If you do not set this, the restriction and rscale is used to 580 project the solution instead. 581 582 .keywords: FAS, MG, set, multigrid, restriction, level 583 584 .seealso: SNESFASSetInterpolation(), SNESFASSetRestriction() 585 @*/ 586 PetscErrorCode SNESFASSetInjection(SNES snes, PetscInt level, Mat mat) { 587 SNES_FAS * fas = (SNES_FAS *)snes->data; 588 PetscInt top_level = fas->level,i; 589 PetscErrorCode ierr; 590 591 PetscFunctionBegin; 592 if (level > top_level) SETERRQ3(((PetscObject)snes)->comm,PETSC_ERR_ARG_OUTOFRANGE,"Cannot set level %D injection from level %D of SNESFAS with %D levels total",level,top_level,fas->levels); 593 /* get to the correct level */ 594 for (i = fas->level; i > level; i--) { 595 fas = (SNES_FAS *)fas->next->data; 596 } 597 if (fas->level != level) SETERRQ(((PetscObject)snes)->comm,PETSC_ERR_PLIB,"SNESFAS level hierarchy corrupt"); 598 ierr = PetscObjectReference((PetscObject)mat);CHKERRQ(ierr); 599 ierr = MatDestroy(&fas->inject);CHKERRQ(ierr); 600 fas->inject = mat; 601 PetscFunctionReturn(0); 602 } 603 604 #undef __FUNCT__ 605 #define __FUNCT__ "SNESReset_FAS" 606 PetscErrorCode SNESReset_FAS(SNES snes) 607 { 608 PetscErrorCode ierr = 0; 609 SNES_FAS * fas = (SNES_FAS *)snes->data; 610 611 PetscFunctionBegin; 612 ierr = SNESDestroy(&fas->upsmooth);CHKERRQ(ierr); 613 ierr = SNESDestroy(&fas->downsmooth);CHKERRQ(ierr); 614 ierr = MatDestroy(&fas->inject);CHKERRQ(ierr); 615 ierr = MatDestroy(&fas->interpolate);CHKERRQ(ierr); 616 ierr = MatDestroy(&fas->restrct);CHKERRQ(ierr); 617 ierr = VecDestroy(&fas->rscale);CHKERRQ(ierr); 618 619 if (fas->upsmooth) ierr = SNESReset(fas->upsmooth);CHKERRQ(ierr); 620 if (fas->downsmooth) ierr = SNESReset(fas->downsmooth);CHKERRQ(ierr); 621 if (fas->next) ierr = SNESReset(fas->next);CHKERRQ(ierr); 622 ierr = PetscObjectComposeFunctionDynamic((PetscObject)snes,"SNESLineSearchSetType_C","",PETSC_NULL);CHKERRQ(ierr); 623 PetscFunctionReturn(0); 624 } 625 626 #undef __FUNCT__ 627 #define __FUNCT__ "SNESDestroy_FAS" 628 PetscErrorCode SNESDestroy_FAS(SNES snes) 629 { 630 SNES_FAS * fas = (SNES_FAS *)snes->data; 631 PetscErrorCode ierr = 0; 632 633 PetscFunctionBegin; 634 /* recursively resets and then destroys */ 635 ierr = SNESReset(snes);CHKERRQ(ierr); 636 if (fas->next) ierr = SNESDestroy(&fas->next);CHKERRQ(ierr); 637 ierr = PetscFree(fas);CHKERRQ(ierr); 638 639 PetscFunctionReturn(0); 640 } 641 642 #undef __FUNCT__ 643 #define __FUNCT__ "SNESSetUp_FAS" 644 PetscErrorCode SNESSetUp_FAS(SNES snes) 645 { 646 SNES_FAS *fas = (SNES_FAS *) snes->data; 647 PetscErrorCode ierr; 648 VecScatter injscatter; 649 PetscInt dm_levels; 650 Vec vec_sol, vec_func, vec_sol_update, vec_rhs; /* preserve these if they're set through the reset */ 651 652 PetscFunctionBegin; 653 654 if (fas->usedmfornumberoflevels && (fas->level == fas->levels - 1)) { 655 ierr = DMGetRefineLevel(snes->dm,&dm_levels);CHKERRQ(ierr); 656 dm_levels++; 657 if (dm_levels > fas->levels) { 658 659 /* we don't want the solution and func vectors to be destroyed in the SNESReset when it's called in SNESFASSetLevels_FAS*/ 660 vec_sol = snes->vec_sol; 661 vec_func = snes->vec_func; 662 vec_sol_update = snes->vec_sol_update; 663 vec_rhs = snes->vec_rhs; 664 snes->vec_sol = PETSC_NULL; 665 snes->vec_func = PETSC_NULL; 666 snes->vec_sol_update = PETSC_NULL; 667 snes->vec_rhs = PETSC_NULL; 668 669 /* reset the number of levels */ 670 ierr = SNESFASSetLevels(snes,dm_levels,PETSC_NULL);CHKERRQ(ierr); 671 ierr = SNESSetFromOptions(snes);CHKERRQ(ierr); 672 673 snes->vec_sol = vec_sol; 674 snes->vec_func = vec_func; 675 snes->vec_rhs = vec_rhs; 676 snes->vec_sol_update = vec_sol_update; 677 } 678 } 679 680 if (fas->level != fas->levels - 1) snes->gridsequence = 0; /* no grid sequencing inside the multigrid hierarchy! */ 681 682 if (fas->fastype == SNES_FAS_MULTIPLICATIVE) { 683 ierr = SNESDefaultGetWork(snes, 4);CHKERRQ(ierr); /* work vectors used for intergrid transfers */ 684 } else { 685 ierr = SNESDefaultGetWork(snes, 4);CHKERRQ(ierr); /* work vectors used for intergrid transfers */ 686 } 687 688 if (snes->dm) { 689 /* construct EVERYTHING from the DM -- including the progressive set of smoothers */ 690 if (fas->next) { 691 /* for now -- assume the DM and the evaluation functions have been set externally */ 692 if (!fas->next->dm) { 693 ierr = DMCoarsen(snes->dm, ((PetscObject)fas->next)->comm, &fas->next->dm);CHKERRQ(ierr); 694 ierr = SNESSetDM(fas->next, fas->next->dm);CHKERRQ(ierr); 695 } 696 /* set the interpolation and restriction from the DM */ 697 if (!fas->interpolate) { 698 ierr = DMCreateInterpolation(fas->next->dm, snes->dm, &fas->interpolate, &fas->rscale);CHKERRQ(ierr); 699 if (!fas->restrct) { 700 ierr = PetscObjectReference((PetscObject)fas->interpolate);CHKERRQ(ierr); 701 fas->restrct = fas->interpolate; 702 } 703 } 704 /* set the injection from the DM */ 705 if (!fas->inject) { 706 ierr = DMCreateInjection(fas->next->dm, snes->dm, &injscatter);CHKERRQ(ierr); 707 ierr = MatCreateScatter(((PetscObject)snes)->comm, injscatter, &fas->inject);CHKERRQ(ierr); 708 ierr = VecScatterDestroy(&injscatter);CHKERRQ(ierr); 709 } 710 } 711 /* set the DMs of the pre and post-smoothers here */ 712 if (fas->upsmooth) {ierr = SNESSetDM(fas->upsmooth, snes->dm);CHKERRQ(ierr);} 713 if (fas->downsmooth){ierr = SNESSetDM(fas->downsmooth, snes->dm);CHKERRQ(ierr);} 714 } 715 /*pass the smoother, function, and jacobian up to the next level if it's not user set already */ 716 717 if (fas->next) { 718 if (fas->galerkin) { 719 ierr = SNESSetFunction(fas->next, PETSC_NULL, SNESFASGalerkinDefaultFunction, fas->next);CHKERRQ(ierr); 720 } else { 721 if (snes->ops->computefunction && !fas->next->ops->computefunction) { 722 ierr = SNESSetFunction(fas->next, PETSC_NULL, snes->ops->computefunction, snes->funP);CHKERRQ(ierr); 723 } 724 if (snes->ops->computejacobian && !fas->next->ops->computejacobian) { 725 ierr = SNESSetJacobian(fas->next, fas->next->jacobian, fas->next->jacobian_pre, snes->ops->computejacobian, snes->jacP);CHKERRQ(ierr); 726 } 727 if (snes->ops->computegs && !fas->next->ops->computegs) { 728 ierr = SNESSetGS(fas->next, snes->ops->computegs, snes->gsP);CHKERRQ(ierr); 729 } 730 } 731 } 732 733 if (fas->next) { 734 /* gotta set up the solution vector for this to work */ 735 if (!fas->next->vec_sol) {ierr = VecDuplicate(fas->rscale, &fas->next->vec_sol);CHKERRQ(ierr);} 736 if (!fas->next->vec_rhs) {ierr = VecDuplicate(fas->rscale, &fas->next->vec_rhs);CHKERRQ(ierr);} 737 ierr = SNESSetUp(fas->next);CHKERRQ(ierr); 738 } 739 740 /* setup the pre and post smoothers and set their function, jacobian, and gs evaluation routines if the user has neglected this */ 741 if (fas->upsmooth) { 742 if (snes->ops->computefunction && !fas->upsmooth->ops->computefunction) { 743 ierr = SNESSetFunction(fas->upsmooth, PETSC_NULL, snes->ops->computefunction, snes->funP);CHKERRQ(ierr); 744 } 745 if (snes->ops->computejacobian && !fas->upsmooth->ops->computejacobian) { 746 ierr = SNESSetJacobian(fas->upsmooth, fas->upsmooth->jacobian, fas->upsmooth->jacobian_pre, snes->ops->computejacobian, snes->jacP);CHKERRQ(ierr); 747 } 748 if (snes->ops->computegs && !fas->upsmooth->ops->computegs) { 749 ierr = SNESSetGS(fas->upsmooth, snes->ops->computegs, snes->gsP);CHKERRQ(ierr); 750 } 751 ierr = SNESSetFromOptions(fas->upsmooth);CHKERRQ(ierr); 752 } 753 if (fas->downsmooth) { 754 if (snes->ops->computefunction && !fas->downsmooth->ops->computefunction) { 755 ierr = SNESSetFunction(fas->downsmooth, PETSC_NULL, snes->ops->computefunction, snes->funP);CHKERRQ(ierr); 756 } 757 if (snes->ops->computejacobian && !fas->downsmooth->ops->computejacobian) { 758 ierr = SNESSetJacobian(fas->downsmooth, fas->downsmooth->jacobian, fas->downsmooth->jacobian_pre, snes->ops->computejacobian, snes->jacP);CHKERRQ(ierr); 759 } 760 if (snes->ops->computegs && !fas->downsmooth->ops->computegs) { 761 ierr = SNESSetGS(fas->downsmooth, snes->ops->computegs, snes->gsP);CHKERRQ(ierr); 762 } 763 ierr = SNESSetFromOptions(fas->downsmooth);CHKERRQ(ierr); 764 } 765 766 /* setup FAS work vectors */ 767 if (fas->galerkin) { 768 ierr = VecDuplicate(snes->vec_sol, &fas->Xg);CHKERRQ(ierr); 769 ierr = VecDuplicate(snes->vec_sol, &fas->Fg);CHKERRQ(ierr); 770 } 771 772 773 /* got to set them all up at once */ 774 PetscFunctionReturn(0); 775 } 776 777 #undef __FUNCT__ 778 #define __FUNCT__ "SNESSetFromOptions_FAS" 779 PetscErrorCode SNESSetFromOptions_FAS(SNES snes) 780 { 781 SNES_FAS *fas = (SNES_FAS *) snes->data; 782 PetscInt levels = 1; 783 PetscBool flg, smoothflg, smoothupflg, smoothdownflg, smoothcoarseflg = PETSC_FALSE, monflg; 784 PetscErrorCode ierr; 785 char monfilename[PETSC_MAX_PATH_LEN]; 786 SNESFASType fastype; 787 const char *optionsprefix; 788 const char *prefix; 789 790 PetscFunctionBegin; 791 ierr = PetscOptionsHead("SNESFAS Options-----------------------------------");CHKERRQ(ierr); 792 793 /* number of levels -- only process on the finest level */ 794 if (fas->levels - 1 == fas->level) { 795 ierr = PetscOptionsInt("-snes_fas_levels", "Number of Levels", "SNESFASSetLevels", levels, &levels, &flg);CHKERRQ(ierr); 796 if (!flg && snes->dm) { 797 ierr = DMGetRefineLevel(snes->dm,&levels);CHKERRQ(ierr); 798 levels++; 799 fas->usedmfornumberoflevels = PETSC_TRUE; 800 } 801 ierr = SNESFASSetLevels(snes, levels, PETSC_NULL);CHKERRQ(ierr); 802 } 803 fastype = fas->fastype; 804 ierr = PetscOptionsEnum("-snes_fas_type","FAS correction type","SNESFASSetType",SNESFASTypes,(PetscEnum)fastype,(PetscEnum*)&fastype,&flg);CHKERRQ(ierr); 805 if (flg) { 806 ierr = SNESFASSetType(snes, fastype);CHKERRQ(ierr); 807 } 808 809 ierr = SNESGetOptionsPrefix(snes, &optionsprefix);CHKERRQ(ierr); 810 811 /* smoother setup options */ 812 ierr = PetscOptionsHasName(optionsprefix, "-fas_snes_type", &smoothflg);CHKERRQ(ierr); 813 ierr = PetscOptionsHasName(optionsprefix, "-fas_up_snes_type", &smoothupflg);CHKERRQ(ierr); 814 ierr = PetscOptionsHasName(optionsprefix, "-fas_down_snes_type", &smoothdownflg);CHKERRQ(ierr); 815 if (fas->level == 0) { 816 ierr = PetscOptionsHasName(optionsprefix, "-fas_coarse_snes_type", &smoothcoarseflg);CHKERRQ(ierr); 817 } 818 /* options for the number of preconditioning cycles and cycle type */ 819 820 ierr = PetscOptionsInt("-snes_fas_cycles","Number of cycles","SNESFASSetCycles",fas->n_cycles,&fas->n_cycles,&flg);CHKERRQ(ierr); 821 822 ierr = PetscOptionsBool("-snes_fas_galerkin", "Form coarse problems with Galerkin","SNESFAS",fas->galerkin,&fas->galerkin,&flg);CHKERRQ(ierr); 823 824 ierr = PetscOptionsString("-snes_fas_monitor","Monitor FAS progress","SNESMonitorSet","stdout",monfilename,PETSC_MAX_PATH_LEN,&monflg);CHKERRQ(ierr); 825 826 827 ierr = PetscOptionsTail();CHKERRQ(ierr); 828 /* setup from the determined types if there is no pointwise procedure or smoother defined */ 829 830 if ((!fas->downsmooth) && smoothcoarseflg) { 831 ierr = SNESGetOptionsPrefix(snes,&prefix);CHKERRQ(ierr); 832 ierr = SNESCreate(((PetscObject)snes)->comm, &fas->downsmooth);CHKERRQ(ierr); 833 ierr = SNESSetOptionsPrefix(fas->downsmooth,prefix);CHKERRQ(ierr); 834 ierr = SNESAppendOptionsPrefix(fas->downsmooth,"fas_coarse_");CHKERRQ(ierr); 835 ierr = PetscObjectIncrementTabLevel((PetscObject)fas->downsmooth, (PetscObject)snes, 1);CHKERRQ(ierr); 836 } 837 838 if ((!fas->downsmooth) && smoothdownflg) { 839 ierr = SNESGetOptionsPrefix(snes,&prefix);CHKERRQ(ierr); 840 ierr = SNESCreate(((PetscObject)snes)->comm, &fas->downsmooth);CHKERRQ(ierr); 841 ierr = SNESSetOptionsPrefix(fas->downsmooth,prefix);CHKERRQ(ierr); 842 ierr = SNESAppendOptionsPrefix(fas->downsmooth,"fas_down_");CHKERRQ(ierr); 843 ierr = PetscObjectIncrementTabLevel((PetscObject)fas->downsmooth, (PetscObject)snes, 1);CHKERRQ(ierr); 844 } 845 846 if ((!fas->upsmooth) && (fas->level != 0) && smoothupflg) { 847 ierr = SNESGetOptionsPrefix(snes,&prefix);CHKERRQ(ierr); 848 ierr = SNESCreate(((PetscObject)snes)->comm, &fas->upsmooth);CHKERRQ(ierr); 849 ierr = SNESSetOptionsPrefix(fas->upsmooth,prefix);CHKERRQ(ierr); 850 ierr = SNESAppendOptionsPrefix(fas->upsmooth,"fas_up_");CHKERRQ(ierr); 851 ierr = PetscObjectIncrementTabLevel((PetscObject)fas->upsmooth, (PetscObject)snes, 1);CHKERRQ(ierr); 852 } 853 854 if ((!fas->downsmooth) && smoothflg) { 855 ierr = SNESGetOptionsPrefix(snes,&prefix);CHKERRQ(ierr); 856 ierr = SNESCreate(((PetscObject)snes)->comm, &fas->downsmooth);CHKERRQ(ierr); 857 ierr = SNESSetOptionsPrefix(fas->downsmooth,prefix);CHKERRQ(ierr); 858 ierr = SNESAppendOptionsPrefix(fas->downsmooth,"fas_");CHKERRQ(ierr); 859 ierr = PetscObjectIncrementTabLevel((PetscObject)fas->downsmooth, (PetscObject)snes, 1);CHKERRQ(ierr); 860 } 861 862 if ((!fas->upsmooth) && (fas->level != 0) && smoothflg) { 863 ierr = SNESGetOptionsPrefix(snes,&prefix);CHKERRQ(ierr); 864 ierr = SNESCreate(((PetscObject)snes)->comm, &fas->upsmooth);CHKERRQ(ierr); 865 ierr = SNESSetOptionsPrefix(fas->upsmooth,prefix);CHKERRQ(ierr); 866 ierr = SNESAppendOptionsPrefix(fas->upsmooth,"fas_");CHKERRQ(ierr); 867 ierr = PetscObjectIncrementTabLevel((PetscObject)fas->upsmooth, (PetscObject)snes, 1);CHKERRQ(ierr); 868 } 869 870 if (fas->upsmooth) { 871 ierr = SNESSetTolerances(fas->upsmooth, fas->upsmooth->abstol, fas->upsmooth->rtol, fas->upsmooth->xtol, 1, 1000);CHKERRQ(ierr); 872 } 873 874 if (fas->downsmooth) { 875 ierr = SNESSetTolerances(fas->downsmooth, fas->downsmooth->abstol, fas->downsmooth->rtol, fas->downsmooth->xtol, 1, 1000);CHKERRQ(ierr); 876 } 877 878 if (fas->level != fas->levels - 1) { 879 ierr = SNESSetTolerances(snes, snes->abstol, snes->rtol, snes->xtol, fas->n_cycles, 1000);CHKERRQ(ierr); 880 } 881 882 /* control the simple Richardson smoother that is default if there's no upsmooth or downsmooth */ 883 if (!fas->downsmooth) { 884 ierr = PetscOptionsInt("-fas_down_snes_max_it","Down smooth iterations","SNESFASSetCycles",fas->max_down_it,&fas->max_down_it,&flg);CHKERRQ(ierr); 885 ierr = PetscOptionsInt("-fas_snes_max_it","Down smooth iterations","SNESFASSetCycles",fas->max_down_it,&fas->max_down_it,&flg);CHKERRQ(ierr); 886 if (fas->level == 0) { 887 ierr = PetscOptionsInt("-fas_coarse_snes_max_it","Coarse smooth iterations","SNESFASSetCycles",fas->max_down_it,&fas->max_down_it,&flg);CHKERRQ(ierr); 888 } 889 } 890 891 if (!fas->upsmooth) { 892 ierr = PetscOptionsInt("-fas_up_snes_max_it","Upsmooth iterations","SNESFASSetCycles",fas->max_up_it,&fas->max_up_it,&flg);CHKERRQ(ierr); 893 ierr = PetscOptionsInt("-fas_snes_max_it","Upsmooth iterations","SNESFASSetCycles",fas->max_up_it,&fas->max_up_it,&flg);CHKERRQ(ierr); 894 } 895 896 if (monflg) { 897 fas->monitor = PETSC_VIEWER_STDOUT_(((PetscObject)snes)->comm);CHKERRQ(ierr); 898 /* set the monitors for the upsmoother and downsmoother */ 899 ierr = SNESMonitorCancel(snes);CHKERRQ(ierr); 900 ierr = SNESMonitorSet(snes,SNESMonitorDefault,PETSC_NULL,(PetscErrorCode (*)(void**))PetscViewerDestroy);CHKERRQ(ierr); 901 if (fas->upsmooth) ierr = SNESMonitorSet(fas->upsmooth,SNESMonitorDefault,PETSC_NULL,(PetscErrorCode (*)(void**))PetscViewerDestroy);CHKERRQ(ierr); 902 if (fas->downsmooth) ierr = SNESMonitorSet(fas->downsmooth,SNESMonitorDefault,PETSC_NULL,(PetscErrorCode (*)(void**))PetscViewerDestroy);CHKERRQ(ierr); 903 } else { 904 /* unset the monitors on the coarse levels */ 905 if (fas->level != fas->levels - 1) { 906 ierr = SNESMonitorCancel(snes);CHKERRQ(ierr); 907 } 908 } 909 910 /* recursive option setting for the smoothers */ 911 if (fas->next) {ierr = SNESSetFromOptions(fas->next);CHKERRQ(ierr);} 912 PetscFunctionReturn(0); 913 } 914 915 #undef __FUNCT__ 916 #define __FUNCT__ "SNESView_FAS" 917 PetscErrorCode SNESView_FAS(SNES snes, PetscViewer viewer) 918 { 919 SNES_FAS *fas = (SNES_FAS *) snes->data; 920 PetscBool iascii; 921 PetscErrorCode ierr; 922 923 PetscFunctionBegin; 924 ierr = PetscTypeCompare((PetscObject) viewer, PETSCVIEWERASCII, &iascii);CHKERRQ(ierr); 925 if (iascii) { 926 ierr = PetscViewerASCIIPrintf(viewer, "FAS, levels = %D\n", fas->levels);CHKERRQ(ierr); 927 ierr = PetscViewerASCIIPushTab(viewer); 928 ierr = PetscViewerASCIIPrintf(viewer, "level: %D\n", fas->level);CHKERRQ(ierr); 929 if (fas->upsmooth) { 930 ierr = PetscViewerASCIIPrintf(viewer, "up-smoother on level %D:\n", fas->level);CHKERRQ(ierr); 931 ierr = PetscViewerASCIIPushTab(viewer); 932 ierr = SNESView(fas->upsmooth, viewer);CHKERRQ(ierr); 933 ierr = PetscViewerASCIIPopTab(viewer); 934 } else { 935 ierr = PetscViewerASCIIPrintf(viewer, "no up-smoother on level %D\n", fas->level);CHKERRQ(ierr); 936 } 937 if (fas->downsmooth) { 938 ierr = PetscViewerASCIIPrintf(viewer, "down-smoother on level %D:\n", fas->level);CHKERRQ(ierr); 939 ierr = PetscViewerASCIIPushTab(viewer); 940 ierr = SNESView(fas->downsmooth, viewer);CHKERRQ(ierr); 941 ierr = PetscViewerASCIIPopTab(viewer); 942 } else { 943 ierr = PetscViewerASCIIPrintf(viewer, "no down-smoother on level %D\n", fas->level);CHKERRQ(ierr); 944 } 945 ierr = PetscViewerASCIIPopTab(viewer); 946 } else { 947 SETERRQ1(((PetscObject)snes)->comm,PETSC_ERR_SUP,"Viewer type %s not supported for SNESFAS",((PetscObject)viewer)->type_name); 948 } 949 PetscFunctionReturn(0); 950 } 951 952 #undef __FUNCT__ 953 #define __FUNCT__ "FASDownSmooth" 954 /* 955 Defines the action of the downsmoother 956 */ 957 PetscErrorCode FASDownSmooth(SNES snes, Vec B, Vec X, Vec F){ 958 PetscErrorCode ierr = 0; 959 PetscReal fnorm, gnorm, ynorm, xnorm = 0.0; 960 SNESConvergedReason reason; 961 SNES_FAS *fas = (SNES_FAS *)snes->data; 962 Vec G, W, Y, FPC; 963 PetscBool lssuccess; 964 PetscInt k; 965 PetscFunctionBegin; 966 G = snes->work[1]; 967 W = snes->work[2]; 968 Y = snes->work[3]; 969 if (fas->downsmooth) { 970 ierr = SNESSolve(fas->downsmooth, B, X);CHKERRQ(ierr); 971 /* check convergence reason for the smoother */ 972 ierr = SNESGetConvergedReason(fas->downsmooth,&reason);CHKERRQ(ierr); 973 if (reason < 0 && reason != SNES_DIVERGED_MAX_IT) { 974 snes->reason = SNES_DIVERGED_INNER; 975 PetscFunctionReturn(0); 976 } 977 ierr = SNESGetFunction(fas->downsmooth, &FPC, PETSC_NULL, PETSC_NULL);CHKERRQ(ierr); 978 ierr = VecCopy(FPC, F);CHKERRQ(ierr); 979 } else { 980 /* basic richardson smoother */ 981 for (k = 0; k < fas->max_up_it; k++) { 982 ierr = SNESComputeFunction(snes, X, F);CHKERRQ(ierr); 983 ierr = VecNorm(F, NORM_2, &fnorm);CHKERRQ(ierr); 984 ierr = VecCopy(F, Y);CHKERRQ(ierr); 985 ierr = (*snes->ops->linesearch)(snes,snes->lsP,X,F,Y,fnorm,xnorm,G,W,&ynorm,&gnorm,&lssuccess);CHKERRQ(ierr); 986 if (!lssuccess) { 987 if (++snes->numFailures >= snes->maxFailures) { 988 snes->reason = SNES_DIVERGED_LINE_SEARCH; 989 PetscFunctionReturn(0); 990 } 991 } 992 ierr = VecCopy(W, X);CHKERRQ(ierr); 993 ierr = VecCopy(G, F);CHKERRQ(ierr); 994 fnorm = gnorm; 995 } 996 } 997 PetscFunctionReturn(0); 998 } 999 1000 1001 #undef __FUNCT__ 1002 #define __FUNCT__ "FASUpSmooth" 1003 /* 1004 Defines the action of the upsmoother 1005 */ 1006 PetscErrorCode FASUpSmooth (SNES snes, Vec B, Vec X, Vec F) { 1007 PetscErrorCode ierr = 0; 1008 PetscReal fnorm, gnorm, ynorm, xnorm = 0.0; 1009 SNESConvergedReason reason; 1010 SNES_FAS *fas = (SNES_FAS *)snes->data; 1011 Vec G, W, Y, FPC; 1012 PetscBool lssuccess; 1013 PetscInt k; 1014 PetscFunctionBegin; 1015 G = snes->work[1]; 1016 W = snes->work[2]; 1017 Y = snes->work[3]; 1018 if (fas->upsmooth) { 1019 ierr = SNESSolve(fas->upsmooth, B, X);CHKERRQ(ierr); 1020 /* check convergence reason for the smoother */ 1021 ierr = SNESGetConvergedReason(fas->upsmooth,&reason);CHKERRQ(ierr); 1022 if (reason < 0 && reason != SNES_DIVERGED_MAX_IT) { 1023 snes->reason = SNES_DIVERGED_INNER; 1024 PetscFunctionReturn(0); 1025 } 1026 ierr = SNESGetFunction(fas->upsmooth, &FPC, PETSC_NULL, PETSC_NULL);CHKERRQ(ierr); 1027 ierr = VecCopy(FPC, F);CHKERRQ(ierr); 1028 } else { 1029 /* basic richardson smoother */ 1030 for (k = 0; k < fas->max_up_it; k++) { 1031 ierr = SNESComputeFunction(snes, X, F);CHKERRQ(ierr); 1032 ierr = VecNorm(F, NORM_2, &fnorm);CHKERRQ(ierr); 1033 ierr = VecCopy(F, Y);CHKERRQ(ierr); 1034 ierr = (*snes->ops->linesearch)(snes,snes->lsP,X,F,Y,fnorm,xnorm,G,W,&ynorm,&gnorm,&lssuccess);CHKERRQ(ierr); 1035 if (!lssuccess) { 1036 if (++snes->numFailures >= snes->maxFailures) { 1037 snes->reason = SNES_DIVERGED_LINE_SEARCH; 1038 PetscFunctionReturn(0); 1039 } 1040 } 1041 ierr = VecCopy(W, X);CHKERRQ(ierr); 1042 ierr = VecCopy(G, F);CHKERRQ(ierr); 1043 fnorm = gnorm; 1044 } 1045 } 1046 PetscFunctionReturn(0); 1047 } 1048 1049 #undef __FUNCT__ 1050 #define __FUNCT__ "FASCoarseCorrection" 1051 /* 1052 1053 Performs the FAS coarse correction as: 1054 1055 fine problem: F(x) = 0 1056 coarse problem: F^c(x) = b^c 1057 1058 b^c = F^c(I^c_fx^f - I^c_fF(x)) 1059 1060 with correction: 1061 1062 1063 1064 */ 1065 PetscErrorCode FASCoarseCorrection(SNES snes, Vec X, Vec F, Vec X_new) { 1066 PetscErrorCode ierr; 1067 Vec X_c, Xo_c, F_c, B_c; 1068 SNES_FAS *fas = (SNES_FAS *)snes->data; 1069 SNESConvergedReason reason; 1070 PetscFunctionBegin; 1071 if (fas->next) { 1072 X_c = fas->next->vec_sol; 1073 Xo_c = fas->next->work[0]; 1074 F_c = fas->next->vec_func; 1075 B_c = fas->next->vec_rhs; 1076 1077 /* inject the solution */ 1078 if (fas->inject) { 1079 ierr = MatRestrict(fas->inject, X, Xo_c);CHKERRQ(ierr); 1080 } else { 1081 ierr = MatRestrict(fas->restrct, X, Xo_c);CHKERRQ(ierr); 1082 ierr = VecPointwiseMult(Xo_c, fas->rscale, Xo_c);CHKERRQ(ierr); 1083 } 1084 ierr = VecScale(F, -1.0);CHKERRQ(ierr); 1085 1086 /* restrict the defect */ 1087 ierr = MatRestrict(fas->restrct, F, B_c);CHKERRQ(ierr); 1088 1089 /* solve the coarse problem corresponding to F^c(x^c) = b^c = Rb + F^c(Rx) - RF(x) */ 1090 fas->next->vec_rhs = PETSC_NULL; /*unset the RHS to evaluate function instead of residual*/ 1091 ierr = SNESComputeFunction(fas->next, Xo_c, F_c);CHKERRQ(ierr); 1092 1093 ierr = VecAXPY(B_c, 1.0, F_c);CHKERRQ(ierr); /* add F_c(X) to the RHS */ 1094 1095 /* set initial guess of the coarse problem to the projected fine solution */ 1096 ierr = VecCopy(Xo_c, X_c);CHKERRQ(ierr); 1097 1098 /* recurse to the next level */ 1099 fas->next->vec_rhs = B_c; 1100 /* ierr = FASCycle_Private(fas->next, X_c);CHKERRQ(ierr); */ 1101 ierr = SNESSolve(fas->next, B_c, X_c);CHKERRQ(ierr); 1102 ierr = SNESGetConvergedReason(fas->next,&reason);CHKERRQ(ierr); 1103 if (reason < 0 && reason != SNES_DIVERGED_MAX_IT) { 1104 snes->reason = SNES_DIVERGED_INNER; 1105 PetscFunctionReturn(0); 1106 } 1107 /* fas->next->vec_rhs = PETSC_NULL; */ 1108 1109 /* correct as x <- x + I(x^c - Rx)*/ 1110 ierr = VecAXPY(X_c, -1.0, Xo_c);CHKERRQ(ierr); 1111 ierr = MatInterpolateAdd(fas->interpolate, X_c, X, X_new);CHKERRQ(ierr); 1112 } 1113 PetscFunctionReturn(0); 1114 } 1115 1116 #undef __FUNCT__ 1117 #define __FUNCT__ "FASCycle_Additive" 1118 /* 1119 1120 The additive cycle looks like: 1121 1122 xhat = x 1123 xhat = dS(x, b) 1124 x = coarsecorrection(xhat, b_d) 1125 x = x + nu*(xhat - x); 1126 (optional) x = uS(x, b) 1127 1128 With the coarse RHS (defect correction) as below. 1129 1130 */ 1131 PetscErrorCode FASCycle_Additive(SNES snes, Vec X) { 1132 Vec F, B, Xhat; 1133 Vec X_c, Xo_c, F_c, B_c, G, W; 1134 PetscErrorCode ierr; 1135 SNES_FAS * fas = (SNES_FAS *)snes->data; 1136 SNESConvergedReason reason; 1137 PetscReal xnorm = 0., fnorm = 0., gnorm = 0., ynorm = 0.; 1138 PetscBool lssucceed; 1139 PetscFunctionBegin; 1140 1141 F = snes->vec_func; 1142 B = snes->vec_rhs; 1143 Xhat = snes->work[3]; 1144 G = snes->work[1]; 1145 W = snes->work[2]; 1146 ierr = VecCopy(X, Xhat);CHKERRQ(ierr); 1147 /* recurse first */ 1148 if (fas->next) { 1149 ierr = SNESComputeFunction(snes, Xhat, F);CHKERRQ(ierr); 1150 1151 X_c = fas->next->vec_sol; 1152 Xo_c = fas->next->work[0]; 1153 F_c = fas->next->vec_func; 1154 B_c = fas->next->vec_rhs; 1155 1156 /* inject the solution */ 1157 if (fas->inject) { 1158 ierr = MatRestrict(fas->inject, Xhat, Xo_c);CHKERRQ(ierr); 1159 } else { 1160 ierr = MatRestrict(fas->restrct, Xhat, Xo_c);CHKERRQ(ierr); 1161 ierr = VecPointwiseMult(Xo_c, fas->rscale, Xo_c);CHKERRQ(ierr); 1162 } 1163 ierr = VecScale(F, -1.0);CHKERRQ(ierr); 1164 1165 /* restrict the defect */ 1166 ierr = MatRestrict(fas->restrct, F, B_c);CHKERRQ(ierr); 1167 1168 /* solve the coarse problem corresponding to F^c(x^c) = b^c = Rb + F^c(Rx) - RF(x) */ 1169 fas->next->vec_rhs = PETSC_NULL; /*unset the RHS to evaluate function instead of residual*/ 1170 ierr = SNESComputeFunction(fas->next, Xo_c, F_c);CHKERRQ(ierr); 1171 1172 ierr = VecAXPY(B_c, 1.0, F_c);CHKERRQ(ierr); /* add F_c(X) to the RHS */ 1173 1174 /* set initial guess of the coarse problem to the projected fine solution */ 1175 ierr = VecCopy(Xo_c, X_c);CHKERRQ(ierr); 1176 1177 /* recurse */ 1178 fas->next->vec_rhs = B_c; 1179 ierr = SNESSolve(fas->next, B_c, X_c);CHKERRQ(ierr); 1180 1181 /* smooth on this level */ 1182 ierr = FASDownSmooth(snes, B, X, F);CHKERRQ(ierr); 1183 1184 ierr = SNESGetConvergedReason(fas->next,&reason);CHKERRQ(ierr); 1185 if (reason < 0 && reason != SNES_DIVERGED_MAX_IT) { 1186 snes->reason = SNES_DIVERGED_INNER; 1187 PetscFunctionReturn(0); 1188 } 1189 1190 /* correct as x <- x + I(x^c - Rx)*/ 1191 ierr = VecAXPY(X_c, -1.0, Xo_c);CHKERRQ(ierr); 1192 ierr = MatInterpolate(fas->interpolate, X_c, Xhat);CHKERRQ(ierr); 1193 1194 /* additive correction of the coarse direction*/ 1195 ierr = SNESComputeFunction(snes, X, F);CHKERRQ(ierr); 1196 ierr = VecNorm(F, NORM_2, &fnorm);CHKERRQ(ierr); 1197 ierr = VecScale(Xhat, -1.0);CHKERRQ(ierr); 1198 ierr = (*snes->ops->linesearch)(snes,snes->lsP,X,F,Xhat,fnorm,xnorm,G,W,&ynorm,&gnorm,&lssucceed);CHKERRQ(ierr); 1199 ierr = VecCopy(W, X);CHKERRQ(ierr); 1200 ierr = VecCopy(G, F);CHKERRQ(ierr); 1201 fnorm = gnorm; 1202 } else { 1203 ierr = FASDownSmooth(snes, B, X, F);CHKERRQ(ierr); 1204 } 1205 PetscFunctionReturn(0); 1206 } 1207 1208 #undef __FUNCT__ 1209 #define __FUNCT__ "FASCycle_Multiplicative" 1210 /* 1211 1212 Defines the FAS cycle as: 1213 1214 fine problem: F(x) = 0 1215 coarse problem: F^c(x) = b^c 1216 1217 b^c = F^c(I^c_fx^f - I^c_fF(x)) 1218 1219 correction: 1220 1221 x = x + I(x^c - Rx) 1222 1223 */ 1224 PetscErrorCode FASCycle_Multiplicative(SNES snes, Vec X) { 1225 1226 PetscErrorCode ierr; 1227 Vec F,B; 1228 SNES_FAS *fas = (SNES_FAS *)snes->data; 1229 1230 PetscFunctionBegin; 1231 F = snes->vec_func; 1232 B = snes->vec_rhs; 1233 /* pre-smooth -- just update using the pre-smoother */ 1234 ierr = FASDownSmooth(snes, B, X, F);CHKERRQ(ierr); 1235 1236 ierr = FASCoarseCorrection(snes, X, F, X);CHKERRQ(ierr); 1237 1238 if (fas->level != 0) { 1239 ierr = FASUpSmooth(snes, B, X, F);CHKERRQ(ierr); 1240 } 1241 ierr = SNESComputeFunction(snes, X, F);CHKERRQ(ierr); 1242 1243 PetscFunctionReturn(0); 1244 } 1245 1246 #undef __FUNCT__ 1247 #define __FUNCT__ "SNESSolve_FAS" 1248 1249 PetscErrorCode SNESSolve_FAS(SNES snes) 1250 { 1251 PetscErrorCode ierr; 1252 PetscInt i, maxits; 1253 Vec X, F; 1254 PetscReal fnorm; 1255 SNES_FAS *fas = (SNES_FAS *)snes->data; 1256 PetscFunctionBegin; 1257 maxits = snes->max_its; /* maximum number of iterations */ 1258 snes->reason = SNES_CONVERGED_ITERATING; 1259 X = snes->vec_sol; 1260 F = snes->vec_func; 1261 1262 /*norm setup */ 1263 ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr); 1264 snes->iter = 0; 1265 snes->norm = 0.; 1266 ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr); 1267 ierr = SNESComputeFunction(snes,X,F);CHKERRQ(ierr); 1268 if (snes->domainerror) { 1269 snes->reason = SNES_DIVERGED_FUNCTION_DOMAIN; 1270 PetscFunctionReturn(0); 1271 } 1272 ierr = VecNorm(F, NORM_2, &fnorm);CHKERRQ(ierr); /* fnorm <- ||F|| */ 1273 if (PetscIsInfOrNanReal(fnorm)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"Infinite or not-a-number generated in norm"); 1274 ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr); 1275 snes->norm = fnorm; 1276 ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr); 1277 SNESLogConvHistory(snes,fnorm,0); 1278 ierr = SNESMonitor(snes,0,fnorm);CHKERRQ(ierr); 1279 1280 /* set parameter for default relative tolerance convergence test */ 1281 snes->ttol = fnorm*snes->rtol; 1282 /* test convergence */ 1283 ierr = (*snes->ops->converged)(snes,0,0.0,0.0,fnorm,&snes->reason,snes->cnvP);CHKERRQ(ierr); 1284 if (snes->reason) PetscFunctionReturn(0); 1285 for (i = 0; i < maxits; i++) { 1286 /* Call general purpose update function */ 1287 1288 if (snes->ops->update) { 1289 ierr = (*snes->ops->update)(snes, snes->iter);CHKERRQ(ierr); 1290 } 1291 if (fas->fastype == SNES_FAS_MULTIPLICATIVE) { 1292 ierr = FASCycle_Multiplicative(snes, X);CHKERRQ(ierr); 1293 } else { 1294 ierr = FASCycle_Additive(snes, X);CHKERRQ(ierr); 1295 } 1296 1297 /* check for FAS cycle divergence */ 1298 if (snes->reason != SNES_CONVERGED_ITERATING) { 1299 PetscFunctionReturn(0); 1300 } 1301 ierr = VecNorm(F, NORM_2, &fnorm);CHKERRQ(ierr); /* fnorm <- ||F|| */ 1302 /* Monitor convergence */ 1303 ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr); 1304 snes->iter = i+1; 1305 snes->norm = fnorm; 1306 ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr); 1307 SNESLogConvHistory(snes,snes->norm,0); 1308 ierr = SNESMonitor(snes,snes->iter,snes->norm);CHKERRQ(ierr); 1309 /* Test for convergence */ 1310 ierr = (*snes->ops->converged)(snes,snes->iter,0.0,0.0,fnorm,&snes->reason,snes->cnvP);CHKERRQ(ierr); 1311 if (snes->reason) break; 1312 } 1313 if (i == maxits) { 1314 ierr = PetscInfo1(snes, "Maximum number of iterations has been reached: %D\n", maxits);CHKERRQ(ierr); 1315 if (!snes->reason) snes->reason = SNES_DIVERGED_MAX_IT; 1316 } 1317 PetscFunctionReturn(0); 1318 } 1319