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