1 /* Defines the basic SNES object */ 2 #include <../src/snes/impls/fas/fasimpls.h> 3 4 /*MC 5 Full Approximation Scheme nonlinear multigrid solver. 6 7 The nonlinear problem is solved via the repeated application of nonlinear preconditioners and coarse-grid corrections 8 9 .seealso: SNESCreate(), SNES, SNESSetType(), SNESType (for list of available types) 10 M*/ 11 12 extern PetscErrorCode SNESDestroy_FAS(SNES snes); 13 extern PetscErrorCode SNESSetUp_FAS(SNES snes); 14 extern PetscErrorCode SNESSetFromOptions_FAS(SNES snes); 15 extern PetscErrorCode SNESView_FAS(SNES snes, PetscViewer viewer); 16 extern PetscErrorCode SNESSolve_FAS(SNES snes); 17 extern PetscErrorCode SNESReset_FAS(SNES snes); 18 19 EXTERN_C_BEGIN 20 21 #undef __FUNCT__ 22 #define __FUNCT__ "SNESCreate_FAS" 23 PetscErrorCode SNESCreate_FAS(SNES snes) 24 { 25 SNES_FAS * fas; 26 PetscErrorCode ierr; 27 28 PetscFunctionBegin; 29 snes->ops->destroy = SNESDestroy_FAS; 30 snes->ops->setup = SNESSetUp_FAS; 31 snes->ops->setfromoptions = SNESSetFromOptions_FAS; 32 snes->ops->view = SNESView_FAS; 33 snes->ops->solve = SNESSolve_FAS; 34 snes->ops->reset = SNESReset_FAS; 35 36 snes->usesksp = PETSC_FALSE; 37 snes->usespc = PETSC_FALSE; 38 39 ierr = PetscNewLog(snes, SNES_FAS, &fas);CHKERRQ(ierr); 40 snes->data = (void*) fas; 41 fas->level = 0; 42 fas->levels = 1; 43 fas->n_cycles = 1; 44 fas->max_up_it = 1; 45 fas->max_down_it = 1; 46 fas->upsmooth = PETSC_NULL; 47 fas->downsmooth = PETSC_NULL; 48 fas->next = PETSC_NULL; 49 fas->interpolate = PETSC_NULL; 50 fas->restrct = PETSC_NULL; 51 fas->inject = PETSC_NULL; 52 53 PetscFunctionReturn(0); 54 } 55 EXTERN_C_END 56 57 #undef __FUNCT__ 58 #define __FUNCT__ "SNESFASGetLevels" 59 PetscErrorCode SNESFASGetLevels(SNES snes, PetscInt * levels) { 60 SNES_FAS * fas = (SNES_FAS *)snes->data; 61 PetscFunctionBegin; 62 *levels = fas->levels; 63 PetscFunctionReturn(0); 64 } 65 66 #undef __FUNCT__ 67 #define __FUNCT__ "SNESFASSetCycles" 68 PetscErrorCode SNESFASSetCycles(SNES snes, PetscInt cycles) { 69 SNES_FAS * fas = (SNES_FAS *)snes->data; 70 PetscErrorCode ierr; 71 PetscFunctionBegin; 72 fas->n_cycles = cycles; 73 if (fas->next) { 74 ierr = SNESFASSetCycles(fas->next, cycles);CHKERRQ(ierr); 75 } 76 PetscFunctionReturn(0); 77 } 78 79 80 #undef __FUNCT__ 81 #define __FUNCT__ "SNESFASSetCyclesOnLevel" 82 PetscErrorCode SNESFASSetRScale(SNES snes, PetscInt level, PetscInt cycles) { 83 SNES_FAS * fas = (SNES_FAS *)snes->data; 84 PetscInt top_level = fas->level,i; 85 86 PetscFunctionBegin; 87 if (level > top_level) 88 SETERRQ1(((PetscObject)snes)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Bad level number %d in SNESFASSetRestriction", level); 89 /* get to the correct level */ 90 for (i = fas->level; i > level; i--) { 91 fas = (SNES_FAS *)fas->next->data; 92 } 93 if (fas->level != level) 94 SETERRQ(((PetscObject)snes)->comm, PETSC_ERR_ARG_WRONG, "Inconsistent level labelling in SNESFASSetRestriction"); 95 fas->n_cycles = cycles; 96 PetscFunctionReturn(0); 97 } 98 99 100 #undef __FUNCT__ 101 #define __FUNCT__ "SNESFASGetSNES" 102 PetscErrorCode SNESFASGetSNES(SNES snes, PetscInt level, SNES * lsnes) { 103 SNES_FAS * fas = (SNES_FAS *)snes->data; 104 PetscInt levels = fas->level; 105 PetscInt i; 106 PetscFunctionBegin; 107 *lsnes = snes; 108 if (fas->level < level) { 109 SETERRQ(((PetscObject)snes)->comm, PETSC_ERR_ARG_OUTOFRANGE, "SNESFASGetSNES should only be called on a finer SNESFAS instance than the level."); 110 } 111 if (level > levels - 1) { 112 SETERRQ(((PetscObject)snes)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Level %d doesn't exist in the SNESFAS."); 113 } 114 for (i = fas->level; i > level; i--) { 115 *lsnes = fas->next; 116 fas = (SNES_FAS *)(*lsnes)->data; 117 } 118 if (fas->level != level) SETERRQ(((PetscObject)snes)->comm, PETSC_ERR_ARG_OUTOFRANGE, "SNESFASGetSNES didn't return the right level!"); 119 PetscFunctionReturn(0); 120 } 121 122 #undef __FUNCT__ 123 #define __FUNCT__ "SNESFASSetLevels" 124 PetscErrorCode SNESFASSetLevels(SNES snes, PetscInt levels, MPI_Comm * comms) { 125 PetscErrorCode ierr; 126 PetscInt i; 127 SNES_FAS * fas = (SNES_FAS *)snes->data; 128 MPI_Comm comm; 129 PetscFunctionBegin; 130 comm = ((PetscObject)snes)->comm; 131 if (levels == fas->levels) { 132 if (!comms) 133 PetscFunctionReturn(0); 134 } 135 /* user has changed the number of levels; reset */ 136 ierr = SNESReset(snes);CHKERRQ(ierr); 137 /* destroy any coarser levels if necessary */ 138 if (fas->next) SNESDestroy(&fas->next);CHKERRQ(ierr); 139 fas->next = PETSC_NULL; 140 /* setup the finest level */ 141 for (i = levels - 1; i >= 0; i--) { 142 if (comms) comm = comms[i]; 143 fas->level = i; 144 fas->levels = levels; 145 fas->next = PETSC_NULL; 146 if (i > 0) { 147 ierr = SNESCreate(comm, &fas->next);CHKERRQ(ierr); 148 ierr = SNESSetOptionsPrefix(fas->next,((PetscObject)snes)->prefix);CHKERRQ(ierr); 149 ierr = PetscObjectIncrementTabLevel((PetscObject)fas->next, (PetscObject)snes, levels - i);CHKERRQ(ierr); 150 ierr = SNESSetType(fas->next, SNESFAS);CHKERRQ(ierr); 151 fas = (SNES_FAS *)fas->next->data; 152 } 153 } 154 PetscFunctionReturn(0); 155 } 156 157 #undef __FUNCT__ 158 #define __FUNCT__ "SNESFASSetInterpolation" 159 PetscErrorCode SNESFASSetInterpolation(SNES snes, PetscInt level, Mat mat) { 160 SNES_FAS * fas = (SNES_FAS *)snes->data; 161 PetscInt top_level = fas->level,i; 162 163 PetscFunctionBegin; 164 if (level > top_level) 165 SETERRQ1(((PetscObject)snes)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Bad level number %d in SNESFASSetInterpolation", level); 166 /* get to the correct level */ 167 for (i = fas->level; i > level; i--) { 168 fas = (SNES_FAS *)fas->next->data; 169 } 170 if (fas->level != level) 171 SETERRQ(((PetscObject)snes)->comm, PETSC_ERR_ARG_WRONG, "Inconsistent level labelling in SNESFASSetInterpolation"); 172 fas->interpolate = mat; 173 PetscFunctionReturn(0); 174 } 175 176 #undef __FUNCT__ 177 #define __FUNCT__ "SNESFASSetRestriction" 178 PetscErrorCode SNESFASSetRestriction(SNES snes, PetscInt level, Mat mat) { 179 SNES_FAS * fas = (SNES_FAS *)snes->data; 180 PetscInt top_level = fas->level,i; 181 182 PetscFunctionBegin; 183 if (level > top_level) 184 SETERRQ1(((PetscObject)snes)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Bad level number %d in SNESFASSetRestriction", level); 185 /* get to the correct level */ 186 for (i = fas->level; i > level; i--) { 187 fas = (SNES_FAS *)fas->next->data; 188 } 189 if (fas->level != level) 190 SETERRQ(((PetscObject)snes)->comm, PETSC_ERR_ARG_WRONG, "Inconsistent level labelling in SNESFASSetRestriction"); 191 fas->restrct = mat; 192 PetscFunctionReturn(0); 193 } 194 195 196 #undef __FUNCT__ 197 #define __FUNCT__ "SNESFASSetRScale" 198 PetscErrorCode SNESFASSetRScale(SNES snes, PetscInt level, Vec rscale) { 199 SNES_FAS * fas = (SNES_FAS *)snes->data; 200 PetscInt top_level = fas->level,i; 201 202 PetscFunctionBegin; 203 if (level > top_level) 204 SETERRQ1(((PetscObject)snes)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Bad level number %d in SNESFASSetRestriction", level); 205 /* get to the correct level */ 206 for (i = fas->level; i > level; i--) { 207 fas = (SNES_FAS *)fas->next->data; 208 } 209 if (fas->level != level) 210 SETERRQ(((PetscObject)snes)->comm, PETSC_ERR_ARG_WRONG, "Inconsistent level labelling in SNESFASSetRestriction"); 211 fas->rscale = rscale; 212 PetscFunctionReturn(0); 213 } 214 215 216 #undef __FUNCT__ 217 #define __FUNCT__ "SNESFASSetInjection" 218 PetscErrorCode SNESFASSetInjection(SNES snes, PetscInt level, Mat mat) { 219 SNES_FAS * fas = (SNES_FAS *)snes->data; 220 PetscInt top_level = fas->level,i; 221 222 PetscFunctionBegin; 223 if (level > top_level) 224 SETERRQ1(((PetscObject)snes)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Bad level number %d in SNESFASSetInjection", level); 225 /* get to the correct level */ 226 for (i = fas->level; i > level; i--) { 227 fas = (SNES_FAS *)fas->next->data; 228 } 229 if (fas->level != level) 230 SETERRQ(((PetscObject)snes)->comm, PETSC_ERR_ARG_WRONG, "Inconsistent level labelling in SNESFASSetInjection"); 231 fas->inject = mat; 232 PetscFunctionReturn(0); 233 } 234 235 #undef __FUNCT__ 236 #define __FUNCT__ "SNESReset_FAS" 237 PetscErrorCode SNESReset_FAS(SNES snes) 238 { 239 PetscErrorCode ierr = 0; 240 SNES_FAS * fas = (SNES_FAS *)snes->data; 241 242 PetscFunctionBegin; 243 /* destroy local data created in SNESSetup_FAS */ 244 #if 0 245 /* recurse -- reset should destroy the structures -- destroy should destroy the structures recursively */ 246 #endif 247 if (fas->next) ierr = SNESReset_FAS(fas->next);CHKERRQ(ierr); 248 #if 0 249 #endif 250 PetscFunctionReturn(0); 251 } 252 253 #undef __FUNCT__ 254 #define __FUNCT__ "SNESDestroy_FAS" 255 PetscErrorCode SNESDestroy_FAS(SNES snes) 256 { 257 SNES_FAS * fas = (SNES_FAS *)snes->data; 258 PetscErrorCode ierr; 259 260 PetscFunctionBegin; 261 /* recursively resets and then destroys */ 262 ierr = SNESReset_FAS(snes);CHKERRQ(ierr); 263 if (fas->upsmooth) ierr = SNESDestroy(&fas->upsmooth);CHKERRQ(ierr); 264 if (fas->downsmooth) ierr = SNESDestroy(&fas->downsmooth);CHKERRQ(ierr); 265 if (fas->inject) { 266 ierr = MatDestroy(&fas->inject);CHKERRQ(ierr); 267 } 268 if (fas->interpolate == fas->restrct) { 269 if (fas->interpolate) ierr = MatDestroy(&fas->interpolate);CHKERRQ(ierr); 270 fas->restrct = PETSC_NULL; 271 } else { 272 if (fas->interpolate) ierr = MatDestroy(&fas->interpolate);CHKERRQ(ierr); 273 if (fas->restrct) ierr = MatDestroy(&fas->restrct);CHKERRQ(ierr); 274 } 275 if (fas->rscale) ierr = VecDestroy(&fas->rscale);CHKERRQ(ierr); 276 if (snes->work) ierr = VecDestroyVecs(snes->nwork,&snes->work);CHKERRQ(ierr); 277 if (fas->next) ierr = SNESDestroy(&fas->next);CHKERRQ(ierr); 278 ierr = PetscFree(fas);CHKERRQ(ierr); 279 280 PetscFunctionReturn(0); 281 } 282 283 #undef __FUNCT__ 284 #define __FUNCT__ "SNESSetUp_FAS" 285 PetscErrorCode SNESSetUp_FAS(SNES snes) 286 { 287 SNES_FAS *fas = (SNES_FAS *) snes->data,*tmp; 288 PetscErrorCode ierr; 289 VecScatter injscatter; 290 291 PetscFunctionBegin; 292 /* should call the SNESSetFromOptions() only when approriate */ 293 tmp = fas; 294 while (tmp) { 295 if (tmp->upsmooth) {ierr = SNESSetFromOptions(tmp->upsmooth);CHKERRQ(ierr);} 296 if (tmp->downsmooth) {ierr = SNESSetFromOptions(tmp->downsmooth);CHKERRQ(ierr);} 297 tmp = tmp->next ? (SNES_FAS*) tmp->next->data : 0; 298 } 299 300 if (!snes->work || snes->nwork != 2) {ierr = SNESDefaultGetWork(snes, 2);CHKERRQ(ierr);} /* work vectors used for intergrid transfers */ 301 /* gets the solver ready for solution */ 302 if (fas->next) { 303 if (snes->ops->computegs) { 304 ierr = SNESSetGS(fas->next, snes->ops->computegs, snes->gsP);CHKERRQ(ierr); 305 } 306 } 307 if (snes->dm) { 308 /* construct EVERYTHING from the DM -- including the progressive set of smoothers */ 309 if (fas->next) { 310 /* for now -- assume the DM and the evaluation functions have been set externally */ 311 if (!fas->next->dm) { 312 ierr = DMCoarsen(snes->dm, ((PetscObject)fas->next)->comm, &fas->next->dm);CHKERRQ(ierr); 313 ierr = SNESSetDM(fas->next, fas->next->dm);CHKERRQ(ierr); 314 } 315 /* set the interpolation and restriction from the DM */ 316 if (!fas->interpolate) { 317 ierr = DMGetInterpolation(fas->next->dm, snes->dm, &fas->interpolate, &fas->rscale);CHKERRQ(ierr); 318 fas->restrct = fas->interpolate; 319 } 320 /* set the injection from the DM */ 321 if (!fas->inject) { 322 ierr = DMGetInjection(fas->next->dm, snes->dm, &injscatter);CHKERRQ(ierr); 323 ierr = MatCreateScatter(((PetscObject)snes)->comm, injscatter, &fas->inject);CHKERRQ(ierr); 324 ierr = VecScatterDestroy(&injscatter);CHKERRQ(ierr); 325 } 326 } 327 /* set the DMs of the pre and post-smoothers here */ 328 if (fas->upsmooth) {ierr = SNESSetDM(fas->upsmooth, snes->dm);CHKERRQ(ierr);} 329 if (fas->downsmooth){ierr = SNESSetDM(fas->downsmooth, snes->dm);CHKERRQ(ierr);} 330 } 331 if (fas->next) { 332 /* gotta set up the solution vector for this to work */ 333 if (!fas->next->vec_sol) {ierr = VecDuplicate(fas->rscale, &fas->next->vec_sol);CHKERRQ(ierr);} 334 ierr = SNESSetUp(fas->next);CHKERRQ(ierr); 335 } 336 /* got to set them all up at once */ 337 PetscFunctionReturn(0); 338 } 339 340 #undef __FUNCT__ 341 #define __FUNCT__ "SNESSetFromOptions_FAS" 342 PetscErrorCode SNESSetFromOptions_FAS(SNES snes) 343 { 344 SNES_FAS *fas = (SNES_FAS *) snes->data; 345 PetscInt levels = 1; 346 PetscBool flg, monflg; 347 PetscErrorCode ierr; 348 const char * def_smooth = SNESNRICHARDSON; 349 char pre_type[256]; 350 char post_type[256]; 351 char monfilename[PETSC_MAX_PATH_LEN]; 352 353 PetscFunctionBegin; 354 ierr = PetscOptionsHead("SNESFAS Options-----------------------------------");CHKERRQ(ierr); 355 356 /* number of levels -- only process on the finest level */ 357 if (fas->levels - 1 == fas->level) { 358 ierr = PetscOptionsInt("-snes_fas_levels", "Number of Levels", "SNESFASSetLevels", levels, &levels, &flg);CHKERRQ(ierr); 359 if (!flg && snes->dm) { 360 ierr = DMGetRefineLevel(snes->dm,&levels);CHKERRQ(ierr); 361 levels++; 362 } 363 ierr = SNESFASSetLevels(snes, levels, PETSC_NULL);CHKERRQ(ierr); 364 } 365 366 /* type of pre and/or post smoothers -- set both at once */ 367 ierr = PetscMemcpy(post_type, def_smooth, 256);CHKERRQ(ierr); 368 ierr = PetscMemcpy(pre_type, def_smooth, 256);CHKERRQ(ierr); 369 ierr = PetscOptionsList("-snes_fas_smoother_type","Nonlinear smoother method","SNESSetType",SNESList,def_smooth,pre_type,256,&flg);CHKERRQ(ierr); 370 if (flg) { 371 ierr = PetscMemcpy(post_type, pre_type, 256);CHKERRQ(ierr); 372 } else { 373 ierr = PetscOptionsList("-snes_fas_smoothup_type", "Nonlinear smoother method","SNESSetType",SNESList,def_smooth,pre_type, 256,&flg);CHKERRQ(ierr); 374 ierr = PetscOptionsList("-snes_fas_smoothdown_type","Nonlinear smoother method","SNESSetType",SNESList,def_smooth,post_type,256,&flg);CHKERRQ(ierr); 375 } 376 377 /* options for the number of preconditioning cycles and cycle type */ 378 ierr = PetscOptionsInt("-snes_fas_up_it","Number of upsmoother iterations","PCMGSetNumberSmoothUp",fas->max_up_it,&fas->max_up_it,&flg);CHKERRQ(ierr); 379 ierr = PetscOptionsInt("-snes_fas_down_it","Number of downsmoother iterations","PCMGSetNumberSmoothUp",fas->max_down_it,&fas->max_down_it,&flg);CHKERRQ(ierr); 380 ierr = PetscOptionsInt("-snes_fas_cycles","Number of cycles","PCMGSetNumberSmoothUp",fas->n_cycles,&fas->n_cycles,&flg);CHKERRQ(ierr); 381 382 ierr = PetscOptionsString("-snes_fas_monitor","Monitor FAS progress","SNESMonitorSet","stdout",monfilename,PETSC_MAX_PATH_LEN,&monflg);CHKERRQ(ierr); 383 if (monflg) { 384 385 } 386 387 /* other options for the coarsest level */ 388 if (fas->level == 0) { 389 ierr = PetscOptionsList("-snes_fas_coarse_smoother_type","Coarsest smoother method","SNESSetType",SNESList,def_smooth,pre_type,256,&flg);CHKERRQ(ierr); 390 if (flg) { 391 ierr = PetscMemcpy(post_type, pre_type, 256);CHKERRQ(ierr); 392 } else { 393 ierr = PetscOptionsList("-snes_fas_coarse_smoothup_type", "Nonlinear smoother method","SNESSetType",SNESList,def_smooth,pre_type, 256,&flg);CHKERRQ(ierr); 394 ierr = PetscOptionsList("-snes_fas_coarse_smoothdown_type","Nonlinear smoother method","SNESSetType",SNESList,def_smooth,post_type,256,&flg);CHKERRQ(ierr); 395 } 396 } 397 398 ierr = PetscOptionsTail();CHKERRQ(ierr); 399 /* setup from the determined types if the smoothers don't exist */ 400 if (!fas->upsmooth) { 401 const char *prefix; 402 ierr = SNESGetOptionsPrefix(snes,&prefix);CHKERRQ(ierr); 403 ierr = SNESCreate(((PetscObject)snes)->comm, &fas->upsmooth);CHKERRQ(ierr); 404 ierr = SNESSetOptionsPrefix(fas->upsmooth,prefix);CHKERRQ(ierr); 405 if (fas->level || (fas->levels == 1)) { 406 ierr = SNESAppendOptionsPrefix(fas->upsmooth,"fas_levels_");CHKERRQ(ierr); 407 } else { 408 ierr = SNESAppendOptionsPrefix(fas->upsmooth,"fas_coarse_");CHKERRQ(ierr); 409 } 410 ierr = PetscObjectIncrementTabLevel((PetscObject)fas->upsmooth, (PetscObject)snes, 1);CHKERRQ(ierr); 411 ierr = SNESSetType(fas->upsmooth, pre_type);CHKERRQ(ierr); 412 if (snes->ops->computefunction) { 413 ierr = SNESSetFunction(fas->upsmooth,PETSC_NULL,snes->ops->computefunction,snes->funP);CHKERRQ(ierr); 414 } 415 } 416 if (fas->upsmooth) { 417 ierr = SNESSetTolerances(fas->upsmooth, 0.0, 0.0, 0.0, fas->max_up_it, 1000);CHKERRQ(ierr); 418 } 419 420 if (!fas->downsmooth && fas->level != 0) { 421 const char *prefix; 422 ierr = SNESGetOptionsPrefix(snes,&prefix);CHKERRQ(ierr); 423 ierr = SNESCreate(((PetscObject)snes)->comm, &fas->downsmooth);CHKERRQ(ierr); 424 ierr = SNESSetOptionsPrefix(fas->downsmooth,prefix);CHKERRQ(ierr); 425 ierr = SNESAppendOptionsPrefix(fas->downsmooth,"fas_levels_");CHKERRQ(ierr); 426 ierr = PetscObjectIncrementTabLevel((PetscObject)fas->downsmooth, (PetscObject)snes, 1);CHKERRQ(ierr); 427 ierr = SNESSetType(fas->downsmooth, pre_type);CHKERRQ(ierr); 428 if (snes->ops->computefunction) { 429 ierr = SNESSetFunction(fas->downsmooth,PETSC_NULL,snes->ops->computefunction,snes->funP);CHKERRQ(ierr); 430 } 431 } 432 if (fas->downsmooth) { 433 ierr = SNESSetTolerances(fas->downsmooth, 0.0, 0.0, 0.0, fas->max_down_it, 1000);CHKERRQ(ierr); 434 } 435 436 if (monflg) { 437 fas->monitor = PETSC_VIEWER_STDOUT_(((PetscObject)snes)->comm);CHKERRQ(ierr); 438 if (fas->upsmooth) ierr = SNESMonitorSet(fas->upsmooth,SNESMonitorDefault,PETSC_NULL,(PetscErrorCode (*)(void**))PetscViewerDestroy);CHKERRQ(ierr); 439 if (fas->downsmooth) ierr = SNESMonitorSet(fas->downsmooth,SNESMonitorDefault,PETSC_NULL,(PetscErrorCode (*)(void**))PetscViewerDestroy);CHKERRQ(ierr); 440 } 441 442 /* recursive option setting for the smoothers */ 443 if (fas->next) {ierr = SNESSetFromOptions_FAS(fas->next);CHKERRQ(ierr);} 444 PetscFunctionReturn(0); 445 } 446 447 #undef __FUNCT__ 448 #define __FUNCT__ "SNESView_FAS" 449 PetscErrorCode SNESView_FAS(SNES snes, PetscViewer viewer) 450 { 451 SNES_FAS *fas = (SNES_FAS *) snes->data; 452 PetscBool iascii; 453 PetscErrorCode ierr; 454 PetscInt levels = fas->levels; 455 PetscInt i; 456 457 PetscFunctionBegin; 458 ierr = PetscTypeCompare((PetscObject) viewer, PETSCVIEWERASCII, &iascii);CHKERRQ(ierr); 459 if (iascii) { 460 ierr = PetscViewerASCIIPrintf(viewer, "FAS, levels = %d\n", fas->levels);CHKERRQ(ierr); 461 ierr = PetscViewerASCIIPushTab(viewer); 462 for (i = levels - 1; i >= 0; i--) { 463 ierr = PetscViewerASCIIPrintf(viewer, "level: %d\n", fas->level);CHKERRQ(ierr); 464 if (fas->upsmooth) { 465 ierr = PetscViewerASCIIPrintf(viewer, "up-smoother on level %D\n", fas->level);CHKERRQ(ierr); 466 ierr = PetscViewerASCIIPushTab(viewer); 467 ierr = SNESView(fas->upsmooth, viewer);CHKERRQ(ierr); 468 ierr = PetscViewerASCIIPopTab(viewer); 469 } else { 470 ierr = PetscViewerASCIIPrintf(viewer, "no up-smoother on level %D\n", fas->level);CHKERRQ(ierr); 471 } 472 if (fas->downsmooth) { 473 ierr = PetscViewerASCIIPrintf(viewer, "down-smoother on level %D\n", fas->level);CHKERRQ(ierr); 474 ierr = PetscViewerASCIIPushTab(viewer); 475 ierr = SNESView(fas->downsmooth, viewer);CHKERRQ(ierr); 476 ierr = PetscViewerASCIIPopTab(viewer); 477 } else { 478 ierr = PetscViewerASCIIPrintf(viewer, "no down-smoother on level %D\n", fas->level);CHKERRQ(ierr); 479 } 480 if (fas->next) fas = (SNES_FAS *)fas->next->data; 481 } 482 ierr = PetscViewerASCIIPopTab(viewer); 483 } else { 484 SETERRQ1(((PetscObject)snes)->comm,PETSC_ERR_SUP,"Viewer type %s not supported for SNESFAS",((PetscObject)viewer)->type_name); 485 } 486 PetscFunctionReturn(0); 487 } 488 489 /* 490 491 Defines the FAS cycle as: 492 493 fine problem: F(x) = 0 494 coarse problem: F^c(x) = b^c 495 496 b^c = F^c(I^c_fx^f - I^c_fF(x)) 497 498 correction: 499 500 x = x + I(x^c - Rx) 501 502 */ 503 504 #undef __FUNCT__ 505 #define __FUNCT__ "FASCycle_Private" 506 PetscErrorCode FASCycle_Private(SNES snes, Vec X) { 507 508 PetscErrorCode ierr; 509 Vec X_c, Xo_c, F_c, B_c,F,B; 510 SNES_FAS * fas = (SNES_FAS *)snes->data; 511 PetscInt i, k; 512 PetscScalar fnorm; 513 514 PetscFunctionBegin; 515 F = snes->vec_func; 516 B = snes->vec_rhs; 517 /* pre-smooth -- just update using the pre-smoother */ 518 if (snes->ops->computegs) { 519 for (k = 0; k < fas->max_up_it; k++) { 520 ierr = SNESComputeGS(snes, B, X);CHKERRQ(ierr); 521 } 522 } else if (fas->upsmooth) { 523 ierr = SNESSolve(fas->upsmooth, B, X);CHKERRQ(ierr); 524 } else if (snes->pc) { 525 ierr = SNESSolve(snes->pc, B, X);CHKERRQ(ierr); 526 } 527 if (fas->next) { 528 for (i = 0; i < fas->n_cycles; i++) { 529 ierr = SNESComputeFunction(snes, X, F);CHKERRQ(ierr); 530 if (fas->monitor) { 531 ierr = VecNorm(F, NORM_2, &fnorm);CHKERRQ(ierr); 532 ierr = PetscViewerASCIIPrintf(fas->monitor, "%d=%e\n", fas->level, fnorm);CHKERRQ(ierr); 533 } 534 X_c = fas->next->vec_sol; 535 Xo_c = fas->next->work[0]; 536 F_c = fas->next->vec_func; 537 B_c = fas->next->work[1]; 538 539 /* inject the solution */ 540 if (fas->inject) { 541 ierr = MatRestrict(fas->inject, X, Xo_c);CHKERRQ(ierr); 542 } else { 543 ierr = MatRestrict(fas->restrct, X, Xo_c);CHKERRQ(ierr); 544 ierr = VecPointwiseMult(Xo_c, fas->rscale, Xo_c);CHKERRQ(ierr); 545 } 546 ierr = VecScale(F, -1.0);CHKERRQ(ierr); 547 548 /* restrict the defect */ 549 ierr = MatRestrict(fas->restrct, F, B_c);CHKERRQ(ierr); 550 551 /* solve the coarse problem corresponding to F^c(x^c) = b^c = Rb + F^c(Rx) - RF(x) */ 552 fas->next->vec_rhs = PETSC_NULL; /*unset the RHS to evaluate function instead of residual*/ 553 ierr = SNESComputeFunction(fas->next, Xo_c, F_c);CHKERRQ(ierr); 554 ierr = VecAXPY(B_c, 1.0, F_c);CHKERRQ(ierr); /* add F_c(X) to the RHS */ 555 556 /* set initial guess of the coarse problem to the projected fine solution */ 557 ierr = VecCopy(Xo_c, X_c);CHKERRQ(ierr); 558 559 /* recurse to the next level */ 560 fas->next->vec_rhs = B_c; 561 ierr = FASCycle_Private(fas->next, X_c);CHKERRQ(ierr); 562 fas->next->vec_rhs = PETSC_NULL; 563 564 /* correct as x <- x + I(x^c - Rx)*/ 565 ierr = VecAXPY(X_c, -1.0, Xo_c);CHKERRQ(ierr); 566 ierr = MatInterpolateAdd(fas->interpolate, X_c, X, X);CHKERRQ(ierr); 567 } 568 } 569 /* down-smooth -- just update using the down-smoother */ 570 if (fas->level != 0) { 571 if (snes->ops->computegs) { 572 for (k = 0; k < fas->max_down_it; k++) { 573 ierr = SNESComputeGS(snes, B, X);CHKERRQ(ierr); 574 } 575 }else if (fas->downsmooth) { 576 ierr = SNESSolve(fas->downsmooth, B, X);CHKERRQ(ierr); 577 } else if (snes->pc) { 578 ierr = SNESSolve(snes->pc, B, X);CHKERRQ(ierr); 579 } 580 } 581 ierr = SNESComputeFunction(snes, X, F);CHKERRQ(ierr); 582 583 PetscFunctionReturn(0); 584 } 585 586 #undef __FUNCT__ 587 #define __FUNCT__ "SNESSolve_FAS" 588 589 PetscErrorCode SNESSolve_FAS(SNES snes) 590 { 591 PetscErrorCode ierr; 592 PetscInt i, maxits; 593 Vec X, B,F; 594 PetscReal fnorm; 595 PetscFunctionBegin; 596 maxits = snes->max_its; /* maximum number of iterations */ 597 snes->reason = SNES_CONVERGED_ITERATING; 598 X = snes->vec_sol; 599 B = snes->vec_rhs; 600 F = snes->vec_func; 601 602 /*norm setup */ 603 ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr); 604 snes->iter = 0; 605 snes->norm = 0.; 606 ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr); 607 ierr = SNESComputeFunction(snes,X,F);CHKERRQ(ierr); 608 if (snes->domainerror) { 609 snes->reason = SNES_DIVERGED_FUNCTION_DOMAIN; 610 PetscFunctionReturn(0); 611 } 612 ierr = VecNorm(F, NORM_2, &fnorm);CHKERRQ(ierr); /* fnorm <- ||F|| */ 613 if (PetscIsInfOrNanReal(fnorm)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"Infinite or not-a-number generated in norm"); 614 ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr); 615 snes->norm = fnorm; 616 ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr); 617 SNESLogConvHistory(snes,fnorm,0); 618 ierr = SNESMonitor(snes,0,fnorm);CHKERRQ(ierr); 619 620 /* set parameter for default relative tolerance convergence test */ 621 snes->ttol = fnorm*snes->rtol; 622 /* test convergence */ 623 ierr = (*snes->ops->converged)(snes,0,0.0,0.0,fnorm,&snes->reason,snes->cnvP);CHKERRQ(ierr); 624 if (snes->reason) PetscFunctionReturn(0); 625 for (i = 0; i < maxits; i++) { 626 /* Call general purpose update function */ 627 628 if (snes->ops->update) { 629 ierr = (*snes->ops->update)(snes, snes->iter);CHKERRQ(ierr); 630 } 631 ierr = FASCycle_Private(snes, X);CHKERRQ(ierr); 632 ierr = VecNorm(F, NORM_2, &fnorm);CHKERRQ(ierr); /* fnorm <- ||F|| */ 633 /* Monitor convergence */ 634 ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr); 635 snes->iter = i+1; 636 snes->norm = fnorm; 637 ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr); 638 SNESLogConvHistory(snes,snes->norm,0); 639 ierr = SNESMonitor(snes,snes->iter,snes->norm);CHKERRQ(ierr); 640 /* Test for convergence */ 641 ierr = (*snes->ops->converged)(snes,snes->iter,0.0,0.0,fnorm,&snes->reason,snes->cnvP);CHKERRQ(ierr); 642 if (snes->reason) break; 643 } 644 if (i == maxits) { 645 ierr = PetscInfo1(snes, "Maximum number of iterations has been reached: %D\n", maxits);CHKERRQ(ierr); 646 if (!snes->reason) snes->reason = SNES_DIVERGED_MAX_IT; 647 } 648 PetscFunctionReturn(0); 649 } 650