xref: /petsc/src/ksp/pc/impls/mg/mg.c (revision efb308899f58eff35e31f4136d1431f0c81bf4bc)
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;
1579416396SBarry Smith   PetscInt       cycles = mg->cycles;
164b9ad928SBarry Smith 
174b9ad928SBarry Smith   PetscFunctionBegin;
184b9ad928SBarry Smith   if (converged) *converged = PETSC_FALSE;
194b9ad928SBarry Smith 
204b9ad928SBarry Smith   if (mg->eventsolve) {ierr = PetscLogEventBegin(mg->eventsolve,0,0,0,0);CHKERRQ(ierr);}
2123ce1328SBarry Smith   ierr = KSPSolve(mg->smoothd,mg->b,mg->x);CHKERRQ(ierr);
224b9ad928SBarry Smith   if (mg->eventsolve) {ierr = PetscLogEventEnd(mg->eventsolve,0,0,0,0);CHKERRQ(ierr);}
234b9ad928SBarry Smith   if (mg->level) {  /* not the coarsest grid */
244b9ad928SBarry Smith     ierr = (*mg->residual)(mg->A,mg->b,mg->x,mg->r);CHKERRQ(ierr);
254b9ad928SBarry Smith 
264b9ad928SBarry Smith     /* if on finest level and have convergence criteria set */
274b9ad928SBarry Smith     if (mg->level == mg->levels-1 && mg->ttol) {
284b9ad928SBarry Smith       PetscReal rnorm;
294b9ad928SBarry Smith       ierr = VecNorm(mg->r,NORM_2,&rnorm);CHKERRQ(ierr);
304b9ad928SBarry Smith       if (rnorm <= mg->ttol) {
314b9ad928SBarry Smith         *converged = PETSC_TRUE;
3270441072SBarry Smith         if (rnorm < mg->abstol) {
339dcbbd2bSBarry Smith           ierr = PetscLogInfo((0,"PCMGMCycle_Private:Linear solver has converged. Residual norm %g is less than absolute tolerance %g\n",rnorm,mg->abstol));CHKERRQ(ierr);
344b9ad928SBarry Smith         } else {
359dcbbd2bSBarry Smith           ierr = PetscLogInfo((0,"PCMGMCycle_Private:Linear solver has converged. Residual norm %g is less than relative tolerance times initial residual norm %g\n",rnorm,mg->ttol));CHKERRQ(ierr);
364b9ad928SBarry Smith         }
374b9ad928SBarry Smith         PetscFunctionReturn(0);
384b9ad928SBarry Smith       }
394b9ad928SBarry Smith     }
404b9ad928SBarry Smith 
414b9ad928SBarry Smith     mgc = *(mglevels - 1);
424b9ad928SBarry Smith     ierr = MatRestrict(mg->restrct,mg->r,mgc->b);CHKERRQ(ierr);
43*efb30889SBarry Smith     ierr = VecSet(mgc->x,0.0);CHKERRQ(ierr);
444b9ad928SBarry Smith     while (cycles--) {
459dcbbd2bSBarry Smith       ierr = PCMGMCycle_Private(mglevels-1,converged);CHKERRQ(ierr);
464b9ad928SBarry Smith     }
474b9ad928SBarry Smith     ierr = MatInterpolateAdd(mg->interpolate,mgc->x,mg->x,mg->x);CHKERRQ(ierr);
484b9ad928SBarry Smith     if (mg->eventsolve) {ierr = PetscLogEventBegin(mg->eventsolve,0,0,0,0);CHKERRQ(ierr);}
4923ce1328SBarry Smith     ierr = KSPSolve(mg->smoothu,mg->b,mg->x);CHKERRQ(ierr);
504b9ad928SBarry Smith     if (mg->eventsolve) {ierr = PetscLogEventEnd(mg->eventsolve,0,0,0,0);CHKERRQ(ierr);}
514b9ad928SBarry Smith   }
524b9ad928SBarry Smith   PetscFunctionReturn(0);
534b9ad928SBarry Smith }
544b9ad928SBarry Smith 
554b9ad928SBarry Smith /*
569dcbbd2bSBarry Smith        PCMGCreate_Private - Creates a PC_MG structure for use with the
574b9ad928SBarry Smith                multigrid code. Level 0 is the coarsest. (But the
584b9ad928SBarry Smith                finest level is stored first in the array).
594b9ad928SBarry Smith 
604b9ad928SBarry Smith */
614b9ad928SBarry Smith #undef __FUNCT__
629dcbbd2bSBarry Smith #define __FUNCT__ "PCMGCreate_Private"
639dcbbd2bSBarry Smith static PetscErrorCode PCMGCreate_Private(MPI_Comm comm,PetscInt levels,PC pc,MPI_Comm *comms,PC_MG ***result)
644b9ad928SBarry Smith {
659dcbbd2bSBarry Smith   PC_MG          **mg;
666849ba73SBarry Smith   PetscErrorCode ierr;
6779416396SBarry Smith   PetscInt       i;
6879416396SBarry Smith   PetscMPIInt    size;
69f69a0ea3SMatthew Knepley   const char     *prefix;
704b9ad928SBarry Smith   PC             ipc;
714b9ad928SBarry Smith 
724b9ad928SBarry Smith   PetscFunctionBegin;
739dcbbd2bSBarry Smith   ierr = PetscMalloc(levels*sizeof(PC_MG*),&mg);CHKERRQ(ierr);
749dcbbd2bSBarry Smith   ierr = PetscLogObjectMemory(pc,levels*(sizeof(PC_MG*)+sizeof(PC_MG)));CHKERRQ(ierr);
754b9ad928SBarry Smith 
764b9ad928SBarry Smith   ierr = PCGetOptionsPrefix(pc,&prefix);CHKERRQ(ierr);
774b9ad928SBarry Smith 
784b9ad928SBarry Smith   for (i=0; i<levels; i++) {
799dcbbd2bSBarry Smith     ierr = PetscNew(PC_MG,&mg[i]);CHKERRQ(ierr);
804b9ad928SBarry Smith     mg[i]->level           = i;
814b9ad928SBarry Smith     mg[i]->levels          = levels;
824b9ad928SBarry Smith     mg[i]->cycles          = 1;
83c2be2410SBarry Smith     mg[i]->galerkin        = PETSC_FALSE;
84c2be2410SBarry Smith     mg[i]->galerkinused    = PETSC_FALSE;
8579416396SBarry Smith     mg[i]->default_smoothu = 1;
8679416396SBarry Smith     mg[i]->default_smoothd = 1;
874b9ad928SBarry Smith 
884b9ad928SBarry Smith     if (comms) comm = comms[i];
894b9ad928SBarry Smith     ierr = KSPCreate(comm,&mg[i]->smoothd);CHKERRQ(ierr);
9079416396SBarry Smith     ierr = KSPSetTolerances(mg[i]->smoothd,PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT, mg[i]->default_smoothd);CHKERRQ(ierr);
914b9ad928SBarry Smith     ierr = KSPSetOptionsPrefix(mg[i]->smoothd,prefix);CHKERRQ(ierr);
924b9ad928SBarry Smith 
934b9ad928SBarry Smith     /* do special stuff for coarse grid */
944b9ad928SBarry Smith     if (!i && levels > 1) {
954b9ad928SBarry Smith       ierr = KSPAppendOptionsPrefix(mg[0]->smoothd,"mg_coarse_");CHKERRQ(ierr);
964b9ad928SBarry Smith 
974b9ad928SBarry Smith       /* coarse solve is (redundant) LU by default */
984b9ad928SBarry Smith       ierr = KSPSetType(mg[0]->smoothd,KSPPREONLY);CHKERRQ(ierr);
994b9ad928SBarry Smith       ierr = KSPGetPC(mg[0]->smoothd,&ipc);CHKERRQ(ierr);
1004b9ad928SBarry Smith       ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
1014b9ad928SBarry Smith       if (size > 1) {
1024b9ad928SBarry Smith         ierr = PCSetType(ipc,PCREDUNDANT);CHKERRQ(ierr);
1034b9ad928SBarry Smith         ierr = PCRedundantGetPC(ipc,&ipc);CHKERRQ(ierr);
1044b9ad928SBarry Smith       }
1054b9ad928SBarry Smith       ierr = PCSetType(ipc,PCLU);CHKERRQ(ierr);
1064b9ad928SBarry Smith 
1074b9ad928SBarry Smith     } else {
1082e70eadcSBarry Smith       char tprefix[128];
10913f74950SBarry Smith       sprintf(tprefix,"mg_levels_%d_",(int)i);
1102e70eadcSBarry Smith       ierr = KSPAppendOptionsPrefix(mg[i]->smoothd,tprefix);CHKERRQ(ierr);
1114b9ad928SBarry Smith     }
11252e6d16bSBarry Smith     ierr = PetscLogObjectParent(pc,mg[i]->smoothd);CHKERRQ(ierr);
1134b9ad928SBarry Smith     mg[i]->smoothu         = mg[i]->smoothd;
1144b9ad928SBarry Smith     mg[i]->rtol = 0.0;
11570441072SBarry Smith     mg[i]->abstol = 0.0;
1164b9ad928SBarry Smith     mg[i]->dtol = 0.0;
1174b9ad928SBarry Smith     mg[i]->ttol = 0.0;
1184b9ad928SBarry Smith     mg[i]->eventsetup = 0;
1194b9ad928SBarry Smith     mg[i]->eventsolve = 0;
1204b9ad928SBarry Smith   }
1214b9ad928SBarry Smith   *result = mg;
1224b9ad928SBarry Smith   PetscFunctionReturn(0);
1234b9ad928SBarry Smith }
1244b9ad928SBarry Smith 
1254b9ad928SBarry Smith #undef __FUNCT__
1264b9ad928SBarry Smith #define __FUNCT__ "PCDestroy_MG"
1276849ba73SBarry Smith static PetscErrorCode PCDestroy_MG(PC pc)
1284b9ad928SBarry Smith {
1299dcbbd2bSBarry Smith   PC_MG          **mg = (PC_MG**)pc->data;
1306849ba73SBarry Smith   PetscErrorCode ierr;
13179416396SBarry Smith   PetscInt       i,n = mg[0]->levels;
1324b9ad928SBarry Smith 
1334b9ad928SBarry Smith   PetscFunctionBegin;
134c2be2410SBarry Smith   if (mg[0]->galerkinused) {
135c2be2410SBarry Smith     Mat B;
136c2be2410SBarry Smith     for (i=0; i<n-1; i++) {
137c2be2410SBarry Smith       ierr = KSPGetOperators(mg[i]->smoothd,0,&B,0);CHKERRQ(ierr);
138c2be2410SBarry Smith       ierr = MatDestroy(B);CHKERRQ(ierr);
139c2be2410SBarry Smith     }
140c2be2410SBarry Smith   }
141c2be2410SBarry Smith 
142fccaa45eSBarry Smith   for (i=0; i<n-1; i++) {
143630ba2eeSBarry Smith     if (mg[i+1]->r) {ierr = VecDestroy(mg[i+1]->r);CHKERRQ(ierr);}
144fccaa45eSBarry Smith     if (mg[i]->b) {ierr = VecDestroy(mg[i]->b);CHKERRQ(ierr);}
145fccaa45eSBarry Smith     if (mg[i]->x) {ierr = VecDestroy(mg[i]->x);CHKERRQ(ierr);}
146fccaa45eSBarry Smith     if (mg[i+1]->restrct) {ierr = MatDestroy(mg[i+1]->restrct);CHKERRQ(ierr);}
147fccaa45eSBarry Smith     if (mg[i+1]->interpolate) {ierr = MatDestroy(mg[i+1]->interpolate);CHKERRQ(ierr);}
148fccaa45eSBarry Smith   }
149fccaa45eSBarry Smith 
1504b9ad928SBarry Smith   for (i=0; i<n; i++) {
1514b9ad928SBarry Smith     if (mg[i]->smoothd != mg[i]->smoothu) {
1524b9ad928SBarry Smith       ierr = KSPDestroy(mg[i]->smoothd);CHKERRQ(ierr);
1534b9ad928SBarry Smith     }
1544b9ad928SBarry Smith     ierr = KSPDestroy(mg[i]->smoothu);CHKERRQ(ierr);
1554b9ad928SBarry Smith     ierr = PetscFree(mg[i]);CHKERRQ(ierr);
1564b9ad928SBarry Smith   }
1574b9ad928SBarry Smith   ierr = PetscFree(mg);CHKERRQ(ierr);
1584b9ad928SBarry Smith   PetscFunctionReturn(0);
1594b9ad928SBarry Smith }
1604b9ad928SBarry Smith 
1614b9ad928SBarry Smith 
1624b9ad928SBarry Smith 
1639dcbbd2bSBarry Smith EXTERN PetscErrorCode PCMGACycle_Private(PC_MG**);
1649dcbbd2bSBarry Smith EXTERN PetscErrorCode PCMGFCycle_Private(PC_MG**);
1659dcbbd2bSBarry Smith EXTERN PetscErrorCode PCMGKCycle_Private(PC_MG**);
1664b9ad928SBarry Smith 
1674b9ad928SBarry Smith /*
1684b9ad928SBarry Smith    PCApply_MG - Runs either an additive, multiplicative, Kaskadic
1694b9ad928SBarry Smith              or full cycle of multigrid.
1704b9ad928SBarry Smith 
1714b9ad928SBarry Smith   Note:
1729dcbbd2bSBarry Smith   A simple wrapper which calls PCMGMCycle(),PCMGACycle(), or PCMGFCycle().
1734b9ad928SBarry Smith */
1744b9ad928SBarry Smith #undef __FUNCT__
1754b9ad928SBarry Smith #define __FUNCT__ "PCApply_MG"
1766849ba73SBarry Smith static PetscErrorCode PCApply_MG(PC pc,Vec b,Vec x)
1774b9ad928SBarry Smith {
1789dcbbd2bSBarry Smith   PC_MG          **mg = (PC_MG**)pc->data;
1796849ba73SBarry Smith   PetscErrorCode ierr;
18079416396SBarry Smith   PetscInt       levels = mg[0]->levels;
1814b9ad928SBarry Smith 
1824b9ad928SBarry Smith   PetscFunctionBegin;
1834b9ad928SBarry Smith   mg[levels-1]->b = b;
1844b9ad928SBarry Smith   mg[levels-1]->x = x;
1859dcbbd2bSBarry Smith   if (!mg[levels-1]->r && mg[0]->am == PC_MG_ADDITIVE) {
1860a6bb862SBarry Smith     Vec tvec;
1870a6bb862SBarry Smith     ierr = VecDuplicate(mg[levels-1]->b,&tvec);CHKERRQ(ierr);
18897177400SBarry Smith     ierr = PCMGSetR(pc,levels-1,tvec);CHKERRQ(ierr);
1890a6bb862SBarry Smith     ierr = VecDestroy(tvec);CHKERRQ(ierr);
1900a6bb862SBarry Smith   }
1919dcbbd2bSBarry Smith   if (mg[0]->am == PC_MG_MULTIPLICATIVE) {
192*efb30889SBarry Smith     ierr = VecSet(x,0.0);CHKERRQ(ierr);
1939dcbbd2bSBarry Smith     ierr = PCMGMCycle_Private(mg+levels-1,PETSC_NULL);CHKERRQ(ierr);
1944b9ad928SBarry Smith   }
1959dcbbd2bSBarry Smith   else if (mg[0]->am == PC_MG_ADDITIVE) {
1969dcbbd2bSBarry Smith     ierr = PCMGACycle_Private(mg);CHKERRQ(ierr);
1974b9ad928SBarry Smith   }
1989dcbbd2bSBarry Smith   else if (mg[0]->am == PC_MG_KASKADE) {
1999dcbbd2bSBarry Smith     ierr = PCMGKCycle_Private(mg);CHKERRQ(ierr);
2004b9ad928SBarry Smith   }
2014b9ad928SBarry Smith   else {
2029dcbbd2bSBarry Smith     ierr = PCMGFCycle_Private(mg);CHKERRQ(ierr);
2034b9ad928SBarry Smith   }
2044b9ad928SBarry Smith   PetscFunctionReturn(0);
2054b9ad928SBarry Smith }
2064b9ad928SBarry Smith 
2074b9ad928SBarry Smith #undef __FUNCT__
2084b9ad928SBarry Smith #define __FUNCT__ "PCApplyRichardson_MG"
20979416396SBarry Smith static PetscErrorCode PCApplyRichardson_MG(PC pc,Vec b,Vec x,Vec w,PetscReal rtol,PetscReal abstol, PetscReal dtol,PetscInt its)
2104b9ad928SBarry Smith {
2119dcbbd2bSBarry Smith   PC_MG          **mg = (PC_MG**)pc->data;
212dfbe8321SBarry Smith   PetscErrorCode ierr;
21379416396SBarry Smith   PetscInt       levels = mg[0]->levels;
2144b9ad928SBarry Smith   PetscTruth     converged = PETSC_FALSE;
2154b9ad928SBarry Smith 
2164b9ad928SBarry Smith   PetscFunctionBegin;
2174b9ad928SBarry Smith   mg[levels-1]->b    = b;
2184b9ad928SBarry Smith   mg[levels-1]->x    = x;
2194b9ad928SBarry Smith 
2204b9ad928SBarry Smith   mg[levels-1]->rtol = rtol;
22170441072SBarry Smith   mg[levels-1]->abstol = abstol;
2224b9ad928SBarry Smith   mg[levels-1]->dtol = dtol;
2234b9ad928SBarry Smith   if (rtol) {
2244b9ad928SBarry Smith     /* compute initial residual norm for relative convergence test */
2254b9ad928SBarry Smith     PetscReal rnorm;
2264b9ad928SBarry Smith     ierr               = (*mg[levels-1]->residual)(mg[levels-1]->A,b,x,w);CHKERRQ(ierr);
2274b9ad928SBarry Smith     ierr               = VecNorm(w,NORM_2,&rnorm);CHKERRQ(ierr);
22870441072SBarry Smith     mg[levels-1]->ttol = PetscMax(rtol*rnorm,abstol);
22970441072SBarry Smith   } else if (abstol) {
23070441072SBarry Smith     mg[levels-1]->ttol = abstol;
2314b9ad928SBarry Smith   } else {
2324b9ad928SBarry Smith     mg[levels-1]->ttol = 0.0;
2334b9ad928SBarry Smith   }
2344b9ad928SBarry Smith 
2354b9ad928SBarry Smith   while (its-- && !converged) {
2369dcbbd2bSBarry Smith     ierr = PCMGMCycle_Private(mg+levels-1,&converged);CHKERRQ(ierr);
2374b9ad928SBarry Smith   }
2384b9ad928SBarry Smith   PetscFunctionReturn(0);
2394b9ad928SBarry Smith }
2404b9ad928SBarry Smith 
2414b9ad928SBarry Smith #undef __FUNCT__
2424b9ad928SBarry Smith #define __FUNCT__ "PCSetFromOptions_MG"
2436ca4d86aSHong Zhang PetscErrorCode PCSetFromOptions_MG(PC pc)
2444b9ad928SBarry Smith {
245dfbe8321SBarry Smith   PetscErrorCode ierr;
2469dcbbd2bSBarry Smith   PetscInt       m,levels = 1;
2474b9ad928SBarry Smith   PetscTruth     flg;
2489dcbbd2bSBarry Smith   PC_MG          **mg = (PC_MG**)pc->data;
2499dcbbd2bSBarry Smith   PCMGType       mgtype = mg[0]->am;;
2504b9ad928SBarry Smith 
2514b9ad928SBarry Smith   PetscFunctionBegin;
2524b9ad928SBarry Smith 
2534b9ad928SBarry Smith   ierr = PetscOptionsHead("Multigrid options");CHKERRQ(ierr);
2544b9ad928SBarry Smith     if (!pc->data) {
2559dcbbd2bSBarry Smith       ierr = PetscOptionsInt("-pc_mg_levels","Number of Levels","PCMGSetLevels",levels,&levels,&flg);CHKERRQ(ierr);
25697177400SBarry Smith       ierr = PCMGSetLevels(pc,levels,PETSC_NULL);CHKERRQ(ierr);
2574b9ad928SBarry Smith     }
2589dcbbd2bSBarry Smith     ierr = PetscOptionsInt("-pc_mg_cycles","1 for V cycle, 2 for W-cycle","PCMGSetCycles",1,&m,&flg);CHKERRQ(ierr);
2594b9ad928SBarry Smith     if (flg) {
26097177400SBarry Smith       ierr = PCMGSetCycles(pc,m);CHKERRQ(ierr);
2614b9ad928SBarry Smith     }
2629dcbbd2bSBarry Smith     ierr = PetscOptionsName("-pc_mg_galerkin","Use Galerkin process to compute coarser operators","PCMGSetGalerkin",&flg);CHKERRQ(ierr);
263c2be2410SBarry Smith     if (flg) {
26497177400SBarry Smith       ierr = PCMGSetGalerkin(pc);CHKERRQ(ierr);
265c2be2410SBarry Smith     }
2669dcbbd2bSBarry Smith     ierr = PetscOptionsInt("-pc_mg_smoothup","Number of post-smoothing steps","PCMGSetNumberSmoothUp",1,&m,&flg);CHKERRQ(ierr);
2674b9ad928SBarry Smith     if (flg) {
26897177400SBarry Smith       ierr = PCMGSetNumberSmoothUp(pc,m);CHKERRQ(ierr);
2694b9ad928SBarry Smith     }
2709dcbbd2bSBarry Smith     ierr = PetscOptionsInt("-pc_mg_smoothdown","Number of pre-smoothing steps","PCMGSetNumberSmoothDown",1,&m,&flg);CHKERRQ(ierr);
2714b9ad928SBarry Smith     if (flg) {
27297177400SBarry Smith       ierr = PCMGSetNumberSmoothDown(pc,m);CHKERRQ(ierr);
2734b9ad928SBarry Smith     }
2749dcbbd2bSBarry Smith     ierr = PetscOptionsEnum("-pc_mg_type","Multigrid type","PCMGSetType",PCMGTypes,(PetscEnum)mgtype,(PetscEnum*)&mgtype,&flg);CHKERRQ(ierr);
2759dcbbd2bSBarry Smith     if (flg) {ierr = PCMGSetType(pc,mgtype);CHKERRQ(ierr);}
2764b9ad928SBarry Smith     ierr = PetscOptionsName("-pc_mg_log","Log times for each multigrid level","None",&flg);CHKERRQ(ierr);
2774b9ad928SBarry Smith     if (flg) {
2784f5ab15aSBarry Smith       PetscInt i;
2794b9ad928SBarry Smith       char     eventname[128];
2804b9ad928SBarry Smith       if (!mg) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Must set MG levels before calling");
2814b9ad928SBarry Smith       levels = mg[0]->levels;
2824b9ad928SBarry Smith       for (i=0; i<levels; i++) {
28377431f27SBarry Smith         sprintf(eventname,"MSetup Level %d",(int)i);
2844b9ad928SBarry Smith         ierr = PetscLogEventRegister(&mg[i]->eventsetup,eventname,pc->cookie);CHKERRQ(ierr);
28525a62d46SBarry Smith         sprintf(eventname,"MGSolve Level %d to 0",(int)i);
2864b9ad928SBarry Smith         ierr = PetscLogEventRegister(&mg[i]->eventsolve,eventname,pc->cookie);CHKERRQ(ierr);
2874b9ad928SBarry Smith       }
2884b9ad928SBarry Smith     }
2894b9ad928SBarry Smith   ierr = PetscOptionsTail();CHKERRQ(ierr);
2904b9ad928SBarry Smith   PetscFunctionReturn(0);
2914b9ad928SBarry Smith }
2924b9ad928SBarry Smith 
2939dcbbd2bSBarry Smith const char *PCMGTypes[] = {"MULTIPLICATIVE","ADDITIVE","FULL","KASKADE","PCMGType","PC_MG",0};
2949dcbbd2bSBarry Smith 
2954b9ad928SBarry Smith #undef __FUNCT__
2964b9ad928SBarry Smith #define __FUNCT__ "PCView_MG"
2976849ba73SBarry Smith static PetscErrorCode PCView_MG(PC pc,PetscViewer viewer)
2984b9ad928SBarry Smith {
2999dcbbd2bSBarry Smith   PC_MG          **mg = (PC_MG**)pc->data;
300dfbe8321SBarry Smith   PetscErrorCode ierr;
30179416396SBarry Smith   PetscInt       levels = mg[0]->levels,i;
30232077d6dSBarry Smith   PetscTruth     iascii;
3034b9ad928SBarry Smith 
3044b9ad928SBarry Smith   PetscFunctionBegin;
30532077d6dSBarry Smith   ierr = PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_ASCII,&iascii);CHKERRQ(ierr);
30632077d6dSBarry Smith   if (iascii) {
30777431f27SBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  MG: type is %s, levels=%D cycles=%D, pre-smooths=%D, post-smooths=%D\n",
3089dcbbd2bSBarry Smith                       PCMGTypes[mg[0]->am],levels,mg[0]->cycles,mg[0]->default_smoothd,mg[0]->default_smoothu);CHKERRQ(ierr);
309c2be2410SBarry Smith     if (mg[0]->galerkin) {
310c2be2410SBarry Smith       ierr = PetscViewerASCIIPrintf(viewer,"    Using Galerkin computed coarse grid matrices\n");CHKERRQ(ierr);
311c2be2410SBarry Smith     }
3124b9ad928SBarry Smith     for (i=0; i<levels; i++) {
313b03c7568SBarry Smith       if (!i) {
314b03c7568SBarry Smith         ierr = PetscViewerASCIIPrintf(viewer,"Coarse gride solver -- level %D -------------------------------\n",i);CHKERRQ(ierr);
315b03c7568SBarry Smith       } else {
31677431f27SBarry Smith         ierr = PetscViewerASCIIPrintf(viewer,"Down solver (pre-smoother) on level %D -------------------------------\n",i);CHKERRQ(ierr);
317b03c7568SBarry Smith       }
3184b9ad928SBarry Smith       ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr);
3194b9ad928SBarry Smith       ierr = KSPView(mg[i]->smoothd,viewer);CHKERRQ(ierr);
3204b9ad928SBarry Smith       ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr);
321b03c7568SBarry Smith       if (i && mg[i]->smoothd == mg[i]->smoothu) {
3224b9ad928SBarry Smith         ierr = PetscViewerASCIIPrintf(viewer,"Up solver (post-smoother) same as down solver (pre-smoother)\n");CHKERRQ(ierr);
323b03c7568SBarry Smith       } else if (i){
32477431f27SBarry Smith         ierr = PetscViewerASCIIPrintf(viewer,"Up solver (post-smoother) on level %D -------------------------------\n",i);CHKERRQ(ierr);
3254b9ad928SBarry Smith         ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr);
3264b9ad928SBarry Smith         ierr = KSPView(mg[i]->smoothu,viewer);CHKERRQ(ierr);
3274b9ad928SBarry Smith         ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr);
3284b9ad928SBarry Smith       }
3294b9ad928SBarry Smith     }
3304b9ad928SBarry Smith   } else {
33179a5c55eSBarry Smith     SETERRQ1(PETSC_ERR_SUP,"Viewer type %s not supported for PCMG",((PetscObject)viewer)->type_name);
3324b9ad928SBarry Smith   }
3334b9ad928SBarry Smith   PetscFunctionReturn(0);
3344b9ad928SBarry Smith }
3354b9ad928SBarry Smith 
3364b9ad928SBarry Smith /*
3374b9ad928SBarry Smith     Calls setup for the KSP on each level
3384b9ad928SBarry Smith */
3394b9ad928SBarry Smith #undef __FUNCT__
3404b9ad928SBarry Smith #define __FUNCT__ "PCSetUp_MG"
3416849ba73SBarry Smith static PetscErrorCode PCSetUp_MG(PC pc)
3424b9ad928SBarry Smith {
3439dcbbd2bSBarry Smith   PC_MG          **mg = (PC_MG**)pc->data;
344dfbe8321SBarry Smith   PetscErrorCode ierr;
34579416396SBarry Smith   PetscInt       i,n = mg[0]->levels;
3464b9ad928SBarry Smith   PC             cpc;
34768eff7e6SBarry Smith   PetscTruth     preonly,lu,redundant,cholesky,monitor = PETSC_FALSE,dump;
3484b9ad928SBarry Smith   PetscViewer    ascii;
3494b9ad928SBarry Smith   MPI_Comm       comm;
350c2be2410SBarry Smith   Mat            dA,dB;
351c2be2410SBarry Smith   MatStructure   uflag;
3520a6bb862SBarry Smith   Vec            tvec;
3534b9ad928SBarry Smith 
3544b9ad928SBarry Smith   PetscFunctionBegin;
355958c9bccSBarry Smith   if (!pc->setupcalled) {
3564b9ad928SBarry Smith     ierr = PetscOptionsHasName(0,"-pc_mg_monitor",&monitor);CHKERRQ(ierr);
3574b9ad928SBarry Smith 
358b03c7568SBarry Smith     for (i=0; i<n; i++) {
3594b9ad928SBarry Smith       if (monitor) {
3604b9ad928SBarry Smith         ierr = PetscObjectGetComm((PetscObject)mg[i]->smoothd,&comm);CHKERRQ(ierr);
3614b9ad928SBarry Smith         ierr = PetscViewerASCIIOpen(comm,"stdout",&ascii);CHKERRQ(ierr);
3624b9ad928SBarry Smith         ierr = PetscViewerASCIISetTab(ascii,n-i);CHKERRQ(ierr);
3636849ba73SBarry Smith         ierr = KSPSetMonitor(mg[i]->smoothd,KSPDefaultMonitor,ascii,(PetscErrorCode(*)(void*))PetscViewerDestroy);CHKERRQ(ierr);
3644b9ad928SBarry Smith       }
3654b9ad928SBarry Smith       ierr = KSPSetFromOptions(mg[i]->smoothd);CHKERRQ(ierr);
3664b9ad928SBarry Smith     }
367b03c7568SBarry Smith     for (i=1; i<n; i++) {
3684b9ad928SBarry Smith       if (mg[i]->smoothu && mg[i]->smoothu != mg[i]->smoothd) {
3694b9ad928SBarry Smith         if (monitor) {
3704b9ad928SBarry Smith           ierr = PetscObjectGetComm((PetscObject)mg[i]->smoothu,&comm);CHKERRQ(ierr);
3714b9ad928SBarry Smith           ierr = PetscViewerASCIIOpen(comm,"stdout",&ascii);CHKERRQ(ierr);
3724b9ad928SBarry Smith           ierr = PetscViewerASCIISetTab(ascii,n-i);CHKERRQ(ierr);
3736849ba73SBarry Smith           ierr = KSPSetMonitor(mg[i]->smoothu,KSPDefaultMonitor,ascii,(PetscErrorCode(*)(void*))PetscViewerDestroy);CHKERRQ(ierr);
3744b9ad928SBarry Smith         }
3754b9ad928SBarry Smith         ierr = KSPSetFromOptions(mg[i]->smoothu);CHKERRQ(ierr);
3764b9ad928SBarry Smith       }
3774b9ad928SBarry Smith     }
378fccaa45eSBarry Smith     for (i=1; i<n; i++) {
379fccaa45eSBarry Smith       if (mg[i]->restrct && !mg[i]->interpolate) {
38097177400SBarry Smith         ierr = PCMGSetInterpolate(pc,i,mg[i]->restrct);CHKERRQ(ierr);
381fccaa45eSBarry Smith       }
382fccaa45eSBarry Smith       if (!mg[i]->restrct && mg[i]->interpolate) {
38397177400SBarry Smith         ierr = PCMGSetRestriction(pc,i,mg[i]->interpolate);CHKERRQ(ierr);
384fccaa45eSBarry Smith       }
385fccaa45eSBarry Smith #if defined(PETSC_USE_DEBUG)
386fccaa45eSBarry Smith       if (!mg[i]->restrct || !mg[i]->interpolate) {
387fccaa45eSBarry Smith         SETERRQ1(PETSC_ERR_ARG_WRONGSTATE,"Need to set restriction or interpolation on level %d",(int)i);
388fccaa45eSBarry Smith       }
389fccaa45eSBarry Smith #endif
390fccaa45eSBarry Smith     }
3910a6bb862SBarry Smith     for (i=0; i<n-1; i++) {
3926ca4d86aSHong Zhang       if (!mg[i]->r && i) {
3930a6bb862SBarry Smith         ierr = VecDuplicate(mg[i]->b,&tvec);CHKERRQ(ierr);
39497177400SBarry Smith         ierr = PCMGSetR(pc,i,tvec);CHKERRQ(ierr);
3950a6bb862SBarry Smith         ierr = VecDestroy(tvec);CHKERRQ(ierr);
3960a6bb862SBarry Smith       }
3970a6bb862SBarry Smith       if (!mg[i]->x) {
3980a6bb862SBarry Smith         ierr = VecDuplicate(mg[i]->b,&tvec);CHKERRQ(ierr);
39997177400SBarry Smith         ierr = PCMGSetX(pc,i,tvec);CHKERRQ(ierr);
4000a6bb862SBarry Smith         ierr = VecDestroy(tvec);CHKERRQ(ierr);
4010a6bb862SBarry Smith       }
4020a6bb862SBarry Smith     }
4034b9ad928SBarry Smith   }
4044b9ad928SBarry Smith 
405c2be2410SBarry Smith   /* If user did not provide fine grid operators, use those from PC */
406c2be2410SBarry Smith   /* BUG BUG BUG This will work ONLY the first time called: hence if the user changes
407c2be2410SBarry Smith      the PC matrices between solves PCMG will continue to use first set provided */
408c2be2410SBarry Smith   ierr = KSPGetOperators(mg[n-1]->smoothd,&dA,&dB,&uflag);CHKERRQ(ierr);
409c2be2410SBarry Smith   if (!dA  && !dB) {
41097177400SBarry Smith     ierr = PetscLogInfo((pc,"PCSetUp_MG: Using outer operators to define finest grid operator \n  because PCMGGetSmoother(pc,nlevels-1,&ksp);KSPSetOperators(ksp,...); was not called.\n"));
411c2be2410SBarry Smith     ierr = KSPSetOperators(mg[n-1]->smoothd,pc->mat,pc->pmat,uflag);CHKERRQ(ierr);
412c2be2410SBarry Smith   }
413c2be2410SBarry Smith 
414c2be2410SBarry Smith   if (mg[0]->galerkin) {
4155e8befabSKris Buschelman     Mat B;
416c2be2410SBarry Smith     mg[0]->galerkinused = PETSC_TRUE;
417c2be2410SBarry Smith     /* currently only handle case where mat and pmat are the same on coarser levels */
418c2be2410SBarry Smith     ierr = KSPGetOperators(mg[n-1]->smoothd,&dA,&dB,&uflag);CHKERRQ(ierr);
419c2be2410SBarry Smith     if (!pc->setupcalled) {
420c2be2410SBarry Smith       for (i=n-2; i>-1; i--) {
421c2be2410SBarry Smith         ierr = MatPtAP(dB,mg[i+1]->interpolate,MAT_INITIAL_MATRIX,1.0,&B);CHKERRQ(ierr);
422c2be2410SBarry Smith         ierr = KSPSetOperators(mg[i]->smoothd,B,B,uflag);CHKERRQ(ierr);
423c2be2410SBarry Smith         dB   = B;
424c2be2410SBarry Smith       }
425c2be2410SBarry Smith     } else {
426c2be2410SBarry Smith       for (i=n-2; i>-1; i--) {
427c2be2410SBarry Smith         ierr = KSPGetOperators(mg[i]->smoothd,0,&B,0);CHKERRQ(ierr);
428c2be2410SBarry Smith         ierr = MatPtAP(dB,mg[i]->interpolate,MAT_REUSE_MATRIX,1.0,&B);CHKERRQ(ierr);
429c2be2410SBarry Smith         ierr = KSPSetOperators(mg[i]->smoothd,B,B,uflag);CHKERRQ(ierr);
430c2be2410SBarry Smith         dB   = B;
431c2be2410SBarry Smith       }
432c2be2410SBarry Smith     }
433c2be2410SBarry Smith   }
434c2be2410SBarry Smith 
4354b9ad928SBarry Smith   for (i=1; i<n; i++) {
436b03c7568SBarry Smith     if (mg[i]->smoothu == mg[i]->smoothd) {
437b03c7568SBarry Smith       /* if doing only down then initial guess is zero */
4384b9ad928SBarry Smith       ierr = KSPSetInitialGuessNonzero(mg[i]->smoothd,PETSC_TRUE);CHKERRQ(ierr);
439b03c7568SBarry Smith     }
4404b9ad928SBarry Smith     if (mg[i]->eventsetup) {ierr = PetscLogEventBegin(mg[i]->eventsetup,0,0,0,0);CHKERRQ(ierr);}
4414b9ad928SBarry Smith     ierr = KSPSetUp(mg[i]->smoothd);CHKERRQ(ierr);
4424b9ad928SBarry Smith     if (mg[i]->eventsetup) {ierr = PetscLogEventEnd(mg[i]->eventsetup,0,0,0,0);CHKERRQ(ierr);}
4434b9ad928SBarry Smith   }
444b03c7568SBarry Smith   for (i=1; i<n; i++) {
4454b9ad928SBarry Smith     if (mg[i]->smoothu && mg[i]->smoothu != mg[i]->smoothd) {
446c2be2410SBarry Smith       PC           uppc,downpc;
44797f1f81fSBarry Smith       Mat          downmat,downpmat,upmat,uppmat;
44897f1f81fSBarry Smith       MatStructure matflag;
44997f1f81fSBarry Smith 
45097f1f81fSBarry Smith       /* check if operators have been set for up, if not use down operators to set them */
45197f1f81fSBarry Smith       ierr = KSPGetPC(mg[i]->smoothu,&uppc);CHKERRQ(ierr);
45297f1f81fSBarry Smith       ierr = PCGetOperators(uppc,&upmat,&uppmat,PETSC_NULL);CHKERRQ(ierr);
45397f1f81fSBarry Smith       if (!upmat) {
45497f1f81fSBarry Smith         ierr = KSPGetPC(mg[i]->smoothd,&downpc);CHKERRQ(ierr);
45597f1f81fSBarry Smith         ierr = PCGetOperators(downpc,&downmat,&downpmat,&matflag);CHKERRQ(ierr);
45697f1f81fSBarry Smith         ierr = KSPSetOperators(mg[i]->smoothu,downmat,downpmat,matflag);CHKERRQ(ierr);
45797f1f81fSBarry Smith       }
45897f1f81fSBarry Smith 
4594b9ad928SBarry Smith       ierr = KSPSetInitialGuessNonzero(mg[i]->smoothu,PETSC_TRUE);CHKERRQ(ierr);
4604b9ad928SBarry Smith       if (mg[i]->eventsetup) {ierr = PetscLogEventBegin(mg[i]->eventsetup,0,0,0,0);CHKERRQ(ierr);}
4614b9ad928SBarry Smith       ierr = KSPSetUp(mg[i]->smoothu);CHKERRQ(ierr);
4624b9ad928SBarry Smith       if (mg[i]->eventsetup) {ierr = PetscLogEventEnd(mg[i]->eventsetup,0,0,0,0);CHKERRQ(ierr);}
4634b9ad928SBarry Smith     }
4644b9ad928SBarry Smith   }
4654b9ad928SBarry Smith 
4664b9ad928SBarry Smith   /*
4674b9ad928SBarry Smith       If coarse solver is not direct method then DO NOT USE preonly
4684b9ad928SBarry Smith   */
4694b9ad928SBarry Smith   ierr = PetscTypeCompare((PetscObject)mg[0]->smoothd,KSPPREONLY,&preonly);CHKERRQ(ierr);
4704b9ad928SBarry Smith   if (preonly) {
4714b9ad928SBarry Smith     ierr = KSPGetPC(mg[0]->smoothd,&cpc);CHKERRQ(ierr);
4724b9ad928SBarry Smith     ierr = PetscTypeCompare((PetscObject)cpc,PCLU,&lu);CHKERRQ(ierr);
4734b9ad928SBarry Smith     ierr = PetscTypeCompare((PetscObject)cpc,PCREDUNDANT,&redundant);CHKERRQ(ierr);
47468eff7e6SBarry Smith     ierr = PetscTypeCompare((PetscObject)cpc,PCCHOLESKY,&cholesky);CHKERRQ(ierr);
47568eff7e6SBarry Smith     if (!lu && !redundant && !cholesky) {
4764b9ad928SBarry Smith       ierr = KSPSetType(mg[0]->smoothd,KSPGMRES);CHKERRQ(ierr);
4774b9ad928SBarry Smith     }
4784b9ad928SBarry Smith   }
4794b9ad928SBarry Smith 
480958c9bccSBarry Smith   if (!pc->setupcalled) {
4814b9ad928SBarry Smith     if (monitor) {
4824b9ad928SBarry Smith       ierr = PetscObjectGetComm((PetscObject)mg[0]->smoothd,&comm);CHKERRQ(ierr);
4834b9ad928SBarry Smith       ierr = PetscViewerASCIIOpen(comm,"stdout",&ascii);CHKERRQ(ierr);
4844b9ad928SBarry Smith       ierr = PetscViewerASCIISetTab(ascii,n);CHKERRQ(ierr);
4856849ba73SBarry Smith       ierr = KSPSetMonitor(mg[0]->smoothd,KSPDefaultMonitor,ascii,(PetscErrorCode(*)(void*))PetscViewerDestroy);CHKERRQ(ierr);
4864b9ad928SBarry Smith     }
4874b9ad928SBarry Smith     ierr = KSPSetFromOptions(mg[0]->smoothd);CHKERRQ(ierr);
4884b9ad928SBarry Smith   }
4894b9ad928SBarry Smith 
4904b9ad928SBarry Smith   if (mg[0]->eventsetup) {ierr = PetscLogEventBegin(mg[0]->eventsetup,0,0,0,0);CHKERRQ(ierr);}
4914b9ad928SBarry Smith   ierr = KSPSetUp(mg[0]->smoothd);CHKERRQ(ierr);
4924b9ad928SBarry Smith   if (mg[0]->eventsetup) {ierr = PetscLogEventEnd(mg[0]->eventsetup,0,0,0,0);CHKERRQ(ierr);}
4934b9ad928SBarry Smith 
4944cf18111SSatish Balay #if defined(PETSC_USE_SOCKET_VIEWER)
4954b9ad928SBarry Smith   /*
4964b9ad928SBarry Smith      Dump the interpolation/restriction matrices to matlab plus the
4974b9ad928SBarry Smith    Jacobian/stiffness on each level. This allows Matlab users to
4984b9ad928SBarry Smith    easily check if the Galerkin condition A_c = R A_f R^T is satisfied */
4994b9ad928SBarry Smith   ierr = PetscOptionsHasName(pc->prefix,"-pc_mg_dump_matlab",&dump);CHKERRQ(ierr);
5004b9ad928SBarry Smith   if (dump) {
5014b9ad928SBarry Smith     for (i=1; i<n; i++) {
5024b9ad928SBarry Smith       ierr = MatView(mg[i]->restrct,PETSC_VIEWER_SOCKET_(pc->comm));CHKERRQ(ierr);
5034b9ad928SBarry Smith     }
5044b9ad928SBarry Smith     for (i=0; i<n; i++) {
5054b9ad928SBarry Smith       ierr = KSPGetPC(mg[i]->smoothd,&pc);CHKERRQ(ierr);
5064b9ad928SBarry Smith       ierr = MatView(pc->mat,PETSC_VIEWER_SOCKET_(pc->comm));CHKERRQ(ierr);
5074b9ad928SBarry Smith     }
5084b9ad928SBarry Smith   }
509c45a1595SBarry Smith #endif
510c45a1595SBarry Smith 
511c2be2410SBarry Smith   ierr = PetscOptionsHasName(pc->prefix,"-pc_mg_dump_binary",&dump);CHKERRQ(ierr);
512c2be2410SBarry Smith   if (dump) {
513c2be2410SBarry Smith     for (i=1; i<n; i++) {
514c2be2410SBarry Smith       ierr = MatView(mg[i]->restrct,PETSC_VIEWER_BINARY_(pc->comm));CHKERRQ(ierr);
515c2be2410SBarry Smith     }
516c2be2410SBarry Smith     for (i=0; i<n; i++) {
517c2be2410SBarry Smith       ierr = KSPGetPC(mg[i]->smoothd,&pc);CHKERRQ(ierr);
518c2be2410SBarry Smith       ierr = MatView(pc->mat,PETSC_VIEWER_BINARY_(pc->comm));CHKERRQ(ierr);
519c2be2410SBarry Smith     }
520c2be2410SBarry Smith   }
5214b9ad928SBarry Smith   PetscFunctionReturn(0);
5224b9ad928SBarry Smith }
5234b9ad928SBarry Smith 
5244b9ad928SBarry Smith /* -------------------------------------------------------------------------------------*/
5254b9ad928SBarry Smith 
5264b9ad928SBarry Smith #undef __FUNCT__
5279dcbbd2bSBarry Smith #define __FUNCT__ "PCMGSetLevels"
5284b9ad928SBarry Smith /*@C
52997177400SBarry Smith    PCMGSetLevels - Sets the number of levels to use with MG.
5304b9ad928SBarry Smith    Must be called before any other MG routine.
5314b9ad928SBarry Smith 
5324b9ad928SBarry Smith    Collective on PC
5334b9ad928SBarry Smith 
5344b9ad928SBarry Smith    Input Parameters:
5354b9ad928SBarry Smith +  pc - the preconditioner context
5364b9ad928SBarry Smith .  levels - the number of levels
5374b9ad928SBarry Smith -  comms - optional communicators for each level; this is to allow solving the coarser problems
5384b9ad928SBarry Smith            on smaller sets of processors. Use PETSC_NULL_OBJECT for default in Fortran
5394b9ad928SBarry Smith 
5404b9ad928SBarry Smith    Level: intermediate
5414b9ad928SBarry Smith 
5424b9ad928SBarry Smith    Notes:
5434b9ad928SBarry Smith      If the number of levels is one then the multigrid uses the -mg_levels prefix
5444b9ad928SBarry Smith   for setting the level options rather than the -mg_coarse prefix.
5454b9ad928SBarry Smith 
5464b9ad928SBarry Smith .keywords: MG, set, levels, multigrid
5474b9ad928SBarry Smith 
54897177400SBarry Smith .seealso: PCMGSetType(), PCMGGetLevels()
5494b9ad928SBarry Smith @*/
55097177400SBarry Smith PetscErrorCode PETSCKSP_DLLEXPORT PCMGSetLevels(PC pc,PetscInt levels,MPI_Comm *comms)
5514b9ad928SBarry Smith {
552dfbe8321SBarry Smith   PetscErrorCode ierr;
5539dcbbd2bSBarry Smith   PC_MG          **mg;
5544b9ad928SBarry Smith 
5554b9ad928SBarry Smith   PetscFunctionBegin;
5564482741eSBarry Smith   PetscValidHeaderSpecific(pc,PC_COOKIE,1);
5574b9ad928SBarry Smith 
5584b9ad928SBarry Smith   if (pc->data) {
5591302d50aSBarry Smith     SETERRQ(PETSC_ERR_ORDER,"Number levels already set for MG\n\
56097177400SBarry Smith     make sure that you call PCMGSetLevels() before KSPSetFromOptions()");
5614b9ad928SBarry Smith   }
5629dcbbd2bSBarry Smith   ierr                     = PCMGCreate_Private(pc->comm,levels,pc,comms,&mg);CHKERRQ(ierr);
5639dcbbd2bSBarry Smith   mg[0]->am                = PC_MG_MULTIPLICATIVE;
5644b9ad928SBarry Smith   pc->data                 = (void*)mg;
5654b9ad928SBarry Smith   pc->ops->applyrichardson = PCApplyRichardson_MG;
5664b9ad928SBarry Smith   PetscFunctionReturn(0);
5674b9ad928SBarry Smith }
5684b9ad928SBarry Smith 
5694b9ad928SBarry Smith #undef __FUNCT__
5709dcbbd2bSBarry Smith #define __FUNCT__ "PCMGGetLevels"
5714b9ad928SBarry Smith /*@
57297177400SBarry Smith    PCMGGetLevels - Gets the number of levels to use with MG.
5734b9ad928SBarry Smith 
5744b9ad928SBarry Smith    Not Collective
5754b9ad928SBarry Smith 
5764b9ad928SBarry Smith    Input Parameter:
5774b9ad928SBarry Smith .  pc - the preconditioner context
5784b9ad928SBarry Smith 
5794b9ad928SBarry Smith    Output parameter:
5804b9ad928SBarry Smith .  levels - the number of levels
5814b9ad928SBarry Smith 
5824b9ad928SBarry Smith    Level: advanced
5834b9ad928SBarry Smith 
5844b9ad928SBarry Smith .keywords: MG, get, levels, multigrid
5854b9ad928SBarry Smith 
58697177400SBarry Smith .seealso: PCMGSetLevels()
5874b9ad928SBarry Smith @*/
58897177400SBarry Smith PetscErrorCode PETSCKSP_DLLEXPORT PCMGGetLevels(PC pc,PetscInt *levels)
5894b9ad928SBarry Smith {
5909dcbbd2bSBarry Smith   PC_MG  **mg;
5914b9ad928SBarry Smith 
5924b9ad928SBarry Smith   PetscFunctionBegin;
5934482741eSBarry Smith   PetscValidHeaderSpecific(pc,PC_COOKIE,1);
5944482741eSBarry Smith   PetscValidIntPointer(levels,2);
5954b9ad928SBarry Smith 
5969dcbbd2bSBarry Smith   mg      = (PC_MG**)pc->data;
5974b9ad928SBarry Smith   *levels = mg[0]->levels;
5984b9ad928SBarry Smith   PetscFunctionReturn(0);
5994b9ad928SBarry Smith }
6004b9ad928SBarry Smith 
6014b9ad928SBarry Smith #undef __FUNCT__
6029dcbbd2bSBarry Smith #define __FUNCT__ "PCMGSetType"
6034b9ad928SBarry Smith /*@
60497177400SBarry Smith    PCMGSetType - Determines the form of multigrid to use:
6054b9ad928SBarry Smith    multiplicative, additive, full, or the Kaskade algorithm.
6064b9ad928SBarry Smith 
6074b9ad928SBarry Smith    Collective on PC
6084b9ad928SBarry Smith 
6094b9ad928SBarry Smith    Input Parameters:
6104b9ad928SBarry Smith +  pc - the preconditioner context
6119dcbbd2bSBarry Smith -  form - multigrid form, one of PC_MG_MULTIPLICATIVE, PC_MG_ADDITIVE,
6129dcbbd2bSBarry Smith    PC_MG_FULL, PC_MG_KASKADE
6134b9ad928SBarry Smith 
6144b9ad928SBarry Smith    Options Database Key:
6154b9ad928SBarry Smith .  -pc_mg_type <form> - Sets <form>, one of multiplicative,
6164b9ad928SBarry Smith    additive, full, kaskade
6174b9ad928SBarry Smith 
6184b9ad928SBarry Smith    Level: advanced
6194b9ad928SBarry Smith 
6204b9ad928SBarry Smith .keywords: MG, set, method, multiplicative, additive, full, Kaskade, multigrid
6214b9ad928SBarry Smith 
62297177400SBarry Smith .seealso: PCMGSetLevels()
6234b9ad928SBarry Smith @*/
6249dcbbd2bSBarry Smith PetscErrorCode PETSCKSP_DLLEXPORT PCMGSetType(PC pc,PCMGType form)
6254b9ad928SBarry Smith {
6269dcbbd2bSBarry Smith   PC_MG **mg;
6274b9ad928SBarry Smith 
6284b9ad928SBarry Smith   PetscFunctionBegin;
6294482741eSBarry Smith   PetscValidHeaderSpecific(pc,PC_COOKIE,1);
6309dcbbd2bSBarry Smith   mg = (PC_MG**)pc->data;
6314b9ad928SBarry Smith 
6324b9ad928SBarry Smith   if (!mg) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Must set MG levels before calling");
6334b9ad928SBarry Smith   mg[0]->am = form;
6349dcbbd2bSBarry Smith   if (form == PC_MG_MULTIPLICATIVE) pc->ops->applyrichardson = PCApplyRichardson_MG;
6354b9ad928SBarry Smith   else pc->ops->applyrichardson = 0;
6364b9ad928SBarry Smith   PetscFunctionReturn(0);
6374b9ad928SBarry Smith }
6384b9ad928SBarry Smith 
6394b9ad928SBarry Smith #undef __FUNCT__
6409dcbbd2bSBarry Smith #define __FUNCT__ "PCMGSetCycles"
6414b9ad928SBarry Smith /*@
64297177400SBarry Smith    PCMGSetCycles - Sets the type cycles to use.  Use PCMGSetCyclesOnLevel() for more
6434b9ad928SBarry Smith    complicated cycling.
6444b9ad928SBarry Smith 
6454b9ad928SBarry Smith    Collective on PC
6464b9ad928SBarry Smith 
6474b9ad928SBarry Smith    Input Parameters:
648c2be2410SBarry Smith +  pc - the multigrid context
6494b9ad928SBarry Smith -  n - the number of cycles
6504b9ad928SBarry Smith 
6514b9ad928SBarry Smith    Options Database Key:
6524b9ad928SBarry Smith $  -pc_mg_cycles n - 1 denotes a V-cycle; 2 denotes a W-cycle.
6534b9ad928SBarry Smith 
6544b9ad928SBarry Smith    Level: advanced
6554b9ad928SBarry Smith 
6564b9ad928SBarry Smith .keywords: MG, set, cycles, V-cycle, W-cycle, multigrid
6574b9ad928SBarry Smith 
65897177400SBarry Smith .seealso: PCMGSetCyclesOnLevel()
6594b9ad928SBarry Smith @*/
66097177400SBarry Smith PetscErrorCode PETSCKSP_DLLEXPORT PCMGSetCycles(PC pc,PetscInt n)
6614b9ad928SBarry Smith {
6629dcbbd2bSBarry Smith   PC_MG    **mg;
66379416396SBarry Smith   PetscInt i,levels;
6644b9ad928SBarry Smith 
6654b9ad928SBarry Smith   PetscFunctionBegin;
6664482741eSBarry Smith   PetscValidHeaderSpecific(pc,PC_COOKIE,1);
6679dcbbd2bSBarry Smith   mg     = (PC_MG**)pc->data;
6684b9ad928SBarry Smith   if (!mg) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Must set MG levels before calling");
6694b9ad928SBarry Smith   levels = mg[0]->levels;
6704b9ad928SBarry Smith 
6714b9ad928SBarry Smith   for (i=0; i<levels; i++) {
6724b9ad928SBarry Smith     mg[i]->cycles  = n;
6734b9ad928SBarry Smith   }
6744b9ad928SBarry Smith   PetscFunctionReturn(0);
6754b9ad928SBarry Smith }
6764b9ad928SBarry Smith 
6774b9ad928SBarry Smith #undef __FUNCT__
6789dcbbd2bSBarry Smith #define __FUNCT__ "PCMGSetGalerkin"
679c2be2410SBarry Smith /*@
68097177400SBarry Smith    PCMGSetGalerkin - Causes the coarser grid matrices to be computed from the
681c2be2410SBarry Smith       finest grid via the Galerkin process: A_i-1 = r_i * A_i * r_i^t
682c2be2410SBarry Smith 
683c2be2410SBarry Smith    Collective on PC
684c2be2410SBarry Smith 
685c2be2410SBarry Smith    Input Parameters:
686c2be2410SBarry Smith +  pc - the multigrid context
687c2be2410SBarry Smith -  n - the number of cycles
688c2be2410SBarry Smith 
689c2be2410SBarry Smith    Options Database Key:
690c2be2410SBarry Smith $  -pc_mg_galerkin
691c2be2410SBarry Smith 
692c2be2410SBarry Smith    Level: intermediate
693c2be2410SBarry Smith 
694c2be2410SBarry Smith .keywords: MG, set, Galerkin
695c2be2410SBarry Smith 
696c2be2410SBarry Smith @*/
69797177400SBarry Smith PetscErrorCode PETSCKSP_DLLEXPORT PCMGSetGalerkin(PC pc)
698c2be2410SBarry Smith {
6999dcbbd2bSBarry Smith   PC_MG    **mg;
700c2be2410SBarry Smith   PetscInt i,levels;
701c2be2410SBarry Smith 
702c2be2410SBarry Smith   PetscFunctionBegin;
703c2be2410SBarry Smith   PetscValidHeaderSpecific(pc,PC_COOKIE,1);
7049dcbbd2bSBarry Smith   mg     = (PC_MG**)pc->data;
705c2be2410SBarry Smith   if (!mg) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Must set MG levels before calling");
706c2be2410SBarry Smith   levels = mg[0]->levels;
707c2be2410SBarry Smith 
708c2be2410SBarry Smith   for (i=0; i<levels; i++) {
709c2be2410SBarry Smith     mg[i]->galerkin = PETSC_TRUE;
710c2be2410SBarry Smith   }
711c2be2410SBarry Smith   PetscFunctionReturn(0);
712c2be2410SBarry Smith }
713c2be2410SBarry Smith 
714c2be2410SBarry Smith #undef __FUNCT__
7159dcbbd2bSBarry Smith #define __FUNCT__ "PCMGSetNumberSmoothDown"
7164b9ad928SBarry Smith /*@
71797177400SBarry Smith    PCMGSetNumberSmoothDown - Sets the number of pre-smoothing steps to
71897177400SBarry Smith    use on all levels. Use PCMGGetSmootherDown() to set different
7194b9ad928SBarry Smith    pre-smoothing steps on different levels.
7204b9ad928SBarry Smith 
7214b9ad928SBarry Smith    Collective on PC
7224b9ad928SBarry Smith 
7234b9ad928SBarry Smith    Input Parameters:
7244b9ad928SBarry Smith +  mg - the multigrid context
7254b9ad928SBarry Smith -  n - the number of smoothing steps
7264b9ad928SBarry Smith 
7274b9ad928SBarry Smith    Options Database Key:
7284b9ad928SBarry Smith .  -pc_mg_smoothdown <n> - Sets number of pre-smoothing steps
7294b9ad928SBarry Smith 
7304b9ad928SBarry Smith    Level: advanced
7314b9ad928SBarry Smith 
7324b9ad928SBarry Smith .keywords: MG, smooth, down, pre-smoothing, steps, multigrid
7334b9ad928SBarry Smith 
73497177400SBarry Smith .seealso: PCMGSetNumberSmoothUp()
7354b9ad928SBarry Smith @*/
73697177400SBarry Smith PetscErrorCode PETSCKSP_DLLEXPORT PCMGSetNumberSmoothDown(PC pc,PetscInt n)
7374b9ad928SBarry Smith {
7389dcbbd2bSBarry Smith   PC_MG          **mg;
7396849ba73SBarry Smith   PetscErrorCode ierr;
74079416396SBarry Smith   PetscInt       i,levels;
7414b9ad928SBarry Smith 
7424b9ad928SBarry Smith   PetscFunctionBegin;
7434482741eSBarry Smith   PetscValidHeaderSpecific(pc,PC_COOKIE,1);
7449dcbbd2bSBarry Smith   mg     = (PC_MG**)pc->data;
7454b9ad928SBarry Smith   if (!mg) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Must set MG levels before calling");
7464b9ad928SBarry Smith   levels = mg[0]->levels;
7474b9ad928SBarry Smith 
7484b9ad928SBarry Smith   for (i=0; i<levels; i++) {
7494b9ad928SBarry Smith     /* make sure smoother up and down are different */
75097177400SBarry Smith     ierr = PCMGGetSmootherUp(pc,i,PETSC_NULL);CHKERRQ(ierr);
7514b9ad928SBarry Smith     ierr = KSPSetTolerances(mg[i]->smoothd,PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT,n);CHKERRQ(ierr);
7524b9ad928SBarry Smith     mg[i]->default_smoothd = n;
7534b9ad928SBarry Smith   }
7544b9ad928SBarry Smith   PetscFunctionReturn(0);
7554b9ad928SBarry Smith }
7564b9ad928SBarry Smith 
7574b9ad928SBarry Smith #undef __FUNCT__
7589dcbbd2bSBarry Smith #define __FUNCT__ "PCMGSetNumberSmoothUp"
7594b9ad928SBarry Smith /*@
76097177400SBarry Smith    PCMGSetNumberSmoothUp - Sets the number of post-smoothing steps to use
76197177400SBarry Smith    on all levels. Use PCMGGetSmootherUp() to set different numbers of
7624b9ad928SBarry Smith    post-smoothing steps on different levels.
7634b9ad928SBarry Smith 
7644b9ad928SBarry Smith    Collective on PC
7654b9ad928SBarry Smith 
7664b9ad928SBarry Smith    Input Parameters:
7674b9ad928SBarry Smith +  mg - the multigrid context
7684b9ad928SBarry Smith -  n - the number of smoothing steps
7694b9ad928SBarry Smith 
7704b9ad928SBarry Smith    Options Database Key:
7714b9ad928SBarry Smith .  -pc_mg_smoothup <n> - Sets number of post-smoothing steps
7724b9ad928SBarry Smith 
7734b9ad928SBarry Smith    Level: advanced
7744b9ad928SBarry Smith 
7754b9ad928SBarry Smith    Note: this does not set a value on the coarsest grid, since we assume that
776b03c7568SBarry Smith     there is no seperate smooth up on the coarsest grid.
7774b9ad928SBarry Smith 
7784b9ad928SBarry Smith .keywords: MG, smooth, up, post-smoothing, steps, multigrid
7794b9ad928SBarry Smith 
78097177400SBarry Smith .seealso: PCMGSetNumberSmoothDown()
7814b9ad928SBarry Smith @*/
78297177400SBarry Smith PetscErrorCode PETSCKSP_DLLEXPORT PCMGSetNumberSmoothUp(PC pc,PetscInt n)
7834b9ad928SBarry Smith {
7849dcbbd2bSBarry Smith   PC_MG          **mg;
7856849ba73SBarry Smith   PetscErrorCode ierr;
78679416396SBarry Smith   PetscInt       i,levels;
7874b9ad928SBarry Smith 
7884b9ad928SBarry Smith   PetscFunctionBegin;
7894482741eSBarry Smith   PetscValidHeaderSpecific(pc,PC_COOKIE,1);
7909dcbbd2bSBarry Smith   mg     = (PC_MG**)pc->data;
7914b9ad928SBarry Smith   if (!mg) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Must set MG levels before calling");
7924b9ad928SBarry Smith   levels = mg[0]->levels;
7934b9ad928SBarry Smith 
7944b9ad928SBarry Smith   for (i=1; i<levels; i++) {
7954b9ad928SBarry Smith     /* make sure smoother up and down are different */
79697177400SBarry Smith     ierr = PCMGGetSmootherUp(pc,i,PETSC_NULL);CHKERRQ(ierr);
7974b9ad928SBarry Smith     ierr = KSPSetTolerances(mg[i]->smoothu,PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT,n);CHKERRQ(ierr);
7984b9ad928SBarry Smith     mg[i]->default_smoothu = n;
7994b9ad928SBarry Smith   }
8004b9ad928SBarry Smith   PetscFunctionReturn(0);
8014b9ad928SBarry Smith }
8024b9ad928SBarry Smith 
8034b9ad928SBarry Smith /* ----------------------------------------------------------------------------------------*/
8044b9ad928SBarry Smith 
8053b09bd56SBarry Smith /*MC
8063b09bd56SBarry Smith    PCMG - Use geometric multigrid preconditioning. This preconditioner requires you provide additional
8073b09bd56SBarry Smith     information about the coarser grid matrices and restriction/interpolation operators.
8083b09bd56SBarry Smith 
8093b09bd56SBarry Smith    Options Database Keys:
8103b09bd56SBarry Smith +  -pc_mg_levels <nlevels> - number of levels including finest
8113b09bd56SBarry Smith .  -pc_mg_cycles 1 or 2 - for V or W-cycle
81279416396SBarry Smith .  -pc_mg_smoothup <n> - number of smoothing steps after interpolation
8133b09bd56SBarry Smith .  -pc_mg_smoothdown <n> - number of smoothing steps before applying restriction operator
8143b09bd56SBarry Smith .  -pc_mg_type <additive,multiplicative,full,cascade> - multiplicative is the default
8153b09bd56SBarry Smith .  -pc_mg_log - log information about time spent on each level of the solver
8163b09bd56SBarry Smith .  -pc_mg_monitor - print information on the multigrid convergence
81768eff7e6SBarry Smith .  -pc_mg_galerkin - use Galerkin process to compute coarser operators
8183b09bd56SBarry Smith -  -pc_mg_dump_matlab - dumps the matrices for each level and the restriction/interpolation matrices
8193b09bd56SBarry Smith                         to the Socket viewer for reading from Matlab.
8203b09bd56SBarry Smith 
8213b09bd56SBarry Smith    Notes:
8223b09bd56SBarry Smith 
8233b09bd56SBarry Smith    Level: intermediate
8243b09bd56SBarry Smith 
8253b09bd56SBarry Smith    Concepts: multigrid
8263b09bd56SBarry Smith 
8273b09bd56SBarry Smith .seealso:  PCCreate(), PCSetType(), PCType (for list of available types), PC, PCMGType,
8289dcbbd2bSBarry Smith            PCMGSetLevels(), PCMGGetLevels(), PCMGSetType(), PCMGSetCycles(), PCMGSetNumberSmoothDown(),
82997177400SBarry Smith            PCMGSetNumberSmoothUp(), PCMGGetCoarseSolve(), PCMGSetResidual(), PCMGSetInterpolation(),
83097177400SBarry Smith            PCMGSetRestriction(), PCMGGetSmoother(), PCMGGetSmootherUp(), PCMGGetSmootherDown(),
83197177400SBarry Smith            PCMGSetCyclesOnLevel(), PCMGSetRhs(), PCMGSetX(), PCMGSetR()
8323b09bd56SBarry Smith M*/
8333b09bd56SBarry Smith 
8344b9ad928SBarry Smith EXTERN_C_BEGIN
8354b9ad928SBarry Smith #undef __FUNCT__
8364b9ad928SBarry Smith #define __FUNCT__ "PCCreate_MG"
837dba47a55SKris Buschelman PetscErrorCode PETSCKSP_DLLEXPORT PCCreate_MG(PC pc)
8384b9ad928SBarry Smith {
8394b9ad928SBarry Smith   PetscFunctionBegin;
8404b9ad928SBarry Smith   pc->ops->apply          = PCApply_MG;
8414b9ad928SBarry Smith   pc->ops->setup          = PCSetUp_MG;
8424b9ad928SBarry Smith   pc->ops->destroy        = PCDestroy_MG;
8434b9ad928SBarry Smith   pc->ops->setfromoptions = PCSetFromOptions_MG;
8444b9ad928SBarry Smith   pc->ops->view           = PCView_MG;
8454b9ad928SBarry Smith 
8464b9ad928SBarry Smith   pc->data                = (void*)0;
8474b9ad928SBarry Smith   PetscFunctionReturn(0);
8484b9ad928SBarry Smith }
8494b9ad928SBarry Smith EXTERN_C_END
850