xref: /petsc/src/ksp/pc/impls/mg/mgfunc.c (revision 48a46eb9bd028bec07ec0f396b1a3abb43f14558)
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 
8d083f849SBarry Smith    Collective on Mat
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 
20db781477SPatrick Sanan .seealso: `PCMGSetResidual()`
214b9ad928SBarry Smith @*/
229371c9d4SSatish Balay PetscErrorCode PCMGResidualDefault(Mat mat, Vec b, Vec x, Vec r) {
234b9ad928SBarry Smith   PetscFunctionBegin;
249566063dSJacob Faibussowitsch   PetscCall(MatResidual(mat, b, x, r));
254b9ad928SBarry Smith   PetscFunctionReturn(0);
264b9ad928SBarry Smith }
274b9ad928SBarry Smith 
28fcb023d4SJed Brown /*@C
29fcb023d4SJed Brown    PCMGResidualTransposeDefault - Default routine to calculate the residual of the transposed linear system
30fcb023d4SJed Brown 
31fcb023d4SJed Brown    Collective on Mat
32fcb023d4SJed Brown 
33fcb023d4SJed Brown    Input Parameters:
34fcb023d4SJed Brown +  mat - the matrix
35fcb023d4SJed Brown .  b   - the right-hand-side
36fcb023d4SJed Brown -  x   - the approximate solution
37fcb023d4SJed Brown 
38fcb023d4SJed Brown    Output Parameter:
39fcb023d4SJed Brown .  r - location to store the residual
40fcb023d4SJed Brown 
41fcb023d4SJed Brown    Level: developer
42fcb023d4SJed Brown 
43db781477SPatrick Sanan .seealso: `PCMGSetResidualTranspose()`
44fcb023d4SJed Brown @*/
459371c9d4SSatish Balay PetscErrorCode PCMGResidualTransposeDefault(Mat mat, Vec b, Vec x, Vec r) {
46fcb023d4SJed Brown   PetscFunctionBegin;
479566063dSJacob Faibussowitsch   PetscCall(MatMultTranspose(mat, x, r));
489566063dSJacob Faibussowitsch   PetscCall(VecAYPX(r, -1.0, b));
49fcb023d4SJed Brown   PetscFunctionReturn(0);
50fcb023d4SJed Brown }
51fcb023d4SJed Brown 
5230b0564aSStefano Zampini /*@C
5330b0564aSStefano Zampini    PCMGMatResidualDefault - Default routine to calculate the residual.
5430b0564aSStefano Zampini 
5530b0564aSStefano Zampini    Collective on Mat
5630b0564aSStefano Zampini 
5730b0564aSStefano Zampini    Input Parameters:
5830b0564aSStefano Zampini +  mat - the matrix
5930b0564aSStefano Zampini .  b   - the right-hand-side
6030b0564aSStefano Zampini -  x   - the approximate solution
6130b0564aSStefano Zampini 
6230b0564aSStefano Zampini    Output Parameter:
6330b0564aSStefano Zampini .  r - location to store the residual
6430b0564aSStefano Zampini 
6530b0564aSStefano Zampini    Level: developer
6630b0564aSStefano Zampini 
67db781477SPatrick Sanan .seealso: `PCMGSetMatResidual()`
6830b0564aSStefano Zampini @*/
699371c9d4SSatish Balay PetscErrorCode PCMGMatResidualDefault(Mat mat, Mat b, Mat x, Mat r) {
7030b0564aSStefano Zampini   PetscFunctionBegin;
719566063dSJacob Faibussowitsch   PetscCall(MatMatMult(mat, x, MAT_REUSE_MATRIX, PETSC_DEFAULT, &r));
729566063dSJacob Faibussowitsch   PetscCall(MatAYPX(r, -1.0, b, UNKNOWN_NONZERO_PATTERN));
7330b0564aSStefano Zampini   PetscFunctionReturn(0);
7430b0564aSStefano Zampini }
7530b0564aSStefano Zampini 
7630b0564aSStefano Zampini /*@C
7730b0564aSStefano Zampini    PCMGMatResidualTransposeDefault - Default routine to calculate the residual of the transposed linear system
7830b0564aSStefano Zampini 
7930b0564aSStefano Zampini    Collective on Mat
8030b0564aSStefano Zampini 
8130b0564aSStefano Zampini    Input Parameters:
8230b0564aSStefano Zampini +  mat - the matrix
8330b0564aSStefano Zampini .  b   - the right-hand-side
8430b0564aSStefano Zampini -  x   - the approximate solution
8530b0564aSStefano Zampini 
8630b0564aSStefano Zampini    Output Parameter:
8730b0564aSStefano Zampini .  r - location to store the residual
8830b0564aSStefano Zampini 
8930b0564aSStefano Zampini    Level: developer
9030b0564aSStefano Zampini 
91db781477SPatrick Sanan .seealso: `PCMGSetMatResidualTranspose()`
9230b0564aSStefano Zampini @*/
939371c9d4SSatish Balay PetscErrorCode PCMGMatResidualTransposeDefault(Mat mat, Mat b, Mat x, Mat r) {
9430b0564aSStefano Zampini   PetscFunctionBegin;
959566063dSJacob Faibussowitsch   PetscCall(MatTransposeMatMult(mat, x, MAT_REUSE_MATRIX, PETSC_DEFAULT, &r));
969566063dSJacob Faibussowitsch   PetscCall(MatAYPX(r, -1.0, b, UNKNOWN_NONZERO_PATTERN));
9730b0564aSStefano Zampini   PetscFunctionReturn(0);
9830b0564aSStefano Zampini }
99f39d8e23SSatish Balay /*@
10097177400SBarry Smith    PCMGGetCoarseSolve - Gets the solver context to be used on the coarse grid.
1014b9ad928SBarry Smith 
1024b9ad928SBarry Smith    Not Collective
1034b9ad928SBarry Smith 
1044b9ad928SBarry Smith    Input Parameter:
1054b9ad928SBarry Smith .  pc - the multigrid context
1064b9ad928SBarry Smith 
1074b9ad928SBarry Smith    Output Parameter:
1084b9ad928SBarry Smith .  ksp - the coarse grid solver context
1094b9ad928SBarry Smith 
1104b9ad928SBarry Smith    Level: advanced
1114b9ad928SBarry Smith 
112db781477SPatrick Sanan .seealso: `PCMGGetSmootherUp()`, `PCMGGetSmootherDown()`, `PCMGGetSmoother()`
1134b9ad928SBarry Smith @*/
1149371c9d4SSatish Balay PetscErrorCode PCMGGetCoarseSolve(PC pc, KSP *ksp) {
115f3fbd535SBarry Smith   PC_MG         *mg       = (PC_MG *)pc->data;
116f3fbd535SBarry Smith   PC_MG_Levels **mglevels = mg->levels;
1174b9ad928SBarry Smith 
1184b9ad928SBarry Smith   PetscFunctionBegin;
119c5eb9154SBarry Smith   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
120f3fbd535SBarry Smith   *ksp = mglevels[0]->smoothd;
1214b9ad928SBarry Smith   PetscFunctionReturn(0);
1224b9ad928SBarry Smith }
1234b9ad928SBarry Smith 
1244b9ad928SBarry Smith /*@C
12597177400SBarry Smith    PCMGSetResidual - Sets the function to be used to calculate the residual
1264b9ad928SBarry Smith    on the lth level.
1274b9ad928SBarry Smith 
128d083f849SBarry Smith    Logically Collective on PC
1294b9ad928SBarry Smith 
1304b9ad928SBarry Smith    Input Parameters:
1314b9ad928SBarry Smith +  pc       - the multigrid context
1324b9ad928SBarry Smith .  l        - the level (0 is coarsest) to supply
133157726a2SBarry Smith .  residual - function used to form residual, if none is provided the previously provide one is used, if no
134d0e4de75SBarry Smith               previous one were provided then a default is used
1354b9ad928SBarry Smith -  mat      - matrix associated with residual
1364b9ad928SBarry Smith 
1374b9ad928SBarry Smith    Level: advanced
1384b9ad928SBarry Smith 
139db781477SPatrick Sanan .seealso: `PCMGResidualDefault()`
1404b9ad928SBarry Smith @*/
1419371c9d4SSatish Balay PetscErrorCode PCMGSetResidual(PC pc, PetscInt l, PetscErrorCode (*residual)(Mat, Vec, Vec, Vec), Mat mat) {
142f3fbd535SBarry Smith   PC_MG         *mg       = (PC_MG *)pc->data;
143f3fbd535SBarry Smith   PC_MG_Levels **mglevels = mg->levels;
1444b9ad928SBarry Smith 
1454b9ad928SBarry Smith   PetscFunctionBegin;
146c5eb9154SBarry Smith   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
14728b400f6SJacob Faibussowitsch   PetscCheck(mglevels, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_WRONGSTATE, "Must set MG levels before calling");
1482fa5cd67SKarl Rupp   if (residual) mglevels[l]->residual = residual;
14954b2cd4bSJed Brown   if (!mglevels[l]->residual) mglevels[l]->residual = PCMGResidualDefault;
15030b0564aSStefano Zampini   mglevels[l]->matresidual = PCMGMatResidualDefault;
1519566063dSJacob Faibussowitsch   if (mat) PetscCall(PetscObjectReference((PetscObject)mat));
1529566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&mglevels[l]->A));
153f3fbd535SBarry Smith   mglevels[l]->A = mat;
1544b9ad928SBarry Smith   PetscFunctionReturn(0);
1554b9ad928SBarry Smith }
1564b9ad928SBarry Smith 
157fcb023d4SJed Brown /*@C
158fcb023d4SJed Brown    PCMGSetResidualTranspose - Sets the function to be used to calculate the residual of the transposed linear system
159fcb023d4SJed Brown    on the lth level.
160fcb023d4SJed Brown 
161fcb023d4SJed Brown    Logically Collective on PC
162fcb023d4SJed Brown 
163fcb023d4SJed Brown    Input Parameters:
164fcb023d4SJed Brown +  pc        - the multigrid context
165fcb023d4SJed Brown .  l         - the level (0 is coarsest) to supply
166fcb023d4SJed Brown .  residualt - function used to form transpose of residual, if none is provided the previously provide one is used, if no
167fcb023d4SJed Brown                previous one were provided then a default is used
168fcb023d4SJed Brown -  mat       - matrix associated with residual
169fcb023d4SJed Brown 
170fcb023d4SJed Brown    Level: advanced
171fcb023d4SJed Brown 
172db781477SPatrick Sanan .seealso: `PCMGResidualTransposeDefault()`
173fcb023d4SJed Brown @*/
1749371c9d4SSatish Balay PetscErrorCode PCMGSetResidualTranspose(PC pc, PetscInt l, PetscErrorCode (*residualt)(Mat, Vec, Vec, Vec), Mat mat) {
175fcb023d4SJed Brown   PC_MG         *mg       = (PC_MG *)pc->data;
176fcb023d4SJed Brown   PC_MG_Levels **mglevels = mg->levels;
177fcb023d4SJed Brown 
178fcb023d4SJed Brown   PetscFunctionBegin;
179fcb023d4SJed Brown   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
18028b400f6SJacob Faibussowitsch   PetscCheck(mglevels, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_WRONGSTATE, "Must set MG levels before calling");
181fcb023d4SJed Brown   if (residualt) mglevels[l]->residualtranspose = residualt;
182fcb023d4SJed Brown   if (!mglevels[l]->residualtranspose) mglevels[l]->residualtranspose = PCMGResidualTransposeDefault;
18330b0564aSStefano Zampini   mglevels[l]->matresidualtranspose = PCMGMatResidualTransposeDefault;
1849566063dSJacob Faibussowitsch   if (mat) PetscCall(PetscObjectReference((PetscObject)mat));
1859566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&mglevels[l]->A));
186fcb023d4SJed Brown   mglevels[l]->A = mat;
187fcb023d4SJed Brown   PetscFunctionReturn(0);
188fcb023d4SJed Brown }
189fcb023d4SJed Brown 
1904b9ad928SBarry Smith /*@
191aea2a34eSBarry Smith    PCMGSetInterpolation - Sets the function to be used to calculate the
192bf5b2e24SBarry Smith    interpolation from l-1 to the lth level
1934b9ad928SBarry Smith 
194d083f849SBarry Smith    Logically Collective on PC
1954b9ad928SBarry Smith 
1964b9ad928SBarry Smith    Input Parameters:
1974b9ad928SBarry Smith +  pc  - the multigrid context
1984b9ad928SBarry Smith .  mat - the interpolation operator
199bf5b2e24SBarry Smith -  l   - the level (0 is coarsest) to supply [do not supply 0]
2004b9ad928SBarry Smith 
2014b9ad928SBarry Smith    Level: advanced
2024b9ad928SBarry Smith 
2034b9ad928SBarry Smith    Notes:
2044b9ad928SBarry Smith           Usually this is the same matrix used also to set the restriction
2054b9ad928SBarry Smith     for the same level.
2064b9ad928SBarry Smith 
2074b9ad928SBarry Smith           One can pass in the interpolation matrix or its transpose; PETSc figures
2084b9ad928SBarry Smith     out from the matrix size which one it is.
2094b9ad928SBarry Smith 
210db781477SPatrick Sanan .seealso: `PCMGSetRestriction()`
2114b9ad928SBarry Smith @*/
2129371c9d4SSatish Balay PetscErrorCode PCMGSetInterpolation(PC pc, PetscInt l, Mat mat) {
213f3fbd535SBarry Smith   PC_MG         *mg       = (PC_MG *)pc->data;
214f3fbd535SBarry Smith   PC_MG_Levels **mglevels = mg->levels;
2154b9ad928SBarry Smith 
2164b9ad928SBarry Smith   PetscFunctionBegin;
217c5eb9154SBarry Smith   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
21828b400f6SJacob Faibussowitsch   PetscCheck(mglevels, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_WRONGSTATE, "Must set MG levels before calling");
21928b400f6SJacob Faibussowitsch   PetscCheck(l, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_OUTOFRANGE, "Do not set interpolation routine for coarsest level");
2209566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)mat));
2219566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&mglevels[l]->interpolate));
2222fa5cd67SKarl Rupp 
223f3fbd535SBarry Smith   mglevels[l]->interpolate = mat;
2244b9ad928SBarry Smith   PetscFunctionReturn(0);
2254b9ad928SBarry Smith }
2264b9ad928SBarry Smith 
2278a2c336bSFande Kong /*@
22895750439SFande Kong    PCMGSetOperators - Sets operator and preconditioning matrix for lth level
2298a2c336bSFande Kong 
230d083f849SBarry Smith    Logically Collective on PC
2318a2c336bSFande Kong 
2328a2c336bSFande Kong    Input Parameters:
2338a2c336bSFande Kong +  pc  - the multigrid context
2348a2c336bSFande Kong .  Amat - the operator
2358a2c336bSFande Kong .  pmat - the preconditioning operator
23695750439SFande Kong -  l   - the level (0 is the coarsest) to supply
2378a2c336bSFande Kong 
2388a2c336bSFande Kong    Level: advanced
2398a2c336bSFande Kong 
2408a2c336bSFande Kong .keywords:  multigrid, set, interpolate, level
2418a2c336bSFande Kong 
242db781477SPatrick Sanan .seealso: `PCMGSetRestriction()`, `PCMGSetInterpolation()`
2438a2c336bSFande Kong @*/
2449371c9d4SSatish Balay PetscErrorCode PCMGSetOperators(PC pc, PetscInt l, Mat Amat, Mat Pmat) {
245360ee056SFande Kong   PC_MG         *mg       = (PC_MG *)pc->data;
246360ee056SFande Kong   PC_MG_Levels **mglevels = mg->levels;
247360ee056SFande Kong 
248360ee056SFande Kong   PetscFunctionBegin;
249360ee056SFande Kong   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
2508a2c336bSFande Kong   PetscValidHeaderSpecific(Amat, MAT_CLASSID, 3);
2518a2c336bSFande Kong   PetscValidHeaderSpecific(Pmat, MAT_CLASSID, 4);
25228b400f6SJacob Faibussowitsch   PetscCheck(mglevels, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_WRONGSTATE, "Must set MG levels before calling");
2539566063dSJacob Faibussowitsch   PetscCall(KSPSetOperators(mglevels[l]->smoothd, Amat, Pmat));
254360ee056SFande Kong   PetscFunctionReturn(0);
255360ee056SFande Kong }
256360ee056SFande Kong 
257c88c5224SJed Brown /*@
258c88c5224SJed Brown    PCMGGetInterpolation - Gets the function to be used to calculate the
259c88c5224SJed Brown    interpolation from l-1 to the lth level
260c88c5224SJed Brown 
261c88c5224SJed Brown    Logically Collective on PC
262c88c5224SJed Brown 
263c88c5224SJed Brown    Input Parameters:
264c88c5224SJed Brown +  pc - the multigrid context
265c88c5224SJed Brown -  l - the level (0 is coarsest) to supply [Do not supply 0]
266c88c5224SJed Brown 
267c88c5224SJed Brown    Output Parameter:
2683ad4599aSBarry Smith .  mat - the interpolation matrix, can be NULL
269c88c5224SJed Brown 
270c88c5224SJed Brown    Level: advanced
271c88c5224SJed Brown 
272db781477SPatrick Sanan .seealso: `PCMGGetRestriction()`, `PCMGSetInterpolation()`, `PCMGGetRScale()`
273c88c5224SJed Brown @*/
2749371c9d4SSatish Balay PetscErrorCode PCMGGetInterpolation(PC pc, PetscInt l, Mat *mat) {
275c88c5224SJed Brown   PC_MG         *mg       = (PC_MG *)pc->data;
276c88c5224SJed Brown   PC_MG_Levels **mglevels = mg->levels;
277c88c5224SJed Brown 
278c88c5224SJed Brown   PetscFunctionBegin;
279c88c5224SJed Brown   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
2803ad4599aSBarry Smith   if (mat) PetscValidPointer(mat, 3);
28128b400f6SJacob Faibussowitsch   PetscCheck(mglevels, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_WRONGSTATE, "Must set MG levels before calling");
2822472a847SBarry Smith   PetscCheck(l > 0 && l < mg->nlevels, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_OUTOFRANGE, "Level %" PetscInt_FMT " must be in range {1,...,%" PetscInt_FMT "}", l, mg->nlevels - 1);
283*48a46eb9SPierre Jolivet   if (!mglevels[l]->interpolate && mglevels[l]->restrct) PetscCall(PCMGSetInterpolation(pc, l, mglevels[l]->restrct));
2843ad4599aSBarry Smith   if (mat) *mat = mglevels[l]->interpolate;
285c88c5224SJed Brown   PetscFunctionReturn(0);
286c88c5224SJed Brown }
287c88c5224SJed Brown 
2888a2c336bSFande Kong /*@
289eab52d2bSLawrence Mitchell    PCMGSetRestriction - Sets the function to be used to restrict dual vectors
2904b9ad928SBarry Smith    from level l to l-1.
2914b9ad928SBarry Smith 
292d083f849SBarry Smith    Logically Collective on PC
2934b9ad928SBarry Smith 
2944b9ad928SBarry Smith    Input Parameters:
2954b9ad928SBarry Smith +  pc - the multigrid context
296c88c5224SJed Brown .  l - the level (0 is coarsest) to supply [Do not supply 0]
297c88c5224SJed Brown -  mat - the restriction matrix
2984b9ad928SBarry Smith 
2994b9ad928SBarry Smith    Level: advanced
3004b9ad928SBarry Smith 
3014b9ad928SBarry Smith    Notes:
3024b9ad928SBarry Smith           Usually this is the same matrix used also to set the interpolation
3034b9ad928SBarry Smith     for the same level.
3044b9ad928SBarry Smith 
3054b9ad928SBarry Smith           One can pass in the interpolation matrix or its transpose; PETSc figures
3064b9ad928SBarry Smith     out from the matrix size which one it is.
3074b9ad928SBarry Smith 
308aea2a34eSBarry Smith          If you do not set this, the transpose of the Mat set with PCMGSetInterpolation()
309fccaa45eSBarry Smith     is used.
310fccaa45eSBarry Smith 
311db781477SPatrick Sanan .seealso: `PCMGSetInterpolation()`
3124b9ad928SBarry Smith @*/
3139371c9d4SSatish Balay PetscErrorCode PCMGSetRestriction(PC pc, PetscInt l, Mat mat) {
314f3fbd535SBarry Smith   PC_MG         *mg       = (PC_MG *)pc->data;
315f3fbd535SBarry Smith   PC_MG_Levels **mglevels = mg->levels;
3164b9ad928SBarry Smith 
3174b9ad928SBarry Smith   PetscFunctionBegin;
318c5eb9154SBarry Smith   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
319c88c5224SJed Brown   PetscValidHeaderSpecific(mat, MAT_CLASSID, 3);
32028b400f6SJacob Faibussowitsch   PetscCheck(mglevels, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_WRONGSTATE, "Must set MG levels before calling");
32128b400f6SJacob Faibussowitsch   PetscCheck(l, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_OUTOFRANGE, "Do not set restriction routine for coarsest level");
3229566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)mat));
3239566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&mglevels[l]->restrct));
3242fa5cd67SKarl Rupp 
325f3fbd535SBarry Smith   mglevels[l]->restrct = mat;
3264b9ad928SBarry Smith   PetscFunctionReturn(0);
3274b9ad928SBarry Smith }
3284b9ad928SBarry Smith 
329c88c5224SJed Brown /*@
330eab52d2bSLawrence Mitchell    PCMGGetRestriction - Gets the function to be used to restrict dual vectors
331c88c5224SJed Brown    from level l to l-1.
332c88c5224SJed Brown 
333d083f849SBarry Smith    Logically Collective on PC
334c88c5224SJed Brown 
335c88c5224SJed Brown    Input Parameters:
336c88c5224SJed Brown +  pc - the multigrid context
337c88c5224SJed Brown -  l - the level (0 is coarsest) to supply [Do not supply 0]
338c88c5224SJed Brown 
339c88c5224SJed Brown    Output Parameter:
340c88c5224SJed Brown .  mat - the restriction matrix
341c88c5224SJed Brown 
342c88c5224SJed Brown    Level: advanced
343c88c5224SJed Brown 
344db781477SPatrick Sanan .seealso: `PCMGGetInterpolation()`, `PCMGSetRestriction()`, `PCMGGetRScale()`, `PCMGGetInjection()`
345c88c5224SJed Brown @*/
3469371c9d4SSatish Balay PetscErrorCode PCMGGetRestriction(PC pc, PetscInt l, Mat *mat) {
347c88c5224SJed Brown   PC_MG         *mg       = (PC_MG *)pc->data;
348c88c5224SJed Brown   PC_MG_Levels **mglevels = mg->levels;
349c88c5224SJed Brown 
350c88c5224SJed Brown   PetscFunctionBegin;
351c88c5224SJed Brown   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
3523ad4599aSBarry Smith   if (mat) PetscValidPointer(mat, 3);
35328b400f6SJacob Faibussowitsch   PetscCheck(mglevels, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_WRONGSTATE, "Must set MG levels before calling");
3542472a847SBarry Smith   PetscCheck(l > 0 && l < mg->nlevels, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_OUTOFRANGE, "Level %" PetscInt_FMT " must be in range {1,...,%" PetscInt_FMT "}", l, mg->nlevels - 1);
355*48a46eb9SPierre Jolivet   if (!mglevels[l]->restrct && mglevels[l]->interpolate) PetscCall(PCMGSetRestriction(pc, l, mglevels[l]->interpolate));
3563ad4599aSBarry Smith   if (mat) *mat = mglevels[l]->restrct;
357c88c5224SJed Brown   PetscFunctionReturn(0);
358c88c5224SJed Brown }
359c88c5224SJed Brown 
36073250ac0SBarry Smith /*@
36173250ac0SBarry Smith    PCMGSetRScale - Sets the pointwise scaling for the restriction operator from level l to l-1.
36273250ac0SBarry Smith 
363d083f849SBarry Smith    Logically Collective on PC
364c88c5224SJed Brown 
365c88c5224SJed Brown    Input Parameters:
366c88c5224SJed Brown +  pc - the multigrid context
367c88c5224SJed Brown -  l - the level (0 is coarsest) to supply [Do not supply 0]
368c88c5224SJed Brown .  rscale - the scaling
369c88c5224SJed Brown 
370c88c5224SJed Brown    Level: advanced
371c88c5224SJed Brown 
372c88c5224SJed Brown    Notes:
373eab52d2bSLawrence 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.
374c88c5224SJed Brown 
375db781477SPatrick Sanan .seealso: `PCMGSetInterpolation()`, `PCMGSetRestriction()`, `PCMGGetRScale()`, `PCMGSetInjection()`
376c88c5224SJed Brown @*/
3779371c9d4SSatish Balay PetscErrorCode PCMGSetRScale(PC pc, PetscInt l, Vec rscale) {
378c88c5224SJed Brown   PC_MG         *mg       = (PC_MG *)pc->data;
379c88c5224SJed Brown   PC_MG_Levels **mglevels = mg->levels;
380c88c5224SJed Brown 
381c88c5224SJed Brown   PetscFunctionBegin;
382c88c5224SJed Brown   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
38328b400f6SJacob Faibussowitsch   PetscCheck(mglevels, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_WRONGSTATE, "Must set MG levels before calling");
3842472a847SBarry Smith   PetscCheck(l > 0 && l < mg->nlevels, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_OUTOFRANGE, "Level %" PetscInt_FMT " must be in range {1,...,%" PetscInt_FMT "}", l, mg->nlevels - 1);
3859566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)rscale));
3869566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&mglevels[l]->rscale));
3872fa5cd67SKarl Rupp 
388c88c5224SJed Brown   mglevels[l]->rscale = rscale;
389c88c5224SJed Brown   PetscFunctionReturn(0);
390c88c5224SJed Brown }
391c88c5224SJed Brown 
392c88c5224SJed Brown /*@
393c88c5224SJed Brown    PCMGGetRScale - Gets the pointwise scaling for the restriction operator from level l to l-1.
394c88c5224SJed Brown 
395c88c5224SJed Brown    Collective on PC
39673250ac0SBarry Smith 
39773250ac0SBarry Smith    Input Parameters:
39873250ac0SBarry Smith +  pc - the multigrid context
39973250ac0SBarry Smith .  rscale - the scaling
40073250ac0SBarry Smith -  l - the level (0 is coarsest) to supply [Do not supply 0]
40173250ac0SBarry Smith 
40273250ac0SBarry Smith    Level: advanced
40373250ac0SBarry Smith 
40473250ac0SBarry Smith    Notes:
405eab52d2bSLawrence 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.
40673250ac0SBarry Smith 
407db781477SPatrick Sanan .seealso: `PCMGSetInterpolation()`, `PCMGGetRestriction()`, `PCMGGetInjection()`
40873250ac0SBarry Smith @*/
4099371c9d4SSatish Balay PetscErrorCode PCMGGetRScale(PC pc, PetscInt l, Vec *rscale) {
41073250ac0SBarry Smith   PC_MG         *mg       = (PC_MG *)pc->data;
41173250ac0SBarry Smith   PC_MG_Levels **mglevels = mg->levels;
41273250ac0SBarry Smith 
41373250ac0SBarry Smith   PetscFunctionBegin;
41473250ac0SBarry Smith   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
41528b400f6SJacob Faibussowitsch   PetscCheck(mglevels, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_WRONGSTATE, "Must set MG levels before calling");
4162472a847SBarry Smith   PetscCheck(l > 0 && l < mg->nlevels, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_OUTOFRANGE, "Level %" PetscInt_FMT " must be in range {1,...,%" PetscInt_FMT "}", l, mg->nlevels - 1);
417c88c5224SJed Brown   if (!mglevels[l]->rscale) {
418c88c5224SJed Brown     Mat      R;
419c88c5224SJed Brown     Vec      X, Y, coarse, fine;
420c88c5224SJed Brown     PetscInt M, N;
4219566063dSJacob Faibussowitsch     PetscCall(PCMGGetRestriction(pc, l, &R));
4229566063dSJacob Faibussowitsch     PetscCall(MatCreateVecs(R, &X, &Y));
4239566063dSJacob Faibussowitsch     PetscCall(MatGetSize(R, &M, &N));
4242fa5cd67SKarl Rupp     if (M < N) {
4252fa5cd67SKarl Rupp       fine   = X;
4262fa5cd67SKarl Rupp       coarse = Y;
4272fa5cd67SKarl Rupp     } else if (N < M) {
4289371c9d4SSatish Balay       fine   = Y;
4299371c9d4SSatish Balay       coarse = X;
430ce94432eSBarry Smith     } else SETERRQ(PetscObjectComm((PetscObject)R), PETSC_ERR_SUP, "Restriction matrix is square, cannot determine which Vec is coarser");
4319566063dSJacob Faibussowitsch     PetscCall(VecSet(fine, 1.));
4329566063dSJacob Faibussowitsch     PetscCall(MatRestrict(R, fine, coarse));
4339566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&fine));
4349566063dSJacob Faibussowitsch     PetscCall(VecReciprocal(coarse));
435c88c5224SJed Brown     mglevels[l]->rscale = coarse;
436c88c5224SJed Brown   }
437c88c5224SJed Brown   *rscale = mglevels[l]->rscale;
43873250ac0SBarry Smith   PetscFunctionReturn(0);
43973250ac0SBarry Smith }
44073250ac0SBarry Smith 
441f39d8e23SSatish Balay /*@
442eab52d2bSLawrence Mitchell    PCMGSetInjection - Sets the function to be used to inject primal vectors
443eab52d2bSLawrence Mitchell    from level l to l-1.
444eab52d2bSLawrence Mitchell 
445d083f849SBarry Smith    Logically Collective on PC
446eab52d2bSLawrence Mitchell 
447eab52d2bSLawrence Mitchell    Input Parameters:
448eab52d2bSLawrence Mitchell +  pc - the multigrid context
449eab52d2bSLawrence Mitchell .  l - the level (0 is coarsest) to supply [Do not supply 0]
450eab52d2bSLawrence Mitchell -  mat - the injection matrix
451eab52d2bSLawrence Mitchell 
452eab52d2bSLawrence Mitchell    Level: advanced
453eab52d2bSLawrence Mitchell 
454db781477SPatrick Sanan .seealso: `PCMGSetRestriction()`
455eab52d2bSLawrence Mitchell @*/
4569371c9d4SSatish Balay PetscErrorCode PCMGSetInjection(PC pc, PetscInt l, Mat mat) {
457eab52d2bSLawrence Mitchell   PC_MG         *mg       = (PC_MG *)pc->data;
458eab52d2bSLawrence Mitchell   PC_MG_Levels **mglevels = mg->levels;
459eab52d2bSLawrence Mitchell 
460eab52d2bSLawrence Mitchell   PetscFunctionBegin;
461eab52d2bSLawrence Mitchell   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
462eab52d2bSLawrence Mitchell   PetscValidHeaderSpecific(mat, MAT_CLASSID, 3);
46328b400f6SJacob Faibussowitsch   PetscCheck(mglevels, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_WRONGSTATE, "Must set MG levels before calling");
46428b400f6SJacob Faibussowitsch   PetscCheck(l, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_OUTOFRANGE, "Do not set restriction routine for coarsest level");
4659566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)mat));
4669566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&mglevels[l]->inject));
467eab52d2bSLawrence Mitchell 
468eab52d2bSLawrence Mitchell   mglevels[l]->inject = mat;
469eab52d2bSLawrence Mitchell   PetscFunctionReturn(0);
470eab52d2bSLawrence Mitchell }
471eab52d2bSLawrence Mitchell 
472eab52d2bSLawrence Mitchell /*@
473eab52d2bSLawrence Mitchell    PCMGGetInjection - Gets the function to be used to inject primal vectors
474eab52d2bSLawrence Mitchell    from level l to l-1.
475eab52d2bSLawrence Mitchell 
476d083f849SBarry Smith    Logically Collective on PC
477eab52d2bSLawrence Mitchell 
478eab52d2bSLawrence Mitchell    Input Parameters:
479eab52d2bSLawrence Mitchell +  pc - the multigrid context
480eab52d2bSLawrence Mitchell -  l - the level (0 is coarsest) to supply [Do not supply 0]
481eab52d2bSLawrence Mitchell 
482eab52d2bSLawrence Mitchell    Output Parameter:
48399a38656SLawrence Mitchell .  mat - the restriction matrix (may be NULL if no injection is available).
484eab52d2bSLawrence Mitchell 
485eab52d2bSLawrence Mitchell    Level: advanced
486eab52d2bSLawrence Mitchell 
487db781477SPatrick Sanan .seealso: `PCMGSetInjection()`, `PCMGetGetRestriction()`
488eab52d2bSLawrence Mitchell @*/
4899371c9d4SSatish Balay PetscErrorCode PCMGGetInjection(PC pc, PetscInt l, Mat *mat) {
490eab52d2bSLawrence Mitchell   PC_MG         *mg       = (PC_MG *)pc->data;
491eab52d2bSLawrence Mitchell   PC_MG_Levels **mglevels = mg->levels;
492eab52d2bSLawrence Mitchell 
493eab52d2bSLawrence Mitchell   PetscFunctionBegin;
494eab52d2bSLawrence Mitchell   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
495eab52d2bSLawrence Mitchell   if (mat) PetscValidPointer(mat, 3);
49628b400f6SJacob Faibussowitsch   PetscCheck(mglevels, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_WRONGSTATE, "Must set MG levels before calling");
4972472a847SBarry Smith   PetscCheck(l > 0 && l < mg->nlevels, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_OUTOFRANGE, "Level %" PetscInt_FMT " must be in range {1,...,%" PetscInt_FMT "}", l, mg->nlevels - 1);
498eab52d2bSLawrence Mitchell   if (mat) *mat = mglevels[l]->inject;
499eab52d2bSLawrence Mitchell   PetscFunctionReturn(0);
500eab52d2bSLawrence Mitchell }
501eab52d2bSLawrence Mitchell 
502eab52d2bSLawrence Mitchell /*@
50397177400SBarry Smith    PCMGGetSmoother - Gets the KSP context to be used as smoother for
50497177400SBarry Smith    both pre- and post-smoothing.  Call both PCMGGetSmootherUp() and
50597177400SBarry Smith    PCMGGetSmootherDown() to use different functions for pre- and
5064b9ad928SBarry Smith    post-smoothing.
5074b9ad928SBarry Smith 
5084b9ad928SBarry Smith    Not Collective, KSP returned is parallel if PC is
5094b9ad928SBarry Smith 
5104b9ad928SBarry Smith    Input Parameters:
5114b9ad928SBarry Smith +  pc - the multigrid context
5124b9ad928SBarry Smith -  l - the level (0 is coarsest) to supply
5134b9ad928SBarry Smith 
51401d2d390SJose E. Roman    Output Parameter:
5154b9ad928SBarry Smith .  ksp - the smoother
5164b9ad928SBarry Smith 
51757420d5bSBarry Smith    Notes:
51857420d5bSBarry 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.
51957420d5bSBarry Smith    You can also modify smoother options by calling the various KSPSetXXX() options on this ksp. In addition you can call KSPGetPC(ksp,&pc)
52057420d5bSBarry Smith    and modify PC options for the smoother; for example PCSetType(pc,PCSOR); to use SOR smoothing.
52157420d5bSBarry Smith 
5224b9ad928SBarry Smith    Level: advanced
5234b9ad928SBarry Smith 
524db781477SPatrick Sanan .seealso: `PCMGGetSmootherUp()`, `PCMGGetSmootherDown()`, `PCMGGetCoarseSolve()`
5254b9ad928SBarry Smith @*/
5269371c9d4SSatish Balay PetscErrorCode PCMGGetSmoother(PC pc, PetscInt l, KSP *ksp) {
527f3fbd535SBarry Smith   PC_MG         *mg       = (PC_MG *)pc->data;
528f3fbd535SBarry Smith   PC_MG_Levels **mglevels = mg->levels;
5294b9ad928SBarry Smith 
5304b9ad928SBarry Smith   PetscFunctionBegin;
531c5eb9154SBarry Smith   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
532f3fbd535SBarry Smith   *ksp = mglevels[l]->smoothd;
5334b9ad928SBarry Smith   PetscFunctionReturn(0);
5344b9ad928SBarry Smith }
5354b9ad928SBarry Smith 
536f39d8e23SSatish Balay /*@
53797177400SBarry Smith    PCMGGetSmootherUp - Gets the KSP context to be used as smoother after
5384b9ad928SBarry Smith    coarse grid correction (post-smoother).
5394b9ad928SBarry Smith 
5404b9ad928SBarry Smith    Not Collective, KSP returned is parallel if PC is
5414b9ad928SBarry Smith 
5424b9ad928SBarry Smith    Input Parameters:
5434b9ad928SBarry Smith +  pc - the multigrid context
5444b9ad928SBarry Smith -  l  - the level (0 is coarsest) to supply
5454b9ad928SBarry Smith 
54601d2d390SJose E. Roman    Output Parameter:
5474b9ad928SBarry Smith .  ksp - the smoother
5484b9ad928SBarry Smith 
5494b9ad928SBarry Smith    Level: advanced
5504b9ad928SBarry Smith 
55195452b02SPatrick Sanan    Notes:
55295452b02SPatrick Sanan     calling this will result in a different pre and post smoother so you may need to
55389cce641SBarry Smith          set options on the pre smoother also
55489cce641SBarry Smith 
555db781477SPatrick Sanan .seealso: `PCMGGetSmootherUp()`, `PCMGGetSmootherDown()`
5564b9ad928SBarry Smith @*/
5579371c9d4SSatish Balay PetscErrorCode PCMGGetSmootherUp(PC pc, PetscInt l, KSP *ksp) {
558f3fbd535SBarry Smith   PC_MG         *mg       = (PC_MG *)pc->data;
559f3fbd535SBarry Smith   PC_MG_Levels **mglevels = mg->levels;
560f69a0ea3SMatthew Knepley   const char    *prefix;
5614b9ad928SBarry Smith   MPI_Comm       comm;
5624b9ad928SBarry Smith 
5634b9ad928SBarry Smith   PetscFunctionBegin;
564c5eb9154SBarry Smith   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
5654b9ad928SBarry Smith   /*
5664b9ad928SBarry Smith      This is called only if user wants a different pre-smoother from post.
5674b9ad928SBarry Smith      Thus we check if a different one has already been allocated,
5684b9ad928SBarry Smith      if not we allocate it.
5694b9ad928SBarry Smith   */
57028b400f6SJacob Faibussowitsch   PetscCheck(l, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_OUTOFRANGE, "There is no such thing as a up smoother on the coarse grid");
571f3fbd535SBarry Smith   if (mglevels[l]->smoothu == mglevels[l]->smoothd) {
57219fd82e9SBarry Smith     KSPType     ksptype;
57319fd82e9SBarry Smith     PCType      pctype;
574336babb1SJed Brown     PC          ipc;
575336babb1SJed Brown     PetscReal   rtol, abstol, dtol;
576336babb1SJed Brown     PetscInt    maxits;
577336babb1SJed Brown     KSPNormType normtype;
5789566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetComm((PetscObject)mglevels[l]->smoothd, &comm));
5799566063dSJacob Faibussowitsch     PetscCall(KSPGetOptionsPrefix(mglevels[l]->smoothd, &prefix));
5809566063dSJacob Faibussowitsch     PetscCall(KSPGetTolerances(mglevels[l]->smoothd, &rtol, &abstol, &dtol, &maxits));
5819566063dSJacob Faibussowitsch     PetscCall(KSPGetType(mglevels[l]->smoothd, &ksptype));
5829566063dSJacob Faibussowitsch     PetscCall(KSPGetNormType(mglevels[l]->smoothd, &normtype));
5839566063dSJacob Faibussowitsch     PetscCall(KSPGetPC(mglevels[l]->smoothd, &ipc));
5849566063dSJacob Faibussowitsch     PetscCall(PCGetType(ipc, &pctype));
585336babb1SJed Brown 
5869566063dSJacob Faibussowitsch     PetscCall(KSPCreate(comm, &mglevels[l]->smoothu));
5879566063dSJacob Faibussowitsch     PetscCall(KSPSetErrorIfNotConverged(mglevels[l]->smoothu, pc->erroriffailure));
5889566063dSJacob Faibussowitsch     PetscCall(PetscObjectIncrementTabLevel((PetscObject)mglevels[l]->smoothu, (PetscObject)pc, mglevels[0]->levels - l));
5899566063dSJacob Faibussowitsch     PetscCall(KSPSetOptionsPrefix(mglevels[l]->smoothu, prefix));
5909566063dSJacob Faibussowitsch     PetscCall(KSPSetTolerances(mglevels[l]->smoothu, rtol, abstol, dtol, maxits));
5919566063dSJacob Faibussowitsch     PetscCall(KSPSetType(mglevels[l]->smoothu, ksptype));
5929566063dSJacob Faibussowitsch     PetscCall(KSPSetNormType(mglevels[l]->smoothu, normtype));
5939566063dSJacob Faibussowitsch     PetscCall(KSPSetConvergenceTest(mglevels[l]->smoothu, KSPConvergedSkip, NULL, NULL));
5949566063dSJacob Faibussowitsch     PetscCall(KSPGetPC(mglevels[l]->smoothu, &ipc));
5959566063dSJacob Faibussowitsch     PetscCall(PCSetType(ipc, pctype));
5969566063dSJacob Faibussowitsch     PetscCall(PetscLogObjectParent((PetscObject)pc, (PetscObject)mglevels[l]->smoothu));
5979566063dSJacob Faibussowitsch     PetscCall(PetscObjectComposedDataSetInt((PetscObject)mglevels[l]->smoothu, PetscMGLevelId, mglevels[l]->level));
5984b9ad928SBarry Smith   }
599f3fbd535SBarry Smith   if (ksp) *ksp = mglevels[l]->smoothu;
6004b9ad928SBarry Smith   PetscFunctionReturn(0);
6014b9ad928SBarry Smith }
6024b9ad928SBarry Smith 
603f39d8e23SSatish Balay /*@
60497177400SBarry Smith    PCMGGetSmootherDown - Gets the KSP context to be used as smoother before
6054b9ad928SBarry Smith    coarse grid correction (pre-smoother).
6064b9ad928SBarry Smith 
6074b9ad928SBarry Smith    Not Collective, KSP returned is parallel if PC is
6084b9ad928SBarry Smith 
6094b9ad928SBarry Smith    Input Parameters:
6104b9ad928SBarry Smith +  pc - the multigrid context
6114b9ad928SBarry Smith -  l  - the level (0 is coarsest) to supply
6124b9ad928SBarry Smith 
61301d2d390SJose E. Roman    Output Parameter:
6144b9ad928SBarry Smith .  ksp - the smoother
6154b9ad928SBarry Smith 
6164b9ad928SBarry Smith    Level: advanced
6174b9ad928SBarry Smith 
61895452b02SPatrick Sanan    Notes:
61995452b02SPatrick Sanan     calling this will result in a different pre and post smoother so you may need to
62089cce641SBarry Smith          set options on the post smoother also
62189cce641SBarry Smith 
622db781477SPatrick Sanan .seealso: `PCMGGetSmootherUp()`, `PCMGGetSmoother()`
6234b9ad928SBarry Smith @*/
6249371c9d4SSatish Balay PetscErrorCode PCMGGetSmootherDown(PC pc, PetscInt l, KSP *ksp) {
625f3fbd535SBarry Smith   PC_MG         *mg       = (PC_MG *)pc->data;
626f3fbd535SBarry Smith   PC_MG_Levels **mglevels = mg->levels;
6274b9ad928SBarry Smith 
6284b9ad928SBarry Smith   PetscFunctionBegin;
629c5eb9154SBarry Smith   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
6304b9ad928SBarry Smith   /* make sure smoother up and down are different */
6311baa6e33SBarry Smith   if (l) PetscCall(PCMGGetSmootherUp(pc, l, NULL));
632f3fbd535SBarry Smith   *ksp = mglevels[l]->smoothd;
6334b9ad928SBarry Smith   PetscFunctionReturn(0);
6344b9ad928SBarry Smith }
6354b9ad928SBarry Smith 
6364b9ad928SBarry Smith /*@
637cab31ae5SJed Brown    PCMGSetCycleTypeOnLevel - Sets the type of cycle (aka cycle index) to run on the specified level.
6384b9ad928SBarry Smith 
639ad4df100SBarry Smith    Logically Collective on PC
6404b9ad928SBarry Smith 
6414b9ad928SBarry Smith    Input Parameters:
6424b9ad928SBarry Smith +  pc - the multigrid context
643c1cbb1deSBarry Smith .  l  - the level (0 is coarsest)
644c1cbb1deSBarry Smith -  c  - either PC_MG_CYCLE_V or PC_MG_CYCLE_W
6454b9ad928SBarry Smith 
6464b9ad928SBarry Smith    Level: advanced
6474b9ad928SBarry Smith 
648db781477SPatrick Sanan .seealso: `PCMGSetCycleType()`
6494b9ad928SBarry Smith @*/
6509371c9d4SSatish Balay PetscErrorCode PCMGSetCycleTypeOnLevel(PC pc, PetscInt l, PCMGCycleType c) {
651f3fbd535SBarry Smith   PC_MG         *mg       = (PC_MG *)pc->data;
652f3fbd535SBarry Smith   PC_MG_Levels **mglevels = mg->levels;
6534b9ad928SBarry Smith 
6544b9ad928SBarry Smith   PetscFunctionBegin;
655c5eb9154SBarry Smith   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
65628b400f6SJacob Faibussowitsch   PetscCheck(mglevels, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_WRONGSTATE, "Must set MG levels before calling");
657c5eb9154SBarry Smith   PetscValidLogicalCollectiveInt(pc, l, 2);
658c51679f6SSatish Balay   PetscValidLogicalCollectiveEnum(pc, c, 3);
659f3fbd535SBarry Smith   mglevels[l]->cycles = c;
6604b9ad928SBarry Smith   PetscFunctionReturn(0);
6614b9ad928SBarry Smith }
6624b9ad928SBarry Smith 
6634b9ad928SBarry Smith /*@
664f3b08a26SMatthew G. Knepley   PCMGSetRhs - Sets the vector to be used to store the right-hand side on a particular level.
6654b9ad928SBarry Smith 
666d083f849SBarry Smith    Logically Collective on PC
6674b9ad928SBarry Smith 
6684b9ad928SBarry Smith   Input Parameters:
6694b9ad928SBarry Smith + pc - the multigrid context
6704b9ad928SBarry Smith . l  - the level (0 is coarsest) this is to be used for
671f3b08a26SMatthew G. Knepley - c  - the Vec
6724b9ad928SBarry Smith 
6734b9ad928SBarry Smith   Level: advanced
6744b9ad928SBarry Smith 
67595452b02SPatrick Sanan   Notes:
676f3b08a26SMatthew G. Knepley   If this is not provided PETSc will automatically generate one. You do not need to keep a reference to this vector if you do not need it. PCDestroy() will properly free it.
677fccaa45eSBarry Smith 
678f3b08a26SMatthew G. Knepley .keywords: MG, multigrid, set, right-hand-side, rhs, level
679db781477SPatrick Sanan .seealso: `PCMGSetX()`, `PCMGSetR()`
6804b9ad928SBarry Smith @*/
6819371c9d4SSatish Balay PetscErrorCode PCMGSetRhs(PC pc, PetscInt l, Vec c) {
682f3fbd535SBarry Smith   PC_MG         *mg       = (PC_MG *)pc->data;
683f3fbd535SBarry Smith   PC_MG_Levels **mglevels = mg->levels;
6844b9ad928SBarry Smith 
6854b9ad928SBarry Smith   PetscFunctionBegin;
686c5eb9154SBarry Smith   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
68728b400f6SJacob Faibussowitsch   PetscCheck(mglevels, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_WRONGSTATE, "Must set MG levels before calling");
68808401ef6SPierre Jolivet   PetscCheck(l != mglevels[0]->levels - 1, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_INCOMP, "Do not set rhs for finest level");
6899566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)c));
6909566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&mglevels[l]->b));
6912fa5cd67SKarl Rupp 
692f3fbd535SBarry Smith   mglevels[l]->b = c;
6934b9ad928SBarry Smith   PetscFunctionReturn(0);
6944b9ad928SBarry Smith }
6954b9ad928SBarry Smith 
6964b9ad928SBarry Smith /*@
697f3b08a26SMatthew G. Knepley   PCMGSetX - Sets the vector to be used to store the solution on a particular level.
6984b9ad928SBarry Smith 
699d083f849SBarry Smith   Logically Collective on PC
7004b9ad928SBarry Smith 
7014b9ad928SBarry Smith   Input Parameters:
7024b9ad928SBarry Smith + pc - the multigrid context
703251f4c67SDmitry Karpeev . l - the level (0 is coarsest) this is to be used for (do not supply the finest level)
704f3b08a26SMatthew G. Knepley - c - the Vec
7054b9ad928SBarry Smith 
7064b9ad928SBarry Smith   Level: advanced
7074b9ad928SBarry Smith 
70895452b02SPatrick Sanan   Notes:
709f3b08a26SMatthew G. Knepley   If this is not provided PETSc will automatically generate one. You do not need to keep a reference to this vector if you do not need it. PCDestroy() will properly free it.
710fccaa45eSBarry Smith 
711f3b08a26SMatthew G. Knepley .keywords: MG, multigrid, set, solution, level
712db781477SPatrick Sanan .seealso: `PCMGSetRhs()`, `PCMGSetR()`
7134b9ad928SBarry Smith @*/
7149371c9d4SSatish Balay PetscErrorCode PCMGSetX(PC pc, PetscInt l, Vec c) {
715f3fbd535SBarry Smith   PC_MG         *mg       = (PC_MG *)pc->data;
716f3fbd535SBarry Smith   PC_MG_Levels **mglevels = mg->levels;
7174b9ad928SBarry Smith 
7184b9ad928SBarry Smith   PetscFunctionBegin;
719c5eb9154SBarry Smith   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
72028b400f6SJacob Faibussowitsch   PetscCheck(mglevels, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_WRONGSTATE, "Must set MG levels before calling");
72108401ef6SPierre Jolivet   PetscCheck(l != mglevels[0]->levels - 1, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_INCOMP, "Do not set x for finest level");
7229566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)c));
7239566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&mglevels[l]->x));
7242fa5cd67SKarl Rupp 
725f3fbd535SBarry Smith   mglevels[l]->x = c;
7264b9ad928SBarry Smith   PetscFunctionReturn(0);
7274b9ad928SBarry Smith }
7284b9ad928SBarry Smith 
7294b9ad928SBarry Smith /*@
730f3b08a26SMatthew G. Knepley   PCMGSetR - Sets the vector to be used to store the residual on a particular level.
7314b9ad928SBarry Smith 
732d083f849SBarry Smith   Logically Collective on PC
7334b9ad928SBarry Smith 
7344b9ad928SBarry Smith   Input Parameters:
7354b9ad928SBarry Smith + pc - the multigrid context
7364b9ad928SBarry Smith . l - the level (0 is coarsest) this is to be used for
737f3b08a26SMatthew G. Knepley - c - the Vec
7384b9ad928SBarry Smith 
7394b9ad928SBarry Smith   Level: advanced
7404b9ad928SBarry Smith 
74195452b02SPatrick Sanan   Notes:
742f3b08a26SMatthew G. Knepley   If this is not provided PETSc will automatically generate one. You do not need to keep a reference to this vector if you do not need it. PCDestroy() will properly free it.
743fccaa45eSBarry Smith 
744f3b08a26SMatthew G. Knepley .keywords: MG, multigrid, set, residual, level
745db781477SPatrick Sanan .seealso: `PCMGSetRhs()`, `PCMGSetX()`
7464b9ad928SBarry Smith @*/
7479371c9d4SSatish Balay PetscErrorCode PCMGSetR(PC pc, PetscInt l, Vec c) {
748f3fbd535SBarry Smith   PC_MG         *mg       = (PC_MG *)pc->data;
749f3fbd535SBarry Smith   PC_MG_Levels **mglevels = mg->levels;
7504b9ad928SBarry Smith 
7514b9ad928SBarry Smith   PetscFunctionBegin;
752c5eb9154SBarry Smith   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
75328b400f6SJacob Faibussowitsch   PetscCheck(mglevels, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_WRONGSTATE, "Must set MG levels before calling");
75428b400f6SJacob Faibussowitsch   PetscCheck(l, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_OUTOFRANGE, "Need not set residual vector for coarse grid");
7559566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)c));
7569566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&mglevels[l]->r));
7572fa5cd67SKarl Rupp 
758f3fbd535SBarry Smith   mglevels[l]->r = c;
7594b9ad928SBarry Smith   PetscFunctionReturn(0);
7604b9ad928SBarry Smith }
761