xref: /petsc/src/ksp/pc/impls/mg/mgfunc.c (revision 95452b02e12c0ee11232c7ff2b24b568a8e07e43)
14b9ad928SBarry Smith 
2af0996ceSBarry Smith #include <petsc/private/pcmgimpl.h>       /*I "petscksp.h" I*/
34b9ad928SBarry Smith 
4f9426fe0SMark Adams /* ---------------------------------------------------------------------------*/
51f6cc5b2SSatish Balay /*@C
654b2cd4bSJed Brown    PCMGResidualDefault - Default routine to calculate the residual.
74b9ad928SBarry Smith 
84b9ad928SBarry Smith    Collective on Mat and Vec
94b9ad928SBarry Smith 
104b9ad928SBarry Smith    Input Parameters:
114b9ad928SBarry Smith +  mat - the matrix
124b9ad928SBarry Smith .  b   - the right-hand-side
134b9ad928SBarry Smith -  x   - the approximate solution
144b9ad928SBarry Smith 
154b9ad928SBarry Smith    Output Parameter:
164b9ad928SBarry Smith .  r - location to store the residual
174b9ad928SBarry Smith 
18d0e4de75SBarry Smith    Level: developer
194b9ad928SBarry Smith 
204b9ad928SBarry Smith .keywords: MG, default, multigrid, residual
214b9ad928SBarry Smith 
2297177400SBarry Smith .seealso: PCMGSetResidual()
234b9ad928SBarry Smith @*/
2454b2cd4bSJed Brown PetscErrorCode  PCMGResidualDefault(Mat mat,Vec b,Vec x,Vec r)
254b9ad928SBarry Smith {
26dfbe8321SBarry Smith   PetscErrorCode ierr;
274b9ad928SBarry Smith 
284b9ad928SBarry Smith   PetscFunctionBegin;
29f9426fe0SMark Adams   ierr = MatResidual(mat,b,x,r);CHKERRQ(ierr);
304b9ad928SBarry Smith   PetscFunctionReturn(0);
314b9ad928SBarry Smith }
324b9ad928SBarry Smith 
33f39d8e23SSatish Balay /*@
3497177400SBarry Smith    PCMGGetCoarseSolve - Gets the solver context to be used on the coarse grid.
354b9ad928SBarry Smith 
364b9ad928SBarry Smith    Not Collective
374b9ad928SBarry Smith 
384b9ad928SBarry Smith    Input Parameter:
394b9ad928SBarry Smith .  pc - the multigrid context
404b9ad928SBarry Smith 
414b9ad928SBarry Smith    Output Parameter:
424b9ad928SBarry Smith .  ksp - the coarse grid solver context
434b9ad928SBarry Smith 
444b9ad928SBarry Smith    Level: advanced
454b9ad928SBarry Smith 
464b9ad928SBarry Smith .keywords: MG, multigrid, get, coarse grid
474b9ad928SBarry Smith @*/
487087cfbeSBarry Smith PetscErrorCode  PCMGGetCoarseSolve(PC pc,KSP *ksp)
494b9ad928SBarry Smith {
50f3fbd535SBarry Smith   PC_MG        *mg        = (PC_MG*)pc->data;
51f3fbd535SBarry Smith   PC_MG_Levels **mglevels = mg->levels;
524b9ad928SBarry Smith 
534b9ad928SBarry Smith   PetscFunctionBegin;
54c5eb9154SBarry Smith   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
55f3fbd535SBarry Smith   *ksp =  mglevels[0]->smoothd;
564b9ad928SBarry Smith   PetscFunctionReturn(0);
574b9ad928SBarry Smith }
584b9ad928SBarry Smith 
594b9ad928SBarry Smith /*@C
6097177400SBarry Smith    PCMGSetResidual - Sets the function to be used to calculate the residual
614b9ad928SBarry Smith    on the lth level.
624b9ad928SBarry Smith 
63ad4df100SBarry Smith    Logically Collective on PC and Mat
644b9ad928SBarry Smith 
654b9ad928SBarry Smith    Input Parameters:
664b9ad928SBarry Smith +  pc       - the multigrid context
674b9ad928SBarry Smith .  l        - the level (0 is coarsest) to supply
68157726a2SBarry Smith .  residual - function used to form residual, if none is provided the previously provide one is used, if no
69d0e4de75SBarry Smith               previous one were provided then a default is used
704b9ad928SBarry Smith -  mat      - matrix associated with residual
714b9ad928SBarry Smith 
724b9ad928SBarry Smith    Level: advanced
734b9ad928SBarry Smith 
744b9ad928SBarry Smith .keywords:  MG, set, multigrid, residual, level
754b9ad928SBarry Smith 
7654b2cd4bSJed Brown .seealso: PCMGResidualDefault()
774b9ad928SBarry Smith @*/
787087cfbeSBarry Smith PetscErrorCode  PCMGSetResidual(PC pc,PetscInt l,PetscErrorCode (*residual)(Mat,Vec,Vec,Vec),Mat mat)
794b9ad928SBarry Smith {
80f3fbd535SBarry Smith   PC_MG          *mg        = (PC_MG*)pc->data;
81f3fbd535SBarry Smith   PC_MG_Levels   **mglevels = mg->levels;
82298cc208SBarry Smith   PetscErrorCode ierr;
834b9ad928SBarry Smith 
844b9ad928SBarry Smith   PetscFunctionBegin;
85c5eb9154SBarry Smith   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
86ce94432eSBarry Smith   if (!mglevels) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONGSTATE,"Must set MG levels before calling");
872fa5cd67SKarl Rupp   if (residual) mglevels[l]->residual = residual;
8854b2cd4bSJed Brown   if (!mglevels[l]->residual) mglevels[l]->residual = PCMGResidualDefault;
89f3ae41bdSBarry Smith   if (mat) {ierr = PetscObjectReference((PetscObject)mat);CHKERRQ(ierr);}
90298cc208SBarry Smith   ierr = MatDestroy(&mglevels[l]->A);CHKERRQ(ierr);
91f3fbd535SBarry Smith   mglevels[l]->A = mat;
924b9ad928SBarry Smith   PetscFunctionReturn(0);
934b9ad928SBarry Smith }
944b9ad928SBarry Smith 
954b9ad928SBarry Smith /*@
96aea2a34eSBarry Smith    PCMGSetInterpolation - Sets the function to be used to calculate the
97bf5b2e24SBarry Smith    interpolation from l-1 to the lth level
984b9ad928SBarry Smith 
99ad4df100SBarry Smith    Logically Collective on PC and Mat
1004b9ad928SBarry Smith 
1014b9ad928SBarry Smith    Input Parameters:
1024b9ad928SBarry Smith +  pc  - the multigrid context
1034b9ad928SBarry Smith .  mat - the interpolation operator
104bf5b2e24SBarry Smith -  l   - the level (0 is coarsest) to supply [do not supply 0]
1054b9ad928SBarry Smith 
1064b9ad928SBarry Smith    Level: advanced
1074b9ad928SBarry Smith 
1084b9ad928SBarry Smith    Notes:
1094b9ad928SBarry Smith           Usually this is the same matrix used also to set the restriction
1104b9ad928SBarry Smith     for the same level.
1114b9ad928SBarry Smith 
1124b9ad928SBarry Smith           One can pass in the interpolation matrix or its transpose; PETSc figures
1134b9ad928SBarry Smith     out from the matrix size which one it is.
1144b9ad928SBarry Smith 
1154b9ad928SBarry Smith .keywords:  multigrid, set, interpolate, level
1164b9ad928SBarry Smith 
11797177400SBarry Smith .seealso: PCMGSetRestriction()
1184b9ad928SBarry Smith @*/
1197087cfbeSBarry Smith PetscErrorCode  PCMGSetInterpolation(PC pc,PetscInt l,Mat mat)
1204b9ad928SBarry Smith {
121f3fbd535SBarry Smith   PC_MG          *mg        = (PC_MG*)pc->data;
122f3fbd535SBarry Smith   PC_MG_Levels   **mglevels = mg->levels;
123fccaa45eSBarry Smith   PetscErrorCode ierr;
1244b9ad928SBarry Smith 
1254b9ad928SBarry Smith   PetscFunctionBegin;
126c5eb9154SBarry Smith   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
127ce94432eSBarry Smith   if (!mglevels) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONGSTATE,"Must set MG levels before calling");
128ce94432eSBarry Smith   if (!l) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_OUTOFRANGE,"Do not set interpolation routine for coarsest level");
129c3122656SLisandro Dalcin   ierr = PetscObjectReference((PetscObject)mat);CHKERRQ(ierr);
1306bf464f9SBarry Smith   ierr = MatDestroy(&mglevels[l]->interpolate);CHKERRQ(ierr);
1312fa5cd67SKarl Rupp 
132f3fbd535SBarry Smith   mglevels[l]->interpolate = mat;
1334b9ad928SBarry Smith   PetscFunctionReturn(0);
1344b9ad928SBarry Smith }
1354b9ad928SBarry Smith 
136c88c5224SJed Brown /*@
137c88c5224SJed Brown    PCMGGetInterpolation - Gets the function to be used to calculate the
138c88c5224SJed Brown    interpolation from l-1 to the lth level
139c88c5224SJed Brown 
140c88c5224SJed Brown    Logically Collective on PC
141c88c5224SJed Brown 
142c88c5224SJed Brown    Input Parameters:
143c88c5224SJed Brown +  pc - the multigrid context
144c88c5224SJed Brown -  l - the level (0 is coarsest) to supply [Do not supply 0]
145c88c5224SJed Brown 
146c88c5224SJed Brown    Output Parameter:
1473ad4599aSBarry Smith .  mat - the interpolation matrix, can be NULL
148c88c5224SJed Brown 
149c88c5224SJed Brown    Level: advanced
150c88c5224SJed Brown 
151c88c5224SJed Brown .keywords: MG, get, multigrid, interpolation, level
152c88c5224SJed Brown 
153c88c5224SJed Brown .seealso: PCMGGetRestriction(), PCMGSetInterpolation(), PCMGGetRScale()
154c88c5224SJed Brown @*/
155c88c5224SJed Brown PetscErrorCode  PCMGGetInterpolation(PC pc,PetscInt l,Mat *mat)
156c88c5224SJed Brown {
157c88c5224SJed Brown   PC_MG          *mg        = (PC_MG*)pc->data;
158c88c5224SJed Brown   PC_MG_Levels   **mglevels = mg->levels;
159c88c5224SJed Brown   PetscErrorCode ierr;
160c88c5224SJed Brown 
161c88c5224SJed Brown   PetscFunctionBegin;
162c88c5224SJed Brown   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
1633ad4599aSBarry Smith   if (mat) PetscValidPointer(mat,3);
164ce94432eSBarry Smith   if (!mglevels) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONGSTATE,"Must set MG levels before calling");
165ce94432eSBarry Smith   if (l <= 0 || mg->nlevels <= l) SETERRQ2(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_OUTOFRANGE,"Level %D must be in range {1,...,%D}",l,mg->nlevels-1);
166c88c5224SJed Brown   if (!mglevels[l]->interpolate) {
1675aa31b60SBarry Smith     if (!mglevels[l]->restrct) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONGSTATE,"Must call PCMGSetInterpolation() or PCMGSetRestriction()");
168c88c5224SJed Brown     ierr = PCMGSetInterpolation(pc,l,mglevels[l]->restrct);CHKERRQ(ierr);
169c88c5224SJed Brown   }
1703ad4599aSBarry Smith   if (mat) *mat = mglevels[l]->interpolate;
171c88c5224SJed Brown   PetscFunctionReturn(0);
172c88c5224SJed Brown }
173c88c5224SJed Brown 
1744b9ad928SBarry Smith /*@
175eab52d2bSLawrence Mitchell    PCMGSetRestriction - Sets the function to be used to restrict dual vectors
1764b9ad928SBarry Smith    from level l to l-1.
1774b9ad928SBarry Smith 
178ad4df100SBarry Smith    Logically Collective on PC and Mat
1794b9ad928SBarry Smith 
1804b9ad928SBarry Smith    Input Parameters:
1814b9ad928SBarry Smith +  pc - the multigrid context
182c88c5224SJed Brown .  l - the level (0 is coarsest) to supply [Do not supply 0]
183c88c5224SJed Brown -  mat - the restriction matrix
1844b9ad928SBarry Smith 
1854b9ad928SBarry Smith    Level: advanced
1864b9ad928SBarry Smith 
1874b9ad928SBarry Smith    Notes:
1884b9ad928SBarry Smith           Usually this is the same matrix used also to set the interpolation
1894b9ad928SBarry Smith     for the same level.
1904b9ad928SBarry Smith 
1914b9ad928SBarry Smith           One can pass in the interpolation matrix or its transpose; PETSc figures
1924b9ad928SBarry Smith     out from the matrix size which one it is.
1934b9ad928SBarry Smith 
194aea2a34eSBarry Smith          If you do not set this, the transpose of the Mat set with PCMGSetInterpolation()
195fccaa45eSBarry Smith     is used.
196fccaa45eSBarry Smith 
1974b9ad928SBarry Smith .keywords: MG, set, multigrid, restriction, level
1984b9ad928SBarry Smith 
199eab52d2bSLawrence Mitchell .seealso: PCMGSetInterpolation(), PCMGetSetInjection()
2004b9ad928SBarry Smith @*/
2017087cfbeSBarry Smith PetscErrorCode  PCMGSetRestriction(PC pc,PetscInt l,Mat mat)
2024b9ad928SBarry Smith {
203fccaa45eSBarry Smith   PetscErrorCode ierr;
204f3fbd535SBarry Smith   PC_MG          *mg        = (PC_MG*)pc->data;
205f3fbd535SBarry Smith   PC_MG_Levels   **mglevels = mg->levels;
2064b9ad928SBarry Smith 
2074b9ad928SBarry Smith   PetscFunctionBegin;
208c5eb9154SBarry Smith   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
209c88c5224SJed Brown   PetscValidHeaderSpecific(mat,MAT_CLASSID,3);
210ce94432eSBarry Smith   if (!mglevels) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONGSTATE,"Must set MG levels before calling");
211ce94432eSBarry Smith   if (!l) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_OUTOFRANGE,"Do not set restriction routine for coarsest level");
212c3122656SLisandro Dalcin   ierr = PetscObjectReference((PetscObject)mat);CHKERRQ(ierr);
2136bf464f9SBarry Smith   ierr = MatDestroy(&mglevels[l]->restrct);CHKERRQ(ierr);
2142fa5cd67SKarl Rupp 
215f3fbd535SBarry Smith   mglevels[l]->restrct = mat;
2164b9ad928SBarry Smith   PetscFunctionReturn(0);
2174b9ad928SBarry Smith }
2184b9ad928SBarry Smith 
219c88c5224SJed Brown /*@
220eab52d2bSLawrence Mitchell    PCMGGetRestriction - Gets the function to be used to restrict dual vectors
221c88c5224SJed Brown    from level l to l-1.
222c88c5224SJed Brown 
223c88c5224SJed Brown    Logically Collective on PC and Mat
224c88c5224SJed Brown 
225c88c5224SJed Brown    Input Parameters:
226c88c5224SJed Brown +  pc - the multigrid context
227c88c5224SJed Brown -  l - the level (0 is coarsest) to supply [Do not supply 0]
228c88c5224SJed Brown 
229c88c5224SJed Brown    Output Parameter:
230c88c5224SJed Brown .  mat - the restriction matrix
231c88c5224SJed Brown 
232c88c5224SJed Brown    Level: advanced
233c88c5224SJed Brown 
234c88c5224SJed Brown .keywords: MG, get, multigrid, restriction, level
235c88c5224SJed Brown 
236eab52d2bSLawrence Mitchell .seealso: PCMGGetInterpolation(), PCMGSetRestriction(), PCMGGetRScale(), PCMGGetInjection()
237c88c5224SJed Brown @*/
238c88c5224SJed Brown PetscErrorCode  PCMGGetRestriction(PC pc,PetscInt l,Mat *mat)
239c88c5224SJed Brown {
240c88c5224SJed Brown   PC_MG          *mg        = (PC_MG*)pc->data;
241c88c5224SJed Brown   PC_MG_Levels   **mglevels = mg->levels;
242c88c5224SJed Brown   PetscErrorCode ierr;
243c88c5224SJed Brown 
244c88c5224SJed Brown   PetscFunctionBegin;
245c88c5224SJed Brown   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
2463ad4599aSBarry Smith   if (mat) PetscValidPointer(mat,3);
247ce94432eSBarry Smith   if (!mglevels) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONGSTATE,"Must set MG levels before calling");
248ce94432eSBarry Smith   if (l <= 0 || mg->nlevels <= l) SETERRQ2(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_OUTOFRANGE,"Level %D must be in range {1,...,%D}",l,mg->nlevels-1);
249c88c5224SJed Brown   if (!mglevels[l]->restrct) {
250ce94432eSBarry Smith     if (!mglevels[l]->interpolate) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONGSTATE,"Must call PCMGSetRestriction() or PCMGSetInterpolation()");
251c88c5224SJed Brown     ierr = PCMGSetRestriction(pc,l,mglevels[l]->interpolate);CHKERRQ(ierr);
252c88c5224SJed Brown   }
2533ad4599aSBarry Smith   if (mat) *mat = mglevels[l]->restrct;
254c88c5224SJed Brown   PetscFunctionReturn(0);
255c88c5224SJed Brown }
256c88c5224SJed Brown 
25773250ac0SBarry Smith /*@
25873250ac0SBarry Smith    PCMGSetRScale - Sets the pointwise scaling for the restriction operator from level l to l-1.
25973250ac0SBarry Smith 
260c88c5224SJed Brown    Logically Collective on PC and Vec
261c88c5224SJed Brown 
262c88c5224SJed Brown    Input Parameters:
263c88c5224SJed Brown +  pc - the multigrid context
264c88c5224SJed Brown -  l - the level (0 is coarsest) to supply [Do not supply 0]
265c88c5224SJed Brown .  rscale - the scaling
266c88c5224SJed Brown 
267c88c5224SJed Brown    Level: advanced
268c88c5224SJed Brown 
269c88c5224SJed Brown    Notes:
270eab52d2bSLawrence Mitchell        When evaluating a function on a coarse level one does not want to do F(R * x) one does F(rscale * R * x) where rscale is 1 over the row sums of R.  It is preferable to use PCMGSetInjection() to control moving primal vectors.
271c88c5224SJed Brown 
272c88c5224SJed Brown .keywords: MG, set, multigrid, restriction, level
273c88c5224SJed Brown 
274eab52d2bSLawrence Mitchell .seealso: PCMGSetInterpolation(), PCMGSetRestriction(), PCMGGetRScale(), PCMGSetInjection()
275c88c5224SJed Brown @*/
276c88c5224SJed Brown PetscErrorCode  PCMGSetRScale(PC pc,PetscInt l,Vec rscale)
277c88c5224SJed Brown {
278c88c5224SJed Brown   PetscErrorCode ierr;
279c88c5224SJed Brown   PC_MG          *mg        = (PC_MG*)pc->data;
280c88c5224SJed Brown   PC_MG_Levels   **mglevels = mg->levels;
281c88c5224SJed Brown 
282c88c5224SJed Brown   PetscFunctionBegin;
283c88c5224SJed Brown   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
284ce94432eSBarry Smith   if (!mglevels) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONGSTATE,"Must set MG levels before calling");
285ce94432eSBarry Smith   if (l <= 0 || mg->nlevels <= l) SETERRQ2(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_OUTOFRANGE,"Level %D must be in range {1,...,%D}",l,mg->nlevels-1);
286c88c5224SJed Brown   ierr = PetscObjectReference((PetscObject)rscale);CHKERRQ(ierr);
287c88c5224SJed Brown   ierr = VecDestroy(&mglevels[l]->rscale);CHKERRQ(ierr);
2882fa5cd67SKarl Rupp 
289c88c5224SJed Brown   mglevels[l]->rscale = rscale;
290c88c5224SJed Brown   PetscFunctionReturn(0);
291c88c5224SJed Brown }
292c88c5224SJed Brown 
293c88c5224SJed Brown /*@
294c88c5224SJed Brown    PCMGGetRScale - Gets the pointwise scaling for the restriction operator from level l to l-1.
295c88c5224SJed Brown 
296c88c5224SJed Brown    Collective on PC
29773250ac0SBarry Smith 
29873250ac0SBarry Smith    Input Parameters:
29973250ac0SBarry Smith +  pc - the multigrid context
30073250ac0SBarry Smith .  rscale - the scaling
30173250ac0SBarry Smith -  l - the level (0 is coarsest) to supply [Do not supply 0]
30273250ac0SBarry Smith 
30373250ac0SBarry Smith    Level: advanced
30473250ac0SBarry Smith 
30573250ac0SBarry Smith    Notes:
306eab52d2bSLawrence Mitchell        When evaluating a function on a coarse level one does not want to do F(R * x) one does F(rscale * R * x) where rscale is 1 over the row sums of R.  It is preferable to use PCMGGetInjection() to control moving primal vectors.
30773250ac0SBarry Smith 
30873250ac0SBarry Smith .keywords: MG, set, multigrid, restriction, level
30973250ac0SBarry Smith 
310eab52d2bSLawrence Mitchell .seealso: PCMGSetInterpolation(), PCMGGetRestriction(), PCMGGetInjection()
31173250ac0SBarry Smith @*/
312c88c5224SJed Brown PetscErrorCode PCMGGetRScale(PC pc,PetscInt l,Vec *rscale)
31373250ac0SBarry Smith {
31473250ac0SBarry Smith   PetscErrorCode ierr;
31573250ac0SBarry Smith   PC_MG          *mg        = (PC_MG*)pc->data;
31673250ac0SBarry Smith   PC_MG_Levels   **mglevels = mg->levels;
31773250ac0SBarry Smith 
31873250ac0SBarry Smith   PetscFunctionBegin;
31973250ac0SBarry Smith   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
320ce94432eSBarry Smith   if (!mglevels) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONGSTATE,"Must set MG levels before calling");
321ce94432eSBarry Smith   if (l <= 0 || mg->nlevels <= l) SETERRQ2(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_OUTOFRANGE,"Level %D must be in range {1,...,%D}",l,mg->nlevels-1);
322c88c5224SJed Brown   if (!mglevels[l]->rscale) {
323c88c5224SJed Brown     Mat      R;
324c88c5224SJed Brown     Vec      X,Y,coarse,fine;
325c88c5224SJed Brown     PetscInt M,N;
326c88c5224SJed Brown     ierr = PCMGGetRestriction(pc,l,&R);CHKERRQ(ierr);
3272a7a6963SBarry Smith     ierr = MatCreateVecs(R,&X,&Y);CHKERRQ(ierr);
328c88c5224SJed Brown     ierr = MatGetSize(R,&M,&N);CHKERRQ(ierr);
3292fa5cd67SKarl Rupp     if (M < N) {
3302fa5cd67SKarl Rupp       fine = X;
3312fa5cd67SKarl Rupp       coarse = Y;
3322fa5cd67SKarl Rupp     } else if (N < M) {
3332fa5cd67SKarl Rupp       fine = Y; coarse = X;
334ce94432eSBarry Smith     } else SETERRQ(PetscObjectComm((PetscObject)R),PETSC_ERR_SUP,"Restriction matrix is square, cannot determine which Vec is coarser");
335c88c5224SJed Brown     ierr = VecSet(fine,1.);CHKERRQ(ierr);
336c88c5224SJed Brown     ierr = MatRestrict(R,fine,coarse);CHKERRQ(ierr);
337c88c5224SJed Brown     ierr = VecDestroy(&fine);CHKERRQ(ierr);
338c88c5224SJed Brown     ierr = VecReciprocal(coarse);CHKERRQ(ierr);
339c88c5224SJed Brown     mglevels[l]->rscale = coarse;
340c88c5224SJed Brown   }
341c88c5224SJed Brown   *rscale = mglevels[l]->rscale;
34273250ac0SBarry Smith   PetscFunctionReturn(0);
34373250ac0SBarry Smith }
34473250ac0SBarry Smith 
345f39d8e23SSatish Balay /*@
346eab52d2bSLawrence Mitchell    PCMGSetInjection - Sets the function to be used to inject primal vectors
347eab52d2bSLawrence Mitchell    from level l to l-1.
348eab52d2bSLawrence Mitchell 
349eab52d2bSLawrence Mitchell    Logically Collective on PC and Mat
350eab52d2bSLawrence Mitchell 
351eab52d2bSLawrence Mitchell    Input Parameters:
352eab52d2bSLawrence Mitchell +  pc - the multigrid context
353eab52d2bSLawrence Mitchell .  l - the level (0 is coarsest) to supply [Do not supply 0]
354eab52d2bSLawrence Mitchell -  mat - the injection matrix
355eab52d2bSLawrence Mitchell 
356eab52d2bSLawrence Mitchell    Level: advanced
357eab52d2bSLawrence Mitchell 
358eab52d2bSLawrence Mitchell .keywords: MG, set, multigrid, restriction, injection, level
359eab52d2bSLawrence Mitchell 
360eab52d2bSLawrence Mitchell .seealso: PCMGSetRestriction()
361eab52d2bSLawrence Mitchell @*/
362eab52d2bSLawrence Mitchell PetscErrorCode  PCMGSetInjection(PC pc,PetscInt l,Mat mat)
363eab52d2bSLawrence Mitchell {
364eab52d2bSLawrence Mitchell   PetscErrorCode ierr;
365eab52d2bSLawrence Mitchell   PC_MG          *mg        = (PC_MG*)pc->data;
366eab52d2bSLawrence Mitchell   PC_MG_Levels   **mglevels = mg->levels;
367eab52d2bSLawrence Mitchell 
368eab52d2bSLawrence Mitchell   PetscFunctionBegin;
369eab52d2bSLawrence Mitchell   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
370eab52d2bSLawrence Mitchell   PetscValidHeaderSpecific(mat,MAT_CLASSID,3);
371eab52d2bSLawrence Mitchell   if (!mglevels) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONGSTATE,"Must set MG levels before calling");
372eab52d2bSLawrence Mitchell   if (!l) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_OUTOFRANGE,"Do not set restriction routine for coarsest level");
373eab52d2bSLawrence Mitchell   ierr = PetscObjectReference((PetscObject)mat);CHKERRQ(ierr);
374eab52d2bSLawrence Mitchell   ierr = MatDestroy(&mglevels[l]->inject);CHKERRQ(ierr);
375eab52d2bSLawrence Mitchell 
376eab52d2bSLawrence Mitchell   mglevels[l]->inject = mat;
377eab52d2bSLawrence Mitchell   PetscFunctionReturn(0);
378eab52d2bSLawrence Mitchell }
379eab52d2bSLawrence Mitchell 
380eab52d2bSLawrence Mitchell /*@
381eab52d2bSLawrence Mitchell    PCMGGetInjection - Gets the function to be used to inject primal vectors
382eab52d2bSLawrence Mitchell    from level l to l-1.
383eab52d2bSLawrence Mitchell 
384eab52d2bSLawrence Mitchell    Logically Collective on PC and Mat
385eab52d2bSLawrence Mitchell 
386eab52d2bSLawrence Mitchell    Input Parameters:
387eab52d2bSLawrence Mitchell +  pc - the multigrid context
388eab52d2bSLawrence Mitchell -  l - the level (0 is coarsest) to supply [Do not supply 0]
389eab52d2bSLawrence Mitchell 
390eab52d2bSLawrence Mitchell    Output Parameter:
39199a38656SLawrence Mitchell .  mat - the restriction matrix (may be NULL if no injection is available).
392eab52d2bSLawrence Mitchell 
393eab52d2bSLawrence Mitchell    Level: advanced
394eab52d2bSLawrence Mitchell 
395eab52d2bSLawrence Mitchell .keywords: MG, get, multigrid, restriction, injection, level
396eab52d2bSLawrence Mitchell 
397eab52d2bSLawrence Mitchell .seealso: PCMGSetInjection(), PCMGetGetRestriction()
398eab52d2bSLawrence Mitchell @*/
399eab52d2bSLawrence Mitchell PetscErrorCode  PCMGGetInjection(PC pc,PetscInt l,Mat *mat)
400eab52d2bSLawrence Mitchell {
401eab52d2bSLawrence Mitchell   PC_MG          *mg        = (PC_MG*)pc->data;
402eab52d2bSLawrence Mitchell   PC_MG_Levels   **mglevels = mg->levels;
403eab52d2bSLawrence Mitchell 
404eab52d2bSLawrence Mitchell   PetscFunctionBegin;
405eab52d2bSLawrence Mitchell   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
406eab52d2bSLawrence Mitchell   if (mat) PetscValidPointer(mat,3);
407eab52d2bSLawrence Mitchell   if (!mglevels) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONGSTATE,"Must set MG levels before calling");
408eab52d2bSLawrence Mitchell   if (l <= 0 || mg->nlevels <= l) SETERRQ2(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_OUTOFRANGE,"Level %D must be in range {1,...,%D}",l,mg->nlevels-1);
409eab52d2bSLawrence Mitchell   if (mat) *mat = mglevels[l]->inject;
410eab52d2bSLawrence Mitchell   PetscFunctionReturn(0);
411eab52d2bSLawrence Mitchell }
412eab52d2bSLawrence Mitchell 
413eab52d2bSLawrence Mitchell /*@
41497177400SBarry Smith    PCMGGetSmoother - Gets the KSP context to be used as smoother for
41597177400SBarry Smith    both pre- and post-smoothing.  Call both PCMGGetSmootherUp() and
41697177400SBarry Smith    PCMGGetSmootherDown() to use different functions for pre- and
4174b9ad928SBarry Smith    post-smoothing.
4184b9ad928SBarry Smith 
4194b9ad928SBarry Smith    Not Collective, KSP returned is parallel if PC is
4204b9ad928SBarry Smith 
4214b9ad928SBarry Smith    Input Parameters:
4224b9ad928SBarry Smith +  pc - the multigrid context
4234b9ad928SBarry Smith -  l - the level (0 is coarsest) to supply
4244b9ad928SBarry Smith 
4254b9ad928SBarry Smith    Ouput Parameters:
4264b9ad928SBarry Smith .  ksp - the smoother
4274b9ad928SBarry Smith 
42857420d5bSBarry Smith    Notes:
42957420d5bSBarry Smith    Once you have called this routine, you can call KSPSetOperators(ksp,...) on the resulting ksp to provide the operators for the smoother for this level.
43057420d5bSBarry Smith    You can also modify smoother options by calling the various KSPSetXXX() options on this ksp. In addition you can call KSPGetPC(ksp,&pc)
43157420d5bSBarry Smith    and modify PC options for the smoother; for example PCSetType(pc,PCSOR); to use SOR smoothing.
43257420d5bSBarry Smith 
4334b9ad928SBarry Smith    Level: advanced
4344b9ad928SBarry Smith 
4354b9ad928SBarry Smith .keywords: MG, get, multigrid, level, smoother, pre-smoother, post-smoother
4364b9ad928SBarry Smith 
43797177400SBarry Smith .seealso: PCMGGetSmootherUp(), PCMGGetSmootherDown()
4384b9ad928SBarry Smith @*/
4397087cfbeSBarry Smith PetscErrorCode  PCMGGetSmoother(PC pc,PetscInt l,KSP *ksp)
4404b9ad928SBarry Smith {
441f3fbd535SBarry Smith   PC_MG        *mg        = (PC_MG*)pc->data;
442f3fbd535SBarry Smith   PC_MG_Levels **mglevels = mg->levels;
4434b9ad928SBarry Smith 
4444b9ad928SBarry Smith   PetscFunctionBegin;
445c5eb9154SBarry Smith   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
446f3fbd535SBarry Smith   *ksp = mglevels[l]->smoothd;
4474b9ad928SBarry Smith   PetscFunctionReturn(0);
4484b9ad928SBarry Smith }
4494b9ad928SBarry Smith 
450f39d8e23SSatish Balay /*@
45197177400SBarry Smith    PCMGGetSmootherUp - Gets the KSP context to be used as smoother after
4524b9ad928SBarry Smith    coarse grid correction (post-smoother).
4534b9ad928SBarry Smith 
4544b9ad928SBarry Smith    Not Collective, KSP returned is parallel if PC is
4554b9ad928SBarry Smith 
4564b9ad928SBarry Smith    Input Parameters:
4574b9ad928SBarry Smith +  pc - the multigrid context
4584b9ad928SBarry Smith -  l  - the level (0 is coarsest) to supply
4594b9ad928SBarry Smith 
4604b9ad928SBarry Smith    Ouput Parameters:
4614b9ad928SBarry Smith .  ksp - the smoother
4624b9ad928SBarry Smith 
4634b9ad928SBarry Smith    Level: advanced
4644b9ad928SBarry Smith 
465*95452b02SPatrick Sanan    Notes:
466*95452b02SPatrick Sanan     calling this will result in a different pre and post smoother so you may need to
46789cce641SBarry Smith          set options on the pre smoother also
46889cce641SBarry Smith 
4694b9ad928SBarry Smith .keywords: MG, multigrid, get, smoother, up, post-smoother, level
4704b9ad928SBarry Smith 
47197177400SBarry Smith .seealso: PCMGGetSmootherUp(), PCMGGetSmootherDown()
4724b9ad928SBarry Smith @*/
4737087cfbeSBarry Smith PetscErrorCode  PCMGGetSmootherUp(PC pc,PetscInt l,KSP *ksp)
4744b9ad928SBarry Smith {
475f3fbd535SBarry Smith   PC_MG          *mg        = (PC_MG*)pc->data;
476f3fbd535SBarry Smith   PC_MG_Levels   **mglevels = mg->levels;
477dfbe8321SBarry Smith   PetscErrorCode ierr;
478f69a0ea3SMatthew Knepley   const char     *prefix;
4794b9ad928SBarry Smith   MPI_Comm       comm;
4804b9ad928SBarry Smith 
4814b9ad928SBarry Smith   PetscFunctionBegin;
482c5eb9154SBarry Smith   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
4834b9ad928SBarry Smith   /*
4844b9ad928SBarry Smith      This is called only if user wants a different pre-smoother from post.
4854b9ad928SBarry Smith      Thus we check if a different one has already been allocated,
4864b9ad928SBarry Smith      if not we allocate it.
4874b9ad928SBarry Smith   */
488ce94432eSBarry Smith   if (!l) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_OUTOFRANGE,"There is no such thing as a up smoother on the coarse grid");
489f3fbd535SBarry Smith   if (mglevels[l]->smoothu == mglevels[l]->smoothd) {
49019fd82e9SBarry Smith     KSPType     ksptype;
49119fd82e9SBarry Smith     PCType      pctype;
492336babb1SJed Brown     PC          ipc;
493336babb1SJed Brown     PetscReal   rtol,abstol,dtol;
494336babb1SJed Brown     PetscInt    maxits;
495336babb1SJed Brown     KSPNormType normtype;
496f3fbd535SBarry Smith     ierr = PetscObjectGetComm((PetscObject)mglevels[l]->smoothd,&comm);CHKERRQ(ierr);
497f3fbd535SBarry Smith     ierr = KSPGetOptionsPrefix(mglevels[l]->smoothd,&prefix);CHKERRQ(ierr);
498336babb1SJed Brown     ierr = KSPGetTolerances(mglevels[l]->smoothd,&rtol,&abstol,&dtol,&maxits);CHKERRQ(ierr);
4993bf036e2SBarry Smith     ierr = KSPGetType(mglevels[l]->smoothd,&ksptype);CHKERRQ(ierr);
500336babb1SJed Brown     ierr = KSPGetNormType(mglevels[l]->smoothd,&normtype);CHKERRQ(ierr);
501336babb1SJed Brown     ierr = KSPGetPC(mglevels[l]->smoothd,&ipc);CHKERRQ(ierr);
502336babb1SJed Brown     ierr = PCGetType(ipc,&pctype);CHKERRQ(ierr);
503336babb1SJed Brown 
504f3fbd535SBarry Smith     ierr = KSPCreate(comm,&mglevels[l]->smoothu);CHKERRQ(ierr);
505422a814eSBarry Smith     ierr = KSPSetErrorIfNotConverged(mglevels[l]->smoothu,pc->erroriffailure);CHKERRQ(ierr);
506f3fbd535SBarry Smith     ierr = PetscObjectIncrementTabLevel((PetscObject)mglevels[l]->smoothu,(PetscObject)pc,mglevels[0]->levels-l);CHKERRQ(ierr);
507f3fbd535SBarry Smith     ierr = KSPSetOptionsPrefix(mglevels[l]->smoothu,prefix);CHKERRQ(ierr);
508336babb1SJed Brown     ierr = KSPSetTolerances(mglevels[l]->smoothu,rtol,abstol,dtol,maxits);CHKERRQ(ierr);
509336babb1SJed Brown     ierr = KSPSetType(mglevels[l]->smoothu,ksptype);CHKERRQ(ierr);
510336babb1SJed Brown     ierr = KSPSetNormType(mglevels[l]->smoothu,normtype);CHKERRQ(ierr);
5110059c7bdSJed Brown     ierr = KSPSetConvergenceTest(mglevels[l]->smoothu,KSPConvergedSkip,NULL,NULL);CHKERRQ(ierr);
512336babb1SJed Brown     ierr = KSPGetPC(mglevels[l]->smoothu,&ipc);CHKERRQ(ierr);
513336babb1SJed Brown     ierr = PCSetType(ipc,pctype);CHKERRQ(ierr);
5143bb1ff40SBarry Smith     ierr = PetscLogObjectParent((PetscObject)pc,(PetscObject)mglevels[l]->smoothu);CHKERRQ(ierr);
515ab83eea4SMatthew G. Knepley     ierr = PetscObjectComposedDataSetInt((PetscObject) mglevels[l]->smoothu, PetscMGLevelId, mglevels[l]->level);CHKERRQ(ierr);
5164b9ad928SBarry Smith   }
517f3fbd535SBarry Smith   if (ksp) *ksp = mglevels[l]->smoothu;
5184b9ad928SBarry Smith   PetscFunctionReturn(0);
5194b9ad928SBarry Smith }
5204b9ad928SBarry Smith 
521f39d8e23SSatish Balay /*@
52297177400SBarry Smith    PCMGGetSmootherDown - Gets the KSP context to be used as smoother before
5234b9ad928SBarry Smith    coarse grid correction (pre-smoother).
5244b9ad928SBarry Smith 
5254b9ad928SBarry Smith    Not Collective, KSP returned is parallel if PC is
5264b9ad928SBarry Smith 
5274b9ad928SBarry Smith    Input Parameters:
5284b9ad928SBarry Smith +  pc - the multigrid context
5294b9ad928SBarry Smith -  l  - the level (0 is coarsest) to supply
5304b9ad928SBarry Smith 
5314b9ad928SBarry Smith    Ouput Parameters:
5324b9ad928SBarry Smith .  ksp - the smoother
5334b9ad928SBarry Smith 
5344b9ad928SBarry Smith    Level: advanced
5354b9ad928SBarry Smith 
536*95452b02SPatrick Sanan    Notes:
537*95452b02SPatrick Sanan     calling this will result in a different pre and post smoother so you may need to
53889cce641SBarry Smith          set options on the post smoother also
53989cce641SBarry Smith 
5404b9ad928SBarry Smith .keywords: MG, multigrid, get, smoother, down, pre-smoother, level
5414b9ad928SBarry Smith 
54297177400SBarry Smith .seealso: PCMGGetSmootherUp(), PCMGGetSmoother()
5434b9ad928SBarry Smith @*/
5447087cfbeSBarry Smith PetscErrorCode  PCMGGetSmootherDown(PC pc,PetscInt l,KSP *ksp)
5454b9ad928SBarry Smith {
546dfbe8321SBarry Smith   PetscErrorCode ierr;
547f3fbd535SBarry Smith   PC_MG          *mg        = (PC_MG*)pc->data;
548f3fbd535SBarry Smith   PC_MG_Levels   **mglevels = mg->levels;
5494b9ad928SBarry Smith 
5504b9ad928SBarry Smith   PetscFunctionBegin;
551c5eb9154SBarry Smith   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
5524b9ad928SBarry Smith   /* make sure smoother up and down are different */
553c5eb9154SBarry Smith   if (l) {
5540298fd71SBarry Smith     ierr = PCMGGetSmootherUp(pc,l,NULL);CHKERRQ(ierr);
555d8148a5aSMatthew Knepley   }
556f3fbd535SBarry Smith   *ksp = mglevels[l]->smoothd;
5574b9ad928SBarry Smith   PetscFunctionReturn(0);
5584b9ad928SBarry Smith }
5594b9ad928SBarry Smith 
5604b9ad928SBarry Smith /*@
561cab31ae5SJed Brown    PCMGSetCycleTypeOnLevel - Sets the type of cycle (aka cycle index) to run on the specified level.
5624b9ad928SBarry Smith 
563ad4df100SBarry Smith    Logically Collective on PC
5644b9ad928SBarry Smith 
5654b9ad928SBarry Smith    Input Parameters:
5664b9ad928SBarry Smith +  pc - the multigrid context
567c1cbb1deSBarry Smith .  l  - the level (0 is coarsest)
568c1cbb1deSBarry Smith -  c  - either PC_MG_CYCLE_V or PC_MG_CYCLE_W
5694b9ad928SBarry Smith 
5704b9ad928SBarry Smith    Level: advanced
5714b9ad928SBarry Smith 
5724b9ad928SBarry Smith .keywords: MG, multigrid, set, cycles, V-cycle, W-cycle, level
5734b9ad928SBarry Smith 
574c1cbb1deSBarry Smith .seealso: PCMGSetCycleType()
5754b9ad928SBarry Smith @*/
576c1cbb1deSBarry Smith PetscErrorCode  PCMGSetCycleTypeOnLevel(PC pc,PetscInt l,PCMGCycleType c)
5774b9ad928SBarry Smith {
578f3fbd535SBarry Smith   PC_MG        *mg        = (PC_MG*)pc->data;
579f3fbd535SBarry Smith   PC_MG_Levels **mglevels = mg->levels;
5804b9ad928SBarry Smith 
5814b9ad928SBarry Smith   PetscFunctionBegin;
582c5eb9154SBarry Smith   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
583ce94432eSBarry Smith   if (!mglevels) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONGSTATE,"Must set MG levels before calling");
584c5eb9154SBarry Smith   PetscValidLogicalCollectiveInt(pc,l,2);
585c51679f6SSatish Balay   PetscValidLogicalCollectiveEnum(pc,c,3);
586f3fbd535SBarry Smith   mglevels[l]->cycles = c;
5874b9ad928SBarry Smith   PetscFunctionReturn(0);
5884b9ad928SBarry Smith }
5894b9ad928SBarry Smith 
5904b9ad928SBarry Smith /*@
59197177400SBarry Smith    PCMGSetRhs - Sets the vector space to be used to store the right-hand side
592fccaa45eSBarry Smith    on a particular level.
5934b9ad928SBarry Smith 
594ad4df100SBarry Smith    Logically Collective on PC and Vec
5954b9ad928SBarry Smith 
5964b9ad928SBarry Smith    Input Parameters:
5974b9ad928SBarry Smith +  pc - the multigrid context
5984b9ad928SBarry Smith .  l  - the level (0 is coarsest) this is to be used for
5994b9ad928SBarry Smith -  c  - the space
6004b9ad928SBarry Smith 
6014b9ad928SBarry Smith    Level: advanced
6024b9ad928SBarry Smith 
603*95452b02SPatrick Sanan    Notes:
604*95452b02SPatrick Sanan     If this is not provided PETSc will automatically generate one.
605fccaa45eSBarry Smith 
606fccaa45eSBarry Smith           You do not need to keep a reference to this vector if you do
607fccaa45eSBarry Smith           not need it PCDestroy() will properly free it.
608fccaa45eSBarry Smith 
6094b9ad928SBarry Smith .keywords: MG, multigrid, set, right-hand-side, rhs, level
6104b9ad928SBarry Smith 
61197177400SBarry Smith .seealso: PCMGSetX(), PCMGSetR()
6124b9ad928SBarry Smith @*/
6137087cfbeSBarry Smith PetscErrorCode  PCMGSetRhs(PC pc,PetscInt l,Vec c)
6144b9ad928SBarry Smith {
615fccaa45eSBarry Smith   PetscErrorCode ierr;
616f3fbd535SBarry Smith   PC_MG          *mg        = (PC_MG*)pc->data;
617f3fbd535SBarry Smith   PC_MG_Levels   **mglevels = mg->levels;
6184b9ad928SBarry Smith 
6194b9ad928SBarry Smith   PetscFunctionBegin;
620c5eb9154SBarry Smith   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
621ce94432eSBarry Smith   if (!mglevels) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONGSTATE,"Must set MG levels before calling");
622ce94432eSBarry Smith   if (l == mglevels[0]->levels-1) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_INCOMP,"Do not set rhs for finest level");
623c3122656SLisandro Dalcin   ierr = PetscObjectReference((PetscObject)c);CHKERRQ(ierr);
6246bf464f9SBarry Smith   ierr = VecDestroy(&mglevels[l]->b);CHKERRQ(ierr);
6252fa5cd67SKarl Rupp 
626f3fbd535SBarry Smith   mglevels[l]->b = c;
6274b9ad928SBarry Smith   PetscFunctionReturn(0);
6284b9ad928SBarry Smith }
6294b9ad928SBarry Smith 
6304b9ad928SBarry Smith /*@
63197177400SBarry Smith    PCMGSetX - Sets the vector space to be used to store the solution on a
632fccaa45eSBarry Smith    particular level.
6334b9ad928SBarry Smith 
634ad4df100SBarry Smith    Logically Collective on PC and Vec
6354b9ad928SBarry Smith 
6364b9ad928SBarry Smith    Input Parameters:
6374b9ad928SBarry Smith +  pc - the multigrid context
638251f4c67SDmitry Karpeev .  l - the level (0 is coarsest) this is to be used for (do not supply the finest level)
6394b9ad928SBarry Smith -  c - the space
6404b9ad928SBarry Smith 
6414b9ad928SBarry Smith    Level: advanced
6424b9ad928SBarry Smith 
643*95452b02SPatrick Sanan    Notes:
644*95452b02SPatrick Sanan     If this is not provided PETSc will automatically generate one.
645fccaa45eSBarry Smith 
646fccaa45eSBarry Smith           You do not need to keep a reference to this vector if you do
647fccaa45eSBarry Smith           not need it PCDestroy() will properly free it.
648fccaa45eSBarry Smith 
6494b9ad928SBarry Smith .keywords: MG, multigrid, set, solution, level
6504b9ad928SBarry Smith 
65197177400SBarry Smith .seealso: PCMGSetRhs(), PCMGSetR()
6524b9ad928SBarry Smith @*/
6537087cfbeSBarry Smith PetscErrorCode  PCMGSetX(PC pc,PetscInt l,Vec c)
6544b9ad928SBarry Smith {
655fccaa45eSBarry Smith   PetscErrorCode ierr;
656f3fbd535SBarry Smith   PC_MG          *mg        = (PC_MG*)pc->data;
657f3fbd535SBarry Smith   PC_MG_Levels   **mglevels = mg->levels;
6584b9ad928SBarry Smith 
6594b9ad928SBarry Smith   PetscFunctionBegin;
660c5eb9154SBarry Smith   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
661ce94432eSBarry Smith   if (!mglevels) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONGSTATE,"Must set MG levels before calling");
662ce94432eSBarry Smith   if (l == mglevels[0]->levels-1) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_INCOMP,"Do not set x for finest level");
663c3122656SLisandro Dalcin   ierr = PetscObjectReference((PetscObject)c);CHKERRQ(ierr);
6646bf464f9SBarry Smith   ierr = VecDestroy(&mglevels[l]->x);CHKERRQ(ierr);
6652fa5cd67SKarl Rupp 
666f3fbd535SBarry Smith   mglevels[l]->x = c;
6674b9ad928SBarry Smith   PetscFunctionReturn(0);
6684b9ad928SBarry Smith }
6694b9ad928SBarry Smith 
6704b9ad928SBarry Smith /*@
67197177400SBarry Smith    PCMGSetR - Sets the vector space to be used to store the residual on a
672fccaa45eSBarry Smith    particular level.
6734b9ad928SBarry Smith 
674ad4df100SBarry Smith    Logically Collective on PC and Vec
6754b9ad928SBarry Smith 
6764b9ad928SBarry Smith    Input Parameters:
6774b9ad928SBarry Smith +  pc - the multigrid context
6784b9ad928SBarry Smith .  l - the level (0 is coarsest) this is to be used for
6794b9ad928SBarry Smith -  c - the space
6804b9ad928SBarry Smith 
6814b9ad928SBarry Smith    Level: advanced
6824b9ad928SBarry Smith 
683*95452b02SPatrick Sanan    Notes:
684*95452b02SPatrick Sanan     If this is not provided PETSc will automatically generate one.
685fccaa45eSBarry Smith 
686fccaa45eSBarry Smith           You do not need to keep a reference to this vector if you do
687fccaa45eSBarry Smith           not need it PCDestroy() will properly free it.
688fccaa45eSBarry Smith 
6894b9ad928SBarry Smith .keywords: MG, multigrid, set, residual, level
6904b9ad928SBarry Smith @*/
6917087cfbeSBarry Smith PetscErrorCode  PCMGSetR(PC pc,PetscInt l,Vec c)
6924b9ad928SBarry Smith {
693fccaa45eSBarry Smith   PetscErrorCode ierr;
694f3fbd535SBarry Smith   PC_MG          *mg        = (PC_MG*)pc->data;
695f3fbd535SBarry Smith   PC_MG_Levels   **mglevels = mg->levels;
6964b9ad928SBarry Smith 
6974b9ad928SBarry Smith   PetscFunctionBegin;
698c5eb9154SBarry Smith   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
699ce94432eSBarry Smith   if (!mglevels) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONGSTATE,"Must set MG levels before calling");
700ce94432eSBarry Smith   if (!l) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_OUTOFRANGE,"Need not set residual vector for coarse grid");
701c3122656SLisandro Dalcin   ierr = PetscObjectReference((PetscObject)c);CHKERRQ(ierr);
7026bf464f9SBarry Smith   ierr = VecDestroy(&mglevels[l]->r);CHKERRQ(ierr);
7032fa5cd67SKarl Rupp 
704f3fbd535SBarry Smith   mglevels[l]->r = c;
7054b9ad928SBarry Smith   PetscFunctionReturn(0);
7064b9ad928SBarry Smith }
707