xref: /petsc/src/ksp/pc/impls/mg/mgfunc.c (revision eab52d2bb9dac9db8361b7da22424a1839b6b115)
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 /*@
175*eab52d2bSLawrence 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 
199*eab52d2bSLawrence 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 /*@
220*eab52d2bSLawrence 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 
236*eab52d2bSLawrence 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:
270*eab52d2bSLawrence 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 
274*eab52d2bSLawrence 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:
306*eab52d2bSLawrence 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 
310*eab52d2bSLawrence 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 /*@
346*eab52d2bSLawrence Mitchell    PCMGSetInjection - Sets the function to be used to inject primal vectors
347*eab52d2bSLawrence Mitchell    from level l to l-1.
348*eab52d2bSLawrence Mitchell 
349*eab52d2bSLawrence Mitchell    Logically Collective on PC and Mat
350*eab52d2bSLawrence Mitchell 
351*eab52d2bSLawrence Mitchell    Input Parameters:
352*eab52d2bSLawrence Mitchell +  pc - the multigrid context
353*eab52d2bSLawrence Mitchell .  l - the level (0 is coarsest) to supply [Do not supply 0]
354*eab52d2bSLawrence Mitchell -  mat - the injection matrix
355*eab52d2bSLawrence Mitchell 
356*eab52d2bSLawrence Mitchell    Level: advanced
357*eab52d2bSLawrence Mitchell 
358*eab52d2bSLawrence Mitchell .keywords: MG, set, multigrid, restriction, injection, level
359*eab52d2bSLawrence Mitchell 
360*eab52d2bSLawrence Mitchell .seealso: PCMGSetRestriction()
361*eab52d2bSLawrence Mitchell @*/
362*eab52d2bSLawrence Mitchell PetscErrorCode  PCMGSetInjection(PC pc,PetscInt l,Mat mat)
363*eab52d2bSLawrence Mitchell {
364*eab52d2bSLawrence Mitchell   PetscErrorCode ierr;
365*eab52d2bSLawrence Mitchell   PC_MG          *mg        = (PC_MG*)pc->data;
366*eab52d2bSLawrence Mitchell   PC_MG_Levels   **mglevels = mg->levels;
367*eab52d2bSLawrence Mitchell 
368*eab52d2bSLawrence Mitchell   PetscFunctionBegin;
369*eab52d2bSLawrence Mitchell   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
370*eab52d2bSLawrence Mitchell   PetscValidHeaderSpecific(mat,MAT_CLASSID,3);
371*eab52d2bSLawrence Mitchell   if (!mglevels) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONGSTATE,"Must set MG levels before calling");
372*eab52d2bSLawrence Mitchell   if (!l) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_OUTOFRANGE,"Do not set restriction routine for coarsest level");
373*eab52d2bSLawrence Mitchell   ierr = PetscObjectReference((PetscObject)mat);CHKERRQ(ierr);
374*eab52d2bSLawrence Mitchell   ierr = MatDestroy(&mglevels[l]->inject);CHKERRQ(ierr);
375*eab52d2bSLawrence Mitchell 
376*eab52d2bSLawrence Mitchell   mglevels[l]->inject = mat;
377*eab52d2bSLawrence Mitchell   PetscFunctionReturn(0);
378*eab52d2bSLawrence Mitchell }
379*eab52d2bSLawrence Mitchell 
380*eab52d2bSLawrence Mitchell /*@
381*eab52d2bSLawrence Mitchell    PCMGGetInjection - Gets the function to be used to inject primal vectors
382*eab52d2bSLawrence Mitchell    from level l to l-1.
383*eab52d2bSLawrence Mitchell 
384*eab52d2bSLawrence Mitchell    Logically Collective on PC and Mat
385*eab52d2bSLawrence Mitchell 
386*eab52d2bSLawrence Mitchell    Input Parameters:
387*eab52d2bSLawrence Mitchell +  pc - the multigrid context
388*eab52d2bSLawrence Mitchell -  l - the level (0 is coarsest) to supply [Do not supply 0]
389*eab52d2bSLawrence Mitchell 
390*eab52d2bSLawrence Mitchell    Output Parameter:
391*eab52d2bSLawrence Mitchell .  mat - the restriction matrix
392*eab52d2bSLawrence Mitchell 
393*eab52d2bSLawrence Mitchell    Level: advanced
394*eab52d2bSLawrence Mitchell 
395*eab52d2bSLawrence Mitchell .keywords: MG, get, multigrid, restriction, injection, level
396*eab52d2bSLawrence Mitchell 
397*eab52d2bSLawrence Mitchell .seealso: PCMGSetInjection(), PCMGetGetRestriction()
398*eab52d2bSLawrence Mitchell @*/
399*eab52d2bSLawrence Mitchell PetscErrorCode  PCMGGetInjection(PC pc,PetscInt l,Mat *mat)
400*eab52d2bSLawrence Mitchell {
401*eab52d2bSLawrence Mitchell   PC_MG          *mg        = (PC_MG*)pc->data;
402*eab52d2bSLawrence Mitchell   PC_MG_Levels   **mglevels = mg->levels;
403*eab52d2bSLawrence Mitchell 
404*eab52d2bSLawrence Mitchell   PetscFunctionBegin;
405*eab52d2bSLawrence Mitchell   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
406*eab52d2bSLawrence Mitchell   if (mat) PetscValidPointer(mat,3);
407*eab52d2bSLawrence Mitchell   if (!mglevels) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONGSTATE,"Must set MG levels before calling");
408*eab52d2bSLawrence 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);
409*eab52d2bSLawrence Mitchell   if (!mglevels[l]->inject) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONGSTATE,"Must call PCMGSetInjection() before calling");
410*eab52d2bSLawrence Mitchell   if (mat) *mat = mglevels[l]->inject;
411*eab52d2bSLawrence Mitchell   PetscFunctionReturn(0);
412*eab52d2bSLawrence Mitchell }
413*eab52d2bSLawrence Mitchell 
414*eab52d2bSLawrence Mitchell /*@
41597177400SBarry Smith    PCMGGetSmoother - Gets the KSP context to be used as smoother for
41697177400SBarry Smith    both pre- and post-smoothing.  Call both PCMGGetSmootherUp() and
41797177400SBarry Smith    PCMGGetSmootherDown() to use different functions for pre- and
4184b9ad928SBarry Smith    post-smoothing.
4194b9ad928SBarry Smith 
4204b9ad928SBarry Smith    Not Collective, KSP returned is parallel if PC is
4214b9ad928SBarry Smith 
4224b9ad928SBarry Smith    Input Parameters:
4234b9ad928SBarry Smith +  pc - the multigrid context
4244b9ad928SBarry Smith -  l - the level (0 is coarsest) to supply
4254b9ad928SBarry Smith 
4264b9ad928SBarry Smith    Ouput Parameters:
4274b9ad928SBarry Smith .  ksp - the smoother
4284b9ad928SBarry Smith 
42957420d5bSBarry Smith    Notes:
43057420d5bSBarry 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.
43157420d5bSBarry Smith    You can also modify smoother options by calling the various KSPSetXXX() options on this ksp. In addition you can call KSPGetPC(ksp,&pc)
43257420d5bSBarry Smith    and modify PC options for the smoother; for example PCSetType(pc,PCSOR); to use SOR smoothing.
43357420d5bSBarry Smith 
4344b9ad928SBarry Smith    Level: advanced
4354b9ad928SBarry Smith 
4364b9ad928SBarry Smith .keywords: MG, get, multigrid, level, smoother, pre-smoother, post-smoother
4374b9ad928SBarry Smith 
43897177400SBarry Smith .seealso: PCMGGetSmootherUp(), PCMGGetSmootherDown()
4394b9ad928SBarry Smith @*/
4407087cfbeSBarry Smith PetscErrorCode  PCMGGetSmoother(PC pc,PetscInt l,KSP *ksp)
4414b9ad928SBarry Smith {
442f3fbd535SBarry Smith   PC_MG        *mg        = (PC_MG*)pc->data;
443f3fbd535SBarry Smith   PC_MG_Levels **mglevels = mg->levels;
4444b9ad928SBarry Smith 
4454b9ad928SBarry Smith   PetscFunctionBegin;
446c5eb9154SBarry Smith   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
447f3fbd535SBarry Smith   *ksp = mglevels[l]->smoothd;
4484b9ad928SBarry Smith   PetscFunctionReturn(0);
4494b9ad928SBarry Smith }
4504b9ad928SBarry Smith 
451f39d8e23SSatish Balay /*@
45297177400SBarry Smith    PCMGGetSmootherUp - Gets the KSP context to be used as smoother after
4534b9ad928SBarry Smith    coarse grid correction (post-smoother).
4544b9ad928SBarry Smith 
4554b9ad928SBarry Smith    Not Collective, KSP returned is parallel if PC is
4564b9ad928SBarry Smith 
4574b9ad928SBarry Smith    Input Parameters:
4584b9ad928SBarry Smith +  pc - the multigrid context
4594b9ad928SBarry Smith -  l  - the level (0 is coarsest) to supply
4604b9ad928SBarry Smith 
4614b9ad928SBarry Smith    Ouput Parameters:
4624b9ad928SBarry Smith .  ksp - the smoother
4634b9ad928SBarry Smith 
4644b9ad928SBarry Smith    Level: advanced
4654b9ad928SBarry Smith 
46689cce641SBarry Smith    Notes: 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 
53689cce641SBarry Smith    Notes: calling this will result in a different pre and post smoother so you may need to
53789cce641SBarry Smith          set options on the post smoother also
53889cce641SBarry Smith 
5394b9ad928SBarry Smith .keywords: MG, multigrid, get, smoother, down, pre-smoother, level
5404b9ad928SBarry Smith 
54197177400SBarry Smith .seealso: PCMGGetSmootherUp(), PCMGGetSmoother()
5424b9ad928SBarry Smith @*/
5437087cfbeSBarry Smith PetscErrorCode  PCMGGetSmootherDown(PC pc,PetscInt l,KSP *ksp)
5444b9ad928SBarry Smith {
545dfbe8321SBarry Smith   PetscErrorCode ierr;
546f3fbd535SBarry Smith   PC_MG          *mg        = (PC_MG*)pc->data;
547f3fbd535SBarry Smith   PC_MG_Levels   **mglevels = mg->levels;
5484b9ad928SBarry Smith 
5494b9ad928SBarry Smith   PetscFunctionBegin;
550c5eb9154SBarry Smith   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
5514b9ad928SBarry Smith   /* make sure smoother up and down are different */
552c5eb9154SBarry Smith   if (l) {
5530298fd71SBarry Smith     ierr = PCMGGetSmootherUp(pc,l,NULL);CHKERRQ(ierr);
554d8148a5aSMatthew Knepley   }
555f3fbd535SBarry Smith   *ksp = mglevels[l]->smoothd;
5564b9ad928SBarry Smith   PetscFunctionReturn(0);
5574b9ad928SBarry Smith }
5584b9ad928SBarry Smith 
5594b9ad928SBarry Smith /*@
560cab31ae5SJed Brown    PCMGSetCycleTypeOnLevel - Sets the type of cycle (aka cycle index) to run on the specified level.
5614b9ad928SBarry Smith 
562ad4df100SBarry Smith    Logically Collective on PC
5634b9ad928SBarry Smith 
5644b9ad928SBarry Smith    Input Parameters:
5654b9ad928SBarry Smith +  pc - the multigrid context
566c1cbb1deSBarry Smith .  l  - the level (0 is coarsest)
567c1cbb1deSBarry Smith -  c  - either PC_MG_CYCLE_V or PC_MG_CYCLE_W
5684b9ad928SBarry Smith 
5694b9ad928SBarry Smith    Level: advanced
5704b9ad928SBarry Smith 
5714b9ad928SBarry Smith .keywords: MG, multigrid, set, cycles, V-cycle, W-cycle, level
5724b9ad928SBarry Smith 
573c1cbb1deSBarry Smith .seealso: PCMGSetCycleType()
5744b9ad928SBarry Smith @*/
575c1cbb1deSBarry Smith PetscErrorCode  PCMGSetCycleTypeOnLevel(PC pc,PetscInt l,PCMGCycleType c)
5764b9ad928SBarry Smith {
577f3fbd535SBarry Smith   PC_MG        *mg        = (PC_MG*)pc->data;
578f3fbd535SBarry Smith   PC_MG_Levels **mglevels = mg->levels;
5794b9ad928SBarry Smith 
5804b9ad928SBarry Smith   PetscFunctionBegin;
581c5eb9154SBarry Smith   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
582ce94432eSBarry Smith   if (!mglevels) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONGSTATE,"Must set MG levels before calling");
583c5eb9154SBarry Smith   PetscValidLogicalCollectiveInt(pc,l,2);
584c51679f6SSatish Balay   PetscValidLogicalCollectiveEnum(pc,c,3);
585f3fbd535SBarry Smith   mglevels[l]->cycles = c;
5864b9ad928SBarry Smith   PetscFunctionReturn(0);
5874b9ad928SBarry Smith }
5884b9ad928SBarry Smith 
5894b9ad928SBarry Smith /*@
59097177400SBarry Smith    PCMGSetRhs - Sets the vector space to be used to store the right-hand side
591fccaa45eSBarry Smith    on a particular level.
5924b9ad928SBarry Smith 
593ad4df100SBarry Smith    Logically Collective on PC and Vec
5944b9ad928SBarry Smith 
5954b9ad928SBarry Smith    Input Parameters:
5964b9ad928SBarry Smith +  pc - the multigrid context
5974b9ad928SBarry Smith .  l  - the level (0 is coarsest) this is to be used for
5984b9ad928SBarry Smith -  c  - the space
5994b9ad928SBarry Smith 
6004b9ad928SBarry Smith    Level: advanced
6014b9ad928SBarry Smith 
602fccaa45eSBarry Smith    Notes: If this is not provided PETSc will automatically generate one.
603fccaa45eSBarry Smith 
604fccaa45eSBarry Smith           You do not need to keep a reference to this vector if you do
605fccaa45eSBarry Smith           not need it PCDestroy() will properly free it.
606fccaa45eSBarry Smith 
6074b9ad928SBarry Smith .keywords: MG, multigrid, set, right-hand-side, rhs, level
6084b9ad928SBarry Smith 
60997177400SBarry Smith .seealso: PCMGSetX(), PCMGSetR()
6104b9ad928SBarry Smith @*/
6117087cfbeSBarry Smith PetscErrorCode  PCMGSetRhs(PC pc,PetscInt l,Vec c)
6124b9ad928SBarry Smith {
613fccaa45eSBarry Smith   PetscErrorCode ierr;
614f3fbd535SBarry Smith   PC_MG          *mg        = (PC_MG*)pc->data;
615f3fbd535SBarry Smith   PC_MG_Levels   **mglevels = mg->levels;
6164b9ad928SBarry Smith 
6174b9ad928SBarry Smith   PetscFunctionBegin;
618c5eb9154SBarry Smith   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
619ce94432eSBarry Smith   if (!mglevels) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONGSTATE,"Must set MG levels before calling");
620ce94432eSBarry Smith   if (l == mglevels[0]->levels-1) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_INCOMP,"Do not set rhs for finest level");
621c3122656SLisandro Dalcin   ierr = PetscObjectReference((PetscObject)c);CHKERRQ(ierr);
6226bf464f9SBarry Smith   ierr = VecDestroy(&mglevels[l]->b);CHKERRQ(ierr);
6232fa5cd67SKarl Rupp 
624f3fbd535SBarry Smith   mglevels[l]->b = c;
6254b9ad928SBarry Smith   PetscFunctionReturn(0);
6264b9ad928SBarry Smith }
6274b9ad928SBarry Smith 
6284b9ad928SBarry Smith /*@
62997177400SBarry Smith    PCMGSetX - Sets the vector space to be used to store the solution on a
630fccaa45eSBarry Smith    particular level.
6314b9ad928SBarry Smith 
632ad4df100SBarry Smith    Logically Collective on PC and Vec
6334b9ad928SBarry Smith 
6344b9ad928SBarry Smith    Input Parameters:
6354b9ad928SBarry Smith +  pc - the multigrid context
636251f4c67SDmitry Karpeev .  l - the level (0 is coarsest) this is to be used for (do not supply the finest level)
6374b9ad928SBarry Smith -  c - the space
6384b9ad928SBarry Smith 
6394b9ad928SBarry Smith    Level: advanced
6404b9ad928SBarry Smith 
641fccaa45eSBarry Smith    Notes: If this is not provided PETSc will automatically generate one.
642fccaa45eSBarry Smith 
643fccaa45eSBarry Smith           You do not need to keep a reference to this vector if you do
644fccaa45eSBarry Smith           not need it PCDestroy() will properly free it.
645fccaa45eSBarry Smith 
6464b9ad928SBarry Smith .keywords: MG, multigrid, set, solution, level
6474b9ad928SBarry Smith 
64897177400SBarry Smith .seealso: PCMGSetRhs(), PCMGSetR()
6494b9ad928SBarry Smith @*/
6507087cfbeSBarry Smith PetscErrorCode  PCMGSetX(PC pc,PetscInt l,Vec c)
6514b9ad928SBarry Smith {
652fccaa45eSBarry Smith   PetscErrorCode ierr;
653f3fbd535SBarry Smith   PC_MG          *mg        = (PC_MG*)pc->data;
654f3fbd535SBarry Smith   PC_MG_Levels   **mglevels = mg->levels;
6554b9ad928SBarry Smith 
6564b9ad928SBarry Smith   PetscFunctionBegin;
657c5eb9154SBarry Smith   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
658ce94432eSBarry Smith   if (!mglevels) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONGSTATE,"Must set MG levels before calling");
659ce94432eSBarry Smith   if (l == mglevels[0]->levels-1) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_INCOMP,"Do not set x for finest level");
660c3122656SLisandro Dalcin   ierr = PetscObjectReference((PetscObject)c);CHKERRQ(ierr);
6616bf464f9SBarry Smith   ierr = VecDestroy(&mglevels[l]->x);CHKERRQ(ierr);
6622fa5cd67SKarl Rupp 
663f3fbd535SBarry Smith   mglevels[l]->x = c;
6644b9ad928SBarry Smith   PetscFunctionReturn(0);
6654b9ad928SBarry Smith }
6664b9ad928SBarry Smith 
6674b9ad928SBarry Smith /*@
66897177400SBarry Smith    PCMGSetR - Sets the vector space to be used to store the residual on a
669fccaa45eSBarry Smith    particular level.
6704b9ad928SBarry Smith 
671ad4df100SBarry Smith    Logically Collective on PC and Vec
6724b9ad928SBarry Smith 
6734b9ad928SBarry Smith    Input Parameters:
6744b9ad928SBarry Smith +  pc - the multigrid context
6754b9ad928SBarry Smith .  l - the level (0 is coarsest) this is to be used for
6764b9ad928SBarry Smith -  c - the space
6774b9ad928SBarry Smith 
6784b9ad928SBarry Smith    Level: advanced
6794b9ad928SBarry Smith 
680fccaa45eSBarry Smith    Notes: If this is not provided PETSc will automatically generate one.
681fccaa45eSBarry Smith 
682fccaa45eSBarry Smith           You do not need to keep a reference to this vector if you do
683fccaa45eSBarry Smith           not need it PCDestroy() will properly free it.
684fccaa45eSBarry Smith 
6854b9ad928SBarry Smith .keywords: MG, multigrid, set, residual, level
6864b9ad928SBarry Smith @*/
6877087cfbeSBarry Smith PetscErrorCode  PCMGSetR(PC pc,PetscInt l,Vec c)
6884b9ad928SBarry Smith {
689fccaa45eSBarry Smith   PetscErrorCode ierr;
690f3fbd535SBarry Smith   PC_MG          *mg        = (PC_MG*)pc->data;
691f3fbd535SBarry Smith   PC_MG_Levels   **mglevels = mg->levels;
6924b9ad928SBarry Smith 
6934b9ad928SBarry Smith   PetscFunctionBegin;
694c5eb9154SBarry Smith   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
695ce94432eSBarry Smith   if (!mglevels) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONGSTATE,"Must set MG levels before calling");
696ce94432eSBarry Smith   if (!l) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_OUTOFRANGE,"Need not set residual vector for coarse grid");
697c3122656SLisandro Dalcin   ierr = PetscObjectReference((PetscObject)c);CHKERRQ(ierr);
6986bf464f9SBarry Smith   ierr = VecDestroy(&mglevels[l]->r);CHKERRQ(ierr);
6992fa5cd67SKarl Rupp 
700f3fbd535SBarry Smith   mglevels[l]->r = c;
7014b9ad928SBarry Smith   PetscFunctionReturn(0);
7024b9ad928SBarry Smith }
703