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