1 2 #include <petsc/private/pcmgimpl.h> /*I "petscksp.h" I*/ 3 4 /* ---------------------------------------------------------------------------*/ 5 /*@C 6 PCMGResidualDefault - Default routine to calculate the residual. 7 8 Collective on Mat 9 10 Input Parameters: 11 + mat - the matrix 12 . b - the right-hand-side 13 - x - the approximate solution 14 15 Output Parameter: 16 . r - location to store the residual 17 18 Level: developer 19 20 .seealso: PCMGSetResidual() 21 @*/ 22 PetscErrorCode PCMGResidualDefault(Mat mat,Vec b,Vec x,Vec r) 23 { 24 PetscErrorCode ierr; 25 26 PetscFunctionBegin; 27 ierr = MatResidual(mat,b,x,r);CHKERRQ(ierr); 28 PetscFunctionReturn(0); 29 } 30 31 /*@ 32 PCMGGetCoarseSolve - Gets the solver context to be used on the coarse grid. 33 34 Not Collective 35 36 Input Parameter: 37 . pc - the multigrid context 38 39 Output Parameter: 40 . ksp - the coarse grid solver context 41 42 Level: advanced 43 44 .seealso: PCMGGetSmootherUp(), PCMGGetSmootherDown(), PCMGGetSmoother() 45 @*/ 46 PetscErrorCode PCMGGetCoarseSolve(PC pc,KSP *ksp) 47 { 48 PC_MG *mg = (PC_MG*)pc->data; 49 PC_MG_Levels **mglevels = mg->levels; 50 51 PetscFunctionBegin; 52 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 53 *ksp = mglevels[0]->smoothd; 54 PetscFunctionReturn(0); 55 } 56 57 /*@C 58 PCMGSetResidual - Sets the function to be used to calculate the residual 59 on the lth level. 60 61 Logically Collective on PC 62 63 Input Parameters: 64 + pc - the multigrid context 65 . l - the level (0 is coarsest) to supply 66 . residual - function used to form residual, if none is provided the previously provide one is used, if no 67 previous one were provided then a default is used 68 - mat - matrix associated with residual 69 70 Level: advanced 71 72 .seealso: PCMGResidualDefault() 73 @*/ 74 PetscErrorCode PCMGSetResidual(PC pc,PetscInt l,PetscErrorCode (*residual)(Mat,Vec,Vec,Vec),Mat mat) 75 { 76 PC_MG *mg = (PC_MG*)pc->data; 77 PC_MG_Levels **mglevels = mg->levels; 78 PetscErrorCode ierr; 79 80 PetscFunctionBegin; 81 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 82 if (!mglevels) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONGSTATE,"Must set MG levels before calling"); 83 if (residual) mglevels[l]->residual = residual; 84 if (!mglevels[l]->residual) mglevels[l]->residual = PCMGResidualDefault; 85 if (mat) {ierr = PetscObjectReference((PetscObject)mat);CHKERRQ(ierr);} 86 ierr = MatDestroy(&mglevels[l]->A);CHKERRQ(ierr); 87 mglevels[l]->A = mat; 88 PetscFunctionReturn(0); 89 } 90 91 /*@ 92 PCMGSetInterpolation - Sets the function to be used to calculate the 93 interpolation from l-1 to the lth level 94 95 Logically Collective on PC 96 97 Input Parameters: 98 + pc - the multigrid context 99 . mat - the interpolation operator 100 - l - the level (0 is coarsest) to supply [do not supply 0] 101 102 Level: advanced 103 104 Notes: 105 Usually this is the same matrix used also to set the restriction 106 for the same level. 107 108 One can pass in the interpolation matrix or its transpose; PETSc figures 109 out from the matrix size which one it is. 110 111 .seealso: PCMGSetRestriction() 112 @*/ 113 PetscErrorCode PCMGSetInterpolation(PC pc,PetscInt l,Mat mat) 114 { 115 PC_MG *mg = (PC_MG*)pc->data; 116 PC_MG_Levels **mglevels = mg->levels; 117 PetscErrorCode ierr; 118 119 PetscFunctionBegin; 120 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 121 if (!mglevels) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONGSTATE,"Must set MG levels before calling"); 122 if (!l) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_OUTOFRANGE,"Do not set interpolation routine for coarsest level"); 123 ierr = PetscObjectReference((PetscObject)mat);CHKERRQ(ierr); 124 ierr = MatDestroy(&mglevels[l]->interpolate);CHKERRQ(ierr); 125 126 mglevels[l]->interpolate = mat; 127 PetscFunctionReturn(0); 128 } 129 130 /*@ 131 PCMGSetOperators - Sets operator and preconditioning matrix for lth level 132 133 Logically Collective on PC 134 135 Input Parameters: 136 + pc - the multigrid context 137 . Amat - the operator 138 . pmat - the preconditioning operator 139 - l - the level (0 is the coarsest) to supply 140 141 Level: advanced 142 143 .keywords: multigrid, set, interpolate, level 144 145 .seealso: PCMGSetRestriction(), PCMGSetInterpolation() 146 @*/ 147 PetscErrorCode PCMGSetOperators(PC pc,PetscInt l,Mat Amat,Mat Pmat) 148 { 149 PC_MG *mg = (PC_MG*)pc->data; 150 PC_MG_Levels **mglevels = mg->levels; 151 PetscErrorCode ierr; 152 153 PetscFunctionBegin; 154 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 155 PetscValidHeaderSpecific(Amat,MAT_CLASSID,3); 156 PetscValidHeaderSpecific(Pmat,MAT_CLASSID,4); 157 if (!mglevels) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONGSTATE,"Must set MG levels before calling"); 158 ierr = KSPSetOperators(mglevels[l]->smoothd,Amat,Pmat);CHKERRQ(ierr); 159 PetscFunctionReturn(0); 160 } 161 162 /*@ 163 PCMGGetInterpolation - Gets the function to be used to calculate the 164 interpolation from l-1 to the lth level 165 166 Logically Collective on PC 167 168 Input Parameters: 169 + pc - the multigrid context 170 - l - the level (0 is coarsest) to supply [Do not supply 0] 171 172 Output Parameter: 173 . mat - the interpolation matrix, can be NULL 174 175 Level: advanced 176 177 .seealso: PCMGGetRestriction(), PCMGSetInterpolation(), PCMGGetRScale() 178 @*/ 179 PetscErrorCode PCMGGetInterpolation(PC pc,PetscInt l,Mat *mat) 180 { 181 PC_MG *mg = (PC_MG*)pc->data; 182 PC_MG_Levels **mglevels = mg->levels; 183 PetscErrorCode ierr; 184 185 PetscFunctionBegin; 186 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 187 if (mat) PetscValidPointer(mat,3); 188 if (!mglevels) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONGSTATE,"Must set MG levels before calling"); 189 if (l <= 0 || mg->nlevels <= l) SETERRQ2(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_OUTOFRANGE,"Level %D must be in range {1,...,%D}",l,mg->nlevels-1); 190 if (!mglevels[l]->interpolate) { 191 if (!mglevels[l]->restrct) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONGSTATE,"Must call PCMGSetInterpolation() or PCMGSetRestriction()"); 192 ierr = PCMGSetInterpolation(pc,l,mglevels[l]->restrct);CHKERRQ(ierr); 193 } 194 if (mat) *mat = mglevels[l]->interpolate; 195 PetscFunctionReturn(0); 196 } 197 198 /*@ 199 PCMGSetRestriction - Sets the function to be used to restrict dual vectors 200 from level l to l-1. 201 202 Logically Collective on PC 203 204 Input Parameters: 205 + pc - the multigrid context 206 . l - the level (0 is coarsest) to supply [Do not supply 0] 207 - mat - the restriction matrix 208 209 Level: advanced 210 211 Notes: 212 Usually this is the same matrix used also to set the interpolation 213 for the same level. 214 215 One can pass in the interpolation matrix or its transpose; PETSc figures 216 out from the matrix size which one it is. 217 218 If you do not set this, the transpose of the Mat set with PCMGSetInterpolation() 219 is used. 220 221 .seealso: PCMGSetInterpolation() 222 @*/ 223 PetscErrorCode PCMGSetRestriction(PC pc,PetscInt l,Mat mat) 224 { 225 PetscErrorCode ierr; 226 PC_MG *mg = (PC_MG*)pc->data; 227 PC_MG_Levels **mglevels = mg->levels; 228 229 PetscFunctionBegin; 230 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 231 PetscValidHeaderSpecific(mat,MAT_CLASSID,3); 232 if (!mglevels) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONGSTATE,"Must set MG levels before calling"); 233 if (!l) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_OUTOFRANGE,"Do not set restriction routine for coarsest level"); 234 ierr = PetscObjectReference((PetscObject)mat);CHKERRQ(ierr); 235 ierr = MatDestroy(&mglevels[l]->restrct);CHKERRQ(ierr); 236 237 mglevels[l]->restrct = mat; 238 PetscFunctionReturn(0); 239 } 240 241 /*@ 242 PCMGGetRestriction - Gets the function to be used to restrict dual vectors 243 from level l to l-1. 244 245 Logically Collective on PC 246 247 Input Parameters: 248 + pc - the multigrid context 249 - l - the level (0 is coarsest) to supply [Do not supply 0] 250 251 Output Parameter: 252 . mat - the restriction matrix 253 254 Level: advanced 255 256 .seealso: PCMGGetInterpolation(), PCMGSetRestriction(), PCMGGetRScale(), PCMGGetInjection() 257 @*/ 258 PetscErrorCode PCMGGetRestriction(PC pc,PetscInt l,Mat *mat) 259 { 260 PC_MG *mg = (PC_MG*)pc->data; 261 PC_MG_Levels **mglevels = mg->levels; 262 PetscErrorCode ierr; 263 264 PetscFunctionBegin; 265 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 266 if (mat) PetscValidPointer(mat,3); 267 if (!mglevels) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONGSTATE,"Must set MG levels before calling"); 268 if (l <= 0 || mg->nlevels <= l) SETERRQ2(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_OUTOFRANGE,"Level %D must be in range {1,...,%D}",l,mg->nlevels-1); 269 if (!mglevels[l]->restrct) { 270 if (!mglevels[l]->interpolate) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONGSTATE,"Must call PCMGSetRestriction() or PCMGSetInterpolation()"); 271 ierr = PCMGSetRestriction(pc,l,mglevels[l]->interpolate);CHKERRQ(ierr); 272 } 273 if (mat) *mat = mglevels[l]->restrct; 274 PetscFunctionReturn(0); 275 } 276 277 /*@ 278 PCMGSetRScale - Sets the pointwise scaling for the restriction operator from level l to l-1. 279 280 Logically Collective on PC 281 282 Input Parameters: 283 + pc - the multigrid context 284 - l - the level (0 is coarsest) to supply [Do not supply 0] 285 . rscale - the scaling 286 287 Level: advanced 288 289 Notes: 290 When evaluating a function on a coarse level one does not want to do F(R * x) one does F(rscale * R * x) where rscale is 1 over the row sums of R. It is preferable to use PCMGSetInjection() to control moving primal vectors. 291 292 .seealso: PCMGSetInterpolation(), PCMGSetRestriction(), PCMGGetRScale(), PCMGSetInjection() 293 @*/ 294 PetscErrorCode PCMGSetRScale(PC pc,PetscInt l,Vec rscale) 295 { 296 PetscErrorCode ierr; 297 PC_MG *mg = (PC_MG*)pc->data; 298 PC_MG_Levels **mglevels = mg->levels; 299 300 PetscFunctionBegin; 301 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 302 if (!mglevels) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONGSTATE,"Must set MG levels before calling"); 303 if (l <= 0 || mg->nlevels <= l) SETERRQ2(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_OUTOFRANGE,"Level %D must be in range {1,...,%D}",l,mg->nlevels-1); 304 ierr = PetscObjectReference((PetscObject)rscale);CHKERRQ(ierr); 305 ierr = VecDestroy(&mglevels[l]->rscale);CHKERRQ(ierr); 306 307 mglevels[l]->rscale = rscale; 308 PetscFunctionReturn(0); 309 } 310 311 /*@ 312 PCMGGetRScale - Gets the pointwise scaling for the restriction operator from level l to l-1. 313 314 Collective on PC 315 316 Input Parameters: 317 + pc - the multigrid context 318 . rscale - the scaling 319 - l - the level (0 is coarsest) to supply [Do not supply 0] 320 321 Level: advanced 322 323 Notes: 324 When evaluating a function on a coarse level one does not want to do F(R * x) one does F(rscale * R * x) where rscale is 1 over the row sums of R. It is preferable to use PCMGGetInjection() to control moving primal vectors. 325 326 .seealso: PCMGSetInterpolation(), PCMGGetRestriction(), PCMGGetInjection() 327 @*/ 328 PetscErrorCode PCMGGetRScale(PC pc,PetscInt l,Vec *rscale) 329 { 330 PetscErrorCode ierr; 331 PC_MG *mg = (PC_MG*)pc->data; 332 PC_MG_Levels **mglevels = mg->levels; 333 334 PetscFunctionBegin; 335 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 336 if (!mglevels) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONGSTATE,"Must set MG levels before calling"); 337 if (l <= 0 || mg->nlevels <= l) SETERRQ2(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_OUTOFRANGE,"Level %D must be in range {1,...,%D}",l,mg->nlevels-1); 338 if (!mglevels[l]->rscale) { 339 Mat R; 340 Vec X,Y,coarse,fine; 341 PetscInt M,N; 342 ierr = PCMGGetRestriction(pc,l,&R);CHKERRQ(ierr); 343 ierr = MatCreateVecs(R,&X,&Y);CHKERRQ(ierr); 344 ierr = MatGetSize(R,&M,&N);CHKERRQ(ierr); 345 if (M < N) { 346 fine = X; 347 coarse = Y; 348 } else if (N < M) { 349 fine = Y; coarse = X; 350 } else SETERRQ(PetscObjectComm((PetscObject)R),PETSC_ERR_SUP,"Restriction matrix is square, cannot determine which Vec is coarser"); 351 ierr = VecSet(fine,1.);CHKERRQ(ierr); 352 ierr = MatRestrict(R,fine,coarse);CHKERRQ(ierr); 353 ierr = VecDestroy(&fine);CHKERRQ(ierr); 354 ierr = VecReciprocal(coarse);CHKERRQ(ierr); 355 mglevels[l]->rscale = coarse; 356 } 357 *rscale = mglevels[l]->rscale; 358 PetscFunctionReturn(0); 359 } 360 361 /*@ 362 PCMGSetInjection - Sets the function to be used to inject primal vectors 363 from level l to l-1. 364 365 Logically Collective on PC 366 367 Input Parameters: 368 + pc - the multigrid context 369 . l - the level (0 is coarsest) to supply [Do not supply 0] 370 - mat - the injection matrix 371 372 Level: advanced 373 374 .seealso: PCMGSetRestriction() 375 @*/ 376 PetscErrorCode PCMGSetInjection(PC pc,PetscInt l,Mat mat) 377 { 378 PetscErrorCode ierr; 379 PC_MG *mg = (PC_MG*)pc->data; 380 PC_MG_Levels **mglevels = mg->levels; 381 382 PetscFunctionBegin; 383 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 384 PetscValidHeaderSpecific(mat,MAT_CLASSID,3); 385 if (!mglevels) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONGSTATE,"Must set MG levels before calling"); 386 if (!l) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_OUTOFRANGE,"Do not set restriction routine for coarsest level"); 387 ierr = PetscObjectReference((PetscObject)mat);CHKERRQ(ierr); 388 ierr = MatDestroy(&mglevels[l]->inject);CHKERRQ(ierr); 389 390 mglevels[l]->inject = mat; 391 PetscFunctionReturn(0); 392 } 393 394 /*@ 395 PCMGGetInjection - Gets the function to be used to inject primal vectors 396 from level l to l-1. 397 398 Logically Collective on PC 399 400 Input Parameters: 401 + pc - the multigrid context 402 - l - the level (0 is coarsest) to supply [Do not supply 0] 403 404 Output Parameter: 405 . mat - the restriction matrix (may be NULL if no injection is available). 406 407 Level: advanced 408 409 .seealso: PCMGSetInjection(), PCMGetGetRestriction() 410 @*/ 411 PetscErrorCode PCMGGetInjection(PC pc,PetscInt l,Mat *mat) 412 { 413 PC_MG *mg = (PC_MG*)pc->data; 414 PC_MG_Levels **mglevels = mg->levels; 415 416 PetscFunctionBegin; 417 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 418 if (mat) PetscValidPointer(mat,3); 419 if (!mglevels) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONGSTATE,"Must set MG levels before calling"); 420 if (l <= 0 || mg->nlevels <= l) SETERRQ2(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_OUTOFRANGE,"Level %D must be in range {1,...,%D}",l,mg->nlevels-1); 421 if (mat) *mat = mglevels[l]->inject; 422 PetscFunctionReturn(0); 423 } 424 425 /*@ 426 PCMGGetSmoother - Gets the KSP context to be used as smoother for 427 both pre- and post-smoothing. Call both PCMGGetSmootherUp() and 428 PCMGGetSmootherDown() to use different functions for pre- and 429 post-smoothing. 430 431 Not Collective, KSP returned is parallel if PC is 432 433 Input Parameters: 434 + pc - the multigrid context 435 - l - the level (0 is coarsest) to supply 436 437 Ouput Parameters: 438 . ksp - the smoother 439 440 Notes: 441 Once you have called this routine, you can call KSPSetOperators(ksp,...) on the resulting ksp to provide the operators for the smoother for this level. 442 You can also modify smoother options by calling the various KSPSetXXX() options on this ksp. In addition you can call KSPGetPC(ksp,&pc) 443 and modify PC options for the smoother; for example PCSetType(pc,PCSOR); to use SOR smoothing. 444 445 Level: advanced 446 447 .seealso: PCMGGetSmootherUp(), PCMGGetSmootherDown(), PCMGGetCoarseSolve() 448 @*/ 449 PetscErrorCode PCMGGetSmoother(PC pc,PetscInt l,KSP *ksp) 450 { 451 PC_MG *mg = (PC_MG*)pc->data; 452 PC_MG_Levels **mglevels = mg->levels; 453 454 PetscFunctionBegin; 455 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 456 *ksp = mglevels[l]->smoothd; 457 PetscFunctionReturn(0); 458 } 459 460 /*@ 461 PCMGGetSmootherUp - Gets the KSP context to be used as smoother after 462 coarse grid correction (post-smoother). 463 464 Not Collective, KSP returned is parallel if PC is 465 466 Input Parameters: 467 + pc - the multigrid context 468 - l - the level (0 is coarsest) to supply 469 470 Ouput Parameters: 471 . ksp - the smoother 472 473 Level: advanced 474 475 Notes: 476 calling this will result in a different pre and post smoother so you may need to 477 set options on the pre smoother also 478 479 .seealso: PCMGGetSmootherUp(), PCMGGetSmootherDown() 480 @*/ 481 PetscErrorCode PCMGGetSmootherUp(PC pc,PetscInt l,KSP *ksp) 482 { 483 PC_MG *mg = (PC_MG*)pc->data; 484 PC_MG_Levels **mglevels = mg->levels; 485 PetscErrorCode ierr; 486 const char *prefix; 487 MPI_Comm comm; 488 489 PetscFunctionBegin; 490 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 491 /* 492 This is called only if user wants a different pre-smoother from post. 493 Thus we check if a different one has already been allocated, 494 if not we allocate it. 495 */ 496 if (!l) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_OUTOFRANGE,"There is no such thing as a up smoother on the coarse grid"); 497 if (mglevels[l]->smoothu == mglevels[l]->smoothd) { 498 KSPType ksptype; 499 PCType pctype; 500 PC ipc; 501 PetscReal rtol,abstol,dtol; 502 PetscInt maxits; 503 KSPNormType normtype; 504 ierr = PetscObjectGetComm((PetscObject)mglevels[l]->smoothd,&comm);CHKERRQ(ierr); 505 ierr = KSPGetOptionsPrefix(mglevels[l]->smoothd,&prefix);CHKERRQ(ierr); 506 ierr = KSPGetTolerances(mglevels[l]->smoothd,&rtol,&abstol,&dtol,&maxits);CHKERRQ(ierr); 507 ierr = KSPGetType(mglevels[l]->smoothd,&ksptype);CHKERRQ(ierr); 508 ierr = KSPGetNormType(mglevels[l]->smoothd,&normtype);CHKERRQ(ierr); 509 ierr = KSPGetPC(mglevels[l]->smoothd,&ipc);CHKERRQ(ierr); 510 ierr = PCGetType(ipc,&pctype);CHKERRQ(ierr); 511 512 ierr = KSPCreate(comm,&mglevels[l]->smoothu);CHKERRQ(ierr); 513 ierr = KSPSetErrorIfNotConverged(mglevels[l]->smoothu,pc->erroriffailure);CHKERRQ(ierr); 514 ierr = PetscObjectIncrementTabLevel((PetscObject)mglevels[l]->smoothu,(PetscObject)pc,mglevels[0]->levels-l);CHKERRQ(ierr); 515 ierr = KSPSetOptionsPrefix(mglevels[l]->smoothu,prefix);CHKERRQ(ierr); 516 ierr = KSPSetTolerances(mglevels[l]->smoothu,rtol,abstol,dtol,maxits);CHKERRQ(ierr); 517 ierr = KSPSetType(mglevels[l]->smoothu,ksptype);CHKERRQ(ierr); 518 ierr = KSPSetNormType(mglevels[l]->smoothu,normtype);CHKERRQ(ierr); 519 ierr = KSPSetConvergenceTest(mglevels[l]->smoothu,KSPConvergedSkip,NULL,NULL);CHKERRQ(ierr); 520 ierr = KSPGetPC(mglevels[l]->smoothu,&ipc);CHKERRQ(ierr); 521 ierr = PCSetType(ipc,pctype);CHKERRQ(ierr); 522 ierr = PetscLogObjectParent((PetscObject)pc,(PetscObject)mglevels[l]->smoothu);CHKERRQ(ierr); 523 ierr = PetscObjectComposedDataSetInt((PetscObject) mglevels[l]->smoothu, PetscMGLevelId, mglevels[l]->level);CHKERRQ(ierr); 524 } 525 if (ksp) *ksp = mglevels[l]->smoothu; 526 PetscFunctionReturn(0); 527 } 528 529 /*@ 530 PCMGGetSmootherDown - Gets the KSP context to be used as smoother before 531 coarse grid correction (pre-smoother). 532 533 Not Collective, KSP returned is parallel if PC is 534 535 Input Parameters: 536 + pc - the multigrid context 537 - l - the level (0 is coarsest) to supply 538 539 Ouput Parameters: 540 . ksp - the smoother 541 542 Level: advanced 543 544 Notes: 545 calling this will result in a different pre and post smoother so you may need to 546 set options on the post smoother also 547 548 .seealso: PCMGGetSmootherUp(), PCMGGetSmoother() 549 @*/ 550 PetscErrorCode PCMGGetSmootherDown(PC pc,PetscInt l,KSP *ksp) 551 { 552 PetscErrorCode ierr; 553 PC_MG *mg = (PC_MG*)pc->data; 554 PC_MG_Levels **mglevels = mg->levels; 555 556 PetscFunctionBegin; 557 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 558 /* make sure smoother up and down are different */ 559 if (l) { 560 ierr = PCMGGetSmootherUp(pc,l,NULL);CHKERRQ(ierr); 561 } 562 *ksp = mglevels[l]->smoothd; 563 PetscFunctionReturn(0); 564 } 565 566 /*@ 567 PCMGSetCycleTypeOnLevel - Sets the type of cycle (aka cycle index) to run on the specified level. 568 569 Logically Collective on PC 570 571 Input Parameters: 572 + pc - the multigrid context 573 . l - the level (0 is coarsest) 574 - c - either PC_MG_CYCLE_V or PC_MG_CYCLE_W 575 576 Level: advanced 577 578 .seealso: PCMGSetCycleType() 579 @*/ 580 PetscErrorCode PCMGSetCycleTypeOnLevel(PC pc,PetscInt l,PCMGCycleType c) 581 { 582 PC_MG *mg = (PC_MG*)pc->data; 583 PC_MG_Levels **mglevels = mg->levels; 584 585 PetscFunctionBegin; 586 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 587 if (!mglevels) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONGSTATE,"Must set MG levels before calling"); 588 PetscValidLogicalCollectiveInt(pc,l,2); 589 PetscValidLogicalCollectiveEnum(pc,c,3); 590 mglevels[l]->cycles = c; 591 PetscFunctionReturn(0); 592 } 593 594 /*@ 595 PCMGSetRhs - Sets the vector to be used to store the right-hand side on a particular level. 596 597 Logically Collective on PC 598 599 Input Parameters: 600 + pc - the multigrid context 601 . l - the level (0 is coarsest) this is to be used for 602 - c - the Vec 603 604 Level: advanced 605 606 Notes: 607 If this is not provided PETSc will automatically generate one. You do not need to keep a reference to this vector if you do not need it. PCDestroy() will properly free it. 608 609 .keywords: MG, multigrid, set, right-hand-side, rhs, level 610 .seealso: PCMGSetX(), PCMGSetR() 611 @*/ 612 PetscErrorCode PCMGSetRhs(PC pc,PetscInt l,Vec c) 613 { 614 PetscErrorCode ierr; 615 PC_MG *mg = (PC_MG*)pc->data; 616 PC_MG_Levels **mglevels = mg->levels; 617 618 PetscFunctionBegin; 619 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 620 if (!mglevels) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONGSTATE,"Must set MG levels before calling"); 621 if (l == mglevels[0]->levels-1) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_INCOMP,"Do not set rhs for finest level"); 622 ierr = PetscObjectReference((PetscObject)c);CHKERRQ(ierr); 623 ierr = VecDestroy(&mglevels[l]->b);CHKERRQ(ierr); 624 625 mglevels[l]->b = c; 626 PetscFunctionReturn(0); 627 } 628 629 /*@ 630 PCMGSetX - Sets the vector to be used to store the solution on a particular level. 631 632 Logically Collective on PC 633 634 Input Parameters: 635 + pc - the multigrid context 636 . l - the level (0 is coarsest) this is to be used for (do not supply the finest level) 637 - c - the Vec 638 639 Level: advanced 640 641 Notes: 642 If this is not provided PETSc will automatically generate one. You do not need to keep a reference to this vector if you do not need it. PCDestroy() will properly free it. 643 644 .keywords: MG, multigrid, set, solution, level 645 .seealso: PCMGSetRhs(), PCMGSetR() 646 @*/ 647 PetscErrorCode PCMGSetX(PC pc,PetscInt l,Vec c) 648 { 649 PetscErrorCode ierr; 650 PC_MG *mg = (PC_MG*)pc->data; 651 PC_MG_Levels **mglevels = mg->levels; 652 653 PetscFunctionBegin; 654 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 655 if (!mglevels) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONGSTATE,"Must set MG levels before calling"); 656 if (l == mglevels[0]->levels-1) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_INCOMP,"Do not set x for finest level"); 657 ierr = PetscObjectReference((PetscObject)c);CHKERRQ(ierr); 658 ierr = VecDestroy(&mglevels[l]->x);CHKERRQ(ierr); 659 660 mglevels[l]->x = c; 661 PetscFunctionReturn(0); 662 } 663 664 /*@ 665 PCMGSetR - Sets the vector to be used to store the residual on a particular level. 666 667 Logically Collective on PC 668 669 Input Parameters: 670 + pc - the multigrid context 671 . l - the level (0 is coarsest) this is to be used for 672 - c - the Vec 673 674 Level: advanced 675 676 Notes: 677 If this is not provided PETSc will automatically generate one. You do not need to keep a reference to this vector if you do not need it. PCDestroy() will properly free it. 678 679 .keywords: MG, multigrid, set, residual, level 680 .seealso: PCMGSetRhs(), PCMGSetX() 681 @*/ 682 PetscErrorCode PCMGSetR(PC pc,PetscInt l,Vec c) 683 { 684 PetscErrorCode ierr; 685 PC_MG *mg = (PC_MG*)pc->data; 686 PC_MG_Levels **mglevels = mg->levels; 687 688 PetscFunctionBegin; 689 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 690 if (!mglevels) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONGSTATE,"Must set MG levels before calling"); 691 if (!l) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_OUTOFRANGE,"Need not set residual vector for coarse grid"); 692 ierr = PetscObjectReference((PetscObject)c);CHKERRQ(ierr); 693 ierr = VecDestroy(&mglevels[l]->r);CHKERRQ(ierr); 694 695 mglevels[l]->r = c; 696 PetscFunctionReturn(0); 697 } 698