xref: /petsc/src/ksp/pc/impls/fieldsplit/fieldsplit.c (revision 5ddf11f8e001baeb79e0c2e10012b003f03bd2a5)
1af0996ceSBarry Smith #include <petsc/private/pcimpl.h>     /*I "petscpc.h" I*/
2a80b646eSBarry Smith #include <petsc/private/kspimpl.h>    /*  This is needed to provide the appropriate PETSC_EXTERN for KSP_Solve_FS ....*/
31e25c274SJed Brown #include <petscdm.h>
40971522cSBarry Smith 
50a545947SLisandro Dalcin const char *const PCFieldSplitSchurPreTypes[] = {"SELF","SELFP","A11","USER","FULL","PCFieldSplitSchurPreType","PC_FIELDSPLIT_SCHUR_PRE_",NULL};
60a545947SLisandro Dalcin const char *const PCFieldSplitSchurFactTypes[] = {"DIAG","LOWER","UPPER","FULL","PCFieldSplitSchurFactType","PC_FIELDSPLIT_SCHUR_FACT_",NULL};
7c5d2311dSJed Brown 
89df09d43SBarry 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;
99df09d43SBarry Smith 
100971522cSBarry Smith typedef struct _PC_FieldSplitLink *PC_FieldSplitLink;
110971522cSBarry Smith struct _PC_FieldSplitLink {
1269a612a9SBarry Smith   KSP               ksp;
13443836d0SMatthew G Knepley   Vec               x,y,z;
14db4c96c1SJed Brown   char              *splitname;
150971522cSBarry Smith   PetscInt          nfields;
165d4c12cdSJungho Lee   PetscInt          *fields,*fields_col;
171b9fc7fcSBarry Smith   VecScatter        sctx;
18f5f0d762SBarry Smith   IS                is,is_col;
1951f519a2SBarry Smith   PC_FieldSplitLink next,previous;
209df09d43SBarry Smith   PetscLogEvent     event;
21*5ddf11f8SNicolas Barnafi 
22*5ddf11f8SNicolas Barnafi   /* Used only when setting coordinates with PCSetCoordinates */
23*5ddf11f8SNicolas Barnafi   PetscInt dim;
24*5ddf11f8SNicolas Barnafi   PetscInt ndofs;
25*5ddf11f8SNicolas Barnafi   PetscReal *coords;
260971522cSBarry Smith };
270971522cSBarry Smith 
280971522cSBarry Smith typedef struct {
2968dd23aaSBarry Smith   PCCompositeType type;
30ace3abfcSBarry Smith   PetscBool       defaultsplit;                    /* Flag for a system with a set of 'k' scalar fields with the same layout (and bs = k) */
31ace3abfcSBarry Smith   PetscBool       splitdefined;                    /* Flag is set after the splits have been defined, to prevent more splits from being added */
3230ad9308SMatthew Knepley   PetscInt        bs;                              /* Block size for IS and Mat structures */
3330ad9308SMatthew Knepley   PetscInt        nsplits;                         /* Number of field divisions defined */
3479416396SBarry Smith   Vec             *x,*y,w1,w2;
35519d70e2SJed Brown   Mat             *mat;                            /* The diagonal block for each split */
36519d70e2SJed Brown   Mat             *pmat;                           /* The preconditioning diagonal block for each split */
3730ad9308SMatthew Knepley   Mat             *Afield;                         /* The rows of the matrix associated with each split */
38ace3abfcSBarry Smith   PetscBool       issetup;
392fa5cd67SKarl Rupp 
4030ad9308SMatthew Knepley   /* Only used when Schur complement preconditioning is used */
4130ad9308SMatthew Knepley   Mat                       B;                     /* The (0,1) block */
4230ad9308SMatthew Knepley   Mat                       C;                     /* The (1,0) block */
43443836d0SMatthew G Knepley   Mat                       schur;                 /* The Schur complement S = A11 - A10 A00^{-1} A01, the KSP here, kspinner, is H_1 in [El08] */
44a7476a74SDmitry Karpeev   Mat                       schurp;                /* Assembled approximation to S built by MatSchurComplement to be used as a preconditioning matrix when solving with S */
45084e4875SJed Brown   Mat                       schur_user;            /* User-provided preconditioning matrix for the Schur complement */
46084e4875SJed Brown   PCFieldSplitSchurPreType  schurpre;              /* Determines which preconditioning matrix is used for the Schur complement */
47c9c6ffaaSJed Brown   PCFieldSplitSchurFactType schurfactorization;
4830ad9308SMatthew Knepley   KSP                       kspschur;              /* The solver for S */
49443836d0SMatthew G Knepley   KSP                       kspupper;              /* The solver for A in the upper diagonal part of the factorization (H_2 in [El08]) */
50c096484dSStefano Zampini   PetscScalar               schurscale;            /* Scaling factor for the Schur complement solution with DIAG factorization */
51c096484dSStefano Zampini 
52a51937d4SCarola Kruse   /* Only used when Golub-Kahan bidiagonalization preconditioning is used */
53a51937d4SCarola Kruse   Mat                       H;                     /* The modified matrix H = A00 + nu*A01*A01'              */
54a51937d4SCarola Kruse   PetscReal                 gkbtol;                /* Stopping tolerance for lower bound estimate            */
55a51937d4SCarola Kruse   PetscInt                  gkbdelay;              /* The delay window for the stopping criterion            */
56a51937d4SCarola Kruse   PetscReal                 gkbnu;                 /* Parameter for augmented Lagrangian H = A + nu*A01*A01' */
57a51937d4SCarola Kruse   PetscInt                  gkbmaxit;              /* Maximum number of iterations for outer loop            */
58de482cd7SCarola Kruse   PetscBool                 gkbmonitor;            /* Monitor for gkb iterations and the lower bound error   */
59de482cd7SCarola Kruse   PetscViewer               gkbviewer;             /* Viewer context for gkbmonitor                          */
60e071a0a4SCarola Kruse   Vec                       u,v,d,Hu;              /* Work vectors for the GKB algorithm                     */
61e071a0a4SCarola Kruse   PetscScalar               *vecz;                 /* Contains intermediate values, eg for lower bound       */
62a51937d4SCarola Kruse 
6397bbdb24SBarry Smith   PC_FieldSplitLink         head;
646dbb499eSCian Wilson   PetscBool                 isrestrict;             /* indicates PCFieldSplitRestrictIS() has been last called on this object, hack */
65c1570756SJed Brown   PetscBool                 suboptionsset;          /* Indicates that the KSPSetFromOptions() has been called on the sub-KSPs */
664ab8060aSDmitry Karpeev   PetscBool                 dm_splits;              /* Whether to use DMCreateFieldDecomposition() whenever possible */
67c84da90fSDmitry Karpeev   PetscBool                 diag_use_amat;          /* Whether to extract diagonal matrix blocks from Amat, rather than Pmat (weaker than -pc_use_amat) */
68c84da90fSDmitry Karpeev   PetscBool                 offdiag_use_amat;       /* Whether to extract off-diagonal matrix blocks from Amat, rather than Pmat (weaker than -pc_use_amat) */
697b752e3dSPatrick Sanan   PetscBool                 detect;                 /* Whether to form 2-way split by finding zero diagonal entries */
70*5ddf11f8SNicolas Barnafi   PetscBool                 coordinates_set;        /* Whether PCSetCoordinates has been called */
710971522cSBarry Smith } PC_FieldSplit;
720971522cSBarry Smith 
7316913363SBarry Smith /*
7495452b02SPatrick Sanan     Notes:
7595452b02SPatrick Sanan     there is no particular reason that pmat, x, and y are stored as arrays in PC_FieldSplit instead of
7616913363SBarry Smith    inside PC_FieldSplitLink, just historical. If you want to be able to add new fields after already using the
7716913363SBarry Smith    PC you could change this.
7816913363SBarry Smith */
79084e4875SJed Brown 
80e6cab6aaSJed Brown /* This helper is so that setting a user-provided preconditioning matrix is orthogonal to choosing to use it.  This way the
81084e4875SJed Brown * application-provided FormJacobian can provide this matrix without interfering with the user's (command-line) choices. */
82084e4875SJed Brown static Mat FieldSplitSchurPre(PC_FieldSplit *jac)
83084e4875SJed Brown {
84084e4875SJed Brown   switch (jac->schurpre) {
85084e4875SJed Brown   case PC_FIELDSPLIT_SCHUR_PRE_SELF: return jac->schur;
86a7476a74SDmitry Karpeev   case PC_FIELDSPLIT_SCHUR_PRE_SELFP: return jac->schurp;
87e87fab1bSBarry Smith   case PC_FIELDSPLIT_SCHUR_PRE_A11: return jac->pmat[1];
88e74569cdSMatthew G. Knepley   case PC_FIELDSPLIT_SCHUR_PRE_FULL: /* We calculate this and store it in schur_user */
89084e4875SJed Brown   case PC_FIELDSPLIT_SCHUR_PRE_USER: /* Use a user-provided matrix if it is given, otherwise diagonal block */
90084e4875SJed Brown   default:
91084e4875SJed Brown     return jac->schur_user ? jac->schur_user : jac->pmat[1];
92084e4875SJed Brown   }
93084e4875SJed Brown }
94084e4875SJed Brown 
959804daf3SBarry Smith #include <petscdraw.h>
960971522cSBarry Smith static PetscErrorCode PCView_FieldSplit(PC pc,PetscViewer viewer)
970971522cSBarry Smith {
980971522cSBarry Smith   PC_FieldSplit     *jac = (PC_FieldSplit*)pc->data;
990971522cSBarry Smith   PetscErrorCode    ierr;
100d9884438SBarry Smith   PetscBool         iascii,isdraw;
1010971522cSBarry Smith   PetscInt          i,j;
1025a9f2f41SSatish Balay   PC_FieldSplitLink ilink = jac->head;
1030971522cSBarry Smith 
1040971522cSBarry Smith   PetscFunctionBegin;
105251f4c67SDmitry Karpeev   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
106d9884438SBarry Smith   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERDRAW,&isdraw);CHKERRQ(ierr);
1070971522cSBarry Smith   if (iascii) {
1082c9966d7SBarry Smith     if (jac->bs > 0) {
10951f519a2SBarry Smith       ierr = PetscViewerASCIIPrintf(viewer,"  FieldSplit with %s composition: total splits = %D, blocksize = %D\n",PCCompositeTypes[jac->type],jac->nsplits,jac->bs);CHKERRQ(ierr);
1102c9966d7SBarry Smith     } else {
1112c9966d7SBarry Smith       ierr = PetscViewerASCIIPrintf(viewer,"  FieldSplit with %s composition: total splits = %D\n",PCCompositeTypes[jac->type],jac->nsplits);CHKERRQ(ierr);
1122c9966d7SBarry Smith     }
113f5236f50SJed Brown     if (pc->useAmat) {
114f5236f50SJed Brown       ierr = PetscViewerASCIIPrintf(viewer,"  using Amat (not Pmat) as operator for blocks\n");CHKERRQ(ierr);
115a3df900dSMatthew G Knepley     }
116c84da90fSDmitry Karpeev     if (jac->diag_use_amat) {
117c84da90fSDmitry Karpeev       ierr = PetscViewerASCIIPrintf(viewer,"  using Amat (not Pmat) as operator for diagonal blocks\n");CHKERRQ(ierr);
118c84da90fSDmitry Karpeev     }
119c84da90fSDmitry Karpeev     if (jac->offdiag_use_amat) {
120c84da90fSDmitry Karpeev       ierr = PetscViewerASCIIPrintf(viewer,"  using Amat (not Pmat) as operator for off-diagonal blocks\n");CHKERRQ(ierr);
121c84da90fSDmitry Karpeev     }
12269a612a9SBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  Solver info for each split is in the following KSP objects:\n");CHKERRQ(ierr);
1230971522cSBarry Smith     for (i=0; i<jac->nsplits; i++) {
1241ab39975SBarry Smith       if (ilink->fields) {
1250971522cSBarry Smith         ierr = PetscViewerASCIIPrintf(viewer,"Split number %D Fields ",i);CHKERRQ(ierr);
12679416396SBarry Smith         ierr = PetscViewerASCIIUseTabs(viewer,PETSC_FALSE);CHKERRQ(ierr);
1275a9f2f41SSatish Balay         for (j=0; j<ilink->nfields; j++) {
12879416396SBarry Smith           if (j > 0) {
12979416396SBarry Smith             ierr = PetscViewerASCIIPrintf(viewer,",");CHKERRQ(ierr);
13079416396SBarry Smith           }
1315a9f2f41SSatish Balay           ierr = PetscViewerASCIIPrintf(viewer," %D",ilink->fields[j]);CHKERRQ(ierr);
1320971522cSBarry Smith         }
1330971522cSBarry Smith         ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr);
13479416396SBarry Smith         ierr = PetscViewerASCIIUseTabs(viewer,PETSC_TRUE);CHKERRQ(ierr);
1351ab39975SBarry Smith       } else {
1361ab39975SBarry Smith         ierr = PetscViewerASCIIPrintf(viewer,"Split number %D Defined by IS\n",i);CHKERRQ(ierr);
1371ab39975SBarry Smith       }
1385a9f2f41SSatish Balay       ierr  = KSPView(ilink->ksp,viewer);CHKERRQ(ierr);
1395a9f2f41SSatish Balay       ilink = ilink->next;
1400971522cSBarry Smith     }
1412fa5cd67SKarl Rupp   }
1422fa5cd67SKarl Rupp 
1432fa5cd67SKarl Rupp  if (isdraw) {
144d9884438SBarry Smith     PetscDraw draw;
145d9884438SBarry Smith     PetscReal x,y,w,wd;
146d9884438SBarry Smith 
147d9884438SBarry Smith     ierr = PetscViewerDrawGetDraw(viewer,0,&draw);CHKERRQ(ierr);
148d9884438SBarry Smith     ierr = PetscDrawGetCurrentPoint(draw,&x,&y);CHKERRQ(ierr);
149d9884438SBarry Smith     w    = 2*PetscMin(1.0 - x,x);
150d9884438SBarry Smith     wd   = w/(jac->nsplits + 1);
151d9884438SBarry Smith     x    = x - wd*(jac->nsplits-1)/2.0;
152d9884438SBarry Smith     for (i=0; i<jac->nsplits; i++) {
153d9884438SBarry Smith       ierr  = PetscDrawPushCurrentPoint(draw,x,y);CHKERRQ(ierr);
154d9884438SBarry Smith       ierr  = KSPView(ilink->ksp,viewer);CHKERRQ(ierr);
155d9884438SBarry Smith       ierr  = PetscDrawPopCurrentPoint(draw);CHKERRQ(ierr);
156d9884438SBarry Smith       x    += wd;
157d9884438SBarry Smith       ilink = ilink->next;
158d9884438SBarry Smith     }
1590971522cSBarry Smith   }
1600971522cSBarry Smith   PetscFunctionReturn(0);
1610971522cSBarry Smith }
1620971522cSBarry Smith 
1633b224e63SBarry Smith static PetscErrorCode PCView_FieldSplit_Schur(PC pc,PetscViewer viewer)
1643b224e63SBarry Smith {
1653b224e63SBarry Smith   PC_FieldSplit              *jac = (PC_FieldSplit*)pc->data;
1663b224e63SBarry Smith   PetscErrorCode             ierr;
1674996c5bdSBarry Smith   PetscBool                  iascii,isdraw;
1683b224e63SBarry Smith   PetscInt                   i,j;
1693b224e63SBarry Smith   PC_FieldSplitLink          ilink = jac->head;
170a9908d51SBarry Smith   MatSchurComplementAinvType atype;
1713b224e63SBarry Smith 
1723b224e63SBarry Smith   PetscFunctionBegin;
173251f4c67SDmitry Karpeev   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
1744996c5bdSBarry Smith   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERDRAW,&isdraw);CHKERRQ(ierr);
1753b224e63SBarry Smith   if (iascii) {
1762c9966d7SBarry Smith     if (jac->bs > 0) {
177c9c6ffaaSJed Brown       ierr = PetscViewerASCIIPrintf(viewer,"  FieldSplit with Schur preconditioner, blocksize = %D, factorization %s\n",jac->bs,PCFieldSplitSchurFactTypes[jac->schurfactorization]);CHKERRQ(ierr);
1782c9966d7SBarry Smith     } else {
1792c9966d7SBarry Smith       ierr = PetscViewerASCIIPrintf(viewer,"  FieldSplit with Schur preconditioner, factorization %s\n",PCFieldSplitSchurFactTypes[jac->schurfactorization]);CHKERRQ(ierr);
1802c9966d7SBarry Smith     }
181f5236f50SJed Brown     if (pc->useAmat) {
182f5236f50SJed Brown       ierr = PetscViewerASCIIPrintf(viewer,"  using Amat (not Pmat) as operator for blocks\n");CHKERRQ(ierr);
183a3df900dSMatthew G Knepley     }
1843e8b8b31SMatthew G Knepley     switch (jac->schurpre) {
1853e8b8b31SMatthew G Knepley     case PC_FIELDSPLIT_SCHUR_PRE_SELF:
186a9908d51SBarry Smith       ierr = PetscViewerASCIIPrintf(viewer,"  Preconditioner for the Schur complement formed from S itself\n");CHKERRQ(ierr);
187a9908d51SBarry Smith       break;
188a7476a74SDmitry Karpeev     case PC_FIELDSPLIT_SCHUR_PRE_SELFP:
189a9908d51SBarry Smith       ierr = MatSchurComplementGetAinvType(jac->schur,&atype);CHKERRQ(ierr);
190d0a9c1a2SBarry 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;
191e87fab1bSBarry Smith     case PC_FIELDSPLIT_SCHUR_PRE_A11:
192a9908d51SBarry Smith       ierr = PetscViewerASCIIPrintf(viewer,"  Preconditioner for the Schur complement formed from A11\n");CHKERRQ(ierr);
193a9908d51SBarry Smith       break;
194e74569cdSMatthew G. Knepley     case PC_FIELDSPLIT_SCHUR_PRE_FULL:
195a9908d51SBarry Smith       ierr = PetscViewerASCIIPrintf(viewer,"  Preconditioner for the Schur complement formed from the exact Schur complement\n");CHKERRQ(ierr);
196a9908d51SBarry Smith       break;
1973e8b8b31SMatthew G Knepley     case PC_FIELDSPLIT_SCHUR_PRE_USER:
1983e8b8b31SMatthew G Knepley       if (jac->schur_user) {
1993e8b8b31SMatthew G Knepley         ierr = PetscViewerASCIIPrintf(viewer,"  Preconditioner for the Schur complement formed from user provided matrix\n");CHKERRQ(ierr);
2003e8b8b31SMatthew G Knepley       } else {
201e87fab1bSBarry Smith         ierr = PetscViewerASCIIPrintf(viewer,"  Preconditioner for the Schur complement formed from A11\n");CHKERRQ(ierr);
2023e8b8b31SMatthew G Knepley       }
2033e8b8b31SMatthew G Knepley       break;
2043e8b8b31SMatthew G Knepley     default:
20598921bdaSJacob Faibussowitsch       SETERRQ(PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_OUTOFRANGE, "Invalid Schur preconditioning type: %d", jac->schurpre);
2063e8b8b31SMatthew G Knepley     }
2073b224e63SBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  Split info:\n");CHKERRQ(ierr);
2083b224e63SBarry Smith     ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr);
2093b224e63SBarry Smith     for (i=0; i<jac->nsplits; i++) {
2103b224e63SBarry Smith       if (ilink->fields) {
2113b224e63SBarry Smith         ierr = PetscViewerASCIIPrintf(viewer,"Split number %D Fields ",i);CHKERRQ(ierr);
2123b224e63SBarry Smith         ierr = PetscViewerASCIIUseTabs(viewer,PETSC_FALSE);CHKERRQ(ierr);
2133b224e63SBarry Smith         for (j=0; j<ilink->nfields; j++) {
2143b224e63SBarry Smith           if (j > 0) {
2153b224e63SBarry Smith             ierr = PetscViewerASCIIPrintf(viewer,",");CHKERRQ(ierr);
2163b224e63SBarry Smith           }
2173b224e63SBarry Smith           ierr = PetscViewerASCIIPrintf(viewer," %D",ilink->fields[j]);CHKERRQ(ierr);
2183b224e63SBarry Smith         }
2193b224e63SBarry Smith         ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr);
2203b224e63SBarry Smith         ierr = PetscViewerASCIIUseTabs(viewer,PETSC_TRUE);CHKERRQ(ierr);
2213b224e63SBarry Smith       } else {
2223b224e63SBarry Smith         ierr = PetscViewerASCIIPrintf(viewer,"Split number %D Defined by IS\n",i);CHKERRQ(ierr);
2233b224e63SBarry Smith       }
2243b224e63SBarry Smith       ilink = ilink->next;
2253b224e63SBarry Smith     }
226435f959eSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"KSP solver for A00 block\n");CHKERRQ(ierr);
2273b224e63SBarry Smith     ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr);
22806de4afeSJed Brown     if (jac->head) {
229443836d0SMatthew G Knepley       ierr = KSPView(jac->head->ksp,viewer);CHKERRQ(ierr);
23006de4afeSJed Brown     } else  {ierr = PetscViewerASCIIPrintf(viewer,"  not yet available\n");CHKERRQ(ierr);}
2313b224e63SBarry Smith     ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr);
23206de4afeSJed Brown     if (jac->head && jac->kspupper != jac->head->ksp) {
233443836d0SMatthew G Knepley       ierr = PetscViewerASCIIPrintf(viewer,"KSP solver for upper A00 in upper triangular factor \n");CHKERRQ(ierr);
234443836d0SMatthew G Knepley       ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr);
235b2750c55SJed Brown       if (jac->kspupper) {ierr = KSPView(jac->kspupper,viewer);CHKERRQ(ierr);}
236b2750c55SJed Brown       else {ierr = PetscViewerASCIIPrintf(viewer,"  not yet available\n");CHKERRQ(ierr);}
237443836d0SMatthew G Knepley       ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr);
238443836d0SMatthew G Knepley     }
239435f959eSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"KSP solver for S = A11 - A10 inv(A00) A01 \n");CHKERRQ(ierr);
2403b224e63SBarry Smith     ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr);
24112cae6f2SJed Brown     if (jac->kspschur) {
2423b224e63SBarry Smith       ierr = KSPView(jac->kspschur,viewer);CHKERRQ(ierr);
24312cae6f2SJed Brown     } else {
24412cae6f2SJed Brown       ierr = PetscViewerASCIIPrintf(viewer,"  not yet available\n");CHKERRQ(ierr);
24512cae6f2SJed Brown     }
2463b224e63SBarry Smith     ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr);
2473b224e63SBarry Smith     ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr);
24806de4afeSJed Brown   } else if (isdraw && jac->head) {
2494996c5bdSBarry Smith     PetscDraw draw;
2504996c5bdSBarry Smith     PetscReal x,y,w,wd,h;
2514996c5bdSBarry Smith     PetscInt  cnt = 2;
2524996c5bdSBarry Smith     char      str[32];
2534996c5bdSBarry Smith 
2544996c5bdSBarry Smith     ierr = PetscViewerDrawGetDraw(viewer,0,&draw);CHKERRQ(ierr);
2554996c5bdSBarry Smith     ierr = PetscDrawGetCurrentPoint(draw,&x,&y);CHKERRQ(ierr);
256c74581afSBarry Smith     if (jac->kspupper != jac->head->ksp) cnt++;
257c74581afSBarry Smith     w  = 2*PetscMin(1.0 - x,x);
258c74581afSBarry Smith     wd = w/(cnt + 1);
259c74581afSBarry Smith 
2604996c5bdSBarry Smith     ierr = PetscSNPrintf(str,32,"Schur fact. %s",PCFieldSplitSchurFactTypes[jac->schurfactorization]);CHKERRQ(ierr);
26151fa3d41SBarry Smith     ierr = PetscDrawStringBoxed(draw,x,y,PETSC_DRAW_RED,PETSC_DRAW_BLACK,str,NULL,&h);CHKERRQ(ierr);
2624996c5bdSBarry Smith     y   -= h;
2634996c5bdSBarry Smith     if (jac->schurpre == PC_FIELDSPLIT_SCHUR_PRE_USER &&  !jac->schur_user) {
264e87fab1bSBarry Smith       ierr = PetscSNPrintf(str,32,"Prec. for Schur from %s",PCFieldSplitSchurPreTypes[PC_FIELDSPLIT_SCHUR_PRE_A11]);CHKERRQ(ierr);
2653b224e63SBarry Smith     } else {
2664996c5bdSBarry Smith       ierr = PetscSNPrintf(str,32,"Prec. for Schur from %s",PCFieldSplitSchurPreTypes[jac->schurpre]);CHKERRQ(ierr);
2674996c5bdSBarry Smith     }
26851fa3d41SBarry Smith     ierr = PetscDrawStringBoxed(draw,x+wd*(cnt-1)/2.0,y,PETSC_DRAW_RED,PETSC_DRAW_BLACK,str,NULL,&h);CHKERRQ(ierr);
2694996c5bdSBarry Smith     y   -= h;
2704996c5bdSBarry Smith     x    = x - wd*(cnt-1)/2.0;
2714996c5bdSBarry Smith 
2724996c5bdSBarry Smith     ierr = PetscDrawPushCurrentPoint(draw,x,y);CHKERRQ(ierr);
2734996c5bdSBarry Smith     ierr = KSPView(jac->head->ksp,viewer);CHKERRQ(ierr);
2744996c5bdSBarry Smith     ierr = PetscDrawPopCurrentPoint(draw);CHKERRQ(ierr);
2754996c5bdSBarry Smith     if (jac->kspupper != jac->head->ksp) {
2764996c5bdSBarry Smith       x   += wd;
2774996c5bdSBarry Smith       ierr = PetscDrawPushCurrentPoint(draw,x,y);CHKERRQ(ierr);
2784996c5bdSBarry Smith       ierr = KSPView(jac->kspupper,viewer);CHKERRQ(ierr);
2794996c5bdSBarry Smith       ierr = PetscDrawPopCurrentPoint(draw);CHKERRQ(ierr);
2804996c5bdSBarry Smith     }
2814996c5bdSBarry Smith     x   += wd;
2824996c5bdSBarry Smith     ierr = PetscDrawPushCurrentPoint(draw,x,y);CHKERRQ(ierr);
2834996c5bdSBarry Smith     ierr = KSPView(jac->kspschur,viewer);CHKERRQ(ierr);
2844996c5bdSBarry Smith     ierr = PetscDrawPopCurrentPoint(draw);CHKERRQ(ierr);
2853b224e63SBarry Smith   }
2863b224e63SBarry Smith   PetscFunctionReturn(0);
2873b224e63SBarry Smith }
2883b224e63SBarry Smith 
289a51937d4SCarola Kruse static PetscErrorCode PCView_FieldSplit_GKB(PC pc,PetscViewer viewer)
290a51937d4SCarola Kruse {
291a51937d4SCarola Kruse   PC_FieldSplit     *jac = (PC_FieldSplit*)pc->data;
292a51937d4SCarola Kruse   PetscErrorCode    ierr;
293a51937d4SCarola Kruse   PetscBool         iascii,isdraw;
294a51937d4SCarola Kruse   PetscInt          i,j;
295a51937d4SCarola Kruse   PC_FieldSplitLink ilink = jac->head;
296a51937d4SCarola Kruse 
297a51937d4SCarola Kruse   PetscFunctionBegin;
298a51937d4SCarola Kruse   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
299a51937d4SCarola Kruse   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERDRAW,&isdraw);CHKERRQ(ierr);
300a51937d4SCarola Kruse   if (iascii) {
301a51937d4SCarola Kruse     if (jac->bs > 0) {
302a51937d4SCarola Kruse       ierr = PetscViewerASCIIPrintf(viewer,"  FieldSplit with %s composition: total splits = %D, blocksize = %D\n",PCCompositeTypes[jac->type],jac->nsplits,jac->bs);CHKERRQ(ierr);
303a51937d4SCarola Kruse     } else {
304a51937d4SCarola Kruse       ierr = PetscViewerASCIIPrintf(viewer,"  FieldSplit with %s composition: total splits = %D\n",PCCompositeTypes[jac->type],jac->nsplits);CHKERRQ(ierr);
305a51937d4SCarola Kruse     }
306a51937d4SCarola Kruse     if (pc->useAmat) {
307a51937d4SCarola Kruse       ierr = PetscViewerASCIIPrintf(viewer,"  using Amat (not Pmat) as operator for blocks\n");CHKERRQ(ierr);
308a51937d4SCarola Kruse     }
309a51937d4SCarola Kruse     if (jac->diag_use_amat) {
310a51937d4SCarola Kruse       ierr = PetscViewerASCIIPrintf(viewer,"  using Amat (not Pmat) as operator for diagonal blocks\n");CHKERRQ(ierr);
311a51937d4SCarola Kruse     }
312a51937d4SCarola Kruse     if (jac->offdiag_use_amat) {
313a51937d4SCarola Kruse       ierr = PetscViewerASCIIPrintf(viewer,"  using Amat (not Pmat) as operator for off-diagonal blocks\n");CHKERRQ(ierr);
314a51937d4SCarola Kruse     }
315a51937d4SCarola Kruse 
316a51937d4SCarola Kruse     ierr = PetscViewerASCIIPrintf(viewer,"  Stopping tolerance=%.1e, delay in error estimate=%D, maximum iterations=%D\n",jac->gkbtol,jac->gkbdelay,jac->gkbmaxit);CHKERRQ(ierr);
317a51937d4SCarola Kruse     ierr = PetscViewerASCIIPrintf(viewer,"  Solver info for H = A00 + nu*A01*A01' matrix:\n");CHKERRQ(ierr);
318a51937d4SCarola Kruse     ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr);
319a51937d4SCarola Kruse 
320a51937d4SCarola Kruse     if (ilink->fields) {
321a51937d4SCarola Kruse       ierr = PetscViewerASCIIPrintf(viewer,"Split number %D Fields ",0);CHKERRQ(ierr);
322a51937d4SCarola Kruse       ierr = PetscViewerASCIIUseTabs(viewer,PETSC_FALSE);CHKERRQ(ierr);
323a51937d4SCarola Kruse       for (j=0; j<ilink->nfields; j++) {
324a51937d4SCarola Kruse         if (j > 0) {
325a51937d4SCarola Kruse           ierr = PetscViewerASCIIPrintf(viewer,",");CHKERRQ(ierr);
326a51937d4SCarola Kruse         }
327a51937d4SCarola Kruse         ierr = PetscViewerASCIIPrintf(viewer," %D",ilink->fields[j]);CHKERRQ(ierr);
328a51937d4SCarola Kruse       }
329a51937d4SCarola Kruse       ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr);
330a51937d4SCarola Kruse       ierr = PetscViewerASCIIUseTabs(viewer,PETSC_TRUE);CHKERRQ(ierr);
331a51937d4SCarola Kruse     } else {
332a51937d4SCarola Kruse         ierr = PetscViewerASCIIPrintf(viewer,"Split number %D Defined by IS\n",0);CHKERRQ(ierr);
333a51937d4SCarola Kruse     }
334a51937d4SCarola Kruse     ierr  = KSPView(ilink->ksp,viewer);CHKERRQ(ierr);
335a51937d4SCarola Kruse 
336a51937d4SCarola Kruse     ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr);
337a51937d4SCarola Kruse   }
338a51937d4SCarola Kruse 
339a51937d4SCarola Kruse  if (isdraw) {
340a51937d4SCarola Kruse     PetscDraw draw;
341a51937d4SCarola Kruse     PetscReal x,y,w,wd;
342a51937d4SCarola Kruse 
343a51937d4SCarola Kruse     ierr = PetscViewerDrawGetDraw(viewer,0,&draw);CHKERRQ(ierr);
344a51937d4SCarola Kruse     ierr = PetscDrawGetCurrentPoint(draw,&x,&y);CHKERRQ(ierr);
345a51937d4SCarola Kruse     w    = 2*PetscMin(1.0 - x,x);
346a51937d4SCarola Kruse     wd   = w/(jac->nsplits + 1);
347a51937d4SCarola Kruse     x    = x - wd*(jac->nsplits-1)/2.0;
348a51937d4SCarola Kruse     for (i=0; i<jac->nsplits; i++) {
349a51937d4SCarola Kruse       ierr  = PetscDrawPushCurrentPoint(draw,x,y);CHKERRQ(ierr);
350a51937d4SCarola Kruse       ierr  = KSPView(ilink->ksp,viewer);CHKERRQ(ierr);
351a51937d4SCarola Kruse       ierr  = PetscDrawPopCurrentPoint(draw);CHKERRQ(ierr);
352a51937d4SCarola Kruse       x    += wd;
353a51937d4SCarola Kruse       ilink = ilink->next;
354a51937d4SCarola Kruse     }
355a51937d4SCarola Kruse   }
356a51937d4SCarola Kruse   PetscFunctionReturn(0);
357a51937d4SCarola Kruse }
358a51937d4SCarola Kruse 
3596c924f48SJed Brown /* Precondition: jac->bs is set to a meaningful value */
3606c924f48SJed Brown static PetscErrorCode PCFieldSplitSetRuntimeSplits_Private(PC pc)
3616c924f48SJed Brown {
3626c924f48SJed Brown   PetscErrorCode ierr;
3636c924f48SJed Brown   PC_FieldSplit  *jac = (PC_FieldSplit*)pc->data;
3645d4c12cdSJungho Lee   PetscInt       i,nfields,*ifields,nfields_col,*ifields_col;
3655d4c12cdSJungho Lee   PetscBool      flg,flg_col;
3665d4c12cdSJungho Lee   char           optionname[128],splitname[8],optionname_col[128];
3676c924f48SJed Brown 
3686c924f48SJed Brown   PetscFunctionBegin;
369785e854fSJed Brown   ierr = PetscMalloc1(jac->bs,&ifields);CHKERRQ(ierr);
370785e854fSJed Brown   ierr = PetscMalloc1(jac->bs,&ifields_col);CHKERRQ(ierr);
3716c924f48SJed Brown   for (i=0,flg=PETSC_TRUE;; i++) {
3728caf3d72SBarry Smith     ierr        = PetscSNPrintf(splitname,sizeof(splitname),"%D",i);CHKERRQ(ierr);
3738caf3d72SBarry Smith     ierr        = PetscSNPrintf(optionname,sizeof(optionname),"-pc_fieldsplit_%D_fields",i);CHKERRQ(ierr);
3748caf3d72SBarry Smith     ierr        = PetscSNPrintf(optionname_col,sizeof(optionname_col),"-pc_fieldsplit_%D_fields_col",i);CHKERRQ(ierr);
3756c924f48SJed Brown     nfields     = jac->bs;
37629499fbbSJungho Lee     nfields_col = jac->bs;
377c5929fdfSBarry Smith     ierr        = PetscOptionsGetIntArray(((PetscObject)pc)->options,((PetscObject)pc)->prefix,optionname,ifields,&nfields,&flg);CHKERRQ(ierr);
378c5929fdfSBarry Smith     ierr        = PetscOptionsGetIntArray(((PetscObject)pc)->options,((PetscObject)pc)->prefix,optionname_col,ifields_col,&nfields_col,&flg_col);CHKERRQ(ierr);
3796c924f48SJed Brown     if (!flg) break;
3805d4c12cdSJungho Lee     else if (flg && !flg_col) {
3812c71b3e2SJacob Faibussowitsch       PetscCheckFalse(!nfields,PETSC_COMM_SELF,PETSC_ERR_USER,"Cannot list zero fields");
3825d4c12cdSJungho Lee       ierr = PCFieldSplitSetFields(pc,splitname,nfields,ifields,ifields);CHKERRQ(ierr);
3832fa5cd67SKarl Rupp     } else {
3842c71b3e2SJacob Faibussowitsch       PetscCheckFalse(!nfields || !nfields_col,PETSC_COMM_SELF,PETSC_ERR_USER,"Cannot list zero fields");
3852c71b3e2SJacob Faibussowitsch       PetscCheckFalse(nfields != nfields_col,PETSC_COMM_SELF,PETSC_ERR_USER,"Number of row and column fields must match");
3865d4c12cdSJungho Lee       ierr = PCFieldSplitSetFields(pc,splitname,nfields,ifields,ifields_col);CHKERRQ(ierr);
3875d4c12cdSJungho Lee     }
3886c924f48SJed Brown   }
3896c924f48SJed Brown   if (i > 0) {
3906c924f48SJed Brown     /* Makes command-line setting of splits take precedence over setting them in code.
3916c924f48SJed Brown        Otherwise subsequent calls to PCFieldSplitSetIS() or PCFieldSplitSetFields() would
3926c924f48SJed Brown        create new splits, which would probably not be what the user wanted. */
3936c924f48SJed Brown     jac->splitdefined = PETSC_TRUE;
3946c924f48SJed Brown   }
3956c924f48SJed Brown   ierr = PetscFree(ifields);CHKERRQ(ierr);
3965d4c12cdSJungho Lee   ierr = PetscFree(ifields_col);CHKERRQ(ierr);
3976c924f48SJed Brown   PetscFunctionReturn(0);
3986c924f48SJed Brown }
3996c924f48SJed Brown 
40069a612a9SBarry Smith static PetscErrorCode PCFieldSplitSetDefaults(PC pc)
4010971522cSBarry Smith {
4020971522cSBarry Smith   PC_FieldSplit     *jac = (PC_FieldSplit*)pc->data;
4030971522cSBarry Smith   PetscErrorCode    ierr;
4045a9f2f41SSatish Balay   PC_FieldSplitLink ilink = jac->head;
4057b752e3dSPatrick Sanan   PetscBool         fieldsplit_default = PETSC_FALSE,coupling = PETSC_FALSE;
4066c924f48SJed Brown   PetscInt          i;
4070971522cSBarry Smith 
4080971522cSBarry Smith   PetscFunctionBegin;
4097287d2a3SDmitry Karpeev   /*
410f5f0d762SBarry Smith    Kinda messy, but at least this now uses DMCreateFieldDecomposition().
4117287d2a3SDmitry Karpeev    Should probably be rewritten.
4127287d2a3SDmitry Karpeev    */
413f5f0d762SBarry Smith   if (!ilink) {
414c5929fdfSBarry Smith     ierr = PetscOptionsGetBool(((PetscObject)pc)->options,((PetscObject)pc)->prefix,"-pc_fieldsplit_detect_coupling",&coupling,NULL);CHKERRQ(ierr);
4157b752e3dSPatrick Sanan     if (pc->dm && jac->dm_splits && !jac->detect && !coupling) {
416bafc1b83SMatthew G Knepley       PetscInt  numFields, f, i, j;
4170784a22cSJed Brown       char      **fieldNames;
4187b62db95SJungho Lee       IS        *fields;
419e7c4fc90SDmitry Karpeev       DM        *dms;
420bafc1b83SMatthew G Knepley       DM        subdm[128];
421bafc1b83SMatthew G Knepley       PetscBool flg;
422bafc1b83SMatthew G Knepley 
42316621825SDmitry Karpeev       ierr = DMCreateFieldDecomposition(pc->dm, &numFields, &fieldNames, &fields, &dms);CHKERRQ(ierr);
424bafc1b83SMatthew G Knepley       /* Allow the user to prescribe the splits */
425bafc1b83SMatthew G Knepley       for (i = 0, flg = PETSC_TRUE;; i++) {
426bafc1b83SMatthew G Knepley         PetscInt ifields[128];
427bafc1b83SMatthew G Knepley         IS       compField;
428bafc1b83SMatthew G Knepley         char     optionname[128], splitname[8];
429bafc1b83SMatthew G Knepley         PetscInt nfields = numFields;
430bafc1b83SMatthew G Knepley 
4318caf3d72SBarry Smith         ierr = PetscSNPrintf(optionname, sizeof(optionname), "-pc_fieldsplit_%D_fields", i);CHKERRQ(ierr);
432c5929fdfSBarry Smith         ierr = PetscOptionsGetIntArray(((PetscObject)pc)->options,((PetscObject)pc)->prefix, optionname, ifields, &nfields, &flg);CHKERRQ(ierr);
433bafc1b83SMatthew G Knepley         if (!flg) break;
4342c71b3e2SJacob Faibussowitsch         PetscCheckFalse(numFields > 128,PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Cannot currently support %d > 128 fields", numFields);
435bafc1b83SMatthew G Knepley         ierr = DMCreateSubDM(pc->dm, nfields, ifields, &compField, &subdm[i]);CHKERRQ(ierr);
436bafc1b83SMatthew G Knepley         if (nfields == 1) {
437bafc1b83SMatthew G Knepley           ierr = PCFieldSplitSetIS(pc, fieldNames[ifields[0]], compField);CHKERRQ(ierr);
438bafc1b83SMatthew G Knepley         } else {
4398caf3d72SBarry Smith           ierr = PetscSNPrintf(splitname, sizeof(splitname), "%D", i);CHKERRQ(ierr);
440bafc1b83SMatthew G Knepley           ierr = PCFieldSplitSetIS(pc, splitname, compField);CHKERRQ(ierr);
4417287d2a3SDmitry Karpeev         }
442bafc1b83SMatthew G Knepley         ierr = ISDestroy(&compField);CHKERRQ(ierr);
443bafc1b83SMatthew G Knepley         for (j = 0; j < nfields; ++j) {
444bafc1b83SMatthew G Knepley           f    = ifields[j];
4457b62db95SJungho Lee           ierr = PetscFree(fieldNames[f]);CHKERRQ(ierr);
4467b62db95SJungho Lee           ierr = ISDestroy(&fields[f]);CHKERRQ(ierr);
4477b62db95SJungho Lee         }
448bafc1b83SMatthew G Knepley       }
449bafc1b83SMatthew G Knepley       if (i == 0) {
450bafc1b83SMatthew G Knepley         for (f = 0; f < numFields; ++f) {
451bafc1b83SMatthew G Knepley           ierr = PCFieldSplitSetIS(pc, fieldNames[f], fields[f]);CHKERRQ(ierr);
452bafc1b83SMatthew G Knepley           ierr = PetscFree(fieldNames[f]);CHKERRQ(ierr);
453bafc1b83SMatthew G Knepley           ierr = ISDestroy(&fields[f]);CHKERRQ(ierr);
454bafc1b83SMatthew G Knepley         }
455bafc1b83SMatthew G Knepley       } else {
456d724dfffSBarry Smith         for (j=0; j<numFields; j++) {
457d724dfffSBarry Smith           ierr = DMDestroy(dms+j);CHKERRQ(ierr);
458d724dfffSBarry Smith         }
459d724dfffSBarry Smith         ierr = PetscFree(dms);CHKERRQ(ierr);
460785e854fSJed Brown         ierr = PetscMalloc1(i, &dms);CHKERRQ(ierr);
4612fa5cd67SKarl Rupp         for (j = 0; j < i; ++j) dms[j] = subdm[j];
462bafc1b83SMatthew G Knepley       }
4637b62db95SJungho Lee       ierr = PetscFree(fieldNames);CHKERRQ(ierr);
4647b62db95SJungho Lee       ierr = PetscFree(fields);CHKERRQ(ierr);
465e7c4fc90SDmitry Karpeev       if (dms) {
4668b8307b2SJed Brown         ierr = PetscInfo(pc, "Setting up physics based fieldsplit preconditioner using the embedded DM\n");CHKERRQ(ierr);
467bafc1b83SMatthew G Knepley         for (ilink = jac->head, i = 0; ilink; ilink = ilink->next, ++i) {
4687287d2a3SDmitry Karpeev           const char *prefix;
4697287d2a3SDmitry Karpeev           ierr = PetscObjectGetOptionsPrefix((PetscObject)(ilink->ksp),&prefix);CHKERRQ(ierr);
4707287d2a3SDmitry Karpeev           ierr = PetscObjectSetOptionsPrefix((PetscObject)(dms[i]), prefix);CHKERRQ(ierr);
4717b62db95SJungho Lee           ierr = KSPSetDM(ilink->ksp, dms[i]);CHKERRQ(ierr);
4727b62db95SJungho Lee           ierr = KSPSetDMActive(ilink->ksp, PETSC_FALSE);CHKERRQ(ierr);
47395dbaa6fSMatthew G. Knepley           {
47495dbaa6fSMatthew G. Knepley             PetscErrorCode (*func)(KSP,Mat,Mat,void*);
47595dbaa6fSMatthew G. Knepley             void            *ctx;
47695dbaa6fSMatthew G. Knepley 
47795dbaa6fSMatthew G. Knepley             ierr = DMKSPGetComputeOperators(pc->dm, &func, &ctx);CHKERRQ(ierr);
47895dbaa6fSMatthew G. Knepley             ierr = DMKSPSetComputeOperators(dms[i],  func,  ctx);CHKERRQ(ierr);
47995dbaa6fSMatthew G. Knepley           }
4807287d2a3SDmitry Karpeev           ierr = PetscObjectIncrementTabLevel((PetscObject)dms[i],(PetscObject)ilink->ksp,0);CHKERRQ(ierr);
481e7c4fc90SDmitry Karpeev           ierr = DMDestroy(&dms[i]);CHKERRQ(ierr);
4822fa5ba8aSJed Brown         }
4837b62db95SJungho Lee         ierr = PetscFree(dms);CHKERRQ(ierr);
4848b8307b2SJed Brown       }
48566ffff09SJed Brown     } else {
486521d7252SBarry Smith       if (jac->bs <= 0) {
487704ba839SBarry Smith         if (pc->pmat) {
488521d7252SBarry Smith           ierr = MatGetBlockSize(pc->pmat,&jac->bs);CHKERRQ(ierr);
4892fa5cd67SKarl Rupp         } else jac->bs = 1;
490521d7252SBarry Smith       }
491d32f9abdSBarry Smith 
4927b752e3dSPatrick Sanan       if (jac->detect) {
4936ce1633cSBarry Smith         IS       zerodiags,rest;
4946ce1633cSBarry Smith         PetscInt nmin,nmax;
4956ce1633cSBarry Smith 
4966ce1633cSBarry Smith         ierr = MatGetOwnershipRange(pc->mat,&nmin,&nmax);CHKERRQ(ierr);
4977199da05SBarry Smith         if (jac->diag_use_amat) {
4986ce1633cSBarry Smith           ierr = MatFindZeroDiagonals(pc->mat,&zerodiags);CHKERRQ(ierr);
4997199da05SBarry Smith         } else {
5007199da05SBarry Smith           ierr = MatFindZeroDiagonals(pc->pmat,&zerodiags);CHKERRQ(ierr);
5017199da05SBarry Smith         }
5026ce1633cSBarry Smith         ierr = ISComplement(zerodiags,nmin,nmax,&rest);CHKERRQ(ierr);
5036ce1633cSBarry Smith         ierr = PCFieldSplitSetIS(pc,"0",rest);CHKERRQ(ierr);
5046ce1633cSBarry Smith         ierr = PCFieldSplitSetIS(pc,"1",zerodiags);CHKERRQ(ierr);
505fcfd50ebSBarry Smith         ierr = ISDestroy(&zerodiags);CHKERRQ(ierr);
506fcfd50ebSBarry Smith         ierr = ISDestroy(&rest);CHKERRQ(ierr);
5073a062f41SBarry Smith       } else if (coupling) {
5083a062f41SBarry Smith         IS       coupling,rest;
5093a062f41SBarry Smith         PetscInt nmin,nmax;
5103a062f41SBarry Smith 
5113a062f41SBarry Smith         ierr = MatGetOwnershipRange(pc->mat,&nmin,&nmax);CHKERRQ(ierr);
5127199da05SBarry Smith         if (jac->offdiag_use_amat) {
5133a062f41SBarry Smith           ierr = MatFindOffBlockDiagonalEntries(pc->mat,&coupling);CHKERRQ(ierr);
5147199da05SBarry Smith         } else {
5157199da05SBarry Smith           ierr = MatFindOffBlockDiagonalEntries(pc->pmat,&coupling);CHKERRQ(ierr);
5167199da05SBarry Smith         }
5176bea0878SBarry Smith         ierr = ISCreateStride(PetscObjectComm((PetscObject)pc->mat),nmax-nmin,nmin,1,&rest);CHKERRQ(ierr);
518e52d2c62SBarry Smith         ierr = ISSetIdentity(rest);CHKERRQ(ierr);
519d020c841SBarry Smith         ierr = PCFieldSplitSetIS(pc,"0",rest);CHKERRQ(ierr);
520d020c841SBarry Smith         ierr = PCFieldSplitSetIS(pc,"1",coupling);CHKERRQ(ierr);
5213a062f41SBarry Smith         ierr = ISDestroy(&coupling);CHKERRQ(ierr);
5223a062f41SBarry Smith         ierr = ISDestroy(&rest);CHKERRQ(ierr);
5236ce1633cSBarry Smith       } else {
524c5929fdfSBarry Smith         ierr = PetscOptionsGetBool(((PetscObject)pc)->options,((PetscObject)pc)->prefix,"-pc_fieldsplit_default",&fieldsplit_default,NULL);CHKERRQ(ierr);
5257287d2a3SDmitry Karpeev         if (!fieldsplit_default) {
526d32f9abdSBarry Smith           /* Allow user to set fields from command line,  if bs was known at the time of PCSetFromOptions_FieldSplit()
527d32f9abdSBarry Smith            then it is set there. This is not ideal because we should only have options set in XXSetFromOptions(). */
5286c924f48SJed Brown           ierr = PCFieldSplitSetRuntimeSplits_Private(pc);CHKERRQ(ierr);
5296c924f48SJed Brown           if (jac->splitdefined) {ierr = PetscInfo(pc,"Splits defined using the options database\n");CHKERRQ(ierr);}
530d32f9abdSBarry Smith         }
5316dbb499eSCian Wilson         if ((fieldsplit_default || !jac->splitdefined) && !jac->isrestrict) {
5329f001fe8SStefano Zampini           Mat       M = pc->pmat;
533f3b928b9SStefano Zampini           PetscBool isnest;
534f3b928b9SStefano Zampini 
535d32f9abdSBarry Smith           ierr = PetscInfo(pc,"Using default splitting of fields\n");CHKERRQ(ierr);
536f3b928b9SStefano Zampini           ierr = PetscObjectTypeCompare((PetscObject)pc->pmat,MATNEST,&isnest);CHKERRQ(ierr);
537f3b928b9SStefano Zampini           if (!isnest) {
5389f001fe8SStefano Zampini             M    = pc->mat;
539f3b928b9SStefano Zampini             ierr = PetscObjectTypeCompare((PetscObject)pc->mat,MATNEST,&isnest);CHKERRQ(ierr);
540f3b928b9SStefano Zampini           }
541f3b928b9SStefano Zampini           if (isnest) {
542f3b928b9SStefano Zampini             IS       *fields;
543f3b928b9SStefano Zampini             PetscInt nf;
544f3b928b9SStefano Zampini 
5459f001fe8SStefano Zampini             ierr = MatNestGetSize(M,&nf,NULL);CHKERRQ(ierr);
546f3b928b9SStefano Zampini             ierr = PetscMalloc1(nf,&fields);CHKERRQ(ierr);
5479f001fe8SStefano Zampini             ierr = MatNestGetISs(M,fields,NULL);CHKERRQ(ierr);
548f3b928b9SStefano Zampini             for (i=0;i<nf;i++) {
549f3b928b9SStefano Zampini               ierr = PCFieldSplitSetIS(pc,NULL,fields[i]);CHKERRQ(ierr);
550f3b928b9SStefano Zampini             }
551f3b928b9SStefano Zampini             ierr = PetscFree(fields);CHKERRQ(ierr);
552f3b928b9SStefano Zampini           } else {
553db4c96c1SJed Brown             for (i=0; i<jac->bs; i++) {
5546c924f48SJed Brown               char splitname[8];
5558caf3d72SBarry Smith               ierr = PetscSNPrintf(splitname,sizeof(splitname),"%D",i);CHKERRQ(ierr);
5565d4c12cdSJungho Lee               ierr = PCFieldSplitSetFields(pc,splitname,1,&i,&i);CHKERRQ(ierr);
55779416396SBarry Smith             }
5585d4c12cdSJungho Lee             jac->defaultsplit = PETSC_TRUE;
559521d7252SBarry Smith           }
56066ffff09SJed Brown         }
5616ce1633cSBarry Smith       }
562f3b928b9SStefano Zampini     }
563edf189efSBarry Smith   } else if (jac->nsplits == 1) {
564edf189efSBarry Smith     if (ilink->is) {
565edf189efSBarry Smith       IS       is2;
566edf189efSBarry Smith       PetscInt nmin,nmax;
567edf189efSBarry Smith 
568edf189efSBarry Smith       ierr = MatGetOwnershipRange(pc->mat,&nmin,&nmax);CHKERRQ(ierr);
569edf189efSBarry Smith       ierr = ISComplement(ilink->is,nmin,nmax,&is2);CHKERRQ(ierr);
570db4c96c1SJed Brown       ierr = PCFieldSplitSetIS(pc,"1",is2);CHKERRQ(ierr);
571fcfd50ebSBarry Smith       ierr = ISDestroy(&is2);CHKERRQ(ierr);
57282f516ccSBarry Smith     } else SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Must provide at least two sets of fields to PCFieldSplit()");
573edf189efSBarry Smith   }
574d0af7cd3SBarry Smith 
5752c71b3e2SJacob Faibussowitsch   PetscCheckFalse(jac->nsplits < 2,PetscObjectComm((PetscObject)pc),PETSC_ERR_PLIB,"Unhandled case, must have at least two fields, not %d", jac->nsplits);
57669a612a9SBarry Smith   PetscFunctionReturn(0);
57769a612a9SBarry Smith }
57869a612a9SBarry Smith 
579a51937d4SCarola Kruse static PetscErrorCode MatGolubKahanComputeExplicitOperator(Mat A,Mat B,Mat C,Mat *H,PetscReal gkbnu)
580a51937d4SCarola Kruse {
581a51937d4SCarola Kruse   PetscErrorCode    ierr;
582a51937d4SCarola Kruse   Mat               BT,T;
583de482cd7SCarola Kruse   PetscReal         nrmT,nrmB;
584a51937d4SCarola Kruse 
585a51937d4SCarola Kruse   PetscFunctionBegin;
586a51937d4SCarola Kruse   ierr = MatHermitianTranspose(C,MAT_INITIAL_MATRIX,&T);CHKERRQ(ierr);            /* Test if augmented matrix is symmetric */
587a51937d4SCarola Kruse   ierr = MatAXPY(T,-1.0,B,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
588de482cd7SCarola Kruse   ierr = MatNorm(T,NORM_1,&nrmT);CHKERRQ(ierr);
589de482cd7SCarola Kruse   ierr = MatNorm(B,NORM_1,&nrmB);CHKERRQ(ierr);
590de482cd7SCarola Kruse   if (nrmB > 0) {
591de482cd7SCarola Kruse     if (nrmT/nrmB >= PETSC_SMALL) {
592de482cd7SCarola Kruse       SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Matrix is not symmetric/hermitian, GKB is not applicable.");
593de482cd7SCarola Kruse     }
594a51937d4SCarola Kruse   }
595a51937d4SCarola Kruse   /* Compute augmented Lagrangian matrix H = A00 + nu*A01*A01'. This corresponds to */
596a51937d4SCarola Kruse   /* setting N := 1/nu*I in [Ar13].                                                 */
597a51937d4SCarola Kruse   ierr = MatHermitianTranspose(B,MAT_INITIAL_MATRIX,&BT);CHKERRQ(ierr);
598a51937d4SCarola Kruse   ierr = MatMatMult(B,BT,MAT_INITIAL_MATRIX,PETSC_DEFAULT,H);CHKERRQ(ierr);       /* H = A01*A01'          */
599a51937d4SCarola Kruse   ierr = MatAYPX(*H,gkbnu,A,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);             /* H = A00 + nu*A01*A01' */
600a51937d4SCarola Kruse 
601a51937d4SCarola Kruse   ierr = MatDestroy(&BT);CHKERRQ(ierr);
602a51937d4SCarola Kruse   ierr = MatDestroy(&T);CHKERRQ(ierr);
603a51937d4SCarola Kruse   PetscFunctionReturn(0);
604a51937d4SCarola Kruse }
605a51937d4SCarola Kruse 
6062d747510SLisandro Dalcin PETSC_EXTERN PetscErrorCode PetscOptionsFindPairPrefix_Private(PetscOptions,const char pre[], const char name[],const char *value[],PetscBool *flg);
607514bf10dSMatthew G Knepley 
60869a612a9SBarry Smith static PetscErrorCode PCSetUp_FieldSplit(PC pc)
60969a612a9SBarry Smith {
61069a612a9SBarry Smith   PC_FieldSplit     *jac = (PC_FieldSplit*)pc->data;
61169a612a9SBarry Smith   PetscErrorCode    ierr;
6125a9f2f41SSatish Balay   PC_FieldSplitLink ilink;
6132c9966d7SBarry Smith   PetscInt          i,nsplit;
6145f4ab4e1SJungho Lee   PetscBool         sorted, sorted_col;
61569a612a9SBarry Smith 
61669a612a9SBarry Smith   PetscFunctionBegin;
6175da88fe4STristan Konolige   pc->failedreason = PC_NOERROR;
61869a612a9SBarry Smith   ierr   = PCFieldSplitSetDefaults(pc);CHKERRQ(ierr);
61997bbdb24SBarry Smith   nsplit = jac->nsplits;
6205a9f2f41SSatish Balay   ilink  = jac->head;
62197bbdb24SBarry Smith 
62297bbdb24SBarry Smith   /* get the matrices for each split */
623704ba839SBarry Smith   if (!jac->issetup) {
6241b9fc7fcSBarry Smith     PetscInt rstart,rend,nslots,bs;
62597bbdb24SBarry Smith 
626704ba839SBarry Smith     jac->issetup = PETSC_TRUE;
627704ba839SBarry Smith 
6285d4c12cdSJungho Lee     /* This is done here instead of in PCFieldSplitSetFields() because may not have matrix at that point */
6292c9966d7SBarry Smith     if (jac->defaultsplit || !ilink->is) {
6302c9966d7SBarry Smith       if (jac->bs <= 0) jac->bs = nsplit;
6312c9966d7SBarry Smith     }
63251f519a2SBarry Smith     bs     = jac->bs;
63397bbdb24SBarry Smith     ierr   = MatGetOwnershipRange(pc->pmat,&rstart,&rend);CHKERRQ(ierr);
6341b9fc7fcSBarry Smith     nslots = (rend - rstart)/bs;
6351b9fc7fcSBarry Smith     for (i=0; i<nsplit; i++) {
6361b9fc7fcSBarry Smith       if (jac->defaultsplit) {
637ce94432eSBarry Smith         ierr = ISCreateStride(PetscObjectComm((PetscObject)pc),nslots,rstart+i,nsplit,&ilink->is);CHKERRQ(ierr);
6385f4ab4e1SJungho Lee         ierr = ISDuplicate(ilink->is,&ilink->is_col);CHKERRQ(ierr);
639704ba839SBarry Smith       } else if (!ilink->is) {
640ccb205f8SBarry Smith         if (ilink->nfields > 1) {
6415f4ab4e1SJungho Lee           PetscInt *ii,*jj,j,k,nfields = ilink->nfields,*fields = ilink->fields,*fields_col = ilink->fields_col;
642785e854fSJed Brown           ierr = PetscMalloc1(ilink->nfields*nslots,&ii);CHKERRQ(ierr);
643785e854fSJed Brown           ierr = PetscMalloc1(ilink->nfields*nslots,&jj);CHKERRQ(ierr);
6441b9fc7fcSBarry Smith           for (j=0; j<nslots; j++) {
6451b9fc7fcSBarry Smith             for (k=0; k<nfields; k++) {
6461b9fc7fcSBarry Smith               ii[nfields*j + k] = rstart + bs*j + fields[k];
6475f4ab4e1SJungho Lee               jj[nfields*j + k] = rstart + bs*j + fields_col[k];
64897bbdb24SBarry Smith             }
64997bbdb24SBarry Smith           }
650ce94432eSBarry Smith           ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),nslots*nfields,ii,PETSC_OWN_POINTER,&ilink->is);CHKERRQ(ierr);
651ce94432eSBarry Smith           ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),nslots*nfields,jj,PETSC_OWN_POINTER,&ilink->is_col);CHKERRQ(ierr);
65290e68f20SPatrick Farrell           ierr = ISSetBlockSize(ilink->is, nfields);CHKERRQ(ierr);
65390e68f20SPatrick Farrell           ierr = ISSetBlockSize(ilink->is_col, nfields);CHKERRQ(ierr);
654ccb205f8SBarry Smith         } else {
655ce94432eSBarry Smith           ierr = ISCreateStride(PetscObjectComm((PetscObject)pc),nslots,rstart+ilink->fields[0],bs,&ilink->is);CHKERRQ(ierr);
656ce94432eSBarry Smith           ierr = ISCreateStride(PetscObjectComm((PetscObject)pc),nslots,rstart+ilink->fields_col[0],bs,&ilink->is_col);CHKERRQ(ierr);
657ccb205f8SBarry Smith         }
6583e197d65SBarry Smith       }
659704ba839SBarry Smith       ierr = ISSorted(ilink->is,&sorted);CHKERRQ(ierr);
6605f4ab4e1SJungho Lee       if (ilink->is_col) { ierr = ISSorted(ilink->is_col,&sorted_col);CHKERRQ(ierr); }
6612c71b3e2SJacob Faibussowitsch       PetscCheckFalse(!sorted || !sorted_col,PETSC_COMM_SELF,PETSC_ERR_USER,"Fields must be sorted when creating split");
662704ba839SBarry Smith       ilink = ilink->next;
6631b9fc7fcSBarry Smith     }
6641b9fc7fcSBarry Smith   }
6651b9fc7fcSBarry Smith 
666704ba839SBarry Smith   ilink = jac->head;
66797bbdb24SBarry Smith   if (!jac->pmat) {
668bdddcaaaSMatthew G Knepley     Vec xtmp;
669bdddcaaaSMatthew G Knepley 
6702a7a6963SBarry Smith     ierr = MatCreateVecs(pc->pmat,&xtmp,NULL);CHKERRQ(ierr);
671785e854fSJed Brown     ierr = PetscMalloc1(nsplit,&jac->pmat);CHKERRQ(ierr);
672dcca6d9dSJed Brown     ierr = PetscMalloc2(nsplit,&jac->x,nsplit,&jac->y);CHKERRQ(ierr);
673cf502942SBarry Smith     for (i=0; i<nsplit; i++) {
674bdddcaaaSMatthew G Knepley       MatNullSpace sp;
675bdddcaaaSMatthew G Knepley 
676a3df900dSMatthew G Knepley       /* Check for preconditioning matrix attached to IS */
677a3df900dSMatthew G Knepley       ierr = PetscObjectQuery((PetscObject) ilink->is, "pmat", (PetscObject*) &jac->pmat[i]);CHKERRQ(ierr);
678a3df900dSMatthew G Knepley       if (jac->pmat[i]) {
679a3df900dSMatthew G Knepley         ierr = PetscObjectReference((PetscObject) jac->pmat[i]);CHKERRQ(ierr);
680a3df900dSMatthew G Knepley         if (jac->type == PC_COMPOSITE_SCHUR) {
681a3df900dSMatthew G Knepley           jac->schur_user = jac->pmat[i];
6822fa5cd67SKarl Rupp 
683a3df900dSMatthew G Knepley           ierr = PetscObjectReference((PetscObject) jac->schur_user);CHKERRQ(ierr);
684a3df900dSMatthew G Knepley         }
685a3df900dSMatthew G Knepley       } else {
6863a062f41SBarry Smith         const char *prefix;
6877dae84e0SHong Zhang         ierr = MatCreateSubMatrix(pc->pmat,ilink->is,ilink->is_col,MAT_INITIAL_MATRIX,&jac->pmat[i]);CHKERRQ(ierr);
6883a062f41SBarry Smith         ierr = KSPGetOptionsPrefix(ilink->ksp,&prefix);CHKERRQ(ierr);
6893a062f41SBarry Smith         ierr = MatSetOptionsPrefix(jac->pmat[i],prefix);CHKERRQ(ierr);
6903a062f41SBarry Smith         ierr = MatViewFromOptions(jac->pmat[i],NULL,"-mat_view");CHKERRQ(ierr);
691a3df900dSMatthew G Knepley       }
692bdddcaaaSMatthew G Knepley       /* create work vectors for each split */
6932a7a6963SBarry Smith       ierr     = MatCreateVecs(jac->pmat[i],&jac->x[i],&jac->y[i]);CHKERRQ(ierr);
6940298fd71SBarry Smith       ilink->x = jac->x[i]; ilink->y = jac->y[i]; ilink->z = NULL;
695bdddcaaaSMatthew G Knepley       /* compute scatter contexts needed by multiplicative versions and non-default splits */
6969448b7f1SJunchao Zhang       ierr = VecScatterCreate(xtmp,ilink->is,jac->x[i],NULL,&ilink->sctx);CHKERRQ(ierr);
697ed1f0337SMatthew G Knepley       ierr = PetscObjectQuery((PetscObject) ilink->is, "nearnullspace", (PetscObject*) &sp);CHKERRQ(ierr);
698ed1f0337SMatthew G Knepley       if (sp) {
699ed1f0337SMatthew G Knepley         ierr = MatSetNearNullSpace(jac->pmat[i], sp);CHKERRQ(ierr);
700ed1f0337SMatthew G Knepley       }
701704ba839SBarry Smith       ilink = ilink->next;
702cf502942SBarry Smith     }
703bdddcaaaSMatthew G Knepley     ierr = VecDestroy(&xtmp);CHKERRQ(ierr);
70497bbdb24SBarry Smith   } else {
705ef7efd37SHong Zhang     MatReuse scall;
706ef7efd37SHong Zhang     if (pc->flag == DIFFERENT_NONZERO_PATTERN) {
707ef7efd37SHong Zhang       for (i=0; i<nsplit; i++) {
708ef7efd37SHong Zhang         ierr = MatDestroy(&jac->pmat[i]);CHKERRQ(ierr);
709ef7efd37SHong Zhang       }
710ef7efd37SHong Zhang       scall = MAT_INITIAL_MATRIX;
711ef7efd37SHong Zhang     } else scall = MAT_REUSE_MATRIX;
712ef7efd37SHong Zhang 
713cf502942SBarry Smith     for (i=0; i<nsplit; i++) {
714a3df900dSMatthew G Knepley       Mat pmat;
715a3df900dSMatthew G Knepley 
716a3df900dSMatthew G Knepley       /* Check for preconditioning matrix attached to IS */
717a3df900dSMatthew G Knepley       ierr = PetscObjectQuery((PetscObject) ilink->is, "pmat", (PetscObject*) &pmat);CHKERRQ(ierr);
718a3df900dSMatthew G Knepley       if (!pmat) {
719ef7efd37SHong Zhang         ierr = MatCreateSubMatrix(pc->pmat,ilink->is,ilink->is_col,scall,&jac->pmat[i]);CHKERRQ(ierr);
720a3df900dSMatthew G Knepley       }
721704ba839SBarry Smith       ilink = ilink->next;
722cf502942SBarry Smith     }
72397bbdb24SBarry Smith   }
7244e39094bSDmitry Karpeev   if (jac->diag_use_amat) {
725519d70e2SJed Brown     ilink = jac->head;
726519d70e2SJed Brown     if (!jac->mat) {
727785e854fSJed Brown       ierr = PetscMalloc1(nsplit,&jac->mat);CHKERRQ(ierr);
728519d70e2SJed Brown       for (i=0; i<nsplit; i++) {
7297dae84e0SHong Zhang         ierr  = MatCreateSubMatrix(pc->mat,ilink->is,ilink->is_col,MAT_INITIAL_MATRIX,&jac->mat[i]);CHKERRQ(ierr);
730519d70e2SJed Brown         ilink = ilink->next;
731519d70e2SJed Brown       }
732519d70e2SJed Brown     } else {
733ef7efd37SHong Zhang       MatReuse scall;
734ef7efd37SHong Zhang       if (pc->flag == DIFFERENT_NONZERO_PATTERN) {
735519d70e2SJed Brown         for (i=0; i<nsplit; i++) {
736ef7efd37SHong Zhang           ierr = MatDestroy(&jac->mat[i]);CHKERRQ(ierr);
737ef7efd37SHong Zhang         }
738ef7efd37SHong Zhang         scall = MAT_INITIAL_MATRIX;
739ef7efd37SHong Zhang       } else scall = MAT_REUSE_MATRIX;
740ef7efd37SHong Zhang 
741ef7efd37SHong Zhang       for (i=0; i<nsplit; i++) {
742e9422dd5SStefano Zampini         ierr  = MatCreateSubMatrix(pc->mat,ilink->is,ilink->is_col,scall,&jac->mat[i]);CHKERRQ(ierr);
743519d70e2SJed Brown         ilink = ilink->next;
744519d70e2SJed Brown       }
745519d70e2SJed Brown     }
746519d70e2SJed Brown   } else {
747519d70e2SJed Brown     jac->mat = jac->pmat;
748519d70e2SJed Brown   }
74997bbdb24SBarry Smith 
75053935eafSBarry Smith   /* Check for null space attached to IS */
75153935eafSBarry Smith   ilink = jac->head;
75253935eafSBarry Smith   for (i=0; i<nsplit; i++) {
75353935eafSBarry Smith     MatNullSpace sp;
75453935eafSBarry Smith 
75553935eafSBarry Smith     ierr = PetscObjectQuery((PetscObject) ilink->is, "nullspace", (PetscObject*) &sp);CHKERRQ(ierr);
75653935eafSBarry Smith     if (sp) {
75753935eafSBarry Smith       ierr = MatSetNullSpace(jac->mat[i], sp);CHKERRQ(ierr);
75853935eafSBarry Smith     }
75953935eafSBarry Smith     ilink = ilink->next;
76053935eafSBarry Smith   }
76153935eafSBarry Smith 
762a51937d4SCarola Kruse   if (jac->type != PC_COMPOSITE_ADDITIVE  && jac->type != PC_COMPOSITE_SCHUR && jac->type != PC_COMPOSITE_GKB) {
76368dd23aaSBarry Smith     /* extract the rows of the matrix associated with each field: used for efficient computation of residual inside algorithm */
7644e39094bSDmitry Karpeev     /* FIXME: Can/should we reuse jac->mat whenever (jac->diag_use_amat) is true? */
76568dd23aaSBarry Smith     ilink = jac->head;
766e52d2c62SBarry Smith     if (nsplit == 2 && jac->type == PC_COMPOSITE_MULTIPLICATIVE) {
767e52d2c62SBarry 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 */
768e52d2c62SBarry Smith       if (!jac->Afield) {
769e52d2c62SBarry Smith         ierr = PetscCalloc1(nsplit,&jac->Afield);CHKERRQ(ierr);
77080c96bb1SFande Kong         if (jac->offdiag_use_amat) {
7717dae84e0SHong Zhang           ierr = MatCreateSubMatrix(pc->mat,ilink->next->is,ilink->is,MAT_INITIAL_MATRIX,&jac->Afield[1]);CHKERRQ(ierr);
772e52d2c62SBarry Smith         } else {
7737dae84e0SHong Zhang           ierr = MatCreateSubMatrix(pc->pmat,ilink->next->is,ilink->is,MAT_INITIAL_MATRIX,&jac->Afield[1]);CHKERRQ(ierr);
77480c96bb1SFande Kong         }
77580c96bb1SFande Kong       } else {
776ef7efd37SHong Zhang         MatReuse scall;
777e9422dd5SStefano Zampini 
778ef7efd37SHong Zhang         if (pc->flag == DIFFERENT_NONZERO_PATTERN) {
779ef7efd37SHong Zhang           ierr  = MatDestroy(&jac->Afield[1]);CHKERRQ(ierr);
780ef7efd37SHong Zhang           scall = MAT_INITIAL_MATRIX;
781ef7efd37SHong Zhang         } else scall = MAT_REUSE_MATRIX;
782ef7efd37SHong Zhang 
78380c96bb1SFande Kong         if (jac->offdiag_use_amat) {
784ef7efd37SHong Zhang           ierr = MatCreateSubMatrix(pc->mat,ilink->next->is,ilink->is,scall,&jac->Afield[1]);CHKERRQ(ierr);
78580c96bb1SFande Kong         } else {
786ef7efd37SHong Zhang           ierr = MatCreateSubMatrix(pc->pmat,ilink->next->is,ilink->is,scall,&jac->Afield[1]);CHKERRQ(ierr);
78780c96bb1SFande Kong         }
788e52d2c62SBarry Smith       }
789e52d2c62SBarry Smith     } else {
79068dd23aaSBarry Smith       if (!jac->Afield) {
791785e854fSJed Brown         ierr = PetscMalloc1(nsplit,&jac->Afield);CHKERRQ(ierr);
79268dd23aaSBarry Smith         for (i=0; i<nsplit; i++) {
79380c96bb1SFande Kong           if (jac->offdiag_use_amat) {
7947dae84e0SHong Zhang             ierr = MatCreateSubMatrix(pc->mat,ilink->is,NULL,MAT_INITIAL_MATRIX,&jac->Afield[i]);CHKERRQ(ierr);
79580c96bb1SFande Kong           } else {
7967dae84e0SHong Zhang             ierr = MatCreateSubMatrix(pc->pmat,ilink->is,NULL,MAT_INITIAL_MATRIX,&jac->Afield[i]);CHKERRQ(ierr);
79780c96bb1SFande Kong           }
79868dd23aaSBarry Smith           ilink = ilink->next;
79968dd23aaSBarry Smith         }
80068dd23aaSBarry Smith       } else {
801ef7efd37SHong Zhang         MatReuse scall;
802ef7efd37SHong Zhang         if (pc->flag == DIFFERENT_NONZERO_PATTERN) {
803ef7efd37SHong Zhang           for (i=0; i<nsplit; i++) {
804ef7efd37SHong Zhang             ierr = MatDestroy(&jac->Afield[i]);CHKERRQ(ierr);
805ef7efd37SHong Zhang           }
806ef7efd37SHong Zhang           scall = MAT_INITIAL_MATRIX;
807ef7efd37SHong Zhang         } else scall = MAT_REUSE_MATRIX;
808ef7efd37SHong Zhang 
80968dd23aaSBarry Smith         for (i=0; i<nsplit; i++) {
81080c96bb1SFande Kong           if (jac->offdiag_use_amat) {
811ef7efd37SHong Zhang             ierr = MatCreateSubMatrix(pc->mat,ilink->is,NULL,scall,&jac->Afield[i]);CHKERRQ(ierr);
81280c96bb1SFande Kong           } else {
813ef7efd37SHong Zhang             ierr = MatCreateSubMatrix(pc->pmat,ilink->is,NULL,scall,&jac->Afield[i]);CHKERRQ(ierr);
81480c96bb1SFande Kong           }
81568dd23aaSBarry Smith           ilink = ilink->next;
81668dd23aaSBarry Smith         }
81768dd23aaSBarry Smith       }
81868dd23aaSBarry Smith     }
819e52d2c62SBarry Smith   }
82068dd23aaSBarry Smith 
8213b224e63SBarry Smith   if (jac->type == PC_COMPOSITE_SCHUR) {
8223b224e63SBarry Smith     IS          ccis;
823c096484dSStefano Zampini     PetscBool   isspd;
8244aa3045dSJed Brown     PetscInt    rstart,rend;
825093c86ffSJed Brown     char        lscname[256];
826093c86ffSJed Brown     PetscObject LSC_L;
827ce94432eSBarry Smith 
8282c71b3e2SJacob Faibussowitsch     PetscCheckFalse(nsplit != 2,PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_INCOMP,"To use Schur complement preconditioner you must have exactly 2 fields");
82968dd23aaSBarry Smith 
830c096484dSStefano Zampini     /* If pc->mat is SPD, don't scale by -1 the Schur complement */
831c096484dSStefano Zampini     if (jac->schurscale == (PetscScalar)-1.0) {
832c096484dSStefano Zampini       ierr = MatGetOption(pc->pmat,MAT_SPD,&isspd);CHKERRQ(ierr);
833c096484dSStefano Zampini       jac->schurscale = (isspd == PETSC_TRUE) ? 1.0 : -1.0;
834c096484dSStefano Zampini     }
835c096484dSStefano Zampini 
836e6cab6aaSJed Brown     /* When extracting off-diagonal submatrices, we take complements from this range */
837e6cab6aaSJed Brown     ierr = MatGetOwnershipRangeColumn(pc->mat,&rstart,&rend);CHKERRQ(ierr);
838e6cab6aaSJed Brown 
8393b224e63SBarry Smith     if (jac->schur) {
8400298fd71SBarry Smith       KSP      kspA = jac->head->ksp, kspInner = NULL, kspUpper = jac->kspupper;
841e9422dd5SStefano Zampini       MatReuse scall;
842e9422dd5SStefano Zampini 
843e9422dd5SStefano Zampini       if (pc->flag == DIFFERENT_NONZERO_PATTERN) {
844e9422dd5SStefano Zampini         scall = MAT_INITIAL_MATRIX;
845e9422dd5SStefano Zampini         ierr  = MatDestroy(&jac->B);CHKERRQ(ierr);
846e9422dd5SStefano Zampini         ierr  = MatDestroy(&jac->C);CHKERRQ(ierr);
847e9422dd5SStefano Zampini       } else scall = MAT_REUSE_MATRIX;
848443836d0SMatthew G Knepley 
849fb3147dbSMatthew G Knepley       ierr  = MatSchurComplementGetKSP(jac->schur, &kspInner);CHKERRQ(ierr);
8503b224e63SBarry Smith       ilink = jac->head;
85149bb4cd7SJungho Lee       ierr  = ISComplement(ilink->is_col,rstart,rend,&ccis);CHKERRQ(ierr);
8524e39094bSDmitry Karpeev       if (jac->offdiag_use_amat) {
853e9422dd5SStefano Zampini         ierr = MatCreateSubMatrix(pc->mat,ilink->is,ccis,scall,&jac->B);CHKERRQ(ierr);
854c84da90fSDmitry Karpeev       } else {
855e9422dd5SStefano Zampini         ierr = MatCreateSubMatrix(pc->pmat,ilink->is,ccis,scall,&jac->B);CHKERRQ(ierr);
856c84da90fSDmitry Karpeev       }
857fcfd50ebSBarry Smith       ierr  = ISDestroy(&ccis);CHKERRQ(ierr);
8583b224e63SBarry Smith       ilink = ilink->next;
85949bb4cd7SJungho Lee       ierr  = ISComplement(ilink->is_col,rstart,rend,&ccis);CHKERRQ(ierr);
8604e39094bSDmitry Karpeev       if (jac->offdiag_use_amat) {
861e9422dd5SStefano Zampini         ierr = MatCreateSubMatrix(pc->mat,ilink->is,ccis,scall,&jac->C);CHKERRQ(ierr);
862c84da90fSDmitry Karpeev       } else {
863e9422dd5SStefano Zampini         ierr = MatCreateSubMatrix(pc->pmat,ilink->is,ccis,scall,&jac->C);CHKERRQ(ierr);
864c84da90fSDmitry Karpeev       }
865fcfd50ebSBarry Smith       ierr  = ISDestroy(&ccis);CHKERRQ(ierr);
866aa6c7ce3SBarry Smith       ierr  = MatSchurComplementUpdateSubMatrices(jac->schur,jac->mat[0],jac->pmat[0],jac->B,jac->C,jac->mat[1]);CHKERRQ(ierr);
867a7476a74SDmitry Karpeev       if (jac->schurpre == PC_FIELDSPLIT_SCHUR_PRE_SELFP) {
868a7476a74SDmitry Karpeev         ierr = MatDestroy(&jac->schurp);CHKERRQ(ierr);
869a7476a74SDmitry Karpeev         ierr = MatSchurComplementGetPmat(jac->schur,MAT_INITIAL_MATRIX,&jac->schurp);CHKERRQ(ierr);
870a7476a74SDmitry Karpeev       }
871443836d0SMatthew G Knepley       if (kspA != kspInner) {
87223ee1639SBarry Smith         ierr = KSPSetOperators(kspA,jac->mat[0],jac->pmat[0]);CHKERRQ(ierr);
873443836d0SMatthew G Knepley       }
874443836d0SMatthew G Knepley       if (kspUpper != kspA) {
87523ee1639SBarry Smith         ierr = KSPSetOperators(kspUpper,jac->mat[0],jac->pmat[0]);CHKERRQ(ierr);
876443836d0SMatthew G Knepley       }
87723ee1639SBarry Smith       ierr = KSPSetOperators(jac->kspschur,jac->schur,FieldSplitSchurPre(jac));CHKERRQ(ierr);
8783b224e63SBarry Smith     } else {
879bafc1b83SMatthew G Knepley       const char   *Dprefix;
880470b340bSDmitry Karpeev       char         schurprefix[256], schurmatprefix[256];
881514bf10dSMatthew G Knepley       char         schurtestoption[256];
882bdddcaaaSMatthew G Knepley       MatNullSpace sp;
883514bf10dSMatthew G Knepley       PetscBool    flg;
884686bed4dSStefano Zampini       KSP          kspt;
8853b224e63SBarry Smith 
886a04f6461SBarry Smith       /* extract the A01 and A10 matrices */
8873b224e63SBarry Smith       ilink = jac->head;
88849bb4cd7SJungho Lee       ierr  = ISComplement(ilink->is_col,rstart,rend,&ccis);CHKERRQ(ierr);
8894e39094bSDmitry Karpeev       if (jac->offdiag_use_amat) {
8907dae84e0SHong Zhang         ierr = MatCreateSubMatrix(pc->mat,ilink->is,ccis,MAT_INITIAL_MATRIX,&jac->B);CHKERRQ(ierr);
891c84da90fSDmitry Karpeev       } else {
8927dae84e0SHong Zhang         ierr = MatCreateSubMatrix(pc->pmat,ilink->is,ccis,MAT_INITIAL_MATRIX,&jac->B);CHKERRQ(ierr);
893c84da90fSDmitry Karpeev       }
894fcfd50ebSBarry Smith       ierr  = ISDestroy(&ccis);CHKERRQ(ierr);
8953b224e63SBarry Smith       ilink = ilink->next;
89649bb4cd7SJungho Lee       ierr  = ISComplement(ilink->is_col,rstart,rend,&ccis);CHKERRQ(ierr);
8974e39094bSDmitry Karpeev       if (jac->offdiag_use_amat) {
8987dae84e0SHong Zhang         ierr = MatCreateSubMatrix(pc->mat,ilink->is,ccis,MAT_INITIAL_MATRIX,&jac->C);CHKERRQ(ierr);
899c84da90fSDmitry Karpeev       } else {
9007dae84e0SHong Zhang         ierr = MatCreateSubMatrix(pc->pmat,ilink->is,ccis,MAT_INITIAL_MATRIX,&jac->C);CHKERRQ(ierr);
901c84da90fSDmitry Karpeev       }
902fcfd50ebSBarry Smith       ierr = ISDestroy(&ccis);CHKERRQ(ierr);
90320252d06SBarry Smith 
904f5236f50SJed Brown       /* Use mat[0] (diagonal block of Amat) preconditioned by pmat[0] to define Schur complement */
90520252d06SBarry Smith       ierr = MatCreate(((PetscObject)jac->mat[0])->comm,&jac->schur);CHKERRQ(ierr);
90620252d06SBarry Smith       ierr = MatSetType(jac->schur,MATSCHURCOMPLEMENT);CHKERRQ(ierr);
907bee83525SDmitry Karpeev       ierr = MatSchurComplementSetSubMatrices(jac->schur,jac->mat[0],jac->pmat[0],jac->B,jac->C,jac->mat[1]);CHKERRQ(ierr);
908470b340bSDmitry Karpeev       ierr = PetscSNPrintf(schurmatprefix, sizeof(schurmatprefix), "%sfieldsplit_%s_", ((PetscObject)pc)->prefix ? ((PetscObject)pc)->prefix : "", ilink->splitname);CHKERRQ(ierr);
909470b340bSDmitry Karpeev       ierr = MatSetOptionsPrefix(jac->schur,schurmatprefix);CHKERRQ(ierr);
910686bed4dSStefano Zampini       ierr = MatSchurComplementGetKSP(jac->schur,&kspt);CHKERRQ(ierr);
911686bed4dSStefano Zampini       ierr = KSPSetOptionsPrefix(kspt,schurmatprefix);CHKERRQ(ierr);
912686bed4dSStefano Zampini 
913686bed4dSStefano Zampini       /* Note: this is not true in general */
914895c21f2SBarry Smith       ierr = MatGetNullSpace(jac->mat[1], &sp);CHKERRQ(ierr);
91520252d06SBarry Smith       if (sp) {
91620252d06SBarry Smith         ierr = MatSetNullSpace(jac->schur, sp);CHKERRQ(ierr);
91720252d06SBarry Smith       }
91820252d06SBarry Smith 
91920252d06SBarry Smith       ierr = PetscSNPrintf(schurtestoption, sizeof(schurtestoption), "-fieldsplit_%s_inner_", ilink->splitname);CHKERRQ(ierr);
920c5929fdfSBarry Smith       ierr = PetscOptionsFindPairPrefix_Private(((PetscObject)pc)->options,((PetscObject)pc)->prefix, schurtestoption, NULL, &flg);CHKERRQ(ierr);
921514bf10dSMatthew G Knepley       if (flg) {
922514bf10dSMatthew G Knepley         DM  dmInner;
92321635b76SJed Brown         KSP kspInner;
924686bed4dSStefano Zampini         PC  pcInner;
92521635b76SJed Brown 
92621635b76SJed Brown         ierr = MatSchurComplementGetKSP(jac->schur, &kspInner);CHKERRQ(ierr);
9272cc093acSMatthew G. Knepley         ierr = KSPReset(kspInner);CHKERRQ(ierr);
9282cc093acSMatthew G. Knepley         ierr = KSPSetOperators(kspInner,jac->mat[0],jac->pmat[0]);CHKERRQ(ierr);
92921635b76SJed Brown         ierr = PetscSNPrintf(schurprefix, sizeof(schurprefix), "%sfieldsplit_%s_inner_", ((PetscObject)pc)->prefix ? ((PetscObject)pc)->prefix : "", ilink->splitname);CHKERRQ(ierr);
93021635b76SJed Brown         /* Indent this deeper to emphasize the "inner" nature of this solver. */
93121635b76SJed Brown         ierr = PetscObjectIncrementTabLevel((PetscObject)kspInner, (PetscObject) pc, 2);CHKERRQ(ierr);
9322cc093acSMatthew G. Knepley         ierr = PetscObjectIncrementTabLevel((PetscObject)kspInner->pc, (PetscObject) pc, 2);CHKERRQ(ierr);
93321635b76SJed Brown         ierr = KSPSetOptionsPrefix(kspInner, schurprefix);CHKERRQ(ierr);
934514bf10dSMatthew G Knepley 
935514bf10dSMatthew G Knepley         /* Set DM for new solver */
936bafc1b83SMatthew G Knepley         ierr = KSPGetDM(jac->head->ksp, &dmInner);CHKERRQ(ierr);
93721635b76SJed Brown         ierr = KSPSetDM(kspInner, dmInner);CHKERRQ(ierr);
93821635b76SJed Brown         ierr = KSPSetDMActive(kspInner, PETSC_FALSE);CHKERRQ(ierr);
939686bed4dSStefano Zampini 
940686bed4dSStefano Zampini         /* Defaults to PCKSP as preconditioner */
941686bed4dSStefano Zampini         ierr = KSPGetPC(kspInner, &pcInner);CHKERRQ(ierr);
942686bed4dSStefano Zampini         ierr = PCSetType(pcInner, PCKSP);CHKERRQ(ierr);
943686bed4dSStefano Zampini         ierr = PCKSPSetKSP(pcInner, jac->head->ksp);CHKERRQ(ierr);
944514bf10dSMatthew G Knepley       } else {
94521635b76SJed Brown          /* Use the outer solver for the inner solve, but revert the KSPPREONLY from PCFieldSplitSetFields_FieldSplit or
94621635b76SJed Brown           * PCFieldSplitSetIS_FieldSplit. We don't want KSPPREONLY because it makes the Schur complement inexact,
94721635b76SJed Brown           * preventing Schur complement reduction to be an accurate solve. Usually when an iterative solver is used for
94821635b76SJed 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
94921635b76SJed Brown           * GMRES the default. Note that it is also common to use PREONLY for S, in which case S may not be used
95021635b76SJed Brown           * directly, and the user is responsible for setting an inexact method for fieldsplit's A^{-1}. */
95121635b76SJed Brown         ierr = KSPSetType(jac->head->ksp,KSPGMRES);CHKERRQ(ierr);
952514bf10dSMatthew G Knepley         ierr = MatSchurComplementSetKSP(jac->schur,jac->head->ksp);CHKERRQ(ierr);
953bafc1b83SMatthew G Knepley       }
95423ee1639SBarry Smith       ierr = KSPSetOperators(jac->head->ksp,jac->mat[0],jac->pmat[0]);CHKERRQ(ierr);
9555a9f2f41SSatish Balay       ierr = KSPSetFromOptions(jac->head->ksp);CHKERRQ(ierr);
95697bbdb24SBarry Smith       ierr = MatSetFromOptions(jac->schur);CHKERRQ(ierr);
95797bbdb24SBarry Smith 
958686bed4dSStefano Zampini       ierr = PetscObjectTypeCompare((PetscObject)jac->schur, MATSCHURCOMPLEMENT, &flg);CHKERRQ(ierr);
959686bed4dSStefano Zampini       if (flg) { /* Need to do this otherwise PCSetUp_KSP will overwrite the amat of jac->head->ksp */
960686bed4dSStefano Zampini         KSP kspInner;
961686bed4dSStefano Zampini         PC  pcInner;
962686bed4dSStefano Zampini 
963686bed4dSStefano Zampini         ierr = MatSchurComplementGetKSP(jac->schur, &kspInner);CHKERRQ(ierr);
964686bed4dSStefano Zampini         ierr = KSPGetPC(kspInner, &pcInner);CHKERRQ(ierr);
965686bed4dSStefano Zampini         ierr = PetscObjectTypeCompare((PetscObject)pcInner, PCKSP, &flg);CHKERRQ(ierr);
966686bed4dSStefano Zampini         if (flg) {
967686bed4dSStefano Zampini           KSP ksp;
968686bed4dSStefano Zampini 
969686bed4dSStefano Zampini           ierr = PCKSPGetKSP(pcInner, &ksp);CHKERRQ(ierr);
970686bed4dSStefano Zampini           if (ksp == jac->head->ksp) {
971686bed4dSStefano Zampini             ierr = PCSetUseAmat(pcInner, PETSC_TRUE);CHKERRQ(ierr);
972686bed4dSStefano Zampini           }
973686bed4dSStefano Zampini         }
974686bed4dSStefano Zampini       }
975443836d0SMatthew G Knepley       ierr = PetscSNPrintf(schurtestoption, sizeof(schurtestoption), "-fieldsplit_%s_upper_", ilink->splitname);CHKERRQ(ierr);
976c5929fdfSBarry Smith       ierr = PetscOptionsFindPairPrefix_Private(((PetscObject)pc)->options,((PetscObject)pc)->prefix, schurtestoption, NULL, &flg);CHKERRQ(ierr);
977443836d0SMatthew G Knepley       if (flg) {
978443836d0SMatthew G Knepley         DM dmInner;
979443836d0SMatthew G Knepley 
980443836d0SMatthew G Knepley         ierr = PetscSNPrintf(schurprefix, sizeof(schurprefix), "%sfieldsplit_%s_upper_", ((PetscObject)pc)->prefix ? ((PetscObject)pc)->prefix : "", ilink->splitname);CHKERRQ(ierr);
98182f516ccSBarry Smith         ierr = KSPCreate(PetscObjectComm((PetscObject)pc), &jac->kspupper);CHKERRQ(ierr);
982422a814eSBarry Smith         ierr = KSPSetErrorIfNotConverged(jac->kspupper,pc->erroriffailure);CHKERRQ(ierr);
983443836d0SMatthew G Knepley         ierr = KSPSetOptionsPrefix(jac->kspupper, schurprefix);CHKERRQ(ierr);
9842cc093acSMatthew G. Knepley         ierr = PetscObjectIncrementTabLevel((PetscObject)jac->kspupper, (PetscObject) pc, 1);CHKERRQ(ierr);
9852cc093acSMatthew G. Knepley         ierr = PetscObjectIncrementTabLevel((PetscObject)jac->kspupper->pc, (PetscObject) pc, 1);CHKERRQ(ierr);
986443836d0SMatthew G Knepley         ierr = KSPGetDM(jac->head->ksp, &dmInner);CHKERRQ(ierr);
987443836d0SMatthew G Knepley         ierr = KSPSetDM(jac->kspupper, dmInner);CHKERRQ(ierr);
988443836d0SMatthew G Knepley         ierr = KSPSetDMActive(jac->kspupper, PETSC_FALSE);CHKERRQ(ierr);
989443836d0SMatthew G Knepley         ierr = KSPSetFromOptions(jac->kspupper);CHKERRQ(ierr);
99023ee1639SBarry Smith         ierr = KSPSetOperators(jac->kspupper,jac->mat[0],jac->pmat[0]);CHKERRQ(ierr);
991443836d0SMatthew G Knepley         ierr = VecDuplicate(jac->head->x, &jac->head->z);CHKERRQ(ierr);
992443836d0SMatthew G Knepley       } else {
993443836d0SMatthew G Knepley         jac->kspupper = jac->head->ksp;
994443836d0SMatthew G Knepley         ierr          = PetscObjectReference((PetscObject) jac->head->ksp);CHKERRQ(ierr);
995443836d0SMatthew G Knepley       }
996443836d0SMatthew G Knepley 
997a7476a74SDmitry Karpeev       if (jac->schurpre == PC_FIELDSPLIT_SCHUR_PRE_SELFP) {
998a7476a74SDmitry Karpeev         ierr = MatSchurComplementGetPmat(jac->schur,MAT_INITIAL_MATRIX,&jac->schurp);CHKERRQ(ierr);
999a7476a74SDmitry Karpeev       }
1000ce94432eSBarry Smith       ierr = KSPCreate(PetscObjectComm((PetscObject)pc),&jac->kspschur);CHKERRQ(ierr);
1001422a814eSBarry Smith       ierr = KSPSetErrorIfNotConverged(jac->kspschur,pc->erroriffailure);CHKERRQ(ierr);
100297bbdb24SBarry Smith       ierr = PetscLogObjectParent((PetscObject)pc,(PetscObject)jac->kspschur);CHKERRQ(ierr);
100320252d06SBarry Smith       ierr = PetscObjectIncrementTabLevel((PetscObject)jac->kspschur,(PetscObject)pc,1);CHKERRQ(ierr);
100497bbdb24SBarry Smith       if (jac->schurpre == PC_FIELDSPLIT_SCHUR_PRE_SELF) {
10057233a360SDmitry Karpeev         PC pcschur;
10067233a360SDmitry Karpeev         ierr = KSPGetPC(jac->kspschur,&pcschur);CHKERRQ(ierr);
10077233a360SDmitry Karpeev         ierr = PCSetType(pcschur,PCNONE);CHKERRQ(ierr);
100897bbdb24SBarry Smith         /* Note: This is bad if there exist preconditioners for MATSCHURCOMPLEMENT */
1009e74569cdSMatthew G. Knepley       } else if (jac->schurpre == PC_FIELDSPLIT_SCHUR_PRE_FULL) {
1010e74569cdSMatthew G. Knepley         ierr = MatSchurComplementComputeExplicitOperator(jac->schur, &jac->schur_user);CHKERRQ(ierr);
101197bbdb24SBarry Smith       }
101223ee1639SBarry Smith       ierr = KSPSetOperators(jac->kspschur,jac->schur,FieldSplitSchurPre(jac));CHKERRQ(ierr);
101397bbdb24SBarry Smith       ierr = KSPGetOptionsPrefix(jac->head->next->ksp, &Dprefix);CHKERRQ(ierr);
101497bbdb24SBarry Smith       ierr = KSPSetOptionsPrefix(jac->kspschur,         Dprefix);CHKERRQ(ierr);
1015c096484dSStefano Zampini       /* propagate DM */
1016b20b4189SMatthew G. Knepley       {
1017b20b4189SMatthew G. Knepley         DM sdm;
1018b20b4189SMatthew G. Knepley         ierr = KSPGetDM(jac->head->next->ksp, &sdm);CHKERRQ(ierr);
1019b20b4189SMatthew G. Knepley         if (sdm) {
1020b20b4189SMatthew G. Knepley           ierr = KSPSetDM(jac->kspschur, sdm);CHKERRQ(ierr);
1021b20b4189SMatthew G. Knepley           ierr = KSPSetDMActive(jac->kspschur, PETSC_FALSE);CHKERRQ(ierr);
1022b20b4189SMatthew G. Knepley         }
1023b20b4189SMatthew G. Knepley       }
102497bbdb24SBarry Smith       /* really want setfromoptions called in PCSetFromOptions_FieldSplit(), but it is not ready yet */
102597bbdb24SBarry Smith       /* need to call this every time, since the jac->kspschur is freshly created, otherwise its options never get set */
102697bbdb24SBarry Smith       ierr = KSPSetFromOptions(jac->kspschur);CHKERRQ(ierr);
102797bbdb24SBarry Smith     }
1028686bed4dSStefano Zampini     ierr = MatAssemblyBegin(jac->schur,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1029686bed4dSStefano Zampini     ierr = MatAssemblyEnd(jac->schur,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
103097bbdb24SBarry Smith 
10315a9f2f41SSatish Balay     /* HACK: special support to forward L and Lp matrices that might be used by PCLSC */
10328caf3d72SBarry Smith     ierr = PetscSNPrintf(lscname,sizeof(lscname),"%s_LSC_L",ilink->splitname);CHKERRQ(ierr);
1033519d70e2SJed Brown     ierr = PetscObjectQuery((PetscObject)pc->mat,lscname,(PetscObject*)&LSC_L);CHKERRQ(ierr);
10343b224e63SBarry Smith     if (!LSC_L) {ierr = PetscObjectQuery((PetscObject)pc->pmat,lscname,(PetscObject*)&LSC_L);CHKERRQ(ierr);}
1035c1570756SJed Brown     if (LSC_L) {ierr = PetscObjectCompose((PetscObject)jac->schur,"LSC_L",(PetscObject)LSC_L);CHKERRQ(ierr);}
10368caf3d72SBarry Smith     ierr = PetscSNPrintf(lscname,sizeof(lscname),"%s_LSC_Lp",ilink->splitname);CHKERRQ(ierr);
103797bbdb24SBarry Smith     ierr = PetscObjectQuery((PetscObject)pc->pmat,lscname,(PetscObject*)&LSC_L);CHKERRQ(ierr);
10385a9f2f41SSatish Balay     if (!LSC_L) {ierr = PetscObjectQuery((PetscObject)pc->mat,lscname,(PetscObject*)&LSC_L);CHKERRQ(ierr);}
10390971522cSBarry Smith     if (LSC_L) {ierr = PetscObjectCompose((PetscObject)jac->schur,"LSC_Lp",(PetscObject)LSC_L);CHKERRQ(ierr);}
1040a51937d4SCarola Kruse   } else if (jac->type == PC_COMPOSITE_GKB) {
1041a51937d4SCarola Kruse     IS          ccis;
1042a51937d4SCarola Kruse     PetscInt    rstart,rend;
1043a51937d4SCarola Kruse 
10442c71b3e2SJacob Faibussowitsch     PetscCheckFalse(nsplit != 2,PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_INCOMP,"To use GKB preconditioner you must have exactly 2 fields");
1045a51937d4SCarola Kruse 
1046a51937d4SCarola Kruse     ilink = jac->head;
1047a51937d4SCarola Kruse 
1048a51937d4SCarola Kruse     /* When extracting off-diagonal submatrices, we take complements from this range */
1049a51937d4SCarola Kruse     ierr = MatGetOwnershipRangeColumn(pc->mat,&rstart,&rend);CHKERRQ(ierr);
1050a51937d4SCarola Kruse 
1051a51937d4SCarola Kruse     ierr = ISComplement(ilink->is_col,rstart,rend,&ccis);CHKERRQ(ierr);
1052a51937d4SCarola Kruse     if (jac->offdiag_use_amat) {
1053a51937d4SCarola Kruse       ierr = MatCreateSubMatrix(pc->mat,ilink->is,ccis,MAT_INITIAL_MATRIX,&jac->B);CHKERRQ(ierr);
1054a51937d4SCarola Kruse     } else {
1055a51937d4SCarola Kruse       ierr = MatCreateSubMatrix(pc->pmat,ilink->is,ccis,MAT_INITIAL_MATRIX,&jac->B);CHKERRQ(ierr);
1056a51937d4SCarola Kruse     }
1057a51937d4SCarola Kruse     ierr  = ISDestroy(&ccis);CHKERRQ(ierr);
1058e071a0a4SCarola Kruse     /* Create work vectors for GKB algorithm */
1059e071a0a4SCarola Kruse     ierr  = VecDuplicate(ilink->x,&jac->u);CHKERRQ(ierr);
1060e071a0a4SCarola Kruse     ierr  = VecDuplicate(ilink->x,&jac->Hu);CHKERRQ(ierr);
1061e071a0a4SCarola Kruse     ierr  = VecDuplicate(ilink->x,&jac->w2);CHKERRQ(ierr);
1062a51937d4SCarola Kruse     ilink = ilink->next;
1063a51937d4SCarola Kruse     ierr  = ISComplement(ilink->is_col,rstart,rend,&ccis);CHKERRQ(ierr);
1064a51937d4SCarola Kruse     if (jac->offdiag_use_amat) {
1065a51937d4SCarola Kruse       ierr = MatCreateSubMatrix(pc->mat,ilink->is,ccis,MAT_INITIAL_MATRIX,&jac->C);CHKERRQ(ierr);
1066a51937d4SCarola Kruse     } else {
1067a51937d4SCarola Kruse       ierr = MatCreateSubMatrix(pc->pmat,ilink->is,ccis,MAT_INITIAL_MATRIX,&jac->C);CHKERRQ(ierr);
1068a51937d4SCarola Kruse     }
1069a51937d4SCarola Kruse     ierr = ISDestroy(&ccis);CHKERRQ(ierr);
1070e071a0a4SCarola Kruse     /* Create work vectors for GKB algorithm */
1071e071a0a4SCarola Kruse     ierr = VecDuplicate(ilink->x,&jac->v);CHKERRQ(ierr);
1072e071a0a4SCarola Kruse     ierr = VecDuplicate(ilink->x,&jac->d);CHKERRQ(ierr);
1073e071a0a4SCarola Kruse     ierr = VecDuplicate(ilink->x,&jac->w1);CHKERRQ(ierr);
1074a51937d4SCarola Kruse     ierr = MatGolubKahanComputeExplicitOperator(jac->mat[0],jac->B,jac->C,&jac->H,jac->gkbnu);CHKERRQ(ierr);
1075e071a0a4SCarola Kruse     ierr = PetscCalloc1(jac->gkbdelay,&jac->vecz);CHKERRQ(ierr);
1076e071a0a4SCarola Kruse 
1077a51937d4SCarola Kruse     ilink = jac->head;
1078a51937d4SCarola Kruse     ierr  = KSPSetOperators(ilink->ksp,jac->H,jac->H);CHKERRQ(ierr);
1079a51937d4SCarola Kruse     if (!jac->suboptionsset) {ierr = KSPSetFromOptions(ilink->ksp);CHKERRQ(ierr);}
1080e071a0a4SCarola Kruse     /* Create gkb_monitor context */
1081de482cd7SCarola Kruse     if (jac->gkbmonitor) {
1082de482cd7SCarola Kruse       PetscInt  tablevel;
1083de482cd7SCarola Kruse       ierr = PetscViewerCreate(PETSC_COMM_WORLD,&jac->gkbviewer);CHKERRQ(ierr);
1084de482cd7SCarola Kruse       ierr = PetscViewerSetType(jac->gkbviewer,PETSCVIEWERASCII);CHKERRQ(ierr);
1085de482cd7SCarola Kruse       ierr = PetscObjectGetTabLevel((PetscObject)ilink->ksp,&tablevel);CHKERRQ(ierr);
1086e071a0a4SCarola Kruse       ierr = PetscViewerASCIISetTab(jac->gkbviewer,tablevel);CHKERRQ(ierr);
1087de482cd7SCarola Kruse       ierr = PetscObjectIncrementTabLevel((PetscObject)ilink->ksp,(PetscObject)ilink->ksp,1);CHKERRQ(ierr);
1088de482cd7SCarola Kruse     }
10890971522cSBarry Smith   } else {
109068bd789dSDmitry Karpeev     /* set up the individual splits' PCs */
10910971522cSBarry Smith     i     = 0;
10920971522cSBarry Smith     ilink = jac->head;
10930971522cSBarry Smith     while (ilink) {
109423ee1639SBarry Smith       ierr = KSPSetOperators(ilink->ksp,jac->mat[i],jac->pmat[i]);CHKERRQ(ierr);
10950971522cSBarry Smith       /* really want setfromoptions called in PCSetFromOptions_FieldSplit(), but it is not ready yet */
10960971522cSBarry Smith       if (!jac->suboptionsset) {ierr = KSPSetFromOptions(ilink->ksp);CHKERRQ(ierr);}
10970971522cSBarry Smith       i++;
10980971522cSBarry Smith       ilink = ilink->next;
10990971522cSBarry Smith     }
11003b224e63SBarry Smith   }
11013b224e63SBarry Smith 
1102*5ddf11f8SNicolas Barnafi   /* Set coordinates to the sub PC objects whenever these are set */
1103*5ddf11f8SNicolas Barnafi   if (jac->coordinates_set) {
1104*5ddf11f8SNicolas Barnafi     PC pc_coords;
1105*5ddf11f8SNicolas Barnafi     if (jac->type == PC_COMPOSITE_SCHUR) {
1106*5ddf11f8SNicolas Barnafi       // Head is first block.
1107*5ddf11f8SNicolas Barnafi       ierr = KSPGetPC(jac->head->ksp, &pc_coords);CHKERRQ(ierr);
1108*5ddf11f8SNicolas Barnafi       ierr = PCSetCoordinates(pc_coords, jac->head->dim, jac->head->ndofs, jac->head->coords);CHKERRQ(ierr);
1109*5ddf11f8SNicolas Barnafi       // Second one is Schur block, but its KSP object is in kspschur.
1110*5ddf11f8SNicolas Barnafi       ierr = KSPGetPC(jac->kspschur, &pc_coords);CHKERRQ(ierr);
1111*5ddf11f8SNicolas Barnafi       ierr = PCSetCoordinates(pc_coords, jac->head->next->dim, jac->head->next->ndofs, jac->head->next->coords);CHKERRQ(ierr);
1112*5ddf11f8SNicolas Barnafi     } else if (jac->type == PC_COMPOSITE_GKB) {
1113*5ddf11f8SNicolas Barnafi       ierr = PetscInfo(pc, "Warning: Setting coordinates does nothing for the GKB Fieldpslit preconditioner");CHKERRQ(ierr);
1114*5ddf11f8SNicolas Barnafi     } else {
1115*5ddf11f8SNicolas Barnafi       ilink = jac->head;
1116*5ddf11f8SNicolas Barnafi       while (ilink) {
1117*5ddf11f8SNicolas Barnafi         ierr = KSPGetPC(ilink->ksp, &pc_coords);CHKERRQ(ierr);
1118*5ddf11f8SNicolas Barnafi         ierr = PCSetCoordinates(pc_coords, ilink->dim, ilink->ndofs, ilink->coords);CHKERRQ(ierr);
1119*5ddf11f8SNicolas Barnafi         ilink = ilink->next;
1120*5ddf11f8SNicolas Barnafi       }
1121*5ddf11f8SNicolas Barnafi     }
1122*5ddf11f8SNicolas Barnafi   }
1123*5ddf11f8SNicolas Barnafi 
1124c1570756SJed Brown   jac->suboptionsset = PETSC_TRUE;
11250971522cSBarry Smith   PetscFunctionReturn(0);
11260971522cSBarry Smith }
11270971522cSBarry Smith 
11285a9f2f41SSatish Balay #define FieldSplitSplitSolveAdd(ilink,xx,yy) \
1129ca9f406cSSatish Balay   (VecScatterBegin(ilink->sctx,xx,ilink->x,INSERT_VALUES,SCATTER_FORWARD) || \
1130ca9f406cSSatish Balay    VecScatterEnd(ilink->sctx,xx,ilink->x,INSERT_VALUES,SCATTER_FORWARD) || \
11319df09d43SBarry Smith    PetscLogEventBegin(ilink->event,ilink->ksp,ilink->x,ilink->y,NULL) ||\
11325a9f2f41SSatish Balay    KSPSolve(ilink->ksp,ilink->x,ilink->y) ||                               \
1133c0decd05SBarry Smith    KSPCheckSolve(ilink->ksp,pc,ilink->y)  || \
11349df09d43SBarry Smith    PetscLogEventEnd(ilink->event,ilink->ksp,ilink->x,ilink->y,NULL) ||\
1135ca9f406cSSatish Balay    VecScatterBegin(ilink->sctx,ilink->y,yy,ADD_VALUES,SCATTER_REVERSE) ||  \
1136ca9f406cSSatish Balay    VecScatterEnd(ilink->sctx,ilink->y,yy,ADD_VALUES,SCATTER_REVERSE))
113779416396SBarry Smith 
11383b224e63SBarry Smith static PetscErrorCode PCApply_FieldSplit_Schur(PC pc,Vec x,Vec y)
11393b224e63SBarry Smith {
11403b224e63SBarry Smith   PC_FieldSplit      *jac = (PC_FieldSplit*)pc->data;
11413b224e63SBarry Smith   PetscErrorCode     ierr;
11423b224e63SBarry Smith   PC_FieldSplitLink  ilinkA = jac->head, ilinkD = ilinkA->next;
1143443836d0SMatthew G Knepley   KSP                kspA   = ilinkA->ksp, kspLower = kspA, kspUpper = jac->kspupper;
11443b224e63SBarry Smith 
11453b224e63SBarry Smith   PetscFunctionBegin;
1146c5d2311dSJed Brown   switch (jac->schurfactorization) {
1147c9c6ffaaSJed Brown   case PC_FIELDSPLIT_SCHUR_FACT_DIAG:
1148a04f6461SBarry Smith     /* [A00 0; 0 -S], positive definite, suitable for MINRES */
1149c5d2311dSJed Brown     ierr = VecScatterBegin(ilinkA->sctx,x,ilinkA->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1150c5d2311dSJed Brown     ierr = VecScatterBegin(ilinkD->sctx,x,ilinkD->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1151c5d2311dSJed Brown     ierr = VecScatterEnd(ilinkA->sctx,x,ilinkA->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
11529df09d43SBarry Smith     ierr = PetscLogEventBegin(ilinkA->event,kspA,ilinkA->x,ilinkA->y,NULL);CHKERRQ(ierr);
1153443836d0SMatthew G Knepley     ierr = KSPSolve(kspA,ilinkA->x,ilinkA->y);CHKERRQ(ierr);
1154c0decd05SBarry Smith     ierr = KSPCheckSolve(kspA,pc,ilinkA->y);CHKERRQ(ierr);
11559df09d43SBarry Smith     ierr = PetscLogEventEnd(ilinkA->event,kspA,ilinkA->x,ilinkA->y,NULL);CHKERRQ(ierr);
1156c5d2311dSJed Brown     ierr = VecScatterBegin(ilinkA->sctx,ilinkA->y,y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1157c5d2311dSJed Brown     ierr = VecScatterEnd(ilinkD->sctx,x,ilinkD->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
11589df09d43SBarry Smith     ierr = PetscLogEventBegin(KSP_Solve_FS_S,jac->kspschur,ilinkD->x,ilinkD->y,NULL);CHKERRQ(ierr);
1159c5d2311dSJed Brown     ierr = KSPSolve(jac->kspschur,ilinkD->x,ilinkD->y);CHKERRQ(ierr);
1160c0decd05SBarry Smith     ierr = KSPCheckSolve(jac->kspschur,pc,ilinkD->y);CHKERRQ(ierr);
11619df09d43SBarry Smith     ierr = PetscLogEventEnd(KSP_Solve_FS_S,jac->kspschur,ilinkD->x,ilinkD->y,NULL);CHKERRQ(ierr);
1162c096484dSStefano Zampini     ierr = VecScale(ilinkD->y,jac->schurscale);CHKERRQ(ierr);
1163c5d2311dSJed Brown     ierr = VecScatterEnd(ilinkA->sctx,ilinkA->y,y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1164653b62c3SJunchao Zhang     ierr = VecScatterBegin(ilinkD->sctx,ilinkD->y,y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1165c5d2311dSJed Brown     ierr = VecScatterEnd(ilinkD->sctx,ilinkD->y,y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1166c5d2311dSJed Brown     break;
1167c9c6ffaaSJed Brown   case PC_FIELDSPLIT_SCHUR_FACT_LOWER:
1168a04f6461SBarry Smith     /* [A00 0; A10 S], suitable for left preconditioning */
1169c5d2311dSJed Brown     ierr = VecScatterBegin(ilinkA->sctx,x,ilinkA->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1170c5d2311dSJed Brown     ierr = VecScatterEnd(ilinkA->sctx,x,ilinkA->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
11719df09d43SBarry Smith     ierr = PetscLogEventBegin(ilinkA->event,kspA,ilinkA->x,ilinkA->y,NULL);CHKERRQ(ierr);
1172443836d0SMatthew G Knepley     ierr = KSPSolve(kspA,ilinkA->x,ilinkA->y);CHKERRQ(ierr);
1173c0decd05SBarry Smith     ierr = KSPCheckSolve(kspA,pc,ilinkA->y);CHKERRQ(ierr);
11749df09d43SBarry Smith     ierr = PetscLogEventEnd(ilinkA->event,kspA,ilinkA->x,ilinkA->y,NULL);CHKERRQ(ierr);
1175c5d2311dSJed Brown     ierr = MatMult(jac->C,ilinkA->y,ilinkD->x);CHKERRQ(ierr);
1176c5d2311dSJed Brown     ierr = VecScale(ilinkD->x,-1.);CHKERRQ(ierr);
1177c5d2311dSJed Brown     ierr = VecScatterBegin(ilinkD->sctx,x,ilinkD->x,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1178c5d2311dSJed Brown     ierr = VecScatterBegin(ilinkA->sctx,ilinkA->y,y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1179c5d2311dSJed Brown     ierr = VecScatterEnd(ilinkD->sctx,x,ilinkD->x,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
11809df09d43SBarry Smith     ierr = PetscLogEventBegin(KSP_Solve_FS_S,jac->kspschur,ilinkD->x,ilinkD->y,NULL);CHKERRQ(ierr);
1181c5d2311dSJed Brown     ierr = KSPSolve(jac->kspschur,ilinkD->x,ilinkD->y);CHKERRQ(ierr);
1182c0decd05SBarry Smith     ierr = KSPCheckSolve(jac->kspschur,pc,ilinkD->y);CHKERRQ(ierr);
11839df09d43SBarry Smith     ierr = PetscLogEventEnd(KSP_Solve_FS_S,jac->kspschur,ilinkD->x,ilinkD->y,NULL);CHKERRQ(ierr);
1184c5d2311dSJed Brown     ierr = VecScatterEnd(ilinkA->sctx,ilinkA->y,y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1185653b62c3SJunchao Zhang     ierr = VecScatterBegin(ilinkD->sctx,ilinkD->y,y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1186c5d2311dSJed Brown     ierr = VecScatterEnd(ilinkD->sctx,ilinkD->y,y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1187c5d2311dSJed Brown     break;
1188c9c6ffaaSJed Brown   case PC_FIELDSPLIT_SCHUR_FACT_UPPER:
1189a04f6461SBarry Smith     /* [A00 A01; 0 S], suitable for right preconditioning */
1190c5d2311dSJed Brown     ierr = VecScatterBegin(ilinkD->sctx,x,ilinkD->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1191c5d2311dSJed Brown     ierr = VecScatterEnd(ilinkD->sctx,x,ilinkD->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
11929df09d43SBarry Smith     ierr = PetscLogEventBegin(KSP_Solve_FS_S,jac->kspschur,ilinkD->x,ilinkD->y,NULL);CHKERRQ(ierr);
1193c5d2311dSJed Brown     ierr = KSPSolve(jac->kspschur,ilinkD->x,ilinkD->y);CHKERRQ(ierr);
1194c0decd05SBarry Smith     ierr = KSPCheckSolve(jac->kspschur,pc,ilinkD->y);CHKERRQ(ierr);
11959df09d43SBarry 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);
1196c5d2311dSJed Brown     ierr = VecScale(ilinkA->x,-1.);CHKERRQ(ierr);
1197c5d2311dSJed Brown     ierr = VecScatterBegin(ilinkA->sctx,x,ilinkA->x,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1198c5d2311dSJed Brown     ierr = VecScatterBegin(ilinkD->sctx,ilinkD->y,y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1199c5d2311dSJed Brown     ierr = VecScatterEnd(ilinkA->sctx,x,ilinkA->x,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
12009df09d43SBarry Smith     ierr = PetscLogEventBegin(ilinkA->event,kspA,ilinkA->x,ilinkA->y,NULL);CHKERRQ(ierr);
1201443836d0SMatthew G Knepley     ierr = KSPSolve(kspA,ilinkA->x,ilinkA->y);CHKERRQ(ierr);
1202c0decd05SBarry Smith     ierr = KSPCheckSolve(kspA,pc,ilinkA->y);CHKERRQ(ierr);
12039df09d43SBarry Smith     ierr = PetscLogEventEnd(ilinkA->event,kspA,ilinkA->x,ilinkA->y,NULL);CHKERRQ(ierr);
1204c5d2311dSJed Brown     ierr = VecScatterEnd(ilinkD->sctx,ilinkD->y,y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1205653b62c3SJunchao Zhang     ierr = VecScatterBegin(ilinkA->sctx,ilinkA->y,y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1206c5d2311dSJed Brown     ierr = VecScatterEnd(ilinkA->sctx,ilinkA->y,y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1207c5d2311dSJed Brown     break;
1208c9c6ffaaSJed Brown   case PC_FIELDSPLIT_SCHUR_FACT_FULL:
1209c238f8cdSStefano Zampini     /* [1 0; A10 A00^{-1} 1] [A00 0; 0 S] [1 A00^{-1}A01; 0 1] */
12103b224e63SBarry Smith     ierr = VecScatterBegin(ilinkA->sctx,x,ilinkA->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
12113b224e63SBarry Smith     ierr = VecScatterEnd(ilinkA->sctx,x,ilinkA->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
12129df09d43SBarry Smith     ierr = PetscLogEventBegin(KSP_Solve_FS_L,kspLower,ilinkA->x,ilinkA->y,NULL);CHKERRQ(ierr);
1213443836d0SMatthew G Knepley     ierr = KSPSolve(kspLower,ilinkA->x,ilinkA->y);CHKERRQ(ierr);
1214c0decd05SBarry Smith     ierr = KSPCheckSolve(kspLower,pc,ilinkA->y);CHKERRQ(ierr);
12159df09d43SBarry Smith     ierr = PetscLogEventEnd(KSP_Solve_FS_L,kspLower,ilinkA->x,ilinkA->y,NULL);CHKERRQ(ierr);
12163b224e63SBarry Smith     ierr = MatMult(jac->C,ilinkA->y,ilinkD->x);CHKERRQ(ierr);
12173b224e63SBarry Smith     ierr = VecScale(ilinkD->x,-1.0);CHKERRQ(ierr);
12183b224e63SBarry Smith     ierr = VecScatterBegin(ilinkD->sctx,x,ilinkD->x,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
12193b224e63SBarry Smith     ierr = VecScatterEnd(ilinkD->sctx,x,ilinkD->x,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
12203b224e63SBarry Smith 
12219df09d43SBarry Smith     ierr = PetscLogEventBegin(KSP_Solve_FS_S,jac->kspschur,ilinkD->x,ilinkD->y,NULL);CHKERRQ(ierr);
12223b224e63SBarry Smith     ierr = KSPSolve(jac->kspschur,ilinkD->x,ilinkD->y);CHKERRQ(ierr);
1223c0decd05SBarry Smith     ierr = KSPCheckSolve(jac->kspschur,pc,ilinkD->y);CHKERRQ(ierr);
12249df09d43SBarry Smith     ierr = PetscLogEventEnd(KSP_Solve_FS_S,jac->kspschur,ilinkD->x,ilinkD->y,NULL);CHKERRQ(ierr);
12253b224e63SBarry Smith     ierr = VecScatterBegin(ilinkD->sctx,ilinkD->y,y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
12263b224e63SBarry Smith 
1227443836d0SMatthew G Knepley     if (kspUpper == kspA) {
12283b224e63SBarry Smith       ierr = MatMult(jac->B,ilinkD->y,ilinkA->y);CHKERRQ(ierr);
12293b224e63SBarry Smith       ierr = VecAXPY(ilinkA->x,-1.0,ilinkA->y);CHKERRQ(ierr);
12309df09d43SBarry Smith       ierr = PetscLogEventBegin(ilinkA->event,kspA,ilinkA->x,ilinkA->y,NULL);CHKERRQ(ierr);
1231443836d0SMatthew G Knepley       ierr = KSPSolve(kspA,ilinkA->x,ilinkA->y);CHKERRQ(ierr);
1232c0decd05SBarry Smith       ierr = KSPCheckSolve(kspA,pc,ilinkA->y);CHKERRQ(ierr);
12339df09d43SBarry Smith       ierr = PetscLogEventEnd(ilinkA->event,kspA,ilinkA->x,ilinkA->y,NULL);CHKERRQ(ierr);
1234443836d0SMatthew G Knepley     } else {
12359df09d43SBarry Smith       ierr = PetscLogEventBegin(ilinkA->event,kspA,ilinkA->x,ilinkA->y,NULL);CHKERRQ(ierr);
1236443836d0SMatthew G Knepley       ierr = KSPSolve(kspA,ilinkA->x,ilinkA->y);CHKERRQ(ierr);
1237c0decd05SBarry Smith       ierr = KSPCheckSolve(kspA,pc,ilinkA->y);CHKERRQ(ierr);
1238443836d0SMatthew G Knepley       ierr = MatMult(jac->B,ilinkD->y,ilinkA->x);CHKERRQ(ierr);
12399df09d43SBarry Smith       ierr = PetscLogEventBegin(KSP_Solve_FS_U,kspUpper,ilinkA->x,ilinkA->z,NULL);CHKERRQ(ierr);
1240443836d0SMatthew G Knepley       ierr = KSPSolve(kspUpper,ilinkA->x,ilinkA->z);CHKERRQ(ierr);
1241c0decd05SBarry Smith       ierr = KSPCheckSolve(kspUpper,pc,ilinkA->z);CHKERRQ(ierr);
12429df09d43SBarry Smith       ierr = PetscLogEventEnd(KSP_Solve_FS_U,kspUpper,ilinkA->x,ilinkA->z,NULL);CHKERRQ(ierr);
1243443836d0SMatthew G Knepley       ierr = VecAXPY(ilinkA->y,-1.0,ilinkA->z);CHKERRQ(ierr);
1244443836d0SMatthew G Knepley     }
1245c238f8cdSStefano Zampini     ierr = VecScatterEnd(ilinkD->sctx,ilinkD->y,y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
12463b224e63SBarry Smith     ierr = VecScatterBegin(ilinkA->sctx,ilinkA->y,y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
12473b224e63SBarry Smith     ierr = VecScatterEnd(ilinkA->sctx,ilinkA->y,y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1248c5d2311dSJed Brown   }
12493b224e63SBarry Smith   PetscFunctionReturn(0);
12503b224e63SBarry Smith }
12513b224e63SBarry Smith 
12520971522cSBarry Smith static PetscErrorCode PCApply_FieldSplit(PC pc,Vec x,Vec y)
12530971522cSBarry Smith {
12540971522cSBarry Smith   PC_FieldSplit      *jac = (PC_FieldSplit*)pc->data;
12550971522cSBarry Smith   PetscErrorCode     ierr;
12565a9f2f41SSatish Balay   PC_FieldSplitLink  ilink = jac->head;
1257939b8a20SBarry Smith   PetscInt           cnt,bs;
12580971522cSBarry Smith 
12590971522cSBarry Smith   PetscFunctionBegin;
126079416396SBarry Smith   if (jac->type == PC_COMPOSITE_ADDITIVE) {
12611b9fc7fcSBarry Smith     if (jac->defaultsplit) {
1262939b8a20SBarry Smith       ierr = VecGetBlockSize(x,&bs);CHKERRQ(ierr);
12632c71b3e2SJacob Faibussowitsch       PetscCheckFalse(jac->bs > 0 && bs != jac->bs,PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONGSTATE,"Blocksize of x vector %D does not match fieldsplit blocksize %D",bs,jac->bs);
1264939b8a20SBarry Smith       ierr = VecGetBlockSize(y,&bs);CHKERRQ(ierr);
12652c71b3e2SJacob Faibussowitsch       PetscCheckFalse(jac->bs > 0 && bs != jac->bs,PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONGSTATE,"Blocksize of y vector %D does not match fieldsplit blocksize %D",bs,jac->bs);
12660971522cSBarry Smith       ierr = VecStrideGatherAll(x,jac->x,INSERT_VALUES);CHKERRQ(ierr);
12675a9f2f41SSatish Balay       while (ilink) {
12689df09d43SBarry Smith         ierr = PetscLogEventBegin(ilink->event,ilink->ksp,ilink->x,ilink->y,NULL);CHKERRQ(ierr);
12695a9f2f41SSatish Balay         ierr = KSPSolve(ilink->ksp,ilink->x,ilink->y);CHKERRQ(ierr);
1270c0decd05SBarry Smith         ierr = KSPCheckSolve(ilink->ksp,pc,ilink->y);CHKERRQ(ierr);
12719df09d43SBarry Smith         ierr = PetscLogEventEnd(ilink->event,ilink->ksp,ilink->x,ilink->y,NULL);CHKERRQ(ierr);
12725a9f2f41SSatish Balay         ilink = ilink->next;
12730971522cSBarry Smith       }
12740971522cSBarry Smith       ierr = VecStrideScatterAll(jac->y,y,INSERT_VALUES);CHKERRQ(ierr);
12751b9fc7fcSBarry Smith     } else {
1276efb30889SBarry Smith       ierr = VecSet(y,0.0);CHKERRQ(ierr);
12775a9f2f41SSatish Balay       while (ilink) {
12785a9f2f41SSatish Balay         ierr = FieldSplitSplitSolveAdd(ilink,x,y);CHKERRQ(ierr);
12795a9f2f41SSatish Balay         ilink = ilink->next;
12801b9fc7fcSBarry Smith       }
12811b9fc7fcSBarry Smith     }
1282e52d2c62SBarry Smith   } else if (jac->type == PC_COMPOSITE_MULTIPLICATIVE && jac->nsplits == 2) {
1283e52d2c62SBarry Smith     ierr = VecSet(y,0.0);CHKERRQ(ierr);
1284e52d2c62SBarry Smith     /* solve on first block for first block variables */
1285e52d2c62SBarry Smith     ierr = VecScatterBegin(ilink->sctx,x,ilink->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1286e52d2c62SBarry Smith     ierr = VecScatterEnd(ilink->sctx,x,ilink->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
12879df09d43SBarry Smith     ierr = PetscLogEventBegin(ilink->event,ilink->ksp,ilink->x,ilink->y,NULL);CHKERRQ(ierr);
1288e52d2c62SBarry Smith     ierr = KSPSolve(ilink->ksp,ilink->x,ilink->y);CHKERRQ(ierr);
1289c0decd05SBarry Smith     ierr = KSPCheckSolve(ilink->ksp,pc,ilink->y);CHKERRQ(ierr);
12909df09d43SBarry Smith     ierr = PetscLogEventEnd(ilink->event,ilink->ksp,ilink->x,ilink->y,NULL);CHKERRQ(ierr);
1291e52d2c62SBarry Smith     ierr = VecScatterBegin(ilink->sctx,ilink->y,y,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1292e52d2c62SBarry Smith     ierr = VecScatterEnd(ilink->sctx,ilink->y,y,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1293e52d2c62SBarry Smith 
1294e52d2c62SBarry Smith     /* compute the residual only onto second block variables using first block variables */
1295e52d2c62SBarry Smith     ierr = MatMult(jac->Afield[1],ilink->y,ilink->next->x);CHKERRQ(ierr);
1296e52d2c62SBarry Smith     ilink = ilink->next;
1297e52d2c62SBarry Smith     ierr = VecScale(ilink->x,-1.0);CHKERRQ(ierr);
1298e52d2c62SBarry Smith     ierr = VecScatterBegin(ilink->sctx,x,ilink->x,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1299e52d2c62SBarry Smith     ierr = VecScatterEnd(ilink->sctx,x,ilink->x,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1300e52d2c62SBarry Smith 
1301e52d2c62SBarry Smith     /* solve on second block variables */
13029df09d43SBarry Smith     ierr = PetscLogEventBegin(ilink->event,ilink->ksp,ilink->x,ilink->y,NULL);CHKERRQ(ierr);
1303e52d2c62SBarry Smith     ierr = KSPSolve(ilink->ksp,ilink->x,ilink->y);CHKERRQ(ierr);
1304c0decd05SBarry Smith     ierr = KSPCheckSolve(ilink->ksp,pc,ilink->y);CHKERRQ(ierr);
13059df09d43SBarry Smith     ierr = PetscLogEventEnd(ilink->event,ilink->ksp,ilink->x,ilink->y,NULL);CHKERRQ(ierr);
1306e52d2c62SBarry Smith     ierr = VecScatterBegin(ilink->sctx,ilink->y,y,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1307e52d2c62SBarry Smith     ierr = VecScatterEnd(ilink->sctx,ilink->y,y,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
130816913363SBarry Smith   } else if (jac->type == PC_COMPOSITE_MULTIPLICATIVE || jac->type == PC_COMPOSITE_SYMMETRIC_MULTIPLICATIVE) {
130979416396SBarry Smith     if (!jac->w1) {
131079416396SBarry Smith       ierr = VecDuplicate(x,&jac->w1);CHKERRQ(ierr);
131179416396SBarry Smith       ierr = VecDuplicate(x,&jac->w2);CHKERRQ(ierr);
131279416396SBarry Smith     }
1313efb30889SBarry Smith     ierr = VecSet(y,0.0);CHKERRQ(ierr);
13145a9f2f41SSatish Balay     ierr = FieldSplitSplitSolveAdd(ilink,x,y);CHKERRQ(ierr);
13153e197d65SBarry Smith     cnt  = 1;
13165a9f2f41SSatish Balay     while (ilink->next) {
13175a9f2f41SSatish Balay       ilink = ilink->next;
13183e197d65SBarry Smith       /* compute the residual only over the part of the vector needed */
13193e197d65SBarry Smith       ierr = MatMult(jac->Afield[cnt++],y,ilink->x);CHKERRQ(ierr);
13203e197d65SBarry Smith       ierr = VecScale(ilink->x,-1.0);CHKERRQ(ierr);
13213e197d65SBarry Smith       ierr = VecScatterBegin(ilink->sctx,x,ilink->x,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
13223e197d65SBarry Smith       ierr = VecScatterEnd(ilink->sctx,x,ilink->x,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
13239df09d43SBarry Smith       ierr = PetscLogEventBegin(ilink->event,ilink->ksp,ilink->x,ilink->y,NULL);CHKERRQ(ierr);
13243e197d65SBarry Smith       ierr = KSPSolve(ilink->ksp,ilink->x,ilink->y);CHKERRQ(ierr);
1325c0decd05SBarry Smith       ierr = KSPCheckSolve(ilink->ksp,pc,ilink->y);CHKERRQ(ierr);
13269df09d43SBarry Smith       ierr = PetscLogEventEnd(ilink->event,ilink->ksp,ilink->x,ilink->y,NULL);CHKERRQ(ierr);
13273e197d65SBarry Smith       ierr = VecScatterBegin(ilink->sctx,ilink->y,y,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
13283e197d65SBarry Smith       ierr = VecScatterEnd(ilink->sctx,ilink->y,y,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
13293e197d65SBarry Smith     }
133051f519a2SBarry Smith     if (jac->type == PC_COMPOSITE_SYMMETRIC_MULTIPLICATIVE) {
133111755939SBarry Smith       cnt -= 2;
133251f519a2SBarry Smith       while (ilink->previous) {
133351f519a2SBarry Smith         ilink = ilink->previous;
133411755939SBarry Smith         /* compute the residual only over the part of the vector needed */
133511755939SBarry Smith         ierr = MatMult(jac->Afield[cnt--],y,ilink->x);CHKERRQ(ierr);
133611755939SBarry Smith         ierr = VecScale(ilink->x,-1.0);CHKERRQ(ierr);
133711755939SBarry Smith         ierr = VecScatterBegin(ilink->sctx,x,ilink->x,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
133811755939SBarry Smith         ierr = VecScatterEnd(ilink->sctx,x,ilink->x,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
13399df09d43SBarry Smith         ierr = PetscLogEventBegin(ilink->event,ilink->ksp,ilink->x,ilink->y,NULL);CHKERRQ(ierr);
134011755939SBarry Smith         ierr = KSPSolve(ilink->ksp,ilink->x,ilink->y);CHKERRQ(ierr);
1341c0decd05SBarry Smith         ierr = KSPCheckSolve(ilink->ksp,pc,ilink->y);CHKERRQ(ierr);
13429df09d43SBarry Smith         ierr = PetscLogEventEnd(ilink->event,ilink->ksp,ilink->x,ilink->y,NULL);CHKERRQ(ierr);
134311755939SBarry Smith         ierr = VecScatterBegin(ilink->sctx,ilink->y,y,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
134411755939SBarry Smith         ierr = VecScatterEnd(ilink->sctx,ilink->y,y,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
134551f519a2SBarry Smith       }
134611755939SBarry Smith     }
134798921bdaSJacob Faibussowitsch   } else SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Unsupported or unknown composition",(int) jac->type);
13480971522cSBarry Smith   PetscFunctionReturn(0);
13490971522cSBarry Smith }
13500971522cSBarry Smith 
1351a51937d4SCarola Kruse static PetscErrorCode PCApply_FieldSplit_GKB(PC pc,Vec x,Vec y)
1352a51937d4SCarola Kruse {
1353a51937d4SCarola Kruse   PC_FieldSplit      *jac = (PC_FieldSplit*)pc->data;
1354a51937d4SCarola Kruse   PetscErrorCode     ierr;
1355a51937d4SCarola Kruse   PC_FieldSplitLink  ilinkA = jac->head,ilinkD = ilinkA->next;
1356a51937d4SCarola Kruse   KSP                ksp = ilinkA->ksp;
1357de482cd7SCarola Kruse   Vec                u,v,Hu,d,work1,work2;
1358e071a0a4SCarola Kruse   PetscScalar        alpha,z,nrmz2,*vecz;
1359e071a0a4SCarola Kruse   PetscReal          lowbnd,nu,beta;
1360a51937d4SCarola Kruse   PetscInt           j,iterGKB;
1361a51937d4SCarola Kruse 
1362a51937d4SCarola Kruse   PetscFunctionBegin;
1363a51937d4SCarola Kruse   ierr = VecScatterBegin(ilinkA->sctx,x,ilinkA->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1364a51937d4SCarola Kruse   ierr = VecScatterBegin(ilinkD->sctx,x,ilinkD->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1365de482cd7SCarola Kruse   ierr = VecScatterEnd(ilinkA->sctx,x,ilinkA->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1366a51937d4SCarola Kruse   ierr = VecScatterEnd(ilinkD->sctx,x,ilinkD->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1367e071a0a4SCarola Kruse 
1368e071a0a4SCarola Kruse   u     = jac->u;
1369e071a0a4SCarola Kruse   v     = jac->v;
1370e071a0a4SCarola Kruse   Hu    = jac->Hu;
1371e071a0a4SCarola Kruse   d     = jac->d;
1372e071a0a4SCarola Kruse   work1 = jac->w1;
1373e071a0a4SCarola Kruse   work2 = jac->w2;
1374e071a0a4SCarola Kruse   vecz  = jac->vecz;
1375a51937d4SCarola Kruse 
1376a51937d4SCarola Kruse   /* Change RHS to comply with matrix regularization H = A + nu*B*B' */
1377a51937d4SCarola Kruse   /* Add q = q + nu*B*b */
1378a51937d4SCarola Kruse   if (jac->gkbnu) {
1379a51937d4SCarola Kruse     nu = jac->gkbnu;
1380de482cd7SCarola Kruse     ierr = VecScale(ilinkD->x,jac->gkbnu);CHKERRQ(ierr);
1381de482cd7SCarola Kruse     ierr = MatMultAdd(jac->B,ilinkD->x,ilinkA->x,ilinkA->x);CHKERRQ(ierr);            /* q = q + nu*B*b */
1382a51937d4SCarola Kruse   } else {
1383a51937d4SCarola Kruse     /* Situation when no augmented Lagrangian is used. Then we set inner  */
1384a51937d4SCarola Kruse     /* matrix N = I in [Ar13], and thus nu = 1.                           */
1385a51937d4SCarola Kruse     nu = 1;
1386a51937d4SCarola Kruse   }
1387a51937d4SCarola Kruse 
1388a51937d4SCarola Kruse   /* Transform rhs from [q,tilde{b}] to [0,b] */
1389de482cd7SCarola Kruse   ierr = PetscLogEventBegin(ilinkA->event,ksp,ilinkA->x,ilinkA->y,NULL);CHKERRQ(ierr);
1390de482cd7SCarola Kruse   ierr = KSPSolve(ksp,ilinkA->x,ilinkA->y);CHKERRQ(ierr);
1391c0decd05SBarry Smith   ierr = KSPCheckSolve(ksp,pc,ilinkA->y);CHKERRQ(ierr);
1392de482cd7SCarola Kruse   ierr = PetscLogEventEnd(ilinkA->event,ksp,ilinkA->x,ilinkA->y,NULL);CHKERRQ(ierr);
1393a51937d4SCarola Kruse   ierr = MatMultHermitianTranspose(jac->B,ilinkA->y,work1);CHKERRQ(ierr);
139492c1e38eSCarola Kruse   ierr = VecAXPBY(work1,1.0/nu,-1.0,ilinkD->x);CHKERRQ(ierr);            /* c = b - B'*x        */
1395a51937d4SCarola Kruse 
1396a51937d4SCarola Kruse   /* First step of algorithm */
1397de482cd7SCarola Kruse   ierr  = VecNorm(work1,NORM_2,&beta);CHKERRQ(ierr);                   /* beta = sqrt(nu*c'*c)*/
1398e071a0a4SCarola Kruse   KSPCheckDot(ksp,beta);
1399addd1e01SJunchao Zhang   beta  = PetscSqrtReal(nu)*beta;
140092c1e38eSCarola Kruse   ierr  = VecAXPBY(v,nu/beta,0.0,work1);CHKERRQ(ierr);                   /* v = nu/beta *c      */
1401a51937d4SCarola Kruse   ierr  = MatMult(jac->B,v,work2);CHKERRQ(ierr);                       /* u = H^{-1}*B*v      */
1402a51937d4SCarola Kruse   ierr  = PetscLogEventBegin(ilinkA->event,ksp,work2,u,NULL);CHKERRQ(ierr);
1403a51937d4SCarola Kruse   ierr  = KSPSolve(ksp,work2,u);CHKERRQ(ierr);
1404c0decd05SBarry Smith   ierr  = KSPCheckSolve(ksp,pc,u);CHKERRQ(ierr);
1405a51937d4SCarola Kruse   ierr  = PetscLogEventEnd(ilinkA->event,ksp,work2,u,NULL);CHKERRQ(ierr);
1406a51937d4SCarola Kruse   ierr  = MatMult(jac->H,u,Hu);CHKERRQ(ierr);                          /* alpha = u'*H*u      */
1407a51937d4SCarola Kruse   ierr  = VecDot(Hu,u,&alpha);CHKERRQ(ierr);
1408e071a0a4SCarola Kruse   KSPCheckDot(ksp,alpha);
14092c71b3e2SJacob Faibussowitsch   PetscCheckFalse(PetscRealPart(alpha) <= 0.0,PETSC_COMM_SELF,PETSC_ERR_NOT_CONVERGED,"GKB preconditioner diverged, H is not positive definite");
1410addd1e01SJunchao Zhang   alpha = PetscSqrtReal(PetscAbsScalar(alpha));
141192c1e38eSCarola Kruse   ierr  = VecScale(u,1.0/alpha);CHKERRQ(ierr);
141292c1e38eSCarola Kruse   ierr  = VecAXPBY(d,1.0/alpha,0.0,v);CHKERRQ(ierr);                       /* v = nu/beta *c      */
1413de482cd7SCarola Kruse 
1414a51937d4SCarola Kruse   z = beta/alpha;
1415a51937d4SCarola Kruse   vecz[1] = z;
1416a51937d4SCarola Kruse 
1417de482cd7SCarola Kruse   /* Computation of first iterate x(1) and p(1) */
1418a51937d4SCarola Kruse   ierr = VecAXPY(ilinkA->y,z,u);CHKERRQ(ierr);
1419a51937d4SCarola Kruse   ierr = VecCopy(d,ilinkD->y);CHKERRQ(ierr);
1420a51937d4SCarola Kruse   ierr = VecScale(ilinkD->y,-z);CHKERRQ(ierr);
1421a51937d4SCarola Kruse 
1422a51937d4SCarola Kruse   iterGKB = 1; lowbnd = 2*jac->gkbtol;
1423de482cd7SCarola Kruse   if (jac->gkbmonitor) {
1424de482cd7SCarola Kruse       ierr = PetscViewerASCIIPrintf(jac->gkbviewer,"%3D GKB Lower bound estimate %14.12e\n",iterGKB,lowbnd);CHKERRQ(ierr);
1425de482cd7SCarola Kruse   }
1426de482cd7SCarola Kruse 
1427a51937d4SCarola Kruse   while (iterGKB < jac->gkbmaxit && lowbnd > jac->gkbtol) {
1428a51937d4SCarola Kruse     iterGKB += 1;
1429e071a0a4SCarola Kruse     ierr  = MatMultHermitianTranspose(jac->B,u,work1);CHKERRQ(ierr); /* v <- nu*(B'*u-alpha/nu*v) */
1430e071a0a4SCarola Kruse     ierr  = VecAXPBY(v,nu,-alpha,work1);CHKERRQ(ierr);
1431e071a0a4SCarola Kruse     ierr  = VecNorm(v,NORM_2,&beta);CHKERRQ(ierr);                   /* beta = sqrt(nu)*v'*v      */
1432addd1e01SJunchao Zhang     beta  = beta/PetscSqrtReal(nu);
143392c1e38eSCarola Kruse     ierr  = VecScale(v,1.0/beta);CHKERRQ(ierr);
1434e071a0a4SCarola Kruse     ierr  = MatMult(jac->B,v,work2);CHKERRQ(ierr);                  /* u <- H^{-1}*(B*v-beta*H*u) */
1435a51937d4SCarola Kruse     ierr  = MatMult(jac->H,u,Hu);CHKERRQ(ierr);
1436a51937d4SCarola Kruse     ierr  = VecAXPY(work2,-beta,Hu);CHKERRQ(ierr);
1437a51937d4SCarola Kruse     ierr  = PetscLogEventBegin(ilinkA->event,ksp,work2,u,NULL);CHKERRQ(ierr);
1438a51937d4SCarola Kruse     ierr  = KSPSolve(ksp,work2,u);CHKERRQ(ierr);
1439c0decd05SBarry Smith     ierr  = KSPCheckSolve(ksp,pc,u);CHKERRQ(ierr);
1440a51937d4SCarola Kruse     ierr  = PetscLogEventEnd(ilinkA->event,ksp,work2,u,NULL);CHKERRQ(ierr);
1441a51937d4SCarola Kruse     ierr  = MatMult(jac->H,u,Hu);CHKERRQ(ierr);                      /* alpha = u'*H*u            */
1442a51937d4SCarola Kruse     ierr  = VecDot(Hu,u,&alpha);CHKERRQ(ierr);
1443e071a0a4SCarola Kruse     KSPCheckDot(ksp,alpha);
14442c71b3e2SJacob Faibussowitsch     PetscCheckFalse(PetscRealPart(alpha) <= 0.0,PETSC_COMM_SELF,PETSC_ERR_NOT_CONVERGED,"GKB preconditioner diverged, H is not positive definite");
1445addd1e01SJunchao Zhang     alpha = PetscSqrtReal(PetscAbsScalar(alpha));
144692c1e38eSCarola Kruse     ierr  = VecScale(u,1.0/alpha);CHKERRQ(ierr);
1447a51937d4SCarola Kruse 
1448e071a0a4SCarola Kruse     z = -beta/alpha*z;                                            /* z <- beta/alpha*z     */
1449a51937d4SCarola Kruse     vecz[0] = z;
1450a51937d4SCarola Kruse 
1451a51937d4SCarola Kruse     /* Computation of new iterate x(i+1) and p(i+1) */
145292c1e38eSCarola Kruse     ierr = VecAXPBY(d,1.0/alpha,-beta/alpha,v);CHKERRQ(ierr);       /* d = (v-beta*d)/alpha */
1453a51937d4SCarola Kruse     ierr = VecAXPY(ilinkA->y,z,u);CHKERRQ(ierr);                  /* r = r + z*u          */
1454a51937d4SCarola Kruse     ierr = VecAXPY(ilinkD->y,-z,d);CHKERRQ(ierr);                 /* p = p - z*d          */
1455de482cd7SCarola Kruse     ierr = MatMult(jac->H,ilinkA->y,Hu);CHKERRQ(ierr);            /* ||u||_H = u'*H*u     */
1456a51937d4SCarola Kruse     ierr = VecDot(Hu,ilinkA->y,&nrmz2);CHKERRQ(ierr);
1457a51937d4SCarola Kruse 
1458a51937d4SCarola Kruse     /* Compute Lower Bound estimate */
1459a51937d4SCarola Kruse     if (iterGKB > jac->gkbdelay) {
1460a51937d4SCarola Kruse       lowbnd = 0.0;
1461a51937d4SCarola Kruse       for (j=0; j<jac->gkbdelay; j++) {
1462a51937d4SCarola Kruse         lowbnd += PetscAbsScalar(vecz[j]*vecz[j]);
1463a51937d4SCarola Kruse       }
1464addd1e01SJunchao Zhang       lowbnd = PetscSqrtReal(lowbnd/PetscAbsScalar(nrmz2));
1465a51937d4SCarola Kruse     }
1466a51937d4SCarola Kruse 
1467a51937d4SCarola Kruse     for (j=0; j<jac->gkbdelay-1; j++) {
1468a51937d4SCarola Kruse       vecz[jac->gkbdelay-j-1] = vecz[jac->gkbdelay-j-2];
1469a51937d4SCarola Kruse     }
1470de482cd7SCarola Kruse     if (jac->gkbmonitor) {
1471de482cd7SCarola Kruse       ierr = PetscViewerASCIIPrintf(jac->gkbviewer,"%3D GKB Lower bound estimate %14.12e\n",iterGKB,lowbnd);CHKERRQ(ierr);
1472de482cd7SCarola Kruse     }
1473a51937d4SCarola Kruse   }
1474a51937d4SCarola Kruse 
1475a51937d4SCarola Kruse   ierr = VecScatterBegin(ilinkA->sctx,ilinkA->y,y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1476de482cd7SCarola Kruse   ierr = VecScatterEnd(ilinkA->sctx,ilinkA->y,y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1477a29b4eb7SJunchao Zhang   ierr = VecScatterBegin(ilinkD->sctx,ilinkD->y,y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1478a51937d4SCarola Kruse   ierr = VecScatterEnd(ilinkD->sctx,ilinkD->y,y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1479a51937d4SCarola Kruse 
1480a51937d4SCarola Kruse   PetscFunctionReturn(0);
1481a51937d4SCarola Kruse }
1482a51937d4SCarola Kruse 
1483421e10b8SBarry Smith #define FieldSplitSplitSolveAddTranspose(ilink,xx,yy) \
1484ca9f406cSSatish Balay   (VecScatterBegin(ilink->sctx,xx,ilink->y,INSERT_VALUES,SCATTER_FORWARD) || \
1485ca9f406cSSatish Balay    VecScatterEnd(ilink->sctx,xx,ilink->y,INSERT_VALUES,SCATTER_FORWARD) || \
14869df09d43SBarry Smith    PetscLogEventBegin(ilink->event,ilink->ksp,ilink->y,ilink->x,NULL) || \
1487421e10b8SBarry Smith    KSPSolveTranspose(ilink->ksp,ilink->y,ilink->x) ||                  \
1488c0decd05SBarry Smith    KSPCheckSolve(ilink->ksp,pc,ilink->x) || \
1489c0decd05SBarry Smith    PetscLogEventEnd(ilink->event,ilink->ksp,ilink->y,ilink->x,NULL) ||   \
1490ca9f406cSSatish Balay    VecScatterBegin(ilink->sctx,ilink->x,yy,ADD_VALUES,SCATTER_REVERSE) || \
1491ca9f406cSSatish Balay    VecScatterEnd(ilink->sctx,ilink->x,yy,ADD_VALUES,SCATTER_REVERSE))
1492421e10b8SBarry Smith 
1493421e10b8SBarry Smith static PetscErrorCode PCApplyTranspose_FieldSplit(PC pc,Vec x,Vec y)
1494421e10b8SBarry Smith {
1495421e10b8SBarry Smith   PC_FieldSplit      *jac = (PC_FieldSplit*)pc->data;
1496421e10b8SBarry Smith   PetscErrorCode     ierr;
1497421e10b8SBarry Smith   PC_FieldSplitLink  ilink = jac->head;
1498939b8a20SBarry Smith   PetscInt           bs;
1499421e10b8SBarry Smith 
1500421e10b8SBarry Smith   PetscFunctionBegin;
1501421e10b8SBarry Smith   if (jac->type == PC_COMPOSITE_ADDITIVE) {
1502421e10b8SBarry Smith     if (jac->defaultsplit) {
1503939b8a20SBarry Smith       ierr = VecGetBlockSize(x,&bs);CHKERRQ(ierr);
15042c71b3e2SJacob Faibussowitsch       PetscCheckFalse(jac->bs > 0 && bs != jac->bs,PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONGSTATE,"Blocksize of x vector %D does not match fieldsplit blocksize %D",bs,jac->bs);
1505939b8a20SBarry Smith       ierr = VecGetBlockSize(y,&bs);CHKERRQ(ierr);
15062c71b3e2SJacob Faibussowitsch       PetscCheckFalse(jac->bs > 0 && bs != jac->bs,PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONGSTATE,"Blocksize of y vector %D does not match fieldsplit blocksize %D",bs,jac->bs);
1507421e10b8SBarry Smith       ierr = VecStrideGatherAll(x,jac->x,INSERT_VALUES);CHKERRQ(ierr);
1508421e10b8SBarry Smith       while (ilink) {
15099df09d43SBarry Smith         ierr = PetscLogEventBegin(ilink->event,ilink->ksp,ilink->x,ilink->y,NULL);CHKERRQ(ierr);
1510421e10b8SBarry Smith         ierr = KSPSolveTranspose(ilink->ksp,ilink->x,ilink->y);CHKERRQ(ierr);
1511c0decd05SBarry Smith         ierr = KSPCheckSolve(ilink->ksp,pc,ilink->y);CHKERRQ(ierr);
15129df09d43SBarry Smith         ierr = PetscLogEventEnd(ilink->event,ilink->ksp,ilink->x,ilink->y,NULL);CHKERRQ(ierr);
1513421e10b8SBarry Smith         ilink = ilink->next;
1514421e10b8SBarry Smith       }
1515421e10b8SBarry Smith       ierr = VecStrideScatterAll(jac->y,y,INSERT_VALUES);CHKERRQ(ierr);
1516421e10b8SBarry Smith     } else {
1517421e10b8SBarry Smith       ierr = VecSet(y,0.0);CHKERRQ(ierr);
1518421e10b8SBarry Smith       while (ilink) {
1519421e10b8SBarry Smith         ierr = FieldSplitSplitSolveAddTranspose(ilink,x,y);CHKERRQ(ierr);
1520421e10b8SBarry Smith         ilink = ilink->next;
1521421e10b8SBarry Smith       }
1522421e10b8SBarry Smith     }
1523421e10b8SBarry Smith   } else {
1524421e10b8SBarry Smith     if (!jac->w1) {
1525421e10b8SBarry Smith       ierr = VecDuplicate(x,&jac->w1);CHKERRQ(ierr);
1526421e10b8SBarry Smith       ierr = VecDuplicate(x,&jac->w2);CHKERRQ(ierr);
1527421e10b8SBarry Smith     }
1528421e10b8SBarry Smith     ierr = VecSet(y,0.0);CHKERRQ(ierr);
1529421e10b8SBarry Smith     if (jac->type == PC_COMPOSITE_SYMMETRIC_MULTIPLICATIVE) {
1530421e10b8SBarry Smith       ierr = FieldSplitSplitSolveAddTranspose(ilink,x,y);CHKERRQ(ierr);
1531421e10b8SBarry Smith       while (ilink->next) {
1532421e10b8SBarry Smith         ilink = ilink->next;
15339989ab13SBarry Smith         ierr  = MatMultTranspose(pc->mat,y,jac->w1);CHKERRQ(ierr);
1534421e10b8SBarry Smith         ierr  = VecWAXPY(jac->w2,-1.0,jac->w1,x);CHKERRQ(ierr);
1535421e10b8SBarry Smith         ierr  = FieldSplitSplitSolveAddTranspose(ilink,jac->w2,y);CHKERRQ(ierr);
1536421e10b8SBarry Smith       }
1537421e10b8SBarry Smith       while (ilink->previous) {
1538421e10b8SBarry Smith         ilink = ilink->previous;
15399989ab13SBarry Smith         ierr  = MatMultTranspose(pc->mat,y,jac->w1);CHKERRQ(ierr);
1540421e10b8SBarry Smith         ierr  = VecWAXPY(jac->w2,-1.0,jac->w1,x);CHKERRQ(ierr);
1541421e10b8SBarry Smith         ierr  = FieldSplitSplitSolveAddTranspose(ilink,jac->w2,y);CHKERRQ(ierr);
1542421e10b8SBarry Smith       }
1543421e10b8SBarry Smith     } else {
1544421e10b8SBarry Smith       while (ilink->next) {   /* get to last entry in linked list */
1545421e10b8SBarry Smith         ilink = ilink->next;
1546421e10b8SBarry Smith       }
1547421e10b8SBarry Smith       ierr = FieldSplitSplitSolveAddTranspose(ilink,x,y);CHKERRQ(ierr);
1548421e10b8SBarry Smith       while (ilink->previous) {
1549421e10b8SBarry Smith         ilink = ilink->previous;
15509989ab13SBarry Smith         ierr  = MatMultTranspose(pc->mat,y,jac->w1);CHKERRQ(ierr);
1551421e10b8SBarry Smith         ierr  = VecWAXPY(jac->w2,-1.0,jac->w1,x);CHKERRQ(ierr);
1552421e10b8SBarry Smith         ierr  = FieldSplitSplitSolveAddTranspose(ilink,jac->w2,y);CHKERRQ(ierr);
1553421e10b8SBarry Smith       }
1554421e10b8SBarry Smith     }
1555421e10b8SBarry Smith   }
1556421e10b8SBarry Smith   PetscFunctionReturn(0);
1557421e10b8SBarry Smith }
1558421e10b8SBarry Smith 
1559574deadeSBarry Smith static PetscErrorCode PCReset_FieldSplit(PC pc)
15600971522cSBarry Smith {
15610971522cSBarry Smith   PC_FieldSplit     *jac = (PC_FieldSplit*)pc->data;
15620971522cSBarry Smith   PetscErrorCode    ierr;
15635a9f2f41SSatish Balay   PC_FieldSplitLink ilink = jac->head,next;
15640971522cSBarry Smith 
15650971522cSBarry Smith   PetscFunctionBegin;
15665a9f2f41SSatish Balay   while (ilink) {
1567f5f0d762SBarry Smith     ierr  = KSPDestroy(&ilink->ksp);CHKERRQ(ierr);
1568fcfd50ebSBarry Smith     ierr  = VecDestroy(&ilink->x);CHKERRQ(ierr);
1569fcfd50ebSBarry Smith     ierr  = VecDestroy(&ilink->y);CHKERRQ(ierr);
1570443836d0SMatthew G Knepley     ierr  = VecDestroy(&ilink->z);CHKERRQ(ierr);
1571fcfd50ebSBarry Smith     ierr  = VecScatterDestroy(&ilink->sctx);CHKERRQ(ierr);
1572fcfd50ebSBarry Smith     ierr  = ISDestroy(&ilink->is);CHKERRQ(ierr);
1573b5787286SJed Brown     ierr  = ISDestroy(&ilink->is_col);CHKERRQ(ierr);
1574f5f0d762SBarry Smith     ierr  = PetscFree(ilink->splitname);CHKERRQ(ierr);
1575f5f0d762SBarry Smith     ierr  = PetscFree(ilink->fields);CHKERRQ(ierr);
1576f5f0d762SBarry Smith     ierr  = PetscFree(ilink->fields_col);CHKERRQ(ierr);
15775a9f2f41SSatish Balay     next  = ilink->next;
1578f5f0d762SBarry Smith     ierr  = PetscFree(ilink);CHKERRQ(ierr);
15795a9f2f41SSatish Balay     ilink = next;
15800971522cSBarry Smith   }
1581f5f0d762SBarry Smith   jac->head = NULL;
158205b42c5fSBarry Smith   ierr = PetscFree2(jac->x,jac->y);CHKERRQ(ierr);
1583574deadeSBarry Smith   if (jac->mat && jac->mat != jac->pmat) {
1584574deadeSBarry Smith     ierr = MatDestroyMatrices(jac->nsplits,&jac->mat);CHKERRQ(ierr);
1585574deadeSBarry Smith   } else if (jac->mat) {
15860298fd71SBarry Smith     jac->mat = NULL;
1587574deadeSBarry Smith   }
158897bbdb24SBarry Smith   if (jac->pmat) {ierr = MatDestroyMatrices(jac->nsplits,&jac->pmat);CHKERRQ(ierr);}
158968dd23aaSBarry Smith   if (jac->Afield) {ierr = MatDestroyMatrices(jac->nsplits,&jac->Afield);CHKERRQ(ierr);}
1590f5f0d762SBarry Smith   jac->nsplits = 0;
15916bf464f9SBarry Smith   ierr = VecDestroy(&jac->w1);CHKERRQ(ierr);
15926bf464f9SBarry Smith   ierr = VecDestroy(&jac->w2);CHKERRQ(ierr);
15936bf464f9SBarry Smith   ierr = MatDestroy(&jac->schur);CHKERRQ(ierr);
1594a7476a74SDmitry Karpeev   ierr = MatDestroy(&jac->schurp);CHKERRQ(ierr);
15956bf464f9SBarry Smith   ierr = MatDestroy(&jac->schur_user);CHKERRQ(ierr);
15966bf464f9SBarry Smith   ierr = KSPDestroy(&jac->kspschur);CHKERRQ(ierr);
1597d78dad28SBarry Smith   ierr = KSPDestroy(&jac->kspupper);CHKERRQ(ierr);
15986bf464f9SBarry Smith   ierr = MatDestroy(&jac->B);CHKERRQ(ierr);
15996bf464f9SBarry Smith   ierr = MatDestroy(&jac->C);CHKERRQ(ierr);
1600a51937d4SCarola Kruse   ierr = MatDestroy(&jac->H);CHKERRQ(ierr);
1601e071a0a4SCarola Kruse   ierr = VecDestroy(&jac->u);CHKERRQ(ierr);
1602e071a0a4SCarola Kruse   ierr = VecDestroy(&jac->v);CHKERRQ(ierr);
1603e071a0a4SCarola Kruse   ierr = VecDestroy(&jac->Hu);CHKERRQ(ierr);
1604e071a0a4SCarola Kruse   ierr = VecDestroy(&jac->d);CHKERRQ(ierr);
1605e071a0a4SCarola Kruse   ierr = PetscFree(jac->vecz);CHKERRQ(ierr);
1606de482cd7SCarola Kruse   ierr = PetscViewerDestroy(&jac->gkbviewer);CHKERRQ(ierr);
16076dbb499eSCian Wilson   jac->isrestrict = PETSC_FALSE;
1608574deadeSBarry Smith   PetscFunctionReturn(0);
1609574deadeSBarry Smith }
1610574deadeSBarry Smith 
1611574deadeSBarry Smith static PetscErrorCode PCDestroy_FieldSplit(PC pc)
1612574deadeSBarry Smith {
1613574deadeSBarry Smith   PetscErrorCode    ierr;
1614574deadeSBarry Smith 
1615574deadeSBarry Smith   PetscFunctionBegin;
1616574deadeSBarry Smith   ierr = PCReset_FieldSplit(pc);CHKERRQ(ierr);
1617c31cb41cSBarry Smith   ierr = PetscFree(pc->data);CHKERRQ(ierr);
1618285fb4e2SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCFieldSplitSchurGetSubKSP_C",NULL);CHKERRQ(ierr);
1619bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCFieldSplitGetSubKSP_C",NULL);CHKERRQ(ierr);
1620bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCFieldSplitSetFields_C",NULL);CHKERRQ(ierr);
1621bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCFieldSplitSetIS_C",NULL);CHKERRQ(ierr);
1622bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCFieldSplitSetType_C",NULL);CHKERRQ(ierr);
1623bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCFieldSplitSetBlockSize_C",NULL);CHKERRQ(ierr);
162429f8a81cSJed Brown   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCFieldSplitSetSchurPre_C",NULL);CHKERRQ(ierr);
162537a82bf0SJed Brown   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCFieldSplitGetSchurPre_C",NULL);CHKERRQ(ierr);
1626bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCFieldSplitSetSchurFactType_C",NULL);CHKERRQ(ierr);
16276dbb499eSCian Wilson   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCFieldSplitRestrictIS_C",NULL);CHKERRQ(ierr);
16280971522cSBarry Smith   PetscFunctionReturn(0);
16290971522cSBarry Smith }
16300971522cSBarry Smith 
16314416b707SBarry Smith static PetscErrorCode PCSetFromOptions_FieldSplit(PetscOptionItems *PetscOptionsObject,PC pc)
16320971522cSBarry Smith {
16331b9fc7fcSBarry Smith   PetscErrorCode  ierr;
16346c924f48SJed Brown   PetscInt        bs;
16357b752e3dSPatrick Sanan   PetscBool       flg;
16369dcbbd2bSBarry Smith   PC_FieldSplit   *jac = (PC_FieldSplit*)pc->data;
16373b224e63SBarry Smith   PCCompositeType ctype;
16381b9fc7fcSBarry Smith 
16390971522cSBarry Smith   PetscFunctionBegin;
1640e55864a3SBarry Smith   ierr = PetscOptionsHead(PetscOptionsObject,"FieldSplit options");CHKERRQ(ierr);
16414ab8060aSDmitry Karpeev   ierr = PetscOptionsBool("-pc_fieldsplit_dm_splits","Whether to use DMCreateFieldDecomposition() for splits","PCFieldSplitSetDMSplits",jac->dm_splits,&jac->dm_splits,NULL);CHKERRQ(ierr);
164251f519a2SBarry Smith   ierr = PetscOptionsInt("-pc_fieldsplit_block_size","Blocksize that defines number of fields","PCFieldSplitSetBlockSize",jac->bs,&bs,&flg);CHKERRQ(ierr);
164351f519a2SBarry Smith   if (flg) {
164451f519a2SBarry Smith     ierr = PCFieldSplitSetBlockSize(pc,bs);CHKERRQ(ierr);
164551f519a2SBarry Smith   }
16462686e3e9SMatthew G. Knepley   jac->diag_use_amat = pc->useAmat;
16472686e3e9SMatthew 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);
16482686e3e9SMatthew G. Knepley   jac->offdiag_use_amat = pc->useAmat;
16492686e3e9SMatthew 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);
16507b752e3dSPatrick 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);
16517b752e3dSPatrick Sanan   ierr = PCFieldSplitSetDetectSaddlePoint(pc,jac->detect);CHKERRQ(ierr); /* Sets split type and Schur PC type */
16523b224e63SBarry Smith   ierr = PetscOptionsEnum("-pc_fieldsplit_type","Type of composition","PCFieldSplitSetType",PCCompositeTypes,(PetscEnum)jac->type,(PetscEnum*)&ctype,&flg);CHKERRQ(ierr);
16533b224e63SBarry Smith   if (flg) {
16543b224e63SBarry Smith     ierr = PCFieldSplitSetType(pc,ctype);CHKERRQ(ierr);
16553b224e63SBarry Smith   }
1656c30613efSMatthew Knepley   /* Only setup fields once */
1657c30613efSMatthew Knepley   if ((jac->bs > 0) && (jac->nsplits == 0)) {
1658d32f9abdSBarry Smith     /* only allow user to set fields from command line if bs is already known.
1659d32f9abdSBarry Smith        otherwise user can set them in PCFieldSplitSetDefaults() */
16606c924f48SJed Brown     ierr = PCFieldSplitSetRuntimeSplits_Private(pc);CHKERRQ(ierr);
16616c924f48SJed Brown     if (jac->splitdefined) {ierr = PetscInfo(pc,"Splits defined using the options database\n");CHKERRQ(ierr);}
1662d32f9abdSBarry Smith   }
1663c5d2311dSJed Brown   if (jac->type == PC_COMPOSITE_SCHUR) {
1664c5929fdfSBarry Smith     ierr = PetscOptionsGetEnum(((PetscObject)pc)->options,((PetscObject)pc)->prefix,"-pc_fieldsplit_schur_factorization_type",PCFieldSplitSchurFactTypes,(PetscEnum*)&jac->schurfactorization,&flg);CHKERRQ(ierr);
1665c9c6ffaaSJed Brown     if (flg) {ierr = PetscInfo(pc,"Deprecated use of -pc_fieldsplit_schur_factorization_type\n");CHKERRQ(ierr);}
16660298fd71SBarry 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);
166729f8a81cSJed 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);
1668c096484dSStefano Zampini     ierr = PetscOptionsScalar("-pc_fieldsplit_schur_scale","Scale Schur complement","PCFieldSplitSetSchurScale",jac->schurscale,&jac->schurscale,NULL);CHKERRQ(ierr);
1669a51937d4SCarola Kruse   } else if (jac->type == PC_COMPOSITE_GKB) {
1670a51937d4SCarola Kruse     ierr = PetscOptionsReal("-pc_fieldsplit_gkb_tol","The tolerance for the lower bound stopping criterion","PCFieldSplitGKBTol",jac->gkbtol,&jac->gkbtol,NULL);CHKERRQ(ierr);
1671a51937d4SCarola Kruse     ierr = PetscOptionsInt("-pc_fieldsplit_gkb_delay","The delay value for lower bound criterion","PCFieldSplitGKBDelay",jac->gkbdelay,&jac->gkbdelay,NULL);CHKERRQ(ierr);
1672a51937d4SCarola Kruse     ierr = PetscOptionsReal("-pc_fieldsplit_gkb_nu","Parameter in augmented Lagrangian approach","PCFieldSplitGKBNu",jac->gkbnu,&jac->gkbnu,NULL);CHKERRQ(ierr);
16732c71b3e2SJacob Faibussowitsch     PetscCheckFalse(jac->gkbnu < 0,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"nu cannot be less than 0: value %f",jac->gkbnu);
1674a51937d4SCarola Kruse     ierr = PetscOptionsInt("-pc_fieldsplit_gkb_maxit","Maximum allowed number of iterations","PCFieldSplitGKBMaxit",jac->gkbmaxit,&jac->gkbmaxit,NULL);CHKERRQ(ierr);
1675de482cd7SCarola Kruse     ierr = PetscOptionsBool("-pc_fieldsplit_gkb_monitor","Prints number of GKB iterations and error","PCFieldSplitGKB",jac->gkbmonitor,&jac->gkbmonitor,NULL);CHKERRQ(ierr);
1676c5d2311dSJed Brown   }
16771b9fc7fcSBarry Smith   ierr = PetscOptionsTail();CHKERRQ(ierr);
16780971522cSBarry Smith   PetscFunctionReturn(0);
16790971522cSBarry Smith }
16800971522cSBarry Smith 
16810971522cSBarry Smith /*------------------------------------------------------------------------------------*/
16820971522cSBarry Smith 
16831e6b0712SBarry Smith static PetscErrorCode  PCFieldSplitSetFields_FieldSplit(PC pc,const char splitname[],PetscInt n,const PetscInt *fields,const PetscInt *fields_col)
16840971522cSBarry Smith {
168597bbdb24SBarry Smith   PC_FieldSplit     *jac = (PC_FieldSplit*)pc->data;
16860971522cSBarry Smith   PetscErrorCode    ierr;
16875a9f2f41SSatish Balay   PC_FieldSplitLink ilink,next = jac->head;
168869a612a9SBarry Smith   char              prefix[128];
16895d4c12cdSJungho Lee   PetscInt          i;
16900971522cSBarry Smith 
16910971522cSBarry Smith   PetscFunctionBegin;
16926c924f48SJed Brown   if (jac->splitdefined) {
16937d3de750SJacob Faibussowitsch     ierr = PetscInfo(pc,"Ignoring new split \"%s\" because the splits have already been defined\n",splitname);CHKERRQ(ierr);
16946c924f48SJed Brown     PetscFunctionReturn(0);
16956c924f48SJed Brown   }
169651f519a2SBarry Smith   for (i=0; i<n; i++) {
16972c71b3e2SJacob Faibussowitsch     PetscCheckFalse(fields[i] >= jac->bs,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Field %D requested but only %D exist",fields[i],jac->bs);
16982c71b3e2SJacob Faibussowitsch     PetscCheckFalse(fields[i] < 0,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Negative field %D requested",fields[i]);
169951f519a2SBarry Smith   }
1700b00a9115SJed Brown   ierr = PetscNew(&ilink);CHKERRQ(ierr);
1701a04f6461SBarry Smith   if (splitname) {
1702db4c96c1SJed Brown     ierr = PetscStrallocpy(splitname,&ilink->splitname);CHKERRQ(ierr);
1703a04f6461SBarry Smith   } else {
1704785e854fSJed Brown     ierr = PetscMalloc1(3,&ilink->splitname);CHKERRQ(ierr);
1705a04f6461SBarry Smith     ierr = PetscSNPrintf(ilink->splitname,2,"%s",jac->nsplits);CHKERRQ(ierr);
1706a04f6461SBarry Smith   }
17079df09d43SBarry 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 */
1708785e854fSJed Brown   ierr = PetscMalloc1(n,&ilink->fields);CHKERRQ(ierr);
1709580bdb30SBarry Smith   ierr = PetscArraycpy(ilink->fields,fields,n);CHKERRQ(ierr);
1710785e854fSJed Brown   ierr = PetscMalloc1(n,&ilink->fields_col);CHKERRQ(ierr);
1711580bdb30SBarry Smith   ierr = PetscArraycpy(ilink->fields_col,fields_col,n);CHKERRQ(ierr);
17122fa5cd67SKarl Rupp 
17135a9f2f41SSatish Balay   ilink->nfields = n;
17140298fd71SBarry Smith   ilink->next    = NULL;
1715ce94432eSBarry Smith   ierr           = KSPCreate(PetscObjectComm((PetscObject)pc),&ilink->ksp);CHKERRQ(ierr);
1716422a814eSBarry Smith   ierr           = KSPSetErrorIfNotConverged(ilink->ksp,pc->erroriffailure);CHKERRQ(ierr);
171720252d06SBarry Smith   ierr           = PetscObjectIncrementTabLevel((PetscObject)ilink->ksp,(PetscObject)pc,1);CHKERRQ(ierr);
17185a9f2f41SSatish Balay   ierr           = KSPSetType(ilink->ksp,KSPPREONLY);CHKERRQ(ierr);
17199005cf84SBarry Smith   ierr           = PetscLogObjectParent((PetscObject)pc,(PetscObject)ilink->ksp);CHKERRQ(ierr);
172069a612a9SBarry Smith 
17218caf3d72SBarry Smith   ierr = PetscSNPrintf(prefix,sizeof(prefix),"%sfieldsplit_%s_",((PetscObject)pc)->prefix ? ((PetscObject)pc)->prefix : "",ilink->splitname);CHKERRQ(ierr);
17225a9f2f41SSatish Balay   ierr = KSPSetOptionsPrefix(ilink->ksp,prefix);CHKERRQ(ierr);
17230971522cSBarry Smith 
17240971522cSBarry Smith   if (!next) {
17255a9f2f41SSatish Balay     jac->head       = ilink;
17260298fd71SBarry Smith     ilink->previous = NULL;
17270971522cSBarry Smith   } else {
17280971522cSBarry Smith     while (next->next) {
17290971522cSBarry Smith       next = next->next;
17300971522cSBarry Smith     }
17315a9f2f41SSatish Balay     next->next      = ilink;
173251f519a2SBarry Smith     ilink->previous = next;
17330971522cSBarry Smith   }
17340971522cSBarry Smith   jac->nsplits++;
17350971522cSBarry Smith   PetscFunctionReturn(0);
17360971522cSBarry Smith }
17370971522cSBarry Smith 
1738285fb4e2SStefano Zampini static PetscErrorCode  PCFieldSplitSchurGetSubKSP_FieldSplit(PC pc,PetscInt *n,KSP **subksp)
1739285fb4e2SStefano Zampini {
1740285fb4e2SStefano Zampini   PC_FieldSplit  *jac = (PC_FieldSplit*)pc->data;
1741285fb4e2SStefano Zampini   PetscErrorCode ierr;
1742285fb4e2SStefano Zampini 
1743285fb4e2SStefano Zampini   PetscFunctionBegin;
1744285fb4e2SStefano Zampini   *subksp = NULL;
1745285fb4e2SStefano Zampini   if (n) *n = 0;
1746285fb4e2SStefano Zampini   if (jac->type == PC_COMPOSITE_SCHUR) {
1747285fb4e2SStefano Zampini     PetscInt nn;
1748285fb4e2SStefano Zampini 
17492c71b3e2SJacob Faibussowitsch     PetscCheckFalse(!jac->schur,PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONGSTATE,"Must call KSPSetUp() or PCSetUp() before calling PCFieldSplitSchurGetSubKSP()");
17502c71b3e2SJacob Faibussowitsch     PetscCheckFalse(jac->nsplits != 2,PetscObjectComm((PetscObject)pc),PETSC_ERR_PLIB,"Unexpected number of splits %D != 2",jac->nsplits);
1751285fb4e2SStefano Zampini     nn   = jac->nsplits + (jac->kspupper != jac->head->ksp ? 1 : 0);
1752285fb4e2SStefano Zampini     ierr = PetscMalloc1(nn,subksp);CHKERRQ(ierr);
1753285fb4e2SStefano Zampini     (*subksp)[0] = jac->head->ksp;
1754285fb4e2SStefano Zampini     (*subksp)[1] = jac->kspschur;
1755285fb4e2SStefano Zampini     if (jac->kspupper != jac->head->ksp) (*subksp)[2] = jac->kspupper;
1756285fb4e2SStefano Zampini     if (n) *n = nn;
1757285fb4e2SStefano Zampini   }
1758285fb4e2SStefano Zampini   PetscFunctionReturn(0);
1759285fb4e2SStefano Zampini }
1760285fb4e2SStefano Zampini 
17611e6b0712SBarry Smith static PetscErrorCode  PCFieldSplitGetSubKSP_FieldSplit_Schur(PC pc,PetscInt *n,KSP **subksp)
1762e69d4d44SBarry Smith {
1763e69d4d44SBarry Smith   PC_FieldSplit  *jac = (PC_FieldSplit*)pc->data;
1764e69d4d44SBarry Smith   PetscErrorCode ierr;
1765e69d4d44SBarry Smith 
1766e69d4d44SBarry Smith   PetscFunctionBegin;
17672c71b3e2SJacob Faibussowitsch   PetscCheckFalse(!jac->schur,PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONGSTATE,"Must call KSPSetUp() or PCSetUp() before calling PCFieldSplitGetSubKSP()");
1768785e854fSJed Brown   ierr = PetscMalloc1(jac->nsplits,subksp);CHKERRQ(ierr);
1769e69d4d44SBarry Smith   ierr = MatSchurComplementGetKSP(jac->schur,*subksp);CHKERRQ(ierr);
17702fa5cd67SKarl Rupp 
1771e69d4d44SBarry Smith   (*subksp)[1] = jac->kspschur;
177213e0d083SBarry Smith   if (n) *n = jac->nsplits;
1773e69d4d44SBarry Smith   PetscFunctionReturn(0);
1774e69d4d44SBarry Smith }
17750971522cSBarry Smith 
17761e6b0712SBarry Smith static PetscErrorCode  PCFieldSplitGetSubKSP_FieldSplit(PC pc,PetscInt *n,KSP **subksp)
17770971522cSBarry Smith {
17780971522cSBarry Smith   PC_FieldSplit     *jac = (PC_FieldSplit*)pc->data;
17790971522cSBarry Smith   PetscErrorCode    ierr;
17800971522cSBarry Smith   PetscInt          cnt   = 0;
17815a9f2f41SSatish Balay   PC_FieldSplitLink ilink = jac->head;
17820971522cSBarry Smith 
17830971522cSBarry Smith   PetscFunctionBegin;
1784785e854fSJed Brown   ierr = PetscMalloc1(jac->nsplits,subksp);CHKERRQ(ierr);
17855a9f2f41SSatish Balay   while (ilink) {
17865a9f2f41SSatish Balay     (*subksp)[cnt++] = ilink->ksp;
17875a9f2f41SSatish Balay     ilink            = ilink->next;
17880971522cSBarry Smith   }
17892c71b3e2SJacob Faibussowitsch   PetscCheckFalse(cnt != jac->nsplits,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);
179013e0d083SBarry Smith   if (n) *n = jac->nsplits;
17910971522cSBarry Smith   PetscFunctionReturn(0);
17920971522cSBarry Smith }
17930971522cSBarry Smith 
17946dbb499eSCian Wilson /*@C
17956dbb499eSCian Wilson     PCFieldSplitRestrictIS - Restricts the fieldsplit ISs to be within a given IS.
17966dbb499eSCian Wilson 
17976dbb499eSCian Wilson     Input Parameters:
17986dbb499eSCian Wilson +   pc  - the preconditioner context
1799a2b725a8SWilliam Gropp -   is - the index set that defines the indices to which the fieldsplit is to be restricted
18006dbb499eSCian Wilson 
18016dbb499eSCian Wilson     Level: advanced
18026dbb499eSCian Wilson 
18036dbb499eSCian Wilson @*/
18046dbb499eSCian Wilson PetscErrorCode  PCFieldSplitRestrictIS(PC pc,IS isy)
18056dbb499eSCian Wilson {
18066dbb499eSCian Wilson   PetscErrorCode ierr;
18076dbb499eSCian Wilson 
18086dbb499eSCian Wilson   PetscFunctionBegin;
18096dbb499eSCian Wilson   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
18106dbb499eSCian Wilson   PetscValidHeaderSpecific(isy,IS_CLASSID,2);
18110246f55cSBarry Smith   ierr = PetscTryMethod(pc,"PCFieldSplitRestrictIS_C",(PC,IS),(pc,isy));CHKERRQ(ierr);
18126dbb499eSCian Wilson   PetscFunctionReturn(0);
18136dbb499eSCian Wilson }
18146dbb499eSCian Wilson 
18156dbb499eSCian Wilson static PetscErrorCode  PCFieldSplitRestrictIS_FieldSplit(PC pc, IS isy)
18166dbb499eSCian Wilson {
18176dbb499eSCian Wilson   PC_FieldSplit     *jac = (PC_FieldSplit*)pc->data;
18186dbb499eSCian Wilson   PetscErrorCode    ierr;
18196dbb499eSCian Wilson   PC_FieldSplitLink ilink = jac->head, next;
18206dbb499eSCian Wilson   PetscInt          localsize,size,sizez,i;
18216dbb499eSCian Wilson   const PetscInt    *ind, *indz;
18226dbb499eSCian Wilson   PetscInt          *indc, *indcz;
18236dbb499eSCian Wilson   PetscBool         flg;
18246dbb499eSCian Wilson 
18256dbb499eSCian Wilson   PetscFunctionBegin;
18266dbb499eSCian Wilson   ierr = ISGetLocalSize(isy,&localsize);CHKERRQ(ierr);
1827ffc4695bSBarry Smith   ierr = MPI_Scan(&localsize,&size,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)isy));CHKERRMPI(ierr);
18286dbb499eSCian Wilson   size -= localsize;
18296dbb499eSCian Wilson   while (ilink) {
18306dbb499eSCian Wilson     IS isrl,isr;
18311c7cfba8SBarry Smith     PC subpc;
18326dbb499eSCian Wilson     ierr          = ISEmbed(ilink->is, isy, PETSC_TRUE, &isrl);CHKERRQ(ierr);
18336dbb499eSCian Wilson     ierr          = ISGetLocalSize(isrl,&localsize);CHKERRQ(ierr);
18346dbb499eSCian Wilson     ierr          = PetscMalloc1(localsize,&indc);CHKERRQ(ierr);
18356dbb499eSCian Wilson     ierr          = ISGetIndices(isrl,&ind);CHKERRQ(ierr);
1836580bdb30SBarry Smith     ierr          = PetscArraycpy(indc,ind,localsize);CHKERRQ(ierr);
18376dbb499eSCian Wilson     ierr          = ISRestoreIndices(isrl,&ind);CHKERRQ(ierr);
18386dbb499eSCian Wilson     ierr          = ISDestroy(&isrl);CHKERRQ(ierr);
18396dbb499eSCian Wilson     for (i=0; i<localsize; i++) *(indc+i) += size;
18406dbb499eSCian Wilson     ierr          = ISCreateGeneral(PetscObjectComm((PetscObject)isy),localsize,indc,PETSC_OWN_POINTER,&isr);CHKERRQ(ierr);
18416dbb499eSCian Wilson     ierr          = PetscObjectReference((PetscObject)isr);CHKERRQ(ierr);
18426dbb499eSCian Wilson     ierr          = ISDestroy(&ilink->is);CHKERRQ(ierr);
18436dbb499eSCian Wilson     ilink->is     = isr;
18446dbb499eSCian Wilson     ierr          = PetscObjectReference((PetscObject)isr);CHKERRQ(ierr);
18456dbb499eSCian Wilson     ierr          = ISDestroy(&ilink->is_col);CHKERRQ(ierr);
18466dbb499eSCian Wilson     ilink->is_col = isr;
18476dbb499eSCian Wilson     ierr          = ISDestroy(&isr);CHKERRQ(ierr);
18486dbb499eSCian Wilson     ierr          = KSPGetPC(ilink->ksp, &subpc);CHKERRQ(ierr);
18496dbb499eSCian Wilson     ierr          = PetscObjectTypeCompare((PetscObject)subpc,PCFIELDSPLIT,&flg);CHKERRQ(ierr);
18506dbb499eSCian Wilson     if (flg) {
18516dbb499eSCian Wilson       IS iszl,isz;
18526dbb499eSCian Wilson       MPI_Comm comm;
18536dbb499eSCian Wilson       ierr   = ISGetLocalSize(ilink->is,&localsize);CHKERRQ(ierr);
18546dbb499eSCian Wilson       comm   = PetscObjectComm((PetscObject)ilink->is);
18556dbb499eSCian Wilson       ierr   = ISEmbed(isy, ilink->is, PETSC_TRUE, &iszl);CHKERRQ(ierr);
185655b25c41SPierre Jolivet       ierr   = MPI_Scan(&localsize,&sizez,1,MPIU_INT,MPI_SUM,comm);CHKERRMPI(ierr);
18576dbb499eSCian Wilson       sizez -= localsize;
18586dbb499eSCian Wilson       ierr   = ISGetLocalSize(iszl,&localsize);CHKERRQ(ierr);
18596dbb499eSCian Wilson       ierr   = PetscMalloc1(localsize,&indcz);CHKERRQ(ierr);
18606dbb499eSCian Wilson       ierr   = ISGetIndices(iszl,&indz);CHKERRQ(ierr);
1861580bdb30SBarry Smith       ierr   = PetscArraycpy(indcz,indz,localsize);CHKERRQ(ierr);
18626dbb499eSCian Wilson       ierr   = ISRestoreIndices(iszl,&indz);CHKERRQ(ierr);
18636dbb499eSCian Wilson       ierr   = ISDestroy(&iszl);CHKERRQ(ierr);
18646dbb499eSCian Wilson       for (i=0; i<localsize; i++) *(indcz+i) += sizez;
18656dbb499eSCian Wilson       ierr   = ISCreateGeneral(comm,localsize,indcz,PETSC_OWN_POINTER,&isz);CHKERRQ(ierr);
18666dbb499eSCian Wilson       ierr   = PCFieldSplitRestrictIS(subpc,isz);CHKERRQ(ierr);
18676dbb499eSCian Wilson       ierr   = ISDestroy(&isz);CHKERRQ(ierr);
18686dbb499eSCian Wilson     }
18696dbb499eSCian Wilson     next = ilink->next;
18706dbb499eSCian Wilson     ilink = next;
18716dbb499eSCian Wilson   }
18726dbb499eSCian Wilson   jac->isrestrict = PETSC_TRUE;
18736dbb499eSCian Wilson   PetscFunctionReturn(0);
18746dbb499eSCian Wilson }
18756dbb499eSCian Wilson 
18761e6b0712SBarry Smith static PetscErrorCode  PCFieldSplitSetIS_FieldSplit(PC pc,const char splitname[],IS is)
1877704ba839SBarry Smith {
1878704ba839SBarry Smith   PC_FieldSplit     *jac = (PC_FieldSplit*)pc->data;
1879704ba839SBarry Smith   PetscErrorCode    ierr;
1880704ba839SBarry Smith   PC_FieldSplitLink ilink, next = jac->head;
1881704ba839SBarry Smith   char              prefix[128];
1882704ba839SBarry Smith 
1883704ba839SBarry Smith   PetscFunctionBegin;
18846c924f48SJed Brown   if (jac->splitdefined) {
18857d3de750SJacob Faibussowitsch     ierr = PetscInfo(pc,"Ignoring new split \"%s\" because the splits have already been defined\n",splitname);CHKERRQ(ierr);
18866c924f48SJed Brown     PetscFunctionReturn(0);
18876c924f48SJed Brown   }
1888b00a9115SJed Brown   ierr = PetscNew(&ilink);CHKERRQ(ierr);
1889a04f6461SBarry Smith   if (splitname) {
1890db4c96c1SJed Brown     ierr = PetscStrallocpy(splitname,&ilink->splitname);CHKERRQ(ierr);
1891a04f6461SBarry Smith   } else {
1892785e854fSJed Brown     ierr = PetscMalloc1(8,&ilink->splitname);CHKERRQ(ierr);
1893b5787286SJed Brown     ierr = PetscSNPrintf(ilink->splitname,7,"%D",jac->nsplits);CHKERRQ(ierr);
1894a04f6461SBarry Smith   }
18959df09d43SBarry 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 */
18961ab39975SBarry Smith   ierr          = PetscObjectReference((PetscObject)is);CHKERRQ(ierr);
1897b5787286SJed Brown   ierr          = ISDestroy(&ilink->is);CHKERRQ(ierr);
1898b5787286SJed Brown   ilink->is     = is;
1899b5787286SJed Brown   ierr          = PetscObjectReference((PetscObject)is);CHKERRQ(ierr);
1900b5787286SJed Brown   ierr          = ISDestroy(&ilink->is_col);CHKERRQ(ierr);
1901b5787286SJed Brown   ilink->is_col = is;
19020298fd71SBarry Smith   ilink->next   = NULL;
1903ce94432eSBarry Smith   ierr          = KSPCreate(PetscObjectComm((PetscObject)pc),&ilink->ksp);CHKERRQ(ierr);
1904422a814eSBarry Smith   ierr          = KSPSetErrorIfNotConverged(ilink->ksp,pc->erroriffailure);CHKERRQ(ierr);
190520252d06SBarry Smith   ierr          = PetscObjectIncrementTabLevel((PetscObject)ilink->ksp,(PetscObject)pc,1);CHKERRQ(ierr);
1906704ba839SBarry Smith   ierr          = KSPSetType(ilink->ksp,KSPPREONLY);CHKERRQ(ierr);
19079005cf84SBarry Smith   ierr          = PetscLogObjectParent((PetscObject)pc,(PetscObject)ilink->ksp);CHKERRQ(ierr);
1908704ba839SBarry Smith 
19098caf3d72SBarry Smith   ierr = PetscSNPrintf(prefix,sizeof(prefix),"%sfieldsplit_%s_",((PetscObject)pc)->prefix ? ((PetscObject)pc)->prefix : "",ilink->splitname);CHKERRQ(ierr);
1910704ba839SBarry Smith   ierr = KSPSetOptionsPrefix(ilink->ksp,prefix);CHKERRQ(ierr);
1911704ba839SBarry Smith 
1912704ba839SBarry Smith   if (!next) {
1913704ba839SBarry Smith     jac->head       = ilink;
19140298fd71SBarry Smith     ilink->previous = NULL;
1915704ba839SBarry Smith   } else {
1916704ba839SBarry Smith     while (next->next) {
1917704ba839SBarry Smith       next = next->next;
1918704ba839SBarry Smith     }
1919704ba839SBarry Smith     next->next      = ilink;
1920704ba839SBarry Smith     ilink->previous = next;
1921704ba839SBarry Smith   }
1922704ba839SBarry Smith   jac->nsplits++;
1923704ba839SBarry Smith   PetscFunctionReturn(0);
1924704ba839SBarry Smith }
1925704ba839SBarry Smith 
192694ef8ddeSSatish Balay /*@C
19270971522cSBarry Smith     PCFieldSplitSetFields - Sets the fields for one particular split in the field split preconditioner
19280971522cSBarry Smith 
1929ad4df100SBarry Smith     Logically Collective on PC
19300971522cSBarry Smith 
19310971522cSBarry Smith     Input Parameters:
19320971522cSBarry Smith +   pc  - the preconditioner context
19330298fd71SBarry Smith .   splitname - name of this split, if NULL the number of the split is used
19340971522cSBarry Smith .   n - the number of fields in this split
1935db4c96c1SJed Brown -   fields - the fields in this split
19360971522cSBarry Smith 
19370971522cSBarry Smith     Level: intermediate
19380971522cSBarry Smith 
193995452b02SPatrick Sanan     Notes:
194095452b02SPatrick Sanan     Use PCFieldSplitSetIS() to set a completely general set of indices as a field.
1941d32f9abdSBarry Smith 
19427287d2a3SDmitry Karpeev      The PCFieldSplitSetFields() is for defining fields as strided blocks. For example, if the block
1943d32f9abdSBarry 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
1944d32f9abdSBarry Smith      0xx3xx6xx9xx12 ... x1xx4xx7xx ... xx2xx5xx8xx.. 01x34x67x... 0x1x3x5x7.. x12x45x78x....
1945d32f9abdSBarry Smith      where the numbered entries indicate what is in the field.
1946d32f9abdSBarry Smith 
1947db4c96c1SJed Brown      This function is called once per split (it creates a new split each time).  Solve options
1948db4c96c1SJed Brown      for this split will be available under the prefix -fieldsplit_SPLITNAME_.
1949db4c96c1SJed Brown 
19505d4c12cdSJungho Lee      Developer Note: This routine does not actually create the IS representing the split, that is delayed
19515d4c12cdSJungho Lee      until PCSetUp_FieldSplit(), because information about the vector/matrix layouts may not be
19525d4c12cdSJungho Lee      available when this routine is called.
19535d4c12cdSJungho Lee 
1954d32f9abdSBarry Smith .seealso: PCFieldSplitGetSubKSP(), PCFIELDSPLIT, PCFieldSplitSetBlockSize(), PCFieldSplitSetIS()
19550971522cSBarry Smith 
19560971522cSBarry Smith @*/
19575d4c12cdSJungho Lee PetscErrorCode  PCFieldSplitSetFields(PC pc,const char splitname[],PetscInt n,const PetscInt *fields,const PetscInt *fields_col)
19580971522cSBarry Smith {
19594ac538c5SBarry Smith   PetscErrorCode ierr;
19600971522cSBarry Smith 
19610971522cSBarry Smith   PetscFunctionBegin;
19620700a824SBarry Smith   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
1963db4c96c1SJed Brown   PetscValidCharPointer(splitname,2);
19642c71b3e2SJacob Faibussowitsch   PetscCheckFalse(n < 1,PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_OUTOFRANGE,"Provided number of fields %D in split \"%s\" not positive",n,splitname);
1965064a246eSJacob Faibussowitsch   PetscValidIntPointer(fields,4);
19660246f55cSBarry Smith   ierr = PetscTryMethod(pc,"PCFieldSplitSetFields_C",(PC,const char[],PetscInt,const PetscInt*,const PetscInt*),(pc,splitname,n,fields,fields_col));CHKERRQ(ierr);
19670971522cSBarry Smith   PetscFunctionReturn(0);
19680971522cSBarry Smith }
19690971522cSBarry Smith 
1970c84da90fSDmitry Karpeev /*@
1971c84da90fSDmitry Karpeev     PCFieldSplitSetDiagUseAmat - set flag indicating whether to extract diagonal blocks from Amat (rather than Pmat)
1972c84da90fSDmitry Karpeev 
1973c84da90fSDmitry Karpeev     Logically Collective on PC
1974c84da90fSDmitry Karpeev 
1975c84da90fSDmitry Karpeev     Input Parameters:
1976c84da90fSDmitry Karpeev +   pc  - the preconditioner object
1977c84da90fSDmitry Karpeev -   flg - boolean flag indicating whether or not to use Amat to extract the diagonal blocks from
1978c84da90fSDmitry Karpeev 
19799506b623SDmitry Karpeev     Options Database:
19809506b623SDmitry Karpeev .     -pc_fieldsplit_diag_use_amat
1981c84da90fSDmitry Karpeev 
1982c84da90fSDmitry Karpeev     Level: intermediate
1983c84da90fSDmitry Karpeev 
1984c84da90fSDmitry Karpeev .seealso: PCFieldSplitGetDiagUseAmat(), PCFieldSplitSetOffDiagUseAmat(), PCFIELDSPLIT
1985c84da90fSDmitry Karpeev 
1986c84da90fSDmitry Karpeev @*/
1987c84da90fSDmitry Karpeev PetscErrorCode  PCFieldSplitSetDiagUseAmat(PC pc,PetscBool flg)
1988c84da90fSDmitry Karpeev {
1989c84da90fSDmitry Karpeev   PC_FieldSplit  *jac = (PC_FieldSplit*)pc->data;
1990c84da90fSDmitry Karpeev   PetscBool      isfs;
1991c84da90fSDmitry Karpeev   PetscErrorCode ierr;
1992c84da90fSDmitry Karpeev 
1993c84da90fSDmitry Karpeev   PetscFunctionBegin;
1994c84da90fSDmitry Karpeev   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
1995c84da90fSDmitry Karpeev   ierr = PetscObjectTypeCompare((PetscObject)pc,PCFIELDSPLIT,&isfs);CHKERRQ(ierr);
19962c71b3e2SJacob Faibussowitsch   PetscCheckFalse(!isfs,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"PC not of type %s",PCFIELDSPLIT);
1997c84da90fSDmitry Karpeev   jac->diag_use_amat = flg;
1998c84da90fSDmitry Karpeev   PetscFunctionReturn(0);
1999c84da90fSDmitry Karpeev }
2000c84da90fSDmitry Karpeev 
2001c84da90fSDmitry Karpeev /*@
2002c84da90fSDmitry Karpeev     PCFieldSplitGetDiagUseAmat - get the flag indicating whether to extract diagonal blocks from Amat (rather than Pmat)
2003c84da90fSDmitry Karpeev 
2004c84da90fSDmitry Karpeev     Logically Collective on PC
2005c84da90fSDmitry Karpeev 
2006c84da90fSDmitry Karpeev     Input Parameters:
2007c84da90fSDmitry Karpeev .   pc  - the preconditioner object
2008c84da90fSDmitry Karpeev 
2009c84da90fSDmitry Karpeev     Output Parameters:
2010c84da90fSDmitry Karpeev .   flg - boolean flag indicating whether or not to use Amat to extract the diagonal blocks from
2011c84da90fSDmitry Karpeev 
2012c84da90fSDmitry Karpeev     Level: intermediate
2013c84da90fSDmitry Karpeev 
2014c84da90fSDmitry Karpeev .seealso: PCFieldSplitSetDiagUseAmat(), PCFieldSplitGetOffDiagUseAmat(), PCFIELDSPLIT
2015c84da90fSDmitry Karpeev 
2016c84da90fSDmitry Karpeev @*/
2017c84da90fSDmitry Karpeev PetscErrorCode  PCFieldSplitGetDiagUseAmat(PC pc,PetscBool *flg)
2018c84da90fSDmitry Karpeev {
2019c84da90fSDmitry Karpeev   PC_FieldSplit  *jac = (PC_FieldSplit*)pc->data;
2020c84da90fSDmitry Karpeev   PetscBool      isfs;
2021c84da90fSDmitry Karpeev   PetscErrorCode ierr;
2022c84da90fSDmitry Karpeev 
2023c84da90fSDmitry Karpeev   PetscFunctionBegin;
2024c84da90fSDmitry Karpeev   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
2025534a8f05SLisandro Dalcin   PetscValidBoolPointer(flg,2);
2026c84da90fSDmitry Karpeev   ierr = PetscObjectTypeCompare((PetscObject)pc,PCFIELDSPLIT,&isfs);CHKERRQ(ierr);
20272c71b3e2SJacob Faibussowitsch   PetscCheckFalse(!isfs,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"PC not of type %s",PCFIELDSPLIT);
2028c84da90fSDmitry Karpeev   *flg = jac->diag_use_amat;
2029c84da90fSDmitry Karpeev   PetscFunctionReturn(0);
2030c84da90fSDmitry Karpeev }
2031c84da90fSDmitry Karpeev 
2032c84da90fSDmitry Karpeev /*@
2033c84da90fSDmitry Karpeev     PCFieldSplitSetOffDiagUseAmat - set flag indicating whether to extract off-diagonal blocks from Amat (rather than Pmat)
2034c84da90fSDmitry Karpeev 
2035c84da90fSDmitry Karpeev     Logically Collective on PC
2036c84da90fSDmitry Karpeev 
2037c84da90fSDmitry Karpeev     Input Parameters:
2038c84da90fSDmitry Karpeev +   pc  - the preconditioner object
2039c84da90fSDmitry Karpeev -   flg - boolean flag indicating whether or not to use Amat to extract the off-diagonal blocks from
2040c84da90fSDmitry Karpeev 
20419506b623SDmitry Karpeev     Options Database:
20429506b623SDmitry Karpeev .     -pc_fieldsplit_off_diag_use_amat
2043c84da90fSDmitry Karpeev 
2044c84da90fSDmitry Karpeev     Level: intermediate
2045c84da90fSDmitry Karpeev 
2046c84da90fSDmitry Karpeev .seealso: PCFieldSplitGetOffDiagUseAmat(), PCFieldSplitSetDiagUseAmat(), PCFIELDSPLIT
2047c84da90fSDmitry Karpeev 
2048c84da90fSDmitry Karpeev @*/
2049c84da90fSDmitry Karpeev PetscErrorCode  PCFieldSplitSetOffDiagUseAmat(PC pc,PetscBool flg)
2050c84da90fSDmitry Karpeev {
2051c84da90fSDmitry Karpeev   PC_FieldSplit *jac = (PC_FieldSplit*)pc->data;
2052c84da90fSDmitry Karpeev   PetscBool      isfs;
2053c84da90fSDmitry Karpeev   PetscErrorCode ierr;
2054c84da90fSDmitry Karpeev 
2055c84da90fSDmitry Karpeev   PetscFunctionBegin;
2056c84da90fSDmitry Karpeev   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
2057c84da90fSDmitry Karpeev   ierr = PetscObjectTypeCompare((PetscObject)pc,PCFIELDSPLIT,&isfs);CHKERRQ(ierr);
20582c71b3e2SJacob Faibussowitsch   PetscCheckFalse(!isfs,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"PC not of type %s",PCFIELDSPLIT);
2059c84da90fSDmitry Karpeev   jac->offdiag_use_amat = flg;
2060c84da90fSDmitry Karpeev   PetscFunctionReturn(0);
2061c84da90fSDmitry Karpeev }
2062c84da90fSDmitry Karpeev 
2063c84da90fSDmitry Karpeev /*@
2064c84da90fSDmitry Karpeev     PCFieldSplitGetOffDiagUseAmat - get the flag indicating whether to extract off-diagonal blocks from Amat (rather than Pmat)
2065c84da90fSDmitry Karpeev 
2066c84da90fSDmitry Karpeev     Logically Collective on PC
2067c84da90fSDmitry Karpeev 
2068c84da90fSDmitry Karpeev     Input Parameters:
2069c84da90fSDmitry Karpeev .   pc  - the preconditioner object
2070c84da90fSDmitry Karpeev 
2071c84da90fSDmitry Karpeev     Output Parameters:
2072c84da90fSDmitry Karpeev .   flg - boolean flag indicating whether or not to use Amat to extract the off-diagonal blocks from
2073c84da90fSDmitry Karpeev 
2074c84da90fSDmitry Karpeev     Level: intermediate
2075c84da90fSDmitry Karpeev 
2076c84da90fSDmitry Karpeev .seealso: PCFieldSplitSetOffDiagUseAmat(), PCFieldSplitGetDiagUseAmat(), PCFIELDSPLIT
2077c84da90fSDmitry Karpeev 
2078c84da90fSDmitry Karpeev @*/
2079c84da90fSDmitry Karpeev PetscErrorCode  PCFieldSplitGetOffDiagUseAmat(PC pc,PetscBool *flg)
2080c84da90fSDmitry Karpeev {
2081c84da90fSDmitry Karpeev   PC_FieldSplit  *jac = (PC_FieldSplit*)pc->data;
2082c84da90fSDmitry Karpeev   PetscBool      isfs;
2083c84da90fSDmitry Karpeev   PetscErrorCode ierr;
2084c84da90fSDmitry Karpeev 
2085c84da90fSDmitry Karpeev   PetscFunctionBegin;
2086c84da90fSDmitry Karpeev   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
2087534a8f05SLisandro Dalcin   PetscValidBoolPointer(flg,2);
2088c84da90fSDmitry Karpeev   ierr = PetscObjectTypeCompare((PetscObject)pc,PCFIELDSPLIT,&isfs);CHKERRQ(ierr);
20892c71b3e2SJacob Faibussowitsch   PetscCheckFalse(!isfs,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"PC not of type %s",PCFIELDSPLIT);
2090c84da90fSDmitry Karpeev   *flg = jac->offdiag_use_amat;
2091c84da90fSDmitry Karpeev   PetscFunctionReturn(0);
2092c84da90fSDmitry Karpeev }
2093c84da90fSDmitry Karpeev 
2094218d4943SBarry Smith /*@C
2095704ba839SBarry Smith     PCFieldSplitSetIS - Sets the exact elements for field
2096704ba839SBarry Smith 
2097ad4df100SBarry Smith     Logically Collective on PC
2098704ba839SBarry Smith 
2099704ba839SBarry Smith     Input Parameters:
2100704ba839SBarry Smith +   pc  - the preconditioner context
21010298fd71SBarry Smith .   splitname - name of this split, if NULL the number of the split is used
2102db4c96c1SJed Brown -   is - the index set that defines the vector elements in this field
2103704ba839SBarry Smith 
2104a6ffb8dbSJed Brown     Notes:
2105a6ffb8dbSJed Brown     Use PCFieldSplitSetFields(), for fields defined by strided types.
2106a6ffb8dbSJed Brown 
2107db4c96c1SJed Brown     This function is called once per split (it creates a new split each time).  Solve options
2108db4c96c1SJed Brown     for this split will be available under the prefix -fieldsplit_SPLITNAME_.
2109d32f9abdSBarry Smith 
2110704ba839SBarry Smith     Level: intermediate
2111704ba839SBarry Smith 
2112704ba839SBarry Smith .seealso: PCFieldSplitGetSubKSP(), PCFIELDSPLIT, PCFieldSplitSetBlockSize()
2113704ba839SBarry Smith 
2114704ba839SBarry Smith @*/
21157087cfbeSBarry Smith PetscErrorCode  PCFieldSplitSetIS(PC pc,const char splitname[],IS is)
2116704ba839SBarry Smith {
21174ac538c5SBarry Smith   PetscErrorCode ierr;
2118704ba839SBarry Smith 
2119704ba839SBarry Smith   PetscFunctionBegin;
21200700a824SBarry Smith   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
21217b62db95SJungho Lee   if (splitname) PetscValidCharPointer(splitname,2);
2122db4c96c1SJed Brown   PetscValidHeaderSpecific(is,IS_CLASSID,3);
2123ccc738f7SBarry Smith   ierr = PetscTryMethod(pc,"PCFieldSplitSetIS_C",(PC,const char[],IS),(pc,splitname,is));CHKERRQ(ierr);
2124704ba839SBarry Smith   PetscFunctionReturn(0);
2125704ba839SBarry Smith }
2126704ba839SBarry Smith 
212794ef8ddeSSatish Balay /*@C
212857a9adfeSMatthew G Knepley     PCFieldSplitGetIS - Retrieves the elements for a field as an IS
212957a9adfeSMatthew G Knepley 
213057a9adfeSMatthew G Knepley     Logically Collective on PC
213157a9adfeSMatthew G Knepley 
213257a9adfeSMatthew G Knepley     Input Parameters:
213357a9adfeSMatthew G Knepley +   pc  - the preconditioner context
213457a9adfeSMatthew G Knepley -   splitname - name of this split
213557a9adfeSMatthew G Knepley 
213657a9adfeSMatthew G Knepley     Output Parameter:
21370298fd71SBarry Smith -   is - the index set that defines the vector elements in this field, or NULL if the field is not found
213857a9adfeSMatthew G Knepley 
213957a9adfeSMatthew G Knepley     Level: intermediate
214057a9adfeSMatthew G Knepley 
214157a9adfeSMatthew G Knepley .seealso: PCFieldSplitGetSubKSP(), PCFIELDSPLIT, PCFieldSplitSetIS()
214257a9adfeSMatthew G Knepley 
214357a9adfeSMatthew G Knepley @*/
214457a9adfeSMatthew G Knepley PetscErrorCode PCFieldSplitGetIS(PC pc,const char splitname[],IS *is)
214557a9adfeSMatthew G Knepley {
214657a9adfeSMatthew G Knepley   PetscErrorCode ierr;
214757a9adfeSMatthew G Knepley 
214857a9adfeSMatthew G Knepley   PetscFunctionBegin;
214957a9adfeSMatthew G Knepley   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
215057a9adfeSMatthew G Knepley   PetscValidCharPointer(splitname,2);
215157a9adfeSMatthew G Knepley   PetscValidPointer(is,3);
215257a9adfeSMatthew G Knepley   {
215357a9adfeSMatthew G Knepley     PC_FieldSplit     *jac  = (PC_FieldSplit*) pc->data;
215457a9adfeSMatthew G Knepley     PC_FieldSplitLink ilink = jac->head;
215557a9adfeSMatthew G Knepley     PetscBool         found;
215657a9adfeSMatthew G Knepley 
21570298fd71SBarry Smith     *is = NULL;
215857a9adfeSMatthew G Knepley     while (ilink) {
215957a9adfeSMatthew G Knepley       ierr = PetscStrcmp(ilink->splitname, splitname, &found);CHKERRQ(ierr);
216057a9adfeSMatthew G Knepley       if (found) {
216157a9adfeSMatthew G Knepley         *is = ilink->is;
216257a9adfeSMatthew G Knepley         break;
216357a9adfeSMatthew G Knepley       }
216457a9adfeSMatthew G Knepley       ilink = ilink->next;
216557a9adfeSMatthew G Knepley     }
216657a9adfeSMatthew G Knepley   }
216757a9adfeSMatthew G Knepley   PetscFunctionReturn(0);
216857a9adfeSMatthew G Knepley }
216957a9adfeSMatthew G Knepley 
2170998f007dSPierre Jolivet /*@C
2171998f007dSPierre Jolivet     PCFieldSplitGetISByIndex - Retrieves the elements for a given index field as an IS
2172998f007dSPierre Jolivet 
2173998f007dSPierre Jolivet     Logically Collective on PC
2174998f007dSPierre Jolivet 
2175998f007dSPierre Jolivet     Input Parameters:
2176998f007dSPierre Jolivet +   pc  - the preconditioner context
2177998f007dSPierre Jolivet -   index - index of this split
2178998f007dSPierre Jolivet 
2179998f007dSPierre Jolivet     Output Parameter:
2180998f007dSPierre Jolivet -   is - the index set that defines the vector elements in this field
2181998f007dSPierre Jolivet 
2182998f007dSPierre Jolivet     Level: intermediate
2183998f007dSPierre Jolivet 
2184998f007dSPierre Jolivet .seealso: PCFieldSplitGetSubKSP(), PCFIELDSPLIT, PCFieldSplitGetIS(), PCFieldSplitSetIS()
2185998f007dSPierre Jolivet 
2186998f007dSPierre Jolivet @*/
2187998f007dSPierre Jolivet PetscErrorCode PCFieldSplitGetISByIndex(PC pc,PetscInt index,IS *is)
2188998f007dSPierre Jolivet {
2189998f007dSPierre Jolivet   PetscErrorCode ierr;
2190998f007dSPierre Jolivet 
2191998f007dSPierre Jolivet   PetscFunctionBegin;
21922c71b3e2SJacob Faibussowitsch   PetscCheckFalse(index < 0,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Negative field %D requested",index);
2193998f007dSPierre Jolivet   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
2194998f007dSPierre Jolivet   PetscValidPointer(is,3);
2195998f007dSPierre Jolivet   {
2196998f007dSPierre Jolivet     PC_FieldSplit     *jac  = (PC_FieldSplit*) pc->data;
2197998f007dSPierre Jolivet     PC_FieldSplitLink ilink = jac->head;
2198998f007dSPierre Jolivet     PetscInt          i     = 0;
21992c71b3e2SJacob Faibussowitsch     PetscCheckFalse(index >= jac->nsplits,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Field %D requested but only %D exist",index,jac->nsplits);
2200998f007dSPierre Jolivet 
2201998f007dSPierre Jolivet     while (i < index) {
2202998f007dSPierre Jolivet       ilink = ilink->next;
2203998f007dSPierre Jolivet       ++i;
2204998f007dSPierre Jolivet     }
2205998f007dSPierre Jolivet     ierr = PCFieldSplitGetIS(pc,ilink->splitname,is);CHKERRQ(ierr);
2206998f007dSPierre Jolivet   }
2207998f007dSPierre Jolivet   PetscFunctionReturn(0);
2208998f007dSPierre Jolivet }
2209998f007dSPierre Jolivet 
221051f519a2SBarry Smith /*@
221151f519a2SBarry Smith     PCFieldSplitSetBlockSize - Sets the block size for defining where fields start in the
221251f519a2SBarry Smith       fieldsplit preconditioner. If not set the matrix block size is used.
221351f519a2SBarry Smith 
2214ad4df100SBarry Smith     Logically Collective on PC
221551f519a2SBarry Smith 
221651f519a2SBarry Smith     Input Parameters:
221751f519a2SBarry Smith +   pc  - the preconditioner context
221851f519a2SBarry Smith -   bs - the block size
221951f519a2SBarry Smith 
222051f519a2SBarry Smith     Level: intermediate
222151f519a2SBarry Smith 
222251f519a2SBarry Smith .seealso: PCFieldSplitGetSubKSP(), PCFIELDSPLIT, PCFieldSplitSetFields()
222351f519a2SBarry Smith 
222451f519a2SBarry Smith @*/
22257087cfbeSBarry Smith PetscErrorCode  PCFieldSplitSetBlockSize(PC pc,PetscInt bs)
222651f519a2SBarry Smith {
22274ac538c5SBarry Smith   PetscErrorCode ierr;
222851f519a2SBarry Smith 
222951f519a2SBarry Smith   PetscFunctionBegin;
22300700a824SBarry Smith   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
2231c5eb9154SBarry Smith   PetscValidLogicalCollectiveInt(pc,bs,2);
22324ac538c5SBarry Smith   ierr = PetscTryMethod(pc,"PCFieldSplitSetBlockSize_C",(PC,PetscInt),(pc,bs));CHKERRQ(ierr);
223351f519a2SBarry Smith   PetscFunctionReturn(0);
223451f519a2SBarry Smith }
223551f519a2SBarry Smith 
22360971522cSBarry Smith /*@C
223769a612a9SBarry Smith    PCFieldSplitGetSubKSP - Gets the KSP contexts for all splits
22380971522cSBarry Smith 
223969a612a9SBarry Smith    Collective on KSP
22400971522cSBarry Smith 
22410971522cSBarry Smith    Input Parameter:
22420971522cSBarry Smith .  pc - the preconditioner context
22430971522cSBarry Smith 
22440971522cSBarry Smith    Output Parameters:
224513e0d083SBarry Smith +  n - the number of splits
22463111de3cSBarry Smith -  subksp - the array of KSP contexts
22470971522cSBarry Smith 
22480971522cSBarry Smith    Note:
22499a4f7e47SBarry Smith    After PCFieldSplitGetSubKSP() the array of KSPs is to be freed by the user with PetscFree()
2250d32f9abdSBarry Smith    (not the KSP just the array that contains them).
22510971522cSBarry Smith 
2252285fb4e2SStefano Zampini    You must call PCSetUp() before calling PCFieldSplitGetSubKSP().
2253285fb4e2SStefano Zampini 
2254285fb4e2SStefano Zampini    If the fieldsplit is of type PC_COMPOSITE_SCHUR, it returns the KSP object used inside the
2255285fb4e2SStefano Zampini    Schur complement and the KSP object used to iterate over the Schur complement.
2256a51937d4SCarola Kruse    To access all the KSP objects used in PC_COMPOSITE_SCHUR, use PCFieldSplitSchurGetSubKSP().
2257a51937d4SCarola Kruse 
2258a51937d4SCarola Kruse    If the fieldsplit is of type PC_COMPOSITE_GKB, it returns the KSP object used to solve the
2259a51937d4SCarola Kruse    inner linear system defined by the matrix H in each loop.
22600971522cSBarry Smith 
2261196cc216SBarry Smith    Fortran Usage: You must pass in a KSP array that is large enough to contain all the local KSPs.
22622bf68e3eSBarry Smith       You can call PCFieldSplitGetSubKSP(pc,n,PETSC_NULL_KSP,ierr) to determine how large the
2263196cc216SBarry Smith       KSP array must be.
2264196cc216SBarry Smith 
22650971522cSBarry Smith    Level: advanced
22660971522cSBarry Smith 
22670971522cSBarry Smith .seealso: PCFIELDSPLIT
22680971522cSBarry Smith @*/
22697087cfbeSBarry Smith PetscErrorCode  PCFieldSplitGetSubKSP(PC pc,PetscInt *n,KSP *subksp[])
22700971522cSBarry Smith {
22714ac538c5SBarry Smith   PetscErrorCode ierr;
22720971522cSBarry Smith 
22730971522cSBarry Smith   PetscFunctionBegin;
22740700a824SBarry Smith   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
227513e0d083SBarry Smith   if (n) PetscValidIntPointer(n,2);
22764ac538c5SBarry Smith   ierr = PetscUseMethod(pc,"PCFieldSplitGetSubKSP_C",(PC,PetscInt*,KSP **),(pc,n,subksp));CHKERRQ(ierr);
22770971522cSBarry Smith   PetscFunctionReturn(0);
22780971522cSBarry Smith }
22790971522cSBarry Smith 
2280285fb4e2SStefano Zampini /*@C
2281285fb4e2SStefano Zampini    PCFieldSplitSchurGetSubKSP - Gets the KSP contexts used inside the Schur complement based PCFIELDSPLIT
2282285fb4e2SStefano Zampini 
2283285fb4e2SStefano Zampini    Collective on KSP
2284285fb4e2SStefano Zampini 
2285285fb4e2SStefano Zampini    Input Parameter:
2286285fb4e2SStefano Zampini .  pc - the preconditioner context
2287285fb4e2SStefano Zampini 
2288285fb4e2SStefano Zampini    Output Parameters:
2289285fb4e2SStefano Zampini +  n - the number of splits
2290285fb4e2SStefano Zampini -  subksp - the array of KSP contexts
2291285fb4e2SStefano Zampini 
2292285fb4e2SStefano Zampini    Note:
2293285fb4e2SStefano Zampini    After PCFieldSplitSchurGetSubKSP() the array of KSPs is to be freed by the user with PetscFree()
2294285fb4e2SStefano Zampini    (not the KSP just the array that contains them).
2295285fb4e2SStefano Zampini 
2296285fb4e2SStefano Zampini    You must call PCSetUp() before calling PCFieldSplitSchurGetSubKSP().
2297285fb4e2SStefano Zampini 
2298285fb4e2SStefano Zampini    If the fieldsplit type is of type PC_COMPOSITE_SCHUR, it returns (in order)
2299285fb4e2SStefano Zampini    - the KSP used for the (1,1) block
2300285fb4e2SStefano Zampini    - the KSP used for the Schur complement (not the one used for the interior Schur solver)
2301285fb4e2SStefano Zampini    - the KSP used for the (1,1) block in the upper triangular factor (if different from that of the (1,1) block).
2302285fb4e2SStefano Zampini 
2303285fb4e2SStefano Zampini    It returns a null array if the fieldsplit is not of type PC_COMPOSITE_SCHUR; in this case, you should use PCFieldSplitGetSubKSP().
2304285fb4e2SStefano Zampini 
2305285fb4e2SStefano Zampini    Fortran Usage: You must pass in a KSP array that is large enough to contain all the local KSPs.
2306285fb4e2SStefano Zampini       You can call PCFieldSplitSchurGetSubKSP(pc,n,PETSC_NULL_KSP,ierr) to determine how large the
2307285fb4e2SStefano Zampini       KSP array must be.
2308285fb4e2SStefano Zampini 
2309285fb4e2SStefano Zampini    Level: advanced
2310285fb4e2SStefano Zampini 
2311285fb4e2SStefano Zampini .seealso: PCFIELDSPLIT
2312285fb4e2SStefano Zampini @*/
2313285fb4e2SStefano Zampini PetscErrorCode  PCFieldSplitSchurGetSubKSP(PC pc,PetscInt *n,KSP *subksp[])
2314285fb4e2SStefano Zampini {
2315285fb4e2SStefano Zampini   PetscErrorCode ierr;
2316285fb4e2SStefano Zampini 
2317285fb4e2SStefano Zampini   PetscFunctionBegin;
2318285fb4e2SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
2319285fb4e2SStefano Zampini   if (n) PetscValidIntPointer(n,2);
2320285fb4e2SStefano Zampini   ierr = PetscUseMethod(pc,"PCFieldSplitSchurGetSubKSP_C",(PC,PetscInt*,KSP **),(pc,n,subksp));CHKERRQ(ierr);
2321285fb4e2SStefano Zampini   PetscFunctionReturn(0);
2322285fb4e2SStefano Zampini }
2323285fb4e2SStefano Zampini 
2324e69d4d44SBarry Smith /*@
2325a1e3cbf9SBarry Smith     PCFieldSplitSetSchurPre -  Indicates from what operator the preconditioner is constructucted for the Schur complement.
2326a1e3cbf9SBarry Smith       The default is the A11 matrix.
2327e69d4d44SBarry Smith 
2328e69d4d44SBarry Smith     Collective on PC
2329e69d4d44SBarry Smith 
2330e69d4d44SBarry Smith     Input Parameters:
2331e69d4d44SBarry Smith +   pc      - the preconditioner context
23326fdd48a9SBarry 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
23336fdd48a9SBarry Smith               PC_FIELDSPLIT_SCHUR_PRE_SELFP, and PC_FIELDSPLIT_SCHUR_PRE_FULL
23340298fd71SBarry Smith -   userpre - matrix to use for preconditioning, or NULL
2335084e4875SJed Brown 
2336e69d4d44SBarry Smith     Options Database:
2337a1e3cbf9SBarry Smith +    -pc_fieldsplit_schur_precondition <self,selfp,user,a11,full> - default is a11. See notes for meaning of various arguments
2338a1e3cbf9SBarry Smith -    -fieldsplit_1_pc_type <pctype> - the preconditioner algorithm that is used to construct the preconditioner from the operator
2339e69d4d44SBarry Smith 
2340fd1303e9SJungho Lee     Notes:
2341fd1303e9SJungho Lee $    If ptype is
2342a1e3cbf9SBarry Smith $        a11 - the preconditioner for the Schur complement is generated from the block diagonal part of the preconditioner
234353f2277eSBarry Smith $        matrix associated with the Schur complement (i.e. A11), not the Schur complement matrix
2344a1e3cbf9SBarry Smith $        self - the preconditioner for the Schur complement is generated from the symbolic representation of the Schur complement matrix:
2345a6a584a2SBarry Smith $             The only preconditioner that currently works with this symbolic respresentation matrix object is the PCLSC
2346fd1303e9SJungho Lee $             preconditioner
2347a1e3cbf9SBarry Smith $        user - the preconditioner for the Schur complement is generated from the user provided matrix (pre argument
23486fdd48a9SBarry Smith $             to this function).
2349a1e3cbf9SBarry Smith $        selfp - the preconditioning for the Schur complement is generated from an explicitly-assembled approximation Sp = A11 - A10 inv(diag(A00)) A01
23501d71051fSDmitry Karpeev $             This is only a good preconditioner when diag(A00) is a good preconditioner for A00. Optionally, A00 can be
23516fdd48a9SBarry Smith $             lumped before extracting the diagonal using the additional option -fieldsplit_1_mat_schur_complement_ainv_type lump
2352a1e3cbf9SBarry Smith $        full - the preconditioner for the Schur complement is generated from the exact Schur complement matrix representation computed internally by PCFIELDSPLIT (this is expensive)
23536fdd48a9SBarry Smith $             useful mostly as a test that the Schur complement approach can work for your problem
2354fd1303e9SJungho Lee 
2355e87fab1bSBarry Smith      When solving a saddle point problem, where the A11 block is identically zero, using a11 as the ptype only makes sense
2356fd1303e9SJungho Lee     with the additional option -fieldsplit_1_pc_type none. Usually for saddle point problems one would use a ptype of self and
2357a7476a74SDmitry Karpeev     -fieldsplit_1_pc_type lsc which uses the least squares commutator to compute a preconditioner for the Schur complement.
2358fd1303e9SJungho Lee 
2359e69d4d44SBarry Smith     Level: intermediate
2360e69d4d44SBarry Smith 
23611d71051fSDmitry Karpeev .seealso: PCFieldSplitGetSchurPre(), PCFieldSplitGetSubKSP(), PCFIELDSPLIT, PCFieldSplitSetFields(), PCFieldSplitSchurPreType,
23621d71051fSDmitry Karpeev           MatSchurComplementSetAinvType(), PCLSC
2363e69d4d44SBarry Smith 
2364e69d4d44SBarry Smith @*/
236529f8a81cSJed Brown PetscErrorCode PCFieldSplitSetSchurPre(PC pc,PCFieldSplitSchurPreType ptype,Mat pre)
2366e69d4d44SBarry Smith {
23674ac538c5SBarry Smith   PetscErrorCode ierr;
2368e69d4d44SBarry Smith 
2369e69d4d44SBarry Smith   PetscFunctionBegin;
23700700a824SBarry Smith   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
237129f8a81cSJed Brown   ierr = PetscTryMethod(pc,"PCFieldSplitSetSchurPre_C",(PC,PCFieldSplitSchurPreType,Mat),(pc,ptype,pre));CHKERRQ(ierr);
2372e69d4d44SBarry Smith   PetscFunctionReturn(0);
2373e69d4d44SBarry Smith }
2374686bed4dSStefano Zampini 
237529f8a81cSJed Brown PetscErrorCode PCFieldSplitSchurPrecondition(PC pc,PCFieldSplitSchurPreType ptype,Mat pre) {return PCFieldSplitSetSchurPre(pc,ptype,pre);} /* Deprecated name */
2376e69d4d44SBarry Smith 
237737a82bf0SJed Brown /*@
237837a82bf0SJed Brown     PCFieldSplitGetSchurPre - For Schur complement fieldsplit, determine how the Schur complement will be
237929f8a81cSJed Brown     preconditioned.  See PCFieldSplitSetSchurPre() for details.
238037a82bf0SJed Brown 
238137a82bf0SJed Brown     Logically Collective on PC
238237a82bf0SJed Brown 
2383f899ff85SJose E. Roman     Input Parameter:
238437a82bf0SJed Brown .   pc      - the preconditioner context
238537a82bf0SJed Brown 
238637a82bf0SJed Brown     Output Parameters:
238737a82bf0SJed 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
238837a82bf0SJed Brown -   userpre - matrix to use for preconditioning (with PC_FIELDSPLIT_PRE_USER), or NULL
238937a82bf0SJed Brown 
239037a82bf0SJed Brown     Level: intermediate
239137a82bf0SJed Brown 
239229f8a81cSJed Brown .seealso: PCFieldSplitSetSchurPre(), PCFieldSplitGetSubKSP(), PCFIELDSPLIT, PCFieldSplitSetFields(), PCFieldSplitSchurPreType, PCLSC
239337a82bf0SJed Brown 
239437a82bf0SJed Brown @*/
239537a82bf0SJed Brown PetscErrorCode PCFieldSplitGetSchurPre(PC pc,PCFieldSplitSchurPreType *ptype,Mat *pre)
239637a82bf0SJed Brown {
239737a82bf0SJed Brown   PetscErrorCode ierr;
239837a82bf0SJed Brown 
239937a82bf0SJed Brown   PetscFunctionBegin;
240037a82bf0SJed Brown   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
240137a82bf0SJed Brown   ierr = PetscUseMethod(pc,"PCFieldSplitGetSchurPre_C",(PC,PCFieldSplitSchurPreType*,Mat*),(pc,ptype,pre));CHKERRQ(ierr);
2402e69d4d44SBarry Smith   PetscFunctionReturn(0);
2403e69d4d44SBarry Smith }
2404e69d4d44SBarry Smith 
240545e7fc46SDmitry Karpeev /*@
2406470b340bSDmitry Karpeev     PCFieldSplitSchurGetS -  extract the MatSchurComplement object used by this PC in case it needs to be configured separately
240745e7fc46SDmitry Karpeev 
240845e7fc46SDmitry Karpeev     Not collective
240945e7fc46SDmitry Karpeev 
241045e7fc46SDmitry Karpeev     Input Parameter:
241145e7fc46SDmitry Karpeev .   pc      - the preconditioner context
241245e7fc46SDmitry Karpeev 
241345e7fc46SDmitry Karpeev     Output Parameter:
2414470b340bSDmitry Karpeev .   S       - the Schur complement matrix
241545e7fc46SDmitry Karpeev 
2416470b340bSDmitry Karpeev     Notes:
2417470b340bSDmitry Karpeev     This matrix should not be destroyed using MatDestroy(); rather, use PCFieldSplitSchurRestoreS().
241845e7fc46SDmitry Karpeev 
241945e7fc46SDmitry Karpeev     Level: advanced
242045e7fc46SDmitry Karpeev 
242129f8a81cSJed Brown .seealso: PCFieldSplitGetSubKSP(), PCFIELDSPLIT, PCFieldSplitSchurPreType, PCFieldSplitSetSchurPre(), MatSchurComplement, PCFieldSplitSchurRestoreS()
242245e7fc46SDmitry Karpeev 
242345e7fc46SDmitry Karpeev @*/
2424470b340bSDmitry Karpeev PetscErrorCode  PCFieldSplitSchurGetS(PC pc,Mat *S)
242545e7fc46SDmitry Karpeev {
242645e7fc46SDmitry Karpeev   PetscErrorCode ierr;
242745e7fc46SDmitry Karpeev   const char*    t;
242845e7fc46SDmitry Karpeev   PetscBool      isfs;
242945e7fc46SDmitry Karpeev   PC_FieldSplit  *jac;
243045e7fc46SDmitry Karpeev 
243145e7fc46SDmitry Karpeev   PetscFunctionBegin;
243245e7fc46SDmitry Karpeev   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
243345e7fc46SDmitry Karpeev   ierr = PetscObjectGetType((PetscObject)pc,&t);CHKERRQ(ierr);
243445e7fc46SDmitry Karpeev   ierr = PetscStrcmp(t,PCFIELDSPLIT,&isfs);CHKERRQ(ierr);
24352c71b3e2SJacob Faibussowitsch   PetscCheckFalse(!isfs,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Expected PC of type PCFIELDSPLIT, got %s instead",t);
243645e7fc46SDmitry Karpeev   jac = (PC_FieldSplit*)pc->data;
24372c71b3e2SJacob Faibussowitsch   PetscCheckFalse(jac->type != PC_COMPOSITE_SCHUR,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Expected PCFIELDSPLIT of type SCHUR, got %D instead",jac->type);
2438470b340bSDmitry Karpeev   if (S) *S = jac->schur;
243945e7fc46SDmitry Karpeev   PetscFunctionReturn(0);
244045e7fc46SDmitry Karpeev }
244145e7fc46SDmitry Karpeev 
2442470b340bSDmitry Karpeev /*@
2443470b340bSDmitry Karpeev     PCFieldSplitSchurRestoreS -  restores the MatSchurComplement object used by this PC
2444470b340bSDmitry Karpeev 
2445470b340bSDmitry Karpeev     Not collective
2446470b340bSDmitry Karpeev 
2447470b340bSDmitry Karpeev     Input Parameters:
2448470b340bSDmitry Karpeev +   pc      - the preconditioner context
2449a2b725a8SWilliam Gropp -   S       - the Schur complement matrix
2450470b340bSDmitry Karpeev 
2451470b340bSDmitry Karpeev     Level: advanced
2452470b340bSDmitry Karpeev 
245329f8a81cSJed Brown .seealso: PCFieldSplitGetSubKSP(), PCFIELDSPLIT, PCFieldSplitSchurPreType, PCFieldSplitSetSchurPre(), MatSchurComplement, PCFieldSplitSchurGetS()
2454470b340bSDmitry Karpeev 
2455470b340bSDmitry Karpeev @*/
2456bca69d2bSDmitry Karpeev PetscErrorCode  PCFieldSplitSchurRestoreS(PC pc,Mat *S)
2457470b340bSDmitry Karpeev {
2458470b340bSDmitry Karpeev   PetscErrorCode ierr;
2459470b340bSDmitry Karpeev   const char*    t;
2460470b340bSDmitry Karpeev   PetscBool      isfs;
2461470b340bSDmitry Karpeev   PC_FieldSplit  *jac;
2462470b340bSDmitry Karpeev 
2463470b340bSDmitry Karpeev   PetscFunctionBegin;
2464470b340bSDmitry Karpeev   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
2465470b340bSDmitry Karpeev   ierr = PetscObjectGetType((PetscObject)pc,&t);CHKERRQ(ierr);
2466470b340bSDmitry Karpeev   ierr = PetscStrcmp(t,PCFIELDSPLIT,&isfs);CHKERRQ(ierr);
24672c71b3e2SJacob Faibussowitsch   PetscCheckFalse(!isfs,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Expected PC of type PCFIELDSPLIT, got %s instead",t);
2468470b340bSDmitry Karpeev   jac = (PC_FieldSplit*)pc->data;
24692c71b3e2SJacob Faibussowitsch   PetscCheckFalse(jac->type != PC_COMPOSITE_SCHUR,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Expected PCFIELDSPLIT of type SCHUR, got %D instead",jac->type);
24702c71b3e2SJacob Faibussowitsch   PetscCheckFalse(!S || *S != jac->schur,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"MatSchurComplement restored is not the same as gotten");
2471470b340bSDmitry Karpeev   PetscFunctionReturn(0);
2472470b340bSDmitry Karpeev }
2473470b340bSDmitry Karpeev 
247429f8a81cSJed Brown static PetscErrorCode  PCFieldSplitSetSchurPre_FieldSplit(PC pc,PCFieldSplitSchurPreType ptype,Mat pre)
2475e69d4d44SBarry Smith {
2476e69d4d44SBarry Smith   PC_FieldSplit  *jac = (PC_FieldSplit*)pc->data;
2477084e4875SJed Brown   PetscErrorCode ierr;
2478e69d4d44SBarry Smith 
2479e69d4d44SBarry Smith   PetscFunctionBegin;
2480084e4875SJed Brown   jac->schurpre = ptype;
2481a7476a74SDmitry Karpeev   if (ptype == PC_FIELDSPLIT_SCHUR_PRE_USER && pre) {
24826bf464f9SBarry Smith     ierr            = MatDestroy(&jac->schur_user);CHKERRQ(ierr);
2483084e4875SJed Brown     jac->schur_user = pre;
2484084e4875SJed Brown     ierr            = PetscObjectReference((PetscObject)jac->schur_user);CHKERRQ(ierr);
2485084e4875SJed Brown   }
2486e69d4d44SBarry Smith   PetscFunctionReturn(0);
2487e69d4d44SBarry Smith }
2488e69d4d44SBarry Smith 
248937a82bf0SJed Brown static PetscErrorCode  PCFieldSplitGetSchurPre_FieldSplit(PC pc,PCFieldSplitSchurPreType *ptype,Mat *pre)
249037a82bf0SJed Brown {
249137a82bf0SJed Brown   PC_FieldSplit  *jac = (PC_FieldSplit*)pc->data;
249237a82bf0SJed Brown 
249337a82bf0SJed Brown   PetscFunctionBegin;
249437a82bf0SJed Brown   *ptype = jac->schurpre;
249537a82bf0SJed Brown   *pre   = jac->schur_user;
249637a82bf0SJed Brown   PetscFunctionReturn(0);
249737a82bf0SJed Brown }
249837a82bf0SJed Brown 
2499ab1df9f5SJed Brown /*@
25000ffb0e17SBarry Smith     PCFieldSplitSetSchurFactType -  sets which blocks of the approximate block factorization to retain in the preconditioner
2501ab1df9f5SJed Brown 
2502ab1df9f5SJed Brown     Collective on PC
2503ab1df9f5SJed Brown 
2504ab1df9f5SJed Brown     Input Parameters:
2505ab1df9f5SJed Brown +   pc  - the preconditioner context
2506c9c6ffaaSJed Brown -   ftype - which blocks of factorization to retain, PC_FIELDSPLIT_SCHUR_FACT_FULL is default
2507ab1df9f5SJed Brown 
2508ab1df9f5SJed Brown     Options Database:
2509c9c6ffaaSJed Brown .     -pc_fieldsplit_schur_fact_type <diag,lower,upper,full> default is full
2510ab1df9f5SJed Brown 
2511ab1df9f5SJed Brown     Level: intermediate
2512ab1df9f5SJed Brown 
2513ab1df9f5SJed Brown     Notes:
2514ab1df9f5SJed Brown     The FULL factorization is
2515ab1df9f5SJed Brown 
25160ffb0e17SBarry Smith $   (A   B)  = (1       0) (A   0) (1  Ainv*B)  = L D U
25170ffb0e17SBarry Smith $   (C   E)    (C*Ainv  1) (0   S) (0     1)
2518ab1df9f5SJed Brown 
25190ffb0e17SBarry 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,
2520c096484dSStefano 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().
2521ab1df9f5SJed Brown 
25220ffb0e17SBarry Smith $    If A and S are solved exactly
25230ffb0e17SBarry Smith $      *) FULL factorization is a direct solver.
25240ffb0e17SBarry 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.
25250ffb0e17SBarry 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.
2526ab1df9f5SJed Brown 
25270ffb0e17SBarry Smith     If the iteration count is very low, consider using KSPFGMRES or KSPGCR which can use one less preconditioner
25280ffb0e17SBarry 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.
25290ffb0e17SBarry Smith 
25300ffb0e17SBarry Smith     For symmetric problems in which A is positive definite and S is negative definite, DIAG can be used with KSPMINRES.
25310ffb0e17SBarry Smith 
25320ffb0e17SBarry 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).
2533ab1df9f5SJed Brown 
2534ab1df9f5SJed Brown     References:
253596a0c994SBarry Smith +   1. - Murphy, Golub, and Wathen, A note on preconditioning indefinite linear systems, SIAM J. Sci. Comput., 21 (2000).
253696a0c994SBarry Smith -   2. - Ipsen, A note on preconditioning nonsymmetric matrices, SIAM J. Sci. Comput., 23 (2001).
2537ab1df9f5SJed Brown 
2538c096484dSStefano Zampini .seealso: PCFieldSplitGetSubKSP(), PCFIELDSPLIT, PCFieldSplitSetFields(), PCFieldSplitSchurPreType, PCFieldSplitSetSchurScale()
2539ab1df9f5SJed Brown @*/
2540c9c6ffaaSJed Brown PetscErrorCode  PCFieldSplitSetSchurFactType(PC pc,PCFieldSplitSchurFactType ftype)
2541ab1df9f5SJed Brown {
2542ab1df9f5SJed Brown   PetscErrorCode ierr;
2543ab1df9f5SJed Brown 
2544ab1df9f5SJed Brown   PetscFunctionBegin;
2545ab1df9f5SJed Brown   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
2546c9c6ffaaSJed Brown   ierr = PetscTryMethod(pc,"PCFieldSplitSetSchurFactType_C",(PC,PCFieldSplitSchurFactType),(pc,ftype));CHKERRQ(ierr);
2547ab1df9f5SJed Brown   PetscFunctionReturn(0);
2548ab1df9f5SJed Brown }
2549ab1df9f5SJed Brown 
25501e6b0712SBarry Smith static PetscErrorCode PCFieldSplitSetSchurFactType_FieldSplit(PC pc,PCFieldSplitSchurFactType ftype)
2551ab1df9f5SJed Brown {
2552ab1df9f5SJed Brown   PC_FieldSplit *jac = (PC_FieldSplit*)pc->data;
2553ab1df9f5SJed Brown 
2554ab1df9f5SJed Brown   PetscFunctionBegin;
2555ab1df9f5SJed Brown   jac->schurfactorization = ftype;
2556ab1df9f5SJed Brown   PetscFunctionReturn(0);
2557ab1df9f5SJed Brown }
2558ab1df9f5SJed Brown 
2559c096484dSStefano Zampini /*@
2560c096484dSStefano Zampini     PCFieldSplitSetSchurScale -  Controls the sign flip of S for PC_FIELDSPLIT_SCHUR_FACT_DIAG.
2561c096484dSStefano Zampini 
2562c096484dSStefano Zampini     Collective on PC
2563c096484dSStefano Zampini 
2564c096484dSStefano Zampini     Input Parameters:
2565c096484dSStefano Zampini +   pc    - the preconditioner context
2566c096484dSStefano Zampini -   scale - scaling factor for the Schur complement
2567c096484dSStefano Zampini 
2568c096484dSStefano Zampini     Options Database:
2569c096484dSStefano Zampini .     -pc_fieldsplit_schur_scale - default is -1.0
2570c096484dSStefano Zampini 
2571c096484dSStefano Zampini     Level: intermediate
2572c096484dSStefano Zampini 
2573c096484dSStefano Zampini .seealso: PCFIELDSPLIT, PCFieldSplitSetFields(), PCFieldSplitSchurFactType, PCFieldSplitSetSchurScale()
2574c096484dSStefano Zampini @*/
2575c096484dSStefano Zampini PetscErrorCode PCFieldSplitSetSchurScale(PC pc,PetscScalar scale)
2576c096484dSStefano Zampini {
2577c096484dSStefano Zampini   PetscErrorCode ierr;
2578c096484dSStefano Zampini 
2579c096484dSStefano Zampini   PetscFunctionBegin;
2580c096484dSStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
2581c096484dSStefano Zampini   PetscValidLogicalCollectiveScalar(pc,scale,2);
2582c096484dSStefano Zampini   ierr = PetscTryMethod(pc,"PCFieldSplitSetSchurScale_C",(PC,PetscScalar),(pc,scale));CHKERRQ(ierr);
2583c096484dSStefano Zampini   PetscFunctionReturn(0);
2584c096484dSStefano Zampini }
2585c096484dSStefano Zampini 
2586c096484dSStefano Zampini static PetscErrorCode PCFieldSplitSetSchurScale_FieldSplit(PC pc,PetscScalar scale)
2587c096484dSStefano Zampini {
2588c096484dSStefano Zampini   PC_FieldSplit *jac = (PC_FieldSplit*)pc->data;
2589c096484dSStefano Zampini 
2590c096484dSStefano Zampini   PetscFunctionBegin;
2591c096484dSStefano Zampini   jac->schurscale = scale;
2592c096484dSStefano Zampini   PetscFunctionReturn(0);
2593c096484dSStefano Zampini }
2594c096484dSStefano Zampini 
259530ad9308SMatthew Knepley /*@C
25968c03b21aSDmitry Karpeev    PCFieldSplitGetSchurBlocks - Gets all matrix blocks for the Schur complement
259730ad9308SMatthew Knepley 
259830ad9308SMatthew Knepley    Collective on KSP
259930ad9308SMatthew Knepley 
260030ad9308SMatthew Knepley    Input Parameter:
260130ad9308SMatthew Knepley .  pc - the preconditioner context
260230ad9308SMatthew Knepley 
260330ad9308SMatthew Knepley    Output Parameters:
2604a04f6461SBarry Smith +  A00 - the (0,0) block
2605a04f6461SBarry Smith .  A01 - the (0,1) block
2606a04f6461SBarry Smith .  A10 - the (1,0) block
2607a04f6461SBarry Smith -  A11 - the (1,1) block
260830ad9308SMatthew Knepley 
260930ad9308SMatthew Knepley    Level: advanced
261030ad9308SMatthew Knepley 
261130ad9308SMatthew Knepley .seealso: PCFIELDSPLIT
261230ad9308SMatthew Knepley @*/
2613a04f6461SBarry Smith PetscErrorCode  PCFieldSplitGetSchurBlocks(PC pc,Mat *A00,Mat *A01,Mat *A10, Mat *A11)
261430ad9308SMatthew Knepley {
261530ad9308SMatthew Knepley   PC_FieldSplit *jac = (PC_FieldSplit*) pc->data;
261630ad9308SMatthew Knepley 
261730ad9308SMatthew Knepley   PetscFunctionBegin;
26180700a824SBarry Smith   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
26192c71b3e2SJacob Faibussowitsch   PetscCheckFalse(jac->type != PC_COMPOSITE_SCHUR,PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONG, "FieldSplit is not using a Schur complement approach.");
2620a04f6461SBarry Smith   if (A00) *A00 = jac->pmat[0];
2621a04f6461SBarry Smith   if (A01) *A01 = jac->B;
2622a04f6461SBarry Smith   if (A10) *A10 = jac->C;
2623a04f6461SBarry Smith   if (A11) *A11 = jac->pmat[1];
262430ad9308SMatthew Knepley   PetscFunctionReturn(0);
262530ad9308SMatthew Knepley }
262630ad9308SMatthew Knepley 
2627b09e027eSCarola Kruse /*@
2628e071a0a4SCarola Kruse     PCFieldSplitSetGKBTol -  Sets the solver tolerance for the generalized Golub-Kahan bidiagonalization preconditioner.
2629b09e027eSCarola Kruse 
2630b09e027eSCarola Kruse     Collective on PC
2631b09e027eSCarola Kruse 
2632e071a0a4SCarola Kruse     Notes:
2633e071a0a4SCarola Kruse     The generalized GKB algorithm uses a lower bound estimate of the error in energy norm as stopping criterion.
2634e071a0a4SCarola Kruse     It stops once the lower bound estimate undershoots the required solver tolerance. Although the actual error might be bigger than
2635e071a0a4SCarola Kruse     this estimate, the stopping criterion is satisfactory in practical cases [A13].
2636e071a0a4SCarola Kruse 
2637e071a0a4SCarola Kruse [Ar13] Generalized Golub-Kahan bidiagonalization and stopping criteria, SIAM J. Matrix Anal. Appl., Vol. 34, No. 2, pp. 571-592, 2013.
2638e071a0a4SCarola Kruse 
2639b09e027eSCarola Kruse     Input Parameters:
2640b09e027eSCarola Kruse +   pc        - the preconditioner context
2641b09e027eSCarola Kruse -   tolerance - the solver tolerance
2642b09e027eSCarola Kruse 
2643b09e027eSCarola Kruse     Options Database:
2644b09e027eSCarola Kruse .     -pc_fieldsplit_gkb_tol - default is 1e-5
2645b09e027eSCarola Kruse 
2646b09e027eSCarola Kruse     Level: intermediate
2647b09e027eSCarola Kruse 
2648b09e027eSCarola Kruse .seealso: PCFIELDSPLIT, PCFieldSplitSetGKBDelay(), PCFieldSplitSetGKBNu(), PCFieldSplitSetGKBMaxit()
2649b09e027eSCarola Kruse @*/
2650b09e027eSCarola Kruse PetscErrorCode PCFieldSplitSetGKBTol(PC pc,PetscReal tolerance)
2651b09e027eSCarola Kruse {
2652b09e027eSCarola Kruse   PetscErrorCode ierr;
2653b09e027eSCarola Kruse 
2654b09e027eSCarola Kruse   PetscFunctionBegin;
2655b09e027eSCarola Kruse   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
2656de482cd7SCarola Kruse   PetscValidLogicalCollectiveReal(pc,tolerance,2);
2657b09e027eSCarola Kruse   ierr = PetscTryMethod(pc,"PCFieldSplitSetGKBTol_C",(PC,PetscReal),(pc,tolerance));CHKERRQ(ierr);
2658b09e027eSCarola Kruse   PetscFunctionReturn(0);
2659b09e027eSCarola Kruse }
2660b09e027eSCarola Kruse 
2661b09e027eSCarola Kruse static PetscErrorCode PCFieldSplitSetGKBTol_FieldSplit(PC pc,PetscReal tolerance)
2662b09e027eSCarola Kruse {
2663b09e027eSCarola Kruse   PC_FieldSplit *jac = (PC_FieldSplit*)pc->data;
2664b09e027eSCarola Kruse 
2665b09e027eSCarola Kruse   PetscFunctionBegin;
2666b09e027eSCarola Kruse   jac->gkbtol = tolerance;
2667b09e027eSCarola Kruse   PetscFunctionReturn(0);
2668b09e027eSCarola Kruse }
2669b09e027eSCarola Kruse 
2670b09e027eSCarola Kruse /*@
2671e071a0a4SCarola Kruse     PCFieldSplitSetGKBMaxit -  Sets the maximum number of iterations for the generalized Golub-Kahan bidiagonalization
2672e071a0a4SCarola Kruse     preconditioner.
2673b09e027eSCarola Kruse 
2674b09e027eSCarola Kruse     Collective on PC
2675b09e027eSCarola Kruse 
2676b09e027eSCarola Kruse     Input Parameters:
2677b09e027eSCarola Kruse +   pc     - the preconditioner context
2678b09e027eSCarola Kruse -   maxit  - the maximum number of iterations
2679b09e027eSCarola Kruse 
2680b09e027eSCarola Kruse     Options Database:
2681b09e027eSCarola Kruse .     -pc_fieldsplit_gkb_maxit - default is 100
2682b09e027eSCarola Kruse 
2683b09e027eSCarola Kruse     Level: intermediate
2684b09e027eSCarola Kruse 
2685b09e027eSCarola Kruse .seealso: PCFIELDSPLIT, PCFieldSplitSetGKBDelay(), PCFieldSplitSetGKBTol(), PCFieldSplitSetGKBNu()
2686b09e027eSCarola Kruse @*/
2687b09e027eSCarola Kruse PetscErrorCode PCFieldSplitSetGKBMaxit(PC pc,PetscInt maxit)
2688b09e027eSCarola Kruse {
2689b09e027eSCarola Kruse   PetscErrorCode ierr;
2690b09e027eSCarola Kruse 
2691b09e027eSCarola Kruse   PetscFunctionBegin;
2692b09e027eSCarola Kruse   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
2693de482cd7SCarola Kruse   PetscValidLogicalCollectiveInt(pc,maxit,2);
2694b09e027eSCarola Kruse   ierr = PetscTryMethod(pc,"PCFieldSplitSetGKBMaxit_C",(PC,PetscInt),(pc,maxit));CHKERRQ(ierr);
2695b09e027eSCarola Kruse   PetscFunctionReturn(0);
2696b09e027eSCarola Kruse }
2697b09e027eSCarola Kruse 
2698b09e027eSCarola Kruse static PetscErrorCode PCFieldSplitSetGKBMaxit_FieldSplit(PC pc,PetscInt maxit)
2699b09e027eSCarola Kruse {
2700b09e027eSCarola Kruse   PC_FieldSplit *jac = (PC_FieldSplit*)pc->data;
2701b09e027eSCarola Kruse 
2702b09e027eSCarola Kruse   PetscFunctionBegin;
2703b09e027eSCarola Kruse   jac->gkbmaxit = maxit;
2704b09e027eSCarola Kruse   PetscFunctionReturn(0);
2705b09e027eSCarola Kruse }
2706b09e027eSCarola Kruse 
2707b09e027eSCarola Kruse /*@
2708e071a0a4SCarola Kruse     PCFieldSplitSetGKBDelay -  Sets the delay in the lower bound error estimate in the generalized Golub-Kahan bidiagonalization
2709e071a0a4SCarola Kruse     preconditioner.
2710b09e027eSCarola Kruse 
2711b09e027eSCarola Kruse     Collective on PC
2712b09e027eSCarola Kruse 
2713b09e027eSCarola Kruse     Notes:
2714e071a0a4SCarola Kruse     The algorithm uses a lower bound estimate of the error in energy norm as stopping criterion. The lower bound of the error ||u-u^k||_H
2715e071a0a4SCarola Kruse     is expressed as a truncated sum. The error at iteration k can only be measured at iteration (k + delay), and thus the algorithm needs
2716e071a0a4SCarola Kruse     at least (delay + 1) iterations to stop. For more details on the generalized Golub-Kahan bidiagonalization method and its lower bound stopping criterion, please refer to
2717b09e027eSCarola Kruse 
2718b09e027eSCarola Kruse [Ar13] Generalized Golub-Kahan bidiagonalization and stopping criteria, SIAM J. Matrix Anal. Appl., Vol. 34, No. 2, pp. 571-592, 2013.
2719b09e027eSCarola Kruse 
2720b09e027eSCarola Kruse     Input Parameters:
2721b09e027eSCarola Kruse +   pc     - the preconditioner context
2722b09e027eSCarola Kruse -   delay  - the delay window in the lower bound estimate
2723b09e027eSCarola Kruse 
2724b09e027eSCarola Kruse     Options Database:
2725b09e027eSCarola Kruse .     -pc_fieldsplit_gkb_delay - default is 5
2726b09e027eSCarola Kruse 
2727b09e027eSCarola Kruse     Level: intermediate
2728b09e027eSCarola Kruse 
2729b09e027eSCarola Kruse .seealso: PCFIELDSPLIT, PCFieldSplitSetGKBNu(), PCFieldSplitSetGKBTol(), PCFieldSplitSetGKBMaxit()
2730b09e027eSCarola Kruse @*/
2731b09e027eSCarola Kruse PetscErrorCode PCFieldSplitSetGKBDelay(PC pc,PetscInt delay)
2732b09e027eSCarola Kruse {
2733b09e027eSCarola Kruse   PetscErrorCode ierr;
2734b09e027eSCarola Kruse 
2735b09e027eSCarola Kruse   PetscFunctionBegin;
2736b09e027eSCarola Kruse   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
2737b09e027eSCarola Kruse   PetscValidLogicalCollectiveInt(pc,delay,2);
2738b09e027eSCarola Kruse   ierr = PetscTryMethod(pc,"PCFieldSplitSetGKBDelay_C",(PC,PetscInt),(pc,delay));CHKERRQ(ierr);
2739b09e027eSCarola Kruse   PetscFunctionReturn(0);
2740b09e027eSCarola Kruse }
2741b09e027eSCarola Kruse 
2742b09e027eSCarola Kruse static PetscErrorCode PCFieldSplitSetGKBDelay_FieldSplit(PC pc,PetscInt delay)
2743b09e027eSCarola Kruse {
2744b09e027eSCarola Kruse   PC_FieldSplit *jac = (PC_FieldSplit*)pc->data;
2745b09e027eSCarola Kruse 
2746b09e027eSCarola Kruse   PetscFunctionBegin;
2747b09e027eSCarola Kruse   jac->gkbdelay = delay;
2748b09e027eSCarola Kruse   PetscFunctionReturn(0);
2749b09e027eSCarola Kruse }
2750b09e027eSCarola Kruse 
2751b09e027eSCarola Kruse /*@
2752b09e027eSCarola Kruse     PCFieldSplitSetGKBNu -  Sets the scalar value nu >= 0 in the transformation H = A00 + nu*A01*A01' of the (1,1) block in the Golub-Kahan bidiagonalization preconditioner.
2753b09e027eSCarola Kruse 
2754b09e027eSCarola Kruse     Collective on PC
2755b09e027eSCarola Kruse 
2756b09e027eSCarola Kruse     Notes:
2757e071a0a4SCarola Kruse     This shift is in general done to obtain better convergence properties for the outer loop of the algorithm. This is often achieved by chosing nu sufficiently big. However,
2758b09e027eSCarola Kruse     if nu is chosen too big, the matrix H might be badly conditioned and the solution of the linear system Hx = b in the inner loop gets difficult. It is therefore
2759b09e027eSCarola Kruse     necessary to find a good balance in between the convergence of the inner and outer loop.
2760b09e027eSCarola Kruse 
2761b09e027eSCarola Kruse     For nu = 0, no shift is done. In this case A00 has to be positive definite. The matrix N in [Ar13] is then chosen as identity.
2762b09e027eSCarola Kruse 
2763b09e027eSCarola Kruse [Ar13] Generalized Golub-Kahan bidiagonalization and stopping criteria, SIAM J. Matrix Anal. Appl., Vol. 34, No. 2, pp. 571-592, 2013.
2764b09e027eSCarola Kruse 
2765b09e027eSCarola Kruse     Input Parameters:
2766b09e027eSCarola Kruse +   pc     - the preconditioner context
2767b09e027eSCarola Kruse -   nu     - the shift parameter
2768b09e027eSCarola Kruse 
2769b09e027eSCarola Kruse     Options Database:
2770b09e027eSCarola Kruse .     -pc_fieldsplit_gkb_nu - default is 1
2771b09e027eSCarola Kruse 
2772b09e027eSCarola Kruse     Level: intermediate
2773b09e027eSCarola Kruse 
2774b09e027eSCarola Kruse .seealso: PCFIELDSPLIT, PCFieldSplitSetGKBDelay(), PCFieldSplitSetGKBTol(), PCFieldSplitSetGKBMaxit()
2775b09e027eSCarola Kruse @*/
2776b09e027eSCarola Kruse PetscErrorCode PCFieldSplitSetGKBNu(PC pc,PetscReal nu)
2777b09e027eSCarola Kruse {
2778b09e027eSCarola Kruse   PetscErrorCode ierr;
2779b09e027eSCarola Kruse 
2780b09e027eSCarola Kruse   PetscFunctionBegin;
2781b09e027eSCarola Kruse   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
2782de482cd7SCarola Kruse   PetscValidLogicalCollectiveReal(pc,nu,2);
2783b09e027eSCarola Kruse   ierr = PetscTryMethod(pc,"PCFieldSplitSetGKBNu_C",(PC,PetscReal),(pc,nu));CHKERRQ(ierr);
2784b09e027eSCarola Kruse   PetscFunctionReturn(0);
2785b09e027eSCarola Kruse }
2786b09e027eSCarola Kruse 
2787b09e027eSCarola Kruse static PetscErrorCode PCFieldSplitSetGKBNu_FieldSplit(PC pc,PetscReal nu)
2788b09e027eSCarola Kruse {
2789b09e027eSCarola Kruse   PC_FieldSplit *jac = (PC_FieldSplit*)pc->data;
2790b09e027eSCarola Kruse 
2791b09e027eSCarola Kruse   PetscFunctionBegin;
2792b09e027eSCarola Kruse   jac->gkbnu = nu;
2793b09e027eSCarola Kruse   PetscFunctionReturn(0);
2794b09e027eSCarola Kruse }
2795b09e027eSCarola Kruse 
27961e6b0712SBarry Smith static PetscErrorCode  PCFieldSplitSetType_FieldSplit(PC pc,PCCompositeType type)
279779416396SBarry Smith {
279879416396SBarry Smith   PC_FieldSplit  *jac = (PC_FieldSplit*)pc->data;
2799e69d4d44SBarry Smith   PetscErrorCode ierr;
280079416396SBarry Smith 
280179416396SBarry Smith   PetscFunctionBegin;
280279416396SBarry Smith   jac->type = type;
2803e071a0a4SCarola Kruse 
2804e071a0a4SCarola Kruse   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCFieldSplitGetSubKSP_C",0);CHKERRQ(ierr);
2805e071a0a4SCarola Kruse   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCFieldSplitSetSchurPre_C",0);CHKERRQ(ierr);
2806e071a0a4SCarola Kruse   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCFieldSplitGetSchurPre_C",0);CHKERRQ(ierr);
2807e071a0a4SCarola Kruse   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCFieldSplitSetSchurFactType_C",0);CHKERRQ(ierr);
2808e071a0a4SCarola Kruse   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCFieldSplitSetSchurScale_C",0);CHKERRQ(ierr);
2809e071a0a4SCarola Kruse   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCFieldSplitSetGKBTol_C",0);CHKERRQ(ierr);
2810e071a0a4SCarola Kruse   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCFieldSplitSetGKBMaxit_C",0);CHKERRQ(ierr);
2811e071a0a4SCarola Kruse   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCFieldSplitSetGKBNu_C",0);CHKERRQ(ierr);
2812e071a0a4SCarola Kruse   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCFieldSplitSetGKBDelay_C",0);CHKERRQ(ierr);
2813e071a0a4SCarola Kruse 
28143b224e63SBarry Smith   if (type == PC_COMPOSITE_SCHUR) {
28153b224e63SBarry Smith     pc->ops->apply = PCApply_FieldSplit_Schur;
28163b224e63SBarry Smith     pc->ops->view  = PCView_FieldSplit_Schur;
28172fa5cd67SKarl Rupp 
2818bdf89e91SBarry Smith     ierr = PetscObjectComposeFunction((PetscObject)pc,"PCFieldSplitGetSubKSP_C",PCFieldSplitGetSubKSP_FieldSplit_Schur);CHKERRQ(ierr);
281929f8a81cSJed Brown     ierr = PetscObjectComposeFunction((PetscObject)pc,"PCFieldSplitSetSchurPre_C",PCFieldSplitSetSchurPre_FieldSplit);CHKERRQ(ierr);
282037a82bf0SJed Brown     ierr = PetscObjectComposeFunction((PetscObject)pc,"PCFieldSplitGetSchurPre_C",PCFieldSplitGetSchurPre_FieldSplit);CHKERRQ(ierr);
2821bdf89e91SBarry Smith     ierr = PetscObjectComposeFunction((PetscObject)pc,"PCFieldSplitSetSchurFactType_C",PCFieldSplitSetSchurFactType_FieldSplit);CHKERRQ(ierr);
2822c096484dSStefano Zampini     ierr = PetscObjectComposeFunction((PetscObject)pc,"PCFieldSplitSetSchurScale_C",PCFieldSplitSetSchurScale_FieldSplit);CHKERRQ(ierr);
2823a51937d4SCarola Kruse   } else if (type == PC_COMPOSITE_GKB) {
2824a51937d4SCarola Kruse     pc->ops->apply = PCApply_FieldSplit_GKB;
2825a51937d4SCarola Kruse     pc->ops->view  = PCView_FieldSplit_GKB;
2826e69d4d44SBarry Smith 
2827a51937d4SCarola Kruse     ierr = PetscObjectComposeFunction((PetscObject)pc,"PCFieldSplitGetSubKSP_C",PCFieldSplitGetSubKSP_FieldSplit);CHKERRQ(ierr);
2828b09e027eSCarola Kruse     ierr = PetscObjectComposeFunction((PetscObject)pc,"PCFieldSplitSetGKBTol_C",PCFieldSplitSetGKBTol_FieldSplit);CHKERRQ(ierr);
2829b09e027eSCarola Kruse     ierr = PetscObjectComposeFunction((PetscObject)pc,"PCFieldSplitSetGKBMaxit_C",PCFieldSplitSetGKBMaxit_FieldSplit);CHKERRQ(ierr);
2830b09e027eSCarola Kruse     ierr = PetscObjectComposeFunction((PetscObject)pc,"PCFieldSplitSetGKBNu_C",PCFieldSplitSetGKBNu_FieldSplit);CHKERRQ(ierr);
2831b09e027eSCarola Kruse     ierr = PetscObjectComposeFunction((PetscObject)pc,"PCFieldSplitSetGKBDelay_C",PCFieldSplitSetGKBDelay_FieldSplit);CHKERRQ(ierr);
28323b224e63SBarry Smith   } else {
28333b224e63SBarry Smith     pc->ops->apply = PCApply_FieldSplit;
28343b224e63SBarry Smith     pc->ops->view  = PCView_FieldSplit;
28352fa5cd67SKarl Rupp 
2836bdf89e91SBarry Smith     ierr = PetscObjectComposeFunction((PetscObject)pc,"PCFieldSplitGetSubKSP_C",PCFieldSplitGetSubKSP_FieldSplit);CHKERRQ(ierr);
28373b224e63SBarry Smith   }
283879416396SBarry Smith   PetscFunctionReturn(0);
283979416396SBarry Smith }
284079416396SBarry Smith 
28411e6b0712SBarry Smith static PetscErrorCode  PCFieldSplitSetBlockSize_FieldSplit(PC pc,PetscInt bs)
284251f519a2SBarry Smith {
284351f519a2SBarry Smith   PC_FieldSplit *jac = (PC_FieldSplit*)pc->data;
284451f519a2SBarry Smith 
284551f519a2SBarry Smith   PetscFunctionBegin;
28462c71b3e2SJacob Faibussowitsch   PetscCheckFalse(bs < 1,PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_OUTOFRANGE,"Blocksize must be positive, you gave %D",bs);
28472c71b3e2SJacob Faibussowitsch   PetscCheckFalse(jac->bs > 0 && jac->bs != bs,PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONGSTATE,"Cannot change fieldsplit blocksize from %D to %D after it has been set",jac->bs,bs);
284851f519a2SBarry Smith   jac->bs = bs;
284951f519a2SBarry Smith   PetscFunctionReturn(0);
285051f519a2SBarry Smith }
285151f519a2SBarry Smith 
2852*5ddf11f8SNicolas Barnafi static PetscErrorCode PCSetCoordinates_FieldSplit(PC pc, PetscInt dim, PetscInt nloc, PetscReal coords[])
2853*5ddf11f8SNicolas Barnafi {
2854*5ddf11f8SNicolas Barnafi   PetscErrorCode    ierr;
2855*5ddf11f8SNicolas Barnafi   PC_FieldSplit *   jac = (PC_FieldSplit*)pc->data;
2856*5ddf11f8SNicolas Barnafi   PC_FieldSplitLink ilink_current = jac->head;
2857*5ddf11f8SNicolas Barnafi   PetscInt          ii;
2858*5ddf11f8SNicolas Barnafi   IS                is_owned;
2859*5ddf11f8SNicolas Barnafi 
2860*5ddf11f8SNicolas Barnafi   PetscFunctionBegin;
2861*5ddf11f8SNicolas Barnafi   jac->coordinates_set = PETSC_TRUE; // Internal flag
2862*5ddf11f8SNicolas Barnafi   ierr = MatGetOwnershipIS(pc->mat,&is_owned,PETSC_NULL);CHKERRQ(ierr);
2863*5ddf11f8SNicolas Barnafi 
2864*5ddf11f8SNicolas Barnafi   ii=0;
2865*5ddf11f8SNicolas Barnafi   while (ilink_current) {
2866*5ddf11f8SNicolas Barnafi     // For each IS, embed it to get local coords indces
2867*5ddf11f8SNicolas Barnafi     IS        is_coords;
2868*5ddf11f8SNicolas Barnafi     PetscInt  ndofs_block;
2869*5ddf11f8SNicolas Barnafi     const PetscInt *block_dofs_enumeration; // Numbering of the dofs relevant to the current block
2870*5ddf11f8SNicolas Barnafi 
2871*5ddf11f8SNicolas Barnafi     // Setting drop to true for safety. It should make no difference.
2872*5ddf11f8SNicolas Barnafi     ierr = ISEmbed(ilink_current->is, is_owned, PETSC_TRUE, &is_coords);CHKERRQ(ierr);
2873*5ddf11f8SNicolas Barnafi     ierr = ISGetLocalSize(is_coords, &ndofs_block);CHKERRQ(ierr);
2874*5ddf11f8SNicolas Barnafi     ierr = ISGetIndices(is_coords, &block_dofs_enumeration);CHKERRQ(ierr);
2875*5ddf11f8SNicolas Barnafi 
2876*5ddf11f8SNicolas Barnafi     // Allocate coordinates vector and set it directly
2877*5ddf11f8SNicolas Barnafi     ierr = PetscMalloc1(ndofs_block * dim, &(ilink_current->coords));
2878*5ddf11f8SNicolas Barnafi     for (PetscInt dof=0;dof<ndofs_block;++dof) {
2879*5ddf11f8SNicolas Barnafi       for (PetscInt d=0;d<dim;++d) {
2880*5ddf11f8SNicolas Barnafi         (ilink_current->coords)[dim*dof + d] = coords[dim * block_dofs_enumeration[dof] + d];
2881*5ddf11f8SNicolas Barnafi       }
2882*5ddf11f8SNicolas Barnafi     }
2883*5ddf11f8SNicolas Barnafi     ilink_current->dim = dim;
2884*5ddf11f8SNicolas Barnafi     ilink_current->ndofs = ndofs_block;
2885*5ddf11f8SNicolas Barnafi     ierr = ISRestoreIndices(is_coords, &block_dofs_enumeration);CHKERRQ(ierr);
2886*5ddf11f8SNicolas Barnafi     ierr = ISDestroy(&is_coords);CHKERRQ(ierr);
2887*5ddf11f8SNicolas Barnafi     ilink_current = ilink_current->next;
2888*5ddf11f8SNicolas Barnafi     ++ii;
2889*5ddf11f8SNicolas Barnafi   }
2890*5ddf11f8SNicolas Barnafi   ierr = ISDestroy(&is_owned);CHKERRQ(ierr);
2891*5ddf11f8SNicolas Barnafi   PetscFunctionReturn(0);
2892*5ddf11f8SNicolas Barnafi }
2893*5ddf11f8SNicolas Barnafi 
2894bc08b0f1SBarry Smith /*@
289579416396SBarry Smith    PCFieldSplitSetType - Sets the type of fieldsplit preconditioner.
289679416396SBarry Smith 
289779416396SBarry Smith    Collective on PC
289879416396SBarry Smith 
2899d8d19677SJose E. Roman    Input Parameters:
2900a2b725a8SWilliam Gropp +  pc - the preconditioner context
2901a2b725a8SWilliam Gropp -  type - PC_COMPOSITE_ADDITIVE, PC_COMPOSITE_MULTIPLICATIVE (default), PC_COMPOSITE_SYMMETRIC_MULTIPLICATIVE, PC_COMPOSITE_SPECIAL, PC_COMPOSITE_SCHUR
290279416396SBarry Smith 
290379416396SBarry Smith    Options Database Key:
2904a4efd8eaSMatthew Knepley .  -pc_fieldsplit_type <type: one of multiplicative, additive, symmetric_multiplicative, special, schur> - Sets fieldsplit preconditioner type
290579416396SBarry Smith 
2906b02e2d75SMatthew G Knepley    Level: Intermediate
290779416396SBarry Smith 
290879416396SBarry Smith .seealso: PCCompositeSetType()
290979416396SBarry Smith 
291079416396SBarry Smith @*/
29117087cfbeSBarry Smith PetscErrorCode  PCFieldSplitSetType(PC pc,PCCompositeType type)
291279416396SBarry Smith {
29134ac538c5SBarry Smith   PetscErrorCode ierr;
291479416396SBarry Smith 
291579416396SBarry Smith   PetscFunctionBegin;
29160700a824SBarry Smith   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
29174ac538c5SBarry Smith   ierr = PetscTryMethod(pc,"PCFieldSplitSetType_C",(PC,PCCompositeType),(pc,type));CHKERRQ(ierr);
291879416396SBarry Smith   PetscFunctionReturn(0);
291979416396SBarry Smith }
292079416396SBarry Smith 
2921b02e2d75SMatthew G Knepley /*@
2922b02e2d75SMatthew G Knepley   PCFieldSplitGetType - Gets the type of fieldsplit preconditioner.
2923b02e2d75SMatthew G Knepley 
2924b02e2d75SMatthew G Knepley   Not collective
2925b02e2d75SMatthew G Knepley 
2926b02e2d75SMatthew G Knepley   Input Parameter:
2927b02e2d75SMatthew G Knepley . pc - the preconditioner context
2928b02e2d75SMatthew G Knepley 
2929b02e2d75SMatthew G Knepley   Output Parameter:
2930b02e2d75SMatthew G Knepley . type - PC_COMPOSITE_ADDITIVE, PC_COMPOSITE_MULTIPLICATIVE (default), PC_COMPOSITE_SYMMETRIC_MULTIPLICATIVE, PC_COMPOSITE_SPECIAL, PC_COMPOSITE_SCHUR
2931b02e2d75SMatthew G Knepley 
2932b02e2d75SMatthew G Knepley   Level: Intermediate
2933b02e2d75SMatthew G Knepley 
2934b02e2d75SMatthew G Knepley .seealso: PCCompositeSetType()
2935b02e2d75SMatthew G Knepley @*/
2936b02e2d75SMatthew G Knepley PetscErrorCode PCFieldSplitGetType(PC pc, PCCompositeType *type)
2937b02e2d75SMatthew G Knepley {
2938b02e2d75SMatthew G Knepley   PC_FieldSplit *jac = (PC_FieldSplit*) pc->data;
2939b02e2d75SMatthew G Knepley 
2940b02e2d75SMatthew G Knepley   PetscFunctionBegin;
2941b02e2d75SMatthew G Knepley   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
2942b02e2d75SMatthew G Knepley   PetscValidIntPointer(type,2);
2943b02e2d75SMatthew G Knepley   *type = jac->type;
2944b02e2d75SMatthew G Knepley   PetscFunctionReturn(0);
2945b02e2d75SMatthew G Knepley }
2946b02e2d75SMatthew G Knepley 
29474ab8060aSDmitry Karpeev /*@
29484ab8060aSDmitry Karpeev    PCFieldSplitSetDMSplits - Flags whether DMCreateFieldDecomposition() should be used to define the splits, whenever possible.
29494ab8060aSDmitry Karpeev 
29504ab8060aSDmitry Karpeev    Logically Collective
29514ab8060aSDmitry Karpeev 
29524ab8060aSDmitry Karpeev    Input Parameters:
29534ab8060aSDmitry Karpeev +  pc   - the preconditioner context
29544ab8060aSDmitry Karpeev -  flg  - boolean indicating whether to use field splits defined by the DM
29554ab8060aSDmitry Karpeev 
29564ab8060aSDmitry Karpeev    Options Database Key:
29574ab8060aSDmitry Karpeev .  -pc_fieldsplit_dm_splits
29584ab8060aSDmitry Karpeev 
29594ab8060aSDmitry Karpeev    Level: Intermediate
29604ab8060aSDmitry Karpeev 
29614ab8060aSDmitry Karpeev .seealso: PCFieldSplitGetDMSplits()
29624ab8060aSDmitry Karpeev 
29634ab8060aSDmitry Karpeev @*/
29644ab8060aSDmitry Karpeev PetscErrorCode  PCFieldSplitSetDMSplits(PC pc,PetscBool flg)
29654ab8060aSDmitry Karpeev {
29664ab8060aSDmitry Karpeev   PC_FieldSplit  *jac = (PC_FieldSplit*)pc->data;
29674ab8060aSDmitry Karpeev   PetscBool      isfs;
29684ab8060aSDmitry Karpeev   PetscErrorCode ierr;
29694ab8060aSDmitry Karpeev 
29704ab8060aSDmitry Karpeev   PetscFunctionBegin;
29714ab8060aSDmitry Karpeev   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
29724ab8060aSDmitry Karpeev   PetscValidLogicalCollectiveBool(pc,flg,2);
29734ab8060aSDmitry Karpeev   ierr = PetscObjectTypeCompare((PetscObject)pc,PCFIELDSPLIT,&isfs);CHKERRQ(ierr);
29744ab8060aSDmitry Karpeev   if (isfs) {
29754ab8060aSDmitry Karpeev     jac->dm_splits = flg;
29764ab8060aSDmitry Karpeev   }
29774ab8060aSDmitry Karpeev   PetscFunctionReturn(0);
29784ab8060aSDmitry Karpeev }
29794ab8060aSDmitry Karpeev 
29804ab8060aSDmitry Karpeev /*@
29814ab8060aSDmitry Karpeev    PCFieldSplitGetDMSplits - Returns flag indicating whether DMCreateFieldDecomposition() should be used to define the splits, whenever possible.
29824ab8060aSDmitry Karpeev 
29834ab8060aSDmitry Karpeev    Logically Collective
29844ab8060aSDmitry Karpeev 
29854ab8060aSDmitry Karpeev    Input Parameter:
29864ab8060aSDmitry Karpeev .  pc   - the preconditioner context
29874ab8060aSDmitry Karpeev 
29884ab8060aSDmitry Karpeev    Output Parameter:
29894ab8060aSDmitry Karpeev .  flg  - boolean indicating whether to use field splits defined by the DM
29904ab8060aSDmitry Karpeev 
29914ab8060aSDmitry Karpeev    Level: Intermediate
29924ab8060aSDmitry Karpeev 
29934ab8060aSDmitry Karpeev .seealso: PCFieldSplitSetDMSplits()
29944ab8060aSDmitry Karpeev 
29954ab8060aSDmitry Karpeev @*/
29964ab8060aSDmitry Karpeev PetscErrorCode  PCFieldSplitGetDMSplits(PC pc,PetscBool* flg)
29974ab8060aSDmitry Karpeev {
29984ab8060aSDmitry Karpeev   PC_FieldSplit  *jac = (PC_FieldSplit*)pc->data;
29994ab8060aSDmitry Karpeev   PetscBool      isfs;
30004ab8060aSDmitry Karpeev   PetscErrorCode ierr;
30014ab8060aSDmitry Karpeev 
30024ab8060aSDmitry Karpeev   PetscFunctionBegin;
30034ab8060aSDmitry Karpeev   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
3004534a8f05SLisandro Dalcin   PetscValidBoolPointer(flg,2);
30054ab8060aSDmitry Karpeev   ierr = PetscObjectTypeCompare((PetscObject)pc,PCFIELDSPLIT,&isfs);CHKERRQ(ierr);
30064ab8060aSDmitry Karpeev   if (isfs) {
30074ab8060aSDmitry Karpeev     if (flg) *flg = jac->dm_splits;
30084ab8060aSDmitry Karpeev   }
30094ab8060aSDmitry Karpeev   PetscFunctionReturn(0);
30104ab8060aSDmitry Karpeev }
30114ab8060aSDmitry Karpeev 
30127b752e3dSPatrick Sanan /*@
30137b752e3dSPatrick Sanan    PCFieldSplitGetDetectSaddlePoint - Returns flag indicating whether PCFieldSplit will attempt to automatically determine fields based on zero diagonal entries.
30147b752e3dSPatrick Sanan 
30157b752e3dSPatrick Sanan    Logically Collective
30167b752e3dSPatrick Sanan 
30177b752e3dSPatrick Sanan    Input Parameter:
30187b752e3dSPatrick Sanan .  pc   - the preconditioner context
30197b752e3dSPatrick Sanan 
30207b752e3dSPatrick Sanan    Output Parameter:
30217b752e3dSPatrick Sanan .  flg  - boolean indicating whether to detect fields or not
30227b752e3dSPatrick Sanan 
30237b752e3dSPatrick Sanan    Level: Intermediate
30247b752e3dSPatrick Sanan 
30257b752e3dSPatrick Sanan .seealso: PCFIELDSPLIT, PCFieldSplitSetDetectSaddlePoint()
30267b752e3dSPatrick Sanan 
30277b752e3dSPatrick Sanan @*/
30287b752e3dSPatrick Sanan PetscErrorCode PCFieldSplitGetDetectSaddlePoint(PC pc,PetscBool *flg)
30297b752e3dSPatrick Sanan {
30307b752e3dSPatrick Sanan   PC_FieldSplit *jac = (PC_FieldSplit*)pc->data;
30317b752e3dSPatrick Sanan 
30327b752e3dSPatrick Sanan   PetscFunctionBegin;
30337b752e3dSPatrick Sanan   *flg = jac->detect;
30347b752e3dSPatrick Sanan   PetscFunctionReturn(0);
30357b752e3dSPatrick Sanan }
30367b752e3dSPatrick Sanan 
30377b752e3dSPatrick Sanan /*@
30387b752e3dSPatrick Sanan    PCFieldSplitSetDetectSaddlePoint - Sets flag indicating whether PCFieldSplit will attempt to automatically determine fields based on zero diagonal entries.
30397b752e3dSPatrick Sanan 
30407b752e3dSPatrick Sanan    Logically Collective
30417b752e3dSPatrick Sanan 
30427b752e3dSPatrick Sanan    Notes:
30437b752e3dSPatrick 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()).
30447b752e3dSPatrick Sanan 
30457b752e3dSPatrick Sanan    Input Parameter:
30467b752e3dSPatrick Sanan .  pc   - the preconditioner context
30477b752e3dSPatrick Sanan 
30487b752e3dSPatrick Sanan    Output Parameter:
30497b752e3dSPatrick Sanan .  flg  - boolean indicating whether to detect fields or not
30507b752e3dSPatrick Sanan 
30517b752e3dSPatrick Sanan    Options Database Key:
30527b752e3dSPatrick Sanan .  -pc_fieldsplit_detect_saddle_point
30537b752e3dSPatrick Sanan 
30547b752e3dSPatrick Sanan    Level: Intermediate
30557b752e3dSPatrick Sanan 
30567b752e3dSPatrick Sanan .seealso: PCFIELDSPLIT, PCFieldSplitSetDetectSaddlePoint(), PCFieldSplitSetType(), PCFieldSplitSetSchurPre()
30577b752e3dSPatrick Sanan 
30587b752e3dSPatrick Sanan @*/
30597b752e3dSPatrick Sanan PetscErrorCode PCFieldSplitSetDetectSaddlePoint(PC pc,PetscBool flg)
30607b752e3dSPatrick Sanan {
30617b752e3dSPatrick Sanan   PC_FieldSplit  *jac = (PC_FieldSplit*)pc->data;
30627b752e3dSPatrick Sanan   PetscErrorCode ierr;
30637b752e3dSPatrick Sanan 
30647b752e3dSPatrick Sanan   PetscFunctionBegin;
30657b752e3dSPatrick Sanan   jac->detect = flg;
30667b752e3dSPatrick Sanan   if (jac->detect) {
30677b752e3dSPatrick Sanan     ierr = PCFieldSplitSetType(pc,PC_COMPOSITE_SCHUR);CHKERRQ(ierr);
30687b752e3dSPatrick Sanan     ierr = PCFieldSplitSetSchurPre(pc,PC_FIELDSPLIT_SCHUR_PRE_SELF,NULL);CHKERRQ(ierr);
30697b752e3dSPatrick Sanan   }
30707b752e3dSPatrick Sanan   PetscFunctionReturn(0);
30717b752e3dSPatrick Sanan }
30727b752e3dSPatrick Sanan 
30730971522cSBarry Smith /* -------------------------------------------------------------------------------------*/
30740971522cSBarry Smith /*MC
3075a8c7a070SBarry Smith    PCFIELDSPLIT - Preconditioner created by combining separate preconditioners for individual
3076a04f6461SBarry Smith                   fields or groups of fields. See the users manual section "Solving Block Matrices" for more details.
30770971522cSBarry Smith 
3078edf189efSBarry Smith      To set options on the solvers for each block append -fieldsplit_ to all the PC
3079edf189efSBarry Smith         options database keys. For example, -fieldsplit_pc_type ilu -fieldsplit_pc_factor_levels 1
30800971522cSBarry Smith 
3081a8c7a070SBarry Smith      To set the options on the solvers separate for each block call PCFieldSplitGetSubKSP()
308269a612a9SBarry Smith          and set the options directly on the resulting KSP object
30830971522cSBarry Smith 
30840971522cSBarry Smith    Level: intermediate
30850971522cSBarry Smith 
308679416396SBarry Smith    Options Database Keys:
308781540f2fSBarry Smith +   -pc_fieldsplit_%d_fields <a,b,..> - indicates the fields to be used in the %d'th split
308881540f2fSBarry Smith .   -pc_fieldsplit_default - automatically add any fields to additional splits that have not
308981540f2fSBarry Smith                               been supplied explicitly by -pc_fieldsplit_%d_fields
309081540f2fSBarry Smith .   -pc_fieldsplit_block_size <bs> - size of block that defines fields (i.e. there are bs fields)
3091a51937d4SCarola Kruse .   -pc_fieldsplit_type <additive,multiplicative,symmetric_multiplicative,schur,gkb> - type of relaxation or factorization splitting
3092a6a584a2SBarry Smith .   -pc_fieldsplit_schur_precondition <self,selfp,user,a11,full> - default is a11; see PCFieldSplitSetSchurPre()
3093412be6bfSPatrick Sanan .   -pc_fieldsplit_schur_fact_type <diag,lower,upper,full> - set factorization type when using -pc_fieldsplit_type schur; see PCFieldSplitSetSchurFactType()
3094fb6809a2SPatrick Sanan -   -pc_fieldsplit_detect_saddle_point - automatically finds rows with zero diagonal and uses Schur complement with no preconditioner as the solver
309579416396SBarry Smith 
3096fb6809a2SPatrick Sanan      Options prefixes for inner solvers when using the Schur complement preconditioner are -fieldsplit_0_ and -fieldsplit_1_ .
3097fb6809a2SPatrick Sanan      For all other solvers they are -fieldsplit_%d_ for the dth field; use -fieldsplit_ for all fields.
3098fb6809a2SPatrick Sanan      The options prefix for the inner solver when using the Golub-Kahan biadiagonalization preconditioner is -fieldsplit_0_
30995d4c12cdSJungho Lee 
3100c8a0d604SMatthew G Knepley    Notes:
3101c8a0d604SMatthew G Knepley     Use PCFieldSplitSetFields() to set fields defined by "strided" entries and PCFieldSplitSetIS()
3102d32f9abdSBarry Smith      to define a field by an arbitrary collection of entries.
3103d32f9abdSBarry Smith 
3104d32f9abdSBarry Smith       If no fields are set the default is used. The fields are defined by entries strided by bs,
3105d32f9abdSBarry Smith       beginning at 0 then 1, etc to bs-1. The block size can be set with PCFieldSplitSetBlockSize(),
3106d32f9abdSBarry Smith       if this is not called the block size defaults to the blocksize of the second matrix passed
3107d32f9abdSBarry Smith       to KSPSetOperators()/PCSetOperators().
3108d32f9abdSBarry Smith 
31092da392ccSBarry Smith $     For the Schur complement preconditioner if J = [ A00 A01]
31102da392ccSBarry Smith $                                                    [ A10 A11]
3111c8a0d604SMatthew G Knepley $     the preconditioner using full factorization is
31122da392ccSBarry Smith $              [ I   -ksp(A00) A01] [ inv(A00)    0  ] [     I          0]
31132da392ccSBarry Smith $              [ 0         I      ] [   0      ksp(S)] [ -A10 ksp(A00)  I]
311413b05affSJed Brown      where the action of inv(A00) is applied using the KSP solver with prefix -fieldsplit_0_.  S is the Schur complement
311513b05affSJed Brown $              S = A11 - A10 ksp(A00) A01
311613b05affSJed 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
3117686bed4dSStefano Zampini      in providing the SECOND split or 1 if not give). For PCFieldSplitGetSubKSP() when field number is 0,
3118c8a0d604SMatthew G Knepley      it returns the KSP associated with -fieldsplit_0_ while field number 1 gives -fieldsplit_1_ KSP. By default
3119a6a584a2SBarry Smith      A11 is used to construct a preconditioner for S, use PCFieldSplitSetSchurPre() for all the possible ways to construct the preconditioner for S.
31201d71051fSDmitry Karpeev 
3121a7476a74SDmitry Karpeev      The factorization type is set using -pc_fieldsplit_schur_fact_type <diag, lower, upper, full>. The full is shown above,
31225668aaf4SBarry Smith      diag gives
31232da392ccSBarry Smith $              [ inv(A00)     0 ]
31242da392ccSBarry Smith $              [   0      -ksp(S)]
3125c096484dSStefano 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
3126c096484dSStefano Zampini      can be turned off with PCFieldSplitSetSchurScale() or by command line -pc_fieldsplit_schur_scale 1.0. The lower factorization is the inverse of
31272da392ccSBarry Smith $              [  A00   0]
31282da392ccSBarry Smith $              [  A10   S]
3129c8a0d604SMatthew G Knepley      where the inverses of A00 and S are applied using KSPs. The upper factorization is the inverse of
31302da392ccSBarry Smith $              [ A00 A01]
31312da392ccSBarry Smith $              [  0   S ]
3132c8a0d604SMatthew G Knepley      where again the inverses of A00 and S are applied using KSPs.
3133e69d4d44SBarry Smith 
3134edf189efSBarry Smith      If only one set of indices (one IS) is provided with PCFieldSplitSetIS() then the complement of that IS
3135edf189efSBarry Smith      is used automatically for a second block.
3136edf189efSBarry Smith 
3137ff218e97SBarry Smith      The fieldsplit preconditioner cannot currently be used with the BAIJ or SBAIJ data formats if the blocksize is larger than 1.
3138ff218e97SBarry Smith      Generally it should be used with the AIJ format.
3139ff218e97SBarry Smith 
3140ff218e97SBarry Smith      The forms of these preconditioners are closely related if not identical to forms derived as "Distributive Iterations", see,
3141ff218e97SBarry Smith      for example, page 294 in "Principles of Computational Fluid Dynamics" by Pieter Wesseling. Note that one can also use PCFIELDSPLIT
3142ff218e97SBarry Smith      inside a smoother resulting in "Distributive Smoothers".
31430716a85fSBarry Smith 
31442da392ccSBarry Smith      References:
31452da392ccSBarry Smith        A taxonomy and comparison of parallel block multi-level preconditioners for the incompressible Navier-Stokes equations
31463bc631e0SBarry Smith        Howard Elman, V.E. Howle, John Shadid, Robert Shuttleworth, Ray Tuminaro, Journal of Computational Physics 227 (2008) 1790--1808
31473bc631e0SBarry Smith        http://chess.cs.umd.edu/~elman/papers/tax.pdf
31483bc631e0SBarry Smith 
31494d308398SBarry Smith    The Constrained Pressure Preconditioner (CPR) can be implemented using PCCOMPOSITE with PCGALERKIN. CPR first solves an R A P subsystem, updates the
31504d308398SBarry Smith    residual on all variables (PCCompositeSetType(pc,PC_COMPOSITE_MULTIPLICATIVE)), and then applies a simple ILU like preconditioner on all the variables.
3151a6a584a2SBarry Smith 
3152e071a0a4SCarola Kruse    The generalized Golub-Kahan bidiagonalization preconditioner (gkb) can be applied to symmetric 2x2 block matrices of the shape
31532da392ccSBarry Smith $        [ A00  A01]
31542da392ccSBarry Smith $        [ A01' 0  ]
3155a51937d4SCarola Kruse    with A00 positive semi-definite. The implementation follows [Ar13]. Therein, we choose N := 1/nu * I and the (1,1)-block of the matrix is modified to H = A00 + nu*A01*A01'.
3156e071a0a4SCarola Kruse    A linear system Hx = b has to be solved in each iteration of the GKB algorithm. This solver is chosen with the option prefix -fieldsplit_0_.
3157a51937d4SCarola Kruse 
3158a51937d4SCarola Kruse [Ar13] Generalized Golub-Kahan bidiagonalization and stopping criteria, SIAM J. Matrix Anal. Appl., Vol. 34, No. 2, pp. 571-592, 2013.
3159a51937d4SCarola Kruse 
3160412be6bfSPatrick Sanan .seealso:  PCCreate(), PCSetType(), PCType (for list of available types), PC, PCLSC,
3161412be6bfSPatrick Sanan            PCFieldSplitGetSubKSP(), PCFieldSplitSchurGetSubKSP(), PCFieldSplitSetFields(),
3162412be6bfSPatrick Sanan            PCFieldSplitSetType(), PCFieldSplitSetIS(), PCFieldSplitSetSchurPre(), PCFieldSplitSetSchurFactType(),
3163412be6bfSPatrick Sanan            MatSchurComplementSetAinvType(), PCFieldSplitSetSchurScale(), PCFieldSplitSetDetectSaddlePoint()
31640971522cSBarry Smith M*/
31650971522cSBarry Smith 
31668cc058d9SJed Brown PETSC_EXTERN PetscErrorCode PCCreate_FieldSplit(PC pc)
31670971522cSBarry Smith {
31680971522cSBarry Smith   PetscErrorCode ierr;
31690971522cSBarry Smith   PC_FieldSplit  *jac;
31700971522cSBarry Smith 
31710971522cSBarry Smith   PetscFunctionBegin;
3172b00a9115SJed Brown   ierr = PetscNewLog(pc,&jac);CHKERRQ(ierr);
31732fa5cd67SKarl Rupp 
31740971522cSBarry Smith   jac->bs                 = -1;
31750971522cSBarry Smith   jac->nsplits            = 0;
31763e197d65SBarry Smith   jac->type               = PC_COMPOSITE_MULTIPLICATIVE;
3177e6cab6aaSJed Brown   jac->schurpre           = PC_FIELDSPLIT_SCHUR_PRE_USER; /* Try user preconditioner first, fall back on diagonal */
3178c9c6ffaaSJed Brown   jac->schurfactorization = PC_FIELDSPLIT_SCHUR_FACT_FULL;
3179c096484dSStefano Zampini   jac->schurscale         = -1.0;
3180fbe7908bSJed Brown   jac->dm_splits          = PETSC_TRUE;
31817b752e3dSPatrick Sanan   jac->detect             = PETSC_FALSE;
3182a51937d4SCarola Kruse   jac->gkbtol             = 1e-5;
3183a51937d4SCarola Kruse   jac->gkbdelay           = 5;
3184a51937d4SCarola Kruse   jac->gkbnu              = 1;
3185a51937d4SCarola Kruse   jac->gkbmaxit           = 100;
3186de482cd7SCarola Kruse   jac->gkbmonitor         = PETSC_FALSE;
3187*5ddf11f8SNicolas Barnafi   jac->coordinates_set    = PETSC_FALSE;
318851f519a2SBarry Smith 
31890971522cSBarry Smith   pc->data = (void*)jac;
31900971522cSBarry Smith 
31910971522cSBarry Smith   pc->ops->apply           = PCApply_FieldSplit;
3192421e10b8SBarry Smith   pc->ops->applytranspose  = PCApplyTranspose_FieldSplit;
31930971522cSBarry Smith   pc->ops->setup           = PCSetUp_FieldSplit;
3194574deadeSBarry Smith   pc->ops->reset           = PCReset_FieldSplit;
31950971522cSBarry Smith   pc->ops->destroy         = PCDestroy_FieldSplit;
31960971522cSBarry Smith   pc->ops->setfromoptions  = PCSetFromOptions_FieldSplit;
31970971522cSBarry Smith   pc->ops->view            = PCView_FieldSplit;
31980a545947SLisandro Dalcin   pc->ops->applyrichardson = NULL;
31990971522cSBarry Smith 
3200285fb4e2SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCFieldSplitSchurGetSubKSP_C",PCFieldSplitSchurGetSubKSP_FieldSplit);CHKERRQ(ierr);
3201bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCFieldSplitGetSubKSP_C",PCFieldSplitGetSubKSP_FieldSplit);CHKERRQ(ierr);
3202bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCFieldSplitSetFields_C",PCFieldSplitSetFields_FieldSplit);CHKERRQ(ierr);
3203bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCFieldSplitSetIS_C",PCFieldSplitSetIS_FieldSplit);CHKERRQ(ierr);
3204bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCFieldSplitSetType_C",PCFieldSplitSetType_FieldSplit);CHKERRQ(ierr);
3205bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCFieldSplitSetBlockSize_C",PCFieldSplitSetBlockSize_FieldSplit);CHKERRQ(ierr);
32066dbb499eSCian Wilson   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCFieldSplitRestrictIS_C",PCFieldSplitRestrictIS_FieldSplit);CHKERRQ(ierr);
3207*5ddf11f8SNicolas Barnafi   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCSetCoordinates_C",PCSetCoordinates_FieldSplit);CHKERRQ(ierr);
32080971522cSBarry Smith   PetscFunctionReturn(0);
32090971522cSBarry Smith }
3210