1dba47a55SKris Buschelman 24b9ad928SBarry Smith /* 34b9ad928SBarry Smith Defines the multigrid preconditioner interface. 44b9ad928SBarry Smith */ 5af0996ceSBarry Smith #include <petsc/private/pcmgimpl.h> /*I "petscksp.h" I*/ 61e25c274SJed Brown #include <petscdm.h> 7391689abSStefano Zampini PETSC_INTERN PetscErrorCode PCPreSolveChangeRHS(PC,PetscBool*); 84b9ad928SBarry Smith 931567311SBarry Smith PetscErrorCode PCMGMCycle_Private(PC pc,PC_MG_Levels **mglevelsin,PCRichardsonConvergedReason *reason) 104b9ad928SBarry Smith { 1131567311SBarry Smith PC_MG *mg = (PC_MG*)pc->data; 1231567311SBarry Smith PC_MG_Levels *mgc,*mglevels = *mglevelsin; 136849ba73SBarry Smith PetscErrorCode ierr; 1431567311SBarry Smith PetscInt cycles = (mglevels->level == 1) ? 1 : (PetscInt) mglevels->cycles; 15a0808db4SHong Zhang PC subpc; 16a0808db4SHong Zhang PCFailedReason pcreason; 174b9ad928SBarry Smith 184b9ad928SBarry Smith PetscFunctionBegin; 1963e6d426SJed Brown if (mglevels->eventsmoothsolve) {ierr = PetscLogEventBegin(mglevels->eventsmoothsolve,0,0,0,0);CHKERRQ(ierr);} 2031567311SBarry Smith ierr = KSPSolve(mglevels->smoothd,mglevels->b,mglevels->x);CHKERRQ(ierr); /* pre-smooth */ 21a0808db4SHong Zhang ierr = KSPGetPC(mglevels->smoothd,&subpc);CHKERRQ(ierr); 22a0808db4SHong Zhang ierr = PCGetSetUpFailedReason(subpc,&pcreason);CHKERRQ(ierr); 23a0808db4SHong Zhang if (pcreason) { 24a0808db4SHong Zhang pc->failedreason = PC_SUBPC_ERROR; 25a0808db4SHong Zhang } 2663e6d426SJed Brown if (mglevels->eventsmoothsolve) {ierr = PetscLogEventEnd(mglevels->eventsmoothsolve,0,0,0,0);CHKERRQ(ierr);} 2731567311SBarry Smith if (mglevels->level) { /* not the coarsest grid */ 2863e6d426SJed Brown if (mglevels->eventresidual) {ierr = PetscLogEventBegin(mglevels->eventresidual,0,0,0,0);CHKERRQ(ierr);} 2931567311SBarry Smith ierr = (*mglevels->residual)(mglevels->A,mglevels->b,mglevels->x,mglevels->r);CHKERRQ(ierr); 3063e6d426SJed Brown if (mglevels->eventresidual) {ierr = PetscLogEventEnd(mglevels->eventresidual,0,0,0,0);CHKERRQ(ierr);} 314b9ad928SBarry Smith 324b9ad928SBarry Smith /* if on finest level and have convergence criteria set */ 3331567311SBarry Smith if (mglevels->level == mglevels->levels-1 && mg->ttol && reason) { 344b9ad928SBarry Smith PetscReal rnorm; 3531567311SBarry Smith ierr = VecNorm(mglevels->r,NORM_2,&rnorm);CHKERRQ(ierr); 364b9ad928SBarry Smith if (rnorm <= mg->ttol) { 3770441072SBarry Smith if (rnorm < mg->abstol) { 384d0a8057SBarry Smith *reason = PCRICHARDSON_CONVERGED_ATOL; 3957622a8eSBarry Smith ierr = PetscInfo2(pc,"Linear solver has converged. Residual norm %g is less than absolute tolerance %g\n",(double)rnorm,(double)mg->abstol);CHKERRQ(ierr); 404b9ad928SBarry Smith } else { 414d0a8057SBarry Smith *reason = PCRICHARDSON_CONVERGED_RTOL; 4257622a8eSBarry Smith ierr = PetscInfo2(pc,"Linear solver has converged. Residual norm %g is less than relative tolerance times initial residual norm %g\n",(double)rnorm,(double)mg->ttol);CHKERRQ(ierr); 434b9ad928SBarry Smith } 444b9ad928SBarry Smith PetscFunctionReturn(0); 454b9ad928SBarry Smith } 464b9ad928SBarry Smith } 474b9ad928SBarry Smith 4831567311SBarry Smith mgc = *(mglevelsin - 1); 4963e6d426SJed Brown if (mglevels->eventinterprestrict) {ierr = PetscLogEventBegin(mglevels->eventinterprestrict,0,0,0,0);CHKERRQ(ierr);} 5031567311SBarry Smith ierr = MatRestrict(mglevels->restrct,mglevels->r,mgc->b);CHKERRQ(ierr); 5163e6d426SJed Brown if (mglevels->eventinterprestrict) {ierr = PetscLogEventEnd(mglevels->eventinterprestrict,0,0,0,0);CHKERRQ(ierr);} 52efb30889SBarry Smith ierr = VecSet(mgc->x,0.0);CHKERRQ(ierr); 534b9ad928SBarry Smith while (cycles--) { 5431567311SBarry Smith ierr = PCMGMCycle_Private(pc,mglevelsin-1,reason);CHKERRQ(ierr); 554b9ad928SBarry Smith } 5663e6d426SJed Brown if (mglevels->eventinterprestrict) {ierr = PetscLogEventBegin(mglevels->eventinterprestrict,0,0,0,0);CHKERRQ(ierr);} 5731567311SBarry Smith ierr = MatInterpolateAdd(mglevels->interpolate,mgc->x,mglevels->x,mglevels->x);CHKERRQ(ierr); 5863e6d426SJed Brown if (mglevels->eventinterprestrict) {ierr = PetscLogEventEnd(mglevels->eventinterprestrict,0,0,0,0);CHKERRQ(ierr);} 5963e6d426SJed Brown if (mglevels->eventsmoothsolve) {ierr = PetscLogEventBegin(mglevels->eventsmoothsolve,0,0,0,0);CHKERRQ(ierr);} 6031567311SBarry Smith ierr = KSPSolve(mglevels->smoothu,mglevels->b,mglevels->x);CHKERRQ(ierr); /* post smooth */ 6163e6d426SJed Brown if (mglevels->eventsmoothsolve) {ierr = PetscLogEventEnd(mglevels->eventsmoothsolve,0,0,0,0);CHKERRQ(ierr);} 624b9ad928SBarry Smith } 634b9ad928SBarry Smith PetscFunctionReturn(0); 644b9ad928SBarry Smith } 654b9ad928SBarry Smith 66ace3abfcSBarry Smith static PetscErrorCode PCApplyRichardson_MG(PC pc,Vec b,Vec x,Vec w,PetscReal rtol,PetscReal abstol, PetscReal dtol,PetscInt its,PetscBool zeroguess,PetscInt *outits,PCRichardsonConvergedReason *reason) 674b9ad928SBarry Smith { 68f3fbd535SBarry Smith PC_MG *mg = (PC_MG*)pc->data; 69f3fbd535SBarry Smith PC_MG_Levels **mglevels = mg->levels; 70dfbe8321SBarry Smith PetscErrorCode ierr; 71391689abSStefano Zampini PC tpc; 72391689abSStefano Zampini PetscBool changeu,changed; 73f3fbd535SBarry Smith PetscInt levels = mglevels[0]->levels,i; 744b9ad928SBarry Smith 754b9ad928SBarry Smith PetscFunctionBegin; 76a762d673SBarry Smith /* When the DM is supplying the matrix then it will not exist until here */ 77a762d673SBarry Smith for (i=0; i<levels; i++) { 78a762d673SBarry Smith if (!mglevels[i]->A) { 79a762d673SBarry Smith ierr = KSPGetOperators(mglevels[i]->smoothu,&mglevels[i]->A,NULL);CHKERRQ(ierr); 80a762d673SBarry Smith ierr = PetscObjectReference((PetscObject)mglevels[i]->A);CHKERRQ(ierr); 81a762d673SBarry Smith } 82a762d673SBarry Smith } 83391689abSStefano Zampini 84391689abSStefano Zampini ierr = KSPGetPC(mglevels[levels-1]->smoothd,&tpc);CHKERRQ(ierr); 85391689abSStefano Zampini ierr = PCPreSolveChangeRHS(tpc,&changed);CHKERRQ(ierr); 86391689abSStefano Zampini ierr = KSPGetPC(mglevels[levels-1]->smoothu,&tpc);CHKERRQ(ierr); 87391689abSStefano Zampini ierr = PCPreSolveChangeRHS(tpc,&changeu);CHKERRQ(ierr); 88391689abSStefano Zampini if (!changed && !changeu) { 89391689abSStefano Zampini ierr = VecDestroy(&mglevels[levels-1]->b);CHKERRQ(ierr); 90f3fbd535SBarry Smith mglevels[levels-1]->b = b; 91391689abSStefano Zampini } else { /* if the smoother changes the rhs during PreSolve, we cannot use the input vector */ 92391689abSStefano Zampini if (!mglevels[levels-1]->b) { 93391689abSStefano Zampini Vec *vec; 94391689abSStefano Zampini 95391689abSStefano Zampini ierr = KSPCreateVecs(mglevels[levels-1]->smoothd,1,&vec,0,NULL);CHKERRQ(ierr); 96391689abSStefano Zampini mglevels[levels-1]->b = *vec; 977ae21d43SStefano Zampini ierr = PetscFree(vec);CHKERRQ(ierr); 98391689abSStefano Zampini } 99391689abSStefano Zampini ierr = VecCopy(b,mglevels[levels-1]->b);CHKERRQ(ierr); 100391689abSStefano Zampini } 101f3fbd535SBarry Smith mglevels[levels-1]->x = x; 1024b9ad928SBarry Smith 10331567311SBarry Smith mg->rtol = rtol; 10431567311SBarry Smith mg->abstol = abstol; 10531567311SBarry Smith mg->dtol = dtol; 1064b9ad928SBarry Smith if (rtol) { 1074b9ad928SBarry Smith /* compute initial residual norm for relative convergence test */ 1084b9ad928SBarry Smith PetscReal rnorm; 1097319c654SBarry Smith if (zeroguess) { 1107319c654SBarry Smith ierr = VecNorm(b,NORM_2,&rnorm);CHKERRQ(ierr); 1117319c654SBarry Smith } else { 112f3fbd535SBarry Smith ierr = (*mglevels[levels-1]->residual)(mglevels[levels-1]->A,b,x,w);CHKERRQ(ierr); 1134b9ad928SBarry Smith ierr = VecNorm(w,NORM_2,&rnorm);CHKERRQ(ierr); 1147319c654SBarry Smith } 11531567311SBarry Smith mg->ttol = PetscMax(rtol*rnorm,abstol); 1162fa5cd67SKarl Rupp } else if (abstol) mg->ttol = abstol; 1172fa5cd67SKarl Rupp else mg->ttol = 0.0; 1184b9ad928SBarry Smith 1194d0a8057SBarry Smith /* since smoother is applied to full system, not just residual we need to make sure that smoothers don't 120336babb1SJed Brown stop prematurely due to small residual */ 1214d0a8057SBarry Smith for (i=1; i<levels; i++) { 122f3fbd535SBarry Smith ierr = KSPSetTolerances(mglevels[i]->smoothu,0,PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT);CHKERRQ(ierr); 123f3fbd535SBarry Smith if (mglevels[i]->smoothu != mglevels[i]->smoothd) { 12423067569SBarry Smith /* For Richardson the initial guess is nonzero since it is solving in each cycle the original system not just applying as a preconditioner */ 12523067569SBarry Smith ierr = KSPSetInitialGuessNonzero(mglevels[i]->smoothd,PETSC_TRUE);CHKERRQ(ierr); 126f3fbd535SBarry Smith ierr = KSPSetTolerances(mglevels[i]->smoothd,0,PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT);CHKERRQ(ierr); 1274b9ad928SBarry Smith } 1284d0a8057SBarry Smith } 1294d0a8057SBarry Smith 1304d0a8057SBarry Smith *reason = (PCRichardsonConvergedReason)0; 1314d0a8057SBarry Smith for (i=0; i<its; i++) { 132f3fbd535SBarry Smith ierr = PCMGMCycle_Private(pc,mglevels+levels-1,reason);CHKERRQ(ierr); 1334d0a8057SBarry Smith if (*reason) break; 1344d0a8057SBarry Smith } 1354d0a8057SBarry Smith if (!*reason) *reason = PCRICHARDSON_CONVERGED_ITS; 1364d0a8057SBarry Smith *outits = i; 137391689abSStefano Zampini if (!changed && !changeu) mglevels[levels-1]->b = NULL; 1384b9ad928SBarry Smith PetscFunctionReturn(0); 1394b9ad928SBarry Smith } 1404b9ad928SBarry Smith 1413aeaf226SBarry Smith PetscErrorCode PCReset_MG(PC pc) 1423aeaf226SBarry Smith { 1433aeaf226SBarry Smith PC_MG *mg = (PC_MG*)pc->data; 1443aeaf226SBarry Smith PC_MG_Levels **mglevels = mg->levels; 1453aeaf226SBarry Smith PetscErrorCode ierr; 1463aeaf226SBarry Smith PetscInt i,n; 1473aeaf226SBarry Smith 1483aeaf226SBarry Smith PetscFunctionBegin; 1493aeaf226SBarry Smith if (mglevels) { 1503aeaf226SBarry Smith n = mglevels[0]->levels; 1513aeaf226SBarry Smith for (i=0; i<n-1; i++) { 1523aeaf226SBarry Smith ierr = VecDestroy(&mglevels[i+1]->r);CHKERRQ(ierr); 1533aeaf226SBarry Smith ierr = VecDestroy(&mglevels[i]->b);CHKERRQ(ierr); 1543aeaf226SBarry Smith ierr = VecDestroy(&mglevels[i]->x);CHKERRQ(ierr); 1553aeaf226SBarry Smith ierr = MatDestroy(&mglevels[i+1]->restrct);CHKERRQ(ierr); 1563aeaf226SBarry Smith ierr = MatDestroy(&mglevels[i+1]->interpolate);CHKERRQ(ierr); 1570de8493bSLawrence Mitchell ierr = MatDestroy(&mglevels[i+1]->inject);CHKERRQ(ierr); 15873250ac0SBarry Smith ierr = VecDestroy(&mglevels[i+1]->rscale);CHKERRQ(ierr); 1593aeaf226SBarry Smith } 160391689abSStefano Zampini /* this is not null only if the smoother on the finest level 161391689abSStefano Zampini changes the rhs during PreSolve */ 162391689abSStefano Zampini ierr = VecDestroy(&mglevels[n-1]->b);CHKERRQ(ierr); 1633aeaf226SBarry Smith 1643aeaf226SBarry Smith for (i=0; i<n; i++) { 1653aeaf226SBarry Smith ierr = MatDestroy(&mglevels[i]->A);CHKERRQ(ierr); 1663aeaf226SBarry Smith if (mglevels[i]->smoothd != mglevels[i]->smoothu) { 1673aeaf226SBarry Smith ierr = KSPReset(mglevels[i]->smoothd);CHKERRQ(ierr); 1683aeaf226SBarry Smith } 1693aeaf226SBarry Smith ierr = KSPReset(mglevels[i]->smoothu);CHKERRQ(ierr); 1703aeaf226SBarry Smith } 1713aeaf226SBarry Smith } 1723aeaf226SBarry Smith PetscFunctionReturn(0); 1733aeaf226SBarry Smith } 1743aeaf226SBarry Smith 1754b9ad928SBarry Smith /*@C 17697177400SBarry Smith PCMGSetLevels - Sets the number of levels to use with MG. 1774b9ad928SBarry Smith Must be called before any other MG routine. 1784b9ad928SBarry Smith 179ad4df100SBarry Smith Logically Collective on PC 1804b9ad928SBarry Smith 1814b9ad928SBarry Smith Input Parameters: 1824b9ad928SBarry Smith + pc - the preconditioner context 1834b9ad928SBarry Smith . levels - the number of levels 1844b9ad928SBarry Smith - comms - optional communicators for each level; this is to allow solving the coarser problems 1852bf68e3eSBarry Smith on smaller sets of processors. 1864b9ad928SBarry Smith 1874b9ad928SBarry Smith Level: intermediate 1884b9ad928SBarry Smith 1894b9ad928SBarry Smith Notes: 1904b9ad928SBarry Smith If the number of levels is one then the multigrid uses the -mg_levels prefix 1914b9ad928SBarry Smith for setting the level options rather than the -mg_coarse prefix. 1924b9ad928SBarry Smith 1934b9ad928SBarry Smith .keywords: MG, set, levels, multigrid 1944b9ad928SBarry Smith 19597177400SBarry Smith .seealso: PCMGSetType(), PCMGGetLevels() 1964b9ad928SBarry Smith @*/ 1977087cfbeSBarry Smith PetscErrorCode PCMGSetLevels(PC pc,PetscInt levels,MPI_Comm *comms) 1984b9ad928SBarry Smith { 199dfbe8321SBarry Smith PetscErrorCode ierr; 200f3fbd535SBarry Smith PC_MG *mg = (PC_MG*)pc->data; 201ce94432eSBarry Smith MPI_Comm comm; 2023aeaf226SBarry Smith PC_MG_Levels **mglevels = mg->levels; 20310eca3edSLisandro Dalcin PCMGType mgtype = mg->am; 20410167fecSBarry Smith PetscInt mgctype = (PetscInt) PC_MG_CYCLE_V; 205f3fbd535SBarry Smith PetscInt i; 206f3fbd535SBarry Smith PetscMPIInt size; 207f3fbd535SBarry Smith const char *prefix; 208f3fbd535SBarry Smith PC ipc; 209*e952c529SMatthew G. Knepley PetscBool ismg; 2103aeaf226SBarry Smith PetscInt n; 2114b9ad928SBarry Smith 2124b9ad928SBarry Smith PetscFunctionBegin; 2130700a824SBarry Smith PetscValidHeaderSpecific(pc,PC_CLASSID,1); 214548767e0SJed Brown PetscValidLogicalCollectiveInt(pc,levels,2); 215*e952c529SMatthew G. Knepley ierr = PetscObjectTypeCompare((PetscObject) pc, PCMG, &ismg);CHKERRQ(ierr); 216*e952c529SMatthew G. Knepley if (!ismg) PetscFunctionReturn(0); 217548767e0SJed Brown if (mg->nlevels == levels) PetscFunctionReturn(0); 2181a97d7b6SStefano Zampini ierr = PetscObjectGetComm((PetscObject)pc,&comm);CHKERRQ(ierr); 2193aeaf226SBarry Smith if (mglevels) { 22010eca3edSLisandro Dalcin mgctype = mglevels[0]->cycles; 2213aeaf226SBarry Smith /* changing the number of levels so free up the previous stuff */ 2223aeaf226SBarry Smith ierr = PCReset_MG(pc);CHKERRQ(ierr); 2233aeaf226SBarry Smith n = mglevels[0]->levels; 2243aeaf226SBarry Smith for (i=0; i<n; i++) { 2253aeaf226SBarry Smith if (mglevels[i]->smoothd != mglevels[i]->smoothu) { 2263aeaf226SBarry Smith ierr = KSPDestroy(&mglevels[i]->smoothd);CHKERRQ(ierr); 2273aeaf226SBarry Smith } 2283aeaf226SBarry Smith ierr = KSPDestroy(&mglevels[i]->smoothu);CHKERRQ(ierr); 2293aeaf226SBarry Smith ierr = PetscFree(mglevels[i]);CHKERRQ(ierr); 2303aeaf226SBarry Smith } 2313aeaf226SBarry Smith ierr = PetscFree(mg->levels);CHKERRQ(ierr); 2323aeaf226SBarry Smith } 233f3fbd535SBarry Smith 234f3fbd535SBarry Smith mg->nlevels = levels; 235f3fbd535SBarry Smith 236785e854fSJed Brown ierr = PetscMalloc1(levels,&mglevels);CHKERRQ(ierr); 2373bb1ff40SBarry Smith ierr = PetscLogObjectMemory((PetscObject)pc,levels*(sizeof(PC_MG*)));CHKERRQ(ierr); 238f3fbd535SBarry Smith 239f3fbd535SBarry Smith ierr = PCGetOptionsPrefix(pc,&prefix);CHKERRQ(ierr); 240f3fbd535SBarry Smith 241a9db87a2SMatthew G Knepley mg->stageApply = 0; 242f3fbd535SBarry Smith for (i=0; i<levels; i++) { 243b00a9115SJed Brown ierr = PetscNewLog(pc,&mglevels[i]);CHKERRQ(ierr); 2442fa5cd67SKarl Rupp 245f3fbd535SBarry Smith mglevels[i]->level = i; 246f3fbd535SBarry Smith mglevels[i]->levels = levels; 24710eca3edSLisandro Dalcin mglevels[i]->cycles = mgctype; 248336babb1SJed Brown mg->default_smoothu = 2; 249336babb1SJed Brown mg->default_smoothd = 2; 25063e6d426SJed Brown mglevels[i]->eventsmoothsetup = 0; 25163e6d426SJed Brown mglevels[i]->eventsmoothsolve = 0; 25263e6d426SJed Brown mglevels[i]->eventresidual = 0; 25363e6d426SJed Brown mglevels[i]->eventinterprestrict = 0; 254f3fbd535SBarry Smith 255f3fbd535SBarry Smith if (comms) comm = comms[i]; 256f3fbd535SBarry Smith ierr = KSPCreate(comm,&mglevels[i]->smoothd);CHKERRQ(ierr); 257422a814eSBarry Smith ierr = KSPSetErrorIfNotConverged(mglevels[i]->smoothd,pc->erroriffailure);CHKERRQ(ierr); 2580ee9a668SBarry Smith ierr = PetscObjectIncrementTabLevel((PetscObject)mglevels[i]->smoothd,(PetscObject)pc,levels-i);CHKERRQ(ierr); 2590ee9a668SBarry Smith ierr = KSPSetOptionsPrefix(mglevels[i]->smoothd,prefix);CHKERRQ(ierr); 2600ee9a668SBarry Smith ierr = PetscObjectComposedDataSetInt((PetscObject) mglevels[i]->smoothd, PetscMGLevelId, mglevels[i]->level);CHKERRQ(ierr); 2610ee9a668SBarry Smith if (i || levels == 1) { 2620ee9a668SBarry Smith char tprefix[128]; 2630ee9a668SBarry Smith 264336babb1SJed Brown ierr = KSPSetType(mglevels[i]->smoothd,KSPCHEBYSHEV);CHKERRQ(ierr); 2650059c7bdSJed Brown ierr = KSPSetConvergenceTest(mglevels[i]->smoothd,KSPConvergedSkip,NULL,NULL);CHKERRQ(ierr); 266336babb1SJed Brown ierr = KSPSetNormType(mglevels[i]->smoothd,KSP_NORM_NONE);CHKERRQ(ierr); 267336babb1SJed Brown ierr = KSPGetPC(mglevels[i]->smoothd,&ipc);CHKERRQ(ierr); 268336babb1SJed Brown ierr = PCSetType(ipc,PCSOR);CHKERRQ(ierr); 2690ee9a668SBarry Smith ierr = KSPSetTolerances(mglevels[i]->smoothd,PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT, mg->default_smoothd);CHKERRQ(ierr); 270f3fbd535SBarry Smith 2710ee9a668SBarry Smith sprintf(tprefix,"mg_levels_%d_",(int)i); 2720ee9a668SBarry Smith ierr = KSPAppendOptionsPrefix(mglevels[i]->smoothd,tprefix);CHKERRQ(ierr); 2730ee9a668SBarry Smith } else { 274f3fbd535SBarry Smith ierr = KSPAppendOptionsPrefix(mglevels[0]->smoothd,"mg_coarse_");CHKERRQ(ierr); 275f3fbd535SBarry Smith 2769dbfc187SHong Zhang /* coarse solve is (redundant) LU by default; set shifttype NONZERO to avoid annoying zero-pivot in LU preconditioner */ 277f3fbd535SBarry Smith ierr = KSPSetType(mglevels[0]->smoothd,KSPPREONLY);CHKERRQ(ierr); 278f3fbd535SBarry Smith ierr = KSPGetPC(mglevels[0]->smoothd,&ipc);CHKERRQ(ierr); 279f3fbd535SBarry Smith ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr); 280f3fbd535SBarry Smith if (size > 1) { 281f3fbd535SBarry Smith ierr = PCSetType(ipc,PCREDUNDANT);CHKERRQ(ierr); 282f3fbd535SBarry Smith } else { 283f3fbd535SBarry Smith ierr = PCSetType(ipc,PCLU);CHKERRQ(ierr); 284f3fbd535SBarry Smith } 285753b7fb9SBarry Smith ierr = PCFactorSetShiftType(ipc,MAT_SHIFT_INBLOCKS);CHKERRQ(ierr); 286f3fbd535SBarry Smith } 2873bb1ff40SBarry Smith ierr = PetscLogObjectParent((PetscObject)pc,(PetscObject)mglevels[i]->smoothd);CHKERRQ(ierr); 2882fa5cd67SKarl Rupp 289f3fbd535SBarry Smith mglevels[i]->smoothu = mglevels[i]->smoothd; 29031567311SBarry Smith mg->rtol = 0.0; 29131567311SBarry Smith mg->abstol = 0.0; 29231567311SBarry Smith mg->dtol = 0.0; 29331567311SBarry Smith mg->ttol = 0.0; 29431567311SBarry Smith mg->cyclesperpcapply = 1; 295f3fbd535SBarry Smith } 296f3fbd535SBarry Smith mg->levels = mglevels; 29710eca3edSLisandro Dalcin ierr = PCMGSetType(pc,mgtype);CHKERRQ(ierr); 2984b9ad928SBarry Smith PetscFunctionReturn(0); 2994b9ad928SBarry Smith } 3004b9ad928SBarry Smith 301c07bf074SBarry Smith 302c07bf074SBarry Smith PetscErrorCode PCDestroy_MG(PC pc) 303c07bf074SBarry Smith { 304c07bf074SBarry Smith PetscErrorCode ierr; 305a06653b4SBarry Smith PC_MG *mg = (PC_MG*)pc->data; 306a06653b4SBarry Smith PC_MG_Levels **mglevels = mg->levels; 307a06653b4SBarry Smith PetscInt i,n; 308c07bf074SBarry Smith 309c07bf074SBarry Smith PetscFunctionBegin; 310a06653b4SBarry Smith ierr = PCReset_MG(pc);CHKERRQ(ierr); 311a06653b4SBarry Smith if (mglevels) { 312a06653b4SBarry Smith n = mglevels[0]->levels; 313a06653b4SBarry Smith for (i=0; i<n; i++) { 314a06653b4SBarry Smith if (mglevels[i]->smoothd != mglevels[i]->smoothu) { 3156bf464f9SBarry Smith ierr = KSPDestroy(&mglevels[i]->smoothd);CHKERRQ(ierr); 316a06653b4SBarry Smith } 3176bf464f9SBarry Smith ierr = KSPDestroy(&mglevels[i]->smoothu);CHKERRQ(ierr); 318a06653b4SBarry Smith ierr = PetscFree(mglevels[i]);CHKERRQ(ierr); 319a06653b4SBarry Smith } 320a06653b4SBarry Smith ierr = PetscFree(mg->levels);CHKERRQ(ierr); 321a06653b4SBarry Smith } 322c31cb41cSBarry Smith ierr = PetscFree(pc->data);CHKERRQ(ierr); 323f3fbd535SBarry Smith PetscFunctionReturn(0); 324f3fbd535SBarry Smith } 325f3fbd535SBarry Smith 326f3fbd535SBarry Smith 327f3fbd535SBarry Smith 32809573ac7SBarry Smith extern PetscErrorCode PCMGACycle_Private(PC,PC_MG_Levels**); 32909573ac7SBarry Smith extern PetscErrorCode PCMGFCycle_Private(PC,PC_MG_Levels**); 33009573ac7SBarry Smith extern PetscErrorCode PCMGKCycle_Private(PC,PC_MG_Levels**); 331f3fbd535SBarry Smith 332f3fbd535SBarry Smith /* 333f3fbd535SBarry Smith PCApply_MG - Runs either an additive, multiplicative, Kaskadic 334f3fbd535SBarry Smith or full cycle of multigrid. 335f3fbd535SBarry Smith 336f3fbd535SBarry Smith Note: 337f3fbd535SBarry Smith A simple wrapper which calls PCMGMCycle(),PCMGACycle(), or PCMGFCycle(). 338f3fbd535SBarry Smith */ 339f3fbd535SBarry Smith static PetscErrorCode PCApply_MG(PC pc,Vec b,Vec x) 340f3fbd535SBarry Smith { 341f3fbd535SBarry Smith PC_MG *mg = (PC_MG*)pc->data; 342f3fbd535SBarry Smith PC_MG_Levels **mglevels = mg->levels; 343f3fbd535SBarry Smith PetscErrorCode ierr; 344391689abSStefano Zampini PC tpc; 345f3fbd535SBarry Smith PetscInt levels = mglevels[0]->levels,i; 346391689abSStefano Zampini PetscBool changeu,changed; 347f3fbd535SBarry Smith 348f3fbd535SBarry Smith PetscFunctionBegin; 349a9db87a2SMatthew G Knepley if (mg->stageApply) {ierr = PetscLogStagePush(mg->stageApply);CHKERRQ(ierr);} 350e1d8e5deSBarry Smith /* When the DM is supplying the matrix then it will not exist until here */ 351298cc208SBarry Smith for (i=0; i<levels; i++) { 352e1d8e5deSBarry Smith if (!mglevels[i]->A) { 35323ee1639SBarry Smith ierr = KSPGetOperators(mglevels[i]->smoothu,&mglevels[i]->A,NULL);CHKERRQ(ierr); 354298cc208SBarry Smith ierr = PetscObjectReference((PetscObject)mglevels[i]->A);CHKERRQ(ierr); 355e1d8e5deSBarry Smith } 356e1d8e5deSBarry Smith } 357e1d8e5deSBarry Smith 358391689abSStefano Zampini ierr = KSPGetPC(mglevels[levels-1]->smoothd,&tpc);CHKERRQ(ierr); 359391689abSStefano Zampini ierr = PCPreSolveChangeRHS(tpc,&changed);CHKERRQ(ierr); 360391689abSStefano Zampini ierr = KSPGetPC(mglevels[levels-1]->smoothu,&tpc);CHKERRQ(ierr); 361391689abSStefano Zampini ierr = PCPreSolveChangeRHS(tpc,&changeu);CHKERRQ(ierr); 362391689abSStefano Zampini if (!changeu && !changed) { 363391689abSStefano Zampini ierr = VecDestroy(&mglevels[levels-1]->b);CHKERRQ(ierr); 364f3fbd535SBarry Smith mglevels[levels-1]->b = b; 365391689abSStefano Zampini } else { /* if the smoother changes the rhs during PreSolve, we cannot use the input vector */ 366391689abSStefano Zampini if (!mglevels[levels-1]->b) { 367391689abSStefano Zampini Vec *vec; 368391689abSStefano Zampini 369391689abSStefano Zampini ierr = KSPCreateVecs(mglevels[levels-1]->smoothd,1,&vec,0,NULL);CHKERRQ(ierr); 370391689abSStefano Zampini mglevels[levels-1]->b = *vec; 3717ae21d43SStefano Zampini ierr = PetscFree(vec);CHKERRQ(ierr); 372391689abSStefano Zampini } 373391689abSStefano Zampini ierr = VecCopy(b,mglevels[levels-1]->b);CHKERRQ(ierr); 374391689abSStefano Zampini } 375f3fbd535SBarry Smith mglevels[levels-1]->x = x; 376391689abSStefano Zampini 37731567311SBarry Smith if (mg->am == PC_MG_MULTIPLICATIVE) { 378f3fbd535SBarry Smith ierr = VecSet(x,0.0);CHKERRQ(ierr); 37931567311SBarry Smith for (i=0; i<mg->cyclesperpcapply; i++) { 3800298fd71SBarry Smith ierr = PCMGMCycle_Private(pc,mglevels+levels-1,NULL);CHKERRQ(ierr); 381f3fbd535SBarry Smith } 3822fa5cd67SKarl Rupp } else if (mg->am == PC_MG_ADDITIVE) { 38331567311SBarry Smith ierr = PCMGACycle_Private(pc,mglevels);CHKERRQ(ierr); 3842fa5cd67SKarl Rupp } else if (mg->am == PC_MG_KASKADE) { 38531567311SBarry Smith ierr = PCMGKCycle_Private(pc,mglevels);CHKERRQ(ierr); 3862fa5cd67SKarl Rupp } else { 387f3fbd535SBarry Smith ierr = PCMGFCycle_Private(pc,mglevels);CHKERRQ(ierr); 388f3fbd535SBarry Smith } 389a9db87a2SMatthew G Knepley if (mg->stageApply) {ierr = PetscLogStagePop();CHKERRQ(ierr);} 390391689abSStefano Zampini if (!changeu && !changed) mglevels[levels-1]->b = NULL; 391f3fbd535SBarry Smith PetscFunctionReturn(0); 392f3fbd535SBarry Smith } 393f3fbd535SBarry Smith 394f3fbd535SBarry Smith 3954416b707SBarry Smith PetscErrorCode PCSetFromOptions_MG(PetscOptionItems *PetscOptionsObject,PC pc) 396f3fbd535SBarry Smith { 397f3fbd535SBarry Smith PetscErrorCode ierr; 398710315b6SLawrence Mitchell PetscInt levels,cycles; 3992134b1e4SBarry Smith PetscBool flg; 400f3fbd535SBarry Smith PC_MG *mg = (PC_MG*)pc->data; 4013d3eaba7SBarry Smith PC_MG_Levels **mglevels; 402f3fbd535SBarry Smith PCMGType mgtype; 403f3fbd535SBarry Smith PCMGCycleType mgctype; 4042134b1e4SBarry Smith PCMGGalerkinType gtype; 405f3fbd535SBarry Smith 406f3fbd535SBarry Smith PetscFunctionBegin; 4071d743356SStefano Zampini levels = PetscMax(mg->nlevels,1); 408e55864a3SBarry Smith ierr = PetscOptionsHead(PetscOptionsObject,"Multigrid options");CHKERRQ(ierr); 409f3fbd535SBarry Smith ierr = PetscOptionsInt("-pc_mg_levels","Number of Levels","PCMGSetLevels",levels,&levels,&flg);CHKERRQ(ierr); 4101a97d7b6SStefano Zampini if (!flg && !mg->levels && pc->dm) { 411eb3f98d2SBarry Smith ierr = DMGetRefineLevel(pc->dm,&levels);CHKERRQ(ierr); 412eb3f98d2SBarry Smith levels++; 4133aeaf226SBarry Smith mg->usedmfornumberoflevels = PETSC_TRUE; 414eb3f98d2SBarry Smith } 4150298fd71SBarry Smith ierr = PCMGSetLevels(pc,levels,NULL);CHKERRQ(ierr); 4163aeaf226SBarry Smith mglevels = mg->levels; 4173aeaf226SBarry Smith 418f3fbd535SBarry Smith mgctype = (PCMGCycleType) mglevels[0]->cycles; 419f3fbd535SBarry Smith ierr = PetscOptionsEnum("-pc_mg_cycle_type","V cycle or for W-cycle","PCMGSetCycleType",PCMGCycleTypes,(PetscEnum)mgctype,(PetscEnum*)&mgctype,&flg);CHKERRQ(ierr); 420f3fbd535SBarry Smith if (flg) { 421f3fbd535SBarry Smith ierr = PCMGSetCycleType(pc,mgctype);CHKERRQ(ierr); 4222fa5cd67SKarl Rupp } 4232134b1e4SBarry Smith gtype = mg->galerkin; 4242134b1e4SBarry Smith ierr = PetscOptionsEnum("-pc_mg_galerkin","Use Galerkin process to compute coarser operators","PCMGSetGalerkin",PCMGGalerkinTypes,(PetscEnum)gtype,(PetscEnum*)>ype,&flg);CHKERRQ(ierr); 4252134b1e4SBarry Smith if (flg) { 4262134b1e4SBarry Smith ierr = PCMGSetGalerkin(pc,gtype);CHKERRQ(ierr); 427f3fbd535SBarry Smith } 428f56b1265SBarry Smith flg = PETSC_FALSE; 429f442ab6aSBarry Smith ierr = PetscOptionsBool("-pc_mg_distinct_smoothup","Create seperate smoothup KSP and append the prefix _up","PCMGSetDistinctSmoothUp",PETSC_FALSE,&flg,NULL);CHKERRQ(ierr); 430f442ab6aSBarry Smith if (flg) { 431f442ab6aSBarry Smith ierr = PCMGSetDistinctSmoothUp(pc);CHKERRQ(ierr); 432f442ab6aSBarry Smith } 43331567311SBarry Smith mgtype = mg->am; 434f3fbd535SBarry Smith ierr = PetscOptionsEnum("-pc_mg_type","Multigrid type","PCMGSetType",PCMGTypes,(PetscEnum)mgtype,(PetscEnum*)&mgtype,&flg);CHKERRQ(ierr); 435f3fbd535SBarry Smith if (flg) { 436f3fbd535SBarry Smith ierr = PCMGSetType(pc,mgtype);CHKERRQ(ierr); 437f3fbd535SBarry Smith } 43831567311SBarry Smith if (mg->am == PC_MG_MULTIPLICATIVE) { 4395363c1e0SLisandro Dalcin ierr = PetscOptionsInt("-pc_mg_multiplicative_cycles","Number of cycles for each preconditioner step","PCMGMultiplicativeSetCycles",mg->cyclesperpcapply,&cycles,&flg);CHKERRQ(ierr); 440f3fbd535SBarry Smith if (flg) { 441f3fbd535SBarry Smith ierr = PCMGMultiplicativeSetCycles(pc,cycles);CHKERRQ(ierr); 442f3fbd535SBarry Smith } 443f3fbd535SBarry Smith } 444f3fbd535SBarry Smith flg = PETSC_FALSE; 4450298fd71SBarry Smith ierr = PetscOptionsBool("-pc_mg_log","Log times for each multigrid level","None",flg,&flg,NULL);CHKERRQ(ierr); 446f3fbd535SBarry Smith if (flg) { 447f3fbd535SBarry Smith PetscInt i; 448f3fbd535SBarry Smith char eventname[128]; 4491a97d7b6SStefano Zampini 450f3fbd535SBarry Smith levels = mglevels[0]->levels; 451f3fbd535SBarry Smith for (i=0; i<levels; i++) { 452f3fbd535SBarry Smith sprintf(eventname,"MGSetup Level %d",(int)i); 45363e6d426SJed Brown ierr = PetscLogEventRegister(eventname,((PetscObject)pc)->classid,&mglevels[i]->eventsmoothsetup);CHKERRQ(ierr); 454f3fbd535SBarry Smith sprintf(eventname,"MGSmooth Level %d",(int)i); 45563e6d426SJed Brown ierr = PetscLogEventRegister(eventname,((PetscObject)pc)->classid,&mglevels[i]->eventsmoothsolve);CHKERRQ(ierr); 456f3fbd535SBarry Smith if (i) { 457f3fbd535SBarry Smith sprintf(eventname,"MGResid Level %d",(int)i); 45863e6d426SJed Brown ierr = PetscLogEventRegister(eventname,((PetscObject)pc)->classid,&mglevels[i]->eventresidual);CHKERRQ(ierr); 459f3fbd535SBarry Smith sprintf(eventname,"MGInterp Level %d",(int)i); 46063e6d426SJed Brown ierr = PetscLogEventRegister(eventname,((PetscObject)pc)->classid,&mglevels[i]->eventinterprestrict);CHKERRQ(ierr); 461f3fbd535SBarry Smith } 462f3fbd535SBarry Smith } 463eec35531SMatthew G Knepley 464ec60ca73SSatish Balay #if defined(PETSC_USE_LOG) 465eec35531SMatthew G Knepley { 466eec35531SMatthew G Knepley const char *sname = "MG Apply"; 467eec35531SMatthew G Knepley PetscStageLog stageLog; 468eec35531SMatthew G Knepley PetscInt st; 469eec35531SMatthew G Knepley 470eec35531SMatthew G Knepley ierr = PetscLogGetStageLog(&stageLog);CHKERRQ(ierr); 471eec35531SMatthew G Knepley for (st = 0; st < stageLog->numStages; ++st) { 472eec35531SMatthew G Knepley PetscBool same; 473eec35531SMatthew G Knepley 474eec35531SMatthew G Knepley ierr = PetscStrcmp(stageLog->stageInfo[st].name, sname, &same);CHKERRQ(ierr); 4752fa5cd67SKarl Rupp if (same) mg->stageApply = st; 476eec35531SMatthew G Knepley } 477eec35531SMatthew G Knepley if (!mg->stageApply) { 478eec35531SMatthew G Knepley ierr = PetscLogStageRegister(sname, &mg->stageApply);CHKERRQ(ierr); 479eec35531SMatthew G Knepley } 480eec35531SMatthew G Knepley } 481ec60ca73SSatish Balay #endif 482f3fbd535SBarry Smith } 483f3fbd535SBarry Smith ierr = PetscOptionsTail();CHKERRQ(ierr); 484f3fbd535SBarry Smith PetscFunctionReturn(0); 485f3fbd535SBarry Smith } 486f3fbd535SBarry Smith 4876a6fc655SJed Brown const char *const PCMGTypes[] = {"MULTIPLICATIVE","ADDITIVE","FULL","KASKADE","PCMGType","PC_MG",0}; 4886a6fc655SJed Brown const char *const PCMGCycleTypes[] = {"invalid","v","w","PCMGCycleType","PC_MG_CYCLE",0}; 4892134b1e4SBarry Smith const char *const PCMGGalerkinTypes[] = {"both","pmat","mat","none","external","PCMGGalerkinType","PC_MG_GALERKIN",0}; 490f3fbd535SBarry Smith 4919804daf3SBarry Smith #include <petscdraw.h> 492f3fbd535SBarry Smith PetscErrorCode PCView_MG(PC pc,PetscViewer viewer) 493f3fbd535SBarry Smith { 494f3fbd535SBarry Smith PC_MG *mg = (PC_MG*)pc->data; 495f3fbd535SBarry Smith PC_MG_Levels **mglevels = mg->levels; 496f3fbd535SBarry Smith PetscErrorCode ierr; 497e3deeeafSJed Brown PetscInt levels = mglevels ? mglevels[0]->levels : 0,i; 498219b1045SBarry Smith PetscBool iascii,isbinary,isdraw; 499f3fbd535SBarry Smith 500f3fbd535SBarry Smith PetscFunctionBegin; 501251f4c67SDmitry Karpeev ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr); 5025b0b0462SBarry Smith ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERBINARY,&isbinary);CHKERRQ(ierr); 503219b1045SBarry Smith ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERDRAW,&isdraw);CHKERRQ(ierr); 504f3fbd535SBarry Smith if (iascii) { 505e3deeeafSJed Brown const char *cyclename = levels ? (mglevels[0]->cycles == PC_MG_CYCLE_V ? "v" : "w") : "unknown"; 506efd4aadfSBarry Smith ierr = PetscViewerASCIIPrintf(viewer," type is %s, levels=%D cycles=%s\n", PCMGTypes[mg->am],levels,cyclename);CHKERRQ(ierr); 50731567311SBarry Smith if (mg->am == PC_MG_MULTIPLICATIVE) { 50831567311SBarry Smith ierr = PetscViewerASCIIPrintf(viewer," Cycles per PCApply=%d\n",mg->cyclesperpcapply);CHKERRQ(ierr); 509f3fbd535SBarry Smith } 5102134b1e4SBarry Smith if (mg->galerkin == PC_MG_GALERKIN_BOTH) { 511f3fbd535SBarry Smith ierr = PetscViewerASCIIPrintf(viewer," Using Galerkin computed coarse grid matrices\n");CHKERRQ(ierr); 5122134b1e4SBarry Smith } else if (mg->galerkin == PC_MG_GALERKIN_PMAT) { 5132134b1e4SBarry Smith ierr = PetscViewerASCIIPrintf(viewer," Using Galerkin computed coarse grid matrices for pmat\n");CHKERRQ(ierr); 5142134b1e4SBarry Smith } else if (mg->galerkin == PC_MG_GALERKIN_MAT) { 5152134b1e4SBarry Smith ierr = PetscViewerASCIIPrintf(viewer," Using Galerkin computed coarse grid matrices for mat\n");CHKERRQ(ierr); 5162134b1e4SBarry Smith } else if (mg->galerkin == PC_MG_GALERKIN_EXTERNAL) { 5172134b1e4SBarry Smith ierr = PetscViewerASCIIPrintf(viewer," Using externally compute Galerkin coarse grid matrices\n");CHKERRQ(ierr); 5184f66f45eSBarry Smith } else { 5194f66f45eSBarry Smith ierr = PetscViewerASCIIPrintf(viewer," Not using Galerkin computed coarse grid matrices\n");CHKERRQ(ierr); 520f3fbd535SBarry Smith } 5215adeb434SBarry Smith if (mg->view){ 5225adeb434SBarry Smith ierr = (*mg->view)(pc,viewer);CHKERRQ(ierr); 5235adeb434SBarry Smith } 524f3fbd535SBarry Smith for (i=0; i<levels; i++) { 525f3fbd535SBarry Smith if (!i) { 52689cce641SBarry Smith ierr = PetscViewerASCIIPrintf(viewer,"Coarse grid solver -- level -------------------------------\n",i);CHKERRQ(ierr); 527f3fbd535SBarry Smith } else { 52889cce641SBarry Smith ierr = PetscViewerASCIIPrintf(viewer,"Down solver (pre-smoother) on level %D -------------------------------\n",i);CHKERRQ(ierr); 529f3fbd535SBarry Smith } 530f3fbd535SBarry Smith ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); 531f3fbd535SBarry Smith ierr = KSPView(mglevels[i]->smoothd,viewer);CHKERRQ(ierr); 532f3fbd535SBarry Smith ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); 533f3fbd535SBarry Smith if (i && mglevels[i]->smoothd == mglevels[i]->smoothu) { 534f3fbd535SBarry Smith ierr = PetscViewerASCIIPrintf(viewer,"Up solver (post-smoother) same as down solver (pre-smoother)\n");CHKERRQ(ierr); 535f3fbd535SBarry Smith } else if (i) { 53689cce641SBarry Smith ierr = PetscViewerASCIIPrintf(viewer,"Up solver (post-smoother) on level %D -------------------------------\n",i);CHKERRQ(ierr); 537f3fbd535SBarry Smith ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); 538f3fbd535SBarry Smith ierr = KSPView(mglevels[i]->smoothu,viewer);CHKERRQ(ierr); 539f3fbd535SBarry Smith ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); 540f3fbd535SBarry Smith } 541f3fbd535SBarry Smith } 5425b0b0462SBarry Smith } else if (isbinary) { 5435b0b0462SBarry Smith for (i=levels-1; i>=0; i--) { 5445b0b0462SBarry Smith ierr = KSPView(mglevels[i]->smoothd,viewer);CHKERRQ(ierr); 5455b0b0462SBarry Smith if (i && mglevels[i]->smoothd != mglevels[i]->smoothu) { 5465b0b0462SBarry Smith ierr = KSPView(mglevels[i]->smoothu,viewer);CHKERRQ(ierr); 5475b0b0462SBarry Smith } 5485b0b0462SBarry Smith } 549219b1045SBarry Smith } else if (isdraw) { 550219b1045SBarry Smith PetscDraw draw; 551b4375e8dSPeter Brune PetscReal x,w,y,bottom,th; 552219b1045SBarry Smith ierr = PetscViewerDrawGetDraw(viewer,0,&draw);CHKERRQ(ierr); 553219b1045SBarry Smith ierr = PetscDrawGetCurrentPoint(draw,&x,&y);CHKERRQ(ierr); 5540298fd71SBarry Smith ierr = PetscDrawStringGetSize(draw,NULL,&th);CHKERRQ(ierr); 555219b1045SBarry Smith bottom = y - th; 556219b1045SBarry Smith for (i=levels-1; i>=0; i--) { 557b4375e8dSPeter Brune if (!mglevels[i]->smoothu || (mglevels[i]->smoothu == mglevels[i]->smoothd)) { 558219b1045SBarry Smith ierr = PetscDrawPushCurrentPoint(draw,x,bottom);CHKERRQ(ierr); 559219b1045SBarry Smith ierr = KSPView(mglevels[i]->smoothd,viewer);CHKERRQ(ierr); 560219b1045SBarry Smith ierr = PetscDrawPopCurrentPoint(draw);CHKERRQ(ierr); 561b4375e8dSPeter Brune } else { 562b4375e8dSPeter Brune w = 0.5*PetscMin(1.0-x,x); 563b4375e8dSPeter Brune ierr = PetscDrawPushCurrentPoint(draw,x+w,bottom);CHKERRQ(ierr); 564b4375e8dSPeter Brune ierr = KSPView(mglevels[i]->smoothd,viewer);CHKERRQ(ierr); 565b4375e8dSPeter Brune ierr = PetscDrawPopCurrentPoint(draw);CHKERRQ(ierr); 566b4375e8dSPeter Brune ierr = PetscDrawPushCurrentPoint(draw,x-w,bottom);CHKERRQ(ierr); 567b4375e8dSPeter Brune ierr = KSPView(mglevels[i]->smoothu,viewer);CHKERRQ(ierr); 568b4375e8dSPeter Brune ierr = PetscDrawPopCurrentPoint(draw);CHKERRQ(ierr); 569b4375e8dSPeter Brune } 5700298fd71SBarry Smith ierr = PetscDrawGetBoundingBox(draw,NULL,&bottom,NULL,NULL);CHKERRQ(ierr); 5711cd381d6SBarry Smith bottom -= th; 572219b1045SBarry Smith } 5735b0b0462SBarry Smith } 574f3fbd535SBarry Smith PetscFunctionReturn(0); 575f3fbd535SBarry Smith } 576f3fbd535SBarry Smith 577af0996ceSBarry Smith #include <petsc/private/dmimpl.h> 578af0996ceSBarry Smith #include <petsc/private/kspimpl.h> 579cab2e9ccSBarry Smith 580f3fbd535SBarry Smith /* 581f3fbd535SBarry Smith Calls setup for the KSP on each level 582f3fbd535SBarry Smith */ 583f3fbd535SBarry Smith PetscErrorCode PCSetUp_MG(PC pc) 584f3fbd535SBarry Smith { 585f3fbd535SBarry Smith PC_MG *mg = (PC_MG*)pc->data; 586f3fbd535SBarry Smith PC_MG_Levels **mglevels = mg->levels; 587f3fbd535SBarry Smith PetscErrorCode ierr; 5881a97d7b6SStefano Zampini PetscInt i,n; 58998e04984SBarry Smith PC cpc; 5903db492dfSBarry Smith PetscBool dump = PETSC_FALSE,opsset,use_amat,missinginterpolate = PETSC_FALSE; 591f3fbd535SBarry Smith Mat dA,dB; 592f3fbd535SBarry Smith Vec tvec; 593218a07d4SBarry Smith DM *dms; 594649052a6SBarry Smith PetscViewer viewer = 0; 5952134b1e4SBarry Smith PetscBool dAeqdB = PETSC_FALSE, needRestricts = PETSC_FALSE; 596f3fbd535SBarry Smith 597f3fbd535SBarry Smith PetscFunctionBegin; 5981a97d7b6SStefano Zampini if (!mglevels) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONGSTATE,"Must set MG levels with PCMGSetLevels() before setting up"); 5991a97d7b6SStefano Zampini n = mglevels[0]->levels; 60001bc414fSDmitry Karpeev /* FIX: Move this to PCSetFromOptions_MG? */ 6013aeaf226SBarry Smith if (mg->usedmfornumberoflevels) { 6023aeaf226SBarry Smith PetscInt levels; 6033aeaf226SBarry Smith ierr = DMGetRefineLevel(pc->dm,&levels);CHKERRQ(ierr); 6043aeaf226SBarry Smith levels++; 6053aeaf226SBarry Smith if (levels > n) { /* the problem is now being solved on a finer grid */ 6060298fd71SBarry Smith ierr = PCMGSetLevels(pc,levels,NULL);CHKERRQ(ierr); 6073aeaf226SBarry Smith n = levels; 6083aeaf226SBarry Smith ierr = PCSetFromOptions(pc);CHKERRQ(ierr); /* it is bad to call this here, but otherwise will never be called for the new hierarchy */ 6093aeaf226SBarry Smith mglevels = mg->levels; 6103aeaf226SBarry Smith } 6113aeaf226SBarry Smith } 61298e04984SBarry Smith ierr = KSPGetPC(mglevels[0]->smoothd,&cpc);CHKERRQ(ierr); 6133aeaf226SBarry Smith 614f3fbd535SBarry Smith 615f3fbd535SBarry Smith /* If user did not provide fine grid operators OR operator was not updated since last global KSPSetOperators() */ 616f3fbd535SBarry Smith /* so use those from global PC */ 617f3fbd535SBarry Smith /* Is this what we always want? What if user wants to keep old one? */ 6180298fd71SBarry Smith ierr = KSPGetOperatorsSet(mglevels[n-1]->smoothd,NULL,&opsset);CHKERRQ(ierr); 61998e04984SBarry Smith if (opsset) { 62098e04984SBarry Smith Mat mmat; 62123ee1639SBarry Smith ierr = KSPGetOperators(mglevels[n-1]->smoothd,NULL,&mmat);CHKERRQ(ierr); 62298e04984SBarry Smith if (mmat == pc->pmat) opsset = PETSC_FALSE; 62398e04984SBarry Smith } 6244a5f07a5SMark F. Adams 6254a5f07a5SMark F. Adams if (!opsset) { 62671b23a65SMark F. Adams ierr = PCGetUseAmat(pc,&use_amat);CHKERRQ(ierr); 6274a5f07a5SMark F. Adams if(use_amat){ 628f3fbd535SBarry Smith ierr = PetscInfo(pc,"Using outer operators to define finest grid operator \n because PCMGGetSmoother(pc,nlevels-1,&ksp);KSPSetOperators(ksp,...); was not called.\n");CHKERRQ(ierr); 62923ee1639SBarry Smith ierr = KSPSetOperators(mglevels[n-1]->smoothd,pc->mat,pc->pmat);CHKERRQ(ierr); 630f3fbd535SBarry Smith } 6314a5f07a5SMark F. Adams else { 6324a5f07a5SMark F. Adams ierr = PetscInfo(pc,"Using matrix (pmat) operators to define finest grid operator \n because PCMGGetSmoother(pc,nlevels-1,&ksp);KSPSetOperators(ksp,...); was not called.\n");CHKERRQ(ierr); 63323ee1639SBarry Smith ierr = KSPSetOperators(mglevels[n-1]->smoothd,pc->pmat,pc->pmat);CHKERRQ(ierr); 6344a5f07a5SMark F. Adams } 6354a5f07a5SMark F. Adams } 636f3fbd535SBarry Smith 6379c7ffb39SBarry Smith for (i=n-1; i>0; i--) { 6389c7ffb39SBarry Smith if (!(mglevels[i]->interpolate || mglevels[i]->restrct)) { 6399c7ffb39SBarry Smith missinginterpolate = PETSC_TRUE; 6409c7ffb39SBarry Smith continue; 6419c7ffb39SBarry Smith } 6429c7ffb39SBarry Smith } 6432134b1e4SBarry Smith 6442134b1e4SBarry Smith ierr = KSPGetOperators(mglevels[n-1]->smoothd,&dA,&dB);CHKERRQ(ierr); 6452134b1e4SBarry Smith if (dA == dB) dAeqdB = PETSC_TRUE; 6462134b1e4SBarry Smith if ((mg->galerkin == PC_MG_GALERKIN_NONE) || (((mg->galerkin == PC_MG_GALERKIN_PMAT) || (mg->galerkin == PC_MG_GALERKIN_MAT)) && !dAeqdB)) { 6472134b1e4SBarry Smith needRestricts = PETSC_TRUE; /* user must compute either mat, pmat, or both so must restrict x to coarser levels */ 6482134b1e4SBarry Smith } 6492134b1e4SBarry Smith 6502134b1e4SBarry Smith 6519c7ffb39SBarry Smith /* 6529c7ffb39SBarry Smith Skipping if user has provided all interpolation/restriction needed (since DM might not be able to produce them (when coming from SNES/TS) 6539c7ffb39SBarry Smith Skipping for galerkin==2 (externally managed hierarchy such as ML and GAMG). Cleaner logic here would be great. Wrap ML/GAMG as DMs? 6549c7ffb39SBarry Smith */ 6552134b1e4SBarry Smith if (missinginterpolate && pc->dm && mg->galerkin != PC_MG_GALERKIN_EXTERNAL && !pc->setupcalled) { 6562d2b81a6SBarry Smith /* construct the interpolation from the DMs */ 6572e499ae9SBarry Smith Mat p; 65873250ac0SBarry Smith Vec rscale; 659785e854fSJed Brown ierr = PetscMalloc1(n,&dms);CHKERRQ(ierr); 660218a07d4SBarry Smith dms[n-1] = pc->dm; 661ef1267afSMatthew G. Knepley /* Separately create them so we do not get DMKSP interference between levels */ 662ef1267afSMatthew G. Knepley for (i=n-2; i>-1; i--) {ierr = DMCoarsen(dms[i+1],MPI_COMM_NULL,&dms[i]);CHKERRQ(ierr);} 66341fce8fdSHong Zhang /* 66441fce8fdSHong Zhang Force the mat type of coarse level operator to be AIJ because usually we want to use LU for coarse level. 66541fce8fdSHong Zhang Notice that it can be overwritten by -mat_type because KSPSetUp() reads command line options. 66641fce8fdSHong Zhang But it is safe to use -dm_mat_type. 66741fce8fdSHong Zhang 66841fce8fdSHong Zhang The mat type should not be hardcoded like this, we need to find a better way. 66941fce8fdSHong Zhang ierr = DMSetMatType(dms[0],MATAIJ);CHKERRQ(ierr); 67041fce8fdSHong Zhang */ 671218a07d4SBarry Smith for (i=n-2; i>-1; i--) { 672942e3340SBarry Smith DMKSP kdm; 673eab52d2bSLawrence Mitchell PetscBool dmhasrestrict, dmhasinject; 6743c0c59f3SBarry Smith ierr = KSPSetDM(mglevels[i]->smoothd,dms[i]);CHKERRQ(ierr); 6752134b1e4SBarry Smith if (!needRestricts) {ierr = KSPSetDMActive(mglevels[i]->smoothd,PETSC_FALSE);CHKERRQ(ierr);} 676942e3340SBarry Smith ierr = DMGetDMKSPWrite(dms[i],&kdm);CHKERRQ(ierr); 677d1a3e677SJed Brown /* Ugly hack so that the next KSPSetUp() will use the RHS that we set. A better fix is to change dmActive to take 678d1a3e677SJed Brown * a bitwise OR of computing the matrix, RHS, and initial iterate. */ 6790298fd71SBarry Smith kdm->ops->computerhs = NULL; 6800298fd71SBarry Smith kdm->rhsctx = NULL; 68124c3aa18SBarry Smith if (!mglevels[i+1]->interpolate) { 682e727c939SJed Brown ierr = DMCreateInterpolation(dms[i],dms[i+1],&p,&rscale);CHKERRQ(ierr); 6832d2b81a6SBarry Smith ierr = PCMGSetInterpolation(pc,i+1,p);CHKERRQ(ierr); 68400ac8be1SBarry Smith if (rscale) {ierr = PCMGSetRScale(pc,i+1,rscale);CHKERRQ(ierr);} 68573250ac0SBarry Smith ierr = VecDestroy(&rscale);CHKERRQ(ierr); 6866bf464f9SBarry Smith ierr = MatDestroy(&p);CHKERRQ(ierr); 687218a07d4SBarry Smith } 6883ad4599aSBarry Smith ierr = DMHasCreateRestriction(dms[i],&dmhasrestrict);CHKERRQ(ierr); 6893ad4599aSBarry Smith if (dmhasrestrict && !mglevels[i+1]->restrct){ 6903ad4599aSBarry Smith ierr = DMCreateRestriction(dms[i],dms[i+1],&p);CHKERRQ(ierr); 6913ad4599aSBarry Smith ierr = PCMGSetRestriction(pc,i+1,p);CHKERRQ(ierr); 6923ad4599aSBarry Smith ierr = MatDestroy(&p);CHKERRQ(ierr); 6933ad4599aSBarry Smith } 694eab52d2bSLawrence Mitchell ierr = DMHasCreateInjection(dms[i],&dmhasinject);CHKERRQ(ierr); 695eab52d2bSLawrence Mitchell if (dmhasinject && !mglevels[i+1]->inject){ 696eab52d2bSLawrence Mitchell ierr = DMCreateInjection(dms[i],dms[i+1],&p);CHKERRQ(ierr); 697eab52d2bSLawrence Mitchell ierr = PCMGSetInjection(pc,i+1,p);CHKERRQ(ierr); 698eab52d2bSLawrence Mitchell ierr = MatDestroy(&p);CHKERRQ(ierr); 699eab52d2bSLawrence Mitchell } 70024c3aa18SBarry Smith } 7012d2b81a6SBarry Smith 702ef1267afSMatthew G. Knepley for (i=n-2; i>-1; i--) {ierr = DMDestroy(&dms[i]);CHKERRQ(ierr);} 7032d2b81a6SBarry Smith ierr = PetscFree(dms);CHKERRQ(ierr); 704ce4cda84SJed Brown } 705cab2e9ccSBarry Smith 706ce4cda84SJed Brown if (pc->dm && !pc->setupcalled) { 7072134b1e4SBarry Smith /* finest smoother also gets DM but it is not active, independent of whether galerkin==PC_MG_GALERKIN_EXTERNAL */ 708cab2e9ccSBarry Smith ierr = KSPSetDM(mglevels[n-1]->smoothd,pc->dm);CHKERRQ(ierr); 709cab2e9ccSBarry Smith ierr = KSPSetDMActive(mglevels[n-1]->smoothd,PETSC_FALSE);CHKERRQ(ierr); 710218a07d4SBarry Smith } 711218a07d4SBarry Smith 7122134b1e4SBarry Smith if (mg->galerkin < PC_MG_GALERKIN_NONE) { 7132134b1e4SBarry Smith Mat A,B; 7142134b1e4SBarry Smith PetscBool doA = PETSC_FALSE,doB = PETSC_FALSE; 7152134b1e4SBarry Smith MatReuse reuse = MAT_INITIAL_MATRIX; 7162134b1e4SBarry Smith 7172134b1e4SBarry Smith if ((mg->galerkin == PC_MG_GALERKIN_PMAT) || (mg->galerkin == PC_MG_GALERKIN_BOTH)) doB = PETSC_TRUE; 7182134b1e4SBarry Smith if ((mg->galerkin == PC_MG_GALERKIN_MAT) || ((mg->galerkin == PC_MG_GALERKIN_BOTH) && (dA != dB))) doA = PETSC_TRUE; 7192134b1e4SBarry Smith if (pc->setupcalled) reuse = MAT_REUSE_MATRIX; 720f3fbd535SBarry Smith for (i=n-2; i>-1; i--) { 721b9367914SBarry Smith if (!mglevels[i+1]->restrct && !mglevels[i+1]->interpolate) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONGSTATE,"Must provide interpolation or restriction for each MG level except level 0"); 722b9367914SBarry Smith if (!mglevels[i+1]->interpolate) { 723b9367914SBarry Smith ierr = PCMGSetInterpolation(pc,i+1,mglevels[i+1]->restrct);CHKERRQ(ierr); 724b9367914SBarry Smith } 725b9367914SBarry Smith if (!mglevels[i+1]->restrct) { 726b9367914SBarry Smith ierr = PCMGSetRestriction(pc,i+1,mglevels[i+1]->interpolate);CHKERRQ(ierr); 727b9367914SBarry Smith } 7282134b1e4SBarry Smith if (reuse == MAT_REUSE_MATRIX) { 7292134b1e4SBarry Smith ierr = KSPGetOperators(mglevels[i]->smoothd,&A,&B);CHKERRQ(ierr); 7302134b1e4SBarry Smith } 7312134b1e4SBarry Smith if (doA) { 7322df6c5c3SPatrick Farrell ierr = MatGalerkin(mglevels[i+1]->restrct,dA,mglevels[i+1]->interpolate,reuse,1.0,&A);CHKERRQ(ierr); 7332134b1e4SBarry Smith } 7342134b1e4SBarry Smith if (doB) { 7352df6c5c3SPatrick Farrell ierr = MatGalerkin(mglevels[i+1]->restrct,dB,mglevels[i+1]->interpolate,reuse,1.0,&B);CHKERRQ(ierr); 736b9367914SBarry Smith } 7372134b1e4SBarry Smith /* the management of the PetscObjectReference() and PetscObjecDereference() below is rather delicate */ 7382134b1e4SBarry Smith if (!doA && dAeqdB) { 7392134b1e4SBarry Smith if (reuse == MAT_INITIAL_MATRIX) {ierr = PetscObjectReference((PetscObject)B);CHKERRQ(ierr);} 7402134b1e4SBarry Smith A = B; 7412134b1e4SBarry Smith } else if (!doA && reuse == MAT_INITIAL_MATRIX ) { 7422134b1e4SBarry Smith ierr = KSPGetOperators(mglevels[i]->smoothd,&A,NULL);CHKERRQ(ierr); 7432134b1e4SBarry Smith ierr = PetscObjectReference((PetscObject)A);CHKERRQ(ierr); 744b9367914SBarry Smith } 7452134b1e4SBarry Smith if (!doB && dAeqdB) { 7462134b1e4SBarry Smith if (reuse == MAT_INITIAL_MATRIX) {ierr = PetscObjectReference((PetscObject)A);CHKERRQ(ierr);} 7472134b1e4SBarry Smith B = A; 7482134b1e4SBarry Smith } else if (!doB && reuse == MAT_INITIAL_MATRIX) { 74923ee1639SBarry Smith ierr = KSPGetOperators(mglevels[i]->smoothd,NULL,&B);CHKERRQ(ierr); 7502134b1e4SBarry Smith ierr = PetscObjectReference((PetscObject)B);CHKERRQ(ierr); 7517d537d92SJed Brown } 7522134b1e4SBarry Smith if (reuse == MAT_INITIAL_MATRIX) { 7532134b1e4SBarry Smith ierr = KSPSetOperators(mglevels[i]->smoothd,A,B);CHKERRQ(ierr); 7542134b1e4SBarry Smith ierr = PetscObjectDereference((PetscObject)A);CHKERRQ(ierr); 7552134b1e4SBarry Smith ierr = PetscObjectDereference((PetscObject)B);CHKERRQ(ierr); 7562134b1e4SBarry Smith } 7572134b1e4SBarry Smith dA = A; 758f3fbd535SBarry Smith dB = B; 759f3fbd535SBarry Smith } 760f3fbd535SBarry Smith } 7612134b1e4SBarry Smith if (needRestricts && pc->dm && pc->dm->x) { 762cab2e9ccSBarry Smith /* need to restrict Jacobian location to coarser meshes for evaluation */ 763cab2e9ccSBarry Smith for (i=n-2; i>-1; i--) { 764c88c5224SJed Brown Mat R; 765c88c5224SJed Brown Vec rscale; 766cab2e9ccSBarry Smith if (!mglevels[i]->smoothd->dm->x) { 767cab2e9ccSBarry Smith Vec *vecs; 7682a7a6963SBarry Smith ierr = KSPCreateVecs(mglevels[i]->smoothd,1,&vecs,0,NULL);CHKERRQ(ierr); 769cab2e9ccSBarry Smith mglevels[i]->smoothd->dm->x = vecs[0]; 770cab2e9ccSBarry Smith ierr = PetscFree(vecs);CHKERRQ(ierr); 771cab2e9ccSBarry Smith } 772c88c5224SJed Brown ierr = PCMGGetRestriction(pc,i+1,&R);CHKERRQ(ierr); 773c88c5224SJed Brown ierr = PCMGGetRScale(pc,i+1,&rscale);CHKERRQ(ierr); 774c88c5224SJed Brown ierr = MatRestrict(R,mglevels[i+1]->smoothd->dm->x,mglevels[i]->smoothd->dm->x);CHKERRQ(ierr); 775c88c5224SJed Brown ierr = VecPointwiseMult(mglevels[i]->smoothd->dm->x,mglevels[i]->smoothd->dm->x,rscale);CHKERRQ(ierr); 776cab2e9ccSBarry Smith } 777f3fbd535SBarry Smith } 7782134b1e4SBarry Smith if (needRestricts && pc->dm) { 779caa4e7f2SJed Brown for (i=n-2; i>=0; i--) { 780ccceb50cSJed Brown DM dmfine,dmcoarse; 781caa4e7f2SJed Brown Mat Restrict,Inject; 782caa4e7f2SJed Brown Vec rscale; 783ccceb50cSJed Brown ierr = KSPGetDM(mglevels[i+1]->smoothd,&dmfine);CHKERRQ(ierr); 784ccceb50cSJed Brown ierr = KSPGetDM(mglevels[i]->smoothd,&dmcoarse);CHKERRQ(ierr); 785caa4e7f2SJed Brown ierr = PCMGGetRestriction(pc,i+1,&Restrict);CHKERRQ(ierr); 786caa4e7f2SJed Brown ierr = PCMGGetRScale(pc,i+1,&rscale);CHKERRQ(ierr); 787eab52d2bSLawrence Mitchell ierr = PCMGGetInjection(pc,i+1,&Inject);CHKERRQ(ierr); 788caa4e7f2SJed Brown ierr = DMRestrict(dmfine,Restrict,rscale,Inject,dmcoarse);CHKERRQ(ierr); 789caa4e7f2SJed Brown } 790caa4e7f2SJed Brown } 791f3fbd535SBarry Smith 792f3fbd535SBarry Smith if (!pc->setupcalled) { 793f3fbd535SBarry Smith for (i=0; i<n; i++) { 794f3fbd535SBarry Smith ierr = KSPSetFromOptions(mglevels[i]->smoothd);CHKERRQ(ierr); 795f3fbd535SBarry Smith } 796f3fbd535SBarry Smith for (i=1; i<n; i++) { 797f3fbd535SBarry Smith if (mglevels[i]->smoothu && (mglevels[i]->smoothu != mglevels[i]->smoothd)) { 798f3fbd535SBarry Smith ierr = KSPSetFromOptions(mglevels[i]->smoothu);CHKERRQ(ierr); 799f3fbd535SBarry Smith } 800f3fbd535SBarry Smith } 8013ad4599aSBarry Smith /* insure that if either interpolation or restriction is set the other other one is set */ 802f3fbd535SBarry Smith for (i=1; i<n; i++) { 8033ad4599aSBarry Smith ierr = PCMGGetInterpolation(pc,i,NULL);CHKERRQ(ierr); 8043ad4599aSBarry Smith ierr = PCMGGetRestriction(pc,i,NULL);CHKERRQ(ierr); 805f3fbd535SBarry Smith } 806f3fbd535SBarry Smith for (i=0; i<n-1; i++) { 807f3fbd535SBarry Smith if (!mglevels[i]->b) { 808f3fbd535SBarry Smith Vec *vec; 8092a7a6963SBarry Smith ierr = KSPCreateVecs(mglevels[i]->smoothd,1,&vec,0,NULL);CHKERRQ(ierr); 810f3fbd535SBarry Smith ierr = PCMGSetRhs(pc,i,*vec);CHKERRQ(ierr); 8116bf464f9SBarry Smith ierr = VecDestroy(vec);CHKERRQ(ierr); 812f3fbd535SBarry Smith ierr = PetscFree(vec);CHKERRQ(ierr); 813f3fbd535SBarry Smith } 814f3fbd535SBarry Smith if (!mglevels[i]->r && i) { 815f3fbd535SBarry Smith ierr = VecDuplicate(mglevels[i]->b,&tvec);CHKERRQ(ierr); 816f3fbd535SBarry Smith ierr = PCMGSetR(pc,i,tvec);CHKERRQ(ierr); 8176bf464f9SBarry Smith ierr = VecDestroy(&tvec);CHKERRQ(ierr); 818f3fbd535SBarry Smith } 819f3fbd535SBarry Smith if (!mglevels[i]->x) { 820f3fbd535SBarry Smith ierr = VecDuplicate(mglevels[i]->b,&tvec);CHKERRQ(ierr); 821f3fbd535SBarry Smith ierr = PCMGSetX(pc,i,tvec);CHKERRQ(ierr); 8226bf464f9SBarry Smith ierr = VecDestroy(&tvec);CHKERRQ(ierr); 823f3fbd535SBarry Smith } 824f3fbd535SBarry Smith } 825f3fbd535SBarry Smith if (n != 1 && !mglevels[n-1]->r) { 826f3fbd535SBarry Smith /* PCMGSetR() on the finest level if user did not supply it */ 827f3fbd535SBarry Smith Vec *vec; 8282a7a6963SBarry Smith ierr = KSPCreateVecs(mglevels[n-1]->smoothd,1,&vec,0,NULL);CHKERRQ(ierr); 829f3fbd535SBarry Smith ierr = PCMGSetR(pc,n-1,*vec);CHKERRQ(ierr); 8306bf464f9SBarry Smith ierr = VecDestroy(vec);CHKERRQ(ierr); 831f3fbd535SBarry Smith ierr = PetscFree(vec);CHKERRQ(ierr); 832f3fbd535SBarry Smith } 833f3fbd535SBarry Smith } 834f3fbd535SBarry Smith 83598e04984SBarry Smith if (pc->dm) { 83698e04984SBarry Smith /* need to tell all the coarser levels to rebuild the matrix using the DM for that level */ 83798e04984SBarry Smith for (i=0; i<n-1; i++) { 83898e04984SBarry Smith if (mglevels[i]->smoothd->setupstage != KSP_SETUP_NEW) mglevels[i]->smoothd->setupstage = KSP_SETUP_NEWMATRIX; 83998e04984SBarry Smith } 84098e04984SBarry Smith } 841f3fbd535SBarry Smith 842f3fbd535SBarry Smith for (i=1; i<n; i++) { 8432a21e185SBarry Smith if (mglevels[i]->smoothu == mglevels[i]->smoothd || mg->am == PC_MG_FULL || mg->am == PC_MG_KASKADE || mg->cyclesperpcapply > 1){ 844f3fbd535SBarry Smith /* if doing only down then initial guess is zero */ 845f3fbd535SBarry Smith ierr = KSPSetInitialGuessNonzero(mglevels[i]->smoothd,PETSC_TRUE);CHKERRQ(ierr); 846f3fbd535SBarry Smith } 84763e6d426SJed Brown if (mglevels[i]->eventsmoothsetup) {ierr = PetscLogEventBegin(mglevels[i]->eventsmoothsetup,0,0,0,0);CHKERRQ(ierr);} 848f3fbd535SBarry Smith ierr = KSPSetUp(mglevels[i]->smoothd);CHKERRQ(ierr); 849899639b0SHong Zhang if (mglevels[i]->smoothd->reason == KSP_DIVERGED_PCSETUP_FAILED) { 850899639b0SHong Zhang pc->failedreason = PC_SUBPC_ERROR; 851899639b0SHong Zhang } 85263e6d426SJed Brown if (mglevels[i]->eventsmoothsetup) {ierr = PetscLogEventEnd(mglevels[i]->eventsmoothsetup,0,0,0,0);CHKERRQ(ierr);} 853d42688cbSBarry Smith if (!mglevels[i]->residual) { 854d42688cbSBarry Smith Mat mat; 85513842ffbSBarry Smith ierr = KSPGetOperators(mglevels[i]->smoothd,&mat,NULL);CHKERRQ(ierr); 85654b2cd4bSJed Brown ierr = PCMGSetResidual(pc,i,PCMGResidualDefault,mat);CHKERRQ(ierr); 857d42688cbSBarry Smith } 858f3fbd535SBarry Smith } 859f3fbd535SBarry Smith for (i=1; i<n; i++) { 860f3fbd535SBarry Smith if (mglevels[i]->smoothu && mglevels[i]->smoothu != mglevels[i]->smoothd) { 861f3fbd535SBarry Smith Mat downmat,downpmat; 862f3fbd535SBarry Smith 863f3fbd535SBarry Smith /* check if operators have been set for up, if not use down operators to set them */ 8640298fd71SBarry Smith ierr = KSPGetOperatorsSet(mglevels[i]->smoothu,&opsset,NULL);CHKERRQ(ierr); 865f3fbd535SBarry Smith if (!opsset) { 86623ee1639SBarry Smith ierr = KSPGetOperators(mglevels[i]->smoothd,&downmat,&downpmat);CHKERRQ(ierr); 86723ee1639SBarry Smith ierr = KSPSetOperators(mglevels[i]->smoothu,downmat,downpmat);CHKERRQ(ierr); 868f3fbd535SBarry Smith } 869f3fbd535SBarry Smith 870f3fbd535SBarry Smith ierr = KSPSetInitialGuessNonzero(mglevels[i]->smoothu,PETSC_TRUE);CHKERRQ(ierr); 87163e6d426SJed Brown if (mglevels[i]->eventsmoothsetup) {ierr = PetscLogEventBegin(mglevels[i]->eventsmoothsetup,0,0,0,0);CHKERRQ(ierr);} 872f3fbd535SBarry Smith ierr = KSPSetUp(mglevels[i]->smoothu);CHKERRQ(ierr); 873899639b0SHong Zhang if (mglevels[i]->smoothu->reason == KSP_DIVERGED_PCSETUP_FAILED) { 874899639b0SHong Zhang pc->failedreason = PC_SUBPC_ERROR; 875899639b0SHong Zhang } 87663e6d426SJed Brown if (mglevels[i]->eventsmoothsetup) {ierr = PetscLogEventEnd(mglevels[i]->eventsmoothsetup,0,0,0,0);CHKERRQ(ierr);} 877f3fbd535SBarry Smith } 878f3fbd535SBarry Smith } 879f3fbd535SBarry Smith 88063e6d426SJed Brown if (mglevels[0]->eventsmoothsetup) {ierr = PetscLogEventBegin(mglevels[0]->eventsmoothsetup,0,0,0,0);CHKERRQ(ierr);} 881f3fbd535SBarry Smith ierr = KSPSetUp(mglevels[0]->smoothd);CHKERRQ(ierr); 882899639b0SHong Zhang if (mglevels[0]->smoothd->reason == KSP_DIVERGED_PCSETUP_FAILED) { 883899639b0SHong Zhang pc->failedreason = PC_SUBPC_ERROR; 884899639b0SHong Zhang } 88563e6d426SJed Brown if (mglevels[0]->eventsmoothsetup) {ierr = PetscLogEventEnd(mglevels[0]->eventsmoothsetup,0,0,0,0);CHKERRQ(ierr);} 886f3fbd535SBarry Smith 887f3fbd535SBarry Smith /* 888f3fbd535SBarry Smith Dump the interpolation/restriction matrices plus the 889e3c5b3baSBarry Smith Jacobian/stiffness on each level. This allows MATLAB users to 890f3fbd535SBarry Smith easily check if the Galerkin condition A_c = R A_f R^T is satisfied. 891f3fbd535SBarry Smith 892f3fbd535SBarry Smith Only support one or the other at the same time. 893f3fbd535SBarry Smith */ 894f3fbd535SBarry Smith #if defined(PETSC_USE_SOCKET_VIEWER) 895c5929fdfSBarry Smith ierr = PetscOptionsGetBool(((PetscObject)pc)->options,((PetscObject)pc)->prefix,"-pc_mg_dump_matlab",&dump,NULL);CHKERRQ(ierr); 896ce94432eSBarry Smith if (dump) viewer = PETSC_VIEWER_SOCKET_(PetscObjectComm((PetscObject)pc)); 897f3fbd535SBarry Smith dump = PETSC_FALSE; 898f3fbd535SBarry Smith #endif 899c5929fdfSBarry Smith ierr = PetscOptionsGetBool(((PetscObject)pc)->options,((PetscObject)pc)->prefix,"-pc_mg_dump_binary",&dump,NULL);CHKERRQ(ierr); 900ce94432eSBarry Smith if (dump) viewer = PETSC_VIEWER_BINARY_(PetscObjectComm((PetscObject)pc)); 901f3fbd535SBarry Smith 902f3fbd535SBarry Smith if (viewer) { 903f3fbd535SBarry Smith for (i=1; i<n; i++) { 904f3fbd535SBarry Smith ierr = MatView(mglevels[i]->restrct,viewer);CHKERRQ(ierr); 905f3fbd535SBarry Smith } 906f3fbd535SBarry Smith for (i=0; i<n; i++) { 907f3fbd535SBarry Smith ierr = KSPGetPC(mglevels[i]->smoothd,&pc);CHKERRQ(ierr); 908f3fbd535SBarry Smith ierr = MatView(pc->mat,viewer);CHKERRQ(ierr); 909f3fbd535SBarry Smith } 910f3fbd535SBarry Smith } 911f3fbd535SBarry Smith PetscFunctionReturn(0); 912f3fbd535SBarry Smith } 913f3fbd535SBarry Smith 914f3fbd535SBarry Smith /* -------------------------------------------------------------------------------------*/ 915f3fbd535SBarry Smith 9164b9ad928SBarry Smith /*@ 91797177400SBarry Smith PCMGGetLevels - Gets the number of levels to use with MG. 9184b9ad928SBarry Smith 9194b9ad928SBarry Smith Not Collective 9204b9ad928SBarry Smith 9214b9ad928SBarry Smith Input Parameter: 9224b9ad928SBarry Smith . pc - the preconditioner context 9234b9ad928SBarry Smith 9244b9ad928SBarry Smith Output parameter: 9254b9ad928SBarry Smith . levels - the number of levels 9264b9ad928SBarry Smith 9274b9ad928SBarry Smith Level: advanced 9284b9ad928SBarry Smith 9294b9ad928SBarry Smith .keywords: MG, get, levels, multigrid 9304b9ad928SBarry Smith 93197177400SBarry Smith .seealso: PCMGSetLevels() 9324b9ad928SBarry Smith @*/ 9337087cfbeSBarry Smith PetscErrorCode PCMGGetLevels(PC pc,PetscInt *levels) 9344b9ad928SBarry Smith { 935f3fbd535SBarry Smith PC_MG *mg = (PC_MG*)pc->data; 936*e952c529SMatthew G. Knepley PetscBool ismg; 937*e952c529SMatthew G. Knepley PetscErrorCode ierr; 9384b9ad928SBarry Smith 9394b9ad928SBarry Smith PetscFunctionBegin; 9400700a824SBarry Smith PetscValidHeaderSpecific(pc,PC_CLASSID,1); 9414482741eSBarry Smith PetscValidIntPointer(levels,2); 942*e952c529SMatthew G. Knepley ierr = PetscObjectTypeCompare((PetscObject) pc, PCMG, &ismg);CHKERRQ(ierr); 943*e952c529SMatthew G. Knepley if (ismg) {*levels = mg->nlevels;} 944*e952c529SMatthew G. Knepley else {*levels = 0;} 9454b9ad928SBarry Smith PetscFunctionReturn(0); 9464b9ad928SBarry Smith } 9474b9ad928SBarry Smith 9484b9ad928SBarry Smith /*@ 94997177400SBarry Smith PCMGSetType - Determines the form of multigrid to use: 9504b9ad928SBarry Smith multiplicative, additive, full, or the Kaskade algorithm. 9514b9ad928SBarry Smith 952ad4df100SBarry Smith Logically Collective on PC 9534b9ad928SBarry Smith 9544b9ad928SBarry Smith Input Parameters: 9554b9ad928SBarry Smith + pc - the preconditioner context 9569dcbbd2bSBarry Smith - form - multigrid form, one of PC_MG_MULTIPLICATIVE, PC_MG_ADDITIVE, 9579dcbbd2bSBarry Smith PC_MG_FULL, PC_MG_KASKADE 9584b9ad928SBarry Smith 9594b9ad928SBarry Smith Options Database Key: 9604b9ad928SBarry Smith . -pc_mg_type <form> - Sets <form>, one of multiplicative, 9614b9ad928SBarry Smith additive, full, kaskade 9624b9ad928SBarry Smith 9634b9ad928SBarry Smith Level: advanced 9644b9ad928SBarry Smith 9654b9ad928SBarry Smith .keywords: MG, set, method, multiplicative, additive, full, Kaskade, multigrid 9664b9ad928SBarry Smith 96797177400SBarry Smith .seealso: PCMGSetLevels() 9684b9ad928SBarry Smith @*/ 9697087cfbeSBarry Smith PetscErrorCode PCMGSetType(PC pc,PCMGType form) 9704b9ad928SBarry Smith { 971f3fbd535SBarry Smith PC_MG *mg = (PC_MG*)pc->data; 9724b9ad928SBarry Smith 9734b9ad928SBarry Smith PetscFunctionBegin; 9740700a824SBarry Smith PetscValidHeaderSpecific(pc,PC_CLASSID,1); 975c5eb9154SBarry Smith PetscValidLogicalCollectiveEnum(pc,form,2); 97631567311SBarry Smith mg->am = form; 9779dcbbd2bSBarry Smith if (form == PC_MG_MULTIPLICATIVE) pc->ops->applyrichardson = PCApplyRichardson_MG; 978c60c7ad4SBarry Smith else pc->ops->applyrichardson = NULL; 979c60c7ad4SBarry Smith PetscFunctionReturn(0); 980c60c7ad4SBarry Smith } 981c60c7ad4SBarry Smith 982c60c7ad4SBarry Smith /*@ 983c60c7ad4SBarry Smith PCMGGetType - Determines the form of multigrid to use: 984c60c7ad4SBarry Smith multiplicative, additive, full, or the Kaskade algorithm. 985c60c7ad4SBarry Smith 986c60c7ad4SBarry Smith Logically Collective on PC 987c60c7ad4SBarry Smith 988c60c7ad4SBarry Smith Input Parameter: 989c60c7ad4SBarry Smith . pc - the preconditioner context 990c60c7ad4SBarry Smith 991c60c7ad4SBarry Smith Output Parameter: 992c60c7ad4SBarry Smith . type - one of PC_MG_MULTIPLICATIVE, PC_MG_ADDITIVE,PC_MG_FULL, PC_MG_KASKADE 993c60c7ad4SBarry Smith 994c60c7ad4SBarry Smith 995c60c7ad4SBarry Smith Level: advanced 996c60c7ad4SBarry Smith 997c60c7ad4SBarry Smith .keywords: MG, set, method, multiplicative, additive, full, Kaskade, multigrid 998c60c7ad4SBarry Smith 999c60c7ad4SBarry Smith .seealso: PCMGSetLevels() 1000c60c7ad4SBarry Smith @*/ 1001c60c7ad4SBarry Smith PetscErrorCode PCMGGetType(PC pc,PCMGType *type) 1002c60c7ad4SBarry Smith { 1003c60c7ad4SBarry Smith PC_MG *mg = (PC_MG*)pc->data; 1004c60c7ad4SBarry Smith 1005c60c7ad4SBarry Smith PetscFunctionBegin; 1006c60c7ad4SBarry Smith PetscValidHeaderSpecific(pc,PC_CLASSID,1); 1007c60c7ad4SBarry Smith *type = mg->am; 10084b9ad928SBarry Smith PetscFunctionReturn(0); 10094b9ad928SBarry Smith } 10104b9ad928SBarry Smith 10114b9ad928SBarry Smith /*@ 10120d353602SBarry Smith PCMGSetCycleType - Sets the type cycles to use. Use PCMGSetCycleTypeOnLevel() for more 10134b9ad928SBarry Smith complicated cycling. 10144b9ad928SBarry Smith 1015ad4df100SBarry Smith Logically Collective on PC 10164b9ad928SBarry Smith 10174b9ad928SBarry Smith Input Parameters: 1018c2be2410SBarry Smith + pc - the multigrid context 1019c1cbb1deSBarry Smith - n - either PC_MG_CYCLE_V or PC_MG_CYCLE_W 10204b9ad928SBarry Smith 10214b9ad928SBarry Smith Options Database Key: 1022c1cbb1deSBarry Smith . -pc_mg_cycle_type <v,w> - provide the cycle desired 10234b9ad928SBarry Smith 10244b9ad928SBarry Smith Level: advanced 10254b9ad928SBarry Smith 10264b9ad928SBarry Smith .keywords: MG, set, cycles, V-cycle, W-cycle, multigrid 10274b9ad928SBarry Smith 10280d353602SBarry Smith .seealso: PCMGSetCycleTypeOnLevel() 10294b9ad928SBarry Smith @*/ 10307087cfbeSBarry Smith PetscErrorCode PCMGSetCycleType(PC pc,PCMGCycleType n) 10314b9ad928SBarry Smith { 1032f3fbd535SBarry Smith PC_MG *mg = (PC_MG*)pc->data; 1033f3fbd535SBarry Smith PC_MG_Levels **mglevels = mg->levels; 103479416396SBarry Smith PetscInt i,levels; 10354b9ad928SBarry Smith 10364b9ad928SBarry Smith PetscFunctionBegin; 10370700a824SBarry Smith PetscValidHeaderSpecific(pc,PC_CLASSID,1); 103869fbec6eSBarry Smith PetscValidLogicalCollectiveEnum(pc,n,2); 10391a97d7b6SStefano Zampini if (!mglevels) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ORDER,"Must set MG levels with PCMGSetLevels() before calling"); 1040f3fbd535SBarry Smith levels = mglevels[0]->levels; 10412fa5cd67SKarl Rupp for (i=0; i<levels; i++) mglevels[i]->cycles = n; 10424b9ad928SBarry Smith PetscFunctionReturn(0); 10434b9ad928SBarry Smith } 10444b9ad928SBarry Smith 10458cc2d5dfSBarry Smith /*@ 10468cc2d5dfSBarry Smith PCMGMultiplicativeSetCycles - Sets the number of cycles to use for each preconditioner step 10478cc2d5dfSBarry Smith of multigrid when PCMGType of PC_MG_MULTIPLICATIVE is used 10488cc2d5dfSBarry Smith 1049ad4df100SBarry Smith Logically Collective on PC 10508cc2d5dfSBarry Smith 10518cc2d5dfSBarry Smith Input Parameters: 10528cc2d5dfSBarry Smith + pc - the multigrid context 10538cc2d5dfSBarry Smith - n - number of cycles (default is 1) 10548cc2d5dfSBarry Smith 10558cc2d5dfSBarry Smith Options Database Key: 1056e1bc860dSBarry Smith . -pc_mg_multiplicative_cycles n 10578cc2d5dfSBarry Smith 10588cc2d5dfSBarry Smith Level: advanced 10598cc2d5dfSBarry Smith 106095452b02SPatrick Sanan Notes: 106195452b02SPatrick Sanan This is not associated with setting a v or w cycle, that is set with PCMGSetCycleType() 10628cc2d5dfSBarry Smith 10638cc2d5dfSBarry Smith .keywords: MG, set, cycles, V-cycle, W-cycle, multigrid 10648cc2d5dfSBarry Smith 10658cc2d5dfSBarry Smith .seealso: PCMGSetCycleTypeOnLevel(), PCMGSetCycleType() 10668cc2d5dfSBarry Smith @*/ 10677087cfbeSBarry Smith PetscErrorCode PCMGMultiplicativeSetCycles(PC pc,PetscInt n) 10688cc2d5dfSBarry Smith { 1069f3fbd535SBarry Smith PC_MG *mg = (PC_MG*)pc->data; 10708cc2d5dfSBarry Smith 10718cc2d5dfSBarry Smith PetscFunctionBegin; 10720700a824SBarry Smith PetscValidHeaderSpecific(pc,PC_CLASSID,1); 1073c5eb9154SBarry Smith PetscValidLogicalCollectiveInt(pc,n,2); 10742a21e185SBarry Smith mg->cyclesperpcapply = n; 10758cc2d5dfSBarry Smith PetscFunctionReturn(0); 10768cc2d5dfSBarry Smith } 10778cc2d5dfSBarry Smith 10782134b1e4SBarry Smith PetscErrorCode PCMGSetGalerkin_MG(PC pc,PCMGGalerkinType use) 1079fb15c04eSBarry Smith { 1080fb15c04eSBarry Smith PC_MG *mg = (PC_MG*)pc->data; 1081fb15c04eSBarry Smith 1082fb15c04eSBarry Smith PetscFunctionBegin; 10832134b1e4SBarry Smith mg->galerkin = use; 1084fb15c04eSBarry Smith PetscFunctionReturn(0); 1085fb15c04eSBarry Smith } 1086fb15c04eSBarry Smith 1087c2be2410SBarry Smith /*@ 108897177400SBarry Smith PCMGSetGalerkin - Causes the coarser grid matrices to be computed from the 108982b87d87SMatthew G. Knepley finest grid via the Galerkin process: A_i-1 = r_i * A_i * p_i 1090c2be2410SBarry Smith 1091ad4df100SBarry Smith Logically Collective on PC 1092c2be2410SBarry Smith 1093c2be2410SBarry Smith Input Parameters: 1094c91913d3SJed Brown + pc - the multigrid context 10952134b1e4SBarry Smith - use - one of PC_MG_GALERKIN_BOTH,PC_MG_GALERKIN_PMAT,PC_MG_GALERKIN_MAT, or PC_MG_GALERKIN_NONE 1096c2be2410SBarry Smith 1097c2be2410SBarry Smith Options Database Key: 10982134b1e4SBarry Smith . -pc_mg_galerkin <both,pmat,mat,none> 1099c2be2410SBarry Smith 1100c2be2410SBarry Smith Level: intermediate 1101c2be2410SBarry Smith 110295452b02SPatrick Sanan Notes: 110395452b02SPatrick Sanan Some codes that use PCMG such as PCGAMG use Galerkin internally while constructing the hierarchy and thus do not 11041c1aac46SBarry Smith use the PCMG construction of the coarser grids. 11051c1aac46SBarry Smith 1106c2be2410SBarry Smith .keywords: MG, set, Galerkin 1107c2be2410SBarry Smith 11082134b1e4SBarry Smith .seealso: PCMGGetGalerkin(), PCMGGalerkinType 11093fc8bf9cSBarry Smith 1110c2be2410SBarry Smith @*/ 11112134b1e4SBarry Smith PetscErrorCode PCMGSetGalerkin(PC pc,PCMGGalerkinType use) 1112c2be2410SBarry Smith { 1113fb15c04eSBarry Smith PetscErrorCode ierr; 1114c2be2410SBarry Smith 1115c2be2410SBarry Smith PetscFunctionBegin; 11160700a824SBarry Smith PetscValidHeaderSpecific(pc,PC_CLASSID,1); 11172134b1e4SBarry Smith ierr = PetscTryMethod(pc,"PCMGSetGalerkin_C",(PC,PCMGGalerkinType),(pc,use));CHKERRQ(ierr); 1118c2be2410SBarry Smith PetscFunctionReturn(0); 1119c2be2410SBarry Smith } 1120c2be2410SBarry Smith 11213fc8bf9cSBarry Smith /*@ 11223fc8bf9cSBarry Smith PCMGGetGalerkin - Checks if Galerkin multigrid is being used, i.e. 112382b87d87SMatthew G. Knepley A_i-1 = r_i * A_i * p_i 11243fc8bf9cSBarry Smith 11253fc8bf9cSBarry Smith Not Collective 11263fc8bf9cSBarry Smith 11273fc8bf9cSBarry Smith Input Parameter: 11283fc8bf9cSBarry Smith . pc - the multigrid context 11293fc8bf9cSBarry Smith 11303fc8bf9cSBarry Smith Output Parameter: 11312134b1e4SBarry Smith . galerkin - one of PC_MG_GALERKIN_BOTH,PC_MG_GALERKIN_PMAT,PC_MG_GALERKIN_MAT, PC_MG_GALERKIN_NONE, or PC_MG_GALERKIN_EXTERNAL 11323fc8bf9cSBarry Smith 11333fc8bf9cSBarry Smith Level: intermediate 11343fc8bf9cSBarry Smith 11353fc8bf9cSBarry Smith .keywords: MG, set, Galerkin 11363fc8bf9cSBarry Smith 11372134b1e4SBarry Smith .seealso: PCMGSetGalerkin(), PCMGGalerkinType 11383fc8bf9cSBarry Smith 11393fc8bf9cSBarry Smith @*/ 11402134b1e4SBarry Smith PetscErrorCode PCMGGetGalerkin(PC pc,PCMGGalerkinType *galerkin) 11413fc8bf9cSBarry Smith { 1142f3fbd535SBarry Smith PC_MG *mg = (PC_MG*)pc->data; 11433fc8bf9cSBarry Smith 11443fc8bf9cSBarry Smith PetscFunctionBegin; 11450700a824SBarry Smith PetscValidHeaderSpecific(pc,PC_CLASSID,1); 11462134b1e4SBarry Smith *galerkin = mg->galerkin; 11473fc8bf9cSBarry Smith PetscFunctionReturn(0); 11483fc8bf9cSBarry Smith } 11493fc8bf9cSBarry Smith 11504b9ad928SBarry Smith /*@ 115106792cafSBarry Smith PCMGSetNumberSmooth - Sets the number of pre and post-smoothing steps to use 1152710315b6SLawrence Mitchell on all levels. Use PCMGDistinctSmoothUp() to create separate up and down smoothers if you want different numbers of 1153710315b6SLawrence Mitchell pre- and post-smoothing steps. 115406792cafSBarry Smith 115506792cafSBarry Smith Logically Collective on PC 115606792cafSBarry Smith 115706792cafSBarry Smith Input Parameters: 115806792cafSBarry Smith + mg - the multigrid context 115906792cafSBarry Smith - n - the number of smoothing steps 116006792cafSBarry Smith 116106792cafSBarry Smith Options Database Key: 116206792cafSBarry Smith + -mg_levels_ksp_max_it <n> - Sets number of pre and post-smoothing steps 116306792cafSBarry Smith 116406792cafSBarry Smith Level: advanced 116506792cafSBarry Smith 116695452b02SPatrick Sanan Notes: 116795452b02SPatrick Sanan this does not set a value on the coarsest grid, since we assume that 116806792cafSBarry Smith there is no separate smooth up on the coarsest grid. 116906792cafSBarry Smith 117006792cafSBarry Smith .keywords: MG, smooth, up, post-smoothing, steps, multigrid 117106792cafSBarry Smith 1172710315b6SLawrence Mitchell .seealso: PCMGSetDistinctSmoothUp() 117306792cafSBarry Smith @*/ 117406792cafSBarry Smith PetscErrorCode PCMGSetNumberSmooth(PC pc,PetscInt n) 117506792cafSBarry Smith { 117606792cafSBarry Smith PC_MG *mg = (PC_MG*)pc->data; 117706792cafSBarry Smith PC_MG_Levels **mglevels = mg->levels; 117806792cafSBarry Smith PetscErrorCode ierr; 117906792cafSBarry Smith PetscInt i,levels; 118006792cafSBarry Smith 118106792cafSBarry Smith PetscFunctionBegin; 118206792cafSBarry Smith PetscValidHeaderSpecific(pc,PC_CLASSID,1); 118306792cafSBarry Smith PetscValidLogicalCollectiveInt(pc,n,2); 11841a97d7b6SStefano Zampini if (!mglevels) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ORDER,"Must set MG levels with PCMGSetLevels() before calling"); 118506792cafSBarry Smith levels = mglevels[0]->levels; 118606792cafSBarry Smith 118706792cafSBarry Smith for (i=1; i<levels; i++) { 118806792cafSBarry Smith ierr = KSPSetTolerances(mglevels[i]->smoothu,PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT,n);CHKERRQ(ierr); 118906792cafSBarry Smith ierr = KSPSetTolerances(mglevels[i]->smoothd,PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT,n);CHKERRQ(ierr); 119006792cafSBarry Smith mg->default_smoothu = n; 119106792cafSBarry Smith mg->default_smoothd = n; 119206792cafSBarry Smith } 119306792cafSBarry Smith PetscFunctionReturn(0); 119406792cafSBarry Smith } 119506792cafSBarry Smith 1196f442ab6aSBarry Smith /*@ 1197f442ab6aSBarry Smith PCMGSetDistinctSmoothUp - sets the up (post) smoother to be a seperate KSP from the down (pre) smoother on all levels 1198710315b6SLawrence Mitchell and adds the suffix _up to the options name 1199f442ab6aSBarry Smith 1200f442ab6aSBarry Smith Logically Collective on PC 1201f442ab6aSBarry Smith 1202f442ab6aSBarry Smith Input Parameters: 1203f442ab6aSBarry Smith . pc - the preconditioner context 1204f442ab6aSBarry Smith 1205f442ab6aSBarry Smith Options Database Key: 1206f442ab6aSBarry Smith . -pc_mg_distinct_smoothup 1207f442ab6aSBarry Smith 1208f442ab6aSBarry Smith Level: advanced 1209f442ab6aSBarry Smith 121095452b02SPatrick Sanan Notes: 121195452b02SPatrick Sanan this does not set a value on the coarsest grid, since we assume that 1212f442ab6aSBarry Smith there is no separate smooth up on the coarsest grid. 1213f442ab6aSBarry Smith 1214f442ab6aSBarry Smith .keywords: MG, smooth, up, post-smoothing, steps, multigrid 1215f442ab6aSBarry Smith 1216710315b6SLawrence Mitchell .seealso: PCMGSetNumberSmooth() 1217f442ab6aSBarry Smith @*/ 1218f442ab6aSBarry Smith PetscErrorCode PCMGSetDistinctSmoothUp(PC pc) 1219f442ab6aSBarry Smith { 1220f442ab6aSBarry Smith PC_MG *mg = (PC_MG*)pc->data; 1221f442ab6aSBarry Smith PC_MG_Levels **mglevels = mg->levels; 1222f442ab6aSBarry Smith PetscErrorCode ierr; 1223f442ab6aSBarry Smith PetscInt i,levels; 1224f442ab6aSBarry Smith KSP subksp; 1225f442ab6aSBarry Smith 1226f442ab6aSBarry Smith PetscFunctionBegin; 1227f442ab6aSBarry Smith PetscValidHeaderSpecific(pc,PC_CLASSID,1); 1228f442ab6aSBarry Smith if (!mglevels) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ORDER,"Must set MG levels with PCMGSetLevels() before calling"); 1229f442ab6aSBarry Smith levels = mglevels[0]->levels; 1230f442ab6aSBarry Smith 1231f442ab6aSBarry Smith for (i=1; i<levels; i++) { 1232710315b6SLawrence Mitchell const char *prefix = NULL; 1233f442ab6aSBarry Smith /* make sure smoother up and down are different */ 1234f442ab6aSBarry Smith ierr = PCMGGetSmootherUp(pc,i,&subksp);CHKERRQ(ierr); 1235710315b6SLawrence Mitchell ierr = KSPGetOptionsPrefix(mglevels[i]->smoothd,&prefix);CHKERRQ(ierr); 1236710315b6SLawrence Mitchell ierr = KSPSetOptionsPrefix(subksp,prefix);CHKERRQ(ierr); 1237f442ab6aSBarry Smith ierr = KSPAppendOptionsPrefix(subksp,"up_");CHKERRQ(ierr); 1238f442ab6aSBarry Smith } 1239f442ab6aSBarry Smith PetscFunctionReturn(0); 1240f442ab6aSBarry Smith } 1241f442ab6aSBarry Smith 12424b9ad928SBarry Smith /* ----------------------------------------------------------------------------------------*/ 12434b9ad928SBarry Smith 12443b09bd56SBarry Smith /*MC 1245ccb205f8SBarry Smith PCMG - Use multigrid preconditioning. This preconditioner requires you provide additional 12463b09bd56SBarry Smith information about the coarser grid matrices and restriction/interpolation operators. 12473b09bd56SBarry Smith 12483b09bd56SBarry Smith Options Database Keys: 12493b09bd56SBarry Smith + -pc_mg_levels <nlevels> - number of levels including finest 1250391689abSStefano Zampini . -pc_mg_cycle_type <v,w> - provide the cycle desired 12518c1c2452SJed Brown . -pc_mg_type <additive,multiplicative,full,kaskade> - multiplicative is the default 12523b09bd56SBarry Smith . -pc_mg_log - log information about time spent on each level of the solver 1253710315b6SLawrence Mitchell . -pc_mg_distinct_smoothup - configure up (after interpolation) and down (before restriction) smoothers separately (with different options prefixes) 12542134b1e4SBarry Smith . -pc_mg_galerkin <both,pmat,mat,none> - use Galerkin process to compute coarser operators, i.e. Acoarse = R A R' 12558cf6037eSBarry Smith . -pc_mg_multiplicative_cycles - number of cycles to use as the preconditioner (defaults to 1) 12568cf6037eSBarry Smith . -pc_mg_dump_matlab - dumps the matrices for each level and the restriction/interpolation matrices 1257e3c5b3baSBarry Smith to the Socket viewer for reading from MATLAB. 12588cf6037eSBarry Smith - -pc_mg_dump_binary - dumps the matrices for each level and the restriction/interpolation matrices 12598cf6037eSBarry Smith to the binary output file called binaryoutput 12603b09bd56SBarry Smith 126195452b02SPatrick Sanan Notes: 12620b3c753eSRichard Tran Mills If one uses a Krylov method such GMRES or CG as the smoother then one must use KSPFGMRES, KSPGCR, or KSPRICHARDSON as the outer Krylov method 12633b09bd56SBarry Smith 12648cf6037eSBarry Smith When run with a single level the smoother options are used on that level NOT the coarse grid solver options 12658cf6037eSBarry Smith 126623067569SBarry Smith When run with KSPRICHARDSON the convergence test changes slightly if monitor is turned on. The iteration count may change slightly. This 126723067569SBarry Smith is because without monitoring the residual norm is computed WITHIN each multigrid cycle on the finest level after the pre-smoothing 126823067569SBarry Smith (because the residual has just been computed for the multigrid algorithm and is hence available for free) while with monitoring the 126923067569SBarry Smith residual is computed at the end of each cycle. 127023067569SBarry Smith 12713b09bd56SBarry Smith Level: intermediate 12723b09bd56SBarry Smith 12738f87f92bSBarry Smith Concepts: multigrid/multilevel 12743b09bd56SBarry Smith 12758cf6037eSBarry Smith .seealso: PCCreate(), PCSetType(), PCType (for list of available types), PC, PCMGType, PCEXOTIC, PCGAMG, PCML, PCHYPRE 1276710315b6SLawrence Mitchell PCMGSetLevels(), PCMGGetLevels(), PCMGSetType(), PCMGSetCycleType(), 1277710315b6SLawrence Mitchell PCMGSetDistinctSmoothUp(), PCMGGetCoarseSolve(), PCMGSetResidual(), PCMGSetInterpolation(), 127897177400SBarry Smith PCMGSetRestriction(), PCMGGetSmoother(), PCMGGetSmootherUp(), PCMGGetSmootherDown(), 12790d353602SBarry Smith PCMGSetCycleTypeOnLevel(), PCMGSetRhs(), PCMGSetX(), PCMGSetR() 12803b09bd56SBarry Smith M*/ 12813b09bd56SBarry Smith 12828cc058d9SJed Brown PETSC_EXTERN PetscErrorCode PCCreate_MG(PC pc) 12834b9ad928SBarry Smith { 1284f3fbd535SBarry Smith PC_MG *mg; 1285f3fbd535SBarry Smith PetscErrorCode ierr; 1286f3fbd535SBarry Smith 12874b9ad928SBarry Smith PetscFunctionBegin; 1288b00a9115SJed Brown ierr = PetscNewLog(pc,&mg);CHKERRQ(ierr); 1289f3fbd535SBarry Smith pc->data = (void*)mg; 1290f3fbd535SBarry Smith mg->nlevels = -1; 129110eca3edSLisandro Dalcin mg->am = PC_MG_MULTIPLICATIVE; 12922134b1e4SBarry Smith mg->galerkin = PC_MG_GALERKIN_NONE; 1293f3fbd535SBarry Smith 129437a44384SMark Adams pc->useAmat = PETSC_TRUE; 129537a44384SMark Adams 12964b9ad928SBarry Smith pc->ops->apply = PCApply_MG; 12974b9ad928SBarry Smith pc->ops->setup = PCSetUp_MG; 1298a06653b4SBarry Smith pc->ops->reset = PCReset_MG; 12994b9ad928SBarry Smith pc->ops->destroy = PCDestroy_MG; 13004b9ad928SBarry Smith pc->ops->setfromoptions = PCSetFromOptions_MG; 13014b9ad928SBarry Smith pc->ops->view = PCView_MG; 1302fb15c04eSBarry Smith 1303fb15c04eSBarry Smith ierr = PetscObjectComposeFunction((PetscObject)pc,"PCMGSetGalerkin_C",PCMGSetGalerkin_MG);CHKERRQ(ierr); 13044b9ad928SBarry Smith PetscFunctionReturn(0); 13054b9ad928SBarry Smith } 1306