xref: /petsc/src/ksp/pc/impls/gamg/gamg.c (revision 5b89ad90565591c81ad34c125ce486a2658e4093)
1*5b89ad90SMark F. Adams /*
2*5b89ad90SMark F. Adams  GAMG geometric-algebric multiogrid PC - Mark Adams 2011
3*5b89ad90SMark F. Adams  */
4*5b89ad90SMark F. Adams #include <private/pcimpl.h>   /*I "petscpc.h" I*/
5*5b89ad90SMark F. Adams #include <../src/ksp/pc/impls/mg/mgimpl.h>                    /*I "petscpcmg.h" I*/
6*5b89ad90SMark F. Adams #include <../src/mat/impls/aij/seq/aij.h>
7*5b89ad90SMark F. Adams #include <../src/mat/impls/aij/mpi/mpiaij.h>
8*5b89ad90SMark F. Adams 
9*5b89ad90SMark F. Adams /* Private context for the GAMG preconditioner */
10*5b89ad90SMark F. Adams typedef struct gamg_TAG {
11*5b89ad90SMark F. Adams gamg_TAG() : m_dim(0), m_Nlevels(-1), m_data(0)
12*5b89ad90SMark F. Adams     {}
13*5b89ad90SMark F. Adams   PetscInt       m_dim;
14*5b89ad90SMark F. Adams   PetscInt       m_Nlevels;
15*5b89ad90SMark F. Adams   PetscInt       m_data_sz;
16*5b89ad90SMark F. Adams   PetscReal     *m_data; /* blocked vector of vertex data on fine grid (coordinates) */
17*5b89ad90SMark F. Adams } PC_GAMG;
18*5b89ad90SMark F. Adams 
19*5b89ad90SMark F. Adams /* -----------------------------------------------------------------------------*/
20*5b89ad90SMark F. Adams #undef __FUNCT__
21*5b89ad90SMark F. Adams #define __FUNCT__ "PCReset_GAMG"
22*5b89ad90SMark F. Adams PetscErrorCode PCReset_GAMG(PC pc)
23*5b89ad90SMark F. Adams {
24*5b89ad90SMark F. Adams   PetscErrorCode  ierr;
25*5b89ad90SMark F. Adams   PC_MG           *mg = (PC_MG*)pc->data;
26*5b89ad90SMark F. Adams   PC_GAMG         *pc_gamg = (PC_GAMG*)mg->innerctx;
27*5b89ad90SMark F. Adams 
28*5b89ad90SMark F. Adams   PetscFunctionBegin;
29*5b89ad90SMark F. Adams   if (pc_gamg->m_data) {
30*5b89ad90SMark F. Adams     ierr = PetscFree(pc_gamg->m_data);CHKERRQ(ierr);
31*5b89ad90SMark F. Adams     pc_gamg->m_data = 0;
32*5b89ad90SMark F. Adams   }
33*5b89ad90SMark F. Adams   PetscFunctionReturn(0);
34*5b89ad90SMark F. Adams }
35*5b89ad90SMark F. Adams 
36*5b89ad90SMark F. Adams /* -------------------------------------------------------------------------- */
37*5b89ad90SMark F. Adams /*
38*5b89ad90SMark F. Adams    PCSetCoordinates_GAMG
39*5b89ad90SMark F. Adams 
40*5b89ad90SMark F. Adams    Input Parameter:
41*5b89ad90SMark F. Adams    .  pc - the preconditioner context
42*5b89ad90SMark F. Adams */
43*5b89ad90SMark F. Adams #undef __FUNCT__
44*5b89ad90SMark F. Adams #define __FUNCT__ "PCSetCoordinates_GAMG"
45*5b89ad90SMark F. Adams PetscErrorCode PCSetCoordinates_GAMG( PC pc, const int ndm,
46*5b89ad90SMark F. Adams                                       PetscReal *coords )
47*5b89ad90SMark F. Adams {
48*5b89ad90SMark F. Adams   PC_MG           *mg = (PC_MG*)pc->data;
49*5b89ad90SMark F. Adams   PC_GAMG         *pc_gamg = (PC_GAMG*)mg->innerctx;
50*5b89ad90SMark F. Adams   PetscErrorCode ierr;  PetscInt bs, my0, tt;
51*5b89ad90SMark F. Adams 
52*5b89ad90SMark F. Adams   PetscFunctionBegin;
53*5b89ad90SMark F. Adams   Mat mat = pc->pmat;
54*5b89ad90SMark F. Adams   ierr = MatGetBlockSize( mat, &bs );               CHKERRQ( ierr );
55*5b89ad90SMark F. Adams   ierr = MatGetOwnershipRange( mat, &my0, &tt ); CHKERRQ(ierr);
56*5b89ad90SMark F. Adams   const PetscInt arrsz = (tt-my0)/bs*ndm;
57*5b89ad90SMark F. Adams 
58*5b89ad90SMark F. Adams   // put coordinates
59*5b89ad90SMark F. Adams   if ( pc_gamg->m_data==0 || pc_gamg->m_data_sz != arrsz ) {
60*5b89ad90SMark F. Adams     if( pc_gamg->m_data != 0 ) {
61*5b89ad90SMark F. Adams       ierr = PetscFree( pc_gamg->m_data );  CHKERRQ(ierr);
62*5b89ad90SMark F. Adams     }
63*5b89ad90SMark F. Adams     ierr = PetscMalloc( (arrsz+1)*sizeof(double), &pc_gamg->m_data ); CHKERRQ(ierr);
64*5b89ad90SMark F. Adams   }
65*5b89ad90SMark F. Adams 
66*5b89ad90SMark F. Adams   /* copy data in */
67*5b89ad90SMark F. Adams   for(tt=0;tt<arrsz;tt++){
68*5b89ad90SMark F. Adams     pc_gamg->m_data[tt] = coords[tt];
69*5b89ad90SMark F. Adams   }
70*5b89ad90SMark F. Adams   pc_gamg->m_data_sz = arrsz;
71*5b89ad90SMark F. Adams   pc_gamg->m_dim = ndm;
72*5b89ad90SMark F. Adams 
73*5b89ad90SMark F. Adams   PetscFunctionReturn(0);
74*5b89ad90SMark F. Adams }
75*5b89ad90SMark F. Adams 
76*5b89ad90SMark F. Adams /* -------------------------------------------------------------------------- */
77*5b89ad90SMark F. Adams /*
78*5b89ad90SMark F. Adams    createCrsOp
79*5b89ad90SMark F. Adams 
80*5b89ad90SMark F. Adams    Input Parameter:
81*5b89ad90SMark F. Adams    . Amat - matrix on this fine level
82*5b89ad90SMark F. Adams    . P_out - prolongation operator to the next level
83*5b89ad90SMark F. Adams    . Acrs - coarse matrix that is created
84*5b89ad90SMark F. Adams */
85*5b89ad90SMark F. Adams #undef __FUNCT__
86*5b89ad90SMark F. Adams #define __FUNCT__ "createCrsOp"
87*5b89ad90SMark F. Adams PetscErrorCode createCrsOp( Mat Amat, Mat P_inout, Mat *Acrs )
88*5b89ad90SMark F. Adams {
89*5b89ad90SMark F. Adams   PetscErrorCode ierr;
90*5b89ad90SMark F. Adams 
91*5b89ad90SMark F. Adams   PetscFunctionBegin;
92*5b89ad90SMark F. Adams   Mat H;
93*5b89ad90SMark F. Adams   ierr = MatPtAP( Amat, P_inout, MAT_INITIAL_MATRIX, 2.0, &H); CHKERRQ(ierr);
94*5b89ad90SMark F. Adams   *Acrs = H;
95*5b89ad90SMark F. Adams 
96*5b89ad90SMark F. Adams   PetscFunctionReturn(0);
97*5b89ad90SMark F. Adams }
98*5b89ad90SMark F. Adams 
99*5b89ad90SMark F. Adams /* -------------------------------------------------------------------------- */
100*5b89ad90SMark F. Adams /*
101*5b89ad90SMark F. Adams    PCSetUp_GAMG - Prepares for the use of the GAMG preconditioner
102*5b89ad90SMark F. Adams                     by setting data structures and options.
103*5b89ad90SMark F. Adams 
104*5b89ad90SMark F. Adams    Input Parameter:
105*5b89ad90SMark F. Adams .  pc - the preconditioner context
106*5b89ad90SMark F. Adams 
107*5b89ad90SMark F. Adams    Application Interface Routine: PCSetUp()
108*5b89ad90SMark F. Adams 
109*5b89ad90SMark F. Adams    Notes:
110*5b89ad90SMark F. Adams    The interface routine PCSetUp() is not usually called directly by
111*5b89ad90SMark F. Adams    the user, but instead is called by PCApply() if necessary.
112*5b89ad90SMark F. Adams */
113*5b89ad90SMark F. Adams extern PetscErrorCode PCSetFromOptions_MG(PC);
114*5b89ad90SMark F. Adams extern PetscErrorCode PCReset_MG(PC);
115*5b89ad90SMark F. Adams extern PetscErrorCode createProlongation( Mat, Mat *, PetscReal [], PetscReal **, const PetscInt);
116*5b89ad90SMark F. Adams #undef __FUNCT__
117*5b89ad90SMark F. Adams #define __FUNCT__ "PCSetUp_GAMG"
118*5b89ad90SMark F. Adams PetscErrorCode PCSetUp_GAMG( PC pc )
119*5b89ad90SMark F. Adams {
120*5b89ad90SMark F. Adams   PetscErrorCode  ierr;
121*5b89ad90SMark F. Adams   PC_MG           *mg = (PC_MG*)pc->data;
122*5b89ad90SMark F. Adams   PC_GAMG         *pc_gamg = (PC_GAMG*)mg->innerctx;
123*5b89ad90SMark F. Adams   Mat              Amat = pc->mat, Pmat = pc->pmat;
124*5b89ad90SMark F. Adams   PetscBool        isSeq, isMPI;
125*5b89ad90SMark F. Adams   PetscInt         fine_level, level, level1, M, N, bs, lidx;
126*5b89ad90SMark F. Adams   MPI_Comm         wcomm = ((PetscObject)pc)->comm;
127*5b89ad90SMark F. Adams 
128*5b89ad90SMark F. Adams   PetscFunctionBegin;
129*5b89ad90SMark F. Adams   if (pc->setupcalled){
130*5b89ad90SMark F. Adams     /* no state data in GAMG to destroy (now) */
131*5b89ad90SMark F. Adams     ierr = PCReset_MG(pc);CHKERRQ(ierr);
132*5b89ad90SMark F. Adams   }
133*5b89ad90SMark F. Adams   if ( pc_gamg->m_data==0 ) {
134*5b89ad90SMark F. Adams     SETERRQ(wcomm,PETSC_ERR_SUP,"PCSetUp_GAMG called before PCSetCoordinates");
135*5b89ad90SMark F. Adams   }
136*5b89ad90SMark F. Adams   /* setup special features of PCGAMG */
137*5b89ad90SMark F. Adams   ierr = PetscTypeCompare((PetscObject) Amat, MATSEQAIJ, &isSeq);CHKERRQ(ierr);
138*5b89ad90SMark F. Adams   ierr = PetscTypeCompare((PetscObject) Amat, MATMPIAIJ, &isMPI);CHKERRQ(ierr);
139*5b89ad90SMark F. Adams   if (isMPI) {
140*5b89ad90SMark F. Adams   } else if (isSeq) {
141*5b89ad90SMark F. Adams   } else SETERRQ1(wcomm,PETSC_ERR_ARG_WRONG, "Matrix type '%s' cannot be used with GAMG. GAMG can only handle AIJ matrices.",((PetscObject)Amat)->type_name);
142*5b89ad90SMark F. Adams 
143*5b89ad90SMark F. Adams   /* GAMG requires input of fine-grid matrix. It determines nlevels. */
144*5b89ad90SMark F. Adams   ierr = MatGetSize( Amat, &M, &N );CHKERRQ(ierr);
145*5b89ad90SMark F. Adams   ierr = MatGetBlockSize( Amat, &bs ); CHKERRQ(ierr);
146*5b89ad90SMark F. Adams   if(bs!=1) SETERRQ1(wcomm,PETSC_ERR_ARG_WRONG, "GAMG only supports scalar prblems bs = '%d'.",bs);
147*5b89ad90SMark F. Adams 
148*5b89ad90SMark F. Adams   /* Get A_i and R_i */
149*5b89ad90SMark F. Adams #define GAMG_MAXLEVELS 10
150*5b89ad90SMark F. Adams   Mat Aarr[GAMG_MAXLEVELS], Rarr[GAMG_MAXLEVELS];  PetscReal *coarse_crds = 0, *crds = pc_gamg->m_data;
151*5b89ad90SMark F. Adams   for (level=0, Aarr[0] = Pmat; level < GAMG_MAXLEVELS-1; level++ ){
152*5b89ad90SMark F. Adams     ierr = MatGetSize( Aarr[level], &M, &N );CHKERRQ(ierr);
153*5b89ad90SMark F. Adams     if( M < 100 ) { /* hard wire this for now */
154*5b89ad90SMark F. Adams       break;
155*5b89ad90SMark F. Adams     }
156*5b89ad90SMark F. Adams     level1 = level + 1;
157*5b89ad90SMark F. Adams     ierr = createProlongation( Aarr[level], &Rarr[level1], crds, &coarse_crds, pc_gamg->m_dim );
158*5b89ad90SMark F. Adams     CHKERRQ(ierr);
159*5b89ad90SMark F. Adams     if(level==0)  Aarr[0] = Amat; /* use Pmat for finest level setup, but use mat for solver */
160*5b89ad90SMark F. Adams     ierr = createCrsOp( Aarr[level], Rarr[level1], &Aarr[level1] ); CHKERRQ(ierr);
161*5b89ad90SMark F. Adams     ierr = PetscFree( crds ); CHKERRQ( ierr );
162*5b89ad90SMark F. Adams     crds = coarse_crds;
163*5b89ad90SMark F. Adams   }
164*5b89ad90SMark F. Adams   if( coarse_crds != 0 ) {
165*5b89ad90SMark F. Adams     ierr = PetscFree( coarse_crds ); CHKERRQ( ierr );
166*5b89ad90SMark F. Adams   }
167*5b89ad90SMark F. Adams   pc_gamg->m_data = 0; /* destroyed coordinate data */
168*5b89ad90SMark F. Adams   pc_gamg->m_Nlevels = level + 1;
169*5b89ad90SMark F. Adams   fine_level = level;
170*5b89ad90SMark F. Adams   ierr = PCMGSetLevels(pc,pc_gamg->m_Nlevels,PETSC_NULL);CHKERRQ(ierr);
171*5b89ad90SMark F. Adams 
172*5b89ad90SMark F. Adams   /* set default smoothers */
173*5b89ad90SMark F. Adams   PetscReal emax = 2.0, emin;
174*5b89ad90SMark F. Adams   for (level=1; level<=fine_level; level++){
175*5b89ad90SMark F. Adams     KSP smoother; PC subpc;
176*5b89ad90SMark F. Adams     ierr = PCMGGetSmoother(pc,level,&smoother);CHKERRQ(ierr);
177*5b89ad90SMark F. Adams     ierr = KSPSetType(smoother,KSPCHEBYCHEV);CHKERRQ(ierr);
178*5b89ad90SMark F. Adams     emin = emax/5.0;
179*5b89ad90SMark F. Adams     ierr = KSPGetPC(smoother,&subpc);CHKERRQ(ierr);
180*5b89ad90SMark F. Adams     ierr = PCSetType(subpc,PCJACOBI);CHKERRQ(ierr);
181*5b89ad90SMark F. Adams     ierr = KSPChebychevSetEigenvalues(smoother, emax, emin);CHKERRQ(ierr); /* need auto !!!!*/
182*5b89ad90SMark F. Adams   }
183*5b89ad90SMark F. Adams   ierr = PCSetFromOptions_MG(pc); CHKERRQ(ierr); /* should be called in PCSetFromOptions_GAMG(), but cannot be called prior to PCMGSetLevels() */
184*5b89ad90SMark F. Adams   {
185*5b89ad90SMark F. Adams     PetscBool galerkin;
186*5b89ad90SMark F. Adams     ierr = PCMGGetGalerkin( pc,  &galerkin); CHKERRQ(ierr);
187*5b89ad90SMark F. Adams     if(galerkin){
188*5b89ad90SMark F. Adams       SETERRQ(wcomm,PETSC_ERR_ARG_WRONG, "GAMG does galerkin manually so it must not be used in PC_MG.");
189*5b89ad90SMark F. Adams     }
190*5b89ad90SMark F. Adams   }
191*5b89ad90SMark F. Adams   /* create coarse level and the interpolation between the levels */
192*5b89ad90SMark F. Adams   for (level=0,lidx=pc_gamg->m_Nlevels-1; level<fine_level; level++,lidx--){
193*5b89ad90SMark F. Adams     level1 = level + 1;
194*5b89ad90SMark F. Adams     /* PetscInt MM,NN; */
195*5b89ad90SMark F. Adams     /* ierr = MatGetSize( Rarr[lidx], &MM, &NN );CHKERRQ(ierr); */
196*5b89ad90SMark F. Adams     /* PetscPrintf(PETSC_COMM_WORLD,"%s Set P(%d,%d) on level %d (%d)\n",__FUNCT__,MM,NN,level1,lidx); */
197*5b89ad90SMark F. Adams     ierr = PCMGSetInterpolation(pc,level1,Rarr[lidx]);CHKERRQ(ierr);
198*5b89ad90SMark F. Adams     if(!true) {
199*5b89ad90SMark F. Adams       PetscViewer        viewer;
200*5b89ad90SMark F. Adams       ierr = PetscViewerASCIIOpen(PETSC_COMM_SELF, "Rmat.m", &viewer);  CHKERRQ(ierr);
201*5b89ad90SMark F. Adams       ierr = PetscViewerSetFormat( viewer, PETSC_VIEWER_ASCII_MATLAB);  CHKERRQ(ierr);
202*5b89ad90SMark F. Adams       ierr = MatView(Rarr[level1],viewer);CHKERRQ(ierr);
203*5b89ad90SMark F. Adams       ierr = PetscViewerDestroy( &viewer );
204*5b89ad90SMark F. Adams     }
205*5b89ad90SMark F. Adams     KSP smoother;
206*5b89ad90SMark F. Adams     ierr = PCMGGetSmoother(pc,level,&smoother); CHKERRQ(ierr);
207*5b89ad90SMark F. Adams     ierr = KSPSetOperators( smoother, Aarr[lidx], Aarr[lidx], DIFFERENT_NONZERO_PATTERN );
208*5b89ad90SMark F. Adams     CHKERRQ(ierr);
209*5b89ad90SMark F. Adams     /* ierr = MatGetSize( Aarr[lidx], &MM, &NN ); CHKERRQ(ierr); */
210*5b89ad90SMark F. Adams     /* PetscPrintf(PETSC_COMM_WORLD,"%s Set A(%d,%d) on level %d (%d)\n",__FUNCT__,MM,NN,level,lidx); */
211*5b89ad90SMark F. Adams   }
212*5b89ad90SMark F. Adams   { /* fine level (no P) */
213*5b89ad90SMark F. Adams     KSP smoother;
214*5b89ad90SMark F. Adams     ierr = PCMGGetSmoother(pc,fine_level,&smoother); CHKERRQ(ierr);
215*5b89ad90SMark F. Adams     ierr = KSPSetOperators( smoother, Aarr[0], Aarr[0], DIFFERENT_NONZERO_PATTERN );
216*5b89ad90SMark F. Adams     CHKERRQ(ierr);
217*5b89ad90SMark F. Adams     /* PetscInt MM,NN; */
218*5b89ad90SMark F. Adams     /* ierr = MatGetSize( Aarr[0], &MM, &NN );CHKERRQ(ierr); */
219*5b89ad90SMark F. Adams     /* PetscPrintf(PETSC_COMM_WORLD,"%s Set A(%d,%d) on level %d (%d)\n",__FUNCT__,MM,NN,fine_level,0); */
220*5b89ad90SMark F. Adams   }
221*5b89ad90SMark F. Adams 
222*5b89ad90SMark F. Adams   /* setupcalled is set to 0 so that MG is setup from scratch */
223*5b89ad90SMark F. Adams   pc->setupcalled = 0;
224*5b89ad90SMark F. Adams   ierr = PCSetUp_MG(pc);CHKERRQ(ierr);
225*5b89ad90SMark F. Adams   PetscFunctionReturn(0);
226*5b89ad90SMark F. Adams }
227*5b89ad90SMark F. Adams 
228*5b89ad90SMark F. Adams /* -------------------------------------------------------------------------- */
229*5b89ad90SMark F. Adams /*
230*5b89ad90SMark F. Adams    PCDestroy_GAMG - Destroys the private context for the GAMG preconditioner
231*5b89ad90SMark F. Adams    that was created with PCCreate_GAMG().
232*5b89ad90SMark F. Adams 
233*5b89ad90SMark F. Adams    Input Parameter:
234*5b89ad90SMark F. Adams .  pc - the preconditioner context
235*5b89ad90SMark F. Adams 
236*5b89ad90SMark F. Adams    Application Interface Routine: PCDestroy()
237*5b89ad90SMark F. Adams */
238*5b89ad90SMark F. Adams #undef __FUNCT__
239*5b89ad90SMark F. Adams #define __FUNCT__ "PCDestroy_GAMG"
240*5b89ad90SMark F. Adams PetscErrorCode PCDestroy_GAMG(PC pc)
241*5b89ad90SMark F. Adams {
242*5b89ad90SMark F. Adams   PetscErrorCode  ierr;
243*5b89ad90SMark F. Adams   PC_MG           *mg = (PC_MG*)pc->data;
244*5b89ad90SMark F. Adams   PC_GAMG         *pc_gamg= (PC_GAMG*)mg->innerctx;
245*5b89ad90SMark F. Adams 
246*5b89ad90SMark F. Adams   PetscFunctionBegin;
247*5b89ad90SMark F. Adams   ierr = PCReset_GAMG(pc);CHKERRQ(ierr);
248*5b89ad90SMark F. Adams   if (pc_gamg->m_data) {
249*5b89ad90SMark F. Adams     ierr = PetscFree(pc_gamg->m_data);CHKERRQ(ierr);
250*5b89ad90SMark F. Adams   }
251*5b89ad90SMark F. Adams   ierr = PetscFree(pc_gamg);CHKERRQ(ierr);
252*5b89ad90SMark F. Adams   ierr = PCDestroy_MG(pc);CHKERRQ(ierr);
253*5b89ad90SMark F. Adams   PetscFunctionReturn(0);
254*5b89ad90SMark F. Adams }
255*5b89ad90SMark F. Adams 
256*5b89ad90SMark F. Adams #undef __FUNCT__
257*5b89ad90SMark F. Adams #define __FUNCT__ "PCSetFromOptions_GAMG"
258*5b89ad90SMark F. Adams PetscErrorCode PCSetFromOptions_GAMG(PC pc)
259*5b89ad90SMark F. Adams {
260*5b89ad90SMark F. Adams   /* PetscErrorCode  ierr; */
261*5b89ad90SMark F. Adams   /* PC_MG           *mg = (PC_MG*)pc->data; */
262*5b89ad90SMark F. Adams   /* PC_GAMG         *pc_gamg = (PC_GAMG*)mg->innerctx; */
263*5b89ad90SMark F. Adams   /* MPI_Comm        comm = ((PetscObject)pc)->comm; */
264*5b89ad90SMark F. Adams 
265*5b89ad90SMark F. Adams   PetscFunctionBegin;
266*5b89ad90SMark F. Adams   PetscFunctionReturn(0);
267*5b89ad90SMark F. Adams }
268*5b89ad90SMark F. Adams 
269*5b89ad90SMark F. Adams /* -------------------------------------------------------------------------- */
270*5b89ad90SMark F. Adams /*
271*5b89ad90SMark F. Adams  PCCreate_GAMG - Creates a GAMG preconditioner context, PC_GAMG
272*5b89ad90SMark F. Adams 
273*5b89ad90SMark F. Adams    Input Parameter:
274*5b89ad90SMark F. Adams .  pc - the preconditioner context
275*5b89ad90SMark F. Adams 
276*5b89ad90SMark F. Adams    Application Interface Routine: PCCreate()
277*5b89ad90SMark F. Adams 
278*5b89ad90SMark F. Adams   */
279*5b89ad90SMark F. Adams  /* MC
280*5b89ad90SMark F. Adams      PCGAMG - Use algebraic multigrid preconditioning. This preconditioner requires you provide
281*5b89ad90SMark F. Adams        fine grid discretization matrix and coordinates on the fine grid.
282*5b89ad90SMark F. Adams 
283*5b89ad90SMark F. Adams    Options Database Key:
284*5b89ad90SMark F. Adams    Multigrid options(inherited)
285*5b89ad90SMark F. Adams +  -pc_mg_cycles <1>: 1 for V cycle, 2 for W-cycle (MGSetCycles)
286*5b89ad90SMark F. Adams .  -pc_mg_smoothup <1>: Number of post-smoothing steps (MGSetNumberSmoothUp)
287*5b89ad90SMark F. Adams .  -pc_mg_smoothdown <1>: Number of pre-smoothing steps (MGSetNumberSmoothDown)
288*5b89ad90SMark F. Adams    -pc_mg_type <multiplicative>: (one of) additive multiplicative full cascade kascade
289*5b89ad90SMark F. Adams    GAMG options:
290*5b89ad90SMark F. Adams 
291*5b89ad90SMark F. Adams    Level: intermediate
292*5b89ad90SMark F. Adams   Concepts: multigrid
293*5b89ad90SMark F. Adams 
294*5b89ad90SMark F. Adams .seealso:  PCCreate(), PCSetType(), PCType (for list of available types), PC, PCMGType,
295*5b89ad90SMark F. Adams            PCMGSetLevels(), PCMGGetLevels(), PCMGSetType(), MPSetCycles(), PCMGSetNumberSmoothDown(),
296*5b89ad90SMark F. Adams            PCMGSetNumberSmoothUp(), PCMGGetCoarseSolve(), PCMGSetResidual(), PCMGSetInterpolation(),
297*5b89ad90SMark F. Adams            PCMGSetRestriction(), PCMGGetSmoother(), PCMGGetSmootherUp(), PCMGGetSmootherDown(),
298*5b89ad90SMark F. Adams            PCMGSetCyclesOnLevel(), PCMGSetRhs(), PCMGSetX(), PCMGSetR()
299*5b89ad90SMark F. Adams M */
300*5b89ad90SMark F. Adams 
301*5b89ad90SMark F. Adams EXTERN_C_BEGIN
302*5b89ad90SMark F. Adams #undef __FUNCT__
303*5b89ad90SMark F. Adams #define __FUNCT__ "PCCreate_GAMG"
304*5b89ad90SMark F. Adams PetscErrorCode  PCCreate_GAMG(PC pc)
305*5b89ad90SMark F. Adams {
306*5b89ad90SMark F. Adams   PetscErrorCode  ierr;
307*5b89ad90SMark F. Adams   PC_GAMG         *pc_gamg;
308*5b89ad90SMark F. Adams   PC_MG           *mg;
309*5b89ad90SMark F. Adams 
310*5b89ad90SMark F. Adams   PetscFunctionBegin;
311*5b89ad90SMark F. Adams   /* PCGAMG is an inherited class of PCMG. Initialize pc as PCMG */
312*5b89ad90SMark F. Adams   ierr = PCSetType(pc,PCMG);CHKERRQ(ierr); /* calls PCCreate_MG() and MGCreate_Private() */
313*5b89ad90SMark F. Adams   ierr = PetscObjectChangeTypeName((PetscObject)pc,PCGAMG);CHKERRQ(ierr);
314*5b89ad90SMark F. Adams 
315*5b89ad90SMark F. Adams   /* create a supporting struct and attach it to pc */
316*5b89ad90SMark F. Adams   ierr = PetscNewLog(pc,PC_GAMG,&pc_gamg);CHKERRQ(ierr);
317*5b89ad90SMark F. Adams   mg = (PC_MG*)pc->data;
318*5b89ad90SMark F. Adams   mg->innerctx = pc_gamg;
319*5b89ad90SMark F. Adams 
320*5b89ad90SMark F. Adams   pc_gamg->m_data     = 0;
321*5b89ad90SMark F. Adams   pc_gamg->m_Nlevels    = -1;
322*5b89ad90SMark F. Adams 
323*5b89ad90SMark F. Adams   /* overwrite the pointers of PCMG by the functions of PCGAMG */
324*5b89ad90SMark F. Adams   pc->ops->setfromoptions = PCSetFromOptions_GAMG;
325*5b89ad90SMark F. Adams   pc->ops->setup          = PCSetUp_GAMG;
326*5b89ad90SMark F. Adams   pc->ops->reset          = PCReset_GAMG;
327*5b89ad90SMark F. Adams   pc->ops->destroy        = PCDestroy_GAMG;
328*5b89ad90SMark F. Adams 
329*5b89ad90SMark F. Adams   ierr = PetscObjectComposeFunctionDynamic( (PetscObject)pc,
330*5b89ad90SMark F. Adams 					    "PCSetCoordinates_C",
331*5b89ad90SMark F. Adams 					    "PCSetCoordinates_GAMG",
332*5b89ad90SMark F. Adams 					    PCSetCoordinates_GAMG);CHKERRQ(ierr);
333*5b89ad90SMark F. Adams   PetscFunctionReturn(0);
334*5b89ad90SMark F. Adams }
335*5b89ad90SMark F. Adams EXTERN_C_END
336