1dba47a55SKris Buschelman 24b9ad928SBarry Smith /* 34b9ad928SBarry Smith Defines the multigrid preconditioner interface. 44b9ad928SBarry Smith */ 5af0996ceSBarry Smith #include <petsc/private/pcmgimpl.h> /*I "petscksp.h" I*/ 641b6fd38SMatthew G. Knepley #include <petsc/private/kspimpl.h> 71e25c274SJed Brown #include <petscdm.h> 8391689abSStefano Zampini PETSC_INTERN PetscErrorCode PCPreSolveChangeRHS(PC,PetscBool*); 94b9ad928SBarry Smith 10f3b08a26SMatthew G. Knepley /* 11f3b08a26SMatthew G. Knepley Contains the list of registered coarse space construction routines 12f3b08a26SMatthew G. Knepley */ 13f3b08a26SMatthew G. Knepley PetscFunctionList PCMGCoarseList = NULL; 14f3b08a26SMatthew G. Knepley 1530b0564aSStefano Zampini PetscErrorCode PCMGMCycle_Private(PC pc,PC_MG_Levels **mglevelsin,PetscBool transpose,PetscBool matapp,PCRichardsonConvergedReason *reason) 164b9ad928SBarry Smith { 1731567311SBarry Smith PC_MG *mg = (PC_MG*)pc->data; 1831567311SBarry Smith PC_MG_Levels *mgc,*mglevels = *mglevelsin; 1931567311SBarry Smith PetscInt cycles = (mglevels->level == 1) ? 1 : (PetscInt) mglevels->cycles; 204b9ad928SBarry Smith 214b9ad928SBarry Smith PetscFunctionBegin; 229566063dSJacob Faibussowitsch if (mglevels->eventsmoothsolve) PetscCall(PetscLogEventBegin(mglevels->eventsmoothsolve,0,0,0,0)); 23fcb023d4SJed Brown if (!transpose) { 2430b0564aSStefano Zampini if (matapp) { 259566063dSJacob Faibussowitsch PetscCall(KSPMatSolve(mglevels->smoothd,mglevels->B,mglevels->X)); /* pre-smooth */ 269566063dSJacob Faibussowitsch PetscCall(KSPCheckSolve(mglevels->smoothd,pc,NULL)); 2730b0564aSStefano Zampini } else { 289566063dSJacob Faibussowitsch PetscCall(KSPSolve(mglevels->smoothd,mglevels->b,mglevels->x)); /* pre-smooth */ 299566063dSJacob Faibussowitsch PetscCall(KSPCheckSolve(mglevels->smoothd,pc,mglevels->x)); 3030b0564aSStefano Zampini } 31fcb023d4SJed Brown } else { 3228b400f6SJacob Faibussowitsch PetscCheck(!matapp,PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Not supported"); 339566063dSJacob Faibussowitsch PetscCall(KSPSolveTranspose(mglevels->smoothu,mglevels->b,mglevels->x)); /* transpose of post-smooth */ 349566063dSJacob Faibussowitsch PetscCall(KSPCheckSolve(mglevels->smoothu,pc,mglevels->x)); 35fcb023d4SJed Brown } 369566063dSJacob Faibussowitsch if (mglevels->eventsmoothsolve) PetscCall(PetscLogEventEnd(mglevels->eventsmoothsolve,0,0,0,0)); 3731567311SBarry Smith if (mglevels->level) { /* not the coarsest grid */ 389566063dSJacob Faibussowitsch if (mglevels->eventresidual) PetscCall(PetscLogEventBegin(mglevels->eventresidual,0,0,0,0)); 3930b0564aSStefano Zampini if (matapp && !mglevels->R) { 409566063dSJacob Faibussowitsch PetscCall(MatDuplicate(mglevels->B,MAT_DO_NOT_COPY_VALUES,&mglevels->R)); 4130b0564aSStefano Zampini } 42fcb023d4SJed Brown if (!transpose) { 439566063dSJacob Faibussowitsch if (matapp) PetscCall((*mglevels->matresidual)(mglevels->A,mglevels->B,mglevels->X,mglevels->R)); 449566063dSJacob Faibussowitsch else PetscCall((*mglevels->residual)(mglevels->A,mglevels->b,mglevels->x,mglevels->r)); 45fcb023d4SJed Brown } else { 469566063dSJacob Faibussowitsch if (matapp) PetscCall((*mglevels->matresidualtranspose)(mglevels->A,mglevels->B,mglevels->X,mglevels->R)); 479566063dSJacob Faibussowitsch else PetscCall((*mglevels->residualtranspose)(mglevels->A,mglevels->b,mglevels->x,mglevels->r)); 48fcb023d4SJed Brown } 499566063dSJacob Faibussowitsch if (mglevels->eventresidual) PetscCall(PetscLogEventEnd(mglevels->eventresidual,0,0,0,0)); 504b9ad928SBarry Smith 514b9ad928SBarry Smith /* if on finest level and have convergence criteria set */ 5231567311SBarry Smith if (mglevels->level == mglevels->levels-1 && mg->ttol && reason) { 534b9ad928SBarry Smith PetscReal rnorm; 549566063dSJacob Faibussowitsch PetscCall(VecNorm(mglevels->r,NORM_2,&rnorm)); 554b9ad928SBarry Smith if (rnorm <= mg->ttol) { 5670441072SBarry Smith if (rnorm < mg->abstol) { 574d0a8057SBarry Smith *reason = PCRICHARDSON_CONVERGED_ATOL; 589566063dSJacob Faibussowitsch PetscCall(PetscInfo(pc,"Linear solver has converged. Residual norm %g is less than absolute tolerance %g\n",(double)rnorm,(double)mg->abstol)); 594b9ad928SBarry Smith } else { 604d0a8057SBarry Smith *reason = PCRICHARDSON_CONVERGED_RTOL; 619566063dSJacob Faibussowitsch PetscCall(PetscInfo(pc,"Linear solver has converged. Residual norm %g is less than relative tolerance times initial residual norm %g\n",(double)rnorm,(double)mg->ttol)); 624b9ad928SBarry Smith } 634b9ad928SBarry Smith PetscFunctionReturn(0); 644b9ad928SBarry Smith } 654b9ad928SBarry Smith } 664b9ad928SBarry Smith 6731567311SBarry Smith mgc = *(mglevelsin - 1); 689566063dSJacob Faibussowitsch if (mglevels->eventinterprestrict) PetscCall(PetscLogEventBegin(mglevels->eventinterprestrict,0,0,0,0)); 69fcb023d4SJed Brown if (!transpose) { 709566063dSJacob Faibussowitsch if (matapp) PetscCall(MatMatRestrict(mglevels->restrct,mglevels->R,&mgc->B)); 719566063dSJacob Faibussowitsch else PetscCall(MatRestrict(mglevels->restrct,mglevels->r,mgc->b)); 72fcb023d4SJed Brown } else { 739566063dSJacob Faibussowitsch if (matapp) PetscCall(MatMatRestrict(mglevels->interpolate,mglevels->R,&mgc->B)); 749566063dSJacob Faibussowitsch else PetscCall(MatRestrict(mglevels->interpolate,mglevels->r,mgc->b)); 75fcb023d4SJed Brown } 769566063dSJacob Faibussowitsch if (mglevels->eventinterprestrict) PetscCall(PetscLogEventEnd(mglevels->eventinterprestrict,0,0,0,0)); 7730b0564aSStefano Zampini if (matapp) { 7830b0564aSStefano Zampini if (!mgc->X) { 799566063dSJacob Faibussowitsch PetscCall(MatDuplicate(mgc->B,MAT_DO_NOT_COPY_VALUES,&mgc->X)); 8030b0564aSStefano Zampini } else { 819566063dSJacob Faibussowitsch PetscCall(MatZeroEntries(mgc->X)); 8230b0564aSStefano Zampini } 8330b0564aSStefano Zampini } else { 849566063dSJacob Faibussowitsch PetscCall(VecZeroEntries(mgc->x)); 8530b0564aSStefano Zampini } 864b9ad928SBarry Smith while (cycles--) { 879566063dSJacob Faibussowitsch PetscCall(PCMGMCycle_Private(pc,mglevelsin-1,transpose,matapp,reason)); 884b9ad928SBarry Smith } 899566063dSJacob Faibussowitsch if (mglevels->eventinterprestrict) PetscCall(PetscLogEventBegin(mglevels->eventinterprestrict,0,0,0,0)); 90fcb023d4SJed Brown if (!transpose) { 919566063dSJacob Faibussowitsch if (matapp) PetscCall(MatMatInterpolateAdd(mglevels->interpolate,mgc->X,mglevels->X,&mglevels->X)); 929566063dSJacob Faibussowitsch else PetscCall(MatInterpolateAdd(mglevels->interpolate,mgc->x,mglevels->x,mglevels->x)); 93fcb023d4SJed Brown } else { 949566063dSJacob Faibussowitsch PetscCall(MatInterpolateAdd(mglevels->restrct,mgc->x,mglevels->x,mglevels->x)); 95fcb023d4SJed Brown } 969566063dSJacob Faibussowitsch if (mglevels->eventinterprestrict) PetscCall(PetscLogEventEnd(mglevels->eventinterprestrict,0,0,0,0)); 979566063dSJacob Faibussowitsch if (mglevels->eventsmoothsolve) PetscCall(PetscLogEventBegin(mglevels->eventsmoothsolve,0,0,0,0)); 98fcb023d4SJed Brown if (!transpose) { 9930b0564aSStefano Zampini if (matapp) { 1009566063dSJacob Faibussowitsch PetscCall(KSPMatSolve(mglevels->smoothu,mglevels->B,mglevels->X)); /* post smooth */ 1019566063dSJacob Faibussowitsch PetscCall(KSPCheckSolve(mglevels->smoothu,pc,NULL)); 10230b0564aSStefano Zampini } else { 1039566063dSJacob Faibussowitsch PetscCall(KSPSolve(mglevels->smoothu,mglevels->b,mglevels->x)); /* post smooth */ 1049566063dSJacob Faibussowitsch PetscCall(KSPCheckSolve(mglevels->smoothu,pc,mglevels->x)); 10530b0564aSStefano Zampini } 106fcb023d4SJed Brown } else { 10728b400f6SJacob Faibussowitsch PetscCheck(!matapp,PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Not supported"); 1089566063dSJacob Faibussowitsch PetscCall(KSPSolveTranspose(mglevels->smoothd,mglevels->b,mglevels->x)); /* post smooth */ 1099566063dSJacob Faibussowitsch PetscCall(KSPCheckSolve(mglevels->smoothd,pc,mglevels->x)); 110fcb023d4SJed Brown } 11141b6fd38SMatthew G. Knepley if (mglevels->cr) { 11228b400f6SJacob Faibussowitsch PetscCheck(!matapp,PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Not supported"); 11341b6fd38SMatthew G. Knepley /* TODO Turn on copy and turn off noisy if we have an exact solution 1149566063dSJacob Faibussowitsch PetscCall(VecCopy(mglevels->x, mglevels->crx)); 1159566063dSJacob Faibussowitsch PetscCall(VecCopy(mglevels->b, mglevels->crb)); */ 1169566063dSJacob Faibussowitsch PetscCall(KSPSetNoisy_Private(mglevels->crx)); 1179566063dSJacob Faibussowitsch PetscCall(KSPSolve(mglevels->cr,mglevels->crb,mglevels->crx)); /* compatible relaxation */ 1189566063dSJacob Faibussowitsch PetscCall(KSPCheckSolve(mglevels->cr,pc,mglevels->crx)); 11941b6fd38SMatthew G. Knepley } 1209566063dSJacob Faibussowitsch if (mglevels->eventsmoothsolve) PetscCall(PetscLogEventEnd(mglevels->eventsmoothsolve,0,0,0,0)); 1214b9ad928SBarry Smith } 1224b9ad928SBarry Smith PetscFunctionReturn(0); 1234b9ad928SBarry Smith } 1244b9ad928SBarry Smith 125ace3abfcSBarry 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) 1264b9ad928SBarry Smith { 127f3fbd535SBarry Smith PC_MG *mg = (PC_MG*)pc->data; 128f3fbd535SBarry Smith PC_MG_Levels **mglevels = mg->levels; 129391689abSStefano Zampini PC tpc; 130391689abSStefano Zampini PetscBool changeu,changed; 131f3fbd535SBarry Smith PetscInt levels = mglevels[0]->levels,i; 1324b9ad928SBarry Smith 1334b9ad928SBarry Smith PetscFunctionBegin; 134a762d673SBarry Smith /* When the DM is supplying the matrix then it will not exist until here */ 135a762d673SBarry Smith for (i=0; i<levels; i++) { 136a762d673SBarry Smith if (!mglevels[i]->A) { 1379566063dSJacob Faibussowitsch PetscCall(KSPGetOperators(mglevels[i]->smoothu,&mglevels[i]->A,NULL)); 1389566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)mglevels[i]->A)); 139a762d673SBarry Smith } 140a762d673SBarry Smith } 141391689abSStefano Zampini 1429566063dSJacob Faibussowitsch PetscCall(KSPGetPC(mglevels[levels-1]->smoothd,&tpc)); 1439566063dSJacob Faibussowitsch PetscCall(PCPreSolveChangeRHS(tpc,&changed)); 1449566063dSJacob Faibussowitsch PetscCall(KSPGetPC(mglevels[levels-1]->smoothu,&tpc)); 1459566063dSJacob Faibussowitsch PetscCall(PCPreSolveChangeRHS(tpc,&changeu)); 146391689abSStefano Zampini if (!changed && !changeu) { 1479566063dSJacob Faibussowitsch PetscCall(VecDestroy(&mglevels[levels-1]->b)); 148f3fbd535SBarry Smith mglevels[levels-1]->b = b; 149391689abSStefano Zampini } else { /* if the smoother changes the rhs during PreSolve, we cannot use the input vector */ 150391689abSStefano Zampini if (!mglevels[levels-1]->b) { 151391689abSStefano Zampini Vec *vec; 152391689abSStefano Zampini 1539566063dSJacob Faibussowitsch PetscCall(KSPCreateVecs(mglevels[levels-1]->smoothd,1,&vec,0,NULL)); 154391689abSStefano Zampini mglevels[levels-1]->b = *vec; 1559566063dSJacob Faibussowitsch PetscCall(PetscFree(vec)); 156391689abSStefano Zampini } 1579566063dSJacob Faibussowitsch PetscCall(VecCopy(b,mglevels[levels-1]->b)); 158391689abSStefano Zampini } 159f3fbd535SBarry Smith mglevels[levels-1]->x = x; 1604b9ad928SBarry Smith 16131567311SBarry Smith mg->rtol = rtol; 16231567311SBarry Smith mg->abstol = abstol; 16331567311SBarry Smith mg->dtol = dtol; 1644b9ad928SBarry Smith if (rtol) { 1654b9ad928SBarry Smith /* compute initial residual norm for relative convergence test */ 1664b9ad928SBarry Smith PetscReal rnorm; 1677319c654SBarry Smith if (zeroguess) { 1689566063dSJacob Faibussowitsch PetscCall(VecNorm(b,NORM_2,&rnorm)); 1697319c654SBarry Smith } else { 1709566063dSJacob Faibussowitsch PetscCall((*mglevels[levels-1]->residual)(mglevels[levels-1]->A,b,x,w)); 1719566063dSJacob Faibussowitsch PetscCall(VecNorm(w,NORM_2,&rnorm)); 1727319c654SBarry Smith } 17331567311SBarry Smith mg->ttol = PetscMax(rtol*rnorm,abstol); 1742fa5cd67SKarl Rupp } else if (abstol) mg->ttol = abstol; 1752fa5cd67SKarl Rupp else mg->ttol = 0.0; 1764b9ad928SBarry Smith 1774d0a8057SBarry Smith /* since smoother is applied to full system, not just residual we need to make sure that smoothers don't 178336babb1SJed Brown stop prematurely due to small residual */ 1794d0a8057SBarry Smith for (i=1; i<levels; i++) { 1809566063dSJacob Faibussowitsch PetscCall(KSPSetTolerances(mglevels[i]->smoothu,0,PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT)); 181f3fbd535SBarry Smith if (mglevels[i]->smoothu != mglevels[i]->smoothd) { 18223067569SBarry Smith /* For Richardson the initial guess is nonzero since it is solving in each cycle the original system not just applying as a preconditioner */ 1839566063dSJacob Faibussowitsch PetscCall(KSPSetInitialGuessNonzero(mglevels[i]->smoothd,PETSC_TRUE)); 1849566063dSJacob Faibussowitsch PetscCall(KSPSetTolerances(mglevels[i]->smoothd,0,PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT)); 1854b9ad928SBarry Smith } 1864d0a8057SBarry Smith } 1874d0a8057SBarry Smith 1884d0a8057SBarry Smith *reason = (PCRichardsonConvergedReason)0; 1894d0a8057SBarry Smith for (i=0; i<its; i++) { 1909566063dSJacob Faibussowitsch PetscCall(PCMGMCycle_Private(pc,mglevels+levels-1,PETSC_FALSE,PETSC_FALSE,reason)); 1914d0a8057SBarry Smith if (*reason) break; 1924d0a8057SBarry Smith } 1934d0a8057SBarry Smith if (!*reason) *reason = PCRICHARDSON_CONVERGED_ITS; 1944d0a8057SBarry Smith *outits = i; 195391689abSStefano Zampini if (!changed && !changeu) mglevels[levels-1]->b = NULL; 1964b9ad928SBarry Smith PetscFunctionReturn(0); 1974b9ad928SBarry Smith } 1984b9ad928SBarry Smith 1993aeaf226SBarry Smith PetscErrorCode PCReset_MG(PC pc) 2003aeaf226SBarry Smith { 2013aeaf226SBarry Smith PC_MG *mg = (PC_MG*)pc->data; 2023aeaf226SBarry Smith PC_MG_Levels **mglevels = mg->levels; 2032b3cbbdaSStefano Zampini PetscInt i,n; 2043aeaf226SBarry Smith 2053aeaf226SBarry Smith PetscFunctionBegin; 2063aeaf226SBarry Smith if (mglevels) { 2073aeaf226SBarry Smith n = mglevels[0]->levels; 2083aeaf226SBarry Smith for (i=0; i<n-1; i++) { 2099566063dSJacob Faibussowitsch PetscCall(VecDestroy(&mglevels[i+1]->r)); 2109566063dSJacob Faibussowitsch PetscCall(VecDestroy(&mglevels[i]->b)); 2119566063dSJacob Faibussowitsch PetscCall(VecDestroy(&mglevels[i]->x)); 2129566063dSJacob Faibussowitsch PetscCall(MatDestroy(&mglevels[i+1]->R)); 2139566063dSJacob Faibussowitsch PetscCall(MatDestroy(&mglevels[i]->B)); 2149566063dSJacob Faibussowitsch PetscCall(MatDestroy(&mglevels[i]->X)); 2159566063dSJacob Faibussowitsch PetscCall(VecDestroy(&mglevels[i]->crx)); 2169566063dSJacob Faibussowitsch PetscCall(VecDestroy(&mglevels[i]->crb)); 2179566063dSJacob Faibussowitsch PetscCall(MatDestroy(&mglevels[i+1]->restrct)); 2189566063dSJacob Faibussowitsch PetscCall(MatDestroy(&mglevels[i+1]->interpolate)); 2199566063dSJacob Faibussowitsch PetscCall(MatDestroy(&mglevels[i+1]->inject)); 2209566063dSJacob Faibussowitsch PetscCall(VecDestroy(&mglevels[i+1]->rscale)); 2213aeaf226SBarry Smith } 2229566063dSJacob Faibussowitsch PetscCall(VecDestroy(&mglevels[n-1]->crx)); 2239566063dSJacob Faibussowitsch PetscCall(VecDestroy(&mglevels[n-1]->crb)); 224391689abSStefano Zampini /* this is not null only if the smoother on the finest level 225391689abSStefano Zampini changes the rhs during PreSolve */ 2269566063dSJacob Faibussowitsch PetscCall(VecDestroy(&mglevels[n-1]->b)); 2279566063dSJacob Faibussowitsch PetscCall(MatDestroy(&mglevels[n-1]->B)); 2283aeaf226SBarry Smith 2293aeaf226SBarry Smith for (i=0; i<n; i++) { 2302b3cbbdaSStefano Zampini PetscCall(MatDestroy(&mglevels[i]->coarseSpace)); 2319566063dSJacob Faibussowitsch PetscCall(MatDestroy(&mglevels[i]->A)); 2323aeaf226SBarry Smith if (mglevels[i]->smoothd != mglevels[i]->smoothu) { 2339566063dSJacob Faibussowitsch PetscCall(KSPReset(mglevels[i]->smoothd)); 2343aeaf226SBarry Smith } 2359566063dSJacob Faibussowitsch PetscCall(KSPReset(mglevels[i]->smoothu)); 2369566063dSJacob Faibussowitsch if (mglevels[i]->cr) PetscCall(KSPReset(mglevels[i]->cr)); 2373aeaf226SBarry Smith } 238f3b08a26SMatthew G. Knepley mg->Nc = 0; 2393aeaf226SBarry Smith } 2403aeaf226SBarry Smith PetscFunctionReturn(0); 2413aeaf226SBarry Smith } 2423aeaf226SBarry Smith 24341b6fd38SMatthew G. Knepley /* Implementing CR 24441b6fd38SMatthew G. Knepley 24541b6fd38SMatthew G. Knepley We only want to make corrections that ``do not change'' the coarse solution. What we mean by not changing is that if I prolong my coarse solution to the fine grid and then inject that fine solution back to the coarse grid, I get the same answer. Injection is what Brannick calls R. We want the complementary projector to Inj, which we will call S, after Brannick, so that Inj S = 0. Now the orthogonal projector onto the range of Inj^T is 24641b6fd38SMatthew G. Knepley 24741b6fd38SMatthew G. Knepley Inj^T (Inj Inj^T)^{-1} Inj 24841b6fd38SMatthew G. Knepley 24941b6fd38SMatthew G. Knepley and if Inj is a VecScatter, as it is now in PETSc, we have 25041b6fd38SMatthew G. Knepley 25141b6fd38SMatthew G. Knepley Inj^T Inj 25241b6fd38SMatthew G. Knepley 25341b6fd38SMatthew G. Knepley and 25441b6fd38SMatthew G. Knepley 25541b6fd38SMatthew G. Knepley S = I - Inj^T Inj 25641b6fd38SMatthew G. Knepley 25741b6fd38SMatthew G. Knepley since 25841b6fd38SMatthew G. Knepley 25941b6fd38SMatthew G. Knepley Inj S = Inj - (Inj Inj^T) Inj = 0. 26041b6fd38SMatthew G. Knepley 26141b6fd38SMatthew G. Knepley Brannick suggests 26241b6fd38SMatthew G. Knepley 26341b6fd38SMatthew G. Knepley A \to S^T A S \qquad\mathrm{and}\qquad M \to S^T M S 26441b6fd38SMatthew G. Knepley 26541b6fd38SMatthew G. Knepley but I do not think his :math:`S^T S = I` is correct. Our S is an orthogonal projector, so :math:`S^T S = S^2 = S`. We will use 26641b6fd38SMatthew G. Knepley 26741b6fd38SMatthew G. Knepley M^{-1} A \to S M^{-1} A S 26841b6fd38SMatthew G. Knepley 26941b6fd38SMatthew G. Knepley In fact, since it is somewhat hard in PETSc to do the symmetric application, we will just apply S on the left. 27041b6fd38SMatthew G. Knepley 27141b6fd38SMatthew G. Knepley Check: || Inj P - I ||_F < tol 27241b6fd38SMatthew G. Knepley Check: In general, Inj Inj^T = I 27341b6fd38SMatthew G. Knepley */ 27441b6fd38SMatthew G. Knepley 27541b6fd38SMatthew G. Knepley typedef struct { 27641b6fd38SMatthew G. Knepley PC mg; /* The PCMG object */ 27741b6fd38SMatthew G. Knepley PetscInt l; /* The multigrid level for this solver */ 27841b6fd38SMatthew G. Knepley Mat Inj; /* The injection matrix */ 27941b6fd38SMatthew G. Knepley Mat S; /* I - Inj^T Inj */ 28041b6fd38SMatthew G. Knepley } CRContext; 28141b6fd38SMatthew G. Knepley 28241b6fd38SMatthew G. Knepley static PetscErrorCode CRSetup_Private(PC pc) 28341b6fd38SMatthew G. Knepley { 28441b6fd38SMatthew G. Knepley CRContext *ctx; 28541b6fd38SMatthew G. Knepley Mat It; 28641b6fd38SMatthew G. Knepley 28741b6fd38SMatthew G. Knepley PetscFunctionBeginUser; 2889566063dSJacob Faibussowitsch PetscCall(PCShellGetContext(pc, &ctx)); 2899566063dSJacob Faibussowitsch PetscCall(PCMGGetInjection(ctx->mg, ctx->l, &It)); 29028b400f6SJacob Faibussowitsch PetscCheck(It,PetscObjectComm((PetscObject) pc), PETSC_ERR_ARG_WRONGSTATE, "CR requires that injection be defined for this PCMG"); 2919566063dSJacob Faibussowitsch PetscCall(MatCreateTranspose(It, &ctx->Inj)); 2929566063dSJacob Faibussowitsch PetscCall(MatCreateNormal(ctx->Inj, &ctx->S)); 2939566063dSJacob Faibussowitsch PetscCall(MatScale(ctx->S, -1.0)); 2949566063dSJacob Faibussowitsch PetscCall(MatShift(ctx->S, 1.0)); 29541b6fd38SMatthew G. Knepley PetscFunctionReturn(0); 29641b6fd38SMatthew G. Knepley } 29741b6fd38SMatthew G. Knepley 29841b6fd38SMatthew G. Knepley static PetscErrorCode CRApply_Private(PC pc, Vec x, Vec y) 29941b6fd38SMatthew G. Knepley { 30041b6fd38SMatthew G. Knepley CRContext *ctx; 30141b6fd38SMatthew G. Knepley 30241b6fd38SMatthew G. Knepley PetscFunctionBeginUser; 3039566063dSJacob Faibussowitsch PetscCall(PCShellGetContext(pc, &ctx)); 3049566063dSJacob Faibussowitsch PetscCall(MatMult(ctx->S, x, y)); 30541b6fd38SMatthew G. Knepley PetscFunctionReturn(0); 30641b6fd38SMatthew G. Knepley } 30741b6fd38SMatthew G. Knepley 30841b6fd38SMatthew G. Knepley static PetscErrorCode CRDestroy_Private(PC pc) 30941b6fd38SMatthew G. Knepley { 31041b6fd38SMatthew G. Knepley CRContext *ctx; 31141b6fd38SMatthew G. Knepley 31241b6fd38SMatthew G. Knepley PetscFunctionBeginUser; 3139566063dSJacob Faibussowitsch PetscCall(PCShellGetContext(pc, &ctx)); 3149566063dSJacob Faibussowitsch PetscCall(MatDestroy(&ctx->Inj)); 3159566063dSJacob Faibussowitsch PetscCall(MatDestroy(&ctx->S)); 3169566063dSJacob Faibussowitsch PetscCall(PetscFree(ctx)); 3179566063dSJacob Faibussowitsch PetscCall(PCShellSetContext(pc, NULL)); 31841b6fd38SMatthew G. Knepley PetscFunctionReturn(0); 31941b6fd38SMatthew G. Knepley } 32041b6fd38SMatthew G. Knepley 32141b6fd38SMatthew G. Knepley static PetscErrorCode CreateCR_Private(PC pc, PetscInt l, PC *cr) 32241b6fd38SMatthew G. Knepley { 32341b6fd38SMatthew G. Knepley CRContext *ctx; 32441b6fd38SMatthew G. Knepley 32541b6fd38SMatthew G. Knepley PetscFunctionBeginUser; 3269566063dSJacob Faibussowitsch PetscCall(PCCreate(PetscObjectComm((PetscObject) pc), cr)); 3279566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject) *cr, "S (complementary projector to injection)")); 3289566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(1, &ctx)); 32941b6fd38SMatthew G. Knepley ctx->mg = pc; 33041b6fd38SMatthew G. Knepley ctx->l = l; 3319566063dSJacob Faibussowitsch PetscCall(PCSetType(*cr, PCSHELL)); 3329566063dSJacob Faibussowitsch PetscCall(PCShellSetContext(*cr, ctx)); 3339566063dSJacob Faibussowitsch PetscCall(PCShellSetApply(*cr, CRApply_Private)); 3349566063dSJacob Faibussowitsch PetscCall(PCShellSetSetUp(*cr, CRSetup_Private)); 3359566063dSJacob Faibussowitsch PetscCall(PCShellSetDestroy(*cr, CRDestroy_Private)); 33641b6fd38SMatthew G. Knepley PetscFunctionReturn(0); 33741b6fd38SMatthew G. Knepley } 33841b6fd38SMatthew G. Knepley 33997d33e41SMatthew G. Knepley PetscErrorCode PCMGSetLevels_MG(PC pc,PetscInt levels,MPI_Comm *comms) 3404b9ad928SBarry Smith { 341f3fbd535SBarry Smith PC_MG *mg = (PC_MG*)pc->data; 342ce94432eSBarry Smith MPI_Comm comm; 3433aeaf226SBarry Smith PC_MG_Levels **mglevels = mg->levels; 34410eca3edSLisandro Dalcin PCMGType mgtype = mg->am; 34510167fecSBarry Smith PetscInt mgctype = (PetscInt) PC_MG_CYCLE_V; 346f3fbd535SBarry Smith PetscInt i; 347f3fbd535SBarry Smith PetscMPIInt size; 348f3fbd535SBarry Smith const char *prefix; 349f3fbd535SBarry Smith PC ipc; 3503aeaf226SBarry Smith PetscInt n; 3514b9ad928SBarry Smith 3524b9ad928SBarry Smith PetscFunctionBegin; 3530700a824SBarry Smith PetscValidHeaderSpecific(pc,PC_CLASSID,1); 354548767e0SJed Brown PetscValidLogicalCollectiveInt(pc,levels,2); 355548767e0SJed Brown if (mg->nlevels == levels) PetscFunctionReturn(0); 3569566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)pc,&comm)); 3573aeaf226SBarry Smith if (mglevels) { 35810eca3edSLisandro Dalcin mgctype = mglevels[0]->cycles; 3593aeaf226SBarry Smith /* changing the number of levels so free up the previous stuff */ 3609566063dSJacob Faibussowitsch PetscCall(PCReset_MG(pc)); 3613aeaf226SBarry Smith n = mglevels[0]->levels; 3623aeaf226SBarry Smith for (i=0; i<n; i++) { 3633aeaf226SBarry Smith if (mglevels[i]->smoothd != mglevels[i]->smoothu) { 3649566063dSJacob Faibussowitsch PetscCall(KSPDestroy(&mglevels[i]->smoothd)); 3653aeaf226SBarry Smith } 3669566063dSJacob Faibussowitsch PetscCall(KSPDestroy(&mglevels[i]->smoothu)); 3679566063dSJacob Faibussowitsch PetscCall(KSPDestroy(&mglevels[i]->cr)); 3689566063dSJacob Faibussowitsch PetscCall(PetscFree(mglevels[i])); 3693aeaf226SBarry Smith } 3709566063dSJacob Faibussowitsch PetscCall(PetscFree(mg->levels)); 3713aeaf226SBarry Smith } 372f3fbd535SBarry Smith 373f3fbd535SBarry Smith mg->nlevels = levels; 374f3fbd535SBarry Smith 3759566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(levels,&mglevels)); 3769566063dSJacob Faibussowitsch PetscCall(PetscLogObjectMemory((PetscObject)pc,levels*(sizeof(PC_MG*)))); 377f3fbd535SBarry Smith 3789566063dSJacob Faibussowitsch PetscCall(PCGetOptionsPrefix(pc,&prefix)); 379f3fbd535SBarry Smith 380a9db87a2SMatthew G Knepley mg->stageApply = 0; 381f3fbd535SBarry Smith for (i=0; i<levels; i++) { 3829566063dSJacob Faibussowitsch PetscCall(PetscNewLog(pc,&mglevels[i])); 3832fa5cd67SKarl Rupp 384f3fbd535SBarry Smith mglevels[i]->level = i; 385f3fbd535SBarry Smith mglevels[i]->levels = levels; 38610eca3edSLisandro Dalcin mglevels[i]->cycles = mgctype; 387336babb1SJed Brown mg->default_smoothu = 2; 388336babb1SJed Brown mg->default_smoothd = 2; 38963e6d426SJed Brown mglevels[i]->eventsmoothsetup = 0; 39063e6d426SJed Brown mglevels[i]->eventsmoothsolve = 0; 39163e6d426SJed Brown mglevels[i]->eventresidual = 0; 39263e6d426SJed Brown mglevels[i]->eventinterprestrict = 0; 393f3fbd535SBarry Smith 394f3fbd535SBarry Smith if (comms) comm = comms[i]; 395d5a8f7e6SBarry Smith if (comm != MPI_COMM_NULL) { 3969566063dSJacob Faibussowitsch PetscCall(KSPCreate(comm,&mglevels[i]->smoothd)); 3979566063dSJacob Faibussowitsch PetscCall(KSPSetErrorIfNotConverged(mglevels[i]->smoothd,pc->erroriffailure)); 3989566063dSJacob Faibussowitsch PetscCall(PetscObjectIncrementTabLevel((PetscObject)mglevels[i]->smoothd,(PetscObject)pc,levels-i)); 3999566063dSJacob Faibussowitsch PetscCall(KSPSetOptionsPrefix(mglevels[i]->smoothd,prefix)); 4009566063dSJacob Faibussowitsch PetscCall(PetscObjectComposedDataSetInt((PetscObject) mglevels[i]->smoothd, PetscMGLevelId, mglevels[i]->level)); 4010ee9a668SBarry Smith if (i || levels == 1) { 4020ee9a668SBarry Smith char tprefix[128]; 4030ee9a668SBarry Smith 4049566063dSJacob Faibussowitsch PetscCall(KSPSetType(mglevels[i]->smoothd,KSPCHEBYSHEV)); 4059566063dSJacob Faibussowitsch PetscCall(KSPSetConvergenceTest(mglevels[i]->smoothd,KSPConvergedSkip,NULL,NULL)); 4069566063dSJacob Faibussowitsch PetscCall(KSPSetNormType(mglevels[i]->smoothd,KSP_NORM_NONE)); 4079566063dSJacob Faibussowitsch PetscCall(KSPGetPC(mglevels[i]->smoothd,&ipc)); 4089566063dSJacob Faibussowitsch PetscCall(PCSetType(ipc,PCSOR)); 4099566063dSJacob Faibussowitsch PetscCall(KSPSetTolerances(mglevels[i]->smoothd,PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT, mg->default_smoothd)); 410f3fbd535SBarry Smith 4119566063dSJacob Faibussowitsch PetscCall(PetscSNPrintf(tprefix,128,"mg_levels_%d_",(int)i)); 4129566063dSJacob Faibussowitsch PetscCall(KSPAppendOptionsPrefix(mglevels[i]->smoothd,tprefix)); 4130ee9a668SBarry Smith } else { 4149566063dSJacob Faibussowitsch PetscCall(KSPAppendOptionsPrefix(mglevels[0]->smoothd,"mg_coarse_")); 415f3fbd535SBarry Smith 4169dbfc187SHong Zhang /* coarse solve is (redundant) LU by default; set shifttype NONZERO to avoid annoying zero-pivot in LU preconditioner */ 4179566063dSJacob Faibussowitsch PetscCall(KSPSetType(mglevels[0]->smoothd,KSPPREONLY)); 4189566063dSJacob Faibussowitsch PetscCall(KSPGetPC(mglevels[0]->smoothd,&ipc)); 4199566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(comm,&size)); 420f3fbd535SBarry Smith if (size > 1) { 4219566063dSJacob Faibussowitsch PetscCall(PCSetType(ipc,PCREDUNDANT)); 422f3fbd535SBarry Smith } else { 4239566063dSJacob Faibussowitsch PetscCall(PCSetType(ipc,PCLU)); 424f3fbd535SBarry Smith } 4259566063dSJacob Faibussowitsch PetscCall(PCFactorSetShiftType(ipc,MAT_SHIFT_INBLOCKS)); 426f3fbd535SBarry Smith } 4279566063dSJacob Faibussowitsch PetscCall(PetscLogObjectParent((PetscObject)pc,(PetscObject)mglevels[i]->smoothd)); 428d5a8f7e6SBarry Smith } 429f3fbd535SBarry Smith mglevels[i]->smoothu = mglevels[i]->smoothd; 43031567311SBarry Smith mg->rtol = 0.0; 43131567311SBarry Smith mg->abstol = 0.0; 43231567311SBarry Smith mg->dtol = 0.0; 43331567311SBarry Smith mg->ttol = 0.0; 43431567311SBarry Smith mg->cyclesperpcapply = 1; 435f3fbd535SBarry Smith } 436f3fbd535SBarry Smith mg->levels = mglevels; 4379566063dSJacob Faibussowitsch PetscCall(PCMGSetType(pc,mgtype)); 4384b9ad928SBarry Smith PetscFunctionReturn(0); 4394b9ad928SBarry Smith } 4404b9ad928SBarry Smith 44197d33e41SMatthew G. Knepley /*@C 44297d33e41SMatthew G. Knepley PCMGSetLevels - Sets the number of levels to use with MG. 44397d33e41SMatthew G. Knepley Must be called before any other MG routine. 44497d33e41SMatthew G. Knepley 44597d33e41SMatthew G. Knepley Logically Collective on PC 44697d33e41SMatthew G. Knepley 44797d33e41SMatthew G. Knepley Input Parameters: 44897d33e41SMatthew G. Knepley + pc - the preconditioner context 44997d33e41SMatthew G. Knepley . levels - the number of levels 45097d33e41SMatthew G. Knepley - comms - optional communicators for each level; this is to allow solving the coarser problems 451d5a8f7e6SBarry Smith on smaller sets of processes. For processes that are not included in the computation 45205552d4bSJunchao Zhang you must pass MPI_COMM_NULL. Use comms = NULL to specify that all processes 45305552d4bSJunchao Zhang should participate in each level of problem. 45497d33e41SMatthew G. Knepley 45597d33e41SMatthew G. Knepley Level: intermediate 45697d33e41SMatthew G. Knepley 45797d33e41SMatthew G. Knepley Notes: 45897d33e41SMatthew G. Knepley If the number of levels is one then the multigrid uses the -mg_levels prefix 45997d33e41SMatthew G. Knepley for setting the level options rather than the -mg_coarse prefix. 46097d33e41SMatthew G. Knepley 461d5a8f7e6SBarry Smith You can free the information in comms after this routine is called. 462d5a8f7e6SBarry Smith 463d5a8f7e6SBarry Smith The array of MPI communicators must contain MPI_COMM_NULL for those ranks that at each level 464d5a8f7e6SBarry Smith are not participating in the coarser solve. For example, with 2 levels and 1 and 2 ranks on 465d5a8f7e6SBarry Smith the two levels, rank 0 in the original communicator will pass in an array of 2 communicators 466d5a8f7e6SBarry Smith of size 2 and 1, while rank 1 in the original communicator will pass in array of 2 communicators 467d5a8f7e6SBarry Smith the first of size 2 and the second of value MPI_COMM_NULL since the rank 1 does not participate 468d5a8f7e6SBarry Smith in the coarse grid solve. 469d5a8f7e6SBarry Smith 470d5a8f7e6SBarry Smith Since each coarser level may have a new MPI_Comm with fewer ranks than the previous, one 471d5a8f7e6SBarry Smith must take special care in providing the restriction and interpolation operation. We recommend 472d5a8f7e6SBarry Smith providing these as two step operations; first perform a standard restriction or interpolation on 473d5a8f7e6SBarry Smith the full number of ranks for that level and then use an MPI call to copy the resulting vector 47405552d4bSJunchao Zhang array entries (after calls to VecGetArray()) to the smaller or larger number of ranks, note in both 475d5a8f7e6SBarry Smith cases the MPI calls must be made on the larger of the two communicators. Traditional MPI send and 476d5a8f7e6SBarry Smith recieves or MPI_AlltoAllv() could be used to do the reshuffling of the vector entries. 477d5a8f7e6SBarry Smith 47805552d4bSJunchao Zhang Fortran Notes: 47905552d4bSJunchao Zhang Use comms = PETSC_NULL_MPI_COMM as the equivalent of NULL in the C interface. Note PETSC_NULL_MPI_COMM 48005552d4bSJunchao Zhang is not MPI_COMM_NULL. It is more like PETSC_NULL_INTEGER, PETSC_NULL_REAL etc. 481d5a8f7e6SBarry Smith 482db781477SPatrick Sanan .seealso: `PCMGSetType()`, `PCMGGetLevels()` 48397d33e41SMatthew G. Knepley @*/ 48497d33e41SMatthew G. Knepley PetscErrorCode PCMGSetLevels(PC pc,PetscInt levels,MPI_Comm *comms) 48597d33e41SMatthew G. Knepley { 48697d33e41SMatthew G. Knepley PetscFunctionBegin; 48797d33e41SMatthew G. Knepley PetscValidHeaderSpecific(pc,PC_CLASSID,1); 48897d33e41SMatthew G. Knepley if (comms) PetscValidPointer(comms,3); 489cac4c232SBarry Smith PetscTryMethod(pc,"PCMGSetLevels_C",(PC,PetscInt,MPI_Comm*),(pc,levels,comms)); 49097d33e41SMatthew G. Knepley PetscFunctionReturn(0); 49197d33e41SMatthew G. Knepley } 49297d33e41SMatthew G. Knepley 493c07bf074SBarry Smith PetscErrorCode PCDestroy_MG(PC pc) 494c07bf074SBarry Smith { 495a06653b4SBarry Smith PC_MG *mg = (PC_MG*)pc->data; 496a06653b4SBarry Smith PC_MG_Levels **mglevels = mg->levels; 497a06653b4SBarry Smith PetscInt i,n; 498c07bf074SBarry Smith 499c07bf074SBarry Smith PetscFunctionBegin; 5009566063dSJacob Faibussowitsch PetscCall(PCReset_MG(pc)); 501a06653b4SBarry Smith if (mglevels) { 502a06653b4SBarry Smith n = mglevels[0]->levels; 503a06653b4SBarry Smith for (i=0; i<n; i++) { 504a06653b4SBarry Smith if (mglevels[i]->smoothd != mglevels[i]->smoothu) { 5059566063dSJacob Faibussowitsch PetscCall(KSPDestroy(&mglevels[i]->smoothd)); 506a06653b4SBarry Smith } 5079566063dSJacob Faibussowitsch PetscCall(KSPDestroy(&mglevels[i]->smoothu)); 5089566063dSJacob Faibussowitsch PetscCall(KSPDestroy(&mglevels[i]->cr)); 5099566063dSJacob Faibussowitsch PetscCall(PetscFree(mglevels[i])); 510a06653b4SBarry Smith } 5119566063dSJacob Faibussowitsch PetscCall(PetscFree(mg->levels)); 512a06653b4SBarry Smith } 5139566063dSJacob Faibussowitsch PetscCall(PetscFree(pc->data)); 5149566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCGetInterpolations_C",NULL)); 5159566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCGetCoarseOperators_C",NULL)); 5162b3cbbdaSStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCMGSetGalerkin_C",NULL)); 5172b3cbbdaSStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCMGGetLevels_C",NULL)); 5182b3cbbdaSStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCMGSetLevels_C",NULL)); 5192b3cbbdaSStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCGetInterpolations_C",NULL)); 5202b3cbbdaSStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCGetCoarseOperators_C",NULL)); 5212b3cbbdaSStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCMGSetAdaptInterpolation_C",NULL)); 5222b3cbbdaSStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCMGGetAdaptInterpolation_C",NULL)); 5232b3cbbdaSStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCMGSetAdaptCR_C",NULL)); 5242b3cbbdaSStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCMGGetAdaptCR_C",NULL)); 5252b3cbbdaSStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCMGSetAdaptCoarseSpaceType_C",NULL)); 5262b3cbbdaSStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCMGGetAdaptCoarseSpaceType_C",NULL)); 527f3fbd535SBarry Smith PetscFunctionReturn(0); 528f3fbd535SBarry Smith } 529f3fbd535SBarry Smith 530f3fbd535SBarry Smith /* 531f3fbd535SBarry Smith PCApply_MG - Runs either an additive, multiplicative, Kaskadic 532f3fbd535SBarry Smith or full cycle of multigrid. 533f3fbd535SBarry Smith 534f3fbd535SBarry Smith Note: 535f3fbd535SBarry Smith A simple wrapper which calls PCMGMCycle(),PCMGACycle(), or PCMGFCycle(). 536f3fbd535SBarry Smith */ 53730b0564aSStefano Zampini static PetscErrorCode PCApply_MG_Internal(PC pc,Vec b,Vec x,Mat B,Mat X,PetscBool transpose) 538f3fbd535SBarry Smith { 539f3fbd535SBarry Smith PC_MG *mg = (PC_MG*)pc->data; 540f3fbd535SBarry Smith PC_MG_Levels **mglevels = mg->levels; 541391689abSStefano Zampini PC tpc; 542f3fbd535SBarry Smith PetscInt levels = mglevels[0]->levels,i; 54330b0564aSStefano Zampini PetscBool changeu,changed,matapp; 544f3fbd535SBarry Smith 545f3fbd535SBarry Smith PetscFunctionBegin; 54630b0564aSStefano Zampini matapp = (PetscBool)(B && X); 5479566063dSJacob Faibussowitsch if (mg->stageApply) PetscCall(PetscLogStagePush(mg->stageApply)); 548e1d8e5deSBarry Smith /* When the DM is supplying the matrix then it will not exist until here */ 549298cc208SBarry Smith for (i=0; i<levels; i++) { 550e1d8e5deSBarry Smith if (!mglevels[i]->A) { 5519566063dSJacob Faibussowitsch PetscCall(KSPGetOperators(mglevels[i]->smoothu,&mglevels[i]->A,NULL)); 5529566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)mglevels[i]->A)); 553e1d8e5deSBarry Smith } 554e1d8e5deSBarry Smith } 555e1d8e5deSBarry Smith 5569566063dSJacob Faibussowitsch PetscCall(KSPGetPC(mglevels[levels-1]->smoothd,&tpc)); 5579566063dSJacob Faibussowitsch PetscCall(PCPreSolveChangeRHS(tpc,&changed)); 5589566063dSJacob Faibussowitsch PetscCall(KSPGetPC(mglevels[levels-1]->smoothu,&tpc)); 5599566063dSJacob Faibussowitsch PetscCall(PCPreSolveChangeRHS(tpc,&changeu)); 560391689abSStefano Zampini if (!changeu && !changed) { 56130b0564aSStefano Zampini if (matapp) { 5629566063dSJacob Faibussowitsch PetscCall(MatDestroy(&mglevels[levels-1]->B)); 56330b0564aSStefano Zampini mglevels[levels-1]->B = B; 56430b0564aSStefano Zampini } else { 5659566063dSJacob Faibussowitsch PetscCall(VecDestroy(&mglevels[levels-1]->b)); 566f3fbd535SBarry Smith mglevels[levels-1]->b = b; 56730b0564aSStefano Zampini } 568391689abSStefano Zampini } else { /* if the smoother changes the rhs during PreSolve, we cannot use the input vector */ 56930b0564aSStefano Zampini if (matapp) { 57030b0564aSStefano Zampini if (mglevels[levels-1]->B) { 57130b0564aSStefano Zampini PetscInt N1,N2; 57230b0564aSStefano Zampini PetscBool flg; 57330b0564aSStefano Zampini 5749566063dSJacob Faibussowitsch PetscCall(MatGetSize(mglevels[levels-1]->B,NULL,&N1)); 5759566063dSJacob Faibussowitsch PetscCall(MatGetSize(B,NULL,&N2)); 5769566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)mglevels[levels-1]->B,((PetscObject)B)->type_name,&flg)); 57730b0564aSStefano Zampini if (N1 != N2 || !flg) { 5789566063dSJacob Faibussowitsch PetscCall(MatDestroy(&mglevels[levels-1]->B)); 57930b0564aSStefano Zampini } 58030b0564aSStefano Zampini } 58130b0564aSStefano Zampini if (!mglevels[levels-1]->B) { 5829566063dSJacob Faibussowitsch PetscCall(MatDuplicate(B,MAT_COPY_VALUES,&mglevels[levels-1]->B)); 58330b0564aSStefano Zampini } else { 5849566063dSJacob Faibussowitsch PetscCall(MatCopy(B,mglevels[levels-1]->B,SAME_NONZERO_PATTERN)); 58530b0564aSStefano Zampini } 58630b0564aSStefano Zampini } else { 587391689abSStefano Zampini if (!mglevels[levels-1]->b) { 588391689abSStefano Zampini Vec *vec; 589391689abSStefano Zampini 5909566063dSJacob Faibussowitsch PetscCall(KSPCreateVecs(mglevels[levels-1]->smoothd,1,&vec,0,NULL)); 591391689abSStefano Zampini mglevels[levels-1]->b = *vec; 5929566063dSJacob Faibussowitsch PetscCall(PetscFree(vec)); 593391689abSStefano Zampini } 5949566063dSJacob Faibussowitsch PetscCall(VecCopy(b,mglevels[levels-1]->b)); 595391689abSStefano Zampini } 59630b0564aSStefano Zampini } 59730b0564aSStefano Zampini if (matapp) { mglevels[levels-1]->X = X; } 59830b0564aSStefano Zampini else { mglevels[levels-1]->x = x; } 59930b0564aSStefano Zampini 60030b0564aSStefano Zampini /* If coarser Xs are present, it means we have already block applied the PC at least once 60130b0564aSStefano Zampini Reset operators if sizes/type do no match */ 60230b0564aSStefano Zampini if (matapp && levels > 1 && mglevels[levels-2]->X) { 60330b0564aSStefano Zampini PetscInt Xc,Bc; 60430b0564aSStefano Zampini PetscBool flg; 60530b0564aSStefano Zampini 6069566063dSJacob Faibussowitsch PetscCall(MatGetSize(mglevels[levels-2]->X,NULL,&Xc)); 6079566063dSJacob Faibussowitsch PetscCall(MatGetSize(mglevels[levels-1]->B,NULL,&Bc)); 6089566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)mglevels[levels-2]->X,((PetscObject)mglevels[levels-1]->X)->type_name,&flg)); 60930b0564aSStefano Zampini if (Xc != Bc || !flg) { 6109566063dSJacob Faibussowitsch PetscCall(MatDestroy(&mglevels[levels-1]->R)); 61130b0564aSStefano Zampini for (i=0;i<levels-1;i++) { 6129566063dSJacob Faibussowitsch PetscCall(MatDestroy(&mglevels[i]->R)); 6139566063dSJacob Faibussowitsch PetscCall(MatDestroy(&mglevels[i]->B)); 6149566063dSJacob Faibussowitsch PetscCall(MatDestroy(&mglevels[i]->X)); 61530b0564aSStefano Zampini } 61630b0564aSStefano Zampini } 61730b0564aSStefano Zampini } 618391689abSStefano Zampini 61931567311SBarry Smith if (mg->am == PC_MG_MULTIPLICATIVE) { 6209566063dSJacob Faibussowitsch if (matapp) PetscCall(MatZeroEntries(X)); 6219566063dSJacob Faibussowitsch else PetscCall(VecZeroEntries(x)); 62231567311SBarry Smith for (i=0; i<mg->cyclesperpcapply; i++) { 6239566063dSJacob Faibussowitsch PetscCall(PCMGMCycle_Private(pc,mglevels+levels-1,transpose,matapp,NULL)); 624f3fbd535SBarry Smith } 6252fa5cd67SKarl Rupp } else if (mg->am == PC_MG_ADDITIVE) { 6269566063dSJacob Faibussowitsch PetscCall(PCMGACycle_Private(pc,mglevels,transpose,matapp)); 6272fa5cd67SKarl Rupp } else if (mg->am == PC_MG_KASKADE) { 6289566063dSJacob Faibussowitsch PetscCall(PCMGKCycle_Private(pc,mglevels,transpose,matapp)); 6292fa5cd67SKarl Rupp } else { 6309566063dSJacob Faibussowitsch PetscCall(PCMGFCycle_Private(pc,mglevels,transpose,matapp)); 631f3fbd535SBarry Smith } 6329566063dSJacob Faibussowitsch if (mg->stageApply) PetscCall(PetscLogStagePop()); 63330b0564aSStefano Zampini if (!changeu && !changed) { 63430b0564aSStefano Zampini if (matapp) { mglevels[levels-1]->B = NULL; } 63530b0564aSStefano Zampini else { mglevels[levels-1]->b = NULL; } 63630b0564aSStefano Zampini } 637f3fbd535SBarry Smith PetscFunctionReturn(0); 638f3fbd535SBarry Smith } 639f3fbd535SBarry Smith 640fcb023d4SJed Brown static PetscErrorCode PCApply_MG(PC pc,Vec b,Vec x) 641fcb023d4SJed Brown { 642fcb023d4SJed Brown PetscFunctionBegin; 6439566063dSJacob Faibussowitsch PetscCall(PCApply_MG_Internal(pc,b,x,NULL,NULL,PETSC_FALSE)); 644fcb023d4SJed Brown PetscFunctionReturn(0); 645fcb023d4SJed Brown } 646fcb023d4SJed Brown 647fcb023d4SJed Brown static PetscErrorCode PCApplyTranspose_MG(PC pc,Vec b,Vec x) 648fcb023d4SJed Brown { 649fcb023d4SJed Brown PetscFunctionBegin; 6509566063dSJacob Faibussowitsch PetscCall(PCApply_MG_Internal(pc,b,x,NULL,NULL,PETSC_TRUE)); 65130b0564aSStefano Zampini PetscFunctionReturn(0); 65230b0564aSStefano Zampini } 65330b0564aSStefano Zampini 65430b0564aSStefano Zampini static PetscErrorCode PCMatApply_MG(PC pc,Mat b,Mat x) 65530b0564aSStefano Zampini { 65630b0564aSStefano Zampini PetscFunctionBegin; 6579566063dSJacob Faibussowitsch PetscCall(PCApply_MG_Internal(pc,NULL,NULL,b,x,PETSC_FALSE)); 658fcb023d4SJed Brown PetscFunctionReturn(0); 659fcb023d4SJed Brown } 660f3fbd535SBarry Smith 6614416b707SBarry Smith PetscErrorCode PCSetFromOptions_MG(PetscOptionItems *PetscOptionsObject,PC pc) 662f3fbd535SBarry Smith { 663710315b6SLawrence Mitchell PetscInt levels,cycles; 664f3b08a26SMatthew G. Knepley PetscBool flg, flg2; 665f3fbd535SBarry Smith PC_MG *mg = (PC_MG*)pc->data; 6663d3eaba7SBarry Smith PC_MG_Levels **mglevels; 667f3fbd535SBarry Smith PCMGType mgtype; 668f3fbd535SBarry Smith PCMGCycleType mgctype; 6692134b1e4SBarry Smith PCMGGalerkinType gtype; 6702b3cbbdaSStefano Zampini PCMGCoarseSpaceType coarseSpaceType; 671f3fbd535SBarry Smith 672f3fbd535SBarry Smith PetscFunctionBegin; 6731d743356SStefano Zampini levels = PetscMax(mg->nlevels,1); 674d0609cedSBarry Smith PetscOptionsHeadBegin(PetscOptionsObject,"Multigrid options"); 6759566063dSJacob Faibussowitsch PetscCall(PetscOptionsInt("-pc_mg_levels","Number of Levels","PCMGSetLevels",levels,&levels,&flg)); 6761a97d7b6SStefano Zampini if (!flg && !mg->levels && pc->dm) { 6779566063dSJacob Faibussowitsch PetscCall(DMGetRefineLevel(pc->dm,&levels)); 678eb3f98d2SBarry Smith levels++; 6793aeaf226SBarry Smith mg->usedmfornumberoflevels = PETSC_TRUE; 680eb3f98d2SBarry Smith } 6819566063dSJacob Faibussowitsch PetscCall(PCMGSetLevels(pc,levels,NULL)); 6823aeaf226SBarry Smith mglevels = mg->levels; 6833aeaf226SBarry Smith 684f3fbd535SBarry Smith mgctype = (PCMGCycleType) mglevels[0]->cycles; 6859566063dSJacob Faibussowitsch PetscCall(PetscOptionsEnum("-pc_mg_cycle_type","V cycle or for W-cycle","PCMGSetCycleType",PCMGCycleTypes,(PetscEnum)mgctype,(PetscEnum*)&mgctype,&flg)); 686f3fbd535SBarry Smith if (flg) { 6879566063dSJacob Faibussowitsch PetscCall(PCMGSetCycleType(pc,mgctype)); 6882fa5cd67SKarl Rupp } 6892134b1e4SBarry Smith gtype = mg->galerkin; 6909566063dSJacob Faibussowitsch PetscCall(PetscOptionsEnum("-pc_mg_galerkin","Use Galerkin process to compute coarser operators","PCMGSetGalerkin",PCMGGalerkinTypes,(PetscEnum)gtype,(PetscEnum*)>ype,&flg)); 6912134b1e4SBarry Smith if (flg) { 6929566063dSJacob Faibussowitsch PetscCall(PCMGSetGalerkin(pc,gtype)); 693f3fbd535SBarry Smith } 6942b3cbbdaSStefano Zampini coarseSpaceType = mg->coarseSpaceType; 6952b3cbbdaSStefano Zampini PetscCall(PetscOptionsEnum("-pc_mg_adapt_interp_coarse_space","Type of adaptive coarse space: none, polynomial, harmonic, eigenvector, generalized_eigenvector, gdsw","PCMGSetAdaptCoarseSpaceType",PCMGCoarseSpaceTypes,(PetscEnum)coarseSpaceType,(PetscEnum*)&coarseSpaceType,&flg)); 6962b3cbbdaSStefano Zampini if (flg) PetscCall(PCMGSetAdaptCoarseSpaceType(pc,coarseSpaceType)); 6979566063dSJacob Faibussowitsch PetscCall(PetscOptionsInt("-pc_mg_adapt_interp_n","Size of the coarse space for adaptive interpolation","PCMGSetCoarseSpace",mg->Nc,&mg->Nc,&flg)); 6989566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-pc_mg_mesp_monitor","Monitor the multilevel eigensolver","PCMGSetAdaptInterpolation",PETSC_FALSE,&mg->mespMonitor,&flg)); 69941b6fd38SMatthew G. Knepley flg2 = PETSC_FALSE; 7009566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-pc_mg_adapt_cr","Monitor coarse space quality using Compatible Relaxation (CR)","PCMGSetAdaptCR",PETSC_FALSE,&flg2,&flg)); 7019566063dSJacob Faibussowitsch if (flg) PetscCall(PCMGSetAdaptCR(pc, flg2)); 702f56b1265SBarry Smith flg = PETSC_FALSE; 7039566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-pc_mg_distinct_smoothup","Create separate smoothup KSP and append the prefix _up","PCMGSetDistinctSmoothUp",PETSC_FALSE,&flg,NULL)); 704f442ab6aSBarry Smith if (flg) { 7059566063dSJacob Faibussowitsch PetscCall(PCMGSetDistinctSmoothUp(pc)); 706f442ab6aSBarry Smith } 70731567311SBarry Smith mgtype = mg->am; 7089566063dSJacob Faibussowitsch PetscCall(PetscOptionsEnum("-pc_mg_type","Multigrid type","PCMGSetType",PCMGTypes,(PetscEnum)mgtype,(PetscEnum*)&mgtype,&flg)); 709f3fbd535SBarry Smith if (flg) { 7109566063dSJacob Faibussowitsch PetscCall(PCMGSetType(pc,mgtype)); 711f3fbd535SBarry Smith } 71231567311SBarry Smith if (mg->am == PC_MG_MULTIPLICATIVE) { 7139566063dSJacob Faibussowitsch PetscCall(PetscOptionsInt("-pc_mg_multiplicative_cycles","Number of cycles for each preconditioner step","PCMGMultiplicativeSetCycles",mg->cyclesperpcapply,&cycles,&flg)); 714f3fbd535SBarry Smith if (flg) { 7159566063dSJacob Faibussowitsch PetscCall(PCMGMultiplicativeSetCycles(pc,cycles)); 716f3fbd535SBarry Smith } 717f3fbd535SBarry Smith } 718f3fbd535SBarry Smith flg = PETSC_FALSE; 7199566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-pc_mg_log","Log times for each multigrid level","None",flg,&flg,NULL)); 720f3fbd535SBarry Smith if (flg) { 721f3fbd535SBarry Smith PetscInt i; 722f3fbd535SBarry Smith char eventname[128]; 7231a97d7b6SStefano Zampini 724f3fbd535SBarry Smith levels = mglevels[0]->levels; 725f3fbd535SBarry Smith for (i=0; i<levels; i++) { 726f3fbd535SBarry Smith sprintf(eventname,"MGSetup Level %d",(int)i); 7279566063dSJacob Faibussowitsch PetscCall(PetscLogEventRegister(eventname,((PetscObject)pc)->classid,&mglevels[i]->eventsmoothsetup)); 728f3fbd535SBarry Smith sprintf(eventname,"MGSmooth Level %d",(int)i); 7299566063dSJacob Faibussowitsch PetscCall(PetscLogEventRegister(eventname,((PetscObject)pc)->classid,&mglevels[i]->eventsmoothsolve)); 730f3fbd535SBarry Smith if (i) { 731f3fbd535SBarry Smith sprintf(eventname,"MGResid Level %d",(int)i); 7329566063dSJacob Faibussowitsch PetscCall(PetscLogEventRegister(eventname,((PetscObject)pc)->classid,&mglevels[i]->eventresidual)); 733f3fbd535SBarry Smith sprintf(eventname,"MGInterp Level %d",(int)i); 7349566063dSJacob Faibussowitsch PetscCall(PetscLogEventRegister(eventname,((PetscObject)pc)->classid,&mglevels[i]->eventinterprestrict)); 735f3fbd535SBarry Smith } 736f3fbd535SBarry Smith } 737eec35531SMatthew G Knepley 738ec60ca73SSatish Balay #if defined(PETSC_USE_LOG) 739eec35531SMatthew G Knepley { 740eec35531SMatthew G Knepley const char *sname = "MG Apply"; 741eec35531SMatthew G Knepley PetscStageLog stageLog; 742eec35531SMatthew G Knepley PetscInt st; 743eec35531SMatthew G Knepley 7449566063dSJacob Faibussowitsch PetscCall(PetscLogGetStageLog(&stageLog)); 745eec35531SMatthew G Knepley for (st = 0; st < stageLog->numStages; ++st) { 746eec35531SMatthew G Knepley PetscBool same; 747eec35531SMatthew G Knepley 7489566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(stageLog->stageInfo[st].name, sname, &same)); 7492fa5cd67SKarl Rupp if (same) mg->stageApply = st; 750eec35531SMatthew G Knepley } 751eec35531SMatthew G Knepley if (!mg->stageApply) { 7529566063dSJacob Faibussowitsch PetscCall(PetscLogStageRegister(sname, &mg->stageApply)); 753eec35531SMatthew G Knepley } 754eec35531SMatthew G Knepley } 755ec60ca73SSatish Balay #endif 756f3fbd535SBarry Smith } 757d0609cedSBarry Smith PetscOptionsHeadEnd(); 758f3b08a26SMatthew G. Knepley /* Check option consistency */ 7599566063dSJacob Faibussowitsch PetscCall(PCMGGetGalerkin(pc, >ype)); 7609566063dSJacob Faibussowitsch PetscCall(PCMGGetAdaptInterpolation(pc, &flg)); 76108401ef6SPierre Jolivet PetscCheck(!flg || !(gtype >= PC_MG_GALERKIN_NONE),PetscObjectComm((PetscObject) pc), PETSC_ERR_ARG_INCOMP, "Must use Galerkin coarse operators when adapting the interpolator"); 762f3fbd535SBarry Smith PetscFunctionReturn(0); 763f3fbd535SBarry Smith } 764f3fbd535SBarry Smith 7650a545947SLisandro Dalcin const char *const PCMGTypes[] = {"MULTIPLICATIVE","ADDITIVE","FULL","KASKADE","PCMGType","PC_MG",NULL}; 7660a545947SLisandro Dalcin const char *const PCMGCycleTypes[] = {"invalid","v","w","PCMGCycleType","PC_MG_CYCLE",NULL}; 7670a545947SLisandro Dalcin const char *const PCMGGalerkinTypes[] = {"both","pmat","mat","none","external","PCMGGalerkinType","PC_MG_GALERKIN",NULL}; 7682b3cbbdaSStefano Zampini const char *const PCMGCoarseSpaceTypes[] = {"none","polynomial","harmonic","eigenvector","generalized_eigenvector","gdsw","PCMGCoarseSpaceType","PCMG_ADAPT_NONE",NULL}; 769f3fbd535SBarry Smith 7709804daf3SBarry Smith #include <petscdraw.h> 771f3fbd535SBarry Smith PetscErrorCode PCView_MG(PC pc,PetscViewer viewer) 772f3fbd535SBarry Smith { 773f3fbd535SBarry Smith PC_MG *mg = (PC_MG*)pc->data; 774f3fbd535SBarry Smith PC_MG_Levels **mglevels = mg->levels; 775e3deeeafSJed Brown PetscInt levels = mglevels ? mglevels[0]->levels : 0,i; 776219b1045SBarry Smith PetscBool iascii,isbinary,isdraw; 777f3fbd535SBarry Smith 778f3fbd535SBarry Smith PetscFunctionBegin; 7799566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii)); 7809566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERBINARY,&isbinary)); 7819566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERDRAW,&isdraw)); 782f3fbd535SBarry Smith if (iascii) { 783e3deeeafSJed Brown const char *cyclename = levels ? (mglevels[0]->cycles == PC_MG_CYCLE_V ? "v" : "w") : "unknown"; 78463a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer," type is %s, levels=%" PetscInt_FMT " cycles=%s\n", PCMGTypes[mg->am],levels,cyclename)); 78531567311SBarry Smith if (mg->am == PC_MG_MULTIPLICATIVE) { 78663a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer," Cycles per PCApply=%" PetscInt_FMT "\n",mg->cyclesperpcapply)); 787f3fbd535SBarry Smith } 7882134b1e4SBarry Smith if (mg->galerkin == PC_MG_GALERKIN_BOTH) { 7899566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer," Using Galerkin computed coarse grid matrices\n")); 7902134b1e4SBarry Smith } else if (mg->galerkin == PC_MG_GALERKIN_PMAT) { 7919566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer," Using Galerkin computed coarse grid matrices for pmat\n")); 7922134b1e4SBarry Smith } else if (mg->galerkin == PC_MG_GALERKIN_MAT) { 7939566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer," Using Galerkin computed coarse grid matrices for mat\n")); 7942134b1e4SBarry Smith } else if (mg->galerkin == PC_MG_GALERKIN_EXTERNAL) { 7959566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer," Using externally compute Galerkin coarse grid matrices\n")); 7964f66f45eSBarry Smith } else { 7979566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer," Not using Galerkin computed coarse grid matrices\n")); 798f3fbd535SBarry Smith } 7995adeb434SBarry Smith if (mg->view) { 8009566063dSJacob Faibussowitsch PetscCall((*mg->view)(pc,viewer)); 8015adeb434SBarry Smith } 802f3fbd535SBarry Smith for (i=0; i<levels; i++) { 80363a3b9bcSJacob Faibussowitsch if (i) { 80463a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer,"Down solver (pre-smoother) on level %" PetscInt_FMT " -------------------------------\n",i)); 805f3fbd535SBarry Smith } else { 80663a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer,"Coarse grid solver -- level %" PetscInt_FMT " -------------------------------\n",i)); 807f3fbd535SBarry Smith } 8089566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushTab(viewer)); 8099566063dSJacob Faibussowitsch PetscCall(KSPView(mglevels[i]->smoothd,viewer)); 8109566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopTab(viewer)); 811f3fbd535SBarry Smith if (i && mglevels[i]->smoothd == mglevels[i]->smoothu) { 8129566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer,"Up solver (post-smoother) same as down solver (pre-smoother)\n")); 813f3fbd535SBarry Smith } else if (i) { 81463a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer,"Up solver (post-smoother) on level %" PetscInt_FMT " -------------------------------\n",i)); 8159566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushTab(viewer)); 8169566063dSJacob Faibussowitsch PetscCall(KSPView(mglevels[i]->smoothu,viewer)); 8179566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopTab(viewer)); 818f3fbd535SBarry Smith } 81941b6fd38SMatthew G. Knepley if (i && mglevels[i]->cr) { 82063a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer,"CR solver on level %" PetscInt_FMT " -------------------------------\n",i)); 8219566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushTab(viewer)); 8229566063dSJacob Faibussowitsch PetscCall(KSPView(mglevels[i]->cr,viewer)); 8239566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopTab(viewer)); 82441b6fd38SMatthew G. Knepley } 825f3fbd535SBarry Smith } 8265b0b0462SBarry Smith } else if (isbinary) { 8275b0b0462SBarry Smith for (i=levels-1; i>=0; i--) { 8289566063dSJacob Faibussowitsch PetscCall(KSPView(mglevels[i]->smoothd,viewer)); 8295b0b0462SBarry Smith if (i && mglevels[i]->smoothd != mglevels[i]->smoothu) { 8309566063dSJacob Faibussowitsch PetscCall(KSPView(mglevels[i]->smoothu,viewer)); 8315b0b0462SBarry Smith } 8325b0b0462SBarry Smith } 833219b1045SBarry Smith } else if (isdraw) { 834219b1045SBarry Smith PetscDraw draw; 835b4375e8dSPeter Brune PetscReal x,w,y,bottom,th; 8369566063dSJacob Faibussowitsch PetscCall(PetscViewerDrawGetDraw(viewer,0,&draw)); 8379566063dSJacob Faibussowitsch PetscCall(PetscDrawGetCurrentPoint(draw,&x,&y)); 8389566063dSJacob Faibussowitsch PetscCall(PetscDrawStringGetSize(draw,NULL,&th)); 839219b1045SBarry Smith bottom = y - th; 840219b1045SBarry Smith for (i=levels-1; i>=0; i--) { 841b4375e8dSPeter Brune if (!mglevels[i]->smoothu || (mglevels[i]->smoothu == mglevels[i]->smoothd)) { 8429566063dSJacob Faibussowitsch PetscCall(PetscDrawPushCurrentPoint(draw,x,bottom)); 8439566063dSJacob Faibussowitsch PetscCall(KSPView(mglevels[i]->smoothd,viewer)); 8449566063dSJacob Faibussowitsch PetscCall(PetscDrawPopCurrentPoint(draw)); 845b4375e8dSPeter Brune } else { 846b4375e8dSPeter Brune w = 0.5*PetscMin(1.0-x,x); 8479566063dSJacob Faibussowitsch PetscCall(PetscDrawPushCurrentPoint(draw,x+w,bottom)); 8489566063dSJacob Faibussowitsch PetscCall(KSPView(mglevels[i]->smoothd,viewer)); 8499566063dSJacob Faibussowitsch PetscCall(PetscDrawPopCurrentPoint(draw)); 8509566063dSJacob Faibussowitsch PetscCall(PetscDrawPushCurrentPoint(draw,x-w,bottom)); 8519566063dSJacob Faibussowitsch PetscCall(KSPView(mglevels[i]->smoothu,viewer)); 8529566063dSJacob Faibussowitsch PetscCall(PetscDrawPopCurrentPoint(draw)); 853b4375e8dSPeter Brune } 8549566063dSJacob Faibussowitsch PetscCall(PetscDrawGetBoundingBox(draw,NULL,&bottom,NULL,NULL)); 8551cd381d6SBarry Smith bottom -= th; 856219b1045SBarry Smith } 8575b0b0462SBarry Smith } 858f3fbd535SBarry Smith PetscFunctionReturn(0); 859f3fbd535SBarry Smith } 860f3fbd535SBarry Smith 861af0996ceSBarry Smith #include <petsc/private/kspimpl.h> 862cab2e9ccSBarry Smith 863f3fbd535SBarry Smith /* 864f3fbd535SBarry Smith Calls setup for the KSP on each level 865f3fbd535SBarry Smith */ 866f3fbd535SBarry Smith PetscErrorCode PCSetUp_MG(PC pc) 867f3fbd535SBarry Smith { 868f3fbd535SBarry Smith PC_MG *mg = (PC_MG*)pc->data; 869f3fbd535SBarry Smith PC_MG_Levels **mglevels = mg->levels; 8701a97d7b6SStefano Zampini PetscInt i,n; 87198e04984SBarry Smith PC cpc; 8723db492dfSBarry Smith PetscBool dump = PETSC_FALSE,opsset,use_amat,missinginterpolate = PETSC_FALSE; 873f3fbd535SBarry Smith Mat dA,dB; 874f3fbd535SBarry Smith Vec tvec; 875218a07d4SBarry Smith DM *dms; 8760a545947SLisandro Dalcin PetscViewer viewer = NULL; 87741b6fd38SMatthew G. Knepley PetscBool dAeqdB = PETSC_FALSE, needRestricts = PETSC_FALSE, doCR = PETSC_FALSE; 8782b3cbbdaSStefano Zampini PetscBool adaptInterpolation = mg->adaptInterpolation; 879f3fbd535SBarry Smith 880f3fbd535SBarry Smith PetscFunctionBegin; 88128b400f6SJacob Faibussowitsch PetscCheck(mglevels,PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONGSTATE,"Must set MG levels with PCMGSetLevels() before setting up"); 8821a97d7b6SStefano Zampini n = mglevels[0]->levels; 88301bc414fSDmitry Karpeev /* FIX: Move this to PCSetFromOptions_MG? */ 8843aeaf226SBarry Smith if (mg->usedmfornumberoflevels) { 8853aeaf226SBarry Smith PetscInt levels; 8869566063dSJacob Faibussowitsch PetscCall(DMGetRefineLevel(pc->dm,&levels)); 8873aeaf226SBarry Smith levels++; 8883aeaf226SBarry Smith if (levels > n) { /* the problem is now being solved on a finer grid */ 8899566063dSJacob Faibussowitsch PetscCall(PCMGSetLevels(pc,levels,NULL)); 8903aeaf226SBarry Smith n = levels; 8919566063dSJacob Faibussowitsch PetscCall(PCSetFromOptions(pc)); /* it is bad to call this here, but otherwise will never be called for the new hierarchy */ 8923aeaf226SBarry Smith mglevels = mg->levels; 8933aeaf226SBarry Smith } 8943aeaf226SBarry Smith } 8959566063dSJacob Faibussowitsch PetscCall(KSPGetPC(mglevels[0]->smoothd,&cpc)); 8963aeaf226SBarry Smith 897f3fbd535SBarry Smith /* If user did not provide fine grid operators OR operator was not updated since last global KSPSetOperators() */ 898f3fbd535SBarry Smith /* so use those from global PC */ 899f3fbd535SBarry Smith /* Is this what we always want? What if user wants to keep old one? */ 9009566063dSJacob Faibussowitsch PetscCall(KSPGetOperatorsSet(mglevels[n-1]->smoothd,NULL,&opsset)); 90198e04984SBarry Smith if (opsset) { 90298e04984SBarry Smith Mat mmat; 9039566063dSJacob Faibussowitsch PetscCall(KSPGetOperators(mglevels[n-1]->smoothd,NULL,&mmat)); 90498e04984SBarry Smith if (mmat == pc->pmat) opsset = PETSC_FALSE; 90598e04984SBarry Smith } 9064a5f07a5SMark F. Adams 90741b6fd38SMatthew G. Knepley /* Create CR solvers */ 9089566063dSJacob Faibussowitsch PetscCall(PCMGGetAdaptCR(pc, &doCR)); 90941b6fd38SMatthew G. Knepley if (doCR) { 91041b6fd38SMatthew G. Knepley const char *prefix; 91141b6fd38SMatthew G. Knepley 9129566063dSJacob Faibussowitsch PetscCall(PCGetOptionsPrefix(pc, &prefix)); 91341b6fd38SMatthew G. Knepley for (i = 1; i < n; ++i) { 91441b6fd38SMatthew G. Knepley PC ipc, cr; 91541b6fd38SMatthew G. Knepley char crprefix[128]; 91641b6fd38SMatthew G. Knepley 9179566063dSJacob Faibussowitsch PetscCall(KSPCreate(PetscObjectComm((PetscObject) pc), &mglevels[i]->cr)); 9189566063dSJacob Faibussowitsch PetscCall(KSPSetErrorIfNotConverged(mglevels[i]->cr, PETSC_FALSE)); 9199566063dSJacob Faibussowitsch PetscCall(PetscObjectIncrementTabLevel((PetscObject) mglevels[i]->cr, (PetscObject) pc, n-i)); 9209566063dSJacob Faibussowitsch PetscCall(KSPSetOptionsPrefix(mglevels[i]->cr, prefix)); 9219566063dSJacob Faibussowitsch PetscCall(PetscObjectComposedDataSetInt((PetscObject) mglevels[i]->cr, PetscMGLevelId, mglevels[i]->level)); 9229566063dSJacob Faibussowitsch PetscCall(KSPSetType(mglevels[i]->cr, KSPCHEBYSHEV)); 9239566063dSJacob Faibussowitsch PetscCall(KSPSetConvergenceTest(mglevels[i]->cr, KSPConvergedSkip, NULL, NULL)); 9249566063dSJacob Faibussowitsch PetscCall(KSPSetNormType(mglevels[i]->cr, KSP_NORM_PRECONDITIONED)); 9259566063dSJacob Faibussowitsch PetscCall(KSPGetPC(mglevels[i]->cr, &ipc)); 92641b6fd38SMatthew G. Knepley 9279566063dSJacob Faibussowitsch PetscCall(PCSetType(ipc, PCCOMPOSITE)); 9289566063dSJacob Faibussowitsch PetscCall(PCCompositeSetType(ipc, PC_COMPOSITE_MULTIPLICATIVE)); 9299566063dSJacob Faibussowitsch PetscCall(PCCompositeAddPCType(ipc, PCSOR)); 9309566063dSJacob Faibussowitsch PetscCall(CreateCR_Private(pc, i, &cr)); 9319566063dSJacob Faibussowitsch PetscCall(PCCompositeAddPC(ipc, cr)); 9329566063dSJacob Faibussowitsch PetscCall(PCDestroy(&cr)); 93341b6fd38SMatthew G. Knepley 9349566063dSJacob Faibussowitsch PetscCall(KSPSetTolerances(mglevels[i]->cr, PETSC_DEFAULT, PETSC_DEFAULT, PETSC_DEFAULT, mg->default_smoothd)); 9359566063dSJacob Faibussowitsch PetscCall(KSPSetInitialGuessNonzero(mglevels[i]->cr, PETSC_TRUE)); 9369566063dSJacob Faibussowitsch PetscCall(PetscSNPrintf(crprefix, 128, "mg_levels_%d_cr_", (int) i)); 9379566063dSJacob Faibussowitsch PetscCall(KSPAppendOptionsPrefix(mglevels[i]->cr, crprefix)); 9389566063dSJacob Faibussowitsch PetscCall(PetscLogObjectParent((PetscObject) pc, (PetscObject) mglevels[i]->cr)); 93941b6fd38SMatthew G. Knepley } 94041b6fd38SMatthew G. Knepley } 94141b6fd38SMatthew G. Knepley 9424a5f07a5SMark F. Adams if (!opsset) { 9439566063dSJacob Faibussowitsch PetscCall(PCGetUseAmat(pc,&use_amat)); 9444a5f07a5SMark F. Adams if (use_amat) { 9459566063dSJacob Faibussowitsch PetscCall(PetscInfo(pc,"Using outer operators to define finest grid operator \n because PCMGGetSmoother(pc,nlevels-1,&ksp);KSPSetOperators(ksp,...); was not called.\n")); 9469566063dSJacob Faibussowitsch PetscCall(KSPSetOperators(mglevels[n-1]->smoothd,pc->mat,pc->pmat)); 94769858f1bSStefano Zampini } else { 9489566063dSJacob Faibussowitsch PetscCall(PetscInfo(pc,"Using matrix (pmat) operators to define finest grid operator \n because PCMGGetSmoother(pc,nlevels-1,&ksp);KSPSetOperators(ksp,...); was not called.\n")); 9499566063dSJacob Faibussowitsch PetscCall(KSPSetOperators(mglevels[n-1]->smoothd,pc->pmat,pc->pmat)); 9504a5f07a5SMark F. Adams } 9514a5f07a5SMark F. Adams } 952f3fbd535SBarry Smith 9539c7ffb39SBarry Smith for (i=n-1; i>0; i--) { 9549c7ffb39SBarry Smith if (!(mglevels[i]->interpolate || mglevels[i]->restrct)) { 9559c7ffb39SBarry Smith missinginterpolate = PETSC_TRUE; 9562b3cbbdaSStefano Zampini break; 9579c7ffb39SBarry Smith } 9589c7ffb39SBarry Smith } 9592134b1e4SBarry Smith 9609566063dSJacob Faibussowitsch PetscCall(KSPGetOperators(mglevels[n-1]->smoothd,&dA,&dB)); 9612134b1e4SBarry Smith if (dA == dB) dAeqdB = PETSC_TRUE; 9622b3cbbdaSStefano Zampini if (mg->galerkin == PC_MG_GALERKIN_NONE || ((mg->galerkin == PC_MG_GALERKIN_PMAT || mg->galerkin == PC_MG_GALERKIN_MAT) && !dAeqdB)) { 9632134b1e4SBarry Smith needRestricts = PETSC_TRUE; /* user must compute either mat, pmat, or both so must restrict x to coarser levels */ 9642134b1e4SBarry Smith } 9652134b1e4SBarry Smith 9662b3cbbdaSStefano Zampini if (pc->dm && !pc->setupcalled) { 9672b3cbbdaSStefano Zampini /* finest smoother also gets DM but it is not active, independent of whether galerkin==PC_MG_GALERKIN_EXTERNAL */ 9682b3cbbdaSStefano Zampini PetscCall(KSPSetDM(mglevels[n-1]->smoothd,pc->dm)); 9692b3cbbdaSStefano Zampini PetscCall(KSPSetDMActive(mglevels[n-1]->smoothd,PETSC_FALSE)); 9702b3cbbdaSStefano Zampini if (mglevels[n-1]->smoothd != mglevels[n-1]->smoothu) { 9712b3cbbdaSStefano Zampini PetscCall(KSPSetDM(mglevels[n-1]->smoothu,pc->dm)); 9722b3cbbdaSStefano Zampini PetscCall(KSPSetDMActive(mglevels[n-1]->smoothu,PETSC_FALSE)); 9732b3cbbdaSStefano Zampini } 9742b3cbbdaSStefano Zampini if (mglevels[n-1]->cr) { 9752b3cbbdaSStefano Zampini PetscCall(KSPSetDM(mglevels[n-1]->cr,pc->dm)); 9762b3cbbdaSStefano Zampini PetscCall(KSPSetDMActive(mglevels[n-1]->cr,PETSC_FALSE)); 9772b3cbbdaSStefano Zampini } 9782b3cbbdaSStefano Zampini } 9792b3cbbdaSStefano Zampini 9809c7ffb39SBarry Smith /* 9819c7ffb39SBarry Smith Skipping if user has provided all interpolation/restriction needed (since DM might not be able to produce them (when coming from SNES/TS) 9822b3cbbdaSStefano Zampini Skipping for externally managed hierarchy (such as ML and GAMG). Cleaner logic here would be great. Wrap ML/GAMG as DMs? 9839c7ffb39SBarry Smith */ 984*32fe681dSStefano Zampini if (missinginterpolate && mg->galerkin != PC_MG_GALERKIN_EXTERNAL && !pc->setupcalled) { 985*32fe681dSStefano Zampini /* first see if we can compute a coarse space */ 986*32fe681dSStefano Zampini if (mg->coarseSpaceType == PCMG_ADAPT_GDSW) { 987*32fe681dSStefano Zampini for (i=n-2; i>-1; i--) { 988*32fe681dSStefano Zampini if (!mglevels[i+1]->restrct && !mglevels[i+1]->interpolate) { 989*32fe681dSStefano Zampini PetscCall(PCMGComputeCoarseSpace_Internal(pc, i+1, mg->coarseSpaceType, mg->Nc, NULL, &mglevels[i+1]->coarseSpace)); 990*32fe681dSStefano Zampini PetscCall(PCMGSetInterpolation(pc,i+1,mglevels[i+1]->coarseSpace)); 991*32fe681dSStefano Zampini } 992*32fe681dSStefano Zampini } 993*32fe681dSStefano Zampini } else { /* construct the interpolation from the DMs */ 9942e499ae9SBarry Smith Mat p; 99573250ac0SBarry Smith Vec rscale; 9969566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(n,&dms)); 997218a07d4SBarry Smith dms[n-1] = pc->dm; 998ef1267afSMatthew G. Knepley /* Separately create them so we do not get DMKSP interference between levels */ 9999566063dSJacob Faibussowitsch for (i=n-2; i>-1; i--) PetscCall(DMCoarsen(dms[i+1],MPI_COMM_NULL,&dms[i])); 1000218a07d4SBarry Smith for (i=n-2; i>-1; i--) { 1001942e3340SBarry Smith DMKSP kdm; 1002eab52d2bSLawrence Mitchell PetscBool dmhasrestrict, dmhasinject; 10039566063dSJacob Faibussowitsch PetscCall(KSPSetDM(mglevels[i]->smoothd,dms[i])); 10049566063dSJacob Faibussowitsch if (!needRestricts) PetscCall(KSPSetDMActive(mglevels[i]->smoothd,PETSC_FALSE)); 1005c27ee7a3SPatrick Farrell if (mglevels[i]->smoothd != mglevels[i]->smoothu) { 10069566063dSJacob Faibussowitsch PetscCall(KSPSetDM(mglevels[i]->smoothu,dms[i])); 10079566063dSJacob Faibussowitsch if (!needRestricts) PetscCall(KSPSetDMActive(mglevels[i]->smoothu,PETSC_FALSE)); 1008c27ee7a3SPatrick Farrell } 100941b6fd38SMatthew G. Knepley if (mglevels[i]->cr) { 10109566063dSJacob Faibussowitsch PetscCall(KSPSetDM(mglevels[i]->cr,dms[i])); 10119566063dSJacob Faibussowitsch if (!needRestricts) PetscCall(KSPSetDMActive(mglevels[i]->cr,PETSC_FALSE)); 101241b6fd38SMatthew G. Knepley } 10139566063dSJacob Faibussowitsch PetscCall(DMGetDMKSPWrite(dms[i],&kdm)); 1014d1a3e677SJed Brown /* Ugly hack so that the next KSPSetUp() will use the RHS that we set. A better fix is to change dmActive to take 1015d1a3e677SJed Brown * a bitwise OR of computing the matrix, RHS, and initial iterate. */ 10160298fd71SBarry Smith kdm->ops->computerhs = NULL; 10170298fd71SBarry Smith kdm->rhsctx = NULL; 101824c3aa18SBarry Smith if (!mglevels[i+1]->interpolate) { 10199566063dSJacob Faibussowitsch PetscCall(DMCreateInterpolation(dms[i],dms[i+1],&p,&rscale)); 10209566063dSJacob Faibussowitsch PetscCall(PCMGSetInterpolation(pc,i+1,p)); 10219566063dSJacob Faibussowitsch if (rscale) PetscCall(PCMGSetRScale(pc,i+1,rscale)); 10229566063dSJacob Faibussowitsch PetscCall(VecDestroy(&rscale)); 10239566063dSJacob Faibussowitsch PetscCall(MatDestroy(&p)); 1024218a07d4SBarry Smith } 10259566063dSJacob Faibussowitsch PetscCall(DMHasCreateRestriction(dms[i],&dmhasrestrict)); 10263ad4599aSBarry Smith if (dmhasrestrict && !mglevels[i+1]->restrct) { 10279566063dSJacob Faibussowitsch PetscCall(DMCreateRestriction(dms[i],dms[i+1],&p)); 10289566063dSJacob Faibussowitsch PetscCall(PCMGSetRestriction(pc,i+1,p)); 10299566063dSJacob Faibussowitsch PetscCall(MatDestroy(&p)); 10303ad4599aSBarry Smith } 10319566063dSJacob Faibussowitsch PetscCall(DMHasCreateInjection(dms[i],&dmhasinject)); 1032eab52d2bSLawrence Mitchell if (dmhasinject && !mglevels[i+1]->inject) { 10339566063dSJacob Faibussowitsch PetscCall(DMCreateInjection(dms[i],dms[i+1],&p)); 10349566063dSJacob Faibussowitsch PetscCall(PCMGSetInjection(pc,i+1,p)); 10359566063dSJacob Faibussowitsch PetscCall(MatDestroy(&p)); 1036eab52d2bSLawrence Mitchell } 103724c3aa18SBarry Smith } 10382d2b81a6SBarry Smith 10399566063dSJacob Faibussowitsch for (i=n-2; i>-1; i--) PetscCall(DMDestroy(&dms[i])); 10409566063dSJacob Faibussowitsch PetscCall(PetscFree(dms)); 1041ce4cda84SJed Brown } 1042*32fe681dSStefano Zampini } 1043cab2e9ccSBarry Smith 10442134b1e4SBarry Smith if (mg->galerkin < PC_MG_GALERKIN_NONE) { 10452134b1e4SBarry Smith Mat A,B; 10462134b1e4SBarry Smith PetscBool doA = PETSC_FALSE,doB = PETSC_FALSE; 10472134b1e4SBarry Smith MatReuse reuse = MAT_INITIAL_MATRIX; 10482134b1e4SBarry Smith 10492b3cbbdaSStefano Zampini if (mg->galerkin == PC_MG_GALERKIN_PMAT || mg->galerkin == PC_MG_GALERKIN_BOTH) doB = PETSC_TRUE; 10502b3cbbdaSStefano Zampini if (mg->galerkin == PC_MG_GALERKIN_MAT || (mg->galerkin == PC_MG_GALERKIN_BOTH && dA != dB)) doA = PETSC_TRUE; 10512134b1e4SBarry Smith if (pc->setupcalled) reuse = MAT_REUSE_MATRIX; 1052f3fbd535SBarry Smith for (i=n-2; i>-1; i--) { 10537827d75bSBarry Smith PetscCheck(mglevels[i+1]->restrct || mglevels[i+1]->interpolate,PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONGSTATE,"Must provide interpolation or restriction for each MG level except level 0"); 1054b9367914SBarry Smith if (!mglevels[i+1]->interpolate) { 10559566063dSJacob Faibussowitsch PetscCall(PCMGSetInterpolation(pc,i+1,mglevels[i+1]->restrct)); 1056b9367914SBarry Smith } 1057b9367914SBarry Smith if (!mglevels[i+1]->restrct) { 10589566063dSJacob Faibussowitsch PetscCall(PCMGSetRestriction(pc,i+1,mglevels[i+1]->interpolate)); 1059b9367914SBarry Smith } 10602134b1e4SBarry Smith if (reuse == MAT_REUSE_MATRIX) { 10619566063dSJacob Faibussowitsch PetscCall(KSPGetOperators(mglevels[i]->smoothd,&A,&B)); 10622134b1e4SBarry Smith } 10632134b1e4SBarry Smith if (doA) { 10649566063dSJacob Faibussowitsch PetscCall(MatGalerkin(mglevels[i+1]->restrct,dA,mglevels[i+1]->interpolate,reuse,1.0,&A)); 10652134b1e4SBarry Smith } 10662134b1e4SBarry Smith if (doB) { 10679566063dSJacob Faibussowitsch PetscCall(MatGalerkin(mglevels[i+1]->restrct,dB,mglevels[i+1]->interpolate,reuse,1.0,&B)); 1068b9367914SBarry Smith } 10692134b1e4SBarry Smith /* the management of the PetscObjectReference() and PetscObjecDereference() below is rather delicate */ 10702134b1e4SBarry Smith if (!doA && dAeqdB) { 10719566063dSJacob Faibussowitsch if (reuse == MAT_INITIAL_MATRIX) PetscCall(PetscObjectReference((PetscObject)B)); 10722134b1e4SBarry Smith A = B; 10732134b1e4SBarry Smith } else if (!doA && reuse == MAT_INITIAL_MATRIX) { 10749566063dSJacob Faibussowitsch PetscCall(KSPGetOperators(mglevels[i]->smoothd,&A,NULL)); 10759566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)A)); 1076b9367914SBarry Smith } 10772134b1e4SBarry Smith if (!doB && dAeqdB) { 10789566063dSJacob Faibussowitsch if (reuse == MAT_INITIAL_MATRIX) PetscCall(PetscObjectReference((PetscObject)A)); 10792134b1e4SBarry Smith B = A; 10802134b1e4SBarry Smith } else if (!doB && reuse == MAT_INITIAL_MATRIX) { 10819566063dSJacob Faibussowitsch PetscCall(KSPGetOperators(mglevels[i]->smoothd,NULL,&B)); 10829566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)B)); 10837d537d92SJed Brown } 10842134b1e4SBarry Smith if (reuse == MAT_INITIAL_MATRIX) { 10859566063dSJacob Faibussowitsch PetscCall(KSPSetOperators(mglevels[i]->smoothd,A,B)); 10869566063dSJacob Faibussowitsch PetscCall(PetscObjectDereference((PetscObject)A)); 10879566063dSJacob Faibussowitsch PetscCall(PetscObjectDereference((PetscObject)B)); 10882134b1e4SBarry Smith } 10892134b1e4SBarry Smith dA = A; 1090f3fbd535SBarry Smith dB = B; 1091f3fbd535SBarry Smith } 1092f3fbd535SBarry Smith } 1093f3b08a26SMatthew G. Knepley 1094f3b08a26SMatthew G. Knepley /* Adapt interpolation matrices */ 10952b3cbbdaSStefano Zampini if (adaptInterpolation) { 1096f3b08a26SMatthew G. Knepley for (i = 0; i < n; ++i) { 10972b3cbbdaSStefano Zampini if (!mglevels[i]->coarseSpace) { 10989566063dSJacob Faibussowitsch PetscCall(PCMGComputeCoarseSpace_Internal(pc, i, mg->coarseSpaceType, mg->Nc, !i ? NULL : mglevels[i-1]->coarseSpace, &mglevels[i]->coarseSpace)); 10992b3cbbdaSStefano Zampini } 11002b3cbbdaSStefano Zampini if (i) PetscCall(PCMGAdaptInterpolator_Internal(pc, i, mglevels[i-1]->smoothu, mglevels[i]->smoothu, mglevels[i-1]->coarseSpace, mglevels[i]->coarseSpace)); 1101f3b08a26SMatthew G. Knepley } 1102f3b08a26SMatthew G. Knepley for (i = n-2; i > -1; --i) { 11039566063dSJacob Faibussowitsch PetscCall(PCMGRecomputeLevelOperators_Internal(pc, i)); 1104f3b08a26SMatthew G. Knepley } 1105f3b08a26SMatthew G. Knepley } 1106f3b08a26SMatthew G. Knepley 11072134b1e4SBarry Smith if (needRestricts && pc->dm) { 1108caa4e7f2SJed Brown for (i=n-2; i>=0; i--) { 1109ccceb50cSJed Brown DM dmfine,dmcoarse; 1110caa4e7f2SJed Brown Mat Restrict,Inject; 1111caa4e7f2SJed Brown Vec rscale; 11129566063dSJacob Faibussowitsch PetscCall(KSPGetDM(mglevels[i+1]->smoothd,&dmfine)); 11139566063dSJacob Faibussowitsch PetscCall(KSPGetDM(mglevels[i]->smoothd,&dmcoarse)); 11149566063dSJacob Faibussowitsch PetscCall(PCMGGetRestriction(pc,i+1,&Restrict)); 11159566063dSJacob Faibussowitsch PetscCall(PCMGGetRScale(pc,i+1,&rscale)); 11169566063dSJacob Faibussowitsch PetscCall(PCMGGetInjection(pc,i+1,&Inject)); 11179566063dSJacob Faibussowitsch PetscCall(DMRestrict(dmfine,Restrict,rscale,Inject,dmcoarse)); 1118caa4e7f2SJed Brown } 1119caa4e7f2SJed Brown } 1120f3fbd535SBarry Smith 1121f3fbd535SBarry Smith if (!pc->setupcalled) { 1122f3fbd535SBarry Smith for (i=0; i<n; i++) { 11239566063dSJacob Faibussowitsch PetscCall(KSPSetFromOptions(mglevels[i]->smoothd)); 1124f3fbd535SBarry Smith } 1125f3fbd535SBarry Smith for (i=1; i<n; i++) { 1126f3fbd535SBarry Smith if (mglevels[i]->smoothu && (mglevels[i]->smoothu != mglevels[i]->smoothd)) { 11279566063dSJacob Faibussowitsch PetscCall(KSPSetFromOptions(mglevels[i]->smoothu)); 1128f3fbd535SBarry Smith } 112941b6fd38SMatthew G. Knepley if (mglevels[i]->cr) { 11309566063dSJacob Faibussowitsch PetscCall(KSPSetFromOptions(mglevels[i]->cr)); 113141b6fd38SMatthew G. Knepley } 1132f3fbd535SBarry Smith } 11333ad4599aSBarry Smith /* insure that if either interpolation or restriction is set the other other one is set */ 1134f3fbd535SBarry Smith for (i=1; i<n; i++) { 11359566063dSJacob Faibussowitsch PetscCall(PCMGGetInterpolation(pc,i,NULL)); 11369566063dSJacob Faibussowitsch PetscCall(PCMGGetRestriction(pc,i,NULL)); 1137f3fbd535SBarry Smith } 1138f3fbd535SBarry Smith for (i=0; i<n-1; i++) { 1139f3fbd535SBarry Smith if (!mglevels[i]->b) { 1140f3fbd535SBarry Smith Vec *vec; 11419566063dSJacob Faibussowitsch PetscCall(KSPCreateVecs(mglevels[i]->smoothd,1,&vec,0,NULL)); 11429566063dSJacob Faibussowitsch PetscCall(PCMGSetRhs(pc,i,*vec)); 11439566063dSJacob Faibussowitsch PetscCall(VecDestroy(vec)); 11449566063dSJacob Faibussowitsch PetscCall(PetscFree(vec)); 1145f3fbd535SBarry Smith } 1146f3fbd535SBarry Smith if (!mglevels[i]->r && i) { 11479566063dSJacob Faibussowitsch PetscCall(VecDuplicate(mglevels[i]->b,&tvec)); 11489566063dSJacob Faibussowitsch PetscCall(PCMGSetR(pc,i,tvec)); 11499566063dSJacob Faibussowitsch PetscCall(VecDestroy(&tvec)); 1150f3fbd535SBarry Smith } 1151f3fbd535SBarry Smith if (!mglevels[i]->x) { 11529566063dSJacob Faibussowitsch PetscCall(VecDuplicate(mglevels[i]->b,&tvec)); 11539566063dSJacob Faibussowitsch PetscCall(PCMGSetX(pc,i,tvec)); 11549566063dSJacob Faibussowitsch PetscCall(VecDestroy(&tvec)); 1155f3fbd535SBarry Smith } 115641b6fd38SMatthew G. Knepley if (doCR) { 11579566063dSJacob Faibussowitsch PetscCall(VecDuplicate(mglevels[i]->b,&mglevels[i]->crx)); 11589566063dSJacob Faibussowitsch PetscCall(VecDuplicate(mglevels[i]->b,&mglevels[i]->crb)); 11599566063dSJacob Faibussowitsch PetscCall(VecZeroEntries(mglevels[i]->crb)); 116041b6fd38SMatthew G. Knepley } 1161f3fbd535SBarry Smith } 1162f3fbd535SBarry Smith if (n != 1 && !mglevels[n-1]->r) { 1163f3fbd535SBarry Smith /* PCMGSetR() on the finest level if user did not supply it */ 1164f3fbd535SBarry Smith Vec *vec; 11659566063dSJacob Faibussowitsch PetscCall(KSPCreateVecs(mglevels[n-1]->smoothd,1,&vec,0,NULL)); 11669566063dSJacob Faibussowitsch PetscCall(PCMGSetR(pc,n-1,*vec)); 11679566063dSJacob Faibussowitsch PetscCall(VecDestroy(vec)); 11689566063dSJacob Faibussowitsch PetscCall(PetscFree(vec)); 1169f3fbd535SBarry Smith } 117041b6fd38SMatthew G. Knepley if (doCR) { 11719566063dSJacob Faibussowitsch PetscCall(VecDuplicate(mglevels[n-1]->r, &mglevels[n-1]->crx)); 11729566063dSJacob Faibussowitsch PetscCall(VecDuplicate(mglevels[n-1]->r, &mglevels[n-1]->crb)); 11739566063dSJacob Faibussowitsch PetscCall(VecZeroEntries(mglevels[n-1]->crb)); 117441b6fd38SMatthew G. Knepley } 1175f3fbd535SBarry Smith } 1176f3fbd535SBarry Smith 117798e04984SBarry Smith if (pc->dm) { 117898e04984SBarry Smith /* need to tell all the coarser levels to rebuild the matrix using the DM for that level */ 117998e04984SBarry Smith for (i=0; i<n-1; i++) { 118098e04984SBarry Smith if (mglevels[i]->smoothd->setupstage != KSP_SETUP_NEW) mglevels[i]->smoothd->setupstage = KSP_SETUP_NEWMATRIX; 118198e04984SBarry Smith } 118298e04984SBarry Smith } 118308549ed4SJed Brown // We got here (PCSetUp_MG) because the matrix has changed, which means the smoother needs to be set up again (e.g., 118408549ed4SJed Brown // new diagonal for Jacobi). Setting it here allows it to be logged under PCSetUp rather than deep inside a PCApply. 118508549ed4SJed Brown if (mglevels[n-1]->smoothd->setupstage != KSP_SETUP_NEW) mglevels[n-1]->smoothd->setupstage = KSP_SETUP_NEWMATRIX; 1186f3fbd535SBarry Smith 1187f3fbd535SBarry Smith for (i=1; i<n; i++) { 11882a21e185SBarry Smith if (mglevels[i]->smoothu == mglevels[i]->smoothd || mg->am == PC_MG_FULL || mg->am == PC_MG_KASKADE || mg->cyclesperpcapply > 1) { 1189f3fbd535SBarry Smith /* if doing only down then initial guess is zero */ 11909566063dSJacob Faibussowitsch PetscCall(KSPSetInitialGuessNonzero(mglevels[i]->smoothd,PETSC_TRUE)); 1191f3fbd535SBarry Smith } 11929566063dSJacob Faibussowitsch if (mglevels[i]->cr) PetscCall(KSPSetInitialGuessNonzero(mglevels[i]->cr,PETSC_TRUE)); 11939566063dSJacob Faibussowitsch if (mglevels[i]->eventsmoothsetup) PetscCall(PetscLogEventBegin(mglevels[i]->eventsmoothsetup,0,0,0,0)); 11949566063dSJacob Faibussowitsch PetscCall(KSPSetUp(mglevels[i]->smoothd)); 1195c0decd05SBarry Smith if (mglevels[i]->smoothd->reason == KSP_DIVERGED_PC_FAILED) { 1196899639b0SHong Zhang pc->failedreason = PC_SUBPC_ERROR; 1197899639b0SHong Zhang } 11989566063dSJacob Faibussowitsch if (mglevels[i]->eventsmoothsetup) PetscCall(PetscLogEventEnd(mglevels[i]->eventsmoothsetup,0,0,0,0)); 1199d42688cbSBarry Smith if (!mglevels[i]->residual) { 1200d42688cbSBarry Smith Mat mat; 12019566063dSJacob Faibussowitsch PetscCall(KSPGetOperators(mglevels[i]->smoothd,&mat,NULL)); 12029566063dSJacob Faibussowitsch PetscCall(PCMGSetResidual(pc,i,PCMGResidualDefault,mat)); 1203d42688cbSBarry Smith } 1204fcb023d4SJed Brown if (!mglevels[i]->residualtranspose) { 1205fcb023d4SJed Brown Mat mat; 12069566063dSJacob Faibussowitsch PetscCall(KSPGetOperators(mglevels[i]->smoothd,&mat,NULL)); 12079566063dSJacob Faibussowitsch PetscCall(PCMGSetResidualTranspose(pc,i,PCMGResidualTransposeDefault,mat)); 1208fcb023d4SJed Brown } 1209f3fbd535SBarry Smith } 1210f3fbd535SBarry Smith for (i=1; i<n; i++) { 1211f3fbd535SBarry Smith if (mglevels[i]->smoothu && mglevels[i]->smoothu != mglevels[i]->smoothd) { 1212f3fbd535SBarry Smith Mat downmat,downpmat; 1213f3fbd535SBarry Smith 1214f3fbd535SBarry Smith /* check if operators have been set for up, if not use down operators to set them */ 12159566063dSJacob Faibussowitsch PetscCall(KSPGetOperatorsSet(mglevels[i]->smoothu,&opsset,NULL)); 1216f3fbd535SBarry Smith if (!opsset) { 12179566063dSJacob Faibussowitsch PetscCall(KSPGetOperators(mglevels[i]->smoothd,&downmat,&downpmat)); 12189566063dSJacob Faibussowitsch PetscCall(KSPSetOperators(mglevels[i]->smoothu,downmat,downpmat)); 1219f3fbd535SBarry Smith } 1220f3fbd535SBarry Smith 12219566063dSJacob Faibussowitsch PetscCall(KSPSetInitialGuessNonzero(mglevels[i]->smoothu,PETSC_TRUE)); 12229566063dSJacob Faibussowitsch if (mglevels[i]->eventsmoothsetup) PetscCall(PetscLogEventBegin(mglevels[i]->eventsmoothsetup,0,0,0,0)); 12239566063dSJacob Faibussowitsch PetscCall(KSPSetUp(mglevels[i]->smoothu)); 1224c0decd05SBarry Smith if (mglevels[i]->smoothu->reason == KSP_DIVERGED_PC_FAILED) { 1225899639b0SHong Zhang pc->failedreason = PC_SUBPC_ERROR; 1226899639b0SHong Zhang } 12279566063dSJacob Faibussowitsch if (mglevels[i]->eventsmoothsetup) PetscCall(PetscLogEventEnd(mglevels[i]->eventsmoothsetup,0,0,0,0)); 1228f3fbd535SBarry Smith } 122941b6fd38SMatthew G. Knepley if (mglevels[i]->cr) { 123041b6fd38SMatthew G. Knepley Mat downmat,downpmat; 123141b6fd38SMatthew G. Knepley 123241b6fd38SMatthew G. Knepley /* check if operators have been set for up, if not use down operators to set them */ 12339566063dSJacob Faibussowitsch PetscCall(KSPGetOperatorsSet(mglevels[i]->cr,&opsset,NULL)); 123441b6fd38SMatthew G. Knepley if (!opsset) { 12359566063dSJacob Faibussowitsch PetscCall(KSPGetOperators(mglevels[i]->smoothd,&downmat,&downpmat)); 12369566063dSJacob Faibussowitsch PetscCall(KSPSetOperators(mglevels[i]->cr,downmat,downpmat)); 123741b6fd38SMatthew G. Knepley } 123841b6fd38SMatthew G. Knepley 12399566063dSJacob Faibussowitsch PetscCall(KSPSetInitialGuessNonzero(mglevels[i]->cr,PETSC_TRUE)); 12409566063dSJacob Faibussowitsch if (mglevels[i]->eventsmoothsetup) PetscCall(PetscLogEventBegin(mglevels[i]->eventsmoothsetup,0,0,0,0)); 12419566063dSJacob Faibussowitsch PetscCall(KSPSetUp(mglevels[i]->cr)); 124241b6fd38SMatthew G. Knepley if (mglevels[i]->cr->reason == KSP_DIVERGED_PC_FAILED) { 124341b6fd38SMatthew G. Knepley pc->failedreason = PC_SUBPC_ERROR; 124441b6fd38SMatthew G. Knepley } 12459566063dSJacob Faibussowitsch if (mglevels[i]->eventsmoothsetup) PetscCall(PetscLogEventEnd(mglevels[i]->eventsmoothsetup,0,0,0,0)); 124641b6fd38SMatthew G. Knepley } 1247f3fbd535SBarry Smith } 1248f3fbd535SBarry Smith 12499566063dSJacob Faibussowitsch if (mglevels[0]->eventsmoothsetup) PetscCall(PetscLogEventBegin(mglevels[0]->eventsmoothsetup,0,0,0,0)); 12509566063dSJacob Faibussowitsch PetscCall(KSPSetUp(mglevels[0]->smoothd)); 1251c0decd05SBarry Smith if (mglevels[0]->smoothd->reason == KSP_DIVERGED_PC_FAILED) { 1252899639b0SHong Zhang pc->failedreason = PC_SUBPC_ERROR; 1253899639b0SHong Zhang } 12549566063dSJacob Faibussowitsch if (mglevels[0]->eventsmoothsetup) PetscCall(PetscLogEventEnd(mglevels[0]->eventsmoothsetup,0,0,0,0)); 1255f3fbd535SBarry Smith 1256f3fbd535SBarry Smith /* 1257f3fbd535SBarry Smith Dump the interpolation/restriction matrices plus the 1258e3c5b3baSBarry Smith Jacobian/stiffness on each level. This allows MATLAB users to 1259f3fbd535SBarry Smith easily check if the Galerkin condition A_c = R A_f R^T is satisfied. 1260f3fbd535SBarry Smith 1261f3fbd535SBarry Smith Only support one or the other at the same time. 1262f3fbd535SBarry Smith */ 1263f3fbd535SBarry Smith #if defined(PETSC_USE_SOCKET_VIEWER) 12649566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(((PetscObject)pc)->options,((PetscObject)pc)->prefix,"-pc_mg_dump_matlab",&dump,NULL)); 1265ce94432eSBarry Smith if (dump) viewer = PETSC_VIEWER_SOCKET_(PetscObjectComm((PetscObject)pc)); 1266f3fbd535SBarry Smith dump = PETSC_FALSE; 1267f3fbd535SBarry Smith #endif 12689566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(((PetscObject)pc)->options,((PetscObject)pc)->prefix,"-pc_mg_dump_binary",&dump,NULL)); 1269ce94432eSBarry Smith if (dump) viewer = PETSC_VIEWER_BINARY_(PetscObjectComm((PetscObject)pc)); 1270f3fbd535SBarry Smith 1271f3fbd535SBarry Smith if (viewer) { 1272f3fbd535SBarry Smith for (i=1; i<n; i++) { 12739566063dSJacob Faibussowitsch PetscCall(MatView(mglevels[i]->restrct,viewer)); 1274f3fbd535SBarry Smith } 1275f3fbd535SBarry Smith for (i=0; i<n; i++) { 12769566063dSJacob Faibussowitsch PetscCall(KSPGetPC(mglevels[i]->smoothd,&pc)); 12779566063dSJacob Faibussowitsch PetscCall(MatView(pc->mat,viewer)); 1278f3fbd535SBarry Smith } 1279f3fbd535SBarry Smith } 1280f3fbd535SBarry Smith PetscFunctionReturn(0); 1281f3fbd535SBarry Smith } 1282f3fbd535SBarry Smith 1283f3fbd535SBarry Smith /* -------------------------------------------------------------------------------------*/ 1284f3fbd535SBarry Smith 128597d33e41SMatthew G. Knepley PetscErrorCode PCMGGetLevels_MG(PC pc, PetscInt *levels) 128697d33e41SMatthew G. Knepley { 128797d33e41SMatthew G. Knepley PC_MG *mg = (PC_MG *) pc->data; 128897d33e41SMatthew G. Knepley 128997d33e41SMatthew G. Knepley PetscFunctionBegin; 129097d33e41SMatthew G. Knepley *levels = mg->nlevels; 129197d33e41SMatthew G. Knepley PetscFunctionReturn(0); 129297d33e41SMatthew G. Knepley } 129397d33e41SMatthew G. Knepley 12944b9ad928SBarry Smith /*@ 129597177400SBarry Smith PCMGGetLevels - Gets the number of levels to use with MG. 12964b9ad928SBarry Smith 12974b9ad928SBarry Smith Not Collective 12984b9ad928SBarry Smith 12994b9ad928SBarry Smith Input Parameter: 13004b9ad928SBarry Smith . pc - the preconditioner context 13014b9ad928SBarry Smith 13024b9ad928SBarry Smith Output parameter: 13034b9ad928SBarry Smith . levels - the number of levels 13044b9ad928SBarry Smith 13054b9ad928SBarry Smith Level: advanced 13064b9ad928SBarry Smith 1307db781477SPatrick Sanan .seealso: `PCMGSetLevels()` 13084b9ad928SBarry Smith @*/ 13097087cfbeSBarry Smith PetscErrorCode PCMGGetLevels(PC pc,PetscInt *levels) 13104b9ad928SBarry Smith { 13114b9ad928SBarry Smith PetscFunctionBegin; 13120700a824SBarry Smith PetscValidHeaderSpecific(pc,PC_CLASSID,1); 13134482741eSBarry Smith PetscValidIntPointer(levels,2); 131497d33e41SMatthew G. Knepley *levels = 0; 1315cac4c232SBarry Smith PetscTryMethod(pc,"PCMGGetLevels_C",(PC,PetscInt*),(pc,levels)); 13164b9ad928SBarry Smith PetscFunctionReturn(0); 13174b9ad928SBarry Smith } 13184b9ad928SBarry Smith 13194b9ad928SBarry Smith /*@ 1320e7d4b4cbSMark Adams PCMGGetGridComplexity - compute operator and grid complexity of MG hierarchy 1321e7d4b4cbSMark Adams 1322e7d4b4cbSMark Adams Input Parameter: 1323e7d4b4cbSMark Adams . pc - the preconditioner context 1324e7d4b4cbSMark Adams 132590db8557SMark Adams Output Parameters: 132690db8557SMark Adams + gc - grid complexity = sum_i(n_i) / n_0 132790db8557SMark Adams - oc - operator complexity = sum_i(nnz_i) / nnz_0 1328e7d4b4cbSMark Adams 1329e7d4b4cbSMark Adams Level: advanced 1330e7d4b4cbSMark Adams 1331db781477SPatrick Sanan .seealso: `PCMGGetLevels()` 1332e7d4b4cbSMark Adams @*/ 1333e7d4b4cbSMark Adams PetscErrorCode PCMGGetGridComplexity(PC pc, PetscReal *gc, PetscReal *oc) 1334e7d4b4cbSMark Adams { 1335e7d4b4cbSMark Adams PC_MG *mg = (PC_MG*)pc->data; 1336e7d4b4cbSMark Adams PC_MG_Levels **mglevels = mg->levels; 1337e7d4b4cbSMark Adams PetscInt lev,N; 1338e7d4b4cbSMark Adams PetscLogDouble nnz0 = 0, sgc = 0, soc = 0, n0 = 0; 1339e7d4b4cbSMark Adams MatInfo info; 1340e7d4b4cbSMark Adams 1341e7d4b4cbSMark Adams PetscFunctionBegin; 134290db8557SMark Adams PetscValidHeaderSpecific(pc,PC_CLASSID,1); 134390db8557SMark Adams if (gc) PetscValidRealPointer(gc,2); 134490db8557SMark Adams if (oc) PetscValidRealPointer(oc,3); 1345e7d4b4cbSMark Adams if (!pc->setupcalled) { 134690db8557SMark Adams if (gc) *gc = 0; 134790db8557SMark Adams if (oc) *oc = 0; 1348e7d4b4cbSMark Adams PetscFunctionReturn(0); 1349e7d4b4cbSMark Adams } 1350e7d4b4cbSMark Adams PetscCheck(mg->nlevels > 0,PETSC_COMM_SELF,PETSC_ERR_PLIB,"MG has no levels"); 1351e7d4b4cbSMark Adams for (lev=0; lev<mg->nlevels; lev++) { 1352e7d4b4cbSMark Adams Mat dB; 13539566063dSJacob Faibussowitsch PetscCall(KSPGetOperators(mglevels[lev]->smoothd,NULL,&dB)); 13549566063dSJacob Faibussowitsch PetscCall(MatGetInfo(dB,MAT_GLOBAL_SUM,&info)); /* global reduction */ 13559566063dSJacob Faibussowitsch PetscCall(MatGetSize(dB,&N,NULL)); 1356e7d4b4cbSMark Adams sgc += N; 1357e7d4b4cbSMark Adams soc += info.nz_used; 1358e7d4b4cbSMark Adams if (lev==mg->nlevels-1) {nnz0 = info.nz_used; n0 = N;} 1359e7d4b4cbSMark Adams } 136090db8557SMark Adams if (n0 > 0 && gc) *gc = (PetscReal)(sgc/n0); 1361e7d4b4cbSMark Adams else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Number for grid points on finest level is not available"); 136290db8557SMark Adams if (nnz0 > 0 && oc) *oc = (PetscReal)(soc/nnz0); 1363e7d4b4cbSMark Adams PetscFunctionReturn(0); 1364e7d4b4cbSMark Adams } 1365e7d4b4cbSMark Adams 1366e7d4b4cbSMark Adams /*@ 136797177400SBarry Smith PCMGSetType - Determines the form of multigrid to use: 13684b9ad928SBarry Smith multiplicative, additive, full, or the Kaskade algorithm. 13694b9ad928SBarry Smith 1370ad4df100SBarry Smith Logically Collective on PC 13714b9ad928SBarry Smith 13724b9ad928SBarry Smith Input Parameters: 13734b9ad928SBarry Smith + pc - the preconditioner context 13749dcbbd2bSBarry Smith - form - multigrid form, one of PC_MG_MULTIPLICATIVE, PC_MG_ADDITIVE, 13759dcbbd2bSBarry Smith PC_MG_FULL, PC_MG_KASKADE 13764b9ad928SBarry Smith 13774b9ad928SBarry Smith Options Database Key: 13784b9ad928SBarry Smith . -pc_mg_type <form> - Sets <form>, one of multiplicative, 13794b9ad928SBarry Smith additive, full, kaskade 13804b9ad928SBarry Smith 13814b9ad928SBarry Smith Level: advanced 13824b9ad928SBarry Smith 1383db781477SPatrick Sanan .seealso: `PCMGSetLevels()` 13844b9ad928SBarry Smith @*/ 13857087cfbeSBarry Smith PetscErrorCode PCMGSetType(PC pc,PCMGType form) 13864b9ad928SBarry Smith { 1387f3fbd535SBarry Smith PC_MG *mg = (PC_MG*)pc->data; 13884b9ad928SBarry Smith 13894b9ad928SBarry Smith PetscFunctionBegin; 13900700a824SBarry Smith PetscValidHeaderSpecific(pc,PC_CLASSID,1); 1391c5eb9154SBarry Smith PetscValidLogicalCollectiveEnum(pc,form,2); 139231567311SBarry Smith mg->am = form; 13939dcbbd2bSBarry Smith if (form == PC_MG_MULTIPLICATIVE) pc->ops->applyrichardson = PCApplyRichardson_MG; 1394c60c7ad4SBarry Smith else pc->ops->applyrichardson = NULL; 1395c60c7ad4SBarry Smith PetscFunctionReturn(0); 1396c60c7ad4SBarry Smith } 1397c60c7ad4SBarry Smith 1398c60c7ad4SBarry Smith /*@ 1399c60c7ad4SBarry Smith PCMGGetType - Determines the form of multigrid to use: 1400c60c7ad4SBarry Smith multiplicative, additive, full, or the Kaskade algorithm. 1401c60c7ad4SBarry Smith 1402c60c7ad4SBarry Smith Logically Collective on PC 1403c60c7ad4SBarry Smith 1404c60c7ad4SBarry Smith Input Parameter: 1405c60c7ad4SBarry Smith . pc - the preconditioner context 1406c60c7ad4SBarry Smith 1407c60c7ad4SBarry Smith Output Parameter: 1408c60c7ad4SBarry Smith . type - one of PC_MG_MULTIPLICATIVE, PC_MG_ADDITIVE,PC_MG_FULL, PC_MG_KASKADE 1409c60c7ad4SBarry Smith 1410c60c7ad4SBarry Smith Level: advanced 1411c60c7ad4SBarry Smith 1412db781477SPatrick Sanan .seealso: `PCMGSetLevels()` 1413c60c7ad4SBarry Smith @*/ 1414c60c7ad4SBarry Smith PetscErrorCode PCMGGetType(PC pc,PCMGType *type) 1415c60c7ad4SBarry Smith { 1416c60c7ad4SBarry Smith PC_MG *mg = (PC_MG*)pc->data; 1417c60c7ad4SBarry Smith 1418c60c7ad4SBarry Smith PetscFunctionBegin; 1419c60c7ad4SBarry Smith PetscValidHeaderSpecific(pc,PC_CLASSID,1); 1420c60c7ad4SBarry Smith *type = mg->am; 14214b9ad928SBarry Smith PetscFunctionReturn(0); 14224b9ad928SBarry Smith } 14234b9ad928SBarry Smith 14244b9ad928SBarry Smith /*@ 14250d353602SBarry Smith PCMGSetCycleType - Sets the type cycles to use. Use PCMGSetCycleTypeOnLevel() for more 14264b9ad928SBarry Smith complicated cycling. 14274b9ad928SBarry Smith 1428ad4df100SBarry Smith Logically Collective on PC 14294b9ad928SBarry Smith 14304b9ad928SBarry Smith Input Parameters: 1431c2be2410SBarry Smith + pc - the multigrid context 1432c1cbb1deSBarry Smith - n - either PC_MG_CYCLE_V or PC_MG_CYCLE_W 14334b9ad928SBarry Smith 14344b9ad928SBarry Smith Options Database Key: 1435c1cbb1deSBarry Smith . -pc_mg_cycle_type <v,w> - provide the cycle desired 14364b9ad928SBarry Smith 14374b9ad928SBarry Smith Level: advanced 14384b9ad928SBarry Smith 1439db781477SPatrick Sanan .seealso: `PCMGSetCycleTypeOnLevel()` 14404b9ad928SBarry Smith @*/ 14417087cfbeSBarry Smith PetscErrorCode PCMGSetCycleType(PC pc,PCMGCycleType n) 14424b9ad928SBarry Smith { 1443f3fbd535SBarry Smith PC_MG *mg = (PC_MG*)pc->data; 1444f3fbd535SBarry Smith PC_MG_Levels **mglevels = mg->levels; 144579416396SBarry Smith PetscInt i,levels; 14464b9ad928SBarry Smith 14474b9ad928SBarry Smith PetscFunctionBegin; 14480700a824SBarry Smith PetscValidHeaderSpecific(pc,PC_CLASSID,1); 144969fbec6eSBarry Smith PetscValidLogicalCollectiveEnum(pc,n,2); 145028b400f6SJacob Faibussowitsch PetscCheck(mglevels,PetscObjectComm((PetscObject)pc),PETSC_ERR_ORDER,"Must set MG levels with PCMGSetLevels() before calling"); 1451f3fbd535SBarry Smith levels = mglevels[0]->levels; 14522fa5cd67SKarl Rupp for (i=0; i<levels; i++) mglevels[i]->cycles = n; 14534b9ad928SBarry Smith PetscFunctionReturn(0); 14544b9ad928SBarry Smith } 14554b9ad928SBarry Smith 14568cc2d5dfSBarry Smith /*@ 14578cc2d5dfSBarry Smith PCMGMultiplicativeSetCycles - Sets the number of cycles to use for each preconditioner step 14588cc2d5dfSBarry Smith of multigrid when PCMGType of PC_MG_MULTIPLICATIVE is used 14598cc2d5dfSBarry Smith 1460ad4df100SBarry Smith Logically Collective on PC 14618cc2d5dfSBarry Smith 14628cc2d5dfSBarry Smith Input Parameters: 14638cc2d5dfSBarry Smith + pc - the multigrid context 14648cc2d5dfSBarry Smith - n - number of cycles (default is 1) 14658cc2d5dfSBarry Smith 14668cc2d5dfSBarry Smith Options Database Key: 1467147403d9SBarry Smith . -pc_mg_multiplicative_cycles n - set the number of cycles 14688cc2d5dfSBarry Smith 14698cc2d5dfSBarry Smith Level: advanced 14708cc2d5dfSBarry Smith 147195452b02SPatrick Sanan Notes: 147295452b02SPatrick Sanan This is not associated with setting a v or w cycle, that is set with PCMGSetCycleType() 14738cc2d5dfSBarry Smith 1474db781477SPatrick Sanan .seealso: `PCMGSetCycleTypeOnLevel()`, `PCMGSetCycleType()` 14758cc2d5dfSBarry Smith @*/ 14767087cfbeSBarry Smith PetscErrorCode PCMGMultiplicativeSetCycles(PC pc,PetscInt n) 14778cc2d5dfSBarry Smith { 1478f3fbd535SBarry Smith PC_MG *mg = (PC_MG*)pc->data; 14798cc2d5dfSBarry Smith 14808cc2d5dfSBarry Smith PetscFunctionBegin; 14810700a824SBarry Smith PetscValidHeaderSpecific(pc,PC_CLASSID,1); 1482c5eb9154SBarry Smith PetscValidLogicalCollectiveInt(pc,n,2); 14832a21e185SBarry Smith mg->cyclesperpcapply = n; 14848cc2d5dfSBarry Smith PetscFunctionReturn(0); 14858cc2d5dfSBarry Smith } 14868cc2d5dfSBarry Smith 14872134b1e4SBarry Smith PetscErrorCode PCMGSetGalerkin_MG(PC pc,PCMGGalerkinType use) 1488fb15c04eSBarry Smith { 1489fb15c04eSBarry Smith PC_MG *mg = (PC_MG*)pc->data; 1490fb15c04eSBarry Smith 1491fb15c04eSBarry Smith PetscFunctionBegin; 14922134b1e4SBarry Smith mg->galerkin = use; 1493fb15c04eSBarry Smith PetscFunctionReturn(0); 1494fb15c04eSBarry Smith } 1495fb15c04eSBarry Smith 1496c2be2410SBarry Smith /*@ 149797177400SBarry Smith PCMGSetGalerkin - Causes the coarser grid matrices to be computed from the 149882b87d87SMatthew G. Knepley finest grid via the Galerkin process: A_i-1 = r_i * A_i * p_i 1499c2be2410SBarry Smith 1500ad4df100SBarry Smith Logically Collective on PC 1501c2be2410SBarry Smith 1502c2be2410SBarry Smith Input Parameters: 1503c91913d3SJed Brown + pc - the multigrid context 15042134b1e4SBarry Smith - use - one of PC_MG_GALERKIN_BOTH,PC_MG_GALERKIN_PMAT,PC_MG_GALERKIN_MAT, or PC_MG_GALERKIN_NONE 1505c2be2410SBarry Smith 1506c2be2410SBarry Smith Options Database Key: 1507147403d9SBarry Smith . -pc_mg_galerkin <both,pmat,mat,none> - set the matrices to form via the Galerkin process 1508c2be2410SBarry Smith 1509c2be2410SBarry Smith Level: intermediate 1510c2be2410SBarry Smith 151195452b02SPatrick Sanan Notes: 151295452b02SPatrick Sanan Some codes that use PCMG such as PCGAMG use Galerkin internally while constructing the hierarchy and thus do not 15131c1aac46SBarry Smith use the PCMG construction of the coarser grids. 15141c1aac46SBarry Smith 1515db781477SPatrick Sanan .seealso: `PCMGGetGalerkin()`, `PCMGGalerkinType` 15163fc8bf9cSBarry Smith 1517c2be2410SBarry Smith @*/ 15182134b1e4SBarry Smith PetscErrorCode PCMGSetGalerkin(PC pc,PCMGGalerkinType use) 1519c2be2410SBarry Smith { 1520c2be2410SBarry Smith PetscFunctionBegin; 15210700a824SBarry Smith PetscValidHeaderSpecific(pc,PC_CLASSID,1); 1522cac4c232SBarry Smith PetscTryMethod(pc,"PCMGSetGalerkin_C",(PC,PCMGGalerkinType),(pc,use)); 1523c2be2410SBarry Smith PetscFunctionReturn(0); 1524c2be2410SBarry Smith } 1525c2be2410SBarry Smith 15263fc8bf9cSBarry Smith /*@ 15273fc8bf9cSBarry Smith PCMGGetGalerkin - Checks if Galerkin multigrid is being used, i.e. 152882b87d87SMatthew G. Knepley A_i-1 = r_i * A_i * p_i 15293fc8bf9cSBarry Smith 15303fc8bf9cSBarry Smith Not Collective 15313fc8bf9cSBarry Smith 15323fc8bf9cSBarry Smith Input Parameter: 15333fc8bf9cSBarry Smith . pc - the multigrid context 15343fc8bf9cSBarry Smith 15353fc8bf9cSBarry Smith Output Parameter: 15362134b1e4SBarry 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 15373fc8bf9cSBarry Smith 15383fc8bf9cSBarry Smith Level: intermediate 15393fc8bf9cSBarry Smith 1540db781477SPatrick Sanan .seealso: `PCMGSetGalerkin()`, `PCMGGalerkinType` 15413fc8bf9cSBarry Smith 15423fc8bf9cSBarry Smith @*/ 15432134b1e4SBarry Smith PetscErrorCode PCMGGetGalerkin(PC pc,PCMGGalerkinType *galerkin) 15443fc8bf9cSBarry Smith { 1545f3fbd535SBarry Smith PC_MG *mg = (PC_MG*)pc->data; 15463fc8bf9cSBarry Smith 15473fc8bf9cSBarry Smith PetscFunctionBegin; 15480700a824SBarry Smith PetscValidHeaderSpecific(pc,PC_CLASSID,1); 15492134b1e4SBarry Smith *galerkin = mg->galerkin; 15503fc8bf9cSBarry Smith PetscFunctionReturn(0); 15513fc8bf9cSBarry Smith } 15523fc8bf9cSBarry Smith 1553f3b08a26SMatthew G. Knepley PetscErrorCode PCMGSetAdaptInterpolation_MG(PC pc, PetscBool adapt) 1554f3b08a26SMatthew G. Knepley { 1555f3b08a26SMatthew G. Knepley PC_MG *mg = (PC_MG *) pc->data; 1556f3b08a26SMatthew G. Knepley 1557f3b08a26SMatthew G. Knepley PetscFunctionBegin; 1558f3b08a26SMatthew G. Knepley mg->adaptInterpolation = adapt; 1559f3b08a26SMatthew G. Knepley PetscFunctionReturn(0); 1560f3b08a26SMatthew G. Knepley } 1561f3b08a26SMatthew G. Knepley 1562f3b08a26SMatthew G. Knepley PetscErrorCode PCMGGetAdaptInterpolation_MG(PC pc, PetscBool *adapt) 1563f3b08a26SMatthew G. Knepley { 1564f3b08a26SMatthew G. Knepley PC_MG *mg = (PC_MG *) pc->data; 1565f3b08a26SMatthew G. Knepley 1566f3b08a26SMatthew G. Knepley PetscFunctionBegin; 1567f3b08a26SMatthew G. Knepley *adapt = mg->adaptInterpolation; 1568f3b08a26SMatthew G. Knepley PetscFunctionReturn(0); 1569f3b08a26SMatthew G. Knepley } 1570f3b08a26SMatthew G. Knepley 15712b3cbbdaSStefano Zampini PetscErrorCode PCMGSetAdaptCoarseSpaceType_MG(PC pc, PCMGCoarseSpaceType ctype) 15722b3cbbdaSStefano Zampini { 15732b3cbbdaSStefano Zampini PC_MG *mg = (PC_MG *) pc->data; 15742b3cbbdaSStefano Zampini 15752b3cbbdaSStefano Zampini PetscFunctionBegin; 15762b3cbbdaSStefano Zampini mg->adaptInterpolation = ctype != PCMG_ADAPT_NONE ? PETSC_TRUE : PETSC_FALSE; 15772b3cbbdaSStefano Zampini mg->coarseSpaceType = ctype; 15782b3cbbdaSStefano Zampini PetscFunctionReturn(0); 15792b3cbbdaSStefano Zampini } 15802b3cbbdaSStefano Zampini 15812b3cbbdaSStefano Zampini PetscErrorCode PCMGGetAdaptCoarseSpaceType_MG(PC pc, PCMGCoarseSpaceType *ctype) 15822b3cbbdaSStefano Zampini { 15832b3cbbdaSStefano Zampini PC_MG *mg = (PC_MG *) pc->data; 15842b3cbbdaSStefano Zampini 15852b3cbbdaSStefano Zampini PetscFunctionBegin; 15862b3cbbdaSStefano Zampini *ctype = mg->coarseSpaceType; 15872b3cbbdaSStefano Zampini PetscFunctionReturn(0); 15882b3cbbdaSStefano Zampini } 15892b3cbbdaSStefano Zampini 159041b6fd38SMatthew G. Knepley PetscErrorCode PCMGSetAdaptCR_MG(PC pc, PetscBool cr) 159141b6fd38SMatthew G. Knepley { 159241b6fd38SMatthew G. Knepley PC_MG *mg = (PC_MG *) pc->data; 159341b6fd38SMatthew G. Knepley 159441b6fd38SMatthew G. Knepley PetscFunctionBegin; 159541b6fd38SMatthew G. Knepley mg->compatibleRelaxation = cr; 159641b6fd38SMatthew G. Knepley PetscFunctionReturn(0); 159741b6fd38SMatthew G. Knepley } 159841b6fd38SMatthew G. Knepley 159941b6fd38SMatthew G. Knepley PetscErrorCode PCMGGetAdaptCR_MG(PC pc, PetscBool *cr) 160041b6fd38SMatthew G. Knepley { 160141b6fd38SMatthew G. Knepley PC_MG *mg = (PC_MG *) pc->data; 160241b6fd38SMatthew G. Knepley 160341b6fd38SMatthew G. Knepley PetscFunctionBegin; 160441b6fd38SMatthew G. Knepley *cr = mg->compatibleRelaxation; 160541b6fd38SMatthew G. Knepley PetscFunctionReturn(0); 160641b6fd38SMatthew G. Knepley } 160741b6fd38SMatthew G. Knepley 16082b3cbbdaSStefano Zampini /*@C 16092b3cbbdaSStefano Zampini PCMGSetAdaptCoarseSpaceType - Set the type of adaptive coarse space. 16102b3cbbdaSStefano Zampini 16112b3cbbdaSStefano Zampini Adapts or creates the interpolator based upon a vector space which should be accurately captured by the next coarser mesh, and thus accurately interpolated. 16122b3cbbdaSStefano Zampini 16132b3cbbdaSStefano Zampini Logically Collective on PC 16142b3cbbdaSStefano Zampini 16152b3cbbdaSStefano Zampini Input Parameters: 16162b3cbbdaSStefano Zampini + pc - the multigrid context 16172b3cbbdaSStefano Zampini - ctype - the type of coarse space 16182b3cbbdaSStefano Zampini 16192b3cbbdaSStefano Zampini Options Database Keys: 16202b3cbbdaSStefano Zampini + -pc_mg_adapt_interp_n <int> - The number of modes to use 16212b3cbbdaSStefano Zampini - -pc_mg_adapt_interp_coarse_space <type> - The type of coarse space: none, polynomial, harmonic, eigenvector, generalized_eigenvector, gdsw 16222b3cbbdaSStefano Zampini 16232b3cbbdaSStefano Zampini Level: intermediate 16242b3cbbdaSStefano Zampini 16252b3cbbdaSStefano Zampini .keywords: MG, set, Galerkin 16262b3cbbdaSStefano Zampini .seealso: `PCMGCoarseSpaceType`, `PCMGGetAdaptCoarseSpaceType()`, `PCMGSetGalerkin()` 16272b3cbbdaSStefano Zampini @*/ 16282b3cbbdaSStefano Zampini PetscErrorCode PCMGSetAdaptCoarseSpaceType(PC pc, PCMGCoarseSpaceType ctype) 16292b3cbbdaSStefano Zampini { 16302b3cbbdaSStefano Zampini PetscFunctionBegin; 16312b3cbbdaSStefano Zampini PetscValidHeaderSpecific(pc,PC_CLASSID,1); 16322b3cbbdaSStefano Zampini PetscValidLogicalCollectiveEnum(pc,ctype,2); 16332b3cbbdaSStefano Zampini PetscTryMethod(pc,"PCMGSetAdaptCoarseSpaceType_C",(PC,PCMGCoarseSpaceType),(pc,ctype)); 16342b3cbbdaSStefano Zampini PetscFunctionReturn(0); 16352b3cbbdaSStefano Zampini } 16362b3cbbdaSStefano Zampini 16372b3cbbdaSStefano Zampini /*@C 16382b3cbbdaSStefano Zampini PCMGGetAdaptCoarseSpaceType - Get the type of adaptive coarse space. 16392b3cbbdaSStefano Zampini 16402b3cbbdaSStefano Zampini Not Collective 16412b3cbbdaSStefano Zampini 16422b3cbbdaSStefano Zampini Input Parameter: 16432b3cbbdaSStefano Zampini . pc - the multigrid context 16442b3cbbdaSStefano Zampini 16452b3cbbdaSStefano Zampini Output Parameter: 16462b3cbbdaSStefano Zampini . ctype - the type of coarse space 16472b3cbbdaSStefano Zampini 16482b3cbbdaSStefano Zampini Level: intermediate 16492b3cbbdaSStefano Zampini 16502b3cbbdaSStefano Zampini .keywords: MG, Get, Galerkin 16512b3cbbdaSStefano Zampini .seealso: `PCMGCoarseSpaceType`, `PCMGSetAdaptCoarseSpaceType()`, `PCMGSetGalerkin()` 16522b3cbbdaSStefano Zampini @*/ 16532b3cbbdaSStefano Zampini PetscErrorCode PCMGGetAdaptCoarseSpaceType(PC pc, PCMGCoarseSpaceType *ctype) 16542b3cbbdaSStefano Zampini { 16552b3cbbdaSStefano Zampini PetscFunctionBegin; 16562b3cbbdaSStefano Zampini PetscValidHeaderSpecific(pc,PC_CLASSID,1); 16572b3cbbdaSStefano Zampini PetscValidPointer(ctype,2); 16582b3cbbdaSStefano Zampini PetscUseMethod(pc,"PCMGGetAdaptCoarseSpaceType_C",(PC,PCMGCoarseSpaceType*),(pc,ctype)); 16592b3cbbdaSStefano Zampini PetscFunctionReturn(0); 16602b3cbbdaSStefano Zampini } 16612b3cbbdaSStefano Zampini 16622b3cbbdaSStefano Zampini /* MATT: REMOVE? */ 1663f3b08a26SMatthew G. Knepley /*@ 1664f3b08a26SMatthew G. Knepley PCMGSetAdaptInterpolation - Adapt the interpolator based upon a vector space which should be accurately captured by the next coarser mesh, and thus accurately interpolated. 1665f3b08a26SMatthew G. Knepley 1666f3b08a26SMatthew G. Knepley Logically Collective on PC 1667f3b08a26SMatthew G. Knepley 1668f3b08a26SMatthew G. Knepley Input Parameters: 1669f3b08a26SMatthew G. Knepley + pc - the multigrid context 1670f3b08a26SMatthew G. Knepley - adapt - flag for adaptation of the interpolator 1671f3b08a26SMatthew G. Knepley 1672f3b08a26SMatthew G. Knepley Options Database Keys: 1673f3b08a26SMatthew G. Knepley + -pc_mg_adapt_interp - Turn on adaptation 1674f3b08a26SMatthew G. Knepley . -pc_mg_adapt_interp_n <int> - The number of modes to use, should be divisible by dimension 1675f3b08a26SMatthew G. Knepley - -pc_mg_adapt_interp_coarse_space <type> - The type of coarse space: polynomial, harmonic, eigenvector, generalized_eigenvector 1676f3b08a26SMatthew G. Knepley 1677f3b08a26SMatthew G. Knepley Level: intermediate 1678f3b08a26SMatthew G. Knepley 1679f3b08a26SMatthew G. Knepley .keywords: MG, set, Galerkin 1680db781477SPatrick Sanan .seealso: `PCMGGetAdaptInterpolation()`, `PCMGSetGalerkin()` 1681f3b08a26SMatthew G. Knepley @*/ 1682f3b08a26SMatthew G. Knepley PetscErrorCode PCMGSetAdaptInterpolation(PC pc, PetscBool adapt) 1683f3b08a26SMatthew G. Knepley { 1684f3b08a26SMatthew G. Knepley PetscFunctionBegin; 1685f3b08a26SMatthew G. Knepley PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 1686cac4c232SBarry Smith PetscTryMethod(pc,"PCMGSetAdaptInterpolation_C",(PC,PetscBool),(pc,adapt)); 1687f3b08a26SMatthew G. Knepley PetscFunctionReturn(0); 1688f3b08a26SMatthew G. Knepley } 1689f3b08a26SMatthew G. Knepley 1690f3b08a26SMatthew G. Knepley /*@ 1691f3b08a26SMatthew G. Knepley PCMGGetAdaptInterpolation - Get the flag to adapt the interpolator based upon a vector space which should be accurately captured by the next coarser mesh, and thus accurately interpolated. 1692f3b08a26SMatthew G. Knepley 1693f3b08a26SMatthew G. Knepley Not collective 1694f3b08a26SMatthew G. Knepley 1695f3b08a26SMatthew G. Knepley Input Parameter: 1696f3b08a26SMatthew G. Knepley . pc - the multigrid context 1697f3b08a26SMatthew G. Knepley 1698f3b08a26SMatthew G. Knepley Output Parameter: 1699f3b08a26SMatthew G. Knepley . adapt - flag for adaptation of the interpolator 1700f3b08a26SMatthew G. Knepley 1701f3b08a26SMatthew G. Knepley Level: intermediate 1702f3b08a26SMatthew G. Knepley 1703f3b08a26SMatthew G. Knepley .keywords: MG, set, Galerkin 1704db781477SPatrick Sanan .seealso: `PCMGSetAdaptInterpolation()`, `PCMGSetGalerkin()` 1705f3b08a26SMatthew G. Knepley @*/ 1706f3b08a26SMatthew G. Knepley PetscErrorCode PCMGGetAdaptInterpolation(PC pc, PetscBool *adapt) 1707f3b08a26SMatthew G. Knepley { 1708f3b08a26SMatthew G. Knepley PetscFunctionBegin; 1709f3b08a26SMatthew G. Knepley PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 1710dadcf809SJacob Faibussowitsch PetscValidBoolPointer(adapt, 2); 1711cac4c232SBarry Smith PetscUseMethod(pc,"PCMGGetAdaptInterpolation_C",(PC,PetscBool*),(pc,adapt)); 1712f3b08a26SMatthew G. Knepley PetscFunctionReturn(0); 1713f3b08a26SMatthew G. Knepley } 1714f3b08a26SMatthew G. Knepley 17154b9ad928SBarry Smith /*@ 171641b6fd38SMatthew G. Knepley PCMGSetAdaptCR - Monitor the coarse space quality using an auxiliary solve with compatible relaxation. 171741b6fd38SMatthew G. Knepley 171841b6fd38SMatthew G. Knepley Logically Collective on PC 171941b6fd38SMatthew G. Knepley 172041b6fd38SMatthew G. Knepley Input Parameters: 172141b6fd38SMatthew G. Knepley + pc - the multigrid context 172241b6fd38SMatthew G. Knepley - cr - flag for compatible relaxation 172341b6fd38SMatthew G. Knepley 172441b6fd38SMatthew G. Knepley Options Database Keys: 172541b6fd38SMatthew G. Knepley . -pc_mg_adapt_cr - Turn on compatible relaxation 172641b6fd38SMatthew G. Knepley 172741b6fd38SMatthew G. Knepley Level: intermediate 172841b6fd38SMatthew G. Knepley 172941b6fd38SMatthew G. Knepley .keywords: MG, set, Galerkin 1730db781477SPatrick Sanan .seealso: `PCMGGetAdaptCR()`, `PCMGSetAdaptInterpolation()`, `PCMGSetGalerkin()` 173141b6fd38SMatthew G. Knepley @*/ 173241b6fd38SMatthew G. Knepley PetscErrorCode PCMGSetAdaptCR(PC pc, PetscBool cr) 173341b6fd38SMatthew G. Knepley { 173441b6fd38SMatthew G. Knepley PetscFunctionBegin; 173541b6fd38SMatthew G. Knepley PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 1736cac4c232SBarry Smith PetscTryMethod(pc,"PCMGSetAdaptCR_C",(PC,PetscBool),(pc,cr)); 173741b6fd38SMatthew G. Knepley PetscFunctionReturn(0); 173841b6fd38SMatthew G. Knepley } 173941b6fd38SMatthew G. Knepley 174041b6fd38SMatthew G. Knepley /*@ 174141b6fd38SMatthew G. Knepley PCMGGetAdaptCR - Get the flag to monitor coarse space quality using an auxiliary solve with compatible relaxation. 174241b6fd38SMatthew G. Knepley 174341b6fd38SMatthew G. Knepley Not collective 174441b6fd38SMatthew G. Knepley 174541b6fd38SMatthew G. Knepley Input Parameter: 174641b6fd38SMatthew G. Knepley . pc - the multigrid context 174741b6fd38SMatthew G. Knepley 174841b6fd38SMatthew G. Knepley Output Parameter: 174941b6fd38SMatthew G. Knepley . cr - flag for compatible relaxaion 175041b6fd38SMatthew G. Knepley 175141b6fd38SMatthew G. Knepley Level: intermediate 175241b6fd38SMatthew G. Knepley 175341b6fd38SMatthew G. Knepley .keywords: MG, set, Galerkin 1754db781477SPatrick Sanan .seealso: `PCMGSetAdaptCR()`, `PCMGGetAdaptInterpolation()`, `PCMGSetGalerkin()` 175541b6fd38SMatthew G. Knepley @*/ 175641b6fd38SMatthew G. Knepley PetscErrorCode PCMGGetAdaptCR(PC pc, PetscBool *cr) 175741b6fd38SMatthew G. Knepley { 175841b6fd38SMatthew G. Knepley PetscFunctionBegin; 175941b6fd38SMatthew G. Knepley PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 1760dadcf809SJacob Faibussowitsch PetscValidBoolPointer(cr, 2); 1761cac4c232SBarry Smith PetscUseMethod(pc,"PCMGGetAdaptCR_C",(PC,PetscBool*),(pc,cr)); 176241b6fd38SMatthew G. Knepley PetscFunctionReturn(0); 176341b6fd38SMatthew G. Knepley } 176441b6fd38SMatthew G. Knepley 176541b6fd38SMatthew G. Knepley /*@ 176606792cafSBarry Smith PCMGSetNumberSmooth - Sets the number of pre and post-smoothing steps to use 1767710315b6SLawrence Mitchell on all levels. Use PCMGDistinctSmoothUp() to create separate up and down smoothers if you want different numbers of 1768710315b6SLawrence Mitchell pre- and post-smoothing steps. 176906792cafSBarry Smith 177006792cafSBarry Smith Logically Collective on PC 177106792cafSBarry Smith 177206792cafSBarry Smith Input Parameters: 177306792cafSBarry Smith + mg - the multigrid context 177406792cafSBarry Smith - n - the number of smoothing steps 177506792cafSBarry Smith 177606792cafSBarry Smith Options Database Key: 1777a2b725a8SWilliam Gropp . -mg_levels_ksp_max_it <n> - Sets number of pre and post-smoothing steps 177806792cafSBarry Smith 177906792cafSBarry Smith Level: advanced 178006792cafSBarry Smith 178195452b02SPatrick Sanan Notes: 178295452b02SPatrick Sanan this does not set a value on the coarsest grid, since we assume that 178306792cafSBarry Smith there is no separate smooth up on the coarsest grid. 178406792cafSBarry Smith 1785db781477SPatrick Sanan .seealso: `PCMGSetDistinctSmoothUp()` 178606792cafSBarry Smith @*/ 178706792cafSBarry Smith PetscErrorCode PCMGSetNumberSmooth(PC pc,PetscInt n) 178806792cafSBarry Smith { 178906792cafSBarry Smith PC_MG *mg = (PC_MG*)pc->data; 179006792cafSBarry Smith PC_MG_Levels **mglevels = mg->levels; 179106792cafSBarry Smith PetscInt i,levels; 179206792cafSBarry Smith 179306792cafSBarry Smith PetscFunctionBegin; 179406792cafSBarry Smith PetscValidHeaderSpecific(pc,PC_CLASSID,1); 179506792cafSBarry Smith PetscValidLogicalCollectiveInt(pc,n,2); 179628b400f6SJacob Faibussowitsch PetscCheck(mglevels,PetscObjectComm((PetscObject)pc),PETSC_ERR_ORDER,"Must set MG levels with PCMGSetLevels() before calling"); 179706792cafSBarry Smith levels = mglevels[0]->levels; 179806792cafSBarry Smith 179906792cafSBarry Smith for (i=1; i<levels; i++) { 18009566063dSJacob Faibussowitsch PetscCall(KSPSetTolerances(mglevels[i]->smoothu,PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT,n)); 18019566063dSJacob Faibussowitsch PetscCall(KSPSetTolerances(mglevels[i]->smoothd,PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT,n)); 180206792cafSBarry Smith mg->default_smoothu = n; 180306792cafSBarry Smith mg->default_smoothd = n; 180406792cafSBarry Smith } 180506792cafSBarry Smith PetscFunctionReturn(0); 180606792cafSBarry Smith } 180706792cafSBarry Smith 1808f442ab6aSBarry Smith /*@ 18098e5aa403SBarry Smith PCMGSetDistinctSmoothUp - sets the up (post) smoother to be a separate KSP from the down (pre) smoother on all levels 1810710315b6SLawrence Mitchell and adds the suffix _up to the options name 1811f442ab6aSBarry Smith 1812f442ab6aSBarry Smith Logically Collective on PC 1813f442ab6aSBarry Smith 1814f442ab6aSBarry Smith Input Parameters: 1815f442ab6aSBarry Smith . pc - the preconditioner context 1816f442ab6aSBarry Smith 1817f442ab6aSBarry Smith Options Database Key: 1818147403d9SBarry Smith . -pc_mg_distinct_smoothup <bool> - use distinct smoothing objects 1819f442ab6aSBarry Smith 1820f442ab6aSBarry Smith Level: advanced 1821f442ab6aSBarry Smith 182295452b02SPatrick Sanan Notes: 182395452b02SPatrick Sanan this does not set a value on the coarsest grid, since we assume that 1824f442ab6aSBarry Smith there is no separate smooth up on the coarsest grid. 1825f442ab6aSBarry Smith 1826db781477SPatrick Sanan .seealso: `PCMGSetNumberSmooth()` 1827f442ab6aSBarry Smith @*/ 1828f442ab6aSBarry Smith PetscErrorCode PCMGSetDistinctSmoothUp(PC pc) 1829f442ab6aSBarry Smith { 1830f442ab6aSBarry Smith PC_MG *mg = (PC_MG*)pc->data; 1831f442ab6aSBarry Smith PC_MG_Levels **mglevels = mg->levels; 1832f442ab6aSBarry Smith PetscInt i,levels; 1833f442ab6aSBarry Smith KSP subksp; 1834f442ab6aSBarry Smith 1835f442ab6aSBarry Smith PetscFunctionBegin; 1836f442ab6aSBarry Smith PetscValidHeaderSpecific(pc,PC_CLASSID,1); 183728b400f6SJacob Faibussowitsch PetscCheck(mglevels,PetscObjectComm((PetscObject)pc),PETSC_ERR_ORDER,"Must set MG levels with PCMGSetLevels() before calling"); 1838f442ab6aSBarry Smith levels = mglevels[0]->levels; 1839f442ab6aSBarry Smith 1840f442ab6aSBarry Smith for (i=1; i<levels; i++) { 1841710315b6SLawrence Mitchell const char *prefix = NULL; 1842f442ab6aSBarry Smith /* make sure smoother up and down are different */ 18439566063dSJacob Faibussowitsch PetscCall(PCMGGetSmootherUp(pc,i,&subksp)); 18449566063dSJacob Faibussowitsch PetscCall(KSPGetOptionsPrefix(mglevels[i]->smoothd,&prefix)); 18459566063dSJacob Faibussowitsch PetscCall(KSPSetOptionsPrefix(subksp,prefix)); 18469566063dSJacob Faibussowitsch PetscCall(KSPAppendOptionsPrefix(subksp,"up_")); 1847f442ab6aSBarry Smith } 1848f442ab6aSBarry Smith PetscFunctionReturn(0); 1849f442ab6aSBarry Smith } 1850f442ab6aSBarry Smith 185107a4832bSFande Kong /* No new matrices are created, and the coarse operator matrices are the references to the original ones */ 185207a4832bSFande Kong PetscErrorCode PCGetInterpolations_MG(PC pc,PetscInt *num_levels,Mat *interpolations[]) 185307a4832bSFande Kong { 185407a4832bSFande Kong PC_MG *mg = (PC_MG*)pc->data; 185507a4832bSFande Kong PC_MG_Levels **mglevels = mg->levels; 185607a4832bSFande Kong Mat *mat; 185707a4832bSFande Kong PetscInt l; 185807a4832bSFande Kong 185907a4832bSFande Kong PetscFunctionBegin; 186028b400f6SJacob Faibussowitsch PetscCheck(mglevels,PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONGSTATE,"Must set MG levels before calling"); 18619566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(mg->nlevels,&mat)); 186207a4832bSFande Kong for (l=1; l< mg->nlevels; l++) { 186307a4832bSFande Kong mat[l-1] = mglevels[l]->interpolate; 18649566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)mat[l-1])); 186507a4832bSFande Kong } 186607a4832bSFande Kong *num_levels = mg->nlevels; 186707a4832bSFande Kong *interpolations = mat; 186807a4832bSFande Kong PetscFunctionReturn(0); 186907a4832bSFande Kong } 187007a4832bSFande Kong 187107a4832bSFande Kong /* No new matrices are created, and the coarse operator matrices are the references to the original ones */ 187207a4832bSFande Kong PetscErrorCode PCGetCoarseOperators_MG(PC pc,PetscInt *num_levels,Mat *coarseOperators[]) 187307a4832bSFande Kong { 187407a4832bSFande Kong PC_MG *mg = (PC_MG*)pc->data; 187507a4832bSFande Kong PC_MG_Levels **mglevels = mg->levels; 187607a4832bSFande Kong PetscInt l; 187707a4832bSFande Kong Mat *mat; 187807a4832bSFande Kong 187907a4832bSFande Kong PetscFunctionBegin; 188028b400f6SJacob Faibussowitsch PetscCheck(mglevels,PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONGSTATE,"Must set MG levels before calling"); 18819566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(mg->nlevels,&mat)); 188207a4832bSFande Kong for (l=0; l<mg->nlevels-1; l++) { 18839566063dSJacob Faibussowitsch PetscCall(KSPGetOperators(mglevels[l]->smoothd,NULL,&(mat[l]))); 18849566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)mat[l])); 188507a4832bSFande Kong } 188607a4832bSFande Kong *num_levels = mg->nlevels; 188707a4832bSFande Kong *coarseOperators = mat; 188807a4832bSFande Kong PetscFunctionReturn(0); 188907a4832bSFande Kong } 189007a4832bSFande Kong 1891f3b08a26SMatthew G. Knepley /*@C 1892f3b08a26SMatthew G. Knepley PCMGRegisterCoarseSpaceConstructor - Adds a method to the PCMG package for coarse space construction. 1893f3b08a26SMatthew G. Knepley 1894f3b08a26SMatthew G. Knepley Not collective 1895f3b08a26SMatthew G. Knepley 1896f3b08a26SMatthew G. Knepley Input Parameters: 1897f3b08a26SMatthew G. Knepley + name - name of the constructor 1898f3b08a26SMatthew G. Knepley - function - constructor routine 1899f3b08a26SMatthew G. Knepley 1900f3b08a26SMatthew G. Knepley Notes: 1901f3b08a26SMatthew G. Knepley Calling sequence for the routine: 19022b3cbbdaSStefano Zampini $ my_csp(PC pc, PetscInt l, DM dm, KSP smooth, PetscInt Nc, Mat initGuess, Mat *coarseSp) 1903f3b08a26SMatthew G. Knepley $ pc - The PC object 1904f3b08a26SMatthew G. Knepley $ l - The multigrid level, 0 is the coarse level 1905f3b08a26SMatthew G. Knepley $ dm - The DM for this level 1906f3b08a26SMatthew G. Knepley $ smooth - The level smoother 1907f3b08a26SMatthew G. Knepley $ Nc - The size of the coarse space 1908f3b08a26SMatthew G. Knepley $ initGuess - Basis for an initial guess for the space 1909f3b08a26SMatthew G. Knepley $ coarseSp - A basis for the computed coarse space 1910f3b08a26SMatthew G. Knepley 1911f3b08a26SMatthew G. Knepley Level: advanced 1912f3b08a26SMatthew G. Knepley 1913db781477SPatrick Sanan .seealso: `PCMGGetCoarseSpaceConstructor()`, `PCRegister()` 1914f3b08a26SMatthew G. Knepley @*/ 19152b3cbbdaSStefano Zampini PetscErrorCode PCMGRegisterCoarseSpaceConstructor(const char name[], PetscErrorCode (*function)(PC, PetscInt, DM, KSP, PetscInt, Mat, Mat*)) 1916f3b08a26SMatthew G. Knepley { 1917f3b08a26SMatthew G. Knepley PetscFunctionBegin; 19189566063dSJacob Faibussowitsch PetscCall(PCInitializePackage()); 19199566063dSJacob Faibussowitsch PetscCall(PetscFunctionListAdd(&PCMGCoarseList,name,function)); 1920f3b08a26SMatthew G. Knepley PetscFunctionReturn(0); 1921f3b08a26SMatthew G. Knepley } 1922f3b08a26SMatthew G. Knepley 1923f3b08a26SMatthew G. Knepley /*@C 1924f3b08a26SMatthew G. Knepley PCMGGetCoarseSpaceConstructor - Returns the given coarse space construction method. 1925f3b08a26SMatthew G. Knepley 1926f3b08a26SMatthew G. Knepley Not collective 1927f3b08a26SMatthew G. Knepley 1928f3b08a26SMatthew G. Knepley Input Parameter: 1929f3b08a26SMatthew G. Knepley . name - name of the constructor 1930f3b08a26SMatthew G. Knepley 1931f3b08a26SMatthew G. Knepley Output Parameter: 1932f3b08a26SMatthew G. Knepley . function - constructor routine 1933f3b08a26SMatthew G. Knepley 1934f3b08a26SMatthew G. Knepley Notes: 1935f3b08a26SMatthew G. Knepley Calling sequence for the routine: 19362b3cbbdaSStefano Zampini $ my_csp(PC pc, PetscInt l, DM dm, KSP smooth, PetscInt Nc, Mat initGuess, Mat *coarseSp) 1937f3b08a26SMatthew G. Knepley $ pc - The PC object 1938f3b08a26SMatthew G. Knepley $ l - The multigrid level, 0 is the coarse level 1939f3b08a26SMatthew G. Knepley $ dm - The DM for this level 1940f3b08a26SMatthew G. Knepley $ smooth - The level smoother 1941f3b08a26SMatthew G. Knepley $ Nc - The size of the coarse space 1942f3b08a26SMatthew G. Knepley $ initGuess - Basis for an initial guess for the space 1943f3b08a26SMatthew G. Knepley $ coarseSp - A basis for the computed coarse space 1944f3b08a26SMatthew G. Knepley 1945f3b08a26SMatthew G. Knepley Level: advanced 1946f3b08a26SMatthew G. Knepley 1947db781477SPatrick Sanan .seealso: `PCMGRegisterCoarseSpaceConstructor()`, `PCRegister()` 1948f3b08a26SMatthew G. Knepley @*/ 19492b3cbbdaSStefano Zampini PetscErrorCode PCMGGetCoarseSpaceConstructor(const char name[], PetscErrorCode (**function)(PC, PetscInt, DM, KSP, PetscInt, Mat, Mat*)) 1950f3b08a26SMatthew G. Knepley { 1951f3b08a26SMatthew G. Knepley PetscFunctionBegin; 19529566063dSJacob Faibussowitsch PetscCall(PetscFunctionListFind(PCMGCoarseList,name,function)); 1953f3b08a26SMatthew G. Knepley PetscFunctionReturn(0); 1954f3b08a26SMatthew G. Knepley } 1955f3b08a26SMatthew G. Knepley 19564b9ad928SBarry Smith /* ----------------------------------------------------------------------------------------*/ 19574b9ad928SBarry Smith 19583b09bd56SBarry Smith /*MC 1959ccb205f8SBarry Smith PCMG - Use multigrid preconditioning. This preconditioner requires you provide additional 19603b09bd56SBarry Smith information about the coarser grid matrices and restriction/interpolation operators. 19613b09bd56SBarry Smith 19623b09bd56SBarry Smith Options Database Keys: 19633b09bd56SBarry Smith + -pc_mg_levels <nlevels> - number of levels including finest 1964391689abSStefano Zampini . -pc_mg_cycle_type <v,w> - provide the cycle desired 19658c1c2452SJed Brown . -pc_mg_type <additive,multiplicative,full,kaskade> - multiplicative is the default 19663b09bd56SBarry Smith . -pc_mg_log - log information about time spent on each level of the solver 1967710315b6SLawrence Mitchell . -pc_mg_distinct_smoothup - configure up (after interpolation) and down (before restriction) smoothers separately (with different options prefixes) 19682134b1e4SBarry Smith . -pc_mg_galerkin <both,pmat,mat,none> - use Galerkin process to compute coarser operators, i.e. Acoarse = R A R' 19698cf6037eSBarry Smith . -pc_mg_multiplicative_cycles - number of cycles to use as the preconditioner (defaults to 1) 19708cf6037eSBarry Smith . -pc_mg_dump_matlab - dumps the matrices for each level and the restriction/interpolation matrices 1971e3c5b3baSBarry Smith to the Socket viewer for reading from MATLAB. 19728cf6037eSBarry Smith - -pc_mg_dump_binary - dumps the matrices for each level and the restriction/interpolation matrices 19738cf6037eSBarry Smith to the binary output file called binaryoutput 19743b09bd56SBarry Smith 197595452b02SPatrick Sanan Notes: 19760b3c753eSRichard 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 19773b09bd56SBarry Smith 19788cf6037eSBarry Smith When run with a single level the smoother options are used on that level NOT the coarse grid solver options 19798cf6037eSBarry Smith 198023067569SBarry Smith When run with KSPRICHARDSON the convergence test changes slightly if monitor is turned on. The iteration count may change slightly. This 198123067569SBarry Smith is because without monitoring the residual norm is computed WITHIN each multigrid cycle on the finest level after the pre-smoothing 198223067569SBarry Smith (because the residual has just been computed for the multigrid algorithm and is hence available for free) while with monitoring the 198323067569SBarry Smith residual is computed at the end of each cycle. 198423067569SBarry Smith 19853b09bd56SBarry Smith Level: intermediate 19863b09bd56SBarry Smith 1987db781477SPatrick Sanan .seealso: `PCCreate()`, `PCSetType()`, `PCType`, `PC`, `PCMGType`, `PCEXOTIC`, `PCGAMG`, `PCML`, `PCHYPRE` 1988db781477SPatrick Sanan `PCMGSetLevels()`, `PCMGGetLevels()`, `PCMGSetType()`, `PCMGSetCycleType()`, 1989db781477SPatrick Sanan `PCMGSetDistinctSmoothUp()`, `PCMGGetCoarseSolve()`, `PCMGSetResidual()`, `PCMGSetInterpolation()`, 1990db781477SPatrick Sanan `PCMGSetRestriction()`, `PCMGGetSmoother()`, `PCMGGetSmootherUp()`, `PCMGGetSmootherDown()`, 1991db781477SPatrick Sanan `PCMGSetCycleTypeOnLevel()`, `PCMGSetRhs()`, `PCMGSetX()`, `PCMGSetR()` 19923b09bd56SBarry Smith M*/ 19933b09bd56SBarry Smith 19948cc058d9SJed Brown PETSC_EXTERN PetscErrorCode PCCreate_MG(PC pc) 19954b9ad928SBarry Smith { 1996f3fbd535SBarry Smith PC_MG *mg; 1997f3fbd535SBarry Smith 19984b9ad928SBarry Smith PetscFunctionBegin; 19999566063dSJacob Faibussowitsch PetscCall(PetscNewLog(pc,&mg)); 20003ec1f749SStefano Zampini pc->data = mg; 2001f3fbd535SBarry Smith mg->nlevels = -1; 200210eca3edSLisandro Dalcin mg->am = PC_MG_MULTIPLICATIVE; 20032134b1e4SBarry Smith mg->galerkin = PC_MG_GALERKIN_NONE; 2004f3b08a26SMatthew G. Knepley mg->adaptInterpolation = PETSC_FALSE; 2005f3b08a26SMatthew G. Knepley mg->Nc = -1; 2006f3b08a26SMatthew G. Knepley mg->eigenvalue = -1; 2007f3fbd535SBarry Smith 200837a44384SMark Adams pc->useAmat = PETSC_TRUE; 200937a44384SMark Adams 20104b9ad928SBarry Smith pc->ops->apply = PCApply_MG; 2011fcb023d4SJed Brown pc->ops->applytranspose = PCApplyTranspose_MG; 201230b0564aSStefano Zampini pc->ops->matapply = PCMatApply_MG; 20134b9ad928SBarry Smith pc->ops->setup = PCSetUp_MG; 2014a06653b4SBarry Smith pc->ops->reset = PCReset_MG; 20154b9ad928SBarry Smith pc->ops->destroy = PCDestroy_MG; 20164b9ad928SBarry Smith pc->ops->setfromoptions = PCSetFromOptions_MG; 20174b9ad928SBarry Smith pc->ops->view = PCView_MG; 2018fb15c04eSBarry Smith 20199566063dSJacob Faibussowitsch PetscCall(PetscObjectComposedDataRegister(&mg->eigenvalue)); 20209566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCMGSetGalerkin_C",PCMGSetGalerkin_MG)); 20219566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCMGGetLevels_C",PCMGGetLevels_MG)); 20229566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCMGSetLevels_C",PCMGSetLevels_MG)); 20239566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCGetInterpolations_C",PCGetInterpolations_MG)); 20249566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCGetCoarseOperators_C",PCGetCoarseOperators_MG)); 20259566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCMGSetAdaptInterpolation_C",PCMGSetAdaptInterpolation_MG)); 20269566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCMGGetAdaptInterpolation_C",PCMGGetAdaptInterpolation_MG)); 20279566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCMGSetAdaptCR_C",PCMGSetAdaptCR_MG)); 20289566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCMGGetAdaptCR_C",PCMGGetAdaptCR_MG)); 20292b3cbbdaSStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCMGSetAdaptCoarseSpaceType_C",PCMGSetAdaptCoarseSpaceType_MG)); 20302b3cbbdaSStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCMGGetAdaptCoarseSpaceType_C",PCMGGetAdaptCoarseSpaceType_MG)); 20314b9ad928SBarry Smith PetscFunctionReturn(0); 20324b9ad928SBarry Smith } 2033