xref: /petsc/src/ksp/pc/impls/mg/mg.c (revision a8e6722d6c138290148760b73775d2c0df5f142b)
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"
111e2582c4SBarry Smith PetscErrorCode PCMGMCycle_Private(PC pc,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) {
351e2582c4SBarry Smith           ierr = PetscInfo2(pc,"Linear solver has converged. Residual norm %G is less than absolute tolerance %G\n",rnorm,mg->abstol);CHKERRQ(ierr);
364b9ad928SBarry Smith         } else {
371e2582c4SBarry Smith           ierr = PetscInfo2(pc,"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--) {
491e2582c4SBarry Smith       ierr = PCMGMCycle_Private(pc,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);
8038f2d2fdSLisandro Dalcin   ierr = PetscLogObjectMemory(pc,levels*(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++) {
8538f2d2fdSLisandro Dalcin     ierr = PetscNewLog(pc,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;
14038f2d2fdSLisandro Dalcin   PetscInt       i,n;
1414b9ad928SBarry Smith 
1424b9ad928SBarry Smith   PetscFunctionBegin;
14338f2d2fdSLisandro Dalcin   if (!mg) PetscFunctionReturn(0);
14438f2d2fdSLisandro Dalcin   n = mg[0]->levels;
145fccaa45eSBarry Smith   for (i=0; i<n-1; i++) {
146630ba2eeSBarry Smith     if (mg[i+1]->r) {ierr = VecDestroy(mg[i+1]->r);CHKERRQ(ierr);}
147fccaa45eSBarry Smith     if (mg[i]->b) {ierr = VecDestroy(mg[i]->b);CHKERRQ(ierr);}
148fccaa45eSBarry Smith     if (mg[i]->x) {ierr = VecDestroy(mg[i]->x);CHKERRQ(ierr);}
149fccaa45eSBarry Smith     if (mg[i+1]->restrct) {ierr = MatDestroy(mg[i+1]->restrct);CHKERRQ(ierr);}
150fccaa45eSBarry Smith     if (mg[i+1]->interpolate) {ierr = MatDestroy(mg[i+1]->interpolate);CHKERRQ(ierr);}
151fccaa45eSBarry Smith   }
152fccaa45eSBarry Smith 
1534b9ad928SBarry Smith   for (i=0; i<n; i++) {
1544b9ad928SBarry Smith     if (mg[i]->smoothd != mg[i]->smoothu) {
1554b9ad928SBarry Smith       ierr = KSPDestroy(mg[i]->smoothd);CHKERRQ(ierr);
1564b9ad928SBarry Smith     }
1574b9ad928SBarry Smith     ierr = KSPDestroy(mg[i]->smoothu);CHKERRQ(ierr);
1584b9ad928SBarry Smith     ierr = PetscFree(mg[i]);CHKERRQ(ierr);
1594b9ad928SBarry Smith   }
1604b9ad928SBarry Smith   ierr = PetscFree(mg);CHKERRQ(ierr);
1614b9ad928SBarry Smith   PetscFunctionReturn(0);
1624b9ad928SBarry Smith }
1634b9ad928SBarry Smith 
1644b9ad928SBarry Smith 
1654b9ad928SBarry Smith 
1669dcbbd2bSBarry Smith EXTERN PetscErrorCode PCMGACycle_Private(PC_MG**);
1671e2582c4SBarry Smith EXTERN PetscErrorCode PCMGFCycle_Private(PC,PC_MG**);
1689dcbbd2bSBarry Smith EXTERN PetscErrorCode PCMGKCycle_Private(PC_MG**);
1694b9ad928SBarry Smith 
1704b9ad928SBarry Smith /*
1714b9ad928SBarry Smith    PCApply_MG - Runs either an additive, multiplicative, Kaskadic
1724b9ad928SBarry Smith              or full cycle of multigrid.
1734b9ad928SBarry Smith 
1744b9ad928SBarry Smith   Note:
1759dcbbd2bSBarry Smith   A simple wrapper which calls PCMGMCycle(),PCMGACycle(), or PCMGFCycle().
1764b9ad928SBarry Smith */
1774b9ad928SBarry Smith #undef __FUNCT__
1784b9ad928SBarry Smith #define __FUNCT__ "PCApply_MG"
1796849ba73SBarry Smith static PetscErrorCode PCApply_MG(PC pc,Vec b,Vec x)
1804b9ad928SBarry Smith {
1819dcbbd2bSBarry Smith   PC_MG          **mg = (PC_MG**)pc->data;
1826849ba73SBarry Smith   PetscErrorCode ierr;
1838cc2d5dfSBarry Smith   PetscInt       levels = mg[0]->levels,i;
1844b9ad928SBarry Smith 
1854b9ad928SBarry Smith   PetscFunctionBegin;
1864b9ad928SBarry Smith   mg[levels-1]->b = b;
1874b9ad928SBarry Smith   mg[levels-1]->x = x;
188ef70c39aSMatthew Knepley   if (!mg[levels-1]->r && mg[0]->am != PC_MG_ADDITIVE && levels > 1) {
1890a6bb862SBarry Smith     Vec tvec;
1900a6bb862SBarry Smith     ierr = VecDuplicate(mg[levels-1]->b,&tvec);CHKERRQ(ierr);
19197177400SBarry Smith     ierr = PCMGSetR(pc,levels-1,tvec);CHKERRQ(ierr);
1920a6bb862SBarry Smith     ierr = VecDestroy(tvec);CHKERRQ(ierr);
1930a6bb862SBarry Smith   }
1949dcbbd2bSBarry Smith   if (mg[0]->am == PC_MG_MULTIPLICATIVE) {
195efb30889SBarry Smith     ierr = VecSet(x,0.0);CHKERRQ(ierr);
1968cc2d5dfSBarry Smith     for (i=0; i<mg[0]->cyclesperpcapply; i++) {
1971e2582c4SBarry Smith       ierr = PCMGMCycle_Private(pc,mg+levels-1,PETSC_NULL);CHKERRQ(ierr);
1984b9ad928SBarry Smith     }
1998cc2d5dfSBarry Smith   }
2009dcbbd2bSBarry Smith   else if (mg[0]->am == PC_MG_ADDITIVE) {
2019dcbbd2bSBarry Smith     ierr = PCMGACycle_Private(mg);CHKERRQ(ierr);
2024b9ad928SBarry Smith   }
2039dcbbd2bSBarry Smith   else if (mg[0]->am == PC_MG_KASKADE) {
2049dcbbd2bSBarry Smith     ierr = PCMGKCycle_Private(mg);CHKERRQ(ierr);
2054b9ad928SBarry Smith   }
2064b9ad928SBarry Smith   else {
2071e2582c4SBarry Smith     ierr = PCMGFCycle_Private(pc,mg);CHKERRQ(ierr);
2084b9ad928SBarry Smith   }
2094b9ad928SBarry Smith   PetscFunctionReturn(0);
2104b9ad928SBarry Smith }
2114b9ad928SBarry Smith 
2124b9ad928SBarry Smith #undef __FUNCT__
2134b9ad928SBarry Smith #define __FUNCT__ "PCApplyRichardson_MG"
21479416396SBarry Smith static PetscErrorCode PCApplyRichardson_MG(PC pc,Vec b,Vec x,Vec w,PetscReal rtol,PetscReal abstol, PetscReal dtol,PetscInt its)
2154b9ad928SBarry Smith {
2169dcbbd2bSBarry Smith   PC_MG          **mg = (PC_MG**)pc->data;
217dfbe8321SBarry Smith   PetscErrorCode ierr;
21879416396SBarry Smith   PetscInt       levels = mg[0]->levels;
2194b9ad928SBarry Smith   PetscTruth     converged = PETSC_FALSE;
2204b9ad928SBarry Smith 
2214b9ad928SBarry Smith   PetscFunctionBegin;
2224b9ad928SBarry Smith   mg[levels-1]->b    = b;
2234b9ad928SBarry Smith   mg[levels-1]->x    = x;
2244b9ad928SBarry Smith 
2254b9ad928SBarry Smith   mg[levels-1]->rtol = rtol;
22670441072SBarry Smith   mg[levels-1]->abstol = abstol;
2274b9ad928SBarry Smith   mg[levels-1]->dtol = dtol;
2284b9ad928SBarry Smith   if (rtol) {
2294b9ad928SBarry Smith     /* compute initial residual norm for relative convergence test */
2304b9ad928SBarry Smith     PetscReal rnorm;
2314b9ad928SBarry Smith     ierr               = (*mg[levels-1]->residual)(mg[levels-1]->A,b,x,w);CHKERRQ(ierr);
2324b9ad928SBarry Smith     ierr               = VecNorm(w,NORM_2,&rnorm);CHKERRQ(ierr);
23370441072SBarry Smith     mg[levels-1]->ttol = PetscMax(rtol*rnorm,abstol);
23470441072SBarry Smith   } else if (abstol) {
23570441072SBarry Smith     mg[levels-1]->ttol = abstol;
2364b9ad928SBarry Smith   } else {
2374b9ad928SBarry Smith     mg[levels-1]->ttol = 0.0;
2384b9ad928SBarry Smith   }
2394b9ad928SBarry Smith 
2404b9ad928SBarry Smith   while (its-- && !converged) {
2411e2582c4SBarry Smith     ierr = PCMGMCycle_Private(pc,mg+levels-1,&converged);CHKERRQ(ierr);
2424b9ad928SBarry Smith   }
2434b9ad928SBarry Smith   PetscFunctionReturn(0);
2444b9ad928SBarry Smith }
2454b9ad928SBarry Smith 
2464b9ad928SBarry Smith #undef __FUNCT__
2474b9ad928SBarry Smith #define __FUNCT__ "PCSetFromOptions_MG"
2486ca4d86aSHong Zhang PetscErrorCode PCSetFromOptions_MG(PC pc)
2494b9ad928SBarry Smith {
250dfbe8321SBarry Smith   PetscErrorCode ierr;
2518cc2d5dfSBarry Smith   PetscInt       m,levels = 1,cycles;
2524b9ad928SBarry Smith   PetscTruth     flg;
2539dcbbd2bSBarry Smith   PC_MG          **mg = (PC_MG**)pc->data;
25490da95b0SMatthew Knepley   PCMGType       mgtype = PC_MG_ADDITIVE;
2551aa34eeaSBarry Smith   PCMGCycleType  mgctype;
2564b9ad928SBarry Smith 
2574b9ad928SBarry Smith   PetscFunctionBegin;
2584b9ad928SBarry Smith   ierr = PetscOptionsHead("Multigrid options");CHKERRQ(ierr);
2594b9ad928SBarry Smith     if (!pc->data) {
2609dcbbd2bSBarry Smith       ierr = PetscOptionsInt("-pc_mg_levels","Number of Levels","PCMGSetLevels",levels,&levels,&flg);CHKERRQ(ierr);
26197177400SBarry Smith       ierr = PCMGSetLevels(pc,levels,PETSC_NULL);CHKERRQ(ierr);
262cf502942SBarry Smith       mg = (PC_MG**)pc->data;
2634b9ad928SBarry Smith     }
264f2070a76SMatthew Knepley     mgctype = (PCMGCycleType) mg[0]->cycles;
2650d353602SBarry Smith     ierr = PetscOptionsEnum("-pc_mg_cycle_type","V cycle or for W-cycle","PCMGSetCycleType",PCMGCycleTypes,(PetscEnum)mgctype,(PetscEnum*)&mgctype,&flg);CHKERRQ(ierr);
2664b9ad928SBarry Smith     if (flg) {
2670d353602SBarry Smith       ierr = PCMGSetCycleType(pc,mgctype);CHKERRQ(ierr);
2680d353602SBarry Smith     };
2699dcbbd2bSBarry Smith     ierr = PetscOptionsName("-pc_mg_galerkin","Use Galerkin process to compute coarser operators","PCMGSetGalerkin",&flg);CHKERRQ(ierr);
270c2be2410SBarry Smith     if (flg) {
27197177400SBarry Smith       ierr = PCMGSetGalerkin(pc);CHKERRQ(ierr);
272c2be2410SBarry Smith     }
2739dcbbd2bSBarry Smith     ierr = PetscOptionsInt("-pc_mg_smoothup","Number of post-smoothing steps","PCMGSetNumberSmoothUp",1,&m,&flg);CHKERRQ(ierr);
2744b9ad928SBarry Smith     if (flg) {
27597177400SBarry Smith       ierr = PCMGSetNumberSmoothUp(pc,m);CHKERRQ(ierr);
2764b9ad928SBarry Smith     }
2779dcbbd2bSBarry Smith     ierr = PetscOptionsInt("-pc_mg_smoothdown","Number of pre-smoothing steps","PCMGSetNumberSmoothDown",1,&m,&flg);CHKERRQ(ierr);
2784b9ad928SBarry Smith     if (flg) {
27997177400SBarry Smith       ierr = PCMGSetNumberSmoothDown(pc,m);CHKERRQ(ierr);
2804b9ad928SBarry Smith     }
2819dcbbd2bSBarry Smith     ierr = PetscOptionsEnum("-pc_mg_type","Multigrid type","PCMGSetType",PCMGTypes,(PetscEnum)mgtype,(PetscEnum*)&mgtype,&flg);CHKERRQ(ierr);
2828cc2d5dfSBarry Smith     if (flg) {
2838cc2d5dfSBarry Smith       ierr = PCMGSetType(pc,mgtype);CHKERRQ(ierr);
2848cc2d5dfSBarry Smith     }
2858cc2d5dfSBarry Smith     if (mg[0]->am == PC_MG_MULTIPLICATIVE) {
2868cc2d5dfSBarry Smith       ierr = PetscOptionsInt("-pc_mg_multiplicative_cycles","Number of cycles for each preconditioner step","PCMGSetLevels",mg[0]->cyclesperpcapply,&cycles,&flg);CHKERRQ(ierr);
2878cc2d5dfSBarry Smith       if (flg) {
2888cc2d5dfSBarry Smith 	ierr = PCMGMultiplicativeSetCycles(pc,cycles);CHKERRQ(ierr);
2898cc2d5dfSBarry Smith       }
2908cc2d5dfSBarry Smith     }
2914b9ad928SBarry Smith     ierr = PetscOptionsName("-pc_mg_log","Log times for each multigrid level","None",&flg);CHKERRQ(ierr);
2924b9ad928SBarry Smith     if (flg) {
2934f5ab15aSBarry Smith       PetscInt i;
2944b9ad928SBarry Smith       char     eventname[128];
2954b9ad928SBarry Smith       if (!mg) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Must set MG levels before calling");
2964b9ad928SBarry Smith       levels = mg[0]->levels;
2974b9ad928SBarry Smith       for (i=0; i<levels; i++) {
29832cf1786SBarry Smith         sprintf(eventname,"MGSetup Level %d",(int)i);
2998cbcd9ccSBarry Smith         ierr = PetscLogEventRegister(eventname,((PetscObject)pc)->cookie,&mg[i]->eventsmoothsetup);CHKERRQ(ierr);
30032cf1786SBarry Smith         sprintf(eventname,"MGSmooth Level %d",(int)i);
3018cbcd9ccSBarry Smith         ierr = PetscLogEventRegister(eventname,((PetscObject)pc)->cookie,&mg[i]->eventsmoothsolve);CHKERRQ(ierr);
30232cf1786SBarry Smith         if (i) {
30332cf1786SBarry Smith           sprintf(eventname,"MGResid Level %d",(int)i);
304a3bc4eb9SBarry Smith           ierr = PetscLogEventRegister(eventname,((PetscObject)pc)->cookie,&mg[i]->eventresidual);CHKERRQ(ierr);
30532cf1786SBarry Smith           sprintf(eventname,"MGInterp Level %d",(int)i);
3068cbcd9ccSBarry Smith           ierr = PetscLogEventRegister(eventname,((PetscObject)pc)->cookie,&mg[i]->eventinterprestrict);CHKERRQ(ierr);
30732cf1786SBarry Smith         }
3084b9ad928SBarry Smith       }
3094b9ad928SBarry Smith     }
3104b9ad928SBarry Smith   ierr = PetscOptionsTail();CHKERRQ(ierr);
3114b9ad928SBarry Smith   PetscFunctionReturn(0);
3124b9ad928SBarry Smith }
3134b9ad928SBarry Smith 
3149dcbbd2bSBarry Smith const char *PCMGTypes[] = {"MULTIPLICATIVE","ADDITIVE","FULL","KASKADE","PCMGType","PC_MG",0};
3150d353602SBarry Smith const char *PCMGCycleTypes[] = {"invalid","v","w","PCMGCycleType","PC_MG_CYCLE",0};
3169dcbbd2bSBarry Smith 
3174b9ad928SBarry Smith #undef __FUNCT__
3184b9ad928SBarry Smith #define __FUNCT__ "PCView_MG"
3196849ba73SBarry Smith static PetscErrorCode PCView_MG(PC pc,PetscViewer viewer)
3204b9ad928SBarry Smith {
3219dcbbd2bSBarry Smith   PC_MG          **mg = (PC_MG**)pc->data;
322dfbe8321SBarry Smith   PetscErrorCode ierr;
32379416396SBarry Smith   PetscInt       levels = mg[0]->levels,i;
32432077d6dSBarry Smith   PetscTruth     iascii;
3254b9ad928SBarry Smith 
3264b9ad928SBarry Smith   PetscFunctionBegin;
32732077d6dSBarry Smith   ierr = PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_ASCII,&iascii);CHKERRQ(ierr);
32832077d6dSBarry Smith   if (iascii) {
329*a8e6722dSMatthew Knepley     ierr = PetscViewerASCIIPrintf(viewer,"  MG: type is %s, levels=%D cycles=%s\n", PCMGTypes[mg[0]->am],levels,(mg[0]->cycles == PC_MG_CYCLE_V) ? "v" : "w");CHKERRQ(ierr);
330d792f543SMatthew Knepley     if (mg[0]->am == PC_MG_MULTIPLICATIVE) {
331d792f543SMatthew Knepley       ierr = PetscViewerASCIIPrintf(viewer,"    Cycles per PCApply=%d\n",mg[0]->cyclesperpcapply);CHKERRQ(ierr);
332d792f543SMatthew Knepley     }
333c2be2410SBarry Smith     if (mg[0]->galerkin) {
334c2be2410SBarry Smith       ierr = PetscViewerASCIIPrintf(viewer,"    Using Galerkin computed coarse grid matrices\n");CHKERRQ(ierr);
335c2be2410SBarry Smith     }
3364b9ad928SBarry Smith     for (i=0; i<levels; i++) {
337b03c7568SBarry Smith       if (!i) {
338*a8e6722dSMatthew Knepley         ierr = PetscViewerASCIIPrintf(viewer,"Coarse gride solver -- level %D presmooths=%D postsmooths=%D -----\n",i,mg[0]->default_smoothd,mg[0]->default_smoothu);CHKERRQ(ierr);
339b03c7568SBarry Smith       } else {
340*a8e6722dSMatthew Knepley         ierr = PetscViewerASCIIPrintf(viewer,"Down solver (pre-smoother) on level %D smooths=%D --------------------\n",i,mg[i]->default_smoothd);CHKERRQ(ierr);
341b03c7568SBarry Smith       }
3424b9ad928SBarry Smith       ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr);
3434b9ad928SBarry Smith       ierr = KSPView(mg[i]->smoothd,viewer);CHKERRQ(ierr);
3444b9ad928SBarry Smith       ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr);
345b03c7568SBarry Smith       if (i && mg[i]->smoothd == mg[i]->smoothu) {
3464b9ad928SBarry Smith         ierr = PetscViewerASCIIPrintf(viewer,"Up solver (post-smoother) same as down solver (pre-smoother)\n");CHKERRQ(ierr);
347b03c7568SBarry Smith       } else if (i){
348*a8e6722dSMatthew Knepley         ierr = PetscViewerASCIIPrintf(viewer,"Up solver (post-smoother) on level %D smooths=%D --------------------\n",i,mg[i]->default_smoothu);CHKERRQ(ierr);
3494b9ad928SBarry Smith         ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr);
3504b9ad928SBarry Smith         ierr = KSPView(mg[i]->smoothu,viewer);CHKERRQ(ierr);
3514b9ad928SBarry Smith         ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr);
3524b9ad928SBarry Smith       }
3534b9ad928SBarry Smith     }
3544b9ad928SBarry Smith   } else {
35579a5c55eSBarry Smith     SETERRQ1(PETSC_ERR_SUP,"Viewer type %s not supported for PCMG",((PetscObject)viewer)->type_name);
3564b9ad928SBarry Smith   }
3574b9ad928SBarry Smith   PetscFunctionReturn(0);
3584b9ad928SBarry Smith }
3594b9ad928SBarry Smith 
3604b9ad928SBarry Smith /*
3614b9ad928SBarry Smith     Calls setup for the KSP on each level
3624b9ad928SBarry Smith */
3634b9ad928SBarry Smith #undef __FUNCT__
3644b9ad928SBarry Smith #define __FUNCT__ "PCSetUp_MG"
3656849ba73SBarry Smith static PetscErrorCode PCSetUp_MG(PC pc)
3664b9ad928SBarry Smith {
3679dcbbd2bSBarry Smith   PC_MG                   **mg = (PC_MG**)pc->data;
368dfbe8321SBarry Smith   PetscErrorCode          ierr;
36979416396SBarry Smith   PetscInt                i,n = mg[0]->levels;
37077122347SBarry Smith   PC                      cpc,mpc;
371906ed7ccSBarry Smith   PetscTruth              preonly,lu,redundant,cholesky,monitor = PETSC_FALSE,dump,opsset;
37223d894e5SBarry Smith   PetscViewerASCIIMonitor ascii;
37323d894e5SBarry Smith   PetscViewer             viewer = PETSC_NULL;
3744b9ad928SBarry Smith   MPI_Comm                comm;
375c2be2410SBarry Smith   Mat                     dA,dB;
376c2be2410SBarry Smith   MatStructure            uflag;
3770a6bb862SBarry Smith   Vec                     tvec;
3784b9ad928SBarry Smith 
3794b9ad928SBarry Smith   PetscFunctionBegin;
380852665d3SBarry Smith 
38143fb2f97SBarry Smith   /* If user did not provide fine grid operators OR operator was not updated since last global KSPSetOperators() */
38243fb2f97SBarry Smith   /* so use those from global PC */
38343fb2f97SBarry Smith   /* Is this what we always want? What if user wants to keep old one? */
384906ed7ccSBarry Smith   ierr = KSPGetOperatorsSet(mg[n-1]->smoothd,PETSC_NULL,&opsset);CHKERRQ(ierr);
38543fb2f97SBarry Smith   ierr = KSPGetPC(mg[0]->smoothd,&cpc);CHKERRQ(ierr);
38677122347SBarry Smith   ierr = KSPGetPC(mg[n-1]->smoothd,&mpc);CHKERRQ(ierr);
38777122347SBarry Smith   if (!opsset || ((cpc->setupcalled == 1) && (mpc->setupcalled == 2))) {
388852665d3SBarry 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);
3891cfe3bddSBarry Smith     ierr = KSPSetOperators(mg[n-1]->smoothd,pc->mat,pc->pmat,pc->flag);CHKERRQ(ierr);
390852665d3SBarry Smith   }
391852665d3SBarry Smith 
392852665d3SBarry Smith   if (mg[0]->galerkin) {
393852665d3SBarry Smith     Mat B;
394852665d3SBarry Smith     mg[0]->galerkinused = PETSC_TRUE;
395852665d3SBarry Smith     /* currently only handle case where mat and pmat are the same on coarser levels */
396852665d3SBarry Smith     ierr = KSPGetOperators(mg[n-1]->smoothd,&dA,&dB,&uflag);CHKERRQ(ierr);
397852665d3SBarry Smith     if (!pc->setupcalled) {
398852665d3SBarry Smith       for (i=n-2; i>-1; i--) {
399852665d3SBarry Smith         ierr = MatPtAP(dB,mg[i+1]->interpolate,MAT_INITIAL_MATRIX,1.0,&B);CHKERRQ(ierr);
400852665d3SBarry Smith         ierr = KSPSetOperators(mg[i]->smoothd,B,B,uflag);CHKERRQ(ierr);
401906ed7ccSBarry Smith 	if (i != n-2) {ierr = PetscObjectDereference((PetscObject)dB);CHKERRQ(ierr);}
402852665d3SBarry Smith         dB   = B;
403852665d3SBarry Smith       }
404906ed7ccSBarry Smith       ierr = PetscObjectDereference((PetscObject)dB);CHKERRQ(ierr);
405852665d3SBarry Smith     } else {
406852665d3SBarry Smith       for (i=n-2; i>-1; i--) {
407906ed7ccSBarry Smith         ierr = KSPGetOperators(mg[i]->smoothd,PETSC_NULL,&B,PETSC_NULL);CHKERRQ(ierr);
408852665d3SBarry Smith         ierr = MatPtAP(dB,mg[i+1]->interpolate,MAT_REUSE_MATRIX,1.0,&B);CHKERRQ(ierr);
409852665d3SBarry Smith         ierr = KSPSetOperators(mg[i]->smoothd,B,B,uflag);CHKERRQ(ierr);
410852665d3SBarry Smith         dB   = B;
411852665d3SBarry Smith       }
412852665d3SBarry Smith     }
413852665d3SBarry Smith   }
414852665d3SBarry Smith 
415958c9bccSBarry Smith   if (!pc->setupcalled) {
4164b9ad928SBarry Smith     ierr = PetscOptionsHasName(0,"-pc_mg_monitor",&monitor);CHKERRQ(ierr);
4174b9ad928SBarry Smith 
418b03c7568SBarry Smith     for (i=0; i<n; i++) {
4194b9ad928SBarry Smith       if (monitor) {
4204b9ad928SBarry Smith         ierr = PetscObjectGetComm((PetscObject)mg[i]->smoothd,&comm);CHKERRQ(ierr);
42123d894e5SBarry Smith         ierr = PetscViewerASCIIMonitorCreate(comm,"stdout",n-i,&ascii);CHKERRQ(ierr);
42223d894e5SBarry Smith         ierr = KSPMonitorSet(mg[i]->smoothd,KSPMonitorDefault,ascii,(PetscErrorCode(*)(void*))PetscViewerASCIIMonitorDestroy);CHKERRQ(ierr);
4234b9ad928SBarry Smith       }
4244b9ad928SBarry Smith       ierr = KSPSetFromOptions(mg[i]->smoothd);CHKERRQ(ierr);
4254b9ad928SBarry Smith     }
426b03c7568SBarry Smith     for (i=1; i<n; i++) {
427a98fc643SBarry Smith       if (mg[i]->smoothu && (mg[i]->smoothu != mg[i]->smoothd)) {
4284b9ad928SBarry Smith         if (monitor) {
4294b9ad928SBarry Smith           ierr = PetscObjectGetComm((PetscObject)mg[i]->smoothu,&comm);CHKERRQ(ierr);
43023d894e5SBarry Smith           ierr = PetscViewerASCIIMonitorCreate(comm,"stdout",n-i,&ascii);CHKERRQ(ierr);
43123d894e5SBarry Smith           ierr = KSPMonitorSet(mg[i]->smoothu,KSPMonitorDefault,ascii,(PetscErrorCode(*)(void*))PetscViewerASCIIMonitorDestroy);CHKERRQ(ierr);
4324b9ad928SBarry Smith         }
4334b9ad928SBarry Smith         ierr = KSPSetFromOptions(mg[i]->smoothu);CHKERRQ(ierr);
4344b9ad928SBarry Smith       }
4354b9ad928SBarry Smith     }
436fccaa45eSBarry Smith     for (i=1; i<n; i++) {
4370cace4b0SBarry Smith       if (!mg[i]->residual) {
4380cace4b0SBarry Smith         Mat mat;
4390cace4b0SBarry Smith         ierr = KSPGetOperators(mg[i]->smoothd,PETSC_NULL,&mat,PETSC_NULL);CHKERRQ(ierr);
4400cace4b0SBarry Smith         ierr = PCMGSetResidual(pc,i,PCMGDefaultResidual,mat);CHKERRQ(ierr);
4410cace4b0SBarry Smith       }
442fccaa45eSBarry Smith       if (mg[i]->restrct && !mg[i]->interpolate) {
443aea2a34eSBarry Smith         ierr = PCMGSetInterpolation(pc,i,mg[i]->restrct);CHKERRQ(ierr);
444fccaa45eSBarry Smith       }
445fccaa45eSBarry Smith       if (!mg[i]->restrct && mg[i]->interpolate) {
44697177400SBarry Smith         ierr = PCMGSetRestriction(pc,i,mg[i]->interpolate);CHKERRQ(ierr);
447fccaa45eSBarry Smith       }
448fccaa45eSBarry Smith #if defined(PETSC_USE_DEBUG)
449fccaa45eSBarry Smith       if (!mg[i]->restrct || !mg[i]->interpolate) {
450fccaa45eSBarry Smith         SETERRQ1(PETSC_ERR_ARG_WRONGSTATE,"Need to set restriction or interpolation on level %d",(int)i);
451fccaa45eSBarry Smith       }
452fccaa45eSBarry Smith #endif
453fccaa45eSBarry Smith     }
4540a6bb862SBarry Smith     for (i=0; i<n-1; i++) {
45537b0e6c0SBarry Smith       if (!mg[i]->b) {
456906ed7ccSBarry Smith         Vec *vec;
457906ed7ccSBarry Smith         ierr = KSPGetVecs(mg[i]->smoothd,1,&vec,0,PETSC_NULL);CHKERRQ(ierr);
458906ed7ccSBarry Smith         ierr = PCMGSetRhs(pc,i,*vec);CHKERRQ(ierr);
459906ed7ccSBarry Smith         ierr = PetscFree(vec);CHKERRQ(ierr);
46037b0e6c0SBarry Smith       }
4616ca4d86aSHong Zhang       if (!mg[i]->r && i) {
4620a6bb862SBarry Smith         ierr = VecDuplicate(mg[i]->b,&tvec);CHKERRQ(ierr);
46397177400SBarry Smith         ierr = PCMGSetR(pc,i,tvec);CHKERRQ(ierr);
4640a6bb862SBarry Smith         ierr = VecDestroy(tvec);CHKERRQ(ierr);
4650a6bb862SBarry Smith       }
4660a6bb862SBarry Smith       if (!mg[i]->x) {
4670a6bb862SBarry Smith         ierr = VecDuplicate(mg[i]->b,&tvec);CHKERRQ(ierr);
46897177400SBarry Smith         ierr = PCMGSetX(pc,i,tvec);CHKERRQ(ierr);
4690a6bb862SBarry Smith         ierr = VecDestroy(tvec);CHKERRQ(ierr);
4700a6bb862SBarry Smith       }
4710a6bb862SBarry Smith     }
472dfef70bdSHong Zhang     if (n != 1 && !mg[n-1]->r) {
473dfef70bdSHong Zhang       /* PCMGSetR() on the finest level if user did not supply it */
4740f77fa87SBarry Smith       Vec *vec;
4750f77fa87SBarry Smith       ierr = KSPGetVecs(mg[n-1]->smoothd,1,&vec,0,PETSC_NULL);CHKERRQ(ierr);
4760f77fa87SBarry Smith       ierr = PCMGSetR(pc,n-1,*vec);CHKERRQ(ierr);
4770f77fa87SBarry Smith       ierr = PetscFree(vec);CHKERRQ(ierr);
4780f77fa87SBarry Smith     }
4794b9ad928SBarry Smith   }
4804b9ad928SBarry Smith 
481c2be2410SBarry Smith 
4824b9ad928SBarry Smith   for (i=1; i<n; i++) {
483b03c7568SBarry Smith     if (mg[i]->smoothu == mg[i]->smoothd) {
484b03c7568SBarry Smith       /* if doing only down then initial guess is zero */
4854b9ad928SBarry Smith       ierr = KSPSetInitialGuessNonzero(mg[i]->smoothd,PETSC_TRUE);CHKERRQ(ierr);
486b03c7568SBarry Smith     }
48732cf1786SBarry Smith     if (mg[i]->eventsmoothsetup) {ierr = PetscLogEventBegin(mg[i]->eventsmoothsetup,0,0,0,0);CHKERRQ(ierr);}
4884b9ad928SBarry Smith     ierr = KSPSetUp(mg[i]->smoothd);CHKERRQ(ierr);
48932cf1786SBarry Smith     if (mg[i]->eventsmoothsetup) {ierr = PetscLogEventEnd(mg[i]->eventsmoothsetup,0,0,0,0);CHKERRQ(ierr);}
4904b9ad928SBarry Smith   }
491b03c7568SBarry Smith   for (i=1; i<n; i++) {
4924b9ad928SBarry Smith     if (mg[i]->smoothu && mg[i]->smoothu != mg[i]->smoothd) {
493906ed7ccSBarry Smith       Mat          downmat,downpmat;
49497f1f81fSBarry Smith       MatStructure matflag;
495906ed7ccSBarry Smith       PetscTruth   opsset;
49697f1f81fSBarry Smith 
49797f1f81fSBarry Smith       /* check if operators have been set for up, if not use down operators to set them */
498906ed7ccSBarry Smith       ierr = KSPGetOperatorsSet(mg[i]->smoothu,&opsset,PETSC_NULL);CHKERRQ(ierr);
499906ed7ccSBarry Smith       if (!opsset) {
500906ed7ccSBarry Smith         ierr = KSPGetOperators(mg[i]->smoothd,&downmat,&downpmat,&matflag);CHKERRQ(ierr);
50197f1f81fSBarry Smith         ierr = KSPSetOperators(mg[i]->smoothu,downmat,downpmat,matflag);CHKERRQ(ierr);
50297f1f81fSBarry Smith       }
50397f1f81fSBarry Smith 
5044b9ad928SBarry Smith       ierr = KSPSetInitialGuessNonzero(mg[i]->smoothu,PETSC_TRUE);CHKERRQ(ierr);
50532cf1786SBarry Smith       if (mg[i]->eventsmoothsetup) {ierr = PetscLogEventBegin(mg[i]->eventsmoothsetup,0,0,0,0);CHKERRQ(ierr);}
5064b9ad928SBarry Smith       ierr = KSPSetUp(mg[i]->smoothu);CHKERRQ(ierr);
50732cf1786SBarry Smith       if (mg[i]->eventsmoothsetup) {ierr = PetscLogEventEnd(mg[i]->eventsmoothsetup,0,0,0,0);CHKERRQ(ierr);}
5084b9ad928SBarry Smith     }
5094b9ad928SBarry Smith   }
5104b9ad928SBarry Smith 
5114b9ad928SBarry Smith   /*
5124b9ad928SBarry Smith       If coarse solver is not direct method then DO NOT USE preonly
5134b9ad928SBarry Smith   */
5144b9ad928SBarry Smith   ierr = PetscTypeCompare((PetscObject)mg[0]->smoothd,KSPPREONLY,&preonly);CHKERRQ(ierr);
5154b9ad928SBarry Smith   if (preonly) {
5164b9ad928SBarry Smith     ierr = PetscTypeCompare((PetscObject)cpc,PCLU,&lu);CHKERRQ(ierr);
5174b9ad928SBarry Smith     ierr = PetscTypeCompare((PetscObject)cpc,PCREDUNDANT,&redundant);CHKERRQ(ierr);
51868eff7e6SBarry Smith     ierr = PetscTypeCompare((PetscObject)cpc,PCCHOLESKY,&cholesky);CHKERRQ(ierr);
51968eff7e6SBarry Smith     if (!lu && !redundant && !cholesky) {
5204b9ad928SBarry Smith       ierr = KSPSetType(mg[0]->smoothd,KSPGMRES);CHKERRQ(ierr);
5214b9ad928SBarry Smith     }
5224b9ad928SBarry Smith   }
5234b9ad928SBarry Smith 
524958c9bccSBarry Smith   if (!pc->setupcalled) {
5254b9ad928SBarry Smith     if (monitor) {
5264b9ad928SBarry Smith       ierr = PetscObjectGetComm((PetscObject)mg[0]->smoothd,&comm);CHKERRQ(ierr);
52723d894e5SBarry Smith       ierr = PetscViewerASCIIMonitorCreate(comm,"stdout",n,&ascii);CHKERRQ(ierr);
52823d894e5SBarry Smith       ierr = KSPMonitorSet(mg[0]->smoothd,KSPMonitorDefault,ascii,(PetscErrorCode(*)(void*))PetscViewerASCIIMonitorDestroy);CHKERRQ(ierr);
5294b9ad928SBarry Smith     }
5304b9ad928SBarry Smith     ierr = KSPSetFromOptions(mg[0]->smoothd);CHKERRQ(ierr);
5314b9ad928SBarry Smith   }
5324b9ad928SBarry Smith 
53332cf1786SBarry Smith   if (mg[0]->eventsmoothsetup) {ierr = PetscLogEventBegin(mg[0]->eventsmoothsetup,0,0,0,0);CHKERRQ(ierr);}
5344b9ad928SBarry Smith   ierr = KSPSetUp(mg[0]->smoothd);CHKERRQ(ierr);
53532cf1786SBarry Smith   if (mg[0]->eventsmoothsetup) {ierr = PetscLogEventEnd(mg[0]->eventsmoothsetup,0,0,0,0);CHKERRQ(ierr);}
5364b9ad928SBarry Smith 
5374b9ad928SBarry Smith   /*
5386805f65bSBarry Smith      Dump the interpolation/restriction matrices plus the
5394b9ad928SBarry Smith    Jacobian/stiffness on each level. This allows Matlab users to
5406805f65bSBarry Smith    easily check if the Galerkin condition A_c = R A_f R^T is satisfied.
5416805f65bSBarry Smith 
5426805f65bSBarry Smith    Only support one or the other at the same time.
5436805f65bSBarry Smith   */
5446805f65bSBarry Smith #if defined(PETSC_USE_SOCKET_VIEWER)
5457adad957SLisandro Dalcin   ierr = PetscOptionsHasName(((PetscObject)pc)->prefix,"-pc_mg_dump_matlab",&dump);CHKERRQ(ierr);
5464b9ad928SBarry Smith   if (dump) {
5477adad957SLisandro Dalcin     viewer = PETSC_VIEWER_SOCKET_(((PetscObject)pc)->comm);
5484b9ad928SBarry Smith   }
549c45a1595SBarry Smith #endif
5507adad957SLisandro Dalcin   ierr = PetscOptionsHasName(((PetscObject)pc)->prefix,"-pc_mg_dump_binary",&dump);CHKERRQ(ierr);
551c2be2410SBarry Smith   if (dump) {
5527adad957SLisandro Dalcin     viewer = PETSC_VIEWER_BINARY_(((PetscObject)pc)->comm);
5536805f65bSBarry Smith   }
5546805f65bSBarry Smith 
5556805f65bSBarry Smith   if (viewer) {
556c2be2410SBarry Smith     for (i=1; i<n; i++) {
5576805f65bSBarry Smith       ierr = MatView(mg[i]->restrct,viewer);CHKERRQ(ierr);
558c2be2410SBarry Smith     }
559c2be2410SBarry Smith     for (i=0; i<n; i++) {
560c2be2410SBarry Smith       ierr = KSPGetPC(mg[i]->smoothd,&pc);CHKERRQ(ierr);
5616805f65bSBarry Smith       ierr = MatView(pc->mat,viewer);CHKERRQ(ierr);
562c2be2410SBarry Smith     }
563c2be2410SBarry Smith   }
5644b9ad928SBarry Smith   PetscFunctionReturn(0);
5654b9ad928SBarry Smith }
5664b9ad928SBarry Smith 
5674b9ad928SBarry Smith /* -------------------------------------------------------------------------------------*/
5684b9ad928SBarry Smith 
5694b9ad928SBarry Smith #undef __FUNCT__
5709dcbbd2bSBarry Smith #define __FUNCT__ "PCMGSetLevels"
5714b9ad928SBarry Smith /*@C
57297177400SBarry Smith    PCMGSetLevels - Sets the number of levels to use with MG.
5734b9ad928SBarry Smith    Must be called before any other MG routine.
5744b9ad928SBarry Smith 
5754b9ad928SBarry Smith    Collective on PC
5764b9ad928SBarry Smith 
5774b9ad928SBarry Smith    Input Parameters:
5784b9ad928SBarry Smith +  pc - the preconditioner context
5794b9ad928SBarry Smith .  levels - the number of levels
5804b9ad928SBarry Smith -  comms - optional communicators for each level; this is to allow solving the coarser problems
5814b9ad928SBarry Smith            on smaller sets of processors. Use PETSC_NULL_OBJECT for default in Fortran
5824b9ad928SBarry Smith 
5834b9ad928SBarry Smith    Level: intermediate
5844b9ad928SBarry Smith 
5854b9ad928SBarry Smith    Notes:
5864b9ad928SBarry Smith      If the number of levels is one then the multigrid uses the -mg_levels prefix
5874b9ad928SBarry Smith   for setting the level options rather than the -mg_coarse prefix.
5884b9ad928SBarry Smith 
5894b9ad928SBarry Smith .keywords: MG, set, levels, multigrid
5904b9ad928SBarry Smith 
59197177400SBarry Smith .seealso: PCMGSetType(), PCMGGetLevels()
5924b9ad928SBarry Smith @*/
59397177400SBarry Smith PetscErrorCode PETSCKSP_DLLEXPORT PCMGSetLevels(PC pc,PetscInt levels,MPI_Comm *comms)
5944b9ad928SBarry Smith {
595dfbe8321SBarry Smith   PetscErrorCode ierr;
596ada7143aSSatish Balay   PC_MG          **mg=0;
5974b9ad928SBarry Smith 
5984b9ad928SBarry Smith   PetscFunctionBegin;
5994482741eSBarry Smith   PetscValidHeaderSpecific(pc,PC_COOKIE,1);
6004b9ad928SBarry Smith 
6014b9ad928SBarry Smith   if (pc->data) {
6021302d50aSBarry Smith     SETERRQ(PETSC_ERR_ORDER,"Number levels already set for MG\n\
60397177400SBarry Smith     make sure that you call PCMGSetLevels() before KSPSetFromOptions()");
6044b9ad928SBarry Smith   }
6057adad957SLisandro Dalcin   ierr                     = PCMGCreate_Private(((PetscObject)pc)->comm,levels,pc,comms,&mg);CHKERRQ(ierr);
6069dcbbd2bSBarry Smith   mg[0]->am                = PC_MG_MULTIPLICATIVE;
6074b9ad928SBarry Smith   pc->data                 = (void*)mg;
6084b9ad928SBarry Smith   pc->ops->applyrichardson = PCApplyRichardson_MG;
6094b9ad928SBarry Smith   PetscFunctionReturn(0);
6104b9ad928SBarry Smith }
6114b9ad928SBarry Smith 
6124b9ad928SBarry Smith #undef __FUNCT__
6139dcbbd2bSBarry Smith #define __FUNCT__ "PCMGGetLevels"
6144b9ad928SBarry Smith /*@
61597177400SBarry Smith    PCMGGetLevels - Gets the number of levels to use with MG.
6164b9ad928SBarry Smith 
6174b9ad928SBarry Smith    Not Collective
6184b9ad928SBarry Smith 
6194b9ad928SBarry Smith    Input Parameter:
6204b9ad928SBarry Smith .  pc - the preconditioner context
6214b9ad928SBarry Smith 
6224b9ad928SBarry Smith    Output parameter:
6234b9ad928SBarry Smith .  levels - the number of levels
6244b9ad928SBarry Smith 
6254b9ad928SBarry Smith    Level: advanced
6264b9ad928SBarry Smith 
6274b9ad928SBarry Smith .keywords: MG, get, levels, multigrid
6284b9ad928SBarry Smith 
62997177400SBarry Smith .seealso: PCMGSetLevels()
6304b9ad928SBarry Smith @*/
63197177400SBarry Smith PetscErrorCode PETSCKSP_DLLEXPORT PCMGGetLevels(PC pc,PetscInt *levels)
6324b9ad928SBarry Smith {
6339dcbbd2bSBarry Smith   PC_MG  **mg;
6344b9ad928SBarry Smith 
6354b9ad928SBarry Smith   PetscFunctionBegin;
6364482741eSBarry Smith   PetscValidHeaderSpecific(pc,PC_COOKIE,1);
6374482741eSBarry Smith   PetscValidIntPointer(levels,2);
6384b9ad928SBarry Smith 
6399dcbbd2bSBarry Smith   mg      = (PC_MG**)pc->data;
6404b9ad928SBarry Smith   *levels = mg[0]->levels;
6414b9ad928SBarry Smith   PetscFunctionReturn(0);
6424b9ad928SBarry Smith }
6434b9ad928SBarry Smith 
6444b9ad928SBarry Smith #undef __FUNCT__
6459dcbbd2bSBarry Smith #define __FUNCT__ "PCMGSetType"
6464b9ad928SBarry Smith /*@
64797177400SBarry Smith    PCMGSetType - Determines the form of multigrid to use:
6484b9ad928SBarry Smith    multiplicative, additive, full, or the Kaskade algorithm.
6494b9ad928SBarry Smith 
6504b9ad928SBarry Smith    Collective on PC
6514b9ad928SBarry Smith 
6524b9ad928SBarry Smith    Input Parameters:
6534b9ad928SBarry Smith +  pc - the preconditioner context
6549dcbbd2bSBarry Smith -  form - multigrid form, one of PC_MG_MULTIPLICATIVE, PC_MG_ADDITIVE,
6559dcbbd2bSBarry Smith    PC_MG_FULL, PC_MG_KASKADE
6564b9ad928SBarry Smith 
6574b9ad928SBarry Smith    Options Database Key:
6584b9ad928SBarry Smith .  -pc_mg_type <form> - Sets <form>, one of multiplicative,
6594b9ad928SBarry Smith    additive, full, kaskade
6604b9ad928SBarry Smith 
6614b9ad928SBarry Smith    Level: advanced
6624b9ad928SBarry Smith 
6634b9ad928SBarry Smith .keywords: MG, set, method, multiplicative, additive, full, Kaskade, multigrid
6644b9ad928SBarry Smith 
66597177400SBarry Smith .seealso: PCMGSetLevels()
6664b9ad928SBarry Smith @*/
6679dcbbd2bSBarry Smith PetscErrorCode PETSCKSP_DLLEXPORT PCMGSetType(PC pc,PCMGType form)
6684b9ad928SBarry Smith {
6699dcbbd2bSBarry Smith   PC_MG **mg;
6704b9ad928SBarry Smith 
6714b9ad928SBarry Smith   PetscFunctionBegin;
6724482741eSBarry Smith   PetscValidHeaderSpecific(pc,PC_COOKIE,1);
6739dcbbd2bSBarry Smith   mg = (PC_MG**)pc->data;
6744b9ad928SBarry Smith 
6754b9ad928SBarry Smith   if (!mg) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Must set MG levels before calling");
6764b9ad928SBarry Smith   mg[0]->am = form;
6779dcbbd2bSBarry Smith   if (form == PC_MG_MULTIPLICATIVE) pc->ops->applyrichardson = PCApplyRichardson_MG;
6784b9ad928SBarry Smith   else pc->ops->applyrichardson = 0;
6794b9ad928SBarry Smith   PetscFunctionReturn(0);
6804b9ad928SBarry Smith }
6814b9ad928SBarry Smith 
6824b9ad928SBarry Smith #undef __FUNCT__
6830d353602SBarry Smith #define __FUNCT__ "PCMGSetCycleType"
6844b9ad928SBarry Smith /*@
6850d353602SBarry Smith    PCMGSetCycleType - Sets the type cycles to use.  Use PCMGSetCycleTypeOnLevel() for more
6864b9ad928SBarry Smith    complicated cycling.
6874b9ad928SBarry Smith 
6884b9ad928SBarry Smith    Collective on PC
6894b9ad928SBarry Smith 
6904b9ad928SBarry Smith    Input Parameters:
691c2be2410SBarry Smith +  pc - the multigrid context
6920d353602SBarry Smith -  PC_MG_CYCLE_V or PC_MG_CYCLE_W
6934b9ad928SBarry Smith 
6944b9ad928SBarry Smith    Options Database Key:
6950d353602SBarry Smith $  -pc_mg_cycle_type v or w
6964b9ad928SBarry Smith 
6974b9ad928SBarry Smith    Level: advanced
6984b9ad928SBarry Smith 
6994b9ad928SBarry Smith .keywords: MG, set, cycles, V-cycle, W-cycle, multigrid
7004b9ad928SBarry Smith 
7010d353602SBarry Smith .seealso: PCMGSetCycleTypeOnLevel()
7024b9ad928SBarry Smith @*/
7030d353602SBarry Smith PetscErrorCode PETSCKSP_DLLEXPORT PCMGSetCycleType(PC pc,PCMGCycleType n)
7044b9ad928SBarry Smith {
7059dcbbd2bSBarry Smith   PC_MG    **mg;
70679416396SBarry Smith   PetscInt i,levels;
7074b9ad928SBarry Smith 
7084b9ad928SBarry Smith   PetscFunctionBegin;
7094482741eSBarry Smith   PetscValidHeaderSpecific(pc,PC_COOKIE,1);
7109dcbbd2bSBarry Smith   mg     = (PC_MG**)pc->data;
7114b9ad928SBarry Smith   if (!mg) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Must set MG levels before calling");
7124b9ad928SBarry Smith   levels = mg[0]->levels;
7134b9ad928SBarry Smith 
7144b9ad928SBarry Smith   for (i=0; i<levels; i++) {
7154b9ad928SBarry Smith     mg[i]->cycles  = n;
7164b9ad928SBarry Smith   }
7174b9ad928SBarry Smith   PetscFunctionReturn(0);
7184b9ad928SBarry Smith }
7194b9ad928SBarry Smith 
7204b9ad928SBarry Smith #undef __FUNCT__
7218cc2d5dfSBarry Smith #define __FUNCT__ "PCMGMultiplicativeSetCycles"
7228cc2d5dfSBarry Smith /*@
7238cc2d5dfSBarry Smith    PCMGMultiplicativeSetCycles - Sets the number of cycles to use for each preconditioner step
7248cc2d5dfSBarry Smith          of multigrid when PCMGType of PC_MG_MULTIPLICATIVE is used
7258cc2d5dfSBarry Smith 
7268cc2d5dfSBarry Smith    Collective on PC
7278cc2d5dfSBarry Smith 
7288cc2d5dfSBarry Smith    Input Parameters:
7298cc2d5dfSBarry Smith +  pc - the multigrid context
7308cc2d5dfSBarry Smith -  n - number of cycles (default is 1)
7318cc2d5dfSBarry Smith 
7328cc2d5dfSBarry Smith    Options Database Key:
7338cc2d5dfSBarry Smith $  -pc_mg_multiplicative_cycles n
7348cc2d5dfSBarry Smith 
7358cc2d5dfSBarry Smith    Level: advanced
7368cc2d5dfSBarry Smith 
7378cc2d5dfSBarry Smith    Notes: This is not associated with setting a v or w cycle, that is set with PCMGSetCycleType()
7388cc2d5dfSBarry Smith 
7398cc2d5dfSBarry Smith .keywords: MG, set, cycles, V-cycle, W-cycle, multigrid
7408cc2d5dfSBarry Smith 
7418cc2d5dfSBarry Smith .seealso: PCMGSetCycleTypeOnLevel(), PCMGSetCycleType()
7428cc2d5dfSBarry Smith @*/
7438cc2d5dfSBarry Smith PetscErrorCode PETSCKSP_DLLEXPORT PCMGMultiplicativeSetCycles(PC pc,PetscInt n)
7448cc2d5dfSBarry Smith {
7458cc2d5dfSBarry Smith   PC_MG    **mg;
7468cc2d5dfSBarry Smith   PetscInt i,levels;
7478cc2d5dfSBarry Smith 
7488cc2d5dfSBarry Smith   PetscFunctionBegin;
7498cc2d5dfSBarry Smith   PetscValidHeaderSpecific(pc,PC_COOKIE,1);
7508cc2d5dfSBarry Smith   mg     = (PC_MG**)pc->data;
7518cc2d5dfSBarry Smith   if (!mg) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Must set MG levels before calling");
7528cc2d5dfSBarry Smith   levels = mg[0]->levels;
7538cc2d5dfSBarry Smith 
7548cc2d5dfSBarry Smith   for (i=0; i<levels; i++) {
7558cc2d5dfSBarry Smith     mg[i]->cyclesperpcapply  = n;
7568cc2d5dfSBarry Smith   }
7578cc2d5dfSBarry Smith   PetscFunctionReturn(0);
7588cc2d5dfSBarry Smith }
7598cc2d5dfSBarry Smith 
7608cc2d5dfSBarry Smith #undef __FUNCT__
7619dcbbd2bSBarry Smith #define __FUNCT__ "PCMGSetGalerkin"
762c2be2410SBarry Smith /*@
76397177400SBarry Smith    PCMGSetGalerkin - Causes the coarser grid matrices to be computed from the
764c2be2410SBarry Smith       finest grid via the Galerkin process: A_i-1 = r_i * A_i * r_i^t
765c2be2410SBarry Smith 
766c2be2410SBarry Smith    Collective on PC
767c2be2410SBarry Smith 
768c2be2410SBarry Smith    Input Parameters:
7693fc8bf9cSBarry Smith .  pc - the multigrid context
770c2be2410SBarry Smith 
771c2be2410SBarry Smith    Options Database Key:
772c2be2410SBarry Smith $  -pc_mg_galerkin
773c2be2410SBarry Smith 
774c2be2410SBarry Smith    Level: intermediate
775c2be2410SBarry Smith 
776c2be2410SBarry Smith .keywords: MG, set, Galerkin
777c2be2410SBarry Smith 
7783fc8bf9cSBarry Smith .seealso: PCMGGetGalerkin()
7793fc8bf9cSBarry Smith 
780c2be2410SBarry Smith @*/
78197177400SBarry Smith PetscErrorCode PETSCKSP_DLLEXPORT PCMGSetGalerkin(PC pc)
782c2be2410SBarry Smith {
7839dcbbd2bSBarry Smith   PC_MG    **mg;
784c2be2410SBarry Smith   PetscInt i,levels;
785c2be2410SBarry Smith 
786c2be2410SBarry Smith   PetscFunctionBegin;
787c2be2410SBarry Smith   PetscValidHeaderSpecific(pc,PC_COOKIE,1);
7889dcbbd2bSBarry Smith   mg     = (PC_MG**)pc->data;
789c2be2410SBarry Smith   if (!mg) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Must set MG levels before calling");
790c2be2410SBarry Smith   levels = mg[0]->levels;
791c2be2410SBarry Smith 
792c2be2410SBarry Smith   for (i=0; i<levels; i++) {
793c2be2410SBarry Smith     mg[i]->galerkin = PETSC_TRUE;
794c2be2410SBarry Smith   }
795c2be2410SBarry Smith   PetscFunctionReturn(0);
796c2be2410SBarry Smith }
797c2be2410SBarry Smith 
798c2be2410SBarry Smith #undef __FUNCT__
7993fc8bf9cSBarry Smith #define __FUNCT__ "PCMGGetGalerkin"
8003fc8bf9cSBarry Smith /*@
8013fc8bf9cSBarry Smith    PCMGGetGalerkin - Checks if Galerkin multigrid is being used, i.e.
8023fc8bf9cSBarry Smith       A_i-1 = r_i * A_i * r_i^t
8033fc8bf9cSBarry Smith 
8043fc8bf9cSBarry Smith    Not Collective
8053fc8bf9cSBarry Smith 
8063fc8bf9cSBarry Smith    Input Parameter:
8073fc8bf9cSBarry Smith .  pc - the multigrid context
8083fc8bf9cSBarry Smith 
8093fc8bf9cSBarry Smith    Output Parameter:
8103fc8bf9cSBarry Smith .  gelerkin - PETSC_TRUE or PETSC_FALSE
8113fc8bf9cSBarry Smith 
8123fc8bf9cSBarry Smith    Options Database Key:
8133fc8bf9cSBarry Smith $  -pc_mg_galerkin
8143fc8bf9cSBarry Smith 
8153fc8bf9cSBarry Smith    Level: intermediate
8163fc8bf9cSBarry Smith 
8173fc8bf9cSBarry Smith .keywords: MG, set, Galerkin
8183fc8bf9cSBarry Smith 
8193fc8bf9cSBarry Smith .seealso: PCMGSetGalerkin()
8203fc8bf9cSBarry Smith 
8213fc8bf9cSBarry Smith @*/
8223fc8bf9cSBarry Smith PetscErrorCode PETSCKSP_DLLEXPORT PCMGGetGalerkin(PC pc,PetscTruth *galerkin)
8233fc8bf9cSBarry Smith {
8243fc8bf9cSBarry Smith   PC_MG    **mg;
8253fc8bf9cSBarry Smith 
8263fc8bf9cSBarry Smith   PetscFunctionBegin;
8273fc8bf9cSBarry Smith   PetscValidHeaderSpecific(pc,PC_COOKIE,1);
8283fc8bf9cSBarry Smith   mg     = (PC_MG**)pc->data;
8293fc8bf9cSBarry Smith   if (!mg) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Must set MG levels before calling");
8303fc8bf9cSBarry Smith   *galerkin = mg[0]->galerkin;
8313fc8bf9cSBarry Smith   PetscFunctionReturn(0);
8323fc8bf9cSBarry Smith }
8333fc8bf9cSBarry Smith 
8343fc8bf9cSBarry Smith #undef __FUNCT__
8359dcbbd2bSBarry Smith #define __FUNCT__ "PCMGSetNumberSmoothDown"
8364b9ad928SBarry Smith /*@
83797177400SBarry Smith    PCMGSetNumberSmoothDown - Sets the number of pre-smoothing steps to
83897177400SBarry Smith    use on all levels. Use PCMGGetSmootherDown() to set different
8394b9ad928SBarry Smith    pre-smoothing steps on different levels.
8404b9ad928SBarry Smith 
8414b9ad928SBarry Smith    Collective on PC
8424b9ad928SBarry Smith 
8434b9ad928SBarry Smith    Input Parameters:
8444b9ad928SBarry Smith +  mg - the multigrid context
8454b9ad928SBarry Smith -  n - the number of smoothing steps
8464b9ad928SBarry Smith 
8474b9ad928SBarry Smith    Options Database Key:
8484b9ad928SBarry Smith .  -pc_mg_smoothdown <n> - Sets number of pre-smoothing steps
8494b9ad928SBarry Smith 
8504b9ad928SBarry Smith    Level: advanced
8514b9ad928SBarry Smith 
8524b9ad928SBarry Smith .keywords: MG, smooth, down, pre-smoothing, steps, multigrid
8534b9ad928SBarry Smith 
85497177400SBarry Smith .seealso: PCMGSetNumberSmoothUp()
8554b9ad928SBarry Smith @*/
85697177400SBarry Smith PetscErrorCode PETSCKSP_DLLEXPORT PCMGSetNumberSmoothDown(PC pc,PetscInt n)
8574b9ad928SBarry Smith {
8589dcbbd2bSBarry Smith   PC_MG          **mg;
8596849ba73SBarry Smith   PetscErrorCode ierr;
86079416396SBarry Smith   PetscInt       i,levels;
8614b9ad928SBarry Smith 
8624b9ad928SBarry Smith   PetscFunctionBegin;
8634482741eSBarry Smith   PetscValidHeaderSpecific(pc,PC_COOKIE,1);
8649dcbbd2bSBarry Smith   mg     = (PC_MG**)pc->data;
8654b9ad928SBarry Smith   if (!mg) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Must set MG levels before calling");
8664b9ad928SBarry Smith   levels = mg[0]->levels;
8674b9ad928SBarry Smith 
868b05257ddSBarry Smith   for (i=1; i<levels; i++) {
8694b9ad928SBarry Smith     /* make sure smoother up and down are different */
87097177400SBarry Smith     ierr = PCMGGetSmootherUp(pc,i,PETSC_NULL);CHKERRQ(ierr);
8714b9ad928SBarry Smith     ierr = KSPSetTolerances(mg[i]->smoothd,PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT,n);CHKERRQ(ierr);
8724b9ad928SBarry Smith     mg[i]->default_smoothd = n;
8734b9ad928SBarry Smith   }
8744b9ad928SBarry Smith   PetscFunctionReturn(0);
8754b9ad928SBarry Smith }
8764b9ad928SBarry Smith 
8774b9ad928SBarry Smith #undef __FUNCT__
8789dcbbd2bSBarry Smith #define __FUNCT__ "PCMGSetNumberSmoothUp"
8794b9ad928SBarry Smith /*@
88097177400SBarry Smith    PCMGSetNumberSmoothUp - Sets the number of post-smoothing steps to use
88197177400SBarry Smith    on all levels. Use PCMGGetSmootherUp() to set different numbers of
8824b9ad928SBarry Smith    post-smoothing steps on different levels.
8834b9ad928SBarry Smith 
8844b9ad928SBarry Smith    Collective on PC
8854b9ad928SBarry Smith 
8864b9ad928SBarry Smith    Input Parameters:
8874b9ad928SBarry Smith +  mg - the multigrid context
8884b9ad928SBarry Smith -  n - the number of smoothing steps
8894b9ad928SBarry Smith 
8904b9ad928SBarry Smith    Options Database Key:
8914b9ad928SBarry Smith .  -pc_mg_smoothup <n> - Sets number of post-smoothing steps
8924b9ad928SBarry Smith 
8934b9ad928SBarry Smith    Level: advanced
8944b9ad928SBarry Smith 
8954b9ad928SBarry Smith    Note: this does not set a value on the coarsest grid, since we assume that
896a8c7a070SBarry Smith     there is no separate smooth up on the coarsest grid.
8974b9ad928SBarry Smith 
8984b9ad928SBarry Smith .keywords: MG, smooth, up, post-smoothing, steps, multigrid
8994b9ad928SBarry Smith 
90097177400SBarry Smith .seealso: PCMGSetNumberSmoothDown()
9014b9ad928SBarry Smith @*/
90297177400SBarry Smith PetscErrorCode PETSCKSP_DLLEXPORT PCMGSetNumberSmoothUp(PC pc,PetscInt n)
9034b9ad928SBarry Smith {
9049dcbbd2bSBarry Smith   PC_MG          **mg;
9056849ba73SBarry Smith   PetscErrorCode ierr;
90679416396SBarry Smith   PetscInt       i,levels;
9074b9ad928SBarry Smith 
9084b9ad928SBarry Smith   PetscFunctionBegin;
9094482741eSBarry Smith   PetscValidHeaderSpecific(pc,PC_COOKIE,1);
9109dcbbd2bSBarry Smith   mg     = (PC_MG**)pc->data;
9114b9ad928SBarry Smith   if (!mg) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Must set MG levels before calling");
9124b9ad928SBarry Smith   levels = mg[0]->levels;
9134b9ad928SBarry Smith 
9144b9ad928SBarry Smith   for (i=1; i<levels; i++) {
9154b9ad928SBarry Smith     /* make sure smoother up and down are different */
91697177400SBarry Smith     ierr = PCMGGetSmootherUp(pc,i,PETSC_NULL);CHKERRQ(ierr);
9174b9ad928SBarry Smith     ierr = KSPSetTolerances(mg[i]->smoothu,PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT,n);CHKERRQ(ierr);
9184b9ad928SBarry Smith     mg[i]->default_smoothu = n;
9194b9ad928SBarry Smith   }
9204b9ad928SBarry Smith   PetscFunctionReturn(0);
9214b9ad928SBarry Smith }
9224b9ad928SBarry Smith 
9234b9ad928SBarry Smith /* ----------------------------------------------------------------------------------------*/
9244b9ad928SBarry Smith 
9253b09bd56SBarry Smith /*MC
926ccb205f8SBarry Smith    PCMG - Use multigrid preconditioning. This preconditioner requires you provide additional
9273b09bd56SBarry Smith     information about the coarser grid matrices and restriction/interpolation operators.
9283b09bd56SBarry Smith 
9293b09bd56SBarry Smith    Options Database Keys:
9303b09bd56SBarry Smith +  -pc_mg_levels <nlevels> - number of levels including finest
9310d353602SBarry Smith .  -pc_mg_cycles v or w
93279416396SBarry Smith .  -pc_mg_smoothup <n> - number of smoothing steps after interpolation
9333b09bd56SBarry Smith .  -pc_mg_smoothdown <n> - number of smoothing steps before applying restriction operator
9343b09bd56SBarry Smith .  -pc_mg_type <additive,multiplicative,full,cascade> - multiplicative is the default
9353b09bd56SBarry Smith .  -pc_mg_log - log information about time spent on each level of the solver
9363b09bd56SBarry Smith .  -pc_mg_monitor - print information on the multigrid convergence
93768eff7e6SBarry Smith .  -pc_mg_galerkin - use Galerkin process to compute coarser operators
9383b09bd56SBarry Smith -  -pc_mg_dump_matlab - dumps the matrices for each level and the restriction/interpolation matrices
9393b09bd56SBarry Smith                         to the Socket viewer for reading from Matlab.
9403b09bd56SBarry Smith 
9413b09bd56SBarry Smith    Notes:
9423b09bd56SBarry Smith 
9433b09bd56SBarry Smith    Level: intermediate
9443b09bd56SBarry Smith 
9458f87f92bSBarry Smith    Concepts: multigrid/multilevel
9463b09bd56SBarry Smith 
9473b09bd56SBarry Smith .seealso:  PCCreate(), PCSetType(), PCType (for list of available types), PC, PCMGType,
9480d353602SBarry Smith            PCMGSetLevels(), PCMGGetLevels(), PCMGSetType(), PCMGSetCycleType(), PCMGSetNumberSmoothDown(),
94997177400SBarry Smith            PCMGSetNumberSmoothUp(), PCMGGetCoarseSolve(), PCMGSetResidual(), PCMGSetInterpolation(),
95097177400SBarry Smith            PCMGSetRestriction(), PCMGGetSmoother(), PCMGGetSmootherUp(), PCMGGetSmootherDown(),
9510d353602SBarry Smith            PCMGSetCycleTypeOnLevel(), PCMGSetRhs(), PCMGSetX(), PCMGSetR()
9523b09bd56SBarry Smith M*/
9533b09bd56SBarry Smith 
9544b9ad928SBarry Smith EXTERN_C_BEGIN
9554b9ad928SBarry Smith #undef __FUNCT__
9564b9ad928SBarry Smith #define __FUNCT__ "PCCreate_MG"
957dba47a55SKris Buschelman PetscErrorCode PETSCKSP_DLLEXPORT PCCreate_MG(PC pc)
9584b9ad928SBarry Smith {
9594b9ad928SBarry Smith   PetscFunctionBegin;
9604b9ad928SBarry Smith   pc->ops->apply          = PCApply_MG;
9614b9ad928SBarry Smith   pc->ops->setup          = PCSetUp_MG;
9624b9ad928SBarry Smith   pc->ops->destroy        = PCDestroy_MG;
9634b9ad928SBarry Smith   pc->ops->setfromoptions = PCSetFromOptions_MG;
9644b9ad928SBarry Smith   pc->ops->view           = PCView_MG;
9654b9ad928SBarry Smith 
9664b9ad928SBarry Smith   pc->data                = (void*)0;
9674b9ad928SBarry Smith   PetscFunctionReturn(0);
9684b9ad928SBarry Smith }
9694b9ad928SBarry Smith EXTERN_C_END
970