xref: /petsc/src/ksp/pc/impls/mg/mgfunc.c (revision e2df7a95c5ea77c899beea10ff9effd6061e7c8f)
1 #define PETSCKSP_DLL
2 
3 #include "src/ksp/pc/impls/mg/mgimpl.h"       /*I "petscksp.h" I*/
4                           /*I "petscmg.h"   I*/
5 
6 #undef __FUNCT__
7 #define __FUNCT__ "PCMGDefaultResidual"
8 /*@
9    PCMGDefaultResidual - Default routine to calculate the residual.
10 
11    Collective on Mat and Vec
12 
13    Input Parameters:
14 +  mat - the matrix
15 .  b   - the right-hand-side
16 -  x   - the approximate solution
17 
18    Output Parameter:
19 .  r - location to store the residual
20 
21    Level: advanced
22 
23 .keywords: MG, default, multigrid, residual
24 
25 .seealso: PCMGSetResidual()
26 @*/
27 PetscErrorCode PETSCKSP_DLLEXPORT PCMGDefaultResidual(Mat mat,Vec b,Vec x,Vec r)
28 {
29   PetscErrorCode ierr;
30 
31   PetscFunctionBegin;
32   ierr = MatMult(mat,x,r);CHKERRQ(ierr);
33   ierr = VecAYPX(r,-1.0,b);CHKERRQ(ierr);
34   PetscFunctionReturn(0);
35 }
36 
37 /* ---------------------------------------------------------------------------*/
38 
39 #undef __FUNCT__
40 #define __FUNCT__ "MGGetCoarseSolve"
41 /*@
42    PCMGGetCoarseSolve - Gets the solver context to be used on the coarse grid.
43 
44    Not Collective
45 
46    Input Parameter:
47 .  pc - the multigrid context
48 
49    Output Parameter:
50 .  ksp - the coarse grid solver context
51 
52    Level: advanced
53 
54 .keywords: MG, multigrid, get, coarse grid
55 @*/
56 PetscErrorCode PETSCKSP_DLLEXPORT PCMGGetCoarseSolve(PC pc,KSP *ksp)
57 {
58   PC_MG **mg = (PC_MG**)pc->data;
59 
60   PetscFunctionBegin;
61   *ksp =  mg[0]->smoothd;
62   PetscFunctionReturn(0);
63 }
64 
65 #undef __FUNCT__
66 #define __FUNCT__ "MGSetResidual"
67 /*@C
68    PCMGSetResidual - Sets the function to be used to calculate the residual
69    on the lth level.
70 
71    Collective on PC and Mat
72 
73    Input Parameters:
74 +  pc       - the multigrid context
75 .  l        - the level (0 is coarsest) to supply
76 .  residual - function used to form residual (usually PCMGDefaultResidual)
77 -  mat      - matrix associated with residual
78 
79    Level: advanced
80 
81 .keywords:  MG, set, multigrid, residual, level
82 
83 .seealso: PCMGDefaultResidual()
84 @*/
85 PetscErrorCode PETSCKSP_DLLEXPORT PCMGSetResidual(PC pc,PetscInt l,PetscErrorCode (*residual)(Mat,Vec,Vec,Vec),Mat mat)
86 {
87   PC_MG **mg = (PC_MG**)pc->data;
88 
89   PetscFunctionBegin;
90   if (!mg) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Must set MG levels before calling");
91 
92   mg[l]->residual = residual;
93   mg[l]->A        = mat;
94   PetscFunctionReturn(0);
95 }
96 
97 #undef __FUNCT__
98 #define __FUNCT__ "MGSetInterpolate"
99 /*@
100    PCMGSetInterpolate - Sets the function to be used to calculate the
101    interpolation on the lth level.
102 
103    Collective on PC and Mat
104 
105    Input Parameters:
106 +  pc  - the multigrid context
107 .  mat - the interpolation operator
108 -  l   - the level (0 is coarsest) to supply
109 
110    Level: advanced
111 
112    Notes:
113           Usually this is the same matrix used also to set the restriction
114     for the same level.
115 
116           One can pass in the interpolation matrix or its transpose; PETSc figures
117     out from the matrix size which one it is.
118 
119          If you do not set this, the transpose of the Mat set with PCMGSetRestriction()
120     is used.
121 
122 .keywords:  multigrid, set, interpolate, level
123 
124 .seealso: PCMGSetRestriction()
125 @*/
126 PetscErrorCode PETSCKSP_DLLEXPORT PCMGSetInterpolate(PC pc,PetscInt l,Mat mat)
127 {
128   PC_MG          **mg = (PC_MG**)pc->data;
129   PetscErrorCode ierr;
130 
131   PetscFunctionBegin;
132   if (!mg) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Must set MG levels before calling");
133   if (!l) SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"Do not set interpolation routine for coarsest level");
134   if (mg[l]->interpolate) {ierr = MatDestroy(mg[l]->interpolate);CHKERRQ(ierr);}
135   mg[l]->interpolate = mat;
136   ierr = PetscObjectReference((PetscObject)mat);CHKERRQ(ierr);
137   PetscFunctionReturn(0);
138 }
139 
140 #undef __FUNCT__
141 #define __FUNCT__ "MGSetRestriction"
142 /*@
143    PCMGSetRestriction - Sets the function to be used to restrict vector
144    from level l to l-1.
145 
146    Collective on PC and Mat
147 
148    Input Parameters:
149 +  pc - the multigrid context
150 .  mat - the restriction matrix
151 -  l - the level (0 is coarsest) to supply
152 
153    Level: advanced
154 
155    Notes:
156           Usually this is the same matrix used also to set the interpolation
157     for the same level.
158 
159           One can pass in the interpolation matrix or its transpose; PETSc figures
160     out from the matrix size which one it is.
161 
162          If you do not set this, the transpose of the Mat set with PCMGSetInterpolate()
163     is used.
164 
165 .keywords: MG, set, multigrid, restriction, level
166 
167 .seealso: PCMGSetInterpolate()
168 @*/
169 PetscErrorCode PETSCKSP_DLLEXPORT PCMGSetRestriction(PC pc,PetscInt l,Mat mat)
170 {
171   PetscErrorCode ierr;
172   PC_MG          **mg = (PC_MG**)pc->data;
173 
174   PetscFunctionBegin;
175   if (!mg) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Must set MG levels before calling");
176   if (!l) SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"Do not set restriction routine for coarsest level");
177   if (mg[l]->restrct) {ierr = MatDestroy(mg[l]->restrct);CHKERRQ(ierr);}
178   mg[l]->restrct  = mat;
179   ierr = PetscObjectReference((PetscObject)mat);CHKERRQ(ierr);
180   PetscFunctionReturn(0);
181 }
182 
183 #undef __FUNCT__
184 #define __FUNCT__ "MGGetSmoother"
185 /*@
186    PCMGGetSmoother - Gets the KSP context to be used as smoother for
187    both pre- and post-smoothing.  Call both PCMGGetSmootherUp() and
188    PCMGGetSmootherDown() to use different functions for pre- and
189    post-smoothing.
190 
191    Not Collective, KSP returned is parallel if PC is
192 
193    Input Parameters:
194 +  pc - the multigrid context
195 -  l - the level (0 is coarsest) to supply
196 
197    Ouput Parameters:
198 .  ksp - the smoother
199 
200    Level: advanced
201 
202 .keywords: MG, get, multigrid, level, smoother, pre-smoother, post-smoother
203 
204 .seealso: PCMGGetSmootherUp(), PCMGGetSmootherDown()
205 @*/
206 PetscErrorCode PETSCKSP_DLLEXPORT PCMGGetSmoother(PC pc,PetscInt l,KSP *ksp)
207 {
208   PC_MG **mg = (PC_MG**)pc->data;
209 
210   PetscFunctionBegin;
211   *ksp = mg[l]->smoothd;
212   PetscFunctionReturn(0);
213 }
214 
215 #undef __FUNCT__
216 #define __FUNCT__ "MGGetSmootherUp"
217 /*@
218    PCMGGetSmootherUp - Gets the KSP context to be used as smoother after
219    coarse grid correction (post-smoother).
220 
221    Not Collective, KSP returned is parallel if PC is
222 
223    Input Parameters:
224 +  pc - the multigrid context
225 -  l  - the level (0 is coarsest) to supply
226 
227    Ouput Parameters:
228 .  ksp - the smoother
229 
230    Level: advanced
231 
232 .keywords: MG, multigrid, get, smoother, up, post-smoother, level
233 
234 .seealso: PCMGGetSmootherUp(), PCMGGetSmootherDown()
235 @*/
236 PetscErrorCode PETSCKSP_DLLEXPORT PCMGGetSmootherUp(PC pc,PetscInt l,KSP *ksp)
237 {
238   PC_MG          **mg = (PC_MG**)pc->data;
239   PetscErrorCode ierr;
240   const char     *prefix;
241   MPI_Comm       comm;
242 
243   PetscFunctionBegin;
244   /*
245      This is called only if user wants a different pre-smoother from post.
246      Thus we check if a different one has already been allocated,
247      if not we allocate it.
248   */
249   if (!l) SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"There is no such thing as a up smoother on the coarse grid");
250   if (mg[l]->smoothu == mg[l]->smoothd) {
251     ierr = PetscObjectGetComm((PetscObject)mg[l]->smoothd,&comm);CHKERRQ(ierr);
252     ierr = KSPGetOptionsPrefix(mg[l]->smoothd,&prefix);CHKERRQ(ierr);
253     ierr = KSPCreate(comm,&mg[l]->smoothu);CHKERRQ(ierr);
254     ierr = KSPSetTolerances(mg[l]->smoothu,PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT,1);CHKERRQ(ierr);
255     ierr = KSPSetOptionsPrefix(mg[l]->smoothu,prefix);CHKERRQ(ierr);
256     ierr = PetscLogObjectParent(pc,mg[l]->smoothu);CHKERRQ(ierr);
257   }
258   if (ksp) *ksp = mg[l]->smoothu;
259   PetscFunctionReturn(0);
260 }
261 
262 #undef __FUNCT__
263 #define __FUNCT__ "PCMGGetSmootherDown"
264 /*@
265    PCMGGetSmootherDown - Gets the KSP context to be used as smoother before
266    coarse grid correction (pre-smoother).
267 
268    Not Collective, KSP returned is parallel if PC is
269 
270    Input Parameters:
271 +  pc - the multigrid context
272 -  l  - the level (0 is coarsest) to supply
273 
274    Ouput Parameters:
275 .  ksp - the smoother
276 
277    Level: advanced
278 
279 .keywords: MG, multigrid, get, smoother, down, pre-smoother, level
280 
281 .seealso: PCMGGetSmootherUp(), PCMGGetSmoother()
282 @*/
283 PetscErrorCode PETSCKSP_DLLEXPORT PCMGGetSmootherDown(PC pc,PetscInt l,KSP *ksp)
284 {
285   PetscErrorCode ierr;
286   PC_MG          **mg = (PC_MG**)pc->data;
287 
288   PetscFunctionBegin;
289   /* make sure smoother up and down are different */
290   ierr = PCMGGetSmootherUp(pc,l,PETSC_NULL);CHKERRQ(ierr);
291   *ksp = mg[l]->smoothd;
292   PetscFunctionReturn(0);
293 }
294 
295 #undef __FUNCT__
296 #define __FUNCT__ "PCMGSetCyclesOnLevel"
297 /*@
298    PCMGSetCyclesOnLevel - Sets the number of cycles to run on this level.
299 
300    Collective on PC
301 
302    Input Parameters:
303 +  pc - the multigrid context
304 .  l  - the level (0 is coarsest) this is to be used for
305 -  n  - the number of cycles
306 
307    Level: advanced
308 
309 .keywords: MG, multigrid, set, cycles, V-cycle, W-cycle, level
310 
311 .seealso: PCMGSetCycles()
312 @*/
313 PetscErrorCode PETSCKSP_DLLEXPORT PCMGSetCyclesOnLevel(PC pc,PetscInt l,PetscInt c)
314 {
315   PC_MG **mg = (PC_MG**)pc->data;
316 
317   PetscFunctionBegin;
318   if (!mg) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Must set MG levels before calling");
319   mg[l]->cycles  = c;
320   PetscFunctionReturn(0);
321 }
322 
323 #undef __FUNCT__
324 #define __FUNCT__ "MGSetRhs"
325 /*@
326    PCMGSetRhs - Sets the vector space to be used to store the right-hand side
327    on a particular level.
328 
329    Collective on PC and Vec
330 
331    Input Parameters:
332 +  pc - the multigrid context
333 .  l  - the level (0 is coarsest) this is to be used for
334 -  c  - the space
335 
336    Level: advanced
337 
338    Notes: If this is not provided PETSc will automatically generate one.
339 
340           You do not need to keep a reference to this vector if you do
341           not need it PCDestroy() will properly free it.
342 
343 .keywords: MG, multigrid, set, right-hand-side, rhs, level
344 
345 .seealso: PCMGSetX(), PCMGSetR()
346 @*/
347 PetscErrorCode PETSCKSP_DLLEXPORT PCMGSetRhs(PC pc,PetscInt l,Vec c)
348 {
349   PetscErrorCode ierr;
350   PC_MG          **mg = (PC_MG**)pc->data;
351 
352   PetscFunctionBegin;
353   if (!mg) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Must set MG levels before calling");
354   if (l == mg[0]->levels-1) SETERRQ(PETSC_ERR_ARG_INCOMP,"Do not set rhs for finest level");
355   if (mg[l]->b) {ierr = VecDestroy(mg[l]->b);CHKERRQ(ierr);}
356   mg[l]->b  = c;
357   ierr = PetscObjectReference((PetscObject)c);CHKERRQ(ierr);
358   PetscFunctionReturn(0);
359 }
360 
361 #undef __FUNCT__
362 #define __FUNCT__ "MGSetX"
363 /*@
364    PCMGSetX - Sets the vector space to be used to store the solution on a
365    particular level.
366 
367    Collective on PC and Vec
368 
369    Input Parameters:
370 +  pc - the multigrid context
371 .  l - the level (0 is coarsest) this is to be used for
372 -  c - the space
373 
374    Level: advanced
375 
376    Notes: If this is not provided PETSc will automatically generate one.
377 
378           You do not need to keep a reference to this vector if you do
379           not need it PCDestroy() will properly free it.
380 
381 .keywords: MG, multigrid, set, solution, level
382 
383 .seealso: PCMGSetRhs(), PCMGSetR()
384 @*/
385 PetscErrorCode PETSCKSP_DLLEXPORT PCMGSetX(PC pc,PetscInt l,Vec c)
386 {
387   PetscErrorCode ierr;
388   PC_MG          **mg = (PC_MG**)pc->data;
389 
390   PetscFunctionBegin;
391   if (!mg) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Must set MG levels before calling");
392   if (l == mg[0]->levels-1) SETERRQ(PETSC_ERR_ARG_INCOMP,"Do not set rhs for finest level");
393   if (mg[l]->x) {ierr = VecDestroy(mg[l]->x);CHKERRQ(ierr);}
394   mg[l]->x  = c;
395   ierr = PetscObjectReference((PetscObject)c);CHKERRQ(ierr);
396   PetscFunctionReturn(0);
397 }
398 
399 #undef __FUNCT__
400 #define __FUNCT__ "MGSetR"
401 /*@
402    PCMGSetR - Sets the vector space to be used to store the residual on a
403    particular level.
404 
405    Collective on PC and Vec
406 
407    Input Parameters:
408 +  pc - the multigrid context
409 .  l - the level (0 is coarsest) this is to be used for
410 -  c - the space
411 
412    Level: advanced
413 
414    Notes: If this is not provided PETSc will automatically generate one.
415 
416           You do not need to keep a reference to this vector if you do
417           not need it PCDestroy() will properly free it.
418 
419 .keywords: MG, multigrid, set, residual, level
420 @*/
421 PetscErrorCode PETSCKSP_DLLEXPORT PCMGSetR(PC pc,PetscInt l,Vec c)
422 {
423   PetscErrorCode ierr;
424   PC_MG          **mg = (PC_MG**)pc->data;
425 
426   PetscFunctionBegin;
427   if (!mg) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Must set MG levels before calling");
428   if (!l) SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"Need not set residual vector for coarse grid");
429   if (mg[l]->r) {ierr = VecDestroy(mg[l]->r);CHKERRQ(ierr);}
430   mg[l]->r  = c;
431   ierr = PetscObjectReference((PetscObject)c);CHKERRQ(ierr);
432   PetscFunctionReturn(0);
433 }
434 
435 
436 
437 
438 
439 
440 
441 
442