1dba47a55SKris Buschelman #define PETSCKSP_DLL 2dba47a55SKris Buschelman 34b9ad928SBarry Smith /* 44b9ad928SBarry Smith Defines the multigrid preconditioner interface. 54b9ad928SBarry Smith */ 64b9ad928SBarry Smith #include "src/ksp/pc/impls/mg/mgimpl.h" /*I "petscmg.h" I*/ 74b9ad928SBarry Smith 84b9ad928SBarry Smith 94b9ad928SBarry Smith #undef __FUNCT__ 109dcbbd2bSBarry Smith #define __FUNCT__ "PCMGMCycle_Private" 119dcbbd2bSBarry Smith PetscErrorCode PCMGMCycle_Private(PC_MG **mglevels,PetscTruth *converged) 124b9ad928SBarry Smith { 139dcbbd2bSBarry Smith PC_MG *mg = *mglevels,*mgc; 146849ba73SBarry Smith PetscErrorCode ierr; 150d353602SBarry Smith PetscInt cycles = (PetscInt) mg->cycles; 164b9ad928SBarry Smith 174b9ad928SBarry Smith PetscFunctionBegin; 184b9ad928SBarry Smith if (converged) *converged = PETSC_FALSE; 194b9ad928SBarry Smith 2032cf1786SBarry Smith if (mg->eventsmoothsolve) {ierr = PetscLogEventBegin(mg->eventsmoothsolve,0,0,0,0);CHKERRQ(ierr);} 210d353602SBarry Smith ierr = KSPSolve(mg->smoothd,mg->b,mg->x);CHKERRQ(ierr); /* pre-smooth */ 2232cf1786SBarry Smith if (mg->eventsmoothsolve) {ierr = PetscLogEventEnd(mg->eventsmoothsolve,0,0,0,0);CHKERRQ(ierr);} 234b9ad928SBarry Smith if (mg->level) { /* not the coarsest grid */ 2432cf1786SBarry Smith if (mg->eventresidual) {ierr = PetscLogEventBegin(mg->eventresidual,0,0,0,0);CHKERRQ(ierr);} 254b9ad928SBarry Smith ierr = (*mg->residual)(mg->A,mg->b,mg->x,mg->r);CHKERRQ(ierr); 2632cf1786SBarry Smith if (mg->eventresidual) {ierr = PetscLogEventEnd(mg->eventresidual,0,0,0,0);CHKERRQ(ierr);} 274b9ad928SBarry Smith 284b9ad928SBarry Smith /* if on finest level and have convergence criteria set */ 294b9ad928SBarry Smith if (mg->level == mg->levels-1 && mg->ttol) { 304b9ad928SBarry Smith PetscReal rnorm; 314b9ad928SBarry Smith ierr = VecNorm(mg->r,NORM_2,&rnorm);CHKERRQ(ierr); 324b9ad928SBarry Smith if (rnorm <= mg->ttol) { 334b9ad928SBarry Smith *converged = PETSC_TRUE; 3470441072SBarry Smith if (rnorm < mg->abstol) { 35ae15b995SBarry Smith ierr = PetscInfo2(0,"Linear solver has converged. Residual norm %G is less than absolute tolerance %G\n",rnorm,mg->abstol);CHKERRQ(ierr); 364b9ad928SBarry Smith } else { 37ae15b995SBarry Smith ierr = PetscInfo2(0,"Linear solver has converged. Residual norm %G is less than relative tolerance times initial residual norm %G\n",rnorm,mg->ttol);CHKERRQ(ierr); 384b9ad928SBarry Smith } 394b9ad928SBarry Smith PetscFunctionReturn(0); 404b9ad928SBarry Smith } 414b9ad928SBarry Smith } 424b9ad928SBarry Smith 434b9ad928SBarry Smith mgc = *(mglevels - 1); 4432cf1786SBarry Smith if (mg->eventinterprestrict) {ierr = PetscLogEventBegin(mg->eventinterprestrict,0,0,0,0);CHKERRQ(ierr);} 454b9ad928SBarry Smith ierr = MatRestrict(mg->restrct,mg->r,mgc->b);CHKERRQ(ierr); 4632cf1786SBarry Smith if (mg->eventinterprestrict) {ierr = PetscLogEventEnd(mg->eventinterprestrict,0,0,0,0);CHKERRQ(ierr);} 47efb30889SBarry Smith ierr = VecSet(mgc->x,0.0);CHKERRQ(ierr); 484b9ad928SBarry Smith while (cycles--) { 499dcbbd2bSBarry Smith ierr = PCMGMCycle_Private(mglevels-1,converged);CHKERRQ(ierr); 504b9ad928SBarry Smith } 5132cf1786SBarry Smith if (mg->eventinterprestrict) {ierr = PetscLogEventBegin(mg->eventinterprestrict,0,0,0,0);CHKERRQ(ierr);} 524b9ad928SBarry Smith ierr = MatInterpolateAdd(mg->interpolate,mgc->x,mg->x,mg->x);CHKERRQ(ierr); 5332cf1786SBarry Smith if (mg->eventinterprestrict) {ierr = PetscLogEventEnd(mg->eventinterprestrict,0,0,0,0);CHKERRQ(ierr);} 5432cf1786SBarry Smith if (mg->eventsmoothsolve) {ierr = PetscLogEventBegin(mg->eventsmoothsolve,0,0,0,0);CHKERRQ(ierr);} 550d353602SBarry Smith ierr = KSPSolve(mg->smoothu,mg->b,mg->x);CHKERRQ(ierr); /* post smooth */ 5632cf1786SBarry Smith if (mg->eventsmoothsolve) {ierr = PetscLogEventEnd(mg->eventsmoothsolve,0,0,0,0);CHKERRQ(ierr);} 574b9ad928SBarry Smith } 584b9ad928SBarry Smith PetscFunctionReturn(0); 594b9ad928SBarry Smith } 604b9ad928SBarry Smith 614b9ad928SBarry Smith /* 629dcbbd2bSBarry Smith PCMGCreate_Private - Creates a PC_MG structure for use with the 634b9ad928SBarry Smith multigrid code. Level 0 is the coarsest. (But the 644b9ad928SBarry Smith finest level is stored first in the array). 654b9ad928SBarry Smith 664b9ad928SBarry Smith */ 674b9ad928SBarry Smith #undef __FUNCT__ 689dcbbd2bSBarry Smith #define __FUNCT__ "PCMGCreate_Private" 699dcbbd2bSBarry Smith static PetscErrorCode PCMGCreate_Private(MPI_Comm comm,PetscInt levels,PC pc,MPI_Comm *comms,PC_MG ***result) 704b9ad928SBarry Smith { 719dcbbd2bSBarry Smith PC_MG **mg; 726849ba73SBarry Smith PetscErrorCode ierr; 7379416396SBarry Smith PetscInt i; 7479416396SBarry Smith PetscMPIInt size; 75f69a0ea3SMatthew Knepley const char *prefix; 764b9ad928SBarry Smith PC ipc; 774b9ad928SBarry Smith 784b9ad928SBarry Smith PetscFunctionBegin; 799dcbbd2bSBarry Smith ierr = PetscMalloc(levels*sizeof(PC_MG*),&mg);CHKERRQ(ierr); 809dcbbd2bSBarry Smith ierr = PetscLogObjectMemory(pc,levels*(sizeof(PC_MG*)+sizeof(PC_MG)));CHKERRQ(ierr); 814b9ad928SBarry Smith 824b9ad928SBarry Smith ierr = PCGetOptionsPrefix(pc,&prefix);CHKERRQ(ierr); 834b9ad928SBarry Smith 844b9ad928SBarry Smith for (i=0; i<levels; i++) { 859dcbbd2bSBarry Smith ierr = PetscNew(PC_MG,&mg[i]);CHKERRQ(ierr); 864b9ad928SBarry Smith mg[i]->level = i; 874b9ad928SBarry Smith mg[i]->levels = levels; 880d353602SBarry Smith mg[i]->cycles = PC_MG_CYCLE_V; 89c2be2410SBarry Smith mg[i]->galerkin = PETSC_FALSE; 90c2be2410SBarry Smith mg[i]->galerkinused = PETSC_FALSE; 9179416396SBarry Smith mg[i]->default_smoothu = 1; 9279416396SBarry Smith mg[i]->default_smoothd = 1; 934b9ad928SBarry Smith 944b9ad928SBarry Smith if (comms) comm = comms[i]; 954b9ad928SBarry Smith ierr = KSPCreate(comm,&mg[i]->smoothd);CHKERRQ(ierr); 9679416396SBarry Smith ierr = KSPSetTolerances(mg[i]->smoothd,PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT, mg[i]->default_smoothd);CHKERRQ(ierr); 974b9ad928SBarry Smith ierr = KSPSetOptionsPrefix(mg[i]->smoothd,prefix);CHKERRQ(ierr); 984b9ad928SBarry Smith 994b9ad928SBarry Smith /* do special stuff for coarse grid */ 1004b9ad928SBarry Smith if (!i && levels > 1) { 1014b9ad928SBarry Smith ierr = KSPAppendOptionsPrefix(mg[0]->smoothd,"mg_coarse_");CHKERRQ(ierr); 1024b9ad928SBarry Smith 1034b9ad928SBarry Smith /* coarse solve is (redundant) LU by default */ 1044b9ad928SBarry Smith ierr = KSPSetType(mg[0]->smoothd,KSPPREONLY);CHKERRQ(ierr); 1054b9ad928SBarry Smith ierr = KSPGetPC(mg[0]->smoothd,&ipc);CHKERRQ(ierr); 1064b9ad928SBarry Smith ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr); 1074b9ad928SBarry Smith if (size > 1) { 1084b9ad928SBarry Smith ierr = PCSetType(ipc,PCREDUNDANT);CHKERRQ(ierr); 1090d7810c8SBarry Smith } else { 1104b9ad928SBarry Smith ierr = PCSetType(ipc,PCLU);CHKERRQ(ierr); 1110d7810c8SBarry Smith } 1124b9ad928SBarry Smith 1134b9ad928SBarry Smith } else { 1142e70eadcSBarry Smith char tprefix[128]; 11513f74950SBarry Smith sprintf(tprefix,"mg_levels_%d_",(int)i); 1162e70eadcSBarry Smith ierr = KSPAppendOptionsPrefix(mg[i]->smoothd,tprefix);CHKERRQ(ierr); 1174b9ad928SBarry Smith } 11852e6d16bSBarry Smith ierr = PetscLogObjectParent(pc,mg[i]->smoothd);CHKERRQ(ierr); 1194b9ad928SBarry Smith mg[i]->smoothu = mg[i]->smoothd; 1204b9ad928SBarry Smith mg[i]->rtol = 0.0; 12170441072SBarry Smith mg[i]->abstol = 0.0; 1224b9ad928SBarry Smith mg[i]->dtol = 0.0; 1234b9ad928SBarry Smith mg[i]->ttol = 0.0; 12432cf1786SBarry Smith mg[i]->eventsmoothsetup = 0; 12532cf1786SBarry Smith mg[i]->eventsmoothsolve = 0; 12632cf1786SBarry Smith mg[i]->eventresidual = 0; 12732cf1786SBarry Smith mg[i]->eventinterprestrict = 0; 1288cc2d5dfSBarry Smith mg[i]->cyclesperpcapply = 1; 1294b9ad928SBarry Smith } 1304b9ad928SBarry Smith *result = mg; 1314b9ad928SBarry Smith PetscFunctionReturn(0); 1324b9ad928SBarry Smith } 1334b9ad928SBarry Smith 1344b9ad928SBarry Smith #undef __FUNCT__ 1354b9ad928SBarry Smith #define __FUNCT__ "PCDestroy_MG" 1366849ba73SBarry Smith static PetscErrorCode PCDestroy_MG(PC pc) 1374b9ad928SBarry Smith { 1389dcbbd2bSBarry Smith PC_MG **mg = (PC_MG**)pc->data; 1396849ba73SBarry Smith PetscErrorCode ierr; 14079416396SBarry Smith PetscInt i,n = mg[0]->levels; 1414b9ad928SBarry Smith 1424b9ad928SBarry Smith PetscFunctionBegin; 143fccaa45eSBarry Smith for (i=0; i<n-1; i++) { 144630ba2eeSBarry Smith if (mg[i+1]->r) {ierr = VecDestroy(mg[i+1]->r);CHKERRQ(ierr);} 145fccaa45eSBarry Smith if (mg[i]->b) {ierr = VecDestroy(mg[i]->b);CHKERRQ(ierr);} 146fccaa45eSBarry Smith if (mg[i]->x) {ierr = VecDestroy(mg[i]->x);CHKERRQ(ierr);} 147fccaa45eSBarry Smith if (mg[i+1]->restrct) {ierr = MatDestroy(mg[i+1]->restrct);CHKERRQ(ierr);} 148fccaa45eSBarry Smith if (mg[i+1]->interpolate) {ierr = MatDestroy(mg[i+1]->interpolate);CHKERRQ(ierr);} 149fccaa45eSBarry Smith } 150fccaa45eSBarry Smith 1514b9ad928SBarry Smith for (i=0; i<n; i++) { 1524b9ad928SBarry Smith if (mg[i]->smoothd != mg[i]->smoothu) { 1534b9ad928SBarry Smith ierr = KSPDestroy(mg[i]->smoothd);CHKERRQ(ierr); 1544b9ad928SBarry Smith } 1554b9ad928SBarry Smith ierr = KSPDestroy(mg[i]->smoothu);CHKERRQ(ierr); 1564b9ad928SBarry Smith ierr = PetscFree(mg[i]);CHKERRQ(ierr); 1574b9ad928SBarry Smith } 1584b9ad928SBarry Smith ierr = PetscFree(mg);CHKERRQ(ierr); 1594b9ad928SBarry Smith PetscFunctionReturn(0); 1604b9ad928SBarry Smith } 1614b9ad928SBarry Smith 1624b9ad928SBarry Smith 1634b9ad928SBarry Smith 1649dcbbd2bSBarry Smith EXTERN PetscErrorCode PCMGACycle_Private(PC_MG**); 1659dcbbd2bSBarry Smith EXTERN PetscErrorCode PCMGFCycle_Private(PC_MG**); 1669dcbbd2bSBarry Smith EXTERN PetscErrorCode PCMGKCycle_Private(PC_MG**); 1674b9ad928SBarry Smith 1684b9ad928SBarry Smith /* 1694b9ad928SBarry Smith PCApply_MG - Runs either an additive, multiplicative, Kaskadic 1704b9ad928SBarry Smith or full cycle of multigrid. 1714b9ad928SBarry Smith 1724b9ad928SBarry Smith Note: 1739dcbbd2bSBarry Smith A simple wrapper which calls PCMGMCycle(),PCMGACycle(), or PCMGFCycle(). 1744b9ad928SBarry Smith */ 1754b9ad928SBarry Smith #undef __FUNCT__ 1764b9ad928SBarry Smith #define __FUNCT__ "PCApply_MG" 1776849ba73SBarry Smith static PetscErrorCode PCApply_MG(PC pc,Vec b,Vec x) 1784b9ad928SBarry Smith { 1799dcbbd2bSBarry Smith PC_MG **mg = (PC_MG**)pc->data; 1806849ba73SBarry Smith PetscErrorCode ierr; 1818cc2d5dfSBarry Smith PetscInt levels = mg[0]->levels,i; 1824b9ad928SBarry Smith 1834b9ad928SBarry Smith PetscFunctionBegin; 1844b9ad928SBarry Smith mg[levels-1]->b = b; 1854b9ad928SBarry Smith mg[levels-1]->x = x; 186ef70c39aSMatthew Knepley if (!mg[levels-1]->r && mg[0]->am != PC_MG_ADDITIVE && levels > 1) { 1870a6bb862SBarry Smith Vec tvec; 1880a6bb862SBarry Smith ierr = VecDuplicate(mg[levels-1]->b,&tvec);CHKERRQ(ierr); 18997177400SBarry Smith ierr = PCMGSetR(pc,levels-1,tvec);CHKERRQ(ierr); 1900a6bb862SBarry Smith ierr = VecDestroy(tvec);CHKERRQ(ierr); 1910a6bb862SBarry Smith } 1929dcbbd2bSBarry Smith if (mg[0]->am == PC_MG_MULTIPLICATIVE) { 193efb30889SBarry Smith ierr = VecSet(x,0.0);CHKERRQ(ierr); 1948cc2d5dfSBarry Smith for (i=0; i<mg[0]->cyclesperpcapply; i++) { 1959dcbbd2bSBarry Smith ierr = PCMGMCycle_Private(mg+levels-1,PETSC_NULL);CHKERRQ(ierr); 1964b9ad928SBarry Smith } 1978cc2d5dfSBarry Smith } 1989dcbbd2bSBarry Smith else if (mg[0]->am == PC_MG_ADDITIVE) { 1999dcbbd2bSBarry Smith ierr = PCMGACycle_Private(mg);CHKERRQ(ierr); 2004b9ad928SBarry Smith } 2019dcbbd2bSBarry Smith else if (mg[0]->am == PC_MG_KASKADE) { 2029dcbbd2bSBarry Smith ierr = PCMGKCycle_Private(mg);CHKERRQ(ierr); 2034b9ad928SBarry Smith } 2044b9ad928SBarry Smith else { 2059dcbbd2bSBarry Smith ierr = PCMGFCycle_Private(mg);CHKERRQ(ierr); 2064b9ad928SBarry Smith } 2074b9ad928SBarry Smith PetscFunctionReturn(0); 2084b9ad928SBarry Smith } 2094b9ad928SBarry Smith 2104b9ad928SBarry Smith #undef __FUNCT__ 2114b9ad928SBarry Smith #define __FUNCT__ "PCApplyRichardson_MG" 21279416396SBarry Smith static PetscErrorCode PCApplyRichardson_MG(PC pc,Vec b,Vec x,Vec w,PetscReal rtol,PetscReal abstol, PetscReal dtol,PetscInt its) 2134b9ad928SBarry Smith { 2149dcbbd2bSBarry Smith PC_MG **mg = (PC_MG**)pc->data; 215dfbe8321SBarry Smith PetscErrorCode ierr; 21679416396SBarry Smith PetscInt levels = mg[0]->levels; 2174b9ad928SBarry Smith PetscTruth converged = PETSC_FALSE; 2184b9ad928SBarry Smith 2194b9ad928SBarry Smith PetscFunctionBegin; 2204b9ad928SBarry Smith mg[levels-1]->b = b; 2214b9ad928SBarry Smith mg[levels-1]->x = x; 2224b9ad928SBarry Smith 2234b9ad928SBarry Smith mg[levels-1]->rtol = rtol; 22470441072SBarry Smith mg[levels-1]->abstol = abstol; 2254b9ad928SBarry Smith mg[levels-1]->dtol = dtol; 2264b9ad928SBarry Smith if (rtol) { 2274b9ad928SBarry Smith /* compute initial residual norm for relative convergence test */ 2284b9ad928SBarry Smith PetscReal rnorm; 2294b9ad928SBarry Smith ierr = (*mg[levels-1]->residual)(mg[levels-1]->A,b,x,w);CHKERRQ(ierr); 2304b9ad928SBarry Smith ierr = VecNorm(w,NORM_2,&rnorm);CHKERRQ(ierr); 23170441072SBarry Smith mg[levels-1]->ttol = PetscMax(rtol*rnorm,abstol); 23270441072SBarry Smith } else if (abstol) { 23370441072SBarry Smith mg[levels-1]->ttol = abstol; 2344b9ad928SBarry Smith } else { 2354b9ad928SBarry Smith mg[levels-1]->ttol = 0.0; 2364b9ad928SBarry Smith } 2374b9ad928SBarry Smith 2384b9ad928SBarry Smith while (its-- && !converged) { 2399dcbbd2bSBarry Smith ierr = PCMGMCycle_Private(mg+levels-1,&converged);CHKERRQ(ierr); 2404b9ad928SBarry Smith } 2414b9ad928SBarry Smith PetscFunctionReturn(0); 2424b9ad928SBarry Smith } 2434b9ad928SBarry Smith 2444b9ad928SBarry Smith #undef __FUNCT__ 2454b9ad928SBarry Smith #define __FUNCT__ "PCSetFromOptions_MG" 2466ca4d86aSHong Zhang PetscErrorCode PCSetFromOptions_MG(PC pc) 2474b9ad928SBarry Smith { 248dfbe8321SBarry Smith PetscErrorCode ierr; 2498cc2d5dfSBarry Smith PetscInt m,levels = 1,cycles; 2504b9ad928SBarry Smith PetscTruth flg; 2519dcbbd2bSBarry Smith PC_MG **mg = (PC_MG**)pc->data; 25290da95b0SMatthew Knepley PCMGType mgtype = PC_MG_ADDITIVE; 2531aa34eeaSBarry Smith PCMGCycleType mgctype; 2544b9ad928SBarry Smith 2554b9ad928SBarry Smith PetscFunctionBegin; 2564b9ad928SBarry Smith ierr = PetscOptionsHead("Multigrid options");CHKERRQ(ierr); 2574b9ad928SBarry Smith if (!pc->data) { 2589dcbbd2bSBarry Smith ierr = PetscOptionsInt("-pc_mg_levels","Number of Levels","PCMGSetLevels",levels,&levels,&flg);CHKERRQ(ierr); 25997177400SBarry Smith ierr = PCMGSetLevels(pc,levels,PETSC_NULL);CHKERRQ(ierr); 260cf502942SBarry Smith mg = (PC_MG**)pc->data; 2614b9ad928SBarry Smith } 262f2070a76SMatthew Knepley mgctype = (PCMGCycleType) mg[0]->cycles; 2630d353602SBarry Smith ierr = PetscOptionsEnum("-pc_mg_cycle_type","V cycle or for W-cycle","PCMGSetCycleType",PCMGCycleTypes,(PetscEnum)mgctype,(PetscEnum*)&mgctype,&flg);CHKERRQ(ierr); 2644b9ad928SBarry Smith if (flg) { 2650d353602SBarry Smith ierr = PCMGSetCycleType(pc,mgctype);CHKERRQ(ierr); 2660d353602SBarry Smith }; 2679dcbbd2bSBarry Smith ierr = PetscOptionsName("-pc_mg_galerkin","Use Galerkin process to compute coarser operators","PCMGSetGalerkin",&flg);CHKERRQ(ierr); 268c2be2410SBarry Smith if (flg) { 26997177400SBarry Smith ierr = PCMGSetGalerkin(pc);CHKERRQ(ierr); 270c2be2410SBarry Smith } 2719dcbbd2bSBarry Smith ierr = PetscOptionsInt("-pc_mg_smoothup","Number of post-smoothing steps","PCMGSetNumberSmoothUp",1,&m,&flg);CHKERRQ(ierr); 2724b9ad928SBarry Smith if (flg) { 27397177400SBarry Smith ierr = PCMGSetNumberSmoothUp(pc,m);CHKERRQ(ierr); 2744b9ad928SBarry Smith } 2759dcbbd2bSBarry Smith ierr = PetscOptionsInt("-pc_mg_smoothdown","Number of pre-smoothing steps","PCMGSetNumberSmoothDown",1,&m,&flg);CHKERRQ(ierr); 2764b9ad928SBarry Smith if (flg) { 27797177400SBarry Smith ierr = PCMGSetNumberSmoothDown(pc,m);CHKERRQ(ierr); 2784b9ad928SBarry Smith } 2799dcbbd2bSBarry Smith ierr = PetscOptionsEnum("-pc_mg_type","Multigrid type","PCMGSetType",PCMGTypes,(PetscEnum)mgtype,(PetscEnum*)&mgtype,&flg);CHKERRQ(ierr); 2808cc2d5dfSBarry Smith if (flg) { 2818cc2d5dfSBarry Smith ierr = PCMGSetType(pc,mgtype);CHKERRQ(ierr); 2828cc2d5dfSBarry Smith } 2838cc2d5dfSBarry Smith if (mg[0]->am == PC_MG_MULTIPLICATIVE) { 2848cc2d5dfSBarry Smith ierr = PetscOptionsInt("-pc_mg_multiplicative_cycles","Number of cycles for each preconditioner step","PCMGSetLevels",mg[0]->cyclesperpcapply,&cycles,&flg);CHKERRQ(ierr); 2858cc2d5dfSBarry Smith if (flg) { 2868cc2d5dfSBarry Smith ierr = PCMGMultiplicativeSetCycles(pc,cycles);CHKERRQ(ierr); 2878cc2d5dfSBarry Smith } 2888cc2d5dfSBarry Smith } 2894b9ad928SBarry Smith ierr = PetscOptionsName("-pc_mg_log","Log times for each multigrid level","None",&flg);CHKERRQ(ierr); 2904b9ad928SBarry Smith if (flg) { 2914f5ab15aSBarry Smith PetscInt i; 2924b9ad928SBarry Smith char eventname[128]; 2934b9ad928SBarry Smith if (!mg) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Must set MG levels before calling"); 2944b9ad928SBarry Smith levels = mg[0]->levels; 2954b9ad928SBarry Smith for (i=0; i<levels; i++) { 29632cf1786SBarry Smith sprintf(eventname,"MGSetup Level %d",(int)i); 29732cf1786SBarry Smith ierr = PetscLogEventRegister(&mg[i]->eventsmoothsetup,eventname,pc->cookie);CHKERRQ(ierr); 29832cf1786SBarry Smith sprintf(eventname,"MGSmooth Level %d",(int)i); 29932cf1786SBarry Smith ierr = PetscLogEventRegister(&mg[i]->eventsmoothsolve,eventname,pc->cookie);CHKERRQ(ierr); 30032cf1786SBarry Smith if (i) { 30132cf1786SBarry Smith sprintf(eventname,"MGResid Level %d",(int)i); 30232cf1786SBarry Smith ierr = PetscLogEventRegister(&mg[i]->eventresidual,eventname,pc->cookie);CHKERRQ(ierr); 30332cf1786SBarry Smith sprintf(eventname,"MGInterp Level %d",(int)i); 30432cf1786SBarry Smith ierr = PetscLogEventRegister(&mg[i]->eventinterprestrict,eventname,pc->cookie);CHKERRQ(ierr); 30532cf1786SBarry Smith } 3064b9ad928SBarry Smith } 3074b9ad928SBarry Smith } 3084b9ad928SBarry Smith ierr = PetscOptionsTail();CHKERRQ(ierr); 3094b9ad928SBarry Smith PetscFunctionReturn(0); 3104b9ad928SBarry Smith } 3114b9ad928SBarry Smith 3129dcbbd2bSBarry Smith const char *PCMGTypes[] = {"MULTIPLICATIVE","ADDITIVE","FULL","KASKADE","PCMGType","PC_MG",0}; 3130d353602SBarry Smith const char *PCMGCycleTypes[] = {"invalid","v","w","PCMGCycleType","PC_MG_CYCLE",0}; 3149dcbbd2bSBarry Smith 3154b9ad928SBarry Smith #undef __FUNCT__ 3164b9ad928SBarry Smith #define __FUNCT__ "PCView_MG" 3176849ba73SBarry Smith static PetscErrorCode PCView_MG(PC pc,PetscViewer viewer) 3184b9ad928SBarry Smith { 3199dcbbd2bSBarry Smith PC_MG **mg = (PC_MG**)pc->data; 320dfbe8321SBarry Smith PetscErrorCode ierr; 32179416396SBarry Smith PetscInt levels = mg[0]->levels,i; 32232077d6dSBarry Smith PetscTruth iascii; 3234b9ad928SBarry Smith 3244b9ad928SBarry Smith PetscFunctionBegin; 32532077d6dSBarry Smith ierr = PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_ASCII,&iascii);CHKERRQ(ierr); 32632077d6dSBarry Smith if (iascii) { 3270d353602SBarry Smith ierr = PetscViewerASCIIPrintf(viewer," MG: type is %s, levels=%D cycles=%s, pre-smooths=%D, post-smooths=%D\n", 3280d353602SBarry Smith PCMGTypes[mg[0]->am],levels,(mg[0]->cycles == PC_MG_CYCLE_V) ? "v" : "w", 3290d353602SBarry Smith mg[0]->default_smoothd,mg[0]->default_smoothu);CHKERRQ(ierr); 330c2be2410SBarry Smith if (mg[0]->galerkin) { 331c2be2410SBarry Smith ierr = PetscViewerASCIIPrintf(viewer," Using Galerkin computed coarse grid matrices\n");CHKERRQ(ierr); 332c2be2410SBarry Smith } 3334b9ad928SBarry Smith for (i=0; i<levels; i++) { 334b03c7568SBarry Smith if (!i) { 335b03c7568SBarry Smith ierr = PetscViewerASCIIPrintf(viewer,"Coarse gride solver -- level %D -------------------------------\n",i);CHKERRQ(ierr); 336b03c7568SBarry Smith } else { 33777431f27SBarry Smith ierr = PetscViewerASCIIPrintf(viewer,"Down solver (pre-smoother) on level %D -------------------------------\n",i);CHKERRQ(ierr); 338b03c7568SBarry Smith } 3394b9ad928SBarry Smith ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); 3404b9ad928SBarry Smith ierr = KSPView(mg[i]->smoothd,viewer);CHKERRQ(ierr); 3414b9ad928SBarry Smith ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); 342b03c7568SBarry Smith if (i && mg[i]->smoothd == mg[i]->smoothu) { 3434b9ad928SBarry Smith ierr = PetscViewerASCIIPrintf(viewer,"Up solver (post-smoother) same as down solver (pre-smoother)\n");CHKERRQ(ierr); 344b03c7568SBarry Smith } else if (i){ 34577431f27SBarry Smith ierr = PetscViewerASCIIPrintf(viewer,"Up solver (post-smoother) on level %D -------------------------------\n",i);CHKERRQ(ierr); 3464b9ad928SBarry Smith ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); 3474b9ad928SBarry Smith ierr = KSPView(mg[i]->smoothu,viewer);CHKERRQ(ierr); 3484b9ad928SBarry Smith ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); 3494b9ad928SBarry Smith } 3504b9ad928SBarry Smith } 3514b9ad928SBarry Smith } else { 35279a5c55eSBarry Smith SETERRQ1(PETSC_ERR_SUP,"Viewer type %s not supported for PCMG",((PetscObject)viewer)->type_name); 3534b9ad928SBarry Smith } 3544b9ad928SBarry Smith PetscFunctionReturn(0); 3554b9ad928SBarry Smith } 3564b9ad928SBarry Smith 3574b9ad928SBarry Smith /* 3584b9ad928SBarry Smith Calls setup for the KSP on each level 3594b9ad928SBarry Smith */ 3604b9ad928SBarry Smith #undef __FUNCT__ 3614b9ad928SBarry Smith #define __FUNCT__ "PCSetUp_MG" 3626849ba73SBarry Smith static PetscErrorCode PCSetUp_MG(PC pc) 3634b9ad928SBarry Smith { 3649dcbbd2bSBarry Smith PC_MG **mg = (PC_MG**)pc->data; 365dfbe8321SBarry Smith PetscErrorCode ierr; 36679416396SBarry Smith PetscInt i,n = mg[0]->levels; 36777122347SBarry Smith PC cpc,mpc; 368906ed7ccSBarry Smith PetscTruth preonly,lu,redundant,cholesky,monitor = PETSC_FALSE,dump,opsset; 36923d894e5SBarry Smith PetscViewerASCIIMonitor ascii; 37023d894e5SBarry Smith PetscViewer viewer = PETSC_NULL; 3714b9ad928SBarry Smith MPI_Comm comm; 372c2be2410SBarry Smith Mat dA,dB; 373c2be2410SBarry Smith MatStructure uflag; 3740a6bb862SBarry Smith Vec tvec; 3754b9ad928SBarry Smith 3764b9ad928SBarry Smith PetscFunctionBegin; 377852665d3SBarry Smith 37843fb2f97SBarry Smith /* If user did not provide fine grid operators OR operator was not updated since last global KSPSetOperators() */ 37943fb2f97SBarry Smith /* so use those from global PC */ 38043fb2f97SBarry Smith /* Is this what we always want? What if user wants to keep old one? */ 381906ed7ccSBarry Smith ierr = KSPGetOperatorsSet(mg[n-1]->smoothd,PETSC_NULL,&opsset);CHKERRQ(ierr); 38243fb2f97SBarry Smith ierr = KSPGetPC(mg[0]->smoothd,&cpc);CHKERRQ(ierr); 38377122347SBarry Smith ierr = KSPGetPC(mg[n-1]->smoothd,&mpc);CHKERRQ(ierr); 38477122347SBarry Smith if (!opsset || ((cpc->setupcalled == 1) && (mpc->setupcalled == 2))) { 385852665d3SBarry Smith ierr = PetscInfo(pc,"Using outer operators to define finest grid operator \n because PCMGGetSmoother(pc,nlevels-1,&ksp);KSPSetOperators(ksp,...); was not called.\n");CHKERRQ(ierr); 3861cfe3bddSBarry Smith ierr = KSPSetOperators(mg[n-1]->smoothd,pc->mat,pc->pmat,pc->flag);CHKERRQ(ierr); 387852665d3SBarry Smith } 388852665d3SBarry Smith 389852665d3SBarry Smith if (mg[0]->galerkin) { 390852665d3SBarry Smith Mat B; 391852665d3SBarry Smith mg[0]->galerkinused = PETSC_TRUE; 392852665d3SBarry Smith /* currently only handle case where mat and pmat are the same on coarser levels */ 393852665d3SBarry Smith ierr = KSPGetOperators(mg[n-1]->smoothd,&dA,&dB,&uflag);CHKERRQ(ierr); 394852665d3SBarry Smith if (!pc->setupcalled) { 395852665d3SBarry Smith for (i=n-2; i>-1; i--) { 396852665d3SBarry Smith ierr = MatPtAP(dB,mg[i+1]->interpolate,MAT_INITIAL_MATRIX,1.0,&B);CHKERRQ(ierr); 397852665d3SBarry Smith ierr = KSPSetOperators(mg[i]->smoothd,B,B,uflag);CHKERRQ(ierr); 398906ed7ccSBarry Smith if (i != n-2) {ierr = PetscObjectDereference((PetscObject)dB);CHKERRQ(ierr);} 399852665d3SBarry Smith dB = B; 400852665d3SBarry Smith } 401906ed7ccSBarry Smith ierr = PetscObjectDereference((PetscObject)dB);CHKERRQ(ierr); 402852665d3SBarry Smith } else { 403852665d3SBarry Smith for (i=n-2; i>-1; i--) { 404906ed7ccSBarry Smith ierr = KSPGetOperators(mg[i]->smoothd,PETSC_NULL,&B,PETSC_NULL);CHKERRQ(ierr); 405852665d3SBarry Smith ierr = MatPtAP(dB,mg[i+1]->interpolate,MAT_REUSE_MATRIX,1.0,&B);CHKERRQ(ierr); 406852665d3SBarry Smith ierr = KSPSetOperators(mg[i]->smoothd,B,B,uflag);CHKERRQ(ierr); 407852665d3SBarry Smith dB = B; 408852665d3SBarry Smith } 409852665d3SBarry Smith } 410852665d3SBarry Smith } 411852665d3SBarry Smith 412958c9bccSBarry Smith if (!pc->setupcalled) { 4134b9ad928SBarry Smith ierr = PetscOptionsHasName(0,"-pc_mg_monitor",&monitor);CHKERRQ(ierr); 4144b9ad928SBarry Smith 415b03c7568SBarry Smith for (i=0; i<n; i++) { 4164b9ad928SBarry Smith if (monitor) { 4174b9ad928SBarry Smith ierr = PetscObjectGetComm((PetscObject)mg[i]->smoothd,&comm);CHKERRQ(ierr); 41823d894e5SBarry Smith ierr = PetscViewerASCIIMonitorCreate(comm,"stdout",n-i,&ascii);CHKERRQ(ierr); 41923d894e5SBarry Smith ierr = KSPMonitorSet(mg[i]->smoothd,KSPMonitorDefault,ascii,(PetscErrorCode(*)(void*))PetscViewerASCIIMonitorDestroy);CHKERRQ(ierr); 4204b9ad928SBarry Smith } 4214b9ad928SBarry Smith ierr = KSPSetFromOptions(mg[i]->smoothd);CHKERRQ(ierr); 4224b9ad928SBarry Smith } 423b03c7568SBarry Smith for (i=1; i<n; i++) { 424a98fc643SBarry Smith if (mg[i]->smoothu && (mg[i]->smoothu != mg[i]->smoothd)) { 4254b9ad928SBarry Smith if (monitor) { 4264b9ad928SBarry Smith ierr = PetscObjectGetComm((PetscObject)mg[i]->smoothu,&comm);CHKERRQ(ierr); 42723d894e5SBarry Smith ierr = PetscViewerASCIIMonitorCreate(comm,"stdout",n-i,&ascii);CHKERRQ(ierr); 42823d894e5SBarry Smith ierr = KSPMonitorSet(mg[i]->smoothu,KSPMonitorDefault,ascii,(PetscErrorCode(*)(void*))PetscViewerASCIIMonitorDestroy);CHKERRQ(ierr); 4294b9ad928SBarry Smith } 4304b9ad928SBarry Smith ierr = KSPSetFromOptions(mg[i]->smoothu);CHKERRQ(ierr); 4314b9ad928SBarry Smith } 4324b9ad928SBarry Smith } 433fccaa45eSBarry Smith for (i=1; i<n; i++) { 4340cace4b0SBarry Smith if (!mg[i]->residual) { 4350cace4b0SBarry Smith Mat mat; 4360cace4b0SBarry Smith ierr = KSPGetOperators(mg[i]->smoothd,PETSC_NULL,&mat,PETSC_NULL);CHKERRQ(ierr); 4370cace4b0SBarry Smith ierr = PCMGSetResidual(pc,i,PCMGDefaultResidual,mat);CHKERRQ(ierr); 4380cace4b0SBarry Smith } 439fccaa45eSBarry Smith if (mg[i]->restrct && !mg[i]->interpolate) { 440aea2a34eSBarry Smith ierr = PCMGSetInterpolation(pc,i,mg[i]->restrct);CHKERRQ(ierr); 441fccaa45eSBarry Smith } 442fccaa45eSBarry Smith if (!mg[i]->restrct && mg[i]->interpolate) { 44397177400SBarry Smith ierr = PCMGSetRestriction(pc,i,mg[i]->interpolate);CHKERRQ(ierr); 444fccaa45eSBarry Smith } 445fccaa45eSBarry Smith #if defined(PETSC_USE_DEBUG) 446fccaa45eSBarry Smith if (!mg[i]->restrct || !mg[i]->interpolate) { 447fccaa45eSBarry Smith SETERRQ1(PETSC_ERR_ARG_WRONGSTATE,"Need to set restriction or interpolation on level %d",(int)i); 448fccaa45eSBarry Smith } 449fccaa45eSBarry Smith #endif 450fccaa45eSBarry Smith } 4510a6bb862SBarry Smith for (i=0; i<n-1; i++) { 45237b0e6c0SBarry Smith if (!mg[i]->b) { 453906ed7ccSBarry Smith Vec *vec; 454906ed7ccSBarry Smith ierr = KSPGetVecs(mg[i]->smoothd,1,&vec,0,PETSC_NULL);CHKERRQ(ierr); 455906ed7ccSBarry Smith ierr = PCMGSetRhs(pc,i,*vec);CHKERRQ(ierr); 456*4fdc791cSSatish Balay ierr = VecDestroy(*vec);CHKERRQ(ierr); 457906ed7ccSBarry Smith ierr = PetscFree(vec);CHKERRQ(ierr); 45837b0e6c0SBarry Smith } 4596ca4d86aSHong Zhang if (!mg[i]->r && i) { 4600a6bb862SBarry Smith ierr = VecDuplicate(mg[i]->b,&tvec);CHKERRQ(ierr); 46197177400SBarry Smith ierr = PCMGSetR(pc,i,tvec);CHKERRQ(ierr); 4620a6bb862SBarry Smith ierr = VecDestroy(tvec);CHKERRQ(ierr); 4630a6bb862SBarry Smith } 4640a6bb862SBarry Smith if (!mg[i]->x) { 4650a6bb862SBarry Smith ierr = VecDuplicate(mg[i]->b,&tvec);CHKERRQ(ierr); 46697177400SBarry Smith ierr = PCMGSetX(pc,i,tvec);CHKERRQ(ierr); 4670a6bb862SBarry Smith ierr = VecDestroy(tvec);CHKERRQ(ierr); 4680a6bb862SBarry Smith } 4690a6bb862SBarry Smith } 4704b9ad928SBarry Smith } 4714b9ad928SBarry Smith 472c2be2410SBarry Smith 4734b9ad928SBarry Smith for (i=1; i<n; i++) { 474b03c7568SBarry Smith if (mg[i]->smoothu == mg[i]->smoothd) { 475b03c7568SBarry Smith /* if doing only down then initial guess is zero */ 4764b9ad928SBarry Smith ierr = KSPSetInitialGuessNonzero(mg[i]->smoothd,PETSC_TRUE);CHKERRQ(ierr); 477b03c7568SBarry Smith } 47832cf1786SBarry Smith if (mg[i]->eventsmoothsetup) {ierr = PetscLogEventBegin(mg[i]->eventsmoothsetup,0,0,0,0);CHKERRQ(ierr);} 4794b9ad928SBarry Smith ierr = KSPSetUp(mg[i]->smoothd);CHKERRQ(ierr); 48032cf1786SBarry Smith if (mg[i]->eventsmoothsetup) {ierr = PetscLogEventEnd(mg[i]->eventsmoothsetup,0,0,0,0);CHKERRQ(ierr);} 4814b9ad928SBarry Smith } 482b03c7568SBarry Smith for (i=1; i<n; i++) { 4834b9ad928SBarry Smith if (mg[i]->smoothu && mg[i]->smoothu != mg[i]->smoothd) { 484906ed7ccSBarry Smith Mat downmat,downpmat; 48597f1f81fSBarry Smith MatStructure matflag; 486906ed7ccSBarry Smith PetscTruth opsset; 48797f1f81fSBarry Smith 48897f1f81fSBarry Smith /* check if operators have been set for up, if not use down operators to set them */ 489906ed7ccSBarry Smith ierr = KSPGetOperatorsSet(mg[i]->smoothu,&opsset,PETSC_NULL);CHKERRQ(ierr); 490906ed7ccSBarry Smith if (!opsset) { 491906ed7ccSBarry Smith ierr = KSPGetOperators(mg[i]->smoothd,&downmat,&downpmat,&matflag);CHKERRQ(ierr); 49297f1f81fSBarry Smith ierr = KSPSetOperators(mg[i]->smoothu,downmat,downpmat,matflag);CHKERRQ(ierr); 49397f1f81fSBarry Smith } 49497f1f81fSBarry Smith 4954b9ad928SBarry Smith ierr = KSPSetInitialGuessNonzero(mg[i]->smoothu,PETSC_TRUE);CHKERRQ(ierr); 49632cf1786SBarry Smith if (mg[i]->eventsmoothsetup) {ierr = PetscLogEventBegin(mg[i]->eventsmoothsetup,0,0,0,0);CHKERRQ(ierr);} 4974b9ad928SBarry Smith ierr = KSPSetUp(mg[i]->smoothu);CHKERRQ(ierr); 49832cf1786SBarry Smith if (mg[i]->eventsmoothsetup) {ierr = PetscLogEventEnd(mg[i]->eventsmoothsetup,0,0,0,0);CHKERRQ(ierr);} 4994b9ad928SBarry Smith } 5004b9ad928SBarry Smith } 5014b9ad928SBarry Smith 5024b9ad928SBarry Smith /* 5034b9ad928SBarry Smith If coarse solver is not direct method then DO NOT USE preonly 5044b9ad928SBarry Smith */ 5054b9ad928SBarry Smith ierr = PetscTypeCompare((PetscObject)mg[0]->smoothd,KSPPREONLY,&preonly);CHKERRQ(ierr); 5064b9ad928SBarry Smith if (preonly) { 5074b9ad928SBarry Smith ierr = PetscTypeCompare((PetscObject)cpc,PCLU,&lu);CHKERRQ(ierr); 5084b9ad928SBarry Smith ierr = PetscTypeCompare((PetscObject)cpc,PCREDUNDANT,&redundant);CHKERRQ(ierr); 50968eff7e6SBarry Smith ierr = PetscTypeCompare((PetscObject)cpc,PCCHOLESKY,&cholesky);CHKERRQ(ierr); 51068eff7e6SBarry Smith if (!lu && !redundant && !cholesky) { 5114b9ad928SBarry Smith ierr = KSPSetType(mg[0]->smoothd,KSPGMRES);CHKERRQ(ierr); 5124b9ad928SBarry Smith } 5134b9ad928SBarry Smith } 5144b9ad928SBarry Smith 515958c9bccSBarry Smith if (!pc->setupcalled) { 5164b9ad928SBarry Smith if (monitor) { 5174b9ad928SBarry Smith ierr = PetscObjectGetComm((PetscObject)mg[0]->smoothd,&comm);CHKERRQ(ierr); 51823d894e5SBarry Smith ierr = PetscViewerASCIIMonitorCreate(comm,"stdout",n,&ascii);CHKERRQ(ierr); 51923d894e5SBarry Smith ierr = KSPMonitorSet(mg[0]->smoothd,KSPMonitorDefault,ascii,(PetscErrorCode(*)(void*))PetscViewerASCIIMonitorDestroy);CHKERRQ(ierr); 5204b9ad928SBarry Smith } 5214b9ad928SBarry Smith ierr = KSPSetFromOptions(mg[0]->smoothd);CHKERRQ(ierr); 5224b9ad928SBarry Smith } 5234b9ad928SBarry Smith 52432cf1786SBarry Smith if (mg[0]->eventsmoothsetup) {ierr = PetscLogEventBegin(mg[0]->eventsmoothsetup,0,0,0,0);CHKERRQ(ierr);} 5254b9ad928SBarry Smith ierr = KSPSetUp(mg[0]->smoothd);CHKERRQ(ierr); 52632cf1786SBarry Smith if (mg[0]->eventsmoothsetup) {ierr = PetscLogEventEnd(mg[0]->eventsmoothsetup,0,0,0,0);CHKERRQ(ierr);} 5274b9ad928SBarry Smith 5284b9ad928SBarry Smith /* 5296805f65bSBarry Smith Dump the interpolation/restriction matrices plus the 5304b9ad928SBarry Smith Jacobian/stiffness on each level. This allows Matlab users to 5316805f65bSBarry Smith easily check if the Galerkin condition A_c = R A_f R^T is satisfied. 5326805f65bSBarry Smith 5336805f65bSBarry Smith Only support one or the other at the same time. 5346805f65bSBarry Smith */ 5356805f65bSBarry Smith #if defined(PETSC_USE_SOCKET_VIEWER) 5364b9ad928SBarry Smith ierr = PetscOptionsHasName(pc->prefix,"-pc_mg_dump_matlab",&dump);CHKERRQ(ierr); 5374b9ad928SBarry Smith if (dump) { 5386805f65bSBarry Smith viewer = PETSC_VIEWER_SOCKET_(pc->comm); 5394b9ad928SBarry Smith } 540c45a1595SBarry Smith #endif 541c2be2410SBarry Smith ierr = PetscOptionsHasName(pc->prefix,"-pc_mg_dump_binary",&dump);CHKERRQ(ierr); 542c2be2410SBarry Smith if (dump) { 5436805f65bSBarry Smith viewer = PETSC_VIEWER_BINARY_(pc->comm); 5446805f65bSBarry Smith } 5456805f65bSBarry Smith 5466805f65bSBarry Smith if (viewer) { 547c2be2410SBarry Smith for (i=1; i<n; i++) { 5486805f65bSBarry Smith ierr = MatView(mg[i]->restrct,viewer);CHKERRQ(ierr); 549c2be2410SBarry Smith } 550c2be2410SBarry Smith for (i=0; i<n; i++) { 551c2be2410SBarry Smith ierr = KSPGetPC(mg[i]->smoothd,&pc);CHKERRQ(ierr); 5526805f65bSBarry Smith ierr = MatView(pc->mat,viewer);CHKERRQ(ierr); 553c2be2410SBarry Smith } 554c2be2410SBarry Smith } 5554b9ad928SBarry Smith PetscFunctionReturn(0); 5564b9ad928SBarry Smith } 5574b9ad928SBarry Smith 5584b9ad928SBarry Smith /* -------------------------------------------------------------------------------------*/ 5594b9ad928SBarry Smith 5604b9ad928SBarry Smith #undef __FUNCT__ 5619dcbbd2bSBarry Smith #define __FUNCT__ "PCMGSetLevels" 5624b9ad928SBarry Smith /*@C 56397177400SBarry Smith PCMGSetLevels - Sets the number of levels to use with MG. 5644b9ad928SBarry Smith Must be called before any other MG routine. 5654b9ad928SBarry Smith 5664b9ad928SBarry Smith Collective on PC 5674b9ad928SBarry Smith 5684b9ad928SBarry Smith Input Parameters: 5694b9ad928SBarry Smith + pc - the preconditioner context 5704b9ad928SBarry Smith . levels - the number of levels 5714b9ad928SBarry Smith - comms - optional communicators for each level; this is to allow solving the coarser problems 5724b9ad928SBarry Smith on smaller sets of processors. Use PETSC_NULL_OBJECT for default in Fortran 5734b9ad928SBarry Smith 5744b9ad928SBarry Smith Level: intermediate 5754b9ad928SBarry Smith 5764b9ad928SBarry Smith Notes: 5774b9ad928SBarry Smith If the number of levels is one then the multigrid uses the -mg_levels prefix 5784b9ad928SBarry Smith for setting the level options rather than the -mg_coarse prefix. 5794b9ad928SBarry Smith 5804b9ad928SBarry Smith .keywords: MG, set, levels, multigrid 5814b9ad928SBarry Smith 58297177400SBarry Smith .seealso: PCMGSetType(), PCMGGetLevels() 5834b9ad928SBarry Smith @*/ 58497177400SBarry Smith PetscErrorCode PETSCKSP_DLLEXPORT PCMGSetLevels(PC pc,PetscInt levels,MPI_Comm *comms) 5854b9ad928SBarry Smith { 586dfbe8321SBarry Smith PetscErrorCode ierr; 587ada7143aSSatish Balay PC_MG **mg=0; 5884b9ad928SBarry Smith 5894b9ad928SBarry Smith PetscFunctionBegin; 5904482741eSBarry Smith PetscValidHeaderSpecific(pc,PC_COOKIE,1); 5914b9ad928SBarry Smith 5924b9ad928SBarry Smith if (pc->data) { 5931302d50aSBarry Smith SETERRQ(PETSC_ERR_ORDER,"Number levels already set for MG\n\ 59497177400SBarry Smith make sure that you call PCMGSetLevels() before KSPSetFromOptions()"); 5954b9ad928SBarry Smith } 5969dcbbd2bSBarry Smith ierr = PCMGCreate_Private(pc->comm,levels,pc,comms,&mg);CHKERRQ(ierr); 5979dcbbd2bSBarry Smith mg[0]->am = PC_MG_MULTIPLICATIVE; 5984b9ad928SBarry Smith pc->data = (void*)mg; 5994b9ad928SBarry Smith pc->ops->applyrichardson = PCApplyRichardson_MG; 6004b9ad928SBarry Smith PetscFunctionReturn(0); 6014b9ad928SBarry Smith } 6024b9ad928SBarry Smith 6034b9ad928SBarry Smith #undef __FUNCT__ 6049dcbbd2bSBarry Smith #define __FUNCT__ "PCMGGetLevels" 6054b9ad928SBarry Smith /*@ 60697177400SBarry Smith PCMGGetLevels - Gets the number of levels to use with MG. 6074b9ad928SBarry Smith 6084b9ad928SBarry Smith Not Collective 6094b9ad928SBarry Smith 6104b9ad928SBarry Smith Input Parameter: 6114b9ad928SBarry Smith . pc - the preconditioner context 6124b9ad928SBarry Smith 6134b9ad928SBarry Smith Output parameter: 6144b9ad928SBarry Smith . levels - the number of levels 6154b9ad928SBarry Smith 6164b9ad928SBarry Smith Level: advanced 6174b9ad928SBarry Smith 6184b9ad928SBarry Smith .keywords: MG, get, levels, multigrid 6194b9ad928SBarry Smith 62097177400SBarry Smith .seealso: PCMGSetLevels() 6214b9ad928SBarry Smith @*/ 62297177400SBarry Smith PetscErrorCode PETSCKSP_DLLEXPORT PCMGGetLevels(PC pc,PetscInt *levels) 6234b9ad928SBarry Smith { 6249dcbbd2bSBarry Smith PC_MG **mg; 6254b9ad928SBarry Smith 6264b9ad928SBarry Smith PetscFunctionBegin; 6274482741eSBarry Smith PetscValidHeaderSpecific(pc,PC_COOKIE,1); 6284482741eSBarry Smith PetscValidIntPointer(levels,2); 6294b9ad928SBarry Smith 6309dcbbd2bSBarry Smith mg = (PC_MG**)pc->data; 6314b9ad928SBarry Smith *levels = mg[0]->levels; 6324b9ad928SBarry Smith PetscFunctionReturn(0); 6334b9ad928SBarry Smith } 6344b9ad928SBarry Smith 6354b9ad928SBarry Smith #undef __FUNCT__ 6369dcbbd2bSBarry Smith #define __FUNCT__ "PCMGSetType" 6374b9ad928SBarry Smith /*@ 63897177400SBarry Smith PCMGSetType - Determines the form of multigrid to use: 6394b9ad928SBarry Smith multiplicative, additive, full, or the Kaskade algorithm. 6404b9ad928SBarry Smith 6414b9ad928SBarry Smith Collective on PC 6424b9ad928SBarry Smith 6434b9ad928SBarry Smith Input Parameters: 6444b9ad928SBarry Smith + pc - the preconditioner context 6459dcbbd2bSBarry Smith - form - multigrid form, one of PC_MG_MULTIPLICATIVE, PC_MG_ADDITIVE, 6469dcbbd2bSBarry Smith PC_MG_FULL, PC_MG_KASKADE 6474b9ad928SBarry Smith 6484b9ad928SBarry Smith Options Database Key: 6494b9ad928SBarry Smith . -pc_mg_type <form> - Sets <form>, one of multiplicative, 6504b9ad928SBarry Smith additive, full, kaskade 6514b9ad928SBarry Smith 6524b9ad928SBarry Smith Level: advanced 6534b9ad928SBarry Smith 6544b9ad928SBarry Smith .keywords: MG, set, method, multiplicative, additive, full, Kaskade, multigrid 6554b9ad928SBarry Smith 65697177400SBarry Smith .seealso: PCMGSetLevels() 6574b9ad928SBarry Smith @*/ 6589dcbbd2bSBarry Smith PetscErrorCode PETSCKSP_DLLEXPORT PCMGSetType(PC pc,PCMGType form) 6594b9ad928SBarry Smith { 6609dcbbd2bSBarry Smith PC_MG **mg; 6614b9ad928SBarry Smith 6624b9ad928SBarry Smith PetscFunctionBegin; 6634482741eSBarry Smith PetscValidHeaderSpecific(pc,PC_COOKIE,1); 6649dcbbd2bSBarry Smith mg = (PC_MG**)pc->data; 6654b9ad928SBarry Smith 6664b9ad928SBarry Smith if (!mg) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Must set MG levels before calling"); 6674b9ad928SBarry Smith mg[0]->am = form; 6689dcbbd2bSBarry Smith if (form == PC_MG_MULTIPLICATIVE) pc->ops->applyrichardson = PCApplyRichardson_MG; 6694b9ad928SBarry Smith else pc->ops->applyrichardson = 0; 6704b9ad928SBarry Smith PetscFunctionReturn(0); 6714b9ad928SBarry Smith } 6724b9ad928SBarry Smith 6734b9ad928SBarry Smith #undef __FUNCT__ 6740d353602SBarry Smith #define __FUNCT__ "PCMGSetCycleType" 6754b9ad928SBarry Smith /*@ 6760d353602SBarry Smith PCMGSetCycleType - Sets the type cycles to use. Use PCMGSetCycleTypeOnLevel() for more 6774b9ad928SBarry Smith complicated cycling. 6784b9ad928SBarry Smith 6794b9ad928SBarry Smith Collective on PC 6804b9ad928SBarry Smith 6814b9ad928SBarry Smith Input Parameters: 682c2be2410SBarry Smith + pc - the multigrid context 6830d353602SBarry Smith - PC_MG_CYCLE_V or PC_MG_CYCLE_W 6844b9ad928SBarry Smith 6854b9ad928SBarry Smith Options Database Key: 6860d353602SBarry Smith $ -pc_mg_cycle_type v or w 6874b9ad928SBarry Smith 6884b9ad928SBarry Smith Level: advanced 6894b9ad928SBarry Smith 6904b9ad928SBarry Smith .keywords: MG, set, cycles, V-cycle, W-cycle, multigrid 6914b9ad928SBarry Smith 6920d353602SBarry Smith .seealso: PCMGSetCycleTypeOnLevel() 6934b9ad928SBarry Smith @*/ 6940d353602SBarry Smith PetscErrorCode PETSCKSP_DLLEXPORT PCMGSetCycleType(PC pc,PCMGCycleType n) 6954b9ad928SBarry Smith { 6969dcbbd2bSBarry Smith PC_MG **mg; 69779416396SBarry Smith PetscInt i,levels; 6984b9ad928SBarry Smith 6994b9ad928SBarry Smith PetscFunctionBegin; 7004482741eSBarry Smith PetscValidHeaderSpecific(pc,PC_COOKIE,1); 7019dcbbd2bSBarry Smith mg = (PC_MG**)pc->data; 7024b9ad928SBarry Smith if (!mg) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Must set MG levels before calling"); 7034b9ad928SBarry Smith levels = mg[0]->levels; 7044b9ad928SBarry Smith 7054b9ad928SBarry Smith for (i=0; i<levels; i++) { 7064b9ad928SBarry Smith mg[i]->cycles = n; 7074b9ad928SBarry Smith } 7084b9ad928SBarry Smith PetscFunctionReturn(0); 7094b9ad928SBarry Smith } 7104b9ad928SBarry Smith 7114b9ad928SBarry Smith #undef __FUNCT__ 7128cc2d5dfSBarry Smith #define __FUNCT__ "PCMGMultiplicativeSetCycles" 7138cc2d5dfSBarry Smith /*@ 7148cc2d5dfSBarry Smith PCMGMultiplicativeSetCycles - Sets the number of cycles to use for each preconditioner step 7158cc2d5dfSBarry Smith of multigrid when PCMGType of PC_MG_MULTIPLICATIVE is used 7168cc2d5dfSBarry Smith 7178cc2d5dfSBarry Smith Collective on PC 7188cc2d5dfSBarry Smith 7198cc2d5dfSBarry Smith Input Parameters: 7208cc2d5dfSBarry Smith + pc - the multigrid context 7218cc2d5dfSBarry Smith - n - number of cycles (default is 1) 7228cc2d5dfSBarry Smith 7238cc2d5dfSBarry Smith Options Database Key: 7248cc2d5dfSBarry Smith $ -pc_mg_multiplicative_cycles n 7258cc2d5dfSBarry Smith 7268cc2d5dfSBarry Smith Level: advanced 7278cc2d5dfSBarry Smith 7288cc2d5dfSBarry Smith Notes: This is not associated with setting a v or w cycle, that is set with PCMGSetCycleType() 7298cc2d5dfSBarry Smith 7308cc2d5dfSBarry Smith .keywords: MG, set, cycles, V-cycle, W-cycle, multigrid 7318cc2d5dfSBarry Smith 7328cc2d5dfSBarry Smith .seealso: PCMGSetCycleTypeOnLevel(), PCMGSetCycleType() 7338cc2d5dfSBarry Smith @*/ 7348cc2d5dfSBarry Smith PetscErrorCode PETSCKSP_DLLEXPORT PCMGMultiplicativeSetCycles(PC pc,PetscInt n) 7358cc2d5dfSBarry Smith { 7368cc2d5dfSBarry Smith PC_MG **mg; 7378cc2d5dfSBarry Smith PetscInt i,levels; 7388cc2d5dfSBarry Smith 7398cc2d5dfSBarry Smith PetscFunctionBegin; 7408cc2d5dfSBarry Smith PetscValidHeaderSpecific(pc,PC_COOKIE,1); 7418cc2d5dfSBarry Smith mg = (PC_MG**)pc->data; 7428cc2d5dfSBarry Smith if (!mg) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Must set MG levels before calling"); 7438cc2d5dfSBarry Smith levels = mg[0]->levels; 7448cc2d5dfSBarry Smith 7458cc2d5dfSBarry Smith for (i=0; i<levels; i++) { 7468cc2d5dfSBarry Smith mg[i]->cyclesperpcapply = n; 7478cc2d5dfSBarry Smith } 7488cc2d5dfSBarry Smith PetscFunctionReturn(0); 7498cc2d5dfSBarry Smith } 7508cc2d5dfSBarry Smith 7518cc2d5dfSBarry Smith #undef __FUNCT__ 7529dcbbd2bSBarry Smith #define __FUNCT__ "PCMGSetGalerkin" 753c2be2410SBarry Smith /*@ 75497177400SBarry Smith PCMGSetGalerkin - Causes the coarser grid matrices to be computed from the 755c2be2410SBarry Smith finest grid via the Galerkin process: A_i-1 = r_i * A_i * r_i^t 756c2be2410SBarry Smith 757c2be2410SBarry Smith Collective on PC 758c2be2410SBarry Smith 759c2be2410SBarry Smith Input Parameters: 7603fc8bf9cSBarry Smith . pc - the multigrid context 761c2be2410SBarry Smith 762c2be2410SBarry Smith Options Database Key: 763c2be2410SBarry Smith $ -pc_mg_galerkin 764c2be2410SBarry Smith 765c2be2410SBarry Smith Level: intermediate 766c2be2410SBarry Smith 767c2be2410SBarry Smith .keywords: MG, set, Galerkin 768c2be2410SBarry Smith 7693fc8bf9cSBarry Smith .seealso: PCMGGetGalerkin() 7703fc8bf9cSBarry Smith 771c2be2410SBarry Smith @*/ 77297177400SBarry Smith PetscErrorCode PETSCKSP_DLLEXPORT PCMGSetGalerkin(PC pc) 773c2be2410SBarry Smith { 7749dcbbd2bSBarry Smith PC_MG **mg; 775c2be2410SBarry Smith PetscInt i,levels; 776c2be2410SBarry Smith 777c2be2410SBarry Smith PetscFunctionBegin; 778c2be2410SBarry Smith PetscValidHeaderSpecific(pc,PC_COOKIE,1); 7799dcbbd2bSBarry Smith mg = (PC_MG**)pc->data; 780c2be2410SBarry Smith if (!mg) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Must set MG levels before calling"); 781c2be2410SBarry Smith levels = mg[0]->levels; 782c2be2410SBarry Smith 783c2be2410SBarry Smith for (i=0; i<levels; i++) { 784c2be2410SBarry Smith mg[i]->galerkin = PETSC_TRUE; 785c2be2410SBarry Smith } 786c2be2410SBarry Smith PetscFunctionReturn(0); 787c2be2410SBarry Smith } 788c2be2410SBarry Smith 789c2be2410SBarry Smith #undef __FUNCT__ 7903fc8bf9cSBarry Smith #define __FUNCT__ "PCMGGetGalerkin" 7913fc8bf9cSBarry Smith /*@ 7923fc8bf9cSBarry Smith PCMGGetGalerkin - Checks if Galerkin multigrid is being used, i.e. 7933fc8bf9cSBarry Smith A_i-1 = r_i * A_i * r_i^t 7943fc8bf9cSBarry Smith 7953fc8bf9cSBarry Smith Not Collective 7963fc8bf9cSBarry Smith 7973fc8bf9cSBarry Smith Input Parameter: 7983fc8bf9cSBarry Smith . pc - the multigrid context 7993fc8bf9cSBarry Smith 8003fc8bf9cSBarry Smith Output Parameter: 8013fc8bf9cSBarry Smith . gelerkin - PETSC_TRUE or PETSC_FALSE 8023fc8bf9cSBarry Smith 8033fc8bf9cSBarry Smith Options Database Key: 8043fc8bf9cSBarry Smith $ -pc_mg_galerkin 8053fc8bf9cSBarry Smith 8063fc8bf9cSBarry Smith Level: intermediate 8073fc8bf9cSBarry Smith 8083fc8bf9cSBarry Smith .keywords: MG, set, Galerkin 8093fc8bf9cSBarry Smith 8103fc8bf9cSBarry Smith .seealso: PCMGSetGalerkin() 8113fc8bf9cSBarry Smith 8123fc8bf9cSBarry Smith @*/ 8133fc8bf9cSBarry Smith PetscErrorCode PETSCKSP_DLLEXPORT PCMGGetGalerkin(PC pc,PetscTruth *galerkin) 8143fc8bf9cSBarry Smith { 8153fc8bf9cSBarry Smith PC_MG **mg; 8163fc8bf9cSBarry Smith 8173fc8bf9cSBarry Smith PetscFunctionBegin; 8183fc8bf9cSBarry Smith PetscValidHeaderSpecific(pc,PC_COOKIE,1); 8193fc8bf9cSBarry Smith mg = (PC_MG**)pc->data; 8203fc8bf9cSBarry Smith if (!mg) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Must set MG levels before calling"); 8213fc8bf9cSBarry Smith *galerkin = mg[0]->galerkin; 8223fc8bf9cSBarry Smith PetscFunctionReturn(0); 8233fc8bf9cSBarry Smith } 8243fc8bf9cSBarry Smith 8253fc8bf9cSBarry Smith #undef __FUNCT__ 8269dcbbd2bSBarry Smith #define __FUNCT__ "PCMGSetNumberSmoothDown" 8274b9ad928SBarry Smith /*@ 82897177400SBarry Smith PCMGSetNumberSmoothDown - Sets the number of pre-smoothing steps to 82997177400SBarry Smith use on all levels. Use PCMGGetSmootherDown() to set different 8304b9ad928SBarry Smith pre-smoothing steps on different levels. 8314b9ad928SBarry Smith 8324b9ad928SBarry Smith Collective on PC 8334b9ad928SBarry Smith 8344b9ad928SBarry Smith Input Parameters: 8354b9ad928SBarry Smith + mg - the multigrid context 8364b9ad928SBarry Smith - n - the number of smoothing steps 8374b9ad928SBarry Smith 8384b9ad928SBarry Smith Options Database Key: 8394b9ad928SBarry Smith . -pc_mg_smoothdown <n> - Sets number of pre-smoothing steps 8404b9ad928SBarry Smith 8414b9ad928SBarry Smith Level: advanced 8424b9ad928SBarry Smith 8434b9ad928SBarry Smith .keywords: MG, smooth, down, pre-smoothing, steps, multigrid 8444b9ad928SBarry Smith 84597177400SBarry Smith .seealso: PCMGSetNumberSmoothUp() 8464b9ad928SBarry Smith @*/ 84797177400SBarry Smith PetscErrorCode PETSCKSP_DLLEXPORT PCMGSetNumberSmoothDown(PC pc,PetscInt n) 8484b9ad928SBarry Smith { 8499dcbbd2bSBarry Smith PC_MG **mg; 8506849ba73SBarry Smith PetscErrorCode ierr; 85179416396SBarry Smith PetscInt i,levels; 8524b9ad928SBarry Smith 8534b9ad928SBarry Smith PetscFunctionBegin; 8544482741eSBarry Smith PetscValidHeaderSpecific(pc,PC_COOKIE,1); 8559dcbbd2bSBarry Smith mg = (PC_MG**)pc->data; 8564b9ad928SBarry Smith if (!mg) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Must set MG levels before calling"); 8574b9ad928SBarry Smith levels = mg[0]->levels; 8584b9ad928SBarry Smith 859b05257ddSBarry Smith for (i=1; i<levels; i++) { 8604b9ad928SBarry Smith /* make sure smoother up and down are different */ 86197177400SBarry Smith ierr = PCMGGetSmootherUp(pc,i,PETSC_NULL);CHKERRQ(ierr); 8624b9ad928SBarry Smith ierr = KSPSetTolerances(mg[i]->smoothd,PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT,n);CHKERRQ(ierr); 8634b9ad928SBarry Smith mg[i]->default_smoothd = n; 8644b9ad928SBarry Smith } 8654b9ad928SBarry Smith PetscFunctionReturn(0); 8664b9ad928SBarry Smith } 8674b9ad928SBarry Smith 8684b9ad928SBarry Smith #undef __FUNCT__ 8699dcbbd2bSBarry Smith #define __FUNCT__ "PCMGSetNumberSmoothUp" 8704b9ad928SBarry Smith /*@ 87197177400SBarry Smith PCMGSetNumberSmoothUp - Sets the number of post-smoothing steps to use 87297177400SBarry Smith on all levels. Use PCMGGetSmootherUp() to set different numbers of 8734b9ad928SBarry Smith post-smoothing steps on different levels. 8744b9ad928SBarry Smith 8754b9ad928SBarry Smith Collective on PC 8764b9ad928SBarry Smith 8774b9ad928SBarry Smith Input Parameters: 8784b9ad928SBarry Smith + mg - the multigrid context 8794b9ad928SBarry Smith - n - the number of smoothing steps 8804b9ad928SBarry Smith 8814b9ad928SBarry Smith Options Database Key: 8824b9ad928SBarry Smith . -pc_mg_smoothup <n> - Sets number of post-smoothing steps 8834b9ad928SBarry Smith 8844b9ad928SBarry Smith Level: advanced 8854b9ad928SBarry Smith 8864b9ad928SBarry Smith Note: this does not set a value on the coarsest grid, since we assume that 887a8c7a070SBarry Smith there is no separate smooth up on the coarsest grid. 8884b9ad928SBarry Smith 8894b9ad928SBarry Smith .keywords: MG, smooth, up, post-smoothing, steps, multigrid 8904b9ad928SBarry Smith 89197177400SBarry Smith .seealso: PCMGSetNumberSmoothDown() 8924b9ad928SBarry Smith @*/ 89397177400SBarry Smith PetscErrorCode PETSCKSP_DLLEXPORT PCMGSetNumberSmoothUp(PC pc,PetscInt n) 8944b9ad928SBarry Smith { 8959dcbbd2bSBarry Smith PC_MG **mg; 8966849ba73SBarry Smith PetscErrorCode ierr; 89779416396SBarry Smith PetscInt i,levels; 8984b9ad928SBarry Smith 8994b9ad928SBarry Smith PetscFunctionBegin; 9004482741eSBarry Smith PetscValidHeaderSpecific(pc,PC_COOKIE,1); 9019dcbbd2bSBarry Smith mg = (PC_MG**)pc->data; 9024b9ad928SBarry Smith if (!mg) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Must set MG levels before calling"); 9034b9ad928SBarry Smith levels = mg[0]->levels; 9044b9ad928SBarry Smith 9054b9ad928SBarry Smith for (i=1; i<levels; i++) { 9064b9ad928SBarry Smith /* make sure smoother up and down are different */ 90797177400SBarry Smith ierr = PCMGGetSmootherUp(pc,i,PETSC_NULL);CHKERRQ(ierr); 9084b9ad928SBarry Smith ierr = KSPSetTolerances(mg[i]->smoothu,PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT,n);CHKERRQ(ierr); 9094b9ad928SBarry Smith mg[i]->default_smoothu = n; 9104b9ad928SBarry Smith } 9114b9ad928SBarry Smith PetscFunctionReturn(0); 9124b9ad928SBarry Smith } 9134b9ad928SBarry Smith 9144b9ad928SBarry Smith /* ----------------------------------------------------------------------------------------*/ 9154b9ad928SBarry Smith 9163b09bd56SBarry Smith /*MC 917ccb205f8SBarry Smith PCMG - Use multigrid preconditioning. This preconditioner requires you provide additional 9183b09bd56SBarry Smith information about the coarser grid matrices and restriction/interpolation operators. 9193b09bd56SBarry Smith 9203b09bd56SBarry Smith Options Database Keys: 9213b09bd56SBarry Smith + -pc_mg_levels <nlevels> - number of levels including finest 9220d353602SBarry Smith . -pc_mg_cycles v or w 92379416396SBarry Smith . -pc_mg_smoothup <n> - number of smoothing steps after interpolation 9243b09bd56SBarry Smith . -pc_mg_smoothdown <n> - number of smoothing steps before applying restriction operator 9253b09bd56SBarry Smith . -pc_mg_type <additive,multiplicative,full,cascade> - multiplicative is the default 9263b09bd56SBarry Smith . -pc_mg_log - log information about time spent on each level of the solver 9273b09bd56SBarry Smith . -pc_mg_monitor - print information on the multigrid convergence 92868eff7e6SBarry Smith . -pc_mg_galerkin - use Galerkin process to compute coarser operators 9293b09bd56SBarry Smith - -pc_mg_dump_matlab - dumps the matrices for each level and the restriction/interpolation matrices 9303b09bd56SBarry Smith to the Socket viewer for reading from Matlab. 9313b09bd56SBarry Smith 9323b09bd56SBarry Smith Notes: 9333b09bd56SBarry Smith 9343b09bd56SBarry Smith Level: intermediate 9353b09bd56SBarry Smith 9368f87f92bSBarry Smith Concepts: multigrid/multilevel 9373b09bd56SBarry Smith 9383b09bd56SBarry Smith .seealso: PCCreate(), PCSetType(), PCType (for list of available types), PC, PCMGType, 9390d353602SBarry Smith PCMGSetLevels(), PCMGGetLevels(), PCMGSetType(), PCMGSetCycleType(), PCMGSetNumberSmoothDown(), 94097177400SBarry Smith PCMGSetNumberSmoothUp(), PCMGGetCoarseSolve(), PCMGSetResidual(), PCMGSetInterpolation(), 94197177400SBarry Smith PCMGSetRestriction(), PCMGGetSmoother(), PCMGGetSmootherUp(), PCMGGetSmootherDown(), 9420d353602SBarry Smith PCMGSetCycleTypeOnLevel(), PCMGSetRhs(), PCMGSetX(), PCMGSetR() 9433b09bd56SBarry Smith M*/ 9443b09bd56SBarry Smith 9454b9ad928SBarry Smith EXTERN_C_BEGIN 9464b9ad928SBarry Smith #undef __FUNCT__ 9474b9ad928SBarry Smith #define __FUNCT__ "PCCreate_MG" 948dba47a55SKris Buschelman PetscErrorCode PETSCKSP_DLLEXPORT PCCreate_MG(PC pc) 9494b9ad928SBarry Smith { 9504b9ad928SBarry Smith PetscFunctionBegin; 9514b9ad928SBarry Smith pc->ops->apply = PCApply_MG; 9524b9ad928SBarry Smith pc->ops->setup = PCSetUp_MG; 9534b9ad928SBarry Smith pc->ops->destroy = PCDestroy_MG; 9544b9ad928SBarry Smith pc->ops->setfromoptions = PCSetFromOptions_MG; 9554b9ad928SBarry Smith pc->ops->view = PCView_MG; 9564b9ad928SBarry Smith 9574b9ad928SBarry Smith pc->data = (void*)0; 9584b9ad928SBarry Smith PetscFunctionReturn(0); 9594b9ad928SBarry Smith } 9604b9ad928SBarry Smith EXTERN_C_END 961