xref: /petsc/src/ksp/pc/impls/fieldsplit/fieldsplit.c (revision 1ab39975f6d5667e421eaadecb27851f23f8be13)
1dba47a55SKris Buschelman #define PETSCKSP_DLL
2dba47a55SKris Buschelman 
30971522cSBarry Smith /*
40971522cSBarry Smith 
50971522cSBarry Smith */
66356e834SBarry Smith #include "private/pcimpl.h"     /*I "petscpc.h" I*/
70971522cSBarry Smith 
80971522cSBarry Smith typedef struct _PC_FieldSplitLink *PC_FieldSplitLink;
90971522cSBarry Smith struct _PC_FieldSplitLink {
1069a612a9SBarry Smith   KSP               ksp;
110971522cSBarry Smith   Vec               x,y;
120971522cSBarry Smith   PetscInt          nfields;
130971522cSBarry Smith   PetscInt          *fields;
141b9fc7fcSBarry Smith   VecScatter        sctx;
15704ba839SBarry Smith   IS                is,cis;
16704ba839SBarry Smith   PetscInt          csize;
1751f519a2SBarry Smith   PC_FieldSplitLink next,previous;
180971522cSBarry Smith };
190971522cSBarry Smith 
200971522cSBarry Smith typedef struct {
2179416396SBarry Smith   PCCompositeType   type;              /* additive or multiplicative */
2297bbdb24SBarry Smith   PetscTruth        defaultsplit;
230971522cSBarry Smith   PetscInt          bs;
24704ba839SBarry Smith   PetscInt          nsplits;
2579416396SBarry Smith   Vec               *x,*y,w1,w2;
2697bbdb24SBarry Smith   Mat               *pmat;
27704ba839SBarry Smith   PetscTruth        issetup;
2897bbdb24SBarry Smith   PC_FieldSplitLink head;
290971522cSBarry Smith } PC_FieldSplit;
300971522cSBarry Smith 
3116913363SBarry Smith /*
3216913363SBarry Smith     Notes: there is no particular reason that pmat, x, and y are stored as arrays in PC_FieldSplit instead of
3316913363SBarry Smith    inside PC_FieldSplitLink, just historical. If you want to be able to add new fields after already using the
3416913363SBarry Smith    PC you could change this.
3516913363SBarry Smith */
360971522cSBarry Smith #undef __FUNCT__
370971522cSBarry Smith #define __FUNCT__ "PCView_FieldSplit"
380971522cSBarry Smith static PetscErrorCode PCView_FieldSplit(PC pc,PetscViewer viewer)
390971522cSBarry Smith {
400971522cSBarry Smith   PC_FieldSplit     *jac = (PC_FieldSplit*)pc->data;
410971522cSBarry Smith   PetscErrorCode    ierr;
420971522cSBarry Smith   PetscTruth        iascii;
430971522cSBarry Smith   PetscInt          i,j;
445a9f2f41SSatish Balay   PC_FieldSplitLink ilink = jac->head;
450971522cSBarry Smith 
460971522cSBarry Smith   PetscFunctionBegin;
470971522cSBarry Smith   ierr = PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_ASCII,&iascii);CHKERRQ(ierr);
480971522cSBarry Smith   if (iascii) {
4951f519a2SBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  FieldSplit with %s composition: total splits = %D, blocksize = %D\n",PCCompositeTypes[jac->type],jac->nsplits,jac->bs);CHKERRQ(ierr);
5069a612a9SBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  Solver info for each split is in the following KSP objects:\n");CHKERRQ(ierr);
510971522cSBarry Smith     ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr);
520971522cSBarry Smith     for (i=0; i<jac->nsplits; i++) {
53*1ab39975SBarry Smith       if (ilink->fields) {
540971522cSBarry Smith 	ierr = PetscViewerASCIIPrintf(viewer,"Split number %D Fields ",i);CHKERRQ(ierr);
5579416396SBarry Smith 	ierr = PetscViewerASCIIUseTabs(viewer,PETSC_FALSE);CHKERRQ(ierr);
565a9f2f41SSatish Balay 	for (j=0; j<ilink->nfields; j++) {
5779416396SBarry Smith 	  if (j > 0) {
5879416396SBarry Smith 	    ierr = PetscViewerASCIIPrintf(viewer,",");CHKERRQ(ierr);
5979416396SBarry Smith 	  }
605a9f2f41SSatish Balay 	  ierr = PetscViewerASCIIPrintf(viewer," %D",ilink->fields[j]);CHKERRQ(ierr);
610971522cSBarry Smith 	}
620971522cSBarry Smith 	ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr);
6379416396SBarry Smith         ierr = PetscViewerASCIIUseTabs(viewer,PETSC_TRUE);CHKERRQ(ierr);
64*1ab39975SBarry Smith       } else {
65*1ab39975SBarry Smith 	ierr = PetscViewerASCIIPrintf(viewer,"Split number %D Defined by IS\n",i);CHKERRQ(ierr);
66*1ab39975SBarry Smith       }
675a9f2f41SSatish Balay       ierr = KSPView(ilink->ksp,viewer);CHKERRQ(ierr);
685a9f2f41SSatish Balay       ilink = ilink->next;
690971522cSBarry Smith     }
700971522cSBarry Smith     ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr);
710971522cSBarry Smith   } else {
720971522cSBarry Smith     SETERRQ1(PETSC_ERR_SUP,"Viewer type %s not supported for PCFieldSplit",((PetscObject)viewer)->type_name);
730971522cSBarry Smith   }
740971522cSBarry Smith   PetscFunctionReturn(0);
750971522cSBarry Smith }
760971522cSBarry Smith 
770971522cSBarry Smith #undef __FUNCT__
7869a612a9SBarry Smith #define __FUNCT__ "PCFieldSplitSetDefaults"
7969a612a9SBarry Smith static PetscErrorCode PCFieldSplitSetDefaults(PC pc)
800971522cSBarry Smith {
810971522cSBarry Smith   PC_FieldSplit     *jac  = (PC_FieldSplit*)pc->data;
820971522cSBarry Smith   PetscErrorCode    ierr;
835a9f2f41SSatish Balay   PC_FieldSplitLink ilink = jac->head;
8469a612a9SBarry Smith   PetscInt          i;
8579416396SBarry Smith   PetscTruth        flg = PETSC_FALSE,*fields;
860971522cSBarry Smith 
870971522cSBarry Smith   PetscFunctionBegin;
887adad957SLisandro Dalcin   ierr = PetscOptionsGetTruth(((PetscObject)pc)->prefix,"-pc_fieldsplit_default",&flg,PETSC_NULL);CHKERRQ(ierr);
895a9f2f41SSatish Balay   if (!ilink || flg) {
90ae15b995SBarry Smith     ierr = PetscInfo(pc,"Using default splitting of fields\n");CHKERRQ(ierr);
91521d7252SBarry Smith     if (jac->bs <= 0) {
92704ba839SBarry Smith       if (pc->pmat) {
93521d7252SBarry Smith         ierr   = MatGetBlockSize(pc->pmat,&jac->bs);CHKERRQ(ierr);
94704ba839SBarry Smith       } else {
95704ba839SBarry Smith         jac->bs = 1;
96704ba839SBarry Smith       }
97521d7252SBarry Smith     }
9879416396SBarry Smith     ierr = PetscMalloc(jac->bs*sizeof(PetscTruth),&fields);CHKERRQ(ierr);
9979416396SBarry Smith     ierr = PetscMemzero(fields,jac->bs*sizeof(PetscTruth));CHKERRQ(ierr);
1005a9f2f41SSatish Balay     while (ilink) {
1015a9f2f41SSatish Balay       for (i=0; i<ilink->nfields; i++) {
1025a9f2f41SSatish Balay         fields[ilink->fields[i]] = PETSC_TRUE;
103521d7252SBarry Smith       }
1045a9f2f41SSatish Balay       ilink = ilink->next;
10579416396SBarry Smith     }
10697bbdb24SBarry Smith     jac->defaultsplit = PETSC_TRUE;
10779416396SBarry Smith     for (i=0; i<jac->bs; i++) {
10879416396SBarry Smith       if (!fields[i]) {
10979416396SBarry Smith 	ierr = PCFieldSplitSetFields(pc,1,&i);CHKERRQ(ierr);
11079416396SBarry Smith       } else {
11179416396SBarry Smith         jac->defaultsplit = PETSC_FALSE;
11279416396SBarry Smith       }
11379416396SBarry Smith     }
114521d7252SBarry Smith   }
11569a612a9SBarry Smith   PetscFunctionReturn(0);
11669a612a9SBarry Smith }
11769a612a9SBarry Smith 
11869a612a9SBarry Smith 
11969a612a9SBarry Smith #undef __FUNCT__
12069a612a9SBarry Smith #define __FUNCT__ "PCSetUp_FieldSplit"
12169a612a9SBarry Smith static PetscErrorCode PCSetUp_FieldSplit(PC pc)
12269a612a9SBarry Smith {
12369a612a9SBarry Smith   PC_FieldSplit     *jac = (PC_FieldSplit*)pc->data;
12469a612a9SBarry Smith   PetscErrorCode    ierr;
1255a9f2f41SSatish Balay   PC_FieldSplitLink ilink;
126cf502942SBarry Smith   PetscInt          i,nsplit,ccsize;
12769a612a9SBarry Smith   MatStructure      flag = pc->flag;
128ccb205f8SBarry Smith   PetscTruth        sorted;
12969a612a9SBarry Smith 
13069a612a9SBarry Smith   PetscFunctionBegin;
13169a612a9SBarry Smith   ierr   = PCFieldSplitSetDefaults(pc);CHKERRQ(ierr);
13297bbdb24SBarry Smith   nsplit = jac->nsplits;
1335a9f2f41SSatish Balay   ilink  = jac->head;
13497bbdb24SBarry Smith 
13597bbdb24SBarry Smith   /* get the matrices for each split */
136704ba839SBarry Smith   if (!jac->issetup) {
1371b9fc7fcSBarry Smith     PetscInt rstart,rend,nslots,bs;
13897bbdb24SBarry Smith 
139704ba839SBarry Smith     jac->issetup = PETSC_TRUE;
140704ba839SBarry Smith 
141704ba839SBarry Smith     /* This is done here instead of in PCFieldSplitSetFields() because may not have matrix at that point */
14251f519a2SBarry Smith     bs     = jac->bs;
14397bbdb24SBarry Smith     ierr   = MatGetOwnershipRange(pc->pmat,&rstart,&rend);CHKERRQ(ierr);
144cf502942SBarry Smith     ierr   = MatGetLocalSize(pc->pmat,PETSC_NULL,&ccsize);CHKERRQ(ierr);
1451b9fc7fcSBarry Smith     nslots = (rend - rstart)/bs;
1461b9fc7fcSBarry Smith     for (i=0; i<nsplit; i++) {
1471b9fc7fcSBarry Smith       if (jac->defaultsplit) {
148704ba839SBarry Smith         ierr = ISCreateStride(((PetscObject)pc)->comm,nslots,rstart+i,nsplit,&ilink->is);CHKERRQ(ierr);
149704ba839SBarry Smith         ilink->csize = ccsize/nsplit;
150704ba839SBarry Smith       } else if (!ilink->is) {
151ccb205f8SBarry Smith         if (ilink->nfields > 1) {
1525a9f2f41SSatish Balay           PetscInt   *ii,j,k,nfields = ilink->nfields,*fields = ilink->fields;
1535a9f2f41SSatish Balay           ierr = PetscMalloc(ilink->nfields*nslots*sizeof(PetscInt),&ii);CHKERRQ(ierr);
1541b9fc7fcSBarry Smith           for (j=0; j<nslots; j++) {
1551b9fc7fcSBarry Smith             for (k=0; k<nfields; k++) {
1561b9fc7fcSBarry Smith               ii[nfields*j + k] = rstart + bs*j + fields[k];
15797bbdb24SBarry Smith             }
15897bbdb24SBarry Smith           }
159704ba839SBarry Smith           ierr = ISCreateGeneral(((PetscObject)pc)->comm,nslots*nfields,ii,&ilink->is);CHKERRQ(ierr);
160ccb205f8SBarry Smith           ierr = PetscFree(ii);CHKERRQ(ierr);
161ccb205f8SBarry Smith         } else {
162704ba839SBarry Smith           ierr = ISCreateStride(((PetscObject)pc)->comm,nslots,rstart+ilink->fields[0],bs,&ilink->is);CHKERRQ(ierr);
163ccb205f8SBarry Smith         }
164704ba839SBarry Smith         ilink->csize = (ccsize/bs)*ilink->nfields;
165704ba839SBarry Smith         ierr = ISSorted(ilink->is,&sorted);CHKERRQ(ierr);
1661b9fc7fcSBarry Smith         if (!sorted) SETERRQ(PETSC_ERR_USER,"Fields must be sorted when creating split");
1671b9fc7fcSBarry Smith       }
168704ba839SBarry Smith       ierr  = ISAllGather(ilink->is,&ilink->cis);CHKERRQ(ierr);
169704ba839SBarry Smith       ilink = ilink->next;
1701b9fc7fcSBarry Smith     }
1711b9fc7fcSBarry Smith   }
1721b9fc7fcSBarry Smith 
173704ba839SBarry Smith   ilink  = jac->head;
17497bbdb24SBarry Smith   if (!jac->pmat) {
175cf502942SBarry Smith     ierr = PetscMalloc(nsplit*sizeof(Mat),&jac->pmat);CHKERRQ(ierr);
176cf502942SBarry Smith     for (i=0; i<nsplit; i++) {
177704ba839SBarry Smith       ierr = MatGetSubMatrix(pc->pmat,ilink->is,ilink->cis,ilink->csize,MAT_INITIAL_MATRIX,&jac->pmat[i]);CHKERRQ(ierr);
178704ba839SBarry Smith       ilink = ilink->next;
179cf502942SBarry Smith     }
18097bbdb24SBarry Smith   } else {
181cf502942SBarry Smith     for (i=0; i<nsplit; i++) {
182704ba839SBarry Smith       ierr = MatGetSubMatrix(pc->pmat,ilink->is,ilink->cis,ilink->csize,MAT_REUSE_MATRIX,&jac->pmat[i]);CHKERRQ(ierr);
183704ba839SBarry Smith       ilink = ilink->next;
184cf502942SBarry Smith     }
18597bbdb24SBarry Smith   }
18697bbdb24SBarry Smith 
18797bbdb24SBarry Smith   /* set up the individual PCs */
18897bbdb24SBarry Smith   i    = 0;
1895a9f2f41SSatish Balay   ilink = jac->head;
1905a9f2f41SSatish Balay   while (ilink) {
1915a9f2f41SSatish Balay     ierr = KSPSetOperators(ilink->ksp,jac->pmat[i],jac->pmat[i],flag);CHKERRQ(ierr);
1925a9f2f41SSatish Balay     ierr = KSPSetFromOptions(ilink->ksp);CHKERRQ(ierr);
1935a9f2f41SSatish Balay     ierr = KSPSetUp(ilink->ksp);CHKERRQ(ierr);
19497bbdb24SBarry Smith     i++;
1955a9f2f41SSatish Balay     ilink = ilink->next;
1960971522cSBarry Smith   }
19797bbdb24SBarry Smith 
19897bbdb24SBarry Smith   /* create work vectors for each split */
1991b9fc7fcSBarry Smith   if (!jac->x) {
20079416396SBarry Smith     Vec xtmp;
20197bbdb24SBarry Smith     ierr = PetscMalloc2(nsplit,Vec,&jac->x,nsplit,Vec,&jac->y);CHKERRQ(ierr);
2025a9f2f41SSatish Balay     ilink = jac->head;
20397bbdb24SBarry Smith     for (i=0; i<nsplit; i++) {
204906ed7ccSBarry Smith       Vec *vl,*vr;
205906ed7ccSBarry Smith 
206906ed7ccSBarry Smith       ierr      = KSPGetVecs(ilink->ksp,1,&vr,1,&vl);CHKERRQ(ierr);
207906ed7ccSBarry Smith       ilink->x  = *vr;
208906ed7ccSBarry Smith       ilink->y  = *vl;
209906ed7ccSBarry Smith       ierr      = PetscFree(vr);CHKERRQ(ierr);
210906ed7ccSBarry Smith       ierr      = PetscFree(vl);CHKERRQ(ierr);
2115a9f2f41SSatish Balay       jac->x[i] = ilink->x;
2125a9f2f41SSatish Balay       jac->y[i] = ilink->y;
2135a9f2f41SSatish Balay       ilink     = ilink->next;
21497bbdb24SBarry Smith     }
21579416396SBarry Smith     /* compute scatter contexts needed by multiplicative versions and non-default splits */
2161b9fc7fcSBarry Smith 
2175a9f2f41SSatish Balay     ilink = jac->head;
2181b9fc7fcSBarry Smith     ierr = MatGetVecs(pc->pmat,&xtmp,PETSC_NULL);CHKERRQ(ierr);
2191b9fc7fcSBarry Smith     for (i=0; i<nsplit; i++) {
220704ba839SBarry Smith       ierr = VecScatterCreate(xtmp,ilink->is,jac->x[i],PETSC_NULL,&ilink->sctx);CHKERRQ(ierr);
2215a9f2f41SSatish Balay       ilink = ilink->next;
2221b9fc7fcSBarry Smith     }
2231b9fc7fcSBarry Smith     ierr = VecDestroy(xtmp);CHKERRQ(ierr);
2241b9fc7fcSBarry Smith   }
2250971522cSBarry Smith   PetscFunctionReturn(0);
2260971522cSBarry Smith }
2270971522cSBarry Smith 
2285a9f2f41SSatish Balay #define FieldSplitSplitSolveAdd(ilink,xx,yy) \
229ca9f406cSSatish Balay     (VecScatterBegin(ilink->sctx,xx,ilink->x,INSERT_VALUES,SCATTER_FORWARD) || \
230ca9f406cSSatish Balay      VecScatterEnd(ilink->sctx,xx,ilink->x,INSERT_VALUES,SCATTER_FORWARD) || \
2315a9f2f41SSatish Balay      KSPSolve(ilink->ksp,ilink->x,ilink->y) || \
232ca9f406cSSatish Balay      VecScatterBegin(ilink->sctx,ilink->y,yy,ADD_VALUES,SCATTER_REVERSE) || \
233ca9f406cSSatish Balay      VecScatterEnd(ilink->sctx,ilink->y,yy,ADD_VALUES,SCATTER_REVERSE))
23479416396SBarry Smith 
2350971522cSBarry Smith #undef __FUNCT__
2360971522cSBarry Smith #define __FUNCT__ "PCApply_FieldSplit"
2370971522cSBarry Smith static PetscErrorCode PCApply_FieldSplit(PC pc,Vec x,Vec y)
2380971522cSBarry Smith {
2390971522cSBarry Smith   PC_FieldSplit     *jac = (PC_FieldSplit*)pc->data;
2400971522cSBarry Smith   PetscErrorCode    ierr;
2415a9f2f41SSatish Balay   PC_FieldSplitLink ilink = jac->head;
242e25d487eSBarry Smith   PetscInt          bs;
2430971522cSBarry Smith 
2440971522cSBarry Smith   PetscFunctionBegin;
24551f519a2SBarry Smith   CHKMEMQ;
246e25d487eSBarry Smith   ierr = VecGetBlockSize(x,&bs);CHKERRQ(ierr);
24751f519a2SBarry Smith   ierr = VecSetBlockSize(x,jac->bs);CHKERRQ(ierr);
24851f519a2SBarry Smith   ierr = VecSetBlockSize(y,jac->bs);CHKERRQ(ierr);
24951f519a2SBarry Smith 
25079416396SBarry Smith   if (jac->type == PC_COMPOSITE_ADDITIVE) {
2511b9fc7fcSBarry Smith     if (jac->defaultsplit) {
2520971522cSBarry Smith       ierr = VecStrideGatherAll(x,jac->x,INSERT_VALUES);CHKERRQ(ierr);
2535a9f2f41SSatish Balay       while (ilink) {
2545a9f2f41SSatish Balay 	ierr = KSPSolve(ilink->ksp,ilink->x,ilink->y);CHKERRQ(ierr);
2555a9f2f41SSatish Balay 	ilink = ilink->next;
2560971522cSBarry Smith       }
2570971522cSBarry Smith       ierr = VecStrideScatterAll(jac->y,y,INSERT_VALUES);CHKERRQ(ierr);
2581b9fc7fcSBarry Smith     } else {
259efb30889SBarry Smith       ierr = VecSet(y,0.0);CHKERRQ(ierr);
2605a9f2f41SSatish Balay       while (ilink) {
2615a9f2f41SSatish Balay         ierr = FieldSplitSplitSolveAdd(ilink,x,y);CHKERRQ(ierr);
2625a9f2f41SSatish Balay 	ilink = ilink->next;
2631b9fc7fcSBarry Smith       }
2641b9fc7fcSBarry Smith     }
26516913363SBarry Smith   } else if (jac->type == PC_COMPOSITE_MULTIPLICATIVE || jac->type == PC_COMPOSITE_SYMMETRIC_MULTIPLICATIVE) {
26679416396SBarry Smith     if (!jac->w1) {
26779416396SBarry Smith       ierr = VecDuplicate(x,&jac->w1);CHKERRQ(ierr);
26879416396SBarry Smith       ierr = VecDuplicate(x,&jac->w2);CHKERRQ(ierr);
26979416396SBarry Smith     }
270efb30889SBarry Smith     ierr = VecSet(y,0.0);CHKERRQ(ierr);
2715a9f2f41SSatish Balay     ierr = FieldSplitSplitSolveAdd(ilink,x,y);CHKERRQ(ierr);
2725a9f2f41SSatish Balay     while (ilink->next) {
2735a9f2f41SSatish Balay       ilink = ilink->next;
274*1ab39975SBarry Smith       ierr  = MatMult(pc->mat,y,jac->w1);CHKERRQ(ierr);
275efb30889SBarry Smith       ierr  = VecWAXPY(jac->w2,-1.0,jac->w1,x);CHKERRQ(ierr);
2765a9f2f41SSatish Balay       ierr  = FieldSplitSplitSolveAdd(ilink,jac->w2,y);CHKERRQ(ierr);
27779416396SBarry Smith     }
27851f519a2SBarry Smith     if (jac->type == PC_COMPOSITE_SYMMETRIC_MULTIPLICATIVE) {
27951f519a2SBarry Smith       while (ilink->previous) {
28051f519a2SBarry Smith         ilink = ilink->previous;
281*1ab39975SBarry Smith         ierr  = MatMult(pc->mat,y,jac->w1);CHKERRQ(ierr);
28251f519a2SBarry Smith         ierr  = VecWAXPY(jac->w2,-1.0,jac->w1,x);CHKERRQ(ierr);
28351f519a2SBarry Smith         ierr  = FieldSplitSplitSolveAdd(ilink,jac->w2,y);CHKERRQ(ierr);
28479416396SBarry Smith       }
28551f519a2SBarry Smith     }
28616913363SBarry Smith     } else SETERRQ1(PETSC_ERR_SUP,"Unsupported or unknown composition",(int) jac->type);
28751f519a2SBarry Smith   CHKMEMQ;
2880971522cSBarry Smith   PetscFunctionReturn(0);
2890971522cSBarry Smith }
2900971522cSBarry Smith 
291421e10b8SBarry Smith #define FieldSplitSplitSolveAddTranspose(ilink,xx,yy) \
292ca9f406cSSatish Balay     (VecScatterBegin(ilink->sctx,xx,ilink->y,INSERT_VALUES,SCATTER_FORWARD) || \
293ca9f406cSSatish Balay      VecScatterEnd(ilink->sctx,xx,ilink->y,INSERT_VALUES,SCATTER_FORWARD) || \
294421e10b8SBarry Smith      KSPSolveTranspose(ilink->ksp,ilink->y,ilink->x) || \
295ca9f406cSSatish Balay      VecScatterBegin(ilink->sctx,ilink->x,yy,ADD_VALUES,SCATTER_REVERSE) || \
296ca9f406cSSatish Balay      VecScatterEnd(ilink->sctx,ilink->x,yy,ADD_VALUES,SCATTER_REVERSE))
297421e10b8SBarry Smith 
298421e10b8SBarry Smith #undef __FUNCT__
299421e10b8SBarry Smith #define __FUNCT__ "PCApply_FieldSplit"
300421e10b8SBarry Smith static PetscErrorCode PCApplyTranspose_FieldSplit(PC pc,Vec x,Vec y)
301421e10b8SBarry Smith {
302421e10b8SBarry Smith   PC_FieldSplit     *jac = (PC_FieldSplit*)pc->data;
303421e10b8SBarry Smith   PetscErrorCode    ierr;
304421e10b8SBarry Smith   PC_FieldSplitLink ilink = jac->head;
305421e10b8SBarry Smith   PetscInt          bs;
306421e10b8SBarry Smith 
307421e10b8SBarry Smith   PetscFunctionBegin;
308421e10b8SBarry Smith   CHKMEMQ;
309421e10b8SBarry Smith   ierr = VecGetBlockSize(x,&bs);CHKERRQ(ierr);
310421e10b8SBarry Smith   ierr = VecSetBlockSize(x,jac->bs);CHKERRQ(ierr);
311421e10b8SBarry Smith   ierr = VecSetBlockSize(y,jac->bs);CHKERRQ(ierr);
312421e10b8SBarry Smith 
313421e10b8SBarry Smith   if (jac->type == PC_COMPOSITE_ADDITIVE) {
314421e10b8SBarry Smith     if (jac->defaultsplit) {
315421e10b8SBarry Smith       ierr = VecStrideGatherAll(x,jac->x,INSERT_VALUES);CHKERRQ(ierr);
316421e10b8SBarry Smith       while (ilink) {
317421e10b8SBarry Smith 	ierr = KSPSolveTranspose(ilink->ksp,ilink->x,ilink->y);CHKERRQ(ierr);
318421e10b8SBarry Smith 	ilink = ilink->next;
319421e10b8SBarry Smith       }
320421e10b8SBarry Smith       ierr = VecStrideScatterAll(jac->y,y,INSERT_VALUES);CHKERRQ(ierr);
321421e10b8SBarry Smith     } else {
322421e10b8SBarry Smith       ierr = VecSet(y,0.0);CHKERRQ(ierr);
323421e10b8SBarry Smith       while (ilink) {
324421e10b8SBarry Smith         ierr = FieldSplitSplitSolveAddTranspose(ilink,x,y);CHKERRQ(ierr);
325421e10b8SBarry Smith 	ilink = ilink->next;
326421e10b8SBarry Smith       }
327421e10b8SBarry Smith     }
328421e10b8SBarry Smith   } else {
329421e10b8SBarry Smith     if (!jac->w1) {
330421e10b8SBarry Smith       ierr = VecDuplicate(x,&jac->w1);CHKERRQ(ierr);
331421e10b8SBarry Smith       ierr = VecDuplicate(x,&jac->w2);CHKERRQ(ierr);
332421e10b8SBarry Smith     }
333421e10b8SBarry Smith     ierr = VecSet(y,0.0);CHKERRQ(ierr);
334421e10b8SBarry Smith     if (jac->type == PC_COMPOSITE_SYMMETRIC_MULTIPLICATIVE) {
335421e10b8SBarry Smith       ierr = FieldSplitSplitSolveAddTranspose(ilink,x,y);CHKERRQ(ierr);
336421e10b8SBarry Smith       while (ilink->next) {
337421e10b8SBarry Smith         ilink = ilink->next;
338421e10b8SBarry Smith         ierr  = MatMultTranspose(pc->pmat,y,jac->w1);CHKERRQ(ierr);
339421e10b8SBarry Smith         ierr  = VecWAXPY(jac->w2,-1.0,jac->w1,x);CHKERRQ(ierr);
340421e10b8SBarry Smith         ierr  = FieldSplitSplitSolveAddTranspose(ilink,jac->w2,y);CHKERRQ(ierr);
341421e10b8SBarry Smith       }
342421e10b8SBarry Smith       while (ilink->previous) {
343421e10b8SBarry Smith         ilink = ilink->previous;
344421e10b8SBarry Smith         ierr  = MatMultTranspose(pc->pmat,y,jac->w1);CHKERRQ(ierr);
345421e10b8SBarry Smith         ierr  = VecWAXPY(jac->w2,-1.0,jac->w1,x);CHKERRQ(ierr);
346421e10b8SBarry Smith         ierr  = FieldSplitSplitSolveAddTranspose(ilink,jac->w2,y);CHKERRQ(ierr);
347421e10b8SBarry Smith       }
348421e10b8SBarry Smith     } else {
349421e10b8SBarry Smith       while (ilink->next) {   /* get to last entry in linked list */
350421e10b8SBarry Smith 	ilink = ilink->next;
351421e10b8SBarry Smith       }
352421e10b8SBarry Smith       ierr = FieldSplitSplitSolveAddTranspose(ilink,x,y);CHKERRQ(ierr);
353421e10b8SBarry Smith       while (ilink->previous) {
354421e10b8SBarry Smith 	ilink = ilink->previous;
355421e10b8SBarry Smith 	ierr  = MatMultTranspose(pc->pmat,y,jac->w1);CHKERRQ(ierr);
356421e10b8SBarry Smith 	ierr  = VecWAXPY(jac->w2,-1.0,jac->w1,x);CHKERRQ(ierr);
357421e10b8SBarry Smith 	ierr  = FieldSplitSplitSolveAddTranspose(ilink,jac->w2,y);CHKERRQ(ierr);
358421e10b8SBarry Smith       }
359421e10b8SBarry Smith     }
360421e10b8SBarry Smith   }
361421e10b8SBarry Smith   CHKMEMQ;
362421e10b8SBarry Smith   PetscFunctionReturn(0);
363421e10b8SBarry Smith }
364421e10b8SBarry Smith 
3650971522cSBarry Smith #undef __FUNCT__
3660971522cSBarry Smith #define __FUNCT__ "PCDestroy_FieldSplit"
3670971522cSBarry Smith static PetscErrorCode PCDestroy_FieldSplit(PC pc)
3680971522cSBarry Smith {
3690971522cSBarry Smith   PC_FieldSplit     *jac = (PC_FieldSplit*)pc->data;
3700971522cSBarry Smith   PetscErrorCode    ierr;
3715a9f2f41SSatish Balay   PC_FieldSplitLink ilink = jac->head,next;
3720971522cSBarry Smith 
3730971522cSBarry Smith   PetscFunctionBegin;
3745a9f2f41SSatish Balay   while (ilink) {
3755a9f2f41SSatish Balay     ierr = KSPDestroy(ilink->ksp);CHKERRQ(ierr);
3765a9f2f41SSatish Balay     if (ilink->x) {ierr = VecDestroy(ilink->x);CHKERRQ(ierr);}
3775a9f2f41SSatish Balay     if (ilink->y) {ierr = VecDestroy(ilink->y);CHKERRQ(ierr);}
3785a9f2f41SSatish Balay     if (ilink->sctx) {ierr = VecScatterDestroy(ilink->sctx);CHKERRQ(ierr);}
379704ba839SBarry Smith     if (ilink->is) {ierr = ISDestroy(ilink->is);CHKERRQ(ierr);}
380704ba839SBarry Smith     if (ilink->cis) {ierr = ISDestroy(ilink->cis);CHKERRQ(ierr);}
3815a9f2f41SSatish Balay     next = ilink->next;
382704ba839SBarry Smith     ierr = PetscFree(ilink->fields);CHKERRQ(ierr);
383704ba839SBarry Smith     ierr = PetscFree(ilink);CHKERRQ(ierr);
3845a9f2f41SSatish Balay     ilink = next;
3850971522cSBarry Smith   }
38605b42c5fSBarry Smith   ierr = PetscFree2(jac->x,jac->y);CHKERRQ(ierr);
38797bbdb24SBarry Smith   if (jac->pmat) {ierr = MatDestroyMatrices(jac->nsplits,&jac->pmat);CHKERRQ(ierr);}
38879416396SBarry Smith   if (jac->w1) {ierr = VecDestroy(jac->w1);CHKERRQ(ierr);}
38979416396SBarry Smith   if (jac->w2) {ierr = VecDestroy(jac->w2);CHKERRQ(ierr);}
3900971522cSBarry Smith   ierr = PetscFree(jac);CHKERRQ(ierr);
3910971522cSBarry Smith   PetscFunctionReturn(0);
3920971522cSBarry Smith }
3930971522cSBarry Smith 
3940971522cSBarry Smith #undef __FUNCT__
3950971522cSBarry Smith #define __FUNCT__ "PCSetFromOptions_FieldSplit"
3960971522cSBarry Smith static PetscErrorCode PCSetFromOptions_FieldSplit(PC pc)
3970971522cSBarry Smith {
3981b9fc7fcSBarry Smith   PetscErrorCode ierr;
39951f519a2SBarry Smith   PetscInt       i = 0,nfields,*fields,bs;
4001b9fc7fcSBarry Smith   PetscTruth     flg;
4011b9fc7fcSBarry Smith   char           optionname[128];
4029dcbbd2bSBarry Smith   PC_FieldSplit  *jac = (PC_FieldSplit*)pc->data;
4031b9fc7fcSBarry Smith 
4040971522cSBarry Smith   PetscFunctionBegin;
4051b9fc7fcSBarry Smith   ierr = PetscOptionsHead("FieldSplit options");CHKERRQ(ierr);
40651f519a2SBarry Smith   ierr = PetscOptionsInt("-pc_fieldsplit_block_size","Blocksize that defines number of fields","PCFieldSplitSetBlockSize",jac->bs,&bs,&flg);CHKERRQ(ierr);
40751f519a2SBarry Smith   if (flg) {
40851f519a2SBarry Smith     ierr = PCFieldSplitSetBlockSize(pc,bs);CHKERRQ(ierr);
40951f519a2SBarry Smith   }
41051f519a2SBarry Smith   if (jac->bs <= 0) {
411704ba839SBarry Smith 
41251f519a2SBarry Smith     ierr = PCFieldSplitSetBlockSize(pc,1);CHKERRQ(ierr);
41351f519a2SBarry Smith   }
4149dcbbd2bSBarry Smith   ierr = PetscOptionsEnum("-pc_fieldsplit_type","Type of composition","PCFieldSplitSetType",PCCompositeTypes,(PetscEnum)jac->type,(PetscEnum*)&jac->type,&flg);CHKERRQ(ierr);
41551f519a2SBarry Smith   ierr = PetscMalloc(jac->bs*sizeof(PetscInt),&fields);CHKERRQ(ierr);
4161b9fc7fcSBarry Smith   while (PETSC_TRUE) {
41713f74950SBarry Smith     sprintf(optionname,"-pc_fieldsplit_%d_fields",(int)i++);
41851f519a2SBarry Smith     nfields = jac->bs;
4191b9fc7fcSBarry Smith     ierr    = PetscOptionsIntArray(optionname,"Fields in this split","PCFieldSplitSetFields",fields,&nfields,&flg);CHKERRQ(ierr);
4201b9fc7fcSBarry Smith     if (!flg) break;
4211b9fc7fcSBarry Smith     if (!nfields) SETERRQ(PETSC_ERR_USER,"Cannot list zero fields");
4221b9fc7fcSBarry Smith     ierr = PCFieldSplitSetFields(pc,nfields,fields);CHKERRQ(ierr);
4231b9fc7fcSBarry Smith   }
42451f519a2SBarry Smith   ierr = PetscFree(fields);CHKERRQ(ierr);
4251b9fc7fcSBarry Smith   ierr = PetscOptionsTail();CHKERRQ(ierr);
4260971522cSBarry Smith   PetscFunctionReturn(0);
4270971522cSBarry Smith }
4280971522cSBarry Smith 
4290971522cSBarry Smith /*------------------------------------------------------------------------------------*/
4300971522cSBarry Smith 
4310971522cSBarry Smith EXTERN_C_BEGIN
4320971522cSBarry Smith #undef __FUNCT__
4330971522cSBarry Smith #define __FUNCT__ "PCFieldSplitSetFields_FieldSplit"
434dba47a55SKris Buschelman PetscErrorCode PETSCKSP_DLLEXPORT PCFieldSplitSetFields_FieldSplit(PC pc,PetscInt n,PetscInt *fields)
4350971522cSBarry Smith {
43697bbdb24SBarry Smith   PC_FieldSplit     *jac = (PC_FieldSplit*)pc->data;
4370971522cSBarry Smith   PetscErrorCode    ierr;
4385a9f2f41SSatish Balay   PC_FieldSplitLink ilink,next = jac->head;
43969a612a9SBarry Smith   char              prefix[128];
44051f519a2SBarry Smith   PetscInt          i;
4410971522cSBarry Smith 
4420971522cSBarry Smith   PetscFunctionBegin;
4430971522cSBarry Smith   if (n <= 0) SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"Negative number of fields requested");
44451f519a2SBarry Smith   for (i=0; i<n; i++) {
44551f519a2SBarry Smith     if (fields[i] >= jac->bs) SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"Field %D requested but only %D exist",fields[i],jac->bs);
44651f519a2SBarry Smith     if (fields[i] < 0) SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,"Negative field %D requested",fields[i]);
44751f519a2SBarry Smith   }
448704ba839SBarry Smith   ierr = PetscNew(struct _PC_FieldSplitLink,&ilink);CHKERRQ(ierr);
449704ba839SBarry Smith   ierr = PetscMalloc(n*sizeof(PetscInt),&ilink->fields);CHKERRQ(ierr);
4505a9f2f41SSatish Balay   ierr = PetscMemcpy(ilink->fields,fields,n*sizeof(PetscInt));CHKERRQ(ierr);
4515a9f2f41SSatish Balay   ilink->nfields = n;
4525a9f2f41SSatish Balay   ilink->next    = PETSC_NULL;
4537adad957SLisandro Dalcin   ierr           = KSPCreate(((PetscObject)pc)->comm,&ilink->ksp);CHKERRQ(ierr);
4545a9f2f41SSatish Balay   ierr           = KSPSetType(ilink->ksp,KSPPREONLY);CHKERRQ(ierr);
45569a612a9SBarry Smith 
4567adad957SLisandro Dalcin   if (((PetscObject)pc)->prefix) {
4577adad957SLisandro Dalcin     sprintf(prefix,"%sfieldsplit_%d_",((PetscObject)pc)->prefix,(int)jac->nsplits);
45869a612a9SBarry Smith   } else {
45913f74950SBarry Smith     sprintf(prefix,"fieldsplit_%d_",(int)jac->nsplits);
46069a612a9SBarry Smith   }
4615a9f2f41SSatish Balay   ierr = KSPSetOptionsPrefix(ilink->ksp,prefix);CHKERRQ(ierr);
4620971522cSBarry Smith 
4630971522cSBarry Smith   if (!next) {
4645a9f2f41SSatish Balay     jac->head       = ilink;
46551f519a2SBarry Smith     ilink->previous = PETSC_NULL;
4660971522cSBarry Smith   } else {
4670971522cSBarry Smith     while (next->next) {
4680971522cSBarry Smith       next = next->next;
4690971522cSBarry Smith     }
4705a9f2f41SSatish Balay     next->next      = ilink;
47151f519a2SBarry Smith     ilink->previous = next;
4720971522cSBarry Smith   }
4730971522cSBarry Smith   jac->nsplits++;
4740971522cSBarry Smith   PetscFunctionReturn(0);
4750971522cSBarry Smith }
4760971522cSBarry Smith EXTERN_C_END
4770971522cSBarry Smith 
4780971522cSBarry Smith 
4790971522cSBarry Smith EXTERN_C_BEGIN
4800971522cSBarry Smith #undef __FUNCT__
48169a612a9SBarry Smith #define __FUNCT__ "PCFieldSplitGetSubKSP_FieldSplit"
482dba47a55SKris Buschelman PetscErrorCode PETSCKSP_DLLEXPORT PCFieldSplitGetSubKSP_FieldSplit(PC pc,PetscInt *n,KSP **subksp)
4830971522cSBarry Smith {
4840971522cSBarry Smith   PC_FieldSplit     *jac = (PC_FieldSplit*)pc->data;
4850971522cSBarry Smith   PetscErrorCode    ierr;
4860971522cSBarry Smith   PetscInt          cnt = 0;
4875a9f2f41SSatish Balay   PC_FieldSplitLink ilink = jac->head;
4880971522cSBarry Smith 
4890971522cSBarry Smith   PetscFunctionBegin;
49069a612a9SBarry Smith   ierr = PetscMalloc(jac->nsplits*sizeof(KSP*),subksp);CHKERRQ(ierr);
4915a9f2f41SSatish Balay   while (ilink) {
4925a9f2f41SSatish Balay     (*subksp)[cnt++] = ilink->ksp;
4935a9f2f41SSatish Balay     ilink = ilink->next;
4940971522cSBarry Smith   }
4950971522cSBarry Smith   if (cnt != jac->nsplits) SETERRQ2(PETSC_ERR_PLIB,"Corrupt PCFIELDSPLIT object: number splits in linked list %D in object %D",cnt,jac->nsplits);
4960971522cSBarry Smith   *n = jac->nsplits;
4970971522cSBarry Smith   PetscFunctionReturn(0);
4980971522cSBarry Smith }
4990971522cSBarry Smith EXTERN_C_END
5000971522cSBarry Smith 
501704ba839SBarry Smith EXTERN_C_BEGIN
502704ba839SBarry Smith #undef __FUNCT__
503704ba839SBarry Smith #define __FUNCT__ "PCFieldSplitSetIS_FieldSplit"
504704ba839SBarry Smith PetscErrorCode PETSCKSP_DLLEXPORT PCFieldSplitSetIS_FieldSplit(PC pc,IS is)
505704ba839SBarry Smith {
506704ba839SBarry Smith   PC_FieldSplit     *jac = (PC_FieldSplit*)pc->data;
507704ba839SBarry Smith   PetscErrorCode    ierr;
508704ba839SBarry Smith     PC_FieldSplitLink ilink, next = jac->head;
509704ba839SBarry Smith   char              prefix[128];
510704ba839SBarry Smith 
511704ba839SBarry Smith   PetscFunctionBegin;
51216913363SBarry Smith   ierr = PetscNew(struct _PC_FieldSplitLink,&ilink);CHKERRQ(ierr);
513*1ab39975SBarry Smith   ilink->is      = is;
514*1ab39975SBarry Smith   ierr           = PetscObjectReference((PetscObject)is);CHKERRQ(ierr);
515704ba839SBarry Smith   ilink->next    = PETSC_NULL;
516704ba839SBarry Smith   ierr           = KSPCreate(((PetscObject)pc)->comm,&ilink->ksp);CHKERRQ(ierr);
517704ba839SBarry Smith   ierr           = KSPSetType(ilink->ksp,KSPPREONLY);CHKERRQ(ierr);
518704ba839SBarry Smith 
519704ba839SBarry Smith   if (((PetscObject)pc)->prefix) {
520704ba839SBarry Smith     sprintf(prefix,"%sfieldsplit_%d_",((PetscObject)pc)->prefix,(int)jac->nsplits);
521704ba839SBarry Smith   } else {
522704ba839SBarry Smith     sprintf(prefix,"fieldsplit_%d_",(int)jac->nsplits);
523704ba839SBarry Smith   }
524704ba839SBarry Smith   ierr = KSPSetOptionsPrefix(ilink->ksp,prefix);CHKERRQ(ierr);
525704ba839SBarry Smith 
526704ba839SBarry Smith   if (!next) {
527704ba839SBarry Smith     jac->head       = ilink;
528704ba839SBarry Smith     ilink->previous = PETSC_NULL;
529704ba839SBarry Smith   } else {
530704ba839SBarry Smith     while (next->next) {
531704ba839SBarry Smith       next = next->next;
532704ba839SBarry Smith     }
533704ba839SBarry Smith     next->next      = ilink;
534704ba839SBarry Smith     ilink->previous = next;
535704ba839SBarry Smith   }
536704ba839SBarry Smith   jac->nsplits++;
537704ba839SBarry Smith 
538704ba839SBarry Smith   PetscFunctionReturn(0);
539704ba839SBarry Smith }
540704ba839SBarry Smith EXTERN_C_END
541704ba839SBarry Smith 
5420971522cSBarry Smith #undef __FUNCT__
5430971522cSBarry Smith #define __FUNCT__ "PCFieldSplitSetFields"
5440971522cSBarry Smith /*@
5450971522cSBarry Smith     PCFieldSplitSetFields - Sets the fields for one particular split in the field split preconditioner
5460971522cSBarry Smith 
5470971522cSBarry Smith     Collective on PC
5480971522cSBarry Smith 
5490971522cSBarry Smith     Input Parameters:
5500971522cSBarry Smith +   pc  - the preconditioner context
5510971522cSBarry Smith .   n - the number of fields in this split
5520971522cSBarry Smith .   fields - the fields in this split
5530971522cSBarry Smith 
5540971522cSBarry Smith     Level: intermediate
5550971522cSBarry Smith 
55651f519a2SBarry Smith .seealso: PCFieldSplitGetSubKSP(), PCFIELDSPLIT, PCFieldSplitSetBlockSize()
5570971522cSBarry Smith 
5580971522cSBarry Smith @*/
559dba47a55SKris Buschelman PetscErrorCode PETSCKSP_DLLEXPORT PCFieldSplitSetFields(PC pc,PetscInt n, PetscInt *fields)
5600971522cSBarry Smith {
5610971522cSBarry Smith   PetscErrorCode ierr,(*f)(PC,PetscInt,PetscInt *);
5620971522cSBarry Smith 
5630971522cSBarry Smith   PetscFunctionBegin;
5640971522cSBarry Smith   PetscValidHeaderSpecific(pc,PC_COOKIE,1);
5650971522cSBarry Smith   ierr = PetscObjectQueryFunction((PetscObject)pc,"PCFieldSplitSetFields_C",(void (**)(void))&f);CHKERRQ(ierr);
5660971522cSBarry Smith   if (f) {
5670971522cSBarry Smith     ierr = (*f)(pc,n,fields);CHKERRQ(ierr);
5680971522cSBarry Smith   }
5690971522cSBarry Smith   PetscFunctionReturn(0);
5700971522cSBarry Smith }
5710971522cSBarry Smith 
5720971522cSBarry Smith #undef __FUNCT__
573704ba839SBarry Smith #define __FUNCT__ "PCFieldSplitSetIS"
574704ba839SBarry Smith /*@
575704ba839SBarry Smith     PCFieldSplitSetIS - Sets the exact elements for field
576704ba839SBarry Smith 
577704ba839SBarry Smith     Collective on PC
578704ba839SBarry Smith 
579704ba839SBarry Smith     Input Parameters:
580704ba839SBarry Smith +   pc  - the preconditioner context
581704ba839SBarry Smith .   is - the index set that defines the vector elements in this field
582704ba839SBarry Smith 
583704ba839SBarry Smith     Level: intermediate
584704ba839SBarry Smith 
585704ba839SBarry Smith .seealso: PCFieldSplitGetSubKSP(), PCFIELDSPLIT, PCFieldSplitSetBlockSize()
586704ba839SBarry Smith 
587704ba839SBarry Smith @*/
588704ba839SBarry Smith PetscErrorCode PETSCKSP_DLLEXPORT PCFieldSplitSetIS(PC pc,IS is)
589704ba839SBarry Smith {
590704ba839SBarry Smith   PetscErrorCode ierr,(*f)(PC,IS);
591704ba839SBarry Smith 
592704ba839SBarry Smith   PetscFunctionBegin;
593704ba839SBarry Smith   PetscValidHeaderSpecific(pc,PC_COOKIE,1);
594704ba839SBarry Smith   PetscValidHeaderSpecific(is,IS_COOKIE,1);
595704ba839SBarry Smith   ierr = PetscObjectQueryFunction((PetscObject)pc,"PCFieldSplitSetIS_C",(void (**)(void))&f);CHKERRQ(ierr);
596704ba839SBarry Smith   if (f) {
597704ba839SBarry Smith     ierr = (*f)(pc,is);CHKERRQ(ierr);
598704ba839SBarry Smith   }
599704ba839SBarry Smith   PetscFunctionReturn(0);
600704ba839SBarry Smith }
601704ba839SBarry Smith 
602704ba839SBarry Smith #undef __FUNCT__
60351f519a2SBarry Smith #define __FUNCT__ "PCFieldSplitSetBlockSize"
60451f519a2SBarry Smith /*@
60551f519a2SBarry Smith     PCFieldSplitSetBlockSize - Sets the block size for defining where fields start in the
60651f519a2SBarry Smith       fieldsplit preconditioner. If not set the matrix block size is used.
60751f519a2SBarry Smith 
60851f519a2SBarry Smith     Collective on PC
60951f519a2SBarry Smith 
61051f519a2SBarry Smith     Input Parameters:
61151f519a2SBarry Smith +   pc  - the preconditioner context
61251f519a2SBarry Smith -   bs - the block size
61351f519a2SBarry Smith 
61451f519a2SBarry Smith     Level: intermediate
61551f519a2SBarry Smith 
61651f519a2SBarry Smith .seealso: PCFieldSplitGetSubKSP(), PCFIELDSPLIT, PCFieldSplitSetFields()
61751f519a2SBarry Smith 
61851f519a2SBarry Smith @*/
61951f519a2SBarry Smith PetscErrorCode PETSCKSP_DLLEXPORT PCFieldSplitSetBlockSize(PC pc,PetscInt bs)
62051f519a2SBarry Smith {
62151f519a2SBarry Smith   PetscErrorCode ierr,(*f)(PC,PetscInt);
62251f519a2SBarry Smith 
62351f519a2SBarry Smith   PetscFunctionBegin;
62451f519a2SBarry Smith   PetscValidHeaderSpecific(pc,PC_COOKIE,1);
62551f519a2SBarry Smith   ierr = PetscObjectQueryFunction((PetscObject)pc,"PCFieldSplitSetBlockSize_C",(void (**)(void))&f);CHKERRQ(ierr);
62651f519a2SBarry Smith   if (f) {
62751f519a2SBarry Smith     ierr = (*f)(pc,bs);CHKERRQ(ierr);
62851f519a2SBarry Smith   }
62951f519a2SBarry Smith   PetscFunctionReturn(0);
63051f519a2SBarry Smith }
63151f519a2SBarry Smith 
63251f519a2SBarry Smith #undef __FUNCT__
63369a612a9SBarry Smith #define __FUNCT__ "PCFieldSplitGetSubKSP"
6340971522cSBarry Smith /*@C
63569a612a9SBarry Smith    PCFieldSplitGetSubKSP - Gets the KSP contexts for all splits
6360971522cSBarry Smith 
63769a612a9SBarry Smith    Collective on KSP
6380971522cSBarry Smith 
6390971522cSBarry Smith    Input Parameter:
6400971522cSBarry Smith .  pc - the preconditioner context
6410971522cSBarry Smith 
6420971522cSBarry Smith    Output Parameters:
6430971522cSBarry Smith +  n - the number of split
64469a612a9SBarry Smith -  pc - the array of KSP contexts
6450971522cSBarry Smith 
6460971522cSBarry Smith    Note:
64769a612a9SBarry Smith    After PCFieldSplitGetSubKSP() the array of KSPs IS to be freed
6480971522cSBarry Smith 
64969a612a9SBarry Smith    You must call KSPSetUp() before calling PCFieldSplitGetSubKSP().
6500971522cSBarry Smith 
6510971522cSBarry Smith    Level: advanced
6520971522cSBarry Smith 
6530971522cSBarry Smith .seealso: PCFIELDSPLIT
6540971522cSBarry Smith @*/
655dba47a55SKris Buschelman PetscErrorCode PETSCKSP_DLLEXPORT PCFieldSplitGetSubKSP(PC pc,PetscInt *n,KSP *subksp[])
6560971522cSBarry Smith {
65769a612a9SBarry Smith   PetscErrorCode ierr,(*f)(PC,PetscInt*,KSP **);
6580971522cSBarry Smith 
6590971522cSBarry Smith   PetscFunctionBegin;
6600971522cSBarry Smith   PetscValidHeaderSpecific(pc,PC_COOKIE,1);
6610971522cSBarry Smith   PetscValidIntPointer(n,2);
66269a612a9SBarry Smith   ierr = PetscObjectQueryFunction((PetscObject)pc,"PCFieldSplitGetSubKSP_C",(void (**)(void))&f);CHKERRQ(ierr);
6630971522cSBarry Smith   if (f) {
66469a612a9SBarry Smith     ierr = (*f)(pc,n,subksp);CHKERRQ(ierr);
6650971522cSBarry Smith   } else {
66669a612a9SBarry Smith     SETERRQ(PETSC_ERR_ARG_WRONG,"Cannot get subksp for this type of PC");
6670971522cSBarry Smith   }
6680971522cSBarry Smith   PetscFunctionReturn(0);
6690971522cSBarry Smith }
6700971522cSBarry Smith 
67179416396SBarry Smith EXTERN_C_BEGIN
67279416396SBarry Smith #undef __FUNCT__
67379416396SBarry Smith #define __FUNCT__ "PCFieldSplitSetType_FieldSplit"
674dba47a55SKris Buschelman PetscErrorCode PETSCKSP_DLLEXPORT PCFieldSplitSetType_FieldSplit(PC pc,PCCompositeType type)
67579416396SBarry Smith {
67679416396SBarry Smith   PC_FieldSplit  *jac = (PC_FieldSplit*)pc->data;
67779416396SBarry Smith 
67879416396SBarry Smith   PetscFunctionBegin;
67979416396SBarry Smith   jac->type = type;
68079416396SBarry Smith   PetscFunctionReturn(0);
68179416396SBarry Smith }
68279416396SBarry Smith EXTERN_C_END
68379416396SBarry Smith 
68451f519a2SBarry Smith EXTERN_C_BEGIN
68551f519a2SBarry Smith #undef __FUNCT__
68651f519a2SBarry Smith #define __FUNCT__ "PCFieldSplitSetBlockSize_FieldSplit"
68751f519a2SBarry Smith PetscErrorCode PETSCKSP_DLLEXPORT PCFieldSplitSetBlockSize_FieldSplit(PC pc,PetscInt bs)
68851f519a2SBarry Smith {
68951f519a2SBarry Smith   PC_FieldSplit  *jac = (PC_FieldSplit*)pc->data;
69051f519a2SBarry Smith 
69151f519a2SBarry Smith   PetscFunctionBegin;
69251f519a2SBarry Smith   if (bs < 1) SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,"Blocksize must be positive, you gave %D",bs);
69351f519a2SBarry Smith   if (jac->bs > 0 && jac->bs != bs) SETERRQ2(PETSC_ERR_ARG_WRONGSTATE,"Cannot change fieldsplit blocksize from %D to %D after it has been set",jac->bs,bs);
69451f519a2SBarry Smith   jac->bs = bs;
69551f519a2SBarry Smith   PetscFunctionReturn(0);
69651f519a2SBarry Smith }
69751f519a2SBarry Smith EXTERN_C_END
69851f519a2SBarry Smith 
69979416396SBarry Smith #undef __FUNCT__
70079416396SBarry Smith #define __FUNCT__ "PCFieldSplitSetType"
701bc08b0f1SBarry Smith /*@
70279416396SBarry Smith    PCFieldSplitSetType - Sets the type of fieldsplit preconditioner.
70379416396SBarry Smith 
70479416396SBarry Smith    Collective on PC
70579416396SBarry Smith 
70679416396SBarry Smith    Input Parameter:
70779416396SBarry Smith .  pc - the preconditioner context
708ce9499c7SBarry Smith .  type - PC_COMPOSITE_ADDITIVE (default), PC_COMPOSITE_MULTIPLICATIVE, PC_COMPOSITE_SYMMETRIC_MULTIPLICATIVE
70979416396SBarry Smith 
71079416396SBarry Smith    Options Database Key:
711ce9499c7SBarry Smith .  -pc_fieldsplit_type <type: one of multiplicative, additive, symmetric_multiplicative, special> - Sets fieldsplit preconditioner type
71279416396SBarry Smith 
71379416396SBarry Smith    Level: Developer
71479416396SBarry Smith 
71579416396SBarry Smith .keywords: PC, set, type, composite preconditioner, additive, multiplicative
71679416396SBarry Smith 
71779416396SBarry Smith .seealso: PCCompositeSetType()
71879416396SBarry Smith 
71979416396SBarry Smith @*/
720dba47a55SKris Buschelman PetscErrorCode PETSCKSP_DLLEXPORT PCFieldSplitSetType(PC pc,PCCompositeType type)
72179416396SBarry Smith {
72279416396SBarry Smith   PetscErrorCode ierr,(*f)(PC,PCCompositeType);
72379416396SBarry Smith 
72479416396SBarry Smith   PetscFunctionBegin;
72579416396SBarry Smith   PetscValidHeaderSpecific(pc,PC_COOKIE,1);
72679416396SBarry Smith   ierr = PetscObjectQueryFunction((PetscObject)pc,"PCFieldSplitSetType_C",(void (**)(void))&f);CHKERRQ(ierr);
72779416396SBarry Smith   if (f) {
72879416396SBarry Smith     ierr = (*f)(pc,type);CHKERRQ(ierr);
72979416396SBarry Smith   }
73079416396SBarry Smith   PetscFunctionReturn(0);
73179416396SBarry Smith }
73279416396SBarry Smith 
7330971522cSBarry Smith /* -------------------------------------------------------------------------------------*/
7340971522cSBarry Smith /*MC
735a8c7a070SBarry Smith    PCFIELDSPLIT - Preconditioner created by combining separate preconditioners for individual
7360971522cSBarry Smith                   fields or groups of fields
7370971522cSBarry Smith 
7380971522cSBarry Smith 
7390971522cSBarry Smith      To set options on the solvers for each block append -sub_ to all the PC
740d7ee0231SBarry Smith         options database keys. For example, -sub_pc_type ilu -sub_pc_factor_levels 1
7410971522cSBarry Smith 
742a8c7a070SBarry Smith      To set the options on the solvers separate for each block call PCFieldSplitGetSubKSP()
74369a612a9SBarry Smith          and set the options directly on the resulting KSP object
7440971522cSBarry Smith 
7450971522cSBarry Smith    Level: intermediate
7460971522cSBarry Smith 
74779416396SBarry Smith    Options Database Keys:
7482e70eadcSBarry Smith +   -pc_splitfield_%d_fields <a,b,..> - indicates the fields to be used in the %d'th split
7492e70eadcSBarry Smith .   -pc_splitfield_default - automatically add any fields to additional splits that have not
7502e70eadcSBarry Smith                               been supplied explicitly by -pc_splitfield_%d_fields
75151f519a2SBarry Smith .   -pc_splitfield_block_size <bs> - size of block that defines fields (i.e. there are bs fields)
7522e70eadcSBarry Smith -   -pc_splitfield_type <additive,multiplicative>
75379416396SBarry Smith 
7540971522cSBarry Smith    Concepts: physics based preconditioners
7550971522cSBarry Smith 
7560971522cSBarry Smith .seealso:  PCCreate(), PCSetType(), PCType (for list of available types), PC,
757c8d321e0SBarry Smith            PCFieldSplitGetSubKSP(), PCFieldSplitSetFields(),PCFieldSplitSetType()
7580971522cSBarry Smith M*/
7590971522cSBarry Smith 
7600971522cSBarry Smith EXTERN_C_BEGIN
7610971522cSBarry Smith #undef __FUNCT__
7620971522cSBarry Smith #define __FUNCT__ "PCCreate_FieldSplit"
763dba47a55SKris Buschelman PetscErrorCode PETSCKSP_DLLEXPORT PCCreate_FieldSplit(PC pc)
7640971522cSBarry Smith {
7650971522cSBarry Smith   PetscErrorCode ierr;
7660971522cSBarry Smith   PC_FieldSplit  *jac;
7670971522cSBarry Smith 
7680971522cSBarry Smith   PetscFunctionBegin;
76938f2d2fdSLisandro Dalcin   ierr = PetscNewLog(pc,PC_FieldSplit,&jac);CHKERRQ(ierr);
7700971522cSBarry Smith   jac->bs        = -1;
7710971522cSBarry Smith   jac->nsplits   = 0;
77279416396SBarry Smith   jac->type      = PC_COMPOSITE_ADDITIVE;
77351f519a2SBarry Smith 
7740971522cSBarry Smith   pc->data     = (void*)jac;
7750971522cSBarry Smith 
7760971522cSBarry Smith   pc->ops->apply             = PCApply_FieldSplit;
777421e10b8SBarry Smith   pc->ops->applytranspose    = PCApplyTranspose_FieldSplit;
7780971522cSBarry Smith   pc->ops->setup             = PCSetUp_FieldSplit;
7790971522cSBarry Smith   pc->ops->destroy           = PCDestroy_FieldSplit;
7800971522cSBarry Smith   pc->ops->setfromoptions    = PCSetFromOptions_FieldSplit;
7810971522cSBarry Smith   pc->ops->view              = PCView_FieldSplit;
7820971522cSBarry Smith   pc->ops->applyrichardson   = 0;
7830971522cSBarry Smith 
78469a612a9SBarry Smith   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCFieldSplitGetSubKSP_C","PCFieldSplitGetSubKSP_FieldSplit",
78569a612a9SBarry Smith                     PCFieldSplitGetSubKSP_FieldSplit);CHKERRQ(ierr);
7860971522cSBarry Smith   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCFieldSplitSetFields_C","PCFieldSplitSetFields_FieldSplit",
7870971522cSBarry Smith                     PCFieldSplitSetFields_FieldSplit);CHKERRQ(ierr);
788704ba839SBarry Smith   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCFieldSplitSetIS_C","PCFieldSplitSetIS_FieldSplit",
789704ba839SBarry Smith                     PCFieldSplitSetIS_FieldSplit);CHKERRQ(ierr);
79079416396SBarry Smith   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCFieldSplitSetType_C","PCFieldSplitSetType_FieldSplit",
79179416396SBarry Smith                     PCFieldSplitSetType_FieldSplit);CHKERRQ(ierr);
79251f519a2SBarry Smith   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCFieldSplitSetBlockSize_C","PCFieldSplitSetBlockSize_FieldSplit",
79351f519a2SBarry Smith                     PCFieldSplitSetBlockSize_FieldSplit);CHKERRQ(ierr);
7940971522cSBarry Smith   PetscFunctionReturn(0);
7950971522cSBarry Smith }
7960971522cSBarry Smith EXTERN_C_END
7970971522cSBarry Smith 
7980971522cSBarry Smith 
799