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