xref: /petsc/src/ksp/pc/impls/mg/mg.c (revision 32cf17861994f4b329954fe70b634d0bfe79b198)
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 
20*32cf1786SBarry 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 */
22*32cf1786SBarry Smith   if (mg->eventsmoothsolve) {ierr = PetscLogEventEnd(mg->eventsmoothsolve,0,0,0,0);CHKERRQ(ierr);}
234b9ad928SBarry Smith   if (mg->level) {  /* not the coarsest grid */
24*32cf1786SBarry 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);
26*32cf1786SBarry 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);
44*32cf1786SBarry 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);
46*32cf1786SBarry 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     }
51*32cf1786SBarry 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);
53*32cf1786SBarry Smith     if (mg->eventinterprestrict) {ierr = PetscLogEventEnd(mg->eventinterprestrict,0,0,0,0);CHKERRQ(ierr);}
54*32cf1786SBarry 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 */
56*32cf1786SBarry 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;
124*32cf1786SBarry Smith     mg[i]->eventsmoothsetup    = 0;
125*32cf1786SBarry Smith     mg[i]->eventsmoothsolve    = 0;
126*32cf1786SBarry Smith     mg[i]->eventresidual       = 0;
127*32cf1786SBarry 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++) {
296*32cf1786SBarry Smith         sprintf(eventname,"MGSetup Level %d",(int)i);
297*32cf1786SBarry Smith         ierr = PetscLogEventRegister(&mg[i]->eventsmoothsetup,eventname,pc->cookie);CHKERRQ(ierr);
298*32cf1786SBarry Smith         sprintf(eventname,"MGSmooth Level %d",(int)i);
299*32cf1786SBarry Smith         ierr = PetscLogEventRegister(&mg[i]->eventsmoothsolve,eventname,pc->cookie);CHKERRQ(ierr);
300*32cf1786SBarry Smith         if (i) {
301*32cf1786SBarry Smith           sprintf(eventname,"MGResid Level %d",(int)i);
302*32cf1786SBarry Smith           ierr = PetscLogEventRegister(&mg[i]->eventresidual,eventname,pc->cookie);CHKERRQ(ierr);
303*32cf1786SBarry Smith           sprintf(eventname,"MGInterp Level %d",(int)i);
304*32cf1786SBarry Smith           ierr = PetscLogEventRegister(&mg[i]->eventinterprestrict,eventname,pc->cookie);CHKERRQ(ierr);
305*32cf1786SBarry 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;
3674b9ad928SBarry Smith   PC                      cpc;
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);
38343fb2f97SBarry Smith   if (!opsset || cpc->setupcalled == 2) {
384852665d3SBarry 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);
3851cfe3bddSBarry Smith     ierr = KSPSetOperators(mg[n-1]->smoothd,pc->mat,pc->pmat,pc->flag);CHKERRQ(ierr);
386852665d3SBarry Smith   }
387852665d3SBarry Smith 
388852665d3SBarry Smith   if (mg[0]->galerkin) {
389852665d3SBarry Smith     Mat B;
390852665d3SBarry Smith     mg[0]->galerkinused = PETSC_TRUE;
391852665d3SBarry Smith     /* currently only handle case where mat and pmat are the same on coarser levels */
392852665d3SBarry Smith     ierr = KSPGetOperators(mg[n-1]->smoothd,&dA,&dB,&uflag);CHKERRQ(ierr);
393852665d3SBarry Smith     if (!pc->setupcalled) {
394852665d3SBarry Smith       for (i=n-2; i>-1; i--) {
395852665d3SBarry Smith         ierr = MatPtAP(dB,mg[i+1]->interpolate,MAT_INITIAL_MATRIX,1.0,&B);CHKERRQ(ierr);
396852665d3SBarry Smith         ierr = KSPSetOperators(mg[i]->smoothd,B,B,uflag);CHKERRQ(ierr);
397906ed7ccSBarry Smith 	if (i != n-2) {ierr = PetscObjectDereference((PetscObject)dB);CHKERRQ(ierr);}
398852665d3SBarry Smith         dB   = B;
399852665d3SBarry Smith       }
400906ed7ccSBarry Smith       ierr = PetscObjectDereference((PetscObject)dB);CHKERRQ(ierr);
401852665d3SBarry Smith     } else {
402852665d3SBarry Smith       for (i=n-2; i>-1; i--) {
403906ed7ccSBarry Smith         ierr = KSPGetOperators(mg[i]->smoothd,PETSC_NULL,&B,PETSC_NULL);CHKERRQ(ierr);
404852665d3SBarry Smith         ierr = MatPtAP(dB,mg[i+1]->interpolate,MAT_REUSE_MATRIX,1.0,&B);CHKERRQ(ierr);
405852665d3SBarry Smith         ierr = KSPSetOperators(mg[i]->smoothd,B,B,uflag);CHKERRQ(ierr);
406852665d3SBarry Smith         dB   = B;
407852665d3SBarry Smith       }
408852665d3SBarry Smith     }
409852665d3SBarry Smith   }
410852665d3SBarry Smith 
411958c9bccSBarry Smith   if (!pc->setupcalled) {
4124b9ad928SBarry Smith     ierr = PetscOptionsHasName(0,"-pc_mg_monitor",&monitor);CHKERRQ(ierr);
4134b9ad928SBarry Smith 
414b03c7568SBarry Smith     for (i=0; i<n; i++) {
4154b9ad928SBarry Smith       if (monitor) {
4164b9ad928SBarry Smith         ierr = PetscObjectGetComm((PetscObject)mg[i]->smoothd,&comm);CHKERRQ(ierr);
41723d894e5SBarry Smith         ierr = PetscViewerASCIIMonitorCreate(comm,"stdout",n-i,&ascii);CHKERRQ(ierr);
41823d894e5SBarry Smith         ierr = KSPMonitorSet(mg[i]->smoothd,KSPMonitorDefault,ascii,(PetscErrorCode(*)(void*))PetscViewerASCIIMonitorDestroy);CHKERRQ(ierr);
4194b9ad928SBarry Smith       }
4204b9ad928SBarry Smith       ierr = KSPSetFromOptions(mg[i]->smoothd);CHKERRQ(ierr);
4214b9ad928SBarry Smith     }
422b03c7568SBarry Smith     for (i=1; i<n; i++) {
423a98fc643SBarry Smith       if (mg[i]->smoothu && (mg[i]->smoothu != mg[i]->smoothd)) {
4244b9ad928SBarry Smith         if (monitor) {
4254b9ad928SBarry Smith           ierr = PetscObjectGetComm((PetscObject)mg[i]->smoothu,&comm);CHKERRQ(ierr);
42623d894e5SBarry Smith           ierr = PetscViewerASCIIMonitorCreate(comm,"stdout",n-i,&ascii);CHKERRQ(ierr);
42723d894e5SBarry Smith           ierr = KSPMonitorSet(mg[i]->smoothu,KSPMonitorDefault,ascii,(PetscErrorCode(*)(void*))PetscViewerASCIIMonitorDestroy);CHKERRQ(ierr);
4284b9ad928SBarry Smith         }
4294b9ad928SBarry Smith         ierr = KSPSetFromOptions(mg[i]->smoothu);CHKERRQ(ierr);
4304b9ad928SBarry Smith       }
4314b9ad928SBarry Smith     }
432fccaa45eSBarry Smith     for (i=1; i<n; i++) {
4330cace4b0SBarry Smith       if (!mg[i]->residual) {
4340cace4b0SBarry Smith         Mat mat;
4350cace4b0SBarry Smith         ierr = KSPGetOperators(mg[i]->smoothd,PETSC_NULL,&mat,PETSC_NULL);CHKERRQ(ierr);
4360cace4b0SBarry Smith         ierr = PCMGSetResidual(pc,i,PCMGDefaultResidual,mat);CHKERRQ(ierr);
4370cace4b0SBarry Smith       }
438fccaa45eSBarry Smith       if (mg[i]->restrct && !mg[i]->interpolate) {
43997177400SBarry Smith         ierr = PCMGSetInterpolate(pc,i,mg[i]->restrct);CHKERRQ(ierr);
440fccaa45eSBarry Smith       }
441fccaa45eSBarry Smith       if (!mg[i]->restrct && mg[i]->interpolate) {
44297177400SBarry Smith         ierr = PCMGSetRestriction(pc,i,mg[i]->interpolate);CHKERRQ(ierr);
443fccaa45eSBarry Smith       }
444fccaa45eSBarry Smith #if defined(PETSC_USE_DEBUG)
445fccaa45eSBarry Smith       if (!mg[i]->restrct || !mg[i]->interpolate) {
446fccaa45eSBarry Smith         SETERRQ1(PETSC_ERR_ARG_WRONGSTATE,"Need to set restriction or interpolation on level %d",(int)i);
447fccaa45eSBarry Smith       }
448fccaa45eSBarry Smith #endif
449fccaa45eSBarry Smith     }
4500a6bb862SBarry Smith     for (i=0; i<n-1; i++) {
45137b0e6c0SBarry Smith       if (!mg[i]->b) {
452906ed7ccSBarry Smith         Vec *vec;
453906ed7ccSBarry Smith         ierr = KSPGetVecs(mg[i]->smoothd,1,&vec,0,PETSC_NULL);CHKERRQ(ierr);
454906ed7ccSBarry Smith         ierr = PCMGSetRhs(pc,i,*vec);CHKERRQ(ierr);
455906ed7ccSBarry Smith         ierr = PetscFree(vec);CHKERRQ(ierr);
45637b0e6c0SBarry Smith       }
4576ca4d86aSHong Zhang       if (!mg[i]->r && i) {
4580a6bb862SBarry Smith         ierr = VecDuplicate(mg[i]->b,&tvec);CHKERRQ(ierr);
45997177400SBarry Smith         ierr = PCMGSetR(pc,i,tvec);CHKERRQ(ierr);
4600a6bb862SBarry Smith         ierr = VecDestroy(tvec);CHKERRQ(ierr);
4610a6bb862SBarry Smith       }
4620a6bb862SBarry Smith       if (!mg[i]->x) {
4630a6bb862SBarry Smith         ierr = VecDuplicate(mg[i]->b,&tvec);CHKERRQ(ierr);
46497177400SBarry Smith         ierr = PCMGSetX(pc,i,tvec);CHKERRQ(ierr);
4650a6bb862SBarry Smith         ierr = VecDestroy(tvec);CHKERRQ(ierr);
4660a6bb862SBarry Smith       }
4670a6bb862SBarry Smith     }
4684b9ad928SBarry Smith   }
4694b9ad928SBarry Smith 
470c2be2410SBarry Smith 
4714b9ad928SBarry Smith   for (i=1; i<n; i++) {
472b03c7568SBarry Smith     if (mg[i]->smoothu == mg[i]->smoothd) {
473b03c7568SBarry Smith       /* if doing only down then initial guess is zero */
4744b9ad928SBarry Smith       ierr = KSPSetInitialGuessNonzero(mg[i]->smoothd,PETSC_TRUE);CHKERRQ(ierr);
475b03c7568SBarry Smith     }
476*32cf1786SBarry Smith     if (mg[i]->eventsmoothsetup) {ierr = PetscLogEventBegin(mg[i]->eventsmoothsetup,0,0,0,0);CHKERRQ(ierr);}
4774b9ad928SBarry Smith     ierr = KSPSetUp(mg[i]->smoothd);CHKERRQ(ierr);
478*32cf1786SBarry Smith     if (mg[i]->eventsmoothsetup) {ierr = PetscLogEventEnd(mg[i]->eventsmoothsetup,0,0,0,0);CHKERRQ(ierr);}
4794b9ad928SBarry Smith   }
480b03c7568SBarry Smith   for (i=1; i<n; i++) {
4814b9ad928SBarry Smith     if (mg[i]->smoothu && mg[i]->smoothu != mg[i]->smoothd) {
482906ed7ccSBarry Smith       Mat          downmat,downpmat;
48397f1f81fSBarry Smith       MatStructure matflag;
484906ed7ccSBarry Smith       PetscTruth   opsset;
48597f1f81fSBarry Smith 
48697f1f81fSBarry Smith       /* check if operators have been set for up, if not use down operators to set them */
487906ed7ccSBarry Smith       ierr = KSPGetOperatorsSet(mg[i]->smoothu,&opsset,PETSC_NULL);CHKERRQ(ierr);
488906ed7ccSBarry Smith       if (!opsset) {
489906ed7ccSBarry Smith         ierr = KSPGetOperators(mg[i]->smoothd,&downmat,&downpmat,&matflag);CHKERRQ(ierr);
49097f1f81fSBarry Smith         ierr = KSPSetOperators(mg[i]->smoothu,downmat,downpmat,matflag);CHKERRQ(ierr);
49197f1f81fSBarry Smith       }
49297f1f81fSBarry Smith 
4934b9ad928SBarry Smith       ierr = KSPSetInitialGuessNonzero(mg[i]->smoothu,PETSC_TRUE);CHKERRQ(ierr);
494*32cf1786SBarry Smith       if (mg[i]->eventsmoothsetup) {ierr = PetscLogEventBegin(mg[i]->eventsmoothsetup,0,0,0,0);CHKERRQ(ierr);}
4954b9ad928SBarry Smith       ierr = KSPSetUp(mg[i]->smoothu);CHKERRQ(ierr);
496*32cf1786SBarry Smith       if (mg[i]->eventsmoothsetup) {ierr = PetscLogEventEnd(mg[i]->eventsmoothsetup,0,0,0,0);CHKERRQ(ierr);}
4974b9ad928SBarry Smith     }
4984b9ad928SBarry Smith   }
4994b9ad928SBarry Smith 
5004b9ad928SBarry Smith   /*
5014b9ad928SBarry Smith       If coarse solver is not direct method then DO NOT USE preonly
5024b9ad928SBarry Smith   */
5034b9ad928SBarry Smith   ierr = PetscTypeCompare((PetscObject)mg[0]->smoothd,KSPPREONLY,&preonly);CHKERRQ(ierr);
5044b9ad928SBarry Smith   if (preonly) {
5054b9ad928SBarry Smith     ierr = PetscTypeCompare((PetscObject)cpc,PCLU,&lu);CHKERRQ(ierr);
5064b9ad928SBarry Smith     ierr = PetscTypeCompare((PetscObject)cpc,PCREDUNDANT,&redundant);CHKERRQ(ierr);
50768eff7e6SBarry Smith     ierr = PetscTypeCompare((PetscObject)cpc,PCCHOLESKY,&cholesky);CHKERRQ(ierr);
50868eff7e6SBarry Smith     if (!lu && !redundant && !cholesky) {
5094b9ad928SBarry Smith       ierr = KSPSetType(mg[0]->smoothd,KSPGMRES);CHKERRQ(ierr);
5104b9ad928SBarry Smith     }
5114b9ad928SBarry Smith   }
5124b9ad928SBarry Smith 
513958c9bccSBarry Smith   if (!pc->setupcalled) {
5144b9ad928SBarry Smith     if (monitor) {
5154b9ad928SBarry Smith       ierr = PetscObjectGetComm((PetscObject)mg[0]->smoothd,&comm);CHKERRQ(ierr);
51623d894e5SBarry Smith       ierr = PetscViewerASCIIMonitorCreate(comm,"stdout",n,&ascii);CHKERRQ(ierr);
51723d894e5SBarry Smith       ierr = KSPMonitorSet(mg[0]->smoothd,KSPMonitorDefault,ascii,(PetscErrorCode(*)(void*))PetscViewerASCIIMonitorDestroy);CHKERRQ(ierr);
5184b9ad928SBarry Smith     }
5194b9ad928SBarry Smith     ierr = KSPSetFromOptions(mg[0]->smoothd);CHKERRQ(ierr);
5204b9ad928SBarry Smith   }
5214b9ad928SBarry Smith 
522*32cf1786SBarry Smith   if (mg[0]->eventsmoothsetup) {ierr = PetscLogEventBegin(mg[0]->eventsmoothsetup,0,0,0,0);CHKERRQ(ierr);}
5234b9ad928SBarry Smith   ierr = KSPSetUp(mg[0]->smoothd);CHKERRQ(ierr);
524*32cf1786SBarry Smith   if (mg[0]->eventsmoothsetup) {ierr = PetscLogEventEnd(mg[0]->eventsmoothsetup,0,0,0,0);CHKERRQ(ierr);}
5254b9ad928SBarry Smith 
5264b9ad928SBarry Smith   /*
5276805f65bSBarry Smith      Dump the interpolation/restriction matrices plus the
5284b9ad928SBarry Smith    Jacobian/stiffness on each level. This allows Matlab users to
5296805f65bSBarry Smith    easily check if the Galerkin condition A_c = R A_f R^T is satisfied.
5306805f65bSBarry Smith 
5316805f65bSBarry Smith    Only support one or the other at the same time.
5326805f65bSBarry Smith   */
5336805f65bSBarry Smith #if defined(PETSC_USE_SOCKET_VIEWER)
5344b9ad928SBarry Smith   ierr = PetscOptionsHasName(pc->prefix,"-pc_mg_dump_matlab",&dump);CHKERRQ(ierr);
5354b9ad928SBarry Smith   if (dump) {
5366805f65bSBarry Smith     viewer = PETSC_VIEWER_SOCKET_(pc->comm);
5374b9ad928SBarry Smith   }
538c45a1595SBarry Smith #endif
539c2be2410SBarry Smith   ierr = PetscOptionsHasName(pc->prefix,"-pc_mg_dump_binary",&dump);CHKERRQ(ierr);
540c2be2410SBarry Smith   if (dump) {
5416805f65bSBarry Smith     viewer = PETSC_VIEWER_BINARY_(pc->comm);
5426805f65bSBarry Smith   }
5436805f65bSBarry Smith 
5446805f65bSBarry Smith   if (viewer) {
545c2be2410SBarry Smith     for (i=1; i<n; i++) {
5466805f65bSBarry Smith       ierr = MatView(mg[i]->restrct,viewer);CHKERRQ(ierr);
547c2be2410SBarry Smith     }
548c2be2410SBarry Smith     for (i=0; i<n; i++) {
549c2be2410SBarry Smith       ierr = KSPGetPC(mg[i]->smoothd,&pc);CHKERRQ(ierr);
5506805f65bSBarry Smith       ierr = MatView(pc->mat,viewer);CHKERRQ(ierr);
551c2be2410SBarry Smith     }
552c2be2410SBarry Smith   }
5534b9ad928SBarry Smith   PetscFunctionReturn(0);
5544b9ad928SBarry Smith }
5554b9ad928SBarry Smith 
5564b9ad928SBarry Smith /* -------------------------------------------------------------------------------------*/
5574b9ad928SBarry Smith 
5584b9ad928SBarry Smith #undef __FUNCT__
5599dcbbd2bSBarry Smith #define __FUNCT__ "PCMGSetLevels"
5604b9ad928SBarry Smith /*@C
56197177400SBarry Smith    PCMGSetLevels - Sets the number of levels to use with MG.
5624b9ad928SBarry Smith    Must be called before any other MG routine.
5634b9ad928SBarry Smith 
5644b9ad928SBarry Smith    Collective on PC
5654b9ad928SBarry Smith 
5664b9ad928SBarry Smith    Input Parameters:
5674b9ad928SBarry Smith +  pc - the preconditioner context
5684b9ad928SBarry Smith .  levels - the number of levels
5694b9ad928SBarry Smith -  comms - optional communicators for each level; this is to allow solving the coarser problems
5704b9ad928SBarry Smith            on smaller sets of processors. Use PETSC_NULL_OBJECT for default in Fortran
5714b9ad928SBarry Smith 
5724b9ad928SBarry Smith    Level: intermediate
5734b9ad928SBarry Smith 
5744b9ad928SBarry Smith    Notes:
5754b9ad928SBarry Smith      If the number of levels is one then the multigrid uses the -mg_levels prefix
5764b9ad928SBarry Smith   for setting the level options rather than the -mg_coarse prefix.
5774b9ad928SBarry Smith 
5784b9ad928SBarry Smith .keywords: MG, set, levels, multigrid
5794b9ad928SBarry Smith 
58097177400SBarry Smith .seealso: PCMGSetType(), PCMGGetLevels()
5814b9ad928SBarry Smith @*/
58297177400SBarry Smith PetscErrorCode PETSCKSP_DLLEXPORT PCMGSetLevels(PC pc,PetscInt levels,MPI_Comm *comms)
5834b9ad928SBarry Smith {
584dfbe8321SBarry Smith   PetscErrorCode ierr;
585ada7143aSSatish Balay   PC_MG          **mg=0;
5864b9ad928SBarry Smith 
5874b9ad928SBarry Smith   PetscFunctionBegin;
5884482741eSBarry Smith   PetscValidHeaderSpecific(pc,PC_COOKIE,1);
5894b9ad928SBarry Smith 
5904b9ad928SBarry Smith   if (pc->data) {
5911302d50aSBarry Smith     SETERRQ(PETSC_ERR_ORDER,"Number levels already set for MG\n\
59297177400SBarry Smith     make sure that you call PCMGSetLevels() before KSPSetFromOptions()");
5934b9ad928SBarry Smith   }
5949dcbbd2bSBarry Smith   ierr                     = PCMGCreate_Private(pc->comm,levels,pc,comms,&mg);CHKERRQ(ierr);
5959dcbbd2bSBarry Smith   mg[0]->am                = PC_MG_MULTIPLICATIVE;
5964b9ad928SBarry Smith   pc->data                 = (void*)mg;
5974b9ad928SBarry Smith   pc->ops->applyrichardson = PCApplyRichardson_MG;
5984b9ad928SBarry Smith   PetscFunctionReturn(0);
5994b9ad928SBarry Smith }
6004b9ad928SBarry Smith 
6014b9ad928SBarry Smith #undef __FUNCT__
6029dcbbd2bSBarry Smith #define __FUNCT__ "PCMGGetLevels"
6034b9ad928SBarry Smith /*@
60497177400SBarry Smith    PCMGGetLevels - Gets the number of levels to use with MG.
6054b9ad928SBarry Smith 
6064b9ad928SBarry Smith    Not Collective
6074b9ad928SBarry Smith 
6084b9ad928SBarry Smith    Input Parameter:
6094b9ad928SBarry Smith .  pc - the preconditioner context
6104b9ad928SBarry Smith 
6114b9ad928SBarry Smith    Output parameter:
6124b9ad928SBarry Smith .  levels - the number of levels
6134b9ad928SBarry Smith 
6144b9ad928SBarry Smith    Level: advanced
6154b9ad928SBarry Smith 
6164b9ad928SBarry Smith .keywords: MG, get, levels, multigrid
6174b9ad928SBarry Smith 
61897177400SBarry Smith .seealso: PCMGSetLevels()
6194b9ad928SBarry Smith @*/
62097177400SBarry Smith PetscErrorCode PETSCKSP_DLLEXPORT PCMGGetLevels(PC pc,PetscInt *levels)
6214b9ad928SBarry Smith {
6229dcbbd2bSBarry Smith   PC_MG  **mg;
6234b9ad928SBarry Smith 
6244b9ad928SBarry Smith   PetscFunctionBegin;
6254482741eSBarry Smith   PetscValidHeaderSpecific(pc,PC_COOKIE,1);
6264482741eSBarry Smith   PetscValidIntPointer(levels,2);
6274b9ad928SBarry Smith 
6289dcbbd2bSBarry Smith   mg      = (PC_MG**)pc->data;
6294b9ad928SBarry Smith   *levels = mg[0]->levels;
6304b9ad928SBarry Smith   PetscFunctionReturn(0);
6314b9ad928SBarry Smith }
6324b9ad928SBarry Smith 
6334b9ad928SBarry Smith #undef __FUNCT__
6349dcbbd2bSBarry Smith #define __FUNCT__ "PCMGSetType"
6354b9ad928SBarry Smith /*@
63697177400SBarry Smith    PCMGSetType - Determines the form of multigrid to use:
6374b9ad928SBarry Smith    multiplicative, additive, full, or the Kaskade algorithm.
6384b9ad928SBarry Smith 
6394b9ad928SBarry Smith    Collective on PC
6404b9ad928SBarry Smith 
6414b9ad928SBarry Smith    Input Parameters:
6424b9ad928SBarry Smith +  pc - the preconditioner context
6439dcbbd2bSBarry Smith -  form - multigrid form, one of PC_MG_MULTIPLICATIVE, PC_MG_ADDITIVE,
6449dcbbd2bSBarry Smith    PC_MG_FULL, PC_MG_KASKADE
6454b9ad928SBarry Smith 
6464b9ad928SBarry Smith    Options Database Key:
6474b9ad928SBarry Smith .  -pc_mg_type <form> - Sets <form>, one of multiplicative,
6484b9ad928SBarry Smith    additive, full, kaskade
6494b9ad928SBarry Smith 
6504b9ad928SBarry Smith    Level: advanced
6514b9ad928SBarry Smith 
6524b9ad928SBarry Smith .keywords: MG, set, method, multiplicative, additive, full, Kaskade, multigrid
6534b9ad928SBarry Smith 
65497177400SBarry Smith .seealso: PCMGSetLevels()
6554b9ad928SBarry Smith @*/
6569dcbbd2bSBarry Smith PetscErrorCode PETSCKSP_DLLEXPORT PCMGSetType(PC pc,PCMGType form)
6574b9ad928SBarry Smith {
6589dcbbd2bSBarry Smith   PC_MG **mg;
6594b9ad928SBarry Smith 
6604b9ad928SBarry Smith   PetscFunctionBegin;
6614482741eSBarry Smith   PetscValidHeaderSpecific(pc,PC_COOKIE,1);
6629dcbbd2bSBarry Smith   mg = (PC_MG**)pc->data;
6634b9ad928SBarry Smith 
6644b9ad928SBarry Smith   if (!mg) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Must set MG levels before calling");
6654b9ad928SBarry Smith   mg[0]->am = form;
6669dcbbd2bSBarry Smith   if (form == PC_MG_MULTIPLICATIVE) pc->ops->applyrichardson = PCApplyRichardson_MG;
6674b9ad928SBarry Smith   else pc->ops->applyrichardson = 0;
6684b9ad928SBarry Smith   PetscFunctionReturn(0);
6694b9ad928SBarry Smith }
6704b9ad928SBarry Smith 
6714b9ad928SBarry Smith #undef __FUNCT__
6720d353602SBarry Smith #define __FUNCT__ "PCMGSetCycleType"
6734b9ad928SBarry Smith /*@
6740d353602SBarry Smith    PCMGSetCycleType - Sets the type cycles to use.  Use PCMGSetCycleTypeOnLevel() for more
6754b9ad928SBarry Smith    complicated cycling.
6764b9ad928SBarry Smith 
6774b9ad928SBarry Smith    Collective on PC
6784b9ad928SBarry Smith 
6794b9ad928SBarry Smith    Input Parameters:
680c2be2410SBarry Smith +  pc - the multigrid context
6810d353602SBarry Smith -  PC_MG_CYCLE_V or PC_MG_CYCLE_W
6824b9ad928SBarry Smith 
6834b9ad928SBarry Smith    Options Database Key:
6840d353602SBarry Smith $  -pc_mg_cycle_type v or w
6854b9ad928SBarry Smith 
6864b9ad928SBarry Smith    Level: advanced
6874b9ad928SBarry Smith 
6884b9ad928SBarry Smith .keywords: MG, set, cycles, V-cycle, W-cycle, multigrid
6894b9ad928SBarry Smith 
6900d353602SBarry Smith .seealso: PCMGSetCycleTypeOnLevel()
6914b9ad928SBarry Smith @*/
6920d353602SBarry Smith PetscErrorCode PETSCKSP_DLLEXPORT PCMGSetCycleType(PC pc,PCMGCycleType n)
6934b9ad928SBarry Smith {
6949dcbbd2bSBarry Smith   PC_MG    **mg;
69579416396SBarry Smith   PetscInt i,levels;
6964b9ad928SBarry Smith 
6974b9ad928SBarry Smith   PetscFunctionBegin;
6984482741eSBarry Smith   PetscValidHeaderSpecific(pc,PC_COOKIE,1);
6999dcbbd2bSBarry Smith   mg     = (PC_MG**)pc->data;
7004b9ad928SBarry Smith   if (!mg) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Must set MG levels before calling");
7014b9ad928SBarry Smith   levels = mg[0]->levels;
7024b9ad928SBarry Smith 
7034b9ad928SBarry Smith   for (i=0; i<levels; i++) {
7044b9ad928SBarry Smith     mg[i]->cycles  = n;
7054b9ad928SBarry Smith   }
7064b9ad928SBarry Smith   PetscFunctionReturn(0);
7074b9ad928SBarry Smith }
7084b9ad928SBarry Smith 
7094b9ad928SBarry Smith #undef __FUNCT__
7108cc2d5dfSBarry Smith #define __FUNCT__ "PCMGMultiplicativeSetCycles"
7118cc2d5dfSBarry Smith /*@
7128cc2d5dfSBarry Smith    PCMGMultiplicativeSetCycles - Sets the number of cycles to use for each preconditioner step
7138cc2d5dfSBarry Smith          of multigrid when PCMGType of PC_MG_MULTIPLICATIVE is used
7148cc2d5dfSBarry Smith 
7158cc2d5dfSBarry Smith    Collective on PC
7168cc2d5dfSBarry Smith 
7178cc2d5dfSBarry Smith    Input Parameters:
7188cc2d5dfSBarry Smith +  pc - the multigrid context
7198cc2d5dfSBarry Smith -  n - number of cycles (default is 1)
7208cc2d5dfSBarry Smith 
7218cc2d5dfSBarry Smith    Options Database Key:
7228cc2d5dfSBarry Smith $  -pc_mg_multiplicative_cycles n
7238cc2d5dfSBarry Smith 
7248cc2d5dfSBarry Smith    Level: advanced
7258cc2d5dfSBarry Smith 
7268cc2d5dfSBarry Smith    Notes: This is not associated with setting a v or w cycle, that is set with PCMGSetCycleType()
7278cc2d5dfSBarry Smith 
7288cc2d5dfSBarry Smith .keywords: MG, set, cycles, V-cycle, W-cycle, multigrid
7298cc2d5dfSBarry Smith 
7308cc2d5dfSBarry Smith .seealso: PCMGSetCycleTypeOnLevel(), PCMGSetCycleType()
7318cc2d5dfSBarry Smith @*/
7328cc2d5dfSBarry Smith PetscErrorCode PETSCKSP_DLLEXPORT PCMGMultiplicativeSetCycles(PC pc,PetscInt n)
7338cc2d5dfSBarry Smith {
7348cc2d5dfSBarry Smith   PC_MG    **mg;
7358cc2d5dfSBarry Smith   PetscInt i,levels;
7368cc2d5dfSBarry Smith 
7378cc2d5dfSBarry Smith   PetscFunctionBegin;
7388cc2d5dfSBarry Smith   PetscValidHeaderSpecific(pc,PC_COOKIE,1);
7398cc2d5dfSBarry Smith   mg     = (PC_MG**)pc->data;
7408cc2d5dfSBarry Smith   if (!mg) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Must set MG levels before calling");
7418cc2d5dfSBarry Smith   levels = mg[0]->levels;
7428cc2d5dfSBarry Smith 
7438cc2d5dfSBarry Smith   for (i=0; i<levels; i++) {
7448cc2d5dfSBarry Smith     mg[i]->cyclesperpcapply  = n;
7458cc2d5dfSBarry Smith   }
7468cc2d5dfSBarry Smith   PetscFunctionReturn(0);
7478cc2d5dfSBarry Smith }
7488cc2d5dfSBarry Smith 
7498cc2d5dfSBarry Smith #undef __FUNCT__
7509dcbbd2bSBarry Smith #define __FUNCT__ "PCMGSetGalerkin"
751c2be2410SBarry Smith /*@
75297177400SBarry Smith    PCMGSetGalerkin - Causes the coarser grid matrices to be computed from the
753c2be2410SBarry Smith       finest grid via the Galerkin process: A_i-1 = r_i * A_i * r_i^t
754c2be2410SBarry Smith 
755c2be2410SBarry Smith    Collective on PC
756c2be2410SBarry Smith 
757c2be2410SBarry Smith    Input Parameters:
7583fc8bf9cSBarry Smith .  pc - the multigrid context
759c2be2410SBarry Smith 
760c2be2410SBarry Smith    Options Database Key:
761c2be2410SBarry Smith $  -pc_mg_galerkin
762c2be2410SBarry Smith 
763c2be2410SBarry Smith    Level: intermediate
764c2be2410SBarry Smith 
765c2be2410SBarry Smith .keywords: MG, set, Galerkin
766c2be2410SBarry Smith 
7673fc8bf9cSBarry Smith .seealso: PCMGGetGalerkin()
7683fc8bf9cSBarry Smith 
769c2be2410SBarry Smith @*/
77097177400SBarry Smith PetscErrorCode PETSCKSP_DLLEXPORT PCMGSetGalerkin(PC pc)
771c2be2410SBarry Smith {
7729dcbbd2bSBarry Smith   PC_MG    **mg;
773c2be2410SBarry Smith   PetscInt i,levels;
774c2be2410SBarry Smith 
775c2be2410SBarry Smith   PetscFunctionBegin;
776c2be2410SBarry Smith   PetscValidHeaderSpecific(pc,PC_COOKIE,1);
7779dcbbd2bSBarry Smith   mg     = (PC_MG**)pc->data;
778c2be2410SBarry Smith   if (!mg) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Must set MG levels before calling");
779c2be2410SBarry Smith   levels = mg[0]->levels;
780c2be2410SBarry Smith 
781c2be2410SBarry Smith   for (i=0; i<levels; i++) {
782c2be2410SBarry Smith     mg[i]->galerkin = PETSC_TRUE;
783c2be2410SBarry Smith   }
784c2be2410SBarry Smith   PetscFunctionReturn(0);
785c2be2410SBarry Smith }
786c2be2410SBarry Smith 
787c2be2410SBarry Smith #undef __FUNCT__
7883fc8bf9cSBarry Smith #define __FUNCT__ "PCMGGetGalerkin"
7893fc8bf9cSBarry Smith /*@
7903fc8bf9cSBarry Smith    PCMGGetGalerkin - Checks if Galerkin multigrid is being used, i.e.
7913fc8bf9cSBarry Smith       A_i-1 = r_i * A_i * r_i^t
7923fc8bf9cSBarry Smith 
7933fc8bf9cSBarry Smith    Not Collective
7943fc8bf9cSBarry Smith 
7953fc8bf9cSBarry Smith    Input Parameter:
7963fc8bf9cSBarry Smith .  pc - the multigrid context
7973fc8bf9cSBarry Smith 
7983fc8bf9cSBarry Smith    Output Parameter:
7993fc8bf9cSBarry Smith .  gelerkin - PETSC_TRUE or PETSC_FALSE
8003fc8bf9cSBarry Smith 
8013fc8bf9cSBarry Smith    Options Database Key:
8023fc8bf9cSBarry Smith $  -pc_mg_galerkin
8033fc8bf9cSBarry Smith 
8043fc8bf9cSBarry Smith    Level: intermediate
8053fc8bf9cSBarry Smith 
8063fc8bf9cSBarry Smith .keywords: MG, set, Galerkin
8073fc8bf9cSBarry Smith 
8083fc8bf9cSBarry Smith .seealso: PCMGSetGalerkin()
8093fc8bf9cSBarry Smith 
8103fc8bf9cSBarry Smith @*/
8113fc8bf9cSBarry Smith PetscErrorCode PETSCKSP_DLLEXPORT PCMGGetGalerkin(PC pc,PetscTruth *galerkin)
8123fc8bf9cSBarry Smith {
8133fc8bf9cSBarry Smith   PC_MG    **mg;
8143fc8bf9cSBarry Smith 
8153fc8bf9cSBarry Smith   PetscFunctionBegin;
8163fc8bf9cSBarry Smith   PetscValidHeaderSpecific(pc,PC_COOKIE,1);
8173fc8bf9cSBarry Smith   mg     = (PC_MG**)pc->data;
8183fc8bf9cSBarry Smith   if (!mg) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Must set MG levels before calling");
8193fc8bf9cSBarry Smith   *galerkin = mg[0]->galerkin;
8203fc8bf9cSBarry Smith   PetscFunctionReturn(0);
8213fc8bf9cSBarry Smith }
8223fc8bf9cSBarry Smith 
8233fc8bf9cSBarry Smith #undef __FUNCT__
8249dcbbd2bSBarry Smith #define __FUNCT__ "PCMGSetNumberSmoothDown"
8254b9ad928SBarry Smith /*@
82697177400SBarry Smith    PCMGSetNumberSmoothDown - Sets the number of pre-smoothing steps to
82797177400SBarry Smith    use on all levels. Use PCMGGetSmootherDown() to set different
8284b9ad928SBarry Smith    pre-smoothing steps on different levels.
8294b9ad928SBarry Smith 
8304b9ad928SBarry Smith    Collective on PC
8314b9ad928SBarry Smith 
8324b9ad928SBarry Smith    Input Parameters:
8334b9ad928SBarry Smith +  mg - the multigrid context
8344b9ad928SBarry Smith -  n - the number of smoothing steps
8354b9ad928SBarry Smith 
8364b9ad928SBarry Smith    Options Database Key:
8374b9ad928SBarry Smith .  -pc_mg_smoothdown <n> - Sets number of pre-smoothing steps
8384b9ad928SBarry Smith 
8394b9ad928SBarry Smith    Level: advanced
8404b9ad928SBarry Smith 
8414b9ad928SBarry Smith .keywords: MG, smooth, down, pre-smoothing, steps, multigrid
8424b9ad928SBarry Smith 
84397177400SBarry Smith .seealso: PCMGSetNumberSmoothUp()
8444b9ad928SBarry Smith @*/
84597177400SBarry Smith PetscErrorCode PETSCKSP_DLLEXPORT PCMGSetNumberSmoothDown(PC pc,PetscInt n)
8464b9ad928SBarry Smith {
8479dcbbd2bSBarry Smith   PC_MG          **mg;
8486849ba73SBarry Smith   PetscErrorCode ierr;
84979416396SBarry Smith   PetscInt       i,levels;
8504b9ad928SBarry Smith 
8514b9ad928SBarry Smith   PetscFunctionBegin;
8524482741eSBarry Smith   PetscValidHeaderSpecific(pc,PC_COOKIE,1);
8539dcbbd2bSBarry Smith   mg     = (PC_MG**)pc->data;
8544b9ad928SBarry Smith   if (!mg) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Must set MG levels before calling");
8554b9ad928SBarry Smith   levels = mg[0]->levels;
8564b9ad928SBarry Smith 
857b05257ddSBarry Smith   for (i=1; i<levels; i++) {
8584b9ad928SBarry Smith     /* make sure smoother up and down are different */
85997177400SBarry Smith     ierr = PCMGGetSmootherUp(pc,i,PETSC_NULL);CHKERRQ(ierr);
8604b9ad928SBarry Smith     ierr = KSPSetTolerances(mg[i]->smoothd,PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT,n);CHKERRQ(ierr);
8614b9ad928SBarry Smith     mg[i]->default_smoothd = n;
8624b9ad928SBarry Smith   }
8634b9ad928SBarry Smith   PetscFunctionReturn(0);
8644b9ad928SBarry Smith }
8654b9ad928SBarry Smith 
8664b9ad928SBarry Smith #undef __FUNCT__
8679dcbbd2bSBarry Smith #define __FUNCT__ "PCMGSetNumberSmoothUp"
8684b9ad928SBarry Smith /*@
86997177400SBarry Smith    PCMGSetNumberSmoothUp - Sets the number of post-smoothing steps to use
87097177400SBarry Smith    on all levels. Use PCMGGetSmootherUp() to set different numbers of
8714b9ad928SBarry Smith    post-smoothing steps on different levels.
8724b9ad928SBarry Smith 
8734b9ad928SBarry Smith    Collective on PC
8744b9ad928SBarry Smith 
8754b9ad928SBarry Smith    Input Parameters:
8764b9ad928SBarry Smith +  mg - the multigrid context
8774b9ad928SBarry Smith -  n - the number of smoothing steps
8784b9ad928SBarry Smith 
8794b9ad928SBarry Smith    Options Database Key:
8804b9ad928SBarry Smith .  -pc_mg_smoothup <n> - Sets number of post-smoothing steps
8814b9ad928SBarry Smith 
8824b9ad928SBarry Smith    Level: advanced
8834b9ad928SBarry Smith 
8844b9ad928SBarry Smith    Note: this does not set a value on the coarsest grid, since we assume that
885a8c7a070SBarry Smith     there is no separate smooth up on the coarsest grid.
8864b9ad928SBarry Smith 
8874b9ad928SBarry Smith .keywords: MG, smooth, up, post-smoothing, steps, multigrid
8884b9ad928SBarry Smith 
88997177400SBarry Smith .seealso: PCMGSetNumberSmoothDown()
8904b9ad928SBarry Smith @*/
89197177400SBarry Smith PetscErrorCode PETSCKSP_DLLEXPORT PCMGSetNumberSmoothUp(PC pc,PetscInt n)
8924b9ad928SBarry Smith {
8939dcbbd2bSBarry Smith   PC_MG          **mg;
8946849ba73SBarry Smith   PetscErrorCode ierr;
89579416396SBarry Smith   PetscInt       i,levels;
8964b9ad928SBarry Smith 
8974b9ad928SBarry Smith   PetscFunctionBegin;
8984482741eSBarry Smith   PetscValidHeaderSpecific(pc,PC_COOKIE,1);
8999dcbbd2bSBarry Smith   mg     = (PC_MG**)pc->data;
9004b9ad928SBarry Smith   if (!mg) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Must set MG levels before calling");
9014b9ad928SBarry Smith   levels = mg[0]->levels;
9024b9ad928SBarry Smith 
9034b9ad928SBarry Smith   for (i=1; i<levels; i++) {
9044b9ad928SBarry Smith     /* make sure smoother up and down are different */
90597177400SBarry Smith     ierr = PCMGGetSmootherUp(pc,i,PETSC_NULL);CHKERRQ(ierr);
9064b9ad928SBarry Smith     ierr = KSPSetTolerances(mg[i]->smoothu,PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT,n);CHKERRQ(ierr);
9074b9ad928SBarry Smith     mg[i]->default_smoothu = n;
9084b9ad928SBarry Smith   }
9094b9ad928SBarry Smith   PetscFunctionReturn(0);
9104b9ad928SBarry Smith }
9114b9ad928SBarry Smith 
9124b9ad928SBarry Smith /* ----------------------------------------------------------------------------------------*/
9134b9ad928SBarry Smith 
9143b09bd56SBarry Smith /*MC
915ccb205f8SBarry Smith    PCMG - Use multigrid preconditioning. This preconditioner requires you provide additional
9163b09bd56SBarry Smith     information about the coarser grid matrices and restriction/interpolation operators.
9173b09bd56SBarry Smith 
9183b09bd56SBarry Smith    Options Database Keys:
9193b09bd56SBarry Smith +  -pc_mg_levels <nlevels> - number of levels including finest
9200d353602SBarry Smith .  -pc_mg_cycles v or w
92179416396SBarry Smith .  -pc_mg_smoothup <n> - number of smoothing steps after interpolation
9223b09bd56SBarry Smith .  -pc_mg_smoothdown <n> - number of smoothing steps before applying restriction operator
9233b09bd56SBarry Smith .  -pc_mg_type <additive,multiplicative,full,cascade> - multiplicative is the default
9243b09bd56SBarry Smith .  -pc_mg_log - log information about time spent on each level of the solver
9253b09bd56SBarry Smith .  -pc_mg_monitor - print information on the multigrid convergence
92668eff7e6SBarry Smith .  -pc_mg_galerkin - use Galerkin process to compute coarser operators
9273b09bd56SBarry Smith -  -pc_mg_dump_matlab - dumps the matrices for each level and the restriction/interpolation matrices
9283b09bd56SBarry Smith                         to the Socket viewer for reading from Matlab.
9293b09bd56SBarry Smith 
9303b09bd56SBarry Smith    Notes:
9313b09bd56SBarry Smith 
9323b09bd56SBarry Smith    Level: intermediate
9333b09bd56SBarry Smith 
9343b09bd56SBarry Smith    Concepts: multigrid
9353b09bd56SBarry Smith 
9363b09bd56SBarry Smith .seealso:  PCCreate(), PCSetType(), PCType (for list of available types), PC, PCMGType,
9370d353602SBarry Smith            PCMGSetLevels(), PCMGGetLevels(), PCMGSetType(), PCMGSetCycleType(), PCMGSetNumberSmoothDown(),
93897177400SBarry Smith            PCMGSetNumberSmoothUp(), PCMGGetCoarseSolve(), PCMGSetResidual(), PCMGSetInterpolation(),
93997177400SBarry Smith            PCMGSetRestriction(), PCMGGetSmoother(), PCMGGetSmootherUp(), PCMGGetSmootherDown(),
9400d353602SBarry Smith            PCMGSetCycleTypeOnLevel(), PCMGSetRhs(), PCMGSetX(), PCMGSetR()
9413b09bd56SBarry Smith M*/
9423b09bd56SBarry Smith 
9434b9ad928SBarry Smith EXTERN_C_BEGIN
9444b9ad928SBarry Smith #undef __FUNCT__
9454b9ad928SBarry Smith #define __FUNCT__ "PCCreate_MG"
946dba47a55SKris Buschelman PetscErrorCode PETSCKSP_DLLEXPORT PCCreate_MG(PC pc)
9474b9ad928SBarry Smith {
9484b9ad928SBarry Smith   PetscFunctionBegin;
9494b9ad928SBarry Smith   pc->ops->apply          = PCApply_MG;
9504b9ad928SBarry Smith   pc->ops->setup          = PCSetUp_MG;
9514b9ad928SBarry Smith   pc->ops->destroy        = PCDestroy_MG;
9524b9ad928SBarry Smith   pc->ops->setfromoptions = PCSetFromOptions_MG;
9534b9ad928SBarry Smith   pc->ops->view           = PCView_MG;
9544b9ad928SBarry Smith 
9554b9ad928SBarry Smith   pc->data                = (void*)0;
9564b9ad928SBarry Smith   PetscFunctionReturn(0);
9574b9ad928SBarry Smith }
9584b9ad928SBarry Smith EXTERN_C_END
959