xref: /petsc/src/ksp/pc/impls/fieldsplit/fieldsplit.c (revision fcfd50eb5fbe12291db06fc1b33ad004ead64926)
1dba47a55SKris Buschelman 
2c6db04a5SJed Brown #include <private/pcimpl.h>     /*I "petscpc.h" I*/
33c48a1e8SJed Brown #include <petscdmcomposite.h>   /*I "petscdmcomposite.h" I*/
40971522cSBarry Smith 
5f7c28744SJed Brown const char *const PCFieldSplitSchurPreTypes[] = {"SELF","DIAG","USER","PCFieldSplitSchurPreType","PC_FIELDSPLIT_SCHUR_PRE_",0};
6f7c28744SJed Brown const char *const PCFieldSplitSchurFactorizationTypes[] = {"DIAG","LOWER","UPPER","FULL","PCFieldSplitSchurFactorizationType","PC_FIELDSPLIT_SCHUR_FACTORIZATION_",0};
7c5d2311dSJed Brown 
8c5d2311dSJed Brown typedef enum {
9c5d2311dSJed Brown   PC_FIELDSPLIT_SCHUR_FACTORIZATION_DIAG,
10c5d2311dSJed Brown   PC_FIELDSPLIT_SCHUR_FACTORIZATION_LOWER,
11c5d2311dSJed Brown   PC_FIELDSPLIT_SCHUR_FACTORIZATION_UPPER,
12c5d2311dSJed Brown   PC_FIELDSPLIT_SCHUR_FACTORIZATION_FULL
13c5d2311dSJed Brown } PCFieldSplitSchurFactorizationType;
14084e4875SJed Brown 
150971522cSBarry Smith typedef struct _PC_FieldSplitLink *PC_FieldSplitLink;
160971522cSBarry Smith struct _PC_FieldSplitLink {
1769a612a9SBarry Smith   KSP               ksp;
180971522cSBarry Smith   Vec               x,y;
19db4c96c1SJed Brown   char              *splitname;
200971522cSBarry Smith   PetscInt          nfields;
210971522cSBarry Smith   PetscInt          *fields;
221b9fc7fcSBarry Smith   VecScatter        sctx;
234aa3045dSJed Brown   IS                is;
2451f519a2SBarry Smith   PC_FieldSplitLink next,previous;
250971522cSBarry Smith };
260971522cSBarry Smith 
270971522cSBarry Smith typedef struct {
2868dd23aaSBarry Smith   PCCompositeType                    type;
29ace3abfcSBarry Smith   PetscBool                          defaultsplit; /* Flag for a system with a set of 'k' scalar fields with the same layout (and bs = k) */
30ace3abfcSBarry Smith   PetscBool                          splitdefined; /* Flag is set after the splits have been defined, to prevent more splits from being added */
31ace3abfcSBarry Smith   PetscBool                          realdiagonal; /* Flag to use the diagonal blocks of mat preconditioned by pmat, instead of just pmat */
3230ad9308SMatthew Knepley   PetscInt                           bs;           /* Block size for IS and Mat structures */
3330ad9308SMatthew Knepley   PetscInt                           nsplits;      /* Number of field divisions defined */
3479416396SBarry Smith   Vec                                *x,*y,w1,w2;
35519d70e2SJed Brown   Mat                                *mat;         /* The diagonal block for each split */
36519d70e2SJed Brown   Mat                                *pmat;        /* The preconditioning diagonal block for each split */
3730ad9308SMatthew Knepley   Mat                                *Afield;      /* The rows of the matrix associated with each split */
38ace3abfcSBarry Smith   PetscBool                          issetup;
3930ad9308SMatthew Knepley   /* Only used when Schur complement preconditioning is used */
4030ad9308SMatthew Knepley   Mat                                B;            /* The (0,1) block */
4130ad9308SMatthew Knepley   Mat                                C;            /* The (1,0) block */
42a04f6461SBarry Smith   Mat                                schur;        /* The Schur complement S = A11 - A10 A00^{-1} A01 */
43084e4875SJed Brown   Mat                                schur_user;   /* User-provided preconditioning matrix for the Schur complement */
44084e4875SJed Brown   PCFieldSplitSchurPreType           schurpre; /* Determines which preconditioning matrix is used for the Schur complement */
45c5d2311dSJed Brown   PCFieldSplitSchurFactorizationType schurfactorization;
4630ad9308SMatthew Knepley   KSP                                kspschur;     /* The solver for S */
4797bbdb24SBarry Smith   PC_FieldSplitLink                  head;
480971522cSBarry Smith } PC_FieldSplit;
490971522cSBarry Smith 
5016913363SBarry Smith /*
5116913363SBarry Smith     Notes: there is no particular reason that pmat, x, and y are stored as arrays in PC_FieldSplit instead of
5216913363SBarry Smith    inside PC_FieldSplitLink, just historical. If you want to be able to add new fields after already using the
5316913363SBarry Smith    PC you could change this.
5416913363SBarry Smith */
55084e4875SJed Brown 
56e6cab6aaSJed Brown /* This helper is so that setting a user-provided preconditioning matrix is orthogonal to choosing to use it.  This way the
57084e4875SJed Brown * application-provided FormJacobian can provide this matrix without interfering with the user's (command-line) choices. */
58084e4875SJed Brown static Mat FieldSplitSchurPre(PC_FieldSplit *jac)
59084e4875SJed Brown {
60084e4875SJed Brown   switch (jac->schurpre) {
61084e4875SJed Brown     case PC_FIELDSPLIT_SCHUR_PRE_SELF: return jac->schur;
62084e4875SJed Brown     case PC_FIELDSPLIT_SCHUR_PRE_DIAG: return jac->pmat[1];
63084e4875SJed Brown     case PC_FIELDSPLIT_SCHUR_PRE_USER: /* Use a user-provided matrix if it is given, otherwise diagonal block */
64084e4875SJed Brown     default:
65084e4875SJed Brown       return jac->schur_user ? jac->schur_user : jac->pmat[1];
66084e4875SJed Brown   }
67084e4875SJed Brown }
68084e4875SJed Brown 
69084e4875SJed Brown 
700971522cSBarry Smith #undef __FUNCT__
710971522cSBarry Smith #define __FUNCT__ "PCView_FieldSplit"
720971522cSBarry Smith static PetscErrorCode PCView_FieldSplit(PC pc,PetscViewer viewer)
730971522cSBarry Smith {
740971522cSBarry Smith   PC_FieldSplit     *jac = (PC_FieldSplit*)pc->data;
750971522cSBarry Smith   PetscErrorCode    ierr;
76ace3abfcSBarry Smith   PetscBool         iascii;
770971522cSBarry Smith   PetscInt          i,j;
785a9f2f41SSatish Balay   PC_FieldSplitLink ilink = jac->head;
790971522cSBarry Smith 
800971522cSBarry Smith   PetscFunctionBegin;
812692d6eeSBarry Smith   ierr = PetscTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
820971522cSBarry Smith   if (iascii) {
8351f519a2SBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  FieldSplit with %s composition: total splits = %D, blocksize = %D\n",PCCompositeTypes[jac->type],jac->nsplits,jac->bs);CHKERRQ(ierr);
8469a612a9SBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  Solver info for each split is in the following KSP objects:\n");CHKERRQ(ierr);
850971522cSBarry Smith     ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr);
860971522cSBarry Smith     for (i=0; i<jac->nsplits; i++) {
871ab39975SBarry Smith       if (ilink->fields) {
880971522cSBarry Smith 	ierr = PetscViewerASCIIPrintf(viewer,"Split number %D Fields ",i);CHKERRQ(ierr);
8979416396SBarry Smith 	ierr = PetscViewerASCIIUseTabs(viewer,PETSC_FALSE);CHKERRQ(ierr);
905a9f2f41SSatish Balay 	for (j=0; j<ilink->nfields; j++) {
9179416396SBarry Smith 	  if (j > 0) {
9279416396SBarry Smith 	    ierr = PetscViewerASCIIPrintf(viewer,",");CHKERRQ(ierr);
9379416396SBarry Smith 	  }
945a9f2f41SSatish Balay 	  ierr = PetscViewerASCIIPrintf(viewer," %D",ilink->fields[j]);CHKERRQ(ierr);
950971522cSBarry Smith 	}
960971522cSBarry Smith 	ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr);
9779416396SBarry Smith         ierr = PetscViewerASCIIUseTabs(viewer,PETSC_TRUE);CHKERRQ(ierr);
981ab39975SBarry Smith       } else {
991ab39975SBarry Smith 	ierr = PetscViewerASCIIPrintf(viewer,"Split number %D Defined by IS\n",i);CHKERRQ(ierr);
1001ab39975SBarry Smith       }
1015a9f2f41SSatish Balay       ierr = KSPView(ilink->ksp,viewer);CHKERRQ(ierr);
1025a9f2f41SSatish Balay       ilink = ilink->next;
1030971522cSBarry Smith     }
1040971522cSBarry Smith     ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr);
1050971522cSBarry Smith   } else {
10665e19b50SBarry Smith     SETERRQ1(((PetscObject)pc)->comm,PETSC_ERR_SUP,"Viewer type %s not supported for PCFieldSplit",((PetscObject)viewer)->type_name);
1070971522cSBarry Smith   }
1080971522cSBarry Smith   PetscFunctionReturn(0);
1090971522cSBarry Smith }
1100971522cSBarry Smith 
1110971522cSBarry Smith #undef __FUNCT__
1123b224e63SBarry Smith #define __FUNCT__ "PCView_FieldSplit_Schur"
1133b224e63SBarry Smith static PetscErrorCode PCView_FieldSplit_Schur(PC pc,PetscViewer viewer)
1143b224e63SBarry Smith {
1153b224e63SBarry Smith   PC_FieldSplit     *jac = (PC_FieldSplit*)pc->data;
1163b224e63SBarry Smith   PetscErrorCode    ierr;
117ace3abfcSBarry Smith   PetscBool         iascii;
1183b224e63SBarry Smith   PetscInt          i,j;
1193b224e63SBarry Smith   PC_FieldSplitLink ilink = jac->head;
1203b224e63SBarry Smith   KSP               ksp;
1213b224e63SBarry Smith 
1223b224e63SBarry Smith   PetscFunctionBegin;
1232692d6eeSBarry Smith   ierr = PetscTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
1243b224e63SBarry Smith   if (iascii) {
125c5d2311dSJed Brown     ierr = PetscViewerASCIIPrintf(viewer,"  FieldSplit with Schur preconditioner, blocksize = %D, factorization %s\n",jac->bs,PCFieldSplitSchurFactorizationTypes[jac->schurfactorization]);CHKERRQ(ierr);
1263b224e63SBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  Split info:\n");CHKERRQ(ierr);
1273b224e63SBarry Smith     ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr);
1283b224e63SBarry Smith     for (i=0; i<jac->nsplits; i++) {
1293b224e63SBarry Smith       if (ilink->fields) {
1303b224e63SBarry Smith 	ierr = PetscViewerASCIIPrintf(viewer,"Split number %D Fields ",i);CHKERRQ(ierr);
1313b224e63SBarry Smith 	ierr = PetscViewerASCIIUseTabs(viewer,PETSC_FALSE);CHKERRQ(ierr);
1323b224e63SBarry Smith 	for (j=0; j<ilink->nfields; j++) {
1333b224e63SBarry Smith 	  if (j > 0) {
1343b224e63SBarry Smith 	    ierr = PetscViewerASCIIPrintf(viewer,",");CHKERRQ(ierr);
1353b224e63SBarry Smith 	  }
1363b224e63SBarry Smith 	  ierr = PetscViewerASCIIPrintf(viewer," %D",ilink->fields[j]);CHKERRQ(ierr);
1373b224e63SBarry Smith 	}
1383b224e63SBarry Smith 	ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr);
1393b224e63SBarry Smith         ierr = PetscViewerASCIIUseTabs(viewer,PETSC_TRUE);CHKERRQ(ierr);
1403b224e63SBarry Smith       } else {
1413b224e63SBarry Smith 	ierr = PetscViewerASCIIPrintf(viewer,"Split number %D Defined by IS\n",i);CHKERRQ(ierr);
1423b224e63SBarry Smith       }
1433b224e63SBarry Smith       ilink = ilink->next;
1443b224e63SBarry Smith     }
145435f959eSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"KSP solver for A00 block \n");CHKERRQ(ierr);
1463b224e63SBarry Smith     ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr);
14712cae6f2SJed Brown     if (jac->schur) {
14812cae6f2SJed Brown       ierr = MatSchurComplementGetKSP(jac->schur,&ksp);CHKERRQ(ierr);
1493b224e63SBarry Smith       ierr = KSPView(ksp,viewer);CHKERRQ(ierr);
15012cae6f2SJed Brown     } else {
15112cae6f2SJed Brown       ierr = PetscViewerASCIIPrintf(viewer,"  not yet available\n");CHKERRQ(ierr);
15212cae6f2SJed Brown     }
1533b224e63SBarry Smith     ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr);
154435f959eSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"KSP solver for S = A11 - A10 inv(A00) A01 \n");CHKERRQ(ierr);
1553b224e63SBarry Smith     ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr);
15612cae6f2SJed Brown     if (jac->kspschur) {
1573b224e63SBarry Smith       ierr = KSPView(jac->kspschur,viewer);CHKERRQ(ierr);
15812cae6f2SJed Brown     } else {
15912cae6f2SJed Brown       ierr = PetscViewerASCIIPrintf(viewer,"  not yet available\n");CHKERRQ(ierr);
16012cae6f2SJed Brown     }
1613b224e63SBarry Smith     ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr);
1623b224e63SBarry Smith     ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr);
1633b224e63SBarry Smith   } else {
16465e19b50SBarry Smith     SETERRQ1(((PetscObject)pc)->comm,PETSC_ERR_SUP,"Viewer type %s not supported for PCFieldSplit",((PetscObject)viewer)->type_name);
1653b224e63SBarry Smith   }
1663b224e63SBarry Smith   PetscFunctionReturn(0);
1673b224e63SBarry Smith }
1683b224e63SBarry Smith 
1693b224e63SBarry Smith #undef __FUNCT__
1706c924f48SJed Brown #define __FUNCT__ "PCFieldSplitSetRuntimeSplits_Private"
1716c924f48SJed Brown /* Precondition: jac->bs is set to a meaningful value */
1726c924f48SJed Brown static PetscErrorCode PCFieldSplitSetRuntimeSplits_Private(PC pc)
1736c924f48SJed Brown {
1746c924f48SJed Brown   PetscErrorCode ierr;
1756c924f48SJed Brown   PC_FieldSplit  *jac = (PC_FieldSplit*)pc->data;
1766c924f48SJed Brown   PetscInt       i,nfields,*ifields;
177ace3abfcSBarry Smith   PetscBool      flg;
1786c924f48SJed Brown   char           optionname[128],splitname[8];
1796c924f48SJed Brown 
1806c924f48SJed Brown   PetscFunctionBegin;
1816c924f48SJed Brown   ierr = PetscMalloc(jac->bs*sizeof(PetscInt),&ifields);CHKERRQ(ierr);
1826c924f48SJed Brown   for (i=0,flg=PETSC_TRUE; ; i++) {
1836c924f48SJed Brown     ierr = PetscSNPrintf(splitname,sizeof splitname,"%D",i);CHKERRQ(ierr);
1846c924f48SJed Brown     ierr = PetscSNPrintf(optionname,sizeof optionname,"-pc_fieldsplit_%D_fields",i);CHKERRQ(ierr);
1856c924f48SJed Brown     nfields = jac->bs;
1866c924f48SJed Brown     ierr    = PetscOptionsGetIntArray(((PetscObject)pc)->prefix,optionname,ifields,&nfields,&flg);CHKERRQ(ierr);
1876c924f48SJed Brown     if (!flg) break;
1886c924f48SJed Brown     if (!nfields) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_USER,"Cannot list zero fields");
1896c924f48SJed Brown     ierr = PCFieldSplitSetFields(pc,splitname,nfields,ifields);CHKERRQ(ierr);
1906c924f48SJed Brown   }
1916c924f48SJed Brown   if (i > 0) {
1926c924f48SJed Brown     /* Makes command-line setting of splits take precedence over setting them in code.
1936c924f48SJed Brown        Otherwise subsequent calls to PCFieldSplitSetIS() or PCFieldSplitSetFields() would
1946c924f48SJed Brown        create new splits, which would probably not be what the user wanted. */
1956c924f48SJed Brown     jac->splitdefined = PETSC_TRUE;
1966c924f48SJed Brown   }
1976c924f48SJed Brown   ierr = PetscFree(ifields);CHKERRQ(ierr);
1986c924f48SJed Brown   PetscFunctionReturn(0);
1996c924f48SJed Brown }
2006c924f48SJed Brown 
2016c924f48SJed Brown #undef __FUNCT__
20269a612a9SBarry Smith #define __FUNCT__ "PCFieldSplitSetDefaults"
20369a612a9SBarry Smith static PetscErrorCode PCFieldSplitSetDefaults(PC pc)
2040971522cSBarry Smith {
2050971522cSBarry Smith   PC_FieldSplit     *jac  = (PC_FieldSplit*)pc->data;
2060971522cSBarry Smith   PetscErrorCode    ierr;
2075a9f2f41SSatish Balay   PC_FieldSplitLink ilink = jac->head;
2086ce1633cSBarry Smith   PetscBool         flg = PETSC_FALSE,stokes = PETSC_FALSE;
2096c924f48SJed Brown   PetscInt          i;
2100971522cSBarry Smith 
2110971522cSBarry Smith   PetscFunctionBegin;
212d32f9abdSBarry Smith   if (!ilink) {
2138b8307b2SJed Brown     if (pc->dm) {
2148b8307b2SJed Brown       PetscBool dmcomposite;
2158b8307b2SJed Brown       ierr = PetscTypeCompare((PetscObject)pc->dm,DMCOMPOSITE,&dmcomposite);CHKERRQ(ierr);
2168b8307b2SJed Brown       if (dmcomposite) {
2178b8307b2SJed Brown         PetscInt nDM;
2188b8307b2SJed Brown         IS       *fields;
2198b8307b2SJed Brown         ierr = PetscInfo(pc,"Setting up physics based fieldsplit preconditioner using the embedded DM\n");CHKERRQ(ierr);
2208b8307b2SJed Brown         ierr = DMCompositeGetNumberDM(pc->dm,&nDM);CHKERRQ(ierr);
2218b8307b2SJed Brown         ierr = DMCompositeGetGlobalISs(pc->dm,&fields);CHKERRQ(ierr);
2228b8307b2SJed Brown         for (i=0; i<nDM; i++) {
2238b8307b2SJed Brown           char splitname[8];
2248b8307b2SJed Brown           ierr = PetscSNPrintf(splitname,sizeof splitname,"%D",i);CHKERRQ(ierr);
2258b8307b2SJed Brown           ierr = PCFieldSplitSetIS(pc,splitname,fields[i]);CHKERRQ(ierr);
226*fcfd50ebSBarry Smith           ierr = ISDestroy(&fields[i]);CHKERRQ(ierr);
2278b8307b2SJed Brown         }
2288b8307b2SJed Brown         ierr = PetscFree(fields);CHKERRQ(ierr);
2298b8307b2SJed Brown       }
23066ffff09SJed Brown     } else {
231521d7252SBarry Smith       if (jac->bs <= 0) {
232704ba839SBarry Smith         if (pc->pmat) {
233521d7252SBarry Smith           ierr   = MatGetBlockSize(pc->pmat,&jac->bs);CHKERRQ(ierr);
234704ba839SBarry Smith         } else {
235704ba839SBarry Smith           jac->bs = 1;
236704ba839SBarry Smith         }
237521d7252SBarry Smith       }
238d32f9abdSBarry Smith 
239acfcf0e5SJed Brown       ierr = PetscOptionsGetBool(((PetscObject)pc)->prefix,"-pc_fieldsplit_default",&flg,PETSC_NULL);CHKERRQ(ierr);
240435f959eSBarry Smith       ierr = PetscOptionsGetBool(((PetscObject)pc)->prefix,"-pc_fieldsplit_detect_saddle_point",&stokes,PETSC_NULL);CHKERRQ(ierr);
2416ce1633cSBarry Smith       if (stokes) {
2426ce1633cSBarry Smith         IS       zerodiags,rest;
2436ce1633cSBarry Smith         PetscInt nmin,nmax;
2446ce1633cSBarry Smith 
2456ce1633cSBarry Smith         ierr = MatGetOwnershipRange(pc->mat,&nmin,&nmax);CHKERRQ(ierr);
2466ce1633cSBarry Smith         ierr = MatFindZeroDiagonals(pc->mat,&zerodiags);CHKERRQ(ierr);
2476ce1633cSBarry Smith         ierr = ISComplement(zerodiags,nmin,nmax,&rest);CHKERRQ(ierr);
2486ce1633cSBarry Smith         ierr = PCFieldSplitSetIS(pc,"0",rest);CHKERRQ(ierr);
2496ce1633cSBarry Smith         ierr = PCFieldSplitSetIS(pc,"1",zerodiags);CHKERRQ(ierr);
250*fcfd50ebSBarry Smith         ierr = ISDestroy(&zerodiags);CHKERRQ(ierr);
251*fcfd50ebSBarry Smith         ierr = ISDestroy(&rest);CHKERRQ(ierr);
2526ce1633cSBarry Smith       } else {
253d32f9abdSBarry Smith         if (!flg) {
254d32f9abdSBarry Smith           /* Allow user to set fields from command line,  if bs was known at the time of PCSetFromOptions_FieldSplit()
255d32f9abdSBarry Smith            then it is set there. This is not ideal because we should only have options set in XXSetFromOptions(). */
2566c924f48SJed Brown           ierr = PCFieldSplitSetRuntimeSplits_Private(pc);CHKERRQ(ierr);
2576c924f48SJed Brown           if (jac->splitdefined) {ierr = PetscInfo(pc,"Splits defined using the options database\n");CHKERRQ(ierr);}
258d32f9abdSBarry Smith         }
2596c924f48SJed Brown         if (flg || !jac->splitdefined) {
260d32f9abdSBarry Smith           ierr = PetscInfo(pc,"Using default splitting of fields\n");CHKERRQ(ierr);
261db4c96c1SJed Brown           for (i=0; i<jac->bs; i++) {
2626c924f48SJed Brown             char splitname[8];
2636c924f48SJed Brown             ierr = PetscSNPrintf(splitname,sizeof splitname,"%D",i);CHKERRQ(ierr);
264db4c96c1SJed Brown             ierr = PCFieldSplitSetFields(pc,splitname,1,&i);CHKERRQ(ierr);
26579416396SBarry Smith           }
26697bbdb24SBarry Smith           jac->defaultsplit = PETSC_TRUE;
267521d7252SBarry Smith         }
26866ffff09SJed Brown       }
2696ce1633cSBarry Smith     }
270edf189efSBarry Smith   } else if (jac->nsplits == 1) {
271edf189efSBarry Smith     if (ilink->is) {
272edf189efSBarry Smith       IS       is2;
273edf189efSBarry Smith       PetscInt nmin,nmax;
274edf189efSBarry Smith 
275edf189efSBarry Smith       ierr = MatGetOwnershipRange(pc->mat,&nmin,&nmax);CHKERRQ(ierr);
276edf189efSBarry Smith       ierr = ISComplement(ilink->is,nmin,nmax,&is2);CHKERRQ(ierr);
277db4c96c1SJed Brown       ierr = PCFieldSplitSetIS(pc,"1",is2);CHKERRQ(ierr);
278*fcfd50ebSBarry Smith       ierr = ISDestroy(&is2);CHKERRQ(ierr);
279e7e72b3dSBarry Smith     } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Must provide at least two sets of fields to PCFieldSplit()");
280edf189efSBarry Smith   }
281e7e72b3dSBarry Smith   if (jac->nsplits < 2) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unhandled case, must have at least two fields");
28269a612a9SBarry Smith   PetscFunctionReturn(0);
28369a612a9SBarry Smith }
28469a612a9SBarry Smith 
28569a612a9SBarry Smith 
28669a612a9SBarry Smith #undef __FUNCT__
28769a612a9SBarry Smith #define __FUNCT__ "PCSetUp_FieldSplit"
28869a612a9SBarry Smith static PetscErrorCode PCSetUp_FieldSplit(PC pc)
28969a612a9SBarry Smith {
29069a612a9SBarry Smith   PC_FieldSplit     *jac = (PC_FieldSplit*)pc->data;
29169a612a9SBarry Smith   PetscErrorCode    ierr;
2925a9f2f41SSatish Balay   PC_FieldSplitLink ilink;
293cf502942SBarry Smith   PetscInt          i,nsplit,ccsize;
29469a612a9SBarry Smith   MatStructure      flag = pc->flag;
295ace3abfcSBarry Smith   PetscBool         sorted;
29669a612a9SBarry Smith 
29769a612a9SBarry Smith   PetscFunctionBegin;
29869a612a9SBarry Smith   ierr   = PCFieldSplitSetDefaults(pc);CHKERRQ(ierr);
29997bbdb24SBarry Smith   nsplit = jac->nsplits;
3005a9f2f41SSatish Balay   ilink  = jac->head;
30197bbdb24SBarry Smith 
30297bbdb24SBarry Smith   /* get the matrices for each split */
303704ba839SBarry Smith   if (!jac->issetup) {
3041b9fc7fcSBarry Smith     PetscInt rstart,rend,nslots,bs;
30597bbdb24SBarry Smith 
306704ba839SBarry Smith     jac->issetup = PETSC_TRUE;
307704ba839SBarry Smith 
308704ba839SBarry Smith     /* This is done here instead of in PCFieldSplitSetFields() because may not have matrix at that point */
30951f519a2SBarry Smith     bs     = jac->bs;
31097bbdb24SBarry Smith     ierr   = MatGetOwnershipRange(pc->pmat,&rstart,&rend);CHKERRQ(ierr);
311cf502942SBarry Smith     ierr   = MatGetLocalSize(pc->pmat,PETSC_NULL,&ccsize);CHKERRQ(ierr);
3121b9fc7fcSBarry Smith     nslots = (rend - rstart)/bs;
3131b9fc7fcSBarry Smith     for (i=0; i<nsplit; i++) {
3141b9fc7fcSBarry Smith       if (jac->defaultsplit) {
315704ba839SBarry Smith         ierr = ISCreateStride(((PetscObject)pc)->comm,nslots,rstart+i,nsplit,&ilink->is);CHKERRQ(ierr);
316704ba839SBarry Smith       } else if (!ilink->is) {
317ccb205f8SBarry Smith         if (ilink->nfields > 1) {
3185a9f2f41SSatish Balay           PetscInt   *ii,j,k,nfields = ilink->nfields,*fields = ilink->fields;
3195a9f2f41SSatish Balay           ierr = PetscMalloc(ilink->nfields*nslots*sizeof(PetscInt),&ii);CHKERRQ(ierr);
3201b9fc7fcSBarry Smith           for (j=0; j<nslots; j++) {
3211b9fc7fcSBarry Smith             for (k=0; k<nfields; k++) {
3221b9fc7fcSBarry Smith               ii[nfields*j + k] = rstart + bs*j + fields[k];
32397bbdb24SBarry Smith             }
32497bbdb24SBarry Smith           }
325d67e408aSBarry Smith           ierr = ISCreateGeneral(((PetscObject)pc)->comm,nslots*nfields,ii,PETSC_OWN_POINTER,&ilink->is);CHKERRQ(ierr);
326ccb205f8SBarry Smith         } else {
327704ba839SBarry Smith           ierr = ISCreateStride(((PetscObject)pc)->comm,nslots,rstart+ilink->fields[0],bs,&ilink->is);CHKERRQ(ierr);
328ccb205f8SBarry Smith         }
3293e197d65SBarry Smith       }
330704ba839SBarry Smith       ierr = ISSorted(ilink->is,&sorted);CHKERRQ(ierr);
331e32f2f54SBarry Smith       if (!sorted) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_USER,"Fields must be sorted when creating split");
332704ba839SBarry Smith       ilink = ilink->next;
3331b9fc7fcSBarry Smith     }
3341b9fc7fcSBarry Smith   }
3351b9fc7fcSBarry Smith 
336704ba839SBarry Smith   ilink  = jac->head;
33797bbdb24SBarry Smith   if (!jac->pmat) {
338cf502942SBarry Smith     ierr = PetscMalloc(nsplit*sizeof(Mat),&jac->pmat);CHKERRQ(ierr);
339cf502942SBarry Smith     for (i=0; i<nsplit; i++) {
3404aa3045dSJed Brown       ierr = MatGetSubMatrix(pc->pmat,ilink->is,ilink->is,MAT_INITIAL_MATRIX,&jac->pmat[i]);CHKERRQ(ierr);
341704ba839SBarry Smith       ilink = ilink->next;
342cf502942SBarry Smith     }
34397bbdb24SBarry Smith   } else {
344cf502942SBarry Smith     for (i=0; i<nsplit; i++) {
3454aa3045dSJed Brown       ierr = MatGetSubMatrix(pc->pmat,ilink->is,ilink->is,MAT_REUSE_MATRIX,&jac->pmat[i]);CHKERRQ(ierr);
346704ba839SBarry Smith       ilink = ilink->next;
347cf502942SBarry Smith     }
34897bbdb24SBarry Smith   }
349519d70e2SJed Brown   if (jac->realdiagonal) {
350519d70e2SJed Brown     ilink = jac->head;
351519d70e2SJed Brown     if (!jac->mat) {
352519d70e2SJed Brown       ierr = PetscMalloc(nsplit*sizeof(Mat),&jac->mat);CHKERRQ(ierr);
353519d70e2SJed Brown       for (i=0; i<nsplit; i++) {
354519d70e2SJed Brown         ierr = MatGetSubMatrix(pc->mat,ilink->is,ilink->is,MAT_INITIAL_MATRIX,&jac->mat[i]);CHKERRQ(ierr);
355519d70e2SJed Brown         ilink = ilink->next;
356519d70e2SJed Brown       }
357519d70e2SJed Brown     } else {
358519d70e2SJed Brown       for (i=0; i<nsplit; i++) {
359519d70e2SJed Brown         ierr = MatGetSubMatrix(pc->mat,ilink->is,ilink->is,MAT_REUSE_MATRIX,&jac->mat[i]);CHKERRQ(ierr);
360519d70e2SJed Brown         ilink = ilink->next;
361519d70e2SJed Brown       }
362519d70e2SJed Brown     }
363519d70e2SJed Brown   } else {
364519d70e2SJed Brown     jac->mat = jac->pmat;
365519d70e2SJed Brown   }
36697bbdb24SBarry Smith 
3676c8605c2SJed Brown   if (jac->type != PC_COMPOSITE_ADDITIVE  && jac->type != PC_COMPOSITE_SCHUR) {
36868dd23aaSBarry Smith     /* extract the rows of the matrix associated with each field: used for efficient computation of residual inside algorithm */
36968dd23aaSBarry Smith     ilink  = jac->head;
37068dd23aaSBarry Smith     if (!jac->Afield) {
37168dd23aaSBarry Smith       ierr = PetscMalloc(nsplit*sizeof(Mat),&jac->Afield);CHKERRQ(ierr);
37268dd23aaSBarry Smith       for (i=0; i<nsplit; i++) {
3734aa3045dSJed Brown         ierr = MatGetSubMatrix(pc->mat,ilink->is,PETSC_NULL,MAT_INITIAL_MATRIX,&jac->Afield[i]);CHKERRQ(ierr);
37468dd23aaSBarry Smith         ilink = ilink->next;
37568dd23aaSBarry Smith       }
37668dd23aaSBarry Smith     } else {
37768dd23aaSBarry Smith       for (i=0; i<nsplit; i++) {
3784aa3045dSJed Brown         ierr = MatGetSubMatrix(pc->mat,ilink->is,PETSC_NULL,MAT_REUSE_MATRIX,&jac->Afield[i]);CHKERRQ(ierr);
37968dd23aaSBarry Smith         ilink = ilink->next;
38068dd23aaSBarry Smith       }
38168dd23aaSBarry Smith     }
38268dd23aaSBarry Smith   }
38368dd23aaSBarry Smith 
3843b224e63SBarry Smith   if (jac->type == PC_COMPOSITE_SCHUR) {
3853b224e63SBarry Smith     IS       ccis;
3864aa3045dSJed Brown     PetscInt rstart,rend;
387e7e72b3dSBarry Smith     if (nsplit != 2) SETERRQ(((PetscObject)pc)->comm,PETSC_ERR_ARG_INCOMP,"To use Schur complement preconditioner you must have exactly 2 fields");
38868dd23aaSBarry Smith 
389e6cab6aaSJed Brown     /* When extracting off-diagonal submatrices, we take complements from this range */
390e6cab6aaSJed Brown     ierr  = MatGetOwnershipRangeColumn(pc->mat,&rstart,&rend);CHKERRQ(ierr);
391e6cab6aaSJed Brown 
3923b224e63SBarry Smith     /* need to handle case when one is resetting up the preconditioner */
3933b224e63SBarry Smith     if (jac->schur) {
3943b224e63SBarry Smith       ilink = jac->head;
3954aa3045dSJed Brown       ierr  = ISComplement(ilink->is,rstart,rend,&ccis);CHKERRQ(ierr);
3964aa3045dSJed Brown       ierr  = MatGetSubMatrix(pc->mat,ilink->is,ccis,MAT_REUSE_MATRIX,&jac->B);CHKERRQ(ierr);
397*fcfd50ebSBarry Smith       ierr  = ISDestroy(&ccis);CHKERRQ(ierr);
3983b224e63SBarry Smith       ilink = ilink->next;
3994aa3045dSJed Brown       ierr  = ISComplement(ilink->is,rstart,rend,&ccis);CHKERRQ(ierr);
4004aa3045dSJed Brown       ierr  = MatGetSubMatrix(pc->mat,ilink->is,ccis,MAT_REUSE_MATRIX,&jac->C);CHKERRQ(ierr);
401*fcfd50ebSBarry Smith       ierr  = ISDestroy(&ccis);CHKERRQ(ierr);
402519d70e2SJed Brown       ierr  = MatSchurComplementUpdate(jac->schur,jac->mat[0],jac->pmat[0],jac->B,jac->C,jac->pmat[1],pc->flag);CHKERRQ(ierr);
403084e4875SJed Brown       ierr  = KSPSetOperators(jac->kspschur,jac->schur,FieldSplitSchurPre(jac),pc->flag);CHKERRQ(ierr);
4043b224e63SBarry Smith 
4053b224e63SBarry Smith      } else {
4061cee3971SBarry Smith       KSP ksp;
4076c924f48SJed Brown       char schurprefix[256];
4083b224e63SBarry Smith 
409a04f6461SBarry Smith       /* extract the A01 and A10 matrices */
4103b224e63SBarry Smith       ilink = jac->head;
4114aa3045dSJed Brown       ierr  = ISComplement(ilink->is,rstart,rend,&ccis);CHKERRQ(ierr);
4124aa3045dSJed Brown       ierr  = MatGetSubMatrix(pc->mat,ilink->is,ccis,MAT_INITIAL_MATRIX,&jac->B);CHKERRQ(ierr);
413*fcfd50ebSBarry Smith       ierr  = ISDestroy(&ccis);CHKERRQ(ierr);
4143b224e63SBarry Smith       ilink = ilink->next;
4154aa3045dSJed Brown       ierr  = ISComplement(ilink->is,rstart,rend,&ccis);CHKERRQ(ierr);
4164aa3045dSJed Brown       ierr  = MatGetSubMatrix(pc->mat,ilink->is,ccis,MAT_INITIAL_MATRIX,&jac->C);CHKERRQ(ierr);
417*fcfd50ebSBarry Smith       ierr  = ISDestroy(&ccis);CHKERRQ(ierr);
418084e4875SJed Brown       /* Better would be to use 'mat[0]' (diagonal block of the real matrix) preconditioned by pmat[0] */
419519d70e2SJed Brown       ierr  = MatCreateSchurComplement(jac->mat[0],jac->pmat[0],jac->B,jac->C,jac->mat[1],&jac->schur);CHKERRQ(ierr);
420a04f6461SBarry Smith       /* set tabbing and options prefix of KSP inside the MatSchur */
4211cee3971SBarry Smith       ierr  = MatSchurComplementGetKSP(jac->schur,&ksp);CHKERRQ(ierr);
422e69d4d44SBarry Smith       ierr  = PetscObjectIncrementTabLevel((PetscObject)ksp,(PetscObject)pc,2);CHKERRQ(ierr);
423a04f6461SBarry Smith       ierr  = PetscSNPrintf(schurprefix,sizeof schurprefix,"%sfieldsplit_%s_",((PetscObject)pc)->prefix?((PetscObject)pc)->prefix:"",jac->head->splitname);CHKERRQ(ierr);
424a04f6461SBarry Smith       ierr  = KSPSetOptionsPrefix(ksp,schurprefix);CHKERRQ(ierr);
4253b224e63SBarry Smith       ierr  = MatSetFromOptions(jac->schur);CHKERRQ(ierr);
4263b224e63SBarry Smith 
4273b224e63SBarry Smith       ierr  = KSPCreate(((PetscObject)pc)->comm,&jac->kspschur);CHKERRQ(ierr);
4289005cf84SBarry Smith       ierr  = PetscLogObjectParent((PetscObject)pc,(PetscObject)jac->kspschur);CHKERRQ(ierr);
4291cee3971SBarry Smith       ierr  = PetscObjectIncrementTabLevel((PetscObject)jac->kspschur,(PetscObject)pc,1);CHKERRQ(ierr);
430084e4875SJed Brown       ierr  = KSPSetOperators(jac->kspschur,jac->schur,FieldSplitSchurPre(jac),DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
431084e4875SJed Brown       if (jac->schurpre == PC_FIELDSPLIT_SCHUR_PRE_SELF) {
432084e4875SJed Brown         PC pc;
433cd5f4a64SJed Brown         ierr = KSPGetPC(jac->kspschur,&pc);CHKERRQ(ierr);
434084e4875SJed Brown         ierr = PCSetType(pc,PCNONE);CHKERRQ(ierr);
435084e4875SJed Brown         /* Note: This is bad if there exist preconditioners for MATSCHURCOMPLEMENT */
436e69d4d44SBarry Smith       }
4376c924f48SJed Brown       ierr = PetscSNPrintf(schurprefix,sizeof schurprefix,"%sfieldsplit_%s_",((PetscObject)pc)->prefix?((PetscObject)pc)->prefix:"",ilink->splitname);CHKERRQ(ierr);
4386c924f48SJed Brown       ierr  = KSPSetOptionsPrefix(jac->kspschur,schurprefix);CHKERRQ(ierr);
4393b224e63SBarry Smith       /* really want setfromoptions called in PCSetFromOptions_FieldSplit(), but it is not ready yet */
4403b224e63SBarry Smith       ierr = KSPSetFromOptions(jac->kspschur);CHKERRQ(ierr);
4413b224e63SBarry Smith 
4423b224e63SBarry Smith       ierr = PetscMalloc2(2,Vec,&jac->x,2,Vec,&jac->y);CHKERRQ(ierr);
4433b224e63SBarry Smith       ierr = MatGetVecs(jac->pmat[0],&jac->x[0],&jac->y[0]);CHKERRQ(ierr);
4443b224e63SBarry Smith       ierr = MatGetVecs(jac->pmat[1],&jac->x[1],&jac->y[1]);CHKERRQ(ierr);
4453b224e63SBarry Smith       ilink = jac->head;
4463b224e63SBarry Smith       ilink->x = jac->x[0]; ilink->y = jac->y[0];
4473b224e63SBarry Smith       ilink = ilink->next;
4483b224e63SBarry Smith       ilink->x = jac->x[1]; ilink->y = jac->y[1];
4493b224e63SBarry Smith     }
4503b224e63SBarry Smith   } else {
45197bbdb24SBarry Smith     /* set up the individual PCs */
45297bbdb24SBarry Smith     i    = 0;
4535a9f2f41SSatish Balay     ilink = jac->head;
4545a9f2f41SSatish Balay     while (ilink) {
455519d70e2SJed Brown       ierr = KSPSetOperators(ilink->ksp,jac->mat[i],jac->pmat[i],flag);CHKERRQ(ierr);
4563b224e63SBarry Smith       /* really want setfromoptions called in PCSetFromOptions_FieldSplit(), but it is not ready yet */
4575a9f2f41SSatish Balay       ierr = KSPSetFromOptions(ilink->ksp);CHKERRQ(ierr);
4585a9f2f41SSatish Balay       ierr = KSPSetUp(ilink->ksp);CHKERRQ(ierr);
45997bbdb24SBarry Smith       i++;
4605a9f2f41SSatish Balay       ilink = ilink->next;
4610971522cSBarry Smith     }
46297bbdb24SBarry Smith 
46397bbdb24SBarry Smith     /* create work vectors for each split */
4641b9fc7fcSBarry Smith     if (!jac->x) {
46597bbdb24SBarry Smith       ierr = PetscMalloc2(nsplit,Vec,&jac->x,nsplit,Vec,&jac->y);CHKERRQ(ierr);
4665a9f2f41SSatish Balay       ilink = jac->head;
46797bbdb24SBarry Smith       for (i=0; i<nsplit; i++) {
468906ed7ccSBarry Smith         Vec *vl,*vr;
469906ed7ccSBarry Smith 
470906ed7ccSBarry Smith         ierr      = KSPGetVecs(ilink->ksp,1,&vr,1,&vl);CHKERRQ(ierr);
471906ed7ccSBarry Smith         ilink->x  = *vr;
472906ed7ccSBarry Smith         ilink->y  = *vl;
473906ed7ccSBarry Smith         ierr      = PetscFree(vr);CHKERRQ(ierr);
474906ed7ccSBarry Smith         ierr      = PetscFree(vl);CHKERRQ(ierr);
4755a9f2f41SSatish Balay         jac->x[i] = ilink->x;
4765a9f2f41SSatish Balay         jac->y[i] = ilink->y;
4775a9f2f41SSatish Balay         ilink     = ilink->next;
47897bbdb24SBarry Smith       }
4793b224e63SBarry Smith     }
4803b224e63SBarry Smith   }
4813b224e63SBarry Smith 
4823b224e63SBarry Smith 
483d0f46423SBarry Smith   if (!jac->head->sctx) {
4843b224e63SBarry Smith     Vec xtmp;
4853b224e63SBarry Smith 
48679416396SBarry Smith     /* compute scatter contexts needed by multiplicative versions and non-default splits */
4871b9fc7fcSBarry Smith 
4885a9f2f41SSatish Balay     ilink = jac->head;
4891b9fc7fcSBarry Smith     ierr = MatGetVecs(pc->pmat,&xtmp,PETSC_NULL);CHKERRQ(ierr);
4901b9fc7fcSBarry Smith     for (i=0; i<nsplit; i++) {
491704ba839SBarry Smith       ierr = VecScatterCreate(xtmp,ilink->is,jac->x[i],PETSC_NULL,&ilink->sctx);CHKERRQ(ierr);
4925a9f2f41SSatish Balay       ilink = ilink->next;
4931b9fc7fcSBarry Smith     }
4941b9fc7fcSBarry Smith     ierr = VecDestroy(xtmp);CHKERRQ(ierr);
4951b9fc7fcSBarry Smith   }
4960971522cSBarry Smith   PetscFunctionReturn(0);
4970971522cSBarry Smith }
4980971522cSBarry Smith 
4995a9f2f41SSatish Balay #define FieldSplitSplitSolveAdd(ilink,xx,yy) \
500ca9f406cSSatish Balay     (VecScatterBegin(ilink->sctx,xx,ilink->x,INSERT_VALUES,SCATTER_FORWARD) || \
501ca9f406cSSatish Balay      VecScatterEnd(ilink->sctx,xx,ilink->x,INSERT_VALUES,SCATTER_FORWARD) || \
5025a9f2f41SSatish Balay      KSPSolve(ilink->ksp,ilink->x,ilink->y) || \
503ca9f406cSSatish Balay      VecScatterBegin(ilink->sctx,ilink->y,yy,ADD_VALUES,SCATTER_REVERSE) || \
504ca9f406cSSatish Balay      VecScatterEnd(ilink->sctx,ilink->y,yy,ADD_VALUES,SCATTER_REVERSE))
50579416396SBarry Smith 
5060971522cSBarry Smith #undef __FUNCT__
5073b224e63SBarry Smith #define __FUNCT__ "PCApply_FieldSplit_Schur"
5083b224e63SBarry Smith static PetscErrorCode PCApply_FieldSplit_Schur(PC pc,Vec x,Vec y)
5093b224e63SBarry Smith {
5103b224e63SBarry Smith   PC_FieldSplit     *jac = (PC_FieldSplit*)pc->data;
5113b224e63SBarry Smith   PetscErrorCode    ierr;
5123b224e63SBarry Smith   KSP               ksp;
5133b224e63SBarry Smith   PC_FieldSplitLink ilinkA = jac->head, ilinkD = ilinkA->next;
5143b224e63SBarry Smith 
5153b224e63SBarry Smith   PetscFunctionBegin;
5163b224e63SBarry Smith   ierr = MatSchurComplementGetKSP(jac->schur,&ksp);CHKERRQ(ierr);
5173b224e63SBarry Smith 
518c5d2311dSJed Brown   switch (jac->schurfactorization) {
519c5d2311dSJed Brown     case PC_FIELDSPLIT_SCHUR_FACTORIZATION_DIAG:
520a04f6461SBarry Smith       /* [A00 0; 0 -S], positive definite, suitable for MINRES */
521c5d2311dSJed Brown       ierr = VecScatterBegin(ilinkA->sctx,x,ilinkA->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
522c5d2311dSJed Brown       ierr = VecScatterBegin(ilinkD->sctx,x,ilinkD->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
523c5d2311dSJed Brown       ierr = VecScatterEnd(ilinkA->sctx,x,ilinkA->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
524c5d2311dSJed Brown       ierr = KSPSolve(ksp,ilinkA->x,ilinkA->y);CHKERRQ(ierr);
525c5d2311dSJed Brown       ierr = VecScatterBegin(ilinkA->sctx,ilinkA->y,y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
526c5d2311dSJed Brown       ierr = VecScatterEnd(ilinkD->sctx,x,ilinkD->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
527c5d2311dSJed Brown       ierr = KSPSolve(jac->kspschur,ilinkD->x,ilinkD->y);CHKERRQ(ierr);
528c5d2311dSJed Brown       ierr = VecScale(ilinkD->y,-1.);CHKERRQ(ierr);
529c5d2311dSJed Brown       ierr = VecScatterBegin(ilinkD->sctx,ilinkD->y,y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
530c5d2311dSJed Brown       ierr = VecScatterEnd(ilinkA->sctx,ilinkA->y,y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
531c5d2311dSJed Brown       ierr = VecScatterEnd(ilinkD->sctx,ilinkD->y,y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
532c5d2311dSJed Brown       break;
533c5d2311dSJed Brown     case PC_FIELDSPLIT_SCHUR_FACTORIZATION_LOWER:
534a04f6461SBarry Smith       /* [A00 0; A10 S], suitable for left preconditioning */
535c5d2311dSJed Brown       ierr = VecScatterBegin(ilinkA->sctx,x,ilinkA->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
536c5d2311dSJed Brown       ierr = VecScatterEnd(ilinkA->sctx,x,ilinkA->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
537c5d2311dSJed Brown       ierr = KSPSolve(ksp,ilinkA->x,ilinkA->y);CHKERRQ(ierr);
538c5d2311dSJed Brown       ierr = MatMult(jac->C,ilinkA->y,ilinkD->x);CHKERRQ(ierr);
539c5d2311dSJed Brown       ierr = VecScale(ilinkD->x,-1.);CHKERRQ(ierr);
540c5d2311dSJed Brown       ierr = VecScatterBegin(ilinkD->sctx,x,ilinkD->x,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
541c5d2311dSJed Brown       ierr = VecScatterBegin(ilinkA->sctx,ilinkA->y,y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
542c5d2311dSJed Brown       ierr = VecScatterEnd(ilinkD->sctx,x,ilinkD->x,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
543c5d2311dSJed Brown       ierr = KSPSolve(jac->kspschur,ilinkD->x,ilinkD->y);CHKERRQ(ierr);
544c5d2311dSJed Brown       ierr = VecScatterBegin(ilinkD->sctx,ilinkD->y,y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
545c5d2311dSJed Brown       ierr = VecScatterEnd(ilinkA->sctx,ilinkA->y,y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
546c5d2311dSJed Brown       ierr = VecScatterEnd(ilinkD->sctx,ilinkD->y,y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
547c5d2311dSJed Brown       break;
548c5d2311dSJed Brown     case PC_FIELDSPLIT_SCHUR_FACTORIZATION_UPPER:
549a04f6461SBarry Smith       /* [A00 A01; 0 S], suitable for right preconditioning */
550c5d2311dSJed Brown       ierr = VecScatterBegin(ilinkD->sctx,x,ilinkD->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
551c5d2311dSJed Brown       ierr = VecScatterEnd(ilinkD->sctx,x,ilinkD->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
552c5d2311dSJed Brown       ierr = KSPSolve(jac->kspschur,ilinkD->x,ilinkD->y);CHKERRQ(ierr);
553c5d2311dSJed Brown       ierr = MatMult(jac->B,ilinkD->y,ilinkA->x);CHKERRQ(ierr);
554c5d2311dSJed Brown       ierr = VecScale(ilinkA->x,-1.);CHKERRQ(ierr);
555c5d2311dSJed Brown       ierr = VecScatterBegin(ilinkA->sctx,x,ilinkA->x,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
556c5d2311dSJed Brown       ierr = VecScatterBegin(ilinkD->sctx,ilinkD->y,y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
557c5d2311dSJed Brown       ierr = VecScatterEnd(ilinkA->sctx,x,ilinkA->x,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
558c5d2311dSJed Brown       ierr = KSPSolve(ksp,ilinkA->x,ilinkA->y);CHKERRQ(ierr);
559c5d2311dSJed Brown       ierr = VecScatterBegin(ilinkA->sctx,ilinkA->y,y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
560c5d2311dSJed Brown       ierr = VecScatterEnd(ilinkD->sctx,ilinkD->y,y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
561c5d2311dSJed Brown       ierr = VecScatterEnd(ilinkA->sctx,ilinkA->y,y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
562c5d2311dSJed Brown       break;
563c5d2311dSJed Brown     case PC_FIELDSPLIT_SCHUR_FACTORIZATION_FULL:
564a04f6461SBarry Smith       /* [1 0; A10 A00^{-1} 1] [A00 0; 0 S] [1 A00^{-1}A01; 0 1], an exact solve if applied exactly, needs one extra solve with A */
5653b224e63SBarry Smith       ierr = VecScatterBegin(ilinkA->sctx,x,ilinkA->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5663b224e63SBarry Smith       ierr = VecScatterEnd(ilinkA->sctx,x,ilinkA->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5673b224e63SBarry Smith       ierr = KSPSolve(ksp,ilinkA->x,ilinkA->y);CHKERRQ(ierr);
5683b224e63SBarry Smith       ierr = MatMult(jac->C,ilinkA->y,ilinkD->x);CHKERRQ(ierr);
5693b224e63SBarry Smith       ierr = VecScale(ilinkD->x,-1.0);CHKERRQ(ierr);
5703b224e63SBarry Smith       ierr = VecScatterBegin(ilinkD->sctx,x,ilinkD->x,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5713b224e63SBarry Smith       ierr = VecScatterEnd(ilinkD->sctx,x,ilinkD->x,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5723b224e63SBarry Smith 
5733b224e63SBarry Smith       ierr = KSPSolve(jac->kspschur,ilinkD->x,ilinkD->y);CHKERRQ(ierr);
5743b224e63SBarry Smith       ierr = VecScatterBegin(ilinkD->sctx,ilinkD->y,y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5753b224e63SBarry Smith       ierr = VecScatterEnd(ilinkD->sctx,ilinkD->y,y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5763b224e63SBarry Smith 
5773b224e63SBarry Smith       ierr = MatMult(jac->B,ilinkD->y,ilinkA->y);CHKERRQ(ierr);
5783b224e63SBarry Smith       ierr = VecAXPY(ilinkA->x,-1.0,ilinkA->y);CHKERRQ(ierr);
5793b224e63SBarry Smith       ierr = KSPSolve(ksp,ilinkA->x,ilinkA->y);CHKERRQ(ierr);
5803b224e63SBarry Smith       ierr = VecScatterBegin(ilinkA->sctx,ilinkA->y,y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5813b224e63SBarry Smith       ierr = VecScatterEnd(ilinkA->sctx,ilinkA->y,y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
582c5d2311dSJed Brown   }
5833b224e63SBarry Smith   PetscFunctionReturn(0);
5843b224e63SBarry Smith }
5853b224e63SBarry Smith 
5863b224e63SBarry Smith #undef __FUNCT__
5870971522cSBarry Smith #define __FUNCT__ "PCApply_FieldSplit"
5880971522cSBarry Smith static PetscErrorCode PCApply_FieldSplit(PC pc,Vec x,Vec y)
5890971522cSBarry Smith {
5900971522cSBarry Smith   PC_FieldSplit     *jac = (PC_FieldSplit*)pc->data;
5910971522cSBarry Smith   PetscErrorCode    ierr;
5925a9f2f41SSatish Balay   PC_FieldSplitLink ilink = jac->head;
593af93645bSJed Brown   PetscInt          cnt;
5940971522cSBarry Smith 
5950971522cSBarry Smith   PetscFunctionBegin;
59651f519a2SBarry Smith   CHKMEMQ;
59751f519a2SBarry Smith   ierr = VecSetBlockSize(x,jac->bs);CHKERRQ(ierr);
59851f519a2SBarry Smith   ierr = VecSetBlockSize(y,jac->bs);CHKERRQ(ierr);
59951f519a2SBarry Smith 
60079416396SBarry Smith   if (jac->type == PC_COMPOSITE_ADDITIVE) {
6011b9fc7fcSBarry Smith     if (jac->defaultsplit) {
6020971522cSBarry Smith       ierr = VecStrideGatherAll(x,jac->x,INSERT_VALUES);CHKERRQ(ierr);
6035a9f2f41SSatish Balay       while (ilink) {
6045a9f2f41SSatish Balay         ierr = KSPSolve(ilink->ksp,ilink->x,ilink->y);CHKERRQ(ierr);
6055a9f2f41SSatish Balay         ilink = ilink->next;
6060971522cSBarry Smith       }
6070971522cSBarry Smith       ierr = VecStrideScatterAll(jac->y,y,INSERT_VALUES);CHKERRQ(ierr);
6081b9fc7fcSBarry Smith     } else {
609efb30889SBarry Smith       ierr = VecSet(y,0.0);CHKERRQ(ierr);
6105a9f2f41SSatish Balay       while (ilink) {
6115a9f2f41SSatish Balay         ierr = FieldSplitSplitSolveAdd(ilink,x,y);CHKERRQ(ierr);
6125a9f2f41SSatish Balay         ilink = ilink->next;
6131b9fc7fcSBarry Smith       }
6141b9fc7fcSBarry Smith     }
61516913363SBarry Smith   } else if (jac->type == PC_COMPOSITE_MULTIPLICATIVE || jac->type == PC_COMPOSITE_SYMMETRIC_MULTIPLICATIVE) {
61679416396SBarry Smith     if (!jac->w1) {
61779416396SBarry Smith       ierr = VecDuplicate(x,&jac->w1);CHKERRQ(ierr);
61879416396SBarry Smith       ierr = VecDuplicate(x,&jac->w2);CHKERRQ(ierr);
61979416396SBarry Smith     }
620efb30889SBarry Smith     ierr = VecSet(y,0.0);CHKERRQ(ierr);
6215a9f2f41SSatish Balay     ierr = FieldSplitSplitSolveAdd(ilink,x,y);CHKERRQ(ierr);
6223e197d65SBarry Smith     cnt = 1;
6235a9f2f41SSatish Balay     while (ilink->next) {
6245a9f2f41SSatish Balay       ilink = ilink->next;
6253e197d65SBarry Smith       /* compute the residual only over the part of the vector needed */
6263e197d65SBarry Smith       ierr = MatMult(jac->Afield[cnt++],y,ilink->x);CHKERRQ(ierr);
6273e197d65SBarry Smith       ierr = VecScale(ilink->x,-1.0);CHKERRQ(ierr);
6283e197d65SBarry Smith       ierr = VecScatterBegin(ilink->sctx,x,ilink->x,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6293e197d65SBarry Smith       ierr = VecScatterEnd(ilink->sctx,x,ilink->x,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6303e197d65SBarry Smith       ierr = KSPSolve(ilink->ksp,ilink->x,ilink->y);CHKERRQ(ierr);
6313e197d65SBarry Smith       ierr = VecScatterBegin(ilink->sctx,ilink->y,y,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
6323e197d65SBarry Smith       ierr = VecScatterEnd(ilink->sctx,ilink->y,y,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
6333e197d65SBarry Smith     }
63451f519a2SBarry Smith     if (jac->type == PC_COMPOSITE_SYMMETRIC_MULTIPLICATIVE) {
63511755939SBarry Smith       cnt -= 2;
63651f519a2SBarry Smith       while (ilink->previous) {
63751f519a2SBarry Smith         ilink = ilink->previous;
63811755939SBarry Smith         /* compute the residual only over the part of the vector needed */
63911755939SBarry Smith         ierr = MatMult(jac->Afield[cnt--],y,ilink->x);CHKERRQ(ierr);
64011755939SBarry Smith         ierr = VecScale(ilink->x,-1.0);CHKERRQ(ierr);
64111755939SBarry Smith         ierr = VecScatterBegin(ilink->sctx,x,ilink->x,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
64211755939SBarry Smith         ierr = VecScatterEnd(ilink->sctx,x,ilink->x,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
64311755939SBarry Smith         ierr = KSPSolve(ilink->ksp,ilink->x,ilink->y);CHKERRQ(ierr);
64411755939SBarry Smith         ierr = VecScatterBegin(ilink->sctx,ilink->y,y,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
64511755939SBarry Smith         ierr = VecScatterEnd(ilink->sctx,ilink->y,y,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
64651f519a2SBarry Smith       }
64711755939SBarry Smith     }
64865e19b50SBarry Smith   } else SETERRQ1(((PetscObject)pc)->comm,PETSC_ERR_SUP,"Unsupported or unknown composition",(int) jac->type);
64951f519a2SBarry Smith   CHKMEMQ;
6500971522cSBarry Smith   PetscFunctionReturn(0);
6510971522cSBarry Smith }
6520971522cSBarry Smith 
653421e10b8SBarry Smith #define FieldSplitSplitSolveAddTranspose(ilink,xx,yy) \
654ca9f406cSSatish Balay     (VecScatterBegin(ilink->sctx,xx,ilink->y,INSERT_VALUES,SCATTER_FORWARD) || \
655ca9f406cSSatish Balay      VecScatterEnd(ilink->sctx,xx,ilink->y,INSERT_VALUES,SCATTER_FORWARD) || \
656421e10b8SBarry Smith      KSPSolveTranspose(ilink->ksp,ilink->y,ilink->x) || \
657ca9f406cSSatish Balay      VecScatterBegin(ilink->sctx,ilink->x,yy,ADD_VALUES,SCATTER_REVERSE) || \
658ca9f406cSSatish Balay      VecScatterEnd(ilink->sctx,ilink->x,yy,ADD_VALUES,SCATTER_REVERSE))
659421e10b8SBarry Smith 
660421e10b8SBarry Smith #undef __FUNCT__
6618c03b21aSDmitry Karpeev #define __FUNCT__ "PCApplyTranspose_FieldSplit"
662421e10b8SBarry Smith static PetscErrorCode PCApplyTranspose_FieldSplit(PC pc,Vec x,Vec y)
663421e10b8SBarry Smith {
664421e10b8SBarry Smith   PC_FieldSplit     *jac = (PC_FieldSplit*)pc->data;
665421e10b8SBarry Smith   PetscErrorCode    ierr;
666421e10b8SBarry Smith   PC_FieldSplitLink ilink = jac->head;
667421e10b8SBarry Smith 
668421e10b8SBarry Smith   PetscFunctionBegin;
669421e10b8SBarry Smith   CHKMEMQ;
670421e10b8SBarry Smith   ierr = VecSetBlockSize(x,jac->bs);CHKERRQ(ierr);
671421e10b8SBarry Smith   ierr = VecSetBlockSize(y,jac->bs);CHKERRQ(ierr);
672421e10b8SBarry Smith 
673421e10b8SBarry Smith   if (jac->type == PC_COMPOSITE_ADDITIVE) {
674421e10b8SBarry Smith     if (jac->defaultsplit) {
675421e10b8SBarry Smith       ierr = VecStrideGatherAll(x,jac->x,INSERT_VALUES);CHKERRQ(ierr);
676421e10b8SBarry Smith       while (ilink) {
677421e10b8SBarry Smith 	ierr = KSPSolveTranspose(ilink->ksp,ilink->x,ilink->y);CHKERRQ(ierr);
678421e10b8SBarry Smith 	ilink = ilink->next;
679421e10b8SBarry Smith       }
680421e10b8SBarry Smith       ierr = VecStrideScatterAll(jac->y,y,INSERT_VALUES);CHKERRQ(ierr);
681421e10b8SBarry Smith     } else {
682421e10b8SBarry Smith       ierr = VecSet(y,0.0);CHKERRQ(ierr);
683421e10b8SBarry Smith       while (ilink) {
684421e10b8SBarry Smith         ierr = FieldSplitSplitSolveAddTranspose(ilink,x,y);CHKERRQ(ierr);
685421e10b8SBarry Smith 	ilink = ilink->next;
686421e10b8SBarry Smith       }
687421e10b8SBarry Smith     }
688421e10b8SBarry Smith   } else {
689421e10b8SBarry Smith     if (!jac->w1) {
690421e10b8SBarry Smith       ierr = VecDuplicate(x,&jac->w1);CHKERRQ(ierr);
691421e10b8SBarry Smith       ierr = VecDuplicate(x,&jac->w2);CHKERRQ(ierr);
692421e10b8SBarry Smith     }
693421e10b8SBarry Smith     ierr = VecSet(y,0.0);CHKERRQ(ierr);
694421e10b8SBarry Smith     if (jac->type == PC_COMPOSITE_SYMMETRIC_MULTIPLICATIVE) {
695421e10b8SBarry Smith       ierr = FieldSplitSplitSolveAddTranspose(ilink,x,y);CHKERRQ(ierr);
696421e10b8SBarry Smith       while (ilink->next) {
697421e10b8SBarry Smith         ilink = ilink->next;
6989989ab13SBarry Smith         ierr  = MatMultTranspose(pc->mat,y,jac->w1);CHKERRQ(ierr);
699421e10b8SBarry Smith         ierr  = VecWAXPY(jac->w2,-1.0,jac->w1,x);CHKERRQ(ierr);
700421e10b8SBarry Smith         ierr  = FieldSplitSplitSolveAddTranspose(ilink,jac->w2,y);CHKERRQ(ierr);
701421e10b8SBarry Smith       }
702421e10b8SBarry Smith       while (ilink->previous) {
703421e10b8SBarry Smith         ilink = ilink->previous;
7049989ab13SBarry Smith         ierr  = MatMultTranspose(pc->mat,y,jac->w1);CHKERRQ(ierr);
705421e10b8SBarry Smith         ierr  = VecWAXPY(jac->w2,-1.0,jac->w1,x);CHKERRQ(ierr);
706421e10b8SBarry Smith         ierr  = FieldSplitSplitSolveAddTranspose(ilink,jac->w2,y);CHKERRQ(ierr);
707421e10b8SBarry Smith       }
708421e10b8SBarry Smith     } else {
709421e10b8SBarry Smith       while (ilink->next) {   /* get to last entry in linked list */
710421e10b8SBarry Smith 	ilink = ilink->next;
711421e10b8SBarry Smith       }
712421e10b8SBarry Smith       ierr = FieldSplitSplitSolveAddTranspose(ilink,x,y);CHKERRQ(ierr);
713421e10b8SBarry Smith       while (ilink->previous) {
714421e10b8SBarry Smith 	ilink = ilink->previous;
7159989ab13SBarry Smith 	ierr  = MatMultTranspose(pc->mat,y,jac->w1);CHKERRQ(ierr);
716421e10b8SBarry Smith 	ierr  = VecWAXPY(jac->w2,-1.0,jac->w1,x);CHKERRQ(ierr);
717421e10b8SBarry Smith 	ierr  = FieldSplitSplitSolveAddTranspose(ilink,jac->w2,y);CHKERRQ(ierr);
718421e10b8SBarry Smith       }
719421e10b8SBarry Smith     }
720421e10b8SBarry Smith   }
721421e10b8SBarry Smith   CHKMEMQ;
722421e10b8SBarry Smith   PetscFunctionReturn(0);
723421e10b8SBarry Smith }
724421e10b8SBarry Smith 
7250971522cSBarry Smith #undef __FUNCT__
726574deadeSBarry Smith #define __FUNCT__ "PCReset_FieldSplit"
727574deadeSBarry Smith static PetscErrorCode PCReset_FieldSplit(PC pc)
7280971522cSBarry Smith {
7290971522cSBarry Smith   PC_FieldSplit     *jac = (PC_FieldSplit*)pc->data;
7300971522cSBarry Smith   PetscErrorCode    ierr;
7315a9f2f41SSatish Balay   PC_FieldSplitLink ilink = jac->head,next;
7320971522cSBarry Smith 
7330971522cSBarry Smith   PetscFunctionBegin;
7345a9f2f41SSatish Balay   while (ilink) {
735574deadeSBarry Smith     ierr = KSPReset(ilink->ksp);CHKERRQ(ierr);
736*fcfd50ebSBarry Smith     ierr = VecDestroy(&ilink->x);CHKERRQ(ierr);
737*fcfd50ebSBarry Smith     ierr = VecDestroy(&ilink->y);CHKERRQ(ierr);
738*fcfd50ebSBarry Smith     ierr = VecScatterDestroy(&ilink->sctx);CHKERRQ(ierr);
739*fcfd50ebSBarry Smith     ierr = ISDestroy(&ilink->is);CHKERRQ(ierr);
7405a9f2f41SSatish Balay     next = ilink->next;
7415a9f2f41SSatish Balay     ilink = next;
7420971522cSBarry Smith   }
74305b42c5fSBarry Smith   ierr = PetscFree2(jac->x,jac->y);CHKERRQ(ierr);
744574deadeSBarry Smith   if (jac->mat && jac->mat != jac->pmat) {
745574deadeSBarry Smith     ierr = MatDestroyMatrices(jac->nsplits,&jac->mat);CHKERRQ(ierr);
746574deadeSBarry Smith   } else if (jac->mat) {
747574deadeSBarry Smith     jac->mat = PETSC_NULL;
748574deadeSBarry Smith   }
74997bbdb24SBarry Smith   if (jac->pmat) {ierr = MatDestroyMatrices(jac->nsplits,&jac->pmat);CHKERRQ(ierr);}
75068dd23aaSBarry Smith   if (jac->Afield) {ierr = MatDestroyMatrices(jac->nsplits,&jac->Afield);CHKERRQ(ierr);}
75179416396SBarry Smith   if (jac->w1) {ierr = VecDestroy(jac->w1);CHKERRQ(ierr);}
75279416396SBarry Smith   if (jac->w2) {ierr = VecDestroy(jac->w2);CHKERRQ(ierr);}
7533b224e63SBarry Smith   if (jac->schur) {ierr = MatDestroy(jac->schur);CHKERRQ(ierr);}
754084e4875SJed Brown   if (jac->schur_user) {ierr = MatDestroy(jac->schur_user);CHKERRQ(ierr);}
755d0f46423SBarry Smith   if (jac->kspschur) {ierr = KSPDestroy(jac->kspschur);CHKERRQ(ierr);}
7563b224e63SBarry Smith   if (jac->B) {ierr = MatDestroy(jac->B);CHKERRQ(ierr);}
7573b224e63SBarry Smith   if (jac->C) {ierr = MatDestroy(jac->C);CHKERRQ(ierr);}
758574deadeSBarry Smith   PetscFunctionReturn(0);
759574deadeSBarry Smith }
760574deadeSBarry Smith 
761574deadeSBarry Smith #undef __FUNCT__
762574deadeSBarry Smith #define __FUNCT__ "PCDestroy_FieldSplit"
763574deadeSBarry Smith static PetscErrorCode PCDestroy_FieldSplit(PC pc)
764574deadeSBarry Smith {
765574deadeSBarry Smith   PC_FieldSplit     *jac = (PC_FieldSplit*)pc->data;
766574deadeSBarry Smith   PetscErrorCode    ierr;
767574deadeSBarry Smith   PC_FieldSplitLink ilink = jac->head,next;
768574deadeSBarry Smith 
769574deadeSBarry Smith   PetscFunctionBegin;
770574deadeSBarry Smith   ierr = PCReset_FieldSplit(pc);CHKERRQ(ierr);
771574deadeSBarry Smith   while (ilink) {
772574deadeSBarry Smith     ierr = KSPDestroy(ilink->ksp);CHKERRQ(ierr);
773574deadeSBarry Smith     next = ilink->next;
774574deadeSBarry Smith     ierr = PetscFree(ilink->splitname);CHKERRQ(ierr);
775574deadeSBarry Smith     ierr = PetscFree(ilink->fields);CHKERRQ(ierr);
776574deadeSBarry Smith     ierr = PetscFree(ilink);CHKERRQ(ierr);
777574deadeSBarry Smith     ilink = next;
778574deadeSBarry Smith   }
779574deadeSBarry Smith   ierr = PetscFree2(jac->x,jac->y);CHKERRQ(ierr);
780c31cb41cSBarry Smith   ierr = PetscFree(pc->data);CHKERRQ(ierr);
7810971522cSBarry Smith   PetscFunctionReturn(0);
7820971522cSBarry Smith }
7830971522cSBarry Smith 
7840971522cSBarry Smith #undef __FUNCT__
7850971522cSBarry Smith #define __FUNCT__ "PCSetFromOptions_FieldSplit"
7860971522cSBarry Smith static PetscErrorCode PCSetFromOptions_FieldSplit(PC pc)
7870971522cSBarry Smith {
7881b9fc7fcSBarry Smith   PetscErrorCode  ierr;
7896c924f48SJed Brown   PetscInt        bs;
790bc59fbc5SBarry Smith   PetscBool       flg,stokes = PETSC_FALSE;
7919dcbbd2bSBarry Smith   PC_FieldSplit   *jac = (PC_FieldSplit*)pc->data;
7923b224e63SBarry Smith   PCCompositeType ctype;
7931b9fc7fcSBarry Smith 
7940971522cSBarry Smith   PetscFunctionBegin;
7951b9fc7fcSBarry Smith   ierr = PetscOptionsHead("FieldSplit options");CHKERRQ(ierr);
796acfcf0e5SJed Brown   ierr = PetscOptionsBool("-pc_fieldsplit_real_diagonal","Use diagonal blocks of the operator","PCFieldSplitSetRealDiagonal",jac->realdiagonal,&jac->realdiagonal,PETSC_NULL);CHKERRQ(ierr);
79751f519a2SBarry Smith   ierr = PetscOptionsInt("-pc_fieldsplit_block_size","Blocksize that defines number of fields","PCFieldSplitSetBlockSize",jac->bs,&bs,&flg);CHKERRQ(ierr);
79851f519a2SBarry Smith   if (flg) {
79951f519a2SBarry Smith     ierr = PCFieldSplitSetBlockSize(pc,bs);CHKERRQ(ierr);
80051f519a2SBarry Smith   }
801704ba839SBarry Smith 
802435f959eSBarry Smith   ierr = PetscOptionsGetBool(((PetscObject)pc)->prefix,"-pc_fieldsplit_detect_saddle_point",&stokes,PETSC_NULL);CHKERRQ(ierr);
803c0adfefeSBarry Smith   if (stokes) {
804c0adfefeSBarry Smith     ierr = PCFieldSplitSetType(pc,PC_COMPOSITE_SCHUR);CHKERRQ(ierr);
805c0adfefeSBarry Smith     jac->schurpre = PC_FIELDSPLIT_SCHUR_PRE_SELF;
806c0adfefeSBarry Smith   }
807c0adfefeSBarry Smith 
8083b224e63SBarry Smith   ierr = PetscOptionsEnum("-pc_fieldsplit_type","Type of composition","PCFieldSplitSetType",PCCompositeTypes,(PetscEnum)jac->type,(PetscEnum*)&ctype,&flg);CHKERRQ(ierr);
8093b224e63SBarry Smith   if (flg) {
8103b224e63SBarry Smith     ierr = PCFieldSplitSetType(pc,ctype);CHKERRQ(ierr);
8113b224e63SBarry Smith   }
812d32f9abdSBarry Smith 
813c30613efSMatthew Knepley   /* Only setup fields once */
814c30613efSMatthew Knepley   if ((jac->bs > 0) && (jac->nsplits == 0)) {
815d32f9abdSBarry Smith     /* only allow user to set fields from command line if bs is already known.
816d32f9abdSBarry Smith        otherwise user can set them in PCFieldSplitSetDefaults() */
8176c924f48SJed Brown     ierr = PCFieldSplitSetRuntimeSplits_Private(pc);CHKERRQ(ierr);
8186c924f48SJed Brown     if (jac->splitdefined) {ierr = PetscInfo(pc,"Splits defined using the options database\n");CHKERRQ(ierr);}
819d32f9abdSBarry Smith   }
820c5d2311dSJed Brown   if (jac->type == PC_COMPOSITE_SCHUR) {
821c5d2311dSJed Brown     ierr = PetscOptionsEnum("-pc_fieldsplit_schur_factorization_type","Factorization to use","None",PCFieldSplitSchurFactorizationTypes,(PetscEnum)jac->schurfactorization,(PetscEnum*)&jac->schurfactorization,PETSC_NULL);CHKERRQ(ierr);
822084e4875SJed 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);
823c5d2311dSJed Brown   }
8241b9fc7fcSBarry Smith   ierr = PetscOptionsTail();CHKERRQ(ierr);
8250971522cSBarry Smith   PetscFunctionReturn(0);
8260971522cSBarry Smith }
8270971522cSBarry Smith 
8280971522cSBarry Smith /*------------------------------------------------------------------------------------*/
8290971522cSBarry Smith 
8300971522cSBarry Smith EXTERN_C_BEGIN
8310971522cSBarry Smith #undef __FUNCT__
8320971522cSBarry Smith #define __FUNCT__ "PCFieldSplitSetFields_FieldSplit"
8337087cfbeSBarry Smith PetscErrorCode  PCFieldSplitSetFields_FieldSplit(PC pc,const char splitname[],PetscInt n,const PetscInt *fields)
8340971522cSBarry Smith {
83597bbdb24SBarry Smith   PC_FieldSplit     *jac = (PC_FieldSplit*)pc->data;
8360971522cSBarry Smith   PetscErrorCode    ierr;
8375a9f2f41SSatish Balay   PC_FieldSplitLink ilink,next = jac->head;
83869a612a9SBarry Smith   char              prefix[128];
83951f519a2SBarry Smith   PetscInt          i;
8400971522cSBarry Smith 
8410971522cSBarry Smith   PetscFunctionBegin;
8426c924f48SJed Brown   if (jac->splitdefined) {
8436c924f48SJed Brown     ierr = PetscInfo1(pc,"Ignoring new split \"%s\" because the splits have already been defined\n",splitname);CHKERRQ(ierr);
8446c924f48SJed Brown     PetscFunctionReturn(0);
8456c924f48SJed Brown   }
84651f519a2SBarry Smith   for (i=0; i<n; i++) {
847e32f2f54SBarry Smith     if (fields[i] >= jac->bs) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Field %D requested but only %D exist",fields[i],jac->bs);
848e32f2f54SBarry Smith     if (fields[i] < 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Negative field %D requested",fields[i]);
84951f519a2SBarry Smith   }
850704ba839SBarry Smith   ierr = PetscNew(struct _PC_FieldSplitLink,&ilink);CHKERRQ(ierr);
851a04f6461SBarry Smith   if (splitname) {
852db4c96c1SJed Brown     ierr = PetscStrallocpy(splitname,&ilink->splitname);CHKERRQ(ierr);
853a04f6461SBarry Smith   } else {
854a04f6461SBarry Smith     ierr = PetscMalloc(3*sizeof(char),&ilink->splitname);CHKERRQ(ierr);
855a04f6461SBarry Smith     ierr = PetscSNPrintf(ilink->splitname,2,"%s",jac->nsplits);CHKERRQ(ierr);
856a04f6461SBarry Smith   }
857704ba839SBarry Smith   ierr = PetscMalloc(n*sizeof(PetscInt),&ilink->fields);CHKERRQ(ierr);
8585a9f2f41SSatish Balay   ierr = PetscMemcpy(ilink->fields,fields,n*sizeof(PetscInt));CHKERRQ(ierr);
8595a9f2f41SSatish Balay   ilink->nfields = n;
8605a9f2f41SSatish Balay   ilink->next    = PETSC_NULL;
8617adad957SLisandro Dalcin   ierr           = KSPCreate(((PetscObject)pc)->comm,&ilink->ksp);CHKERRQ(ierr);
8621cee3971SBarry Smith   ierr           = PetscObjectIncrementTabLevel((PetscObject)ilink->ksp,(PetscObject)pc,1);CHKERRQ(ierr);
8635a9f2f41SSatish Balay   ierr           = KSPSetType(ilink->ksp,KSPPREONLY);CHKERRQ(ierr);
8649005cf84SBarry Smith   ierr           = PetscLogObjectParent((PetscObject)pc,(PetscObject)ilink->ksp);CHKERRQ(ierr);
86569a612a9SBarry Smith 
866a04f6461SBarry Smith   ierr = PetscSNPrintf(prefix,sizeof prefix,"%sfieldsplit_%s_",((PetscObject)pc)->prefix?((PetscObject)pc)->prefix:"",ilink->splitname);CHKERRQ(ierr);
8675a9f2f41SSatish Balay   ierr = KSPSetOptionsPrefix(ilink->ksp,prefix);CHKERRQ(ierr);
8680971522cSBarry Smith 
8690971522cSBarry Smith   if (!next) {
8705a9f2f41SSatish Balay     jac->head       = ilink;
87151f519a2SBarry Smith     ilink->previous = PETSC_NULL;
8720971522cSBarry Smith   } else {
8730971522cSBarry Smith     while (next->next) {
8740971522cSBarry Smith       next = next->next;
8750971522cSBarry Smith     }
8765a9f2f41SSatish Balay     next->next      = ilink;
87751f519a2SBarry Smith     ilink->previous = next;
8780971522cSBarry Smith   }
8790971522cSBarry Smith   jac->nsplits++;
8800971522cSBarry Smith   PetscFunctionReturn(0);
8810971522cSBarry Smith }
8820971522cSBarry Smith EXTERN_C_END
8830971522cSBarry Smith 
884e69d4d44SBarry Smith EXTERN_C_BEGIN
885e69d4d44SBarry Smith #undef __FUNCT__
886e69d4d44SBarry Smith #define __FUNCT__ "PCFieldSplitGetSubKSP_FieldSplit_Schur"
8877087cfbeSBarry Smith PetscErrorCode  PCFieldSplitGetSubKSP_FieldSplit_Schur(PC pc,PetscInt *n,KSP **subksp)
888e69d4d44SBarry Smith {
889e69d4d44SBarry Smith   PC_FieldSplit *jac = (PC_FieldSplit*)pc->data;
890e69d4d44SBarry Smith   PetscErrorCode ierr;
891e69d4d44SBarry Smith 
892e69d4d44SBarry Smith   PetscFunctionBegin;
893519d70e2SJed Brown   ierr = PetscMalloc(jac->nsplits*sizeof(KSP),subksp);CHKERRQ(ierr);
894e69d4d44SBarry Smith   ierr = MatSchurComplementGetKSP(jac->schur,*subksp);CHKERRQ(ierr);
895e69d4d44SBarry Smith   (*subksp)[1] = jac->kspschur;
89613e0d083SBarry Smith   if (n) *n = jac->nsplits;
897e69d4d44SBarry Smith   PetscFunctionReturn(0);
898e69d4d44SBarry Smith }
899e69d4d44SBarry Smith EXTERN_C_END
9000971522cSBarry Smith 
9010971522cSBarry Smith EXTERN_C_BEGIN
9020971522cSBarry Smith #undef __FUNCT__
90369a612a9SBarry Smith #define __FUNCT__ "PCFieldSplitGetSubKSP_FieldSplit"
9047087cfbeSBarry Smith PetscErrorCode  PCFieldSplitGetSubKSP_FieldSplit(PC pc,PetscInt *n,KSP **subksp)
9050971522cSBarry Smith {
9060971522cSBarry Smith   PC_FieldSplit     *jac = (PC_FieldSplit*)pc->data;
9070971522cSBarry Smith   PetscErrorCode    ierr;
9080971522cSBarry Smith   PetscInt          cnt = 0;
9095a9f2f41SSatish Balay   PC_FieldSplitLink ilink = jac->head;
9100971522cSBarry Smith 
9110971522cSBarry Smith   PetscFunctionBegin;
91269a612a9SBarry Smith   ierr = PetscMalloc(jac->nsplits*sizeof(KSP*),subksp);CHKERRQ(ierr);
9135a9f2f41SSatish Balay   while (ilink) {
9145a9f2f41SSatish Balay     (*subksp)[cnt++] = ilink->ksp;
9155a9f2f41SSatish Balay     ilink = ilink->next;
9160971522cSBarry Smith   }
917e32f2f54SBarry Smith   if (cnt != jac->nsplits) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Corrupt PCFIELDSPLIT object: number splits in linked list %D in object %D",cnt,jac->nsplits);
91813e0d083SBarry Smith   if (n) *n = jac->nsplits;
9190971522cSBarry Smith   PetscFunctionReturn(0);
9200971522cSBarry Smith }
9210971522cSBarry Smith EXTERN_C_END
9220971522cSBarry Smith 
923704ba839SBarry Smith EXTERN_C_BEGIN
924704ba839SBarry Smith #undef __FUNCT__
925704ba839SBarry Smith #define __FUNCT__ "PCFieldSplitSetIS_FieldSplit"
9267087cfbeSBarry Smith PetscErrorCode  PCFieldSplitSetIS_FieldSplit(PC pc,const char splitname[],IS is)
927704ba839SBarry Smith {
928704ba839SBarry Smith   PC_FieldSplit     *jac = (PC_FieldSplit*)pc->data;
929704ba839SBarry Smith   PetscErrorCode    ierr;
930704ba839SBarry Smith   PC_FieldSplitLink ilink, next = jac->head;
931704ba839SBarry Smith   char              prefix[128];
932704ba839SBarry Smith 
933704ba839SBarry Smith   PetscFunctionBegin;
9346c924f48SJed Brown   if (jac->splitdefined) {
9356c924f48SJed Brown     ierr = PetscInfo1(pc,"Ignoring new split \"%s\" because the splits have already been defined\n",splitname);CHKERRQ(ierr);
9366c924f48SJed Brown     PetscFunctionReturn(0);
9376c924f48SJed Brown   }
93816913363SBarry Smith   ierr = PetscNew(struct _PC_FieldSplitLink,&ilink);CHKERRQ(ierr);
939a04f6461SBarry Smith   if (splitname) {
940db4c96c1SJed Brown     ierr = PetscStrallocpy(splitname,&ilink->splitname);CHKERRQ(ierr);
941a04f6461SBarry Smith   } else {
942a04f6461SBarry Smith     ierr = PetscMalloc(3*sizeof(char),&ilink->splitname);CHKERRQ(ierr);
943a04f6461SBarry Smith     ierr = PetscSNPrintf(ilink->splitname,2,"%s",jac->nsplits);CHKERRQ(ierr);
944a04f6461SBarry Smith   }
9451ab39975SBarry Smith   ilink->is      = is;
9461ab39975SBarry Smith   ierr           = PetscObjectReference((PetscObject)is);CHKERRQ(ierr);
947704ba839SBarry Smith   ilink->next    = PETSC_NULL;
948704ba839SBarry Smith   ierr           = KSPCreate(((PetscObject)pc)->comm,&ilink->ksp);CHKERRQ(ierr);
9491cee3971SBarry Smith   ierr           = PetscObjectIncrementTabLevel((PetscObject)ilink->ksp,(PetscObject)pc,1);CHKERRQ(ierr);
950704ba839SBarry Smith   ierr           = KSPSetType(ilink->ksp,KSPPREONLY);CHKERRQ(ierr);
9519005cf84SBarry Smith   ierr           = PetscLogObjectParent((PetscObject)pc,(PetscObject)ilink->ksp);CHKERRQ(ierr);
952704ba839SBarry Smith 
953a04f6461SBarry Smith   ierr = PetscSNPrintf(prefix,sizeof prefix,"%sfieldsplit_%s_",((PetscObject)pc)->prefix?((PetscObject)pc)->prefix:"",ilink->splitname);CHKERRQ(ierr);
954704ba839SBarry Smith   ierr = KSPSetOptionsPrefix(ilink->ksp,prefix);CHKERRQ(ierr);
955704ba839SBarry Smith 
956704ba839SBarry Smith   if (!next) {
957704ba839SBarry Smith     jac->head       = ilink;
958704ba839SBarry Smith     ilink->previous = PETSC_NULL;
959704ba839SBarry Smith   } else {
960704ba839SBarry Smith     while (next->next) {
961704ba839SBarry Smith       next = next->next;
962704ba839SBarry Smith     }
963704ba839SBarry Smith     next->next      = ilink;
964704ba839SBarry Smith     ilink->previous = next;
965704ba839SBarry Smith   }
966704ba839SBarry Smith   jac->nsplits++;
967704ba839SBarry Smith 
968704ba839SBarry Smith   PetscFunctionReturn(0);
969704ba839SBarry Smith }
970704ba839SBarry Smith EXTERN_C_END
971704ba839SBarry Smith 
9720971522cSBarry Smith #undef __FUNCT__
9730971522cSBarry Smith #define __FUNCT__ "PCFieldSplitSetFields"
9740971522cSBarry Smith /*@
9750971522cSBarry Smith     PCFieldSplitSetFields - Sets the fields for one particular split in the field split preconditioner
9760971522cSBarry Smith 
977ad4df100SBarry Smith     Logically Collective on PC
9780971522cSBarry Smith 
9790971522cSBarry Smith     Input Parameters:
9800971522cSBarry Smith +   pc  - the preconditioner context
981a04f6461SBarry Smith .   splitname - name of this split, if PETSC_NULL the number of the split is used
9820971522cSBarry Smith .   n - the number of fields in this split
983db4c96c1SJed Brown -   fields - the fields in this split
9840971522cSBarry Smith 
9850971522cSBarry Smith     Level: intermediate
9860971522cSBarry Smith 
987d32f9abdSBarry Smith     Notes: Use PCFieldSplitSetIS() to set a completely general set of indices as a field.
988d32f9abdSBarry Smith 
989d32f9abdSBarry Smith      The PCFieldSplitSetFields() is for defining fields as a strided blocks. For example, if the block
990d32f9abdSBarry 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
991d32f9abdSBarry Smith      0xx3xx6xx9xx12 ... x1xx4xx7xx ... xx2xx5xx8xx.. 01x34x67x... 0x1x3x5x7.. x12x45x78x....
992d32f9abdSBarry Smith      where the numbered entries indicate what is in the field.
993d32f9abdSBarry Smith 
994db4c96c1SJed Brown      This function is called once per split (it creates a new split each time).  Solve options
995db4c96c1SJed Brown      for this split will be available under the prefix -fieldsplit_SPLITNAME_.
996db4c96c1SJed Brown 
997d32f9abdSBarry Smith .seealso: PCFieldSplitGetSubKSP(), PCFIELDSPLIT, PCFieldSplitSetBlockSize(), PCFieldSplitSetIS()
9980971522cSBarry Smith 
9990971522cSBarry Smith @*/
10007087cfbeSBarry Smith PetscErrorCode  PCFieldSplitSetFields(PC pc,const char splitname[],PetscInt n,const PetscInt *fields)
10010971522cSBarry Smith {
10024ac538c5SBarry Smith   PetscErrorCode ierr;
10030971522cSBarry Smith 
10040971522cSBarry Smith   PetscFunctionBegin;
10050700a824SBarry Smith   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
1006db4c96c1SJed Brown   PetscValidCharPointer(splitname,2);
1007db4c96c1SJed Brown   if (n < 1) SETERRQ2(((PetscObject)pc)->comm,PETSC_ERR_ARG_OUTOFRANGE,"Provided number of fields %D in split \"%s\" not positive",n,splitname);
1008db4c96c1SJed Brown   PetscValidIntPointer(fields,3);
10094ac538c5SBarry Smith   ierr = PetscTryMethod(pc,"PCFieldSplitSetFields_C",(PC,const char[],PetscInt,const PetscInt *),(pc,splitname,n,fields));CHKERRQ(ierr);
10100971522cSBarry Smith   PetscFunctionReturn(0);
10110971522cSBarry Smith }
10120971522cSBarry Smith 
10130971522cSBarry Smith #undef __FUNCT__
1014704ba839SBarry Smith #define __FUNCT__ "PCFieldSplitSetIS"
1015704ba839SBarry Smith /*@
1016704ba839SBarry Smith     PCFieldSplitSetIS - Sets the exact elements for field
1017704ba839SBarry Smith 
1018ad4df100SBarry Smith     Logically Collective on PC
1019704ba839SBarry Smith 
1020704ba839SBarry Smith     Input Parameters:
1021704ba839SBarry Smith +   pc  - the preconditioner context
1022a04f6461SBarry Smith .   splitname - name of this split, if PETSC_NULL the number of the split is used
1023db4c96c1SJed Brown -   is - the index set that defines the vector elements in this field
1024704ba839SBarry Smith 
1025d32f9abdSBarry Smith 
1026a6ffb8dbSJed Brown     Notes:
1027a6ffb8dbSJed Brown     Use PCFieldSplitSetFields(), for fields defined by strided types.
1028a6ffb8dbSJed Brown 
1029db4c96c1SJed Brown     This function is called once per split (it creates a new split each time).  Solve options
1030db4c96c1SJed Brown     for this split will be available under the prefix -fieldsplit_SPLITNAME_.
1031d32f9abdSBarry Smith 
1032704ba839SBarry Smith     Level: intermediate
1033704ba839SBarry Smith 
1034704ba839SBarry Smith .seealso: PCFieldSplitGetSubKSP(), PCFIELDSPLIT, PCFieldSplitSetBlockSize()
1035704ba839SBarry Smith 
1036704ba839SBarry Smith @*/
10377087cfbeSBarry Smith PetscErrorCode  PCFieldSplitSetIS(PC pc,const char splitname[],IS is)
1038704ba839SBarry Smith {
10394ac538c5SBarry Smith   PetscErrorCode ierr;
1040704ba839SBarry Smith 
1041704ba839SBarry Smith   PetscFunctionBegin;
10420700a824SBarry Smith   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
1043db4c96c1SJed Brown   PetscValidCharPointer(splitname,2);
1044db4c96c1SJed Brown   PetscValidHeaderSpecific(is,IS_CLASSID,3);
10454ac538c5SBarry Smith   ierr = PetscTryMethod(pc,"PCFieldSplitSetIS_C",(PC,const char[],IS),(pc,splitname,is));CHKERRQ(ierr);
1046704ba839SBarry Smith   PetscFunctionReturn(0);
1047704ba839SBarry Smith }
1048704ba839SBarry Smith 
1049704ba839SBarry Smith #undef __FUNCT__
105057a9adfeSMatthew G Knepley #define __FUNCT__ "PCFieldSplitGetIS"
105157a9adfeSMatthew G Knepley /*@
105257a9adfeSMatthew G Knepley     PCFieldSplitGetIS - Retrieves the elements for a field as an IS
105357a9adfeSMatthew G Knepley 
105457a9adfeSMatthew G Knepley     Logically Collective on PC
105557a9adfeSMatthew G Knepley 
105657a9adfeSMatthew G Knepley     Input Parameters:
105757a9adfeSMatthew G Knepley +   pc  - the preconditioner context
105857a9adfeSMatthew G Knepley -   splitname - name of this split
105957a9adfeSMatthew G Knepley 
106057a9adfeSMatthew G Knepley     Output Parameter:
106157a9adfeSMatthew G Knepley -   is - the index set that defines the vector elements in this field, or PETSC_NULL if the field is not found
106257a9adfeSMatthew G Knepley 
106357a9adfeSMatthew G Knepley     Level: intermediate
106457a9adfeSMatthew G Knepley 
106557a9adfeSMatthew G Knepley .seealso: PCFieldSplitGetSubKSP(), PCFIELDSPLIT, PCFieldSplitSetIS()
106657a9adfeSMatthew G Knepley 
106757a9adfeSMatthew G Knepley @*/
106857a9adfeSMatthew G Knepley PetscErrorCode PCFieldSplitGetIS(PC pc,const char splitname[],IS *is)
106957a9adfeSMatthew G Knepley {
107057a9adfeSMatthew G Knepley   PetscErrorCode ierr;
107157a9adfeSMatthew G Knepley 
107257a9adfeSMatthew G Knepley   PetscFunctionBegin;
107357a9adfeSMatthew G Knepley   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
107457a9adfeSMatthew G Knepley   PetscValidCharPointer(splitname,2);
107557a9adfeSMatthew G Knepley   PetscValidPointer(is,3);
107657a9adfeSMatthew G Knepley   {
107757a9adfeSMatthew G Knepley     PC_FieldSplit    *jac   = (PC_FieldSplit *) pc->data;
107857a9adfeSMatthew G Knepley     PC_FieldSplitLink ilink = jac->head;
107957a9adfeSMatthew G Knepley     PetscBool         found;
108057a9adfeSMatthew G Knepley 
108157a9adfeSMatthew G Knepley     *is = PETSC_NULL;
108257a9adfeSMatthew G Knepley     while(ilink) {
108357a9adfeSMatthew G Knepley       ierr = PetscStrcmp(ilink->splitname, splitname, &found);CHKERRQ(ierr);
108457a9adfeSMatthew G Knepley       if (found) {
108557a9adfeSMatthew G Knepley         *is = ilink->is;
108657a9adfeSMatthew G Knepley         break;
108757a9adfeSMatthew G Knepley       }
108857a9adfeSMatthew G Knepley       ilink = ilink->next;
108957a9adfeSMatthew G Knepley     }
109057a9adfeSMatthew G Knepley   }
109157a9adfeSMatthew G Knepley   PetscFunctionReturn(0);
109257a9adfeSMatthew G Knepley }
109357a9adfeSMatthew G Knepley 
109457a9adfeSMatthew G Knepley #undef __FUNCT__
109551f519a2SBarry Smith #define __FUNCT__ "PCFieldSplitSetBlockSize"
109651f519a2SBarry Smith /*@
109751f519a2SBarry Smith     PCFieldSplitSetBlockSize - Sets the block size for defining where fields start in the
109851f519a2SBarry Smith       fieldsplit preconditioner. If not set the matrix block size is used.
109951f519a2SBarry Smith 
1100ad4df100SBarry Smith     Logically Collective on PC
110151f519a2SBarry Smith 
110251f519a2SBarry Smith     Input Parameters:
110351f519a2SBarry Smith +   pc  - the preconditioner context
110451f519a2SBarry Smith -   bs - the block size
110551f519a2SBarry Smith 
110651f519a2SBarry Smith     Level: intermediate
110751f519a2SBarry Smith 
110851f519a2SBarry Smith .seealso: PCFieldSplitGetSubKSP(), PCFIELDSPLIT, PCFieldSplitSetFields()
110951f519a2SBarry Smith 
111051f519a2SBarry Smith @*/
11117087cfbeSBarry Smith PetscErrorCode  PCFieldSplitSetBlockSize(PC pc,PetscInt bs)
111251f519a2SBarry Smith {
11134ac538c5SBarry Smith   PetscErrorCode ierr;
111451f519a2SBarry Smith 
111551f519a2SBarry Smith   PetscFunctionBegin;
11160700a824SBarry Smith   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
1117c5eb9154SBarry Smith   PetscValidLogicalCollectiveInt(pc,bs,2);
11184ac538c5SBarry Smith   ierr = PetscTryMethod(pc,"PCFieldSplitSetBlockSize_C",(PC,PetscInt),(pc,bs));CHKERRQ(ierr);
111951f519a2SBarry Smith   PetscFunctionReturn(0);
112051f519a2SBarry Smith }
112151f519a2SBarry Smith 
112251f519a2SBarry Smith #undef __FUNCT__
112369a612a9SBarry Smith #define __FUNCT__ "PCFieldSplitGetSubKSP"
11240971522cSBarry Smith /*@C
112569a612a9SBarry Smith    PCFieldSplitGetSubKSP - Gets the KSP contexts for all splits
11260971522cSBarry Smith 
112769a612a9SBarry Smith    Collective on KSP
11280971522cSBarry Smith 
11290971522cSBarry Smith    Input Parameter:
11300971522cSBarry Smith .  pc - the preconditioner context
11310971522cSBarry Smith 
11320971522cSBarry Smith    Output Parameters:
113313e0d083SBarry Smith +  n - the number of splits
113469a612a9SBarry Smith -  pc - the array of KSP contexts
11350971522cSBarry Smith 
11360971522cSBarry Smith    Note:
1137d32f9abdSBarry Smith    After PCFieldSplitGetSubKSP() the array of KSPs IS to be freed by the user
1138d32f9abdSBarry Smith    (not the KSP just the array that contains them).
11390971522cSBarry Smith 
114069a612a9SBarry Smith    You must call KSPSetUp() before calling PCFieldSplitGetSubKSP().
11410971522cSBarry Smith 
11420971522cSBarry Smith    Level: advanced
11430971522cSBarry Smith 
11440971522cSBarry Smith .seealso: PCFIELDSPLIT
11450971522cSBarry Smith @*/
11467087cfbeSBarry Smith PetscErrorCode  PCFieldSplitGetSubKSP(PC pc,PetscInt *n,KSP *subksp[])
11470971522cSBarry Smith {
11484ac538c5SBarry Smith   PetscErrorCode ierr;
11490971522cSBarry Smith 
11500971522cSBarry Smith   PetscFunctionBegin;
11510700a824SBarry Smith   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
115213e0d083SBarry Smith   if (n) PetscValidIntPointer(n,2);
11534ac538c5SBarry Smith   ierr = PetscUseMethod(pc,"PCFieldSplitGetSubKSP_C",(PC,PetscInt*,KSP **),(pc,n,subksp));CHKERRQ(ierr);
11540971522cSBarry Smith   PetscFunctionReturn(0);
11550971522cSBarry Smith }
11560971522cSBarry Smith 
1157e69d4d44SBarry Smith #undef __FUNCT__
1158e69d4d44SBarry Smith #define __FUNCT__ "PCFieldSplitSchurPrecondition"
1159e69d4d44SBarry Smith /*@
1160e69d4d44SBarry Smith     PCFieldSplitSchurPrecondition -  Indicates if the Schur complement is preconditioned by a preconditioner constructed by the
1161a04f6461SBarry Smith       A11 matrix. Otherwise no preconditioner is used.
1162e69d4d44SBarry Smith 
1163e69d4d44SBarry Smith     Collective on PC
1164e69d4d44SBarry Smith 
1165e69d4d44SBarry Smith     Input Parameters:
1166e69d4d44SBarry Smith +   pc  - the preconditioner context
1167084e4875SJed Brown .   ptype - which matrix to use for preconditioning the Schur complement
1168084e4875SJed Brown -   userpre - matrix to use for preconditioning, or PETSC_NULL
1169084e4875SJed Brown 
1170084e4875SJed Brown     Notes:
1171a04f6461SBarry Smith     The default is to use the block on the diagonal of the preconditioning matrix.  This is A11, in the (1,1) position.
1172084e4875SJed Brown     There are currently no preconditioners that work directly with the Schur complement so setting
1173084e4875SJed Brown     PC_FIELDSPLIT_SCHUR_PRE_SELF is observationally equivalent to -fieldsplit_1_pc_type none.
1174e69d4d44SBarry Smith 
1175e69d4d44SBarry Smith     Options Database:
1176084e4875SJed Brown .     -pc_fieldsplit_schur_precondition <self,user,diag> default is diag
1177e69d4d44SBarry Smith 
1178e69d4d44SBarry Smith     Level: intermediate
1179e69d4d44SBarry Smith 
1180084e4875SJed Brown .seealso: PCFieldSplitGetSubKSP(), PCFIELDSPLIT, PCFieldSplitSetFields(), PCFieldSplitSchurPreType
1181e69d4d44SBarry Smith 
1182e69d4d44SBarry Smith @*/
11837087cfbeSBarry Smith PetscErrorCode  PCFieldSplitSchurPrecondition(PC pc,PCFieldSplitSchurPreType ptype,Mat pre)
1184e69d4d44SBarry Smith {
11854ac538c5SBarry Smith   PetscErrorCode ierr;
1186e69d4d44SBarry Smith 
1187e69d4d44SBarry Smith   PetscFunctionBegin;
11880700a824SBarry Smith   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
11894ac538c5SBarry Smith   ierr = PetscTryMethod(pc,"PCFieldSplitSchurPrecondition_C",(PC,PCFieldSplitSchurPreType,Mat),(pc,ptype,pre));CHKERRQ(ierr);
1190e69d4d44SBarry Smith   PetscFunctionReturn(0);
1191e69d4d44SBarry Smith }
1192e69d4d44SBarry Smith 
1193e69d4d44SBarry Smith EXTERN_C_BEGIN
1194e69d4d44SBarry Smith #undef __FUNCT__
1195e69d4d44SBarry Smith #define __FUNCT__ "PCFieldSplitSchurPrecondition_FieldSplit"
11967087cfbeSBarry Smith PetscErrorCode  PCFieldSplitSchurPrecondition_FieldSplit(PC pc,PCFieldSplitSchurPreType ptype,Mat pre)
1197e69d4d44SBarry Smith {
1198e69d4d44SBarry Smith   PC_FieldSplit  *jac = (PC_FieldSplit*)pc->data;
1199084e4875SJed Brown   PetscErrorCode  ierr;
1200e69d4d44SBarry Smith 
1201e69d4d44SBarry Smith   PetscFunctionBegin;
1202084e4875SJed Brown   jac->schurpre = ptype;
1203084e4875SJed Brown   if (pre) {
1204084e4875SJed Brown     if (jac->schur_user) {ierr = MatDestroy(jac->schur_user);CHKERRQ(ierr);}
1205084e4875SJed Brown     jac->schur_user = pre;
1206084e4875SJed Brown     ierr = PetscObjectReference((PetscObject)jac->schur_user);CHKERRQ(ierr);
1207084e4875SJed Brown   }
1208e69d4d44SBarry Smith   PetscFunctionReturn(0);
1209e69d4d44SBarry Smith }
1210e69d4d44SBarry Smith EXTERN_C_END
1211e69d4d44SBarry Smith 
121230ad9308SMatthew Knepley #undef __FUNCT__
121330ad9308SMatthew Knepley #define __FUNCT__ "PCFieldSplitGetSchurBlocks"
121430ad9308SMatthew Knepley /*@C
12158c03b21aSDmitry Karpeev    PCFieldSplitGetSchurBlocks - Gets all matrix blocks for the Schur complement
121630ad9308SMatthew Knepley 
121730ad9308SMatthew Knepley    Collective on KSP
121830ad9308SMatthew Knepley 
121930ad9308SMatthew Knepley    Input Parameter:
122030ad9308SMatthew Knepley .  pc - the preconditioner context
122130ad9308SMatthew Knepley 
122230ad9308SMatthew Knepley    Output Parameters:
1223a04f6461SBarry Smith +  A00 - the (0,0) block
1224a04f6461SBarry Smith .  A01 - the (0,1) block
1225a04f6461SBarry Smith .  A10 - the (1,0) block
1226a04f6461SBarry Smith -  A11 - the (1,1) block
122730ad9308SMatthew Knepley 
122830ad9308SMatthew Knepley    Level: advanced
122930ad9308SMatthew Knepley 
123030ad9308SMatthew Knepley .seealso: PCFIELDSPLIT
123130ad9308SMatthew Knepley @*/
1232a04f6461SBarry Smith PetscErrorCode  PCFieldSplitGetSchurBlocks(PC pc,Mat *A00,Mat *A01,Mat *A10, Mat *A11)
123330ad9308SMatthew Knepley {
123430ad9308SMatthew Knepley   PC_FieldSplit *jac = (PC_FieldSplit *) pc->data;
123530ad9308SMatthew Knepley 
123630ad9308SMatthew Knepley   PetscFunctionBegin;
12370700a824SBarry Smith   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
1238c1235816SBarry Smith   if (jac->type != PC_COMPOSITE_SCHUR) SETERRQ(((PetscObject)pc)->comm,PETSC_ERR_ARG_WRONG, "FieldSplit is not using a Schur complement approach.");
1239a04f6461SBarry Smith   if (A00) *A00 = jac->pmat[0];
1240a04f6461SBarry Smith   if (A01) *A01 = jac->B;
1241a04f6461SBarry Smith   if (A10) *A10 = jac->C;
1242a04f6461SBarry Smith   if (A11) *A11 = jac->pmat[1];
124330ad9308SMatthew Knepley   PetscFunctionReturn(0);
124430ad9308SMatthew Knepley }
124530ad9308SMatthew Knepley 
124679416396SBarry Smith EXTERN_C_BEGIN
124779416396SBarry Smith #undef __FUNCT__
124879416396SBarry Smith #define __FUNCT__ "PCFieldSplitSetType_FieldSplit"
12497087cfbeSBarry Smith PetscErrorCode  PCFieldSplitSetType_FieldSplit(PC pc,PCCompositeType type)
125079416396SBarry Smith {
125179416396SBarry Smith   PC_FieldSplit  *jac = (PC_FieldSplit*)pc->data;
1252e69d4d44SBarry Smith   PetscErrorCode ierr;
125379416396SBarry Smith 
125479416396SBarry Smith   PetscFunctionBegin;
125579416396SBarry Smith   jac->type = type;
12563b224e63SBarry Smith   if (type == PC_COMPOSITE_SCHUR) {
12573b224e63SBarry Smith     pc->ops->apply = PCApply_FieldSplit_Schur;
12583b224e63SBarry Smith     pc->ops->view  = PCView_FieldSplit_Schur;
1259e69d4d44SBarry Smith     ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCFieldSplitGetSubKSP_C","PCFieldSplitGetSubKSP_FieldSplit_Schur",PCFieldSplitGetSubKSP_FieldSplit_Schur);CHKERRQ(ierr);
1260e69d4d44SBarry Smith     ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCFieldSplitSchurPrecondition_C","PCFieldSplitSchurPrecondition_FieldSplit",PCFieldSplitSchurPrecondition_FieldSplit);CHKERRQ(ierr);
1261e69d4d44SBarry Smith 
12623b224e63SBarry Smith   } else {
12633b224e63SBarry Smith     pc->ops->apply = PCApply_FieldSplit;
12643b224e63SBarry Smith     pc->ops->view  = PCView_FieldSplit;
1265e69d4d44SBarry Smith     ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCFieldSplitGetSubKSP_C","PCFieldSplitGetSubKSP_FieldSplit",PCFieldSplitGetSubKSP_FieldSplit);CHKERRQ(ierr);
12669e7d6b0aSBarry Smith     ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCFieldSplitSchurPrecondition_C","",0);CHKERRQ(ierr);
12673b224e63SBarry Smith   }
126879416396SBarry Smith   PetscFunctionReturn(0);
126979416396SBarry Smith }
127079416396SBarry Smith EXTERN_C_END
127179416396SBarry Smith 
127251f519a2SBarry Smith EXTERN_C_BEGIN
127351f519a2SBarry Smith #undef __FUNCT__
127451f519a2SBarry Smith #define __FUNCT__ "PCFieldSplitSetBlockSize_FieldSplit"
12757087cfbeSBarry Smith PetscErrorCode  PCFieldSplitSetBlockSize_FieldSplit(PC pc,PetscInt bs)
127651f519a2SBarry Smith {
127751f519a2SBarry Smith   PC_FieldSplit  *jac = (PC_FieldSplit*)pc->data;
127851f519a2SBarry Smith 
127951f519a2SBarry Smith   PetscFunctionBegin;
128065e19b50SBarry Smith   if (bs < 1) SETERRQ1(((PetscObject)pc)->comm,PETSC_ERR_ARG_OUTOFRANGE,"Blocksize must be positive, you gave %D",bs);
128165e19b50SBarry Smith   if (jac->bs > 0 && jac->bs != bs) SETERRQ2(((PetscObject)pc)->comm,PETSC_ERR_ARG_WRONGSTATE,"Cannot change fieldsplit blocksize from %D to %D after it has been set",jac->bs,bs);
128251f519a2SBarry Smith   jac->bs = bs;
128351f519a2SBarry Smith   PetscFunctionReturn(0);
128451f519a2SBarry Smith }
128551f519a2SBarry Smith EXTERN_C_END
128651f519a2SBarry Smith 
128779416396SBarry Smith #undef __FUNCT__
128879416396SBarry Smith #define __FUNCT__ "PCFieldSplitSetType"
1289bc08b0f1SBarry Smith /*@
129079416396SBarry Smith    PCFieldSplitSetType - Sets the type of fieldsplit preconditioner.
129179416396SBarry Smith 
129279416396SBarry Smith    Collective on PC
129379416396SBarry Smith 
129479416396SBarry Smith    Input Parameter:
129579416396SBarry Smith .  pc - the preconditioner context
129681540f2fSBarry Smith .  type - PC_COMPOSITE_ADDITIVE, PC_COMPOSITE_MULTIPLICATIVE (default), PC_COMPOSITE_SYMMETRIC_MULTIPLICATIVE, PC_COMPOSITE_SPECIAL, PC_COMPOSITE_SCHUR
129779416396SBarry Smith 
129879416396SBarry Smith    Options Database Key:
1299a4efd8eaSMatthew Knepley .  -pc_fieldsplit_type <type: one of multiplicative, additive, symmetric_multiplicative, special, schur> - Sets fieldsplit preconditioner type
130079416396SBarry Smith 
130179416396SBarry Smith    Level: Developer
130279416396SBarry Smith 
130379416396SBarry Smith .keywords: PC, set, type, composite preconditioner, additive, multiplicative
130479416396SBarry Smith 
130579416396SBarry Smith .seealso: PCCompositeSetType()
130679416396SBarry Smith 
130779416396SBarry Smith @*/
13087087cfbeSBarry Smith PetscErrorCode  PCFieldSplitSetType(PC pc,PCCompositeType type)
130979416396SBarry Smith {
13104ac538c5SBarry Smith   PetscErrorCode ierr;
131179416396SBarry Smith 
131279416396SBarry Smith   PetscFunctionBegin;
13130700a824SBarry Smith   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
13144ac538c5SBarry Smith   ierr = PetscTryMethod(pc,"PCFieldSplitSetType_C",(PC,PCCompositeType),(pc,type));CHKERRQ(ierr);
131579416396SBarry Smith   PetscFunctionReturn(0);
131679416396SBarry Smith }
131779416396SBarry Smith 
13180971522cSBarry Smith /* -------------------------------------------------------------------------------------*/
13190971522cSBarry Smith /*MC
1320a8c7a070SBarry Smith    PCFIELDSPLIT - Preconditioner created by combining separate preconditioners for individual
1321a04f6461SBarry Smith                   fields or groups of fields. See the users manual section "Solving Block Matrices" for more details.
13220971522cSBarry Smith 
1323edf189efSBarry Smith      To set options on the solvers for each block append -fieldsplit_ to all the PC
1324edf189efSBarry Smith         options database keys. For example, -fieldsplit_pc_type ilu -fieldsplit_pc_factor_levels 1
13250971522cSBarry Smith 
1326a8c7a070SBarry Smith      To set the options on the solvers separate for each block call PCFieldSplitGetSubKSP()
132769a612a9SBarry Smith          and set the options directly on the resulting KSP object
13280971522cSBarry Smith 
13290971522cSBarry Smith    Level: intermediate
13300971522cSBarry Smith 
133179416396SBarry Smith    Options Database Keys:
133281540f2fSBarry Smith +   -pc_fieldsplit_%d_fields <a,b,..> - indicates the fields to be used in the %d'th split
133381540f2fSBarry Smith .   -pc_fieldsplit_default - automatically add any fields to additional splits that have not
133481540f2fSBarry Smith                               been supplied explicitly by -pc_fieldsplit_%d_fields
133581540f2fSBarry Smith .   -pc_fieldsplit_block_size <bs> - size of block that defines fields (i.e. there are bs fields)
133681540f2fSBarry Smith .   -pc_fieldsplit_type <additive,multiplicative,schur,symmetric_multiplicative>
1337e69d4d44SBarry Smith .   -pc_fieldsplit_schur_precondition <true,false> default is true
1338435f959eSBarry Smith .   -pc_fieldsplit_detect_saddle_point - automatically finds rows with zero or negative diagonal and uses Schur complement with no preconditioner as the solver
133979416396SBarry Smith 
1340edf189efSBarry Smith -    Options prefix for inner solvers when using Schur complement preconditioner are -fieldsplit_0_ and -fieldsplit_1_
13413b224e63SBarry Smith      for all other solvers they are -fieldsplit_%d_ for the dth field, use -fieldsplit_ for all fields
13423b224e63SBarry Smith 
1343d32f9abdSBarry Smith    Notes: use PCFieldSplitSetFields() to set fields defined by "strided" entries and PCFieldSplitSetIS()
1344d32f9abdSBarry Smith      to define a field by an arbitrary collection of entries.
1345d32f9abdSBarry Smith 
1346d32f9abdSBarry Smith       If no fields are set the default is used. The fields are defined by entries strided by bs,
1347d32f9abdSBarry Smith       beginning at 0 then 1, etc to bs-1. The block size can be set with PCFieldSplitSetBlockSize(),
1348d32f9abdSBarry Smith       if this is not called the block size defaults to the blocksize of the second matrix passed
1349d32f9abdSBarry Smith       to KSPSetOperators()/PCSetOperators().
1350d32f9abdSBarry Smith 
1351a04f6461SBarry Smith      For the Schur complement preconditioner if J = ( A00 A01 )
1352a04f6461SBarry Smith                                                     ( A10 A11 )
1353e69d4d44SBarry Smith      the preconditioner is
1354a04f6461SBarry Smith               (I   -B ksp(A00)) ( inv(A00)   0  (I         0  )
1355a04f6461SBarry Smith               (0    I       ) (   0    ksp(S) ) (-A10 ksp(A00) I  )
1356a04f6461SBarry Smith      where the action of inv(A00) is applied using the KSP solver with prefix -fieldsplit_0_. The action of
1357a04f6461SBarry Smith      ksp(S) is computed using the KSP solver with prefix -fieldsplit_splitname_ (where splitname was given in providing the SECOND split or 1 if not give).
1358a04f6461SBarry Smith      For PCFieldSplitGetKSP() when field number is
1359edf189efSBarry Smith      0 it returns the KSP associated with -fieldsplit_0_ while field number 1 gives -fieldsplit_1_ KSP. By default
1360a04f6461SBarry Smith      A11 is used to construct a preconditioner for S, use PCFieldSplitSchurPrecondition() to turn on or off this
13617e8cb189SBarry Smith      option. You can use the preconditioner PCLSC to precondition the Schur complement with -fieldsplit_1_pc_type lsc
1362e69d4d44SBarry Smith 
1363edf189efSBarry Smith      If only one set of indices (one IS) is provided with PCFieldSplitSetIS() then the complement of that IS
1364edf189efSBarry Smith      is used automatically for a second block.
1365edf189efSBarry Smith 
1366a541d17aSBarry Smith    Concepts: physics based preconditioners, block preconditioners
13670971522cSBarry Smith 
13687e8cb189SBarry Smith .seealso:  PCCreate(), PCSetType(), PCType (for list of available types), PC, Block_Preconditioners, PCLSC,
1369e69d4d44SBarry Smith            PCFieldSplitGetSubKSP(), PCFieldSplitSetFields(), PCFieldSplitSetType(), PCFieldSplitSetIS(), PCFieldSplitSchurPrecondition()
13700971522cSBarry Smith M*/
13710971522cSBarry Smith 
13720971522cSBarry Smith EXTERN_C_BEGIN
13730971522cSBarry Smith #undef __FUNCT__
13740971522cSBarry Smith #define __FUNCT__ "PCCreate_FieldSplit"
13757087cfbeSBarry Smith PetscErrorCode  PCCreate_FieldSplit(PC pc)
13760971522cSBarry Smith {
13770971522cSBarry Smith   PetscErrorCode ierr;
13780971522cSBarry Smith   PC_FieldSplit  *jac;
13790971522cSBarry Smith 
13800971522cSBarry Smith   PetscFunctionBegin;
138138f2d2fdSLisandro Dalcin   ierr = PetscNewLog(pc,PC_FieldSplit,&jac);CHKERRQ(ierr);
13820971522cSBarry Smith   jac->bs        = -1;
13830971522cSBarry Smith   jac->nsplits   = 0;
13843e197d65SBarry Smith   jac->type      = PC_COMPOSITE_MULTIPLICATIVE;
1385e6cab6aaSJed Brown   jac->schurpre  = PC_FIELDSPLIT_SCHUR_PRE_USER; /* Try user preconditioner first, fall back on diagonal */
1386c5d2311dSJed Brown   jac->schurfactorization = PC_FIELDSPLIT_SCHUR_FACTORIZATION_FULL;
138751f519a2SBarry Smith 
13880971522cSBarry Smith   pc->data     = (void*)jac;
13890971522cSBarry Smith 
13900971522cSBarry Smith   pc->ops->apply             = PCApply_FieldSplit;
1391421e10b8SBarry Smith   pc->ops->applytranspose    = PCApplyTranspose_FieldSplit;
13920971522cSBarry Smith   pc->ops->setup             = PCSetUp_FieldSplit;
1393574deadeSBarry Smith   pc->ops->reset             = PCReset_FieldSplit;
13940971522cSBarry Smith   pc->ops->destroy           = PCDestroy_FieldSplit;
13950971522cSBarry Smith   pc->ops->setfromoptions    = PCSetFromOptions_FieldSplit;
13960971522cSBarry Smith   pc->ops->view              = PCView_FieldSplit;
13970971522cSBarry Smith   pc->ops->applyrichardson   = 0;
13980971522cSBarry Smith 
139969a612a9SBarry Smith   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCFieldSplitGetSubKSP_C","PCFieldSplitGetSubKSP_FieldSplit",
140069a612a9SBarry Smith                     PCFieldSplitGetSubKSP_FieldSplit);CHKERRQ(ierr);
14010971522cSBarry Smith   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCFieldSplitSetFields_C","PCFieldSplitSetFields_FieldSplit",
14020971522cSBarry Smith                     PCFieldSplitSetFields_FieldSplit);CHKERRQ(ierr);
1403704ba839SBarry Smith   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCFieldSplitSetIS_C","PCFieldSplitSetIS_FieldSplit",
1404704ba839SBarry Smith                     PCFieldSplitSetIS_FieldSplit);CHKERRQ(ierr);
140579416396SBarry Smith   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCFieldSplitSetType_C","PCFieldSplitSetType_FieldSplit",
140679416396SBarry Smith                     PCFieldSplitSetType_FieldSplit);CHKERRQ(ierr);
140751f519a2SBarry Smith   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCFieldSplitSetBlockSize_C","PCFieldSplitSetBlockSize_FieldSplit",
140851f519a2SBarry Smith                     PCFieldSplitSetBlockSize_FieldSplit);CHKERRQ(ierr);
14090971522cSBarry Smith   PetscFunctionReturn(0);
14100971522cSBarry Smith }
14110971522cSBarry Smith EXTERN_C_END
14120971522cSBarry Smith 
14130971522cSBarry Smith 
1414a541d17aSBarry Smith 
1415