xref: /petsc/src/ksp/pc/impls/fieldsplit/fieldsplit.c (revision 18be62a5feccf172f7bc80c15c4be8f6d6443e8b)
1 #define PETSCKSP_DLL
2 
3 /*
4 
5 */
6 #include "src/ksp/pc/pcimpl.h"     /*I "petscpc.h" I*/
7 
8 typedef struct _PC_FieldSplitLink *PC_FieldSplitLink;
9 struct _PC_FieldSplitLink {
10   KSP               ksp;
11   Vec               x,y;
12   PetscInt          nfields;
13   PetscInt          *fields;
14   VecScatter        sctx;
15   PC_FieldSplitLink next;
16 };
17 
18 typedef struct {
19   PCCompositeType   type;              /* additive or multiplicative */
20   PetscTruth        defaultsplit;
21   PetscInt          bs;
22   PetscInt          nsplits;
23   Vec               *x,*y,w1,w2;
24   Mat               *pmat;
25   IS                *is;
26   PC_FieldSplitLink head;
27 } PC_FieldSplit;
28 
29 #undef __FUNCT__
30 #define __FUNCT__ "PCView_FieldSplit"
31 static PetscErrorCode PCView_FieldSplit(PC pc,PetscViewer viewer)
32 {
33   PC_FieldSplit     *jac = (PC_FieldSplit*)pc->data;
34   PetscErrorCode    ierr;
35   PetscTruth        iascii;
36   PetscInt          i,j;
37   PC_FieldSplitLink ilink = jac->head;
38 
39   PetscFunctionBegin;
40   ierr = PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_ASCII,&iascii);CHKERRQ(ierr);
41   if (iascii) {
42     ierr = PetscViewerASCIIPrintf(viewer,"  FieldSplit with %s composition: total splits = %D",PCCompositeTypes[jac->type],jac->nsplits);CHKERRQ(ierr);
43     ierr = PetscViewerASCIIPrintf(viewer,"  Solver info for each split is in the following KSP objects:\n");CHKERRQ(ierr);
44     ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr);
45     for (i=0; i<jac->nsplits; i++) {
46       ierr = PetscViewerASCIIPrintf(viewer,"Split number %D Fields ",i);CHKERRQ(ierr);
47       ierr = PetscViewerASCIIUseTabs(viewer,PETSC_FALSE);CHKERRQ(ierr);
48       for (j=0; j<ilink->nfields; j++) {
49         if (j > 0) {
50           ierr = PetscViewerASCIIPrintf(viewer,",");CHKERRQ(ierr);
51         }
52         ierr = PetscViewerASCIIPrintf(viewer," %D",ilink->fields[j]);CHKERRQ(ierr);
53       }
54       ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr);
55       ierr = PetscViewerASCIIUseTabs(viewer,PETSC_TRUE);CHKERRQ(ierr);
56       ierr = KSPView(ilink->ksp,viewer);CHKERRQ(ierr);
57       ilink = ilink->next;
58     }
59     ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr);
60   } else {
61     SETERRQ1(PETSC_ERR_SUP,"Viewer type %s not supported for PCFieldSplit",((PetscObject)viewer)->type_name);
62   }
63   PetscFunctionReturn(0);
64 }
65 
66 #undef __FUNCT__
67 #define __FUNCT__ "PCFieldSplitSetDefaults"
68 static PetscErrorCode PCFieldSplitSetDefaults(PC pc)
69 {
70   PC_FieldSplit     *jac  = (PC_FieldSplit*)pc->data;
71   PetscErrorCode    ierr;
72   PC_FieldSplitLink ilink = jac->head;
73   PetscInt          i;
74   PetscTruth        flg = PETSC_FALSE,*fields;
75 
76   PetscFunctionBegin;
77   ierr = PetscOptionsGetTruth(pc->prefix,"-pc_fieldsplit_default",&flg,PETSC_NULL);CHKERRQ(ierr);
78   if (!ilink || flg) {
79     ierr = PetscLogInfo((pc,"PCFieldSplitSetDefaults: Using default splitting of fields\n"));CHKERRQ(ierr);
80     if (jac->bs <= 0) {
81       ierr   = MatGetBlockSize(pc->pmat,&jac->bs);CHKERRQ(ierr);
82     }
83     ierr = PetscMalloc(jac->bs*sizeof(PetscTruth),&fields);CHKERRQ(ierr);
84     ierr = PetscMemzero(fields,jac->bs*sizeof(PetscTruth));CHKERRQ(ierr);
85     while (ilink) {
86       for (i=0; i<ilink->nfields; i++) {
87         fields[ilink->fields[i]] = PETSC_TRUE;
88       }
89       ilink = ilink->next;
90     }
91     jac->defaultsplit = PETSC_TRUE;
92     for (i=0; i<jac->bs; i++) {
93       if (!fields[i]) {
94 	ierr = PCFieldSplitSetFields(pc,1,&i);CHKERRQ(ierr);
95       } else {
96         jac->defaultsplit = PETSC_FALSE;
97       }
98     }
99   }
100   PetscFunctionReturn(0);
101 }
102 
103 
104 #undef __FUNCT__
105 #define __FUNCT__ "PCSetUp_FieldSplit"
106 static PetscErrorCode PCSetUp_FieldSplit(PC pc)
107 {
108   PC_FieldSplit     *jac = (PC_FieldSplit*)pc->data;
109   PetscErrorCode    ierr;
110   PC_FieldSplitLink ilink;
111   PetscInt          i,nsplit;
112   MatStructure      flag = pc->flag;
113 
114   PetscFunctionBegin;
115   ierr   = PCFieldSplitSetDefaults(pc);CHKERRQ(ierr);
116   nsplit = jac->nsplits;
117   ilink   = jac->head;
118 
119   /* get the matrices for each split */
120   if (!jac->is) {
121     PetscInt rstart,rend,nslots,bs;
122 
123     ierr   = MatGetBlockSize(pc->pmat,&bs);CHKERRQ(ierr);
124     ierr   = MatGetOwnershipRange(pc->pmat,&rstart,&rend);CHKERRQ(ierr);
125     nslots = (rend - rstart)/bs;
126     ierr   = PetscMalloc(nsplit*sizeof(IS),&jac->is);CHKERRQ(ierr);
127     for (i=0; i<nsplit; i++) {
128       if (jac->defaultsplit) {
129 	ierr = ISCreateStride(pc->comm,nslots,rstart+i,nsplit,&jac->is[i]);CHKERRQ(ierr);
130       } else {
131         PetscInt   *ii,j,k,nfields = ilink->nfields,*fields = ilink->fields;
132         PetscTruth sorted;
133         ierr = PetscMalloc(ilink->nfields*nslots*sizeof(PetscInt),&ii);CHKERRQ(ierr);
134         for (j=0; j<nslots; j++) {
135           for (k=0; k<nfields; k++) {
136             ii[nfields*j + k] = rstart + bs*j + fields[k];
137           }
138         }
139 	ierr = ISCreateGeneral(pc->comm,nslots*nfields,ii,&jac->is[i]);CHKERRQ(ierr);
140         ierr = ISSorted(jac->is[i],&sorted);CHKERRQ(ierr);
141         if (!sorted) SETERRQ(PETSC_ERR_USER,"Fields must be sorted when creating split");
142         ierr = PetscFree(ii);CHKERRQ(ierr);
143         ilink = ilink->next;
144       }
145     }
146   }
147 
148   if (!jac->pmat) {
149     ierr = MatGetSubMatrices(pc->pmat,nsplit,jac->is,jac->is,MAT_INITIAL_MATRIX,&jac->pmat);CHKERRQ(ierr);
150   } else {
151     ierr = MatGetSubMatrices(pc->pmat,nsplit,jac->is,jac->is,MAT_REUSE_MATRIX,&jac->pmat);CHKERRQ(ierr);
152   }
153 
154   /* set up the individual PCs */
155   i    = 0;
156   ilink = jac->head;
157   while (ilink) {
158     ierr = KSPSetOperators(ilink->ksp,jac->pmat[i],jac->pmat[i],flag);CHKERRQ(ierr);
159     ierr = KSPSetFromOptions(ilink->ksp);CHKERRQ(ierr);
160     ierr = KSPSetUp(ilink->ksp);CHKERRQ(ierr);
161     i++;
162     ilink = ilink->next;
163   }
164 
165   /* create work vectors for each split */
166   if (!jac->x) {
167     Vec xtmp;
168     ierr = PetscMalloc2(nsplit,Vec,&jac->x,nsplit,Vec,&jac->y);CHKERRQ(ierr);
169     ilink = jac->head;
170     for (i=0; i<nsplit; i++) {
171       Mat A;
172       ierr      = KSPGetOperators(ilink->ksp,PETSC_NULL,&A,PETSC_NULL);CHKERRQ(ierr);
173       ierr      = MatGetVecs(A,&ilink->x,&ilink->y);CHKERRQ(ierr);
174       jac->x[i] = ilink->x;
175       jac->y[i] = ilink->y;
176       ilink      = ilink->next;
177     }
178     /* compute scatter contexts needed by multiplicative versions and non-default splits */
179 
180     ilink = jac->head;
181     ierr = MatGetVecs(pc->pmat,&xtmp,PETSC_NULL);CHKERRQ(ierr);
182     for (i=0; i<nsplit; i++) {
183       ierr = VecScatterCreate(xtmp,jac->is[i],jac->x[i],PETSC_NULL,&ilink->sctx);CHKERRQ(ierr);
184       ilink = ilink->next;
185     }
186     ierr = VecDestroy(xtmp);CHKERRQ(ierr);
187   }
188   PetscFunctionReturn(0);
189 }
190 
191 #define FieldSplitSplitSolveAdd(ilink,xx,yy) \
192     (VecScatterBegin(xx,ilink->x,INSERT_VALUES,SCATTER_FORWARD,ilink->sctx) || \
193      VecScatterEnd(xx,ilink->x,INSERT_VALUES,SCATTER_FORWARD,ilink->sctx) || \
194      KSPSolve(ilink->ksp,ilink->x,ilink->y) || \
195      VecScatterBegin(ilink->y,yy,ADD_VALUES,SCATTER_REVERSE,ilink->sctx) || \
196      VecScatterEnd(ilink->y,yy,ADD_VALUES,SCATTER_REVERSE,ilink->sctx))
197 
198 #undef __FUNCT__
199 #define __FUNCT__ "PCApply_FieldSplit"
200 static PetscErrorCode PCApply_FieldSplit(PC pc,Vec x,Vec y)
201 {
202   PC_FieldSplit     *jac = (PC_FieldSplit*)pc->data;
203   PetscErrorCode    ierr;
204   PC_FieldSplitLink ilink = jac->head;
205   PetscScalar       zero = 0.0,mone = -1.0;
206 
207   PetscFunctionBegin;
208   if (jac->type == PC_COMPOSITE_ADDITIVE) {
209     if (jac->defaultsplit) {
210       ierr = VecStrideGatherAll(x,jac->x,INSERT_VALUES);CHKERRQ(ierr);
211       while (ilink) {
212 	ierr = KSPSolve(ilink->ksp,ilink->x,ilink->y);CHKERRQ(ierr);
213 	ilink = ilink->next;
214       }
215       ierr = VecStrideScatterAll(jac->y,y,INSERT_VALUES);CHKERRQ(ierr);
216     } else {
217       PetscInt    i = 0;
218 
219       ierr = VecSet(y,zero);CHKERRQ(ierr);
220       while (ilink) {
221         ierr = FieldSplitSplitSolveAdd(ilink,x,y);CHKERRQ(ierr);
222 	ilink = ilink->next;
223 	i++;
224       }
225     }
226   } else {
227     if (!jac->w1) {
228       ierr = VecDuplicate(x,&jac->w1);CHKERRQ(ierr);
229       ierr = VecDuplicate(x,&jac->w2);CHKERRQ(ierr);
230     }
231     ierr = VecSet(y,zero);CHKERRQ(ierr);
232     ierr = FieldSplitSplitSolveAdd(ilink,x,y);CHKERRQ(ierr);
233     while (ilink->next) {
234       ilink = ilink->next;
235       ierr = MatMult(pc->pmat,y,jac->w1);CHKERRQ(ierr);
236       ierr = VecWAXPY(jac->w2,mone,jac->w1,x);CHKERRQ(ierr);
237       ierr = FieldSplitSplitSolveAdd(ilink,jac->w2,y);CHKERRQ(ierr);
238     }
239   }
240   PetscFunctionReturn(0);
241 }
242 
243 #undef __FUNCT__
244 #define __FUNCT__ "PCDestroy_FieldSplit"
245 static PetscErrorCode PCDestroy_FieldSplit(PC pc)
246 {
247   PC_FieldSplit     *jac = (PC_FieldSplit*)pc->data;
248   PetscErrorCode    ierr;
249   PC_FieldSplitLink ilink = jac->head,next;
250 
251   PetscFunctionBegin;
252   while (ilink) {
253     ierr = KSPDestroy(ilink->ksp);CHKERRQ(ierr);
254     if (ilink->x) {ierr = VecDestroy(ilink->x);CHKERRQ(ierr);}
255     if (ilink->y) {ierr = VecDestroy(ilink->y);CHKERRQ(ierr);}
256     if (ilink->sctx) {ierr = VecScatterDestroy(ilink->sctx);CHKERRQ(ierr);}
257     next = ilink->next;
258     ierr = PetscFree2(ilink,ilink->fields);CHKERRQ(ierr);
259     ilink = next;
260   }
261   if (jac->x) {ierr = PetscFree2(jac->x,jac->y);CHKERRQ(ierr);}
262   if (jac->pmat) {ierr = MatDestroyMatrices(jac->nsplits,&jac->pmat);CHKERRQ(ierr);}
263   if (jac->is) {
264     PetscInt i;
265     for (i=0; i<jac->nsplits; i++) {ierr = ISDestroy(jac->is[i]);CHKERRQ(ierr);}
266     ierr = PetscFree(jac->is);CHKERRQ(ierr);
267   }
268   if (jac->w1) {ierr = VecDestroy(jac->w1);CHKERRQ(ierr);}
269   if (jac->w2) {ierr = VecDestroy(jac->w2);CHKERRQ(ierr);}
270   ierr = PetscFree(jac);CHKERRQ(ierr);
271   PetscFunctionReturn(0);
272 }
273 
274 #undef __FUNCT__
275 #define __FUNCT__ "PCSetFromOptions_FieldSplit"
276 static PetscErrorCode PCSetFromOptions_FieldSplit(PC pc)
277 /*   This does not call KSPSetFromOptions() on the subksp's, see PCSetFromOptionsBJacobi/ASM() */
278 {
279   PetscErrorCode ierr;
280   PetscInt       i = 0,nfields,fields[12];
281   PetscTruth     flg;
282   char           optionname[128];
283   PC_FieldSplit  *jac = (PC_FieldSplit*)pc->data;
284 
285   PetscFunctionBegin;
286   ierr = PetscOptionsHead("FieldSplit options");CHKERRQ(ierr);
287   ierr = PetscOptionsEnum("-pc_fieldsplit_type","Type of composition","PCFieldSplitSetType",PCCompositeTypes,(PetscEnum)jac->type,(PetscEnum*)&jac->type,&flg);CHKERRQ(ierr);
288   while (PETSC_TRUE) {
289     sprintf(optionname,"-pc_fieldsplit_%d_fields",(int)i++);
290     nfields = 12;
291     ierr    = PetscOptionsIntArray(optionname,"Fields in this split","PCFieldSplitSetFields",fields,&nfields,&flg);CHKERRQ(ierr);
292     if (!flg) break;
293     if (!nfields) SETERRQ(PETSC_ERR_USER,"Cannot list zero fields");
294     ierr = PCFieldSplitSetFields(pc,nfields,fields);CHKERRQ(ierr);
295   }
296   ierr = PetscOptionsTail();CHKERRQ(ierr);
297   PetscFunctionReturn(0);
298 }
299 
300 /*------------------------------------------------------------------------------------*/
301 
302 EXTERN_C_BEGIN
303 #undef __FUNCT__
304 #define __FUNCT__ "PCFieldSplitSetFields_FieldSplit"
305 PetscErrorCode PETSCKSP_DLLEXPORT PCFieldSplitSetFields_FieldSplit(PC pc,PetscInt n,PetscInt *fields)
306 {
307   PC_FieldSplit     *jac = (PC_FieldSplit*)pc->data;
308   PetscErrorCode    ierr;
309   PC_FieldSplitLink ilink,next = jac->head;
310   char              prefix[128];
311 
312   PetscFunctionBegin;
313   if (n <= 0) SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"Negative number of fields requested");
314   ierr = PetscMalloc2(1,struct _PC_FieldSplitLink,&ilink,n,PetscInt,&ilink->fields);CHKERRQ(ierr);
315   ierr = PetscMemcpy(ilink->fields,fields,n*sizeof(PetscInt));CHKERRQ(ierr);
316   ilink->nfields = n;
317   ilink->next    = PETSC_NULL;
318   ierr          = KSPCreate(pc->comm,&ilink->ksp);CHKERRQ(ierr);
319   ierr          = KSPSetType(ilink->ksp,KSPPREONLY);CHKERRQ(ierr);
320 
321   if (pc->prefix) {
322     sprintf(prefix,"%sfieldsplit_%d_",pc->prefix,(int)jac->nsplits);
323   } else {
324     sprintf(prefix,"fieldsplit_%d_",(int)jac->nsplits);
325   }
326   ierr = KSPSetOptionsPrefix(ilink->ksp,prefix);CHKERRQ(ierr);
327 
328   if (!next) {
329     jac->head = ilink;
330   } else {
331     while (next->next) {
332       next = next->next;
333     }
334     next->next = ilink;
335   }
336   jac->nsplits++;
337   PetscFunctionReturn(0);
338 }
339 EXTERN_C_END
340 
341 
342 EXTERN_C_BEGIN
343 #undef __FUNCT__
344 #define __FUNCT__ "PCFieldSplitGetSubKSP_FieldSplit"
345 PetscErrorCode PETSCKSP_DLLEXPORT PCFieldSplitGetSubKSP_FieldSplit(PC pc,PetscInt *n,KSP **subksp)
346 {
347   PC_FieldSplit     *jac = (PC_FieldSplit*)pc->data;
348   PetscErrorCode    ierr;
349   PetscInt          cnt = 0;
350   PC_FieldSplitLink ilink = jac->head;
351 
352   PetscFunctionBegin;
353   ierr = PetscMalloc(jac->nsplits*sizeof(KSP*),subksp);CHKERRQ(ierr);
354   while (ilink) {
355     (*subksp)[cnt++] = ilink->ksp;
356     ilink = ilink->next;
357   }
358   if (cnt != jac->nsplits) SETERRQ2(PETSC_ERR_PLIB,"Corrupt PCFIELDSPLIT object: number splits in linked list %D in object %D",cnt,jac->nsplits);
359   *n = jac->nsplits;
360   PetscFunctionReturn(0);
361 }
362 EXTERN_C_END
363 
364 #undef __FUNCT__
365 #define __FUNCT__ "PCFieldSplitSetFields"
366 /*@
367     PCFieldSplitSetFields - Sets the fields for one particular split in the field split preconditioner
368 
369     Collective on PC
370 
371     Input Parameters:
372 +   pc  - the preconditioner context
373 .   n - the number of fields in this split
374 .   fields - the fields in this split
375 
376     Level: intermediate
377 
378 .seealso: PCFieldSplitGetSubKSP(), PCFIELDSPLIT
379 
380 @*/
381 PetscErrorCode PETSCKSP_DLLEXPORT PCFieldSplitSetFields(PC pc,PetscInt n, PetscInt *fields)
382 {
383   PetscErrorCode ierr,(*f)(PC,PetscInt,PetscInt *);
384 
385   PetscFunctionBegin;
386   PetscValidHeaderSpecific(pc,PC_COOKIE,1);
387   ierr = PetscObjectQueryFunction((PetscObject)pc,"PCFieldSplitSetFields_C",(void (**)(void))&f);CHKERRQ(ierr);
388   if (f) {
389     ierr = (*f)(pc,n,fields);CHKERRQ(ierr);
390   }
391   PetscFunctionReturn(0);
392 }
393 
394 #undef __FUNCT__
395 #define __FUNCT__ "PCFieldSplitGetSubKSP"
396 /*@C
397    PCFieldSplitGetSubKSP - Gets the KSP contexts for all splits
398 
399    Collective on KSP
400 
401    Input Parameter:
402 .  pc - the preconditioner context
403 
404    Output Parameters:
405 +  n - the number of split
406 -  pc - the array of KSP contexts
407 
408    Note:
409    After PCFieldSplitGetSubKSP() the array of KSPs IS to be freed
410 
411    You must call KSPSetUp() before calling PCFieldSplitGetSubKSP().
412 
413    Level: advanced
414 
415 .seealso: PCFIELDSPLIT
416 @*/
417 PetscErrorCode PETSCKSP_DLLEXPORT PCFieldSplitGetSubKSP(PC pc,PetscInt *n,KSP *subksp[])
418 {
419   PetscErrorCode ierr,(*f)(PC,PetscInt*,KSP **);
420 
421   PetscFunctionBegin;
422   PetscValidHeaderSpecific(pc,PC_COOKIE,1);
423   PetscValidIntPointer(n,2);
424   ierr = PetscObjectQueryFunction((PetscObject)pc,"PCFieldSplitGetSubKSP_C",(void (**)(void))&f);CHKERRQ(ierr);
425   if (f) {
426     ierr = (*f)(pc,n,subksp);CHKERRQ(ierr);
427   } else {
428     SETERRQ(PETSC_ERR_ARG_WRONG,"Cannot get subksp for this type of PC");
429   }
430   PetscFunctionReturn(0);
431 }
432 
433 EXTERN_C_BEGIN
434 #undef __FUNCT__
435 #define __FUNCT__ "PCFieldSplitSetType_FieldSplit"
436 PetscErrorCode PETSCKSP_DLLEXPORT PCFieldSplitSetType_FieldSplit(PC pc,PCCompositeType type)
437 {
438   PC_FieldSplit  *jac = (PC_FieldSplit*)pc->data;
439 
440   PetscFunctionBegin;
441   jac->type = type;
442   PetscFunctionReturn(0);
443 }
444 EXTERN_C_END
445 
446 #undef __FUNCT__
447 #define __FUNCT__ "PCFieldSplitSetType"
448 /*@C
449    PCFieldSplitSetType - Sets the type of fieldsplit preconditioner.
450 
451    Collective on PC
452 
453    Input Parameter:
454 .  pc - the preconditioner context
455 .  type - PC_COMPOSITE_ADDITIVE (default), PC_COMPOSITE_MULTIPLICATIVE
456 
457    Options Database Key:
458 .  -pc_fieldsplit_type <type: one of multiplicative, additive, special> - Sets fieldsplit preconditioner type
459 
460    Level: Developer
461 
462 .keywords: PC, set, type, composite preconditioner, additive, multiplicative
463 
464 .seealso: PCCompositeSetType()
465 
466 @*/
467 PetscErrorCode PETSCKSP_DLLEXPORT PCFieldSplitSetType(PC pc,PCCompositeType type)
468 {
469   PetscErrorCode ierr,(*f)(PC,PCCompositeType);
470 
471   PetscFunctionBegin;
472   PetscValidHeaderSpecific(pc,PC_COOKIE,1);
473   ierr = PetscObjectQueryFunction((PetscObject)pc,"PCFieldSplitSetType_C",(void (**)(void))&f);CHKERRQ(ierr);
474   if (f) {
475     ierr = (*f)(pc,type);CHKERRQ(ierr);
476   }
477   PetscFunctionReturn(0);
478 }
479 
480 /* -------------------------------------------------------------------------------------*/
481 /*MC
482    PCFIELDSPLIT - Preconditioner created by combining seperate preconditioners for individual
483                   fields or groups of fields
484 
485 
486      To set options on the solvers for each block append -sub_ to all the PC
487         options database keys. For example, -sub_pc_type ilu -sub_pc_ilu_levels 1
488 
489      To set the options on the solvers seperate for each block call PCFieldSplitGetSubKSP()
490          and set the options directly on the resulting KSP object
491 
492    Level: intermediate
493 
494    Options Database Keys:
495 +   -pc_splitfield_%d_fields <a,b,..> - indicates the fields to be used in the %d'th split
496 .   -pc_splitfield_default - automatically add any fields to additional splits that have not
497                               been supplied explicitly by -pc_splitfield_%d_fields
498 -   -pc_splitfield_type <additive,multiplicative>
499 
500    Concepts: physics based preconditioners
501 
502 .seealso:  PCCreate(), PCSetType(), PCType (for list of available types), PC,
503            PCFieldSplitGetSubKSP(), PCFieldSplitSetFields(),PCFieldSplitSetType()
504 M*/
505 
506 EXTERN_C_BEGIN
507 #undef __FUNCT__
508 #define __FUNCT__ "PCCreate_FieldSplit"
509 PetscErrorCode PETSCKSP_DLLEXPORT PCCreate_FieldSplit(PC pc)
510 {
511   PetscErrorCode ierr;
512   PC_FieldSplit  *jac;
513 
514   PetscFunctionBegin;
515   ierr = PetscNew(PC_FieldSplit,&jac);CHKERRQ(ierr);
516   ierr = PetscLogObjectMemory(pc,sizeof(PC_FieldSplit));CHKERRQ(ierr);
517   jac->bs      = -1;
518   jac->nsplits = 0;
519   jac->type    = PC_COMPOSITE_ADDITIVE;
520   pc->data     = (void*)jac;
521 
522   pc->ops->apply             = PCApply_FieldSplit;
523   pc->ops->setup             = PCSetUp_FieldSplit;
524   pc->ops->destroy           = PCDestroy_FieldSplit;
525   pc->ops->setfromoptions    = PCSetFromOptions_FieldSplit;
526   pc->ops->view              = PCView_FieldSplit;
527   pc->ops->applyrichardson   = 0;
528 
529   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCFieldSplitGetSubKSP_C","PCFieldSplitGetSubKSP_FieldSplit",
530                     PCFieldSplitGetSubKSP_FieldSplit);CHKERRQ(ierr);
531   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCFieldSplitSetFields_C","PCFieldSplitSetFields_FieldSplit",
532                     PCFieldSplitSetFields_FieldSplit);CHKERRQ(ierr);
533   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCFieldSplitSetType_C","PCFieldSplitSetType_FieldSplit",
534                     PCFieldSplitSetType_FieldSplit);CHKERRQ(ierr);
535   PetscFunctionReturn(0);
536 }
537 EXTERN_C_END
538 
539 
540