xref: /petsc/src/ksp/pc/impls/fieldsplit/fieldsplit.c (revision 6c8605c20e1aa455e2aaafc5c0b2c57b04d60bad)
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 
8084e4875SJed Brown const char *PCFieldSplitSchurPreTypes[] = {"self","diag","user","PCFieldSplitSchurPreType","PC_FIELDSPLIT_SCHUR_PRE_",0};
9084e4875SJed Brown 
100971522cSBarry Smith typedef struct _PC_FieldSplitLink *PC_FieldSplitLink;
110971522cSBarry Smith struct _PC_FieldSplitLink {
1269a612a9SBarry Smith   KSP               ksp;
130971522cSBarry Smith   Vec               x,y;
140971522cSBarry Smith   PetscInt          nfields;
150971522cSBarry Smith   PetscInt          *fields;
161b9fc7fcSBarry Smith   VecScatter        sctx;
174aa3045dSJed Brown   IS                is;
1851f519a2SBarry Smith   PC_FieldSplitLink next,previous;
190971522cSBarry Smith };
200971522cSBarry Smith 
210971522cSBarry Smith typedef struct {
2268dd23aaSBarry Smith   PCCompositeType   type;
23a4efd8eaSMatthew Knepley   PetscTruth        defaultsplit; /* Flag for a system with a set of 'k' scalar fields with the same layout (and bs = k) */
24519d70e2SJed Brown   PetscTruth        realdiagonal; /* Flag to use the diagonal blocks of mat preconditioned by pmat, instead of just pmat */
2530ad9308SMatthew Knepley   PetscInt          bs;           /* Block size for IS and Mat structures */
2630ad9308SMatthew Knepley   PetscInt          nsplits;      /* Number of field divisions defined */
2779416396SBarry Smith   Vec               *x,*y,w1,w2;
28519d70e2SJed Brown   Mat               *mat;         /* The diagonal block for each split */
29519d70e2SJed Brown   Mat               *pmat;        /* The preconditioning diagonal block for each split */
3030ad9308SMatthew Knepley   Mat               *Afield;      /* The rows of the matrix associated with each split */
31704ba839SBarry Smith   PetscTruth        issetup;
3230ad9308SMatthew Knepley   /* Only used when Schur complement preconditioning is used */
3330ad9308SMatthew Knepley   Mat               B;            /* The (0,1) block */
3430ad9308SMatthew Knepley   Mat               C;            /* The (1,0) block */
3530ad9308SMatthew Knepley   Mat               schur;        /* The Schur complement S = D - C A^{-1} B */
36084e4875SJed Brown   Mat               schur_user;   /* User-provided preconditioning matrix for the Schur complement */
37084e4875SJed Brown   PCFieldSplitSchurPreType schurpre; /* Determines which preconditioning matrix is used for the Schur complement */
3830ad9308SMatthew Knepley   KSP               kspschur;     /* The solver for S */
3997bbdb24SBarry Smith   PC_FieldSplitLink head;
400971522cSBarry Smith } PC_FieldSplit;
410971522cSBarry Smith 
4216913363SBarry Smith /*
4316913363SBarry Smith     Notes: there is no particular reason that pmat, x, and y are stored as arrays in PC_FieldSplit instead of
4416913363SBarry Smith    inside PC_FieldSplitLink, just historical. If you want to be able to add new fields after already using the
4516913363SBarry Smith    PC you could change this.
4616913363SBarry Smith */
47084e4875SJed Brown 
48e6cab6aaSJed Brown /* This helper is so that setting a user-provided preconditioning matrix is orthogonal to choosing to use it.  This way the
49084e4875SJed Brown * application-provided FormJacobian can provide this matrix without interfering with the user's (command-line) choices. */
50084e4875SJed Brown static Mat FieldSplitSchurPre(PC_FieldSplit *jac)
51084e4875SJed Brown {
52084e4875SJed Brown   switch (jac->schurpre) {
53084e4875SJed Brown     case PC_FIELDSPLIT_SCHUR_PRE_SELF: return jac->schur;
54084e4875SJed Brown     case PC_FIELDSPLIT_SCHUR_PRE_DIAG: return jac->pmat[1];
55084e4875SJed Brown     case PC_FIELDSPLIT_SCHUR_PRE_USER: /* Use a user-provided matrix if it is given, otherwise diagonal block */
56084e4875SJed Brown     default:
57084e4875SJed Brown       return jac->schur_user ? jac->schur_user : jac->pmat[1];
58084e4875SJed Brown   }
59084e4875SJed Brown }
60084e4875SJed Brown 
61084e4875SJed Brown 
620971522cSBarry Smith #undef __FUNCT__
630971522cSBarry Smith #define __FUNCT__ "PCView_FieldSplit"
640971522cSBarry Smith static PetscErrorCode PCView_FieldSplit(PC pc,PetscViewer viewer)
650971522cSBarry Smith {
660971522cSBarry Smith   PC_FieldSplit     *jac = (PC_FieldSplit*)pc->data;
670971522cSBarry Smith   PetscErrorCode    ierr;
680971522cSBarry Smith   PetscTruth        iascii;
690971522cSBarry Smith   PetscInt          i,j;
705a9f2f41SSatish Balay   PC_FieldSplitLink ilink = jac->head;
710971522cSBarry Smith 
720971522cSBarry Smith   PetscFunctionBegin;
730971522cSBarry Smith   ierr = PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_ASCII,&iascii);CHKERRQ(ierr);
740971522cSBarry Smith   if (iascii) {
7551f519a2SBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  FieldSplit with %s composition: total splits = %D, blocksize = %D\n",PCCompositeTypes[jac->type],jac->nsplits,jac->bs);CHKERRQ(ierr);
7669a612a9SBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  Solver info for each split is in the following KSP objects:\n");CHKERRQ(ierr);
770971522cSBarry Smith     ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr);
780971522cSBarry Smith     for (i=0; i<jac->nsplits; i++) {
791ab39975SBarry Smith       if (ilink->fields) {
800971522cSBarry Smith 	ierr = PetscViewerASCIIPrintf(viewer,"Split number %D Fields ",i);CHKERRQ(ierr);
8179416396SBarry Smith 	ierr = PetscViewerASCIIUseTabs(viewer,PETSC_FALSE);CHKERRQ(ierr);
825a9f2f41SSatish Balay 	for (j=0; j<ilink->nfields; j++) {
8379416396SBarry Smith 	  if (j > 0) {
8479416396SBarry Smith 	    ierr = PetscViewerASCIIPrintf(viewer,",");CHKERRQ(ierr);
8579416396SBarry Smith 	  }
865a9f2f41SSatish Balay 	  ierr = PetscViewerASCIIPrintf(viewer," %D",ilink->fields[j]);CHKERRQ(ierr);
870971522cSBarry Smith 	}
880971522cSBarry Smith 	ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr);
8979416396SBarry Smith         ierr = PetscViewerASCIIUseTabs(viewer,PETSC_TRUE);CHKERRQ(ierr);
901ab39975SBarry Smith       } else {
911ab39975SBarry Smith 	ierr = PetscViewerASCIIPrintf(viewer,"Split number %D Defined by IS\n",i);CHKERRQ(ierr);
921ab39975SBarry Smith       }
935a9f2f41SSatish Balay       ierr = KSPView(ilink->ksp,viewer);CHKERRQ(ierr);
945a9f2f41SSatish Balay       ilink = ilink->next;
950971522cSBarry Smith     }
960971522cSBarry Smith     ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr);
970971522cSBarry Smith   } else {
980971522cSBarry Smith     SETERRQ1(PETSC_ERR_SUP,"Viewer type %s not supported for PCFieldSplit",((PetscObject)viewer)->type_name);
990971522cSBarry Smith   }
1000971522cSBarry Smith   PetscFunctionReturn(0);
1010971522cSBarry Smith }
1020971522cSBarry Smith 
1030971522cSBarry Smith #undef __FUNCT__
1043b224e63SBarry Smith #define __FUNCT__ "PCView_FieldSplit_Schur"
1053b224e63SBarry Smith static PetscErrorCode PCView_FieldSplit_Schur(PC pc,PetscViewer viewer)
1063b224e63SBarry Smith {
1073b224e63SBarry Smith   PC_FieldSplit     *jac = (PC_FieldSplit*)pc->data;
1083b224e63SBarry Smith   PetscErrorCode    ierr;
1093b224e63SBarry Smith   PetscTruth        iascii;
1103b224e63SBarry Smith   PetscInt          i,j;
1113b224e63SBarry Smith   PC_FieldSplitLink ilink = jac->head;
1123b224e63SBarry Smith   KSP               ksp;
1133b224e63SBarry Smith 
1143b224e63SBarry Smith   PetscFunctionBegin;
1153b224e63SBarry Smith   ierr = PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_ASCII,&iascii);CHKERRQ(ierr);
1163b224e63SBarry Smith   if (iascii) {
1173b224e63SBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  FieldSplit with Schur preconditioner, blocksize = %D\n",jac->bs);CHKERRQ(ierr);
1183b224e63SBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  Split info:\n");CHKERRQ(ierr);
1193b224e63SBarry Smith     ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr);
1203b224e63SBarry Smith     for (i=0; i<jac->nsplits; i++) {
1213b224e63SBarry Smith       if (ilink->fields) {
1223b224e63SBarry Smith 	ierr = PetscViewerASCIIPrintf(viewer,"Split number %D Fields ",i);CHKERRQ(ierr);
1233b224e63SBarry Smith 	ierr = PetscViewerASCIIUseTabs(viewer,PETSC_FALSE);CHKERRQ(ierr);
1243b224e63SBarry Smith 	for (j=0; j<ilink->nfields; j++) {
1253b224e63SBarry Smith 	  if (j > 0) {
1263b224e63SBarry Smith 	    ierr = PetscViewerASCIIPrintf(viewer,",");CHKERRQ(ierr);
1273b224e63SBarry Smith 	  }
1283b224e63SBarry Smith 	  ierr = PetscViewerASCIIPrintf(viewer," %D",ilink->fields[j]);CHKERRQ(ierr);
1293b224e63SBarry Smith 	}
1303b224e63SBarry Smith 	ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr);
1313b224e63SBarry Smith         ierr = PetscViewerASCIIUseTabs(viewer,PETSC_TRUE);CHKERRQ(ierr);
1323b224e63SBarry Smith       } else {
1333b224e63SBarry Smith 	ierr = PetscViewerASCIIPrintf(viewer,"Split number %D Defined by IS\n",i);CHKERRQ(ierr);
1343b224e63SBarry Smith       }
1353b224e63SBarry Smith       ilink = ilink->next;
1363b224e63SBarry Smith     }
1373b224e63SBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"KSP solver for A block \n");CHKERRQ(ierr);
1383b224e63SBarry Smith     ierr = MatSchurComplementGetKSP(jac->schur,&ksp);CHKERRQ(ierr);
1393b224e63SBarry Smith     ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr);
1403b224e63SBarry Smith     ierr = KSPView(ksp,viewer);CHKERRQ(ierr);
1413b224e63SBarry Smith     ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr);
1423b224e63SBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"KSP solver for S = D - C inv(A) B \n");CHKERRQ(ierr);
1433b224e63SBarry Smith     ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr);
1443b224e63SBarry Smith     ierr = KSPView(jac->kspschur,viewer);CHKERRQ(ierr);
1453b224e63SBarry Smith     ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr);
1463b224e63SBarry Smith     ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr);
1473b224e63SBarry Smith   } else {
1483b224e63SBarry Smith     SETERRQ1(PETSC_ERR_SUP,"Viewer type %s not supported for PCFieldSplit",((PetscObject)viewer)->type_name);
1493b224e63SBarry Smith   }
1503b224e63SBarry Smith   PetscFunctionReturn(0);
1513b224e63SBarry Smith }
1523b224e63SBarry Smith 
1533b224e63SBarry Smith #undef __FUNCT__
15469a612a9SBarry Smith #define __FUNCT__ "PCFieldSplitSetDefaults"
15569a612a9SBarry Smith static PetscErrorCode PCFieldSplitSetDefaults(PC pc)
1560971522cSBarry Smith {
1570971522cSBarry Smith   PC_FieldSplit     *jac  = (PC_FieldSplit*)pc->data;
1580971522cSBarry Smith   PetscErrorCode    ierr;
1595a9f2f41SSatish Balay   PC_FieldSplitLink ilink = jac->head;
160d32f9abdSBarry Smith   PetscInt          i = 0,*ifields,nfields;
161d32f9abdSBarry Smith   PetscTruth        flg = PETSC_FALSE,*fields,flg2;
162d32f9abdSBarry Smith   char              optionname[128];
1630971522cSBarry Smith 
1640971522cSBarry Smith   PetscFunctionBegin;
165d32f9abdSBarry Smith   if (!ilink) {
166d32f9abdSBarry Smith 
167521d7252SBarry Smith     if (jac->bs <= 0) {
168704ba839SBarry Smith       if (pc->pmat) {
169521d7252SBarry Smith         ierr   = MatGetBlockSize(pc->pmat,&jac->bs);CHKERRQ(ierr);
170704ba839SBarry Smith       } else {
171704ba839SBarry Smith         jac->bs = 1;
172704ba839SBarry Smith       }
173521d7252SBarry Smith     }
174d32f9abdSBarry Smith 
175d32f9abdSBarry Smith     ierr = PetscOptionsGetTruth(((PetscObject)pc)->prefix,"-pc_fieldsplit_default",&flg,PETSC_NULL);CHKERRQ(ierr);
176d32f9abdSBarry Smith     if (!flg) {
177d32f9abdSBarry Smith       /* Allow user to set fields from command line,  if bs was known at the time of PCSetFromOptions_FieldSplit()
178d32f9abdSBarry Smith          then it is set there. This is not ideal because we should only have options set in XXSetFromOptions(). */
179d32f9abdSBarry Smith       flg = PETSC_TRUE; /* switched off automatically if user sets fields manually here */
180d32f9abdSBarry Smith       ierr = PetscMalloc(jac->bs*sizeof(PetscInt),&ifields);CHKERRQ(ierr);
181d32f9abdSBarry Smith       while (PETSC_TRUE) {
182d32f9abdSBarry Smith         sprintf(optionname,"-pc_fieldsplit_%d_fields",(int)i++);
183d32f9abdSBarry Smith         nfields = jac->bs;
184d32f9abdSBarry Smith         ierr    = PetscOptionsGetIntArray(((PetscObject)pc)->prefix,optionname,ifields,&nfields,&flg2);CHKERRQ(ierr);
185d32f9abdSBarry Smith         if (!flg2) break;
186d32f9abdSBarry Smith         if (!nfields) SETERRQ(PETSC_ERR_USER,"Cannot list zero fields");
187d32f9abdSBarry Smith         flg = PETSC_FALSE;
188d32f9abdSBarry Smith         ierr = PCFieldSplitSetFields(pc,nfields,ifields);CHKERRQ(ierr);
189d32f9abdSBarry Smith       }
190d32f9abdSBarry Smith       ierr = PetscFree(ifields);CHKERRQ(ierr);
191d32f9abdSBarry Smith     }
192d32f9abdSBarry Smith 
193d32f9abdSBarry Smith     if (flg) {
194d32f9abdSBarry Smith       ierr = PetscInfo(pc,"Using default splitting of fields\n");CHKERRQ(ierr);
19579416396SBarry Smith       ierr = PetscMalloc(jac->bs*sizeof(PetscTruth),&fields);CHKERRQ(ierr);
19679416396SBarry Smith       ierr = PetscMemzero(fields,jac->bs*sizeof(PetscTruth));CHKERRQ(ierr);
1975a9f2f41SSatish Balay       while (ilink) {
1985a9f2f41SSatish Balay 	for (i=0; i<ilink->nfields; i++) {
1995a9f2f41SSatish Balay 	  fields[ilink->fields[i]] = PETSC_TRUE;
200521d7252SBarry Smith 	}
2015a9f2f41SSatish Balay 	ilink = ilink->next;
20279416396SBarry Smith       }
20397bbdb24SBarry Smith       jac->defaultsplit = PETSC_TRUE;
20479416396SBarry Smith       for (i=0; i<jac->bs; i++) {
20579416396SBarry Smith 	if (!fields[i]) {
20679416396SBarry Smith 	  ierr = PCFieldSplitSetFields(pc,1,&i);CHKERRQ(ierr);
20779416396SBarry Smith 	} else {
20879416396SBarry Smith 	  jac->defaultsplit = PETSC_FALSE;
20979416396SBarry Smith 	}
21079416396SBarry Smith       }
21168dd23aaSBarry Smith       ierr = PetscFree(fields);CHKERRQ(ierr);
212521d7252SBarry Smith     }
213edf189efSBarry Smith   } else if (jac->nsplits == 1) {
214edf189efSBarry Smith     if (ilink->is) {
215edf189efSBarry Smith       IS       is2;
216edf189efSBarry Smith       PetscInt nmin,nmax;
217edf189efSBarry Smith 
218edf189efSBarry Smith       ierr = MatGetOwnershipRange(pc->mat,&nmin,&nmax);CHKERRQ(ierr);
219edf189efSBarry Smith       ierr = ISComplement(ilink->is,nmin,nmax,&is2);CHKERRQ(ierr);
220edf189efSBarry Smith       ierr = PCFieldSplitSetIS(pc,is2);CHKERRQ(ierr);
221edf189efSBarry Smith       ierr = ISDestroy(is2);CHKERRQ(ierr);
222edf189efSBarry Smith     } else {
223edf189efSBarry Smith       SETERRQ(PETSC_ERR_SUP,"Must provide at least two sets of fields to PCFieldSplit()");
224edf189efSBarry Smith     }
225d32f9abdSBarry Smith   }
22669a612a9SBarry Smith   PetscFunctionReturn(0);
22769a612a9SBarry Smith }
22869a612a9SBarry Smith 
22969a612a9SBarry Smith 
23069a612a9SBarry Smith #undef __FUNCT__
23169a612a9SBarry Smith #define __FUNCT__ "PCSetUp_FieldSplit"
23269a612a9SBarry Smith static PetscErrorCode PCSetUp_FieldSplit(PC pc)
23369a612a9SBarry Smith {
23469a612a9SBarry Smith   PC_FieldSplit     *jac = (PC_FieldSplit*)pc->data;
23569a612a9SBarry Smith   PetscErrorCode    ierr;
2365a9f2f41SSatish Balay   PC_FieldSplitLink ilink;
237cf502942SBarry Smith   PetscInt          i,nsplit,ccsize;
23869a612a9SBarry Smith   MatStructure      flag = pc->flag;
239*6c8605c2SJed Brown   PetscTruth        sorted;
24069a612a9SBarry Smith 
24169a612a9SBarry Smith   PetscFunctionBegin;
24269a612a9SBarry Smith   ierr   = PCFieldSplitSetDefaults(pc);CHKERRQ(ierr);
24397bbdb24SBarry Smith   nsplit = jac->nsplits;
2445a9f2f41SSatish Balay   ilink  = jac->head;
24597bbdb24SBarry Smith 
24697bbdb24SBarry Smith   /* get the matrices for each split */
247704ba839SBarry Smith   if (!jac->issetup) {
2481b9fc7fcSBarry Smith     PetscInt rstart,rend,nslots,bs;
24997bbdb24SBarry Smith 
250704ba839SBarry Smith     jac->issetup = PETSC_TRUE;
251704ba839SBarry Smith 
252704ba839SBarry Smith     /* This is done here instead of in PCFieldSplitSetFields() because may not have matrix at that point */
25351f519a2SBarry Smith     bs     = jac->bs;
25497bbdb24SBarry Smith     ierr   = MatGetOwnershipRange(pc->pmat,&rstart,&rend);CHKERRQ(ierr);
255cf502942SBarry Smith     ierr   = MatGetLocalSize(pc->pmat,PETSC_NULL,&ccsize);CHKERRQ(ierr);
2561b9fc7fcSBarry Smith     nslots = (rend - rstart)/bs;
2571b9fc7fcSBarry Smith     for (i=0; i<nsplit; i++) {
2581b9fc7fcSBarry Smith       if (jac->defaultsplit) {
259704ba839SBarry Smith         ierr = ISCreateStride(((PetscObject)pc)->comm,nslots,rstart+i,nsplit,&ilink->is);CHKERRQ(ierr);
260704ba839SBarry Smith       } else if (!ilink->is) {
261ccb205f8SBarry Smith         if (ilink->nfields > 1) {
2625a9f2f41SSatish Balay           PetscInt   *ii,j,k,nfields = ilink->nfields,*fields = ilink->fields;
2635a9f2f41SSatish Balay           ierr = PetscMalloc(ilink->nfields*nslots*sizeof(PetscInt),&ii);CHKERRQ(ierr);
2641b9fc7fcSBarry Smith           for (j=0; j<nslots; j++) {
2651b9fc7fcSBarry Smith             for (k=0; k<nfields; k++) {
2661b9fc7fcSBarry Smith               ii[nfields*j + k] = rstart + bs*j + fields[k];
26797bbdb24SBarry Smith             }
26897bbdb24SBarry Smith           }
269704ba839SBarry Smith           ierr = ISCreateGeneral(((PetscObject)pc)->comm,nslots*nfields,ii,&ilink->is);CHKERRQ(ierr);
270ccb205f8SBarry Smith           ierr = PetscFree(ii);CHKERRQ(ierr);
271ccb205f8SBarry Smith         } else {
272704ba839SBarry Smith           ierr = ISCreateStride(((PetscObject)pc)->comm,nslots,rstart+ilink->fields[0],bs,&ilink->is);CHKERRQ(ierr);
273ccb205f8SBarry Smith         }
2743e197d65SBarry Smith       }
275704ba839SBarry Smith       ierr = ISSorted(ilink->is,&sorted);CHKERRQ(ierr);
2761b9fc7fcSBarry Smith       if (!sorted) SETERRQ(PETSC_ERR_USER,"Fields must be sorted when creating split");
277704ba839SBarry Smith       ilink = ilink->next;
2781b9fc7fcSBarry Smith     }
2791b9fc7fcSBarry Smith   }
2801b9fc7fcSBarry Smith 
281704ba839SBarry Smith   ilink  = jac->head;
28297bbdb24SBarry Smith   if (!jac->pmat) {
283cf502942SBarry Smith     ierr = PetscMalloc(nsplit*sizeof(Mat),&jac->pmat);CHKERRQ(ierr);
284cf502942SBarry Smith     for (i=0; i<nsplit; i++) {
2854aa3045dSJed Brown       ierr = MatGetSubMatrix(pc->pmat,ilink->is,ilink->is,MAT_INITIAL_MATRIX,&jac->pmat[i]);CHKERRQ(ierr);
286704ba839SBarry Smith       ilink = ilink->next;
287cf502942SBarry Smith     }
28897bbdb24SBarry Smith   } else {
289cf502942SBarry Smith     for (i=0; i<nsplit; i++) {
2904aa3045dSJed Brown       ierr = MatGetSubMatrix(pc->pmat,ilink->is,ilink->is,MAT_REUSE_MATRIX,&jac->pmat[i]);CHKERRQ(ierr);
291704ba839SBarry Smith       ilink = ilink->next;
292cf502942SBarry Smith     }
29397bbdb24SBarry Smith   }
294519d70e2SJed Brown   if (jac->realdiagonal) {
295519d70e2SJed Brown     ilink = jac->head;
296519d70e2SJed Brown     if (!jac->mat) {
297519d70e2SJed Brown       ierr = PetscMalloc(nsplit*sizeof(Mat),&jac->mat);CHKERRQ(ierr);
298519d70e2SJed Brown       for (i=0; i<nsplit; i++) {
299519d70e2SJed Brown         ierr = MatGetSubMatrix(pc->mat,ilink->is,ilink->is,MAT_INITIAL_MATRIX,&jac->mat[i]);CHKERRQ(ierr);
300519d70e2SJed Brown         ilink = ilink->next;
301519d70e2SJed Brown       }
302519d70e2SJed Brown     } else {
303519d70e2SJed Brown       for (i=0; i<nsplit; i++) {
304519d70e2SJed Brown         ierr = MatGetSubMatrix(pc->mat,ilink->is,ilink->is,MAT_REUSE_MATRIX,&jac->mat[i]);CHKERRQ(ierr);
305519d70e2SJed Brown         ilink = ilink->next;
306519d70e2SJed Brown       }
307519d70e2SJed Brown     }
308519d70e2SJed Brown   } else {
309519d70e2SJed Brown     jac->mat = jac->pmat;
310519d70e2SJed Brown   }
31197bbdb24SBarry Smith 
312*6c8605c2SJed Brown   if (jac->type != PC_COMPOSITE_ADDITIVE  && jac->type != PC_COMPOSITE_SCHUR) {
31368dd23aaSBarry Smith     /* extract the rows of the matrix associated with each field: used for efficient computation of residual inside algorithm */
31468dd23aaSBarry Smith     ilink  = jac->head;
31568dd23aaSBarry Smith     if (!jac->Afield) {
31668dd23aaSBarry Smith       ierr = PetscMalloc(nsplit*sizeof(Mat),&jac->Afield);CHKERRQ(ierr);
31768dd23aaSBarry Smith       for (i=0; i<nsplit; i++) {
3184aa3045dSJed Brown         ierr = MatGetSubMatrix(pc->mat,ilink->is,PETSC_NULL,MAT_INITIAL_MATRIX,&jac->Afield[i]);CHKERRQ(ierr);
31968dd23aaSBarry Smith         ilink = ilink->next;
32068dd23aaSBarry Smith       }
32168dd23aaSBarry Smith     } else {
32268dd23aaSBarry Smith       for (i=0; i<nsplit; i++) {
3234aa3045dSJed Brown         ierr = MatGetSubMatrix(pc->mat,ilink->is,PETSC_NULL,MAT_REUSE_MATRIX,&jac->Afield[i]);CHKERRQ(ierr);
32468dd23aaSBarry Smith         ilink = ilink->next;
32568dd23aaSBarry Smith       }
32668dd23aaSBarry Smith     }
32768dd23aaSBarry Smith   }
32868dd23aaSBarry Smith 
3293b224e63SBarry Smith   if (jac->type == PC_COMPOSITE_SCHUR) {
3303b224e63SBarry Smith     IS       ccis;
3314aa3045dSJed Brown     PetscInt rstart,rend;
3323b224e63SBarry Smith     if (nsplit != 2) SETERRQ(PETSC_ERR_ARG_INCOMP,"To use Schur complement preconditioner you must have exactly 2 fields");
33368dd23aaSBarry Smith 
334e6cab6aaSJed Brown     /* When extracting off-diagonal submatrices, we take complements from this range */
335e6cab6aaSJed Brown     ierr  = MatGetOwnershipRangeColumn(pc->mat,&rstart,&rend);CHKERRQ(ierr);
336e6cab6aaSJed Brown 
3373b224e63SBarry Smith     /* need to handle case when one is resetting up the preconditioner */
3383b224e63SBarry Smith     if (jac->schur) {
3393b224e63SBarry Smith       ilink = jac->head;
3404aa3045dSJed Brown       ierr  = ISComplement(ilink->is,rstart,rend,&ccis);CHKERRQ(ierr);
3414aa3045dSJed Brown       ierr  = MatGetSubMatrix(pc->mat,ilink->is,ccis,MAT_REUSE_MATRIX,&jac->B);CHKERRQ(ierr);
3423b224e63SBarry Smith       ierr  = ISDestroy(ccis);CHKERRQ(ierr);
3433b224e63SBarry Smith       ilink = ilink->next;
3444aa3045dSJed Brown       ierr  = ISComplement(ilink->is,rstart,rend,&ccis);CHKERRQ(ierr);
3454aa3045dSJed Brown       ierr  = MatGetSubMatrix(pc->mat,ilink->is,ccis,MAT_REUSE_MATRIX,&jac->C);CHKERRQ(ierr);
3463b224e63SBarry Smith       ierr  = ISDestroy(ccis);CHKERRQ(ierr);
347519d70e2SJed Brown       ierr  = MatSchurComplementUpdate(jac->schur,jac->mat[0],jac->pmat[0],jac->B,jac->C,jac->pmat[1],pc->flag);CHKERRQ(ierr);
348084e4875SJed Brown       ierr  = KSPSetOperators(jac->kspschur,jac->schur,FieldSplitSchurPre(jac),pc->flag);CHKERRQ(ierr);
3493b224e63SBarry Smith 
3503b224e63SBarry Smith      } else {
3511cee3971SBarry Smith       KSP ksp;
3523b224e63SBarry Smith 
3533b224e63SBarry Smith       /* extract the B and C matrices */
3543b224e63SBarry Smith       ilink = jac->head;
3554aa3045dSJed Brown       ierr  = ISComplement(ilink->is,rstart,rend,&ccis);CHKERRQ(ierr);
3564aa3045dSJed Brown       ierr  = MatGetSubMatrix(pc->mat,ilink->is,ccis,MAT_INITIAL_MATRIX,&jac->B);CHKERRQ(ierr);
3573b224e63SBarry Smith       ierr  = ISDestroy(ccis);CHKERRQ(ierr);
3583b224e63SBarry Smith       ilink = ilink->next;
3594aa3045dSJed Brown       ierr  = ISComplement(ilink->is,rstart,rend,&ccis);CHKERRQ(ierr);
3604aa3045dSJed Brown       ierr  = MatGetSubMatrix(pc->mat,ilink->is,ccis,MAT_INITIAL_MATRIX,&jac->C);CHKERRQ(ierr);
3613b224e63SBarry Smith       ierr  = ISDestroy(ccis);CHKERRQ(ierr);
362084e4875SJed Brown       /* Better would be to use 'mat[0]' (diagonal block of the real matrix) preconditioned by pmat[0] */
363519d70e2SJed Brown       ierr  = MatCreateSchurComplement(jac->mat[0],jac->pmat[0],jac->B,jac->C,jac->mat[1],&jac->schur);CHKERRQ(ierr);
3641cee3971SBarry Smith       ierr  = MatSchurComplementGetKSP(jac->schur,&ksp);CHKERRQ(ierr);
365e69d4d44SBarry Smith       ierr  = PetscObjectIncrementTabLevel((PetscObject)ksp,(PetscObject)pc,2);CHKERRQ(ierr);
3663b224e63SBarry Smith       ierr  = MatSetFromOptions(jac->schur);CHKERRQ(ierr);
3673b224e63SBarry Smith 
3683b224e63SBarry Smith       ierr  = KSPCreate(((PetscObject)pc)->comm,&jac->kspschur);CHKERRQ(ierr);
3691cee3971SBarry Smith       ierr  = PetscObjectIncrementTabLevel((PetscObject)jac->kspschur,(PetscObject)pc,1);CHKERRQ(ierr);
370084e4875SJed Brown       ierr  = KSPSetOperators(jac->kspschur,jac->schur,FieldSplitSchurPre(jac),DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
371084e4875SJed Brown       if (jac->schurpre == PC_FIELDSPLIT_SCHUR_PRE_SELF) {
372084e4875SJed Brown         PC pc;
373084e4875SJed Brown         ierr = KSPGetPC(ksp,&pc);CHKERRQ(ierr);
374084e4875SJed Brown         ierr = PCSetType(pc,PCNONE);CHKERRQ(ierr);
375084e4875SJed Brown         /* Note: This is bad if there exist preconditioners for MATSCHURCOMPLEMENT */
376e69d4d44SBarry Smith       }
3773b224e63SBarry Smith       ierr  = KSPSetOptionsPrefix(jac->kspschur,((PetscObject)pc)->prefix);CHKERRQ(ierr);
378edf189efSBarry Smith       ierr  = KSPAppendOptionsPrefix(jac->kspschur,"fieldsplit_1_");CHKERRQ(ierr);
3793b224e63SBarry Smith       /* really want setfromoptions called in PCSetFromOptions_FieldSplit(), but it is not ready yet */
3803b224e63SBarry Smith       ierr = KSPSetFromOptions(jac->kspschur);CHKERRQ(ierr);
3813b224e63SBarry Smith 
3823b224e63SBarry Smith       ierr = PetscMalloc2(2,Vec,&jac->x,2,Vec,&jac->y);CHKERRQ(ierr);
3833b224e63SBarry Smith       ierr = MatGetVecs(jac->pmat[0],&jac->x[0],&jac->y[0]);CHKERRQ(ierr);
3843b224e63SBarry Smith       ierr = MatGetVecs(jac->pmat[1],&jac->x[1],&jac->y[1]);CHKERRQ(ierr);
3853b224e63SBarry Smith       ilink = jac->head;
3863b224e63SBarry Smith       ilink->x = jac->x[0]; ilink->y = jac->y[0];
3873b224e63SBarry Smith       ilink = ilink->next;
3883b224e63SBarry Smith       ilink->x = jac->x[1]; ilink->y = jac->y[1];
3893b224e63SBarry Smith     }
3903b224e63SBarry Smith   } else {
39197bbdb24SBarry Smith     /* set up the individual PCs */
39297bbdb24SBarry Smith     i    = 0;
3935a9f2f41SSatish Balay     ilink = jac->head;
3945a9f2f41SSatish Balay     while (ilink) {
395519d70e2SJed Brown       ierr = KSPSetOperators(ilink->ksp,jac->mat[i],jac->pmat[i],flag);CHKERRQ(ierr);
3963b224e63SBarry Smith       /* really want setfromoptions called in PCSetFromOptions_FieldSplit(), but it is not ready yet */
3975a9f2f41SSatish Balay       ierr = KSPSetFromOptions(ilink->ksp);CHKERRQ(ierr);
3985a9f2f41SSatish Balay       ierr = KSPSetUp(ilink->ksp);CHKERRQ(ierr);
39997bbdb24SBarry Smith       i++;
4005a9f2f41SSatish Balay       ilink = ilink->next;
4010971522cSBarry Smith     }
40297bbdb24SBarry Smith 
40397bbdb24SBarry Smith     /* create work vectors for each split */
4041b9fc7fcSBarry Smith     if (!jac->x) {
40597bbdb24SBarry Smith       ierr = PetscMalloc2(nsplit,Vec,&jac->x,nsplit,Vec,&jac->y);CHKERRQ(ierr);
4065a9f2f41SSatish Balay       ilink = jac->head;
40797bbdb24SBarry Smith       for (i=0; i<nsplit; i++) {
408906ed7ccSBarry Smith         Vec *vl,*vr;
409906ed7ccSBarry Smith 
410906ed7ccSBarry Smith         ierr      = KSPGetVecs(ilink->ksp,1,&vr,1,&vl);CHKERRQ(ierr);
411906ed7ccSBarry Smith         ilink->x  = *vr;
412906ed7ccSBarry Smith         ilink->y  = *vl;
413906ed7ccSBarry Smith         ierr      = PetscFree(vr);CHKERRQ(ierr);
414906ed7ccSBarry Smith         ierr      = PetscFree(vl);CHKERRQ(ierr);
4155a9f2f41SSatish Balay         jac->x[i] = ilink->x;
4165a9f2f41SSatish Balay         jac->y[i] = ilink->y;
4175a9f2f41SSatish Balay         ilink     = ilink->next;
41897bbdb24SBarry Smith       }
4193b224e63SBarry Smith     }
4203b224e63SBarry Smith   }
4213b224e63SBarry Smith 
4223b224e63SBarry Smith 
423d0f46423SBarry Smith   if (!jac->head->sctx) {
4243b224e63SBarry Smith     Vec xtmp;
4253b224e63SBarry Smith 
42679416396SBarry Smith     /* compute scatter contexts needed by multiplicative versions and non-default splits */
4271b9fc7fcSBarry Smith 
4285a9f2f41SSatish Balay     ilink = jac->head;
4291b9fc7fcSBarry Smith     ierr = MatGetVecs(pc->pmat,&xtmp,PETSC_NULL);CHKERRQ(ierr);
4301b9fc7fcSBarry Smith     for (i=0; i<nsplit; i++) {
431704ba839SBarry Smith       ierr = VecScatterCreate(xtmp,ilink->is,jac->x[i],PETSC_NULL,&ilink->sctx);CHKERRQ(ierr);
4325a9f2f41SSatish Balay       ilink = ilink->next;
4331b9fc7fcSBarry Smith     }
4341b9fc7fcSBarry Smith     ierr = VecDestroy(xtmp);CHKERRQ(ierr);
4351b9fc7fcSBarry Smith   }
4360971522cSBarry Smith   PetscFunctionReturn(0);
4370971522cSBarry Smith }
4380971522cSBarry Smith 
4395a9f2f41SSatish Balay #define FieldSplitSplitSolveAdd(ilink,xx,yy) \
440ca9f406cSSatish Balay     (VecScatterBegin(ilink->sctx,xx,ilink->x,INSERT_VALUES,SCATTER_FORWARD) || \
441ca9f406cSSatish Balay      VecScatterEnd(ilink->sctx,xx,ilink->x,INSERT_VALUES,SCATTER_FORWARD) || \
4425a9f2f41SSatish Balay      KSPSolve(ilink->ksp,ilink->x,ilink->y) || \
443ca9f406cSSatish Balay      VecScatterBegin(ilink->sctx,ilink->y,yy,ADD_VALUES,SCATTER_REVERSE) || \
444ca9f406cSSatish Balay      VecScatterEnd(ilink->sctx,ilink->y,yy,ADD_VALUES,SCATTER_REVERSE))
44579416396SBarry Smith 
4460971522cSBarry Smith #undef __FUNCT__
4473b224e63SBarry Smith #define __FUNCT__ "PCApply_FieldSplit_Schur"
4483b224e63SBarry Smith static PetscErrorCode PCApply_FieldSplit_Schur(PC pc,Vec x,Vec y)
4493b224e63SBarry Smith {
4503b224e63SBarry Smith   PC_FieldSplit     *jac = (PC_FieldSplit*)pc->data;
4513b224e63SBarry Smith   PetscErrorCode    ierr;
4523b224e63SBarry Smith   KSP               ksp;
4533b224e63SBarry Smith   PC_FieldSplitLink ilinkA = jac->head, ilinkD = ilinkA->next;
4543b224e63SBarry Smith 
4553b224e63SBarry Smith   PetscFunctionBegin;
4563b224e63SBarry Smith   ierr = MatSchurComplementGetKSP(jac->schur,&ksp);CHKERRQ(ierr);
4573b224e63SBarry Smith 
4583b224e63SBarry Smith   ierr = VecScatterBegin(ilinkA->sctx,x,ilinkA->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
4593b224e63SBarry Smith   ierr = VecScatterEnd(ilinkA->sctx,x,ilinkA->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
4603b224e63SBarry Smith   ierr = KSPSolve(ksp,ilinkA->x,ilinkA->y);CHKERRQ(ierr);
4613b224e63SBarry Smith   ierr = MatMult(jac->C,ilinkA->y,ilinkD->x);CHKERRQ(ierr);
4623b224e63SBarry Smith   ierr = VecScale(ilinkD->x,-1.0);CHKERRQ(ierr);
4633b224e63SBarry Smith   ierr = VecScatterBegin(ilinkD->sctx,x,ilinkD->x,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
4643b224e63SBarry Smith   ierr = VecScatterEnd(ilinkD->sctx,x,ilinkD->x,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
4653b224e63SBarry Smith 
4663b224e63SBarry Smith   ierr = KSPSolve(jac->kspschur,ilinkD->x,ilinkD->y);CHKERRQ(ierr);
4673b224e63SBarry Smith   ierr = VecScatterBegin(ilinkD->sctx,ilinkD->y,y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
4683b224e63SBarry Smith   ierr = VecScatterEnd(ilinkD->sctx,ilinkD->y,y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
4693b224e63SBarry Smith 
4703b224e63SBarry Smith   ierr = MatMult(jac->B,ilinkD->y,ilinkA->y);CHKERRQ(ierr);
4713b224e63SBarry Smith   ierr = VecAXPY(ilinkA->x,-1.0,ilinkA->y);CHKERRQ(ierr);
4723b224e63SBarry Smith   ierr = KSPSolve(ksp,ilinkA->x,ilinkA->y);CHKERRQ(ierr);
4733b224e63SBarry Smith   ierr = VecScatterBegin(ilinkA->sctx,ilinkA->y,y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
4743b224e63SBarry Smith   ierr = VecScatterEnd(ilinkA->sctx,ilinkA->y,y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
4753b224e63SBarry Smith 
4763b224e63SBarry Smith   PetscFunctionReturn(0);
4773b224e63SBarry Smith }
4783b224e63SBarry Smith 
4793b224e63SBarry Smith #undef __FUNCT__
4800971522cSBarry Smith #define __FUNCT__ "PCApply_FieldSplit"
4810971522cSBarry Smith static PetscErrorCode PCApply_FieldSplit(PC pc,Vec x,Vec y)
4820971522cSBarry Smith {
4830971522cSBarry Smith   PC_FieldSplit     *jac = (PC_FieldSplit*)pc->data;
4840971522cSBarry Smith   PetscErrorCode    ierr;
4855a9f2f41SSatish Balay   PC_FieldSplitLink ilink = jac->head;
486af93645bSJed Brown   PetscInt          cnt;
4870971522cSBarry Smith 
4880971522cSBarry Smith   PetscFunctionBegin;
48951f519a2SBarry Smith   CHKMEMQ;
49051f519a2SBarry Smith   ierr = VecSetBlockSize(x,jac->bs);CHKERRQ(ierr);
49151f519a2SBarry Smith   ierr = VecSetBlockSize(y,jac->bs);CHKERRQ(ierr);
49251f519a2SBarry Smith 
49379416396SBarry Smith   if (jac->type == PC_COMPOSITE_ADDITIVE) {
4941b9fc7fcSBarry Smith     if (jac->defaultsplit) {
4950971522cSBarry Smith       ierr = VecStrideGatherAll(x,jac->x,INSERT_VALUES);CHKERRQ(ierr);
4965a9f2f41SSatish Balay       while (ilink) {
4975a9f2f41SSatish Balay         ierr = KSPSolve(ilink->ksp,ilink->x,ilink->y);CHKERRQ(ierr);
4985a9f2f41SSatish Balay         ilink = ilink->next;
4990971522cSBarry Smith       }
5000971522cSBarry Smith       ierr = VecStrideScatterAll(jac->y,y,INSERT_VALUES);CHKERRQ(ierr);
5011b9fc7fcSBarry Smith     } else {
502efb30889SBarry Smith       ierr = VecSet(y,0.0);CHKERRQ(ierr);
5035a9f2f41SSatish Balay       while (ilink) {
5045a9f2f41SSatish Balay         ierr = FieldSplitSplitSolveAdd(ilink,x,y);CHKERRQ(ierr);
5055a9f2f41SSatish Balay         ilink = ilink->next;
5061b9fc7fcSBarry Smith       }
5071b9fc7fcSBarry Smith     }
50816913363SBarry Smith   } else if (jac->type == PC_COMPOSITE_MULTIPLICATIVE || jac->type == PC_COMPOSITE_SYMMETRIC_MULTIPLICATIVE) {
50979416396SBarry Smith     if (!jac->w1) {
51079416396SBarry Smith       ierr = VecDuplicate(x,&jac->w1);CHKERRQ(ierr);
51179416396SBarry Smith       ierr = VecDuplicate(x,&jac->w2);CHKERRQ(ierr);
51279416396SBarry Smith     }
513efb30889SBarry Smith     ierr = VecSet(y,0.0);CHKERRQ(ierr);
5145a9f2f41SSatish Balay     ierr = FieldSplitSplitSolveAdd(ilink,x,y);CHKERRQ(ierr);
5153e197d65SBarry Smith     cnt = 1;
5165a9f2f41SSatish Balay     while (ilink->next) {
5175a9f2f41SSatish Balay       ilink = ilink->next;
5183e197d65SBarry Smith       /* compute the residual only over the part of the vector needed */
5193e197d65SBarry Smith       ierr = MatMult(jac->Afield[cnt++],y,ilink->x);CHKERRQ(ierr);
5203e197d65SBarry Smith       ierr = VecScale(ilink->x,-1.0);CHKERRQ(ierr);
5213e197d65SBarry Smith       ierr = VecScatterBegin(ilink->sctx,x,ilink->x,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5223e197d65SBarry Smith       ierr = VecScatterEnd(ilink->sctx,x,ilink->x,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5233e197d65SBarry Smith       ierr = KSPSolve(ilink->ksp,ilink->x,ilink->y);CHKERRQ(ierr);
5243e197d65SBarry Smith       ierr = VecScatterBegin(ilink->sctx,ilink->y,y,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5253e197d65SBarry Smith       ierr = VecScatterEnd(ilink->sctx,ilink->y,y,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5263e197d65SBarry Smith     }
52751f519a2SBarry Smith     if (jac->type == PC_COMPOSITE_SYMMETRIC_MULTIPLICATIVE) {
52811755939SBarry Smith       cnt -= 2;
52951f519a2SBarry Smith       while (ilink->previous) {
53051f519a2SBarry Smith         ilink = ilink->previous;
53111755939SBarry Smith         /* compute the residual only over the part of the vector needed */
53211755939SBarry Smith         ierr = MatMult(jac->Afield[cnt--],y,ilink->x);CHKERRQ(ierr);
53311755939SBarry Smith         ierr = VecScale(ilink->x,-1.0);CHKERRQ(ierr);
53411755939SBarry Smith         ierr = VecScatterBegin(ilink->sctx,x,ilink->x,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
53511755939SBarry Smith         ierr = VecScatterEnd(ilink->sctx,x,ilink->x,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
53611755939SBarry Smith         ierr = KSPSolve(ilink->ksp,ilink->x,ilink->y);CHKERRQ(ierr);
53711755939SBarry Smith         ierr = VecScatterBegin(ilink->sctx,ilink->y,y,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
53811755939SBarry Smith         ierr = VecScatterEnd(ilink->sctx,ilink->y,y,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
53951f519a2SBarry Smith       }
54011755939SBarry Smith     }
54116913363SBarry Smith   } else SETERRQ1(PETSC_ERR_SUP,"Unsupported or unknown composition",(int) jac->type);
54251f519a2SBarry Smith   CHKMEMQ;
5430971522cSBarry Smith   PetscFunctionReturn(0);
5440971522cSBarry Smith }
5450971522cSBarry Smith 
546421e10b8SBarry Smith #define FieldSplitSplitSolveAddTranspose(ilink,xx,yy) \
547ca9f406cSSatish Balay     (VecScatterBegin(ilink->sctx,xx,ilink->y,INSERT_VALUES,SCATTER_FORWARD) || \
548ca9f406cSSatish Balay      VecScatterEnd(ilink->sctx,xx,ilink->y,INSERT_VALUES,SCATTER_FORWARD) || \
549421e10b8SBarry Smith      KSPSolveTranspose(ilink->ksp,ilink->y,ilink->x) || \
550ca9f406cSSatish Balay      VecScatterBegin(ilink->sctx,ilink->x,yy,ADD_VALUES,SCATTER_REVERSE) || \
551ca9f406cSSatish Balay      VecScatterEnd(ilink->sctx,ilink->x,yy,ADD_VALUES,SCATTER_REVERSE))
552421e10b8SBarry Smith 
553421e10b8SBarry Smith #undef __FUNCT__
554421e10b8SBarry Smith #define __FUNCT__ "PCApply_FieldSplit"
555421e10b8SBarry Smith static PetscErrorCode PCApplyTranspose_FieldSplit(PC pc,Vec x,Vec y)
556421e10b8SBarry Smith {
557421e10b8SBarry Smith   PC_FieldSplit     *jac = (PC_FieldSplit*)pc->data;
558421e10b8SBarry Smith   PetscErrorCode    ierr;
559421e10b8SBarry Smith   PC_FieldSplitLink ilink = jac->head;
560421e10b8SBarry Smith 
561421e10b8SBarry Smith   PetscFunctionBegin;
562421e10b8SBarry Smith   CHKMEMQ;
563421e10b8SBarry Smith   ierr = VecSetBlockSize(x,jac->bs);CHKERRQ(ierr);
564421e10b8SBarry Smith   ierr = VecSetBlockSize(y,jac->bs);CHKERRQ(ierr);
565421e10b8SBarry Smith 
566421e10b8SBarry Smith   if (jac->type == PC_COMPOSITE_ADDITIVE) {
567421e10b8SBarry Smith     if (jac->defaultsplit) {
568421e10b8SBarry Smith       ierr = VecStrideGatherAll(x,jac->x,INSERT_VALUES);CHKERRQ(ierr);
569421e10b8SBarry Smith       while (ilink) {
570421e10b8SBarry Smith 	ierr = KSPSolveTranspose(ilink->ksp,ilink->x,ilink->y);CHKERRQ(ierr);
571421e10b8SBarry Smith 	ilink = ilink->next;
572421e10b8SBarry Smith       }
573421e10b8SBarry Smith       ierr = VecStrideScatterAll(jac->y,y,INSERT_VALUES);CHKERRQ(ierr);
574421e10b8SBarry Smith     } else {
575421e10b8SBarry Smith       ierr = VecSet(y,0.0);CHKERRQ(ierr);
576421e10b8SBarry Smith       while (ilink) {
577421e10b8SBarry Smith         ierr = FieldSplitSplitSolveAddTranspose(ilink,x,y);CHKERRQ(ierr);
578421e10b8SBarry Smith 	ilink = ilink->next;
579421e10b8SBarry Smith       }
580421e10b8SBarry Smith     }
581421e10b8SBarry Smith   } else {
582421e10b8SBarry Smith     if (!jac->w1) {
583421e10b8SBarry Smith       ierr = VecDuplicate(x,&jac->w1);CHKERRQ(ierr);
584421e10b8SBarry Smith       ierr = VecDuplicate(x,&jac->w2);CHKERRQ(ierr);
585421e10b8SBarry Smith     }
586421e10b8SBarry Smith     ierr = VecSet(y,0.0);CHKERRQ(ierr);
587421e10b8SBarry Smith     if (jac->type == PC_COMPOSITE_SYMMETRIC_MULTIPLICATIVE) {
588421e10b8SBarry Smith       ierr = FieldSplitSplitSolveAddTranspose(ilink,x,y);CHKERRQ(ierr);
589421e10b8SBarry Smith       while (ilink->next) {
590421e10b8SBarry Smith         ilink = ilink->next;
5919989ab13SBarry Smith         ierr  = MatMultTranspose(pc->mat,y,jac->w1);CHKERRQ(ierr);
592421e10b8SBarry Smith         ierr  = VecWAXPY(jac->w2,-1.0,jac->w1,x);CHKERRQ(ierr);
593421e10b8SBarry Smith         ierr  = FieldSplitSplitSolveAddTranspose(ilink,jac->w2,y);CHKERRQ(ierr);
594421e10b8SBarry Smith       }
595421e10b8SBarry Smith       while (ilink->previous) {
596421e10b8SBarry Smith         ilink = ilink->previous;
5979989ab13SBarry Smith         ierr  = MatMultTranspose(pc->mat,y,jac->w1);CHKERRQ(ierr);
598421e10b8SBarry Smith         ierr  = VecWAXPY(jac->w2,-1.0,jac->w1,x);CHKERRQ(ierr);
599421e10b8SBarry Smith         ierr  = FieldSplitSplitSolveAddTranspose(ilink,jac->w2,y);CHKERRQ(ierr);
600421e10b8SBarry Smith       }
601421e10b8SBarry Smith     } else {
602421e10b8SBarry Smith       while (ilink->next) {   /* get to last entry in linked list */
603421e10b8SBarry Smith 	ilink = ilink->next;
604421e10b8SBarry Smith       }
605421e10b8SBarry Smith       ierr = FieldSplitSplitSolveAddTranspose(ilink,x,y);CHKERRQ(ierr);
606421e10b8SBarry Smith       while (ilink->previous) {
607421e10b8SBarry Smith 	ilink = ilink->previous;
6089989ab13SBarry Smith 	ierr  = MatMultTranspose(pc->mat,y,jac->w1);CHKERRQ(ierr);
609421e10b8SBarry Smith 	ierr  = VecWAXPY(jac->w2,-1.0,jac->w1,x);CHKERRQ(ierr);
610421e10b8SBarry Smith 	ierr  = FieldSplitSplitSolveAddTranspose(ilink,jac->w2,y);CHKERRQ(ierr);
611421e10b8SBarry Smith       }
612421e10b8SBarry Smith     }
613421e10b8SBarry Smith   }
614421e10b8SBarry Smith   CHKMEMQ;
615421e10b8SBarry Smith   PetscFunctionReturn(0);
616421e10b8SBarry Smith }
617421e10b8SBarry Smith 
6180971522cSBarry Smith #undef __FUNCT__
6190971522cSBarry Smith #define __FUNCT__ "PCDestroy_FieldSplit"
6200971522cSBarry Smith static PetscErrorCode PCDestroy_FieldSplit(PC pc)
6210971522cSBarry Smith {
6220971522cSBarry Smith   PC_FieldSplit     *jac = (PC_FieldSplit*)pc->data;
6230971522cSBarry Smith   PetscErrorCode    ierr;
6245a9f2f41SSatish Balay   PC_FieldSplitLink ilink = jac->head,next;
6250971522cSBarry Smith 
6260971522cSBarry Smith   PetscFunctionBegin;
6275a9f2f41SSatish Balay   while (ilink) {
6285a9f2f41SSatish Balay     ierr = KSPDestroy(ilink->ksp);CHKERRQ(ierr);
6295a9f2f41SSatish Balay     if (ilink->x) {ierr = VecDestroy(ilink->x);CHKERRQ(ierr);}
6305a9f2f41SSatish Balay     if (ilink->y) {ierr = VecDestroy(ilink->y);CHKERRQ(ierr);}
6315a9f2f41SSatish Balay     if (ilink->sctx) {ierr = VecScatterDestroy(ilink->sctx);CHKERRQ(ierr);}
632704ba839SBarry Smith     if (ilink->is) {ierr = ISDestroy(ilink->is);CHKERRQ(ierr);}
6335a9f2f41SSatish Balay     next = ilink->next;
634704ba839SBarry Smith     ierr = PetscFree(ilink->fields);CHKERRQ(ierr);
635704ba839SBarry Smith     ierr = PetscFree(ilink);CHKERRQ(ierr);
6365a9f2f41SSatish Balay     ilink = next;
6370971522cSBarry Smith   }
63805b42c5fSBarry Smith   ierr = PetscFree2(jac->x,jac->y);CHKERRQ(ierr);
639519d70e2SJed Brown   if (jac->mat && jac->mat != jac->pmat) {ierr = MatDestroyMatrices(jac->nsplits,&jac->mat);CHKERRQ(ierr);}
64097bbdb24SBarry Smith   if (jac->pmat) {ierr = MatDestroyMatrices(jac->nsplits,&jac->pmat);CHKERRQ(ierr);}
64168dd23aaSBarry Smith   if (jac->Afield) {ierr = MatDestroyMatrices(jac->nsplits,&jac->Afield);CHKERRQ(ierr);}
64279416396SBarry Smith   if (jac->w1) {ierr = VecDestroy(jac->w1);CHKERRQ(ierr);}
64379416396SBarry Smith   if (jac->w2) {ierr = VecDestroy(jac->w2);CHKERRQ(ierr);}
6443b224e63SBarry Smith   if (jac->schur) {ierr = MatDestroy(jac->schur);CHKERRQ(ierr);}
645084e4875SJed Brown   if (jac->schur_user) {ierr = MatDestroy(jac->schur_user);CHKERRQ(ierr);}
646d0f46423SBarry Smith   if (jac->kspschur) {ierr = KSPDestroy(jac->kspschur);CHKERRQ(ierr);}
6473b224e63SBarry Smith   if (jac->B) {ierr = MatDestroy(jac->B);CHKERRQ(ierr);}
6483b224e63SBarry Smith   if (jac->C) {ierr = MatDestroy(jac->C);CHKERRQ(ierr);}
6490971522cSBarry Smith   ierr = PetscFree(jac);CHKERRQ(ierr);
6500971522cSBarry Smith   PetscFunctionReturn(0);
6510971522cSBarry Smith }
6520971522cSBarry Smith 
6530971522cSBarry Smith #undef __FUNCT__
6540971522cSBarry Smith #define __FUNCT__ "PCSetFromOptions_FieldSplit"
6550971522cSBarry Smith static PetscErrorCode PCSetFromOptions_FieldSplit(PC pc)
6560971522cSBarry Smith {
6571b9fc7fcSBarry Smith   PetscErrorCode  ierr;
65851f519a2SBarry Smith   PetscInt        i = 0,nfields,*fields,bs;
659084e4875SJed Brown   PetscTruth      flg;
6601b9fc7fcSBarry Smith   char            optionname[128];
6619dcbbd2bSBarry Smith   PC_FieldSplit   *jac = (PC_FieldSplit*)pc->data;
6623b224e63SBarry Smith   PCCompositeType ctype;
6631b9fc7fcSBarry Smith 
6640971522cSBarry Smith   PetscFunctionBegin;
6651b9fc7fcSBarry Smith   ierr = PetscOptionsHead("FieldSplit options");CHKERRQ(ierr);
666519d70e2SJed Brown   ierr = PetscOptionsTruth("-pc_fieldsplit_real_diagonal","Use diagonal blocks of the operator","PCFieldSplitSetRealDiagonal",jac->realdiagonal,&jac->realdiagonal,PETSC_NULL);CHKERRQ(ierr);
66751f519a2SBarry Smith   ierr = PetscOptionsInt("-pc_fieldsplit_block_size","Blocksize that defines number of fields","PCFieldSplitSetBlockSize",jac->bs,&bs,&flg);CHKERRQ(ierr);
66851f519a2SBarry Smith   if (flg) {
66951f519a2SBarry Smith     ierr = PCFieldSplitSetBlockSize(pc,bs);CHKERRQ(ierr);
67051f519a2SBarry Smith   }
671704ba839SBarry Smith 
6723b224e63SBarry Smith   ierr = PetscOptionsEnum("-pc_fieldsplit_type","Type of composition","PCFieldSplitSetType",PCCompositeTypes,(PetscEnum)jac->type,(PetscEnum*)&ctype,&flg);CHKERRQ(ierr);
6733b224e63SBarry Smith   if (flg) {
6743b224e63SBarry Smith     ierr = PCFieldSplitSetType(pc,ctype);CHKERRQ(ierr);
6753b224e63SBarry Smith   }
676d32f9abdSBarry Smith 
677c30613efSMatthew Knepley   /* Only setup fields once */
678c30613efSMatthew Knepley   if ((jac->bs > 0) && (jac->nsplits == 0)) {
679d32f9abdSBarry Smith     /* only allow user to set fields from command line if bs is already known.
680d32f9abdSBarry Smith        otherwise user can set them in PCFieldSplitSetDefaults() */
68151f519a2SBarry Smith     ierr = PetscMalloc(jac->bs*sizeof(PetscInt),&fields);CHKERRQ(ierr);
6821b9fc7fcSBarry Smith     while (PETSC_TRUE) {
68313f74950SBarry Smith       sprintf(optionname,"-pc_fieldsplit_%d_fields",(int)i++);
68451f519a2SBarry Smith       nfields = jac->bs;
6851b9fc7fcSBarry Smith       ierr    = PetscOptionsIntArray(optionname,"Fields in this split","PCFieldSplitSetFields",fields,&nfields,&flg);CHKERRQ(ierr);
6861b9fc7fcSBarry Smith       if (!flg) break;
6871b9fc7fcSBarry Smith       if (!nfields) SETERRQ(PETSC_ERR_USER,"Cannot list zero fields");
6881b9fc7fcSBarry Smith       ierr = PCFieldSplitSetFields(pc,nfields,fields);CHKERRQ(ierr);
6891b9fc7fcSBarry Smith     }
69051f519a2SBarry Smith     ierr = PetscFree(fields);CHKERRQ(ierr);
691d32f9abdSBarry Smith   }
692084e4875SJed Brown   ierr = PetscOptionsEnum("-pc_fieldsplit_schur_precondition","How to build preconditioner for Schur complement","PCFieldSplitSchurPrecondition",PCFieldSplitSchurPreTypes,(PetscEnum)jac->schurpre,(PetscEnum*)&jac->schurpre,PETSC_NULL);CHKERRQ(ierr);
6931b9fc7fcSBarry Smith   ierr = PetscOptionsTail();CHKERRQ(ierr);
6940971522cSBarry Smith   PetscFunctionReturn(0);
6950971522cSBarry Smith }
6960971522cSBarry Smith 
6970971522cSBarry Smith /*------------------------------------------------------------------------------------*/
6980971522cSBarry Smith 
6990971522cSBarry Smith EXTERN_C_BEGIN
7000971522cSBarry Smith #undef __FUNCT__
7010971522cSBarry Smith #define __FUNCT__ "PCFieldSplitSetFields_FieldSplit"
702dba47a55SKris Buschelman PetscErrorCode PETSCKSP_DLLEXPORT PCFieldSplitSetFields_FieldSplit(PC pc,PetscInt n,PetscInt *fields)
7030971522cSBarry Smith {
70497bbdb24SBarry Smith   PC_FieldSplit     *jac = (PC_FieldSplit*)pc->data;
7050971522cSBarry Smith   PetscErrorCode    ierr;
7065a9f2f41SSatish Balay   PC_FieldSplitLink ilink,next = jac->head;
70769a612a9SBarry Smith   char              prefix[128];
70851f519a2SBarry Smith   PetscInt          i;
7090971522cSBarry Smith 
7100971522cSBarry Smith   PetscFunctionBegin;
7110971522cSBarry Smith   if (n <= 0) SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"Negative number of fields requested");
71251f519a2SBarry Smith   for (i=0; i<n; i++) {
71351f519a2SBarry Smith     if (fields[i] >= jac->bs) SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"Field %D requested but only %D exist",fields[i],jac->bs);
71451f519a2SBarry Smith     if (fields[i] < 0) SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,"Negative field %D requested",fields[i]);
71551f519a2SBarry Smith   }
716704ba839SBarry Smith   ierr = PetscNew(struct _PC_FieldSplitLink,&ilink);CHKERRQ(ierr);
717704ba839SBarry Smith   ierr = PetscMalloc(n*sizeof(PetscInt),&ilink->fields);CHKERRQ(ierr);
7185a9f2f41SSatish Balay   ierr = PetscMemcpy(ilink->fields,fields,n*sizeof(PetscInt));CHKERRQ(ierr);
7195a9f2f41SSatish Balay   ilink->nfields = n;
7205a9f2f41SSatish Balay   ilink->next    = PETSC_NULL;
7217adad957SLisandro Dalcin   ierr           = KSPCreate(((PetscObject)pc)->comm,&ilink->ksp);CHKERRQ(ierr);
7221cee3971SBarry Smith   ierr           = PetscObjectIncrementTabLevel((PetscObject)ilink->ksp,(PetscObject)pc,1);CHKERRQ(ierr);
7235a9f2f41SSatish Balay   ierr           = KSPSetType(ilink->ksp,KSPPREONLY);CHKERRQ(ierr);
72469a612a9SBarry Smith 
7257adad957SLisandro Dalcin   if (((PetscObject)pc)->prefix) {
7267adad957SLisandro Dalcin     sprintf(prefix,"%sfieldsplit_%d_",((PetscObject)pc)->prefix,(int)jac->nsplits);
72769a612a9SBarry Smith   } else {
72813f74950SBarry Smith     sprintf(prefix,"fieldsplit_%d_",(int)jac->nsplits);
72969a612a9SBarry Smith   }
7305a9f2f41SSatish Balay   ierr = KSPSetOptionsPrefix(ilink->ksp,prefix);CHKERRQ(ierr);
7310971522cSBarry Smith 
7320971522cSBarry Smith   if (!next) {
7335a9f2f41SSatish Balay     jac->head       = ilink;
73451f519a2SBarry Smith     ilink->previous = PETSC_NULL;
7350971522cSBarry Smith   } else {
7360971522cSBarry Smith     while (next->next) {
7370971522cSBarry Smith       next = next->next;
7380971522cSBarry Smith     }
7395a9f2f41SSatish Balay     next->next      = ilink;
74051f519a2SBarry Smith     ilink->previous = next;
7410971522cSBarry Smith   }
7420971522cSBarry Smith   jac->nsplits++;
7430971522cSBarry Smith   PetscFunctionReturn(0);
7440971522cSBarry Smith }
7450971522cSBarry Smith EXTERN_C_END
7460971522cSBarry Smith 
747e69d4d44SBarry Smith EXTERN_C_BEGIN
748e69d4d44SBarry Smith #undef __FUNCT__
749e69d4d44SBarry Smith #define __FUNCT__ "PCFieldSplitGetSubKSP_FieldSplit_Schur"
750e69d4d44SBarry Smith PetscErrorCode PETSCKSP_DLLEXPORT PCFieldSplitGetSubKSP_FieldSplit_Schur(PC pc,PetscInt *n,KSP **subksp)
751e69d4d44SBarry Smith {
752e69d4d44SBarry Smith   PC_FieldSplit *jac = (PC_FieldSplit*)pc->data;
753e69d4d44SBarry Smith   PetscErrorCode ierr;
754e69d4d44SBarry Smith 
755e69d4d44SBarry Smith   PetscFunctionBegin;
756519d70e2SJed Brown   ierr = PetscMalloc(jac->nsplits*sizeof(KSP),subksp);CHKERRQ(ierr);
757e69d4d44SBarry Smith   ierr = MatSchurComplementGetKSP(jac->schur,*subksp);CHKERRQ(ierr);
758e69d4d44SBarry Smith   (*subksp)[1] = jac->kspschur;
759084e4875SJed Brown   *n = jac->nsplits;
760e69d4d44SBarry Smith   PetscFunctionReturn(0);
761e69d4d44SBarry Smith }
762e69d4d44SBarry Smith EXTERN_C_END
7630971522cSBarry Smith 
7640971522cSBarry Smith EXTERN_C_BEGIN
7650971522cSBarry Smith #undef __FUNCT__
76669a612a9SBarry Smith #define __FUNCT__ "PCFieldSplitGetSubKSP_FieldSplit"
767dba47a55SKris Buschelman PetscErrorCode PETSCKSP_DLLEXPORT PCFieldSplitGetSubKSP_FieldSplit(PC pc,PetscInt *n,KSP **subksp)
7680971522cSBarry Smith {
7690971522cSBarry Smith   PC_FieldSplit     *jac = (PC_FieldSplit*)pc->data;
7700971522cSBarry Smith   PetscErrorCode    ierr;
7710971522cSBarry Smith   PetscInt          cnt = 0;
7725a9f2f41SSatish Balay   PC_FieldSplitLink ilink = jac->head;
7730971522cSBarry Smith 
7740971522cSBarry Smith   PetscFunctionBegin;
77569a612a9SBarry Smith   ierr = PetscMalloc(jac->nsplits*sizeof(KSP*),subksp);CHKERRQ(ierr);
7765a9f2f41SSatish Balay   while (ilink) {
7775a9f2f41SSatish Balay     (*subksp)[cnt++] = ilink->ksp;
7785a9f2f41SSatish Balay     ilink = ilink->next;
7790971522cSBarry Smith   }
7800971522cSBarry Smith   if (cnt != jac->nsplits) SETERRQ2(PETSC_ERR_PLIB,"Corrupt PCFIELDSPLIT object: number splits in linked list %D in object %D",cnt,jac->nsplits);
7810971522cSBarry Smith   *n = jac->nsplits;
7820971522cSBarry Smith   PetscFunctionReturn(0);
7830971522cSBarry Smith }
7840971522cSBarry Smith EXTERN_C_END
7850971522cSBarry Smith 
786704ba839SBarry Smith EXTERN_C_BEGIN
787704ba839SBarry Smith #undef __FUNCT__
788704ba839SBarry Smith #define __FUNCT__ "PCFieldSplitSetIS_FieldSplit"
789704ba839SBarry Smith PetscErrorCode PETSCKSP_DLLEXPORT PCFieldSplitSetIS_FieldSplit(PC pc,IS is)
790704ba839SBarry Smith {
791704ba839SBarry Smith   PC_FieldSplit     *jac = (PC_FieldSplit*)pc->data;
792704ba839SBarry Smith   PetscErrorCode    ierr;
793704ba839SBarry Smith   PC_FieldSplitLink ilink, next = jac->head;
794704ba839SBarry Smith   char              prefix[128];
795704ba839SBarry Smith 
796704ba839SBarry Smith   PetscFunctionBegin;
79716913363SBarry Smith   ierr = PetscNew(struct _PC_FieldSplitLink,&ilink);CHKERRQ(ierr);
7981ab39975SBarry Smith   ilink->is      = is;
7991ab39975SBarry Smith   ierr           = PetscObjectReference((PetscObject)is);CHKERRQ(ierr);
800704ba839SBarry Smith   ilink->next    = PETSC_NULL;
801704ba839SBarry Smith   ierr           = KSPCreate(((PetscObject)pc)->comm,&ilink->ksp);CHKERRQ(ierr);
8021cee3971SBarry Smith   ierr           = PetscObjectIncrementTabLevel((PetscObject)ilink->ksp,(PetscObject)pc,1);CHKERRQ(ierr);
803704ba839SBarry Smith   ierr           = KSPSetType(ilink->ksp,KSPPREONLY);CHKERRQ(ierr);
804704ba839SBarry Smith 
805704ba839SBarry Smith   if (((PetscObject)pc)->prefix) {
806704ba839SBarry Smith     sprintf(prefix,"%sfieldsplit_%d_",((PetscObject)pc)->prefix,(int)jac->nsplits);
807704ba839SBarry Smith   } else {
808704ba839SBarry Smith     sprintf(prefix,"fieldsplit_%d_",(int)jac->nsplits);
809704ba839SBarry Smith   }
810704ba839SBarry Smith   ierr = KSPSetOptionsPrefix(ilink->ksp,prefix);CHKERRQ(ierr);
811704ba839SBarry Smith 
812704ba839SBarry Smith   if (!next) {
813704ba839SBarry Smith     jac->head       = ilink;
814704ba839SBarry Smith     ilink->previous = PETSC_NULL;
815704ba839SBarry Smith   } else {
816704ba839SBarry Smith     while (next->next) {
817704ba839SBarry Smith       next = next->next;
818704ba839SBarry Smith     }
819704ba839SBarry Smith     next->next      = ilink;
820704ba839SBarry Smith     ilink->previous = next;
821704ba839SBarry Smith   }
822704ba839SBarry Smith   jac->nsplits++;
823704ba839SBarry Smith 
824704ba839SBarry Smith   PetscFunctionReturn(0);
825704ba839SBarry Smith }
826704ba839SBarry Smith EXTERN_C_END
827704ba839SBarry Smith 
8280971522cSBarry Smith #undef __FUNCT__
8290971522cSBarry Smith #define __FUNCT__ "PCFieldSplitSetFields"
8300971522cSBarry Smith /*@
8310971522cSBarry Smith     PCFieldSplitSetFields - Sets the fields for one particular split in the field split preconditioner
8320971522cSBarry Smith 
8330971522cSBarry Smith     Collective on PC
8340971522cSBarry Smith 
8350971522cSBarry Smith     Input Parameters:
8360971522cSBarry Smith +   pc  - the preconditioner context
8370971522cSBarry Smith .   n - the number of fields in this split
8380971522cSBarry Smith .   fields - the fields in this split
8390971522cSBarry Smith 
8400971522cSBarry Smith     Level: intermediate
8410971522cSBarry Smith 
842d32f9abdSBarry Smith     Notes: Use PCFieldSplitSetIS() to set a completely general set of indices as a field.
843d32f9abdSBarry Smith 
844d32f9abdSBarry Smith      The PCFieldSplitSetFields() is for defining fields as a strided blocks. For example, if the block
845d32f9abdSBarry Smith      size is three then one can define a field as 0, or 1 or 2 or 0,1 or 0,2 or 1,2 which mean
846d32f9abdSBarry Smith      0xx3xx6xx9xx12 ... x1xx4xx7xx ... xx2xx5xx8xx.. 01x34x67x... 0x1x3x5x7.. x12x45x78x....
847d32f9abdSBarry Smith      where the numbered entries indicate what is in the field.
848d32f9abdSBarry Smith 
849d32f9abdSBarry Smith .seealso: PCFieldSplitGetSubKSP(), PCFIELDSPLIT, PCFieldSplitSetBlockSize(), PCFieldSplitSetIS()
8500971522cSBarry Smith 
8510971522cSBarry Smith @*/
852dba47a55SKris Buschelman PetscErrorCode PETSCKSP_DLLEXPORT PCFieldSplitSetFields(PC pc,PetscInt n, PetscInt *fields)
8530971522cSBarry Smith {
8540971522cSBarry Smith   PetscErrorCode ierr,(*f)(PC,PetscInt,PetscInt *);
8550971522cSBarry Smith 
8560971522cSBarry Smith   PetscFunctionBegin;
8570971522cSBarry Smith   PetscValidHeaderSpecific(pc,PC_COOKIE,1);
8580971522cSBarry Smith   ierr = PetscObjectQueryFunction((PetscObject)pc,"PCFieldSplitSetFields_C",(void (**)(void))&f);CHKERRQ(ierr);
8590971522cSBarry Smith   if (f) {
8600971522cSBarry Smith     ierr = (*f)(pc,n,fields);CHKERRQ(ierr);
8610971522cSBarry Smith   }
8620971522cSBarry Smith   PetscFunctionReturn(0);
8630971522cSBarry Smith }
8640971522cSBarry Smith 
8650971522cSBarry Smith #undef __FUNCT__
866704ba839SBarry Smith #define __FUNCT__ "PCFieldSplitSetIS"
867704ba839SBarry Smith /*@
868704ba839SBarry Smith     PCFieldSplitSetIS - Sets the exact elements for field
869704ba839SBarry Smith 
870704ba839SBarry Smith     Collective on PC
871704ba839SBarry Smith 
872704ba839SBarry Smith     Input Parameters:
873704ba839SBarry Smith +   pc  - the preconditioner context
874704ba839SBarry Smith .   is - the index set that defines the vector elements in this field
875704ba839SBarry Smith 
876d32f9abdSBarry Smith 
877d32f9abdSBarry Smith     Notes: Use PCFieldSplitSetFields(), for fields defined by strided types.
878d32f9abdSBarry Smith 
879704ba839SBarry Smith     Level: intermediate
880704ba839SBarry Smith 
881704ba839SBarry Smith .seealso: PCFieldSplitGetSubKSP(), PCFIELDSPLIT, PCFieldSplitSetBlockSize()
882704ba839SBarry Smith 
883704ba839SBarry Smith @*/
884704ba839SBarry Smith PetscErrorCode PETSCKSP_DLLEXPORT PCFieldSplitSetIS(PC pc,IS is)
885704ba839SBarry Smith {
886704ba839SBarry Smith   PetscErrorCode ierr,(*f)(PC,IS);
887704ba839SBarry Smith 
888704ba839SBarry Smith   PetscFunctionBegin;
889704ba839SBarry Smith   PetscValidHeaderSpecific(pc,PC_COOKIE,1);
890704ba839SBarry Smith   PetscValidHeaderSpecific(is,IS_COOKIE,1);
891704ba839SBarry Smith   ierr = PetscObjectQueryFunction((PetscObject)pc,"PCFieldSplitSetIS_C",(void (**)(void))&f);CHKERRQ(ierr);
892704ba839SBarry Smith   if (f) {
893704ba839SBarry Smith     ierr = (*f)(pc,is);CHKERRQ(ierr);
894704ba839SBarry Smith   }
895704ba839SBarry Smith   PetscFunctionReturn(0);
896704ba839SBarry Smith }
897704ba839SBarry Smith 
898704ba839SBarry Smith #undef __FUNCT__
89951f519a2SBarry Smith #define __FUNCT__ "PCFieldSplitSetBlockSize"
90051f519a2SBarry Smith /*@
90151f519a2SBarry Smith     PCFieldSplitSetBlockSize - Sets the block size for defining where fields start in the
90251f519a2SBarry Smith       fieldsplit preconditioner. If not set the matrix block size is used.
90351f519a2SBarry Smith 
90451f519a2SBarry Smith     Collective on PC
90551f519a2SBarry Smith 
90651f519a2SBarry Smith     Input Parameters:
90751f519a2SBarry Smith +   pc  - the preconditioner context
90851f519a2SBarry Smith -   bs - the block size
90951f519a2SBarry Smith 
91051f519a2SBarry Smith     Level: intermediate
91151f519a2SBarry Smith 
91251f519a2SBarry Smith .seealso: PCFieldSplitGetSubKSP(), PCFIELDSPLIT, PCFieldSplitSetFields()
91351f519a2SBarry Smith 
91451f519a2SBarry Smith @*/
91551f519a2SBarry Smith PetscErrorCode PETSCKSP_DLLEXPORT PCFieldSplitSetBlockSize(PC pc,PetscInt bs)
91651f519a2SBarry Smith {
91751f519a2SBarry Smith   PetscErrorCode ierr,(*f)(PC,PetscInt);
91851f519a2SBarry Smith 
91951f519a2SBarry Smith   PetscFunctionBegin;
92051f519a2SBarry Smith   PetscValidHeaderSpecific(pc,PC_COOKIE,1);
92151f519a2SBarry Smith   ierr = PetscObjectQueryFunction((PetscObject)pc,"PCFieldSplitSetBlockSize_C",(void (**)(void))&f);CHKERRQ(ierr);
92251f519a2SBarry Smith   if (f) {
92351f519a2SBarry Smith     ierr = (*f)(pc,bs);CHKERRQ(ierr);
92451f519a2SBarry Smith   }
92551f519a2SBarry Smith   PetscFunctionReturn(0);
92651f519a2SBarry Smith }
92751f519a2SBarry Smith 
92851f519a2SBarry Smith #undef __FUNCT__
92969a612a9SBarry Smith #define __FUNCT__ "PCFieldSplitGetSubKSP"
9300971522cSBarry Smith /*@C
93169a612a9SBarry Smith    PCFieldSplitGetSubKSP - Gets the KSP contexts for all splits
9320971522cSBarry Smith 
93369a612a9SBarry Smith    Collective on KSP
9340971522cSBarry Smith 
9350971522cSBarry Smith    Input Parameter:
9360971522cSBarry Smith .  pc - the preconditioner context
9370971522cSBarry Smith 
9380971522cSBarry Smith    Output Parameters:
9390971522cSBarry Smith +  n - the number of split
94069a612a9SBarry Smith -  pc - the array of KSP contexts
9410971522cSBarry Smith 
9420971522cSBarry Smith    Note:
943d32f9abdSBarry Smith    After PCFieldSplitGetSubKSP() the array of KSPs IS to be freed by the user
944d32f9abdSBarry Smith    (not the KSP just the array that contains them).
9450971522cSBarry Smith 
94669a612a9SBarry Smith    You must call KSPSetUp() before calling PCFieldSplitGetSubKSP().
9470971522cSBarry Smith 
9480971522cSBarry Smith    Level: advanced
9490971522cSBarry Smith 
9500971522cSBarry Smith .seealso: PCFIELDSPLIT
9510971522cSBarry Smith @*/
952dba47a55SKris Buschelman PetscErrorCode PETSCKSP_DLLEXPORT PCFieldSplitGetSubKSP(PC pc,PetscInt *n,KSP *subksp[])
9530971522cSBarry Smith {
95469a612a9SBarry Smith   PetscErrorCode ierr,(*f)(PC,PetscInt*,KSP **);
9550971522cSBarry Smith 
9560971522cSBarry Smith   PetscFunctionBegin;
9570971522cSBarry Smith   PetscValidHeaderSpecific(pc,PC_COOKIE,1);
9580971522cSBarry Smith   PetscValidIntPointer(n,2);
95969a612a9SBarry Smith   ierr = PetscObjectQueryFunction((PetscObject)pc,"PCFieldSplitGetSubKSP_C",(void (**)(void))&f);CHKERRQ(ierr);
9600971522cSBarry Smith   if (f) {
96169a612a9SBarry Smith     ierr = (*f)(pc,n,subksp);CHKERRQ(ierr);
9620971522cSBarry Smith   } else {
96369a612a9SBarry Smith     SETERRQ(PETSC_ERR_ARG_WRONG,"Cannot get subksp for this type of PC");
9640971522cSBarry Smith   }
9650971522cSBarry Smith   PetscFunctionReturn(0);
9660971522cSBarry Smith }
9670971522cSBarry Smith 
968e69d4d44SBarry Smith #undef __FUNCT__
969e69d4d44SBarry Smith #define __FUNCT__ "PCFieldSplitSchurPrecondition"
970e69d4d44SBarry Smith /*@
971e69d4d44SBarry Smith     PCFieldSplitSchurPrecondition -  Indicates if the Schur complement is preconditioned by a preconditioner constructed by the
972e69d4d44SBarry Smith       D matrix. Otherwise no preconditioner is used.
973e69d4d44SBarry Smith 
974e69d4d44SBarry Smith     Collective on PC
975e69d4d44SBarry Smith 
976e69d4d44SBarry Smith     Input Parameters:
977e69d4d44SBarry Smith +   pc  - the preconditioner context
978084e4875SJed Brown .   ptype - which matrix to use for preconditioning the Schur complement
979084e4875SJed Brown -   userpre - matrix to use for preconditioning, or PETSC_NULL
980084e4875SJed Brown 
981084e4875SJed Brown     Notes:
982084e4875SJed Brown     The default is to use the block on the diagonal of the preconditioning matrix.  This is D, in the (1,1) position.
983084e4875SJed Brown     There are currently no preconditioners that work directly with the Schur complement so setting
984084e4875SJed Brown     PC_FIELDSPLIT_SCHUR_PRE_SELF is observationally equivalent to -fieldsplit_1_pc_type none.
985e69d4d44SBarry Smith 
986e69d4d44SBarry Smith     Options Database:
987084e4875SJed Brown .     -pc_fieldsplit_schur_precondition <self,user,diag> default is diag
988e69d4d44SBarry Smith 
989e69d4d44SBarry Smith     Level: intermediate
990e69d4d44SBarry Smith 
991084e4875SJed Brown .seealso: PCFieldSplitGetSubKSP(), PCFIELDSPLIT, PCFieldSplitSetFields(), PCFieldSplitSchurPreType
992e69d4d44SBarry Smith 
993e69d4d44SBarry Smith @*/
994084e4875SJed Brown PetscErrorCode PETSCKSP_DLLEXPORT PCFieldSplitSchurPrecondition(PC pc,PCFieldSplitSchurPreType ptype,Mat pre)
995e69d4d44SBarry Smith {
996084e4875SJed Brown   PetscErrorCode ierr,(*f)(PC,PCFieldSplitSchurPreType,Mat);
997e69d4d44SBarry Smith 
998e69d4d44SBarry Smith   PetscFunctionBegin;
999e69d4d44SBarry Smith   PetscValidHeaderSpecific(pc,PC_COOKIE,1);
1000e69d4d44SBarry Smith   ierr = PetscObjectQueryFunction((PetscObject)pc,"PCFieldSplitSchurPrecondition_C",(void (**)(void))&f);CHKERRQ(ierr);
1001e69d4d44SBarry Smith   if (f) {
1002084e4875SJed Brown     ierr = (*f)(pc,ptype,pre);CHKERRQ(ierr);
1003e69d4d44SBarry Smith   }
1004e69d4d44SBarry Smith   PetscFunctionReturn(0);
1005e69d4d44SBarry Smith }
1006e69d4d44SBarry Smith 
1007e69d4d44SBarry Smith EXTERN_C_BEGIN
1008e69d4d44SBarry Smith #undef __FUNCT__
1009e69d4d44SBarry Smith #define __FUNCT__ "PCFieldSplitSchurPrecondition_FieldSplit"
1010084e4875SJed Brown PetscErrorCode PETSCKSP_DLLEXPORT PCFieldSplitSchurPrecondition_FieldSplit(PC pc,PCFieldSplitSchurPreType ptype,Mat pre)
1011e69d4d44SBarry Smith {
1012e69d4d44SBarry Smith   PC_FieldSplit  *jac = (PC_FieldSplit*)pc->data;
1013084e4875SJed Brown   PetscErrorCode  ierr;
1014e69d4d44SBarry Smith 
1015e69d4d44SBarry Smith   PetscFunctionBegin;
1016084e4875SJed Brown   jac->schurpre = ptype;
1017084e4875SJed Brown   if (pre) {
1018084e4875SJed Brown     if (jac->schur_user) {ierr = MatDestroy(jac->schur_user);CHKERRQ(ierr);}
1019084e4875SJed Brown     jac->schur_user = pre;
1020084e4875SJed Brown     ierr = PetscObjectReference((PetscObject)jac->schur_user);CHKERRQ(ierr);
1021084e4875SJed Brown   }
1022e69d4d44SBarry Smith   PetscFunctionReturn(0);
1023e69d4d44SBarry Smith }
1024e69d4d44SBarry Smith EXTERN_C_END
1025e69d4d44SBarry Smith 
102630ad9308SMatthew Knepley #undef __FUNCT__
102730ad9308SMatthew Knepley #define __FUNCT__ "PCFieldSplitGetSchurBlocks"
102830ad9308SMatthew Knepley /*@C
102930ad9308SMatthew Knepley    PCFieldSplitGetSchurBlocks - Gets the all matrix blocks for the Schur complement
103030ad9308SMatthew Knepley 
103130ad9308SMatthew Knepley    Collective on KSP
103230ad9308SMatthew Knepley 
103330ad9308SMatthew Knepley    Input Parameter:
103430ad9308SMatthew Knepley .  pc - the preconditioner context
103530ad9308SMatthew Knepley 
103630ad9308SMatthew Knepley    Output Parameters:
103730ad9308SMatthew Knepley +  A - the (0,0) block
103830ad9308SMatthew Knepley .  B - the (0,1) block
103930ad9308SMatthew Knepley .  C - the (1,0) block
104030ad9308SMatthew Knepley -  D - the (1,1) block
104130ad9308SMatthew Knepley 
104230ad9308SMatthew Knepley    Level: advanced
104330ad9308SMatthew Knepley 
104430ad9308SMatthew Knepley .seealso: PCFIELDSPLIT
104530ad9308SMatthew Knepley @*/
104630ad9308SMatthew Knepley PetscErrorCode PETSCKSP_DLLEXPORT PCFieldSplitGetSchurBlocks(PC pc,Mat *A,Mat *B,Mat *C, Mat *D)
104730ad9308SMatthew Knepley {
104830ad9308SMatthew Knepley   PC_FieldSplit *jac = (PC_FieldSplit *) pc->data;
104930ad9308SMatthew Knepley 
105030ad9308SMatthew Knepley   PetscFunctionBegin;
105130ad9308SMatthew Knepley   PetscValidHeaderSpecific(pc,PC_COOKIE,1);
1052cf8ad460SMatthew Knepley   if (jac->type != PC_COMPOSITE_SCHUR) {SETERRQ(PETSC_ERR_ARG_WRONG, "FieldSplit is not using a Schur complement approach.");}
105330ad9308SMatthew Knepley   if (A) *A = jac->pmat[0];
105430ad9308SMatthew Knepley   if (B) *B = jac->B;
105530ad9308SMatthew Knepley   if (C) *C = jac->C;
105630ad9308SMatthew Knepley   if (D) *D = jac->pmat[1];
105730ad9308SMatthew Knepley   PetscFunctionReturn(0);
105830ad9308SMatthew Knepley }
105930ad9308SMatthew Knepley 
106079416396SBarry Smith EXTERN_C_BEGIN
106179416396SBarry Smith #undef __FUNCT__
106279416396SBarry Smith #define __FUNCT__ "PCFieldSplitSetType_FieldSplit"
1063dba47a55SKris Buschelman PetscErrorCode PETSCKSP_DLLEXPORT PCFieldSplitSetType_FieldSplit(PC pc,PCCompositeType type)
106479416396SBarry Smith {
106579416396SBarry Smith   PC_FieldSplit  *jac = (PC_FieldSplit*)pc->data;
1066e69d4d44SBarry Smith   PetscErrorCode ierr;
106779416396SBarry Smith 
106879416396SBarry Smith   PetscFunctionBegin;
106979416396SBarry Smith   jac->type = type;
10703b224e63SBarry Smith   if (type == PC_COMPOSITE_SCHUR) {
10713b224e63SBarry Smith     pc->ops->apply = PCApply_FieldSplit_Schur;
10723b224e63SBarry Smith     pc->ops->view  = PCView_FieldSplit_Schur;
1073e69d4d44SBarry Smith     ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCFieldSplitGetSubKSP_C","PCFieldSplitGetSubKSP_FieldSplit_Schur",PCFieldSplitGetSubKSP_FieldSplit_Schur);CHKERRQ(ierr);
1074e69d4d44SBarry Smith     ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCFieldSplitSchurPrecondition_C","PCFieldSplitSchurPrecondition_FieldSplit",PCFieldSplitSchurPrecondition_FieldSplit);CHKERRQ(ierr);
1075e69d4d44SBarry Smith 
10763b224e63SBarry Smith   } else {
10773b224e63SBarry Smith     pc->ops->apply = PCApply_FieldSplit;
10783b224e63SBarry Smith     pc->ops->view  = PCView_FieldSplit;
1079e69d4d44SBarry Smith     ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCFieldSplitGetSubKSP_C","PCFieldSplitGetSubKSP_FieldSplit",PCFieldSplitGetSubKSP_FieldSplit);CHKERRQ(ierr);
10809e7d6b0aSBarry Smith     ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCFieldSplitSchurPrecondition_C","",0);CHKERRQ(ierr);
10813b224e63SBarry Smith   }
108279416396SBarry Smith   PetscFunctionReturn(0);
108379416396SBarry Smith }
108479416396SBarry Smith EXTERN_C_END
108579416396SBarry Smith 
108651f519a2SBarry Smith EXTERN_C_BEGIN
108751f519a2SBarry Smith #undef __FUNCT__
108851f519a2SBarry Smith #define __FUNCT__ "PCFieldSplitSetBlockSize_FieldSplit"
108951f519a2SBarry Smith PetscErrorCode PETSCKSP_DLLEXPORT PCFieldSplitSetBlockSize_FieldSplit(PC pc,PetscInt bs)
109051f519a2SBarry Smith {
109151f519a2SBarry Smith   PC_FieldSplit  *jac = (PC_FieldSplit*)pc->data;
109251f519a2SBarry Smith 
109351f519a2SBarry Smith   PetscFunctionBegin;
109451f519a2SBarry Smith   if (bs < 1) SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,"Blocksize must be positive, you gave %D",bs);
109551f519a2SBarry 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);
109651f519a2SBarry Smith   jac->bs = bs;
109751f519a2SBarry Smith   PetscFunctionReturn(0);
109851f519a2SBarry Smith }
109951f519a2SBarry Smith EXTERN_C_END
110051f519a2SBarry Smith 
110179416396SBarry Smith #undef __FUNCT__
110279416396SBarry Smith #define __FUNCT__ "PCFieldSplitSetType"
1103bc08b0f1SBarry Smith /*@
110479416396SBarry Smith    PCFieldSplitSetType - Sets the type of fieldsplit preconditioner.
110579416396SBarry Smith 
110679416396SBarry Smith    Collective on PC
110779416396SBarry Smith 
110879416396SBarry Smith    Input Parameter:
110979416396SBarry Smith .  pc - the preconditioner context
111081540f2fSBarry Smith .  type - PC_COMPOSITE_ADDITIVE, PC_COMPOSITE_MULTIPLICATIVE (default), PC_COMPOSITE_SYMMETRIC_MULTIPLICATIVE, PC_COMPOSITE_SPECIAL, PC_COMPOSITE_SCHUR
111179416396SBarry Smith 
111279416396SBarry Smith    Options Database Key:
1113a4efd8eaSMatthew Knepley .  -pc_fieldsplit_type <type: one of multiplicative, additive, symmetric_multiplicative, special, schur> - Sets fieldsplit preconditioner type
111479416396SBarry Smith 
111579416396SBarry Smith    Level: Developer
111679416396SBarry Smith 
111779416396SBarry Smith .keywords: PC, set, type, composite preconditioner, additive, multiplicative
111879416396SBarry Smith 
111979416396SBarry Smith .seealso: PCCompositeSetType()
112079416396SBarry Smith 
112179416396SBarry Smith @*/
1122dba47a55SKris Buschelman PetscErrorCode PETSCKSP_DLLEXPORT PCFieldSplitSetType(PC pc,PCCompositeType type)
112379416396SBarry Smith {
112479416396SBarry Smith   PetscErrorCode ierr,(*f)(PC,PCCompositeType);
112579416396SBarry Smith 
112679416396SBarry Smith   PetscFunctionBegin;
112779416396SBarry Smith   PetscValidHeaderSpecific(pc,PC_COOKIE,1);
112879416396SBarry Smith   ierr = PetscObjectQueryFunction((PetscObject)pc,"PCFieldSplitSetType_C",(void (**)(void))&f);CHKERRQ(ierr);
112979416396SBarry Smith   if (f) {
113079416396SBarry Smith     ierr = (*f)(pc,type);CHKERRQ(ierr);
113179416396SBarry Smith   }
113279416396SBarry Smith   PetscFunctionReturn(0);
113379416396SBarry Smith }
113479416396SBarry Smith 
11350971522cSBarry Smith /* -------------------------------------------------------------------------------------*/
11360971522cSBarry Smith /*MC
1137a8c7a070SBarry Smith    PCFIELDSPLIT - Preconditioner created by combining separate preconditioners for individual
11380971522cSBarry Smith                   fields or groups of fields
11390971522cSBarry Smith 
11400971522cSBarry Smith 
1141edf189efSBarry Smith      To set options on the solvers for each block append -fieldsplit_ to all the PC
1142edf189efSBarry Smith         options database keys. For example, -fieldsplit_pc_type ilu -fieldsplit_pc_factor_levels 1
11430971522cSBarry Smith 
1144a8c7a070SBarry Smith      To set the options on the solvers separate for each block call PCFieldSplitGetSubKSP()
114569a612a9SBarry Smith          and set the options directly on the resulting KSP object
11460971522cSBarry Smith 
11470971522cSBarry Smith    Level: intermediate
11480971522cSBarry Smith 
114979416396SBarry Smith    Options Database Keys:
115081540f2fSBarry Smith +   -pc_fieldsplit_%d_fields <a,b,..> - indicates the fields to be used in the %d'th split
115181540f2fSBarry Smith .   -pc_fieldsplit_default - automatically add any fields to additional splits that have not
115281540f2fSBarry Smith                               been supplied explicitly by -pc_fieldsplit_%d_fields
115381540f2fSBarry Smith .   -pc_fieldsplit_block_size <bs> - size of block that defines fields (i.e. there are bs fields)
115481540f2fSBarry Smith .    -pc_fieldsplit_type <additive,multiplicative,schur,symmetric_multiplicative>
1155e69d4d44SBarry Smith .    -pc_fieldsplit_schur_precondition <true,false> default is true
115679416396SBarry Smith 
1157edf189efSBarry Smith -    Options prefix for inner solvers when using Schur complement preconditioner are -fieldsplit_0_ and -fieldsplit_1_
11583b224e63SBarry Smith      for all other solvers they are -fieldsplit_%d_ for the dth field, use -fieldsplit_ for all fields
11593b224e63SBarry Smith 
11603b224e63SBarry Smith 
1161d32f9abdSBarry Smith    Notes: use PCFieldSplitSetFields() to set fields defined by "strided" entries and PCFieldSplitSetIS()
1162d32f9abdSBarry Smith      to define a field by an arbitrary collection of entries.
1163d32f9abdSBarry Smith 
1164d32f9abdSBarry Smith       If no fields are set the default is used. The fields are defined by entries strided by bs,
1165d32f9abdSBarry Smith       beginning at 0 then 1, etc to bs-1. The block size can be set with PCFieldSplitSetBlockSize(),
1166d32f9abdSBarry Smith       if this is not called the block size defaults to the blocksize of the second matrix passed
1167d32f9abdSBarry Smith       to KSPSetOperators()/PCSetOperators().
1168d32f9abdSBarry Smith 
1169d32f9abdSBarry Smith       Currently for the multiplicative version, the updated residual needed for the next field
1170d32f9abdSBarry Smith      solve is computed via a matrix vector product over the entire array. An optimization would be
1171d32f9abdSBarry Smith      to update the residual only for the part of the right hand side associated with the next field
1172d32f9abdSBarry Smith      solve. (This would involve more MatGetSubMatrix() calls or some other mechanism to compute the
1173d32f9abdSBarry Smith      part of the matrix needed to just update part of the residual).
1174d32f9abdSBarry Smith 
1175e69d4d44SBarry Smith      For the Schur complement preconditioner if J = ( A B )
1176e69d4d44SBarry Smith                                                     ( C D )
1177e69d4d44SBarry Smith      the preconditioner is
1178e69d4d44SBarry Smith               (I   -B inv(A)) ( inv(A)   0    ) (I         0  )
1179e69d4d44SBarry Smith               (0    I       ) (   0    inv(S) ) (-C inv(A) I  )
1180edf189efSBarry Smith      where the action of inv(A) is applied using the KSP solver with prefix -fieldsplit_0_. The action of
1181e69d4d44SBarry Smith      inv(S) is computed using the KSP solver with prefix -schur_. For PCFieldSplitGetKSP() when field number is
1182edf189efSBarry Smith      0 it returns the KSP associated with -fieldsplit_0_ while field number 1 gives -fieldsplit_1_ KSP. By default
1183e69d4d44SBarry Smith      D is used to construct a preconditioner for S, use PCFieldSplitSchurPrecondition() to turn on or off this
1184e69d4d44SBarry Smith      option.
1185e69d4d44SBarry Smith 
1186edf189efSBarry Smith      If only one set of indices (one IS) is provided with PCFieldSplitSetIS() then the complement of that IS
1187edf189efSBarry Smith      is used automatically for a second block.
1188edf189efSBarry Smith 
1189a541d17aSBarry Smith    Concepts: physics based preconditioners, block preconditioners
11900971522cSBarry Smith 
1191a541d17aSBarry Smith .seealso:  PCCreate(), PCSetType(), PCType (for list of available types), PC, Block_Preconditioners
1192e69d4d44SBarry Smith            PCFieldSplitGetSubKSP(), PCFieldSplitSetFields(), PCFieldSplitSetType(), PCFieldSplitSetIS(), PCFieldSplitSchurPrecondition()
11930971522cSBarry Smith M*/
11940971522cSBarry Smith 
11950971522cSBarry Smith EXTERN_C_BEGIN
11960971522cSBarry Smith #undef __FUNCT__
11970971522cSBarry Smith #define __FUNCT__ "PCCreate_FieldSplit"
1198dba47a55SKris Buschelman PetscErrorCode PETSCKSP_DLLEXPORT PCCreate_FieldSplit(PC pc)
11990971522cSBarry Smith {
12000971522cSBarry Smith   PetscErrorCode ierr;
12010971522cSBarry Smith   PC_FieldSplit  *jac;
12020971522cSBarry Smith 
12030971522cSBarry Smith   PetscFunctionBegin;
120438f2d2fdSLisandro Dalcin   ierr = PetscNewLog(pc,PC_FieldSplit,&jac);CHKERRQ(ierr);
12050971522cSBarry Smith   jac->bs        = -1;
12060971522cSBarry Smith   jac->nsplits   = 0;
12073e197d65SBarry Smith   jac->type      = PC_COMPOSITE_MULTIPLICATIVE;
1208e6cab6aaSJed Brown   jac->schurpre  = PC_FIELDSPLIT_SCHUR_PRE_USER; /* Try user preconditioner first, fall back on diagonal */
120951f519a2SBarry Smith 
12100971522cSBarry Smith   pc->data     = (void*)jac;
12110971522cSBarry Smith 
12120971522cSBarry Smith   pc->ops->apply             = PCApply_FieldSplit;
1213421e10b8SBarry Smith   pc->ops->applytranspose    = PCApplyTranspose_FieldSplit;
12140971522cSBarry Smith   pc->ops->setup             = PCSetUp_FieldSplit;
12150971522cSBarry Smith   pc->ops->destroy           = PCDestroy_FieldSplit;
12160971522cSBarry Smith   pc->ops->setfromoptions    = PCSetFromOptions_FieldSplit;
12170971522cSBarry Smith   pc->ops->view              = PCView_FieldSplit;
12180971522cSBarry Smith   pc->ops->applyrichardson   = 0;
12190971522cSBarry Smith 
122069a612a9SBarry Smith   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCFieldSplitGetSubKSP_C","PCFieldSplitGetSubKSP_FieldSplit",
122169a612a9SBarry Smith                     PCFieldSplitGetSubKSP_FieldSplit);CHKERRQ(ierr);
12220971522cSBarry Smith   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCFieldSplitSetFields_C","PCFieldSplitSetFields_FieldSplit",
12230971522cSBarry Smith                     PCFieldSplitSetFields_FieldSplit);CHKERRQ(ierr);
1224704ba839SBarry Smith   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCFieldSplitSetIS_C","PCFieldSplitSetIS_FieldSplit",
1225704ba839SBarry Smith                     PCFieldSplitSetIS_FieldSplit);CHKERRQ(ierr);
122679416396SBarry Smith   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCFieldSplitSetType_C","PCFieldSplitSetType_FieldSplit",
122779416396SBarry Smith                     PCFieldSplitSetType_FieldSplit);CHKERRQ(ierr);
122851f519a2SBarry Smith   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCFieldSplitSetBlockSize_C","PCFieldSplitSetBlockSize_FieldSplit",
122951f519a2SBarry Smith                     PCFieldSplitSetBlockSize_FieldSplit);CHKERRQ(ierr);
12300971522cSBarry Smith   PetscFunctionReturn(0);
12310971522cSBarry Smith }
12320971522cSBarry Smith EXTERN_C_END
12330971522cSBarry Smith 
12340971522cSBarry Smith 
1235a541d17aSBarry Smith /*MC
1236a541d17aSBarry Smith    Block_Preconditioners - PETSc provides support for a variety of "block preconditioners", this provides an
1237a541d17aSBarry Smith           overview of these methods.
1238a541d17aSBarry Smith 
1239a541d17aSBarry Smith       Consider the solution to ( A B ) (x_1)  =  (b_1)
1240a541d17aSBarry Smith                                ( C D ) (x_2)     (b_2)
1241a541d17aSBarry Smith 
1242a541d17aSBarry Smith       Important special cases, the Stokes equation: C = B' and D = 0  (A   B) (x_1) = (b_1)
1243a541d17aSBarry Smith                                                                        B'  0) (x_2)   (b_2)
1244a541d17aSBarry Smith 
1245a541d17aSBarry Smith       One of the goals of the PCFieldSplit preconditioner in PETSc is to provide a variety of preconditioners
1246a541d17aSBarry Smith       for this block system.
1247a541d17aSBarry Smith 
1248a541d17aSBarry Smith       Consider an additional matrix (Ap  Bp)
1249a541d17aSBarry Smith                                     (Cp  Dp) where some or all of the entries may be the same as
1250a541d17aSBarry Smith       in the original matrix (for example Ap == A).
1251a541d17aSBarry Smith 
1252a541d17aSBarry Smith       In the following, A^ denotes the approximate application of the inverse of A, possibly using Ap in the
1253a541d17aSBarry Smith       approximation. In PETSc this simply means one has called KSPSetOperators(ksp,A,Ap,...) or KSPSetOperators(ksp,Ap,Ap,...)
1254a541d17aSBarry Smith 
1255a541d17aSBarry Smith       Block Jacobi:   x_1 = A^ b_1
1256a541d17aSBarry Smith                       x_2 = D^ b_2
1257a541d17aSBarry Smith 
1258a541d17aSBarry Smith       Lower block Gauss-Seidel:   x_1 = A^ b_1
1259a541d17aSBarry Smith                             x_2 = D^ (b_2 - C x_1)       variant x_2 = D^ (b_2 - Cp x_1)
1260a541d17aSBarry Smith 
1261a541d17aSBarry Smith       Symmetric Gauss-Seidel:  x_1 = x_1 + A^(b_1 - A x_1 - B x_2)    variant  x_1 = x_1 + A^(b_1 - Ap x_1 - Bp x_2)
1262a541d17aSBarry Smith           Interestingly this form is not actually a symmetric matrix, the symmetric version is
1263a541d17aSBarry Smith                               x_1 = A^(b_1 - B x_2)      variant x_1 = A^(b_1 - Bp x_2)
1264a541d17aSBarry Smith 
12650bc0a719SBarry Smith    Level: intermediate
12660bc0a719SBarry Smith 
1267a541d17aSBarry Smith .seealso:  PCCreate(), PCSetType(), PCType (for list of available types), PC, PCFIELDSPLIT
1268a541d17aSBarry Smith            PCFieldSplitGetSubKSP(), PCFieldSplitSetFields(), PCFieldSplitSetType(), PCFieldSplitSetIS(), PCFieldSplitSchurPrecondition()
1269a541d17aSBarry Smith M*/
1270