xref: /petsc/src/ksp/pc/impls/fieldsplit/fieldsplit.c (revision 95dbaa6faf01fdfd99114b7c9e5668e4b2aa754d)
1dba47a55SKris Buschelman 
2f5f0d762SBarry Smith 
3af0996ceSBarry Smith #include <petsc/private/pcimpl.h>     /*I "petscpc.h" I*/
4a80b646eSBarry Smith #include <petsc/private/kspimpl.h>    /*  This is needed to provide the appropriate PETSC_EXTERN for KSP_Solve_FS ....*/
51e25c274SJed Brown #include <petscdm.h>
60971522cSBarry Smith 
72e71c61dSMatthew G. Knepley const char *const PCFieldSplitSchurPreTypes[] = {"SELF","SELFP","A11","USER","FULL","PCFieldSplitSchurPreType","PC_FIELDSPLIT_SCHUR_PRE_",0};
8c9c6ffaaSJed Brown const char *const PCFieldSplitSchurFactTypes[] = {"DIAG","LOWER","UPPER","FULL","PCFieldSplitSchurFactType","PC_FIELDSPLIT_SCHUR_FACT_",0};
9c5d2311dSJed Brown 
109df09d43SBarry Smith PetscLogEvent KSP_Solve_FS_0,KSP_Solve_FS_1,KSP_Solve_FS_S,KSP_Solve_FS_U,KSP_Solve_FS_L,KSP_Solve_FS_2,KSP_Solve_FS_3,KSP_Solve_FS_4;
119df09d43SBarry Smith 
120971522cSBarry Smith typedef struct _PC_FieldSplitLink *PC_FieldSplitLink;
130971522cSBarry Smith struct _PC_FieldSplitLink {
1469a612a9SBarry Smith   KSP               ksp;
15443836d0SMatthew G Knepley   Vec               x,y,z;
16db4c96c1SJed Brown   char              *splitname;
170971522cSBarry Smith   PetscInt          nfields;
185d4c12cdSJungho Lee   PetscInt          *fields,*fields_col;
191b9fc7fcSBarry Smith   VecScatter        sctx;
20f5f0d762SBarry Smith   IS                is,is_col;
2151f519a2SBarry Smith   PC_FieldSplitLink next,previous;
229df09d43SBarry Smith   PetscLogEvent     event;
230971522cSBarry Smith };
240971522cSBarry Smith 
250971522cSBarry Smith typedef struct {
2668dd23aaSBarry Smith   PCCompositeType type;
27ace3abfcSBarry Smith   PetscBool       defaultsplit;                    /* Flag for a system with a set of 'k' scalar fields with the same layout (and bs = k) */
28ace3abfcSBarry Smith   PetscBool       splitdefined;                    /* Flag is set after the splits have been defined, to prevent more splits from being added */
2930ad9308SMatthew Knepley   PetscInt        bs;                              /* Block size for IS and Mat structures */
3030ad9308SMatthew Knepley   PetscInt        nsplits;                         /* Number of field divisions defined */
3179416396SBarry Smith   Vec             *x,*y,w1,w2;
32519d70e2SJed Brown   Mat             *mat;                            /* The diagonal block for each split */
33519d70e2SJed Brown   Mat             *pmat;                           /* The preconditioning diagonal block for each split */
3430ad9308SMatthew Knepley   Mat             *Afield;                         /* The rows of the matrix associated with each split */
35ace3abfcSBarry Smith   PetscBool       issetup;
362fa5cd67SKarl Rupp 
3730ad9308SMatthew Knepley   /* Only used when Schur complement preconditioning is used */
3830ad9308SMatthew Knepley   Mat                       B;                     /* The (0,1) block */
3930ad9308SMatthew Knepley   Mat                       C;                     /* The (1,0) block */
40443836d0SMatthew G Knepley   Mat                       schur;                 /* The Schur complement S = A11 - A10 A00^{-1} A01, the KSP here, kspinner, is H_1 in [El08] */
41a7476a74SDmitry Karpeev   Mat                       schurp;                /* Assembled approximation to S built by MatSchurComplement to be used as a preconditioning matrix when solving with S */
42084e4875SJed Brown   Mat                       schur_user;            /* User-provided preconditioning matrix for the Schur complement */
43084e4875SJed Brown   PCFieldSplitSchurPreType  schurpre;              /* Determines which preconditioning matrix is used for the Schur complement */
44c9c6ffaaSJed Brown   PCFieldSplitSchurFactType schurfactorization;
4530ad9308SMatthew Knepley   KSP                       kspschur;              /* The solver for S */
46443836d0SMatthew G Knepley   KSP                       kspupper;              /* The solver for A in the upper diagonal part of the factorization (H_2 in [El08]) */
47c096484dSStefano Zampini   PetscScalar               schurscale;            /* Scaling factor for the Schur complement solution with DIAG factorization */
48c096484dSStefano Zampini 
4997bbdb24SBarry Smith   PC_FieldSplitLink         head;
506dbb499eSCian Wilson   PetscBool                 isrestrict;             /* indicates PCFieldSplitRestrictIS() has been last called on this object, hack */
51c1570756SJed Brown   PetscBool                 suboptionsset;          /* Indicates that the KSPSetFromOptions() has been called on the sub-KSPs */
524ab8060aSDmitry Karpeev   PetscBool                 dm_splits;              /* Whether to use DMCreateFieldDecomposition() whenever possible */
53c84da90fSDmitry Karpeev   PetscBool                 diag_use_amat;          /* Whether to extract diagonal matrix blocks from Amat, rather than Pmat (weaker than -pc_use_amat) */
54c84da90fSDmitry Karpeev   PetscBool                 offdiag_use_amat;       /* Whether to extract off-diagonal matrix blocks from Amat, rather than Pmat (weaker than -pc_use_amat) */
557b752e3dSPatrick Sanan   PetscBool                 detect;                 /* Whether to form 2-way split by finding zero diagonal entries */
560971522cSBarry Smith } PC_FieldSplit;
570971522cSBarry Smith 
5816913363SBarry Smith /*
5995452b02SPatrick Sanan     Notes:
6095452b02SPatrick Sanan     there is no particular reason that pmat, x, and y are stored as arrays in PC_FieldSplit instead of
6116913363SBarry Smith    inside PC_FieldSplitLink, just historical. If you want to be able to add new fields after already using the
6216913363SBarry Smith    PC you could change this.
6316913363SBarry Smith */
64084e4875SJed Brown 
65e6cab6aaSJed Brown /* This helper is so that setting a user-provided preconditioning matrix is orthogonal to choosing to use it.  This way the
66084e4875SJed Brown * application-provided FormJacobian can provide this matrix without interfering with the user's (command-line) choices. */
67084e4875SJed Brown static Mat FieldSplitSchurPre(PC_FieldSplit *jac)
68084e4875SJed Brown {
69084e4875SJed Brown   switch (jac->schurpre) {
70084e4875SJed Brown   case PC_FIELDSPLIT_SCHUR_PRE_SELF: return jac->schur;
71a7476a74SDmitry Karpeev   case PC_FIELDSPLIT_SCHUR_PRE_SELFP: return jac->schurp;
72e87fab1bSBarry Smith   case PC_FIELDSPLIT_SCHUR_PRE_A11: return jac->pmat[1];
73e74569cdSMatthew G. Knepley   case PC_FIELDSPLIT_SCHUR_PRE_FULL: /* We calculate this and store it in schur_user */
74084e4875SJed Brown   case PC_FIELDSPLIT_SCHUR_PRE_USER: /* Use a user-provided matrix if it is given, otherwise diagonal block */
75084e4875SJed Brown   default:
76084e4875SJed Brown     return jac->schur_user ? jac->schur_user : jac->pmat[1];
77084e4875SJed Brown   }
78084e4875SJed Brown }
79084e4875SJed Brown 
80084e4875SJed Brown 
819804daf3SBarry Smith #include <petscdraw.h>
820971522cSBarry Smith static PetscErrorCode PCView_FieldSplit(PC pc,PetscViewer viewer)
830971522cSBarry Smith {
840971522cSBarry Smith   PC_FieldSplit     *jac = (PC_FieldSplit*)pc->data;
850971522cSBarry Smith   PetscErrorCode    ierr;
86d9884438SBarry Smith   PetscBool         iascii,isdraw;
870971522cSBarry Smith   PetscInt          i,j;
885a9f2f41SSatish Balay   PC_FieldSplitLink ilink = jac->head;
890971522cSBarry Smith 
900971522cSBarry Smith   PetscFunctionBegin;
91251f4c67SDmitry Karpeev   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
92d9884438SBarry Smith   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERDRAW,&isdraw);CHKERRQ(ierr);
930971522cSBarry Smith   if (iascii) {
942c9966d7SBarry Smith     if (jac->bs > 0) {
9551f519a2SBarry Smith       ierr = PetscViewerASCIIPrintf(viewer,"  FieldSplit with %s composition: total splits = %D, blocksize = %D\n",PCCompositeTypes[jac->type],jac->nsplits,jac->bs);CHKERRQ(ierr);
962c9966d7SBarry Smith     } else {
972c9966d7SBarry Smith       ierr = PetscViewerASCIIPrintf(viewer,"  FieldSplit with %s composition: total splits = %D\n",PCCompositeTypes[jac->type],jac->nsplits);CHKERRQ(ierr);
982c9966d7SBarry Smith     }
99f5236f50SJed Brown     if (pc->useAmat) {
100f5236f50SJed Brown       ierr = PetscViewerASCIIPrintf(viewer,"  using Amat (not Pmat) as operator for blocks\n");CHKERRQ(ierr);
101a3df900dSMatthew G Knepley     }
102c84da90fSDmitry Karpeev     if (jac->diag_use_amat) {
103c84da90fSDmitry Karpeev       ierr = PetscViewerASCIIPrintf(viewer,"  using Amat (not Pmat) as operator for diagonal blocks\n");CHKERRQ(ierr);
104c84da90fSDmitry Karpeev     }
105c84da90fSDmitry Karpeev     if (jac->offdiag_use_amat) {
106c84da90fSDmitry Karpeev       ierr = PetscViewerASCIIPrintf(viewer,"  using Amat (not Pmat) as operator for off-diagonal blocks\n");CHKERRQ(ierr);
107c84da90fSDmitry Karpeev     }
10869a612a9SBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  Solver info for each split is in the following KSP objects:\n");CHKERRQ(ierr);
1090971522cSBarry Smith     for (i=0; i<jac->nsplits; i++) {
1101ab39975SBarry Smith       if (ilink->fields) {
1110971522cSBarry Smith         ierr = PetscViewerASCIIPrintf(viewer,"Split number %D Fields ",i);CHKERRQ(ierr);
11279416396SBarry Smith         ierr = PetscViewerASCIIUseTabs(viewer,PETSC_FALSE);CHKERRQ(ierr);
1135a9f2f41SSatish Balay         for (j=0; j<ilink->nfields; j++) {
11479416396SBarry Smith           if (j > 0) {
11579416396SBarry Smith             ierr = PetscViewerASCIIPrintf(viewer,",");CHKERRQ(ierr);
11679416396SBarry Smith           }
1175a9f2f41SSatish Balay           ierr = PetscViewerASCIIPrintf(viewer," %D",ilink->fields[j]);CHKERRQ(ierr);
1180971522cSBarry Smith         }
1190971522cSBarry Smith         ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr);
12079416396SBarry Smith         ierr = PetscViewerASCIIUseTabs(viewer,PETSC_TRUE);CHKERRQ(ierr);
1211ab39975SBarry Smith       } else {
1221ab39975SBarry Smith         ierr = PetscViewerASCIIPrintf(viewer,"Split number %D Defined by IS\n",i);CHKERRQ(ierr);
1231ab39975SBarry Smith       }
1245a9f2f41SSatish Balay       ierr  = KSPView(ilink->ksp,viewer);CHKERRQ(ierr);
1255a9f2f41SSatish Balay       ilink = ilink->next;
1260971522cSBarry Smith     }
1272fa5cd67SKarl Rupp   }
1282fa5cd67SKarl Rupp 
1292fa5cd67SKarl Rupp  if (isdraw) {
130d9884438SBarry Smith     PetscDraw draw;
131d9884438SBarry Smith     PetscReal x,y,w,wd;
132d9884438SBarry Smith 
133d9884438SBarry Smith     ierr = PetscViewerDrawGetDraw(viewer,0,&draw);CHKERRQ(ierr);
134d9884438SBarry Smith     ierr = PetscDrawGetCurrentPoint(draw,&x,&y);CHKERRQ(ierr);
135d9884438SBarry Smith     w    = 2*PetscMin(1.0 - x,x);
136d9884438SBarry Smith     wd   = w/(jac->nsplits + 1);
137d9884438SBarry Smith     x    = x - wd*(jac->nsplits-1)/2.0;
138d9884438SBarry Smith     for (i=0; i<jac->nsplits; i++) {
139d9884438SBarry Smith       ierr  = PetscDrawPushCurrentPoint(draw,x,y);CHKERRQ(ierr);
140d9884438SBarry Smith       ierr  = KSPView(ilink->ksp,viewer);CHKERRQ(ierr);
141d9884438SBarry Smith       ierr  = PetscDrawPopCurrentPoint(draw);CHKERRQ(ierr);
142d9884438SBarry Smith       x    += wd;
143d9884438SBarry Smith       ilink = ilink->next;
144d9884438SBarry Smith     }
1450971522cSBarry Smith   }
1460971522cSBarry Smith   PetscFunctionReturn(0);
1470971522cSBarry Smith }
1480971522cSBarry Smith 
1493b224e63SBarry Smith static PetscErrorCode PCView_FieldSplit_Schur(PC pc,PetscViewer viewer)
1503b224e63SBarry Smith {
1513b224e63SBarry Smith   PC_FieldSplit              *jac = (PC_FieldSplit*)pc->data;
1523b224e63SBarry Smith   PetscErrorCode             ierr;
1534996c5bdSBarry Smith   PetscBool                  iascii,isdraw;
1543b224e63SBarry Smith   PetscInt                   i,j;
1553b224e63SBarry Smith   PC_FieldSplitLink          ilink = jac->head;
156a9908d51SBarry Smith   MatSchurComplementAinvType atype;
1573b224e63SBarry Smith 
1583b224e63SBarry Smith   PetscFunctionBegin;
159251f4c67SDmitry Karpeev   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
1604996c5bdSBarry Smith   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERDRAW,&isdraw);CHKERRQ(ierr);
1613b224e63SBarry Smith   if (iascii) {
1622c9966d7SBarry Smith     if (jac->bs > 0) {
163c9c6ffaaSJed Brown       ierr = PetscViewerASCIIPrintf(viewer,"  FieldSplit with Schur preconditioner, blocksize = %D, factorization %s\n",jac->bs,PCFieldSplitSchurFactTypes[jac->schurfactorization]);CHKERRQ(ierr);
1642c9966d7SBarry Smith     } else {
1652c9966d7SBarry Smith       ierr = PetscViewerASCIIPrintf(viewer,"  FieldSplit with Schur preconditioner, factorization %s\n",PCFieldSplitSchurFactTypes[jac->schurfactorization]);CHKERRQ(ierr);
1662c9966d7SBarry Smith     }
167f5236f50SJed Brown     if (pc->useAmat) {
168f5236f50SJed Brown       ierr = PetscViewerASCIIPrintf(viewer,"  using Amat (not Pmat) as operator for blocks\n");CHKERRQ(ierr);
169a3df900dSMatthew G Knepley     }
1703e8b8b31SMatthew G Knepley     switch (jac->schurpre) {
1713e8b8b31SMatthew G Knepley     case PC_FIELDSPLIT_SCHUR_PRE_SELF:
172a9908d51SBarry Smith       ierr = PetscViewerASCIIPrintf(viewer,"  Preconditioner for the Schur complement formed from S itself\n");CHKERRQ(ierr);
173a9908d51SBarry Smith       break;
174a7476a74SDmitry Karpeev     case PC_FIELDSPLIT_SCHUR_PRE_SELFP:
175a9908d51SBarry Smith       ierr = MatSchurComplementGetAinvType(jac->schur,&atype);CHKERRQ(ierr);
176d0a9c1a2SBarry Smith       ierr = PetscViewerASCIIPrintf(viewer,"  Preconditioner for the Schur complement formed from Sp, an assembled approximation to S, which uses A00's %sdiagonal's inverse\n",atype == MAT_SCHUR_COMPLEMENT_AINV_DIAG ? "" : (atype == MAT_SCHUR_COMPLEMENT_AINV_BLOCK_DIAG ? "block " : "lumped "));CHKERRQ(ierr);break;
177e87fab1bSBarry Smith     case PC_FIELDSPLIT_SCHUR_PRE_A11:
178a9908d51SBarry Smith       ierr = PetscViewerASCIIPrintf(viewer,"  Preconditioner for the Schur complement formed from A11\n");CHKERRQ(ierr);
179a9908d51SBarry Smith       break;
180e74569cdSMatthew G. Knepley     case PC_FIELDSPLIT_SCHUR_PRE_FULL:
181a9908d51SBarry Smith       ierr = PetscViewerASCIIPrintf(viewer,"  Preconditioner for the Schur complement formed from the exact Schur complement\n");CHKERRQ(ierr);
182a9908d51SBarry Smith       break;
1833e8b8b31SMatthew G Knepley     case PC_FIELDSPLIT_SCHUR_PRE_USER:
1843e8b8b31SMatthew G Knepley       if (jac->schur_user) {
1853e8b8b31SMatthew G Knepley         ierr = PetscViewerASCIIPrintf(viewer,"  Preconditioner for the Schur complement formed from user provided matrix\n");CHKERRQ(ierr);
1863e8b8b31SMatthew G Knepley       } else {
187e87fab1bSBarry Smith         ierr = PetscViewerASCIIPrintf(viewer,"  Preconditioner for the Schur complement formed from A11\n");CHKERRQ(ierr);
1883e8b8b31SMatthew G Knepley       }
1893e8b8b31SMatthew G Knepley       break;
1903e8b8b31SMatthew G Knepley     default:
19182f516ccSBarry Smith       SETERRQ1(PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_OUTOFRANGE, "Invalid Schur preconditioning type: %d", jac->schurpre);
1923e8b8b31SMatthew G Knepley     }
1933b224e63SBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  Split info:\n");CHKERRQ(ierr);
1943b224e63SBarry Smith     ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr);
1953b224e63SBarry Smith     for (i=0; i<jac->nsplits; i++) {
1963b224e63SBarry Smith       if (ilink->fields) {
1973b224e63SBarry Smith         ierr = PetscViewerASCIIPrintf(viewer,"Split number %D Fields ",i);CHKERRQ(ierr);
1983b224e63SBarry Smith         ierr = PetscViewerASCIIUseTabs(viewer,PETSC_FALSE);CHKERRQ(ierr);
1993b224e63SBarry Smith         for (j=0; j<ilink->nfields; j++) {
2003b224e63SBarry Smith           if (j > 0) {
2013b224e63SBarry Smith             ierr = PetscViewerASCIIPrintf(viewer,",");CHKERRQ(ierr);
2023b224e63SBarry Smith           }
2033b224e63SBarry Smith           ierr = PetscViewerASCIIPrintf(viewer," %D",ilink->fields[j]);CHKERRQ(ierr);
2043b224e63SBarry Smith         }
2053b224e63SBarry Smith         ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr);
2063b224e63SBarry Smith         ierr = PetscViewerASCIIUseTabs(viewer,PETSC_TRUE);CHKERRQ(ierr);
2073b224e63SBarry Smith       } else {
2083b224e63SBarry Smith         ierr = PetscViewerASCIIPrintf(viewer,"Split number %D Defined by IS\n",i);CHKERRQ(ierr);
2093b224e63SBarry Smith       }
2103b224e63SBarry Smith       ilink = ilink->next;
2113b224e63SBarry Smith     }
212435f959eSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"KSP solver for A00 block\n");CHKERRQ(ierr);
2133b224e63SBarry Smith     ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr);
21406de4afeSJed Brown     if (jac->head) {
215443836d0SMatthew G Knepley       ierr = KSPView(jac->head->ksp,viewer);CHKERRQ(ierr);
21606de4afeSJed Brown     } else  {ierr = PetscViewerASCIIPrintf(viewer,"  not yet available\n");CHKERRQ(ierr);}
2173b224e63SBarry Smith     ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr);
21806de4afeSJed Brown     if (jac->head && jac->kspupper != jac->head->ksp) {
219443836d0SMatthew G Knepley       ierr = PetscViewerASCIIPrintf(viewer,"KSP solver for upper A00 in upper triangular factor \n");CHKERRQ(ierr);
220443836d0SMatthew G Knepley       ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr);
221b2750c55SJed Brown       if (jac->kspupper) {ierr = KSPView(jac->kspupper,viewer);CHKERRQ(ierr);}
222b2750c55SJed Brown       else {ierr = PetscViewerASCIIPrintf(viewer,"  not yet available\n");CHKERRQ(ierr);}
223443836d0SMatthew G Knepley       ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr);
224443836d0SMatthew G Knepley     }
225435f959eSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"KSP solver for S = A11 - A10 inv(A00) A01 \n");CHKERRQ(ierr);
2263b224e63SBarry Smith     ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr);
22712cae6f2SJed Brown     if (jac->kspschur) {
2283b224e63SBarry Smith       ierr = KSPView(jac->kspschur,viewer);CHKERRQ(ierr);
22912cae6f2SJed Brown     } else {
23012cae6f2SJed Brown       ierr = PetscViewerASCIIPrintf(viewer,"  not yet available\n");CHKERRQ(ierr);
23112cae6f2SJed Brown     }
2323b224e63SBarry Smith     ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr);
2333b224e63SBarry Smith     ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr);
23406de4afeSJed Brown   } else if (isdraw && jac->head) {
2354996c5bdSBarry Smith     PetscDraw draw;
2364996c5bdSBarry Smith     PetscReal x,y,w,wd,h;
2374996c5bdSBarry Smith     PetscInt  cnt = 2;
2384996c5bdSBarry Smith     char      str[32];
2394996c5bdSBarry Smith 
2404996c5bdSBarry Smith     ierr = PetscViewerDrawGetDraw(viewer,0,&draw);CHKERRQ(ierr);
2414996c5bdSBarry Smith     ierr = PetscDrawGetCurrentPoint(draw,&x,&y);CHKERRQ(ierr);
242c74581afSBarry Smith     if (jac->kspupper != jac->head->ksp) cnt++;
243c74581afSBarry Smith     w  = 2*PetscMin(1.0 - x,x);
244c74581afSBarry Smith     wd = w/(cnt + 1);
245c74581afSBarry Smith 
2464996c5bdSBarry Smith     ierr = PetscSNPrintf(str,32,"Schur fact. %s",PCFieldSplitSchurFactTypes[jac->schurfactorization]);CHKERRQ(ierr);
24751fa3d41SBarry Smith     ierr = PetscDrawStringBoxed(draw,x,y,PETSC_DRAW_RED,PETSC_DRAW_BLACK,str,NULL,&h);CHKERRQ(ierr);
2484996c5bdSBarry Smith     y   -= h;
2494996c5bdSBarry Smith     if (jac->schurpre == PC_FIELDSPLIT_SCHUR_PRE_USER &&  !jac->schur_user) {
250e87fab1bSBarry Smith       ierr = PetscSNPrintf(str,32,"Prec. for Schur from %s",PCFieldSplitSchurPreTypes[PC_FIELDSPLIT_SCHUR_PRE_A11]);CHKERRQ(ierr);
2513b224e63SBarry Smith     } else {
2524996c5bdSBarry Smith       ierr = PetscSNPrintf(str,32,"Prec. for Schur from %s",PCFieldSplitSchurPreTypes[jac->schurpre]);CHKERRQ(ierr);
2534996c5bdSBarry Smith     }
25451fa3d41SBarry Smith     ierr = PetscDrawStringBoxed(draw,x+wd*(cnt-1)/2.0,y,PETSC_DRAW_RED,PETSC_DRAW_BLACK,str,NULL,&h);CHKERRQ(ierr);
2554996c5bdSBarry Smith     y   -= h;
2564996c5bdSBarry Smith     x    = x - wd*(cnt-1)/2.0;
2574996c5bdSBarry Smith 
2584996c5bdSBarry Smith     ierr = PetscDrawPushCurrentPoint(draw,x,y);CHKERRQ(ierr);
2594996c5bdSBarry Smith     ierr = KSPView(jac->head->ksp,viewer);CHKERRQ(ierr);
2604996c5bdSBarry Smith     ierr = PetscDrawPopCurrentPoint(draw);CHKERRQ(ierr);
2614996c5bdSBarry Smith     if (jac->kspupper != jac->head->ksp) {
2624996c5bdSBarry Smith       x   += wd;
2634996c5bdSBarry Smith       ierr = PetscDrawPushCurrentPoint(draw,x,y);CHKERRQ(ierr);
2644996c5bdSBarry Smith       ierr = KSPView(jac->kspupper,viewer);CHKERRQ(ierr);
2654996c5bdSBarry Smith       ierr = PetscDrawPopCurrentPoint(draw);CHKERRQ(ierr);
2664996c5bdSBarry Smith     }
2674996c5bdSBarry Smith     x   += wd;
2684996c5bdSBarry Smith     ierr = PetscDrawPushCurrentPoint(draw,x,y);CHKERRQ(ierr);
2694996c5bdSBarry Smith     ierr = KSPView(jac->kspschur,viewer);CHKERRQ(ierr);
2704996c5bdSBarry Smith     ierr = PetscDrawPopCurrentPoint(draw);CHKERRQ(ierr);
2713b224e63SBarry Smith   }
2723b224e63SBarry Smith   PetscFunctionReturn(0);
2733b224e63SBarry Smith }
2743b224e63SBarry Smith 
2756c924f48SJed Brown /* Precondition: jac->bs is set to a meaningful value */
2766c924f48SJed Brown static PetscErrorCode PCFieldSplitSetRuntimeSplits_Private(PC pc)
2776c924f48SJed Brown {
2786c924f48SJed Brown   PetscErrorCode ierr;
2796c924f48SJed Brown   PC_FieldSplit  *jac = (PC_FieldSplit*)pc->data;
2805d4c12cdSJungho Lee   PetscInt       i,nfields,*ifields,nfields_col,*ifields_col;
2815d4c12cdSJungho Lee   PetscBool      flg,flg_col;
2825d4c12cdSJungho Lee   char           optionname[128],splitname[8],optionname_col[128];
2836c924f48SJed Brown 
2846c924f48SJed Brown   PetscFunctionBegin;
285785e854fSJed Brown   ierr = PetscMalloc1(jac->bs,&ifields);CHKERRQ(ierr);
286785e854fSJed Brown   ierr = PetscMalloc1(jac->bs,&ifields_col);CHKERRQ(ierr);
2876c924f48SJed Brown   for (i=0,flg=PETSC_TRUE;; i++) {
2888caf3d72SBarry Smith     ierr        = PetscSNPrintf(splitname,sizeof(splitname),"%D",i);CHKERRQ(ierr);
2898caf3d72SBarry Smith     ierr        = PetscSNPrintf(optionname,sizeof(optionname),"-pc_fieldsplit_%D_fields",i);CHKERRQ(ierr);
2908caf3d72SBarry Smith     ierr        = PetscSNPrintf(optionname_col,sizeof(optionname_col),"-pc_fieldsplit_%D_fields_col",i);CHKERRQ(ierr);
2916c924f48SJed Brown     nfields     = jac->bs;
29229499fbbSJungho Lee     nfields_col = jac->bs;
293c5929fdfSBarry Smith     ierr        = PetscOptionsGetIntArray(((PetscObject)pc)->options,((PetscObject)pc)->prefix,optionname,ifields,&nfields,&flg);CHKERRQ(ierr);
294c5929fdfSBarry Smith     ierr        = PetscOptionsGetIntArray(((PetscObject)pc)->options,((PetscObject)pc)->prefix,optionname_col,ifields_col,&nfields_col,&flg_col);CHKERRQ(ierr);
2956c924f48SJed Brown     if (!flg) break;
2965d4c12cdSJungho Lee     else if (flg && !flg_col) {
2975d4c12cdSJungho Lee       if (!nfields) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_USER,"Cannot list zero fields");
2985d4c12cdSJungho Lee       ierr = PCFieldSplitSetFields(pc,splitname,nfields,ifields,ifields);CHKERRQ(ierr);
2992fa5cd67SKarl Rupp     } else {
3005d4c12cdSJungho Lee       if (!nfields || !nfields_col) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_USER,"Cannot list zero fields");
3015d4c12cdSJungho Lee       if (nfields != nfields_col) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_USER,"Number of row and column fields must match");
3025d4c12cdSJungho Lee       ierr = PCFieldSplitSetFields(pc,splitname,nfields,ifields,ifields_col);CHKERRQ(ierr);
3035d4c12cdSJungho Lee     }
3046c924f48SJed Brown   }
3056c924f48SJed Brown   if (i > 0) {
3066c924f48SJed Brown     /* Makes command-line setting of splits take precedence over setting them in code.
3076c924f48SJed Brown        Otherwise subsequent calls to PCFieldSplitSetIS() or PCFieldSplitSetFields() would
3086c924f48SJed Brown        create new splits, which would probably not be what the user wanted. */
3096c924f48SJed Brown     jac->splitdefined = PETSC_TRUE;
3106c924f48SJed Brown   }
3116c924f48SJed Brown   ierr = PetscFree(ifields);CHKERRQ(ierr);
3125d4c12cdSJungho Lee   ierr = PetscFree(ifields_col);CHKERRQ(ierr);
3136c924f48SJed Brown   PetscFunctionReturn(0);
3146c924f48SJed Brown }
3156c924f48SJed Brown 
31669a612a9SBarry Smith static PetscErrorCode PCFieldSplitSetDefaults(PC pc)
3170971522cSBarry Smith {
3180971522cSBarry Smith   PC_FieldSplit     *jac = (PC_FieldSplit*)pc->data;
3190971522cSBarry Smith   PetscErrorCode    ierr;
3205a9f2f41SSatish Balay   PC_FieldSplitLink ilink = jac->head;
3217b752e3dSPatrick Sanan   PetscBool         fieldsplit_default = PETSC_FALSE,coupling = PETSC_FALSE;
3226c924f48SJed Brown   PetscInt          i;
3230971522cSBarry Smith 
3240971522cSBarry Smith   PetscFunctionBegin;
3257287d2a3SDmitry Karpeev   /*
326f5f0d762SBarry Smith    Kinda messy, but at least this now uses DMCreateFieldDecomposition().
3277287d2a3SDmitry Karpeev    Should probably be rewritten.
3287287d2a3SDmitry Karpeev    */
329f5f0d762SBarry Smith   if (!ilink) {
330c5929fdfSBarry Smith     ierr = PetscOptionsGetBool(((PetscObject)pc)->options,((PetscObject)pc)->prefix,"-pc_fieldsplit_detect_coupling",&coupling,NULL);CHKERRQ(ierr);
3317b752e3dSPatrick Sanan     if (pc->dm && jac->dm_splits && !jac->detect && !coupling) {
332bafc1b83SMatthew G Knepley       PetscInt  numFields, f, i, j;
3330784a22cSJed Brown       char      **fieldNames;
3347b62db95SJungho Lee       IS        *fields;
335e7c4fc90SDmitry Karpeev       DM        *dms;
336bafc1b83SMatthew G Knepley       DM        subdm[128];
337bafc1b83SMatthew G Knepley       PetscBool flg;
338bafc1b83SMatthew G Knepley 
33916621825SDmitry Karpeev       ierr = DMCreateFieldDecomposition(pc->dm, &numFields, &fieldNames, &fields, &dms);CHKERRQ(ierr);
340bafc1b83SMatthew G Knepley       /* Allow the user to prescribe the splits */
341bafc1b83SMatthew G Knepley       for (i = 0, flg = PETSC_TRUE;; i++) {
342bafc1b83SMatthew G Knepley         PetscInt ifields[128];
343bafc1b83SMatthew G Knepley         IS       compField;
344bafc1b83SMatthew G Knepley         char     optionname[128], splitname[8];
345bafc1b83SMatthew G Knepley         PetscInt nfields = numFields;
346bafc1b83SMatthew G Knepley 
3478caf3d72SBarry Smith         ierr = PetscSNPrintf(optionname, sizeof(optionname), "-pc_fieldsplit_%D_fields", i);CHKERRQ(ierr);
348c5929fdfSBarry Smith         ierr = PetscOptionsGetIntArray(((PetscObject)pc)->options,((PetscObject)pc)->prefix, optionname, ifields, &nfields, &flg);CHKERRQ(ierr);
349bafc1b83SMatthew G Knepley         if (!flg) break;
35082f516ccSBarry Smith         if (numFields > 128) SETERRQ1(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Cannot currently support %d > 128 fields", numFields);
351bafc1b83SMatthew G Knepley         ierr = DMCreateSubDM(pc->dm, nfields, ifields, &compField, &subdm[i]);CHKERRQ(ierr);
352bafc1b83SMatthew G Knepley         if (nfields == 1) {
353bafc1b83SMatthew G Knepley           ierr = PCFieldSplitSetIS(pc, fieldNames[ifields[0]], compField);CHKERRQ(ierr);
354bafc1b83SMatthew G Knepley         } else {
3558caf3d72SBarry Smith           ierr = PetscSNPrintf(splitname, sizeof(splitname), "%D", i);CHKERRQ(ierr);
356bafc1b83SMatthew G Knepley           ierr = PCFieldSplitSetIS(pc, splitname, compField);CHKERRQ(ierr);
3577287d2a3SDmitry Karpeev         }
358bafc1b83SMatthew G Knepley         ierr = ISDestroy(&compField);CHKERRQ(ierr);
359bafc1b83SMatthew G Knepley         for (j = 0; j < nfields; ++j) {
360bafc1b83SMatthew G Knepley           f    = ifields[j];
3617b62db95SJungho Lee           ierr = PetscFree(fieldNames[f]);CHKERRQ(ierr);
3627b62db95SJungho Lee           ierr = ISDestroy(&fields[f]);CHKERRQ(ierr);
3637b62db95SJungho Lee         }
364bafc1b83SMatthew G Knepley       }
365bafc1b83SMatthew G Knepley       if (i == 0) {
366bafc1b83SMatthew G Knepley         for (f = 0; f < numFields; ++f) {
367bafc1b83SMatthew G Knepley           ierr = PCFieldSplitSetIS(pc, fieldNames[f], fields[f]);CHKERRQ(ierr);
368bafc1b83SMatthew G Knepley           ierr = PetscFree(fieldNames[f]);CHKERRQ(ierr);
369bafc1b83SMatthew G Knepley           ierr = ISDestroy(&fields[f]);CHKERRQ(ierr);
370bafc1b83SMatthew G Knepley         }
371bafc1b83SMatthew G Knepley       } else {
372d724dfffSBarry Smith         for (j=0; j<numFields; j++) {
373d724dfffSBarry Smith           ierr = DMDestroy(dms+j);CHKERRQ(ierr);
374d724dfffSBarry Smith         }
375d724dfffSBarry Smith         ierr = PetscFree(dms);CHKERRQ(ierr);
376785e854fSJed Brown         ierr = PetscMalloc1(i, &dms);CHKERRQ(ierr);
3772fa5cd67SKarl Rupp         for (j = 0; j < i; ++j) dms[j] = subdm[j];
378bafc1b83SMatthew G Knepley       }
3797b62db95SJungho Lee       ierr = PetscFree(fieldNames);CHKERRQ(ierr);
3807b62db95SJungho Lee       ierr = PetscFree(fields);CHKERRQ(ierr);
381e7c4fc90SDmitry Karpeev       if (dms) {
3828b8307b2SJed Brown         ierr = PetscInfo(pc, "Setting up physics based fieldsplit preconditioner using the embedded DM\n");CHKERRQ(ierr);
383bafc1b83SMatthew G Knepley         for (ilink = jac->head, i = 0; ilink; ilink = ilink->next, ++i) {
3847287d2a3SDmitry Karpeev           const char *prefix;
3857287d2a3SDmitry Karpeev           ierr = PetscObjectGetOptionsPrefix((PetscObject)(ilink->ksp),&prefix);CHKERRQ(ierr);
3867287d2a3SDmitry Karpeev           ierr = PetscObjectSetOptionsPrefix((PetscObject)(dms[i]), prefix);CHKERRQ(ierr);
3877b62db95SJungho Lee           ierr = KSPSetDM(ilink->ksp, dms[i]);CHKERRQ(ierr);
3887b62db95SJungho Lee           ierr = KSPSetDMActive(ilink->ksp, PETSC_FALSE);CHKERRQ(ierr);
389*95dbaa6fSMatthew G. Knepley           {
390*95dbaa6fSMatthew G. Knepley             PetscErrorCode (*func)(KSP,Mat,Mat,void*);
391*95dbaa6fSMatthew G. Knepley             void            *ctx;
392*95dbaa6fSMatthew G. Knepley 
393*95dbaa6fSMatthew G. Knepley             ierr = DMKSPGetComputeOperators(pc->dm, &func, &ctx);CHKERRQ(ierr);
394*95dbaa6fSMatthew G. Knepley             ierr = DMKSPSetComputeOperators(dms[i],  func,  ctx);CHKERRQ(ierr);
395*95dbaa6fSMatthew G. Knepley           }
3967287d2a3SDmitry Karpeev           ierr = PetscObjectIncrementTabLevel((PetscObject)dms[i],(PetscObject)ilink->ksp,0);CHKERRQ(ierr);
397e7c4fc90SDmitry Karpeev           ierr = DMDestroy(&dms[i]);CHKERRQ(ierr);
3982fa5ba8aSJed Brown         }
3997b62db95SJungho Lee         ierr = PetscFree(dms);CHKERRQ(ierr);
4008b8307b2SJed Brown       }
40166ffff09SJed Brown     } else {
402521d7252SBarry Smith       if (jac->bs <= 0) {
403704ba839SBarry Smith         if (pc->pmat) {
404521d7252SBarry Smith           ierr = MatGetBlockSize(pc->pmat,&jac->bs);CHKERRQ(ierr);
4052fa5cd67SKarl Rupp         } else jac->bs = 1;
406521d7252SBarry Smith       }
407d32f9abdSBarry Smith 
4087b752e3dSPatrick Sanan       if (jac->detect) {
4096ce1633cSBarry Smith         IS       zerodiags,rest;
4106ce1633cSBarry Smith         PetscInt nmin,nmax;
4116ce1633cSBarry Smith 
4126ce1633cSBarry Smith         ierr = MatGetOwnershipRange(pc->mat,&nmin,&nmax);CHKERRQ(ierr);
4136ce1633cSBarry Smith         ierr = MatFindZeroDiagonals(pc->mat,&zerodiags);CHKERRQ(ierr);
4146ce1633cSBarry Smith         ierr = ISComplement(zerodiags,nmin,nmax,&rest);CHKERRQ(ierr);
4156ce1633cSBarry Smith         ierr = PCFieldSplitSetIS(pc,"0",rest);CHKERRQ(ierr);
4166ce1633cSBarry Smith         ierr = PCFieldSplitSetIS(pc,"1",zerodiags);CHKERRQ(ierr);
417fcfd50ebSBarry Smith         ierr = ISDestroy(&zerodiags);CHKERRQ(ierr);
418fcfd50ebSBarry Smith         ierr = ISDestroy(&rest);CHKERRQ(ierr);
4193a062f41SBarry Smith       } else if (coupling) {
4203a062f41SBarry Smith         IS       coupling,rest;
4213a062f41SBarry Smith         PetscInt nmin,nmax;
4223a062f41SBarry Smith 
4233a062f41SBarry Smith         ierr = MatGetOwnershipRange(pc->mat,&nmin,&nmax);CHKERRQ(ierr);
4243a062f41SBarry Smith         ierr = MatFindOffBlockDiagonalEntries(pc->mat,&coupling);CHKERRQ(ierr);
4256bea0878SBarry Smith         ierr = ISCreateStride(PetscObjectComm((PetscObject)pc->mat),nmax-nmin,nmin,1,&rest);CHKERRQ(ierr);
426e52d2c62SBarry Smith         ierr = ISSetIdentity(rest);CHKERRQ(ierr);
427d020c841SBarry Smith         ierr = PCFieldSplitSetIS(pc,"0",rest);CHKERRQ(ierr);
428d020c841SBarry Smith         ierr = PCFieldSplitSetIS(pc,"1",coupling);CHKERRQ(ierr);
4293a062f41SBarry Smith         ierr = ISDestroy(&coupling);CHKERRQ(ierr);
4303a062f41SBarry Smith         ierr = ISDestroy(&rest);CHKERRQ(ierr);
4316ce1633cSBarry Smith       } else {
432c5929fdfSBarry Smith         ierr = PetscOptionsGetBool(((PetscObject)pc)->options,((PetscObject)pc)->prefix,"-pc_fieldsplit_default",&fieldsplit_default,NULL);CHKERRQ(ierr);
4337287d2a3SDmitry Karpeev         if (!fieldsplit_default) {
434d32f9abdSBarry Smith           /* Allow user to set fields from command line,  if bs was known at the time of PCSetFromOptions_FieldSplit()
435d32f9abdSBarry Smith            then it is set there. This is not ideal because we should only have options set in XXSetFromOptions(). */
4366c924f48SJed Brown           ierr = PCFieldSplitSetRuntimeSplits_Private(pc);CHKERRQ(ierr);
4376c924f48SJed Brown           if (jac->splitdefined) {ierr = PetscInfo(pc,"Splits defined using the options database\n");CHKERRQ(ierr);}
438d32f9abdSBarry Smith         }
4396dbb499eSCian Wilson         if ((fieldsplit_default || !jac->splitdefined) && !jac->isrestrict) {
440d32f9abdSBarry Smith           ierr = PetscInfo(pc,"Using default splitting of fields\n");CHKERRQ(ierr);
441db4c96c1SJed Brown           for (i=0; i<jac->bs; i++) {
4426c924f48SJed Brown             char splitname[8];
4438caf3d72SBarry Smith             ierr = PetscSNPrintf(splitname,sizeof(splitname),"%D",i);CHKERRQ(ierr);
4445d4c12cdSJungho Lee             ierr = PCFieldSplitSetFields(pc,splitname,1,&i,&i);CHKERRQ(ierr);
44579416396SBarry Smith           }
4465d4c12cdSJungho Lee           jac->defaultsplit = PETSC_TRUE;
447521d7252SBarry Smith         }
44866ffff09SJed Brown       }
4496ce1633cSBarry Smith     }
450edf189efSBarry Smith   } else if (jac->nsplits == 1) {
451edf189efSBarry Smith     if (ilink->is) {
452edf189efSBarry Smith       IS       is2;
453edf189efSBarry Smith       PetscInt nmin,nmax;
454edf189efSBarry Smith 
455edf189efSBarry Smith       ierr = MatGetOwnershipRange(pc->mat,&nmin,&nmax);CHKERRQ(ierr);
456edf189efSBarry Smith       ierr = ISComplement(ilink->is,nmin,nmax,&is2);CHKERRQ(ierr);
457db4c96c1SJed Brown       ierr = PCFieldSplitSetIS(pc,"1",is2);CHKERRQ(ierr);
458fcfd50ebSBarry Smith       ierr = ISDestroy(&is2);CHKERRQ(ierr);
45982f516ccSBarry Smith     } else SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Must provide at least two sets of fields to PCFieldSplit()");
460edf189efSBarry Smith   }
461d0af7cd3SBarry Smith 
46282f516ccSBarry Smith   if (jac->nsplits < 2) SETERRQ1(PetscObjectComm((PetscObject)pc),PETSC_ERR_PLIB,"Unhandled case, must have at least two fields, not %d", jac->nsplits);
46369a612a9SBarry Smith   PetscFunctionReturn(0);
46469a612a9SBarry Smith }
46569a612a9SBarry Smith 
4662d747510SLisandro Dalcin PETSC_EXTERN PetscErrorCode PetscOptionsFindPairPrefix_Private(PetscOptions,const char pre[], const char name[],const char *value[],PetscBool *flg);
467514bf10dSMatthew G Knepley 
46869a612a9SBarry Smith static PetscErrorCode PCSetUp_FieldSplit(PC pc)
46969a612a9SBarry Smith {
47069a612a9SBarry Smith   PC_FieldSplit     *jac = (PC_FieldSplit*)pc->data;
47169a612a9SBarry Smith   PetscErrorCode    ierr;
4725a9f2f41SSatish Balay   PC_FieldSplitLink ilink;
4732c9966d7SBarry Smith   PetscInt          i,nsplit;
4745f4ab4e1SJungho Lee   PetscBool         sorted, sorted_col;
47569a612a9SBarry Smith 
47669a612a9SBarry Smith   PetscFunctionBegin;
47769a612a9SBarry Smith   ierr   = PCFieldSplitSetDefaults(pc);CHKERRQ(ierr);
47897bbdb24SBarry Smith   nsplit = jac->nsplits;
4795a9f2f41SSatish Balay   ilink  = jac->head;
48097bbdb24SBarry Smith 
48197bbdb24SBarry Smith   /* get the matrices for each split */
482704ba839SBarry Smith   if (!jac->issetup) {
4831b9fc7fcSBarry Smith     PetscInt rstart,rend,nslots,bs;
48497bbdb24SBarry Smith 
485704ba839SBarry Smith     jac->issetup = PETSC_TRUE;
486704ba839SBarry Smith 
4875d4c12cdSJungho Lee     /* This is done here instead of in PCFieldSplitSetFields() because may not have matrix at that point */
4882c9966d7SBarry Smith     if (jac->defaultsplit || !ilink->is) {
4892c9966d7SBarry Smith       if (jac->bs <= 0) jac->bs = nsplit;
4902c9966d7SBarry Smith     }
49151f519a2SBarry Smith     bs     = jac->bs;
49297bbdb24SBarry Smith     ierr   = MatGetOwnershipRange(pc->pmat,&rstart,&rend);CHKERRQ(ierr);
4931b9fc7fcSBarry Smith     nslots = (rend - rstart)/bs;
4941b9fc7fcSBarry Smith     for (i=0; i<nsplit; i++) {
4951b9fc7fcSBarry Smith       if (jac->defaultsplit) {
496ce94432eSBarry Smith         ierr = ISCreateStride(PetscObjectComm((PetscObject)pc),nslots,rstart+i,nsplit,&ilink->is);CHKERRQ(ierr);
4975f4ab4e1SJungho Lee         ierr = ISDuplicate(ilink->is,&ilink->is_col);CHKERRQ(ierr);
498704ba839SBarry Smith       } else if (!ilink->is) {
499ccb205f8SBarry Smith         if (ilink->nfields > 1) {
5005f4ab4e1SJungho Lee           PetscInt *ii,*jj,j,k,nfields = ilink->nfields,*fields = ilink->fields,*fields_col = ilink->fields_col;
501785e854fSJed Brown           ierr = PetscMalloc1(ilink->nfields*nslots,&ii);CHKERRQ(ierr);
502785e854fSJed Brown           ierr = PetscMalloc1(ilink->nfields*nslots,&jj);CHKERRQ(ierr);
5031b9fc7fcSBarry Smith           for (j=0; j<nslots; j++) {
5041b9fc7fcSBarry Smith             for (k=0; k<nfields; k++) {
5051b9fc7fcSBarry Smith               ii[nfields*j + k] = rstart + bs*j + fields[k];
5065f4ab4e1SJungho Lee               jj[nfields*j + k] = rstart + bs*j + fields_col[k];
50797bbdb24SBarry Smith             }
50897bbdb24SBarry Smith           }
509ce94432eSBarry Smith           ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),nslots*nfields,ii,PETSC_OWN_POINTER,&ilink->is);CHKERRQ(ierr);
510ce94432eSBarry Smith           ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),nslots*nfields,jj,PETSC_OWN_POINTER,&ilink->is_col);CHKERRQ(ierr);
51190e68f20SPatrick Farrell           ierr = ISSetBlockSize(ilink->is, nfields);CHKERRQ(ierr);
51290e68f20SPatrick Farrell           ierr = ISSetBlockSize(ilink->is_col, nfields);CHKERRQ(ierr);
513ccb205f8SBarry Smith         } else {
514ce94432eSBarry Smith           ierr = ISCreateStride(PetscObjectComm((PetscObject)pc),nslots,rstart+ilink->fields[0],bs,&ilink->is);CHKERRQ(ierr);
515ce94432eSBarry Smith           ierr = ISCreateStride(PetscObjectComm((PetscObject)pc),nslots,rstart+ilink->fields_col[0],bs,&ilink->is_col);CHKERRQ(ierr);
516ccb205f8SBarry Smith         }
5173e197d65SBarry Smith       }
518704ba839SBarry Smith       ierr = ISSorted(ilink->is,&sorted);CHKERRQ(ierr);
5195f4ab4e1SJungho Lee       if (ilink->is_col) { ierr = ISSorted(ilink->is_col,&sorted_col);CHKERRQ(ierr); }
5205f4ab4e1SJungho Lee       if (!sorted || !sorted_col) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_USER,"Fields must be sorted when creating split");
521704ba839SBarry Smith       ilink = ilink->next;
5221b9fc7fcSBarry Smith     }
5231b9fc7fcSBarry Smith   }
5241b9fc7fcSBarry Smith 
525704ba839SBarry Smith   ilink = jac->head;
52697bbdb24SBarry Smith   if (!jac->pmat) {
527bdddcaaaSMatthew G Knepley     Vec xtmp;
528bdddcaaaSMatthew G Knepley 
5292a7a6963SBarry Smith     ierr = MatCreateVecs(pc->pmat,&xtmp,NULL);CHKERRQ(ierr);
530785e854fSJed Brown     ierr = PetscMalloc1(nsplit,&jac->pmat);CHKERRQ(ierr);
531dcca6d9dSJed Brown     ierr = PetscMalloc2(nsplit,&jac->x,nsplit,&jac->y);CHKERRQ(ierr);
532cf502942SBarry Smith     for (i=0; i<nsplit; i++) {
533bdddcaaaSMatthew G Knepley       MatNullSpace sp;
534bdddcaaaSMatthew G Knepley 
535a3df900dSMatthew G Knepley       /* Check for preconditioning matrix attached to IS */
536a3df900dSMatthew G Knepley       ierr = PetscObjectQuery((PetscObject) ilink->is, "pmat", (PetscObject*) &jac->pmat[i]);CHKERRQ(ierr);
537a3df900dSMatthew G Knepley       if (jac->pmat[i]) {
538a3df900dSMatthew G Knepley         ierr = PetscObjectReference((PetscObject) jac->pmat[i]);CHKERRQ(ierr);
539a3df900dSMatthew G Knepley         if (jac->type == PC_COMPOSITE_SCHUR) {
540a3df900dSMatthew G Knepley           jac->schur_user = jac->pmat[i];
5412fa5cd67SKarl Rupp 
542a3df900dSMatthew G Knepley           ierr = PetscObjectReference((PetscObject) jac->schur_user);CHKERRQ(ierr);
543a3df900dSMatthew G Knepley         }
544a3df900dSMatthew G Knepley       } else {
5453a062f41SBarry Smith         const char *prefix;
5467dae84e0SHong Zhang         ierr = MatCreateSubMatrix(pc->pmat,ilink->is,ilink->is_col,MAT_INITIAL_MATRIX,&jac->pmat[i]);CHKERRQ(ierr);
5473a062f41SBarry Smith         ierr = KSPGetOptionsPrefix(ilink->ksp,&prefix);CHKERRQ(ierr);
5483a062f41SBarry Smith         ierr = MatSetOptionsPrefix(jac->pmat[i],prefix);CHKERRQ(ierr);
5493a062f41SBarry Smith         ierr = MatViewFromOptions(jac->pmat[i],NULL,"-mat_view");CHKERRQ(ierr);
550a3df900dSMatthew G Knepley       }
551bdddcaaaSMatthew G Knepley       /* create work vectors for each split */
5522a7a6963SBarry Smith       ierr     = MatCreateVecs(jac->pmat[i],&jac->x[i],&jac->y[i]);CHKERRQ(ierr);
5530298fd71SBarry Smith       ilink->x = jac->x[i]; ilink->y = jac->y[i]; ilink->z = NULL;
554bdddcaaaSMatthew G Knepley       /* compute scatter contexts needed by multiplicative versions and non-default splits */
55535928de7SBarry Smith       ierr = VecScatterCreateWithData(xtmp,ilink->is,jac->x[i],NULL,&ilink->sctx);CHKERRQ(ierr);
556ed1f0337SMatthew G Knepley       ierr = PetscObjectQuery((PetscObject) ilink->is, "nearnullspace", (PetscObject*) &sp);CHKERRQ(ierr);
557ed1f0337SMatthew G Knepley       if (sp) {
558ed1f0337SMatthew G Knepley         ierr = MatSetNearNullSpace(jac->pmat[i], sp);CHKERRQ(ierr);
559ed1f0337SMatthew G Knepley       }
560704ba839SBarry Smith       ilink = ilink->next;
561cf502942SBarry Smith     }
562bdddcaaaSMatthew G Knepley     ierr = VecDestroy(&xtmp);CHKERRQ(ierr);
56397bbdb24SBarry Smith   } else {
564ef7efd37SHong Zhang     MatReuse scall;
565ef7efd37SHong Zhang     if (pc->flag == DIFFERENT_NONZERO_PATTERN) {
566ef7efd37SHong Zhang       for (i=0; i<nsplit; i++) {
567ef7efd37SHong Zhang         ierr = MatDestroy(&jac->pmat[i]);CHKERRQ(ierr);
568ef7efd37SHong Zhang       }
569ef7efd37SHong Zhang       scall = MAT_INITIAL_MATRIX;
570ef7efd37SHong Zhang     } else scall = MAT_REUSE_MATRIX;
571ef7efd37SHong Zhang 
572cf502942SBarry Smith     for (i=0; i<nsplit; i++) {
573a3df900dSMatthew G Knepley       Mat pmat;
574a3df900dSMatthew G Knepley 
575a3df900dSMatthew G Knepley       /* Check for preconditioning matrix attached to IS */
576a3df900dSMatthew G Knepley       ierr = PetscObjectQuery((PetscObject) ilink->is, "pmat", (PetscObject*) &pmat);CHKERRQ(ierr);
577a3df900dSMatthew G Knepley       if (!pmat) {
578ef7efd37SHong Zhang         ierr = MatCreateSubMatrix(pc->pmat,ilink->is,ilink->is_col,scall,&jac->pmat[i]);CHKERRQ(ierr);
579a3df900dSMatthew G Knepley       }
580704ba839SBarry Smith       ilink = ilink->next;
581cf502942SBarry Smith     }
58297bbdb24SBarry Smith   }
5834e39094bSDmitry Karpeev   if (jac->diag_use_amat) {
584519d70e2SJed Brown     ilink = jac->head;
585519d70e2SJed Brown     if (!jac->mat) {
586785e854fSJed Brown       ierr = PetscMalloc1(nsplit,&jac->mat);CHKERRQ(ierr);
587519d70e2SJed Brown       for (i=0; i<nsplit; i++) {
5887dae84e0SHong Zhang         ierr  = MatCreateSubMatrix(pc->mat,ilink->is,ilink->is_col,MAT_INITIAL_MATRIX,&jac->mat[i]);CHKERRQ(ierr);
589519d70e2SJed Brown         ilink = ilink->next;
590519d70e2SJed Brown       }
591519d70e2SJed Brown     } else {
592ef7efd37SHong Zhang       MatReuse scall;
593ef7efd37SHong Zhang       if (pc->flag == DIFFERENT_NONZERO_PATTERN) {
594519d70e2SJed Brown         for (i=0; i<nsplit; i++) {
595ef7efd37SHong Zhang           ierr = MatDestroy(&jac->mat[i]);CHKERRQ(ierr);
596ef7efd37SHong Zhang         }
597ef7efd37SHong Zhang         scall = MAT_INITIAL_MATRIX;
598ef7efd37SHong Zhang       } else scall = MAT_REUSE_MATRIX;
599ef7efd37SHong Zhang 
600ef7efd37SHong Zhang       for (i=0; i<nsplit; i++) {
601ef7efd37SHong Zhang         if (jac->mat[i]) {ierr = MatCreateSubMatrix(pc->mat,ilink->is,ilink->is_col,scall,&jac->mat[i]);CHKERRQ(ierr);}
602519d70e2SJed Brown         ilink = ilink->next;
603519d70e2SJed Brown       }
604519d70e2SJed Brown     }
605519d70e2SJed Brown   } else {
606519d70e2SJed Brown     jac->mat = jac->pmat;
607519d70e2SJed Brown   }
60897bbdb24SBarry Smith 
60953935eafSBarry Smith   /* Check for null space attached to IS */
61053935eafSBarry Smith   ilink = jac->head;
61153935eafSBarry Smith   for (i=0; i<nsplit; i++) {
61253935eafSBarry Smith     MatNullSpace sp;
61353935eafSBarry Smith 
61453935eafSBarry Smith     ierr = PetscObjectQuery((PetscObject) ilink->is, "nullspace", (PetscObject*) &sp);CHKERRQ(ierr);
61553935eafSBarry Smith     if (sp) {
61653935eafSBarry Smith       ierr = MatSetNullSpace(jac->mat[i], sp);CHKERRQ(ierr);
61753935eafSBarry Smith     }
61853935eafSBarry Smith     ilink = ilink->next;
61953935eafSBarry Smith   }
62053935eafSBarry Smith 
6216c8605c2SJed Brown   if (jac->type != PC_COMPOSITE_ADDITIVE  && jac->type != PC_COMPOSITE_SCHUR) {
62268dd23aaSBarry Smith     /* extract the rows of the matrix associated with each field: used for efficient computation of residual inside algorithm */
6234e39094bSDmitry Karpeev     /* FIXME: Can/should we reuse jac->mat whenever (jac->diag_use_amat) is true? */
62468dd23aaSBarry Smith     ilink = jac->head;
625e52d2c62SBarry Smith     if (nsplit == 2 && jac->type == PC_COMPOSITE_MULTIPLICATIVE) {
626e52d2c62SBarry Smith       /* special case need where Afield[0] is not needed and only certain columns of Afield[1] are needed since update is only on those rows of the solution */
627e52d2c62SBarry Smith       if (!jac->Afield) {
628e52d2c62SBarry Smith         ierr = PetscCalloc1(nsplit,&jac->Afield);CHKERRQ(ierr);
62980c96bb1SFande Kong         if (jac->offdiag_use_amat) {
6307dae84e0SHong Zhang           ierr  = MatCreateSubMatrix(pc->mat,ilink->next->is,ilink->is,MAT_INITIAL_MATRIX,&jac->Afield[1]);CHKERRQ(ierr);
631e52d2c62SBarry Smith         } else {
6327dae84e0SHong Zhang           ierr  = MatCreateSubMatrix(pc->pmat,ilink->next->is,ilink->is,MAT_INITIAL_MATRIX,&jac->Afield[1]);CHKERRQ(ierr);
63380c96bb1SFande Kong         }
63480c96bb1SFande Kong       } else {
635ef7efd37SHong Zhang         MatReuse scall;
636ef7efd37SHong Zhang         if (pc->flag == DIFFERENT_NONZERO_PATTERN) {
637ef7efd37SHong Zhang           for (i=0; i<nsplit; i++) {
638ef7efd37SHong Zhang             ierr = MatDestroy(&jac->Afield[1]);CHKERRQ(ierr);
639ef7efd37SHong Zhang           }
640ef7efd37SHong Zhang           scall = MAT_INITIAL_MATRIX;
641ef7efd37SHong Zhang         } else scall = MAT_REUSE_MATRIX;
642ef7efd37SHong Zhang 
64380c96bb1SFande Kong         if (jac->offdiag_use_amat) {
644ef7efd37SHong Zhang           ierr  = MatCreateSubMatrix(pc->mat,ilink->next->is,ilink->is,scall,&jac->Afield[1]);CHKERRQ(ierr);
64580c96bb1SFande Kong         } else {
646ef7efd37SHong Zhang           ierr  = MatCreateSubMatrix(pc->pmat,ilink->next->is,ilink->is,scall,&jac->Afield[1]);CHKERRQ(ierr);
64780c96bb1SFande Kong         }
648e52d2c62SBarry Smith       }
649e52d2c62SBarry Smith     } else {
65068dd23aaSBarry Smith       if (!jac->Afield) {
651785e854fSJed Brown         ierr = PetscMalloc1(nsplit,&jac->Afield);CHKERRQ(ierr);
65268dd23aaSBarry Smith         for (i=0; i<nsplit; i++) {
65380c96bb1SFande Kong           if (jac->offdiag_use_amat) {
6547dae84e0SHong Zhang             ierr  = MatCreateSubMatrix(pc->mat,ilink->is,NULL,MAT_INITIAL_MATRIX,&jac->Afield[i]);CHKERRQ(ierr);
65580c96bb1SFande Kong           } else {
6567dae84e0SHong Zhang             ierr  = MatCreateSubMatrix(pc->pmat,ilink->is,NULL,MAT_INITIAL_MATRIX,&jac->Afield[i]);CHKERRQ(ierr);
65780c96bb1SFande Kong           }
65868dd23aaSBarry Smith           ilink = ilink->next;
65968dd23aaSBarry Smith         }
66068dd23aaSBarry Smith       } else {
661ef7efd37SHong Zhang         MatReuse scall;
662ef7efd37SHong Zhang         if (pc->flag == DIFFERENT_NONZERO_PATTERN) {
663ef7efd37SHong Zhang           for (i=0; i<nsplit; i++) {
664ef7efd37SHong Zhang             ierr = MatDestroy(&jac->Afield[i]);CHKERRQ(ierr);
665ef7efd37SHong Zhang           }
666ef7efd37SHong Zhang           scall = MAT_INITIAL_MATRIX;
667ef7efd37SHong Zhang         } else scall = MAT_REUSE_MATRIX;
668ef7efd37SHong Zhang 
66968dd23aaSBarry Smith         for (i=0; i<nsplit; i++) {
67080c96bb1SFande Kong           if (jac->offdiag_use_amat) {
671ef7efd37SHong Zhang             ierr  = MatCreateSubMatrix(pc->mat,ilink->is,NULL,scall,&jac->Afield[i]);CHKERRQ(ierr);
67280c96bb1SFande Kong           } else {
673ef7efd37SHong Zhang             ierr  = MatCreateSubMatrix(pc->pmat,ilink->is,NULL,scall,&jac->Afield[i]);CHKERRQ(ierr);
67480c96bb1SFande Kong           }
67568dd23aaSBarry Smith           ilink = ilink->next;
67668dd23aaSBarry Smith         }
67768dd23aaSBarry Smith       }
67868dd23aaSBarry Smith     }
679e52d2c62SBarry Smith   }
68068dd23aaSBarry Smith 
6813b224e63SBarry Smith   if (jac->type == PC_COMPOSITE_SCHUR) {
6823b224e63SBarry Smith     IS          ccis;
683c096484dSStefano Zampini     PetscBool   isspd;
6844aa3045dSJed Brown     PetscInt    rstart,rend;
685093c86ffSJed Brown     char        lscname[256];
686093c86ffSJed Brown     PetscObject LSC_L;
687ce94432eSBarry Smith 
688ce94432eSBarry Smith     if (nsplit != 2) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_INCOMP,"To use Schur complement preconditioner you must have exactly 2 fields");
68968dd23aaSBarry Smith 
690c096484dSStefano Zampini     /* If pc->mat is SPD, don't scale by -1 the Schur complement */
691c096484dSStefano Zampini     if (jac->schurscale == (PetscScalar)-1.0) {
692c096484dSStefano Zampini       ierr = MatGetOption(pc->pmat,MAT_SPD,&isspd);CHKERRQ(ierr);
693c096484dSStefano Zampini       jac->schurscale = (isspd == PETSC_TRUE) ? 1.0 : -1.0;
694c096484dSStefano Zampini     }
695c096484dSStefano Zampini 
696e6cab6aaSJed Brown     /* When extracting off-diagonal submatrices, we take complements from this range */
697e6cab6aaSJed Brown     ierr = MatGetOwnershipRangeColumn(pc->mat,&rstart,&rend);CHKERRQ(ierr);
698e6cab6aaSJed Brown 
6993b224e63SBarry Smith     /* need to handle case when one is resetting up the preconditioner */
7003b224e63SBarry Smith     if (jac->schur) {
7010298fd71SBarry Smith       KSP kspA = jac->head->ksp, kspInner = NULL, kspUpper = jac->kspupper;
702443836d0SMatthew G Knepley 
703fb3147dbSMatthew G Knepley       ierr  = MatSchurComplementGetKSP(jac->schur, &kspInner);CHKERRQ(ierr);
7043b224e63SBarry Smith       ilink = jac->head;
70549bb4cd7SJungho Lee       ierr  = ISComplement(ilink->is_col,rstart,rend,&ccis);CHKERRQ(ierr);
7064e39094bSDmitry Karpeev       if (jac->offdiag_use_amat) {
7077dae84e0SHong Zhang 	ierr  = MatCreateSubMatrix(pc->mat,ilink->is,ccis,MAT_REUSE_MATRIX,&jac->B);CHKERRQ(ierr);
708c84da90fSDmitry Karpeev       } else {
7097dae84e0SHong Zhang 	ierr  = MatCreateSubMatrix(pc->pmat,ilink->is,ccis,MAT_REUSE_MATRIX,&jac->B);CHKERRQ(ierr);
710c84da90fSDmitry Karpeev       }
711fcfd50ebSBarry Smith       ierr  = ISDestroy(&ccis);CHKERRQ(ierr);
7123b224e63SBarry Smith       ilink = ilink->next;
71349bb4cd7SJungho Lee       ierr  = ISComplement(ilink->is_col,rstart,rend,&ccis);CHKERRQ(ierr);
7144e39094bSDmitry Karpeev       if (jac->offdiag_use_amat) {
7157dae84e0SHong Zhang 	ierr  = MatCreateSubMatrix(pc->mat,ilink->is,ccis,MAT_REUSE_MATRIX,&jac->C);CHKERRQ(ierr);
716c84da90fSDmitry Karpeev       } else {
7177dae84e0SHong Zhang 	ierr  = MatCreateSubMatrix(pc->pmat,ilink->is,ccis,MAT_REUSE_MATRIX,&jac->C);CHKERRQ(ierr);
718c84da90fSDmitry Karpeev       }
719fcfd50ebSBarry Smith       ierr  = ISDestroy(&ccis);CHKERRQ(ierr);
720aa6c7ce3SBarry Smith       ierr  = MatSchurComplementUpdateSubMatrices(jac->schur,jac->mat[0],jac->pmat[0],jac->B,jac->C,jac->mat[1]);CHKERRQ(ierr);
721a7476a74SDmitry Karpeev       if (jac->schurpre == PC_FIELDSPLIT_SCHUR_PRE_SELFP) {
722a7476a74SDmitry Karpeev 	ierr = MatDestroy(&jac->schurp);CHKERRQ(ierr);
723a7476a74SDmitry Karpeev 	ierr = MatSchurComplementGetPmat(jac->schur,MAT_INITIAL_MATRIX,&jac->schurp);CHKERRQ(ierr);
724a7476a74SDmitry Karpeev       }
725443836d0SMatthew G Knepley       if (kspA != kspInner) {
72623ee1639SBarry Smith         ierr = KSPSetOperators(kspA,jac->mat[0],jac->pmat[0]);CHKERRQ(ierr);
727443836d0SMatthew G Knepley       }
728443836d0SMatthew G Knepley       if (kspUpper != kspA) {
72923ee1639SBarry Smith         ierr = KSPSetOperators(kspUpper,jac->mat[0],jac->pmat[0]);CHKERRQ(ierr);
730443836d0SMatthew G Knepley       }
73123ee1639SBarry Smith       ierr = KSPSetOperators(jac->kspschur,jac->schur,FieldSplitSchurPre(jac));CHKERRQ(ierr);
7323b224e63SBarry Smith     } else {
733bafc1b83SMatthew G Knepley       const char   *Dprefix;
734470b340bSDmitry Karpeev       char         schurprefix[256], schurmatprefix[256];
735514bf10dSMatthew G Knepley       char         schurtestoption[256];
736bdddcaaaSMatthew G Knepley       MatNullSpace sp;
737514bf10dSMatthew G Knepley       PetscBool    flg;
738686bed4dSStefano Zampini       KSP          kspt;
7393b224e63SBarry Smith 
740a04f6461SBarry Smith       /* extract the A01 and A10 matrices */
7413b224e63SBarry Smith       ilink = jac->head;
74249bb4cd7SJungho Lee       ierr  = ISComplement(ilink->is_col,rstart,rend,&ccis);CHKERRQ(ierr);
7434e39094bSDmitry Karpeev       if (jac->offdiag_use_amat) {
7447dae84e0SHong Zhang 	ierr = MatCreateSubMatrix(pc->mat,ilink->is,ccis,MAT_INITIAL_MATRIX,&jac->B);CHKERRQ(ierr);
745c84da90fSDmitry Karpeev       } else {
7467dae84e0SHong Zhang 	ierr = MatCreateSubMatrix(pc->pmat,ilink->is,ccis,MAT_INITIAL_MATRIX,&jac->B);CHKERRQ(ierr);
747c84da90fSDmitry Karpeev       }
748fcfd50ebSBarry Smith       ierr  = ISDestroy(&ccis);CHKERRQ(ierr);
7493b224e63SBarry Smith       ilink = ilink->next;
75049bb4cd7SJungho Lee       ierr  = ISComplement(ilink->is_col,rstart,rend,&ccis);CHKERRQ(ierr);
7514e39094bSDmitry Karpeev       if (jac->offdiag_use_amat) {
7527dae84e0SHong Zhang 	ierr = MatCreateSubMatrix(pc->mat,ilink->is,ccis,MAT_INITIAL_MATRIX,&jac->C);CHKERRQ(ierr);
753c84da90fSDmitry Karpeev       } else {
7547dae84e0SHong Zhang 	ierr = MatCreateSubMatrix(pc->pmat,ilink->is,ccis,MAT_INITIAL_MATRIX,&jac->C);CHKERRQ(ierr);
755c84da90fSDmitry Karpeev       }
756fcfd50ebSBarry Smith       ierr = ISDestroy(&ccis);CHKERRQ(ierr);
75720252d06SBarry Smith 
758f5236f50SJed Brown       /* Use mat[0] (diagonal block of Amat) preconditioned by pmat[0] to define Schur complement */
75920252d06SBarry Smith       ierr = MatCreate(((PetscObject)jac->mat[0])->comm,&jac->schur);CHKERRQ(ierr);
76020252d06SBarry Smith       ierr = MatSetType(jac->schur,MATSCHURCOMPLEMENT);CHKERRQ(ierr);
761bee83525SDmitry Karpeev       ierr = MatSchurComplementSetSubMatrices(jac->schur,jac->mat[0],jac->pmat[0],jac->B,jac->C,jac->mat[1]);CHKERRQ(ierr);
762470b340bSDmitry Karpeev       ierr = PetscSNPrintf(schurmatprefix, sizeof(schurmatprefix), "%sfieldsplit_%s_", ((PetscObject)pc)->prefix ? ((PetscObject)pc)->prefix : "", ilink->splitname);CHKERRQ(ierr);
763470b340bSDmitry Karpeev       ierr = MatSetOptionsPrefix(jac->schur,schurmatprefix);CHKERRQ(ierr);
764686bed4dSStefano Zampini       ierr = MatSchurComplementGetKSP(jac->schur,&kspt);CHKERRQ(ierr);
765686bed4dSStefano Zampini       ierr = KSPSetOptionsPrefix(kspt,schurmatprefix);CHKERRQ(ierr);
766686bed4dSStefano Zampini 
767686bed4dSStefano Zampini       /* Note: this is not true in general */
768895c21f2SBarry Smith       ierr = MatGetNullSpace(jac->mat[1], &sp);CHKERRQ(ierr);
76920252d06SBarry Smith       if (sp) {
77020252d06SBarry Smith         ierr = MatSetNullSpace(jac->schur, sp);CHKERRQ(ierr);
77120252d06SBarry Smith       }
77220252d06SBarry Smith 
77320252d06SBarry Smith       ierr = PetscSNPrintf(schurtestoption, sizeof(schurtestoption), "-fieldsplit_%s_inner_", ilink->splitname);CHKERRQ(ierr);
774c5929fdfSBarry Smith       ierr = PetscOptionsFindPairPrefix_Private(((PetscObject)pc)->options,((PetscObject)pc)->prefix, schurtestoption, NULL, &flg);CHKERRQ(ierr);
775514bf10dSMatthew G Knepley       if (flg) {
776514bf10dSMatthew G Knepley         DM  dmInner;
77721635b76SJed Brown         KSP kspInner;
778686bed4dSStefano Zampini         PC  pcInner;
77921635b76SJed Brown 
78021635b76SJed Brown         ierr = MatSchurComplementGetKSP(jac->schur, &kspInner);CHKERRQ(ierr);
7812cc093acSMatthew G. Knepley         ierr = KSPReset(kspInner);CHKERRQ(ierr);
7822cc093acSMatthew G. Knepley         ierr = KSPSetOperators(kspInner,jac->mat[0],jac->pmat[0]);CHKERRQ(ierr);
78321635b76SJed Brown         ierr = PetscSNPrintf(schurprefix, sizeof(schurprefix), "%sfieldsplit_%s_inner_", ((PetscObject)pc)->prefix ? ((PetscObject)pc)->prefix : "", ilink->splitname);CHKERRQ(ierr);
78421635b76SJed Brown         /* Indent this deeper to emphasize the "inner" nature of this solver. */
78521635b76SJed Brown         ierr = PetscObjectIncrementTabLevel((PetscObject)kspInner, (PetscObject) pc, 2);CHKERRQ(ierr);
7862cc093acSMatthew G. Knepley         ierr = PetscObjectIncrementTabLevel((PetscObject)kspInner->pc, (PetscObject) pc, 2);CHKERRQ(ierr);
78721635b76SJed Brown         ierr = KSPSetOptionsPrefix(kspInner, schurprefix);CHKERRQ(ierr);
788514bf10dSMatthew G Knepley 
789514bf10dSMatthew G Knepley         /* Set DM for new solver */
790bafc1b83SMatthew G Knepley         ierr = KSPGetDM(jac->head->ksp, &dmInner);CHKERRQ(ierr);
79121635b76SJed Brown         ierr = KSPSetDM(kspInner, dmInner);CHKERRQ(ierr);
79221635b76SJed Brown         ierr = KSPSetDMActive(kspInner, PETSC_FALSE);CHKERRQ(ierr);
793686bed4dSStefano Zampini 
794686bed4dSStefano Zampini         /* Defaults to PCKSP as preconditioner */
795686bed4dSStefano Zampini         ierr = KSPGetPC(kspInner, &pcInner);CHKERRQ(ierr);
796686bed4dSStefano Zampini         ierr = PCSetType(pcInner, PCKSP);CHKERRQ(ierr);
797686bed4dSStefano Zampini         ierr = PCKSPSetKSP(pcInner, jac->head->ksp);CHKERRQ(ierr);
798514bf10dSMatthew G Knepley       } else {
79921635b76SJed Brown          /* Use the outer solver for the inner solve, but revert the KSPPREONLY from PCFieldSplitSetFields_FieldSplit or
80021635b76SJed Brown           * PCFieldSplitSetIS_FieldSplit. We don't want KSPPREONLY because it makes the Schur complement inexact,
80121635b76SJed Brown           * preventing Schur complement reduction to be an accurate solve. Usually when an iterative solver is used for
80221635b76SJed Brown           * S = D - C A_inner^{-1} B, we expect S to be defined using an accurate definition of A_inner^{-1}, so we make
80321635b76SJed Brown           * GMRES the default. Note that it is also common to use PREONLY for S, in which case S may not be used
80421635b76SJed Brown           * directly, and the user is responsible for setting an inexact method for fieldsplit's A^{-1}. */
80521635b76SJed Brown         ierr = KSPSetType(jac->head->ksp,KSPGMRES);CHKERRQ(ierr);
806514bf10dSMatthew G Knepley         ierr = MatSchurComplementSetKSP(jac->schur,jac->head->ksp);CHKERRQ(ierr);
807bafc1b83SMatthew G Knepley       }
80823ee1639SBarry Smith       ierr = KSPSetOperators(jac->head->ksp,jac->mat[0],jac->pmat[0]);CHKERRQ(ierr);
8095a9f2f41SSatish Balay       ierr = KSPSetFromOptions(jac->head->ksp);CHKERRQ(ierr);
81097bbdb24SBarry Smith       ierr = MatSetFromOptions(jac->schur);CHKERRQ(ierr);
81197bbdb24SBarry Smith 
812686bed4dSStefano Zampini       ierr = PetscObjectTypeCompare((PetscObject)jac->schur, MATSCHURCOMPLEMENT, &flg);CHKERRQ(ierr);
813686bed4dSStefano Zampini       if (flg) { /* Need to do this otherwise PCSetUp_KSP will overwrite the amat of jac->head->ksp */
814686bed4dSStefano Zampini         KSP kspInner;
815686bed4dSStefano Zampini         PC  pcInner;
816686bed4dSStefano Zampini 
817686bed4dSStefano Zampini         ierr = MatSchurComplementGetKSP(jac->schur, &kspInner);CHKERRQ(ierr);
818686bed4dSStefano Zampini         ierr = KSPGetPC(kspInner, &pcInner);CHKERRQ(ierr);
819686bed4dSStefano Zampini         ierr = PetscObjectTypeCompare((PetscObject)pcInner, PCKSP, &flg);CHKERRQ(ierr);
820686bed4dSStefano Zampini         if (flg) {
821686bed4dSStefano Zampini           KSP ksp;
822686bed4dSStefano Zampini 
823686bed4dSStefano Zampini           ierr = PCKSPGetKSP(pcInner, &ksp);CHKERRQ(ierr);
824686bed4dSStefano Zampini           if (ksp == jac->head->ksp) {
825686bed4dSStefano Zampini             ierr = PCSetUseAmat(pcInner, PETSC_TRUE);CHKERRQ(ierr);
826686bed4dSStefano Zampini           }
827686bed4dSStefano Zampini         }
828686bed4dSStefano Zampini       }
829443836d0SMatthew G Knepley       ierr = PetscSNPrintf(schurtestoption, sizeof(schurtestoption), "-fieldsplit_%s_upper_", ilink->splitname);CHKERRQ(ierr);
830c5929fdfSBarry Smith       ierr = PetscOptionsFindPairPrefix_Private(((PetscObject)pc)->options,((PetscObject)pc)->prefix, schurtestoption, NULL, &flg);CHKERRQ(ierr);
831443836d0SMatthew G Knepley       if (flg) {
832443836d0SMatthew G Knepley         DM dmInner;
833443836d0SMatthew G Knepley 
834443836d0SMatthew G Knepley         ierr = PetscSNPrintf(schurprefix, sizeof(schurprefix), "%sfieldsplit_%s_upper_", ((PetscObject)pc)->prefix ? ((PetscObject)pc)->prefix : "", ilink->splitname);CHKERRQ(ierr);
83582f516ccSBarry Smith         ierr = KSPCreate(PetscObjectComm((PetscObject)pc), &jac->kspupper);CHKERRQ(ierr);
836422a814eSBarry Smith         ierr = KSPSetErrorIfNotConverged(jac->kspupper,pc->erroriffailure);CHKERRQ(ierr);
837443836d0SMatthew G Knepley         ierr = KSPSetOptionsPrefix(jac->kspupper, schurprefix);CHKERRQ(ierr);
8382cc093acSMatthew G. Knepley         ierr = PetscObjectIncrementTabLevel((PetscObject)jac->kspupper, (PetscObject) pc, 1);CHKERRQ(ierr);
8392cc093acSMatthew G. Knepley         ierr = PetscObjectIncrementTabLevel((PetscObject)jac->kspupper->pc, (PetscObject) pc, 1);CHKERRQ(ierr);
840443836d0SMatthew G Knepley         ierr = KSPGetDM(jac->head->ksp, &dmInner);CHKERRQ(ierr);
841443836d0SMatthew G Knepley         ierr = KSPSetDM(jac->kspupper, dmInner);CHKERRQ(ierr);
842443836d0SMatthew G Knepley         ierr = KSPSetDMActive(jac->kspupper, PETSC_FALSE);CHKERRQ(ierr);
843443836d0SMatthew G Knepley         ierr = KSPSetFromOptions(jac->kspupper);CHKERRQ(ierr);
84423ee1639SBarry Smith         ierr = KSPSetOperators(jac->kspupper,jac->mat[0],jac->pmat[0]);CHKERRQ(ierr);
845443836d0SMatthew G Knepley         ierr = VecDuplicate(jac->head->x, &jac->head->z);CHKERRQ(ierr);
846443836d0SMatthew G Knepley       } else {
847443836d0SMatthew G Knepley         jac->kspupper = jac->head->ksp;
848443836d0SMatthew G Knepley         ierr          = PetscObjectReference((PetscObject) jac->head->ksp);CHKERRQ(ierr);
849443836d0SMatthew G Knepley       }
850443836d0SMatthew G Knepley 
851a7476a74SDmitry Karpeev       if (jac->schurpre == PC_FIELDSPLIT_SCHUR_PRE_SELFP) {
852a7476a74SDmitry Karpeev 	ierr = MatSchurComplementGetPmat(jac->schur,MAT_INITIAL_MATRIX,&jac->schurp);CHKERRQ(ierr);
853a7476a74SDmitry Karpeev       }
854ce94432eSBarry Smith       ierr = KSPCreate(PetscObjectComm((PetscObject)pc),&jac->kspschur);CHKERRQ(ierr);
855422a814eSBarry Smith       ierr = KSPSetErrorIfNotConverged(jac->kspschur,pc->erroriffailure);CHKERRQ(ierr);
85697bbdb24SBarry Smith       ierr = PetscLogObjectParent((PetscObject)pc,(PetscObject)jac->kspschur);CHKERRQ(ierr);
85720252d06SBarry Smith       ierr = PetscObjectIncrementTabLevel((PetscObject)jac->kspschur,(PetscObject)pc,1);CHKERRQ(ierr);
85897bbdb24SBarry Smith       if (jac->schurpre == PC_FIELDSPLIT_SCHUR_PRE_SELF) {
8597233a360SDmitry Karpeev         PC pcschur;
8607233a360SDmitry Karpeev         ierr = KSPGetPC(jac->kspschur,&pcschur);CHKERRQ(ierr);
8617233a360SDmitry Karpeev         ierr = PCSetType(pcschur,PCNONE);CHKERRQ(ierr);
86297bbdb24SBarry Smith         /* Note: This is bad if there exist preconditioners for MATSCHURCOMPLEMENT */
863e74569cdSMatthew G. Knepley       } else if (jac->schurpre == PC_FIELDSPLIT_SCHUR_PRE_FULL) {
864e74569cdSMatthew G. Knepley         ierr = MatSchurComplementComputeExplicitOperator(jac->schur, &jac->schur_user);CHKERRQ(ierr);
86597bbdb24SBarry Smith       }
86623ee1639SBarry Smith       ierr = KSPSetOperators(jac->kspschur,jac->schur,FieldSplitSchurPre(jac));CHKERRQ(ierr);
86797bbdb24SBarry Smith       ierr = KSPGetOptionsPrefix(jac->head->next->ksp, &Dprefix);CHKERRQ(ierr);
86897bbdb24SBarry Smith       ierr = KSPSetOptionsPrefix(jac->kspschur,         Dprefix);CHKERRQ(ierr);
869c096484dSStefano Zampini       /* propagate DM */
870b20b4189SMatthew G. Knepley       {
871b20b4189SMatthew G. Knepley         DM sdm;
872b20b4189SMatthew G. Knepley         ierr = KSPGetDM(jac->head->next->ksp, &sdm);CHKERRQ(ierr);
873b20b4189SMatthew G. Knepley         if (sdm) {
874b20b4189SMatthew G. Knepley           ierr = KSPSetDM(jac->kspschur, sdm);CHKERRQ(ierr);
875b20b4189SMatthew G. Knepley           ierr = KSPSetDMActive(jac->kspschur, PETSC_FALSE);CHKERRQ(ierr);
876b20b4189SMatthew G. Knepley         }
877b20b4189SMatthew G. Knepley       }
87897bbdb24SBarry Smith       /* really want setfromoptions called in PCSetFromOptions_FieldSplit(), but it is not ready yet */
87997bbdb24SBarry Smith       /* need to call this every time, since the jac->kspschur is freshly created, otherwise its options never get set */
88097bbdb24SBarry Smith       ierr = KSPSetFromOptions(jac->kspschur);CHKERRQ(ierr);
88197bbdb24SBarry Smith     }
882686bed4dSStefano Zampini     ierr = MatAssemblyBegin(jac->schur,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
883686bed4dSStefano Zampini     ierr = MatAssemblyEnd(jac->schur,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
88497bbdb24SBarry Smith 
8855a9f2f41SSatish Balay     /* HACK: special support to forward L and Lp matrices that might be used by PCLSC */
8868caf3d72SBarry Smith     ierr = PetscSNPrintf(lscname,sizeof(lscname),"%s_LSC_L",ilink->splitname);CHKERRQ(ierr);
887519d70e2SJed Brown     ierr = PetscObjectQuery((PetscObject)pc->mat,lscname,(PetscObject*)&LSC_L);CHKERRQ(ierr);
8883b224e63SBarry Smith     if (!LSC_L) {ierr = PetscObjectQuery((PetscObject)pc->pmat,lscname,(PetscObject*)&LSC_L);CHKERRQ(ierr);}
889c1570756SJed Brown     if (LSC_L) {ierr = PetscObjectCompose((PetscObject)jac->schur,"LSC_L",(PetscObject)LSC_L);CHKERRQ(ierr);}
8908caf3d72SBarry Smith     ierr = PetscSNPrintf(lscname,sizeof(lscname),"%s_LSC_Lp",ilink->splitname);CHKERRQ(ierr);
89197bbdb24SBarry Smith     ierr = PetscObjectQuery((PetscObject)pc->pmat,lscname,(PetscObject*)&LSC_L);CHKERRQ(ierr);
8925a9f2f41SSatish Balay     if (!LSC_L) {ierr = PetscObjectQuery((PetscObject)pc->mat,lscname,(PetscObject*)&LSC_L);CHKERRQ(ierr);}
8930971522cSBarry Smith     if (LSC_L) {ierr = PetscObjectCompose((PetscObject)jac->schur,"LSC_Lp",(PetscObject)LSC_L);CHKERRQ(ierr);}
89497bbdb24SBarry Smith   } else {
89568bd789dSDmitry Karpeev     /* set up the individual splits' PCs */
8960971522cSBarry Smith     i     = 0;
8970971522cSBarry Smith     ilink = jac->head;
8980971522cSBarry Smith     while (ilink) {
89923ee1639SBarry Smith       ierr = KSPSetOperators(ilink->ksp,jac->mat[i],jac->pmat[i]);CHKERRQ(ierr);
9000971522cSBarry Smith       /* really want setfromoptions called in PCSetFromOptions_FieldSplit(), but it is not ready yet */
9010971522cSBarry Smith       if (!jac->suboptionsset) {ierr = KSPSetFromOptions(ilink->ksp);CHKERRQ(ierr);}
9020971522cSBarry Smith       i++;
9030971522cSBarry Smith       ilink = ilink->next;
9040971522cSBarry Smith     }
9053b224e63SBarry Smith   }
9063b224e63SBarry Smith 
907c1570756SJed Brown   jac->suboptionsset = PETSC_TRUE;
9080971522cSBarry Smith   PetscFunctionReturn(0);
9090971522cSBarry Smith }
9100971522cSBarry Smith 
9115a9f2f41SSatish Balay #define FieldSplitSplitSolveAdd(ilink,xx,yy) \
912ca9f406cSSatish Balay   (VecScatterBegin(ilink->sctx,xx,ilink->x,INSERT_VALUES,SCATTER_FORWARD) || \
913ca9f406cSSatish Balay    VecScatterEnd(ilink->sctx,xx,ilink->x,INSERT_VALUES,SCATTER_FORWARD) || \
9149df09d43SBarry Smith    PetscLogEventBegin(ilink->event,ilink->ksp,ilink->x,ilink->y,NULL) ||\
9155a9f2f41SSatish Balay    KSPSolve(ilink->ksp,ilink->x,ilink->y) ||                               \
9169df09d43SBarry Smith    PetscLogEventEnd(ilink->event,ilink->ksp,ilink->x,ilink->y,NULL) ||\
917ca9f406cSSatish Balay    VecScatterBegin(ilink->sctx,ilink->y,yy,ADD_VALUES,SCATTER_REVERSE) ||  \
918ca9f406cSSatish Balay    VecScatterEnd(ilink->sctx,ilink->y,yy,ADD_VALUES,SCATTER_REVERSE))
91979416396SBarry Smith 
9203b224e63SBarry Smith static PetscErrorCode PCApply_FieldSplit_Schur(PC pc,Vec x,Vec y)
9213b224e63SBarry Smith {
9223b224e63SBarry Smith   PC_FieldSplit     *jac = (PC_FieldSplit*)pc->data;
9233b224e63SBarry Smith   PetscErrorCode    ierr;
9243b224e63SBarry Smith   PC_FieldSplitLink ilinkA = jac->head, ilinkD = ilinkA->next;
925443836d0SMatthew G Knepley   KSP               kspA   = ilinkA->ksp, kspLower = kspA, kspUpper = jac->kspupper;
9263b224e63SBarry Smith 
9273b224e63SBarry Smith   PetscFunctionBegin;
928c5d2311dSJed Brown   switch (jac->schurfactorization) {
929c9c6ffaaSJed Brown   case PC_FIELDSPLIT_SCHUR_FACT_DIAG:
930a04f6461SBarry Smith     /* [A00 0; 0 -S], positive definite, suitable for MINRES */
931c5d2311dSJed Brown     ierr = VecScatterBegin(ilinkA->sctx,x,ilinkA->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
932c5d2311dSJed Brown     ierr = VecScatterBegin(ilinkD->sctx,x,ilinkD->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
933c5d2311dSJed Brown     ierr = VecScatterEnd(ilinkA->sctx,x,ilinkA->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
9349df09d43SBarry Smith     ierr = PetscLogEventBegin(ilinkA->event,kspA,ilinkA->x,ilinkA->y,NULL);CHKERRQ(ierr);
935443836d0SMatthew G Knepley     ierr = KSPSolve(kspA,ilinkA->x,ilinkA->y);CHKERRQ(ierr);
9369df09d43SBarry Smith     ierr = PetscLogEventEnd(ilinkA->event,kspA,ilinkA->x,ilinkA->y,NULL);CHKERRQ(ierr);
937c5d2311dSJed Brown     ierr = VecScatterBegin(ilinkA->sctx,ilinkA->y,y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
938c5d2311dSJed Brown     ierr = VecScatterEnd(ilinkD->sctx,x,ilinkD->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
9399df09d43SBarry Smith     ierr = PetscLogEventBegin(KSP_Solve_FS_S,jac->kspschur,ilinkD->x,ilinkD->y,NULL);CHKERRQ(ierr);
940c5d2311dSJed Brown     ierr = KSPSolve(jac->kspschur,ilinkD->x,ilinkD->y);CHKERRQ(ierr);
9419df09d43SBarry Smith     ierr = PetscLogEventEnd(KSP_Solve_FS_S,jac->kspschur,ilinkD->x,ilinkD->y,NULL);CHKERRQ(ierr);
942c096484dSStefano Zampini     ierr = VecScale(ilinkD->y,jac->schurscale);CHKERRQ(ierr);
943c5d2311dSJed Brown     ierr = VecScatterBegin(ilinkD->sctx,ilinkD->y,y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
944c5d2311dSJed Brown     ierr = VecScatterEnd(ilinkA->sctx,ilinkA->y,y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
945c5d2311dSJed Brown     ierr = VecScatterEnd(ilinkD->sctx,ilinkD->y,y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
946c5d2311dSJed Brown     break;
947c9c6ffaaSJed Brown   case PC_FIELDSPLIT_SCHUR_FACT_LOWER:
948a04f6461SBarry Smith     /* [A00 0; A10 S], suitable for left preconditioning */
949c5d2311dSJed Brown     ierr = VecScatterBegin(ilinkA->sctx,x,ilinkA->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
950c5d2311dSJed Brown     ierr = VecScatterEnd(ilinkA->sctx,x,ilinkA->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
9519df09d43SBarry Smith     ierr = PetscLogEventBegin(ilinkA->event,kspA,ilinkA->x,ilinkA->y,NULL);CHKERRQ(ierr);
952443836d0SMatthew G Knepley     ierr = KSPSolve(kspA,ilinkA->x,ilinkA->y);CHKERRQ(ierr);
9539df09d43SBarry Smith     ierr = PetscLogEventEnd(ilinkA->event,kspA,ilinkA->x,ilinkA->y,NULL);CHKERRQ(ierr);
954c5d2311dSJed Brown     ierr = MatMult(jac->C,ilinkA->y,ilinkD->x);CHKERRQ(ierr);
955c5d2311dSJed Brown     ierr = VecScale(ilinkD->x,-1.);CHKERRQ(ierr);
956c5d2311dSJed Brown     ierr = VecScatterBegin(ilinkD->sctx,x,ilinkD->x,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
957c5d2311dSJed Brown     ierr = VecScatterBegin(ilinkA->sctx,ilinkA->y,y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
958c5d2311dSJed Brown     ierr = VecScatterEnd(ilinkD->sctx,x,ilinkD->x,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
9599df09d43SBarry Smith     ierr = PetscLogEventBegin(KSP_Solve_FS_S,jac->kspschur,ilinkD->x,ilinkD->y,NULL);CHKERRQ(ierr);
960c5d2311dSJed Brown     ierr = KSPSolve(jac->kspschur,ilinkD->x,ilinkD->y);CHKERRQ(ierr);
9619df09d43SBarry Smith     ierr = PetscLogEventEnd(KSP_Solve_FS_S,jac->kspschur,ilinkD->x,ilinkD->y,NULL);CHKERRQ(ierr);
962c5d2311dSJed Brown     ierr = VecScatterBegin(ilinkD->sctx,ilinkD->y,y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
963c5d2311dSJed Brown     ierr = VecScatterEnd(ilinkA->sctx,ilinkA->y,y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
964c5d2311dSJed Brown     ierr = VecScatterEnd(ilinkD->sctx,ilinkD->y,y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
965c5d2311dSJed Brown     break;
966c9c6ffaaSJed Brown   case PC_FIELDSPLIT_SCHUR_FACT_UPPER:
967a04f6461SBarry Smith     /* [A00 A01; 0 S], suitable for right preconditioning */
968c5d2311dSJed Brown     ierr = VecScatterBegin(ilinkD->sctx,x,ilinkD->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
969c5d2311dSJed Brown     ierr = VecScatterEnd(ilinkD->sctx,x,ilinkD->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
9709df09d43SBarry Smith     ierr = PetscLogEventBegin(KSP_Solve_FS_S,jac->kspschur,ilinkD->x,ilinkD->y,NULL);CHKERRQ(ierr);
971c5d2311dSJed Brown     ierr = KSPSolve(jac->kspschur,ilinkD->x,ilinkD->y);CHKERRQ(ierr);
9729df09d43SBarry Smith     ierr = PetscLogEventEnd(KSP_Solve_FS_S,jac->kspschur,ilinkD->x,ilinkD->y,NULL);CHKERRQ(ierr);    ierr = MatMult(jac->B,ilinkD->y,ilinkA->x);CHKERRQ(ierr);
973c5d2311dSJed Brown     ierr = VecScale(ilinkA->x,-1.);CHKERRQ(ierr);
974c5d2311dSJed Brown     ierr = VecScatterBegin(ilinkA->sctx,x,ilinkA->x,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
975c5d2311dSJed Brown     ierr = VecScatterBegin(ilinkD->sctx,ilinkD->y,y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
976c5d2311dSJed Brown     ierr = VecScatterEnd(ilinkA->sctx,x,ilinkA->x,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
9779df09d43SBarry Smith     ierr = PetscLogEventBegin(ilinkA->event,kspA,ilinkA->x,ilinkA->y,NULL);CHKERRQ(ierr);
978443836d0SMatthew G Knepley     ierr = KSPSolve(kspA,ilinkA->x,ilinkA->y);CHKERRQ(ierr);
9799df09d43SBarry Smith     ierr = PetscLogEventEnd(ilinkA->event,kspA,ilinkA->x,ilinkA->y,NULL);CHKERRQ(ierr);
980c5d2311dSJed Brown     ierr = VecScatterBegin(ilinkA->sctx,ilinkA->y,y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
981c5d2311dSJed Brown     ierr = VecScatterEnd(ilinkD->sctx,ilinkD->y,y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
982c5d2311dSJed Brown     ierr = VecScatterEnd(ilinkA->sctx,ilinkA->y,y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
983c5d2311dSJed Brown     break;
984c9c6ffaaSJed Brown   case PC_FIELDSPLIT_SCHUR_FACT_FULL:
985c238f8cdSStefano Zampini     /* [1 0; A10 A00^{-1} 1] [A00 0; 0 S] [1 A00^{-1}A01; 0 1] */
9863b224e63SBarry Smith     ierr = VecScatterBegin(ilinkA->sctx,x,ilinkA->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
9873b224e63SBarry Smith     ierr = VecScatterEnd(ilinkA->sctx,x,ilinkA->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
9889df09d43SBarry Smith     ierr = PetscLogEventBegin(KSP_Solve_FS_L,kspLower,ilinkA->x,ilinkA->y,NULL);CHKERRQ(ierr);
989443836d0SMatthew G Knepley     ierr = KSPSolve(kspLower,ilinkA->x,ilinkA->y);CHKERRQ(ierr);
9909df09d43SBarry Smith     ierr = PetscLogEventEnd(KSP_Solve_FS_L,kspLower,ilinkA->x,ilinkA->y,NULL);CHKERRQ(ierr);
9913b224e63SBarry Smith     ierr = MatMult(jac->C,ilinkA->y,ilinkD->x);CHKERRQ(ierr);
9923b224e63SBarry Smith     ierr = VecScale(ilinkD->x,-1.0);CHKERRQ(ierr);
9933b224e63SBarry Smith     ierr = VecScatterBegin(ilinkD->sctx,x,ilinkD->x,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
9943b224e63SBarry Smith     ierr = VecScatterEnd(ilinkD->sctx,x,ilinkD->x,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
9953b224e63SBarry Smith 
9969df09d43SBarry Smith     ierr = PetscLogEventBegin(KSP_Solve_FS_S,jac->kspschur,ilinkD->x,ilinkD->y,NULL);CHKERRQ(ierr);
9973b224e63SBarry Smith     ierr = KSPSolve(jac->kspschur,ilinkD->x,ilinkD->y);CHKERRQ(ierr);
9989df09d43SBarry Smith     ierr = PetscLogEventEnd(KSP_Solve_FS_S,jac->kspschur,ilinkD->x,ilinkD->y,NULL);CHKERRQ(ierr);
9993b224e63SBarry Smith     ierr = VecScatterBegin(ilinkD->sctx,ilinkD->y,y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
10003b224e63SBarry Smith 
1001443836d0SMatthew G Knepley     if (kspUpper == kspA) {
10023b224e63SBarry Smith       ierr = MatMult(jac->B,ilinkD->y,ilinkA->y);CHKERRQ(ierr);
10033b224e63SBarry Smith       ierr = VecAXPY(ilinkA->x,-1.0,ilinkA->y);CHKERRQ(ierr);
10049df09d43SBarry Smith       ierr = PetscLogEventBegin(ilinkA->event,kspA,ilinkA->x,ilinkA->y,NULL);CHKERRQ(ierr);
1005443836d0SMatthew G Knepley       ierr = KSPSolve(kspA,ilinkA->x,ilinkA->y);CHKERRQ(ierr);
10069df09d43SBarry Smith       ierr = PetscLogEventEnd(ilinkA->event,kspA,ilinkA->x,ilinkA->y,NULL);CHKERRQ(ierr);
1007443836d0SMatthew G Knepley     } else {
10089df09d43SBarry Smith       ierr = PetscLogEventBegin(ilinkA->event,kspA,ilinkA->x,ilinkA->y,NULL);CHKERRQ(ierr);
1009443836d0SMatthew G Knepley       ierr = KSPSolve(kspA,ilinkA->x,ilinkA->y);CHKERRQ(ierr);
10109df09d43SBarry Smith       ierr = PetscLogEventEnd(ilinkA->event,kspA,ilinkA->x,ilinkA->y,NULL);CHKERRQ(ierr);
1011443836d0SMatthew G Knepley       ierr = MatMult(jac->B,ilinkD->y,ilinkA->x);CHKERRQ(ierr);
10129df09d43SBarry Smith       ierr = PetscLogEventBegin(KSP_Solve_FS_U,kspUpper,ilinkA->x,ilinkA->z,NULL);CHKERRQ(ierr);
1013443836d0SMatthew G Knepley       ierr = KSPSolve(kspUpper,ilinkA->x,ilinkA->z);CHKERRQ(ierr);
10149df09d43SBarry Smith       ierr = PetscLogEventEnd(KSP_Solve_FS_U,kspUpper,ilinkA->x,ilinkA->z,NULL);CHKERRQ(ierr);
1015443836d0SMatthew G Knepley       ierr = VecAXPY(ilinkA->y,-1.0,ilinkA->z);CHKERRQ(ierr);
1016443836d0SMatthew G Knepley     }
1017c238f8cdSStefano Zampini     ierr = VecScatterEnd(ilinkD->sctx,ilinkD->y,y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
10183b224e63SBarry Smith     ierr = VecScatterBegin(ilinkA->sctx,ilinkA->y,y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
10193b224e63SBarry Smith     ierr = VecScatterEnd(ilinkA->sctx,ilinkA->y,y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1020c5d2311dSJed Brown   }
10213b224e63SBarry Smith   PetscFunctionReturn(0);
10223b224e63SBarry Smith }
10233b224e63SBarry Smith 
10240971522cSBarry Smith static PetscErrorCode PCApply_FieldSplit(PC pc,Vec x,Vec y)
10250971522cSBarry Smith {
10260971522cSBarry Smith   PC_FieldSplit      *jac = (PC_FieldSplit*)pc->data;
10270971522cSBarry Smith   PetscErrorCode     ierr;
10285a9f2f41SSatish Balay   PC_FieldSplitLink  ilink = jac->head;
1029939b8a20SBarry Smith   PetscInt           cnt,bs;
1030568ed31eSHong Zhang   KSPConvergedReason reason;
10310971522cSBarry Smith 
10320971522cSBarry Smith   PetscFunctionBegin;
103379416396SBarry Smith   if (jac->type == PC_COMPOSITE_ADDITIVE) {
10341b9fc7fcSBarry Smith     if (jac->defaultsplit) {
1035939b8a20SBarry Smith       ierr = VecGetBlockSize(x,&bs);CHKERRQ(ierr);
1036ce94432eSBarry Smith       if (jac->bs > 0 && bs != jac->bs) SETERRQ2(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONGSTATE,"Blocksize of x vector %D does not match fieldsplit blocksize %D",bs,jac->bs);
1037939b8a20SBarry Smith       ierr = VecGetBlockSize(y,&bs);CHKERRQ(ierr);
1038ce94432eSBarry Smith       if (jac->bs > 0 && bs != jac->bs) SETERRQ2(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONGSTATE,"Blocksize of y vector %D does not match fieldsplit blocksize %D",bs,jac->bs);
10390971522cSBarry Smith       ierr = VecStrideGatherAll(x,jac->x,INSERT_VALUES);CHKERRQ(ierr);
10405a9f2f41SSatish Balay       while (ilink) {
10419df09d43SBarry Smith         ierr = PetscLogEventBegin(ilink->event,ilink->ksp,ilink->x,ilink->y,NULL);CHKERRQ(ierr);
10425a9f2f41SSatish Balay         ierr = KSPSolve(ilink->ksp,ilink->x,ilink->y);CHKERRQ(ierr);
10439df09d43SBarry Smith         ierr = PetscLogEventEnd(ilink->event,ilink->ksp,ilink->x,ilink->y,NULL);CHKERRQ(ierr);
1044568ed31eSHong Zhang         ierr = KSPGetConvergedReason(ilink->ksp,&reason);CHKERRQ(ierr);
1045568ed31eSHong Zhang         if (reason == KSP_DIVERGED_PCSETUP_FAILED) {
1046568ed31eSHong Zhang           pc->failedreason = PC_SUBPC_ERROR;
1047568ed31eSHong Zhang         }
10485a9f2f41SSatish Balay         ilink = ilink->next;
10490971522cSBarry Smith       }
10500971522cSBarry Smith       ierr = VecStrideScatterAll(jac->y,y,INSERT_VALUES);CHKERRQ(ierr);
10511b9fc7fcSBarry Smith     } else {
1052efb30889SBarry Smith       ierr = VecSet(y,0.0);CHKERRQ(ierr);
10535a9f2f41SSatish Balay       while (ilink) {
10545a9f2f41SSatish Balay         ierr = FieldSplitSplitSolveAdd(ilink,x,y);CHKERRQ(ierr);
1055568ed31eSHong Zhang         ierr = KSPGetConvergedReason(ilink->ksp,&reason);CHKERRQ(ierr);
1056568ed31eSHong Zhang         if (reason == KSP_DIVERGED_PCSETUP_FAILED) {
1057568ed31eSHong Zhang           pc->failedreason = PC_SUBPC_ERROR;
1058568ed31eSHong Zhang         }
10595a9f2f41SSatish Balay         ilink = ilink->next;
10601b9fc7fcSBarry Smith       }
10611b9fc7fcSBarry Smith     }
1062e52d2c62SBarry Smith   } else if (jac->type == PC_COMPOSITE_MULTIPLICATIVE && jac->nsplits == 2) {
1063e52d2c62SBarry Smith     ierr = VecSet(y,0.0);CHKERRQ(ierr);
1064e52d2c62SBarry Smith     /* solve on first block for first block variables */
1065e52d2c62SBarry Smith     ierr = VecScatterBegin(ilink->sctx,x,ilink->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1066e52d2c62SBarry Smith     ierr = VecScatterEnd(ilink->sctx,x,ilink->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
10679df09d43SBarry Smith     ierr = PetscLogEventBegin(ilink->event,ilink->ksp,ilink->x,ilink->y,NULL);CHKERRQ(ierr);
1068e52d2c62SBarry Smith     ierr = KSPSolve(ilink->ksp,ilink->x,ilink->y);CHKERRQ(ierr);
10699df09d43SBarry Smith     ierr = PetscLogEventEnd(ilink->event,ilink->ksp,ilink->x,ilink->y,NULL);CHKERRQ(ierr);
1070568ed31eSHong Zhang     ierr = KSPGetConvergedReason(ilink->ksp,&reason);CHKERRQ(ierr);
1071568ed31eSHong Zhang     if (reason == KSP_DIVERGED_PCSETUP_FAILED) {
1072568ed31eSHong Zhang       pc->failedreason = PC_SUBPC_ERROR;
1073568ed31eSHong Zhang     }
1074e52d2c62SBarry Smith     ierr = VecScatterBegin(ilink->sctx,ilink->y,y,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1075e52d2c62SBarry Smith     ierr = VecScatterEnd(ilink->sctx,ilink->y,y,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1076e52d2c62SBarry Smith 
1077e52d2c62SBarry Smith     /* compute the residual only onto second block variables using first block variables */
1078e52d2c62SBarry Smith     ierr = MatMult(jac->Afield[1],ilink->y,ilink->next->x);CHKERRQ(ierr);
1079e52d2c62SBarry Smith     ilink = ilink->next;
1080e52d2c62SBarry Smith     ierr = VecScale(ilink->x,-1.0);CHKERRQ(ierr);
1081e52d2c62SBarry Smith     ierr = VecScatterBegin(ilink->sctx,x,ilink->x,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1082e52d2c62SBarry Smith     ierr = VecScatterEnd(ilink->sctx,x,ilink->x,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1083e52d2c62SBarry Smith 
1084e52d2c62SBarry Smith     /* solve on second block variables */
10859df09d43SBarry Smith     ierr = PetscLogEventBegin(ilink->event,ilink->ksp,ilink->x,ilink->y,NULL);CHKERRQ(ierr);
1086e52d2c62SBarry Smith     ierr = KSPSolve(ilink->ksp,ilink->x,ilink->y);CHKERRQ(ierr);
10879df09d43SBarry Smith     ierr = PetscLogEventEnd(ilink->event,ilink->ksp,ilink->x,ilink->y,NULL);CHKERRQ(ierr);
1088568ed31eSHong Zhang     ierr = KSPGetConvergedReason(ilink->ksp,&reason);CHKERRQ(ierr);
1089568ed31eSHong Zhang     if (reason == KSP_DIVERGED_PCSETUP_FAILED) {
1090568ed31eSHong Zhang       pc->failedreason = PC_SUBPC_ERROR;
1091568ed31eSHong Zhang     }
1092e52d2c62SBarry Smith     ierr = VecScatterBegin(ilink->sctx,ilink->y,y,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1093e52d2c62SBarry Smith     ierr = VecScatterEnd(ilink->sctx,ilink->y,y,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
109416913363SBarry Smith   } else if (jac->type == PC_COMPOSITE_MULTIPLICATIVE || jac->type == PC_COMPOSITE_SYMMETRIC_MULTIPLICATIVE) {
109579416396SBarry Smith     if (!jac->w1) {
109679416396SBarry Smith       ierr = VecDuplicate(x,&jac->w1);CHKERRQ(ierr);
109779416396SBarry Smith       ierr = VecDuplicate(x,&jac->w2);CHKERRQ(ierr);
109879416396SBarry Smith     }
1099efb30889SBarry Smith     ierr = VecSet(y,0.0);CHKERRQ(ierr);
11005a9f2f41SSatish Balay     ierr = FieldSplitSplitSolveAdd(ilink,x,y);CHKERRQ(ierr);
1101568ed31eSHong Zhang     ierr = KSPGetConvergedReason(ilink->ksp,&reason);CHKERRQ(ierr);
1102568ed31eSHong Zhang     if (reason == KSP_DIVERGED_PCSETUP_FAILED) {
1103568ed31eSHong Zhang       pc->failedreason = PC_SUBPC_ERROR;
1104568ed31eSHong Zhang     }
11053e197d65SBarry Smith     cnt  = 1;
11065a9f2f41SSatish Balay     while (ilink->next) {
11075a9f2f41SSatish Balay       ilink = ilink->next;
11083e197d65SBarry Smith       /* compute the residual only over the part of the vector needed */
11093e197d65SBarry Smith       ierr = MatMult(jac->Afield[cnt++],y,ilink->x);CHKERRQ(ierr);
11103e197d65SBarry Smith       ierr = VecScale(ilink->x,-1.0);CHKERRQ(ierr);
11113e197d65SBarry Smith       ierr = VecScatterBegin(ilink->sctx,x,ilink->x,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
11123e197d65SBarry Smith       ierr = VecScatterEnd(ilink->sctx,x,ilink->x,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
11139df09d43SBarry Smith       ierr = PetscLogEventBegin(ilink->event,ilink->ksp,ilink->x,ilink->y,NULL);CHKERRQ(ierr);
11143e197d65SBarry Smith       ierr = KSPSolve(ilink->ksp,ilink->x,ilink->y);CHKERRQ(ierr);
11159df09d43SBarry Smith       ierr = PetscLogEventEnd(ilink->event,ilink->ksp,ilink->x,ilink->y,NULL);CHKERRQ(ierr);
11162618eb8fSHong Zhang       ierr = KSPGetConvergedReason(ilink->ksp,&reason);CHKERRQ(ierr);
11172618eb8fSHong Zhang       if (reason == KSP_DIVERGED_PCSETUP_FAILED) {
11182618eb8fSHong Zhang         pc->failedreason = PC_SUBPC_ERROR;
11192618eb8fSHong Zhang       }
11203e197d65SBarry Smith       ierr = VecScatterBegin(ilink->sctx,ilink->y,y,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
11213e197d65SBarry Smith       ierr = VecScatterEnd(ilink->sctx,ilink->y,y,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
11223e197d65SBarry Smith     }
112351f519a2SBarry Smith     if (jac->type == PC_COMPOSITE_SYMMETRIC_MULTIPLICATIVE) {
112411755939SBarry Smith       cnt -= 2;
112551f519a2SBarry Smith       while (ilink->previous) {
112651f519a2SBarry Smith         ilink = ilink->previous;
112711755939SBarry Smith         /* compute the residual only over the part of the vector needed */
112811755939SBarry Smith         ierr = MatMult(jac->Afield[cnt--],y,ilink->x);CHKERRQ(ierr);
112911755939SBarry Smith         ierr = VecScale(ilink->x,-1.0);CHKERRQ(ierr);
113011755939SBarry Smith         ierr = VecScatterBegin(ilink->sctx,x,ilink->x,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
113111755939SBarry Smith         ierr = VecScatterEnd(ilink->sctx,x,ilink->x,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
11329df09d43SBarry Smith         ierr = PetscLogEventBegin(ilink->event,ilink->ksp,ilink->x,ilink->y,NULL);CHKERRQ(ierr);
113311755939SBarry Smith         ierr = KSPSolve(ilink->ksp,ilink->x,ilink->y);CHKERRQ(ierr);
11349df09d43SBarry Smith         ierr = PetscLogEventEnd(ilink->event,ilink->ksp,ilink->x,ilink->y,NULL);CHKERRQ(ierr);
1135568ed31eSHong Zhang         ierr = KSPGetConvergedReason(ilink->ksp,&reason);CHKERRQ(ierr);
1136568ed31eSHong Zhang         if (reason == KSP_DIVERGED_PCSETUP_FAILED) {
1137568ed31eSHong Zhang           pc->failedreason = PC_SUBPC_ERROR;
1138568ed31eSHong Zhang         }
113911755939SBarry Smith         ierr = VecScatterBegin(ilink->sctx,ilink->y,y,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
114011755939SBarry Smith         ierr = VecScatterEnd(ilink->sctx,ilink->y,y,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
114151f519a2SBarry Smith       }
114211755939SBarry Smith     }
1143ce94432eSBarry Smith   } else SETERRQ1(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Unsupported or unknown composition",(int) jac->type);
11440971522cSBarry Smith   PetscFunctionReturn(0);
11450971522cSBarry Smith }
11460971522cSBarry Smith 
1147421e10b8SBarry Smith #define FieldSplitSplitSolveAddTranspose(ilink,xx,yy) \
1148ca9f406cSSatish Balay   (VecScatterBegin(ilink->sctx,xx,ilink->y,INSERT_VALUES,SCATTER_FORWARD) || \
1149ca9f406cSSatish Balay    VecScatterEnd(ilink->sctx,xx,ilink->y,INSERT_VALUES,SCATTER_FORWARD) || \
11509df09d43SBarry Smith    PetscLogEventBegin(ilink->event,ilink->ksp,ilink->y,ilink->x,NULL) || \
1151421e10b8SBarry Smith    KSPSolveTranspose(ilink->ksp,ilink->y,ilink->x) ||                  \
11529df09d43SBarry Smith    PetscLogEventBegin(ilink->event,ilink->ksp,ilink->y,ilink->x,NULL) || \
1153ca9f406cSSatish Balay    VecScatterBegin(ilink->sctx,ilink->x,yy,ADD_VALUES,SCATTER_REVERSE) || \
1154ca9f406cSSatish Balay    VecScatterEnd(ilink->sctx,ilink->x,yy,ADD_VALUES,SCATTER_REVERSE))
1155421e10b8SBarry Smith 
1156421e10b8SBarry Smith static PetscErrorCode PCApplyTranspose_FieldSplit(PC pc,Vec x,Vec y)
1157421e10b8SBarry Smith {
1158421e10b8SBarry Smith   PC_FieldSplit      *jac = (PC_FieldSplit*)pc->data;
1159421e10b8SBarry Smith   PetscErrorCode     ierr;
1160421e10b8SBarry Smith   PC_FieldSplitLink  ilink = jac->head;
1161939b8a20SBarry Smith   PetscInt           bs;
1162291dd214SHong Zhang   KSPConvergedReason reason;
1163421e10b8SBarry Smith 
1164421e10b8SBarry Smith   PetscFunctionBegin;
1165421e10b8SBarry Smith   if (jac->type == PC_COMPOSITE_ADDITIVE) {
1166421e10b8SBarry Smith     if (jac->defaultsplit) {
1167939b8a20SBarry Smith       ierr = VecGetBlockSize(x,&bs);CHKERRQ(ierr);
1168ce94432eSBarry Smith       if (jac->bs > 0 && bs != jac->bs) SETERRQ2(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONGSTATE,"Blocksize of x vector %D does not match fieldsplit blocksize %D",bs,jac->bs);
1169939b8a20SBarry Smith       ierr = VecGetBlockSize(y,&bs);CHKERRQ(ierr);
1170ce94432eSBarry Smith       if (jac->bs > 0 && bs != jac->bs) SETERRQ2(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONGSTATE,"Blocksize of y vector %D does not match fieldsplit blocksize %D",bs,jac->bs);
1171421e10b8SBarry Smith       ierr = VecStrideGatherAll(x,jac->x,INSERT_VALUES);CHKERRQ(ierr);
1172421e10b8SBarry Smith       while (ilink) {
11739df09d43SBarry Smith         ierr = PetscLogEventBegin(ilink->event,ilink->ksp,ilink->x,ilink->y,NULL);CHKERRQ(ierr);
1174421e10b8SBarry Smith         ierr  = KSPSolveTranspose(ilink->ksp,ilink->x,ilink->y);CHKERRQ(ierr);
11759df09d43SBarry Smith         ierr = PetscLogEventEnd(ilink->event,ilink->ksp,ilink->x,ilink->y,NULL);CHKERRQ(ierr);
11762618eb8fSHong Zhang         ierr = KSPGetConvergedReason(ilink->ksp,&reason);CHKERRQ(ierr);
11772618eb8fSHong Zhang         if (reason == KSP_DIVERGED_PCSETUP_FAILED) {
11782618eb8fSHong Zhang           pc->failedreason = PC_SUBPC_ERROR;
11792618eb8fSHong Zhang         }
1180421e10b8SBarry Smith         ilink = ilink->next;
1181421e10b8SBarry Smith       }
1182421e10b8SBarry Smith       ierr = VecStrideScatterAll(jac->y,y,INSERT_VALUES);CHKERRQ(ierr);
1183421e10b8SBarry Smith     } else {
1184421e10b8SBarry Smith       ierr = VecSet(y,0.0);CHKERRQ(ierr);
1185421e10b8SBarry Smith       while (ilink) {
1186421e10b8SBarry Smith         ierr = FieldSplitSplitSolveAddTranspose(ilink,x,y);CHKERRQ(ierr);
11872618eb8fSHong Zhang         ierr = KSPGetConvergedReason(ilink->ksp,&reason);CHKERRQ(ierr);
11882618eb8fSHong Zhang         if (reason == KSP_DIVERGED_PCSETUP_FAILED) {
11892618eb8fSHong Zhang           pc->failedreason = PC_SUBPC_ERROR;
11902618eb8fSHong Zhang         }
1191421e10b8SBarry Smith         ilink = ilink->next;
1192421e10b8SBarry Smith       }
1193421e10b8SBarry Smith     }
1194421e10b8SBarry Smith   } else {
1195421e10b8SBarry Smith     if (!jac->w1) {
1196421e10b8SBarry Smith       ierr = VecDuplicate(x,&jac->w1);CHKERRQ(ierr);
1197421e10b8SBarry Smith       ierr = VecDuplicate(x,&jac->w2);CHKERRQ(ierr);
1198421e10b8SBarry Smith     }
1199421e10b8SBarry Smith     ierr = VecSet(y,0.0);CHKERRQ(ierr);
1200421e10b8SBarry Smith     if (jac->type == PC_COMPOSITE_SYMMETRIC_MULTIPLICATIVE) {
1201421e10b8SBarry Smith       ierr = FieldSplitSplitSolveAddTranspose(ilink,x,y);CHKERRQ(ierr);
12022618eb8fSHong Zhang       ierr = KSPGetConvergedReason(ilink->ksp,&reason);CHKERRQ(ierr);
12032618eb8fSHong Zhang       if (reason == KSP_DIVERGED_PCSETUP_FAILED) {
12042618eb8fSHong Zhang         pc->failedreason = PC_SUBPC_ERROR;
12052618eb8fSHong Zhang       }
1206421e10b8SBarry Smith       while (ilink->next) {
1207421e10b8SBarry Smith         ilink = ilink->next;
12089989ab13SBarry Smith         ierr  = MatMultTranspose(pc->mat,y,jac->w1);CHKERRQ(ierr);
1209421e10b8SBarry Smith         ierr  = VecWAXPY(jac->w2,-1.0,jac->w1,x);CHKERRQ(ierr);
1210421e10b8SBarry Smith         ierr  = FieldSplitSplitSolveAddTranspose(ilink,jac->w2,y);CHKERRQ(ierr);
1211421e10b8SBarry Smith       }
1212421e10b8SBarry Smith       while (ilink->previous) {
1213421e10b8SBarry Smith         ilink = ilink->previous;
12149989ab13SBarry Smith         ierr  = MatMultTranspose(pc->mat,y,jac->w1);CHKERRQ(ierr);
1215421e10b8SBarry Smith         ierr  = VecWAXPY(jac->w2,-1.0,jac->w1,x);CHKERRQ(ierr);
1216421e10b8SBarry Smith         ierr  = FieldSplitSplitSolveAddTranspose(ilink,jac->w2,y);CHKERRQ(ierr);
1217421e10b8SBarry Smith       }
1218421e10b8SBarry Smith     } else {
1219421e10b8SBarry Smith       while (ilink->next) {   /* get to last entry in linked list */
1220421e10b8SBarry Smith         ilink = ilink->next;
1221421e10b8SBarry Smith       }
1222421e10b8SBarry Smith       ierr = FieldSplitSplitSolveAddTranspose(ilink,x,y);CHKERRQ(ierr);
12232618eb8fSHong Zhang       ierr = KSPGetConvergedReason(ilink->ksp,&reason);CHKERRQ(ierr);
12242618eb8fSHong Zhang       if (reason == KSP_DIVERGED_PCSETUP_FAILED) {
12252618eb8fSHong Zhang         pc->failedreason = PC_SUBPC_ERROR;
12262618eb8fSHong Zhang       }
1227421e10b8SBarry Smith       while (ilink->previous) {
1228421e10b8SBarry Smith         ilink = ilink->previous;
12299989ab13SBarry Smith         ierr  = MatMultTranspose(pc->mat,y,jac->w1);CHKERRQ(ierr);
1230421e10b8SBarry Smith         ierr  = VecWAXPY(jac->w2,-1.0,jac->w1,x);CHKERRQ(ierr);
1231421e10b8SBarry Smith         ierr  = FieldSplitSplitSolveAddTranspose(ilink,jac->w2,y);CHKERRQ(ierr);
1232421e10b8SBarry Smith       }
1233421e10b8SBarry Smith     }
1234421e10b8SBarry Smith   }
1235421e10b8SBarry Smith   PetscFunctionReturn(0);
1236421e10b8SBarry Smith }
1237421e10b8SBarry Smith 
1238574deadeSBarry Smith static PetscErrorCode PCReset_FieldSplit(PC pc)
12390971522cSBarry Smith {
12400971522cSBarry Smith   PC_FieldSplit     *jac = (PC_FieldSplit*)pc->data;
12410971522cSBarry Smith   PetscErrorCode    ierr;
12425a9f2f41SSatish Balay   PC_FieldSplitLink ilink = jac->head,next;
12430971522cSBarry Smith 
12440971522cSBarry Smith   PetscFunctionBegin;
12455a9f2f41SSatish Balay   while (ilink) {
1246f5f0d762SBarry Smith     ierr  = KSPDestroy(&ilink->ksp);CHKERRQ(ierr);
1247fcfd50ebSBarry Smith     ierr  = VecDestroy(&ilink->x);CHKERRQ(ierr);
1248fcfd50ebSBarry Smith     ierr  = VecDestroy(&ilink->y);CHKERRQ(ierr);
1249443836d0SMatthew G Knepley     ierr  = VecDestroy(&ilink->z);CHKERRQ(ierr);
1250fcfd50ebSBarry Smith     ierr  = VecScatterDestroy(&ilink->sctx);CHKERRQ(ierr);
1251fcfd50ebSBarry Smith     ierr  = ISDestroy(&ilink->is);CHKERRQ(ierr);
1252b5787286SJed Brown     ierr  = ISDestroy(&ilink->is_col);CHKERRQ(ierr);
1253f5f0d762SBarry Smith     ierr  = PetscFree(ilink->splitname);CHKERRQ(ierr);
1254f5f0d762SBarry Smith     ierr  = PetscFree(ilink->fields);CHKERRQ(ierr);
1255f5f0d762SBarry Smith     ierr  = PetscFree(ilink->fields_col);CHKERRQ(ierr);
12565a9f2f41SSatish Balay     next  = ilink->next;
1257f5f0d762SBarry Smith     ierr  = PetscFree(ilink);CHKERRQ(ierr);
12585a9f2f41SSatish Balay     ilink = next;
12590971522cSBarry Smith   }
1260f5f0d762SBarry Smith   jac->head = NULL;
126105b42c5fSBarry Smith   ierr = PetscFree2(jac->x,jac->y);CHKERRQ(ierr);
1262574deadeSBarry Smith   if (jac->mat && jac->mat != jac->pmat) {
1263574deadeSBarry Smith     ierr = MatDestroyMatrices(jac->nsplits,&jac->mat);CHKERRQ(ierr);
1264574deadeSBarry Smith   } else if (jac->mat) {
12650298fd71SBarry Smith     jac->mat = NULL;
1266574deadeSBarry Smith   }
126797bbdb24SBarry Smith   if (jac->pmat) {ierr = MatDestroyMatrices(jac->nsplits,&jac->pmat);CHKERRQ(ierr);}
126868dd23aaSBarry Smith   if (jac->Afield) {ierr = MatDestroyMatrices(jac->nsplits,&jac->Afield);CHKERRQ(ierr);}
1269f5f0d762SBarry Smith   jac->nsplits = 0;
12706bf464f9SBarry Smith   ierr       = VecDestroy(&jac->w1);CHKERRQ(ierr);
12716bf464f9SBarry Smith   ierr       = VecDestroy(&jac->w2);CHKERRQ(ierr);
12726bf464f9SBarry Smith   ierr       = MatDestroy(&jac->schur);CHKERRQ(ierr);
1273a7476a74SDmitry Karpeev   ierr       = MatDestroy(&jac->schurp);CHKERRQ(ierr);
12746bf464f9SBarry Smith   ierr       = MatDestroy(&jac->schur_user);CHKERRQ(ierr);
12756bf464f9SBarry Smith   ierr       = KSPDestroy(&jac->kspschur);CHKERRQ(ierr);
1276d78dad28SBarry Smith   ierr       = KSPDestroy(&jac->kspupper);CHKERRQ(ierr);
12776bf464f9SBarry Smith   ierr       = MatDestroy(&jac->B);CHKERRQ(ierr);
12786bf464f9SBarry Smith   ierr       = MatDestroy(&jac->C);CHKERRQ(ierr);
12796dbb499eSCian Wilson   jac->isrestrict = PETSC_FALSE;
1280574deadeSBarry Smith   PetscFunctionReturn(0);
1281574deadeSBarry Smith }
1282574deadeSBarry Smith 
1283574deadeSBarry Smith static PetscErrorCode PCDestroy_FieldSplit(PC pc)
1284574deadeSBarry Smith {
1285574deadeSBarry Smith   PetscErrorCode    ierr;
1286574deadeSBarry Smith 
1287574deadeSBarry Smith   PetscFunctionBegin;
1288574deadeSBarry Smith   ierr = PCReset_FieldSplit(pc);CHKERRQ(ierr);
1289c31cb41cSBarry Smith   ierr = PetscFree(pc->data);CHKERRQ(ierr);
1290285fb4e2SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCFieldSplitSchurGetSubKSP_C",NULL);CHKERRQ(ierr);
1291bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCFieldSplitGetSubKSP_C",NULL);CHKERRQ(ierr);
1292bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCFieldSplitSetFields_C",NULL);CHKERRQ(ierr);
1293bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCFieldSplitSetIS_C",NULL);CHKERRQ(ierr);
1294bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCFieldSplitSetType_C",NULL);CHKERRQ(ierr);
1295bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCFieldSplitSetBlockSize_C",NULL);CHKERRQ(ierr);
129629f8a81cSJed Brown   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCFieldSplitSetSchurPre_C",NULL);CHKERRQ(ierr);
129737a82bf0SJed Brown   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCFieldSplitGetSchurPre_C",NULL);CHKERRQ(ierr);
1298bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCFieldSplitSetSchurFactType_C",NULL);CHKERRQ(ierr);
12996dbb499eSCian Wilson   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCFieldSplitRestrictIS_C",NULL);CHKERRQ(ierr);
13000971522cSBarry Smith   PetscFunctionReturn(0);
13010971522cSBarry Smith }
13020971522cSBarry Smith 
13034416b707SBarry Smith static PetscErrorCode PCSetFromOptions_FieldSplit(PetscOptionItems *PetscOptionsObject,PC pc)
13040971522cSBarry Smith {
13051b9fc7fcSBarry Smith   PetscErrorCode  ierr;
13066c924f48SJed Brown   PetscInt        bs;
13077b752e3dSPatrick Sanan   PetscBool       flg;
13089dcbbd2bSBarry Smith   PC_FieldSplit   *jac = (PC_FieldSplit*)pc->data;
13093b224e63SBarry Smith   PCCompositeType ctype;
13101b9fc7fcSBarry Smith 
13110971522cSBarry Smith   PetscFunctionBegin;
1312e55864a3SBarry Smith   ierr = PetscOptionsHead(PetscOptionsObject,"FieldSplit options");CHKERRQ(ierr);
13134ab8060aSDmitry Karpeev   ierr = PetscOptionsBool("-pc_fieldsplit_dm_splits","Whether to use DMCreateFieldDecomposition() for splits","PCFieldSplitSetDMSplits",jac->dm_splits,&jac->dm_splits,NULL);CHKERRQ(ierr);
131451f519a2SBarry Smith   ierr = PetscOptionsInt("-pc_fieldsplit_block_size","Blocksize that defines number of fields","PCFieldSplitSetBlockSize",jac->bs,&bs,&flg);CHKERRQ(ierr);
131551f519a2SBarry Smith   if (flg) {
131651f519a2SBarry Smith     ierr = PCFieldSplitSetBlockSize(pc,bs);CHKERRQ(ierr);
131751f519a2SBarry Smith   }
13182686e3e9SMatthew G. Knepley   jac->diag_use_amat = pc->useAmat;
13192686e3e9SMatthew G. Knepley   ierr = PetscOptionsBool("-pc_fieldsplit_diag_use_amat","Use Amat (not Pmat) to extract diagonal fieldsplit blocks", "PCFieldSplitSetDiagUseAmat",jac->diag_use_amat,&jac->diag_use_amat,NULL);CHKERRQ(ierr);
13202686e3e9SMatthew G. Knepley   jac->offdiag_use_amat = pc->useAmat;
13212686e3e9SMatthew G. Knepley   ierr = PetscOptionsBool("-pc_fieldsplit_off_diag_use_amat","Use Amat (not Pmat) to extract off-diagonal fieldsplit blocks", "PCFieldSplitSetOffDiagUseAmat",jac->offdiag_use_amat,&jac->offdiag_use_amat,NULL);CHKERRQ(ierr);
13227b752e3dSPatrick Sanan   ierr = PetscOptionsBool("-pc_fieldsplit_detect_saddle_point","Form 2-way split by detecting zero diagonal entries", "PCFieldSplitSetDetectSaddlePoint",jac->detect,&jac->detect,NULL);CHKERRQ(ierr);
13237b752e3dSPatrick Sanan   ierr = PCFieldSplitSetDetectSaddlePoint(pc,jac->detect);CHKERRQ(ierr); /* Sets split type and Schur PC type */
13243b224e63SBarry Smith   ierr = PetscOptionsEnum("-pc_fieldsplit_type","Type of composition","PCFieldSplitSetType",PCCompositeTypes,(PetscEnum)jac->type,(PetscEnum*)&ctype,&flg);CHKERRQ(ierr);
13253b224e63SBarry Smith   if (flg) {
13263b224e63SBarry Smith     ierr = PCFieldSplitSetType(pc,ctype);CHKERRQ(ierr);
13273b224e63SBarry Smith   }
1328c30613efSMatthew Knepley   /* Only setup fields once */
1329c30613efSMatthew Knepley   if ((jac->bs > 0) && (jac->nsplits == 0)) {
1330d32f9abdSBarry Smith     /* only allow user to set fields from command line if bs is already known.
1331d32f9abdSBarry Smith        otherwise user can set them in PCFieldSplitSetDefaults() */
13326c924f48SJed Brown     ierr = PCFieldSplitSetRuntimeSplits_Private(pc);CHKERRQ(ierr);
13336c924f48SJed Brown     if (jac->splitdefined) {ierr = PetscInfo(pc,"Splits defined using the options database\n");CHKERRQ(ierr);}
1334d32f9abdSBarry Smith   }
1335c5d2311dSJed Brown   if (jac->type == PC_COMPOSITE_SCHUR) {
1336c5929fdfSBarry Smith     ierr = PetscOptionsGetEnum(((PetscObject)pc)->options,((PetscObject)pc)->prefix,"-pc_fieldsplit_schur_factorization_type",PCFieldSplitSchurFactTypes,(PetscEnum*)&jac->schurfactorization,&flg);CHKERRQ(ierr);
1337c9c6ffaaSJed Brown     if (flg) {ierr = PetscInfo(pc,"Deprecated use of -pc_fieldsplit_schur_factorization_type\n");CHKERRQ(ierr);}
13380298fd71SBarry Smith     ierr = PetscOptionsEnum("-pc_fieldsplit_schur_fact_type","Which off-diagonal parts of the block factorization to use","PCFieldSplitSetSchurFactType",PCFieldSplitSchurFactTypes,(PetscEnum)jac->schurfactorization,(PetscEnum*)&jac->schurfactorization,NULL);CHKERRQ(ierr);
133929f8a81cSJed Brown     ierr = PetscOptionsEnum("-pc_fieldsplit_schur_precondition","How to build preconditioner for Schur complement","PCFieldSplitSetSchurPre",PCFieldSplitSchurPreTypes,(PetscEnum)jac->schurpre,(PetscEnum*)&jac->schurpre,NULL);CHKERRQ(ierr);
1340c096484dSStefano Zampini     ierr = PetscOptionsScalar("-pc_fieldsplit_schur_scale","Scale Schur complement","PCFieldSplitSetSchurScale",jac->schurscale,&jac->schurscale,NULL);CHKERRQ(ierr);
1341c5d2311dSJed Brown   }
13421b9fc7fcSBarry Smith   ierr = PetscOptionsTail();CHKERRQ(ierr);
13430971522cSBarry Smith   PetscFunctionReturn(0);
13440971522cSBarry Smith }
13450971522cSBarry Smith 
13460971522cSBarry Smith /*------------------------------------------------------------------------------------*/
13470971522cSBarry Smith 
13481e6b0712SBarry Smith static PetscErrorCode  PCFieldSplitSetFields_FieldSplit(PC pc,const char splitname[],PetscInt n,const PetscInt *fields,const PetscInt *fields_col)
13490971522cSBarry Smith {
135097bbdb24SBarry Smith   PC_FieldSplit     *jac = (PC_FieldSplit*)pc->data;
13510971522cSBarry Smith   PetscErrorCode    ierr;
13525a9f2f41SSatish Balay   PC_FieldSplitLink ilink,next = jac->head;
135369a612a9SBarry Smith   char              prefix[128];
13545d4c12cdSJungho Lee   PetscInt          i;
13550971522cSBarry Smith 
13560971522cSBarry Smith   PetscFunctionBegin;
13576c924f48SJed Brown   if (jac->splitdefined) {
13586c924f48SJed Brown     ierr = PetscInfo1(pc,"Ignoring new split \"%s\" because the splits have already been defined\n",splitname);CHKERRQ(ierr);
13596c924f48SJed Brown     PetscFunctionReturn(0);
13606c924f48SJed Brown   }
136151f519a2SBarry Smith   for (i=0; i<n; i++) {
1362e32f2f54SBarry 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);
1363e32f2f54SBarry Smith     if (fields[i] < 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Negative field %D requested",fields[i]);
136451f519a2SBarry Smith   }
1365b00a9115SJed Brown   ierr = PetscNew(&ilink);CHKERRQ(ierr);
1366a04f6461SBarry Smith   if (splitname) {
1367db4c96c1SJed Brown     ierr = PetscStrallocpy(splitname,&ilink->splitname);CHKERRQ(ierr);
1368a04f6461SBarry Smith   } else {
1369785e854fSJed Brown     ierr = PetscMalloc1(3,&ilink->splitname);CHKERRQ(ierr);
1370a04f6461SBarry Smith     ierr = PetscSNPrintf(ilink->splitname,2,"%s",jac->nsplits);CHKERRQ(ierr);
1371a04f6461SBarry Smith   }
13729df09d43SBarry Smith   ilink->event = jac->nsplits < 5 ? KSP_Solve_FS_0 + jac->nsplits : KSP_Solve_FS_0 + 4; /* Any split great than 4 gets logged in the 4th split */
1373785e854fSJed Brown   ierr = PetscMalloc1(n,&ilink->fields);CHKERRQ(ierr);
13745a9f2f41SSatish Balay   ierr = PetscMemcpy(ilink->fields,fields,n*sizeof(PetscInt));CHKERRQ(ierr);
1375785e854fSJed Brown   ierr = PetscMalloc1(n,&ilink->fields_col);CHKERRQ(ierr);
13765d4c12cdSJungho Lee   ierr = PetscMemcpy(ilink->fields_col,fields_col,n*sizeof(PetscInt));CHKERRQ(ierr);
13772fa5cd67SKarl Rupp 
13785a9f2f41SSatish Balay   ilink->nfields = n;
13790298fd71SBarry Smith   ilink->next    = NULL;
1380ce94432eSBarry Smith   ierr           = KSPCreate(PetscObjectComm((PetscObject)pc),&ilink->ksp);CHKERRQ(ierr);
1381422a814eSBarry Smith   ierr           = KSPSetErrorIfNotConverged(ilink->ksp,pc->erroriffailure);CHKERRQ(ierr);
138220252d06SBarry Smith   ierr           = PetscObjectIncrementTabLevel((PetscObject)ilink->ksp,(PetscObject)pc,1);CHKERRQ(ierr);
13835a9f2f41SSatish Balay   ierr           = KSPSetType(ilink->ksp,KSPPREONLY);CHKERRQ(ierr);
13849005cf84SBarry Smith   ierr           = PetscLogObjectParent((PetscObject)pc,(PetscObject)ilink->ksp);CHKERRQ(ierr);
138569a612a9SBarry Smith 
13868caf3d72SBarry Smith   ierr = PetscSNPrintf(prefix,sizeof(prefix),"%sfieldsplit_%s_",((PetscObject)pc)->prefix ? ((PetscObject)pc)->prefix : "",ilink->splitname);CHKERRQ(ierr);
13875a9f2f41SSatish Balay   ierr = KSPSetOptionsPrefix(ilink->ksp,prefix);CHKERRQ(ierr);
13880971522cSBarry Smith 
13890971522cSBarry Smith   if (!next) {
13905a9f2f41SSatish Balay     jac->head       = ilink;
13910298fd71SBarry Smith     ilink->previous = NULL;
13920971522cSBarry Smith   } else {
13930971522cSBarry Smith     while (next->next) {
13940971522cSBarry Smith       next = next->next;
13950971522cSBarry Smith     }
13965a9f2f41SSatish Balay     next->next      = ilink;
139751f519a2SBarry Smith     ilink->previous = next;
13980971522cSBarry Smith   }
13990971522cSBarry Smith   jac->nsplits++;
14000971522cSBarry Smith   PetscFunctionReturn(0);
14010971522cSBarry Smith }
14020971522cSBarry Smith 
1403285fb4e2SStefano Zampini static PetscErrorCode  PCFieldSplitSchurGetSubKSP_FieldSplit(PC pc,PetscInt *n,KSP **subksp)
1404285fb4e2SStefano Zampini {
1405285fb4e2SStefano Zampini   PC_FieldSplit  *jac = (PC_FieldSplit*)pc->data;
1406285fb4e2SStefano Zampini   PetscErrorCode ierr;
1407285fb4e2SStefano Zampini 
1408285fb4e2SStefano Zampini   PetscFunctionBegin;
1409285fb4e2SStefano Zampini   *subksp = NULL;
1410285fb4e2SStefano Zampini   if (n) *n = 0;
1411285fb4e2SStefano Zampini   if (jac->type == PC_COMPOSITE_SCHUR) {
1412285fb4e2SStefano Zampini     PetscInt nn;
1413285fb4e2SStefano Zampini 
1414285fb4e2SStefano Zampini     if (!jac->schur) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONGSTATE,"Must call KSPSetUp() or PCSetUp() before calling PCFieldSplitSchurGetSubKSP()");
1415285fb4e2SStefano Zampini     if (jac->nsplits != 2) SETERRQ1(PetscObjectComm((PetscObject)pc),PETSC_ERR_PLIB,"Unexpected number of splits %D != 2",jac->nsplits);
1416285fb4e2SStefano Zampini     nn   = jac->nsplits + (jac->kspupper != jac->head->ksp ? 1 : 0);
1417285fb4e2SStefano Zampini     ierr = PetscMalloc1(nn,subksp);CHKERRQ(ierr);
1418285fb4e2SStefano Zampini     (*subksp)[0] = jac->head->ksp;
1419285fb4e2SStefano Zampini     (*subksp)[1] = jac->kspschur;
1420285fb4e2SStefano Zampini     if (jac->kspupper != jac->head->ksp) (*subksp)[2] = jac->kspupper;
1421285fb4e2SStefano Zampini     if (n) *n = nn;
1422285fb4e2SStefano Zampini   }
1423285fb4e2SStefano Zampini   PetscFunctionReturn(0);
1424285fb4e2SStefano Zampini }
1425285fb4e2SStefano Zampini 
14261e6b0712SBarry Smith static PetscErrorCode  PCFieldSplitGetSubKSP_FieldSplit_Schur(PC pc,PetscInt *n,KSP **subksp)
1427e69d4d44SBarry Smith {
1428e69d4d44SBarry Smith   PC_FieldSplit  *jac = (PC_FieldSplit*)pc->data;
1429e69d4d44SBarry Smith   PetscErrorCode ierr;
1430e69d4d44SBarry Smith 
1431e69d4d44SBarry Smith   PetscFunctionBegin;
143234a3b412SBarry Smith   if (!jac->schur) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONGSTATE,"Must call KSPSetUp() or PCSetUp() before calling PCFieldSplitGetSubKSP()");
1433785e854fSJed Brown   ierr = PetscMalloc1(jac->nsplits,subksp);CHKERRQ(ierr);
1434e69d4d44SBarry Smith   ierr = MatSchurComplementGetKSP(jac->schur,*subksp);CHKERRQ(ierr);
14352fa5cd67SKarl Rupp 
1436e69d4d44SBarry Smith   (*subksp)[1] = jac->kspschur;
143713e0d083SBarry Smith   if (n) *n = jac->nsplits;
1438e69d4d44SBarry Smith   PetscFunctionReturn(0);
1439e69d4d44SBarry Smith }
14400971522cSBarry Smith 
14411e6b0712SBarry Smith static PetscErrorCode  PCFieldSplitGetSubKSP_FieldSplit(PC pc,PetscInt *n,KSP **subksp)
14420971522cSBarry Smith {
14430971522cSBarry Smith   PC_FieldSplit     *jac = (PC_FieldSplit*)pc->data;
14440971522cSBarry Smith   PetscErrorCode    ierr;
14450971522cSBarry Smith   PetscInt          cnt   = 0;
14465a9f2f41SSatish Balay   PC_FieldSplitLink ilink = jac->head;
14470971522cSBarry Smith 
14480971522cSBarry Smith   PetscFunctionBegin;
1449785e854fSJed Brown   ierr = PetscMalloc1(jac->nsplits,subksp);CHKERRQ(ierr);
14505a9f2f41SSatish Balay   while (ilink) {
14515a9f2f41SSatish Balay     (*subksp)[cnt++] = ilink->ksp;
14525a9f2f41SSatish Balay     ilink            = ilink->next;
14530971522cSBarry Smith   }
14545d480477SMatthew G Knepley   if (cnt != jac->nsplits) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Corrupt PCFIELDSPLIT object: number of splits in linked list %D does not match number in object %D",cnt,jac->nsplits);
145513e0d083SBarry Smith   if (n) *n = jac->nsplits;
14560971522cSBarry Smith   PetscFunctionReturn(0);
14570971522cSBarry Smith }
14580971522cSBarry Smith 
14596dbb499eSCian Wilson /*@C
14606dbb499eSCian Wilson     PCFieldSplitRestrictIS - Restricts the fieldsplit ISs to be within a given IS.
14616dbb499eSCian Wilson 
14626dbb499eSCian Wilson     Input Parameters:
14636dbb499eSCian Wilson +   pc  - the preconditioner context
14646dbb499eSCian Wilson +   is - the index set that defines the indices to which the fieldsplit is to be restricted
14656dbb499eSCian Wilson 
14666dbb499eSCian Wilson     Level: advanced
14676dbb499eSCian Wilson 
14686dbb499eSCian Wilson @*/
14696dbb499eSCian Wilson PetscErrorCode  PCFieldSplitRestrictIS(PC pc,IS isy)
14706dbb499eSCian Wilson {
14716dbb499eSCian Wilson   PetscErrorCode ierr;
14726dbb499eSCian Wilson 
14736dbb499eSCian Wilson   PetscFunctionBegin;
14746dbb499eSCian Wilson   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
14756dbb499eSCian Wilson   PetscValidHeaderSpecific(isy,IS_CLASSID,2);
14760246f55cSBarry Smith   ierr = PetscTryMethod(pc,"PCFieldSplitRestrictIS_C",(PC,IS),(pc,isy));CHKERRQ(ierr);
14776dbb499eSCian Wilson   PetscFunctionReturn(0);
14786dbb499eSCian Wilson }
14796dbb499eSCian Wilson 
14806dbb499eSCian Wilson 
14816dbb499eSCian Wilson static PetscErrorCode  PCFieldSplitRestrictIS_FieldSplit(PC pc, IS isy)
14826dbb499eSCian Wilson {
14836dbb499eSCian Wilson   PC_FieldSplit     *jac = (PC_FieldSplit*)pc->data;
14846dbb499eSCian Wilson   PetscErrorCode    ierr;
14856dbb499eSCian Wilson   PC_FieldSplitLink ilink = jac->head, next;
14866dbb499eSCian Wilson   PetscInt          localsize,size,sizez,i;
14876dbb499eSCian Wilson   const PetscInt    *ind, *indz;
14886dbb499eSCian Wilson   PetscInt          *indc, *indcz;
14896dbb499eSCian Wilson   PetscBool         flg;
14906dbb499eSCian Wilson 
14916dbb499eSCian Wilson   PetscFunctionBegin;
14926dbb499eSCian Wilson   ierr = ISGetLocalSize(isy,&localsize);CHKERRQ(ierr);
14936dbb499eSCian Wilson   ierr = MPI_Scan(&localsize,&size,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)isy));CHKERRQ(ierr);
14946dbb499eSCian Wilson   size -= localsize;
14956dbb499eSCian Wilson   while(ilink) {
14966dbb499eSCian Wilson     IS isrl,isr;
14971c7cfba8SBarry Smith     PC subpc;
14986dbb499eSCian Wilson     ierr          = ISEmbed(ilink->is, isy, PETSC_TRUE, &isrl);CHKERRQ(ierr);
14996dbb499eSCian Wilson     ierr          = ISGetLocalSize(isrl,&localsize);CHKERRQ(ierr);
15006dbb499eSCian Wilson     ierr          = PetscMalloc1(localsize,&indc);CHKERRQ(ierr);
15016dbb499eSCian Wilson     ierr          = ISGetIndices(isrl,&ind);CHKERRQ(ierr);
15026dbb499eSCian Wilson     ierr          = PetscMemcpy(indc,ind,localsize*sizeof(PetscInt));CHKERRQ(ierr);
15036dbb499eSCian Wilson     ierr          = ISRestoreIndices(isrl,&ind);CHKERRQ(ierr);
15046dbb499eSCian Wilson     ierr          = ISDestroy(&isrl);CHKERRQ(ierr);
15056dbb499eSCian Wilson     for (i=0; i<localsize; i++) *(indc+i) += size;
15066dbb499eSCian Wilson     ierr          = ISCreateGeneral(PetscObjectComm((PetscObject)isy),localsize,indc,PETSC_OWN_POINTER,&isr);CHKERRQ(ierr);
15076dbb499eSCian Wilson     ierr          = PetscObjectReference((PetscObject)isr);CHKERRQ(ierr);
15086dbb499eSCian Wilson     ierr          = ISDestroy(&ilink->is);CHKERRQ(ierr);
15096dbb499eSCian Wilson     ilink->is     = isr;
15106dbb499eSCian Wilson     ierr          = PetscObjectReference((PetscObject)isr);CHKERRQ(ierr);
15116dbb499eSCian Wilson     ierr          = ISDestroy(&ilink->is_col);CHKERRQ(ierr);
15126dbb499eSCian Wilson     ilink->is_col = isr;
15136dbb499eSCian Wilson     ierr          = ISDestroy(&isr);CHKERRQ(ierr);
15146dbb499eSCian Wilson     ierr          = KSPGetPC(ilink->ksp, &subpc);CHKERRQ(ierr);
15156dbb499eSCian Wilson     ierr          = PetscObjectTypeCompare((PetscObject)subpc,PCFIELDSPLIT,&flg);CHKERRQ(ierr);
15166dbb499eSCian Wilson     if(flg) {
15176dbb499eSCian Wilson       IS iszl,isz;
15186dbb499eSCian Wilson       MPI_Comm comm;
15196dbb499eSCian Wilson       ierr   = ISGetLocalSize(ilink->is,&localsize);CHKERRQ(ierr);
15206dbb499eSCian Wilson       comm   = PetscObjectComm((PetscObject)ilink->is);
15216dbb499eSCian Wilson       ierr   = ISEmbed(isy, ilink->is, PETSC_TRUE, &iszl);CHKERRQ(ierr);
15226dbb499eSCian Wilson       ierr   = MPI_Scan(&localsize,&sizez,1,MPIU_INT,MPI_SUM,comm);CHKERRQ(ierr);
15236dbb499eSCian Wilson       sizez -= localsize;
15246dbb499eSCian Wilson       ierr   = ISGetLocalSize(iszl,&localsize);CHKERRQ(ierr);
15256dbb499eSCian Wilson       ierr   = PetscMalloc1(localsize,&indcz);CHKERRQ(ierr);
15266dbb499eSCian Wilson       ierr   = ISGetIndices(iszl,&indz);CHKERRQ(ierr);
15276dbb499eSCian Wilson       ierr   = PetscMemcpy(indcz,indz,localsize*sizeof(PetscInt));CHKERRQ(ierr);
15286dbb499eSCian Wilson       ierr   = ISRestoreIndices(iszl,&indz);CHKERRQ(ierr);
15296dbb499eSCian Wilson       ierr   = ISDestroy(&iszl);CHKERRQ(ierr);
15306dbb499eSCian Wilson       for (i=0; i<localsize; i++) *(indcz+i) += sizez;
15316dbb499eSCian Wilson       ierr   = ISCreateGeneral(comm,localsize,indcz,PETSC_OWN_POINTER,&isz);CHKERRQ(ierr);
15326dbb499eSCian Wilson       ierr   = PCFieldSplitRestrictIS(subpc,isz);CHKERRQ(ierr);
15336dbb499eSCian Wilson       ierr   = ISDestroy(&isz);CHKERRQ(ierr);
15346dbb499eSCian Wilson     }
15356dbb499eSCian Wilson     next = ilink->next;
15366dbb499eSCian Wilson     ilink = next;
15376dbb499eSCian Wilson   }
15386dbb499eSCian Wilson   jac->isrestrict = PETSC_TRUE;
15396dbb499eSCian Wilson   PetscFunctionReturn(0);
15406dbb499eSCian Wilson }
15416dbb499eSCian Wilson 
15421e6b0712SBarry Smith static PetscErrorCode  PCFieldSplitSetIS_FieldSplit(PC pc,const char splitname[],IS is)
1543704ba839SBarry Smith {
1544704ba839SBarry Smith   PC_FieldSplit     *jac = (PC_FieldSplit*)pc->data;
1545704ba839SBarry Smith   PetscErrorCode    ierr;
1546704ba839SBarry Smith   PC_FieldSplitLink ilink, next = jac->head;
1547704ba839SBarry Smith   char              prefix[128];
1548704ba839SBarry Smith 
1549704ba839SBarry Smith   PetscFunctionBegin;
15506c924f48SJed Brown   if (jac->splitdefined) {
15516c924f48SJed Brown     ierr = PetscInfo1(pc,"Ignoring new split \"%s\" because the splits have already been defined\n",splitname);CHKERRQ(ierr);
15526c924f48SJed Brown     PetscFunctionReturn(0);
15536c924f48SJed Brown   }
1554b00a9115SJed Brown   ierr = PetscNew(&ilink);CHKERRQ(ierr);
1555a04f6461SBarry Smith   if (splitname) {
1556db4c96c1SJed Brown     ierr = PetscStrallocpy(splitname,&ilink->splitname);CHKERRQ(ierr);
1557a04f6461SBarry Smith   } else {
1558785e854fSJed Brown     ierr = PetscMalloc1(8,&ilink->splitname);CHKERRQ(ierr);
1559b5787286SJed Brown     ierr = PetscSNPrintf(ilink->splitname,7,"%D",jac->nsplits);CHKERRQ(ierr);
1560a04f6461SBarry Smith   }
15619df09d43SBarry Smith   ilink->event = jac->nsplits < 5 ? KSP_Solve_FS_0 + jac->nsplits : KSP_Solve_FS_0 + 4; /* Any split great than 4 gets logged in the 4th split */
15621ab39975SBarry Smith   ierr          = PetscObjectReference((PetscObject)is);CHKERRQ(ierr);
1563b5787286SJed Brown   ierr          = ISDestroy(&ilink->is);CHKERRQ(ierr);
1564b5787286SJed Brown   ilink->is     = is;
1565b5787286SJed Brown   ierr          = PetscObjectReference((PetscObject)is);CHKERRQ(ierr);
1566b5787286SJed Brown   ierr          = ISDestroy(&ilink->is_col);CHKERRQ(ierr);
1567b5787286SJed Brown   ilink->is_col = is;
15680298fd71SBarry Smith   ilink->next   = NULL;
1569ce94432eSBarry Smith   ierr          = KSPCreate(PetscObjectComm((PetscObject)pc),&ilink->ksp);CHKERRQ(ierr);
1570422a814eSBarry Smith   ierr          = KSPSetErrorIfNotConverged(ilink->ksp,pc->erroriffailure);CHKERRQ(ierr);
157120252d06SBarry Smith   ierr          = PetscObjectIncrementTabLevel((PetscObject)ilink->ksp,(PetscObject)pc,1);CHKERRQ(ierr);
1572704ba839SBarry Smith   ierr          = KSPSetType(ilink->ksp,KSPPREONLY);CHKERRQ(ierr);
15739005cf84SBarry Smith   ierr          = PetscLogObjectParent((PetscObject)pc,(PetscObject)ilink->ksp);CHKERRQ(ierr);
1574704ba839SBarry Smith 
15758caf3d72SBarry Smith   ierr = PetscSNPrintf(prefix,sizeof(prefix),"%sfieldsplit_%s_",((PetscObject)pc)->prefix ? ((PetscObject)pc)->prefix : "",ilink->splitname);CHKERRQ(ierr);
1576704ba839SBarry Smith   ierr = KSPSetOptionsPrefix(ilink->ksp,prefix);CHKERRQ(ierr);
1577704ba839SBarry Smith 
1578704ba839SBarry Smith   if (!next) {
1579704ba839SBarry Smith     jac->head       = ilink;
15800298fd71SBarry Smith     ilink->previous = NULL;
1581704ba839SBarry Smith   } else {
1582704ba839SBarry Smith     while (next->next) {
1583704ba839SBarry Smith       next = next->next;
1584704ba839SBarry Smith     }
1585704ba839SBarry Smith     next->next      = ilink;
1586704ba839SBarry Smith     ilink->previous = next;
1587704ba839SBarry Smith   }
1588704ba839SBarry Smith   jac->nsplits++;
1589704ba839SBarry Smith   PetscFunctionReturn(0);
1590704ba839SBarry Smith }
1591704ba839SBarry Smith 
159294ef8ddeSSatish Balay /*@C
15930971522cSBarry Smith     PCFieldSplitSetFields - Sets the fields for one particular split in the field split preconditioner
15940971522cSBarry Smith 
1595ad4df100SBarry Smith     Logically Collective on PC
15960971522cSBarry Smith 
15970971522cSBarry Smith     Input Parameters:
15980971522cSBarry Smith +   pc  - the preconditioner context
15990298fd71SBarry Smith .   splitname - name of this split, if NULL the number of the split is used
16000971522cSBarry Smith .   n - the number of fields in this split
1601db4c96c1SJed Brown -   fields - the fields in this split
16020971522cSBarry Smith 
16030971522cSBarry Smith     Level: intermediate
16040971522cSBarry Smith 
160595452b02SPatrick Sanan     Notes:
160695452b02SPatrick Sanan     Use PCFieldSplitSetIS() to set a completely general set of indices as a field.
1607d32f9abdSBarry Smith 
16087287d2a3SDmitry Karpeev      The PCFieldSplitSetFields() is for defining fields as strided blocks. For example, if the block
1609d32f9abdSBarry 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
1610d32f9abdSBarry Smith      0xx3xx6xx9xx12 ... x1xx4xx7xx ... xx2xx5xx8xx.. 01x34x67x... 0x1x3x5x7.. x12x45x78x....
1611d32f9abdSBarry Smith      where the numbered entries indicate what is in the field.
1612d32f9abdSBarry Smith 
1613db4c96c1SJed Brown      This function is called once per split (it creates a new split each time).  Solve options
1614db4c96c1SJed Brown      for this split will be available under the prefix -fieldsplit_SPLITNAME_.
1615db4c96c1SJed Brown 
16165d4c12cdSJungho Lee      Developer Note: This routine does not actually create the IS representing the split, that is delayed
16175d4c12cdSJungho Lee      until PCSetUp_FieldSplit(), because information about the vector/matrix layouts may not be
16185d4c12cdSJungho Lee      available when this routine is called.
16195d4c12cdSJungho Lee 
1620d32f9abdSBarry Smith .seealso: PCFieldSplitGetSubKSP(), PCFIELDSPLIT, PCFieldSplitSetBlockSize(), PCFieldSplitSetIS()
16210971522cSBarry Smith 
16220971522cSBarry Smith @*/
16235d4c12cdSJungho Lee PetscErrorCode  PCFieldSplitSetFields(PC pc,const char splitname[],PetscInt n,const PetscInt *fields,const PetscInt *fields_col)
16240971522cSBarry Smith {
16254ac538c5SBarry Smith   PetscErrorCode ierr;
16260971522cSBarry Smith 
16270971522cSBarry Smith   PetscFunctionBegin;
16280700a824SBarry Smith   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
1629db4c96c1SJed Brown   PetscValidCharPointer(splitname,2);
1630ce94432eSBarry Smith   if (n < 1) SETERRQ2(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_OUTOFRANGE,"Provided number of fields %D in split \"%s\" not positive",n,splitname);
1631db4c96c1SJed Brown   PetscValidIntPointer(fields,3);
16320246f55cSBarry Smith   ierr = PetscTryMethod(pc,"PCFieldSplitSetFields_C",(PC,const char[],PetscInt,const PetscInt*,const PetscInt*),(pc,splitname,n,fields,fields_col));CHKERRQ(ierr);
16330971522cSBarry Smith   PetscFunctionReturn(0);
16340971522cSBarry Smith }
16350971522cSBarry Smith 
1636c84da90fSDmitry Karpeev /*@
1637c84da90fSDmitry Karpeev     PCFieldSplitSetDiagUseAmat - set flag indicating whether to extract diagonal blocks from Amat (rather than Pmat)
1638c84da90fSDmitry Karpeev 
1639c84da90fSDmitry Karpeev     Logically Collective on PC
1640c84da90fSDmitry Karpeev 
1641c84da90fSDmitry Karpeev     Input Parameters:
1642c84da90fSDmitry Karpeev +   pc  - the preconditioner object
1643c84da90fSDmitry Karpeev -   flg - boolean flag indicating whether or not to use Amat to extract the diagonal blocks from
1644c84da90fSDmitry Karpeev 
16459506b623SDmitry Karpeev     Options Database:
16469506b623SDmitry Karpeev .     -pc_fieldsplit_diag_use_amat
1647c84da90fSDmitry Karpeev 
1648c84da90fSDmitry Karpeev     Level: intermediate
1649c84da90fSDmitry Karpeev 
1650c84da90fSDmitry Karpeev .seealso: PCFieldSplitGetDiagUseAmat(), PCFieldSplitSetOffDiagUseAmat(), PCFIELDSPLIT
1651c84da90fSDmitry Karpeev 
1652c84da90fSDmitry Karpeev @*/
1653c84da90fSDmitry Karpeev PetscErrorCode  PCFieldSplitSetDiagUseAmat(PC pc,PetscBool flg)
1654c84da90fSDmitry Karpeev {
1655c84da90fSDmitry Karpeev   PC_FieldSplit  *jac = (PC_FieldSplit*)pc->data;
1656c84da90fSDmitry Karpeev   PetscBool      isfs;
1657c84da90fSDmitry Karpeev   PetscErrorCode ierr;
1658c84da90fSDmitry Karpeev 
1659c84da90fSDmitry Karpeev   PetscFunctionBegin;
1660c84da90fSDmitry Karpeev   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
1661c84da90fSDmitry Karpeev   ierr = PetscObjectTypeCompare((PetscObject)pc,PCFIELDSPLIT,&isfs);CHKERRQ(ierr);
1662c84da90fSDmitry Karpeev   if (!isfs) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"PC not of type %s",PCFIELDSPLIT);
1663c84da90fSDmitry Karpeev   jac->diag_use_amat = flg;
1664c84da90fSDmitry Karpeev   PetscFunctionReturn(0);
1665c84da90fSDmitry Karpeev }
1666c84da90fSDmitry Karpeev 
1667c84da90fSDmitry Karpeev /*@
1668c84da90fSDmitry Karpeev     PCFieldSplitGetDiagUseAmat - get the flag indicating whether to extract diagonal blocks from Amat (rather than Pmat)
1669c84da90fSDmitry Karpeev 
1670c84da90fSDmitry Karpeev     Logically Collective on PC
1671c84da90fSDmitry Karpeev 
1672c84da90fSDmitry Karpeev     Input Parameters:
1673c84da90fSDmitry Karpeev .   pc  - the preconditioner object
1674c84da90fSDmitry Karpeev 
1675c84da90fSDmitry Karpeev     Output Parameters:
1676c84da90fSDmitry Karpeev .   flg - boolean flag indicating whether or not to use Amat to extract the diagonal blocks from
1677c84da90fSDmitry Karpeev 
1678c84da90fSDmitry Karpeev 
1679c84da90fSDmitry Karpeev     Level: intermediate
1680c84da90fSDmitry Karpeev 
1681c84da90fSDmitry Karpeev .seealso: PCFieldSplitSetDiagUseAmat(), PCFieldSplitGetOffDiagUseAmat(), PCFIELDSPLIT
1682c84da90fSDmitry Karpeev 
1683c84da90fSDmitry Karpeev @*/
1684c84da90fSDmitry Karpeev PetscErrorCode  PCFieldSplitGetDiagUseAmat(PC pc,PetscBool *flg)
1685c84da90fSDmitry Karpeev {
1686c84da90fSDmitry Karpeev   PC_FieldSplit  *jac = (PC_FieldSplit*)pc->data;
1687c84da90fSDmitry Karpeev   PetscBool      isfs;
1688c84da90fSDmitry Karpeev   PetscErrorCode ierr;
1689c84da90fSDmitry Karpeev 
1690c84da90fSDmitry Karpeev   PetscFunctionBegin;
1691c84da90fSDmitry Karpeev   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
1692c84da90fSDmitry Karpeev   PetscValidPointer(flg,2);
1693c84da90fSDmitry Karpeev   ierr = PetscObjectTypeCompare((PetscObject)pc,PCFIELDSPLIT,&isfs);CHKERRQ(ierr);
1694c84da90fSDmitry Karpeev   if (!isfs) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"PC not of type %s",PCFIELDSPLIT);
1695c84da90fSDmitry Karpeev   *flg = jac->diag_use_amat;
1696c84da90fSDmitry Karpeev   PetscFunctionReturn(0);
1697c84da90fSDmitry Karpeev }
1698c84da90fSDmitry Karpeev 
1699c84da90fSDmitry Karpeev /*@
1700c84da90fSDmitry Karpeev     PCFieldSplitSetOffDiagUseAmat - set flag indicating whether to extract off-diagonal blocks from Amat (rather than Pmat)
1701c84da90fSDmitry Karpeev 
1702c84da90fSDmitry Karpeev     Logically Collective on PC
1703c84da90fSDmitry Karpeev 
1704c84da90fSDmitry Karpeev     Input Parameters:
1705c84da90fSDmitry Karpeev +   pc  - the preconditioner object
1706c84da90fSDmitry Karpeev -   flg - boolean flag indicating whether or not to use Amat to extract the off-diagonal blocks from
1707c84da90fSDmitry Karpeev 
17089506b623SDmitry Karpeev     Options Database:
17099506b623SDmitry Karpeev .     -pc_fieldsplit_off_diag_use_amat
1710c84da90fSDmitry Karpeev 
1711c84da90fSDmitry Karpeev     Level: intermediate
1712c84da90fSDmitry Karpeev 
1713c84da90fSDmitry Karpeev .seealso: PCFieldSplitGetOffDiagUseAmat(), PCFieldSplitSetDiagUseAmat(), PCFIELDSPLIT
1714c84da90fSDmitry Karpeev 
1715c84da90fSDmitry Karpeev @*/
1716c84da90fSDmitry Karpeev PetscErrorCode  PCFieldSplitSetOffDiagUseAmat(PC pc,PetscBool flg)
1717c84da90fSDmitry Karpeev {
1718c84da90fSDmitry Karpeev   PC_FieldSplit *jac = (PC_FieldSplit*)pc->data;
1719c84da90fSDmitry Karpeev   PetscBool      isfs;
1720c84da90fSDmitry Karpeev   PetscErrorCode ierr;
1721c84da90fSDmitry Karpeev 
1722c84da90fSDmitry Karpeev   PetscFunctionBegin;
1723c84da90fSDmitry Karpeev   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
1724c84da90fSDmitry Karpeev   ierr = PetscObjectTypeCompare((PetscObject)pc,PCFIELDSPLIT,&isfs);CHKERRQ(ierr);
1725c84da90fSDmitry Karpeev   if (!isfs) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"PC not of type %s",PCFIELDSPLIT);
1726c84da90fSDmitry Karpeev   jac->offdiag_use_amat = flg;
1727c84da90fSDmitry Karpeev   PetscFunctionReturn(0);
1728c84da90fSDmitry Karpeev }
1729c84da90fSDmitry Karpeev 
1730c84da90fSDmitry Karpeev /*@
1731c84da90fSDmitry Karpeev     PCFieldSplitGetOffDiagUseAmat - get the flag indicating whether to extract off-diagonal blocks from Amat (rather than Pmat)
1732c84da90fSDmitry Karpeev 
1733c84da90fSDmitry Karpeev     Logically Collective on PC
1734c84da90fSDmitry Karpeev 
1735c84da90fSDmitry Karpeev     Input Parameters:
1736c84da90fSDmitry Karpeev .   pc  - the preconditioner object
1737c84da90fSDmitry Karpeev 
1738c84da90fSDmitry Karpeev     Output Parameters:
1739c84da90fSDmitry Karpeev .   flg - boolean flag indicating whether or not to use Amat to extract the off-diagonal blocks from
1740c84da90fSDmitry Karpeev 
1741c84da90fSDmitry Karpeev 
1742c84da90fSDmitry Karpeev     Level: intermediate
1743c84da90fSDmitry Karpeev 
1744c84da90fSDmitry Karpeev .seealso: PCFieldSplitSetOffDiagUseAmat(), PCFieldSplitGetDiagUseAmat(), PCFIELDSPLIT
1745c84da90fSDmitry Karpeev 
1746c84da90fSDmitry Karpeev @*/
1747c84da90fSDmitry Karpeev PetscErrorCode  PCFieldSplitGetOffDiagUseAmat(PC pc,PetscBool *flg)
1748c84da90fSDmitry Karpeev {
1749c84da90fSDmitry Karpeev   PC_FieldSplit  *jac = (PC_FieldSplit*)pc->data;
1750c84da90fSDmitry Karpeev   PetscBool      isfs;
1751c84da90fSDmitry Karpeev   PetscErrorCode ierr;
1752c84da90fSDmitry Karpeev 
1753c84da90fSDmitry Karpeev   PetscFunctionBegin;
1754c84da90fSDmitry Karpeev   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
1755c84da90fSDmitry Karpeev   PetscValidPointer(flg,2);
1756c84da90fSDmitry Karpeev   ierr = PetscObjectTypeCompare((PetscObject)pc,PCFIELDSPLIT,&isfs);CHKERRQ(ierr);
1757c84da90fSDmitry Karpeev   if (!isfs) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"PC not of type %s",PCFIELDSPLIT);
1758c84da90fSDmitry Karpeev   *flg = jac->offdiag_use_amat;
1759c84da90fSDmitry Karpeev   PetscFunctionReturn(0);
1760c84da90fSDmitry Karpeev }
1761c84da90fSDmitry Karpeev 
1762c84da90fSDmitry Karpeev 
1763c84da90fSDmitry Karpeev 
1764218d4943SBarry Smith /*@C
1765704ba839SBarry Smith     PCFieldSplitSetIS - Sets the exact elements for field
1766704ba839SBarry Smith 
1767ad4df100SBarry Smith     Logically Collective on PC
1768704ba839SBarry Smith 
1769704ba839SBarry Smith     Input Parameters:
1770704ba839SBarry Smith +   pc  - the preconditioner context
17710298fd71SBarry Smith .   splitname - name of this split, if NULL the number of the split is used
1772db4c96c1SJed Brown -   is - the index set that defines the vector elements in this field
1773704ba839SBarry Smith 
1774d32f9abdSBarry Smith 
1775a6ffb8dbSJed Brown     Notes:
1776a6ffb8dbSJed Brown     Use PCFieldSplitSetFields(), for fields defined by strided types.
1777a6ffb8dbSJed Brown 
1778db4c96c1SJed Brown     This function is called once per split (it creates a new split each time).  Solve options
1779db4c96c1SJed Brown     for this split will be available under the prefix -fieldsplit_SPLITNAME_.
1780d32f9abdSBarry Smith 
1781704ba839SBarry Smith     Level: intermediate
1782704ba839SBarry Smith 
1783704ba839SBarry Smith .seealso: PCFieldSplitGetSubKSP(), PCFIELDSPLIT, PCFieldSplitSetBlockSize()
1784704ba839SBarry Smith 
1785704ba839SBarry Smith @*/
17867087cfbeSBarry Smith PetscErrorCode  PCFieldSplitSetIS(PC pc,const char splitname[],IS is)
1787704ba839SBarry Smith {
17884ac538c5SBarry Smith   PetscErrorCode ierr;
1789704ba839SBarry Smith 
1790704ba839SBarry Smith   PetscFunctionBegin;
17910700a824SBarry Smith   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
17927b62db95SJungho Lee   if (splitname) PetscValidCharPointer(splitname,2);
1793db4c96c1SJed Brown   PetscValidHeaderSpecific(is,IS_CLASSID,3);
1794ccc738f7SBarry Smith   ierr = PetscTryMethod(pc,"PCFieldSplitSetIS_C",(PC,const char[],IS),(pc,splitname,is));CHKERRQ(ierr);
1795704ba839SBarry Smith   PetscFunctionReturn(0);
1796704ba839SBarry Smith }
1797704ba839SBarry Smith 
179894ef8ddeSSatish Balay /*@C
179957a9adfeSMatthew G Knepley     PCFieldSplitGetIS - Retrieves the elements for a field as an IS
180057a9adfeSMatthew G Knepley 
180157a9adfeSMatthew G Knepley     Logically Collective on PC
180257a9adfeSMatthew G Knepley 
180357a9adfeSMatthew G Knepley     Input Parameters:
180457a9adfeSMatthew G Knepley +   pc  - the preconditioner context
180557a9adfeSMatthew G Knepley -   splitname - name of this split
180657a9adfeSMatthew G Knepley 
180757a9adfeSMatthew G Knepley     Output Parameter:
18080298fd71SBarry Smith -   is - the index set that defines the vector elements in this field, or NULL if the field is not found
180957a9adfeSMatthew G Knepley 
181057a9adfeSMatthew G Knepley     Level: intermediate
181157a9adfeSMatthew G Knepley 
181257a9adfeSMatthew G Knepley .seealso: PCFieldSplitGetSubKSP(), PCFIELDSPLIT, PCFieldSplitSetIS()
181357a9adfeSMatthew G Knepley 
181457a9adfeSMatthew G Knepley @*/
181557a9adfeSMatthew G Knepley PetscErrorCode PCFieldSplitGetIS(PC pc,const char splitname[],IS *is)
181657a9adfeSMatthew G Knepley {
181757a9adfeSMatthew G Knepley   PetscErrorCode ierr;
181857a9adfeSMatthew G Knepley 
181957a9adfeSMatthew G Knepley   PetscFunctionBegin;
182057a9adfeSMatthew G Knepley   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
182157a9adfeSMatthew G Knepley   PetscValidCharPointer(splitname,2);
182257a9adfeSMatthew G Knepley   PetscValidPointer(is,3);
182357a9adfeSMatthew G Knepley   {
182457a9adfeSMatthew G Knepley     PC_FieldSplit     *jac  = (PC_FieldSplit*) pc->data;
182557a9adfeSMatthew G Knepley     PC_FieldSplitLink ilink = jac->head;
182657a9adfeSMatthew G Knepley     PetscBool         found;
182757a9adfeSMatthew G Knepley 
18280298fd71SBarry Smith     *is = NULL;
182957a9adfeSMatthew G Knepley     while (ilink) {
183057a9adfeSMatthew G Knepley       ierr = PetscStrcmp(ilink->splitname, splitname, &found);CHKERRQ(ierr);
183157a9adfeSMatthew G Knepley       if (found) {
183257a9adfeSMatthew G Knepley         *is = ilink->is;
183357a9adfeSMatthew G Knepley         break;
183457a9adfeSMatthew G Knepley       }
183557a9adfeSMatthew G Knepley       ilink = ilink->next;
183657a9adfeSMatthew G Knepley     }
183757a9adfeSMatthew G Knepley   }
183857a9adfeSMatthew G Knepley   PetscFunctionReturn(0);
183957a9adfeSMatthew G Knepley }
184057a9adfeSMatthew G Knepley 
184151f519a2SBarry Smith /*@
184251f519a2SBarry Smith     PCFieldSplitSetBlockSize - Sets the block size for defining where fields start in the
184351f519a2SBarry Smith       fieldsplit preconditioner. If not set the matrix block size is used.
184451f519a2SBarry Smith 
1845ad4df100SBarry Smith     Logically Collective on PC
184651f519a2SBarry Smith 
184751f519a2SBarry Smith     Input Parameters:
184851f519a2SBarry Smith +   pc  - the preconditioner context
184951f519a2SBarry Smith -   bs - the block size
185051f519a2SBarry Smith 
185151f519a2SBarry Smith     Level: intermediate
185251f519a2SBarry Smith 
185351f519a2SBarry Smith .seealso: PCFieldSplitGetSubKSP(), PCFIELDSPLIT, PCFieldSplitSetFields()
185451f519a2SBarry Smith 
185551f519a2SBarry Smith @*/
18567087cfbeSBarry Smith PetscErrorCode  PCFieldSplitSetBlockSize(PC pc,PetscInt bs)
185751f519a2SBarry Smith {
18584ac538c5SBarry Smith   PetscErrorCode ierr;
185951f519a2SBarry Smith 
186051f519a2SBarry Smith   PetscFunctionBegin;
18610700a824SBarry Smith   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
1862c5eb9154SBarry Smith   PetscValidLogicalCollectiveInt(pc,bs,2);
18634ac538c5SBarry Smith   ierr = PetscTryMethod(pc,"PCFieldSplitSetBlockSize_C",(PC,PetscInt),(pc,bs));CHKERRQ(ierr);
186451f519a2SBarry Smith   PetscFunctionReturn(0);
186551f519a2SBarry Smith }
186651f519a2SBarry Smith 
18670971522cSBarry Smith /*@C
186869a612a9SBarry Smith    PCFieldSplitGetSubKSP - Gets the KSP contexts for all splits
18690971522cSBarry Smith 
187069a612a9SBarry Smith    Collective on KSP
18710971522cSBarry Smith 
18720971522cSBarry Smith    Input Parameter:
18730971522cSBarry Smith .  pc - the preconditioner context
18740971522cSBarry Smith 
18750971522cSBarry Smith    Output Parameters:
187613e0d083SBarry Smith +  n - the number of splits
18773111de3cSBarry Smith -  subksp - the array of KSP contexts
18780971522cSBarry Smith 
18790971522cSBarry Smith    Note:
18809a4f7e47SBarry Smith    After PCFieldSplitGetSubKSP() the array of KSPs is to be freed by the user with PetscFree()
1881d32f9abdSBarry Smith    (not the KSP just the array that contains them).
18820971522cSBarry Smith 
1883285fb4e2SStefano Zampini    You must call PCSetUp() before calling PCFieldSplitGetSubKSP().
1884285fb4e2SStefano Zampini 
1885285fb4e2SStefano Zampini    If the fieldsplit is of type PC_COMPOSITE_SCHUR, it returns the KSP object used inside the
1886285fb4e2SStefano Zampini    Schur complement and the KSP object used to iterate over the Schur complement.
1887285fb4e2SStefano Zampini    To access all the KSP objects used in PC_COMPOSITE_SCHUR, use PCFieldSplitSchurGetSubKSP()
18880971522cSBarry Smith 
1889196cc216SBarry Smith    Fortran Usage: You must pass in a KSP array that is large enough to contain all the local KSPs.
18902bf68e3eSBarry Smith       You can call PCFieldSplitGetSubKSP(pc,n,PETSC_NULL_KSP,ierr) to determine how large the
1891196cc216SBarry Smith       KSP array must be.
1892196cc216SBarry Smith 
1893196cc216SBarry Smith 
18940971522cSBarry Smith    Level: advanced
18950971522cSBarry Smith 
18960971522cSBarry Smith .seealso: PCFIELDSPLIT
18970971522cSBarry Smith @*/
18987087cfbeSBarry Smith PetscErrorCode  PCFieldSplitGetSubKSP(PC pc,PetscInt *n,KSP *subksp[])
18990971522cSBarry Smith {
19004ac538c5SBarry Smith   PetscErrorCode ierr;
19010971522cSBarry Smith 
19020971522cSBarry Smith   PetscFunctionBegin;
19030700a824SBarry Smith   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
190413e0d083SBarry Smith   if (n) PetscValidIntPointer(n,2);
19054ac538c5SBarry Smith   ierr = PetscUseMethod(pc,"PCFieldSplitGetSubKSP_C",(PC,PetscInt*,KSP **),(pc,n,subksp));CHKERRQ(ierr);
19060971522cSBarry Smith   PetscFunctionReturn(0);
19070971522cSBarry Smith }
19080971522cSBarry Smith 
1909285fb4e2SStefano Zampini /*@C
1910285fb4e2SStefano Zampini    PCFieldSplitSchurGetSubKSP - Gets the KSP contexts used inside the Schur complement based PCFIELDSPLIT
1911285fb4e2SStefano Zampini 
1912285fb4e2SStefano Zampini    Collective on KSP
1913285fb4e2SStefano Zampini 
1914285fb4e2SStefano Zampini    Input Parameter:
1915285fb4e2SStefano Zampini .  pc - the preconditioner context
1916285fb4e2SStefano Zampini 
1917285fb4e2SStefano Zampini    Output Parameters:
1918285fb4e2SStefano Zampini +  n - the number of splits
1919285fb4e2SStefano Zampini -  subksp - the array of KSP contexts
1920285fb4e2SStefano Zampini 
1921285fb4e2SStefano Zampini    Note:
1922285fb4e2SStefano Zampini    After PCFieldSplitSchurGetSubKSP() the array of KSPs is to be freed by the user with PetscFree()
1923285fb4e2SStefano Zampini    (not the KSP just the array that contains them).
1924285fb4e2SStefano Zampini 
1925285fb4e2SStefano Zampini    You must call PCSetUp() before calling PCFieldSplitSchurGetSubKSP().
1926285fb4e2SStefano Zampini 
1927285fb4e2SStefano Zampini    If the fieldsplit type is of type PC_COMPOSITE_SCHUR, it returns (in order)
1928285fb4e2SStefano Zampini    - the KSP used for the (1,1) block
1929285fb4e2SStefano Zampini    - the KSP used for the Schur complement (not the one used for the interior Schur solver)
1930285fb4e2SStefano Zampini    - the KSP used for the (1,1) block in the upper triangular factor (if different from that of the (1,1) block).
1931285fb4e2SStefano Zampini 
1932285fb4e2SStefano Zampini    It returns a null array if the fieldsplit is not of type PC_COMPOSITE_SCHUR; in this case, you should use PCFieldSplitGetSubKSP().
1933285fb4e2SStefano Zampini 
1934285fb4e2SStefano Zampini    Fortran Usage: You must pass in a KSP array that is large enough to contain all the local KSPs.
1935285fb4e2SStefano Zampini       You can call PCFieldSplitSchurGetSubKSP(pc,n,PETSC_NULL_KSP,ierr) to determine how large the
1936285fb4e2SStefano Zampini       KSP array must be.
1937285fb4e2SStefano Zampini 
1938285fb4e2SStefano Zampini    Level: advanced
1939285fb4e2SStefano Zampini 
1940285fb4e2SStefano Zampini .seealso: PCFIELDSPLIT
1941285fb4e2SStefano Zampini @*/
1942285fb4e2SStefano Zampini PetscErrorCode  PCFieldSplitSchurGetSubKSP(PC pc,PetscInt *n,KSP *subksp[])
1943285fb4e2SStefano Zampini {
1944285fb4e2SStefano Zampini   PetscErrorCode ierr;
1945285fb4e2SStefano Zampini 
1946285fb4e2SStefano Zampini   PetscFunctionBegin;
1947285fb4e2SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
1948285fb4e2SStefano Zampini   if (n) PetscValidIntPointer(n,2);
1949285fb4e2SStefano Zampini   ierr = PetscUseMethod(pc,"PCFieldSplitSchurGetSubKSP_C",(PC,PetscInt*,KSP **),(pc,n,subksp));CHKERRQ(ierr);
1950285fb4e2SStefano Zampini   PetscFunctionReturn(0);
1951285fb4e2SStefano Zampini }
1952285fb4e2SStefano Zampini 
1953e69d4d44SBarry Smith /*@
195453f2277eSBarry Smith     PCFieldSplitSetSchurPre -  Indicates what operator is used to construct the preconditioner for the Schur complement.
1955a04f6461SBarry Smith       A11 matrix. Otherwise no preconditioner is used.
1956e69d4d44SBarry Smith 
1957e69d4d44SBarry Smith     Collective on PC
1958e69d4d44SBarry Smith 
1959e69d4d44SBarry Smith     Input Parameters:
1960e69d4d44SBarry Smith +   pc      - the preconditioner context
19616fdd48a9SBarry Smith .   ptype   - which matrix to use for preconditioning the Schur complement: PC_FIELDSPLIT_SCHUR_PRE_A11 (default), PC_FIELDSPLIT_SCHUR_PRE_SELF, PC_FIELDSPLIT_SCHUR_PRE_USER
19626fdd48a9SBarry Smith               PC_FIELDSPLIT_SCHUR_PRE_SELFP, and PC_FIELDSPLIT_SCHUR_PRE_FULL
19630298fd71SBarry Smith -   userpre - matrix to use for preconditioning, or NULL
1964084e4875SJed Brown 
1965e69d4d44SBarry Smith     Options Database:
19666fdd48a9SBarry Smith .     -pc_fieldsplit_schur_precondition <self,selfp,user,a11,full> - default is a11. See notes for meaning of various arguments
1967e69d4d44SBarry Smith 
1968fd1303e9SJungho Lee     Notes:
1969fd1303e9SJungho Lee $    If ptype is
1970a6a584a2SBarry Smith $        a11 then the preconditioner for the Schur complement is generated from the block diagonal part of the preconditioner
197153f2277eSBarry Smith $             matrix associated with the Schur complement (i.e. A11), not the Schur complement matrix
1972a6a584a2SBarry Smith $        self the preconditioner for the Schur complement is generated from the symbolic representation of the Schur complement matrix:
1973a6a584a2SBarry Smith $             The only preconditioner that currently works with this symbolic respresentation matrix object is the PCLSC
1974fd1303e9SJungho Lee $             preconditioner
19756fdd48a9SBarry Smith $        user then the preconditioner for the Schur complement is generated from the user provided matrix (pre argument
19766fdd48a9SBarry Smith $             to this function).
1977a6a584a2SBarry Smith $        selfp then the preconditioning for the Schur complement is generated from an explicitly-assembled approximation Sp = A11 - A10 inv(diag(A00)) A01
19781d71051fSDmitry Karpeev $             This is only a good preconditioner when diag(A00) is a good preconditioner for A00. Optionally, A00 can be
19796fdd48a9SBarry Smith $             lumped before extracting the diagonal using the additional option -fieldsplit_1_mat_schur_complement_ainv_type lump
198094350679SMatthew Knepley $        full then the preconditioner for the Schur complement is generated from the exact Schur complement matrix representation computed internally by PCFIELDSPLIT (this is expensive)
19816fdd48a9SBarry Smith $             useful mostly as a test that the Schur complement approach can work for your problem
1982fd1303e9SJungho Lee 
1983e87fab1bSBarry Smith      When solving a saddle point problem, where the A11 block is identically zero, using a11 as the ptype only makes sense
1984fd1303e9SJungho Lee     with the additional option -fieldsplit_1_pc_type none. Usually for saddle point problems one would use a ptype of self and
1985a7476a74SDmitry Karpeev     -fieldsplit_1_pc_type lsc which uses the least squares commutator to compute a preconditioner for the Schur complement.
1986fd1303e9SJungho Lee 
1987e69d4d44SBarry Smith     Level: intermediate
1988e69d4d44SBarry Smith 
19891d71051fSDmitry Karpeev .seealso: PCFieldSplitGetSchurPre(), PCFieldSplitGetSubKSP(), PCFIELDSPLIT, PCFieldSplitSetFields(), PCFieldSplitSchurPreType,
19901d71051fSDmitry Karpeev           MatSchurComplementSetAinvType(), PCLSC
1991e69d4d44SBarry Smith 
1992e69d4d44SBarry Smith @*/
199329f8a81cSJed Brown PetscErrorCode PCFieldSplitSetSchurPre(PC pc,PCFieldSplitSchurPreType ptype,Mat pre)
1994e69d4d44SBarry Smith {
19954ac538c5SBarry Smith   PetscErrorCode ierr;
1996e69d4d44SBarry Smith 
1997e69d4d44SBarry Smith   PetscFunctionBegin;
19980700a824SBarry Smith   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
199929f8a81cSJed Brown   ierr = PetscTryMethod(pc,"PCFieldSplitSetSchurPre_C",(PC,PCFieldSplitSchurPreType,Mat),(pc,ptype,pre));CHKERRQ(ierr);
2000e69d4d44SBarry Smith   PetscFunctionReturn(0);
2001e69d4d44SBarry Smith }
2002686bed4dSStefano Zampini 
200329f8a81cSJed Brown PetscErrorCode PCFieldSplitSchurPrecondition(PC pc,PCFieldSplitSchurPreType ptype,Mat pre) {return PCFieldSplitSetSchurPre(pc,ptype,pre);} /* Deprecated name */
2004e69d4d44SBarry Smith 
200537a82bf0SJed Brown /*@
200637a82bf0SJed Brown     PCFieldSplitGetSchurPre - For Schur complement fieldsplit, determine how the Schur complement will be
200729f8a81cSJed Brown     preconditioned.  See PCFieldSplitSetSchurPre() for details.
200837a82bf0SJed Brown 
200937a82bf0SJed Brown     Logically Collective on PC
201037a82bf0SJed Brown 
201137a82bf0SJed Brown     Input Parameters:
201237a82bf0SJed Brown .   pc      - the preconditioner context
201337a82bf0SJed Brown 
201437a82bf0SJed Brown     Output Parameters:
201537a82bf0SJed Brown +   ptype   - which matrix to use for preconditioning the Schur complement: PC_FIELDSPLIT_SCHUR_PRE_A11, PC_FIELDSPLIT_SCHUR_PRE_SELF, PC_FIELDSPLIT_PRE_USER
201637a82bf0SJed Brown -   userpre - matrix to use for preconditioning (with PC_FIELDSPLIT_PRE_USER), or NULL
201737a82bf0SJed Brown 
201837a82bf0SJed Brown     Level: intermediate
201937a82bf0SJed Brown 
202029f8a81cSJed Brown .seealso: PCFieldSplitSetSchurPre(), PCFieldSplitGetSubKSP(), PCFIELDSPLIT, PCFieldSplitSetFields(), PCFieldSplitSchurPreType, PCLSC
202137a82bf0SJed Brown 
202237a82bf0SJed Brown @*/
202337a82bf0SJed Brown PetscErrorCode PCFieldSplitGetSchurPre(PC pc,PCFieldSplitSchurPreType *ptype,Mat *pre)
202437a82bf0SJed Brown {
202537a82bf0SJed Brown   PetscErrorCode ierr;
202637a82bf0SJed Brown 
202737a82bf0SJed Brown   PetscFunctionBegin;
202837a82bf0SJed Brown   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
202937a82bf0SJed Brown   ierr = PetscUseMethod(pc,"PCFieldSplitGetSchurPre_C",(PC,PCFieldSplitSchurPreType*,Mat*),(pc,ptype,pre));CHKERRQ(ierr);
2030e69d4d44SBarry Smith   PetscFunctionReturn(0);
2031e69d4d44SBarry Smith }
2032e69d4d44SBarry Smith 
203345e7fc46SDmitry Karpeev /*@
2034470b340bSDmitry Karpeev     PCFieldSplitSchurGetS -  extract the MatSchurComplement object used by this PC in case it needs to be configured separately
203545e7fc46SDmitry Karpeev 
203645e7fc46SDmitry Karpeev     Not collective
203745e7fc46SDmitry Karpeev 
203845e7fc46SDmitry Karpeev     Input Parameter:
203945e7fc46SDmitry Karpeev .   pc      - the preconditioner context
204045e7fc46SDmitry Karpeev 
204145e7fc46SDmitry Karpeev     Output Parameter:
2042470b340bSDmitry Karpeev .   S       - the Schur complement matrix
204345e7fc46SDmitry Karpeev 
2044470b340bSDmitry Karpeev     Notes:
2045470b340bSDmitry Karpeev     This matrix should not be destroyed using MatDestroy(); rather, use PCFieldSplitSchurRestoreS().
204645e7fc46SDmitry Karpeev 
204745e7fc46SDmitry Karpeev     Level: advanced
204845e7fc46SDmitry Karpeev 
204929f8a81cSJed Brown .seealso: PCFieldSplitGetSubKSP(), PCFIELDSPLIT, PCFieldSplitSchurPreType, PCFieldSplitSetSchurPre(), MatSchurComplement, PCFieldSplitSchurRestoreS()
205045e7fc46SDmitry Karpeev 
205145e7fc46SDmitry Karpeev @*/
2052470b340bSDmitry Karpeev PetscErrorCode  PCFieldSplitSchurGetS(PC pc,Mat *S)
205345e7fc46SDmitry Karpeev {
205445e7fc46SDmitry Karpeev   PetscErrorCode ierr;
205545e7fc46SDmitry Karpeev   const char*    t;
205645e7fc46SDmitry Karpeev   PetscBool      isfs;
205745e7fc46SDmitry Karpeev   PC_FieldSplit  *jac;
205845e7fc46SDmitry Karpeev 
205945e7fc46SDmitry Karpeev   PetscFunctionBegin;
206045e7fc46SDmitry Karpeev   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
206145e7fc46SDmitry Karpeev   ierr = PetscObjectGetType((PetscObject)pc,&t);CHKERRQ(ierr);
206245e7fc46SDmitry Karpeev   ierr = PetscStrcmp(t,PCFIELDSPLIT,&isfs);CHKERRQ(ierr);
206345e7fc46SDmitry Karpeev   if (!isfs) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Expected PC of type PCFIELDSPLIT, got %s instead",t);
206445e7fc46SDmitry Karpeev   jac = (PC_FieldSplit*)pc->data;
2065470b340bSDmitry Karpeev   if (jac->type != PC_COMPOSITE_SCHUR) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Expected PCFIELDSPLIT of type SCHUR, got %D instead",jac->type);
2066470b340bSDmitry Karpeev   if (S) *S = jac->schur;
206745e7fc46SDmitry Karpeev   PetscFunctionReturn(0);
206845e7fc46SDmitry Karpeev }
206945e7fc46SDmitry Karpeev 
2070470b340bSDmitry Karpeev /*@
2071470b340bSDmitry Karpeev     PCFieldSplitSchurRestoreS -  restores the MatSchurComplement object used by this PC
2072470b340bSDmitry Karpeev 
2073470b340bSDmitry Karpeev     Not collective
2074470b340bSDmitry Karpeev 
2075470b340bSDmitry Karpeev     Input Parameters:
2076470b340bSDmitry Karpeev +   pc      - the preconditioner context
2077470b340bSDmitry Karpeev .   S       - the Schur complement matrix
2078470b340bSDmitry Karpeev 
2079470b340bSDmitry Karpeev     Level: advanced
2080470b340bSDmitry Karpeev 
208129f8a81cSJed Brown .seealso: PCFieldSplitGetSubKSP(), PCFIELDSPLIT, PCFieldSplitSchurPreType, PCFieldSplitSetSchurPre(), MatSchurComplement, PCFieldSplitSchurGetS()
2082470b340bSDmitry Karpeev 
2083470b340bSDmitry Karpeev @*/
2084bca69d2bSDmitry Karpeev PetscErrorCode  PCFieldSplitSchurRestoreS(PC pc,Mat *S)
2085470b340bSDmitry Karpeev {
2086470b340bSDmitry Karpeev   PetscErrorCode ierr;
2087470b340bSDmitry Karpeev   const char*    t;
2088470b340bSDmitry Karpeev   PetscBool      isfs;
2089470b340bSDmitry Karpeev   PC_FieldSplit  *jac;
2090470b340bSDmitry Karpeev 
2091470b340bSDmitry Karpeev   PetscFunctionBegin;
2092470b340bSDmitry Karpeev   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
2093470b340bSDmitry Karpeev   ierr = PetscObjectGetType((PetscObject)pc,&t);CHKERRQ(ierr);
2094470b340bSDmitry Karpeev   ierr = PetscStrcmp(t,PCFIELDSPLIT,&isfs);CHKERRQ(ierr);
2095470b340bSDmitry Karpeev   if (!isfs) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Expected PC of type PCFIELDSPLIT, got %s instead",t);
2096470b340bSDmitry Karpeev   jac = (PC_FieldSplit*)pc->data;
2097470b340bSDmitry Karpeev   if (jac->type != PC_COMPOSITE_SCHUR) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Expected PCFIELDSPLIT of type SCHUR, got %D instead",jac->type);
2098bca69d2bSDmitry Karpeev   if (!S || *S != jac->schur) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"MatSchurComplement restored is not the same as gotten");
2099470b340bSDmitry Karpeev   PetscFunctionReturn(0);
2100470b340bSDmitry Karpeev }
2101470b340bSDmitry Karpeev 
2102470b340bSDmitry Karpeev 
210329f8a81cSJed Brown static PetscErrorCode  PCFieldSplitSetSchurPre_FieldSplit(PC pc,PCFieldSplitSchurPreType ptype,Mat pre)
2104e69d4d44SBarry Smith {
2105e69d4d44SBarry Smith   PC_FieldSplit  *jac = (PC_FieldSplit*)pc->data;
2106084e4875SJed Brown   PetscErrorCode ierr;
2107e69d4d44SBarry Smith 
2108e69d4d44SBarry Smith   PetscFunctionBegin;
2109084e4875SJed Brown   jac->schurpre = ptype;
2110a7476a74SDmitry Karpeev   if (ptype == PC_FIELDSPLIT_SCHUR_PRE_USER && pre) {
21116bf464f9SBarry Smith     ierr            = MatDestroy(&jac->schur_user);CHKERRQ(ierr);
2112084e4875SJed Brown     jac->schur_user = pre;
2113084e4875SJed Brown     ierr            = PetscObjectReference((PetscObject)jac->schur_user);CHKERRQ(ierr);
2114084e4875SJed Brown   }
2115e69d4d44SBarry Smith   PetscFunctionReturn(0);
2116e69d4d44SBarry Smith }
2117e69d4d44SBarry Smith 
211837a82bf0SJed Brown static PetscErrorCode  PCFieldSplitGetSchurPre_FieldSplit(PC pc,PCFieldSplitSchurPreType *ptype,Mat *pre)
211937a82bf0SJed Brown {
212037a82bf0SJed Brown   PC_FieldSplit  *jac = (PC_FieldSplit*)pc->data;
212137a82bf0SJed Brown 
212237a82bf0SJed Brown   PetscFunctionBegin;
212337a82bf0SJed Brown   *ptype = jac->schurpre;
212437a82bf0SJed Brown   *pre   = jac->schur_user;
212537a82bf0SJed Brown   PetscFunctionReturn(0);
212637a82bf0SJed Brown }
212737a82bf0SJed Brown 
2128ab1df9f5SJed Brown /*@
21290ffb0e17SBarry Smith     PCFieldSplitSetSchurFactType -  sets which blocks of the approximate block factorization to retain in the preconditioner
2130ab1df9f5SJed Brown 
2131ab1df9f5SJed Brown     Collective on PC
2132ab1df9f5SJed Brown 
2133ab1df9f5SJed Brown     Input Parameters:
2134ab1df9f5SJed Brown +   pc  - the preconditioner context
2135c9c6ffaaSJed Brown -   ftype - which blocks of factorization to retain, PC_FIELDSPLIT_SCHUR_FACT_FULL is default
2136ab1df9f5SJed Brown 
2137ab1df9f5SJed Brown     Options Database:
2138c9c6ffaaSJed Brown .     -pc_fieldsplit_schur_fact_type <diag,lower,upper,full> default is full
2139ab1df9f5SJed Brown 
2140ab1df9f5SJed Brown 
2141ab1df9f5SJed Brown     Level: intermediate
2142ab1df9f5SJed Brown 
2143ab1df9f5SJed Brown     Notes:
2144ab1df9f5SJed Brown     The FULL factorization is
2145ab1df9f5SJed Brown 
21460ffb0e17SBarry Smith $   (A   B)  = (1       0) (A   0) (1  Ainv*B)  = L D U
21470ffb0e17SBarry Smith $   (C   E)    (C*Ainv  1) (0   S) (0     1  )
2148ab1df9f5SJed Brown 
21490ffb0e17SBarry Smith     where S = E - C*Ainv*B. In practice, the full factorization is applied via block triangular solves with the grouping L*(D*U). UPPER uses D*U, LOWER uses L*D,
2150c096484dSStefano Zampini     and DIAG is the diagonal part with the sign of S flipped (because this makes the preconditioner positive definite for many formulations, thus allowing the use of KSPMINRES). Sign flipping of S can be turned off with PCFieldSplitSetSchurScale().
2151ab1df9f5SJed Brown 
21520ffb0e17SBarry Smith $    If A and S are solved exactly
21530ffb0e17SBarry Smith $      *) FULL factorization is a direct solver.
21540ffb0e17SBarry Smith $      *) The preconditioned operator with LOWER or UPPER has all eigenvalues equal to 1 and minimal polynomial of degree 2, so KSPGMRES converges in 2 iterations.
21550ffb0e17SBarry Smith $      *) With DIAG, the preconditioned operator has three distinct nonzero eigenvalues and minimal polynomial of degree at most 4, so KSPGMRES converges in at most 4 iterations.
2156ab1df9f5SJed Brown 
21570ffb0e17SBarry Smith     If the iteration count is very low, consider using KSPFGMRES or KSPGCR which can use one less preconditioner
21580ffb0e17SBarry Smith     application in this case. Note that the preconditioned operator may be highly non-normal, so such fast convergence may not be observed in practice.
21590ffb0e17SBarry Smith 
21600ffb0e17SBarry Smith     For symmetric problems in which A is positive definite and S is negative definite, DIAG can be used with KSPMINRES.
21610ffb0e17SBarry Smith 
21620ffb0e17SBarry Smith     Note that a flexible method like KSPFGMRES or KSPGCR must be used if the fieldsplit preconditioner is nonlinear (e.g. a few iterations of a Krylov method is used to solve with A or S).
2163ab1df9f5SJed Brown 
2164ab1df9f5SJed Brown     References:
216596a0c994SBarry Smith +   1. - Murphy, Golub, and Wathen, A note on preconditioning indefinite linear systems, SIAM J. Sci. Comput., 21 (2000).
216696a0c994SBarry Smith -   2. - Ipsen, A note on preconditioning nonsymmetric matrices, SIAM J. Sci. Comput., 23 (2001).
2167ab1df9f5SJed Brown 
2168c096484dSStefano Zampini .seealso: PCFieldSplitGetSubKSP(), PCFIELDSPLIT, PCFieldSplitSetFields(), PCFieldSplitSchurPreType, PCFieldSplitSetSchurScale()
2169ab1df9f5SJed Brown @*/
2170c9c6ffaaSJed Brown PetscErrorCode  PCFieldSplitSetSchurFactType(PC pc,PCFieldSplitSchurFactType ftype)
2171ab1df9f5SJed Brown {
2172ab1df9f5SJed Brown   PetscErrorCode ierr;
2173ab1df9f5SJed Brown 
2174ab1df9f5SJed Brown   PetscFunctionBegin;
2175ab1df9f5SJed Brown   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
2176c9c6ffaaSJed Brown   ierr = PetscTryMethod(pc,"PCFieldSplitSetSchurFactType_C",(PC,PCFieldSplitSchurFactType),(pc,ftype));CHKERRQ(ierr);
2177ab1df9f5SJed Brown   PetscFunctionReturn(0);
2178ab1df9f5SJed Brown }
2179ab1df9f5SJed Brown 
21801e6b0712SBarry Smith static PetscErrorCode PCFieldSplitSetSchurFactType_FieldSplit(PC pc,PCFieldSplitSchurFactType ftype)
2181ab1df9f5SJed Brown {
2182ab1df9f5SJed Brown   PC_FieldSplit *jac = (PC_FieldSplit*)pc->data;
2183ab1df9f5SJed Brown 
2184ab1df9f5SJed Brown   PetscFunctionBegin;
2185ab1df9f5SJed Brown   jac->schurfactorization = ftype;
2186ab1df9f5SJed Brown   PetscFunctionReturn(0);
2187ab1df9f5SJed Brown }
2188ab1df9f5SJed Brown 
2189c096484dSStefano Zampini /*@
2190c096484dSStefano Zampini     PCFieldSplitSetSchurScale -  Controls the sign flip of S for PC_FIELDSPLIT_SCHUR_FACT_DIAG.
2191c096484dSStefano Zampini 
2192c096484dSStefano Zampini     Collective on PC
2193c096484dSStefano Zampini 
2194c096484dSStefano Zampini     Input Parameters:
2195c096484dSStefano Zampini +   pc    - the preconditioner context
2196c096484dSStefano Zampini -   scale - scaling factor for the Schur complement
2197c096484dSStefano Zampini 
2198c096484dSStefano Zampini     Options Database:
2199c096484dSStefano Zampini .     -pc_fieldsplit_schur_scale - default is -1.0
2200c096484dSStefano Zampini 
2201c096484dSStefano Zampini     Level: intermediate
2202c096484dSStefano Zampini 
2203c096484dSStefano Zampini .seealso: PCFIELDSPLIT, PCFieldSplitSetFields(), PCFieldSplitSchurFactType, PCFieldSplitSetSchurScale()
2204c096484dSStefano Zampini @*/
2205c096484dSStefano Zampini PetscErrorCode PCFieldSplitSetSchurScale(PC pc,PetscScalar scale)
2206c096484dSStefano Zampini {
2207c096484dSStefano Zampini   PetscErrorCode ierr;
2208c096484dSStefano Zampini 
2209c096484dSStefano Zampini   PetscFunctionBegin;
2210c096484dSStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
2211c096484dSStefano Zampini   PetscValidLogicalCollectiveScalar(pc,scale,2);
2212c096484dSStefano Zampini   ierr = PetscTryMethod(pc,"PCFieldSplitSetSchurScale_C",(PC,PetscScalar),(pc,scale));CHKERRQ(ierr);
2213c096484dSStefano Zampini   PetscFunctionReturn(0);
2214c096484dSStefano Zampini }
2215c096484dSStefano Zampini 
2216c096484dSStefano Zampini static PetscErrorCode PCFieldSplitSetSchurScale_FieldSplit(PC pc,PetscScalar scale)
2217c096484dSStefano Zampini {
2218c096484dSStefano Zampini   PC_FieldSplit *jac = (PC_FieldSplit*)pc->data;
2219c096484dSStefano Zampini 
2220c096484dSStefano Zampini   PetscFunctionBegin;
2221c096484dSStefano Zampini   jac->schurscale = scale;
2222c096484dSStefano Zampini   PetscFunctionReturn(0);
2223c096484dSStefano Zampini }
2224c096484dSStefano Zampini 
222530ad9308SMatthew Knepley /*@C
22268c03b21aSDmitry Karpeev    PCFieldSplitGetSchurBlocks - Gets all matrix blocks for the Schur complement
222730ad9308SMatthew Knepley 
222830ad9308SMatthew Knepley    Collective on KSP
222930ad9308SMatthew Knepley 
223030ad9308SMatthew Knepley    Input Parameter:
223130ad9308SMatthew Knepley .  pc - the preconditioner context
223230ad9308SMatthew Knepley 
223330ad9308SMatthew Knepley    Output Parameters:
2234a04f6461SBarry Smith +  A00 - the (0,0) block
2235a04f6461SBarry Smith .  A01 - the (0,1) block
2236a04f6461SBarry Smith .  A10 - the (1,0) block
2237a04f6461SBarry Smith -  A11 - the (1,1) block
223830ad9308SMatthew Knepley 
223930ad9308SMatthew Knepley    Level: advanced
224030ad9308SMatthew Knepley 
224130ad9308SMatthew Knepley .seealso: PCFIELDSPLIT
224230ad9308SMatthew Knepley @*/
2243a04f6461SBarry Smith PetscErrorCode  PCFieldSplitGetSchurBlocks(PC pc,Mat *A00,Mat *A01,Mat *A10, Mat *A11)
224430ad9308SMatthew Knepley {
224530ad9308SMatthew Knepley   PC_FieldSplit *jac = (PC_FieldSplit*) pc->data;
224630ad9308SMatthew Knepley 
224730ad9308SMatthew Knepley   PetscFunctionBegin;
22480700a824SBarry Smith   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
2249ce94432eSBarry Smith   if (jac->type != PC_COMPOSITE_SCHUR) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONG, "FieldSplit is not using a Schur complement approach.");
2250a04f6461SBarry Smith   if (A00) *A00 = jac->pmat[0];
2251a04f6461SBarry Smith   if (A01) *A01 = jac->B;
2252a04f6461SBarry Smith   if (A10) *A10 = jac->C;
2253a04f6461SBarry Smith   if (A11) *A11 = jac->pmat[1];
225430ad9308SMatthew Knepley   PetscFunctionReturn(0);
225530ad9308SMatthew Knepley }
225630ad9308SMatthew Knepley 
22571e6b0712SBarry Smith static PetscErrorCode  PCFieldSplitSetType_FieldSplit(PC pc,PCCompositeType type)
225879416396SBarry Smith {
225979416396SBarry Smith   PC_FieldSplit  *jac = (PC_FieldSplit*)pc->data;
2260e69d4d44SBarry Smith   PetscErrorCode ierr;
226179416396SBarry Smith 
226279416396SBarry Smith   PetscFunctionBegin;
226379416396SBarry Smith   jac->type = type;
22643b224e63SBarry Smith   if (type == PC_COMPOSITE_SCHUR) {
22653b224e63SBarry Smith     pc->ops->apply = PCApply_FieldSplit_Schur;
22663b224e63SBarry Smith     pc->ops->view  = PCView_FieldSplit_Schur;
22672fa5cd67SKarl Rupp 
2268bdf89e91SBarry Smith     ierr = PetscObjectComposeFunction((PetscObject)pc,"PCFieldSplitGetSubKSP_C",PCFieldSplitGetSubKSP_FieldSplit_Schur);CHKERRQ(ierr);
226929f8a81cSJed Brown     ierr = PetscObjectComposeFunction((PetscObject)pc,"PCFieldSplitSetSchurPre_C",PCFieldSplitSetSchurPre_FieldSplit);CHKERRQ(ierr);
227037a82bf0SJed Brown     ierr = PetscObjectComposeFunction((PetscObject)pc,"PCFieldSplitGetSchurPre_C",PCFieldSplitGetSchurPre_FieldSplit);CHKERRQ(ierr);
2271bdf89e91SBarry Smith     ierr = PetscObjectComposeFunction((PetscObject)pc,"PCFieldSplitSetSchurFactType_C",PCFieldSplitSetSchurFactType_FieldSplit);CHKERRQ(ierr);
2272c096484dSStefano Zampini     ierr = PetscObjectComposeFunction((PetscObject)pc,"PCFieldSplitSetSchurScale_C",PCFieldSplitSetSchurScale_FieldSplit);CHKERRQ(ierr);
2273e69d4d44SBarry Smith 
22743b224e63SBarry Smith   } else {
22753b224e63SBarry Smith     pc->ops->apply = PCApply_FieldSplit;
22763b224e63SBarry Smith     pc->ops->view  = PCView_FieldSplit;
22772fa5cd67SKarl Rupp 
2278bdf89e91SBarry Smith     ierr = PetscObjectComposeFunction((PetscObject)pc,"PCFieldSplitGetSubKSP_C",PCFieldSplitGetSubKSP_FieldSplit);CHKERRQ(ierr);
227929f8a81cSJed Brown     ierr = PetscObjectComposeFunction((PetscObject)pc,"PCFieldSplitSetSchurPre_C",0);CHKERRQ(ierr);
228037a82bf0SJed Brown     ierr = PetscObjectComposeFunction((PetscObject)pc,"PCFieldSplitGetSchurPre_C",0);CHKERRQ(ierr);
2281bdf89e91SBarry Smith     ierr = PetscObjectComposeFunction((PetscObject)pc,"PCFieldSplitSetSchurFactType_C",0);CHKERRQ(ierr);
2282c096484dSStefano Zampini     ierr = PetscObjectComposeFunction((PetscObject)pc,"PCFieldSplitSetSchurScale_C",0);CHKERRQ(ierr);
22833b224e63SBarry Smith   }
228479416396SBarry Smith   PetscFunctionReturn(0);
228579416396SBarry Smith }
228679416396SBarry Smith 
22871e6b0712SBarry Smith static PetscErrorCode  PCFieldSplitSetBlockSize_FieldSplit(PC pc,PetscInt bs)
228851f519a2SBarry Smith {
228951f519a2SBarry Smith   PC_FieldSplit *jac = (PC_FieldSplit*)pc->data;
229051f519a2SBarry Smith 
229151f519a2SBarry Smith   PetscFunctionBegin;
2292ce94432eSBarry Smith   if (bs < 1) SETERRQ1(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_OUTOFRANGE,"Blocksize must be positive, you gave %D",bs);
2293ce94432eSBarry Smith   if (jac->bs > 0 && jac->bs != bs) SETERRQ2(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONGSTATE,"Cannot change fieldsplit blocksize from %D to %D after it has been set",jac->bs,bs);
229451f519a2SBarry Smith   jac->bs = bs;
229551f519a2SBarry Smith   PetscFunctionReturn(0);
229651f519a2SBarry Smith }
229751f519a2SBarry Smith 
2298bc08b0f1SBarry Smith /*@
229979416396SBarry Smith    PCFieldSplitSetType - Sets the type of fieldsplit preconditioner.
230079416396SBarry Smith 
230179416396SBarry Smith    Collective on PC
230279416396SBarry Smith 
230379416396SBarry Smith    Input Parameter:
230479416396SBarry Smith .  pc - the preconditioner context
230581540f2fSBarry Smith .  type - PC_COMPOSITE_ADDITIVE, PC_COMPOSITE_MULTIPLICATIVE (default), PC_COMPOSITE_SYMMETRIC_MULTIPLICATIVE, PC_COMPOSITE_SPECIAL, PC_COMPOSITE_SCHUR
230679416396SBarry Smith 
230779416396SBarry Smith    Options Database Key:
2308a4efd8eaSMatthew Knepley .  -pc_fieldsplit_type <type: one of multiplicative, additive, symmetric_multiplicative, special, schur> - Sets fieldsplit preconditioner type
230979416396SBarry Smith 
2310b02e2d75SMatthew G Knepley    Level: Intermediate
231179416396SBarry Smith 
231279416396SBarry Smith .keywords: PC, set, type, composite preconditioner, additive, multiplicative
231379416396SBarry Smith 
231479416396SBarry Smith .seealso: PCCompositeSetType()
231579416396SBarry Smith 
231679416396SBarry Smith @*/
23177087cfbeSBarry Smith PetscErrorCode  PCFieldSplitSetType(PC pc,PCCompositeType type)
231879416396SBarry Smith {
23194ac538c5SBarry Smith   PetscErrorCode ierr;
232079416396SBarry Smith 
232179416396SBarry Smith   PetscFunctionBegin;
23220700a824SBarry Smith   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
23234ac538c5SBarry Smith   ierr = PetscTryMethod(pc,"PCFieldSplitSetType_C",(PC,PCCompositeType),(pc,type));CHKERRQ(ierr);
232479416396SBarry Smith   PetscFunctionReturn(0);
232579416396SBarry Smith }
232679416396SBarry Smith 
2327b02e2d75SMatthew G Knepley /*@
2328b02e2d75SMatthew G Knepley   PCFieldSplitGetType - Gets the type of fieldsplit preconditioner.
2329b02e2d75SMatthew G Knepley 
2330b02e2d75SMatthew G Knepley   Not collective
2331b02e2d75SMatthew G Knepley 
2332b02e2d75SMatthew G Knepley   Input Parameter:
2333b02e2d75SMatthew G Knepley . pc - the preconditioner context
2334b02e2d75SMatthew G Knepley 
2335b02e2d75SMatthew G Knepley   Output Parameter:
2336b02e2d75SMatthew G Knepley . type - PC_COMPOSITE_ADDITIVE, PC_COMPOSITE_MULTIPLICATIVE (default), PC_COMPOSITE_SYMMETRIC_MULTIPLICATIVE, PC_COMPOSITE_SPECIAL, PC_COMPOSITE_SCHUR
2337b02e2d75SMatthew G Knepley 
2338b02e2d75SMatthew G Knepley   Level: Intermediate
2339b02e2d75SMatthew G Knepley 
2340b02e2d75SMatthew G Knepley .keywords: PC, set, type, composite preconditioner, additive, multiplicative
2341b02e2d75SMatthew G Knepley .seealso: PCCompositeSetType()
2342b02e2d75SMatthew G Knepley @*/
2343b02e2d75SMatthew G Knepley PetscErrorCode PCFieldSplitGetType(PC pc, PCCompositeType *type)
2344b02e2d75SMatthew G Knepley {
2345b02e2d75SMatthew G Knepley   PC_FieldSplit *jac = (PC_FieldSplit*) pc->data;
2346b02e2d75SMatthew G Knepley 
2347b02e2d75SMatthew G Knepley   PetscFunctionBegin;
2348b02e2d75SMatthew G Knepley   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
2349b02e2d75SMatthew G Knepley   PetscValidIntPointer(type,2);
2350b02e2d75SMatthew G Knepley   *type = jac->type;
2351b02e2d75SMatthew G Knepley   PetscFunctionReturn(0);
2352b02e2d75SMatthew G Knepley }
2353b02e2d75SMatthew G Knepley 
23544ab8060aSDmitry Karpeev /*@
23554ab8060aSDmitry Karpeev    PCFieldSplitSetDMSplits - Flags whether DMCreateFieldDecomposition() should be used to define the splits, whenever possible.
23564ab8060aSDmitry Karpeev 
23574ab8060aSDmitry Karpeev    Logically Collective
23584ab8060aSDmitry Karpeev 
23594ab8060aSDmitry Karpeev    Input Parameters:
23604ab8060aSDmitry Karpeev +  pc   - the preconditioner context
23614ab8060aSDmitry Karpeev -  flg  - boolean indicating whether to use field splits defined by the DM
23624ab8060aSDmitry Karpeev 
23634ab8060aSDmitry Karpeev    Options Database Key:
23644ab8060aSDmitry Karpeev .  -pc_fieldsplit_dm_splits
23654ab8060aSDmitry Karpeev 
23664ab8060aSDmitry Karpeev    Level: Intermediate
23674ab8060aSDmitry Karpeev 
23684ab8060aSDmitry Karpeev .keywords: PC, DM, composite preconditioner, additive, multiplicative
23694ab8060aSDmitry Karpeev 
23704ab8060aSDmitry Karpeev .seealso: PCFieldSplitGetDMSplits()
23714ab8060aSDmitry Karpeev 
23724ab8060aSDmitry Karpeev @*/
23734ab8060aSDmitry Karpeev PetscErrorCode  PCFieldSplitSetDMSplits(PC pc,PetscBool flg)
23744ab8060aSDmitry Karpeev {
23754ab8060aSDmitry Karpeev   PC_FieldSplit  *jac = (PC_FieldSplit*)pc->data;
23764ab8060aSDmitry Karpeev   PetscBool      isfs;
23774ab8060aSDmitry Karpeev   PetscErrorCode ierr;
23784ab8060aSDmitry Karpeev 
23794ab8060aSDmitry Karpeev   PetscFunctionBegin;
23804ab8060aSDmitry Karpeev   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
23814ab8060aSDmitry Karpeev   PetscValidLogicalCollectiveBool(pc,flg,2);
23824ab8060aSDmitry Karpeev   ierr = PetscObjectTypeCompare((PetscObject)pc,PCFIELDSPLIT,&isfs);CHKERRQ(ierr);
23834ab8060aSDmitry Karpeev   if (isfs) {
23844ab8060aSDmitry Karpeev     jac->dm_splits = flg;
23854ab8060aSDmitry Karpeev   }
23864ab8060aSDmitry Karpeev   PetscFunctionReturn(0);
23874ab8060aSDmitry Karpeev }
23884ab8060aSDmitry Karpeev 
23894ab8060aSDmitry Karpeev 
23904ab8060aSDmitry Karpeev /*@
23914ab8060aSDmitry Karpeev    PCFieldSplitGetDMSplits - Returns flag indicating whether DMCreateFieldDecomposition() should be used to define the splits, whenever possible.
23924ab8060aSDmitry Karpeev 
23934ab8060aSDmitry Karpeev    Logically Collective
23944ab8060aSDmitry Karpeev 
23954ab8060aSDmitry Karpeev    Input Parameter:
23964ab8060aSDmitry Karpeev .  pc   - the preconditioner context
23974ab8060aSDmitry Karpeev 
23984ab8060aSDmitry Karpeev    Output Parameter:
23994ab8060aSDmitry Karpeev .  flg  - boolean indicating whether to use field splits defined by the DM
24004ab8060aSDmitry Karpeev 
24014ab8060aSDmitry Karpeev    Level: Intermediate
24024ab8060aSDmitry Karpeev 
24034ab8060aSDmitry Karpeev .keywords: PC, DM, composite preconditioner, additive, multiplicative
24044ab8060aSDmitry Karpeev 
24054ab8060aSDmitry Karpeev .seealso: PCFieldSplitSetDMSplits()
24064ab8060aSDmitry Karpeev 
24074ab8060aSDmitry Karpeev @*/
24084ab8060aSDmitry Karpeev PetscErrorCode  PCFieldSplitGetDMSplits(PC pc,PetscBool* flg)
24094ab8060aSDmitry Karpeev {
24104ab8060aSDmitry Karpeev   PC_FieldSplit  *jac = (PC_FieldSplit*)pc->data;
24114ab8060aSDmitry Karpeev   PetscBool      isfs;
24124ab8060aSDmitry Karpeev   PetscErrorCode ierr;
24134ab8060aSDmitry Karpeev 
24144ab8060aSDmitry Karpeev   PetscFunctionBegin;
24154ab8060aSDmitry Karpeev   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
24164ab8060aSDmitry Karpeev   PetscValidPointer(flg,2);
24174ab8060aSDmitry Karpeev   ierr = PetscObjectTypeCompare((PetscObject)pc,PCFIELDSPLIT,&isfs);CHKERRQ(ierr);
24184ab8060aSDmitry Karpeev   if (isfs) {
24194ab8060aSDmitry Karpeev     if(flg) *flg = jac->dm_splits;
24204ab8060aSDmitry Karpeev   }
24214ab8060aSDmitry Karpeev   PetscFunctionReturn(0);
24224ab8060aSDmitry Karpeev }
24234ab8060aSDmitry Karpeev 
24247b752e3dSPatrick Sanan /*@
24257b752e3dSPatrick Sanan    PCFieldSplitGetDetectSaddlePoint - Returns flag indicating whether PCFieldSplit will attempt to automatically determine fields based on zero diagonal entries.
24267b752e3dSPatrick Sanan 
24277b752e3dSPatrick Sanan    Logically Collective
24287b752e3dSPatrick Sanan 
24297b752e3dSPatrick Sanan    Input Parameter:
24307b752e3dSPatrick Sanan .  pc   - the preconditioner context
24317b752e3dSPatrick Sanan 
24327b752e3dSPatrick Sanan    Output Parameter:
24337b752e3dSPatrick Sanan .  flg  - boolean indicating whether to detect fields or not
24347b752e3dSPatrick Sanan 
24357b752e3dSPatrick Sanan    Level: Intermediate
24367b752e3dSPatrick Sanan 
24377b752e3dSPatrick Sanan .seealso: PCFIELDSPLIT, PCFieldSplitSetDetectSaddlePoint()
24387b752e3dSPatrick Sanan 
24397b752e3dSPatrick Sanan @*/
24407b752e3dSPatrick Sanan PetscErrorCode PCFieldSplitGetDetectSaddlePoint(PC pc,PetscBool *flg)
24417b752e3dSPatrick Sanan {
24427b752e3dSPatrick Sanan   PC_FieldSplit *jac = (PC_FieldSplit*)pc->data;
24437b752e3dSPatrick Sanan 
24447b752e3dSPatrick Sanan   PetscFunctionBegin;
24457b752e3dSPatrick Sanan   *flg = jac->detect;
24467b752e3dSPatrick Sanan   PetscFunctionReturn(0);
24477b752e3dSPatrick Sanan }
24487b752e3dSPatrick Sanan 
24497b752e3dSPatrick Sanan /*@
24507b752e3dSPatrick Sanan    PCFieldSplitSetDetectSaddlePoint - Sets flag indicating whether PCFieldSplit will attempt to automatically determine fields based on zero diagonal entries.
24517b752e3dSPatrick Sanan 
24527b752e3dSPatrick Sanan    Logically Collective
24537b752e3dSPatrick Sanan 
24547b752e3dSPatrick Sanan    Notes:
24557b752e3dSPatrick Sanan    Also sets the split type to PC_COMPOSITE_SCHUR (see PCFieldSplitSetType()) and the Schur preconditioner type to PC_FIELDSPLIT_SCHUR_PRE_SELF (see PCFieldSplitSetSchurPre()).
24567b752e3dSPatrick Sanan 
24577b752e3dSPatrick Sanan    Input Parameter:
24587b752e3dSPatrick Sanan .  pc   - the preconditioner context
24597b752e3dSPatrick Sanan 
24607b752e3dSPatrick Sanan    Output Parameter:
24617b752e3dSPatrick Sanan .  flg  - boolean indicating whether to detect fields or not
24627b752e3dSPatrick Sanan 
24637b752e3dSPatrick Sanan    Options Database Key:
24647b752e3dSPatrick Sanan .  -pc_fieldsplit_detect_saddle_point
24657b752e3dSPatrick Sanan 
24667b752e3dSPatrick Sanan    Level: Intermediate
24677b752e3dSPatrick Sanan 
24687b752e3dSPatrick Sanan .seealso: PCFIELDSPLIT, PCFieldSplitSetDetectSaddlePoint(), PCFieldSplitSetType(), PCFieldSplitSetSchurPre()
24697b752e3dSPatrick Sanan 
24707b752e3dSPatrick Sanan @*/
24717b752e3dSPatrick Sanan PetscErrorCode PCFieldSplitSetDetectSaddlePoint(PC pc,PetscBool flg)
24727b752e3dSPatrick Sanan {
24737b752e3dSPatrick Sanan   PC_FieldSplit  *jac = (PC_FieldSplit*)pc->data;
24747b752e3dSPatrick Sanan   PetscErrorCode ierr;
24757b752e3dSPatrick Sanan 
24767b752e3dSPatrick Sanan   PetscFunctionBegin;
24777b752e3dSPatrick Sanan   jac->detect = flg;
24787b752e3dSPatrick Sanan   if (jac->detect) {
24797b752e3dSPatrick Sanan     ierr = PCFieldSplitSetType(pc,PC_COMPOSITE_SCHUR);CHKERRQ(ierr);
24807b752e3dSPatrick Sanan     ierr = PCFieldSplitSetSchurPre(pc,PC_FIELDSPLIT_SCHUR_PRE_SELF,NULL);CHKERRQ(ierr);
24817b752e3dSPatrick Sanan   }
24827b752e3dSPatrick Sanan   PetscFunctionReturn(0);
24837b752e3dSPatrick Sanan }
24847b752e3dSPatrick Sanan 
24850971522cSBarry Smith /* -------------------------------------------------------------------------------------*/
24860971522cSBarry Smith /*MC
2487a8c7a070SBarry Smith    PCFIELDSPLIT - Preconditioner created by combining separate preconditioners for individual
2488a04f6461SBarry Smith                   fields or groups of fields. See the users manual section "Solving Block Matrices" for more details.
24890971522cSBarry Smith 
2490edf189efSBarry Smith      To set options on the solvers for each block append -fieldsplit_ to all the PC
2491edf189efSBarry Smith         options database keys. For example, -fieldsplit_pc_type ilu -fieldsplit_pc_factor_levels 1
24920971522cSBarry Smith 
2493a8c7a070SBarry Smith      To set the options on the solvers separate for each block call PCFieldSplitGetSubKSP()
249469a612a9SBarry Smith          and set the options directly on the resulting KSP object
24950971522cSBarry Smith 
24960971522cSBarry Smith    Level: intermediate
24970971522cSBarry Smith 
249879416396SBarry Smith    Options Database Keys:
249981540f2fSBarry Smith +   -pc_fieldsplit_%d_fields <a,b,..> - indicates the fields to be used in the %d'th split
250081540f2fSBarry Smith .   -pc_fieldsplit_default - automatically add any fields to additional splits that have not
250181540f2fSBarry Smith                               been supplied explicitly by -pc_fieldsplit_%d_fields
250281540f2fSBarry Smith .   -pc_fieldsplit_block_size <bs> - size of block that defines fields (i.e. there are bs fields)
25030f188ba9SJed Brown .   -pc_fieldsplit_type <additive,multiplicative,symmetric_multiplicative,schur> - type of relaxation or factorization splitting
2504a6a584a2SBarry Smith .   -pc_fieldsplit_schur_precondition <self,selfp,user,a11,full> - default is a11; see PCFieldSplitSetSchurPre()
25057b752e3dSPatrick Sanan .   -pc_fieldsplit_detect_saddle_point - automatically finds rows with zero diagonal and uses Schur complement with no preconditioner as the solver
250679416396SBarry Smith 
25075d4c12cdSJungho Lee -    Options prefix for inner solvers when using Schur complement preconditioner are -fieldsplit_0_ and -fieldsplit_1_
25085d4c12cdSJungho Lee      for all other solvers they are -fieldsplit_%d_ for the dth field, use -fieldsplit_ for all fields
25095d4c12cdSJungho Lee 
2510c8a0d604SMatthew G Knepley    Notes:
2511c8a0d604SMatthew G Knepley     Use PCFieldSplitSetFields() to set fields defined by "strided" entries and PCFieldSplitSetIS()
2512d32f9abdSBarry Smith      to define a field by an arbitrary collection of entries.
2513d32f9abdSBarry Smith 
2514d32f9abdSBarry Smith       If no fields are set the default is used. The fields are defined by entries strided by bs,
2515d32f9abdSBarry Smith       beginning at 0 then 1, etc to bs-1. The block size can be set with PCFieldSplitSetBlockSize(),
2516d32f9abdSBarry Smith       if this is not called the block size defaults to the blocksize of the second matrix passed
2517d32f9abdSBarry Smith       to KSPSetOperators()/PCSetOperators().
2518d32f9abdSBarry Smith 
2519c8a0d604SMatthew G Knepley $     For the Schur complement preconditioner if J = ( A00 A01 )
2520c8a0d604SMatthew G Knepley $                                                    ( A10 A11 )
2521c8a0d604SMatthew G Knepley $     the preconditioner using full factorization is
252213b05affSJed Brown $              ( I   -ksp(A00) A01 ) ( inv(A00)     0  ) (     I          0  )
2523c8a0d604SMatthew G Knepley $              ( 0         I       ) (   0      ksp(S) ) ( -A10 ksp(A00)  I  )
252413b05affSJed Brown      where the action of inv(A00) is applied using the KSP solver with prefix -fieldsplit_0_.  S is the Schur complement
252513b05affSJed Brown $              S = A11 - A10 ksp(A00) A01
252613b05affSJed Brown      which is usually dense and not stored explicitly.  The action of ksp(S) is computed using the KSP solver with prefix -fieldsplit_splitname_ (where splitname was given
2527686bed4dSStefano Zampini      in providing the SECOND split or 1 if not give). For PCFieldSplitGetSubKSP() when field number is 0,
2528c8a0d604SMatthew G Knepley      it returns the KSP associated with -fieldsplit_0_ while field number 1 gives -fieldsplit_1_ KSP. By default
2529a6a584a2SBarry Smith      A11 is used to construct a preconditioner for S, use PCFieldSplitSetSchurPre() for all the possible ways to construct the preconditioner for S.
25301d71051fSDmitry Karpeev 
2531a7476a74SDmitry Karpeev      The factorization type is set using -pc_fieldsplit_schur_fact_type <diag, lower, upper, full>. The full is shown above,
25325668aaf4SBarry Smith      diag gives
2533c8a0d604SMatthew G Knepley $              ( inv(A00)     0   )
2534c8a0d604SMatthew G Knepley $              (   0      -ksp(S) )
2535c096484dSStefano Zampini      note that slightly counter intuitively there is a negative in front of the ksp(S) so that the preconditioner is positive definite. For SPD matrices J, the sign flip
2536c096484dSStefano Zampini      can be turned off with PCFieldSplitSetSchurScale() or by command line -pc_fieldsplit_schur_scale 1.0. The lower factorization is the inverse of
2537c8a0d604SMatthew G Knepley $              (  A00   0 )
2538c8a0d604SMatthew G Knepley $              (  A10   S )
2539c8a0d604SMatthew G Knepley      where the inverses of A00 and S are applied using KSPs. The upper factorization is the inverse of
2540c8a0d604SMatthew G Knepley $              ( A00 A01 )
2541c8a0d604SMatthew G Knepley $              (  0   S  )
2542c8a0d604SMatthew G Knepley      where again the inverses of A00 and S are applied using KSPs.
2543e69d4d44SBarry Smith 
2544edf189efSBarry Smith      If only one set of indices (one IS) is provided with PCFieldSplitSetIS() then the complement of that IS
2545edf189efSBarry Smith      is used automatically for a second block.
2546edf189efSBarry Smith 
2547ff218e97SBarry Smith      The fieldsplit preconditioner cannot currently be used with the BAIJ or SBAIJ data formats if the blocksize is larger than 1.
2548ff218e97SBarry Smith      Generally it should be used with the AIJ format.
2549ff218e97SBarry Smith 
2550ff218e97SBarry Smith      The forms of these preconditioners are closely related if not identical to forms derived as "Distributive Iterations", see,
2551ff218e97SBarry Smith      for example, page 294 in "Principles of Computational Fluid Dynamics" by Pieter Wesseling. Note that one can also use PCFIELDSPLIT
2552ff218e97SBarry Smith      inside a smoother resulting in "Distributive Smoothers".
25530716a85fSBarry Smith 
2554a541d17aSBarry Smith    Concepts: physics based preconditioners, block preconditioners
25550971522cSBarry Smith 
25563bc631e0SBarry Smith    There is a nice discussion of block preconditioners in
25573bc631e0SBarry Smith 
25583bc631e0SBarry Smith [El08] A taxonomy and comparison of parallel block multi-level preconditioners for the incompressible Navier-Stokes equations
25593bc631e0SBarry Smith        Howard Elman, V.E. Howle, John Shadid, Robert Shuttleworth, Ray Tuminaro, Journal of Computational Physics 227 (2008) 1790--1808
25603bc631e0SBarry Smith        http://chess.cs.umd.edu/~elman/papers/tax.pdf
25613bc631e0SBarry Smith 
25624d308398SBarry Smith    The Constrained Pressure Preconditioner (CPR) can be implemented using PCCOMPOSITE with PCGALERKIN. CPR first solves an R A P subsystem, updates the
25634d308398SBarry Smith    residual on all variables (PCCompositeSetType(pc,PC_COMPOSITE_MULTIPLICATIVE)), and then applies a simple ILU like preconditioner on all the variables.
2564a6a584a2SBarry Smith 
25657e8cb189SBarry Smith .seealso:  PCCreate(), PCSetType(), PCType (for list of available types), PC, Block_Preconditioners, PCLSC,
2566285fb4e2SStefano Zampini            PCFieldSplitGetSubKSP(), PCFieldSplitSchurGetSubKSP(), PCFieldSplitSetFields(), PCFieldSplitSetType(), PCFieldSplitSetIS(), PCFieldSplitSetSchurPre(),
25677b752e3dSPatrick Sanan           MatSchurComplementSetAinvType(), PCFieldSplitSetSchurScale(),
25687b752e3dSPatrick Sanan           PCFieldSplitSetDetectSaddlePoint()
25690971522cSBarry Smith M*/
25700971522cSBarry Smith 
25718cc058d9SJed Brown PETSC_EXTERN PetscErrorCode PCCreate_FieldSplit(PC pc)
25720971522cSBarry Smith {
25730971522cSBarry Smith   PetscErrorCode ierr;
25740971522cSBarry Smith   PC_FieldSplit  *jac;
25750971522cSBarry Smith 
25760971522cSBarry Smith   PetscFunctionBegin;
2577b00a9115SJed Brown   ierr = PetscNewLog(pc,&jac);CHKERRQ(ierr);
25782fa5cd67SKarl Rupp 
25790971522cSBarry Smith   jac->bs                 = -1;
25800971522cSBarry Smith   jac->nsplits            = 0;
25813e197d65SBarry Smith   jac->type               = PC_COMPOSITE_MULTIPLICATIVE;
2582e6cab6aaSJed Brown   jac->schurpre           = PC_FIELDSPLIT_SCHUR_PRE_USER; /* Try user preconditioner first, fall back on diagonal */
2583c9c6ffaaSJed Brown   jac->schurfactorization = PC_FIELDSPLIT_SCHUR_FACT_FULL;
2584c096484dSStefano Zampini   jac->schurscale         = -1.0;
2585fbe7908bSJed Brown   jac->dm_splits          = PETSC_TRUE;
25867b752e3dSPatrick Sanan   jac->detect             = PETSC_FALSE;
258751f519a2SBarry Smith 
25880971522cSBarry Smith   pc->data = (void*)jac;
25890971522cSBarry Smith 
25900971522cSBarry Smith   pc->ops->apply           = PCApply_FieldSplit;
2591421e10b8SBarry Smith   pc->ops->applytranspose  = PCApplyTranspose_FieldSplit;
25920971522cSBarry Smith   pc->ops->setup           = PCSetUp_FieldSplit;
2593574deadeSBarry Smith   pc->ops->reset           = PCReset_FieldSplit;
25940971522cSBarry Smith   pc->ops->destroy         = PCDestroy_FieldSplit;
25950971522cSBarry Smith   pc->ops->setfromoptions  = PCSetFromOptions_FieldSplit;
25960971522cSBarry Smith   pc->ops->view            = PCView_FieldSplit;
25970971522cSBarry Smith   pc->ops->applyrichardson = 0;
25980971522cSBarry Smith 
2599285fb4e2SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCFieldSplitSchurGetSubKSP_C",PCFieldSplitSchurGetSubKSP_FieldSplit);CHKERRQ(ierr);
2600bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCFieldSplitGetSubKSP_C",PCFieldSplitGetSubKSP_FieldSplit);CHKERRQ(ierr);
2601bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCFieldSplitSetFields_C",PCFieldSplitSetFields_FieldSplit);CHKERRQ(ierr);
2602bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCFieldSplitSetIS_C",PCFieldSplitSetIS_FieldSplit);CHKERRQ(ierr);
2603bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCFieldSplitSetType_C",PCFieldSplitSetType_FieldSplit);CHKERRQ(ierr);
2604bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCFieldSplitSetBlockSize_C",PCFieldSplitSetBlockSize_FieldSplit);CHKERRQ(ierr);
26056dbb499eSCian Wilson   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCFieldSplitRestrictIS_C",PCFieldSplitRestrictIS_FieldSplit);CHKERRQ(ierr);
26060971522cSBarry Smith   PetscFunctionReturn(0);
26070971522cSBarry Smith }
2608