xref: /petsc/src/ksp/pc/impls/composite/composite.c (revision 5a4a3fab906bfb9662de262fadfe73a6df2d9a34)
1 
2 /*
3       Defines a preconditioner that can consist of a collection of PCs
4 */
5 #include <petsc/private/pcimpl.h>
6 #include <petscksp.h>            /*I "petscksp.h" I*/
7 
8 typedef struct _PC_CompositeLink *PC_CompositeLink;
9 struct _PC_CompositeLink {
10   PC               pc;
11   PC_CompositeLink next;
12   PC_CompositeLink previous;
13 };
14 
15 typedef struct {
16   PC_CompositeLink head;
17   PCCompositeType  type;
18   Vec              work1;
19   Vec              work2;
20   PetscScalar      alpha;
21 } PC_Composite;
22 
23 #undef __FUNCT__
24 #define __FUNCT__ "PCApply_Composite_Multiplicative"
25 static PetscErrorCode PCApply_Composite_Multiplicative(PC pc,Vec x,Vec y)
26 {
27   PetscErrorCode   ierr;
28   PC_Composite     *jac = (PC_Composite*)pc->data;
29   PC_CompositeLink next = jac->head;
30   Mat              mat  = pc->pmat;
31 
32   PetscFunctionBegin;
33   if (!next) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONGSTATE,"No composite preconditioners supplied via PCCompositeAddPC() or -pc_composite_pcs");
34   if (next->next && !jac->work2) { /* allocate second work vector */
35     ierr = VecDuplicate(jac->work1,&jac->work2);CHKERRQ(ierr);
36   }
37   if (pc->useAmat) mat = pc->mat;
38   ierr = PCApply(next->pc,x,y);CHKERRQ(ierr);                      /* y <- B x */
39   while (next->next) {
40     next = next->next;
41     ierr = MatMult(mat,y,jac->work1);CHKERRQ(ierr);                /* work1 <- A y */
42     ierr = VecWAXPY(jac->work2,-1.0,jac->work1,x);CHKERRQ(ierr);   /* work2 <- x - work1 */
43     ierr = VecSet(jac->work1,0.0);CHKERRQ(ierr);  /* zero since some PC's may not set all entries in the result */
44     ierr = PCApply(next->pc,jac->work2,jac->work1);CHKERRQ(ierr);  /* work1 <- C work2 */
45     ierr = VecAXPY(y,1.0,jac->work1);CHKERRQ(ierr);                /* y <- y + work1 = B x + C (x - A B x) = (B + C (1 - A B)) x */
46   }
47   if (jac->type == PC_COMPOSITE_SYMMETRIC_MULTIPLICATIVE) {
48     while (next->previous) {
49       next = next->previous;
50       ierr = MatMult(mat,y,jac->work1);CHKERRQ(ierr);
51       ierr = VecWAXPY(jac->work2,-1.0,jac->work1,x);CHKERRQ(ierr);
52       ierr = VecSet(jac->work1,0.0);CHKERRQ(ierr);  /* zero since some PC's may not set all entries in the result */
53       ierr = PCApply(next->pc,jac->work2,jac->work1);CHKERRQ(ierr);
54       ierr = VecAXPY(y,1.0,jac->work1);CHKERRQ(ierr);
55     }
56   }
57   PetscFunctionReturn(0);
58 }
59 
60 #undef __FUNCT__
61 #define __FUNCT__ "PCApplyTranspose_Composite_Multiplicative"
62 static PetscErrorCode PCApplyTranspose_Composite_Multiplicative(PC pc,Vec x,Vec y)
63 {
64   PetscErrorCode   ierr;
65   PC_Composite     *jac = (PC_Composite*)pc->data;
66   PC_CompositeLink next = jac->head;
67   Mat              mat  = pc->pmat;
68 
69   PetscFunctionBegin;
70   if (!next) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONGSTATE,"No composite preconditioners supplied via PCCompositeAddPC() or -pc_composite_pcs");
71   if (next->next && !jac->work2) { /* allocate second work vector */
72     ierr = VecDuplicate(jac->work1,&jac->work2);CHKERRQ(ierr);
73   }
74   if (pc->useAmat) mat = pc->mat;
75   /* locate last PC */
76   while (next->next) {
77     next = next->next;
78   }
79   ierr = PCApplyTranspose(next->pc,x,y);CHKERRQ(ierr);
80   while (next->previous) {
81     next = next->previous;
82     ierr = MatMultTranspose(mat,y,jac->work1);CHKERRQ(ierr);
83     ierr = VecWAXPY(jac->work2,-1.0,jac->work1,x);CHKERRQ(ierr);
84     ierr = VecSet(jac->work1,0.0);CHKERRQ(ierr);  /* zero since some PC's may not set all entries in the result */
85     ierr = PCApplyTranspose(next->pc,jac->work2,jac->work1);CHKERRQ(ierr);
86     ierr = VecAXPY(y,1.0,jac->work1);CHKERRQ(ierr);
87   }
88   if (jac->type == PC_COMPOSITE_SYMMETRIC_MULTIPLICATIVE) {
89     next = jac->head;
90     while (next->next) {
91       next = next->next;
92       ierr = MatMultTranspose(mat,y,jac->work1);CHKERRQ(ierr);
93       ierr = VecWAXPY(jac->work2,-1.0,jac->work1,x);CHKERRQ(ierr);
94       ierr = VecSet(jac->work1,0.0);CHKERRQ(ierr);  /* zero since some PC's may not set all entries in the result */
95       ierr = PCApplyTranspose(next->pc,jac->work2,jac->work1);CHKERRQ(ierr);
96       ierr = VecAXPY(y,1.0,jac->work1);CHKERRQ(ierr);
97     }
98   }
99   PetscFunctionReturn(0);
100 }
101 
102 /*
103     This is very special for a matrix of the form alpha I + R + S
104 where first preconditioner is built from alpha I + S and second from
105 alpha I + R
106 */
107 #undef __FUNCT__
108 #define __FUNCT__ "PCApply_Composite_Special"
109 static PetscErrorCode PCApply_Composite_Special(PC pc,Vec x,Vec y)
110 {
111   PetscErrorCode   ierr;
112   PC_Composite     *jac = (PC_Composite*)pc->data;
113   PC_CompositeLink next = jac->head;
114 
115   PetscFunctionBegin;
116   if (!next) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONGSTATE,"No composite preconditioners supplied via PCCompositeAddPC() or -pc_composite_pcs");
117   if (!next->next || next->next->next) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONGSTATE,"Special composite preconditioners requires exactly two PCs");
118 
119   ierr = PCApply(next->pc,x,jac->work1);CHKERRQ(ierr);
120   ierr = PCApply(next->next->pc,jac->work1,y);CHKERRQ(ierr);
121   PetscFunctionReturn(0);
122 }
123 
124 #undef __FUNCT__
125 #define __FUNCT__ "PCApply_Composite_Additive"
126 static PetscErrorCode PCApply_Composite_Additive(PC pc,Vec x,Vec y)
127 {
128   PetscErrorCode   ierr;
129   PC_Composite     *jac = (PC_Composite*)pc->data;
130   PC_CompositeLink next = jac->head;
131 
132   PetscFunctionBegin;
133   if (!next) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONGSTATE,"No composite preconditioners supplied via PCCompositeAddPC() or -pc_composite_pcs");
134   ierr = PCApply(next->pc,x,y);CHKERRQ(ierr);
135   while (next->next) {
136     next = next->next;
137     ierr = VecSet(jac->work1,0.0);CHKERRQ(ierr);  /* zero since some PC's may not set all entries in the result */
138     ierr = PCApply(next->pc,x,jac->work1);CHKERRQ(ierr);
139     ierr = VecAXPY(y,1.0,jac->work1);CHKERRQ(ierr);
140   }
141   PetscFunctionReturn(0);
142 }
143 
144 #undef __FUNCT__
145 #define __FUNCT__ "PCApplyTranspose_Composite_Additive"
146 static PetscErrorCode PCApplyTranspose_Composite_Additive(PC pc,Vec x,Vec y)
147 {
148   PetscErrorCode   ierr;
149   PC_Composite     *jac = (PC_Composite*)pc->data;
150   PC_CompositeLink next = jac->head;
151 
152   PetscFunctionBegin;
153   if (!next) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONGSTATE,"No composite preconditioners supplied via PCCompositeAddPC() or -pc_composite_pcs");
154   ierr = PCApplyTranspose(next->pc,x,y);CHKERRQ(ierr);
155   while (next->next) {
156     next = next->next;
157     ierr = VecSet(jac->work1,0.0);CHKERRQ(ierr);  /* zero since some PC's may not set all entries in the result */
158     ierr = PCApplyTranspose(next->pc,x,jac->work1);CHKERRQ(ierr);
159     ierr = VecAXPY(y,1.0,jac->work1);CHKERRQ(ierr);
160   }
161   PetscFunctionReturn(0);
162 }
163 
164 #undef __FUNCT__
165 #define __FUNCT__ "PCSetUp_Composite"
166 static PetscErrorCode PCSetUp_Composite(PC pc)
167 {
168   PetscErrorCode   ierr;
169   PC_Composite     *jac = (PC_Composite*)pc->data;
170   PC_CompositeLink next = jac->head;
171 
172   PetscFunctionBegin;
173   if (!jac->work1) {
174     ierr = MatCreateVecs(pc->pmat,&jac->work1,0);CHKERRQ(ierr);
175   }
176   while (next) {
177     ierr = PCSetOperators(next->pc,pc->mat,pc->pmat);CHKERRQ(ierr);
178     next = next->next;
179   }
180   PetscFunctionReturn(0);
181 }
182 
183 #undef __FUNCT__
184 #define __FUNCT__ "PCReset_Composite"
185 static PetscErrorCode PCReset_Composite(PC pc)
186 {
187   PC_Composite     *jac = (PC_Composite*)pc->data;
188   PetscErrorCode   ierr;
189   PC_CompositeLink next = jac->head;
190 
191   PetscFunctionBegin;
192   while (next) {
193     ierr = PCReset(next->pc);CHKERRQ(ierr);
194     next = next->next;
195   }
196   ierr = VecDestroy(&jac->work1);CHKERRQ(ierr);
197   ierr = VecDestroy(&jac->work2);CHKERRQ(ierr);
198   PetscFunctionReturn(0);
199 }
200 
201 #undef __FUNCT__
202 #define __FUNCT__ "PCDestroy_Composite"
203 static PetscErrorCode PCDestroy_Composite(PC pc)
204 {
205   PC_Composite     *jac = (PC_Composite*)pc->data;
206   PetscErrorCode   ierr;
207   PC_CompositeLink next = jac->head,next_tmp;
208 
209   PetscFunctionBegin;
210   ierr = PCReset_Composite(pc);CHKERRQ(ierr);
211   while (next) {
212     ierr     = PCDestroy(&next->pc);CHKERRQ(ierr);
213     next_tmp = next;
214     next     = next->next;
215     ierr     = PetscFree(next_tmp);CHKERRQ(ierr);
216   }
217   ierr = PetscFree(pc->data);CHKERRQ(ierr);
218   PetscFunctionReturn(0);
219 }
220 
221 #undef __FUNCT__
222 #define __FUNCT__ "PCSetFromOptions_Composite"
223 static PetscErrorCode PCSetFromOptions_Composite(PetscOptions *PetscOptionsObject,PC pc)
224 {
225   PC_Composite     *jac = (PC_Composite*)pc->data;
226   PetscErrorCode   ierr;
227   PetscInt         nmax = 8,i;
228   PC_CompositeLink next;
229   char             *pcs[8];
230   PetscBool        flg;
231 
232   PetscFunctionBegin;
233   ierr = PetscOptionsHead(PetscOptionsObject,"Composite preconditioner options");CHKERRQ(ierr);
234   ierr = PetscOptionsEnum("-pc_composite_type","Type of composition","PCCompositeSetType",PCCompositeTypes,(PetscEnum)jac->type,(PetscEnum*)&jac->type,&flg);CHKERRQ(ierr);
235   if (flg) {
236     ierr = PCCompositeSetType(pc,jac->type);CHKERRQ(ierr);
237   }
238   ierr = PetscOptionsStringArray("-pc_composite_pcs","List of composite solvers","PCCompositeAddPC",pcs,&nmax,&flg);CHKERRQ(ierr);
239   if (flg) {
240     for (i=0; i<nmax; i++) {
241       ierr = PCCompositeAddPC(pc,pcs[i]);CHKERRQ(ierr);
242       ierr = PetscFree(pcs[i]);CHKERRQ(ierr);   /* deallocate string pcs[i], which is allocated in PetscOptionsStringArray() */
243     }
244   }
245   ierr = PetscOptionsTail();CHKERRQ(ierr);
246 
247   next = jac->head;
248   while (next) {
249     ierr = PCSetFromOptions(next->pc);CHKERRQ(ierr);
250     next = next->next;
251   }
252   PetscFunctionReturn(0);
253 }
254 
255 #undef __FUNCT__
256 #define __FUNCT__ "PCView_Composite"
257 static PetscErrorCode PCView_Composite(PC pc,PetscViewer viewer)
258 {
259   PC_Composite     *jac = (PC_Composite*)pc->data;
260   PetscErrorCode   ierr;
261   PC_CompositeLink next = jac->head;
262   PetscBool        iascii;
263 
264   PetscFunctionBegin;
265   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
266   if (iascii) {
267     ierr = PetscViewerASCIIPrintf(viewer,"Composite PC type - %s\n",PCCompositeTypes[jac->type]);CHKERRQ(ierr);
268     ierr = PetscViewerASCIIPrintf(viewer,"PCs on composite preconditioner follow\n");CHKERRQ(ierr);
269     ierr = PetscViewerASCIIPrintf(viewer,"---------------------------------\n");CHKERRQ(ierr);
270   }
271   if (iascii) {
272     ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr);
273   }
274   while (next) {
275     ierr = PCView(next->pc,viewer);CHKERRQ(ierr);
276     next = next->next;
277   }
278   if (iascii) {
279     ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr);
280     ierr = PetscViewerASCIIPrintf(viewer,"---------------------------------\n");CHKERRQ(ierr);
281   }
282   PetscFunctionReturn(0);
283 }
284 
285 /* ------------------------------------------------------------------------------*/
286 
287 #undef __FUNCT__
288 #define __FUNCT__ "PCCompositeSpecialSetAlpha_Composite"
289 static PetscErrorCode  PCCompositeSpecialSetAlpha_Composite(PC pc,PetscScalar alpha)
290 {
291   PC_Composite *jac = (PC_Composite*)pc->data;
292 
293   PetscFunctionBegin;
294   jac->alpha = alpha;
295   PetscFunctionReturn(0);
296 }
297 
298 #undef __FUNCT__
299 #define __FUNCT__ "PCCompositeSetType_Composite"
300 static PetscErrorCode  PCCompositeSetType_Composite(PC pc,PCCompositeType type)
301 {
302   PC_Composite *jac = (PC_Composite*)pc->data;
303 
304   PetscFunctionBegin;
305   if (type == PC_COMPOSITE_ADDITIVE) {
306     pc->ops->apply          = PCApply_Composite_Additive;
307     pc->ops->applytranspose = PCApplyTranspose_Composite_Additive;
308   } else if (type ==  PC_COMPOSITE_MULTIPLICATIVE || type == PC_COMPOSITE_SYMMETRIC_MULTIPLICATIVE) {
309     pc->ops->apply          = PCApply_Composite_Multiplicative;
310     pc->ops->applytranspose = PCApplyTranspose_Composite_Multiplicative;
311   } else if (type ==  PC_COMPOSITE_SPECIAL) {
312     pc->ops->apply          = PCApply_Composite_Special;
313     pc->ops->applytranspose = NULL;
314   } else SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONG,"Unkown composite preconditioner type");
315   jac->type = type;
316   PetscFunctionReturn(0);
317 }
318 
319 #undef __FUNCT__
320 #define __FUNCT__ "PCCompositeGetType_Composite"
321 static PetscErrorCode  PCCompositeGetType_Composite(PC pc,PCCompositeType *type)
322 {
323   PC_Composite *jac = (PC_Composite*)pc->data;
324 
325   PetscFunctionBegin;
326   *type = jac->type;
327   PetscFunctionReturn(0);
328 }
329 
330 #undef __FUNCT__
331 #define __FUNCT__ "PCCompositeAddPC_Composite"
332 static PetscErrorCode  PCCompositeAddPC_Composite(PC pc,PCType type)
333 {
334   PC_Composite     *jac;
335   PC_CompositeLink next,ilink;
336   PetscErrorCode   ierr;
337   PetscInt         cnt = 0;
338   const char       *prefix;
339   char             newprefix[8];
340 
341   PetscFunctionBegin;
342   ierr        = PetscNewLog(pc,&ilink);CHKERRQ(ierr);
343   ilink->next = 0;
344   ierr        = PCCreate(PetscObjectComm((PetscObject)pc),&ilink->pc);CHKERRQ(ierr);
345   ierr        = PetscLogObjectParent((PetscObject)pc,(PetscObject)ilink->pc);CHKERRQ(ierr);
346 
347   jac  = (PC_Composite*)pc->data;
348   next = jac->head;
349   if (!next) {
350     jac->head       = ilink;
351     ilink->previous = NULL;
352   } else {
353     cnt++;
354     while (next->next) {
355       next = next->next;
356       cnt++;
357     }
358     next->next      = ilink;
359     ilink->previous = next;
360   }
361   ierr = PCGetOptionsPrefix(pc,&prefix);CHKERRQ(ierr);
362   ierr = PCSetOptionsPrefix(ilink->pc,prefix);CHKERRQ(ierr);
363   sprintf(newprefix,"sub_%d_",(int)cnt);
364   ierr = PCAppendOptionsPrefix(ilink->pc,newprefix);CHKERRQ(ierr);
365   /* type is set after prefix, because some methods may modify prefix, e.g. pcksp */
366   ierr = PCSetType(ilink->pc,type);CHKERRQ(ierr);
367   PetscFunctionReturn(0);
368 }
369 
370 #undef __FUNCT__
371 #define __FUNCT__ "PCCompositeGetNumberPC_Composite"
372 static PetscErrorCode  PCCompositeGetNumberPC_Composite(PC pc,PetscInt *n)
373 {
374   PC_Composite     *jac;
375   PC_CompositeLink next;
376 
377   PetscFunctionBegin;
378   jac  = (PC_Composite*)pc->data;
379   next = jac->head;
380   *n = 0;
381   while (next) {
382     next = next->next;
383     (*n) ++;
384   }
385   PetscFunctionReturn(0);
386 }
387 
388 #undef __FUNCT__
389 #define __FUNCT__ "PCCompositeGetPC_Composite"
390 static PetscErrorCode  PCCompositeGetPC_Composite(PC pc,PetscInt n,PC *subpc)
391 {
392   PC_Composite     *jac;
393   PC_CompositeLink next;
394   PetscInt         i;
395 
396   PetscFunctionBegin;
397   jac  = (PC_Composite*)pc->data;
398   next = jac->head;
399   for (i=0; i<n; i++) {
400     if (!next->next) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_INCOMP,"Not enough PCs in composite preconditioner");
401     next = next->next;
402   }
403   *subpc = next->pc;
404   PetscFunctionReturn(0);
405 }
406 
407 /* -------------------------------------------------------------------------------- */
408 #undef __FUNCT__
409 #define __FUNCT__ "PCCompositeSetType"
410 /*@
411    PCCompositeSetType - Sets the type of composite preconditioner.
412 
413    Logically Collective on PC
414 
415    Input Parameters:
416 +  pc - the preconditioner context
417 -  type - PC_COMPOSITE_ADDITIVE (default), PC_COMPOSITE_MULTIPLICATIVE, PC_COMPOSITE_SPECIAL
418 
419    Options Database Key:
420 .  -pc_composite_type <type: one of multiplicative, additive, special> - Sets composite preconditioner type
421 
422    Level: Developer
423 
424 .keywords: PC, set, type, composite preconditioner, additive, multiplicative
425 @*/
426 PetscErrorCode  PCCompositeSetType(PC pc,PCCompositeType type)
427 {
428   PetscErrorCode ierr;
429 
430   PetscFunctionBegin;
431   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
432   PetscValidLogicalCollectiveEnum(pc,type,2);
433   ierr = PetscTryMethod(pc,"PCCompositeSetType_C",(PC,PCCompositeType),(pc,type));CHKERRQ(ierr);
434   PetscFunctionReturn(0);
435 }
436 
437 #undef __FUNCT__
438 #define __FUNCT__ "PCCompositeGetType"
439 /*@
440    PCCompositeGetType - Gets the type of composite preconditioner.
441 
442    Logically Collective on PC
443 
444    Input Parameter:
445 .  pc - the preconditioner context
446 
447    Output Parameter:
448 .  type - PC_COMPOSITE_ADDITIVE (default), PC_COMPOSITE_MULTIPLICATIVE, PC_COMPOSITE_SPECIAL
449 
450    Options Database Key:
451 .  -pc_composite_type <type: one of multiplicative, additive, special> - Sets composite preconditioner type
452 
453    Level: Developer
454 
455 .keywords: PC, set, type, composite preconditioner, additive, multiplicative
456 @*/
457 PetscErrorCode  PCCompositeGetType(PC pc,PCCompositeType *type)
458 {
459   PetscErrorCode ierr;
460 
461   PetscFunctionBegin;
462   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
463   ierr = PetscUseMethod(pc,"PCCompositeGetType_C",(PC,PCCompositeType*),(pc,type));CHKERRQ(ierr);
464   PetscFunctionReturn(0);
465 }
466 
467 #undef __FUNCT__
468 #define __FUNCT__ "PCCompositeSpecialSetAlpha"
469 /*@
470    PCCompositeSpecialSetAlpha - Sets alpha for the special composite preconditioner
471      for alphaI + R + S
472 
473    Logically Collective on PC
474 
475    Input Parameter:
476 +  pc - the preconditioner context
477 -  alpha - scale on identity
478 
479    Level: Developer
480 
481 .keywords: PC, set, type, composite preconditioner, additive, multiplicative
482 @*/
483 PetscErrorCode  PCCompositeSpecialSetAlpha(PC pc,PetscScalar alpha)
484 {
485   PetscErrorCode ierr;
486 
487   PetscFunctionBegin;
488   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
489   PetscValidLogicalCollectiveScalar(pc,alpha,2);
490   ierr = PetscTryMethod(pc,"PCCompositeSpecialSetAlpha_C",(PC,PetscScalar),(pc,alpha));CHKERRQ(ierr);
491   PetscFunctionReturn(0);
492 }
493 
494 #undef __FUNCT__
495 #define __FUNCT__ "PCCompositeAddPC"
496 /*@C
497    PCCompositeAddPC - Adds another PC to the composite PC.
498 
499    Collective on PC
500 
501    Input Parameters:
502 +  pc - the preconditioner context
503 -  type - the type of the new preconditioner
504 
505    Level: Developer
506 
507 .keywords: PC, composite preconditioner, add
508 @*/
509 PetscErrorCode  PCCompositeAddPC(PC pc,PCType type)
510 {
511   PetscErrorCode ierr;
512 
513   PetscFunctionBegin;
514   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
515   ierr = PetscTryMethod(pc,"PCCompositeAddPC_C",(PC,PCType),(pc,type));CHKERRQ(ierr);
516   PetscFunctionReturn(0);
517 }
518 
519 #undef __FUNCT__
520 #define __FUNCT__ "PCCompositeGetNumberPC"
521 /*@
522    PCCompositeGetNumberPC - Gets the number of PC objects in the composite PC.
523 
524    Not Collective
525 
526    Input Parameter:
527 .  pc - the preconditioner context
528 
529    Output Parameter:
530 .  num - the number of sub pcs
531 
532    Level: Developer
533 
534 .keywords: PC, get, composite preconditioner, sub preconditioner
535 
536 .seealso: PCCompositeGetPC()
537 @*/
538 PetscErrorCode  PCCompositeGetNumberPC(PC pc,PetscInt *num)
539 {
540   PetscErrorCode ierr;
541 
542   PetscFunctionBegin;
543   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
544   PetscValidIntPointer(num,2);
545   ierr = PetscUseMethod(pc,"PCCompositeGetNumberPC_C",(PC,PetscInt*),(pc,num));CHKERRQ(ierr);
546   PetscFunctionReturn(0);
547 }
548 
549 #undef __FUNCT__
550 #define __FUNCT__ "PCCompositeGetPC"
551 /*@
552    PCCompositeGetPC - Gets one of the PC objects in the composite PC.
553 
554    Not Collective
555 
556    Input Parameter:
557 +  pc - the preconditioner context
558 -  n - the number of the pc requested
559 
560    Output Parameters:
561 .  subpc - the PC requested
562 
563    Level: Developer
564 
565 .keywords: PC, get, composite preconditioner, sub preconditioner
566 
567 .seealso: PCCompositeAddPC(), PCCompositeGetNumberPC()
568 @*/
569 PetscErrorCode  PCCompositeGetPC(PC pc,PetscInt n,PC *subpc)
570 {
571   PetscErrorCode ierr;
572 
573   PetscFunctionBegin;
574   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
575   PetscValidPointer(subpc,3);
576   ierr = PetscUseMethod(pc,"PCCompositeGetPC_C",(PC,PetscInt,PC*),(pc,n,subpc));CHKERRQ(ierr);
577   PetscFunctionReturn(0);
578 }
579 
580 /* -------------------------------------------------------------------------------------------*/
581 
582 /*MC
583      PCCOMPOSITE - Build a preconditioner by composing together several preconditioners
584 
585    Options Database Keys:
586 +  -pc_composite_type <type: one of multiplicative, additive, symmetric_multiplicative, special> - Sets composite preconditioner type
587 .  -pc_use_amat - Activates PCSetUseAmat()
588 -  -pc_composite_pcs - <pc0,pc1,...> list of PCs to compose
589 
590    Level: intermediate
591 
592    Concepts: composing solvers
593 
594    Notes: To use a Krylov method inside the composite preconditioner, set the PCType of one or more
595           inner PCs to be PCKSP.
596           Using a Krylov method inside another Krylov method can be dangerous (you get divergence or
597           the incorrect answer) unless you use KSPFGMRES as the outer Krylov method
598 
599 
600 .seealso:  PCCreate(), PCSetType(), PCType (for list of available types), PC,
601            PCSHELL, PCKSP, PCCompositeSetType(), PCCompositeSpecialSetAlpha(), PCCompositeAddPC(),
602            PCCompositeGetPC(), PCSetUseAmat()
603 
604 M*/
605 
606 #undef __FUNCT__
607 #define __FUNCT__ "PCCreate_Composite"
608 PETSC_EXTERN PetscErrorCode PCCreate_Composite(PC pc)
609 {
610   PetscErrorCode ierr;
611   PC_Composite   *jac;
612 
613   PetscFunctionBegin;
614   ierr = PetscNewLog(pc,&jac);CHKERRQ(ierr);
615 
616   pc->ops->apply           = PCApply_Composite_Additive;
617   pc->ops->applytranspose  = PCApplyTranspose_Composite_Additive;
618   pc->ops->setup           = PCSetUp_Composite;
619   pc->ops->reset           = PCReset_Composite;
620   pc->ops->destroy         = PCDestroy_Composite;
621   pc->ops->setfromoptions  = PCSetFromOptions_Composite;
622   pc->ops->view            = PCView_Composite;
623   pc->ops->applyrichardson = 0;
624 
625   pc->data   = (void*)jac;
626   jac->type  = PC_COMPOSITE_ADDITIVE;
627   jac->work1 = 0;
628   jac->work2 = 0;
629   jac->head  = 0;
630 
631   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCCompositeSetType_C",PCCompositeSetType_Composite);CHKERRQ(ierr);
632   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCCompositeGetType_C",PCCompositeGetType_Composite);CHKERRQ(ierr);
633   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCCompositeAddPC_C",PCCompositeAddPC_Composite);CHKERRQ(ierr);
634   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCCompositeGetNumberPC_C",PCCompositeGetNumberPC_Composite);CHKERRQ(ierr);
635   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCCompositeGetPC_C",PCCompositeGetPC_Composite);CHKERRQ(ierr);
636   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCCompositeSpecialSetAlpha_C",PCCompositeSpecialSetAlpha_Composite);CHKERRQ(ierr);
637   PetscFunctionReturn(0);
638 }
639 
640