xref: /petsc/src/ksp/pc/impls/fieldsplit/fieldsplit.c (revision 1b9fc7fceab7a1cd2be1962681e1587198d947cb)
10971522cSBarry Smith /*
20971522cSBarry Smith 
30971522cSBarry Smith */
40971522cSBarry Smith #include "src/ksp/pc/pcimpl.h"     /*I "petscpc.h" I*/
50971522cSBarry Smith 
60971522cSBarry Smith typedef struct _PC_FieldSplitLink *PC_FieldSplitLink;
70971522cSBarry Smith struct _PC_FieldSplitLink {
869a612a9SBarry Smith   KSP               ksp;
90971522cSBarry Smith   Vec               x,y;
100971522cSBarry Smith   PetscInt          nfields;
110971522cSBarry Smith   PetscInt          *fields;
12*1b9fc7fcSBarry Smith   VecScatter        sctx;
130971522cSBarry Smith   PC_FieldSplitLink next;
140971522cSBarry Smith };
150971522cSBarry Smith 
160971522cSBarry Smith typedef struct {
1797bbdb24SBarry Smith   PetscTruth        defaultsplit;
180971522cSBarry Smith   PetscInt          bs;
190971522cSBarry Smith   PetscInt          nsplits;
200971522cSBarry Smith   Vec               *x,*y;
2197bbdb24SBarry Smith   Mat               *pmat;
2297bbdb24SBarry Smith   IS                *is;
2397bbdb24SBarry Smith   PC_FieldSplitLink head;
240971522cSBarry Smith } PC_FieldSplit;
250971522cSBarry Smith 
260971522cSBarry Smith #undef __FUNCT__
270971522cSBarry Smith #define __FUNCT__ "PCView_FieldSplit"
280971522cSBarry Smith static PetscErrorCode PCView_FieldSplit(PC pc,PetscViewer viewer)
290971522cSBarry Smith {
300971522cSBarry Smith   PC_FieldSplit     *jac = (PC_FieldSplit*)pc->data;
310971522cSBarry Smith   PetscErrorCode    ierr;
320971522cSBarry Smith   PetscTruth        iascii;
330971522cSBarry Smith   PetscInt          i,j;
340971522cSBarry Smith   PC_FieldSplitLink link = jac->head;
350971522cSBarry Smith 
360971522cSBarry Smith   PetscFunctionBegin;
370971522cSBarry Smith   ierr = PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_ASCII,&iascii);CHKERRQ(ierr);
380971522cSBarry Smith   if (iascii) {
390971522cSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  FieldSplit: total splits = %D",jac->nsplits);CHKERRQ(ierr);
4069a612a9SBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  Solver info for each split is in the following KSP objects:\n");CHKERRQ(ierr);
410971522cSBarry Smith     ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr);
420971522cSBarry Smith     for (i=0; i<jac->nsplits; i++) {
430971522cSBarry Smith       ierr = PetscViewerASCIIPrintf(viewer,"Split number %D Fields ",i);CHKERRQ(ierr);
440971522cSBarry Smith       for (j=0; j<link->nfields; j++) {
450971522cSBarry Smith         ierr = PetscViewerASCIIPrintf(viewer,"%D \n",link->fields[j]);CHKERRQ(ierr);
460971522cSBarry Smith       }
470971522cSBarry Smith       ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr);
4869a612a9SBarry Smith       ierr = KSPView(link->ksp,viewer);CHKERRQ(ierr);
490971522cSBarry Smith       link = link->next;
500971522cSBarry Smith     }
510971522cSBarry Smith     ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr);
520971522cSBarry Smith   } else {
530971522cSBarry Smith     SETERRQ1(PETSC_ERR_SUP,"Viewer type %s not supported for PCFieldSplit",((PetscObject)viewer)->type_name);
540971522cSBarry Smith   }
550971522cSBarry Smith   PetscFunctionReturn(0);
560971522cSBarry Smith }
570971522cSBarry Smith 
580971522cSBarry Smith #undef __FUNCT__
5969a612a9SBarry Smith #define __FUNCT__ "PCFieldSplitSetDefaults"
6069a612a9SBarry Smith static PetscErrorCode PCFieldSplitSetDefaults(PC pc)
610971522cSBarry Smith {
620971522cSBarry Smith   PC_FieldSplit     *jac  = (PC_FieldSplit*)pc->data;
630971522cSBarry Smith   PetscErrorCode    ierr;
640971522cSBarry Smith   PC_FieldSplitLink link = jac->head;
6569a612a9SBarry Smith   PetscInt          i;
660971522cSBarry Smith 
670971522cSBarry Smith   PetscFunctionBegin;
6869a612a9SBarry Smith   /* user has not split fields so use default */
6969a612a9SBarry Smith   if (!link) {
70*1b9fc7fcSBarry Smith     ierr = PetscLogInfo(pc,"PCFieldSplitSetDefaults: Using default splitting of fields");CHKERRQ(ierr);
71521d7252SBarry Smith     if (jac->bs <= 0) {
72521d7252SBarry Smith       ierr   = MatGetBlockSize(pc->pmat,&jac->bs);CHKERRQ(ierr);
73521d7252SBarry Smith     }
74521d7252SBarry Smith     for (i=0; i<jac->bs; i++) {
75521d7252SBarry Smith       ierr = PCFieldSplitSetFields(pc,1,&i);CHKERRQ(ierr);
76521d7252SBarry Smith     }
77521d7252SBarry Smith     link              = jac->head;
7897bbdb24SBarry Smith     jac->defaultsplit = PETSC_TRUE;
79521d7252SBarry Smith   }
8069a612a9SBarry Smith   PetscFunctionReturn(0);
8169a612a9SBarry Smith }
8269a612a9SBarry Smith 
8369a612a9SBarry Smith 
8469a612a9SBarry Smith #undef __FUNCT__
8569a612a9SBarry Smith #define __FUNCT__ "PCSetUp_FieldSplit"
8669a612a9SBarry Smith static PetscErrorCode PCSetUp_FieldSplit(PC pc)
8769a612a9SBarry Smith {
8869a612a9SBarry Smith   PC_FieldSplit     *jac = (PC_FieldSplit*)pc->data;
8969a612a9SBarry Smith   PetscErrorCode    ierr;
9069a612a9SBarry Smith   PC_FieldSplitLink link;
9169a612a9SBarry Smith   PetscInt          i,nsplit;
9269a612a9SBarry Smith   MatStructure      flag = pc->flag;
9369a612a9SBarry Smith 
9469a612a9SBarry Smith   PetscFunctionBegin;
9569a612a9SBarry Smith   ierr   = PCFieldSplitSetDefaults(pc);CHKERRQ(ierr);
9697bbdb24SBarry Smith   nsplit = jac->nsplits;
9769a612a9SBarry Smith   link   = jac->head;
9897bbdb24SBarry Smith 
9997bbdb24SBarry Smith   /* get the matrices for each split */
10097bbdb24SBarry Smith   if (!jac->is) {
101*1b9fc7fcSBarry Smith     PetscInt rstart,rend,nslots,bs;
10297bbdb24SBarry Smith 
103*1b9fc7fcSBarry Smith     ierr   = MatGetBlockSize(pc->pmat,&bs);CHKERRQ(ierr);
10497bbdb24SBarry Smith     ierr   = MatGetOwnershipRange(pc->pmat,&rstart,&rend);CHKERRQ(ierr);
105*1b9fc7fcSBarry Smith     nslots = (rend - rstart)/bs;
106*1b9fc7fcSBarry Smith     ierr   = PetscMalloc(nsplit*sizeof(IS),&jac->is);CHKERRQ(ierr);
107*1b9fc7fcSBarry Smith     for (i=0; i<nsplit; i++) {
108*1b9fc7fcSBarry Smith       if (jac->defaultsplit) {
109*1b9fc7fcSBarry Smith 	ierr = ISCreateStride(pc->comm,nslots,rstart+i,nsplit,&jac->is[i]);CHKERRQ(ierr);
11097bbdb24SBarry Smith       } else {
111*1b9fc7fcSBarry Smith         PetscInt   *ii,j,k,nfields = link->nfields,*fields = link->fields;
112*1b9fc7fcSBarry Smith         PetscTruth sorted;
113*1b9fc7fcSBarry Smith         ierr = PetscMalloc(link->nfields*nslots*sizeof(PetscInt),&ii);CHKERRQ(ierr);
114*1b9fc7fcSBarry Smith         for (j=0; j<nslots; j++) {
115*1b9fc7fcSBarry Smith           for (k=0; k<nfields; k++) {
116*1b9fc7fcSBarry Smith             ii[nfields*j + k] = rstart + bs*j + fields[k];
11797bbdb24SBarry Smith           }
11897bbdb24SBarry Smith         }
119*1b9fc7fcSBarry Smith 	ierr = ISCreateGeneral(pc->comm,nslots*nfields,ii,&jac->is[i]);CHKERRQ(ierr);
120*1b9fc7fcSBarry Smith         ierr = ISSorted(jac->is[i],&sorted);CHKERRQ(ierr);
121*1b9fc7fcSBarry Smith         if (!sorted) SETERRQ(PETSC_ERR_USER,"Fields must be sorted when creating split");
122*1b9fc7fcSBarry Smith         ierr = PetscFree(ii);CHKERRQ(ierr);
123*1b9fc7fcSBarry Smith         link = link->next;
124*1b9fc7fcSBarry Smith       }
125*1b9fc7fcSBarry Smith     }
126*1b9fc7fcSBarry Smith   }
127*1b9fc7fcSBarry Smith 
12897bbdb24SBarry Smith   if (!jac->pmat) {
12997bbdb24SBarry Smith     ierr = MatGetSubMatrices(pc->pmat,nsplit,jac->is,jac->is,MAT_INITIAL_MATRIX,&jac->pmat);CHKERRQ(ierr);
13097bbdb24SBarry Smith   } else {
13197bbdb24SBarry Smith     ierr = MatGetSubMatrices(pc->pmat,nsplit,jac->is,jac->is,MAT_REUSE_MATRIX,&jac->pmat);CHKERRQ(ierr);
13297bbdb24SBarry Smith   }
13397bbdb24SBarry Smith 
13497bbdb24SBarry Smith   /* set up the individual PCs */
13597bbdb24SBarry Smith   i    = 0;
136*1b9fc7fcSBarry Smith   link = jac->head;
1370971522cSBarry Smith   while (link) {
13869a612a9SBarry Smith     ierr = KSPSetOperators(link->ksp,jac->pmat[i],jac->pmat[i],flag);CHKERRQ(ierr);
13969a612a9SBarry Smith     ierr = KSPSetFromOptions(link->ksp);CHKERRQ(ierr);
14069a612a9SBarry Smith     ierr = KSPSetUp(link->ksp);CHKERRQ(ierr);
14197bbdb24SBarry Smith     i++;
1420971522cSBarry Smith     link = link->next;
1430971522cSBarry Smith   }
14497bbdb24SBarry Smith 
14597bbdb24SBarry Smith   /* create work vectors for each split */
146*1b9fc7fcSBarry Smith   if (!jac->x) {
14797bbdb24SBarry Smith     ierr = PetscMalloc2(nsplit,Vec,&jac->x,nsplit,Vec,&jac->y);CHKERRQ(ierr);
14897bbdb24SBarry Smith     link = jac->head;
14997bbdb24SBarry Smith     for (i=0; i<nsplit; i++) {
15097bbdb24SBarry Smith       Mat A;
15169a612a9SBarry Smith       ierr      = KSPGetOperators(link->ksp,PETSC_NULL,&A,PETSC_NULL);CHKERRQ(ierr);
15297bbdb24SBarry Smith       ierr      = MatGetVecs(A,&link->x,&link->y);CHKERRQ(ierr);
15397bbdb24SBarry Smith       jac->x[i] = link->x;
15497bbdb24SBarry Smith       jac->y[i] = link->y;
15597bbdb24SBarry Smith       link      = link->next;
15697bbdb24SBarry Smith     }
157*1b9fc7fcSBarry Smith     if (!jac->defaultsplit) {
158*1b9fc7fcSBarry Smith       Vec xtmp;
159*1b9fc7fcSBarry Smith 
160*1b9fc7fcSBarry Smith       link = jac->head;
161*1b9fc7fcSBarry Smith       ierr = MatGetVecs(pc->pmat,&xtmp,PETSC_NULL);CHKERRQ(ierr);
162*1b9fc7fcSBarry Smith       for (i=0; i<nsplit; i++) {
163*1b9fc7fcSBarry Smith         ierr = VecScatterCreate(xtmp,jac->is[i],jac->x[i],PETSC_NULL,&link->sctx);CHKERRQ(ierr);
164*1b9fc7fcSBarry Smith         link = link->next;
165*1b9fc7fcSBarry Smith       }
166*1b9fc7fcSBarry Smith       ierr = VecDestroy(xtmp);CHKERRQ(ierr);
167*1b9fc7fcSBarry Smith     }
16897bbdb24SBarry Smith   }
1690971522cSBarry Smith   PetscFunctionReturn(0);
1700971522cSBarry Smith }
1710971522cSBarry Smith 
1720971522cSBarry Smith #undef __FUNCT__
1730971522cSBarry Smith #define __FUNCT__ "PCApply_FieldSplit"
1740971522cSBarry Smith static PetscErrorCode PCApply_FieldSplit(PC pc,Vec x,Vec y)
1750971522cSBarry Smith {
1760971522cSBarry Smith   PC_FieldSplit     *jac = (PC_FieldSplit*)pc->data;
1770971522cSBarry Smith   PetscErrorCode    ierr;
1780971522cSBarry Smith   PC_FieldSplitLink link = jac->head;
1790971522cSBarry Smith 
1800971522cSBarry Smith   PetscFunctionBegin;
181*1b9fc7fcSBarry Smith   if (jac->defaultsplit) {
1820971522cSBarry Smith     ierr = VecStrideGatherAll(x,jac->x,INSERT_VALUES);CHKERRQ(ierr);
1830971522cSBarry Smith     while (link) {
18469a612a9SBarry Smith       ierr = KSPSolve(link->ksp,link->x,link->y);CHKERRQ(ierr);
1850971522cSBarry Smith       link = link->next;
1860971522cSBarry Smith     }
1870971522cSBarry Smith     ierr = VecStrideScatterAll(jac->y,y,INSERT_VALUES);CHKERRQ(ierr);
188*1b9fc7fcSBarry Smith   } else {
189*1b9fc7fcSBarry Smith     PetscScalar zero = 0.0;
190*1b9fc7fcSBarry Smith     PetscInt    i = 0;
191*1b9fc7fcSBarry Smith 
192*1b9fc7fcSBarry Smith     ierr = VecSet(&zero,y);CHKERRQ(ierr);
193*1b9fc7fcSBarry Smith     while (link) {
194*1b9fc7fcSBarry Smith       ierr = VecScatterBegin(x,link->x,INSERT_VALUES,SCATTER_FORWARD,link->sctx);CHKERRQ(ierr);
195*1b9fc7fcSBarry Smith       ierr = VecScatterEnd(x,link->x,INSERT_VALUES,SCATTER_FORWARD,link->sctx);CHKERRQ(ierr);
196*1b9fc7fcSBarry Smith       ierr = KSPSolve(link->ksp,link->x,link->y);CHKERRQ(ierr);
197*1b9fc7fcSBarry Smith       ierr = VecScatterBegin(link->y,y,ADD_VALUES,SCATTER_REVERSE,link->sctx);CHKERRQ(ierr);
198*1b9fc7fcSBarry Smith       ierr = VecScatterEnd(y,link->y,ADD_VALUES,SCATTER_REVERSE,link->sctx);CHKERRQ(ierr);
199*1b9fc7fcSBarry Smith 
200*1b9fc7fcSBarry Smith       link = link->next;
201*1b9fc7fcSBarry Smith       i++;
202*1b9fc7fcSBarry Smith     }
203*1b9fc7fcSBarry Smith   }
2040971522cSBarry Smith   PetscFunctionReturn(0);
2050971522cSBarry Smith }
2060971522cSBarry Smith 
2070971522cSBarry Smith #undef __FUNCT__
2080971522cSBarry Smith #define __FUNCT__ "PCDestroy_FieldSplit"
2090971522cSBarry Smith static PetscErrorCode PCDestroy_FieldSplit(PC pc)
2100971522cSBarry Smith {
2110971522cSBarry Smith   PC_FieldSplit     *jac = (PC_FieldSplit*)pc->data;
2120971522cSBarry Smith   PetscErrorCode    ierr;
21397bbdb24SBarry Smith   PC_FieldSplitLink link = jac->head,next;
2140971522cSBarry Smith 
2150971522cSBarry Smith   PetscFunctionBegin;
2160971522cSBarry Smith   while (link) {
21769a612a9SBarry Smith     ierr = KSPDestroy(link->ksp);CHKERRQ(ierr);
21869a612a9SBarry Smith     if (link->x) {ierr = VecDestroy(link->x);CHKERRQ(ierr);}
21969a612a9SBarry Smith     if (link->y) {ierr = VecDestroy(link->y);CHKERRQ(ierr);}
220*1b9fc7fcSBarry Smith     if (link->sctx) {ierr = VecScatterDestroy(link->sctx);CHKERRQ(ierr);}
22197bbdb24SBarry Smith     next = link->next;
2220971522cSBarry Smith     ierr = PetscFree2(link,link->fields);CHKERRQ(ierr);
22397bbdb24SBarry Smith     link = next;
2240971522cSBarry Smith   }
2250971522cSBarry Smith   if (jac->x) {ierr = PetscFree2(jac->x,jac->y);CHKERRQ(ierr);}
22697bbdb24SBarry Smith   if (jac->pmat) {ierr = MatDestroyMatrices(jac->nsplits,&jac->pmat);CHKERRQ(ierr);}
22797bbdb24SBarry Smith   if (jac->is) {
22897bbdb24SBarry Smith     PetscInt i;
22997bbdb24SBarry Smith     for (i=0; i<jac->nsplits; i++) {ierr = ISDestroy(jac->is[i]);CHKERRQ(ierr);}
23097bbdb24SBarry Smith     ierr = PetscFree(jac->is);CHKERRQ(ierr);
23197bbdb24SBarry Smith   }
2320971522cSBarry Smith   ierr = PetscFree(jac);CHKERRQ(ierr);
2330971522cSBarry Smith   PetscFunctionReturn(0);
2340971522cSBarry Smith }
2350971522cSBarry Smith 
2360971522cSBarry Smith #undef __FUNCT__
2370971522cSBarry Smith #define __FUNCT__ "PCSetFromOptions_FieldSplit"
2380971522cSBarry Smith static PetscErrorCode PCSetFromOptions_FieldSplit(PC pc)
239*1b9fc7fcSBarry Smith /*   This does not call KSPSetFromOptions() on the subksp's, see PCSetFromOptionsBJacobi/ASM() */
2400971522cSBarry Smith {
241*1b9fc7fcSBarry Smith   PetscErrorCode ierr;
242*1b9fc7fcSBarry Smith   PetscInt       i = 0,nfields,fields[12];
243*1b9fc7fcSBarry Smith   PetscTruth     flg;
244*1b9fc7fcSBarry Smith   char           optionname[128];
245*1b9fc7fcSBarry Smith 
2460971522cSBarry Smith   PetscFunctionBegin;
247*1b9fc7fcSBarry Smith   ierr = PetscOptionsHead("FieldSplit options");CHKERRQ(ierr);
248*1b9fc7fcSBarry Smith   while (PETSC_TRUE) {
249*1b9fc7fcSBarry Smith     sprintf(optionname,"-pc_fieldsplit_%d_fields",i++);
250*1b9fc7fcSBarry Smith     nfields = 12;
251*1b9fc7fcSBarry Smith     ierr    = PetscOptionsIntArray(optionname,"Fields in this split","PCFieldSplitSetFields",fields,&nfields,&flg);CHKERRQ(ierr);
252*1b9fc7fcSBarry Smith     if (!flg) break;
253*1b9fc7fcSBarry Smith     if (!nfields) SETERRQ(PETSC_ERR_USER,"Cannot list zero fields");
254*1b9fc7fcSBarry Smith     ierr = PCFieldSplitSetFields(pc,nfields,fields);CHKERRQ(ierr);
255*1b9fc7fcSBarry Smith   }
256*1b9fc7fcSBarry Smith   ierr = PetscOptionsTail();CHKERRQ(ierr);
2570971522cSBarry Smith   PetscFunctionReturn(0);
2580971522cSBarry Smith }
2590971522cSBarry Smith 
2600971522cSBarry Smith /*------------------------------------------------------------------------------------*/
2610971522cSBarry Smith 
2620971522cSBarry Smith EXTERN_C_BEGIN
2630971522cSBarry Smith #undef __FUNCT__
2640971522cSBarry Smith #define __FUNCT__ "PCFieldSplitSetFields_FieldSplit"
2650971522cSBarry Smith PetscErrorCode PCFieldSplitSetFields_FieldSplit(PC pc,PetscInt n,PetscInt *fields)
2660971522cSBarry Smith {
26797bbdb24SBarry Smith   PC_FieldSplit     *jac = (PC_FieldSplit*)pc->data;
2680971522cSBarry Smith   PetscErrorCode    ierr;
2690971522cSBarry Smith   PC_FieldSplitLink link,next = jac->head;
27069a612a9SBarry Smith   char              prefix[128];
2710971522cSBarry Smith 
2720971522cSBarry Smith   PetscFunctionBegin;
2730971522cSBarry Smith   if (n <= 0) SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"Negative number of fields requested");
27497bbdb24SBarry Smith   ierr = PetscMalloc2(1,struct _PC_FieldSplitLink,&link,n,PetscInt,&link->fields);CHKERRQ(ierr);
27597bbdb24SBarry Smith   ierr = PetscMemcpy(link->fields,fields,n*sizeof(PetscInt));CHKERRQ(ierr);
2760971522cSBarry Smith   link->nfields = n;
27797bbdb24SBarry Smith   link->next    = PETSC_NULL;
27869a612a9SBarry Smith   ierr          = KSPCreate(pc->comm,&link->ksp);CHKERRQ(ierr);
27969a612a9SBarry Smith   ierr          = KSPSetType(link->ksp,KSPPREONLY);CHKERRQ(ierr);
28069a612a9SBarry Smith 
28169a612a9SBarry Smith   if (pc->prefix) {
28269a612a9SBarry Smith     sprintf(prefix,"%s_fieldsplit_%d_",pc->prefix,jac->nsplits);
28369a612a9SBarry Smith   } else {
28469a612a9SBarry Smith     sprintf(prefix,"fieldsplit_%d_",jac->nsplits);
28569a612a9SBarry Smith   }
28669a612a9SBarry Smith   ierr = KSPSetOptionsPrefix(link->ksp,prefix);CHKERRQ(ierr);
2870971522cSBarry Smith 
2880971522cSBarry Smith   if (!next) {
2890971522cSBarry Smith     jac->head = link;
2900971522cSBarry Smith   } else {
2910971522cSBarry Smith     while (next->next) {
2920971522cSBarry Smith       next = next->next;
2930971522cSBarry Smith     }
2940971522cSBarry Smith     next->next = link;
2950971522cSBarry Smith   }
2960971522cSBarry Smith   jac->nsplits++;
2970971522cSBarry Smith   PetscFunctionReturn(0);
2980971522cSBarry Smith }
2990971522cSBarry Smith EXTERN_C_END
3000971522cSBarry Smith 
3010971522cSBarry Smith 
3020971522cSBarry Smith EXTERN_C_BEGIN
3030971522cSBarry Smith #undef __FUNCT__
30469a612a9SBarry Smith #define __FUNCT__ "PCFieldSplitGetSubKSP_FieldSplit"
30569a612a9SBarry Smith PetscErrorCode PCFieldSplitGetSubKSP_FieldSplit(PC pc,PetscInt *n,KSP **subksp)
3060971522cSBarry Smith {
3070971522cSBarry Smith   PC_FieldSplit     *jac = (PC_FieldSplit*)pc->data;
3080971522cSBarry Smith   PetscErrorCode    ierr;
3090971522cSBarry Smith   PetscInt          cnt = 0;
3100971522cSBarry Smith   PC_FieldSplitLink link;
3110971522cSBarry Smith 
3120971522cSBarry Smith   PetscFunctionBegin;
31369a612a9SBarry Smith   ierr = PetscMalloc(jac->nsplits*sizeof(KSP*),subksp);CHKERRQ(ierr);
3140971522cSBarry Smith   while (link) {
31569a612a9SBarry Smith     (*subksp)[cnt++] = link->ksp;
3160971522cSBarry Smith     link = link->next;
3170971522cSBarry Smith   }
3180971522cSBarry Smith   if (cnt != jac->nsplits) SETERRQ2(PETSC_ERR_PLIB,"Corrupt PCFIELDSPLIT object: number splits in linked list %D in object %D",cnt,jac->nsplits);
3190971522cSBarry Smith   *n = jac->nsplits;
3200971522cSBarry Smith   PetscFunctionReturn(0);
3210971522cSBarry Smith }
3220971522cSBarry Smith EXTERN_C_END
3230971522cSBarry Smith 
3240971522cSBarry Smith #undef __FUNCT__
3250971522cSBarry Smith #define __FUNCT__ "PCFieldSplitSetFields"
3260971522cSBarry Smith /*@
3270971522cSBarry Smith     PCFieldSplitSetFields - Sets the fields for one particular split in the field split preconditioner
3280971522cSBarry Smith 
3290971522cSBarry Smith     Collective on PC
3300971522cSBarry Smith 
3310971522cSBarry Smith     Input Parameters:
3320971522cSBarry Smith +   pc  - the preconditioner context
3330971522cSBarry Smith .   n - the number of fields in this split
3340971522cSBarry Smith .   fields - the fields in this split
3350971522cSBarry Smith 
3360971522cSBarry Smith     Level: intermediate
3370971522cSBarry Smith 
33869a612a9SBarry Smith .seealso: PCFieldSplitGetSubKSP(), PCFIELDSPLIT
3390971522cSBarry Smith 
3400971522cSBarry Smith @*/
3410971522cSBarry Smith PetscErrorCode PCFieldSplitSetFields(PC pc,PetscInt n, PetscInt *fields)
3420971522cSBarry Smith {
3430971522cSBarry Smith   PetscErrorCode ierr,(*f)(PC,PetscInt,PetscInt *);
3440971522cSBarry Smith 
3450971522cSBarry Smith   PetscFunctionBegin;
3460971522cSBarry Smith   PetscValidHeaderSpecific(pc,PC_COOKIE,1);
3470971522cSBarry Smith   ierr = PetscObjectQueryFunction((PetscObject)pc,"PCFieldSplitSetFields_C",(void (**)(void))&f);CHKERRQ(ierr);
3480971522cSBarry Smith   if (f) {
3490971522cSBarry Smith     ierr = (*f)(pc,n,fields);CHKERRQ(ierr);
3500971522cSBarry Smith   }
3510971522cSBarry Smith   PetscFunctionReturn(0);
3520971522cSBarry Smith }
3530971522cSBarry Smith 
3540971522cSBarry Smith #undef __FUNCT__
35569a612a9SBarry Smith #define __FUNCT__ "PCFieldSplitGetSubKSP"
3560971522cSBarry Smith /*@C
35769a612a9SBarry Smith    PCFieldSplitGetSubKSP - Gets the KSP contexts for all splits
3580971522cSBarry Smith 
35969a612a9SBarry Smith    Collective on KSP
3600971522cSBarry Smith 
3610971522cSBarry Smith    Input Parameter:
3620971522cSBarry Smith .  pc - the preconditioner context
3630971522cSBarry Smith 
3640971522cSBarry Smith    Output Parameters:
3650971522cSBarry Smith +  n - the number of split
36669a612a9SBarry Smith -  pc - the array of KSP contexts
3670971522cSBarry Smith 
3680971522cSBarry Smith    Note:
36969a612a9SBarry Smith    After PCFieldSplitGetSubKSP() the array of KSPs IS to be freed
3700971522cSBarry Smith 
37169a612a9SBarry Smith    You must call KSPSetUp() before calling PCFieldSplitGetSubKSP().
3720971522cSBarry Smith 
3730971522cSBarry Smith    Level: advanced
3740971522cSBarry Smith 
3750971522cSBarry Smith .seealso: PCFIELDSPLIT
3760971522cSBarry Smith @*/
37769a612a9SBarry Smith PetscErrorCode PCFieldSplitGetSubKSP(PC pc,PetscInt *n,KSP *subksp[])
3780971522cSBarry Smith {
37969a612a9SBarry Smith   PetscErrorCode ierr,(*f)(PC,PetscInt*,KSP **);
3800971522cSBarry Smith 
3810971522cSBarry Smith   PetscFunctionBegin;
3820971522cSBarry Smith   PetscValidHeaderSpecific(pc,PC_COOKIE,1);
3830971522cSBarry Smith   PetscValidIntPointer(n,2);
38469a612a9SBarry Smith   ierr = PetscObjectQueryFunction((PetscObject)pc,"PCFieldSplitGetSubKSP_C",(void (**)(void))&f);CHKERRQ(ierr);
3850971522cSBarry Smith   if (f) {
38669a612a9SBarry Smith     ierr = (*f)(pc,n,subksp);CHKERRQ(ierr);
3870971522cSBarry Smith   } else {
38869a612a9SBarry Smith     SETERRQ(PETSC_ERR_ARG_WRONG,"Cannot get subksp for this type of PC");
3890971522cSBarry Smith   }
3900971522cSBarry Smith   PetscFunctionReturn(0);
3910971522cSBarry Smith }
3920971522cSBarry Smith 
3930971522cSBarry Smith /* -------------------------------------------------------------------------------------*/
3940971522cSBarry Smith /*MC
3950971522cSBarry Smith    PCFieldSplit - Preconditioner created by combining seperate preconditioners for individual
3960971522cSBarry Smith                   fields or groups of fields
3970971522cSBarry Smith 
3980971522cSBarry Smith 
3990971522cSBarry Smith      To set options on the solvers for each block append -sub_ to all the PC
4000971522cSBarry Smith         options database keys. For example, -sub_pc_type ilu -sub_pc_ilu_levels 1
4010971522cSBarry Smith 
40269a612a9SBarry Smith      To set the options on the solvers seperate for each block call PCFieldSplitGetSubKSP()
40369a612a9SBarry Smith          and set the options directly on the resulting KSP object
4040971522cSBarry Smith 
4050971522cSBarry Smith    Level: intermediate
4060971522cSBarry Smith 
4070971522cSBarry Smith    Concepts: physics based preconditioners
4080971522cSBarry Smith 
4090971522cSBarry Smith .seealso:  PCCreate(), PCSetType(), PCType (for list of available types), PC,
41069a612a9SBarry Smith            PCFieldSplitGetSubKSP(), PCFieldSplitSetFields()
4110971522cSBarry Smith M*/
4120971522cSBarry Smith 
4130971522cSBarry Smith EXTERN_C_BEGIN
4140971522cSBarry Smith #undef __FUNCT__
4150971522cSBarry Smith #define __FUNCT__ "PCCreate_FieldSplit"
4160971522cSBarry Smith PetscErrorCode PCCreate_FieldSplit(PC pc)
4170971522cSBarry Smith {
4180971522cSBarry Smith   PetscErrorCode ierr;
4190971522cSBarry Smith   PC_FieldSplit  *jac;
4200971522cSBarry Smith 
4210971522cSBarry Smith   PetscFunctionBegin;
4220971522cSBarry Smith   ierr = PetscNew(PC_FieldSplit,&jac);CHKERRQ(ierr);
4230971522cSBarry Smith   PetscLogObjectMemory(pc,sizeof(PC_FieldSplit));
4240971522cSBarry Smith   ierr = PetscMemzero(jac,sizeof(PC_FieldSplit));CHKERRQ(ierr);
4250971522cSBarry Smith   jac->bs      = -1;
4260971522cSBarry Smith   jac->nsplits = 0;
4270971522cSBarry Smith   pc->data     = (void*)jac;
4280971522cSBarry Smith 
4290971522cSBarry Smith   pc->ops->apply             = PCApply_FieldSplit;
4300971522cSBarry Smith   pc->ops->setup             = PCSetUp_FieldSplit;
4310971522cSBarry Smith   pc->ops->destroy           = PCDestroy_FieldSplit;
4320971522cSBarry Smith   pc->ops->setfromoptions    = PCSetFromOptions_FieldSplit;
4330971522cSBarry Smith   pc->ops->view              = PCView_FieldSplit;
4340971522cSBarry Smith   pc->ops->applyrichardson   = 0;
4350971522cSBarry Smith 
43669a612a9SBarry Smith   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCFieldSplitGetSubKSP_C","PCFieldSplitGetSubKSP_FieldSplit",
43769a612a9SBarry Smith                     PCFieldSplitGetSubKSP_FieldSplit);CHKERRQ(ierr);
4380971522cSBarry Smith   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCFieldSplitSetFields_C","PCFieldSplitSetFields_FieldSplit",
4390971522cSBarry Smith                     PCFieldSplitSetFields_FieldSplit);CHKERRQ(ierr);
4400971522cSBarry Smith   PetscFunctionReturn(0);
4410971522cSBarry Smith }
4420971522cSBarry Smith EXTERN_C_END
4430971522cSBarry Smith 
4440971522cSBarry Smith 
445